diff options
363 files changed, 10800 insertions, 4220 deletions
diff --git a/Documentation/devicetree/bindings/sound/cs4270.txt b/Documentation/devicetree/bindings/sound/cs4270.txt new file mode 100644 index 000000000000..6b222f9b8ef5 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/cs4270.txt | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | CS4270 audio CODEC | ||
| 2 | |||
| 3 | The driver for this device currently only supports I2C. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | |||
| 7 | - compatible : "cirrus,cs4270" | ||
| 8 | |||
| 9 | - reg : the I2C address of the device for I2C | ||
| 10 | |||
| 11 | Optional properties: | ||
| 12 | |||
| 13 | - reset-gpio : a GPIO spec for the reset pin. If specified, it will be | ||
| 14 | deasserted before communication to the codec starts. | ||
| 15 | |||
| 16 | Example: | ||
| 17 | |||
| 18 | codec: cs4270@48 { | ||
| 19 | compatible = "cirrus,cs4270"; | ||
| 20 | reg = <0x48>; | ||
| 21 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/cs4271.txt b/Documentation/devicetree/bindings/sound/cs4271.txt new file mode 100644 index 000000000000..c81b5fd5a5bc --- /dev/null +++ b/Documentation/devicetree/bindings/sound/cs4271.txt | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | Cirrus Logic CS4271 DT bindings | ||
| 2 | |||
| 3 | This driver supports both the I2C and the SPI bus. | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | |||
| 7 | - compatible: "cirrus,cs4271" | ||
| 8 | |||
| 9 | For required properties on SPI, please consult | ||
| 10 | Documentation/devicetree/bindings/spi/spi-bus.txt | ||
| 11 | |||
| 12 | Required properties on I2C: | ||
| 13 | |||
| 14 | - reg: the i2c address | ||
| 15 | |||
| 16 | |||
| 17 | Optional properties: | ||
| 18 | |||
| 19 | - reset-gpio: a GPIO spec to define which pin is connected to the chip's | ||
| 20 | !RESET pin | ||
| 21 | |||
| 22 | Examples: | ||
| 23 | |||
| 24 | codec_i2c: cs4271@10 { | ||
| 25 | compatible = "cirrus,cs4271"; | ||
| 26 | reg = <0x10>; | ||
| 27 | reset-gpio = <&gpio 23 0>; | ||
| 28 | }; | ||
| 29 | |||
| 30 | codec_spi: cs4271@0 { | ||
| 31 | compatible = "cirrus,cs4271"; | ||
| 32 | reg = <0x0>; | ||
| 33 | reset-gpio = <&gpio 23 0>; | ||
| 34 | spi-max-frequency = <6000000>; | ||
| 35 | }; | ||
| 36 | |||
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt new file mode 100644 index 000000000000..374e145c2ef1 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | Texas Instruments McASP controller | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible : | ||
| 5 | "ti,dm646x-mcasp-audio" : for DM646x platforms | ||
| 6 | "ti,da830-mcasp-audio" : for both DA830 & DA850 platforms | ||
| 7 | "ti,omap2-mcasp-audio" : for OMAP2 platforms (TI81xx, AM33xx) | ||
| 8 | |||
| 9 | - reg : Should contain McASP registers offset and length | ||
| 10 | - interrupts : Interrupt number for McASP | ||
| 11 | - op-mode : I2S/DIT ops mode. | ||
| 12 | - tdm-slots : Slots for TDM operation. | ||
| 13 | - num-serializer : Serializers used by McASP. | ||
| 14 | - serial-dir : A list of serializer pin mode. The list number should be equal | ||
| 15 | to "num-serializer" parameter. Each entry is a number indication | ||
| 16 | serializer pin direction. (0 - INACTIVE, 1 - TX, 2 - RX) | ||
| 17 | |||
| 18 | |||
| 19 | Optional properties: | ||
| 20 | |||
| 21 | - ti,hwmods : Must be "mcasp<n>", n is controller instance starting 0 | ||
| 22 | - tx-num-evt : FIFO levels. | ||
| 23 | - rx-num-evt : FIFO levels. | ||
| 24 | - sram-size-playback : size of sram to be allocated during playback | ||
| 25 | - sram-size-capture : size of sram to be allocated during capture | ||
| 26 | |||
| 27 | Example: | ||
| 28 | |||
| 29 | mcasp0: mcasp0@1d00000 { | ||
| 30 | compatible = "ti,da830-mcasp-audio"; | ||
| 31 | #address-cells = <1>; | ||
| 32 | #size-cells = <0>; | ||
| 33 | reg = <0x100000 0x3000>; | ||
| 34 | interrupts = <82 83>; | ||
| 35 | op-mode = <0>; /* MCASP_IIS_MODE */ | ||
| 36 | tdm-slots = <2>; | ||
| 37 | num-serializer = <16>; | ||
| 38 | serial-dir = < | ||
| 39 | 0 0 0 0 /* 0: INACTIVE, 1: TX, 2: RX */ | ||
| 40 | 0 0 0 0 | ||
| 41 | 0 0 0 1 | ||
| 42 | 2 0 0 0 >; | ||
| 43 | tx-num-evt = <1>; | ||
| 44 | rx-num-evt = <1>; | ||
| 45 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt b/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt new file mode 100644 index 000000000000..65dec876cb2d --- /dev/null +++ b/Documentation/devicetree/bindings/sound/omap-abe-twl6040.txt | |||
| @@ -0,0 +1,91 @@ | |||
| 1 | * Texas Instruments OMAP4+ and twl6040 based audio setups | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: "ti,abe-twl6040" | ||
| 5 | - ti,model: Name of the sound card ( for example "SDP4430") | ||
| 6 | - ti,mclk-freq: MCLK frequency for HPPLL operation | ||
| 7 | - ti,mcpdm: phandle for the McPDM node | ||
| 8 | - ti,twl6040: phandle for the twl6040 core node | ||
| 9 | - ti,audio-routing: List of connections between audio components. | ||
| 10 | Each entry is a pair of strings, the first being the connection's sink, | ||
| 11 | the second being the connection's source. | ||
| 12 | |||
| 13 | Optional properties: | ||
| 14 | - ti,dmic: phandle for the OMAP dmic node if the machine have it connected | ||
| 15 | - ti,jack_detection: Need to be set to <1> if the board capable to detect jack | ||
| 16 | insertion, removal. | ||
| 17 | |||
| 18 | Available audio endpoints for the audio-routing table: | ||
| 19 | |||
| 20 | Board connectors: | ||
| 21 | * Headset Stereophone | ||
| 22 | * Earphone Spk | ||
| 23 | * Ext Spk | ||
| 24 | * Line Out | ||
| 25 | * Vibrator | ||
| 26 | * Headset Mic | ||
| 27 | * Main Handset Mic | ||
| 28 | * Sub Handset Mic | ||
| 29 | * Line In | ||
| 30 | * Digital Mic | ||
| 31 | |||
| 32 | twl6040 pins: | ||
| 33 | * HSOL | ||
| 34 | * HSOR | ||
| 35 | * EP | ||
| 36 | * HFL | ||
| 37 | * HFR | ||
| 38 | * AUXL | ||
| 39 | * AUXR | ||
| 40 | * VIBRAL | ||
| 41 | * VIBRAR | ||
| 42 | * HSMIC | ||
| 43 | * MAINMIC | ||
| 44 | * SUBMIC | ||
| 45 | * AFML | ||
| 46 | * AFMR | ||
| 47 | |||
| 48 | * Headset Mic Bias | ||
| 49 | * Main Mic Bias | ||
| 50 | * Digital Mic1 Bias | ||
| 51 | * Digital Mic2 Bias | ||
| 52 | |||
| 53 | Digital mic pins: | ||
| 54 | * DMic | ||
| 55 | |||
| 56 | Example: | ||
| 57 | |||
| 58 | sound { | ||
| 59 | compatible = "ti,abe-twl6040"; | ||
| 60 | ti,model = "SDP4430"; | ||
| 61 | |||
| 62 | ti,jack-detection = <1>; | ||
| 63 | ti,mclk-freq = <38400000>; | ||
| 64 | |||
| 65 | ti,mcpdm = <&mcpdm>; | ||
| 66 | ti,dmic = <&dmic>; | ||
| 67 | |||
| 68 | ti,twl6040 = <&twl6040>; | ||
| 69 | |||
| 70 | /* Audio routing */ | ||
| 71 | ti,audio-routing = | ||
| 72 | "Headset Stereophone", "HSOL", | ||
| 73 | "Headset Stereophone", "HSOR", | ||
| 74 | "Earphone Spk", "EP", | ||
| 75 | "Ext Spk", "HFL", | ||
| 76 | "Ext Spk", "HFR", | ||
| 77 | "Line Out", "AUXL", | ||
| 78 | "Line Out", "AUXR", | ||
| 79 | "Vibrator", "VIBRAL", | ||
| 80 | "Vibrator", "VIBRAR", | ||
| 81 | "HSMIC", "Headset Mic", | ||
| 82 | "Headset Mic", "Headset Mic Bias", | ||
| 83 | "MAINMIC", "Main Handset Mic", | ||
| 84 | "Main Handset Mic", "Main Mic Bias", | ||
| 85 | "SUBMIC", "Sub Handset Mic", | ||
| 86 | "Sub Handset Mic", "Main Mic Bias", | ||
| 87 | "AFML", "Line In", | ||
| 88 | "AFMR", "Line In", | ||
| 89 | "DMic", "Digital Mic", | ||
| 90 | "Digital Mic", "Digital Mic1 Bias"; | ||
| 91 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/omap-mcbsp.txt b/Documentation/devicetree/bindings/sound/omap-mcbsp.txt new file mode 100644 index 000000000000..17cce4490456 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/omap-mcbsp.txt | |||
| @@ -0,0 +1,37 @@ | |||
| 1 | * Texas Instruments OMAP2+ McBSP module | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: "ti,omap2420-mcbsp" for McBSP on OMAP2420 | ||
| 5 | "ti,omap2430-mcbsp" for McBSP on OMAP2430 | ||
| 6 | "ti,omap3-mcbsp" for McBSP on OMAP3 | ||
| 7 | "ti,omap4-mcbsp" for McBSP on OMAP4 and newer SoC | ||
| 8 | - reg: Register location and size, for OMAP4+ as an array: | ||
| 9 | <MPU access base address, size>, | ||
| 10 | <L3 interconnect address, size>; | ||
| 11 | - reg-names: Array of strings associated with the address space | ||
| 12 | - interrupts: Interrupt numbers for the McBSP port, as an array in case the | ||
| 13 | McBSP IP have more interrupt lines: | ||
| 14 | <OCP compliant irq>, | ||
| 15 | <TX irq>, | ||
| 16 | <RX irq>; | ||
| 17 | - interrupt-names: Array of strings associated with the interrupt numbers | ||
| 18 | - interrupt-parent: The parent interrupt controller | ||
| 19 | - ti,buffer-size: Size of the FIFO on the port (OMAP2430 and newer SoC) | ||
| 20 | - ti,hwmods: Name of the hwmod associated to the McBSP port | ||
| 21 | |||
| 22 | Example: | ||
| 23 | |||
| 24 | mcbsp2: mcbsp@49022000 { | ||
| 25 | compatible = "ti,omap3-mcbsp"; | ||
| 26 | reg = <0x49022000 0xff>, | ||
| 27 | <0x49028000 0xff>; | ||
| 28 | reg-names = "mpu", "sidetone"; | ||
| 29 | interrupts = <0 17 0x4>, /* OCP compliant interrupt */ | ||
| 30 | <0 62 0x4>, /* TX interrupt */ | ||
| 31 | <0 63 0x4>, /* RX interrupt */ | ||
| 32 | <0 4 0x4>; /* Sidetone */ | ||
| 33 | interrupt-names = "common", "tx", "rx", "sidetone"; | ||
| 34 | interrupt-parent = <&intc>; | ||
| 35 | ti,buffer-size = <1280>; | ||
| 36 | ti,hwmods = "mcbsp2"; | ||
| 37 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/omap-twl4030.txt b/Documentation/devicetree/bindings/sound/omap-twl4030.txt new file mode 100644 index 000000000000..6fae51c7f766 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/omap-twl4030.txt | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | * Texas Instruments SoC with twl4030 based audio setups | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: "ti,omap-twl4030" | ||
| 5 | - ti,model: Name of the sound card (for example "omap3beagle") | ||
| 6 | - ti,mcbsp: phandle for the McBSP node | ||
| 7 | - ti,codec: phandle for the twl4030 audio node | ||
| 8 | |||
| 9 | Example: | ||
| 10 | |||
| 11 | sound { | ||
| 12 | compatible = "ti,omap-twl4030"; | ||
| 13 | ti,model = "omap3beagle"; | ||
| 14 | |||
| 15 | ti,mcbsp = <&mcbsp2>; | ||
| 16 | ti,codec = <&twl_audio>; | ||
| 17 | }; | ||
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt new file mode 100644 index 000000000000..e7b98f41fa5f --- /dev/null +++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | Texas Instruments - tlv320aic3x Codec module | ||
| 2 | |||
| 3 | The tlv320aic3x serial control bus communicates through I2C protocols | ||
| 4 | |||
| 5 | Required properties: | ||
| 6 | - compatible - "string" - "ti,tlv320aic3x" | ||
| 7 | - reg - <int> - I2C slave address | ||
| 8 | |||
| 9 | |||
| 10 | Optional properties: | ||
| 11 | |||
| 12 | - gpio-reset - gpio pin number used for codec reset | ||
| 13 | - ai3x-gpio-func - <array of 2 int> - AIC3X_GPIO1 & AIC3X_GPIO2 Functionality | ||
| 14 | |||
| 15 | Example: | ||
| 16 | |||
| 17 | tlv320aic3x: tlv320aic3x@1b { | ||
| 18 | compatible = "ti,tlv320aic3x"; | ||
| 19 | reg = <0x1b>; | ||
| 20 | }; | ||
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 4e4d0bc9816f..d90d8ec2853d 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt | |||
| @@ -860,8 +860,14 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
| 860 | 860 | ||
| 861 | [Multiple options for each card instance] | 861 | [Multiple options for each card instance] |
| 862 | model - force the model name | 862 | model - force the model name |
| 863 | position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF, | 863 | position_fix - Fix DMA pointer |
| 864 | 3 = VIACOMBO, 4 = COMBO) | 864 | -1 = system default: choose appropriate one per controller |
| 865 | hardware | ||
| 866 | 0 = auto: falls back to LPIB when POSBUF doesn't work | ||
| 867 | 1 = use LPIB | ||
| 868 | 2 = POSBUF: use position buffer | ||
| 869 | 3 = VIACOMBO: VIA-specific workaround for capture | ||
| 870 | 4 = COMBO: use LPIB for playback, auto for capture stream | ||
| 865 | probe_mask - Bitmask to probe codecs (default = -1, meaning all slots) | 871 | probe_mask - Bitmask to probe codecs (default = -1, meaning all slots) |
| 866 | When the bit 8 (0x100) is set, the lower 8 bits are used | 872 | When the bit 8 (0x100) is set, the lower 8 bits are used |
| 867 | as the "fixed" codec slots; i.e. the driver probes the | 873 | as the "fixed" codec slots; i.e. the driver probes the |
diff --git a/Documentation/sound/alsa/Channel-Mapping-API.txt b/Documentation/sound/alsa/Channel-Mapping-API.txt new file mode 100644 index 000000000000..3c43d1a4ca0e --- /dev/null +++ b/Documentation/sound/alsa/Channel-Mapping-API.txt | |||
| @@ -0,0 +1,153 @@ | |||
| 1 | ALSA PCM channel-mapping API | ||
| 2 | ============================ | ||
| 3 | Takashi Iwai <tiwai@suse.de> | ||
| 4 | |||
| 5 | GENERAL | ||
| 6 | ------- | ||
| 7 | |||
| 8 | The channel mapping API allows user to query the possible channel maps | ||
| 9 | and the current channel map, also optionally to modify the channel map | ||
| 10 | of the current stream. | ||
| 11 | |||
| 12 | A channel map is an array of position for each PCM channel. | ||
| 13 | Typically, a stereo PCM stream has a channel map of | ||
| 14 | { front_left, front_right } | ||
| 15 | while a 4.0 surround PCM stream has a channel map of | ||
| 16 | { front left, front right, rear left, rear right }. | ||
| 17 | |||
| 18 | The problem, so far, was that we had no standard channel map | ||
| 19 | explicitly, and applications had no way to know which channel | ||
| 20 | corresponds to which (speaker) position. Thus, applications applied | ||
| 21 | wrong channels for 5.1 outputs, and you hear suddenly strange sound | ||
| 22 | from rear. Or, some devices secretly assume that center/LFE is the | ||
| 23 | third/fourth channels while others that C/LFE as 5th/6th channels. | ||
| 24 | |||
| 25 | Also, some devices such as HDMI are configurable for different speaker | ||
| 26 | positions even with the same number of total channels. However, there | ||
| 27 | was no way to specify this because of lack of channel map | ||
| 28 | specification. These are the main motivations for the new channel | ||
| 29 | mapping API. | ||
| 30 | |||
| 31 | |||
| 32 | DESIGN | ||
| 33 | ------ | ||
| 34 | |||
| 35 | Actually, "the channel mapping API" doesn't introduce anything new in | ||
| 36 | the kernel/user-space ABI perspective. It uses only the existing | ||
| 37 | control element features. | ||
| 38 | |||
| 39 | As a ground design, each PCM substream may contain a control element | ||
| 40 | providing the channel mapping information and configuration. This | ||
| 41 | element is specified by: | ||
| 42 | iface = SNDRV_CTL_ELEM_IFACE_PCM | ||
| 43 | name = "Playback Channel Map" or "Capture Channel Map" | ||
| 44 | device = the same device number for the assigned PCM substream | ||
| 45 | index = the same index number for the assigned PCM substream | ||
| 46 | |||
| 47 | Note the name is different depending on the PCM substream direction. | ||
| 48 | |||
| 49 | Each control element provides at least the TLV read operation and the | ||
| 50 | read operation. Optionally, the write operation can be provided to | ||
| 51 | allow user to change the channel map dynamically. | ||
| 52 | |||
| 53 | * TLV | ||
| 54 | |||
| 55 | The TLV operation gives the list of available channel | ||
| 56 | maps. A list item of a channel map is usually a TLV of | ||
| 57 | type data-bytes ch0 ch1 ch2... | ||
| 58 | where type is the TLV type value, the second argument is the total | ||
| 59 | bytes (not the numbers) of channel values, and the rest are the | ||
| 60 | position value for each channel. | ||
| 61 | |||
| 62 | As a TLV type, either SNDRV_CTL_TLVT_CHMAP_FIXED, | ||
| 63 | SNDRV_CTL_TLV_CHMAP_VAR or SNDRV_CTL_TLVT_CHMAP_PAIRED can be used. | ||
| 64 | The _FIXED type is for a channel map with the fixed channel position | ||
| 65 | while the latter two are for flexible channel positions. _VAR type is | ||
| 66 | for a channel map where all channels are freely swappable and _PAIRED | ||
| 67 | type is where pair-wise channels are swappable. For example, when you | ||
| 68 | have {FL/FR/RL/RR} channel map, _PAIRED type would allow you to swap | ||
| 69 | only {RL/RR/FL/FR} while _VAR type would allow even swapping FL and | ||
| 70 | RR. | ||
| 71 | |||
| 72 | These new TLV types are defined in sound/tlv.h. | ||
| 73 | |||
| 74 | The available channel position values are defined in sound/asound.h, | ||
| 75 | here is a cut: | ||
| 76 | |||
| 77 | /* channel positions */ | ||
| 78 | enum { | ||
| 79 | SNDRV_CHMAP_UNKNOWN = 0, | ||
| 80 | SNDRV_CHMAP_NA, /* N/A, silent */ | ||
| 81 | SNDRV_CHMAP_MONO, /* mono stream */ | ||
| 82 | /* this follows the alsa-lib mixer channel value + 3 */ | ||
| 83 | SNDRV_CHMAP_FL, /* front left */ | ||
| 84 | SNDRV_CHMAP_FR, /* front right */ | ||
| 85 | SNDRV_CHMAP_RL, /* rear left */ | ||
| 86 | SNDRV_CHMAP_RR, /* rear right */ | ||
| 87 | SNDRV_CHMAP_FC, /* front center */ | ||
| 88 | SNDRV_CHMAP_LFE, /* LFE */ | ||
| 89 | SNDRV_CHMAP_SL, /* side left */ | ||
| 90 | SNDRV_CHMAP_SR, /* side right */ | ||
| 91 | SNDRV_CHMAP_RC, /* rear center */ | ||
| 92 | /* new definitions */ | ||
| 93 | SNDRV_CHMAP_FLC, /* front left center */ | ||
| 94 | SNDRV_CHMAP_FRC, /* front right center */ | ||
| 95 | SNDRV_CHMAP_RLC, /* rear left center */ | ||
| 96 | SNDRV_CHMAP_RRC, /* rear right center */ | ||
| 97 | SNDRV_CHMAP_FLW, /* front left wide */ | ||
| 98 | SNDRV_CHMAP_FRW, /* front right wide */ | ||
| 99 | SNDRV_CHMAP_FLH, /* front left high */ | ||
| 100 | SNDRV_CHMAP_FCH, /* front center high */ | ||
| 101 | SNDRV_CHMAP_FRH, /* front right high */ | ||
| 102 | SNDRV_CHMAP_TC, /* top center */ | ||
| 103 | SNDRV_CHMAP_TFL, /* top front left */ | ||
| 104 | SNDRV_CHMAP_TFR, /* top front right */ | ||
| 105 | SNDRV_CHMAP_TFC, /* top front center */ | ||
| 106 | SNDRV_CHMAP_TRL, /* top rear left */ | ||
| 107 | SNDRV_CHMAP_TRR, /* top rear right */ | ||
| 108 | SNDRV_CHMAP_TRC, /* top rear center */ | ||
| 109 | SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC, | ||
| 110 | }; | ||
| 111 | |||
| 112 | When a PCM stream can provide more than one channel map, you can | ||
| 113 | provide multiple channel maps in a TLV container type. The TLV data | ||
| 114 | to be returned will contain such as: | ||
| 115 | SNDRV_CTL_TLVT_CONTAINER 96 | ||
| 116 | SNDRV_CTL_TLVT_CHMAP_FIXED 4 SNDRV_CHMAP_FC | ||
| 117 | SNDRV_CTL_TLVT_CHMAP_FIXED 8 SNDRV_CHMAP_FL SNDRV_CHMAP_FR | ||
| 118 | SNDRV_CTL_TLVT_CHMAP_FIXED 16 NDRV_CHMAP_FL SNDRV_CHMAP_FR \ | ||
| 119 | SNDRV_CHMAP_RL SNDRV_CHMAP_RR | ||
| 120 | |||
| 121 | The channel position is provided in LSB 16bits. The upper bits are | ||
| 122 | used for bit flags. | ||
| 123 | |||
| 124 | #define SNDRV_CHMAP_POSITION_MASK 0xffff | ||
| 125 | #define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16) | ||
| 126 | #define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16) | ||
| 127 | |||
| 128 | SNDRV_CHMAP_PHASE_INVERSE indicates the channel is phase inverted, | ||
| 129 | (thus summing left and right channels would result in almost silence). | ||
| 130 | Some digital mic devices have this. | ||
| 131 | |||
| 132 | When SNDRV_CHMAP_DRIVER_SPEC is set, all the channel position values | ||
| 133 | don't follow the standard definition above but driver-specific. | ||
| 134 | |||
| 135 | * READ OPERATION | ||
| 136 | |||
| 137 | The control read operation is for providing the current channel map of | ||
| 138 | the given stream. The control element returns an integer array | ||
| 139 | containing the position of each channel. | ||
| 140 | |||
| 141 | When this is performed before the number of the channel is specified | ||
| 142 | (i.e. hw_params is set), it should return all channels set to | ||
| 143 | UNKNOWN. | ||
| 144 | |||
| 145 | * WRITE OPERATION | ||
| 146 | |||
| 147 | The control write operation is optional, and only for devices that can | ||
| 148 | change the channel configuration on the fly, such as HDMI. User needs | ||
| 149 | to pass an integer value containing the valid channel positions for | ||
| 150 | all channels of the assigned PCM substream. | ||
| 151 | |||
| 152 | This operation is allowed only at PCM PREPARED state. When called in | ||
| 153 | other states, it shall return an error. | ||
diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index a92bba816843..16dfe57f1731 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt | |||
| @@ -74,7 +74,8 @@ CMI9880 | |||
| 74 | 74 | ||
| 75 | AD1882 / AD1882A | 75 | AD1882 / AD1882A |
| 76 | ================ | 76 | ================ |
| 77 | 3stack 3-stack mode (default) | 77 | 3stack 3-stack mode |
| 78 | 3stack-automute 3-stack with automute front HP (default) | ||
| 78 | 6stack 6-stack mode | 79 | 6stack 6-stack mode |
| 79 | 80 | ||
| 80 | AD1884A / AD1883 / AD1984A / AD1984B | 81 | AD1884A / AD1883 / AD1984A / AD1984B |
diff --git a/arch/arm/mach-davinci/asp.h b/arch/arm/mach-davinci/asp.h new file mode 100644 index 000000000000..d9b2acd12393 --- /dev/null +++ b/arch/arm/mach-davinci/asp.h | |||
| @@ -0,0 +1,49 @@ | |||
| 1 | /* | ||
| 2 | * TI DaVinci Audio definitions | ||
| 3 | */ | ||
| 4 | #ifndef __ASM_ARCH_DAVINCI_ASP_H | ||
| 5 | #define __ASM_ARCH_DAVINCI_ASP_H | ||
| 6 | |||
| 7 | /* Bases of dm644x and dm355 register banks */ | ||
| 8 | #define DAVINCI_ASP0_BASE 0x01E02000 | ||
| 9 | #define DAVINCI_ASP1_BASE 0x01E04000 | ||
| 10 | |||
| 11 | /* Bases of dm365 register banks */ | ||
| 12 | #define DAVINCI_DM365_ASP0_BASE 0x01D02000 | ||
| 13 | |||
| 14 | /* Bases of dm646x register banks */ | ||
| 15 | #define DAVINCI_DM646X_MCASP0_REG_BASE 0x01D01000 | ||
| 16 | #define DAVINCI_DM646X_MCASP1_REG_BASE 0x01D01800 | ||
| 17 | |||
| 18 | /* Bases of da850/da830 McASP0 register banks */ | ||
| 19 | #define DAVINCI_DA8XX_MCASP0_REG_BASE 0x01D00000 | ||
| 20 | |||
| 21 | /* Bases of da830 McASP1 register banks */ | ||
| 22 | #define DAVINCI_DA830_MCASP1_REG_BASE 0x01D04000 | ||
| 23 | |||
| 24 | /* EDMA channels of dm644x and dm355 */ | ||
| 25 | #define DAVINCI_DMA_ASP0_TX 2 | ||
| 26 | #define DAVINCI_DMA_ASP0_RX 3 | ||
| 27 | #define DAVINCI_DMA_ASP1_TX 8 | ||
| 28 | #define DAVINCI_DMA_ASP1_RX 9 | ||
| 29 | |||
| 30 | /* EDMA channels of dm646x */ | ||
| 31 | #define DAVINCI_DM646X_DMA_MCASP0_AXEVT0 6 | ||
| 32 | #define DAVINCI_DM646X_DMA_MCASP0_AREVT0 9 | ||
| 33 | #define DAVINCI_DM646X_DMA_MCASP1_AXEVT1 12 | ||
| 34 | |||
| 35 | /* EDMA channels of da850/da830 McASP0 */ | ||
| 36 | #define DAVINCI_DA8XX_DMA_MCASP0_AREVT 0 | ||
| 37 | #define DAVINCI_DA8XX_DMA_MCASP0_AXEVT 1 | ||
| 38 | |||
| 39 | /* EDMA channels of da830 McASP1 */ | ||
| 40 | #define DAVINCI_DA830_DMA_MCASP1_AREVT 2 | ||
| 41 | #define DAVINCI_DA830_DMA_MCASP1_AXEVT 3 | ||
| 42 | |||
| 43 | /* Interrupts */ | ||
| 44 | #define DAVINCI_ASP0_RX_INT IRQ_MBRINT | ||
| 45 | #define DAVINCI_ASP0_TX_INT IRQ_MBXINT | ||
| 46 | #define DAVINCI_ASP1_RX_INT IRQ_MBRINT | ||
| 47 | #define DAVINCI_ASP1_TX_INT IRQ_MBXINT | ||
| 48 | |||
| 49 | #endif /* __ASM_ARCH_DAVINCI_ASP_H */ | ||
diff --git a/arch/arm/mach-davinci/davinci.h b/arch/arm/mach-davinci/davinci.h index a37fc44e29bc..12d544befcfa 100644 --- a/arch/arm/mach-davinci/davinci.h +++ b/arch/arm/mach-davinci/davinci.h | |||
| @@ -22,10 +22,10 @@ | |||
| 22 | #include <linux/davinci_emac.h> | 22 | #include <linux/davinci_emac.h> |
| 23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 24 | #include <linux/spi/spi.h> | 24 | #include <linux/spi/spi.h> |
| 25 | 25 | #include <linux/platform_data/davinci_asp.h> | |
| 26 | #include <mach/asp.h> | ||
| 27 | #include <linux/platform_data/keyscan-davinci.h> | 26 | #include <linux/platform_data/keyscan-davinci.h> |
| 28 | #include <mach/hardware.h> | 27 | #include <mach/hardware.h> |
| 28 | #include <mach/edma.h> | ||
| 29 | 29 | ||
| 30 | #include <media/davinci/vpfe_capture.h> | 30 | #include <media/davinci/vpfe_capture.h> |
| 31 | #include <media/davinci/vpif_types.h> | 31 | #include <media/davinci/vpif_types.h> |
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 783eab6845c4..bd2f72b414bc 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <mach/cpuidle.h> | 24 | #include <mach/cpuidle.h> |
| 25 | 25 | ||
| 26 | #include "clock.h" | 26 | #include "clock.h" |
| 27 | #include "asp.h" | ||
| 27 | 28 | ||
| 28 | #define DA8XX_TPCC_BASE 0x01c00000 | 29 | #define DA8XX_TPCC_BASE 0x01c00000 |
| 29 | #define DA8XX_TPTC0_BASE 0x01c08000 | 30 | #define DA8XX_TPTC0_BASE 0x01c08000 |
| @@ -505,15 +506,8 @@ static struct platform_device da850_mcasp_device = { | |||
| 505 | .resource = da850_mcasp_resources, | 506 | .resource = da850_mcasp_resources, |
| 506 | }; | 507 | }; |
| 507 | 508 | ||
| 508 | static struct platform_device davinci_pcm_device = { | ||
| 509 | .name = "davinci-pcm-audio", | ||
| 510 | .id = -1, | ||
| 511 | }; | ||
| 512 | |||
| 513 | void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata) | 509 | void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata) |
| 514 | { | 510 | { |
| 515 | platform_device_register(&davinci_pcm_device); | ||
| 516 | |||
| 517 | /* DA830/OMAP-L137 has 3 instances of McASP */ | 511 | /* DA830/OMAP-L137 has 3 instances of McASP */ |
| 518 | if (cpu_is_davinci_da830() && id == 1) { | 512 | if (cpu_is_davinci_da830() && id == 1) { |
| 519 | da830_mcasp1_device.dev.platform_data = pdata; | 513 | da830_mcasp1_device.dev.platform_data = pdata; |
diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c index 3a42b6f79aa9..4c48a36ee567 100644 --- a/arch/arm/mach-davinci/devices.c +++ b/arch/arm/mach-davinci/devices.c | |||
| @@ -313,16 +313,6 @@ static void davinci_init_wdt(void) | |||
| 313 | 313 | ||
| 314 | /*-------------------------------------------------------------------------*/ | 314 | /*-------------------------------------------------------------------------*/ |
| 315 | 315 | ||
| 316 | static struct platform_device davinci_pcm_device = { | ||
| 317 | .name = "davinci-pcm-audio", | ||
| 318 | .id = -1, | ||
| 319 | }; | ||
| 320 | |||
| 321 | static void davinci_init_pcm(void) | ||
| 322 | { | ||
| 323 | platform_device_register(&davinci_pcm_device); | ||
| 324 | } | ||
| 325 | |||
| 326 | /*-------------------------------------------------------------------------*/ | 316 | /*-------------------------------------------------------------------------*/ |
| 327 | 317 | ||
| 328 | struct davinci_timer_instance davinci_timer_instance[2] = { | 318 | struct davinci_timer_instance davinci_timer_instance[2] = { |
| @@ -345,7 +335,6 @@ static int __init davinci_init_devices(void) | |||
| 345 | /* please keep these calls, and their implementations above, | 335 | /* please keep these calls, and their implementations above, |
| 346 | * in alphabetical order so they're easier to sort through. | 336 | * in alphabetical order so they're easier to sort through. |
| 347 | */ | 337 | */ |
| 348 | davinci_init_pcm(); | ||
| 349 | davinci_init_wdt(); | 338 | davinci_init_wdt(); |
| 350 | 339 | ||
| 351 | return 0; | 340 | return 0; |
diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c index adbde33eca01..a255434908db 100644 --- a/arch/arm/mach-davinci/dm355.c +++ b/arch/arm/mach-davinci/dm355.c | |||
| @@ -26,13 +26,13 @@ | |||
| 26 | #include <mach/time.h> | 26 | #include <mach/time.h> |
| 27 | #include <mach/serial.h> | 27 | #include <mach/serial.h> |
| 28 | #include <mach/common.h> | 28 | #include <mach/common.h> |
| 29 | #include <mach/asp.h> | ||
| 30 | #include <linux/platform_data/spi-davinci.h> | 29 | #include <linux/platform_data/spi-davinci.h> |
| 31 | #include <mach/gpio-davinci.h> | 30 | #include <mach/gpio-davinci.h> |
| 32 | 31 | ||
| 33 | #include "davinci.h" | 32 | #include "davinci.h" |
| 34 | #include "clock.h" | 33 | #include "clock.h" |
| 35 | #include "mux.h" | 34 | #include "mux.h" |
| 35 | #include "asp.h" | ||
| 36 | 36 | ||
| 37 | #define DM355_UART2_BASE (IO_PHYS + 0x206000) | 37 | #define DM355_UART2_BASE (IO_PHYS + 0x206000) |
| 38 | 38 | ||
diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c index 719e22f2a37e..b680c832e0ba 100644 --- a/arch/arm/mach-davinci/dm365.c +++ b/arch/arm/mach-davinci/dm365.c | |||
| @@ -29,7 +29,6 @@ | |||
| 29 | #include <mach/time.h> | 29 | #include <mach/time.h> |
| 30 | #include <mach/serial.h> | 30 | #include <mach/serial.h> |
| 31 | #include <mach/common.h> | 31 | #include <mach/common.h> |
| 32 | #include <mach/asp.h> | ||
| 33 | #include <linux/platform_data/keyscan-davinci.h> | 32 | #include <linux/platform_data/keyscan-davinci.h> |
| 34 | #include <linux/platform_data/spi-davinci.h> | 33 | #include <linux/platform_data/spi-davinci.h> |
| 35 | #include <mach/gpio-davinci.h> | 34 | #include <mach/gpio-davinci.h> |
| @@ -37,6 +36,7 @@ | |||
| 37 | #include "davinci.h" | 36 | #include "davinci.h" |
| 38 | #include "clock.h" | 37 | #include "clock.h" |
| 39 | #include "mux.h" | 38 | #include "mux.h" |
| 39 | #include "asp.h" | ||
| 40 | 40 | ||
| 41 | #define DM365_REF_FREQ 24000000 /* 24 MHz on the DM365 EVM */ | 41 | #define DM365_REF_FREQ 24000000 /* 24 MHz on the DM365 EVM */ |
| 42 | 42 | ||
diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c index c8b866657fcb..0755d466221a 100644 --- a/arch/arm/mach-davinci/dm644x.c +++ b/arch/arm/mach-davinci/dm644x.c | |||
| @@ -23,12 +23,12 @@ | |||
| 23 | #include <mach/time.h> | 23 | #include <mach/time.h> |
| 24 | #include <mach/serial.h> | 24 | #include <mach/serial.h> |
| 25 | #include <mach/common.h> | 25 | #include <mach/common.h> |
| 26 | #include <mach/asp.h> | ||
| 27 | #include <mach/gpio-davinci.h> | 26 | #include <mach/gpio-davinci.h> |
| 28 | 27 | ||
| 29 | #include "davinci.h" | 28 | #include "davinci.h" |
| 30 | #include "clock.h" | 29 | #include "clock.h" |
| 31 | #include "mux.h" | 30 | #include "mux.h" |
| 31 | #include "asp.h" | ||
| 32 | 32 | ||
| 33 | /* | 33 | /* |
| 34 | * Device specific clocks | 34 | * Device specific clocks |
diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c index 9eb87c1d1edd..97c0f8e555bd 100644 --- a/arch/arm/mach-davinci/dm646x.c +++ b/arch/arm/mach-davinci/dm646x.c | |||
| @@ -24,12 +24,12 @@ | |||
| 24 | #include <mach/time.h> | 24 | #include <mach/time.h> |
| 25 | #include <mach/serial.h> | 25 | #include <mach/serial.h> |
| 26 | #include <mach/common.h> | 26 | #include <mach/common.h> |
| 27 | #include <mach/asp.h> | ||
| 28 | #include <mach/gpio-davinci.h> | 27 | #include <mach/gpio-davinci.h> |
| 29 | 28 | ||
| 30 | #include "davinci.h" | 29 | #include "davinci.h" |
| 31 | #include "clock.h" | 30 | #include "clock.h" |
| 32 | #include "mux.h" | 31 | #include "mux.h" |
| 32 | #include "asp.h" | ||
| 33 | 33 | ||
| 34 | #define DAVINCI_VPIF_BASE (0x01C12000) | 34 | #define DAVINCI_VPIF_BASE (0x01C12000) |
| 35 | 35 | ||
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h index 33e78ae2a254..c9ee723c56f3 100644 --- a/arch/arm/mach-davinci/include/mach/da8xx.h +++ b/arch/arm/mach-davinci/include/mach/da8xx.h | |||
| @@ -16,10 +16,10 @@ | |||
| 16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
| 17 | #include <linux/davinci_emac.h> | 17 | #include <linux/davinci_emac.h> |
| 18 | #include <linux/spi/spi.h> | 18 | #include <linux/spi/spi.h> |
| 19 | #include <linux/platform_data/davinci_asp.h> | ||
| 19 | 20 | ||
| 20 | #include <mach/serial.h> | 21 | #include <mach/serial.h> |
| 21 | #include <mach/edma.h> | 22 | #include <mach/edma.h> |
| 22 | #include <mach/asp.h> | ||
| 23 | #include <mach/pm.h> | 23 | #include <mach/pm.h> |
| 24 | #include <linux/platform_data/i2c-davinci.h> | 24 | #include <linux/platform_data/i2c-davinci.h> |
| 25 | #include <linux/platform_data/mmc-davinci.h> | 25 | #include <linux/platform_data/mmc-davinci.h> |
diff --git a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c index fd3177f9e79a..98aef571b9f8 100644 --- a/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c | |||
| @@ -348,4 +348,5 @@ void __init eukrea_mbimx27_baseboard_init(void) | |||
| 348 | imx27_add_imx_keypad(&eukrea_mbimx27_keymap_data); | 348 | imx27_add_imx_keypad(&eukrea_mbimx27_keymap_data); |
| 349 | 349 | ||
| 350 | gpio_led_register_device(-1, &eukrea_mbimx27_gpio_led_info); | 350 | gpio_led_register_device(-1, &eukrea_mbimx27_gpio_led_info); |
| 351 | imx_add_platform_device("eukrea_tlv320", 0, NULL, 0, NULL, 0); | ||
| 351 | } | 352 | } |
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c index dfd2da87c2df..0b84666792f0 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c | |||
| @@ -306,4 +306,5 @@ void __init eukrea_mbimxsd25_baseboard_init(void) | |||
| 306 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); | 306 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); |
| 307 | gpio_led_register_device(-1, &eukrea_mbimxsd_led_info); | 307 | gpio_led_register_device(-1, &eukrea_mbimxsd_led_info); |
| 308 | imx_add_gpio_keys(&eukrea_mbimxsd_button_data); | 308 | imx_add_gpio_keys(&eukrea_mbimxsd_button_data); |
| 309 | imx_add_platform_device("eukrea_tlv320", 0, NULL, 0, NULL, 0); | ||
| 309 | } | 310 | } |
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c index 6e9dd12a6961..c6532a007d46 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c | |||
| @@ -315,4 +315,5 @@ void __init eukrea_mbimxsd35_baseboard_init(void) | |||
| 315 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); | 315 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); |
| 316 | gpio_led_register_device(-1, &eukrea_mbimxsd_led_info); | 316 | gpio_led_register_device(-1, &eukrea_mbimxsd_led_info); |
| 317 | imx_add_gpio_keys(&eukrea_mbimxsd_button_data); | 317 | imx_add_gpio_keys(&eukrea_mbimxsd_button_data); |
| 318 | imx_add_platform_device("eukrea_tlv320", 0, NULL, 0, NULL, 0); | ||
| 318 | } | 319 | } |
diff --git a/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c b/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c index 96a24b73dc23..8b0de30d7a3f 100644 --- a/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c +++ b/arch/arm/mach-imx/eukrea_mbimxsd51-baseboard.c | |||
| @@ -228,4 +228,5 @@ void __init eukrea_mbimxsd51_baseboard_init(void) | |||
| 228 | 228 | ||
| 229 | gpio_led_register_device(-1, &eukrea_mbimxsd51_led_info); | 229 | gpio_led_register_device(-1, &eukrea_mbimxsd51_led_info); |
| 230 | imx_add_gpio_keys(&eukrea_mbimxsd51_button_data); | 230 | imx_add_gpio_keys(&eukrea_mbimxsd51_button_data); |
| 231 | imx_add_platform_device("eukrea_tlv320", 0, NULL, 0, NULL, 0); | ||
| 231 | } | 232 | } |
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c index 821d6aac411c..141756f00ae5 100644 --- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c +++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
| 33 | #include <linux/dma-mapping.h> | 33 | #include <linux/dma-mapping.h> |
| 34 | #include <linux/leds.h> | 34 | #include <linux/leds.h> |
| 35 | #include <linux/platform_data/asoc-mx27vis.h> | ||
| 35 | #include <media/soc_camera.h> | 36 | #include <media/soc_camera.h> |
| 36 | #include <sound/tlv320aic32x4.h> | 37 | #include <sound/tlv320aic32x4.h> |
| 37 | #include <asm/mach-types.h> | 38 | #include <asm/mach-types.h> |
| @@ -58,6 +59,11 @@ | |||
| 58 | #define EXPBOARD_BIT1 (GPIO_PORTD + 27) | 59 | #define EXPBOARD_BIT1 (GPIO_PORTD + 27) |
| 59 | #define EXPBOARD_BIT0 (GPIO_PORTD + 28) | 60 | #define EXPBOARD_BIT0 (GPIO_PORTD + 28) |
| 60 | 61 | ||
| 62 | #define AMP_GAIN_0 (GPIO_PORTF + 9) | ||
| 63 | #define AMP_GAIN_1 (GPIO_PORTF + 8) | ||
| 64 | #define AMP_MUTE_SDL (GPIO_PORTE + 5) | ||
| 65 | #define AMP_MUTE_SDR (GPIO_PORTF + 7) | ||
| 66 | |||
| 61 | static const int visstrim_m10_pins[] __initconst = { | 67 | static const int visstrim_m10_pins[] __initconst = { |
| 62 | /* UART1 (console) */ | 68 | /* UART1 (console) */ |
| 63 | PE12_PF_UART1_TXD, | 69 | PE12_PF_UART1_TXD, |
| @@ -139,6 +145,11 @@ static const int visstrim_m10_pins[] __initconst = { | |||
| 139 | EXPBOARD_BIT2 | GPIO_GPIO | GPIO_IN | GPIO_PUEN, | 145 | EXPBOARD_BIT2 | GPIO_GPIO | GPIO_IN | GPIO_PUEN, |
| 140 | EXPBOARD_BIT1 | GPIO_GPIO | GPIO_IN | GPIO_PUEN, | 146 | EXPBOARD_BIT1 | GPIO_GPIO | GPIO_IN | GPIO_PUEN, |
| 141 | EXPBOARD_BIT0 | GPIO_GPIO | GPIO_IN | GPIO_PUEN, | 147 | EXPBOARD_BIT0 | GPIO_GPIO | GPIO_IN | GPIO_PUEN, |
| 148 | /* Audio AMP control */ | ||
| 149 | AMP_GAIN_0 | GPIO_GPIO | GPIO_OUT, | ||
| 150 | AMP_GAIN_1 | GPIO_GPIO | GPIO_OUT, | ||
| 151 | AMP_MUTE_SDL | GPIO_GPIO | GPIO_OUT, | ||
| 152 | AMP_MUTE_SDR | GPIO_GPIO | GPIO_OUT, | ||
| 142 | }; | 153 | }; |
| 143 | 154 | ||
| 144 | static struct gpio visstrim_m10_version_gpios[] = { | 155 | static struct gpio visstrim_m10_version_gpios[] = { |
| @@ -166,6 +177,26 @@ static const struct gpio visstrim_m10_gpios[] __initconst = { | |||
| 166 | .flags = GPIOF_DIR_OUT | GPIOF_INIT_LOW, | 177 | .flags = GPIOF_DIR_OUT | GPIOF_INIT_LOW, |
| 167 | .label = "usbotg_cs", | 178 | .label = "usbotg_cs", |
| 168 | }, | 179 | }, |
| 180 | { | ||
| 181 | .gpio = AMP_GAIN_0, | ||
| 182 | .flags = GPIOF_DIR_OUT, | ||
| 183 | .label = "amp-gain-0", | ||
| 184 | }, | ||
| 185 | { | ||
| 186 | .gpio = AMP_GAIN_1, | ||
| 187 | .flags = GPIOF_DIR_OUT, | ||
| 188 | .label = "amp-gain-1", | ||
| 189 | }, | ||
| 190 | { | ||
| 191 | .gpio = AMP_MUTE_SDL, | ||
| 192 | .flags = GPIOF_DIR_OUT, | ||
| 193 | .label = "amp-mute-sdl", | ||
| 194 | }, | ||
| 195 | { | ||
| 196 | .gpio = AMP_MUTE_SDR, | ||
| 197 | .flags = GPIOF_DIR_OUT, | ||
| 198 | .label = "amp-mute-sdr", | ||
| 199 | }, | ||
| 169 | }; | 200 | }; |
| 170 | 201 | ||
| 171 | /* Camera */ | 202 | /* Camera */ |
| @@ -444,6 +475,14 @@ static void __init visstrim_deinterlace_init(void) | |||
| 444 | } | 475 | } |
| 445 | 476 | ||
| 446 | 477 | ||
| 478 | /* Audio */ | ||
| 479 | static const struct snd_mx27vis_platform_data snd_mx27vis_pdata __initconst = { | ||
| 480 | .amp_gain0_gpio = AMP_GAIN_0, | ||
| 481 | .amp_gain1_gpio = AMP_GAIN_1, | ||
| 482 | .amp_mutel_gpio = AMP_MUTE_SDL, | ||
| 483 | .amp_muter_gpio = AMP_MUTE_SDR, | ||
| 484 | }; | ||
| 485 | |||
| 447 | static void __init visstrim_m10_revision(void) | 486 | static void __init visstrim_m10_revision(void) |
| 448 | { | 487 | { |
| 449 | int exp_version = 0; | 488 | int exp_version = 0; |
| @@ -502,7 +541,8 @@ static void __init visstrim_m10_board_init(void) | |||
| 502 | imx27_add_fec(NULL); | 541 | imx27_add_fec(NULL); |
| 503 | imx_add_gpio_keys(&visstrim_gpio_keys_platform_data); | 542 | imx_add_gpio_keys(&visstrim_gpio_keys_platform_data); |
| 504 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); | 543 | platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); |
| 505 | imx_add_platform_device("mx27vis", 0, NULL, 0, NULL, 0); | 544 | imx_add_platform_device("mx27vis", 0, NULL, 0, &snd_mx27vis_pdata, |
| 545 | sizeof(snd_mx27vis_pdata)); | ||
| 506 | platform_device_register_resndata(NULL, "soc-camera-pdrv", 0, NULL, 0, | 546 | platform_device_register_resndata(NULL, "soc-camera-pdrv", 0, NULL, 0, |
| 507 | &iclink_tvp5150, sizeof(iclink_tvp5150)); | 547 | &iclink_tvp5150, sizeof(iclink_tvp5150)); |
| 508 | gpio_led_register_device(0, &visstrim_m10_led_data); | 548 | gpio_led_register_device(0, &visstrim_m10_led_data); |
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c index 0d99c9110d01..e16289755f2e 100644 --- a/arch/arm/mach-omap2/board-am3517evm.c +++ b/arch/arm/mach-omap2/board-am3517evm.c | |||
| @@ -263,6 +263,16 @@ static __init void am3517_evm_musb_init(void) | |||
| 263 | usb_musb_init(&musb_board_data); | 263 | usb_musb_init(&musb_board_data); |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | static __init void am3517_evm_mcbsp1_init(void) | ||
| 267 | { | ||
| 268 | u32 devconf0; | ||
| 269 | |||
| 270 | /* McBSP1 CLKR/FSR signal to be connected to CLKX/FSX pin */ | ||
| 271 | devconf0 = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); | ||
| 272 | devconf0 |= OMAP2_MCBSP1_CLKR_MASK | OMAP2_MCBSP1_FSR_MASK; | ||
| 273 | omap_ctrl_writel(devconf0, OMAP2_CONTROL_DEVCONF0); | ||
| 274 | } | ||
| 275 | |||
| 266 | static const struct usbhs_omap_board_data usbhs_bdata __initconst = { | 276 | static const struct usbhs_omap_board_data usbhs_bdata __initconst = { |
| 267 | .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY, | 277 | .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY, |
| 268 | #if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \ | 278 | #if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \ |
| @@ -366,6 +376,9 @@ static void __init am3517_evm_init(void) | |||
| 366 | /* MUSB */ | 376 | /* MUSB */ |
| 367 | am3517_evm_musb_init(); | 377 | am3517_evm_musb_init(); |
| 368 | 378 | ||
| 379 | /* McBSP1 */ | ||
| 380 | am3517_evm_mcbsp1_init(); | ||
| 381 | |||
| 369 | /* MMC init function */ | 382 | /* MMC init function */ |
| 370 | omap_hsmmc_init(mmc); | 383 | omap_hsmmc_init(mmc); |
| 371 | } | 384 | } |
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index 8ffd612c5e07..376d26eb601c 100644 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c | |||
| @@ -723,6 +723,7 @@ static void __init cm_t3x_common_init(void) | |||
| 723 | cm_t35_init_ethernet(); | 723 | cm_t35_init_ethernet(); |
| 724 | cm_t35_init_led(); | 724 | cm_t35_init_led(); |
| 725 | cm_t35_init_display(); | 725 | cm_t35_init_display(); |
| 726 | omap_twl4030_audio_init("cm-t3x"); | ||
| 726 | 727 | ||
| 727 | usb_musb_init(NULL); | 728 | usb_musb_init(NULL); |
| 728 | cm_t35_init_usbh(); | 729 | cm_t35_init_usbh(); |
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 7bb8056d4388..1fd161e934c7 100644 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c | |||
| @@ -623,6 +623,7 @@ static void __init devkit8000_init(void) | |||
| 623 | usbhs_init(&usbhs_bdata); | 623 | usbhs_init(&usbhs_bdata); |
| 624 | omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions, | 624 | omap_nand_flash_init(NAND_BUSWIDTH_16, devkit8000_nand_partitions, |
| 625 | ARRAY_SIZE(devkit8000_nand_partitions)); | 625 | ARRAY_SIZE(devkit8000_nand_partitions)); |
| 626 | omap_twl4030_audio_init("omap3beagle"); | ||
| 626 | 627 | ||
| 627 | /* Ensure SDRC pins are mux'd for self-refresh */ | 628 | /* Ensure SDRC pins are mux'd for self-refresh */ |
| 628 | omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); | 629 | omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); |
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c index fb8bd837dd13..48d5e41dfbfa 100644 --- a/arch/arm/mach-omap2/board-igep0020.c +++ b/arch/arm/mach-omap2/board-igep0020.c | |||
| @@ -625,6 +625,7 @@ static void __init igep_init(void) | |||
| 625 | 625 | ||
| 626 | igep_flash_init(); | 626 | igep_flash_init(); |
| 627 | igep_leds_init(); | 627 | igep_leds_init(); |
| 628 | omap_twl4030_audio_init("igep2"); | ||
| 628 | 629 | ||
| 629 | /* | 630 | /* |
| 630 | * WLAN-BT combo module from MuRata which has a Marvell WLAN | 631 | * WLAN-BT combo module from MuRata which has a Marvell WLAN |
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 68ff8d51973c..a08bebc94ec5 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c | |||
| @@ -514,6 +514,7 @@ static void __init omap3_beagle_init(void) | |||
| 514 | usbhs_init(&usbhs_bdata); | 514 | usbhs_init(&usbhs_bdata); |
| 515 | omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions, | 515 | omap_nand_flash_init(NAND_BUSWIDTH_16, omap3beagle_nand_partitions, |
| 516 | ARRAY_SIZE(omap3beagle_nand_partitions)); | 516 | ARRAY_SIZE(omap3beagle_nand_partitions)); |
| 517 | omap_twl4030_audio_init("omap3beagle"); | ||
| 517 | 518 | ||
| 518 | /* Ensure msecure is mux'd to be able to set the RTC. */ | 519 | /* Ensure msecure is mux'd to be able to set the RTC. */ |
| 519 | omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH); | 520 | omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH); |
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index c64e565bdef5..a3959de85e05 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c | |||
| @@ -739,6 +739,7 @@ static void __init omap3_evm_init(void) | |||
| 739 | omap3evm_init_smsc911x(); | 739 | omap3evm_init_smsc911x(); |
| 740 | omap3_evm_display_init(); | 740 | omap3_evm_display_init(); |
| 741 | omap3_evm_wl12xx_init(); | 741 | omap3_evm_wl12xx_init(); |
| 742 | omap_twl4030_audio_init("omap3evm"); | ||
| 742 | } | 743 | } |
| 743 | 744 | ||
| 744 | MACHINE_START(OMAP3EVM, "OMAP3 EVM") | 745 | MACHINE_START(OMAP3EVM, "OMAP3 EVM") |
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 2e7f24030fc9..b700685762b5 100644 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c | |||
| @@ -504,6 +504,7 @@ static void __init overo_init(void) | |||
| 504 | overo_display_init(); | 504 | overo_display_init(); |
| 505 | overo_init_led(); | 505 | overo_init_led(); |
| 506 | overo_init_keys(); | 506 | overo_init_keys(); |
| 507 | omap_twl4030_audio_init("overo"); | ||
| 507 | 508 | ||
| 508 | /* Ensure SDRC pins are mux'd for self-refresh */ | 509 | /* Ensure SDRC pins are mux'd for self-refresh */ |
| 509 | omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); | 510 | omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT); |
diff --git a/arch/arm/mach-omap2/board-zoom-peripherals.c b/arch/arm/mach-omap2/board-zoom-peripherals.c index 6bcc107b9fc3..67f8540c8e07 100644 --- a/arch/arm/mach-omap2/board-zoom-peripherals.c +++ b/arch/arm/mach-omap2/board-zoom-peripherals.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include "common-board-devices.h" | 35 | #include "common-board-devices.h" |
| 36 | 36 | ||
| 37 | #define OMAP_ZOOM_WLAN_PMENA_GPIO (101) | 37 | #define OMAP_ZOOM_WLAN_PMENA_GPIO (101) |
| 38 | #define ZOOM2_HEADSET_EXTMUTE_GPIO (153) | ||
| 38 | #define OMAP_ZOOM_WLAN_IRQ_GPIO (162) | 39 | #define OMAP_ZOOM_WLAN_IRQ_GPIO (162) |
| 39 | 40 | ||
| 40 | #define LCD_PANEL_ENABLE_GPIO (7 + OMAP_MAX_GPIO_LINES) | 41 | #define LCD_PANEL_ENABLE_GPIO (7 + OMAP_MAX_GPIO_LINES) |
| @@ -245,12 +246,6 @@ static int zoom_twl_gpio_setup(struct device *dev, | |||
| 245 | return ret; | 246 | return ret; |
| 246 | } | 247 | } |
| 247 | 248 | ||
| 248 | /* EXTMUTE callback function */ | ||
| 249 | static void zoom2_set_hs_extmute(int mute) | ||
| 250 | { | ||
| 251 | gpio_set_value(ZOOM2_HEADSET_EXTMUTE_GPIO, mute); | ||
| 252 | } | ||
| 253 | |||
| 254 | static struct twl4030_gpio_platform_data zoom_gpio_data = { | 249 | static struct twl4030_gpio_platform_data zoom_gpio_data = { |
| 255 | .setup = zoom_twl_gpio_setup, | 250 | .setup = zoom_twl_gpio_setup, |
| 256 | }; | 251 | }; |
| @@ -277,7 +272,7 @@ static int __init omap_i2c_init(void) | |||
| 277 | 272 | ||
| 278 | codec_data->ramp_delay_value = 3; /* 161 ms */ | 273 | codec_data->ramp_delay_value = 3; /* 161 ms */ |
| 279 | codec_data->hs_extmute = 1; | 274 | codec_data->hs_extmute = 1; |
| 280 | codec_data->set_hs_extmute = zoom2_set_hs_extmute; | 275 | codec_data->hs_extmute_gpio = ZOOM2_HEADSET_EXTMUTE_GPIO; |
| 281 | } | 276 | } |
| 282 | omap_pmic_init(1, 2400, "twl5030", 7 + OMAP_INTC_START, &zoom_twldata); | 277 | omap_pmic_init(1, 2400, "twl5030", 7 + OMAP_INTC_START, &zoom_twldata); |
| 283 | omap_register_i2c_bus(2, 400, NULL, 0); | 278 | omap_register_i2c_bus(2, 400, NULL, 0); |
diff --git a/arch/arm/mach-omap2/include/mach/board-zoom.h b/arch/arm/mach-omap2/include/mach/board-zoom.h index 775fdc3b000b..2e9486940ead 100644 --- a/arch/arm/mach-omap2/include/mach/board-zoom.h +++ b/arch/arm/mach-omap2/include/mach/board-zoom.h | |||
| @@ -8,5 +8,3 @@ | |||
| 8 | extern int __init zoom_debugboard_init(void); | 8 | extern int __init zoom_debugboard_init(void); |
| 9 | extern void __init zoom_peripherals_init(void); | 9 | extern void __init zoom_peripherals_init(void); |
| 10 | extern void __init zoom_display_init(void); | 10 | extern void __init zoom_display_init(void); |
| 11 | |||
| 12 | #define ZOOM2_HEADSET_EXTMUTE_GPIO 153 | ||
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c index 7d47407d6d46..37f8f948047b 100644 --- a/arch/arm/mach-omap2/mcbsp.c +++ b/arch/arm/mach-omap2/mcbsp.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
| 16 | #include <linux/err.h> | 16 | #include <linux/err.h> |
| 17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
| 18 | #include <linux/of.h> | ||
| 18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
| 19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 20 | #include <linux/platform_data/asoc-ti-mcbsp.h> | 21 | #include <linux/platform_data/asoc-ti-mcbsp.h> |
| @@ -23,8 +24,6 @@ | |||
| 23 | #include <plat/omap_device.h> | 24 | #include <plat/omap_device.h> |
| 24 | #include <linux/pm_runtime.h> | 25 | #include <linux/pm_runtime.h> |
| 25 | 26 | ||
| 26 | #include "control.h" | ||
| 27 | |||
| 28 | /* | 27 | /* |
| 29 | * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle. | 28 | * FIXME: Find a mechanism to enable/disable runtime the McBSP ICLK autoidle. |
| 30 | * Sidetone needs non-gated ICLK and sidetone autoidle is broken. | 29 | * Sidetone needs non-gated ICLK and sidetone autoidle is broken. |
| @@ -32,112 +31,6 @@ | |||
| 32 | #include "cm2xxx_3xxx.h" | 31 | #include "cm2xxx_3xxx.h" |
| 33 | #include "cm-regbits-34xx.h" | 32 | #include "cm-regbits-34xx.h" |
| 34 | 33 | ||
| 35 | /* McBSP1 internal signal muxing function for OMAP2/3 */ | ||
| 36 | static int omap2_mcbsp1_mux_rx_clk(struct device *dev, const char *signal, | ||
| 37 | const char *src) | ||
| 38 | { | ||
| 39 | u32 v; | ||
| 40 | |||
| 41 | v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); | ||
| 42 | |||
| 43 | if (!strcmp(signal, "clkr")) { | ||
| 44 | if (!strcmp(src, "clkr")) | ||
| 45 | v &= ~OMAP2_MCBSP1_CLKR_MASK; | ||
| 46 | else if (!strcmp(src, "clkx")) | ||
| 47 | v |= OMAP2_MCBSP1_CLKR_MASK; | ||
| 48 | else | ||
| 49 | return -EINVAL; | ||
| 50 | } else if (!strcmp(signal, "fsr")) { | ||
| 51 | if (!strcmp(src, "fsr")) | ||
| 52 | v &= ~OMAP2_MCBSP1_FSR_MASK; | ||
| 53 | else if (!strcmp(src, "fsx")) | ||
| 54 | v |= OMAP2_MCBSP1_FSR_MASK; | ||
| 55 | else | ||
| 56 | return -EINVAL; | ||
| 57 | } else { | ||
| 58 | return -EINVAL; | ||
| 59 | } | ||
| 60 | |||
| 61 | omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); | ||
| 62 | |||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | |||
| 66 | /* McBSP4 internal signal muxing function for OMAP4 */ | ||
| 67 | #define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX (1 << 31) | ||
| 68 | #define OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX (1 << 30) | ||
| 69 | static int omap4_mcbsp4_mux_rx_clk(struct device *dev, const char *signal, | ||
| 70 | const char *src) | ||
| 71 | { | ||
| 72 | u32 v; | ||
| 73 | |||
| 74 | /* | ||
| 75 | * In CONTROL_MCBSPLP register only bit 30 (CLKR mux), and bit 31 (FSR | ||
| 76 | * mux) is used */ | ||
| 77 | v = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP); | ||
| 78 | |||
| 79 | if (!strcmp(signal, "clkr")) { | ||
| 80 | if (!strcmp(src, "clkr")) | ||
| 81 | v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX; | ||
| 82 | else if (!strcmp(src, "clkx")) | ||
| 83 | v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_CLKX; | ||
| 84 | else | ||
| 85 | return -EINVAL; | ||
| 86 | } else if (!strcmp(signal, "fsr")) { | ||
| 87 | if (!strcmp(src, "fsr")) | ||
| 88 | v &= ~OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX; | ||
| 89 | else if (!strcmp(src, "fsx")) | ||
| 90 | v |= OMAP4_CONTROL_MCBSPLP_ALBCTRLRX_FSX; | ||
| 91 | else | ||
| 92 | return -EINVAL; | ||
| 93 | } else { | ||
| 94 | return -EINVAL; | ||
| 95 | } | ||
| 96 | |||
| 97 | omap4_ctrl_pad_writel(v, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MCBSPLP); | ||
| 98 | |||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | /* McBSP CLKS source switching function */ | ||
| 103 | static int omap2_mcbsp_set_clk_src(struct device *dev, struct clk *clk, | ||
| 104 | const char *src) | ||
| 105 | { | ||
| 106 | struct clk *fck_src; | ||
| 107 | char *fck_src_name; | ||
| 108 | int r; | ||
| 109 | |||
| 110 | if (!strcmp(src, "clks_ext")) | ||
| 111 | fck_src_name = "pad_fck"; | ||
| 112 | else if (!strcmp(src, "clks_fclk")) | ||
| 113 | fck_src_name = "prcm_fck"; | ||
| 114 | else | ||
| 115 | return -EINVAL; | ||
| 116 | |||
| 117 | fck_src = clk_get(dev, fck_src_name); | ||
| 118 | if (IS_ERR_OR_NULL(fck_src)) { | ||
| 119 | pr_err("omap-mcbsp: %s: could not clk_get() %s\n", "clks", | ||
| 120 | fck_src_name); | ||
| 121 | return -EINVAL; | ||
| 122 | } | ||
| 123 | |||
| 124 | pm_runtime_put_sync(dev); | ||
| 125 | |||
| 126 | r = clk_set_parent(clk, fck_src); | ||
| 127 | if (IS_ERR_VALUE(r)) { | ||
| 128 | pr_err("omap-mcbsp: %s: could not clk_set_parent() to %s\n", | ||
| 129 | "clks", fck_src_name); | ||
| 130 | clk_put(fck_src); | ||
| 131 | return -EINVAL; | ||
| 132 | } | ||
| 133 | |||
| 134 | pm_runtime_get_sync(dev); | ||
| 135 | |||
| 136 | clk_put(fck_src); | ||
| 137 | |||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | static int omap3_enable_st_clock(unsigned int id, bool enable) | 34 | static int omap3_enable_st_clock(unsigned int id, bool enable) |
| 142 | { | 35 | { |
| 143 | unsigned int w; | 36 | unsigned int w; |
| @@ -179,17 +72,11 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused) | |||
| 179 | pdata->reg_size = 4; | 72 | pdata->reg_size = 4; |
| 180 | pdata->has_ccr = true; | 73 | pdata->has_ccr = true; |
| 181 | } | 74 | } |
| 182 | pdata->set_clk_src = omap2_mcbsp_set_clk_src; | ||
| 183 | |||
| 184 | /* On OMAP2/3 the McBSP1 port has 6 pin configuration */ | ||
| 185 | if (id == 1 && oh->class->rev < MCBSP_CONFIG_TYPE4) | ||
| 186 | pdata->mux_signal = omap2_mcbsp1_mux_rx_clk; | ||
| 187 | 75 | ||
| 188 | /* On OMAP4 the McBSP4 port has 6 pin configuration */ | 76 | if (oh->class->rev == MCBSP_CONFIG_TYPE2) { |
| 189 | if (id == 4 && oh->class->rev == MCBSP_CONFIG_TYPE4) | 77 | /* The FIFO has 128 locations */ |
| 190 | pdata->mux_signal = omap4_mcbsp4_mux_rx_clk; | 78 | pdata->buffer_size = 0x80; |
| 191 | 79 | } else if (oh->class->rev == MCBSP_CONFIG_TYPE3) { | |
| 192 | if (oh->class->rev == MCBSP_CONFIG_TYPE3) { | ||
| 193 | if (id == 2) | 80 | if (id == 2) |
| 194 | /* The FIFO has 1024 + 256 locations */ | 81 | /* The FIFO has 1024 + 256 locations */ |
| 195 | pdata->buffer_size = 0x500; | 82 | pdata->buffer_size = 0x500; |
| @@ -225,7 +112,8 @@ static int __init omap_init_mcbsp(struct omap_hwmod *oh, void *unused) | |||
| 225 | 112 | ||
| 226 | static int __init omap2_mcbsp_init(void) | 113 | static int __init omap2_mcbsp_init(void) |
| 227 | { | 114 | { |
| 228 | omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL); | 115 | if (!of_have_populated_dt()) |
| 116 | omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL); | ||
| 229 | 117 | ||
| 230 | return 0; | 118 | return 0; |
| 231 | } | 119 | } |
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 8d7a93525bc6..652d0285bd6d 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c | |||
| @@ -5269,6 +5269,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_per__mcbsp4 = { | |||
| 5269 | 5269 | ||
| 5270 | static struct omap_hwmod_addr_space omap44xx_mcpdm_addrs[] = { | 5270 | static struct omap_hwmod_addr_space omap44xx_mcpdm_addrs[] = { |
| 5271 | { | 5271 | { |
| 5272 | .name = "mpu", | ||
| 5272 | .pa_start = 0x40132000, | 5273 | .pa_start = 0x40132000, |
| 5273 | .pa_end = 0x4013207f, | 5274 | .pa_end = 0x4013207f, |
| 5274 | .flags = ADDR_TYPE_RT | 5275 | .flags = ADDR_TYPE_RT |
| @@ -5287,6 +5288,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm = { | |||
| 5287 | 5288 | ||
| 5288 | static struct omap_hwmod_addr_space omap44xx_mcpdm_dma_addrs[] = { | 5289 | static struct omap_hwmod_addr_space omap44xx_mcpdm_dma_addrs[] = { |
| 5289 | { | 5290 | { |
| 5291 | .name = "dma", | ||
| 5290 | .pa_start = 0x49032000, | 5292 | .pa_start = 0x49032000, |
| 5291 | .pa_end = 0x4903207f, | 5293 | .pa_end = 0x4903207f, |
| 5292 | .flags = ADDR_TYPE_RT | 5294 | .flags = ADDR_TYPE_RT |
diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index 45f77413c21d..18a851959425 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c | |||
| @@ -519,3 +519,30 @@ void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data, | |||
| 519 | pmic_data->v2v1 = &omap4_v2v1_idata; | 519 | pmic_data->v2v1 = &omap4_v2v1_idata; |
| 520 | } | 520 | } |
| 521 | #endif /* CONFIG_ARCH_OMAP4 */ | 521 | #endif /* CONFIG_ARCH_OMAP4 */ |
| 522 | |||
| 523 | #if defined(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) || \ | ||
| 524 | defined(CONFIG_SND_OMAP_SOC_OMAP_TWL4030_MODULE) | ||
| 525 | #include <linux/platform_data/omap-twl4030.h> | ||
| 526 | |||
| 527 | static struct omap_tw4030_pdata omap_twl4030_audio_data; | ||
| 528 | |||
| 529 | static struct platform_device audio_device = { | ||
| 530 | .name = "omap-twl4030", | ||
| 531 | .id = -1, | ||
| 532 | .dev = { | ||
| 533 | .platform_data = &omap_twl4030_audio_data, | ||
| 534 | }, | ||
| 535 | }; | ||
| 536 | |||
| 537 | void __init omap_twl4030_audio_init(char *card_name) | ||
| 538 | { | ||
| 539 | omap_twl4030_audio_data.card_name = card_name; | ||
| 540 | platform_device_register(&audio_device); | ||
| 541 | } | ||
| 542 | |||
| 543 | #else /* SOC_OMAP_TWL4030 */ | ||
| 544 | void __init omap_twl4030_audio_init(char *card_name) | ||
| 545 | { | ||
| 546 | return; | ||
| 547 | } | ||
| 548 | #endif /* SOC_OMAP_TWL4030 */ | ||
diff --git a/arch/arm/mach-omap2/twl-common.h b/arch/arm/mach-omap2/twl-common.h index 2256efe90cf1..dcfbad5ac471 100644 --- a/arch/arm/mach-omap2/twl-common.h +++ b/arch/arm/mach-omap2/twl-common.h | |||
| @@ -60,4 +60,6 @@ void omap3_pmic_get_config(struct twl4030_platform_data *pmic_data, | |||
| 60 | void omap4_pmic_get_config(struct twl4030_platform_data *pmic_data, | 60 | void omap4_pmic_get_config(struct twl4030_platform_data *pmic_data, |
| 61 | u32 pdata_flags, u32 regulators_flags); | 61 | u32 pdata_flags, u32 regulators_flags); |
| 62 | 62 | ||
| 63 | void omap_twl4030_audio_init(char *card_name); | ||
| 64 | |||
| 63 | #endif /* __OMAP_PMIC_COMMON__ */ | 65 | #endif /* __OMAP_PMIC_COMMON__ */ |
diff --git a/arch/arm/plat-samsung/dma-ops.c b/arch/arm/plat-samsung/dma-ops.c index c38d75489240..d088afa034e8 100644 --- a/arch/arm/plat-samsung/dma-ops.c +++ b/arch/arm/plat-samsung/dma-ops.c | |||
| @@ -91,7 +91,8 @@ static int samsung_dmadev_prepare(unsigned ch, | |||
| 91 | break; | 91 | break; |
| 92 | case DMA_CYCLIC: | 92 | case DMA_CYCLIC: |
| 93 | desc = dmaengine_prep_dma_cyclic(chan, param->buf, | 93 | desc = dmaengine_prep_dma_cyclic(chan, param->buf, |
| 94 | param->len, param->period, param->direction); | 94 | param->len, param->period, param->direction, |
| 95 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
| 95 | break; | 96 | break; |
| 96 | default: | 97 | default: |
| 97 | dev_err(&chan->dev->device, "unsupported format\n"); | 98 | dev_err(&chan->dev->device, "unsupported format\n"); |
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c index fc179ca07799..29f16e5c37b9 100644 --- a/arch/blackfin/mach-bf527/boards/ezkit.c +++ b/arch/blackfin/mach-bf527/boards/ezkit.c | |||
| @@ -587,6 +587,21 @@ static struct platform_device bfin_tdm = { | |||
| 587 | }; | 587 | }; |
| 588 | #endif | 588 | #endif |
| 589 | 589 | ||
| 590 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ | ||
| 591 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | ||
| 592 | static const char * const ad1836_link[] = { | ||
| 593 | "bfin-tdm.0", | ||
| 594 | "spi0.4", | ||
| 595 | }; | ||
| 596 | static struct platform_device bfin_ad1836_machine = { | ||
| 597 | .name = "bfin-snd-ad1836", | ||
| 598 | .id = -1, | ||
| 599 | .dev = { | ||
| 600 | .platform_data = (void *)ad1836_link, | ||
| 601 | }, | ||
| 602 | }; | ||
| 603 | #endif | ||
| 604 | |||
| 590 | static struct spi_board_info bfin_spi_board_info[] __initdata = { | 605 | static struct spi_board_info bfin_spi_board_info[] __initdata = { |
| 591 | #if defined(CONFIG_MTD_M25P80) \ | 606 | #if defined(CONFIG_MTD_M25P80) \ |
| 592 | || defined(CONFIG_MTD_M25P80_MODULE) | 607 | || defined(CONFIG_MTD_M25P80_MODULE) |
| @@ -1269,6 +1284,11 @@ static struct platform_device *stamp_devices[] __initdata = { | |||
| 1269 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) | 1284 | #if defined(CONFIG_SND_BF5XX_TDM) || defined(CONFIG_SND_BF5XX_TDM_MODULE) |
| 1270 | &bfin_tdm, | 1285 | &bfin_tdm, |
| 1271 | #endif | 1286 | #endif |
| 1287 | |||
| 1288 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \ | ||
| 1289 | defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | ||
| 1290 | &bfin_ad1836_machine, | ||
| 1291 | #endif | ||
| 1272 | }; | 1292 | }; |
| 1273 | 1293 | ||
| 1274 | static int __init ezkit_init(void) | 1294 | static int __init ezkit_init(void) |
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c index ce88a7165b62..6fca8698bf3b 100644 --- a/arch/blackfin/mach-bf533/boards/stamp.c +++ b/arch/blackfin/mach-bf533/boards/stamp.c | |||
| @@ -617,6 +617,21 @@ static struct platform_device bfin_ac97_pcm = { | |||
| 617 | }; | 617 | }; |
| 618 | #endif | 618 | #endif |
| 619 | 619 | ||
| 620 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ | ||
| 621 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | ||
| 622 | static const char * const ad1836_link[] = { | ||
| 623 | "bfin-tdm.0", | ||
| 624 | "spi0.4", | ||
| 625 | }; | ||
| 626 | static struct platform_device bfin_ad1836_machine = { | ||
| 627 | .name = "bfin-snd-ad1836", | ||
| 628 | .id = -1, | ||
| 629 | .dev = { | ||
| 630 | .platform_data = (void *)ad1836_link, | ||
| 631 | }, | ||
| 632 | }; | ||
| 633 | #endif | ||
| 634 | |||
| 620 | #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \ | 635 | #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \ |
| 621 | defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) | 636 | defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) |
| 622 | static const unsigned ad73311_gpio[] = { | 637 | static const unsigned ad73311_gpio[] = { |
| @@ -754,6 +769,11 @@ static struct platform_device *stamp_devices[] __initdata = { | |||
| 754 | &bfin_ac97_pcm, | 769 | &bfin_ac97_pcm, |
| 755 | #endif | 770 | #endif |
| 756 | 771 | ||
| 772 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \ | ||
| 773 | defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | ||
| 774 | &bfin_ad1836_machine, | ||
| 775 | #endif | ||
| 776 | |||
| 757 | #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \ | 777 | #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \ |
| 758 | defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) | 778 | defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) |
| 759 | &bfin_ad73311_machine, | 779 | &bfin_ad73311_machine, |
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c index 5ed654ae66e1..307bd7e62f43 100644 --- a/arch/blackfin/mach-bf537/boards/stamp.c +++ b/arch/blackfin/mach-bf537/boards/stamp.c | |||
| @@ -2641,6 +2641,21 @@ static struct platform_device bfin_ac97_pcm = { | |||
| 2641 | }; | 2641 | }; |
| 2642 | #endif | 2642 | #endif |
| 2643 | 2643 | ||
| 2644 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ | ||
| 2645 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | ||
| 2646 | static const char * const ad1836_link[] = { | ||
| 2647 | "bfin-tdm.0", | ||
| 2648 | "spi0.4", | ||
| 2649 | }; | ||
| 2650 | static struct platform_device bfin_ad1836_machine = { | ||
| 2651 | .name = "bfin-snd-ad1836", | ||
| 2652 | .id = -1, | ||
| 2653 | .dev = { | ||
| 2654 | .platform_data = (void *)ad1836_link, | ||
| 2655 | }, | ||
| 2656 | }; | ||
| 2657 | #endif | ||
| 2658 | |||
| 2644 | #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \ | 2659 | #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \ |
| 2645 | defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) | 2660 | defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) |
| 2646 | static const unsigned ad73311_gpio[] = { | 2661 | static const unsigned ad73311_gpio[] = { |
| @@ -2927,6 +2942,11 @@ static struct platform_device *stamp_devices[] __initdata = { | |||
| 2927 | &bfin_ac97_pcm, | 2942 | &bfin_ac97_pcm, |
| 2928 | #endif | 2943 | #endif |
| 2929 | 2944 | ||
| 2945 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \ | ||
| 2946 | defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | ||
| 2947 | &bfin_ad1836_machine, | ||
| 2948 | #endif | ||
| 2949 | |||
| 2930 | #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \ | 2950 | #if defined(CONFIG_SND_BF5XX_SOC_AD73311) || \ |
| 2931 | defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) | 2951 | defined(CONFIG_SND_BF5XX_SOC_AD73311_MODULE) |
| 2932 | &bfin_ad73311_machine, | 2952 | &bfin_ad73311_machine, |
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c index 7c36777c6455..551f866172cf 100644 --- a/arch/blackfin/mach-bf561/boards/ezkit.c +++ b/arch/blackfin/mach-bf561/boards/ezkit.c | |||
| @@ -539,6 +539,21 @@ static struct platform_device bfin_ac97 = { | |||
| 539 | }; | 539 | }; |
| 540 | #endif | 540 | #endif |
| 541 | 541 | ||
| 542 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ | ||
| 543 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | ||
| 544 | static const char * const ad1836_link[] = { | ||
| 545 | "bfin-tdm.0", | ||
| 546 | "spi0.4", | ||
| 547 | }; | ||
| 548 | static struct platform_device bfin_ad1836_machine = { | ||
| 549 | .name = "bfin-snd-ad1836", | ||
| 550 | .id = -1, | ||
| 551 | .dev = { | ||
| 552 | .platform_data = (void *)ad1836_link, | ||
| 553 | }, | ||
| 554 | }; | ||
| 555 | #endif | ||
| 556 | |||
| 542 | static struct platform_device *ezkit_devices[] __initdata = { | 557 | static struct platform_device *ezkit_devices[] __initdata = { |
| 543 | 558 | ||
| 544 | &bfin_dpmc, | 559 | &bfin_dpmc, |
| @@ -603,6 +618,11 @@ static struct platform_device *ezkit_devices[] __initdata = { | |||
| 603 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) | 618 | #if defined(CONFIG_SND_BF5XX_AC97) || defined(CONFIG_SND_BF5XX_AC97_MODULE) |
| 604 | &bfin_ac97, | 619 | &bfin_ac97, |
| 605 | #endif | 620 | #endif |
| 621 | |||
| 622 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \ | ||
| 623 | defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | ||
| 624 | &bfin_ad1836_machine, | ||
| 625 | #endif | ||
| 606 | }; | 626 | }; |
| 607 | 627 | ||
| 608 | static int __init net2272_init(void) | 628 | static int __init net2272_init(void) |
diff --git a/arch/blackfin/mach-bf609/boards/ezkit.c b/arch/blackfin/mach-bf609/boards/ezkit.c index c2cf1ae31189..61c1f47a4bf2 100644 --- a/arch/blackfin/mach-bf609/boards/ezkit.c +++ b/arch/blackfin/mach-bf609/boards/ezkit.c | |||
| @@ -818,6 +818,21 @@ static struct platform_device bfin_i2s = { | |||
| 818 | }; | 818 | }; |
| 819 | #endif | 819 | #endif |
| 820 | 820 | ||
| 821 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) \ | ||
| 822 | || defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | ||
| 823 | static const char * const ad1836_link[] = { | ||
| 824 | "bfin-tdm.0", | ||
| 825 | "spi0.76", | ||
| 826 | }; | ||
| 827 | static struct platform_device bfin_ad1836_machine = { | ||
| 828 | .name = "bfin-snd-ad1836", | ||
| 829 | .id = -1, | ||
| 830 | .dev = { | ||
| 831 | .platform_data = (void *)ad1836_link, | ||
| 832 | }, | ||
| 833 | }; | ||
| 834 | #endif | ||
| 835 | |||
| 821 | #if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61) || \ | 836 | #if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61) || \ |
| 822 | defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61_MODULE) | 837 | defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61_MODULE) |
| 823 | static struct platform_device adau1761_device = { | 838 | static struct platform_device adau1761_device = { |
| @@ -1557,6 +1572,10 @@ static struct platform_device *ezkit_devices[] __initdata = { | |||
| 1557 | defined(CONFIG_SND_BF6XX_SOC_I2S_MODULE) | 1572 | defined(CONFIG_SND_BF6XX_SOC_I2S_MODULE) |
| 1558 | &bfin_i2s, | 1573 | &bfin_i2s, |
| 1559 | #endif | 1574 | #endif |
| 1575 | #if defined(CONFIG_SND_BF5XX_SOC_AD1836) || \ | ||
| 1576 | defined(CONFIG_SND_BF5XX_SOC_AD1836_MODULE) | ||
| 1577 | &bfin_ad1836_machine, | ||
| 1578 | #endif | ||
| 1560 | #if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61) || \ | 1579 | #if defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61) || \ |
| 1561 | defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61_MODULE) | 1580 | defined(CONFIG_SND_SOC_BFIN_EVAL_ADAU1X61_MODULE) |
| 1562 | &adau1761_device, | 1581 | &adau1761_device, |
diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 17d6958342e7..13a02f4425b0 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c | |||
| @@ -852,12 +852,13 @@ atc_dma_cyclic_fill_desc(struct dma_chan *chan, struct at_desc *desc, | |||
| 852 | * @buf_len: total number of bytes for the entire buffer | 852 | * @buf_len: total number of bytes for the entire buffer |
| 853 | * @period_len: number of bytes for each period | 853 | * @period_len: number of bytes for each period |
| 854 | * @direction: transfer direction, to or from device | 854 | * @direction: transfer direction, to or from device |
| 855 | * @flags: tx descriptor status flags | ||
| 855 | * @context: transfer context (ignored) | 856 | * @context: transfer context (ignored) |
| 856 | */ | 857 | */ |
| 857 | static struct dma_async_tx_descriptor * | 858 | static struct dma_async_tx_descriptor * |
| 858 | atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, | 859 | atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, |
| 859 | size_t period_len, enum dma_transfer_direction direction, | 860 | size_t period_len, enum dma_transfer_direction direction, |
| 860 | void *context) | 861 | unsigned long flags, void *context) |
| 861 | { | 862 | { |
| 862 | struct at_dma_chan *atchan = to_at_dma_chan(chan); | 863 | struct at_dma_chan *atchan = to_at_dma_chan(chan); |
| 863 | struct at_dma_slave *atslave = chan->private; | 864 | struct at_dma_slave *atslave = chan->private; |
diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index 64256f644252..bcfde400904f 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c | |||
| @@ -1120,6 +1120,7 @@ fail: | |||
| 1120 | * @buf_len: length of the buffer (in bytes) | 1120 | * @buf_len: length of the buffer (in bytes) |
| 1121 | * @period_len: length of a single period | 1121 | * @period_len: length of a single period |
| 1122 | * @dir: direction of the operation | 1122 | * @dir: direction of the operation |
| 1123 | * @flags: tx descriptor status flags | ||
| 1123 | * @context: operation context (ignored) | 1124 | * @context: operation context (ignored) |
| 1124 | * | 1125 | * |
| 1125 | * Prepares a descriptor for cyclic DMA operation. This means that once the | 1126 | * Prepares a descriptor for cyclic DMA operation. This means that once the |
| @@ -1133,7 +1134,8 @@ fail: | |||
| 1133 | static struct dma_async_tx_descriptor * | 1134 | static struct dma_async_tx_descriptor * |
| 1134 | ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, | 1135 | ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, |
| 1135 | size_t buf_len, size_t period_len, | 1136 | size_t buf_len, size_t period_len, |
| 1136 | enum dma_transfer_direction dir, void *context) | 1137 | enum dma_transfer_direction dir, unsigned long flags, |
| 1138 | void *context) | ||
| 1137 | { | 1139 | { |
| 1138 | struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); | 1140 | struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); |
| 1139 | struct ep93xx_dma_desc *desc, *first; | 1141 | struct ep93xx_dma_desc *desc, *first; |
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 2a3fab289db0..f11b5b2b1a1c 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c | |||
| @@ -801,7 +801,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg( | |||
| 801 | static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic( | 801 | static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic( |
| 802 | struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, | 802 | struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, |
| 803 | size_t period_len, enum dma_transfer_direction direction, | 803 | size_t period_len, enum dma_transfer_direction direction, |
| 804 | void *context) | 804 | unsigned long flags, void *context) |
| 805 | { | 805 | { |
| 806 | struct imxdma_channel *imxdmac = to_imxdma_chan(chan); | 806 | struct imxdma_channel *imxdmac = to_imxdma_chan(chan); |
| 807 | struct imxdma_engine *imxdma = imxdmac->imxdma; | 807 | struct imxdma_engine *imxdma = imxdmac->imxdma; |
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index 1b781d6ac425..c099ca0846f4 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c | |||
| @@ -1012,7 +1012,7 @@ err_out: | |||
| 1012 | static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( | 1012 | static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( |
| 1013 | struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, | 1013 | struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, |
| 1014 | size_t period_len, enum dma_transfer_direction direction, | 1014 | size_t period_len, enum dma_transfer_direction direction, |
| 1015 | void *context) | 1015 | unsigned long flags, void *context) |
| 1016 | { | 1016 | { |
| 1017 | struct sdma_channel *sdmac = to_sdma_chan(chan); | 1017 | struct sdma_channel *sdmac = to_sdma_chan(chan); |
| 1018 | struct sdma_engine *sdma = sdmac->sdma; | 1018 | struct sdma_engine *sdma = sdmac->sdma; |
diff --git a/drivers/dma/mmp_tdma.c b/drivers/dma/mmp_tdma.c index 07fa48688ba9..6d9c82e891d7 100644 --- a/drivers/dma/mmp_tdma.c +++ b/drivers/dma/mmp_tdma.c | |||
| @@ -358,7 +358,7 @@ struct mmp_tdma_desc *mmp_tdma_alloc_descriptor(struct mmp_tdma_chan *tdmac) | |||
| 358 | static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic( | 358 | static struct dma_async_tx_descriptor *mmp_tdma_prep_dma_cyclic( |
| 359 | struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, | 359 | struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, |
| 360 | size_t period_len, enum dma_transfer_direction direction, | 360 | size_t period_len, enum dma_transfer_direction direction, |
| 361 | void *context) | 361 | unsigned long flags, void *context) |
| 362 | { | 362 | { |
| 363 | struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); | 363 | struct mmp_tdma_chan *tdmac = to_mmp_tdma_chan(chan); |
| 364 | struct mmp_tdma_desc *desc; | 364 | struct mmp_tdma_desc *desc; |
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index 7f41b25805fa..734a4eb84d65 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c | |||
| @@ -531,7 +531,7 @@ err_out: | |||
| 531 | static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic( | 531 | static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic( |
| 532 | struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, | 532 | struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len, |
| 533 | size_t period_len, enum dma_transfer_direction direction, | 533 | size_t period_len, enum dma_transfer_direction direction, |
| 534 | void *context) | 534 | unsigned long flags, void *context) |
| 535 | { | 535 | { |
| 536 | struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); | 536 | struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); |
| 537 | struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; | 537 | struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; |
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c index 2e1662777661..bb2d8e7029eb 100644 --- a/drivers/dma/omap-dma.c +++ b/drivers/dma/omap-dma.c | |||
| @@ -36,6 +36,7 @@ struct omap_chan { | |||
| 36 | struct dma_slave_config cfg; | 36 | struct dma_slave_config cfg; |
| 37 | unsigned dma_sig; | 37 | unsigned dma_sig; |
| 38 | bool cyclic; | 38 | bool cyclic; |
| 39 | bool paused; | ||
| 39 | 40 | ||
| 40 | int dma_ch; | 41 | int dma_ch; |
| 41 | struct omap_desc *desc; | 42 | struct omap_desc *desc; |
| @@ -367,7 +368,8 @@ static struct dma_async_tx_descriptor *omap_dma_prep_slave_sg( | |||
| 367 | 368 | ||
| 368 | static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( | 369 | static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( |
| 369 | struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, | 370 | struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, |
| 370 | size_t period_len, enum dma_transfer_direction dir, void *context) | 371 | size_t period_len, enum dma_transfer_direction dir, unsigned long flags, |
| 372 | void *context) | ||
| 371 | { | 373 | { |
| 372 | struct omap_chan *c = to_omap_dma_chan(chan); | 374 | struct omap_chan *c = to_omap_dma_chan(chan); |
| 373 | enum dma_slave_buswidth dev_width; | 375 | enum dma_slave_buswidth dev_width; |
| @@ -415,7 +417,10 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( | |||
| 415 | d->dev_addr = dev_addr; | 417 | d->dev_addr = dev_addr; |
| 416 | d->fi = burst; | 418 | d->fi = burst; |
| 417 | d->es = es; | 419 | d->es = es; |
| 418 | d->sync_mode = OMAP_DMA_SYNC_PACKET; | 420 | if (burst) |
| 421 | d->sync_mode = OMAP_DMA_SYNC_PACKET; | ||
| 422 | else | ||
| 423 | d->sync_mode = OMAP_DMA_SYNC_ELEMENT; | ||
| 419 | d->sync_type = sync_type; | 424 | d->sync_type = sync_type; |
| 420 | d->periph_port = OMAP_DMA_PORT_MPUI; | 425 | d->periph_port = OMAP_DMA_PORT_MPUI; |
| 421 | d->sg[0].addr = buf_addr; | 426 | d->sg[0].addr = buf_addr; |
| @@ -426,7 +431,10 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( | |||
| 426 | if (!c->cyclic) { | 431 | if (!c->cyclic) { |
| 427 | c->cyclic = true; | 432 | c->cyclic = true; |
| 428 | omap_dma_link_lch(c->dma_ch, c->dma_ch); | 433 | omap_dma_link_lch(c->dma_ch, c->dma_ch); |
| 429 | omap_enable_dma_irq(c->dma_ch, OMAP_DMA_FRAME_IRQ); | 434 | |
| 435 | if (flags & DMA_PREP_INTERRUPT) | ||
| 436 | omap_enable_dma_irq(c->dma_ch, OMAP_DMA_FRAME_IRQ); | ||
| 437 | |||
| 430 | omap_disable_dma_irq(c->dma_ch, OMAP_DMA_BLOCK_IRQ); | 438 | omap_disable_dma_irq(c->dma_ch, OMAP_DMA_BLOCK_IRQ); |
| 431 | } | 439 | } |
| 432 | 440 | ||
| @@ -435,7 +443,7 @@ static struct dma_async_tx_descriptor *omap_dma_prep_dma_cyclic( | |||
| 435 | omap_set_dma_dest_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16); | 443 | omap_set_dma_dest_burst_mode(c->dma_ch, OMAP_DMA_DATA_BURST_16); |
| 436 | } | 444 | } |
| 437 | 445 | ||
| 438 | return vchan_tx_prep(&c->vc, &d->vd, DMA_CTRL_ACK | DMA_PREP_INTERRUPT); | 446 | return vchan_tx_prep(&c->vc, &d->vd, flags); |
| 439 | } | 447 | } |
| 440 | 448 | ||
| 441 | static int omap_dma_slave_config(struct omap_chan *c, struct dma_slave_config *cfg) | 449 | static int omap_dma_slave_config(struct omap_chan *c, struct dma_slave_config *cfg) |
| @@ -469,11 +477,14 @@ static int omap_dma_terminate_all(struct omap_chan *c) | |||
| 469 | */ | 477 | */ |
| 470 | if (c->desc) { | 478 | if (c->desc) { |
| 471 | c->desc = NULL; | 479 | c->desc = NULL; |
| 472 | omap_stop_dma(c->dma_ch); | 480 | /* Avoid stopping the dma twice */ |
| 481 | if (!c->paused) | ||
| 482 | omap_stop_dma(c->dma_ch); | ||
| 473 | } | 483 | } |
| 474 | 484 | ||
| 475 | if (c->cyclic) { | 485 | if (c->cyclic) { |
| 476 | c->cyclic = false; | 486 | c->cyclic = false; |
| 487 | c->paused = false; | ||
| 477 | omap_dma_unlink_lch(c->dma_ch, c->dma_ch); | 488 | omap_dma_unlink_lch(c->dma_ch, c->dma_ch); |
| 478 | } | 489 | } |
| 479 | 490 | ||
| @@ -486,14 +497,30 @@ static int omap_dma_terminate_all(struct omap_chan *c) | |||
| 486 | 497 | ||
| 487 | static int omap_dma_pause(struct omap_chan *c) | 498 | static int omap_dma_pause(struct omap_chan *c) |
| 488 | { | 499 | { |
| 489 | /* FIXME: not supported by platform private API */ | 500 | /* Pause/Resume only allowed with cyclic mode */ |
| 490 | return -EINVAL; | 501 | if (!c->cyclic) |
| 502 | return -EINVAL; | ||
| 503 | |||
| 504 | if (!c->paused) { | ||
| 505 | omap_stop_dma(c->dma_ch); | ||
| 506 | c->paused = true; | ||
| 507 | } | ||
| 508 | |||
| 509 | return 0; | ||
| 491 | } | 510 | } |
| 492 | 511 | ||
| 493 | static int omap_dma_resume(struct omap_chan *c) | 512 | static int omap_dma_resume(struct omap_chan *c) |
| 494 | { | 513 | { |
| 495 | /* FIXME: not supported by platform private API */ | 514 | /* Pause/Resume only allowed with cyclic mode */ |
| 496 | return -EINVAL; | 515 | if (!c->cyclic) |
| 516 | return -EINVAL; | ||
| 517 | |||
| 518 | if (c->paused) { | ||
| 519 | omap_start_dma(c->dma_ch); | ||
| 520 | c->paused = false; | ||
| 521 | } | ||
| 522 | |||
| 523 | return 0; | ||
| 497 | } | 524 | } |
| 498 | 525 | ||
| 499 | static int omap_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | 526 | static int omap_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, |
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 5d3bbcd279b4..169c0dbd71ae 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c | |||
| @@ -2685,7 +2685,7 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) | |||
| 2685 | static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( | 2685 | static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic( |
| 2686 | struct dma_chan *chan, dma_addr_t dma_addr, size_t len, | 2686 | struct dma_chan *chan, dma_addr_t dma_addr, size_t len, |
| 2687 | size_t period_len, enum dma_transfer_direction direction, | 2687 | size_t period_len, enum dma_transfer_direction direction, |
| 2688 | void *context) | 2688 | unsigned long flags, void *context) |
| 2689 | { | 2689 | { |
| 2690 | struct dma_pl330_desc *desc; | 2690 | struct dma_pl330_desc *desc; |
| 2691 | struct dma_pl330_chan *pch = to_pchan(chan); | 2691 | struct dma_pl330_chan *pch = to_pchan(chan); |
diff --git a/drivers/dma/sa11x0-dma.c b/drivers/dma/sa11x0-dma.c index f5a73606217e..b893159c1ecb 100644 --- a/drivers/dma/sa11x0-dma.c +++ b/drivers/dma/sa11x0-dma.c | |||
| @@ -614,7 +614,7 @@ static struct dma_async_tx_descriptor *sa11x0_dma_prep_slave_sg( | |||
| 614 | 614 | ||
| 615 | static struct dma_async_tx_descriptor *sa11x0_dma_prep_dma_cyclic( | 615 | static struct dma_async_tx_descriptor *sa11x0_dma_prep_dma_cyclic( |
| 616 | struct dma_chan *chan, dma_addr_t addr, size_t size, size_t period, | 616 | struct dma_chan *chan, dma_addr_t addr, size_t size, size_t period, |
| 617 | enum dma_transfer_direction dir, void *context) | 617 | enum dma_transfer_direction dir, unsigned long flags, void *context) |
| 618 | { | 618 | { |
| 619 | struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan); | 619 | struct sa11x0_dma_chan *c = to_sa11x0_dma_chan(chan); |
| 620 | struct sa11x0_dma_desc *txd; | 620 | struct sa11x0_dma_desc *txd; |
diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 434ad31174f2..3eed8b35b0f1 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c | |||
| @@ -489,7 +489,7 @@ err_dir: | |||
| 489 | static struct dma_async_tx_descriptor * | 489 | static struct dma_async_tx_descriptor * |
| 490 | sirfsoc_dma_prep_cyclic(struct dma_chan *chan, dma_addr_t addr, | 490 | sirfsoc_dma_prep_cyclic(struct dma_chan *chan, dma_addr_t addr, |
| 491 | size_t buf_len, size_t period_len, | 491 | size_t buf_len, size_t period_len, |
| 492 | enum dma_transfer_direction direction, void *context) | 492 | enum dma_transfer_direction direction, unsigned long flags, void *context) |
| 493 | { | 493 | { |
| 494 | struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); | 494 | struct sirfsoc_dma_chan *schan = dma_chan_to_sirfsoc_dma_chan(chan); |
| 495 | struct sirfsoc_dma_desc *sdesc = NULL; | 495 | struct sirfsoc_dma_desc *sdesc = NULL; |
diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 000d309602b2..eee8d9b9a20b 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c | |||
| @@ -2347,7 +2347,8 @@ static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan, | |||
| 2347 | static struct dma_async_tx_descriptor * | 2347 | static struct dma_async_tx_descriptor * |
| 2348 | dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, | 2348 | dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, |
| 2349 | size_t buf_len, size_t period_len, | 2349 | size_t buf_len, size_t period_len, |
| 2350 | enum dma_transfer_direction direction, void *context) | 2350 | enum dma_transfer_direction direction, unsigned long flags, |
| 2351 | void *context) | ||
| 2351 | { | 2352 | { |
| 2352 | unsigned int periods = buf_len / period_len; | 2353 | unsigned int periods = buf_len / period_len; |
| 2353 | struct dma_async_tx_descriptor *txd; | 2354 | struct dma_async_tx_descriptor *txd; |
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 4708467e4d83..45fbeed1c1a5 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c | |||
| @@ -990,7 +990,7 @@ static struct dma_async_tx_descriptor *tegra_dma_prep_slave_sg( | |||
| 990 | struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( | 990 | struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( |
| 991 | struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_len, | 991 | struct dma_chan *dc, dma_addr_t buf_addr, size_t buf_len, |
| 992 | size_t period_len, enum dma_transfer_direction direction, | 992 | size_t period_len, enum dma_transfer_direction direction, |
| 993 | void *context) | 993 | unsigned long flags, void *context) |
| 994 | { | 994 | { |
| 995 | struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); | 995 | struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); |
| 996 | struct tegra_dma_desc *dma_desc = NULL; | 996 | struct tegra_dma_desc *dma_desc = NULL; |
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 9c02a4508b25..d3201e438d16 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h | |||
| @@ -591,7 +591,7 @@ struct dma_device { | |||
| 591 | struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( | 591 | struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)( |
| 592 | struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, | 592 | struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, |
| 593 | size_t period_len, enum dma_transfer_direction direction, | 593 | size_t period_len, enum dma_transfer_direction direction, |
| 594 | void *context); | 594 | unsigned long flags, void *context); |
| 595 | struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)( | 595 | struct dma_async_tx_descriptor *(*device_prep_interleaved_dma)( |
| 596 | struct dma_chan *chan, struct dma_interleaved_template *xt, | 596 | struct dma_chan *chan, struct dma_interleaved_template *xt, |
| 597 | unsigned long flags); | 597 | unsigned long flags); |
| @@ -653,10 +653,11 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_rio_sg( | |||
| 653 | 653 | ||
| 654 | static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic( | 654 | static inline struct dma_async_tx_descriptor *dmaengine_prep_dma_cyclic( |
| 655 | struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, | 655 | struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, |
| 656 | size_t period_len, enum dma_transfer_direction dir) | 656 | size_t period_len, enum dma_transfer_direction dir, |
| 657 | unsigned long flags) | ||
| 657 | { | 658 | { |
| 658 | return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len, | 659 | return chan->device->device_prep_dma_cyclic(chan, buf_addr, buf_len, |
| 659 | period_len, dir, NULL); | 660 | period_len, dir, flags, NULL); |
| 660 | } | 661 | } |
| 661 | 662 | ||
| 662 | static inline int dmaengine_terminate_all(struct dma_chan *chan) | 663 | static inline int dmaengine_terminate_all(struct dma_chan *chan) |
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h index 1faa58f9b85e..9a5e28462324 100644 --- a/include/linux/i2c/twl.h +++ b/include/linux/i2c/twl.h | |||
| @@ -664,7 +664,7 @@ struct twl4030_codec_data { | |||
| 664 | unsigned int check_defaults:1; | 664 | unsigned int check_defaults:1; |
| 665 | unsigned int reset_registers:1; | 665 | unsigned int reset_registers:1; |
| 666 | unsigned int hs_extmute:1; | 666 | unsigned int hs_extmute:1; |
| 667 | void (*set_hs_extmute)(int mute); | 667 | int hs_extmute_gpio; |
| 668 | }; | 668 | }; |
| 669 | 669 | ||
| 670 | struct twl4030_vibra_data { | 670 | struct twl4030_vibra_data { |
diff --git a/include/linux/mfd/wm8994/pdata.h b/include/linux/mfd/wm8994/pdata.h index f0361c031927..fc87be4fdc25 100644 --- a/include/linux/mfd/wm8994/pdata.h +++ b/include/linux/mfd/wm8994/pdata.h | |||
| @@ -164,6 +164,10 @@ struct wm8994_pdata { | |||
| 164 | int num_micd_rates; | 164 | int num_micd_rates; |
| 165 | struct wm8958_micd_rate *micd_rates; | 165 | struct wm8958_micd_rate *micd_rates; |
| 166 | 166 | ||
| 167 | /* Power up delays to add after microphone bias power up (ms) */ | ||
| 168 | int micb1_delay; | ||
| 169 | int micb2_delay; | ||
| 170 | |||
| 167 | /* LINEOUT can be differential or single ended */ | 171 | /* LINEOUT can be differential or single ended */ |
| 168 | unsigned int lineout1_diff:1; | 172 | unsigned int lineout1_diff:1; |
| 169 | unsigned int lineout2_diff:1; | 173 | unsigned int lineout2_diff:1; |
diff --git a/include/linux/platform_data/asoc-mx27vis.h b/include/linux/platform_data/asoc-mx27vis.h new file mode 100644 index 000000000000..409adcd04d04 --- /dev/null +++ b/include/linux/platform_data/asoc-mx27vis.h | |||
| @@ -0,0 +1,11 @@ | |||
| 1 | #ifndef __PLATFORM_DATA_ASOC_MX27VIS_H | ||
| 2 | #define __PLATFORM_DATA_ASOC_MX27VIS_H | ||
| 3 | |||
| 4 | struct snd_mx27vis_platform_data { | ||
| 5 | int amp_gain0_gpio; | ||
| 6 | int amp_gain1_gpio; | ||
| 7 | int amp_mutel_gpio; | ||
| 8 | int amp_muter_gpio; | ||
| 9 | }; | ||
| 10 | |||
| 11 | #endif /* __PLATFORM_DATA_ASOC_MX27VIS_H */ | ||
diff --git a/include/linux/platform_data/asoc-ti-mcbsp.h b/include/linux/platform_data/asoc-ti-mcbsp.h index 18814127809a..c78d90b28b19 100644 --- a/include/linux/platform_data/asoc-ti-mcbsp.h +++ b/include/linux/platform_data/asoc-ti-mcbsp.h | |||
| @@ -47,8 +47,6 @@ struct omap_mcbsp_platform_data { | |||
| 47 | bool has_wakeup; /* Wakeup capability */ | 47 | bool has_wakeup; /* Wakeup capability */ |
| 48 | bool has_ccr; /* Transceiver has configuration control registers */ | 48 | bool has_ccr; /* Transceiver has configuration control registers */ |
| 49 | int (*enable_st_clock)(unsigned int, bool); | 49 | int (*enable_st_clock)(unsigned int, bool); |
| 50 | int (*set_clk_src)(struct device *dev, struct clk *clk, const char *src); | ||
| 51 | int (*mux_signal)(struct device *dev, const char *signal, const char *src); | ||
| 52 | }; | 50 | }; |
| 53 | 51 | ||
| 54 | /** | 52 | /** |
diff --git a/arch/arm/mach-davinci/include/mach/asp.h b/include/linux/platform_data/davinci_asp.h index 9aa240909a2c..d0c5825876f8 100644 --- a/arch/arm/mach-davinci/include/mach/asp.h +++ b/include/linux/platform_data/davinci_asp.h | |||
| @@ -1,59 +1,26 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * <mach/asp.h> - DaVinci Audio Serial Port support | 2 | * TI DaVinci Audio Serial Port support |
| 3 | * | ||
| 4 | * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License as | ||
| 8 | * published by the Free Software Foundation version 2. | ||
| 9 | * | ||
| 10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
| 11 | * kind, whether express or implied; without even the implied warranty | ||
| 12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 3 | */ | 14 | */ |
| 4 | #ifndef __ASM_ARCH_DAVINCI_ASP_H | ||
| 5 | #define __ASM_ARCH_DAVINCI_ASP_H | ||
| 6 | 15 | ||
| 7 | #include <mach/irqs.h> | 16 | #ifndef __DAVINCI_ASP_H |
| 8 | #include <mach/edma.h> | 17 | #define __DAVINCI_ASP_H |
| 9 | |||
| 10 | /* Bases of dm644x and dm355 register banks */ | ||
| 11 | #define DAVINCI_ASP0_BASE 0x01E02000 | ||
| 12 | #define DAVINCI_ASP1_BASE 0x01E04000 | ||
| 13 | |||
| 14 | /* Bases of dm365 register banks */ | ||
| 15 | #define DAVINCI_DM365_ASP0_BASE 0x01D02000 | ||
| 16 | |||
| 17 | /* Bases of dm646x register banks */ | ||
| 18 | #define DAVINCI_DM646X_MCASP0_REG_BASE 0x01D01000 | ||
| 19 | #define DAVINCI_DM646X_MCASP1_REG_BASE 0x01D01800 | ||
| 20 | |||
| 21 | /* Bases of da850/da830 McASP0 register banks */ | ||
| 22 | #define DAVINCI_DA8XX_MCASP0_REG_BASE 0x01D00000 | ||
| 23 | |||
| 24 | /* Bases of da830 McASP1 register banks */ | ||
| 25 | #define DAVINCI_DA830_MCASP1_REG_BASE 0x01D04000 | ||
| 26 | |||
| 27 | /* EDMA channels of dm644x and dm355 */ | ||
| 28 | #define DAVINCI_DMA_ASP0_TX 2 | ||
| 29 | #define DAVINCI_DMA_ASP0_RX 3 | ||
| 30 | #define DAVINCI_DMA_ASP1_TX 8 | ||
| 31 | #define DAVINCI_DMA_ASP1_RX 9 | ||
| 32 | |||
| 33 | /* EDMA channels of dm646x */ | ||
| 34 | #define DAVINCI_DM646X_DMA_MCASP0_AXEVT0 6 | ||
| 35 | #define DAVINCI_DM646X_DMA_MCASP0_AREVT0 9 | ||
| 36 | #define DAVINCI_DM646X_DMA_MCASP1_AXEVT1 12 | ||
| 37 | |||
| 38 | /* EDMA channels of da850/da830 McASP0 */ | ||
| 39 | #define DAVINCI_DA8XX_DMA_MCASP0_AREVT 0 | ||
| 40 | #define DAVINCI_DA8XX_DMA_MCASP0_AXEVT 1 | ||
| 41 | |||
| 42 | /* EDMA channels of da830 McASP1 */ | ||
| 43 | #define DAVINCI_DA830_DMA_MCASP1_AREVT 2 | ||
| 44 | #define DAVINCI_DA830_DMA_MCASP1_AXEVT 3 | ||
| 45 | |||
| 46 | /* Interrupts */ | ||
| 47 | #define DAVINCI_ASP0_RX_INT IRQ_MBRINT | ||
| 48 | #define DAVINCI_ASP0_TX_INT IRQ_MBXINT | ||
| 49 | #define DAVINCI_ASP1_RX_INT IRQ_MBRINT | ||
| 50 | #define DAVINCI_ASP1_TX_INT IRQ_MBXINT | ||
| 51 | 18 | ||
| 52 | struct snd_platform_data { | 19 | struct snd_platform_data { |
| 53 | u32 tx_dma_offset; | 20 | u32 tx_dma_offset; |
| 54 | u32 rx_dma_offset; | 21 | u32 rx_dma_offset; |
| 55 | enum dma_event_q asp_chan_q; /* event queue number for ASP channel */ | 22 | int asp_chan_q; /* event queue number for ASP channel */ |
| 56 | enum dma_event_q ram_chan_q; /* event queue number for RAM channel */ | 23 | int ram_chan_q; /* event queue number for RAM channel */ |
| 57 | unsigned int codec_fmt; | 24 | unsigned int codec_fmt; |
| 58 | /* | 25 | /* |
| 59 | * Allowing this is more efficient and eliminates left and right swaps | 26 | * Allowing this is more efficient and eliminates left and right swaps |
| @@ -70,7 +37,7 @@ struct snd_platform_data { | |||
| 70 | * and MCBSP_CLKS. | 37 | * and MCBSP_CLKS. |
| 71 | * Depending on different hardware connections it is possible | 38 | * Depending on different hardware connections it is possible |
| 72 | * to use this setting to change the behaviour of McBSP | 39 | * to use this setting to change the behaviour of McBSP |
| 73 | * driver. The dm365_clk_input_pin enum is available for dm365 | 40 | * driver. |
| 74 | */ | 41 | */ |
| 75 | int clk_input_pin; | 42 | int clk_input_pin; |
| 76 | 43 | ||
| @@ -120,10 +87,11 @@ struct snd_platform_data { | |||
| 120 | enum { | 87 | enum { |
| 121 | MCASP_VERSION_1 = 0, /* DM646x */ | 88 | MCASP_VERSION_1 = 0, /* DM646x */ |
| 122 | MCASP_VERSION_2, /* DA8xx/OMAPL1x */ | 89 | MCASP_VERSION_2, /* DA8xx/OMAPL1x */ |
| 90 | MCASP_VERSION_3, /* TI81xx/AM33xx */ | ||
| 123 | }; | 91 | }; |
| 124 | 92 | ||
| 125 | enum dm365_clk_input_pin { | 93 | enum mcbsp_clk_input_pin { |
| 126 | MCBSP_CLKR = 0, /* DM365 */ | 94 | MCBSP_CLKR = 0, /* as in DM365 */ |
| 127 | MCBSP_CLKS, | 95 | MCBSP_CLKS, |
| 128 | }; | 96 | }; |
| 129 | 97 | ||
| @@ -134,4 +102,4 @@ enum dm365_clk_input_pin { | |||
| 134 | #define DAVINCI_MCASP_IIS_MODE 0 | 102 | #define DAVINCI_MCASP_IIS_MODE 0 |
| 135 | #define DAVINCI_MCASP_DIT_MODE 1 | 103 | #define DAVINCI_MCASP_DIT_MODE 1 |
| 136 | 104 | ||
| 137 | #endif /* __ASM_ARCH_DAVINCI_ASP_H */ | 105 | #endif |
diff --git a/include/linux/platform_data/omap-twl4030.h b/include/linux/platform_data/omap-twl4030.h new file mode 100644 index 000000000000..c7bef788daab --- /dev/null +++ b/include/linux/platform_data/omap-twl4030.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | /** | ||
| 2 | * omap-twl4030.h - ASoC machine driver for TI SoC based boards with twl4030 | ||
| 3 | * codec, header. | ||
| 4 | * | ||
| 5 | * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com | ||
| 6 | * All rights reserved. | ||
| 7 | * | ||
| 8 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License | ||
| 12 | * version 2 as published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, but | ||
| 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 17 | * General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
| 22 | * 02110-1301 USA | ||
| 23 | */ | ||
| 24 | |||
| 25 | #ifndef _OMAP_TWL4030_H_ | ||
| 26 | #define _OMAP_TWL4030_H_ | ||
| 27 | |||
| 28 | struct omap_tw4030_pdata { | ||
| 29 | const char *card_name; | ||
| 30 | }; | ||
| 31 | |||
| 32 | #endif /* _OMAP_TWL4030_H_ */ | ||
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index fdeb8dceec0f..d315a08d6c6d 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h | |||
| @@ -422,6 +422,7 @@ | |||
| 422 | */ | 422 | */ |
| 423 | 423 | ||
| 424 | struct snd_ac97; | 424 | struct snd_ac97; |
| 425 | struct snd_pcm_chmap; | ||
| 425 | 426 | ||
| 426 | struct snd_ac97_build_ops { | 427 | struct snd_ac97_build_ops { |
| 427 | int (*build_3d) (struct snd_ac97 *ac97); | 428 | int (*build_3d) (struct snd_ac97 *ac97); |
| @@ -528,6 +529,8 @@ struct snd_ac97 { | |||
| 528 | struct delayed_work power_work; | 529 | struct delayed_work power_work; |
| 529 | #endif | 530 | #endif |
| 530 | struct device dev; | 531 | struct device dev; |
| 532 | |||
| 533 | struct snd_pcm_chmap *chmaps[2]; /* channel-maps (optional) */ | ||
| 531 | }; | 534 | }; |
| 532 | 535 | ||
| 533 | #define to_ac97_t(d) container_of(d, struct snd_ac97, dev) | 536 | #define to_ac97_t(d) container_of(d, struct snd_ac97, dev) |
diff --git a/include/sound/ad1816a.h b/include/sound/ad1816a.h index a7d8dc782e7c..abdf609c5918 100644 --- a/include/sound/ad1816a.h +++ b/include/sound/ad1816a.h | |||
| @@ -147,6 +147,9 @@ struct snd_ad1816a { | |||
| 147 | unsigned int c_dma_size; | 147 | unsigned int c_dma_size; |
| 148 | 148 | ||
| 149 | struct snd_timer *timer; | 149 | struct snd_timer *timer; |
| 150 | #ifdef CONFIG_PM | ||
| 151 | unsigned short image[48]; | ||
| 152 | #endif | ||
| 150 | }; | 153 | }; |
| 151 | 154 | ||
| 152 | 155 | ||
| @@ -165,11 +168,15 @@ struct snd_ad1816a { | |||
| 165 | 168 | ||
| 166 | extern int snd_ad1816a_create(struct snd_card *card, unsigned long port, | 169 | extern int snd_ad1816a_create(struct snd_card *card, unsigned long port, |
| 167 | int irq, int dma1, int dma2, | 170 | int irq, int dma1, int dma2, |
| 168 | struct snd_ad1816a **chip); | 171 | struct snd_ad1816a *chip); |
| 169 | 172 | ||
| 170 | extern int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm); | 173 | extern int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm); |
| 171 | extern int snd_ad1816a_mixer(struct snd_ad1816a *chip); | 174 | extern int snd_ad1816a_mixer(struct snd_ad1816a *chip); |
| 172 | extern int snd_ad1816a_timer(struct snd_ad1816a *chip, int device, | 175 | extern int snd_ad1816a_timer(struct snd_ad1816a *chip, int device, |
| 173 | struct snd_timer **rtimer); | 176 | struct snd_timer **rtimer); |
| 177 | #ifdef CONFIG_PM | ||
| 178 | extern void snd_ad1816a_suspend(struct snd_ad1816a *chip); | ||
| 179 | extern void snd_ad1816a_resume(struct snd_ad1816a *chip); | ||
| 180 | #endif | ||
| 174 | 181 | ||
| 175 | #endif /* __SOUND_AD1816A_H */ | 182 | #endif /* __SOUND_AD1816A_H */ |
diff --git a/include/sound/asound.h b/include/sound/asound.h index 0876a1e76aef..dfe7d441748c 100644 --- a/include/sound/asound.h +++ b/include/sound/asound.h | |||
| @@ -472,6 +472,45 @@ enum { | |||
| 472 | SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, | 472 | SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC, |
| 473 | }; | 473 | }; |
| 474 | 474 | ||
| 475 | /* channel positions */ | ||
| 476 | enum { | ||
| 477 | SNDRV_CHMAP_UNKNOWN = 0, | ||
| 478 | SNDRV_CHMAP_NA, /* N/A, silent */ | ||
| 479 | SNDRV_CHMAP_MONO, /* mono stream */ | ||
| 480 | /* this follows the alsa-lib mixer channel value + 3 */ | ||
| 481 | SNDRV_CHMAP_FL, /* front left */ | ||
| 482 | SNDRV_CHMAP_FR, /* front right */ | ||
| 483 | SNDRV_CHMAP_RL, /* rear left */ | ||
| 484 | SNDRV_CHMAP_RR, /* rear right */ | ||
| 485 | SNDRV_CHMAP_FC, /* front center */ | ||
| 486 | SNDRV_CHMAP_LFE, /* LFE */ | ||
| 487 | SNDRV_CHMAP_SL, /* side left */ | ||
| 488 | SNDRV_CHMAP_SR, /* side right */ | ||
| 489 | SNDRV_CHMAP_RC, /* rear center */ | ||
| 490 | /* new definitions */ | ||
| 491 | SNDRV_CHMAP_FLC, /* front left center */ | ||
| 492 | SNDRV_CHMAP_FRC, /* front right center */ | ||
| 493 | SNDRV_CHMAP_RLC, /* rear left center */ | ||
| 494 | SNDRV_CHMAP_RRC, /* rear right center */ | ||
| 495 | SNDRV_CHMAP_FLW, /* front left wide */ | ||
| 496 | SNDRV_CHMAP_FRW, /* front right wide */ | ||
| 497 | SNDRV_CHMAP_FLH, /* front left high */ | ||
| 498 | SNDRV_CHMAP_FCH, /* front center high */ | ||
| 499 | SNDRV_CHMAP_FRH, /* front right high */ | ||
| 500 | SNDRV_CHMAP_TC, /* top center */ | ||
| 501 | SNDRV_CHMAP_TFL, /* top front left */ | ||
| 502 | SNDRV_CHMAP_TFR, /* top front right */ | ||
| 503 | SNDRV_CHMAP_TFC, /* top front center */ | ||
| 504 | SNDRV_CHMAP_TRL, /* top rear left */ | ||
| 505 | SNDRV_CHMAP_TRR, /* top rear right */ | ||
| 506 | SNDRV_CHMAP_TRC, /* top rear center */ | ||
| 507 | SNDRV_CHMAP_LAST = SNDRV_CHMAP_TRC, | ||
| 508 | }; | ||
| 509 | |||
| 510 | #define SNDRV_CHMAP_POSITION_MASK 0xffff | ||
| 511 | #define SNDRV_CHMAP_PHASE_INVERSE (0x01 << 16) | ||
| 512 | #define SNDRV_CHMAP_DRIVER_SPEC (0x02 << 16) | ||
| 513 | |||
| 475 | #define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int) | 514 | #define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int) |
| 476 | #define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info) | 515 | #define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info) |
| 477 | #define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int) | 516 | #define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int) |
diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index 48f2a1ff2bbc..f2912abacdf3 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h | |||
| @@ -61,6 +61,7 @@ struct snd_compr_runtime { | |||
| 61 | u64 total_bytes_available; | 61 | u64 total_bytes_available; |
| 62 | u64 total_bytes_transferred; | 62 | u64 total_bytes_transferred; |
| 63 | wait_queue_head_t sleep; | 63 | wait_queue_head_t sleep; |
| 64 | void *private_data; | ||
| 64 | }; | 65 | }; |
| 65 | 66 | ||
| 66 | /** | 67 | /** |
diff --git a/include/sound/compress_params.h b/include/sound/compress_params.h index da4a456de032..602dc6c45d1a 100644 --- a/include/sound/compress_params.h +++ b/include/sound/compress_params.h | |||
| @@ -72,6 +72,7 @@ | |||
| 72 | #define SND_AUDIOCODEC_IEC61937 ((__u32) 0x0000000B) | 72 | #define SND_AUDIOCODEC_IEC61937 ((__u32) 0x0000000B) |
| 73 | #define SND_AUDIOCODEC_G723_1 ((__u32) 0x0000000C) | 73 | #define SND_AUDIOCODEC_G723_1 ((__u32) 0x0000000C) |
| 74 | #define SND_AUDIOCODEC_G729 ((__u32) 0x0000000D) | 74 | #define SND_AUDIOCODEC_G729 ((__u32) 0x0000000D) |
| 75 | #define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_G729 | ||
| 75 | 76 | ||
| 76 | /* | 77 | /* |
| 77 | * Profile and modes are listed with bit masks. This allows for a | 78 | * Profile and modes are listed with bit masks. This allows for a |
diff --git a/include/sound/da9055.h b/include/sound/da9055.h new file mode 100644 index 000000000000..cf1241b64d89 --- /dev/null +++ b/include/sound/da9055.h | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | /* | ||
| 2 | * DA9055 ALSA Soc codec driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2012 Dialog Semiconductor | ||
| 5 | * | ||
| 6 | * Tested on (Samsung SMDK6410 board + DA9055 EVB) using I2S and I2C | ||
| 7 | * Written by David Chen <david.chen@diasemi.com> and | ||
| 8 | * Ashish Chavan <ashish.chavan@kpitcummins.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms of the GNU General Public License as published by the | ||
| 12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 13 | * option) any later version. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #ifndef __SOUND_DA9055_H__ | ||
| 17 | #define __SOUND_DA9055_H__ | ||
| 18 | |||
| 19 | enum da9055_micbias_voltage { | ||
| 20 | DA9055_MICBIAS_1_6V = 0, | ||
| 21 | DA9055_MICBIAS_1_8V = 1, | ||
| 22 | DA9055_MICBIAS_2_1V = 2, | ||
| 23 | DA9055_MICBIAS_2_2V = 3, | ||
| 24 | }; | ||
| 25 | |||
| 26 | struct da9055_platform_data { | ||
| 27 | /* Selects which of the two MicBias pins acts as the bias source */ | ||
| 28 | bool micbias_source; | ||
| 29 | /* Selects the micbias voltage */ | ||
| 30 | enum da9055_micbias_voltage micbias; | ||
| 31 | }; | ||
| 32 | |||
| 33 | #endif | ||
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 4f865df42f0f..1a33f48ebe78 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h | |||
| @@ -1788,7 +1788,7 @@ struct snd_emu10k1 { | |||
| 1788 | unsigned int efx_voices_mask[2]; | 1788 | unsigned int efx_voices_mask[2]; |
| 1789 | unsigned int next_free_voice; | 1789 | unsigned int next_free_voice; |
| 1790 | 1790 | ||
| 1791 | #ifdef CONFIG_PM | 1791 | #ifdef CONFIG_PM_SLEEP |
| 1792 | unsigned int *saved_ptr; | 1792 | unsigned int *saved_ptr; |
| 1793 | unsigned int *saved_gpr; | 1793 | unsigned int *saved_gpr; |
| 1794 | unsigned int *tram_val_saved; | 1794 | unsigned int *tram_val_saved; |
| @@ -1856,7 +1856,7 @@ unsigned short snd_emu10k1_ac97_read(struct snd_ac97 *ac97, unsigned short reg); | |||
| 1856 | void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data); | 1856 | void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data); |
| 1857 | unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate); | 1857 | unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate); |
| 1858 | 1858 | ||
| 1859 | #ifdef CONFIG_PM | 1859 | #ifdef CONFIG_PM_SLEEP |
| 1860 | void snd_emu10k1_suspend_regs(struct snd_emu10k1 *emu); | 1860 | void snd_emu10k1_suspend_regs(struct snd_emu10k1 *emu); |
| 1861 | void snd_emu10k1_resume_init(struct snd_emu10k1 *emu); | 1861 | void snd_emu10k1_resume_init(struct snd_emu10k1 *emu); |
| 1862 | void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu); | 1862 | void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu); |
diff --git a/include/sound/initval.h b/include/sound/initval.h index f99a0d2ddfe7..ac62c67e6f42 100644 --- a/include/sound/initval.h +++ b/include/sound/initval.h | |||
| @@ -50,6 +50,20 @@ | |||
| 50 | #define SNDRV_DEFAULT_DMA_SIZE { [0 ... (SNDRV_CARDS-1)] = SNDRV_AUTO_DMA_SIZE } | 50 | #define SNDRV_DEFAULT_DMA_SIZE { [0 ... (SNDRV_CARDS-1)] = SNDRV_AUTO_DMA_SIZE } |
| 51 | #define SNDRV_DEFAULT_PTR SNDRV_DEFAULT_STR | 51 | #define SNDRV_DEFAULT_PTR SNDRV_DEFAULT_STR |
| 52 | 52 | ||
| 53 | #ifdef SNDRV_LEGACY_FIND_FREE_IOPORT | ||
| 54 | static long snd_legacy_find_free_ioport(long *port_table, long size) | ||
| 55 | { | ||
| 56 | while (*port_table != -1) { | ||
| 57 | if (request_region(*port_table, size, "ALSA test")) { | ||
| 58 | release_region(*port_table, size); | ||
| 59 | return *port_table; | ||
| 60 | } | ||
| 61 | port_table++; | ||
| 62 | } | ||
| 63 | return -1; | ||
| 64 | } | ||
| 65 | #endif | ||
| 66 | |||
| 53 | #ifdef SNDRV_LEGACY_FIND_FREE_IRQ | 67 | #ifdef SNDRV_LEGACY_FIND_FREE_IRQ |
| 54 | #include <linux/interrupt.h> | 68 | #include <linux/interrupt.h> |
| 55 | 69 | ||
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h index c42506212649..844af65af626 100644 --- a/include/sound/memalloc.h +++ b/include/sound/memalloc.h | |||
| @@ -98,8 +98,10 @@ static inline unsigned int snd_sgbuf_aligned_pages(size_t size) | |||
| 98 | /* | 98 | /* |
| 99 | * return the physical address at the corresponding offset | 99 | * return the physical address at the corresponding offset |
| 100 | */ | 100 | */ |
| 101 | static inline dma_addr_t snd_sgbuf_get_addr(struct snd_sg_buf *sgbuf, size_t offset) | 101 | static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab, |
| 102 | size_t offset) | ||
| 102 | { | 103 | { |
| 104 | struct snd_sg_buf *sgbuf = dmab->private_data; | ||
| 103 | dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr; | 105 | dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr; |
| 104 | addr &= PAGE_MASK; | 106 | addr &= PAGE_MASK; |
| 105 | return addr + offset % PAGE_SIZE; | 107 | return addr + offset % PAGE_SIZE; |
| @@ -108,10 +110,31 @@ static inline dma_addr_t snd_sgbuf_get_addr(struct snd_sg_buf *sgbuf, size_t off | |||
| 108 | /* | 110 | /* |
| 109 | * return the virtual address at the corresponding offset | 111 | * return the virtual address at the corresponding offset |
| 110 | */ | 112 | */ |
| 111 | static inline void *snd_sgbuf_get_ptr(struct snd_sg_buf *sgbuf, size_t offset) | 113 | static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab, |
| 114 | size_t offset) | ||
| 112 | { | 115 | { |
| 116 | struct snd_sg_buf *sgbuf = dmab->private_data; | ||
| 113 | return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE; | 117 | return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE; |
| 114 | } | 118 | } |
| 119 | |||
| 120 | unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab, | ||
| 121 | unsigned int ofs, unsigned int size); | ||
| 122 | #else | ||
| 123 | /* non-SG versions */ | ||
| 124 | static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab, | ||
| 125 | size_t offset) | ||
| 126 | { | ||
| 127 | return dmab->addr + offset; | ||
| 128 | } | ||
| 129 | |||
| 130 | static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab, | ||
| 131 | size_t offset) | ||
| 132 | { | ||
| 133 | return dmab->area + offset; | ||
| 134 | } | ||
| 135 | |||
| 136 | #define snd_sgbuf_get_chunk_size(dmab, ofs, size) (size) | ||
| 137 | |||
| 115 | #endif /* CONFIG_SND_DMA_SGBUF */ | 138 | #endif /* CONFIG_SND_DMA_SGBUF */ |
| 116 | 139 | ||
| 117 | /* allocate/release a buffer */ | 140 | /* allocate/release a buffer */ |
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index d0711bc8c914..6268a4192d5c 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h | |||
| @@ -437,6 +437,7 @@ struct snd_pcm_str { | |||
| 437 | struct snd_info_entry *proc_xrun_debug_entry; | 437 | struct snd_info_entry *proc_xrun_debug_entry; |
| 438 | #endif | 438 | #endif |
| 439 | #endif | 439 | #endif |
| 440 | struct snd_kcontrol *chmap_kctl; /* channel-mapping controls */ | ||
| 440 | }; | 441 | }; |
| 441 | 442 | ||
| 442 | struct snd_pcm { | 443 | struct snd_pcm { |
| @@ -982,53 +983,42 @@ static int snd_pcm_lib_alloc_vmalloc_32_buffer | |||
| 982 | _snd_pcm_lib_alloc_vmalloc_buffer \ | 983 | _snd_pcm_lib_alloc_vmalloc_buffer \ |
| 983 | (subs, size, GFP_KERNEL | GFP_DMA32 | __GFP_ZERO) | 984 | (subs, size, GFP_KERNEL | GFP_DMA32 | __GFP_ZERO) |
| 984 | 985 | ||
| 986 | #define snd_pcm_get_dma_buf(substream) ((substream)->runtime->dma_buffer_p) | ||
| 987 | |||
| 985 | #ifdef CONFIG_SND_DMA_SGBUF | 988 | #ifdef CONFIG_SND_DMA_SGBUF |
| 986 | /* | 989 | /* |
| 987 | * SG-buffer handling | 990 | * SG-buffer handling |
| 988 | */ | 991 | */ |
| 989 | #define snd_pcm_substream_sgbuf(substream) \ | 992 | #define snd_pcm_substream_sgbuf(substream) \ |
| 990 | ((substream)->runtime->dma_buffer_p->private_data) | 993 | snd_pcm_get_dma_buf(substream)->private_data |
| 991 | |||
| 992 | static inline dma_addr_t | ||
| 993 | snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs) | ||
| 994 | { | ||
| 995 | struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream); | ||
| 996 | return snd_sgbuf_get_addr(sg, ofs); | ||
| 997 | } | ||
| 998 | |||
| 999 | static inline void * | ||
| 1000 | snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs) | ||
| 1001 | { | ||
| 1002 | struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream); | ||
| 1003 | return snd_sgbuf_get_ptr(sg, ofs); | ||
| 1004 | } | ||
| 1005 | 994 | ||
| 1006 | struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, | 995 | struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, |
| 1007 | unsigned long offset); | 996 | unsigned long offset); |
| 1008 | unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, | ||
| 1009 | unsigned int ofs, unsigned int size); | ||
| 1010 | |||
| 1011 | #else /* !SND_DMA_SGBUF */ | 997 | #else /* !SND_DMA_SGBUF */ |
| 1012 | /* | 998 | /* |
| 1013 | * fake using a continuous buffer | 999 | * fake using a continuous buffer |
| 1014 | */ | 1000 | */ |
| 1001 | #define snd_pcm_sgbuf_ops_page NULL | ||
| 1002 | #endif /* SND_DMA_SGBUF */ | ||
| 1003 | |||
| 1015 | static inline dma_addr_t | 1004 | static inline dma_addr_t |
| 1016 | snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs) | 1005 | snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs) |
| 1017 | { | 1006 | { |
| 1018 | return substream->runtime->dma_addr + ofs; | 1007 | return snd_sgbuf_get_addr(snd_pcm_get_dma_buf(substream), ofs); |
| 1019 | } | 1008 | } |
| 1020 | 1009 | ||
| 1021 | static inline void * | 1010 | static inline void * |
| 1022 | snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs) | 1011 | snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs) |
| 1023 | { | 1012 | { |
| 1024 | return substream->runtime->dma_area + ofs; | 1013 | return snd_sgbuf_get_ptr(snd_pcm_get_dma_buf(substream), ofs); |
| 1025 | } | 1014 | } |
| 1026 | 1015 | ||
| 1027 | #define snd_pcm_sgbuf_ops_page NULL | 1016 | static inline unsigned int |
| 1028 | 1017 | snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, | |
| 1029 | #define snd_pcm_sgbuf_get_chunk_size(subs, ofs, size) (size) | 1018 | unsigned int ofs, unsigned int size) |
| 1030 | 1019 | { | |
| 1031 | #endif /* SND_DMA_SGBUF */ | 1020 | return snd_sgbuf_get_chunk_size(snd_pcm_get_dma_buf(substream), ofs, size); |
| 1021 | } | ||
| 1032 | 1022 | ||
| 1033 | /* handle mmap counter - PCM mmap callback should handle this counter properly */ | 1023 | /* handle mmap counter - PCM mmap callback should handle this counter properly */ |
| 1034 | static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) | 1024 | static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) |
| @@ -1086,4 +1076,51 @@ static inline const char *snd_pcm_stream_str(struct snd_pcm_substream *substream | |||
| 1086 | return "Capture"; | 1076 | return "Capture"; |
| 1087 | } | 1077 | } |
| 1088 | 1078 | ||
| 1079 | /* | ||
| 1080 | * PCM channel-mapping control API | ||
| 1081 | */ | ||
| 1082 | /* array element of channel maps */ | ||
| 1083 | struct snd_pcm_chmap_elem { | ||
| 1084 | unsigned char channels; | ||
| 1085 | unsigned char map[15]; | ||
| 1086 | }; | ||
| 1087 | |||
| 1088 | /* channel map information; retrieved via snd_kcontrol_chip() */ | ||
| 1089 | struct snd_pcm_chmap { | ||
| 1090 | struct snd_pcm *pcm; /* assigned PCM instance */ | ||
| 1091 | int stream; /* PLAYBACK or CAPTURE */ | ||
| 1092 | struct snd_kcontrol *kctl; | ||
| 1093 | const struct snd_pcm_chmap_elem *chmap; | ||
| 1094 | unsigned int max_channels; | ||
| 1095 | unsigned int channel_mask; /* optional: active channels bitmask */ | ||
| 1096 | void *private_data; /* optional: private data pointer */ | ||
| 1097 | }; | ||
| 1098 | |||
| 1099 | /* get the PCM substream assigned to the given chmap info */ | ||
| 1100 | static inline struct snd_pcm_substream * | ||
| 1101 | snd_pcm_chmap_substream(struct snd_pcm_chmap *info, unsigned int idx) | ||
| 1102 | { | ||
| 1103 | struct snd_pcm_substream *s; | ||
| 1104 | for (s = info->pcm->streams[info->stream].substream; s; s = s->next) | ||
| 1105 | if (s->number == idx) | ||
| 1106 | return s; | ||
| 1107 | return NULL; | ||
| 1108 | } | ||
| 1109 | |||
| 1110 | /* ALSA-standard channel maps (RL/RR prior to C/LFE) */ | ||
| 1111 | extern const struct snd_pcm_chmap_elem snd_pcm_std_chmaps[]; | ||
| 1112 | /* Other world's standard channel maps (C/LFE prior to RL/RR) */ | ||
| 1113 | extern const struct snd_pcm_chmap_elem snd_pcm_alt_chmaps[]; | ||
| 1114 | |||
| 1115 | /* bit masks to be passed to snd_pcm_chmap.channel_mask field */ | ||
| 1116 | #define SND_PCM_CHMAP_MASK_24 ((1U << 2) | (1U << 4)) | ||
| 1117 | #define SND_PCM_CHMAP_MASK_246 (SND_PCM_CHMAP_MASK_24 | (1U << 6)) | ||
| 1118 | #define SND_PCM_CHMAP_MASK_2468 (SND_PCM_CHMAP_MASK_246 | (1U << 8)) | ||
| 1119 | |||
| 1120 | int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream, | ||
| 1121 | const struct snd_pcm_chmap_elem *chmap, | ||
| 1122 | int max_channels, | ||
| 1123 | unsigned long private_value, | ||
| 1124 | struct snd_pcm_chmap **info_ret); | ||
| 1125 | |||
| 1089 | #endif /* __SOUND_PCM_H */ | 1126 | #endif /* __SOUND_PCM_H */ |
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 1f69e0af2941..628db7bca4fd 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | struct snd_pcm_substream; | 19 | struct snd_pcm_substream; |
| 20 | struct snd_soc_dapm_widget; | 20 | struct snd_soc_dapm_widget; |
| 21 | struct snd_compr_stream; | ||
| 21 | 22 | ||
| 22 | /* | 23 | /* |
| 23 | * DAI hardware audio formats. | 24 | * DAI hardware audio formats. |
| @@ -205,6 +206,8 @@ struct snd_soc_dai_driver { | |||
| 205 | int (*remove)(struct snd_soc_dai *dai); | 206 | int (*remove)(struct snd_soc_dai *dai); |
| 206 | int (*suspend)(struct snd_soc_dai *dai); | 207 | int (*suspend)(struct snd_soc_dai *dai); |
| 207 | int (*resume)(struct snd_soc_dai *dai); | 208 | int (*resume)(struct snd_soc_dai *dai); |
| 209 | /* compress dai */ | ||
| 210 | bool compress_dai; | ||
| 208 | 211 | ||
| 209 | /* ops */ | 212 | /* ops */ |
| 210 | const struct snd_soc_dai_ops *ops; | 213 | const struct snd_soc_dai_ops *ops; |
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index abe373d57adc..e1ef63d4a5c4 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
| @@ -244,10 +244,11 @@ struct device; | |||
| 244 | { .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \ | 244 | { .id = snd_soc_dapm_supply, .name = wname, .reg = wreg, \ |
| 245 | .shift = wshift, .invert = winvert, .event = wevent, \ | 245 | .shift = wshift, .invert = winvert, .event = wevent, \ |
| 246 | .event_flags = wflags} | 246 | .event_flags = wflags} |
| 247 | #define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay) \ | 247 | #define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \ |
| 248 | { .id = snd_soc_dapm_regulator_supply, .name = wname, \ | 248 | { .id = snd_soc_dapm_regulator_supply, .name = wname, \ |
| 249 | .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \ | 249 | .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \ |
| 250 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD } | 250 | .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \ |
| 251 | .invert = wflags} | ||
| 251 | 252 | ||
| 252 | 253 | ||
| 253 | /* dapm kcontrol types */ | 254 | /* dapm kcontrol types */ |
| @@ -319,6 +320,9 @@ struct device; | |||
| 319 | #define SND_SOC_DAPM_EVENT_OFF(e) \ | 320 | #define SND_SOC_DAPM_EVENT_OFF(e) \ |
| 320 | (e & (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD)) | 321 | (e & (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD)) |
| 321 | 322 | ||
| 323 | /* regulator widget flags */ | ||
| 324 | #define SND_SOC_DAPM_REGULATOR_BYPASS 0x1 /* bypass when disabled */ | ||
| 325 | |||
| 322 | struct snd_soc_dapm_widget; | 326 | struct snd_soc_dapm_widget; |
| 323 | enum snd_soc_dapm_type; | 327 | enum snd_soc_dapm_type; |
| 324 | struct snd_soc_dapm_path; | 328 | struct snd_soc_dapm_path; |
| @@ -412,6 +416,7 @@ void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec); | |||
| 412 | 416 | ||
| 413 | /* Mostly internal - should not normally be used */ | 417 | /* Mostly internal - should not normally be used */ |
| 414 | void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason); | 418 | void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason); |
| 419 | void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm); | ||
| 415 | 420 | ||
| 416 | /* dapm path query */ | 421 | /* dapm path query */ |
| 417 | int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, | 422 | int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, |
| @@ -510,7 +515,6 @@ struct snd_soc_dapm_widget { | |||
| 510 | /* dapm control */ | 515 | /* dapm control */ |
| 511 | int reg; /* negative reg = no direct dapm */ | 516 | int reg; /* negative reg = no direct dapm */ |
| 512 | unsigned char shift; /* bits to shift */ | 517 | unsigned char shift; /* bits to shift */ |
| 513 | unsigned int saved_value; /* widget saved value */ | ||
| 514 | unsigned int value; /* widget current value */ | 518 | unsigned int value; /* widget current value */ |
| 515 | unsigned int mask; /* non-shifted mask */ | 519 | unsigned int mask; /* non-shifted mask */ |
| 516 | unsigned int on_val; /* on state value */ | 520 | unsigned int on_val; /* on state value */ |
diff --git a/include/sound/soc.h b/include/sound/soc.h index e063380f63a2..91244a096c19 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
| @@ -20,8 +20,10 @@ | |||
| 20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
| 21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| 22 | #include <linux/regmap.h> | 22 | #include <linux/regmap.h> |
| 23 | #include <linux/log2.h> | ||
| 23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
| 24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
| 26 | #include <sound/compress_driver.h> | ||
| 25 | #include <sound/control.h> | 27 | #include <sound/control.h> |
| 26 | #include <sound/ac97_codec.h> | 28 | #include <sound/ac97_codec.h> |
| 27 | 29 | ||
| @@ -159,7 +161,8 @@ | |||
| 159 | .platform_max = xmax} } | 161 | .platform_max = xmax} } |
| 160 | #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \ | 162 | #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmax, xtexts) \ |
| 161 | { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ | 163 | { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ |
| 162 | .max = xmax, .texts = xtexts } | 164 | .max = xmax, .texts = xtexts, \ |
| 165 | .mask = xmax ? roundup_pow_of_two(xmax) - 1 : 0} | ||
| 163 | #define SOC_ENUM_SINGLE(xreg, xshift, xmax, xtexts) \ | 166 | #define SOC_ENUM_SINGLE(xreg, xshift, xmax, xtexts) \ |
| 164 | SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts) | 167 | SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmax, xtexts) |
| 165 | #define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \ | 168 | #define SOC_ENUM_SINGLE_EXT(xmax, xtexts) \ |
| @@ -399,6 +402,7 @@ int snd_soc_platform_read(struct snd_soc_platform *platform, | |||
| 399 | int snd_soc_platform_write(struct snd_soc_platform *platform, | 402 | int snd_soc_platform_write(struct snd_soc_platform *platform, |
| 400 | unsigned int reg, unsigned int val); | 403 | unsigned int reg, unsigned int val); |
| 401 | int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); | 404 | int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); |
| 405 | int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num); | ||
| 402 | 406 | ||
| 403 | struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card, | 407 | struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card, |
| 404 | const char *dai_link, int stream); | 408 | const char *dai_link, int stream); |
| @@ -632,6 +636,13 @@ struct snd_soc_ops { | |||
| 632 | int (*trigger)(struct snd_pcm_substream *, int); | 636 | int (*trigger)(struct snd_pcm_substream *, int); |
| 633 | }; | 637 | }; |
| 634 | 638 | ||
| 639 | struct snd_soc_compr_ops { | ||
| 640 | int (*startup)(struct snd_compr_stream *); | ||
| 641 | void (*shutdown)(struct snd_compr_stream *); | ||
| 642 | int (*set_params)(struct snd_compr_stream *); | ||
| 643 | int (*trigger)(struct snd_compr_stream *); | ||
| 644 | }; | ||
| 645 | |||
| 635 | /* SoC cache ops */ | 646 | /* SoC cache ops */ |
| 636 | struct snd_soc_cache_ops { | 647 | struct snd_soc_cache_ops { |
| 637 | const char *name; | 648 | const char *name; |
| @@ -787,9 +798,12 @@ struct snd_soc_platform_driver { | |||
| 787 | snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *, | 798 | snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *, |
| 788 | struct snd_soc_dai *); | 799 | struct snd_soc_dai *); |
| 789 | 800 | ||
| 790 | /* platform stream ops */ | 801 | /* platform stream pcm ops */ |
| 791 | struct snd_pcm_ops *ops; | 802 | struct snd_pcm_ops *ops; |
| 792 | 803 | ||
| 804 | /* platform stream compress ops */ | ||
| 805 | struct snd_compr_ops *compr_ops; | ||
| 806 | |||
| 793 | /* platform stream completion event */ | 807 | /* platform stream completion event */ |
| 794 | int (*stream_event)(struct snd_soc_dapm_context *dapm, int event); | 808 | int (*stream_event)(struct snd_soc_dapm_context *dapm, int event); |
| 795 | 809 | ||
| @@ -891,6 +905,7 @@ struct snd_soc_dai_link { | |||
| 891 | 905 | ||
| 892 | /* machine stream operations */ | 906 | /* machine stream operations */ |
| 893 | struct snd_soc_ops *ops; | 907 | struct snd_soc_ops *ops; |
| 908 | struct snd_soc_compr_ops *compr_ops; | ||
| 894 | }; | 909 | }; |
| 895 | 910 | ||
| 896 | struct snd_soc_codec_conf { | 911 | struct snd_soc_codec_conf { |
| @@ -1027,6 +1042,7 @@ struct snd_soc_pcm_runtime { | |||
| 1027 | 1042 | ||
| 1028 | /* runtime devices */ | 1043 | /* runtime devices */ |
| 1029 | struct snd_pcm *pcm; | 1044 | struct snd_pcm *pcm; |
| 1045 | struct snd_compr *compr; | ||
| 1030 | struct snd_soc_codec *codec; | 1046 | struct snd_soc_codec *codec; |
| 1031 | struct snd_soc_platform *platform; | 1047 | struct snd_soc_platform *platform; |
| 1032 | struct snd_soc_dai *codec_dai; | 1048 | struct snd_soc_dai *codec_dai; |
diff --git a/arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h b/include/sound/tegra_wm8903.h index 9d293344a7ff..57b202ee97c3 100644 --- a/arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h +++ b/include/sound/tegra_wm8903.h | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/arm/mach-tegra/include/mach/tegra_wm8903_pdata.h | ||
| 3 | * | ||
| 4 | * Copyright 2011 NVIDIA, Inc. | 2 | * Copyright 2011 NVIDIA, Inc. |
| 5 | * | 3 | * |
| 6 | * This software is licensed under the terms of the GNU General Public | 4 | * This software is licensed under the terms of the GNU General Public |
| @@ -14,6 +12,9 @@ | |||
| 14 | * | 12 | * |
| 15 | */ | 13 | */ |
| 16 | 14 | ||
| 15 | #ifndef __SOUND_TEGRA_WM38903_H | ||
| 16 | #define __SOUND_TEGRA_WM38903_H | ||
| 17 | |||
| 17 | struct tegra_wm8903_platform_data { | 18 | struct tegra_wm8903_platform_data { |
| 18 | int gpio_spkr_en; | 19 | int gpio_spkr_en; |
| 19 | int gpio_hp_det; | 20 | int gpio_hp_det; |
| @@ -21,3 +22,5 @@ struct tegra_wm8903_platform_data { | |||
| 21 | int gpio_int_mic_en; | 22 | int gpio_int_mic_en; |
| 22 | int gpio_ext_mic_en; | 23 | int gpio_ext_mic_en; |
| 23 | }; | 24 | }; |
| 25 | |||
| 26 | #endif | ||
diff --git a/include/sound/tlv.h b/include/sound/tlv.h index a64d8fe3f855..28c65e1ada21 100644 --- a/include/sound/tlv.h +++ b/include/sound/tlv.h | |||
| @@ -86,4 +86,12 @@ | |||
| 86 | 86 | ||
| 87 | #define TLV_DB_GAIN_MUTE -9999999 | 87 | #define TLV_DB_GAIN_MUTE -9999999 |
| 88 | 88 | ||
| 89 | /* | ||
| 90 | * channel-mapping TLV items | ||
| 91 | * TLV length must match with num_channels | ||
| 92 | */ | ||
| 93 | #define SNDRV_CTL_TLVT_CHMAP_FIXED 0x101 /* fixed channel position */ | ||
| 94 | #define SNDRV_CTL_TLVT_CHMAP_VAR 0x102 /* channels freely swappable */ | ||
| 95 | #define SNDRV_CTL_TLVT_CHMAP_PAIRED 0x103 /* pair-wise swappable */ | ||
| 96 | |||
| 89 | #endif /* __SOUND_TLV_H */ | 97 | #endif /* __SOUND_TLV_H */ |
diff --git a/include/sound/version.h b/include/sound/version.h deleted file mode 100644 index cc75024c1089..000000000000 --- a/include/sound/version.h +++ /dev/null | |||
| @@ -1,3 +0,0 @@ | |||
| 1 | /* include/version.h */ | ||
| 2 | #define CONFIG_SND_VERSION "1.0.25" | ||
| 3 | #define CONFIG_SND_DATE "" | ||
diff --git a/include/sound/wm0010.h b/include/sound/wm0010.h new file mode 100644 index 000000000000..3261e90815af --- /dev/null +++ b/include/sound/wm0010.h | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | /* | ||
| 2 | * wm0010.h -- Platform data for WM0010 DSP Driver | ||
| 3 | * | ||
| 4 | * Copyright 2012 Wolfson Microelectronics PLC. | ||
| 5 | * | ||
| 6 | * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify it | ||
| 9 | * under the terms of the GNU General Public License as published by the | ||
| 10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 11 | * option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #ifndef WM0010_PDATA_H | ||
| 15 | #define WM0010_PDATA_H | ||
| 16 | |||
| 17 | struct wm0010_pdata { | ||
| 18 | int gpio_reset; | ||
| 19 | |||
| 20 | /* Set if there is an inverter between the GPIO controlling | ||
| 21 | * the reset signal and the device. | ||
| 22 | */ | ||
| 23 | int reset_active_high; | ||
| 24 | int irq_flags; | ||
| 25 | }; | ||
| 26 | |||
| 27 | #endif | ||
diff --git a/include/sound/wm8960.h b/include/sound/wm8960.h index 74e9a95529c5..e8ce8ee7d62d 100644 --- a/include/sound/wm8960.h +++ b/include/sound/wm8960.h | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | struct wm8960_data { | 18 | struct wm8960_data { |
| 19 | bool capless; /* Headphone outputs configured in capless mode */ | 19 | bool capless; /* Headphone outputs configured in capless mode */ |
| 20 | 20 | ||
| 21 | int dres; /* Discharge resistance for headphone outputs */ | 21 | bool shared_lrclk; /* DAC and ADC LRCLKs are wired together */ |
| 22 | }; | 22 | }; |
| 23 | 23 | ||
| 24 | #endif | 24 | #endif |
diff --git a/include/sound/wm8993.h b/include/sound/wm8993.h index eee19f63c0d8..8016fd826f5a 100644 --- a/include/sound/wm8993.h +++ b/include/sound/wm8993.h | |||
| @@ -32,6 +32,10 @@ struct wm8993_platform_data { | |||
| 32 | unsigned int lineout1fb:1; | 32 | unsigned int lineout1fb:1; |
| 33 | unsigned int lineout2fb:1; | 33 | unsigned int lineout2fb:1; |
| 34 | 34 | ||
| 35 | /* Delay to add for microphones to stabalise after power up */ | ||
| 36 | int micbias1_delay; | ||
| 37 | int micbias2_delay; | ||
| 38 | |||
| 35 | /* Microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */ | 39 | /* Microphone biases: 0=0.9*AVDD1 1=0.65*AVVD1 */ |
| 36 | unsigned int micbias1_lvl:1; | 40 | unsigned int micbias1_lvl:1; |
| 37 | unsigned int micbias2_lvl:1; | 41 | unsigned int micbias2_lvl:1; |
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index eb60cb8dbb8a..c40ae573346d 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c | |||
| @@ -425,6 +425,26 @@ static int snd_compr_allocate_buffer(struct snd_compr_stream *stream, | |||
| 425 | return 0; | 425 | return 0; |
| 426 | } | 426 | } |
| 427 | 427 | ||
| 428 | static int snd_compress_check_input(struct snd_compr_params *params) | ||
| 429 | { | ||
| 430 | /* first let's check the buffer parameter's */ | ||
| 431 | if (params->buffer.fragment_size == 0 || | ||
| 432 | params->buffer.fragments > SIZE_MAX / params->buffer.fragment_size) | ||
| 433 | return -EINVAL; | ||
| 434 | |||
| 435 | /* now codec parameters */ | ||
| 436 | if (params->codec.id == 0 || params->codec.id > SND_AUDIOCODEC_MAX) | ||
| 437 | return -EINVAL; | ||
| 438 | |||
| 439 | if (params->codec.ch_in == 0 || params->codec.ch_out == 0) | ||
| 440 | return -EINVAL; | ||
| 441 | |||
| 442 | if (!(params->codec.sample_rate & SNDRV_PCM_RATE_8000_192000)) | ||
| 443 | return -EINVAL; | ||
| 444 | |||
| 445 | return 0; | ||
| 446 | } | ||
| 447 | |||
| 428 | static int | 448 | static int |
| 429 | snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg) | 449 | snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg) |
| 430 | { | 450 | { |
| @@ -443,11 +463,17 @@ snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg) | |||
| 443 | retval = -EFAULT; | 463 | retval = -EFAULT; |
| 444 | goto out; | 464 | goto out; |
| 445 | } | 465 | } |
| 466 | |||
| 467 | retval = snd_compress_check_input(params); | ||
| 468 | if (retval) | ||
| 469 | goto out; | ||
| 470 | |||
| 446 | retval = snd_compr_allocate_buffer(stream, params); | 471 | retval = snd_compr_allocate_buffer(stream, params); |
| 447 | if (retval) { | 472 | if (retval) { |
| 448 | retval = -ENOMEM; | 473 | retval = -ENOMEM; |
| 449 | goto out; | 474 | goto out; |
| 450 | } | 475 | } |
| 476 | |||
| 451 | retval = stream->ops->set_params(stream, params); | 477 | retval = stream->ops->set_params(stream, params); |
| 452 | if (retval) | 478 | if (retval) |
| 453 | goto out; | 479 | goto out; |
diff --git a/sound/core/control.c b/sound/core/control.c index 2487a6bb1c54..7e86a5b9f3b5 100644 --- a/sound/core/control.c +++ b/sound/core/control.c | |||
| @@ -246,6 +246,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol, | |||
| 246 | kctl.count = ncontrol->count ? ncontrol->count : 1; | 246 | kctl.count = ncontrol->count ? ncontrol->count : 1; |
| 247 | access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : | 247 | access = ncontrol->access == 0 ? SNDRV_CTL_ELEM_ACCESS_READWRITE : |
| 248 | (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| | 248 | (ncontrol->access & (SNDRV_CTL_ELEM_ACCESS_READWRITE| |
| 249 | SNDRV_CTL_ELEM_ACCESS_VOLATILE| | ||
| 249 | SNDRV_CTL_ELEM_ACCESS_INACTIVE| | 250 | SNDRV_CTL_ELEM_ACCESS_INACTIVE| |
| 250 | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE| | 251 | SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE| |
| 251 | SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND| | 252 | SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND| |
diff --git a/sound/core/info.c b/sound/core/info.c index c1e611c65c8f..6b368d25073b 100644 --- a/sound/core/info.c +++ b/sound/core/info.c | |||
| @@ -28,7 +28,7 @@ | |||
| 28 | #include <sound/core.h> | 28 | #include <sound/core.h> |
| 29 | #include <sound/minors.h> | 29 | #include <sound/minors.h> |
| 30 | #include <sound/info.h> | 30 | #include <sound/info.h> |
| 31 | #include <sound/version.h> | 31 | #include <linux/utsname.h> |
| 32 | #include <linux/proc_fs.h> | 32 | #include <linux/proc_fs.h> |
| 33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
| 34 | #include <stdarg.h> | 34 | #include <stdarg.h> |
| @@ -986,9 +986,8 @@ static struct snd_info_entry *snd_info_version_entry; | |||
| 986 | static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) | 986 | static void snd_info_version_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) |
| 987 | { | 987 | { |
| 988 | snd_iprintf(buffer, | 988 | snd_iprintf(buffer, |
| 989 | "Advanced Linux Sound Architecture Driver Version " | 989 | "Advanced Linux Sound Architecture Driver Version k%s.\n", |
| 990 | CONFIG_SND_VERSION CONFIG_SND_DATE ".\n" | 990 | init_utsname()->release); |
| 991 | ); | ||
| 992 | } | 991 | } |
| 993 | 992 | ||
| 994 | static int __init snd_info_version_init(void) | 993 | static int __init snd_info_version_init(void) |
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c index cf42ab5080eb..83c29dbff9c0 100644 --- a/sound/core/info_oss.c +++ b/sound/core/info_oss.c | |||
| @@ -26,7 +26,6 @@ | |||
| 26 | #include <sound/core.h> | 26 | #include <sound/core.h> |
| 27 | #include <sound/minors.h> | 27 | #include <sound/minors.h> |
| 28 | #include <sound/info.h> | 28 | #include <sound/info.h> |
| 29 | #include <sound/version.h> | ||
| 30 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
| 31 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
| 32 | 31 | ||
| @@ -94,7 +93,7 @@ static int snd_sndstat_show_strings(struct snd_info_buffer *buf, char *id, int d | |||
| 94 | static void snd_sndstat_proc_read(struct snd_info_entry *entry, | 93 | static void snd_sndstat_proc_read(struct snd_info_entry *entry, |
| 95 | struct snd_info_buffer *buffer) | 94 | struct snd_info_buffer *buffer) |
| 96 | { | 95 | { |
| 97 | snd_iprintf(buffer, "Sound Driver:3.8.1a-980706 (ALSA v" CONFIG_SND_VERSION " emulation code)\n"); | 96 | snd_iprintf(buffer, "Sound Driver:3.8.1a-980706 (ALSA emulation code)\n"); |
| 98 | snd_iprintf(buffer, "Kernel: %s %s %s %s %s\n", | 97 | snd_iprintf(buffer, "Kernel: %s %s %s %s %s\n", |
| 99 | init_utsname()->sysname, | 98 | init_utsname()->sysname, |
| 100 | init_utsname()->nodename, | 99 | init_utsname()->nodename, |
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 18297f7f2c55..29f6ded02555 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c | |||
| @@ -1046,6 +1046,7 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mix | |||
| 1046 | 1046 | ||
| 1047 | if (kctl->info(kctl, uinfo)) { | 1047 | if (kctl->info(kctl, uinfo)) { |
| 1048 | up_read(&mixer->card->controls_rwsem); | 1048 | up_read(&mixer->card->controls_rwsem); |
| 1049 | kfree(uinfo); | ||
| 1049 | return 0; | 1050 | return 0; |
| 1050 | } | 1051 | } |
| 1051 | strcpy(str, ptr->name); | 1052 | strcpy(str, ptr->name); |
| @@ -1061,6 +1062,7 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mix | |||
| 1061 | uinfo->value.enumerated.item = slot.capture_item; | 1062 | uinfo->value.enumerated.item = slot.capture_item; |
| 1062 | if (kctl->info(kctl, uinfo)) { | 1063 | if (kctl->info(kctl, uinfo)) { |
| 1063 | up_read(&mixer->card->controls_rwsem); | 1064 | up_read(&mixer->card->controls_rwsem); |
| 1065 | kfree(uinfo); | ||
| 1064 | return 0; | 1066 | return 0; |
| 1065 | } | 1067 | } |
| 1066 | if (!strcmp(uinfo->value.enumerated.name, str)) { | 1068 | if (!strcmp(uinfo->value.enumerated.name, str)) { |
diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 1a3070b4e5b5..f2991940b271 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c | |||
| @@ -1105,6 +1105,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) | |||
| 1105 | break; | 1105 | break; |
| 1106 | } | 1106 | } |
| 1107 | snd_unregister_device(devtype, pcm->card, pcm->device); | 1107 | snd_unregister_device(devtype, pcm->card, pcm->device); |
| 1108 | if (pcm->streams[cidx].chmap_kctl) { | ||
| 1109 | snd_ctl_remove(pcm->card, pcm->streams[cidx].chmap_kctl); | ||
| 1110 | pcm->streams[cidx].chmap_kctl = NULL; | ||
| 1111 | } | ||
| 1108 | } | 1112 | } |
| 1109 | unlock: | 1113 | unlock: |
| 1110 | mutex_unlock(®ister_mutex); | 1114 | mutex_unlock(®ister_mutex); |
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 7ae671923393..f42c10a43315 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | #include <linux/export.h> | 26 | #include <linux/export.h> |
| 27 | #include <sound/core.h> | 27 | #include <sound/core.h> |
| 28 | #include <sound/control.h> | 28 | #include <sound/control.h> |
| 29 | #include <sound/tlv.h> | ||
| 29 | #include <sound/info.h> | 30 | #include <sound/info.h> |
| 30 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
| 31 | #include <sound/pcm_params.h> | 32 | #include <sound/pcm_params.h> |
| @@ -2302,3 +2303,216 @@ snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream, | |||
| 2302 | } | 2303 | } |
| 2303 | 2304 | ||
| 2304 | EXPORT_SYMBOL(snd_pcm_lib_readv); | 2305 | EXPORT_SYMBOL(snd_pcm_lib_readv); |
| 2306 | |||
| 2307 | /* | ||
| 2308 | * standard channel mapping helpers | ||
| 2309 | */ | ||
| 2310 | |||
| 2311 | /* default channel maps for multi-channel playbacks, up to 8 channels */ | ||
| 2312 | const struct snd_pcm_chmap_elem snd_pcm_std_chmaps[] = { | ||
| 2313 | { .channels = 1, | ||
| 2314 | .map = { SNDRV_CHMAP_MONO } }, | ||
| 2315 | { .channels = 2, | ||
| 2316 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, | ||
| 2317 | { .channels = 4, | ||
| 2318 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, | ||
| 2319 | SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
| 2320 | { .channels = 6, | ||
| 2321 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, | ||
| 2322 | SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, | ||
| 2323 | SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } }, | ||
| 2324 | { .channels = 8, | ||
| 2325 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, | ||
| 2326 | SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, | ||
| 2327 | SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE, | ||
| 2328 | SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } }, | ||
| 2329 | { } | ||
| 2330 | }; | ||
| 2331 | EXPORT_SYMBOL_GPL(snd_pcm_std_chmaps); | ||
| 2332 | |||
| 2333 | /* alternative channel maps with CLFE <-> surround swapped for 6/8 channels */ | ||
| 2334 | const struct snd_pcm_chmap_elem snd_pcm_alt_chmaps[] = { | ||
| 2335 | { .channels = 1, | ||
| 2336 | .map = { SNDRV_CHMAP_MONO } }, | ||
| 2337 | { .channels = 2, | ||
| 2338 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } }, | ||
| 2339 | { .channels = 4, | ||
| 2340 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, | ||
| 2341 | SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
| 2342 | { .channels = 6, | ||
| 2343 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, | ||
| 2344 | SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE, | ||
| 2345 | SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
| 2346 | { .channels = 8, | ||
| 2347 | .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, | ||
| 2348 | SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE, | ||
| 2349 | SNDRV_CHMAP_RL, SNDRV_CHMAP_RR, | ||
| 2350 | SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } }, | ||
| 2351 | { } | ||
| 2352 | }; | ||
| 2353 | EXPORT_SYMBOL_GPL(snd_pcm_alt_chmaps); | ||
| 2354 | |||
| 2355 | static bool valid_chmap_channels(const struct snd_pcm_chmap *info, int ch) | ||
| 2356 | { | ||
| 2357 | if (ch > info->max_channels) | ||
| 2358 | return false; | ||
| 2359 | return !info->channel_mask || (info->channel_mask & (1U << ch)); | ||
| 2360 | } | ||
| 2361 | |||
| 2362 | static int pcm_chmap_ctl_info(struct snd_kcontrol *kcontrol, | ||
| 2363 | struct snd_ctl_elem_info *uinfo) | ||
| 2364 | { | ||
| 2365 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
| 2366 | |||
| 2367 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
| 2368 | uinfo->count = 0; | ||
| 2369 | uinfo->count = info->max_channels; | ||
| 2370 | uinfo->value.integer.min = 0; | ||
| 2371 | uinfo->value.integer.max = SNDRV_CHMAP_LAST; | ||
| 2372 | return 0; | ||
| 2373 | } | ||
| 2374 | |||
| 2375 | /* get callback for channel map ctl element | ||
| 2376 | * stores the channel position firstly matching with the current channels | ||
| 2377 | */ | ||
| 2378 | static int pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol, | ||
| 2379 | struct snd_ctl_elem_value *ucontrol) | ||
| 2380 | { | ||
| 2381 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
| 2382 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
| 2383 | struct snd_pcm_substream *substream; | ||
| 2384 | const struct snd_pcm_chmap_elem *map; | ||
| 2385 | |||
| 2386 | if (snd_BUG_ON(!info->chmap)) | ||
| 2387 | return -EINVAL; | ||
| 2388 | substream = snd_pcm_chmap_substream(info, idx); | ||
| 2389 | if (!substream) | ||
| 2390 | return -ENODEV; | ||
| 2391 | memset(ucontrol->value.integer.value, 0, | ||
| 2392 | sizeof(ucontrol->value.integer.value)); | ||
| 2393 | if (!substream->runtime) | ||
| 2394 | return 0; /* no channels set */ | ||
| 2395 | for (map = info->chmap; map->channels; map++) { | ||
| 2396 | int i; | ||
| 2397 | if (map->channels == substream->runtime->channels && | ||
| 2398 | valid_chmap_channels(info, map->channels)) { | ||
| 2399 | for (i = 0; i < map->channels; i++) | ||
| 2400 | ucontrol->value.integer.value[i] = map->map[i]; | ||
| 2401 | return 0; | ||
| 2402 | } | ||
| 2403 | } | ||
| 2404 | return -EINVAL; | ||
| 2405 | } | ||
| 2406 | |||
| 2407 | /* tlv callback for channel map ctl element | ||
| 2408 | * expands the pre-defined channel maps in a form of TLV | ||
| 2409 | */ | ||
| 2410 | static int pcm_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
| 2411 | unsigned int size, unsigned int __user *tlv) | ||
| 2412 | { | ||
| 2413 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
| 2414 | const struct snd_pcm_chmap_elem *map; | ||
| 2415 | unsigned int __user *dst; | ||
| 2416 | int c, count = 0; | ||
| 2417 | |||
| 2418 | if (snd_BUG_ON(!info->chmap)) | ||
| 2419 | return -EINVAL; | ||
| 2420 | if (size < 8) | ||
| 2421 | return -ENOMEM; | ||
| 2422 | if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv)) | ||
| 2423 | return -EFAULT; | ||
| 2424 | size -= 8; | ||
| 2425 | dst = tlv + 2; | ||
| 2426 | for (map = info->chmap; map->channels; map++) { | ||
| 2427 | int chs_bytes = map->channels * 4; | ||
| 2428 | if (!valid_chmap_channels(info, map->channels)) | ||
| 2429 | continue; | ||
| 2430 | if (size < 8) | ||
| 2431 | return -ENOMEM; | ||
| 2432 | if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) || | ||
| 2433 | put_user(chs_bytes, dst + 1)) | ||
| 2434 | return -EFAULT; | ||
| 2435 | dst += 2; | ||
| 2436 | size -= 8; | ||
| 2437 | count += 8; | ||
| 2438 | if (size < chs_bytes) | ||
| 2439 | return -ENOMEM; | ||
| 2440 | size -= chs_bytes; | ||
| 2441 | count += chs_bytes; | ||
| 2442 | for (c = 0; c < map->channels; c++) { | ||
| 2443 | if (put_user(map->map[c], dst)) | ||
| 2444 | return -EFAULT; | ||
| 2445 | dst++; | ||
| 2446 | } | ||
| 2447 | } | ||
| 2448 | if (put_user(count, tlv + 1)) | ||
| 2449 | return -EFAULT; | ||
| 2450 | return 0; | ||
| 2451 | } | ||
| 2452 | |||
| 2453 | static void pcm_chmap_ctl_private_free(struct snd_kcontrol *kcontrol) | ||
| 2454 | { | ||
| 2455 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
| 2456 | info->pcm->streams[info->stream].chmap_kctl = NULL; | ||
| 2457 | kfree(info); | ||
| 2458 | } | ||
| 2459 | |||
| 2460 | /** | ||
| 2461 | * snd_pcm_add_chmap_ctls - create channel-mapping control elements | ||
| 2462 | * @pcm: the assigned PCM instance | ||
| 2463 | * @stream: stream direction | ||
| 2464 | * @chmap: channel map elements (for query) | ||
| 2465 | * @max_channels: the max number of channels for the stream | ||
| 2466 | * @private_value: the value passed to each kcontrol's private_value field | ||
| 2467 | * @info_ret: store struct snd_pcm_chmap instance if non-NULL | ||
| 2468 | * | ||
| 2469 | * Create channel-mapping control elements assigned to the given PCM stream(s). | ||
| 2470 | * Returns zero if succeed, or a negative error value. | ||
| 2471 | */ | ||
| 2472 | int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream, | ||
| 2473 | const struct snd_pcm_chmap_elem *chmap, | ||
| 2474 | int max_channels, | ||
| 2475 | unsigned long private_value, | ||
| 2476 | struct snd_pcm_chmap **info_ret) | ||
| 2477 | { | ||
| 2478 | struct snd_pcm_chmap *info; | ||
| 2479 | struct snd_kcontrol_new knew = { | ||
| 2480 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
| 2481 | .access = SNDRV_CTL_ELEM_ACCESS_READ | | ||
| 2482 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
| 2483 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, | ||
| 2484 | .info = pcm_chmap_ctl_info, | ||
| 2485 | .get = pcm_chmap_ctl_get, | ||
| 2486 | .tlv.c = pcm_chmap_ctl_tlv, | ||
| 2487 | }; | ||
| 2488 | int err; | ||
| 2489 | |||
| 2490 | info = kzalloc(sizeof(*info), GFP_KERNEL); | ||
| 2491 | if (!info) | ||
| 2492 | return -ENOMEM; | ||
| 2493 | info->pcm = pcm; | ||
| 2494 | info->stream = stream; | ||
| 2495 | info->chmap = chmap; | ||
| 2496 | info->max_channels = max_channels; | ||
| 2497 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
| 2498 | knew.name = "Playback Channel Map"; | ||
| 2499 | else | ||
| 2500 | knew.name = "Capture Channel Map"; | ||
| 2501 | knew.device = pcm->device; | ||
| 2502 | knew.count = pcm->streams[stream].substream_count; | ||
| 2503 | knew.private_value = private_value; | ||
| 2504 | info->kctl = snd_ctl_new1(&knew, info); | ||
| 2505 | if (!info->kctl) { | ||
| 2506 | kfree(info); | ||
| 2507 | return -ENOMEM; | ||
| 2508 | } | ||
| 2509 | info->kctl->private_free = pcm_chmap_ctl_private_free; | ||
| 2510 | err = snd_ctl_add(pcm->card, info->kctl); | ||
| 2511 | if (err < 0) | ||
| 2512 | return err; | ||
| 2513 | pcm->streams[stream].chmap_kctl = info->kctl; | ||
| 2514 | if (info_ret) | ||
| 2515 | *info_ret = info; | ||
| 2516 | return 0; | ||
| 2517 | } | ||
| 2518 | EXPORT_SYMBOL_GPL(snd_pcm_add_chmap_ctls); | ||
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c index 957131366dd9..69e01c4fc32d 100644 --- a/sound/core/pcm_memory.c +++ b/sound/core/pcm_memory.c | |||
| @@ -327,32 +327,6 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne | |||
| 327 | } | 327 | } |
| 328 | 328 | ||
| 329 | EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); | 329 | EXPORT_SYMBOL(snd_pcm_sgbuf_ops_page); |
| 330 | |||
| 331 | /* | ||
| 332 | * compute the max chunk size with continuous pages on sg-buffer | ||
| 333 | */ | ||
| 334 | unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, | ||
| 335 | unsigned int ofs, unsigned int size) | ||
| 336 | { | ||
| 337 | struct snd_sg_buf *sg = snd_pcm_substream_sgbuf(substream); | ||
| 338 | unsigned int start, end, pg; | ||
| 339 | |||
| 340 | start = ofs >> PAGE_SHIFT; | ||
| 341 | end = (ofs + size - 1) >> PAGE_SHIFT; | ||
| 342 | /* check page continuity */ | ||
| 343 | pg = sg->table[start].addr >> PAGE_SHIFT; | ||
| 344 | for (;;) { | ||
| 345 | start++; | ||
| 346 | if (start > end) | ||
| 347 | break; | ||
| 348 | pg++; | ||
| 349 | if ((sg->table[start].addr >> PAGE_SHIFT) != pg) | ||
| 350 | return (start << PAGE_SHIFT) - ofs; | ||
| 351 | } | ||
| 352 | /* ok, all on continuous pages */ | ||
| 353 | return size; | ||
| 354 | } | ||
| 355 | EXPORT_SYMBOL(snd_pcm_sgbuf_get_chunk_size); | ||
| 356 | #endif /* CONFIG_SND_DMA_SGBUF */ | 330 | #endif /* CONFIG_SND_DMA_SGBUF */ |
| 357 | 331 | ||
| 358 | /** | 332 | /** |
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c index 5cf8d65ed5ef..60e8fc1b3440 100644 --- a/sound/core/seq/seq_device.c +++ b/sound/core/seq/seq_device.c | |||
| @@ -569,5 +569,7 @@ EXPORT_SYMBOL(snd_seq_device_load_drivers); | |||
| 569 | EXPORT_SYMBOL(snd_seq_device_new); | 569 | EXPORT_SYMBOL(snd_seq_device_new); |
| 570 | EXPORT_SYMBOL(snd_seq_device_register_driver); | 570 | EXPORT_SYMBOL(snd_seq_device_register_driver); |
| 571 | EXPORT_SYMBOL(snd_seq_device_unregister_driver); | 571 | EXPORT_SYMBOL(snd_seq_device_unregister_driver); |
| 572 | #ifdef CONFIG_MODULES | ||
| 572 | EXPORT_SYMBOL(snd_seq_autoload_lock); | 573 | EXPORT_SYMBOL(snd_seq_autoload_lock); |
| 573 | EXPORT_SYMBOL(snd_seq_autoload_unlock); | 574 | EXPORT_SYMBOL(snd_seq_autoload_unlock); |
| 575 | #endif | ||
diff --git a/sound/core/sgbuf.c b/sound/core/sgbuf.c index d0f00356fc11..0a418503ec41 100644 --- a/sound/core/sgbuf.c +++ b/sound/core/sgbuf.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
| 24 | #include <linux/vmalloc.h> | 24 | #include <linux/vmalloc.h> |
| 25 | #include <linux/export.h> | ||
| 25 | #include <sound/memalloc.h> | 26 | #include <sound/memalloc.h> |
| 26 | 27 | ||
| 27 | 28 | ||
| @@ -136,3 +137,29 @@ void *snd_malloc_sgbuf_pages(struct device *device, | |||
| 136 | snd_free_sgbuf_pages(dmab); /* free the table */ | 137 | snd_free_sgbuf_pages(dmab); /* free the table */ |
| 137 | return NULL; | 138 | return NULL; |
| 138 | } | 139 | } |
| 140 | |||
| 141 | /* | ||
| 142 | * compute the max chunk size with continuous pages on sg-buffer | ||
| 143 | */ | ||
| 144 | unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab, | ||
| 145 | unsigned int ofs, unsigned int size) | ||
| 146 | { | ||
| 147 | struct snd_sg_buf *sg = dmab->private_data; | ||
| 148 | unsigned int start, end, pg; | ||
| 149 | |||
| 150 | start = ofs >> PAGE_SHIFT; | ||
| 151 | end = (ofs + size - 1) >> PAGE_SHIFT; | ||
| 152 | /* check page continuity */ | ||
| 153 | pg = sg->table[start].addr >> PAGE_SHIFT; | ||
| 154 | for (;;) { | ||
| 155 | start++; | ||
| 156 | if (start > end) | ||
| 157 | break; | ||
| 158 | pg++; | ||
| 159 | if ((sg->table[start].addr >> PAGE_SHIFT) != pg) | ||
| 160 | return (start << PAGE_SHIFT) - ofs; | ||
| 161 | } | ||
| 162 | /* ok, all on continuous pages */ | ||
| 163 | return size; | ||
| 164 | } | ||
| 165 | EXPORT_SYMBOL(snd_sgbuf_get_chunk_size); | ||
diff --git a/sound/core/sound.c b/sound/core/sound.c index 28f35593a750..643976000ce8 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c | |||
| @@ -27,7 +27,6 @@ | |||
| 27 | #include <sound/core.h> | 27 | #include <sound/core.h> |
| 28 | #include <sound/minors.h> | 28 | #include <sound/minors.h> |
| 29 | #include <sound/info.h> | 29 | #include <sound/info.h> |
| 30 | #include <sound/version.h> | ||
| 31 | #include <sound/control.h> | 30 | #include <sound/control.h> |
| 32 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
| 33 | #include <linux/kmod.h> | 32 | #include <linux/kmod.h> |
| @@ -468,7 +467,7 @@ static int __init alsa_sound_init(void) | |||
| 468 | } | 467 | } |
| 469 | snd_info_minor_register(); | 468 | snd_info_minor_register(); |
| 470 | #ifndef MODULE | 469 | #ifndef MODULE |
| 471 | printk(KERN_INFO "Advanced Linux Sound Architecture Driver Version " CONFIG_SND_VERSION CONFIG_SND_DATE ".\n"); | 470 | printk(KERN_INFO "Advanced Linux Sound Architecture Driver Initialized.\n"); |
| 472 | #endif | 471 | #endif |
| 473 | return 0; | 472 | return 0; |
| 474 | } | 473 | } |
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index 5a34355e78e8..0fe6d64ff840 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c | |||
| @@ -120,6 +120,7 @@ struct loopback_pcm { | |||
| 120 | unsigned int last_drift; | 120 | unsigned int last_drift; |
| 121 | unsigned long last_jiffies; | 121 | unsigned long last_jiffies; |
| 122 | struct timer_list timer; | 122 | struct timer_list timer; |
| 123 | spinlock_t timer_lock; | ||
| 123 | }; | 124 | }; |
| 124 | 125 | ||
| 125 | static struct platform_device *devices[SNDRV_CARDS]; | 126 | static struct platform_device *devices[SNDRV_CARDS]; |
| @@ -170,6 +171,7 @@ static void loopback_timer_start(struct loopback_pcm *dpcm) | |||
| 170 | unsigned long tick; | 171 | unsigned long tick; |
| 171 | unsigned int rate_shift = get_rate_shift(dpcm); | 172 | unsigned int rate_shift = get_rate_shift(dpcm); |
| 172 | 173 | ||
| 174 | spin_lock(&dpcm->timer_lock); | ||
| 173 | if (rate_shift != dpcm->pcm_rate_shift) { | 175 | if (rate_shift != dpcm->pcm_rate_shift) { |
| 174 | dpcm->pcm_rate_shift = rate_shift; | 176 | dpcm->pcm_rate_shift = rate_shift; |
| 175 | dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size); | 177 | dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size); |
| @@ -182,12 +184,15 @@ static void loopback_timer_start(struct loopback_pcm *dpcm) | |||
| 182 | tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; | 184 | tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; |
| 183 | dpcm->timer.expires = jiffies + tick; | 185 | dpcm->timer.expires = jiffies + tick; |
| 184 | add_timer(&dpcm->timer); | 186 | add_timer(&dpcm->timer); |
| 187 | spin_unlock(&dpcm->timer_lock); | ||
| 185 | } | 188 | } |
| 186 | 189 | ||
| 187 | static inline void loopback_timer_stop(struct loopback_pcm *dpcm) | 190 | static inline void loopback_timer_stop(struct loopback_pcm *dpcm) |
| 188 | { | 191 | { |
| 192 | spin_lock(&dpcm->timer_lock); | ||
| 189 | del_timer(&dpcm->timer); | 193 | del_timer(&dpcm->timer); |
| 190 | dpcm->timer.expires = 0; | 194 | dpcm->timer.expires = 0; |
| 195 | spin_unlock(&dpcm->timer_lock); | ||
| 191 | } | 196 | } |
| 192 | 197 | ||
| 193 | #define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK) | 198 | #define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK) |
| @@ -667,6 +672,7 @@ static int loopback_open(struct snd_pcm_substream *substream) | |||
| 667 | dpcm->substream = substream; | 672 | dpcm->substream = substream; |
| 668 | setup_timer(&dpcm->timer, loopback_timer_function, | 673 | setup_timer(&dpcm->timer, loopback_timer_function, |
| 669 | (unsigned long)dpcm); | 674 | (unsigned long)dpcm); |
| 675 | spin_lock_init(&dpcm->timer_lock); | ||
| 670 | 676 | ||
| 671 | cable = loopback->cables[substream->number][dev]; | 677 | cable = loopback->cables[substream->number][dev]; |
| 672 | if (!cable) { | 678 | if (!cable) { |
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c index 2bfe4bcb7a7d..0c796bcbc0a3 100644 --- a/sound/drivers/opl3/opl3_midi.c +++ b/sound/drivers/opl3/opl3_midi.c | |||
| @@ -163,7 +163,7 @@ static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op, | |||
| 163 | struct best *bp; | 163 | struct best *bp; |
| 164 | 164 | ||
| 165 | for (i = 0; i < END; i++) { | 165 | for (i = 0; i < END; i++) { |
| 166 | best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */; | 166 | best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */ |
| 167 | best[i].voice = -1; | 167 | best[i].voice = -1; |
| 168 | } | 168 | } |
| 169 | 169 | ||
diff --git a/sound/drivers/opl4/opl4_synth.c b/sound/drivers/opl4/opl4_synth.c index 49b9e240915c..4b91adc0238c 100644 --- a/sound/drivers/opl4/opl4_synth.c +++ b/sound/drivers/opl4/opl4_synth.c | |||
| @@ -504,8 +504,7 @@ void snd_opl4_note_on(void *private_data, int note, int vel, struct snd_midi_cha | |||
| 504 | spin_lock_irqsave(&opl4->reg_lock, flags); | 504 | spin_lock_irqsave(&opl4->reg_lock, flags); |
| 505 | for (i = 0; i < voices; i++) { | 505 | for (i = 0; i < voices; i++) { |
| 506 | voice[i] = snd_opl4_get_voice(opl4); | 506 | voice[i] = snd_opl4_get_voice(opl4); |
| 507 | list_del(&voice[i]->list); | 507 | list_move_tail(&voice[i]->list, &opl4->on_voices); |
| 508 | list_add_tail(&voice[i]->list, &opl4->on_voices); | ||
| 509 | voice[i]->chan = chan; | 508 | voice[i]->chan = chan; |
| 510 | voice[i]->note = note; | 509 | voice[i]->note = note; |
| 511 | voice[i]->velocity = vel & 0x7f; | 510 | voice[i]->velocity = vel & 0x7f; |
| @@ -555,8 +554,7 @@ void snd_opl4_note_on(void *private_data, int note, int vel, struct snd_midi_cha | |||
| 555 | 554 | ||
| 556 | static void snd_opl4_voice_off(struct snd_opl4 *opl4, struct opl4_voice *voice) | 555 | static void snd_opl4_voice_off(struct snd_opl4 *opl4, struct opl4_voice *voice) |
| 557 | { | 556 | { |
| 558 | list_del(&voice->list); | 557 | list_move_tail(&voice->list, &opl4->off_voices); |
| 559 | list_add_tail(&voice->list, &opl4->off_voices); | ||
| 560 | 558 | ||
| 561 | voice->reg_misc &= ~OPL4_KEY_ON_BIT; | 559 | voice->reg_misc &= ~OPL4_KEY_ON_BIT; |
| 562 | snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc); | 560 | snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc); |
| @@ -571,8 +569,7 @@ void snd_opl4_note_off(void *private_data, int note, int vel, struct snd_midi_ch | |||
| 571 | 569 | ||
| 572 | static void snd_opl4_terminate_voice(struct snd_opl4 *opl4, struct opl4_voice *voice) | 570 | static void snd_opl4_terminate_voice(struct snd_opl4 *opl4, struct opl4_voice *voice) |
| 573 | { | 571 | { |
| 574 | list_del(&voice->list); | 572 | list_move_tail(&voice->list, &opl4->off_voices); |
| 575 | list_add_tail(&voice->list, &opl4->off_voices); | ||
| 576 | 573 | ||
| 577 | voice->reg_misc = (voice->reg_misc & ~OPL4_KEY_ON_BIT) | OPL4_DAMP_BIT; | 574 | voice->reg_misc = (voice->reg_misc & ~OPL4_KEY_ON_BIT) | OPL4_DAMP_BIT; |
| 578 | snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc); | 575 | snd_opl4_write(opl4, OPL4_REG_MISC + voice->number, voice->reg_misc); |
diff --git a/sound/drivers/vx/vx_pcm.c b/sound/drivers/vx/vx_pcm.c index 5e897b236cec..deed5efff33c 100644 --- a/sound/drivers/vx/vx_pcm.c +++ b/sound/drivers/vx/vx_pcm.c | |||
| @@ -184,7 +184,7 @@ static int vx_set_format(struct vx_core *chip, struct vx_pipe *pipe, | |||
| 184 | default : | 184 | default : |
| 185 | snd_BUG(); | 185 | snd_BUG(); |
| 186 | return -EINVAL; | 186 | return -EINVAL; |
| 187 | }; | 187 | } |
| 188 | 188 | ||
| 189 | return vx_set_stream_format(chip, pipe, header); | 189 | return vx_set_stream_format(chip, pipe, header); |
| 190 | } | 190 | } |
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index 52064cfa91f3..a38d9643e9d8 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig | |||
| @@ -117,6 +117,18 @@ config SND_AZT2320 | |||
| 117 | To compile this driver as a module, choose M here: the module | 117 | To compile this driver as a module, choose M here: the module |
| 118 | will be called snd-azt2320. | 118 | will be called snd-azt2320. |
| 119 | 119 | ||
| 120 | config SND_CMI8328 | ||
| 121 | tristate "C-Media CMI8328" | ||
| 122 | select SND_WSS_LIB | ||
| 123 | select SND_OPL3_LIB | ||
| 124 | select SND_MPU401_UART | ||
| 125 | help | ||
| 126 | Say Y here to include support for soundcards based on the | ||
| 127 | C-Media CMI8328 chip. | ||
| 128 | |||
| 129 | To compile this driver as a module, choose M here: the module | ||
| 130 | will be called snd-cmi8328. | ||
| 131 | |||
| 120 | config SND_CMI8330 | 132 | config SND_CMI8330 |
| 121 | tristate "C-Media CMI8330" | 133 | tristate "C-Media CMI8330" |
| 122 | select SND_WSS_LIB | 134 | select SND_WSS_LIB |
diff --git a/sound/isa/Makefile b/sound/isa/Makefile index 8d781e419e2e..9a15f1497b10 100644 --- a/sound/isa/Makefile +++ b/sound/isa/Makefile | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | snd-adlib-objs := adlib.o | 6 | snd-adlib-objs := adlib.o |
| 7 | snd-als100-objs := als100.o | 7 | snd-als100-objs := als100.o |
| 8 | snd-azt2320-objs := azt2320.o | 8 | snd-azt2320-objs := azt2320.o |
| 9 | snd-cmi8328-objs := cmi8328.o | ||
| 9 | snd-cmi8330-objs := cmi8330.o | 10 | snd-cmi8330-objs := cmi8330.o |
| 10 | snd-es18xx-objs := es18xx.o | 11 | snd-es18xx-objs := es18xx.o |
| 11 | snd-opl3sa2-objs := opl3sa2.o | 12 | snd-opl3sa2-objs := opl3sa2.o |
| @@ -16,6 +17,7 @@ snd-sscape-objs := sscape.o | |||
| 16 | obj-$(CONFIG_SND_ADLIB) += snd-adlib.o | 17 | obj-$(CONFIG_SND_ADLIB) += snd-adlib.o |
| 17 | obj-$(CONFIG_SND_ALS100) += snd-als100.o | 18 | obj-$(CONFIG_SND_ALS100) += snd-als100.o |
| 18 | obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o | 19 | obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o |
| 20 | obj-$(CONFIG_SND_CMI8328) += snd-cmi8328.o | ||
| 19 | obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o | 21 | obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o |
| 20 | obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o | 22 | obj-$(CONFIG_SND_ES18XX) += snd-es18xx.o |
| 21 | obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o | 23 | obj-$(CONFIG_SND_OPL3SA2) += snd-opl3sa2.o |
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c index 94b83b6e46a3..2c2f829c3fd7 100644 --- a/sound/isa/ad1816a/ad1816a.c +++ b/sound/isa/ad1816a/ad1816a.c | |||
| @@ -63,11 +63,6 @@ MODULE_PARM_DESC(enable, "Enable ad1816a based soundcard."); | |||
| 63 | module_param_array(clockfreq, int, NULL, 0444); | 63 | module_param_array(clockfreq, int, NULL, 0444); |
| 64 | MODULE_PARM_DESC(clockfreq, "Clock frequency for ad1816a driver (default = 0)."); | 64 | MODULE_PARM_DESC(clockfreq, "Clock frequency for ad1816a driver (default = 0)."); |
| 65 | 65 | ||
| 66 | struct snd_card_ad1816a { | ||
| 67 | struct pnp_dev *dev; | ||
| 68 | struct pnp_dev *devmpu; | ||
| 69 | }; | ||
| 70 | |||
| 71 | static struct pnp_card_device_id snd_ad1816a_pnpids[] = { | 66 | static struct pnp_card_device_id snd_ad1816a_pnpids[] = { |
| 72 | /* Analog Devices AD1815 */ | 67 | /* Analog Devices AD1815 */ |
| 73 | { .id = "ADS7150", .devs = { { .id = "ADS7150" }, { .id = "ADS7151" } } }, | 68 | { .id = "ADS7150", .devs = { { .id = "ADS7150" }, { .id = "ADS7151" } } }, |
| @@ -99,25 +94,16 @@ MODULE_DEVICE_TABLE(pnp_card, snd_ad1816a_pnpids); | |||
| 99 | #define DRIVER_NAME "snd-card-ad1816a" | 94 | #define DRIVER_NAME "snd-card-ad1816a" |
| 100 | 95 | ||
| 101 | 96 | ||
| 102 | static int __devinit snd_card_ad1816a_pnp(int dev, struct snd_card_ad1816a *acard, | 97 | static int __devinit snd_card_ad1816a_pnp(int dev, struct pnp_card_link *card, |
| 103 | struct pnp_card_link *card, | ||
| 104 | const struct pnp_card_device_id *id) | 98 | const struct pnp_card_device_id *id) |
| 105 | { | 99 | { |
| 106 | struct pnp_dev *pdev; | 100 | struct pnp_dev *pdev; |
| 107 | int err; | 101 | int err; |
| 108 | 102 | ||
| 109 | acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL); | 103 | pdev = pnp_request_card_device(card, id->devs[0].id, NULL); |
| 110 | if (acard->dev == NULL) | 104 | if (pdev == NULL) |
| 111 | return -EBUSY; | 105 | return -EBUSY; |
| 112 | 106 | ||
| 113 | acard->devmpu = pnp_request_card_device(card, id->devs[1].id, NULL); | ||
| 114 | if (acard->devmpu == NULL) { | ||
| 115 | mpu_port[dev] = -1; | ||
| 116 | snd_printk(KERN_WARNING PFX "MPU401 device busy, skipping.\n"); | ||
| 117 | } | ||
| 118 | |||
| 119 | pdev = acard->dev; | ||
| 120 | |||
| 121 | err = pnp_activate_dev(pdev); | 107 | err = pnp_activate_dev(pdev); |
| 122 | if (err < 0) { | 108 | if (err < 0) { |
| 123 | printk(KERN_ERR PFX "AUDIO PnP configure failure\n"); | 109 | printk(KERN_ERR PFX "AUDIO PnP configure failure\n"); |
| @@ -130,16 +116,17 @@ static int __devinit snd_card_ad1816a_pnp(int dev, struct snd_card_ad1816a *acar | |||
| 130 | dma2[dev] = pnp_dma(pdev, 1); | 116 | dma2[dev] = pnp_dma(pdev, 1); |
| 131 | irq[dev] = pnp_irq(pdev, 0); | 117 | irq[dev] = pnp_irq(pdev, 0); |
| 132 | 118 | ||
| 133 | if (acard->devmpu == NULL) | 119 | pdev = pnp_request_card_device(card, id->devs[1].id, NULL); |
| 120 | if (pdev == NULL) { | ||
| 121 | mpu_port[dev] = -1; | ||
| 122 | snd_printk(KERN_WARNING PFX "MPU401 device busy, skipping.\n"); | ||
| 134 | return 0; | 123 | return 0; |
| 135 | 124 | } | |
| 136 | pdev = acard->devmpu; | ||
| 137 | 125 | ||
| 138 | err = pnp_activate_dev(pdev); | 126 | err = pnp_activate_dev(pdev); |
| 139 | if (err < 0) { | 127 | if (err < 0) { |
| 140 | printk(KERN_ERR PFX "MPU401 PnP configure failure\n"); | 128 | printk(KERN_ERR PFX "MPU401 PnP configure failure\n"); |
| 141 | mpu_port[dev] = -1; | 129 | mpu_port[dev] = -1; |
| 142 | acard->devmpu = NULL; | ||
| 143 | } else { | 130 | } else { |
| 144 | mpu_port[dev] = pnp_port_start(pdev, 0); | 131 | mpu_port[dev] = pnp_port_start(pdev, 0); |
| 145 | mpu_irq[dev] = pnp_irq(pdev, 0); | 132 | mpu_irq[dev] = pnp_irq(pdev, 0); |
| @@ -153,18 +140,17 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard | |||
| 153 | { | 140 | { |
| 154 | int error; | 141 | int error; |
| 155 | struct snd_card *card; | 142 | struct snd_card *card; |
| 156 | struct snd_card_ad1816a *acard; | ||
| 157 | struct snd_ad1816a *chip; | 143 | struct snd_ad1816a *chip; |
| 158 | struct snd_opl3 *opl3; | 144 | struct snd_opl3 *opl3; |
| 159 | struct snd_timer *timer; | 145 | struct snd_timer *timer; |
| 160 | 146 | ||
| 161 | error = snd_card_create(index[dev], id[dev], THIS_MODULE, | 147 | error = snd_card_create(index[dev], id[dev], THIS_MODULE, |
| 162 | sizeof(struct snd_card_ad1816a), &card); | 148 | sizeof(struct snd_ad1816a), &card); |
| 163 | if (error < 0) | 149 | if (error < 0) |
| 164 | return error; | 150 | return error; |
| 165 | acard = card->private_data; | 151 | chip = card->private_data; |
| 166 | 152 | ||
| 167 | if ((error = snd_card_ad1816a_pnp(dev, acard, pcard, pid))) { | 153 | if ((error = snd_card_ad1816a_pnp(dev, pcard, pid))) { |
| 168 | snd_card_free(card); | 154 | snd_card_free(card); |
| 169 | return error; | 155 | return error; |
| 170 | } | 156 | } |
| @@ -174,7 +160,7 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard | |||
| 174 | irq[dev], | 160 | irq[dev], |
| 175 | dma1[dev], | 161 | dma1[dev], |
| 176 | dma2[dev], | 162 | dma2[dev], |
| 177 | &chip)) < 0) { | 163 | chip)) < 0) { |
| 178 | snd_card_free(card); | 164 | snd_card_free(card); |
| 179 | return error; | 165 | return error; |
| 180 | } | 166 | } |
| @@ -258,13 +244,37 @@ static void __devexit snd_ad1816a_pnp_remove(struct pnp_card_link * pcard) | |||
| 258 | pnp_set_card_drvdata(pcard, NULL); | 244 | pnp_set_card_drvdata(pcard, NULL); |
| 259 | } | 245 | } |
| 260 | 246 | ||
| 247 | #ifdef CONFIG_PM | ||
| 248 | static int snd_ad1816a_pnp_suspend(struct pnp_card_link *pcard, | ||
| 249 | pm_message_t state) | ||
| 250 | { | ||
| 251 | struct snd_card *card = pnp_get_card_drvdata(pcard); | ||
| 252 | |||
| 253 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | ||
| 254 | snd_ad1816a_suspend(card->private_data); | ||
| 255 | return 0; | ||
| 256 | } | ||
| 257 | |||
| 258 | static int snd_ad1816a_pnp_resume(struct pnp_card_link *pcard) | ||
| 259 | { | ||
| 260 | struct snd_card *card = pnp_get_card_drvdata(pcard); | ||
| 261 | |||
| 262 | snd_ad1816a_resume(card->private_data); | ||
| 263 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
| 264 | return 0; | ||
| 265 | } | ||
| 266 | #endif | ||
| 267 | |||
| 261 | static struct pnp_card_driver ad1816a_pnpc_driver = { | 268 | static struct pnp_card_driver ad1816a_pnpc_driver = { |
| 262 | .flags = PNP_DRIVER_RES_DISABLE, | 269 | .flags = PNP_DRIVER_RES_DISABLE, |
| 263 | .name = "ad1816a", | 270 | .name = "ad1816a", |
| 264 | .id_table = snd_ad1816a_pnpids, | 271 | .id_table = snd_ad1816a_pnpids, |
| 265 | .probe = snd_ad1816a_pnp_detect, | 272 | .probe = snd_ad1816a_pnp_detect, |
| 266 | .remove = __devexit_p(snd_ad1816a_pnp_remove), | 273 | .remove = __devexit_p(snd_ad1816a_pnp_remove), |
| 267 | /* FIXME: suspend/resume */ | 274 | #ifdef CONFIG_PM |
| 275 | .suspend = snd_ad1816a_pnp_suspend, | ||
| 276 | .resume = snd_ad1816a_pnp_resume, | ||
| 277 | #endif | ||
| 268 | }; | 278 | }; |
| 269 | 279 | ||
| 270 | static int __init alsa_card_ad1816a_init(void) | 280 | static int __init alsa_card_ad1816a_init(void) |
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c index 177eed3271bc..db64df6023e0 100644 --- a/sound/isa/ad1816a/ad1816a_lib.c +++ b/sound/isa/ad1816a/ad1816a_lib.c | |||
| @@ -491,7 +491,7 @@ static int snd_ad1816a_capture_close(struct snd_pcm_substream *substream) | |||
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | 493 | ||
| 494 | static void __devinit snd_ad1816a_init(struct snd_ad1816a *chip) | 494 | static void snd_ad1816a_init(struct snd_ad1816a *chip) |
| 495 | { | 495 | { |
| 496 | unsigned long flags; | 496 | unsigned long flags; |
| 497 | 497 | ||
| @@ -511,6 +511,32 @@ static void __devinit snd_ad1816a_init(struct snd_ad1816a *chip) | |||
| 511 | spin_unlock_irqrestore(&chip->lock, flags); | 511 | spin_unlock_irqrestore(&chip->lock, flags); |
| 512 | } | 512 | } |
| 513 | 513 | ||
| 514 | #ifdef CONFIG_PM | ||
| 515 | void snd_ad1816a_suspend(struct snd_ad1816a *chip) | ||
| 516 | { | ||
| 517 | int reg; | ||
| 518 | unsigned long flags; | ||
| 519 | |||
| 520 | snd_pcm_suspend_all(chip->pcm); | ||
| 521 | spin_lock_irqsave(&chip->lock, flags); | ||
| 522 | for (reg = 0; reg < 48; reg++) | ||
| 523 | chip->image[reg] = snd_ad1816a_read(chip, reg); | ||
| 524 | spin_unlock_irqrestore(&chip->lock, flags); | ||
| 525 | } | ||
| 526 | |||
| 527 | void snd_ad1816a_resume(struct snd_ad1816a *chip) | ||
| 528 | { | ||
| 529 | int reg; | ||
| 530 | unsigned long flags; | ||
| 531 | |||
| 532 | snd_ad1816a_init(chip); | ||
| 533 | spin_lock_irqsave(&chip->lock, flags); | ||
| 534 | for (reg = 0; reg < 48; reg++) | ||
| 535 | snd_ad1816a_write(chip, reg, chip->image[reg]); | ||
| 536 | spin_unlock_irqrestore(&chip->lock, flags); | ||
| 537 | } | ||
| 538 | #endif | ||
| 539 | |||
| 514 | static int __devinit snd_ad1816a_probe(struct snd_ad1816a *chip) | 540 | static int __devinit snd_ad1816a_probe(struct snd_ad1816a *chip) |
| 515 | { | 541 | { |
| 516 | unsigned long flags; | 542 | unsigned long flags; |
| @@ -548,7 +574,6 @@ static int snd_ad1816a_free(struct snd_ad1816a *chip) | |||
| 548 | snd_dma_disable(chip->dma2); | 574 | snd_dma_disable(chip->dma2); |
| 549 | free_dma(chip->dma2); | 575 | free_dma(chip->dma2); |
| 550 | } | 576 | } |
| 551 | kfree(chip); | ||
| 552 | return 0; | 577 | return 0; |
| 553 | } | 578 | } |
| 554 | 579 | ||
| @@ -573,19 +598,13 @@ static const char __devinit *snd_ad1816a_chip_id(struct snd_ad1816a *chip) | |||
| 573 | 598 | ||
| 574 | int __devinit snd_ad1816a_create(struct snd_card *card, | 599 | int __devinit snd_ad1816a_create(struct snd_card *card, |
| 575 | unsigned long port, int irq, int dma1, int dma2, | 600 | unsigned long port, int irq, int dma1, int dma2, |
| 576 | struct snd_ad1816a **rchip) | 601 | struct snd_ad1816a *chip) |
| 577 | { | 602 | { |
| 578 | static struct snd_device_ops ops = { | 603 | static struct snd_device_ops ops = { |
| 579 | .dev_free = snd_ad1816a_dev_free, | 604 | .dev_free = snd_ad1816a_dev_free, |
| 580 | }; | 605 | }; |
| 581 | int error; | 606 | int error; |
| 582 | struct snd_ad1816a *chip; | ||
| 583 | |||
| 584 | *rchip = NULL; | ||
| 585 | 607 | ||
| 586 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
| 587 | if (chip == NULL) | ||
| 588 | return -ENOMEM; | ||
| 589 | chip->irq = -1; | 608 | chip->irq = -1; |
| 590 | chip->dma1 = -1; | 609 | chip->dma1 = -1; |
| 591 | chip->dma2 = -1; | 610 | chip->dma2 = -1; |
| @@ -631,7 +650,6 @@ int __devinit snd_ad1816a_create(struct snd_card *card, | |||
| 631 | return error; | 650 | return error; |
| 632 | } | 651 | } |
| 633 | 652 | ||
| 634 | *rchip = chip; | ||
| 635 | return 0; | 653 | return 0; |
| 636 | } | 654 | } |
| 637 | 655 | ||
diff --git a/sound/isa/cmi8328.c b/sound/isa/cmi8328.c new file mode 100644 index 000000000000..bde60139bb95 --- /dev/null +++ b/sound/isa/cmi8328.c | |||
| @@ -0,0 +1,483 @@ | |||
| 1 | /* | ||
| 2 | * Driver for C-Media CMI8328-based soundcards, such as AudioExcel AV500 | ||
| 3 | * Copyright (c) 2012 Ondrej Zary | ||
| 4 | * | ||
| 5 | * AudioExcel AV500 card consists of: | ||
| 6 | * - CMI8328 - main chip (SB Pro emulation, gameport, OPL3, MPU401, CD-ROM) | ||
| 7 | * - CS4231A - WSS codec | ||
| 8 | * - Dream SAM9233+GMS950400+RAM+ROM: Wavetable MIDI, connected to MPU401 | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/init.h> | ||
| 12 | #include <linux/isa.h> | ||
| 13 | #include <linux/module.h> | ||
| 14 | #include <linux/gameport.h> | ||
| 15 | #include <asm/dma.h> | ||
| 16 | #include <sound/core.h> | ||
| 17 | #include <sound/wss.h> | ||
| 18 | #include <sound/opl3.h> | ||
| 19 | #include <sound/mpu401.h> | ||
| 20 | #define SNDRV_LEGACY_FIND_FREE_IOPORT | ||
| 21 | #define SNDRV_LEGACY_FIND_FREE_IRQ | ||
| 22 | #define SNDRV_LEGACY_FIND_FREE_DMA | ||
| 23 | #include <sound/initval.h> | ||
| 24 | |||
| 25 | MODULE_AUTHOR("Ondrej Zary <linux@rainbow-software.org>"); | ||
| 26 | MODULE_DESCRIPTION("C-Media CMI8328"); | ||
| 27 | MODULE_LICENSE("GPL"); | ||
| 28 | |||
| 29 | #if defined(CONFIG_GAMEPORT) || defined(CONFIG_GAMEPORT_MODULE) | ||
| 30 | #define SUPPORT_JOYSTICK 1 | ||
| 31 | #endif | ||
| 32 | |||
| 33 | /* I/O port is configured by jumpers on the card to one of these */ | ||
| 34 | static int cmi8328_ports[] = { 0x530, 0xe80, 0xf40, 0x604 }; | ||
| 35 | #define CMI8328_MAX ARRAY_SIZE(cmi8328_ports) | ||
| 36 | |||
| 37 | static int index[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = -1}; | ||
| 38 | static char *id[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = NULL}; | ||
| 39 | static long port[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = SNDRV_AUTO_PORT}; | ||
| 40 | static int irq[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = SNDRV_AUTO_IRQ}; | ||
| 41 | static int dma1[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = SNDRV_AUTO_DMA}; | ||
| 42 | static int dma2[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = SNDRV_AUTO_DMA}; | ||
| 43 | static long mpuport[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = SNDRV_AUTO_PORT}; | ||
| 44 | static int mpuirq[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = SNDRV_AUTO_IRQ}; | ||
| 45 | #ifdef SUPPORT_JOYSTICK | ||
| 46 | static bool gameport[CMI8328_MAX] = {[0 ... (CMI8328_MAX-1)] = true}; | ||
| 47 | #endif | ||
| 48 | |||
| 49 | module_param_array(index, int, NULL, 0444); | ||
| 50 | MODULE_PARM_DESC(index, "Index value for CMI8328 soundcard."); | ||
| 51 | module_param_array(id, charp, NULL, 0444); | ||
| 52 | MODULE_PARM_DESC(id, "ID string for CMI8328 soundcard."); | ||
| 53 | |||
| 54 | module_param_array(port, long, NULL, 0444); | ||
| 55 | MODULE_PARM_DESC(port, "Port # for CMI8328 driver."); | ||
| 56 | module_param_array(irq, int, NULL, 0444); | ||
| 57 | MODULE_PARM_DESC(irq, "IRQ # for CMI8328 driver."); | ||
| 58 | module_param_array(dma1, int, NULL, 0444); | ||
| 59 | MODULE_PARM_DESC(dma1, "DMA1 for CMI8328 driver."); | ||
| 60 | module_param_array(dma2, int, NULL, 0444); | ||
| 61 | MODULE_PARM_DESC(dma2, "DMA2 for CMI8328 driver."); | ||
| 62 | |||
| 63 | module_param_array(mpuport, long, NULL, 0444); | ||
| 64 | MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8328 driver."); | ||
| 65 | module_param_array(mpuirq, int, NULL, 0444); | ||
| 66 | MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8328 MPU-401 port."); | ||
| 67 | #ifdef SUPPORT_JOYSTICK | ||
| 68 | module_param_array(gameport, bool, NULL, 0444); | ||
| 69 | MODULE_PARM_DESC(gameport, "Enable gameport."); | ||
| 70 | #endif | ||
| 71 | |||
| 72 | struct snd_cmi8328 { | ||
| 73 | u16 port; | ||
| 74 | u8 cfg[3]; | ||
| 75 | u8 wss_cfg; | ||
| 76 | struct snd_card *card; | ||
| 77 | struct snd_wss *wss; | ||
| 78 | #ifdef SUPPORT_JOYSTICK | ||
| 79 | struct gameport *gameport; | ||
| 80 | #endif | ||
| 81 | }; | ||
| 82 | |||
| 83 | /* CMI8328 configuration registers */ | ||
| 84 | #define CFG1 0x61 | ||
| 85 | #define CFG1_SB_DISABLE (1 << 0) | ||
| 86 | #define CFG1_GAMEPORT (1 << 1) | ||
| 87 | /* | ||
| 88 | * bit 0: SB: 0=enabled, 1=disabled | ||
| 89 | * bit 1: gameport: 0=disabled, 1=enabled | ||
| 90 | * bits 2-4: SB IRQ: 001=3, 010=5, 011=7, 100=9, 101=10, 110=11 | ||
| 91 | * bits 5-6: SB DMA: 00=disabled (when SB disabled), 01=DMA0, 10=DMA1, 11=DMA3 | ||
| 92 | * bit 7: SB port: 0=0x220, 1=0x240 | ||
| 93 | */ | ||
| 94 | #define CFG2 0x62 | ||
| 95 | #define CFG2_MPU_ENABLE (1 << 2) | ||
| 96 | /* | ||
| 97 | * bits 0-1: CD-ROM mode: 00=disabled, 01=Panasonic, 10=Sony/Mitsumi/Wearnes, | ||
| 98 | 11=IDE | ||
| 99 | * bit 2: MPU401: 0=disabled, 1=enabled | ||
| 100 | * bits 3-4: MPU401 IRQ: 00=3, 01=5, 10=7, 11=9, | ||
| 101 | * bits 5-7: MPU401 port: 000=0x300, 001=0x310, 010=0x320, 011=0x330, 100=0x332, | ||
| 102 | 101=0x334, 110=0x336 | ||
| 103 | */ | ||
| 104 | #define CFG3 0x63 | ||
| 105 | /* | ||
| 106 | * bits 0-2: CD-ROM IRQ: 000=disabled, 001=3, 010=5, 011=7, 100=9, 101=10, | ||
| 107 | 110=11 | ||
| 108 | * bits 3-4: CD-ROM DMA: 00=disabled, 01=DMA0, 10=DMA1, 11=DMA3 | ||
| 109 | * bits 5-7: CD-ROM port: 000=0x300, 001=0x310, 010=0x320, 011=0x330, 100=0x340, | ||
| 110 | 101=0x350, 110=0x360, 111=0x370 | ||
| 111 | */ | ||
| 112 | |||
| 113 | static u8 snd_cmi8328_cfg_read(u16 port, u8 reg) | ||
| 114 | { | ||
| 115 | outb(0x43, port + 3); | ||
| 116 | outb(0x21, port + 3); | ||
| 117 | outb(reg, port + 3); | ||
| 118 | return inb(port); | ||
| 119 | } | ||
| 120 | |||
| 121 | static void snd_cmi8328_cfg_write(u16 port, u8 reg, u8 val) | ||
| 122 | { | ||
| 123 | outb(0x43, port + 3); | ||
| 124 | outb(0x21, port + 3); | ||
| 125 | outb(reg, port + 3); | ||
| 126 | outb(val, port + 3); /* yes, value goes to the same port as index */ | ||
| 127 | } | ||
| 128 | |||
| 129 | static void snd_cmi8328_cfg_save(u16 port, u8 cfg[]) | ||
| 130 | { | ||
| 131 | cfg[0] = snd_cmi8328_cfg_read(port, CFG1); | ||
| 132 | cfg[1] = snd_cmi8328_cfg_read(port, CFG2); | ||
| 133 | cfg[2] = snd_cmi8328_cfg_read(port, CFG3); | ||
| 134 | } | ||
| 135 | |||
| 136 | static void snd_cmi8328_cfg_restore(u16 port, u8 cfg[]) | ||
| 137 | { | ||
| 138 | snd_cmi8328_cfg_write(port, CFG1, cfg[0]); | ||
| 139 | snd_cmi8328_cfg_write(port, CFG2, cfg[1]); | ||
| 140 | snd_cmi8328_cfg_write(port, CFG3, cfg[2]); | ||
| 141 | } | ||
| 142 | |||
| 143 | static int __devinit snd_cmi8328_mixer(struct snd_wss *chip) | ||
| 144 | { | ||
| 145 | struct snd_card *card; | ||
| 146 | struct snd_ctl_elem_id id1, id2; | ||
| 147 | int err; | ||
| 148 | |||
| 149 | card = chip->card; | ||
| 150 | |||
| 151 | memset(&id1, 0, sizeof(id1)); | ||
| 152 | memset(&id2, 0, sizeof(id2)); | ||
| 153 | id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
| 154 | /* rename AUX0 switch to CD */ | ||
| 155 | strcpy(id1.name, "Aux Playback Switch"); | ||
| 156 | strcpy(id2.name, "CD Playback Switch"); | ||
| 157 | err = snd_ctl_rename_id(card, &id1, &id2); | ||
| 158 | if (err < 0) { | ||
| 159 | snd_printk(KERN_ERR "error renaming control\n"); | ||
| 160 | return err; | ||
| 161 | } | ||
| 162 | /* rename AUX0 volume to CD */ | ||
| 163 | strcpy(id1.name, "Aux Playback Volume"); | ||
| 164 | strcpy(id2.name, "CD Playback Volume"); | ||
| 165 | err = snd_ctl_rename_id(card, &id1, &id2); | ||
| 166 | if (err < 0) { | ||
| 167 | snd_printk(KERN_ERR "error renaming control\n"); | ||
| 168 | return err; | ||
| 169 | } | ||
| 170 | /* rename AUX1 switch to Synth */ | ||
| 171 | strcpy(id1.name, "Aux Playback Switch"); | ||
| 172 | id1.index = 1; | ||
| 173 | strcpy(id2.name, "Synth Playback Switch"); | ||
| 174 | err = snd_ctl_rename_id(card, &id1, &id2); | ||
| 175 | if (err < 0) { | ||
| 176 | snd_printk(KERN_ERR "error renaming control\n"); | ||
| 177 | return err; | ||
| 178 | } | ||
| 179 | /* rename AUX1 volume to Synth */ | ||
| 180 | strcpy(id1.name, "Aux Playback Volume"); | ||
| 181 | id1.index = 1; | ||
| 182 | strcpy(id2.name, "Synth Playback Volume"); | ||
| 183 | err = snd_ctl_rename_id(card, &id1, &id2); | ||
| 184 | if (err < 0) { | ||
| 185 | snd_printk(KERN_ERR "error renaming control\n"); | ||
| 186 | return err; | ||
| 187 | } | ||
| 188 | |||
| 189 | return 0; | ||
| 190 | } | ||
| 191 | |||
| 192 | /* find index of an item in "-1"-ended array */ | ||
| 193 | int array_find(int array[], int item) | ||
| 194 | { | ||
| 195 | int i; | ||
| 196 | |||
| 197 | for (i = 0; array[i] != -1; i++) | ||
| 198 | if (array[i] == item) | ||
| 199 | return i; | ||
| 200 | |||
| 201 | return -1; | ||
| 202 | } | ||
| 203 | /* the same for long */ | ||
| 204 | int array_find_l(long array[], long item) | ||
| 205 | { | ||
| 206 | int i; | ||
| 207 | |||
| 208 | for (i = 0; array[i] != -1; i++) | ||
| 209 | if (array[i] == item) | ||
| 210 | return i; | ||
| 211 | |||
| 212 | return -1; | ||
| 213 | } | ||
| 214 | |||
| 215 | static int __devinit snd_cmi8328_probe(struct device *pdev, unsigned int ndev) | ||
| 216 | { | ||
| 217 | struct snd_card *card; | ||
| 218 | struct snd_opl3 *opl3; | ||
| 219 | struct snd_cmi8328 *cmi; | ||
| 220 | #ifdef SUPPORT_JOYSTICK | ||
| 221 | struct resource *res; | ||
| 222 | #endif | ||
| 223 | int err, pos; | ||
| 224 | static long mpu_ports[] = { 0x330, 0x300, 0x310, 0x320, 0x332, 0x334, | ||
| 225 | 0x336, -1 }; | ||
| 226 | static u8 mpu_port_bits[] = { 3, 0, 1, 2, 4, 5, 6 }; | ||
| 227 | static int mpu_irqs[] = { 9, 7, 5, 3, -1 }; | ||
| 228 | static u8 mpu_irq_bits[] = { 3, 2, 1, 0 }; | ||
| 229 | static int irqs[] = { 9, 10, 11, 7, -1 }; | ||
| 230 | static u8 irq_bits[] = { 2, 3, 4, 1 }; | ||
| 231 | static int dma1s[] = { 3, 1, 0, -1 }; | ||
| 232 | static u8 dma_bits[] = { 3, 2, 1 }; | ||
| 233 | static int dma2s[][2] = { {1, -1}, {0, -1}, {-1, -1}, {0, -1} }; | ||
| 234 | u16 port = cmi8328_ports[ndev]; | ||
| 235 | u8 val; | ||
| 236 | |||
| 237 | /* 0xff is invalid configuration (but settable - hope it isn't set) */ | ||
| 238 | if (snd_cmi8328_cfg_read(port, CFG1) == 0xff) | ||
| 239 | return -ENODEV; | ||
| 240 | /* the SB disable bit must NEVER EVER be cleared or the WSS dies */ | ||
| 241 | snd_cmi8328_cfg_write(port, CFG1, CFG1_SB_DISABLE); | ||
| 242 | if (snd_cmi8328_cfg_read(port, CFG1) != CFG1_SB_DISABLE) | ||
| 243 | return -ENODEV; | ||
| 244 | /* disable everything first */ | ||
| 245 | snd_cmi8328_cfg_write(port, CFG2, 0); /* disable CDROM and MPU401 */ | ||
| 246 | snd_cmi8328_cfg_write(port, CFG3, 0); /* disable CDROM IRQ and DMA */ | ||
| 247 | |||
| 248 | if (irq[ndev] == SNDRV_AUTO_IRQ) { | ||
| 249 | irq[ndev] = snd_legacy_find_free_irq(irqs); | ||
| 250 | if (irq[ndev] < 0) { | ||
| 251 | snd_printk(KERN_ERR "unable to find a free IRQ\n"); | ||
| 252 | return -EBUSY; | ||
| 253 | } | ||
| 254 | } | ||
| 255 | if (dma1[ndev] == SNDRV_AUTO_DMA) { | ||
| 256 | dma1[ndev] = snd_legacy_find_free_dma(dma1s); | ||
| 257 | if (dma1[ndev] < 0) { | ||
| 258 | snd_printk(KERN_ERR "unable to find a free DMA1\n"); | ||
| 259 | return -EBUSY; | ||
| 260 | } | ||
| 261 | } | ||
| 262 | if (dma2[ndev] == SNDRV_AUTO_DMA) { | ||
| 263 | dma2[ndev] = snd_legacy_find_free_dma(dma2s[dma1[ndev] % 4]); | ||
| 264 | if (dma2[ndev] < 0) { | ||
| 265 | snd_printk(KERN_WARNING "unable to find a free DMA2, full-duplex will not work\n"); | ||
| 266 | dma2[ndev] = -1; | ||
| 267 | } | ||
| 268 | } | ||
| 269 | /* configure WSS IRQ... */ | ||
| 270 | pos = array_find(irqs, irq[ndev]); | ||
| 271 | if (pos < 0) { | ||
| 272 | snd_printk(KERN_ERR "invalid IRQ %d\n", irq[ndev]); | ||
| 273 | return -EINVAL; | ||
| 274 | } | ||
| 275 | val = irq_bits[pos] << 3; | ||
| 276 | /* ...and DMA... */ | ||
| 277 | pos = array_find(dma1s, dma1[ndev]); | ||
| 278 | if (pos < 0) { | ||
| 279 | snd_printk(KERN_ERR "invalid DMA1 %d\n", dma1[ndev]); | ||
| 280 | return -EINVAL; | ||
| 281 | } | ||
| 282 | val |= dma_bits[pos]; | ||
| 283 | /* ...and DMA2 */ | ||
| 284 | if (dma2[ndev] >= 0 && dma1[ndev] != dma2[ndev]) { | ||
| 285 | pos = array_find(dma2s[dma1[ndev]], dma2[ndev]); | ||
| 286 | if (pos < 0) { | ||
| 287 | snd_printk(KERN_ERR "invalid DMA2 %d\n", dma2[ndev]); | ||
| 288 | return -EINVAL; | ||
| 289 | } | ||
| 290 | val |= 0x04; /* enable separate capture DMA */ | ||
| 291 | } | ||
| 292 | outb(val, port); | ||
| 293 | |||
| 294 | err = snd_card_create(index[ndev], id[ndev], THIS_MODULE, | ||
| 295 | sizeof(struct snd_cmi8328), &card); | ||
| 296 | if (err < 0) | ||
| 297 | return err; | ||
| 298 | cmi = card->private_data; | ||
| 299 | cmi->card = card; | ||
| 300 | cmi->port = port; | ||
| 301 | cmi->wss_cfg = val; | ||
| 302 | snd_card_set_dev(card, pdev); | ||
| 303 | |||
| 304 | err = snd_wss_create(card, port + 4, -1, irq[ndev], dma1[ndev], | ||
| 305 | dma2[ndev], WSS_HW_DETECT, 0, &cmi->wss); | ||
| 306 | if (err < 0) | ||
| 307 | goto error; | ||
| 308 | |||
| 309 | err = snd_wss_pcm(cmi->wss, 0, NULL); | ||
| 310 | if (err < 0) | ||
| 311 | goto error; | ||
| 312 | |||
| 313 | err = snd_wss_mixer(cmi->wss); | ||
| 314 | if (err < 0) | ||
| 315 | goto error; | ||
| 316 | err = snd_cmi8328_mixer(cmi->wss); | ||
| 317 | if (err < 0) | ||
| 318 | goto error; | ||
| 319 | |||
| 320 | if (snd_wss_timer(cmi->wss, 0, NULL) < 0) | ||
| 321 | snd_printk(KERN_WARNING "error initializing WSS timer\n"); | ||
| 322 | |||
| 323 | if (mpuport[ndev] == SNDRV_AUTO_PORT) { | ||
| 324 | mpuport[ndev] = snd_legacy_find_free_ioport(mpu_ports, 2); | ||
| 325 | if (mpuport[ndev] < 0) | ||
| 326 | snd_printk(KERN_ERR "unable to find a free MPU401 port\n"); | ||
| 327 | } | ||
| 328 | if (mpuirq[ndev] == SNDRV_AUTO_IRQ) { | ||
| 329 | mpuirq[ndev] = snd_legacy_find_free_irq(mpu_irqs); | ||
| 330 | if (mpuirq[ndev] < 0) | ||
| 331 | snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n"); | ||
| 332 | } | ||
| 333 | /* enable and configure MPU401 */ | ||
| 334 | if (mpuport[ndev] > 0 && mpuirq[ndev] > 0) { | ||
| 335 | val = CFG2_MPU_ENABLE; | ||
| 336 | pos = array_find_l(mpu_ports, mpuport[ndev]); | ||
| 337 | if (pos < 0) | ||
| 338 | snd_printk(KERN_WARNING "invalid MPU401 port 0x%lx\n", | ||
| 339 | mpuport[ndev]); | ||
| 340 | else { | ||
| 341 | val |= mpu_port_bits[pos] << 5; | ||
| 342 | pos = array_find(mpu_irqs, mpuirq[ndev]); | ||
| 343 | if (pos < 0) | ||
| 344 | snd_printk(KERN_WARNING "invalid MPU401 IRQ %d\n", | ||
| 345 | mpuirq[ndev]); | ||
| 346 | else { | ||
| 347 | val |= mpu_irq_bits[pos] << 3; | ||
| 348 | snd_cmi8328_cfg_write(port, CFG2, val); | ||
| 349 | if (snd_mpu401_uart_new(card, 0, | ||
| 350 | MPU401_HW_MPU401, mpuport[ndev], | ||
| 351 | 0, mpuirq[ndev], NULL) < 0) | ||
| 352 | snd_printk(KERN_ERR "error initializing MPU401\n"); | ||
| 353 | } | ||
| 354 | } | ||
| 355 | } | ||
| 356 | /* OPL3 is hardwired to 0x388 and cannot be disabled */ | ||
| 357 | if (snd_opl3_create(card, 0x388, 0x38a, OPL3_HW_AUTO, 0, &opl3) < 0) | ||
| 358 | snd_printk(KERN_ERR "error initializing OPL3\n"); | ||
| 359 | else | ||
| 360 | if (snd_opl3_hwdep_new(opl3, 0, 1, NULL) < 0) | ||
| 361 | snd_printk(KERN_WARNING "error initializing OPL3 hwdep\n"); | ||
| 362 | |||
| 363 | strcpy(card->driver, "CMI8328"); | ||
| 364 | strcpy(card->shortname, "C-Media CMI8328"); | ||
| 365 | sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d,%d", | ||
| 366 | card->shortname, cmi->wss->port, irq[ndev], dma1[ndev], | ||
| 367 | (dma2[ndev] >= 0) ? dma2[ndev] : dma1[ndev]); | ||
| 368 | |||
| 369 | dev_set_drvdata(pdev, card); | ||
| 370 | err = snd_card_register(card); | ||
| 371 | if (err < 0) | ||
| 372 | goto error; | ||
| 373 | #ifdef SUPPORT_JOYSTICK | ||
| 374 | if (!gameport[ndev]) | ||
| 375 | return 0; | ||
| 376 | /* gameport is hardwired to 0x200 */ | ||
| 377 | res = request_region(0x200, 8, "CMI8328 gameport"); | ||
| 378 | if (!res) | ||
| 379 | snd_printk(KERN_WARNING "unable to allocate gameport I/O port\n"); | ||
| 380 | else { | ||
| 381 | struct gameport *gp = cmi->gameport = gameport_allocate_port(); | ||
| 382 | if (!cmi->gameport) | ||
| 383 | release_and_free_resource(res); | ||
| 384 | else { | ||
| 385 | gameport_set_name(gp, "CMI8328 Gameport"); | ||
| 386 | gameport_set_phys(gp, "%s/gameport0", dev_name(pdev)); | ||
| 387 | gameport_set_dev_parent(gp, pdev); | ||
| 388 | gp->io = 0x200; | ||
| 389 | gameport_set_port_data(gp, res); | ||
| 390 | /* Enable gameport */ | ||
| 391 | snd_cmi8328_cfg_write(port, CFG1, | ||
| 392 | CFG1_SB_DISABLE | CFG1_GAMEPORT); | ||
| 393 | gameport_register_port(gp); | ||
| 394 | } | ||
| 395 | } | ||
| 396 | #endif | ||
| 397 | return 0; | ||
| 398 | error: | ||
| 399 | snd_card_free(card); | ||
| 400 | |||
| 401 | return err; | ||
| 402 | } | ||
| 403 | |||
| 404 | static int __devexit snd_cmi8328_remove(struct device *pdev, unsigned int dev) | ||
| 405 | { | ||
| 406 | struct snd_card *card = dev_get_drvdata(pdev); | ||
| 407 | struct snd_cmi8328 *cmi = card->private_data; | ||
| 408 | |||
| 409 | #ifdef SUPPORT_JOYSTICK | ||
| 410 | if (cmi->gameport) { | ||
| 411 | struct resource *res = gameport_get_port_data(cmi->gameport); | ||
| 412 | gameport_unregister_port(cmi->gameport); | ||
| 413 | release_and_free_resource(res); | ||
| 414 | } | ||
| 415 | #endif | ||
| 416 | /* disable everything */ | ||
| 417 | snd_cmi8328_cfg_write(cmi->port, CFG1, CFG1_SB_DISABLE); | ||
| 418 | snd_cmi8328_cfg_write(cmi->port, CFG2, 0); | ||
| 419 | snd_cmi8328_cfg_write(cmi->port, CFG3, 0); | ||
| 420 | snd_card_free(card); | ||
| 421 | dev_set_drvdata(pdev, NULL); | ||
| 422 | return 0; | ||
| 423 | } | ||
| 424 | |||
| 425 | #ifdef CONFIG_PM | ||
| 426 | static int snd_cmi8328_suspend(struct device *pdev, unsigned int n, | ||
| 427 | pm_message_t state) | ||
| 428 | { | ||
| 429 | struct snd_card *card = dev_get_drvdata(pdev); | ||
| 430 | struct snd_cmi8328 *cmi; | ||
| 431 | |||
| 432 | if (!card) /* ignore absent devices */ | ||
| 433 | return 0; | ||
| 434 | cmi = card->private_data; | ||
| 435 | snd_cmi8328_cfg_save(cmi->port, cmi->cfg); | ||
| 436 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | ||
| 437 | snd_pcm_suspend_all(cmi->wss->pcm); | ||
| 438 | cmi->wss->suspend(cmi->wss); | ||
| 439 | |||
| 440 | return 0; | ||
| 441 | } | ||
| 442 | |||
| 443 | static int snd_cmi8328_resume(struct device *pdev, unsigned int n) | ||
| 444 | { | ||
| 445 | struct snd_card *card = dev_get_drvdata(pdev); | ||
| 446 | struct snd_cmi8328 *cmi; | ||
| 447 | |||
| 448 | if (!card) /* ignore absent devices */ | ||
| 449 | return 0; | ||
| 450 | cmi = card->private_data; | ||
| 451 | snd_cmi8328_cfg_restore(cmi->port, cmi->cfg); | ||
| 452 | outb(cmi->wss_cfg, cmi->port); | ||
| 453 | cmi->wss->resume(cmi->wss); | ||
| 454 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
| 455 | |||
| 456 | return 0; | ||
| 457 | } | ||
| 458 | #endif | ||
| 459 | |||
| 460 | static struct isa_driver snd_cmi8328_driver = { | ||
| 461 | .probe = snd_cmi8328_probe, | ||
| 462 | .remove = __devexit_p(snd_cmi8328_remove), | ||
| 463 | #ifdef CONFIG_PM | ||
| 464 | .suspend = snd_cmi8328_suspend, | ||
| 465 | .resume = snd_cmi8328_resume, | ||
| 466 | #endif | ||
| 467 | .driver = { | ||
| 468 | .name = "cmi8328" | ||
| 469 | }, | ||
| 470 | }; | ||
| 471 | |||
| 472 | static int __init alsa_card_cmi8328_init(void) | ||
| 473 | { | ||
| 474 | return isa_register_driver(&snd_cmi8328_driver, CMI8328_MAX); | ||
| 475 | } | ||
| 476 | |||
| 477 | static void __exit alsa_card_cmi8328_exit(void) | ||
| 478 | { | ||
| 479 | isa_unregister_driver(&snd_cmi8328_driver); | ||
| 480 | } | ||
| 481 | |||
| 482 | module_init(alsa_card_cmi8328_init) | ||
| 483 | module_exit(alsa_card_cmi8328_exit) | ||
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c index a76bc8d27c1d..3fc8b66fd167 100644 --- a/sound/isa/gus/interwave.c +++ b/sound/isa/gus/interwave.c | |||
| @@ -443,9 +443,8 @@ static void __devinit snd_interwave_detect_memory(struct snd_gus_card * gus) | |||
| 443 | for (i = 0; i < 8; ++i) | 443 | for (i = 0; i < 8; ++i) |
| 444 | iwave[i] = snd_gf1_peek(gus, bank_pos + i); | 444 | iwave[i] = snd_gf1_peek(gus, bank_pos + i); |
| 445 | #ifdef CONFIG_SND_DEBUG_ROM | 445 | #ifdef CONFIG_SND_DEBUG_ROM |
| 446 | printk(KERN_DEBUG "ROM at 0x%06x = %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", bank_pos, | 446 | printk(KERN_DEBUG "ROM at 0x%06x = %*phC\n", bank_pos, |
| 447 | iwave[0], iwave[1], iwave[2], iwave[3], | 447 | 8, iwave); |
| 448 | iwave[4], iwave[5], iwave[6], iwave[7]); | ||
| 449 | #endif | 448 | #endif |
| 450 | if (strncmp(iwave, "INTRWAVE", 8)) | 449 | if (strncmp(iwave, "INTRWAVE", 8)) |
| 451 | continue; /* first check */ | 450 | continue; /* first check */ |
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index c24594c866f4..3d1afb612b35 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <sound/opl4.h> | 37 | #include <sound/opl4.h> |
| 38 | #include <sound/control.h> | 38 | #include <sound/control.h> |
| 39 | #include <sound/info.h> | 39 | #include <sound/info.h> |
| 40 | #define SNDRV_LEGACY_FIND_FREE_IOPORT | ||
| 40 | #define SNDRV_LEGACY_FIND_FREE_IRQ | 41 | #define SNDRV_LEGACY_FIND_FREE_IRQ |
| 41 | #define SNDRV_LEGACY_FIND_FREE_DMA | 42 | #define SNDRV_LEGACY_FIND_FREE_DMA |
| 42 | #include <sound/initval.h> | 43 | #include <sound/initval.h> |
| @@ -770,20 +771,6 @@ static int __devinit snd_miro_mixer(struct snd_card *card, | |||
| 770 | return 0; | 771 | return 0; |
| 771 | } | 772 | } |
| 772 | 773 | ||
| 773 | static long snd_legacy_find_free_ioport(long *port_table, long size) | ||
| 774 | { | ||
| 775 | while (*port_table != -1) { | ||
| 776 | struct resource *res; | ||
| 777 | if ((res = request_region(*port_table, size, | ||
| 778 | "ALSA test")) != NULL) { | ||
| 779 | release_and_free_resource(res); | ||
| 780 | return *port_table; | ||
| 781 | } | ||
| 782 | port_table++; | ||
| 783 | } | ||
| 784 | return -1; | ||
| 785 | } | ||
| 786 | |||
| 787 | static int __devinit snd_miro_init(struct snd_miro *chip, | 774 | static int __devinit snd_miro_init(struct snd_miro *chip, |
| 788 | unsigned short hardware) | 775 | unsigned short hardware) |
| 789 | { | 776 | { |
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index f8fbe22515c9..2899c9fd1ceb 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #ifndef OPTi93X | 39 | #ifndef OPTi93X |
| 40 | #include <sound/opl4.h> | 40 | #include <sound/opl4.h> |
| 41 | #endif | 41 | #endif |
| 42 | #define SNDRV_LEGACY_FIND_FREE_IOPORT | ||
| 42 | #define SNDRV_LEGACY_FIND_FREE_IRQ | 43 | #define SNDRV_LEGACY_FIND_FREE_IRQ |
| 43 | #define SNDRV_LEGACY_FIND_FREE_DMA | 44 | #define SNDRV_LEGACY_FIND_FREE_DMA |
| 44 | #include <sound/initval.h> | 45 | #include <sound/initval.h> |
| @@ -185,19 +186,6 @@ static char * snd_opti9xx_names[] = { | |||
| 185 | "82C930", "82C931", "82C933" | 186 | "82C930", "82C931", "82C933" |
| 186 | }; | 187 | }; |
| 187 | 188 | ||
| 188 | |||
| 189 | static long __devinit snd_legacy_find_free_ioport(long *port_table, long size) | ||
| 190 | { | ||
| 191 | while (*port_table != -1) { | ||
| 192 | if (request_region(*port_table, size, "ALSA test")) { | ||
| 193 | release_region(*port_table, size); | ||
| 194 | return *port_table; | ||
| 195 | } | ||
| 196 | port_table++; | ||
| 197 | } | ||
| 198 | return -1; | ||
| 199 | } | ||
| 200 | |||
| 201 | static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, | 189 | static int __devinit snd_opti9xx_init(struct snd_opti9xx *chip, |
| 202 | unsigned short hardware) | 190 | unsigned short hardware) |
| 203 | { | 191 | { |
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c index 71887874679c..2aae6a0efbcd 100644 --- a/sound/isa/sb/emu8000.c +++ b/sound/isa/sb/emu8000.c | |||
| @@ -417,9 +417,6 @@ size_dram(struct snd_emu8000 *emu) | |||
| 417 | EMU8000_SMLD_READ(emu); /* discard stale data */ | 417 | EMU8000_SMLD_READ(emu); /* discard stale data */ |
| 418 | if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2) | 418 | if (EMU8000_SMLD_READ(emu) != UNIQUE_ID2) |
| 419 | break; /* no memory at this address */ | 419 | break; /* no memory at this address */ |
| 420 | |||
| 421 | detected_size = size; | ||
| 422 | |||
| 423 | snd_emu8000_read_wait(emu); | 420 | snd_emu8000_read_wait(emu); |
| 424 | 421 | ||
| 425 | /* | 422 | /* |
| @@ -432,6 +429,18 @@ size_dram(struct snd_emu8000 *emu) | |||
| 432 | if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1) | 429 | if (EMU8000_SMLD_READ(emu) != UNIQUE_ID1) |
| 433 | break; /* we must have wrapped around */ | 430 | break; /* we must have wrapped around */ |
| 434 | snd_emu8000_read_wait(emu); | 431 | snd_emu8000_read_wait(emu); |
| 432 | |||
| 433 | /* Otherwise, it's valid memory. */ | ||
| 434 | detected_size = size + 512 * 1024; | ||
| 435 | } | ||
| 436 | |||
| 437 | /* Distinguish 512 KiB from 0. */ | ||
| 438 | if (detected_size == 0) { | ||
| 439 | snd_emu8000_read_wait(emu); | ||
| 440 | EMU8000_SMALR_WRITE(emu, EMU8000_DRAM_OFFSET); | ||
| 441 | EMU8000_SMLD_READ(emu); /* discard stale data */ | ||
| 442 | if (EMU8000_SMLD_READ(emu) == UNIQUE_ID1) | ||
| 443 | detected_size = 512 * 1024; | ||
| 435 | } | 444 | } |
| 436 | 445 | ||
| 437 | /* wait until FULL bit in SMAxW register is false */ | 446 | /* wait until FULL bit in SMAxW register is false */ |
diff --git a/sound/isa/sb/emu8000_callback.c b/sound/isa/sb/emu8000_callback.c index 344b4355be1c..72a9ac5efb40 100644 --- a/sound/isa/sb/emu8000_callback.c +++ b/sound/isa/sb/emu8000_callback.c | |||
| @@ -175,7 +175,7 @@ get_voice(struct snd_emux *emu, struct snd_emux_port *port) | |||
| 175 | hw = emu->hw; | 175 | hw = emu->hw; |
| 176 | 176 | ||
| 177 | for (i = 0; i < END; i++) { | 177 | for (i = 0; i < END; i++) { |
| 178 | best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */; | 178 | best[i].time = (unsigned int)(-1); /* XXX MAX_?INT really */ |
| 179 | best[i].voice = -1; | 179 | best[i].voice = -1; |
| 180 | } | 180 | } |
| 181 | 181 | ||
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index 405f8b6a58b5..b1bf8d4e6494 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c | |||
| @@ -538,7 +538,7 @@ munge_int32 (unsigned int src, | |||
| 538 | /* Note: we leave the upper bits in place */ | 538 | /* Note: we leave the upper bits in place */ |
| 539 | 539 | ||
| 540 | dst++; | 540 | dst++; |
| 541 | }; | 541 | } |
| 542 | return dst; | 542 | return dst; |
| 543 | }; | 543 | }; |
| 544 | 544 | ||
diff --git a/sound/last.c b/sound/last.c index 7ffc182e0844..43f222825038 100644 --- a/sound/last.c +++ b/sound/last.c | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | * | 19 | * |
| 20 | */ | 20 | */ |
| 21 | 21 | ||
| 22 | #define SNDRV_MAIN_OBJECT_FILE | ||
| 23 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 24 | #include <sound/core.h> | 23 | #include <sound/core.h> |
| 25 | 24 | ||
diff --git a/sound/oss/audio.c b/sound/oss/audio.c index 4b958b1c497c..09c932f899b8 100644 --- a/sound/oss/audio.c +++ b/sound/oss/audio.c | |||
| @@ -354,7 +354,7 @@ int audio_read(int dev, struct file *file, char __user *buf, int count) | |||
| 354 | 354 | ||
| 355 | if(copy_to_user(&(buf)[p], fixit, l)) | 355 | if(copy_to_user(&(buf)[p], fixit, l)) |
| 356 | return -EFAULT; | 356 | return -EFAULT; |
| 357 | }; | 357 | } |
| 358 | 358 | ||
| 359 | DMAbuf_rmchars(dev, buf_no, l); | 359 | DMAbuf_rmchars(dev, buf_no, l); |
| 360 | 360 | ||
diff --git a/sound/oss/opl3.c b/sound/oss/opl3.c index 407cd677950b..c5c24409ceb0 100644 --- a/sound/oss/opl3.c +++ b/sound/oss/opl3.c | |||
| @@ -1190,7 +1190,7 @@ static int opl3_init(int ioaddr, struct module *owner) | |||
| 1190 | 1190 | ||
| 1191 | for (i = 0; i < 18; i++) | 1191 | for (i = 0; i < 18; i++) |
| 1192 | pv_map[i].ioaddr = devc->left_io; | 1192 | pv_map[i].ioaddr = devc->left_io; |
| 1193 | }; | 1193 | } |
| 1194 | conf_printf2(devc->fm_info.name, ioaddr, 0, -1, -1); | 1194 | conf_printf2(devc->fm_info.name, ioaddr, 0, -1, -1); |
| 1195 | 1195 | ||
| 1196 | for (i = 0; i < SBFM_MAXINSTR; i++) | 1196 | for (i = 0; i < SBFM_MAXINSTR; i++) |
diff --git a/sound/oss/pss.c b/sound/oss/pss.c index 0f32a561f15f..145e36b2cfd0 100644 --- a/sound/oss/pss.c +++ b/sound/oss/pss.c | |||
| @@ -359,7 +359,7 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size | |||
| 359 | { | 359 | { |
| 360 | /*_____ Send the next byte */ | 360 | /*_____ Send the next byte */ |
| 361 | outw (*block++, REG (PSS_DATA)); | 361 | outw (*block++, REG (PSS_DATA)); |
| 362 | }; | 362 | } |
| 363 | count++; | 363 | count++; |
| 364 | } | 364 | } |
| 365 | 365 | ||
diff --git a/sound/oss/sb_ess.c b/sound/oss/sb_ess.c index 5c773dff5ac5..c0be085e4a20 100644 --- a/sound/oss/sb_ess.c +++ b/sound/oss/sb_ess.c | |||
| @@ -1104,15 +1104,15 @@ int ess_init(sb_devc * devc, struct address_info *hw_config) | |||
| 1104 | default: | 1104 | default: |
| 1105 | printk (KERN_ERR "Invalid esstype=%d specified\n", devc->sbmo.esstype); | 1105 | printk (KERN_ERR "Invalid esstype=%d specified\n", devc->sbmo.esstype); |
| 1106 | return 0; | 1106 | return 0; |
| 1107 | }; | 1107 | } |
| 1108 | if (submodel != -1) { | 1108 | if (submodel != -1) { |
| 1109 | devc->submodel = submodel; | 1109 | devc->submodel = submodel; |
| 1110 | sprintf (modelname, "ES%d", devc->sbmo.esstype); | 1110 | sprintf (modelname, "ES%d", devc->sbmo.esstype); |
| 1111 | chip = modelname; | 1111 | chip = modelname; |
| 1112 | }; | 1112 | } |
| 1113 | if (chip == NULL && (ess_minor & 0x0f) < 8) { | 1113 | if (chip == NULL && (ess_minor & 0x0f) < 8) { |
| 1114 | chip = "ES688"; | 1114 | chip = "ES688"; |
| 1115 | }; | 1115 | } |
| 1116 | #ifdef FKS_TEST | 1116 | #ifdef FKS_TEST |
| 1117 | FKS_test (devc); | 1117 | FKS_test (devc); |
| 1118 | #endif | 1118 | #endif |
| @@ -1122,7 +1122,7 @@ FKS_test (devc); | |||
| 1122 | */ | 1122 | */ |
| 1123 | if (chip == NULL && devc->sbmo.esstype == ESSTYPE_LIKE20) { | 1123 | if (chip == NULL && devc->sbmo.esstype == ESSTYPE_LIKE20) { |
| 1124 | chip = "ES1688"; | 1124 | chip = "ES1688"; |
| 1125 | }; | 1125 | } |
| 1126 | 1126 | ||
| 1127 | if (chip == NULL) { | 1127 | if (chip == NULL) { |
| 1128 | int type; | 1128 | int type; |
| @@ -1150,8 +1150,8 @@ FKS_test (devc); | |||
| 1150 | if ((type & 0x00ff) != ((type >> 8) & 0x00ff)) { | 1150 | if ((type & 0x00ff) != ((type >> 8) & 0x00ff)) { |
| 1151 | printk ("ess_init: Unrecognized %04x\n", type); | 1151 | printk ("ess_init: Unrecognized %04x\n", type); |
| 1152 | } | 1152 | } |
| 1153 | }; | 1153 | } |
| 1154 | }; | 1154 | } |
| 1155 | #if 0 | 1155 | #if 0 |
| 1156 | /* | 1156 | /* |
| 1157 | * this one failed: | 1157 | * this one failed: |
| @@ -1182,10 +1182,10 @@ FKS_test (devc); | |||
| 1182 | chip = "ES1788"; | 1182 | chip = "ES1788"; |
| 1183 | devc->submodel = SUBMDL_ES1788; | 1183 | devc->submodel = SUBMDL_ES1788; |
| 1184 | } | 1184 | } |
| 1185 | }; | 1185 | } |
| 1186 | if (chip == NULL) { | 1186 | if (chip == NULL) { |
| 1187 | chip = "ES1688"; | 1187 | chip = "ES1688"; |
| 1188 | }; | 1188 | } |
| 1189 | 1189 | ||
| 1190 | printk ( KERN_INFO "ESS chip %s %s%s\n" | 1190 | printk ( KERN_INFO "ESS chip %s %s%s\n" |
| 1191 | , chip | 1191 | , chip |
| @@ -1293,7 +1293,7 @@ printk(KERN_INFO "ess_set_dma_hw: dma8=%d,dma16=%d,dup=%d\n" | |||
| 1293 | default: | 1293 | default: |
| 1294 | printk(KERN_ERR "ESS1887: Invalid DMA16 %d\n", dma); | 1294 | printk(KERN_ERR "ESS1887: Invalid DMA16 %d\n", dma); |
| 1295 | return 0; | 1295 | return 0; |
| 1296 | }; | 1296 | } |
| 1297 | ess_chgmixer (devc, 0x78, 0x20, dma16_bits); | 1297 | ess_chgmixer (devc, 0x78, 0x20, dma16_bits); |
| 1298 | ess_chgmixer (devc, 0x7d, 0x07, dma_bits); | 1298 | ess_chgmixer (devc, 0x7d, 0x07, dma_bits); |
| 1299 | } | 1299 | } |
| @@ -1584,7 +1584,7 @@ printk(KERN_INFO "FKS: write mixer %x: %x\n", port, value); | |||
| 1584 | udelay(20); | 1584 | udelay(20); |
| 1585 | outb(((unsigned char) (value & 0xff)), MIXER_DATA); | 1585 | outb(((unsigned char) (value & 0xff)), MIXER_DATA); |
| 1586 | udelay(20); | 1586 | udelay(20); |
| 1587 | }; | 1587 | } |
| 1588 | spin_unlock_irqrestore(&devc->lock, flags); | 1588 | spin_unlock_irqrestore(&devc->lock, flags); |
| 1589 | } | 1589 | } |
| 1590 | 1590 | ||
| @@ -1761,7 +1761,7 @@ int ess_mixer_reset (sb_devc * devc) | |||
| 1761 | ess_chgmixer(devc, 0x7a, 0x18, 0x08); | 1761 | ess_chgmixer(devc, 0x7a, 0x18, 0x08); |
| 1762 | ess_chgmixer(devc, 0x1c, 0x07, 0x07); | 1762 | ess_chgmixer(devc, 0x1c, 0x07, 0x07); |
| 1763 | break; | 1763 | break; |
| 1764 | }; | 1764 | } |
| 1765 | /* | 1765 | /* |
| 1766 | * Call set_recmask for proper initialization | 1766 | * Call set_recmask for proper initialization |
| 1767 | */ | 1767 | */ |
diff --git a/sound/oss/sb_mixer.c b/sound/oss/sb_mixer.c index f8f3b7a66b73..acf7586aeb47 100644 --- a/sound/oss/sb_mixer.c +++ b/sound/oss/sb_mixer.c | |||
| @@ -410,7 +410,7 @@ static int set_recmask(sb_devc * devc, int mask) | |||
| 410 | case MDL_SMW: | 410 | case MDL_SMW: |
| 411 | if (devc->model == MDL_ESS && ess_set_recmask (devc, &devmask)) { | 411 | if (devc->model == MDL_ESS && ess_set_recmask (devc, &devmask)) { |
| 412 | break; | 412 | break; |
| 413 | }; | 413 | } |
| 414 | if (devmask != SOUND_MASK_MIC && | 414 | if (devmask != SOUND_MASK_MIC && |
| 415 | devmask != SOUND_MASK_LINE && | 415 | devmask != SOUND_MASK_LINE && |
| 416 | devmask != SOUND_MASK_CD) | 416 | devmask != SOUND_MASK_CD) |
| @@ -666,7 +666,7 @@ static void sb_mixer_reset(sb_devc * devc) | |||
| 666 | 666 | ||
| 667 | if (devc->model != MDL_ESS || !ess_mixer_reset (devc)) { | 667 | if (devc->model != MDL_ESS || !ess_mixer_reset (devc)) { |
| 668 | set_recmask(devc, SOUND_MASK_MIC); | 668 | set_recmask(devc, SOUND_MASK_MIC); |
| 669 | }; | 669 | } |
| 670 | } | 670 | } |
| 671 | 671 | ||
| 672 | int sb_mixer_init(sb_devc * devc, struct module *owner) | 672 | int sb_mixer_init(sb_devc * devc, struct module *owner) |
diff --git a/sound/oss/sys_timer.c b/sound/oss/sys_timer.c index 8db6aefe15e4..9f039831114c 100644 --- a/sound/oss/sys_timer.c +++ b/sound/oss/sys_timer.c | |||
| @@ -57,7 +57,7 @@ poll_def_tmr(unsigned long dummy) | |||
| 57 | { | 57 | { |
| 58 | def_tmr.expires = (1) + jiffies; | 58 | def_tmr.expires = (1) + jiffies; |
| 59 | add_timer(&def_tmr); | 59 | add_timer(&def_tmr); |
| 60 | }; | 60 | } |
| 61 | 61 | ||
| 62 | if (tmr_running) | 62 | if (tmr_running) |
| 63 | { | 63 | { |
| @@ -103,7 +103,7 @@ def_tmr_open(int dev, int mode) | |||
| 103 | { | 103 | { |
| 104 | def_tmr.expires = (1) + jiffies; | 104 | def_tmr.expires = (1) + jiffies; |
| 105 | add_timer(&def_tmr); | 105 | add_timer(&def_tmr); |
| 106 | }; | 106 | } |
| 107 | 107 | ||
| 108 | return 0; | 108 | return 0; |
| 109 | } | 109 | } |
diff --git a/sound/oss/uart6850.c b/sound/oss/uart6850.c index f3f914aa92ee..1079133dd6ab 100644 --- a/sound/oss/uart6850.c +++ b/sound/oss/uart6850.c | |||
| @@ -146,7 +146,7 @@ static int uart6850_open(int dev, int mode, | |||
| 146 | { | 146 | { |
| 147 | /* printk("Midi6850: Midi busy\n");*/ | 147 | /* printk("Midi6850: Midi busy\n");*/ |
| 148 | return -EBUSY; | 148 | return -EBUSY; |
| 149 | }; | 149 | } |
| 150 | 150 | ||
| 151 | uart6850_cmd(UART_RESET); | 151 | uart6850_cmd(UART_RESET); |
| 152 | uart6850_input_loop(); | 152 | uart6850_input_loop(); |
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index a872d0a82976..66a3bc95fb84 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
| @@ -2595,6 +2595,21 @@ static void alc650_update_jacks(struct snd_ac97 *ac97) | |||
| 2595 | shared ? 0 : 0x100); | 2595 | shared ? 0 : 0x100); |
| 2596 | } | 2596 | } |
| 2597 | 2597 | ||
| 2598 | static int alc650_swap_surround_put(struct snd_kcontrol *kcontrol, | ||
| 2599 | struct snd_ctl_elem_value *ucontrol) | ||
| 2600 | { | ||
| 2601 | struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); | ||
| 2602 | struct snd_pcm_chmap *map = ac97->chmaps[SNDRV_PCM_STREAM_PLAYBACK]; | ||
| 2603 | |||
| 2604 | if (map) { | ||
| 2605 | if (ucontrol->value.integer.value[0]) | ||
| 2606 | map->chmap = snd_pcm_std_chmaps; | ||
| 2607 | else | ||
| 2608 | map->chmap = snd_pcm_alt_chmaps; | ||
| 2609 | } | ||
| 2610 | return snd_ac97_put_volsw(kcontrol, ucontrol); | ||
| 2611 | } | ||
| 2612 | |||
| 2598 | static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = { | 2613 | static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = { |
| 2599 | AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0), | 2614 | AC97_SINGLE("Duplicate Front", AC97_ALC650_MULTICH, 0, 1, 0), |
| 2600 | AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0), | 2615 | AC97_SINGLE("Surround Down Mix", AC97_ALC650_MULTICH, 1, 1, 0), |
| @@ -2608,7 +2623,14 @@ static const struct snd_kcontrol_new snd_ac97_controls_alc650[] = { | |||
| 2608 | /* 9: Line-In/Surround share */ | 2623 | /* 9: Line-In/Surround share */ |
| 2609 | /* 10: Mic/CLFE share */ | 2624 | /* 10: Mic/CLFE share */ |
| 2610 | /* 11-13: in IEC958 controls */ | 2625 | /* 11-13: in IEC958 controls */ |
| 2611 | AC97_SINGLE("Swap Surround Slot", AC97_ALC650_MULTICH, 14, 1, 0), | 2626 | { |
| 2627 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
| 2628 | .name = "Swap Surround Slot", | ||
| 2629 | .info = snd_ac97_info_volsw, | ||
| 2630 | .get = snd_ac97_get_volsw, | ||
| 2631 | .put = alc650_swap_surround_put, | ||
| 2632 | .private_value = AC97_SINGLE_VALUE(AC97_ALC650_MULTICH, 14, 1, 0), | ||
| 2633 | }, | ||
| 2612 | #if 0 /* always set in patch_alc650 */ | 2634 | #if 0 /* always set in patch_alc650 */ |
| 2613 | AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0), | 2635 | AC97_SINGLE("IEC958 Input Clock Enable", AC97_ALC650_CLOCK, 0, 1, 0), |
| 2614 | AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0), | 2636 | AC97_SINGLE("IEC958 Input Pin Enable", AC97_ALC650_CLOCK, 1, 1, 0), |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index ee895f3c8605..c7e3c533316e 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
| @@ -270,7 +270,7 @@ struct snd_ali { | |||
| 270 | spinlock_t reg_lock; | 270 | spinlock_t reg_lock; |
| 271 | spinlock_t voice_alloc; | 271 | spinlock_t voice_alloc; |
| 272 | 272 | ||
| 273 | #ifdef CONFIG_PM | 273 | #ifdef CONFIG_PM_SLEEP |
| 274 | struct snd_ali_image *image; | 274 | struct snd_ali_image *image; |
| 275 | #endif | 275 | #endif |
| 276 | }; | 276 | }; |
| @@ -1883,7 +1883,7 @@ static int __devinit snd_ali_mixer(struct snd_ali * codec) | |||
| 1883 | return 0; | 1883 | return 0; |
| 1884 | } | 1884 | } |
| 1885 | 1885 | ||
| 1886 | #ifdef CONFIG_PM | 1886 | #ifdef CONFIG_PM_SLEEP |
| 1887 | static int ali_suspend(struct device *dev) | 1887 | static int ali_suspend(struct device *dev) |
| 1888 | { | 1888 | { |
| 1889 | struct pci_dev *pci = to_pci_dev(dev); | 1889 | struct pci_dev *pci = to_pci_dev(dev); |
| @@ -1989,7 +1989,7 @@ static SIMPLE_DEV_PM_OPS(ali_pm, ali_suspend, ali_resume); | |||
| 1989 | #define ALI_PM_OPS &ali_pm | 1989 | #define ALI_PM_OPS &ali_pm |
| 1990 | #else | 1990 | #else |
| 1991 | #define ALI_PM_OPS NULL | 1991 | #define ALI_PM_OPS NULL |
| 1992 | #endif /* CONFIG_PM */ | 1992 | #endif /* CONFIG_PM_SLEEP */ |
| 1993 | 1993 | ||
| 1994 | static int snd_ali_free(struct snd_ali * codec) | 1994 | static int snd_ali_free(struct snd_ali * codec) |
| 1995 | { | 1995 | { |
| @@ -2000,7 +2000,7 @@ static int snd_ali_free(struct snd_ali * codec) | |||
| 2000 | if (codec->port) | 2000 | if (codec->port) |
| 2001 | pci_release_regions(codec->pci); | 2001 | pci_release_regions(codec->pci); |
| 2002 | pci_disable_device(codec->pci); | 2002 | pci_disable_device(codec->pci); |
| 2003 | #ifdef CONFIG_PM | 2003 | #ifdef CONFIG_PM_SLEEP |
| 2004 | kfree(codec->image); | 2004 | kfree(codec->image); |
| 2005 | #endif | 2005 | #endif |
| 2006 | pci_dev_put(codec->pci_m1533); | 2006 | pci_dev_put(codec->pci_m1533); |
| @@ -2232,7 +2232,7 @@ static int __devinit snd_ali_create(struct snd_card *card, | |||
| 2232 | return err; | 2232 | return err; |
| 2233 | } | 2233 | } |
| 2234 | 2234 | ||
| 2235 | #ifdef CONFIG_PM | 2235 | #ifdef CONFIG_PM_SLEEP |
| 2236 | codec->image = kmalloc(sizeof(*codec->image), GFP_KERNEL); | 2236 | codec->image = kmalloc(sizeof(*codec->image), GFP_KERNEL); |
| 2237 | if (!codec->image) | 2237 | if (!codec->image) |
| 2238 | snd_printk(KERN_WARNING "can't allocate apm buffer\n"); | 2238 | snd_printk(KERN_WARNING "can't allocate apm buffer\n"); |
diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 68c4469c6d19..00f157a2cf64 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c | |||
| @@ -765,7 +765,7 @@ static int __devinit snd_als300_create(struct snd_card *card, | |||
| 765 | return 0; | 765 | return 0; |
| 766 | } | 766 | } |
| 767 | 767 | ||
| 768 | #ifdef CONFIG_PM | 768 | #ifdef CONFIG_PM_SLEEP |
| 769 | static int snd_als300_suspend(struct device *dev) | 769 | static int snd_als300_suspend(struct device *dev) |
| 770 | { | 770 | { |
| 771 | struct pci_dev *pci = to_pci_dev(dev); | 771 | struct pci_dev *pci = to_pci_dev(dev); |
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c index 0eeca49c5754..feb2a1436830 100644 --- a/sound/pci/als4000.c +++ b/sound/pci/als4000.c | |||
| @@ -987,7 +987,7 @@ static void __devexit snd_card_als4000_remove(struct pci_dev *pci) | |||
| 987 | pci_set_drvdata(pci, NULL); | 987 | pci_set_drvdata(pci, NULL); |
| 988 | } | 988 | } |
| 989 | 989 | ||
| 990 | #ifdef CONFIG_PM | 990 | #ifdef CONFIG_PM_SLEEP |
| 991 | static int snd_als4000_suspend(struct device *dev) | 991 | static int snd_als4000_suspend(struct device *dev) |
| 992 | { | 992 | { |
| 993 | struct pci_dev *pci = to_pci_dev(dev); | 993 | struct pci_dev *pci = to_pci_dev(dev); |
| @@ -1040,7 +1040,7 @@ static SIMPLE_DEV_PM_OPS(snd_als4000_pm, snd_als4000_suspend, snd_als4000_resume | |||
| 1040 | #define SND_ALS4000_PM_OPS &snd_als4000_pm | 1040 | #define SND_ALS4000_PM_OPS &snd_als4000_pm |
| 1041 | #else | 1041 | #else |
| 1042 | #define SND_ALS4000_PM_OPS NULL | 1042 | #define SND_ALS4000_PM_OPS NULL |
| 1043 | #endif /* CONFIG_PM */ | 1043 | #endif /* CONFIG_PM_SLEEP */ |
| 1044 | 1044 | ||
| 1045 | static struct pci_driver als4000_driver = { | 1045 | static struct pci_driver als4000_driver = { |
| 1046 | .name = KBUILD_MODNAME, | 1046 | .name = KBUILD_MODNAME, |
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c index e8de831f98bc..eedc017c1cd8 100644 --- a/sound/pci/asihpi/asihpi.c +++ b/sound/pci/asihpi/asihpi.c | |||
| @@ -2658,7 +2658,7 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi) | |||
| 2658 | hpi_ctl.dst_node_type, | 2658 | hpi_ctl.dst_node_type, |
| 2659 | hpi_ctl.dst_node_index); | 2659 | hpi_ctl.dst_node_index); |
| 2660 | continue; | 2660 | continue; |
| 2661 | }; | 2661 | } |
| 2662 | if (err < 0) | 2662 | if (err < 0) |
| 2663 | return err; | 2663 | return err; |
| 2664 | } | 2664 | } |
| @@ -2968,7 +2968,7 @@ static struct pci_driver driver = { | |||
| 2968 | .id_table = asihpi_pci_tbl, | 2968 | .id_table = asihpi_pci_tbl, |
| 2969 | .probe = snd_asihpi_probe, | 2969 | .probe = snd_asihpi_probe, |
| 2970 | .remove = __devexit_p(snd_asihpi_remove), | 2970 | .remove = __devexit_p(snd_asihpi_remove), |
| 2971 | #ifdef CONFIG_PM | 2971 | #ifdef CONFIG_PM_SLEEP |
| 2972 | /* .suspend = snd_asihpi_suspend, | 2972 | /* .suspend = snd_asihpi_suspend, |
| 2973 | .resume = snd_asihpi_resume, */ | 2973 | .resume = snd_asihpi_resume, */ |
| 2974 | #endif | 2974 | #endif |
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c index 31020d2a868b..368df8b0853e 100644 --- a/sound/pci/atiixp.c +++ b/sound/pci/atiixp.c | |||
| @@ -535,7 +535,7 @@ static int snd_atiixp_aclink_reset(struct atiixp *chip) | |||
| 535 | return 0; | 535 | return 0; |
| 536 | } | 536 | } |
| 537 | 537 | ||
| 538 | #ifdef CONFIG_PM | 538 | #ifdef CONFIG_PM_SLEEP |
| 539 | static int snd_atiixp_aclink_down(struct atiixp *chip) | 539 | static int snd_atiixp_aclink_down(struct atiixp *chip) |
| 540 | { | 540 | { |
| 541 | // if (atiixp_read(chip, MODEM_MIRROR) & 0x1) /* modem running, too? */ | 541 | // if (atiixp_read(chip, MODEM_MIRROR) & 0x1) /* modem running, too? */ |
| @@ -1250,6 +1250,7 @@ static struct atiixp_dma_ops snd_atiixp_spdif_dma_ops = { | |||
| 1250 | static int __devinit snd_atiixp_pcm_new(struct atiixp *chip) | 1250 | static int __devinit snd_atiixp_pcm_new(struct atiixp *chip) |
| 1251 | { | 1251 | { |
| 1252 | struct snd_pcm *pcm; | 1252 | struct snd_pcm *pcm; |
| 1253 | struct snd_pcm_chmap *chmap; | ||
| 1253 | struct snd_ac97_bus *pbus = chip->ac97_bus; | 1254 | struct snd_ac97_bus *pbus = chip->ac97_bus; |
| 1254 | int err, i, num_pcms; | 1255 | int err, i, num_pcms; |
| 1255 | 1256 | ||
| @@ -1293,6 +1294,14 @@ static int __devinit snd_atiixp_pcm_new(struct atiixp *chip) | |||
| 1293 | snd_dma_pci_data(chip->pci), | 1294 | snd_dma_pci_data(chip->pci), |
| 1294 | 64*1024, 128*1024); | 1295 | 64*1024, 128*1024); |
| 1295 | 1296 | ||
| 1297 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
| 1298 | snd_pcm_alt_chmaps, chip->max_channels, 0, | ||
| 1299 | &chmap); | ||
| 1300 | if (err < 0) | ||
| 1301 | return err; | ||
| 1302 | chmap->channel_mask = SND_PCM_CHMAP_MASK_2468; | ||
| 1303 | chip->ac97[0]->chmaps[SNDRV_PCM_STREAM_PLAYBACK] = chmap; | ||
| 1304 | |||
| 1296 | /* no SPDIF support on codec? */ | 1305 | /* no SPDIF support on codec? */ |
| 1297 | if (chip->pcms[ATI_PCM_SPDIF] && ! chip->pcms[ATI_PCM_SPDIF]->rates) | 1306 | if (chip->pcms[ATI_PCM_SPDIF] && ! chip->pcms[ATI_PCM_SPDIF]->rates) |
| 1298 | return 0; | 1307 | return 0; |
| @@ -1458,7 +1467,7 @@ static int __devinit snd_atiixp_mixer_new(struct atiixp *chip, int clock, | |||
| 1458 | } | 1467 | } |
| 1459 | 1468 | ||
| 1460 | 1469 | ||
| 1461 | #ifdef CONFIG_PM | 1470 | #ifdef CONFIG_PM_SLEEP |
| 1462 | /* | 1471 | /* |
| 1463 | * power management | 1472 | * power management |
| 1464 | */ | 1473 | */ |
| @@ -1533,7 +1542,7 @@ static SIMPLE_DEV_PM_OPS(snd_atiixp_pm, snd_atiixp_suspend, snd_atiixp_resume); | |||
| 1533 | #define SND_ATIIXP_PM_OPS &snd_atiixp_pm | 1542 | #define SND_ATIIXP_PM_OPS &snd_atiixp_pm |
| 1534 | #else | 1543 | #else |
| 1535 | #define SND_ATIIXP_PM_OPS NULL | 1544 | #define SND_ATIIXP_PM_OPS NULL |
| 1536 | #endif /* CONFIG_PM */ | 1545 | #endif /* CONFIG_PM_SLEEP */ |
| 1537 | 1546 | ||
| 1538 | 1547 | ||
| 1539 | #ifdef CONFIG_PROC_FS | 1548 | #ifdef CONFIG_PROC_FS |
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c index 79e204ec623f..6fc03d9f2cff 100644 --- a/sound/pci/atiixp_modem.c +++ b/sound/pci/atiixp_modem.c | |||
| @@ -511,7 +511,7 @@ static int snd_atiixp_aclink_reset(struct atiixp_modem *chip) | |||
| 511 | return 0; | 511 | return 0; |
| 512 | } | 512 | } |
| 513 | 513 | ||
| 514 | #ifdef CONFIG_PM | 514 | #ifdef CONFIG_PM_SLEEP |
| 515 | static int snd_atiixp_aclink_down(struct atiixp_modem *chip) | 515 | static int snd_atiixp_aclink_down(struct atiixp_modem *chip) |
| 516 | { | 516 | { |
| 517 | // if (atiixp_read(chip, MODEM_MIRROR) & 0x1) /* modem running, too? */ | 517 | // if (atiixp_read(chip, MODEM_MIRROR) & 0x1) /* modem running, too? */ |
| @@ -1113,7 +1113,7 @@ static int __devinit snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock) | |||
| 1113 | } | 1113 | } |
| 1114 | 1114 | ||
| 1115 | 1115 | ||
| 1116 | #ifdef CONFIG_PM | 1116 | #ifdef CONFIG_PM_SLEEP |
| 1117 | /* | 1117 | /* |
| 1118 | * power management | 1118 | * power management |
| 1119 | */ | 1119 | */ |
| @@ -1169,7 +1169,7 @@ static SIMPLE_DEV_PM_OPS(snd_atiixp_pm, snd_atiixp_suspend, snd_atiixp_resume); | |||
| 1169 | #define SND_ATIIXP_PM_OPS &snd_atiixp_pm | 1169 | #define SND_ATIIXP_PM_OPS &snd_atiixp_pm |
| 1170 | #else | 1170 | #else |
| 1171 | #define SND_ATIIXP_PM_OPS NULL | 1171 | #define SND_ATIIXP_PM_OPS NULL |
| 1172 | #endif /* CONFIG_PM */ | 1172 | #endif /* CONFIG_PM_SLEEP */ |
| 1173 | 1173 | ||
| 1174 | #ifdef CONFIG_PROC_FS | 1174 | #ifdef CONFIG_PROC_FS |
| 1175 | /* | 1175 | /* |
diff --git a/sound/pci/au88x0/au88x0_game.c b/sound/pci/au88x0/au88x0_game.c index c07c792bde8d..30a456700d89 100644 --- a/sound/pci/au88x0/au88x0_game.c +++ b/sound/pci/au88x0/au88x0_game.c | |||
| @@ -100,7 +100,7 @@ static int __devinit vortex_gameport_register(vortex_t * vortex) | |||
| 100 | if (!gp) { | 100 | if (!gp) { |
| 101 | printk(KERN_ERR "vortex: cannot allocate memory for gameport\n"); | 101 | printk(KERN_ERR "vortex: cannot allocate memory for gameport\n"); |
| 102 | return -ENOMEM; | 102 | return -ENOMEM; |
| 103 | }; | 103 | } |
| 104 | 104 | ||
| 105 | gameport_set_name(gp, "AU88x0 Gameport"); | 105 | gameport_set_name(gp, "AU88x0 Gameport"); |
| 106 | gameport_set_phys(gp, "pci%s/gameport0", pci_name(vortex->pci_dev)); | 106 | gameport_set_phys(gp, "pci%s/gameport0", pci_name(vortex->pci_dev)); |
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c index e59f120742a4..b2405020284c 100644 --- a/sound/pci/au88x0/au88x0_pcm.c +++ b/sound/pci/au88x0/au88x0_pcm.c | |||
| @@ -585,7 +585,7 @@ static int snd_vortex_pcm_vol_put(struct snd_kcontrol *kcontrol, | |||
| 585 | case 4: | 585 | case 4: |
| 586 | mixin = p->mixin[i]; | 586 | mixin = p->mixin[i]; |
| 587 | break; | 587 | break; |
| 588 | }; | 588 | } |
| 589 | vol = p->vol[i]; | 589 | vol = p->vol[i]; |
| 590 | vortex_mix_setinputvolumebyte(vortex, | 590 | vortex_mix_setinputvolumebyte(vortex, |
| 591 | vortex->mixplayb[i], mixin, vol); | 591 | vortex->mixplayb[i], mixin, vol); |
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c index 4dddd871548b..c03b66b784a3 100644 --- a/sound/pci/azt3328.c +++ b/sound/pci/azt3328.c | |||
| @@ -365,7 +365,7 @@ struct snd_azf3328 { | |||
| 365 | * CONFIG_PM register storage below, but that's slightly difficult. */ | 365 | * CONFIG_PM register storage below, but that's slightly difficult. */ |
| 366 | u16 shadow_reg_ctrl_6AH; | 366 | u16 shadow_reg_ctrl_6AH; |
| 367 | 367 | ||
| 368 | #ifdef CONFIG_PM | 368 | #ifdef CONFIG_PM_SLEEP |
| 369 | /* register value containers for power management | 369 | /* register value containers for power management |
| 370 | * Note: not always full I/O range preserved (similar to Win driver!) */ | 370 | * Note: not always full I/O range preserved (similar to Win driver!) */ |
| 371 | u32 saved_regs_ctrl[AZF_ALIGN(AZF_IO_SIZE_CTRL_PM) / 4]; | 371 | u32 saved_regs_ctrl[AZF_ALIGN(AZF_IO_SIZE_CTRL_PM) / 4]; |
| @@ -2729,7 +2729,7 @@ snd_azf3328_remove(struct pci_dev *pci) | |||
| 2729 | snd_azf3328_dbgcallleave(); | 2729 | snd_azf3328_dbgcallleave(); |
| 2730 | } | 2730 | } |
| 2731 | 2731 | ||
| 2732 | #ifdef CONFIG_PM | 2732 | #ifdef CONFIG_PM_SLEEP |
| 2733 | static inline void | 2733 | static inline void |
| 2734 | snd_azf3328_suspend_regs(unsigned long io_addr, unsigned count, u32 *saved_regs) | 2734 | snd_azf3328_suspend_regs(unsigned long io_addr, unsigned count, u32 *saved_regs) |
| 2735 | { | 2735 | { |
| @@ -2866,7 +2866,7 @@ static SIMPLE_DEV_PM_OPS(snd_azf3328_pm, snd_azf3328_suspend, snd_azf3328_resume | |||
| 2866 | #define SND_AZF3328_PM_OPS &snd_azf3328_pm | 2866 | #define SND_AZF3328_PM_OPS &snd_azf3328_pm |
| 2867 | #else | 2867 | #else |
| 2868 | #define SND_AZF3328_PM_OPS NULL | 2868 | #define SND_AZF3328_PM_OPS NULL |
| 2869 | #endif /* CONFIG_PM */ | 2869 | #endif /* CONFIG_PM_SLEEP */ |
| 2870 | 2870 | ||
| 2871 | static struct pci_driver azf3328_driver = { | 2871 | static struct pci_driver azf3328_driver = { |
| 2872 | .name = KBUILD_MODNAME, | 2872 | .name = KBUILD_MODNAME, |
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index e8e8ccc96403..04402c14cb23 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h | |||
| @@ -710,7 +710,7 @@ struct snd_ca0106 { | |||
| 710 | 710 | ||
| 711 | u16 spi_dac_reg[16]; | 711 | u16 spi_dac_reg[16]; |
| 712 | 712 | ||
| 713 | #ifdef CONFIG_PM | 713 | #ifdef CONFIG_PM_SLEEP |
| 714 | #define NUM_SAVED_VOLUMES 9 | 714 | #define NUM_SAVED_VOLUMES 9 |
| 715 | unsigned int saved_vol[NUM_SAVED_VOLUMES]; | 715 | unsigned int saved_vol[NUM_SAVED_VOLUMES]; |
| 716 | #endif | 716 | #endif |
| @@ -733,7 +733,7 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value); | |||
| 733 | int snd_ca0106_spi_write(struct snd_ca0106 * emu, | 733 | int snd_ca0106_spi_write(struct snd_ca0106 * emu, |
| 734 | unsigned int data); | 734 | unsigned int data); |
| 735 | 735 | ||
| 736 | #ifdef CONFIG_PM | 736 | #ifdef CONFIG_PM_SLEEP |
| 737 | void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip); | 737 | void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip); |
| 738 | void snd_ca0106_mixer_resume(struct snd_ca0106 *chip); | 738 | void snd_ca0106_mixer_resume(struct snd_ca0106 *chip); |
| 739 | #else | 739 | #else |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 83277b747b36..65c55910566b 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
| @@ -1334,10 +1334,29 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id) | |||
| 1334 | return IRQ_HANDLED; | 1334 | return IRQ_HANDLED; |
| 1335 | } | 1335 | } |
| 1336 | 1336 | ||
| 1337 | static const struct snd_pcm_chmap_elem surround_map[] = { | ||
| 1338 | { .channels = 2, | ||
| 1339 | .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
| 1340 | { } | ||
| 1341 | }; | ||
| 1342 | |||
| 1343 | static const struct snd_pcm_chmap_elem clfe_map[] = { | ||
| 1344 | { .channels = 2, | ||
| 1345 | .map = { SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } }, | ||
| 1346 | { } | ||
| 1347 | }; | ||
| 1348 | |||
| 1349 | static const struct snd_pcm_chmap_elem side_map[] = { | ||
| 1350 | { .channels = 2, | ||
| 1351 | .map = { SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } }, | ||
| 1352 | { } | ||
| 1353 | }; | ||
| 1354 | |||
| 1337 | static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device) | 1355 | static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device) |
| 1338 | { | 1356 | { |
| 1339 | struct snd_pcm *pcm; | 1357 | struct snd_pcm *pcm; |
| 1340 | struct snd_pcm_substream *substream; | 1358 | struct snd_pcm_substream *substream; |
| 1359 | const struct snd_pcm_chmap_elem *map = NULL; | ||
| 1341 | int err; | 1360 | int err; |
| 1342 | 1361 | ||
| 1343 | err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm); | 1362 | err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm); |
| @@ -1350,18 +1369,22 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device) | |||
| 1350 | case 0: | 1369 | case 0: |
| 1351 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_front_ops); | 1370 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_front_ops); |
| 1352 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_0_ops); | 1371 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_0_ops); |
| 1372 | map = snd_pcm_std_chmaps; | ||
| 1353 | break; | 1373 | break; |
| 1354 | case 1: | 1374 | case 1: |
| 1355 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_rear_ops); | 1375 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_rear_ops); |
| 1356 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_1_ops); | 1376 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_1_ops); |
| 1377 | map = surround_map; | ||
| 1357 | break; | 1378 | break; |
| 1358 | case 2: | 1379 | case 2: |
| 1359 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_center_lfe_ops); | 1380 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_center_lfe_ops); |
| 1360 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_2_ops); | 1381 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_2_ops); |
| 1382 | map = clfe_map; | ||
| 1361 | break; | 1383 | break; |
| 1362 | case 3: | 1384 | case 3: |
| 1363 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_unknown_ops); | 1385 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ca0106_playback_unknown_ops); |
| 1364 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_3_ops); | 1386 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_ca0106_capture_3_ops); |
| 1387 | map = side_map; | ||
| 1365 | break; | 1388 | break; |
| 1366 | } | 1389 | } |
| 1367 | 1390 | ||
| @@ -1388,6 +1411,11 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device) | |||
| 1388 | return err; | 1411 | return err; |
| 1389 | } | 1412 | } |
| 1390 | 1413 | ||
| 1414 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, 2, | ||
| 1415 | 1 << 2, NULL); | ||
| 1416 | if (err < 0) | ||
| 1417 | return err; | ||
| 1418 | |||
| 1391 | emu->pcm[device] = pcm; | 1419 | emu->pcm[device] = pcm; |
| 1392 | 1420 | ||
| 1393 | return 0; | 1421 | return 0; |
| @@ -1871,7 +1899,7 @@ static void __devexit snd_ca0106_remove(struct pci_dev *pci) | |||
| 1871 | pci_set_drvdata(pci, NULL); | 1899 | pci_set_drvdata(pci, NULL); |
| 1872 | } | 1900 | } |
| 1873 | 1901 | ||
| 1874 | #ifdef CONFIG_PM | 1902 | #ifdef CONFIG_PM_SLEEP |
| 1875 | static int snd_ca0106_suspend(struct device *dev) | 1903 | static int snd_ca0106_suspend(struct device *dev) |
| 1876 | { | 1904 | { |
| 1877 | struct pci_dev *pci = to_pci_dev(dev); | 1905 | struct pci_dev *pci = to_pci_dev(dev); |
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 84f3f92436b5..68eacf7002d6 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c | |||
| @@ -907,7 +907,7 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) | |||
| 907 | return 0; | 907 | return 0; |
| 908 | } | 908 | } |
| 909 | 909 | ||
| 910 | #ifdef CONFIG_PM | 910 | #ifdef CONFIG_PM_SLEEP |
| 911 | struct ca0106_vol_tbl { | 911 | struct ca0106_vol_tbl { |
| 912 | unsigned int channel_id; | 912 | unsigned int channel_id; |
| 913 | unsigned int reg; | 913 | unsigned int reg; |
| @@ -953,4 +953,4 @@ void snd_ca0106_mixer_resume(struct snd_ca0106 *chip) | |||
| 953 | if (chip->details->i2c_adc) | 953 | if (chip->details->i2c_adc) |
| 954 | ca0106_set_capture_mic_line_in(chip); | 954 | ca0106_set_capture_mic_line_in(chip); |
| 955 | } | 955 | } |
| 956 | #endif /* CONFIG_PM */ | 956 | #endif /* CONFIG_PM_SLEEP */ |
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c index b7d6f2b886ef..22122ff26e34 100644 --- a/sound/pci/cmipci.c +++ b/sound/pci/cmipci.c | |||
| @@ -504,7 +504,7 @@ struct cmipci { | |||
| 504 | 504 | ||
| 505 | spinlock_t reg_lock; | 505 | spinlock_t reg_lock; |
| 506 | 506 | ||
| 507 | #ifdef CONFIG_PM | 507 | #ifdef CONFIG_PM_SLEEP |
| 508 | unsigned int saved_regs[0x20]; | 508 | unsigned int saved_regs[0x20]; |
| 509 | unsigned char saved_mixers[0x20]; | 509 | unsigned char saved_mixers[0x20]; |
| 510 | #endif | 510 | #endif |
| @@ -1962,6 +1962,12 @@ static int __devinit snd_cmipci_pcm_spdif_new(struct cmipci *cm, int device) | |||
| 1962 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1962 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
| 1963 | snd_dma_pci_data(cm->pci), 64*1024, 128*1024); | 1963 | snd_dma_pci_data(cm->pci), 64*1024, 128*1024); |
| 1964 | 1964 | ||
| 1965 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
| 1966 | snd_pcm_alt_chmaps, cm->max_channels, 0, | ||
| 1967 | NULL); | ||
| 1968 | if (err < 0) | ||
| 1969 | return err; | ||
| 1970 | |||
| 1965 | return 0; | 1971 | return 0; |
| 1966 | } | 1972 | } |
| 1967 | 1973 | ||
| @@ -3315,7 +3321,7 @@ static void __devexit snd_cmipci_remove(struct pci_dev *pci) | |||
| 3315 | } | 3321 | } |
| 3316 | 3322 | ||
| 3317 | 3323 | ||
| 3318 | #ifdef CONFIG_PM | 3324 | #ifdef CONFIG_PM_SLEEP |
| 3319 | /* | 3325 | /* |
| 3320 | * power management | 3326 | * power management |
| 3321 | */ | 3327 | */ |
| @@ -3403,7 +3409,7 @@ static SIMPLE_DEV_PM_OPS(snd_cmipci_pm, snd_cmipci_suspend, snd_cmipci_resume); | |||
| 3403 | #define SND_CMIPCI_PM_OPS &snd_cmipci_pm | 3409 | #define SND_CMIPCI_PM_OPS &snd_cmipci_pm |
| 3404 | #else | 3410 | #else |
| 3405 | #define SND_CMIPCI_PM_OPS NULL | 3411 | #define SND_CMIPCI_PM_OPS NULL |
| 3406 | #endif /* CONFIG_PM */ | 3412 | #endif /* CONFIG_PM_SLEEP */ |
| 3407 | 3413 | ||
| 3408 | static struct pci_driver cmipci_driver = { | 3414 | static struct pci_driver cmipci_driver = { |
| 3409 | .name = KBUILD_MODNAME, | 3415 | .name = KBUILD_MODNAME, |
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c index 45a8317085f4..8e86ec0031fc 100644 --- a/sound/pci/cs4281.c +++ b/sound/pci/cs4281.c | |||
| @@ -486,7 +486,7 @@ struct cs4281 { | |||
| 486 | 486 | ||
| 487 | struct gameport *gameport; | 487 | struct gameport *gameport; |
| 488 | 488 | ||
| 489 | #ifdef CONFIG_PM | 489 | #ifdef CONFIG_PM_SLEEP |
| 490 | u32 suspend_regs[SUSPEND_REGISTERS]; | 490 | u32 suspend_regs[SUSPEND_REGISTERS]; |
| 491 | #endif | 491 | #endif |
| 492 | 492 | ||
| @@ -1977,7 +1977,7 @@ static void __devexit snd_cs4281_remove(struct pci_dev *pci) | |||
| 1977 | /* | 1977 | /* |
| 1978 | * Power Management | 1978 | * Power Management |
| 1979 | */ | 1979 | */ |
| 1980 | #ifdef CONFIG_PM | 1980 | #ifdef CONFIG_PM_SLEEP |
| 1981 | 1981 | ||
| 1982 | static int saved_regs[SUSPEND_REGISTERS] = { | 1982 | static int saved_regs[SUSPEND_REGISTERS] = { |
| 1983 | BA0_JSCTL, | 1983 | BA0_JSCTL, |
| @@ -2089,7 +2089,7 @@ static SIMPLE_DEV_PM_OPS(cs4281_pm, cs4281_suspend, cs4281_resume); | |||
| 2089 | #define CS4281_PM_OPS &cs4281_pm | 2089 | #define CS4281_PM_OPS &cs4281_pm |
| 2090 | #else | 2090 | #else |
| 2091 | #define CS4281_PM_OPS NULL | 2091 | #define CS4281_PM_OPS NULL |
| 2092 | #endif /* CONFIG_PM */ | 2092 | #endif /* CONFIG_PM_SLEEP */ |
| 2093 | 2093 | ||
| 2094 | static struct pci_driver cs4281_driver = { | 2094 | static struct pci_driver cs4281_driver = { |
| 2095 | .name = KBUILD_MODNAME, | 2095 | .name = KBUILD_MODNAME, |
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c index 1e007c736a8b..575bed0836ff 100644 --- a/sound/pci/cs46xx/cs46xx.c +++ b/sound/pci/cs46xx/cs46xx.c | |||
| @@ -166,7 +166,7 @@ static struct pci_driver cs46xx_driver = { | |||
| 166 | .id_table = snd_cs46xx_ids, | 166 | .id_table = snd_cs46xx_ids, |
| 167 | .probe = snd_card_cs46xx_probe, | 167 | .probe = snd_card_cs46xx_probe, |
| 168 | .remove = __devexit_p(snd_card_cs46xx_remove), | 168 | .remove = __devexit_p(snd_card_cs46xx_remove), |
| 169 | #ifdef CONFIG_PM | 169 | #ifdef CONFIG_PM_SLEEP |
| 170 | .driver = { | 170 | .driver = { |
| 171 | .pm = &snd_cs46xx_pm, | 171 | .pm = &snd_cs46xx_pm, |
| 172 | }, | 172 | }, |
diff --git a/sound/pci/cs46xx/cs46xx.h b/sound/pci/cs46xx/cs46xx.h index 29d8a8da1ba7..fc339ef0a0ae 100644 --- a/sound/pci/cs46xx/cs46xx.h +++ b/sound/pci/cs46xx/cs46xx.h | |||
| @@ -1721,7 +1721,7 @@ struct snd_cs46xx { | |||
| 1721 | unsigned int play_ctl; | 1721 | unsigned int play_ctl; |
| 1722 | #endif | 1722 | #endif |
| 1723 | 1723 | ||
| 1724 | #ifdef CONFIG_PM | 1724 | #ifdef CONFIG_PM_SLEEP |
| 1725 | u32 *saved_regs; | 1725 | u32 *saved_regs; |
| 1726 | #endif | 1726 | #endif |
| 1727 | }; | 1727 | }; |
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index a71d1c14a0f6..a2bb8c91ebe6 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
| @@ -2797,7 +2797,7 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip) | |||
| 2797 | } | 2797 | } |
| 2798 | #endif | 2798 | #endif |
| 2799 | 2799 | ||
| 2800 | #ifdef CONFIG_PM | 2800 | #ifdef CONFIG_PM_SLEEP |
| 2801 | kfree(chip->saved_regs); | 2801 | kfree(chip->saved_regs); |
| 2802 | #endif | 2802 | #endif |
| 2803 | 2803 | ||
| @@ -3590,7 +3590,7 @@ static struct cs_card_type __devinitdata cards[] = { | |||
| 3590 | /* | 3590 | /* |
| 3591 | * APM support | 3591 | * APM support |
| 3592 | */ | 3592 | */ |
| 3593 | #ifdef CONFIG_PM | 3593 | #ifdef CONFIG_PM_SLEEP |
| 3594 | static unsigned int saved_regs[] = { | 3594 | static unsigned int saved_regs[] = { |
| 3595 | BA0_ACOSV, | 3595 | BA0_ACOSV, |
| 3596 | /*BA0_ASER_FADDR,*/ | 3596 | /*BA0_ASER_FADDR,*/ |
| @@ -3711,7 +3711,7 @@ static int snd_cs46xx_resume(struct device *dev) | |||
| 3711 | } | 3711 | } |
| 3712 | 3712 | ||
| 3713 | SIMPLE_DEV_PM_OPS(snd_cs46xx_pm, snd_cs46xx_suspend, snd_cs46xx_resume); | 3713 | SIMPLE_DEV_PM_OPS(snd_cs46xx_pm, snd_cs46xx_suspend, snd_cs46xx_resume); |
| 3714 | #endif /* CONFIG_PM */ | 3714 | #endif /* CONFIG_PM_SLEEP */ |
| 3715 | 3715 | ||
| 3716 | 3716 | ||
| 3717 | /* | 3717 | /* |
| @@ -3868,7 +3868,7 @@ int __devinit snd_cs46xx_create(struct snd_card *card, | |||
| 3868 | 3868 | ||
| 3869 | snd_cs46xx_proc_init(card, chip); | 3869 | snd_cs46xx_proc_init(card, chip); |
| 3870 | 3870 | ||
| 3871 | #ifdef CONFIG_PM | 3871 | #ifdef CONFIG_PM_SLEEP |
| 3872 | chip->saved_regs = kmalloc(sizeof(*chip->saved_regs) * | 3872 | chip->saved_regs = kmalloc(sizeof(*chip->saved_regs) * |
| 3873 | ARRAY_SIZE(saved_regs), GFP_KERNEL); | 3873 | ARRAY_SIZE(saved_regs), GFP_KERNEL); |
| 3874 | if (!chip->saved_regs) { | 3874 | if (!chip->saved_regs) { |
diff --git a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h index b5189495d58a..86f14620f817 100644 --- a/sound/pci/cs46xx/cs46xx_lib.h +++ b/sound/pci/cs46xx/cs46xx_lib.h | |||
| @@ -90,7 +90,7 @@ static inline unsigned int snd_cs46xx_peekBA0(struct snd_cs46xx *chip, unsigned | |||
| 90 | struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip); | 90 | struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip); |
| 91 | void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip); | 91 | void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip); |
| 92 | int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module); | 92 | int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module); |
| 93 | #ifdef CONFIG_PM | 93 | #ifdef CONFIG_PM_SLEEP |
| 94 | int cs46xx_dsp_resume(struct snd_cs46xx * chip); | 94 | int cs46xx_dsp_resume(struct snd_cs46xx * chip); |
| 95 | #endif | 95 | #endif |
| 96 | struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, | 96 | struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, |
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index 56fec0bc0efb..1686b4f4c44f 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c | |||
| @@ -287,7 +287,7 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) | |||
| 287 | if (ins->scbs[i].deleted) continue; | 287 | if (ins->scbs[i].deleted) continue; |
| 288 | 288 | ||
| 289 | cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) ); | 289 | cs46xx_dsp_proc_free_scb_desc ( (ins->scbs + i) ); |
| 290 | #ifdef CONFIG_PM | 290 | #ifdef CONFIG_PM_SLEEP |
| 291 | kfree(ins->scbs[i].data); | 291 | kfree(ins->scbs[i].data); |
| 292 | #endif | 292 | #endif |
| 293 | } | 293 | } |
| @@ -1019,7 +1019,7 @@ cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 | |||
| 1019 | { | 1019 | { |
| 1020 | struct dsp_scb_descriptor * desc; | 1020 | struct dsp_scb_descriptor * desc; |
| 1021 | 1021 | ||
| 1022 | #ifdef CONFIG_PM | 1022 | #ifdef CONFIG_PM_SLEEP |
| 1023 | /* copy the data for resume */ | 1023 | /* copy the data for resume */ |
| 1024 | scb_data = kmemdup(scb_data, SCB_BYTES, GFP_KERNEL); | 1024 | scb_data = kmemdup(scb_data, SCB_BYTES, GFP_KERNEL); |
| 1025 | if (!scb_data) | 1025 | if (!scb_data) |
| @@ -1032,7 +1032,7 @@ cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 | |||
| 1032 | _dsp_create_scb(chip,scb_data,dest); | 1032 | _dsp_create_scb(chip,scb_data,dest); |
| 1033 | } else { | 1033 | } else { |
| 1034 | snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); | 1034 | snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); |
| 1035 | #ifdef CONFIG_PM | 1035 | #ifdef CONFIG_PM_SLEEP |
| 1036 | kfree(scb_data); | 1036 | kfree(scb_data); |
| 1037 | #endif | 1037 | #endif |
| 1038 | } | 1038 | } |
| @@ -1937,7 +1937,7 @@ int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right) | |||
| 1937 | return 0; | 1937 | return 0; |
| 1938 | } | 1938 | } |
| 1939 | 1939 | ||
| 1940 | #ifdef CONFIG_PM | 1940 | #ifdef CONFIG_PM_SLEEP |
| 1941 | int cs46xx_dsp_resume(struct snd_cs46xx * chip) | 1941 | int cs46xx_dsp_resume(struct snd_cs46xx * chip) |
| 1942 | { | 1942 | { |
| 1943 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; | 1943 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; |
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c index c2c695b07f8c..409e8764fbeb 100644 --- a/sound/pci/cs46xx/dsp_spos_scb_lib.c +++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c | |||
| @@ -203,7 +203,7 @@ void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * | |||
| 203 | remove_symbol (chip,scb->scb_symbol); | 203 | remove_symbol (chip,scb->scb_symbol); |
| 204 | 204 | ||
| 205 | ins->scbs[scb->index].deleted = 1; | 205 | ins->scbs[scb->index].deleted = 1; |
| 206 | #ifdef CONFIG_PM | 206 | #ifdef CONFIG_PM_SLEEP |
| 207 | kfree(ins->scbs[scb->index].data); | 207 | kfree(ins->scbs[scb->index].data); |
| 208 | ins->scbs[scb->index].data = NULL; | 208 | ins->scbs[scb->index].data = NULL; |
| 209 | #endif | 209 | #endif |
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c index f1e4229993af..d1cca2831575 100644 --- a/sound/pci/cs5530.c +++ b/sound/pci/cs5530.c | |||
| @@ -142,8 +142,7 @@ static int __devinit snd_cs5530_create(struct snd_card *card, | |||
| 142 | 142 | ||
| 143 | mem = pci_ioremap_bar(pci, 0); | 143 | mem = pci_ioremap_bar(pci, 0); |
| 144 | if (mem == NULL) { | 144 | if (mem == NULL) { |
| 145 | kfree(chip); | 145 | snd_cs5530_free(chip); |
| 146 | pci_disable_device(pci); | ||
| 147 | return -EBUSY; | 146 | return -EBUSY; |
| 148 | } | 147 | } |
| 149 | 148 | ||
diff --git a/sound/pci/cs5535audio/Makefile b/sound/pci/cs5535audio/Makefile index ccc642269b9e..a8f75f8dfda9 100644 --- a/sound/pci/cs5535audio/Makefile +++ b/sound/pci/cs5535audio/Makefile | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | snd-cs5535audio-y := cs5535audio.o cs5535audio_pcm.o | 5 | snd-cs5535audio-y := cs5535audio.o cs5535audio_pcm.o |
| 6 | snd-cs5535audio-$(CONFIG_PM) += cs5535audio_pm.o | 6 | snd-cs5535audio-$(CONFIG_PM_SLEEP) += cs5535audio_pm.o |
| 7 | snd-cs5535audio-$(CONFIG_OLPC) += cs5535audio_olpc.o | 7 | snd-cs5535audio-$(CONFIG_OLPC) += cs5535audio_olpc.o |
| 8 | 8 | ||
| 9 | # Toplevel Module Dependency | 9 | # Toplevel Module Dependency |
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c index 51f64ba5facf..4915efa551fc 100644 --- a/sound/pci/cs5535audio/cs5535audio.c +++ b/sound/pci/cs5535audio/cs5535audio.c | |||
| @@ -399,7 +399,7 @@ static struct pci_driver cs5535audio_driver = { | |||
| 399 | .id_table = snd_cs5535audio_ids, | 399 | .id_table = snd_cs5535audio_ids, |
| 400 | .probe = snd_cs5535audio_probe, | 400 | .probe = snd_cs5535audio_probe, |
| 401 | .remove = __devexit_p(snd_cs5535audio_remove), | 401 | .remove = __devexit_p(snd_cs5535audio_remove), |
| 402 | #ifdef CONFIG_PM | 402 | #ifdef CONFIG_PM_SLEEP |
| 403 | .driver = { | 403 | .driver = { |
| 404 | .pm = &snd_cs5535audio_pm, | 404 | .pm = &snd_cs5535audio_pm, |
| 405 | }, | 405 | }, |
diff --git a/sound/pci/ctxfi/ctatc.c b/sound/pci/ctxfi/ctatc.c index 2f6e9c762d3f..a2f997a9977a 100644 --- a/sound/pci/ctxfi/ctatc.c +++ b/sound/pci/ctxfi/ctatc.c | |||
| @@ -1536,7 +1536,7 @@ static void atc_connect_resources(struct ct_atc *atc) | |||
| 1536 | } | 1536 | } |
| 1537 | } | 1537 | } |
| 1538 | 1538 | ||
| 1539 | #ifdef CONFIG_PM | 1539 | #ifdef CONFIG_PM_SLEEP |
| 1540 | static int atc_suspend(struct ct_atc *atc) | 1540 | static int atc_suspend(struct ct_atc *atc) |
| 1541 | { | 1541 | { |
| 1542 | int i; | 1542 | int i; |
| @@ -1647,7 +1647,7 @@ static struct ct_atc atc_preset __devinitdata = { | |||
| 1647 | .output_switch_put = atc_output_switch_put, | 1647 | .output_switch_put = atc_output_switch_put, |
| 1648 | .mic_source_switch_get = atc_mic_source_switch_get, | 1648 | .mic_source_switch_get = atc_mic_source_switch_get, |
| 1649 | .mic_source_switch_put = atc_mic_source_switch_put, | 1649 | .mic_source_switch_put = atc_mic_source_switch_put, |
| 1650 | #ifdef CONFIG_PM | 1650 | #ifdef CONFIG_PM_SLEEP |
| 1651 | .suspend = atc_suspend, | 1651 | .suspend = atc_suspend, |
| 1652 | .resume = atc_resume, | 1652 | .resume = atc_resume, |
| 1653 | #endif | 1653 | #endif |
diff --git a/sound/pci/ctxfi/ctatc.h b/sound/pci/ctxfi/ctatc.h index 653e813ad142..69b51f9d345e 100644 --- a/sound/pci/ctxfi/ctatc.h +++ b/sound/pci/ctxfi/ctatc.h | |||
| @@ -143,7 +143,7 @@ struct ct_atc { | |||
| 143 | 143 | ||
| 144 | struct ct_timer *timer; | 144 | struct ct_timer *timer; |
| 145 | 145 | ||
| 146 | #ifdef CONFIG_PM | 146 | #ifdef CONFIG_PM_SLEEP |
| 147 | int (*suspend)(struct ct_atc *atc); | 147 | int (*suspend)(struct ct_atc *atc); |
| 148 | int (*resume)(struct ct_atc *atc); | 148 | int (*resume)(struct ct_atc *atc); |
| 149 | #define NUM_PCMS (NUM_CTALSADEVS - 1) | 149 | #define NUM_PCMS (NUM_CTALSADEVS - 1) |
diff --git a/sound/pci/ctxfi/cthardware.h b/sound/pci/ctxfi/cthardware.h index c56fe533b3f3..5977e9a24b5c 100644 --- a/sound/pci/ctxfi/cthardware.h +++ b/sound/pci/ctxfi/cthardware.h | |||
| @@ -72,7 +72,7 @@ struct hw { | |||
| 72 | int (*card_init)(struct hw *hw, struct card_conf *info); | 72 | int (*card_init)(struct hw *hw, struct card_conf *info); |
| 73 | int (*card_stop)(struct hw *hw); | 73 | int (*card_stop)(struct hw *hw); |
| 74 | int (*pll_init)(struct hw *hw, unsigned int rsr); | 74 | int (*pll_init)(struct hw *hw, unsigned int rsr); |
| 75 | #ifdef CONFIG_PM | 75 | #ifdef CONFIG_PM_SLEEP |
| 76 | int (*suspend)(struct hw *hw); | 76 | int (*suspend)(struct hw *hw); |
| 77 | int (*resume)(struct hw *hw, struct card_conf *info); | 77 | int (*resume)(struct hw *hw, struct card_conf *info); |
| 78 | #endif | 78 | #endif |
diff --git a/sound/pci/ctxfi/cthw20k1.c b/sound/pci/ctxfi/cthw20k1.c index dc1969bc67d4..4507f7088b24 100644 --- a/sound/pci/ctxfi/cthw20k1.c +++ b/sound/pci/ctxfi/cthw20k1.c | |||
| @@ -2085,7 +2085,7 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) | |||
| 2085 | return 0; | 2085 | return 0; |
| 2086 | } | 2086 | } |
| 2087 | 2087 | ||
| 2088 | #ifdef CONFIG_PM | 2088 | #ifdef CONFIG_PM_SLEEP |
| 2089 | static int hw_suspend(struct hw *hw) | 2089 | static int hw_suspend(struct hw *hw) |
| 2090 | { | 2090 | { |
| 2091 | struct pci_dev *pci = hw->pci; | 2091 | struct pci_dev *pci = hw->pci; |
| @@ -2180,7 +2180,7 @@ static struct hw ct20k1_preset __devinitdata = { | |||
| 2180 | .is_adc_source_selected = hw_is_adc_input_selected, | 2180 | .is_adc_source_selected = hw_is_adc_input_selected, |
| 2181 | .select_adc_source = hw_adc_input_select, | 2181 | .select_adc_source = hw_adc_input_select, |
| 2182 | .capabilities = hw_capabilities, | 2182 | .capabilities = hw_capabilities, |
| 2183 | #ifdef CONFIG_PM | 2183 | #ifdef CONFIG_PM_SLEEP |
| 2184 | .suspend = hw_suspend, | 2184 | .suspend = hw_suspend, |
| 2185 | .resume = hw_resume, | 2185 | .resume = hw_resume, |
| 2186 | #endif | 2186 | #endif |
diff --git a/sound/pci/ctxfi/cthw20k2.c b/sound/pci/ctxfi/cthw20k2.c index 9d1231dc4ae2..b9c9349058bc 100644 --- a/sound/pci/ctxfi/cthw20k2.c +++ b/sound/pci/ctxfi/cthw20k2.c | |||
| @@ -2201,7 +2201,7 @@ static int hw_card_init(struct hw *hw, struct card_conf *info) | |||
| 2201 | return 0; | 2201 | return 0; |
| 2202 | } | 2202 | } |
| 2203 | 2203 | ||
| 2204 | #ifdef CONFIG_PM | 2204 | #ifdef CONFIG_PM_SLEEP |
| 2205 | static int hw_suspend(struct hw *hw) | 2205 | static int hw_suspend(struct hw *hw) |
| 2206 | { | 2206 | { |
| 2207 | struct pci_dev *pci = hw->pci; | 2207 | struct pci_dev *pci = hw->pci; |
| @@ -2250,7 +2250,7 @@ static struct hw ct20k2_preset __devinitdata = { | |||
| 2250 | .output_switch_put = hw_output_switch_put, | 2250 | .output_switch_put = hw_output_switch_put, |
| 2251 | .mic_source_switch_get = hw_mic_source_switch_get, | 2251 | .mic_source_switch_get = hw_mic_source_switch_get, |
| 2252 | .mic_source_switch_put = hw_mic_source_switch_put, | 2252 | .mic_source_switch_put = hw_mic_source_switch_put, |
| 2253 | #ifdef CONFIG_PM | 2253 | #ifdef CONFIG_PM_SLEEP |
| 2254 | .suspend = hw_suspend, | 2254 | .suspend = hw_suspend, |
| 2255 | .resume = hw_resume, | 2255 | .resume = hw_resume, |
| 2256 | #endif | 2256 | #endif |
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c index 0cc13eeef8da..48fe0e39c2be 100644 --- a/sound/pci/ctxfi/ctmixer.c +++ b/sound/pci/ctxfi/ctmixer.c | |||
| @@ -1118,7 +1118,7 @@ mixer_set_input_right(struct ct_mixer *mixer, | |||
| 1118 | return 0; | 1118 | return 0; |
| 1119 | } | 1119 | } |
| 1120 | 1120 | ||
| 1121 | #ifdef CONFIG_PM | 1121 | #ifdef CONFIG_PM_SLEEP |
| 1122 | static int mixer_resume(struct ct_mixer *mixer) | 1122 | static int mixer_resume(struct ct_mixer *mixer) |
| 1123 | { | 1123 | { |
| 1124 | int i, state; | 1124 | int i, state; |
| @@ -1188,7 +1188,7 @@ int ct_mixer_create(struct ct_atc *atc, struct ct_mixer **rmixer) | |||
| 1188 | mixer->get_output_ports = mixer_get_output_ports; | 1188 | mixer->get_output_ports = mixer_get_output_ports; |
| 1189 | mixer->set_input_left = mixer_set_input_left; | 1189 | mixer->set_input_left = mixer_set_input_left; |
| 1190 | mixer->set_input_right = mixer_set_input_right; | 1190 | mixer->set_input_right = mixer_set_input_right; |
| 1191 | #ifdef CONFIG_PM | 1191 | #ifdef CONFIG_PM_SLEEP |
| 1192 | mixer->resume = mixer_resume; | 1192 | mixer->resume = mixer_resume; |
| 1193 | #endif | 1193 | #endif |
| 1194 | 1194 | ||
diff --git a/sound/pci/ctxfi/ctmixer.h b/sound/pci/ctxfi/ctmixer.h index b009e989e77d..be881c639fee 100644 --- a/sound/pci/ctxfi/ctmixer.h +++ b/sound/pci/ctxfi/ctmixer.h | |||
| @@ -56,7 +56,7 @@ struct ct_mixer { | |||
| 56 | enum MIXER_PORT_T type, struct rsc *rsc); | 56 | enum MIXER_PORT_T type, struct rsc *rsc); |
| 57 | int (*set_input_right)(struct ct_mixer *mixer, | 57 | int (*set_input_right)(struct ct_mixer *mixer, |
| 58 | enum MIXER_PORT_T type, struct rsc *rsc); | 58 | enum MIXER_PORT_T type, struct rsc *rsc); |
| 59 | #ifdef CONFIG_PM | 59 | #ifdef CONFIG_PM_SLEEP |
| 60 | int (*resume)(struct ct_mixer *mixer); | 60 | int (*resume)(struct ct_mixer *mixer); |
| 61 | #endif | 61 | #endif |
| 62 | }; | 62 | }; |
diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c index 2c8622617c8c..e8a4feb1ed86 100644 --- a/sound/pci/ctxfi/ctpcm.c +++ b/sound/pci/ctxfi/ctpcm.c | |||
| @@ -395,12 +395,38 @@ static struct snd_pcm_ops ct_pcm_capture_ops = { | |||
| 395 | .page = snd_pcm_sgbuf_ops_page, | 395 | .page = snd_pcm_sgbuf_ops_page, |
| 396 | }; | 396 | }; |
| 397 | 397 | ||
| 398 | static const struct snd_pcm_chmap_elem surround_map[] = { | ||
| 399 | { .channels = 1, | ||
| 400 | .map = { SNDRV_CHMAP_MONO } }, | ||
| 401 | { .channels = 2, | ||
| 402 | .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
| 403 | { } | ||
| 404 | }; | ||
| 405 | |||
| 406 | static const struct snd_pcm_chmap_elem clfe_map[] = { | ||
| 407 | { .channels = 1, | ||
| 408 | .map = { SNDRV_CHMAP_MONO } }, | ||
| 409 | { .channels = 2, | ||
| 410 | .map = { SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } }, | ||
| 411 | { } | ||
| 412 | }; | ||
| 413 | |||
| 414 | static const struct snd_pcm_chmap_elem side_map[] = { | ||
| 415 | { .channels = 1, | ||
| 416 | .map = { SNDRV_CHMAP_MONO } }, | ||
| 417 | { .channels = 2, | ||
| 418 | .map = { SNDRV_CHMAP_SL, SNDRV_CHMAP_SR } }, | ||
| 419 | { } | ||
| 420 | }; | ||
| 421 | |||
| 398 | /* Create ALSA pcm device */ | 422 | /* Create ALSA pcm device */ |
| 399 | int ct_alsa_pcm_create(struct ct_atc *atc, | 423 | int ct_alsa_pcm_create(struct ct_atc *atc, |
| 400 | enum CTALSADEVS device, | 424 | enum CTALSADEVS device, |
| 401 | const char *device_name) | 425 | const char *device_name) |
| 402 | { | 426 | { |
| 403 | struct snd_pcm *pcm; | 427 | struct snd_pcm *pcm; |
| 428 | const struct snd_pcm_chmap_elem *map; | ||
| 429 | int chs; | ||
| 404 | int err; | 430 | int err; |
| 405 | int playback_count, capture_count; | 431 | int playback_count, capture_count; |
| 406 | 432 | ||
| @@ -427,7 +453,31 @@ int ct_alsa_pcm_create(struct ct_atc *atc, | |||
| 427 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 453 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
| 428 | snd_dma_pci_data(atc->pci), 128*1024, 128*1024); | 454 | snd_dma_pci_data(atc->pci), 128*1024, 128*1024); |
| 429 | 455 | ||
| 430 | #ifdef CONFIG_PM | 456 | chs = 2; |
| 457 | switch (device) { | ||
| 458 | case FRONT: | ||
| 459 | chs = 8; | ||
| 460 | map = snd_pcm_std_chmaps; | ||
| 461 | break; | ||
| 462 | case SURROUND: | ||
| 463 | map = surround_map; | ||
| 464 | break; | ||
| 465 | case CLFE: | ||
| 466 | map = clfe_map; | ||
| 467 | break; | ||
| 468 | case SIDE: | ||
| 469 | map = side_map; | ||
| 470 | break; | ||
| 471 | default: | ||
| 472 | map = snd_pcm_std_chmaps; | ||
| 473 | break; | ||
| 474 | } | ||
| 475 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, chs, | ||
| 476 | 0, NULL); | ||
| 477 | if (err < 0) | ||
| 478 | return err; | ||
| 479 | |||
| 480 | #ifdef CONFIG_PM_SLEEP | ||
| 431 | atc->pcms[device] = pcm; | 481 | atc->pcms[device] = pcm; |
| 432 | #endif | 482 | #endif |
| 433 | 483 | ||
diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c index e002183ef8b2..07c07d752fd8 100644 --- a/sound/pci/ctxfi/xfi.c +++ b/sound/pci/ctxfi/xfi.c | |||
| @@ -125,7 +125,7 @@ static void __devexit ct_card_remove(struct pci_dev *pci) | |||
| 125 | pci_set_drvdata(pci, NULL); | 125 | pci_set_drvdata(pci, NULL); |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | #ifdef CONFIG_PM | 128 | #ifdef CONFIG_PM_SLEEP |
| 129 | static int ct_card_suspend(struct device *dev) | 129 | static int ct_card_suspend(struct device *dev) |
| 130 | { | 130 | { |
| 131 | struct snd_card *card = dev_get_drvdata(dev); | 131 | struct snd_card *card = dev_get_drvdata(dev); |
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index 0ff754f180d0..abb0b86c41c9 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c | |||
| @@ -46,7 +46,7 @@ static int get_firmware(const struct firmware **fw_entry, | |||
| 46 | int err; | 46 | int err; |
| 47 | char name[30]; | 47 | char name[30]; |
| 48 | 48 | ||
| 49 | #ifdef CONFIG_PM | 49 | #ifdef CONFIG_PM_SLEEP |
| 50 | if (chip->fw_cache[fw_index]) { | 50 | if (chip->fw_cache[fw_index]) { |
| 51 | DE_ACT(("firmware requested: %s is cached\n", card_fw[fw_index].data)); | 51 | DE_ACT(("firmware requested: %s is cached\n", card_fw[fw_index].data)); |
| 52 | *fw_entry = chip->fw_cache[fw_index]; | 52 | *fw_entry = chip->fw_cache[fw_index]; |
| @@ -59,7 +59,7 @@ static int get_firmware(const struct firmware **fw_entry, | |||
| 59 | err = request_firmware(fw_entry, name, pci_device(chip)); | 59 | err = request_firmware(fw_entry, name, pci_device(chip)); |
| 60 | if (err < 0) | 60 | if (err < 0) |
| 61 | snd_printk(KERN_ERR "get_firmware(): Firmware not available (%d)\n", err); | 61 | snd_printk(KERN_ERR "get_firmware(): Firmware not available (%d)\n", err); |
| 62 | #ifdef CONFIG_PM | 62 | #ifdef CONFIG_PM_SLEEP |
| 63 | else | 63 | else |
| 64 | chip->fw_cache[fw_index] = *fw_entry; | 64 | chip->fw_cache[fw_index] = *fw_entry; |
| 65 | #endif | 65 | #endif |
| @@ -70,7 +70,7 @@ static int get_firmware(const struct firmware **fw_entry, | |||
| 70 | 70 | ||
| 71 | static void free_firmware(const struct firmware *fw_entry) | 71 | static void free_firmware(const struct firmware *fw_entry) |
| 72 | { | 72 | { |
| 73 | #ifdef CONFIG_PM | 73 | #ifdef CONFIG_PM_SLEEP |
| 74 | DE_ACT(("firmware not released (kept in cache)\n")); | 74 | DE_ACT(("firmware not released (kept in cache)\n")); |
| 75 | #else | 75 | #else |
| 76 | release_firmware(fw_entry); | 76 | release_firmware(fw_entry); |
| @@ -82,7 +82,7 @@ static void free_firmware(const struct firmware *fw_entry) | |||
| 82 | 82 | ||
| 83 | static void free_firmware_cache(struct echoaudio *chip) | 83 | static void free_firmware_cache(struct echoaudio *chip) |
| 84 | { | 84 | { |
| 85 | #ifdef CONFIG_PM | 85 | #ifdef CONFIG_PM_SLEEP |
| 86 | int i; | 86 | int i; |
| 87 | 87 | ||
| 88 | for (i = 0; i < 8 ; i++) | 88 | for (i = 0; i < 8 ; i++) |
| @@ -2203,7 +2203,7 @@ ctl_error: | |||
| 2203 | 2203 | ||
| 2204 | 2204 | ||
| 2205 | 2205 | ||
| 2206 | #if defined(CONFIG_PM) | 2206 | #if defined(CONFIG_PM_SLEEP) |
| 2207 | 2207 | ||
| 2208 | static int snd_echo_suspend(struct device *dev) | 2208 | static int snd_echo_suspend(struct device *dev) |
| 2209 | { | 2209 | { |
| @@ -2313,7 +2313,7 @@ static SIMPLE_DEV_PM_OPS(snd_echo_pm, snd_echo_suspend, snd_echo_resume); | |||
| 2313 | #define SND_ECHO_PM_OPS &snd_echo_pm | 2313 | #define SND_ECHO_PM_OPS &snd_echo_pm |
| 2314 | #else | 2314 | #else |
| 2315 | #define SND_ECHO_PM_OPS NULL | 2315 | #define SND_ECHO_PM_OPS NULL |
| 2316 | #endif /* CONFIG_PM */ | 2316 | #endif /* CONFIG_PM_SLEEP */ |
| 2317 | 2317 | ||
| 2318 | 2318 | ||
| 2319 | static void __devexit snd_echo_remove(struct pci_dev *pci) | 2319 | static void __devexit snd_echo_remove(struct pci_dev *pci) |
diff --git a/sound/pci/echoaudio/echoaudio.h b/sound/pci/echoaudio/echoaudio.h index 1df974dcb5f4..e158369f5faa 100644 --- a/sound/pci/echoaudio/echoaudio.h +++ b/sound/pci/echoaudio/echoaudio.h | |||
| @@ -449,7 +449,7 @@ struct echoaudio { | |||
| 449 | volatile u32 __iomem *dsp_registers; /* DSP's register base */ | 449 | volatile u32 __iomem *dsp_registers; /* DSP's register base */ |
| 450 | u32 active_mask; /* Chs. active mask or | 450 | u32 active_mask; /* Chs. active mask or |
| 451 | * punks out */ | 451 | * punks out */ |
| 452 | #ifdef CONFIG_PM | 452 | #ifdef CONFIG_PM_SLEEP |
| 453 | const struct firmware *fw_cache[8]; /* Cached firmwares */ | 453 | const struct firmware *fw_cache[8]; /* Cached firmwares */ |
| 454 | #endif | 454 | #endif |
| 455 | 455 | ||
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c index ddac4e6d660d..b7c1875ba90e 100644 --- a/sound/pci/emu10k1/emu10k1.c +++ b/sound/pci/emu10k1/emu10k1.c | |||
| @@ -206,7 +206,7 @@ static void __devexit snd_card_emu10k1_remove(struct pci_dev *pci) | |||
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | 208 | ||
| 209 | #ifdef CONFIG_PM | 209 | #ifdef CONFIG_PM_SLEEP |
| 210 | static int snd_emu10k1_suspend(struct device *dev) | 210 | static int snd_emu10k1_suspend(struct device *dev) |
| 211 | { | 211 | { |
| 212 | struct pci_dev *pci = to_pci_dev(dev); | 212 | struct pci_dev *pci = to_pci_dev(dev); |
| @@ -268,7 +268,7 @@ static SIMPLE_DEV_PM_OPS(snd_emu10k1_pm, snd_emu10k1_suspend, snd_emu10k1_resume | |||
| 268 | #define SND_EMU10K1_PM_OPS &snd_emu10k1_pm | 268 | #define SND_EMU10K1_PM_OPS &snd_emu10k1_pm |
| 269 | #else | 269 | #else |
| 270 | #define SND_EMU10K1_PM_OPS NULL | 270 | #define SND_EMU10K1_PM_OPS NULL |
| 271 | #endif /* CONFIG_PM */ | 271 | #endif /* CONFIG_PM_SLEEP */ |
| 272 | 272 | ||
| 273 | static struct pci_driver emu10k1_driver = { | 273 | static struct pci_driver emu10k1_driver = { |
| 274 | .name = KBUILD_MODNAME, | 274 | .name = KBUILD_MODNAME, |
diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c index a0afa5057488..cae36597aa71 100644 --- a/sound/pci/emu10k1/emu10k1_callback.c +++ b/sound/pci/emu10k1/emu10k1_callback.c | |||
| @@ -228,7 +228,7 @@ lookup_voices(struct snd_emux *emu, struct snd_emu10k1 *hw, | |||
| 228 | int i; | 228 | int i; |
| 229 | 229 | ||
| 230 | for (i = 0; i < V_END; i++) { | 230 | for (i = 0; i < V_END; i++) { |
| 231 | best[i].time = (unsigned int)-1; /* XXX MAX_?INT really */; | 231 | best[i].time = (unsigned int)-1; /* XXX MAX_?INT really */ |
| 232 | best[i].voice = -1; | 232 | best[i].voice = -1; |
| 233 | } | 233 | } |
| 234 | 234 | ||
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 754924081d0a..bed4485f34f6 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
| @@ -1241,7 +1241,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) | |||
| 1241 | * Create the EMU10K1 instance | 1241 | * Create the EMU10K1 instance |
| 1242 | */ | 1242 | */ |
| 1243 | 1243 | ||
| 1244 | #ifdef CONFIG_PM | 1244 | #ifdef CONFIG_PM_SLEEP |
| 1245 | static int alloc_pm_buffer(struct snd_emu10k1 *emu); | 1245 | static int alloc_pm_buffer(struct snd_emu10k1 *emu); |
| 1246 | static void free_pm_buffer(struct snd_emu10k1 *emu); | 1246 | static void free_pm_buffer(struct snd_emu10k1 *emu); |
| 1247 | #endif | 1247 | #endif |
| @@ -1275,7 +1275,7 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu) | |||
| 1275 | snd_dma_free_pages(&emu->ptb_pages); | 1275 | snd_dma_free_pages(&emu->ptb_pages); |
| 1276 | vfree(emu->page_ptr_table); | 1276 | vfree(emu->page_ptr_table); |
| 1277 | vfree(emu->page_addr_table); | 1277 | vfree(emu->page_addr_table); |
| 1278 | #ifdef CONFIG_PM | 1278 | #ifdef CONFIG_PM_SLEEP |
| 1279 | free_pm_buffer(emu); | 1279 | free_pm_buffer(emu); |
| 1280 | #endif | 1280 | #endif |
| 1281 | if (emu->port) | 1281 | if (emu->port) |
| @@ -1971,7 +1971,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
| 1971 | err = snd_emu10k1_init(emu, enable_ir, 0); | 1971 | err = snd_emu10k1_init(emu, enable_ir, 0); |
| 1972 | if (err < 0) | 1972 | if (err < 0) |
| 1973 | goto error; | 1973 | goto error; |
| 1974 | #ifdef CONFIG_PM | 1974 | #ifdef CONFIG_PM_SLEEP |
| 1975 | err = alloc_pm_buffer(emu); | 1975 | err = alloc_pm_buffer(emu); |
| 1976 | if (err < 0) | 1976 | if (err < 0) |
| 1977 | goto error; | 1977 | goto error; |
| @@ -2000,7 +2000,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
| 2000 | return err; | 2000 | return err; |
| 2001 | } | 2001 | } |
| 2002 | 2002 | ||
| 2003 | #ifdef CONFIG_PM | 2003 | #ifdef CONFIG_PM_SLEEP |
| 2004 | static unsigned char saved_regs[] = { | 2004 | static unsigned char saved_regs[] = { |
| 2005 | CPF, PTRX, CVCF, VTFT, Z1, Z2, PSST, DSL, CCCA, CCR, CLP, | 2005 | CPF, PTRX, CVCF, VTFT, Z1, Z2, PSST, DSL, CCCA, CCR, CLP, |
| 2006 | FXRT, MAPA, MAPB, ENVVOL, ATKHLDV, DCYSUSV, LFOVAL1, ENVVAL, | 2006 | FXRT, MAPA, MAPB, ENVVOL, ATKHLDV, DCYSUSV, LFOVAL1, ENVVAL, |
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c index 5c8978b2c4d9..556fd6f456e3 100644 --- a/sound/pci/emu10k1/emu10k1x.c +++ b/sound/pci/emu10k1/emu10k1x.c | |||
| @@ -830,9 +830,22 @@ static irqreturn_t snd_emu10k1x_interrupt(int irq, void *dev_id) | |||
| 830 | return IRQ_HANDLED; | 830 | return IRQ_HANDLED; |
| 831 | } | 831 | } |
| 832 | 832 | ||
| 833 | static const struct snd_pcm_chmap_elem surround_map[] = { | ||
| 834 | { .channels = 2, | ||
| 835 | .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
| 836 | { } | ||
| 837 | }; | ||
| 838 | |||
| 839 | static const struct snd_pcm_chmap_elem clfe_map[] = { | ||
| 840 | { .channels = 2, | ||
| 841 | .map = { SNDRV_CHMAP_FC, SNDRV_CHMAP_LFE } }, | ||
| 842 | { } | ||
| 843 | }; | ||
| 844 | |||
| 833 | static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm) | 845 | static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct snd_pcm **rpcm) |
| 834 | { | 846 | { |
| 835 | struct snd_pcm *pcm; | 847 | struct snd_pcm *pcm; |
| 848 | const struct snd_pcm_chmap_elem *map = NULL; | ||
| 836 | int err; | 849 | int err; |
| 837 | int capture = 0; | 850 | int capture = 0; |
| 838 | 851 | ||
| @@ -861,12 +874,15 @@ static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct s | |||
| 861 | switch(device) { | 874 | switch(device) { |
| 862 | case 0: | 875 | case 0: |
| 863 | strcpy(pcm->name, "EMU10K1X Front"); | 876 | strcpy(pcm->name, "EMU10K1X Front"); |
| 877 | map = snd_pcm_std_chmaps; | ||
| 864 | break; | 878 | break; |
| 865 | case 1: | 879 | case 1: |
| 866 | strcpy(pcm->name, "EMU10K1X Rear"); | 880 | strcpy(pcm->name, "EMU10K1X Rear"); |
| 881 | map = surround_map; | ||
| 867 | break; | 882 | break; |
| 868 | case 2: | 883 | case 2: |
| 869 | strcpy(pcm->name, "EMU10K1X Center/LFE"); | 884 | strcpy(pcm->name, "EMU10K1X Center/LFE"); |
| 885 | map = clfe_map; | ||
| 870 | break; | 886 | break; |
| 871 | } | 887 | } |
| 872 | emu->pcm = pcm; | 888 | emu->pcm = pcm; |
| @@ -875,6 +891,11 @@ static int __devinit snd_emu10k1x_pcm(struct emu10k1x *emu, int device, struct s | |||
| 875 | snd_dma_pci_data(emu->pci), | 891 | snd_dma_pci_data(emu->pci), |
| 876 | 32*1024, 32*1024); | 892 | 32*1024, 32*1024); |
| 877 | 893 | ||
| 894 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, 2, | ||
| 895 | 1 << 2, NULL); | ||
| 896 | if (err < 0) | ||
| 897 | return err; | ||
| 898 | |||
| 878 | if (rpcm) | 899 | if (rpcm) |
| 879 | *rpcm = pcm; | 900 | *rpcm = pcm; |
| 880 | 901 | ||
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index dae4050ede5c..52419959178c 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c | |||
| @@ -2646,7 +2646,7 @@ int __devinit snd_emu10k1_fx8010_new(struct snd_emu10k1 *emu, int device, struct | |||
| 2646 | return 0; | 2646 | return 0; |
| 2647 | } | 2647 | } |
| 2648 | 2648 | ||
| 2649 | #ifdef CONFIG_PM | 2649 | #ifdef CONFIG_PM_SLEEP |
| 2650 | int __devinit snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu) | 2650 | int __devinit snd_emu10k1_efx_alloc_pm_buffer(struct snd_emu10k1 *emu) |
| 2651 | { | 2651 | { |
| 2652 | int len; | 2652 | int len; |
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index e22b8e2bbd88..0e6664fa6cd9 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c | |||
| @@ -1310,7 +1310,7 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) | |||
| 1310 | runtime->hw.channels_min = | 1310 | runtime->hw.channels_min = |
| 1311 | runtime->hw.channels_max = 16; | 1311 | runtime->hw.channels_max = 16; |
| 1312 | break; | 1312 | break; |
| 1313 | }; | 1313 | } |
| 1314 | #endif | 1314 | #endif |
| 1315 | #if 0 | 1315 | #if 0 |
| 1316 | /* For 96kHz */ | 1316 | /* For 96kHz */ |
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 0a436626182b..ae709c1ab3a8 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c | |||
| @@ -263,8 +263,8 @@ int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *b | |||
| 263 | spin_lock_irqsave(&emu->memblk_lock, flags); | 263 | spin_lock_irqsave(&emu->memblk_lock, flags); |
| 264 | if (blk->mapped_page >= 0) { | 264 | if (blk->mapped_page >= 0) { |
| 265 | /* update order link */ | 265 | /* update order link */ |
| 266 | list_del(&blk->mapped_order_link); | 266 | list_move_tail(&blk->mapped_order_link, |
| 267 | list_add_tail(&blk->mapped_order_link, &emu->mapped_order_link_head); | 267 | &emu->mapped_order_link_head); |
| 268 | spin_unlock_irqrestore(&emu->memblk_lock, flags); | 268 | spin_unlock_irqrestore(&emu->memblk_lock, flags); |
| 269 | return 0; | 269 | return 0; |
| 270 | } | 270 | } |
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c index a81dc44228ea..88cec6b7dd41 100644 --- a/sound/pci/emu10k1/p16v.c +++ b/sound/pci/emu10k1/p16v.c | |||
| @@ -893,7 +893,7 @@ int __devinit snd_p16v_mixer(struct snd_emu10k1 *emu) | |||
| 893 | return 0; | 893 | return 0; |
| 894 | } | 894 | } |
| 895 | 895 | ||
| 896 | #ifdef CONFIG_PM | 896 | #ifdef CONFIG_PM_SLEEP |
| 897 | 897 | ||
| 898 | #define NUM_CHS 1 /* up to 4, but only first channel is used */ | 898 | #define NUM_CHS 1 /* up to 4, but only first channel is used */ |
| 899 | 899 | ||
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index f7e6f73186e1..5674cc316530 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
| @@ -55,8 +55,10 @@ | |||
| 55 | 55 | ||
| 56 | #ifdef CHIP1370 | 56 | #ifdef CHIP1370 |
| 57 | #define DRIVER_NAME "ENS1370" | 57 | #define DRIVER_NAME "ENS1370" |
| 58 | #define CHIP_NAME "ES1370" /* it can be ENS but just to keep compatibility... */ | ||
| 58 | #else | 59 | #else |
| 59 | #define DRIVER_NAME "ENS1371" | 60 | #define DRIVER_NAME "ENS1371" |
| 61 | #define CHIP_NAME "ES1371" | ||
| 60 | #endif | 62 | #endif |
| 61 | 63 | ||
| 62 | 64 | ||
| @@ -1258,6 +1260,14 @@ static struct snd_pcm_ops snd_ensoniq_capture_ops = { | |||
| 1258 | .pointer = snd_ensoniq_capture_pointer, | 1260 | .pointer = snd_ensoniq_capture_pointer, |
| 1259 | }; | 1261 | }; |
| 1260 | 1262 | ||
| 1263 | static const struct snd_pcm_chmap_elem surround_map[] = { | ||
| 1264 | { .channels = 1, | ||
| 1265 | .map = { SNDRV_CHMAP_MONO } }, | ||
| 1266 | { .channels = 2, | ||
| 1267 | .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
| 1268 | { } | ||
| 1269 | }; | ||
| 1270 | |||
| 1261 | static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device, | 1271 | static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device, |
| 1262 | struct snd_pcm ** rpcm) | 1272 | struct snd_pcm ** rpcm) |
| 1263 | { | 1273 | { |
| @@ -1266,11 +1276,7 @@ static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device, | |||
| 1266 | 1276 | ||
| 1267 | if (rpcm) | 1277 | if (rpcm) |
| 1268 | *rpcm = NULL; | 1278 | *rpcm = NULL; |
| 1269 | #ifdef CHIP1370 | 1279 | err = snd_pcm_new(ensoniq->card, CHIP_NAME "/1", device, 1, 1, &pcm); |
| 1270 | err = snd_pcm_new(ensoniq->card, "ES1370/1", device, 1, 1, &pcm); | ||
| 1271 | #else | ||
| 1272 | err = snd_pcm_new(ensoniq->card, "ES1371/1", device, 1, 1, &pcm); | ||
| 1273 | #endif | ||
| 1274 | if (err < 0) | 1280 | if (err < 0) |
| 1275 | return err; | 1281 | return err; |
| 1276 | 1282 | ||
| @@ -1283,16 +1289,22 @@ static int __devinit snd_ensoniq_pcm(struct ensoniq * ensoniq, int device, | |||
| 1283 | 1289 | ||
| 1284 | pcm->private_data = ensoniq; | 1290 | pcm->private_data = ensoniq; |
| 1285 | pcm->info_flags = 0; | 1291 | pcm->info_flags = 0; |
| 1286 | #ifdef CHIP1370 | 1292 | strcpy(pcm->name, CHIP_NAME " DAC2/ADC"); |
| 1287 | strcpy(pcm->name, "ES1370 DAC2/ADC"); | ||
| 1288 | #else | ||
| 1289 | strcpy(pcm->name, "ES1371 DAC2/ADC"); | ||
| 1290 | #endif | ||
| 1291 | ensoniq->pcm1 = pcm; | 1293 | ensoniq->pcm1 = pcm; |
| 1292 | 1294 | ||
| 1293 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1295 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
| 1294 | snd_dma_pci_data(ensoniq->pci), 64*1024, 128*1024); | 1296 | snd_dma_pci_data(ensoniq->pci), 64*1024, 128*1024); |
| 1295 | 1297 | ||
| 1298 | #ifdef CHIP1370 | ||
| 1299 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
| 1300 | surround_map, 2, 0, NULL); | ||
| 1301 | #else | ||
| 1302 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
| 1303 | snd_pcm_std_chmaps, 2, 0, NULL); | ||
| 1304 | #endif | ||
| 1305 | if (err < 0) | ||
| 1306 | return err; | ||
| 1307 | |||
| 1296 | if (rpcm) | 1308 | if (rpcm) |
| 1297 | *rpcm = pcm; | 1309 | *rpcm = pcm; |
| 1298 | return 0; | 1310 | return 0; |
| @@ -1306,11 +1318,7 @@ static int __devinit snd_ensoniq_pcm2(struct ensoniq * ensoniq, int device, | |||
| 1306 | 1318 | ||
| 1307 | if (rpcm) | 1319 | if (rpcm) |
| 1308 | *rpcm = NULL; | 1320 | *rpcm = NULL; |
| 1309 | #ifdef CHIP1370 | 1321 | err = snd_pcm_new(ensoniq->card, CHIP_NAME "/2", device, 1, 0, &pcm); |
| 1310 | err = snd_pcm_new(ensoniq->card, "ES1370/2", device, 1, 0, &pcm); | ||
| 1311 | #else | ||
| 1312 | err = snd_pcm_new(ensoniq->card, "ES1371/2", device, 1, 0, &pcm); | ||
| 1313 | #endif | ||
| 1314 | if (err < 0) | 1322 | if (err < 0) |
| 1315 | return err; | 1323 | return err; |
| 1316 | 1324 | ||
| @@ -1321,16 +1329,22 @@ static int __devinit snd_ensoniq_pcm2(struct ensoniq * ensoniq, int device, | |||
| 1321 | #endif | 1329 | #endif |
| 1322 | pcm->private_data = ensoniq; | 1330 | pcm->private_data = ensoniq; |
| 1323 | pcm->info_flags = 0; | 1331 | pcm->info_flags = 0; |
| 1324 | #ifdef CHIP1370 | 1332 | strcpy(pcm->name, CHIP_NAME " DAC1"); |
| 1325 | strcpy(pcm->name, "ES1370 DAC1"); | ||
| 1326 | #else | ||
| 1327 | strcpy(pcm->name, "ES1371 DAC1"); | ||
| 1328 | #endif | ||
| 1329 | ensoniq->pcm2 = pcm; | 1333 | ensoniq->pcm2 = pcm; |
| 1330 | 1334 | ||
| 1331 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1335 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
| 1332 | snd_dma_pci_data(ensoniq->pci), 64*1024, 128*1024); | 1336 | snd_dma_pci_data(ensoniq->pci), 64*1024, 128*1024); |
| 1333 | 1337 | ||
| 1338 | #ifdef CHIP1370 | ||
| 1339 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
| 1340 | snd_pcm_std_chmaps, 2, 0, NULL); | ||
| 1341 | #else | ||
| 1342 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
| 1343 | surround_map, 2, 0, NULL); | ||
| 1344 | #endif | ||
| 1345 | if (err < 0) | ||
| 1346 | return err; | ||
| 1347 | |||
| 1334 | if (rpcm) | 1348 | if (rpcm) |
| 1335 | *rpcm = pcm; | 1349 | *rpcm = pcm; |
| 1336 | return 0; | 1350 | return 0; |
| @@ -1885,11 +1899,7 @@ static void snd_ensoniq_proc_read(struct snd_info_entry *entry, | |||
| 1885 | { | 1899 | { |
| 1886 | struct ensoniq *ensoniq = entry->private_data; | 1900 | struct ensoniq *ensoniq = entry->private_data; |
| 1887 | 1901 | ||
| 1888 | #ifdef CHIP1370 | 1902 | snd_iprintf(buffer, "Ensoniq AudioPCI " CHIP_NAME "\n\n"); |
| 1889 | snd_iprintf(buffer, "Ensoniq AudioPCI ES1370\n\n"); | ||
| 1890 | #else | ||
| 1891 | snd_iprintf(buffer, "Ensoniq AudioPCI ES1371\n\n"); | ||
| 1892 | #endif | ||
| 1893 | snd_iprintf(buffer, "Joystick enable : %s\n", | 1903 | snd_iprintf(buffer, "Joystick enable : %s\n", |
| 1894 | ensoniq->ctrl & ES_JYSTK_EN ? "on" : "off"); | 1904 | ensoniq->ctrl & ES_JYSTK_EN ? "on" : "off"); |
| 1895 | #ifdef CHIP1370 | 1905 | #ifdef CHIP1370 |
| @@ -2032,7 +2042,7 @@ static void snd_ensoniq_chip_init(struct ensoniq *ensoniq) | |||
| 2032 | synchronize_irq(ensoniq->irq); | 2042 | synchronize_irq(ensoniq->irq); |
| 2033 | } | 2043 | } |
| 2034 | 2044 | ||
| 2035 | #ifdef CONFIG_PM | 2045 | #ifdef CONFIG_PM_SLEEP |
| 2036 | static int snd_ensoniq_suspend(struct device *dev) | 2046 | static int snd_ensoniq_suspend(struct device *dev) |
| 2037 | { | 2047 | { |
| 2038 | struct pci_dev *pci = to_pci_dev(dev); | 2048 | struct pci_dev *pci = to_pci_dev(dev); |
| @@ -2094,7 +2104,7 @@ static SIMPLE_DEV_PM_OPS(snd_ensoniq_pm, snd_ensoniq_suspend, snd_ensoniq_resume | |||
| 2094 | #define SND_ENSONIQ_PM_OPS &snd_ensoniq_pm | 2104 | #define SND_ENSONIQ_PM_OPS &snd_ensoniq_pm |
| 2095 | #else | 2105 | #else |
| 2096 | #define SND_ENSONIQ_PM_OPS NULL | 2106 | #define SND_ENSONIQ_PM_OPS NULL |
| 2097 | #endif /* CONFIG_PM */ | 2107 | #endif /* CONFIG_PM_SLEEP */ |
| 2098 | 2108 | ||
| 2099 | static int __devinit snd_ensoniq_create(struct snd_card *card, | 2109 | static int __devinit snd_ensoniq_create(struct snd_card *card, |
| 2100 | struct pci_dev *pci, | 2110 | struct pci_dev *pci, |
| @@ -2361,11 +2371,7 @@ static int __devinit snd_ensoniq_midi(struct ensoniq * ensoniq, int device, | |||
| 2361 | *rrawmidi = NULL; | 2371 | *rrawmidi = NULL; |
| 2362 | if ((err = snd_rawmidi_new(ensoniq->card, "ES1370/1", device, 1, 1, &rmidi)) < 0) | 2372 | if ((err = snd_rawmidi_new(ensoniq->card, "ES1370/1", device, 1, 1, &rmidi)) < 0) |
| 2363 | return err; | 2373 | return err; |
| 2364 | #ifdef CHIP1370 | 2374 | strcpy(rmidi->name, CHIP_NAME); |
| 2365 | strcpy(rmidi->name, "ES1370"); | ||
| 2366 | #else | ||
| 2367 | strcpy(rmidi->name, "ES1371"); | ||
| 2368 | #endif | ||
| 2369 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_ensoniq_midi_output); | 2375 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_ensoniq_midi_output); |
| 2370 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_ensoniq_midi_input); | 2376 | snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_ensoniq_midi_input); |
| 2371 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | | 2377 | rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | |
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c index dbb81807bc1a..394c5d413530 100644 --- a/sound/pci/es1938.c +++ b/sound/pci/es1938.c | |||
| @@ -236,7 +236,7 @@ struct es1938 { | |||
| 236 | #ifdef SUPPORT_JOYSTICK | 236 | #ifdef SUPPORT_JOYSTICK |
| 237 | struct gameport *gameport; | 237 | struct gameport *gameport; |
| 238 | #endif | 238 | #endif |
| 239 | #ifdef CONFIG_PM | 239 | #ifdef CONFIG_PM_SLEEP |
| 240 | unsigned char saved_regs[SAVED_REG_SIZE]; | 240 | unsigned char saved_regs[SAVED_REG_SIZE]; |
| 241 | #endif | 241 | #endif |
| 242 | }; | 242 | }; |
| @@ -1456,7 +1456,7 @@ static void snd_es1938_chip_init(struct es1938 *chip) | |||
| 1456 | outb(0, SLDM_REG(chip, DMACLEAR)); | 1456 | outb(0, SLDM_REG(chip, DMACLEAR)); |
| 1457 | } | 1457 | } |
| 1458 | 1458 | ||
| 1459 | #ifdef CONFIG_PM | 1459 | #ifdef CONFIG_PM_SLEEP |
| 1460 | /* | 1460 | /* |
| 1461 | * PM support | 1461 | * PM support |
| 1462 | */ | 1462 | */ |
| @@ -1536,7 +1536,7 @@ static SIMPLE_DEV_PM_OPS(es1938_pm, es1938_suspend, es1938_resume); | |||
| 1536 | #define ES1938_PM_OPS &es1938_pm | 1536 | #define ES1938_PM_OPS &es1938_pm |
| 1537 | #else | 1537 | #else |
| 1538 | #define ES1938_PM_OPS NULL | 1538 | #define ES1938_PM_OPS NULL |
| 1539 | #endif /* CONFIG_PM */ | 1539 | #endif /* CONFIG_PM_SLEEP */ |
| 1540 | 1540 | ||
| 1541 | #ifdef SUPPORT_JOYSTICK | 1541 | #ifdef SUPPORT_JOYSTICK |
| 1542 | static int __devinit snd_es1938_create_gameport(struct es1938 *chip) | 1542 | static int __devinit snd_es1938_create_gameport(struct es1938 *chip) |
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c index fb4c90b99c00..5d0e568fdea1 100644 --- a/sound/pci/es1968.c +++ b/sound/pci/es1968.c | |||
| @@ -491,7 +491,7 @@ struct esschan { | |||
| 491 | /* linked list */ | 491 | /* linked list */ |
| 492 | struct list_head list; | 492 | struct list_head list; |
| 493 | 493 | ||
| 494 | #ifdef CONFIG_PM | 494 | #ifdef CONFIG_PM_SLEEP |
| 495 | u16 wc_map[4]; | 495 | u16 wc_map[4]; |
| 496 | #endif | 496 | #endif |
| 497 | }; | 497 | }; |
| @@ -544,7 +544,7 @@ struct es1968 { | |||
| 544 | struct list_head substream_list; | 544 | struct list_head substream_list; |
| 545 | spinlock_t substream_lock; | 545 | spinlock_t substream_lock; |
| 546 | 546 | ||
| 547 | #ifdef CONFIG_PM | 547 | #ifdef CONFIG_PM_SLEEP |
| 548 | u16 apu_map[NR_APUS][NR_APU_REGS]; | 548 | u16 apu_map[NR_APUS][NR_APU_REGS]; |
| 549 | #endif | 549 | #endif |
| 550 | 550 | ||
| @@ -706,7 +706,7 @@ static void __apu_set_register(struct es1968 *chip, u16 channel, u8 reg, u16 dat | |||
| 706 | { | 706 | { |
| 707 | if (snd_BUG_ON(channel >= NR_APUS)) | 707 | if (snd_BUG_ON(channel >= NR_APUS)) |
| 708 | return; | 708 | return; |
| 709 | #ifdef CONFIG_PM | 709 | #ifdef CONFIG_PM_SLEEP |
| 710 | chip->apu_map[channel][reg] = data; | 710 | chip->apu_map[channel][reg] = data; |
| 711 | #endif | 711 | #endif |
| 712 | reg |= (channel << 4); | 712 | reg |= (channel << 4); |
| @@ -993,7 +993,7 @@ static void snd_es1968_program_wavecache(struct es1968 *chip, struct esschan *es | |||
| 993 | /* set the wavecache control reg */ | 993 | /* set the wavecache control reg */ |
| 994 | wave_set_register(chip, es->apu[channel] << 3, tmpval); | 994 | wave_set_register(chip, es->apu[channel] << 3, tmpval); |
| 995 | 995 | ||
| 996 | #ifdef CONFIG_PM | 996 | #ifdef CONFIG_PM_SLEEP |
| 997 | es->wc_map[channel] = tmpval; | 997 | es->wc_map[channel] = tmpval; |
| 998 | #endif | 998 | #endif |
| 999 | } | 999 | } |
| @@ -2377,7 +2377,7 @@ static void snd_es1968_start_irq(struct es1968 *chip) | |||
| 2377 | outw(w, chip->io_port + ESM_PORT_HOST_IRQ); | 2377 | outw(w, chip->io_port + ESM_PORT_HOST_IRQ); |
| 2378 | } | 2378 | } |
| 2379 | 2379 | ||
| 2380 | #ifdef CONFIG_PM | 2380 | #ifdef CONFIG_PM_SLEEP |
| 2381 | /* | 2381 | /* |
| 2382 | * PM support | 2382 | * PM support |
| 2383 | */ | 2383 | */ |
| @@ -2461,7 +2461,7 @@ static SIMPLE_DEV_PM_OPS(es1968_pm, es1968_suspend, es1968_resume); | |||
| 2461 | #define ES1968_PM_OPS &es1968_pm | 2461 | #define ES1968_PM_OPS &es1968_pm |
| 2462 | #else | 2462 | #else |
| 2463 | #define ES1968_PM_OPS NULL | 2463 | #define ES1968_PM_OPS NULL |
| 2464 | #endif /* CONFIG_PM */ | 2464 | #endif /* CONFIG_PM_SLEEP */ |
| 2465 | 2465 | ||
| 2466 | #ifdef SUPPORT_JOYSTICK | 2466 | #ifdef SUPPORT_JOYSTICK |
| 2467 | #define JOYSTICK_ADDR 0x200 | 2467 | #define JOYSTICK_ADDR 0x200 |
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index 522c8706f244..cc2e91d15538 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c | |||
| @@ -205,7 +205,7 @@ struct fm801 { | |||
| 205 | struct snd_tea575x tea; | 205 | struct snd_tea575x tea; |
| 206 | #endif | 206 | #endif |
| 207 | 207 | ||
| 208 | #ifdef CONFIG_PM | 208 | #ifdef CONFIG_PM_SLEEP |
| 209 | u16 saved_regs[0x20]; | 209 | u16 saved_regs[0x20]; |
| 210 | #endif | 210 | #endif |
| 211 | }; | 211 | }; |
| @@ -711,6 +711,13 @@ static int __devinit snd_fm801_pcm(struct fm801 *chip, int device, struct snd_pc | |||
| 711 | snd_dma_pci_data(chip->pci), | 711 | snd_dma_pci_data(chip->pci), |
| 712 | chip->multichannel ? 128*1024 : 64*1024, 128*1024); | 712 | chip->multichannel ? 128*1024 : 64*1024, 128*1024); |
| 713 | 713 | ||
| 714 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
| 715 | snd_pcm_alt_chmaps, | ||
| 716 | chip->multichannel ? 6 : 2, 0, | ||
| 717 | NULL); | ||
| 718 | if (err < 0) | ||
| 719 | return err; | ||
| 720 | |||
| 714 | if (rpcm) | 721 | if (rpcm) |
| 715 | *rpcm = pcm; | 722 | *rpcm = pcm; |
| 716 | return 0; | 723 | return 0; |
| @@ -1361,7 +1368,7 @@ static void __devexit snd_card_fm801_remove(struct pci_dev *pci) | |||
| 1361 | pci_set_drvdata(pci, NULL); | 1368 | pci_set_drvdata(pci, NULL); |
| 1362 | } | 1369 | } |
| 1363 | 1370 | ||
| 1364 | #ifdef CONFIG_PM | 1371 | #ifdef CONFIG_PM_SLEEP |
| 1365 | static unsigned char saved_regs[] = { | 1372 | static unsigned char saved_regs[] = { |
| 1366 | FM801_PCM_VOL, FM801_I2S_VOL, FM801_FM_VOL, FM801_REC_SRC, | 1373 | FM801_PCM_VOL, FM801_I2S_VOL, FM801_FM_VOL, FM801_REC_SRC, |
| 1367 | FM801_PLY_CTRL, FM801_PLY_COUNT, FM801_PLY_BUF1, FM801_PLY_BUF2, | 1374 | FM801_PLY_CTRL, FM801_PLY_COUNT, FM801_PLY_BUF1, FM801_PLY_BUF2, |
| @@ -1421,7 +1428,7 @@ static SIMPLE_DEV_PM_OPS(snd_fm801_pm, snd_fm801_suspend, snd_fm801_resume); | |||
| 1421 | #define SND_FM801_PM_OPS &snd_fm801_pm | 1428 | #define SND_FM801_PM_OPS &snd_fm801_pm |
| 1422 | #else | 1429 | #else |
| 1423 | #define SND_FM801_PM_OPS NULL | 1430 | #define SND_FM801_PM_OPS NULL |
| 1424 | #endif /* CONFIG_PM */ | 1431 | #endif /* CONFIG_PM_SLEEP */ |
| 1425 | 1432 | ||
| 1426 | static struct pci_driver fm801_driver = { | 1433 | static struct pci_driver fm801_driver = { |
| 1427 | .name = KBUILD_MODNAME, | 1434 | .name = KBUILD_MODNAME, |
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 194d625c1f83..7105c3de1bca 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
| @@ -228,17 +228,9 @@ config SND_HDA_GENERIC | |||
| 228 | Say Y here to enable the generic HD-audio codec parser | 228 | Say Y here to enable the generic HD-audio codec parser |
| 229 | in snd-hda-intel driver. | 229 | in snd-hda-intel driver. |
| 230 | 230 | ||
| 231 | config SND_HDA_POWER_SAVE | ||
| 232 | bool "Aggressive power-saving on HD-audio" | ||
| 233 | depends on PM | ||
| 234 | help | ||
| 235 | Say Y here to enable more aggressive power-saving mode on | ||
| 236 | HD-audio driver. The power-saving timeout can be configured | ||
| 237 | via power_save option or over sysfs on-the-fly. | ||
| 238 | |||
| 239 | config SND_HDA_POWER_SAVE_DEFAULT | 231 | config SND_HDA_POWER_SAVE_DEFAULT |
| 240 | int "Default time-out for HD-audio power-save mode" | 232 | int "Default time-out for HD-audio power-save mode" |
| 241 | depends on SND_HDA_POWER_SAVE | 233 | depends on PM |
| 242 | default 0 | 234 | default 0 |
| 243 | help | 235 | help |
| 244 | The default time-out value in seconds for HD-audio automatic | 236 | The default time-out value in seconds for HD-audio automatic |
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c index 4f7d2dfcef7b..4ec6dc88b7f8 100644 --- a/sound/pci/hda/hda_auto_parser.c +++ b/sound/pci/hda/hda_auto_parser.c | |||
| @@ -141,7 +141,6 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, | |||
| 141 | memset(sequences_hp, 0, sizeof(sequences_hp)); | 141 | memset(sequences_hp, 0, sizeof(sequences_hp)); |
| 142 | assoc_line_out = 0; | 142 | assoc_line_out = 0; |
| 143 | 143 | ||
| 144 | codec->ignore_misc_bit = true; | ||
| 145 | end_nid = codec->start_nid + codec->num_nodes; | 144 | end_nid = codec->start_nid + codec->num_nodes; |
| 146 | for (nid = codec->start_nid; nid < end_nid; nid++) { | 145 | for (nid = codec->start_nid; nid < end_nid; nid++) { |
| 147 | unsigned int wid_caps = get_wcaps(codec, nid); | 146 | unsigned int wid_caps = get_wcaps(codec, nid); |
| @@ -157,9 +156,6 @@ int snd_hda_parse_pin_defcfg(struct hda_codec *codec, | |||
| 157 | continue; | 156 | continue; |
| 158 | 157 | ||
| 159 | def_conf = snd_hda_codec_get_pincfg(codec, nid); | 158 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
| 160 | if (!(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & | ||
| 161 | AC_DEFCFG_MISC_NO_PRESENCE)) | ||
| 162 | codec->ignore_misc_bit = false; | ||
| 163 | conn = get_defcfg_connect(def_conf); | 159 | conn = get_defcfg_connect(def_conf); |
| 164 | if (conn == AC_JACK_PORT_NONE) | 160 | if (conn == AC_JACK_PORT_NONE) |
| 165 | continue; | 161 | continue; |
| @@ -502,6 +498,38 @@ static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins, | |||
| 502 | return channel_sfx[i]; | 498 | return channel_sfx[i]; |
| 503 | } | 499 | } |
| 504 | 500 | ||
| 501 | static const char *check_output_pfx(struct hda_codec *codec, hda_nid_t nid) | ||
| 502 | { | ||
| 503 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); | ||
| 504 | int attr = snd_hda_get_input_pin_attr(def_conf); | ||
| 505 | |||
| 506 | /* check the location */ | ||
| 507 | switch (attr) { | ||
| 508 | case INPUT_PIN_ATTR_DOCK: | ||
| 509 | return "Dock "; | ||
| 510 | case INPUT_PIN_ATTR_FRONT: | ||
| 511 | return "Front "; | ||
| 512 | } | ||
| 513 | return ""; | ||
| 514 | } | ||
| 515 | |||
| 516 | static int get_hp_label_index(struct hda_codec *codec, hda_nid_t nid, | ||
| 517 | const hda_nid_t *pins, int num_pins) | ||
| 518 | { | ||
| 519 | int i, j, idx = 0; | ||
| 520 | |||
| 521 | const char *pfx = check_output_pfx(codec, nid); | ||
| 522 | |||
| 523 | i = find_idx_in_nid_list(nid, pins, num_pins); | ||
| 524 | if (i < 0) | ||
| 525 | return -1; | ||
| 526 | for (j = 0; j < i; j++) | ||
| 527 | if (pfx == check_output_pfx(codec, pins[j])) | ||
| 528 | idx++; | ||
| 529 | |||
| 530 | return idx; | ||
| 531 | } | ||
| 532 | |||
| 505 | static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid, | 533 | static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid, |
| 506 | const struct auto_pin_cfg *cfg, | 534 | const struct auto_pin_cfg *cfg, |
| 507 | const char *name, char *label, int maxlen, | 535 | const char *name, char *label, int maxlen, |
| @@ -509,20 +537,13 @@ static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid, | |||
| 509 | { | 537 | { |
| 510 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); | 538 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); |
| 511 | int attr = snd_hda_get_input_pin_attr(def_conf); | 539 | int attr = snd_hda_get_input_pin_attr(def_conf); |
| 512 | const char *pfx = "", *sfx = ""; | 540 | const char *pfx, *sfx = ""; |
| 513 | 541 | ||
| 514 | /* handle as a speaker if it's a fixed line-out */ | 542 | /* handle as a speaker if it's a fixed line-out */ |
| 515 | if (!strcmp(name, "Line Out") && attr == INPUT_PIN_ATTR_INT) | 543 | if (!strcmp(name, "Line Out") && attr == INPUT_PIN_ATTR_INT) |
| 516 | name = "Speaker"; | 544 | name = "Speaker"; |
| 517 | /* check the location */ | 545 | pfx = check_output_pfx(codec, nid); |
| 518 | switch (attr) { | 546 | |
| 519 | case INPUT_PIN_ATTR_DOCK: | ||
| 520 | pfx = "Dock "; | ||
| 521 | break; | ||
| 522 | case INPUT_PIN_ATTR_FRONT: | ||
| 523 | pfx = "Front "; | ||
| 524 | break; | ||
| 525 | } | ||
| 526 | if (cfg) { | 547 | if (cfg) { |
| 527 | /* try to give a unique suffix if needed */ | 548 | /* try to give a unique suffix if needed */ |
| 528 | sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs, | 549 | sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs, |
| @@ -532,8 +553,8 @@ static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid, | |||
| 532 | indexp); | 553 | indexp); |
| 533 | if (!sfx) { | 554 | if (!sfx) { |
| 534 | /* don't add channel suffix for Headphone controls */ | 555 | /* don't add channel suffix for Headphone controls */ |
| 535 | int idx = find_idx_in_nid_list(nid, cfg->hp_pins, | 556 | int idx = get_hp_label_index(codec, nid, cfg->hp_pins, |
| 536 | cfg->hp_outs); | 557 | cfg->hp_outs); |
| 537 | if (idx >= 0) | 558 | if (idx >= 0) |
| 538 | *indexp = idx; | 559 | *indexp = idx; |
| 539 | sfx = ""; | 560 | sfx = ""; |
| @@ -739,7 +760,8 @@ void snd_hda_pick_fixup(struct hda_codec *codec, | |||
| 739 | for (q = quirk; q->subvendor; q++) { | 760 | for (q = quirk; q->subvendor; q++) { |
| 740 | unsigned int vendorid = | 761 | unsigned int vendorid = |
| 741 | q->subdevice | (q->subvendor << 16); | 762 | q->subdevice | (q->subvendor << 16); |
| 742 | if (vendorid == codec->subsystem_id) { | 763 | unsigned int mask = 0xffff0000 | q->subdevice_mask; |
| 764 | if ((codec->subsystem_id & mask) == (vendorid & mask)) { | ||
| 743 | id = q->value; | 765 | id = q->value; |
| 744 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 766 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
| 745 | name = q->name; | 767 | name = q->name; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 1c65cc5e3a31..c0ab72cbeed1 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
| @@ -94,13 +94,19 @@ int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset) | |||
| 94 | } | 94 | } |
| 95 | EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset); | 95 | EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset); |
| 96 | 96 | ||
| 97 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 97 | #ifdef CONFIG_PM |
| 98 | static void hda_power_work(struct work_struct *work); | 98 | static void hda_power_work(struct work_struct *work); |
| 99 | static void hda_keep_power_on(struct hda_codec *codec); | 99 | static void hda_keep_power_on(struct hda_codec *codec); |
| 100 | #define hda_codec_is_power_on(codec) ((codec)->power_on) | 100 | #define hda_codec_is_power_on(codec) ((codec)->power_on) |
| 101 | static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up) | ||
| 102 | { | ||
| 103 | if (bus->ops.pm_notify) | ||
| 104 | bus->ops.pm_notify(bus, power_up); | ||
| 105 | } | ||
| 101 | #else | 106 | #else |
| 102 | static inline void hda_keep_power_on(struct hda_codec *codec) {} | 107 | static inline void hda_keep_power_on(struct hda_codec *codec) {} |
| 103 | #define hda_codec_is_power_on(codec) 1 | 108 | #define hda_codec_is_power_on(codec) 1 |
| 109 | #define hda_call_pm_notify(bus, state) {} | ||
| 104 | #endif | 110 | #endif |
| 105 | 111 | ||
| 106 | /** | 112 | /** |
| @@ -808,7 +814,7 @@ find_codec_preset(struct hda_codec *codec) | |||
| 808 | { | 814 | { |
| 809 | struct hda_codec_preset_list *tbl; | 815 | struct hda_codec_preset_list *tbl; |
| 810 | const struct hda_codec_preset *preset; | 816 | const struct hda_codec_preset *preset; |
| 811 | int mod_requested = 0; | 817 | unsigned int mod_requested = 0; |
| 812 | 818 | ||
| 813 | if (is_generic_config(codec)) | 819 | if (is_generic_config(codec)) |
| 814 | return NULL; /* use the generic parser */ | 820 | return NULL; /* use the generic parser */ |
| @@ -1186,7 +1192,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
| 1186 | return; | 1192 | return; |
| 1187 | snd_hda_jack_tbl_clear(codec); | 1193 | snd_hda_jack_tbl_clear(codec); |
| 1188 | restore_init_pincfgs(codec); | 1194 | restore_init_pincfgs(codec); |
| 1189 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1195 | #ifdef CONFIG_PM |
| 1190 | cancel_delayed_work(&codec->power_work); | 1196 | cancel_delayed_work(&codec->power_work); |
| 1191 | flush_workqueue(codec->bus->workq); | 1197 | flush_workqueue(codec->bus->workq); |
| 1192 | #endif | 1198 | #endif |
| @@ -1199,6 +1205,10 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
| 1199 | codec->bus->caddr_tbl[codec->addr] = NULL; | 1205 | codec->bus->caddr_tbl[codec->addr] = NULL; |
| 1200 | if (codec->patch_ops.free) | 1206 | if (codec->patch_ops.free) |
| 1201 | codec->patch_ops.free(codec); | 1207 | codec->patch_ops.free(codec); |
| 1208 | #ifdef CONFIG_PM | ||
| 1209 | if (!codec->pm_down_notified) /* cancel leftover refcounts */ | ||
| 1210 | hda_call_pm_notify(codec->bus, false); | ||
| 1211 | #endif | ||
| 1202 | module_put(codec->owner); | 1212 | module_put(codec->owner); |
| 1203 | free_hda_cache(&codec->amp_cache); | 1213 | free_hda_cache(&codec->amp_cache); |
| 1204 | free_hda_cache(&codec->cmd_cache); | 1214 | free_hda_cache(&codec->cmd_cache); |
| @@ -1212,7 +1222,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
| 1212 | static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, | 1222 | static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, |
| 1213 | hda_nid_t fg, unsigned int power_state); | 1223 | hda_nid_t fg, unsigned int power_state); |
| 1214 | 1224 | ||
| 1215 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | 1225 | static unsigned int hda_set_power_state(struct hda_codec *codec, |
| 1216 | unsigned int power_state); | 1226 | unsigned int power_state); |
| 1217 | 1227 | ||
| 1218 | /** | 1228 | /** |
| @@ -1229,6 +1239,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, | |||
| 1229 | { | 1239 | { |
| 1230 | struct hda_codec *codec; | 1240 | struct hda_codec *codec; |
| 1231 | char component[31]; | 1241 | char component[31]; |
| 1242 | hda_nid_t fg; | ||
| 1232 | int err; | 1243 | int err; |
| 1233 | 1244 | ||
| 1234 | if (snd_BUG_ON(!bus)) | 1245 | if (snd_BUG_ON(!bus)) |
| @@ -1263,7 +1274,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, | |||
| 1263 | snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64); | 1274 | snd_array_init(&codec->conn_lists, sizeof(hda_nid_t), 64); |
| 1264 | snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16); | 1275 | snd_array_init(&codec->spdif_out, sizeof(struct hda_spdif_out), 16); |
| 1265 | 1276 | ||
| 1266 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1277 | #ifdef CONFIG_PM |
| 1267 | spin_lock_init(&codec->power_lock); | 1278 | spin_lock_init(&codec->power_lock); |
| 1268 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); | 1279 | INIT_DELAYED_WORK(&codec->power_work, hda_power_work); |
| 1269 | /* snd_hda_codec_new() marks the codec as power-up, and leave it as is. | 1280 | /* snd_hda_codec_new() marks the codec as power-up, and leave it as is. |
| @@ -1271,6 +1282,7 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, | |||
| 1271 | * phase. | 1282 | * phase. |
| 1272 | */ | 1283 | */ |
| 1273 | hda_keep_power_on(codec); | 1284 | hda_keep_power_on(codec); |
| 1285 | hda_call_pm_notify(bus, true); | ||
| 1274 | #endif | 1286 | #endif |
| 1275 | 1287 | ||
| 1276 | if (codec->bus->modelname) { | 1288 | if (codec->bus->modelname) { |
| @@ -1304,7 +1316,8 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, | |||
| 1304 | goto error; | 1316 | goto error; |
| 1305 | } | 1317 | } |
| 1306 | 1318 | ||
| 1307 | err = read_widget_caps(codec, codec->afg ? codec->afg : codec->mfg); | 1319 | fg = codec->afg ? codec->afg : codec->mfg; |
| 1320 | err = read_widget_caps(codec, fg); | ||
| 1308 | if (err < 0) { | 1321 | if (err < 0) { |
| 1309 | snd_printk(KERN_ERR "hda_codec: cannot malloc\n"); | 1322 | snd_printk(KERN_ERR "hda_codec: cannot malloc\n"); |
| 1310 | goto error; | 1323 | goto error; |
| @@ -1314,20 +1327,22 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, | |||
| 1314 | goto error; | 1327 | goto error; |
| 1315 | 1328 | ||
| 1316 | if (!codec->subsystem_id) { | 1329 | if (!codec->subsystem_id) { |
| 1317 | hda_nid_t nid = codec->afg ? codec->afg : codec->mfg; | ||
| 1318 | codec->subsystem_id = | 1330 | codec->subsystem_id = |
| 1319 | snd_hda_codec_read(codec, nid, 0, | 1331 | snd_hda_codec_read(codec, fg, 0, |
| 1320 | AC_VERB_GET_SUBSYSTEM_ID, 0); | 1332 | AC_VERB_GET_SUBSYSTEM_ID, 0); |
| 1321 | } | 1333 | } |
| 1322 | 1334 | ||
| 1323 | codec->epss = snd_hda_codec_get_supported_ps(codec, | 1335 | #ifdef CONFIG_PM |
| 1324 | codec->afg ? codec->afg : codec->mfg, | 1336 | codec->d3_stop_clk = snd_hda_codec_get_supported_ps(codec, fg, |
| 1337 | AC_PWRST_CLKSTOP); | ||
| 1338 | if (!codec->d3_stop_clk) | ||
| 1339 | bus->power_keep_link_on = 1; | ||
| 1340 | #endif | ||
| 1341 | codec->epss = snd_hda_codec_get_supported_ps(codec, fg, | ||
| 1325 | AC_PWRST_EPSS); | 1342 | AC_PWRST_EPSS); |
| 1326 | 1343 | ||
| 1327 | /* power-up all before initialization */ | 1344 | /* power-up all before initialization */ |
| 1328 | hda_set_power_state(codec, | 1345 | hda_set_power_state(codec, AC_PWRST_D0); |
| 1329 | codec->afg ? codec->afg : codec->mfg, | ||
| 1330 | AC_PWRST_D0); | ||
| 1331 | 1346 | ||
| 1332 | snd_hda_codec_proc_new(codec); | 1347 | snd_hda_codec_proc_new(codec); |
| 1333 | 1348 | ||
| @@ -2335,7 +2350,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) | |||
| 2335 | 2350 | ||
| 2336 | /* OK, let it free */ | 2351 | /* OK, let it free */ |
| 2337 | 2352 | ||
| 2338 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2353 | #ifdef CONFIG_PM |
| 2339 | cancel_delayed_work_sync(&codec->power_work); | 2354 | cancel_delayed_work_sync(&codec->power_work); |
| 2340 | codec->power_on = 0; | 2355 | codec->power_on = 0; |
| 2341 | codec->power_transition = 0; | 2356 | codec->power_transition = 0; |
| @@ -3500,20 +3515,6 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, | |||
| 3500 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, | 3515 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, |
| 3501 | power_state); | 3516 | power_state); |
| 3502 | } | 3517 | } |
| 3503 | |||
| 3504 | if (power_state == AC_PWRST_D0) { | ||
| 3505 | unsigned long end_time; | ||
| 3506 | int state; | ||
| 3507 | /* wait until the codec reachs to D0 */ | ||
| 3508 | end_time = jiffies + msecs_to_jiffies(500); | ||
| 3509 | do { | ||
| 3510 | state = snd_hda_codec_read(codec, fg, 0, | ||
| 3511 | AC_VERB_GET_POWER_STATE, 0); | ||
| 3512 | if (state == power_state) | ||
| 3513 | break; | ||
| 3514 | msleep(1); | ||
| 3515 | } while (time_after_eq(end_time, jiffies)); | ||
| 3516 | } | ||
| 3517 | } | 3518 | } |
| 3518 | EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); | 3519 | EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); |
| 3519 | 3520 | ||
| @@ -3534,18 +3535,40 @@ static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, hda_nid_t fg | |||
| 3534 | } | 3535 | } |
| 3535 | 3536 | ||
| 3536 | /* | 3537 | /* |
| 3537 | * set power state of the codec | 3538 | * wait until the state is reached, returns the current state |
| 3538 | */ | 3539 | */ |
| 3539 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | 3540 | static unsigned int hda_sync_power_state(struct hda_codec *codec, |
| 3540 | unsigned int power_state) | 3541 | hda_nid_t fg, |
| 3542 | unsigned int power_state) | ||
| 3541 | { | 3543 | { |
| 3542 | int count; | 3544 | unsigned long end_time = jiffies + msecs_to_jiffies(500); |
| 3543 | unsigned int state; | 3545 | unsigned int state, actual_state; |
| 3544 | 3546 | ||
| 3545 | if (codec->patch_ops.set_power_state) { | 3547 | for (;;) { |
| 3546 | codec->patch_ops.set_power_state(codec, fg, power_state); | 3548 | state = snd_hda_codec_read(codec, fg, 0, |
| 3547 | return; | 3549 | AC_VERB_GET_POWER_STATE, 0); |
| 3550 | if (state & AC_PWRST_ERROR) | ||
| 3551 | break; | ||
| 3552 | actual_state = (state >> 4) & 0x0f; | ||
| 3553 | if (actual_state == power_state) | ||
| 3554 | break; | ||
| 3555 | if (time_after_eq(jiffies, end_time)) | ||
| 3556 | break; | ||
| 3557 | /* wait until the codec reachs to the target state */ | ||
| 3558 | msleep(1); | ||
| 3548 | } | 3559 | } |
| 3560 | return state; | ||
| 3561 | } | ||
| 3562 | |||
| 3563 | /* | ||
| 3564 | * set power state of the codec, and return the power state | ||
| 3565 | */ | ||
| 3566 | static unsigned int hda_set_power_state(struct hda_codec *codec, | ||
| 3567 | unsigned int power_state) | ||
| 3568 | { | ||
| 3569 | hda_nid_t fg = codec->afg ? codec->afg : codec->mfg; | ||
| 3570 | int count; | ||
| 3571 | unsigned int state; | ||
| 3549 | 3572 | ||
| 3550 | /* this delay seems necessary to avoid click noise at power-down */ | 3573 | /* this delay seems necessary to avoid click noise at power-down */ |
| 3551 | if (power_state == AC_PWRST_D3) { | 3574 | if (power_state == AC_PWRST_D3) { |
| @@ -3555,14 +3578,22 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
| 3555 | 3578 | ||
| 3556 | /* repeat power states setting at most 10 times*/ | 3579 | /* repeat power states setting at most 10 times*/ |
| 3557 | for (count = 0; count < 10; count++) { | 3580 | for (count = 0; count < 10; count++) { |
| 3558 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | 3581 | if (codec->patch_ops.set_power_state) |
| 3559 | power_state); | 3582 | codec->patch_ops.set_power_state(codec, fg, |
| 3560 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | 3583 | power_state); |
| 3561 | state = snd_hda_codec_read(codec, fg, 0, | 3584 | else { |
| 3562 | AC_VERB_GET_POWER_STATE, 0); | 3585 | snd_hda_codec_read(codec, fg, 0, |
| 3586 | AC_VERB_SET_POWER_STATE, | ||
| 3587 | power_state); | ||
| 3588 | snd_hda_codec_set_power_to_all(codec, fg, power_state, | ||
| 3589 | true); | ||
| 3590 | } | ||
| 3591 | state = hda_sync_power_state(codec, fg, power_state); | ||
| 3563 | if (!(state & AC_PWRST_ERROR)) | 3592 | if (!(state & AC_PWRST_ERROR)) |
| 3564 | break; | 3593 | break; |
| 3565 | } | 3594 | } |
| 3595 | |||
| 3596 | return state; | ||
| 3566 | } | 3597 | } |
| 3567 | 3598 | ||
| 3568 | #ifdef CONFIG_SND_HDA_HWDEP | 3599 | #ifdef CONFIG_SND_HDA_HWDEP |
| @@ -3579,17 +3610,19 @@ static inline void hda_exec_init_verbs(struct hda_codec *codec) {} | |||
| 3579 | #ifdef CONFIG_PM | 3610 | #ifdef CONFIG_PM |
| 3580 | /* | 3611 | /* |
| 3581 | * call suspend and power-down; used both from PM and power-save | 3612 | * call suspend and power-down; used both from PM and power-save |
| 3613 | * this function returns the power state in the end | ||
| 3582 | */ | 3614 | */ |
| 3583 | static void hda_call_codec_suspend(struct hda_codec *codec) | 3615 | static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq) |
| 3584 | { | 3616 | { |
| 3617 | unsigned int state; | ||
| 3618 | |||
| 3585 | if (codec->patch_ops.suspend) | 3619 | if (codec->patch_ops.suspend) |
| 3586 | codec->patch_ops.suspend(codec); | 3620 | codec->patch_ops.suspend(codec); |
| 3587 | hda_cleanup_all_streams(codec); | 3621 | hda_cleanup_all_streams(codec); |
| 3588 | hda_set_power_state(codec, | 3622 | state = hda_set_power_state(codec, AC_PWRST_D3); |
| 3589 | codec->afg ? codec->afg : codec->mfg, | 3623 | /* Cancel delayed work if we aren't currently running from it. */ |
| 3590 | AC_PWRST_D3); | 3624 | if (!in_wq) |
| 3591 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3625 | cancel_delayed_work_sync(&codec->power_work); |
| 3592 | cancel_delayed_work(&codec->power_work); | ||
| 3593 | spin_lock(&codec->power_lock); | 3626 | spin_lock(&codec->power_lock); |
| 3594 | snd_hda_update_power_acct(codec); | 3627 | snd_hda_update_power_acct(codec); |
| 3595 | trace_hda_power_down(codec); | 3628 | trace_hda_power_down(codec); |
| @@ -3597,7 +3630,7 @@ static void hda_call_codec_suspend(struct hda_codec *codec) | |||
| 3597 | codec->power_transition = 0; | 3630 | codec->power_transition = 0; |
| 3598 | codec->power_jiffies = jiffies; | 3631 | codec->power_jiffies = jiffies; |
| 3599 | spin_unlock(&codec->power_lock); | 3632 | spin_unlock(&codec->power_lock); |
| 3600 | #endif | 3633 | return state; |
| 3601 | } | 3634 | } |
| 3602 | 3635 | ||
| 3603 | /* | 3636 | /* |
| @@ -3609,9 +3642,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
| 3609 | * in the resume / power-save sequence | 3642 | * in the resume / power-save sequence |
| 3610 | */ | 3643 | */ |
| 3611 | hda_keep_power_on(codec); | 3644 | hda_keep_power_on(codec); |
| 3612 | hda_set_power_state(codec, | 3645 | hda_set_power_state(codec, AC_PWRST_D0); |
| 3613 | codec->afg ? codec->afg : codec->mfg, | ||
| 3614 | AC_PWRST_D0); | ||
| 3615 | restore_pincfgs(codec); /* restore all current pin configs */ | 3646 | restore_pincfgs(codec); /* restore all current pin configs */ |
| 3616 | restore_shutup_pins(codec); | 3647 | restore_shutup_pins(codec); |
| 3617 | hda_exec_init_verbs(codec); | 3648 | hda_exec_init_verbs(codec); |
| @@ -3624,6 +3655,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
| 3624 | snd_hda_codec_resume_amp(codec); | 3655 | snd_hda_codec_resume_amp(codec); |
| 3625 | snd_hda_codec_resume_cache(codec); | 3656 | snd_hda_codec_resume_cache(codec); |
| 3626 | } | 3657 | } |
| 3658 | snd_hda_jack_report_sync(codec); | ||
| 3627 | snd_hda_power_down(codec); /* flag down before returning */ | 3659 | snd_hda_power_down(codec); /* flag down before returning */ |
| 3628 | } | 3660 | } |
| 3629 | #endif /* CONFIG_PM */ | 3661 | #endif /* CONFIG_PM */ |
| @@ -3658,6 +3690,36 @@ int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus) | |||
| 3658 | } | 3690 | } |
| 3659 | EXPORT_SYMBOL_HDA(snd_hda_build_controls); | 3691 | EXPORT_SYMBOL_HDA(snd_hda_build_controls); |
| 3660 | 3692 | ||
| 3693 | /* | ||
| 3694 | * add standard channel maps if not specified | ||
| 3695 | */ | ||
| 3696 | static int add_std_chmaps(struct hda_codec *codec) | ||
| 3697 | { | ||
| 3698 | int i, str, err; | ||
| 3699 | |||
| 3700 | for (i = 0; i < codec->num_pcms; i++) { | ||
| 3701 | for (str = 0; str < 2; str++) { | ||
| 3702 | struct snd_pcm *pcm = codec->pcm_info[i].pcm; | ||
| 3703 | struct hda_pcm_stream *hinfo = | ||
| 3704 | &codec->pcm_info[i].stream[str]; | ||
| 3705 | struct snd_pcm_chmap *chmap; | ||
| 3706 | |||
| 3707 | if (codec->pcm_info[i].own_chmap) | ||
| 3708 | continue; | ||
| 3709 | if (!pcm || !hinfo->substreams) | ||
| 3710 | continue; | ||
| 3711 | err = snd_pcm_add_chmap_ctls(pcm, str, | ||
| 3712 | snd_pcm_std_chmaps, | ||
| 3713 | hinfo->channels_max, | ||
| 3714 | 0, &chmap); | ||
| 3715 | if (err < 0) | ||
| 3716 | return err; | ||
| 3717 | chmap->channel_mask = SND_PCM_CHMAP_MASK_2468; | ||
| 3718 | } | ||
| 3719 | } | ||
| 3720 | return 0; | ||
| 3721 | } | ||
| 3722 | |||
| 3661 | int snd_hda_codec_build_controls(struct hda_codec *codec) | 3723 | int snd_hda_codec_build_controls(struct hda_codec *codec) |
| 3662 | { | 3724 | { |
| 3663 | int err = 0; | 3725 | int err = 0; |
| @@ -3669,6 +3731,13 @@ int snd_hda_codec_build_controls(struct hda_codec *codec) | |||
| 3669 | err = codec->patch_ops.build_controls(codec); | 3731 | err = codec->patch_ops.build_controls(codec); |
| 3670 | if (err < 0) | 3732 | if (err < 0) |
| 3671 | return err; | 3733 | return err; |
| 3734 | |||
| 3735 | /* we create chmaps here instead of build_pcms */ | ||
| 3736 | err = add_std_chmaps(codec); | ||
| 3737 | if (err < 0) | ||
| 3738 | return err; | ||
| 3739 | |||
| 3740 | snd_hda_jack_report_sync(codec); /* call at the last init point */ | ||
| 3672 | return 0; | 3741 | return 0; |
| 3673 | } | 3742 | } |
| 3674 | 3743 | ||
| @@ -4211,7 +4280,7 @@ int snd_hda_codec_build_pcms(struct hda_codec *codec) | |||
| 4211 | * | 4280 | * |
| 4212 | * This function returns 0 if successful, or a negative error code. | 4281 | * This function returns 0 if successful, or a negative error code. |
| 4213 | */ | 4282 | */ |
| 4214 | int __devinit snd_hda_build_pcms(struct hda_bus *bus) | 4283 | int snd_hda_build_pcms(struct hda_bus *bus) |
| 4215 | { | 4284 | { |
| 4216 | struct hda_codec *codec; | 4285 | struct hda_codec *codec; |
| 4217 | 4286 | ||
| @@ -4391,12 +4460,13 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, | |||
| 4391 | } | 4460 | } |
| 4392 | EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls); | 4461 | EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls); |
| 4393 | 4462 | ||
| 4394 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 4463 | #ifdef CONFIG_PM |
| 4395 | static void hda_power_work(struct work_struct *work) | 4464 | static void hda_power_work(struct work_struct *work) |
| 4396 | { | 4465 | { |
| 4397 | struct hda_codec *codec = | 4466 | struct hda_codec *codec = |
| 4398 | container_of(work, struct hda_codec, power_work.work); | 4467 | container_of(work, struct hda_codec, power_work.work); |
| 4399 | struct hda_bus *bus = codec->bus; | 4468 | struct hda_bus *bus = codec->bus; |
| 4469 | unsigned int state; | ||
| 4400 | 4470 | ||
| 4401 | spin_lock(&codec->power_lock); | 4471 | spin_lock(&codec->power_lock); |
| 4402 | if (codec->power_transition > 0) { /* during power-up sequence? */ | 4472 | if (codec->power_transition > 0) { /* during power-up sequence? */ |
| @@ -4410,9 +4480,12 @@ static void hda_power_work(struct work_struct *work) | |||
| 4410 | } | 4480 | } |
| 4411 | spin_unlock(&codec->power_lock); | 4481 | spin_unlock(&codec->power_lock); |
| 4412 | 4482 | ||
| 4413 | hda_call_codec_suspend(codec); | 4483 | state = hda_call_codec_suspend(codec, true); |
| 4414 | if (bus->ops.pm_notify) | 4484 | codec->pm_down_notified = 0; |
| 4415 | bus->ops.pm_notify(bus); | 4485 | if (!bus->power_keep_link_on && (state & AC_PWRST_CLK_STOP_OK)) { |
| 4486 | codec->pm_down_notified = 1; | ||
| 4487 | hda_call_pm_notify(bus, false); | ||
| 4488 | } | ||
| 4416 | } | 4489 | } |
| 4417 | 4490 | ||
| 4418 | static void hda_keep_power_on(struct hda_codec *codec) | 4491 | static void hda_keep_power_on(struct hda_codec *codec) |
| @@ -4438,19 +4511,16 @@ void snd_hda_update_power_acct(struct hda_codec *codec) | |||
| 4438 | /* Transition to powered up, if wait_power_down then wait for a pending | 4511 | /* Transition to powered up, if wait_power_down then wait for a pending |
| 4439 | * transition to D3 to complete. A pending D3 transition is indicated | 4512 | * transition to D3 to complete. A pending D3 transition is indicated |
| 4440 | * with power_transition == -1. */ | 4513 | * with power_transition == -1. */ |
| 4514 | /* call this with codec->power_lock held! */ | ||
| 4441 | static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) | 4515 | static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) |
| 4442 | { | 4516 | { |
| 4443 | struct hda_bus *bus = codec->bus; | 4517 | struct hda_bus *bus = codec->bus; |
| 4444 | 4518 | ||
| 4445 | spin_lock(&codec->power_lock); | ||
| 4446 | codec->power_count++; | ||
| 4447 | /* Return if power_on or transitioning to power_on, unless currently | 4519 | /* Return if power_on or transitioning to power_on, unless currently |
| 4448 | * powering down. */ | 4520 | * powering down. */ |
| 4449 | if ((codec->power_on || codec->power_transition > 0) && | 4521 | if ((codec->power_on || codec->power_transition > 0) && |
| 4450 | !(wait_power_down && codec->power_transition < 0)) { | 4522 | !(wait_power_down && codec->power_transition < 0)) |
| 4451 | spin_unlock(&codec->power_lock); | ||
| 4452 | return; | 4523 | return; |
| 4453 | } | ||
| 4454 | spin_unlock(&codec->power_lock); | 4524 | spin_unlock(&codec->power_lock); |
| 4455 | 4525 | ||
| 4456 | cancel_delayed_work_sync(&codec->power_work); | 4526 | cancel_delayed_work_sync(&codec->power_work); |
| @@ -4462,9 +4532,9 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) | |||
| 4462 | if (codec->power_on) { | 4532 | if (codec->power_on) { |
| 4463 | if (codec->power_transition < 0) | 4533 | if (codec->power_transition < 0) |
| 4464 | codec->power_transition = 0; | 4534 | codec->power_transition = 0; |
| 4465 | spin_unlock(&codec->power_lock); | ||
| 4466 | return; | 4535 | return; |
| 4467 | } | 4536 | } |
| 4537 | |||
| 4468 | trace_hda_power_up(codec); | 4538 | trace_hda_power_up(codec); |
| 4469 | snd_hda_update_power_acct(codec); | 4539 | snd_hda_update_power_acct(codec); |
| 4470 | codec->power_on = 1; | 4540 | codec->power_on = 1; |
| @@ -4472,71 +4542,54 @@ static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) | |||
| 4472 | codec->power_transition = 1; /* avoid reentrance */ | 4542 | codec->power_transition = 1; /* avoid reentrance */ |
| 4473 | spin_unlock(&codec->power_lock); | 4543 | spin_unlock(&codec->power_lock); |
| 4474 | 4544 | ||
| 4475 | if (bus->ops.pm_notify) | 4545 | if (codec->pm_down_notified) { |
| 4476 | bus->ops.pm_notify(bus); | 4546 | codec->pm_down_notified = 0; |
| 4547 | hda_call_pm_notify(bus, true); | ||
| 4548 | } | ||
| 4549 | |||
| 4477 | hda_call_codec_resume(codec); | 4550 | hda_call_codec_resume(codec); |
| 4478 | 4551 | ||
| 4479 | spin_lock(&codec->power_lock); | 4552 | spin_lock(&codec->power_lock); |
| 4480 | codec->power_transition = 0; | 4553 | codec->power_transition = 0; |
| 4481 | spin_unlock(&codec->power_lock); | ||
| 4482 | } | ||
| 4483 | |||
| 4484 | /** | ||
| 4485 | * snd_hda_power_up - Power-up the codec | ||
| 4486 | * @codec: HD-audio codec | ||
| 4487 | * | ||
| 4488 | * Increment the power-up counter and power up the hardware really when | ||
| 4489 | * not turned on yet. | ||
| 4490 | */ | ||
| 4491 | void snd_hda_power_up(struct hda_codec *codec) | ||
| 4492 | { | ||
| 4493 | __snd_hda_power_up(codec, false); | ||
| 4494 | } | 4554 | } |
| 4495 | EXPORT_SYMBOL_HDA(snd_hda_power_up); | ||
| 4496 | |||
| 4497 | /** | ||
| 4498 | * snd_hda_power_up_d3wait - Power-up the codec after waiting for any pending | ||
| 4499 | * D3 transition to complete. This differs from snd_hda_power_up() when | ||
| 4500 | * power_transition == -1. snd_hda_power_up sees this case as a nop, | ||
| 4501 | * snd_hda_power_up_d3wait waits for the D3 transition to complete then powers | ||
| 4502 | * back up. | ||
| 4503 | * @codec: HD-audio codec | ||
| 4504 | * | ||
| 4505 | * Cancel any power down operation hapenning on the work queue, then power up. | ||
| 4506 | */ | ||
| 4507 | void snd_hda_power_up_d3wait(struct hda_codec *codec) | ||
| 4508 | { | ||
| 4509 | /* This will cancel and wait for pending power_work to complete. */ | ||
| 4510 | __snd_hda_power_up(codec, true); | ||
| 4511 | } | ||
| 4512 | EXPORT_SYMBOL_HDA(snd_hda_power_up_d3wait); | ||
| 4513 | 4555 | ||
| 4514 | #define power_save(codec) \ | 4556 | #define power_save(codec) \ |
| 4515 | ((codec)->bus->power_save ? *(codec)->bus->power_save : 0) | 4557 | ((codec)->bus->power_save ? *(codec)->bus->power_save : 0) |
| 4516 | 4558 | ||
| 4517 | /** | 4559 | /* Transition to powered down */ |
| 4518 | * snd_hda_power_down - Power-down the codec | 4560 | static void __snd_hda_power_down(struct hda_codec *codec) |
| 4519 | * @codec: HD-audio codec | ||
| 4520 | * | ||
| 4521 | * Decrement the power-up counter and schedules the power-off work if | ||
| 4522 | * the counter rearches to zero. | ||
| 4523 | */ | ||
| 4524 | void snd_hda_power_down(struct hda_codec *codec) | ||
| 4525 | { | 4561 | { |
| 4526 | spin_lock(&codec->power_lock); | 4562 | if (!codec->power_on || codec->power_count || codec->power_transition) |
| 4527 | --codec->power_count; | ||
| 4528 | if (!codec->power_on || codec->power_count || codec->power_transition) { | ||
| 4529 | spin_unlock(&codec->power_lock); | ||
| 4530 | return; | 4563 | return; |
| 4531 | } | 4564 | |
| 4532 | if (power_save(codec)) { | 4565 | if (power_save(codec)) { |
| 4533 | codec->power_transition = -1; /* avoid reentrance */ | 4566 | codec->power_transition = -1; /* avoid reentrance */ |
| 4534 | queue_delayed_work(codec->bus->workq, &codec->power_work, | 4567 | queue_delayed_work(codec->bus->workq, &codec->power_work, |
| 4535 | msecs_to_jiffies(power_save(codec) * 1000)); | 4568 | msecs_to_jiffies(power_save(codec) * 1000)); |
| 4536 | } | 4569 | } |
| 4570 | } | ||
| 4571 | |||
| 4572 | /** | ||
| 4573 | * snd_hda_power_save - Power-up/down/sync the codec | ||
| 4574 | * @codec: HD-audio codec | ||
| 4575 | * @delta: the counter delta to change | ||
| 4576 | * | ||
| 4577 | * Change the power-up counter via @delta, and power up or down the hardware | ||
| 4578 | * appropriately. For the power-down, queue to the delayed action. | ||
| 4579 | * Passing zero to @delta means to synchronize the power state. | ||
| 4580 | */ | ||
| 4581 | void snd_hda_power_save(struct hda_codec *codec, int delta, bool d3wait) | ||
| 4582 | { | ||
| 4583 | spin_lock(&codec->power_lock); | ||
| 4584 | codec->power_count += delta; | ||
| 4585 | trace_hda_power_count(codec); | ||
| 4586 | if (delta > 0) | ||
| 4587 | __snd_hda_power_up(codec, d3wait); | ||
| 4588 | else | ||
| 4589 | __snd_hda_power_down(codec); | ||
| 4537 | spin_unlock(&codec->power_lock); | 4590 | spin_unlock(&codec->power_lock); |
| 4538 | } | 4591 | } |
| 4539 | EXPORT_SYMBOL_HDA(snd_hda_power_down); | 4592 | EXPORT_SYMBOL_HDA(snd_hda_power_save); |
| 4540 | 4593 | ||
| 4541 | /** | 4594 | /** |
| 4542 | * snd_hda_check_amp_list_power - Check the amp list and update the power | 4595 | * snd_hda_check_amp_list_power - Check the amp list and update the power |
| @@ -5076,7 +5129,7 @@ int snd_hda_suspend(struct hda_bus *bus) | |||
| 5076 | 5129 | ||
| 5077 | list_for_each_entry(codec, &bus->codec_list, list) { | 5130 | list_for_each_entry(codec, &bus->codec_list, list) { |
| 5078 | if (hda_codec_is_power_on(codec)) | 5131 | if (hda_codec_is_power_on(codec)) |
| 5079 | hda_call_codec_suspend(codec); | 5132 | hda_call_codec_suspend(codec, false); |
| 5080 | } | 5133 | } |
| 5081 | return 0; | 5134 | return 0; |
| 5082 | } | 5135 | } |
| @@ -5087,9 +5140,6 @@ EXPORT_SYMBOL_HDA(snd_hda_suspend); | |||
| 5087 | * @bus: the HDA bus | 5140 | * @bus: the HDA bus |
| 5088 | * | 5141 | * |
| 5089 | * Returns 0 if successful. | 5142 | * Returns 0 if successful. |
| 5090 | * | ||
| 5091 | * This function is defined only when POWER_SAVE isn't set. | ||
| 5092 | * In the power-save mode, the codec is resumed dynamically. | ||
| 5093 | */ | 5143 | */ |
| 5094 | int snd_hda_resume(struct hda_bus *bus) | 5144 | int snd_hda_resume(struct hda_bus *bus) |
| 5095 | { | 5145 | { |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index e5a7e19a8071..507fe8a917b6 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
| @@ -386,6 +386,10 @@ enum { | |||
| 386 | /* DIGITAL2 bits */ | 386 | /* DIGITAL2 bits */ |
| 387 | #define AC_DIG2_CC (0x7f<<0) | 387 | #define AC_DIG2_CC (0x7f<<0) |
| 388 | 388 | ||
| 389 | /* DIGITAL3 bits */ | ||
| 390 | #define AC_DIG3_ICT (0xf<<0) | ||
| 391 | #define AC_DIG3_KAE (1<<7) | ||
| 392 | |||
| 389 | /* Pin widget control - 8bit */ | 393 | /* Pin widget control - 8bit */ |
| 390 | #define AC_PINCTL_EPT (0x3<<0) | 394 | #define AC_PINCTL_EPT (0x3<<0) |
| 391 | #define AC_PINCTL_EPT_NATIVE 0 | 395 | #define AC_PINCTL_EPT_NATIVE 0 |
| @@ -610,9 +614,9 @@ struct hda_bus_ops { | |||
| 610 | struct hda_pcm *pcm); | 614 | struct hda_pcm *pcm); |
| 611 | /* reset bus for retry verb */ | 615 | /* reset bus for retry verb */ |
| 612 | void (*bus_reset)(struct hda_bus *bus); | 616 | void (*bus_reset)(struct hda_bus *bus); |
| 613 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 617 | #ifdef CONFIG_PM |
| 614 | /* notify power-up/down from codec to controller */ | 618 | /* notify power-up/down from codec to controller */ |
| 615 | void (*pm_notify)(struct hda_bus *bus); | 619 | void (*pm_notify)(struct hda_bus *bus, bool power_up); |
| 616 | #endif | 620 | #endif |
| 617 | }; | 621 | }; |
| 618 | 622 | ||
| @@ -708,8 +712,6 @@ struct hda_codec_ops { | |||
| 708 | #ifdef CONFIG_PM | 712 | #ifdef CONFIG_PM |
| 709 | int (*suspend)(struct hda_codec *codec); | 713 | int (*suspend)(struct hda_codec *codec); |
| 710 | int (*resume)(struct hda_codec *codec); | 714 | int (*resume)(struct hda_codec *codec); |
| 711 | #endif | ||
| 712 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
| 713 | int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid); | 715 | int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid); |
| 714 | #endif | 716 | #endif |
| 715 | void (*reboot_notify)(struct hda_codec *codec); | 717 | void (*reboot_notify)(struct hda_codec *codec); |
| @@ -774,6 +776,7 @@ struct hda_pcm { | |||
| 774 | unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */ | 776 | unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */ |
| 775 | int device; /* device number to assign */ | 777 | int device; /* device number to assign */ |
| 776 | struct snd_pcm *pcm; /* assigned PCM instance */ | 778 | struct snd_pcm *pcm; /* assigned PCM instance */ |
| 779 | bool own_chmap; /* codec driver provides own channel maps */ | ||
| 777 | }; | 780 | }; |
| 778 | 781 | ||
| 779 | /* codec information */ | 782 | /* codec information */ |
| @@ -859,12 +862,13 @@ struct hda_codec { | |||
| 859 | unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */ | 862 | unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */ |
| 860 | unsigned int pins_shutup:1; /* pins are shut up */ | 863 | unsigned int pins_shutup:1; /* pins are shut up */ |
| 861 | unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ | 864 | unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ |
| 862 | unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */ | ||
| 863 | unsigned int no_jack_detect:1; /* Machine has no jack-detection */ | 865 | unsigned int no_jack_detect:1; /* Machine has no jack-detection */ |
| 864 | unsigned int pcm_format_first:1; /* PCM format must be set first */ | 866 | unsigned int pcm_format_first:1; /* PCM format must be set first */ |
| 865 | unsigned int epss:1; /* supporting EPSS? */ | 867 | unsigned int epss:1; /* supporting EPSS? */ |
| 866 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 868 | #ifdef CONFIG_PM |
| 867 | unsigned int power_on :1; /* current (global) power-state */ | 869 | unsigned int power_on :1; /* current (global) power-state */ |
| 870 | unsigned int d3_stop_clk:1; /* support D3 operation without BCLK */ | ||
| 871 | unsigned int pm_down_notified:1; /* PM notified to controller */ | ||
| 868 | int power_transition; /* power-state in transition */ | 872 | int power_transition; /* power-state in transition */ |
| 869 | int power_count; /* current (global) power refcount */ | 873 | int power_count; /* current (global) power refcount */ |
| 870 | struct delayed_work power_work; /* delayed task for powerdown */ | 874 | struct delayed_work power_work; /* delayed task for powerdown */ |
| @@ -1042,7 +1046,7 @@ int snd_hda_resume(struct hda_bus *bus); | |||
| 1042 | static inline | 1046 | static inline |
| 1043 | int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid) | 1047 | int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid) |
| 1044 | { | 1048 | { |
| 1045 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1049 | #ifdef CONFIG_PM |
| 1046 | if (codec->patch_ops.check_power_status) | 1050 | if (codec->patch_ops.check_power_status) |
| 1047 | return codec->patch_ops.check_power_status(codec, nid); | 1051 | return codec->patch_ops.check_power_status(codec, nid); |
| 1048 | #endif | 1052 | #endif |
| @@ -1059,22 +1063,70 @@ const char *snd_hda_get_jack_location(u32 cfg); | |||
| 1059 | /* | 1063 | /* |
| 1060 | * power saving | 1064 | * power saving |
| 1061 | */ | 1065 | */ |
| 1062 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1066 | #ifdef CONFIG_PM |
| 1063 | void snd_hda_power_up(struct hda_codec *codec); | 1067 | void snd_hda_power_save(struct hda_codec *codec, int delta, bool d3wait); |
| 1064 | void snd_hda_power_up_d3wait(struct hda_codec *codec); | ||
| 1065 | void snd_hda_power_down(struct hda_codec *codec); | ||
| 1066 | void snd_hda_update_power_acct(struct hda_codec *codec); | 1068 | void snd_hda_update_power_acct(struct hda_codec *codec); |
| 1067 | #else | 1069 | #else |
| 1068 | static inline void snd_hda_power_up(struct hda_codec *codec) {} | 1070 | static inline void snd_hda_power_save(struct hda_codec *codec, int delta, |
| 1069 | static inline void snd_hda_power_up_d3wait(struct hda_codec *codec) {} | 1071 | bool d3wait) {} |
| 1070 | static inline void snd_hda_power_down(struct hda_codec *codec) {} | ||
| 1071 | #endif | 1072 | #endif |
| 1072 | 1073 | ||
| 1074 | /** | ||
| 1075 | * snd_hda_power_up - Power-up the codec | ||
| 1076 | * @codec: HD-audio codec | ||
| 1077 | * | ||
| 1078 | * Increment the power-up counter and power up the hardware really when | ||
| 1079 | * not turned on yet. | ||
| 1080 | */ | ||
| 1081 | static inline void snd_hda_power_up(struct hda_codec *codec) | ||
| 1082 | { | ||
| 1083 | snd_hda_power_save(codec, 1, false); | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | /** | ||
| 1087 | * snd_hda_power_up_d3wait - Power-up the codec after waiting for any pending | ||
| 1088 | * D3 transition to complete. This differs from snd_hda_power_up() when | ||
| 1089 | * power_transition == -1. snd_hda_power_up sees this case as a nop, | ||
| 1090 | * snd_hda_power_up_d3wait waits for the D3 transition to complete then powers | ||
| 1091 | * back up. | ||
| 1092 | * @codec: HD-audio codec | ||
| 1093 | * | ||
| 1094 | * Cancel any power down operation hapenning on the work queue, then power up. | ||
| 1095 | */ | ||
| 1096 | static inline void snd_hda_power_up_d3wait(struct hda_codec *codec) | ||
| 1097 | { | ||
| 1098 | snd_hda_power_save(codec, 1, true); | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | /** | ||
| 1102 | * snd_hda_power_down - Power-down the codec | ||
| 1103 | * @codec: HD-audio codec | ||
| 1104 | * | ||
| 1105 | * Decrement the power-up counter and schedules the power-off work if | ||
| 1106 | * the counter rearches to zero. | ||
| 1107 | */ | ||
| 1108 | static inline void snd_hda_power_down(struct hda_codec *codec) | ||
| 1109 | { | ||
| 1110 | snd_hda_power_save(codec, -1, false); | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | /** | ||
| 1114 | * snd_hda_power_sync - Synchronize the power-save status | ||
| 1115 | * @codec: HD-audio codec | ||
| 1116 | * | ||
| 1117 | * Synchronize the actual power state with the power account; | ||
| 1118 | * called when power_save parameter is changed | ||
| 1119 | */ | ||
| 1120 | static inline void snd_hda_power_sync(struct hda_codec *codec) | ||
| 1121 | { | ||
| 1122 | snd_hda_power_save(codec, 0, false); | ||
| 1123 | } | ||
| 1124 | |||
| 1073 | #ifdef CONFIG_SND_HDA_PATCH_LOADER | 1125 | #ifdef CONFIG_SND_HDA_PATCH_LOADER |
| 1074 | /* | 1126 | /* |
| 1075 | * patch firmware | 1127 | * patch firmware |
| 1076 | */ | 1128 | */ |
| 1077 | int snd_hda_load_patch(struct hda_bus *bus, const char *patch); | 1129 | int snd_hda_load_patch(struct hda_bus *bus, size_t size, const void *buf); |
| 1078 | #endif | 1130 | #endif |
| 1079 | 1131 | ||
| 1080 | /* | 1132 | /* |
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 431bf868711e..b81d3d0b952d 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
| @@ -70,7 +70,7 @@ struct hda_gspec { | |||
| 70 | 70 | ||
| 71 | struct list_head nid_list; /* list of widgets */ | 71 | struct list_head nid_list; /* list of widgets */ |
| 72 | 72 | ||
| 73 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 73 | #ifdef CONFIG_PM |
| 74 | #define MAX_LOOPBACK_AMPS 7 | 74 | #define MAX_LOOPBACK_AMPS 7 |
| 75 | struct hda_loopback_check loopback; | 75 | struct hda_loopback_check loopback; |
| 76 | int num_loopbacks; | 76 | int num_loopbacks; |
| @@ -654,7 +654,7 @@ static int parse_input(struct hda_codec *codec) | |||
| 654 | return 0; | 654 | return 0; |
| 655 | } | 655 | } |
| 656 | 656 | ||
| 657 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 657 | #ifdef CONFIG_PM |
| 658 | static void add_input_loopback(struct hda_codec *codec, hda_nid_t nid, | 658 | static void add_input_loopback(struct hda_codec *codec, hda_nid_t nid, |
| 659 | int dir, int idx) | 659 | int dir, int idx) |
| 660 | { | 660 | { |
| @@ -1028,7 +1028,7 @@ static int build_generic_pcms(struct hda_codec *codec) | |||
| 1028 | return 0; | 1028 | return 0; |
| 1029 | } | 1029 | } |
| 1030 | 1030 | ||
| 1031 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1031 | #ifdef CONFIG_PM |
| 1032 | static int generic_check_power_status(struct hda_codec *codec, hda_nid_t nid) | 1032 | static int generic_check_power_status(struct hda_codec *codec, hda_nid_t nid) |
| 1033 | { | 1033 | { |
| 1034 | struct hda_gspec *spec = codec->spec; | 1034 | struct hda_gspec *spec = codec->spec; |
| @@ -1043,7 +1043,7 @@ static struct hda_codec_ops generic_patch_ops = { | |||
| 1043 | .build_controls = build_generic_controls, | 1043 | .build_controls = build_generic_controls, |
| 1044 | .build_pcms = build_generic_pcms, | 1044 | .build_pcms = build_generic_pcms, |
| 1045 | .free = snd_hda_generic_free, | 1045 | .free = snd_hda_generic_free, |
| 1046 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1046 | #ifdef CONFIG_PM |
| 1047 | .check_power_status = generic_check_power_status, | 1047 | .check_power_status = generic_check_power_status, |
| 1048 | #endif | 1048 | #endif |
| 1049 | }; | 1049 | }; |
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c index 6b2efb8cb1f9..1af86d40eb23 100644 --- a/sound/pci/hda/hda_hwdep.c +++ b/sound/pci/hda/hda_hwdep.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <linux/mutex.h> | 25 | #include <linux/mutex.h> |
| 26 | #include <linux/ctype.h> | 26 | #include <linux/ctype.h> |
| 27 | #include <linux/string.h> | 27 | #include <linux/string.h> |
| 28 | #include <linux/firmware.h> | ||
| 29 | #include <linux/export.h> | 28 | #include <linux/export.h> |
| 30 | #include <sound/core.h> | 29 | #include <sound/core.h> |
| 31 | #include "hda_codec.h" | 30 | #include "hda_codec.h" |
| @@ -156,7 +155,7 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec) | |||
| 156 | return 0; | 155 | return 0; |
| 157 | } | 156 | } |
| 158 | 157 | ||
| 159 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 158 | #ifdef CONFIG_PM |
| 160 | static ssize_t power_on_acct_show(struct device *dev, | 159 | static ssize_t power_on_acct_show(struct device *dev, |
| 161 | struct device_attribute *attr, | 160 | struct device_attribute *attr, |
| 162 | char *buf) | 161 | char *buf) |
| @@ -192,7 +191,7 @@ int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec) | |||
| 192 | hwdep->device, &power_attrs[i]); | 191 | hwdep->device, &power_attrs[i]); |
| 193 | return 0; | 192 | return 0; |
| 194 | } | 193 | } |
| 195 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | 194 | #endif /* CONFIG_PM */ |
| 196 | 195 | ||
| 197 | #ifdef CONFIG_SND_HDA_RECONFIG | 196 | #ifdef CONFIG_SND_HDA_RECONFIG |
| 198 | 197 | ||
| @@ -747,18 +746,21 @@ static int parse_line_mode(char *buf, struct hda_bus *bus) | |||
| 747 | * | 746 | * |
| 748 | * the spaces at the beginning and the end of the line are stripped | 747 | * the spaces at the beginning and the end of the line are stripped |
| 749 | */ | 748 | */ |
| 750 | static int get_line_from_fw(char *buf, int size, struct firmware *fw) | 749 | static int get_line_from_fw(char *buf, int size, size_t *fw_size_p, |
| 750 | const void **fw_data_p) | ||
| 751 | { | 751 | { |
| 752 | int len; | 752 | int len; |
| 753 | const char *p = fw->data; | 753 | size_t fw_size = *fw_size_p; |
| 754 | while (isspace(*p) && fw->size) { | 754 | const char *p = *fw_data_p; |
| 755 | |||
| 756 | while (isspace(*p) && fw_size) { | ||
| 755 | p++; | 757 | p++; |
| 756 | fw->size--; | 758 | fw_size--; |
| 757 | } | 759 | } |
| 758 | if (!fw->size) | 760 | if (!fw_size) |
| 759 | return 0; | 761 | return 0; |
| 760 | 762 | ||
| 761 | for (len = 0; len < fw->size; len++) { | 763 | for (len = 0; len < fw_size; len++) { |
| 762 | if (!*p) | 764 | if (!*p) |
| 763 | break; | 765 | break; |
| 764 | if (*p == '\n') { | 766 | if (*p == '\n') { |
| @@ -770,8 +772,8 @@ static int get_line_from_fw(char *buf, int size, struct firmware *fw) | |||
| 770 | *buf++ = *p++; | 772 | *buf++ = *p++; |
| 771 | } | 773 | } |
| 772 | *buf = 0; | 774 | *buf = 0; |
| 773 | fw->size -= len; | 775 | *fw_size_p = fw_size - len; |
| 774 | fw->data = p; | 776 | *fw_data_p = p; |
| 775 | remove_trail_spaces(buf); | 777 | remove_trail_spaces(buf); |
| 776 | return 1; | 778 | return 1; |
| 777 | } | 779 | } |
| @@ -779,29 +781,15 @@ static int get_line_from_fw(char *buf, int size, struct firmware *fw) | |||
| 779 | /* | 781 | /* |
| 780 | * load a "patch" firmware file and parse it | 782 | * load a "patch" firmware file and parse it |
| 781 | */ | 783 | */ |
| 782 | int snd_hda_load_patch(struct hda_bus *bus, const char *patch) | 784 | int snd_hda_load_patch(struct hda_bus *bus, size_t fw_size, const void *fw_buf) |
| 783 | { | 785 | { |
| 784 | int err; | ||
| 785 | const struct firmware *fw; | ||
| 786 | struct firmware tmp; | ||
| 787 | char buf[128]; | 786 | char buf[128]; |
| 788 | struct hda_codec *codec; | 787 | struct hda_codec *codec; |
| 789 | int line_mode; | 788 | int line_mode; |
| 790 | struct device *dev = bus->card->dev; | ||
| 791 | |||
| 792 | if (snd_BUG_ON(!dev)) | ||
| 793 | return -ENODEV; | ||
| 794 | err = request_firmware(&fw, patch, dev); | ||
| 795 | if (err < 0) { | ||
| 796 | printk(KERN_ERR "hda-codec: Cannot load the patch '%s'\n", | ||
| 797 | patch); | ||
| 798 | return err; | ||
| 799 | } | ||
| 800 | 789 | ||
| 801 | tmp = *fw; | ||
| 802 | line_mode = LINE_MODE_NONE; | 790 | line_mode = LINE_MODE_NONE; |
| 803 | codec = NULL; | 791 | codec = NULL; |
| 804 | while (get_line_from_fw(buf, sizeof(buf) - 1, &tmp)) { | 792 | while (get_line_from_fw(buf, sizeof(buf) - 1, &fw_size, &fw_buf)) { |
| 805 | if (!*buf || *buf == '#' || *buf == '\n') | 793 | if (!*buf || *buf == '#' || *buf == '\n') |
| 806 | continue; | 794 | continue; |
| 807 | if (*buf == '[') | 795 | if (*buf == '[') |
| @@ -810,7 +798,6 @@ int snd_hda_load_patch(struct hda_bus *bus, const char *patch) | |||
| 810 | (codec || !patch_items[line_mode].need_codec)) | 798 | (codec || !patch_items[line_mode].need_codec)) |
| 811 | patch_items[line_mode].parser(buf, bus, &codec); | 799 | patch_items[line_mode].parser(buf, bus, &codec); |
| 812 | } | 800 | } |
| 813 | release_firmware(fw); | ||
| 814 | return 0; | 801 | return 0; |
| 815 | } | 802 | } |
| 816 | EXPORT_SYMBOL_HDA(snd_hda_load_patch); | 803 | EXPORT_SYMBOL_HDA(snd_hda_load_patch); |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index c4763c52eaf6..f09ff6c14041 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
| @@ -46,6 +46,7 @@ | |||
| 46 | #include <linux/mutex.h> | 46 | #include <linux/mutex.h> |
| 47 | #include <linux/reboot.h> | 47 | #include <linux/reboot.h> |
| 48 | #include <linux/io.h> | 48 | #include <linux/io.h> |
| 49 | #include <linux/pm_runtime.h> | ||
| 49 | #ifdef CONFIG_X86 | 50 | #ifdef CONFIG_X86 |
| 50 | /* for snoop control */ | 51 | /* for snoop control */ |
| 51 | #include <asm/pgtable.h> | 52 | #include <asm/pgtable.h> |
| @@ -55,6 +56,7 @@ | |||
| 55 | #include <sound/initval.h> | 56 | #include <sound/initval.h> |
| 56 | #include <linux/vgaarb.h> | 57 | #include <linux/vgaarb.h> |
| 57 | #include <linux/vga_switcheroo.h> | 58 | #include <linux/vga_switcheroo.h> |
| 59 | #include <linux/firmware.h> | ||
| 58 | #include "hda_codec.h" | 60 | #include "hda_codec.h" |
| 59 | 61 | ||
| 60 | 62 | ||
| @@ -62,7 +64,7 @@ static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | |||
| 62 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | 64 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; |
| 63 | static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | 65 | static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; |
| 64 | static char *model[SNDRV_CARDS]; | 66 | static char *model[SNDRV_CARDS]; |
| 65 | static int position_fix[SNDRV_CARDS]; | 67 | static int position_fix[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; |
| 66 | static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; | 68 | static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; |
| 67 | static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; | 69 | static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1}; |
| 68 | static int probe_only[SNDRV_CARDS]; | 70 | static int probe_only[SNDRV_CARDS]; |
| @@ -86,7 +88,7 @@ module_param_array(model, charp, NULL, 0444); | |||
| 86 | MODULE_PARM_DESC(model, "Use the given board model."); | 88 | MODULE_PARM_DESC(model, "Use the given board model."); |
| 87 | module_param_array(position_fix, int, NULL, 0444); | 89 | module_param_array(position_fix, int, NULL, 0444); |
| 88 | MODULE_PARM_DESC(position_fix, "DMA pointer read method." | 90 | MODULE_PARM_DESC(position_fix, "DMA pointer read method." |
| 89 | "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO)."); | 91 | "(-1 = system default, 0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO)."); |
| 90 | module_param_array(bdl_pos_adj, int, NULL, 0644); | 92 | module_param_array(bdl_pos_adj, int, NULL, 0644); |
| 91 | MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); | 93 | MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); |
| 92 | module_param_array(probe_mask, int, NULL, 0444); | 94 | module_param_array(probe_mask, int, NULL, 0444); |
| @@ -108,9 +110,16 @@ MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode " | |||
| 108 | "(0=off, 1=on) (default=1)."); | 110 | "(0=off, 1=on) (default=1)."); |
| 109 | #endif | 111 | #endif |
| 110 | 112 | ||
| 111 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 113 | #ifdef CONFIG_PM |
| 114 | static int param_set_xint(const char *val, const struct kernel_param *kp); | ||
| 115 | static struct kernel_param_ops param_ops_xint = { | ||
| 116 | .set = param_set_xint, | ||
| 117 | .get = param_get_int, | ||
| 118 | }; | ||
| 119 | #define param_check_xint param_check_int | ||
| 120 | |||
| 112 | static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; | 121 | static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; |
| 113 | module_param(power_save, int, 0644); | 122 | module_param(power_save, xint, 0644); |
| 114 | MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " | 123 | MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " |
| 115 | "(in second, 0 = disable)."); | 124 | "(in second, 0 = disable)."); |
| 116 | 125 | ||
| @@ -121,7 +130,7 @@ MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " | |||
| 121 | static bool power_save_controller = 1; | 130 | static bool power_save_controller = 1; |
| 122 | module_param(power_save_controller, bool, 0644); | 131 | module_param(power_save_controller, bool, 0644); |
| 123 | MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode."); | 132 | MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode."); |
| 124 | #endif | 133 | #endif /* CONFIG_PM */ |
| 125 | 134 | ||
| 126 | static int align_buffer_size = -1; | 135 | static int align_buffer_size = -1; |
| 127 | module_param(align_buffer_size, bint, 0644); | 136 | module_param(align_buffer_size, bint, 0644); |
| @@ -406,6 +415,7 @@ struct azx_dev { | |||
| 406 | */ | 415 | */ |
| 407 | unsigned int insufficient :1; | 416 | unsigned int insufficient :1; |
| 408 | unsigned int wc_marked:1; | 417 | unsigned int wc_marked:1; |
| 418 | unsigned int no_period_wakeup:1; | ||
| 409 | }; | 419 | }; |
| 410 | 420 | ||
| 411 | /* CORB/RIRB */ | 421 | /* CORB/RIRB */ |
| @@ -471,6 +481,10 @@ struct azx { | |||
| 471 | struct snd_dma_buffer rb; | 481 | struct snd_dma_buffer rb; |
| 472 | struct snd_dma_buffer posbuf; | 482 | struct snd_dma_buffer posbuf; |
| 473 | 483 | ||
| 484 | #ifdef CONFIG_SND_HDA_PATCH_LOADER | ||
| 485 | const struct firmware *fw; | ||
| 486 | #endif | ||
| 487 | |||
| 474 | /* flags */ | 488 | /* flags */ |
| 475 | int position_fix[2]; /* for both playback/capture streams */ | 489 | int position_fix[2]; /* for both playback/capture streams */ |
| 476 | int poll_count; | 490 | int poll_count; |
| @@ -498,6 +512,9 @@ struct azx { | |||
| 498 | 512 | ||
| 499 | /* reboot notifier (for mysterious hangup problem at power-down) */ | 513 | /* reboot notifier (for mysterious hangup problem at power-down) */ |
| 500 | struct notifier_block reboot_notifier; | 514 | struct notifier_block reboot_notifier; |
| 515 | |||
| 516 | /* card list (for power_save trigger) */ | ||
| 517 | struct list_head list; | ||
| 501 | }; | 518 | }; |
| 502 | 519 | ||
| 503 | /* driver types */ | 520 | /* driver types */ |
| @@ -538,6 +555,7 @@ enum { | |||
| 538 | #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ | 555 | #define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */ |
| 539 | #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ | 556 | #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23) /* BDLE in 4k boundary */ |
| 540 | #define AZX_DCAPS_POSFIX_COMBO (1 << 24) /* Use COMBO as default */ | 557 | #define AZX_DCAPS_POSFIX_COMBO (1 << 24) /* Use COMBO as default */ |
| 558 | #define AZX_DCAPS_COUNT_LPIB_DELAY (1 << 25) /* Take LPIB as delay */ | ||
| 541 | 559 | ||
| 542 | /* quirks for ATI SB / AMD Hudson */ | 560 | /* quirks for ATI SB / AMD Hudson */ |
| 543 | #define AZX_DCAPS_PRESET_ATI_SB \ | 561 | #define AZX_DCAPS_PRESET_ATI_SB \ |
| @@ -560,13 +578,17 @@ enum { | |||
| 560 | * VGA-switcher support | 578 | * VGA-switcher support |
| 561 | */ | 579 | */ |
| 562 | #ifdef SUPPORT_VGA_SWITCHEROO | 580 | #ifdef SUPPORT_VGA_SWITCHEROO |
| 581 | #define use_vga_switcheroo(chip) ((chip)->use_vga_switcheroo) | ||
| 582 | #else | ||
| 583 | #define use_vga_switcheroo(chip) 0 | ||
| 584 | #endif | ||
| 585 | |||
| 586 | #if defined(SUPPORT_VGA_SWITCHEROO) || defined(CONFIG_SND_HDA_PATCH_LOADER) | ||
| 563 | #define DELAYED_INIT_MARK | 587 | #define DELAYED_INIT_MARK |
| 564 | #define DELAYED_INITDATA_MARK | 588 | #define DELAYED_INITDATA_MARK |
| 565 | #define use_vga_switcheroo(chip) ((chip)->use_vga_switcheroo) | ||
| 566 | #else | 589 | #else |
| 567 | #define DELAYED_INIT_MARK __devinit | 590 | #define DELAYED_INIT_MARK __devinit |
| 568 | #define DELAYED_INITDATA_MARK __devinitdata | 591 | #define DELAYED_INITDATA_MARK __devinitdata |
| 569 | #define use_vga_switcheroo(chip) 0 | ||
| 570 | #endif | 592 | #endif |
| 571 | 593 | ||
| 572 | static char *driver_short_names[] DELAYED_INITDATA_MARK = { | 594 | static char *driver_short_names[] DELAYED_INITDATA_MARK = { |
| @@ -1012,8 +1034,8 @@ static unsigned int azx_get_response(struct hda_bus *bus, | |||
| 1012 | return azx_rirb_get_response(bus, addr); | 1034 | return azx_rirb_get_response(bus, addr); |
| 1013 | } | 1035 | } |
| 1014 | 1036 | ||
| 1015 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1037 | #ifdef CONFIG_PM |
| 1016 | static void azx_power_notify(struct hda_bus *bus); | 1038 | static void azx_power_notify(struct hda_bus *bus, bool power_up); |
| 1017 | #endif | 1039 | #endif |
| 1018 | 1040 | ||
| 1019 | /* reset codec link */ | 1041 | /* reset codec link */ |
| @@ -1269,6 +1291,11 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) | |||
| 1269 | u8 sd_status; | 1291 | u8 sd_status; |
| 1270 | int i, ok; | 1292 | int i, ok; |
| 1271 | 1293 | ||
| 1294 | #ifdef CONFIG_PM_RUNTIME | ||
| 1295 | if (chip->pci->dev.power.runtime_status != RPM_ACTIVE) | ||
| 1296 | return IRQ_NONE; | ||
| 1297 | #endif | ||
| 1298 | |||
| 1272 | spin_lock(&chip->reg_lock); | 1299 | spin_lock(&chip->reg_lock); |
| 1273 | 1300 | ||
| 1274 | if (chip->disabled) { | 1301 | if (chip->disabled) { |
| @@ -1394,7 +1421,7 @@ static int azx_setup_periods(struct azx *chip, | |||
| 1394 | ofs = 0; | 1421 | ofs = 0; |
| 1395 | azx_dev->frags = 0; | 1422 | azx_dev->frags = 0; |
| 1396 | pos_adj = bdl_pos_adj[chip->dev_index]; | 1423 | pos_adj = bdl_pos_adj[chip->dev_index]; |
| 1397 | if (pos_adj > 0) { | 1424 | if (!azx_dev->no_period_wakeup && pos_adj > 0) { |
| 1398 | struct snd_pcm_runtime *runtime = substream->runtime; | 1425 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 1399 | int pos_align = pos_adj; | 1426 | int pos_align = pos_adj; |
| 1400 | pos_adj = (pos_adj * runtime->rate + 47999) / 48000; | 1427 | pos_adj = (pos_adj * runtime->rate + 47999) / 48000; |
| @@ -1410,8 +1437,7 @@ static int azx_setup_periods(struct azx *chip, | |||
| 1410 | pos_adj = 0; | 1437 | pos_adj = 0; |
| 1411 | } else { | 1438 | } else { |
| 1412 | ofs = setup_bdle(chip, substream, azx_dev, | 1439 | ofs = setup_bdle(chip, substream, azx_dev, |
| 1413 | &bdl, ofs, pos_adj, | 1440 | &bdl, ofs, pos_adj, true); |
| 1414 | !substream->runtime->no_period_wakeup); | ||
| 1415 | if (ofs < 0) | 1441 | if (ofs < 0) |
| 1416 | goto error; | 1442 | goto error; |
| 1417 | } | 1443 | } |
| @@ -1424,7 +1450,7 @@ static int azx_setup_periods(struct azx *chip, | |||
| 1424 | else | 1450 | else |
| 1425 | ofs = setup_bdle(chip, substream, azx_dev, &bdl, ofs, | 1451 | ofs = setup_bdle(chip, substream, azx_dev, &bdl, ofs, |
| 1426 | period_bytes, | 1452 | period_bytes, |
| 1427 | !substream->runtime->no_period_wakeup); | 1453 | !azx_dev->no_period_wakeup); |
| 1428 | if (ofs < 0) | 1454 | if (ofs < 0) |
| 1429 | goto error; | 1455 | goto error; |
| 1430 | } | 1456 | } |
| @@ -1580,7 +1606,7 @@ static int DELAYED_INIT_MARK azx_codec_create(struct azx *chip, const char *mode | |||
| 1580 | bus_temp.ops.get_response = azx_get_response; | 1606 | bus_temp.ops.get_response = azx_get_response; |
| 1581 | bus_temp.ops.attach_pcm = azx_attach_pcm_stream; | 1607 | bus_temp.ops.attach_pcm = azx_attach_pcm_stream; |
| 1582 | bus_temp.ops.bus_reset = azx_bus_reset; | 1608 | bus_temp.ops.bus_reset = azx_bus_reset; |
| 1583 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1609 | #ifdef CONFIG_PM |
| 1584 | bus_temp.power_save = &power_save; | 1610 | bus_temp.power_save = &power_save; |
| 1585 | bus_temp.ops.pm_notify = azx_power_notify; | 1611 | bus_temp.ops.pm_notify = azx_power_notify; |
| 1586 | #endif | 1612 | #endif |
| @@ -1897,10 +1923,12 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
| 1897 | 1923 | ||
| 1898 | if (bufsize != azx_dev->bufsize || | 1924 | if (bufsize != azx_dev->bufsize || |
| 1899 | period_bytes != azx_dev->period_bytes || | 1925 | period_bytes != azx_dev->period_bytes || |
| 1900 | format_val != azx_dev->format_val) { | 1926 | format_val != azx_dev->format_val || |
| 1927 | runtime->no_period_wakeup != azx_dev->no_period_wakeup) { | ||
| 1901 | azx_dev->bufsize = bufsize; | 1928 | azx_dev->bufsize = bufsize; |
| 1902 | azx_dev->period_bytes = period_bytes; | 1929 | azx_dev->period_bytes = period_bytes; |
| 1903 | azx_dev->format_val = format_val; | 1930 | azx_dev->format_val = format_val; |
| 1931 | azx_dev->no_period_wakeup = runtime->no_period_wakeup; | ||
| 1904 | err = azx_setup_periods(chip, substream, azx_dev); | 1932 | err = azx_setup_periods(chip, substream, azx_dev); |
| 1905 | if (err < 0) | 1933 | if (err < 0) |
| 1906 | return err; | 1934 | return err; |
| @@ -1959,14 +1987,14 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
| 1959 | } | 1987 | } |
| 1960 | 1988 | ||
| 1961 | spin_lock(&chip->reg_lock); | 1989 | spin_lock(&chip->reg_lock); |
| 1962 | if (nsync > 1) { | 1990 | |
| 1963 | /* first, set SYNC bits of corresponding streams */ | 1991 | /* first, set SYNC bits of corresponding streams */ |
| 1964 | if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) | 1992 | if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) |
| 1965 | azx_writel(chip, OLD_SSYNC, | 1993 | azx_writel(chip, OLD_SSYNC, |
| 1966 | azx_readl(chip, OLD_SSYNC) | sbits); | 1994 | azx_readl(chip, OLD_SSYNC) | sbits); |
| 1967 | else | 1995 | else |
| 1968 | azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) | sbits); | 1996 | azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) | sbits); |
| 1969 | } | 1997 | |
| 1970 | snd_pcm_group_for_each_entry(s, substream) { | 1998 | snd_pcm_group_for_each_entry(s, substream) { |
| 1971 | if (s->pcm->card != substream->pcm->card) | 1999 | if (s->pcm->card != substream->pcm->card) |
| 1972 | continue; | 2000 | continue; |
| @@ -1984,8 +2012,6 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
| 1984 | } | 2012 | } |
| 1985 | spin_unlock(&chip->reg_lock); | 2013 | spin_unlock(&chip->reg_lock); |
| 1986 | if (start) { | 2014 | if (start) { |
| 1987 | if (nsync == 1) | ||
| 1988 | return 0; | ||
| 1989 | /* wait until all FIFOs get ready */ | 2015 | /* wait until all FIFOs get ready */ |
| 1990 | for (timeout = 5000; timeout; timeout--) { | 2016 | for (timeout = 5000; timeout; timeout--) { |
| 1991 | nwait = 0; | 2017 | nwait = 0; |
| @@ -2018,16 +2044,14 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
| 2018 | cpu_relax(); | 2044 | cpu_relax(); |
| 2019 | } | 2045 | } |
| 2020 | } | 2046 | } |
| 2021 | if (nsync > 1) { | 2047 | spin_lock(&chip->reg_lock); |
| 2022 | spin_lock(&chip->reg_lock); | 2048 | /* reset SYNC bits */ |
| 2023 | /* reset SYNC bits */ | 2049 | if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) |
| 2024 | if (chip->driver_caps & AZX_DCAPS_OLD_SSYNC) | 2050 | azx_writel(chip, OLD_SSYNC, |
| 2025 | azx_writel(chip, OLD_SSYNC, | 2051 | azx_readl(chip, OLD_SSYNC) & ~sbits); |
| 2026 | azx_readl(chip, OLD_SSYNC) & ~sbits); | 2052 | else |
| 2027 | else | 2053 | azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits); |
| 2028 | azx_writel(chip, SSYNC, azx_readl(chip, SSYNC) & ~sbits); | 2054 | spin_unlock(&chip->reg_lock); |
| 2029 | spin_unlock(&chip->reg_lock); | ||
| 2030 | } | ||
| 2031 | return 0; | 2055 | return 0; |
| 2032 | } | 2056 | } |
| 2033 | 2057 | ||
| @@ -2120,6 +2144,27 @@ static unsigned int azx_get_position(struct azx *chip, | |||
| 2120 | 2144 | ||
| 2121 | if (pos >= azx_dev->bufsize) | 2145 | if (pos >= azx_dev->bufsize) |
| 2122 | pos = 0; | 2146 | pos = 0; |
| 2147 | |||
| 2148 | /* calculate runtime delay from LPIB */ | ||
| 2149 | if (azx_dev->substream->runtime && | ||
| 2150 | chip->position_fix[stream] == POS_FIX_POSBUF && | ||
| 2151 | (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) { | ||
| 2152 | unsigned int lpib_pos = azx_sd_readl(azx_dev, SD_LPIB); | ||
| 2153 | int delay; | ||
| 2154 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
| 2155 | delay = pos - lpib_pos; | ||
| 2156 | else | ||
| 2157 | delay = lpib_pos - pos; | ||
| 2158 | if (delay < 0) | ||
| 2159 | delay += azx_dev->bufsize; | ||
| 2160 | if (delay >= azx_dev->period_bytes) { | ||
| 2161 | snd_printdd("delay %d > period_bytes %d\n", | ||
| 2162 | delay, azx_dev->period_bytes); | ||
| 2163 | delay = 0; /* something is wrong */ | ||
| 2164 | } | ||
| 2165 | azx_dev->substream->runtime->delay = | ||
| 2166 | bytes_to_frames(azx_dev->substream->runtime, delay); | ||
| 2167 | } | ||
| 2123 | return pos; | 2168 | return pos; |
| 2124 | } | 2169 | } |
| 2125 | 2170 | ||
| @@ -2379,33 +2424,65 @@ static void azx_stop_chip(struct azx *chip) | |||
| 2379 | chip->initialized = 0; | 2424 | chip->initialized = 0; |
| 2380 | } | 2425 | } |
| 2381 | 2426 | ||
| 2382 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2427 | #ifdef CONFIG_PM |
| 2383 | /* power-up/down the controller */ | 2428 | /* power-up/down the controller */ |
| 2384 | static void azx_power_notify(struct hda_bus *bus) | 2429 | static void azx_power_notify(struct hda_bus *bus, bool power_up) |
| 2385 | { | 2430 | { |
| 2386 | struct azx *chip = bus->private_data; | 2431 | struct azx *chip = bus->private_data; |
| 2432 | |||
| 2433 | if (power_up) | ||
| 2434 | pm_runtime_get_sync(&chip->pci->dev); | ||
| 2435 | else | ||
| 2436 | pm_runtime_put_sync(&chip->pci->dev); | ||
| 2437 | } | ||
| 2438 | |||
| 2439 | static DEFINE_MUTEX(card_list_lock); | ||
| 2440 | static LIST_HEAD(card_list); | ||
| 2441 | |||
| 2442 | static void azx_add_card_list(struct azx *chip) | ||
| 2443 | { | ||
| 2444 | mutex_lock(&card_list_lock); | ||
| 2445 | list_add(&chip->list, &card_list); | ||
| 2446 | mutex_unlock(&card_list_lock); | ||
| 2447 | } | ||
| 2448 | |||
| 2449 | static void azx_del_card_list(struct azx *chip) | ||
| 2450 | { | ||
| 2451 | mutex_lock(&card_list_lock); | ||
| 2452 | list_del_init(&chip->list); | ||
| 2453 | mutex_unlock(&card_list_lock); | ||
| 2454 | } | ||
| 2455 | |||
| 2456 | /* trigger power-save check at writing parameter */ | ||
| 2457 | static int param_set_xint(const char *val, const struct kernel_param *kp) | ||
| 2458 | { | ||
| 2459 | struct azx *chip; | ||
| 2387 | struct hda_codec *c; | 2460 | struct hda_codec *c; |
| 2388 | int power_on = 0; | 2461 | int prev = power_save; |
| 2462 | int ret = param_set_int(val, kp); | ||
| 2389 | 2463 | ||
| 2390 | list_for_each_entry(c, &bus->codec_list, list) { | 2464 | if (ret || prev == power_save) |
| 2391 | if (c->power_on) { | 2465 | return ret; |
| 2392 | power_on = 1; | 2466 | |
| 2393 | break; | 2467 | mutex_lock(&card_list_lock); |
| 2394 | } | 2468 | list_for_each_entry(chip, &card_list, list) { |
| 2469 | if (!chip->bus || chip->disabled) | ||
| 2470 | continue; | ||
| 2471 | list_for_each_entry(c, &chip->bus->codec_list, list) | ||
| 2472 | snd_hda_power_sync(c); | ||
| 2395 | } | 2473 | } |
| 2396 | if (power_on) | 2474 | mutex_unlock(&card_list_lock); |
| 2397 | azx_init_chip(chip, 1); | 2475 | return 0; |
| 2398 | else if (chip->running && power_save_controller && | ||
| 2399 | !bus->power_keep_link_on) | ||
| 2400 | azx_stop_chip(chip); | ||
| 2401 | } | 2476 | } |
| 2402 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | 2477 | #else |
| 2478 | #define azx_add_card_list(chip) /* NOP */ | ||
| 2479 | #define azx_del_card_list(chip) /* NOP */ | ||
| 2480 | #endif /* CONFIG_PM */ | ||
| 2403 | 2481 | ||
| 2404 | #ifdef CONFIG_PM | 2482 | #if defined(CONFIG_PM_SLEEP) || defined(SUPPORT_VGA_SWITCHEROO) |
| 2405 | /* | 2483 | /* |
| 2406 | * power management | 2484 | * power management |
| 2407 | */ | 2485 | */ |
| 2408 | |||
| 2409 | static int azx_suspend(struct device *dev) | 2486 | static int azx_suspend(struct device *dev) |
| 2410 | { | 2487 | { |
| 2411 | struct pci_dev *pci = to_pci_dev(dev); | 2488 | struct pci_dev *pci = to_pci_dev(dev); |
| @@ -2460,11 +2537,41 @@ static int azx_resume(struct device *dev) | |||
| 2460 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | 2537 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); |
| 2461 | return 0; | 2538 | return 0; |
| 2462 | } | 2539 | } |
| 2463 | static SIMPLE_DEV_PM_OPS(azx_pm, azx_suspend, azx_resume); | 2540 | #endif /* CONFIG_PM_SLEEP || SUPPORT_VGA_SWITCHEROO */ |
| 2541 | |||
| 2542 | #ifdef CONFIG_PM_RUNTIME | ||
| 2543 | static int azx_runtime_suspend(struct device *dev) | ||
| 2544 | { | ||
| 2545 | struct snd_card *card = dev_get_drvdata(dev); | ||
| 2546 | struct azx *chip = card->private_data; | ||
| 2547 | |||
| 2548 | if (!power_save_controller) | ||
| 2549 | return -EAGAIN; | ||
| 2550 | |||
| 2551 | azx_stop_chip(chip); | ||
| 2552 | azx_clear_irq_pending(chip); | ||
| 2553 | return 0; | ||
| 2554 | } | ||
| 2555 | |||
| 2556 | static int azx_runtime_resume(struct device *dev) | ||
| 2557 | { | ||
| 2558 | struct snd_card *card = dev_get_drvdata(dev); | ||
| 2559 | struct azx *chip = card->private_data; | ||
| 2560 | |||
| 2561 | azx_init_pci(chip); | ||
| 2562 | azx_init_chip(chip, 1); | ||
| 2563 | return 0; | ||
| 2564 | } | ||
| 2565 | #endif /* CONFIG_PM_RUNTIME */ | ||
| 2566 | |||
| 2567 | #ifdef CONFIG_PM | ||
| 2568 | static const struct dev_pm_ops azx_pm = { | ||
| 2569 | SET_SYSTEM_SLEEP_PM_OPS(azx_suspend, azx_resume) | ||
| 2570 | SET_RUNTIME_PM_OPS(azx_runtime_suspend, azx_runtime_resume, NULL) | ||
| 2571 | }; | ||
| 2572 | |||
| 2464 | #define AZX_PM_OPS &azx_pm | 2573 | #define AZX_PM_OPS &azx_pm |
| 2465 | #else | 2574 | #else |
| 2466 | #define azx_suspend(dev) | ||
| 2467 | #define azx_resume(dev) | ||
| 2468 | #define AZX_PM_OPS NULL | 2575 | #define AZX_PM_OPS NULL |
| 2469 | #endif /* CONFIG_PM */ | 2576 | #endif /* CONFIG_PM */ |
| 2470 | 2577 | ||
| @@ -2599,6 +2706,8 @@ static int azx_free(struct azx *chip) | |||
| 2599 | { | 2706 | { |
| 2600 | int i; | 2707 | int i; |
| 2601 | 2708 | ||
| 2709 | azx_del_card_list(chip); | ||
| 2710 | |||
| 2602 | azx_notifier_unregister(chip); | 2711 | azx_notifier_unregister(chip); |
| 2603 | 2712 | ||
| 2604 | if (use_vga_switcheroo(chip)) { | 2713 | if (use_vga_switcheroo(chip)) { |
| @@ -2640,6 +2749,10 @@ static int azx_free(struct azx *chip) | |||
| 2640 | pci_release_regions(chip->pci); | 2749 | pci_release_regions(chip->pci); |
| 2641 | pci_disable_device(chip->pci); | 2750 | pci_disable_device(chip->pci); |
| 2642 | kfree(chip->azx_dev); | 2751 | kfree(chip->azx_dev); |
| 2752 | #ifdef CONFIG_SND_HDA_PATCH_LOADER | ||
| 2753 | if (chip->fw) | ||
| 2754 | release_firmware(chip->fw); | ||
| 2755 | #endif | ||
| 2643 | kfree(chip); | 2756 | kfree(chip); |
| 2644 | 2757 | ||
| 2645 | return 0; | 2758 | return 0; |
| @@ -2719,6 +2832,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix) | |||
| 2719 | const struct snd_pci_quirk *q; | 2832 | const struct snd_pci_quirk *q; |
| 2720 | 2833 | ||
| 2721 | switch (fix) { | 2834 | switch (fix) { |
| 2835 | case POS_FIX_AUTO: | ||
| 2722 | case POS_FIX_LPIB: | 2836 | case POS_FIX_LPIB: |
| 2723 | case POS_FIX_POSBUF: | 2837 | case POS_FIX_POSBUF: |
| 2724 | case POS_FIX_VIACOMBO: | 2838 | case POS_FIX_VIACOMBO: |
| @@ -2904,6 +3018,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, | |||
| 2904 | chip->dev_index = dev; | 3018 | chip->dev_index = dev; |
| 2905 | INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); | 3019 | INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work); |
| 2906 | INIT_LIST_HEAD(&chip->pcm_list); | 3020 | INIT_LIST_HEAD(&chip->pcm_list); |
| 3021 | INIT_LIST_HEAD(&chip->list); | ||
| 2907 | init_vga_switcheroo(chip); | 3022 | init_vga_switcheroo(chip); |
| 2908 | 3023 | ||
| 2909 | chip->position_fix[0] = chip->position_fix[1] = | 3024 | chip->position_fix[0] = chip->position_fix[1] = |
| @@ -3138,7 +3253,7 @@ static int DELAYED_INIT_MARK azx_first_init(struct azx *chip) | |||
| 3138 | 3253 | ||
| 3139 | static void power_down_all_codecs(struct azx *chip) | 3254 | static void power_down_all_codecs(struct azx *chip) |
| 3140 | { | 3255 | { |
| 3141 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3256 | #ifdef CONFIG_PM |
| 3142 | /* The codecs were powered up in snd_hda_codec_new(). | 3257 | /* The codecs were powered up in snd_hda_codec_new(). |
| 3143 | * Now all initialization done, so turn them down if possible | 3258 | * Now all initialization done, so turn them down if possible |
| 3144 | */ | 3259 | */ |
| @@ -3149,12 +3264,40 @@ static void power_down_all_codecs(struct azx *chip) | |||
| 3149 | #endif | 3264 | #endif |
| 3150 | } | 3265 | } |
| 3151 | 3266 | ||
| 3267 | #ifdef CONFIG_SND_HDA_PATCH_LOADER | ||
| 3268 | /* callback from request_firmware_nowait() */ | ||
| 3269 | static void azx_firmware_cb(const struct firmware *fw, void *context) | ||
| 3270 | { | ||
| 3271 | struct snd_card *card = context; | ||
| 3272 | struct azx *chip = card->private_data; | ||
| 3273 | struct pci_dev *pci = chip->pci; | ||
| 3274 | |||
| 3275 | if (!fw) { | ||
| 3276 | snd_printk(KERN_ERR SFX "Cannot load firmware, aborting\n"); | ||
| 3277 | goto error; | ||
| 3278 | } | ||
| 3279 | |||
| 3280 | chip->fw = fw; | ||
| 3281 | if (!chip->disabled) { | ||
| 3282 | /* continue probing */ | ||
| 3283 | if (azx_probe_continue(chip)) | ||
| 3284 | goto error; | ||
| 3285 | } | ||
| 3286 | return; /* OK */ | ||
| 3287 | |||
| 3288 | error: | ||
| 3289 | snd_card_free(card); | ||
| 3290 | pci_set_drvdata(pci, NULL); | ||
| 3291 | } | ||
| 3292 | #endif | ||
| 3293 | |||
| 3152 | static int __devinit azx_probe(struct pci_dev *pci, | 3294 | static int __devinit azx_probe(struct pci_dev *pci, |
| 3153 | const struct pci_device_id *pci_id) | 3295 | const struct pci_device_id *pci_id) |
| 3154 | { | 3296 | { |
| 3155 | static int dev; | 3297 | static int dev; |
| 3156 | struct snd_card *card; | 3298 | struct snd_card *card; |
| 3157 | struct azx *chip; | 3299 | struct azx *chip; |
| 3300 | bool probe_now; | ||
| 3158 | int err; | 3301 | int err; |
| 3159 | 3302 | ||
| 3160 | if (dev >= SNDRV_CARDS) | 3303 | if (dev >= SNDRV_CARDS) |
| @@ -3170,15 +3313,28 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
| 3170 | return err; | 3313 | return err; |
| 3171 | } | 3314 | } |
| 3172 | 3315 | ||
| 3173 | /* set this here since it's referred in snd_hda_load_patch() */ | ||
| 3174 | snd_card_set_dev(card, &pci->dev); | 3316 | snd_card_set_dev(card, &pci->dev); |
| 3175 | 3317 | ||
| 3176 | err = azx_create(card, pci, dev, pci_id->driver_data, &chip); | 3318 | err = azx_create(card, pci, dev, pci_id->driver_data, &chip); |
| 3177 | if (err < 0) | 3319 | if (err < 0) |
| 3178 | goto out_free; | 3320 | goto out_free; |
| 3179 | card->private_data = chip; | 3321 | card->private_data = chip; |
| 3322 | probe_now = !chip->disabled; | ||
| 3180 | 3323 | ||
| 3181 | if (!chip->disabled) { | 3324 | #ifdef CONFIG_SND_HDA_PATCH_LOADER |
| 3325 | if (patch[dev] && *patch[dev]) { | ||
| 3326 | snd_printk(KERN_ERR SFX "Applying patch firmware '%s'\n", | ||
| 3327 | patch[dev]); | ||
| 3328 | err = request_firmware_nowait(THIS_MODULE, true, patch[dev], | ||
| 3329 | &pci->dev, GFP_KERNEL, card, | ||
| 3330 | azx_firmware_cb); | ||
| 3331 | if (err < 0) | ||
| 3332 | goto out_free; | ||
| 3333 | probe_now = false; /* continued in azx_firmware_cb() */ | ||
| 3334 | } | ||
| 3335 | #endif /* CONFIG_SND_HDA_PATCH_LOADER */ | ||
| 3336 | |||
| 3337 | if (probe_now) { | ||
| 3182 | err = azx_probe_continue(chip); | 3338 | err = azx_probe_continue(chip); |
| 3183 | if (err < 0) | 3339 | if (err < 0) |
| 3184 | goto out_free; | 3340 | goto out_free; |
| @@ -3186,6 +3342,9 @@ static int __devinit azx_probe(struct pci_dev *pci, | |||
| 3186 | 3342 | ||
| 3187 | pci_set_drvdata(pci, card); | 3343 | pci_set_drvdata(pci, card); |
| 3188 | 3344 | ||
| 3345 | if (pci_dev_run_wake(pci)) | ||
| 3346 | pm_runtime_put_noidle(&pci->dev); | ||
| 3347 | |||
| 3189 | dev++; | 3348 | dev++; |
| 3190 | return 0; | 3349 | return 0; |
| 3191 | 3350 | ||
| @@ -3208,12 +3367,13 @@ static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip) | |||
| 3208 | if (err < 0) | 3367 | if (err < 0) |
| 3209 | goto out_free; | 3368 | goto out_free; |
| 3210 | #ifdef CONFIG_SND_HDA_PATCH_LOADER | 3369 | #ifdef CONFIG_SND_HDA_PATCH_LOADER |
| 3211 | if (patch[dev] && *patch[dev]) { | 3370 | if (chip->fw) { |
| 3212 | snd_printk(KERN_ERR SFX "Applying patch firmware '%s'\n", | 3371 | err = snd_hda_load_patch(chip->bus, chip->fw->size, |
| 3213 | patch[dev]); | 3372 | chip->fw->data); |
| 3214 | err = snd_hda_load_patch(chip->bus, patch[dev]); | ||
| 3215 | if (err < 0) | 3373 | if (err < 0) |
| 3216 | goto out_free; | 3374 | goto out_free; |
| 3375 | release_firmware(chip->fw); /* no longer needed */ | ||
| 3376 | chip->fw = NULL; | ||
| 3217 | } | 3377 | } |
| 3218 | #endif | 3378 | #endif |
| 3219 | if ((probe_only[dev] & 1) == 0) { | 3379 | if ((probe_only[dev] & 1) == 0) { |
| @@ -3239,6 +3399,7 @@ static int DELAYED_INIT_MARK azx_probe_continue(struct azx *chip) | |||
| 3239 | chip->running = 1; | 3399 | chip->running = 1; |
| 3240 | power_down_all_codecs(chip); | 3400 | power_down_all_codecs(chip); |
| 3241 | azx_notifier_register(chip); | 3401 | azx_notifier_register(chip); |
| 3402 | azx_add_card_list(chip); | ||
| 3242 | 3403 | ||
| 3243 | return 0; | 3404 | return 0; |
| 3244 | 3405 | ||
| @@ -3250,6 +3411,10 @@ out_free: | |||
| 3250 | static void __devexit azx_remove(struct pci_dev *pci) | 3411 | static void __devexit azx_remove(struct pci_dev *pci) |
| 3251 | { | 3412 | { |
| 3252 | struct snd_card *card = pci_get_drvdata(pci); | 3413 | struct snd_card *card = pci_get_drvdata(pci); |
| 3414 | |||
| 3415 | if (pci_dev_run_wake(pci)) | ||
| 3416 | pm_runtime_get_noresume(&pci->dev); | ||
| 3417 | |||
| 3253 | if (card) | 3418 | if (card) |
| 3254 | snd_card_free(card); | 3419 | snd_card_free(card); |
| 3255 | pci_set_drvdata(pci, NULL); | 3420 | pci_set_drvdata(pci, NULL); |
| @@ -3260,7 +3425,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
| 3260 | /* CPT */ | 3425 | /* CPT */ |
| 3261 | { PCI_DEVICE(0x8086, 0x1c20), | 3426 | { PCI_DEVICE(0x8086, 0x1c20), |
| 3262 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 3427 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
| 3263 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, | 3428 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, |
| 3264 | /* PBG */ | 3429 | /* PBG */ |
| 3265 | { PCI_DEVICE(0x8086, 0x1d20), | 3430 | { PCI_DEVICE(0x8086, 0x1d20), |
| 3266 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 3431 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
| @@ -3268,23 +3433,30 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
| 3268 | /* Panther Point */ | 3433 | /* Panther Point */ |
| 3269 | { PCI_DEVICE(0x8086, 0x1e20), | 3434 | { PCI_DEVICE(0x8086, 0x1e20), |
| 3270 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 3435 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
| 3271 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, | 3436 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, |
| 3272 | /* Lynx Point */ | 3437 | /* Lynx Point */ |
| 3273 | { PCI_DEVICE(0x8086, 0x8c20), | 3438 | { PCI_DEVICE(0x8086, 0x8c20), |
| 3274 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 3439 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
| 3275 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, | 3440 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, |
| 3276 | /* Lynx Point-LP */ | 3441 | /* Lynx Point-LP */ |
| 3277 | { PCI_DEVICE(0x8086, 0x9c20), | 3442 | { PCI_DEVICE(0x8086, 0x9c20), |
| 3278 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 3443 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
| 3279 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, | 3444 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, |
| 3280 | /* Lynx Point-LP */ | 3445 | /* Lynx Point-LP */ |
| 3281 | { PCI_DEVICE(0x8086, 0x9c21), | 3446 | { PCI_DEVICE(0x8086, 0x9c21), |
| 3282 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | | 3447 | .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP | |
| 3283 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, | 3448 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, |
| 3284 | /* Haswell */ | 3449 | /* Haswell */ |
| 3285 | { PCI_DEVICE(0x8086, 0x0c0c), | 3450 | { PCI_DEVICE(0x8086, 0x0c0c), |
| 3286 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | | 3451 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | |
| 3287 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_COMBO }, | 3452 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, |
| 3453 | { PCI_DEVICE(0x8086, 0x0d0c), | ||
| 3454 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | | ||
| 3455 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, | ||
| 3456 | /* 5 Series/3400 */ | ||
| 3457 | { PCI_DEVICE(0x8086, 0x3b56), | ||
| 3458 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | | ||
| 3459 | AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY }, | ||
| 3288 | /* SCH */ | 3460 | /* SCH */ |
| 3289 | { PCI_DEVICE(0x8086, 0x811b), | 3461 | { PCI_DEVICE(0x8086, 0x811b), |
| 3290 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | | 3462 | .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP | |
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c index aaccc0236bda..5c690cb873d4 100644 --- a/sound/pci/hda/hda_jack.c +++ b/sound/pci/hda/hda_jack.c | |||
| @@ -26,9 +26,8 @@ bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) | |||
| 26 | return false; | 26 | return false; |
| 27 | if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) | 27 | if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) |
| 28 | return false; | 28 | return false; |
| 29 | if (!codec->ignore_misc_bit && | 29 | if (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & |
| 30 | (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & | 30 | AC_DEFCFG_MISC_NO_PRESENCE) |
| 31 | AC_DEFCFG_MISC_NO_PRESENCE)) | ||
| 32 | return false; | 31 | return false; |
| 33 | if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) | 32 | if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) |
| 34 | return false; | 33 | return false; |
| @@ -193,8 +192,9 @@ EXPORT_SYMBOL_HDA(snd_hda_jack_detect); | |||
| 193 | /** | 192 | /** |
| 194 | * snd_hda_jack_detect_enable - enable the jack-detection | 193 | * snd_hda_jack_detect_enable - enable the jack-detection |
| 195 | */ | 194 | */ |
| 196 | int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, | 195 | int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, |
| 197 | unsigned char action) | 196 | unsigned char action, |
| 197 | hda_jack_callback cb) | ||
| 198 | { | 198 | { |
| 199 | struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); | 199 | struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); |
| 200 | if (!jack) | 200 | if (!jack) |
| @@ -204,10 +204,19 @@ int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, | |||
| 204 | jack->jack_detect = 1; | 204 | jack->jack_detect = 1; |
| 205 | if (action) | 205 | if (action) |
| 206 | jack->action = action; | 206 | jack->action = action; |
| 207 | if (cb) | ||
| 208 | jack->callback = cb; | ||
| 207 | return snd_hda_codec_write_cache(codec, nid, 0, | 209 | return snd_hda_codec_write_cache(codec, nid, 0, |
| 208 | AC_VERB_SET_UNSOLICITED_ENABLE, | 210 | AC_VERB_SET_UNSOLICITED_ENABLE, |
| 209 | AC_USRSP_EN | jack->tag); | 211 | AC_USRSP_EN | jack->tag); |
| 210 | } | 212 | } |
| 213 | EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable_callback); | ||
| 214 | |||
| 215 | int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, | ||
| 216 | unsigned char action) | ||
| 217 | { | ||
| 218 | return snd_hda_jack_detect_enable_callback(codec, nid, action, NULL); | ||
| 219 | } | ||
| 211 | EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable); | 220 | EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable); |
| 212 | 221 | ||
| 213 | /** | 222 | /** |
| @@ -412,3 +421,21 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec, | |||
| 412 | return 0; | 421 | return 0; |
| 413 | } | 422 | } |
| 414 | EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls); | 423 | EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls); |
| 424 | |||
| 425 | void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res) | ||
| 426 | { | ||
| 427 | struct hda_jack_tbl *event; | ||
| 428 | int tag = (res >> AC_UNSOL_RES_TAG_SHIFT) & 0x7f; | ||
| 429 | |||
| 430 | event = snd_hda_jack_tbl_get_from_tag(codec, tag); | ||
| 431 | if (!event) | ||
| 432 | return; | ||
| 433 | event->jack_dirty = 1; | ||
| 434 | |||
| 435 | if (event->callback) | ||
| 436 | event->callback(codec, event); | ||
| 437 | |||
| 438 | snd_hda_jack_report_sync(codec); | ||
| 439 | } | ||
| 440 | EXPORT_SYMBOL_HDA(snd_hda_jack_unsol_event); | ||
| 441 | |||
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h index a9803da633c0..af8dd4724da5 100644 --- a/sound/pci/hda/hda_jack.h +++ b/sound/pci/hda/hda_jack.h | |||
| @@ -13,12 +13,16 @@ | |||
| 13 | #define __SOUND_HDA_JACK_H | 13 | #define __SOUND_HDA_JACK_H |
| 14 | 14 | ||
| 15 | struct auto_pin_cfg; | 15 | struct auto_pin_cfg; |
| 16 | struct hda_jack_tbl; | ||
| 17 | |||
| 18 | typedef void (*hda_jack_callback) (struct hda_codec *, struct hda_jack_tbl *); | ||
| 16 | 19 | ||
| 17 | struct hda_jack_tbl { | 20 | struct hda_jack_tbl { |
| 18 | hda_nid_t nid; | 21 | hda_nid_t nid; |
| 19 | unsigned char action; /* event action (0 = none) */ | 22 | unsigned char action; /* event action (0 = none) */ |
| 20 | unsigned char tag; /* unsol event tag */ | 23 | unsigned char tag; /* unsol event tag */ |
| 21 | unsigned int private_data; /* arbitrary data */ | 24 | unsigned int private_data; /* arbitrary data */ |
| 25 | hda_jack_callback callback; | ||
| 22 | /* jack-detection stuff */ | 26 | /* jack-detection stuff */ |
| 23 | unsigned int pin_sense; /* cached pin-sense value */ | 27 | unsigned int pin_sense; /* cached pin-sense value */ |
| 24 | unsigned int jack_detect:1; /* capable of jack-detection? */ | 28 | unsigned int jack_detect:1; /* capable of jack-detection? */ |
| @@ -61,6 +65,10 @@ void snd_hda_jack_set_dirty_all(struct hda_codec *codec); | |||
| 61 | 65 | ||
| 62 | int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, | 66 | int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, |
| 63 | unsigned char action); | 67 | unsigned char action); |
| 68 | int snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, | ||
| 69 | unsigned char action, | ||
| 70 | hda_jack_callback cb); | ||
| 71 | |||
| 64 | 72 | ||
| 65 | u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); | 73 | u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); |
| 66 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); | 74 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); |
| @@ -74,5 +82,6 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec, | |||
| 74 | 82 | ||
| 75 | void snd_hda_jack_report_sync(struct hda_codec *codec); | 83 | void snd_hda_jack_report_sync(struct hda_codec *codec); |
| 76 | 84 | ||
| 85 | void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res); | ||
| 77 | 86 | ||
| 78 | #endif /* __SOUND_HDA_JACK_H */ | 87 | #endif /* __SOUND_HDA_JACK_H */ |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 1b4c12941baa..09dbdc37f781 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
| @@ -529,7 +529,7 @@ int snd_hda_create_hwdep(struct hda_codec *codec); | |||
| 529 | static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; } | 529 | static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; } |
| 530 | #endif | 530 | #endif |
| 531 | 531 | ||
| 532 | #if defined(CONFIG_SND_HDA_POWER_SAVE) && defined(CONFIG_SND_HDA_HWDEP) | 532 | #if defined(CONFIG_PM) && defined(CONFIG_SND_HDA_HWDEP) |
| 533 | int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec); | 533 | int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec); |
| 534 | #else | 534 | #else |
| 535 | static inline int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec) | 535 | static inline int snd_hda_hwdep_add_power_sysfs(struct hda_codec *codec) |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index 6894ec66258c..045e5d32f5de 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
| @@ -402,6 +402,9 @@ static void print_digital_conv(struct snd_info_buffer *buffer, | |||
| 402 | { | 402 | { |
| 403 | unsigned int digi1 = snd_hda_codec_read(codec, nid, 0, | 403 | unsigned int digi1 = snd_hda_codec_read(codec, nid, 0, |
| 404 | AC_VERB_GET_DIGI_CONVERT_1, 0); | 404 | AC_VERB_GET_DIGI_CONVERT_1, 0); |
| 405 | unsigned char digi2 = digi1 >> 8; | ||
| 406 | unsigned char digi3 = digi1 >> 16; | ||
| 407 | |||
| 405 | snd_iprintf(buffer, " Digital:"); | 408 | snd_iprintf(buffer, " Digital:"); |
| 406 | if (digi1 & AC_DIG1_ENABLE) | 409 | if (digi1 & AC_DIG1_ENABLE) |
| 407 | snd_iprintf(buffer, " Enabled"); | 410 | snd_iprintf(buffer, " Enabled"); |
| @@ -419,9 +422,13 @@ static void print_digital_conv(struct snd_info_buffer *buffer, | |||
| 419 | snd_iprintf(buffer, " Pro"); | 422 | snd_iprintf(buffer, " Pro"); |
| 420 | if (digi1 & AC_DIG1_LEVEL) | 423 | if (digi1 & AC_DIG1_LEVEL) |
| 421 | snd_iprintf(buffer, " GenLevel"); | 424 | snd_iprintf(buffer, " GenLevel"); |
| 425 | if (digi3 & AC_DIG3_KAE) | ||
| 426 | snd_iprintf(buffer, " KAE"); | ||
| 422 | snd_iprintf(buffer, "\n"); | 427 | snd_iprintf(buffer, "\n"); |
| 423 | snd_iprintf(buffer, " Digital category: 0x%x\n", | 428 | snd_iprintf(buffer, " Digital category: 0x%x\n", |
| 424 | (digi1 >> 8) & AC_DIG2_CC); | 429 | digi2 & AC_DIG2_CC); |
| 430 | snd_iprintf(buffer, " IEC Coding Type: 0x%x\n", | ||
| 431 | digi3 & AC_DIG3_ICT); | ||
| 425 | } | 432 | } |
| 426 | 433 | ||
| 427 | static const char *get_pwr_state(u32 state) | 434 | static const char *get_pwr_state(u32 state) |
diff --git a/sound/pci/hda/hda_trace.h b/sound/pci/hda/hda_trace.h index 9884871ddb00..3a1c63161eb1 100644 --- a/sound/pci/hda/hda_trace.h +++ b/sound/pci/hda/hda_trace.h | |||
| @@ -58,6 +58,7 @@ TRACE_EVENT(hda_bus_reset, | |||
| 58 | TP_printk("[%d]", __entry->card) | 58 | TP_printk("[%d]", __entry->card) |
| 59 | ); | 59 | ); |
| 60 | 60 | ||
| 61 | #ifdef CONFIG_PM | ||
| 61 | DECLARE_EVENT_CLASS(hda_power, | 62 | DECLARE_EVENT_CLASS(hda_power, |
| 62 | 63 | ||
| 63 | TP_PROTO(struct hda_codec *codec), | 64 | TP_PROTO(struct hda_codec *codec), |
| @@ -87,6 +88,31 @@ DEFINE_EVENT(hda_power, hda_power_up, | |||
| 87 | TP_ARGS(codec) | 88 | TP_ARGS(codec) |
| 88 | ); | 89 | ); |
| 89 | 90 | ||
| 91 | TRACE_EVENT(hda_power_count, | ||
| 92 | TP_PROTO(struct hda_codec *codec), | ||
| 93 | TP_ARGS(codec), | ||
| 94 | TP_STRUCT__entry( | ||
| 95 | __field( unsigned int, card ) | ||
| 96 | __field( unsigned int, addr ) | ||
| 97 | __field( int, power_count ) | ||
| 98 | __field( int, power_on ) | ||
| 99 | __field( int, power_transition ) | ||
| 100 | ), | ||
| 101 | |||
| 102 | TP_fast_assign( | ||
| 103 | __entry->card = (codec)->bus->card->number; | ||
| 104 | __entry->addr = (codec)->addr; | ||
| 105 | __entry->power_count = (codec)->power_count; | ||
| 106 | __entry->power_on = (codec)->power_on; | ||
| 107 | __entry->power_transition = (codec)->power_transition; | ||
| 108 | ), | ||
| 109 | |||
| 110 | TP_printk("[%d:%d] power_count=%d, power_on=%d, power_transition=%d", | ||
| 111 | __entry->card, __entry->addr, __entry->power_count, | ||
| 112 | __entry->power_on, __entry->power_transition) | ||
| 113 | ); | ||
| 114 | #endif /* CONFIG_PM */ | ||
| 115 | |||
| 90 | TRACE_EVENT(hda_unsol_event, | 116 | TRACE_EVENT(hda_unsol_event, |
| 91 | 117 | ||
| 92 | TP_PROTO(struct hda_bus *bus, u32 res, u32 res_ex), | 118 | TP_PROTO(struct hda_bus *bus, u32 res, u32 res_ex), |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 0208fa121e5a..cdd43eadbc67 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
| @@ -85,7 +85,7 @@ struct ad198x_spec { | |||
| 85 | unsigned int analog_beep: 1; /* analog beep input present */ | 85 | unsigned int analog_beep: 1; /* analog beep input present */ |
| 86 | unsigned int avoid_init_slave_vol:1; | 86 | unsigned int avoid_init_slave_vol:1; |
| 87 | 87 | ||
| 88 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 88 | #ifdef CONFIG_PM |
| 89 | struct hda_loopback_check loopback; | 89 | struct hda_loopback_check loopback; |
| 90 | #endif | 90 | #endif |
| 91 | /* for virtual master */ | 91 | /* for virtual master */ |
| @@ -269,7 +269,7 @@ static int ad198x_build_controls(struct hda_codec *codec) | |||
| 269 | return 0; | 269 | return 0; |
| 270 | } | 270 | } |
| 271 | 271 | ||
| 272 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 272 | #ifdef CONFIG_PM |
| 273 | static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid) | 273 | static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid) |
| 274 | { | 274 | { |
| 275 | struct ad198x_spec *spec = codec->spec; | 275 | struct ad198x_spec *spec = codec->spec; |
| @@ -654,10 +654,8 @@ static const struct hda_codec_ops ad198x_patch_ops = { | |||
| 654 | .build_pcms = ad198x_build_pcms, | 654 | .build_pcms = ad198x_build_pcms, |
| 655 | .init = ad198x_init, | 655 | .init = ad198x_init, |
| 656 | .free = ad198x_free, | 656 | .free = ad198x_free, |
| 657 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
| 658 | .check_power_status = ad198x_check_power_status, | ||
| 659 | #endif | ||
| 660 | #ifdef CONFIG_PM | 657 | #ifdef CONFIG_PM |
| 658 | .check_power_status = ad198x_check_power_status, | ||
| 661 | .suspend = ad198x_suspend, | 659 | .suspend = ad198x_suspend, |
| 662 | #endif | 660 | #endif |
| 663 | .reboot_notify = ad198x_shutup, | 661 | .reboot_notify = ad198x_shutup, |
| @@ -1231,7 +1229,7 @@ static const struct snd_pci_quirk ad1986a_cfg_tbl[] = { | |||
| 1231 | {} | 1229 | {} |
| 1232 | }; | 1230 | }; |
| 1233 | 1231 | ||
| 1234 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1232 | #ifdef CONFIG_PM |
| 1235 | static const struct hda_amp_list ad1986a_loopbacks[] = { | 1233 | static const struct hda_amp_list ad1986a_loopbacks[] = { |
| 1236 | { 0x13, HDA_OUTPUT, 0 }, /* Mic */ | 1234 | { 0x13, HDA_OUTPUT, 0 }, /* Mic */ |
| 1237 | { 0x14, HDA_OUTPUT, 0 }, /* Phone */ | 1235 | { 0x14, HDA_OUTPUT, 0 }, /* Phone */ |
| @@ -1278,7 +1276,7 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
| 1278 | spec->mixers[0] = ad1986a_mixers; | 1276 | spec->mixers[0] = ad1986a_mixers; |
| 1279 | spec->num_init_verbs = 1; | 1277 | spec->num_init_verbs = 1; |
| 1280 | spec->init_verbs[0] = ad1986a_init_verbs; | 1278 | spec->init_verbs[0] = ad1986a_init_verbs; |
| 1281 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1279 | #ifdef CONFIG_PM |
| 1282 | spec->loopback.amplist = ad1986a_loopbacks; | 1280 | spec->loopback.amplist = ad1986a_loopbacks; |
| 1283 | #endif | 1281 | #endif |
| 1284 | spec->vmaster_nid = 0x1b; | 1282 | spec->vmaster_nid = 0x1b; |
| @@ -1537,7 +1535,7 @@ static const struct hda_verb ad1983_init_verbs[] = { | |||
| 1537 | { } /* end */ | 1535 | { } /* end */ |
| 1538 | }; | 1536 | }; |
| 1539 | 1537 | ||
| 1540 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1538 | #ifdef CONFIG_PM |
| 1541 | static const struct hda_amp_list ad1983_loopbacks[] = { | 1539 | static const struct hda_amp_list ad1983_loopbacks[] = { |
| 1542 | { 0x12, HDA_OUTPUT, 0 }, /* Mic */ | 1540 | { 0x12, HDA_OUTPUT, 0 }, /* Mic */ |
| 1543 | { 0x13, HDA_OUTPUT, 0 }, /* Line */ | 1541 | { 0x13, HDA_OUTPUT, 0 }, /* Line */ |
| @@ -1576,7 +1574,7 @@ static int patch_ad1983(struct hda_codec *codec) | |||
| 1576 | spec->num_init_verbs = 1; | 1574 | spec->num_init_verbs = 1; |
| 1577 | spec->init_verbs[0] = ad1983_init_verbs; | 1575 | spec->init_verbs[0] = ad1983_init_verbs; |
| 1578 | spec->spdif_route = 0; | 1576 | spec->spdif_route = 0; |
| 1579 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1577 | #ifdef CONFIG_PM |
| 1580 | spec->loopback.amplist = ad1983_loopbacks; | 1578 | spec->loopback.amplist = ad1983_loopbacks; |
| 1581 | #endif | 1579 | #endif |
| 1582 | spec->vmaster_nid = 0x05; | 1580 | spec->vmaster_nid = 0x05; |
| @@ -1704,7 +1702,7 @@ static const struct hda_verb ad1981_init_verbs[] = { | |||
| 1704 | { } /* end */ | 1702 | { } /* end */ |
| 1705 | }; | 1703 | }; |
| 1706 | 1704 | ||
| 1707 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1705 | #ifdef CONFIG_PM |
| 1708 | static const struct hda_amp_list ad1981_loopbacks[] = { | 1706 | static const struct hda_amp_list ad1981_loopbacks[] = { |
| 1709 | { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */ | 1707 | { 0x12, HDA_OUTPUT, 0 }, /* Front Mic */ |
| 1710 | { 0x13, HDA_OUTPUT, 0 }, /* Line */ | 1708 | { 0x13, HDA_OUTPUT, 0 }, /* Line */ |
| @@ -1812,7 +1810,7 @@ static const struct hda_input_mux ad1981_hp_capture_source = { | |||
| 1812 | .num_items = 3, | 1810 | .num_items = 3, |
| 1813 | .items = { | 1811 | .items = { |
| 1814 | { "Mic", 0x0 }, | 1812 | { "Mic", 0x0 }, |
| 1815 | { "Docking-Station", 0x1 }, | 1813 | { "Dock Mic", 0x1 }, |
| 1816 | { "Mix", 0x2 }, | 1814 | { "Mix", 0x2 }, |
| 1817 | }, | 1815 | }, |
| 1818 | }; | 1816 | }; |
| @@ -1836,8 +1834,8 @@ static const struct snd_kcontrol_new ad1981_hp_mixers[] = { | |||
| 1836 | */ | 1834 | */ |
| 1837 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), | 1835 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x12, 0x0, HDA_OUTPUT), |
| 1838 | HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), | 1836 | HDA_CODEC_MUTE("Mic Playback Switch", 0x12, 0x0, HDA_OUTPUT), |
| 1839 | HDA_CODEC_VOLUME("Docking-Station Playback Volume", 0x13, 0x0, HDA_OUTPUT), | 1837 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT), |
| 1840 | HDA_CODEC_MUTE("Docking-Station Playback Switch", 0x13, 0x0, HDA_OUTPUT), | 1838 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT), |
| 1841 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), | 1839 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x1c, 0x0, HDA_OUTPUT), |
| 1842 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), | 1840 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x1c, 0x0, HDA_OUTPUT), |
| 1843 | /* FIXME: does this laptop have analog CD connection? */ | 1841 | /* FIXME: does this laptop have analog CD connection? */ |
| @@ -1982,7 +1980,7 @@ static int patch_ad1981(struct hda_codec *codec) | |||
| 1982 | spec->num_init_verbs = 1; | 1980 | spec->num_init_verbs = 1; |
| 1983 | spec->init_verbs[0] = ad1981_init_verbs; | 1981 | spec->init_verbs[0] = ad1981_init_verbs; |
| 1984 | spec->spdif_route = 0; | 1982 | spec->spdif_route = 0; |
| 1985 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1983 | #ifdef CONFIG_PM |
| 1986 | spec->loopback.amplist = ad1981_loopbacks; | 1984 | spec->loopback.amplist = ad1981_loopbacks; |
| 1987 | #endif | 1985 | #endif |
| 1988 | spec->vmaster_nid = 0x05; | 1986 | spec->vmaster_nid = 0x05; |
| @@ -2807,7 +2805,7 @@ static void ad1988_laptop_unsol_event(struct hda_codec *codec, unsigned int res) | |||
| 2807 | snd_hda_sequence_write(codec, ad1988_laptop_hp_off); | 2805 | snd_hda_sequence_write(codec, ad1988_laptop_hp_off); |
| 2808 | } | 2806 | } |
| 2809 | 2807 | ||
| 2810 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2808 | #ifdef CONFIG_PM |
| 2811 | static const struct hda_amp_list ad1988_loopbacks[] = { | 2809 | static const struct hda_amp_list ad1988_loopbacks[] = { |
| 2812 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ | 2810 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ |
| 2813 | { 0x20, HDA_INPUT, 1 }, /* Line */ | 2811 | { 0x20, HDA_INPUT, 1 }, /* Line */ |
| @@ -3399,7 +3397,7 @@ static int patch_ad1988(struct hda_codec *codec) | |||
| 3399 | codec->patch_ops.unsol_event = ad1988_laptop_unsol_event; | 3397 | codec->patch_ops.unsol_event = ad1988_laptop_unsol_event; |
| 3400 | break; | 3398 | break; |
| 3401 | } | 3399 | } |
| 3402 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3400 | #ifdef CONFIG_PM |
| 3403 | spec->loopback.amplist = ad1988_loopbacks; | 3401 | spec->loopback.amplist = ad1988_loopbacks; |
| 3404 | #endif | 3402 | #endif |
| 3405 | spec->vmaster_nid = 0x04; | 3403 | spec->vmaster_nid = 0x04; |
| @@ -3555,7 +3553,7 @@ static const struct hda_verb ad1884_init_verbs[] = { | |||
| 3555 | { } /* end */ | 3553 | { } /* end */ |
| 3556 | }; | 3554 | }; |
| 3557 | 3555 | ||
| 3558 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3556 | #ifdef CONFIG_PM |
| 3559 | static const struct hda_amp_list ad1884_loopbacks[] = { | 3557 | static const struct hda_amp_list ad1884_loopbacks[] = { |
| 3560 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ | 3558 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ |
| 3561 | { 0x20, HDA_INPUT, 1 }, /* Mic */ | 3559 | { 0x20, HDA_INPUT, 1 }, /* Mic */ |
| @@ -3567,7 +3565,7 @@ static const struct hda_amp_list ad1884_loopbacks[] = { | |||
| 3567 | 3565 | ||
| 3568 | static const char * const ad1884_slave_vols[] = { | 3566 | static const char * const ad1884_slave_vols[] = { |
| 3569 | "PCM", "Mic", "Mono", "Front Mic", "Mic", "CD", | 3567 | "PCM", "Mic", "Mono", "Front Mic", "Mic", "CD", |
| 3570 | "Internal Mic", "Docking Mic", /* "Beep", */ "IEC958", | 3568 | "Internal Mic", "Dock Mic", /* "Beep", */ "IEC958", |
| 3571 | NULL | 3569 | NULL |
| 3572 | }; | 3570 | }; |
| 3573 | 3571 | ||
| @@ -3602,7 +3600,7 @@ static int patch_ad1884(struct hda_codec *codec) | |||
| 3602 | spec->num_init_verbs = 1; | 3600 | spec->num_init_verbs = 1; |
| 3603 | spec->init_verbs[0] = ad1884_init_verbs; | 3601 | spec->init_verbs[0] = ad1884_init_verbs; |
| 3604 | spec->spdif_route = 0; | 3602 | spec->spdif_route = 0; |
| 3605 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3603 | #ifdef CONFIG_PM |
| 3606 | spec->loopback.amplist = ad1884_loopbacks; | 3604 | spec->loopback.amplist = ad1884_loopbacks; |
| 3607 | #endif | 3605 | #endif |
| 3608 | spec->vmaster_nid = 0x04; | 3606 | spec->vmaster_nid = 0x04; |
| @@ -3628,7 +3626,7 @@ static const struct hda_input_mux ad1984_thinkpad_capture_source = { | |||
| 3628 | { "Mic", 0x0 }, | 3626 | { "Mic", 0x0 }, |
| 3629 | { "Internal Mic", 0x1 }, | 3627 | { "Internal Mic", 0x1 }, |
| 3630 | { "Mix", 0x3 }, | 3628 | { "Mix", 0x3 }, |
| 3631 | { "Docking-Station", 0x4 }, | 3629 | { "Dock Mic", 0x4 }, |
| 3632 | }, | 3630 | }, |
| 3633 | }; | 3631 | }; |
| 3634 | 3632 | ||
| @@ -3657,8 +3655,8 @@ static const struct snd_kcontrol_new ad1984_thinkpad_mixers[] = { | |||
| 3657 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), | 3655 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), |
| 3658 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), | 3656 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), |
| 3659 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | 3657 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), |
| 3660 | HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT), | 3658 | HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), |
| 3661 | HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT), | 3659 | HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), |
| 3662 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), | 3660 | HDA_CODEC_VOLUME("Mic Boost Volume", 0x14, 0x0, HDA_INPUT), |
| 3663 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT), | 3661 | HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x15, 0x0, HDA_INPUT), |
| 3664 | HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), | 3662 | HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x25, 0x0, HDA_OUTPUT), |
| @@ -3994,7 +3992,7 @@ static const struct hda_verb ad1884a_init_verbs[] = { | |||
| 3994 | { } /* end */ | 3992 | { } /* end */ |
| 3995 | }; | 3993 | }; |
| 3996 | 3994 | ||
| 3997 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3995 | #ifdef CONFIG_PM |
| 3998 | static const struct hda_amp_list ad1884a_loopbacks[] = { | 3996 | static const struct hda_amp_list ad1884a_loopbacks[] = { |
| 3999 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ | 3997 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ |
| 4000 | { 0x20, HDA_INPUT, 1 }, /* Mic */ | 3998 | { 0x20, HDA_INPUT, 1 }, /* Mic */ |
| @@ -4602,7 +4600,7 @@ static int patch_ad1884a(struct hda_codec *codec) | |||
| 4602 | spec->num_init_verbs = 1; | 4600 | spec->num_init_verbs = 1; |
| 4603 | spec->init_verbs[0] = ad1884a_init_verbs; | 4601 | spec->init_verbs[0] = ad1884a_init_verbs; |
| 4604 | spec->spdif_route = 0; | 4602 | spec->spdif_route = 0; |
| 4605 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 4603 | #ifdef CONFIG_PM |
| 4606 | spec->loopback.amplist = ad1884a_loopbacks; | 4604 | spec->loopback.amplist = ad1884a_loopbacks; |
| 4607 | #endif | 4605 | #endif |
| 4608 | codec->patch_ops = ad198x_patch_ops; | 4606 | codec->patch_ops = ad198x_patch_ops; |
| @@ -4814,6 +4812,32 @@ static const struct snd_kcontrol_new ad1882_3stack_mixers[] = { | |||
| 4814 | { } /* end */ | 4812 | { } /* end */ |
| 4815 | }; | 4813 | }; |
| 4816 | 4814 | ||
| 4815 | /* simple auto-mute control for AD1882 3-stack board */ | ||
| 4816 | #define AD1882_HP_EVENT 0x01 | ||
| 4817 | |||
| 4818 | static void ad1882_3stack_automute(struct hda_codec *codec) | ||
| 4819 | { | ||
| 4820 | bool mute = snd_hda_jack_detect(codec, 0x11); | ||
| 4821 | snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
| 4822 | mute ? 0 : PIN_OUT); | ||
| 4823 | } | ||
| 4824 | |||
| 4825 | static int ad1882_3stack_automute_init(struct hda_codec *codec) | ||
| 4826 | { | ||
| 4827 | ad198x_init(codec); | ||
| 4828 | ad1882_3stack_automute(codec); | ||
| 4829 | return 0; | ||
| 4830 | } | ||
| 4831 | |||
| 4832 | static void ad1882_3stack_unsol_event(struct hda_codec *codec, unsigned int res) | ||
| 4833 | { | ||
| 4834 | switch (res >> 26) { | ||
| 4835 | case AD1882_HP_EVENT: | ||
| 4836 | ad1882_3stack_automute(codec); | ||
| 4837 | break; | ||
| 4838 | } | ||
| 4839 | } | ||
| 4840 | |||
| 4817 | static const struct snd_kcontrol_new ad1882_6stack_mixers[] = { | 4841 | static const struct snd_kcontrol_new ad1882_6stack_mixers[] = { |
| 4818 | HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT), | 4842 | HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT), |
| 4819 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT), | 4843 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT), |
| @@ -4928,7 +4952,12 @@ static const struct hda_verb ad1882_init_verbs[] = { | |||
| 4928 | { } /* end */ | 4952 | { } /* end */ |
| 4929 | }; | 4953 | }; |
| 4930 | 4954 | ||
| 4931 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 4955 | static const struct hda_verb ad1882_3stack_automute_verbs[] = { |
| 4956 | {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1882_HP_EVENT}, | ||
| 4957 | { } /* end */ | ||
| 4958 | }; | ||
| 4959 | |||
| 4960 | #ifdef CONFIG_PM | ||
| 4932 | static const struct hda_amp_list ad1882_loopbacks[] = { | 4961 | static const struct hda_amp_list ad1882_loopbacks[] = { |
| 4933 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ | 4962 | { 0x20, HDA_INPUT, 0 }, /* Front Mic */ |
| 4934 | { 0x20, HDA_INPUT, 1 }, /* Mic */ | 4963 | { 0x20, HDA_INPUT, 1 }, /* Mic */ |
| @@ -4942,12 +4971,14 @@ static const struct hda_amp_list ad1882_loopbacks[] = { | |||
| 4942 | enum { | 4971 | enum { |
| 4943 | AD1882_3STACK, | 4972 | AD1882_3STACK, |
| 4944 | AD1882_6STACK, | 4973 | AD1882_6STACK, |
| 4974 | AD1882_3STACK_AUTOMUTE, | ||
| 4945 | AD1882_MODELS | 4975 | AD1882_MODELS |
| 4946 | }; | 4976 | }; |
| 4947 | 4977 | ||
| 4948 | static const char * const ad1882_models[AD1986A_MODELS] = { | 4978 | static const char * const ad1882_models[AD1986A_MODELS] = { |
| 4949 | [AD1882_3STACK] = "3stack", | 4979 | [AD1882_3STACK] = "3stack", |
| 4950 | [AD1882_6STACK] = "6stack", | 4980 | [AD1882_6STACK] = "6stack", |
| 4981 | [AD1882_3STACK_AUTOMUTE] = "3stack-automute", | ||
| 4951 | }; | 4982 | }; |
| 4952 | 4983 | ||
| 4953 | 4984 | ||
| @@ -4989,7 +5020,7 @@ static int patch_ad1882(struct hda_codec *codec) | |||
| 4989 | spec->num_init_verbs = 1; | 5020 | spec->num_init_verbs = 1; |
| 4990 | spec->init_verbs[0] = ad1882_init_verbs; | 5021 | spec->init_verbs[0] = ad1882_init_verbs; |
| 4991 | spec->spdif_route = 0; | 5022 | spec->spdif_route = 0; |
| 4992 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5023 | #ifdef CONFIG_PM |
| 4993 | spec->loopback.amplist = ad1882_loopbacks; | 5024 | spec->loopback.amplist = ad1882_loopbacks; |
| 4994 | #endif | 5025 | #endif |
| 4995 | spec->vmaster_nid = 0x04; | 5026 | spec->vmaster_nid = 0x04; |
| @@ -5002,6 +5033,7 @@ static int patch_ad1882(struct hda_codec *codec) | |||
| 5002 | switch (board_config) { | 5033 | switch (board_config) { |
| 5003 | default: | 5034 | default: |
| 5004 | case AD1882_3STACK: | 5035 | case AD1882_3STACK: |
| 5036 | case AD1882_3STACK_AUTOMUTE: | ||
| 5005 | spec->num_mixers = 3; | 5037 | spec->num_mixers = 3; |
| 5006 | spec->mixers[2] = ad1882_3stack_mixers; | 5038 | spec->mixers[2] = ad1882_3stack_mixers; |
| 5007 | spec->channel_mode = ad1882_modes; | 5039 | spec->channel_mode = ad1882_modes; |
| @@ -5009,6 +5041,12 @@ static int patch_ad1882(struct hda_codec *codec) | |||
| 5009 | spec->need_dac_fix = 1; | 5041 | spec->need_dac_fix = 1; |
| 5010 | spec->multiout.max_channels = 2; | 5042 | spec->multiout.max_channels = 2; |
| 5011 | spec->multiout.num_dacs = 1; | 5043 | spec->multiout.num_dacs = 1; |
| 5044 | if (board_config != AD1882_3STACK) { | ||
| 5045 | spec->init_verbs[spec->num_init_verbs++] = | ||
| 5046 | ad1882_3stack_automute_verbs; | ||
| 5047 | codec->patch_ops.unsol_event = ad1882_3stack_unsol_event; | ||
| 5048 | codec->patch_ops.init = ad1882_3stack_automute_init; | ||
| 5049 | } | ||
| 5012 | break; | 5050 | break; |
| 5013 | case AD1882_6STACK: | 5051 | case AD1882_6STACK: |
| 5014 | spec->num_mixers = 3; | 5052 | spec->num_mixers = 3; |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 0c4c1a61b378..fcfc9f0a056b 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
| @@ -34,7 +34,8 @@ | |||
| 34 | */ | 34 | */ |
| 35 | 35 | ||
| 36 | struct cs_spec { | 36 | struct cs_spec { |
| 37 | int board_config; | 37 | struct hda_gen_spec gen; |
| 38 | |||
| 38 | struct auto_pin_cfg autocfg; | 39 | struct auto_pin_cfg autocfg; |
| 39 | struct hda_multi_out multiout; | 40 | struct hda_multi_out multiout; |
| 40 | struct snd_kcontrol *vmaster_sw; | 41 | struct snd_kcontrol *vmaster_sw; |
| @@ -80,16 +81,20 @@ enum { | |||
| 80 | CS420X_MBP53, | 81 | CS420X_MBP53, |
| 81 | CS420X_MBP55, | 82 | CS420X_MBP55, |
| 82 | CS420X_IMAC27, | 83 | CS420X_IMAC27, |
| 83 | CS420X_IMAC27_122, | 84 | CS420X_GPIO_13, |
| 84 | CS420X_APPLE, | 85 | CS420X_GPIO_23, |
| 86 | CS420X_MBP101, | ||
| 87 | CS420X_MBP101_COEF, | ||
| 85 | CS420X_AUTO, | 88 | CS420X_AUTO, |
| 86 | CS420X_MODELS | 89 | /* aliases */ |
| 90 | CS420X_IMAC27_122 = CS420X_GPIO_23, | ||
| 91 | CS420X_APPLE = CS420X_GPIO_13, | ||
| 87 | }; | 92 | }; |
| 88 | 93 | ||
| 89 | /* CS421x boards */ | 94 | /* CS421x boards */ |
| 90 | enum { | 95 | enum { |
| 91 | CS421X_CDB4210, | 96 | CS421X_CDB4210, |
| 92 | CS421X_MODELS | 97 | CS421X_SENSE_B, |
| 93 | }; | 98 | }; |
| 94 | 99 | ||
| 95 | /* Vendor-specific processing widget */ | 100 | /* Vendor-specific processing widget */ |
| @@ -1157,6 +1162,14 @@ static const struct hda_verb cs_errata_init_verbs[] = { | |||
| 1157 | {} /* terminator */ | 1162 | {} /* terminator */ |
| 1158 | }; | 1163 | }; |
| 1159 | 1164 | ||
| 1165 | static const struct hda_verb mbp101_init_verbs[] = { | ||
| 1166 | {0x11, AC_VERB_SET_COEF_INDEX, 0x0002}, | ||
| 1167 | {0x11, AC_VERB_SET_PROC_COEF, 0x100a}, | ||
| 1168 | {0x11, AC_VERB_SET_COEF_INDEX, 0x0004}, | ||
| 1169 | {0x11, AC_VERB_SET_PROC_COEF, 0x000f}, | ||
| 1170 | {} | ||
| 1171 | }; | ||
| 1172 | |||
| 1160 | /* SPDIF setup */ | 1173 | /* SPDIF setup */ |
| 1161 | static void init_digital(struct hda_codec *codec) | 1174 | static void init_digital(struct hda_codec *codec) |
| 1162 | { | 1175 | { |
| @@ -1193,7 +1206,6 @@ static int cs_init(struct hda_codec *codec) | |||
| 1193 | init_output(codec); | 1206 | init_output(codec); |
| 1194 | init_input(codec); | 1207 | init_input(codec); |
| 1195 | init_digital(codec); | 1208 | init_digital(codec); |
| 1196 | snd_hda_jack_report_sync(codec); | ||
| 1197 | 1209 | ||
| 1198 | return 0; | 1210 | return 0; |
| 1199 | } | 1211 | } |
| @@ -1279,38 +1291,32 @@ static int cs_parse_auto_config(struct hda_codec *codec) | |||
| 1279 | return 0; | 1291 | return 0; |
| 1280 | } | 1292 | } |
| 1281 | 1293 | ||
| 1282 | static const char * const cs420x_models[CS420X_MODELS] = { | 1294 | static const struct hda_model_fixup cs420x_models[] = { |
| 1283 | [CS420X_MBP53] = "mbp53", | 1295 | { .id = CS420X_MBP53, .name = "mbp53" }, |
| 1284 | [CS420X_MBP55] = "mbp55", | 1296 | { .id = CS420X_MBP55, .name = "mbp55" }, |
| 1285 | [CS420X_IMAC27] = "imac27", | 1297 | { .id = CS420X_IMAC27, .name = "imac27" }, |
| 1286 | [CS420X_IMAC27_122] = "imac27_122", | 1298 | { .id = CS420X_IMAC27_122, .name = "imac27_122" }, |
| 1287 | [CS420X_APPLE] = "apple", | 1299 | { .id = CS420X_APPLE, .name = "apple" }, |
| 1288 | [CS420X_AUTO] = "auto", | 1300 | { .id = CS420X_MBP101, .name = "mbp101" }, |
| 1301 | {} | ||
| 1289 | }; | 1302 | }; |
| 1290 | 1303 | ||
| 1291 | 1304 | static const struct snd_pci_quirk cs420x_fixup_tbl[] = { | |
| 1292 | static const struct snd_pci_quirk cs420x_cfg_tbl[] = { | ||
| 1293 | SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53), | 1305 | SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53), |
| 1294 | SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55), | 1306 | SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55), |
| 1295 | SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), | 1307 | SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), |
| 1296 | SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55), | 1308 | SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55), |
| 1297 | /* this conflicts with too many other models */ | 1309 | /* this conflicts with too many other models */ |
| 1298 | /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/ | 1310 | /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/ |
| 1299 | {} /* terminator */ | ||
| 1300 | }; | ||
| 1301 | 1311 | ||
| 1302 | static const struct snd_pci_quirk cs420x_codec_cfg_tbl[] = { | 1312 | /* codec SSID */ |
| 1303 | SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122), | 1313 | SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122), |
| 1314 | SND_PCI_QUIRK(0x106b, 0x2800, "MacBookPro 10,1", CS420X_MBP101), | ||
| 1304 | SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE), | 1315 | SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE), |
| 1305 | {} /* terminator */ | 1316 | {} /* terminator */ |
| 1306 | }; | 1317 | }; |
| 1307 | 1318 | ||
| 1308 | struct cs_pincfg { | 1319 | static const struct hda_pintbl mbp53_pincfgs[] = { |
| 1309 | hda_nid_t nid; | ||
| 1310 | u32 val; | ||
| 1311 | }; | ||
| 1312 | |||
| 1313 | static const struct cs_pincfg mbp53_pincfgs[] = { | ||
| 1314 | { 0x09, 0x012b4050 }, | 1320 | { 0x09, 0x012b4050 }, |
| 1315 | { 0x0a, 0x90100141 }, | 1321 | { 0x0a, 0x90100141 }, |
| 1316 | { 0x0b, 0x90100140 }, | 1322 | { 0x0b, 0x90100140 }, |
| @@ -1324,7 +1330,7 @@ static const struct cs_pincfg mbp53_pincfgs[] = { | |||
| 1324 | {} /* terminator */ | 1330 | {} /* terminator */ |
| 1325 | }; | 1331 | }; |
| 1326 | 1332 | ||
| 1327 | static const struct cs_pincfg mbp55_pincfgs[] = { | 1333 | static const struct hda_pintbl mbp55_pincfgs[] = { |
| 1328 | { 0x09, 0x012b4030 }, | 1334 | { 0x09, 0x012b4030 }, |
| 1329 | { 0x0a, 0x90100121 }, | 1335 | { 0x0a, 0x90100121 }, |
| 1330 | { 0x0b, 0x90100120 }, | 1336 | { 0x0b, 0x90100120 }, |
| @@ -1338,7 +1344,7 @@ static const struct cs_pincfg mbp55_pincfgs[] = { | |||
| 1338 | {} /* terminator */ | 1344 | {} /* terminator */ |
| 1339 | }; | 1345 | }; |
| 1340 | 1346 | ||
| 1341 | static const struct cs_pincfg imac27_pincfgs[] = { | 1347 | static const struct hda_pintbl imac27_pincfgs[] = { |
| 1342 | { 0x09, 0x012b4050 }, | 1348 | { 0x09, 0x012b4050 }, |
| 1343 | { 0x0a, 0x90100140 }, | 1349 | { 0x0a, 0x90100140 }, |
| 1344 | { 0x0b, 0x90100142 }, | 1350 | { 0x0b, 0x90100142 }, |
| @@ -1352,22 +1358,78 @@ static const struct cs_pincfg imac27_pincfgs[] = { | |||
| 1352 | {} /* terminator */ | 1358 | {} /* terminator */ |
| 1353 | }; | 1359 | }; |
| 1354 | 1360 | ||
| 1355 | static const struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { | 1361 | static const struct hda_pintbl mbp101_pincfgs[] = { |
| 1356 | [CS420X_MBP53] = mbp53_pincfgs, | 1362 | { 0x0d, 0x40ab90f0 }, |
| 1357 | [CS420X_MBP55] = mbp55_pincfgs, | 1363 | { 0x0e, 0x90a600f0 }, |
| 1358 | [CS420X_IMAC27] = imac27_pincfgs, | 1364 | { 0x12, 0x50a600f0 }, |
| 1365 | {} /* terminator */ | ||
| 1359 | }; | 1366 | }; |
| 1360 | 1367 | ||
| 1361 | static void fix_pincfg(struct hda_codec *codec, int model, | 1368 | static void cs420x_fixup_gpio_13(struct hda_codec *codec, |
| 1362 | const struct cs_pincfg **pin_configs) | 1369 | const struct hda_fixup *fix, int action) |
| 1363 | { | 1370 | { |
| 1364 | const struct cs_pincfg *cfg = pin_configs[model]; | 1371 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { |
| 1365 | if (!cfg) | 1372 | struct cs_spec *spec = codec->spec; |
| 1366 | return; | 1373 | spec->gpio_eapd_hp = 2; /* GPIO1 = headphones */ |
| 1367 | for (; cfg->nid; cfg++) | 1374 | spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */ |
| 1368 | snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val); | 1375 | spec->gpio_mask = spec->gpio_dir = |
| 1376 | spec->gpio_eapd_hp | spec->gpio_eapd_speaker; | ||
| 1377 | } | ||
| 1369 | } | 1378 | } |
| 1370 | 1379 | ||
| 1380 | static void cs420x_fixup_gpio_23(struct hda_codec *codec, | ||
| 1381 | const struct hda_fixup *fix, int action) | ||
| 1382 | { | ||
| 1383 | if (action == HDA_FIXUP_ACT_PRE_PROBE) { | ||
| 1384 | struct cs_spec *spec = codec->spec; | ||
| 1385 | spec->gpio_eapd_hp = 4; /* GPIO2 = headphones */ | ||
| 1386 | spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */ | ||
| 1387 | spec->gpio_mask = spec->gpio_dir = | ||
| 1388 | spec->gpio_eapd_hp | spec->gpio_eapd_speaker; | ||
| 1389 | } | ||
| 1390 | } | ||
| 1391 | |||
| 1392 | static const struct hda_fixup cs420x_fixups[] = { | ||
| 1393 | [CS420X_MBP53] = { | ||
| 1394 | .type = HDA_FIXUP_PINS, | ||
| 1395 | .v.pins = mbp53_pincfgs, | ||
| 1396 | .chained = true, | ||
| 1397 | .chain_id = CS420X_APPLE, | ||
| 1398 | }, | ||
| 1399 | [CS420X_MBP55] = { | ||
| 1400 | .type = HDA_FIXUP_PINS, | ||
| 1401 | .v.pins = mbp55_pincfgs, | ||
| 1402 | .chained = true, | ||
| 1403 | .chain_id = CS420X_GPIO_13, | ||
| 1404 | }, | ||
| 1405 | [CS420X_IMAC27] = { | ||
| 1406 | .type = HDA_FIXUP_PINS, | ||
| 1407 | .v.pins = imac27_pincfgs, | ||
| 1408 | .chained = true, | ||
| 1409 | .chain_id = CS420X_GPIO_13, | ||
| 1410 | }, | ||
| 1411 | [CS420X_GPIO_13] = { | ||
| 1412 | .type = HDA_FIXUP_FUNC, | ||
| 1413 | .v.func = cs420x_fixup_gpio_13, | ||
| 1414 | }, | ||
| 1415 | [CS420X_GPIO_23] = { | ||
| 1416 | .type = HDA_FIXUP_FUNC, | ||
| 1417 | .v.func = cs420x_fixup_gpio_23, | ||
| 1418 | }, | ||
| 1419 | [CS420X_MBP101] = { | ||
| 1420 | .type = HDA_FIXUP_PINS, | ||
| 1421 | .v.pins = mbp101_pincfgs, | ||
| 1422 | .chained = true, | ||
| 1423 | .chain_id = CS420X_MBP101_COEF, | ||
| 1424 | }, | ||
| 1425 | [CS420X_MBP101_COEF] = { | ||
| 1426 | .type = HDA_FIXUP_VERBS, | ||
| 1427 | .v.verbs = mbp101_init_verbs, | ||
| 1428 | .chained = true, | ||
| 1429 | .chain_id = CS420X_GPIO_13, | ||
| 1430 | }, | ||
| 1431 | }; | ||
| 1432 | |||
| 1371 | static int patch_cs420x(struct hda_codec *codec) | 1433 | static int patch_cs420x(struct hda_codec *codec) |
| 1372 | { | 1434 | { |
| 1373 | struct cs_spec *spec; | 1435 | struct cs_spec *spec; |
| @@ -1380,33 +1442,9 @@ static int patch_cs420x(struct hda_codec *codec) | |||
| 1380 | 1442 | ||
| 1381 | spec->vendor_nid = CS420X_VENDOR_NID; | 1443 | spec->vendor_nid = CS420X_VENDOR_NID; |
| 1382 | 1444 | ||
| 1383 | spec->board_config = | 1445 | snd_hda_pick_fixup(codec, cs420x_models, cs420x_fixup_tbl, |
| 1384 | snd_hda_check_board_config(codec, CS420X_MODELS, | 1446 | cs420x_fixups); |
| 1385 | cs420x_models, cs420x_cfg_tbl); | 1447 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
| 1386 | if (spec->board_config < 0) | ||
| 1387 | spec->board_config = | ||
| 1388 | snd_hda_check_board_codec_sid_config(codec, | ||
| 1389 | CS420X_MODELS, NULL, cs420x_codec_cfg_tbl); | ||
| 1390 | if (spec->board_config >= 0) | ||
| 1391 | fix_pincfg(codec, spec->board_config, cs_pincfgs); | ||
| 1392 | |||
| 1393 | switch (spec->board_config) { | ||
| 1394 | case CS420X_IMAC27: | ||
| 1395 | case CS420X_MBP53: | ||
| 1396 | case CS420X_MBP55: | ||
| 1397 | case CS420X_APPLE: | ||
| 1398 | spec->gpio_eapd_hp = 2; /* GPIO1 = headphones */ | ||
| 1399 | spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */ | ||
| 1400 | spec->gpio_mask = spec->gpio_dir = | ||
| 1401 | spec->gpio_eapd_hp | spec->gpio_eapd_speaker; | ||
| 1402 | break; | ||
| 1403 | case CS420X_IMAC27_122: | ||
| 1404 | spec->gpio_eapd_hp = 4; /* GPIO2 = headphones */ | ||
| 1405 | spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */ | ||
| 1406 | spec->gpio_mask = spec->gpio_dir = | ||
| 1407 | spec->gpio_eapd_hp | spec->gpio_eapd_speaker; | ||
| 1408 | break; | ||
| 1409 | } | ||
| 1410 | 1448 | ||
| 1411 | err = cs_parse_auto_config(codec); | 1449 | err = cs_parse_auto_config(codec); |
| 1412 | if (err < 0) | 1450 | if (err < 0) |
| @@ -1414,6 +1452,8 @@ static int patch_cs420x(struct hda_codec *codec) | |||
| 1414 | 1452 | ||
| 1415 | codec->patch_ops = cs_patch_ops; | 1453 | codec->patch_ops = cs_patch_ops; |
| 1416 | 1454 | ||
| 1455 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | ||
| 1456 | |||
| 1417 | return 0; | 1457 | return 0; |
| 1418 | 1458 | ||
| 1419 | error: | 1459 | error: |
| @@ -1431,11 +1471,12 @@ static int patch_cs420x(struct hda_codec *codec) | |||
| 1431 | */ | 1471 | */ |
| 1432 | 1472 | ||
| 1433 | /* CS4210 board names */ | 1473 | /* CS4210 board names */ |
| 1434 | static const char *cs421x_models[CS421X_MODELS] = { | 1474 | static const struct hda_model_fixup cs421x_models[] = { |
| 1435 | [CS421X_CDB4210] = "cdb4210", | 1475 | { .id = CS421X_CDB4210, .name = "cdb4210" }, |
| 1476 | {} | ||
| 1436 | }; | 1477 | }; |
| 1437 | 1478 | ||
| 1438 | static const struct snd_pci_quirk cs421x_cfg_tbl[] = { | 1479 | static const struct snd_pci_quirk cs421x_fixup_tbl[] = { |
| 1439 | /* Test Intel board + CDB2410 */ | 1480 | /* Test Intel board + CDB2410 */ |
| 1440 | SND_PCI_QUIRK(0x8086, 0x5001, "DP45SG/CDB4210", CS421X_CDB4210), | 1481 | SND_PCI_QUIRK(0x8086, 0x5001, "DP45SG/CDB4210", CS421X_CDB4210), |
| 1441 | {} /* terminator */ | 1482 | {} /* terminator */ |
| @@ -1443,7 +1484,7 @@ static const struct snd_pci_quirk cs421x_cfg_tbl[] = { | |||
| 1443 | 1484 | ||
| 1444 | /* CS4210 board pinconfigs */ | 1485 | /* CS4210 board pinconfigs */ |
| 1445 | /* Default CS4210 (CDB4210)*/ | 1486 | /* Default CS4210 (CDB4210)*/ |
| 1446 | static const struct cs_pincfg cdb4210_pincfgs[] = { | 1487 | static const struct hda_pintbl cdb4210_pincfgs[] = { |
| 1447 | { 0x05, 0x0321401f }, | 1488 | { 0x05, 0x0321401f }, |
| 1448 | { 0x06, 0x90170010 }, | 1489 | { 0x06, 0x90170010 }, |
| 1449 | { 0x07, 0x03813031 }, | 1490 | { 0x07, 0x03813031 }, |
| @@ -1453,8 +1494,26 @@ static const struct cs_pincfg cdb4210_pincfgs[] = { | |||
| 1453 | {} /* terminator */ | 1494 | {} /* terminator */ |
| 1454 | }; | 1495 | }; |
| 1455 | 1496 | ||
| 1456 | static const struct cs_pincfg *cs421x_pincfgs[CS421X_MODELS] = { | 1497 | /* Setup GPIO/SENSE for each board (if used) */ |
| 1457 | [CS421X_CDB4210] = cdb4210_pincfgs, | 1498 | static void cs421x_fixup_sense_b(struct hda_codec *codec, |
| 1499 | const struct hda_fixup *fix, int action) | ||
| 1500 | { | ||
| 1501 | struct cs_spec *spec = codec->spec; | ||
| 1502 | if (action == HDA_FIXUP_ACT_PRE_PROBE) | ||
| 1503 | spec->sense_b = 1; | ||
| 1504 | } | ||
| 1505 | |||
| 1506 | static const struct hda_fixup cs421x_fixups[] = { | ||
| 1507 | [CS421X_CDB4210] = { | ||
| 1508 | .type = HDA_FIXUP_PINS, | ||
| 1509 | .v.pins = cdb4210_pincfgs, | ||
| 1510 | .chained = true, | ||
| 1511 | .chain_id = CS421X_SENSE_B, | ||
| 1512 | }, | ||
| 1513 | [CS421X_SENSE_B] = { | ||
| 1514 | .type = HDA_FIXUP_FUNC, | ||
| 1515 | .v.func = cs421x_fixup_sense_b, | ||
| 1516 | } | ||
| 1458 | }; | 1517 | }; |
| 1459 | 1518 | ||
| 1460 | static const struct hda_verb cs421x_coef_init_verbs[] = { | 1519 | static const struct hda_verb cs421x_coef_init_verbs[] = { |
| @@ -1643,7 +1702,6 @@ static int cs421x_init(struct hda_codec *codec) | |||
| 1643 | init_output(codec); | 1702 | init_output(codec); |
| 1644 | init_input(codec); | 1703 | init_input(codec); |
| 1645 | init_cs421x_digital(codec); | 1704 | init_cs421x_digital(codec); |
| 1646 | snd_hda_jack_report_sync(codec); | ||
| 1647 | 1705 | ||
| 1648 | return 0; | 1706 | return 0; |
| 1649 | } | 1707 | } |
| @@ -1937,26 +1995,9 @@ static int patch_cs4210(struct hda_codec *codec) | |||
| 1937 | 1995 | ||
| 1938 | spec->vendor_nid = CS4210_VENDOR_NID; | 1996 | spec->vendor_nid = CS4210_VENDOR_NID; |
| 1939 | 1997 | ||
| 1940 | spec->board_config = | 1998 | snd_hda_pick_fixup(codec, cs421x_models, cs421x_fixup_tbl, |
| 1941 | snd_hda_check_board_config(codec, CS421X_MODELS, | 1999 | cs421x_fixups); |
| 1942 | cs421x_models, cs421x_cfg_tbl); | 2000 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); |
| 1943 | if (spec->board_config >= 0) | ||
| 1944 | fix_pincfg(codec, spec->board_config, cs421x_pincfgs); | ||
| 1945 | /* | ||
| 1946 | Setup GPIO/SENSE for each board (if used) | ||
| 1947 | */ | ||
| 1948 | switch (spec->board_config) { | ||
| 1949 | case CS421X_CDB4210: | ||
| 1950 | snd_printd("CS4210 board: %s\n", | ||
| 1951 | cs421x_models[spec->board_config]); | ||
| 1952 | /* spec->gpio_mask = 3; | ||
| 1953 | spec->gpio_dir = 3; | ||
| 1954 | spec->gpio_data = 3; | ||
| 1955 | */ | ||
| 1956 | spec->sense_b = 1; | ||
| 1957 | |||
| 1958 | break; | ||
| 1959 | } | ||
| 1960 | 2001 | ||
| 1961 | /* | 2002 | /* |
| 1962 | Update the GPIO/DMIC/SENSE_B pinmux before the configuration | 2003 | Update the GPIO/DMIC/SENSE_B pinmux before the configuration |
| @@ -1971,6 +2012,8 @@ static int patch_cs4210(struct hda_codec *codec) | |||
| 1971 | 2012 | ||
| 1972 | codec->patch_ops = cs421x_patch_ops; | 2013 | codec->patch_ops = cs421x_patch_ops; |
| 1973 | 2014 | ||
| 2015 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE); | ||
| 2016 | |||
| 1974 | return 0; | 2017 | return 0; |
| 1975 | 2018 | ||
| 1976 | error: | 2019 | error: |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 5e22a8f43d2e..03b1dc317ff0 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
| @@ -553,7 +553,7 @@ static int conexant_build_controls(struct hda_codec *codec) | |||
| 553 | return 0; | 553 | return 0; |
| 554 | } | 554 | } |
| 555 | 555 | ||
| 556 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 556 | #ifdef CONFIG_PM |
| 557 | static int conexant_suspend(struct hda_codec *codec) | 557 | static int conexant_suspend(struct hda_codec *codec) |
| 558 | { | 558 | { |
| 559 | snd_hda_shutup_pins(codec); | 559 | snd_hda_shutup_pins(codec); |
| @@ -567,7 +567,7 @@ static const struct hda_codec_ops conexant_patch_ops = { | |||
| 567 | .init = conexant_init, | 567 | .init = conexant_init, |
| 568 | .free = conexant_free, | 568 | .free = conexant_free, |
| 569 | .set_power_state = conexant_set_power, | 569 | .set_power_state = conexant_set_power, |
| 570 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 570 | #ifdef CONFIG_PM |
| 571 | .suspend = conexant_suspend, | 571 | .suspend = conexant_suspend, |
| 572 | #endif | 572 | #endif |
| 573 | .reboot_notify = snd_hda_shutup_pins, | 573 | .reboot_notify = snd_hda_shutup_pins, |
| @@ -1710,8 +1710,8 @@ static const struct snd_kcontrol_new cxt5051_capture_mixers[] = { | |||
| 1710 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), | 1710 | HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT), |
| 1711 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), | 1711 | HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT), |
| 1712 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), | 1712 | HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT), |
| 1713 | HDA_CODEC_VOLUME("Docking Mic Volume", 0x15, 0x00, HDA_INPUT), | 1713 | HDA_CODEC_VOLUME("Dock Mic Volume", 0x15, 0x00, HDA_INPUT), |
| 1714 | HDA_CODEC_MUTE("Docking Mic Switch", 0x15, 0x00, HDA_INPUT), | 1714 | HDA_CODEC_MUTE("Dock Mic Switch", 0x15, 0x00, HDA_INPUT), |
| 1715 | {} | 1715 | {} |
| 1716 | }; | 1716 | }; |
| 1717 | 1717 | ||
| @@ -3402,7 +3402,7 @@ static void cx_auto_update_speakers(struct hda_codec *codec) | |||
| 3402 | do_automute(codec, cfg->line_outs, cfg->line_out_pins, on); | 3402 | do_automute(codec, cfg->line_outs, cfg->line_out_pins, on); |
| 3403 | } | 3403 | } |
| 3404 | 3404 | ||
| 3405 | static void cx_auto_hp_automute(struct hda_codec *codec) | 3405 | static void cx_auto_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) |
| 3406 | { | 3406 | { |
| 3407 | struct conexant_spec *spec = codec->spec; | 3407 | struct conexant_spec *spec = codec->spec; |
| 3408 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3408 | struct auto_pin_cfg *cfg = &spec->autocfg; |
| @@ -3413,7 +3413,7 @@ static void cx_auto_hp_automute(struct hda_codec *codec) | |||
| 3413 | cx_auto_update_speakers(codec); | 3413 | cx_auto_update_speakers(codec); |
| 3414 | } | 3414 | } |
| 3415 | 3415 | ||
| 3416 | static void cx_auto_line_automute(struct hda_codec *codec) | 3416 | static void cx_auto_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) |
| 3417 | { | 3417 | { |
| 3418 | struct conexant_spec *spec = codec->spec; | 3418 | struct conexant_spec *spec = codec->spec; |
| 3419 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3419 | struct auto_pin_cfg *cfg = &spec->autocfg; |
| @@ -3540,8 +3540,9 @@ static int __select_input_connection(struct hda_codec *codec, hda_nid_t mux, | |||
| 3540 | hda_nid_t pin, hda_nid_t *srcp, | 3540 | hda_nid_t pin, hda_nid_t *srcp, |
| 3541 | bool do_select, int depth) | 3541 | bool do_select, int depth) |
| 3542 | { | 3542 | { |
| 3543 | struct conexant_spec *spec = codec->spec; | ||
| 3543 | hda_nid_t conn[HDA_MAX_NUM_INPUTS]; | 3544 | hda_nid_t conn[HDA_MAX_NUM_INPUTS]; |
| 3544 | int i, nums; | 3545 | int startidx, i, nums; |
| 3545 | 3546 | ||
| 3546 | switch (get_wcaps_type(get_wcaps(codec, mux))) { | 3547 | switch (get_wcaps_type(get_wcaps(codec, mux))) { |
| 3547 | case AC_WID_AUD_IN: | 3548 | case AC_WID_AUD_IN: |
| @@ -3565,14 +3566,25 @@ static int __select_input_connection(struct hda_codec *codec, hda_nid_t mux, | |||
| 3565 | depth++; | 3566 | depth++; |
| 3566 | if (depth == 2) | 3567 | if (depth == 2) |
| 3567 | return -1; | 3568 | return -1; |
| 3569 | |||
| 3570 | /* Try to rotate around connections to avoid one boost controlling | ||
| 3571 | another input path as well */ | ||
| 3572 | startidx = 0; | ||
| 3573 | for (i = 0; i < spec->private_imux.num_items; i++) | ||
| 3574 | if (spec->imux_info[i].pin == pin) { | ||
| 3575 | startidx = i; | ||
| 3576 | break; | ||
| 3577 | } | ||
| 3578 | |||
| 3568 | for (i = 0; i < nums; i++) { | 3579 | for (i = 0; i < nums; i++) { |
| 3569 | int ret = __select_input_connection(codec, conn[i], pin, srcp, | 3580 | int j = (i + startidx) % nums; |
| 3581 | int ret = __select_input_connection(codec, conn[j], pin, srcp, | ||
| 3570 | do_select, depth); | 3582 | do_select, depth); |
| 3571 | if (ret >= 0) { | 3583 | if (ret >= 0) { |
| 3572 | if (do_select) | 3584 | if (do_select) |
| 3573 | snd_hda_codec_write(codec, mux, 0, | 3585 | snd_hda_codec_write(codec, mux, 0, |
| 3574 | AC_VERB_SET_CONNECT_SEL, i); | 3586 | AC_VERB_SET_CONNECT_SEL, j); |
| 3575 | return i; | 3587 | return j; |
| 3576 | } | 3588 | } |
| 3577 | } | 3589 | } |
| 3578 | return -1; | 3590 | return -1; |
| @@ -3652,7 +3664,7 @@ static bool select_automic(struct hda_codec *codec, int idx, bool detect) | |||
| 3652 | } | 3664 | } |
| 3653 | 3665 | ||
| 3654 | /* automatic switch internal and external mic */ | 3666 | /* automatic switch internal and external mic */ |
| 3655 | static void cx_auto_automic(struct hda_codec *codec) | 3667 | static void cx_auto_automic(struct hda_codec *codec, struct hda_jack_tbl *jack) |
| 3656 | { | 3668 | { |
| 3657 | struct conexant_spec *spec = codec->spec; | 3669 | struct conexant_spec *spec = codec->spec; |
| 3658 | 3670 | ||
| @@ -3663,22 +3675,6 @@ static void cx_auto_automic(struct hda_codec *codec) | |||
| 3663 | select_automic(codec, spec->auto_mic_int, false); | 3675 | select_automic(codec, spec->auto_mic_int, false); |
| 3664 | } | 3676 | } |
| 3665 | 3677 | ||
| 3666 | static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res) | ||
| 3667 | { | ||
| 3668 | switch (snd_hda_jack_get_action(codec, res >> 26)) { | ||
| 3669 | case CONEXANT_HP_EVENT: | ||
| 3670 | cx_auto_hp_automute(codec); | ||
| 3671 | break; | ||
| 3672 | case CONEXANT_LINE_EVENT: | ||
| 3673 | cx_auto_line_automute(codec); | ||
| 3674 | break; | ||
| 3675 | case CONEXANT_MIC_EVENT: | ||
| 3676 | cx_auto_automic(codec); | ||
| 3677 | break; | ||
| 3678 | } | ||
| 3679 | snd_hda_jack_report_sync(codec); | ||
| 3680 | } | ||
| 3681 | |||
| 3682 | /* check whether the pin config is suitable for auto-mic switching; | 3678 | /* check whether the pin config is suitable for auto-mic switching; |
| 3683 | * auto-mic is enabled only when one int-mic and one ext- and/or | 3679 | * auto-mic is enabled only when one int-mic and one ext- and/or |
| 3684 | * one dock-mic exist | 3680 | * one dock-mic exist |
| @@ -3888,11 +3884,12 @@ static void mute_outputs(struct hda_codec *codec, int num_nids, | |||
| 3888 | } | 3884 | } |
| 3889 | 3885 | ||
| 3890 | static void enable_unsol_pins(struct hda_codec *codec, int num_pins, | 3886 | static void enable_unsol_pins(struct hda_codec *codec, int num_pins, |
| 3891 | hda_nid_t *pins, unsigned int action) | 3887 | hda_nid_t *pins, unsigned int action, |
| 3888 | hda_jack_callback cb) | ||
| 3892 | { | 3889 | { |
| 3893 | int i; | 3890 | int i; |
| 3894 | for (i = 0; i < num_pins; i++) | 3891 | for (i = 0; i < num_pins; i++) |
| 3895 | snd_hda_jack_detect_enable(codec, pins[i], action); | 3892 | snd_hda_jack_detect_enable_callback(codec, pins[i], action, cb); |
| 3896 | } | 3893 | } |
| 3897 | 3894 | ||
| 3898 | static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) | 3895 | static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums) |
| @@ -3980,13 +3977,14 @@ static void cx_auto_init_output(struct hda_codec *codec) | |||
| 3980 | } | 3977 | } |
| 3981 | if (spec->auto_mute) { | 3978 | if (spec->auto_mute) { |
| 3982 | enable_unsol_pins(codec, cfg->hp_outs, cfg->hp_pins, | 3979 | enable_unsol_pins(codec, cfg->hp_outs, cfg->hp_pins, |
| 3983 | CONEXANT_HP_EVENT); | 3980 | CONEXANT_HP_EVENT, cx_auto_hp_automute); |
| 3984 | spec->hp_present = detect_jacks(codec, cfg->hp_outs, | 3981 | spec->hp_present = detect_jacks(codec, cfg->hp_outs, |
| 3985 | cfg->hp_pins); | 3982 | cfg->hp_pins); |
| 3986 | if (spec->detect_line) { | 3983 | if (spec->detect_line) { |
| 3987 | enable_unsol_pins(codec, cfg->line_outs, | 3984 | enable_unsol_pins(codec, cfg->line_outs, |
| 3988 | cfg->line_out_pins, | 3985 | cfg->line_out_pins, |
| 3989 | CONEXANT_LINE_EVENT); | 3986 | CONEXANT_LINE_EVENT, |
| 3987 | cx_auto_line_automute); | ||
| 3990 | spec->line_present = | 3988 | spec->line_present = |
| 3991 | detect_jacks(codec, cfg->line_outs, | 3989 | detect_jacks(codec, cfg->line_outs, |
| 3992 | cfg->line_out_pins); | 3990 | cfg->line_out_pins); |
| @@ -4027,16 +4025,16 @@ static void cx_auto_init_input(struct hda_codec *codec) | |||
| 4027 | 4025 | ||
| 4028 | if (spec->auto_mic) { | 4026 | if (spec->auto_mic) { |
| 4029 | if (spec->auto_mic_ext >= 0) { | 4027 | if (spec->auto_mic_ext >= 0) { |
| 4030 | snd_hda_jack_detect_enable(codec, | 4028 | snd_hda_jack_detect_enable_callback(codec, |
| 4031 | cfg->inputs[spec->auto_mic_ext].pin, | 4029 | cfg->inputs[spec->auto_mic_ext].pin, |
| 4032 | CONEXANT_MIC_EVENT); | 4030 | CONEXANT_MIC_EVENT, cx_auto_automic); |
| 4033 | } | 4031 | } |
| 4034 | if (spec->auto_mic_dock >= 0) { | 4032 | if (spec->auto_mic_dock >= 0) { |
| 4035 | snd_hda_jack_detect_enable(codec, | 4033 | snd_hda_jack_detect_enable_callback(codec, |
| 4036 | cfg->inputs[spec->auto_mic_dock].pin, | 4034 | cfg->inputs[spec->auto_mic_dock].pin, |
| 4037 | CONEXANT_MIC_EVENT); | 4035 | CONEXANT_MIC_EVENT, cx_auto_automic); |
| 4038 | } | 4036 | } |
| 4039 | cx_auto_automic(codec); | 4037 | cx_auto_automic(codec, NULL); |
| 4040 | } else { | 4038 | } else { |
| 4041 | select_input_connection(codec, spec->imux_info[0].adc, | 4039 | select_input_connection(codec, spec->imux_info[0].adc, |
| 4042 | spec->imux_info[0].pin); | 4040 | spec->imux_info[0].pin); |
| @@ -4061,7 +4059,6 @@ static int cx_auto_init(struct hda_codec *codec) | |||
| 4061 | cx_auto_init_output(codec); | 4059 | cx_auto_init_output(codec); |
| 4062 | cx_auto_init_input(codec); | 4060 | cx_auto_init_input(codec); |
| 4063 | cx_auto_init_digital(codec); | 4061 | cx_auto_init_digital(codec); |
| 4064 | snd_hda_jack_report_sync(codec); | ||
| 4065 | snd_hda_sync_vmaster_hook(&spec->vmaster_mute); | 4062 | snd_hda_sync_vmaster_hook(&spec->vmaster_mute); |
| 4066 | return 0; | 4063 | return 0; |
| 4067 | } | 4064 | } |
| @@ -4262,7 +4259,7 @@ static int cx_auto_add_boost_volume(struct hda_codec *codec, int idx, | |||
| 4262 | 4259 | ||
| 4263 | if (get_wcaps(codec, mux) & AC_WCAP_OUT_AMP) { | 4260 | if (get_wcaps(codec, mux) & AC_WCAP_OUT_AMP) { |
| 4264 | spec->imux_info[idx].boost = mux; | 4261 | spec->imux_info[idx].boost = mux; |
| 4265 | return cx_auto_add_volume(codec, label, " Boost", 0, | 4262 | return cx_auto_add_volume(codec, label, " Boost", cidx, |
| 4266 | mux, HDA_OUTPUT); | 4263 | mux, HDA_OUTPUT); |
| 4267 | } | 4264 | } |
| 4268 | return 0; | 4265 | return 0; |
| @@ -4395,8 +4392,8 @@ static const struct hda_codec_ops cx_auto_patch_ops = { | |||
| 4395 | .build_pcms = conexant_build_pcms, | 4392 | .build_pcms = conexant_build_pcms, |
| 4396 | .init = cx_auto_init, | 4393 | .init = cx_auto_init, |
| 4397 | .free = conexant_free, | 4394 | .free = conexant_free, |
| 4398 | .unsol_event = cx_auto_unsol_event, | 4395 | .unsol_event = snd_hda_jack_unsol_event, |
| 4399 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 4396 | #ifdef CONFIG_PM |
| 4400 | .suspend = conexant_suspend, | 4397 | .suspend = conexant_suspend, |
| 4401 | #endif | 4398 | #endif |
| 4402 | .reboot_notify = snd_hda_shutup_pins, | 4399 | .reboot_notify = snd_hda_shutup_pins, |
| @@ -4462,6 +4459,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { | |||
| 4462 | SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), | 4459 | SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410), |
| 4463 | SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), | 4460 | SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410), |
| 4464 | SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), | 4461 | SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC), |
| 4462 | SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC), | ||
| 4465 | SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC), | 4463 | SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC), |
| 4466 | {} | 4464 | {} |
| 4467 | }; | 4465 | }; |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 8f23374fa642..71555cc54db1 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
| @@ -34,6 +34,8 @@ | |||
| 34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
| 35 | #include <sound/core.h> | 35 | #include <sound/core.h> |
| 36 | #include <sound/jack.h> | 36 | #include <sound/jack.h> |
| 37 | #include <sound/asoundef.h> | ||
| 38 | #include <sound/tlv.h> | ||
| 37 | #include "hda_codec.h" | 39 | #include "hda_codec.h" |
| 38 | #include "hda_local.h" | 40 | #include "hda_local.h" |
| 39 | #include "hda_jack.h" | 41 | #include "hda_jack.h" |
| @@ -71,6 +73,9 @@ struct hdmi_spec_per_pin { | |||
| 71 | struct hdmi_eld sink_eld; | 73 | struct hdmi_eld sink_eld; |
| 72 | struct delayed_work work; | 74 | struct delayed_work work; |
| 73 | int repoll_count; | 75 | int repoll_count; |
| 76 | bool non_pcm; | ||
| 77 | bool chmap_set; /* channel-map override by ALSA API? */ | ||
| 78 | unsigned char chmap[8]; /* ALSA API channel-map */ | ||
| 74 | }; | 79 | }; |
| 75 | 80 | ||
| 76 | struct hdmi_spec { | 81 | struct hdmi_spec { |
| @@ -80,6 +85,7 @@ struct hdmi_spec { | |||
| 80 | int num_pins; | 85 | int num_pins; |
| 81 | struct hdmi_spec_per_pin pins[MAX_HDMI_PINS]; | 86 | struct hdmi_spec_per_pin pins[MAX_HDMI_PINS]; |
| 82 | struct hda_pcm pcm_rec[MAX_HDMI_PINS]; | 87 | struct hda_pcm pcm_rec[MAX_HDMI_PINS]; |
| 88 | unsigned int channels_max; /* max over all cvts */ | ||
| 83 | 89 | ||
| 84 | /* | 90 | /* |
| 85 | * Non-generic ATI/NVIDIA specific | 91 | * Non-generic ATI/NVIDIA specific |
| @@ -469,6 +475,17 @@ static void init_channel_allocations(void) | |||
| 469 | } | 475 | } |
| 470 | } | 476 | } |
| 471 | 477 | ||
| 478 | static int get_channel_allocation_order(int ca) | ||
| 479 | { | ||
| 480 | int i; | ||
| 481 | |||
| 482 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
| 483 | if (channel_allocations[i].ca_index == ca) | ||
| 484 | break; | ||
| 485 | } | ||
| 486 | return i; | ||
| 487 | } | ||
| 488 | |||
| 472 | /* | 489 | /* |
| 473 | * The transformation takes two steps: | 490 | * The transformation takes two steps: |
| 474 | * | 491 | * |
| @@ -535,24 +552,36 @@ static void hdmi_debug_channel_mapping(struct hda_codec *codec, | |||
| 535 | } | 552 | } |
| 536 | 553 | ||
| 537 | 554 | ||
| 538 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | 555 | static void hdmi_std_setup_channel_mapping(struct hda_codec *codec, |
| 539 | hda_nid_t pin_nid, | 556 | hda_nid_t pin_nid, |
| 557 | bool non_pcm, | ||
| 540 | int ca) | 558 | int ca) |
| 541 | { | 559 | { |
| 542 | int i; | 560 | int i; |
| 543 | int err; | 561 | int err; |
| 562 | int order; | ||
| 563 | int non_pcm_mapping[8]; | ||
| 564 | |||
| 565 | order = get_channel_allocation_order(ca); | ||
| 544 | 566 | ||
| 545 | if (hdmi_channel_mapping[ca][1] == 0) { | 567 | if (hdmi_channel_mapping[ca][1] == 0) { |
| 546 | for (i = 0; i < channel_allocations[ca].channels; i++) | 568 | for (i = 0; i < channel_allocations[order].channels; i++) |
| 547 | hdmi_channel_mapping[ca][i] = i | (i << 4); | 569 | hdmi_channel_mapping[ca][i] = i | (i << 4); |
| 548 | for (; i < 8; i++) | 570 | for (; i < 8; i++) |
| 549 | hdmi_channel_mapping[ca][i] = 0xf | (i << 4); | 571 | hdmi_channel_mapping[ca][i] = 0xf | (i << 4); |
| 550 | } | 572 | } |
| 551 | 573 | ||
| 574 | if (non_pcm) { | ||
| 575 | for (i = 0; i < channel_allocations[order].channels; i++) | ||
| 576 | non_pcm_mapping[i] = i | (i << 4); | ||
| 577 | for (; i < 8; i++) | ||
| 578 | non_pcm_mapping[i] = 0xf | (i << 4); | ||
| 579 | } | ||
| 580 | |||
| 552 | for (i = 0; i < 8; i++) { | 581 | for (i = 0; i < 8; i++) { |
| 553 | err = snd_hda_codec_write(codec, pin_nid, 0, | 582 | err = snd_hda_codec_write(codec, pin_nid, 0, |
| 554 | AC_VERB_SET_HDMI_CHAN_SLOT, | 583 | AC_VERB_SET_HDMI_CHAN_SLOT, |
| 555 | hdmi_channel_mapping[ca][i]); | 584 | non_pcm ? non_pcm_mapping[i] : hdmi_channel_mapping[ca][i]); |
| 556 | if (err) { | 585 | if (err) { |
| 557 | snd_printdd(KERN_NOTICE | 586 | snd_printdd(KERN_NOTICE |
| 558 | "HDMI: channel mapping failed\n"); | 587 | "HDMI: channel mapping failed\n"); |
| @@ -563,6 +592,136 @@ static void hdmi_setup_channel_mapping(struct hda_codec *codec, | |||
| 563 | hdmi_debug_channel_mapping(codec, pin_nid); | 592 | hdmi_debug_channel_mapping(codec, pin_nid); |
| 564 | } | 593 | } |
| 565 | 594 | ||
| 595 | struct channel_map_table { | ||
| 596 | unsigned char map; /* ALSA API channel map position */ | ||
| 597 | unsigned char cea_slot; /* CEA slot value */ | ||
| 598 | int spk_mask; /* speaker position bit mask */ | ||
| 599 | }; | ||
| 600 | |||
| 601 | static struct channel_map_table map_tables[] = { | ||
| 602 | { SNDRV_CHMAP_FL, 0x00, FL }, | ||
| 603 | { SNDRV_CHMAP_FR, 0x01, FR }, | ||
| 604 | { SNDRV_CHMAP_RL, 0x04, RL }, | ||
| 605 | { SNDRV_CHMAP_RR, 0x05, RR }, | ||
| 606 | { SNDRV_CHMAP_LFE, 0x02, LFE }, | ||
| 607 | { SNDRV_CHMAP_FC, 0x03, FC }, | ||
| 608 | { SNDRV_CHMAP_RLC, 0x06, RLC }, | ||
| 609 | { SNDRV_CHMAP_RRC, 0x07, RRC }, | ||
| 610 | {} /* terminator */ | ||
| 611 | }; | ||
| 612 | |||
| 613 | /* from ALSA API channel position to speaker bit mask */ | ||
| 614 | static int to_spk_mask(unsigned char c) | ||
| 615 | { | ||
| 616 | struct channel_map_table *t = map_tables; | ||
| 617 | for (; t->map; t++) { | ||
| 618 | if (t->map == c) | ||
| 619 | return t->spk_mask; | ||
| 620 | } | ||
| 621 | return 0; | ||
| 622 | } | ||
| 623 | |||
| 624 | /* from ALSA API channel position to CEA slot */ | ||
| 625 | static int to_cea_slot(unsigned char c) | ||
| 626 | { | ||
| 627 | struct channel_map_table *t = map_tables; | ||
| 628 | for (; t->map; t++) { | ||
| 629 | if (t->map == c) | ||
| 630 | return t->cea_slot; | ||
| 631 | } | ||
| 632 | return 0x0f; | ||
| 633 | } | ||
| 634 | |||
| 635 | /* from CEA slot to ALSA API channel position */ | ||
| 636 | static int from_cea_slot(unsigned char c) | ||
| 637 | { | ||
| 638 | struct channel_map_table *t = map_tables; | ||
| 639 | for (; t->map; t++) { | ||
| 640 | if (t->cea_slot == c) | ||
| 641 | return t->map; | ||
| 642 | } | ||
| 643 | return 0; | ||
| 644 | } | ||
| 645 | |||
| 646 | /* from speaker bit mask to ALSA API channel position */ | ||
| 647 | static int spk_to_chmap(int spk) | ||
| 648 | { | ||
| 649 | struct channel_map_table *t = map_tables; | ||
| 650 | for (; t->map; t++) { | ||
| 651 | if (t->spk_mask == spk) | ||
| 652 | return t->map; | ||
| 653 | } | ||
| 654 | return 0; | ||
| 655 | } | ||
| 656 | |||
| 657 | /* get the CA index corresponding to the given ALSA API channel map */ | ||
| 658 | static int hdmi_manual_channel_allocation(int chs, unsigned char *map) | ||
| 659 | { | ||
| 660 | int i, spks = 0, spk_mask = 0; | ||
| 661 | |||
| 662 | for (i = 0; i < chs; i++) { | ||
| 663 | int mask = to_spk_mask(map[i]); | ||
| 664 | if (mask) { | ||
| 665 | spk_mask |= mask; | ||
| 666 | spks++; | ||
| 667 | } | ||
| 668 | } | ||
| 669 | |||
| 670 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { | ||
| 671 | if ((chs == channel_allocations[i].channels || | ||
| 672 | spks == channel_allocations[i].channels) && | ||
| 673 | (spk_mask & channel_allocations[i].spk_mask) == | ||
| 674 | channel_allocations[i].spk_mask) | ||
| 675 | return channel_allocations[i].ca_index; | ||
| 676 | } | ||
| 677 | return -1; | ||
| 678 | } | ||
| 679 | |||
| 680 | /* set up the channel slots for the given ALSA API channel map */ | ||
| 681 | static int hdmi_manual_setup_channel_mapping(struct hda_codec *codec, | ||
| 682 | hda_nid_t pin_nid, | ||
| 683 | int chs, unsigned char *map) | ||
| 684 | { | ||
| 685 | int i; | ||
| 686 | for (i = 0; i < 8; i++) { | ||
| 687 | int val, err; | ||
| 688 | if (i < chs) | ||
| 689 | val = to_cea_slot(map[i]); | ||
| 690 | else | ||
| 691 | val = 0xf; | ||
| 692 | val |= (i << 4); | ||
| 693 | err = snd_hda_codec_write(codec, pin_nid, 0, | ||
| 694 | AC_VERB_SET_HDMI_CHAN_SLOT, val); | ||
| 695 | if (err) | ||
| 696 | return -EINVAL; | ||
| 697 | } | ||
| 698 | return 0; | ||
| 699 | } | ||
| 700 | |||
| 701 | /* store ALSA API channel map from the current default map */ | ||
| 702 | static void hdmi_setup_fake_chmap(unsigned char *map, int ca) | ||
| 703 | { | ||
| 704 | int i; | ||
| 705 | for (i = 0; i < 8; i++) { | ||
| 706 | if (i < channel_allocations[ca].channels) | ||
| 707 | map[i] = from_cea_slot((hdmi_channel_mapping[ca][i] >> 4) & 0x0f); | ||
| 708 | else | ||
| 709 | map[i] = 0; | ||
| 710 | } | ||
| 711 | } | ||
| 712 | |||
| 713 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | ||
| 714 | hda_nid_t pin_nid, bool non_pcm, int ca, | ||
| 715 | int channels, unsigned char *map) | ||
| 716 | { | ||
| 717 | if (!non_pcm && map) { | ||
| 718 | hdmi_manual_setup_channel_mapping(codec, pin_nid, | ||
| 719 | channels, map); | ||
| 720 | } else { | ||
| 721 | hdmi_std_setup_channel_mapping(codec, pin_nid, non_pcm, ca); | ||
| 722 | hdmi_setup_fake_chmap(map, ca); | ||
| 723 | } | ||
| 724 | } | ||
| 566 | 725 | ||
| 567 | /* | 726 | /* |
| 568 | * Audio InfoFrame routines | 727 | * Audio InfoFrame routines |
| @@ -686,7 +845,8 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | |||
| 686 | } | 845 | } |
| 687 | 846 | ||
| 688 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, | 847 | static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, |
| 689 | struct snd_pcm_substream *substream) | 848 | bool non_pcm, |
| 849 | struct snd_pcm_substream *substream) | ||
| 690 | { | 850 | { |
| 691 | struct hdmi_spec *spec = codec->spec; | 851 | struct hdmi_spec *spec = codec->spec; |
| 692 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | 852 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; |
| @@ -700,7 +860,12 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, | |||
| 700 | if (!eld->monitor_present) | 860 | if (!eld->monitor_present) |
| 701 | return; | 861 | return; |
| 702 | 862 | ||
| 703 | ca = hdmi_channel_allocation(eld, channels); | 863 | if (!non_pcm && per_pin->chmap_set) |
| 864 | ca = hdmi_manual_channel_allocation(channels, per_pin->chmap); | ||
| 865 | else | ||
| 866 | ca = hdmi_channel_allocation(eld, channels); | ||
| 867 | if (ca < 0) | ||
| 868 | ca = 0; | ||
| 704 | 869 | ||
| 705 | memset(&ai, 0, sizeof(ai)); | 870 | memset(&ai, 0, sizeof(ai)); |
| 706 | if (eld->conn_type == 0) { /* HDMI */ | 871 | if (eld->conn_type == 0) { /* HDMI */ |
| @@ -737,12 +902,21 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx, | |||
| 737 | "pin=%d channels=%d\n", | 902 | "pin=%d channels=%d\n", |
| 738 | pin_nid, | 903 | pin_nid, |
| 739 | channels); | 904 | channels); |
| 740 | hdmi_setup_channel_mapping(codec, pin_nid, ca); | 905 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, |
| 906 | channels, per_pin->chmap); | ||
| 741 | hdmi_stop_infoframe_trans(codec, pin_nid); | 907 | hdmi_stop_infoframe_trans(codec, pin_nid); |
| 742 | hdmi_fill_audio_infoframe(codec, pin_nid, | 908 | hdmi_fill_audio_infoframe(codec, pin_nid, |
| 743 | ai.bytes, sizeof(ai)); | 909 | ai.bytes, sizeof(ai)); |
| 744 | hdmi_start_infoframe_trans(codec, pin_nid); | 910 | hdmi_start_infoframe_trans(codec, pin_nid); |
| 911 | } else { | ||
| 912 | /* For non-pcm audio switch, setup new channel mapping | ||
| 913 | * accordingly */ | ||
| 914 | if (per_pin->non_pcm != non_pcm) | ||
| 915 | hdmi_setup_channel_mapping(codec, pin_nid, non_pcm, ca, | ||
| 916 | channels, per_pin->chmap); | ||
| 745 | } | 917 | } |
| 918 | |||
| 919 | per_pin->non_pcm = non_pcm; | ||
| 746 | } | 920 | } |
| 747 | 921 | ||
| 748 | 922 | ||
| @@ -1035,6 +1209,7 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid) | |||
| 1035 | per_pin = &spec->pins[pin_idx]; | 1209 | per_pin = &spec->pins[pin_idx]; |
| 1036 | 1210 | ||
| 1037 | per_pin->pin_nid = pin_nid; | 1211 | per_pin->pin_nid = pin_nid; |
| 1212 | per_pin->non_pcm = false; | ||
| 1038 | 1213 | ||
| 1039 | err = hdmi_read_pin_conn(codec, pin_idx); | 1214 | err = hdmi_read_pin_conn(codec, pin_idx); |
| 1040 | if (err < 0) | 1215 | if (err < 0) |
| @@ -1064,8 +1239,11 @@ static int hdmi_add_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) | |||
| 1064 | 1239 | ||
| 1065 | per_cvt->cvt_nid = cvt_nid; | 1240 | per_cvt->cvt_nid = cvt_nid; |
| 1066 | per_cvt->channels_min = 2; | 1241 | per_cvt->channels_min = 2; |
| 1067 | if (chans <= 16) | 1242 | if (chans <= 16) { |
| 1068 | per_cvt->channels_max = chans; | 1243 | per_cvt->channels_max = chans; |
| 1244 | if (chans > spec->channels_max) | ||
| 1245 | spec->channels_max = chans; | ||
| 1246 | } | ||
| 1069 | 1247 | ||
| 1070 | err = snd_hda_query_supported_pcm(codec, cvt_nid, | 1248 | err = snd_hda_query_supported_pcm(codec, cvt_nid, |
| 1071 | &per_cvt->rates, | 1249 | &per_cvt->rates, |
| @@ -1115,7 +1293,7 @@ static int hdmi_parse_codec(struct hda_codec *codec) | |||
| 1115 | * can be lost and presence sense verb will become inaccurate if the | 1293 | * can be lost and presence sense verb will become inaccurate if the |
| 1116 | * HDA link is powered off at hot plug or hw initialization time. | 1294 | * HDA link is powered off at hot plug or hw initialization time. |
| 1117 | */ | 1295 | */ |
| 1118 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1296 | #ifdef CONFIG_PM |
| 1119 | if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & | 1297 | if (!(snd_hda_param_read(codec, codec->afg, AC_PAR_POWER_STATE) & |
| 1120 | AC_PWRST_EPSS)) | 1298 | AC_PWRST_EPSS)) |
| 1121 | codec->bus->power_keep_link_on = 1; | 1299 | codec->bus->power_keep_link_on = 1; |
| @@ -1133,6 +1311,19 @@ static char *get_hdmi_pcm_name(int idx) | |||
| 1133 | return &names[idx][0]; | 1311 | return &names[idx][0]; |
| 1134 | } | 1312 | } |
| 1135 | 1313 | ||
| 1314 | static bool check_non_pcm_per_cvt(struct hda_codec *codec, hda_nid_t cvt_nid) | ||
| 1315 | { | ||
| 1316 | struct hda_spdif_out *spdif; | ||
| 1317 | bool non_pcm; | ||
| 1318 | |||
| 1319 | mutex_lock(&codec->spdif_mutex); | ||
| 1320 | spdif = snd_hda_spdif_out_of_nid(codec, cvt_nid); | ||
| 1321 | non_pcm = !!(spdif->status & IEC958_AES0_NONAUDIO); | ||
| 1322 | mutex_unlock(&codec->spdif_mutex); | ||
| 1323 | return non_pcm; | ||
| 1324 | } | ||
| 1325 | |||
| 1326 | |||
| 1136 | /* | 1327 | /* |
| 1137 | * HDMI callbacks | 1328 | * HDMI callbacks |
| 1138 | */ | 1329 | */ |
| @@ -1148,10 +1339,13 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
| 1148 | int pin_idx = hinfo_to_pin_index(spec, hinfo); | 1339 | int pin_idx = hinfo_to_pin_index(spec, hinfo); |
| 1149 | hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid; | 1340 | hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid; |
| 1150 | int pinctl; | 1341 | int pinctl; |
| 1342 | bool non_pcm; | ||
| 1343 | |||
| 1344 | non_pcm = check_non_pcm_per_cvt(codec, cvt_nid); | ||
| 1151 | 1345 | ||
| 1152 | hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels); | 1346 | hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels); |
| 1153 | 1347 | ||
| 1154 | hdmi_setup_audio_infoframe(codec, pin_idx, substream); | 1348 | hdmi_setup_audio_infoframe(codec, pin_idx, non_pcm, substream); |
| 1155 | 1349 | ||
| 1156 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, | 1350 | pinctl = snd_hda_codec_read(codec, pin_nid, 0, |
| 1157 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 1351 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
| @@ -1200,7 +1394,10 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo, | |||
| 1200 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1394 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
| 1201 | pinctl & ~PIN_OUT); | 1395 | pinctl & ~PIN_OUT); |
| 1202 | snd_hda_spdif_ctls_unassign(codec, pin_idx); | 1396 | snd_hda_spdif_ctls_unassign(codec, pin_idx); |
| 1397 | per_pin->chmap_set = false; | ||
| 1398 | memset(per_pin->chmap, 0, sizeof(per_pin->chmap)); | ||
| 1203 | } | 1399 | } |
| 1400 | |||
| 1204 | return 0; | 1401 | return 0; |
| 1205 | } | 1402 | } |
| 1206 | 1403 | ||
| @@ -1211,6 +1408,135 @@ static const struct hda_pcm_ops generic_ops = { | |||
| 1211 | .cleanup = generic_hdmi_playback_pcm_cleanup, | 1408 | .cleanup = generic_hdmi_playback_pcm_cleanup, |
| 1212 | }; | 1409 | }; |
| 1213 | 1410 | ||
| 1411 | /* | ||
| 1412 | * ALSA API channel-map control callbacks | ||
| 1413 | */ | ||
| 1414 | static int hdmi_chmap_ctl_info(struct snd_kcontrol *kcontrol, | ||
| 1415 | struct snd_ctl_elem_info *uinfo) | ||
| 1416 | { | ||
| 1417 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
| 1418 | struct hda_codec *codec = info->private_data; | ||
| 1419 | struct hdmi_spec *spec = codec->spec; | ||
| 1420 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
| 1421 | uinfo->count = spec->channels_max; | ||
| 1422 | uinfo->value.integer.min = 0; | ||
| 1423 | uinfo->value.integer.max = SNDRV_CHMAP_LAST; | ||
| 1424 | return 0; | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | static int hdmi_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
| 1428 | unsigned int size, unsigned int __user *tlv) | ||
| 1429 | { | ||
| 1430 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
| 1431 | struct hda_codec *codec = info->private_data; | ||
| 1432 | struct hdmi_spec *spec = codec->spec; | ||
| 1433 | const unsigned int valid_mask = | ||
| 1434 | FL | FR | RL | RR | LFE | FC | RLC | RRC; | ||
| 1435 | unsigned int __user *dst; | ||
| 1436 | int chs, count = 0; | ||
| 1437 | |||
| 1438 | if (size < 8) | ||
| 1439 | return -ENOMEM; | ||
| 1440 | if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv)) | ||
| 1441 | return -EFAULT; | ||
| 1442 | size -= 8; | ||
| 1443 | dst = tlv + 2; | ||
| 1444 | for (chs = 2; chs <= spec->channels_max; chs++) { | ||
| 1445 | int i, c; | ||
| 1446 | struct cea_channel_speaker_allocation *cap; | ||
| 1447 | cap = channel_allocations; | ||
| 1448 | for (i = 0; i < ARRAY_SIZE(channel_allocations); i++, cap++) { | ||
| 1449 | int chs_bytes = chs * 4; | ||
| 1450 | if (cap->channels != chs) | ||
| 1451 | continue; | ||
| 1452 | if (cap->spk_mask & ~valid_mask) | ||
| 1453 | continue; | ||
| 1454 | if (size < 8) | ||
| 1455 | return -ENOMEM; | ||
| 1456 | if (put_user(SNDRV_CTL_TLVT_CHMAP_VAR, dst) || | ||
| 1457 | put_user(chs_bytes, dst + 1)) | ||
| 1458 | return -EFAULT; | ||
| 1459 | dst += 2; | ||
| 1460 | size -= 8; | ||
| 1461 | count += 8; | ||
| 1462 | if (size < chs_bytes) | ||
| 1463 | return -ENOMEM; | ||
| 1464 | size -= chs_bytes; | ||
| 1465 | count += chs_bytes; | ||
| 1466 | for (c = 7; c >= 0; c--) { | ||
| 1467 | int spk = cap->speakers[c]; | ||
| 1468 | if (!spk) | ||
| 1469 | continue; | ||
| 1470 | if (put_user(spk_to_chmap(spk), dst)) | ||
| 1471 | return -EFAULT; | ||
| 1472 | dst++; | ||
| 1473 | } | ||
| 1474 | } | ||
| 1475 | } | ||
| 1476 | if (put_user(count, tlv + 1)) | ||
| 1477 | return -EFAULT; | ||
| 1478 | return 0; | ||
| 1479 | } | ||
| 1480 | |||
| 1481 | static int hdmi_chmap_ctl_get(struct snd_kcontrol *kcontrol, | ||
| 1482 | struct snd_ctl_elem_value *ucontrol) | ||
| 1483 | { | ||
| 1484 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
| 1485 | struct hda_codec *codec = info->private_data; | ||
| 1486 | struct hdmi_spec *spec = codec->spec; | ||
| 1487 | int pin_idx = kcontrol->private_value; | ||
| 1488 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | ||
| 1489 | int i; | ||
| 1490 | |||
| 1491 | for (i = 0; i < ARRAY_SIZE(per_pin->chmap); i++) | ||
| 1492 | ucontrol->value.integer.value[i] = per_pin->chmap[i]; | ||
| 1493 | return 0; | ||
| 1494 | } | ||
| 1495 | |||
| 1496 | static int hdmi_chmap_ctl_put(struct snd_kcontrol *kcontrol, | ||
| 1497 | struct snd_ctl_elem_value *ucontrol) | ||
| 1498 | { | ||
| 1499 | struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); | ||
| 1500 | struct hda_codec *codec = info->private_data; | ||
| 1501 | struct hdmi_spec *spec = codec->spec; | ||
| 1502 | int pin_idx = kcontrol->private_value; | ||
| 1503 | struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; | ||
| 1504 | unsigned int ctl_idx; | ||
| 1505 | struct snd_pcm_substream *substream; | ||
| 1506 | unsigned char chmap[8]; | ||
| 1507 | int i, ca, prepared = 0; | ||
| 1508 | |||
| 1509 | ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
| 1510 | substream = snd_pcm_chmap_substream(info, ctl_idx); | ||
| 1511 | if (!substream || !substream->runtime) | ||
| 1512 | return -EBADFD; | ||
| 1513 | switch (substream->runtime->status->state) { | ||
| 1514 | case SNDRV_PCM_STATE_OPEN: | ||
| 1515 | case SNDRV_PCM_STATE_SETUP: | ||
| 1516 | break; | ||
| 1517 | case SNDRV_PCM_STATE_PREPARED: | ||
| 1518 | prepared = 1; | ||
| 1519 | break; | ||
| 1520 | default: | ||
| 1521 | return -EBUSY; | ||
| 1522 | } | ||
| 1523 | memset(chmap, 0, sizeof(chmap)); | ||
| 1524 | for (i = 0; i < ARRAY_SIZE(chmap); i++) | ||
| 1525 | chmap[i] = ucontrol->value.integer.value[i]; | ||
| 1526 | if (!memcmp(chmap, per_pin->chmap, sizeof(chmap))) | ||
| 1527 | return 0; | ||
| 1528 | ca = hdmi_manual_channel_allocation(ARRAY_SIZE(chmap), chmap); | ||
| 1529 | if (ca < 0) | ||
| 1530 | return -EINVAL; | ||
| 1531 | per_pin->chmap_set = true; | ||
| 1532 | memcpy(per_pin->chmap, chmap, sizeof(chmap)); | ||
| 1533 | if (prepared) | ||
| 1534 | hdmi_setup_audio_infoframe(codec, pin_idx, per_pin->non_pcm, | ||
| 1535 | substream); | ||
| 1536 | |||
| 1537 | return 0; | ||
| 1538 | } | ||
| 1539 | |||
| 1214 | static int generic_hdmi_build_pcms(struct hda_codec *codec) | 1540 | static int generic_hdmi_build_pcms(struct hda_codec *codec) |
| 1215 | { | 1541 | { |
| 1216 | struct hdmi_spec *spec = codec->spec; | 1542 | struct hdmi_spec *spec = codec->spec; |
| @@ -1223,6 +1549,7 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec) | |||
| 1223 | info = &spec->pcm_rec[pin_idx]; | 1549 | info = &spec->pcm_rec[pin_idx]; |
| 1224 | info->name = get_hdmi_pcm_name(pin_idx); | 1550 | info->name = get_hdmi_pcm_name(pin_idx); |
| 1225 | info->pcm_type = HDA_PCM_TYPE_HDMI; | 1551 | info->pcm_type = HDA_PCM_TYPE_HDMI; |
| 1552 | info->own_chmap = true; | ||
| 1226 | 1553 | ||
| 1227 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | 1554 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; |
| 1228 | pstr->substreams = 1; | 1555 | pstr->substreams = 1; |
| @@ -1280,6 +1607,27 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) | |||
| 1280 | hdmi_present_sense(per_pin, 0); | 1607 | hdmi_present_sense(per_pin, 0); |
| 1281 | } | 1608 | } |
| 1282 | 1609 | ||
| 1610 | /* add channel maps */ | ||
| 1611 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | ||
| 1612 | struct snd_pcm_chmap *chmap; | ||
| 1613 | struct snd_kcontrol *kctl; | ||
| 1614 | int i; | ||
| 1615 | err = snd_pcm_add_chmap_ctls(codec->pcm_info[pin_idx].pcm, | ||
| 1616 | SNDRV_PCM_STREAM_PLAYBACK, | ||
| 1617 | NULL, 0, pin_idx, &chmap); | ||
| 1618 | if (err < 0) | ||
| 1619 | return err; | ||
| 1620 | /* override handlers */ | ||
| 1621 | chmap->private_data = codec; | ||
| 1622 | kctl = chmap->kctl; | ||
| 1623 | for (i = 0; i < kctl->count; i++) | ||
| 1624 | kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE; | ||
| 1625 | kctl->info = hdmi_chmap_ctl_info; | ||
| 1626 | kctl->get = hdmi_chmap_ctl_get; | ||
| 1627 | kctl->put = hdmi_chmap_ctl_put; | ||
| 1628 | kctl->tlv.c = hdmi_chmap_ctl_tlv; | ||
| 1629 | } | ||
| 1630 | |||
| 1283 | return 0; | 1631 | return 0; |
| 1284 | } | 1632 | } |
| 1285 | 1633 | ||
| @@ -1311,7 +1659,6 @@ static int generic_hdmi_init(struct hda_codec *codec) | |||
| 1311 | hdmi_init_pin(codec, pin_nid); | 1659 | hdmi_init_pin(codec, pin_nid); |
| 1312 | snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); | 1660 | snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); |
| 1313 | } | 1661 | } |
| 1314 | snd_hda_jack_report_sync(codec); | ||
| 1315 | return 0; | 1662 | return 0; |
| 1316 | } | 1663 | } |
| 1317 | 1664 | ||
| @@ -1428,7 +1775,6 @@ static int simple_playback_init(struct hda_codec *codec) | |||
| 1428 | snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 1775 | snd_hda_codec_write(codec, pin, 0, AC_VERB_SET_AMP_GAIN_MUTE, |
| 1429 | AMP_OUT_UNMUTE); | 1776 | AMP_OUT_UNMUTE); |
| 1430 | snd_hda_jack_detect_enable(codec, pin, pin); | 1777 | snd_hda_jack_detect_enable(codec, pin, pin); |
| 1431 | snd_hda_jack_report_sync(codec); | ||
| 1432 | return 0; | 1778 | return 0; |
| 1433 | } | 1779 | } |
| 1434 | 1780 | ||
| @@ -1809,6 +2155,43 @@ static int patch_nvhdmi_2ch(struct hda_codec *codec) | |||
| 1809 | return 0; | 2155 | return 0; |
| 1810 | } | 2156 | } |
| 1811 | 2157 | ||
| 2158 | static int nvhdmi_7x_8ch_build_pcms(struct hda_codec *codec) | ||
| 2159 | { | ||
| 2160 | struct hdmi_spec *spec = codec->spec; | ||
| 2161 | int err = simple_playback_build_pcms(codec); | ||
| 2162 | spec->pcm_rec[0].own_chmap = true; | ||
| 2163 | return err; | ||
| 2164 | } | ||
| 2165 | |||
| 2166 | static int nvhdmi_7x_8ch_build_controls(struct hda_codec *codec) | ||
| 2167 | { | ||
| 2168 | struct hdmi_spec *spec = codec->spec; | ||
| 2169 | struct snd_pcm_chmap *chmap; | ||
| 2170 | int err; | ||
| 2171 | |||
| 2172 | err = simple_playback_build_controls(codec); | ||
| 2173 | if (err < 0) | ||
| 2174 | return err; | ||
| 2175 | |||
| 2176 | /* add channel maps */ | ||
| 2177 | err = snd_pcm_add_chmap_ctls(spec->pcm_rec[0].pcm, | ||
| 2178 | SNDRV_PCM_STREAM_PLAYBACK, | ||
| 2179 | snd_pcm_alt_chmaps, 8, 0, &chmap); | ||
| 2180 | if (err < 0) | ||
| 2181 | return err; | ||
| 2182 | switch (codec->preset->id) { | ||
| 2183 | case 0x10de0002: | ||
| 2184 | case 0x10de0003: | ||
| 2185 | case 0x10de0005: | ||
| 2186 | case 0x10de0006: | ||
| 2187 | chmap->channel_mask = (1U << 2) | (1U << 8); | ||
| 2188 | break; | ||
| 2189 | case 0x10de0007: | ||
| 2190 | chmap->channel_mask = (1U << 2) | (1U << 6) | (1U << 8); | ||
| 2191 | } | ||
| 2192 | return 0; | ||
| 2193 | } | ||
| 2194 | |||
| 1812 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | 2195 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) |
| 1813 | { | 2196 | { |
| 1814 | struct hdmi_spec *spec; | 2197 | struct hdmi_spec *spec; |
| @@ -1819,6 +2202,8 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | |||
| 1819 | spec->multiout.max_channels = 8; | 2202 | spec->multiout.max_channels = 8; |
| 1820 | spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; | 2203 | spec->pcm_playback = nvhdmi_pcm_playback_8ch_7x; |
| 1821 | codec->patch_ops.init = nvhdmi_7x_init_8ch; | 2204 | codec->patch_ops.init = nvhdmi_7x_init_8ch; |
| 2205 | codec->patch_ops.build_pcms = nvhdmi_7x_8ch_build_pcms; | ||
| 2206 | codec->patch_ops.build_controls = nvhdmi_7x_8ch_build_controls; | ||
| 1822 | 2207 | ||
| 1823 | /* Initialize the audio infoframe channel mask and checksum to something | 2208 | /* Initialize the audio infoframe channel mask and checksum to something |
| 1824 | * valid */ | 2209 | * valid */ |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4f81dd44c837..8568aee56e2d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -174,7 +174,7 @@ struct alc_spec { | |||
| 174 | 174 | ||
| 175 | /* hooks */ | 175 | /* hooks */ |
| 176 | void (*init_hook)(struct hda_codec *codec); | 176 | void (*init_hook)(struct hda_codec *codec); |
| 177 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 177 | #ifdef CONFIG_PM |
| 178 | void (*power_hook)(struct hda_codec *codec); | 178 | void (*power_hook)(struct hda_codec *codec); |
| 179 | #endif | 179 | #endif |
| 180 | void (*shutup)(struct hda_codec *codec); | 180 | void (*shutup)(struct hda_codec *codec); |
| @@ -215,7 +215,7 @@ struct alc_spec { | |||
| 215 | /* for virtual master */ | 215 | /* for virtual master */ |
| 216 | hda_nid_t vmaster_nid; | 216 | hda_nid_t vmaster_nid; |
| 217 | struct hda_vmaster_mute_hook vmaster_mute; | 217 | struct hda_vmaster_mute_hook vmaster_mute; |
| 218 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 218 | #ifdef CONFIG_PM |
| 219 | struct hda_loopback_check loopback; | 219 | struct hda_loopback_check loopback; |
| 220 | int num_loopbacks; | 220 | int num_loopbacks; |
| 221 | struct hda_amp_list loopback_list[8]; | 221 | struct hda_amp_list loopback_list[8]; |
| @@ -594,7 +594,7 @@ static void call_update_outputs(struct hda_codec *codec) | |||
| 594 | } | 594 | } |
| 595 | 595 | ||
| 596 | /* standard HP-automute helper */ | 596 | /* standard HP-automute helper */ |
| 597 | static void alc_hp_automute(struct hda_codec *codec) | 597 | static void alc_hp_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) |
| 598 | { | 598 | { |
| 599 | struct alc_spec *spec = codec->spec; | 599 | struct alc_spec *spec = codec->spec; |
| 600 | 600 | ||
| @@ -607,7 +607,7 @@ static void alc_hp_automute(struct hda_codec *codec) | |||
| 607 | } | 607 | } |
| 608 | 608 | ||
| 609 | /* standard line-out-automute helper */ | 609 | /* standard line-out-automute helper */ |
| 610 | static void alc_line_automute(struct hda_codec *codec) | 610 | static void alc_line_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) |
| 611 | { | 611 | { |
| 612 | struct alc_spec *spec = codec->spec; | 612 | struct alc_spec *spec = codec->spec; |
| 613 | 613 | ||
| @@ -627,7 +627,7 @@ static void alc_line_automute(struct hda_codec *codec) | |||
| 627 | snd_hda_get_conn_index(codec, mux, nid, 0) | 627 | snd_hda_get_conn_index(codec, mux, nid, 0) |
| 628 | 628 | ||
| 629 | /* standard mic auto-switch helper */ | 629 | /* standard mic auto-switch helper */ |
| 630 | static void alc_mic_automute(struct hda_codec *codec) | 630 | static void alc_mic_automute(struct hda_codec *codec, struct hda_jack_tbl *jack) |
| 631 | { | 631 | { |
| 632 | struct alc_spec *spec = codec->spec; | 632 | struct alc_spec *spec = codec->spec; |
| 633 | hda_nid_t *pins = spec->imux_pins; | 633 | hda_nid_t *pins = spec->imux_pins; |
| @@ -648,25 +648,8 @@ static void alc_mic_automute(struct hda_codec *codec) | |||
| 648 | alc_mux_select(codec, 0, spec->int_mic_idx, false); | 648 | alc_mux_select(codec, 0, spec->int_mic_idx, false); |
| 649 | } | 649 | } |
| 650 | 650 | ||
| 651 | /* handle the specified unsol action (ALC_XXX_EVENT) */ | ||
| 652 | static void alc_exec_unsol_event(struct hda_codec *codec, int action) | ||
| 653 | { | ||
| 654 | switch (action) { | ||
| 655 | case ALC_HP_EVENT: | ||
| 656 | alc_hp_automute(codec); | ||
| 657 | break; | ||
| 658 | case ALC_FRONT_EVENT: | ||
| 659 | alc_line_automute(codec); | ||
| 660 | break; | ||
| 661 | case ALC_MIC_EVENT: | ||
| 662 | alc_mic_automute(codec); | ||
| 663 | break; | ||
| 664 | } | ||
| 665 | snd_hda_jack_report_sync(codec); | ||
| 666 | } | ||
| 667 | |||
| 668 | /* update the master volume per volume-knob's unsol event */ | 651 | /* update the master volume per volume-knob's unsol event */ |
| 669 | static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid) | 652 | static void alc_update_knob_master(struct hda_codec *codec, struct hda_jack_tbl *jack) |
| 670 | { | 653 | { |
| 671 | unsigned int val; | 654 | unsigned int val; |
| 672 | struct snd_kcontrol *kctl; | 655 | struct snd_kcontrol *kctl; |
| @@ -678,7 +661,7 @@ static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid) | |||
| 678 | uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); | 661 | uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); |
| 679 | if (!uctl) | 662 | if (!uctl) |
| 680 | return; | 663 | return; |
| 681 | val = snd_hda_codec_read(codec, nid, 0, | 664 | val = snd_hda_codec_read(codec, jack->nid, 0, |
| 682 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); | 665 | AC_VERB_GET_VOLUME_KNOB_CONTROL, 0); |
| 683 | val &= HDA_AMP_VOLMASK; | 666 | val &= HDA_AMP_VOLMASK; |
| 684 | uctl->value.integer.value[0] = val; | 667 | uctl->value.integer.value[0] = val; |
| @@ -687,37 +670,19 @@ static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid) | |||
| 687 | kfree(uctl); | 670 | kfree(uctl); |
| 688 | } | 671 | } |
| 689 | 672 | ||
| 690 | /* unsolicited event for HP jack sensing */ | 673 | static void alc880_unsol_event(struct hda_codec *codec, unsigned int res) |
| 691 | static void alc_unsol_event(struct hda_codec *codec, unsigned int res) | ||
| 692 | { | 674 | { |
| 693 | int action; | 675 | /* For some reason, the res given from ALC880 is broken. |
| 694 | 676 | Here we adjust it properly. */ | |
| 695 | if (codec->vendor_id == 0x10ec0880) | 677 | snd_hda_jack_unsol_event(codec, res >> 2); |
| 696 | res >>= 28; | ||
| 697 | else | ||
| 698 | res >>= 26; | ||
| 699 | action = snd_hda_jack_get_action(codec, res); | ||
| 700 | if (action == ALC_DCVOL_EVENT) { | ||
| 701 | /* Execute the dc-vol event here as it requires the NID | ||
| 702 | * but we don't pass NID to alc_exec_unsol_event(). | ||
| 703 | * Once when we convert all static quirks to the auto-parser, | ||
| 704 | * this can be integerated into there. | ||
| 705 | */ | ||
| 706 | struct hda_jack_tbl *jack; | ||
| 707 | jack = snd_hda_jack_tbl_get_from_tag(codec, res); | ||
| 708 | if (jack) | ||
| 709 | alc_update_knob_master(codec, jack->nid); | ||
| 710 | return; | ||
| 711 | } | ||
| 712 | alc_exec_unsol_event(codec, action); | ||
| 713 | } | 678 | } |
| 714 | 679 | ||
| 715 | /* call init functions of standard auto-mute helpers */ | 680 | /* call init functions of standard auto-mute helpers */ |
| 716 | static void alc_inithook(struct hda_codec *codec) | 681 | static void alc_inithook(struct hda_codec *codec) |
| 717 | { | 682 | { |
| 718 | alc_hp_automute(codec); | 683 | alc_hp_automute(codec, NULL); |
| 719 | alc_line_automute(codec); | 684 | alc_line_automute(codec, NULL); |
| 720 | alc_mic_automute(codec); | 685 | alc_mic_automute(codec, NULL); |
| 721 | } | 686 | } |
| 722 | 687 | ||
| 723 | /* additional initialization for ALC888 variants */ | 688 | /* additional initialization for ALC888 variants */ |
| @@ -999,7 +964,8 @@ static void alc_init_automute(struct hda_codec *codec) | |||
| 999 | continue; | 964 | continue; |
| 1000 | snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", | 965 | snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", |
| 1001 | nid); | 966 | nid); |
| 1002 | snd_hda_jack_detect_enable(codec, nid, ALC_HP_EVENT); | 967 | snd_hda_jack_detect_enable_callback(codec, nid, ALC_HP_EVENT, |
| 968 | alc_hp_automute); | ||
| 1003 | spec->detect_hp = 1; | 969 | spec->detect_hp = 1; |
| 1004 | } | 970 | } |
| 1005 | 971 | ||
| @@ -1011,10 +977,10 @@ static void alc_init_automute(struct hda_codec *codec) | |||
| 1011 | continue; | 977 | continue; |
| 1012 | snd_printdd("realtek: Enable Line-Out " | 978 | snd_printdd("realtek: Enable Line-Out " |
| 1013 | "auto-muting on NID 0x%x\n", nid); | 979 | "auto-muting on NID 0x%x\n", nid); |
| 1014 | snd_hda_jack_detect_enable(codec, nid, | 980 | snd_hda_jack_detect_enable_callback(codec, nid, ALC_FRONT_EVENT, |
| 1015 | ALC_FRONT_EVENT); | 981 | alc_line_automute); |
| 1016 | spec->detect_lo = 1; | 982 | spec->detect_lo = 1; |
| 1017 | } | 983 | } |
| 1018 | spec->automute_lo_possible = spec->detect_hp; | 984 | spec->automute_lo_possible = spec->detect_hp; |
| 1019 | } | 985 | } |
| 1020 | 986 | ||
| @@ -1110,10 +1076,12 @@ static bool alc_auto_mic_check_imux(struct hda_codec *codec) | |||
| 1110 | return false; /* no corresponding imux */ | 1076 | return false; /* no corresponding imux */ |
| 1111 | } | 1077 | } |
| 1112 | 1078 | ||
| 1113 | snd_hda_jack_detect_enable(codec, spec->ext_mic_pin, ALC_MIC_EVENT); | 1079 | snd_hda_jack_detect_enable_callback(codec, spec->ext_mic_pin, |
| 1080 | ALC_MIC_EVENT, alc_mic_automute); | ||
| 1114 | if (spec->dock_mic_pin) | 1081 | if (spec->dock_mic_pin) |
| 1115 | snd_hda_jack_detect_enable(codec, spec->dock_mic_pin, | 1082 | snd_hda_jack_detect_enable_callback(codec, spec->dock_mic_pin, |
| 1116 | ALC_MIC_EVENT); | 1083 | ALC_MIC_EVENT, |
| 1084 | alc_mic_automute); | ||
| 1117 | 1085 | ||
| 1118 | spec->auto_mic_valid_imux = 1; | 1086 | spec->auto_mic_valid_imux = 1; |
| 1119 | spec->auto_mic = 1; | 1087 | spec->auto_mic = 1; |
| @@ -2053,13 +2021,11 @@ static int alc_init(struct hda_codec *codec) | |||
| 2053 | 2021 | ||
| 2054 | alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT); | 2022 | alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT); |
| 2055 | 2023 | ||
| 2056 | snd_hda_jack_report_sync(codec); | ||
| 2057 | |||
| 2058 | hda_call_check_power_status(codec, 0x01); | 2024 | hda_call_check_power_status(codec, 0x01); |
| 2059 | return 0; | 2025 | return 0; |
| 2060 | } | 2026 | } |
| 2061 | 2027 | ||
| 2062 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2028 | #ifdef CONFIG_PM |
| 2063 | static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid) | 2029 | static int alc_check_power_status(struct hda_codec *codec, hda_nid_t nid) |
| 2064 | { | 2030 | { |
| 2065 | struct alc_spec *spec = codec->spec; | 2031 | struct alc_spec *spec = codec->spec; |
| @@ -2289,6 +2255,8 @@ static int alc_build_pcms(struct hda_codec *codec) | |||
| 2289 | p = &alc_pcm_analog_playback; | 2255 | p = &alc_pcm_analog_playback; |
| 2290 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p; | 2256 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *p; |
| 2291 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; | 2257 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0]; |
| 2258 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = | ||
| 2259 | spec->multiout.max_channels; | ||
| 2292 | } | 2260 | } |
| 2293 | if (spec->adc_nids) { | 2261 | if (spec->adc_nids) { |
| 2294 | p = spec->stream_analog_capture; | 2262 | p = spec->stream_analog_capture; |
| @@ -2437,7 +2405,7 @@ static void alc_free(struct hda_codec *codec) | |||
| 2437 | snd_hda_detach_beep_device(codec); | 2405 | snd_hda_detach_beep_device(codec); |
| 2438 | } | 2406 | } |
| 2439 | 2407 | ||
| 2440 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2408 | #ifdef CONFIG_PM |
| 2441 | static void alc_power_eapd(struct hda_codec *codec) | 2409 | static void alc_power_eapd(struct hda_codec *codec) |
| 2442 | { | 2410 | { |
| 2443 | alc_auto_setup_eapd(codec, false); | 2411 | alc_auto_setup_eapd(codec, false); |
| @@ -2473,17 +2441,18 @@ static const struct hda_codec_ops alc_patch_ops = { | |||
| 2473 | .build_pcms = alc_build_pcms, | 2441 | .build_pcms = alc_build_pcms, |
| 2474 | .init = alc_init, | 2442 | .init = alc_init, |
| 2475 | .free = alc_free, | 2443 | .free = alc_free, |
| 2476 | .unsol_event = alc_unsol_event, | 2444 | .unsol_event = snd_hda_jack_unsol_event, |
| 2477 | #ifdef CONFIG_PM | 2445 | #ifdef CONFIG_PM |
| 2478 | .resume = alc_resume, | 2446 | .resume = alc_resume, |
| 2479 | #endif | 2447 | #endif |
| 2480 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2448 | #ifdef CONFIG_PM |
| 2481 | .suspend = alc_suspend, | 2449 | .suspend = alc_suspend, |
| 2482 | .check_power_status = alc_check_power_status, | 2450 | .check_power_status = alc_check_power_status, |
| 2483 | #endif | 2451 | #endif |
| 2484 | .reboot_notify = alc_shutup, | 2452 | .reboot_notify = alc_shutup, |
| 2485 | }; | 2453 | }; |
| 2486 | 2454 | ||
| 2455 | |||
| 2487 | /* replace the codec chip_name with the given string */ | 2456 | /* replace the codec chip_name with the given string */ |
| 2488 | static int alc_codec_rename(struct hda_codec *codec, const char *name) | 2457 | static int alc_codec_rename(struct hda_codec *codec, const char *name) |
| 2489 | { | 2458 | { |
| @@ -2633,7 +2602,7 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, | |||
| 2633 | return channel_name[ch]; | 2602 | return channel_name[ch]; |
| 2634 | } | 2603 | } |
| 2635 | 2604 | ||
| 2636 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2605 | #ifdef CONFIG_PM |
| 2637 | /* add the powersave loopback-list entry */ | 2606 | /* add the powersave loopback-list entry */ |
| 2638 | static void add_loopback_list(struct alc_spec *spec, hda_nid_t mix, int idx) | 2607 | static void add_loopback_list(struct alc_spec *spec, hda_nid_t mix, int idx) |
| 2639 | { | 2608 | { |
| @@ -4447,7 +4416,7 @@ static void alc880_fixup_vol_knob(struct hda_codec *codec, | |||
| 4447 | const struct alc_fixup *fix, int action) | 4416 | const struct alc_fixup *fix, int action) |
| 4448 | { | 4417 | { |
| 4449 | if (action == ALC_FIXUP_ACT_PROBE) | 4418 | if (action == ALC_FIXUP_ACT_PROBE) |
| 4450 | snd_hda_jack_detect_enable(codec, 0x21, ALC_DCVOL_EVENT); | 4419 | snd_hda_jack_detect_enable_callback(codec, 0x21, ALC_DCVOL_EVENT, alc_update_knob_master); |
| 4451 | } | 4420 | } |
| 4452 | 4421 | ||
| 4453 | static const struct alc_fixup alc880_fixups[] = { | 4422 | static const struct alc_fixup alc880_fixups[] = { |
| @@ -4812,6 +4781,8 @@ static int patch_alc880(struct hda_codec *codec) | |||
| 4812 | } | 4781 | } |
| 4813 | 4782 | ||
| 4814 | codec->patch_ops = alc_patch_ops; | 4783 | codec->patch_ops = alc_patch_ops; |
| 4784 | codec->patch_ops.unsol_event = alc880_unsol_event; | ||
| 4785 | |||
| 4815 | 4786 | ||
| 4816 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); | 4787 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE); |
| 4817 | 4788 | ||
| @@ -4866,7 +4837,8 @@ static void alc260_fixup_gpio1_toggle(struct hda_codec *codec, | |||
| 4866 | spec->detect_hp = 1; | 4837 | spec->detect_hp = 1; |
| 4867 | spec->automute_speaker = 1; | 4838 | spec->automute_speaker = 1; |
| 4868 | spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ | 4839 | spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */ |
| 4869 | snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT); | 4840 | snd_hda_jack_detect_enable_callback(codec, 0x0f, ALC_HP_EVENT, |
| 4841 | alc_hp_automute); | ||
| 4870 | snd_hda_gen_add_verbs(&spec->gen, alc_gpio1_init_verbs); | 4842 | snd_hda_gen_add_verbs(&spec->gen, alc_gpio1_init_verbs); |
| 4871 | } | 4843 | } |
| 4872 | } | 4844 | } |
| @@ -6189,6 +6161,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { | |||
| 6189 | SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), | 6161 | SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC), |
| 6190 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), | 6162 | SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED), |
| 6191 | SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), | 6163 | SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC), |
| 6164 | SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_DMIC), | ||
| 6192 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), | 6165 | SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW), |
| 6193 | SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), | 6166 | SND_PCI_QUIRK(0x1043, 0x1b13, "Asus U41SV", ALC269_FIXUP_INV_DMIC), |
| 6194 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), | 6167 | SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC), |
| @@ -6334,6 +6307,12 @@ static int patch_alc269(struct hda_codec *codec) | |||
| 6334 | 6307 | ||
| 6335 | spec = codec->spec; | 6308 | spec = codec->spec; |
| 6336 | 6309 | ||
| 6310 | alc_pick_fixup(codec, alc269_fixup_models, | ||
| 6311 | alc269_fixup_tbl, alc269_fixups); | ||
| 6312 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); | ||
| 6313 | |||
| 6314 | alc_auto_parse_customize_define(codec); | ||
| 6315 | |||
| 6337 | if (codec->vendor_id == 0x10ec0269) { | 6316 | if (codec->vendor_id == 0x10ec0269) { |
| 6338 | spec->codec_variant = ALC269_TYPE_ALC269VA; | 6317 | spec->codec_variant = ALC269_TYPE_ALC269VA; |
| 6339 | switch (alc_get_coef0(codec) & 0x00f0) { | 6318 | switch (alc_get_coef0(codec) & 0x00f0) { |
| @@ -6361,12 +6340,6 @@ static int patch_alc269(struct hda_codec *codec) | |||
| 6361 | alc269_fill_coef(codec); | 6340 | alc269_fill_coef(codec); |
| 6362 | } | 6341 | } |
| 6363 | 6342 | ||
| 6364 | alc_pick_fixup(codec, alc269_fixup_models, | ||
| 6365 | alc269_fixup_tbl, alc269_fixups); | ||
| 6366 | alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); | ||
| 6367 | |||
| 6368 | alc_auto_parse_customize_define(codec); | ||
| 6369 | |||
| 6370 | /* automatic parse from the BIOS config */ | 6343 | /* automatic parse from the BIOS config */ |
| 6371 | err = alc269_parse_auto_config(codec); | 6344 | err = alc269_parse_auto_config(codec); |
| 6372 | if (err < 0) | 6345 | if (err < 0) |
| @@ -6503,7 +6476,7 @@ static int patch_alc861(struct hda_codec *codec) | |||
| 6503 | } | 6476 | } |
| 6504 | 6477 | ||
| 6505 | codec->patch_ops = alc_patch_ops; | 6478 | codec->patch_ops = alc_patch_ops; |
| 6506 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 6479 | #ifdef CONFIG_PM |
| 6507 | spec->power_hook = alc_power_eapd; | 6480 | spec->power_hook = alc_power_eapd; |
| 6508 | #endif | 6481 | #endif |
| 6509 | 6482 | ||
| @@ -7068,6 +7041,8 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { | |||
| 7068 | { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 }, | 7041 | { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 }, |
| 7069 | { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 }, | 7042 | { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 }, |
| 7070 | { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, | 7043 | { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, |
| 7044 | { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 }, | ||
| 7045 | { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 }, | ||
| 7071 | { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", | 7046 | { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", |
| 7072 | .patch = patch_alc861 }, | 7047 | .patch = patch_alc861 }, |
| 7073 | { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, | 7048 | { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 3d4722f0a1ca..fe163547f906 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
| @@ -103,6 +103,7 @@ enum { | |||
| 103 | STAC_HP_ZEPHYR, | 103 | STAC_HP_ZEPHYR, |
| 104 | STAC_92HD83XXX_HP_LED, | 104 | STAC_92HD83XXX_HP_LED, |
| 105 | STAC_92HD83XXX_HP_INV_LED, | 105 | STAC_92HD83XXX_HP_INV_LED, |
| 106 | STAC_92HD83XXX_HP_MIC_LED, | ||
| 106 | STAC_92HD83XXX_MODELS | 107 | STAC_92HD83XXX_MODELS |
| 107 | }; | 108 | }; |
| 108 | 109 | ||
| @@ -215,6 +216,9 @@ struct sigmatel_spec { | |||
| 215 | unsigned int vref_mute_led_nid; /* pin NID for mute-LED vref control */ | 216 | unsigned int vref_mute_led_nid; /* pin NID for mute-LED vref control */ |
| 216 | unsigned int vref_led; | 217 | unsigned int vref_led; |
| 217 | 218 | ||
| 219 | unsigned int mic_mute_led_gpio; /* capture mute LED GPIO */ | ||
| 220 | bool mic_mute_led_on; /* current mic mute state */ | ||
| 221 | |||
| 218 | /* stream */ | 222 | /* stream */ |
| 219 | unsigned int stream_delay; | 223 | unsigned int stream_delay; |
| 220 | 224 | ||
| @@ -1679,6 +1683,7 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { | |||
| 1679 | [STAC_HP_ZEPHYR] = "hp-zephyr", | 1683 | [STAC_HP_ZEPHYR] = "hp-zephyr", |
| 1680 | [STAC_92HD83XXX_HP_LED] = "hp-led", | 1684 | [STAC_92HD83XXX_HP_LED] = "hp-led", |
| 1681 | [STAC_92HD83XXX_HP_INV_LED] = "hp-inv-led", | 1685 | [STAC_92HD83XXX_HP_INV_LED] = "hp-inv-led", |
| 1686 | [STAC_92HD83XXX_HP_MIC_LED] = "hp-mic-led", | ||
| 1682 | }; | 1687 | }; |
| 1683 | 1688 | ||
| 1684 | static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | 1689 | static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { |
| @@ -1703,6 +1708,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | |||
| 1703 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 1708 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
| 1704 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165B, | 1709 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165B, |
| 1705 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 1710 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
| 1711 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x18df, | ||
| 1712 | "HP Folio", STAC_92HD83XXX_HP_MIC_LED), | ||
| 1706 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3388, | 1713 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3388, |
| 1707 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), | 1714 | "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), |
| 1708 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3389, | 1715 | SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3389, |
| @@ -2791,18 +2798,27 @@ stac_control_new(struct sigmatel_spec *spec, | |||
| 2791 | return knew; | 2798 | return knew; |
| 2792 | } | 2799 | } |
| 2793 | 2800 | ||
| 2794 | static int stac92xx_add_control_temp(struct sigmatel_spec *spec, | 2801 | static struct snd_kcontrol_new * |
| 2795 | const struct snd_kcontrol_new *ktemp, | 2802 | add_control_temp(struct sigmatel_spec *spec, |
| 2796 | int idx, const char *name, | 2803 | const struct snd_kcontrol_new *ktemp, |
| 2797 | unsigned long val) | 2804 | int idx, const char *name, |
| 2805 | unsigned long val) | ||
| 2798 | { | 2806 | { |
| 2799 | struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name, | 2807 | struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name, |
| 2800 | HDA_SUBDEV_AMP_FLAG); | 2808 | HDA_SUBDEV_AMP_FLAG); |
| 2801 | if (!knew) | 2809 | if (!knew) |
| 2802 | return -ENOMEM; | 2810 | return NULL; |
| 2803 | knew->index = idx; | 2811 | knew->index = idx; |
| 2804 | knew->private_value = val; | 2812 | knew->private_value = val; |
| 2805 | return 0; | 2813 | return knew; |
| 2814 | } | ||
| 2815 | |||
| 2816 | static int stac92xx_add_control_temp(struct sigmatel_spec *spec, | ||
| 2817 | const struct snd_kcontrol_new *ktemp, | ||
| 2818 | int idx, const char *name, | ||
| 2819 | unsigned long val) | ||
| 2820 | { | ||
| 2821 | return add_control_temp(spec, ktemp, idx, name, val) ? 0 : -ENOMEM; | ||
| 2806 | } | 2822 | } |
| 2807 | 2823 | ||
| 2808 | static inline int stac92xx_add_control_idx(struct sigmatel_spec *spec, | 2824 | static inline int stac92xx_add_control_idx(struct sigmatel_spec *spec, |
| @@ -3226,9 +3242,12 @@ static int create_multi_out_ctls(struct hda_codec *codec, int num_outs, | |||
| 3226 | idx = i; | 3242 | idx = i; |
| 3227 | break; | 3243 | break; |
| 3228 | case AUTO_PIN_SPEAKER_OUT: | 3244 | case AUTO_PIN_SPEAKER_OUT: |
| 3229 | name = "Speaker"; | 3245 | if (num_outs <= 1) { |
| 3230 | idx = i; | 3246 | name = "Speaker"; |
| 3231 | break; | 3247 | idx = i; |
| 3248 | break; | ||
| 3249 | } | ||
| 3250 | /* Fall through in case of multi speaker outs */ | ||
| 3232 | default: | 3251 | default: |
| 3233 | name = chname[i]; | 3252 | name = chname[i]; |
| 3234 | idx = 0; | 3253 | idx = 0; |
| @@ -3242,18 +3261,56 @@ static int create_multi_out_ctls(struct hda_codec *codec, int num_outs, | |||
| 3242 | return 0; | 3261 | return 0; |
| 3243 | } | 3262 | } |
| 3244 | 3263 | ||
| 3264 | static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, | ||
| 3265 | unsigned int dir_mask, unsigned int data); | ||
| 3266 | |||
| 3267 | /* hook for controlling mic-mute LED GPIO */ | ||
| 3268 | static int stac92xx_capture_sw_put_led(struct snd_kcontrol *kcontrol, | ||
| 3269 | struct snd_ctl_elem_value *ucontrol) | ||
| 3270 | { | ||
| 3271 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
| 3272 | struct sigmatel_spec *spec = codec->spec; | ||
| 3273 | int err; | ||
| 3274 | bool mute; | ||
| 3275 | |||
| 3276 | err = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | ||
| 3277 | if (err <= 0) | ||
| 3278 | return err; | ||
| 3279 | mute = !(ucontrol->value.integer.value[0] && | ||
| 3280 | ucontrol->value.integer.value[1]); | ||
| 3281 | if (spec->mic_mute_led_on != mute) { | ||
| 3282 | spec->mic_mute_led_on = mute; | ||
| 3283 | if (mute) | ||
| 3284 | spec->gpio_data |= spec->mic_mute_led_gpio; | ||
| 3285 | else | ||
| 3286 | spec->gpio_data &= ~spec->mic_mute_led_gpio; | ||
| 3287 | stac_gpio_set(codec, spec->gpio_mask, | ||
| 3288 | spec->gpio_dir, spec->gpio_data); | ||
| 3289 | } | ||
| 3290 | return err; | ||
| 3291 | } | ||
| 3292 | |||
| 3245 | static int stac92xx_add_capvol_ctls(struct hda_codec *codec, unsigned long vol, | 3293 | static int stac92xx_add_capvol_ctls(struct hda_codec *codec, unsigned long vol, |
| 3246 | unsigned long sw, int idx) | 3294 | unsigned long sw, int idx) |
| 3247 | { | 3295 | { |
| 3296 | struct sigmatel_spec *spec = codec->spec; | ||
| 3297 | struct snd_kcontrol_new *knew; | ||
| 3248 | int err; | 3298 | int err; |
| 3299 | |||
| 3249 | err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, | 3300 | err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, |
| 3250 | "Capture Volume", vol); | 3301 | "Capture Volume", vol); |
| 3251 | if (err < 0) | 3302 | if (err < 0) |
| 3252 | return err; | 3303 | return err; |
| 3253 | err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_MUTE, idx, | 3304 | |
| 3254 | "Capture Switch", sw); | 3305 | knew = add_control_temp(spec, |
| 3255 | if (err < 0) | 3306 | &stac92xx_control_templates[STAC_CTL_WIDGET_MUTE], |
| 3256 | return err; | 3307 | idx, "Capture Switch", sw); |
| 3308 | if (!knew) | ||
| 3309 | return -ENOMEM; | ||
| 3310 | /* add a LED hook for some HP laptops */ | ||
| 3311 | if (spec->mic_mute_led_gpio) | ||
| 3312 | knew->put = stac92xx_capture_sw_put_led; | ||
| 3313 | |||
| 3257 | return 0; | 3314 | return 0; |
| 3258 | } | 3315 | } |
| 3259 | 3316 | ||
| @@ -4155,6 +4212,9 @@ static int stac_add_event(struct hda_codec *codec, hda_nid_t nid, | |||
| 4155 | return 0; | 4212 | return 0; |
| 4156 | } | 4213 | } |
| 4157 | 4214 | ||
| 4215 | static void handle_unsol_event(struct hda_codec *codec, | ||
| 4216 | struct hda_jack_tbl *event); | ||
| 4217 | |||
| 4158 | /* check if given nid is a valid pin and no other events are assigned | 4218 | /* check if given nid is a valid pin and no other events are assigned |
| 4159 | * to it. If OK, assign the event, set the unsol flag, and returns 1. | 4219 | * to it. If OK, assign the event, set the unsol flag, and returns 1. |
| 4160 | * Otherwise, returns zero. | 4220 | * Otherwise, returns zero. |
| @@ -4172,6 +4232,7 @@ static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | |||
| 4172 | if (event->action && event->action != type) | 4232 | if (event->action && event->action != type) |
| 4173 | return 0; | 4233 | return 0; |
| 4174 | event->action = type; | 4234 | event->action = type; |
| 4235 | event->callback = handle_unsol_event; | ||
| 4175 | snd_hda_jack_detect_enable(codec, nid, 0); | 4236 | snd_hda_jack_detect_enable(codec, nid, 0); |
| 4176 | return 1; | 4237 | return 1; |
| 4177 | } | 4238 | } |
| @@ -4418,8 +4479,6 @@ static int stac92xx_init(struct hda_codec *codec) | |||
| 4418 | stac_toggle_power_map(codec, nid, 0); | 4479 | stac_toggle_power_map(codec, nid, 0); |
| 4419 | } | 4480 | } |
| 4420 | 4481 | ||
| 4421 | snd_hda_jack_report_sync(codec); | ||
| 4422 | |||
| 4423 | /* sync mute LED */ | 4482 | /* sync mute LED */ |
| 4424 | if (spec->gpio_led) { | 4483 | if (spec->gpio_led) { |
| 4425 | if (spec->vmaster_mute.hook) | 4484 | if (spec->vmaster_mute.hook) |
| @@ -4812,20 +4871,6 @@ static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) | |||
| 4812 | handle_unsol_event(codec, event); | 4871 | handle_unsol_event(codec, event); |
| 4813 | } | 4872 | } |
| 4814 | 4873 | ||
| 4815 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | ||
| 4816 | { | ||
| 4817 | struct hda_jack_tbl *event; | ||
| 4818 | int tag; | ||
| 4819 | |||
| 4820 | tag = (res >> 26) & 0x7f; | ||
| 4821 | event = snd_hda_jack_tbl_get_from_tag(codec, tag); | ||
| 4822 | if (!event) | ||
| 4823 | return; | ||
| 4824 | event->jack_dirty = 1; | ||
| 4825 | handle_unsol_event(codec, event); | ||
| 4826 | snd_hda_jack_report_sync(codec); | ||
| 4827 | } | ||
| 4828 | |||
| 4829 | static int hp_blike_system(u32 subsystem_id); | 4874 | static int hp_blike_system(u32 subsystem_id); |
| 4830 | 4875 | ||
| 4831 | static void set_hp_led_gpio(struct hda_codec *codec) | 4876 | static void set_hp_led_gpio(struct hda_codec *codec) |
| @@ -5076,7 +5121,7 @@ static const struct hda_codec_ops stac92xx_patch_ops = { | |||
| 5076 | .build_pcms = stac92xx_build_pcms, | 5121 | .build_pcms = stac92xx_build_pcms, |
| 5077 | .init = stac92xx_init, | 5122 | .init = stac92xx_init, |
| 5078 | .free = stac92xx_free, | 5123 | .free = stac92xx_free, |
| 5079 | .unsol_event = stac92xx_unsol_event, | 5124 | .unsol_event = snd_hda_jack_unsol_event, |
| 5080 | #ifdef CONFIG_PM | 5125 | #ifdef CONFIG_PM |
| 5081 | .suspend = stac92xx_suspend, | 5126 | .suspend = stac92xx_suspend, |
| 5082 | .resume = stac92xx_resume, | 5127 | .resume = stac92xx_resume, |
| @@ -5578,6 +5623,9 @@ again: | |||
| 5578 | case STAC_92HD83XXX_HP_INV_LED: | 5623 | case STAC_92HD83XXX_HP_INV_LED: |
| 5579 | default_polarity = 1; | 5624 | default_polarity = 1; |
| 5580 | break; | 5625 | break; |
| 5626 | case STAC_92HD83XXX_HP_MIC_LED: | ||
| 5627 | spec->mic_mute_led_gpio = 0x08; /* GPIO3 */ | ||
| 5628 | break; | ||
| 5581 | } | 5629 | } |
| 5582 | 5630 | ||
| 5583 | if (find_mute_led_cfg(codec, default_polarity)) | 5631 | if (find_mute_led_cfg(codec, default_polarity)) |
| @@ -5596,6 +5644,13 @@ again: | |||
| 5596 | } | 5644 | } |
| 5597 | } | 5645 | } |
| 5598 | 5646 | ||
| 5647 | if (spec->mic_mute_led_gpio) { | ||
| 5648 | spec->gpio_mask |= spec->mic_mute_led_gpio; | ||
| 5649 | spec->gpio_dir |= spec->mic_mute_led_gpio; | ||
| 5650 | spec->mic_mute_led_on = true; | ||
| 5651 | spec->gpio_data |= spec->mic_mute_led_gpio; | ||
| 5652 | } | ||
| 5653 | |||
| 5599 | err = stac92xx_parse_auto_config(codec); | 5654 | err = stac92xx_parse_auto_config(codec); |
| 5600 | if (!err) { | 5655 | if (!err) { |
| 5601 | if (spec->board_config < 0) { | 5656 | if (spec->board_config < 0) { |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 430771776915..5a45a912aedc 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
| @@ -1672,7 +1672,8 @@ static void via_hp_automute(struct hda_codec *codec) | |||
| 1672 | struct via_spec *spec = codec->spec; | 1672 | struct via_spec *spec = codec->spec; |
| 1673 | 1673 | ||
| 1674 | if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0] && | 1674 | if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0] && |
| 1675 | (spec->codec_type != VT1708 || spec->vt1708_jack_detect)) | 1675 | (spec->codec_type != VT1708 || spec->vt1708_jack_detect) && |
| 1676 | is_jack_detectable(codec, spec->autocfg.hp_pins[0])) | ||
| 1676 | present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]); | 1677 | present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]); |
| 1677 | 1678 | ||
| 1678 | if (spec->smart51_enabled) | 1679 | if (spec->smart51_enabled) |
| @@ -1764,7 +1765,7 @@ static int via_suspend(struct hda_codec *codec) | |||
| 1764 | } | 1765 | } |
| 1765 | #endif | 1766 | #endif |
| 1766 | 1767 | ||
| 1767 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1768 | #ifdef CONFIG_PM |
| 1768 | static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid) | 1769 | static int via_check_power_status(struct hda_codec *codec, hda_nid_t nid) |
| 1769 | { | 1770 | { |
| 1770 | struct via_spec *spec = codec->spec; | 1771 | struct via_spec *spec = codec->spec; |
| @@ -1785,8 +1786,6 @@ static const struct hda_codec_ops via_patch_ops = { | |||
| 1785 | .unsol_event = via_unsol_event, | 1786 | .unsol_event = via_unsol_event, |
| 1786 | #ifdef CONFIG_PM | 1787 | #ifdef CONFIG_PM |
| 1787 | .suspend = via_suspend, | 1788 | .suspend = via_suspend, |
| 1788 | #endif | ||
| 1789 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
| 1790 | .check_power_status = via_check_power_status, | 1789 | .check_power_status = via_check_power_status, |
| 1791 | #endif | 1790 | #endif |
| 1792 | }; | 1791 | }; |
| @@ -2815,7 +2814,6 @@ static int via_init(struct hda_codec *codec) | |||
| 2815 | 2814 | ||
| 2816 | via_hp_automute(codec); | 2815 | via_hp_automute(codec); |
| 2817 | vt1708_update_hp_work(spec); | 2816 | vt1708_update_hp_work(spec); |
| 2818 | snd_hda_jack_report_sync(codec); | ||
| 2819 | 2817 | ||
| 2820 | return 0; | 2818 | return 0; |
| 2821 | } | 2819 | } |
| @@ -3669,6 +3667,32 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec) | |||
| 3669 | update_power_state(codec, 0x21, AC_PWRST_D3); | 3667 | update_power_state(codec, 0x21, AC_PWRST_D3); |
| 3670 | } | 3668 | } |
| 3671 | 3669 | ||
| 3670 | /* | ||
| 3671 | * pin fix-up | ||
| 3672 | */ | ||
| 3673 | enum { | ||
| 3674 | VIA_FIXUP_INTMIC_BOOST, | ||
| 3675 | }; | ||
| 3676 | |||
| 3677 | static void via_fixup_intmic_boost(struct hda_codec *codec, | ||
| 3678 | const struct hda_fixup *fix, int action) | ||
| 3679 | { | ||
| 3680 | if (action == HDA_FIXUP_ACT_PRE_PROBE) | ||
| 3681 | override_mic_boost(codec, 0x30, 0, 2, 40); | ||
| 3682 | } | ||
| 3683 | |||
| 3684 | static const struct hda_fixup via_fixups[] = { | ||
| 3685 | [VIA_FIXUP_INTMIC_BOOST] = { | ||
| 3686 | .type = HDA_FIXUP_FUNC, | ||
| 3687 | .v.func = via_fixup_intmic_boost, | ||
| 3688 | }, | ||
| 3689 | }; | ||
| 3690 | |||
| 3691 | static const struct snd_pci_quirk vt2002p_fixups[] = { | ||
| 3692 | SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST), | ||
| 3693 | {} | ||
| 3694 | }; | ||
| 3695 | |||
| 3672 | /* patch for vt2002P */ | 3696 | /* patch for vt2002P */ |
| 3673 | static int patch_vt2002P(struct hda_codec *codec) | 3697 | static int patch_vt2002P(struct hda_codec *codec) |
| 3674 | { | 3698 | { |
| @@ -3685,6 +3709,9 @@ static int patch_vt2002P(struct hda_codec *codec) | |||
| 3685 | override_mic_boost(codec, 0x29, 0, 3, 40); | 3709 | override_mic_boost(codec, 0x29, 0, 3, 40); |
| 3686 | add_secret_dac_path(codec); | 3710 | add_secret_dac_path(codec); |
| 3687 | 3711 | ||
| 3712 | snd_hda_pick_fixup(codec, NULL, vt2002p_fixups, via_fixups); | ||
| 3713 | snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE); | ||
| 3714 | |||
| 3688 | /* automatic parse from the BIOS config */ | 3715 | /* automatic parse from the BIOS config */ |
| 3689 | err = via_parse_auto_config(codec); | 3716 | err = via_parse_auto_config(codec); |
| 3690 | if (err < 0) { | 3717 | if (err < 0) { |
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c index 3e4f8c12ffce..20bcddea2eab 100644 --- a/sound/pci/ice1712/aureon.c +++ b/sound/pci/ice1712/aureon.c | |||
| @@ -2103,7 +2103,7 @@ static int aureon_reset(struct snd_ice1712 *ice) | |||
| 2103 | /* | 2103 | /* |
| 2104 | * suspend/resume | 2104 | * suspend/resume |
| 2105 | */ | 2105 | */ |
| 2106 | #ifdef CONFIG_PM | 2106 | #ifdef CONFIG_PM_SLEEP |
| 2107 | static int aureon_resume(struct snd_ice1712 *ice) | 2107 | static int aureon_resume(struct snd_ice1712 *ice) |
| 2108 | { | 2108 | { |
| 2109 | struct aureon_spec *spec = ice->spec; | 2109 | struct aureon_spec *spec = ice->spec; |
| @@ -2160,7 +2160,7 @@ static int __devinit aureon_init(struct snd_ice1712 *ice) | |||
| 2160 | wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); | 2160 | wm_set_vol(ice, i, spec->vol[i], spec->master[i % 2]); |
| 2161 | } | 2161 | } |
| 2162 | 2162 | ||
| 2163 | #ifdef CONFIG_PM | 2163 | #ifdef CONFIG_PM_SLEEP |
| 2164 | ice->pm_resume = aureon_resume; | 2164 | ice->pm_resume = aureon_resume; |
| 2165 | ice->pm_suspend_enabled = 1; | 2165 | ice->pm_suspend_enabled = 1; |
| 2166 | #endif | 2166 | #endif |
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h index 0da778a69ef8..d0e7d87f09f0 100644 --- a/sound/pci/ice1712/ice1712.h +++ b/sound/pci/ice1712/ice1712.h | |||
| @@ -384,7 +384,7 @@ struct snd_ice1712 { | |||
| 384 | char **ext_clock_names; | 384 | char **ext_clock_names; |
| 385 | int ext_clock_count; | 385 | int ext_clock_count; |
| 386 | void (*pro_open)(struct snd_ice1712 *, struct snd_pcm_substream *); | 386 | void (*pro_open)(struct snd_ice1712 *, struct snd_pcm_substream *); |
| 387 | #ifdef CONFIG_PM | 387 | #ifdef CONFIG_PM_SLEEP |
| 388 | int (*pm_suspend)(struct snd_ice1712 *); | 388 | int (*pm_suspend)(struct snd_ice1712 *); |
| 389 | int (*pm_resume)(struct snd_ice1712 *); | 389 | int (*pm_resume)(struct snd_ice1712 *); |
| 390 | unsigned int pm_suspend_enabled:1; | 390 | unsigned int pm_suspend_enabled:1; |
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index bed9f34f4efe..3050a5279253 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
| @@ -2792,7 +2792,7 @@ static void __devexit snd_vt1724_remove(struct pci_dev *pci) | |||
| 2792 | pci_set_drvdata(pci, NULL); | 2792 | pci_set_drvdata(pci, NULL); |
| 2793 | } | 2793 | } |
| 2794 | 2794 | ||
| 2795 | #ifdef CONFIG_PM | 2795 | #ifdef CONFIG_PM_SLEEP |
| 2796 | static int snd_vt1724_suspend(struct device *dev) | 2796 | static int snd_vt1724_suspend(struct device *dev) |
| 2797 | { | 2797 | { |
| 2798 | struct pci_dev *pci = to_pci_dev(dev); | 2798 | struct pci_dev *pci = to_pci_dev(dev); |
| @@ -2878,7 +2878,7 @@ static SIMPLE_DEV_PM_OPS(snd_vt1724_pm, snd_vt1724_suspend, snd_vt1724_resume); | |||
| 2878 | #define SND_VT1724_PM_OPS &snd_vt1724_pm | 2878 | #define SND_VT1724_PM_OPS &snd_vt1724_pm |
| 2879 | #else | 2879 | #else |
| 2880 | #define SND_VT1724_PM_OPS NULL | 2880 | #define SND_VT1724_PM_OPS NULL |
| 2881 | #endif /* CONFIG_PM */ | 2881 | #endif /* CONFIG_PM_SLEEP */ |
| 2882 | 2882 | ||
| 2883 | static struct pci_driver vt1724_driver = { | 2883 | static struct pci_driver vt1724_driver = { |
| 2884 | .name = KBUILD_MODNAME, | 2884 | .name = KBUILD_MODNAME, |
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c index 98bc3b7681b5..14fd536b6452 100644 --- a/sound/pci/ice1712/juli.c +++ b/sound/pci/ice1712/juli.c | |||
| @@ -486,7 +486,7 @@ static int __devinit juli_add_controls(struct snd_ice1712 *ice) | |||
| 486 | * suspend/resume | 486 | * suspend/resume |
| 487 | * */ | 487 | * */ |
| 488 | 488 | ||
| 489 | #ifdef CONFIG_PM | 489 | #ifdef CONFIG_PM_SLEEP |
| 490 | static int juli_resume(struct snd_ice1712 *ice) | 490 | static int juli_resume(struct snd_ice1712 *ice) |
| 491 | { | 491 | { |
| 492 | struct snd_akm4xxx *ak = ice->akm; | 492 | struct snd_akm4xxx *ak = ice->akm; |
| @@ -652,7 +652,7 @@ static int __devinit juli_init(struct snd_ice1712 *ice) | |||
| 652 | 652 | ||
| 653 | ice->spdif.ops.open = juli_spdif_in_open; | 653 | ice->spdif.ops.open = juli_spdif_in_open; |
| 654 | 654 | ||
| 655 | #ifdef CONFIG_PM | 655 | #ifdef CONFIG_PM_SLEEP |
| 656 | ice->pm_resume = juli_resume; | 656 | ice->pm_resume = juli_resume; |
| 657 | ice->pm_suspend = juli_suspend; | 657 | ice->pm_suspend = juli_suspend; |
| 658 | ice->pm_suspend_enabled = 1; | 658 | ice->pm_suspend_enabled = 1; |
diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c index 075d5aa1fee0..7bf093c51ce5 100644 --- a/sound/pci/ice1712/prodigy_hifi.c +++ b/sound/pci/ice1712/prodigy_hifi.c | |||
| @@ -1100,7 +1100,7 @@ static void ak4396_init(struct snd_ice1712 *ice) | |||
| 1100 | ak4396_write(ice, ak4396_inits[i], ak4396_inits[i+1]); | 1100 | ak4396_write(ice, ak4396_inits[i], ak4396_inits[i+1]); |
| 1101 | } | 1101 | } |
| 1102 | 1102 | ||
| 1103 | #ifdef CONFIG_PM | 1103 | #ifdef CONFIG_PM_SLEEP |
| 1104 | static int prodigy_hd2_resume(struct snd_ice1712 *ice) | 1104 | static int prodigy_hd2_resume(struct snd_ice1712 *ice) |
| 1105 | { | 1105 | { |
| 1106 | /* initialize ak4396 codec and restore previous mixer volumes */ | 1106 | /* initialize ak4396 codec and restore previous mixer volumes */ |
| @@ -1141,7 +1141,7 @@ static int __devinit prodigy_hd2_init(struct snd_ice1712 *ice) | |||
| 1141 | return -ENOMEM; | 1141 | return -ENOMEM; |
| 1142 | ice->spec = spec; | 1142 | ice->spec = spec; |
| 1143 | 1143 | ||
| 1144 | #ifdef CONFIG_PM | 1144 | #ifdef CONFIG_PM_SLEEP |
| 1145 | ice->pm_resume = &prodigy_hd2_resume; | 1145 | ice->pm_resume = &prodigy_hd2_resume; |
| 1146 | ice->pm_suspend_enabled = 1; | 1146 | ice->pm_suspend_enabled = 1; |
| 1147 | #endif | 1147 | #endif |
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index cd553f592e2d..ea4b706c8d63 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c | |||
| @@ -1541,6 +1541,26 @@ static int __devinit snd_intel8x0_pcm1(struct intel8x0 *chip, int device, | |||
| 1541 | snd_dma_pci_data(chip->pci), | 1541 | snd_dma_pci_data(chip->pci), |
| 1542 | rec->prealloc_size, rec->prealloc_max_size); | 1542 | rec->prealloc_size, rec->prealloc_max_size); |
| 1543 | 1543 | ||
| 1544 | if (rec->ac97_idx == ICHD_PCMOUT && rec->playback_ops) { | ||
| 1545 | struct snd_pcm_chmap *chmap; | ||
| 1546 | int chs = 2; | ||
| 1547 | if (rec->ac97_idx == ICHD_PCMOUT) { | ||
| 1548 | if (chip->multi8) | ||
| 1549 | chs = 8; | ||
| 1550 | else if (chip->multi6) | ||
| 1551 | chs = 6; | ||
| 1552 | else if (chip->multi4) | ||
| 1553 | chs = 4; | ||
| 1554 | } | ||
| 1555 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
| 1556 | snd_pcm_alt_chmaps, chs, 0, | ||
| 1557 | &chmap); | ||
| 1558 | if (err < 0) | ||
| 1559 | return err; | ||
| 1560 | chmap->channel_mask = SND_PCM_CHMAP_MASK_2468; | ||
| 1561 | chip->ac97[0]->chmaps[SNDRV_PCM_STREAM_PLAYBACK] = chmap; | ||
| 1562 | } | ||
| 1563 | |||
| 1544 | return 0; | 1564 | return 0; |
| 1545 | } | 1565 | } |
| 1546 | 1566 | ||
| @@ -2206,7 +2226,7 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, | |||
| 2206 | case DEVICE_INTEL_ICH4: | 2226 | case DEVICE_INTEL_ICH4: |
| 2207 | chip->spdif_idx = ICHD_SPBAR; | 2227 | chip->spdif_idx = ICHD_SPBAR; |
| 2208 | break; | 2228 | break; |
| 2209 | }; | 2229 | } |
| 2210 | } | 2230 | } |
| 2211 | 2231 | ||
| 2212 | chip->in_ac97_init = 1; | 2232 | chip->in_ac97_init = 1; |
| @@ -2620,7 +2640,7 @@ static int snd_intel8x0_free(struct intel8x0 *chip) | |||
| 2620 | return 0; | 2640 | return 0; |
| 2621 | } | 2641 | } |
| 2622 | 2642 | ||
| 2623 | #ifdef CONFIG_PM | 2643 | #ifdef CONFIG_PM_SLEEP |
| 2624 | /* | 2644 | /* |
| 2625 | * power management | 2645 | * power management |
| 2626 | */ | 2646 | */ |
| @@ -2741,7 +2761,7 @@ static SIMPLE_DEV_PM_OPS(intel8x0_pm, intel8x0_suspend, intel8x0_resume); | |||
| 2741 | #define INTEL8X0_PM_OPS &intel8x0_pm | 2761 | #define INTEL8X0_PM_OPS &intel8x0_pm |
| 2742 | #else | 2762 | #else |
| 2743 | #define INTEL8X0_PM_OPS NULL | 2763 | #define INTEL8X0_PM_OPS NULL |
| 2744 | #endif /* CONFIG_PM */ | 2764 | #endif /* CONFIG_PM_SLEEP */ |
| 2745 | 2765 | ||
| 2746 | #define INTEL8X0_TESTBUF_SIZE 32768 /* enough large for one shot */ | 2766 | #define INTEL8X0_TESTBUF_SIZE 32768 /* enough large for one shot */ |
| 2747 | 2767 | ||
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c index da44bb3f8e7a..4d551736531e 100644 --- a/sound/pci/intel8x0m.c +++ b/sound/pci/intel8x0m.c | |||
| @@ -1008,7 +1008,7 @@ static int snd_intel8x0m_free(struct intel8x0m *chip) | |||
| 1008 | return 0; | 1008 | return 0; |
| 1009 | } | 1009 | } |
| 1010 | 1010 | ||
| 1011 | #ifdef CONFIG_PM | 1011 | #ifdef CONFIG_PM_SLEEP |
| 1012 | /* | 1012 | /* |
| 1013 | * power management | 1013 | * power management |
| 1014 | */ | 1014 | */ |
| @@ -1067,7 +1067,7 @@ static SIMPLE_DEV_PM_OPS(intel8x0m_pm, intel8x0m_suspend, intel8x0m_resume); | |||
| 1067 | #define INTEL8X0M_PM_OPS &intel8x0m_pm | 1067 | #define INTEL8X0M_PM_OPS &intel8x0m_pm |
| 1068 | #else | 1068 | #else |
| 1069 | #define INTEL8X0M_PM_OPS NULL | 1069 | #define INTEL8X0M_PM_OPS NULL |
| 1070 | #endif /* CONFIG_PM */ | 1070 | #endif /* CONFIG_PM_SLEEP */ |
| 1071 | 1071 | ||
| 1072 | #ifdef CONFIG_PROC_FS | 1072 | #ifdef CONFIG_PROC_FS |
| 1073 | static void snd_intel8x0m_proc_read(struct snd_info_entry * entry, | 1073 | static void snd_intel8x0m_proc_read(struct snd_info_entry * entry, |
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c index e69ce5f9c31e..8a67ce95f246 100644 --- a/sound/pci/korg1212/korg1212.c +++ b/sound/pci/korg1212/korg1212.c | |||
| @@ -196,8 +196,8 @@ enum MonitorModeSelector { | |||
| 196 | #define K1212_ADAT_BUF_SIZE (K1212_ADAT_CHANNELS * 2 * kPlayBufferFrames * kNumBuffers) | 196 | #define K1212_ADAT_BUF_SIZE (K1212_ADAT_CHANNELS * 2 * kPlayBufferFrames * kNumBuffers) |
| 197 | #define K1212_MAX_BUF_SIZE (K1212_ANALOG_BUF_SIZE + K1212_ADAT_BUF_SIZE) | 197 | #define K1212_MAX_BUF_SIZE (K1212_ANALOG_BUF_SIZE + K1212_ADAT_BUF_SIZE) |
| 198 | 198 | ||
| 199 | #define k1212MinADCSens 0x7f | 199 | #define k1212MinADCSens 0x00 |
| 200 | #define k1212MaxADCSens 0x00 | 200 | #define k1212MaxADCSens 0x7f |
| 201 | #define k1212MaxVolume 0x7fff | 201 | #define k1212MaxVolume 0x7fff |
| 202 | #define k1212MaxWaveVolume 0xffff | 202 | #define k1212MaxWaveVolume 0xffff |
| 203 | #define k1212MinVolume 0x0000 | 203 | #define k1212MinVolume 0x0000 |
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c index c85d1ffcc955..eb3cd3a4315e 100644 --- a/sound/pci/maestro3.c +++ b/sound/pci/maestro3.c | |||
| @@ -789,7 +789,7 @@ struct snd_m3 { | |||
| 789 | 789 | ||
| 790 | unsigned int in_suspend; | 790 | unsigned int in_suspend; |
| 791 | 791 | ||
| 792 | #ifdef CONFIG_PM | 792 | #ifdef CONFIG_PM_SLEEP |
| 793 | u16 *suspend_mem; | 793 | u16 *suspend_mem; |
| 794 | #endif | 794 | #endif |
| 795 | 795 | ||
| @@ -2368,7 +2368,7 @@ static int snd_m3_free(struct snd_m3 *chip) | |||
| 2368 | outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */ | 2368 | outw(0, chip->iobase + HOST_INT_CTRL); /* disable ints */ |
| 2369 | } | 2369 | } |
| 2370 | 2370 | ||
| 2371 | #ifdef CONFIG_PM | 2371 | #ifdef CONFIG_PM_SLEEP |
| 2372 | vfree(chip->suspend_mem); | 2372 | vfree(chip->suspend_mem); |
| 2373 | #endif | 2373 | #endif |
| 2374 | 2374 | ||
| @@ -2390,7 +2390,7 @@ static int snd_m3_free(struct snd_m3 *chip) | |||
| 2390 | /* | 2390 | /* |
| 2391 | * APM support | 2391 | * APM support |
| 2392 | */ | 2392 | */ |
| 2393 | #ifdef CONFIG_PM | 2393 | #ifdef CONFIG_PM_SLEEP |
| 2394 | static int m3_suspend(struct device *dev) | 2394 | static int m3_suspend(struct device *dev) |
| 2395 | { | 2395 | { |
| 2396 | struct pci_dev *pci = to_pci_dev(dev); | 2396 | struct pci_dev *pci = to_pci_dev(dev); |
| @@ -2485,7 +2485,7 @@ static SIMPLE_DEV_PM_OPS(m3_pm, m3_suspend, m3_resume); | |||
| 2485 | #define M3_PM_OPS &m3_pm | 2485 | #define M3_PM_OPS &m3_pm |
| 2486 | #else | 2486 | #else |
| 2487 | #define M3_PM_OPS NULL | 2487 | #define M3_PM_OPS NULL |
| 2488 | #endif /* CONFIG_PM */ | 2488 | #endif /* CONFIG_PM_SLEEP */ |
| 2489 | 2489 | ||
| 2490 | #ifdef CONFIG_SND_MAESTRO3_INPUT | 2490 | #ifdef CONFIG_SND_MAESTRO3_INPUT |
| 2491 | static int __devinit snd_m3_input_register(struct snd_m3 *chip) | 2491 | static int __devinit snd_m3_input_register(struct snd_m3 *chip) |
| @@ -2656,7 +2656,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci, | |||
| 2656 | } | 2656 | } |
| 2657 | chip->irq = pci->irq; | 2657 | chip->irq = pci->irq; |
| 2658 | 2658 | ||
| 2659 | #ifdef CONFIG_PM | 2659 | #ifdef CONFIG_PM_SLEEP |
| 2660 | chip->suspend_mem = vmalloc(sizeof(u16) * (REV_B_CODE_MEMORY_LENGTH + REV_B_DATA_MEMORY_LENGTH)); | 2660 | chip->suspend_mem = vmalloc(sizeof(u16) * (REV_B_CODE_MEMORY_LENGTH + REV_B_DATA_MEMORY_LENGTH)); |
| 2661 | if (chip->suspend_mem == NULL) | 2661 | if (chip->suspend_mem == NULL) |
| 2662 | snd_printk(KERN_WARNING "can't allocate apm buffer\n"); | 2662 | snd_printk(KERN_WARNING "can't allocate apm buffer\n"); |
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c index bfbdc91e4cb3..e0f4d87555a0 100644 --- a/sound/pci/mixart/mixart_hwdep.c +++ b/sound/pci/mixart/mixart_hwdep.c | |||
| @@ -538,7 +538,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw | |||
| 538 | 538 | ||
| 539 | if ((err = snd_card_register(chip->card)) < 0) | 539 | if ((err = snd_card_register(chip->card)) < 0) |
| 540 | return err; | 540 | return err; |
| 541 | }; | 541 | } |
| 542 | 542 | ||
| 543 | snd_printdd("miXart firmware downloaded and successfully set up\n"); | 543 | snd_printdd("miXart firmware downloaded and successfully set up\n"); |
| 544 | 544 | ||
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 465cff25b146..e80e9a1e84aa 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
| @@ -1377,7 +1377,7 @@ snd_nm256_peek_for_sig(struct nm256 *chip) | |||
| 1377 | return 0; | 1377 | return 0; |
| 1378 | } | 1378 | } |
| 1379 | 1379 | ||
| 1380 | #ifdef CONFIG_PM | 1380 | #ifdef CONFIG_PM_SLEEP |
| 1381 | /* | 1381 | /* |
| 1382 | * APM event handler, so the card is properly reinitialized after a power | 1382 | * APM event handler, so the card is properly reinitialized after a power |
| 1383 | * event. | 1383 | * event. |
| @@ -1441,7 +1441,7 @@ static SIMPLE_DEV_PM_OPS(nm256_pm, nm256_suspend, nm256_resume); | |||
| 1441 | #define NM256_PM_OPS &nm256_pm | 1441 | #define NM256_PM_OPS &nm256_pm |
| 1442 | #else | 1442 | #else |
| 1443 | #define NM256_PM_OPS NULL | 1443 | #define NM256_PM_OPS NULL |
| 1444 | #endif /* CONFIG_PM */ | 1444 | #endif /* CONFIG_PM_SLEEP */ |
| 1445 | 1445 | ||
| 1446 | static int snd_nm256_free(struct nm256 *chip) | 1446 | static int snd_nm256_free(struct nm256 *chip) |
| 1447 | { | 1447 | { |
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c index 37520a2b4dcf..2becae155a48 100644 --- a/sound/pci/oxygen/oxygen.c +++ b/sound/pci/oxygen/oxygen.c | |||
| @@ -872,7 +872,7 @@ static struct pci_driver oxygen_driver = { | |||
| 872 | .id_table = oxygen_ids, | 872 | .id_table = oxygen_ids, |
| 873 | .probe = generic_oxygen_probe, | 873 | .probe = generic_oxygen_probe, |
| 874 | .remove = __devexit_p(oxygen_pci_remove), | 874 | .remove = __devexit_p(oxygen_pci_remove), |
| 875 | #ifdef CONFIG_PM | 875 | #ifdef CONFIG_PM_SLEEP |
| 876 | .driver = { | 876 | .driver = { |
| 877 | .pm = &oxygen_pci_pm, | 877 | .pm = &oxygen_pci_pm, |
| 878 | }, | 878 | }, |
diff --git a/sound/pci/oxygen/oxygen.h b/sound/pci/oxygen/oxygen.h index 7112a89fb8bd..09a24b24958b 100644 --- a/sound/pci/oxygen/oxygen.h +++ b/sound/pci/oxygen/oxygen.h | |||
| @@ -161,7 +161,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id, | |||
| 161 | ) | 161 | ) |
| 162 | ); | 162 | ); |
| 163 | void oxygen_pci_remove(struct pci_dev *pci); | 163 | void oxygen_pci_remove(struct pci_dev *pci); |
| 164 | #ifdef CONFIG_PM | 164 | #ifdef CONFIG_PM_SLEEP |
| 165 | extern const struct dev_pm_ops oxygen_pci_pm; | 165 | extern const struct dev_pm_ops oxygen_pci_pm; |
| 166 | #endif | 166 | #endif |
| 167 | void oxygen_pci_shutdown(struct pci_dev *pci); | 167 | void oxygen_pci_shutdown(struct pci_dev *pci); |
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c index e9fa2d07951d..9562dc63ba60 100644 --- a/sound/pci/oxygen/oxygen_lib.c +++ b/sound/pci/oxygen/oxygen_lib.c | |||
| @@ -726,7 +726,7 @@ void oxygen_pci_remove(struct pci_dev *pci) | |||
| 726 | } | 726 | } |
| 727 | EXPORT_SYMBOL(oxygen_pci_remove); | 727 | EXPORT_SYMBOL(oxygen_pci_remove); |
| 728 | 728 | ||
| 729 | #ifdef CONFIG_PM | 729 | #ifdef CONFIG_PM_SLEEP |
| 730 | static int oxygen_pci_suspend(struct device *dev) | 730 | static int oxygen_pci_suspend(struct device *dev) |
| 731 | { | 731 | { |
| 732 | struct pci_dev *pci = to_pci_dev(dev); | 732 | struct pci_dev *pci = to_pci_dev(dev); |
| @@ -824,7 +824,7 @@ static int oxygen_pci_resume(struct device *dev) | |||
| 824 | 824 | ||
| 825 | SIMPLE_DEV_PM_OPS(oxygen_pci_pm, oxygen_pci_suspend, oxygen_pci_resume); | 825 | SIMPLE_DEV_PM_OPS(oxygen_pci_pm, oxygen_pci_suspend, oxygen_pci_resume); |
| 826 | EXPORT_SYMBOL(oxygen_pci_pm); | 826 | EXPORT_SYMBOL(oxygen_pci_pm); |
| 827 | #endif /* CONFIG_PM */ | 827 | #endif /* CONFIG_PM_SLEEP */ |
| 828 | 828 | ||
| 829 | void oxygen_pci_shutdown(struct pci_dev *pci) | 829 | void oxygen_pci_shutdown(struct pci_dev *pci) |
| 830 | { | 830 | { |
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c index d3b606b69f3b..3d71423b23bc 100644 --- a/sound/pci/oxygen/virtuoso.c +++ b/sound/pci/oxygen/virtuoso.c | |||
| @@ -93,7 +93,7 @@ static struct pci_driver xonar_driver = { | |||
| 93 | .id_table = xonar_ids, | 93 | .id_table = xonar_ids, |
| 94 | .probe = xonar_probe, | 94 | .probe = xonar_probe, |
| 95 | .remove = __devexit_p(oxygen_pci_remove), | 95 | .remove = __devexit_p(oxygen_pci_remove), |
| 96 | #ifdef CONFIG_PM | 96 | #ifdef CONFIG_PM_SLEEP |
| 97 | .driver = { | 97 | .driver = { |
| 98 | .pm = &oxygen_pci_pm, | 98 | .pm = &oxygen_pci_pm, |
| 99 | }, | 99 | }, |
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index e3ac1f768ff6..be4f1456009a 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c | |||
| @@ -91,6 +91,14 @@ enum { | |||
| 91 | PCI_ID_PCX924E, | 91 | PCI_ID_PCX924E, |
| 92 | PCI_ID_PCX924HRMIC, | 92 | PCI_ID_PCX924HRMIC, |
| 93 | PCI_ID_PCX924E_MIC, | 93 | PCI_ID_PCX924E_MIC, |
| 94 | PCI_ID_VX442HR, | ||
| 95 | PCI_ID_PCX442HR, | ||
| 96 | PCI_ID_VX442E, | ||
| 97 | PCI_ID_PCX442E, | ||
| 98 | PCI_ID_VX822HR, | ||
| 99 | PCI_ID_PCX822HR, | ||
| 100 | PCI_ID_VX822E, | ||
| 101 | PCI_ID_PCX822E, | ||
| 94 | PCI_ID_LAST | 102 | PCI_ID_LAST |
| 95 | }; | 103 | }; |
| 96 | 104 | ||
| @@ -121,6 +129,14 @@ static DEFINE_PCI_DEVICE_TABLE(pcxhr_ids) = { | |||
| 121 | { 0x10b5, 0x9056, 0x1369, 0xbb21, 0, 0, PCI_ID_PCX924E, }, | 129 | { 0x10b5, 0x9056, 0x1369, 0xbb21, 0, 0, PCI_ID_PCX924E, }, |
| 122 | { 0x10b5, 0x9056, 0x1369, 0xbf01, 0, 0, PCI_ID_PCX924HRMIC, }, | 130 | { 0x10b5, 0x9056, 0x1369, 0xbf01, 0, 0, PCI_ID_PCX924HRMIC, }, |
| 123 | { 0x10b5, 0x9056, 0x1369, 0xbf21, 0, 0, PCI_ID_PCX924E_MIC, }, | 131 | { 0x10b5, 0x9056, 0x1369, 0xbf21, 0, 0, PCI_ID_PCX924E_MIC, }, |
| 132 | { 0x10b5, 0x9656, 0x1369, 0xd001, 0, 0, PCI_ID_VX442HR, }, | ||
| 133 | { 0x10b5, 0x9656, 0x1369, 0xd101, 0, 0, PCI_ID_PCX442HR, }, | ||
| 134 | { 0x10b5, 0x9056, 0x1369, 0xd021, 0, 0, PCI_ID_VX442E, }, | ||
| 135 | { 0x10b5, 0x9056, 0x1369, 0xd121, 0, 0, PCI_ID_PCX442E, }, | ||
| 136 | { 0x10b5, 0x9656, 0x1369, 0xd201, 0, 0, PCI_ID_VX822HR, }, | ||
| 137 | { 0x10b5, 0x9656, 0x1369, 0xd301, 0, 0, PCI_ID_PCX822HR, }, | ||
| 138 | { 0x10b5, 0x9056, 0x1369, 0xd221, 0, 0, PCI_ID_VX822E, }, | ||
| 139 | { 0x10b5, 0x9056, 0x1369, 0xd321, 0, 0, PCI_ID_PCX822E, }, | ||
| 124 | { 0, } | 140 | { 0, } |
| 125 | }; | 141 | }; |
| 126 | 142 | ||
| @@ -160,6 +176,14 @@ static struct board_parameters pcxhr_board_params[] = { | |||
| 160 | [PCI_ID_PCX924E] = { "PCX924e", 1, 1, 5, 44 }, | 176 | [PCI_ID_PCX924E] = { "PCX924e", 1, 1, 5, 44 }, |
| 161 | [PCI_ID_PCX924HRMIC] = { "PCX924HR-Mic", 1, 1, 5, 44 }, | 177 | [PCI_ID_PCX924HRMIC] = { "PCX924HR-Mic", 1, 1, 5, 44 }, |
| 162 | [PCI_ID_PCX924E_MIC] = { "PCX924e-Mic", 1, 1, 5, 44 }, | 178 | [PCI_ID_PCX924E_MIC] = { "PCX924e-Mic", 1, 1, 5, 44 }, |
| 179 | [PCI_ID_VX442HR] = { "VX442HR", 2, 2, 0, 41 }, | ||
| 180 | [PCI_ID_PCX442HR] = { "PCX442HR", 2, 2, 0, 41 }, | ||
| 181 | [PCI_ID_VX442E] = { "VX442e", 2, 2, 1, 41 }, | ||
| 182 | [PCI_ID_PCX442E] = { "PCX442e", 2, 2, 1, 41 }, | ||
| 183 | [PCI_ID_VX822HR] = { "VX822HR", 4, 1, 2, 42 }, | ||
| 184 | [PCI_ID_PCX822HR] = { "PCX822HR", 4, 1, 2, 42 }, | ||
| 185 | [PCI_ID_VX822E] = { "VX822e", 4, 1, 3, 42 }, | ||
| 186 | [PCI_ID_PCX822E] = { "PCX822e", 4, 1, 3, 42 }, | ||
| 163 | }; | 187 | }; |
| 164 | 188 | ||
| 165 | /* boards without hw AES1 and SRC onboard are all using fw_file_set==4 */ | 189 | /* boards without hw AES1 and SRC onboard are all using fw_file_set==4 */ |
diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c index ec1587cddb0c..bf207e317f71 100644 --- a/sound/pci/pcxhr/pcxhr_hwdep.c +++ b/sound/pci/pcxhr/pcxhr_hwdep.c | |||
| @@ -66,10 +66,10 @@ static int pcxhr_init_board(struct pcxhr_mgr *mgr) | |||
| 66 | err = pcxhr_send_msg(mgr, &rmh); | 66 | err = pcxhr_send_msg(mgr, &rmh); |
| 67 | if (err) | 67 | if (err) |
| 68 | return err; | 68 | return err; |
| 69 | /* test 8 or 12 phys out */ | 69 | /* test 4, 8 or 12 phys out */ |
| 70 | if ((rmh.stat[0] & MASK_FIRST_FIELD) != mgr->playback_chips * 2) | 70 | if ((rmh.stat[0] & MASK_FIRST_FIELD) < mgr->playback_chips * 2) |
| 71 | return -EINVAL; | 71 | return -EINVAL; |
| 72 | /* test 8 or 2 phys in */ | 72 | /* test 4, 8 or 2 phys in */ |
| 73 | if (((rmh.stat[0] >> (2 * FIELD_SIZE)) & MASK_FIRST_FIELD) < | 73 | if (((rmh.stat[0] >> (2 * FIELD_SIZE)) & MASK_FIRST_FIELD) < |
| 74 | mgr->capture_chips * 2) | 74 | mgr->capture_chips * 2) |
| 75 | return -EINVAL; | 75 | return -EINVAL; |
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 760ee467cd9a..7d291542c5ba 100644 --- a/sound/pci/riptide/riptide.c +++ b/sound/pci/riptide/riptide.c | |||
| @@ -464,7 +464,7 @@ struct snd_riptide { | |||
| 464 | 464 | ||
| 465 | unsigned long received_irqs; | 465 | unsigned long received_irqs; |
| 466 | unsigned long handled_irqs; | 466 | unsigned long handled_irqs; |
| 467 | #ifdef CONFIG_PM | 467 | #ifdef CONFIG_PM_SLEEP |
| 468 | int in_suspend; | 468 | int in_suspend; |
| 469 | #endif | 469 | #endif |
| 470 | }; | 470 | }; |
| @@ -1150,7 +1150,7 @@ static void riptide_handleirq(unsigned long dev_id) | |||
| 1150 | } | 1150 | } |
| 1151 | } | 1151 | } |
| 1152 | 1152 | ||
| 1153 | #ifdef CONFIG_PM | 1153 | #ifdef CONFIG_PM_SLEEP |
| 1154 | static int riptide_suspend(struct device *dev) | 1154 | static int riptide_suspend(struct device *dev) |
| 1155 | { | 1155 | { |
| 1156 | struct pci_dev *pci = to_pci_dev(dev); | 1156 | struct pci_dev *pci = to_pci_dev(dev); |
| @@ -1193,7 +1193,7 @@ static SIMPLE_DEV_PM_OPS(riptide_pm, riptide_suspend, riptide_resume); | |||
| 1193 | #define RIPTIDE_PM_OPS &riptide_pm | 1193 | #define RIPTIDE_PM_OPS &riptide_pm |
| 1194 | #else | 1194 | #else |
| 1195 | #define RIPTIDE_PM_OPS NULL | 1195 | #define RIPTIDE_PM_OPS NULL |
| 1196 | #endif /* CONFIG_PM */ | 1196 | #endif /* CONFIG_PM_SLEEP */ |
| 1197 | 1197 | ||
| 1198 | static int try_to_load_firmware(struct cmdif *cif, struct snd_riptide *chip) | 1198 | static int try_to_load_firmware(struct cmdif *cif, struct snd_riptide *chip) |
| 1199 | { | 1199 | { |
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index 805ab6e9a78f..51e43407ebc5 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c | |||
| @@ -103,7 +103,7 @@ struct voice { | |||
| 103 | * we're not doing power management, we still need to allocate a page | 103 | * we're not doing power management, we still need to allocate a page |
| 104 | * for the silence buffer. | 104 | * for the silence buffer. |
| 105 | */ | 105 | */ |
| 106 | #ifdef CONFIG_PM | 106 | #ifdef CONFIG_PM_SLEEP |
| 107 | #define SIS_SUSPEND_PAGES 4 | 107 | #define SIS_SUSPEND_PAGES 4 |
| 108 | #else | 108 | #else |
| 109 | #define SIS_SUSPEND_PAGES 1 | 109 | #define SIS_SUSPEND_PAGES 1 |
| @@ -1208,7 +1208,7 @@ static int sis_chip_init(struct sis7019 *sis) | |||
| 1208 | return 0; | 1208 | return 0; |
| 1209 | } | 1209 | } |
| 1210 | 1210 | ||
| 1211 | #ifdef CONFIG_PM | 1211 | #ifdef CONFIG_PM_SLEEP |
| 1212 | static int sis_suspend(struct device *dev) | 1212 | static int sis_suspend(struct device *dev) |
| 1213 | { | 1213 | { |
| 1214 | struct pci_dev *pci = to_pci_dev(dev); | 1214 | struct pci_dev *pci = to_pci_dev(dev); |
| @@ -1305,7 +1305,7 @@ static SIMPLE_DEV_PM_OPS(sis_pm, sis_suspend, sis_resume); | |||
| 1305 | #define SIS_PM_OPS &sis_pm | 1305 | #define SIS_PM_OPS &sis_pm |
| 1306 | #else | 1306 | #else |
| 1307 | #define SIS_PM_OPS NULL | 1307 | #define SIS_PM_OPS NULL |
| 1308 | #endif /* CONFIG_PM */ | 1308 | #endif /* CONFIG_PM_SLEEP */ |
| 1309 | 1309 | ||
| 1310 | static int sis_alloc_suspend(struct sis7019 *sis) | 1310 | static int sis_alloc_suspend(struct sis7019 *sis) |
| 1311 | { | 1311 | { |
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index d36e6ca147e1..8a6f1f76e870 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c | |||
| @@ -177,7 +177,7 @@ static struct pci_driver trident_driver = { | |||
| 177 | .id_table = snd_trident_ids, | 177 | .id_table = snd_trident_ids, |
| 178 | .probe = snd_trident_probe, | 178 | .probe = snd_trident_probe, |
| 179 | .remove = __devexit_p(snd_trident_remove), | 179 | .remove = __devexit_p(snd_trident_remove), |
| 180 | #ifdef CONFIG_PM | 180 | #ifdef CONFIG_PM_SLEEP |
| 181 | .driver = { | 181 | .driver = { |
| 182 | .pm = &snd_trident_pm, | 182 | .pm = &snd_trident_pm, |
| 183 | }, | 183 | }, |
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c index 94011dcae731..06b10d1a76e5 100644 --- a/sound/pci/trident/trident_main.c +++ b/sound/pci/trident/trident_main.c | |||
| @@ -3919,7 +3919,7 @@ static void snd_trident_clear_voices(struct snd_trident * trident, unsigned shor | |||
| 3919 | } | 3919 | } |
| 3920 | } | 3920 | } |
| 3921 | 3921 | ||
| 3922 | #ifdef CONFIG_PM | 3922 | #ifdef CONFIG_PM_SLEEP |
| 3923 | static int snd_trident_suspend(struct device *dev) | 3923 | static int snd_trident_suspend(struct device *dev) |
| 3924 | { | 3924 | { |
| 3925 | struct pci_dev *pci = to_pci_dev(dev); | 3925 | struct pci_dev *pci = to_pci_dev(dev); |
| @@ -3983,4 +3983,4 @@ static int snd_trident_resume(struct device *dev) | |||
| 3983 | } | 3983 | } |
| 3984 | 3984 | ||
| 3985 | SIMPLE_DEV_PM_OPS(snd_trident_pm, snd_trident_suspend, snd_trident_resume); | 3985 | SIMPLE_DEV_PM_OPS(snd_trident_pm, snd_trident_suspend, snd_trident_resume); |
| 3986 | #endif /* CONFIG_PM */ | 3986 | #endif /* CONFIG_PM_SLEEP */ |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 0eb7245dd362..f0b4efdb483c 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
| @@ -362,7 +362,7 @@ struct via82xx { | |||
| 362 | 362 | ||
| 363 | unsigned char old_legacy; | 363 | unsigned char old_legacy; |
| 364 | unsigned char old_legacy_cfg; | 364 | unsigned char old_legacy_cfg; |
| 365 | #ifdef CONFIG_PM | 365 | #ifdef CONFIG_PM_SLEEP |
| 366 | unsigned char legacy_saved; | 366 | unsigned char legacy_saved; |
| 367 | unsigned char legacy_cfg_saved; | 367 | unsigned char legacy_cfg_saved; |
| 368 | unsigned char spdif_ctrl_saved; | 368 | unsigned char spdif_ctrl_saved; |
| @@ -1440,6 +1440,7 @@ static void init_viadev(struct via82xx *chip, int idx, unsigned int reg_offset, | |||
| 1440 | static int __devinit snd_via8233_pcm_new(struct via82xx *chip) | 1440 | static int __devinit snd_via8233_pcm_new(struct via82xx *chip) |
| 1441 | { | 1441 | { |
| 1442 | struct snd_pcm *pcm; | 1442 | struct snd_pcm *pcm; |
| 1443 | struct snd_pcm_chmap *chmap; | ||
| 1443 | int i, err; | 1444 | int i, err; |
| 1444 | 1445 | ||
| 1445 | chip->playback_devno = 0; /* x 4 */ | 1446 | chip->playback_devno = 0; /* x 4 */ |
| @@ -1467,6 +1468,12 @@ static int __devinit snd_via8233_pcm_new(struct via82xx *chip) | |||
| 1467 | snd_dma_pci_data(chip->pci), | 1468 | snd_dma_pci_data(chip->pci), |
| 1468 | 64*1024, VIA_MAX_BUFSIZE); | 1469 | 64*1024, VIA_MAX_BUFSIZE); |
| 1469 | 1470 | ||
| 1471 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
| 1472 | snd_pcm_std_chmaps, 2, 0, | ||
| 1473 | &chmap); | ||
| 1474 | if (err < 0) | ||
| 1475 | return err; | ||
| 1476 | |||
| 1470 | /* PCM #1: multi-channel playback and 2nd capture */ | 1477 | /* PCM #1: multi-channel playback and 2nd capture */ |
| 1471 | err = snd_pcm_new(chip->card, chip->card->shortname, 1, 1, 1, &pcm); | 1478 | err = snd_pcm_new(chip->card, chip->card->shortname, 1, 1, 1, &pcm); |
| 1472 | if (err < 0) | 1479 | if (err < 0) |
| @@ -1484,6 +1491,14 @@ static int __devinit snd_via8233_pcm_new(struct via82xx *chip) | |||
| 1484 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, | 1491 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG, |
| 1485 | snd_dma_pci_data(chip->pci), | 1492 | snd_dma_pci_data(chip->pci), |
| 1486 | 64*1024, VIA_MAX_BUFSIZE); | 1493 | 64*1024, VIA_MAX_BUFSIZE); |
| 1494 | |||
| 1495 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
| 1496 | snd_pcm_alt_chmaps, 6, 0, | ||
| 1497 | &chmap); | ||
| 1498 | if (err < 0) | ||
| 1499 | return err; | ||
| 1500 | chip->ac97->chmaps[SNDRV_PCM_STREAM_PLAYBACK] = chmap; | ||
| 1501 | |||
| 1487 | return 0; | 1502 | return 0; |
| 1488 | } | 1503 | } |
| 1489 | 1504 | ||
| @@ -1493,6 +1508,7 @@ static int __devinit snd_via8233_pcm_new(struct via82xx *chip) | |||
| 1493 | static int __devinit snd_via8233a_pcm_new(struct via82xx *chip) | 1508 | static int __devinit snd_via8233a_pcm_new(struct via82xx *chip) |
| 1494 | { | 1509 | { |
| 1495 | struct snd_pcm *pcm; | 1510 | struct snd_pcm *pcm; |
| 1511 | struct snd_pcm_chmap *chmap; | ||
| 1496 | int err; | 1512 | int err; |
| 1497 | 1513 | ||
| 1498 | chip->multi_devno = 0; | 1514 | chip->multi_devno = 0; |
| @@ -1519,6 +1535,13 @@ static int __devinit snd_via8233a_pcm_new(struct via82xx *chip) | |||
| 1519 | snd_dma_pci_data(chip->pci), | 1535 | snd_dma_pci_data(chip->pci), |
| 1520 | 64*1024, VIA_MAX_BUFSIZE); | 1536 | 64*1024, VIA_MAX_BUFSIZE); |
| 1521 | 1537 | ||
| 1538 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
| 1539 | snd_pcm_alt_chmaps, 6, 0, | ||
| 1540 | &chmap); | ||
| 1541 | if (err < 0) | ||
| 1542 | return err; | ||
| 1543 | chip->ac97->chmaps[SNDRV_PCM_STREAM_PLAYBACK] = chmap; | ||
| 1544 | |||
| 1522 | /* SPDIF supported? */ | 1545 | /* SPDIF supported? */ |
| 1523 | if (! ac97_can_spdif(chip->ac97)) | 1546 | if (! ac97_can_spdif(chip->ac97)) |
| 1524 | return 0; | 1547 | return 0; |
| @@ -2038,7 +2061,7 @@ static int __devinit snd_via686_init_misc(struct via82xx *chip) | |||
| 2038 | if (mpu_port >= 0x200) { /* force MIDI */ | 2061 | if (mpu_port >= 0x200) { /* force MIDI */ |
| 2039 | mpu_port &= 0xfffc; | 2062 | mpu_port &= 0xfffc; |
| 2040 | pci_write_config_dword(chip->pci, 0x18, mpu_port | 0x01); | 2063 | pci_write_config_dword(chip->pci, 0x18, mpu_port | 0x01); |
| 2041 | #ifdef CONFIG_PM | 2064 | #ifdef CONFIG_PM_SLEEP |
| 2042 | chip->mpu_port_saved = mpu_port; | 2065 | chip->mpu_port_saved = mpu_port; |
| 2043 | #endif | 2066 | #endif |
| 2044 | } else { | 2067 | } else { |
| @@ -2090,7 +2113,7 @@ static int __devinit snd_via686_init_misc(struct via82xx *chip) | |||
| 2090 | 2113 | ||
| 2091 | snd_via686_create_gameport(chip, &legacy); | 2114 | snd_via686_create_gameport(chip, &legacy); |
| 2092 | 2115 | ||
| 2093 | #ifdef CONFIG_PM | 2116 | #ifdef CONFIG_PM_SLEEP |
| 2094 | chip->legacy_saved = legacy; | 2117 | chip->legacy_saved = legacy; |
| 2095 | chip->legacy_cfg_saved = legacy_cfg; | 2118 | chip->legacy_cfg_saved = legacy_cfg; |
| 2096 | #endif | 2119 | #endif |
| @@ -2238,7 +2261,7 @@ static int snd_via82xx_chip_init(struct via82xx *chip) | |||
| 2238 | return 0; | 2261 | return 0; |
| 2239 | } | 2262 | } |
| 2240 | 2263 | ||
| 2241 | #ifdef CONFIG_PM | 2264 | #ifdef CONFIG_PM_SLEEP |
| 2242 | /* | 2265 | /* |
| 2243 | * power management | 2266 | * power management |
| 2244 | */ | 2267 | */ |
| @@ -2313,7 +2336,7 @@ static SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume | |||
| 2313 | #define SND_VIA82XX_PM_OPS &snd_via82xx_pm | 2336 | #define SND_VIA82XX_PM_OPS &snd_via82xx_pm |
| 2314 | #else | 2337 | #else |
| 2315 | #define SND_VIA82XX_PM_OPS NULL | 2338 | #define SND_VIA82XX_PM_OPS NULL |
| 2316 | #endif /* CONFIG_PM */ | 2339 | #endif /* CONFIG_PM_SLEEP */ |
| 2317 | 2340 | ||
| 2318 | static int snd_via82xx_free(struct via82xx *chip) | 2341 | static int snd_via82xx_free(struct via82xx *chip) |
| 2319 | { | 2342 | { |
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index e886bc16999d..8e0efc416f22 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
| @@ -1019,7 +1019,7 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) | |||
| 1019 | return 0; | 1019 | return 0; |
| 1020 | } | 1020 | } |
| 1021 | 1021 | ||
| 1022 | #ifdef CONFIG_PM | 1022 | #ifdef CONFIG_PM_SLEEP |
| 1023 | /* | 1023 | /* |
| 1024 | * power management | 1024 | * power management |
| 1025 | */ | 1025 | */ |
| @@ -1076,7 +1076,7 @@ static SIMPLE_DEV_PM_OPS(snd_via82xx_pm, snd_via82xx_suspend, snd_via82xx_resume | |||
| 1076 | #define SND_VIA82XX_PM_OPS &snd_via82xx_pm | 1076 | #define SND_VIA82XX_PM_OPS &snd_via82xx_pm |
| 1077 | #else | 1077 | #else |
| 1078 | #define SND_VIA82XX_PM_OPS NULL | 1078 | #define SND_VIA82XX_PM_OPS NULL |
| 1079 | #endif /* CONFIG_PM */ | 1079 | #endif /* CONFIG_PM_SLEEP */ |
| 1080 | 1080 | ||
| 1081 | static int snd_via82xx_free(struct via82xx_modem *chip) | 1081 | static int snd_via82xx_free(struct via82xx_modem *chip) |
| 1082 | { | 1082 | { |
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c index b89e7a86e9d8..fdfbaf857233 100644 --- a/sound/pci/vx222/vx222.c +++ b/sound/pci/vx222/vx222.c | |||
| @@ -257,7 +257,7 @@ static void __devexit snd_vx222_remove(struct pci_dev *pci) | |||
| 257 | pci_set_drvdata(pci, NULL); | 257 | pci_set_drvdata(pci, NULL); |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | #ifdef CONFIG_PM | 260 | #ifdef CONFIG_PM_SLEEP |
| 261 | static int snd_vx222_suspend(struct device *dev) | 261 | static int snd_vx222_suspend(struct device *dev) |
| 262 | { | 262 | { |
| 263 | struct pci_dev *pci = to_pci_dev(dev); | 263 | struct pci_dev *pci = to_pci_dev(dev); |
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c index 4810356b97ba..e01fe34db9ec 100644 --- a/sound/pci/ymfpci/ymfpci.c +++ b/sound/pci/ymfpci/ymfpci.c | |||
| @@ -355,7 +355,7 @@ static struct pci_driver ymfpci_driver = { | |||
| 355 | .id_table = snd_ymfpci_ids, | 355 | .id_table = snd_ymfpci_ids, |
| 356 | .probe = snd_card_ymfpci_probe, | 356 | .probe = snd_card_ymfpci_probe, |
| 357 | .remove = __devexit_p(snd_card_ymfpci_remove), | 357 | .remove = __devexit_p(snd_card_ymfpci_remove), |
| 358 | #ifdef CONFIG_PM | 358 | #ifdef CONFIG_PM_SLEEP |
| 359 | .driver = { | 359 | .driver = { |
| 360 | .pm = &snd_ymfpci_pm, | 360 | .pm = &snd_ymfpci_pm, |
| 361 | }, | 361 | }, |
diff --git a/sound/pci/ymfpci/ymfpci.h b/sound/pci/ymfpci/ymfpci.h index bddc4052286b..4631a2348915 100644 --- a/sound/pci/ymfpci/ymfpci.h +++ b/sound/pci/ymfpci/ymfpci.h | |||
| @@ -363,7 +363,7 @@ struct snd_ymfpci { | |||
| 363 | const struct firmware *dsp_microcode; | 363 | const struct firmware *dsp_microcode; |
| 364 | const struct firmware *controller_microcode; | 364 | const struct firmware *controller_microcode; |
| 365 | 365 | ||
| 366 | #ifdef CONFIG_PM | 366 | #ifdef CONFIG_PM_SLEEP |
| 367 | u32 *saved_regs; | 367 | u32 *saved_regs; |
| 368 | u32 saved_ydsxgr_mode; | 368 | u32 saved_ydsxgr_mode; |
| 369 | u16 saved_dsxg_legacy; | 369 | u16 saved_dsxg_legacy; |
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c index 62b23635b754..3a6f03f9b02f 100644 --- a/sound/pci/ymfpci/ymfpci_main.c +++ b/sound/pci/ymfpci/ymfpci_main.c | |||
| @@ -1166,6 +1166,11 @@ int __devinit snd_ymfpci_pcm(struct snd_ymfpci *chip, int device, struct snd_pcm | |||
| 1166 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1166 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
| 1167 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); | 1167 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); |
| 1168 | 1168 | ||
| 1169 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
| 1170 | snd_pcm_std_chmaps, 2, 0, NULL); | ||
| 1171 | if (err < 0) | ||
| 1172 | return err; | ||
| 1173 | |||
| 1169 | if (rpcm) | 1174 | if (rpcm) |
| 1170 | *rpcm = pcm; | 1175 | *rpcm = pcm; |
| 1171 | return 0; | 1176 | return 0; |
| @@ -1257,6 +1262,14 @@ static struct snd_pcm_ops snd_ymfpci_playback_4ch_ops = { | |||
| 1257 | .pointer = snd_ymfpci_playback_pointer, | 1262 | .pointer = snd_ymfpci_playback_pointer, |
| 1258 | }; | 1263 | }; |
| 1259 | 1264 | ||
| 1265 | static const struct snd_pcm_chmap_elem surround_map[] = { | ||
| 1266 | { .channels = 1, | ||
| 1267 | .map = { SNDRV_CHMAP_MONO } }, | ||
| 1268 | { .channels = 2, | ||
| 1269 | .map = { SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } }, | ||
| 1270 | { } | ||
| 1271 | }; | ||
| 1272 | |||
| 1260 | int __devinit snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm) | 1273 | int __devinit snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd_pcm ** rpcm) |
| 1261 | { | 1274 | { |
| 1262 | struct snd_pcm *pcm; | 1275 | struct snd_pcm *pcm; |
| @@ -1278,6 +1291,11 @@ int __devinit snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device, struct snd | |||
| 1278 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | 1291 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
| 1279 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); | 1292 | snd_dma_pci_data(chip->pci), 64*1024, 256*1024); |
| 1280 | 1293 | ||
| 1294 | err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
| 1295 | surround_map, 2, 0, NULL); | ||
| 1296 | if (err < 0) | ||
| 1297 | return err; | ||
| 1298 | |||
| 1281 | if (rpcm) | 1299 | if (rpcm) |
| 1282 | *rpcm = pcm; | 1300 | *rpcm = pcm; |
| 1283 | return 0; | 1301 | return 0; |
| @@ -2242,7 +2260,7 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip) | |||
| 2242 | pci_set_power_state(chip->pci, 3); | 2260 | pci_set_power_state(chip->pci, 3); |
| 2243 | #endif | 2261 | #endif |
| 2244 | 2262 | ||
| 2245 | #ifdef CONFIG_PM | 2263 | #ifdef CONFIG_PM_SLEEP |
| 2246 | vfree(chip->saved_regs); | 2264 | vfree(chip->saved_regs); |
| 2247 | #endif | 2265 | #endif |
| 2248 | if (chip->irq >= 0) | 2266 | if (chip->irq >= 0) |
| @@ -2272,7 +2290,7 @@ static int snd_ymfpci_dev_free(struct snd_device *device) | |||
| 2272 | return snd_ymfpci_free(chip); | 2290 | return snd_ymfpci_free(chip); |
| 2273 | } | 2291 | } |
| 2274 | 2292 | ||
| 2275 | #ifdef CONFIG_PM | 2293 | #ifdef CONFIG_PM_SLEEP |
| 2276 | static int saved_regs_index[] = { | 2294 | static int saved_regs_index[] = { |
| 2277 | /* spdif */ | 2295 | /* spdif */ |
| 2278 | YDSXGR_SPDIFOUTCTRL, | 2296 | YDSXGR_SPDIFOUTCTRL, |
| @@ -2374,7 +2392,7 @@ static int snd_ymfpci_resume(struct device *dev) | |||
| 2374 | } | 2392 | } |
| 2375 | 2393 | ||
| 2376 | SIMPLE_DEV_PM_OPS(snd_ymfpci_pm, snd_ymfpci_suspend, snd_ymfpci_resume); | 2394 | SIMPLE_DEV_PM_OPS(snd_ymfpci_pm, snd_ymfpci_suspend, snd_ymfpci_resume); |
| 2377 | #endif /* CONFIG_PM */ | 2395 | #endif /* CONFIG_PM_SLEEP */ |
| 2378 | 2396 | ||
| 2379 | int __devinit snd_ymfpci_create(struct snd_card *card, | 2397 | int __devinit snd_ymfpci_create(struct snd_card *card, |
| 2380 | struct pci_dev * pci, | 2398 | struct pci_dev * pci, |
| @@ -2452,7 +2470,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card, | |||
| 2452 | return err; | 2470 | return err; |
| 2453 | } | 2471 | } |
| 2454 | 2472 | ||
| 2455 | #ifdef CONFIG_PM | 2473 | #ifdef CONFIG_PM_SLEEP |
| 2456 | chip->saved_regs = vmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32)); | 2474 | chip->saved_regs = vmalloc(YDSXGR_NUM_SAVED_REGS * sizeof(u32)); |
| 2457 | if (chip->saved_regs == NULL) { | 2475 | if (chip->saved_regs == NULL) { |
| 2458 | snd_ymfpci_free(chip); | 2476 | snd_ymfpci_free(chip); |
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index c5de0a84566f..5da8ca7aee05 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
| @@ -9,6 +9,7 @@ menuconfig SND_SOC | |||
| 9 | select SND_JACK if INPUT=y || INPUT=SND | 9 | select SND_JACK if INPUT=y || INPUT=SND |
| 10 | select REGMAP_I2C if I2C | 10 | select REGMAP_I2C if I2C |
| 11 | select REGMAP_SPI if SPI_MASTER | 11 | select REGMAP_SPI if SPI_MASTER |
| 12 | select SND_COMPRESS_OFFLOAD | ||
| 12 | ---help--- | 13 | ---help--- |
| 13 | 14 | ||
| 14 | If you want ASoC support, you should say Y here and also to the | 15 | If you want ASoC support, you should say Y here and also to the |
| @@ -32,9 +33,9 @@ config SND_SOC_DMAENGINE_PCM | |||
| 32 | source "sound/soc/atmel/Kconfig" | 33 | source "sound/soc/atmel/Kconfig" |
| 33 | source "sound/soc/au1x/Kconfig" | 34 | source "sound/soc/au1x/Kconfig" |
| 34 | source "sound/soc/blackfin/Kconfig" | 35 | source "sound/soc/blackfin/Kconfig" |
| 36 | source "sound/soc/cirrus/Kconfig" | ||
| 35 | source "sound/soc/davinci/Kconfig" | 37 | source "sound/soc/davinci/Kconfig" |
| 36 | source "sound/soc/dwc/Kconfig" | 38 | source "sound/soc/dwc/Kconfig" |
| 37 | source "sound/soc/ep93xx/Kconfig" | ||
| 38 | source "sound/soc/fsl/Kconfig" | 39 | source "sound/soc/fsl/Kconfig" |
| 39 | source "sound/soc/jz4740/Kconfig" | 40 | source "sound/soc/jz4740/Kconfig" |
| 40 | source "sound/soc/nuc900/Kconfig" | 41 | source "sound/soc/nuc900/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 00a555a743b6..bcbf1d00aa85 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o | 1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o |
| 2 | snd-soc-core-objs += soc-pcm.o soc-io.o | 2 | snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o |
| 3 | 3 | ||
| 4 | snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o | 4 | snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o |
| 5 | obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o | 5 | obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o |
| @@ -10,9 +10,9 @@ obj-$(CONFIG_SND_SOC) += generic/ | |||
| 10 | obj-$(CONFIG_SND_SOC) += atmel/ | 10 | obj-$(CONFIG_SND_SOC) += atmel/ |
| 11 | obj-$(CONFIG_SND_SOC) += au1x/ | 11 | obj-$(CONFIG_SND_SOC) += au1x/ |
| 12 | obj-$(CONFIG_SND_SOC) += blackfin/ | 12 | obj-$(CONFIG_SND_SOC) += blackfin/ |
| 13 | obj-$(CONFIG_SND_SOC) += cirrus/ | ||
| 13 | obj-$(CONFIG_SND_SOC) += davinci/ | 14 | obj-$(CONFIG_SND_SOC) += davinci/ |
| 14 | obj-$(CONFIG_SND_SOC) += dwc/ | 15 | obj-$(CONFIG_SND_SOC) += dwc/ |
| 15 | obj-$(CONFIG_SND_SOC) += ep93xx/ | ||
| 16 | obj-$(CONFIG_SND_SOC) += fsl/ | 16 | obj-$(CONFIG_SND_SOC) += fsl/ |
| 17 | obj-$(CONFIG_SND_SOC) += jz4740/ | 17 | obj-$(CONFIG_SND_SOC) += jz4740/ |
| 18 | obj-$(CONFIG_SND_SOC) += mid-x86/ | 18 | obj-$(CONFIG_SND_SOC) += mid-x86/ |
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c index d542d4063771..16b9c9efd19a 100644 --- a/sound/soc/blackfin/bf5xx-ad1836.c +++ b/sound/soc/blackfin/bf5xx-ad1836.c | |||
| @@ -59,62 +59,63 @@ static struct snd_soc_ops bf5xx_ad1836_ops = { | |||
| 59 | #define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ | 59 | #define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ |
| 60 | SND_SOC_DAIFMT_CBM_CFM) | 60 | SND_SOC_DAIFMT_CBM_CFM) |
| 61 | 61 | ||
| 62 | static struct snd_soc_dai_link bf5xx_ad1836_dai[] = { | 62 | static struct snd_soc_dai_link bf5xx_ad1836_dai = { |
| 63 | { | 63 | .name = "ad1836", |
| 64 | .name = "ad1836", | 64 | .stream_name = "AD1836", |
| 65 | .stream_name = "AD1836", | 65 | .codec_dai_name = "ad1836-hifi", |
| 66 | .cpu_dai_name = "bfin-tdm.0", | 66 | .platform_name = "bfin-tdm-pcm-audio", |
| 67 | .codec_dai_name = "ad1836-hifi", | 67 | .ops = &bf5xx_ad1836_ops, |
| 68 | .platform_name = "bfin-tdm-pcm-audio", | 68 | .dai_fmt = BF5XX_AD1836_DAIFMT, |
| 69 | .codec_name = "spi0.4", | ||
| 70 | .ops = &bf5xx_ad1836_ops, | ||
| 71 | .dai_fmt = BF5XX_AD1836_DAIFMT, | ||
| 72 | }, | ||
| 73 | { | ||
| 74 | .name = "ad1836", | ||
| 75 | .stream_name = "AD1836", | ||
| 76 | .cpu_dai_name = "bfin-tdm.1", | ||
| 77 | .codec_dai_name = "ad1836-hifi", | ||
| 78 | .platform_name = "bfin-tdm-pcm-audio", | ||
| 79 | .codec_name = "spi0.4", | ||
| 80 | .ops = &bf5xx_ad1836_ops, | ||
| 81 | .dai_fmt = BF5XX_AD1836_DAIFMT, | ||
| 82 | }, | ||
| 83 | }; | 69 | }; |
| 84 | 70 | ||
| 85 | static struct snd_soc_card bf5xx_ad1836 = { | 71 | static struct snd_soc_card bf5xx_ad1836 = { |
| 86 | .name = "bfin-ad1836", | 72 | .name = "bfin-ad1836", |
| 87 | .owner = THIS_MODULE, | 73 | .owner = THIS_MODULE, |
| 88 | .dai_link = &bf5xx_ad1836_dai[CONFIG_SND_BF5XX_SPORT_NUM], | 74 | .dai_link = &bf5xx_ad1836_dai, |
| 89 | .num_links = 1, | 75 | .num_links = 1, |
| 90 | }; | 76 | }; |
| 91 | 77 | ||
| 92 | static struct platform_device *bfxx_ad1836_snd_device; | 78 | static __devinit int bf5xx_ad1836_driver_probe(struct platform_device *pdev) |
| 93 | |||
| 94 | static int __init bf5xx_ad1836_init(void) | ||
| 95 | { | 79 | { |
| 80 | struct snd_soc_card *card = &bf5xx_ad1836; | ||
| 81 | const char **link_name; | ||
| 96 | int ret; | 82 | int ret; |
| 97 | 83 | ||
| 98 | bfxx_ad1836_snd_device = platform_device_alloc("soc-audio", -1); | 84 | link_name = pdev->dev.platform_data; |
| 99 | if (!bfxx_ad1836_snd_device) | 85 | if (!link_name) { |
| 100 | return -ENOMEM; | 86 | dev_err(&pdev->dev, "No platform data supplied\n"); |
| 87 | return -EINVAL; | ||
| 88 | } | ||
| 89 | bf5xx_ad1836_dai.cpu_dai_name = link_name[0]; | ||
| 90 | bf5xx_ad1836_dai.codec_name = link_name[1]; | ||
| 101 | 91 | ||
| 102 | platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836); | 92 | card->dev = &pdev->dev; |
| 103 | ret = platform_device_add(bfxx_ad1836_snd_device); | 93 | platform_set_drvdata(pdev, card); |
| 104 | 94 | ||
| 95 | ret = snd_soc_register_card(card); | ||
| 105 | if (ret) | 96 | if (ret) |
| 106 | platform_device_put(bfxx_ad1836_snd_device); | 97 | dev_err(&pdev->dev, "Failed to register card\n"); |
| 107 | |||
| 108 | return ret; | 98 | return ret; |
| 109 | } | 99 | } |
| 110 | 100 | ||
| 111 | static void __exit bf5xx_ad1836_exit(void) | 101 | static int __devexit bf5xx_ad1836_driver_remove(struct platform_device *pdev) |
| 112 | { | 102 | { |
| 113 | platform_device_unregister(bfxx_ad1836_snd_device); | 103 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 104 | |||
| 105 | snd_soc_unregister_card(card); | ||
| 106 | return 0; | ||
| 114 | } | 107 | } |
| 115 | 108 | ||
| 116 | module_init(bf5xx_ad1836_init); | 109 | static struct platform_driver bf5xx_ad1836_driver = { |
| 117 | module_exit(bf5xx_ad1836_exit); | 110 | .driver = { |
| 111 | .name = "bfin-snd-ad1836", | ||
| 112 | .owner = THIS_MODULE, | ||
| 113 | .pm = &snd_soc_pm_ops, | ||
| 114 | }, | ||
| 115 | .probe = bf5xx_ad1836_driver_probe, | ||
| 116 | .remove = __devexit_p(bf5xx_ad1836_driver_remove), | ||
| 117 | }; | ||
| 118 | module_platform_driver(bf5xx_ad1836_driver); | ||
| 118 | 119 | ||
| 119 | /* Module information */ | 120 | /* Module information */ |
| 120 | MODULE_AUTHOR("Barry Song"); | 121 | MODULE_AUTHOR("Barry Song"); |
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/cirrus/Kconfig index 88143db7e753..88143db7e753 100644 --- a/sound/soc/ep93xx/Kconfig +++ b/sound/soc/cirrus/Kconfig | |||
diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/cirrus/Makefile index 5514146cbdf0..5514146cbdf0 100644 --- a/sound/soc/ep93xx/Makefile +++ b/sound/soc/cirrus/Makefile | |||
diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/cirrus/edb93xx.c index e01cb02abd3a..e01cb02abd3a 100644 --- a/sound/soc/ep93xx/edb93xx.c +++ b/sound/soc/cirrus/edb93xx.c | |||
diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index c3521653cfd3..c3521653cfd3 100644 --- a/sound/soc/ep93xx/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c | |||
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index ac4a7515e7be..ac4a7515e7be 100644 --- a/sound/soc/ep93xx/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c | |||
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c index 665d9c94cc17..665d9c94cc17 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ b/sound/soc/cirrus/ep93xx-pcm.c | |||
diff --git a/sound/soc/ep93xx/ep93xx-pcm.h b/sound/soc/cirrus/ep93xx-pcm.h index 111e1121ecb8..111e1121ecb8 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.h +++ b/sound/soc/cirrus/ep93xx-pcm.h | |||
diff --git a/sound/soc/ep93xx/simone.c b/sound/soc/cirrus/simone.c index dd997094eb30..dd997094eb30 100644 --- a/sound/soc/ep93xx/simone.c +++ b/sound/soc/cirrus/simone.c | |||
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/cirrus/snappercl15.c index a193cea3cf3c..a193cea3cf3c 100644 --- a/sound/soc/ep93xx/snappercl15.c +++ b/sound/soc/cirrus/snappercl15.c | |||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9f8e8594aeb9..b92759a39361 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
| @@ -37,6 +37,7 @@ config SND_SOC_ALL_CODECS | |||
| 37 | select SND_SOC_CX20442 | 37 | select SND_SOC_CX20442 |
| 38 | select SND_SOC_DA7210 if I2C | 38 | select SND_SOC_DA7210 if I2C |
| 39 | select SND_SOC_DA732X if I2C | 39 | select SND_SOC_DA732X if I2C |
| 40 | select SND_SOC_DA9055 if I2C | ||
| 40 | select SND_SOC_DFBMCS320 | 41 | select SND_SOC_DFBMCS320 |
| 41 | select SND_SOC_ISABELLE if I2C | 42 | select SND_SOC_ISABELLE if I2C |
| 42 | select SND_SOC_JZ4740_CODEC | 43 | select SND_SOC_JZ4740_CODEC |
| @@ -70,6 +71,7 @@ config SND_SOC_ALL_CODECS | |||
| 70 | select SND_SOC_UDA134X | 71 | select SND_SOC_UDA134X |
| 71 | select SND_SOC_UDA1380 if I2C | 72 | select SND_SOC_UDA1380 if I2C |
| 72 | select SND_SOC_WL1273 if MFD_WL1273_CORE | 73 | select SND_SOC_WL1273 if MFD_WL1273_CORE |
| 74 | select SND_SOC_WM0010 if SPI_MASTER | ||
| 73 | select SND_SOC_WM1250_EV1 if I2C | 75 | select SND_SOC_WM1250_EV1 if I2C |
| 74 | select SND_SOC_WM2000 if I2C | 76 | select SND_SOC_WM2000 if I2C |
| 75 | select SND_SOC_WM2200 if I2C | 77 | select SND_SOC_WM2200 if I2C |
| @@ -238,6 +240,9 @@ config SND_SOC_DA7210 | |||
| 238 | config SND_SOC_DA732X | 240 | config SND_SOC_DA732X |
| 239 | tristate | 241 | tristate |
| 240 | 242 | ||
| 243 | config SND_SOC_DA9055 | ||
| 244 | tristate | ||
| 245 | |||
| 241 | config SND_SOC_DFBMCS320 | 246 | config SND_SOC_DFBMCS320 |
| 242 | tristate | 247 | tristate |
| 243 | 248 | ||
| @@ -326,6 +331,9 @@ config SND_SOC_UDA1380 | |||
| 326 | config SND_SOC_WL1273 | 331 | config SND_SOC_WL1273 |
| 327 | tristate | 332 | tristate |
| 328 | 333 | ||
| 334 | config SND_SOC_WM0010 | ||
| 335 | tristate | ||
| 336 | |||
| 329 | config SND_SOC_WM1250_EV1 | 337 | config SND_SOC_WM1250_EV1 |
| 330 | tristate | 338 | tristate |
| 331 | 339 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 34148bb59c68..9bd4d95aab4f 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
| @@ -24,6 +24,7 @@ snd-soc-cs4271-objs := cs4271.o | |||
| 24 | snd-soc-cx20442-objs := cx20442.o | 24 | snd-soc-cx20442-objs := cx20442.o |
| 25 | snd-soc-da7210-objs := da7210.o | 25 | snd-soc-da7210-objs := da7210.o |
| 26 | snd-soc-da732x-objs := da732x.o | 26 | snd-soc-da732x-objs := da732x.o |
| 27 | snd-soc-da9055-objs := da9055.o | ||
| 27 | snd-soc-dfbmcs320-objs := dfbmcs320.o | 28 | snd-soc-dfbmcs320-objs := dfbmcs320.o |
| 28 | snd-soc-dmic-objs := dmic.o | 29 | snd-soc-dmic-objs := dmic.o |
| 29 | snd-soc-isabelle-objs := isabelle.o | 30 | snd-soc-isabelle-objs := isabelle.o |
| @@ -61,6 +62,7 @@ snd-soc-twl6040-objs := twl6040.o | |||
| 61 | snd-soc-uda134x-objs := uda134x.o | 62 | snd-soc-uda134x-objs := uda134x.o |
| 62 | snd-soc-uda1380-objs := uda1380.o | 63 | snd-soc-uda1380-objs := uda1380.o |
| 63 | snd-soc-wl1273-objs := wl1273.o | 64 | snd-soc-wl1273-objs := wl1273.o |
| 65 | snd-soc-wm0010-objs := wm0010.o | ||
| 64 | snd-soc-wm1250-ev1-objs := wm1250-ev1.o | 66 | snd-soc-wm1250-ev1-objs := wm1250-ev1.o |
| 65 | snd-soc-wm2000-objs := wm2000.o | 67 | snd-soc-wm2000-objs := wm2000.o |
| 66 | snd-soc-wm2200-objs := wm2200.o | 68 | snd-soc-wm2200-objs := wm2200.o |
| @@ -143,6 +145,7 @@ obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o | |||
| 143 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o | 145 | obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o |
| 144 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o | 146 | obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o |
| 145 | obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o | 147 | obj-$(CONFIG_SND_SOC_DA732X) += snd-soc-da732x.o |
| 148 | obj-$(CONFIG_SND_SOC_DA9055) += snd-soc-da9055.o | ||
| 146 | obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o | 149 | obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o |
| 147 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o | 150 | obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o |
| 148 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o | 151 | obj-$(CONFIG_SND_SOC_ISABELLE) += snd-soc-isabelle.o |
| @@ -177,6 +180,7 @@ obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o | |||
| 177 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o | 180 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o |
| 178 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o | 181 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o |
| 179 | obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o | 182 | obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o |
| 183 | obj-$(CONFIG_SND_SOC_WM0010) += snd-soc-wm0010.o | ||
| 180 | obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o | 184 | obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o |
| 181 | obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o | 185 | obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o |
| 182 | obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o | 186 | obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o |
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 07abd09e0b1d..af547490b4f7 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c | |||
| @@ -391,10 +391,10 @@ static const struct snd_soc_dapm_widget ab8500_dapm_widgets[] = { | |||
| 391 | SND_SOC_DAPM_CLOCK_SUPPLY("audioclk"), | 391 | SND_SOC_DAPM_CLOCK_SUPPLY("audioclk"), |
| 392 | 392 | ||
| 393 | /* Regulators */ | 393 | /* Regulators */ |
| 394 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0), | 394 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AUD", 0, 0), |
| 395 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0), | 395 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC1", 0, 0), |
| 396 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0), | 396 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-AMIC2", 0, 0), |
| 397 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0), | 397 | SND_SOC_DAPM_REGULATOR_SUPPLY("V-DMIC", 0, 0), |
| 398 | 398 | ||
| 399 | /* Power */ | 399 | /* Power */ |
| 400 | SND_SOC_DAPM_SUPPLY("Audio Power", | 400 | SND_SOC_DAPM_SUPPLY("Audio Power", |
| @@ -2462,10 +2462,7 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) | |||
| 2462 | dev_dbg(dev, "%s: Enter.\n", __func__); | 2462 | dev_dbg(dev, "%s: Enter.\n", __func__); |
| 2463 | 2463 | ||
| 2464 | /* Setup AB8500 according to board-settings */ | 2464 | /* Setup AB8500 according to board-settings */ |
| 2465 | pdata = (struct ab8500_platform_data *)dev_get_platdata(dev->parent); | 2465 | pdata = dev_get_platdata(dev->parent); |
| 2466 | |||
| 2467 | /* Inform SoC Core that we have our own I/O arrangements. */ | ||
| 2468 | codec->control_data = (void *)true; | ||
| 2469 | 2466 | ||
| 2470 | if (np) { | 2467 | if (np) { |
| 2471 | if (!pdata) | 2468 | if (!pdata) |
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index c67b50d8b317..dce6ebeef452 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
| 20 | #include <sound/tlv.h> | 20 | #include <sound/tlv.h> |
| 21 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
| 22 | #include <linux/regmap.h> | ||
| 23 | |||
| 22 | #include "ad1836.h" | 24 | #include "ad1836.h" |
| 23 | 25 | ||
| 24 | enum ad1836_type { | 26 | enum ad1836_type { |
| @@ -30,6 +32,7 @@ enum ad1836_type { | |||
| 30 | /* codec private data */ | 32 | /* codec private data */ |
| 31 | struct ad1836_priv { | 33 | struct ad1836_priv { |
| 32 | enum ad1836_type type; | 34 | enum ad1836_type type; |
| 35 | struct regmap *regmap; | ||
| 33 | }; | 36 | }; |
| 34 | 37 | ||
| 35 | /* | 38 | /* |
| @@ -161,8 +164,8 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, | |||
| 161 | struct snd_pcm_hw_params *params, | 164 | struct snd_pcm_hw_params *params, |
| 162 | struct snd_soc_dai *dai) | 165 | struct snd_soc_dai *dai) |
| 163 | { | 166 | { |
| 167 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(dai->codec); | ||
| 164 | int word_len = 0; | 168 | int word_len = 0; |
| 165 | struct snd_soc_codec *codec = dai->codec; | ||
| 166 | 169 | ||
| 167 | /* bit size */ | 170 | /* bit size */ |
| 168 | switch (params_format(params)) { | 171 | switch (params_format(params)) { |
| @@ -178,10 +181,12 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, | |||
| 178 | break; | 181 | break; |
| 179 | } | 182 | } |
| 180 | 183 | ||
| 181 | snd_soc_update_bits(codec, AD1836_DAC_CTRL1, AD1836_DAC_WORD_LEN_MASK, | 184 | regmap_update_bits(ad1836->regmap, AD1836_DAC_CTRL1, |
| 185 | AD1836_DAC_WORD_LEN_MASK, | ||
| 182 | word_len << AD1836_DAC_WORD_LEN_OFFSET); | 186 | word_len << AD1836_DAC_WORD_LEN_OFFSET); |
| 183 | 187 | ||
| 184 | snd_soc_update_bits(codec, AD1836_ADC_CTRL2, AD1836_ADC_WORD_LEN_MASK, | 188 | regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, |
| 189 | AD1836_ADC_WORD_LEN_MASK, | ||
| 185 | word_len << AD1836_ADC_WORD_OFFSET); | 190 | word_len << AD1836_ADC_WORD_OFFSET); |
| 186 | 191 | ||
| 187 | return 0; | 192 | return 0; |
| @@ -223,15 +228,17 @@ static struct snd_soc_dai_driver ad183x_dais[] = { | |||
| 223 | #ifdef CONFIG_PM | 228 | #ifdef CONFIG_PM |
| 224 | static int ad1836_suspend(struct snd_soc_codec *codec) | 229 | static int ad1836_suspend(struct snd_soc_codec *codec) |
| 225 | { | 230 | { |
| 231 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); | ||
| 226 | /* reset clock control mode */ | 232 | /* reset clock control mode */ |
| 227 | return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, | 233 | return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, |
| 228 | AD1836_ADC_SERFMT_MASK, 0); | 234 | AD1836_ADC_SERFMT_MASK, 0); |
| 229 | } | 235 | } |
| 230 | 236 | ||
| 231 | static int ad1836_resume(struct snd_soc_codec *codec) | 237 | static int ad1836_resume(struct snd_soc_codec *codec) |
| 232 | { | 238 | { |
| 239 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); | ||
| 233 | /* restore clock control mode */ | 240 | /* restore clock control mode */ |
| 234 | return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, | 241 | return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, |
| 235 | AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX); | 242 | AD1836_ADC_SERFMT_MASK, AD1836_ADC_AUX); |
| 236 | } | 243 | } |
| 237 | #else | 244 | #else |
| @@ -250,37 +257,30 @@ static int ad1836_probe(struct snd_soc_codec *codec) | |||
| 250 | num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2; | 257 | num_dacs = ad183x_dais[ad1836->type].playback.channels_max / 2; |
| 251 | num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2; | 258 | num_adcs = ad183x_dais[ad1836->type].capture.channels_max / 2; |
| 252 | 259 | ||
| 253 | ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); | ||
| 254 | if (ret < 0) { | ||
| 255 | dev_err(codec->dev, "failed to set cache I/O: %d\n", | ||
| 256 | ret); | ||
| 257 | return ret; | ||
| 258 | } | ||
| 259 | |||
| 260 | /* default setting for ad1836 */ | 260 | /* default setting for ad1836 */ |
| 261 | /* de-emphasis: 48kHz, power-on dac */ | 261 | /* de-emphasis: 48kHz, power-on dac */ |
| 262 | snd_soc_write(codec, AD1836_DAC_CTRL1, 0x300); | 262 | regmap_write(ad1836->regmap, AD1836_DAC_CTRL1, 0x300); |
| 263 | /* unmute dac channels */ | 263 | /* unmute dac channels */ |
| 264 | snd_soc_write(codec, AD1836_DAC_CTRL2, 0x0); | 264 | regmap_write(ad1836->regmap, AD1836_DAC_CTRL2, 0x0); |
| 265 | /* high-pass filter enable, power-on adc */ | 265 | /* high-pass filter enable, power-on adc */ |
| 266 | snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100); | 266 | regmap_write(ad1836->regmap, AD1836_ADC_CTRL1, 0x100); |
| 267 | /* unmute adc channles, adc aux mode */ | 267 | /* unmute adc channles, adc aux mode */ |
| 268 | snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180); | 268 | regmap_write(ad1836->regmap, AD1836_ADC_CTRL2, 0x180); |
| 269 | /* volume */ | 269 | /* volume */ |
| 270 | for (i = 1; i <= num_dacs; ++i) { | 270 | for (i = 1; i <= num_dacs; ++i) { |
| 271 | snd_soc_write(codec, AD1836_DAC_L_VOL(i), 0x3FF); | 271 | regmap_write(ad1836->regmap, AD1836_DAC_L_VOL(i), 0x3FF); |
| 272 | snd_soc_write(codec, AD1836_DAC_R_VOL(i), 0x3FF); | 272 | regmap_write(ad1836->regmap, AD1836_DAC_R_VOL(i), 0x3FF); |
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | if (ad1836->type == AD1836) { | 275 | if (ad1836->type == AD1836) { |
| 276 | /* left/right diff:PGA/MUX */ | 276 | /* left/right diff:PGA/MUX */ |
| 277 | snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); | 277 | regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x3A); |
| 278 | ret = snd_soc_add_codec_controls(codec, ad1836_controls, | 278 | ret = snd_soc_add_codec_controls(codec, ad1836_controls, |
| 279 | ARRAY_SIZE(ad1836_controls)); | 279 | ARRAY_SIZE(ad1836_controls)); |
| 280 | if (ret) | 280 | if (ret) |
| 281 | return ret; | 281 | return ret; |
| 282 | } else { | 282 | } else { |
| 283 | snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00); | 283 | regmap_write(ad1836->regmap, AD1836_ADC_CTRL3, 0x00); |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | ret = snd_soc_add_codec_controls(codec, ad183x_dac_controls, num_dacs * 2); | 286 | ret = snd_soc_add_codec_controls(codec, ad183x_dac_controls, num_dacs * 2); |
| @@ -313,8 +313,9 @@ static int ad1836_probe(struct snd_soc_codec *codec) | |||
| 313 | /* power down chip */ | 313 | /* power down chip */ |
| 314 | static int ad1836_remove(struct snd_soc_codec *codec) | 314 | static int ad1836_remove(struct snd_soc_codec *codec) |
| 315 | { | 315 | { |
| 316 | struct ad1836_priv *ad1836 = snd_soc_codec_get_drvdata(codec); | ||
| 316 | /* reset clock control mode */ | 317 | /* reset clock control mode */ |
| 317 | return snd_soc_update_bits(codec, AD1836_ADC_CTRL2, | 318 | return regmap_update_bits(ad1836->regmap, AD1836_ADC_CTRL2, |
| 318 | AD1836_ADC_SERFMT_MASK, 0); | 319 | AD1836_ADC_SERFMT_MASK, 0); |
| 319 | } | 320 | } |
| 320 | 321 | ||
| @@ -323,8 +324,6 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { | |||
| 323 | .remove = ad1836_remove, | 324 | .remove = ad1836_remove, |
| 324 | .suspend = ad1836_suspend, | 325 | .suspend = ad1836_suspend, |
| 325 | .resume = ad1836_resume, | 326 | .resume = ad1836_resume, |
| 326 | .reg_cache_size = AD1836_NUM_REGS, | ||
| 327 | .reg_word_size = sizeof(u16), | ||
| 328 | 327 | ||
| 329 | .controls = ad183x_controls, | 328 | .controls = ad183x_controls, |
| 330 | .num_controls = ARRAY_SIZE(ad183x_controls), | 329 | .num_controls = ARRAY_SIZE(ad183x_controls), |
| @@ -334,6 +333,33 @@ static struct snd_soc_codec_driver soc_codec_dev_ad1836 = { | |||
| 334 | .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes), | 333 | .num_dapm_routes = ARRAY_SIZE(ad183x_dapm_routes), |
| 335 | }; | 334 | }; |
| 336 | 335 | ||
| 336 | static const struct reg_default ad1836_reg_defaults[] = { | ||
| 337 | { AD1836_DAC_CTRL1, 0x0000 }, | ||
| 338 | { AD1836_DAC_CTRL2, 0x0000 }, | ||
| 339 | { AD1836_DAC_L_VOL(0), 0x0000 }, | ||
| 340 | { AD1836_DAC_R_VOL(0), 0x0000 }, | ||
| 341 | { AD1836_DAC_L_VOL(1), 0x0000 }, | ||
| 342 | { AD1836_DAC_R_VOL(1), 0x0000 }, | ||
| 343 | { AD1836_DAC_L_VOL(2), 0x0000 }, | ||
| 344 | { AD1836_DAC_R_VOL(2), 0x0000 }, | ||
| 345 | { AD1836_DAC_L_VOL(3), 0x0000 }, | ||
| 346 | { AD1836_DAC_R_VOL(3), 0x0000 }, | ||
| 347 | { AD1836_ADC_CTRL1, 0x0000 }, | ||
| 348 | { AD1836_ADC_CTRL2, 0x0000 }, | ||
| 349 | { AD1836_ADC_CTRL3, 0x0000 }, | ||
| 350 | }; | ||
| 351 | |||
| 352 | static const struct regmap_config ad1836_regmap_config = { | ||
| 353 | .val_bits = 12, | ||
| 354 | .reg_bits = 4, | ||
| 355 | .read_flag_mask = 0x08, | ||
| 356 | |||
| 357 | .max_register = AD1836_ADC_CTRL3, | ||
| 358 | .reg_defaults = ad1836_reg_defaults, | ||
| 359 | .num_reg_defaults = ARRAY_SIZE(ad1836_reg_defaults), | ||
| 360 | .cache_type = REGCACHE_RBTREE, | ||
| 361 | }; | ||
| 362 | |||
| 337 | static int __devinit ad1836_spi_probe(struct spi_device *spi) | 363 | static int __devinit ad1836_spi_probe(struct spi_device *spi) |
| 338 | { | 364 | { |
| 339 | struct ad1836_priv *ad1836; | 365 | struct ad1836_priv *ad1836; |
| @@ -344,6 +370,10 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi) | |||
| 344 | if (ad1836 == NULL) | 370 | if (ad1836 == NULL) |
| 345 | return -ENOMEM; | 371 | return -ENOMEM; |
| 346 | 372 | ||
| 373 | ad1836->regmap = devm_regmap_init_spi(spi, &ad1836_regmap_config); | ||
| 374 | if (IS_ERR(ad1836->regmap)) | ||
| 375 | return PTR_ERR(ad1836->regmap); | ||
| 376 | |||
| 347 | ad1836->type = spi_get_device_id(spi)->driver_data; | 377 | ad1836->type = spi_get_device_id(spi)->driver_data; |
| 348 | 378 | ||
| 349 | spi_set_drvdata(spi, ad1836); | 379 | spi_set_drvdata(spi, ad1836); |
| @@ -379,17 +409,7 @@ static struct spi_driver ad1836_spi_driver = { | |||
| 379 | .id_table = ad1836_ids, | 409 | .id_table = ad1836_ids, |
| 380 | }; | 410 | }; |
| 381 | 411 | ||
| 382 | static int __init ad1836_init(void) | 412 | module_spi_driver(ad1836_spi_driver); |
| 383 | { | ||
| 384 | return spi_register_driver(&ad1836_spi_driver); | ||
| 385 | } | ||
| 386 | module_init(ad1836_init); | ||
| 387 | |||
| 388 | static void __exit ad1836_exit(void) | ||
| 389 | { | ||
| 390 | spi_unregister_driver(&ad1836_spi_driver); | ||
| 391 | } | ||
| 392 | module_exit(ad1836_exit); | ||
| 393 | 413 | ||
| 394 | MODULE_DESCRIPTION("ASoC ad1836 driver"); | 414 | MODULE_DESCRIPTION("ASoC ad1836 driver"); |
| 395 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | 415 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); |
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 13e62be4f990..2f752660f678 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
| @@ -381,40 +381,25 @@ static const struct regmap_config ad193x_spi_regmap_config = { | |||
| 381 | static int __devinit ad193x_spi_probe(struct spi_device *spi) | 381 | static int __devinit ad193x_spi_probe(struct spi_device *spi) |
| 382 | { | 382 | { |
| 383 | struct ad193x_priv *ad193x; | 383 | struct ad193x_priv *ad193x; |
| 384 | int ret; | ||
| 385 | 384 | ||
| 386 | ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv), | 385 | ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv), |
| 387 | GFP_KERNEL); | 386 | GFP_KERNEL); |
| 388 | if (ad193x == NULL) | 387 | if (ad193x == NULL) |
| 389 | return -ENOMEM; | 388 | return -ENOMEM; |
| 390 | 389 | ||
| 391 | ad193x->regmap = regmap_init_spi(spi, &ad193x_spi_regmap_config); | 390 | ad193x->regmap = devm_regmap_init_spi(spi, &ad193x_spi_regmap_config); |
| 392 | if (IS_ERR(ad193x->regmap)) { | 391 | if (IS_ERR(ad193x->regmap)) |
| 393 | ret = PTR_ERR(ad193x->regmap); | 392 | return PTR_ERR(ad193x->regmap); |
| 394 | goto err_out; | ||
| 395 | } | ||
| 396 | 393 | ||
| 397 | spi_set_drvdata(spi, ad193x); | 394 | spi_set_drvdata(spi, ad193x); |
| 398 | 395 | ||
| 399 | ret = snd_soc_register_codec(&spi->dev, | 396 | return snd_soc_register_codec(&spi->dev, &soc_codec_dev_ad193x, |
| 400 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | 397 | &ad193x_dai, 1); |
| 401 | if (ret < 0) | ||
| 402 | goto err_regmap_exit; | ||
| 403 | |||
| 404 | return 0; | ||
| 405 | |||
| 406 | err_regmap_exit: | ||
| 407 | regmap_exit(ad193x->regmap); | ||
| 408 | err_out: | ||
| 409 | return ret; | ||
| 410 | } | 398 | } |
| 411 | 399 | ||
| 412 | static int __devexit ad193x_spi_remove(struct spi_device *spi) | 400 | static int __devexit ad193x_spi_remove(struct spi_device *spi) |
| 413 | { | 401 | { |
| 414 | struct ad193x_priv *ad193x = spi_get_drvdata(spi); | ||
| 415 | |||
| 416 | snd_soc_unregister_codec(&spi->dev); | 402 | snd_soc_unregister_codec(&spi->dev); |
| 417 | regmap_exit(ad193x->regmap); | ||
| 418 | return 0; | 403 | return 0; |
| 419 | } | 404 | } |
| 420 | 405 | ||
| @@ -449,40 +434,25 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client, | |||
| 449 | const struct i2c_device_id *id) | 434 | const struct i2c_device_id *id) |
| 450 | { | 435 | { |
| 451 | struct ad193x_priv *ad193x; | 436 | struct ad193x_priv *ad193x; |
| 452 | int ret; | ||
| 453 | 437 | ||
| 454 | ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv), | 438 | ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv), |
| 455 | GFP_KERNEL); | 439 | GFP_KERNEL); |
| 456 | if (ad193x == NULL) | 440 | if (ad193x == NULL) |
| 457 | return -ENOMEM; | 441 | return -ENOMEM; |
| 458 | 442 | ||
| 459 | ad193x->regmap = regmap_init_i2c(client, &ad193x_i2c_regmap_config); | 443 | ad193x->regmap = devm_regmap_init_i2c(client, &ad193x_i2c_regmap_config); |
| 460 | if (IS_ERR(ad193x->regmap)) { | 444 | if (IS_ERR(ad193x->regmap)) |
| 461 | ret = PTR_ERR(ad193x->regmap); | 445 | return PTR_ERR(ad193x->regmap); |
| 462 | goto err_out; | ||
| 463 | } | ||
| 464 | 446 | ||
| 465 | i2c_set_clientdata(client, ad193x); | 447 | i2c_set_clientdata(client, ad193x); |
| 466 | 448 | ||
| 467 | ret = snd_soc_register_codec(&client->dev, | 449 | return snd_soc_register_codec(&client->dev, &soc_codec_dev_ad193x, |
| 468 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | 450 | &ad193x_dai, 1); |
| 469 | if (ret < 0) | ||
| 470 | goto err_regmap_exit; | ||
| 471 | |||
| 472 | return 0; | ||
| 473 | |||
| 474 | err_regmap_exit: | ||
| 475 | regmap_exit(ad193x->regmap); | ||
| 476 | err_out: | ||
| 477 | return ret; | ||
| 478 | } | 451 | } |
| 479 | 452 | ||
| 480 | static int __devexit ad193x_i2c_remove(struct i2c_client *client) | 453 | static int __devexit ad193x_i2c_remove(struct i2c_client *client) |
| 481 | { | 454 | { |
| 482 | struct ad193x_priv *ad193x = i2c_get_clientdata(client); | ||
| 483 | |||
| 484 | snd_soc_unregister_codec(&client->dev); | 455 | snd_soc_unregister_codec(&client->dev); |
| 485 | regmap_exit(ad193x->regmap); | ||
| 486 | return 0; | 456 | return 0; |
| 487 | } | 457 | } |
| 488 | 458 | ||
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 11b1b714b8b5..8c39dddd7d00 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
| @@ -186,7 +186,6 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) | |||
| 186 | 186 | ||
| 187 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); | 187 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); |
| 188 | 188 | ||
| 189 | codec->control_data = codec; /* we don't use regmap! */ | ||
| 190 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 189 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
| 191 | if (ret < 0) { | 190 | if (ret < 0) { |
| 192 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); | 191 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); |
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 44f59064d8de..704544bfc90d 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c | |||
| @@ -1392,17 +1392,7 @@ static struct i2c_driver adau1373_i2c_driver = { | |||
| 1392 | .id_table = adau1373_i2c_id, | 1392 | .id_table = adau1373_i2c_id, |
| 1393 | }; | 1393 | }; |
| 1394 | 1394 | ||
| 1395 | static int __init adau1373_init(void) | 1395 | module_i2c_driver(adau1373_i2c_driver); |
| 1396 | { | ||
| 1397 | return i2c_add_driver(&adau1373_i2c_driver); | ||
| 1398 | } | ||
| 1399 | module_init(adau1373_init); | ||
| 1400 | |||
| 1401 | static void __exit adau1373_exit(void) | ||
| 1402 | { | ||
| 1403 | i2c_del_driver(&adau1373_i2c_driver); | ||
| 1404 | } | ||
| 1405 | module_exit(adau1373_exit); | ||
| 1406 | 1396 | ||
| 1407 | MODULE_DESCRIPTION("ASoC ADAU1373 driver"); | 1397 | MODULE_DESCRIPTION("ASoC ADAU1373 driver"); |
| 1408 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 1398 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index 3d50fc8646b6..51f2f3cd8136 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c | |||
| @@ -527,17 +527,7 @@ static struct i2c_driver adau1701_i2c_driver = { | |||
| 527 | .id_table = adau1701_i2c_id, | 527 | .id_table = adau1701_i2c_id, |
| 528 | }; | 528 | }; |
| 529 | 529 | ||
| 530 | static int __init adau1701_init(void) | 530 | module_i2c_driver(adau1701_i2c_driver); |
| 531 | { | ||
| 532 | return i2c_add_driver(&adau1701_i2c_driver); | ||
| 533 | } | ||
| 534 | module_init(adau1701_init); | ||
| 535 | |||
| 536 | static void __exit adau1701_exit(void) | ||
| 537 | { | ||
| 538 | i2c_del_driver(&adau1701_i2c_driver); | ||
| 539 | } | ||
| 540 | module_exit(adau1701_exit); | ||
| 541 | 531 | ||
| 542 | MODULE_DESCRIPTION("ASoC ADAU1701 SigmaDSP driver"); | 532 | MODULE_DESCRIPTION("ASoC ADAU1701 SigmaDSP driver"); |
| 543 | MODULE_AUTHOR("Cliff Cai <cliff.cai@analog.com>"); | 533 | MODULE_AUTHOR("Cliff Cai <cliff.cai@analog.com>"); |
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 5fb7c2a80e6d..2b457976a7bf 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c | |||
| @@ -696,17 +696,7 @@ static struct i2c_driver ak4671_i2c_driver = { | |||
| 696 | .id_table = ak4671_i2c_id, | 696 | .id_table = ak4671_i2c_id, |
| 697 | }; | 697 | }; |
| 698 | 698 | ||
| 699 | static int __init ak4671_modinit(void) | 699 | module_i2c_driver(ak4671_i2c_driver); |
| 700 | { | ||
| 701 | return i2c_add_driver(&ak4671_i2c_driver); | ||
| 702 | } | ||
| 703 | module_init(ak4671_modinit); | ||
| 704 | |||
| 705 | static void __exit ak4671_exit(void) | ||
| 706 | { | ||
| 707 | i2c_del_driver(&ak4671_i2c_driver); | ||
| 708 | } | ||
| 709 | module_exit(ak4671_exit); | ||
| 710 | 700 | ||
| 711 | MODULE_DESCRIPTION("ASoC AK4671 codec driver"); | 701 | MODULE_DESCRIPTION("ASoC AK4671 codec driver"); |
| 712 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | 702 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 1cf7a32d1b21..c03b65af3059 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
| @@ -119,6 +119,24 @@ const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS] = { | |||
| 119 | "DSP1.4", | 119 | "DSP1.4", |
| 120 | "DSP1.5", | 120 | "DSP1.5", |
| 121 | "DSP1.6", | 121 | "DSP1.6", |
| 122 | "DSP2.1", | ||
| 123 | "DSP2.2", | ||
| 124 | "DSP2.3", | ||
| 125 | "DSP2.4", | ||
| 126 | "DSP2.5", | ||
| 127 | "DSP2.6", | ||
| 128 | "DSP3.1", | ||
| 129 | "DSP3.2", | ||
| 130 | "DSP3.3", | ||
| 131 | "DSP3.4", | ||
| 132 | "DSP3.5", | ||
| 133 | "DSP3.6", | ||
| 134 | "DSP4.1", | ||
| 135 | "DSP4.2", | ||
| 136 | "DSP4.3", | ||
| 137 | "DSP4.4", | ||
| 138 | "DSP4.5", | ||
| 139 | "DSP4.6", | ||
| 122 | "ASRC1L", | 140 | "ASRC1L", |
| 123 | "ASRC1R", | 141 | "ASRC1R", |
| 124 | "ASRC2L", | 142 | "ASRC2L", |
| @@ -180,6 +198,24 @@ int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS] = { | |||
| 180 | 0x6b, | 198 | 0x6b, |
| 181 | 0x6c, | 199 | 0x6c, |
| 182 | 0x6d, | 200 | 0x6d, |
| 201 | 0x70, /* DSP2.1 */ | ||
| 202 | 0x71, | ||
| 203 | 0x72, | ||
| 204 | 0x73, | ||
| 205 | 0x74, | ||
| 206 | 0x75, | ||
| 207 | 0x78, /* DSP3.1 */ | ||
| 208 | 0x79, | ||
| 209 | 0x7a, | ||
| 210 | 0x7b, | ||
| 211 | 0x7c, | ||
| 212 | 0x7d, | ||
| 213 | 0x80, /* DSP4.1 */ | ||
| 214 | 0x81, | ||
| 215 | 0x82, | ||
| 216 | 0x83, | ||
| 217 | 0x84, | ||
| 218 | 0x85, | ||
| 183 | 0x90, /* ASRC1L */ | 219 | 0x90, /* ASRC1L */ |
| 184 | 0x91, | 220 | 0x91, |
| 185 | 0x92, | 221 | 0x92, |
| @@ -229,6 +265,75 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, | |||
| 229 | } | 265 | } |
| 230 | EXPORT_SYMBOL_GPL(arizona_out_ev); | 266 | EXPORT_SYMBOL_GPL(arizona_out_ev); |
| 231 | 267 | ||
| 268 | static unsigned int arizona_sysclk_48k_rates[] = { | ||
| 269 | 6144000, | ||
| 270 | 12288000, | ||
| 271 | 22579200, | ||
| 272 | 49152000, | ||
| 273 | 73728000, | ||
| 274 | 98304000, | ||
| 275 | 147456000, | ||
| 276 | }; | ||
| 277 | |||
| 278 | static unsigned int arizona_sysclk_44k1_rates[] = { | ||
| 279 | 5644800, | ||
| 280 | 11289600, | ||
| 281 | 24576000, | ||
| 282 | 45158400, | ||
| 283 | 67737600, | ||
| 284 | 90316800, | ||
| 285 | 135475200, | ||
| 286 | }; | ||
| 287 | |||
| 288 | static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk, | ||
| 289 | unsigned int freq) | ||
| 290 | { | ||
| 291 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
| 292 | unsigned int reg; | ||
| 293 | unsigned int *rates; | ||
| 294 | int ref, div, refclk; | ||
| 295 | |||
| 296 | switch (clk) { | ||
| 297 | case ARIZONA_CLK_OPCLK: | ||
| 298 | reg = ARIZONA_OUTPUT_SYSTEM_CLOCK; | ||
| 299 | refclk = priv->sysclk; | ||
| 300 | break; | ||
| 301 | case ARIZONA_CLK_ASYNC_OPCLK: | ||
| 302 | reg = ARIZONA_OUTPUT_ASYNC_CLOCK; | ||
| 303 | refclk = priv->asyncclk; | ||
| 304 | break; | ||
| 305 | default: | ||
| 306 | return -EINVAL; | ||
| 307 | } | ||
| 308 | |||
| 309 | if (refclk % 8000) | ||
| 310 | rates = arizona_sysclk_44k1_rates; | ||
| 311 | else | ||
| 312 | rates = arizona_sysclk_48k_rates; | ||
| 313 | |||
| 314 | for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) && | ||
| 315 | rates[ref] <= refclk; ref++) { | ||
| 316 | div = 1; | ||
| 317 | while (rates[ref] / div >= freq && div < 32) { | ||
| 318 | if (rates[ref] / div == freq) { | ||
| 319 | dev_dbg(codec->dev, "Configured %dHz OPCLK\n", | ||
| 320 | freq); | ||
| 321 | snd_soc_update_bits(codec, reg, | ||
| 322 | ARIZONA_OPCLK_DIV_MASK | | ||
| 323 | ARIZONA_OPCLK_SEL_MASK, | ||
| 324 | (div << | ||
| 325 | ARIZONA_OPCLK_DIV_SHIFT) | | ||
| 326 | ref); | ||
| 327 | return 0; | ||
| 328 | } | ||
| 329 | div++; | ||
| 330 | } | ||
| 331 | } | ||
| 332 | |||
| 333 | dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq); | ||
| 334 | return -EINVAL; | ||
| 335 | } | ||
| 336 | |||
| 232 | int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, | 337 | int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, |
| 233 | int source, unsigned int freq, int dir) | 338 | int source, unsigned int freq, int dir) |
| 234 | { | 339 | { |
| @@ -252,6 +357,9 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
| 252 | reg = ARIZONA_ASYNC_CLOCK_1; | 357 | reg = ARIZONA_ASYNC_CLOCK_1; |
| 253 | clk = &priv->asyncclk; | 358 | clk = &priv->asyncclk; |
| 254 | break; | 359 | break; |
| 360 | case ARIZONA_CLK_OPCLK: | ||
| 361 | case ARIZONA_CLK_ASYNC_OPCLK: | ||
| 362 | return arizona_set_opclk(codec, clk_id, freq); | ||
| 255 | default: | 363 | default: |
| 256 | return -EINVAL; | 364 | return -EINVAL; |
| 257 | } | 365 | } |
| @@ -666,7 +774,7 @@ static irqreturn_t arizona_fll_lock(int irq, void *data) | |||
| 666 | { | 774 | { |
| 667 | struct arizona_fll *fll = data; | 775 | struct arizona_fll *fll = data; |
| 668 | 776 | ||
| 669 | arizona_fll_dbg(fll, "Locked\n"); | 777 | arizona_fll_dbg(fll, "Lock status changed\n"); |
| 670 | 778 | ||
| 671 | complete(&fll->lock); | 779 | complete(&fll->lock); |
| 672 | 780 | ||
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 59caca8865e8..36ec64946120 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
| @@ -17,8 +17,10 @@ | |||
| 17 | 17 | ||
| 18 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
| 19 | 19 | ||
| 20 | #define ARIZONA_CLK_SYSCLK 1 | 20 | #define ARIZONA_CLK_SYSCLK 1 |
| 21 | #define ARIZONA_CLK_ASYNCCLK 2 | 21 | #define ARIZONA_CLK_ASYNCCLK 2 |
| 22 | #define ARIZONA_CLK_OPCLK 3 | ||
| 23 | #define ARIZONA_CLK_ASYNC_OPCLK 4 | ||
| 22 | 24 | ||
| 23 | #define ARIZONA_CLK_SRC_MCLK1 0x0 | 25 | #define ARIZONA_CLK_SRC_MCLK1 0x0 |
| 24 | #define ARIZONA_CLK_SRC_MCLK2 0x1 | 26 | #define ARIZONA_CLK_SRC_MCLK2 0x1 |
| @@ -59,7 +61,7 @@ struct arizona_priv { | |||
| 59 | struct arizona_dai_priv dai[ARIZONA_MAX_DAI]; | 61 | struct arizona_dai_priv dai[ARIZONA_MAX_DAI]; |
| 60 | }; | 62 | }; |
| 61 | 63 | ||
| 62 | #define ARIZONA_NUM_MIXER_INPUTS 57 | 64 | #define ARIZONA_NUM_MIXER_INPUTS 75 |
| 63 | 65 | ||
| 64 | extern const unsigned int arizona_mixer_tlv[]; | 66 | extern const unsigned int arizona_mixer_tlv[]; |
| 65 | extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS]; | 67 | extern const char *arizona_mixer_texts[ARIZONA_NUM_MIXER_INPUTS]; |
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 047917f0b8ae..8e4779812b96 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | #include <linux/i2c.h> | 29 | #include <linux/i2c.h> |
| 30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
| 31 | #include <linux/regulator/consumer.h> | 31 | #include <linux/regulator/consumer.h> |
| 32 | #include <linux/of_device.h> | ||
| 33 | #include <linux/of_gpio.h> | ||
| 32 | 34 | ||
| 33 | /* | 35 | /* |
| 34 | * The codec isn't really big-endian or little-endian, since the I2S | 36 | * The codec isn't really big-endian or little-endian, since the I2S |
| @@ -110,14 +112,15 @@ | |||
| 110 | * This array contains the power-on default values of the registers, with the | 112 | * This array contains the power-on default values of the registers, with the |
| 111 | * exception of the "CHIPID" register (01h). The lower four bits of that | 113 | * exception of the "CHIPID" register (01h). The lower four bits of that |
| 112 | * register contain the hardware revision, so it is treated as volatile. | 114 | * register contain the hardware revision, so it is treated as volatile. |
| 113 | * | ||
| 114 | * Also note that on the CS4270, the first readable register is 1, but ASoC | ||
| 115 | * assumes the first register is 0. Therfore, the array must have an entry for | ||
| 116 | * register 0, but we use cs4270_reg_is_readable() to tell ASoC that it can't | ||
| 117 | * be read. | ||
| 118 | */ | 115 | */ |
| 119 | static const u8 cs4270_default_reg_cache[CS4270_LASTREG + 1] = { | 116 | static const struct reg_default cs4270_reg_defaults[] = { |
| 120 | 0x00, 0x00, 0x00, 0x30, 0x00, 0x60, 0x20, 0x00, 0x00 | 117 | { 2, 0x00 }, |
| 118 | { 3, 0x30 }, | ||
| 119 | { 4, 0x00 }, | ||
| 120 | { 5, 0x60 }, | ||
| 121 | { 6, 0x20 }, | ||
| 122 | { 7, 0x00 }, | ||
| 123 | { 8, 0x00 }, | ||
| 121 | }; | 124 | }; |
| 122 | 125 | ||
| 123 | static const char *supply_names[] = { | 126 | static const char *supply_names[] = { |
| @@ -126,7 +129,7 @@ static const char *supply_names[] = { | |||
| 126 | 129 | ||
| 127 | /* Private data for the CS4270 */ | 130 | /* Private data for the CS4270 */ |
| 128 | struct cs4270_private { | 131 | struct cs4270_private { |
| 129 | enum snd_soc_control_type control_type; | 132 | struct regmap *regmap; |
| 130 | unsigned int mclk; /* Input frequency of the MCLK pin */ | 133 | unsigned int mclk; /* Input frequency of the MCLK pin */ |
| 131 | unsigned int mode; /* The mode (I2S or left-justified) */ | 134 | unsigned int mode; /* The mode (I2S or left-justified) */ |
| 132 | unsigned int slave_mode; | 135 | unsigned int slave_mode; |
| @@ -191,12 +194,12 @@ static struct cs4270_mode_ratios cs4270_mode_ratios[] = { | |||
| 191 | /* The number of MCLK/LRCK ratios supported by the CS4270 */ | 194 | /* The number of MCLK/LRCK ratios supported by the CS4270 */ |
| 192 | #define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) | 195 | #define NUM_MCLK_RATIOS ARRAY_SIZE(cs4270_mode_ratios) |
| 193 | 196 | ||
| 194 | static int cs4270_reg_is_readable(struct snd_soc_codec *codec, unsigned int reg) | 197 | static bool cs4270_reg_is_readable(struct device *dev, unsigned int reg) |
| 195 | { | 198 | { |
| 196 | return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG); | 199 | return (reg >= CS4270_FIRSTREG) && (reg <= CS4270_LASTREG); |
| 197 | } | 200 | } |
| 198 | 201 | ||
| 199 | static int cs4270_reg_is_volatile(struct snd_soc_codec *codec, unsigned int reg) | 202 | static bool cs4270_reg_is_volatile(struct device *dev, unsigned int reg) |
| 200 | { | 203 | { |
| 201 | /* Unreadable registers are considered volatile */ | 204 | /* Unreadable registers are considered volatile */ |
| 202 | if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) | 205 | if ((reg < CS4270_FIRSTREG) || (reg > CS4270_LASTREG)) |
| @@ -456,7 +459,7 @@ static struct snd_soc_dai_driver cs4270_dai = { | |||
| 456 | .name = "cs4270-hifi", | 459 | .name = "cs4270-hifi", |
| 457 | .playback = { | 460 | .playback = { |
| 458 | .stream_name = "Playback", | 461 | .stream_name = "Playback", |
| 459 | .channels_min = 1, | 462 | .channels_min = 2, |
| 460 | .channels_max = 2, | 463 | .channels_max = 2, |
| 461 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | 464 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
| 462 | .rate_min = 4000, | 465 | .rate_min = 4000, |
| @@ -465,7 +468,7 @@ static struct snd_soc_dai_driver cs4270_dai = { | |||
| 465 | }, | 468 | }, |
| 466 | .capture = { | 469 | .capture = { |
| 467 | .stream_name = "Capture", | 470 | .stream_name = "Capture", |
| 468 | .channels_min = 1, | 471 | .channels_min = 2, |
| 469 | .channels_max = 2, | 472 | .channels_max = 2, |
| 470 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | 473 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
| 471 | .rate_min = 4000, | 474 | .rate_min = 4000, |
| @@ -485,12 +488,12 @@ static struct snd_soc_dai_driver cs4270_dai = { | |||
| 485 | static int cs4270_probe(struct snd_soc_codec *codec) | 488 | static int cs4270_probe(struct snd_soc_codec *codec) |
| 486 | { | 489 | { |
| 487 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 490 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
| 488 | int i, ret; | 491 | int ret; |
| 489 | 492 | ||
| 490 | /* Tell ASoC what kind of I/O to use to read the registers. ASoC will | 493 | /* Tell ASoC what kind of I/O to use to read the registers. ASoC will |
| 491 | * then do the I2C transactions itself. | 494 | * then do the I2C transactions itself. |
| 492 | */ | 495 | */ |
| 493 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, cs4270->control_type); | 496 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); |
| 494 | if (ret < 0) { | 497 | if (ret < 0) { |
| 495 | dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); | 498 | dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); |
| 496 | return ret; | 499 | return ret; |
| @@ -519,33 +522,8 @@ static int cs4270_probe(struct snd_soc_codec *codec) | |||
| 519 | return ret; | 522 | return ret; |
| 520 | } | 523 | } |
| 521 | 524 | ||
| 522 | /* Add the non-DAPM controls */ | ||
| 523 | ret = snd_soc_add_codec_controls(codec, cs4270_snd_controls, | ||
| 524 | ARRAY_SIZE(cs4270_snd_controls)); | ||
| 525 | if (ret < 0) { | ||
| 526 | dev_err(codec->dev, "failed to add controls\n"); | ||
| 527 | return ret; | ||
| 528 | } | ||
| 529 | |||
| 530 | /* get the power supply regulators */ | ||
| 531 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
| 532 | cs4270->supplies[i].supply = supply_names[i]; | ||
| 533 | |||
| 534 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(cs4270->supplies), | ||
| 535 | cs4270->supplies); | ||
| 536 | if (ret < 0) | ||
| 537 | return ret; | ||
| 538 | |||
| 539 | ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), | 525 | ret = regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies), |
| 540 | cs4270->supplies); | 526 | cs4270->supplies); |
| 541 | if (ret < 0) | ||
| 542 | goto error_free_regulators; | ||
| 543 | |||
| 544 | return 0; | ||
| 545 | |||
| 546 | error_free_regulators: | ||
| 547 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), | ||
| 548 | cs4270->supplies); | ||
| 549 | 527 | ||
| 550 | return ret; | 528 | return ret; |
| 551 | } | 529 | } |
| @@ -561,7 +539,6 @@ static int cs4270_remove(struct snd_soc_codec *codec) | |||
| 561 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); | 539 | struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec); |
| 562 | 540 | ||
| 563 | regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); | 541 | regulator_bulk_disable(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); |
| 564 | regulator_bulk_free(ARRAY_SIZE(cs4270->supplies), cs4270->supplies); | ||
| 565 | 542 | ||
| 566 | return 0; | 543 | return 0; |
| 567 | }; | 544 | }; |
| @@ -611,7 +588,7 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec) | |||
| 611 | ndelay(500); | 588 | ndelay(500); |
| 612 | 589 | ||
| 613 | /* first restore the entire register cache ... */ | 590 | /* first restore the entire register cache ... */ |
| 614 | snd_soc_cache_sync(codec); | 591 | regcache_sync(cs4270->regmap); |
| 615 | 592 | ||
| 616 | /* ... then disable the power-down bits */ | 593 | /* ... then disable the power-down bits */ |
| 617 | reg = snd_soc_read(codec, CS4270_PWRCTL); | 594 | reg = snd_soc_read(codec, CS4270_PWRCTL); |
| @@ -632,11 +609,30 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { | |||
| 632 | .remove = cs4270_remove, | 609 | .remove = cs4270_remove, |
| 633 | .suspend = cs4270_soc_suspend, | 610 | .suspend = cs4270_soc_suspend, |
| 634 | .resume = cs4270_soc_resume, | 611 | .resume = cs4270_soc_resume, |
| 635 | .volatile_register = cs4270_reg_is_volatile, | 612 | |
| 636 | .readable_register = cs4270_reg_is_readable, | 613 | .controls = cs4270_snd_controls, |
| 637 | .reg_cache_size = CS4270_LASTREG + 1, | 614 | .num_controls = ARRAY_SIZE(cs4270_snd_controls), |
| 638 | .reg_word_size = sizeof(u8), | 615 | }; |
| 639 | .reg_cache_default = cs4270_default_reg_cache, | 616 | |
| 617 | /* | ||
| 618 | * cs4270_of_match - the device tree bindings | ||
| 619 | */ | ||
| 620 | static const struct of_device_id cs4270_of_match[] = { | ||
| 621 | { .compatible = "cirrus,cs4270", }, | ||
| 622 | { } | ||
| 623 | }; | ||
| 624 | MODULE_DEVICE_TABLE(of, cs4270_of_match); | ||
| 625 | |||
| 626 | static const struct regmap_config cs4270_regmap = { | ||
| 627 | .reg_bits = 8, | ||
| 628 | .val_bits = 8, | ||
| 629 | .max_register = CS4270_LASTREG, | ||
| 630 | .reg_defaults = cs4270_reg_defaults, | ||
| 631 | .num_reg_defaults = ARRAY_SIZE(cs4270_reg_defaults), | ||
| 632 | .cache_type = REGCACHE_RBTREE, | ||
| 633 | |||
| 634 | .readable_reg = cs4270_reg_is_readable, | ||
| 635 | .volatile_reg = cs4270_reg_is_volatile, | ||
| 640 | }; | 636 | }; |
| 641 | 637 | ||
| 642 | /** | 638 | /** |
| @@ -650,19 +646,56 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { | |||
| 650 | static int cs4270_i2c_probe(struct i2c_client *i2c_client, | 646 | static int cs4270_i2c_probe(struct i2c_client *i2c_client, |
| 651 | const struct i2c_device_id *id) | 647 | const struct i2c_device_id *id) |
| 652 | { | 648 | { |
| 649 | struct device_node *np = i2c_client->dev.of_node; | ||
| 653 | struct cs4270_private *cs4270; | 650 | struct cs4270_private *cs4270; |
| 654 | int ret; | 651 | unsigned int val; |
| 652 | int ret, i; | ||
| 655 | 653 | ||
| 656 | /* Verify that we have a CS4270 */ | 654 | cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), |
| 655 | GFP_KERNEL); | ||
| 656 | if (!cs4270) { | ||
| 657 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
| 658 | return -ENOMEM; | ||
| 659 | } | ||
| 660 | |||
| 661 | /* get the power supply regulators */ | ||
| 662 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
| 663 | cs4270->supplies[i].supply = supply_names[i]; | ||
| 664 | |||
| 665 | ret = devm_regulator_bulk_get(&i2c_client->dev, | ||
| 666 | ARRAY_SIZE(cs4270->supplies), | ||
| 667 | cs4270->supplies); | ||
| 668 | if (ret < 0) | ||
| 669 | return ret; | ||
| 670 | |||
| 671 | /* See if we have a way to bring the codec out of reset */ | ||
| 672 | if (np) { | ||
| 673 | enum of_gpio_flags flags; | ||
| 674 | int gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags); | ||
| 675 | |||
| 676 | if (gpio_is_valid(gpio)) { | ||
| 677 | ret = devm_gpio_request_one(&i2c_client->dev, gpio, | ||
| 678 | flags & OF_GPIO_ACTIVE_LOW ? | ||
| 679 | GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, | ||
| 680 | "cs4270 reset"); | ||
| 681 | if (ret < 0) | ||
| 682 | return ret; | ||
| 683 | } | ||
| 684 | } | ||
| 685 | |||
| 686 | cs4270->regmap = devm_regmap_init_i2c(i2c_client, &cs4270_regmap); | ||
| 687 | if (IS_ERR(cs4270->regmap)) | ||
| 688 | return PTR_ERR(cs4270->regmap); | ||
| 657 | 689 | ||
| 658 | ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); | 690 | /* Verify that we have a CS4270 */ |
| 691 | ret = regmap_read(cs4270->regmap, CS4270_CHIPID, &val); | ||
| 659 | if (ret < 0) { | 692 | if (ret < 0) { |
| 660 | dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", | 693 | dev_err(&i2c_client->dev, "failed to read i2c at addr %X\n", |
| 661 | i2c_client->addr); | 694 | i2c_client->addr); |
| 662 | return ret; | 695 | return ret; |
| 663 | } | 696 | } |
| 664 | /* The top four bits of the chip ID should be 1100. */ | 697 | /* The top four bits of the chip ID should be 1100. */ |
| 665 | if ((ret & 0xF0) != 0xC0) { | 698 | if ((val & 0xF0) != 0xC0) { |
| 666 | dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", | 699 | dev_err(&i2c_client->dev, "device at addr %X is not a CS4270\n", |
| 667 | i2c_client->addr); | 700 | i2c_client->addr); |
| 668 | return -ENODEV; | 701 | return -ENODEV; |
| @@ -670,17 +703,9 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, | |||
| 670 | 703 | ||
| 671 | dev_info(&i2c_client->dev, "found device at i2c address %X\n", | 704 | dev_info(&i2c_client->dev, "found device at i2c address %X\n", |
| 672 | i2c_client->addr); | 705 | i2c_client->addr); |
| 673 | dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF); | 706 | dev_info(&i2c_client->dev, "hardware revision %X\n", val & 0xF); |
| 674 | |||
| 675 | cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private), | ||
| 676 | GFP_KERNEL); | ||
| 677 | if (!cs4270) { | ||
| 678 | dev_err(&i2c_client->dev, "could not allocate codec\n"); | ||
| 679 | return -ENOMEM; | ||
| 680 | } | ||
| 681 | 707 | ||
| 682 | i2c_set_clientdata(i2c_client, cs4270); | 708 | i2c_set_clientdata(i2c_client, cs4270); |
| 683 | cs4270->control_type = SND_SOC_I2C; | ||
| 684 | 709 | ||
| 685 | ret = snd_soc_register_codec(&i2c_client->dev, | 710 | ret = snd_soc_register_codec(&i2c_client->dev, |
| 686 | &soc_codec_device_cs4270, &cs4270_dai, 1); | 711 | &soc_codec_device_cs4270, &cs4270_dai, 1); |
| @@ -718,23 +743,14 @@ static struct i2c_driver cs4270_i2c_driver = { | |||
| 718 | .driver = { | 743 | .driver = { |
| 719 | .name = "cs4270", | 744 | .name = "cs4270", |
| 720 | .owner = THIS_MODULE, | 745 | .owner = THIS_MODULE, |
| 746 | .of_match_table = cs4270_of_match, | ||
| 721 | }, | 747 | }, |
| 722 | .id_table = cs4270_id, | 748 | .id_table = cs4270_id, |
| 723 | .probe = cs4270_i2c_probe, | 749 | .probe = cs4270_i2c_probe, |
| 724 | .remove = cs4270_i2c_remove, | 750 | .remove = cs4270_i2c_remove, |
| 725 | }; | 751 | }; |
| 726 | 752 | ||
| 727 | static int __init cs4270_init(void) | 753 | module_i2c_driver(cs4270_i2c_driver); |
| 728 | { | ||
| 729 | return i2c_add_driver(&cs4270_i2c_driver); | ||
| 730 | } | ||
| 731 | module_init(cs4270_init); | ||
| 732 | |||
| 733 | static void __exit cs4270_exit(void) | ||
| 734 | { | ||
| 735 | i2c_del_driver(&cs4270_i2c_driver); | ||
| 736 | } | ||
| 737 | module_exit(cs4270_exit); | ||
| 738 | 754 | ||
| 739 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | 755 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); |
| 740 | MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); | 756 | MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); |
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index 9eb01d7d58a3..f994af34f552 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c | |||
| @@ -22,12 +22,14 @@ | |||
| 22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
| 23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 25 | #include <sound/pcm.h> | ||
| 26 | #include <sound/soc.h> | ||
| 27 | #include <sound/tlv.h> | ||
| 28 | #include <linux/gpio.h> | 25 | #include <linux/gpio.h> |
| 29 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
| 30 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
| 28 | #include <linux/of_device.h> | ||
| 29 | #include <linux/of_gpio.h> | ||
| 30 | #include <sound/pcm.h> | ||
| 31 | #include <sound/soc.h> | ||
| 32 | #include <sound/tlv.h> | ||
| 31 | #include <sound/cs4271.h> | 33 | #include <sound/cs4271.h> |
| 32 | 34 | ||
| 33 | #define CS4271_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ | 35 | #define CS4271_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \ |
| @@ -458,6 +460,14 @@ static int cs4271_soc_resume(struct snd_soc_codec *codec) | |||
| 458 | #define cs4271_soc_resume NULL | 460 | #define cs4271_soc_resume NULL |
| 459 | #endif /* CONFIG_PM */ | 461 | #endif /* CONFIG_PM */ |
| 460 | 462 | ||
| 463 | #ifdef CONFIG_OF | ||
| 464 | static const struct of_device_id cs4271_dt_ids[] = { | ||
| 465 | { .compatible = "cirrus,cs4271", }, | ||
| 466 | { } | ||
| 467 | }; | ||
| 468 | MODULE_DEVICE_TABLE(of, cs4271_dt_ids); | ||
| 469 | #endif | ||
| 470 | |||
| 461 | static int cs4271_probe(struct snd_soc_codec *codec) | 471 | static int cs4271_probe(struct snd_soc_codec *codec) |
| 462 | { | 472 | { |
| 463 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); | 473 | struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec); |
| @@ -465,6 +475,12 @@ static int cs4271_probe(struct snd_soc_codec *codec) | |||
| 465 | int ret; | 475 | int ret; |
| 466 | int gpio_nreset = -EINVAL; | 476 | int gpio_nreset = -EINVAL; |
| 467 | 477 | ||
| 478 | #ifdef CONFIG_OF | ||
| 479 | if (of_match_device(cs4271_dt_ids, codec->dev)) | ||
| 480 | gpio_nreset = of_get_named_gpio(codec->dev->of_node, | ||
| 481 | "reset-gpio", 0); | ||
| 482 | #endif | ||
| 483 | |||
| 468 | if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset)) | 484 | if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset)) |
| 469 | gpio_nreset = cs4271plat->gpio_nreset; | 485 | gpio_nreset = cs4271plat->gpio_nreset; |
| 470 | 486 | ||
| @@ -569,6 +585,7 @@ static struct spi_driver cs4271_spi_driver = { | |||
| 569 | .driver = { | 585 | .driver = { |
| 570 | .name = "cs4271", | 586 | .name = "cs4271", |
| 571 | .owner = THIS_MODULE, | 587 | .owner = THIS_MODULE, |
| 588 | .of_match_table = of_match_ptr(cs4271_dt_ids), | ||
| 572 | }, | 589 | }, |
| 573 | .probe = cs4271_spi_probe, | 590 | .probe = cs4271_spi_probe, |
| 574 | .remove = __devexit_p(cs4271_spi_remove), | 591 | .remove = __devexit_p(cs4271_spi_remove), |
| @@ -608,6 +625,7 @@ static struct i2c_driver cs4271_i2c_driver = { | |||
| 608 | .driver = { | 625 | .driver = { |
| 609 | .name = "cs4271", | 626 | .name = "cs4271", |
| 610 | .owner = THIS_MODULE, | 627 | .owner = THIS_MODULE, |
| 628 | .of_match_table = of_match_ptr(cs4271_dt_ids), | ||
| 611 | }, | 629 | }, |
| 612 | .id_table = cs4271_i2c_id, | 630 | .id_table = cs4271_i2c_id, |
| 613 | .probe = cs4271_i2c_probe, | 631 | .probe = cs4271_i2c_probe, |
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 091d0193f507..1e0fa3b5f79a 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c | |||
| @@ -614,24 +614,7 @@ static struct i2c_driver cs42l51_i2c_driver = { | |||
| 614 | .remove = cs42l51_i2c_remove, | 614 | .remove = cs42l51_i2c_remove, |
| 615 | }; | 615 | }; |
| 616 | 616 | ||
| 617 | static int __init cs42l51_init(void) | 617 | module_i2c_driver(cs42l51_i2c_driver); |
| 618 | { | ||
| 619 | int ret; | ||
| 620 | |||
| 621 | ret = i2c_add_driver(&cs42l51_i2c_driver); | ||
| 622 | if (ret != 0) { | ||
| 623 | printk(KERN_ERR "%s: can't add i2c driver\n", __func__); | ||
| 624 | return ret; | ||
| 625 | } | ||
| 626 | return 0; | ||
| 627 | } | ||
| 628 | module_init(cs42l51_init); | ||
| 629 | |||
| 630 | static void __exit cs42l51_exit(void) | ||
| 631 | { | ||
| 632 | i2c_del_driver(&cs42l51_i2c_driver); | ||
| 633 | } | ||
| 634 | module_exit(cs42l51_exit); | ||
| 635 | 618 | ||
| 636 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); | 619 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); |
| 637 | MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); | 620 | MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); |
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 628daf6a1d97..61599298fb26 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
| @@ -24,7 +24,6 @@ | |||
| 24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 25 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
| 26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
| 27 | #include <linux/slab.h> | ||
| 28 | #include <sound/core.h> | 27 | #include <sound/core.h> |
| 29 | #include <sound/pcm.h> | 28 | #include <sound/pcm.h> |
| 30 | #include <sound/pcm_params.h> | 29 | #include <sound/pcm_params.h> |
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c new file mode 100644 index 000000000000..185d8dd36399 --- /dev/null +++ b/sound/soc/codecs/da9055.c | |||
| @@ -0,0 +1,1510 @@ | |||
| 1 | /* | ||
| 2 | * DA9055 ALSA Soc codec driver | ||
| 3 | * | ||
| 4 | * Copyright (c) 2012 Dialog Semiconductor | ||
| 5 | * | ||
| 6 | * Tested on (Samsung SMDK6410 board + DA9055 EVB) using I2S and I2C | ||
| 7 | * Written by David Chen <david.chen@diasemi.com> and | ||
| 8 | * Ashish Chavan <ashish.chavan@kpitcummins.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms of the GNU General Public License as published by the | ||
| 12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 13 | * option) any later version. | ||
| 14 | */ | ||
| 15 | |||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/i2c.h> | ||
| 18 | #include <linux/regmap.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | #include <sound/pcm.h> | ||
| 22 | #include <sound/pcm_params.h> | ||
| 23 | #include <sound/soc.h> | ||
| 24 | #include <sound/initval.h> | ||
| 25 | #include <sound/tlv.h> | ||
| 26 | #include <sound/da9055.h> | ||
| 27 | |||
| 28 | /* DA9055 register space */ | ||
| 29 | |||
| 30 | /* Status Registers */ | ||
| 31 | #define DA9055_STATUS1 0x02 | ||
| 32 | #define DA9055_PLL_STATUS 0x03 | ||
| 33 | #define DA9055_AUX_L_GAIN_STATUS 0x04 | ||
| 34 | #define DA9055_AUX_R_GAIN_STATUS 0x05 | ||
| 35 | #define DA9055_MIC_L_GAIN_STATUS 0x06 | ||
| 36 | #define DA9055_MIC_R_GAIN_STATUS 0x07 | ||
| 37 | #define DA9055_MIXIN_L_GAIN_STATUS 0x08 | ||
| 38 | #define DA9055_MIXIN_R_GAIN_STATUS 0x09 | ||
| 39 | #define DA9055_ADC_L_GAIN_STATUS 0x0A | ||
| 40 | #define DA9055_ADC_R_GAIN_STATUS 0x0B | ||
| 41 | #define DA9055_DAC_L_GAIN_STATUS 0x0C | ||
| 42 | #define DA9055_DAC_R_GAIN_STATUS 0x0D | ||
| 43 | #define DA9055_HP_L_GAIN_STATUS 0x0E | ||
| 44 | #define DA9055_HP_R_GAIN_STATUS 0x0F | ||
| 45 | #define DA9055_LINE_GAIN_STATUS 0x10 | ||
| 46 | |||
| 47 | /* System Initialisation Registers */ | ||
| 48 | #define DA9055_CIF_CTRL 0x20 | ||
| 49 | #define DA9055_DIG_ROUTING_AIF 0X21 | ||
| 50 | #define DA9055_SR 0x22 | ||
| 51 | #define DA9055_REFERENCES 0x23 | ||
| 52 | #define DA9055_PLL_FRAC_TOP 0x24 | ||
| 53 | #define DA9055_PLL_FRAC_BOT 0x25 | ||
| 54 | #define DA9055_PLL_INTEGER 0x26 | ||
| 55 | #define DA9055_PLL_CTRL 0x27 | ||
| 56 | #define DA9055_AIF_CLK_MODE 0x28 | ||
| 57 | #define DA9055_AIF_CTRL 0x29 | ||
| 58 | #define DA9055_DIG_ROUTING_DAC 0x2A | ||
| 59 | #define DA9055_ALC_CTRL1 0x2B | ||
| 60 | |||
| 61 | /* Input - Gain, Select and Filter Registers */ | ||
| 62 | #define DA9055_AUX_L_GAIN 0x30 | ||
| 63 | #define DA9055_AUX_R_GAIN 0x31 | ||
| 64 | #define DA9055_MIXIN_L_SELECT 0x32 | ||
| 65 | #define DA9055_MIXIN_R_SELECT 0x33 | ||
| 66 | #define DA9055_MIXIN_L_GAIN 0x34 | ||
| 67 | #define DA9055_MIXIN_R_GAIN 0x35 | ||
| 68 | #define DA9055_ADC_L_GAIN 0x36 | ||
| 69 | #define DA9055_ADC_R_GAIN 0x37 | ||
| 70 | #define DA9055_ADC_FILTERS1 0x38 | ||
| 71 | #define DA9055_MIC_L_GAIN 0x39 | ||
| 72 | #define DA9055_MIC_R_GAIN 0x3A | ||
| 73 | |||
| 74 | /* Output - Gain, Select and Filter Registers */ | ||
| 75 | #define DA9055_DAC_FILTERS5 0x40 | ||
| 76 | #define DA9055_DAC_FILTERS2 0x41 | ||
| 77 | #define DA9055_DAC_FILTERS3 0x42 | ||
| 78 | #define DA9055_DAC_FILTERS4 0x43 | ||
| 79 | #define DA9055_DAC_FILTERS1 0x44 | ||
| 80 | #define DA9055_DAC_L_GAIN 0x45 | ||
| 81 | #define DA9055_DAC_R_GAIN 0x46 | ||
| 82 | #define DA9055_CP_CTRL 0x47 | ||
| 83 | #define DA9055_HP_L_GAIN 0x48 | ||
| 84 | #define DA9055_HP_R_GAIN 0x49 | ||
| 85 | #define DA9055_LINE_GAIN 0x4A | ||
| 86 | #define DA9055_MIXOUT_L_SELECT 0x4B | ||
| 87 | #define DA9055_MIXOUT_R_SELECT 0x4C | ||
| 88 | |||
| 89 | /* System Controller Registers */ | ||
| 90 | #define DA9055_SYSTEM_MODES_INPUT 0x50 | ||
| 91 | #define DA9055_SYSTEM_MODES_OUTPUT 0x51 | ||
| 92 | |||
| 93 | /* Control Registers */ | ||
| 94 | #define DA9055_AUX_L_CTRL 0x60 | ||
| 95 | #define DA9055_AUX_R_CTRL 0x61 | ||
| 96 | #define DA9055_MIC_BIAS_CTRL 0x62 | ||
| 97 | #define DA9055_MIC_L_CTRL 0x63 | ||
| 98 | #define DA9055_MIC_R_CTRL 0x64 | ||
| 99 | #define DA9055_MIXIN_L_CTRL 0x65 | ||
| 100 | #define DA9055_MIXIN_R_CTRL 0x66 | ||
| 101 | #define DA9055_ADC_L_CTRL 0x67 | ||
| 102 | #define DA9055_ADC_R_CTRL 0x68 | ||
| 103 | #define DA9055_DAC_L_CTRL 0x69 | ||
| 104 | #define DA9055_DAC_R_CTRL 0x6A | ||
| 105 | #define DA9055_HP_L_CTRL 0x6B | ||
| 106 | #define DA9055_HP_R_CTRL 0x6C | ||
| 107 | #define DA9055_LINE_CTRL 0x6D | ||
| 108 | #define DA9055_MIXOUT_L_CTRL 0x6E | ||
| 109 | #define DA9055_MIXOUT_R_CTRL 0x6F | ||
| 110 | |||
| 111 | /* Configuration Registers */ | ||
| 112 | #define DA9055_LDO_CTRL 0x90 | ||
| 113 | #define DA9055_IO_CTRL 0x91 | ||
| 114 | #define DA9055_GAIN_RAMP_CTRL 0x92 | ||
| 115 | #define DA9055_MIC_CONFIG 0x93 | ||
| 116 | #define DA9055_PC_COUNT 0x94 | ||
| 117 | #define DA9055_CP_VOL_THRESHOLD1 0x95 | ||
| 118 | #define DA9055_CP_DELAY 0x96 | ||
| 119 | #define DA9055_CP_DETECTOR 0x97 | ||
| 120 | #define DA9055_AIF_OFFSET 0x98 | ||
| 121 | #define DA9055_DIG_CTRL 0x99 | ||
| 122 | #define DA9055_ALC_CTRL2 0x9A | ||
| 123 | #define DA9055_ALC_CTRL3 0x9B | ||
| 124 | #define DA9055_ALC_NOISE 0x9C | ||
| 125 | #define DA9055_ALC_TARGET_MIN 0x9D | ||
| 126 | #define DA9055_ALC_TARGET_MAX 0x9E | ||
| 127 | #define DA9055_ALC_GAIN_LIMITS 0x9F | ||
| 128 | #define DA9055_ALC_ANA_GAIN_LIMITS 0xA0 | ||
| 129 | #define DA9055_ALC_ANTICLIP_CTRL 0xA1 | ||
| 130 | #define DA9055_ALC_ANTICLIP_LEVEL 0xA2 | ||
| 131 | #define DA9055_ALC_OFFSET_OP2M_L 0xA6 | ||
| 132 | #define DA9055_ALC_OFFSET_OP2U_L 0xA7 | ||
| 133 | #define DA9055_ALC_OFFSET_OP2M_R 0xAB | ||
| 134 | #define DA9055_ALC_OFFSET_OP2U_R 0xAC | ||
| 135 | #define DA9055_ALC_CIC_OP_LVL_CTRL 0xAD | ||
| 136 | #define DA9055_ALC_CIC_OP_LVL_DATA 0xAE | ||
| 137 | #define DA9055_DAC_NG_SETUP_TIME 0xAF | ||
| 138 | #define DA9055_DAC_NG_OFF_THRESHOLD 0xB0 | ||
| 139 | #define DA9055_DAC_NG_ON_THRESHOLD 0xB1 | ||
| 140 | #define DA9055_DAC_NG_CTRL 0xB2 | ||
| 141 | |||
| 142 | /* SR bit fields */ | ||
| 143 | #define DA9055_SR_8000 (0x1 << 0) | ||
| 144 | #define DA9055_SR_11025 (0x2 << 0) | ||
| 145 | #define DA9055_SR_12000 (0x3 << 0) | ||
| 146 | #define DA9055_SR_16000 (0x5 << 0) | ||
| 147 | #define DA9055_SR_22050 (0x6 << 0) | ||
| 148 | #define DA9055_SR_24000 (0x7 << 0) | ||
| 149 | #define DA9055_SR_32000 (0x9 << 0) | ||
| 150 | #define DA9055_SR_44100 (0xA << 0) | ||
| 151 | #define DA9055_SR_48000 (0xB << 0) | ||
| 152 | #define DA9055_SR_88200 (0xE << 0) | ||
| 153 | #define DA9055_SR_96000 (0xF << 0) | ||
| 154 | |||
| 155 | /* REFERENCES bit fields */ | ||
| 156 | #define DA9055_BIAS_EN (1 << 3) | ||
| 157 | #define DA9055_VMID_EN (1 << 7) | ||
| 158 | |||
| 159 | /* PLL_CTRL bit fields */ | ||
| 160 | #define DA9055_PLL_INDIV_10_20_MHZ (1 << 2) | ||
| 161 | #define DA9055_PLL_SRM_EN (1 << 6) | ||
| 162 | #define DA9055_PLL_EN (1 << 7) | ||
| 163 | |||
| 164 | /* AIF_CLK_MODE bit fields */ | ||
| 165 | #define DA9055_AIF_BCLKS_PER_WCLK_32 (0 << 0) | ||
| 166 | #define DA9055_AIF_BCLKS_PER_WCLK_64 (1 << 0) | ||
| 167 | #define DA9055_AIF_BCLKS_PER_WCLK_128 (2 << 0) | ||
| 168 | #define DA9055_AIF_BCLKS_PER_WCLK_256 (3 << 0) | ||
| 169 | #define DA9055_AIF_CLK_EN_SLAVE_MODE (0 << 7) | ||
| 170 | #define DA9055_AIF_CLK_EN_MASTER_MODE (1 << 7) | ||
| 171 | |||
| 172 | /* AIF_CTRL bit fields */ | ||
| 173 | #define DA9055_AIF_FORMAT_I2S_MODE (0 << 0) | ||
| 174 | #define DA9055_AIF_FORMAT_LEFT_J (1 << 0) | ||
| 175 | #define DA9055_AIF_FORMAT_RIGHT_J (2 << 0) | ||
| 176 | #define DA9055_AIF_WORD_S16_LE (0 << 2) | ||
| 177 | #define DA9055_AIF_WORD_S20_3LE (1 << 2) | ||
| 178 | #define DA9055_AIF_WORD_S24_LE (2 << 2) | ||
| 179 | #define DA9055_AIF_WORD_S32_LE (3 << 2) | ||
| 180 | |||
| 181 | /* MIXIN_L_CTRL bit fields */ | ||
| 182 | #define DA9055_MIXIN_L_MIX_EN (1 << 3) | ||
| 183 | |||
| 184 | /* MIXIN_R_CTRL bit fields */ | ||
| 185 | #define DA9055_MIXIN_R_MIX_EN (1 << 3) | ||
| 186 | |||
| 187 | /* ADC_L_CTRL bit fields */ | ||
| 188 | #define DA9055_ADC_L_EN (1 << 7) | ||
| 189 | |||
| 190 | /* ADC_R_CTRL bit fields */ | ||
| 191 | #define DA9055_ADC_R_EN (1 << 7) | ||
| 192 | |||
| 193 | /* DAC_L_CTRL bit fields */ | ||
| 194 | #define DA9055_DAC_L_MUTE_EN (1 << 6) | ||
| 195 | |||
| 196 | /* DAC_R_CTRL bit fields */ | ||
| 197 | #define DA9055_DAC_R_MUTE_EN (1 << 6) | ||
| 198 | |||
| 199 | /* HP_L_CTRL bit fields */ | ||
| 200 | #define DA9055_HP_L_AMP_OE (1 << 3) | ||
| 201 | |||
| 202 | /* HP_R_CTRL bit fields */ | ||
| 203 | #define DA9055_HP_R_AMP_OE (1 << 3) | ||
| 204 | |||
| 205 | /* LINE_CTRL bit fields */ | ||
| 206 | #define DA9055_LINE_AMP_OE (1 << 3) | ||
| 207 | |||
| 208 | /* MIXOUT_L_CTRL bit fields */ | ||
| 209 | #define DA9055_MIXOUT_L_MIX_EN (1 << 3) | ||
| 210 | |||
| 211 | /* MIXOUT_R_CTRL bit fields */ | ||
| 212 | #define DA9055_MIXOUT_R_MIX_EN (1 << 3) | ||
| 213 | |||
| 214 | /* MIC bias select bit fields */ | ||
| 215 | #define DA9055_MICBIAS2_EN (1 << 6) | ||
| 216 | |||
| 217 | /* ALC_CIC_OP_LEVEL_CTRL bit fields */ | ||
| 218 | #define DA9055_ALC_DATA_MIDDLE (2 << 0) | ||
| 219 | #define DA9055_ALC_DATA_TOP (3 << 0) | ||
| 220 | #define DA9055_ALC_CIC_OP_CHANNEL_LEFT (0 << 7) | ||
| 221 | #define DA9055_ALC_CIC_OP_CHANNEL_RIGHT (1 << 7) | ||
| 222 | |||
| 223 | #define DA9055_AIF_BCLK_MASK (3 << 0) | ||
| 224 | #define DA9055_AIF_CLK_MODE_MASK (1 << 7) | ||
| 225 | #define DA9055_AIF_FORMAT_MASK (3 << 0) | ||
| 226 | #define DA9055_AIF_WORD_LENGTH_MASK (3 << 2) | ||
| 227 | #define DA9055_GAIN_RAMPING_EN (1 << 5) | ||
| 228 | #define DA9055_MICBIAS_LEVEL_MASK (3 << 4) | ||
| 229 | |||
| 230 | #define DA9055_ALC_OFFSET_15_8 0x00FF00 | ||
| 231 | #define DA9055_ALC_OFFSET_17_16 0x030000 | ||
| 232 | #define DA9055_ALC_AVG_ITERATIONS 5 | ||
| 233 | |||
| 234 | struct pll_div { | ||
| 235 | int fref; | ||
| 236 | int fout; | ||
| 237 | u8 frac_top; | ||
| 238 | u8 frac_bot; | ||
| 239 | u8 integer; | ||
| 240 | u8 mode; /* 0 = slave, 1 = master */ | ||
| 241 | }; | ||
| 242 | |||
| 243 | /* PLL divisor table */ | ||
| 244 | static const struct pll_div da9055_pll_div[] = { | ||
| 245 | /* for MASTER mode, fs = 44.1Khz and its harmonics */ | ||
| 246 | {11289600, 2822400, 0x00, 0x00, 0x20, 1}, /* MCLK=11.2896Mhz */ | ||
| 247 | {12000000, 2822400, 0x03, 0x61, 0x1E, 1}, /* MCLK=12Mhz */ | ||
| 248 | {12288000, 2822400, 0x0C, 0xCC, 0x1D, 1}, /* MCLK=12.288Mhz */ | ||
| 249 | {13000000, 2822400, 0x19, 0x45, 0x1B, 1}, /* MCLK=13Mhz */ | ||
| 250 | {13500000, 2822400, 0x18, 0x56, 0x1A, 1}, /* MCLK=13.5Mhz */ | ||
| 251 | {14400000, 2822400, 0x02, 0xD0, 0x19, 1}, /* MCLK=14.4Mhz */ | ||
| 252 | {19200000, 2822400, 0x1A, 0x1C, 0x12, 1}, /* MCLK=19.2Mhz */ | ||
| 253 | {19680000, 2822400, 0x0B, 0x6D, 0x12, 1}, /* MCLK=19.68Mhz */ | ||
| 254 | {19800000, 2822400, 0x07, 0xDD, 0x12, 1}, /* MCLK=19.8Mhz */ | ||
| 255 | /* for MASTER mode, fs = 48Khz and its harmonics */ | ||
| 256 | {11289600, 3072000, 0x1A, 0x8E, 0x22, 1}, /* MCLK=11.2896Mhz */ | ||
| 257 | {12000000, 3072000, 0x18, 0x93, 0x20, 1}, /* MCLK=12Mhz */ | ||
| 258 | {12288000, 3072000, 0x00, 0x00, 0x20, 1}, /* MCLK=12.288Mhz */ | ||
| 259 | {13000000, 3072000, 0x07, 0xEA, 0x1E, 1}, /* MCLK=13Mhz */ | ||
| 260 | {13500000, 3072000, 0x04, 0x11, 0x1D, 1}, /* MCLK=13.5Mhz */ | ||
| 261 | {14400000, 3072000, 0x09, 0xD0, 0x1B, 1}, /* MCLK=14.4Mhz */ | ||
| 262 | {19200000, 3072000, 0x0F, 0x5C, 0x14, 1}, /* MCLK=19.2Mhz */ | ||
| 263 | {19680000, 3072000, 0x1F, 0x60, 0x13, 1}, /* MCLK=19.68Mhz */ | ||
| 264 | {19800000, 3072000, 0x1B, 0x80, 0x13, 1}, /* MCLK=19.8Mhz */ | ||
| 265 | /* for SLAVE mode with SRM */ | ||
| 266 | {11289600, 2822400, 0x0D, 0x47, 0x21, 0}, /* MCLK=11.2896Mhz */ | ||
| 267 | {12000000, 2822400, 0x0D, 0xFA, 0x1F, 0}, /* MCLK=12Mhz */ | ||
| 268 | {12288000, 2822400, 0x16, 0x66, 0x1E, 0}, /* MCLK=12.288Mhz */ | ||
| 269 | {13000000, 2822400, 0x00, 0x98, 0x1D, 0}, /* MCLK=13Mhz */ | ||
| 270 | {13500000, 2822400, 0x1E, 0x33, 0x1B, 0}, /* MCLK=13.5Mhz */ | ||
| 271 | {14400000, 2822400, 0x06, 0x50, 0x1A, 0}, /* MCLK=14.4Mhz */ | ||
| 272 | {19200000, 2822400, 0x14, 0xBC, 0x13, 0}, /* MCLK=19.2Mhz */ | ||
| 273 | {19680000, 2822400, 0x05, 0x66, 0x13, 0}, /* MCLK=19.68Mhz */ | ||
| 274 | {19800000, 2822400, 0x01, 0xAE, 0x13, 0}, /* MCLK=19.8Mhz */ | ||
| 275 | }; | ||
| 276 | |||
| 277 | enum clk_src { | ||
| 278 | DA9055_CLKSRC_MCLK | ||
| 279 | }; | ||
| 280 | |||
| 281 | /* Gain and Volume */ | ||
| 282 | |||
| 283 | static const unsigned int aux_vol_tlv[] = { | ||
| 284 | TLV_DB_RANGE_HEAD(2), | ||
| 285 | 0x0, 0x10, TLV_DB_SCALE_ITEM(-5400, 0, 0), | ||
| 286 | /* -54dB to 15dB */ | ||
| 287 | 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0) | ||
| 288 | }; | ||
| 289 | |||
| 290 | static const unsigned int digital_gain_tlv[] = { | ||
| 291 | TLV_DB_RANGE_HEAD(2), | ||
| 292 | 0x0, 0x07, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), | ||
| 293 | /* -78dB to 12dB */ | ||
| 294 | 0x08, 0x7f, TLV_DB_SCALE_ITEM(-7800, 75, 0) | ||
| 295 | }; | ||
| 296 | |||
| 297 | static const unsigned int alc_analog_gain_tlv[] = { | ||
| 298 | TLV_DB_RANGE_HEAD(2), | ||
| 299 | 0x0, 0x0, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1), | ||
| 300 | /* 0dB to 36dB */ | ||
| 301 | 0x01, 0x07, TLV_DB_SCALE_ITEM(0, 600, 0) | ||
| 302 | }; | ||
| 303 | |||
| 304 | static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, -600, 600, 0); | ||
| 305 | static const DECLARE_TLV_DB_SCALE(mixin_gain_tlv, -450, 150, 0); | ||
| 306 | static const DECLARE_TLV_DB_SCALE(eq_gain_tlv, -1050, 150, 0); | ||
| 307 | static const DECLARE_TLV_DB_SCALE(hp_vol_tlv, -5700, 100, 0); | ||
| 308 | static const DECLARE_TLV_DB_SCALE(lineout_vol_tlv, -4800, 100, 0); | ||
| 309 | static const DECLARE_TLV_DB_SCALE(alc_threshold_tlv, -9450, 150, 0); | ||
| 310 | static const DECLARE_TLV_DB_SCALE(alc_gain_tlv, 0, 600, 0); | ||
| 311 | |||
| 312 | /* ADC and DAC high pass filter cutoff value */ | ||
| 313 | static const char * const da9055_hpf_cutoff_txt[] = { | ||
| 314 | "Fs/24000", "Fs/12000", "Fs/6000", "Fs/3000" | ||
| 315 | }; | ||
| 316 | |||
| 317 | static const struct soc_enum da9055_dac_hpf_cutoff = | ||
| 318 | SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt); | ||
| 319 | |||
| 320 | static const struct soc_enum da9055_adc_hpf_cutoff = | ||
| 321 | SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 4, 4, da9055_hpf_cutoff_txt); | ||
| 322 | |||
| 323 | /* ADC and DAC voice mode (8kHz) high pass cutoff value */ | ||
| 324 | static const char * const da9055_vf_cutoff_txt[] = { | ||
| 325 | "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz" | ||
| 326 | }; | ||
| 327 | |||
| 328 | static const struct soc_enum da9055_dac_vf_cutoff = | ||
| 329 | SOC_ENUM_SINGLE(DA9055_DAC_FILTERS1, 0, 8, da9055_vf_cutoff_txt); | ||
| 330 | |||
| 331 | static const struct soc_enum da9055_adc_vf_cutoff = | ||
| 332 | SOC_ENUM_SINGLE(DA9055_ADC_FILTERS1, 0, 8, da9055_vf_cutoff_txt); | ||
| 333 | |||
| 334 | /* Gain ramping rate value */ | ||
| 335 | static const char * const da9055_gain_ramping_txt[] = { | ||
| 336 | "nominal rate", "nominal rate * 4", "nominal rate * 8", | ||
| 337 | "nominal rate / 8" | ||
| 338 | }; | ||
| 339 | |||
| 340 | static const struct soc_enum da9055_gain_ramping_rate = | ||
| 341 | SOC_ENUM_SINGLE(DA9055_GAIN_RAMP_CTRL, 0, 4, da9055_gain_ramping_txt); | ||
| 342 | |||
| 343 | /* DAC noise gate setup time value */ | ||
| 344 | static const char * const da9055_dac_ng_setup_time_txt[] = { | ||
| 345 | "256 samples", "512 samples", "1024 samples", "2048 samples" | ||
| 346 | }; | ||
| 347 | |||
| 348 | static const struct soc_enum da9055_dac_ng_setup_time = | ||
| 349 | SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 0, 4, | ||
| 350 | da9055_dac_ng_setup_time_txt); | ||
| 351 | |||
| 352 | /* DAC noise gate rampup rate value */ | ||
| 353 | static const char * const da9055_dac_ng_rampup_txt[] = { | ||
| 354 | "0.02 ms/dB", "0.16 ms/dB" | ||
| 355 | }; | ||
| 356 | |||
| 357 | static const struct soc_enum da9055_dac_ng_rampup_rate = | ||
| 358 | SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 2, 2, | ||
| 359 | da9055_dac_ng_rampup_txt); | ||
| 360 | |||
| 361 | /* DAC noise gate rampdown rate value */ | ||
| 362 | static const char * const da9055_dac_ng_rampdown_txt[] = { | ||
| 363 | "0.64 ms/dB", "20.48 ms/dB" | ||
| 364 | }; | ||
| 365 | |||
| 366 | static const struct soc_enum da9055_dac_ng_rampdown_rate = | ||
| 367 | SOC_ENUM_SINGLE(DA9055_DAC_NG_SETUP_TIME, 3, 2, | ||
| 368 | da9055_dac_ng_rampdown_txt); | ||
| 369 | |||
| 370 | /* DAC soft mute rate value */ | ||
| 371 | static const char * const da9055_dac_soft_mute_rate_txt[] = { | ||
| 372 | "1", "2", "4", "8", "16", "32", "64" | ||
| 373 | }; | ||
| 374 | |||
| 375 | static const struct soc_enum da9055_dac_soft_mute_rate = | ||
| 376 | SOC_ENUM_SINGLE(DA9055_DAC_FILTERS5, 4, 7, | ||
| 377 | da9055_dac_soft_mute_rate_txt); | ||
| 378 | |||
| 379 | /* DAC routing select */ | ||
| 380 | static const char * const da9055_dac_src_txt[] = { | ||
| 381 | "ADC output left", "ADC output right", "AIF input left", | ||
| 382 | "AIF input right" | ||
| 383 | }; | ||
| 384 | |||
| 385 | static const struct soc_enum da9055_dac_l_src = | ||
| 386 | SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 0, 4, da9055_dac_src_txt); | ||
| 387 | |||
| 388 | static const struct soc_enum da9055_dac_r_src = | ||
| 389 | SOC_ENUM_SINGLE(DA9055_DIG_ROUTING_DAC, 4, 4, da9055_dac_src_txt); | ||
| 390 | |||
| 391 | /* MIC PGA Left source select */ | ||
| 392 | static const char * const da9055_mic_l_src_txt[] = { | ||
| 393 | "MIC1_P_N", "MIC1_P", "MIC1_N", "MIC2_L" | ||
| 394 | }; | ||
| 395 | |||
| 396 | static const struct soc_enum da9055_mic_l_src = | ||
| 397 | SOC_ENUM_SINGLE(DA9055_MIXIN_L_SELECT, 4, 4, da9055_mic_l_src_txt); | ||
| 398 | |||
| 399 | /* MIC PGA Right source select */ | ||
| 400 | static const char * const da9055_mic_r_src_txt[] = { | ||
| 401 | "MIC2_R_L", "MIC2_R", "MIC2_L" | ||
| 402 | }; | ||
| 403 | |||
| 404 | static const struct soc_enum da9055_mic_r_src = | ||
| 405 | SOC_ENUM_SINGLE(DA9055_MIXIN_R_SELECT, 4, 3, da9055_mic_r_src_txt); | ||
| 406 | |||
| 407 | /* ALC Input Signal Tracking rate select */ | ||
| 408 | static const char * const da9055_signal_tracking_rate_txt[] = { | ||
| 409 | "1/4", "1/16", "1/256", "1/65536" | ||
| 410 | }; | ||
| 411 | |||
| 412 | static const struct soc_enum da9055_integ_attack_rate = | ||
| 413 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 4, 4, | ||
| 414 | da9055_signal_tracking_rate_txt); | ||
| 415 | |||
| 416 | static const struct soc_enum da9055_integ_release_rate = | ||
| 417 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 6, 4, | ||
| 418 | da9055_signal_tracking_rate_txt); | ||
| 419 | |||
| 420 | /* ALC Attack Rate select */ | ||
| 421 | static const char * const da9055_attack_rate_txt[] = { | ||
| 422 | "44/fs", "88/fs", "176/fs", "352/fs", "704/fs", "1408/fs", "2816/fs", | ||
| 423 | "5632/fs", "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" | ||
| 424 | }; | ||
| 425 | |||
| 426 | static const struct soc_enum da9055_attack_rate = | ||
| 427 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 0, 13, da9055_attack_rate_txt); | ||
| 428 | |||
| 429 | /* ALC Release Rate select */ | ||
| 430 | static const char * const da9055_release_rate_txt[] = { | ||
| 431 | "176/fs", "352/fs", "704/fs", "1408/fs", "2816/fs", "5632/fs", | ||
| 432 | "11264/fs", "22528/fs", "45056/fs", "90112/fs", "180224/fs" | ||
| 433 | }; | ||
| 434 | |||
| 435 | static const struct soc_enum da9055_release_rate = | ||
| 436 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL2, 4, 11, da9055_release_rate_txt); | ||
| 437 | |||
| 438 | /* ALC Hold Time select */ | ||
| 439 | static const char * const da9055_hold_time_txt[] = { | ||
| 440 | "62/fs", "124/fs", "248/fs", "496/fs", "992/fs", "1984/fs", "3968/fs", | ||
| 441 | "7936/fs", "15872/fs", "31744/fs", "63488/fs", "126976/fs", | ||
| 442 | "253952/fs", "507904/fs", "1015808/fs", "2031616/fs" | ||
| 443 | }; | ||
| 444 | |||
| 445 | static const struct soc_enum da9055_hold_time = | ||
| 446 | SOC_ENUM_SINGLE(DA9055_ALC_CTRL3, 0, 16, da9055_hold_time_txt); | ||
| 447 | |||
| 448 | static int da9055_get_alc_data(struct snd_soc_codec *codec, u8 reg_val) | ||
| 449 | { | ||
| 450 | int mid_data, top_data; | ||
| 451 | int sum = 0; | ||
| 452 | u8 iteration; | ||
| 453 | |||
| 454 | for (iteration = 0; iteration < DA9055_ALC_AVG_ITERATIONS; | ||
| 455 | iteration++) { | ||
| 456 | /* Select the left or right channel and capture data */ | ||
| 457 | snd_soc_write(codec, DA9055_ALC_CIC_OP_LVL_CTRL, reg_val); | ||
| 458 | |||
| 459 | /* Select middle 8 bits for read back from data register */ | ||
| 460 | snd_soc_write(codec, DA9055_ALC_CIC_OP_LVL_CTRL, | ||
| 461 | reg_val | DA9055_ALC_DATA_MIDDLE); | ||
| 462 | mid_data = snd_soc_read(codec, DA9055_ALC_CIC_OP_LVL_DATA); | ||
| 463 | |||
| 464 | /* Select top 8 bits for read back from data register */ | ||
| 465 | snd_soc_write(codec, DA9055_ALC_CIC_OP_LVL_CTRL, | ||
| 466 | reg_val | DA9055_ALC_DATA_TOP); | ||
| 467 | top_data = snd_soc_read(codec, DA9055_ALC_CIC_OP_LVL_DATA); | ||
| 468 | |||
| 469 | sum += ((mid_data << 8) | (top_data << 16)); | ||
| 470 | } | ||
| 471 | |||
| 472 | return sum / DA9055_ALC_AVG_ITERATIONS; | ||
| 473 | } | ||
| 474 | |||
| 475 | static int da9055_put_alc_sw(struct snd_kcontrol *kcontrol, | ||
| 476 | struct snd_ctl_elem_value *ucontrol) | ||
| 477 | { | ||
| 478 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
| 479 | u8 reg_val, adc_left, adc_right; | ||
| 480 | int avg_left_data, avg_right_data, offset_l, offset_r; | ||
| 481 | |||
| 482 | if (ucontrol->value.integer.value[0]) { | ||
| 483 | /* | ||
| 484 | * While enabling ALC (or ALC sync mode), calibration of the DC | ||
| 485 | * offsets must be done first | ||
| 486 | */ | ||
| 487 | |||
| 488 | /* Save current values from ADC control registers */ | ||
| 489 | adc_left = snd_soc_read(codec, DA9055_ADC_L_CTRL); | ||
| 490 | adc_right = snd_soc_read(codec, DA9055_ADC_R_CTRL); | ||
| 491 | |||
| 492 | /* Enable ADC Left and Right */ | ||
| 493 | snd_soc_update_bits(codec, DA9055_ADC_L_CTRL, | ||
| 494 | DA9055_ADC_L_EN, DA9055_ADC_L_EN); | ||
| 495 | snd_soc_update_bits(codec, DA9055_ADC_R_CTRL, | ||
| 496 | DA9055_ADC_R_EN, DA9055_ADC_R_EN); | ||
| 497 | |||
| 498 | /* Calculate average for Left and Right data */ | ||
| 499 | /* Left Data */ | ||
| 500 | avg_left_data = da9055_get_alc_data(codec, | ||
| 501 | DA9055_ALC_CIC_OP_CHANNEL_LEFT); | ||
| 502 | /* Right Data */ | ||
| 503 | avg_right_data = da9055_get_alc_data(codec, | ||
| 504 | DA9055_ALC_CIC_OP_CHANNEL_RIGHT); | ||
| 505 | |||
| 506 | /* Calculate DC offset */ | ||
| 507 | offset_l = -avg_left_data; | ||
| 508 | offset_r = -avg_right_data; | ||
| 509 | |||
| 510 | reg_val = (offset_l & DA9055_ALC_OFFSET_15_8) >> 8; | ||
| 511 | snd_soc_write(codec, DA9055_ALC_OFFSET_OP2M_L, reg_val); | ||
| 512 | reg_val = (offset_l & DA9055_ALC_OFFSET_17_16) >> 16; | ||
| 513 | snd_soc_write(codec, DA9055_ALC_OFFSET_OP2U_L, reg_val); | ||
| 514 | |||
| 515 | reg_val = (offset_r & DA9055_ALC_OFFSET_15_8) >> 8; | ||
| 516 | snd_soc_write(codec, DA9055_ALC_OFFSET_OP2M_R, reg_val); | ||
| 517 | reg_val = (offset_r & DA9055_ALC_OFFSET_17_16) >> 16; | ||
| 518 | snd_soc_write(codec, DA9055_ALC_OFFSET_OP2U_R, reg_val); | ||
| 519 | |||
| 520 | /* Restore original values of ADC control registers */ | ||
| 521 | snd_soc_write(codec, DA9055_ADC_L_CTRL, adc_left); | ||
| 522 | snd_soc_write(codec, DA9055_ADC_R_CTRL, adc_right); | ||
| 523 | } | ||
| 524 | |||
| 525 | return snd_soc_put_volsw(kcontrol, ucontrol); | ||
| 526 | } | ||
| 527 | |||
| 528 | static const struct snd_kcontrol_new da9055_snd_controls[] = { | ||
| 529 | |||
| 530 | /* Volume controls */ | ||
| 531 | SOC_DOUBLE_R_TLV("Mic Volume", | ||
| 532 | DA9055_MIC_L_GAIN, DA9055_MIC_R_GAIN, | ||
| 533 | 0, 0x7, 0, mic_vol_tlv), | ||
| 534 | SOC_DOUBLE_R_TLV("Aux Volume", | ||
| 535 | DA9055_AUX_L_GAIN, DA9055_AUX_R_GAIN, | ||
| 536 | 0, 0x3f, 0, aux_vol_tlv), | ||
| 537 | SOC_DOUBLE_R_TLV("Mixin PGA Volume", | ||
| 538 | DA9055_MIXIN_L_GAIN, DA9055_MIXIN_R_GAIN, | ||
| 539 | 0, 0xf, 0, mixin_gain_tlv), | ||
| 540 | SOC_DOUBLE_R_TLV("ADC Volume", | ||
| 541 | DA9055_ADC_L_GAIN, DA9055_ADC_R_GAIN, | ||
| 542 | 0, 0x7f, 0, digital_gain_tlv), | ||
| 543 | |||
| 544 | SOC_DOUBLE_R_TLV("DAC Volume", | ||
| 545 | DA9055_DAC_L_GAIN, DA9055_DAC_R_GAIN, | ||
| 546 | 0, 0x7f, 0, digital_gain_tlv), | ||
| 547 | SOC_DOUBLE_R_TLV("Headphone Volume", | ||
| 548 | DA9055_HP_L_GAIN, DA9055_HP_R_GAIN, | ||
| 549 | 0, 0x3f, 0, hp_vol_tlv), | ||
| 550 | SOC_SINGLE_TLV("Lineout Volume", DA9055_LINE_GAIN, 0, 0x3f, 0, | ||
| 551 | lineout_vol_tlv), | ||
| 552 | |||
| 553 | /* DAC Equalizer controls */ | ||
| 554 | SOC_SINGLE("DAC EQ Switch", DA9055_DAC_FILTERS4, 7, 1, 0), | ||
| 555 | SOC_SINGLE_TLV("DAC EQ1 Volume", DA9055_DAC_FILTERS2, 0, 0xf, 0, | ||
| 556 | eq_gain_tlv), | ||
| 557 | SOC_SINGLE_TLV("DAC EQ2 Volume", DA9055_DAC_FILTERS2, 4, 0xf, 0, | ||
| 558 | eq_gain_tlv), | ||
| 559 | SOC_SINGLE_TLV("DAC EQ3 Volume", DA9055_DAC_FILTERS3, 0, 0xf, 0, | ||
| 560 | eq_gain_tlv), | ||
| 561 | SOC_SINGLE_TLV("DAC EQ4 Volume", DA9055_DAC_FILTERS3, 4, 0xf, 0, | ||
| 562 | eq_gain_tlv), | ||
| 563 | SOC_SINGLE_TLV("DAC EQ5 Volume", DA9055_DAC_FILTERS4, 0, 0xf, 0, | ||
| 564 | eq_gain_tlv), | ||
| 565 | |||
| 566 | /* High Pass Filter and Voice Mode controls */ | ||
| 567 | SOC_SINGLE("ADC HPF Switch", DA9055_ADC_FILTERS1, 7, 1, 0), | ||
| 568 | SOC_ENUM("ADC HPF Cutoff", da9055_adc_hpf_cutoff), | ||
| 569 | SOC_SINGLE("ADC Voice Mode Switch", DA9055_ADC_FILTERS1, 3, 1, 0), | ||
| 570 | SOC_ENUM("ADC Voice Cutoff", da9055_adc_vf_cutoff), | ||
| 571 | |||
| 572 | SOC_SINGLE("DAC HPF Switch", DA9055_DAC_FILTERS1, 7, 1, 0), | ||
| 573 | SOC_ENUM("DAC HPF Cutoff", da9055_dac_hpf_cutoff), | ||
| 574 | SOC_SINGLE("DAC Voice Mode Switch", DA9055_DAC_FILTERS1, 3, 1, 0), | ||
| 575 | SOC_ENUM("DAC Voice Cutoff", da9055_dac_vf_cutoff), | ||
| 576 | |||
| 577 | /* Mute controls */ | ||
| 578 | SOC_DOUBLE_R("Mic Switch", DA9055_MIC_L_CTRL, | ||
| 579 | DA9055_MIC_R_CTRL, 6, 1, 0), | ||
| 580 | SOC_DOUBLE_R("Aux Switch", DA9055_AUX_L_CTRL, | ||
| 581 | DA9055_AUX_R_CTRL, 6, 1, 0), | ||
| 582 | SOC_DOUBLE_R("Mixin PGA Switch", DA9055_MIXIN_L_CTRL, | ||
| 583 | DA9055_MIXIN_R_CTRL, 6, 1, 0), | ||
| 584 | SOC_DOUBLE_R("ADC Switch", DA9055_ADC_L_CTRL, | ||
| 585 | DA9055_ADC_R_CTRL, 6, 1, 0), | ||
| 586 | SOC_DOUBLE_R("Headphone Switch", DA9055_HP_L_CTRL, | ||
| 587 | DA9055_HP_R_CTRL, 6, 1, 0), | ||
| 588 | SOC_SINGLE("Lineout Switch", DA9055_LINE_CTRL, 6, 1, 0), | ||
| 589 | SOC_SINGLE("DAC Soft Mute Switch", DA9055_DAC_FILTERS5, 7, 1, 0), | ||
| 590 | SOC_ENUM("DAC Soft Mute Rate", da9055_dac_soft_mute_rate), | ||
| 591 | |||
| 592 | /* Zero Cross controls */ | ||
| 593 | SOC_DOUBLE_R("Aux ZC Switch", DA9055_AUX_L_CTRL, | ||
| 594 | DA9055_AUX_R_CTRL, 4, 1, 0), | ||
| 595 | SOC_DOUBLE_R("Mixin PGA ZC Switch", DA9055_MIXIN_L_CTRL, | ||
| 596 | DA9055_MIXIN_R_CTRL, 4, 1, 0), | ||
| 597 | SOC_DOUBLE_R("Headphone ZC Switch", DA9055_HP_L_CTRL, | ||
| 598 | DA9055_HP_R_CTRL, 4, 1, 0), | ||
| 599 | SOC_SINGLE("Lineout ZC Switch", DA9055_LINE_CTRL, 4, 1, 0), | ||
| 600 | |||
| 601 | /* Gain Ramping controls */ | ||
| 602 | SOC_DOUBLE_R("Aux Gain Ramping Switch", DA9055_AUX_L_CTRL, | ||
| 603 | DA9055_AUX_R_CTRL, 5, 1, 0), | ||
| 604 | SOC_DOUBLE_R("Mixin Gain Ramping Switch", DA9055_MIXIN_L_CTRL, | ||
| 605 | DA9055_MIXIN_R_CTRL, 5, 1, 0), | ||
| 606 | SOC_DOUBLE_R("ADC Gain Ramping Switch", DA9055_ADC_L_CTRL, | ||
| 607 | DA9055_ADC_R_CTRL, 5, 1, 0), | ||
| 608 | SOC_DOUBLE_R("DAC Gain Ramping Switch", DA9055_DAC_L_CTRL, | ||
| 609 | DA9055_DAC_R_CTRL, 5, 1, 0), | ||
| 610 | SOC_DOUBLE_R("Headphone Gain Ramping Switch", DA9055_HP_L_CTRL, | ||
| 611 | DA9055_HP_R_CTRL, 5, 1, 0), | ||
| 612 | SOC_SINGLE("Lineout Gain Ramping Switch", DA9055_LINE_CTRL, 5, 1, 0), | ||
| 613 | SOC_ENUM("Gain Ramping Rate", da9055_gain_ramping_rate), | ||
| 614 | |||
| 615 | /* DAC Noise Gate controls */ | ||
| 616 | SOC_SINGLE("DAC NG Switch", DA9055_DAC_NG_CTRL, 7, 1, 0), | ||
| 617 | SOC_SINGLE("DAC NG ON Threshold", DA9055_DAC_NG_ON_THRESHOLD, | ||
| 618 | 0, 0x7, 0), | ||
| 619 | SOC_SINGLE("DAC NG OFF Threshold", DA9055_DAC_NG_OFF_THRESHOLD, | ||
| 620 | 0, 0x7, 0), | ||
| 621 | SOC_ENUM("DAC NG Setup Time", da9055_dac_ng_setup_time), | ||
| 622 | SOC_ENUM("DAC NG Rampup Rate", da9055_dac_ng_rampup_rate), | ||
| 623 | SOC_ENUM("DAC NG Rampdown Rate", da9055_dac_ng_rampdown_rate), | ||
| 624 | |||
| 625 | /* DAC Invertion control */ | ||
| 626 | SOC_SINGLE("DAC Left Invert", DA9055_DIG_CTRL, 3, 1, 0), | ||
| 627 | SOC_SINGLE("DAC Right Invert", DA9055_DIG_CTRL, 7, 1, 0), | ||
| 628 | |||
| 629 | /* DMIC controls */ | ||
| 630 | SOC_DOUBLE_R("DMIC Switch", DA9055_MIXIN_L_SELECT, | ||
| 631 | DA9055_MIXIN_R_SELECT, 7, 1, 0), | ||
| 632 | |||
| 633 | /* ALC Controls */ | ||
| 634 | SOC_DOUBLE_EXT("ALC Switch", DA9055_ALC_CTRL1, 3, 7, 1, 0, | ||
| 635 | snd_soc_get_volsw, da9055_put_alc_sw), | ||
| 636 | SOC_SINGLE_EXT("ALC Sync Mode Switch", DA9055_ALC_CTRL1, 1, 1, 0, | ||
| 637 | snd_soc_get_volsw, da9055_put_alc_sw), | ||
| 638 | SOC_SINGLE("ALC Offset Switch", DA9055_ALC_CTRL1, 0, 1, 0), | ||
| 639 | SOC_SINGLE("ALC Anticlip Mode Switch", DA9055_ALC_ANTICLIP_CTRL, | ||
| 640 | 7, 1, 0), | ||
| 641 | SOC_SINGLE("ALC Anticlip Level", DA9055_ALC_ANTICLIP_LEVEL, | ||
| 642 | 0, 0x7f, 0), | ||
| 643 | SOC_SINGLE_TLV("ALC Min Threshold Volume", DA9055_ALC_TARGET_MIN, | ||
| 644 | 0, 0x3f, 1, alc_threshold_tlv), | ||
| 645 | SOC_SINGLE_TLV("ALC Max Threshold Volume", DA9055_ALC_TARGET_MAX, | ||
| 646 | 0, 0x3f, 1, alc_threshold_tlv), | ||
| 647 | SOC_SINGLE_TLV("ALC Noise Threshold Volume", DA9055_ALC_NOISE, | ||
| 648 | 0, 0x3f, 1, alc_threshold_tlv), | ||
| 649 | SOC_SINGLE_TLV("ALC Max Gain Volume", DA9055_ALC_GAIN_LIMITS, | ||
| 650 | 4, 0xf, 0, alc_gain_tlv), | ||
| 651 | SOC_SINGLE_TLV("ALC Max Attenuation Volume", DA9055_ALC_GAIN_LIMITS, | ||
| 652 | 0, 0xf, 0, alc_gain_tlv), | ||
| 653 | SOC_SINGLE_TLV("ALC Min Analog Gain Volume", | ||
| 654 | DA9055_ALC_ANA_GAIN_LIMITS, | ||
| 655 | 0, 0x7, 0, alc_analog_gain_tlv), | ||
| 656 | SOC_SINGLE_TLV("ALC Max Analog Gain Volume", | ||
| 657 | DA9055_ALC_ANA_GAIN_LIMITS, | ||
| 658 | 4, 0x7, 0, alc_analog_gain_tlv), | ||
| 659 | SOC_ENUM("ALC Attack Rate", da9055_attack_rate), | ||
| 660 | SOC_ENUM("ALC Release Rate", da9055_release_rate), | ||
| 661 | SOC_ENUM("ALC Hold Time", da9055_hold_time), | ||
| 662 | /* | ||
| 663 | * Rate at which input signal envelope is tracked as the signal gets | ||
| 664 | * larger | ||
| 665 | */ | ||
| 666 | SOC_ENUM("ALC Integ Attack Rate", da9055_integ_attack_rate), | ||
| 667 | /* | ||
| 668 | * Rate at which input signal envelope is tracked as the signal gets | ||
| 669 | * smaller | ||
| 670 | */ | ||
| 671 | SOC_ENUM("ALC Integ Release Rate", da9055_integ_release_rate), | ||
| 672 | }; | ||
| 673 | |||
| 674 | /* DAPM Controls */ | ||
| 675 | |||
| 676 | /* Mic PGA Left Source */ | ||
| 677 | static const struct snd_kcontrol_new da9055_mic_l_mux_controls = | ||
| 678 | SOC_DAPM_ENUM("Route", da9055_mic_l_src); | ||
| 679 | |||
| 680 | /* Mic PGA Right Source */ | ||
| 681 | static const struct snd_kcontrol_new da9055_mic_r_mux_controls = | ||
| 682 | SOC_DAPM_ENUM("Route", da9055_mic_r_src); | ||
| 683 | |||
| 684 | /* In Mixer Left */ | ||
| 685 | static const struct snd_kcontrol_new da9055_dapm_mixinl_controls[] = { | ||
| 686 | SOC_DAPM_SINGLE("Aux Left Switch", DA9055_MIXIN_L_SELECT, 0, 1, 0), | ||
| 687 | SOC_DAPM_SINGLE("Mic Left Switch", DA9055_MIXIN_L_SELECT, 1, 1, 0), | ||
| 688 | SOC_DAPM_SINGLE("Mic Right Switch", DA9055_MIXIN_L_SELECT, 2, 1, 0), | ||
| 689 | }; | ||
| 690 | |||
| 691 | /* In Mixer Right */ | ||
| 692 | static const struct snd_kcontrol_new da9055_dapm_mixinr_controls[] = { | ||
| 693 | SOC_DAPM_SINGLE("Aux Right Switch", DA9055_MIXIN_R_SELECT, 0, 1, 0), | ||
| 694 | SOC_DAPM_SINGLE("Mic Right Switch", DA9055_MIXIN_R_SELECT, 1, 1, 0), | ||
| 695 | SOC_DAPM_SINGLE("Mic Left Switch", DA9055_MIXIN_R_SELECT, 2, 1, 0), | ||
| 696 | SOC_DAPM_SINGLE("Mixin Left Switch", DA9055_MIXIN_R_SELECT, 3, 1, 0), | ||
| 697 | }; | ||
| 698 | |||
| 699 | /* DAC Left Source */ | ||
| 700 | static const struct snd_kcontrol_new da9055_dac_l_mux_controls = | ||
| 701 | SOC_DAPM_ENUM("Route", da9055_dac_l_src); | ||
| 702 | |||
| 703 | /* DAC Right Source */ | ||
| 704 | static const struct snd_kcontrol_new da9055_dac_r_mux_controls = | ||
| 705 | SOC_DAPM_ENUM("Route", da9055_dac_r_src); | ||
| 706 | |||
| 707 | /* Out Mixer Left */ | ||
| 708 | static const struct snd_kcontrol_new da9055_dapm_mixoutl_controls[] = { | ||
| 709 | SOC_DAPM_SINGLE("Aux Left Switch", DA9055_MIXOUT_L_SELECT, 0, 1, 0), | ||
| 710 | SOC_DAPM_SINGLE("Mixin Left Switch", DA9055_MIXOUT_L_SELECT, 1, 1, 0), | ||
| 711 | SOC_DAPM_SINGLE("Mixin Right Switch", DA9055_MIXOUT_L_SELECT, 2, 1, 0), | ||
| 712 | SOC_DAPM_SINGLE("DAC Left Switch", DA9055_MIXOUT_L_SELECT, 3, 1, 0), | ||
| 713 | SOC_DAPM_SINGLE("Aux Left Invert Switch", DA9055_MIXOUT_L_SELECT, | ||
| 714 | 4, 1, 0), | ||
| 715 | SOC_DAPM_SINGLE("Mixin Left Invert Switch", DA9055_MIXOUT_L_SELECT, | ||
| 716 | 5, 1, 0), | ||
| 717 | SOC_DAPM_SINGLE("Mixin Right Invert Switch", DA9055_MIXOUT_L_SELECT, | ||
| 718 | 6, 1, 0), | ||
| 719 | }; | ||
| 720 | |||
| 721 | /* Out Mixer Right */ | ||
| 722 | static const struct snd_kcontrol_new da9055_dapm_mixoutr_controls[] = { | ||
| 723 | SOC_DAPM_SINGLE("Aux Right Switch", DA9055_MIXOUT_R_SELECT, 0, 1, 0), | ||
| 724 | SOC_DAPM_SINGLE("Mixin Right Switch", DA9055_MIXOUT_R_SELECT, 1, 1, 0), | ||
| 725 | SOC_DAPM_SINGLE("Mixin Left Switch", DA9055_MIXOUT_R_SELECT, 2, 1, 0), | ||
| 726 | SOC_DAPM_SINGLE("DAC Right Switch", DA9055_MIXOUT_R_SELECT, 3, 1, 0), | ||
| 727 | SOC_DAPM_SINGLE("Aux Right Invert Switch", DA9055_MIXOUT_R_SELECT, | ||
| 728 | 4, 1, 0), | ||
| 729 | SOC_DAPM_SINGLE("Mixin Right Invert Switch", DA9055_MIXOUT_R_SELECT, | ||
| 730 | 5, 1, 0), | ||
| 731 | SOC_DAPM_SINGLE("Mixin Left Invert Switch", DA9055_MIXOUT_R_SELECT, | ||
| 732 | 6, 1, 0), | ||
| 733 | }; | ||
| 734 | |||
| 735 | /* DAPM widgets */ | ||
| 736 | static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = { | ||
| 737 | /* Input Side */ | ||
| 738 | |||
| 739 | /* Input Lines */ | ||
| 740 | SND_SOC_DAPM_INPUT("MIC1"), | ||
| 741 | SND_SOC_DAPM_INPUT("MIC2"), | ||
| 742 | SND_SOC_DAPM_INPUT("AUXL"), | ||
| 743 | SND_SOC_DAPM_INPUT("AUXR"), | ||
| 744 | |||
| 745 | /* MUXs for Mic PGA source selection */ | ||
| 746 | SND_SOC_DAPM_MUX("Mic Left Source", SND_SOC_NOPM, 0, 0, | ||
| 747 | &da9055_mic_l_mux_controls), | ||
| 748 | SND_SOC_DAPM_MUX("Mic Right Source", SND_SOC_NOPM, 0, 0, | ||
| 749 | &da9055_mic_r_mux_controls), | ||
| 750 | |||
| 751 | /* Input PGAs */ | ||
| 752 | SND_SOC_DAPM_PGA("Mic Left", DA9055_MIC_L_CTRL, 7, 0, NULL, 0), | ||
| 753 | SND_SOC_DAPM_PGA("Mic Right", DA9055_MIC_R_CTRL, 7, 0, NULL, 0), | ||
| 754 | SND_SOC_DAPM_PGA("Aux Left", DA9055_AUX_L_CTRL, 7, 0, NULL, 0), | ||
| 755 | SND_SOC_DAPM_PGA("Aux Right", DA9055_AUX_R_CTRL, 7, 0, NULL, 0), | ||
| 756 | SND_SOC_DAPM_PGA("MIXIN Left", DA9055_MIXIN_L_CTRL, 7, 0, NULL, 0), | ||
| 757 | SND_SOC_DAPM_PGA("MIXIN Right", DA9055_MIXIN_R_CTRL, 7, 0, NULL, 0), | ||
| 758 | |||
| 759 | SND_SOC_DAPM_SUPPLY("Mic Bias", DA9055_MIC_BIAS_CTRL, 7, 0, NULL, 0), | ||
| 760 | SND_SOC_DAPM_SUPPLY("AIF", DA9055_AIF_CTRL, 7, 0, NULL, 0), | ||
| 761 | SND_SOC_DAPM_SUPPLY("Charge Pump", DA9055_CP_CTRL, 7, 0, NULL, 0), | ||
| 762 | |||
| 763 | /* Input Mixers */ | ||
| 764 | SND_SOC_DAPM_MIXER("In Mixer Left", SND_SOC_NOPM, 0, 0, | ||
| 765 | &da9055_dapm_mixinl_controls[0], | ||
| 766 | ARRAY_SIZE(da9055_dapm_mixinl_controls)), | ||
| 767 | SND_SOC_DAPM_MIXER("In Mixer Right", SND_SOC_NOPM, 0, 0, | ||
| 768 | &da9055_dapm_mixinr_controls[0], | ||
| 769 | ARRAY_SIZE(da9055_dapm_mixinr_controls)), | ||
| 770 | |||
| 771 | /* ADCs */ | ||
| 772 | SND_SOC_DAPM_ADC("ADC Left", "Capture", DA9055_ADC_L_CTRL, 7, 0), | ||
| 773 | SND_SOC_DAPM_ADC("ADC Right", "Capture", DA9055_ADC_R_CTRL, 7, 0), | ||
| 774 | |||
| 775 | /* Output Side */ | ||
| 776 | |||
| 777 | /* MUXs for DAC source selection */ | ||
| 778 | SND_SOC_DAPM_MUX("DAC Left Source", SND_SOC_NOPM, 0, 0, | ||
| 779 | &da9055_dac_l_mux_controls), | ||
| 780 | SND_SOC_DAPM_MUX("DAC Right Source", SND_SOC_NOPM, 0, 0, | ||
| 781 | &da9055_dac_r_mux_controls), | ||
| 782 | |||
| 783 | /* AIF input */ | ||
| 784 | SND_SOC_DAPM_AIF_IN("AIFIN Left", "Playback", 0, SND_SOC_NOPM, 0, 0), | ||
| 785 | SND_SOC_DAPM_AIF_IN("AIFIN Right", "Playback", 0, SND_SOC_NOPM, 0, 0), | ||
| 786 | |||
| 787 | /* DACs */ | ||
| 788 | SND_SOC_DAPM_DAC("DAC Left", "Playback", DA9055_DAC_L_CTRL, 7, 0), | ||
| 789 | SND_SOC_DAPM_DAC("DAC Right", "Playback", DA9055_DAC_R_CTRL, 7, 0), | ||
| 790 | |||
| 791 | /* Output Mixers */ | ||
| 792 | SND_SOC_DAPM_MIXER("Out Mixer Left", SND_SOC_NOPM, 0, 0, | ||
| 793 | &da9055_dapm_mixoutl_controls[0], | ||
| 794 | ARRAY_SIZE(da9055_dapm_mixoutl_controls)), | ||
| 795 | SND_SOC_DAPM_MIXER("Out Mixer Right", SND_SOC_NOPM, 0, 0, | ||
| 796 | &da9055_dapm_mixoutr_controls[0], | ||
| 797 | ARRAY_SIZE(da9055_dapm_mixoutr_controls)), | ||
| 798 | |||
| 799 | /* Output PGAs */ | ||
| 800 | SND_SOC_DAPM_PGA("MIXOUT Left", DA9055_MIXOUT_L_CTRL, 7, 0, NULL, 0), | ||
| 801 | SND_SOC_DAPM_PGA("MIXOUT Right", DA9055_MIXOUT_R_CTRL, 7, 0, NULL, 0), | ||
| 802 | SND_SOC_DAPM_PGA("Lineout", DA9055_LINE_CTRL, 7, 0, NULL, 0), | ||
| 803 | SND_SOC_DAPM_PGA("Headphone Left", DA9055_HP_L_CTRL, 7, 0, NULL, 0), | ||
| 804 | SND_SOC_DAPM_PGA("Headphone Right", DA9055_HP_R_CTRL, 7, 0, NULL, 0), | ||
| 805 | |||
| 806 | /* Output Lines */ | ||
| 807 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
| 808 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
| 809 | SND_SOC_DAPM_OUTPUT("LINE"), | ||
| 810 | }; | ||
| 811 | |||
| 812 | /* DAPM audio route definition */ | ||
| 813 | static const struct snd_soc_dapm_route da9055_audio_map[] = { | ||
| 814 | /* Dest Connecting Widget source */ | ||
| 815 | |||
| 816 | /* Input path */ | ||
| 817 | {"Mic Left Source", "MIC1_P_N", "MIC1"}, | ||
| 818 | {"Mic Left Source", "MIC1_P", "MIC1"}, | ||
| 819 | {"Mic Left Source", "MIC1_N", "MIC1"}, | ||
| 820 | {"Mic Left Source", "MIC2_L", "MIC2"}, | ||
| 821 | |||
| 822 | {"Mic Right Source", "MIC2_R_L", "MIC2"}, | ||
| 823 | {"Mic Right Source", "MIC2_R", "MIC2"}, | ||
| 824 | {"Mic Right Source", "MIC2_L", "MIC2"}, | ||
| 825 | |||
| 826 | {"Mic Left", NULL, "Mic Left Source"}, | ||
| 827 | {"Mic Right", NULL, "Mic Right Source"}, | ||
| 828 | |||
| 829 | {"Aux Left", NULL, "AUXL"}, | ||
| 830 | {"Aux Right", NULL, "AUXR"}, | ||
| 831 | |||
| 832 | {"In Mixer Left", "Mic Left Switch", "Mic Left"}, | ||
| 833 | {"In Mixer Left", "Mic Right Switch", "Mic Right"}, | ||
| 834 | {"In Mixer Left", "Aux Left Switch", "Aux Left"}, | ||
| 835 | |||
| 836 | {"In Mixer Right", "Mic Right Switch", "Mic Right"}, | ||
| 837 | {"In Mixer Right", "Mic Left Switch", "Mic Left"}, | ||
| 838 | {"In Mixer Right", "Aux Right Switch", "Aux Right"}, | ||
| 839 | {"In Mixer Right", "Mixin Left Switch", "MIXIN Left"}, | ||
| 840 | |||
| 841 | {"MIXIN Left", NULL, "In Mixer Left"}, | ||
| 842 | {"ADC Left", NULL, "MIXIN Left"}, | ||
| 843 | |||
| 844 | {"MIXIN Right", NULL, "In Mixer Right"}, | ||
| 845 | {"ADC Right", NULL, "MIXIN Right"}, | ||
| 846 | |||
| 847 | {"ADC Left", NULL, "AIF"}, | ||
| 848 | {"ADC Right", NULL, "AIF"}, | ||
| 849 | |||
| 850 | /* Output path */ | ||
| 851 | {"AIFIN Left", NULL, "AIF"}, | ||
| 852 | {"AIFIN Right", NULL, "AIF"}, | ||
| 853 | |||
| 854 | {"DAC Left Source", "ADC output left", "ADC Left"}, | ||
| 855 | {"DAC Left Source", "ADC output right", "ADC Right"}, | ||
| 856 | {"DAC Left Source", "AIF input left", "AIFIN Left"}, | ||
| 857 | {"DAC Left Source", "AIF input right", "AIFIN Right"}, | ||
| 858 | |||
| 859 | {"DAC Right Source", "ADC output left", "ADC Left"}, | ||
| 860 | {"DAC Right Source", "ADC output right", "ADC Right"}, | ||
| 861 | {"DAC Right Source", "AIF input left", "AIFIN Left"}, | ||
| 862 | {"DAC Right Source", "AIF input right", "AIFIN Right"}, | ||
| 863 | |||
| 864 | {"DAC Left", NULL, "DAC Left Source"}, | ||
| 865 | {"DAC Right", NULL, "DAC Right Source"}, | ||
| 866 | |||
| 867 | {"Out Mixer Left", "Aux Left Switch", "Aux Left"}, | ||
| 868 | {"Out Mixer Left", "Mixin Left Switch", "MIXIN Left"}, | ||
| 869 | {"Out Mixer Left", "Mixin Right Switch", "MIXIN Right"}, | ||
| 870 | {"Out Mixer Left", "Aux Left Invert Switch", "Aux Left"}, | ||
| 871 | {"Out Mixer Left", "Mixin Left Invert Switch", "MIXIN Left"}, | ||
| 872 | {"Out Mixer Left", "Mixin Right Invert Switch", "MIXIN Right"}, | ||
| 873 | {"Out Mixer Left", "DAC Left Switch", "DAC Left"}, | ||
| 874 | |||
| 875 | {"Out Mixer Right", "Aux Right Switch", "Aux Right"}, | ||
| 876 | {"Out Mixer Right", "Mixin Right Switch", "MIXIN Right"}, | ||
| 877 | {"Out Mixer Right", "Mixin Left Switch", "MIXIN Left"}, | ||
| 878 | {"Out Mixer Right", "Aux Right Invert Switch", "Aux Right"}, | ||
| 879 | {"Out Mixer Right", "Mixin Right Invert Switch", "MIXIN Right"}, | ||
| 880 | {"Out Mixer Right", "Mixin Left Invert Switch", "MIXIN Left"}, | ||
| 881 | {"Out Mixer Right", "DAC Right Switch", "DAC Right"}, | ||
| 882 | |||
| 883 | {"MIXOUT Left", NULL, "Out Mixer Left"}, | ||
| 884 | {"Headphone Left", NULL, "MIXOUT Left"}, | ||
| 885 | {"Headphone Left", NULL, "Charge Pump"}, | ||
| 886 | {"HPL", NULL, "Headphone Left"}, | ||
| 887 | |||
| 888 | {"MIXOUT Right", NULL, "Out Mixer Right"}, | ||
| 889 | {"Headphone Right", NULL, "MIXOUT Right"}, | ||
| 890 | {"Headphone Right", NULL, "Charge Pump"}, | ||
| 891 | {"HPR", NULL, "Headphone Right"}, | ||
| 892 | |||
| 893 | {"MIXOUT Right", NULL, "Out Mixer Right"}, | ||
| 894 | {"Lineout", NULL, "MIXOUT Right"}, | ||
| 895 | {"LINE", NULL, "Lineout"}, | ||
| 896 | }; | ||
| 897 | |||
| 898 | /* Codec private data */ | ||
| 899 | struct da9055_priv { | ||
| 900 | struct regmap *regmap; | ||
| 901 | unsigned int mclk_rate; | ||
| 902 | int master; | ||
| 903 | struct da9055_platform_data *pdata; | ||
| 904 | }; | ||
| 905 | |||
| 906 | static struct reg_default da9055_reg_defaults[] = { | ||
| 907 | { 0x21, 0x10 }, | ||
| 908 | { 0x22, 0x0A }, | ||
| 909 | { 0x23, 0x00 }, | ||
| 910 | { 0x24, 0x00 }, | ||
| 911 | { 0x25, 0x00 }, | ||
| 912 | { 0x26, 0x00 }, | ||
| 913 | { 0x27, 0x0C }, | ||
| 914 | { 0x28, 0x01 }, | ||
| 915 | { 0x29, 0x08 }, | ||
| 916 | { 0x2A, 0x32 }, | ||
| 917 | { 0x2B, 0x00 }, | ||
| 918 | { 0x30, 0x35 }, | ||
| 919 | { 0x31, 0x35 }, | ||
| 920 | { 0x32, 0x00 }, | ||
| 921 | { 0x33, 0x00 }, | ||
| 922 | { 0x34, 0x03 }, | ||
| 923 | { 0x35, 0x03 }, | ||
| 924 | { 0x36, 0x6F }, | ||
| 925 | { 0x37, 0x6F }, | ||
| 926 | { 0x38, 0x80 }, | ||
| 927 | { 0x39, 0x01 }, | ||
| 928 | { 0x3A, 0x01 }, | ||
| 929 | { 0x40, 0x00 }, | ||
| 930 | { 0x41, 0x88 }, | ||
| 931 | { 0x42, 0x88 }, | ||
| 932 | { 0x43, 0x08 }, | ||
| 933 | { 0x44, 0x80 }, | ||
| 934 | { 0x45, 0x6F }, | ||
| 935 | { 0x46, 0x6F }, | ||
| 936 | { 0x47, 0x61 }, | ||
| 937 | { 0x48, 0x35 }, | ||
| 938 | { 0x49, 0x35 }, | ||
| 939 | { 0x4A, 0x35 }, | ||
| 940 | { 0x4B, 0x00 }, | ||
| 941 | { 0x4C, 0x00 }, | ||
| 942 | { 0x60, 0x44 }, | ||
| 943 | { 0x61, 0x44 }, | ||
| 944 | { 0x62, 0x00 }, | ||
| 945 | { 0x63, 0x40 }, | ||
| 946 | { 0x64, 0x40 }, | ||
| 947 | { 0x65, 0x40 }, | ||
| 948 | { 0x66, 0x40 }, | ||
| 949 | { 0x67, 0x40 }, | ||
| 950 | { 0x68, 0x40 }, | ||
| 951 | { 0x69, 0x48 }, | ||
| 952 | { 0x6A, 0x40 }, | ||
| 953 | { 0x6B, 0x41 }, | ||
| 954 | { 0x6C, 0x40 }, | ||
| 955 | { 0x6D, 0x40 }, | ||
| 956 | { 0x6E, 0x10 }, | ||
| 957 | { 0x6F, 0x10 }, | ||
| 958 | { 0x90, 0x80 }, | ||
| 959 | { 0x92, 0x02 }, | ||
| 960 | { 0x93, 0x00 }, | ||
| 961 | { 0x99, 0x00 }, | ||
| 962 | { 0x9A, 0x00 }, | ||
| 963 | { 0x9B, 0x00 }, | ||
| 964 | { 0x9C, 0x3F }, | ||
| 965 | { 0x9D, 0x00 }, | ||
| 966 | { 0x9E, 0x3F }, | ||
| 967 | { 0x9F, 0xFF }, | ||
| 968 | { 0xA0, 0x71 }, | ||
| 969 | { 0xA1, 0x00 }, | ||
| 970 | { 0xA2, 0x00 }, | ||
| 971 | { 0xA6, 0x00 }, | ||
| 972 | { 0xA7, 0x00 }, | ||
| 973 | { 0xAB, 0x00 }, | ||
| 974 | { 0xAC, 0x00 }, | ||
| 975 | { 0xAD, 0x00 }, | ||
| 976 | { 0xAF, 0x08 }, | ||
| 977 | { 0xB0, 0x00 }, | ||
| 978 | { 0xB1, 0x00 }, | ||
| 979 | { 0xB2, 0x00 }, | ||
| 980 | }; | ||
| 981 | |||
| 982 | static bool da9055_volatile_register(struct device *dev, | ||
| 983 | unsigned int reg) | ||
| 984 | { | ||
| 985 | switch (reg) { | ||
| 986 | case DA9055_STATUS1: | ||
| 987 | case DA9055_PLL_STATUS: | ||
| 988 | case DA9055_AUX_L_GAIN_STATUS: | ||
| 989 | case DA9055_AUX_R_GAIN_STATUS: | ||
| 990 | case DA9055_MIC_L_GAIN_STATUS: | ||
| 991 | case DA9055_MIC_R_GAIN_STATUS: | ||
| 992 | case DA9055_MIXIN_L_GAIN_STATUS: | ||
| 993 | case DA9055_MIXIN_R_GAIN_STATUS: | ||
| 994 | case DA9055_ADC_L_GAIN_STATUS: | ||
| 995 | case DA9055_ADC_R_GAIN_STATUS: | ||
| 996 | case DA9055_DAC_L_GAIN_STATUS: | ||
| 997 | case DA9055_DAC_R_GAIN_STATUS: | ||
| 998 | case DA9055_HP_L_GAIN_STATUS: | ||
| 999 | case DA9055_HP_R_GAIN_STATUS: | ||
| 1000 | case DA9055_LINE_GAIN_STATUS: | ||
| 1001 | case DA9055_ALC_CIC_OP_LVL_DATA: | ||
| 1002 | return 1; | ||
| 1003 | default: | ||
| 1004 | return 0; | ||
| 1005 | } | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | /* Set DAI word length */ | ||
| 1009 | static int da9055_hw_params(struct snd_pcm_substream *substream, | ||
| 1010 | struct snd_pcm_hw_params *params, | ||
| 1011 | struct snd_soc_dai *dai) | ||
| 1012 | { | ||
| 1013 | struct snd_soc_codec *codec = dai->codec; | ||
| 1014 | struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); | ||
| 1015 | u8 aif_ctrl, fs; | ||
| 1016 | u32 sysclk; | ||
| 1017 | |||
| 1018 | switch (params_format(params)) { | ||
| 1019 | case SNDRV_PCM_FORMAT_S16_LE: | ||
| 1020 | aif_ctrl = DA9055_AIF_WORD_S16_LE; | ||
| 1021 | break; | ||
| 1022 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
| 1023 | aif_ctrl = DA9055_AIF_WORD_S20_3LE; | ||
| 1024 | break; | ||
| 1025 | case SNDRV_PCM_FORMAT_S24_LE: | ||
| 1026 | aif_ctrl = DA9055_AIF_WORD_S24_LE; | ||
| 1027 | break; | ||
| 1028 | case SNDRV_PCM_FORMAT_S32_LE: | ||
| 1029 | aif_ctrl = DA9055_AIF_WORD_S32_LE; | ||
| 1030 | break; | ||
| 1031 | default: | ||
| 1032 | return -EINVAL; | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | /* Set AIF format */ | ||
| 1036 | snd_soc_update_bits(codec, DA9055_AIF_CTRL, DA9055_AIF_WORD_LENGTH_MASK, | ||
| 1037 | aif_ctrl); | ||
| 1038 | |||
| 1039 | switch (params_rate(params)) { | ||
| 1040 | case 8000: | ||
| 1041 | fs = DA9055_SR_8000; | ||
| 1042 | sysclk = 3072000; | ||
| 1043 | break; | ||
| 1044 | case 11025: | ||
| 1045 | fs = DA9055_SR_11025; | ||
| 1046 | sysclk = 2822400; | ||
| 1047 | break; | ||
| 1048 | case 12000: | ||
| 1049 | fs = DA9055_SR_12000; | ||
| 1050 | sysclk = 3072000; | ||
| 1051 | break; | ||
| 1052 | case 16000: | ||
| 1053 | fs = DA9055_SR_16000; | ||
| 1054 | sysclk = 3072000; | ||
| 1055 | break; | ||
| 1056 | case 22050: | ||
| 1057 | fs = DA9055_SR_22050; | ||
| 1058 | sysclk = 2822400; | ||
| 1059 | break; | ||
| 1060 | case 32000: | ||
| 1061 | fs = DA9055_SR_32000; | ||
| 1062 | sysclk = 3072000; | ||
| 1063 | break; | ||
| 1064 | case 44100: | ||
| 1065 | fs = DA9055_SR_44100; | ||
| 1066 | sysclk = 2822400; | ||
| 1067 | break; | ||
| 1068 | case 48000: | ||
| 1069 | fs = DA9055_SR_48000; | ||
| 1070 | sysclk = 3072000; | ||
| 1071 | break; | ||
| 1072 | case 88200: | ||
| 1073 | fs = DA9055_SR_88200; | ||
| 1074 | sysclk = 2822400; | ||
| 1075 | break; | ||
| 1076 | case 96000: | ||
| 1077 | fs = DA9055_SR_96000; | ||
| 1078 | sysclk = 3072000; | ||
| 1079 | break; | ||
| 1080 | default: | ||
| 1081 | return -EINVAL; | ||
| 1082 | } | ||
| 1083 | |||
| 1084 | if (da9055->mclk_rate) { | ||
| 1085 | /* PLL Mode, Write actual FS */ | ||
| 1086 | snd_soc_write(codec, DA9055_SR, fs); | ||
| 1087 | } else { | ||
| 1088 | /* | ||
| 1089 | * Non-PLL Mode | ||
| 1090 | * When PLL is bypassed, chip assumes constant MCLK of | ||
| 1091 | * 12.288MHz and uses sample rate value to divide this MCLK | ||
| 1092 | * to derive its sys clk. As sys clk has to be 256 * Fs, we | ||
| 1093 | * need to write constant sample rate i.e. 48KHz. | ||
| 1094 | */ | ||
| 1095 | snd_soc_write(codec, DA9055_SR, DA9055_SR_48000); | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | if (da9055->mclk_rate && (da9055->mclk_rate != sysclk)) { | ||
| 1099 | /* PLL Mode */ | ||
| 1100 | if (!da9055->master) { | ||
| 1101 | /* PLL slave mode, enable PLL and also SRM */ | ||
| 1102 | snd_soc_update_bits(codec, DA9055_PLL_CTRL, | ||
| 1103 | DA9055_PLL_EN | DA9055_PLL_SRM_EN, | ||
| 1104 | DA9055_PLL_EN | DA9055_PLL_SRM_EN); | ||
| 1105 | } else { | ||
| 1106 | /* PLL master mode, only enable PLL */ | ||
| 1107 | snd_soc_update_bits(codec, DA9055_PLL_CTRL, | ||
| 1108 | DA9055_PLL_EN, DA9055_PLL_EN); | ||
| 1109 | } | ||
| 1110 | } else { | ||
| 1111 | /* Non PLL Mode, disable PLL */ | ||
| 1112 | snd_soc_update_bits(codec, DA9055_PLL_CTRL, DA9055_PLL_EN, 0); | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | return 0; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | /* Set DAI mode and Format */ | ||
| 1119 | static int da9055_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
| 1120 | { | ||
| 1121 | struct snd_soc_codec *codec = codec_dai->codec; | ||
| 1122 | struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); | ||
| 1123 | u8 aif_clk_mode, aif_ctrl, mode; | ||
| 1124 | |||
| 1125 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
| 1126 | case SND_SOC_DAIFMT_CBM_CFM: | ||
| 1127 | /* DA9055 in I2S Master Mode */ | ||
| 1128 | mode = 1; | ||
| 1129 | aif_clk_mode = DA9055_AIF_CLK_EN_MASTER_MODE; | ||
| 1130 | break; | ||
| 1131 | case SND_SOC_DAIFMT_CBS_CFS: | ||
| 1132 | /* DA9055 in I2S Slave Mode */ | ||
| 1133 | mode = 0; | ||
| 1134 | aif_clk_mode = DA9055_AIF_CLK_EN_SLAVE_MODE; | ||
| 1135 | break; | ||
| 1136 | default: | ||
| 1137 | return -EINVAL; | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | /* Don't allow change of mode if PLL is enabled */ | ||
| 1141 | if ((snd_soc_read(codec, DA9055_PLL_CTRL) & DA9055_PLL_EN) && | ||
| 1142 | (da9055->master != mode)) | ||
| 1143 | return -EINVAL; | ||
| 1144 | |||
| 1145 | da9055->master = mode; | ||
| 1146 | |||
| 1147 | /* Only I2S is supported */ | ||
| 1148 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
| 1149 | case SND_SOC_DAIFMT_I2S: | ||
| 1150 | aif_ctrl = DA9055_AIF_FORMAT_I2S_MODE; | ||
| 1151 | break; | ||
| 1152 | case SND_SOC_DAIFMT_LEFT_J: | ||
| 1153 | aif_ctrl = DA9055_AIF_FORMAT_LEFT_J; | ||
| 1154 | break; | ||
| 1155 | case SND_SOC_DAIFMT_RIGHT_J: | ||
| 1156 | aif_ctrl = DA9055_AIF_FORMAT_RIGHT_J; | ||
| 1157 | break; | ||
| 1158 | default: | ||
| 1159 | return -EINVAL; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | /* By default only 32 BCLK per WCLK is supported */ | ||
| 1163 | aif_clk_mode |= DA9055_AIF_BCLKS_PER_WCLK_32; | ||
| 1164 | |||
| 1165 | snd_soc_update_bits(codec, DA9055_AIF_CLK_MODE, | ||
| 1166 | (DA9055_AIF_CLK_MODE_MASK | DA9055_AIF_BCLK_MASK), | ||
| 1167 | aif_clk_mode); | ||
| 1168 | snd_soc_update_bits(codec, DA9055_AIF_CTRL, DA9055_AIF_FORMAT_MASK, | ||
| 1169 | aif_ctrl); | ||
| 1170 | return 0; | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | static int da9055_mute(struct snd_soc_dai *dai, int mute) | ||
| 1174 | { | ||
| 1175 | struct snd_soc_codec *codec = dai->codec; | ||
| 1176 | |||
| 1177 | if (mute) { | ||
| 1178 | snd_soc_update_bits(codec, DA9055_DAC_L_CTRL, | ||
| 1179 | DA9055_DAC_L_MUTE_EN, DA9055_DAC_L_MUTE_EN); | ||
| 1180 | snd_soc_update_bits(codec, DA9055_DAC_R_CTRL, | ||
| 1181 | DA9055_DAC_R_MUTE_EN, DA9055_DAC_R_MUTE_EN); | ||
| 1182 | } else { | ||
| 1183 | snd_soc_update_bits(codec, DA9055_DAC_L_CTRL, | ||
| 1184 | DA9055_DAC_L_MUTE_EN, 0); | ||
| 1185 | snd_soc_update_bits(codec, DA9055_DAC_R_CTRL, | ||
| 1186 | DA9055_DAC_R_MUTE_EN, 0); | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | return 0; | ||
| 1190 | } | ||
| 1191 | |||
| 1192 | #define DA9055_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
| 1193 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
| 1194 | |||
| 1195 | static int da9055_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
| 1196 | int clk_id, unsigned int freq, int dir) | ||
| 1197 | { | ||
| 1198 | struct snd_soc_codec *codec = codec_dai->codec; | ||
| 1199 | struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); | ||
| 1200 | |||
| 1201 | switch (clk_id) { | ||
| 1202 | case DA9055_CLKSRC_MCLK: | ||
| 1203 | switch (freq) { | ||
| 1204 | case 11289600: | ||
| 1205 | case 12000000: | ||
| 1206 | case 12288000: | ||
| 1207 | case 13000000: | ||
| 1208 | case 13500000: | ||
| 1209 | case 14400000: | ||
| 1210 | case 19200000: | ||
| 1211 | case 19680000: | ||
| 1212 | case 19800000: | ||
| 1213 | da9055->mclk_rate = freq; | ||
| 1214 | return 0; | ||
| 1215 | default: | ||
| 1216 | dev_err(codec_dai->dev, "Unsupported MCLK value %d\n", | ||
| 1217 | freq); | ||
| 1218 | return -EINVAL; | ||
| 1219 | } | ||
| 1220 | break; | ||
| 1221 | default: | ||
| 1222 | dev_err(codec_dai->dev, "Unknown clock source %d\n", clk_id); | ||
| 1223 | return -EINVAL; | ||
| 1224 | } | ||
| 1225 | } | ||
| 1226 | |||
| 1227 | /* | ||
| 1228 | * da9055_set_dai_pll : Configure the codec PLL | ||
| 1229 | * @param codec_dai : Pointer to codec DAI | ||
| 1230 | * @param pll_id : da9055 has only one pll, so pll_id is always zero | ||
| 1231 | * @param fref : Input MCLK frequency | ||
| 1232 | * @param fout : FsDM value | ||
| 1233 | * @return int : Zero for success, negative error code for error | ||
| 1234 | * | ||
| 1235 | * Note: Supported PLL input frequencies are 11.2896MHz, 12MHz, 12.288MHz, | ||
| 1236 | * 13MHz, 13.5MHz, 14.4MHz, 19.2MHz, 19.6MHz and 19.8MHz | ||
| 1237 | */ | ||
| 1238 | static int da9055_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, | ||
| 1239 | int source, unsigned int fref, unsigned int fout) | ||
| 1240 | { | ||
| 1241 | struct snd_soc_codec *codec = codec_dai->codec; | ||
| 1242 | struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); | ||
| 1243 | |||
| 1244 | u8 pll_frac_top, pll_frac_bot, pll_integer, cnt; | ||
| 1245 | |||
| 1246 | /* Disable PLL before setting the divisors */ | ||
| 1247 | snd_soc_update_bits(codec, DA9055_PLL_CTRL, DA9055_PLL_EN, 0); | ||
| 1248 | |||
| 1249 | /* In slave mode, there is only one set of divisors */ | ||
| 1250 | if (!da9055->master && (fout != 2822400)) | ||
| 1251 | goto pll_err; | ||
| 1252 | |||
| 1253 | /* Search pll div array for correct divisors */ | ||
| 1254 | for (cnt = 0; cnt < ARRAY_SIZE(da9055_pll_div); cnt++) { | ||
| 1255 | /* Check fref, mode and fout */ | ||
| 1256 | if ((fref == da9055_pll_div[cnt].fref) && | ||
| 1257 | (da9055->master == da9055_pll_div[cnt].mode) && | ||
| 1258 | (fout == da9055_pll_div[cnt].fout)) { | ||
| 1259 | /* All match, pick up divisors */ | ||
| 1260 | pll_frac_top = da9055_pll_div[cnt].frac_top; | ||
| 1261 | pll_frac_bot = da9055_pll_div[cnt].frac_bot; | ||
| 1262 | pll_integer = da9055_pll_div[cnt].integer; | ||
| 1263 | break; | ||
| 1264 | } | ||
| 1265 | } | ||
| 1266 | if (cnt >= ARRAY_SIZE(da9055_pll_div)) | ||
| 1267 | goto pll_err; | ||
| 1268 | |||
| 1269 | /* Write PLL dividers */ | ||
| 1270 | snd_soc_write(codec, DA9055_PLL_FRAC_TOP, pll_frac_top); | ||
| 1271 | snd_soc_write(codec, DA9055_PLL_FRAC_BOT, pll_frac_bot); | ||
| 1272 | snd_soc_write(codec, DA9055_PLL_INTEGER, pll_integer); | ||
| 1273 | |||
| 1274 | return 0; | ||
| 1275 | pll_err: | ||
| 1276 | dev_err(codec_dai->dev, "Error in setting up PLL\n"); | ||
| 1277 | return -EINVAL; | ||
| 1278 | } | ||
| 1279 | |||
| 1280 | /* DAI operations */ | ||
| 1281 | static const struct snd_soc_dai_ops da9055_dai_ops = { | ||
| 1282 | .hw_params = da9055_hw_params, | ||
| 1283 | .set_fmt = da9055_set_dai_fmt, | ||
| 1284 | .set_sysclk = da9055_set_dai_sysclk, | ||
| 1285 | .set_pll = da9055_set_dai_pll, | ||
| 1286 | .digital_mute = da9055_mute, | ||
| 1287 | }; | ||
| 1288 | |||
| 1289 | static struct snd_soc_dai_driver da9055_dai = { | ||
| 1290 | .name = "da9055-hifi", | ||
| 1291 | /* Playback Capabilities */ | ||
| 1292 | .playback = { | ||
| 1293 | .stream_name = "Playback", | ||
| 1294 | .channels_min = 1, | ||
| 1295 | .channels_max = 2, | ||
| 1296 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
| 1297 | .formats = DA9055_FORMATS, | ||
| 1298 | }, | ||
| 1299 | /* Capture Capabilities */ | ||
| 1300 | .capture = { | ||
| 1301 | .stream_name = "Capture", | ||
| 1302 | .channels_min = 1, | ||
| 1303 | .channels_max = 2, | ||
| 1304 | .rates = SNDRV_PCM_RATE_8000_96000, | ||
| 1305 | .formats = DA9055_FORMATS, | ||
| 1306 | }, | ||
| 1307 | .ops = &da9055_dai_ops, | ||
| 1308 | .symmetric_rates = 1, | ||
| 1309 | }; | ||
| 1310 | |||
| 1311 | static int da9055_set_bias_level(struct snd_soc_codec *codec, | ||
| 1312 | enum snd_soc_bias_level level) | ||
| 1313 | { | ||
| 1314 | switch (level) { | ||
| 1315 | case SND_SOC_BIAS_ON: | ||
| 1316 | case SND_SOC_BIAS_PREPARE: | ||
| 1317 | break; | ||
| 1318 | case SND_SOC_BIAS_STANDBY: | ||
| 1319 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | ||
| 1320 | /* Enable VMID reference & master bias */ | ||
| 1321 | snd_soc_update_bits(codec, DA9055_REFERENCES, | ||
| 1322 | DA9055_VMID_EN | DA9055_BIAS_EN, | ||
| 1323 | DA9055_VMID_EN | DA9055_BIAS_EN); | ||
| 1324 | } | ||
| 1325 | break; | ||
| 1326 | case SND_SOC_BIAS_OFF: | ||
| 1327 | /* Disable VMID reference & master bias */ | ||
| 1328 | snd_soc_update_bits(codec, DA9055_REFERENCES, | ||
| 1329 | DA9055_VMID_EN | DA9055_BIAS_EN, 0); | ||
| 1330 | break; | ||
| 1331 | } | ||
| 1332 | codec->dapm.bias_level = level; | ||
| 1333 | return 0; | ||
| 1334 | } | ||
| 1335 | |||
| 1336 | static int da9055_probe(struct snd_soc_codec *codec) | ||
| 1337 | { | ||
| 1338 | int ret; | ||
| 1339 | struct da9055_priv *da9055 = snd_soc_codec_get_drvdata(codec); | ||
| 1340 | |||
| 1341 | codec->control_data = da9055->regmap; | ||
| 1342 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
| 1343 | if (ret < 0) { | ||
| 1344 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | ||
| 1345 | return ret; | ||
| 1346 | } | ||
| 1347 | |||
| 1348 | /* Enable all Gain Ramps */ | ||
| 1349 | snd_soc_update_bits(codec, DA9055_AUX_L_CTRL, | ||
| 1350 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1351 | snd_soc_update_bits(codec, DA9055_AUX_R_CTRL, | ||
| 1352 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1353 | snd_soc_update_bits(codec, DA9055_MIXIN_L_CTRL, | ||
| 1354 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1355 | snd_soc_update_bits(codec, DA9055_MIXIN_R_CTRL, | ||
| 1356 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1357 | snd_soc_update_bits(codec, DA9055_ADC_L_CTRL, | ||
| 1358 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1359 | snd_soc_update_bits(codec, DA9055_ADC_R_CTRL, | ||
| 1360 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1361 | snd_soc_update_bits(codec, DA9055_DAC_L_CTRL, | ||
| 1362 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1363 | snd_soc_update_bits(codec, DA9055_DAC_R_CTRL, | ||
| 1364 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1365 | snd_soc_update_bits(codec, DA9055_HP_L_CTRL, | ||
| 1366 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1367 | snd_soc_update_bits(codec, DA9055_HP_R_CTRL, | ||
| 1368 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1369 | snd_soc_update_bits(codec, DA9055_LINE_CTRL, | ||
| 1370 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | ||
| 1371 | |||
| 1372 | /* | ||
| 1373 | * There are two separate control bits for input and output mixers as | ||
| 1374 | * well as headphone and line outs. | ||
| 1375 | * One to enable corresponding amplifier and other to enable its | ||
| 1376 | * output. As amplifier bits are related to power control, they are | ||
| 1377 | * being managed by DAPM while other (non power related) bits are | ||
| 1378 | * enabled here | ||
| 1379 | */ | ||
| 1380 | snd_soc_update_bits(codec, DA9055_MIXIN_L_CTRL, | ||
| 1381 | DA9055_MIXIN_L_MIX_EN, DA9055_MIXIN_L_MIX_EN); | ||
| 1382 | snd_soc_update_bits(codec, DA9055_MIXIN_R_CTRL, | ||
| 1383 | DA9055_MIXIN_R_MIX_EN, DA9055_MIXIN_R_MIX_EN); | ||
| 1384 | |||
| 1385 | snd_soc_update_bits(codec, DA9055_MIXOUT_L_CTRL, | ||
| 1386 | DA9055_MIXOUT_L_MIX_EN, DA9055_MIXOUT_L_MIX_EN); | ||
| 1387 | snd_soc_update_bits(codec, DA9055_MIXOUT_R_CTRL, | ||
| 1388 | DA9055_MIXOUT_R_MIX_EN, DA9055_MIXOUT_R_MIX_EN); | ||
| 1389 | |||
| 1390 | snd_soc_update_bits(codec, DA9055_HP_L_CTRL, | ||
| 1391 | DA9055_HP_L_AMP_OE, DA9055_HP_L_AMP_OE); | ||
| 1392 | snd_soc_update_bits(codec, DA9055_HP_R_CTRL, | ||
| 1393 | DA9055_HP_R_AMP_OE, DA9055_HP_R_AMP_OE); | ||
| 1394 | |||
| 1395 | snd_soc_update_bits(codec, DA9055_LINE_CTRL, | ||
| 1396 | DA9055_LINE_AMP_OE, DA9055_LINE_AMP_OE); | ||
| 1397 | |||
| 1398 | /* Set this as per your system configuration */ | ||
| 1399 | snd_soc_write(codec, DA9055_PLL_CTRL, DA9055_PLL_INDIV_10_20_MHZ); | ||
| 1400 | |||
| 1401 | /* Set platform data values */ | ||
| 1402 | if (da9055->pdata) { | ||
| 1403 | /* set mic bias source */ | ||
| 1404 | if (da9055->pdata->micbias_source) { | ||
| 1405 | snd_soc_update_bits(codec, DA9055_MIXIN_R_SELECT, | ||
| 1406 | DA9055_MICBIAS2_EN, | ||
| 1407 | DA9055_MICBIAS2_EN); | ||
| 1408 | } else { | ||
| 1409 | snd_soc_update_bits(codec, DA9055_MIXIN_R_SELECT, | ||
| 1410 | DA9055_MICBIAS2_EN, 0); | ||
| 1411 | } | ||
| 1412 | /* set mic bias voltage */ | ||
| 1413 | switch (da9055->pdata->micbias) { | ||
| 1414 | case DA9055_MICBIAS_2_2V: | ||
| 1415 | case DA9055_MICBIAS_2_1V: | ||
| 1416 | case DA9055_MICBIAS_1_8V: | ||
| 1417 | case DA9055_MICBIAS_1_6V: | ||
| 1418 | snd_soc_update_bits(codec, DA9055_MIC_CONFIG, | ||
| 1419 | DA9055_MICBIAS_LEVEL_MASK, | ||
| 1420 | (da9055->pdata->micbias) << 4); | ||
| 1421 | break; | ||
| 1422 | } | ||
| 1423 | } | ||
| 1424 | return 0; | ||
| 1425 | } | ||
| 1426 | |||
| 1427 | static struct snd_soc_codec_driver soc_codec_dev_da9055 = { | ||
| 1428 | .probe = da9055_probe, | ||
| 1429 | .set_bias_level = da9055_set_bias_level, | ||
| 1430 | |||
| 1431 | .controls = da9055_snd_controls, | ||
| 1432 | .num_controls = ARRAY_SIZE(da9055_snd_controls), | ||
| 1433 | |||
| 1434 | .dapm_widgets = da9055_dapm_widgets, | ||
| 1435 | .num_dapm_widgets = ARRAY_SIZE(da9055_dapm_widgets), | ||
| 1436 | .dapm_routes = da9055_audio_map, | ||
| 1437 | .num_dapm_routes = ARRAY_SIZE(da9055_audio_map), | ||
| 1438 | }; | ||
| 1439 | |||
| 1440 | static const struct regmap_config da9055_regmap_config = { | ||
| 1441 | .reg_bits = 8, | ||
| 1442 | .val_bits = 8, | ||
| 1443 | |||
| 1444 | .reg_defaults = da9055_reg_defaults, | ||
| 1445 | .num_reg_defaults = ARRAY_SIZE(da9055_reg_defaults), | ||
| 1446 | .volatile_reg = da9055_volatile_register, | ||
| 1447 | .cache_type = REGCACHE_RBTREE, | ||
| 1448 | }; | ||
| 1449 | |||
| 1450 | static int __devinit da9055_i2c_probe(struct i2c_client *i2c, | ||
| 1451 | const struct i2c_device_id *id) | ||
| 1452 | { | ||
| 1453 | struct da9055_priv *da9055; | ||
| 1454 | struct da9055_platform_data *pdata = dev_get_platdata(&i2c->dev); | ||
| 1455 | int ret; | ||
| 1456 | |||
| 1457 | da9055 = devm_kzalloc(&i2c->dev, sizeof(struct da9055_priv), | ||
| 1458 | GFP_KERNEL); | ||
| 1459 | if (!da9055) | ||
| 1460 | return -ENOMEM; | ||
| 1461 | |||
| 1462 | if (pdata) | ||
| 1463 | da9055->pdata = pdata; | ||
| 1464 | |||
| 1465 | i2c_set_clientdata(i2c, da9055); | ||
| 1466 | |||
| 1467 | da9055->regmap = devm_regmap_init_i2c(i2c, &da9055_regmap_config); | ||
| 1468 | if (IS_ERR(da9055->regmap)) { | ||
| 1469 | ret = PTR_ERR(da9055->regmap); | ||
| 1470 | dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); | ||
| 1471 | return ret; | ||
| 1472 | } | ||
| 1473 | |||
| 1474 | ret = snd_soc_register_codec(&i2c->dev, | ||
| 1475 | &soc_codec_dev_da9055, &da9055_dai, 1); | ||
| 1476 | if (ret < 0) { | ||
| 1477 | dev_err(&i2c->dev, "Failed to register da9055 codec: %d\n", | ||
| 1478 | ret); | ||
| 1479 | } | ||
| 1480 | return ret; | ||
| 1481 | } | ||
| 1482 | |||
| 1483 | static int __devexit da9055_remove(struct i2c_client *client) | ||
| 1484 | { | ||
| 1485 | snd_soc_unregister_codec(&client->dev); | ||
| 1486 | return 0; | ||
| 1487 | } | ||
| 1488 | |||
| 1489 | static const struct i2c_device_id da9055_i2c_id[] = { | ||
| 1490 | { "da9055", 0 }, | ||
| 1491 | { } | ||
| 1492 | }; | ||
| 1493 | MODULE_DEVICE_TABLE(i2c, da9055_i2c_id); | ||
| 1494 | |||
| 1495 | /* I2C codec control layer */ | ||
| 1496 | static struct i2c_driver da9055_i2c_driver = { | ||
| 1497 | .driver = { | ||
| 1498 | .name = "da9055", | ||
| 1499 | .owner = THIS_MODULE, | ||
| 1500 | }, | ||
| 1501 | .probe = da9055_i2c_probe, | ||
| 1502 | .remove = __devexit_p(da9055_remove), | ||
| 1503 | .id_table = da9055_i2c_id, | ||
| 1504 | }; | ||
| 1505 | |||
| 1506 | module_i2c_driver(da9055_i2c_driver); | ||
| 1507 | |||
| 1508 | MODULE_DESCRIPTION("ASoC DA9055 Codec driver"); | ||
| 1509 | MODULE_AUTHOR("David Chen, Ashish Chavan"); | ||
| 1510 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index 5d8f39e32978..1bf55602c9eb 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c | |||
| @@ -13,7 +13,6 @@ | |||
| 13 | */ | 13 | */ |
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/moduleparam.h> | 15 | #include <linux/moduleparam.h> |
| 16 | #include <linux/version.h> | ||
| 17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 18 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 19 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index ba4fafb93e56..81a328c78838 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c | |||
| @@ -250,17 +250,7 @@ static struct i2c_driver lm4857_i2c_driver = { | |||
| 250 | .id_table = lm4857_i2c_id, | 250 | .id_table = lm4857_i2c_id, |
| 251 | }; | 251 | }; |
| 252 | 252 | ||
| 253 | static int __init lm4857_init(void) | 253 | module_i2c_driver(lm4857_i2c_driver); |
| 254 | { | ||
| 255 | return i2c_add_driver(&lm4857_i2c_driver); | ||
| 256 | } | ||
| 257 | module_init(lm4857_init); | ||
| 258 | |||
| 259 | static void __exit lm4857_exit(void) | ||
| 260 | { | ||
| 261 | i2c_del_driver(&lm4857_i2c_driver); | ||
| 262 | } | ||
| 263 | module_exit(lm4857_exit); | ||
| 264 | 254 | ||
| 265 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 255 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
| 266 | MODULE_DESCRIPTION("LM4857 amplifier driver"); | 256 | MODULE_DESCRIPTION("LM4857 amplifier driver"); |
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index af7324b79dd0..3264a5169306 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
| @@ -2107,23 +2107,7 @@ static struct i2c_driver max98088_i2c_driver = { | |||
| 2107 | .id_table = max98088_i2c_id, | 2107 | .id_table = max98088_i2c_id, |
| 2108 | }; | 2108 | }; |
| 2109 | 2109 | ||
| 2110 | static int __init max98088_init(void) | 2110 | module_i2c_driver(max98088_i2c_driver); |
| 2111 | { | ||
| 2112 | int ret; | ||
| 2113 | |||
| 2114 | ret = i2c_add_driver(&max98088_i2c_driver); | ||
| 2115 | if (ret) | ||
| 2116 | pr_err("Failed to register max98088 I2C driver: %d\n", ret); | ||
| 2117 | |||
| 2118 | return ret; | ||
| 2119 | } | ||
| 2120 | module_init(max98088_init); | ||
| 2121 | |||
| 2122 | static void __exit max98088_exit(void) | ||
| 2123 | { | ||
| 2124 | i2c_del_driver(&max98088_i2c_driver); | ||
| 2125 | } | ||
| 2126 | module_exit(max98088_exit); | ||
| 2127 | 2111 | ||
| 2128 | MODULE_DESCRIPTION("ALSA SoC MAX98088 driver"); | 2112 | MODULE_DESCRIPTION("ALSA SoC MAX98088 driver"); |
| 2129 | MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin"); | 2113 | MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin"); |
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 7cd508e16a5c..38d43c59d3f4 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c | |||
| @@ -2533,23 +2533,7 @@ static struct i2c_driver max98095_i2c_driver = { | |||
| 2533 | .id_table = max98095_i2c_id, | 2533 | .id_table = max98095_i2c_id, |
| 2534 | }; | 2534 | }; |
| 2535 | 2535 | ||
| 2536 | static int __init max98095_init(void) | 2536 | module_i2c_driver(max98095_i2c_driver); |
| 2537 | { | ||
| 2538 | int ret; | ||
| 2539 | |||
| 2540 | ret = i2c_add_driver(&max98095_i2c_driver); | ||
| 2541 | if (ret) | ||
| 2542 | pr_err("Failed to register max98095 I2C driver: %d\n", ret); | ||
| 2543 | |||
| 2544 | return ret; | ||
| 2545 | } | ||
| 2546 | module_init(max98095_init); | ||
| 2547 | |||
| 2548 | static void __exit max98095_exit(void) | ||
| 2549 | { | ||
| 2550 | i2c_del_driver(&max98095_i2c_driver); | ||
| 2551 | } | ||
| 2552 | module_exit(max98095_exit); | ||
| 2553 | 2537 | ||
| 2554 | MODULE_DESCRIPTION("ALSA SoC MAX98095 driver"); | 2538 | MODULE_DESCRIPTION("ALSA SoC MAX98095 driver"); |
| 2555 | MODULE_AUTHOR("Peter Hsiang"); | 2539 | MODULE_AUTHOR("Peter Hsiang"); |
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index a1913091f56c..efe535c37b39 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c | |||
| @@ -369,17 +369,7 @@ static struct i2c_driver max9850_i2c_driver = { | |||
| 369 | .id_table = max9850_i2c_id, | 369 | .id_table = max9850_i2c_id, |
| 370 | }; | 370 | }; |
| 371 | 371 | ||
| 372 | static int __init max9850_init(void) | 372 | module_i2c_driver(max9850_i2c_driver); |
| 373 | { | ||
| 374 | return i2c_add_driver(&max9850_i2c_driver); | ||
| 375 | } | ||
| 376 | module_init(max9850_init); | ||
| 377 | |||
| 378 | static void __exit max9850_exit(void) | ||
| 379 | { | ||
| 380 | i2c_del_driver(&max9850_i2c_driver); | ||
| 381 | } | ||
| 382 | module_exit(max9850_exit); | ||
| 383 | 373 | ||
| 384 | MODULE_AUTHOR("Christian Glindkamp <christian.glindkamp@taskit.de>"); | 374 | MODULE_AUTHOR("Christian Glindkamp <christian.glindkamp@taskit.de>"); |
| 385 | MODULE_DESCRIPTION("ASoC MAX9850 codec driver"); | 375 | MODULE_DESCRIPTION("ASoC MAX9850 codec driver"); |
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c index 3a2ba3d8fd6d..d15e5943c85e 100644 --- a/sound/soc/codecs/max9877.c +++ b/sound/soc/codecs/max9877.c | |||
| @@ -291,17 +291,7 @@ static struct i2c_driver max9877_i2c_driver = { | |||
| 291 | .id_table = max9877_i2c_id, | 291 | .id_table = max9877_i2c_id, |
| 292 | }; | 292 | }; |
| 293 | 293 | ||
| 294 | static int __init max9877_init(void) | 294 | module_i2c_driver(max9877_i2c_driver); |
| 295 | { | ||
| 296 | return i2c_add_driver(&max9877_i2c_driver); | ||
| 297 | } | ||
| 298 | module_init(max9877_init); | ||
| 299 | |||
| 300 | static void __exit max9877_exit(void) | ||
| 301 | { | ||
| 302 | i2c_del_driver(&max9877_i2c_driver); | ||
| 303 | } | ||
| 304 | module_exit(max9877_exit); | ||
| 305 | 295 | ||
| 306 | MODULE_DESCRIPTION("ASoC MAX9877 amp driver"); | 296 | MODULE_DESCRIPTION("ASoC MAX9877 amp driver"); |
| 307 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | 297 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); |
diff --git a/sound/soc/codecs/mc13783.c b/sound/soc/codecs/mc13783.c index 115a40301810..bc955999c8aa 100644 --- a/sound/soc/codecs/mc13783.c +++ b/sound/soc/codecs/mc13783.c | |||
| @@ -426,16 +426,16 @@ static int mc13783_set_tdm_slot_sync(struct snd_soc_dai *dai, | |||
| 426 | } | 426 | } |
| 427 | 427 | ||
| 428 | static const struct snd_kcontrol_new mc1l_amp_ctl = | 428 | static const struct snd_kcontrol_new mc1l_amp_ctl = |
| 429 | SOC_DAPM_SINGLE("Switch", 38, 7, 1, 0); | 429 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 7, 1, 0); |
| 430 | 430 | ||
| 431 | static const struct snd_kcontrol_new mc1r_amp_ctl = | 431 | static const struct snd_kcontrol_new mc1r_amp_ctl = |
| 432 | SOC_DAPM_SINGLE("Switch", 38, 5, 1, 0); | 432 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 5, 1, 0); |
| 433 | 433 | ||
| 434 | static const struct snd_kcontrol_new mc2_amp_ctl = | 434 | static const struct snd_kcontrol_new mc2_amp_ctl = |
| 435 | SOC_DAPM_SINGLE("Switch", 38, 9, 1, 0); | 435 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 9, 1, 0); |
| 436 | 436 | ||
| 437 | static const struct snd_kcontrol_new atx_amp_ctl = | 437 | static const struct snd_kcontrol_new atx_amp_ctl = |
| 438 | SOC_DAPM_SINGLE("Switch", 38, 11, 1, 0); | 438 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_TX, 11, 1, 0); |
| 439 | 439 | ||
| 440 | 440 | ||
| 441 | /* Virtual mux. The chip does the input selection automatically | 441 | /* Virtual mux. The chip does the input selection automatically |
| @@ -461,22 +461,22 @@ static const struct snd_kcontrol_new right_input_mux = | |||
| 461 | SOC_DAPM_ENUM_VIRT("Route", adcr_enum); | 461 | SOC_DAPM_ENUM_VIRT("Route", adcr_enum); |
| 462 | 462 | ||
| 463 | static const struct snd_kcontrol_new samp_ctl = | 463 | static const struct snd_kcontrol_new samp_ctl = |
| 464 | SOC_DAPM_SINGLE("Switch", 36, 3, 1, 0); | 464 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 3, 1, 0); |
| 465 | 465 | ||
| 466 | static const struct snd_kcontrol_new lamp_ctl = | 466 | static const struct snd_kcontrol_new lamp_ctl = |
| 467 | SOC_DAPM_SINGLE("Switch", 36, 5, 1, 0); | 467 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 5, 1, 0); |
| 468 | 468 | ||
| 469 | static const struct snd_kcontrol_new hlamp_ctl = | 469 | static const struct snd_kcontrol_new hlamp_ctl = |
| 470 | SOC_DAPM_SINGLE("Switch", 36, 10, 1, 0); | 470 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 10, 1, 0); |
| 471 | 471 | ||
| 472 | static const struct snd_kcontrol_new hramp_ctl = | 472 | static const struct snd_kcontrol_new hramp_ctl = |
| 473 | SOC_DAPM_SINGLE("Switch", 36, 9, 1, 0); | 473 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 9, 1, 0); |
| 474 | 474 | ||
| 475 | static const struct snd_kcontrol_new llamp_ctl = | 475 | static const struct snd_kcontrol_new llamp_ctl = |
| 476 | SOC_DAPM_SINGLE("Switch", 36, 16, 1, 0); | 476 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 16, 1, 0); |
| 477 | 477 | ||
| 478 | static const struct snd_kcontrol_new lramp_ctl = | 478 | static const struct snd_kcontrol_new lramp_ctl = |
| 479 | SOC_DAPM_SINGLE("Switch", 36, 15, 1, 0); | 479 | SOC_DAPM_SINGLE("Switch", MC13783_AUDIO_RX0, 15, 1, 0); |
| 480 | 480 | ||
| 481 | static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { | 481 | static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { |
| 482 | /* Input */ | 482 | /* Input */ |
| @@ -487,13 +487,13 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { | |||
| 487 | SND_SOC_DAPM_INPUT("RXINL"), | 487 | SND_SOC_DAPM_INPUT("RXINL"), |
| 488 | SND_SOC_DAPM_INPUT("TXIN"), | 488 | SND_SOC_DAPM_INPUT("TXIN"), |
| 489 | 489 | ||
| 490 | SND_SOC_DAPM_SUPPLY("MC1 Bias", 38, 0, 0, NULL, 0), | 490 | SND_SOC_DAPM_SUPPLY("MC1 Bias", MC13783_AUDIO_TX, 0, 0, NULL, 0), |
| 491 | SND_SOC_DAPM_SUPPLY("MC2 Bias", 38, 1, 0, NULL, 0), | 491 | SND_SOC_DAPM_SUPPLY("MC2 Bias", MC13783_AUDIO_TX, 1, 0, NULL, 0), |
| 492 | 492 | ||
| 493 | SND_SOC_DAPM_SWITCH("MC1L Amp", 38, 7, 0, &mc1l_amp_ctl), | 493 | SND_SOC_DAPM_SWITCH("MC1L Amp", MC13783_AUDIO_TX, 7, 0, &mc1l_amp_ctl), |
| 494 | SND_SOC_DAPM_SWITCH("MC1R Amp", 38, 5, 0, &mc1r_amp_ctl), | 494 | SND_SOC_DAPM_SWITCH("MC1R Amp", MC13783_AUDIO_TX, 5, 0, &mc1r_amp_ctl), |
| 495 | SND_SOC_DAPM_SWITCH("MC2 Amp", 38, 9, 0, &mc2_amp_ctl), | 495 | SND_SOC_DAPM_SWITCH("MC2 Amp", MC13783_AUDIO_TX, 9, 0, &mc2_amp_ctl), |
| 496 | SND_SOC_DAPM_SWITCH("TXIN Amp", 38, 11, 0, &atx_amp_ctl), | 496 | SND_SOC_DAPM_SWITCH("TXIN Amp", MC13783_AUDIO_TX, 11, 0, &atx_amp_ctl), |
| 497 | 497 | ||
| 498 | SND_SOC_DAPM_VIRT_MUX("PGA Left Input Mux", SND_SOC_NOPM, 0, 0, | 498 | SND_SOC_DAPM_VIRT_MUX("PGA Left Input Mux", SND_SOC_NOPM, 0, 0, |
| 499 | &left_input_mux), | 499 | &left_input_mux), |
| @@ -503,12 +503,12 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { | |||
| 503 | SND_SOC_DAPM_PGA("PGA Left Input", SND_SOC_NOPM, 0, 0, NULL, 0), | 503 | SND_SOC_DAPM_PGA("PGA Left Input", SND_SOC_NOPM, 0, 0, NULL, 0), |
| 504 | SND_SOC_DAPM_PGA("PGA Right Input", SND_SOC_NOPM, 0, 0, NULL, 0), | 504 | SND_SOC_DAPM_PGA("PGA Right Input", SND_SOC_NOPM, 0, 0, NULL, 0), |
| 505 | 505 | ||
| 506 | SND_SOC_DAPM_ADC("ADC", "Capture", 40, 11, 0), | 506 | SND_SOC_DAPM_ADC("ADC", "Capture", MC13783_AUDIO_CODEC, 11, 0), |
| 507 | SND_SOC_DAPM_SUPPLY("ADC_Reset", 40, 15, 0, NULL, 0), | 507 | SND_SOC_DAPM_SUPPLY("ADC_Reset", MC13783_AUDIO_CODEC, 15, 0, NULL, 0), |
| 508 | 508 | ||
| 509 | /* Output */ | 509 | /* Output */ |
| 510 | SND_SOC_DAPM_SUPPLY("DAC_E", 41, 11, 0, NULL, 0), | 510 | SND_SOC_DAPM_SUPPLY("DAC_E", MC13783_AUDIO_DAC, 11, 0, NULL, 0), |
| 511 | SND_SOC_DAPM_SUPPLY("DAC_Reset", 41, 15, 0, NULL, 0), | 511 | SND_SOC_DAPM_SUPPLY("DAC_Reset", MC13783_AUDIO_DAC, 15, 0, NULL, 0), |
| 512 | SND_SOC_DAPM_OUTPUT("RXOUTL"), | 512 | SND_SOC_DAPM_OUTPUT("RXOUTL"), |
| 513 | SND_SOC_DAPM_OUTPUT("RXOUTR"), | 513 | SND_SOC_DAPM_OUTPUT("RXOUTR"), |
| 514 | SND_SOC_DAPM_OUTPUT("HSL"), | 514 | SND_SOC_DAPM_OUTPUT("HSL"), |
| @@ -516,14 +516,18 @@ static const struct snd_soc_dapm_widget mc13783_dapm_widgets[] = { | |||
| 516 | SND_SOC_DAPM_OUTPUT("LSP"), | 516 | SND_SOC_DAPM_OUTPUT("LSP"), |
| 517 | SND_SOC_DAPM_OUTPUT("SP"), | 517 | SND_SOC_DAPM_OUTPUT("SP"), |
| 518 | 518 | ||
| 519 | SND_SOC_DAPM_SWITCH("Speaker Amp", 36, 3, 0, &samp_ctl), | 519 | SND_SOC_DAPM_SWITCH("Speaker Amp", MC13783_AUDIO_RX0, 3, 0, &samp_ctl), |
| 520 | SND_SOC_DAPM_SWITCH("Loudspeaker Amp", SND_SOC_NOPM, 0, 0, &lamp_ctl), | 520 | SND_SOC_DAPM_SWITCH("Loudspeaker Amp", SND_SOC_NOPM, 0, 0, &lamp_ctl), |
| 521 | SND_SOC_DAPM_SWITCH("Headset Amp Left", 36, 10, 0, &hlamp_ctl), | 521 | SND_SOC_DAPM_SWITCH("Headset Amp Left", MC13783_AUDIO_RX0, 10, 0, |
| 522 | SND_SOC_DAPM_SWITCH("Headset Amp Right", 36, 9, 0, &hramp_ctl), | 522 | &hlamp_ctl), |
| 523 | SND_SOC_DAPM_SWITCH("Line out Amp Left", 36, 16, 0, &llamp_ctl), | 523 | SND_SOC_DAPM_SWITCH("Headset Amp Right", MC13783_AUDIO_RX0, 9, 0, |
| 524 | SND_SOC_DAPM_SWITCH("Line out Amp Right", 36, 15, 0, &lramp_ctl), | 524 | &hramp_ctl), |
| 525 | SND_SOC_DAPM_DAC("DAC", "Playback", 36, 22, 0), | 525 | SND_SOC_DAPM_SWITCH("Line out Amp Left", MC13783_AUDIO_RX0, 16, 0, |
| 526 | SND_SOC_DAPM_PGA("DAC PGA", 37, 5, 0, NULL, 0), | 526 | &llamp_ctl), |
| 527 | SND_SOC_DAPM_SWITCH("Line out Amp Right", MC13783_AUDIO_RX0, 15, 0, | ||
| 528 | &lramp_ctl), | ||
| 529 | SND_SOC_DAPM_DAC("DAC", "Playback", MC13783_AUDIO_RX0, 22, 0), | ||
| 530 | SND_SOC_DAPM_PGA("DAC PGA", MC13783_AUDIO_RX1, 5, 0, NULL, 0), | ||
| 527 | }; | 531 | }; |
| 528 | 532 | ||
| 529 | static struct snd_soc_dapm_route mc13783_routes[] = { | 533 | static struct snd_soc_dapm_route mc13783_routes[] = { |
| @@ -581,8 +585,6 @@ static int mc13783_probe(struct snd_soc_codec *codec) | |||
| 581 | { | 585 | { |
| 582 | struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); | 586 | struct mc13783_priv *priv = snd_soc_codec_get_drvdata(codec); |
| 583 | 587 | ||
| 584 | codec->control_data = priv->mc13xxx; | ||
| 585 | |||
| 586 | mc13xxx_lock(priv->mc13xxx); | 588 | mc13xxx_lock(priv->mc13xxx); |
| 587 | 589 | ||
| 588 | /* these are the reset values */ | 590 | /* these are the reset values */ |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 8d717f4b5a87..0935bfe62471 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
| 26 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
| 27 | #include <linux/regmap.h> | ||
| 27 | #include <linux/regulator/consumer.h> | 28 | #include <linux/regulator/consumer.h> |
| 28 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 29 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
| @@ -55,12 +56,50 @@ | |||
| 55 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) | 56 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) |
| 56 | 57 | ||
| 57 | /* Power-up register defaults */ | 58 | /* Power-up register defaults */ |
| 58 | static const u8 sta32x_regs[STA32X_REGISTER_COUNT] = { | 59 | static const struct reg_default sta32x_regs[] = { |
| 59 | 0x63, 0x80, 0xc2, 0x40, 0xc2, 0x5c, 0x10, 0xff, 0x60, 0x60, | 60 | { 0x0, 0x63 }, |
| 60 | 0x60, 0x80, 0x00, 0x00, 0x00, 0x40, 0x80, 0x77, 0x6a, 0x69, | 61 | { 0x1, 0x80 }, |
| 61 | 0x6a, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 62 | { 0x2, 0xc2 }, |
| 62 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, | 63 | { 0x3, 0x40 }, |
| 63 | 0xc0, 0xf3, 0x33, 0x00, 0x0c, | 64 | { 0x4, 0xc2 }, |
| 65 | { 0x5, 0x5c }, | ||
| 66 | { 0x6, 0x10 }, | ||
| 67 | { 0x7, 0xff }, | ||
| 68 | { 0x8, 0x60 }, | ||
| 69 | { 0x9, 0x60 }, | ||
| 70 | { 0xa, 0x60 }, | ||
| 71 | { 0xb, 0x80 }, | ||
| 72 | { 0xc, 0x00 }, | ||
| 73 | { 0xd, 0x00 }, | ||
| 74 | { 0xe, 0x00 }, | ||
| 75 | { 0xf, 0x40 }, | ||
| 76 | { 0x10, 0x80 }, | ||
| 77 | { 0x11, 0x77 }, | ||
| 78 | { 0x12, 0x6a }, | ||
| 79 | { 0x13, 0x69 }, | ||
| 80 | { 0x14, 0x6a }, | ||
| 81 | { 0x15, 0x69 }, | ||
| 82 | { 0x16, 0x00 }, | ||
| 83 | { 0x17, 0x00 }, | ||
| 84 | { 0x18, 0x00 }, | ||
| 85 | { 0x19, 0x00 }, | ||
| 86 | { 0x1a, 0x00 }, | ||
| 87 | { 0x1b, 0x00 }, | ||
| 88 | { 0x1c, 0x00 }, | ||
| 89 | { 0x1d, 0x00 }, | ||
| 90 | { 0x1e, 0x00 }, | ||
| 91 | { 0x1f, 0x00 }, | ||
| 92 | { 0x20, 0x00 }, | ||
| 93 | { 0x21, 0x00 }, | ||
| 94 | { 0x22, 0x00 }, | ||
| 95 | { 0x23, 0x00 }, | ||
| 96 | { 0x24, 0x00 }, | ||
| 97 | { 0x25, 0x00 }, | ||
| 98 | { 0x26, 0x00 }, | ||
| 99 | { 0x27, 0x2d }, | ||
| 100 | { 0x28, 0xc0 }, | ||
| 101 | { 0x2b, 0x00 }, | ||
| 102 | { 0x2c, 0x0c }, | ||
| 64 | }; | 103 | }; |
| 65 | 104 | ||
| 66 | /* regulator power supply names */ | 105 | /* regulator power supply names */ |
| @@ -72,6 +111,7 @@ static const char *sta32x_supply_names[] = { | |||
| 72 | 111 | ||
| 73 | /* codec private data */ | 112 | /* codec private data */ |
| 74 | struct sta32x_priv { | 113 | struct sta32x_priv { |
| 114 | struct regmap *regmap; | ||
| 75 | struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)]; | 115 | struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)]; |
| 76 | struct snd_soc_codec *codec; | 116 | struct snd_soc_codec *codec; |
| 77 | struct sta32x_platform_data *pdata; | 117 | struct sta32x_platform_data *pdata; |
| @@ -291,17 +331,15 @@ static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec) | |||
| 291 | 331 | ||
| 292 | static int sta32x_cache_sync(struct snd_soc_codec *codec) | 332 | static int sta32x_cache_sync(struct snd_soc_codec *codec) |
| 293 | { | 333 | { |
| 334 | struct sta32x_priv *sta32x = codec->control_data; | ||
| 294 | unsigned int mute; | 335 | unsigned int mute; |
| 295 | int rc; | 336 | int rc; |
| 296 | 337 | ||
| 297 | if (!codec->cache_sync) | ||
| 298 | return 0; | ||
| 299 | |||
| 300 | /* mute during register sync */ | 338 | /* mute during register sync */ |
| 301 | mute = snd_soc_read(codec, STA32X_MMUTE); | 339 | mute = snd_soc_read(codec, STA32X_MMUTE); |
| 302 | snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); | 340 | snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); |
| 303 | sta32x_sync_coef_shadow(codec); | 341 | sta32x_sync_coef_shadow(codec); |
| 304 | rc = snd_soc_cache_sync(codec); | 342 | rc = regcache_sync(sta32x->regmap); |
| 305 | snd_soc_write(codec, STA32X_MMUTE, mute); | 343 | snd_soc_write(codec, STA32X_MMUTE, mute); |
| 306 | return rc; | 344 | return rc; |
| 307 | } | 345 | } |
| @@ -316,11 +354,11 @@ static void sta32x_watchdog(struct work_struct *work) | |||
| 316 | 354 | ||
| 317 | /* check if sta32x has reset itself */ | 355 | /* check if sta32x has reset itself */ |
| 318 | confa_cached = snd_soc_read(codec, STA32X_CONFA); | 356 | confa_cached = snd_soc_read(codec, STA32X_CONFA); |
| 319 | codec->cache_bypass = 1; | 357 | regcache_cache_bypass(sta32x->regmap, true); |
| 320 | confa = snd_soc_read(codec, STA32X_CONFA); | 358 | confa = snd_soc_read(codec, STA32X_CONFA); |
| 321 | codec->cache_bypass = 0; | 359 | regcache_cache_bypass(sta32x->regmap, false); |
| 322 | if (confa != confa_cached) { | 360 | if (confa != confa_cached) { |
| 323 | codec->cache_sync = 1; | 361 | regcache_mark_dirty(sta32x->regmap); |
| 324 | sta32x_cache_sync(codec); | 362 | sta32x_cache_sync(codec); |
| 325 | } | 363 | } |
| 326 | 364 | ||
| @@ -825,31 +863,21 @@ static int sta32x_probe(struct snd_soc_codec *codec) | |||
| 825 | sta32x->codec = codec; | 863 | sta32x->codec = codec; |
| 826 | sta32x->pdata = dev_get_platdata(codec->dev); | 864 | sta32x->pdata = dev_get_platdata(codec->dev); |
| 827 | 865 | ||
| 828 | /* regulators */ | ||
| 829 | for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) | ||
| 830 | sta32x->supplies[i].supply = sta32x_supply_names[i]; | ||
| 831 | |||
| 832 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sta32x->supplies), | ||
| 833 | sta32x->supplies); | ||
| 834 | if (ret != 0) { | ||
| 835 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
| 836 | goto err; | ||
| 837 | } | ||
| 838 | |||
| 839 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), | 866 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), |
| 840 | sta32x->supplies); | 867 | sta32x->supplies); |
| 841 | if (ret != 0) { | 868 | if (ret != 0) { |
| 842 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | 869 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); |
| 843 | goto err_get; | 870 | return ret; |
| 844 | } | 871 | } |
| 845 | 872 | ||
| 846 | /* Tell ASoC what kind of I/O to use to read the registers. ASoC will | 873 | /* Tell ASoC what kind of I/O to use to read the registers. ASoC will |
| 847 | * then do the I2C transactions itself. | 874 | * then do the I2C transactions itself. |
| 848 | */ | 875 | */ |
| 849 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | 876 | codec->control_data = sta32x->regmap; |
| 877 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
| 850 | if (ret < 0) { | 878 | if (ret < 0) { |
| 851 | dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); | 879 | dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); |
| 852 | return ret; | 880 | goto err; |
| 853 | } | 881 | } |
| 854 | 882 | ||
| 855 | /* Chip documentation explicitly requires that the reset values | 883 | /* Chip documentation explicitly requires that the reset values |
| @@ -858,13 +886,15 @@ static int sta32x_probe(struct snd_soc_codec *codec) | |||
| 858 | * so the write to the these registers are suppressed by the cache | 886 | * so the write to the these registers are suppressed by the cache |
| 859 | * restore code when it skips writes of default registers. | 887 | * restore code when it skips writes of default registers. |
| 860 | */ | 888 | */ |
| 861 | snd_soc_cache_write(codec, STA32X_CONFC, 0xc2); | 889 | regcache_cache_only(sta32x->regmap, true); |
| 862 | snd_soc_cache_write(codec, STA32X_CONFE, 0xc2); | 890 | snd_soc_write(codec, STA32X_CONFC, 0xc2); |
| 863 | snd_soc_cache_write(codec, STA32X_CONFF, 0x5c); | 891 | snd_soc_write(codec, STA32X_CONFE, 0xc2); |
| 864 | snd_soc_cache_write(codec, STA32X_MMUTE, 0x10); | 892 | snd_soc_write(codec, STA32X_CONFF, 0x5c); |
| 865 | snd_soc_cache_write(codec, STA32X_AUTO1, 0x60); | 893 | snd_soc_write(codec, STA32X_MMUTE, 0x10); |
| 866 | snd_soc_cache_write(codec, STA32X_AUTO3, 0x00); | 894 | snd_soc_write(codec, STA32X_AUTO1, 0x60); |
| 867 | snd_soc_cache_write(codec, STA32X_C3CFG, 0x40); | 895 | snd_soc_write(codec, STA32X_AUTO3, 0x00); |
| 896 | snd_soc_write(codec, STA32X_C3CFG, 0x40); | ||
| 897 | regcache_cache_only(sta32x->regmap, false); | ||
| 868 | 898 | ||
| 869 | /* set thermal warning adjustment and recovery */ | 899 | /* set thermal warning adjustment and recovery */ |
| 870 | if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE)) | 900 | if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE)) |
| @@ -915,9 +945,8 @@ static int sta32x_probe(struct snd_soc_codec *codec) | |||
| 915 | 945 | ||
| 916 | return 0; | 946 | return 0; |
| 917 | 947 | ||
| 918 | err_get: | ||
| 919 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
| 920 | err: | 948 | err: |
| 949 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
| 921 | return ret; | 950 | return ret; |
| 922 | } | 951 | } |
| 923 | 952 | ||
| @@ -928,13 +957,11 @@ static int sta32x_remove(struct snd_soc_codec *codec) | |||
| 928 | sta32x_watchdog_stop(sta32x); | 957 | sta32x_watchdog_stop(sta32x); |
| 929 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); | 958 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
| 930 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | 959 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); |
| 931 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
| 932 | 960 | ||
| 933 | return 0; | 961 | return 0; |
| 934 | } | 962 | } |
| 935 | 963 | ||
| 936 | static int sta32x_reg_is_volatile(struct snd_soc_codec *codec, | 964 | static bool sta32x_reg_is_volatile(struct device *dev, unsigned int reg) |
| 937 | unsigned int reg) | ||
| 938 | { | 965 | { |
| 939 | switch (reg) { | 966 | switch (reg) { |
| 940 | case STA32X_CONFA ... STA32X_L2ATRT: | 967 | case STA32X_CONFA ... STA32X_L2ATRT: |
| @@ -949,10 +976,6 @@ static const struct snd_soc_codec_driver sta32x_codec = { | |||
| 949 | .remove = sta32x_remove, | 976 | .remove = sta32x_remove, |
| 950 | .suspend = sta32x_suspend, | 977 | .suspend = sta32x_suspend, |
| 951 | .resume = sta32x_resume, | 978 | .resume = sta32x_resume, |
| 952 | .reg_cache_size = STA32X_REGISTER_COUNT, | ||
| 953 | .reg_word_size = sizeof(u8), | ||
| 954 | .reg_cache_default = sta32x_regs, | ||
| 955 | .volatile_register = sta32x_reg_is_volatile, | ||
| 956 | .set_bias_level = sta32x_set_bias_level, | 979 | .set_bias_level = sta32x_set_bias_level, |
| 957 | .controls = sta32x_snd_controls, | 980 | .controls = sta32x_snd_controls, |
| 958 | .num_controls = ARRAY_SIZE(sta32x_snd_controls), | 981 | .num_controls = ARRAY_SIZE(sta32x_snd_controls), |
| @@ -962,17 +985,45 @@ static const struct snd_soc_codec_driver sta32x_codec = { | |||
| 962 | .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), | 985 | .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), |
| 963 | }; | 986 | }; |
| 964 | 987 | ||
| 988 | static const struct regmap_config sta32x_regmap = { | ||
| 989 | .reg_bits = 8, | ||
| 990 | .val_bits = 8, | ||
| 991 | .max_register = STA32X_FDRC2, | ||
| 992 | .reg_defaults = sta32x_regs, | ||
| 993 | .num_reg_defaults = ARRAY_SIZE(sta32x_regs), | ||
| 994 | .cache_type = REGCACHE_RBTREE, | ||
| 995 | .volatile_reg = sta32x_reg_is_volatile, | ||
| 996 | }; | ||
| 997 | |||
| 965 | static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, | 998 | static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, |
| 966 | const struct i2c_device_id *id) | 999 | const struct i2c_device_id *id) |
| 967 | { | 1000 | { |
| 968 | struct sta32x_priv *sta32x; | 1001 | struct sta32x_priv *sta32x; |
| 969 | int ret; | 1002 | int ret, i; |
| 970 | 1003 | ||
| 971 | sta32x = devm_kzalloc(&i2c->dev, sizeof(struct sta32x_priv), | 1004 | sta32x = devm_kzalloc(&i2c->dev, sizeof(struct sta32x_priv), |
| 972 | GFP_KERNEL); | 1005 | GFP_KERNEL); |
| 973 | if (!sta32x) | 1006 | if (!sta32x) |
| 974 | return -ENOMEM; | 1007 | return -ENOMEM; |
| 975 | 1008 | ||
| 1009 | /* regulators */ | ||
| 1010 | for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) | ||
| 1011 | sta32x->supplies[i].supply = sta32x_supply_names[i]; | ||
| 1012 | |||
| 1013 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(sta32x->supplies), | ||
| 1014 | sta32x->supplies); | ||
| 1015 | if (ret != 0) { | ||
| 1016 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
| 1017 | return ret; | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | sta32x->regmap = devm_regmap_init_i2c(i2c, &sta32x_regmap); | ||
| 1021 | if (IS_ERR(sta32x->regmap)) { | ||
| 1022 | ret = PTR_ERR(sta32x->regmap); | ||
| 1023 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); | ||
| 1024 | return ret; | ||
| 1025 | } | ||
| 1026 | |||
| 976 | i2c_set_clientdata(i2c, sta32x); | 1027 | i2c_set_clientdata(i2c, sta32x); |
| 977 | 1028 | ||
| 978 | ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); | 1029 | ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); |
| @@ -1006,17 +1057,7 @@ static struct i2c_driver sta32x_i2c_driver = { | |||
| 1006 | .id_table = sta32x_i2c_id, | 1057 | .id_table = sta32x_i2c_id, |
| 1007 | }; | 1058 | }; |
| 1008 | 1059 | ||
| 1009 | static int __init sta32x_init(void) | 1060 | module_i2c_driver(sta32x_i2c_driver); |
| 1010 | { | ||
| 1011 | return i2c_add_driver(&sta32x_i2c_driver); | ||
| 1012 | } | ||
| 1013 | module_init(sta32x_init); | ||
| 1014 | |||
| 1015 | static void __exit sta32x_exit(void) | ||
| 1016 | { | ||
| 1017 | i2c_del_driver(&sta32x_i2c_driver); | ||
| 1018 | } | ||
| 1019 | module_exit(sta32x_exit); | ||
| 1020 | 1061 | ||
| 1021 | MODULE_DESCRIPTION("ASoC STA32X driver"); | 1062 | MODULE_DESCRIPTION("ASoC STA32X driver"); |
| 1022 | MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>"); | 1063 | MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>"); |
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 0c225cd569d2..9e3144862386 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c | |||
| @@ -358,7 +358,7 @@ static int sta529_resume(struct snd_soc_codec *codec) | |||
| 358 | return 0; | 358 | return 0; |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | struct snd_soc_codec_driver sta529_codec_driver = { | 361 | static const struct snd_soc_codec_driver sta529_codec_driver = { |
| 362 | .probe = sta529_probe, | 362 | .probe = sta529_probe, |
| 363 | .remove = sta529_remove, | 363 | .remove = sta529_remove, |
| 364 | .set_bias_level = sta529_set_bias_level, | 364 | .set_bias_level = sta529_set_bias_level, |
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 33c0f3d39c87..982e437799a8 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c | |||
| @@ -340,7 +340,6 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec) | |||
| 340 | 340 | ||
| 341 | printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); | 341 | printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); |
| 342 | 342 | ||
| 343 | codec->control_data = codec; /* we don't use regmap! */ | ||
| 344 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 343 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
| 345 | if (ret < 0) | 344 | if (ret < 0) |
| 346 | goto codec_err; | 345 | goto codec_err; |
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 85944e953578..b1f6982c7c9c 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c | |||
| @@ -444,14 +444,4 @@ static struct spi_driver aic26_spi = { | |||
| 444 | .remove = aic26_spi_remove, | 444 | .remove = aic26_spi_remove, |
| 445 | }; | 445 | }; |
| 446 | 446 | ||
| 447 | static int __init aic26_init(void) | 447 | module_spi_driver(aic26_spi); |
| 448 | { | ||
| 449 | return spi_register_driver(&aic26_spi); | ||
| 450 | } | ||
| 451 | module_init(aic26_init); | ||
| 452 | |||
| 453 | static void __exit aic26_exit(void) | ||
| 454 | { | ||
| 455 | spi_unregister_driver(&aic26_spi); | ||
| 456 | } | ||
| 457 | module_exit(aic26_exit); | ||
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index b0a73d37ed52..f230292ba96b 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c | |||
| @@ -746,24 +746,7 @@ static struct i2c_driver aic32x4_i2c_driver = { | |||
| 746 | .id_table = aic32x4_i2c_id, | 746 | .id_table = aic32x4_i2c_id, |
| 747 | }; | 747 | }; |
| 748 | 748 | ||
| 749 | static int __init aic32x4_modinit(void) | 749 | module_i2c_driver(aic32x4_i2c_driver); |
| 750 | { | ||
| 751 | int ret = 0; | ||
| 752 | |||
| 753 | ret = i2c_add_driver(&aic32x4_i2c_driver); | ||
| 754 | if (ret != 0) { | ||
| 755 | printk(KERN_ERR "Failed to register aic32x4 I2C driver: %d\n", | ||
| 756 | ret); | ||
| 757 | } | ||
| 758 | return ret; | ||
| 759 | } | ||
| 760 | module_init(aic32x4_modinit); | ||
| 761 | |||
| 762 | static void __exit aic32x4_exit(void) | ||
| 763 | { | ||
| 764 | i2c_del_driver(&aic32x4_i2c_driver); | ||
| 765 | } | ||
| 766 | module_exit(aic32x4_exit); | ||
| 767 | 750 | ||
| 768 | MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver"); | 751 | MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver"); |
| 769 | MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>"); | 752 | MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>"); |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index dc78f5a4bcbf..5708a973a776 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include <linux/i2c.h> | 40 | #include <linux/i2c.h> |
| 41 | #include <linux/gpio.h> | 41 | #include <linux/gpio.h> |
| 42 | #include <linux/regulator/consumer.h> | 42 | #include <linux/regulator/consumer.h> |
| 43 | #include <linux/of_gpio.h> | ||
| 43 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
| 44 | #include <sound/core.h> | 45 | #include <sound/core.h> |
| 45 | #include <sound/pcm.h> | 46 | #include <sound/pcm.h> |
| @@ -1457,6 +1458,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
| 1457 | { | 1458 | { |
| 1458 | struct aic3x_pdata *pdata = i2c->dev.platform_data; | 1459 | struct aic3x_pdata *pdata = i2c->dev.platform_data; |
| 1459 | struct aic3x_priv *aic3x; | 1460 | struct aic3x_priv *aic3x; |
| 1461 | struct aic3x_setup_data *ai3x_setup; | ||
| 1462 | struct device_node *np = i2c->dev.of_node; | ||
| 1460 | int ret; | 1463 | int ret; |
| 1461 | 1464 | ||
| 1462 | aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); | 1465 | aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); |
| @@ -1471,6 +1474,25 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
| 1471 | if (pdata) { | 1474 | if (pdata) { |
| 1472 | aic3x->gpio_reset = pdata->gpio_reset; | 1475 | aic3x->gpio_reset = pdata->gpio_reset; |
| 1473 | aic3x->setup = pdata->setup; | 1476 | aic3x->setup = pdata->setup; |
| 1477 | } else if (np) { | ||
| 1478 | ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup), | ||
| 1479 | GFP_KERNEL); | ||
| 1480 | if (ai3x_setup == NULL) { | ||
| 1481 | dev_err(&i2c->dev, "failed to create private data\n"); | ||
| 1482 | return -ENOMEM; | ||
| 1483 | } | ||
| 1484 | |||
| 1485 | ret = of_get_named_gpio(np, "gpio-reset", 0); | ||
| 1486 | if (ret >= 0) | ||
| 1487 | aic3x->gpio_reset = ret; | ||
| 1488 | else | ||
| 1489 | aic3x->gpio_reset = -1; | ||
| 1490 | |||
| 1491 | if (of_property_read_u32_array(np, "ai3x-gpio-func", | ||
| 1492 | ai3x_setup->gpio_func, 2) >= 0) { | ||
| 1493 | aic3x->setup = ai3x_setup; | ||
| 1494 | } | ||
| 1495 | |||
| 1474 | } else { | 1496 | } else { |
| 1475 | aic3x->gpio_reset = -1; | 1497 | aic3x->gpio_reset = -1; |
| 1476 | } | 1498 | } |
| @@ -1488,34 +1510,27 @@ static int aic3x_i2c_remove(struct i2c_client *client) | |||
| 1488 | return 0; | 1510 | return 0; |
| 1489 | } | 1511 | } |
| 1490 | 1512 | ||
| 1513 | #if defined(CONFIG_OF) | ||
| 1514 | static const struct of_device_id tlv320aic3x_of_match[] = { | ||
| 1515 | { .compatible = "ti,tlv320aic3x", }, | ||
| 1516 | {}, | ||
| 1517 | }; | ||
| 1518 | MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match); | ||
| 1519 | #endif | ||
| 1520 | |||
| 1491 | /* machine i2c codec control layer */ | 1521 | /* machine i2c codec control layer */ |
| 1492 | static struct i2c_driver aic3x_i2c_driver = { | 1522 | static struct i2c_driver aic3x_i2c_driver = { |
| 1493 | .driver = { | 1523 | .driver = { |
| 1494 | .name = "tlv320aic3x-codec", | 1524 | .name = "tlv320aic3x-codec", |
| 1495 | .owner = THIS_MODULE, | 1525 | .owner = THIS_MODULE, |
| 1526 | .of_match_table = of_match_ptr(tlv320aic3x_of_match), | ||
| 1496 | }, | 1527 | }, |
| 1497 | .probe = aic3x_i2c_probe, | 1528 | .probe = aic3x_i2c_probe, |
| 1498 | .remove = aic3x_i2c_remove, | 1529 | .remove = aic3x_i2c_remove, |
| 1499 | .id_table = aic3x_i2c_id, | 1530 | .id_table = aic3x_i2c_id, |
| 1500 | }; | 1531 | }; |
| 1501 | 1532 | ||
| 1502 | static int __init aic3x_modinit(void) | 1533 | module_i2c_driver(aic3x_i2c_driver); |
| 1503 | { | ||
| 1504 | int ret = 0; | ||
| 1505 | ret = i2c_add_driver(&aic3x_i2c_driver); | ||
| 1506 | if (ret != 0) { | ||
| 1507 | printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n", | ||
| 1508 | ret); | ||
| 1509 | } | ||
| 1510 | return ret; | ||
| 1511 | } | ||
| 1512 | module_init(aic3x_modinit); | ||
| 1513 | |||
| 1514 | static void __exit aic3x_exit(void) | ||
| 1515 | { | ||
| 1516 | i2c_del_driver(&aic3x_i2c_driver); | ||
| 1517 | } | ||
| 1518 | module_exit(aic3x_exit); | ||
| 1519 | 1534 | ||
| 1520 | MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver"); | 1535 | MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver"); |
| 1521 | MODULE_AUTHOR("Vladimir Barinov"); | 1536 | MODULE_AUTHOR("Vladimir Barinov"); |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 0dd41077ab79..d2e16c5d7d1f 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
| @@ -1621,24 +1621,7 @@ static struct i2c_driver tlv320dac33_i2c_driver = { | |||
| 1621 | .id_table = tlv320dac33_i2c_id, | 1621 | .id_table = tlv320dac33_i2c_id, |
| 1622 | }; | 1622 | }; |
| 1623 | 1623 | ||
| 1624 | static int __init dac33_module_init(void) | 1624 | module_i2c_driver(tlv320dac33_i2c_driver); |
| 1625 | { | ||
| 1626 | int r; | ||
| 1627 | r = i2c_add_driver(&tlv320dac33_i2c_driver); | ||
| 1628 | if (r < 0) { | ||
| 1629 | printk(KERN_ERR "DAC33: driver registration failed\n"); | ||
| 1630 | return r; | ||
| 1631 | } | ||
| 1632 | return 0; | ||
| 1633 | } | ||
| 1634 | module_init(dac33_module_init); | ||
| 1635 | |||
| 1636 | static void __exit dac33_module_exit(void) | ||
| 1637 | { | ||
| 1638 | i2c_del_driver(&tlv320dac33_i2c_driver); | ||
| 1639 | } | ||
| 1640 | module_exit(dac33_module_exit); | ||
| 1641 | |||
| 1642 | 1625 | ||
| 1643 | MODULE_DESCRIPTION("ASoC TLV320DAC33 codec driver"); | 1626 | MODULE_DESCRIPTION("ASoC TLV320DAC33 codec driver"); |
| 1644 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); | 1627 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); |
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 6fe4aa3ac544..565ff39ad3a3 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c | |||
| @@ -487,19 +487,8 @@ static struct i2c_driver tpa6130a2_i2c_driver = { | |||
| 487 | .id_table = tpa6130a2_id, | 487 | .id_table = tpa6130a2_id, |
| 488 | }; | 488 | }; |
| 489 | 489 | ||
| 490 | static int __init tpa6130a2_init(void) | 490 | module_i2c_driver(tpa6130a2_i2c_driver); |
| 491 | { | ||
| 492 | return i2c_add_driver(&tpa6130a2_i2c_driver); | ||
| 493 | } | ||
| 494 | |||
| 495 | static void __exit tpa6130a2_exit(void) | ||
| 496 | { | ||
| 497 | i2c_del_driver(&tpa6130a2_i2c_driver); | ||
| 498 | } | ||
| 499 | 491 | ||
| 500 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); | 492 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); |
| 501 | MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver"); | 493 | MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver"); |
| 502 | MODULE_LICENSE("GPL"); | 494 | MODULE_LICENSE("GPL"); |
| 503 | |||
| 504 | module_init(tpa6130a2_init); | ||
| 505 | module_exit(tpa6130a2_exit); | ||
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 391fcfc7b63b..e7f608996c41 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
| @@ -26,8 +26,11 @@ | |||
| 26 | #include <linux/pm.h> | 26 | #include <linux/pm.h> |
| 27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
| 28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
| 29 | #include <linux/of.h> | ||
| 30 | #include <linux/of_gpio.h> | ||
| 29 | #include <linux/i2c/twl.h> | 31 | #include <linux/i2c/twl.h> |
| 30 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/gpio.h> | ||
| 31 | #include <sound/core.h> | 34 | #include <sound/core.h> |
| 32 | #include <sound/pcm.h> | 35 | #include <sound/pcm.h> |
| 33 | #include <sound/pcm_params.h> | 36 | #include <sound/pcm_params.h> |
| @@ -152,8 +155,7 @@ struct twl4030_priv { | |||
| 152 | u8 predrivel_enabled, predriver_enabled; | 155 | u8 predrivel_enabled, predriver_enabled; |
| 153 | u8 carkitl_enabled, carkitr_enabled; | 156 | u8 carkitl_enabled, carkitr_enabled; |
| 154 | 157 | ||
| 155 | /* Delay needed after enabling the digimic interface */ | 158 | struct twl4030_codec_data *pdata; |
| 156 | unsigned int digimic_delay; | ||
| 157 | }; | 159 | }; |
| 158 | 160 | ||
| 159 | /* | 161 | /* |
| @@ -295,13 +297,73 @@ static inline void twl4030_reset_registers(struct snd_soc_codec *codec) | |||
| 295 | 297 | ||
| 296 | } | 298 | } |
| 297 | 299 | ||
| 298 | static void twl4030_init_chip(struct snd_soc_codec *codec) | 300 | static void twl4030_setup_pdata_of(struct twl4030_codec_data *pdata, |
| 301 | struct device_node *node) | ||
| 302 | { | ||
| 303 | int value; | ||
| 304 | |||
| 305 | of_property_read_u32(node, "ti,digimic_delay", | ||
| 306 | &pdata->digimic_delay); | ||
| 307 | of_property_read_u32(node, "ti,ramp_delay_value", | ||
| 308 | &pdata->ramp_delay_value); | ||
| 309 | of_property_read_u32(node, "ti,offset_cncl_path", | ||
| 310 | &pdata->offset_cncl_path); | ||
| 311 | if (!of_property_read_u32(node, "ti,hs_extmute", &value)) | ||
| 312 | pdata->hs_extmute = value; | ||
| 313 | |||
| 314 | pdata->hs_extmute_gpio = of_get_named_gpio(node, | ||
| 315 | "ti,hs_extmute_gpio", 0); | ||
| 316 | if (gpio_is_valid(pdata->hs_extmute_gpio)) | ||
| 317 | pdata->hs_extmute = 1; | ||
| 318 | } | ||
| 319 | |||
| 320 | static struct twl4030_codec_data *twl4030_get_pdata(struct snd_soc_codec *codec) | ||
| 299 | { | 321 | { |
| 300 | struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev); | 322 | struct twl4030_codec_data *pdata = dev_get_platdata(codec->dev); |
| 323 | struct device_node *twl4030_codec_node = NULL; | ||
| 324 | |||
| 325 | twl4030_codec_node = of_find_node_by_name(codec->dev->parent->of_node, | ||
| 326 | "codec"); | ||
| 327 | |||
| 328 | if (!pdata && twl4030_codec_node) { | ||
| 329 | pdata = devm_kzalloc(codec->dev, | ||
| 330 | sizeof(struct twl4030_codec_data), | ||
| 331 | GFP_KERNEL); | ||
| 332 | if (!pdata) { | ||
| 333 | dev_err(codec->dev, "Can not allocate memory\n"); | ||
| 334 | return NULL; | ||
| 335 | } | ||
| 336 | twl4030_setup_pdata_of(pdata, twl4030_codec_node); | ||
| 337 | } | ||
| 338 | |||
| 339 | return pdata; | ||
| 340 | } | ||
| 341 | |||
| 342 | static void twl4030_init_chip(struct snd_soc_codec *codec) | ||
| 343 | { | ||
| 344 | struct twl4030_codec_data *pdata; | ||
| 301 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 345 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
| 302 | u8 reg, byte; | 346 | u8 reg, byte; |
| 303 | int i = 0; | 347 | int i = 0; |
| 304 | 348 | ||
| 349 | pdata = twl4030_get_pdata(codec); | ||
| 350 | |||
| 351 | if (pdata && pdata->hs_extmute && | ||
| 352 | gpio_is_valid(pdata->hs_extmute_gpio)) { | ||
| 353 | int ret; | ||
| 354 | |||
| 355 | if (!pdata->hs_extmute_gpio) | ||
| 356 | dev_warn(codec->dev, | ||
| 357 | "Extmute GPIO is 0 is this correct?\n"); | ||
| 358 | |||
| 359 | ret = gpio_request_one(pdata->hs_extmute_gpio, | ||
| 360 | GPIOF_OUT_INIT_LOW, "hs_extmute"); | ||
| 361 | if (ret) { | ||
| 362 | dev_err(codec->dev, "Failed to get hs_extmute GPIO\n"); | ||
| 363 | pdata->hs_extmute_gpio = -1; | ||
| 364 | } | ||
| 365 | } | ||
| 366 | |||
| 305 | /* Check defaults, if instructed before anything else */ | 367 | /* Check defaults, if instructed before anything else */ |
| 306 | if (pdata && pdata->check_defaults) | 368 | if (pdata && pdata->check_defaults) |
| 307 | twl4030_check_defaults(codec); | 369 | twl4030_check_defaults(codec); |
| @@ -331,7 +393,7 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) | |||
| 331 | if (!pdata) | 393 | if (!pdata) |
| 332 | return; | 394 | return; |
| 333 | 395 | ||
| 334 | twl4030->digimic_delay = pdata->digimic_delay; | 396 | twl4030->pdata = pdata; |
| 335 | 397 | ||
| 336 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); | 398 | reg = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); |
| 337 | reg &= ~TWL4030_RAMP_DELAY; | 399 | reg &= ~TWL4030_RAMP_DELAY; |
| @@ -732,9 +794,9 @@ static int aif_event(struct snd_soc_dapm_widget *w, | |||
| 732 | 794 | ||
| 733 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) | 795 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) |
| 734 | { | 796 | { |
| 735 | struct twl4030_codec_data *pdata = codec->dev->platform_data; | ||
| 736 | unsigned char hs_gain, hs_pop; | 797 | unsigned char hs_gain, hs_pop; |
| 737 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 798 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
| 799 | struct twl4030_codec_data *pdata = twl4030->pdata; | ||
| 738 | /* Base values for ramp delay calculation: 2^19 - 2^26 */ | 800 | /* Base values for ramp delay calculation: 2^19 - 2^26 */ |
| 739 | unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304, | 801 | unsigned int ramp_base[] = {524288, 1048576, 2097152, 4194304, |
| 740 | 8388608, 16777216, 33554432, 67108864}; | 802 | 8388608, 16777216, 33554432, 67108864}; |
| @@ -748,8 +810,8 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
| 748 | /* Enable external mute control, this dramatically reduces | 810 | /* Enable external mute control, this dramatically reduces |
| 749 | * the pop-noise */ | 811 | * the pop-noise */ |
| 750 | if (pdata && pdata->hs_extmute) { | 812 | if (pdata && pdata->hs_extmute) { |
| 751 | if (pdata->set_hs_extmute) { | 813 | if (gpio_is_valid(pdata->hs_extmute_gpio)) { |
| 752 | pdata->set_hs_extmute(1); | 814 | gpio_set_value(pdata->hs_extmute_gpio, 1); |
| 753 | } else { | 815 | } else { |
| 754 | hs_pop |= TWL4030_EXTMUTE; | 816 | hs_pop |= TWL4030_EXTMUTE; |
| 755 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); | 817 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); |
| @@ -786,8 +848,8 @@ static void headset_ramp(struct snd_soc_codec *codec, int ramp) | |||
| 786 | 848 | ||
| 787 | /* Disable external mute */ | 849 | /* Disable external mute */ |
| 788 | if (pdata && pdata->hs_extmute) { | 850 | if (pdata && pdata->hs_extmute) { |
| 789 | if (pdata->set_hs_extmute) { | 851 | if (gpio_is_valid(pdata->hs_extmute_gpio)) { |
| 790 | pdata->set_hs_extmute(0); | 852 | gpio_set_value(pdata->hs_extmute_gpio, 0); |
| 791 | } else { | 853 | } else { |
| 792 | hs_pop &= ~TWL4030_EXTMUTE; | 854 | hs_pop &= ~TWL4030_EXTMUTE; |
| 793 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); | 855 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, hs_pop); |
| @@ -847,9 +909,10 @@ static int digimic_event(struct snd_soc_dapm_widget *w, | |||
| 847 | struct snd_kcontrol *kcontrol, int event) | 909 | struct snd_kcontrol *kcontrol, int event) |
| 848 | { | 910 | { |
| 849 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); | 911 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(w->codec); |
| 912 | struct twl4030_codec_data *pdata = twl4030->pdata; | ||
| 850 | 913 | ||
| 851 | if (twl4030->digimic_delay) | 914 | if (pdata && pdata->digimic_delay) |
| 852 | twl4030_wait_ms(twl4030->digimic_delay); | 915 | twl4030_wait_ms(pdata->digimic_delay); |
| 853 | return 0; | 916 | return 0; |
| 854 | } | 917 | } |
| 855 | 918 | ||
| @@ -999,7 +1062,7 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, | |||
| 999 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 1062 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
| 1000 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 1063 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 1001 | unsigned short val; | 1064 | unsigned short val; |
| 1002 | unsigned short mask, bitmask; | 1065 | unsigned short mask; |
| 1003 | 1066 | ||
| 1004 | if (twl4030->configured) { | 1067 | if (twl4030->configured) { |
| 1005 | dev_err(codec->dev, | 1068 | dev_err(codec->dev, |
| @@ -1007,18 +1070,16 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol, | |||
| 1007 | return -EBUSY; | 1070 | return -EBUSY; |
| 1008 | } | 1071 | } |
| 1009 | 1072 | ||
| 1010 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | ||
| 1011 | ; | ||
| 1012 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 1073 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
| 1013 | return -EINVAL; | 1074 | return -EINVAL; |
| 1014 | 1075 | ||
| 1015 | val = ucontrol->value.enumerated.item[0] << e->shift_l; | 1076 | val = ucontrol->value.enumerated.item[0] << e->shift_l; |
| 1016 | mask = (bitmask - 1) << e->shift_l; | 1077 | mask = e->mask << e->shift_l; |
| 1017 | if (e->shift_l != e->shift_r) { | 1078 | if (e->shift_l != e->shift_r) { |
| 1018 | if (ucontrol->value.enumerated.item[1] > e->max - 1) | 1079 | if (ucontrol->value.enumerated.item[1] > e->max - 1) |
| 1019 | return -EINVAL; | 1080 | return -EINVAL; |
| 1020 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | 1081 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; |
| 1021 | mask |= (bitmask - 1) << e->shift_r; | 1082 | mask |= e->mask << e->shift_r; |
| 1022 | } | 1083 | } |
| 1023 | 1084 | ||
| 1024 | return snd_soc_update_bits(codec, e->reg, mask, val); | 1085 | return snd_soc_update_bits(codec, e->reg, mask, val); |
| @@ -1239,16 +1300,11 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
| 1239 | SND_SOC_DAPM_OUTPUT("Virtual Voice OUT"), | 1300 | SND_SOC_DAPM_OUTPUT("Virtual Voice OUT"), |
| 1240 | 1301 | ||
| 1241 | /* DACs */ | 1302 | /* DACs */ |
| 1242 | SND_SOC_DAPM_DAC("DAC Right1", "Right Front HiFi Playback", | 1303 | SND_SOC_DAPM_DAC("DAC Right1", NULL, SND_SOC_NOPM, 0, 0), |
| 1243 | SND_SOC_NOPM, 0, 0), | 1304 | SND_SOC_DAPM_DAC("DAC Left1", NULL, SND_SOC_NOPM, 0, 0), |
| 1244 | SND_SOC_DAPM_DAC("DAC Left1", "Left Front HiFi Playback", | 1305 | SND_SOC_DAPM_DAC("DAC Right2", NULL, SND_SOC_NOPM, 0, 0), |
| 1245 | SND_SOC_NOPM, 0, 0), | 1306 | SND_SOC_DAPM_DAC("DAC Left2", NULL, SND_SOC_NOPM, 0, 0), |
| 1246 | SND_SOC_DAPM_DAC("DAC Right2", "Right Rear HiFi Playback", | 1307 | SND_SOC_DAPM_DAC("DAC Voice", NULL, SND_SOC_NOPM, 0, 0), |
| 1247 | SND_SOC_NOPM, 0, 0), | ||
| 1248 | SND_SOC_DAPM_DAC("DAC Left2", "Left Rear HiFi Playback", | ||
| 1249 | SND_SOC_NOPM, 0, 0), | ||
| 1250 | SND_SOC_DAPM_DAC("DAC Voice", "Voice Playback", | ||
| 1251 | SND_SOC_NOPM, 0, 0), | ||
| 1252 | 1308 | ||
| 1253 | /* Analog bypasses */ | 1309 | /* Analog bypasses */ |
| 1254 | SND_SOC_DAPM_SWITCH("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, | 1310 | SND_SOC_DAPM_SWITCH("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, |
| @@ -1377,14 +1433,10 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
| 1377 | 1433 | ||
| 1378 | /* Introducing four virtual ADC, since TWL4030 have four channel for | 1434 | /* Introducing four virtual ADC, since TWL4030 have four channel for |
| 1379 | capture */ | 1435 | capture */ |
| 1380 | SND_SOC_DAPM_ADC("ADC Virtual Left1", "Left Front Capture", | 1436 | SND_SOC_DAPM_ADC("ADC Virtual Left1", NULL, SND_SOC_NOPM, 0, 0), |
| 1381 | SND_SOC_NOPM, 0, 0), | 1437 | SND_SOC_DAPM_ADC("ADC Virtual Right1", NULL, SND_SOC_NOPM, 0, 0), |
| 1382 | SND_SOC_DAPM_ADC("ADC Virtual Right1", "Right Front Capture", | 1438 | SND_SOC_DAPM_ADC("ADC Virtual Left2", NULL, SND_SOC_NOPM, 0, 0), |
| 1383 | SND_SOC_NOPM, 0, 0), | 1439 | SND_SOC_DAPM_ADC("ADC Virtual Right2", NULL, SND_SOC_NOPM, 0, 0), |
| 1384 | SND_SOC_DAPM_ADC("ADC Virtual Left2", "Left Rear Capture", | ||
| 1385 | SND_SOC_NOPM, 0, 0), | ||
| 1386 | SND_SOC_DAPM_ADC("ADC Virtual Right2", "Right Rear Capture", | ||
| 1387 | SND_SOC_NOPM, 0, 0), | ||
| 1388 | 1440 | ||
| 1389 | /* Analog/Digital mic path selection. | 1441 | /* Analog/Digital mic path selection. |
| 1390 | TX1 Left/Right: either analog Left/Right or Digimic0 | 1442 | TX1 Left/Right: either analog Left/Right or Digimic0 |
| @@ -1428,6 +1480,23 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
| 1428 | }; | 1480 | }; |
| 1429 | 1481 | ||
| 1430 | static const struct snd_soc_dapm_route intercon[] = { | 1482 | static const struct snd_soc_dapm_route intercon[] = { |
| 1483 | /* Stream -> DAC mapping */ | ||
| 1484 | {"DAC Right1", NULL, "HiFi Playback"}, | ||
| 1485 | {"DAC Left1", NULL, "HiFi Playback"}, | ||
| 1486 | {"DAC Right2", NULL, "HiFi Playback"}, | ||
| 1487 | {"DAC Left2", NULL, "HiFi Playback"}, | ||
| 1488 | {"DAC Voice", NULL, "Voice Playback"}, | ||
| 1489 | |||
| 1490 | /* ADC -> Stream mapping */ | ||
| 1491 | {"HiFi Capture", NULL, "ADC Virtual Left1"}, | ||
| 1492 | {"HiFi Capture", NULL, "ADC Virtual Right1"}, | ||
| 1493 | {"HiFi Capture", NULL, "ADC Virtual Left2"}, | ||
| 1494 | {"HiFi Capture", NULL, "ADC Virtual Right2"}, | ||
| 1495 | {"Voice Capture", NULL, "ADC Virtual Left1"}, | ||
| 1496 | {"Voice Capture", NULL, "ADC Virtual Right1"}, | ||
| 1497 | {"Voice Capture", NULL, "ADC Virtual Left2"}, | ||
| 1498 | {"Voice Capture", NULL, "ADC Virtual Right2"}, | ||
| 1499 | |||
| 1431 | {"Digital L1 Playback Mixer", NULL, "DAC Left1"}, | 1500 | {"Digital L1 Playback Mixer", NULL, "DAC Left1"}, |
| 1432 | {"Digital R1 Playback Mixer", NULL, "DAC Right1"}, | 1501 | {"Digital R1 Playback Mixer", NULL, "DAC Right1"}, |
| 1433 | {"Digital L2 Playback Mixer", NULL, "DAC Left2"}, | 1502 | {"Digital L2 Playback Mixer", NULL, "DAC Left2"}, |
| @@ -2172,7 +2241,7 @@ static struct snd_soc_dai_driver twl4030_dai[] = { | |||
| 2172 | .formats = TWL4030_FORMATS, | 2241 | .formats = TWL4030_FORMATS, |
| 2173 | .sig_bits = 24,}, | 2242 | .sig_bits = 24,}, |
| 2174 | .capture = { | 2243 | .capture = { |
| 2175 | .stream_name = "Capture", | 2244 | .stream_name = "HiFi Capture", |
| 2176 | .channels_min = 2, | 2245 | .channels_min = 2, |
| 2177 | .channels_max = 4, | 2246 | .channels_max = 4, |
| 2178 | .rates = TWL4030_RATES, | 2247 | .rates = TWL4030_RATES, |
| @@ -2189,7 +2258,7 @@ static struct snd_soc_dai_driver twl4030_dai[] = { | |||
| 2189 | .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, | 2258 | .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, |
| 2190 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 2259 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
| 2191 | .capture = { | 2260 | .capture = { |
| 2192 | .stream_name = "Capture", | 2261 | .stream_name = "Voice Capture", |
| 2193 | .channels_min = 1, | 2262 | .channels_min = 1, |
| 2194 | .channels_max = 2, | 2263 | .channels_max = 2, |
| 2195 | .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, | 2264 | .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000, |
| @@ -2214,7 +2283,8 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec) | |||
| 2214 | { | 2283 | { |
| 2215 | struct twl4030_priv *twl4030; | 2284 | struct twl4030_priv *twl4030; |
| 2216 | 2285 | ||
| 2217 | twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); | 2286 | twl4030 = devm_kzalloc(codec->dev, sizeof(struct twl4030_priv), |
| 2287 | GFP_KERNEL); | ||
| 2218 | if (twl4030 == NULL) { | 2288 | if (twl4030 == NULL) { |
| 2219 | dev_err(codec->dev, "Can not allocate memory\n"); | 2289 | dev_err(codec->dev, "Can not allocate memory\n"); |
| 2220 | return -ENOMEM; | 2290 | return -ENOMEM; |
| @@ -2231,11 +2301,15 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec) | |||
| 2231 | static int twl4030_soc_remove(struct snd_soc_codec *codec) | 2301 | static int twl4030_soc_remove(struct snd_soc_codec *codec) |
| 2232 | { | 2302 | { |
| 2233 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 2303 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
| 2304 | struct twl4030_codec_data *pdata = twl4030->pdata; | ||
| 2234 | 2305 | ||
| 2235 | /* Reset registers to their chip default before leaving */ | 2306 | /* Reset registers to their chip default before leaving */ |
| 2236 | twl4030_reset_registers(codec); | 2307 | twl4030_reset_registers(codec); |
| 2237 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); | 2308 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); |
| 2238 | kfree(twl4030); | 2309 | |
| 2310 | if (pdata && pdata->hs_extmute && gpio_is_valid(pdata->hs_extmute_gpio)) | ||
| 2311 | gpio_free(pdata->hs_extmute_gpio); | ||
| 2312 | |||
| 2239 | return 0; | 2313 | return 0; |
| 2240 | } | 2314 | } |
| 2241 | 2315 | ||
| @@ -2262,13 +2336,6 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = { | |||
| 2262 | 2336 | ||
| 2263 | static int __devinit twl4030_codec_probe(struct platform_device *pdev) | 2337 | static int __devinit twl4030_codec_probe(struct platform_device *pdev) |
| 2264 | { | 2338 | { |
| 2265 | struct twl4030_codec_data *pdata = pdev->dev.platform_data; | ||
| 2266 | |||
| 2267 | if (!pdata) { | ||
| 2268 | dev_err(&pdev->dev, "platform_data is missing\n"); | ||
| 2269 | return -EINVAL; | ||
| 2270 | } | ||
| 2271 | |||
| 2272 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030, | 2339 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_twl4030, |
| 2273 | twl4030_dai, ARRAY_SIZE(twl4030_dai)); | 2340 | twl4030_dai, ARRAY_SIZE(twl4030_dai)); |
| 2274 | } | 2341 | } |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index c084c549942e..e8f97af75928 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
| @@ -727,10 +727,8 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { | |||
| 727 | TWL6040_REG_MICRCTL, 1, 0, NULL, 0), | 727 | TWL6040_REG_MICRCTL, 1, 0, NULL, 0), |
| 728 | 728 | ||
| 729 | /* ADCs */ | 729 | /* ADCs */ |
| 730 | SND_SOC_DAPM_ADC("ADC Left", "Left Front Capture", | 730 | SND_SOC_DAPM_ADC("ADC Left", NULL, TWL6040_REG_MICLCTL, 2, 0), |
| 731 | TWL6040_REG_MICLCTL, 2, 0), | 731 | SND_SOC_DAPM_ADC("ADC Right", NULL, TWL6040_REG_MICRCTL, 2, 0), |
| 732 | SND_SOC_DAPM_ADC("ADC Right", "Right Front Capture", | ||
| 733 | TWL6040_REG_MICRCTL, 2, 0), | ||
| 734 | 732 | ||
| 735 | /* Microphone bias */ | 733 | /* Microphone bias */ |
| 736 | SND_SOC_DAPM_SUPPLY("Headset Mic Bias", | 734 | SND_SOC_DAPM_SUPPLY("Headset Mic Bias", |
| @@ -743,15 +741,12 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { | |||
| 743 | TWL6040_REG_DMICBCTL, 4, 0, NULL, 0), | 741 | TWL6040_REG_DMICBCTL, 4, 0, NULL, 0), |
| 744 | 742 | ||
| 745 | /* DACs */ | 743 | /* DACs */ |
| 746 | SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback", SND_SOC_NOPM, 0, 0), | 744 | SND_SOC_DAPM_DAC("HSDAC Left", NULL, SND_SOC_NOPM, 0, 0), |
| 747 | SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback", SND_SOC_NOPM, 0, 0), | 745 | SND_SOC_DAPM_DAC("HSDAC Right", NULL, SND_SOC_NOPM, 0, 0), |
| 748 | SND_SOC_DAPM_DAC("HFDAC Left", "Handsfree Playback", | 746 | SND_SOC_DAPM_DAC("HFDAC Left", NULL, TWL6040_REG_HFLCTL, 0, 0), |
| 749 | TWL6040_REG_HFLCTL, 0, 0), | 747 | SND_SOC_DAPM_DAC("HFDAC Right", NULL, TWL6040_REG_HFRCTL, 0, 0), |
| 750 | SND_SOC_DAPM_DAC("HFDAC Right", "Handsfree Playback", | ||
| 751 | TWL6040_REG_HFRCTL, 0, 0), | ||
| 752 | /* Virtual DAC for vibra path (DL4 channel) */ | 748 | /* Virtual DAC for vibra path (DL4 channel) */ |
| 753 | SND_SOC_DAPM_DAC("VIBRA DAC", "Vibra Playback", | 749 | SND_SOC_DAPM_DAC("VIBRA DAC", NULL, SND_SOC_NOPM, 0, 0), |
| 754 | SND_SOC_NOPM, 0, 0), | ||
| 755 | 750 | ||
| 756 | SND_SOC_DAPM_MUX("Handsfree Left Playback", | 751 | SND_SOC_DAPM_MUX("Handsfree Left Playback", |
| 757 | SND_SOC_NOPM, 0, 0, &hfl_mux_controls), | 752 | SND_SOC_NOPM, 0, 0, &hfl_mux_controls), |
| @@ -810,6 +805,26 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { | |||
| 810 | }; | 805 | }; |
| 811 | 806 | ||
| 812 | static const struct snd_soc_dapm_route intercon[] = { | 807 | static const struct snd_soc_dapm_route intercon[] = { |
| 808 | /* Stream -> DAC mapping */ | ||
| 809 | {"HSDAC Left", NULL, "Legacy Playback"}, | ||
| 810 | {"HSDAC Left", NULL, "Headset Playback"}, | ||
| 811 | {"HSDAC Right", NULL, "Legacy Playback"}, | ||
| 812 | {"HSDAC Right", NULL, "Headset Playback"}, | ||
| 813 | |||
| 814 | {"HFDAC Left", NULL, "Legacy Playback"}, | ||
| 815 | {"HFDAC Left", NULL, "Handsfree Playback"}, | ||
| 816 | {"HFDAC Right", NULL, "Legacy Playback"}, | ||
| 817 | {"HFDAC Right", NULL, "Handsfree Playback"}, | ||
| 818 | |||
| 819 | {"VIBRA DAC", NULL, "Legacy Playback"}, | ||
| 820 | {"VIBRA DAC", NULL, "Vibra Playback"}, | ||
| 821 | |||
| 822 | /* ADC -> Stream mapping */ | ||
| 823 | {"ADC Left", NULL, "Legacy Capture"}, | ||
| 824 | {"ADC Left", NULL, "Capture"}, | ||
| 825 | {"ADC Right", NULL, "Legacy Capture"}, | ||
| 826 | {"ADC Right", NULL, "Capture"}, | ||
| 827 | |||
| 813 | /* Capture path */ | 828 | /* Capture path */ |
| 814 | {"Analog Left Capture Route", "Headset Mic", "HSMIC"}, | 829 | {"Analog Left Capture Route", "Headset Mic", "HSMIC"}, |
| 815 | {"Analog Left Capture Route", "Main Mic", "MAINMIC"}, | 830 | {"Analog Left Capture Route", "Main Mic", "MAINMIC"}, |
| @@ -1028,14 +1043,14 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
| 1028 | { | 1043 | { |
| 1029 | .name = "twl6040-legacy", | 1044 | .name = "twl6040-legacy", |
| 1030 | .playback = { | 1045 | .playback = { |
| 1031 | .stream_name = "Playback", | 1046 | .stream_name = "Legacy Playback", |
| 1032 | .channels_min = 1, | 1047 | .channels_min = 1, |
| 1033 | .channels_max = 5, | 1048 | .channels_max = 5, |
| 1034 | .rates = TWL6040_RATES, | 1049 | .rates = TWL6040_RATES, |
| 1035 | .formats = TWL6040_FORMATS, | 1050 | .formats = TWL6040_FORMATS, |
| 1036 | }, | 1051 | }, |
| 1037 | .capture = { | 1052 | .capture = { |
| 1038 | .stream_name = "Capture", | 1053 | .stream_name = "Legacy Capture", |
| 1039 | .channels_min = 1, | 1054 | .channels_min = 1, |
| 1040 | .channels_max = 2, | 1055 | .channels_max = 2, |
| 1041 | .rates = TWL6040_RATES, | 1056 | .rates = TWL6040_RATES, |
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c new file mode 100644 index 000000000000..99afc003a084 --- /dev/null +++ b/sound/soc/codecs/wm0010.c | |||
| @@ -0,0 +1,940 @@ | |||
| 1 | /* | ||
| 2 | * wm0010.c -- WM0010 DSP Driver | ||
| 3 | * | ||
| 4 | * Copyright 2012 Wolfson Microelectronics PLC. | ||
| 5 | * | ||
| 6 | * Authors: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
| 7 | * Dimitris Papastamos <dp@opensource.wolfsonmicro.com> | ||
| 8 | * Scott Ling <sl@opensource.wolfsonmicro.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/moduleparam.h> | ||
| 17 | #include <linux/irqreturn.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/spi/spi.h> | ||
| 20 | #include <linux/firmware.h> | ||
| 21 | #include <linux/delay.h> | ||
| 22 | #include <linux/fs.h> | ||
| 23 | #include <linux/miscdevice.h> | ||
| 24 | #include <linux/gpio.h> | ||
| 25 | #include <linux/regulator/consumer.h> | ||
| 26 | #include <linux/mutex.h> | ||
| 27 | #include <linux/workqueue.h> | ||
| 28 | |||
| 29 | #include <sound/soc.h> | ||
| 30 | #include <sound/wm0010.h> | ||
| 31 | |||
| 32 | #define DEVICE_ID_WM0010 10 | ||
| 33 | |||
| 34 | enum dfw_cmd { | ||
| 35 | DFW_CMD_FUSE = 0x01, | ||
| 36 | DFW_CMD_CODE_HDR, | ||
| 37 | DFW_CMD_CODE_DATA, | ||
| 38 | DFW_CMD_PLL, | ||
| 39 | DFW_CMD_INFO = 0xff | ||
| 40 | }; | ||
| 41 | |||
| 42 | struct dfw_binrec { | ||
| 43 | u8 command; | ||
| 44 | u32 length:24; | ||
| 45 | u32 address; | ||
| 46 | uint8_t data[0]; | ||
| 47 | } __packed; | ||
| 48 | |||
| 49 | struct dfw_pllrec { | ||
| 50 | u8 command; | ||
| 51 | u32 length:24; | ||
| 52 | u32 address; | ||
| 53 | u32 clkctrl1; | ||
| 54 | u32 clkctrl2; | ||
| 55 | u32 clkctrl3; | ||
| 56 | u32 ldetctrl; | ||
| 57 | u32 uart_div; | ||
| 58 | u32 spi_div; | ||
| 59 | } __packed; | ||
| 60 | |||
| 61 | static struct pll_clock_map { | ||
| 62 | int max_sysclk; | ||
| 63 | int max_pll_spi_speed; | ||
| 64 | u32 pll_clkctrl1; | ||
| 65 | } pll_clock_map[] = { /* Dividers */ | ||
| 66 | { 22000000, 26000000, 0x00201f11 }, /* 2,32,2 */ | ||
| 67 | { 18000000, 26000000, 0x00203f21 }, /* 2,64,4 */ | ||
| 68 | { 14000000, 26000000, 0x00202620 }, /* 1,39,4 */ | ||
| 69 | { 10000000, 22000000, 0x00203120 }, /* 1,50,4 */ | ||
| 70 | { 6500000, 22000000, 0x00204520 }, /* 1,70,4 */ | ||
| 71 | { 5500000, 22000000, 0x00103f10 }, /* 1,64,2 */ | ||
| 72 | }; | ||
| 73 | |||
| 74 | enum wm0010_state { | ||
| 75 | WM0010_POWER_OFF, | ||
| 76 | WM0010_OUT_OF_RESET, | ||
| 77 | WM0010_BOOTROM, | ||
| 78 | WM0010_STAGE2, | ||
| 79 | WM0010_FIRMWARE, | ||
| 80 | }; | ||
| 81 | |||
| 82 | struct wm0010_priv { | ||
| 83 | struct snd_soc_codec *codec; | ||
| 84 | |||
| 85 | struct mutex lock; | ||
| 86 | struct device *dev; | ||
| 87 | |||
| 88 | struct wm0010_pdata pdata; | ||
| 89 | |||
| 90 | int gpio_reset; | ||
| 91 | int gpio_reset_value; | ||
| 92 | |||
| 93 | struct regulator_bulk_data core_supplies[2]; | ||
| 94 | struct regulator *dbvdd; | ||
| 95 | |||
| 96 | int sysclk; | ||
| 97 | |||
| 98 | enum wm0010_state state; | ||
| 99 | bool boot_failed; | ||
| 100 | int boot_done; | ||
| 101 | bool ready; | ||
| 102 | bool pll_running; | ||
| 103 | int max_spi_freq; | ||
| 104 | int board_max_spi_speed; | ||
| 105 | u32 pll_clkctrl1; | ||
| 106 | |||
| 107 | spinlock_t irq_lock; | ||
| 108 | int irq; | ||
| 109 | |||
| 110 | struct completion boot_completion; | ||
| 111 | }; | ||
| 112 | |||
| 113 | struct wm0010_spi_msg { | ||
| 114 | struct spi_message m; | ||
| 115 | struct spi_transfer t; | ||
| 116 | u8 *tx_buf; | ||
| 117 | u8 *rx_buf; | ||
| 118 | size_t len; | ||
| 119 | }; | ||
| 120 | |||
| 121 | static const struct snd_soc_dapm_widget wm0010_dapm_widgets[] = { | ||
| 122 | SND_SOC_DAPM_SUPPLY("CLKIN", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
| 123 | }; | ||
| 124 | |||
| 125 | static const struct snd_soc_dapm_route wm0010_dapm_routes[] = { | ||
| 126 | { "SDI2 Capture", NULL, "SDI1 Playback" }, | ||
| 127 | { "SDI1 Capture", NULL, "SDI2 Playback" }, | ||
| 128 | |||
| 129 | { "SDI1 Capture", NULL, "CLKIN" }, | ||
| 130 | { "SDI2 Capture", NULL, "CLKIN" }, | ||
| 131 | { "SDI1 Playback", NULL, "CLKIN" }, | ||
| 132 | { "SDI2 Playback", NULL, "CLKIN" }, | ||
| 133 | }; | ||
| 134 | |||
| 135 | static const char *wm0010_state_to_str(enum wm0010_state state) | ||
| 136 | { | ||
| 137 | const char *state_to_str[] = { | ||
| 138 | "Power off", | ||
| 139 | "Out of reset", | ||
| 140 | "Boot ROM", | ||
| 141 | "Stage2", | ||
| 142 | "Firmware" | ||
| 143 | }; | ||
| 144 | |||
| 145 | if (state < 0 || state >= ARRAY_SIZE(state_to_str)) | ||
| 146 | return "null"; | ||
| 147 | return state_to_str[state]; | ||
| 148 | } | ||
| 149 | |||
| 150 | /* Called with wm0010->lock held */ | ||
| 151 | static void wm0010_halt(struct snd_soc_codec *codec) | ||
| 152 | { | ||
| 153 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
| 154 | unsigned long flags; | ||
| 155 | enum wm0010_state state; | ||
| 156 | |||
| 157 | /* Fetch the wm0010 state */ | ||
| 158 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
| 159 | state = wm0010->state; | ||
| 160 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
| 161 | |||
| 162 | switch (state) { | ||
| 163 | case WM0010_POWER_OFF: | ||
| 164 | /* If there's nothing to do, bail out */ | ||
| 165 | return; | ||
| 166 | case WM0010_OUT_OF_RESET: | ||
| 167 | case WM0010_BOOTROM: | ||
| 168 | case WM0010_STAGE2: | ||
| 169 | case WM0010_FIRMWARE: | ||
| 170 | /* Remember to put chip back into reset */ | ||
| 171 | gpio_set_value_cansleep(wm0010->gpio_reset, | ||
| 172 | wm0010->gpio_reset_value); | ||
| 173 | /* Disable the regulators */ | ||
| 174 | regulator_disable(wm0010->dbvdd); | ||
| 175 | regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), | ||
| 176 | wm0010->core_supplies); | ||
| 177 | break; | ||
| 178 | } | ||
| 179 | |||
| 180 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
| 181 | wm0010->state = WM0010_POWER_OFF; | ||
| 182 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
| 183 | } | ||
| 184 | |||
| 185 | struct wm0010_boot_xfer { | ||
| 186 | struct list_head list; | ||
| 187 | struct snd_soc_codec *codec; | ||
| 188 | struct completion *done; | ||
| 189 | struct spi_message m; | ||
| 190 | struct spi_transfer t; | ||
| 191 | }; | ||
| 192 | |||
| 193 | /* Called with wm0010->lock held */ | ||
| 194 | static void wm0010_mark_boot_failure(struct wm0010_priv *wm0010) | ||
| 195 | { | ||
| 196 | enum wm0010_state state; | ||
| 197 | unsigned long flags; | ||
| 198 | |||
| 199 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
| 200 | state = wm0010->state; | ||
| 201 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
| 202 | |||
| 203 | dev_err(wm0010->dev, "Failed to transition from `%s' state to `%s' state\n", | ||
| 204 | wm0010_state_to_str(state), wm0010_state_to_str(state + 1)); | ||
| 205 | |||
| 206 | wm0010->boot_failed = true; | ||
| 207 | } | ||
| 208 | |||
| 209 | static void wm0010_boot_xfer_complete(void *data) | ||
| 210 | { | ||
| 211 | struct wm0010_boot_xfer *xfer = data; | ||
| 212 | struct snd_soc_codec *codec = xfer->codec; | ||
| 213 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
| 214 | u32 *out32 = xfer->t.rx_buf; | ||
| 215 | int i; | ||
| 216 | |||
| 217 | if (xfer->m.status != 0) { | ||
| 218 | dev_err(codec->dev, "SPI transfer failed: %d\n", | ||
| 219 | xfer->m.status); | ||
| 220 | wm0010_mark_boot_failure(wm0010); | ||
| 221 | if (xfer->done) | ||
| 222 | complete(xfer->done); | ||
| 223 | return; | ||
| 224 | } | ||
| 225 | |||
| 226 | for (i = 0; i < xfer->t.len / 4; i++) { | ||
| 227 | dev_dbg(codec->dev, "%d: %04x\n", i, out32[i]); | ||
| 228 | |||
| 229 | switch (be32_to_cpu(out32[i])) { | ||
| 230 | case 0xe0e0e0e0: | ||
| 231 | dev_err(codec->dev, | ||
| 232 | "%d: ROM error reported in stage 2\n", i); | ||
| 233 | wm0010_mark_boot_failure(wm0010); | ||
| 234 | break; | ||
| 235 | |||
| 236 | case 0x55555555: | ||
| 237 | if (wm0010->boot_done == 0) | ||
| 238 | break; | ||
| 239 | dev_err(codec->dev, | ||
| 240 | "%d: ROM bootloader running in stage 2\n", i); | ||
| 241 | wm0010_mark_boot_failure(wm0010); | ||
| 242 | break; | ||
| 243 | |||
| 244 | case 0x0fed0000: | ||
| 245 | dev_dbg(codec->dev, "Stage2 loader running\n"); | ||
| 246 | break; | ||
| 247 | |||
| 248 | case 0x0fed0007: | ||
| 249 | dev_dbg(codec->dev, "CODE_HDR packet received\n"); | ||
| 250 | break; | ||
| 251 | |||
| 252 | case 0x0fed0008: | ||
| 253 | dev_dbg(codec->dev, "CODE_DATA packet received\n"); | ||
| 254 | break; | ||
| 255 | |||
| 256 | case 0x0fed0009: | ||
| 257 | dev_dbg(codec->dev, "Download complete\n"); | ||
| 258 | break; | ||
| 259 | |||
| 260 | case 0x0fed000c: | ||
| 261 | dev_dbg(codec->dev, "Application start\n"); | ||
| 262 | break; | ||
| 263 | |||
| 264 | case 0x0fed000e: | ||
| 265 | dev_dbg(codec->dev, "PLL packet received\n"); | ||
| 266 | wm0010->pll_running = true; | ||
| 267 | break; | ||
| 268 | |||
| 269 | case 0x0fed0025: | ||
| 270 | dev_err(codec->dev, "Device reports image too long\n"); | ||
| 271 | wm0010_mark_boot_failure(wm0010); | ||
| 272 | break; | ||
| 273 | |||
| 274 | case 0x0fed002c: | ||
| 275 | dev_err(codec->dev, "Device reports bad SPI packet\n"); | ||
| 276 | wm0010_mark_boot_failure(wm0010); | ||
| 277 | break; | ||
| 278 | |||
| 279 | case 0x0fed0031: | ||
| 280 | dev_err(codec->dev, "Device reports SPI read overflow\n"); | ||
| 281 | wm0010_mark_boot_failure(wm0010); | ||
| 282 | break; | ||
| 283 | |||
| 284 | case 0x0fed0032: | ||
| 285 | dev_err(codec->dev, "Device reports SPI underclock\n"); | ||
| 286 | wm0010_mark_boot_failure(wm0010); | ||
| 287 | break; | ||
| 288 | |||
| 289 | case 0x0fed0033: | ||
| 290 | dev_err(codec->dev, "Device reports bad header packet\n"); | ||
| 291 | wm0010_mark_boot_failure(wm0010); | ||
| 292 | break; | ||
| 293 | |||
| 294 | case 0x0fed0034: | ||
| 295 | dev_err(codec->dev, "Device reports invalid packet type\n"); | ||
| 296 | wm0010_mark_boot_failure(wm0010); | ||
| 297 | break; | ||
| 298 | |||
| 299 | case 0x0fed0035: | ||
| 300 | dev_err(codec->dev, "Device reports data before header error\n"); | ||
| 301 | wm0010_mark_boot_failure(wm0010); | ||
| 302 | break; | ||
| 303 | |||
| 304 | case 0x0fed0038: | ||
| 305 | dev_err(codec->dev, "Device reports invalid PLL packet\n"); | ||
| 306 | break; | ||
| 307 | |||
| 308 | case 0x0fed003a: | ||
| 309 | dev_err(codec->dev, "Device reports packet alignment error\n"); | ||
| 310 | wm0010_mark_boot_failure(wm0010); | ||
| 311 | break; | ||
| 312 | |||
| 313 | default: | ||
| 314 | dev_err(codec->dev, "Unrecognised return 0x%x\n", | ||
| 315 | be32_to_cpu(out32[i])); | ||
| 316 | wm0010_mark_boot_failure(wm0010); | ||
| 317 | break; | ||
| 318 | } | ||
| 319 | |||
| 320 | if (wm0010->boot_failed) | ||
| 321 | break; | ||
| 322 | } | ||
| 323 | |||
| 324 | wm0010->boot_done++; | ||
| 325 | if (xfer->done) | ||
| 326 | complete(xfer->done); | ||
| 327 | } | ||
| 328 | |||
| 329 | static void byte_swap_64(u64 *data_in, u64 *data_out, u32 len) | ||
| 330 | { | ||
| 331 | int i; | ||
| 332 | |||
| 333 | for (i = 0; i < len / 8; i++) | ||
| 334 | data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i])); | ||
| 335 | } | ||
| 336 | |||
| 337 | static int wm0010_boot(struct snd_soc_codec *codec) | ||
| 338 | { | ||
| 339 | struct spi_device *spi = to_spi_device(codec->dev); | ||
| 340 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
| 341 | unsigned long flags; | ||
| 342 | struct list_head xfer_list; | ||
| 343 | struct wm0010_boot_xfer *xfer; | ||
| 344 | int ret; | ||
| 345 | struct completion done; | ||
| 346 | const struct firmware *fw; | ||
| 347 | const struct dfw_binrec *rec; | ||
| 348 | struct spi_message m; | ||
| 349 | struct spi_transfer t; | ||
| 350 | struct dfw_pllrec pll_rec; | ||
| 351 | u32 *img, *p; | ||
| 352 | u64 *img_swap; | ||
| 353 | u8 *out; | ||
| 354 | u32 len, offset; | ||
| 355 | int i; | ||
| 356 | |||
| 357 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
| 358 | if (wm0010->state != WM0010_POWER_OFF) | ||
| 359 | dev_warn(wm0010->dev, "DSP already powered up!\n"); | ||
| 360 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
| 361 | |||
| 362 | if (wm0010->sysclk > 26000000) { | ||
| 363 | dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n"); | ||
| 364 | ret = -ECANCELED; | ||
| 365 | goto err; | ||
| 366 | } | ||
| 367 | |||
| 368 | INIT_LIST_HEAD(&xfer_list); | ||
| 369 | |||
| 370 | mutex_lock(&wm0010->lock); | ||
| 371 | wm0010->pll_running = false; | ||
| 372 | |||
| 373 | dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq); | ||
| 374 | |||
| 375 | ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies), | ||
| 376 | wm0010->core_supplies); | ||
| 377 | if (ret != 0) { | ||
| 378 | dev_err(&spi->dev, "Failed to enable core supplies: %d\n", | ||
| 379 | ret); | ||
| 380 | mutex_unlock(&wm0010->lock); | ||
| 381 | goto err; | ||
| 382 | } | ||
| 383 | |||
| 384 | ret = regulator_enable(wm0010->dbvdd); | ||
| 385 | if (ret != 0) { | ||
| 386 | dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret); | ||
| 387 | goto err_core; | ||
| 388 | } | ||
| 389 | |||
| 390 | /* Release reset */ | ||
| 391 | gpio_set_value_cansleep(wm0010->gpio_reset, !wm0010->gpio_reset_value); | ||
| 392 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
| 393 | wm0010->state = WM0010_OUT_OF_RESET; | ||
| 394 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
| 395 | |||
| 396 | /* First the bootloader */ | ||
| 397 | ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev); | ||
| 398 | if (ret != 0) { | ||
| 399 | dev_err(codec->dev, "Failed to request stage2 loader: %d\n", | ||
| 400 | ret); | ||
| 401 | goto abort; | ||
| 402 | } | ||
| 403 | |||
| 404 | if (!wait_for_completion_timeout(&wm0010->boot_completion, | ||
| 405 | msecs_to_jiffies(10))) | ||
| 406 | dev_err(codec->dev, "Failed to get interrupt from DSP\n"); | ||
| 407 | |||
| 408 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
| 409 | wm0010->state = WM0010_BOOTROM; | ||
| 410 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
| 411 | |||
| 412 | dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size); | ||
| 413 | |||
| 414 | /* Copy to local buffer first as vmalloc causes problems for dma */ | ||
| 415 | img = kzalloc(fw->size, GFP_KERNEL); | ||
| 416 | if (!img) { | ||
| 417 | dev_err(codec->dev, "Failed to allocate image buffer\n"); | ||
| 418 | goto abort; | ||
| 419 | } | ||
| 420 | |||
| 421 | out = kzalloc(fw->size, GFP_KERNEL); | ||
| 422 | if (!out) { | ||
| 423 | dev_err(codec->dev, "Failed to allocate output buffer\n"); | ||
| 424 | goto abort; | ||
| 425 | } | ||
| 426 | |||
| 427 | memcpy(img, &fw->data[0], fw->size); | ||
| 428 | |||
| 429 | spi_message_init(&m); | ||
| 430 | memset(&t, 0, sizeof(t)); | ||
| 431 | t.rx_buf = out; | ||
| 432 | t.tx_buf = img; | ||
| 433 | t.len = fw->size; | ||
| 434 | t.bits_per_word = 8; | ||
| 435 | t.speed_hz = wm0010->sysclk / 10; | ||
| 436 | spi_message_add_tail(&t, &m); | ||
| 437 | |||
| 438 | dev_dbg(codec->dev, "Starting initial download at %dHz\n", | ||
| 439 | t.speed_hz); | ||
| 440 | |||
| 441 | ret = spi_sync(spi, &m); | ||
| 442 | if (ret != 0) { | ||
| 443 | dev_err(codec->dev, "Initial download failed: %d\n", ret); | ||
| 444 | goto abort; | ||
| 445 | } | ||
| 446 | |||
| 447 | /* Look for errors from the boot ROM */ | ||
| 448 | for (i = 0; i < fw->size; i++) { | ||
| 449 | if (out[i] != 0x55) { | ||
| 450 | ret = -EBUSY; | ||
| 451 | dev_err(codec->dev, "Boot ROM error: %x in %d\n", | ||
| 452 | out[i], i); | ||
| 453 | wm0010_mark_boot_failure(wm0010); | ||
| 454 | goto abort; | ||
| 455 | } | ||
| 456 | } | ||
| 457 | |||
| 458 | release_firmware(fw); | ||
| 459 | kfree(img); | ||
| 460 | kfree(out); | ||
| 461 | |||
| 462 | if (!wait_for_completion_timeout(&wm0010->boot_completion, | ||
| 463 | msecs_to_jiffies(10))) | ||
| 464 | dev_err(codec->dev, "Failed to get interrupt from DSP loader.\n"); | ||
| 465 | |||
| 466 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
| 467 | wm0010->state = WM0010_STAGE2; | ||
| 468 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
| 469 | |||
| 470 | /* Only initialise PLL if max_spi_freq initialised */ | ||
| 471 | if (wm0010->max_spi_freq) { | ||
| 472 | |||
| 473 | /* Initialise a PLL record */ | ||
| 474 | memset(&pll_rec, 0, sizeof(pll_rec)); | ||
| 475 | pll_rec.command = DFW_CMD_PLL; | ||
| 476 | pll_rec.length = (sizeof(pll_rec) - 8); | ||
| 477 | |||
| 478 | /* On wm0010 only the CLKCTRL1 value is used */ | ||
| 479 | pll_rec.clkctrl1 = wm0010->pll_clkctrl1; | ||
| 480 | |||
| 481 | len = pll_rec.length + 8; | ||
| 482 | out = kzalloc(len, GFP_KERNEL); | ||
| 483 | if (!out) { | ||
| 484 | dev_err(codec->dev, | ||
| 485 | "Failed to allocate RX buffer\n"); | ||
| 486 | goto abort; | ||
| 487 | } | ||
| 488 | |||
| 489 | img_swap = kzalloc(len, GFP_KERNEL); | ||
| 490 | if (!img_swap) { | ||
| 491 | dev_err(codec->dev, | ||
| 492 | "Failed to allocate image buffer\n"); | ||
| 493 | goto abort; | ||
| 494 | } | ||
| 495 | |||
| 496 | /* We need to re-order for 0010 */ | ||
| 497 | byte_swap_64((u64 *)&pll_rec, img_swap, len); | ||
| 498 | |||
| 499 | spi_message_init(&m); | ||
| 500 | memset(&t, 0, sizeof(t)); | ||
| 501 | t.rx_buf = out; | ||
| 502 | t.tx_buf = img_swap; | ||
| 503 | t.len = len; | ||
| 504 | t.bits_per_word = 8; | ||
| 505 | t.speed_hz = wm0010->sysclk / 6; | ||
| 506 | spi_message_add_tail(&t, &m); | ||
| 507 | |||
| 508 | ret = spi_sync(spi, &m); | ||
| 509 | if (ret != 0) { | ||
| 510 | dev_err(codec->dev, "First PLL write failed: %d\n", ret); | ||
| 511 | goto abort; | ||
| 512 | } | ||
| 513 | |||
| 514 | /* Use a second send of the message to get the return status */ | ||
| 515 | ret = spi_sync(spi, &m); | ||
| 516 | if (ret != 0) { | ||
| 517 | dev_err(codec->dev, "Second PLL write failed: %d\n", ret); | ||
| 518 | goto abort; | ||
| 519 | } | ||
| 520 | |||
| 521 | p = (u32 *)out; | ||
| 522 | |||
| 523 | /* Look for PLL active code from the DSP */ | ||
| 524 | for (i = 0; i < len / 4; i++) { | ||
| 525 | if (*p == 0x0e00ed0f) { | ||
| 526 | dev_dbg(codec->dev, "PLL packet received\n"); | ||
| 527 | wm0010->pll_running = true; | ||
| 528 | break; | ||
| 529 | } | ||
| 530 | p++; | ||
| 531 | } | ||
| 532 | |||
| 533 | kfree(img_swap); | ||
| 534 | kfree(out); | ||
| 535 | } else | ||
| 536 | dev_dbg(codec->dev, "Not enabling DSP PLL."); | ||
| 537 | |||
| 538 | ret = request_firmware(&fw, "wm0010.dfw", codec->dev); | ||
| 539 | if (ret != 0) { | ||
| 540 | dev_err(codec->dev, "Failed to request application: %d\n", | ||
| 541 | ret); | ||
| 542 | goto abort; | ||
| 543 | } | ||
| 544 | |||
| 545 | rec = (const struct dfw_binrec *)fw->data; | ||
| 546 | offset = 0; | ||
| 547 | wm0010->boot_done = 0; | ||
| 548 | wm0010->boot_failed = false; | ||
| 549 | BUG_ON(!list_empty(&xfer_list)); | ||
| 550 | init_completion(&done); | ||
| 551 | |||
| 552 | /* First record should be INFO */ | ||
| 553 | if (rec->command != DFW_CMD_INFO) { | ||
| 554 | dev_err(codec->dev, "First record not INFO\r\n"); | ||
| 555 | goto abort; | ||
| 556 | } | ||
| 557 | |||
| 558 | /* Check it's a 0010 file */ | ||
| 559 | if (rec->data[0] != DEVICE_ID_WM0010) { | ||
| 560 | dev_err(codec->dev, "Not a WM0010 firmware file.\r\n"); | ||
| 561 | goto abort; | ||
| 562 | } | ||
| 563 | |||
| 564 | /* Skip the info record as we don't need to send it */ | ||
| 565 | offset += ((rec->length) + 8); | ||
| 566 | rec = (void *)&rec->data[rec->length]; | ||
| 567 | |||
| 568 | while (offset < fw->size) { | ||
| 569 | dev_dbg(codec->dev, | ||
| 570 | "Packet: command %d, data length = 0x%x\r\n", | ||
| 571 | rec->command, rec->length); | ||
| 572 | len = rec->length + 8; | ||
| 573 | |||
| 574 | out = kzalloc(len, GFP_KERNEL); | ||
| 575 | if (!out) { | ||
| 576 | dev_err(codec->dev, | ||
| 577 | "Failed to allocate RX buffer\n"); | ||
| 578 | goto abort; | ||
| 579 | } | ||
| 580 | |||
| 581 | img_swap = kzalloc(len, GFP_KERNEL); | ||
| 582 | if (!img_swap) { | ||
| 583 | dev_err(codec->dev, | ||
| 584 | "Failed to allocate image buffer\n"); | ||
| 585 | goto abort; | ||
| 586 | } | ||
| 587 | |||
| 588 | /* We need to re-order for 0010 */ | ||
| 589 | byte_swap_64((u64 *)&rec->command, img_swap, len); | ||
| 590 | |||
| 591 | xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); | ||
| 592 | if (!xfer) { | ||
| 593 | dev_err(codec->dev, "Failed to allocate xfer\n"); | ||
| 594 | goto abort; | ||
| 595 | } | ||
| 596 | |||
| 597 | xfer->codec = codec; | ||
| 598 | list_add_tail(&xfer->list, &xfer_list); | ||
| 599 | |||
| 600 | spi_message_init(&xfer->m); | ||
| 601 | xfer->m.complete = wm0010_boot_xfer_complete; | ||
| 602 | xfer->m.context = xfer; | ||
| 603 | xfer->t.tx_buf = img_swap; | ||
| 604 | xfer->t.rx_buf = out; | ||
| 605 | xfer->t.len = len; | ||
| 606 | xfer->t.bits_per_word = 8; | ||
| 607 | |||
| 608 | if (!wm0010->pll_running) { | ||
| 609 | xfer->t.speed_hz = wm0010->sysclk / 6; | ||
| 610 | } else { | ||
| 611 | xfer->t.speed_hz = wm0010->max_spi_freq; | ||
| 612 | |||
| 613 | if (wm0010->board_max_spi_speed && | ||
| 614 | (wm0010->board_max_spi_speed < wm0010->max_spi_freq)) | ||
| 615 | xfer->t.speed_hz = wm0010->board_max_spi_speed; | ||
| 616 | } | ||
| 617 | |||
| 618 | /* Store max usable spi frequency for later use */ | ||
| 619 | wm0010->max_spi_freq = xfer->t.speed_hz; | ||
| 620 | |||
| 621 | spi_message_add_tail(&xfer->t, &xfer->m); | ||
| 622 | |||
| 623 | offset += ((rec->length) + 8); | ||
| 624 | rec = (void *)&rec->data[rec->length]; | ||
| 625 | |||
| 626 | if (offset >= fw->size) { | ||
| 627 | dev_dbg(codec->dev, "All transfers scheduled\n"); | ||
| 628 | xfer->done = &done; | ||
| 629 | } | ||
| 630 | |||
| 631 | ret = spi_async(spi, &xfer->m); | ||
| 632 | if (ret != 0) { | ||
| 633 | dev_err(codec->dev, "Write failed: %d\n", ret); | ||
| 634 | goto abort; | ||
| 635 | } | ||
| 636 | |||
| 637 | if (wm0010->boot_failed) | ||
| 638 | goto abort; | ||
| 639 | } | ||
| 640 | |||
| 641 | wait_for_completion(&done); | ||
| 642 | |||
| 643 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
| 644 | wm0010->state = WM0010_FIRMWARE; | ||
| 645 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
| 646 | |||
| 647 | mutex_unlock(&wm0010->lock); | ||
| 648 | |||
| 649 | release_firmware(fw); | ||
| 650 | |||
| 651 | while (!list_empty(&xfer_list)) { | ||
| 652 | xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer, | ||
| 653 | list); | ||
| 654 | kfree(xfer->t.rx_buf); | ||
| 655 | kfree(xfer->t.tx_buf); | ||
| 656 | list_del(&xfer->list); | ||
| 657 | kfree(xfer); | ||
| 658 | } | ||
| 659 | |||
| 660 | return 0; | ||
| 661 | |||
| 662 | abort: | ||
| 663 | /* Put the chip back into reset */ | ||
| 664 | wm0010_halt(codec); | ||
| 665 | mutex_unlock(&wm0010->lock); | ||
| 666 | return ret; | ||
| 667 | |||
| 668 | err_core: | ||
| 669 | mutex_unlock(&wm0010->lock); | ||
| 670 | regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), | ||
| 671 | wm0010->core_supplies); | ||
| 672 | err: | ||
| 673 | return ret; | ||
| 674 | } | ||
| 675 | |||
| 676 | static int wm0010_set_bias_level(struct snd_soc_codec *codec, | ||
| 677 | enum snd_soc_bias_level level) | ||
| 678 | { | ||
| 679 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
| 680 | |||
| 681 | switch (level) { | ||
| 682 | case SND_SOC_BIAS_ON: | ||
| 683 | if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) | ||
| 684 | wm0010_boot(codec); | ||
| 685 | break; | ||
| 686 | case SND_SOC_BIAS_PREPARE: | ||
| 687 | break; | ||
| 688 | case SND_SOC_BIAS_STANDBY: | ||
| 689 | if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) { | ||
| 690 | mutex_lock(&wm0010->lock); | ||
| 691 | wm0010_halt(codec); | ||
| 692 | mutex_unlock(&wm0010->lock); | ||
| 693 | } | ||
| 694 | break; | ||
| 695 | case SND_SOC_BIAS_OFF: | ||
| 696 | break; | ||
| 697 | } | ||
| 698 | |||
| 699 | codec->dapm.bias_level = level; | ||
| 700 | |||
| 701 | return 0; | ||
| 702 | } | ||
| 703 | |||
| 704 | static int wm0010_set_sysclk(struct snd_soc_codec *codec, int source, | ||
| 705 | int clk_id, unsigned int freq, int dir) | ||
| 706 | { | ||
| 707 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
| 708 | unsigned int i; | ||
| 709 | |||
| 710 | wm0010->sysclk = freq; | ||
| 711 | |||
| 712 | if (freq < pll_clock_map[ARRAY_SIZE(pll_clock_map)-1].max_sysclk) { | ||
| 713 | wm0010->max_spi_freq = 0; | ||
| 714 | } else { | ||
| 715 | for (i = 0; i < ARRAY_SIZE(pll_clock_map); i++) | ||
| 716 | if (freq >= pll_clock_map[i].max_sysclk) | ||
| 717 | break; | ||
| 718 | |||
| 719 | wm0010->max_spi_freq = pll_clock_map[i].max_pll_spi_speed; | ||
| 720 | wm0010->pll_clkctrl1 = pll_clock_map[i].pll_clkctrl1; | ||
| 721 | } | ||
| 722 | |||
| 723 | return 0; | ||
| 724 | } | ||
| 725 | |||
| 726 | static int wm0010_probe(struct snd_soc_codec *codec); | ||
| 727 | |||
| 728 | static struct snd_soc_codec_driver soc_codec_dev_wm0010 = { | ||
| 729 | .probe = wm0010_probe, | ||
| 730 | .set_bias_level = wm0010_set_bias_level, | ||
| 731 | .set_sysclk = wm0010_set_sysclk, | ||
| 732 | .idle_bias_off = true, | ||
| 733 | |||
| 734 | .dapm_widgets = wm0010_dapm_widgets, | ||
| 735 | .num_dapm_widgets = ARRAY_SIZE(wm0010_dapm_widgets), | ||
| 736 | .dapm_routes = wm0010_dapm_routes, | ||
| 737 | .num_dapm_routes = ARRAY_SIZE(wm0010_dapm_routes), | ||
| 738 | }; | ||
| 739 | |||
| 740 | #define WM0010_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) | ||
| 741 | #define WM0010_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
| 742 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\ | ||
| 743 | SNDRV_PCM_FMTBIT_S32_LE) | ||
| 744 | |||
| 745 | static struct snd_soc_dai_driver wm0010_dai[] = { | ||
| 746 | { | ||
| 747 | .name = "wm0010-sdi1", | ||
| 748 | .playback = { | ||
| 749 | .stream_name = "SDI1 Playback", | ||
| 750 | .channels_min = 1, | ||
| 751 | .channels_max = 2, | ||
| 752 | .rates = WM0010_RATES, | ||
| 753 | .formats = WM0010_FORMATS, | ||
| 754 | }, | ||
| 755 | .capture = { | ||
| 756 | .stream_name = "SDI1 Capture", | ||
| 757 | .channels_min = 1, | ||
| 758 | .channels_max = 2, | ||
| 759 | .rates = WM0010_RATES, | ||
| 760 | .formats = WM0010_FORMATS, | ||
| 761 | }, | ||
| 762 | }, | ||
| 763 | { | ||
| 764 | .name = "wm0010-sdi2", | ||
| 765 | .playback = { | ||
| 766 | .stream_name = "SDI2 Playback", | ||
| 767 | .channels_min = 1, | ||
| 768 | .channels_max = 2, | ||
| 769 | .rates = WM0010_RATES, | ||
| 770 | .formats = WM0010_FORMATS, | ||
| 771 | }, | ||
| 772 | .capture = { | ||
| 773 | .stream_name = "SDI2 Capture", | ||
| 774 | .channels_min = 1, | ||
| 775 | .channels_max = 2, | ||
| 776 | .rates = WM0010_RATES, | ||
| 777 | .formats = WM0010_FORMATS, | ||
| 778 | }, | ||
| 779 | }, | ||
| 780 | }; | ||
| 781 | |||
| 782 | static irqreturn_t wm0010_irq(int irq, void *data) | ||
| 783 | { | ||
| 784 | struct wm0010_priv *wm0010 = data; | ||
| 785 | |||
| 786 | switch (wm0010->state) { | ||
| 787 | case WM0010_POWER_OFF: | ||
| 788 | case WM0010_OUT_OF_RESET: | ||
| 789 | case WM0010_BOOTROM: | ||
| 790 | case WM0010_STAGE2: | ||
| 791 | spin_lock(&wm0010->irq_lock); | ||
| 792 | complete(&wm0010->boot_completion); | ||
| 793 | spin_unlock(&wm0010->irq_lock); | ||
| 794 | return IRQ_HANDLED; | ||
| 795 | default: | ||
| 796 | return IRQ_NONE; | ||
| 797 | } | ||
| 798 | |||
| 799 | return IRQ_NONE; | ||
| 800 | } | ||
| 801 | |||
| 802 | static int wm0010_probe(struct snd_soc_codec *codec) | ||
| 803 | { | ||
| 804 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
| 805 | |||
| 806 | wm0010->codec = codec; | ||
| 807 | |||
| 808 | return 0; | ||
| 809 | } | ||
| 810 | |||
| 811 | static int __devinit wm0010_spi_probe(struct spi_device *spi) | ||
| 812 | { | ||
| 813 | unsigned long gpio_flags; | ||
| 814 | int ret; | ||
| 815 | int trigger; | ||
| 816 | int irq; | ||
| 817 | struct wm0010_priv *wm0010; | ||
| 818 | |||
| 819 | wm0010 = devm_kzalloc(&spi->dev, sizeof(*wm0010), | ||
| 820 | GFP_KERNEL); | ||
| 821 | if (!wm0010) | ||
| 822 | return -ENOMEM; | ||
| 823 | |||
| 824 | mutex_init(&wm0010->lock); | ||
| 825 | spin_lock_init(&wm0010->irq_lock); | ||
| 826 | |||
| 827 | spi_set_drvdata(spi, wm0010); | ||
| 828 | wm0010->dev = &spi->dev; | ||
| 829 | |||
| 830 | if (dev_get_platdata(&spi->dev)) | ||
| 831 | memcpy(&wm0010->pdata, dev_get_platdata(&spi->dev), | ||
| 832 | sizeof(wm0010->pdata)); | ||
| 833 | |||
| 834 | init_completion(&wm0010->boot_completion); | ||
| 835 | |||
| 836 | wm0010->core_supplies[0].supply = "AVDD"; | ||
| 837 | wm0010->core_supplies[1].supply = "DCVDD"; | ||
| 838 | ret = devm_regulator_bulk_get(wm0010->dev, ARRAY_SIZE(wm0010->core_supplies), | ||
| 839 | wm0010->core_supplies); | ||
| 840 | if (ret != 0) { | ||
| 841 | dev_err(wm0010->dev, "Failed to obtain core supplies: %d\n", | ||
| 842 | ret); | ||
| 843 | return ret; | ||
| 844 | } | ||
| 845 | |||
| 846 | wm0010->dbvdd = devm_regulator_get(wm0010->dev, "DBVDD"); | ||
| 847 | if (IS_ERR(wm0010->dbvdd)) { | ||
| 848 | ret = PTR_ERR(wm0010->dbvdd); | ||
| 849 | dev_err(wm0010->dev, "Failed to obtain DBVDD: %d\n", ret); | ||
| 850 | return ret; | ||
| 851 | } | ||
| 852 | |||
| 853 | if (wm0010->pdata.gpio_reset) { | ||
| 854 | wm0010->gpio_reset = wm0010->pdata.gpio_reset; | ||
| 855 | |||
| 856 | if (wm0010->pdata.reset_active_high) | ||
| 857 | wm0010->gpio_reset_value = 1; | ||
| 858 | else | ||
| 859 | wm0010->gpio_reset_value = 0; | ||
| 860 | |||
| 861 | if (wm0010->gpio_reset_value) | ||
| 862 | gpio_flags = GPIOF_OUT_INIT_HIGH; | ||
| 863 | else | ||
| 864 | gpio_flags = GPIOF_OUT_INIT_LOW; | ||
| 865 | |||
| 866 | ret = devm_gpio_request_one(wm0010->dev, wm0010->gpio_reset, | ||
| 867 | gpio_flags, "wm0010 reset"); | ||
| 868 | if (ret < 0) { | ||
| 869 | dev_err(wm0010->dev, | ||
| 870 | "Failed to request GPIO for DSP reset: %d\n", | ||
| 871 | ret); | ||
| 872 | return ret; | ||
| 873 | } | ||
| 874 | } else { | ||
| 875 | dev_err(wm0010->dev, "No reset GPIO configured\n"); | ||
| 876 | return -EINVAL; | ||
| 877 | } | ||
| 878 | |||
| 879 | wm0010->state = WM0010_POWER_OFF; | ||
| 880 | |||
| 881 | irq = spi->irq; | ||
| 882 | if (wm0010->pdata.irq_flags) | ||
| 883 | trigger = wm0010->pdata.irq_flags; | ||
| 884 | else | ||
| 885 | trigger = IRQF_TRIGGER_FALLING; | ||
| 886 | trigger |= IRQF_ONESHOT; | ||
| 887 | |||
| 888 | ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger | IRQF_ONESHOT, | ||
| 889 | "wm0010", wm0010); | ||
| 890 | if (ret) { | ||
| 891 | dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n", | ||
| 892 | irq, ret); | ||
| 893 | return ret; | ||
| 894 | } | ||
| 895 | wm0010->irq = irq; | ||
| 896 | |||
| 897 | if (spi->max_speed_hz) | ||
| 898 | wm0010->board_max_spi_speed = spi->max_speed_hz; | ||
| 899 | else | ||
| 900 | wm0010->board_max_spi_speed = 0; | ||
| 901 | |||
| 902 | ret = snd_soc_register_codec(&spi->dev, | ||
| 903 | &soc_codec_dev_wm0010, wm0010_dai, | ||
| 904 | ARRAY_SIZE(wm0010_dai)); | ||
| 905 | if (ret < 0) | ||
| 906 | return ret; | ||
| 907 | |||
| 908 | return 0; | ||
| 909 | } | ||
| 910 | |||
| 911 | static int __devexit wm0010_spi_remove(struct spi_device *spi) | ||
| 912 | { | ||
| 913 | struct wm0010_priv *wm0010 = spi_get_drvdata(spi); | ||
| 914 | |||
| 915 | snd_soc_unregister_codec(&spi->dev); | ||
| 916 | |||
| 917 | gpio_set_value_cansleep(wm0010->gpio_reset, | ||
| 918 | wm0010->gpio_reset_value); | ||
| 919 | |||
| 920 | if (wm0010->irq) | ||
| 921 | free_irq(wm0010->irq, wm0010); | ||
| 922 | |||
| 923 | return 0; | ||
| 924 | } | ||
| 925 | |||
| 926 | static struct spi_driver wm0010_spi_driver = { | ||
| 927 | .driver = { | ||
| 928 | .name = "wm0010", | ||
| 929 | .bus = &spi_bus_type, | ||
| 930 | .owner = THIS_MODULE, | ||
| 931 | }, | ||
| 932 | .probe = wm0010_spi_probe, | ||
| 933 | .remove = __devexit_p(wm0010_spi_remove), | ||
| 934 | }; | ||
| 935 | |||
| 936 | module_spi_driver(wm0010_spi_driver); | ||
| 937 | |||
| 938 | MODULE_DESCRIPTION("ASoC WM0010 driver"); | ||
| 939 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
| 940 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index a3acb7a85f6a..683dc43b1d87 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/i2c.h> | 31 | #include <linux/i2c.h> |
| 32 | #include <linux/regmap.h> | 32 | #include <linux/regmap.h> |
| 33 | #include <linux/debugfs.h> | 33 | #include <linux/debugfs.h> |
| 34 | #include <linux/regulator/consumer.h> | ||
| 34 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
| 35 | #include <sound/core.h> | 36 | #include <sound/core.h> |
| 36 | #include <sound/pcm.h> | 37 | #include <sound/pcm.h> |
| @@ -43,6 +44,14 @@ | |||
| 43 | 44 | ||
| 44 | #include "wm2000.h" | 45 | #include "wm2000.h" |
| 45 | 46 | ||
| 47 | #define WM2000_NUM_SUPPLIES 3 | ||
| 48 | |||
| 49 | static const char *wm2000_supplies[WM2000_NUM_SUPPLIES] = { | ||
| 50 | "SPKVDD", | ||
| 51 | "DBVDD", | ||
| 52 | "DCVDD", | ||
| 53 | }; | ||
| 54 | |||
| 46 | enum wm2000_anc_mode { | 55 | enum wm2000_anc_mode { |
| 47 | ANC_ACTIVE = 0, | 56 | ANC_ACTIVE = 0, |
| 48 | ANC_BYPASS = 1, | 57 | ANC_BYPASS = 1, |
| @@ -54,6 +63,8 @@ struct wm2000_priv { | |||
| 54 | struct i2c_client *i2c; | 63 | struct i2c_client *i2c; |
| 55 | struct regmap *regmap; | 64 | struct regmap *regmap; |
| 56 | 65 | ||
| 66 | struct regulator_bulk_data supplies[WM2000_NUM_SUPPLIES]; | ||
| 67 | |||
| 57 | enum wm2000_anc_mode anc_mode; | 68 | enum wm2000_anc_mode anc_mode; |
| 58 | 69 | ||
| 59 | unsigned int anc_active:1; | 70 | unsigned int anc_active:1; |
| @@ -126,6 +137,12 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
| 126 | 137 | ||
| 127 | dev_dbg(&i2c->dev, "Beginning power up\n"); | 138 | dev_dbg(&i2c->dev, "Beginning power up\n"); |
| 128 | 139 | ||
| 140 | ret = regulator_bulk_enable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 141 | if (ret != 0) { | ||
| 142 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | ||
| 143 | return ret; | ||
| 144 | } | ||
| 145 | |||
| 129 | if (!wm2000->mclk_div) { | 146 | if (!wm2000->mclk_div) { |
| 130 | dev_dbg(&i2c->dev, "Disabling MCLK divider\n"); | 147 | dev_dbg(&i2c->dev, "Disabling MCLK divider\n"); |
| 131 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, | 148 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, |
| @@ -143,12 +160,14 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
| 143 | if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, | 160 | if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, |
| 144 | WM2000_ANC_ENG_IDLE)) { | 161 | WM2000_ANC_ENG_IDLE)) { |
| 145 | dev_err(&i2c->dev, "ANC engine failed to reset\n"); | 162 | dev_err(&i2c->dev, "ANC engine failed to reset\n"); |
| 163 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 146 | return -ETIMEDOUT; | 164 | return -ETIMEDOUT; |
| 147 | } | 165 | } |
| 148 | 166 | ||
| 149 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, | 167 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, |
| 150 | WM2000_STATUS_BOOT_COMPLETE)) { | 168 | WM2000_STATUS_BOOT_COMPLETE)) { |
| 151 | dev_err(&i2c->dev, "ANC engine failed to initialise\n"); | 169 | dev_err(&i2c->dev, "ANC engine failed to initialise\n"); |
| 170 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 152 | return -ETIMEDOUT; | 171 | return -ETIMEDOUT; |
| 153 | } | 172 | } |
| 154 | 173 | ||
| @@ -163,11 +182,13 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
| 163 | wm2000->anc_download_size); | 182 | wm2000->anc_download_size); |
| 164 | if (ret < 0) { | 183 | if (ret < 0) { |
| 165 | dev_err(&i2c->dev, "i2c_transfer() failed: %d\n", ret); | 184 | dev_err(&i2c->dev, "i2c_transfer() failed: %d\n", ret); |
| 185 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 166 | return ret; | 186 | return ret; |
| 167 | } | 187 | } |
| 168 | if (ret != wm2000->anc_download_size) { | 188 | if (ret != wm2000->anc_download_size) { |
| 169 | dev_err(&i2c->dev, "i2c_transfer() failed, %d != %d\n", | 189 | dev_err(&i2c->dev, "i2c_transfer() failed, %d != %d\n", |
| 170 | ret, wm2000->anc_download_size); | 190 | ret, wm2000->anc_download_size); |
| 191 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 171 | return -EIO; | 192 | return -EIO; |
| 172 | } | 193 | } |
| 173 | 194 | ||
| @@ -201,6 +222,7 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
| 201 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, | 222 | if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS, |
| 202 | WM2000_STATUS_MOUSE_ACTIVE)) { | 223 | WM2000_STATUS_MOUSE_ACTIVE)) { |
| 203 | dev_err(&i2c->dev, "Timed out waiting for device\n"); | 224 | dev_err(&i2c->dev, "Timed out waiting for device\n"); |
| 225 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 204 | return -ETIMEDOUT; | 226 | return -ETIMEDOUT; |
| 205 | } | 227 | } |
| 206 | 228 | ||
| @@ -238,6 +260,8 @@ static int wm2000_power_down(struct i2c_client *i2c, int analogue) | |||
| 238 | return -ETIMEDOUT; | 260 | return -ETIMEDOUT; |
| 239 | } | 261 | } |
| 240 | 262 | ||
| 263 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 264 | |||
| 241 | dev_dbg(&i2c->dev, "powered off\n"); | 265 | dev_dbg(&i2c->dev, "powered off\n"); |
| 242 | wm2000->anc_mode = ANC_OFF; | 266 | wm2000->anc_mode = ANC_OFF; |
| 243 | 267 | ||
| @@ -747,7 +771,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
| 747 | struct wm2000_platform_data *pdata; | 771 | struct wm2000_platform_data *pdata; |
| 748 | const char *filename; | 772 | const char *filename; |
| 749 | const struct firmware *fw = NULL; | 773 | const struct firmware *fw = NULL; |
| 750 | int ret; | 774 | int ret, i; |
| 751 | int reg; | 775 | int reg; |
| 752 | u16 id; | 776 | u16 id; |
| 753 | 777 | ||
| @@ -760,7 +784,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
| 760 | 784 | ||
| 761 | dev_set_drvdata(&i2c->dev, wm2000); | 785 | dev_set_drvdata(&i2c->dev, wm2000); |
| 762 | 786 | ||
| 763 | wm2000->regmap = regmap_init_i2c(i2c, &wm2000_regmap); | 787 | wm2000->regmap = devm_regmap_init_i2c(i2c, &wm2000_regmap); |
| 764 | if (IS_ERR(wm2000->regmap)) { | 788 | if (IS_ERR(wm2000->regmap)) { |
| 765 | ret = PTR_ERR(wm2000->regmap); | 789 | ret = PTR_ERR(wm2000->regmap); |
| 766 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | 790 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", |
| @@ -768,6 +792,22 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
| 768 | goto out; | 792 | goto out; |
| 769 | } | 793 | } |
| 770 | 794 | ||
| 795 | for (i = 0; i < WM2000_NUM_SUPPLIES; i++) | ||
| 796 | wm2000->supplies[i].supply = wm2000_supplies[i]; | ||
| 797 | |||
| 798 | ret = devm_regulator_bulk_get(&i2c->dev, WM2000_NUM_SUPPLIES, | ||
| 799 | wm2000->supplies); | ||
| 800 | if (ret != 0) { | ||
| 801 | dev_err(&i2c->dev, "Failed to get supplies: %d\n", ret); | ||
| 802 | return ret; | ||
| 803 | } | ||
| 804 | |||
| 805 | ret = regulator_bulk_enable(WM2000_NUM_SUPPLIES, wm2000->supplies); | ||
| 806 | if (ret != 0) { | ||
| 807 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | ||
| 808 | return ret; | ||
| 809 | } | ||
| 810 | |||
| 771 | /* Verify that this is a WM2000 */ | 811 | /* Verify that this is a WM2000 */ |
| 772 | reg = wm2000_read(i2c, WM2000_REG_ID1); | 812 | reg = wm2000_read(i2c, WM2000_REG_ID1); |
| 773 | id = reg << 8; | 813 | id = reg << 8; |
| @@ -777,7 +817,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
| 777 | if (id != 0x2000) { | 817 | if (id != 0x2000) { |
| 778 | dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id); | 818 | dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id); |
| 779 | ret = -ENODEV; | 819 | ret = -ENODEV; |
| 780 | goto out_regmap_exit; | 820 | goto err_supplies; |
| 781 | } | 821 | } |
| 782 | 822 | ||
| 783 | reg = wm2000_read(i2c, WM2000_REG_REVISON); | 823 | reg = wm2000_read(i2c, WM2000_REG_REVISON); |
| @@ -796,7 +836,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
| 796 | ret = request_firmware(&fw, filename, &i2c->dev); | 836 | ret = request_firmware(&fw, filename, &i2c->dev); |
| 797 | if (ret != 0) { | 837 | if (ret != 0) { |
| 798 | dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret); | 838 | dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret); |
| 799 | goto out_regmap_exit; | 839 | goto err_supplies; |
| 800 | } | 840 | } |
| 801 | 841 | ||
| 802 | /* Pre-cook the concatenation of the register address onto the image */ | 842 | /* Pre-cook the concatenation of the register address onto the image */ |
| @@ -807,7 +847,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
| 807 | if (wm2000->anc_download == NULL) { | 847 | if (wm2000->anc_download == NULL) { |
| 808 | dev_err(&i2c->dev, "Out of memory\n"); | 848 | dev_err(&i2c->dev, "Out of memory\n"); |
| 809 | ret = -ENOMEM; | 849 | ret = -ENOMEM; |
| 810 | goto out_regmap_exit; | 850 | goto err_supplies; |
| 811 | } | 851 | } |
| 812 | 852 | ||
| 813 | wm2000->anc_download[0] = 0x80; | 853 | wm2000->anc_download[0] = 0x80; |
| @@ -822,11 +862,10 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c, | |||
| 822 | wm2000_reset(wm2000); | 862 | wm2000_reset(wm2000); |
| 823 | 863 | ||
| 824 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0); | 864 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0); |
| 825 | if (!ret) | ||
| 826 | goto out; | ||
| 827 | 865 | ||
| 828 | out_regmap_exit: | 866 | err_supplies: |
| 829 | regmap_exit(wm2000->regmap); | 867 | regulator_bulk_disable(WM2000_NUM_SUPPLIES, wm2000->supplies); |
| 868 | |||
| 830 | out: | 869 | out: |
| 831 | release_firmware(fw); | 870 | release_firmware(fw); |
| 832 | return ret; | 871 | return ret; |
| @@ -834,10 +873,7 @@ out: | |||
| 834 | 873 | ||
| 835 | static __devexit int wm2000_i2c_remove(struct i2c_client *i2c) | 874 | static __devexit int wm2000_i2c_remove(struct i2c_client *i2c) |
| 836 | { | 875 | { |
| 837 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | ||
| 838 | |||
| 839 | snd_soc_unregister_codec(&i2c->dev); | 876 | snd_soc_unregister_codec(&i2c->dev); |
| 840 | regmap_exit(wm2000->regmap); | ||
| 841 | 877 | ||
| 842 | return 0; | 878 | return 0; |
| 843 | } | 879 | } |
| @@ -858,17 +894,7 @@ static struct i2c_driver wm2000_i2c_driver = { | |||
| 858 | .id_table = wm2000_i2c_id, | 894 | .id_table = wm2000_i2c_id, |
| 859 | }; | 895 | }; |
| 860 | 896 | ||
| 861 | static int __init wm2000_init(void) | 897 | module_i2c_driver(wm2000_i2c_driver); |
| 862 | { | ||
| 863 | return i2c_add_driver(&wm2000_i2c_driver); | ||
| 864 | } | ||
| 865 | module_init(wm2000_init); | ||
| 866 | |||
| 867 | static void __exit wm2000_exit(void) | ||
| 868 | { | ||
| 869 | i2c_del_driver(&wm2000_i2c_driver); | ||
| 870 | } | ||
| 871 | module_exit(wm2000_exit); | ||
| 872 | 898 | ||
| 873 | MODULE_DESCRIPTION("ASoC WM2000 driver"); | 899 | MODULE_DESCRIPTION("ASoC WM2000 driver"); |
| 874 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>"); | 900 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>"); |
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 32682c1b7cde..efa93dbb0191 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c | |||
| @@ -1117,8 +1117,8 @@ SND_SOC_DAPM_SUPPLY("MICBIAS1", WM2200_MIC_BIAS_CTRL_1, WM2200_MICB1_ENA_SHIFT, | |||
| 1117 | 0, NULL, 0), | 1117 | 0, NULL, 0), |
| 1118 | SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT, | 1118 | SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT, |
| 1119 | 0, NULL, 0), | 1119 | 0, NULL, 0), |
| 1120 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | 1120 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), |
| 1121 | SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20), | 1121 | SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20, 0), |
| 1122 | 1122 | ||
| 1123 | SND_SOC_DAPM_INPUT("IN1L"), | 1123 | SND_SOC_DAPM_INPUT("IN1L"), |
| 1124 | SND_SOC_DAPM_INPUT("IN1R"), | 1124 | SND_SOC_DAPM_INPUT("IN1R"), |
| @@ -2270,17 +2270,7 @@ static struct i2c_driver wm2200_i2c_driver = { | |||
| 2270 | .id_table = wm2200_i2c_id, | 2270 | .id_table = wm2200_i2c_id, |
| 2271 | }; | 2271 | }; |
| 2272 | 2272 | ||
| 2273 | static int __init wm2200_modinit(void) | 2273 | module_i2c_driver(wm2200_i2c_driver); |
| 2274 | { | ||
| 2275 | return i2c_add_driver(&wm2200_i2c_driver); | ||
| 2276 | } | ||
| 2277 | module_init(wm2200_modinit); | ||
| 2278 | |||
| 2279 | static void __exit wm2200_exit(void) | ||
| 2280 | { | ||
| 2281 | i2c_del_driver(&wm2200_i2c_driver); | ||
| 2282 | } | ||
| 2283 | module_exit(wm2200_exit); | ||
| 2284 | 2274 | ||
| 2285 | MODULE_DESCRIPTION("ASoC WM2200 driver"); | 2275 | MODULE_DESCRIPTION("ASoC WM2200 driver"); |
| 2286 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 2276 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index aa62c0e44cb6..7f567585832e 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c | |||
| @@ -848,9 +848,9 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0, | |||
| 848 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT, | 848 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT, |
| 849 | 0, NULL, 0), | 849 | 0, NULL, 0), |
| 850 | 850 | ||
| 851 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | 851 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), |
| 852 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), | 852 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), |
| 853 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), | 853 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), |
| 854 | 854 | ||
| 855 | SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0, | 855 | SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0, |
| 856 | NULL, 0), | 856 | NULL, 0), |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index e33d327396ad..1722b586bdba 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
| @@ -274,18 +274,43 @@ ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | |||
| 274 | ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | 274 | ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); |
| 275 | ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); | 275 | ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); |
| 276 | 276 | ||
| 277 | |||
| 278 | static const char *wm5102_aec_loopback_texts[] = { | ||
| 279 | "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT", | ||
| 280 | "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", | ||
| 281 | }; | ||
| 282 | |||
| 283 | static const unsigned int wm5102_aec_loopback_values[] = { | ||
| 284 | 0, 1, 2, 3, 4, 6, 7, 8, 9, | ||
| 285 | }; | ||
| 286 | |||
| 287 | static const struct soc_enum wm5102_aec_loopback = | ||
| 288 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, | ||
| 289 | ARIZONA_AEC_LOOPBACK_SRC_SHIFT, | ||
| 290 | ARIZONA_AEC_LOOPBACK_SRC_MASK, | ||
| 291 | ARRAY_SIZE(wm5102_aec_loopback_texts), | ||
| 292 | wm5102_aec_loopback_texts, | ||
| 293 | wm5102_aec_loopback_values); | ||
| 294 | |||
| 295 | static const struct snd_kcontrol_new wm5102_aec_loopback_mux = | ||
| 296 | SOC_DAPM_VALUE_ENUM("AEC Loopback", wm5102_aec_loopback); | ||
| 297 | |||
| 277 | static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { | 298 | static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { |
| 278 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | 299 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, |
| 279 | 0, NULL, 0), | 300 | 0, NULL, 0), |
| 280 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, | 301 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, |
| 281 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | 302 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), |
| 282 | 303 | SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, | |
| 283 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), | 304 | ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0), |
| 284 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), | 305 | SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, |
| 285 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | 306 | ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), |
| 286 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0), | 307 | |
| 287 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0), | 308 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), |
| 288 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0), | 309 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), |
| 310 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), | ||
| 311 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), | ||
| 312 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0), | ||
| 313 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), | ||
| 289 | 314 | ||
| 290 | SND_SOC_DAPM_SIGGEN("TONE"), | 315 | SND_SOC_DAPM_SIGGEN("TONE"), |
| 291 | SND_SOC_DAPM_SIGGEN("NOISE"), | 316 | SND_SOC_DAPM_SIGGEN("NOISE"), |
| @@ -421,6 +446,9 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, | |||
| 421 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, | 446 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, |
| 422 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), | 447 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), |
| 423 | 448 | ||
| 449 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, | ||
| 450 | ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux), | ||
| 451 | |||
| 424 | SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, | 452 | SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, |
| 425 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 453 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
| 426 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 454 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
| @@ -516,6 +544,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"), | |||
| 516 | { name, "Noise Generator", "Noise Generator" }, \ | 544 | { name, "Noise Generator", "Noise Generator" }, \ |
| 517 | { name, "Tone Generator 1", "Tone Generator 1" }, \ | 545 | { name, "Tone Generator 1", "Tone Generator 1" }, \ |
| 518 | { name, "Tone Generator 2", "Tone Generator 2" }, \ | 546 | { name, "Tone Generator 2", "Tone Generator 2" }, \ |
| 547 | { name, "AEC", "AEC Loopback" }, \ | ||
| 519 | { name, "IN1L", "IN1L PGA" }, \ | 548 | { name, "IN1L", "IN1L PGA" }, \ |
| 520 | { name, "IN1R", "IN1R PGA" }, \ | 549 | { name, "IN1R", "IN1R PGA" }, \ |
| 521 | { name, "IN2L", "IN2L PGA" }, \ | 550 | { name, "IN2L", "IN2L PGA" }, \ |
| @@ -681,21 +710,30 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | |||
| 681 | ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), | 710 | ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), |
| 682 | ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), | 711 | ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), |
| 683 | 712 | ||
| 713 | { "AEC Loopback", "HPOUT1L", "OUT1L" }, | ||
| 714 | { "AEC Loopback", "HPOUT1R", "OUT1R" }, | ||
| 684 | { "HPOUT1L", NULL, "OUT1L" }, | 715 | { "HPOUT1L", NULL, "OUT1L" }, |
| 685 | { "HPOUT1R", NULL, "OUT1R" }, | 716 | { "HPOUT1R", NULL, "OUT1R" }, |
| 686 | 717 | ||
| 718 | { "AEC Loopback", "HPOUT2L", "OUT2L" }, | ||
| 719 | { "AEC Loopback", "HPOUT2R", "OUT2R" }, | ||
| 687 | { "HPOUT2L", NULL, "OUT2L" }, | 720 | { "HPOUT2L", NULL, "OUT2L" }, |
| 688 | { "HPOUT2R", NULL, "OUT2R" }, | 721 | { "HPOUT2R", NULL, "OUT2R" }, |
| 689 | 722 | ||
| 723 | { "AEC Loopback", "EPOUT", "OUT3L" }, | ||
| 690 | { "EPOUTN", NULL, "OUT3L" }, | 724 | { "EPOUTN", NULL, "OUT3L" }, |
| 691 | { "EPOUTP", NULL, "OUT3L" }, | 725 | { "EPOUTP", NULL, "OUT3L" }, |
| 692 | 726 | ||
| 727 | { "AEC Loopback", "SPKOUTL", "OUT4L" }, | ||
| 693 | { "SPKOUTLN", NULL, "OUT4L" }, | 728 | { "SPKOUTLN", NULL, "OUT4L" }, |
| 694 | { "SPKOUTLP", NULL, "OUT4L" }, | 729 | { "SPKOUTLP", NULL, "OUT4L" }, |
| 695 | 730 | ||
| 731 | { "AEC Loopback", "SPKOUTR", "OUT4R" }, | ||
| 696 | { "SPKOUTRN", NULL, "OUT4R" }, | 732 | { "SPKOUTRN", NULL, "OUT4R" }, |
| 697 | { "SPKOUTRP", NULL, "OUT4R" }, | 733 | { "SPKOUTRP", NULL, "OUT4R" }, |
| 698 | 734 | ||
| 735 | { "AEC Loopback", "SPKDAT1L", "OUT5L" }, | ||
| 736 | { "AEC Loopback", "SPKDAT1R", "OUT5R" }, | ||
| 699 | { "SPKDAT1L", NULL, "OUT5L" }, | 737 | { "SPKDAT1L", NULL, "OUT5L" }, |
| 700 | { "SPKDAT1R", NULL, "OUT5R" }, | 738 | { "SPKDAT1R", NULL, "OUT5R" }, |
| 701 | }; | 739 | }; |
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 01ebbcc5c6a4..9211e4192f71 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
| @@ -153,6 +153,15 @@ SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), | |||
| 153 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), | 153 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), |
| 154 | SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), | 154 | SOC_ENUM("LHPF4 Mode", arizona_lhpf4_mode), |
| 155 | 155 | ||
| 156 | ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE), | ||
| 157 | ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE), | ||
| 158 | ARIZONA_MIXER_CONTROLS("DSP2L", ARIZONA_DSP2LMIX_INPUT_1_SOURCE), | ||
| 159 | ARIZONA_MIXER_CONTROLS("DSP2R", ARIZONA_DSP2RMIX_INPUT_1_SOURCE), | ||
| 160 | ARIZONA_MIXER_CONTROLS("DSP3L", ARIZONA_DSP3LMIX_INPUT_1_SOURCE), | ||
| 161 | ARIZONA_MIXER_CONTROLS("DSP3R", ARIZONA_DSP3RMIX_INPUT_1_SOURCE), | ||
| 162 | ARIZONA_MIXER_CONTROLS("DSP4L", ARIZONA_DSP4LMIX_INPUT_1_SOURCE), | ||
| 163 | ARIZONA_MIXER_CONTROLS("DSP5R", ARIZONA_DSP4RMIX_INPUT_1_SOURCE), | ||
| 164 | |||
| 156 | ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE), | 165 | ARIZONA_MIXER_CONTROLS("Mic", ARIZONA_MICMIX_INPUT_1_SOURCE), |
| 157 | ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE), | 166 | ARIZONA_MIXER_CONTROLS("Noise", ARIZONA_NOISEMIX_INPUT_1_SOURCE), |
| 158 | 167 | ||
| @@ -163,7 +172,8 @@ ARIZONA_MIXER_CONTROLS("HPOUT1L", ARIZONA_OUT1LMIX_INPUT_1_SOURCE), | |||
| 163 | ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE), | 172 | ARIZONA_MIXER_CONTROLS("HPOUT1R", ARIZONA_OUT1RMIX_INPUT_1_SOURCE), |
| 164 | ARIZONA_MIXER_CONTROLS("HPOUT2L", ARIZONA_OUT2LMIX_INPUT_1_SOURCE), | 173 | ARIZONA_MIXER_CONTROLS("HPOUT2L", ARIZONA_OUT2LMIX_INPUT_1_SOURCE), |
| 165 | ARIZONA_MIXER_CONTROLS("HPOUT2R", ARIZONA_OUT2RMIX_INPUT_1_SOURCE), | 174 | ARIZONA_MIXER_CONTROLS("HPOUT2R", ARIZONA_OUT2RMIX_INPUT_1_SOURCE), |
| 166 | ARIZONA_MIXER_CONTROLS("EPOUT", ARIZONA_OUT3LMIX_INPUT_1_SOURCE), | 175 | ARIZONA_MIXER_CONTROLS("HPOUT3L", ARIZONA_OUT3LMIX_INPUT_1_SOURCE), |
| 176 | ARIZONA_MIXER_CONTROLS("HPOUT3R", ARIZONA_OUT3RMIX_INPUT_1_SOURCE), | ||
| 167 | ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE), | 177 | ARIZONA_MIXER_CONTROLS("SPKOUTL", ARIZONA_OUT4LMIX_INPUT_1_SOURCE), |
| 168 | ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE), | 178 | ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE), |
| 169 | ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), | 179 | ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), |
| @@ -175,7 +185,7 @@ SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L, | |||
| 175 | ARIZONA_OUT1_OSR_SHIFT, 1, 0), | 185 | ARIZONA_OUT1_OSR_SHIFT, 1, 0), |
| 176 | SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L, | 186 | SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L, |
| 177 | ARIZONA_OUT2_OSR_SHIFT, 1, 0), | 187 | ARIZONA_OUT2_OSR_SHIFT, 1, 0), |
| 178 | SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L, | 188 | SOC_SINGLE("OUT3 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L, |
| 179 | ARIZONA_OUT3_OSR_SHIFT, 1, 0), | 189 | ARIZONA_OUT3_OSR_SHIFT, 1, 0), |
| 180 | SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L, | 190 | SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L, |
| 181 | ARIZONA_OUT4_OSR_SHIFT, 1, 0), | 191 | ARIZONA_OUT4_OSR_SHIFT, 1, 0), |
| @@ -188,8 +198,8 @@ SOC_DOUBLE_R("HPOUT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_1L, | |||
| 188 | ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), | 198 | ARIZONA_DAC_DIGITAL_VOLUME_1R, ARIZONA_OUT1L_MUTE_SHIFT, 1, 1), |
| 189 | SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L, | 199 | SOC_DOUBLE_R("OUT2 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_2L, |
| 190 | ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1), | 200 | ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_MUTE_SHIFT, 1, 1), |
| 191 | SOC_SINGLE("EPOUT Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L, | 201 | SOC_DOUBLE_R("OUT3 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_3L, |
| 192 | ARIZONA_OUT3L_MUTE_SHIFT, 1, 1), | 202 | ARIZONA_DAC_DIGITAL_VOLUME_3R, ARIZONA_OUT3L_MUTE_SHIFT, 1, 1), |
| 193 | SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L, | 203 | SOC_DOUBLE_R("Speaker Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_4L, |
| 194 | ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1), | 204 | ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_MUTE_SHIFT, 1, 1), |
| 195 | SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L, | 205 | SOC_DOUBLE_R("SPKDAT1 Digital Switch", ARIZONA_DAC_DIGITAL_VOLUME_5L, |
| @@ -203,8 +213,9 @@ SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_1L, | |||
| 203 | SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L, | 213 | SOC_DOUBLE_R_TLV("OUT2 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_2L, |
| 204 | ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT, | 214 | ARIZONA_DAC_DIGITAL_VOLUME_2R, ARIZONA_OUT2L_VOL_SHIFT, |
| 205 | 0xbf, 0, digital_tlv), | 215 | 0xbf, 0, digital_tlv), |
| 206 | SOC_SINGLE_TLV("EPOUT Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L, | 216 | SOC_DOUBLE_R_TLV("OUT3 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_3L, |
| 207 | ARIZONA_OUT3L_VOL_SHIFT, 0xbf, 0, digital_tlv), | 217 | ARIZONA_DAC_DIGITAL_VOLUME_3R, ARIZONA_OUT3L_VOL_SHIFT, |
| 218 | 0xbf, 0, digital_tlv), | ||
| 208 | SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L, | 219 | SOC_DOUBLE_R_TLV("Speaker Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_4L, |
| 209 | ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT, | 220 | ARIZONA_DAC_DIGITAL_VOLUME_4R, ARIZONA_OUT4L_VOL_SHIFT, |
| 210 | 0xbf, 0, digital_tlv), | 221 | 0xbf, 0, digital_tlv), |
| @@ -223,8 +234,9 @@ SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L, | |||
| 223 | ARIZONA_OUTPUT_PATH_CONFIG_2R, | 234 | ARIZONA_OUTPUT_PATH_CONFIG_2R, |
| 224 | ARIZONA_OUT2L_PGA_VOL_SHIFT, | 235 | ARIZONA_OUT2L_PGA_VOL_SHIFT, |
| 225 | 0x34, 0x40, 0, ana_tlv), | 236 | 0x34, 0x40, 0, ana_tlv), |
| 226 | SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L, | 237 | SOC_DOUBLE_R_RANGE_TLV("OUT3 Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L, |
| 227 | ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv), | 238 | ARIZONA_OUTPUT_PATH_CONFIG_3R, |
| 239 | ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv), | ||
| 228 | 240 | ||
| 229 | SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, | 241 | SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, |
| 230 | ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), | 242 | ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), |
| @@ -272,7 +284,8 @@ ARIZONA_MIXER_ENUMS(OUT1L, ARIZONA_OUT1LMIX_INPUT_1_SOURCE); | |||
| 272 | ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE); | 284 | ARIZONA_MIXER_ENUMS(OUT1R, ARIZONA_OUT1RMIX_INPUT_1_SOURCE); |
| 273 | ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE); | 285 | ARIZONA_MIXER_ENUMS(OUT2L, ARIZONA_OUT2LMIX_INPUT_1_SOURCE); |
| 274 | ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE); | 286 | ARIZONA_MIXER_ENUMS(OUT2R, ARIZONA_OUT2RMIX_INPUT_1_SOURCE); |
| 275 | ARIZONA_MIXER_ENUMS(OUT3, ARIZONA_OUT3LMIX_INPUT_1_SOURCE); | 287 | ARIZONA_MIXER_ENUMS(OUT3L, ARIZONA_OUT3LMIX_INPUT_1_SOURCE); |
| 288 | ARIZONA_MIXER_ENUMS(OUT3R, ARIZONA_OUT3RMIX_INPUT_1_SOURCE); | ||
| 276 | ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE); | 289 | ARIZONA_MIXER_ENUMS(SPKOUTL, ARIZONA_OUT4LMIX_INPUT_1_SOURCE); |
| 277 | ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE); | 290 | ARIZONA_MIXER_ENUMS(SPKOUTR, ARIZONA_OUT4RMIX_INPUT_1_SOURCE); |
| 278 | ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE); | 291 | ARIZONA_MIXER_ENUMS(SPKDAT1L, ARIZONA_OUT5LMIX_INPUT_1_SOURCE); |
| @@ -300,18 +313,42 @@ ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | |||
| 300 | ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | 313 | ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); |
| 301 | ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); | 314 | ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); |
| 302 | 315 | ||
| 316 | static const char *wm5110_aec_loopback_texts[] = { | ||
| 317 | "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R", | ||
| 318 | "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", "SPKDAT2L", "SPKDAT2R", | ||
| 319 | }; | ||
| 320 | |||
| 321 | static const unsigned int wm5110_aec_loopback_values[] = { | ||
| 322 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, | ||
| 323 | }; | ||
| 324 | |||
| 325 | static const struct soc_enum wm5110_aec_loopback = | ||
| 326 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, | ||
| 327 | ARIZONA_AEC_LOOPBACK_SRC_SHIFT, | ||
| 328 | ARIZONA_AEC_LOOPBACK_SRC_MASK, | ||
| 329 | ARRAY_SIZE(wm5110_aec_loopback_texts), | ||
| 330 | wm5110_aec_loopback_texts, | ||
| 331 | wm5110_aec_loopback_values); | ||
| 332 | |||
| 333 | static const struct snd_kcontrol_new wm5110_aec_loopback_mux = | ||
| 334 | SOC_DAPM_VALUE_ENUM("AEC Loopback", wm5110_aec_loopback); | ||
| 335 | |||
| 303 | static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = { | 336 | static const struct snd_soc_dapm_widget wm5110_dapm_widgets[] = { |
| 304 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | 337 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, |
| 305 | 0, NULL, 0), | 338 | 0, NULL, 0), |
| 306 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, | 339 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, |
| 307 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | 340 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), |
| 308 | 341 | SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, | |
| 309 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), | 342 | ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0), |
| 310 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), | 343 | SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, |
| 311 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | 344 | ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), |
| 312 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0), | 345 | |
| 313 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0), | 346 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0, 0), |
| 314 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0), | 347 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0, 0), |
| 348 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), | ||
| 349 | SND_SOC_DAPM_REGULATOR_SUPPLY("MICVDD", 0, SND_SOC_DAPM_REGULATOR_BYPASS), | ||
| 350 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDL", 0, 0), | ||
| 351 | SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), | ||
| 315 | 352 | ||
| 316 | SND_SOC_DAPM_SIGGEN("TONE"), | 353 | SND_SOC_DAPM_SIGGEN("TONE"), |
| 317 | SND_SOC_DAPM_SIGGEN("NOISE"), | 354 | SND_SOC_DAPM_SIGGEN("NOISE"), |
| @@ -405,6 +442,9 @@ SND_SOC_DAPM_PGA("ASRC2L", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2L_ENA_SHIFT, 0, | |||
| 405 | SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, | 442 | SND_SOC_DAPM_PGA("ASRC2R", ARIZONA_ASRC_ENABLE, ARIZONA_ASRC2R_ENA_SHIFT, 0, |
| 406 | NULL, 0), | 443 | NULL, 0), |
| 407 | 444 | ||
| 445 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, | ||
| 446 | ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5110_aec_loopback_mux), | ||
| 447 | |||
| 408 | SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, | 448 | SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 0, |
| 409 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0), | 449 | ARIZONA_AIF1_TX_ENABLES, ARIZONA_AIF1TX1_ENA_SHIFT, 0), |
| 410 | SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, | 450 | SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 0, |
| @@ -474,6 +514,9 @@ SND_SOC_DAPM_PGA_E("OUT2R", ARIZONA_OUTPUT_ENABLES_1, | |||
| 474 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, | 514 | SND_SOC_DAPM_PGA_E("OUT3L", ARIZONA_OUTPUT_ENABLES_1, |
| 475 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 515 | ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
| 476 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 516 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
| 517 | SND_SOC_DAPM_PGA_E("OUT3R", ARIZONA_OUTPUT_ENABLES_1, | ||
| 518 | ARIZONA_OUT3R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | ||
| 519 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | ||
| 477 | SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1, | 520 | SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1, |
| 478 | ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 521 | ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
| 479 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 522 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
| @@ -518,7 +561,8 @@ ARIZONA_MIXER_WIDGETS(OUT1L, "HPOUT1L"), | |||
| 518 | ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), | 561 | ARIZONA_MIXER_WIDGETS(OUT1R, "HPOUT1R"), |
| 519 | ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"), | 562 | ARIZONA_MIXER_WIDGETS(OUT2L, "HPOUT2L"), |
| 520 | ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"), | 563 | ARIZONA_MIXER_WIDGETS(OUT2R, "HPOUT2R"), |
| 521 | ARIZONA_MIXER_WIDGETS(OUT3, "EPOUT"), | 564 | ARIZONA_MIXER_WIDGETS(OUT3L, "HPOUT3L"), |
| 565 | ARIZONA_MIXER_WIDGETS(OUT3R, "HPOUT3R"), | ||
| 522 | ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), | 566 | ARIZONA_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"), |
| 523 | ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"), | 567 | ARIZONA_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"), |
| 524 | ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), | 568 | ARIZONA_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"), |
| @@ -550,8 +594,8 @@ SND_SOC_DAPM_OUTPUT("HPOUT1L"), | |||
| 550 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), | 594 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), |
| 551 | SND_SOC_DAPM_OUTPUT("HPOUT2L"), | 595 | SND_SOC_DAPM_OUTPUT("HPOUT2L"), |
| 552 | SND_SOC_DAPM_OUTPUT("HPOUT2R"), | 596 | SND_SOC_DAPM_OUTPUT("HPOUT2R"), |
| 553 | SND_SOC_DAPM_OUTPUT("EPOUTN"), | 597 | SND_SOC_DAPM_OUTPUT("HPOUT3L"), |
| 554 | SND_SOC_DAPM_OUTPUT("EPOUTP"), | 598 | SND_SOC_DAPM_OUTPUT("HPOUT3R"), |
| 555 | SND_SOC_DAPM_OUTPUT("SPKOUTLN"), | 599 | SND_SOC_DAPM_OUTPUT("SPKOUTLN"), |
| 556 | SND_SOC_DAPM_OUTPUT("SPKOUTLP"), | 600 | SND_SOC_DAPM_OUTPUT("SPKOUTLP"), |
| 557 | SND_SOC_DAPM_OUTPUT("SPKOUTRN"), | 601 | SND_SOC_DAPM_OUTPUT("SPKOUTRN"), |
| @@ -566,6 +610,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT2R"), | |||
| 566 | { name, "Noise Generator", "Noise Generator" }, \ | 610 | { name, "Noise Generator", "Noise Generator" }, \ |
| 567 | { name, "Tone Generator 1", "Tone Generator 1" }, \ | 611 | { name, "Tone Generator 1", "Tone Generator 1" }, \ |
| 568 | { name, "Tone Generator 2", "Tone Generator 2" }, \ | 612 | { name, "Tone Generator 2", "Tone Generator 2" }, \ |
| 613 | { name, "AEC", "AEC Loopback" }, \ | ||
| 569 | { name, "IN1L", "IN1L PGA" }, \ | 614 | { name, "IN1L", "IN1L PGA" }, \ |
| 570 | { name, "IN1R", "IN1R PGA" }, \ | 615 | { name, "IN1R", "IN1R PGA" }, \ |
| 571 | { name, "IN2L", "IN2L PGA" }, \ | 616 | { name, "IN2L", "IN2L PGA" }, \ |
| @@ -616,6 +661,7 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
| 616 | { "OUT2L", NULL, "CPVDD" }, | 661 | { "OUT2L", NULL, "CPVDD" }, |
| 617 | { "OUT2R", NULL, "CPVDD" }, | 662 | { "OUT2R", NULL, "CPVDD" }, |
| 618 | { "OUT3L", NULL, "CPVDD" }, | 663 | { "OUT3L", NULL, "CPVDD" }, |
| 664 | { "OUT3R", NULL, "CPVDD" }, | ||
| 619 | 665 | ||
| 620 | { "OUT4L", NULL, "SPKVDDL" }, | 666 | { "OUT4L", NULL, "SPKVDDL" }, |
| 621 | { "OUT4R", NULL, "SPKVDDR" }, | 667 | { "OUT4R", NULL, "SPKVDDR" }, |
| @@ -697,7 +743,8 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
| 697 | ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), | 743 | ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), |
| 698 | ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), | 744 | ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), |
| 699 | ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"), | 745 | ARIZONA_MIXER_ROUTES("OUT2R", "HPOUT2R"), |
| 700 | ARIZONA_MIXER_ROUTES("OUT3L", "EPOUT"), | 746 | ARIZONA_MIXER_ROUTES("OUT3L", "HPOUT3L"), |
| 747 | ARIZONA_MIXER_ROUTES("OUT3R", "HPOUT3R"), | ||
| 701 | 748 | ||
| 702 | ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"), | 749 | ARIZONA_MIXER_ROUTES("OUT4L", "SPKOUTL"), |
| 703 | ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"), | 750 | ARIZONA_MIXER_ROUTES("OUT4R", "SPKOUTR"), |
| @@ -750,8 +797,8 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
| 750 | { "HPOUT2L", NULL, "OUT2L" }, | 797 | { "HPOUT2L", NULL, "OUT2L" }, |
| 751 | { "HPOUT2R", NULL, "OUT2R" }, | 798 | { "HPOUT2R", NULL, "OUT2R" }, |
| 752 | 799 | ||
| 753 | { "EPOUTN", NULL, "OUT3L" }, | 800 | { "HPOUT3L", NULL, "OUT3L" }, |
| 754 | { "EPOUTP", NULL, "OUT3L" }, | 801 | { "HPOUT3R", NULL, "OUT3L" }, |
| 755 | 802 | ||
| 756 | { "SPKOUTLN", NULL, "OUT4L" }, | 803 | { "SPKOUTLN", NULL, "OUT4L" }, |
| 757 | { "SPKOUTLP", NULL, "OUT4L" }, | 804 | { "SPKOUTLP", NULL, "OUT4L" }, |
| @@ -869,6 +916,8 @@ static unsigned int wm5110_digital_vu[] = { | |||
| 869 | ARIZONA_ADC_DIGITAL_VOLUME_2R, | 916 | ARIZONA_ADC_DIGITAL_VOLUME_2R, |
| 870 | ARIZONA_ADC_DIGITAL_VOLUME_3L, | 917 | ARIZONA_ADC_DIGITAL_VOLUME_3L, |
| 871 | ARIZONA_ADC_DIGITAL_VOLUME_3R, | 918 | ARIZONA_ADC_DIGITAL_VOLUME_3R, |
| 919 | ARIZONA_ADC_DIGITAL_VOLUME_4L, | ||
| 920 | ARIZONA_ADC_DIGITAL_VOLUME_4R, | ||
| 872 | 921 | ||
| 873 | ARIZONA_DAC_DIGITAL_VOLUME_1L, | 922 | ARIZONA_DAC_DIGITAL_VOLUME_1L, |
| 874 | ARIZONA_DAC_DIGITAL_VOLUME_1R, | 923 | ARIZONA_DAC_DIGITAL_VOLUME_1R, |
| @@ -880,6 +929,8 @@ static unsigned int wm5110_digital_vu[] = { | |||
| 880 | ARIZONA_DAC_DIGITAL_VOLUME_4R, | 929 | ARIZONA_DAC_DIGITAL_VOLUME_4R, |
| 881 | ARIZONA_DAC_DIGITAL_VOLUME_5L, | 930 | ARIZONA_DAC_DIGITAL_VOLUME_5L, |
| 882 | ARIZONA_DAC_DIGITAL_VOLUME_5R, | 931 | ARIZONA_DAC_DIGITAL_VOLUME_5R, |
| 932 | ARIZONA_DAC_DIGITAL_VOLUME_6L, | ||
| 933 | ARIZONA_DAC_DIGITAL_VOLUME_6R, | ||
| 883 | }; | 934 | }; |
| 884 | 935 | ||
| 885 | static struct snd_soc_codec_driver soc_codec_dev_wm5110 = { | 936 | static struct snd_soc_codec_driver soc_codec_dev_wm5110 = { |
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 56a049555e2c..c12a54e72e89 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
| 21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 22 | #include <linux/of_device.h> | 22 | #include <linux/of_device.h> |
| 23 | #include <linux/regmap.h> | ||
| 23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
| 24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
| 25 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
| @@ -33,24 +34,75 @@ | |||
| 33 | * We can't read the WM8510 register space when we are | 34 | * We can't read the WM8510 register space when we are |
| 34 | * using 2 wire for device control, so we cache them instead. | 35 | * using 2 wire for device control, so we cache them instead. |
| 35 | */ | 36 | */ |
| 36 | static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { | 37 | static const struct reg_default wm8510_reg_defaults[] = { |
| 37 | 0x0000, 0x0000, 0x0000, 0x0000, | 38 | { 1, 0x0000 }, |
| 38 | 0x0050, 0x0000, 0x0140, 0x0000, | 39 | { 2, 0x0000 }, |
| 39 | 0x0000, 0x0000, 0x0000, 0x00ff, | 40 | { 3, 0x0000 }, |
| 40 | 0x0000, 0x0000, 0x0100, 0x00ff, | 41 | { 4, 0x0050 }, |
| 41 | 0x0000, 0x0000, 0x012c, 0x002c, | 42 | { 5, 0x0000 }, |
| 42 | 0x002c, 0x002c, 0x002c, 0x0000, | 43 | { 6, 0x0140 }, |
| 43 | 0x0032, 0x0000, 0x0000, 0x0000, | 44 | { 7, 0x0000 }, |
| 44 | 0x0000, 0x0000, 0x0000, 0x0000, | 45 | { 8, 0x0000 }, |
| 45 | 0x0038, 0x000b, 0x0032, 0x0000, | 46 | { 9, 0x0000 }, |
| 46 | 0x0008, 0x000c, 0x0093, 0x00e9, | 47 | { 10, 0x0000 }, |
| 47 | 0x0000, 0x0000, 0x0000, 0x0000, | 48 | { 11, 0x00ff }, |
| 48 | 0x0003, 0x0010, 0x0000, 0x0000, | 49 | { 12, 0x0000 }, |
| 49 | 0x0000, 0x0002, 0x0001, 0x0000, | 50 | { 13, 0x0000 }, |
| 50 | 0x0000, 0x0000, 0x0039, 0x0000, | 51 | { 14, 0x0100 }, |
| 51 | 0x0001, | 52 | { 15, 0x00ff }, |
| 53 | { 16, 0x0000 }, | ||
| 54 | { 17, 0x0000 }, | ||
| 55 | { 18, 0x012c }, | ||
| 56 | { 19, 0x002c }, | ||
| 57 | { 20, 0x002c }, | ||
| 58 | { 21, 0x002c }, | ||
| 59 | { 22, 0x002c }, | ||
| 60 | { 23, 0x0000 }, | ||
| 61 | { 24, 0x0032 }, | ||
| 62 | { 25, 0x0000 }, | ||
| 63 | { 26, 0x0000 }, | ||
| 64 | { 27, 0x0000 }, | ||
| 65 | { 28, 0x0000 }, | ||
| 66 | { 29, 0x0000 }, | ||
| 67 | { 30, 0x0000 }, | ||
| 68 | { 31, 0x0000 }, | ||
| 69 | { 32, 0x0038 }, | ||
| 70 | { 33, 0x000b }, | ||
| 71 | { 34, 0x0032 }, | ||
| 72 | { 35, 0x0000 }, | ||
| 73 | { 36, 0x0008 }, | ||
| 74 | { 37, 0x000c }, | ||
| 75 | { 38, 0x0093 }, | ||
| 76 | { 39, 0x00e9 }, | ||
| 77 | { 40, 0x0000 }, | ||
| 78 | { 41, 0x0000 }, | ||
| 79 | { 42, 0x0000 }, | ||
| 80 | { 43, 0x0000 }, | ||
| 81 | { 44, 0x0003 }, | ||
| 82 | { 45, 0x0010 }, | ||
| 83 | { 46, 0x0000 }, | ||
| 84 | { 47, 0x0000 }, | ||
| 85 | { 48, 0x0000 }, | ||
| 86 | { 49, 0x0002 }, | ||
| 87 | { 50, 0x0001 }, | ||
| 88 | { 51, 0x0000 }, | ||
| 89 | { 52, 0x0000 }, | ||
| 90 | { 53, 0x0000 }, | ||
| 91 | { 54, 0x0039 }, | ||
| 92 | { 55, 0x0000 }, | ||
| 93 | { 56, 0x0001 }, | ||
| 52 | }; | 94 | }; |
| 53 | 95 | ||
| 96 | static bool wm8510_volatile(struct device *dev, unsigned int reg) | ||
| 97 | { | ||
| 98 | switch (reg) { | ||
| 99 | case WM8510_RESET: | ||
| 100 | return true; | ||
| 101 | default: | ||
| 102 | return false; | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 54 | #define WM8510_POWER1_BIASEN 0x08 | 106 | #define WM8510_POWER1_BIASEN 0x08 |
| 55 | #define WM8510_POWER1_BUFIOEN 0x10 | 107 | #define WM8510_POWER1_BUFIOEN 0x10 |
| 56 | 108 | ||
| @@ -58,7 +110,7 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { | |||
| 58 | 110 | ||
| 59 | /* codec private data */ | 111 | /* codec private data */ |
| 60 | struct wm8510_priv { | 112 | struct wm8510_priv { |
| 61 | enum snd_soc_control_type control_type; | 113 | struct regmap *regmap; |
| 62 | }; | 114 | }; |
| 63 | 115 | ||
| 64 | static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; | 116 | static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; |
| @@ -454,6 +506,7 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute) | |||
| 454 | static int wm8510_set_bias_level(struct snd_soc_codec *codec, | 506 | static int wm8510_set_bias_level(struct snd_soc_codec *codec, |
| 455 | enum snd_soc_bias_level level) | 507 | enum snd_soc_bias_level level) |
| 456 | { | 508 | { |
| 509 | struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); | ||
| 457 | u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3; | 510 | u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3; |
| 458 | 511 | ||
| 459 | switch (level) { | 512 | switch (level) { |
| @@ -467,7 +520,7 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec, | |||
| 467 | power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN; | 520 | power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN; |
| 468 | 521 | ||
| 469 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 522 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
| 470 | snd_soc_cache_sync(codec); | 523 | regcache_sync(wm8510->regmap); |
| 471 | 524 | ||
| 472 | /* Initial cap charge at VMID 5k */ | 525 | /* Initial cap charge at VMID 5k */ |
| 473 | snd_soc_write(codec, WM8510_POWER1, power1 | 0x3); | 526 | snd_soc_write(codec, WM8510_POWER1, power1 | 0x3); |
| @@ -536,10 +589,9 @@ static int wm8510_resume(struct snd_soc_codec *codec) | |||
| 536 | 589 | ||
| 537 | static int wm8510_probe(struct snd_soc_codec *codec) | 590 | static int wm8510_probe(struct snd_soc_codec *codec) |
| 538 | { | 591 | { |
| 539 | struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); | ||
| 540 | int ret; | 592 | int ret; |
| 541 | 593 | ||
| 542 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8510->control_type); | 594 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
| 543 | if (ret < 0) { | 595 | if (ret < 0) { |
| 544 | printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); | 596 | printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n", ret); |
| 545 | return ret; | 597 | return ret; |
| @@ -569,9 +621,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { | |||
| 569 | .suspend = wm8510_suspend, | 621 | .suspend = wm8510_suspend, |
| 570 | .resume = wm8510_resume, | 622 | .resume = wm8510_resume, |
| 571 | .set_bias_level = wm8510_set_bias_level, | 623 | .set_bias_level = wm8510_set_bias_level, |
| 572 | .reg_cache_size = ARRAY_SIZE(wm8510_reg), | ||
| 573 | .reg_word_size = sizeof(u16), | ||
| 574 | .reg_cache_default =wm8510_reg, | ||
| 575 | 624 | ||
| 576 | .controls = wm8510_snd_controls, | 625 | .controls = wm8510_snd_controls, |
| 577 | .num_controls = ARRAY_SIZE(wm8510_snd_controls), | 626 | .num_controls = ARRAY_SIZE(wm8510_snd_controls), |
| @@ -586,23 +635,38 @@ static const struct of_device_id wm8510_of_match[] = { | |||
| 586 | { }, | 635 | { }, |
| 587 | }; | 636 | }; |
| 588 | 637 | ||
| 638 | static const struct regmap_config wm8510_regmap = { | ||
| 639 | .reg_bits = 7, | ||
| 640 | .val_bits = 9, | ||
| 641 | .max_register = WM8510_MONOMIX, | ||
| 642 | |||
| 643 | .reg_defaults = wm8510_reg_defaults, | ||
| 644 | .num_reg_defaults = ARRAY_SIZE(wm8510_reg_defaults), | ||
| 645 | .cache_type = REGCACHE_RBTREE, | ||
| 646 | |||
| 647 | .volatile_reg = wm8510_volatile, | ||
| 648 | }; | ||
| 649 | |||
| 589 | #if defined(CONFIG_SPI_MASTER) | 650 | #if defined(CONFIG_SPI_MASTER) |
| 590 | static int __devinit wm8510_spi_probe(struct spi_device *spi) | 651 | static int __devinit wm8510_spi_probe(struct spi_device *spi) |
| 591 | { | 652 | { |
| 592 | struct wm8510_priv *wm8510; | 653 | struct wm8510_priv *wm8510; |
| 593 | int ret; | 654 | int ret; |
| 594 | 655 | ||
| 595 | wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); | 656 | wm8510 = devm_kzalloc(&spi->dev, sizeof(struct wm8510_priv), |
| 657 | GFP_KERNEL); | ||
| 596 | if (wm8510 == NULL) | 658 | if (wm8510 == NULL) |
| 597 | return -ENOMEM; | 659 | return -ENOMEM; |
| 598 | 660 | ||
| 599 | wm8510->control_type = SND_SOC_SPI; | 661 | wm8510->regmap = devm_regmap_init_spi(spi, &wm8510_regmap); |
| 662 | if (IS_ERR(wm8510->regmap)) | ||
| 663 | return PTR_ERR(wm8510->regmap); | ||
| 664 | |||
| 600 | spi_set_drvdata(spi, wm8510); | 665 | spi_set_drvdata(spi, wm8510); |
| 601 | 666 | ||
| 602 | ret = snd_soc_register_codec(&spi->dev, | 667 | ret = snd_soc_register_codec(&spi->dev, |
| 603 | &soc_codec_dev_wm8510, &wm8510_dai, 1); | 668 | &soc_codec_dev_wm8510, &wm8510_dai, 1); |
| 604 | if (ret < 0) | 669 | |
| 605 | kfree(wm8510); | ||
| 606 | return ret; | 670 | return ret; |
| 607 | } | 671 | } |
| 608 | 672 | ||
| @@ -630,17 +694,20 @@ static __devinit int wm8510_i2c_probe(struct i2c_client *i2c, | |||
| 630 | struct wm8510_priv *wm8510; | 694 | struct wm8510_priv *wm8510; |
| 631 | int ret; | 695 | int ret; |
| 632 | 696 | ||
| 633 | wm8510 = kzalloc(sizeof(struct wm8510_priv), GFP_KERNEL); | 697 | wm8510 = devm_kzalloc(&i2c->dev, sizeof(struct wm8510_priv), |
| 698 | GFP_KERNEL); | ||
| 634 | if (wm8510 == NULL) | 699 | if (wm8510 == NULL) |
| 635 | return -ENOMEM; | 700 | return -ENOMEM; |
| 636 | 701 | ||
| 702 | wm8510->regmap = devm_regmap_init_i2c(i2c, &wm8510_regmap); | ||
| 703 | if (IS_ERR(wm8510->regmap)) | ||
| 704 | return PTR_ERR(wm8510->regmap); | ||
| 705 | |||
| 637 | i2c_set_clientdata(i2c, wm8510); | 706 | i2c_set_clientdata(i2c, wm8510); |
| 638 | wm8510->control_type = SND_SOC_I2C; | ||
| 639 | 707 | ||
| 640 | ret = snd_soc_register_codec(&i2c->dev, | 708 | ret = snd_soc_register_codec(&i2c->dev, |
| 641 | &soc_codec_dev_wm8510, &wm8510_dai, 1); | 709 | &soc_codec_dev_wm8510, &wm8510_dai, 1); |
| 642 | if (ret < 0) | 710 | |
| 643 | kfree(wm8510); | ||
| 644 | return ret; | 711 | return ret; |
| 645 | } | 712 | } |
| 646 | 713 | ||
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 1c3ffb290cdc..8d5c27673501 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
| 18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
| 19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
| 20 | #include <linux/regmap.h> | ||
| 20 | #include <linux/regulator/consumer.h> | 21 | #include <linux/regulator/consumer.h> |
| 21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 22 | #include <linux/of_device.h> | 23 | #include <linux/of_device.h> |
| @@ -39,41 +40,34 @@ static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { | |||
| 39 | 40 | ||
| 40 | /* codec private data */ | 41 | /* codec private data */ |
| 41 | struct wm8523_priv { | 42 | struct wm8523_priv { |
| 42 | enum snd_soc_control_type control_type; | 43 | struct regmap *regmap; |
| 43 | struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; | 44 | struct regulator_bulk_data supplies[WM8523_NUM_SUPPLIES]; |
| 44 | unsigned int sysclk; | 45 | unsigned int sysclk; |
| 45 | unsigned int rate_constraint_list[WM8523_NUM_RATES]; | 46 | unsigned int rate_constraint_list[WM8523_NUM_RATES]; |
| 46 | struct snd_pcm_hw_constraint_list rate_constraint; | 47 | struct snd_pcm_hw_constraint_list rate_constraint; |
| 47 | }; | 48 | }; |
| 48 | 49 | ||
| 49 | static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = { | 50 | static const struct reg_default wm8523_reg_defaults[] = { |
| 50 | 0x8523, /* R0 - DEVICE_ID */ | 51 | { 2, 0x0000 }, /* R2 - PSCTRL1 */ |
| 51 | 0x0001, /* R1 - REVISION */ | 52 | { 3, 0x1812 }, /* R3 - AIF_CTRL1 */ |
| 52 | 0x0000, /* R2 - PSCTRL1 */ | 53 | { 4, 0x0000 }, /* R4 - AIF_CTRL2 */ |
| 53 | 0x1812, /* R3 - AIF_CTRL1 */ | 54 | { 5, 0x0001 }, /* R5 - DAC_CTRL3 */ |
| 54 | 0x0000, /* R4 - AIF_CTRL2 */ | 55 | { 6, 0x0190 }, /* R6 - DAC_GAINL */ |
| 55 | 0x0001, /* R5 - DAC_CTRL3 */ | 56 | { 7, 0x0190 }, /* R7 - DAC_GAINR */ |
| 56 | 0x0190, /* R6 - DAC_GAINL */ | 57 | { 8, 0x0000 }, /* R8 - ZERO_DETECT */ |
| 57 | 0x0190, /* R7 - DAC_GAINR */ | ||
| 58 | 0x0000, /* R8 - ZERO_DETECT */ | ||
| 59 | }; | 58 | }; |
| 60 | 59 | ||
| 61 | static int wm8523_volatile_register(struct snd_soc_codec *codec, unsigned int reg) | 60 | static bool wm8523_volatile_register(struct device *dev, unsigned int reg) |
| 62 | { | 61 | { |
| 63 | switch (reg) { | 62 | switch (reg) { |
| 64 | case WM8523_DEVICE_ID: | 63 | case WM8523_DEVICE_ID: |
| 65 | case WM8523_REVISION: | 64 | case WM8523_REVISION: |
| 66 | return 1; | 65 | return true; |
| 67 | default: | 66 | default: |
| 68 | return 0; | 67 | return false; |
| 69 | } | 68 | } |
| 70 | } | 69 | } |
| 71 | 70 | ||
| 72 | static int wm8523_reset(struct snd_soc_codec *codec) | ||
| 73 | { | ||
| 74 | return snd_soc_write(codec, WM8523_DEVICE_ID, 0); | ||
| 75 | } | ||
| 76 | |||
| 77 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0); | 71 | static const DECLARE_TLV_DB_SCALE(dac_tlv, -10000, 25, 0); |
| 78 | 72 | ||
| 79 | static const char *wm8523_zd_count_text[] = { | 73 | static const char *wm8523_zd_count_text[] = { |
| @@ -301,8 +295,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, | |||
| 301 | enum snd_soc_bias_level level) | 295 | enum snd_soc_bias_level level) |
| 302 | { | 296 | { |
| 303 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); | 297 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); |
| 304 | u16 *reg_cache = codec->reg_cache; | 298 | int ret; |
| 305 | int ret, i; | ||
| 306 | 299 | ||
| 307 | switch (level) { | 300 | switch (level) { |
| 308 | case SND_SOC_BIAS_ON: | 301 | case SND_SOC_BIAS_ON: |
| @@ -325,16 +318,13 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec, | |||
| 325 | return ret; | 318 | return ret; |
| 326 | } | 319 | } |
| 327 | 320 | ||
| 321 | /* Sync back default/cached values */ | ||
| 322 | regcache_sync(wm8523->regmap); | ||
| 323 | |||
| 328 | /* Initial power up */ | 324 | /* Initial power up */ |
| 329 | snd_soc_update_bits(codec, WM8523_PSCTRL1, | 325 | snd_soc_update_bits(codec, WM8523_PSCTRL1, |
| 330 | WM8523_SYS_ENA_MASK, 1); | 326 | WM8523_SYS_ENA_MASK, 1); |
| 331 | 327 | ||
| 332 | /* Sync back default/cached values */ | ||
| 333 | for (i = WM8523_AIF_CTRL1; | ||
| 334 | i < WM8523_MAX_REGISTER; i++) | ||
| 335 | snd_soc_write(codec, i, reg_cache[i]); | ||
| 336 | |||
| 337 | |||
| 338 | msleep(100); | 328 | msleep(100); |
| 339 | } | 329 | } |
| 340 | 330 | ||
| @@ -402,60 +392,18 @@ static int wm8523_resume(struct snd_soc_codec *codec) | |||
| 402 | static int wm8523_probe(struct snd_soc_codec *codec) | 392 | static int wm8523_probe(struct snd_soc_codec *codec) |
| 403 | { | 393 | { |
| 404 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); | 394 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); |
| 405 | int ret, i; | 395 | int ret; |
| 406 | 396 | ||
| 407 | wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; | 397 | wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; |
| 408 | wm8523->rate_constraint.count = | 398 | wm8523->rate_constraint.count = |
| 409 | ARRAY_SIZE(wm8523->rate_constraint_list); | 399 | ARRAY_SIZE(wm8523->rate_constraint_list); |
| 410 | 400 | ||
| 411 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type); | 401 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); |
| 412 | if (ret != 0) { | 402 | if (ret != 0) { |
| 413 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 403 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
| 414 | return ret; | 404 | return ret; |
| 415 | } | 405 | } |
| 416 | 406 | ||
| 417 | for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) | ||
| 418 | wm8523->supplies[i].supply = wm8523_supply_names[i]; | ||
| 419 | |||
| 420 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8523->supplies), | ||
| 421 | wm8523->supplies); | ||
| 422 | if (ret != 0) { | ||
| 423 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
| 424 | return ret; | ||
| 425 | } | ||
| 426 | |||
| 427 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), | ||
| 428 | wm8523->supplies); | ||
| 429 | if (ret != 0) { | ||
| 430 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
| 431 | goto err_get; | ||
| 432 | } | ||
| 433 | |||
| 434 | ret = snd_soc_read(codec, WM8523_DEVICE_ID); | ||
| 435 | if (ret < 0) { | ||
| 436 | dev_err(codec->dev, "Failed to read ID register\n"); | ||
| 437 | goto err_enable; | ||
| 438 | } | ||
| 439 | if (ret != wm8523_reg[WM8523_DEVICE_ID]) { | ||
| 440 | dev_err(codec->dev, "Device is not a WM8523, ID is %x\n", ret); | ||
| 441 | ret = -EINVAL; | ||
| 442 | goto err_enable; | ||
| 443 | } | ||
| 444 | |||
| 445 | ret = snd_soc_read(codec, WM8523_REVISION); | ||
| 446 | if (ret < 0) { | ||
| 447 | dev_err(codec->dev, "Failed to read revision register\n"); | ||
| 448 | goto err_enable; | ||
| 449 | } | ||
| 450 | dev_info(codec->dev, "revision %c\n", | ||
| 451 | (ret & WM8523_CHIP_REV_MASK) + 'A'); | ||
| 452 | |||
| 453 | ret = wm8523_reset(codec); | ||
| 454 | if (ret < 0) { | ||
| 455 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
| 456 | goto err_enable; | ||
| 457 | } | ||
| 458 | |||
| 459 | /* Change some default settings - latch VU and enable ZC */ | 407 | /* Change some default settings - latch VU and enable ZC */ |
| 460 | snd_soc_update_bits(codec, WM8523_DAC_GAINR, | 408 | snd_soc_update_bits(codec, WM8523_DAC_GAINR, |
| 461 | WM8523_DACR_VU, WM8523_DACR_VU); | 409 | WM8523_DACR_VU, WM8523_DACR_VU); |
| @@ -463,25 +411,12 @@ static int wm8523_probe(struct snd_soc_codec *codec) | |||
| 463 | 411 | ||
| 464 | wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 412 | wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
| 465 | 413 | ||
| 466 | /* Bias level configuration will have done an extra enable */ | ||
| 467 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | ||
| 468 | |||
| 469 | return 0; | 414 | return 0; |
| 470 | |||
| 471 | err_enable: | ||
| 472 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | ||
| 473 | err_get: | ||
| 474 | regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | ||
| 475 | |||
| 476 | return ret; | ||
| 477 | } | 415 | } |
| 478 | 416 | ||
| 479 | static int wm8523_remove(struct snd_soc_codec *codec) | 417 | static int wm8523_remove(struct snd_soc_codec *codec) |
| 480 | { | 418 | { |
| 481 | struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); | ||
| 482 | |||
| 483 | wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); | 419 | wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF); |
| 484 | regulator_bulk_free(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | ||
| 485 | return 0; | 420 | return 0; |
| 486 | } | 421 | } |
| 487 | 422 | ||
| @@ -491,10 +426,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { | |||
| 491 | .suspend = wm8523_suspend, | 426 | .suspend = wm8523_suspend, |
| 492 | .resume = wm8523_resume, | 427 | .resume = wm8523_resume, |
| 493 | .set_bias_level = wm8523_set_bias_level, | 428 | .set_bias_level = wm8523_set_bias_level, |
| 494 | .reg_cache_size = WM8523_REGISTER_COUNT, | ||
| 495 | .reg_word_size = sizeof(u16), | ||
| 496 | .reg_cache_default = wm8523_reg, | ||
| 497 | .volatile_register = wm8523_volatile_register, | ||
| 498 | 429 | ||
| 499 | .controls = wm8523_controls, | 430 | .controls = wm8523_controls, |
| 500 | .num_controls = ARRAY_SIZE(wm8523_controls), | 431 | .num_controls = ARRAY_SIZE(wm8523_controls), |
| @@ -509,32 +440,97 @@ static const struct of_device_id wm8523_of_match[] = { | |||
| 509 | { }, | 440 | { }, |
| 510 | }; | 441 | }; |
| 511 | 442 | ||
| 443 | static const struct regmap_config wm8523_regmap = { | ||
| 444 | .reg_bits = 8, | ||
| 445 | .val_bits = 16, | ||
| 446 | .max_register = WM8523_ZERO_DETECT, | ||
| 447 | |||
| 448 | .reg_defaults = wm8523_reg_defaults, | ||
| 449 | .num_reg_defaults = ARRAY_SIZE(wm8523_reg_defaults), | ||
| 450 | .cache_type = REGCACHE_RBTREE, | ||
| 451 | |||
| 452 | .volatile_reg = wm8523_volatile_register, | ||
| 453 | }; | ||
| 454 | |||
| 512 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 455 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
| 513 | static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, | 456 | static __devinit int wm8523_i2c_probe(struct i2c_client *i2c, |
| 514 | const struct i2c_device_id *id) | 457 | const struct i2c_device_id *id) |
| 515 | { | 458 | { |
| 516 | struct wm8523_priv *wm8523; | 459 | struct wm8523_priv *wm8523; |
| 517 | int ret; | 460 | unsigned int val; |
| 461 | int ret, i; | ||
| 518 | 462 | ||
| 519 | wm8523 = kzalloc(sizeof(struct wm8523_priv), GFP_KERNEL); | 463 | wm8523 = devm_kzalloc(&i2c->dev, sizeof(struct wm8523_priv), |
| 464 | GFP_KERNEL); | ||
| 520 | if (wm8523 == NULL) | 465 | if (wm8523 == NULL) |
| 521 | return -ENOMEM; | 466 | return -ENOMEM; |
| 522 | 467 | ||
| 468 | wm8523->regmap = devm_regmap_init_i2c(i2c, &wm8523_regmap); | ||
| 469 | if (IS_ERR(wm8523->regmap)) { | ||
| 470 | ret = PTR_ERR(wm8523->regmap); | ||
| 471 | dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); | ||
| 472 | return ret; | ||
| 473 | } | ||
| 474 | |||
| 475 | for (i = 0; i < ARRAY_SIZE(wm8523->supplies); i++) | ||
| 476 | wm8523->supplies[i].supply = wm8523_supply_names[i]; | ||
| 477 | |||
| 478 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8523->supplies), | ||
| 479 | wm8523->supplies); | ||
| 480 | if (ret != 0) { | ||
| 481 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
| 482 | return ret; | ||
| 483 | } | ||
| 484 | |||
| 485 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies), | ||
| 486 | wm8523->supplies); | ||
| 487 | if (ret != 0) { | ||
| 488 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | ||
| 489 | return ret; | ||
| 490 | } | ||
| 491 | |||
| 492 | ret = regmap_read(wm8523->regmap, WM8523_DEVICE_ID, &val); | ||
| 493 | if (ret < 0) { | ||
| 494 | dev_err(&i2c->dev, "Failed to read ID register\n"); | ||
| 495 | goto err_enable; | ||
| 496 | } | ||
| 497 | if (val != 0x8523) { | ||
| 498 | dev_err(&i2c->dev, "Device is not a WM8523, ID is %x\n", ret); | ||
| 499 | ret = -EINVAL; | ||
| 500 | goto err_enable; | ||
| 501 | } | ||
| 502 | |||
| 503 | ret = regmap_read(wm8523->regmap, WM8523_REVISION, &val); | ||
| 504 | if (ret < 0) { | ||
| 505 | dev_err(&i2c->dev, "Failed to read revision register\n"); | ||
| 506 | goto err_enable; | ||
| 507 | } | ||
| 508 | dev_info(&i2c->dev, "revision %c\n", | ||
| 509 | (val & WM8523_CHIP_REV_MASK) + 'A'); | ||
| 510 | |||
| 511 | ret = regmap_write(wm8523->regmap, WM8523_DEVICE_ID, 0x8523); | ||
| 512 | if (ret != 0) { | ||
| 513 | dev_err(&i2c->dev, "Failed to reset device: %d\n", ret); | ||
| 514 | goto err_enable; | ||
| 515 | } | ||
| 516 | |||
| 517 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | ||
| 518 | |||
| 523 | i2c_set_clientdata(i2c, wm8523); | 519 | i2c_set_clientdata(i2c, wm8523); |
| 524 | wm8523->control_type = SND_SOC_I2C; | ||
| 525 | 520 | ||
| 526 | ret = snd_soc_register_codec(&i2c->dev, | 521 | ret = snd_soc_register_codec(&i2c->dev, |
| 527 | &soc_codec_dev_wm8523, &wm8523_dai, 1); | 522 | &soc_codec_dev_wm8523, &wm8523_dai, 1); |
| 528 | if (ret < 0) | 523 | |
| 529 | kfree(wm8523); | ||
| 530 | return ret; | 524 | return ret; |
| 531 | 525 | ||
| 526 | err_enable: | ||
| 527 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | ||
| 528 | return ret; | ||
| 532 | } | 529 | } |
| 533 | 530 | ||
| 534 | static __devexit int wm8523_i2c_remove(struct i2c_client *client) | 531 | static __devexit int wm8523_i2c_remove(struct i2c_client *client) |
| 535 | { | 532 | { |
| 536 | snd_soc_unregister_codec(&client->dev); | 533 | snd_soc_unregister_codec(&client->dev); |
| 537 | kfree(i2c_get_clientdata(client)); | ||
| 538 | return 0; | 534 | return 0; |
| 539 | } | 535 | } |
| 540 | 536 | ||
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 7c68226376e4..5e9c40fa7eb2 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * wm8580.c -- WM8580 ALSA Soc Audio driver | 2 | * wm8580.c -- WM8580 ALSA Soc Audio driver |
| 3 | * | 3 | * |
| 4 | * Copyright 2008-11 Wolfson Microelectronics PLC. | 4 | * Copyright 2008-12 Wolfson Microelectronics PLC. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms of the GNU General Public License as published by the | 7 | * under the terms of the GNU General Public License as published by the |
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
| 24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
| 25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
| 26 | #include <linux/regmap.h> | ||
| 26 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
| 27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 28 | #include <linux/of_device.h> | 29 | #include <linux/of_device.h> |
| @@ -157,23 +158,72 @@ | |||
| 157 | * We can't read the WM8580 register space when we | 158 | * We can't read the WM8580 register space when we |
| 158 | * are using 2 wire for device control, so we cache them instead. | 159 | * are using 2 wire for device control, so we cache them instead. |
| 159 | */ | 160 | */ |
| 160 | static const u16 wm8580_reg[] = { | 161 | static const struct reg_default wm8580_reg_defaults[] = { |
| 161 | 0x0121, 0x017e, 0x007d, 0x0014, /*R3*/ | 162 | { 0, 0x0121 }, |
| 162 | 0x0121, 0x017e, 0x007d, 0x0194, /*R7*/ | 163 | { 1, 0x017e }, |
| 163 | 0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/ | 164 | { 2, 0x007d }, |
| 164 | 0x0182, 0x0082, 0x000a, 0x0024, /*R15*/ | 165 | { 3, 0x0014 }, |
| 165 | 0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/ | 166 | { 4, 0x0121 }, |
| 166 | 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/ | 167 | { 5, 0x017e }, |
| 167 | 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R27*/ | 168 | { 6, 0x007d }, |
| 168 | 0x01f0, 0x0040, 0x0000, 0x0000, /*R31(0x1F)*/ | 169 | { 7, 0x0194 }, |
| 169 | 0x0000, 0x0000, 0x0031, 0x000b, /*R35*/ | 170 | { 8, 0x0010 }, |
| 170 | 0x0039, 0x0000, 0x0010, 0x0032, /*R39*/ | 171 | { 9, 0x0002 }, |
| 171 | 0x0054, 0x0076, 0x0098, 0x0000, /*R43(0x2B)*/ | 172 | { 10, 0x0002 }, |
| 172 | 0x0000, 0x0000, 0x0000, 0x0000, /*R47*/ | 173 | { 11, 0x00c2 }, |
| 173 | 0x0000, 0x0000, 0x005e, 0x003e, /*R51(0x33)*/ | 174 | { 12, 0x0182 }, |
| 174 | 0x0000, 0x0000 /*R53*/ | 175 | { 13, 0x0082 }, |
| 176 | { 14, 0x000a }, | ||
| 177 | { 15, 0x0024 }, | ||
| 178 | { 16, 0x0009 }, | ||
| 179 | { 17, 0x0000 }, | ||
| 180 | { 18, 0x00ff }, | ||
| 181 | { 19, 0x0000 }, | ||
| 182 | { 20, 0x00ff }, | ||
| 183 | { 21, 0x00ff }, | ||
| 184 | { 22, 0x00ff }, | ||
| 185 | { 23, 0x00ff }, | ||
| 186 | { 24, 0x00ff }, | ||
| 187 | { 25, 0x00ff }, | ||
| 188 | { 26, 0x00ff }, | ||
| 189 | { 27, 0x00ff }, | ||
| 190 | { 28, 0x01f0 }, | ||
| 191 | { 29, 0x0040 }, | ||
| 192 | { 30, 0x0000 }, | ||
| 193 | { 31, 0x0000 }, | ||
| 194 | { 32, 0x0000 }, | ||
| 195 | { 33, 0x0000 }, | ||
| 196 | { 34, 0x0031 }, | ||
| 197 | { 35, 0x000b }, | ||
| 198 | { 36, 0x0039 }, | ||
| 199 | { 37, 0x0000 }, | ||
| 200 | { 38, 0x0010 }, | ||
| 201 | { 39, 0x0032 }, | ||
| 202 | { 40, 0x0054 }, | ||
| 203 | { 41, 0x0076 }, | ||
| 204 | { 42, 0x0098 }, | ||
| 205 | { 43, 0x0000 }, | ||
| 206 | { 44, 0x0000 }, | ||
| 207 | { 45, 0x0000 }, | ||
| 208 | { 46, 0x0000 }, | ||
| 209 | { 47, 0x0000 }, | ||
| 210 | { 48, 0x0000 }, | ||
| 211 | { 49, 0x0000 }, | ||
| 212 | { 50, 0x005e }, | ||
| 213 | { 51, 0x003e }, | ||
| 214 | { 52, 0x0000 }, | ||
| 175 | }; | 215 | }; |
| 176 | 216 | ||
| 217 | static bool wm8580_volatile(struct device *dev, unsigned int reg) | ||
| 218 | { | ||
| 219 | switch (reg) { | ||
| 220 | case WM8580_RESET: | ||
| 221 | return true; | ||
| 222 | default: | ||
| 223 | return false; | ||
| 224 | } | ||
| 225 | } | ||
| 226 | |||
| 177 | struct pll_state { | 227 | struct pll_state { |
| 178 | unsigned int in; | 228 | unsigned int in; |
| 179 | unsigned int out; | 229 | unsigned int out; |
| @@ -188,7 +238,7 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { | |||
| 188 | 238 | ||
| 189 | /* codec private data */ | 239 | /* codec private data */ |
| 190 | struct wm8580_priv { | 240 | struct wm8580_priv { |
| 191 | enum snd_soc_control_type control_type; | 241 | struct regmap *regmap; |
| 192 | struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; | 242 | struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; |
| 193 | struct pll_state a; | 243 | struct pll_state a; |
| 194 | struct pll_state b; | 244 | struct pll_state b; |
| @@ -203,14 +253,16 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol, | |||
| 203 | struct soc_mixer_control *mc = | 253 | struct soc_mixer_control *mc = |
| 204 | (struct soc_mixer_control *)kcontrol->private_value; | 254 | (struct soc_mixer_control *)kcontrol->private_value; |
| 205 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 255 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
| 206 | u16 *reg_cache = codec->reg_cache; | 256 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
| 207 | unsigned int reg = mc->reg; | 257 | unsigned int reg = mc->reg; |
| 208 | unsigned int reg2 = mc->rreg; | 258 | unsigned int reg2 = mc->rreg; |
| 209 | int ret; | 259 | int ret; |
| 210 | 260 | ||
| 211 | /* Clear the register cache so we write without VU set */ | 261 | /* Clear the register cache VU so we write without VU set */ |
| 212 | reg_cache[reg] = 0; | 262 | regcache_cache_only(wm8580->regmap, true); |
| 213 | reg_cache[reg2] = 0; | 263 | regmap_update_bits(wm8580->regmap, reg, 0x100, 0x000); |
| 264 | regmap_update_bits(wm8580->regmap, reg2, 0x100, 0x000); | ||
| 265 | regcache_cache_only(wm8580->regmap, false); | ||
| 214 | 266 | ||
| 215 | ret = snd_soc_put_volsw(kcontrol, ucontrol); | 267 | ret = snd_soc_put_volsw(kcontrol, ucontrol); |
| 216 | if (ret < 0) | 268 | if (ret < 0) |
| @@ -815,24 +867,14 @@ static struct snd_soc_dai_driver wm8580_dai[] = { | |||
| 815 | static int wm8580_probe(struct snd_soc_codec *codec) | 867 | static int wm8580_probe(struct snd_soc_codec *codec) |
| 816 | { | 868 | { |
| 817 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); | 869 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
| 818 | int ret = 0,i; | 870 | int ret = 0; |
| 819 | 871 | ||
| 820 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type); | 872 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
| 821 | if (ret < 0) { | 873 | if (ret < 0) { |
| 822 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 874 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
| 823 | return ret; | 875 | return ret; |
| 824 | } | 876 | } |
| 825 | 877 | ||
| 826 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) | ||
| 827 | wm8580->supplies[i].supply = wm8580_supply_names[i]; | ||
| 828 | |||
| 829 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies), | ||
| 830 | wm8580->supplies); | ||
| 831 | if (ret != 0) { | ||
| 832 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
| 833 | return ret; | ||
| 834 | } | ||
| 835 | |||
| 836 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), | 878 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), |
| 837 | wm8580->supplies); | 879 | wm8580->supplies); |
| 838 | if (ret != 0) { | 880 | if (ret != 0) { |
| @@ -854,7 +896,6 @@ static int wm8580_probe(struct snd_soc_codec *codec) | |||
| 854 | err_regulator_enable: | 896 | err_regulator_enable: |
| 855 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 897 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
| 856 | err_regulator_get: | 898 | err_regulator_get: |
| 857 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | ||
| 858 | return ret; | 899 | return ret; |
| 859 | } | 900 | } |
| 860 | 901 | ||
| @@ -866,7 +907,6 @@ static int wm8580_remove(struct snd_soc_codec *codec) | |||
| 866 | wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); | 907 | wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); |
| 867 | 908 | ||
| 868 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 909 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
| 869 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | ||
| 870 | 910 | ||
| 871 | return 0; | 911 | return 0; |
| 872 | } | 912 | } |
| @@ -875,9 +915,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { | |||
| 875 | .probe = wm8580_probe, | 915 | .probe = wm8580_probe, |
| 876 | .remove = wm8580_remove, | 916 | .remove = wm8580_remove, |
| 877 | .set_bias_level = wm8580_set_bias_level, | 917 | .set_bias_level = wm8580_set_bias_level, |
| 878 | .reg_cache_size = ARRAY_SIZE(wm8580_reg), | ||
| 879 | .reg_word_size = sizeof(u16), | ||
| 880 | .reg_cache_default = wm8580_reg, | ||
| 881 | 918 | ||
| 882 | .controls = wm8580_snd_controls, | 919 | .controls = wm8580_snd_controls, |
| 883 | .num_controls = ARRAY_SIZE(wm8580_snd_controls), | 920 | .num_controls = ARRAY_SIZE(wm8580_snd_controls), |
| @@ -892,31 +929,55 @@ static const struct of_device_id wm8580_of_match[] = { | |||
| 892 | { }, | 929 | { }, |
| 893 | }; | 930 | }; |
| 894 | 931 | ||
| 932 | static const struct regmap_config wm8580_regmap = { | ||
| 933 | .reg_bits = 7, | ||
| 934 | .val_bits = 9, | ||
| 935 | .max_register = WM8580_MAX_REGISTER, | ||
| 936 | |||
| 937 | .reg_defaults = wm8580_reg_defaults, | ||
| 938 | .num_reg_defaults = ARRAY_SIZE(wm8580_reg_defaults), | ||
| 939 | .cache_type = REGCACHE_RBTREE, | ||
| 940 | |||
| 941 | .volatile_reg = wm8580_volatile, | ||
| 942 | }; | ||
| 943 | |||
| 895 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 944 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
| 896 | static int wm8580_i2c_probe(struct i2c_client *i2c, | 945 | static int wm8580_i2c_probe(struct i2c_client *i2c, |
| 897 | const struct i2c_device_id *id) | 946 | const struct i2c_device_id *id) |
| 898 | { | 947 | { |
| 899 | struct wm8580_priv *wm8580; | 948 | struct wm8580_priv *wm8580; |
| 900 | int ret; | 949 | int ret, i; |
| 901 | 950 | ||
| 902 | wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); | 951 | wm8580 = devm_kzalloc(&i2c->dev, sizeof(struct wm8580_priv), |
| 952 | GFP_KERNEL); | ||
| 903 | if (wm8580 == NULL) | 953 | if (wm8580 == NULL) |
| 904 | return -ENOMEM; | 954 | return -ENOMEM; |
| 905 | 955 | ||
| 956 | wm8580->regmap = devm_regmap_init_i2c(i2c, &wm8580_regmap); | ||
| 957 | if (IS_ERR(wm8580->regmap)) | ||
| 958 | return PTR_ERR(wm8580->regmap); | ||
| 959 | |||
| 960 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) | ||
| 961 | wm8580->supplies[i].supply = wm8580_supply_names[i]; | ||
| 962 | |||
| 963 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8580->supplies), | ||
| 964 | wm8580->supplies); | ||
| 965 | if (ret != 0) { | ||
| 966 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
| 967 | return ret; | ||
| 968 | } | ||
| 969 | |||
| 906 | i2c_set_clientdata(i2c, wm8580); | 970 | i2c_set_clientdata(i2c, wm8580); |
| 907 | wm8580->control_type = SND_SOC_I2C; | ||
| 908 | 971 | ||
| 909 | ret = snd_soc_register_codec(&i2c->dev, | 972 | ret = snd_soc_register_codec(&i2c->dev, |
| 910 | &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); | 973 | &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); |
| 911 | if (ret < 0) | 974 | |
| 912 | kfree(wm8580); | ||
| 913 | return ret; | 975 | return ret; |
| 914 | } | 976 | } |
| 915 | 977 | ||
| 916 | static int wm8580_i2c_remove(struct i2c_client *client) | 978 | static int wm8580_i2c_remove(struct i2c_client *client) |
| 917 | { | 979 | { |
| 918 | snd_soc_unregister_codec(&client->dev); | 980 | snd_soc_unregister_codec(&client->dev); |
| 919 | kfree(i2c_get_clientdata(client)); | ||
| 920 | return 0; | 981 | return 0; |
| 921 | } | 982 | } |
| 922 | 983 | ||
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 0b76d1dca5ea..8b8bb70f1eb9 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
| 19 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
| 20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
| 21 | #include <linux/regmap.h> | ||
| 21 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
| 22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 23 | #include <linux/of_device.h> | 24 | #include <linux/of_device.h> |
| @@ -32,7 +33,7 @@ | |||
| 32 | 33 | ||
| 33 | /* codec private data */ | 34 | /* codec private data */ |
| 34 | struct wm8711_priv { | 35 | struct wm8711_priv { |
| 35 | enum snd_soc_control_type bus_type; | 36 | struct regmap *regmap; |
| 36 | unsigned int sysclk; | 37 | unsigned int sysclk; |
| 37 | }; | 38 | }; |
| 38 | 39 | ||
| @@ -42,11 +43,21 @@ struct wm8711_priv { | |||
| 42 | * using 2 wire for device control, so we cache them instead. | 43 | * using 2 wire for device control, so we cache them instead. |
| 43 | * There is no point in caching the reset register | 44 | * There is no point in caching the reset register |
| 44 | */ | 45 | */ |
| 45 | static const u16 wm8711_reg[WM8711_CACHEREGNUM] = { | 46 | static const struct reg_default wm8711_reg_defaults[] = { |
| 46 | 0x0079, 0x0079, 0x000a, 0x0008, | 47 | { 0, 0x0079 }, { 1, 0x0079 }, { 2, 0x000a }, { 3, 0x0008 }, |
| 47 | 0x009f, 0x000a, 0x0000, 0x0000 | 48 | { 4, 0x009f }, { 5, 0x000a }, { 6, 0x0000 }, { 7, 0x0000 }, |
| 48 | }; | 49 | }; |
| 49 | 50 | ||
| 51 | static bool wm8711_volatile(struct device *dev, unsigned int reg) | ||
| 52 | { | ||
| 53 | switch (reg) { | ||
| 54 | case WM8711_RESET: | ||
| 55 | return true; | ||
| 56 | default: | ||
| 57 | return false; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 50 | #define wm8711_reset(c) snd_soc_write(c, WM8711_RESET, 0) | 61 | #define wm8711_reset(c) snd_soc_write(c, WM8711_RESET, 0) |
| 51 | 62 | ||
| 52 | static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); | 63 | static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1); |
| @@ -289,6 +300,7 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
| 289 | static int wm8711_set_bias_level(struct snd_soc_codec *codec, | 300 | static int wm8711_set_bias_level(struct snd_soc_codec *codec, |
| 290 | enum snd_soc_bias_level level) | 301 | enum snd_soc_bias_level level) |
| 291 | { | 302 | { |
| 303 | struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); | ||
| 292 | u16 reg = snd_soc_read(codec, WM8711_PWR) & 0xff7f; | 304 | u16 reg = snd_soc_read(codec, WM8711_PWR) & 0xff7f; |
| 293 | 305 | ||
| 294 | switch (level) { | 306 | switch (level) { |
| @@ -299,7 +311,7 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec, | |||
| 299 | break; | 311 | break; |
| 300 | case SND_SOC_BIAS_STANDBY: | 312 | case SND_SOC_BIAS_STANDBY: |
| 301 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 313 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) |
| 302 | snd_soc_cache_sync(codec); | 314 | regcache_sync(wm8711->regmap); |
| 303 | 315 | ||
| 304 | snd_soc_write(codec, WM8711_PWR, reg | 0x0040); | 316 | snd_soc_write(codec, WM8711_PWR, reg | 0x0040); |
| 305 | break; | 317 | break; |
| @@ -353,10 +365,9 @@ static int wm8711_resume(struct snd_soc_codec *codec) | |||
| 353 | 365 | ||
| 354 | static int wm8711_probe(struct snd_soc_codec *codec) | 366 | static int wm8711_probe(struct snd_soc_codec *codec) |
| 355 | { | 367 | { |
| 356 | struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec); | ||
| 357 | int ret; | 368 | int ret; |
| 358 | 369 | ||
| 359 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type); | 370 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
| 360 | if (ret < 0) { | 371 | if (ret < 0) { |
| 361 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 372 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
| 362 | return ret; | 373 | return ret; |
| @@ -391,9 +402,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { | |||
| 391 | .suspend = wm8711_suspend, | 402 | .suspend = wm8711_suspend, |
| 392 | .resume = wm8711_resume, | 403 | .resume = wm8711_resume, |
| 393 | .set_bias_level = wm8711_set_bias_level, | 404 | .set_bias_level = wm8711_set_bias_level, |
| 394 | .reg_cache_size = ARRAY_SIZE(wm8711_reg), | ||
| 395 | .reg_word_size = sizeof(u16), | ||
| 396 | .reg_cache_default = wm8711_reg, | ||
| 397 | .controls = wm8711_snd_controls, | 405 | .controls = wm8711_snd_controls, |
| 398 | .num_controls = ARRAY_SIZE(wm8711_snd_controls), | 406 | .num_controls = ARRAY_SIZE(wm8711_snd_controls), |
| 399 | .dapm_widgets = wm8711_dapm_widgets, | 407 | .dapm_widgets = wm8711_dapm_widgets, |
| @@ -408,30 +416,45 @@ static const struct of_device_id wm8711_of_match[] = { | |||
| 408 | }; | 416 | }; |
| 409 | MODULE_DEVICE_TABLE(of, wm8711_of_match); | 417 | MODULE_DEVICE_TABLE(of, wm8711_of_match); |
| 410 | 418 | ||
| 419 | static const struct regmap_config wm8711_regmap = { | ||
| 420 | .reg_bits = 7, | ||
| 421 | .val_bits = 9, | ||
| 422 | .max_register = WM8711_RESET, | ||
| 423 | |||
| 424 | .reg_defaults = wm8711_reg_defaults, | ||
| 425 | .num_reg_defaults = ARRAY_SIZE(wm8711_reg_defaults), | ||
| 426 | .cache_type = REGCACHE_RBTREE, | ||
| 427 | |||
| 428 | .volatile_reg = wm8711_volatile, | ||
| 429 | }; | ||
| 430 | |||
| 411 | #if defined(CONFIG_SPI_MASTER) | 431 | #if defined(CONFIG_SPI_MASTER) |
| 412 | static int __devinit wm8711_spi_probe(struct spi_device *spi) | 432 | static int __devinit wm8711_spi_probe(struct spi_device *spi) |
| 413 | { | 433 | { |
| 414 | struct wm8711_priv *wm8711; | 434 | struct wm8711_priv *wm8711; |
| 415 | int ret; | 435 | int ret; |
| 416 | 436 | ||
| 417 | wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); | 437 | wm8711 = devm_kzalloc(&spi->dev, sizeof(struct wm8711_priv), |
| 438 | GFP_KERNEL); | ||
| 418 | if (wm8711 == NULL) | 439 | if (wm8711 == NULL) |
| 419 | return -ENOMEM; | 440 | return -ENOMEM; |
| 420 | 441 | ||
| 442 | wm8711->regmap = devm_regmap_init_spi(spi, &wm8711_regmap); | ||
| 443 | if (IS_ERR(wm8711->regmap)) | ||
| 444 | return PTR_ERR(wm8711->regmap); | ||
| 445 | |||
| 421 | spi_set_drvdata(spi, wm8711); | 446 | spi_set_drvdata(spi, wm8711); |
| 422 | wm8711->bus_type = SND_SOC_SPI; | ||
| 423 | 447 | ||
| 424 | ret = snd_soc_register_codec(&spi->dev, | 448 | ret = snd_soc_register_codec(&spi->dev, |
| 425 | &soc_codec_dev_wm8711, &wm8711_dai, 1); | 449 | &soc_codec_dev_wm8711, &wm8711_dai, 1); |
| 426 | if (ret < 0) | 450 | |
| 427 | kfree(wm8711); | ||
| 428 | return ret; | 451 | return ret; |
| 429 | } | 452 | } |
| 430 | 453 | ||
| 431 | static int __devexit wm8711_spi_remove(struct spi_device *spi) | 454 | static int __devexit wm8711_spi_remove(struct spi_device *spi) |
| 432 | { | 455 | { |
| 433 | snd_soc_unregister_codec(&spi->dev); | 456 | snd_soc_unregister_codec(&spi->dev); |
| 434 | kfree(spi_get_drvdata(spi)); | 457 | |
| 435 | return 0; | 458 | return 0; |
| 436 | } | 459 | } |
| 437 | 460 | ||
| @@ -453,24 +476,26 @@ static __devinit int wm8711_i2c_probe(struct i2c_client *client, | |||
| 453 | struct wm8711_priv *wm8711; | 476 | struct wm8711_priv *wm8711; |
| 454 | int ret; | 477 | int ret; |
| 455 | 478 | ||
| 456 | wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL); | 479 | wm8711 = devm_kzalloc(&client->dev, sizeof(struct wm8711_priv), |
| 480 | GFP_KERNEL); | ||
| 457 | if (wm8711 == NULL) | 481 | if (wm8711 == NULL) |
| 458 | return -ENOMEM; | 482 | return -ENOMEM; |
| 459 | 483 | ||
| 484 | wm8711->regmap = devm_regmap_init_i2c(client, &wm8711_regmap); | ||
| 485 | if (IS_ERR(wm8711->regmap)) | ||
| 486 | return PTR_ERR(wm8711->regmap); | ||
| 487 | |||
| 460 | i2c_set_clientdata(client, wm8711); | 488 | i2c_set_clientdata(client, wm8711); |
| 461 | wm8711->bus_type = SND_SOC_I2C; | ||
| 462 | 489 | ||
| 463 | ret = snd_soc_register_codec(&client->dev, | 490 | ret = snd_soc_register_codec(&client->dev, |
| 464 | &soc_codec_dev_wm8711, &wm8711_dai, 1); | 491 | &soc_codec_dev_wm8711, &wm8711_dai, 1); |
| 465 | if (ret < 0) | 492 | |
| 466 | kfree(wm8711); | ||
| 467 | return ret; | 493 | return ret; |
| 468 | } | 494 | } |
| 469 | 495 | ||
| 470 | static __devexit int wm8711_i2c_remove(struct i2c_client *client) | 496 | static __devexit int wm8711_i2c_remove(struct i2c_client *client) |
| 471 | { | 497 | { |
| 472 | snd_soc_unregister_codec(&client->dev); | 498 | snd_soc_unregister_codec(&client->dev); |
| 473 | kfree(i2c_get_clientdata(client)); | ||
| 474 | return 0; | 499 | return 0; |
| 475 | } | 500 | } |
| 476 | 501 | ||
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 1467f97dce21..00a12a0c3919 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
| 18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
| 19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
| 20 | #include <linux/regmap.h> | ||
| 20 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
| 21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| 22 | #include <linux/of_device.h> | 23 | #include <linux/of_device.h> |
| @@ -35,16 +36,16 @@ | |||
| 35 | * the volume update bits, mute the output and enable infinite zero | 36 | * the volume update bits, mute the output and enable infinite zero |
| 36 | * detect. | 37 | * detect. |
| 37 | */ | 38 | */ |
| 38 | static const u16 wm8728_reg_defaults[] = { | 39 | static const struct reg_default wm8728_reg_defaults[] = { |
| 39 | 0x1ff, | 40 | { 0, 0x1ff }, |
| 40 | 0x1ff, | 41 | { 1, 0x1ff }, |
| 41 | 0x001, | 42 | { 2, 0x001 }, |
| 42 | 0x100, | 43 | { 3, 0x100 }, |
| 43 | }; | 44 | }; |
| 44 | 45 | ||
| 45 | /* codec private data */ | 46 | /* codec private data */ |
| 46 | struct wm8728_priv { | 47 | struct wm8728_priv { |
| 47 | enum snd_soc_control_type control_type; | 48 | struct regmap *regmap; |
| 48 | }; | 49 | }; |
| 49 | 50 | ||
| 50 | static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); | 51 | static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); |
| @@ -162,8 +163,8 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
| 162 | static int wm8728_set_bias_level(struct snd_soc_codec *codec, | 163 | static int wm8728_set_bias_level(struct snd_soc_codec *codec, |
| 163 | enum snd_soc_bias_level level) | 164 | enum snd_soc_bias_level level) |
| 164 | { | 165 | { |
| 166 | struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); | ||
| 165 | u16 reg; | 167 | u16 reg; |
| 166 | int i; | ||
| 167 | 168 | ||
| 168 | switch (level) { | 169 | switch (level) { |
| 169 | case SND_SOC_BIAS_ON: | 170 | case SND_SOC_BIAS_ON: |
| @@ -175,9 +176,7 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec, | |||
| 175 | snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4); | 176 | snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4); |
| 176 | 177 | ||
| 177 | /* ..then sync in the register cache. */ | 178 | /* ..then sync in the register cache. */ |
| 178 | for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++) | 179 | regcache_sync(wm8728->regmap); |
| 179 | snd_soc_write(codec, i, | ||
| 180 | snd_soc_read(codec, i)); | ||
| 181 | } | 180 | } |
| 182 | break; | 181 | break; |
| 183 | 182 | ||
| @@ -229,10 +228,9 @@ static int wm8728_resume(struct snd_soc_codec *codec) | |||
| 229 | 228 | ||
| 230 | static int wm8728_probe(struct snd_soc_codec *codec) | 229 | static int wm8728_probe(struct snd_soc_codec *codec) |
| 231 | { | 230 | { |
| 232 | struct wm8728_priv *wm8728 = snd_soc_codec_get_drvdata(codec); | ||
| 233 | int ret; | 231 | int ret; |
| 234 | 232 | ||
| 235 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8728->control_type); | 233 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
| 236 | if (ret < 0) { | 234 | if (ret < 0) { |
| 237 | printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", | 235 | printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n", |
| 238 | ret); | 236 | ret); |
| @@ -257,9 +255,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { | |||
| 257 | .suspend = wm8728_suspend, | 255 | .suspend = wm8728_suspend, |
| 258 | .resume = wm8728_resume, | 256 | .resume = wm8728_resume, |
| 259 | .set_bias_level = wm8728_set_bias_level, | 257 | .set_bias_level = wm8728_set_bias_level, |
| 260 | .reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults), | ||
| 261 | .reg_word_size = sizeof(u16), | ||
| 262 | .reg_cache_default = wm8728_reg_defaults, | ||
| 263 | .controls = wm8728_snd_controls, | 258 | .controls = wm8728_snd_controls, |
| 264 | .num_controls = ARRAY_SIZE(wm8728_snd_controls), | 259 | .num_controls = ARRAY_SIZE(wm8728_snd_controls), |
| 265 | .dapm_widgets = wm8728_dapm_widgets, | 260 | .dapm_widgets = wm8728_dapm_widgets, |
| @@ -274,30 +269,43 @@ static const struct of_device_id wm8728_of_match[] = { | |||
| 274 | }; | 269 | }; |
| 275 | MODULE_DEVICE_TABLE(of, wm8728_of_match); | 270 | MODULE_DEVICE_TABLE(of, wm8728_of_match); |
| 276 | 271 | ||
| 272 | static const struct regmap_config wm8728_regmap = { | ||
| 273 | .reg_bits = 7, | ||
| 274 | .val_bits = 9, | ||
| 275 | .max_register = WM8728_IFCTL, | ||
| 276 | |||
| 277 | .reg_defaults = wm8728_reg_defaults, | ||
| 278 | .num_reg_defaults = ARRAY_SIZE(wm8728_reg_defaults), | ||
| 279 | .cache_type = REGCACHE_RBTREE, | ||
| 280 | }; | ||
| 281 | |||
| 277 | #if defined(CONFIG_SPI_MASTER) | 282 | #if defined(CONFIG_SPI_MASTER) |
| 278 | static int __devinit wm8728_spi_probe(struct spi_device *spi) | 283 | static int __devinit wm8728_spi_probe(struct spi_device *spi) |
| 279 | { | 284 | { |
| 280 | struct wm8728_priv *wm8728; | 285 | struct wm8728_priv *wm8728; |
| 281 | int ret; | 286 | int ret; |
| 282 | 287 | ||
| 283 | wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); | 288 | wm8728 = devm_kzalloc(&spi->dev, sizeof(struct wm8728_priv), |
| 289 | GFP_KERNEL); | ||
| 284 | if (wm8728 == NULL) | 290 | if (wm8728 == NULL) |
| 285 | return -ENOMEM; | 291 | return -ENOMEM; |
| 286 | 292 | ||
| 287 | wm8728->control_type = SND_SOC_SPI; | 293 | wm8728->regmap = devm_regmap_init_spi(spi, &wm8728_regmap); |
| 294 | if (IS_ERR(wm8728->regmap)) | ||
| 295 | return PTR_ERR(wm8728->regmap); | ||
| 296 | |||
| 288 | spi_set_drvdata(spi, wm8728); | 297 | spi_set_drvdata(spi, wm8728); |
| 289 | 298 | ||
| 290 | ret = snd_soc_register_codec(&spi->dev, | 299 | ret = snd_soc_register_codec(&spi->dev, |
| 291 | &soc_codec_dev_wm8728, &wm8728_dai, 1); | 300 | &soc_codec_dev_wm8728, &wm8728_dai, 1); |
| 292 | if (ret < 0) | 301 | |
| 293 | kfree(wm8728); | ||
| 294 | return ret; | 302 | return ret; |
| 295 | } | 303 | } |
| 296 | 304 | ||
| 297 | static int __devexit wm8728_spi_remove(struct spi_device *spi) | 305 | static int __devexit wm8728_spi_remove(struct spi_device *spi) |
| 298 | { | 306 | { |
| 299 | snd_soc_unregister_codec(&spi->dev); | 307 | snd_soc_unregister_codec(&spi->dev); |
| 300 | kfree(spi_get_drvdata(spi)); | 308 | |
| 301 | return 0; | 309 | return 0; |
| 302 | } | 310 | } |
| 303 | 311 | ||
| @@ -319,24 +327,26 @@ static __devinit int wm8728_i2c_probe(struct i2c_client *i2c, | |||
| 319 | struct wm8728_priv *wm8728; | 327 | struct wm8728_priv *wm8728; |
| 320 | int ret; | 328 | int ret; |
| 321 | 329 | ||
| 322 | wm8728 = kzalloc(sizeof(struct wm8728_priv), GFP_KERNEL); | 330 | wm8728 = devm_kzalloc(&i2c->dev, sizeof(struct wm8728_priv), |
| 331 | GFP_KERNEL); | ||
| 323 | if (wm8728 == NULL) | 332 | if (wm8728 == NULL) |
| 324 | return -ENOMEM; | 333 | return -ENOMEM; |
| 325 | 334 | ||
| 335 | wm8728->regmap = devm_regmap_init_i2c(i2c, &wm8728_regmap); | ||
| 336 | if (IS_ERR(wm8728->regmap)) | ||
| 337 | return PTR_ERR(wm8728->regmap); | ||
| 338 | |||
| 326 | i2c_set_clientdata(i2c, wm8728); | 339 | i2c_set_clientdata(i2c, wm8728); |
| 327 | wm8728->control_type = SND_SOC_I2C; | ||
| 328 | 340 | ||
| 329 | ret = snd_soc_register_codec(&i2c->dev, | 341 | ret = snd_soc_register_codec(&i2c->dev, |
| 330 | &soc_codec_dev_wm8728, &wm8728_dai, 1); | 342 | &soc_codec_dev_wm8728, &wm8728_dai, 1); |
| 331 | if (ret < 0) | 343 | |
| 332 | kfree(wm8728); | ||
| 333 | return ret; | 344 | return ret; |
| 334 | } | 345 | } |
| 335 | 346 | ||
| 336 | static __devexit int wm8728_i2c_remove(struct i2c_client *client) | 347 | static __devexit int wm8728_i2c_remove(struct i2c_client *client) |
| 337 | { | 348 | { |
| 338 | snd_soc_unregister_codec(&client->dev); | 349 | snd_soc_unregister_codec(&client->dev); |
| 339 | kfree(i2c_get_clientdata(client)); | ||
| 340 | return 0; | 350 | return 0; |
| 341 | } | 351 | } |
| 342 | 352 | ||
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index d0520124616d..5c9634f4c1f0 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
| 17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
| 18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
| 19 | #include <linux/regmap.h> | ||
| 19 | #include <linux/regulator/consumer.h> | 20 | #include <linux/regulator/consumer.h> |
| 20 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
| 21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
| @@ -40,29 +41,39 @@ static const char *wm8737_supply_names[WM8737_NUM_SUPPLIES] = { | |||
| 40 | 41 | ||
| 41 | /* codec private data */ | 42 | /* codec private data */ |
| 42 | struct wm8737_priv { | 43 | struct wm8737_priv { |
| 43 | enum snd_soc_control_type control_type; | 44 | struct regmap *regmap; |
| 44 | struct regulator_bulk_data supplies[WM8737_NUM_SUPPLIES]; | 45 | struct regulator_bulk_data supplies[WM8737_NUM_SUPPLIES]; |
| 45 | unsigned int mclk; | 46 | unsigned int mclk; |
| 46 | }; | 47 | }; |
| 47 | 48 | ||
| 48 | static const u16 wm8737_reg[WM8737_REGISTER_COUNT] = { | 49 | static const struct reg_default wm8737_reg_defaults[] = { |
| 49 | 0x00C3, /* R0 - Left PGA volume */ | 50 | { 0, 0x00C3 }, /* R0 - Left PGA volume */ |
| 50 | 0x00C3, /* R1 - Right PGA volume */ | 51 | { 1, 0x00C3 }, /* R1 - Right PGA volume */ |
| 51 | 0x0007, /* R2 - AUDIO path L */ | 52 | { 2, 0x0007 }, /* R2 - AUDIO path L */ |
| 52 | 0x0007, /* R3 - AUDIO path R */ | 53 | { 3, 0x0007 }, /* R3 - AUDIO path R */ |
| 53 | 0x0000, /* R4 - 3D Enhance */ | 54 | { 4, 0x0000 }, /* R4 - 3D Enhance */ |
| 54 | 0x0000, /* R5 - ADC Control */ | 55 | { 5, 0x0000 }, /* R5 - ADC Control */ |
| 55 | 0x0000, /* R6 - Power Management */ | 56 | { 6, 0x0000 }, /* R6 - Power Management */ |
| 56 | 0x000A, /* R7 - Audio Format */ | 57 | { 7, 0x000A }, /* R7 - Audio Format */ |
| 57 | 0x0000, /* R8 - Clocking */ | 58 | { 8, 0x0000 }, /* R8 - Clocking */ |
| 58 | 0x000F, /* R9 - MIC Preamp Control */ | 59 | { 9, 0x000F }, /* R9 - MIC Preamp Control */ |
| 59 | 0x0003, /* R10 - Misc Bias Control */ | 60 | { 10, 0x0003 }, /* R10 - Misc Bias Control */ |
| 60 | 0x0000, /* R11 - Noise Gate */ | 61 | { 11, 0x0000 }, /* R11 - Noise Gate */ |
| 61 | 0x007C, /* R12 - ALC1 */ | 62 | { 12, 0x007C }, /* R12 - ALC1 */ |
| 62 | 0x0000, /* R13 - ALC2 */ | 63 | { 13, 0x0000 }, /* R13 - ALC2 */ |
| 63 | 0x0032, /* R14 - ALC3 */ | 64 | { 14, 0x0032 }, /* R14 - ALC3 */ |
| 64 | }; | 65 | }; |
| 65 | 66 | ||
| 67 | static bool wm8737_volatile(struct device *dev, unsigned int reg) | ||
| 68 | { | ||
| 69 | switch (reg) { | ||
| 70 | case WM8737_RESET: | ||
| 71 | return true; | ||
| 72 | default: | ||
| 73 | return false; | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 66 | static int wm8737_reset(struct snd_soc_codec *codec) | 77 | static int wm8737_reset(struct snd_soc_codec *codec) |
| 67 | { | 78 | { |
| 68 | return snd_soc_write(codec, WM8737_RESET, 0); | 79 | return snd_soc_write(codec, WM8737_RESET, 0); |
| @@ -479,7 +490,7 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec, | |||
| 479 | return ret; | 490 | return ret; |
| 480 | } | 491 | } |
| 481 | 492 | ||
| 482 | snd_soc_cache_sync(codec); | 493 | regcache_sync(wm8737->regmap); |
| 483 | 494 | ||
| 484 | /* Fast VMID ramp at 2*2.5k */ | 495 | /* Fast VMID ramp at 2*2.5k */ |
| 485 | snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, | 496 | snd_soc_update_bits(codec, WM8737_MISC_BIAS_CONTROL, |
| @@ -557,24 +568,14 @@ static int wm8737_resume(struct snd_soc_codec *codec) | |||
| 557 | static int wm8737_probe(struct snd_soc_codec *codec) | 568 | static int wm8737_probe(struct snd_soc_codec *codec) |
| 558 | { | 569 | { |
| 559 | struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); | 570 | struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); |
| 560 | int ret, i; | 571 | int ret; |
| 561 | 572 | ||
| 562 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8737->control_type); | 573 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
| 563 | if (ret != 0) { | 574 | if (ret != 0) { |
| 564 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 575 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
| 565 | return ret; | 576 | return ret; |
| 566 | } | 577 | } |
| 567 | 578 | ||
| 568 | for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++) | ||
| 569 | wm8737->supplies[i].supply = wm8737_supply_names[i]; | ||
| 570 | |||
| 571 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8737->supplies), | ||
| 572 | wm8737->supplies); | ||
| 573 | if (ret != 0) { | ||
| 574 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
| 575 | return ret; | ||
| 576 | } | ||
| 577 | |||
| 578 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), | 579 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8737->supplies), |
| 579 | wm8737->supplies); | 580 | wm8737->supplies); |
| 580 | if (ret != 0) { | 581 | if (ret != 0) { |
| @@ -607,17 +608,12 @@ static int wm8737_probe(struct snd_soc_codec *codec) | |||
| 607 | err_enable: | 608 | err_enable: |
| 608 | regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); | 609 | regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); |
| 609 | err_get: | 610 | err_get: |
| 610 | regulator_bulk_free(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); | ||
| 611 | |||
| 612 | return ret; | 611 | return ret; |
| 613 | } | 612 | } |
| 614 | 613 | ||
| 615 | static int wm8737_remove(struct snd_soc_codec *codec) | 614 | static int wm8737_remove(struct snd_soc_codec *codec) |
| 616 | { | 615 | { |
| 617 | struct wm8737_priv *wm8737 = snd_soc_codec_get_drvdata(codec); | ||
| 618 | |||
| 619 | wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF); | 616 | wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF); |
| 620 | regulator_bulk_free(ARRAY_SIZE(wm8737->supplies), wm8737->supplies); | ||
| 621 | return 0; | 617 | return 0; |
| 622 | } | 618 | } |
| 623 | 619 | ||
| @@ -627,10 +623,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8737 = { | |||
| 627 | .suspend = wm8737_suspend, | 623 | .suspend = wm8737_suspend, |
| 628 | .resume = wm8737_resume, | 624 | .resume = wm8737_resume, |
| 629 | .set_bias_level = wm8737_set_bias_level, | 625 | .set_bias_level = wm8737_set_bias_level, |
| 630 | |||
| 631 | .reg_cache_size = WM8737_REGISTER_COUNT - 1, /* Skip reset */ | ||
| 632 | .reg_word_size = sizeof(u16), | ||
| 633 | .reg_cache_default = wm8737_reg, | ||
| 634 | }; | 626 | }; |
| 635 | 627 | ||
| 636 | static const struct of_device_id wm8737_of_match[] = { | 628 | static const struct of_device_id wm8737_of_match[] = { |
| @@ -640,24 +632,49 @@ static const struct of_device_id wm8737_of_match[] = { | |||
| 640 | 632 | ||
| 641 | MODULE_DEVICE_TABLE(of, wm8737_of_match); | 633 | MODULE_DEVICE_TABLE(of, wm8737_of_match); |
| 642 | 634 | ||
| 635 | static const struct regmap_config wm8737_regmap = { | ||
| 636 | .reg_bits = 7, | ||
| 637 | .val_bits = 9, | ||
| 638 | .max_register = WM8737_MAX_REGISTER, | ||
| 639 | |||
| 640 | .reg_defaults = wm8737_reg_defaults, | ||
| 641 | .num_reg_defaults = ARRAY_SIZE(wm8737_reg_defaults), | ||
| 642 | .cache_type = REGCACHE_RBTREE, | ||
| 643 | |||
| 644 | .volatile_reg = wm8737_volatile, | ||
| 645 | }; | ||
| 646 | |||
| 643 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 647 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
| 644 | static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, | 648 | static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, |
| 645 | const struct i2c_device_id *id) | 649 | const struct i2c_device_id *id) |
| 646 | { | 650 | { |
| 647 | struct wm8737_priv *wm8737; | 651 | struct wm8737_priv *wm8737; |
| 648 | int ret; | 652 | int ret, i; |
| 649 | 653 | ||
| 650 | wm8737 = kzalloc(sizeof(struct wm8737_priv), GFP_KERNEL); | 654 | wm8737 = devm_kzalloc(&i2c->dev, sizeof(struct wm8737_priv), |
| 655 | GFP_KERNEL); | ||
| 651 | if (wm8737 == NULL) | 656 | if (wm8737 == NULL) |
| 652 | return -ENOMEM; | 657 | return -ENOMEM; |
| 653 | 658 | ||
| 659 | for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++) | ||
| 660 | wm8737->supplies[i].supply = wm8737_supply_names[i]; | ||
| 661 | |||
| 662 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8737->supplies), | ||
| 663 | wm8737->supplies); | ||
| 664 | if (ret != 0) { | ||
| 665 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
| 666 | return ret; | ||
| 667 | } | ||
| 668 | |||
| 669 | wm8737->regmap = devm_regmap_init_i2c(i2c, &wm8737_regmap); | ||
| 670 | if (IS_ERR(wm8737->regmap)) | ||
| 671 | return PTR_ERR(wm8737->regmap); | ||
| 672 | |||
| 654 | i2c_set_clientdata(i2c, wm8737); | 673 | i2c_set_clientdata(i2c, wm8737); |
| 655 | wm8737->control_type = SND_SOC_I2C; | ||
| 656 | 674 | ||
| 657 | ret = snd_soc_register_codec(&i2c->dev, | 675 | ret = snd_soc_register_codec(&i2c->dev, |
| 658 | &soc_codec_dev_wm8737, &wm8737_dai, 1); | 676 | &soc_codec_dev_wm8737, &wm8737_dai, 1); |
| 659 | if (ret < 0) | 677 | |
| 660 | kfree(wm8737); | ||
| 661 | return ret; | 678 | return ret; |
| 662 | 679 | ||
| 663 | } | 680 | } |
| @@ -665,7 +682,7 @@ static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, | |||
| 665 | static __devexit int wm8737_i2c_remove(struct i2c_client *client) | 682 | static __devexit int wm8737_i2c_remove(struct i2c_client *client) |
| 666 | { | 683 | { |
| 667 | snd_soc_unregister_codec(&client->dev); | 684 | snd_soc_unregister_codec(&client->dev); |
| 668 | kfree(i2c_get_clientdata(client)); | 685 | |
| 669 | return 0; | 686 | return 0; |
| 670 | } | 687 | } |
| 671 | 688 | ||
| @@ -691,26 +708,39 @@ static struct i2c_driver wm8737_i2c_driver = { | |||
| 691 | static int __devinit wm8737_spi_probe(struct spi_device *spi) | 708 | static int __devinit wm8737_spi_probe(struct spi_device *spi) |
| 692 | { | 709 | { |
| 693 | struct wm8737_priv *wm8737; | 710 | struct wm8737_priv *wm8737; |
| 694 | int ret; | 711 | int ret, i; |
| 695 | 712 | ||
| 696 | wm8737 = kzalloc(sizeof(struct wm8737_priv), GFP_KERNEL); | 713 | wm8737 = devm_kzalloc(&spi->dev, sizeof(struct wm8737_priv), |
| 714 | GFP_KERNEL); | ||
| 697 | if (wm8737 == NULL) | 715 | if (wm8737 == NULL) |
| 698 | return -ENOMEM; | 716 | return -ENOMEM; |
| 699 | 717 | ||
| 700 | wm8737->control_type = SND_SOC_SPI; | 718 | for (i = 0; i < ARRAY_SIZE(wm8737->supplies); i++) |
| 719 | wm8737->supplies[i].supply = wm8737_supply_names[i]; | ||
| 720 | |||
| 721 | ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8737->supplies), | ||
| 722 | wm8737->supplies); | ||
| 723 | if (ret != 0) { | ||
| 724 | dev_err(&spi->dev, "Failed to request supplies: %d\n", ret); | ||
| 725 | return ret; | ||
| 726 | } | ||
| 727 | |||
| 728 | wm8737->regmap = devm_regmap_init_spi(spi, &wm8737_regmap); | ||
| 729 | if (IS_ERR(wm8737->regmap)) | ||
| 730 | return PTR_ERR(wm8737->regmap); | ||
| 731 | |||
| 701 | spi_set_drvdata(spi, wm8737); | 732 | spi_set_drvdata(spi, wm8737); |
| 702 | 733 | ||
| 703 | ret = snd_soc_register_codec(&spi->dev, | 734 | ret = snd_soc_register_codec(&spi->dev, |
| 704 | &soc_codec_dev_wm8737, &wm8737_dai, 1); | 735 | &soc_codec_dev_wm8737, &wm8737_dai, 1); |
| 705 | if (ret < 0) | 736 | |
| 706 | kfree(wm8737); | ||
| 707 | return ret; | 737 | return ret; |
| 708 | } | 738 | } |
| 709 | 739 | ||
| 710 | static int __devexit wm8737_spi_remove(struct spi_device *spi) | 740 | static int __devexit wm8737_spi_remove(struct spi_device *spi) |
| 711 | { | 741 | { |
| 712 | snd_soc_unregister_codec(&spi->dev); | 742 | snd_soc_unregister_codec(&spi->dev); |
| 713 | kfree(spi_get_drvdata(spi)); | 743 | |
| 714 | return 0; | 744 | return 0; |
| 715 | } | 745 | } |
| 716 | 746 | ||
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 35f3d23200e0..4281a0802138 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
| 19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
| 20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
| 21 | #include <linux/regmap.h> | ||
| 21 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
| 22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 23 | #include <linux/of_device.h> | 24 | #include <linux/of_device.h> |
| @@ -40,26 +41,43 @@ static const char *wm8741_supply_names[WM8741_NUM_SUPPLIES] = { | |||
| 40 | 41 | ||
| 41 | /* codec private data */ | 42 | /* codec private data */ |
| 42 | struct wm8741_priv { | 43 | struct wm8741_priv { |
| 43 | enum snd_soc_control_type control_type; | 44 | struct regmap *regmap; |
| 44 | struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; | 45 | struct regulator_bulk_data supplies[WM8741_NUM_SUPPLIES]; |
| 45 | unsigned int sysclk; | 46 | unsigned int sysclk; |
| 46 | struct snd_pcm_hw_constraint_list *sysclk_constraints; | 47 | struct snd_pcm_hw_constraint_list *sysclk_constraints; |
| 47 | }; | 48 | }; |
| 48 | 49 | ||
| 49 | static const u16 wm8741_reg_defaults[WM8741_REGISTER_COUNT] = { | 50 | static const struct reg_default wm8741_reg_defaults[] = { |
| 50 | 0x0000, /* R0 - DACLLSB Attenuation */ | 51 | { 0, 0x0000 }, /* R0 - DACLLSB Attenuation */ |
| 51 | 0x0000, /* R1 - DACLMSB Attenuation */ | 52 | { 1, 0x0000 }, /* R1 - DACLMSB Attenuation */ |
| 52 | 0x0000, /* R2 - DACRLSB Attenuation */ | 53 | { 2, 0x0000 }, /* R2 - DACRLSB Attenuation */ |
| 53 | 0x0000, /* R3 - DACRMSB Attenuation */ | 54 | { 3, 0x0000 }, /* R3 - DACRMSB Attenuation */ |
| 54 | 0x0000, /* R4 - Volume Control */ | 55 | { 4, 0x0000 }, /* R4 - Volume Control */ |
| 55 | 0x000A, /* R5 - Format Control */ | 56 | { 5, 0x000A }, /* R5 - Format Control */ |
| 56 | 0x0000, /* R6 - Filter Control */ | 57 | { 6, 0x0000 }, /* R6 - Filter Control */ |
| 57 | 0x0000, /* R7 - Mode Control 1 */ | 58 | { 7, 0x0000 }, /* R7 - Mode Control 1 */ |
| 58 | 0x0002, /* R8 - Mode Control 2 */ | 59 | { 8, 0x0002 }, /* R8 - Mode Control 2 */ |
| 59 | 0x0000, /* R9 - Reset */ | 60 | { 32, 0x0002 }, /* R32 - ADDITONAL_CONTROL_1 */ |
| 60 | 0x0002, /* R32 - ADDITONAL_CONTROL_1 */ | ||
| 61 | }; | 61 | }; |
| 62 | 62 | ||
| 63 | static bool wm8741_readable(struct device *dev, unsigned int reg) | ||
| 64 | { | ||
| 65 | switch (reg) { | ||
| 66 | case WM8741_DACLLSB_ATTENUATION: | ||
| 67 | case WM8741_DACLMSB_ATTENUATION: | ||
| 68 | case WM8741_DACRLSB_ATTENUATION: | ||
| 69 | case WM8741_DACRMSB_ATTENUATION: | ||
| 70 | case WM8741_VOLUME_CONTROL: | ||
| 71 | case WM8741_FORMAT_CONTROL: | ||
| 72 | case WM8741_FILTER_CONTROL: | ||
| 73 | case WM8741_MODE_CONTROL_1: | ||
| 74 | case WM8741_MODE_CONTROL_2: | ||
| 75 | case WM8741_ADDITIONAL_CONTROL_1: | ||
| 76 | return true; | ||
| 77 | default: | ||
| 78 | return false; | ||
| 79 | } | ||
| 80 | } | ||
| 63 | 81 | ||
| 64 | static int wm8741_reset(struct snd_soc_codec *codec) | 82 | static int wm8741_reset(struct snd_soc_codec *codec) |
| 65 | { | 83 | { |
| @@ -403,17 +421,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) | |||
| 403 | { | 421 | { |
| 404 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | 422 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); |
| 405 | int ret = 0; | 423 | int ret = 0; |
| 406 | int i; | ||
| 407 | |||
| 408 | for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) | ||
| 409 | wm8741->supplies[i].supply = wm8741_supply_names[i]; | ||
| 410 | |||
| 411 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies), | ||
| 412 | wm8741->supplies); | ||
| 413 | if (ret != 0) { | ||
| 414 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
| 415 | goto err; | ||
| 416 | } | ||
| 417 | 424 | ||
| 418 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), | 425 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), |
| 419 | wm8741->supplies); | 426 | wm8741->supplies); |
| @@ -422,7 +429,7 @@ static int wm8741_probe(struct snd_soc_codec *codec) | |||
| 422 | goto err_get; | 429 | goto err_get; |
| 423 | } | 430 | } |
| 424 | 431 | ||
| 425 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); | 432 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
| 426 | if (ret != 0) { | 433 | if (ret != 0) { |
| 427 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 434 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
| 428 | goto err_enable; | 435 | goto err_enable; |
| @@ -450,8 +457,6 @@ static int wm8741_probe(struct snd_soc_codec *codec) | |||
| 450 | err_enable: | 457 | err_enable: |
| 451 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | 458 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); |
| 452 | err_get: | 459 | err_get: |
| 453 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
| 454 | err: | ||
| 455 | return ret; | 460 | return ret; |
| 456 | } | 461 | } |
| 457 | 462 | ||
| @@ -460,7 +465,6 @@ static int wm8741_remove(struct snd_soc_codec *codec) | |||
| 460 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | 465 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); |
| 461 | 466 | ||
| 462 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | 467 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); |
| 463 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
| 464 | 468 | ||
| 465 | return 0; | 469 | return 0; |
| 466 | } | 470 | } |
| @@ -469,9 +473,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { | |||
| 469 | .probe = wm8741_probe, | 473 | .probe = wm8741_probe, |
| 470 | .remove = wm8741_remove, | 474 | .remove = wm8741_remove, |
| 471 | .resume = wm8741_resume, | 475 | .resume = wm8741_resume, |
| 472 | .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults), | ||
| 473 | .reg_word_size = sizeof(u16), | ||
| 474 | .reg_cache_default = wm8741_reg_defaults, | ||
| 475 | 476 | ||
| 476 | .controls = wm8741_snd_controls, | 477 | .controls = wm8741_snd_controls, |
| 477 | .num_controls = ARRAY_SIZE(wm8741_snd_controls), | 478 | .num_controls = ARRAY_SIZE(wm8741_snd_controls), |
| @@ -487,20 +488,48 @@ static const struct of_device_id wm8741_of_match[] = { | |||
| 487 | }; | 488 | }; |
| 488 | MODULE_DEVICE_TABLE(of, wm8741_of_match); | 489 | MODULE_DEVICE_TABLE(of, wm8741_of_match); |
| 489 | 490 | ||
| 491 | static const struct regmap_config wm8741_regmap = { | ||
| 492 | .reg_bits = 7, | ||
| 493 | .val_bits = 9, | ||
| 494 | .max_register = WM8741_MAX_REGISTER, | ||
| 495 | |||
| 496 | .reg_defaults = wm8741_reg_defaults, | ||
| 497 | .num_reg_defaults = ARRAY_SIZE(wm8741_reg_defaults), | ||
| 498 | .cache_type = REGCACHE_RBTREE, | ||
| 499 | |||
| 500 | .readable_reg = wm8741_readable, | ||
| 501 | }; | ||
| 502 | |||
| 490 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 503 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
| 491 | static int wm8741_i2c_probe(struct i2c_client *i2c, | 504 | static int wm8741_i2c_probe(struct i2c_client *i2c, |
| 492 | const struct i2c_device_id *id) | 505 | const struct i2c_device_id *id) |
| 493 | { | 506 | { |
| 494 | struct wm8741_priv *wm8741; | 507 | struct wm8741_priv *wm8741; |
| 495 | int ret; | 508 | int ret, i; |
| 496 | 509 | ||
| 497 | wm8741 = devm_kzalloc(&i2c->dev, sizeof(struct wm8741_priv), | 510 | wm8741 = devm_kzalloc(&i2c->dev, sizeof(struct wm8741_priv), |
| 498 | GFP_KERNEL); | 511 | GFP_KERNEL); |
| 499 | if (wm8741 == NULL) | 512 | if (wm8741 == NULL) |
| 500 | return -ENOMEM; | 513 | return -ENOMEM; |
| 501 | 514 | ||
| 515 | for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) | ||
| 516 | wm8741->supplies[i].supply = wm8741_supply_names[i]; | ||
| 517 | |||
| 518 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), | ||
| 519 | wm8741->supplies); | ||
| 520 | if (ret != 0) { | ||
| 521 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
| 522 | return ret; | ||
| 523 | } | ||
| 524 | |||
| 525 | wm8741->regmap = regmap_init_i2c(i2c, &wm8741_regmap); | ||
| 526 | if (IS_ERR(wm8741->regmap)) { | ||
| 527 | ret = PTR_ERR(wm8741->regmap); | ||
| 528 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); | ||
| 529 | return ret; | ||
| 530 | } | ||
| 531 | |||
| 502 | i2c_set_clientdata(i2c, wm8741); | 532 | i2c_set_clientdata(i2c, wm8741); |
| 503 | wm8741->control_type = SND_SOC_I2C; | ||
| 504 | 533 | ||
| 505 | ret = snd_soc_register_codec(&i2c->dev, | 534 | ret = snd_soc_register_codec(&i2c->dev, |
| 506 | &soc_codec_dev_wm8741, &wm8741_dai, 1); | 535 | &soc_codec_dev_wm8741, &wm8741_dai, 1); |
| @@ -536,14 +565,30 @@ static struct i2c_driver wm8741_i2c_driver = { | |||
| 536 | static int __devinit wm8741_spi_probe(struct spi_device *spi) | 565 | static int __devinit wm8741_spi_probe(struct spi_device *spi) |
| 537 | { | 566 | { |
| 538 | struct wm8741_priv *wm8741; | 567 | struct wm8741_priv *wm8741; |
| 539 | int ret; | 568 | int ret, i; |
| 540 | 569 | ||
| 541 | wm8741 = devm_kzalloc(&spi->dev, sizeof(struct wm8741_priv), | 570 | wm8741 = devm_kzalloc(&spi->dev, sizeof(struct wm8741_priv), |
| 542 | GFP_KERNEL); | 571 | GFP_KERNEL); |
| 543 | if (wm8741 == NULL) | 572 | if (wm8741 == NULL) |
| 544 | return -ENOMEM; | 573 | return -ENOMEM; |
| 545 | 574 | ||
| 546 | wm8741->control_type = SND_SOC_SPI; | 575 | for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) |
| 576 | wm8741->supplies[i].supply = wm8741_supply_names[i]; | ||
| 577 | |||
| 578 | ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8741->supplies), | ||
| 579 | wm8741->supplies); | ||
| 580 | if (ret != 0) { | ||
| 581 | dev_err(&spi->dev, "Failed to request supplies: %d\n", ret); | ||
| 582 | return ret; | ||
| 583 | } | ||
| 584 | |||
| 585 | wm8741->regmap = regmap_init_spi(spi, &wm8741_regmap); | ||
| 586 | if (IS_ERR(wm8741->regmap)) { | ||
| 587 | ret = PTR_ERR(wm8741->regmap); | ||
| 588 | dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); | ||
| 589 | return ret; | ||
| 590 | } | ||
| 591 | |||
| 547 | spi_set_drvdata(spi, wm8741); | 592 | spi_set_drvdata(spi, wm8741); |
| 548 | 593 | ||
| 549 | ret = snd_soc_register_codec(&spi->dev, | 594 | ret = snd_soc_register_codec(&spi->dev, |
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index a5127b4ff9e1..c7c0034d3966 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c | |||
| @@ -724,24 +724,7 @@ static struct spi_driver wm8770_spi_driver = { | |||
| 724 | .remove = __devexit_p(wm8770_spi_remove) | 724 | .remove = __devexit_p(wm8770_spi_remove) |
| 725 | }; | 725 | }; |
| 726 | 726 | ||
| 727 | static int __init wm8770_modinit(void) | 727 | module_spi_driver(wm8770_spi_driver); |
| 728 | { | ||
| 729 | int ret = 0; | ||
| 730 | |||
| 731 | ret = spi_register_driver(&wm8770_spi_driver); | ||
| 732 | if (ret) { | ||
| 733 | printk(KERN_ERR "Failed to register wm8770 SPI driver: %d\n", | ||
| 734 | ret); | ||
| 735 | } | ||
| 736 | return ret; | ||
| 737 | } | ||
| 738 | module_init(wm8770_modinit); | ||
| 739 | |||
| 740 | static void __exit wm8770_exit(void) | ||
| 741 | { | ||
| 742 | spi_unregister_driver(&wm8770_spi_driver); | ||
| 743 | } | ||
| 744 | module_exit(wm8770_exit); | ||
| 745 | 728 | ||
| 746 | MODULE_DESCRIPTION("ASoC WM8770 driver"); | 729 | MODULE_DESCRIPTION("ASoC WM8770 driver"); |
| 747 | MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>"); | 730 | MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>"); |
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 879c356a9045..c32249ddb2e0 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
| 20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
| 21 | #include <linux/of_device.h> | 21 | #include <linux/of_device.h> |
| 22 | #include <linux/regmap.h> | ||
| 22 | #include <linux/spi/spi.h> | 23 | #include <linux/spi/spi.h> |
| 23 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
| 24 | #include <sound/core.h> | 25 | #include <sound/core.h> |
| @@ -37,18 +38,46 @@ enum wm8776_chip_type { | |||
| 37 | 38 | ||
| 38 | /* codec private data */ | 39 | /* codec private data */ |
| 39 | struct wm8776_priv { | 40 | struct wm8776_priv { |
| 40 | enum snd_soc_control_type control_type; | 41 | struct regmap *regmap; |
| 41 | int sysclk[2]; | 42 | int sysclk[2]; |
| 42 | }; | 43 | }; |
| 43 | 44 | ||
| 44 | static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { | 45 | static const struct reg_default wm8776_reg_defaults[] = { |
| 45 | 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ | 46 | { 0, 0x79 }, |
| 46 | 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ | 47 | { 1, 0x79 }, |
| 47 | 0x22, 0x22, 0x22, 0x08, 0xcf, /* 14 */ | 48 | { 2, 0x79 }, |
| 48 | 0xcf, 0x7b, 0x00, 0x32, 0x00, /* 19 */ | 49 | { 3, 0xff }, |
| 49 | 0xa6, 0x01, 0x01 | 50 | { 4, 0xff }, |
| 51 | { 5, 0xff }, | ||
| 52 | { 6, 0x00 }, | ||
| 53 | { 7, 0x90 }, | ||
| 54 | { 8, 0x00 }, | ||
| 55 | { 9, 0x00 }, | ||
| 56 | { 10, 0x22 }, | ||
| 57 | { 11, 0x22 }, | ||
| 58 | { 12, 0x22 }, | ||
| 59 | { 13, 0x08 }, | ||
| 60 | { 14, 0xcf }, | ||
| 61 | { 15, 0xcf }, | ||
| 62 | { 16, 0x7b }, | ||
| 63 | { 17, 0x00 }, | ||
| 64 | { 18, 0x32 }, | ||
| 65 | { 19, 0x00 }, | ||
| 66 | { 20, 0xa6 }, | ||
| 67 | { 21, 0x01 }, | ||
| 68 | { 22, 0x01 }, | ||
| 50 | }; | 69 | }; |
| 51 | 70 | ||
| 71 | static bool wm8776_volatile(struct device *dev, unsigned int reg) | ||
| 72 | { | ||
| 73 | switch (reg) { | ||
| 74 | case WM8776_RESET: | ||
| 75 | return true; | ||
| 76 | default: | ||
| 77 | return false; | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 52 | static int wm8776_reset(struct snd_soc_codec *codec) | 81 | static int wm8776_reset(struct snd_soc_codec *codec) |
| 53 | { | 82 | { |
| 54 | return snd_soc_write(codec, WM8776_RESET, 0); | 83 | return snd_soc_write(codec, WM8776_RESET, 0); |
| @@ -306,6 +335,8 @@ static int wm8776_set_sysclk(struct snd_soc_dai *dai, | |||
| 306 | static int wm8776_set_bias_level(struct snd_soc_codec *codec, | 335 | static int wm8776_set_bias_level(struct snd_soc_codec *codec, |
| 307 | enum snd_soc_bias_level level) | 336 | enum snd_soc_bias_level level) |
| 308 | { | 337 | { |
| 338 | struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); | ||
| 339 | |||
| 309 | switch (level) { | 340 | switch (level) { |
| 310 | case SND_SOC_BIAS_ON: | 341 | case SND_SOC_BIAS_ON: |
| 311 | break; | 342 | break; |
| @@ -313,7 +344,7 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec, | |||
| 313 | break; | 344 | break; |
| 314 | case SND_SOC_BIAS_STANDBY: | 345 | case SND_SOC_BIAS_STANDBY: |
| 315 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 346 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
| 316 | snd_soc_cache_sync(codec); | 347 | regcache_sync(wm8776->regmap); |
| 317 | 348 | ||
| 318 | /* Disable the global powerdown; DAPM does the rest */ | 349 | /* Disable the global powerdown; DAPM does the rest */ |
| 319 | snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); | 350 | snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); |
| @@ -396,10 +427,9 @@ static int wm8776_resume(struct snd_soc_codec *codec) | |||
| 396 | 427 | ||
| 397 | static int wm8776_probe(struct snd_soc_codec *codec) | 428 | static int wm8776_probe(struct snd_soc_codec *codec) |
| 398 | { | 429 | { |
| 399 | struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); | ||
| 400 | int ret = 0; | 430 | int ret = 0; |
| 401 | 431 | ||
| 402 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type); | 432 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
| 403 | if (ret < 0) { | 433 | if (ret < 0) { |
| 404 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 434 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
| 405 | return ret; | 435 | return ret; |
| @@ -434,9 +464,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { | |||
| 434 | .suspend = wm8776_suspend, | 464 | .suspend = wm8776_suspend, |
| 435 | .resume = wm8776_resume, | 465 | .resume = wm8776_resume, |
| 436 | .set_bias_level = wm8776_set_bias_level, | 466 | .set_bias_level = wm8776_set_bias_level, |
| 437 | .reg_cache_size = ARRAY_SIZE(wm8776_reg), | ||
| 438 | .reg_word_size = sizeof(u16), | ||
| 439 | .reg_cache_default = wm8776_reg, | ||
| 440 | 467 | ||
| 441 | .controls = wm8776_snd_controls, | 468 | .controls = wm8776_snd_controls, |
| 442 | .num_controls = ARRAY_SIZE(wm8776_snd_controls), | 469 | .num_controls = ARRAY_SIZE(wm8776_snd_controls), |
| @@ -452,6 +479,18 @@ static const struct of_device_id wm8776_of_match[] = { | |||
| 452 | }; | 479 | }; |
| 453 | MODULE_DEVICE_TABLE(of, wm8776_of_match); | 480 | MODULE_DEVICE_TABLE(of, wm8776_of_match); |
| 454 | 481 | ||
| 482 | static const struct regmap_config wm8776_regmap = { | ||
| 483 | .reg_bits = 7, | ||
| 484 | .val_bits = 9, | ||
| 485 | .max_register = WM8776_RESET, | ||
| 486 | |||
| 487 | .reg_defaults = wm8776_reg_defaults, | ||
| 488 | .num_reg_defaults = ARRAY_SIZE(wm8776_reg_defaults), | ||
| 489 | .cache_type = REGCACHE_RBTREE, | ||
| 490 | |||
| 491 | .volatile_reg = wm8776_volatile, | ||
| 492 | }; | ||
| 493 | |||
| 455 | #if defined(CONFIG_SPI_MASTER) | 494 | #if defined(CONFIG_SPI_MASTER) |
| 456 | static int __devinit wm8776_spi_probe(struct spi_device *spi) | 495 | static int __devinit wm8776_spi_probe(struct spi_device *spi) |
| 457 | { | 496 | { |
| @@ -463,7 +502,10 @@ static int __devinit wm8776_spi_probe(struct spi_device *spi) | |||
| 463 | if (wm8776 == NULL) | 502 | if (wm8776 == NULL) |
| 464 | return -ENOMEM; | 503 | return -ENOMEM; |
| 465 | 504 | ||
| 466 | wm8776->control_type = SND_SOC_SPI; | 505 | wm8776->regmap = devm_regmap_init_spi(spi, &wm8776_regmap); |
| 506 | if (IS_ERR(wm8776->regmap)) | ||
| 507 | return PTR_ERR(wm8776->regmap); | ||
| 508 | |||
| 467 | spi_set_drvdata(spi, wm8776); | 509 | spi_set_drvdata(spi, wm8776); |
| 468 | 510 | ||
| 469 | ret = snd_soc_register_codec(&spi->dev, | 511 | ret = snd_soc_register_codec(&spi->dev, |
| @@ -501,8 +543,11 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c, | |||
| 501 | if (wm8776 == NULL) | 543 | if (wm8776 == NULL) |
| 502 | return -ENOMEM; | 544 | return -ENOMEM; |
| 503 | 545 | ||
| 546 | wm8776->regmap = devm_regmap_init_i2c(i2c, &wm8776_regmap); | ||
| 547 | if (IS_ERR(wm8776->regmap)) | ||
| 548 | return PTR_ERR(wm8776->regmap); | ||
| 549 | |||
| 504 | i2c_set_clientdata(i2c, wm8776); | 550 | i2c_set_clientdata(i2c, wm8776); |
| 505 | wm8776->control_type = SND_SOC_I2C; | ||
| 506 | 551 | ||
| 507 | ret = snd_soc_register_codec(&i2c->dev, | 552 | ret = snd_soc_register_codec(&i2c->dev, |
| 508 | &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); | 553 | &soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai)); |
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 077c9628c70d..e781f865e5d7 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
| 24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
| 25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
| 26 | #include <linux/regmap.h> | ||
| 26 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
| 27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
| @@ -137,7 +138,7 @@ | |||
| 137 | #define WM8900_LRC_MASK 0x03ff | 138 | #define WM8900_LRC_MASK 0x03ff |
| 138 | 139 | ||
| 139 | struct wm8900_priv { | 140 | struct wm8900_priv { |
| 140 | enum snd_soc_control_type control_type; | 141 | struct regmap *regmap; |
| 141 | 142 | ||
| 142 | u32 fll_in; /* FLL input frequency */ | 143 | u32 fll_in; /* FLL input frequency */ |
| 143 | u32 fll_out; /* FLL output frequency */ | 144 | u32 fll_out; /* FLL output frequency */ |
| @@ -147,54 +148,77 @@ struct wm8900_priv { | |||
| 147 | * wm8900 register cache. We can't read the entire register space and we | 148 | * wm8900 register cache. We can't read the entire register space and we |
| 148 | * have slow control buses so we cache the registers. | 149 | * have slow control buses so we cache the registers. |
| 149 | */ | 150 | */ |
| 150 | static const u16 wm8900_reg_defaults[WM8900_MAXREG] = { | 151 | static const struct reg_default wm8900_reg_defaults[] = { |
| 151 | 0x8900, 0x0000, | 152 | { 1, 0x0000 }, |
| 152 | 0xc000, 0x0000, | 153 | { 2, 0xc000 }, |
| 153 | 0x4050, 0x4000, | 154 | { 3, 0x0000 }, |
| 154 | 0x0008, 0x0000, | 155 | { 4, 0x4050 }, |
| 155 | 0x0040, 0x0040, | 156 | { 5, 0x4000 }, |
| 156 | 0x1004, 0x00c0, | 157 | { 6, 0x0008 }, |
| 157 | 0x00c0, 0x0000, | 158 | { 7, 0x0000 }, |
| 158 | 0x0100, 0x00c0, | 159 | { 8, 0x0040 }, |
| 159 | 0x00c0, 0x0000, | 160 | { 9, 0x0040 }, |
| 160 | 0xb001, 0x0000, | 161 | { 10, 0x1004 }, |
| 161 | 0x0000, 0x0044, | 162 | { 11, 0x00c0 }, |
| 162 | 0x004c, 0x004c, | 163 | { 12, 0x00c0 }, |
| 163 | 0x0044, 0x0044, | 164 | { 13, 0x0000 }, |
| 164 | 0x0000, 0x0044, | 165 | { 14, 0x0100 }, |
| 165 | 0x0000, 0x0000, | 166 | { 15, 0x00c0 }, |
| 166 | 0x0002, 0x0000, | 167 | { 16, 0x00c0 }, |
| 167 | 0x0000, 0x0000, | 168 | { 17, 0x0000 }, |
| 168 | 0x0000, 0x0000, | 169 | { 18, 0xb001 }, |
| 169 | 0x0008, 0x0000, | 170 | { 19, 0x0000 }, |
| 170 | 0x0000, 0x0008, | 171 | { 20, 0x0000 }, |
| 171 | 0x0097, 0x0100, | 172 | { 21, 0x0044 }, |
| 172 | 0x0000, 0x0000, | 173 | { 22, 0x004c }, |
| 173 | 0x0050, 0x0050, | 174 | { 23, 0x004c }, |
| 174 | 0x0055, 0x0055, | 175 | { 24, 0x0044 }, |
| 175 | 0x0055, 0x0000, | 176 | { 25, 0x0044 }, |
| 176 | 0x0000, 0x0079, | 177 | { 26, 0x0000 }, |
| 177 | 0x0079, 0x0079, | 178 | { 27, 0x0044 }, |
| 178 | 0x0079, 0x0000, | 179 | { 28, 0x0000 }, |
| 179 | /* Remaining registers all zero */ | 180 | { 29, 0x0000 }, |
| 181 | { 30, 0x0002 }, | ||
| 182 | { 31, 0x0000 }, | ||
| 183 | { 32, 0x0000 }, | ||
| 184 | { 33, 0x0000 }, | ||
| 185 | { 34, 0x0000 }, | ||
| 186 | { 35, 0x0000 }, | ||
| 187 | { 36, 0x0008 }, | ||
| 188 | { 37, 0x0000 }, | ||
| 189 | { 38, 0x0000 }, | ||
| 190 | { 39, 0x0008 }, | ||
| 191 | { 40, 0x0097 }, | ||
| 192 | { 41, 0x0100 }, | ||
| 193 | { 42, 0x0000 }, | ||
| 194 | { 43, 0x0000 }, | ||
| 195 | { 44, 0x0050 }, | ||
| 196 | { 45, 0x0050 }, | ||
| 197 | { 46, 0x0055 }, | ||
| 198 | { 47, 0x0055 }, | ||
| 199 | { 48, 0x0055 }, | ||
| 200 | { 49, 0x0000 }, | ||
| 201 | { 50, 0x0000 }, | ||
| 202 | { 51, 0x0079 }, | ||
| 203 | { 52, 0x0079 }, | ||
| 204 | { 53, 0x0079 }, | ||
| 205 | { 54, 0x0079 }, | ||
| 206 | { 55, 0x0000 }, | ||
| 180 | }; | 207 | }; |
| 181 | 208 | ||
| 182 | static int wm8900_volatile_register(struct snd_soc_codec *codec, unsigned int reg) | 209 | static bool wm8900_volatile_register(struct device *dev, unsigned int reg) |
| 183 | { | 210 | { |
| 184 | switch (reg) { | 211 | switch (reg) { |
| 185 | case WM8900_REG_ID: | 212 | case WM8900_REG_ID: |
| 186 | return 1; | 213 | return true; |
| 187 | default: | 214 | default: |
| 188 | return 0; | 215 | return false; |
| 189 | } | 216 | } |
| 190 | } | 217 | } |
| 191 | 218 | ||
| 192 | static void wm8900_reset(struct snd_soc_codec *codec) | 219 | static void wm8900_reset(struct snd_soc_codec *codec) |
| 193 | { | 220 | { |
| 194 | snd_soc_write(codec, WM8900_REG_RESET, 0); | 221 | snd_soc_write(codec, WM8900_REG_RESET, 0); |
| 195 | |||
| 196 | memcpy(codec->reg_cache, wm8900_reg_defaults, | ||
| 197 | sizeof(wm8900_reg_defaults)); | ||
| 198 | } | 222 | } |
| 199 | 223 | ||
| 200 | static int wm8900_hp_event(struct snd_soc_dapm_widget *w, | 224 | static int wm8900_hp_event(struct snd_soc_dapm_widget *w, |
| @@ -469,10 +493,10 @@ SOC_DAPM_SINGLE("RINPUT2 Switch", WM8900_REG_INCTL, 1, 1, 0), | |||
| 469 | SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0), | 493 | SOC_DAPM_SINGLE("RINPUT3 Switch", WM8900_REG_INCTL, 0, 1, 0), |
| 470 | }; | 494 | }; |
| 471 | 495 | ||
| 472 | static const char *wm9700_lp_mux[] = { "Disabled", "Enabled" }; | 496 | static const char *wm8900_lp_mux[] = { "Disabled", "Enabled" }; |
| 473 | 497 | ||
| 474 | static const struct soc_enum wm8900_lineout2_lp_mux = | 498 | static const struct soc_enum wm8900_lineout2_lp_mux = |
| 475 | SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm9700_lp_mux); | 499 | SOC_ENUM_SINGLE(WM8900_REG_LOUTMIXCTL1, 1, 2, wm8900_lp_mux); |
| 476 | 500 | ||
| 477 | static const struct snd_kcontrol_new wm8900_lineout2_lp = | 501 | static const struct snd_kcontrol_new wm8900_lineout2_lp = |
| 478 | SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux); | 502 | SOC_DAPM_ENUM("Route", wm8900_lineout2_lp_mux); |
| @@ -1119,13 +1143,16 @@ static int wm8900_suspend(struct snd_soc_codec *codec) | |||
| 1119 | static int wm8900_resume(struct snd_soc_codec *codec) | 1143 | static int wm8900_resume(struct snd_soc_codec *codec) |
| 1120 | { | 1144 | { |
| 1121 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); | 1145 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); |
| 1122 | u16 *cache; | 1146 | int ret; |
| 1123 | int i, ret; | ||
| 1124 | |||
| 1125 | cache = kmemdup(codec->reg_cache, sizeof(wm8900_reg_defaults), | ||
| 1126 | GFP_KERNEL); | ||
| 1127 | 1147 | ||
| 1128 | wm8900_reset(codec); | 1148 | wm8900_reset(codec); |
| 1149 | |||
| 1150 | ret = regcache_sync(wm8900->regmap); | ||
| 1151 | if (ret != 0) { | ||
| 1152 | dev_err(codec->dev, "Failed to restore cache: %d\n", ret); | ||
| 1153 | return ret; | ||
| 1154 | } | ||
| 1155 | |||
| 1129 | wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1156 | wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
| 1130 | 1157 | ||
| 1131 | /* Restart the FLL? */ | 1158 | /* Restart the FLL? */ |
| @@ -1139,27 +1166,18 @@ static int wm8900_resume(struct snd_soc_codec *codec) | |||
| 1139 | ret = wm8900_set_fll(codec, 0, fll_in, fll_out); | 1166 | ret = wm8900_set_fll(codec, 0, fll_in, fll_out); |
| 1140 | if (ret != 0) { | 1167 | if (ret != 0) { |
| 1141 | dev_err(codec->dev, "Failed to restart FLL\n"); | 1168 | dev_err(codec->dev, "Failed to restart FLL\n"); |
| 1142 | kfree(cache); | ||
| 1143 | return ret; | 1169 | return ret; |
| 1144 | } | 1170 | } |
| 1145 | } | 1171 | } |
| 1146 | 1172 | ||
| 1147 | if (cache) { | ||
| 1148 | for (i = 0; i < WM8900_MAXREG; i++) | ||
| 1149 | snd_soc_write(codec, i, cache[i]); | ||
| 1150 | kfree(cache); | ||
| 1151 | } else | ||
| 1152 | dev_err(codec->dev, "Unable to allocate register cache\n"); | ||
| 1153 | |||
| 1154 | return 0; | 1173 | return 0; |
| 1155 | } | 1174 | } |
| 1156 | 1175 | ||
| 1157 | static int wm8900_probe(struct snd_soc_codec *codec) | 1176 | static int wm8900_probe(struct snd_soc_codec *codec) |
| 1158 | { | 1177 | { |
| 1159 | struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec); | ||
| 1160 | int ret = 0, reg; | 1178 | int ret = 0, reg; |
| 1161 | 1179 | ||
| 1162 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8900->control_type); | 1180 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); |
| 1163 | if (ret != 0) { | 1181 | if (ret != 0) { |
| 1164 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 1182 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
| 1165 | return ret; | 1183 | return ret; |
| @@ -1207,10 +1225,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { | |||
| 1207 | .suspend = wm8900_suspend, | 1225 | .suspend = wm8900_suspend, |
| 1208 | .resume = wm8900_resume, | 1226 | .resume = wm8900_resume, |
| 1209 | .set_bias_level = wm8900_set_bias_level, | 1227 | .set_bias_level = wm8900_set_bias_level, |
| 1210 | .volatile_register = wm8900_volatile_register, | ||
| 1211 | .reg_cache_size = ARRAY_SIZE(wm8900_reg_defaults), | ||
| 1212 | .reg_word_size = sizeof(u16), | ||
| 1213 | .reg_cache_default = wm8900_reg_defaults, | ||
| 1214 | 1228 | ||
| 1215 | .controls = wm8900_snd_controls, | 1229 | .controls = wm8900_snd_controls, |
| 1216 | .num_controls = ARRAY_SIZE(wm8900_snd_controls), | 1230 | .num_controls = ARRAY_SIZE(wm8900_snd_controls), |
| @@ -1220,30 +1234,44 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8900 = { | |||
| 1220 | .num_dapm_routes = ARRAY_SIZE(wm8900_dapm_routes), | 1234 | .num_dapm_routes = ARRAY_SIZE(wm8900_dapm_routes), |
| 1221 | }; | 1235 | }; |
| 1222 | 1236 | ||
| 1237 | static const struct regmap_config wm8900_regmap = { | ||
| 1238 | .reg_bits = 8, | ||
| 1239 | .val_bits = 16, | ||
| 1240 | .max_register = WM8900_MAXREG, | ||
| 1241 | |||
| 1242 | .reg_defaults = wm8900_reg_defaults, | ||
| 1243 | .num_reg_defaults = ARRAY_SIZE(wm8900_reg_defaults), | ||
| 1244 | .cache_type = REGCACHE_RBTREE, | ||
| 1245 | |||
| 1246 | .volatile_reg = wm8900_volatile_register, | ||
| 1247 | }; | ||
| 1248 | |||
| 1223 | #if defined(CONFIG_SPI_MASTER) | 1249 | #if defined(CONFIG_SPI_MASTER) |
| 1224 | static int __devinit wm8900_spi_probe(struct spi_device *spi) | 1250 | static int __devinit wm8900_spi_probe(struct spi_device *spi) |
| 1225 | { | 1251 | { |
| 1226 | struct wm8900_priv *wm8900; | 1252 | struct wm8900_priv *wm8900; |
| 1227 | int ret; | 1253 | int ret; |
| 1228 | 1254 | ||
| 1229 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | 1255 | wm8900 = devm_kzalloc(&spi->dev, sizeof(struct wm8900_priv), |
| 1256 | GFP_KERNEL); | ||
| 1230 | if (wm8900 == NULL) | 1257 | if (wm8900 == NULL) |
| 1231 | return -ENOMEM; | 1258 | return -ENOMEM; |
| 1232 | 1259 | ||
| 1233 | wm8900->control_type = SND_SOC_SPI; | 1260 | wm8900->regmap = devm_regmap_init_spi(spi, &wm8900_regmap); |
| 1261 | if (IS_ERR(wm8900->regmap)) | ||
| 1262 | return PTR_ERR(wm8900->regmap); | ||
| 1263 | |||
| 1234 | spi_set_drvdata(spi, wm8900); | 1264 | spi_set_drvdata(spi, wm8900); |
| 1235 | 1265 | ||
| 1236 | ret = snd_soc_register_codec(&spi->dev, | 1266 | ret = snd_soc_register_codec(&spi->dev, |
| 1237 | &soc_codec_dev_wm8900, &wm8900_dai, 1); | 1267 | &soc_codec_dev_wm8900, &wm8900_dai, 1); |
| 1238 | if (ret < 0) | 1268 | |
| 1239 | kfree(wm8900); | ||
| 1240 | return ret; | 1269 | return ret; |
| 1241 | } | 1270 | } |
| 1242 | 1271 | ||
| 1243 | static int __devexit wm8900_spi_remove(struct spi_device *spi) | 1272 | static int __devexit wm8900_spi_remove(struct spi_device *spi) |
| 1244 | { | 1273 | { |
| 1245 | snd_soc_unregister_codec(&spi->dev); | 1274 | snd_soc_unregister_codec(&spi->dev); |
| 1246 | kfree(spi_get_drvdata(spi)); | ||
| 1247 | return 0; | 1275 | return 0; |
| 1248 | } | 1276 | } |
| 1249 | 1277 | ||
| @@ -1264,24 +1292,26 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c, | |||
| 1264 | struct wm8900_priv *wm8900; | 1292 | struct wm8900_priv *wm8900; |
| 1265 | int ret; | 1293 | int ret; |
| 1266 | 1294 | ||
| 1267 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | 1295 | wm8900 = devm_kzalloc(&i2c->dev, sizeof(struct wm8900_priv), |
| 1296 | GFP_KERNEL); | ||
| 1268 | if (wm8900 == NULL) | 1297 | if (wm8900 == NULL) |
| 1269 | return -ENOMEM; | 1298 | return -ENOMEM; |
| 1270 | 1299 | ||
| 1300 | wm8900->regmap = devm_regmap_init_i2c(i2c, &wm8900_regmap); | ||
| 1301 | if (IS_ERR(wm8900->regmap)) | ||
| 1302 | return PTR_ERR(wm8900->regmap); | ||
| 1303 | |||
| 1271 | i2c_set_clientdata(i2c, wm8900); | 1304 | i2c_set_clientdata(i2c, wm8900); |
| 1272 | wm8900->control_type = SND_SOC_I2C; | ||
| 1273 | 1305 | ||
| 1274 | ret = snd_soc_register_codec(&i2c->dev, | 1306 | ret = snd_soc_register_codec(&i2c->dev, |
| 1275 | &soc_codec_dev_wm8900, &wm8900_dai, 1); | 1307 | &soc_codec_dev_wm8900, &wm8900_dai, 1); |
| 1276 | if (ret < 0) | 1308 | |
| 1277 | kfree(wm8900); | ||
| 1278 | return ret; | 1309 | return ret; |
| 1279 | } | 1310 | } |
| 1280 | 1311 | ||
| 1281 | static __devexit int wm8900_i2c_remove(struct i2c_client *client) | 1312 | static __devexit int wm8900_i2c_remove(struct i2c_client *client) |
| 1282 | { | 1313 | { |
| 1283 | snd_soc_unregister_codec(&client->dev); | 1314 | snd_soc_unregister_codec(&client->dev); |
| 1284 | kfree(i2c_get_clientdata(client)); | ||
| 1285 | return 0; | 1315 | return 0; |
| 1286 | } | 1316 | } |
| 1287 | 1317 | ||
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 73f1c8d7bafb..839414f9e2ed 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
| @@ -2241,23 +2241,7 @@ static struct i2c_driver wm8903_i2c_driver = { | |||
| 2241 | .id_table = wm8903_i2c_id, | 2241 | .id_table = wm8903_i2c_id, |
| 2242 | }; | 2242 | }; |
| 2243 | 2243 | ||
| 2244 | static int __init wm8903_modinit(void) | 2244 | module_i2c_driver(wm8903_i2c_driver); |
| 2245 | { | ||
| 2246 | int ret = 0; | ||
| 2247 | ret = i2c_add_driver(&wm8903_i2c_driver); | ||
| 2248 | if (ret != 0) { | ||
| 2249 | printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n", | ||
| 2250 | ret); | ||
| 2251 | } | ||
| 2252 | return ret; | ||
| 2253 | } | ||
| 2254 | module_init(wm8903_modinit); | ||
| 2255 | |||
| 2256 | static void __exit wm8903_exit(void) | ||
| 2257 | { | ||
| 2258 | i2c_del_driver(&wm8903_i2c_driver); | ||
| 2259 | } | ||
| 2260 | module_exit(wm8903_exit); | ||
| 2261 | 2245 | ||
| 2262 | MODULE_DESCRIPTION("ASoC WM8903 driver"); | 2246 | MODULE_DESCRIPTION("ASoC WM8903 driver"); |
| 2263 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>"); | 2247 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>"); |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index dc4262eea4b7..7c8df52a8d9d 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
| @@ -1185,8 +1185,6 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec) | |||
| 1185 | snd_soc_dapm_new_controls(dapm, wm8904_dapm_widgets, | 1185 | snd_soc_dapm_new_controls(dapm, wm8904_dapm_widgets, |
| 1186 | ARRAY_SIZE(wm8904_dapm_widgets)); | 1186 | ARRAY_SIZE(wm8904_dapm_widgets)); |
| 1187 | 1187 | ||
| 1188 | snd_soc_dapm_add_routes(dapm, core_intercon, | ||
| 1189 | ARRAY_SIZE(core_intercon)); | ||
| 1190 | snd_soc_dapm_add_routes(dapm, adc_intercon, | 1188 | snd_soc_dapm_add_routes(dapm, adc_intercon, |
| 1191 | ARRAY_SIZE(adc_intercon)); | 1189 | ARRAY_SIZE(adc_intercon)); |
| 1192 | snd_soc_dapm_add_routes(dapm, dac_intercon, | 1190 | snd_soc_dapm_add_routes(dapm, dac_intercon, |
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 481a3d9cfe48..b20aa4e7c3f9 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
| @@ -785,23 +785,7 @@ static struct i2c_driver wm8940_i2c_driver = { | |||
| 785 | .id_table = wm8940_i2c_id, | 785 | .id_table = wm8940_i2c_id, |
| 786 | }; | 786 | }; |
| 787 | 787 | ||
| 788 | static int __init wm8940_modinit(void) | 788 | module_i2c_driver(wm8940_i2c_driver); |
| 789 | { | ||
| 790 | int ret = 0; | ||
| 791 | ret = i2c_add_driver(&wm8940_i2c_driver); | ||
| 792 | if (ret != 0) { | ||
| 793 | printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n", | ||
| 794 | ret); | ||
| 795 | } | ||
| 796 | return ret; | ||
| 797 | } | ||
| 798 | module_init(wm8940_modinit); | ||
| 799 | |||
| 800 | static void __exit wm8940_exit(void) | ||
| 801 | { | ||
| 802 | i2c_del_driver(&wm8940_i2c_driver); | ||
| 803 | } | ||
| 804 | module_exit(wm8940_exit); | ||
| 805 | 789 | ||
| 806 | MODULE_DESCRIPTION("ASoC WM8940 driver"); | 790 | MODULE_DESCRIPTION("ASoC WM8940 driver"); |
| 807 | MODULE_AUTHOR("Jonathan Cameron"); | 791 | MODULE_AUTHOR("Jonathan Cameron"); |
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 61fe97433e73..2f1c075755b1 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c | |||
| @@ -1071,23 +1071,7 @@ static struct i2c_driver wm8955_i2c_driver = { | |||
| 1071 | .id_table = wm8955_i2c_id, | 1071 | .id_table = wm8955_i2c_id, |
| 1072 | }; | 1072 | }; |
| 1073 | 1073 | ||
| 1074 | static int __init wm8955_modinit(void) | 1074 | module_i2c_driver(wm8955_i2c_driver); |
| 1075 | { | ||
| 1076 | int ret = 0; | ||
| 1077 | ret = i2c_add_driver(&wm8955_i2c_driver); | ||
| 1078 | if (ret != 0) { | ||
| 1079 | printk(KERN_ERR "Failed to register WM8955 I2C driver: %d\n", | ||
| 1080 | ret); | ||
| 1081 | } | ||
| 1082 | return ret; | ||
| 1083 | } | ||
| 1084 | module_init(wm8955_modinit); | ||
| 1085 | |||
| 1086 | static void __exit wm8955_exit(void) | ||
| 1087 | { | ||
| 1088 | i2c_del_driver(&wm8955_i2c_driver); | ||
| 1089 | } | ||
| 1090 | module_exit(wm8955_exit); | ||
| 1091 | 1075 | ||
| 1092 | MODULE_DESCRIPTION("ASoC WM8955 driver"); | 1076 | MODULE_DESCRIPTION("ASoC WM8955 driver"); |
| 1093 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 1077 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 1332692ef81b..00121ba36597 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c | |||
| @@ -946,7 +946,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
| 946 | wm8994->mbc_texts = kmalloc(sizeof(char *) | 946 | wm8994->mbc_texts = kmalloc(sizeof(char *) |
| 947 | * pdata->num_mbc_cfgs, GFP_KERNEL); | 947 | * pdata->num_mbc_cfgs, GFP_KERNEL); |
| 948 | if (!wm8994->mbc_texts) { | 948 | if (!wm8994->mbc_texts) { |
| 949 | dev_err(wm8994->codec->dev, | 949 | dev_err(wm8994->hubs.codec->dev, |
| 950 | "Failed to allocate %d MBC config texts\n", | 950 | "Failed to allocate %d MBC config texts\n", |
| 951 | pdata->num_mbc_cfgs); | 951 | pdata->num_mbc_cfgs); |
| 952 | return; | 952 | return; |
| @@ -958,9 +958,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
| 958 | wm8994->mbc_enum.max = pdata->num_mbc_cfgs; | 958 | wm8994->mbc_enum.max = pdata->num_mbc_cfgs; |
| 959 | wm8994->mbc_enum.texts = wm8994->mbc_texts; | 959 | wm8994->mbc_enum.texts = wm8994->mbc_texts; |
| 960 | 960 | ||
| 961 | ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); | 961 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
| 962 | control, 1); | ||
| 962 | if (ret != 0) | 963 | if (ret != 0) |
| 963 | dev_err(wm8994->codec->dev, | 964 | dev_err(wm8994->hubs.codec->dev, |
| 964 | "Failed to add MBC mode controls: %d\n", ret); | 965 | "Failed to add MBC mode controls: %d\n", ret); |
| 965 | } | 966 | } |
| 966 | 967 | ||
| @@ -974,7 +975,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
| 974 | wm8994->vss_texts = kmalloc(sizeof(char *) | 975 | wm8994->vss_texts = kmalloc(sizeof(char *) |
| 975 | * pdata->num_vss_cfgs, GFP_KERNEL); | 976 | * pdata->num_vss_cfgs, GFP_KERNEL); |
| 976 | if (!wm8994->vss_texts) { | 977 | if (!wm8994->vss_texts) { |
| 977 | dev_err(wm8994->codec->dev, | 978 | dev_err(wm8994->hubs.codec->dev, |
| 978 | "Failed to allocate %d VSS config texts\n", | 979 | "Failed to allocate %d VSS config texts\n", |
| 979 | pdata->num_vss_cfgs); | 980 | pdata->num_vss_cfgs); |
| 980 | return; | 981 | return; |
| @@ -986,9 +987,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
| 986 | wm8994->vss_enum.max = pdata->num_vss_cfgs; | 987 | wm8994->vss_enum.max = pdata->num_vss_cfgs; |
| 987 | wm8994->vss_enum.texts = wm8994->vss_texts; | 988 | wm8994->vss_enum.texts = wm8994->vss_texts; |
| 988 | 989 | ||
| 989 | ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); | 990 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
| 991 | control, 1); | ||
| 990 | if (ret != 0) | 992 | if (ret != 0) |
| 991 | dev_err(wm8994->codec->dev, | 993 | dev_err(wm8994->hubs.codec->dev, |
| 992 | "Failed to add VSS mode controls: %d\n", ret); | 994 | "Failed to add VSS mode controls: %d\n", ret); |
| 993 | } | 995 | } |
| 994 | 996 | ||
| @@ -1003,7 +1005,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
| 1003 | wm8994->vss_hpf_texts = kmalloc(sizeof(char *) | 1005 | wm8994->vss_hpf_texts = kmalloc(sizeof(char *) |
| 1004 | * pdata->num_vss_hpf_cfgs, GFP_KERNEL); | 1006 | * pdata->num_vss_hpf_cfgs, GFP_KERNEL); |
| 1005 | if (!wm8994->vss_hpf_texts) { | 1007 | if (!wm8994->vss_hpf_texts) { |
| 1006 | dev_err(wm8994->codec->dev, | 1008 | dev_err(wm8994->hubs.codec->dev, |
| 1007 | "Failed to allocate %d VSS HPF config texts\n", | 1009 | "Failed to allocate %d VSS HPF config texts\n", |
| 1008 | pdata->num_vss_hpf_cfgs); | 1010 | pdata->num_vss_hpf_cfgs); |
| 1009 | return; | 1011 | return; |
| @@ -1015,9 +1017,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
| 1015 | wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs; | 1017 | wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs; |
| 1016 | wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; | 1018 | wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; |
| 1017 | 1019 | ||
| 1018 | ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); | 1020 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
| 1021 | control, 1); | ||
| 1019 | if (ret != 0) | 1022 | if (ret != 0) |
| 1020 | dev_err(wm8994->codec->dev, | 1023 | dev_err(wm8994->hubs.codec->dev, |
| 1021 | "Failed to add VSS HPFmode controls: %d\n", | 1024 | "Failed to add VSS HPFmode controls: %d\n", |
| 1022 | ret); | 1025 | ret); |
| 1023 | } | 1026 | } |
| @@ -1033,7 +1036,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
| 1033 | wm8994->enh_eq_texts = kmalloc(sizeof(char *) | 1036 | wm8994->enh_eq_texts = kmalloc(sizeof(char *) |
| 1034 | * pdata->num_enh_eq_cfgs, GFP_KERNEL); | 1037 | * pdata->num_enh_eq_cfgs, GFP_KERNEL); |
| 1035 | if (!wm8994->enh_eq_texts) { | 1038 | if (!wm8994->enh_eq_texts) { |
| 1036 | dev_err(wm8994->codec->dev, | 1039 | dev_err(wm8994->hubs.codec->dev, |
| 1037 | "Failed to allocate %d enhanced EQ config texts\n", | 1040 | "Failed to allocate %d enhanced EQ config texts\n", |
| 1038 | pdata->num_enh_eq_cfgs); | 1041 | pdata->num_enh_eq_cfgs); |
| 1039 | return; | 1042 | return; |
| @@ -1045,9 +1048,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
| 1045 | wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs; | 1048 | wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs; |
| 1046 | wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; | 1049 | wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; |
| 1047 | 1050 | ||
| 1048 | ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); | 1051 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
| 1052 | control, 1); | ||
| 1049 | if (ret != 0) | 1053 | if (ret != 0) |
| 1050 | dev_err(wm8994->codec->dev, | 1054 | dev_err(wm8994->hubs.codec->dev, |
| 1051 | "Failed to add enhanced EQ controls: %d\n", | 1055 | "Failed to add enhanced EQ controls: %d\n", |
| 1052 | ret); | 1056 | ret); |
| 1053 | } | 1057 | } |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 96518ac8e24c..f0f6f6601785 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
| @@ -52,25 +52,72 @@ | |||
| 52 | * We can't read the WM8960 register space when we are | 52 | * We can't read the WM8960 register space when we are |
| 53 | * using 2 wire for device control, so we cache them instead. | 53 | * using 2 wire for device control, so we cache them instead. |
| 54 | */ | 54 | */ |
| 55 | static const u16 wm8960_reg[WM8960_CACHEREGNUM] = { | 55 | static const struct reg_default wm8960_reg_defaults[] = { |
| 56 | 0x0097, 0x0097, 0x0000, 0x0000, | 56 | { 0x0, 0x0097 }, |
| 57 | 0x0000, 0x0008, 0x0000, 0x000a, | 57 | { 0x1, 0x0097 }, |
| 58 | 0x01c0, 0x0000, 0x00ff, 0x00ff, | 58 | { 0x2, 0x0000 }, |
| 59 | 0x0000, 0x0000, 0x0000, 0x0000, | 59 | { 0x3, 0x0000 }, |
| 60 | 0x0000, 0x007b, 0x0100, 0x0032, | 60 | { 0x4, 0x0000 }, |
| 61 | 0x0000, 0x00c3, 0x00c3, 0x01c0, | 61 | { 0x5, 0x0008 }, |
| 62 | 0x0000, 0x0000, 0x0000, 0x0000, | 62 | { 0x6, 0x0000 }, |
| 63 | 0x0000, 0x0000, 0x0000, 0x0000, | 63 | { 0x7, 0x000a }, |
| 64 | 0x0100, 0x0100, 0x0050, 0x0050, | 64 | { 0x8, 0x01c0 }, |
| 65 | 0x0050, 0x0050, 0x0000, 0x0000, | 65 | { 0x9, 0x0000 }, |
| 66 | 0x0000, 0x0000, 0x0040, 0x0000, | 66 | { 0xa, 0x00ff }, |
| 67 | 0x0000, 0x0050, 0x0050, 0x0000, | 67 | { 0xb, 0x00ff }, |
| 68 | 0x0002, 0x0037, 0x004d, 0x0080, | 68 | |
| 69 | 0x0008, 0x0031, 0x0026, 0x00e9, | 69 | { 0x10, 0x0000 }, |
| 70 | { 0x11, 0x007b }, | ||
| 71 | { 0x12, 0x0100 }, | ||
| 72 | { 0x13, 0x0032 }, | ||
| 73 | { 0x14, 0x0000 }, | ||
| 74 | { 0x15, 0x00c3 }, | ||
| 75 | { 0x16, 0x00c3 }, | ||
| 76 | { 0x17, 0x01c0 }, | ||
| 77 | { 0x18, 0x0000 }, | ||
| 78 | { 0x19, 0x0000 }, | ||
| 79 | { 0x1a, 0x0000 }, | ||
| 80 | { 0x1b, 0x0000 }, | ||
| 81 | { 0x1c, 0x0000 }, | ||
| 82 | { 0x1d, 0x0000 }, | ||
| 83 | |||
| 84 | { 0x20, 0x0100 }, | ||
| 85 | { 0x21, 0x0100 }, | ||
| 86 | { 0x22, 0x0050 }, | ||
| 87 | |||
| 88 | { 0x25, 0x0050 }, | ||
| 89 | { 0x26, 0x0000 }, | ||
| 90 | { 0x27, 0x0000 }, | ||
| 91 | { 0x28, 0x0000 }, | ||
| 92 | { 0x29, 0x0000 }, | ||
| 93 | { 0x2a, 0x0040 }, | ||
| 94 | { 0x2b, 0x0000 }, | ||
| 95 | { 0x2c, 0x0000 }, | ||
| 96 | { 0x2d, 0x0050 }, | ||
| 97 | { 0x2e, 0x0050 }, | ||
| 98 | { 0x2f, 0x0000 }, | ||
| 99 | { 0x30, 0x0002 }, | ||
| 100 | { 0x31, 0x0037 }, | ||
| 101 | |||
| 102 | { 0x33, 0x0080 }, | ||
| 103 | { 0x34, 0x0008 }, | ||
| 104 | { 0x35, 0x0031 }, | ||
| 105 | { 0x36, 0x0026 }, | ||
| 106 | { 0x37, 0x00e9 }, | ||
| 70 | }; | 107 | }; |
| 71 | 108 | ||
| 109 | static bool wm8960_volatile(struct device *dev, unsigned int reg) | ||
| 110 | { | ||
| 111 | switch (reg) { | ||
| 112 | case WM8960_RESET: | ||
| 113 | return true; | ||
| 114 | default: | ||
| 115 | return false; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 72 | struct wm8960_priv { | 119 | struct wm8960_priv { |
| 73 | enum snd_soc_control_type control_type; | 120 | struct regmap *regmap; |
| 74 | int (*set_bias_level)(struct snd_soc_codec *, | 121 | int (*set_bias_level)(struct snd_soc_codec *, |
| 75 | enum snd_soc_bias_level level); | 122 | enum snd_soc_bias_level level); |
| 76 | struct snd_soc_dapm_widget *lout1; | 123 | struct snd_soc_dapm_widget *lout1; |
| @@ -510,18 +557,25 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream, | |||
| 510 | struct snd_soc_codec *codec = dai->codec; | 557 | struct snd_soc_codec *codec = dai->codec; |
| 511 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | 558 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); |
| 512 | u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; | 559 | u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3; |
| 560 | snd_pcm_format_t format = params_format(params); | ||
| 513 | int i; | 561 | int i; |
| 514 | 562 | ||
| 515 | /* bit size */ | 563 | /* bit size */ |
| 516 | switch (params_format(params)) { | 564 | switch (format) { |
| 517 | case SNDRV_PCM_FORMAT_S16_LE: | 565 | case SNDRV_PCM_FORMAT_S16_LE: |
| 566 | case SNDRV_PCM_FORMAT_S16_BE: | ||
| 518 | break; | 567 | break; |
| 519 | case SNDRV_PCM_FORMAT_S20_3LE: | 568 | case SNDRV_PCM_FORMAT_S20_3LE: |
| 569 | case SNDRV_PCM_FORMAT_S20_3BE: | ||
| 520 | iface |= 0x0004; | 570 | iface |= 0x0004; |
| 521 | break; | 571 | break; |
| 522 | case SNDRV_PCM_FORMAT_S24_LE: | 572 | case SNDRV_PCM_FORMAT_S24_LE: |
| 573 | case SNDRV_PCM_FORMAT_S24_BE: | ||
| 523 | iface |= 0x0008; | 574 | iface |= 0x0008; |
| 524 | break; | 575 | break; |
| 576 | default: | ||
| 577 | dev_err(codec->dev, "unsupported format %i\n", format); | ||
| 578 | return -EINVAL; | ||
| 525 | } | 579 | } |
| 526 | 580 | ||
| 527 | /* Update filters for the new rate */ | 581 | /* Update filters for the new rate */ |
| @@ -555,6 +609,8 @@ static int wm8960_mute(struct snd_soc_dai *dai, int mute) | |||
| 555 | static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, | 609 | static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, |
| 556 | enum snd_soc_bias_level level) | 610 | enum snd_soc_bias_level level) |
| 557 | { | 611 | { |
| 612 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
| 613 | |||
| 558 | switch (level) { | 614 | switch (level) { |
| 559 | case SND_SOC_BIAS_ON: | 615 | case SND_SOC_BIAS_ON: |
| 560 | break; | 616 | break; |
| @@ -566,7 +622,7 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, | |||
| 566 | 622 | ||
| 567 | case SND_SOC_BIAS_STANDBY: | 623 | case SND_SOC_BIAS_STANDBY: |
| 568 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 624 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
| 569 | snd_soc_cache_sync(codec); | 625 | regcache_sync(wm8960->regmap); |
| 570 | 626 | ||
| 571 | /* Enable anti-pop features */ | 627 | /* Enable anti-pop features */ |
| 572 | snd_soc_write(codec, WM8960_APOP1, | 628 | snd_soc_write(codec, WM8960_APOP1, |
| @@ -667,7 +723,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, | |||
| 667 | break; | 723 | break; |
| 668 | 724 | ||
| 669 | case SND_SOC_BIAS_OFF: | 725 | case SND_SOC_BIAS_OFF: |
| 670 | snd_soc_cache_sync(codec); | 726 | regcache_sync(wm8960->regmap); |
| 671 | break; | 727 | break; |
| 672 | default: | 728 | default: |
| 673 | break; | 729 | break; |
| @@ -906,16 +962,11 @@ static int wm8960_probe(struct snd_soc_codec *codec) | |||
| 906 | if (!pdata) { | 962 | if (!pdata) { |
| 907 | dev_warn(codec->dev, "No platform data supplied\n"); | 963 | dev_warn(codec->dev, "No platform data supplied\n"); |
| 908 | } else { | 964 | } else { |
| 909 | if (pdata->dres > WM8960_DRES_MAX) { | ||
| 910 | dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres); | ||
| 911 | pdata->dres = 0; | ||
| 912 | } | ||
| 913 | |||
| 914 | if (pdata->capless) | 965 | if (pdata->capless) |
| 915 | wm8960->set_bias_level = wm8960_set_bias_level_capless; | 966 | wm8960->set_bias_level = wm8960_set_bias_level_capless; |
| 916 | } | 967 | } |
| 917 | 968 | ||
| 918 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8960->control_type); | 969 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
| 919 | if (ret < 0) { | 970 | if (ret < 0) { |
| 920 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 971 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
| 921 | return ret; | 972 | return ret; |
| @@ -963,14 +1014,24 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { | |||
| 963 | .suspend = wm8960_suspend, | 1014 | .suspend = wm8960_suspend, |
| 964 | .resume = wm8960_resume, | 1015 | .resume = wm8960_resume, |
| 965 | .set_bias_level = wm8960_set_bias_level, | 1016 | .set_bias_level = wm8960_set_bias_level, |
| 966 | .reg_cache_size = ARRAY_SIZE(wm8960_reg), | 1017 | }; |
| 967 | .reg_word_size = sizeof(u16), | 1018 | |
| 968 | .reg_cache_default = wm8960_reg, | 1019 | static const struct regmap_config wm8960_regmap = { |
| 1020 | .reg_bits = 7, | ||
| 1021 | .val_bits = 9, | ||
| 1022 | .max_register = WM8960_PLL4, | ||
| 1023 | |||
| 1024 | .reg_defaults = wm8960_reg_defaults, | ||
| 1025 | .num_reg_defaults = ARRAY_SIZE(wm8960_reg_defaults), | ||
| 1026 | .cache_type = REGCACHE_RBTREE, | ||
| 1027 | |||
| 1028 | .volatile_reg = wm8960_volatile, | ||
| 969 | }; | 1029 | }; |
| 970 | 1030 | ||
| 971 | static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, | 1031 | static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, |
| 972 | const struct i2c_device_id *id) | 1032 | const struct i2c_device_id *id) |
| 973 | { | 1033 | { |
| 1034 | struct wm8960_data *pdata = dev_get_platdata(&i2c->dev); | ||
| 974 | struct wm8960_priv *wm8960; | 1035 | struct wm8960_priv *wm8960; |
| 975 | int ret; | 1036 | int ret; |
| 976 | 1037 | ||
| @@ -979,8 +1040,21 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, | |||
| 979 | if (wm8960 == NULL) | 1040 | if (wm8960 == NULL) |
| 980 | return -ENOMEM; | 1041 | return -ENOMEM; |
| 981 | 1042 | ||
| 1043 | wm8960->regmap = regmap_init_i2c(i2c, &wm8960_regmap); | ||
| 1044 | if (IS_ERR(wm8960->regmap)) | ||
| 1045 | return PTR_ERR(wm8960->regmap); | ||
| 1046 | |||
| 1047 | if (pdata && pdata->shared_lrclk) { | ||
| 1048 | ret = regmap_update_bits(wm8960->regmap, WM8960_ADDCTL2, | ||
| 1049 | 0x4, 0x4); | ||
| 1050 | if (ret != 0) { | ||
| 1051 | dev_err(&i2c->dev, "Failed to enable LRCM: %d\n", | ||
| 1052 | ret); | ||
| 1053 | return ret; | ||
| 1054 | } | ||
| 1055 | } | ||
| 1056 | |||
| 982 | i2c_set_clientdata(i2c, wm8960); | 1057 | i2c_set_clientdata(i2c, wm8960); |
| 983 | wm8960->control_type = SND_SOC_I2C; | ||
| 984 | 1058 | ||
| 985 | ret = snd_soc_register_codec(&i2c->dev, | 1059 | ret = snd_soc_register_codec(&i2c->dev, |
| 986 | &soc_codec_dev_wm8960, &wm8960_dai, 1); | 1060 | &soc_codec_dev_wm8960, &wm8960_dai, 1); |
| @@ -1010,23 +1084,7 @@ static struct i2c_driver wm8960_i2c_driver = { | |||
| 1010 | .id_table = wm8960_i2c_id, | 1084 | .id_table = wm8960_i2c_id, |
| 1011 | }; | 1085 | }; |
| 1012 | 1086 | ||
| 1013 | static int __init wm8960_modinit(void) | 1087 | module_i2c_driver(wm8960_i2c_driver); |
| 1014 | { | ||
| 1015 | int ret = 0; | ||
| 1016 | ret = i2c_add_driver(&wm8960_i2c_driver); | ||
| 1017 | if (ret != 0) { | ||
| 1018 | printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n", | ||
| 1019 | ret); | ||
| 1020 | } | ||
| 1021 | return ret; | ||
| 1022 | } | ||
| 1023 | module_init(wm8960_modinit); | ||
| 1024 | |||
| 1025 | static void __exit wm8960_exit(void) | ||
| 1026 | { | ||
| 1027 | i2c_del_driver(&wm8960_i2c_driver); | ||
| 1028 | } | ||
| 1029 | module_exit(wm8960_exit); | ||
| 1030 | 1088 | ||
| 1031 | MODULE_DESCRIPTION("ASoC WM8960 driver"); | 1089 | MODULE_DESCRIPTION("ASoC WM8960 driver"); |
| 1032 | MODULE_AUTHOR("Liam Girdwood"); | 1090 | MODULE_AUTHOR("Liam Girdwood"); |
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 01edbcc754d2..f387670d0d75 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
| 20 | #include <linux/pm.h> | 20 | #include <linux/pm.h> |
| 21 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
| 22 | #include <linux/regmap.h> | ||
| 22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
| 24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
| @@ -31,283 +32,159 @@ | |||
| 31 | 32 | ||
| 32 | #define WM8961_MAX_REGISTER 0xFC | 33 | #define WM8961_MAX_REGISTER 0xFC |
| 33 | 34 | ||
| 34 | static u16 wm8961_reg_defaults[] = { | 35 | static const struct reg_default wm8961_reg_defaults[] = { |
| 35 | 0x009F, /* R0 - Left Input volume */ | 36 | { 0, 0x009F }, /* R0 - Left Input volume */ |
| 36 | 0x009F, /* R1 - Right Input volume */ | 37 | { 1, 0x009F }, /* R1 - Right Input volume */ |
| 37 | 0x0000, /* R2 - LOUT1 volume */ | 38 | { 2, 0x0000 }, /* R2 - LOUT1 volume */ |
| 38 | 0x0000, /* R3 - ROUT1 volume */ | 39 | { 3, 0x0000 }, /* R3 - ROUT1 volume */ |
| 39 | 0x0020, /* R4 - Clocking1 */ | 40 | { 4, 0x0020 }, /* R4 - Clocking1 */ |
| 40 | 0x0008, /* R5 - ADC & DAC Control 1 */ | 41 | { 5, 0x0008 }, /* R5 - ADC & DAC Control 1 */ |
| 41 | 0x0000, /* R6 - ADC & DAC Control 2 */ | 42 | { 6, 0x0000 }, /* R6 - ADC & DAC Control 2 */ |
| 42 | 0x000A, /* R7 - Audio Interface 0 */ | 43 | { 7, 0x000A }, /* R7 - Audio Interface 0 */ |
| 43 | 0x01F4, /* R8 - Clocking2 */ | 44 | { 8, 0x01F4 }, /* R8 - Clocking2 */ |
| 44 | 0x0000, /* R9 - Audio Interface 1 */ | 45 | { 9, 0x0000 }, /* R9 - Audio Interface 1 */ |
| 45 | 0x00FF, /* R10 - Left DAC volume */ | 46 | { 10, 0x00FF }, /* R10 - Left DAC volume */ |
| 46 | 0x00FF, /* R11 - Right DAC volume */ | 47 | { 11, 0x00FF }, /* R11 - Right DAC volume */ |
| 47 | 0x0000, /* R12 */ | 48 | |
| 48 | 0x0000, /* R13 */ | 49 | { 14, 0x0040 }, /* R14 - Audio Interface 2 */ |
| 49 | 0x0040, /* R14 - Audio Interface 2 */ | 50 | |
| 50 | 0x0000, /* R15 - Software Reset */ | 51 | { 17, 0x007B }, /* R17 - ALC1 */ |
| 51 | 0x0000, /* R16 */ | 52 | { 18, 0x0000 }, /* R18 - ALC2 */ |
| 52 | 0x007B, /* R17 - ALC1 */ | 53 | { 19, 0x0032 }, /* R19 - ALC3 */ |
| 53 | 0x0000, /* R18 - ALC2 */ | 54 | { 20, 0x0000 }, /* R20 - Noise Gate */ |
| 54 | 0x0032, /* R19 - ALC3 */ | 55 | { 21, 0x00C0 }, /* R21 - Left ADC volume */ |
| 55 | 0x0000, /* R20 - Noise Gate */ | 56 | { 22, 0x00C0 }, /* R22 - Right ADC volume */ |
| 56 | 0x00C0, /* R21 - Left ADC volume */ | 57 | { 23, 0x0120 }, /* R23 - Additional control(1) */ |
| 57 | 0x00C0, /* R22 - Right ADC volume */ | 58 | { 24, 0x0000 }, /* R24 - Additional control(2) */ |
| 58 | 0x0120, /* R23 - Additional control(1) */ | 59 | { 25, 0x0000 }, /* R25 - Pwr Mgmt (1) */ |
| 59 | 0x0000, /* R24 - Additional control(2) */ | 60 | { 26, 0x0000 }, /* R26 - Pwr Mgmt (2) */ |
| 60 | 0x0000, /* R25 - Pwr Mgmt (1) */ | 61 | { 27, 0x0000 }, /* R27 - Additional Control (3) */ |
| 61 | 0x0000, /* R26 - Pwr Mgmt (2) */ | 62 | { 28, 0x0000 }, /* R28 - Anti-pop */ |
| 62 | 0x0000, /* R27 - Additional Control (3) */ | 63 | |
| 63 | 0x0000, /* R28 - Anti-pop */ | 64 | { 30, 0x005F }, /* R30 - Clocking 3 */ |
| 64 | 0x0000, /* R29 */ | 65 | |
| 65 | 0x005F, /* R30 - Clocking 3 */ | 66 | { 32, 0x0000 }, /* R32 - ADCL signal path */ |
| 66 | 0x0000, /* R31 */ | 67 | { 33, 0x0000 }, /* R33 - ADCR signal path */ |
| 67 | 0x0000, /* R32 - ADCL signal path */ | 68 | |
| 68 | 0x0000, /* R33 - ADCR signal path */ | 69 | { 40, 0x0000 }, /* R40 - LOUT2 volume */ |
| 69 | 0x0000, /* R34 */ | 70 | { 41, 0x0000 }, /* R41 - ROUT2 volume */ |
| 70 | 0x0000, /* R35 */ | 71 | |
| 71 | 0x0000, /* R36 */ | 72 | { 47, 0x0000 }, /* R47 - Pwr Mgmt (3) */ |
| 72 | 0x0000, /* R37 */ | 73 | { 48, 0x0023 }, /* R48 - Additional Control (4) */ |
| 73 | 0x0000, /* R38 */ | 74 | { 49, 0x0000 }, /* R49 - Class D Control 1 */ |
| 74 | 0x0000, /* R39 */ | 75 | |
| 75 | 0x0000, /* R40 - LOUT2 volume */ | 76 | { 51, 0x0003 }, /* R51 - Class D Control 2 */ |
| 76 | 0x0000, /* R41 - ROUT2 volume */ | 77 | |
| 77 | 0x0000, /* R42 */ | 78 | { 56, 0x0106 }, /* R56 - Clocking 4 */ |
| 78 | 0x0000, /* R43 */ | 79 | { 57, 0x0000 }, /* R57 - DSP Sidetone 0 */ |
| 79 | 0x0000, /* R44 */ | 80 | { 58, 0x0000 }, /* R58 - DSP Sidetone 1 */ |
| 80 | 0x0000, /* R45 */ | 81 | |
| 81 | 0x0000, /* R46 */ | 82 | { 60, 0x0000 }, /* R60 - DC Servo 0 */ |
| 82 | 0x0000, /* R47 - Pwr Mgmt (3) */ | 83 | { 61, 0x0000 }, /* R61 - DC Servo 1 */ |
| 83 | 0x0023, /* R48 - Additional Control (4) */ | 84 | |
| 84 | 0x0000, /* R49 - Class D Control 1 */ | 85 | { 63, 0x015E }, /* R63 - DC Servo 3 */ |
| 85 | 0x0000, /* R50 */ | 86 | |
| 86 | 0x0003, /* R51 - Class D Control 2 */ | 87 | { 65, 0x0010 }, /* R65 - DC Servo 5 */ |
| 87 | 0x0000, /* R52 */ | 88 | |
| 88 | 0x0000, /* R53 */ | 89 | { 68, 0x0003 }, /* R68 - Analogue PGA Bias */ |
| 89 | 0x0000, /* R54 */ | 90 | { 69, 0x0000 }, /* R69 - Analogue HP 0 */ |
| 90 | 0x0000, /* R55 */ | 91 | |
| 91 | 0x0106, /* R56 - Clocking 4 */ | 92 | { 71, 0x01FB }, /* R71 - Analogue HP 2 */ |
| 92 | 0x0000, /* R57 - DSP Sidetone 0 */ | 93 | { 72, 0x0000 }, /* R72 - Charge Pump 1 */ |
| 93 | 0x0000, /* R58 - DSP Sidetone 1 */ | 94 | |
| 94 | 0x0000, /* R59 */ | 95 | { 82, 0x0000 }, /* R82 - Charge Pump B */ |
| 95 | 0x0000, /* R60 - DC Servo 0 */ | 96 | |
| 96 | 0x0000, /* R61 - DC Servo 1 */ | 97 | { 87, 0x0000 }, /* R87 - Write Sequencer 1 */ |
| 97 | 0x0000, /* R62 */ | 98 | { 88, 0x0000 }, /* R88 - Write Sequencer 2 */ |
| 98 | 0x015E, /* R63 - DC Servo 3 */ | 99 | { 89, 0x0000 }, /* R89 - Write Sequencer 3 */ |
| 99 | 0x0010, /* R64 */ | 100 | { 90, 0x0000 }, /* R90 - Write Sequencer 4 */ |
| 100 | 0x0010, /* R65 - DC Servo 5 */ | 101 | { 91, 0x0000 }, /* R91 - Write Sequencer 5 */ |
| 101 | 0x0000, /* R66 */ | 102 | { 92, 0x0000 }, /* R92 - Write Sequencer 6 */ |
| 102 | 0x0001, /* R67 */ | 103 | { 93, 0x0000 }, /* R93 - Write Sequencer 7 */ |
| 103 | 0x0003, /* R68 - Analogue PGA Bias */ | 104 | |
| 104 | 0x0000, /* R69 - Analogue HP 0 */ | 105 | { 252, 0x0001 }, /* R252 - General test 1 */ |
| 105 | 0x0060, /* R70 */ | ||
| 106 | 0x01FB, /* R71 - Analogue HP 2 */ | ||
| 107 | 0x0000, /* R72 - Charge Pump 1 */ | ||
| 108 | 0x0065, /* R73 */ | ||
| 109 | 0x005F, /* R74 */ | ||
| 110 | 0x0059, /* R75 */ | ||
| 111 | 0x006B, /* R76 */ | ||
| 112 | 0x0038, /* R77 */ | ||
| 113 | 0x000C, /* R78 */ | ||
| 114 | 0x000A, /* R79 */ | ||
| 115 | 0x006B, /* R80 */ | ||
| 116 | 0x0000, /* R81 */ | ||
| 117 | 0x0000, /* R82 - Charge Pump B */ | ||
| 118 | 0x0087, /* R83 */ | ||
| 119 | 0x0000, /* R84 */ | ||
| 120 | 0x005C, /* R85 */ | ||
| 121 | 0x0000, /* R86 */ | ||
| 122 | 0x0000, /* R87 - Write Sequencer 1 */ | ||
| 123 | 0x0000, /* R88 - Write Sequencer 2 */ | ||
| 124 | 0x0000, /* R89 - Write Sequencer 3 */ | ||
| 125 | 0x0000, /* R90 - Write Sequencer 4 */ | ||
| 126 | 0x0000, /* R91 - Write Sequencer 5 */ | ||
| 127 | 0x0000, /* R92 - Write Sequencer 6 */ | ||
| 128 | 0x0000, /* R93 - Write Sequencer 7 */ | ||
| 129 | 0x0000, /* R94 */ | ||
| 130 | 0x0000, /* R95 */ | ||
| 131 | 0x0000, /* R96 */ | ||
| 132 | 0x0000, /* R97 */ | ||
| 133 | 0x0000, /* R98 */ | ||
| 134 | 0x0000, /* R99 */ | ||
| 135 | 0x0000, /* R100 */ | ||
| 136 | 0x0000, /* R101 */ | ||
| 137 | 0x0000, /* R102 */ | ||
| 138 | 0x0000, /* R103 */ | ||
| 139 | 0x0000, /* R104 */ | ||
| 140 | 0x0000, /* R105 */ | ||
| 141 | 0x0000, /* R106 */ | ||
| 142 | 0x0000, /* R107 */ | ||
| 143 | 0x0000, /* R108 */ | ||
| 144 | 0x0000, /* R109 */ | ||
| 145 | 0x0000, /* R110 */ | ||
| 146 | 0x0000, /* R111 */ | ||
| 147 | 0x0000, /* R112 */ | ||
| 148 | 0x0000, /* R113 */ | ||
| 149 | 0x0000, /* R114 */ | ||
| 150 | 0x0000, /* R115 */ | ||
| 151 | 0x0000, /* R116 */ | ||
| 152 | 0x0000, /* R117 */ | ||
| 153 | 0x0000, /* R118 */ | ||
| 154 | 0x0000, /* R119 */ | ||
| 155 | 0x0000, /* R120 */ | ||
| 156 | 0x0000, /* R121 */ | ||
| 157 | 0x0000, /* R122 */ | ||
| 158 | 0x0000, /* R123 */ | ||
| 159 | 0x0000, /* R124 */ | ||
| 160 | 0x0000, /* R125 */ | ||
| 161 | 0x0000, /* R126 */ | ||
| 162 | 0x0000, /* R127 */ | ||
| 163 | 0x0000, /* R128 */ | ||
| 164 | 0x0000, /* R129 */ | ||
| 165 | 0x0000, /* R130 */ | ||
| 166 | 0x0000, /* R131 */ | ||
| 167 | 0x0000, /* R132 */ | ||
| 168 | 0x0000, /* R133 */ | ||
| 169 | 0x0000, /* R134 */ | ||
| 170 | 0x0000, /* R135 */ | ||
| 171 | 0x0000, /* R136 */ | ||
| 172 | 0x0000, /* R137 */ | ||
| 173 | 0x0000, /* R138 */ | ||
| 174 | 0x0000, /* R139 */ | ||
| 175 | 0x0000, /* R140 */ | ||
| 176 | 0x0000, /* R141 */ | ||
| 177 | 0x0000, /* R142 */ | ||
| 178 | 0x0000, /* R143 */ | ||
| 179 | 0x0000, /* R144 */ | ||
| 180 | 0x0000, /* R145 */ | ||
| 181 | 0x0000, /* R146 */ | ||
| 182 | 0x0000, /* R147 */ | ||
| 183 | 0x0000, /* R148 */ | ||
| 184 | 0x0000, /* R149 */ | ||
| 185 | 0x0000, /* R150 */ | ||
| 186 | 0x0000, /* R151 */ | ||
| 187 | 0x0000, /* R152 */ | ||
| 188 | 0x0000, /* R153 */ | ||
| 189 | 0x0000, /* R154 */ | ||
| 190 | 0x0000, /* R155 */ | ||
| 191 | 0x0000, /* R156 */ | ||
| 192 | 0x0000, /* R157 */ | ||
| 193 | 0x0000, /* R158 */ | ||
| 194 | 0x0000, /* R159 */ | ||
| 195 | 0x0000, /* R160 */ | ||
| 196 | 0x0000, /* R161 */ | ||
| 197 | 0x0000, /* R162 */ | ||
| 198 | 0x0000, /* R163 */ | ||
| 199 | 0x0000, /* R164 */ | ||
| 200 | 0x0000, /* R165 */ | ||
| 201 | 0x0000, /* R166 */ | ||
| 202 | 0x0000, /* R167 */ | ||
| 203 | 0x0000, /* R168 */ | ||
| 204 | 0x0000, /* R169 */ | ||
| 205 | 0x0000, /* R170 */ | ||
| 206 | 0x0000, /* R171 */ | ||
| 207 | 0x0000, /* R172 */ | ||
| 208 | 0x0000, /* R173 */ | ||
| 209 | 0x0000, /* R174 */ | ||
| 210 | 0x0000, /* R175 */ | ||
| 211 | 0x0000, /* R176 */ | ||
| 212 | 0x0000, /* R177 */ | ||
| 213 | 0x0000, /* R178 */ | ||
| 214 | 0x0000, /* R179 */ | ||
| 215 | 0x0000, /* R180 */ | ||
| 216 | 0x0000, /* R181 */ | ||
| 217 | 0x0000, /* R182 */ | ||
| 218 | 0x0000, /* R183 */ | ||
| 219 | 0x0000, /* R184 */ | ||
| 220 | 0x0000, /* R185 */ | ||
| 221 | 0x0000, /* R186 */ | ||
| 222 | 0x0000, /* R187 */ | ||
| 223 | 0x0000, /* R188 */ | ||
| 224 | 0x0000, /* R189 */ | ||
| 225 | 0x0000, /* R190 */ | ||
| 226 | 0x0000, /* R191 */ | ||
| 227 | 0x0000, /* R192 */ | ||
| 228 | 0x0000, /* R193 */ | ||
| 229 | 0x0000, /* R194 */ | ||
| 230 | 0x0000, /* R195 */ | ||
| 231 | 0x0030, /* R196 */ | ||
| 232 | 0x0006, /* R197 */ | ||
| 233 | 0x0000, /* R198 */ | ||
| 234 | 0x0060, /* R199 */ | ||
| 235 | 0x0000, /* R200 */ | ||
| 236 | 0x003F, /* R201 */ | ||
| 237 | 0x0000, /* R202 */ | ||
| 238 | 0x0000, /* R203 */ | ||
| 239 | 0x0000, /* R204 */ | ||
| 240 | 0x0001, /* R205 */ | ||
| 241 | 0x0000, /* R206 */ | ||
| 242 | 0x0181, /* R207 */ | ||
| 243 | 0x0005, /* R208 */ | ||
| 244 | 0x0008, /* R209 */ | ||
| 245 | 0x0008, /* R210 */ | ||
| 246 | 0x0000, /* R211 */ | ||
| 247 | 0x013B, /* R212 */ | ||
| 248 | 0x0000, /* R213 */ | ||
| 249 | 0x0000, /* R214 */ | ||
| 250 | 0x0000, /* R215 */ | ||
| 251 | 0x0000, /* R216 */ | ||
| 252 | 0x0070, /* R217 */ | ||
| 253 | 0x0000, /* R218 */ | ||
| 254 | 0x0000, /* R219 */ | ||
| 255 | 0x0000, /* R220 */ | ||
| 256 | 0x0000, /* R221 */ | ||
| 257 | 0x0000, /* R222 */ | ||
| 258 | 0x0003, /* R223 */ | ||
| 259 | 0x0000, /* R224 */ | ||
| 260 | 0x0000, /* R225 */ | ||
| 261 | 0x0001, /* R226 */ | ||
| 262 | 0x0008, /* R227 */ | ||
| 263 | 0x0000, /* R228 */ | ||
| 264 | 0x0000, /* R229 */ | ||
| 265 | 0x0000, /* R230 */ | ||
| 266 | 0x0000, /* R231 */ | ||
| 267 | 0x0004, /* R232 */ | ||
| 268 | 0x0000, /* R233 */ | ||
| 269 | 0x0000, /* R234 */ | ||
| 270 | 0x0000, /* R235 */ | ||
| 271 | 0x0000, /* R236 */ | ||
| 272 | 0x0000, /* R237 */ | ||
| 273 | 0x0080, /* R238 */ | ||
| 274 | 0x0000, /* R239 */ | ||
| 275 | 0x0000, /* R240 */ | ||
| 276 | 0x0000, /* R241 */ | ||
| 277 | 0x0000, /* R242 */ | ||
| 278 | 0x0000, /* R243 */ | ||
| 279 | 0x0000, /* R244 */ | ||
| 280 | 0x0052, /* R245 */ | ||
| 281 | 0x0110, /* R246 */ | ||
| 282 | 0x0040, /* R247 */ | ||
| 283 | 0x0000, /* R248 */ | ||
| 284 | 0x0030, /* R249 */ | ||
| 285 | 0x0000, /* R250 */ | ||
| 286 | 0x0000, /* R251 */ | ||
| 287 | 0x0001, /* R252 - General test 1 */ | ||
| 288 | }; | 106 | }; |
| 289 | 107 | ||
| 290 | struct wm8961_priv { | 108 | struct wm8961_priv { |
| 291 | enum snd_soc_control_type control_type; | 109 | struct regmap *regmap; |
| 292 | int sysclk; | 110 | int sysclk; |
| 293 | }; | 111 | }; |
| 294 | 112 | ||
| 295 | static int wm8961_volatile_register(struct snd_soc_codec *codec, unsigned int reg) | 113 | static bool wm8961_volatile(struct device *dev, unsigned int reg) |
| 296 | { | 114 | { |
| 297 | switch (reg) { | 115 | switch (reg) { |
| 298 | case WM8961_SOFTWARE_RESET: | 116 | case WM8961_SOFTWARE_RESET: |
| 299 | case WM8961_WRITE_SEQUENCER_7: | 117 | case WM8961_WRITE_SEQUENCER_7: |
| 300 | case WM8961_DC_SERVO_1: | 118 | case WM8961_DC_SERVO_1: |
| 301 | return 1; | 119 | return true; |
| 302 | 120 | ||
| 303 | default: | 121 | default: |
| 304 | return 0; | 122 | return false; |
| 305 | } | 123 | } |
| 306 | } | 124 | } |
| 307 | 125 | ||
| 308 | static int wm8961_reset(struct snd_soc_codec *codec) | 126 | static bool wm8961_readable(struct device *dev, unsigned int reg) |
| 309 | { | 127 | { |
| 310 | return snd_soc_write(codec, WM8961_SOFTWARE_RESET, 0); | 128 | switch (reg) { |
| 129 | case WM8961_LEFT_INPUT_VOLUME: | ||
| 130 | case WM8961_RIGHT_INPUT_VOLUME: | ||
| 131 | case WM8961_LOUT1_VOLUME: | ||
| 132 | case WM8961_ROUT1_VOLUME: | ||
| 133 | case WM8961_CLOCKING1: | ||
| 134 | case WM8961_ADC_DAC_CONTROL_1: | ||
| 135 | case WM8961_ADC_DAC_CONTROL_2: | ||
| 136 | case WM8961_AUDIO_INTERFACE_0: | ||
| 137 | case WM8961_CLOCKING2: | ||
| 138 | case WM8961_AUDIO_INTERFACE_1: | ||
| 139 | case WM8961_LEFT_DAC_VOLUME: | ||
| 140 | case WM8961_RIGHT_DAC_VOLUME: | ||
| 141 | case WM8961_AUDIO_INTERFACE_2: | ||
| 142 | case WM8961_SOFTWARE_RESET: | ||
| 143 | case WM8961_ALC1: | ||
| 144 | case WM8961_ALC2: | ||
| 145 | case WM8961_ALC3: | ||
| 146 | case WM8961_NOISE_GATE: | ||
| 147 | case WM8961_LEFT_ADC_VOLUME: | ||
| 148 | case WM8961_RIGHT_ADC_VOLUME: | ||
| 149 | case WM8961_ADDITIONAL_CONTROL_1: | ||
| 150 | case WM8961_ADDITIONAL_CONTROL_2: | ||
| 151 | case WM8961_PWR_MGMT_1: | ||
| 152 | case WM8961_PWR_MGMT_2: | ||
| 153 | case WM8961_ADDITIONAL_CONTROL_3: | ||
| 154 | case WM8961_ANTI_POP: | ||
| 155 | case WM8961_CLOCKING_3: | ||
| 156 | case WM8961_ADCL_SIGNAL_PATH: | ||
| 157 | case WM8961_ADCR_SIGNAL_PATH: | ||
| 158 | case WM8961_LOUT2_VOLUME: | ||
| 159 | case WM8961_ROUT2_VOLUME: | ||
| 160 | case WM8961_PWR_MGMT_3: | ||
| 161 | case WM8961_ADDITIONAL_CONTROL_4: | ||
| 162 | case WM8961_CLASS_D_CONTROL_1: | ||
| 163 | case WM8961_CLASS_D_CONTROL_2: | ||
| 164 | case WM8961_CLOCKING_4: | ||
| 165 | case WM8961_DSP_SIDETONE_0: | ||
| 166 | case WM8961_DSP_SIDETONE_1: | ||
| 167 | case WM8961_DC_SERVO_0: | ||
| 168 | case WM8961_DC_SERVO_1: | ||
| 169 | case WM8961_DC_SERVO_3: | ||
| 170 | case WM8961_DC_SERVO_5: | ||
| 171 | case WM8961_ANALOGUE_PGA_BIAS: | ||
| 172 | case WM8961_ANALOGUE_HP_0: | ||
| 173 | case WM8961_ANALOGUE_HP_2: | ||
| 174 | case WM8961_CHARGE_PUMP_1: | ||
| 175 | case WM8961_CHARGE_PUMP_B: | ||
| 176 | case WM8961_WRITE_SEQUENCER_1: | ||
| 177 | case WM8961_WRITE_SEQUENCER_2: | ||
| 178 | case WM8961_WRITE_SEQUENCER_3: | ||
| 179 | case WM8961_WRITE_SEQUENCER_4: | ||
| 180 | case WM8961_WRITE_SEQUENCER_5: | ||
| 181 | case WM8961_WRITE_SEQUENCER_6: | ||
| 182 | case WM8961_WRITE_SEQUENCER_7: | ||
| 183 | case WM8961_GENERAL_TEST_1: | ||
| 184 | return true; | ||
| 185 | default: | ||
| 186 | return false; | ||
| 187 | } | ||
| 311 | } | 188 | } |
| 312 | 189 | ||
| 313 | /* | 190 | /* |
| @@ -962,33 +839,12 @@ static int wm8961_probe(struct snd_soc_codec *codec) | |||
| 962 | int ret = 0; | 839 | int ret = 0; |
| 963 | u16 reg; | 840 | u16 reg; |
| 964 | 841 | ||
| 965 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 842 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP); |
| 966 | if (ret != 0) { | 843 | if (ret != 0) { |
| 967 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 844 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
| 968 | return ret; | 845 | return ret; |
| 969 | } | 846 | } |
| 970 | 847 | ||
| 971 | reg = snd_soc_read(codec, WM8961_SOFTWARE_RESET); | ||
| 972 | if (reg != 0x1801) { | ||
| 973 | dev_err(codec->dev, "Device is not a WM8961: ID=0x%x\n", reg); | ||
| 974 | return -EINVAL; | ||
| 975 | } | ||
| 976 | |||
| 977 | /* This isn't volatile - readback doesn't correspond to write */ | ||
| 978 | codec->cache_bypass = 1; | ||
| 979 | reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME); | ||
| 980 | codec->cache_bypass = 0; | ||
| 981 | dev_info(codec->dev, "WM8961 family %d revision %c\n", | ||
| 982 | (reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, | ||
| 983 | ((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) | ||
| 984 | + 'A'); | ||
| 985 | |||
| 986 | ret = wm8961_reset(codec); | ||
| 987 | if (ret < 0) { | ||
| 988 | dev_err(codec->dev, "Failed to issue reset\n"); | ||
| 989 | return ret; | ||
| 990 | } | ||
| 991 | |||
| 992 | /* Enable class W */ | 848 | /* Enable class W */ |
| 993 | reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); | 849 | reg = snd_soc_read(codec, WM8961_CHARGE_PUMP_B); |
| 994 | reg |= WM8961_CP_DYN_PWR_MASK; | 850 | reg |= WM8961_CP_DYN_PWR_MASK; |
| @@ -1066,16 +922,26 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8961 = { | |||
| 1066 | .suspend = wm8961_suspend, | 922 | .suspend = wm8961_suspend, |
| 1067 | .resume = wm8961_resume, | 923 | .resume = wm8961_resume, |
| 1068 | .set_bias_level = wm8961_set_bias_level, | 924 | .set_bias_level = wm8961_set_bias_level, |
| 1069 | .reg_cache_size = ARRAY_SIZE(wm8961_reg_defaults), | 925 | }; |
| 1070 | .reg_word_size = sizeof(u16), | 926 | |
| 1071 | .reg_cache_default = wm8961_reg_defaults, | 927 | static const struct regmap_config wm8961_regmap = { |
| 1072 | .volatile_register = wm8961_volatile_register, | 928 | .reg_bits = 8, |
| 929 | .val_bits = 16, | ||
| 930 | .max_register = WM8961_MAX_REGISTER, | ||
| 931 | |||
| 932 | .reg_defaults = wm8961_reg_defaults, | ||
| 933 | .num_reg_defaults = ARRAY_SIZE(wm8961_reg_defaults), | ||
| 934 | .cache_type = REGCACHE_RBTREE, | ||
| 935 | |||
| 936 | .volatile_reg = wm8961_volatile, | ||
| 937 | .readable_reg = wm8961_readable, | ||
| 1073 | }; | 938 | }; |
| 1074 | 939 | ||
| 1075 | static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, | 940 | static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, |
| 1076 | const struct i2c_device_id *id) | 941 | const struct i2c_device_id *id) |
| 1077 | { | 942 | { |
| 1078 | struct wm8961_priv *wm8961; | 943 | struct wm8961_priv *wm8961; |
| 944 | unsigned int val; | ||
| 1079 | int ret; | 945 | int ret; |
| 1080 | 946 | ||
| 1081 | wm8961 = devm_kzalloc(&i2c->dev, sizeof(struct wm8961_priv), | 947 | wm8961 = devm_kzalloc(&i2c->dev, sizeof(struct wm8961_priv), |
| @@ -1083,6 +949,42 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c, | |||
| 1083 | if (wm8961 == NULL) | 949 | if (wm8961 == NULL) |
| 1084 | return -ENOMEM; | 950 | return -ENOMEM; |
| 1085 | 951 | ||
| 952 | wm8961->regmap = devm_regmap_init_i2c(i2c, &wm8961_regmap); | ||
| 953 | if (IS_ERR(wm8961->regmap)) | ||
| 954 | return PTR_ERR(wm8961->regmap); | ||
| 955 | |||
| 956 | ret = regmap_read(wm8961->regmap, WM8961_SOFTWARE_RESET, &val); | ||
| 957 | if (ret != 0) { | ||
| 958 | dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); | ||
| 959 | return ret; | ||
| 960 | } | ||
| 961 | |||
| 962 | if (val != 0x1801) { | ||
| 963 | dev_err(&i2c->dev, "Device is not a WM8961: ID=0x%x\n", val); | ||
| 964 | return -EINVAL; | ||
| 965 | } | ||
| 966 | |||
| 967 | /* This isn't volatile - readback doesn't correspond to write */ | ||
| 968 | regcache_cache_bypass(wm8961->regmap, true); | ||
| 969 | ret = regmap_read(wm8961->regmap, WM8961_RIGHT_INPUT_VOLUME, &val); | ||
| 970 | regcache_cache_bypass(wm8961->regmap, false); | ||
| 971 | |||
| 972 | if (ret != 0) { | ||
| 973 | dev_err(&i2c->dev, "Failed to read chip revision: %d\n", ret); | ||
| 974 | return ret; | ||
| 975 | } | ||
| 976 | |||
| 977 | dev_info(&i2c->dev, "WM8961 family %d revision %c\n", | ||
| 978 | (val & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT, | ||
| 979 | ((val & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT) | ||
| 980 | + 'A'); | ||
| 981 | |||
| 982 | ret = regmap_write(wm8961->regmap, WM8961_SOFTWARE_RESET, 0x1801); | ||
| 983 | if (ret != 0) { | ||
| 984 | dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); | ||
| 985 | return ret; | ||
| 986 | } | ||
| 987 | |||
| 1086 | i2c_set_clientdata(i2c, wm8961); | 988 | i2c_set_clientdata(i2c, wm8961); |
| 1087 | 989 | ||
| 1088 | ret = snd_soc_register_codec(&i2c->dev, | 990 | ret = snd_soc_register_codec(&i2c->dev, |
| @@ -1114,23 +1016,7 @@ static struct i2c_driver wm8961_i2c_driver = { | |||
| 1114 | .id_table = wm8961_i2c_id, | 1016 | .id_table = wm8961_i2c_id, |
| 1115 | }; | 1017 | }; |
| 1116 | 1018 | ||
| 1117 | static int __init wm8961_modinit(void) | 1019 | module_i2c_driver(wm8961_i2c_driver); |
| 1118 | { | ||
| 1119 | int ret = 0; | ||
| 1120 | ret = i2c_add_driver(&wm8961_i2c_driver); | ||
| 1121 | if (ret != 0) { | ||
| 1122 | printk(KERN_ERR "Failed to register wm8961 I2C driver: %d\n", | ||
| 1123 | ret); | ||
| 1124 | } | ||
| 1125 | return ret; | ||
| 1126 | } | ||
| 1127 | module_init(wm8961_modinit); | ||
| 1128 | |||
| 1129 | static void __exit wm8961_exit(void) | ||
| 1130 | { | ||
| 1131 | i2c_del_driver(&wm8961_i2c_driver); | ||
| 1132 | } | ||
| 1133 | module_exit(wm8961_exit); | ||
| 1134 | 1020 | ||
| 1135 | MODULE_DESCRIPTION("ASoC WM8961 driver"); | 1021 | MODULE_DESCRIPTION("ASoC WM8961 driver"); |
| 1136 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 1022 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index eef783f6b6d6..5ce647758443 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
| @@ -721,23 +721,7 @@ static struct i2c_driver wm8971_i2c_driver = { | |||
| 721 | .id_table = wm8971_i2c_id, | 721 | .id_table = wm8971_i2c_id, |
| 722 | }; | 722 | }; |
| 723 | 723 | ||
| 724 | static int __init wm8971_modinit(void) | 724 | module_i2c_driver(wm8971_i2c_driver); |
| 725 | { | ||
| 726 | int ret = 0; | ||
| 727 | ret = i2c_add_driver(&wm8971_i2c_driver); | ||
| 728 | if (ret != 0) { | ||
| 729 | printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n", | ||
| 730 | ret); | ||
| 731 | } | ||
| 732 | return ret; | ||
| 733 | } | ||
| 734 | module_init(wm8971_modinit); | ||
| 735 | |||
| 736 | static void __exit wm8971_exit(void) | ||
| 737 | { | ||
| 738 | i2c_del_driver(&wm8971_i2c_driver); | ||
| 739 | } | ||
| 740 | module_exit(wm8971_exit); | ||
| 741 | 725 | ||
| 742 | MODULE_DESCRIPTION("ASoC WM8971 driver"); | 726 | MODULE_DESCRIPTION("ASoC WM8971 driver"); |
| 743 | MODULE_AUTHOR("Lab126"); | 727 | MODULE_AUTHOR("Lab126"); |
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index d93c03f820c9..9a39511af52a 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c | |||
| @@ -659,23 +659,7 @@ static struct i2c_driver wm8974_i2c_driver = { | |||
| 659 | .id_table = wm8974_i2c_id, | 659 | .id_table = wm8974_i2c_id, |
| 660 | }; | 660 | }; |
| 661 | 661 | ||
| 662 | static int __init wm8974_modinit(void) | 662 | module_i2c_driver(wm8974_i2c_driver); |
| 663 | { | ||
| 664 | int ret = 0; | ||
| 665 | ret = i2c_add_driver(&wm8974_i2c_driver); | ||
| 666 | if (ret != 0) { | ||
| 667 | printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n", | ||
| 668 | ret); | ||
| 669 | } | ||
| 670 | return ret; | ||
| 671 | } | ||
| 672 | module_init(wm8974_modinit); | ||
| 673 | |||
| 674 | static void __exit wm8974_exit(void) | ||
| 675 | { | ||
| 676 | i2c_del_driver(&wm8974_i2c_driver); | ||
| 677 | } | ||
| 678 | module_exit(wm8974_exit); | ||
| 679 | 663 | ||
| 680 | MODULE_DESCRIPTION("ASoC WM8974 driver"); | 664 | MODULE_DESCRIPTION("ASoC WM8974 driver"); |
| 681 | MODULE_AUTHOR("Liam Girdwood"); | 665 | MODULE_AUTHOR("Liam Girdwood"); |
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index a5be3adecf75..5421fd9fbcb5 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c | |||
| @@ -1105,23 +1105,7 @@ static struct i2c_driver wm8978_i2c_driver = { | |||
| 1105 | .id_table = wm8978_i2c_id, | 1105 | .id_table = wm8978_i2c_id, |
| 1106 | }; | 1106 | }; |
| 1107 | 1107 | ||
| 1108 | static int __init wm8978_modinit(void) | 1108 | module_i2c_driver(wm8978_i2c_driver); |
| 1109 | { | ||
| 1110 | int ret = 0; | ||
| 1111 | ret = i2c_add_driver(&wm8978_i2c_driver); | ||
| 1112 | if (ret != 0) { | ||
| 1113 | printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n", | ||
| 1114 | ret); | ||
| 1115 | } | ||
| 1116 | return ret; | ||
| 1117 | } | ||
| 1118 | module_init(wm8978_modinit); | ||
| 1119 | |||
| 1120 | static void __exit wm8978_exit(void) | ||
| 1121 | { | ||
| 1122 | i2c_del_driver(&wm8978_i2c_driver); | ||
| 1123 | } | ||
| 1124 | module_exit(wm8978_exit); | ||
| 1125 | 1109 | ||
| 1126 | MODULE_DESCRIPTION("ASoC WM8978 codec driver"); | 1110 | MODULE_DESCRIPTION("ASoC WM8978 codec driver"); |
| 1127 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | 1111 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); |
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c index 367388fdc486..d8879f262d27 100644 --- a/sound/soc/codecs/wm8983.c +++ b/sound/soc/codecs/wm8983.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
| 17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
| 18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
| 19 | #include <linux/regmap.h> | ||
| 19 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
| 20 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
| @@ -27,61 +28,60 @@ | |||
| 27 | 28 | ||
| 28 | #include "wm8983.h" | 29 | #include "wm8983.h" |
| 29 | 30 | ||
| 30 | static const u16 wm8983_reg_defs[WM8983_MAX_REGISTER + 1] = { | 31 | static const struct reg_default wm8983_defaults[] = { |
| 31 | [0x00] = 0x0000, /* R0 - Software Reset */ | 32 | { 0x01, 0x0000 }, /* R1 - Power management 1 */ |
| 32 | [0x01] = 0x0000, /* R1 - Power management 1 */ | 33 | { 0x02, 0x0000 }, /* R2 - Power management 2 */ |
| 33 | [0x02] = 0x0000, /* R2 - Power management 2 */ | 34 | { 0x03, 0x0000 }, /* R3 - Power management 3 */ |
| 34 | [0x03] = 0x0000, /* R3 - Power management 3 */ | 35 | { 0x04, 0x0050 }, /* R4 - Audio Interface */ |
| 35 | [0x04] = 0x0050, /* R4 - Audio Interface */ | 36 | { 0x05, 0x0000 }, /* R5 - Companding control */ |
| 36 | [0x05] = 0x0000, /* R5 - Companding control */ | 37 | { 0x06, 0x0140 }, /* R6 - Clock Gen control */ |
| 37 | [0x06] = 0x0140, /* R6 - Clock Gen control */ | 38 | { 0x07, 0x0000 }, /* R7 - Additional control */ |
| 38 | [0x07] = 0x0000, /* R7 - Additional control */ | 39 | { 0x08, 0x0000 }, /* R8 - GPIO Control */ |
| 39 | [0x08] = 0x0000, /* R8 - GPIO Control */ | 40 | { 0x09, 0x0000 }, /* R9 - Jack Detect Control 1 */ |
| 40 | [0x09] = 0x0000, /* R9 - Jack Detect Control 1 */ | 41 | { 0x0A, 0x0000 }, /* R10 - DAC Control */ |
| 41 | [0x0A] = 0x0000, /* R10 - DAC Control */ | 42 | { 0x0B, 0x00FF }, /* R11 - Left DAC digital Vol */ |
| 42 | [0x0B] = 0x00FF, /* R11 - Left DAC digital Vol */ | 43 | { 0x0C, 0x00FF }, /* R12 - Right DAC digital vol */ |
| 43 | [0x0C] = 0x00FF, /* R12 - Right DAC digital vol */ | 44 | { 0x0D, 0x0000 }, /* R13 - Jack Detect Control 2 */ |
| 44 | [0x0D] = 0x0000, /* R13 - Jack Detect Control 2 */ | 45 | { 0x0E, 0x0100 }, /* R14 - ADC Control */ |
| 45 | [0x0E] = 0x0100, /* R14 - ADC Control */ | 46 | { 0x0F, 0x00FF }, /* R15 - Left ADC Digital Vol */ |
| 46 | [0x0F] = 0x00FF, /* R15 - Left ADC Digital Vol */ | 47 | { 0x10, 0x00FF }, /* R16 - Right ADC Digital Vol */ |
| 47 | [0x10] = 0x00FF, /* R16 - Right ADC Digital Vol */ | 48 | { 0x12, 0x012C }, /* R18 - EQ1 - low shelf */ |
| 48 | [0x12] = 0x012C, /* R18 - EQ1 - low shelf */ | 49 | { 0x13, 0x002C }, /* R19 - EQ2 - peak 1 */ |
| 49 | [0x13] = 0x002C, /* R19 - EQ2 - peak 1 */ | 50 | { 0x14, 0x002C }, /* R20 - EQ3 - peak 2 */ |
| 50 | [0x14] = 0x002C, /* R20 - EQ3 - peak 2 */ | 51 | { 0x15, 0x002C }, /* R21 - EQ4 - peak 3 */ |
| 51 | [0x15] = 0x002C, /* R21 - EQ4 - peak 3 */ | 52 | { 0x16, 0x002C }, /* R22 - EQ5 - high shelf */ |
| 52 | [0x16] = 0x002C, /* R22 - EQ5 - high shelf */ | 53 | { 0x18, 0x0032 }, /* R24 - DAC Limiter 1 */ |
| 53 | [0x18] = 0x0032, /* R24 - DAC Limiter 1 */ | 54 | { 0x19, 0x0000 }, /* R25 - DAC Limiter 2 */ |
| 54 | [0x19] = 0x0000, /* R25 - DAC Limiter 2 */ | 55 | { 0x1B, 0x0000 }, /* R27 - Notch Filter 1 */ |
| 55 | [0x1B] = 0x0000, /* R27 - Notch Filter 1 */ | 56 | { 0x1C, 0x0000 }, /* R28 - Notch Filter 2 */ |
| 56 | [0x1C] = 0x0000, /* R28 - Notch Filter 2 */ | 57 | { 0x1D, 0x0000 }, /* R29 - Notch Filter 3 */ |
| 57 | [0x1D] = 0x0000, /* R29 - Notch Filter 3 */ | 58 | { 0x1E, 0x0000 }, /* R30 - Notch Filter 4 */ |
| 58 | [0x1E] = 0x0000, /* R30 - Notch Filter 4 */ | 59 | { 0x20, 0x0038 }, /* R32 - ALC control 1 */ |
| 59 | [0x20] = 0x0038, /* R32 - ALC control 1 */ | 60 | { 0x21, 0x000B }, /* R33 - ALC control 2 */ |
| 60 | [0x21] = 0x000B, /* R33 - ALC control 2 */ | 61 | { 0x22, 0x0032 }, /* R34 - ALC control 3 */ |
| 61 | [0x22] = 0x0032, /* R34 - ALC control 3 */ | 62 | { 0x23, 0x0000 }, /* R35 - Noise Gate */ |
| 62 | [0x23] = 0x0000, /* R35 - Noise Gate */ | 63 | { 0x24, 0x0008 }, /* R36 - PLL N */ |
| 63 | [0x24] = 0x0008, /* R36 - PLL N */ | 64 | { 0x25, 0x000C }, /* R37 - PLL K 1 */ |
| 64 | [0x25] = 0x000C, /* R37 - PLL K 1 */ | 65 | { 0x26, 0x0093 }, /* R38 - PLL K 2 */ |
| 65 | [0x26] = 0x0093, /* R38 - PLL K 2 */ | 66 | { 0x27, 0x00E9 }, /* R39 - PLL K 3 */ |
| 66 | [0x27] = 0x00E9, /* R39 - PLL K 3 */ | 67 | { 0x29, 0x0000 }, /* R41 - 3D control */ |
| 67 | [0x29] = 0x0000, /* R41 - 3D control */ | 68 | { 0x2A, 0x0000 }, /* R42 - OUT4 to ADC */ |
| 68 | [0x2A] = 0x0000, /* R42 - OUT4 to ADC */ | 69 | { 0x2B, 0x0000 }, /* R43 - Beep control */ |
| 69 | [0x2B] = 0x0000, /* R43 - Beep control */ | 70 | { 0x2C, 0x0033 }, /* R44 - Input ctrl */ |
| 70 | [0x2C] = 0x0033, /* R44 - Input ctrl */ | 71 | { 0x2D, 0x0010 }, /* R45 - Left INP PGA gain ctrl */ |
| 71 | [0x2D] = 0x0010, /* R45 - Left INP PGA gain ctrl */ | 72 | { 0x2E, 0x0010 }, /* R46 - Right INP PGA gain ctrl */ |
| 72 | [0x2E] = 0x0010, /* R46 - Right INP PGA gain ctrl */ | 73 | { 0x2F, 0x0100 }, /* R47 - Left ADC BOOST ctrl */ |
| 73 | [0x2F] = 0x0100, /* R47 - Left ADC BOOST ctrl */ | 74 | { 0x30, 0x0100 }, /* R48 - Right ADC BOOST ctrl */ |
| 74 | [0x30] = 0x0100, /* R48 - Right ADC BOOST ctrl */ | 75 | { 0x31, 0x0002 }, /* R49 - Output ctrl */ |
| 75 | [0x31] = 0x0002, /* R49 - Output ctrl */ | 76 | { 0x32, 0x0001 }, /* R50 - Left mixer ctrl */ |
| 76 | [0x32] = 0x0001, /* R50 - Left mixer ctrl */ | 77 | { 0x33, 0x0001 }, /* R51 - Right mixer ctrl */ |
| 77 | [0x33] = 0x0001, /* R51 - Right mixer ctrl */ | 78 | { 0x34, 0x0039 }, /* R52 - LOUT1 (HP) volume ctrl */ |
| 78 | [0x34] = 0x0039, /* R52 - LOUT1 (HP) volume ctrl */ | 79 | { 0x35, 0x0039 }, /* R53 - ROUT1 (HP) volume ctrl */ |
| 79 | [0x35] = 0x0039, /* R53 - ROUT1 (HP) volume ctrl */ | 80 | { 0x36, 0x0039 }, /* R54 - LOUT2 (SPK) volume ctrl */ |
| 80 | [0x36] = 0x0039, /* R54 - LOUT2 (SPK) volume ctrl */ | 81 | { 0x37, 0x0039 }, /* R55 - ROUT2 (SPK) volume ctrl */ |
| 81 | [0x37] = 0x0039, /* R55 - ROUT2 (SPK) volume ctrl */ | 82 | { 0x38, 0x0001 }, /* R56 - OUT3 mixer ctrl */ |
| 82 | [0x38] = 0x0001, /* R56 - OUT3 mixer ctrl */ | 83 | { 0x39, 0x0001 }, /* R57 - OUT4 (MONO) mix ctrl */ |
| 83 | [0x39] = 0x0001, /* R57 - OUT4 (MONO) mix ctrl */ | 84 | { 0x3D, 0x0000 }, /* R61 - BIAS CTRL */ |
| 84 | [0x3D] = 0x0000 /* R61 - BIAS CTRL */ | ||
| 85 | }; | 85 | }; |
| 86 | 86 | ||
| 87 | static const struct wm8983_reg_access { | 87 | static const struct wm8983_reg_access { |
| @@ -159,7 +159,7 @@ static const int vol_update_regs[] = { | |||
| 159 | }; | 159 | }; |
| 160 | 160 | ||
| 161 | struct wm8983_priv { | 161 | struct wm8983_priv { |
| 162 | enum snd_soc_control_type control_type; | 162 | struct regmap *regmap; |
| 163 | u32 sysclk; | 163 | u32 sysclk; |
| 164 | u32 bclk; | 164 | u32 bclk; |
| 165 | }; | 165 | }; |
| @@ -610,7 +610,7 @@ static int eqmode_put(struct snd_kcontrol *kcontrol, | |||
| 610 | return 0; | 610 | return 0; |
| 611 | } | 611 | } |
| 612 | 612 | ||
| 613 | static int wm8983_readable(struct snd_soc_codec *codec, unsigned int reg) | 613 | static bool wm8983_readable(struct device *dev, unsigned int reg) |
| 614 | { | 614 | { |
| 615 | if (reg > WM8983_MAX_REGISTER) | 615 | if (reg > WM8983_MAX_REGISTER) |
| 616 | return 0; | 616 | return 0; |
| @@ -905,6 +905,7 @@ static int wm8983_set_sysclk(struct snd_soc_dai *dai, | |||
| 905 | static int wm8983_set_bias_level(struct snd_soc_codec *codec, | 905 | static int wm8983_set_bias_level(struct snd_soc_codec *codec, |
| 906 | enum snd_soc_bias_level level) | 906 | enum snd_soc_bias_level level) |
| 907 | { | 907 | { |
| 908 | struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); | ||
| 908 | int ret; | 909 | int ret; |
| 909 | 910 | ||
| 910 | switch (level) { | 911 | switch (level) { |
| @@ -917,7 +918,7 @@ static int wm8983_set_bias_level(struct snd_soc_codec *codec, | |||
| 917 | break; | 918 | break; |
| 918 | case SND_SOC_BIAS_STANDBY: | 919 | case SND_SOC_BIAS_STANDBY: |
| 919 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { | 920 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
| 920 | ret = snd_soc_cache_sync(codec); | 921 | ret = regcache_sync(wm8983->regmap); |
| 921 | if (ret < 0) { | 922 | if (ret < 0) { |
| 922 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); | 923 | dev_err(codec->dev, "Failed to sync cache: %d\n", ret); |
| 923 | return ret; | 924 | return ret; |
| @@ -994,10 +995,9 @@ static int wm8983_remove(struct snd_soc_codec *codec) | |||
| 994 | static int wm8983_probe(struct snd_soc_codec *codec) | 995 | static int wm8983_probe(struct snd_soc_codec *codec) |
| 995 | { | 996 | { |
| 996 | int ret; | 997 | int ret; |
| 997 | struct wm8983_priv *wm8983 = snd_soc_codec_get_drvdata(codec); | ||
| 998 | int i; | 998 | int i; |
| 999 | 999 | ||
| 1000 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8983->control_type); | 1000 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
| 1001 | if (ret < 0) { | 1001 | if (ret < 0) { |
| 1002 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); | 1002 | dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret); |
| 1003 | return ret; | 1003 | return ret; |
| @@ -1067,16 +1067,23 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8983 = { | |||
| 1067 | .suspend = wm8983_suspend, | 1067 | .suspend = wm8983_suspend, |
| 1068 | .resume = wm8983_resume, | 1068 | .resume = wm8983_resume, |
| 1069 | .set_bias_level = wm8983_set_bias_level, | 1069 | .set_bias_level = wm8983_set_bias_level, |
| 1070 | .reg_cache_size = ARRAY_SIZE(wm8983_reg_defs), | ||
| 1071 | .reg_word_size = sizeof(u16), | ||
| 1072 | .reg_cache_default = wm8983_reg_defs, | ||
| 1073 | .controls = wm8983_snd_controls, | 1070 | .controls = wm8983_snd_controls, |
| 1074 | .num_controls = ARRAY_SIZE(wm8983_snd_controls), | 1071 | .num_controls = ARRAY_SIZE(wm8983_snd_controls), |
| 1075 | .dapm_widgets = wm8983_dapm_widgets, | 1072 | .dapm_widgets = wm8983_dapm_widgets, |
| 1076 | .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), | 1073 | .num_dapm_widgets = ARRAY_SIZE(wm8983_dapm_widgets), |
| 1077 | .dapm_routes = wm8983_audio_map, | 1074 | .dapm_routes = wm8983_audio_map, |
| 1078 | .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), | 1075 | .num_dapm_routes = ARRAY_SIZE(wm8983_audio_map), |
| 1079 | .readable_register = wm8983_readable | 1076 | }; |
| 1077 | |||
| 1078 | static const struct regmap_config wm8983_regmap = { | ||
| 1079 | .reg_bits = 7, | ||
| 1080 | .val_bits = 9, | ||
| 1081 | |||
| 1082 | .reg_defaults = wm8983_defaults, | ||
| 1083 | .num_reg_defaults = ARRAY_SIZE(wm8983_defaults), | ||
| 1084 | .cache_type = REGCACHE_RBTREE, | ||
| 1085 | |||
| 1086 | .readable_reg = wm8983_readable, | ||
| 1080 | }; | 1087 | }; |
| 1081 | 1088 | ||
| 1082 | #if defined(CONFIG_SPI_MASTER) | 1089 | #if defined(CONFIG_SPI_MASTER) |
| @@ -1085,24 +1092,27 @@ static int __devinit wm8983_spi_probe(struct spi_device *spi) | |||
| 1085 | struct wm8983_priv *wm8983; | 1092 | struct wm8983_priv *wm8983; |
| 1086 | int ret; | 1093 | int ret; |
| 1087 | 1094 | ||
| 1088 | wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); | 1095 | wm8983 = devm_kzalloc(&spi->dev, sizeof *wm8983, GFP_KERNEL); |
| 1089 | if (!wm8983) | 1096 | if (!wm8983) |
| 1090 | return -ENOMEM; | 1097 | return -ENOMEM; |
| 1091 | 1098 | ||
| 1092 | wm8983->control_type = SND_SOC_SPI; | 1099 | wm8983->regmap = devm_regmap_init_spi(spi, &wm8983_regmap); |
| 1100 | if (IS_ERR(wm8983->regmap)) { | ||
| 1101 | ret = PTR_ERR(wm8983->regmap); | ||
| 1102 | dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); | ||
| 1103 | return ret; | ||
| 1104 | } | ||
| 1105 | |||
| 1093 | spi_set_drvdata(spi, wm8983); | 1106 | spi_set_drvdata(spi, wm8983); |
| 1094 | 1107 | ||
| 1095 | ret = snd_soc_register_codec(&spi->dev, | 1108 | ret = snd_soc_register_codec(&spi->dev, |
| 1096 | &soc_codec_dev_wm8983, &wm8983_dai, 1); | 1109 | &soc_codec_dev_wm8983, &wm8983_dai, 1); |
| 1097 | if (ret < 0) | ||
| 1098 | kfree(wm8983); | ||
| 1099 | return ret; | 1110 | return ret; |
| 1100 | } | 1111 | } |
| 1101 | 1112 | ||
| 1102 | static int __devexit wm8983_spi_remove(struct spi_device *spi) | 1113 | static int __devexit wm8983_spi_remove(struct spi_device *spi) |
| 1103 | { | 1114 | { |
| 1104 | snd_soc_unregister_codec(&spi->dev); | 1115 | snd_soc_unregister_codec(&spi->dev); |
| 1105 | kfree(spi_get_drvdata(spi)); | ||
| 1106 | return 0; | 1116 | return 0; |
| 1107 | } | 1117 | } |
| 1108 | 1118 | ||
| @@ -1123,24 +1133,28 @@ static __devinit int wm8983_i2c_probe(struct i2c_client *i2c, | |||
| 1123 | struct wm8983_priv *wm8983; | 1133 | struct wm8983_priv *wm8983; |
| 1124 | int ret; | 1134 | int ret; |
| 1125 | 1135 | ||
| 1126 | wm8983 = kzalloc(sizeof *wm8983, GFP_KERNEL); | 1136 | wm8983 = devm_kzalloc(&i2c->dev, sizeof *wm8983, GFP_KERNEL); |
| 1127 | if (!wm8983) | 1137 | if (!wm8983) |
| 1128 | return -ENOMEM; | 1138 | return -ENOMEM; |
| 1129 | 1139 | ||
| 1130 | wm8983->control_type = SND_SOC_I2C; | 1140 | wm8983->regmap = devm_regmap_init_i2c(i2c, &wm8983_regmap); |
| 1141 | if (IS_ERR(wm8983->regmap)) { | ||
| 1142 | ret = PTR_ERR(wm8983->regmap); | ||
| 1143 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); | ||
| 1144 | return ret; | ||
| 1145 | } | ||
| 1146 | |||
| 1131 | i2c_set_clientdata(i2c, wm8983); | 1147 | i2c_set_clientdata(i2c, wm8983); |
| 1132 | 1148 | ||
| 1133 | ret = snd_soc_register_codec(&i2c->dev, | 1149 | ret = snd_soc_register_codec(&i2c->dev, |
| 1134 | &soc_codec_dev_wm8983, &wm8983_dai, 1); | 1150 | &soc_codec_dev_wm8983, &wm8983_dai, 1); |
| 1135 | if (ret < 0) | 1151 | |
| 1136 | kfree(wm8983); | ||
| 1137 | return ret; | 1152 | return ret; |
| 1138 | } | 1153 | } |
| 1139 | 1154 | ||
| 1140 | static __devexit int wm8983_i2c_remove(struct i2c_client *client) | 1155 | static __devexit int wm8983_i2c_remove(struct i2c_client *client) |
| 1141 | { | 1156 | { |
| 1142 | snd_soc_unregister_codec(&client->dev); | 1157 | snd_soc_unregister_codec(&client->dev); |
| 1143 | kfree(i2c_get_clientdata(client)); | ||
| 1144 | return 0; | 1158 | return 0; |
| 1145 | } | 1159 | } |
| 1146 | 1160 | ||
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index db63c97ddf51..c28c83e5395d 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
| @@ -1388,7 +1388,8 @@ static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, | |||
| 1388 | struct wm8990_priv *wm8990; | 1388 | struct wm8990_priv *wm8990; |
| 1389 | int ret; | 1389 | int ret; |
| 1390 | 1390 | ||
| 1391 | wm8990 = kzalloc(sizeof(struct wm8990_priv), GFP_KERNEL); | 1391 | wm8990 = devm_kzalloc(&i2c->dev, sizeof(struct wm8990_priv), |
| 1392 | GFP_KERNEL); | ||
| 1392 | if (wm8990 == NULL) | 1393 | if (wm8990 == NULL) |
| 1393 | return -ENOMEM; | 1394 | return -ENOMEM; |
| 1394 | 1395 | ||
| @@ -1396,15 +1397,14 @@ static __devinit int wm8990_i2c_probe(struct i2c_client *i2c, | |||
| 1396 | 1397 | ||
| 1397 | ret = snd_soc_register_codec(&i2c->dev, | 1398 | ret = snd_soc_register_codec(&i2c->dev, |
| 1398 | &soc_codec_dev_wm8990, &wm8990_dai, 1); | 1399 | &soc_codec_dev_wm8990, &wm8990_dai, 1); |
| 1399 | if (ret < 0) | 1400 | |
| 1400 | kfree(wm8990); | ||
| 1401 | return ret; | 1401 | return ret; |
| 1402 | } | 1402 | } |
| 1403 | 1403 | ||
| 1404 | static __devexit int wm8990_i2c_remove(struct i2c_client *client) | 1404 | static __devexit int wm8990_i2c_remove(struct i2c_client *client) |
| 1405 | { | 1405 | { |
| 1406 | snd_soc_unregister_codec(&client->dev); | 1406 | snd_soc_unregister_codec(&client->dev); |
| 1407 | kfree(i2c_get_clientdata(client)); | 1407 | |
| 1408 | return 0; | 1408 | return 0; |
| 1409 | } | 1409 | } |
| 1410 | 1410 | ||
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 9ac31ba9b82e..fe439f027e10 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c | |||
| @@ -1363,7 +1363,7 @@ static __devinit int wm8991_i2c_probe(struct i2c_client *i2c, | |||
| 1363 | struct wm8991_priv *wm8991; | 1363 | struct wm8991_priv *wm8991; |
| 1364 | int ret; | 1364 | int ret; |
| 1365 | 1365 | ||
| 1366 | wm8991 = kzalloc(sizeof *wm8991, GFP_KERNEL); | 1366 | wm8991 = devm_kzalloc(&i2c->dev, sizeof(*wm8991), GFP_KERNEL); |
| 1367 | if (!wm8991) | 1367 | if (!wm8991) |
| 1368 | return -ENOMEM; | 1368 | return -ENOMEM; |
| 1369 | 1369 | ||
| @@ -1372,15 +1372,14 @@ static __devinit int wm8991_i2c_probe(struct i2c_client *i2c, | |||
| 1372 | 1372 | ||
| 1373 | ret = snd_soc_register_codec(&i2c->dev, | 1373 | ret = snd_soc_register_codec(&i2c->dev, |
| 1374 | &soc_codec_dev_wm8991, &wm8991_dai, 1); | 1374 | &soc_codec_dev_wm8991, &wm8991_dai, 1); |
| 1375 | if (ret < 0) | 1375 | |
| 1376 | kfree(wm8991); | ||
| 1377 | return ret; | 1376 | return ret; |
| 1378 | } | 1377 | } |
| 1379 | 1378 | ||
| 1380 | static __devexit int wm8991_i2c_remove(struct i2c_client *client) | 1379 | static __devexit int wm8991_i2c_remove(struct i2c_client *client) |
| 1381 | { | 1380 | { |
| 1382 | snd_soc_unregister_codec(&client->dev); | 1381 | snd_soc_unregister_codec(&client->dev); |
| 1383 | kfree(i2c_get_clientdata(client)); | 1382 | |
| 1384 | return 0; | 1383 | return 0; |
| 1385 | } | 1384 | } |
| 1386 | 1385 | ||
| @@ -1400,23 +1399,7 @@ static struct i2c_driver wm8991_i2c_driver = { | |||
| 1400 | .id_table = wm8991_i2c_id, | 1399 | .id_table = wm8991_i2c_id, |
| 1401 | }; | 1400 | }; |
| 1402 | 1401 | ||
| 1403 | static int __init wm8991_modinit(void) | 1402 | module_i2c_driver(wm8991_i2c_driver); |
| 1404 | { | ||
| 1405 | int ret; | ||
| 1406 | ret = i2c_add_driver(&wm8991_i2c_driver); | ||
| 1407 | if (ret != 0) { | ||
| 1408 | printk(KERN_ERR "Failed to register WM8991 I2C driver: %d\n", | ||
| 1409 | ret); | ||
| 1410 | } | ||
| 1411 | return 0; | ||
| 1412 | } | ||
| 1413 | module_init(wm8991_modinit); | ||
| 1414 | |||
| 1415 | static void __exit wm8991_exit(void) | ||
| 1416 | { | ||
| 1417 | i2c_del_driver(&wm8991_i2c_driver); | ||
| 1418 | } | ||
| 1419 | module_exit(wm8991_exit); | ||
| 1420 | 1403 | ||
| 1421 | MODULE_DESCRIPTION("ASoC WM8991 driver"); | 1404 | MODULE_DESCRIPTION("ASoC WM8991 driver"); |
| 1422 | MODULE_AUTHOR("Graeme Gregory"); | 1405 | MODULE_AUTHOR("Graeme Gregory"); |
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 9fd80d688979..94737a30716b 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
| @@ -1520,6 +1520,8 @@ static int wm8993_probe(struct snd_soc_codec *codec) | |||
| 1520 | wm8993->pdata.lineout2fb, | 1520 | wm8993->pdata.lineout2fb, |
| 1521 | wm8993->pdata.jd_scthr, | 1521 | wm8993->pdata.jd_scthr, |
| 1522 | wm8993->pdata.jd_thr, | 1522 | wm8993->pdata.jd_thr, |
| 1523 | wm8993->pdata.micbias1_delay, | ||
| 1524 | wm8993->pdata.micbias2_delay, | ||
| 1523 | wm8993->pdata.micbias1_lvl, | 1525 | wm8993->pdata.micbias1_lvl, |
| 1524 | wm8993->pdata.micbias2_lvl); | 1526 | wm8993->pdata.micbias2_lvl); |
| 1525 | 1527 | ||
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 6c9eeca85b95..2b2dadc54dac 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
| @@ -671,6 +671,18 @@ SOC_SINGLE_TLV("AIF2 EQ5 Volume", WM8994_AIF2_EQ_GAINS_2, 6, 31, 0, | |||
| 671 | eq_tlv), | 671 | eq_tlv), |
| 672 | }; | 672 | }; |
| 673 | 673 | ||
| 674 | static const struct snd_kcontrol_new wm8994_drc_controls[] = { | ||
| 675 | SND_SOC_BYTES_MASK("AIF1.1 DRC", WM8994_AIF1_DRC1_1, 5, | ||
| 676 | WM8994_AIF1DAC1_DRC_ENA | WM8994_AIF1ADC1L_DRC_ENA | | ||
| 677 | WM8994_AIF1ADC1R_DRC_ENA), | ||
| 678 | SND_SOC_BYTES_MASK("AIF1.2 DRC", WM8994_AIF1_DRC2_1, 5, | ||
| 679 | WM8994_AIF1DAC2_DRC_ENA | WM8994_AIF1ADC2L_DRC_ENA | | ||
| 680 | WM8994_AIF1ADC2R_DRC_ENA), | ||
| 681 | SND_SOC_BYTES_MASK("AIF2 DRC", WM8994_AIF2_DRC_1, 5, | ||
| 682 | WM8994_AIF2DAC_DRC_ENA | WM8994_AIF2ADCL_DRC_ENA | | ||
| 683 | WM8994_AIF2ADCR_DRC_ENA), | ||
| 684 | }; | ||
| 685 | |||
| 674 | static const char *wm8958_ng_text[] = { | 686 | static const char *wm8958_ng_text[] = { |
| 675 | "30ms", "125ms", "250ms", "500ms", | 687 | "30ms", "125ms", "250ms", "500ms", |
| 676 | }; | 688 | }; |
| @@ -789,11 +801,27 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w, | |||
| 789 | struct snd_kcontrol *kcontrol, int event) | 801 | struct snd_kcontrol *kcontrol, int event) |
| 790 | { | 802 | { |
| 791 | struct snd_soc_codec *codec = w->codec; | 803 | struct snd_soc_codec *codec = w->codec; |
| 804 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
| 792 | 805 | ||
| 793 | switch (event) { | 806 | switch (event) { |
| 794 | case SND_SOC_DAPM_PRE_PMU: | 807 | case SND_SOC_DAPM_PRE_PMU: |
| 795 | return configure_clock(codec); | 808 | return configure_clock(codec); |
| 796 | 809 | ||
| 810 | case SND_SOC_DAPM_POST_PMU: | ||
| 811 | /* | ||
| 812 | * JACKDET won't run until we start the clock and it | ||
| 813 | * only reports deltas, make sure we notify the state | ||
| 814 | * up the stack on startup. Use a *very* generous | ||
| 815 | * timeout for paranoia, there's no urgency and we | ||
| 816 | * don't want false reports. | ||
| 817 | */ | ||
| 818 | if (wm8994->jackdet && !wm8994->clk_has_run) { | ||
| 819 | schedule_delayed_work(&wm8994->jackdet_bootstrap, | ||
| 820 | msecs_to_jiffies(1000)); | ||
| 821 | wm8994->clk_has_run = true; | ||
| 822 | } | ||
| 823 | break; | ||
| 824 | |||
| 797 | case SND_SOC_DAPM_POST_PMD: | 825 | case SND_SOC_DAPM_POST_PMD: |
| 798 | configure_clock(codec); | 826 | configure_clock(codec); |
| 799 | break; | 827 | break; |
| @@ -1632,7 +1660,8 @@ SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, vmid_event, | |||
| 1632 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | 1660 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
| 1633 | 1661 | ||
| 1634 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, | 1662 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, |
| 1635 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 1663 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
| 1664 | SND_SOC_DAPM_PRE_PMD), | ||
| 1636 | 1665 | ||
| 1637 | SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0), | 1666 | SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0), |
| 1638 | SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, 2, 0, NULL, 0), | 1667 | SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, 2, 0, NULL, 0), |
| @@ -2102,6 +2131,10 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
| 2102 | case WM8994_FLL_SRC_LRCLK: | 2131 | case WM8994_FLL_SRC_LRCLK: |
| 2103 | case WM8994_FLL_SRC_BCLK: | 2132 | case WM8994_FLL_SRC_BCLK: |
| 2104 | break; | 2133 | break; |
| 2134 | case WM8994_FLL_SRC_INTERNAL: | ||
| 2135 | freq_in = 12000000; | ||
| 2136 | freq_out = 12000000; | ||
| 2137 | break; | ||
| 2105 | default: | 2138 | default: |
| 2106 | return -EINVAL; | 2139 | return -EINVAL; |
| 2107 | } | 2140 | } |
| @@ -2161,12 +2194,14 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
| 2161 | 2194 | ||
| 2162 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_4 + reg_offset, | 2195 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_4 + reg_offset, |
| 2163 | WM8994_FLL1_N_MASK, | 2196 | WM8994_FLL1_N_MASK, |
| 2164 | fll.n << WM8994_FLL1_N_SHIFT); | 2197 | fll.n << WM8994_FLL1_N_SHIFT); |
| 2165 | 2198 | ||
| 2166 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, | 2199 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, |
| 2167 | WM8958_FLL1_BYP | | 2200 | WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP | |
| 2168 | WM8994_FLL1_REFCLK_DIV_MASK | | 2201 | WM8994_FLL1_REFCLK_DIV_MASK | |
| 2169 | WM8994_FLL1_REFCLK_SRC_MASK, | 2202 | WM8994_FLL1_REFCLK_SRC_MASK, |
| 2203 | ((src == WM8994_FLL_SRC_INTERNAL) | ||
| 2204 | << WM8994_FLL1_FRC_NCO_SHIFT) | | ||
| 2170 | (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | | 2205 | (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | |
| 2171 | (src - 1)); | 2206 | (src - 1)); |
| 2172 | 2207 | ||
| @@ -2192,13 +2227,16 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
| 2192 | } | 2227 | } |
| 2193 | } | 2228 | } |
| 2194 | 2229 | ||
| 2230 | reg = WM8994_FLL1_ENA; | ||
| 2231 | |||
| 2195 | if (fll.k) | 2232 | if (fll.k) |
| 2196 | reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC; | 2233 | reg |= WM8994_FLL1_FRAC; |
| 2197 | else | 2234 | if (src == WM8994_FLL_SRC_INTERNAL) |
| 2198 | reg = WM8994_FLL1_ENA; | 2235 | reg |= WM8994_FLL1_OSC_ENA; |
| 2236 | |||
| 2199 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, | 2237 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, |
| 2200 | WM8994_FLL1_ENA | WM8994_FLL1_FRAC, | 2238 | WM8994_FLL1_ENA | WM8994_FLL1_OSC_ENA | |
| 2201 | reg); | 2239 | WM8994_FLL1_FRAC, reg); |
| 2202 | 2240 | ||
| 2203 | if (wm8994->fll_locked_irq) { | 2241 | if (wm8994->fll_locked_irq) { |
| 2204 | timeout = wait_for_completion_timeout(&wm8994->fll_locked[id], | 2242 | timeout = wait_for_completion_timeout(&wm8994->fll_locked[id], |
| @@ -3027,7 +3065,7 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec) | |||
| 3027 | 3065 | ||
| 3028 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | 3066 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) |
| 3029 | { | 3067 | { |
| 3030 | struct snd_soc_codec *codec = wm8994->codec; | 3068 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
| 3031 | struct wm8994_pdata *pdata = wm8994->pdata; | 3069 | struct wm8994_pdata *pdata = wm8994->pdata; |
| 3032 | struct snd_kcontrol_new controls[] = { | 3070 | struct snd_kcontrol_new controls[] = { |
| 3033 | SOC_ENUM_EXT("AIF1.1 EQ Mode", | 3071 | SOC_ENUM_EXT("AIF1.1 EQ Mode", |
| @@ -3085,16 +3123,16 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | |||
| 3085 | wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; | 3123 | wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; |
| 3086 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; | 3124 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; |
| 3087 | 3125 | ||
| 3088 | ret = snd_soc_add_codec_controls(wm8994->codec, controls, | 3126 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, |
| 3089 | ARRAY_SIZE(controls)); | 3127 | ARRAY_SIZE(controls)); |
| 3090 | if (ret != 0) | 3128 | if (ret != 0) |
| 3091 | dev_err(wm8994->codec->dev, | 3129 | dev_err(wm8994->hubs.codec->dev, |
| 3092 | "Failed to add ReTune Mobile controls: %d\n", ret); | 3130 | "Failed to add ReTune Mobile controls: %d\n", ret); |
| 3093 | } | 3131 | } |
| 3094 | 3132 | ||
| 3095 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | 3133 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) |
| 3096 | { | 3134 | { |
| 3097 | struct snd_soc_codec *codec = wm8994->codec; | 3135 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
| 3098 | struct wm8994_pdata *pdata = wm8994->pdata; | 3136 | struct wm8994_pdata *pdata = wm8994->pdata; |
| 3099 | int ret, i; | 3137 | int ret, i; |
| 3100 | 3138 | ||
| @@ -3107,6 +3145,8 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
| 3107 | pdata->lineout2fb, | 3145 | pdata->lineout2fb, |
| 3108 | pdata->jd_scthr, | 3146 | pdata->jd_scthr, |
| 3109 | pdata->jd_thr, | 3147 | pdata->jd_thr, |
| 3148 | pdata->micb1_delay, | ||
| 3149 | pdata->micb2_delay, | ||
| 3110 | pdata->micbias1_lvl, | 3150 | pdata->micbias1_lvl, |
| 3111 | pdata->micbias2_lvl); | 3151 | pdata->micbias2_lvl); |
| 3112 | 3152 | ||
| @@ -3123,10 +3163,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
| 3123 | }; | 3163 | }; |
| 3124 | 3164 | ||
| 3125 | /* We need an array of texts for the enum API */ | 3165 | /* We need an array of texts for the enum API */ |
| 3126 | wm8994->drc_texts = devm_kzalloc(wm8994->codec->dev, | 3166 | wm8994->drc_texts = devm_kzalloc(wm8994->hubs.codec->dev, |
| 3127 | sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); | 3167 | sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); |
| 3128 | if (!wm8994->drc_texts) { | 3168 | if (!wm8994->drc_texts) { |
| 3129 | dev_err(wm8994->codec->dev, | 3169 | dev_err(wm8994->hubs.codec->dev, |
| 3130 | "Failed to allocate %d DRC config texts\n", | 3170 | "Failed to allocate %d DRC config texts\n", |
| 3131 | pdata->num_drc_cfgs); | 3171 | pdata->num_drc_cfgs); |
| 3132 | return; | 3172 | return; |
| @@ -3138,23 +3178,28 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
| 3138 | wm8994->drc_enum.max = pdata->num_drc_cfgs; | 3178 | wm8994->drc_enum.max = pdata->num_drc_cfgs; |
| 3139 | wm8994->drc_enum.texts = wm8994->drc_texts; | 3179 | wm8994->drc_enum.texts = wm8994->drc_texts; |
| 3140 | 3180 | ||
| 3141 | ret = snd_soc_add_codec_controls(wm8994->codec, controls, | 3181 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, |
| 3142 | ARRAY_SIZE(controls)); | 3182 | ARRAY_SIZE(controls)); |
| 3143 | if (ret != 0) | ||
| 3144 | dev_err(wm8994->codec->dev, | ||
| 3145 | "Failed to add DRC mode controls: %d\n", ret); | ||
| 3146 | |||
| 3147 | for (i = 0; i < WM8994_NUM_DRC; i++) | 3183 | for (i = 0; i < WM8994_NUM_DRC; i++) |
| 3148 | wm8994_set_drc(codec, i); | 3184 | wm8994_set_drc(codec, i); |
| 3185 | } else { | ||
| 3186 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, | ||
| 3187 | wm8994_drc_controls, | ||
| 3188 | ARRAY_SIZE(wm8994_drc_controls)); | ||
| 3149 | } | 3189 | } |
| 3150 | 3190 | ||
| 3191 | if (ret != 0) | ||
| 3192 | dev_err(wm8994->hubs.codec->dev, | ||
| 3193 | "Failed to add DRC mode controls: %d\n", ret); | ||
| 3194 | |||
| 3195 | |||
| 3151 | dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", | 3196 | dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", |
| 3152 | pdata->num_retune_mobile_cfgs); | 3197 | pdata->num_retune_mobile_cfgs); |
| 3153 | 3198 | ||
| 3154 | if (pdata->num_retune_mobile_cfgs) | 3199 | if (pdata->num_retune_mobile_cfgs) |
| 3155 | wm8994_handle_retune_mobile_pdata(wm8994); | 3200 | wm8994_handle_retune_mobile_pdata(wm8994); |
| 3156 | else | 3201 | else |
| 3157 | snd_soc_add_codec_controls(wm8994->codec, wm8994_eq_controls, | 3202 | snd_soc_add_codec_controls(wm8994->hubs.codec, wm8994_eq_controls, |
| 3158 | ARRAY_SIZE(wm8994_eq_controls)); | 3203 | ARRAY_SIZE(wm8994_eq_controls)); |
| 3159 | 3204 | ||
| 3160 | for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) { | 3205 | for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) { |
| @@ -3236,6 +3281,12 @@ int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
| 3236 | 3281 | ||
| 3237 | snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg); | 3282 | snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg); |
| 3238 | 3283 | ||
| 3284 | /* enable MICDET and MICSHRT deboune */ | ||
| 3285 | snd_soc_update_bits(codec, WM8994_IRQ_DEBOUNCE, | ||
| 3286 | WM8994_MIC1_DET_DB_MASK | WM8994_MIC1_SHRT_DB_MASK | | ||
| 3287 | WM8994_MIC2_DET_DB_MASK | WM8994_MIC2_SHRT_DB_MASK, | ||
| 3288 | WM8994_MIC1_DET_DB | WM8994_MIC1_SHRT_DB); | ||
| 3289 | |||
| 3239 | snd_soc_dapm_sync(&codec->dapm); | 3290 | snd_soc_dapm_sync(&codec->dapm); |
| 3240 | 3291 | ||
| 3241 | return 0; | 3292 | return 0; |
| @@ -3309,7 +3360,7 @@ static void wm8994_mic_work(struct work_struct *work) | |||
| 3309 | static irqreturn_t wm8994_mic_irq(int irq, void *data) | 3360 | static irqreturn_t wm8994_mic_irq(int irq, void *data) |
| 3310 | { | 3361 | { |
| 3311 | struct wm8994_priv *priv = data; | 3362 | struct wm8994_priv *priv = data; |
| 3312 | struct snd_soc_codec *codec = priv->codec; | 3363 | struct snd_soc_codec *codec = priv->hubs.codec; |
| 3313 | 3364 | ||
| 3314 | #ifndef CONFIG_SND_SOC_WM8994_MODULE | 3365 | #ifndef CONFIG_SND_SOC_WM8994_MODULE |
| 3315 | trace_snd_soc_jack_irq(dev_name(codec->dev)); | 3366 | trace_snd_soc_jack_irq(dev_name(codec->dev)); |
| @@ -3345,7 +3396,7 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
| 3345 | 3396 | ||
| 3346 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, | 3397 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, |
| 3347 | wm8994->btn_mask | | 3398 | wm8994->btn_mask | |
| 3348 | SND_JACK_HEADSET); | 3399 | SND_JACK_HEADSET); |
| 3349 | } | 3400 | } |
| 3350 | return; | 3401 | return; |
| 3351 | } | 3402 | } |
| @@ -3422,7 +3473,7 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
| 3422 | static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | 3473 | static irqreturn_t wm1811_jackdet_irq(int irq, void *data) |
| 3423 | { | 3474 | { |
| 3424 | struct wm8994_priv *wm8994 = data; | 3475 | struct wm8994_priv *wm8994 = data; |
| 3425 | struct snd_soc_codec *codec = wm8994->codec; | 3476 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
| 3426 | int reg; | 3477 | int reg; |
| 3427 | bool present; | 3478 | bool present; |
| 3428 | 3479 | ||
| @@ -3499,10 +3550,22 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | |||
| 3499 | SND_JACK_MECHANICAL | SND_JACK_HEADSET | | 3550 | SND_JACK_MECHANICAL | SND_JACK_HEADSET | |
| 3500 | wm8994->btn_mask); | 3551 | wm8994->btn_mask); |
| 3501 | 3552 | ||
| 3553 | /* Since we only report deltas force an update, ensures we | ||
| 3554 | * avoid bootstrapping issues with the core. */ | ||
| 3555 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, 0); | ||
| 3556 | |||
| 3502 | pm_runtime_put(codec->dev); | 3557 | pm_runtime_put(codec->dev); |
| 3503 | return IRQ_HANDLED; | 3558 | return IRQ_HANDLED; |
| 3504 | } | 3559 | } |
| 3505 | 3560 | ||
| 3561 | static void wm1811_jackdet_bootstrap(struct work_struct *work) | ||
| 3562 | { | ||
| 3563 | struct wm8994_priv *wm8994 = container_of(work, | ||
| 3564 | struct wm8994_priv, | ||
| 3565 | jackdet_bootstrap.work); | ||
| 3566 | wm1811_jackdet_irq(0, wm8994); | ||
| 3567 | } | ||
| 3568 | |||
| 3506 | /** | 3569 | /** |
| 3507 | * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ | 3570 | * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ |
| 3508 | * | 3571 | * |
| @@ -3573,6 +3636,10 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
| 3573 | * otherwise jump straight to microphone detection. | 3636 | * otherwise jump straight to microphone detection. |
| 3574 | */ | 3637 | */ |
| 3575 | if (wm8994->jackdet) { | 3638 | if (wm8994->jackdet) { |
| 3639 | /* Disable debounce for the initial detect */ | ||
| 3640 | snd_soc_update_bits(codec, WM1811_JACKDET_CTRL, | ||
| 3641 | WM1811_JACKDET_DB, 0); | ||
| 3642 | |||
| 3576 | snd_soc_update_bits(codec, WM8958_MICBIAS2, | 3643 | snd_soc_update_bits(codec, WM8958_MICBIAS2, |
| 3577 | WM8958_MICB2_DISCH, | 3644 | WM8958_MICB2_DISCH, |
| 3578 | WM8958_MICB2_DISCH); | 3645 | WM8958_MICB2_DISCH); |
| @@ -3600,7 +3667,7 @@ EXPORT_SYMBOL_GPL(wm8958_mic_detect); | |||
| 3600 | static irqreturn_t wm8958_mic_irq(int irq, void *data) | 3667 | static irqreturn_t wm8958_mic_irq(int irq, void *data) |
| 3601 | { | 3668 | { |
| 3602 | struct wm8994_priv *wm8994 = data; | 3669 | struct wm8994_priv *wm8994 = data; |
| 3603 | struct snd_soc_codec *codec = wm8994->codec; | 3670 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
| 3604 | int reg, count; | 3671 | int reg, count; |
| 3605 | 3672 | ||
| 3606 | /* | 3673 | /* |
| @@ -3690,15 +3757,15 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
| 3690 | unsigned int reg; | 3757 | unsigned int reg; |
| 3691 | int ret, i; | 3758 | int ret, i; |
| 3692 | 3759 | ||
| 3693 | wm8994->codec = codec; | 3760 | wm8994->hubs.codec = codec; |
| 3694 | codec->control_data = control->regmap; | 3761 | codec->control_data = control->regmap; |
| 3695 | 3762 | ||
| 3696 | snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | 3763 | snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); |
| 3697 | 3764 | ||
| 3698 | wm8994->codec = codec; | ||
| 3699 | |||
| 3700 | mutex_init(&wm8994->accdet_lock); | 3765 | mutex_init(&wm8994->accdet_lock); |
| 3701 | INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); | 3766 | INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); |
| 3767 | INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, | ||
| 3768 | wm1811_jackdet_bootstrap); | ||
| 3702 | 3769 | ||
| 3703 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | 3770 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) |
| 3704 | init_completion(&wm8994->fll_locked[i]); | 3771 | init_completion(&wm8994->fll_locked[i]); |
| @@ -3756,14 +3823,17 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
| 3756 | wm8994->hubs.no_cache_dac_hp_direct = true; | 3823 | wm8994->hubs.no_cache_dac_hp_direct = true; |
| 3757 | wm8994->fll_byp = true; | 3824 | wm8994->fll_byp = true; |
| 3758 | 3825 | ||
| 3759 | switch (wm8994->revision) { | 3826 | switch (control->cust_id) { |
| 3760 | case 0: | 3827 | case 0: |
| 3761 | case 1: | ||
| 3762 | case 2: | 3828 | case 2: |
| 3763 | case 3: | ||
| 3764 | wm8994->hubs.dcs_codes_l = -9; | 3829 | wm8994->hubs.dcs_codes_l = -9; |
| 3765 | wm8994->hubs.dcs_codes_r = -7; | 3830 | wm8994->hubs.dcs_codes_r = -7; |
| 3766 | break; | 3831 | break; |
| 3832 | case 1: | ||
| 3833 | case 3: | ||
| 3834 | wm8994->hubs.dcs_codes_l = -8; | ||
| 3835 | wm8994->hubs.dcs_codes_r = -7; | ||
| 3836 | break; | ||
| 3767 | default: | 3837 | default: |
| 3768 | break; | 3838 | break; |
| 3769 | } | 3839 | } |
| @@ -3852,7 +3922,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
| 3852 | 3922 | ||
| 3853 | switch (control->type) { | 3923 | switch (control->type) { |
| 3854 | case WM1811: | 3924 | case WM1811: |
| 3855 | if (wm8994->revision > 1) { | 3925 | if (control->cust_id > 1 || wm8994->revision > 1) { |
| 3856 | ret = wm8994_request_irq(wm8994->wm8994, | 3926 | ret = wm8994_request_irq(wm8994->wm8994, |
| 3857 | WM8994_IRQ_GPIO(6), | 3927 | WM8994_IRQ_GPIO(6), |
| 3858 | wm1811_jackdet_irq, "JACKDET", | 3928 | wm1811_jackdet_irq, "JACKDET", |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index d77e06f0a675..f142ec198db3 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
| @@ -28,10 +28,11 @@ | |||
| 28 | #define WM8994_FLL1 1 | 28 | #define WM8994_FLL1 1 |
| 29 | #define WM8994_FLL2 2 | 29 | #define WM8994_FLL2 2 |
| 30 | 30 | ||
| 31 | #define WM8994_FLL_SRC_MCLK1 1 | 31 | #define WM8994_FLL_SRC_MCLK1 1 |
| 32 | #define WM8994_FLL_SRC_MCLK2 2 | 32 | #define WM8994_FLL_SRC_MCLK2 2 |
| 33 | #define WM8994_FLL_SRC_LRCLK 3 | 33 | #define WM8994_FLL_SRC_LRCLK 3 |
| 34 | #define WM8994_FLL_SRC_BCLK 4 | 34 | #define WM8994_FLL_SRC_BCLK 4 |
| 35 | #define WM8994_FLL_SRC_INTERNAL 5 | ||
| 35 | 36 | ||
| 36 | enum wm8994_vmid_mode { | 37 | enum wm8994_vmid_mode { |
| 37 | WM8994_VMID_NORMAL, | 38 | WM8994_VMID_NORMAL, |
| @@ -72,7 +73,6 @@ struct wm8994; | |||
| 72 | struct wm8994_priv { | 73 | struct wm8994_priv { |
| 73 | struct wm_hubs_data hubs; | 74 | struct wm_hubs_data hubs; |
| 74 | struct wm8994 *wm8994; | 75 | struct wm8994 *wm8994; |
| 75 | struct snd_soc_codec *codec; | ||
| 76 | int sysclk[2]; | 76 | int sysclk[2]; |
| 77 | int sysclk_rate[2]; | 77 | int sysclk_rate[2]; |
| 78 | int mclk[2]; | 78 | int mclk[2]; |
| @@ -81,6 +81,7 @@ struct wm8994_priv { | |||
| 81 | struct completion fll_locked[2]; | 81 | struct completion fll_locked[2]; |
| 82 | bool fll_locked_irq; | 82 | bool fll_locked_irq; |
| 83 | bool fll_byp; | 83 | bool fll_byp; |
| 84 | bool clk_has_run; | ||
| 84 | 85 | ||
| 85 | int vmid_refcount; | 86 | int vmid_refcount; |
| 86 | int active_refcount; | 87 | int active_refcount; |
| @@ -134,6 +135,7 @@ struct wm8994_priv { | |||
| 134 | int btn_mask; | 135 | int btn_mask; |
| 135 | bool jackdet; | 136 | bool jackdet; |
| 136 | int jackdet_mode; | 137 | int jackdet_mode; |
| 138 | struct delayed_work jackdet_bootstrap; | ||
| 137 | 139 | ||
| 138 | wm8958_micdet_cb jack_cb; | 140 | wm8958_micdet_cb jack_cb; |
| 139 | void *jack_cb_data; | 141 | void *jack_cb_data; |
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 00f183dfa454..6dcb02c3666f 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
| @@ -931,7 +931,7 @@ SND_SOC_DAPM_INPUT("IN2RP"), | |||
| 931 | SND_SOC_DAPM_INPUT("DMIC1DAT"), | 931 | SND_SOC_DAPM_INPUT("DMIC1DAT"), |
| 932 | SND_SOC_DAPM_INPUT("DMIC2DAT"), | 932 | SND_SOC_DAPM_INPUT("DMIC2DAT"), |
| 933 | 933 | ||
| 934 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20), | 934 | SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20, 0), |
| 935 | SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0), | 935 | SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0), |
| 936 | SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), | 936 | SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), |
| 937 | SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), | 937 | SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), |
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 2c2346fdd637..c7ddc56175d1 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
| @@ -695,17 +695,7 @@ static struct i2c_driver wm9090_i2c_driver = { | |||
| 695 | .id_table = wm9090_id, | 695 | .id_table = wm9090_id, |
| 696 | }; | 696 | }; |
| 697 | 697 | ||
| 698 | static int __init wm9090_init(void) | 698 | module_i2c_driver(wm9090_i2c_driver); |
| 699 | { | ||
| 700 | return i2c_add_driver(&wm9090_i2c_driver); | ||
| 701 | } | ||
| 702 | module_init(wm9090_init); | ||
| 703 | |||
| 704 | static void __exit wm9090_exit(void) | ||
| 705 | { | ||
| 706 | i2c_del_driver(&wm9090_i2c_driver); | ||
| 707 | } | ||
| 708 | module_exit(wm9090_exit); | ||
| 709 | 699 | ||
| 710 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 700 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
| 711 | MODULE_DESCRIPTION("WM9090 ASoC driver"); | 701 | MODULE_DESCRIPTION("WM9090 ASoC driver"); |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index c6d2076a796b..4dd73ea08d0b 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
| @@ -132,8 +132,9 @@ SOC_SINGLE("Aux Playback Phone Volume", AC97_CD, 4, 7, 1), | |||
| 132 | SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 1), | 132 | SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 1), |
| 133 | SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8, 0, 31, 1), | 133 | SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8, 0, 31, 1), |
| 134 | 134 | ||
| 135 | SOC_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0), | 135 | SOC_SINGLE_TLV("Capture Boost Switch", AC97_REC_SEL, 14, 1, 0, boost_tlv), |
| 136 | SOC_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1), | 136 | SOC_SINGLE_TLV("Capture to Phone Boost Switch", AC97_REC_SEL, 11, 1, 1, |
| 137 | boost_tlv), | ||
| 137 | 138 | ||
| 138 | SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1), | 139 | SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1), |
| 139 | SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1), | 140 | SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1), |
| @@ -146,7 +147,7 @@ SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0), | |||
| 146 | SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1), | 147 | SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1), |
| 147 | SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1), | 148 | SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1), |
| 148 | 149 | ||
| 149 | SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1), | 150 | SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1), |
| 150 | SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), | 151 | SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), |
| 151 | SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 0), | 152 | SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 0), |
| 152 | SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), | 153 | SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), |
| @@ -634,7 +635,6 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec) | |||
| 634 | { | 635 | { |
| 635 | int ret = 0; | 636 | int ret = 0; |
| 636 | 637 | ||
| 637 | codec->control_data = codec; /* we don't use regmap! */ | ||
| 638 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 638 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
| 639 | if (ret < 0) { | 639 | if (ret < 0) { |
| 640 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); | 640 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); |
| @@ -699,8 +699,8 @@ static int __devexit wm9712_remove(struct platform_device *pdev) | |||
| 699 | 699 | ||
| 700 | static struct platform_driver wm9712_codec_driver = { | 700 | static struct platform_driver wm9712_codec_driver = { |
| 701 | .driver = { | 701 | .driver = { |
| 702 | .name = "wm9712-codec", | 702 | .name = "wm9712-codec", |
| 703 | .owner = THIS_MODULE, | 703 | .owner = THIS_MODULE, |
| 704 | }, | 704 | }, |
| 705 | 705 | ||
| 706 | .probe = wm9712_probe, | 706 | .probe = wm9712_probe, |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index d0b8a3287a85..3eb19fb71d17 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
| @@ -1196,7 +1196,6 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) | |||
| 1196 | if (wm9713 == NULL) | 1196 | if (wm9713 == NULL) |
| 1197 | return -ENOMEM; | 1197 | return -ENOMEM; |
| 1198 | snd_soc_codec_set_drvdata(codec, wm9713); | 1198 | snd_soc_codec_set_drvdata(codec, wm9713); |
| 1199 | codec->control_data = wm9713; /* we don't use regmap! */ | ||
| 1200 | 1199 | ||
| 1201 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 1200 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); |
| 1202 | if (ret < 0) | 1201 | if (ret < 0) |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 61baa48823cb..867ae97ddcec 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
| @@ -199,15 +199,56 @@ static void wm_hubs_dcs_cache_set(struct snd_soc_codec *codec, u16 dcs_cfg) | |||
| 199 | list_add_tail(&cache->list, &hubs->dcs_cache); | 199 | list_add_tail(&cache->list, &hubs->dcs_cache); |
| 200 | } | 200 | } |
| 201 | 201 | ||
| 202 | static void wm_hubs_read_dc_servo(struct snd_soc_codec *codec, | ||
| 203 | u16 *reg_l, u16 *reg_r) | ||
| 204 | { | ||
| 205 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | ||
| 206 | u16 dcs_reg, reg; | ||
| 207 | |||
| 208 | switch (hubs->dcs_readback_mode) { | ||
| 209 | case 2: | ||
| 210 | dcs_reg = WM8994_DC_SERVO_4E; | ||
| 211 | break; | ||
| 212 | case 1: | ||
| 213 | dcs_reg = WM8994_DC_SERVO_READBACK; | ||
| 214 | break; | ||
| 215 | default: | ||
| 216 | dcs_reg = WM8993_DC_SERVO_3; | ||
| 217 | break; | ||
| 218 | } | ||
| 219 | |||
| 220 | /* Different chips in the family support different readback | ||
| 221 | * methods. | ||
| 222 | */ | ||
| 223 | switch (hubs->dcs_readback_mode) { | ||
| 224 | case 0: | ||
| 225 | *reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) | ||
| 226 | & WM8993_DCS_INTEG_CHAN_0_MASK; | ||
| 227 | *reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) | ||
| 228 | & WM8993_DCS_INTEG_CHAN_1_MASK; | ||
| 229 | break; | ||
| 230 | case 2: | ||
| 231 | case 1: | ||
| 232 | reg = snd_soc_read(codec, dcs_reg); | ||
| 233 | *reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) | ||
| 234 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; | ||
| 235 | *reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; | ||
| 236 | break; | ||
| 237 | default: | ||
| 238 | WARN(1, "Unknown DCS readback method\n"); | ||
| 239 | return; | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 202 | /* | 243 | /* |
| 203 | * Startup calibration of the DC servo | 244 | * Startup calibration of the DC servo |
| 204 | */ | 245 | */ |
| 205 | static void calibrate_dc_servo(struct snd_soc_codec *codec) | 246 | static void enable_dc_servo(struct snd_soc_codec *codec) |
| 206 | { | 247 | { |
| 207 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 248 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
| 208 | struct wm_hubs_dcs_cache *cache; | 249 | struct wm_hubs_dcs_cache *cache; |
| 209 | s8 offset; | 250 | s8 offset; |
| 210 | u16 reg, reg_l, reg_r, dcs_cfg, dcs_reg; | 251 | u16 reg_l, reg_r, dcs_cfg, dcs_reg; |
| 211 | 252 | ||
| 212 | switch (hubs->dcs_readback_mode) { | 253 | switch (hubs->dcs_readback_mode) { |
| 213 | case 2: | 254 | case 2: |
| @@ -245,27 +286,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
| 245 | WM8993_DCS_TRIG_STARTUP_1); | 286 | WM8993_DCS_TRIG_STARTUP_1); |
| 246 | } | 287 | } |
| 247 | 288 | ||
| 248 | /* Different chips in the family support different readback | 289 | wm_hubs_read_dc_servo(codec, ®_l, ®_r); |
| 249 | * methods. | ||
| 250 | */ | ||
| 251 | switch (hubs->dcs_readback_mode) { | ||
| 252 | case 0: | ||
| 253 | reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) | ||
| 254 | & WM8993_DCS_INTEG_CHAN_0_MASK; | ||
| 255 | reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) | ||
| 256 | & WM8993_DCS_INTEG_CHAN_1_MASK; | ||
| 257 | break; | ||
| 258 | case 2: | ||
| 259 | case 1: | ||
| 260 | reg = snd_soc_read(codec, dcs_reg); | ||
| 261 | reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) | ||
| 262 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; | ||
| 263 | reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; | ||
| 264 | break; | ||
| 265 | default: | ||
| 266 | WARN(1, "Unknown DCS readback method\n"); | ||
| 267 | return; | ||
| 268 | } | ||
| 269 | 290 | ||
| 270 | dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); | 291 | dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); |
| 271 | 292 | ||
| @@ -276,12 +297,16 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
| 276 | hubs->dcs_codes_l, hubs->dcs_codes_r); | 297 | hubs->dcs_codes_l, hubs->dcs_codes_r); |
| 277 | 298 | ||
| 278 | /* HPOUT1R */ | 299 | /* HPOUT1R */ |
| 279 | offset = reg_r; | 300 | offset = (s8)reg_r; |
| 301 | dev_dbg(codec->dev, "DCS right %d->%d\n", offset, | ||
| 302 | offset + hubs->dcs_codes_r); | ||
| 280 | offset += hubs->dcs_codes_r; | 303 | offset += hubs->dcs_codes_r; |
| 281 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; | 304 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
| 282 | 305 | ||
| 283 | /* HPOUT1L */ | 306 | /* HPOUT1L */ |
| 284 | offset = reg_l; | 307 | offset = (s8)reg_l; |
| 308 | dev_dbg(codec->dev, "DCS left %d->%d\n", offset, | ||
| 309 | offset + hubs->dcs_codes_l); | ||
| 285 | offset += hubs->dcs_codes_l; | 310 | offset += hubs->dcs_codes_l; |
| 286 | dcs_cfg |= (u8)offset; | 311 | dcs_cfg |= (u8)offset; |
| 287 | 312 | ||
| @@ -535,7 +560,7 @@ static int hp_event(struct snd_soc_dapm_widget *w, | |||
| 535 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, | 560 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, |
| 536 | WM8993_DCS_TIMER_PERIOD_01_MASK, 0); | 561 | WM8993_DCS_TIMER_PERIOD_01_MASK, 0); |
| 537 | 562 | ||
| 538 | calibrate_dc_servo(codec); | 563 | enable_dc_servo(codec); |
| 539 | 564 | ||
| 540 | reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | | 565 | reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | |
| 541 | WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; | 566 | WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; |
| @@ -619,6 +644,28 @@ static int lineout_event(struct snd_soc_dapm_widget *w, | |||
| 619 | return 0; | 644 | return 0; |
| 620 | } | 645 | } |
| 621 | 646 | ||
| 647 | static int micbias_event(struct snd_soc_dapm_widget *w, | ||
| 648 | struct snd_kcontrol *kcontrol, int event) | ||
| 649 | { | ||
| 650 | struct snd_soc_codec *codec = w->codec; | ||
| 651 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | ||
| 652 | |||
| 653 | switch (w->shift) { | ||
| 654 | case WM8993_MICB1_ENA_SHIFT: | ||
| 655 | if (hubs->micb1_delay) | ||
| 656 | msleep(hubs->micb1_delay); | ||
| 657 | break; | ||
| 658 | case WM8993_MICB2_ENA_SHIFT: | ||
| 659 | if (hubs->micb2_delay) | ||
| 660 | msleep(hubs->micb2_delay); | ||
| 661 | break; | ||
| 662 | default: | ||
| 663 | return -EINVAL; | ||
| 664 | } | ||
| 665 | |||
| 666 | return 0; | ||
| 667 | } | ||
| 668 | |||
| 622 | void wm_hubs_update_class_w(struct snd_soc_codec *codec) | 669 | void wm_hubs_update_class_w(struct snd_soc_codec *codec) |
| 623 | { | 670 | { |
| 624 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 671 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
| @@ -634,6 +681,11 @@ void wm_hubs_update_class_w(struct snd_soc_codec *codec) | |||
| 634 | 681 | ||
| 635 | snd_soc_update_bits(codec, WM8993_CLASS_W_0, | 682 | snd_soc_update_bits(codec, WM8993_CLASS_W_0, |
| 636 | WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ, enable); | 683 | WM8993_CP_DYN_V | WM8993_CP_DYN_FREQ, enable); |
| 684 | |||
| 685 | snd_soc_write(codec, WM8993_LEFT_OUTPUT_VOLUME, | ||
| 686 | snd_soc_read(codec, WM8993_LEFT_OUTPUT_VOLUME)); | ||
| 687 | snd_soc_write(codec, WM8993_RIGHT_OUTPUT_VOLUME, | ||
| 688 | snd_soc_read(codec, WM8993_RIGHT_OUTPUT_VOLUME)); | ||
| 637 | } | 689 | } |
| 638 | EXPORT_SYMBOL_GPL(wm_hubs_update_class_w); | 690 | EXPORT_SYMBOL_GPL(wm_hubs_update_class_w); |
| 639 | 691 | ||
| @@ -809,8 +861,10 @@ SND_SOC_DAPM_INPUT("IN1RP"), | |||
| 809 | SND_SOC_DAPM_INPUT("IN2RN"), | 861 | SND_SOC_DAPM_INPUT("IN2RN"), |
| 810 | SND_SOC_DAPM_INPUT("IN2RP:VXRP"), | 862 | SND_SOC_DAPM_INPUT("IN2RP:VXRP"), |
| 811 | 863 | ||
| 812 | SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0), | 864 | SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, |
| 813 | SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0), | 865 | micbias_event, SND_SOC_DAPM_POST_PMU), |
| 866 | SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, | ||
| 867 | micbias_event, SND_SOC_DAPM_POST_PMU), | ||
| 814 | 868 | ||
| 815 | SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, | 869 | SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, |
| 816 | in1l_pga, ARRAY_SIZE(in1l_pga)), | 870 | in1l_pga, ARRAY_SIZE(in1l_pga)), |
| @@ -1112,6 +1166,8 @@ int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, | |||
| 1112 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 1166 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
| 1113 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 1167 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
| 1114 | 1168 | ||
| 1169 | hubs->codec = codec; | ||
| 1170 | |||
| 1115 | INIT_LIST_HEAD(&hubs->dcs_cache); | 1171 | INIT_LIST_HEAD(&hubs->dcs_cache); |
| 1116 | init_completion(&hubs->dcs_done); | 1172 | init_completion(&hubs->dcs_done); |
| 1117 | 1173 | ||
| @@ -1143,13 +1199,16 @@ EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes); | |||
| 1143 | int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec, | 1199 | int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec, |
| 1144 | int lineout1_diff, int lineout2_diff, | 1200 | int lineout1_diff, int lineout2_diff, |
| 1145 | int lineout1fb, int lineout2fb, | 1201 | int lineout1fb, int lineout2fb, |
| 1146 | int jd_scthr, int jd_thr, int micbias1_lvl, | 1202 | int jd_scthr, int jd_thr, |
| 1147 | int micbias2_lvl) | 1203 | int micbias1_delay, int micbias2_delay, |
| 1204 | int micbias1_lvl, int micbias2_lvl) | ||
| 1148 | { | 1205 | { |
| 1149 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 1206 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
| 1150 | 1207 | ||
| 1151 | hubs->lineout1_se = !lineout1_diff; | 1208 | hubs->lineout1_se = !lineout1_diff; |
| 1152 | hubs->lineout2_se = !lineout2_diff; | 1209 | hubs->lineout2_se = !lineout2_diff; |
| 1210 | hubs->micb1_delay = micbias1_delay; | ||
| 1211 | hubs->micb2_delay = micbias2_delay; | ||
| 1153 | 1212 | ||
| 1154 | if (!lineout1_diff) | 1213 | if (!lineout1_diff) |
| 1155 | snd_soc_update_bits(codec, WM8993_LINE_MIXER1, | 1214 | snd_soc_update_bits(codec, WM8993_LINE_MIXER1, |
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index da2dc899ce6d..24c763df21f9 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h | |||
| @@ -36,6 +36,9 @@ struct wm_hubs_data { | |||
| 36 | struct list_head dcs_cache; | 36 | struct list_head dcs_cache; |
| 37 | bool (*check_class_w_digital)(struct snd_soc_codec *); | 37 | bool (*check_class_w_digital)(struct snd_soc_codec *); |
| 38 | 38 | ||
| 39 | int micb1_delay; | ||
| 40 | int micb2_delay; | ||
| 41 | |||
| 39 | bool lineout1_se; | 42 | bool lineout1_se; |
| 40 | bool lineout1n_ena; | 43 | bool lineout1n_ena; |
| 41 | bool lineout1p_ena; | 44 | bool lineout1p_ena; |
| @@ -46,6 +49,8 @@ struct wm_hubs_data { | |||
| 46 | 49 | ||
| 47 | bool dcs_done_irq; | 50 | bool dcs_done_irq; |
| 48 | struct completion dcs_done; | 51 | struct completion dcs_done; |
| 52 | |||
| 53 | struct snd_soc_codec *codec; | ||
| 49 | }; | 54 | }; |
| 50 | 55 | ||
| 51 | extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); | 56 | extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); |
| @@ -54,6 +59,7 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *, | |||
| 54 | int lineout1_diff, int lineout2_diff, | 59 | int lineout1_diff, int lineout2_diff, |
| 55 | int lineout1fb, int lineout2fb, | 60 | int lineout1fb, int lineout2fb, |
| 56 | int jd_scthr, int jd_thr, | 61 | int jd_scthr, int jd_thr, |
| 62 | int micbias1_dly, int micbias2_dly, | ||
| 57 | int micbias1_lvl, int micbias2_lvl); | 63 | int micbias1_lvl, int micbias2_lvl); |
| 58 | 64 | ||
| 59 | extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); | 65 | extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); |
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 10a2d8c788b7..6fac5af13298 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c | |||
| @@ -22,10 +22,6 @@ | |||
| 22 | #include <asm/dma.h> | 22 | #include <asm/dma.h> |
| 23 | #include <asm/mach-types.h> | 23 | #include <asm/mach-types.h> |
| 24 | 24 | ||
| 25 | #include <mach/asp.h> | ||
| 26 | #include <mach/edma.h> | ||
| 27 | #include <mach/mux.h> | ||
| 28 | |||
| 29 | #include "davinci-pcm.h" | 25 | #include "davinci-pcm.h" |
| 30 | #include "davinci-i2s.h" | 26 | #include "davinci-i2s.h" |
| 31 | #include "davinci-mcasp.h" | 27 | #include "davinci-mcasp.h" |
| @@ -160,7 +156,7 @@ static struct snd_soc_dai_link dm6446_evm_dai = { | |||
| 160 | .cpu_dai_name = "davinci-mcbsp", | 156 | .cpu_dai_name = "davinci-mcbsp", |
| 161 | .codec_dai_name = "tlv320aic3x-hifi", | 157 | .codec_dai_name = "tlv320aic3x-hifi", |
| 162 | .codec_name = "tlv320aic3x-codec.1-001b", | 158 | .codec_name = "tlv320aic3x-codec.1-001b", |
| 163 | .platform_name = "davinci-pcm-audio", | 159 | .platform_name = "davinci-mcbsp", |
| 164 | .init = evm_aic3x_init, | 160 | .init = evm_aic3x_init, |
| 165 | .ops = &evm_ops, | 161 | .ops = &evm_ops, |
| 166 | }; | 162 | }; |
| @@ -171,7 +167,7 @@ static struct snd_soc_dai_link dm355_evm_dai = { | |||
| 171 | .cpu_dai_name = "davinci-mcbsp.1", | 167 | .cpu_dai_name = "davinci-mcbsp.1", |
| 172 | .codec_dai_name = "tlv320aic3x-hifi", | 168 | .codec_dai_name = "tlv320aic3x-hifi", |
| 173 | .codec_name = "tlv320aic3x-codec.1-001b", | 169 | .codec_name = "tlv320aic3x-codec.1-001b", |
| 174 | .platform_name = "davinci-pcm-audio", | 170 | .platform_name = "davinci-mcbsp.1", |
| 175 | .init = evm_aic3x_init, | 171 | .init = evm_aic3x_init, |
| 176 | .ops = &evm_ops, | 172 | .ops = &evm_ops, |
| 177 | }; | 173 | }; |
| @@ -185,14 +181,15 @@ static struct snd_soc_dai_link dm365_evm_dai = { | |||
| 185 | .init = evm_aic3x_init, | 181 | .init = evm_aic3x_init, |
| 186 | .codec_name = "tlv320aic3x-codec.1-0018", | 182 | .codec_name = "tlv320aic3x-codec.1-0018", |
| 187 | .ops = &evm_ops, | 183 | .ops = &evm_ops, |
| 184 | .platform_name = "davinci-mcbsp", | ||
| 188 | #elif defined(CONFIG_SND_DM365_VOICE_CODEC) | 185 | #elif defined(CONFIG_SND_DM365_VOICE_CODEC) |
| 189 | .name = "Voice Codec - CQ93VC", | 186 | .name = "Voice Codec - CQ93VC", |
| 190 | .stream_name = "CQ93", | 187 | .stream_name = "CQ93", |
| 191 | .cpu_dai_name = "davinci-vcif", | 188 | .cpu_dai_name = "davinci-vcif", |
| 192 | .codec_dai_name = "cq93vc-hifi", | 189 | .codec_dai_name = "cq93vc-hifi", |
| 193 | .codec_name = "cq93vc-codec", | 190 | .codec_name = "cq93vc-codec", |
| 191 | .platform_name = "davinci-vcif", | ||
| 194 | #endif | 192 | #endif |
| 195 | .platform_name = "davinci-pcm-audio", | ||
| 196 | }; | 193 | }; |
| 197 | 194 | ||
| 198 | static struct snd_soc_dai_link dm6467_evm_dai[] = { | 195 | static struct snd_soc_dai_link dm6467_evm_dai[] = { |
| @@ -201,7 +198,7 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = { | |||
| 201 | .stream_name = "AIC3X", | 198 | .stream_name = "AIC3X", |
| 202 | .cpu_dai_name= "davinci-mcasp.0", | 199 | .cpu_dai_name= "davinci-mcasp.0", |
| 203 | .codec_dai_name = "tlv320aic3x-hifi", | 200 | .codec_dai_name = "tlv320aic3x-hifi", |
| 204 | .platform_name ="davinci-pcm-audio", | 201 | .platform_name = "davinci-mcasp.0", |
| 205 | .codec_name = "tlv320aic3x-codec.0-001a", | 202 | .codec_name = "tlv320aic3x-codec.0-001a", |
| 206 | .init = evm_aic3x_init, | 203 | .init = evm_aic3x_init, |
| 207 | .ops = &evm_ops, | 204 | .ops = &evm_ops, |
| @@ -212,7 +209,7 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = { | |||
| 212 | .cpu_dai_name= "davinci-mcasp.1", | 209 | .cpu_dai_name= "davinci-mcasp.1", |
| 213 | .codec_dai_name = "dit-hifi", | 210 | .codec_dai_name = "dit-hifi", |
| 214 | .codec_name = "spdif_dit", | 211 | .codec_name = "spdif_dit", |
| 215 | .platform_name = "davinci-pcm-audio", | 212 | .platform_name = "davinci-mcasp.1", |
| 216 | .ops = &evm_spdif_ops, | 213 | .ops = &evm_spdif_ops, |
| 217 | }, | 214 | }, |
| 218 | }; | 215 | }; |
| @@ -223,7 +220,7 @@ static struct snd_soc_dai_link da830_evm_dai = { | |||
| 223 | .cpu_dai_name = "davinci-mcasp.1", | 220 | .cpu_dai_name = "davinci-mcasp.1", |
| 224 | .codec_dai_name = "tlv320aic3x-hifi", | 221 | .codec_dai_name = "tlv320aic3x-hifi", |
| 225 | .codec_name = "tlv320aic3x-codec.1-0018", | 222 | .codec_name = "tlv320aic3x-codec.1-0018", |
| 226 | .platform_name = "davinci-pcm-audio", | 223 | .platform_name = "davinci-mcasp.1", |
| 227 | .init = evm_aic3x_init, | 224 | .init = evm_aic3x_init, |
| 228 | .ops = &evm_ops, | 225 | .ops = &evm_ops, |
| 229 | }; | 226 | }; |
| @@ -234,7 +231,7 @@ static struct snd_soc_dai_link da850_evm_dai = { | |||
| 234 | .cpu_dai_name= "davinci-mcasp.0", | 231 | .cpu_dai_name= "davinci-mcasp.0", |
| 235 | .codec_dai_name = "tlv320aic3x-hifi", | 232 | .codec_dai_name = "tlv320aic3x-hifi", |
| 236 | .codec_name = "tlv320aic3x-codec.1-0018", | 233 | .codec_name = "tlv320aic3x-codec.1-0018", |
| 237 | .platform_name = "davinci-pcm-audio", | 234 | .platform_name = "davinci-mcasp.0", |
| 238 | .init = evm_aic3x_init, | 235 | .init = evm_aic3x_init, |
| 239 | .ops = &evm_ops, | 236 | .ops = &evm_ops, |
| 240 | }; | 237 | }; |
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 0a74b9587a2c..821831207180 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c | |||
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
| 17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
| 18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
| 19 | #include <linux/platform_data/davinci_asp.h> | ||
| 19 | 20 | ||
| 20 | #include <sound/core.h> | 21 | #include <sound/core.h> |
| 21 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
| @@ -23,8 +24,6 @@ | |||
| 23 | #include <sound/initval.h> | 24 | #include <sound/initval.h> |
| 24 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
| 25 | 26 | ||
| 26 | #include <mach/asp.h> | ||
| 27 | |||
| 28 | #include "davinci-pcm.h" | 27 | #include "davinci-pcm.h" |
| 29 | #include "davinci-i2s.h" | 28 | #include "davinci-i2s.h" |
| 30 | 29 | ||
| @@ -732,8 +731,16 @@ static int davinci_i2s_probe(struct platform_device *pdev) | |||
| 732 | if (ret != 0) | 731 | if (ret != 0) |
| 733 | goto err_release_clk; | 732 | goto err_release_clk; |
| 734 | 733 | ||
| 734 | ret = davinci_soc_platform_register(&pdev->dev); | ||
| 735 | if (ret) { | ||
| 736 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); | ||
| 737 | goto err_unregister_dai; | ||
| 738 | } | ||
| 739 | |||
| 735 | return 0; | 740 | return 0; |
| 736 | 741 | ||
| 742 | err_unregister_dai: | ||
| 743 | snd_soc_unregister_dai(&pdev->dev); | ||
| 737 | err_release_clk: | 744 | err_release_clk: |
| 738 | clk_disable(dev->clk); | 745 | clk_disable(dev->clk); |
| 739 | clk_put(dev->clk); | 746 | clk_put(dev->clk); |
| @@ -745,6 +752,8 @@ static int davinci_i2s_remove(struct platform_device *pdev) | |||
| 745 | struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); | 752 | struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); |
| 746 | 753 | ||
| 747 | snd_soc_unregister_dai(&pdev->dev); | 754 | snd_soc_unregister_dai(&pdev->dev); |
| 755 | davinci_soc_platform_unregister(&pdev->dev); | ||
| 756 | |||
| 748 | clk_disable(dev->clk); | 757 | clk_disable(dev->clk); |
| 749 | clk_put(dev->clk); | 758 | clk_put(dev->clk); |
| 750 | dev->clk = NULL; | 759 | dev->clk = NULL; |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index ce5e5cd254dd..714e51e5be5b 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
| @@ -21,7 +21,10 @@ | |||
| 21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
| 23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
| 24 | #include <linux/clk.h> | 24 | #include <linux/pm_runtime.h> |
| 25 | #include <linux/of.h> | ||
| 26 | #include <linux/of_platform.h> | ||
| 27 | #include <linux/of_device.h> | ||
| 25 | 28 | ||
| 26 | #include <sound/core.h> | 29 | #include <sound/core.h> |
| 27 | #include <sound/pcm.h> | 30 | #include <sound/pcm.h> |
| @@ -108,6 +111,10 @@ | |||
| 108 | #define DAVINCI_MCASP_WFIFOSTS (0x1014) | 111 | #define DAVINCI_MCASP_WFIFOSTS (0x1014) |
| 109 | #define DAVINCI_MCASP_RFIFOCTL (0x1018) | 112 | #define DAVINCI_MCASP_RFIFOCTL (0x1018) |
| 110 | #define DAVINCI_MCASP_RFIFOSTS (0x101C) | 113 | #define DAVINCI_MCASP_RFIFOSTS (0x101C) |
| 114 | #define MCASP_VER3_WFIFOCTL (0x1000) | ||
| 115 | #define MCASP_VER3_WFIFOSTS (0x1004) | ||
| 116 | #define MCASP_VER3_RFIFOCTL (0x1008) | ||
| 117 | #define MCASP_VER3_RFIFOSTS (0x100C) | ||
| 111 | 118 | ||
| 112 | /* | 119 | /* |
| 113 | * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management | 120 | * DAVINCI_MCASP_PWREMUMGT_REG - Power Down and Emulation Management |
| @@ -381,18 +388,36 @@ static void davinci_mcasp_start(struct davinci_audio_dev *dev, int stream) | |||
| 381 | { | 388 | { |
| 382 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 389 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 383 | if (dev->txnumevt) { /* enable FIFO */ | 390 | if (dev->txnumevt) { /* enable FIFO */ |
| 384 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | 391 | switch (dev->version) { |
| 392 | case MCASP_VERSION_3: | ||
| 393 | mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL, | ||
| 385 | FIFO_ENABLE); | 394 | FIFO_ENABLE); |
| 386 | mcasp_set_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | 395 | mcasp_set_bits(dev->base + MCASP_VER3_WFIFOCTL, |
| 387 | FIFO_ENABLE); | 396 | FIFO_ENABLE); |
| 397 | break; | ||
| 398 | default: | ||
| 399 | mcasp_clr_bits(dev->base + | ||
| 400 | DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); | ||
| 401 | mcasp_set_bits(dev->base + | ||
| 402 | DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); | ||
| 403 | } | ||
| 388 | } | 404 | } |
| 389 | mcasp_start_tx(dev); | 405 | mcasp_start_tx(dev); |
| 390 | } else { | 406 | } else { |
| 391 | if (dev->rxnumevt) { /* enable FIFO */ | 407 | if (dev->rxnumevt) { /* enable FIFO */ |
| 392 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | 408 | switch (dev->version) { |
| 409 | case MCASP_VERSION_3: | ||
| 410 | mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL, | ||
| 393 | FIFO_ENABLE); | 411 | FIFO_ENABLE); |
| 394 | mcasp_set_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | 412 | mcasp_set_bits(dev->base + MCASP_VER3_RFIFOCTL, |
| 395 | FIFO_ENABLE); | 413 | FIFO_ENABLE); |
| 414 | break; | ||
| 415 | default: | ||
| 416 | mcasp_clr_bits(dev->base + | ||
| 417 | DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); | ||
| 418 | mcasp_set_bits(dev->base + | ||
| 419 | DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); | ||
| 420 | } | ||
| 396 | } | 421 | } |
| 397 | mcasp_start_rx(dev); | 422 | mcasp_start_rx(dev); |
| 398 | } | 423 | } |
| @@ -413,14 +438,31 @@ static void mcasp_stop_tx(struct davinci_audio_dev *dev) | |||
| 413 | static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) | 438 | static void davinci_mcasp_stop(struct davinci_audio_dev *dev, int stream) |
| 414 | { | 439 | { |
| 415 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 440 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| 416 | if (dev->txnumevt) /* disable FIFO */ | 441 | if (dev->txnumevt) { /* disable FIFO */ |
| 417 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | 442 | switch (dev->version) { |
| 443 | case MCASP_VERSION_3: | ||
| 444 | mcasp_clr_bits(dev->base + MCASP_VER3_WFIFOCTL, | ||
| 418 | FIFO_ENABLE); | 445 | FIFO_ENABLE); |
| 446 | break; | ||
| 447 | default: | ||
| 448 | mcasp_clr_bits(dev->base + | ||
| 449 | DAVINCI_MCASP_WFIFOCTL, FIFO_ENABLE); | ||
| 450 | } | ||
| 451 | } | ||
| 419 | mcasp_stop_tx(dev); | 452 | mcasp_stop_tx(dev); |
| 420 | } else { | 453 | } else { |
| 421 | if (dev->rxnumevt) /* disable FIFO */ | 454 | if (dev->rxnumevt) { /* disable FIFO */ |
| 422 | mcasp_clr_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | 455 | switch (dev->version) { |
| 456 | case MCASP_VERSION_3: | ||
| 457 | mcasp_clr_bits(dev->base + MCASP_VER3_RFIFOCTL, | ||
| 423 | FIFO_ENABLE); | 458 | FIFO_ENABLE); |
| 459 | break; | ||
| 460 | |||
| 461 | default: | ||
| 462 | mcasp_clr_bits(dev->base + | ||
| 463 | DAVINCI_MCASP_RFIFOCTL, FIFO_ENABLE); | ||
| 464 | } | ||
| 465 | } | ||
| 424 | mcasp_stop_rx(dev); | 466 | mcasp_stop_rx(dev); |
| 425 | } | 467 | } |
| 426 | } | 468 | } |
| @@ -619,20 +661,37 @@ static void davinci_hw_common_param(struct davinci_audio_dev *dev, int stream) | |||
| 619 | if (dev->txnumevt * tx_ser > 64) | 661 | if (dev->txnumevt * tx_ser > 64) |
| 620 | dev->txnumevt = 1; | 662 | dev->txnumevt = 1; |
| 621 | 663 | ||
| 622 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, tx_ser, | 664 | switch (dev->version) { |
| 665 | case MCASP_VERSION_3: | ||
| 666 | mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, tx_ser, | ||
| 623 | NUMDMA_MASK); | 667 | NUMDMA_MASK); |
| 624 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | 668 | mcasp_mod_bits(dev->base + MCASP_VER3_WFIFOCTL, |
| 625 | ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); | 669 | ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); |
| 670 | break; | ||
| 671 | default: | ||
| 672 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | ||
| 673 | tx_ser, NUMDMA_MASK); | ||
| 674 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_WFIFOCTL, | ||
| 675 | ((dev->txnumevt * tx_ser) << 8), NUMEVT_MASK); | ||
| 676 | } | ||
| 626 | } | 677 | } |
| 627 | 678 | ||
| 628 | if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { | 679 | if (dev->rxnumevt && stream == SNDRV_PCM_STREAM_CAPTURE) { |
| 629 | if (dev->rxnumevt * rx_ser > 64) | 680 | if (dev->rxnumevt * rx_ser > 64) |
| 630 | dev->rxnumevt = 1; | 681 | dev->rxnumevt = 1; |
| 631 | 682 | switch (dev->version) { | |
| 632 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, rx_ser, | 683 | case MCASP_VERSION_3: |
| 684 | mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, rx_ser, | ||
| 633 | NUMDMA_MASK); | 685 | NUMDMA_MASK); |
| 634 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | 686 | mcasp_mod_bits(dev->base + MCASP_VER3_RFIFOCTL, |
| 635 | ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); | 687 | ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); |
| 688 | break; | ||
| 689 | default: | ||
| 690 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | ||
| 691 | rx_ser, NUMDMA_MASK); | ||
| 692 | mcasp_mod_bits(dev->base + DAVINCI_MCASP_RFIFOCTL, | ||
| 693 | ((dev->rxnumevt * rx_ser) << 8), NUMEVT_MASK); | ||
| 694 | } | ||
| 636 | } | 695 | } |
| 637 | } | 696 | } |
| 638 | 697 | ||
| @@ -782,20 +841,17 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, | |||
| 782 | case SNDRV_PCM_TRIGGER_RESUME: | 841 | case SNDRV_PCM_TRIGGER_RESUME: |
| 783 | case SNDRV_PCM_TRIGGER_START: | 842 | case SNDRV_PCM_TRIGGER_START: |
| 784 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 843 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
| 785 | if (!dev->clk_active) { | 844 | ret = pm_runtime_get_sync(dev->dev); |
| 786 | clk_enable(dev->clk); | 845 | if (IS_ERR_VALUE(ret)) |
| 787 | dev->clk_active = 1; | 846 | dev_err(dev->dev, "pm_runtime_get_sync() failed\n"); |
| 788 | } | ||
| 789 | davinci_mcasp_start(dev, substream->stream); | 847 | davinci_mcasp_start(dev, substream->stream); |
| 790 | break; | 848 | break; |
| 791 | 849 | ||
| 792 | case SNDRV_PCM_TRIGGER_SUSPEND: | 850 | case SNDRV_PCM_TRIGGER_SUSPEND: |
| 793 | davinci_mcasp_stop(dev, substream->stream); | 851 | davinci_mcasp_stop(dev, substream->stream); |
| 794 | if (dev->clk_active) { | 852 | ret = pm_runtime_put_sync(dev->dev); |
| 795 | clk_disable(dev->clk); | 853 | if (IS_ERR_VALUE(ret)) |
| 796 | dev->clk_active = 0; | 854 | dev_err(dev->dev, "pm_runtime_put_sync() failed\n"); |
| 797 | } | ||
| 798 | |||
| 799 | break; | 855 | break; |
| 800 | 856 | ||
| 801 | case SNDRV_PCM_TRIGGER_STOP: | 857 | case SNDRV_PCM_TRIGGER_STOP: |
| @@ -865,6 +921,118 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { | |||
| 865 | 921 | ||
| 866 | }; | 922 | }; |
| 867 | 923 | ||
| 924 | static const struct of_device_id mcasp_dt_ids[] = { | ||
| 925 | { | ||
| 926 | .compatible = "ti,dm646x-mcasp-audio", | ||
| 927 | .data = (void *)MCASP_VERSION_1, | ||
| 928 | }, | ||
| 929 | { | ||
| 930 | .compatible = "ti,da830-mcasp-audio", | ||
| 931 | .data = (void *)MCASP_VERSION_2, | ||
| 932 | }, | ||
| 933 | { | ||
| 934 | .compatible = "ti,omap2-mcasp-audio", | ||
| 935 | .data = (void *)MCASP_VERSION_3, | ||
| 936 | }, | ||
| 937 | { /* sentinel */ } | ||
| 938 | }; | ||
| 939 | MODULE_DEVICE_TABLE(of, mcasp_dt_ids); | ||
| 940 | |||
| 941 | static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | ||
| 942 | struct platform_device *pdev) | ||
| 943 | { | ||
| 944 | struct device_node *np = pdev->dev.of_node; | ||
| 945 | struct snd_platform_data *pdata = NULL; | ||
| 946 | const struct of_device_id *match = | ||
| 947 | of_match_device(of_match_ptr(mcasp_dt_ids), &pdev->dev); | ||
| 948 | |||
| 949 | const u32 *of_serial_dir32; | ||
| 950 | u8 *of_serial_dir; | ||
| 951 | u32 val; | ||
| 952 | int i, ret = 0; | ||
| 953 | |||
| 954 | if (pdev->dev.platform_data) { | ||
| 955 | pdata = pdev->dev.platform_data; | ||
| 956 | return pdata; | ||
| 957 | } else if (match) { | ||
| 958 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
| 959 | if (!pdata) { | ||
| 960 | ret = -ENOMEM; | ||
| 961 | goto nodata; | ||
| 962 | } | ||
| 963 | } else { | ||
| 964 | /* control shouldn't reach here. something is wrong */ | ||
| 965 | ret = -EINVAL; | ||
| 966 | goto nodata; | ||
| 967 | } | ||
| 968 | |||
| 969 | if (match->data) | ||
| 970 | pdata->version = (u8)((int)match->data); | ||
| 971 | |||
| 972 | ret = of_property_read_u32(np, "op-mode", &val); | ||
| 973 | if (ret >= 0) | ||
| 974 | pdata->op_mode = val; | ||
| 975 | |||
| 976 | ret = of_property_read_u32(np, "tdm-slots", &val); | ||
| 977 | if (ret >= 0) | ||
| 978 | pdata->tdm_slots = val; | ||
| 979 | |||
| 980 | ret = of_property_read_u32(np, "num-serializer", &val); | ||
| 981 | if (ret >= 0) | ||
| 982 | pdata->num_serializer = val; | ||
| 983 | |||
| 984 | of_serial_dir32 = of_get_property(np, "serial-dir", &val); | ||
| 985 | val /= sizeof(u32); | ||
| 986 | if (val != pdata->num_serializer) { | ||
| 987 | dev_err(&pdev->dev, | ||
| 988 | "num-serializer(%d) != serial-dir size(%d)\n", | ||
| 989 | pdata->num_serializer, val); | ||
| 990 | ret = -EINVAL; | ||
| 991 | goto nodata; | ||
| 992 | } | ||
| 993 | |||
| 994 | if (of_serial_dir32) { | ||
| 995 | of_serial_dir = devm_kzalloc(&pdev->dev, | ||
| 996 | (sizeof(*of_serial_dir) * val), | ||
| 997 | GFP_KERNEL); | ||
| 998 | if (!of_serial_dir) { | ||
| 999 | ret = -ENOMEM; | ||
| 1000 | goto nodata; | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | for (i = 0; i < pdata->num_serializer; i++) | ||
| 1004 | of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]); | ||
| 1005 | |||
| 1006 | pdata->serial_dir = of_serial_dir; | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | ret = of_property_read_u32(np, "tx-num-evt", &val); | ||
| 1010 | if (ret >= 0) | ||
| 1011 | pdata->txnumevt = val; | ||
| 1012 | |||
| 1013 | ret = of_property_read_u32(np, "rx-num-evt", &val); | ||
| 1014 | if (ret >= 0) | ||
| 1015 | pdata->rxnumevt = val; | ||
| 1016 | |||
| 1017 | ret = of_property_read_u32(np, "sram-size-playback", &val); | ||
| 1018 | if (ret >= 0) | ||
| 1019 | pdata->sram_size_playback = val; | ||
| 1020 | |||
| 1021 | ret = of_property_read_u32(np, "sram-size-capture", &val); | ||
| 1022 | if (ret >= 0) | ||
| 1023 | pdata->sram_size_capture = val; | ||
| 1024 | |||
| 1025 | return pdata; | ||
| 1026 | |||
| 1027 | nodata: | ||
| 1028 | if (ret < 0) { | ||
| 1029 | dev_err(&pdev->dev, "Error populating platform data, err %d\n", | ||
| 1030 | ret); | ||
| 1031 | pdata = NULL; | ||
| 1032 | } | ||
| 1033 | return pdata; | ||
| 1034 | } | ||
| 1035 | |||
| 868 | static int davinci_mcasp_probe(struct platform_device *pdev) | 1036 | static int davinci_mcasp_probe(struct platform_device *pdev) |
| 869 | { | 1037 | { |
| 870 | struct davinci_pcm_dma_params *dma_data; | 1038 | struct davinci_pcm_dma_params *dma_data; |
| @@ -873,11 +1041,22 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
| 873 | struct davinci_audio_dev *dev; | 1041 | struct davinci_audio_dev *dev; |
| 874 | int ret; | 1042 | int ret; |
| 875 | 1043 | ||
| 1044 | if (!pdev->dev.platform_data && !pdev->dev.of_node) { | ||
| 1045 | dev_err(&pdev->dev, "No platform data supplied\n"); | ||
| 1046 | return -EINVAL; | ||
| 1047 | } | ||
| 1048 | |||
| 876 | dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev), | 1049 | dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev), |
| 877 | GFP_KERNEL); | 1050 | GFP_KERNEL); |
| 878 | if (!dev) | 1051 | if (!dev) |
| 879 | return -ENOMEM; | 1052 | return -ENOMEM; |
| 880 | 1053 | ||
| 1054 | pdata = davinci_mcasp_set_pdata_from_of(pdev); | ||
| 1055 | if (!pdata) { | ||
| 1056 | dev_err(&pdev->dev, "no platform data\n"); | ||
| 1057 | return -EINVAL; | ||
| 1058 | } | ||
| 1059 | |||
| 881 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1060 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 882 | if (!mem) { | 1061 | if (!mem) { |
| 883 | dev_err(&pdev->dev, "no mem resource?\n"); | 1062 | dev_err(&pdev->dev, "no mem resource?\n"); |
| @@ -891,13 +1070,13 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
| 891 | return -EBUSY; | 1070 | return -EBUSY; |
| 892 | } | 1071 | } |
| 893 | 1072 | ||
| 894 | pdata = pdev->dev.platform_data; | 1073 | pm_runtime_enable(&pdev->dev); |
| 895 | dev->clk = clk_get(&pdev->dev, NULL); | ||
| 896 | if (IS_ERR(dev->clk)) | ||
| 897 | return -ENODEV; | ||
| 898 | 1074 | ||
| 899 | clk_enable(dev->clk); | 1075 | ret = pm_runtime_get_sync(&pdev->dev); |
| 900 | dev->clk_active = 1; | 1076 | if (IS_ERR_VALUE(ret)) { |
| 1077 | dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); | ||
| 1078 | return ret; | ||
| 1079 | } | ||
| 901 | 1080 | ||
| 902 | dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); | 1081 | dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); |
| 903 | if (!dev->base) { | 1082 | if (!dev->base) { |
| @@ -914,6 +1093,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
| 914 | dev->version = pdata->version; | 1093 | dev->version = pdata->version; |
| 915 | dev->txnumevt = pdata->txnumevt; | 1094 | dev->txnumevt = pdata->txnumevt; |
| 916 | dev->rxnumevt = pdata->rxnumevt; | 1095 | dev->rxnumevt = pdata->rxnumevt; |
| 1096 | dev->dev = &pdev->dev; | ||
| 917 | 1097 | ||
| 918 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; | 1098 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; |
| 919 | dma_data->asp_chan_q = pdata->asp_chan_q; | 1099 | dma_data->asp_chan_q = pdata->asp_chan_q; |
| @@ -952,22 +1132,31 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
| 952 | 1132 | ||
| 953 | if (ret != 0) | 1133 | if (ret != 0) |
| 954 | goto err_release_clk; | 1134 | goto err_release_clk; |
| 1135 | |||
| 1136 | ret = davinci_soc_platform_register(&pdev->dev); | ||
| 1137 | if (ret) { | ||
| 1138 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); | ||
| 1139 | goto err_unregister_dai; | ||
| 1140 | } | ||
| 1141 | |||
| 955 | return 0; | 1142 | return 0; |
| 956 | 1143 | ||
| 1144 | err_unregister_dai: | ||
| 1145 | snd_soc_unregister_dai(&pdev->dev); | ||
| 957 | err_release_clk: | 1146 | err_release_clk: |
| 958 | clk_disable(dev->clk); | 1147 | pm_runtime_put_sync(&pdev->dev); |
| 959 | clk_put(dev->clk); | 1148 | pm_runtime_disable(&pdev->dev); |
| 960 | return ret; | 1149 | return ret; |
| 961 | } | 1150 | } |
| 962 | 1151 | ||
| 963 | static int davinci_mcasp_remove(struct platform_device *pdev) | 1152 | static int davinci_mcasp_remove(struct platform_device *pdev) |
| 964 | { | 1153 | { |
| 965 | struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev); | ||
| 966 | 1154 | ||
| 967 | snd_soc_unregister_dai(&pdev->dev); | 1155 | snd_soc_unregister_dai(&pdev->dev); |
| 968 | clk_disable(dev->clk); | 1156 | davinci_soc_platform_unregister(&pdev->dev); |
| 969 | clk_put(dev->clk); | 1157 | |
| 970 | dev->clk = NULL; | 1158 | pm_runtime_put_sync(&pdev->dev); |
| 1159 | pm_runtime_disable(&pdev->dev); | ||
| 971 | 1160 | ||
| 972 | return 0; | 1161 | return 0; |
| 973 | } | 1162 | } |
| @@ -978,6 +1167,7 @@ static struct platform_driver davinci_mcasp_driver = { | |||
| 978 | .driver = { | 1167 | .driver = { |
| 979 | .name = "davinci-mcasp", | 1168 | .name = "davinci-mcasp", |
| 980 | .owner = THIS_MODULE, | 1169 | .owner = THIS_MODULE, |
| 1170 | .of_match_table = of_match_ptr(mcasp_dt_ids), | ||
| 981 | }, | 1171 | }, |
| 982 | }; | 1172 | }; |
| 983 | 1173 | ||
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index 4681acc63606..0de9ed6ce038 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h | |||
| @@ -19,7 +19,8 @@ | |||
| 19 | #define DAVINCI_MCASP_H | 19 | #define DAVINCI_MCASP_H |
| 20 | 20 | ||
| 21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
| 22 | #include <mach/asp.h> | 22 | #include <linux/platform_data/davinci_asp.h> |
| 23 | |||
| 23 | #include "davinci-pcm.h" | 24 | #include "davinci-pcm.h" |
| 24 | 25 | ||
| 25 | #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 | 26 | #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 |
| @@ -40,9 +41,8 @@ struct davinci_audio_dev { | |||
| 40 | struct davinci_pcm_dma_params dma_params[2]; | 41 | struct davinci_pcm_dma_params dma_params[2]; |
| 41 | void __iomem *base; | 42 | void __iomem *base; |
| 42 | int sample_rate; | 43 | int sample_rate; |
| 43 | struct clk *clk; | 44 | struct device *dev; |
| 44 | unsigned int codec_fmt; | 45 | unsigned int codec_fmt; |
| 45 | u8 clk_active; | ||
| 46 | 46 | ||
| 47 | /* McASP specific data */ | 47 | /* McASP specific data */ |
| 48 | int tdm_slots; | 48 | int tdm_slots; |
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 97d77b298968..93ea3bf567e1 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
| 24 | 24 | ||
| 25 | #include <asm/dma.h> | 25 | #include <asm/dma.h> |
| 26 | #include <mach/edma.h> | ||
| 27 | #include <mach/sram.h> | 26 | #include <mach/sram.h> |
| 28 | 27 | ||
| 29 | #include "davinci-pcm.h" | 28 | #include "davinci-pcm.h" |
| @@ -864,28 +863,17 @@ static struct snd_soc_platform_driver davinci_soc_platform = { | |||
| 864 | .pcm_free = davinci_pcm_free, | 863 | .pcm_free = davinci_pcm_free, |
| 865 | }; | 864 | }; |
| 866 | 865 | ||
| 867 | static int __devinit davinci_soc_platform_probe(struct platform_device *pdev) | 866 | int davinci_soc_platform_register(struct device *dev) |
| 868 | { | 867 | { |
| 869 | return snd_soc_register_platform(&pdev->dev, &davinci_soc_platform); | 868 | return snd_soc_register_platform(dev, &davinci_soc_platform); |
| 870 | } | 869 | } |
| 870 | EXPORT_SYMBOL_GPL(davinci_soc_platform_register); | ||
| 871 | 871 | ||
| 872 | static int __devexit davinci_soc_platform_remove(struct platform_device *pdev) | 872 | void davinci_soc_platform_unregister(struct device *dev) |
| 873 | { | 873 | { |
| 874 | snd_soc_unregister_platform(&pdev->dev); | 874 | snd_soc_unregister_platform(dev); |
| 875 | return 0; | ||
| 876 | } | 875 | } |
| 877 | 876 | EXPORT_SYMBOL_GPL(davinci_soc_platform_unregister); | |
| 878 | static struct platform_driver davinci_pcm_driver = { | ||
| 879 | .driver = { | ||
| 880 | .name = "davinci-pcm-audio", | ||
| 881 | .owner = THIS_MODULE, | ||
| 882 | }, | ||
| 883 | |||
| 884 | .probe = davinci_soc_platform_probe, | ||
| 885 | .remove = __devexit_p(davinci_soc_platform_remove), | ||
| 886 | }; | ||
| 887 | |||
| 888 | module_platform_driver(davinci_pcm_driver); | ||
| 889 | 877 | ||
| 890 | MODULE_AUTHOR("Vladimir Barinov"); | 878 | MODULE_AUTHOR("Vladimir Barinov"); |
| 891 | MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); | 879 | MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); |
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index c0d6c9be4b4d..fc4d01cdd8c9 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h | |||
| @@ -12,9 +12,8 @@ | |||
| 12 | #ifndef _DAVINCI_PCM_H | 12 | #ifndef _DAVINCI_PCM_H |
| 13 | #define _DAVINCI_PCM_H | 13 | #define _DAVINCI_PCM_H |
| 14 | 14 | ||
| 15 | #include <linux/platform_data/davinci_asp.h> | ||
| 15 | #include <mach/edma.h> | 16 | #include <mach/edma.h> |
| 16 | #include <mach/asp.h> | ||
| 17 | |||
| 18 | 17 | ||
| 19 | struct davinci_pcm_dma_params { | 18 | struct davinci_pcm_dma_params { |
| 20 | int channel; /* sync dma channel ID */ | 19 | int channel; /* sync dma channel ID */ |
| @@ -28,4 +27,7 @@ struct davinci_pcm_dma_params { | |||
| 28 | unsigned int fifo_level; | 27 | unsigned int fifo_level; |
| 29 | }; | 28 | }; |
| 30 | 29 | ||
| 30 | int davinci_soc_platform_register(struct device *dev); | ||
| 31 | void davinci_soc_platform_unregister(struct device *dev); | ||
| 32 | |||
| 31 | #endif | 33 | #endif |
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c index f71175b29e38..5be65aae7e0e 100644 --- a/sound/soc/davinci/davinci-sffsdr.c +++ b/sound/soc/davinci/davinci-sffsdr.c | |||
| @@ -86,7 +86,7 @@ static struct snd_soc_dai_link sffsdr_dai = { | |||
| 86 | .cpu_dai_name = "davinci-mcbsp", | 86 | .cpu_dai_name = "davinci-mcbsp", |
| 87 | .codec_dai_name = "pcm3008-hifi", | 87 | .codec_dai_name = "pcm3008-hifi", |
| 88 | .codec_name = "pcm3008-codec", | 88 | .codec_name = "pcm3008-codec", |
| 89 | .platform_name = "davinci-pcm-audio", | 89 | .platform_name = "davinci-mcbsp", |
| 90 | .ops = &sffsdr_ops, | 90 | .ops = &sffsdr_ops, |
| 91 | }; | 91 | }; |
| 92 | 92 | ||
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index da030ff883d5..07bde2e6f84e 100644 --- a/sound/soc/davinci/davinci-vcif.c +++ b/sound/soc/davinci/davinci-vcif.c | |||
| @@ -240,12 +240,20 @@ static int davinci_vcif_probe(struct platform_device *pdev) | |||
| 240 | return ret; | 240 | return ret; |
| 241 | } | 241 | } |
| 242 | 242 | ||
| 243 | ret = davinci_soc_platform_register(&pdev->dev); | ||
| 244 | if (ret) { | ||
| 245 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); | ||
| 246 | snd_soc_unregister_dai(&pdev->dev); | ||
| 247 | return ret; | ||
| 248 | } | ||
| 249 | |||
| 243 | return 0; | 250 | return 0; |
| 244 | } | 251 | } |
| 245 | 252 | ||
| 246 | static int davinci_vcif_remove(struct platform_device *pdev) | 253 | static int davinci_vcif_remove(struct platform_device *pdev) |
| 247 | { | 254 | { |
| 248 | snd_soc_unregister_dai(&pdev->dev); | 255 | snd_soc_unregister_dai(&pdev->dev); |
| 256 | davinci_soc_platform_unregister(&pdev->dev); | ||
| 249 | 257 | ||
| 250 | return 0; | 258 | return 0; |
| 251 | } | 259 | } |
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index d70133086ac3..4563b28bd625 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
| @@ -6,7 +6,7 @@ config SND_SOC_FSL_UTILS | |||
| 6 | 6 | ||
| 7 | menuconfig SND_POWERPC_SOC | 7 | menuconfig SND_POWERPC_SOC |
| 8 | tristate "SoC Audio for Freescale PowerPC CPUs" | 8 | tristate "SoC Audio for Freescale PowerPC CPUs" |
| 9 | depends on FSL_SOC | 9 | depends on FSL_SOC || PPC_MPC52xx |
| 10 | help | 10 | help |
| 11 | Say Y or M if you want to add support for codecs attached to | 11 | Say Y or M if you want to add support for codecs attached to |
| 12 | the PowerPC CPUs. | 12 | the PowerPC CPUs. |
diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index efb9ede01208..267d5b4b63ce 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c | |||
| @@ -93,9 +93,7 @@ static struct snd_soc_card eukrea_tlv320 = { | |||
| 93 | .num_links = 1, | 93 | .num_links = 1, |
| 94 | }; | 94 | }; |
| 95 | 95 | ||
| 96 | static struct platform_device *eukrea_tlv320_snd_device; | 96 | static int __devinit eukrea_tlv320_probe(struct platform_device *pdev) |
| 97 | |||
| 98 | static int __init eukrea_tlv320_init(void) | ||
| 99 | { | 97 | { |
| 100 | int ret; | 98 | int ret; |
| 101 | int int_port = 0, ext_port; | 99 | int int_port = 0, ext_port; |
| @@ -136,29 +134,32 @@ static int __init eukrea_tlv320_init(void) | |||
| 136 | return 0; | 134 | return 0; |
| 137 | } | 135 | } |
| 138 | 136 | ||
| 139 | eukrea_tlv320_snd_device = platform_device_alloc("soc-audio", -1); | 137 | eukrea_tlv320.dev = &pdev->dev; |
| 140 | if (!eukrea_tlv320_snd_device) | 138 | ret = snd_soc_register_card(&eukrea_tlv320); |
| 141 | return -ENOMEM; | 139 | if (ret) |
| 142 | 140 | dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); | |
| 143 | platform_set_drvdata(eukrea_tlv320_snd_device, &eukrea_tlv320); | ||
| 144 | ret = platform_device_add(eukrea_tlv320_snd_device); | ||
| 145 | |||
| 146 | if (ret) { | ||
| 147 | printk(KERN_ERR "ASoC: Platform device allocation failed\n"); | ||
| 148 | platform_device_put(eukrea_tlv320_snd_device); | ||
| 149 | } | ||
| 150 | 141 | ||
| 151 | return ret; | 142 | return ret; |
| 152 | } | 143 | } |
| 153 | 144 | ||
| 154 | static void __exit eukrea_tlv320_exit(void) | 145 | static int __devexit eukrea_tlv320_remove(struct platform_device *pdev) |
| 155 | { | 146 | { |
| 156 | platform_device_unregister(eukrea_tlv320_snd_device); | 147 | snd_soc_unregister_card(&eukrea_tlv320); |
| 148 | |||
| 149 | return 0; | ||
| 157 | } | 150 | } |
| 158 | 151 | ||
| 159 | module_init(eukrea_tlv320_init); | 152 | static struct platform_driver eukrea_tlv320_driver = { |
| 160 | module_exit(eukrea_tlv320_exit); | 153 | .driver = { |
| 154 | .name = "eukrea_tlv320", | ||
| 155 | .owner = THIS_MODULE, | ||
| 156 | }, | ||
| 157 | .probe = eukrea_tlv320_probe, | ||
| 158 | .remove = __devexit_p(eukrea_tlv320_remove),}; | ||
| 159 | |||
| 160 | module_platform_driver(eukrea_tlv320_driver); | ||
| 161 | 161 | ||
| 162 | MODULE_AUTHOR("Eric Bénard <eric@eukrea.com>"); | 162 | MODULE_AUTHOR("Eric Bénard <eric@eukrea.com>"); |
| 163 | MODULE_DESCRIPTION("CPUIMX ALSA SoC driver"); | 163 | MODULE_DESCRIPTION("CPUIMX ALSA SoC driver"); |
| 164 | MODULE_LICENSE("GPL"); | 164 | MODULE_LICENSE("GPL"); |
| 165 | MODULE_ALIAS("platform:eukrea_tlv320"); | ||
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index 96bb92dd174c..6feb26500580 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c | |||
| @@ -823,12 +823,6 @@ static int fsl_dma_close(struct snd_pcm_substream *substream) | |||
| 823 | if (dma_private->irq) | 823 | if (dma_private->irq) |
| 824 | free_irq(dma_private->irq, dma_private); | 824 | free_irq(dma_private->irq, dma_private); |
| 825 | 825 | ||
| 826 | if (dma_private->ld_buf_phys) { | ||
| 827 | dma_unmap_single(dev, dma_private->ld_buf_phys, | ||
| 828 | sizeof(dma_private->link), | ||
| 829 | DMA_TO_DEVICE); | ||
| 830 | } | ||
| 831 | |||
| 832 | /* Deallocate the fsl_dma_private structure */ | 826 | /* Deallocate the fsl_dma_private structure */ |
| 833 | dma_free_coherent(dev, sizeof(struct fsl_dma_private), | 827 | dma_free_coherent(dev, sizeof(struct fsl_dma_private), |
| 834 | dma_private, dma_private->ld_buf_phys); | 828 | dma_private, dma_private->ld_buf_phys); |
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c index e7c800ebbd75..524ce6210cee 100644 --- a/sound/soc/fsl/imx-audmux.c +++ b/sound/soc/fsl/imx-audmux.c | |||
| @@ -74,9 +74,6 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf, | |||
| 74 | if (!buf) | 74 | if (!buf) |
| 75 | return -ENOMEM; | 75 | return -ENOMEM; |
| 76 | 76 | ||
| 77 | if (!audmux_base) | ||
| 78 | return -ENOSYS; | ||
| 79 | |||
| 80 | if (audmux_clk) | 77 | if (audmux_clk) |
| 81 | clk_prepare_enable(audmux_clk); | 78 | clk_prepare_enable(audmux_clk); |
| 82 | 79 | ||
diff --git a/sound/soc/fsl/imx-pcm-dma.c b/sound/soc/fsl/imx-pcm-dma.c index 89a7755b6f56..d85929b79c35 100644 --- a/sound/soc/fsl/imx-pcm-dma.c +++ b/sound/soc/fsl/imx-pcm-dma.c | |||
| @@ -109,6 +109,9 @@ static int snd_imx_open(struct snd_pcm_substream *substream) | |||
| 109 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 109 | dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
| 110 | 110 | ||
| 111 | dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL); | 111 | dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL); |
| 112 | if (!dma_data) | ||
| 113 | return -ENOMEM; | ||
| 114 | |||
| 112 | dma_data->peripheral_type = dma_params->shared_peripheral ? | 115 | dma_data->peripheral_type = dma_params->shared_peripheral ? |
| 113 | IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI; | 116 | IMX_DMATYPE_SSI_SP : IMX_DMATYPE_SSI; |
| 114 | dma_data->priority = DMA_PRIO_HIGH; | 117 | dma_data->priority = DMA_PRIO_HIGH; |
| @@ -117,7 +120,7 @@ static int snd_imx_open(struct snd_pcm_substream *substream) | |||
| 117 | ret = snd_dmaengine_pcm_open(substream, filter, dma_data); | 120 | ret = snd_dmaengine_pcm_open(substream, filter, dma_data); |
| 118 | if (ret) { | 121 | if (ret) { |
| 119 | kfree(dma_data); | 122 | kfree(dma_data); |
| 120 | return 0; | 123 | return ret; |
| 121 | } | 124 | } |
| 122 | 125 | ||
| 123 | snd_dmaengine_pcm_set_data(substream, dma_data); | 126 | snd_dmaengine_pcm_set_data(substream, dma_data); |
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index e6a17baca1ee..006f7d465ed2 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
| @@ -380,14 +380,13 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai) | |||
| 380 | static struct snd_soc_dai_driver imx_ssi_dai = { | 380 | static struct snd_soc_dai_driver imx_ssi_dai = { |
| 381 | .probe = imx_ssi_dai_probe, | 381 | .probe = imx_ssi_dai_probe, |
| 382 | .playback = { | 382 | .playback = { |
| 383 | /* The SSI does not support monaural audio. */ | 383 | .channels_min = 1, |
| 384 | .channels_min = 2, | ||
| 385 | .channels_max = 2, | 384 | .channels_max = 2, |
| 386 | .rates = SNDRV_PCM_RATE_8000_96000, | 385 | .rates = SNDRV_PCM_RATE_8000_96000, |
| 387 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 386 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
| 388 | }, | 387 | }, |
| 389 | .capture = { | 388 | .capture = { |
| 390 | .channels_min = 2, | 389 | .channels_min = 1, |
| 391 | .channels_max = 2, | 390 | .channels_max = 2, |
| 392 | .rates = SNDRV_PCM_RATE_8000_96000, | 391 | .rates = SNDRV_PCM_RATE_8000_96000, |
| 393 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 392 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
| @@ -524,7 +523,7 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
| 524 | int ret = 0; | 523 | int ret = 0; |
| 525 | struct snd_soc_dai_driver *dai; | 524 | struct snd_soc_dai_driver *dai; |
| 526 | 525 | ||
| 527 | ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); | 526 | ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL); |
| 528 | if (!ssi) | 527 | if (!ssi) |
| 529 | return -ENOMEM; | 528 | return -ENOMEM; |
| 530 | dev_set_drvdata(&pdev->dev, ssi); | 529 | dev_set_drvdata(&pdev->dev, ssi); |
| @@ -537,7 +536,7 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
| 537 | 536 | ||
| 538 | ssi->irq = platform_get_irq(pdev, 0); | 537 | ssi->irq = platform_get_irq(pdev, 0); |
| 539 | 538 | ||
| 540 | ssi->clk = clk_get(&pdev->dev, NULL); | 539 | ssi->clk = devm_clk_get(&pdev->dev, NULL); |
| 541 | if (IS_ERR(ssi->clk)) { | 540 | if (IS_ERR(ssi->clk)) { |
| 542 | ret = PTR_ERR(ssi->clk); | 541 | ret = PTR_ERR(ssi->clk); |
| 543 | dev_err(&pdev->dev, "Cannot get the clock: %d\n", | 542 | dev_err(&pdev->dev, "Cannot get the clock: %d\n", |
| @@ -552,23 +551,18 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
| 552 | goto failed_get_resource; | 551 | goto failed_get_resource; |
| 553 | } | 552 | } |
| 554 | 553 | ||
| 555 | if (!request_mem_region(res->start, resource_size(res), DRV_NAME)) { | 554 | ssi->base = devm_request_and_ioremap(&pdev->dev, res); |
| 556 | dev_err(&pdev->dev, "request_mem_region failed\n"); | ||
| 557 | ret = -EBUSY; | ||
| 558 | goto failed_get_resource; | ||
| 559 | } | ||
| 560 | |||
| 561 | ssi->base = ioremap(res->start, resource_size(res)); | ||
| 562 | if (!ssi->base) { | 555 | if (!ssi->base) { |
| 563 | dev_err(&pdev->dev, "ioremap failed\n"); | 556 | dev_err(&pdev->dev, "ioremap failed\n"); |
| 564 | ret = -ENODEV; | 557 | ret = -ENODEV; |
| 565 | goto failed_ioremap; | 558 | goto failed_register; |
| 566 | } | 559 | } |
| 567 | 560 | ||
| 568 | if (ssi->flags & IMX_SSI_USE_AC97) { | 561 | if (ssi->flags & IMX_SSI_USE_AC97) { |
| 569 | if (ac97_ssi) { | 562 | if (ac97_ssi) { |
| 563 | dev_err(&pdev->dev, "AC'97 SSI already registered\n"); | ||
| 570 | ret = -EBUSY; | 564 | ret = -EBUSY; |
| 571 | goto failed_ac97; | 565 | goto failed_register; |
| 572 | } | 566 | } |
| 573 | ac97_ssi = ssi; | 567 | ac97_ssi = ssi; |
| 574 | setup_channel_to_ac97(ssi); | 568 | setup_channel_to_ac97(ssi); |
| @@ -637,15 +631,10 @@ failed_pdev_fiq_add: | |||
| 637 | failed_pdev_fiq_alloc: | 631 | failed_pdev_fiq_alloc: |
| 638 | snd_soc_unregister_dai(&pdev->dev); | 632 | snd_soc_unregister_dai(&pdev->dev); |
| 639 | failed_register: | 633 | failed_register: |
| 640 | failed_ac97: | ||
| 641 | iounmap(ssi->base); | ||
| 642 | failed_ioremap: | ||
| 643 | release_mem_region(res->start, resource_size(res)); | 634 | release_mem_region(res->start, resource_size(res)); |
| 644 | failed_get_resource: | 635 | failed_get_resource: |
| 645 | clk_disable_unprepare(ssi->clk); | 636 | clk_disable_unprepare(ssi->clk); |
| 646 | clk_put(ssi->clk); | ||
| 647 | failed_clk: | 637 | failed_clk: |
| 648 | kfree(ssi); | ||
| 649 | 638 | ||
| 650 | return ret; | 639 | return ret; |
| 651 | } | 640 | } |
| @@ -663,11 +652,8 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev) | |||
| 663 | if (ssi->flags & IMX_SSI_USE_AC97) | 652 | if (ssi->flags & IMX_SSI_USE_AC97) |
| 664 | ac97_ssi = NULL; | 653 | ac97_ssi = NULL; |
| 665 | 654 | ||
| 666 | iounmap(ssi->base); | ||
| 667 | release_mem_region(res->start, resource_size(res)); | 655 | release_mem_region(res->start, resource_size(res)); |
| 668 | clk_disable_unprepare(ssi->clk); | 656 | clk_disable_unprepare(ssi->clk); |
| 669 | clk_put(ssi->clk); | ||
| 670 | kfree(ssi); | ||
| 671 | 657 | ||
| 672 | return 0; | 658 | return 0; |
| 673 | } | 659 | } |
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 9a3f7c5ab687..9997c039bb24 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c | |||
| @@ -370,7 +370,7 @@ static struct snd_soc_platform_driver mpc5200_audio_dma_platform = { | |||
| 370 | .pcm_free = &psc_dma_free, | 370 | .pcm_free = &psc_dma_free, |
| 371 | }; | 371 | }; |
| 372 | 372 | ||
| 373 | static int mpc5200_hpcd_probe(struct platform_device *op) | 373 | int mpc5200_audio_dma_create(struct platform_device *op) |
| 374 | { | 374 | { |
| 375 | phys_addr_t fifo; | 375 | phys_addr_t fifo; |
| 376 | struct psc_dma *psc_dma; | 376 | struct psc_dma *psc_dma; |
| @@ -487,8 +487,9 @@ out_unmap: | |||
| 487 | iounmap(regs); | 487 | iounmap(regs); |
| 488 | return ret; | 488 | return ret; |
| 489 | } | 489 | } |
| 490 | EXPORT_SYMBOL_GPL(mpc5200_audio_dma_create); | ||
| 490 | 491 | ||
| 491 | static int mpc5200_hpcd_remove(struct platform_device *op) | 492 | int mpc5200_audio_dma_destroy(struct platform_device *op) |
| 492 | { | 493 | { |
| 493 | struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); | 494 | struct psc_dma *psc_dma = dev_get_drvdata(&op->dev); |
| 494 | 495 | ||
| @@ -510,24 +511,7 @@ static int mpc5200_hpcd_remove(struct platform_device *op) | |||
| 510 | 511 | ||
| 511 | return 0; | 512 | return 0; |
| 512 | } | 513 | } |
| 513 | 514 | EXPORT_SYMBOL_GPL(mpc5200_audio_dma_destroy); | |
| 514 | static struct of_device_id mpc5200_hpcd_match[] = { | ||
| 515 | { .compatible = "fsl,mpc5200-pcm", }, | ||
| 516 | {} | ||
| 517 | }; | ||
| 518 | MODULE_DEVICE_TABLE(of, mpc5200_hpcd_match); | ||
| 519 | |||
| 520 | static struct platform_driver mpc5200_hpcd_of_driver = { | ||
| 521 | .probe = mpc5200_hpcd_probe, | ||
| 522 | .remove = mpc5200_hpcd_remove, | ||
| 523 | .driver = { | ||
| 524 | .owner = THIS_MODULE, | ||
| 525 | .name = "mpc5200-pcm-audio", | ||
| 526 | .of_match_table = mpc5200_hpcd_match, | ||
| 527 | } | ||
| 528 | }; | ||
| 529 | |||
| 530 | module_platform_driver(mpc5200_hpcd_of_driver); | ||
| 531 | 515 | ||
| 532 | MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); | 516 | MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>"); |
| 533 | MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver"); | 517 | MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver"); |
diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h index a3c0cd5382fb..dff253fde29a 100644 --- a/sound/soc/fsl/mpc5200_dma.h +++ b/sound/soc/fsl/mpc5200_dma.h | |||
| @@ -81,4 +81,7 @@ to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma) | |||
| 81 | return &psc_dma->playback; | 81 | return &psc_dma->playback; |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | int mpc5200_audio_dma_create(struct platform_device *op); | ||
| 85 | int mpc5200_audio_dma_destroy(struct platform_device *op); | ||
| 86 | |||
| 84 | #endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */ | 87 | #endif /* __SOUND_SOC_FSL_MPC5200_DMA_H__ */ |
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index ffa00a2eb770..a313c0ae36db 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c | |||
| @@ -237,15 +237,18 @@ static const struct snd_soc_dai_ops psc_ac97_digital_ops = { | |||
| 237 | 237 | ||
| 238 | static struct snd_soc_dai_driver psc_ac97_dai[] = { | 238 | static struct snd_soc_dai_driver psc_ac97_dai[] = { |
| 239 | { | 239 | { |
| 240 | .name = "mpc5200-psc-ac97.0", | ||
| 240 | .ac97_control = 1, | 241 | .ac97_control = 1, |
| 241 | .probe = psc_ac97_probe, | 242 | .probe = psc_ac97_probe, |
| 242 | .playback = { | 243 | .playback = { |
| 244 | .stream_name = "AC97 Playback", | ||
| 243 | .channels_min = 1, | 245 | .channels_min = 1, |
| 244 | .channels_max = 6, | 246 | .channels_max = 6, |
| 245 | .rates = SNDRV_PCM_RATE_8000_48000, | 247 | .rates = SNDRV_PCM_RATE_8000_48000, |
| 246 | .formats = SNDRV_PCM_FMTBIT_S32_BE, | 248 | .formats = SNDRV_PCM_FMTBIT_S32_BE, |
| 247 | }, | 249 | }, |
| 248 | .capture = { | 250 | .capture = { |
| 251 | .stream_name = "AC97 Capture", | ||
| 249 | .channels_min = 1, | 252 | .channels_min = 1, |
| 250 | .channels_max = 2, | 253 | .channels_max = 2, |
| 251 | .rates = SNDRV_PCM_RATE_8000_48000, | 254 | .rates = SNDRV_PCM_RATE_8000_48000, |
| @@ -254,8 +257,10 @@ static struct snd_soc_dai_driver psc_ac97_dai[] = { | |||
| 254 | .ops = &psc_ac97_analog_ops, | 257 | .ops = &psc_ac97_analog_ops, |
| 255 | }, | 258 | }, |
| 256 | { | 259 | { |
| 260 | .name = "mpc5200-psc-ac97.1", | ||
| 257 | .ac97_control = 1, | 261 | .ac97_control = 1, |
| 258 | .playback = { | 262 | .playback = { |
| 263 | .stream_name = "AC97 SPDIF", | ||
| 259 | .channels_min = 1, | 264 | .channels_min = 1, |
| 260 | .channels_max = 2, | 265 | .channels_max = 2, |
| 261 | .rates = SNDRV_PCM_RATE_32000 | \ | 266 | .rates = SNDRV_PCM_RATE_32000 | \ |
| @@ -278,6 +283,10 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op) | |||
| 278 | struct snd_ac97 ac97; | 283 | struct snd_ac97 ac97; |
| 279 | struct mpc52xx_psc __iomem *regs; | 284 | struct mpc52xx_psc __iomem *regs; |
| 280 | 285 | ||
| 286 | rc = mpc5200_audio_dma_create(op); | ||
| 287 | if (rc != 0) | ||
| 288 | return rc; | ||
| 289 | |||
| 281 | rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); | 290 | rc = snd_soc_register_dais(&op->dev, psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); |
| 282 | if (rc != 0) { | 291 | if (rc != 0) { |
| 283 | dev_err(&op->dev, "Failed to register DAI\n"); | 292 | dev_err(&op->dev, "Failed to register DAI\n"); |
| @@ -303,6 +312,7 @@ static int __devinit psc_ac97_of_probe(struct platform_device *op) | |||
| 303 | 312 | ||
| 304 | static int __devexit psc_ac97_of_remove(struct platform_device *op) | 313 | static int __devexit psc_ac97_of_remove(struct platform_device *op) |
| 305 | { | 314 | { |
| 315 | mpc5200_audio_dma_destroy(op); | ||
| 306 | snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai)); | 316 | snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_ac97_dai)); |
| 307 | return 0; | 317 | return 0; |
| 308 | } | 318 | } |
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c index 7b530327553a..ba1f0a66358f 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c | |||
| @@ -130,13 +130,16 @@ static const struct snd_soc_dai_ops psc_i2s_dai_ops = { | |||
| 130 | }; | 130 | }; |
| 131 | 131 | ||
| 132 | static struct snd_soc_dai_driver psc_i2s_dai[] = {{ | 132 | static struct snd_soc_dai_driver psc_i2s_dai[] = {{ |
| 133 | .name = "mpc5200-psc-i2s.0", | ||
| 133 | .playback = { | 134 | .playback = { |
| 135 | .stream_name = "I2S Playback", | ||
| 134 | .channels_min = 2, | 136 | .channels_min = 2, |
| 135 | .channels_max = 2, | 137 | .channels_max = 2, |
| 136 | .rates = PSC_I2S_RATES, | 138 | .rates = PSC_I2S_RATES, |
| 137 | .formats = PSC_I2S_FORMATS, | 139 | .formats = PSC_I2S_FORMATS, |
| 138 | }, | 140 | }, |
| 139 | .capture = { | 141 | .capture = { |
| 142 | .stream_name = "I2S Capture", | ||
| 140 | .channels_min = 2, | 143 | .channels_min = 2, |
| 141 | .channels_max = 2, | 144 | .channels_max = 2, |
| 142 | .rates = PSC_I2S_RATES, | 145 | .rates = PSC_I2S_RATES, |
| @@ -156,6 +159,10 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op) | |||
| 156 | struct psc_dma *psc_dma; | 159 | struct psc_dma *psc_dma; |
| 157 | struct mpc52xx_psc __iomem *regs; | 160 | struct mpc52xx_psc __iomem *regs; |
| 158 | 161 | ||
| 162 | rc = mpc5200_audio_dma_create(op); | ||
| 163 | if (rc != 0) | ||
| 164 | return rc; | ||
| 165 | |||
| 159 | rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); | 166 | rc = snd_soc_register_dais(&op->dev, psc_i2s_dai, ARRAY_SIZE(psc_i2s_dai)); |
| 160 | if (rc != 0) { | 167 | if (rc != 0) { |
| 161 | pr_err("Failed to register DAI\n"); | 168 | pr_err("Failed to register DAI\n"); |
| @@ -200,6 +207,7 @@ static int __devinit psc_i2s_of_probe(struct platform_device *op) | |||
| 200 | 207 | ||
| 201 | static int __devexit psc_i2s_of_remove(struct platform_device *op) | 208 | static int __devexit psc_i2s_of_remove(struct platform_device *op) |
| 202 | { | 209 | { |
| 210 | mpc5200_audio_dma_destroy(op); | ||
| 203 | snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai)); | 211 | snd_soc_unregister_dais(&op->dev, ARRAY_SIZE(psc_i2s_dai)); |
| 204 | return 0; | 212 | return 0; |
| 205 | } | 213 | } |
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 60bcba1bc30e..9ff9318c52b9 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c | |||
| @@ -192,7 +192,6 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) | |||
| 192 | container_of(dev, struct platform_device, dev); | 192 | container_of(dev, struct platform_device, dev); |
| 193 | struct device_node *np = ssi_pdev->dev.of_node; | 193 | struct device_node *np = ssi_pdev->dev.of_node; |
| 194 | struct device_node *codec_np = NULL; | 194 | struct device_node *codec_np = NULL; |
| 195 | struct platform_device *sound_device = NULL; | ||
| 196 | struct mpc8610_hpcd_data *machine_data; | 195 | struct mpc8610_hpcd_data *machine_data; |
| 197 | int ret = -ENODEV; | 196 | int ret = -ENODEV; |
| 198 | const char *sprop; | 197 | const char *sprop; |
| @@ -341,34 +340,22 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) | |||
| 341 | machine_data->card.probe = mpc8610_hpcd_machine_probe; | 340 | machine_data->card.probe = mpc8610_hpcd_machine_probe; |
| 342 | machine_data->card.remove = mpc8610_hpcd_machine_remove; | 341 | machine_data->card.remove = mpc8610_hpcd_machine_remove; |
| 343 | machine_data->card.name = pdev->name; /* The platform driver name */ | 342 | machine_data->card.name = pdev->name; /* The platform driver name */ |
| 343 | machine_data->card.owner = THIS_MODULE; | ||
| 344 | machine_data->card.dev = &pdev->dev; | ||
| 344 | machine_data->card.num_links = 2; | 345 | machine_data->card.num_links = 2; |
| 345 | machine_data->card.dai_link = machine_data->dai; | 346 | machine_data->card.dai_link = machine_data->dai; |
| 346 | 347 | ||
| 347 | /* Allocate a new audio platform device structure */ | ||
| 348 | sound_device = platform_device_alloc("soc-audio", -1); | ||
| 349 | if (!sound_device) { | ||
| 350 | dev_err(&pdev->dev, "platform device alloc failed\n"); | ||
| 351 | ret = -ENOMEM; | ||
| 352 | goto error; | ||
| 353 | } | ||
| 354 | |||
| 355 | /* Associate the card data with the sound device */ | ||
| 356 | platform_set_drvdata(sound_device, &machine_data->card); | ||
| 357 | |||
| 358 | /* Register with ASoC */ | 348 | /* Register with ASoC */ |
| 359 | ret = platform_device_add(sound_device); | 349 | ret = snd_soc_register_card(&machine_data->card); |
| 360 | if (ret) { | 350 | if (ret) { |
| 361 | dev_err(&pdev->dev, "platform device add failed\n"); | 351 | dev_err(&pdev->dev, "could not register card\n"); |
| 362 | goto error_sound; | 352 | goto error; |
| 363 | } | 353 | } |
| 364 | dev_set_drvdata(&pdev->dev, sound_device); | ||
| 365 | 354 | ||
| 366 | of_node_put(codec_np); | 355 | of_node_put(codec_np); |
| 367 | 356 | ||
| 368 | return 0; | 357 | return 0; |
| 369 | 358 | ||
| 370 | error_sound: | ||
| 371 | platform_device_put(sound_device); | ||
| 372 | error: | 359 | error: |
| 373 | kfree(machine_data); | 360 | kfree(machine_data); |
| 374 | error_alloc: | 361 | error_alloc: |
| @@ -383,17 +370,12 @@ error_alloc: | |||
| 383 | */ | 370 | */ |
| 384 | static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev) | 371 | static int __devexit mpc8610_hpcd_remove(struct platform_device *pdev) |
| 385 | { | 372 | { |
| 386 | struct platform_device *sound_device = dev_get_drvdata(&pdev->dev); | 373 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 387 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
| 388 | struct mpc8610_hpcd_data *machine_data = | 374 | struct mpc8610_hpcd_data *machine_data = |
| 389 | container_of(card, struct mpc8610_hpcd_data, card); | 375 | container_of(card, struct mpc8610_hpcd_data, card); |
| 390 | 376 | ||
| 391 | platform_device_unregister(sound_device); | 377 | snd_soc_unregister_card(card); |
| 392 | |||
| 393 | kfree(machine_data); | 378 | kfree(machine_data); |
| 394 | sound_device->dev.platform_data = NULL; | ||
| 395 | |||
| 396 | dev_set_drvdata(&pdev->dev, NULL); | ||
| 397 | 379 | ||
| 398 | return 0; | 380 | return 0; |
| 399 | } | 381 | } |
diff --git a/sound/soc/fsl/mx27vis-aic32x4.c b/sound/soc/fsl/mx27vis-aic32x4.c index f6d04ad4bb39..2b76877b1789 100644 --- a/sound/soc/fsl/mx27vis-aic32x4.c +++ b/sound/soc/fsl/mx27vis-aic32x4.c | |||
| @@ -26,13 +26,13 @@ | |||
| 26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
| 27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
| 28 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
| 29 | #include <linux/platform_data/asoc-mx27vis.h> | ||
| 29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
| 30 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
| 31 | #include <sound/soc.h> | 32 | #include <sound/soc.h> |
| 32 | #include <sound/soc-dapm.h> | 33 | #include <sound/soc-dapm.h> |
| 33 | #include <sound/tlv.h> | 34 | #include <sound/tlv.h> |
| 34 | #include <asm/mach-types.h> | 35 | #include <asm/mach-types.h> |
| 35 | #include <mach/iomux-mx27.h> | ||
| 36 | 36 | ||
| 37 | #include "../codecs/tlv320aic32x4.h" | 37 | #include "../codecs/tlv320aic32x4.h" |
| 38 | #include "imx-ssi.h" | 38 | #include "imx-ssi.h" |
| @@ -41,20 +41,12 @@ | |||
| 41 | #define MX27VIS_AMP_GAIN 0 | 41 | #define MX27VIS_AMP_GAIN 0 |
| 42 | #define MX27VIS_AMP_MUTE 1 | 42 | #define MX27VIS_AMP_MUTE 1 |
| 43 | 43 | ||
| 44 | #define MX27VIS_PIN_G0 (GPIO_PORTF + 9) | ||
| 45 | #define MX27VIS_PIN_G1 (GPIO_PORTF + 8) | ||
| 46 | #define MX27VIS_PIN_SDL (GPIO_PORTE + 5) | ||
| 47 | #define MX27VIS_PIN_SDR (GPIO_PORTF + 7) | ||
| 48 | |||
| 49 | static int mx27vis_amp_gain; | 44 | static int mx27vis_amp_gain; |
| 50 | static int mx27vis_amp_mute; | 45 | static int mx27vis_amp_mute; |
| 51 | 46 | static int mx27vis_amp_gain0_gpio; | |
| 52 | static const int mx27vis_amp_pins[] = { | 47 | static int mx27vis_amp_gain1_gpio; |
| 53 | MX27VIS_PIN_G0 | GPIO_GPIO | GPIO_OUT, | 48 | static int mx27vis_amp_mutel_gpio; |
| 54 | MX27VIS_PIN_G1 | GPIO_GPIO | GPIO_OUT, | 49 | static int mx27vis_amp_muter_gpio; |
| 55 | MX27VIS_PIN_SDL | GPIO_GPIO | GPIO_OUT, | ||
| 56 | MX27VIS_PIN_SDR | GPIO_GPIO | GPIO_OUT, | ||
| 57 | }; | ||
| 58 | 50 | ||
| 59 | static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, | 51 | static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream, |
| 60 | struct snd_pcm_hw_params *params) | 52 | struct snd_pcm_hw_params *params) |
| @@ -109,13 +101,13 @@ static int mx27vis_amp_set(struct snd_kcontrol *kcontrol, | |||
| 109 | 101 | ||
| 110 | switch (reg) { | 102 | switch (reg) { |
| 111 | case MX27VIS_AMP_GAIN: | 103 | case MX27VIS_AMP_GAIN: |
| 112 | gpio_set_value(MX27VIS_PIN_G0, value & 1); | 104 | gpio_set_value(mx27vis_amp_gain0_gpio, value & 1); |
| 113 | gpio_set_value(MX27VIS_PIN_G1, value >> 1); | 105 | gpio_set_value(mx27vis_amp_gain1_gpio, value >> 1); |
| 114 | mx27vis_amp_gain = value; | 106 | mx27vis_amp_gain = value; |
| 115 | break; | 107 | break; |
| 116 | case MX27VIS_AMP_MUTE: | 108 | case MX27VIS_AMP_MUTE: |
| 117 | gpio_set_value(MX27VIS_PIN_SDL, value & 1); | 109 | gpio_set_value(mx27vis_amp_mutel_gpio, value & 1); |
| 118 | gpio_set_value(MX27VIS_PIN_SDR, value >> 1); | 110 | gpio_set_value(mx27vis_amp_muter_gpio, value >> 1); |
| 119 | mx27vis_amp_mute = value; | 111 | mx27vis_amp_mute = value; |
| 120 | break; | 112 | break; |
| 121 | } | 113 | } |
| @@ -190,8 +182,19 @@ static struct snd_soc_card mx27vis_aic32x4 = { | |||
| 190 | 182 | ||
| 191 | static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev) | 183 | static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev) |
| 192 | { | 184 | { |
| 185 | struct snd_mx27vis_platform_data *pdata = pdev->dev.platform_data; | ||
| 193 | int ret; | 186 | int ret; |
| 194 | 187 | ||
| 188 | if (!pdata) { | ||
| 189 | dev_err(&pdev->dev, "No platform data supplied\n"); | ||
| 190 | return -EINVAL; | ||
| 191 | } | ||
| 192 | |||
| 193 | mx27vis_amp_gain0_gpio = pdata->amp_gain0_gpio; | ||
| 194 | mx27vis_amp_gain1_gpio = pdata->amp_gain1_gpio; | ||
| 195 | mx27vis_amp_mutel_gpio = pdata->amp_mutel_gpio; | ||
| 196 | mx27vis_amp_muter_gpio = pdata->amp_muter_gpio; | ||
| 197 | |||
| 195 | mx27vis_aic32x4.dev = &pdev->dev; | 198 | mx27vis_aic32x4.dev = &pdev->dev; |
| 196 | ret = snd_soc_register_card(&mx27vis_aic32x4); | 199 | ret = snd_soc_register_card(&mx27vis_aic32x4); |
| 197 | if (ret) { | 200 | if (ret) { |
| @@ -213,11 +216,6 @@ static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev) | |||
| 213 | IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) | 216 | IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0) |
| 214 | ); | 217 | ); |
| 215 | 218 | ||
| 216 | ret = mxc_gpio_setup_multiple_pins(mx27vis_amp_pins, | ||
| 217 | ARRAY_SIZE(mx27vis_amp_pins), "MX27VIS_AMP"); | ||
| 218 | if (ret) | ||
| 219 | printk(KERN_ERR "ASoC: unable to setup gpios\n"); | ||
| 220 | |||
| 221 | return ret; | 219 | return ret; |
| 222 | } | 220 | } |
| 223 | 221 | ||
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index 50adf4032bcc..144d49603637 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c | |||
| @@ -202,7 +202,6 @@ static int p1022_ds_probe(struct platform_device *pdev) | |||
| 202 | container_of(dev, struct platform_device, dev); | 202 | container_of(dev, struct platform_device, dev); |
| 203 | struct device_node *np = ssi_pdev->dev.of_node; | 203 | struct device_node *np = ssi_pdev->dev.of_node; |
| 204 | struct device_node *codec_np = NULL; | 204 | struct device_node *codec_np = NULL; |
| 205 | struct platform_device *sound_device = NULL; | ||
| 206 | struct machine_data *mdata; | 205 | struct machine_data *mdata; |
| 207 | int ret = -ENODEV; | 206 | int ret = -ENODEV; |
| 208 | const char *sprop; | 207 | const char *sprop; |
| @@ -349,36 +348,23 @@ static int p1022_ds_probe(struct platform_device *pdev) | |||
| 349 | mdata->card.probe = p1022_ds_machine_probe; | 348 | mdata->card.probe = p1022_ds_machine_probe; |
| 350 | mdata->card.remove = p1022_ds_machine_remove; | 349 | mdata->card.remove = p1022_ds_machine_remove; |
| 351 | mdata->card.name = pdev->name; /* The platform driver name */ | 350 | mdata->card.name = pdev->name; /* The platform driver name */ |
| 351 | mdata->card.owner = THIS_MODULE; | ||
| 352 | mdata->card.dev = &pdev->dev; | ||
| 352 | mdata->card.num_links = 2; | 353 | mdata->card.num_links = 2; |
| 353 | mdata->card.dai_link = mdata->dai; | 354 | mdata->card.dai_link = mdata->dai; |
| 354 | 355 | ||
| 355 | /* Allocate a new audio platform device structure */ | ||
| 356 | sound_device = platform_device_alloc("soc-audio", -1); | ||
| 357 | if (!sound_device) { | ||
| 358 | dev_err(&pdev->dev, "platform device alloc failed\n"); | ||
| 359 | ret = -ENOMEM; | ||
| 360 | goto error; | ||
| 361 | } | ||
| 362 | |||
| 363 | /* Associate the card data with the sound device */ | ||
| 364 | platform_set_drvdata(sound_device, &mdata->card); | ||
| 365 | |||
| 366 | /* Register with ASoC */ | 356 | /* Register with ASoC */ |
| 367 | ret = platform_device_add(sound_device); | 357 | ret = snd_soc_register_card(&mdata->card); |
| 368 | if (ret) { | 358 | if (ret) { |
| 369 | dev_err(&pdev->dev, "platform device add failed\n"); | 359 | dev_err(&pdev->dev, "could not register card\n"); |
| 370 | goto error; | 360 | goto error; |
| 371 | } | 361 | } |
| 372 | dev_set_drvdata(&pdev->dev, sound_device); | ||
| 373 | 362 | ||
| 374 | of_node_put(codec_np); | 363 | of_node_put(codec_np); |
| 375 | 364 | ||
| 376 | return 0; | 365 | return 0; |
| 377 | 366 | ||
| 378 | error: | 367 | error: |
| 379 | if (sound_device) | ||
| 380 | platform_device_put(sound_device); | ||
| 381 | |||
| 382 | kfree(mdata); | 368 | kfree(mdata); |
| 383 | error_put: | 369 | error_put: |
| 384 | of_node_put(codec_np); | 370 | of_node_put(codec_np); |
| @@ -392,17 +378,12 @@ error_put: | |||
| 392 | */ | 378 | */ |
| 393 | static int __devexit p1022_ds_remove(struct platform_device *pdev) | 379 | static int __devexit p1022_ds_remove(struct platform_device *pdev) |
| 394 | { | 380 | { |
| 395 | struct platform_device *sound_device = dev_get_drvdata(&pdev->dev); | 381 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 396 | struct snd_soc_card *card = platform_get_drvdata(sound_device); | ||
| 397 | struct machine_data *mdata = | 382 | struct machine_data *mdata = |
| 398 | container_of(card, struct machine_data, card); | 383 | container_of(card, struct machine_data, card); |
| 399 | 384 | ||
| 400 | platform_device_unregister(sound_device); | 385 | snd_soc_unregister_card(card); |
| 401 | |||
| 402 | kfree(mdata); | 386 | kfree(mdata); |
| 403 | sound_device->dev.platform_data = NULL; | ||
| 404 | |||
| 405 | dev_set_drvdata(&pdev->dev, NULL); | ||
| 406 | 387 | ||
| 407 | return 0; | 388 | return 0; |
| 408 | } | 389 | } |
diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c index b3af55dcde9d..4b63ec8eb372 100644 --- a/sound/soc/fsl/pcm030-audio-fabric.c +++ b/sound/soc/fsl/pcm030-audio-fabric.c | |||
| @@ -12,32 +12,27 @@ | |||
| 12 | 12 | ||
| 13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/interrupt.h> | ||
| 16 | #include <linux/device.h> | 15 | #include <linux/device.h> |
| 17 | #include <linux/delay.h> | ||
| 18 | #include <linux/of_device.h> | 16 | #include <linux/of_device.h> |
| 19 | #include <linux/of_platform.h> | 17 | #include <linux/of_platform.h> |
| 20 | #include <linux/dma-mapping.h> | ||
| 21 | 18 | ||
| 22 | #include <sound/core.h> | ||
| 23 | #include <sound/pcm.h> | ||
| 24 | #include <sound/pcm_params.h> | ||
| 25 | #include <sound/initval.h> | ||
| 26 | #include <sound/soc.h> | 19 | #include <sound/soc.h> |
| 27 | 20 | ||
| 28 | #include "mpc5200_dma.h" | 21 | #include "mpc5200_dma.h" |
| 29 | #include "mpc5200_psc_ac97.h" | ||
| 30 | #include "../codecs/wm9712.h" | ||
| 31 | 22 | ||
| 32 | #define DRV_NAME "pcm030-audio-fabric" | 23 | #define DRV_NAME "pcm030-audio-fabric" |
| 33 | 24 | ||
| 25 | struct pcm030_audio_data { | ||
| 26 | struct snd_soc_card *card; | ||
| 27 | struct platform_device *codec_device; | ||
| 28 | }; | ||
| 29 | |||
| 34 | static struct snd_soc_dai_link pcm030_fabric_dai[] = { | 30 | static struct snd_soc_dai_link pcm030_fabric_dai[] = { |
| 35 | { | 31 | { |
| 36 | .name = "AC97", | 32 | .name = "AC97", |
| 37 | .stream_name = "AC97 Analog", | 33 | .stream_name = "AC97 Analog", |
| 38 | .codec_dai_name = "wm9712-hifi", | 34 | .codec_dai_name = "wm9712-hifi", |
| 39 | .cpu_dai_name = "mpc5200-psc-ac97.0", | 35 | .cpu_dai_name = "mpc5200-psc-ac97.0", |
| 40 | .platform_name = "mpc5200-pcm-audio", | ||
| 41 | .codec_name = "wm9712-codec", | 36 | .codec_name = "wm9712-codec", |
| 42 | }, | 37 | }, |
| 43 | { | 38 | { |
| @@ -45,44 +40,95 @@ static struct snd_soc_dai_link pcm030_fabric_dai[] = { | |||
| 45 | .stream_name = "AC97 IEC958", | 40 | .stream_name = "AC97 IEC958", |
| 46 | .codec_dai_name = "wm9712-aux", | 41 | .codec_dai_name = "wm9712-aux", |
| 47 | .cpu_dai_name = "mpc5200-psc-ac97.1", | 42 | .cpu_dai_name = "mpc5200-psc-ac97.1", |
| 48 | .platform_name = "mpc5200-pcm-audio", | ||
| 49 | .codec_name = "wm9712-codec", | 43 | .codec_name = "wm9712-codec", |
| 50 | }, | 44 | }, |
| 51 | }; | 45 | }; |
| 52 | 46 | ||
| 53 | static struct snd_soc_card card = { | 47 | static struct snd_soc_card pcm030_card = { |
| 54 | .name = "pcm030", | 48 | .name = "pcm030", |
| 55 | .owner = THIS_MODULE, | 49 | .owner = THIS_MODULE, |
| 56 | .dai_link = pcm030_fabric_dai, | 50 | .dai_link = pcm030_fabric_dai, |
| 57 | .num_links = ARRAY_SIZE(pcm030_fabric_dai), | 51 | .num_links = ARRAY_SIZE(pcm030_fabric_dai), |
| 58 | }; | 52 | }; |
| 59 | 53 | ||
| 60 | static __init int pcm030_fabric_init(void) | 54 | static int __init pcm030_fabric_probe(struct platform_device *op) |
| 61 | { | 55 | { |
| 62 | struct platform_device *pdev; | 56 | struct device_node *np = op->dev.of_node; |
| 63 | int rc; | 57 | struct device_node *platform_np; |
| 58 | struct snd_soc_card *card = &pcm030_card; | ||
| 59 | struct pcm030_audio_data *pdata; | ||
| 60 | int ret; | ||
| 61 | int i; | ||
| 64 | 62 | ||
| 65 | if (!of_machine_is_compatible("phytec,pcm030")) | 63 | if (!of_machine_is_compatible("phytec,pcm030")) |
| 66 | return -ENODEV; | 64 | return -ENODEV; |
| 67 | 65 | ||
| 68 | pdev = platform_device_alloc("soc-audio", 1); | 66 | pdata = devm_kzalloc(&op->dev, sizeof(struct pcm030_audio_data), |
| 69 | if (!pdev) { | 67 | GFP_KERNEL); |
| 70 | pr_err("pcm030_fabric_init: platform_device_alloc() failed\n"); | 68 | if (!pdata) |
| 71 | return -ENODEV; | 69 | return -ENOMEM; |
| 72 | } | 70 | |
| 71 | card->dev = &op->dev; | ||
| 72 | platform_set_drvdata(op, pdata); | ||
| 73 | 73 | ||
| 74 | platform_set_drvdata(pdev, &card); | 74 | pdata->card = card; |
| 75 | 75 | ||
| 76 | rc = platform_device_add(pdev); | 76 | platform_np = of_parse_phandle(np, "asoc-platform", 0); |
| 77 | if (rc) { | 77 | if (!platform_np) { |
| 78 | pr_err("pcm030_fabric_init: platform_device_add() failed\n"); | 78 | dev_err(&op->dev, "ac97 not registered\n"); |
| 79 | platform_device_put(pdev); | ||
| 80 | return -ENODEV; | 79 | return -ENODEV; |
| 81 | } | 80 | } |
| 82 | return 0; | 81 | |
| 82 | for (i = 0; i < card->num_links; i++) | ||
| 83 | card->dai_link[i].platform_of_node = platform_np; | ||
| 84 | |||
| 85 | ret = request_module("snd-soc-wm9712"); | ||
| 86 | if (ret) | ||
| 87 | dev_err(&op->dev, "request_module returned: %d\n", ret); | ||
| 88 | |||
| 89 | pdata->codec_device = platform_device_alloc("wm9712-codec", -1); | ||
| 90 | if (!pdata->codec_device) | ||
| 91 | dev_err(&op->dev, "platform_device_alloc() failed\n"); | ||
| 92 | |||
| 93 | ret = platform_device_add(pdata->codec_device); | ||
| 94 | if (ret) | ||
| 95 | dev_err(&op->dev, "platform_device_add() failed: %d\n", ret); | ||
| 96 | |||
| 97 | ret = snd_soc_register_card(card); | ||
| 98 | if (ret) | ||
| 99 | dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret); | ||
| 100 | |||
| 101 | return ret; | ||
| 102 | } | ||
| 103 | |||
| 104 | static int __devexit pcm030_fabric_remove(struct platform_device *op) | ||
| 105 | { | ||
| 106 | struct pcm030_audio_data *pdata = platform_get_drvdata(op); | ||
| 107 | int ret; | ||
| 108 | |||
| 109 | ret = snd_soc_unregister_card(pdata->card); | ||
| 110 | platform_device_unregister(pdata->codec_device); | ||
| 111 | |||
| 112 | return ret; | ||
| 83 | } | 113 | } |
| 84 | 114 | ||
| 85 | module_init(pcm030_fabric_init); | 115 | static struct of_device_id pcm030_audio_match[] = { |
| 116 | { .compatible = "phytec,pcm030-audio-fabric", }, | ||
| 117 | {} | ||
| 118 | }; | ||
| 119 | MODULE_DEVICE_TABLE(of, pcm030_audio_match); | ||
| 120 | |||
| 121 | static struct platform_driver pcm030_fabric_driver = { | ||
| 122 | .probe = pcm030_fabric_probe, | ||
| 123 | .remove = __devexit_p(pcm030_fabric_remove), | ||
| 124 | .driver = { | ||
| 125 | .name = DRV_NAME, | ||
| 126 | .owner = THIS_MODULE, | ||
| 127 | .of_match_table = pcm030_audio_match, | ||
| 128 | }, | ||
| 129 | }; | ||
| 130 | |||
| 131 | module_platform_driver(pcm030_fabric_driver); | ||
| 86 | 132 | ||
| 87 | 133 | ||
| 88 | MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>"); | 134 | MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>"); |
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c index 2937e54da49e..2cc7782714b5 100644 --- a/sound/soc/mid-x86/mfld_machine.c +++ b/sound/soc/mid-x86/mfld_machine.c | |||
| @@ -318,6 +318,15 @@ static struct snd_soc_dai_link mfld_msic_dailink[] = { | |||
| 318 | .platform_name = "sst-platform", | 318 | .platform_name = "sst-platform", |
| 319 | .init = NULL, | 319 | .init = NULL, |
| 320 | }, | 320 | }, |
| 321 | { | ||
| 322 | .name = "Medfield Compress", | ||
| 323 | .stream_name = "Speaker", | ||
| 324 | .cpu_dai_name = "Compress-cpu-dai", | ||
| 325 | .codec_dai_name = "SN95031 Speaker", | ||
| 326 | .codec_name = "sn95031", | ||
| 327 | .platform_name = "sst-platform", | ||
| 328 | .init = NULL, | ||
| 329 | }, | ||
| 321 | }; | 330 | }; |
| 322 | 331 | ||
| 323 | /* SoC card */ | 332 | /* SoC card */ |
diff --git a/sound/soc/mid-x86/sst_dsp.h b/sound/soc/mid-x86/sst_dsp.h new file mode 100644 index 000000000000..0fce1de284ff --- /dev/null +++ b/sound/soc/mid-x86/sst_dsp.h | |||
| @@ -0,0 +1,134 @@ | |||
| 1 | #ifndef __SST_DSP_H__ | ||
| 2 | #define __SST_DSP_H__ | ||
| 3 | /* | ||
| 4 | * sst_dsp.h - Intel SST Driver for audio engine | ||
| 5 | * | ||
| 6 | * Copyright (C) 2008-12 Intel Corporation | ||
| 7 | * Authors: Vinod Koul <vinod.koul@linux.intel.com> | ||
| 8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; version 2 of the License. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, but | ||
| 15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 17 | * General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License along | ||
| 20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 21 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
| 22 | * | ||
| 23 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 24 | */ | ||
| 25 | |||
| 26 | enum sst_codec_types { | ||
| 27 | /* AUDIO/MUSIC CODEC Type Definitions */ | ||
| 28 | SST_CODEC_TYPE_UNKNOWN = 0, | ||
| 29 | SST_CODEC_TYPE_PCM, /* Pass through Audio codec */ | ||
| 30 | SST_CODEC_TYPE_MP3, | ||
| 31 | SST_CODEC_TYPE_MP24, | ||
| 32 | SST_CODEC_TYPE_AAC, | ||
| 33 | SST_CODEC_TYPE_AACP, | ||
| 34 | SST_CODEC_TYPE_eAACP, | ||
| 35 | }; | ||
| 36 | |||
| 37 | enum stream_type { | ||
| 38 | SST_STREAM_TYPE_NONE = 0, | ||
| 39 | SST_STREAM_TYPE_MUSIC = 1, | ||
| 40 | }; | ||
| 41 | |||
| 42 | struct snd_pcm_params { | ||
| 43 | u16 codec; /* codec type */ | ||
| 44 | u8 num_chan; /* 1=Mono, 2=Stereo */ | ||
| 45 | u8 pcm_wd_sz; /* 16/24 - bit*/ | ||
| 46 | u32 reserved; /* Bitrate in bits per second */ | ||
| 47 | u32 sfreq; /* Sampling rate in Hz */ | ||
| 48 | u8 use_offload_path; | ||
| 49 | u8 reserved2; | ||
| 50 | u16 reserved3; | ||
| 51 | u8 channel_map[8]; | ||
| 52 | } __packed; | ||
| 53 | |||
| 54 | /* MP3 Music Parameters Message */ | ||
| 55 | struct snd_mp3_params { | ||
| 56 | u16 codec; | ||
| 57 | u8 num_chan; /* 1=Mono, 2=Stereo */ | ||
| 58 | u8 pcm_wd_sz; /* 16/24 - bit*/ | ||
| 59 | u8 crc_check; /* crc_check - disable (0) or enable (1) */ | ||
| 60 | u8 reserved1; /* unused*/ | ||
| 61 | u16 reserved2; /* Unused */ | ||
| 62 | } __packed; | ||
| 63 | |||
| 64 | #define AAC_BIT_STREAM_ADTS 0 | ||
| 65 | #define AAC_BIT_STREAM_ADIF 1 | ||
| 66 | #define AAC_BIT_STREAM_RAW 2 | ||
| 67 | |||
| 68 | /* AAC Music Parameters Message */ | ||
| 69 | struct snd_aac_params { | ||
| 70 | u16 codec; | ||
| 71 | u8 num_chan; /* 1=Mono, 2=Stereo*/ | ||
| 72 | u8 pcm_wd_sz; /* 16/24 - bit*/ | ||
| 73 | u8 bdownsample; /*SBR downsampling 0 - disable 1 -enabled AAC+ only */ | ||
| 74 | u8 bs_format; /* input bit stream format adts=0, adif=1, raw=2 */ | ||
| 75 | u16 reser2; | ||
| 76 | u32 externalsr; /*sampling rate of basic AAC raw bit stream*/ | ||
| 77 | u8 sbr_signalling;/*disable/enable/set automode the SBR tool.AAC+*/ | ||
| 78 | u8 reser1; | ||
| 79 | u16 reser3; | ||
| 80 | } __packed; | ||
| 81 | |||
| 82 | /* WMA Music Parameters Message */ | ||
| 83 | struct snd_wma_params { | ||
| 84 | u16 codec; | ||
| 85 | u8 num_chan; /* 1=Mono, 2=Stereo */ | ||
| 86 | u8 pcm_wd_sz; /* 16/24 - bit*/ | ||
| 87 | u32 brate; /* Use the hard coded value. */ | ||
| 88 | u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ | ||
| 89 | u32 channel_mask; /* Channel Mask */ | ||
| 90 | u16 format_tag; /* Format Tag */ | ||
| 91 | u16 block_align; /* packet size */ | ||
| 92 | u16 wma_encode_opt;/* Encoder option */ | ||
| 93 | u8 op_align; /* op align 0- 16 bit, 1- MSB, 2 LSB */ | ||
| 94 | u8 reserved; /* reserved */ | ||
| 95 | } __packed; | ||
| 96 | |||
| 97 | /* Codec params struture */ | ||
| 98 | union snd_sst_codec_params { | ||
| 99 | struct snd_pcm_params pcm_params; | ||
| 100 | struct snd_mp3_params mp3_params; | ||
| 101 | struct snd_aac_params aac_params; | ||
| 102 | struct snd_wma_params wma_params; | ||
| 103 | } __packed; | ||
| 104 | |||
| 105 | /* Address and size info of a frame buffer */ | ||
| 106 | struct sst_address_info { | ||
| 107 | u32 addr; /* Address at IA */ | ||
| 108 | u32 size; /* Size of the buffer */ | ||
| 109 | }; | ||
| 110 | |||
| 111 | struct snd_sst_alloc_params_ext { | ||
| 112 | struct sst_address_info ring_buf_info[8]; | ||
| 113 | u8 sg_count; | ||
| 114 | u8 reserved; | ||
| 115 | u16 reserved2; | ||
| 116 | u32 frag_size; /*Number of samples after which period elapsed | ||
| 117 | message is sent valid only if path = 0*/ | ||
| 118 | } __packed; | ||
| 119 | |||
| 120 | struct snd_sst_stream_params { | ||
| 121 | union snd_sst_codec_params uc; | ||
| 122 | } __packed; | ||
| 123 | |||
| 124 | struct snd_sst_params { | ||
| 125 | u32 stream_id; | ||
| 126 | u8 codec; | ||
| 127 | u8 ops; | ||
| 128 | u8 stream_type; | ||
| 129 | u8 device_type; | ||
| 130 | struct snd_sst_stream_params sparams; | ||
| 131 | struct snd_sst_alloc_params_ext aparams; | ||
| 132 | }; | ||
| 133 | |||
| 134 | #endif /* __SST_DSP_H__ */ | ||
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c index d34563b12c3b..a263cbed8624 100644 --- a/sound/soc/mid-x86/sst_platform.c +++ b/sound/soc/mid-x86/sst_platform.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * sst_platform.c - Intel MID Platform driver | 2 | * sst_platform.c - Intel MID Platform driver |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2010 Intel Corp | 4 | * Copyright (C) 2010-2012 Intel Corp |
| 5 | * Author: Vinod Koul <vinod.koul@intel.com> | 5 | * Author: Vinod Koul <vinod.koul@intel.com> |
| 6 | * Author: Harsha Priya <priya.harsha@intel.com> | 6 | * Author: Harsha Priya <priya.harsha@intel.com> |
| 7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
| 33 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
| 34 | #include <sound/soc.h> | 34 | #include <sound/soc.h> |
| 35 | #include <sound/compress_driver.h> | ||
| 35 | #include "sst_platform.h" | 36 | #include "sst_platform.h" |
| 36 | 37 | ||
| 37 | static struct sst_device *sst; | 38 | static struct sst_device *sst; |
| @@ -152,6 +153,16 @@ static struct snd_soc_dai_driver sst_platform_dai[] = { | |||
| 152 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | 153 | .formats = SNDRV_PCM_FMTBIT_S24_LE, |
| 153 | }, | 154 | }, |
| 154 | }, | 155 | }, |
| 156 | { | ||
| 157 | .name = "Compress-cpu-dai", | ||
| 158 | .compress_dai = 1, | ||
| 159 | .playback = { | ||
| 160 | .channels_min = SST_STEREO, | ||
| 161 | .channels_max = SST_STEREO, | ||
| 162 | .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000, | ||
| 163 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
| 164 | }, | ||
| 165 | }, | ||
| 155 | }; | 166 | }; |
| 156 | 167 | ||
| 157 | /* helper functions */ | 168 | /* helper functions */ |
| @@ -463,8 +474,199 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
| 463 | } | 474 | } |
| 464 | return retval; | 475 | return retval; |
| 465 | } | 476 | } |
| 477 | |||
| 478 | /* compress stream operations */ | ||
| 479 | static void sst_compr_fragment_elapsed(void *arg) | ||
| 480 | { | ||
| 481 | struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg; | ||
| 482 | |||
| 483 | pr_debug("fragment elapsed by driver\n"); | ||
| 484 | if (cstream) | ||
| 485 | snd_compr_fragment_elapsed(cstream); | ||
| 486 | } | ||
| 487 | |||
| 488 | static int sst_platform_compr_open(struct snd_compr_stream *cstream) | ||
| 489 | { | ||
| 490 | |||
| 491 | int ret_val = 0; | ||
| 492 | struct snd_compr_runtime *runtime = cstream->runtime; | ||
| 493 | struct sst_runtime_stream *stream; | ||
| 494 | |||
| 495 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); | ||
| 496 | if (!stream) | ||
| 497 | return -ENOMEM; | ||
| 498 | |||
| 499 | spin_lock_init(&stream->status_lock); | ||
| 500 | |||
| 501 | /* get the sst ops */ | ||
| 502 | if (!sst || !try_module_get(sst->dev->driver->owner)) { | ||
| 503 | pr_err("no device available to run\n"); | ||
| 504 | ret_val = -ENODEV; | ||
| 505 | goto out_ops; | ||
| 506 | } | ||
| 507 | stream->compr_ops = sst->compr_ops; | ||
| 508 | |||
| 509 | stream->id = 0; | ||
| 510 | sst_set_stream_status(stream, SST_PLATFORM_INIT); | ||
| 511 | runtime->private_data = stream; | ||
| 512 | return 0; | ||
| 513 | out_ops: | ||
| 514 | kfree(stream); | ||
| 515 | return ret_val; | ||
| 516 | } | ||
| 517 | |||
| 518 | static int sst_platform_compr_free(struct snd_compr_stream *cstream) | ||
| 519 | { | ||
| 520 | struct sst_runtime_stream *stream; | ||
| 521 | int ret_val = 0, str_id; | ||
| 522 | |||
| 523 | stream = cstream->runtime->private_data; | ||
| 524 | /*need to check*/ | ||
| 525 | str_id = stream->id; | ||
| 526 | if (str_id) | ||
| 527 | ret_val = stream->compr_ops->close(str_id); | ||
| 528 | module_put(sst->dev->driver->owner); | ||
| 529 | kfree(stream); | ||
| 530 | pr_debug("%s: %d\n", __func__, ret_val); | ||
| 531 | return 0; | ||
| 532 | } | ||
| 533 | |||
| 534 | static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, | ||
| 535 | struct snd_compr_params *params) | ||
| 536 | { | ||
| 537 | struct sst_runtime_stream *stream; | ||
| 538 | int retval; | ||
| 539 | struct snd_sst_params str_params; | ||
| 540 | struct sst_compress_cb cb; | ||
| 541 | |||
| 542 | stream = cstream->runtime->private_data; | ||
| 543 | /* construct fw structure for this*/ | ||
| 544 | memset(&str_params, 0, sizeof(str_params)); | ||
| 545 | |||
| 546 | str_params.ops = STREAM_OPS_PLAYBACK; | ||
| 547 | str_params.stream_type = SST_STREAM_TYPE_MUSIC; | ||
| 548 | str_params.device_type = SND_SST_DEVICE_COMPRESS; | ||
| 549 | |||
| 550 | switch (params->codec.id) { | ||
| 551 | case SND_AUDIOCODEC_MP3: { | ||
| 552 | str_params.codec = SST_CODEC_TYPE_MP3; | ||
| 553 | str_params.sparams.uc.mp3_params.codec = SST_CODEC_TYPE_MP3; | ||
| 554 | str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in; | ||
| 555 | str_params.sparams.uc.mp3_params.pcm_wd_sz = 16; | ||
| 556 | break; | ||
| 557 | } | ||
| 558 | |||
| 559 | case SND_AUDIOCODEC_AAC: { | ||
| 560 | str_params.codec = SST_CODEC_TYPE_AAC; | ||
| 561 | str_params.sparams.uc.aac_params.codec = SST_CODEC_TYPE_AAC; | ||
| 562 | str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in; | ||
| 563 | str_params.sparams.uc.aac_params.pcm_wd_sz = 16; | ||
| 564 | if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS) | ||
| 565 | str_params.sparams.uc.aac_params.bs_format = | ||
| 566 | AAC_BIT_STREAM_ADTS; | ||
| 567 | else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW) | ||
| 568 | str_params.sparams.uc.aac_params.bs_format = | ||
| 569 | AAC_BIT_STREAM_RAW; | ||
| 570 | else { | ||
| 571 | pr_err("Undefined format%d\n", params->codec.format); | ||
| 572 | return -EINVAL; | ||
| 573 | } | ||
| 574 | str_params.sparams.uc.aac_params.externalsr = | ||
| 575 | params->codec.sample_rate; | ||
| 576 | break; | ||
| 577 | } | ||
| 578 | |||
| 579 | default: | ||
| 580 | pr_err("codec not supported, id =%d\n", params->codec.id); | ||
| 581 | return -EINVAL; | ||
| 582 | } | ||
| 583 | |||
| 584 | str_params.aparams.ring_buf_info[0].addr = | ||
| 585 | virt_to_phys(cstream->runtime->buffer); | ||
| 586 | str_params.aparams.ring_buf_info[0].size = | ||
| 587 | cstream->runtime->buffer_size; | ||
| 588 | str_params.aparams.sg_count = 1; | ||
| 589 | str_params.aparams.frag_size = cstream->runtime->fragment_size; | ||
| 590 | |||
| 591 | cb.param = cstream; | ||
| 592 | cb.compr_cb = sst_compr_fragment_elapsed; | ||
| 593 | |||
| 594 | retval = stream->compr_ops->open(&str_params, &cb); | ||
| 595 | if (retval < 0) { | ||
| 596 | pr_err("stream allocation failed %d\n", retval); | ||
| 597 | return retval; | ||
| 598 | } | ||
| 599 | |||
| 600 | stream->id = retval; | ||
| 601 | return 0; | ||
| 602 | } | ||
| 603 | |||
| 604 | static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd) | ||
| 605 | { | ||
| 606 | struct sst_runtime_stream *stream = | ||
| 607 | cstream->runtime->private_data; | ||
| 608 | |||
| 609 | return stream->compr_ops->control(cmd, stream->id); | ||
| 610 | } | ||
| 611 | |||
| 612 | static int sst_platform_compr_pointer(struct snd_compr_stream *cstream, | ||
| 613 | struct snd_compr_tstamp *tstamp) | ||
| 614 | { | ||
| 615 | struct sst_runtime_stream *stream; | ||
| 616 | |||
| 617 | stream = cstream->runtime->private_data; | ||
| 618 | stream->compr_ops->tstamp(stream->id, tstamp); | ||
| 619 | tstamp->byte_offset = tstamp->copied_total % | ||
| 620 | (u32)cstream->runtime->buffer_size; | ||
| 621 | pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset); | ||
| 622 | return 0; | ||
| 623 | } | ||
| 624 | |||
| 625 | static int sst_platform_compr_ack(struct snd_compr_stream *cstream, | ||
| 626 | size_t bytes) | ||
| 627 | { | ||
| 628 | struct sst_runtime_stream *stream; | ||
| 629 | |||
| 630 | stream = cstream->runtime->private_data; | ||
| 631 | stream->compr_ops->ack(stream->id, (unsigned long)bytes); | ||
| 632 | stream->bytes_written += bytes; | ||
| 633 | |||
| 634 | return 0; | ||
| 635 | } | ||
| 636 | |||
| 637 | static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream, | ||
| 638 | struct snd_compr_caps *caps) | ||
| 639 | { | ||
| 640 | struct sst_runtime_stream *stream = | ||
| 641 | cstream->runtime->private_data; | ||
| 642 | |||
| 643 | return stream->compr_ops->get_caps(caps); | ||
| 644 | } | ||
| 645 | |||
| 646 | static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream, | ||
| 647 | struct snd_compr_codec_caps *codec) | ||
| 648 | { | ||
| 649 | struct sst_runtime_stream *stream = | ||
| 650 | cstream->runtime->private_data; | ||
| 651 | |||
| 652 | return stream->compr_ops->get_codec_caps(codec); | ||
| 653 | } | ||
| 654 | |||
| 655 | static struct snd_compr_ops sst_platform_compr_ops = { | ||
| 656 | |||
| 657 | .open = sst_platform_compr_open, | ||
| 658 | .free = sst_platform_compr_free, | ||
| 659 | .set_params = sst_platform_compr_set_params, | ||
| 660 | .trigger = sst_platform_compr_trigger, | ||
| 661 | .pointer = sst_platform_compr_pointer, | ||
| 662 | .ack = sst_platform_compr_ack, | ||
| 663 | .get_caps = sst_platform_compr_get_caps, | ||
| 664 | .get_codec_caps = sst_platform_compr_get_codec_caps, | ||
| 665 | }; | ||
| 666 | |||
| 466 | static struct snd_soc_platform_driver sst_soc_platform_drv = { | 667 | static struct snd_soc_platform_driver sst_soc_platform_drv = { |
| 467 | .ops = &sst_platform_ops, | 668 | .ops = &sst_platform_ops, |
| 669 | .compr_ops = &sst_platform_compr_ops, | ||
| 468 | .pcm_new = sst_pcm_new, | 670 | .pcm_new = sst_pcm_new, |
| 469 | .pcm_free = sst_pcm_free, | 671 | .pcm_free = sst_pcm_free, |
| 470 | }; | 672 | }; |
diff --git a/sound/soc/mid-x86/sst_platform.h b/sound/soc/mid-x86/sst_platform.h index f04f4f72daa0..d61c5d514ffa 100644 --- a/sound/soc/mid-x86/sst_platform.h +++ b/sound/soc/mid-x86/sst_platform.h | |||
| @@ -27,6 +27,8 @@ | |||
| 27 | #ifndef __SST_PLATFORMDRV_H__ | 27 | #ifndef __SST_PLATFORMDRV_H__ |
| 28 | #define __SST_PLATFORMDRV_H__ | 28 | #define __SST_PLATFORMDRV_H__ |
| 29 | 29 | ||
| 30 | #include "sst_dsp.h" | ||
| 31 | |||
| 30 | #define SST_MONO 1 | 32 | #define SST_MONO 1 |
| 31 | #define SST_STEREO 2 | 33 | #define SST_STEREO 2 |
| 32 | #define SST_MAX_CAP 5 | 34 | #define SST_MAX_CAP 5 |
| @@ -42,7 +44,6 @@ | |||
| 42 | #define SST_MIN_PERIODS 2 | 44 | #define SST_MIN_PERIODS 2 |
| 43 | #define SST_MAX_PERIODS (1024*2) | 45 | #define SST_MAX_PERIODS (1024*2) |
| 44 | #define SST_FIFO_SIZE 0 | 46 | #define SST_FIFO_SIZE 0 |
| 45 | #define SST_CODEC_TYPE_PCM 1 | ||
| 46 | 47 | ||
| 47 | struct pcm_stream_info { | 48 | struct pcm_stream_info { |
| 48 | int str_id; | 49 | int str_id; |
| @@ -83,6 +84,7 @@ enum sst_audio_device_type { | |||
| 83 | SND_SST_DEVICE_VIBRA, | 84 | SND_SST_DEVICE_VIBRA, |
| 84 | SND_SST_DEVICE_HAPTIC, | 85 | SND_SST_DEVICE_HAPTIC, |
| 85 | SND_SST_DEVICE_CAPTURE, | 86 | SND_SST_DEVICE_CAPTURE, |
| 87 | SND_SST_DEVICE_COMPRESS, | ||
| 86 | }; | 88 | }; |
| 87 | 89 | ||
| 88 | /* PCM Parameters */ | 90 | /* PCM Parameters */ |
| @@ -107,6 +109,24 @@ struct sst_stream_params { | |||
| 107 | struct sst_pcm_params sparams; | 109 | struct sst_pcm_params sparams; |
| 108 | }; | 110 | }; |
| 109 | 111 | ||
| 112 | struct sst_compress_cb { | ||
| 113 | void *param; | ||
| 114 | void (*compr_cb)(void *param); | ||
| 115 | }; | ||
| 116 | |||
| 117 | struct compress_sst_ops { | ||
| 118 | const char *name; | ||
| 119 | int (*open) (struct snd_sst_params *str_params, | ||
| 120 | struct sst_compress_cb *cb); | ||
| 121 | int (*control) (unsigned int cmd, unsigned int str_id); | ||
| 122 | int (*tstamp) (unsigned int str_id, struct snd_compr_tstamp *tstamp); | ||
| 123 | int (*ack) (unsigned int str_id, unsigned long bytes); | ||
| 124 | int (*close) (unsigned int str_id); | ||
| 125 | int (*get_caps) (struct snd_compr_caps *caps); | ||
| 126 | int (*get_codec_caps) (struct snd_compr_codec_caps *codec); | ||
| 127 | |||
| 128 | }; | ||
| 129 | |||
| 110 | struct sst_ops { | 130 | struct sst_ops { |
| 111 | int (*open) (struct sst_stream_params *str_param); | 131 | int (*open) (struct sst_stream_params *str_param); |
| 112 | int (*device_control) (int cmd, void *arg); | 132 | int (*device_control) (int cmd, void *arg); |
| @@ -115,8 +135,11 @@ struct sst_ops { | |||
| 115 | 135 | ||
| 116 | struct sst_runtime_stream { | 136 | struct sst_runtime_stream { |
| 117 | int stream_status; | 137 | int stream_status; |
| 138 | unsigned int id; | ||
| 139 | size_t bytes_written; | ||
| 118 | struct pcm_stream_info stream_info; | 140 | struct pcm_stream_info stream_info; |
| 119 | struct sst_ops *ops; | 141 | struct sst_ops *ops; |
| 142 | struct compress_sst_ops *compr_ops; | ||
| 120 | spinlock_t status_lock; | 143 | spinlock_t status_lock; |
| 121 | }; | 144 | }; |
| 122 | 145 | ||
| @@ -124,6 +147,7 @@ struct sst_device { | |||
| 124 | char *name; | 147 | char *name; |
| 125 | struct device *dev; | 148 | struct device *dev; |
| 126 | struct sst_ops *ops; | 149 | struct sst_ops *ops; |
| 150 | struct compress_sst_ops *compr_ops; | ||
| 127 | }; | 151 | }; |
| 128 | 152 | ||
| 129 | int sst_register_dsp(struct sst_device *sst); | 153 | int sst_register_dsp(struct sst_device *sst); |
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index b3030718c228..aa037b292f3d 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c | |||
| @@ -704,7 +704,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
| 704 | return ret; | 704 | return ret; |
| 705 | } | 705 | } |
| 706 | 706 | ||
| 707 | saif->clk = clk_get(&pdev->dev, NULL); | 707 | saif->clk = devm_clk_get(&pdev->dev, NULL); |
| 708 | if (IS_ERR(saif->clk)) { | 708 | if (IS_ERR(saif->clk)) { |
| 709 | ret = PTR_ERR(saif->clk); | 709 | ret = PTR_ERR(saif->clk); |
| 710 | dev_err(&pdev->dev, "Cannot get the clock: %d\n", | 710 | dev_err(&pdev->dev, "Cannot get the clock: %d\n", |
| @@ -717,8 +717,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
| 717 | saif->base = devm_request_and_ioremap(&pdev->dev, iores); | 717 | saif->base = devm_request_and_ioremap(&pdev->dev, iores); |
| 718 | if (!saif->base) { | 718 | if (!saif->base) { |
| 719 | dev_err(&pdev->dev, "ioremap failed\n"); | 719 | dev_err(&pdev->dev, "ioremap failed\n"); |
| 720 | ret = -ENODEV; | 720 | return -ENODEV; |
| 721 | goto failed_get_resource; | ||
| 722 | } | 721 | } |
| 723 | 722 | ||
| 724 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 723 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
| @@ -731,7 +730,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
| 731 | &saif->dma_param.chan_num); | 730 | &saif->dma_param.chan_num); |
| 732 | if (ret) { | 731 | if (ret) { |
| 733 | dev_err(&pdev->dev, "failed to get dma channel\n"); | 732 | dev_err(&pdev->dev, "failed to get dma channel\n"); |
| 734 | goto failed_get_resource; | 733 | return ret; |
| 735 | } | 734 | } |
| 736 | } else { | 735 | } else { |
| 737 | saif->dma_param.chan_num = dmares->start; | 736 | saif->dma_param.chan_num = dmares->start; |
| @@ -742,7 +741,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
| 742 | ret = saif->irq; | 741 | ret = saif->irq; |
| 743 | dev_err(&pdev->dev, "failed to get irq resource: %d\n", | 742 | dev_err(&pdev->dev, "failed to get irq resource: %d\n", |
| 744 | ret); | 743 | ret); |
| 745 | goto failed_get_resource; | 744 | return ret; |
| 746 | } | 745 | } |
| 747 | 746 | ||
| 748 | saif->dev = &pdev->dev; | 747 | saif->dev = &pdev->dev; |
| @@ -750,7 +749,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
| 750 | "mxs-saif", saif); | 749 | "mxs-saif", saif); |
| 751 | if (ret) { | 750 | if (ret) { |
| 752 | dev_err(&pdev->dev, "failed to request irq\n"); | 751 | dev_err(&pdev->dev, "failed to request irq\n"); |
| 753 | goto failed_get_resource; | 752 | return ret; |
| 754 | } | 753 | } |
| 755 | 754 | ||
| 756 | saif->dma_param.chan_irq = platform_get_irq(pdev, 1); | 755 | saif->dma_param.chan_irq = platform_get_irq(pdev, 1); |
| @@ -758,7 +757,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
| 758 | ret = saif->dma_param.chan_irq; | 757 | ret = saif->dma_param.chan_irq; |
| 759 | dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", | 758 | dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", |
| 760 | ret); | 759 | ret); |
| 761 | goto failed_get_resource; | 760 | return ret; |
| 762 | } | 761 | } |
| 763 | 762 | ||
| 764 | platform_set_drvdata(pdev, saif); | 763 | platform_set_drvdata(pdev, saif); |
| @@ -766,7 +765,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
| 766 | ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai); | 765 | ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai); |
| 767 | if (ret) { | 766 | if (ret) { |
| 768 | dev_err(&pdev->dev, "register DAI failed\n"); | 767 | dev_err(&pdev->dev, "register DAI failed\n"); |
| 769 | goto failed_get_resource; | 768 | return ret; |
| 770 | } | 769 | } |
| 771 | 770 | ||
| 772 | ret = mxs_pcm_platform_register(&pdev->dev); | 771 | ret = mxs_pcm_platform_register(&pdev->dev); |
| @@ -779,19 +778,14 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
| 779 | 778 | ||
| 780 | failed_pdev_alloc: | 779 | failed_pdev_alloc: |
| 781 | snd_soc_unregister_dai(&pdev->dev); | 780 | snd_soc_unregister_dai(&pdev->dev); |
| 782 | failed_get_resource: | ||
| 783 | clk_put(saif->clk); | ||
| 784 | 781 | ||
| 785 | return ret; | 782 | return ret; |
| 786 | } | 783 | } |
| 787 | 784 | ||
| 788 | static int __devexit mxs_saif_remove(struct platform_device *pdev) | 785 | static int __devexit mxs_saif_remove(struct platform_device *pdev) |
| 789 | { | 786 | { |
| 790 | struct mxs_saif *saif = platform_get_drvdata(pdev); | ||
| 791 | |||
| 792 | mxs_pcm_platform_unregister(&pdev->dev); | 787 | mxs_pcm_platform_unregister(&pdev->dev); |
| 793 | snd_soc_unregister_dai(&pdev->dev); | 788 | snd_soc_unregister_dai(&pdev->dev); |
| 794 | clk_put(saif->clk); | ||
| 795 | 789 | ||
| 796 | return 0; | 790 | return 0; |
| 797 | } | 791 | } |
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 57a2fa751085..7048137f9a33 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | config SND_OMAP_SOC | 1 | config SND_OMAP_SOC |
| 2 | tristate "SoC Audio for the Texas Instruments OMAP chips" | 2 | tristate "SoC Audio for the Texas Instruments OMAP chips" |
| 3 | depends on ARCH_OMAP | 3 | depends on ARCH_OMAP && DMA_OMAP |
| 4 | select SND_SOC_DMAENGINE_PCM | ||
| 4 | 5 | ||
| 5 | config SND_OMAP_SOC_DMIC | 6 | config SND_OMAP_SOC_DMIC |
| 6 | tristate | 7 | tristate |
| @@ -60,23 +61,6 @@ config SND_OMAP_SOC_OSK5912 | |||
| 60 | help | 61 | help |
| 61 | Say Y if you want to add support for SoC audio on osk5912. | 62 | Say Y if you want to add support for SoC audio on osk5912. |
| 62 | 63 | ||
| 63 | config SND_OMAP_SOC_OVERO | ||
| 64 | tristate "SoC Audio support for Gumstix Overo and CompuLab CM-T35" | ||
| 65 | depends on TWL4030_CORE && SND_OMAP_SOC && (MACH_OVERO || MACH_CM_T35) | ||
| 66 | select SND_OMAP_SOC_MCBSP | ||
| 67 | select SND_SOC_TWL4030 | ||
| 68 | help | ||
| 69 | Say Y if you want to add support for SoC audio on the | ||
| 70 | Gumstix Overo or CompuLab CM-T35 | ||
| 71 | |||
| 72 | config SND_OMAP_SOC_OMAP3EVM | ||
| 73 | tristate "SoC Audio support for OMAP3EVM board" | ||
| 74 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3EVM | ||
| 75 | select SND_OMAP_SOC_MCBSP | ||
| 76 | select SND_SOC_TWL4030 | ||
| 77 | help | ||
| 78 | Say Y if you want to add support for SoC audio on the omap3evm board. | ||
| 79 | |||
| 80 | config SND_OMAP_SOC_AM3517EVM | 64 | config SND_OMAP_SOC_AM3517EVM |
| 81 | tristate "SoC Audio support for OMAP3517 / AM3517 EVM" | 65 | tristate "SoC Audio support for OMAP3517 / AM3517 EVM" |
| 82 | depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C | 66 | depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C |
| @@ -95,6 +79,19 @@ config SND_OMAP_SOC_SDP3430 | |||
| 95 | Say Y if you want to add support for SoC audio on Texas Instruments | 79 | Say Y if you want to add support for SoC audio on Texas Instruments |
| 96 | SDP3430. | 80 | SDP3430. |
| 97 | 81 | ||
| 82 | config SND_OMAP_SOC_OMAP_TWL4030 | ||
| 83 | tristate "SoC Audio support for TI SoC based boards with twl4030 codec" | ||
| 84 | depends on TWL4030_CORE && SND_OMAP_SOC | ||
| 85 | select SND_OMAP_SOC_MCBSP | ||
| 86 | select SND_SOC_TWL4030 | ||
| 87 | help | ||
| 88 | Say Y if you want to add support for SoC audio on TI SoC based boards | ||
| 89 | using twl4030 as c codec. This driver currently supports: | ||
| 90 | - Beagleboard or Devkit8000 | ||
| 91 | - Gumstix Overo or CompuLab CM-T35/CM-T3730 | ||
| 92 | - IGEP v2 | ||
| 93 | - OMAP3EVM | ||
| 94 | |||
| 98 | config SND_OMAP_SOC_OMAP_ABE_TWL6040 | 95 | config SND_OMAP_SOC_OMAP_ABE_TWL6040 |
| 99 | tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" | 96 | tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec" |
| 100 | depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4 | 97 | depends on TWL6040_CORE && SND_OMAP_SOC && ARCH_OMAP4 |
| @@ -127,16 +124,6 @@ config SND_OMAP_SOC_OMAP3_PANDORA | |||
| 127 | help | 124 | help |
| 128 | Say Y if you want to add support for SoC audio on the OMAP3 Pandora. | 125 | Say Y if you want to add support for SoC audio on the OMAP3 Pandora. |
| 129 | 126 | ||
| 130 | config SND_OMAP_SOC_OMAP3_BEAGLE | ||
| 131 | tristate "SoC Audio support for OMAP3 Beagle and Devkit8000" | ||
| 132 | depends on TWL4030_CORE && SND_OMAP_SOC | ||
| 133 | depends on (MACH_OMAP3_BEAGLE || MACH_DEVKIT8000) | ||
| 134 | select SND_OMAP_SOC_MCBSP | ||
| 135 | select SND_SOC_TWL4030 | ||
| 136 | help | ||
| 137 | Say Y if you want to add support for SoC audio on the Beagleboard or | ||
| 138 | the clone Devkit8000. | ||
| 139 | |||
| 140 | config SND_OMAP_SOC_ZOOM2 | 127 | config SND_OMAP_SOC_ZOOM2 |
| 141 | tristate "SoC Audio support for Zoom2" | 128 | tristate "SoC Audio support for Zoom2" |
| 142 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2 | 129 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_ZOOM2 |
| @@ -144,11 +131,3 @@ config SND_OMAP_SOC_ZOOM2 | |||
| 144 | select SND_SOC_TWL4030 | 131 | select SND_SOC_TWL4030 |
| 145 | help | 132 | help |
| 146 | Say Y if you want to add support for Soc audio on Zoom2 board. | 133 | Say Y if you want to add support for Soc audio on Zoom2 board. |
| 147 | |||
| 148 | config SND_OMAP_SOC_IGEP0020 | ||
| 149 | tristate "SoC Audio support for IGEP v2" | ||
| 150 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_IGEP0020 | ||
| 151 | select SND_OMAP_SOC_MCBSP | ||
| 152 | select SND_SOC_TWL4030 | ||
| 153 | help | ||
| 154 | Say Y if you want to add support for Soc audio on IGEP v2 board. | ||
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 0e14dd322565..19637e55ea48 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile | |||
| @@ -16,29 +16,23 @@ snd-soc-n810-objs := n810.o | |||
| 16 | snd-soc-rx51-objs := rx51.o | 16 | snd-soc-rx51-objs := rx51.o |
| 17 | snd-soc-ams-delta-objs := ams-delta.o | 17 | snd-soc-ams-delta-objs := ams-delta.o |
| 18 | snd-soc-osk5912-objs := osk5912.o | 18 | snd-soc-osk5912-objs := osk5912.o |
| 19 | snd-soc-overo-objs := overo.o | ||
| 20 | snd-soc-omap3evm-objs := omap3evm.o | ||
| 21 | snd-soc-am3517evm-objs := am3517evm.o | 19 | snd-soc-am3517evm-objs := am3517evm.o |
| 22 | snd-soc-sdp3430-objs := sdp3430.o | 20 | snd-soc-sdp3430-objs := sdp3430.o |
| 23 | snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o | 21 | snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o |
| 22 | snd-soc-omap-twl4030-objs := omap-twl4030.o | ||
| 24 | snd-soc-omap3pandora-objs := omap3pandora.o | 23 | snd-soc-omap3pandora-objs := omap3pandora.o |
| 25 | snd-soc-omap3beagle-objs := omap3beagle.o | ||
| 26 | snd-soc-zoom2-objs := zoom2.o | 24 | snd-soc-zoom2-objs := zoom2.o |
| 27 | snd-soc-igep0020-objs := igep0020.o | ||
| 28 | snd-soc-omap-hdmi-card-objs := omap-hdmi-card.o | 25 | snd-soc-omap-hdmi-card-objs := omap-hdmi-card.o |
| 29 | 26 | ||
| 30 | obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o | 27 | obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o |
| 31 | obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o | 28 | obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o |
| 32 | obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o | 29 | obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o |
| 33 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o | 30 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o |
| 34 | obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o | ||
| 35 | obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o | 31 | obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o |
| 36 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o | ||
| 37 | obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o | 32 | obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o |
| 38 | obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o | 33 | obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o |
| 39 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o | 34 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o |
| 35 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_TWL4030) += snd-soc-omap-twl4030.o | ||
| 40 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o | 36 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o |
| 41 | obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o | ||
| 42 | obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o | 37 | obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o |
| 43 | obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.o | ||
| 44 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_HDMI) += snd-soc-omap-hdmi-card.o | 38 | obj-$(CONFIG_SND_OMAP_SOC_OMAP_HDMI) += snd-soc-omap-hdmi-card.o |
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c index a52e87d28b6e..fad350682ca2 100644 --- a/sound/soc/omap/am3517evm.c +++ b/sound/soc/omap/am3517evm.c | |||
| @@ -41,32 +41,15 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream, | |||
| 41 | { | 41 | { |
| 42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 42 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 43 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | 43 | struct snd_soc_dai *codec_dai = rtd->codec_dai; |
| 44 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
| 45 | int ret; | 44 | int ret; |
| 46 | 45 | ||
| 47 | /* Set the codec system clock for DAC and ADC */ | 46 | /* Set the codec system clock for DAC and ADC */ |
| 48 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, | 47 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, |
| 49 | CODEC_CLOCK, SND_SOC_CLOCK_IN); | 48 | CODEC_CLOCK, SND_SOC_CLOCK_IN); |
| 50 | if (ret < 0) { | 49 | if (ret < 0) |
| 51 | printk(KERN_ERR "can't set codec system clock\n"); | 50 | printk(KERN_ERR "can't set codec system clock\n"); |
| 52 | return ret; | ||
| 53 | } | ||
| 54 | |||
| 55 | ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_CLKR_SRC_CLKX, 0, | ||
| 56 | SND_SOC_CLOCK_IN); | ||
| 57 | if (ret < 0) { | ||
| 58 | printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_CLKR_SRC_CLKX\n"); | ||
| 59 | return ret; | ||
| 60 | } | ||
| 61 | 51 | ||
| 62 | ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0, | 52 | return ret; |
| 63 | SND_SOC_CLOCK_IN); | ||
| 64 | if (ret < 0) { | ||
| 65 | printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n"); | ||
| 66 | return ret; | ||
| 67 | } | ||
| 68 | |||
| 69 | return 0; | ||
| 70 | } | 53 | } |
| 71 | 54 | ||
| 72 | static struct snd_soc_ops am3517evm_ops = { | 55 | static struct snd_soc_ops am3517evm_ops = { |
diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c deleted file mode 100644 index 5ed871676ed0..000000000000 --- a/sound/soc/omap/igep0020.c +++ /dev/null | |||
| @@ -1,120 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * igep0020.c -- SoC audio for IGEP v2 | ||
| 3 | * | ||
| 4 | * Based on sound/soc/omap/overo.c by Steve Sakoman | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * version 2 as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, but | ||
| 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 13 | * General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
| 18 | * 02110-1301 USA | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/clk.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <sound/core.h> | ||
| 26 | #include <sound/pcm.h> | ||
| 27 | #include <sound/soc.h> | ||
| 28 | |||
| 29 | #include <asm/mach-types.h> | ||
| 30 | #include <mach/hardware.h> | ||
| 31 | #include <mach/gpio.h> | ||
| 32 | #include <linux/platform_data/asoc-ti-mcbsp.h> | ||
| 33 | |||
| 34 | #include "omap-mcbsp.h" | ||
| 35 | #include "omap-pcm.h" | ||
| 36 | |||
| 37 | static int igep2_hw_params(struct snd_pcm_substream *substream, | ||
| 38 | struct snd_pcm_hw_params *params) | ||
| 39 | { | ||
| 40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 41 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
| 42 | int ret; | ||
| 43 | |||
| 44 | /* Set the codec system clock for DAC and ADC */ | ||
| 45 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, | ||
| 46 | SND_SOC_CLOCK_IN); | ||
| 47 | if (ret < 0) { | ||
| 48 | printk(KERN_ERR "can't set codec system clock\n"); | ||
| 49 | return ret; | ||
| 50 | } | ||
| 51 | |||
| 52 | return 0; | ||
| 53 | } | ||
| 54 | |||
| 55 | static struct snd_soc_ops igep2_ops = { | ||
| 56 | .hw_params = igep2_hw_params, | ||
| 57 | }; | ||
| 58 | |||
| 59 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
| 60 | static struct snd_soc_dai_link igep2_dai = { | ||
| 61 | .name = "TWL4030", | ||
| 62 | .stream_name = "TWL4030", | ||
| 63 | .cpu_dai_name = "omap-mcbsp.2", | ||
| 64 | .codec_dai_name = "twl4030-hifi", | ||
| 65 | .platform_name = "omap-pcm-audio", | ||
| 66 | .codec_name = "twl4030-codec", | ||
| 67 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
| 68 | SND_SOC_DAIFMT_CBM_CFM, | ||
| 69 | .ops = &igep2_ops, | ||
| 70 | }; | ||
| 71 | |||
| 72 | /* Audio machine driver */ | ||
| 73 | static struct snd_soc_card snd_soc_card_igep2 = { | ||
| 74 | .name = "igep2", | ||
| 75 | .owner = THIS_MODULE, | ||
| 76 | .dai_link = &igep2_dai, | ||
| 77 | .num_links = 1, | ||
| 78 | }; | ||
| 79 | |||
| 80 | static struct platform_device *igep2_snd_device; | ||
| 81 | |||
| 82 | static int __init igep2_soc_init(void) | ||
| 83 | { | ||
| 84 | int ret; | ||
| 85 | |||
| 86 | if (!machine_is_igep0020()) | ||
| 87 | return -ENODEV; | ||
| 88 | printk(KERN_INFO "IGEP v2 SoC init\n"); | ||
| 89 | |||
| 90 | igep2_snd_device = platform_device_alloc("soc-audio", -1); | ||
| 91 | if (!igep2_snd_device) { | ||
| 92 | printk(KERN_ERR "Platform device allocation failed\n"); | ||
| 93 | return -ENOMEM; | ||
| 94 | } | ||
| 95 | |||
| 96 | platform_set_drvdata(igep2_snd_device, &snd_soc_card_igep2); | ||
| 97 | |||
| 98 | ret = platform_device_add(igep2_snd_device); | ||
| 99 | if (ret) | ||
| 100 | goto err1; | ||
| 101 | |||
| 102 | return 0; | ||
| 103 | |||
| 104 | err1: | ||
| 105 | printk(KERN_ERR "Unable to add platform device\n"); | ||
| 106 | platform_device_put(igep2_snd_device); | ||
| 107 | |||
| 108 | return ret; | ||
| 109 | } | ||
| 110 | module_init(igep2_soc_init); | ||
| 111 | |||
| 112 | static void __exit igep2_soc_exit(void) | ||
| 113 | { | ||
| 114 | platform_device_unregister(igep2_snd_device); | ||
| 115 | } | ||
| 116 | module_exit(igep2_soc_exit); | ||
| 117 | |||
| 118 | MODULE_AUTHOR("Enric Balletbo i Serra <eballetbo@iseebcn.com>"); | ||
| 119 | MODULE_DESCRIPTION("ALSA SoC IGEP v2"); | ||
| 120 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index a681a9a8b846..afb8d4f1bedf 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
| 25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
| 26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| 27 | #include <linux/pm_runtime.h> | ||
| 27 | 28 | ||
| 28 | #include <linux/platform_data/asoc-ti-mcbsp.h> | 29 | #include <linux/platform_data/asoc-ti-mcbsp.h> |
| 29 | 30 | ||
| @@ -728,50 +729,39 @@ void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx) | |||
| 728 | 729 | ||
| 729 | int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id) | 730 | int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id) |
| 730 | { | 731 | { |
| 732 | struct clk *fck_src; | ||
| 731 | const char *src; | 733 | const char *src; |
| 734 | int r; | ||
| 732 | 735 | ||
| 733 | if (fck_src_id == MCBSP_CLKS_PAD_SRC) | 736 | if (fck_src_id == MCBSP_CLKS_PAD_SRC) |
| 734 | src = "clks_ext"; | 737 | src = "pad_fck"; |
| 735 | else if (fck_src_id == MCBSP_CLKS_PRCM_SRC) | 738 | else if (fck_src_id == MCBSP_CLKS_PRCM_SRC) |
| 736 | src = "clks_fclk"; | 739 | src = "prcm_fck"; |
| 737 | else | 740 | else |
| 738 | return -EINVAL; | 741 | return -EINVAL; |
| 739 | 742 | ||
| 740 | if (mcbsp->pdata->set_clk_src) | 743 | fck_src = clk_get(mcbsp->dev, src); |
| 741 | return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src); | 744 | if (IS_ERR(fck_src)) { |
| 742 | else | 745 | dev_err(mcbsp->dev, "CLKS: could not clk_get() %s\n", src); |
| 743 | return -EINVAL; | 746 | return -EINVAL; |
| 744 | } | 747 | } |
| 745 | |||
| 746 | int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux) | ||
| 747 | { | ||
| 748 | const char *signal, *src; | ||
| 749 | 748 | ||
| 750 | if (!mcbsp->pdata->mux_signal) | 749 | pm_runtime_put_sync(mcbsp->dev); |
| 751 | return -EINVAL; | ||
| 752 | 750 | ||
| 753 | switch (mux) { | 751 | r = clk_set_parent(mcbsp->fclk, fck_src); |
| 754 | case CLKR_SRC_CLKR: | 752 | if (r) { |
| 755 | signal = "clkr"; | 753 | dev_err(mcbsp->dev, "CLKS: could not clk_set_parent() to %s\n", |
| 756 | src = "clkr"; | 754 | src); |
| 757 | break; | 755 | clk_put(fck_src); |
| 758 | case CLKR_SRC_CLKX: | 756 | return r; |
| 759 | signal = "clkr"; | ||
| 760 | src = "clkx"; | ||
| 761 | break; | ||
| 762 | case FSR_SRC_FSR: | ||
| 763 | signal = "fsr"; | ||
| 764 | src = "fsr"; | ||
| 765 | break; | ||
| 766 | case FSR_SRC_FSX: | ||
| 767 | signal = "fsr"; | ||
| 768 | src = "fsx"; | ||
| 769 | break; | ||
| 770 | default: | ||
| 771 | return -EINVAL; | ||
| 772 | } | 757 | } |
| 773 | 758 | ||
| 774 | return mcbsp->pdata->mux_signal(mcbsp->dev, signal, src); | 759 | pm_runtime_get_sync(mcbsp->dev); |
| 760 | |||
| 761 | clk_put(fck_src); | ||
| 762 | |||
| 763 | return 0; | ||
| 764 | |||
| 775 | } | 765 | } |
| 776 | 766 | ||
| 777 | #define max_thres(m) (mcbsp->pdata->buffer_size) | 767 | #define max_thres(m) (mcbsp->pdata->buffer_size) |
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h index 262a6152111f..49a67259ce5a 100644 --- a/sound/soc/omap/mcbsp.h +++ b/sound/soc/omap/mcbsp.h | |||
| @@ -334,9 +334,6 @@ void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx); | |||
| 334 | /* McBSP functional clock source changing function */ | 334 | /* McBSP functional clock source changing function */ |
| 335 | int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id); | 335 | int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id); |
| 336 | 336 | ||
| 337 | /* McBSP signal muxing API */ | ||
| 338 | int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux); | ||
| 339 | |||
| 340 | /* Sidetone specific API */ | 337 | /* Sidetone specific API */ |
| 341 | int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain); | 338 | int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain); |
| 342 | int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain); | 339 | int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain); |
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index 45909ca889fa..4a73ef3ae12f 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/mfd/twl6040.h> | 25 | #include <linux/mfd/twl6040.h> |
| 26 | #include <linux/platform_data/omap-abe-twl6040.h> | 26 | #include <linux/platform_data/omap-abe-twl6040.h> |
| 27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
| 28 | #include <linux/of.h> | ||
| 28 | 29 | ||
| 29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
| 30 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
| @@ -39,6 +40,8 @@ | |||
| 39 | struct abe_twl6040 { | 40 | struct abe_twl6040 { |
| 40 | int jack_detection; /* board can detect jack events */ | 41 | int jack_detection; /* board can detect jack events */ |
| 41 | int mclk_freq; /* MCLK frequency speed for twl6040 */ | 42 | int mclk_freq; /* MCLK frequency speed for twl6040 */ |
| 43 | |||
| 44 | struct platform_device *dmic_codec_dev; | ||
| 42 | }; | 45 | }; |
| 43 | 46 | ||
| 44 | static int omap_abe_hw_params(struct snd_pcm_substream *substream, | 47 | static int omap_abe_hw_params(struct snd_pcm_substream *substream, |
| @@ -181,17 +184,6 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) | |||
| 181 | int hs_trim; | 184 | int hs_trim; |
| 182 | int ret = 0; | 185 | int ret = 0; |
| 183 | 186 | ||
| 184 | /* Disable not connected paths if not used */ | ||
| 185 | twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone"); | ||
| 186 | twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); | ||
| 187 | twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); | ||
| 188 | twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); | ||
| 189 | twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); | ||
| 190 | twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); | ||
| 191 | twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); | ||
| 192 | twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); | ||
| 193 | twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In"); | ||
| 194 | |||
| 195 | /* | 187 | /* |
| 196 | * Configure McPDM offset cancellation based on the HSOTRIM value from | 188 | * Configure McPDM offset cancellation based on the HSOTRIM value from |
| 197 | * twl6040. | 189 | * twl6040. |
| @@ -212,6 +204,24 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) | |||
| 212 | twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); | 204 | twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); |
| 213 | } | 205 | } |
| 214 | 206 | ||
| 207 | /* | ||
| 208 | * NULL pdata means we booted with DT. In this case the routing is | ||
| 209 | * provided and the card is fully routed, no need to mark pins. | ||
| 210 | */ | ||
| 211 | if (!pdata) | ||
| 212 | return ret; | ||
| 213 | |||
| 214 | /* Disable not connected paths if not used */ | ||
| 215 | twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone"); | ||
| 216 | twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); | ||
| 217 | twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); | ||
| 218 | twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); | ||
| 219 | twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); | ||
| 220 | twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); | ||
| 221 | twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); | ||
| 222 | twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); | ||
| 223 | twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In"); | ||
| 224 | |||
| 215 | return ret; | 225 | return ret; |
| 216 | } | 226 | } |
| 217 | 227 | ||
| @@ -266,52 +276,116 @@ static struct snd_soc_card omap_abe_card = { | |||
| 266 | static __devinit int omap_abe_probe(struct platform_device *pdev) | 276 | static __devinit int omap_abe_probe(struct platform_device *pdev) |
| 267 | { | 277 | { |
| 268 | struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev); | 278 | struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev); |
| 279 | struct device_node *node = pdev->dev.of_node; | ||
| 269 | struct snd_soc_card *card = &omap_abe_card; | 280 | struct snd_soc_card *card = &omap_abe_card; |
| 270 | struct abe_twl6040 *priv; | 281 | struct abe_twl6040 *priv; |
| 271 | int num_links = 0; | 282 | int num_links = 0; |
| 272 | int ret; | 283 | int ret = 0; |
| 273 | 284 | ||
| 274 | card->dev = &pdev->dev; | 285 | card->dev = &pdev->dev; |
| 275 | 286 | ||
| 276 | if (!pdata) { | ||
| 277 | dev_err(&pdev->dev, "Missing pdata\n"); | ||
| 278 | return -ENODEV; | ||
| 279 | } | ||
| 280 | |||
| 281 | priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); | 287 | priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); |
| 282 | if (priv == NULL) | 288 | if (priv == NULL) |
| 283 | return -ENOMEM; | 289 | return -ENOMEM; |
| 284 | 290 | ||
| 285 | if (pdata->card_name) { | 291 | priv->dmic_codec_dev = ERR_PTR(-EINVAL); |
| 286 | card->name = pdata->card_name; | 292 | |
| 293 | if (node) { | ||
| 294 | struct device_node *dai_node; | ||
| 295 | |||
| 296 | if (snd_soc_of_parse_card_name(card, "ti,model")) { | ||
| 297 | dev_err(&pdev->dev, "Card name is not provided\n"); | ||
| 298 | return -ENODEV; | ||
| 299 | } | ||
| 300 | |||
| 301 | ret = snd_soc_of_parse_audio_routing(card, | ||
| 302 | "ti,audio-routing"); | ||
| 303 | if (ret) { | ||
| 304 | dev_err(&pdev->dev, | ||
| 305 | "Error while parsing DAPM routing\n"); | ||
| 306 | return ret; | ||
| 307 | } | ||
| 308 | |||
| 309 | dai_node = of_parse_phandle(node, "ti,mcpdm", 0); | ||
| 310 | if (!dai_node) { | ||
| 311 | dev_err(&pdev->dev, "McPDM node is not provided\n"); | ||
| 312 | return -EINVAL; | ||
| 313 | } | ||
| 314 | abe_twl6040_dai_links[0].cpu_dai_name = NULL; | ||
| 315 | abe_twl6040_dai_links[0].cpu_of_node = dai_node; | ||
| 316 | |||
| 317 | dai_node = of_parse_phandle(node, "ti,dmic", 0); | ||
| 318 | if (dai_node) { | ||
| 319 | num_links = 2; | ||
| 320 | abe_twl6040_dai_links[1].cpu_dai_name = NULL; | ||
| 321 | abe_twl6040_dai_links[1].cpu_of_node = dai_node; | ||
| 322 | |||
| 323 | priv->dmic_codec_dev = platform_device_register_simple( | ||
| 324 | "dmic-codec", -1, NULL, 0); | ||
| 325 | if (IS_ERR(priv->dmic_codec_dev)) { | ||
| 326 | dev_err(&pdev->dev, | ||
| 327 | "Can't instantiate dmic-codec\n"); | ||
| 328 | return PTR_ERR(priv->dmic_codec_dev); | ||
| 329 | } | ||
| 330 | } else { | ||
| 331 | num_links = 1; | ||
| 332 | } | ||
| 333 | |||
| 334 | of_property_read_u32(node, "ti,jack-detection", | ||
| 335 | &priv->jack_detection); | ||
| 336 | of_property_read_u32(node, "ti,mclk-freq", | ||
| 337 | &priv->mclk_freq); | ||
| 338 | if (!priv->mclk_freq) { | ||
| 339 | dev_err(&pdev->dev, "MCLK frequency not provided\n"); | ||
| 340 | ret = -EINVAL; | ||
| 341 | goto err_unregister; | ||
| 342 | } | ||
| 343 | |||
| 344 | omap_abe_card.fully_routed = 1; | ||
| 345 | } else if (pdata) { | ||
| 346 | if (pdata->card_name) { | ||
| 347 | card->name = pdata->card_name; | ||
| 348 | } else { | ||
| 349 | dev_err(&pdev->dev, "Card name is not provided\n"); | ||
| 350 | return -ENODEV; | ||
| 351 | } | ||
| 352 | |||
| 353 | if (pdata->has_dmic) | ||
| 354 | num_links = 2; | ||
| 355 | else | ||
| 356 | num_links = 1; | ||
| 357 | |||
| 358 | priv->jack_detection = pdata->jack_detection; | ||
| 359 | priv->mclk_freq = pdata->mclk_freq; | ||
| 287 | } else { | 360 | } else { |
| 288 | dev_err(&pdev->dev, "Card name is not provided\n"); | 361 | dev_err(&pdev->dev, "Missing pdata\n"); |
| 289 | return -ENODEV; | 362 | return -ENODEV; |
| 290 | } | 363 | } |
| 291 | 364 | ||
| 292 | priv->jack_detection = pdata->jack_detection; | ||
| 293 | priv->mclk_freq = pdata->mclk_freq; | ||
| 294 | |||
| 295 | 365 | ||
| 296 | if (!priv->mclk_freq) { | 366 | if (!priv->mclk_freq) { |
| 297 | dev_err(&pdev->dev, "MCLK frequency missing\n"); | 367 | dev_err(&pdev->dev, "MCLK frequency missing\n"); |
| 298 | return -ENODEV; | 368 | ret = -ENODEV; |
| 369 | goto err_unregister; | ||
| 299 | } | 370 | } |
| 300 | 371 | ||
| 301 | if (pdata->has_dmic) | ||
| 302 | num_links = 2; | ||
| 303 | else | ||
| 304 | num_links = 1; | ||
| 305 | |||
| 306 | card->dai_link = abe_twl6040_dai_links; | 372 | card->dai_link = abe_twl6040_dai_links; |
| 307 | card->num_links = num_links; | 373 | card->num_links = num_links; |
| 308 | 374 | ||
| 309 | snd_soc_card_set_drvdata(card, priv); | 375 | snd_soc_card_set_drvdata(card, priv); |
| 310 | 376 | ||
| 311 | ret = snd_soc_register_card(card); | 377 | ret = snd_soc_register_card(card); |
| 312 | if (ret) | 378 | if (ret) { |
| 313 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | 379 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", |
| 314 | ret); | 380 | ret); |
| 381 | goto err_unregister; | ||
| 382 | } | ||
| 383 | |||
| 384 | return 0; | ||
| 385 | |||
| 386 | err_unregister: | ||
| 387 | if (!IS_ERR(priv->dmic_codec_dev)) | ||
| 388 | platform_device_unregister(priv->dmic_codec_dev); | ||
| 315 | 389 | ||
| 316 | return ret; | 390 | return ret; |
| 317 | } | 391 | } |
| @@ -319,17 +393,28 @@ static __devinit int omap_abe_probe(struct platform_device *pdev) | |||
| 319 | static int __devexit omap_abe_remove(struct platform_device *pdev) | 393 | static int __devexit omap_abe_remove(struct platform_device *pdev) |
| 320 | { | 394 | { |
| 321 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 395 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 396 | struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); | ||
| 322 | 397 | ||
| 323 | snd_soc_unregister_card(card); | 398 | snd_soc_unregister_card(card); |
| 324 | 399 | ||
| 400 | if (!IS_ERR(priv->dmic_codec_dev)) | ||
| 401 | platform_device_unregister(priv->dmic_codec_dev); | ||
| 402 | |||
| 325 | return 0; | 403 | return 0; |
| 326 | } | 404 | } |
| 327 | 405 | ||
| 406 | static const struct of_device_id omap_abe_of_match[] = { | ||
| 407 | {.compatible = "ti,abe-twl6040", }, | ||
| 408 | { }, | ||
| 409 | }; | ||
| 410 | MODULE_DEVICE_TABLE(of, omap_abe_of_match); | ||
| 411 | |||
| 328 | static struct platform_driver omap_abe_driver = { | 412 | static struct platform_driver omap_abe_driver = { |
| 329 | .driver = { | 413 | .driver = { |
| 330 | .name = "omap-abe-twl6040", | 414 | .name = "omap-abe-twl6040", |
| 331 | .owner = THIS_MODULE, | 415 | .owner = THIS_MODULE, |
| 332 | .pm = &snd_soc_pm_ops, | 416 | .pm = &snd_soc_pm_ops, |
| 417 | .of_match_table = omap_abe_of_match, | ||
| 333 | }, | 418 | }, |
| 334 | .probe = omap_abe_probe, | 419 | .probe = omap_abe_probe, |
| 335 | .remove = __devexit_p(omap_abe_remove), | 420 | .remove = __devexit_p(omap_abe_remove), |
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 75f5dca0e8d2..68f2cd1a9206 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c | |||
| @@ -33,7 +33,6 @@ | |||
| 33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| 34 | #include <linux/pm_runtime.h> | 34 | #include <linux/pm_runtime.h> |
| 35 | #include <linux/of_device.h> | 35 | #include <linux/of_device.h> |
| 36 | #include <plat/dma.h> | ||
| 37 | 36 | ||
| 38 | #include <sound/core.h> | 37 | #include <sound/core.h> |
| 39 | #include <sound/pcm.h> | 38 | #include <sound/pcm.h> |
| @@ -63,8 +62,6 @@ struct omap_dmic { | |||
| 63 | */ | 62 | */ |
| 64 | static struct omap_pcm_dma_data omap_dmic_dai_dma_params = { | 63 | static struct omap_pcm_dma_data omap_dmic_dai_dma_params = { |
| 65 | .name = "DMIC capture", | 64 | .name = "DMIC capture", |
| 66 | .data_type = OMAP_DMA_DATA_TYPE_S32, | ||
| 67 | .sync_mode = OMAP_DMA_SYNC_PACKET, | ||
| 68 | }; | 65 | }; |
| 69 | 66 | ||
| 70 | static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) | 67 | static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val) |
| @@ -121,6 +118,7 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream, | |||
| 121 | 118 | ||
| 122 | mutex_unlock(&dmic->mutex); | 119 | mutex_unlock(&dmic->mutex); |
| 123 | 120 | ||
| 121 | snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params); | ||
| 124 | return ret; | 122 | return ret; |
| 125 | } | 123 | } |
| 126 | 124 | ||
| @@ -205,6 +203,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream, | |||
| 205 | struct snd_soc_dai *dai) | 203 | struct snd_soc_dai *dai) |
| 206 | { | 204 | { |
| 207 | struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); | 205 | struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai); |
| 206 | struct omap_pcm_dma_data *dma_data; | ||
| 208 | int channels; | 207 | int channels; |
| 209 | 208 | ||
| 210 | dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params)); | 209 | dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params)); |
| @@ -230,8 +229,8 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream, | |||
| 230 | } | 229 | } |
| 231 | 230 | ||
| 232 | /* packet size is threshold * channels */ | 231 | /* packet size is threshold * channels */ |
| 233 | omap_dmic_dai_dma_params.packet_size = dmic->threshold * channels; | 232 | dma_data = snd_soc_dai_get_dma_data(dai, substream); |
| 234 | snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params); | 233 | dma_data->packet_size = dmic->threshold * channels; |
| 235 | 234 | ||
| 236 | return 0; | 235 | return 0; |
| 237 | } | 236 | } |
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c index a08245d9203c..f59c69fb400e 100644 --- a/sound/soc/omap/omap-hdmi.c +++ b/sound/soc/omap/omap-hdmi.c | |||
| @@ -34,7 +34,6 @@ | |||
| 34 | #include <sound/asoundef.h> | 34 | #include <sound/asoundef.h> |
| 35 | #include <video/omapdss.h> | 35 | #include <video/omapdss.h> |
| 36 | 36 | ||
| 37 | #include <plat/dma.h> | ||
| 38 | #include "omap-pcm.h" | 37 | #include "omap-pcm.h" |
| 39 | #include "omap-hdmi.h" | 38 | #include "omap-hdmi.h" |
| 40 | 39 | ||
| @@ -68,6 +67,9 @@ static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream, | |||
| 68 | dev_err(dai->dev, "audio not supported\n"); | 67 | dev_err(dai->dev, "audio not supported\n"); |
| 69 | return -ENODEV; | 68 | return -ENODEV; |
| 70 | } | 69 | } |
| 70 | |||
| 71 | snd_soc_dai_set_dma_data(dai, substream, &priv->dma_params); | ||
| 72 | |||
| 71 | return 0; | 73 | return 0; |
| 72 | } | 74 | } |
| 73 | 75 | ||
| @@ -86,24 +88,24 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream, | |||
| 86 | struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai); | 88 | struct hdmi_priv *priv = snd_soc_dai_get_drvdata(dai); |
| 87 | struct snd_aes_iec958 *iec = &priv->iec; | 89 | struct snd_aes_iec958 *iec = &priv->iec; |
| 88 | struct snd_cea_861_aud_if *cea = &priv->cea; | 90 | struct snd_cea_861_aud_if *cea = &priv->cea; |
| 91 | struct omap_pcm_dma_data *dma_data; | ||
| 89 | int err = 0; | 92 | int err = 0; |
| 90 | 93 | ||
| 94 | dma_data = snd_soc_dai_get_dma_data(dai, substream); | ||
| 95 | |||
| 91 | switch (params_format(params)) { | 96 | switch (params_format(params)) { |
| 92 | case SNDRV_PCM_FORMAT_S16_LE: | 97 | case SNDRV_PCM_FORMAT_S16_LE: |
| 93 | priv->dma_params.packet_size = 16; | 98 | dma_data->packet_size = 16; |
| 94 | break; | 99 | break; |
| 95 | case SNDRV_PCM_FORMAT_S24_LE: | 100 | case SNDRV_PCM_FORMAT_S24_LE: |
| 96 | priv->dma_params.packet_size = 32; | 101 | dma_data->packet_size = 32; |
| 97 | break; | 102 | break; |
| 98 | default: | 103 | default: |
| 99 | dev_err(dai->dev, "format not supported!\n"); | 104 | dev_err(dai->dev, "format not supported!\n"); |
| 100 | return -EINVAL; | 105 | return -EINVAL; |
| 101 | } | 106 | } |
| 102 | 107 | ||
| 103 | priv->dma_params.data_type = OMAP_DMA_DATA_TYPE_S32; | 108 | dma_data->data_type = 32; |
| 104 | |||
| 105 | snd_soc_dai_set_dma_data(dai, substream, | ||
| 106 | &priv->dma_params); | ||
| 107 | 109 | ||
| 108 | /* | 110 | /* |
| 109 | * fill the IEC-60958 channel status word | 111 | * fill the IEC-60958 channel status word |
| @@ -290,7 +292,6 @@ static __devinit int omap_hdmi_probe(struct platform_device *pdev) | |||
| 290 | 292 | ||
| 291 | hdmi_data->dma_params.dma_req = hdmi_rsrc->start; | 293 | hdmi_data->dma_params.dma_req = hdmi_rsrc->start; |
| 292 | hdmi_data->dma_params.name = "HDMI playback"; | 294 | hdmi_data->dma_params.name = "HDMI playback"; |
| 293 | hdmi_data->dma_params.sync_mode = OMAP_DMA_SYNC_PACKET; | ||
| 294 | 295 | ||
| 295 | /* | 296 | /* |
| 296 | * TODO: We assume that there is only one DSS HDMI device. Future | 297 | * TODO: We assume that there is only one DSS HDMI device. Future |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 1b18627763ce..a6ee15747859 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | #include <linux/device.h> | 27 | #include <linux/device.h> |
| 28 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
| 29 | #include <linux/of.h> | ||
| 30 | #include <linux/of_device.h> | ||
| 29 | #include <sound/core.h> | 31 | #include <sound/core.h> |
| 30 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
| 31 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
| @@ -33,7 +35,6 @@ | |||
| 33 | #include <sound/soc.h> | 35 | #include <sound/soc.h> |
| 34 | 36 | ||
| 35 | #include <plat/cpu.h> | 37 | #include <plat/cpu.h> |
| 36 | #include <plat/dma.h> | ||
| 37 | #include <linux/platform_data/asoc-ti-mcbsp.h> | 38 | #include <linux/platform_data/asoc-ti-mcbsp.h> |
| 38 | #include "mcbsp.h" | 39 | #include "mcbsp.h" |
| 39 | #include "omap-mcbsp.h" | 40 | #include "omap-mcbsp.h" |
| @@ -80,9 +81,6 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream) | |||
| 80 | */ | 81 | */ |
| 81 | if (dma_data->packet_size) | 82 | if (dma_data->packet_size) |
| 82 | words = dma_data->packet_size; | 83 | words = dma_data->packet_size; |
| 83 | else if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) | ||
| 84 | words = snd_pcm_lib_period_bytes(substream) / | ||
| 85 | (mcbsp->wlen / 8); | ||
| 86 | else | 84 | else |
| 87 | words = 1; | 85 | words = 1; |
| 88 | 86 | ||
| @@ -154,6 +152,9 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, | |||
| 154 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2); | 152 | SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 2); |
| 155 | } | 153 | } |
| 156 | 154 | ||
| 155 | snd_soc_dai_set_dma_data(cpu_dai, substream, | ||
| 156 | &mcbsp->dma_data[substream->stream]); | ||
| 157 | |||
| 157 | return err; | 158 | return err; |
| 158 | } | 159 | } |
| 159 | 160 | ||
| @@ -227,20 +228,18 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
| 227 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); | 228 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); |
| 228 | struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; | 229 | struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs; |
| 229 | struct omap_pcm_dma_data *dma_data; | 230 | struct omap_pcm_dma_data *dma_data; |
| 230 | int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; | 231 | int wlen, channels, wpf; |
| 231 | int pkt_size = 0; | 232 | int pkt_size = 0; |
| 232 | unsigned int format, div, framesize, master; | 233 | unsigned int format, div, framesize, master; |
| 233 | 234 | ||
| 234 | dma_data = &mcbsp->dma_data[substream->stream]; | 235 | dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream); |
| 235 | channels = params_channels(params); | 236 | channels = params_channels(params); |
| 236 | 237 | ||
| 237 | switch (params_format(params)) { | 238 | switch (params_format(params)) { |
| 238 | case SNDRV_PCM_FORMAT_S16_LE: | 239 | case SNDRV_PCM_FORMAT_S16_LE: |
| 239 | dma_data->data_type = OMAP_DMA_DATA_TYPE_S16; | ||
| 240 | wlen = 16; | 240 | wlen = 16; |
| 241 | break; | 241 | break; |
| 242 | case SNDRV_PCM_FORMAT_S32_LE: | 242 | case SNDRV_PCM_FORMAT_S32_LE: |
| 243 | dma_data->data_type = OMAP_DMA_DATA_TYPE_S32; | ||
| 244 | wlen = 32; | 243 | wlen = 32; |
| 245 | break; | 244 | break; |
| 246 | default: | 245 | default: |
| @@ -250,6 +249,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
| 250 | dma_data->set_threshold = omap_mcbsp_set_threshold; | 249 | dma_data->set_threshold = omap_mcbsp_set_threshold; |
| 251 | if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { | 250 | if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { |
| 252 | int period_words, max_thrsh; | 251 | int period_words, max_thrsh; |
| 252 | int divider = 0; | ||
| 253 | 253 | ||
| 254 | period_words = params_period_bytes(params) / (wlen / 8); | 254 | period_words = params_period_bytes(params) / (wlen / 8); |
| 255 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 255 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
| @@ -257,46 +257,30 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
| 257 | else | 257 | else |
| 258 | max_thrsh = mcbsp->max_rx_thres; | 258 | max_thrsh = mcbsp->max_rx_thres; |
| 259 | /* | 259 | /* |
| 260 | * If the period contains less or equal number of words, | 260 | * Use sDMA packet mode if McBSP is in threshold mode: |
| 261 | * we are using the original threshold mode setup: | 261 | * If period words less than the FIFO size the packet |
| 262 | * McBSP threshold = sDMA frame size = period_size | 262 | * size is set to the number of period words, otherwise |
| 263 | * Otherwise we switch to sDMA packet mode: | 263 | * Look for the biggest threshold value which divides |
| 264 | * McBSP threshold = sDMA packet size | 264 | * the period size evenly. |
| 265 | * sDMA frame size = period size | ||
| 266 | */ | 265 | */ |
| 267 | if (period_words > max_thrsh) { | 266 | divider = period_words / max_thrsh; |
| 268 | int divider = 0; | 267 | if (period_words % max_thrsh) |
| 269 | 268 | divider++; | |
| 270 | /* | 269 | while (period_words % divider && |
| 271 | * Look for the biggest threshold value, which | 270 | divider < period_words) |
| 272 | * divides the period size evenly. | 271 | divider++; |
| 273 | */ | 272 | if (divider == period_words) |
| 274 | divider = period_words / max_thrsh; | 273 | return -EINVAL; |
| 275 | if (period_words % max_thrsh) | 274 | |
| 276 | divider++; | 275 | pkt_size = period_words / divider; |
| 277 | while (period_words % divider && | ||
| 278 | divider < period_words) | ||
| 279 | divider++; | ||
| 280 | if (divider == period_words) | ||
| 281 | return -EINVAL; | ||
| 282 | |||
| 283 | pkt_size = period_words / divider; | ||
| 284 | sync_mode = OMAP_DMA_SYNC_PACKET; | ||
| 285 | } else { | ||
| 286 | sync_mode = OMAP_DMA_SYNC_FRAME; | ||
| 287 | } | ||
| 288 | } else if (channels > 1) { | 276 | } else if (channels > 1) { |
| 289 | /* Use packet mode for non mono streams */ | 277 | /* Use packet mode for non mono streams */ |
| 290 | pkt_size = channels; | 278 | pkt_size = channels; |
| 291 | sync_mode = OMAP_DMA_SYNC_PACKET; | ||
| 292 | } | 279 | } |
| 293 | } | 280 | } |
| 294 | 281 | ||
| 295 | dma_data->sync_mode = sync_mode; | ||
| 296 | dma_data->packet_size = pkt_size; | 282 | dma_data->packet_size = pkt_size; |
| 297 | 283 | ||
| 298 | snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data); | ||
| 299 | |||
| 300 | if (mcbsp->configured) { | 284 | if (mcbsp->configured) { |
| 301 | /* McBSP already configured by another stream */ | 285 | /* McBSP already configured by another stream */ |
| 302 | return 0; | 286 | return 0; |
| @@ -399,12 +383,14 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
| 399 | /* Generic McBSP register settings */ | 383 | /* Generic McBSP register settings */ |
| 400 | regs->spcr2 |= XINTM(3) | FREE; | 384 | regs->spcr2 |= XINTM(3) | FREE; |
| 401 | regs->spcr1 |= RINTM(3); | 385 | regs->spcr1 |= RINTM(3); |
| 402 | /* RFIG and XFIG are not defined in 34xx */ | 386 | /* RFIG and XFIG are not defined in 2430 and on OMAP3+ */ |
| 403 | if (!cpu_is_omap34xx() && !cpu_is_omap44xx()) { | 387 | if (!mcbsp->pdata->has_ccr) { |
| 404 | regs->rcr2 |= RFIG; | 388 | regs->rcr2 |= RFIG; |
| 405 | regs->xcr2 |= XFIG; | 389 | regs->xcr2 |= XFIG; |
| 406 | } | 390 | } |
| 407 | if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { | 391 | |
| 392 | /* Configure XCCR/RCCR only for revisions which have ccr registers */ | ||
| 393 | if (mcbsp->pdata->has_ccr) { | ||
| 408 | regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE; | 394 | regs->xccr = DXENDLY(1) | XDMAEN | XDISABLE; |
| 409 | regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE; | 395 | regs->rccr = RFULL_CYCLE | RDMAEN | RDISABLE; |
| 410 | } | 396 | } |
| @@ -517,21 +503,9 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
| 517 | return -EBUSY; | 503 | return -EBUSY; |
| 518 | } | 504 | } |
| 519 | 505 | ||
| 520 | if (clk_id == OMAP_MCBSP_SYSCLK_CLK || | 506 | mcbsp->in_freq = freq; |
| 521 | clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK || | 507 | regs->srgr2 &= ~CLKSM; |
| 522 | clk_id == OMAP_MCBSP_SYSCLK_CLKS_EXT || | 508 | regs->pcr0 &= ~SCLKME; |
| 523 | clk_id == OMAP_MCBSP_SYSCLK_CLKX_EXT || | ||
| 524 | clk_id == OMAP_MCBSP_SYSCLK_CLKR_EXT) { | ||
| 525 | mcbsp->in_freq = freq; | ||
| 526 | regs->srgr2 &= ~CLKSM; | ||
| 527 | regs->pcr0 &= ~SCLKME; | ||
| 528 | } else if (cpu_class_is_omap1()) { | ||
| 529 | /* | ||
| 530 | * McBSP CLKR/FSR signal muxing functions are only available on | ||
| 531 | * OMAP2 or newer versions | ||
| 532 | */ | ||
| 533 | return -EINVAL; | ||
| 534 | } | ||
| 535 | 509 | ||
| 536 | switch (clk_id) { | 510 | switch (clk_id) { |
| 537 | case OMAP_MCBSP_SYSCLK_CLK: | 511 | case OMAP_MCBSP_SYSCLK_CLK: |
| @@ -559,20 +533,6 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
| 559 | case OMAP_MCBSP_SYSCLK_CLKR_EXT: | 533 | case OMAP_MCBSP_SYSCLK_CLKR_EXT: |
| 560 | regs->pcr0 |= SCLKME; | 534 | regs->pcr0 |= SCLKME; |
| 561 | break; | 535 | break; |
| 562 | |||
| 563 | |||
| 564 | case OMAP_MCBSP_CLKR_SRC_CLKR: | ||
| 565 | err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKR); | ||
| 566 | break; | ||
| 567 | case OMAP_MCBSP_CLKR_SRC_CLKX: | ||
| 568 | err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKX); | ||
| 569 | break; | ||
| 570 | case OMAP_MCBSP_FSR_SRC_FSR: | ||
| 571 | err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSR); | ||
| 572 | break; | ||
| 573 | case OMAP_MCBSP_FSR_SRC_FSX: | ||
| 574 | err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSX); | ||
| 575 | break; | ||
| 576 | default: | 536 | default: |
| 577 | err = -ENODEV; | 537 | err = -ENODEV; |
| 578 | } | 538 | } |
| @@ -642,9 +602,9 @@ static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol, | |||
| 642 | return 0; | 602 | return 0; |
| 643 | } | 603 | } |
| 644 | 604 | ||
| 645 | #define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(channel) \ | 605 | #define OMAP_MCBSP_ST_CHANNEL_VOLUME(channel) \ |
| 646 | static int \ | 606 | static int \ |
| 647 | omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ | 607 | omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ |
| 648 | struct snd_ctl_elem_value *uc) \ | 608 | struct snd_ctl_elem_value *uc) \ |
| 649 | { \ | 609 | { \ |
| 650 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ | 610 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ |
| @@ -660,11 +620,10 @@ omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \ | |||
| 660 | \ | 620 | \ |
| 661 | /* OMAP McBSP implementation uses index values 0..4 */ \ | 621 | /* OMAP McBSP implementation uses index values 0..4 */ \ |
| 662 | return omap_st_set_chgain(mcbsp, channel, val); \ | 622 | return omap_st_set_chgain(mcbsp, channel, val); \ |
| 663 | } | 623 | } \ |
| 664 | 624 | \ | |
| 665 | #define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(channel) \ | ||
| 666 | static int \ | 625 | static int \ |
| 667 | omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ | 626 | omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ |
| 668 | struct snd_ctl_elem_value *uc) \ | 627 | struct snd_ctl_elem_value *uc) \ |
| 669 | { \ | 628 | { \ |
| 670 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ | 629 | struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \ |
| @@ -678,10 +637,8 @@ omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \ | |||
| 678 | return 0; \ | 637 | return 0; \ |
| 679 | } | 638 | } |
| 680 | 639 | ||
| 681 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(0) | 640 | OMAP_MCBSP_ST_CHANNEL_VOLUME(0) |
| 682 | OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(1) | 641 | OMAP_MCBSP_ST_CHANNEL_VOLUME(1) |
| 683 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(0) | ||
| 684 | OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(1) | ||
| 685 | 642 | ||
| 686 | static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, | 643 | static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol, |
| 687 | struct snd_ctl_elem_value *ucontrol) | 644 | struct snd_ctl_elem_value *ucontrol) |
| @@ -711,41 +668,34 @@ static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol, | |||
| 711 | return 0; | 668 | return 0; |
| 712 | } | 669 | } |
| 713 | 670 | ||
| 714 | static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = { | 671 | #define OMAP_MCBSP_ST_CONTROLS(port) \ |
| 715 | SOC_SINGLE_EXT("McBSP2 Sidetone Switch", 1, 0, 1, 0, | 672 | static const struct snd_kcontrol_new omap_mcbsp##port##_st_controls[] = { \ |
| 716 | omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), | 673 | SOC_SINGLE_EXT("McBSP" #port " Sidetone Switch", 1, 0, 1, 0, \ |
| 717 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume", | 674 | omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), \ |
| 718 | -32768, 32767, | 675 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 0 Volume", \ |
| 719 | omap_mcbsp_get_st_ch0_volume, | 676 | -32768, 32767, \ |
| 720 | omap_mcbsp_set_st_ch0_volume), | 677 | omap_mcbsp_get_st_ch0_volume, \ |
| 721 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume", | 678 | omap_mcbsp_set_st_ch0_volume), \ |
| 722 | -32768, 32767, | 679 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 1 Volume", \ |
| 723 | omap_mcbsp_get_st_ch1_volume, | 680 | -32768, 32767, \ |
| 724 | omap_mcbsp_set_st_ch1_volume), | 681 | omap_mcbsp_get_st_ch1_volume, \ |
| 725 | }; | 682 | omap_mcbsp_set_st_ch1_volume), \ |
| 683 | } | ||
| 726 | 684 | ||
| 727 | static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = { | 685 | OMAP_MCBSP_ST_CONTROLS(2); |
| 728 | SOC_SINGLE_EXT("McBSP3 Sidetone Switch", 2, 0, 1, 0, | 686 | OMAP_MCBSP_ST_CONTROLS(3); |
| 729 | omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), | ||
| 730 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume", | ||
| 731 | -32768, 32767, | ||
| 732 | omap_mcbsp_get_st_ch0_volume, | ||
| 733 | omap_mcbsp_set_st_ch0_volume), | ||
| 734 | OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume", | ||
| 735 | -32768, 32767, | ||
| 736 | omap_mcbsp_get_st_ch1_volume, | ||
| 737 | omap_mcbsp_set_st_ch1_volume), | ||
| 738 | }; | ||
| 739 | 687 | ||
| 740 | int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) | 688 | int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) |
| 741 | { | 689 | { |
| 742 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | 690 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; |
| 743 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); | 691 | struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); |
| 744 | 692 | ||
| 745 | if (!mcbsp->st_data) | 693 | if (!mcbsp->st_data) { |
| 746 | return -ENODEV; | 694 | dev_warn(mcbsp->dev, "No sidetone data for port\n"); |
| 695 | return 0; | ||
| 696 | } | ||
| 747 | 697 | ||
| 748 | switch (cpu_dai->id) { | 698 | switch (mcbsp->id) { |
| 749 | case 2: /* McBSP 2 */ | 699 | case 2: /* McBSP 2 */ |
| 750 | return snd_soc_add_dai_controls(cpu_dai, | 700 | return snd_soc_add_dai_controls(cpu_dai, |
| 751 | omap_mcbsp2_st_controls, | 701 | omap_mcbsp2_st_controls, |
| @@ -762,13 +712,74 @@ int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd) | |||
| 762 | } | 712 | } |
| 763 | EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); | 713 | EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls); |
| 764 | 714 | ||
| 715 | static struct omap_mcbsp_platform_data omap2420_pdata = { | ||
| 716 | .reg_step = 4, | ||
| 717 | .reg_size = 2, | ||
| 718 | }; | ||
| 719 | |||
| 720 | static struct omap_mcbsp_platform_data omap2430_pdata = { | ||
| 721 | .reg_step = 4, | ||
| 722 | .reg_size = 4, | ||
| 723 | .has_ccr = true, | ||
| 724 | }; | ||
| 725 | |||
| 726 | static struct omap_mcbsp_platform_data omap3_pdata = { | ||
| 727 | .reg_step = 4, | ||
| 728 | .reg_size = 4, | ||
| 729 | .has_ccr = true, | ||
| 730 | .has_wakeup = true, | ||
| 731 | }; | ||
| 732 | |||
| 733 | static struct omap_mcbsp_platform_data omap4_pdata = { | ||
| 734 | .reg_step = 4, | ||
| 735 | .reg_size = 4, | ||
| 736 | .has_ccr = true, | ||
| 737 | .has_wakeup = true, | ||
| 738 | }; | ||
| 739 | |||
| 740 | static const struct of_device_id omap_mcbsp_of_match[] = { | ||
| 741 | { | ||
| 742 | .compatible = "ti,omap2420-mcbsp", | ||
| 743 | .data = &omap2420_pdata, | ||
| 744 | }, | ||
| 745 | { | ||
| 746 | .compatible = "ti,omap2430-mcbsp", | ||
| 747 | .data = &omap2430_pdata, | ||
| 748 | }, | ||
| 749 | { | ||
| 750 | .compatible = "ti,omap3-mcbsp", | ||
| 751 | .data = &omap3_pdata, | ||
| 752 | }, | ||
| 753 | { | ||
| 754 | .compatible = "ti,omap4-mcbsp", | ||
| 755 | .data = &omap4_pdata, | ||
| 756 | }, | ||
| 757 | { }, | ||
| 758 | }; | ||
| 759 | MODULE_DEVICE_TABLE(of, omap_mcbsp_of_match); | ||
| 760 | |||
| 765 | static __devinit int asoc_mcbsp_probe(struct platform_device *pdev) | 761 | static __devinit int asoc_mcbsp_probe(struct platform_device *pdev) |
| 766 | { | 762 | { |
| 767 | struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev); | 763 | struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev); |
| 768 | struct omap_mcbsp *mcbsp; | 764 | struct omap_mcbsp *mcbsp; |
| 765 | const struct of_device_id *match; | ||
| 769 | int ret; | 766 | int ret; |
| 770 | 767 | ||
| 771 | if (!pdata) { | 768 | match = of_match_device(omap_mcbsp_of_match, &pdev->dev); |
| 769 | if (match) { | ||
| 770 | struct device_node *node = pdev->dev.of_node; | ||
| 771 | int buffer_size; | ||
| 772 | |||
| 773 | pdata = devm_kzalloc(&pdev->dev, | ||
| 774 | sizeof(struct omap_mcbsp_platform_data), | ||
| 775 | GFP_KERNEL); | ||
| 776 | if (!pdata) | ||
| 777 | return -ENOMEM; | ||
| 778 | |||
| 779 | memcpy(pdata, match->data, sizeof(*pdata)); | ||
| 780 | if (!of_property_read_u32(node, "ti,buffer-size", &buffer_size)) | ||
| 781 | pdata->buffer_size = buffer_size; | ||
| 782 | } else if (!pdata) { | ||
| 772 | dev_err(&pdev->dev, "missing platform data.\n"); | 783 | dev_err(&pdev->dev, "missing platform data.\n"); |
| 773 | return -EINVAL; | 784 | return -EINVAL; |
| 774 | } | 785 | } |
| @@ -810,6 +821,7 @@ static struct platform_driver asoc_mcbsp_driver = { | |||
| 810 | .driver = { | 821 | .driver = { |
| 811 | .name = "omap-mcbsp", | 822 | .name = "omap-mcbsp", |
| 812 | .owner = THIS_MODULE, | 823 | .owner = THIS_MODULE, |
| 824 | .of_match_table = omap_mcbsp_of_match, | ||
| 813 | }, | 825 | }, |
| 814 | 826 | ||
| 815 | .probe = asoc_mcbsp_probe, | 827 | .probe = asoc_mcbsp_probe, |
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h index f877b16f19c9..ba8386a0d8dc 100644 --- a/sound/soc/omap/omap-mcbsp.h +++ b/sound/soc/omap/omap-mcbsp.h | |||
| @@ -32,10 +32,6 @@ enum omap_mcbsp_clksrg_clk { | |||
| 32 | OMAP_MCBSP_SYSCLK_CLK, /* Internal ICLK */ | 32 | OMAP_MCBSP_SYSCLK_CLK, /* Internal ICLK */ |
| 33 | OMAP_MCBSP_SYSCLK_CLKX_EXT, /* External CLKX pin */ | 33 | OMAP_MCBSP_SYSCLK_CLKX_EXT, /* External CLKX pin */ |
| 34 | OMAP_MCBSP_SYSCLK_CLKR_EXT, /* External CLKR pin */ | 34 | OMAP_MCBSP_SYSCLK_CLKR_EXT, /* External CLKR pin */ |
| 35 | OMAP_MCBSP_CLKR_SRC_CLKR, /* CLKR from CLKR pin */ | ||
| 36 | OMAP_MCBSP_CLKR_SRC_CLKX, /* CLKR from CLKX pin */ | ||
| 37 | OMAP_MCBSP_FSR_SRC_FSR, /* FSR from FSR pin */ | ||
| 38 | OMAP_MCBSP_FSR_SRC_FSX, /* FSR from FSX pin */ | ||
| 39 | }; | 35 | }; |
| 40 | 36 | ||
| 41 | /* McBSP dividers */ | 37 | /* McBSP dividers */ |
| @@ -43,22 +39,6 @@ enum omap_mcbsp_div { | |||
| 43 | OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */ | 39 | OMAP_MCBSP_CLKGDV, /* Sample rate generator divider */ |
| 44 | }; | 40 | }; |
| 45 | 41 | ||
| 46 | #if defined(CONFIG_SOC_OMAP2420) | ||
| 47 | #define NUM_LINKS 2 | ||
| 48 | #endif | ||
| 49 | #if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) | ||
| 50 | #undef NUM_LINKS | ||
| 51 | #define NUM_LINKS 3 | ||
| 52 | #endif | ||
| 53 | #if defined(CONFIG_ARCH_OMAP4) | ||
| 54 | #undef NUM_LINKS | ||
| 55 | #define NUM_LINKS 4 | ||
| 56 | #endif | ||
| 57 | #if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_OMAP2430) | ||
| 58 | #undef NUM_LINKS | ||
| 59 | #define NUM_LINKS 5 | ||
| 60 | #endif | ||
| 61 | |||
| 62 | int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd); | 42 | int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd); |
| 63 | 43 | ||
| 64 | #endif | 44 | #endif |
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index ea053c3d2ab1..c02b001ee4b5 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c | |||
| @@ -40,7 +40,6 @@ | |||
| 40 | #include <sound/pcm_params.h> | 40 | #include <sound/pcm_params.h> |
| 41 | #include <sound/soc.h> | 41 | #include <sound/soc.h> |
| 42 | 42 | ||
| 43 | #include <plat/dma.h> | ||
| 44 | #include <plat/omap_hwmod.h> | 43 | #include <plat/omap_hwmod.h> |
| 45 | #include "omap-mcpdm.h" | 44 | #include "omap-mcpdm.h" |
| 46 | #include "omap-pcm.h" | 45 | #include "omap-pcm.h" |
| @@ -73,17 +72,9 @@ struct omap_mcpdm { | |||
| 73 | static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { | 72 | static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = { |
| 74 | { | 73 | { |
| 75 | .name = "Audio playback", | 74 | .name = "Audio playback", |
| 76 | .dma_req = OMAP44XX_DMA_MCPDM_DL, | ||
| 77 | .data_type = OMAP_DMA_DATA_TYPE_S32, | ||
| 78 | .sync_mode = OMAP_DMA_SYNC_PACKET, | ||
| 79 | .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_DN_DATA, | ||
| 80 | }, | 75 | }, |
| 81 | { | 76 | { |
| 82 | .name = "Audio capture", | 77 | .name = "Audio capture", |
| 83 | .dma_req = OMAP44XX_DMA_MCPDM_UP, | ||
| 84 | .data_type = OMAP_DMA_DATA_TYPE_S32, | ||
| 85 | .sync_mode = OMAP_DMA_SYNC_PACKET, | ||
| 86 | .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_UP_DATA, | ||
| 87 | }, | 78 | }, |
| 88 | }; | 79 | }; |
| 89 | 80 | ||
| @@ -278,9 +269,11 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream, | |||
| 278 | } | 269 | } |
| 279 | omap_mcpdm_open_streams(mcpdm); | 270 | omap_mcpdm_open_streams(mcpdm); |
| 280 | } | 271 | } |
| 281 | |||
| 282 | mutex_unlock(&mcpdm->mutex); | 272 | mutex_unlock(&mcpdm->mutex); |
| 283 | 273 | ||
| 274 | snd_soc_dai_set_dma_data(dai, substream, | ||
| 275 | &omap_mcpdm_dai_dma_params[substream->stream]); | ||
| 276 | |||
| 284 | return 0; | 277 | return 0; |
| 285 | } | 278 | } |
| 286 | 279 | ||
| @@ -335,7 +328,7 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, | |||
| 335 | return -EINVAL; | 328 | return -EINVAL; |
| 336 | } | 329 | } |
| 337 | 330 | ||
| 338 | dma_data = &omap_mcpdm_dai_dma_params[stream]; | 331 | dma_data = snd_soc_dai_get_dma_data(dai, substream); |
| 339 | 332 | ||
| 340 | /* Configure McPDM channels, and DMA packet size */ | 333 | /* Configure McPDM channels, and DMA packet size */ |
| 341 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { | 334 | if (stream == SNDRV_PCM_STREAM_PLAYBACK) { |
| @@ -347,8 +340,6 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream, | |||
| 347 | dma_data->packet_size = mcpdm->up_threshold * channels; | 340 | dma_data->packet_size = mcpdm->up_threshold * channels; |
| 348 | } | 341 | } |
| 349 | 342 | ||
| 350 | snd_soc_dai_set_dma_data(dai, substream, dma_data); | ||
| 351 | |||
| 352 | return 0; | 343 | return 0; |
| 353 | } | 344 | } |
| 354 | 345 | ||
| @@ -447,9 +438,8 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) | |||
| 447 | { | 438 | { |
| 448 | struct omap_mcpdm *mcpdm; | 439 | struct omap_mcpdm *mcpdm; |
| 449 | struct resource *res; | 440 | struct resource *res; |
| 450 | int ret = 0; | ||
| 451 | 441 | ||
| 452 | mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL); | 442 | mcpdm = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcpdm), GFP_KERNEL); |
| 453 | if (!mcpdm) | 443 | if (!mcpdm) |
| 454 | return -ENOMEM; | 444 | return -ENOMEM; |
| 455 | 445 | ||
| @@ -457,56 +447,54 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) | |||
| 457 | 447 | ||
| 458 | mutex_init(&mcpdm->mutex); | 448 | mutex_init(&mcpdm->mutex); |
| 459 | 449 | ||
| 450 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma"); | ||
| 451 | if (res == NULL) | ||
| 452 | return -ENOMEM; | ||
| 453 | |||
| 454 | omap_mcpdm_dai_dma_params[0].port_addr = res->start + MCPDM_REG_DN_DATA; | ||
| 455 | omap_mcpdm_dai_dma_params[1].port_addr = res->start + MCPDM_REG_UP_DATA; | ||
| 456 | |||
| 460 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 457 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 461 | if (res == NULL) { | 458 | if (res == NULL) |
| 462 | dev_err(&pdev->dev, "no resource\n"); | 459 | return -ENOMEM; |
| 463 | goto err_res; | ||
| 464 | } | ||
| 465 | 460 | ||
| 466 | if (!request_mem_region(res->start, resource_size(res), "McPDM")) { | 461 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "dn_link"); |
| 467 | ret = -EBUSY; | 462 | if (!res) |
| 468 | goto err_res; | 463 | return -ENODEV; |
| 469 | } | ||
| 470 | 464 | ||
| 471 | mcpdm->io_base = ioremap(res->start, resource_size(res)); | 465 | omap_mcpdm_dai_dma_params[0].dma_req = res->start; |
| 472 | if (!mcpdm->io_base) { | 466 | |
| 473 | ret = -ENOMEM; | 467 | res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "up_link"); |
| 474 | goto err_iomap; | 468 | if (!res) |
| 475 | } | 469 | return -ENODEV; |
| 470 | |||
| 471 | omap_mcpdm_dai_dma_params[1].dma_req = res->start; | ||
| 472 | |||
| 473 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); | ||
| 474 | if (res == NULL) | ||
| 475 | return -ENOMEM; | ||
| 476 | |||
| 477 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
| 478 | resource_size(res), "McPDM")) | ||
| 479 | return -EBUSY; | ||
| 480 | |||
| 481 | mcpdm->io_base = devm_ioremap(&pdev->dev, res->start, | ||
| 482 | resource_size(res)); | ||
| 483 | if (!mcpdm->io_base) | ||
| 484 | return -ENOMEM; | ||
| 476 | 485 | ||
| 477 | mcpdm->irq = platform_get_irq(pdev, 0); | 486 | mcpdm->irq = platform_get_irq(pdev, 0); |
| 478 | if (mcpdm->irq < 0) { | 487 | if (mcpdm->irq < 0) |
| 479 | ret = mcpdm->irq; | 488 | return mcpdm->irq; |
| 480 | goto err_irq; | ||
| 481 | } | ||
| 482 | 489 | ||
| 483 | mcpdm->dev = &pdev->dev; | 490 | mcpdm->dev = &pdev->dev; |
| 484 | 491 | ||
| 485 | ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); | 492 | return snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); |
| 486 | if (!ret) | ||
| 487 | return 0; | ||
| 488 | |||
| 489 | err_irq: | ||
| 490 | iounmap(mcpdm->io_base); | ||
| 491 | err_iomap: | ||
| 492 | release_mem_region(res->start, resource_size(res)); | ||
| 493 | err_res: | ||
| 494 | kfree(mcpdm); | ||
| 495 | return ret; | ||
| 496 | } | 493 | } |
| 497 | 494 | ||
| 498 | static int __devexit asoc_mcpdm_remove(struct platform_device *pdev) | 495 | static int __devexit asoc_mcpdm_remove(struct platform_device *pdev) |
| 499 | { | 496 | { |
| 500 | struct omap_mcpdm *mcpdm = platform_get_drvdata(pdev); | ||
| 501 | struct resource *res; | ||
| 502 | |||
| 503 | snd_soc_unregister_dai(&pdev->dev); | 497 | snd_soc_unregister_dai(&pdev->dev); |
| 504 | |||
| 505 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 506 | iounmap(mcpdm->io_base); | ||
| 507 | release_mem_region(res->start, resource_size(res)); | ||
| 508 | |||
| 509 | kfree(mcpdm); | ||
| 510 | return 0; | 498 | return 0; |
| 511 | } | 499 | } |
| 512 | 500 | ||
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index b30994179885..340874ebf9ae 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c | |||
| @@ -25,13 +25,14 @@ | |||
| 25 | #include <linux/dma-mapping.h> | 25 | #include <linux/dma-mapping.h> |
| 26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| 27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
| 28 | #include <linux/omap-dma.h> | ||
| 28 | #include <sound/core.h> | 29 | #include <sound/core.h> |
| 29 | #include <sound/pcm.h> | 30 | #include <sound/pcm.h> |
| 30 | #include <sound/pcm_params.h> | 31 | #include <sound/pcm_params.h> |
| 32 | #include <sound/dmaengine_pcm.h> | ||
| 31 | #include <sound/soc.h> | 33 | #include <sound/soc.h> |
| 32 | 34 | ||
| 33 | #include <plat/cpu.h> | 35 | #include <plat/cpu.h> |
| 34 | #include <plat/dma.h> | ||
| 35 | #include "omap-pcm.h" | 36 | #include "omap-pcm.h" |
| 36 | 37 | ||
| 37 | static const struct snd_pcm_hardware omap_pcm_hardware = { | 38 | static const struct snd_pcm_hardware omap_pcm_hardware = { |
| @@ -50,61 +51,34 @@ static const struct snd_pcm_hardware omap_pcm_hardware = { | |||
| 50 | .buffer_bytes_max = 128 * 1024, | 51 | .buffer_bytes_max = 128 * 1024, |
| 51 | }; | 52 | }; |
| 52 | 53 | ||
| 53 | struct omap_runtime_data { | 54 | static int omap_pcm_get_dma_buswidth(int num_bits) |
| 54 | spinlock_t lock; | ||
| 55 | struct omap_pcm_dma_data *dma_data; | ||
| 56 | int dma_ch; | ||
| 57 | int period_index; | ||
| 58 | }; | ||
| 59 | |||
| 60 | static void omap_pcm_dma_irq(int ch, u16 stat, void *data) | ||
| 61 | { | 55 | { |
| 62 | struct snd_pcm_substream *substream = data; | 56 | int buswidth; |
| 63 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 64 | struct omap_runtime_data *prtd = runtime->private_data; | ||
| 65 | unsigned long flags; | ||
| 66 | |||
| 67 | if ((cpu_is_omap1510())) { | ||
| 68 | /* | ||
| 69 | * OMAP1510 doesn't fully support DMA progress counter | ||
| 70 | * and there is no software emulation implemented yet, | ||
| 71 | * so have to maintain our own progress counters | ||
| 72 | * that can be used by omap_pcm_pointer() instead. | ||
| 73 | */ | ||
| 74 | spin_lock_irqsave(&prtd->lock, flags); | ||
| 75 | if ((stat == OMAP_DMA_LAST_IRQ) && | ||
| 76 | (prtd->period_index == runtime->periods - 1)) { | ||
| 77 | /* we are in sync, do nothing */ | ||
| 78 | spin_unlock_irqrestore(&prtd->lock, flags); | ||
| 79 | return; | ||
| 80 | } | ||
| 81 | if (prtd->period_index >= 0) { | ||
| 82 | if (stat & OMAP_DMA_BLOCK_IRQ) { | ||
| 83 | /* end of buffer reached, loop back */ | ||
| 84 | prtd->period_index = 0; | ||
| 85 | } else if (stat & OMAP_DMA_LAST_IRQ) { | ||
| 86 | /* update the counter for the last period */ | ||
| 87 | prtd->period_index = runtime->periods - 1; | ||
| 88 | } else if (++prtd->period_index >= runtime->periods) { | ||
| 89 | /* end of buffer missed? loop back */ | ||
| 90 | prtd->period_index = 0; | ||
| 91 | } | ||
| 92 | } | ||
| 93 | spin_unlock_irqrestore(&prtd->lock, flags); | ||
| 94 | } | ||
| 95 | 57 | ||
| 96 | snd_pcm_period_elapsed(substream); | 58 | switch (num_bits) { |
| 59 | case 16: | ||
| 60 | buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES; | ||
| 61 | break; | ||
| 62 | case 32: | ||
| 63 | buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES; | ||
| 64 | break; | ||
| 65 | default: | ||
| 66 | buswidth = -EINVAL; | ||
| 67 | break; | ||
| 68 | } | ||
| 69 | return buswidth; | ||
| 97 | } | 70 | } |
| 98 | 71 | ||
| 72 | |||
| 99 | /* this may get called several times by oss emulation */ | 73 | /* this may get called several times by oss emulation */ |
| 100 | static int omap_pcm_hw_params(struct snd_pcm_substream *substream, | 74 | static int omap_pcm_hw_params(struct snd_pcm_substream *substream, |
| 101 | struct snd_pcm_hw_params *params) | 75 | struct snd_pcm_hw_params *params) |
| 102 | { | 76 | { |
| 103 | struct snd_pcm_runtime *runtime = substream->runtime; | 77 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 104 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 78 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 105 | struct omap_runtime_data *prtd = runtime->private_data; | ||
| 106 | struct omap_pcm_dma_data *dma_data; | 79 | struct omap_pcm_dma_data *dma_data; |
| 107 | 80 | struct dma_slave_config config; | |
| 81 | struct dma_chan *chan; | ||
| 108 | int err = 0; | 82 | int err = 0; |
| 109 | 83 | ||
| 110 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); | 84 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
| @@ -117,162 +91,78 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, | |||
| 117 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | 91 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); |
| 118 | runtime->dma_bytes = params_buffer_bytes(params); | 92 | runtime->dma_bytes = params_buffer_bytes(params); |
| 119 | 93 | ||
| 120 | if (prtd->dma_data) | 94 | chan = snd_dmaengine_pcm_get_chan(substream); |
| 121 | return 0; | 95 | if (!chan) |
| 122 | prtd->dma_data = dma_data; | 96 | return -EINVAL; |
| 123 | err = omap_request_dma(dma_data->dma_req, dma_data->name, | ||
| 124 | omap_pcm_dma_irq, substream, &prtd->dma_ch); | ||
| 125 | if (!err) { | ||
| 126 | /* | ||
| 127 | * Link channel with itself so DMA doesn't need any | ||
| 128 | * reprogramming while looping the buffer | ||
| 129 | */ | ||
| 130 | omap_dma_link_lch(prtd->dma_ch, prtd->dma_ch); | ||
| 131 | } | ||
| 132 | 97 | ||
| 133 | return err; | 98 | /* fills in addr_width and direction */ |
| 134 | } | 99 | err = snd_hwparams_to_dma_slave_config(substream, params, &config); |
| 100 | if (err) | ||
| 101 | return err; | ||
| 135 | 102 | ||
| 136 | static int omap_pcm_hw_free(struct snd_pcm_substream *substream) | 103 | /* Override the *_dma addr_width if requested by the DAI driver */ |
| 137 | { | 104 | if (dma_data->data_type) { |
| 138 | struct snd_pcm_runtime *runtime = substream->runtime; | 105 | int buswidth = omap_pcm_get_dma_buswidth(dma_data->data_type); |
| 139 | struct omap_runtime_data *prtd = runtime->private_data; | ||
| 140 | 106 | ||
| 141 | if (prtd->dma_data == NULL) | 107 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
| 142 | return 0; | 108 | config.dst_addr_width = buswidth; |
| 143 | 109 | else | |
| 144 | omap_dma_unlink_lch(prtd->dma_ch, prtd->dma_ch); | 110 | config.src_addr_width = buswidth; |
| 145 | omap_free_dma(prtd->dma_ch); | 111 | } |
| 146 | prtd->dma_data = NULL; | ||
| 147 | 112 | ||
| 148 | snd_pcm_set_runtime_buffer(substream, NULL); | 113 | config.src_addr = dma_data->port_addr; |
| 114 | config.dst_addr = dma_data->port_addr; | ||
| 115 | config.src_maxburst = dma_data->packet_size; | ||
| 116 | config.dst_maxburst = dma_data->packet_size; | ||
| 149 | 117 | ||
| 150 | return 0; | 118 | return dmaengine_slave_config(chan, &config); |
| 151 | } | 119 | } |
| 152 | 120 | ||
| 153 | static int omap_pcm_prepare(struct snd_pcm_substream *substream) | 121 | static int omap_pcm_hw_free(struct snd_pcm_substream *substream) |
| 154 | { | 122 | { |
| 155 | struct snd_pcm_runtime *runtime = substream->runtime; | 123 | snd_pcm_set_runtime_buffer(substream, NULL); |
| 156 | struct omap_runtime_data *prtd = runtime->private_data; | ||
| 157 | struct omap_pcm_dma_data *dma_data = prtd->dma_data; | ||
| 158 | struct omap_dma_channel_params dma_params; | ||
| 159 | int bytes; | ||
| 160 | |||
| 161 | /* return if this is a bufferless transfer e.g. | ||
| 162 | * codec <--> BT codec or GSM modem -- lg FIXME */ | ||
| 163 | if (!prtd->dma_data) | ||
| 164 | return 0; | ||
| 165 | |||
| 166 | memset(&dma_params, 0, sizeof(dma_params)); | ||
| 167 | dma_params.data_type = dma_data->data_type; | ||
| 168 | dma_params.trigger = dma_data->dma_req; | ||
| 169 | dma_params.sync_mode = dma_data->sync_mode; | ||
| 170 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
| 171 | dma_params.src_amode = OMAP_DMA_AMODE_POST_INC; | ||
| 172 | dma_params.dst_amode = OMAP_DMA_AMODE_CONSTANT; | ||
| 173 | dma_params.src_or_dst_synch = OMAP_DMA_DST_SYNC; | ||
| 174 | dma_params.src_start = runtime->dma_addr; | ||
| 175 | dma_params.dst_start = dma_data->port_addr; | ||
| 176 | dma_params.dst_port = OMAP_DMA_PORT_MPUI; | ||
| 177 | dma_params.dst_fi = dma_data->packet_size; | ||
| 178 | } else { | ||
| 179 | dma_params.src_amode = OMAP_DMA_AMODE_CONSTANT; | ||
| 180 | dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC; | ||
| 181 | dma_params.src_or_dst_synch = OMAP_DMA_SRC_SYNC; | ||
| 182 | dma_params.src_start = dma_data->port_addr; | ||
| 183 | dma_params.dst_start = runtime->dma_addr; | ||
| 184 | dma_params.src_port = OMAP_DMA_PORT_MPUI; | ||
| 185 | dma_params.src_fi = dma_data->packet_size; | ||
| 186 | } | ||
| 187 | /* | ||
| 188 | * Set DMA transfer frame size equal to ALSA period size and frame | ||
| 189 | * count as no. of ALSA periods. Then with DMA frame interrupt enabled, | ||
| 190 | * we can transfer the whole ALSA buffer with single DMA transfer but | ||
| 191 | * still can get an interrupt at each period bounary | ||
| 192 | */ | ||
| 193 | bytes = snd_pcm_lib_period_bytes(substream); | ||
| 194 | dma_params.elem_count = bytes >> dma_data->data_type; | ||
| 195 | dma_params.frame_count = runtime->periods; | ||
| 196 | omap_set_dma_params(prtd->dma_ch, &dma_params); | ||
| 197 | |||
| 198 | if ((cpu_is_omap1510())) | ||
| 199 | omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ | | ||
| 200 | OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ); | ||
| 201 | else if (!substream->runtime->no_period_wakeup) | ||
| 202 | omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ); | ||
| 203 | else { | ||
| 204 | /* | ||
| 205 | * No period wakeup: | ||
| 206 | * we need to disable BLOCK_IRQ, which is enabled by the omap | ||
| 207 | * dma core at request dma time. | ||
| 208 | */ | ||
| 209 | omap_disable_dma_irq(prtd->dma_ch, OMAP_DMA_BLOCK_IRQ); | ||
| 210 | } | ||
| 211 | |||
| 212 | if (!(cpu_class_is_omap1())) { | ||
| 213 | omap_set_dma_src_burst_mode(prtd->dma_ch, | ||
| 214 | OMAP_DMA_DATA_BURST_16); | ||
| 215 | omap_set_dma_dest_burst_mode(prtd->dma_ch, | ||
| 216 | OMAP_DMA_DATA_BURST_16); | ||
| 217 | } | ||
| 218 | |||
| 219 | return 0; | 124 | return 0; |
| 220 | } | 125 | } |
| 221 | 126 | ||
| 222 | static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | 127 | static int omap_pcm_trigger(struct snd_pcm_substream *substream, int cmd) |
| 223 | { | 128 | { |
| 224 | struct snd_pcm_runtime *runtime = substream->runtime; | 129 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 225 | struct omap_runtime_data *prtd = runtime->private_data; | 130 | struct omap_pcm_dma_data *dma_data; |
| 226 | struct omap_pcm_dma_data *dma_data = prtd->dma_data; | ||
| 227 | unsigned long flags; | ||
| 228 | int ret = 0; | 131 | int ret = 0; |
| 229 | 132 | ||
| 230 | spin_lock_irqsave(&prtd->lock, flags); | 133 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
| 134 | |||
| 231 | switch (cmd) { | 135 | switch (cmd) { |
| 232 | case SNDRV_PCM_TRIGGER_START: | 136 | case SNDRV_PCM_TRIGGER_START: |
| 233 | case SNDRV_PCM_TRIGGER_RESUME: | 137 | case SNDRV_PCM_TRIGGER_RESUME: |
| 234 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 138 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
| 235 | prtd->period_index = 0; | ||
| 236 | /* Configure McBSP internal buffer usage */ | 139 | /* Configure McBSP internal buffer usage */ |
| 237 | if (dma_data->set_threshold) | 140 | if (dma_data->set_threshold) |
| 238 | dma_data->set_threshold(substream); | 141 | dma_data->set_threshold(substream); |
| 239 | |||
| 240 | omap_start_dma(prtd->dma_ch); | ||
| 241 | break; | 142 | break; |
| 242 | 143 | ||
| 243 | case SNDRV_PCM_TRIGGER_STOP: | 144 | case SNDRV_PCM_TRIGGER_STOP: |
| 244 | case SNDRV_PCM_TRIGGER_SUSPEND: | 145 | case SNDRV_PCM_TRIGGER_SUSPEND: |
| 245 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 146 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
| 246 | prtd->period_index = -1; | ||
| 247 | omap_stop_dma(prtd->dma_ch); | ||
| 248 | break; | 147 | break; |
| 249 | default: | 148 | default: |
| 250 | ret = -EINVAL; | 149 | ret = -EINVAL; |
| 251 | } | 150 | } |
| 252 | spin_unlock_irqrestore(&prtd->lock, flags); | 151 | |
| 152 | if (ret == 0) | ||
| 153 | ret = snd_dmaengine_pcm_trigger(substream, cmd); | ||
| 253 | 154 | ||
| 254 | return ret; | 155 | return ret; |
| 255 | } | 156 | } |
| 256 | 157 | ||
| 257 | static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) | 158 | static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) |
| 258 | { | 159 | { |
| 259 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
| 260 | struct omap_runtime_data *prtd = runtime->private_data; | ||
| 261 | dma_addr_t ptr; | ||
| 262 | snd_pcm_uframes_t offset; | 160 | snd_pcm_uframes_t offset; |
| 263 | 161 | ||
| 264 | if (cpu_is_omap1510()) { | 162 | if (cpu_is_omap1510()) |
| 265 | offset = prtd->period_index * runtime->period_size; | 163 | offset = snd_dmaengine_pcm_pointer_no_residue(substream); |
| 266 | } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | 164 | else |
| 267 | ptr = omap_get_dma_dst_pos(prtd->dma_ch); | 165 | offset = snd_dmaengine_pcm_pointer(substream); |
| 268 | offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); | ||
| 269 | } else { | ||
| 270 | ptr = omap_get_dma_src_pos(prtd->dma_ch); | ||
| 271 | offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); | ||
| 272 | } | ||
| 273 | |||
| 274 | if (offset >= runtime->buffer_size) | ||
| 275 | offset = 0; | ||
| 276 | 166 | ||
| 277 | return offset; | 167 | return offset; |
| 278 | } | 168 | } |
| @@ -280,7 +170,8 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) | |||
| 280 | static int omap_pcm_open(struct snd_pcm_substream *substream) | 170 | static int omap_pcm_open(struct snd_pcm_substream *substream) |
| 281 | { | 171 | { |
| 282 | struct snd_pcm_runtime *runtime = substream->runtime; | 172 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 283 | struct omap_runtime_data *prtd; | 173 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 174 | struct omap_pcm_dma_data *dma_data; | ||
| 284 | int ret; | 175 | int ret; |
| 285 | 176 | ||
| 286 | snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware); | 177 | snd_soc_set_runtime_hwparams(substream, &omap_pcm_hardware); |
| @@ -289,25 +180,17 @@ static int omap_pcm_open(struct snd_pcm_substream *substream) | |||
| 289 | ret = snd_pcm_hw_constraint_integer(runtime, | 180 | ret = snd_pcm_hw_constraint_integer(runtime, |
| 290 | SNDRV_PCM_HW_PARAM_PERIODS); | 181 | SNDRV_PCM_HW_PARAM_PERIODS); |
| 291 | if (ret < 0) | 182 | if (ret < 0) |
| 292 | goto out; | 183 | return ret; |
| 293 | 184 | ||
| 294 | prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); | 185 | dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream); |
| 295 | if (prtd == NULL) { | 186 | ret = snd_dmaengine_pcm_open(substream, omap_dma_filter_fn, |
| 296 | ret = -ENOMEM; | 187 | &dma_data->dma_req); |
| 297 | goto out; | ||
| 298 | } | ||
| 299 | spin_lock_init(&prtd->lock); | ||
| 300 | runtime->private_data = prtd; | ||
| 301 | |||
| 302 | out: | ||
| 303 | return ret; | 188 | return ret; |
| 304 | } | 189 | } |
| 305 | 190 | ||
| 306 | static int omap_pcm_close(struct snd_pcm_substream *substream) | 191 | static int omap_pcm_close(struct snd_pcm_substream *substream) |
| 307 | { | 192 | { |
| 308 | struct snd_pcm_runtime *runtime = substream->runtime; | 193 | snd_dmaengine_pcm_close(substream); |
| 309 | |||
| 310 | kfree(runtime->private_data); | ||
| 311 | return 0; | 194 | return 0; |
| 312 | } | 195 | } |
| 313 | 196 | ||
| @@ -328,7 +211,6 @@ static struct snd_pcm_ops omap_pcm_ops = { | |||
| 328 | .ioctl = snd_pcm_lib_ioctl, | 211 | .ioctl = snd_pcm_lib_ioctl, |
| 329 | .hw_params = omap_pcm_hw_params, | 212 | .hw_params = omap_pcm_hw_params, |
| 330 | .hw_free = omap_pcm_hw_free, | 213 | .hw_free = omap_pcm_hw_free, |
| 331 | .prepare = omap_pcm_prepare, | ||
| 332 | .trigger = omap_pcm_trigger, | 214 | .trigger = omap_pcm_trigger, |
| 333 | .pointer = omap_pcm_pointer, | 215 | .pointer = omap_pcm_pointer, |
| 334 | .mmap = omap_pcm_mmap, | 216 | .mmap = omap_pcm_mmap, |
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h index b92248cbd47a..cabe74c4068b 100644 --- a/sound/soc/omap/omap-pcm.h +++ b/sound/soc/omap/omap-pcm.h | |||
| @@ -32,8 +32,8 @@ struct omap_pcm_dma_data { | |||
| 32 | int dma_req; /* DMA request line */ | 32 | int dma_req; /* DMA request line */ |
| 33 | unsigned long port_addr; /* transmit/receive register */ | 33 | unsigned long port_addr; /* transmit/receive register */ |
| 34 | void (*set_threshold)(struct snd_pcm_substream *substream); | 34 | void (*set_threshold)(struct snd_pcm_substream *substream); |
| 35 | int data_type; /* data type 8,16,32 */ | 35 | int data_type; /* 8, 16, 32 (bits) or 0 to let omap-pcm |
| 36 | int sync_mode; /* DMA sync mode */ | 36 | * to decide the sDMA data type */ |
| 37 | int packet_size; /* packet size only in PACKET mode */ | 37 | int packet_size; /* packet size only in PACKET mode */ |
| 38 | }; | 38 | }; |
| 39 | 39 | ||
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c new file mode 100644 index 000000000000..3b97b87971f5 --- /dev/null +++ b/sound/soc/omap/omap-twl4030.c | |||
| @@ -0,0 +1,188 @@ | |||
| 1 | /* | ||
| 2 | * omap-twl4030.c -- SoC audio for TI SoC based boards with twl4030 codec | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com | ||
| 5 | * All rights reserved. | ||
| 6 | * | ||
| 7 | * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> | ||
| 8 | * | ||
| 9 | * This driver replaces the following machine drivers: | ||
| 10 | * omap3beagle (Author: Steve Sakoman <steve@sakoman.com>) | ||
| 11 | * omap3evm (Author: Anuj Aggarwal <anuj.aggarwal@ti.com>) | ||
| 12 | * overo (Author: Steve Sakoman <steve@sakoman.com>) | ||
| 13 | * igep0020 (Author: Enric Balletbo i Serra <eballetbo@iseebcn.com>) | ||
| 14 | * | ||
| 15 | * This program is free software; you can redistribute it and/or | ||
| 16 | * modify it under the terms of the GNU General Public License | ||
| 17 | * version 2 as published by the Free Software Foundation. | ||
| 18 | * | ||
| 19 | * This program is distributed in the hope that it will be useful, but | ||
| 20 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 21 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 22 | * General Public License for more details. | ||
| 23 | * | ||
| 24 | * You should have received a copy of the GNU General Public License | ||
| 25 | * along with this program; if not, write to the Free Software | ||
| 26 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
| 27 | * 02110-1301 USA | ||
| 28 | * | ||
| 29 | */ | ||
| 30 | |||
| 31 | #include <linux/platform_device.h> | ||
| 32 | #include <linux/platform_data/omap-twl4030.h> | ||
| 33 | #include <linux/module.h> | ||
| 34 | #include <linux/of.h> | ||
| 35 | |||
| 36 | #include <sound/core.h> | ||
| 37 | #include <sound/pcm.h> | ||
| 38 | #include <sound/soc.h> | ||
| 39 | |||
| 40 | #include "omap-mcbsp.h" | ||
| 41 | #include "omap-pcm.h" | ||
| 42 | |||
| 43 | static int omap_twl4030_hw_params(struct snd_pcm_substream *substream, | ||
| 44 | struct snd_pcm_hw_params *params) | ||
| 45 | { | ||
| 46 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 47 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
| 48 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
| 49 | struct snd_soc_codec *codec = rtd->codec; | ||
| 50 | struct snd_soc_card *card = codec->card; | ||
| 51 | unsigned int fmt; | ||
| 52 | int ret; | ||
| 53 | |||
| 54 | switch (params_channels(params)) { | ||
| 55 | case 2: /* Stereo I2S mode */ | ||
| 56 | fmt = SND_SOC_DAIFMT_I2S | | ||
| 57 | SND_SOC_DAIFMT_NB_NF | | ||
| 58 | SND_SOC_DAIFMT_CBM_CFM; | ||
| 59 | break; | ||
| 60 | case 4: /* Four channel TDM mode */ | ||
| 61 | fmt = SND_SOC_DAIFMT_DSP_A | | ||
| 62 | SND_SOC_DAIFMT_IB_NF | | ||
| 63 | SND_SOC_DAIFMT_CBM_CFM; | ||
| 64 | break; | ||
| 65 | default: | ||
| 66 | return -EINVAL; | ||
| 67 | } | ||
| 68 | |||
| 69 | /* Set codec DAI configuration */ | ||
| 70 | ret = snd_soc_dai_set_fmt(codec_dai, fmt); | ||
| 71 | if (ret < 0) { | ||
| 72 | dev_err(card->dev, "can't set codec DAI configuration\n"); | ||
| 73 | return ret; | ||
| 74 | } | ||
| 75 | |||
| 76 | /* Set cpu DAI configuration */ | ||
| 77 | ret = snd_soc_dai_set_fmt(cpu_dai, fmt); | ||
| 78 | if (ret < 0) { | ||
| 79 | dev_err(card->dev, "can't set cpu DAI configuration\n"); | ||
| 80 | return ret; | ||
| 81 | } | ||
| 82 | |||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | static struct snd_soc_ops omap_twl4030_ops = { | ||
| 87 | .hw_params = omap_twl4030_hw_params, | ||
| 88 | }; | ||
| 89 | |||
| 90 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
| 91 | static struct snd_soc_dai_link omap_twl4030_dai_links[] = { | ||
| 92 | { | ||
| 93 | .name = "TWL4030", | ||
| 94 | .stream_name = "TWL4030", | ||
| 95 | .cpu_dai_name = "omap-mcbsp.2", | ||
| 96 | .codec_dai_name = "twl4030-hifi", | ||
| 97 | .platform_name = "omap-pcm-audio", | ||
| 98 | .codec_name = "twl4030-codec", | ||
| 99 | .ops = &omap_twl4030_ops, | ||
| 100 | }, | ||
| 101 | }; | ||
| 102 | |||
| 103 | /* Audio machine driver */ | ||
| 104 | static struct snd_soc_card omap_twl4030_card = { | ||
| 105 | .owner = THIS_MODULE, | ||
| 106 | .dai_link = omap_twl4030_dai_links, | ||
| 107 | .num_links = ARRAY_SIZE(omap_twl4030_dai_links), | ||
| 108 | }; | ||
| 109 | |||
| 110 | static __devinit int omap_twl4030_probe(struct platform_device *pdev) | ||
| 111 | { | ||
| 112 | struct omap_tw4030_pdata *pdata = dev_get_platdata(&pdev->dev); | ||
| 113 | struct device_node *node = pdev->dev.of_node; | ||
| 114 | struct snd_soc_card *card = &omap_twl4030_card; | ||
| 115 | int ret = 0; | ||
| 116 | |||
| 117 | card->dev = &pdev->dev; | ||
| 118 | |||
| 119 | if (node) { | ||
| 120 | struct device_node *dai_node; | ||
| 121 | |||
| 122 | if (snd_soc_of_parse_card_name(card, "ti,model")) { | ||
| 123 | dev_err(&pdev->dev, "Card name is not provided\n"); | ||
| 124 | return -ENODEV; | ||
| 125 | } | ||
| 126 | |||
| 127 | dai_node = of_parse_phandle(node, "ti,mcbsp", 0); | ||
| 128 | if (!dai_node) { | ||
| 129 | dev_err(&pdev->dev, "McBSP node is not provided\n"); | ||
| 130 | return -EINVAL; | ||
| 131 | } | ||
| 132 | omap_twl4030_dai_links[0].cpu_dai_name = NULL; | ||
| 133 | omap_twl4030_dai_links[0].cpu_of_node = dai_node; | ||
| 134 | |||
| 135 | } else if (pdata) { | ||
| 136 | if (pdata->card_name) { | ||
| 137 | card->name = pdata->card_name; | ||
| 138 | } else { | ||
| 139 | dev_err(&pdev->dev, "Card name is not provided\n"); | ||
| 140 | return -ENODEV; | ||
| 141 | } | ||
| 142 | } else { | ||
| 143 | dev_err(&pdev->dev, "Missing pdata\n"); | ||
| 144 | return -ENODEV; | ||
| 145 | } | ||
| 146 | |||
| 147 | ret = snd_soc_register_card(card); | ||
| 148 | if (ret) { | ||
| 149 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | ||
| 150 | ret); | ||
| 151 | return ret; | ||
| 152 | } | ||
| 153 | |||
| 154 | return 0; | ||
| 155 | } | ||
| 156 | |||
| 157 | static int __devexit omap_twl4030_remove(struct platform_device *pdev) | ||
| 158 | { | ||
| 159 | struct snd_soc_card *card = platform_get_drvdata(pdev); | ||
| 160 | |||
| 161 | snd_soc_unregister_card(card); | ||
| 162 | |||
| 163 | return 0; | ||
| 164 | } | ||
| 165 | |||
| 166 | static const struct of_device_id omap_twl4030_of_match[] = { | ||
| 167 | {.compatible = "ti,omap-twl4030", }, | ||
| 168 | { }, | ||
| 169 | }; | ||
| 170 | MODULE_DEVICE_TABLE(of, omap_twl4030_of_match); | ||
| 171 | |||
| 172 | static struct platform_driver omap_twl4030_driver = { | ||
| 173 | .driver = { | ||
| 174 | .name = "omap-twl4030", | ||
| 175 | .owner = THIS_MODULE, | ||
| 176 | .pm = &snd_soc_pm_ops, | ||
| 177 | .of_match_table = omap_twl4030_of_match, | ||
| 178 | }, | ||
| 179 | .probe = omap_twl4030_probe, | ||
| 180 | .remove = __devexit_p(omap_twl4030_remove), | ||
| 181 | }; | ||
| 182 | |||
| 183 | module_platform_driver(omap_twl4030_driver); | ||
| 184 | |||
| 185 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); | ||
| 186 | MODULE_DESCRIPTION("ALSA SoC for TI SoC based boards with twl4030 codec"); | ||
| 187 | MODULE_LICENSE("GPL"); | ||
| 188 | MODULE_ALIAS("platform:omap-twl4030"); | ||
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c deleted file mode 100644 index e263188841b6..000000000000 --- a/sound/soc/omap/omap3beagle.c +++ /dev/null | |||
| @@ -1,150 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * omap3beagle.c -- SoC audio for OMAP3 Beagle | ||
| 3 | * | ||
| 4 | * Author: Steve Sakoman <steve@sakoman.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * version 2 as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, but | ||
| 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 13 | * General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
| 18 | * 02110-1301 USA | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/clk.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <sound/core.h> | ||
| 26 | #include <sound/pcm.h> | ||
| 27 | #include <sound/soc.h> | ||
| 28 | |||
| 29 | #include <asm/mach-types.h> | ||
| 30 | #include <mach/hardware.h> | ||
| 31 | #include <mach/gpio.h> | ||
| 32 | #include <linux/platform_data/asoc-ti-mcbsp.h> | ||
| 33 | |||
| 34 | #include "omap-mcbsp.h" | ||
| 35 | #include "omap-pcm.h" | ||
| 36 | |||
| 37 | static int omap3beagle_hw_params(struct snd_pcm_substream *substream, | ||
| 38 | struct snd_pcm_hw_params *params) | ||
| 39 | { | ||
| 40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 41 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
| 42 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
| 43 | unsigned int fmt; | ||
| 44 | int ret; | ||
| 45 | |||
| 46 | switch (params_channels(params)) { | ||
| 47 | case 2: /* Stereo I2S mode */ | ||
| 48 | fmt = SND_SOC_DAIFMT_I2S | | ||
| 49 | SND_SOC_DAIFMT_NB_NF | | ||
| 50 | SND_SOC_DAIFMT_CBM_CFM; | ||
| 51 | break; | ||
| 52 | case 4: /* Four channel TDM mode */ | ||
| 53 | fmt = SND_SOC_DAIFMT_DSP_A | | ||
| 54 | SND_SOC_DAIFMT_IB_NF | | ||
| 55 | SND_SOC_DAIFMT_CBM_CFM; | ||
| 56 | break; | ||
| 57 | default: | ||
| 58 | return -EINVAL; | ||
| 59 | } | ||
| 60 | |||
| 61 | /* Set codec DAI configuration */ | ||
| 62 | ret = snd_soc_dai_set_fmt(codec_dai, fmt); | ||
| 63 | if (ret < 0) { | ||
| 64 | printk(KERN_ERR "can't set codec DAI configuration\n"); | ||
| 65 | return ret; | ||
| 66 | } | ||
| 67 | |||
| 68 | /* Set cpu DAI configuration */ | ||
| 69 | ret = snd_soc_dai_set_fmt(cpu_dai, fmt); | ||
| 70 | if (ret < 0) { | ||
| 71 | printk(KERN_ERR "can't set cpu DAI configuration\n"); | ||
| 72 | return ret; | ||
| 73 | } | ||
| 74 | |||
| 75 | /* Set the codec system clock for DAC and ADC */ | ||
| 76 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, | ||
| 77 | SND_SOC_CLOCK_IN); | ||
| 78 | if (ret < 0) { | ||
| 79 | printk(KERN_ERR "can't set codec system clock\n"); | ||
| 80 | return ret; | ||
| 81 | } | ||
| 82 | |||
| 83 | return 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | static struct snd_soc_ops omap3beagle_ops = { | ||
| 87 | .hw_params = omap3beagle_hw_params, | ||
| 88 | }; | ||
| 89 | |||
| 90 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
| 91 | static struct snd_soc_dai_link omap3beagle_dai = { | ||
| 92 | .name = "TWL4030", | ||
| 93 | .stream_name = "TWL4030", | ||
| 94 | .cpu_dai_name = "omap-mcbsp.2", | ||
| 95 | .platform_name = "omap-pcm-audio", | ||
| 96 | .codec_dai_name = "twl4030-hifi", | ||
| 97 | .codec_name = "twl4030-codec", | ||
| 98 | .ops = &omap3beagle_ops, | ||
| 99 | }; | ||
| 100 | |||
| 101 | /* Audio machine driver */ | ||
| 102 | static struct snd_soc_card snd_soc_omap3beagle = { | ||
| 103 | .name = "omap3beagle", | ||
| 104 | .owner = THIS_MODULE, | ||
| 105 | .dai_link = &omap3beagle_dai, | ||
| 106 | .num_links = 1, | ||
| 107 | }; | ||
| 108 | |||
| 109 | static struct platform_device *omap3beagle_snd_device; | ||
| 110 | |||
| 111 | static int __init omap3beagle_soc_init(void) | ||
| 112 | { | ||
| 113 | int ret; | ||
| 114 | |||
| 115 | if (!(machine_is_omap3_beagle() || machine_is_devkit8000())) | ||
| 116 | return -ENODEV; | ||
| 117 | pr_info("OMAP3 Beagle/Devkit8000 SoC init\n"); | ||
| 118 | |||
| 119 | omap3beagle_snd_device = platform_device_alloc("soc-audio", -1); | ||
| 120 | if (!omap3beagle_snd_device) { | ||
| 121 | printk(KERN_ERR "Platform device allocation failed\n"); | ||
| 122 | return -ENOMEM; | ||
| 123 | } | ||
| 124 | |||
| 125 | platform_set_drvdata(omap3beagle_snd_device, &snd_soc_omap3beagle); | ||
| 126 | |||
| 127 | ret = platform_device_add(omap3beagle_snd_device); | ||
| 128 | if (ret) | ||
| 129 | goto err1; | ||
| 130 | |||
| 131 | return 0; | ||
| 132 | |||
| 133 | err1: | ||
| 134 | printk(KERN_ERR "Unable to add platform device\n"); | ||
| 135 | platform_device_put(omap3beagle_snd_device); | ||
| 136 | |||
| 137 | return ret; | ||
| 138 | } | ||
| 139 | |||
| 140 | static void __exit omap3beagle_soc_exit(void) | ||
| 141 | { | ||
| 142 | platform_device_unregister(omap3beagle_snd_device); | ||
| 143 | } | ||
| 144 | |||
| 145 | module_init(omap3beagle_soc_init); | ||
| 146 | module_exit(omap3beagle_soc_exit); | ||
| 147 | |||
| 148 | MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>"); | ||
| 149 | MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle"); | ||
| 150 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c deleted file mode 100644 index d632bfbb6983..000000000000 --- a/sound/soc/omap/omap3evm.c +++ /dev/null | |||
| @@ -1,118 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * omap3evm.c -- ALSA SoC support for OMAP3 EVM | ||
| 3 | * | ||
| 4 | * Author: Anuj Aggarwal <anuj.aggarwal@ti.com> | ||
| 5 | * | ||
| 6 | * Based on sound/soc/omap/beagle.c by Steve Sakoman | ||
| 7 | * | ||
| 8 | * Copyright (C) 2008 Texas Instruments, Incorporated | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms of the GNU General Public License as published by the | ||
| 12 | * Free Software Foundation version 2. | ||
| 13 | * | ||
| 14 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, | ||
| 15 | * whether express or implied; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 17 | * General Public License for more details. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/clk.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/module.h> | ||
| 23 | #include <sound/core.h> | ||
| 24 | #include <sound/pcm.h> | ||
| 25 | #include <sound/soc.h> | ||
| 26 | |||
| 27 | #include <asm/mach-types.h> | ||
| 28 | #include <mach/hardware.h> | ||
| 29 | #include <mach/gpio.h> | ||
| 30 | #include <linux/platform_data/asoc-ti-mcbsp.h> | ||
| 31 | |||
| 32 | #include "omap-mcbsp.h" | ||
| 33 | #include "omap-pcm.h" | ||
| 34 | |||
| 35 | static int omap3evm_hw_params(struct snd_pcm_substream *substream, | ||
| 36 | struct snd_pcm_hw_params *params) | ||
| 37 | { | ||
| 38 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 39 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
| 40 | int ret; | ||
| 41 | |||
| 42 | /* Set the codec system clock for DAC and ADC */ | ||
| 43 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, | ||
| 44 | SND_SOC_CLOCK_IN); | ||
| 45 | if (ret < 0) { | ||
| 46 | printk(KERN_ERR "Can't set codec system clock\n"); | ||
| 47 | return ret; | ||
| 48 | } | ||
| 49 | |||
| 50 | return 0; | ||
| 51 | } | ||
| 52 | |||
| 53 | static struct snd_soc_ops omap3evm_ops = { | ||
| 54 | .hw_params = omap3evm_hw_params, | ||
| 55 | }; | ||
| 56 | |||
| 57 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
| 58 | static struct snd_soc_dai_link omap3evm_dai = { | ||
| 59 | .name = "TWL4030", | ||
| 60 | .stream_name = "TWL4030", | ||
| 61 | .cpu_dai_name = "omap-mcbsp.2", | ||
| 62 | .codec_dai_name = "twl4030-hifi", | ||
| 63 | .platform_name = "omap-pcm-audio", | ||
| 64 | .codec_name = "twl4030-codec", | ||
| 65 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
| 66 | SND_SOC_DAIFMT_CBM_CFM, | ||
| 67 | .ops = &omap3evm_ops, | ||
| 68 | }; | ||
| 69 | |||
| 70 | /* Audio machine driver */ | ||
| 71 | static struct snd_soc_card snd_soc_omap3evm = { | ||
| 72 | .name = "omap3evm", | ||
| 73 | .owner = THIS_MODULE, | ||
| 74 | .dai_link = &omap3evm_dai, | ||
| 75 | .num_links = 1, | ||
| 76 | }; | ||
| 77 | |||
| 78 | static struct platform_device *omap3evm_snd_device; | ||
| 79 | |||
| 80 | static int __init omap3evm_soc_init(void) | ||
| 81 | { | ||
| 82 | int ret; | ||
| 83 | |||
| 84 | if (!machine_is_omap3evm()) | ||
| 85 | return -ENODEV; | ||
| 86 | pr_info("OMAP3 EVM SoC init\n"); | ||
| 87 | |||
| 88 | omap3evm_snd_device = platform_device_alloc("soc-audio", -1); | ||
| 89 | if (!omap3evm_snd_device) { | ||
| 90 | printk(KERN_ERR "Platform device allocation failed\n"); | ||
| 91 | return -ENOMEM; | ||
| 92 | } | ||
| 93 | |||
| 94 | platform_set_drvdata(omap3evm_snd_device, &snd_soc_omap3evm); | ||
| 95 | ret = platform_device_add(omap3evm_snd_device); | ||
| 96 | if (ret) | ||
| 97 | goto err1; | ||
| 98 | |||
| 99 | return 0; | ||
| 100 | |||
| 101 | err1: | ||
| 102 | printk(KERN_ERR "Unable to add platform device\n"); | ||
| 103 | platform_device_put(omap3evm_snd_device); | ||
| 104 | |||
| 105 | return ret; | ||
| 106 | } | ||
| 107 | |||
| 108 | static void __exit omap3evm_soc_exit(void) | ||
| 109 | { | ||
| 110 | platform_device_unregister(omap3evm_snd_device); | ||
| 111 | } | ||
| 112 | |||
| 113 | module_init(omap3evm_soc_init); | ||
| 114 | module_exit(omap3evm_soc_exit); | ||
| 115 | |||
| 116 | MODULE_AUTHOR("Anuj Aggarwal <anuj.aggarwal@ti.com>"); | ||
| 117 | MODULE_DESCRIPTION("ALSA SoC OMAP3 EVM"); | ||
| 118 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c deleted file mode 100644 index 502bce299885..000000000000 --- a/sound/soc/omap/overo.c +++ /dev/null | |||
| @@ -1,122 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * overo.c -- SoC audio for Gumstix Overo | ||
| 3 | * | ||
| 4 | * Author: Steve Sakoman <steve@sakoman.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * version 2 as published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, but | ||
| 11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 13 | * General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
| 18 | * 02110-1301 USA | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/clk.h> | ||
| 23 | #include <linux/platform_device.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <sound/core.h> | ||
| 26 | #include <sound/pcm.h> | ||
| 27 | #include <sound/soc.h> | ||
| 28 | |||
| 29 | #include <asm/mach-types.h> | ||
| 30 | #include <mach/hardware.h> | ||
| 31 | #include <mach/gpio.h> | ||
| 32 | #include <linux/platform_data/asoc-ti-mcbsp.h> | ||
| 33 | |||
| 34 | #include "omap-mcbsp.h" | ||
| 35 | #include "omap-pcm.h" | ||
| 36 | |||
| 37 | static int overo_hw_params(struct snd_pcm_substream *substream, | ||
| 38 | struct snd_pcm_hw_params *params) | ||
| 39 | { | ||
| 40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
| 41 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
| 42 | int ret; | ||
| 43 | |||
| 44 | /* Set the codec system clock for DAC and ADC */ | ||
| 45 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, | ||
| 46 | SND_SOC_CLOCK_IN); | ||
| 47 | if (ret < 0) { | ||
| 48 | printk(KERN_ERR "can't set codec system clock\n"); | ||
| 49 | return ret; | ||
| 50 | } | ||
| 51 | |||
| 52 | return 0; | ||
| 53 | } | ||
| 54 | |||
| 55 | static struct snd_soc_ops overo_ops = { | ||
| 56 | .hw_params = overo_hw_params, | ||
| 57 | }; | ||
| 58 | |||
| 59 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
| 60 | static struct snd_soc_dai_link overo_dai = { | ||
| 61 | .name = "TWL4030", | ||
| 62 | .stream_name = "TWL4030", | ||
| 63 | .cpu_dai_name = "omap-mcbsp.2", | ||
| 64 | .codec_dai_name = "twl4030-hifi", | ||
| 65 | .platform_name = "omap-pcm-audio", | ||
| 66 | .codec_name = "twl4030-codec", | ||
| 67 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
| 68 | SND_SOC_DAIFMT_CBM_CFM, | ||
| 69 | .ops = &overo_ops, | ||
| 70 | }; | ||
| 71 | |||
| 72 | /* Audio machine driver */ | ||
| 73 | static struct snd_soc_card snd_soc_card_overo = { | ||
| 74 | .name = "overo", | ||
| 75 | .owner = THIS_MODULE, | ||
| 76 | .dai_link = &overo_dai, | ||
| 77 | .num_links = 1, | ||
| 78 | }; | ||
| 79 | |||
| 80 | static struct platform_device *overo_snd_device; | ||
| 81 | |||
| 82 | static int __init overo_soc_init(void) | ||
| 83 | { | ||
| 84 | int ret; | ||
| 85 | |||
| 86 | if (!(machine_is_overo() || machine_is_cm_t35())) { | ||
| 87 | pr_debug("Incomatible machine!\n"); | ||
| 88 | return -ENODEV; | ||
| 89 | } | ||
| 90 | printk(KERN_INFO "overo SoC init\n"); | ||
| 91 | |||
| 92 | overo_snd_device = platform_device_alloc("soc-audio", -1); | ||
| 93 | if (!overo_snd_device) { | ||
| 94 | printk(KERN_ERR "Platform device allocation failed\n"); | ||
| 95 | return -ENOMEM; | ||
| 96 | } | ||
| 97 | |||
| 98 | platform_set_drvdata(overo_snd_device, &snd_soc_card_overo); | ||
| 99 | |||
| 100 | ret = platform_device_add(overo_snd_device); | ||
| 101 | if (ret) | ||
| 102 | goto err1; | ||
| 103 | |||
| 104 | return 0; | ||
| 105 | |||
| 106 | err1: | ||
| 107 | printk(KERN_ERR "Unable to add platform device\n"); | ||
| 108 | platform_device_put(overo_snd_device); | ||
| 109 | |||
| 110 | return ret; | ||
| 111 | } | ||
| 112 | module_init(overo_soc_init); | ||
| 113 | |||
| 114 | static void __exit overo_soc_exit(void) | ||
| 115 | { | ||
| 116 | platform_device_unregister(overo_snd_device); | ||
| 117 | } | ||
| 118 | module_exit(overo_soc_exit); | ||
| 119 | |||
| 120 | MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>"); | ||
| 121 | MODULE_DESCRIPTION("ALSA SoC overo"); | ||
| 122 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index 23de2b21d696..677b567935f8 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c | |||
| @@ -191,9 +191,6 @@ static int __init zoom2_soc_init(void) | |||
| 191 | BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0); | 191 | BUG_ON(gpio_request(ZOOM2_HEADSET_MUX_GPIO, "hs_mux") < 0); |
| 192 | gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0); | 192 | gpio_direction_output(ZOOM2_HEADSET_MUX_GPIO, 0); |
| 193 | 193 | ||
| 194 | BUG_ON(gpio_request(ZOOM2_HEADSET_EXTMUTE_GPIO, "ext_mute") < 0); | ||
| 195 | gpio_direction_output(ZOOM2_HEADSET_EXTMUTE_GPIO, 0); | ||
| 196 | |||
| 197 | return 0; | 194 | return 0; |
| 198 | 195 | ||
| 199 | err1: | 196 | err1: |
| @@ -207,7 +204,6 @@ module_init(zoom2_soc_init); | |||
| 207 | static void __exit zoom2_soc_exit(void) | 204 | static void __exit zoom2_soc_exit(void) |
| 208 | { | 205 | { |
| 209 | gpio_free(ZOOM2_HEADSET_MUX_GPIO); | 206 | gpio_free(ZOOM2_HEADSET_MUX_GPIO); |
| 210 | gpio_free(ZOOM2_HEADSET_EXTMUTE_GPIO); | ||
| 211 | 207 | ||
| 212 | platform_device_unregister(zoom2_snd_device); | 208 | platform_device_unregister(zoom2_snd_device); |
| 213 | } | 209 | } |
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index fe3995ce9b38..e7b83179aca2 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | config SND_SOC_SAMSUNG | 1 | config SND_SOC_SAMSUNG |
| 2 | tristate "ASoC support for Samsung" | 2 | tristate "ASoC support for Samsung" |
| 3 | depends on ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5P64X0 || ARCH_EXYNOS4 | 3 | depends on PLAT_SAMSUNG |
| 4 | select S3C64XX_DMA if ARCH_S3C64XX | 4 | select S3C64XX_DMA if ARCH_S3C64XX |
| 5 | select S3C2410_DMA if ARCH_S3C24XX | 5 | select S3C2410_DMA if ARCH_S3C24XX |
| 6 | help | 6 | help |
| @@ -191,6 +191,7 @@ config SND_SOC_SPEYSIDE | |||
| 191 | select SND_SAMSUNG_I2S | 191 | select SND_SAMSUNG_I2S |
| 192 | select SND_SOC_WM8996 | 192 | select SND_SOC_WM8996 |
| 193 | select SND_SOC_WM9081 | 193 | select SND_SOC_WM9081 |
| 194 | select SND_SOC_WM0010 | ||
| 194 | select SND_SOC_WM1250_EV1 | 195 | select SND_SOC_WM1250_EV1 |
| 195 | 196 | ||
| 196 | config SND_SOC_TOBERMORY | 197 | config SND_SOC_TOBERMORY |
| @@ -199,6 +200,14 @@ config SND_SOC_TOBERMORY | |||
| 199 | select SND_SAMSUNG_I2S | 200 | select SND_SAMSUNG_I2S |
| 200 | select SND_SOC_WM8962 | 201 | select SND_SOC_WM8962 |
| 201 | 202 | ||
| 203 | config SND_SOC_BELLS | ||
| 204 | tristate "Audio support for Wolfson Bells" | ||
| 205 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 | ||
| 206 | select SND_SAMSUNG_I2S | ||
| 207 | select SND_SOC_WM5102 | ||
| 208 | select SND_SOC_WM5110 | ||
| 209 | select SND_SOC_WM9081 | ||
| 210 | |||
| 202 | config SND_SOC_LOWLAND | 211 | config SND_SOC_LOWLAND |
| 203 | tristate "Audio support for Wolfson Lowland" | 212 | tristate "Audio support for Wolfson Lowland" |
| 204 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 | 213 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 |
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 9d03beb40c86..709f6059ad67 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile | |||
| @@ -42,6 +42,7 @@ snd-soc-speyside-objs := speyside.o | |||
| 42 | snd-soc-tobermory-objs := tobermory.o | 42 | snd-soc-tobermory-objs := tobermory.o |
| 43 | snd-soc-lowland-objs := lowland.o | 43 | snd-soc-lowland-objs := lowland.o |
| 44 | snd-soc-littlemill-objs := littlemill.o | 44 | snd-soc-littlemill-objs := littlemill.o |
| 45 | snd-soc-bells-objs := bells.o | ||
| 45 | 46 | ||
| 46 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o | 47 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o |
| 47 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 48 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
| @@ -65,3 +66,4 @@ obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o | |||
| 65 | obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o | 66 | obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o |
| 66 | obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o | 67 | obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o |
| 67 | obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o | 68 | obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o |
| 69 | obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o | ||
diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c new file mode 100644 index 000000000000..5dc10dfc0d42 --- /dev/null +++ b/sound/soc/samsung/bells.c | |||
| @@ -0,0 +1,346 @@ | |||
| 1 | /* | ||
| 2 | * Bells audio support | ||
| 3 | * | ||
| 4 | * Copyright 2012 Wolfson Microelectronics | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU General Public License as published by the | ||
| 8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 9 | * option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <sound/soc.h> | ||
| 13 | #include <sound/soc-dapm.h> | ||
| 14 | #include <sound/jack.h> | ||
| 15 | #include <linux/gpio.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | |||
| 18 | #include "../codecs/wm5102.h" | ||
| 19 | #include "../codecs/wm9081.h" | ||
| 20 | |||
| 21 | /* | ||
| 22 | * 44.1kHz based clocks for the SYSCLK domain, use a very high clock | ||
| 23 | * to allow all the DSP functionality to be enabled if desired. | ||
| 24 | */ | ||
| 25 | #define SYSCLK_RATE (44100 * 1024) | ||
| 26 | |||
| 27 | /* 48kHz based clocks for the ASYNC domain */ | ||
| 28 | #define ASYNCCLK_RATE (48000 * 512) | ||
| 29 | |||
| 30 | /* BCLK2 is fixed at this currently */ | ||
| 31 | #define BCLK2_RATE (64 * 8000) | ||
| 32 | |||
| 33 | /* | ||
| 34 | * Expect a 24.576MHz crystal if one is fitted (the driver will function | ||
| 35 | * if this is not fitted). | ||
| 36 | */ | ||
| 37 | #define MCLK_RATE 24576000 | ||
| 38 | |||
| 39 | #define WM9081_AUDIO_RATE 44100 | ||
| 40 | #define WM9081_MCLK_RATE (WM9081_AUDIO_RATE * 256) | ||
| 41 | |||
| 42 | static int bells_set_bias_level(struct snd_soc_card *card, | ||
| 43 | struct snd_soc_dapm_context *dapm, | ||
| 44 | enum snd_soc_bias_level level) | ||
| 45 | { | ||
| 46 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
| 47 | struct snd_soc_codec *codec = codec_dai->codec; | ||
| 48 | int ret; | ||
| 49 | |||
| 50 | if (dapm->dev != codec_dai->dev) | ||
| 51 | return 0; | ||
| 52 | |||
| 53 | switch (level) { | ||
| 54 | case SND_SOC_BIAS_PREPARE: | ||
| 55 | if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { | ||
| 56 | ret = snd_soc_codec_set_pll(codec, WM5102_FLL1, | ||
| 57 | ARIZONA_FLL_SRC_MCLK1, | ||
| 58 | MCLK_RATE, | ||
| 59 | SYSCLK_RATE); | ||
| 60 | if (ret < 0) | ||
| 61 | pr_err("Failed to start FLL: %d\n", ret); | ||
| 62 | |||
| 63 | ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, | ||
| 64 | ARIZONA_FLL_SRC_AIF2BCLK, | ||
| 65 | BCLK2_RATE, | ||
| 66 | ASYNCCLK_RATE); | ||
| 67 | if (ret < 0) | ||
| 68 | pr_err("Failed to start FLL: %d\n", ret); | ||
| 69 | } | ||
| 70 | break; | ||
| 71 | |||
| 72 | default: | ||
| 73 | break; | ||
| 74 | } | ||
| 75 | |||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | static int bells_set_bias_level_post(struct snd_soc_card *card, | ||
| 80 | struct snd_soc_dapm_context *dapm, | ||
| 81 | enum snd_soc_bias_level level) | ||
| 82 | { | ||
| 83 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
| 84 | struct snd_soc_codec *codec = codec_dai->codec; | ||
| 85 | int ret; | ||
| 86 | |||
| 87 | if (dapm->dev != codec_dai->dev) | ||
| 88 | return 0; | ||
| 89 | |||
| 90 | switch (level) { | ||
| 91 | case SND_SOC_BIAS_STANDBY: | ||
| 92 | ret = snd_soc_codec_set_pll(codec, WM5102_FLL1, 0, 0, 0); | ||
| 93 | if (ret < 0) { | ||
| 94 | pr_err("Failed to stop FLL: %d\n", ret); | ||
| 95 | return ret; | ||
| 96 | } | ||
| 97 | |||
| 98 | ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, 0, 0, 0); | ||
| 99 | if (ret < 0) { | ||
| 100 | pr_err("Failed to stop FLL: %d\n", ret); | ||
| 101 | return ret; | ||
| 102 | } | ||
| 103 | break; | ||
| 104 | |||
| 105 | default: | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | |||
| 109 | dapm->bias_level = level; | ||
| 110 | |||
| 111 | return 0; | ||
| 112 | } | ||
| 113 | |||
| 114 | static int bells_late_probe(struct snd_soc_card *card) | ||
| 115 | { | ||
| 116 | struct snd_soc_codec *codec = card->rtd[0].codec; | ||
| 117 | struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai; | ||
| 118 | struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai; | ||
| 119 | struct snd_soc_dai *aif3_dai = card->rtd[2].cpu_dai; | ||
| 120 | struct snd_soc_dai *wm9081_dai = card->rtd[2].codec_dai; | ||
| 121 | int ret; | ||
| 122 | |||
| 123 | ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0); | ||
| 124 | if (ret != 0) { | ||
| 125 | dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); | ||
| 126 | return ret; | ||
| 127 | } | ||
| 128 | |||
| 129 | ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0); | ||
| 130 | if (ret != 0) { | ||
| 131 | dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret); | ||
| 132 | return ret; | ||
| 133 | } | ||
| 134 | |||
| 135 | ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0); | ||
| 136 | if (ret != 0) { | ||
| 137 | dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); | ||
| 138 | return ret; | ||
| 139 | } | ||
| 140 | |||
| 141 | ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK, | ||
| 142 | ARIZONA_CLK_SRC_FLL1, SYSCLK_RATE, | ||
| 143 | SND_SOC_CLOCK_IN); | ||
| 144 | if (ret != 0) { | ||
| 145 | dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret); | ||
| 146 | return ret; | ||
| 147 | } | ||
| 148 | |||
| 149 | ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0, | ||
| 150 | WM9081_MCLK_RATE, SND_SOC_CLOCK_OUT); | ||
| 151 | if (ret != 0) { | ||
| 152 | dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret); | ||
| 153 | return ret; | ||
| 154 | } | ||
| 155 | |||
| 156 | ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK, | ||
| 157 | ARIZONA_CLK_SRC_FLL2, ASYNCCLK_RATE, | ||
| 158 | SND_SOC_CLOCK_IN); | ||
| 159 | if (ret != 0) { | ||
| 160 | dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret); | ||
| 161 | return ret; | ||
| 162 | } | ||
| 163 | |||
| 164 | ret = snd_soc_codec_set_sysclk(wm9081_dai->codec, WM9081_SYSCLK_MCLK, | ||
| 165 | 0, WM9081_MCLK_RATE, 0); | ||
| 166 | if (ret != 0) { | ||
| 167 | dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret); | ||
| 168 | return ret; | ||
| 169 | } | ||
| 170 | |||
| 171 | return 0; | ||
| 172 | } | ||
| 173 | |||
| 174 | static const struct snd_soc_pcm_stream baseband_params = { | ||
| 175 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
| 176 | .rate_min = 8000, | ||
| 177 | .rate_max = 8000, | ||
| 178 | .channels_min = 2, | ||
| 179 | .channels_max = 2, | ||
| 180 | }; | ||
| 181 | |||
| 182 | static const struct snd_soc_pcm_stream sub_params = { | ||
| 183 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
| 184 | .rate_min = WM9081_AUDIO_RATE, | ||
| 185 | .rate_max = WM9081_AUDIO_RATE, | ||
| 186 | .channels_min = 2, | ||
| 187 | .channels_max = 2, | ||
| 188 | }; | ||
| 189 | |||
| 190 | static struct snd_soc_dai_link bells_dai_wm5102[] = { | ||
| 191 | { | ||
| 192 | .name = "CPU", | ||
| 193 | .stream_name = "CPU", | ||
| 194 | .cpu_dai_name = "samsung-i2s.0", | ||
| 195 | .codec_dai_name = "wm5102-aif1", | ||
| 196 | .platform_name = "samsung-audio", | ||
| 197 | .codec_name = "wm5102-codec", | ||
| 198 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
| 199 | | SND_SOC_DAIFMT_CBM_CFM, | ||
| 200 | }, | ||
| 201 | { | ||
| 202 | .name = "Baseband", | ||
| 203 | .stream_name = "Baseband", | ||
| 204 | .cpu_dai_name = "wm5102-aif2", | ||
| 205 | .codec_dai_name = "wm1250-ev1", | ||
| 206 | .codec_name = "wm1250-ev1.1-0027", | ||
| 207 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
| 208 | | SND_SOC_DAIFMT_CBM_CFM, | ||
| 209 | .ignore_suspend = 1, | ||
| 210 | .params = &baseband_params, | ||
| 211 | }, | ||
| 212 | { | ||
| 213 | .name = "Sub", | ||
| 214 | .stream_name = "Sub", | ||
| 215 | .cpu_dai_name = "wm5102-aif3", | ||
| 216 | .codec_dai_name = "wm9081-hifi", | ||
| 217 | .codec_name = "wm9081.1-006c", | ||
| 218 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
| 219 | | SND_SOC_DAIFMT_CBS_CFS, | ||
| 220 | .ignore_suspend = 1, | ||
| 221 | .params = &sub_params, | ||
| 222 | }, | ||
| 223 | }; | ||
| 224 | |||
| 225 | static struct snd_soc_dai_link bells_dai_wm5110[] = { | ||
| 226 | { | ||
| 227 | .name = "CPU", | ||
| 228 | .stream_name = "CPU", | ||
| 229 | .cpu_dai_name = "samsung-i2s.0", | ||
| 230 | .codec_dai_name = "wm5110-aif1", | ||
| 231 | .platform_name = "samsung-audio", | ||
| 232 | .codec_name = "wm5110-codec", | ||
| 233 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
| 234 | | SND_SOC_DAIFMT_CBM_CFM, | ||
| 235 | }, | ||
| 236 | { | ||
| 237 | .name = "Baseband", | ||
| 238 | .stream_name = "Baseband", | ||
| 239 | .cpu_dai_name = "wm5110-aif2", | ||
| 240 | .codec_dai_name = "wm1250-ev1", | ||
| 241 | .codec_name = "wm1250-ev1.1-0027", | ||
| 242 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
| 243 | | SND_SOC_DAIFMT_CBM_CFM, | ||
| 244 | .ignore_suspend = 1, | ||
| 245 | .params = &baseband_params, | ||
| 246 | }, | ||
| 247 | { | ||
| 248 | .name = "Sub", | ||
| 249 | .stream_name = "Sub", | ||
| 250 | .cpu_dai_name = "wm5102-aif3", | ||
| 251 | .codec_dai_name = "wm9081-hifi", | ||
| 252 | .codec_name = "wm9081.1-006c", | ||
| 253 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
| 254 | | SND_SOC_DAIFMT_CBS_CFS, | ||
| 255 | .ignore_suspend = 1, | ||
| 256 | .params = &sub_params, | ||
| 257 | }, | ||
| 258 | }; | ||
| 259 | |||
| 260 | static struct snd_soc_codec_conf bells_codec_conf[] = { | ||
| 261 | { | ||
| 262 | .dev_name = "wm9081.1-006c", | ||
| 263 | .name_prefix = "Sub", | ||
| 264 | }, | ||
| 265 | }; | ||
| 266 | |||
| 267 | static struct snd_soc_dapm_route bells_routes[] = { | ||
| 268 | { "Sub CLK_SYS", NULL, "OPCLK" }, | ||
| 269 | }; | ||
| 270 | |||
| 271 | static struct snd_soc_card bells_cards[] = { | ||
| 272 | { | ||
| 273 | .name = "Bells WM5102", | ||
| 274 | .owner = THIS_MODULE, | ||
| 275 | .dai_link = bells_dai_wm5102, | ||
| 276 | .num_links = ARRAY_SIZE(bells_dai_wm5102), | ||
| 277 | .codec_conf = bells_codec_conf, | ||
| 278 | .num_configs = ARRAY_SIZE(bells_codec_conf), | ||
| 279 | |||
| 280 | .late_probe = bells_late_probe, | ||
| 281 | |||
| 282 | .dapm_routes = bells_routes, | ||
| 283 | .num_dapm_routes = ARRAY_SIZE(bells_routes), | ||
| 284 | |||
| 285 | .set_bias_level = bells_set_bias_level, | ||
| 286 | .set_bias_level_post = bells_set_bias_level_post, | ||
| 287 | }, | ||
| 288 | { | ||
| 289 | .name = "Bells WM5110", | ||
| 290 | .owner = THIS_MODULE, | ||
| 291 | .dai_link = bells_dai_wm5110, | ||
| 292 | .num_links = ARRAY_SIZE(bells_dai_wm5110), | ||
| 293 | .codec_conf = bells_codec_conf, | ||
| 294 | .num_configs = ARRAY_SIZE(bells_codec_conf), | ||
| 295 | |||
| 296 | .late_probe = bells_late_probe, | ||
| 297 | |||
| 298 | .dapm_routes = bells_routes, | ||
| 299 | .num_dapm_routes = ARRAY_SIZE(bells_routes), | ||
| 300 | |||
| 301 | .set_bias_level = bells_set_bias_level, | ||
| 302 | .set_bias_level_post = bells_set_bias_level_post, | ||
| 303 | }, | ||
| 304 | }; | ||
| 305 | |||
| 306 | |||
| 307 | static __devinit int bells_probe(struct platform_device *pdev) | ||
| 308 | { | ||
| 309 | int ret; | ||
| 310 | |||
| 311 | bells_cards[pdev->id].dev = &pdev->dev; | ||
| 312 | |||
| 313 | ret = snd_soc_register_card(&bells_cards[pdev->id]); | ||
| 314 | if (ret) { | ||
| 315 | dev_err(&pdev->dev, | ||
| 316 | "snd_soc_register_card(%s) failed: %d\n", | ||
| 317 | bells_cards[pdev->id].name, ret); | ||
| 318 | return ret; | ||
| 319 | } | ||
| 320 | |||
| 321 | return 0; | ||
| 322 | } | ||
| 323 | |||
| 324 | static int __devexit bells_remove(struct platform_device *pdev) | ||
| 325 | { | ||
| 326 | snd_soc_unregister_card(&bells_cards[pdev->id]); | ||
| 327 | |||
| 328 | return 0; | ||
| 329 | } | ||
| 330 | |||
| 331 | static struct platform_driver bells_driver = { | ||
| 332 | .driver = { | ||
| 333 | .name = "bells", | ||
| 334 | .owner = THIS_MODULE, | ||
| 335 | .pm = &snd_soc_pm_ops, | ||
| 336 | }, | ||
| 337 | .probe = bells_probe, | ||
| 338 | .remove = __devexit_p(bells_remove), | ||
| 339 | }; | ||
| 340 | |||
| 341 | module_platform_driver(bells_driver); | ||
| 342 | |||
| 343 | MODULE_DESCRIPTION("Bells audio support"); | ||
| 344 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
| 345 | MODULE_LICENSE("GPL"); | ||
| 346 | MODULE_ALIAS("platform:bells"); | ||
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index a4a9fc7e8c76..c7e1c28528a4 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c | |||
| @@ -25,7 +25,7 @@ static int speyside_set_bias_level(struct snd_soc_card *card, | |||
| 25 | struct snd_soc_dapm_context *dapm, | 25 | struct snd_soc_dapm_context *dapm, |
| 26 | enum snd_soc_bias_level level) | 26 | enum snd_soc_bias_level level) |
| 27 | { | 27 | { |
| 28 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | 28 | struct snd_soc_dai *codec_dai = card->rtd[1].codec_dai; |
| 29 | int ret; | 29 | int ret; |
| 30 | 30 | ||
| 31 | if (dapm->dev != codec_dai->dev) | 31 | if (dapm->dev != codec_dai->dev) |
| @@ -57,7 +57,7 @@ static int speyside_set_bias_level_post(struct snd_soc_card *card, | |||
| 57 | struct snd_soc_dapm_context *dapm, | 57 | struct snd_soc_dapm_context *dapm, |
| 58 | enum snd_soc_bias_level level) | 58 | enum snd_soc_bias_level level) |
| 59 | { | 59 | { |
| 60 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | 60 | struct snd_soc_dai *codec_dai = card->rtd[1].codec_dai; |
| 61 | int ret; | 61 | int ret; |
| 62 | 62 | ||
| 63 | if (dapm->dev != codec_dai->dev) | 63 | if (dapm->dev != codec_dai->dev) |
| @@ -126,6 +126,18 @@ static void speyside_set_polarity(struct snd_soc_codec *codec, | |||
| 126 | snd_soc_dapm_sync(&codec->dapm); | 126 | snd_soc_dapm_sync(&codec->dapm); |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | static int speyside_wm0010_init(struct snd_soc_pcm_runtime *rtd) | ||
| 130 | { | ||
| 131 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
| 132 | int ret; | ||
| 133 | |||
| 134 | ret = snd_soc_dai_set_sysclk(dai, 0, MCLK_AUDIO_RATE, 0); | ||
| 135 | if (ret < 0) | ||
| 136 | return ret; | ||
| 137 | |||
| 138 | return 0; | ||
| 139 | } | ||
| 140 | |||
| 129 | static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd) | 141 | static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd) |
| 130 | { | 142 | { |
| 131 | struct snd_soc_dai *dai = rtd->codec_dai; | 143 | struct snd_soc_dai *dai = rtd->codec_dai; |
| @@ -172,17 +184,37 @@ static int speyside_late_probe(struct snd_soc_card *card) | |||
| 172 | return 0; | 184 | return 0; |
| 173 | } | 185 | } |
| 174 | 186 | ||
| 187 | static const struct snd_soc_pcm_stream dsp_codec_params = { | ||
| 188 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
| 189 | .rate_min = 48000, | ||
| 190 | .rate_max = 48000, | ||
| 191 | .channels_min = 2, | ||
| 192 | .channels_max = 2, | ||
| 193 | }; | ||
| 194 | |||
| 175 | static struct snd_soc_dai_link speyside_dai[] = { | 195 | static struct snd_soc_dai_link speyside_dai[] = { |
| 176 | { | 196 | { |
| 177 | .name = "CPU", | 197 | .name = "CPU-DSP", |
| 178 | .stream_name = "CPU", | 198 | .stream_name = "CPU-DSP", |
| 179 | .cpu_dai_name = "samsung-i2s.0", | 199 | .cpu_dai_name = "samsung-i2s.0", |
| 180 | .codec_dai_name = "wm8996-aif1", | 200 | .codec_dai_name = "wm0010-sdi1", |
| 181 | .platform_name = "samsung-audio", | 201 | .platform_name = "samsung-audio", |
| 202 | .codec_name = "spi0.0", | ||
| 203 | .init = speyside_wm0010_init, | ||
| 204 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
| 205 | | SND_SOC_DAIFMT_CBM_CFM, | ||
| 206 | }, | ||
| 207 | { | ||
| 208 | .name = "DSP-CODEC", | ||
| 209 | .stream_name = "DSP-CODEC", | ||
| 210 | .cpu_dai_name = "wm0010-sdi2", | ||
| 211 | .codec_dai_name = "wm8996-aif1", | ||
| 182 | .codec_name = "wm8996.1-001a", | 212 | .codec_name = "wm8996.1-001a", |
| 183 | .init = speyside_wm8996_init, | 213 | .init = speyside_wm8996_init, |
| 184 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 214 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
| 185 | | SND_SOC_DAIFMT_CBM_CFM, | 215 | | SND_SOC_DAIFMT_CBM_CFM, |
| 216 | .params = &dsp_codec_params, | ||
| 217 | .ignore_suspend = 1, | ||
| 186 | }, | 218 | }, |
| 187 | { | 219 | { |
| 188 | .name = "Baseband", | 220 | .name = "Baseband", |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 0540408a9fa9..5328ae5539f1 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
| @@ -1655,22 +1655,20 @@ static int fsi_probe(struct platform_device *pdev) | |||
| 1655 | irq = platform_get_irq(pdev, 0); | 1655 | irq = platform_get_irq(pdev, 0); |
| 1656 | if (!res || (int)irq <= 0) { | 1656 | if (!res || (int)irq <= 0) { |
| 1657 | dev_err(&pdev->dev, "Not enough FSI platform resources.\n"); | 1657 | dev_err(&pdev->dev, "Not enough FSI platform resources.\n"); |
| 1658 | ret = -ENODEV; | 1658 | return -ENODEV; |
| 1659 | goto exit; | ||
| 1660 | } | 1659 | } |
| 1661 | 1660 | ||
| 1662 | master = kzalloc(sizeof(*master), GFP_KERNEL); | 1661 | master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL); |
| 1663 | if (!master) { | 1662 | if (!master) { |
| 1664 | dev_err(&pdev->dev, "Could not allocate master\n"); | 1663 | dev_err(&pdev->dev, "Could not allocate master\n"); |
| 1665 | ret = -ENOMEM; | 1664 | return -ENOMEM; |
| 1666 | goto exit; | ||
| 1667 | } | 1665 | } |
| 1668 | 1666 | ||
| 1669 | master->base = ioremap_nocache(res->start, resource_size(res)); | 1667 | master->base = devm_ioremap_nocache(&pdev->dev, |
| 1668 | res->start, resource_size(res)); | ||
| 1670 | if (!master->base) { | 1669 | if (!master->base) { |
| 1671 | ret = -ENXIO; | ||
| 1672 | dev_err(&pdev->dev, "Unable to ioremap FSI registers.\n"); | 1670 | dev_err(&pdev->dev, "Unable to ioremap FSI registers.\n"); |
| 1673 | goto exit_kfree; | 1671 | return -ENXIO; |
| 1674 | } | 1672 | } |
| 1675 | 1673 | ||
| 1676 | /* master setting */ | 1674 | /* master setting */ |
| @@ -1686,7 +1684,7 @@ static int fsi_probe(struct platform_device *pdev) | |||
| 1686 | ret = fsi_stream_probe(&master->fsia, &pdev->dev); | 1684 | ret = fsi_stream_probe(&master->fsia, &pdev->dev); |
| 1687 | if (ret < 0) { | 1685 | if (ret < 0) { |
| 1688 | dev_err(&pdev->dev, "FSIA stream probe failed\n"); | 1686 | dev_err(&pdev->dev, "FSIA stream probe failed\n"); |
| 1689 | goto exit_iounmap; | 1687 | return ret; |
| 1690 | } | 1688 | } |
| 1691 | 1689 | ||
| 1692 | /* FSI B setting */ | 1690 | /* FSI B setting */ |
| @@ -1730,16 +1728,11 @@ exit_snd_soc: | |||
| 1730 | exit_free_irq: | 1728 | exit_free_irq: |
| 1731 | free_irq(irq, master); | 1729 | free_irq(irq, master); |
| 1732 | exit_fsib: | 1730 | exit_fsib: |
| 1731 | pm_runtime_disable(&pdev->dev); | ||
| 1733 | fsi_stream_remove(&master->fsib); | 1732 | fsi_stream_remove(&master->fsib); |
| 1734 | exit_fsia: | 1733 | exit_fsia: |
| 1735 | fsi_stream_remove(&master->fsia); | 1734 | fsi_stream_remove(&master->fsia); |
| 1736 | exit_iounmap: | 1735 | |
| 1737 | iounmap(master->base); | ||
| 1738 | pm_runtime_disable(&pdev->dev); | ||
| 1739 | exit_kfree: | ||
| 1740 | kfree(master); | ||
| 1741 | master = NULL; | ||
| 1742 | exit: | ||
| 1743 | return ret; | 1736 | return ret; |
| 1744 | } | 1737 | } |
| 1745 | 1738 | ||
| @@ -1758,9 +1751,6 @@ static int fsi_remove(struct platform_device *pdev) | |||
| 1758 | fsi_stream_remove(&master->fsia); | 1751 | fsi_stream_remove(&master->fsia); |
| 1759 | fsi_stream_remove(&master->fsib); | 1752 | fsi_stream_remove(&master->fsib); |
| 1760 | 1753 | ||
| 1761 | iounmap(master->base); | ||
| 1762 | kfree(master); | ||
| 1763 | |||
| 1764 | return 0; | 1754 | return 0; |
| 1765 | } | 1755 | } |
| 1766 | 1756 | ||
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c new file mode 100644 index 000000000000..967d0e173e1b --- /dev/null +++ b/sound/soc/soc-compress.c | |||
| @@ -0,0 +1,294 @@ | |||
| 1 | /* | ||
| 2 | * soc-compress.c -- ALSA SoC Compress | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Intel Corp. | ||
| 5 | * | ||
| 6 | * Authors: Namarta Kohli <namartax.kohli@intel.com> | ||
| 7 | * Ramesh Babu K V <ramesh.babu@linux.intel.com> | ||
| 8 | * Vinod Koul <vinod.koul@linux.intel.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms of the GNU General Public License as published by the | ||
| 12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 13 | * option) any later version. | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/delay.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <linux/workqueue.h> | ||
| 22 | #include <sound/core.h> | ||
| 23 | #include <sound/compress_params.h> | ||
| 24 | #include <sound/compress_driver.h> | ||
| 25 | #include <sound/soc.h> | ||
| 26 | #include <sound/initval.h> | ||
| 27 | |||
| 28 | static int soc_compr_open(struct snd_compr_stream *cstream) | ||
| 29 | { | ||
| 30 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
| 31 | struct snd_soc_platform *platform = rtd->platform; | ||
| 32 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
| 33 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
| 34 | int ret = 0; | ||
| 35 | |||
| 36 | if (platform->driver->compr_ops && platform->driver->compr_ops->open) { | ||
| 37 | ret = platform->driver->compr_ops->open(cstream); | ||
| 38 | if (ret < 0) { | ||
| 39 | pr_err("compress asoc: can't open platform %s\n", platform->name); | ||
| 40 | goto out; | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) { | ||
| 45 | ret = rtd->dai_link->compr_ops->startup(cstream); | ||
| 46 | if (ret < 0) { | ||
| 47 | pr_err("compress asoc: %s startup failed\n", rtd->dai_link->name); | ||
| 48 | goto machine_err; | ||
| 49 | } | ||
| 50 | } | ||
| 51 | |||
| 52 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | ||
| 53 | cpu_dai->playback_active++; | ||
| 54 | codec_dai->playback_active++; | ||
| 55 | } else { | ||
| 56 | cpu_dai->capture_active++; | ||
| 57 | codec_dai->capture_active++; | ||
| 58 | } | ||
| 59 | |||
| 60 | cpu_dai->active++; | ||
| 61 | codec_dai->active++; | ||
| 62 | rtd->codec->active++; | ||
| 63 | |||
| 64 | return 0; | ||
| 65 | |||
| 66 | machine_err: | ||
| 67 | if (platform->driver->compr_ops && platform->driver->compr_ops->free) | ||
| 68 | platform->driver->compr_ops->free(cstream); | ||
| 69 | out: | ||
| 70 | return ret; | ||
| 71 | } | ||
| 72 | |||
| 73 | static int soc_compr_free(struct snd_compr_stream *cstream) | ||
| 74 | { | ||
| 75 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
| 76 | struct snd_soc_platform *platform = rtd->platform; | ||
| 77 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
| 78 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
| 79 | struct snd_soc_codec *codec = rtd->codec; | ||
| 80 | |||
| 81 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | ||
| 82 | cpu_dai->playback_active--; | ||
| 83 | codec_dai->playback_active--; | ||
| 84 | } else { | ||
| 85 | cpu_dai->capture_active--; | ||
| 86 | codec_dai->capture_active--; | ||
| 87 | } | ||
| 88 | |||
| 89 | snd_soc_dai_digital_mute(codec_dai, 1); | ||
| 90 | |||
| 91 | cpu_dai->active--; | ||
| 92 | codec_dai->active--; | ||
| 93 | codec->active--; | ||
| 94 | |||
| 95 | if (!cpu_dai->active) | ||
| 96 | cpu_dai->rate = 0; | ||
| 97 | |||
| 98 | if (!codec_dai->active) | ||
| 99 | codec_dai->rate = 0; | ||
| 100 | |||
| 101 | |||
| 102 | if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown) | ||
| 103 | rtd->dai_link->compr_ops->shutdown(cstream); | ||
| 104 | |||
| 105 | if (platform->driver->compr_ops && platform->driver->compr_ops->free) | ||
| 106 | platform->driver->compr_ops->free(cstream); | ||
| 107 | cpu_dai->runtime = NULL; | ||
| 108 | |||
| 109 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | ||
| 110 | if (!rtd->pmdown_time || codec->ignore_pmdown_time || | ||
| 111 | rtd->dai_link->ignore_pmdown_time) { | ||
| 112 | snd_soc_dapm_stream_event(rtd, | ||
| 113 | SNDRV_PCM_STREAM_PLAYBACK, | ||
| 114 | SND_SOC_DAPM_STREAM_STOP); | ||
| 115 | } else | ||
| 116 | codec_dai->pop_wait = 1; | ||
| 117 | schedule_delayed_work(&rtd->delayed_work, | ||
| 118 | msecs_to_jiffies(rtd->pmdown_time)); | ||
| 119 | } else { | ||
| 120 | /* capture streams can be powered down now */ | ||
| 121 | snd_soc_dapm_stream_event(rtd, | ||
| 122 | SNDRV_PCM_STREAM_CAPTURE, | ||
| 123 | SND_SOC_DAPM_STREAM_STOP); | ||
| 124 | } | ||
| 125 | |||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) | ||
| 130 | { | ||
| 131 | |||
| 132 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
| 133 | struct snd_soc_platform *platform = rtd->platform; | ||
| 134 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
| 135 | int ret = 0; | ||
| 136 | |||
| 137 | if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) { | ||
| 138 | ret = platform->driver->compr_ops->trigger(cstream, cmd); | ||
| 139 | if (ret < 0) | ||
| 140 | return ret; | ||
| 141 | } | ||
| 142 | |||
| 143 | if (cmd == SNDRV_PCM_TRIGGER_START) | ||
| 144 | snd_soc_dai_digital_mute(codec_dai, 0); | ||
| 145 | else if (cmd == SNDRV_PCM_TRIGGER_STOP) | ||
| 146 | snd_soc_dai_digital_mute(codec_dai, 1); | ||
| 147 | |||
| 148 | return ret; | ||
| 149 | } | ||
| 150 | |||
| 151 | static int soc_compr_set_params(struct snd_compr_stream *cstream, | ||
| 152 | struct snd_compr_params *params) | ||
| 153 | { | ||
| 154 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
| 155 | struct snd_soc_platform *platform = rtd->platform; | ||
| 156 | int ret = 0; | ||
| 157 | |||
| 158 | /* first we call set_params for the platform driver | ||
| 159 | * this should configure the soc side | ||
| 160 | * if the machine has compressed ops then we call that as well | ||
| 161 | * expectation is that platform and machine will configure everything | ||
| 162 | * for this compress path, like configuring pcm port for codec | ||
| 163 | */ | ||
| 164 | if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) { | ||
| 165 | ret = platform->driver->compr_ops->set_params(cstream, params); | ||
| 166 | if (ret < 0) | ||
| 167 | return ret; | ||
| 168 | } | ||
| 169 | |||
| 170 | if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) { | ||
| 171 | ret = rtd->dai_link->compr_ops->set_params(cstream); | ||
| 172 | if (ret < 0) | ||
| 173 | return ret; | ||
| 174 | } | ||
| 175 | |||
| 176 | snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, | ||
| 177 | SND_SOC_DAPM_STREAM_START); | ||
| 178 | |||
| 179 | return ret; | ||
| 180 | } | ||
| 181 | |||
| 182 | static int soc_compr_get_params(struct snd_compr_stream *cstream, | ||
| 183 | struct snd_codec *params) | ||
| 184 | { | ||
| 185 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
| 186 | struct snd_soc_platform *platform = rtd->platform; | ||
| 187 | int ret = 0; | ||
| 188 | |||
| 189 | if (platform->driver->compr_ops && platform->driver->compr_ops->get_params) | ||
| 190 | ret = platform->driver->compr_ops->get_params(cstream, params); | ||
| 191 | |||
| 192 | return ret; | ||
| 193 | } | ||
| 194 | |||
| 195 | static int soc_compr_get_caps(struct snd_compr_stream *cstream, | ||
| 196 | struct snd_compr_caps *caps) | ||
| 197 | { | ||
| 198 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
| 199 | struct snd_soc_platform *platform = rtd->platform; | ||
| 200 | int ret = 0; | ||
| 201 | |||
| 202 | if (platform->driver->compr_ops && platform->driver->compr_ops->get_caps) | ||
| 203 | ret = platform->driver->compr_ops->get_caps(cstream, caps); | ||
| 204 | |||
| 205 | return ret; | ||
| 206 | } | ||
| 207 | |||
| 208 | static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, | ||
| 209 | struct snd_compr_codec_caps *codec) | ||
| 210 | { | ||
| 211 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
| 212 | struct snd_soc_platform *platform = rtd->platform; | ||
| 213 | int ret = 0; | ||
| 214 | |||
| 215 | if (platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps) | ||
| 216 | ret = platform->driver->compr_ops->get_codec_caps(cstream, codec); | ||
| 217 | |||
| 218 | return ret; | ||
| 219 | } | ||
| 220 | |||
| 221 | static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) | ||
| 222 | { | ||
| 223 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
| 224 | struct snd_soc_platform *platform = rtd->platform; | ||
| 225 | int ret = 0; | ||
| 226 | |||
| 227 | if (platform->driver->compr_ops && platform->driver->compr_ops->ack) | ||
| 228 | ret = platform->driver->compr_ops->ack(cstream, bytes); | ||
| 229 | |||
| 230 | return ret; | ||
| 231 | } | ||
| 232 | |||
| 233 | static int soc_compr_pointer(struct snd_compr_stream *cstream, | ||
| 234 | struct snd_compr_tstamp *tstamp) | ||
| 235 | { | ||
| 236 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
| 237 | struct snd_soc_platform *platform = rtd->platform; | ||
| 238 | |||
| 239 | if (platform->driver->compr_ops && platform->driver->compr_ops->pointer) | ||
| 240 | platform->driver->compr_ops->pointer(cstream, tstamp); | ||
| 241 | |||
| 242 | return 0; | ||
| 243 | } | ||
| 244 | |||
| 245 | /* ASoC Compress operations */ | ||
| 246 | static struct snd_compr_ops soc_compr_ops = { | ||
| 247 | .open = soc_compr_open, | ||
| 248 | .free = soc_compr_free, | ||
| 249 | .set_params = soc_compr_set_params, | ||
| 250 | .get_params = soc_compr_get_params, | ||
| 251 | .trigger = soc_compr_trigger, | ||
| 252 | .pointer = soc_compr_pointer, | ||
| 253 | .ack = soc_compr_ack, | ||
| 254 | .get_caps = soc_compr_get_caps, | ||
| 255 | .get_codec_caps = soc_compr_get_codec_caps | ||
| 256 | }; | ||
| 257 | |||
| 258 | /* create a new compress */ | ||
| 259 | int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) | ||
| 260 | { | ||
| 261 | struct snd_soc_codec *codec = rtd->codec; | ||
| 262 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
| 263 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
| 264 | struct snd_compr *compr; | ||
| 265 | char new_name[64]; | ||
| 266 | int ret = 0, direction = 0; | ||
| 267 | |||
| 268 | /* check client and interface hw capabilities */ | ||
| 269 | snprintf(new_name, sizeof(new_name), "%s %s-%d", | ||
| 270 | rtd->dai_link->stream_name, codec_dai->name, num); | ||
| 271 | direction = SND_COMPRESS_PLAYBACK; | ||
| 272 | compr = kzalloc(sizeof(*compr), GFP_KERNEL); | ||
| 273 | if (compr == NULL) { | ||
| 274 | snd_printk(KERN_ERR "Cannot allocate compr\n"); | ||
| 275 | return -ENOMEM; | ||
| 276 | } | ||
| 277 | |||
| 278 | compr->ops = &soc_compr_ops; | ||
| 279 | mutex_init(&compr->lock); | ||
| 280 | ret = snd_compress_new(rtd->card->snd_card, num, direction, compr); | ||
| 281 | if (ret < 0) { | ||
| 282 | pr_err("compress asoc: can't create compress for codec %s\n", | ||
| 283 | codec->name); | ||
| 284 | kfree(compr); | ||
| 285 | return ret; | ||
| 286 | } | ||
| 287 | |||
| 288 | rtd->compr = compr; | ||
| 289 | compr->private_data = rtd; | ||
| 290 | |||
| 291 | printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name, | ||
| 292 | cpu_dai->name); | ||
| 293 | return ret; | ||
| 294 | } | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index cf3d0b0c71b9..d1198627fc40 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
| @@ -609,6 +609,10 @@ int snd_soc_suspend(struct device *dev) | |||
| 609 | SND_SOC_DAPM_STREAM_SUSPEND); | 609 | SND_SOC_DAPM_STREAM_SUSPEND); |
| 610 | } | 610 | } |
| 611 | 611 | ||
| 612 | /* Recheck all analogue paths too */ | ||
| 613 | dapm_mark_io_dirty(&card->dapm); | ||
| 614 | snd_soc_dapm_sync(&card->dapm); | ||
| 615 | |||
| 612 | /* suspend all CODECs */ | 616 | /* suspend all CODECs */ |
| 613 | list_for_each_entry(codec, &card->codec_dev_list, card_list) { | 617 | list_for_each_entry(codec, &card->codec_dev_list, card_list) { |
| 614 | /* If there are paths active then the CODEC will be held with | 618 | /* If there are paths active then the CODEC will be held with |
| @@ -631,6 +635,8 @@ int snd_soc_suspend(struct device *dev) | |||
| 631 | codec->driver->suspend(codec); | 635 | codec->driver->suspend(codec); |
| 632 | codec->suspended = 1; | 636 | codec->suspended = 1; |
| 633 | codec->cache_sync = 1; | 637 | codec->cache_sync = 1; |
| 638 | if (codec->using_regmap) | ||
| 639 | regcache_mark_dirty(codec->control_data); | ||
| 634 | break; | 640 | break; |
| 635 | default: | 641 | default: |
| 636 | dev_dbg(codec->dev, "CODEC is on over suspend\n"); | 642 | dev_dbg(codec->dev, "CODEC is on over suspend\n"); |
| @@ -756,6 +762,10 @@ static void soc_resume_deferred(struct work_struct *work) | |||
| 756 | 762 | ||
| 757 | /* userspace can access us now we are back as we were before */ | 763 | /* userspace can access us now we are back as we were before */ |
| 758 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0); | 764 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D0); |
| 765 | |||
| 766 | /* Recheck all analogue paths too */ | ||
| 767 | dapm_mark_io_dirty(&card->dapm); | ||
| 768 | snd_soc_dapm_sync(&card->dapm); | ||
| 759 | } | 769 | } |
| 760 | 770 | ||
| 761 | /* powers up audio subsystem after a suspend */ | 771 | /* powers up audio subsystem after a suspend */ |
| @@ -1388,37 +1398,48 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
| 1388 | if (ret < 0) | 1398 | if (ret < 0) |
| 1389 | pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret); | 1399 | pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret); |
| 1390 | 1400 | ||
| 1391 | if (!dai_link->params) { | 1401 | if (cpu_dai->driver->compress_dai) { |
| 1392 | /* create the pcm */ | 1402 | /*create compress_device"*/ |
| 1393 | ret = soc_new_pcm(rtd, num); | 1403 | ret = soc_new_compress(rtd, num); |
| 1394 | if (ret < 0) { | 1404 | if (ret < 0) { |
| 1395 | pr_err("asoc: can't create pcm %s :%d\n", | 1405 | pr_err("asoc: can't create compress %s\n", |
| 1396 | dai_link->stream_name, ret); | 1406 | dai_link->stream_name); |
| 1397 | return ret; | 1407 | return ret; |
| 1398 | } | 1408 | } |
| 1399 | } else { | 1409 | } else { |
| 1400 | /* link the DAI widgets */ | 1410 | |
| 1401 | play_w = codec_dai->playback_widget; | 1411 | if (!dai_link->params) { |
| 1402 | capture_w = cpu_dai->capture_widget; | 1412 | /* create the pcm */ |
| 1403 | if (play_w && capture_w) { | 1413 | ret = soc_new_pcm(rtd, num); |
| 1404 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, | 1414 | if (ret < 0) { |
| 1405 | capture_w, play_w); | 1415 | pr_err("asoc: can't create pcm %s :%d\n", |
| 1406 | if (ret != 0) { | 1416 | dai_link->stream_name, ret); |
| 1407 | dev_err(card->dev, "Can't link %s to %s: %d\n", | ||
| 1408 | play_w->name, capture_w->name, ret); | ||
| 1409 | return ret; | 1417 | return ret; |
| 1410 | } | 1418 | } |
| 1411 | } | 1419 | } else { |
| 1420 | /* link the DAI widgets */ | ||
| 1421 | play_w = codec_dai->playback_widget; | ||
| 1422 | capture_w = cpu_dai->capture_widget; | ||
| 1423 | if (play_w && capture_w) { | ||
| 1424 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, | ||
| 1425 | capture_w, play_w); | ||
| 1426 | if (ret != 0) { | ||
| 1427 | dev_err(card->dev, "Can't link %s to %s: %d\n", | ||
| 1428 | play_w->name, capture_w->name, ret); | ||
| 1429 | return ret; | ||
| 1430 | } | ||
| 1431 | } | ||
| 1412 | 1432 | ||
| 1413 | play_w = cpu_dai->playback_widget; | 1433 | play_w = cpu_dai->playback_widget; |
| 1414 | capture_w = codec_dai->capture_widget; | 1434 | capture_w = codec_dai->capture_widget; |
| 1415 | if (play_w && capture_w) { | 1435 | if (play_w && capture_w) { |
| 1416 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, | 1436 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, |
| 1417 | capture_w, play_w); | 1437 | capture_w, play_w); |
| 1418 | if (ret != 0) { | 1438 | if (ret != 0) { |
| 1419 | dev_err(card->dev, "Can't link %s to %s: %d\n", | 1439 | dev_err(card->dev, "Can't link %s to %s: %d\n", |
| 1420 | play_w->name, capture_w->name, ret); | 1440 | play_w->name, capture_w->name, ret); |
| 1421 | return ret; | 1441 | return ret; |
| 1442 | } | ||
| 1422 | } | 1443 | } |
| 1423 | } | 1444 | } |
| 1424 | } | 1445 | } |
| @@ -1816,7 +1837,6 @@ base_error: | |||
| 1816 | static int soc_probe(struct platform_device *pdev) | 1837 | static int soc_probe(struct platform_device *pdev) |
| 1817 | { | 1838 | { |
| 1818 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 1839 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
| 1819 | int ret = 0; | ||
| 1820 | 1840 | ||
| 1821 | /* | 1841 | /* |
| 1822 | * no card, so machine driver should be registering card | 1842 | * no card, so machine driver should be registering card |
| @@ -1832,13 +1852,7 @@ static int soc_probe(struct platform_device *pdev) | |||
| 1832 | /* Bodge while we unpick instantiation */ | 1852 | /* Bodge while we unpick instantiation */ |
| 1833 | card->dev = &pdev->dev; | 1853 | card->dev = &pdev->dev; |
| 1834 | 1854 | ||
| 1835 | ret = snd_soc_register_card(card); | 1855 | return snd_soc_register_card(card); |
| 1836 | if (ret != 0) { | ||
| 1837 | dev_err(&pdev->dev, "Failed to register card\n"); | ||
| 1838 | return ret; | ||
| 1839 | } | ||
| 1840 | |||
| 1841 | return 0; | ||
| 1842 | } | 1856 | } |
| 1843 | 1857 | ||
| 1844 | static int soc_cleanup_card_resources(struct snd_soc_card *card) | 1858 | static int soc_cleanup_card_resources(struct snd_soc_card *card) |
| @@ -2399,16 +2413,14 @@ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, | |||
| 2399 | { | 2413 | { |
| 2400 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2414 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
| 2401 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2415 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 2402 | unsigned int val, bitmask; | 2416 | unsigned int val; |
| 2403 | 2417 | ||
| 2404 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | ||
| 2405 | ; | ||
| 2406 | val = snd_soc_read(codec, e->reg); | 2418 | val = snd_soc_read(codec, e->reg); |
| 2407 | ucontrol->value.enumerated.item[0] | 2419 | ucontrol->value.enumerated.item[0] |
| 2408 | = (val >> e->shift_l) & (bitmask - 1); | 2420 | = (val >> e->shift_l) & e->mask; |
| 2409 | if (e->shift_l != e->shift_r) | 2421 | if (e->shift_l != e->shift_r) |
| 2410 | ucontrol->value.enumerated.item[1] = | 2422 | ucontrol->value.enumerated.item[1] = |
| 2411 | (val >> e->shift_r) & (bitmask - 1); | 2423 | (val >> e->shift_r) & e->mask; |
| 2412 | 2424 | ||
| 2413 | return 0; | 2425 | return 0; |
| 2414 | } | 2426 | } |
| @@ -2429,19 +2441,17 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, | |||
| 2429 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2441 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
| 2430 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2442 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 2431 | unsigned int val; | 2443 | unsigned int val; |
| 2432 | unsigned int mask, bitmask; | 2444 | unsigned int mask; |
| 2433 | 2445 | ||
| 2434 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | ||
| 2435 | ; | ||
| 2436 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2446 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
| 2437 | return -EINVAL; | 2447 | return -EINVAL; |
| 2438 | val = ucontrol->value.enumerated.item[0] << e->shift_l; | 2448 | val = ucontrol->value.enumerated.item[0] << e->shift_l; |
| 2439 | mask = (bitmask - 1) << e->shift_l; | 2449 | mask = e->mask << e->shift_l; |
| 2440 | if (e->shift_l != e->shift_r) { | 2450 | if (e->shift_l != e->shift_r) { |
| 2441 | if (ucontrol->value.enumerated.item[1] > e->max - 1) | 2451 | if (ucontrol->value.enumerated.item[1] > e->max - 1) |
| 2442 | return -EINVAL; | 2452 | return -EINVAL; |
| 2443 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | 2453 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; |
| 2444 | mask |= (bitmask - 1) << e->shift_r; | 2454 | mask |= e->mask << e->shift_r; |
| 2445 | } | 2455 | } |
| 2446 | 2456 | ||
| 2447 | return snd_soc_update_bits_locked(codec, e->reg, mask, val); | 2457 | return snd_soc_update_bits_locked(codec, e->reg, mask, val); |
| @@ -3717,6 +3727,9 @@ int snd_soc_register_dai(struct device *dev, | |||
| 3717 | } | 3727 | } |
| 3718 | } | 3728 | } |
| 3719 | 3729 | ||
| 3730 | if (!dai->codec) | ||
| 3731 | dai->dapm.idle_bias_off = 1; | ||
| 3732 | |||
| 3720 | list_add(&dai->list, &dai_list); | 3733 | list_add(&dai->list, &dai_list); |
| 3721 | 3734 | ||
| 3722 | mutex_unlock(&client_mutex); | 3735 | mutex_unlock(&client_mutex); |
| @@ -3805,6 +3818,9 @@ int snd_soc_register_dais(struct device *dev, | |||
| 3805 | } | 3818 | } |
| 3806 | } | 3819 | } |
| 3807 | 3820 | ||
| 3821 | if (!dai->codec) | ||
| 3822 | dai->dapm.idle_bias_off = 1; | ||
| 3823 | |||
| 3808 | list_add(&dai->list, &dai_list); | 3824 | list_add(&dai->list, &dai_list); |
| 3809 | 3825 | ||
| 3810 | mutex_unlock(&client_mutex); | 3826 | mutex_unlock(&client_mutex); |
| @@ -4034,8 +4050,6 @@ int snd_soc_register_codec(struct device *dev, | |||
| 4034 | return 0; | 4050 | return 0; |
| 4035 | 4051 | ||
| 4036 | fail: | 4052 | fail: |
| 4037 | kfree(codec->reg_def_copy); | ||
| 4038 | codec->reg_def_copy = NULL; | ||
| 4039 | kfree(codec->name); | 4053 | kfree(codec->name); |
| 4040 | kfree(codec); | 4054 | kfree(codec); |
| 4041 | return ret; | 4055 | return ret; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index f90139b5f50d..d0a4be38dc0f 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
| @@ -141,6 +141,28 @@ void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason) | |||
| 141 | } | 141 | } |
| 142 | EXPORT_SYMBOL_GPL(dapm_mark_dirty); | 142 | EXPORT_SYMBOL_GPL(dapm_mark_dirty); |
| 143 | 143 | ||
| 144 | void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm) | ||
| 145 | { | ||
| 146 | struct snd_soc_card *card = dapm->card; | ||
| 147 | struct snd_soc_dapm_widget *w; | ||
| 148 | |||
| 149 | mutex_lock(&card->dapm_mutex); | ||
| 150 | |||
| 151 | list_for_each_entry(w, &card->widgets, list) { | ||
| 152 | switch (w->id) { | ||
| 153 | case snd_soc_dapm_input: | ||
| 154 | case snd_soc_dapm_output: | ||
| 155 | dapm_mark_dirty(w, "Rechecking inputs and outputs"); | ||
| 156 | break; | ||
| 157 | default: | ||
| 158 | break; | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | mutex_unlock(&card->dapm_mutex); | ||
| 163 | } | ||
| 164 | EXPORT_SYMBOL_GPL(dapm_mark_io_dirty); | ||
| 165 | |||
| 144 | /* create a new dapm widget */ | 166 | /* create a new dapm widget */ |
| 145 | static inline struct snd_soc_dapm_widget *dapm_cnew_widget( | 167 | static inline struct snd_soc_dapm_widget *dapm_cnew_widget( |
| 146 | const struct snd_soc_dapm_widget *_widget) | 168 | const struct snd_soc_dapm_widget *_widget) |
| @@ -336,12 +358,10 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w, | |||
| 336 | case snd_soc_dapm_mux: { | 358 | case snd_soc_dapm_mux: { |
| 337 | struct soc_enum *e = (struct soc_enum *) | 359 | struct soc_enum *e = (struct soc_enum *) |
| 338 | w->kcontrol_news[i].private_value; | 360 | w->kcontrol_news[i].private_value; |
| 339 | int val, item, bitmask; | 361 | int val, item; |
| 340 | 362 | ||
| 341 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | ||
| 342 | ; | ||
| 343 | val = soc_widget_read(w, e->reg); | 363 | val = soc_widget_read(w, e->reg); |
| 344 | item = (val >> e->shift_l) & (bitmask - 1); | 364 | item = (val >> e->shift_l) & e->mask; |
| 345 | 365 | ||
| 346 | p->connect = 0; | 366 | p->connect = 0; |
| 347 | for (i = 0; i < e->max; i++) { | 367 | for (i = 0; i < e->max; i++) { |
| @@ -997,10 +1017,29 @@ EXPORT_SYMBOL_GPL(dapm_reg_event); | |||
| 997 | int dapm_regulator_event(struct snd_soc_dapm_widget *w, | 1017 | int dapm_regulator_event(struct snd_soc_dapm_widget *w, |
| 998 | struct snd_kcontrol *kcontrol, int event) | 1018 | struct snd_kcontrol *kcontrol, int event) |
| 999 | { | 1019 | { |
| 1000 | if (SND_SOC_DAPM_EVENT_ON(event)) | 1020 | int ret; |
| 1021 | |||
| 1022 | if (SND_SOC_DAPM_EVENT_ON(event)) { | ||
| 1023 | if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { | ||
| 1024 | ret = regulator_allow_bypass(w->regulator, true); | ||
| 1025 | if (ret != 0) | ||
| 1026 | dev_warn(w->dapm->dev, | ||
| 1027 | "Failed to bypass %s: %d\n", | ||
| 1028 | w->name, ret); | ||
| 1029 | } | ||
| 1030 | |||
| 1001 | return regulator_enable(w->regulator); | 1031 | return regulator_enable(w->regulator); |
| 1002 | else | 1032 | } else { |
| 1033 | if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) { | ||
| 1034 | ret = regulator_allow_bypass(w->regulator, false); | ||
| 1035 | if (ret != 0) | ||
| 1036 | dev_warn(w->dapm->dev, | ||
| 1037 | "Failed to unbypass %s: %d\n", | ||
| 1038 | w->name, ret); | ||
| 1039 | } | ||
| 1040 | |||
| 1003 | return regulator_disable_deferred(w->regulator, w->shift); | 1041 | return regulator_disable_deferred(w->regulator, w->shift); |
| 1042 | } | ||
| 1004 | } | 1043 | } |
| 1005 | EXPORT_SYMBOL_GPL(dapm_regulator_event); | 1044 | EXPORT_SYMBOL_GPL(dapm_regulator_event); |
| 1006 | 1045 | ||
| @@ -2658,15 +2697,13 @@ int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, | |||
| 2658 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); | 2697 | struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol); |
| 2659 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; | 2698 | struct snd_soc_dapm_widget *widget = wlist->widgets[0]; |
| 2660 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2699 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 2661 | unsigned int val, bitmask; | 2700 | unsigned int val; |
| 2662 | 2701 | ||
| 2663 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | ||
| 2664 | ; | ||
| 2665 | val = snd_soc_read(widget->codec, e->reg); | 2702 | val = snd_soc_read(widget->codec, e->reg); |
| 2666 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1); | 2703 | ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & e->mask; |
| 2667 | if (e->shift_l != e->shift_r) | 2704 | if (e->shift_l != e->shift_r) |
| 2668 | ucontrol->value.enumerated.item[1] = | 2705 | ucontrol->value.enumerated.item[1] = |
| 2669 | (val >> e->shift_r) & (bitmask - 1); | 2706 | (val >> e->shift_r) & e->mask; |
| 2670 | 2707 | ||
| 2671 | return 0; | 2708 | return 0; |
| 2672 | } | 2709 | } |
| @@ -2690,22 +2727,20 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, | |||
| 2690 | struct snd_soc_card *card = codec->card; | 2727 | struct snd_soc_card *card = codec->card; |
| 2691 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | 2728 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; |
| 2692 | unsigned int val, mux, change; | 2729 | unsigned int val, mux, change; |
| 2693 | unsigned int mask, bitmask; | 2730 | unsigned int mask; |
| 2694 | struct snd_soc_dapm_update update; | 2731 | struct snd_soc_dapm_update update; |
| 2695 | int wi; | 2732 | int wi; |
| 2696 | 2733 | ||
| 2697 | for (bitmask = 1; bitmask < e->max; bitmask <<= 1) | ||
| 2698 | ; | ||
| 2699 | if (ucontrol->value.enumerated.item[0] > e->max - 1) | 2734 | if (ucontrol->value.enumerated.item[0] > e->max - 1) |
| 2700 | return -EINVAL; | 2735 | return -EINVAL; |
| 2701 | mux = ucontrol->value.enumerated.item[0]; | 2736 | mux = ucontrol->value.enumerated.item[0]; |
| 2702 | val = mux << e->shift_l; | 2737 | val = mux << e->shift_l; |
| 2703 | mask = (bitmask - 1) << e->shift_l; | 2738 | mask = e->mask << e->shift_l; |
| 2704 | if (e->shift_l != e->shift_r) { | 2739 | if (e->shift_l != e->shift_r) { |
| 2705 | if (ucontrol->value.enumerated.item[1] > e->max - 1) | 2740 | if (ucontrol->value.enumerated.item[1] > e->max - 1) |
| 2706 | return -EINVAL; | 2741 | return -EINVAL; |
| 2707 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; | 2742 | val |= ucontrol->value.enumerated.item[1] << e->shift_r; |
| 2708 | mask |= (bitmask - 1) << e->shift_r; | 2743 | mask |= e->mask << e->shift_r; |
| 2709 | } | 2744 | } |
| 2710 | 2745 | ||
| 2711 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); | 2746 | mutex_lock_nested(&card->dapm_mutex, SND_SOC_DAPM_CLASS_RUNTIME); |
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c index 5df529eda251..bbc125748a38 100644 --- a/sound/soc/soc-dmaengine-pcm.c +++ b/sound/soc/soc-dmaengine-pcm.c | |||
| @@ -140,14 +140,18 @@ static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream) | |||
| 140 | struct dma_chan *chan = prtd->dma_chan; | 140 | struct dma_chan *chan = prtd->dma_chan; |
| 141 | struct dma_async_tx_descriptor *desc; | 141 | struct dma_async_tx_descriptor *desc; |
| 142 | enum dma_transfer_direction direction; | 142 | enum dma_transfer_direction direction; |
| 143 | unsigned long flags = DMA_CTRL_ACK; | ||
| 143 | 144 | ||
| 144 | direction = snd_pcm_substream_to_dma_direction(substream); | 145 | direction = snd_pcm_substream_to_dma_direction(substream); |
| 145 | 146 | ||
| 147 | if (!substream->runtime->no_period_wakeup) | ||
| 148 | flags |= DMA_PREP_INTERRUPT; | ||
| 149 | |||
| 146 | prtd->pos = 0; | 150 | prtd->pos = 0; |
| 147 | desc = dmaengine_prep_dma_cyclic(chan, | 151 | desc = dmaengine_prep_dma_cyclic(chan, |
| 148 | substream->runtime->dma_addr, | 152 | substream->runtime->dma_addr, |
| 149 | snd_pcm_lib_buffer_bytes(substream), | 153 | snd_pcm_lib_buffer_bytes(substream), |
| 150 | snd_pcm_lib_period_bytes(substream), direction); | 154 | snd_pcm_lib_period_bytes(substream), direction, flags); |
| 151 | 155 | ||
| 152 | if (!desc) | 156 | if (!desc) |
| 153 | return -ENOMEM; | 157 | return -ENOMEM; |
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 0c172938b82a..fa0fd8ddae90 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c | |||
| @@ -83,11 +83,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) | |||
| 83 | jack->status &= ~mask; | 83 | jack->status &= ~mask; |
| 84 | jack->status |= status & mask; | 84 | jack->status |= status & mask; |
| 85 | 85 | ||
| 86 | /* The DAPM sync is expensive enough to be worth skipping. | ||
| 87 | * However, empty mask means pin synchronization is desired. */ | ||
| 88 | if (mask && (jack->status == oldstatus)) | ||
| 89 | goto out; | ||
| 90 | |||
| 91 | trace_snd_soc_jack_notify(jack, status); | 86 | trace_snd_soc_jack_notify(jack, status); |
| 92 | 87 | ||
| 93 | list_for_each_entry(pin, &jack->pins, list) { | 88 | list_for_each_entry(pin, &jack->pins, list) { |
| @@ -109,7 +104,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) | |||
| 109 | 104 | ||
| 110 | snd_jack_report(jack->jack, jack->status); | 105 | snd_jack_report(jack->jack, jack->status); |
| 111 | 106 | ||
| 112 | out: | ||
| 113 | mutex_unlock(&jack->mutex); | 107 | mutex_unlock(&jack->mutex); |
| 114 | } | 108 | } |
| 115 | EXPORT_SYMBOL_GPL(snd_soc_jack_report); | 109 | EXPORT_SYMBOL_GPL(snd_soc_jack_report); |
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index d4f14e492341..cee13b7bfb94 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c | |||
| @@ -34,13 +34,12 @@ | |||
| 34 | #include <linux/gpio.h> | 34 | #include <linux/gpio.h> |
| 35 | #include <linux/of_gpio.h> | 35 | #include <linux/of_gpio.h> |
| 36 | 36 | ||
| 37 | #include <mach/tegra_wm8903_pdata.h> | ||
| 38 | |||
| 39 | #include <sound/core.h> | 37 | #include <sound/core.h> |
| 40 | #include <sound/jack.h> | 38 | #include <sound/jack.h> |
| 41 | #include <sound/pcm.h> | 39 | #include <sound/pcm.h> |
| 42 | #include <sound/pcm_params.h> | 40 | #include <sound/pcm_params.h> |
| 43 | #include <sound/soc.h> | 41 | #include <sound/soc.h> |
| 42 | #include <sound/tegra_wm8903.h> | ||
| 44 | 43 | ||
| 45 | #include "../codecs/wm8903.h" | 44 | #include "../codecs/wm8903.h" |
| 46 | 45 | ||
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 45e43b4057b0..be94bf9bf94f 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c | |||
| @@ -760,6 +760,9 @@ static int __devinit ux500_msp_drv_probe(struct platform_device *pdev) | |||
| 760 | drvdata = devm_kzalloc(&pdev->dev, | 760 | drvdata = devm_kzalloc(&pdev->dev, |
| 761 | sizeof(struct ux500_msp_i2s_drvdata), | 761 | sizeof(struct ux500_msp_i2s_drvdata), |
| 762 | GFP_KERNEL); | 762 | GFP_KERNEL); |
| 763 | if (!drvdata) | ||
| 764 | return -ENOMEM; | ||
| 765 | |||
| 763 | drvdata->fmt = 0; | 766 | drvdata->fmt = 0; |
| 764 | drvdata->slots = 1; | 767 | drvdata->slots = 1; |
| 765 | drvdata->tx_mask = 0x01; | 768 | drvdata->tx_mask = 0x01; |
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index e5c79ca42518..b7c996e77570 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c | |||
| @@ -689,6 +689,8 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, | |||
| 689 | 689 | ||
| 690 | *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL); | 690 | *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL); |
| 691 | msp = *msp_p; | 691 | msp = *msp_p; |
| 692 | if (!msp) | ||
| 693 | return -ENOMEM; | ||
| 692 | 694 | ||
| 693 | if (np) { | 695 | if (np) { |
| 694 | if (!platform_data) { | 696 | if (!platform_data) { |
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index b63b3a86d3f4..5701787c0e6b 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c | |||
| @@ -813,7 +813,7 @@ static int snd_amd7930_get_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem | |||
| 813 | default: | 813 | default: |
| 814 | swval = &amd->pgain; | 814 | swval = &amd->pgain; |
| 815 | break; | 815 | break; |
| 816 | }; | 816 | } |
| 817 | 817 | ||
| 818 | ucontrol->value.integer.value[0] = *swval; | 818 | ucontrol->value.integer.value[0] = *swval; |
| 819 | 819 | ||
| @@ -838,7 +838,7 @@ static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem | |||
| 838 | default: | 838 | default: |
| 839 | swval = &amd->pgain; | 839 | swval = &amd->pgain; |
| 840 | break; | 840 | break; |
| 841 | }; | 841 | } |
| 842 | 842 | ||
| 843 | spin_lock_irqsave(&amd->lock, flags); | 843 | spin_lock_irqsave(&amd->lock, flags); |
| 844 | 844 | ||
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index a6b0deb77746..ae35f5342e10 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c | |||
| @@ -592,7 +592,7 @@ static __u32 reverse_bytes(__u32 b, int len) | |||
| 592 | break; | 592 | break; |
| 593 | default: | 593 | default: |
| 594 | printk(KERN_ERR "DBRI reverse_bytes: unsupported length\n"); | 594 | printk(KERN_ERR "DBRI reverse_bytes: unsupported length\n"); |
| 595 | }; | 595 | } |
| 596 | 596 | ||
| 597 | return b; | 597 | return b; |
| 598 | } | 598 | } |
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c index 56ad923bf6b5..a1d9b0792a1e 100644 --- a/sound/usb/6fire/firmware.c +++ b/sound/usb/6fire/firmware.c | |||
| @@ -346,11 +346,10 @@ static int usb6fire_fw_check(u8 *version) | |||
| 346 | if (!memcmp(version, known_fw_versions + i, 4)) | 346 | if (!memcmp(version, known_fw_versions + i, 4)) |
| 347 | return 0; | 347 | return 0; |
| 348 | 348 | ||
| 349 | snd_printk(KERN_ERR PREFIX "invalid fimware version in device: " | 349 | snd_printk(KERN_ERR PREFIX "invalid fimware version in device: %*ph. " |
| 350 | "%02x %02x %02x %02x. " | ||
| 351 | "please reconnect to power. if this failure " | 350 | "please reconnect to power. if this failure " |
| 352 | "still happens, check your firmware installation.", | 351 | "still happens, check your firmware installation.", |
| 353 | version[0], version[1], version[2], version[3]); | 352 | 4, version); |
| 354 | return -EINVAL; | 353 | return -EINVAL; |
| 355 | } | 354 | } |
| 356 | 355 | ||
diff --git a/sound/usb/card.c b/sound/usb/card.c index 4a469f0cb6d4..561bb74fd364 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c | |||
| @@ -646,6 +646,8 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 646 | list_for_each(p, &chip->pcm_list) { | 646 | list_for_each(p, &chip->pcm_list) { |
| 647 | as = list_entry(p, struct snd_usb_stream, list); | 647 | as = list_entry(p, struct snd_usb_stream, list); |
| 648 | snd_pcm_suspend_all(as->pcm); | 648 | snd_pcm_suspend_all(as->pcm); |
| 649 | as->substream[0].need_setup_ep = | ||
| 650 | as->substream[1].need_setup_ep = true; | ||
| 649 | } | 651 | } |
| 650 | } | 652 | } |
| 651 | } else { | 653 | } else { |
diff --git a/sound/usb/card.h b/sound/usb/card.h index 2b9fffff23b6..afa4f9e9b27a 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h | |||
| @@ -92,6 +92,8 @@ struct snd_usb_endpoint { | |||
| 92 | unsigned char silence_value; | 92 | unsigned char silence_value; |
| 93 | unsigned int stride; | 93 | unsigned int stride; |
| 94 | int iface, alt_idx; | 94 | int iface, alt_idx; |
| 95 | int skip_packets; /* quirks for devices to ignore the first n packets | ||
| 96 | in a stream */ | ||
| 95 | 97 | ||
| 96 | spinlock_t lock; | 98 | spinlock_t lock; |
| 97 | struct list_head list; | 99 | struct list_head list; |
| @@ -105,6 +107,8 @@ struct snd_usb_substream { | |||
| 105 | int interface; /* current interface */ | 107 | int interface; /* current interface */ |
| 106 | int endpoint; /* assigned endpoint */ | 108 | int endpoint; /* assigned endpoint */ |
| 107 | struct audioformat *cur_audiofmt; /* current audioformat pointer (for hw_params callback) */ | 109 | struct audioformat *cur_audiofmt; /* current audioformat pointer (for hw_params callback) */ |
| 110 | snd_pcm_format_t pcm_format; /* current audio format (for hw_params callback) */ | ||
| 111 | unsigned int channels; /* current number of channels (for hw_params callback) */ | ||
| 108 | unsigned int cur_rate; /* current rate (for hw_params callback) */ | 112 | unsigned int cur_rate; /* current rate (for hw_params callback) */ |
| 109 | unsigned int period_bytes; /* current period bytes (for hw_params callback) */ | 113 | unsigned int period_bytes; /* current period bytes (for hw_params callback) */ |
| 110 | unsigned int altset_idx; /* USB data format: index of alternate setting */ | 114 | unsigned int altset_idx; /* USB data format: index of alternate setting */ |
| @@ -115,14 +119,13 @@ struct snd_usb_substream { | |||
| 115 | 119 | ||
| 116 | unsigned int hwptr_done; /* processed byte position in the buffer */ | 120 | unsigned int hwptr_done; /* processed byte position in the buffer */ |
| 117 | unsigned int transfer_done; /* processed frames since last period update */ | 121 | unsigned int transfer_done; /* processed frames since last period update */ |
| 118 | unsigned long active_mask; /* bitmask of active urbs */ | ||
| 119 | unsigned long unlink_mask; /* bitmask of unlinked urbs */ | ||
| 120 | 122 | ||
| 121 | /* data and sync endpoints for this stream */ | 123 | /* data and sync endpoints for this stream */ |
| 122 | unsigned int ep_num; /* the endpoint number */ | 124 | unsigned int ep_num; /* the endpoint number */ |
| 123 | struct snd_usb_endpoint *data_endpoint; | 125 | struct snd_usb_endpoint *data_endpoint; |
| 124 | struct snd_usb_endpoint *sync_endpoint; | 126 | struct snd_usb_endpoint *sync_endpoint; |
| 125 | unsigned long flags; | 127 | unsigned long flags; |
| 128 | bool need_setup_ep; /* (re)configure EP at prepare? */ | ||
| 126 | 129 | ||
| 127 | u64 formats; /* format bitmasks (all or'ed) */ | 130 | u64 formats; /* format bitmasks (all or'ed) */ |
| 128 | unsigned int num_formats; /* number of supported audio formats (list) */ | 131 | unsigned int num_formats; /* number of supported audio formats (list) */ |
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 060dccb9ec75..7f78c6d782b0 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include "card.h" | 31 | #include "card.h" |
| 32 | #include "endpoint.h" | 32 | #include "endpoint.h" |
| 33 | #include "pcm.h" | 33 | #include "pcm.h" |
| 34 | #include "quirks.h" | ||
| 34 | 35 | ||
| 35 | #define EP_FLAG_ACTIVATED 0 | 36 | #define EP_FLAG_ACTIVATED 0 |
| 36 | #define EP_FLAG_RUNNING 1 | 37 | #define EP_FLAG_RUNNING 1 |
| @@ -170,6 +171,11 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep, | |||
| 170 | { | 171 | { |
| 171 | struct urb *urb = urb_ctx->urb; | 172 | struct urb *urb = urb_ctx->urb; |
| 172 | 173 | ||
| 174 | if (unlikely(ep->skip_packets > 0)) { | ||
| 175 | ep->skip_packets--; | ||
| 176 | return; | ||
| 177 | } | ||
| 178 | |||
| 173 | if (ep->sync_slave) | 179 | if (ep->sync_slave) |
| 174 | snd_usb_handle_sync_urb(ep->sync_slave, ep, urb); | 180 | snd_usb_handle_sync_urb(ep->sync_slave, ep, urb); |
| 175 | 181 | ||
| @@ -567,20 +573,19 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force) | |||
| 567 | * configure a data endpoint | 573 | * configure a data endpoint |
| 568 | */ | 574 | */ |
| 569 | static int data_ep_set_params(struct snd_usb_endpoint *ep, | 575 | static int data_ep_set_params(struct snd_usb_endpoint *ep, |
| 570 | struct snd_pcm_hw_params *hw_params, | 576 | snd_pcm_format_t pcm_format, |
| 577 | unsigned int channels, | ||
| 578 | unsigned int period_bytes, | ||
| 571 | struct audioformat *fmt, | 579 | struct audioformat *fmt, |
| 572 | struct snd_usb_endpoint *sync_ep) | 580 | struct snd_usb_endpoint *sync_ep) |
| 573 | { | 581 | { |
| 574 | unsigned int maxsize, i, urb_packs, total_packs, packs_per_ms; | 582 | unsigned int maxsize, i, urb_packs, total_packs, packs_per_ms; |
| 575 | int period_bytes = params_period_bytes(hw_params); | ||
| 576 | int format = params_format(hw_params); | ||
| 577 | int is_playback = usb_pipeout(ep->pipe); | 583 | int is_playback = usb_pipeout(ep->pipe); |
| 578 | int frame_bits = snd_pcm_format_physical_width(params_format(hw_params)) * | 584 | int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels; |
| 579 | params_channels(hw_params); | ||
| 580 | 585 | ||
| 581 | ep->datainterval = fmt->datainterval; | 586 | ep->datainterval = fmt->datainterval; |
| 582 | ep->stride = frame_bits >> 3; | 587 | ep->stride = frame_bits >> 3; |
| 583 | ep->silence_value = format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0; | 588 | ep->silence_value = pcm_format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0; |
| 584 | 589 | ||
| 585 | /* calculate max. frequency */ | 590 | /* calculate max. frequency */ |
| 586 | if (ep->maxpacksize) { | 591 | if (ep->maxpacksize) { |
| @@ -693,7 +698,6 @@ out_of_memory: | |||
| 693 | * configure a sync endpoint | 698 | * configure a sync endpoint |
| 694 | */ | 699 | */ |
| 695 | static int sync_ep_set_params(struct snd_usb_endpoint *ep, | 700 | static int sync_ep_set_params(struct snd_usb_endpoint *ep, |
| 696 | struct snd_pcm_hw_params *hw_params, | ||
| 697 | struct audioformat *fmt) | 701 | struct audioformat *fmt) |
| 698 | { | 702 | { |
| 699 | int i; | 703 | int i; |
| @@ -736,7 +740,10 @@ out_of_memory: | |||
| 736 | * snd_usb_endpoint_set_params: configure an snd_usb_endpoint | 740 | * snd_usb_endpoint_set_params: configure an snd_usb_endpoint |
| 737 | * | 741 | * |
| 738 | * @ep: the snd_usb_endpoint to configure | 742 | * @ep: the snd_usb_endpoint to configure |
| 739 | * @hw_params: the hardware parameters | 743 | * @pcm_format: the audio fomat. |
| 744 | * @channels: the number of audio channels. | ||
| 745 | * @period_bytes: the number of bytes in one alsa period. | ||
| 746 | * @rate: the frame rate. | ||
| 740 | * @fmt: the USB audio format information | 747 | * @fmt: the USB audio format information |
| 741 | * @sync_ep: the sync endpoint to use, if any | 748 | * @sync_ep: the sync endpoint to use, if any |
| 742 | * | 749 | * |
| @@ -745,7 +752,10 @@ out_of_memory: | |||
| 745 | * An endpoint that is already running can not be reconfigured. | 752 | * An endpoint that is already running can not be reconfigured. |
| 746 | */ | 753 | */ |
| 747 | int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, | 754 | int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, |
| 748 | struct snd_pcm_hw_params *hw_params, | 755 | snd_pcm_format_t pcm_format, |
| 756 | unsigned int channels, | ||
| 757 | unsigned int period_bytes, | ||
| 758 | unsigned int rate, | ||
| 749 | struct audioformat *fmt, | 759 | struct audioformat *fmt, |
| 750 | struct snd_usb_endpoint *sync_ep) | 760 | struct snd_usb_endpoint *sync_ep) |
| 751 | { | 761 | { |
| @@ -765,9 +775,9 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, | |||
| 765 | ep->fill_max = !!(fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX); | 775 | ep->fill_max = !!(fmt->attributes & UAC_EP_CS_ATTR_FILL_MAX); |
| 766 | 776 | ||
| 767 | if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_FULL) | 777 | if (snd_usb_get_speed(ep->chip->dev) == USB_SPEED_FULL) |
| 768 | ep->freqn = get_usb_full_speed_rate(params_rate(hw_params)); | 778 | ep->freqn = get_usb_full_speed_rate(rate); |
| 769 | else | 779 | else |
| 770 | ep->freqn = get_usb_high_speed_rate(params_rate(hw_params)); | 780 | ep->freqn = get_usb_high_speed_rate(rate); |
| 771 | 781 | ||
| 772 | /* calculate the frequency in 16.16 format */ | 782 | /* calculate the frequency in 16.16 format */ |
| 773 | ep->freqm = ep->freqn; | 783 | ep->freqm = ep->freqn; |
| @@ -777,10 +787,11 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, | |||
| 777 | 787 | ||
| 778 | switch (ep->type) { | 788 | switch (ep->type) { |
| 779 | case SND_USB_ENDPOINT_TYPE_DATA: | 789 | case SND_USB_ENDPOINT_TYPE_DATA: |
| 780 | err = data_ep_set_params(ep, hw_params, fmt, sync_ep); | 790 | err = data_ep_set_params(ep, pcm_format, channels, |
| 791 | period_bytes, fmt, sync_ep); | ||
| 781 | break; | 792 | break; |
| 782 | case SND_USB_ENDPOINT_TYPE_SYNC: | 793 | case SND_USB_ENDPOINT_TYPE_SYNC: |
| 783 | err = sync_ep_set_params(ep, hw_params, fmt); | 794 | err = sync_ep_set_params(ep, fmt); |
| 784 | break; | 795 | break; |
| 785 | default: | 796 | default: |
| 786 | err = -EINVAL; | 797 | err = -EINVAL; |
| @@ -828,6 +839,8 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep) | |||
| 828 | ep->unlink_mask = 0; | 839 | ep->unlink_mask = 0; |
| 829 | ep->phase = 0; | 840 | ep->phase = 0; |
| 830 | 841 | ||
| 842 | snd_usb_endpoint_start_quirk(ep); | ||
| 843 | |||
| 831 | /* | 844 | /* |
| 832 | * If this endpoint has a data endpoint as implicit feedback source, | 845 | * If this endpoint has a data endpoint as implicit feedback source, |
| 833 | * don't start the urbs here. Instead, mark them all as available, | 846 | * don't start the urbs here. Instead, mark them all as available, |
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h index cbbbdf226d66..6376ccf10fd4 100644 --- a/sound/usb/endpoint.h +++ b/sound/usb/endpoint.h | |||
| @@ -9,7 +9,10 @@ struct snd_usb_endpoint *snd_usb_add_endpoint(struct snd_usb_audio *chip, | |||
| 9 | int ep_num, int direction, int type); | 9 | int ep_num, int direction, int type); |
| 10 | 10 | ||
| 11 | int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, | 11 | int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep, |
| 12 | struct snd_pcm_hw_params *hw_params, | 12 | snd_pcm_format_t pcm_format, |
| 13 | unsigned int channels, | ||
| 14 | unsigned int period_bytes, | ||
| 15 | unsigned int rate, | ||
| 13 | struct audioformat *fmt, | 16 | struct audioformat *fmt, |
| 14 | struct snd_usb_endpoint *sync_ep); | 17 | struct snd_usb_endpoint *sync_ep); |
| 15 | 18 | ||
diff --git a/sound/usb/helper.c b/sound/usb/helper.c index 9eed8f40b179..c1db28f874c2 100644 --- a/sound/usb/helper.c +++ b/sound/usb/helper.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | 21 | ||
| 22 | #include "usbaudio.h" | 22 | #include "usbaudio.h" |
| 23 | #include "helper.h" | 23 | #include "helper.h" |
| 24 | #include "quirks.h" | ||
| 24 | 25 | ||
| 25 | /* | 26 | /* |
| 26 | * combine bytes and get an integer value | 27 | * combine bytes and get an integer value |
| @@ -97,6 +98,10 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request, | |||
| 97 | memcpy(data, buf, size); | 98 | memcpy(data, buf, size); |
| 98 | kfree(buf); | 99 | kfree(buf); |
| 99 | } | 100 | } |
| 101 | |||
| 102 | snd_usb_ctl_msg_quirk(dev, pipe, request, requesttype, | ||
| 103 | value, index, data, size); | ||
| 104 | |||
| 100 | return err; | 105 | return err; |
| 101 | } | 106 | } |
| 102 | 107 | ||
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 4f40ba823163..fe56c9da38e9 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c | |||
| @@ -1267,6 +1267,13 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void | |||
| 1267 | /* disable non-functional volume control */ | 1267 | /* disable non-functional volume control */ |
| 1268 | master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME); | 1268 | master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME); |
| 1269 | break; | 1269 | break; |
| 1270 | case USB_ID(0x1130, 0xf211): | ||
| 1271 | snd_printk(KERN_INFO | ||
| 1272 | "usbmixer: volume control quirk for Tenx TP6911 Audio Headset\n"); | ||
| 1273 | /* disable non-functional volume control */ | ||
| 1274 | channels = 0; | ||
| 1275 | break; | ||
| 1276 | |||
| 1270 | } | 1277 | } |
| 1271 | if (channels > 0) | 1278 | if (channels > 0) |
| 1272 | first_ch_bits = snd_usb_combine_bytes(bmaControls + csize, csize); | 1279 | first_ch_bits = snd_usb_combine_bytes(bmaControls + csize, csize); |
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index f782ce19bf5a..55e19e1b80ec 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
| @@ -82,8 +82,7 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream | |||
| 82 | /* | 82 | /* |
| 83 | * find a matching audio format | 83 | * find a matching audio format |
| 84 | */ | 84 | */ |
| 85 | static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned int format, | 85 | static struct audioformat *find_format(struct snd_usb_substream *subs) |
| 86 | unsigned int rate, unsigned int channels) | ||
| 87 | { | 86 | { |
| 88 | struct list_head *p; | 87 | struct list_head *p; |
| 89 | struct audioformat *found = NULL; | 88 | struct audioformat *found = NULL; |
| @@ -92,16 +91,17 @@ static struct audioformat *find_format(struct snd_usb_substream *subs, unsigned | |||
| 92 | list_for_each(p, &subs->fmt_list) { | 91 | list_for_each(p, &subs->fmt_list) { |
| 93 | struct audioformat *fp; | 92 | struct audioformat *fp; |
| 94 | fp = list_entry(p, struct audioformat, list); | 93 | fp = list_entry(p, struct audioformat, list); |
| 95 | if (!(fp->formats & (1uLL << format))) | 94 | if (!(fp->formats & (1uLL << subs->pcm_format))) |
| 96 | continue; | 95 | continue; |
| 97 | if (fp->channels != channels) | 96 | if (fp->channels != subs->channels) |
| 98 | continue; | 97 | continue; |
| 99 | if (rate < fp->rate_min || rate > fp->rate_max) | 98 | if (subs->cur_rate < fp->rate_min || |
| 99 | subs->cur_rate > fp->rate_max) | ||
| 100 | continue; | 100 | continue; |
| 101 | if (! (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) { | 101 | if (! (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)) { |
| 102 | unsigned int i; | 102 | unsigned int i; |
| 103 | for (i = 0; i < fp->nr_rates; i++) | 103 | for (i = 0; i < fp->nr_rates; i++) |
| 104 | if (fp->rate_table[i] == rate) | 104 | if (fp->rate_table[i] == subs->cur_rate) |
| 105 | break; | 105 | break; |
| 106 | if (i >= fp->nr_rates) | 106 | if (i >= fp->nr_rates) |
| 107 | continue; | 107 | continue; |
| @@ -436,6 +436,42 @@ add_sync_ep: | |||
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | /* | 438 | /* |
| 439 | * configure endpoint params | ||
| 440 | * | ||
| 441 | * called during initial setup and upon resume | ||
| 442 | */ | ||
| 443 | static int configure_endpoint(struct snd_usb_substream *subs) | ||
| 444 | { | ||
| 445 | int ret; | ||
| 446 | |||
| 447 | mutex_lock(&subs->stream->chip->shutdown_mutex); | ||
| 448 | /* format changed */ | ||
| 449 | stop_endpoints(subs, 0, 0, 0); | ||
| 450 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, | ||
| 451 | subs->pcm_format, | ||
| 452 | subs->channels, | ||
| 453 | subs->period_bytes, | ||
| 454 | subs->cur_rate, | ||
| 455 | subs->cur_audiofmt, | ||
| 456 | subs->sync_endpoint); | ||
| 457 | if (ret < 0) | ||
| 458 | goto unlock; | ||
| 459 | |||
| 460 | if (subs->sync_endpoint) | ||
| 461 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, | ||
| 462 | subs->pcm_format, | ||
| 463 | subs->channels, | ||
| 464 | subs->period_bytes, | ||
| 465 | subs->cur_rate, | ||
| 466 | subs->cur_audiofmt, | ||
| 467 | NULL); | ||
| 468 | |||
| 469 | unlock: | ||
| 470 | mutex_unlock(&subs->stream->chip->shutdown_mutex); | ||
| 471 | return ret; | ||
| 472 | } | ||
| 473 | |||
| 474 | /* | ||
| 439 | * hw_params callback | 475 | * hw_params callback |
| 440 | * | 476 | * |
| 441 | * allocate a buffer and set the given audio format. | 477 | * allocate a buffer and set the given audio format. |
| @@ -450,63 +486,33 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, | |||
| 450 | { | 486 | { |
| 451 | struct snd_usb_substream *subs = substream->runtime->private_data; | 487 | struct snd_usb_substream *subs = substream->runtime->private_data; |
| 452 | struct audioformat *fmt; | 488 | struct audioformat *fmt; |
| 453 | unsigned int channels, rate, format; | 489 | int ret; |
| 454 | int ret, changed; | ||
| 455 | 490 | ||
| 456 | ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, | 491 | ret = snd_pcm_lib_alloc_vmalloc_buffer(substream, |
| 457 | params_buffer_bytes(hw_params)); | 492 | params_buffer_bytes(hw_params)); |
| 458 | if (ret < 0) | 493 | if (ret < 0) |
| 459 | return ret; | 494 | return ret; |
| 460 | 495 | ||
| 461 | format = params_format(hw_params); | 496 | subs->pcm_format = params_format(hw_params); |
| 462 | rate = params_rate(hw_params); | 497 | subs->period_bytes = params_period_bytes(hw_params); |
| 463 | channels = params_channels(hw_params); | 498 | subs->channels = params_channels(hw_params); |
| 464 | fmt = find_format(subs, format, rate, channels); | 499 | subs->cur_rate = params_rate(hw_params); |
| 500 | |||
| 501 | fmt = find_format(subs); | ||
| 465 | if (!fmt) { | 502 | if (!fmt) { |
| 466 | snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n", | 503 | snd_printd(KERN_DEBUG "cannot set format: format = %#x, rate = %d, channels = %d\n", |
| 467 | format, rate, channels); | 504 | subs->pcm_format, subs->cur_rate, subs->channels); |
| 468 | return -EINVAL; | 505 | return -EINVAL; |
| 469 | } | 506 | } |
| 470 | 507 | ||
| 471 | changed = subs->cur_audiofmt != fmt || | ||
| 472 | subs->period_bytes != params_period_bytes(hw_params) || | ||
| 473 | subs->cur_rate != rate; | ||
| 474 | if ((ret = set_format(subs, fmt)) < 0) | 508 | if ((ret = set_format(subs, fmt)) < 0) |
| 475 | return ret; | 509 | return ret; |
| 476 | 510 | ||
| 477 | if (subs->cur_rate != rate) { | 511 | subs->interface = fmt->iface; |
| 478 | struct usb_host_interface *alts; | 512 | subs->altset_idx = fmt->altset_idx; |
| 479 | struct usb_interface *iface; | 513 | subs->need_setup_ep = true; |
| 480 | iface = usb_ifnum_to_if(subs->dev, fmt->iface); | ||
| 481 | alts = &iface->altsetting[fmt->altset_idx]; | ||
| 482 | ret = snd_usb_init_sample_rate(subs->stream->chip, fmt->iface, alts, fmt, rate); | ||
| 483 | if (ret < 0) | ||
| 484 | return ret; | ||
| 485 | subs->cur_rate = rate; | ||
| 486 | } | ||
| 487 | |||
| 488 | if (changed) { | ||
| 489 | mutex_lock(&subs->stream->chip->shutdown_mutex); | ||
| 490 | /* format changed */ | ||
| 491 | stop_endpoints(subs, 0, 0, 0); | ||
| 492 | ret = snd_usb_endpoint_set_params(subs->data_endpoint, hw_params, fmt, | ||
| 493 | subs->sync_endpoint); | ||
| 494 | if (ret < 0) | ||
| 495 | goto unlock; | ||
| 496 | 514 | ||
| 497 | if (subs->sync_endpoint) | 515 | return 0; |
| 498 | ret = snd_usb_endpoint_set_params(subs->sync_endpoint, | ||
| 499 | hw_params, fmt, NULL); | ||
| 500 | unlock: | ||
| 501 | mutex_unlock(&subs->stream->chip->shutdown_mutex); | ||
| 502 | } | ||
| 503 | |||
| 504 | if (ret == 0) { | ||
| 505 | subs->interface = fmt->iface; | ||
| 506 | subs->altset_idx = fmt->altset_idx; | ||
| 507 | } | ||
| 508 | |||
| 509 | return ret; | ||
| 510 | } | 516 | } |
| 511 | 517 | ||
| 512 | /* | 518 | /* |
| @@ -537,6 +543,9 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) | |||
| 537 | { | 543 | { |
| 538 | struct snd_pcm_runtime *runtime = substream->runtime; | 544 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 539 | struct snd_usb_substream *subs = runtime->private_data; | 545 | struct snd_usb_substream *subs = runtime->private_data; |
| 546 | struct usb_host_interface *alts; | ||
| 547 | struct usb_interface *iface; | ||
| 548 | int ret; | ||
| 540 | 549 | ||
| 541 | if (! subs->cur_audiofmt) { | 550 | if (! subs->cur_audiofmt) { |
| 542 | snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); | 551 | snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); |
| @@ -546,6 +555,27 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) | |||
| 546 | if (snd_BUG_ON(!subs->data_endpoint)) | 555 | if (snd_BUG_ON(!subs->data_endpoint)) |
| 547 | return -EIO; | 556 | return -EIO; |
| 548 | 557 | ||
| 558 | ret = set_format(subs, subs->cur_audiofmt); | ||
| 559 | if (ret < 0) | ||
| 560 | return ret; | ||
| 561 | |||
| 562 | iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface); | ||
| 563 | alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; | ||
| 564 | ret = snd_usb_init_sample_rate(subs->stream->chip, | ||
| 565 | subs->cur_audiofmt->iface, | ||
| 566 | alts, | ||
| 567 | subs->cur_audiofmt, | ||
| 568 | subs->cur_rate); | ||
| 569 | if (ret < 0) | ||
| 570 | return ret; | ||
| 571 | |||
| 572 | if (subs->need_setup_ep) { | ||
| 573 | ret = configure_endpoint(subs); | ||
| 574 | if (ret < 0) | ||
| 575 | return ret; | ||
| 576 | subs->need_setup_ep = false; | ||
| 577 | } | ||
| 578 | |||
| 549 | /* some unit conversions in runtime */ | 579 | /* some unit conversions in runtime */ |
| 550 | subs->data_endpoint->maxframesize = | 580 | subs->data_endpoint->maxframesize = |
| 551 | bytes_to_frames(runtime, subs->data_endpoint->maxpacksize); | 581 | bytes_to_frames(runtime, subs->data_endpoint->maxpacksize); |
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 79780fa57a43..d73ac9bc4272 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h | |||
| @@ -2781,6 +2781,59 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
| 2781 | } | 2781 | } |
| 2782 | }, | 2782 | }, |
| 2783 | 2783 | ||
| 2784 | /* Microsoft XboxLive Headset/Xbox Communicator */ | ||
| 2785 | { | ||
| 2786 | USB_DEVICE(0x045e, 0x0283), | ||
| 2787 | .bInterfaceClass = USB_CLASS_PER_INTERFACE, | ||
| 2788 | .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { | ||
| 2789 | .vendor_name = "Microsoft", | ||
| 2790 | .product_name = "XboxLive Headset/Xbox Communicator", | ||
| 2791 | .ifnum = QUIRK_ANY_INTERFACE, | ||
| 2792 | .type = QUIRK_COMPOSITE, | ||
| 2793 | .data = &(const struct snd_usb_audio_quirk[]) { | ||
| 2794 | { | ||
| 2795 | /* playback */ | ||
| 2796 | .ifnum = 0, | ||
| 2797 | .type = QUIRK_AUDIO_FIXED_ENDPOINT, | ||
| 2798 | .data = &(const struct audioformat) { | ||
| 2799 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
| 2800 | .channels = 1, | ||
| 2801 | .iface = 0, | ||
| 2802 | .altsetting = 0, | ||
| 2803 | .altset_idx = 0, | ||
| 2804 | .attributes = 0, | ||
| 2805 | .endpoint = 0x04, | ||
| 2806 | .ep_attr = 0x05, | ||
| 2807 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
| 2808 | .rate_min = 22050, | ||
| 2809 | .rate_max = 22050 | ||
| 2810 | } | ||
| 2811 | }, | ||
| 2812 | { | ||
| 2813 | /* capture */ | ||
| 2814 | .ifnum = 1, | ||
| 2815 | .type = QUIRK_AUDIO_FIXED_ENDPOINT, | ||
| 2816 | .data = &(const struct audioformat) { | ||
| 2817 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
| 2818 | .channels = 1, | ||
| 2819 | .iface = 1, | ||
| 2820 | .altsetting = 0, | ||
| 2821 | .altset_idx = 0, | ||
| 2822 | .attributes = 0, | ||
| 2823 | .endpoint = 0x85, | ||
| 2824 | .ep_attr = 0x05, | ||
| 2825 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | ||
| 2826 | .rate_min = 16000, | ||
| 2827 | .rate_max = 16000 | ||
| 2828 | } | ||
| 2829 | }, | ||
| 2830 | { | ||
| 2831 | .ifnum = -1 | ||
| 2832 | } | ||
| 2833 | } | ||
| 2834 | } | ||
| 2835 | }, | ||
| 2836 | |||
| 2784 | { | 2837 | { |
| 2785 | /* | 2838 | /* |
| 2786 | * Some USB MIDI devices don't have an audio control interface, | 2839 | * Some USB MIDI devices don't have an audio control interface, |
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 27817266867a..0f58b4b6d702 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c | |||
| @@ -761,3 +761,27 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, | |||
| 761 | } | 761 | } |
| 762 | } | 762 | } |
| 763 | 763 | ||
| 764 | void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep) | ||
| 765 | { | ||
| 766 | /* | ||
| 767 | * "Playback Design" products send bogus feedback data at the start | ||
| 768 | * of the stream. Ignore them. | ||
| 769 | */ | ||
| 770 | if ((le16_to_cpu(ep->chip->dev->descriptor.idVendor) == 0x23ba) && | ||
| 771 | ep->type == SND_USB_ENDPOINT_TYPE_SYNC) | ||
| 772 | ep->skip_packets = 4; | ||
| 773 | } | ||
| 774 | |||
| 775 | void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, | ||
| 776 | __u8 request, __u8 requesttype, __u16 value, | ||
| 777 | __u16 index, void *data, __u16 size) | ||
| 778 | { | ||
| 779 | /* | ||
| 780 | * "Playback Design" products need a 20ms delay after each | ||
| 781 | * class compliant request | ||
| 782 | */ | ||
| 783 | if ((le16_to_cpu(dev->descriptor.idVendor) == 0x23ba) && | ||
| 784 | (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS) | ||
| 785 | mdelay(20); | ||
| 786 | } | ||
| 787 | |||
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index 03e5e94098cd..0ca9e91067a6 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h | |||
| @@ -1,6 +1,10 @@ | |||
| 1 | #ifndef __USBAUDIO_QUIRKS_H | 1 | #ifndef __USBAUDIO_QUIRKS_H |
| 2 | #define __USBAUDIO_QUIRKS_H | 2 | #define __USBAUDIO_QUIRKS_H |
| 3 | 3 | ||
| 4 | struct audioformat; | ||
| 5 | struct snd_usb_endpoint; | ||
| 6 | struct snd_usb_substream; | ||
| 7 | |||
| 4 | int snd_usb_create_quirk(struct snd_usb_audio *chip, | 8 | int snd_usb_create_quirk(struct snd_usb_audio *chip, |
| 5 | struct usb_interface *iface, | 9 | struct usb_interface *iface, |
| 6 | struct usb_driver *driver, | 10 | struct usb_driver *driver, |
| @@ -20,4 +24,10 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, | |||
| 20 | int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, | 24 | int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, |
| 21 | struct audioformat *fp); | 25 | struct audioformat *fp); |
| 22 | 26 | ||
| 27 | void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep); | ||
| 28 | |||
| 29 | void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, | ||
| 30 | __u8 request, __u8 requesttype, __u16 value, | ||
| 31 | __u16 index, void *data, __u16 size); | ||
| 32 | |||
| 23 | #endif /* __USBAUDIO_QUIRKS_H */ | 33 | #endif /* __USBAUDIO_QUIRKS_H */ |
