Эх сурвалжийг харах

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

Pull sound updates from Takashi Iwai:
 "There've been many updates in ASoC side at this time, especially the
  framework enhancement for multiple CODECs on a single DAI and more
  componentization works.

  The only major change in ALSA core is the addition of timestamp type
  in sw_params field.  This should behave in backward compatible way.

  Other than that, there are lots of small changes and new drivers in
  wide range, including a large code cut in HD-audio driver for
  deprecated static quirks.  Some highlights are below:

  ALSA Core:
   - Add the new timestamp type field to sw_params to choose
     MONOTONIC_RAW type

  HD-audio:
   - Continued conversion to standard printk macros, generic code
     cleanups
   - Removal of obsoleted static quirk codes for Conexant and C-Media
     codecs
   - Fixups for HP Envy TS, Dell XPS 15, HP and Dell mute/mic LED,
     Gigabyte BXBT-2807 mobo
   - Intel Braswell support

  ASoC:
   - Support for multiple CODECs attached to a single DAI, enabling
     systems with for example multiple DAC/speaker drivers on a single
     link, contributed by Benoit Cousson based on work from Misael Lopez
     Cruz
   - Support for byte controls larger than 256 bytes based on the use of
     TLVs contributed by Omair Mohammed Abdullah
   - More componentisation work from Lars-Peter Clausen
   - The remainder of the conversions of CODEC drivers to params_width()
     by Mark Brown
   - Drivers for Cirrus Logic CS4265, Freescale i.MX ASRC blocks,
     Realtek RT286 and RT5670, Rockchip RK3xxx I2S controllers and Texas
     Instruments TAS2552
   - Lots of updates and fixes, especially to the DaVinci, Intel,
     Freescale, Realtek, and rcar drivers"

* tag 'sound-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (402 commits)
  ALSA: usb-audio: Whitespace cleanups for sound/usb/midi.*
  ALSA: usb-audio: Respond to suspend and resume callbacks for MIDI input
  sound/oss/pss: Remove typedefs pss_mixerdata and pss_confdata
  sound/oss/opl3: Remove typedef opl_devinfo
  ALSA: fireworks: fix specifiers in format strings for propper output
  ASoC: imx-audmux: Use uintptr_t for port numbers
  ASoC: davinci: Enable menuconfig entry for McASP
  ASoC: fsl_asrc: Don't access members of config before checking it
  ASoC: fsl_sarc_dma: Check pair before using it
  ASoC: adau1977: Fix truncation warning on 64 bit architectures
  ALSA: virtuoso: add Xonar Essence STX II support
  ALSA: riptide: fix %d confusingly prefixed with 0x in format strings
  ALSA: fireworks: fix %d confusingly prefixed with 0x in format strings
  ALSA: hda - add codec ID for Braswell display audio codec
  ALSA: hda - add PCI IDs for Intel Braswell
  ALSA: usb-audio: Adjust Gamecom 780 volume level
  ALSA: usb-audio: improve dmesg source grepability
  ASoC: rt5670: Fix duplicate const warnings
  ASoC: rt5670: Staticise non-exported symbols
  ASoC: Intel: update stream only on stream IPC msgs
  ...
Linus Torvalds 11 жил өмнө
parent
commit
930e0312bc
100 өөрчлөгдсөн 2689 нэмэгдсэн , 4035 устгасан
  1. 4 0
      Documentation/devicetree/bindings/sound/ak5386.txt
  2. 29 0
      Documentation/devicetree/bindings/sound/cs4265.txt
  3. 60 0
      Documentation/devicetree/bindings/sound/fsl,asrc.txt
  4. 1 1
      Documentation/devicetree/bindings/sound/max98090.txt
  5. 9 0
      Documentation/devicetree/bindings/sound/renesas,rsnd.txt
  6. 37 0
      Documentation/devicetree/bindings/sound/rockchip-i2s.txt
  7. 35 0
      Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt
  8. 27 0
      Documentation/devicetree/bindings/sound/sirf-usp.txt
  9. 5 0
      Documentation/devicetree/bindings/sound/snow.txt
  10. 26 0
      Documentation/devicetree/bindings/sound/tas2552.txt
  11. 5 0
      Documentation/devicetree/bindings/sound/ti,tas5086.txt
  12. 33 0
      Documentation/devicetree/bindings/sound/wm8904.txt
  13. 2 2
      Documentation/sound/alsa/ALSA-Configuration.txt
  14. 5 0
      Documentation/sound/alsa/HD-Audio-Models.txt
  15. 7 0
      MAINTAINERS
  16. 4 0
      arch/arm/mach-shmobile/board-armadillo800eva.c
  17. 2 0
      arch/arm/mach-shmobile/board-kzm9g.c
  18. 4 0
      arch/arm/mach-shmobile/board-mackerel.c
  19. 2 0
      arch/sh/boards/mach-ecovec24/setup.c
  20. 78 0
      arch/x86/include/asm/platform_sst_audio.h
  21. 1 0
      drivers/dma/edma.c
  22. 13 0
      drivers/misc/atmel-ssc.c
  23. 13 0
      include/linux/atmel-ssc.h
  24. 1 0
      include/linux/dmaengine.h
  25. 6 0
      include/linux/mfd/arizona/core.h
  26. 0 9
      include/linux/platform_data/asoc-s3c.h
  27. 1 0
      include/linux/platform_data/dma-imx.h
  28. 6 1
      include/sound/control.h
  29. 9 2
      include/sound/pcm.h
  30. 1 0
      include/sound/rcar_snd.h
  31. 19 0
      include/sound/rt286.h
  32. 27 0
      include/sound/rt5670.h
  33. 4 1
      include/sound/soc-dai.h
  34. 5 3
      include/sound/soc-dapm.h
  35. 72 22
      include/sound/soc.h
  36. 25 0
      include/sound/tas2552-plat.h
  37. 1 0
      include/sound/wm8962.h
  38. 3 3
      include/trace/events/asoc.h
  39. 6 3
      include/uapi/sound/asound.h
  40. 4 8
      sound/aoa/soundbus/i2sbus/core.c
  41. 6 6
      sound/arm/pxa2xx-ac97-lib.c
  42. 1 1
      sound/core/compress_offload.c
  43. 3 3
      sound/core/control.c
  44. 6 2
      sound/core/pcm_compat.c
  45. 3 1
      sound/core/pcm_dmaengine.c
  46. 6 3
      sound/core/pcm_native.c
  47. 2 2
      sound/core/seq/seq_memory.c
  48. 7 7
      sound/firewire/Kconfig
  49. 2 2
      sound/firewire/fireworks/fireworks_proc.c
  50. 1 1
      sound/oss/mpu401.c
  51. 2 2
      sound/oss/opl3.c
  52. 24 22
      sound/oss/pss.c
  53. 2 2
      sound/pci/Kconfig
  54. 0 6
      sound/pci/echoaudio/echoaudio.c
  55. 76 0
      sound/pci/hda/dell_wmi_helper.c
  56. 8 9
      sound/pci/hda/hda_auto_parser.c
  57. 29 16
      sound/pci/hda/hda_codec.c
  58. 2 2
      sound/pci/hda/hda_codec.h
  59. 72 131
      sound/pci/hda/hda_controller.c
  60. 6 3
      sound/pci/hda/hda_controller.h
  61. 22 24
      sound/pci/hda/hda_eld.c
  62. 12 10
      sound/pci/hda/hda_generic.c
  63. 2 2
      sound/pci/hda/hda_i915.c
  64. 293 79
      sound/pci/hda/hda_intel.c
  65. 6 3
      sound/pci/hda/hda_local.h
  66. 93 160
      sound/pci/hda/hda_priv.h
  67. 2 34
      sound/pci/hda/hda_tegra.c
  68. 3 3
      sound/pci/hda/patch_ca0132.c
  69. 3 1
      sound/pci/hda/patch_cirrus.c
  70. 9 615
      sound/pci/hda/patch_cmedia.c
  71. 51 2664
      sound/pci/hda/patch_conexant.c
  72. 8 5
      sound/pci/hda/patch_hdmi.c
  73. 165 5
      sound/pci/hda/patch_realtek.c
  74. 27 2
      sound/pci/hda/patch_sigmatel.c
  75. 9 6
      sound/pci/ice1712/ice1712.h
  76. 1 3
      sound/pci/mixart/mixart_core.c
  77. 1 0
      sound/pci/oxygen/virtuoso.c
  78. 10 2
      sound/pci/oxygen/xonar_pcm179x.c
  79. 2 2
      sound/pci/riptide/riptide.c
  80. 0 2
      sound/pci/trident/trident_main.c
  81. 1 2
      sound/pci/trident/trident_memory.c
  82. 1 0
      sound/soc/Kconfig
  83. 1 0
      sound/soc/Makefile
  84. 18 16
      sound/soc/atmel/atmel_ssc_dai.c
  85. 0 50
      sound/soc/atmel/atmel_wm8904.c
  86. 4 4
      sound/soc/blackfin/bf5xx-i2s-pcm.c
  87. 6 6
      sound/soc/codecs/88pm860x-codec.c
  88. 26 1
      sound/soc/codecs/Kconfig
  89. 8 0
      sound/soc/codecs/Makefile
  90. 2 2
      sound/soc/codecs/ac97.c
  91. 4 2
      sound/soc/codecs/adau1701.c
  92. 4 4
      sound/soc/codecs/adau17x1.c
  93. 1 1
      sound/soc/codecs/adau1977.c
  94. 2 2
      sound/soc/codecs/ak4642.c
  95. 50 0
      sound/soc/codecs/ak5386.c
  96. 244 44
      sound/soc/codecs/arizona.c
  97. 1 0
      sound/soc/codecs/arizona.h
  98. 682 0
      sound/soc/codecs/cs4265.c
  99. 64 0
      sound/soc/codecs/cs4265.h
  100. 1 3
      sound/soc/codecs/cs4270.c

+ 4 - 0
Documentation/devicetree/bindings/sound/ak5386.txt

@@ -10,10 +10,14 @@ Optional properties:
 
 
   - reset-gpio : a GPIO spec for the reset/power down pin.
   - reset-gpio : a GPIO spec for the reset/power down pin.
 		 If specified, it will be deasserted at probe time.
 		 If specified, it will be deasserted at probe time.
+  - va-supply : a regulator spec, providing 5.0V
+  - vd-supply : a regulator spec, providing 3.3V
 
 
 Example:
 Example:
 
 
 spdif: ak5386@0 {
 spdif: ak5386@0 {
 	compatible = "asahi-kasei,ak5386";
 	compatible = "asahi-kasei,ak5386";
 	reset-gpio = <&gpio0 23>;
 	reset-gpio = <&gpio0 23>;
+	va-supply = <&vdd_5v0_reg>;
+	vd-supply = <&vdd_3v3_reg>;
 };
 };

+ 29 - 0
Documentation/devicetree/bindings/sound/cs4265.txt

@@ -0,0 +1,29 @@
+CS4265 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+
+  - compatible : "cirrus,cs4265"
+
+  - reg : the I2C address of the device for I2C. The I2C address depends on
+          the state of the AD0 pin.  If AD0 is high, the i2c address is 0x4f.
+          If it is low, the i2c address is 0x4e.
+
+Optional properties:
+
+  - reset-gpios : a GPIO spec for the reset pin. If specified, it will be
+		 deasserted before communication to the codec starts.
+
+Examples:
+
+codec_ad0_high: cs4265@4f { /* AD0 Pin is high */
+	compatible = "cirrus,cs4265";
+	reg = <0x4f>;
+};
+
+
+codec_ad0_low: cs4265@4e { /* AD0 Pin is low */
+	compatible = "cirrus,cs4265";
+	reg = <0x4e>;
+};

+ 60 - 0
Documentation/devicetree/bindings/sound/fsl,asrc.txt

@@ -0,0 +1,60 @@
+Freescale Asynchronous Sample Rate Converter (ASRC) Controller
+
+The Asynchronous Sample Rate Converter (ASRC) converts the sampling rate of a
+signal associated with an input clock into a signal associated with a different
+output clock. The driver currently works as a Front End of DPCM with other Back
+Ends Audio controller such as ESAI, SSI and SAI. It has three pairs to support
+three substreams within totally 10 channels.
+
+Required properties:
+
+  - compatible		: Contains "fsl,imx35-asrc" or "fsl,imx53-asrc".
+
+  - reg			: Offset and length of the register set for the device.
+
+  - interrupts		: Contains the spdif interrupt.
+
+  - dmas		: Generic dma devicetree binding as described in
+			  Documentation/devicetree/bindings/dma/dma.txt.
+
+  - dma-names		: Contains "rxa", "rxb", "rxc", "txa", "txb" and "txc".
+
+  - clocks		: Contains an entry for each entry in clock-names.
+
+  - clock-names		: Contains the following entries
+	"mem"		  Peripheral access clock to access registers.
+	"ipg"		  Peripheral clock to driver module.
+	"asrck_<0-f>"	  Clock sources for input and output clock.
+
+   - big-endian		: If this property is absent, the little endian mode
+			  will be in use as default. Otherwise, the big endian
+			  mode will be in use for all the device registers.
+
+   - fsl,asrc-rate	: Defines a mutual sample rate used by DPCM Back Ends.
+
+   - fsl,asrc-width	: Defines a mutual sample width used by DPCM Back Ends.
+
+Example:
+
+asrc: asrc@02034000 {
+	compatible = "fsl,imx53-asrc";
+	reg = <0x02034000 0x4000>;
+	interrupts = <0 50 IRQ_TYPE_LEVEL_HIGH>;
+	clocks = <&clks 107>, <&clks 107>, <&clks 0>,
+	       <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+	       <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+	       <&clks 0>, <&clks 0>, <&clks 0>, <&clks 0>,
+	       <&clks 107>, <&clks 0>, <&clks 0>;
+	clock-names = "mem", "ipg", "asrck0",
+		"asrck_1", "asrck_2", "asrck_3", "asrck_4",
+		"asrck_5", "asrck_6", "asrck_7", "asrck_8",
+		"asrck_9", "asrck_a", "asrck_b", "asrck_c",
+		"asrck_d", "asrck_e", "asrck_f";
+	dmas = <&sdma 17 23 1>, <&sdma 18 23 1>, <&sdma 19 23 1>,
+	     <&sdma 20 23 1>, <&sdma 21 23 1>, <&sdma 22 23 1>;
+	dma-names = "rxa", "rxb", "rxc",
+		"txa", "txb", "txc";
+	fsl,asrc-rate  = <48000>;
+	fsl,asrc-width = <16>;
+	status = "okay";
+};

+ 1 - 1
Documentation/devicetree/bindings/sound/max98090.txt

@@ -4,7 +4,7 @@ This device supports I2C only.
 
 
 Required properties:
 Required properties:
 
 
-- compatible : "maxim,max98090".
+- compatible : "maxim,max98090" or "maxim,max98091".
 
 
 - reg : The I2C address of the device.
 - reg : The I2C address of the device.
 
 

+ 9 - 0
Documentation/devicetree/bindings/sound/renesas,rsnd.txt

@@ -13,6 +13,9 @@ Required properties:
 - rcar_sound,src		: Should contain SRC feature.
 - rcar_sound,src		: Should contain SRC feature.
 				  The number of SRC subnode should be same as HW.
 				  The number of SRC subnode should be same as HW.
 				  see below for detail.
 				  see below for detail.
+- rcar_sound,dvc		: Should contain DVC feature.
+				  The number of DVC subnode should be same as HW.
+				  see below for detail.
 - rcar_sound,dai		: DAI contents.
 - rcar_sound,dai		: DAI contents.
 				  The number of DAI subnode should be same as HW.
 				  The number of DAI subnode should be same as HW.
 				  see below for detail.
 				  see below for detail.
@@ -21,6 +24,7 @@ SSI subnode properties:
 - interrupts			: Should contain SSI interrupt for PIO transfer
 - interrupts			: Should contain SSI interrupt for PIO transfer
 - shared-pin			: if shared clock pin
 - shared-pin			: if shared clock pin
 - pio-transfer			: use PIO transfer mode
 - pio-transfer			: use PIO transfer mode
+- no-busif			: BUSIF is not ussed when [mem -> SSI] via DMA case
 
 
 SRC subnode properties:
 SRC subnode properties:
 no properties at this point
 no properties at this point
@@ -39,6 +43,11 @@ rcar_sound: rcar_sound@0xffd90000 {
 		<0 0xec540000 0 0x1000>, /* SSIU */
 		<0 0xec540000 0 0x1000>, /* SSIU */
 		<0 0xec541000 0 0x1280>; /* SSI */
 		<0 0xec541000 0 0x1280>; /* SSI */
 
 
+	rcar_sound,dvc {
+		dvc0: dvc@0 { };
+		dvc1: dvc@1 { };
+	};
+
 	rcar_sound,src {
 	rcar_sound,src {
 		src0: src@0 { };
 		src0: src@0 { };
 		src1: src@1 { };
 		src1: src@1 { };

+ 37 - 0
Documentation/devicetree/bindings/sound/rockchip-i2s.txt

@@ -0,0 +1,37 @@
+* Rockchip I2S controller
+
+The I2S bus (Inter-IC sound bus) is a serial link for digital
+audio data transfer between devices in the system.
+
+Required properties:
+
+- compatible: should be one of the followings
+   - "rockchip,rk3066-i2s": for rk3066
+   - "rockchip,rk3188-i2s", "rockchip,rk3066-i2s": for rk3188
+   - "rockchip,rk3288-i2s", "rockchip,rk3066-i2s": for rk3288
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- interrupts: should contain the I2S interrupt.
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
+	Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: should include "tx" and "rx".
+- clocks: a list of phandle + clock-specifer pairs, one for each entry in clock-names.
+- clock-names: should contain followings:
+   - "i2s_hclk": clock for I2S BUS
+   - "i2s_clk" : clock for I2S controller
+
+Example for rk3288 I2S controller:
+
+i2s@ff890000 {
+	compatible = "rockchip,rk3288-i2s", "rockchip,rk3066-i2s";
+	reg = <0xff890000 0x10000>;
+	interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+	#address-cells = <1>;
+	#size-cells = <0>;
+	dmas = <&pdma1 0>, <&pdma1 1>;
+	dma-names = "rx", "tx";
+	clock-names = "i2s_hclk", "i2s_clk";
+	clocks = <&cru HCLK_I2S0>, <&cru SCLK_I2S0>;
+};

+ 35 - 0
Documentation/devicetree/bindings/sound/samsung,odroidx2-max98090.txt

@@ -0,0 +1,35 @@
+Samsung Exynos Odroid X2/U3 audio complex with MAX98090 codec
+
+Required properties:
+ - compatible : "samsung,odroidx2-audio" - for Odroid X2 board,
+		"samsung,odroidu3-audio" - for Odroid U3 board
+ - samsung,model : the user-visible name of this sound complex
+ - samsung,i2s-controller : the phandle of the I2S controller
+ - samsung,audio-codec : the phandle of the MAX98090 audio codec
+ - samsung,audio-routing : a list of the connections between audio
+   components;  each entry is a pair of strings, the first being the
+   connection's sink, the second being the connection's source;
+   valid names for sources and sinks are the MAX98090's pins (as
+   documented in its binding), and the jacks on the board
+   For Odroid X2:
+     * Headphone Jack
+     * Mic Jack
+     * DMIC
+
+   For Odroid U3:
+     * Headphone Jack
+     * Speakers
+
+Example:
+
+sound {
+	compatible = "samsung,odroidu3-audio";
+	samsung,i2s-controller = <&i2s0>;
+	samsung,audio-codec = <&max98090>;
+	samsung,model = "Odroid-X2";
+	samsung,audio-routing =
+		"Headphone Jack", "HPL",
+		"Headphone Jack", "HPR",
+		"IN1", "Mic Jack",
+		"Mic Jack", "MICBIAS";
+};

+ 27 - 0
Documentation/devicetree/bindings/sound/sirf-usp.txt

@@ -0,0 +1,27 @@
+* SiRF SoC USP module
+
+Required properties:
+- compatible: "sirf,prima2-usp-pcm"
+- reg: Base address and size entries:
+- dmas: List of DMA controller phandle and DMA request line ordered pairs.
+- dma-names: Identifier string for each DMA request line in the dmas property.
+  These strings correspond 1:1 with the ordered pairs in dmas.
+
+  One of the DMA channels will be responsible for transmission (should be
+  named "tx") and one for reception (should be named "rx").
+
+- clocks: USP controller clock source
+- pinctrl-names: Must contain a "default" entry.
+- pinctrl-NNN: One property must exist for each entry in pinctrl-names.
+
+Example:
+usp0: usp@b0080000 {
+	compatible = "sirf,prima2-usp-pcm";
+	reg = <0xb0080000 0x10000>;
+	clocks = <&clks 28>;
+	dmas = <&dmac1 1>, <&dmac1 2>;
+	dma-names = "rx", "tx";
+	pinctrl-names = "default";
+	pinctrl-0 = <&usp0_only_utfs_pins_a>;
+};
+

+ 5 - 0
Documentation/devicetree/bindings/sound/snow.txt

@@ -3,15 +3,20 @@ Audio Binding for Snow boards
 Required properties:
 Required properties:
 - compatible : Can be one of the following,
 - compatible : Can be one of the following,
 			"google,snow-audio-max98090" or
 			"google,snow-audio-max98090" or
+			"google,snow-audio-max98091" or
 			"google,snow-audio-max98095"
 			"google,snow-audio-max98095"
 - samsung,i2s-controller: The phandle of the Samsung I2S controller
 - samsung,i2s-controller: The phandle of the Samsung I2S controller
 - samsung,audio-codec: The phandle of the audio codec
 - samsung,audio-codec: The phandle of the audio codec
 
 
+Optional:
+- samsung,model: The name of the sound-card
+
 Example:
 Example:
 
 
 sound {
 sound {
 		compatible = "google,snow-audio-max98095";
 		compatible = "google,snow-audio-max98095";
 
 
+		samsung,model = "Snow-I2S-MAX98095";
 		samsung,i2s-controller = <&i2s0>;
 		samsung,i2s-controller = <&i2s0>;
 		samsung,audio-codec = <&max98095>;
 		samsung,audio-codec = <&max98095>;
 };
 };

+ 26 - 0
Documentation/devicetree/bindings/sound/tas2552.txt

@@ -0,0 +1,26 @@
+Texas Instruments - tas2552 Codec module
+
+The tas2552 serial control bus communicates through I2C protocols
+
+Required properties:
+	- compatible - One of:
+		"ti,tas2552" - TAS2552
+	- reg -  I2C slave address
+	- supply-*: Required supply regulators are:
+		"vbat"		battery voltage
+		"iovdd"		I/O Voltage
+		"avdd"		Analog DAC Voltage
+
+Optional properties:
+	- enable-gpio - gpio pin to enable/disable the device
+
+Example:
+
+tas2552: tas2552@41 {
+	compatible = "ti,tas2552";
+	reg = <0x41>;
+	enable-gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
+};
+
+For more product information please see the link below:
+http://www.ti.com/product/TAS2552

+ 5 - 0
Documentation/devicetree/bindings/sound/ti,tas5086.txt

@@ -31,6 +31,9 @@ Optional properties:
 
 
 			Most systems should not set any of these properties.
 			Most systems should not set any of these properties.
 
 
+ - avdd-supply:         Power supply for AVDD, providing 3.3V
+ - dvdd-supply:         Power supply for DVDD, providing 3.3V
+
 Examples:
 Examples:
 
 
 	i2c_bus {
 	i2c_bus {
@@ -39,5 +42,7 @@ Examples:
 			reg = <0x1b>;
 			reg = <0x1b>;
 			reset-gpio = <&gpio 23 0>;
 			reset-gpio = <&gpio 23 0>;
 			ti,charge-period = <156000>;
 			ti,charge-period = <156000>;
+			avdd-supply = <&vdd_3v3_reg>;
+			dvdd-supply = <&vdd_3v3_reg>;
 		};
 		};
 	};
 	};

+ 33 - 0
Documentation/devicetree/bindings/sound/wm8904.txt

@@ -0,0 +1,33 @@
+WM8904 audio CODEC
+
+This device supports I2C only.
+
+Required properties:
+  - compatible: "wlf,wm8904"
+  - reg: the I2C address of the device.
+  - clock-names: "mclk"
+  - clocks: reference to
+    <Documentation/devicetree/bindings/clock/clock-bindings.txt>
+
+Pins on the device (for linking into audio routes):
+
+  * IN1L
+  * IN1R
+  * IN2L
+  * IN2R
+  * IN3L
+  * IN3R
+  * HPOUTL
+  * HPOUTR
+  * LINEOUTL
+  * LINEOUTR
+  * MICBIAS
+
+Examples:
+
+codec: wm8904@1a {
+	compatible = "wlf,wm8904";
+	reg = <0x1a>;
+	clocks = <&pck0>;
+	clock-names = "mclk";
+};

+ 2 - 2
Documentation/sound/alsa/ALSA-Configuration.txt

@@ -2026,8 +2026,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
   -------------------
   -------------------
 
 
     Module for sound cards based on the Asus AV66/AV100/AV200 chips,
     Module for sound cards based on the Asus AV66/AV100/AV200 chips,
-    i.e., Xonar D1, DX, D2, D2X, DS, Essence ST (Deluxe), Essence STX,
-    HDAV1.3 (Deluxe), and HDAV1.3 Slim.
+    i.e., Xonar D1, DX, D2, D2X, DS, DSX, Essence ST (Deluxe),
+    Essence STX (II), HDAV1.3 (Deluxe), and HDAV1.3 Slim.
 
 
     This module supports autoprobe and multiple cards.
     This module supports autoprobe and multiple cards.
 
 

+ 5 - 0
Documentation/sound/alsa/HD-Audio-Models.txt

@@ -284,6 +284,11 @@ STAC92HD83*
   hp-zephyr	HP Zephyr
   hp-zephyr	HP Zephyr
   hp-led	HP with broken BIOS for mute LED
   hp-led	HP with broken BIOS for mute LED
   hp-inv-led	HP with broken BIOS for inverted mute LED
   hp-inv-led	HP with broken BIOS for inverted mute LED
+  hp-mic-led	HP with mic-mute LED
+  headset-jack	Dell Latitude with a 4-pin headset jack
+  hp-envy-bass	Pin fixup for HP Envy bass speaker (NID 0x0f)
+  hp-envy-ts-bass Pin fixup for HP Envy TS bass speaker (NID 0x10)
+  hp-bnb13-eq	Hardware equalizer setup for HP laptops
   auto		BIOS setup (default)
   auto		BIOS setup (default)
 
 
 STAC92HD95
 STAC92HD95

+ 7 - 0
MAINTAINERS

@@ -7526,6 +7526,13 @@ F:	drivers/rtc/
 F:	include/linux/rtc.h
 F:	include/linux/rtc.h
 F:	include/uapi/linux/rtc.h
 F:	include/uapi/linux/rtc.h
 
 
+REALTEK AUDIO CODECS
+M:	Bard Liao <bardliao@realtek.com>
+M:	Oder Chiou <oder_chiou@realtek.com>
+S:	Maintained
+F:	sound/soc/codecs/rt*
+F:	include/sound/rt*.h
+
 REISERFS FILE SYSTEM
 REISERFS FILE SYSTEM
 L:	reiserfs-devel@vger.kernel.org
 L:	reiserfs-devel@vger.kernel.org
 S:	Supported
 S:	Supported

+ 4 - 0
arch/arm/mach-shmobile/board-armadillo800eva.c

@@ -998,6 +998,8 @@ static struct platform_device fsi_wm8978_device = {
 	.id	= 0,
 	.id	= 0,
 	.dev	= {
 	.dev	= {
 		.platform_data	= &fsi_wm8978_info,
 		.platform_data	= &fsi_wm8978_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_wm8978_device.dev.coherent_dma_mask,
 	},
 	},
 };
 };
 
 
@@ -1021,6 +1023,8 @@ static struct platform_device fsi_hdmi_device = {
 	.id	= 1,
 	.id	= 1,
 	.dev	= {
 	.dev	= {
 		.platform_data	= &fsi2_hdmi_info,
 		.platform_data	= &fsi2_hdmi_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask,
 	},
 	},
 };
 };
 
 

+ 2 - 0
arch/arm/mach-shmobile/board-kzm9g.c

@@ -603,6 +603,8 @@ static struct platform_device fsi_ak4648_device = {
 	.name	= "asoc-simple-card",
 	.name	= "asoc-simple-card",
 	.dev	= {
 	.dev	= {
 		.platform_data	= &fsi2_ak4648_info,
 		.platform_data	= &fsi2_ak4648_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_ak4648_device.dev.coherent_dma_mask,
 	},
 	},
 };
 };
 
 

+ 4 - 0
arch/arm/mach-shmobile/board-mackerel.c

@@ -523,6 +523,8 @@ static struct platform_device fsi_hdmi_device = {
 	.id	= 1,
 	.id	= 1,
 	.dev	= {
 	.dev	= {
 		.platform_data	= &fsi2_hdmi_info,
 		.platform_data	= &fsi2_hdmi_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_hdmi_device.dev.coherent_dma_mask,
 	},
 	},
 };
 };
 
 
@@ -919,6 +921,8 @@ static struct platform_device fsi_ak4643_device = {
 	.name	= "asoc-simple-card",
 	.name	= "asoc-simple-card",
 	.dev	= {
 	.dev	= {
 		.platform_data	= &fsi2_ak4643_info,
 		.platform_data	= &fsi2_ak4643_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_ak4643_device.dev.coherent_dma_mask,
 	},
 	},
 };
 };
 
 

+ 2 - 0
arch/sh/boards/mach-ecovec24/setup.c

@@ -874,6 +874,8 @@ static struct platform_device fsi_da7210_device = {
 	.name	= "asoc-simple-card",
 	.name	= "asoc-simple-card",
 	.dev	= {
 	.dev	= {
 		.platform_data	= &fsi_da7210_info,
 		.platform_data	= &fsi_da7210_info,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.dma_mask = &fsi_da7210_device.dev.coherent_dma_mask,
 	},
 	},
 };
 };
 
 

+ 78 - 0
arch/x86/include/asm/platform_sst_audio.h

@@ -0,0 +1,78 @@
+/*
+ * platform_sst_audio.h:  sst audio platform data header file
+ *
+ * Copyright (C) 2012-14 Intel Corporation
+ * Author: Jeeja KP <jeeja.kp@intel.com>
+ * 	Omair Mohammed Abdullah <omair.m.abdullah@intel.com>
+ *	Vinod Koul ,vinod.koul@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+#ifndef _PLATFORM_SST_AUDIO_H_
+#define _PLATFORM_SST_AUDIO_H_
+
+#include <linux/sfi.h>
+
+enum sst_audio_task_id_mrfld {
+	SST_TASK_ID_NONE = 0,
+	SST_TASK_ID_SBA = 1,
+	SST_TASK_ID_MEDIA = 3,
+	SST_TASK_ID_MAX = SST_TASK_ID_MEDIA,
+};
+
+/* Device IDs for Merrifield are Pipe IDs,
+ * ref: DSP spec v0.75 */
+enum sst_audio_device_id_mrfld {
+	/* Output pipeline IDs */
+	PIPE_ID_OUT_START = 0x0,
+	PIPE_CODEC_OUT0 = 0x2,
+	PIPE_CODEC_OUT1 = 0x3,
+	PIPE_SPROT_LOOP_OUT = 0x4,
+	PIPE_MEDIA_LOOP1_OUT = 0x5,
+	PIPE_MEDIA_LOOP2_OUT = 0x6,
+	PIPE_VOIP_OUT = 0xC,
+	PIPE_PCM0_OUT = 0xD,
+	PIPE_PCM1_OUT = 0xE,
+	PIPE_PCM2_OUT = 0xF,
+	PIPE_MEDIA0_OUT = 0x12,
+	PIPE_MEDIA1_OUT = 0x13,
+/* Input Pipeline IDs */
+	PIPE_ID_IN_START = 0x80,
+	PIPE_CODEC_IN0 = 0x82,
+	PIPE_CODEC_IN1 = 0x83,
+	PIPE_SPROT_LOOP_IN = 0x84,
+	PIPE_MEDIA_LOOP1_IN = 0x85,
+	PIPE_MEDIA_LOOP2_IN = 0x86,
+	PIPE_VOIP_IN = 0x8C,
+	PIPE_PCM0_IN = 0x8D,
+	PIPE_PCM1_IN = 0x8E,
+	PIPE_MEDIA0_IN = 0x8F,
+	PIPE_MEDIA1_IN = 0x90,
+	PIPE_MEDIA2_IN = 0x91,
+	PIPE_RSVD = 0xFF,
+};
+
+/* The stream map for each platform consists of an array of the below
+ * stream map structure.
+ */
+struct sst_dev_stream_map {
+	u8 dev_num;		/* device id */
+	u8 subdev_num;		/* substream */
+	u8 direction;
+	u8 device_id;		/* fw id */
+	u8 task_id;		/* fw task */
+	u8 status;
+};
+
+struct sst_platform_data {
+	/* Intel software platform id*/
+	struct sst_dev_stream_map *pdev_strm_map;
+	unsigned int strm_map_size;
+};
+
+int add_sst_platform_device(void);
+#endif
+

+ 1 - 0
drivers/dma/edma.c

@@ -982,6 +982,7 @@ static void __init edma_chan_init(struct edma_cc *ecc,
 
 
 #define EDMA_DMA_BUSWIDTHS	(BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
 #define EDMA_DMA_BUSWIDTHS	(BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
 				 BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
 				 BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
+				 BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
 				 BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
 				 BIT(DMA_SLAVE_BUSWIDTH_4_BYTES))
 
 
 static int edma_dma_device_slave_caps(struct dma_chan *dchan,
 static int edma_dma_device_slave_caps(struct dma_chan *dchan,

+ 13 - 0
drivers/misc/atmel-ssc.c

@@ -83,16 +83,26 @@ EXPORT_SYMBOL(ssc_free);
 
 
 static struct atmel_ssc_platform_data at91rm9200_config = {
 static struct atmel_ssc_platform_data at91rm9200_config = {
 	.use_dma = 0,
 	.use_dma = 0,
+	.has_fslen_ext = 0,
+};
+
+static struct atmel_ssc_platform_data at91sam9rl_config = {
+	.use_dma = 0,
+	.has_fslen_ext = 1,
 };
 };
 
 
 static struct atmel_ssc_platform_data at91sam9g45_config = {
 static struct atmel_ssc_platform_data at91sam9g45_config = {
 	.use_dma = 1,
 	.use_dma = 1,
+	.has_fslen_ext = 1,
 };
 };
 
 
 static const struct platform_device_id atmel_ssc_devtypes[] = {
 static const struct platform_device_id atmel_ssc_devtypes[] = {
 	{
 	{
 		.name = "at91rm9200_ssc",
 		.name = "at91rm9200_ssc",
 		.driver_data = (unsigned long) &at91rm9200_config,
 		.driver_data = (unsigned long) &at91rm9200_config,
+	}, {
+		.name = "at91sam9rl_ssc",
+		.driver_data = (unsigned long) &at91sam9rl_config,
 	}, {
 	}, {
 		.name = "at91sam9g45_ssc",
 		.name = "at91sam9g45_ssc",
 		.driver_data = (unsigned long) &at91sam9g45_config,
 		.driver_data = (unsigned long) &at91sam9g45_config,
@@ -106,6 +116,9 @@ static const struct of_device_id atmel_ssc_dt_ids[] = {
 	{
 	{
 		.compatible = "atmel,at91rm9200-ssc",
 		.compatible = "atmel,at91rm9200-ssc",
 		.data = &at91rm9200_config,
 		.data = &at91rm9200_config,
+	}, {
+		.compatible = "atmel,at91sam9rl-ssc",
+		.data = &at91sam9rl_config,
 	}, {
 	}, {
 		.compatible = "atmel,at91sam9g45-ssc",
 		.compatible = "atmel,at91sam9g45-ssc",
 		.data = &at91sam9g45_config,
 		.data = &at91sam9g45_config,

+ 13 - 0
include/linux/atmel-ssc.h

@@ -7,6 +7,7 @@
 
 
 struct atmel_ssc_platform_data {
 struct atmel_ssc_platform_data {
 	int			use_dma;
 	int			use_dma;
+	int			has_fslen_ext;
 };
 };
 
 
 struct ssc_device {
 struct ssc_device {
@@ -71,6 +72,12 @@ void ssc_free(struct ssc_device *ssc);
 #define SSC_RFMR_DATNB_OFFSET			 8
 #define SSC_RFMR_DATNB_OFFSET			 8
 #define SSC_RFMR_FSEDGE_SIZE			 1
 #define SSC_RFMR_FSEDGE_SIZE			 1
 #define SSC_RFMR_FSEDGE_OFFSET			24
 #define SSC_RFMR_FSEDGE_OFFSET			24
+/*
+ * The FSLEN_EXT exist on at91sam9rl, at91sam9g10,
+ * at91sam9g20, and at91sam9g45 and newer SoCs
+ */
+#define SSC_RFMR_FSLEN_EXT_SIZE			 4
+#define SSC_RFMR_FSLEN_EXT_OFFSET		28
 #define SSC_RFMR_FSLEN_SIZE			 4
 #define SSC_RFMR_FSLEN_SIZE			 4
 #define SSC_RFMR_FSLEN_OFFSET			16
 #define SSC_RFMR_FSLEN_OFFSET			16
 #define SSC_RFMR_FSOS_SIZE			 4
 #define SSC_RFMR_FSOS_SIZE			 4
@@ -109,6 +116,12 @@ void ssc_free(struct ssc_device *ssc);
 #define SSC_TFMR_FSDEN_OFFSET			23
 #define SSC_TFMR_FSDEN_OFFSET			23
 #define SSC_TFMR_FSEDGE_SIZE			 1
 #define SSC_TFMR_FSEDGE_SIZE			 1
 #define SSC_TFMR_FSEDGE_OFFSET			24
 #define SSC_TFMR_FSEDGE_OFFSET			24
+/*
+ * The FSLEN_EXT exist on at91sam9rl, at91sam9g10,
+ * at91sam9g20, and at91sam9g45 and newer SoCs
+ */
+#define SSC_TFMR_FSLEN_EXT_SIZE			 4
+#define SSC_TFMR_FSLEN_EXT_OFFSET		28
 #define SSC_TFMR_FSLEN_SIZE			 4
 #define SSC_TFMR_FSLEN_SIZE			 4
 #define SSC_TFMR_FSLEN_OFFSET			16
 #define SSC_TFMR_FSLEN_OFFSET			16
 #define SSC_TFMR_FSOS_SIZE			 3
 #define SSC_TFMR_FSOS_SIZE			 3

+ 1 - 0
include/linux/dmaengine.h

@@ -299,6 +299,7 @@ enum dma_slave_buswidth {
 	DMA_SLAVE_BUSWIDTH_UNDEFINED = 0,
 	DMA_SLAVE_BUSWIDTH_UNDEFINED = 0,
 	DMA_SLAVE_BUSWIDTH_1_BYTE = 1,
 	DMA_SLAVE_BUSWIDTH_1_BYTE = 1,
 	DMA_SLAVE_BUSWIDTH_2_BYTES = 2,
 	DMA_SLAVE_BUSWIDTH_2_BYTES = 2,
+	DMA_SLAVE_BUSWIDTH_3_BYTES = 3,
 	DMA_SLAVE_BUSWIDTH_4_BYTES = 4,
 	DMA_SLAVE_BUSWIDTH_4_BYTES = 4,
 	DMA_SLAVE_BUSWIDTH_8_BYTES = 8,
 	DMA_SLAVE_BUSWIDTH_8_BYTES = 8,
 };
 };

+ 6 - 0
include/linux/mfd/arizona/core.h

@@ -110,6 +110,12 @@ struct arizona {
 	int clk32k_ref;
 	int clk32k_ref;
 
 
 	struct snd_soc_dapm_context *dapm;
 	struct snd_soc_dapm_context *dapm;
+
+	int tdm_width[ARIZONA_MAX_AIF];
+	int tdm_slots[ARIZONA_MAX_AIF];
+
+	uint16_t dac_comp_coeff;
+	uint8_t dac_comp_enabled;
 };
 };
 
 
 int arizona_clk32k_enable(struct arizona *arizona);
 int arizona_clk32k_enable(struct arizona *arizona);

+ 0 - 9
include/linux/platform_data/asoc-s3c.h

@@ -15,15 +15,6 @@
 #define S3C64XX_AC97_GPE  1
 #define S3C64XX_AC97_GPE  1
 extern void s3c64xx_ac97_setup_gpio(int);
 extern void s3c64xx_ac97_setup_gpio(int);
 
 
-/*
- * The machine init code calls s5p*_spdif_setup_gpio with
- * one of these defines in order to select appropriate bank
- * of GPIO for S/PDIF pins
- */
-#define S5PC100_SPDIF_GPD  0
-#define S5PC100_SPDIF_GPG3 1
-extern void s5pc100_spdif_setup_gpio(int);
-
 struct samsung_i2s {
 struct samsung_i2s {
 /* If the Primary DAI has 5.1 Channels */
 /* If the Primary DAI has 5.1 Channels */
 #define QUIRK_PRI_6CHAN		(1 << 0)
 #define QUIRK_PRI_6CHAN		(1 << 0)

+ 1 - 0
include/linux/platform_data/dma-imx.h

@@ -50,6 +50,7 @@ enum imx_dma_prio {
 
 
 struct imx_dma_data {
 struct imx_dma_data {
 	int dma_request; /* DMA request line */
 	int dma_request; /* DMA request line */
+	int dma_request2; /* secondary DMA request line */
 	enum sdma_peripheral_type peripheral_type;
 	enum sdma_peripheral_type peripheral_type;
 	int priority;
 	int priority;
 };
 };

+ 6 - 1
include/sound/control.h

@@ -31,10 +31,15 @@ typedef int (snd_kcontrol_info_t) (struct snd_kcontrol * kcontrol, struct snd_ct
 typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
 typedef int (snd_kcontrol_get_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
 typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
 typedef int (snd_kcontrol_put_t) (struct snd_kcontrol * kcontrol, struct snd_ctl_elem_value * ucontrol);
 typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol,
 typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol,
-				    int op_flag, /* 0=read,1=write,-1=command */
+				    int op_flag, /* SNDRV_CTL_TLV_OP_XXX */
 				    unsigned int size,
 				    unsigned int size,
 				    unsigned int __user *tlv);
 				    unsigned int __user *tlv);
 
 
+enum {
+	SNDRV_CTL_TLV_OP_READ = 0,
+	SNDRV_CTL_TLV_OP_WRITE = 1,
+	SNDRV_CTL_TLV_OP_CMD = -1,
+};
 
 
 struct snd_kcontrol_new {
 struct snd_kcontrol_new {
 	snd_ctl_elem_iface_t iface;	/* interface identifier */
 	snd_ctl_elem_iface_t iface;	/* interface identifier */

+ 9 - 2
include/sound/pcm.h

@@ -931,10 +931,17 @@ void snd_pcm_timer_done(struct snd_pcm_substream *substream);
 static inline void snd_pcm_gettime(struct snd_pcm_runtime *runtime,
 static inline void snd_pcm_gettime(struct snd_pcm_runtime *runtime,
 				   struct timespec *tv)
 				   struct timespec *tv)
 {
 {
-	if (runtime->tstamp_type == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
+	switch (runtime->tstamp_type) {
+	case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC:
 		ktime_get_ts(tv);
 		ktime_get_ts(tv);
-	else
+		break;
+	case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW:
+		getrawmonotonic(tv);
+		break;
+	default:
 		getnstimeofday(tv);
 		getnstimeofday(tv);
+		break;
+	}
 }
 }
 
 
 /*
 /*

+ 1 - 0
include/sound/rcar_snd.h

@@ -34,6 +34,7 @@
  * B : SSI direction
  * B : SSI direction
  */
  */
 #define RSND_SSI_CLK_PIN_SHARE		(1 << 31)
 #define RSND_SSI_CLK_PIN_SHARE		(1 << 31)
+#define RSND_SSI_NO_BUSIF		(1 << 30) /* SSI+DMA without BUSIF */
 
 
 #define RSND_SSI(_dma_id, _pio_irq, _flags)		\
 #define RSND_SSI(_dma_id, _pio_irq, _flags)		\
 { .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
 { .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }

+ 19 - 0
include/sound/rt286.h

@@ -0,0 +1,19 @@
+/*
+ * linux/sound/rt286.h -- Platform data for RT286
+ *
+ * Copyright 2013 Realtek Microelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_RT286_H
+#define __LINUX_SND_RT286_H
+
+struct rt286_platform_data {
+	bool cbj_en; /*combo jack enable*/
+	bool gpio2_en; /*GPIO2 enable*/
+};
+
+#endif

+ 27 - 0
include/sound/rt5670.h

@@ -0,0 +1,27 @@
+/*
+ * linux/sound/rt5670.h -- Platform data for RT5670
+ *
+ * Copyright 2014 Realtek Microelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_SND_RT5670_H
+#define __LINUX_SND_RT5670_H
+
+struct rt5670_platform_data {
+	int jd_mode;
+	bool in2_diff;
+
+	bool dmic_en;
+	unsigned int dmic1_data_pin;
+	/* 0 = GPIO6; 1 = IN2P; 3 = GPIO7*/
+	unsigned int dmic2_data_pin;
+	/* 0 = GPIO8; 1 = IN3N; */
+	unsigned int dmic3_data_pin;
+	/* 0 = GPIO9; 1 = GPIO10; 2 = GPIO5*/
+};
+
+#endif

+ 4 - 1
include/sound/soc-dai.h

@@ -257,7 +257,6 @@ struct snd_soc_dai {
 
 
 	struct snd_soc_dapm_widget *playback_widget;
 	struct snd_soc_dapm_widget *playback_widget;
 	struct snd_soc_dapm_widget *capture_widget;
 	struct snd_soc_dapm_widget *capture_widget;
-	struct snd_soc_dapm_context dapm;
 
 
 	/* DAI DMA data */
 	/* DAI DMA data */
 	void *playback_dma_data;
 	void *playback_dma_data;
@@ -273,6 +272,10 @@ struct snd_soc_dai {
 	struct snd_soc_codec *codec;
 	struct snd_soc_codec *codec;
 	struct snd_soc_component *component;
 	struct snd_soc_component *component;
 
 
+	/* CODEC TDM slot masks and params (for fixup) */
+	unsigned int tx_mask;
+	unsigned int rx_mask;
+
 	struct snd_soc_card *card;
 	struct snd_soc_card *card;
 
 
 	struct list_head list;
 	struct list_head list;

+ 5 - 3
include/sound/soc-dapm.h

@@ -431,7 +431,7 @@ int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm,
 					   const char *pin);
 					   const char *pin);
 int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
 int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
 				const char *pin);
 				const char *pin);
-void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec);
+void snd_soc_dapm_auto_nc_pins(struct snd_soc_card *card);
 
 
 /* Mostly internal - should not normally be used */
 /* Mostly internal - should not normally be used */
 void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm);
 void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm);
@@ -441,6 +441,8 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream,
 	struct snd_soc_dapm_widget_list **list);
 	struct snd_soc_dapm_widget_list **list);
 
 
 struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol);
 struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(struct snd_kcontrol *kcontrol);
+struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(
+	struct snd_kcontrol *kcontrol);
 
 
 /* dapm widget types */
 /* dapm widget types */
 enum snd_soc_dapm_type {
 enum snd_soc_dapm_type {
@@ -524,7 +526,6 @@ struct snd_soc_dapm_widget {
 	const char *name;		/* widget name */
 	const char *name;		/* widget name */
 	const char *sname;	/* stream name */
 	const char *sname;	/* stream name */
 	struct snd_soc_codec *codec;
 	struct snd_soc_codec *codec;
-	struct snd_soc_platform *platform;
 	struct list_head list;
 	struct list_head list;
 	struct snd_soc_dapm_context *dapm;
 	struct snd_soc_dapm_context *dapm;
 
 
@@ -593,7 +594,6 @@ struct snd_soc_dapm_context {
 	struct device *dev; /* from parent - for debug */
 	struct device *dev; /* from parent - for debug */
 	struct snd_soc_component *component; /* parent component */
 	struct snd_soc_component *component; /* parent component */
 	struct snd_soc_codec *codec; /* parent codec */
 	struct snd_soc_codec *codec; /* parent codec */
-	struct snd_soc_platform *platform; /* parent platform */
 	struct snd_soc_card *card; /* parent card */
 	struct snd_soc_card *card; /* parent card */
 
 
 	/* used during DAPM updates */
 	/* used during DAPM updates */
@@ -601,6 +601,8 @@ struct snd_soc_dapm_context {
 	struct list_head list;
 	struct list_head list;
 
 
 	int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
 	int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
+	int (*set_bias_level)(struct snd_soc_dapm_context *dapm,
+			      enum snd_soc_bias_level level);
 
 
 #ifdef CONFIG_DEBUG_FS
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_dapm;
 	struct dentry *debugfs_dapm;

+ 72 - 22
include/sound/soc.h

@@ -248,6 +248,8 @@
 	.info = snd_soc_info_enum_double, \
 	.info = snd_soc_info_enum_double, \
 	.get = xhandler_get, .put = xhandler_put, \
 	.get = xhandler_get, .put = xhandler_put, \
 	.private_value = (unsigned long)&xenum }
 	.private_value = (unsigned long)&xenum }
+#define SOC_VALUE_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
+	SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put)
 
 
 #define SND_SOC_BYTES(xname, xbase, xregs)		      \
 #define SND_SOC_BYTES(xname, xbase, xregs)		      \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,   \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,   \
@@ -270,7 +272,14 @@
 	.get = xhandler_get, .put = xhandler_put, \
 	.get = xhandler_get, .put = xhandler_put, \
 	.private_value = (unsigned long)&(struct soc_bytes_ext) \
 	.private_value = (unsigned long)&(struct soc_bytes_ext) \
 		{.max = xcount} }
 		{.max = xcount} }
-
+#define SND_SOC_BYTES_TLV(xname, xcount, xhandler_get, xhandler_put) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE | \
+		  SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK, \
+	.tlv.c = (snd_soc_bytes_tlv_callback), \
+	.info = snd_soc_info_bytes_ext, \
+	.private_value = (unsigned long)&(struct soc_bytes_ext) \
+		{.max = xcount, .get = xhandler_get, .put = xhandler_put, } }
 #define SOC_SINGLE_XR_SX(xname, xregbase, xregcount, xnbits, \
 #define SOC_SINGLE_XR_SX(xname, xregbase, xregcount, xnbits, \
 		xmin, xmax, xinvert) \
 		xmin, xmax, xinvert) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
@@ -436,6 +445,10 @@ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
 int snd_soc_platform_trigger(struct snd_pcm_substream *substream,
 int snd_soc_platform_trigger(struct snd_pcm_substream *substream,
 		int cmd, struct snd_soc_platform *platform);
 		int cmd, struct snd_soc_platform *platform);
 
 
+int soc_dai_hw_params(struct snd_pcm_substream *substream,
+		      struct snd_pcm_hw_params *params,
+		      struct snd_soc_dai *dai);
+
 /* Jack reporting */
 /* Jack reporting */
 int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
 int snd_soc_jack_new(struct snd_soc_codec *codec, const char *id, int type,
 		     struct snd_soc_jack *jack);
 		     struct snd_soc_jack *jack);
@@ -503,10 +516,12 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
 				  const char *prefix);
 				  const char *prefix);
 struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
 struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card,
 					       const char *name);
 					       const char *name);
+int snd_soc_add_component_controls(struct snd_soc_component *component,
+	const struct snd_kcontrol_new *controls, unsigned int num_controls);
 int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
 int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
-	const struct snd_kcontrol_new *controls, int num_controls);
+	const struct snd_kcontrol_new *controls, unsigned int num_controls);
 int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
 int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
-	const struct snd_kcontrol_new *controls, int num_controls);
+	const struct snd_kcontrol_new *controls, unsigned int num_controls);
 int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
 int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
 	const struct snd_kcontrol_new *controls, int num_controls);
 	const struct snd_kcontrol_new *controls, int num_controls);
 int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
 int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
@@ -552,6 +567,8 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
 		      struct snd_ctl_elem_value *ucontrol);
 		      struct snd_ctl_elem_value *ucontrol);
 int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
 int snd_soc_bytes_info_ext(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_info *ucontrol);
 	struct snd_ctl_elem_info *ucontrol);
+int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag,
+	unsigned int size, unsigned int __user *tlv);
 int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
 int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_info *uinfo);
 	struct snd_ctl_elem_info *uinfo);
 int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
 int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol,
@@ -677,12 +694,17 @@ struct snd_soc_component_driver {
 	int (*of_xlate_dai_name)(struct snd_soc_component *component,
 	int (*of_xlate_dai_name)(struct snd_soc_component *component,
 				 struct of_phandle_args *args,
 				 struct of_phandle_args *args,
 				 const char **dai_name);
 				 const char **dai_name);
+	void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type,
+		int subseq);
+	int (*stream_event)(struct snd_soc_component *, int event);
 };
 };
 
 
 struct snd_soc_component {
 struct snd_soc_component {
 	const char *name;
 	const char *name;
 	int id;
 	int id;
+	const char *name_prefix;
 	struct device *dev;
 	struct device *dev;
+	struct snd_soc_card *card;
 
 
 	unsigned int active;
 	unsigned int active;
 
 
@@ -705,18 +727,18 @@ struct snd_soc_component {
 	int val_bytes;
 	int val_bytes;
 
 
 	struct mutex io_mutex;
 	struct mutex io_mutex;
+
+	/* Don't use these, use snd_soc_component_get_dapm() */
+	struct snd_soc_dapm_context dapm;
+	struct snd_soc_dapm_context *dapm_ptr;
 };
 };
 
 
 /* SoC Audio Codec device */
 /* SoC Audio Codec device */
 struct snd_soc_codec {
 struct snd_soc_codec {
-	const char *name;
-	const char *name_prefix;
-	int id;
 	struct device *dev;
 	struct device *dev;
 	const struct snd_soc_codec_driver *driver;
 	const struct snd_soc_codec_driver *driver;
 
 
 	struct mutex mutex;
 	struct mutex mutex;
-	struct snd_soc_card *card;
 	struct list_head list;
 	struct list_head list;
 	struct list_head card_list;
 	struct list_head card_list;
 
 
@@ -790,9 +812,6 @@ struct snd_soc_codec_driver {
 	void (*seq_notifier)(struct snd_soc_dapm_context *,
 	void (*seq_notifier)(struct snd_soc_dapm_context *,
 			     enum snd_soc_dapm_type, int);
 			     enum snd_soc_dapm_type, int);
 
 
-	/* codec stream completion event */
-	int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
-
 	bool ignore_pmdown_time;  /* Doesn't benefit from pmdown delay */
 	bool ignore_pmdown_time;  /* Doesn't benefit from pmdown delay */
 
 
 	/* probe ordering - for components with runtime dependencies */
 	/* probe ordering - for components with runtime dependencies */
@@ -834,9 +853,6 @@ struct snd_soc_platform_driver {
 	/* platform stream compress ops */
 	/* platform stream compress ops */
 	const struct snd_compr_ops *compr_ops;
 	const struct snd_compr_ops *compr_ops;
 
 
-	/* platform stream completion event */
-	int (*stream_event)(struct snd_soc_dapm_context *dapm, int event);
-
 	/* probe ordering - for components with runtime dependencies */
 	/* probe ordering - for components with runtime dependencies */
 	int probe_order;
 	int probe_order;
 	int remove_order;
 	int remove_order;
@@ -847,23 +863,23 @@ struct snd_soc_platform_driver {
 	int (*bespoke_trigger)(struct snd_pcm_substream *, int);
 	int (*bespoke_trigger)(struct snd_pcm_substream *, int);
 };
 };
 
 
-struct snd_soc_platform {
+struct snd_soc_dai_link_component {
 	const char *name;
 	const char *name;
-	int id;
+	const struct device_node *of_node;
+	const char *dai_name;
+};
+
+struct snd_soc_platform {
 	struct device *dev;
 	struct device *dev;
 	const struct snd_soc_platform_driver *driver;
 	const struct snd_soc_platform_driver *driver;
 
 
 	unsigned int suspended:1; /* platform is suspended */
 	unsigned int suspended:1; /* platform is suspended */
 	unsigned int probed:1;
 	unsigned int probed:1;
 
 
-	struct snd_soc_card *card;
 	struct list_head list;
 	struct list_head list;
-	struct list_head card_list;
 
 
 	struct snd_soc_component component;
 	struct snd_soc_component component;
 
 
-	struct snd_soc_dapm_context dapm;
-
 #ifdef CONFIG_DEBUG_FS
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_platform_root;
 	struct dentry *debugfs_platform_root;
 #endif
 #endif
@@ -896,6 +912,10 @@ struct snd_soc_dai_link {
 	const struct device_node *codec_of_node;
 	const struct device_node *codec_of_node;
 	/* You MUST specify the DAI name within the codec */
 	/* You MUST specify the DAI name within the codec */
 	const char *codec_dai_name;
 	const char *codec_dai_name;
+
+	struct snd_soc_dai_link_component *codecs;
+	unsigned int num_codecs;
+
 	/*
 	/*
 	 * You MAY specify the link's platform/PCM/DMA driver, either by
 	 * You MAY specify the link's platform/PCM/DMA driver, either by
 	 * device name, or by DT/OF node, but not both. Some forms of link
 	 * device name, or by DT/OF node, but not both. Some forms of link
@@ -1047,7 +1067,6 @@ struct snd_soc_card {
 
 
 	/* lists of probed devices belonging to this card */
 	/* lists of probed devices belonging to this card */
 	struct list_head codec_dev_list;
 	struct list_head codec_dev_list;
-	struct list_head platform_dev_list;
 
 
 	struct list_head widgets;
 	struct list_head widgets;
 	struct list_head paths;
 	struct list_head paths;
@@ -1094,6 +1113,9 @@ struct snd_soc_pcm_runtime {
 	struct snd_soc_dai *codec_dai;
 	struct snd_soc_dai *codec_dai;
 	struct snd_soc_dai *cpu_dai;
 	struct snd_soc_dai *cpu_dai;
 
 
+	struct snd_soc_dai **codec_dais;
+	unsigned int num_codecs;
+
 	struct delayed_work delayed_work;
 	struct delayed_work delayed_work;
 #ifdef CONFIG_DEBUG_FS
 #ifdef CONFIG_DEBUG_FS
 	struct dentry *debugfs_dpcm_root;
 	struct dentry *debugfs_dpcm_root;
@@ -1119,6 +1141,9 @@ struct soc_bytes {
 
 
 struct soc_bytes_ext {
 struct soc_bytes_ext {
 	int max;
 	int max;
+	/* used for TLV byte control */
+	int (*get)(unsigned int __user *bytes, unsigned int size);
+	int (*put)(const unsigned int __user *bytes, unsigned int size);
 };
 };
 
 
 /* multi register control */
 /* multi register control */
@@ -1164,6 +1189,21 @@ static inline struct snd_soc_platform *snd_soc_component_to_platform(
 	return container_of(component, struct snd_soc_platform, component);
 	return container_of(component, struct snd_soc_platform, component);
 }
 }
 
 
+/**
+ * snd_soc_dapm_to_component() - Casts a DAPM context to the component it is
+ *  embedded in
+ * @dapm: The DAPM context to cast to the component
+ *
+ * This function must only be used on DAPM contexts that are known to be part of
+ * a component (e.g. in a component driver). Otherwise the behavior is
+ * undefined.
+ */
+static inline struct snd_soc_component *snd_soc_dapm_to_component(
+	struct snd_soc_dapm_context *dapm)
+{
+	return container_of(dapm, struct snd_soc_component, dapm);
+}
+
 /**
 /**
  * snd_soc_dapm_to_codec() - Casts a DAPM context to the CODEC it is embedded in
  * snd_soc_dapm_to_codec() - Casts a DAPM context to the CODEC it is embedded in
  * @dapm: The DAPM context to cast to the CODEC
  * @dapm: The DAPM context to cast to the CODEC
@@ -1188,7 +1228,18 @@ static inline struct snd_soc_codec *snd_soc_dapm_to_codec(
 static inline struct snd_soc_platform *snd_soc_dapm_to_platform(
 static inline struct snd_soc_platform *snd_soc_dapm_to_platform(
 	struct snd_soc_dapm_context *dapm)
 	struct snd_soc_dapm_context *dapm)
 {
 {
-	return container_of(dapm, struct snd_soc_platform, dapm);
+	return snd_soc_component_to_platform(snd_soc_dapm_to_component(dapm));
+}
+
+/**
+ * snd_soc_component_get_dapm() - Returns the DAPM context associated with a
+ *  component
+ * @component: The component for which to get the DAPM context
+ */
+static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm(
+	struct snd_soc_component *component)
+{
+	return component->dapm_ptr;
 }
 }
 
 
 /* codec IO */
 /* codec IO */
@@ -1261,7 +1312,6 @@ static inline void *snd_soc_pcm_get_drvdata(struct snd_soc_pcm_runtime *rtd)
 static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
 static inline void snd_soc_initialize_card_lists(struct snd_soc_card *card)
 {
 {
 	INIT_LIST_HEAD(&card->codec_dev_list);
 	INIT_LIST_HEAD(&card->codec_dev_list);
-	INIT_LIST_HEAD(&card->platform_dev_list);
 	INIT_LIST_HEAD(&card->widgets);
 	INIT_LIST_HEAD(&card->widgets);
 	INIT_LIST_HEAD(&card->paths);
 	INIT_LIST_HEAD(&card->paths);
 	INIT_LIST_HEAD(&card->dapm_list);
 	INIT_LIST_HEAD(&card->dapm_list);

+ 25 - 0
include/sound/tas2552-plat.h

@@ -0,0 +1,25 @@
+/*
+ * TAS2552 driver platform header
+ *
+ * Copyright (C) 2014 Texas Instruments Inc.
+ *
+ * Author: Dan Murphy <dmurphy@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef TAS2552_PLAT_H
+#define TAS2552_PLAT_H
+
+struct tas2552_platform_data {
+	int enable_gpio;
+};
+
+#endif

+ 1 - 0
include/sound/wm8962.h

@@ -37,6 +37,7 @@
 #define WM8962_GPIO_FN_MICSCD          22
 #define WM8962_GPIO_FN_MICSCD          22
 
 
 struct wm8962_pdata {
 struct wm8962_pdata {
+	struct clk *mclk;
 	int gpio_base;
 	int gpio_base;
 	u32 gpio_init[WM8962_MAX_GPIO];
 	u32 gpio_init[WM8962_MAX_GPIO];
 
 

+ 3 - 3
include/trace/events/asoc.h

@@ -296,17 +296,17 @@ TRACE_EVENT(snd_soc_cache_sync,
 	TP_ARGS(codec, type, status),
 	TP_ARGS(codec, type, status),
 
 
 	TP_STRUCT__entry(
 	TP_STRUCT__entry(
-		__string(	name,		codec->name	)
+		__string(	name,		codec->component.name)
 		__string(	status,		status		)
 		__string(	status,		status		)
 		__string(	type,		type		)
 		__string(	type,		type		)
 		__field(	int,		id		)
 		__field(	int,		id		)
 	),
 	),
 
 
 	TP_fast_assign(
 	TP_fast_assign(
-		__assign_str(name, codec->name);
+		__assign_str(name, codec->component.name);
 		__assign_str(status, status);
 		__assign_str(status, status);
 		__assign_str(type, type);
 		__assign_str(type, type);
-		__entry->id = codec->id;
+		__entry->id = codec->component.id;
 	),
 	),
 
 
 	TP_printk("codec=%s.%d type=%s status=%s", __get_str(name),
 	TP_printk("codec=%s.%d type=%s status=%s", __get_str(name),

+ 6 - 3
include/uapi/sound/asound.h

@@ -139,7 +139,7 @@ struct snd_hwdep_dsp_image {
  *                                                                           *
  *                                                                           *
  *****************************************************************************/
  *****************************************************************************/
 
 
-#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 11)
+#define SNDRV_PCM_VERSION		SNDRV_PROTOCOL_VERSION(2, 0, 12)
 
 
 typedef unsigned long snd_pcm_uframes_t;
 typedef unsigned long snd_pcm_uframes_t;
 typedef signed long snd_pcm_sframes_t;
 typedef signed long snd_pcm_sframes_t;
@@ -391,7 +391,9 @@ struct snd_pcm_sw_params {
 	snd_pcm_uframes_t silence_threshold;	/* min distance from noise for silence filling */
 	snd_pcm_uframes_t silence_threshold;	/* min distance from noise for silence filling */
 	snd_pcm_uframes_t silence_size;		/* silence block size */
 	snd_pcm_uframes_t silence_size;		/* silence block size */
 	snd_pcm_uframes_t boundary;		/* pointers wrap point */
 	snd_pcm_uframes_t boundary;		/* pointers wrap point */
-	unsigned char reserved[64];		/* reserved for future */
+	unsigned int proto;			/* protocol version */
+	unsigned int tstamp_type;		/* timestamp type (req. proto >= 2.0.12) */
+	unsigned char reserved[56];		/* reserved for future */
 };
 };
 
 
 struct snd_pcm_channel_info {
 struct snd_pcm_channel_info {
@@ -462,7 +464,8 @@ struct snd_xfern {
 enum {
 enum {
 	SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0,	/* gettimeofday equivalent */
 	SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0,	/* gettimeofday equivalent */
 	SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,	/* posix_clock_monotonic equivalent */
 	SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,	/* posix_clock_monotonic equivalent */
-	SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
+	SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW,    /* monotonic_raw (no NTP) */
+	SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW,
 };
 };
 
 
 /* channel positions */
 /* channel positions */

+ 4 - 8
sound/aoa/soundbus/i2sbus/core.c

@@ -47,15 +47,11 @@ static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
 	/* We use the PCI APIs for now until the generic one gets fixed
 	/* We use the PCI APIs for now until the generic one gets fixed
 	 * enough or until we get some macio-specific versions
 	 * enough or until we get some macio-specific versions
 	 */
 	 */
-	r->space = dma_alloc_coherent(
-			&macio_get_pci_dev(i2sdev->macio)->dev,
-			r->size,
-			&r->bus_addr,
-			GFP_KERNEL);
+	r->space = dma_zalloc_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
+				       r->size, &r->bus_addr, GFP_KERNEL);
+	if (!r->space)
+		return -ENOMEM;
 
 
-	if (!r->space) return -ENOMEM;
-
-	memset(r->space, 0, r->size);
 	r->cmds = (void*)DBDMA_ALIGN(r->space);
 	r->cmds = (void*)DBDMA_ALIGN(r->space);
 	r->bus_cmd_start = r->bus_addr +
 	r->bus_cmd_start = r->bus_addr +
 			   (dma_addr_t)((char*)r->cmds - (char*)r->space);
 			   (dma_addr_t)((char*)r->cmds - (char*)r->space);

+ 6 - 6
sound/arm/pxa2xx-ac97-lib.c

@@ -152,9 +152,9 @@ static inline void pxa_ac97_cold_pxa27x(void)
 	gsr_bits = 0;
 	gsr_bits = 0;
 
 
 	/* PXA27x Developers Manual section 13.5.2.2.1 */
 	/* PXA27x Developers Manual section 13.5.2.2.1 */
-	clk_enable(ac97conf_clk);
+	clk_prepare_enable(ac97conf_clk);
 	udelay(5);
 	udelay(5);
-	clk_disable(ac97conf_clk);
+	clk_disable_unprepare(ac97conf_clk);
 	GCR = GCR_COLD_RST | GCR_WARM_RST;
 	GCR = GCR_COLD_RST | GCR_WARM_RST;
 }
 }
 #endif
 #endif
@@ -299,14 +299,14 @@ static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
 int pxa2xx_ac97_hw_suspend(void)
 int pxa2xx_ac97_hw_suspend(void)
 {
 {
 	GCR |= GCR_ACLINK_OFF;
 	GCR |= GCR_ACLINK_OFF;
-	clk_disable(ac97_clk);
+	clk_disable_unprepare(ac97_clk);
 	return 0;
 	return 0;
 }
 }
 EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend);
 EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend);
 
 
 int pxa2xx_ac97_hw_resume(void)
 int pxa2xx_ac97_hw_resume(void)
 {
 {
-	clk_enable(ac97_clk);
+	clk_prepare_enable(ac97_clk);
 	return 0;
 	return 0;
 }
 }
 EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
 EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
@@ -368,7 +368,7 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev)
 		goto err_clk;
 		goto err_clk;
 	}
 	}
 
 
-	ret = clk_enable(ac97_clk);
+	ret = clk_prepare_enable(ac97_clk);
 	if (ret)
 	if (ret)
 		goto err_clk2;
 		goto err_clk2;
 
 
@@ -403,7 +403,7 @@ void pxa2xx_ac97_hw_remove(struct platform_device *dev)
 		clk_put(ac97conf_clk);
 		clk_put(ac97conf_clk);
 		ac97conf_clk = NULL;
 		ac97conf_clk = NULL;
 	}
 	}
-	clk_disable(ac97_clk);
+	clk_disable_unprepare(ac97_clk);
 	clk_put(ac97_clk);
 	clk_put(ac97_clk);
 	ac97_clk = NULL;
 	ac97_clk = NULL;
 }
 }

+ 1 - 1
sound/core/compress_offload.c

@@ -491,7 +491,7 @@ static int snd_compress_check_input(struct snd_compr_params *params)
 {
 {
 	/* first let's check the buffer parameter's */
 	/* first let's check the buffer parameter's */
 	if (params->buffer.fragment_size == 0 ||
 	if (params->buffer.fragment_size == 0 ||
-			params->buffer.fragments > SIZE_MAX / params->buffer.fragment_size)
+	    params->buffer.fragments > INT_MAX / params->buffer.fragment_size)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	/* now codec parameters */
 	/* now codec parameters */

+ 3 - 3
sound/core/control.c

@@ -1406,11 +1406,11 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
 	case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
 	case SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS:
 		return snd_ctl_subscribe_events(ctl, ip);
 		return snd_ctl_subscribe_events(ctl, ip);
 	case SNDRV_CTL_IOCTL_TLV_READ:
 	case SNDRV_CTL_IOCTL_TLV_READ:
-		return snd_ctl_tlv_ioctl(ctl, argp, 0);
+		return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_READ);
 	case SNDRV_CTL_IOCTL_TLV_WRITE:
 	case SNDRV_CTL_IOCTL_TLV_WRITE:
-		return snd_ctl_tlv_ioctl(ctl, argp, 1);
+		return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_WRITE);
 	case SNDRV_CTL_IOCTL_TLV_COMMAND:
 	case SNDRV_CTL_IOCTL_TLV_COMMAND:
-		return snd_ctl_tlv_ioctl(ctl, argp, -1);
+		return snd_ctl_tlv_ioctl(ctl, argp, SNDRV_CTL_TLV_OP_CMD);
 	case SNDRV_CTL_IOCTL_POWER:
 	case SNDRV_CTL_IOCTL_POWER:
 		return -ENOPROTOOPT;
 		return -ENOPROTOOPT;
 	case SNDRV_CTL_IOCTL_POWER_STATE:
 	case SNDRV_CTL_IOCTL_POWER_STATE:

+ 6 - 2
sound/core/pcm_compat.c

@@ -101,7 +101,9 @@ struct snd_pcm_sw_params32 {
 	u32 silence_threshold;
 	u32 silence_threshold;
 	u32 silence_size;
 	u32 silence_size;
 	u32 boundary;
 	u32 boundary;
-	unsigned char reserved[64];
+	u32 proto;
+	u32 tstamp_type;
+	unsigned char reserved[56];
 };
 };
 
 
 /* recalcuate the boundary within 32bit */
 /* recalcuate the boundary within 32bit */
@@ -133,7 +135,9 @@ static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream,
 	    get_user(params.start_threshold, &src->start_threshold) ||
 	    get_user(params.start_threshold, &src->start_threshold) ||
 	    get_user(params.stop_threshold, &src->stop_threshold) ||
 	    get_user(params.stop_threshold, &src->stop_threshold) ||
 	    get_user(params.silence_threshold, &src->silence_threshold) ||
 	    get_user(params.silence_threshold, &src->silence_threshold) ||
-	    get_user(params.silence_size, &src->silence_size))
+	    get_user(params.silence_size, &src->silence_size) ||
+	    get_user(params.tstamp_type, &src->tstamp_type) ||
+	    get_user(params.proto, &src->proto))
 		return -EFAULT;
 		return -EFAULT;
 	/*
 	/*
 	 * Check silent_size parameter.  Since we have 64bit boundary,
 	 * Check silent_size parameter.  Since we have 64bit boundary,

+ 3 - 1
sound/core/pcm_dmaengine.c

@@ -65,13 +65,15 @@ int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
 	enum dma_slave_buswidth buswidth;
 	enum dma_slave_buswidth buswidth;
 	int bits;
 	int bits;
 
 
-	bits = snd_pcm_format_physical_width(params_format(params));
+	bits = params_physical_width(params);
 	if (bits < 8 || bits > 64)
 	if (bits < 8 || bits > 64)
 		return -EINVAL;
 		return -EINVAL;
 	else if (bits == 8)
 	else if (bits == 8)
 		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
 		buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
 	else if (bits == 16)
 	else if (bits == 16)
 		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
 		buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+	else if (bits == 24)
+		buswidth = DMA_SLAVE_BUSWIDTH_3_BYTES;
 	else if (bits <= 32)
 	else if (bits <= 32)
 		buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
 		buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
 	else
 	else

+ 6 - 3
sound/core/pcm_native.c

@@ -543,6 +543,9 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
 
 
 	if (params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST)
 	if (params->tstamp_mode > SNDRV_PCM_TSTAMP_LAST)
 		return -EINVAL;
 		return -EINVAL;
+	if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12) &&
+	    params->tstamp_type > SNDRV_PCM_TSTAMP_TYPE_LAST)
+		return -EINVAL;
 	if (params->avail_min == 0)
 	if (params->avail_min == 0)
 		return -EINVAL;
 		return -EINVAL;
 	if (params->silence_size >= runtime->boundary) {
 	if (params->silence_size >= runtime->boundary) {
@@ -557,6 +560,8 @@ static int snd_pcm_sw_params(struct snd_pcm_substream *substream,
 	err = 0;
 	err = 0;
 	snd_pcm_stream_lock_irq(substream);
 	snd_pcm_stream_lock_irq(substream);
 	runtime->tstamp_mode = params->tstamp_mode;
 	runtime->tstamp_mode = params->tstamp_mode;
+	if (params->proto >= SNDRV_PROTOCOL_VERSION(2, 0, 12))
+		runtime->tstamp_type = params->tstamp_type;
 	runtime->period_step = params->period_step;
 	runtime->period_step = params->period_step;
 	runtime->control->avail_min = params->avail_min;
 	runtime->control->avail_min = params->avail_min;
 	runtime->start_threshold = params->start_threshold;
 	runtime->start_threshold = params->start_threshold;
@@ -2540,9 +2545,7 @@ static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
 		return -EFAULT;
 		return -EFAULT;
 	if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST)
 	if (arg < 0 || arg > SNDRV_PCM_TSTAMP_TYPE_LAST)
 		return -EINVAL;
 		return -EINVAL;
-	runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY;
-	if (arg == SNDRV_PCM_TSTAMP_TYPE_MONOTONIC)
-		runtime->tstamp_type = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
+	runtime->tstamp_type = arg;
 	return 0;
 	return 0;
 }
 }
 		
 		

+ 2 - 2
sound/core/seq/seq_memory.c

@@ -101,9 +101,9 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event,
 			len -= size;
 			len -= size;
 		}
 		}
 		return 0;
 		return 0;
-	} if (! (event->data.ext.len & SNDRV_SEQ_EXT_CHAINED)) {
-		return func(private_data, event->data.ext.ptr, len);
 	}
 	}
+	if (!(event->data.ext.len & SNDRV_SEQ_EXT_CHAINED))
+		return func(private_data, event->data.ext.ptr, len);
 
 
 	cell = (struct snd_seq_event_cell *)event->data.ext.ptr;
 	cell = (struct snd_seq_event_cell *)event->data.ext.ptr;
 	for (; len > 0 && cell; cell = cell->next) {
 	for (; len > 0 && cell; cell = cell->next) {

+ 7 - 7
sound/firewire/Kconfig

@@ -83,8 +83,8 @@ config SND_BEBOB
 	  * Edirol FA-66/FA-101
 	  * Edirol FA-66/FA-101
 	  * PreSonus FIREBOX/FIREPOD/FP10/Inspire1394
 	  * PreSonus FIREBOX/FIREPOD/FP10/Inspire1394
 	  * BridgeCo RDAudio1/Audio5
 	  * BridgeCo RDAudio1/Audio5
-	  * Mackie Onyx 1220/1620/1640 (Firewire I/O Card)
-	  * Mackie d.2 (Firewire Option)
+	  * Mackie Onyx 1220/1620/1640 (FireWire I/O Card)
+	  * Mackie d.2 (FireWire Option)
 	  * Stanton FinalScratch 2 (ScratchAmp)
 	  * Stanton FinalScratch 2 (ScratchAmp)
 	  * Tascam IF-FW/DM
 	  * Tascam IF-FW/DM
 	  * Behringer XENIX UFX 1204/1604
 	  * Behringer XENIX UFX 1204/1604
@@ -92,7 +92,7 @@ config SND_BEBOB
 	  * Apogee Rosetta 200/400 (X-FireWire card)
 	  * Apogee Rosetta 200/400 (X-FireWire card)
 	  * Apogee DA/AD/DD-16X (X-FireWire card)
 	  * Apogee DA/AD/DD-16X (X-FireWire card)
 	  * Apogee Ensemble
 	  * Apogee Ensemble
-	  * ESI Quotafire610
+	  * ESI QuataFire 610
 	  * AcousticReality eARMasterOne
 	  * AcousticReality eARMasterOne
 	  * CME MatrixKFW
 	  * CME MatrixKFW
 	  * Phonic Helix Board 12 MkII/18 MkII/24 MkII
 	  * Phonic Helix Board 12 MkII/18 MkII/24 MkII
@@ -101,13 +101,13 @@ config SND_BEBOB
 	  * ICON FireXon
 	  * ICON FireXon
 	  * PrismSound Orpheus/ADA-8XR
 	  * PrismSound Orpheus/ADA-8XR
 	  * TerraTec PHASE 24 FW/PHASE X24 FW/PHASE 88 Rack FW
 	  * TerraTec PHASE 24 FW/PHASE X24 FW/PHASE 88 Rack FW
-	  * Terratec EWS MIC2/EWS MIC4
-	  * Terratec Aureon 7.1 Firewire
+	  * TerraTec EWS MIC2/EWS MIC8
+	  * TerraTec Aureon 7.1 FireWire
 	  * Yamaha GO44/GO46
 	  * Yamaha GO44/GO46
 	  * Focusrite Saffire/Saffire LE/SaffirePro10 IO/SaffirePro26 IO
 	  * Focusrite Saffire/Saffire LE/SaffirePro10 IO/SaffirePro26 IO
-	  * M-Audio Firewire410/AudioPhile/Solo
+	  * M-Audio FireWire410/AudioPhile/Solo
 	  * M-Audio Ozonic/NRV10/ProfireLightBridge
 	  * M-Audio Ozonic/NRV10/ProfireLightBridge
-	  * M-Audio Firewire 1814/ProjectMix IO
+	  * M-Audio FireWire 1814/ProjectMix IO
 
 
           To compile this driver as a module, choose M here: the module
           To compile this driver as a module, choose M here: the module
           will be called snd-bebob.
           will be called snd-bebob.

+ 2 - 2
sound/firewire/fireworks/fireworks_proc.c

@@ -64,7 +64,7 @@ proc_read_hwinfo(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 		    hwinfo->phys_in_grp_count);
 		    hwinfo->phys_in_grp_count);
 	for (i = 0; i < hwinfo->phys_in_grp_count; i++) {
 	for (i = 0; i < hwinfo->phys_in_grp_count; i++) {
 		snd_iprintf(buffer,
 		snd_iprintf(buffer,
-			    "phys in grp[0x%d]: type 0x%d, count 0x%d\n",
+			    "phys in grp[%d]: type 0x%X, count 0x%X\n",
 			    i, hwinfo->phys_out_grps[i].type,
 			    i, hwinfo->phys_out_grps[i].type,
 			    hwinfo->phys_out_grps[i].count);
 			    hwinfo->phys_out_grps[i].count);
 	}
 	}
@@ -73,7 +73,7 @@ proc_read_hwinfo(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 		    hwinfo->phys_out_grp_count);
 		    hwinfo->phys_out_grp_count);
 	for (i = 0; i < hwinfo->phys_out_grp_count; i++) {
 	for (i = 0; i < hwinfo->phys_out_grp_count; i++) {
 		snd_iprintf(buffer,
 		snd_iprintf(buffer,
-			    "phys out grps[0x%d]: type 0x%d, count 0x%d\n",
+			    "phys out grps[%d]: type 0x%X, count 0x%X\n",
 			    i, hwinfo->phys_out_grps[i].type,
 			    i, hwinfo->phys_out_grps[i].type,
 			    hwinfo->phys_out_grps[i].count);
 			    hwinfo->phys_out_grps[i].count);
 	}
 	}

+ 1 - 1
sound/oss/mpu401.c

@@ -316,6 +316,7 @@ static int mpu_input_scanner(struct mpu_config *devc, unsigned char midic)
 				case 0xf6:
 				case 0xf6:
 					/* printk( "tune_request\n"); */
 					/* printk( "tune_request\n"); */
 					devc->m_state = ST_INIT;
 					devc->m_state = ST_INIT;
+					break;
 
 
 					/*
 					/*
 					 *    Real time messages
 					 *    Real time messages
@@ -972,7 +973,6 @@ int attach_mpu401(struct address_info *hw_config, struct module *owner)
 	devc->m_busy = 0;
 	devc->m_busy = 0;
 	devc->m_state = ST_INIT;
 	devc->m_state = ST_INIT;
 	devc->shared_irq = hw_config->always_detect;
 	devc->shared_irq = hw_config->always_detect;
-	devc->irq = hw_config->irq;
 	spin_lock_init(&devc->lock);
 	spin_lock_init(&devc->lock);
 
 
 	if (devc->irq < 0)
 	if (devc->irq < 0)

+ 2 - 2
sound/oss/opl3.c

@@ -52,7 +52,7 @@ struct voice_info
 	int             panning;	/* 0xffff means not set */
 	int             panning;	/* 0xffff means not set */
 };
 };
 
 
-typedef struct opl_devinfo
+struct opl_devinfo
 {
 {
 	int             base;
 	int             base;
 	int             left_io, right_io;
 	int             left_io, right_io;
@@ -73,7 +73,7 @@ typedef struct opl_devinfo
 	unsigned char   cmask;
 	unsigned char   cmask;
 
 
 	int             is_opl4;
 	int             is_opl4;
-} opl_devinfo;
+};
 
 
 static struct opl_devinfo *devc = NULL;
 static struct opl_devinfo *devc = NULL;
 
 

+ 24 - 22
sound/oss/pss.c

@@ -123,25 +123,25 @@ static bool pss_mixer;
 #endif
 #endif
 
 
 
 
-typedef struct pss_mixerdata {
+struct pss_mixerdata {
 	unsigned int volume_l;
 	unsigned int volume_l;
 	unsigned int volume_r;
 	unsigned int volume_r;
 	unsigned int bass;
 	unsigned int bass;
 	unsigned int treble;
 	unsigned int treble;
 	unsigned int synth;
 	unsigned int synth;
-} pss_mixerdata;
+};
 
 
-typedef struct pss_confdata {
+struct pss_confdata {
 	int             base;
 	int             base;
 	int             irq;
 	int             irq;
 	int             dma;
 	int             dma;
 	int            *osp;
 	int            *osp;
-	pss_mixerdata   mixer;
+	struct pss_mixerdata mixer;
 	int             ad_mixer_dev;
 	int             ad_mixer_dev;
-} pss_confdata;
+};
   
   
-static pss_confdata pss_data;
-static pss_confdata *devc = &pss_data;
+static struct pss_confdata pss_data;
+static struct pss_confdata *devc = &pss_data;
 static DEFINE_SPINLOCK(lock);
 static DEFINE_SPINLOCK(lock);
 
 
 static int      pss_initialized;
 static int      pss_initialized;
@@ -150,7 +150,7 @@ static int	pss_cdrom_port = -1;	/* Parameter for the PSS cdrom port */
 static bool	pss_enable_joystick;    /* Parameter for enabling the joystick */
 static bool	pss_enable_joystick;    /* Parameter for enabling the joystick */
 static coproc_operations pss_coproc_operations;
 static coproc_operations pss_coproc_operations;
 
 
-static void pss_write(pss_confdata *devc, int data)
+static void pss_write(struct pss_confdata *devc, int data)
 {
 {
 	unsigned long i, limit;
 	unsigned long i, limit;
 
 
@@ -206,7 +206,7 @@ static int __init probe_pss(struct address_info *hw_config)
 	return 1;
 	return 1;
 }
 }
 
 
-static int set_irq(pss_confdata * devc, int dev, int irq)
+static int set_irq(struct pss_confdata *devc, int dev, int irq)
 {
 {
 	static unsigned short irq_bits[16] =
 	static unsigned short irq_bits[16] =
 	{
 	{
@@ -232,7 +232,7 @@ static int set_irq(pss_confdata * devc, int dev, int irq)
 	return 1;
 	return 1;
 }
 }
 
 
-static void set_io_base(pss_confdata * devc, int dev, int base)
+static void set_io_base(struct pss_confdata *devc, int dev, int base)
 {
 {
 	unsigned short  tmp = inw(REG(dev)) & 0x003f;
 	unsigned short  tmp = inw(REG(dev)) & 0x003f;
 	unsigned short  bits = (base & 0x0ffc) << 4;
 	unsigned short  bits = (base & 0x0ffc) << 4;
@@ -240,7 +240,7 @@ static void set_io_base(pss_confdata * devc, int dev, int base)
 	outw(bits | tmp, REG(dev));
 	outw(bits | tmp, REG(dev));
 }
 }
 
 
-static int set_dma(pss_confdata * devc, int dev, int dma)
+static int set_dma(struct pss_confdata *devc, int dev, int dma)
 {
 {
 	static unsigned short dma_bits[8] =
 	static unsigned short dma_bits[8] =
 	{
 	{
@@ -264,7 +264,7 @@ static int set_dma(pss_confdata * devc, int dev, int dma)
 	return 1;
 	return 1;
 }
 }
 
 
-static int pss_reset_dsp(pss_confdata * devc)
+static int pss_reset_dsp(struct pss_confdata *devc)
 {
 {
 	unsigned long   i, limit = jiffies + HZ/10;
 	unsigned long   i, limit = jiffies + HZ/10;
 
 
@@ -275,7 +275,7 @@ static int pss_reset_dsp(pss_confdata * devc)
 	return 1;
 	return 1;
 }
 }
 
 
-static int pss_put_dspword(pss_confdata * devc, unsigned short word)
+static int pss_put_dspword(struct pss_confdata *devc, unsigned short word)
 {
 {
 	int i, val;
 	int i, val;
 
 
@@ -291,7 +291,7 @@ static int pss_put_dspword(pss_confdata * devc, unsigned short word)
 	return 0;
 	return 0;
 }
 }
 
 
-static int pss_get_dspword(pss_confdata * devc, unsigned short *word)
+static int pss_get_dspword(struct pss_confdata *devc, unsigned short *word)
 {
 {
 	int i, val;
 	int i, val;
 
 
@@ -307,7 +307,8 @@ static int pss_get_dspword(pss_confdata * devc, unsigned short *word)
 	return 0;
 	return 0;
 }
 }
 
 
-static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size, int flags)
+static int pss_download_boot(struct pss_confdata *devc, unsigned char *block,
+			     int size, int flags)
 {
 {
 	int i, val, count;
 	int i, val, count;
 	unsigned long limit;
 	unsigned long limit;
@@ -397,7 +398,7 @@ static int pss_download_boot(pss_confdata * devc, unsigned char *block, int size
 }
 }
 
 
 /* Mixer */
 /* Mixer */
-static void set_master_volume(pss_confdata *devc, int left, int right)
+static void set_master_volume(struct pss_confdata *devc, int left, int right)
 {
 {
 	static unsigned char log_scale[101] =  {
 	static unsigned char log_scale[101] =  {
 		0xdb, 0xe0, 0xe3, 0xe5, 0xe7, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee,
 		0xdb, 0xe0, 0xe3, 0xe5, 0xe7, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xed, 0xee,
@@ -416,7 +417,7 @@ static void set_master_volume(pss_confdata *devc, int left, int right)
 	pss_write(devc, log_scale[right] | 0x0100);
 	pss_write(devc, log_scale[right] | 0x0100);
 }
 }
 
 
-static void set_synth_volume(pss_confdata *devc, int volume)
+static void set_synth_volume(struct pss_confdata *devc, int volume)
 {
 {
 	int vol = ((0x8000*volume)/100L);
 	int vol = ((0x8000*volume)/100L);
 	pss_write(devc, 0x0080);
 	pss_write(devc, 0x0080);
@@ -425,21 +426,21 @@ static void set_synth_volume(pss_confdata *devc, int volume)
 	pss_write(devc, vol);
 	pss_write(devc, vol);
 }
 }
 
 
-static void set_bass(pss_confdata *devc, int level)
+static void set_bass(struct pss_confdata *devc, int level)
 {
 {
 	int vol = (int)(((0xfd - 0xf0) * level)/100L) + 0xf0;
 	int vol = (int)(((0xfd - 0xf0) * level)/100L) + 0xf0;
 	pss_write(devc, 0x0010);
 	pss_write(devc, 0x0010);
 	pss_write(devc, vol | 0x0200);
 	pss_write(devc, vol | 0x0200);
 };
 };
 
 
-static void set_treble(pss_confdata *devc, int level)
+static void set_treble(struct pss_confdata *devc, int level)
 {	
 {	
 	int vol = (((0xfd - 0xf0) * level)/100L) + 0xf0;
 	int vol = (((0xfd - 0xf0) * level)/100L) + 0xf0;
 	pss_write(devc, 0x0010);
 	pss_write(devc, 0x0010);
 	pss_write(devc, vol | 0x0300);
 	pss_write(devc, vol | 0x0300);
 };
 };
 
 
-static void pss_mixer_reset(pss_confdata *devc)
+static void pss_mixer_reset(struct pss_confdata *devc)
 {
 {
 	set_master_volume(devc, 33, 33);
 	set_master_volume(devc, 33, 33);
 	set_bass(devc, 50);
 	set_bass(devc, 50);
@@ -499,7 +500,8 @@ static int ret_vol_stereo(int left, int right)
 	return ((right << 8) | left);
 	return ((right << 8) | left);
 }
 }
 
 
-static int call_ad_mixer(pss_confdata *devc,unsigned int cmd, void __user *arg)
+static int call_ad_mixer(struct pss_confdata *devc, unsigned int cmd,
+			 void __user *arg)
 {
 {
 	if (devc->ad_mixer_dev != NO_WSS_MIXER) 
 	if (devc->ad_mixer_dev != NO_WSS_MIXER) 
 		return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev, cmd, arg);
 		return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev, cmd, arg);
@@ -509,7 +511,7 @@ static int call_ad_mixer(pss_confdata *devc,unsigned int cmd, void __user *arg)
 
 
 static int pss_mixer_ioctl (int dev, unsigned int cmd, void __user *arg)
 static int pss_mixer_ioctl (int dev, unsigned int cmd, void __user *arg)
 {
 {
-	pss_confdata *devc = mixer_devs[dev]->devc;
+	struct pss_confdata *devc = mixer_devs[dev]->devc;
 	int cmdf = cmd & 0xff;
 	int cmdf = cmd & 0xff;
 	
 	
 	if ((cmdf != SOUND_MIXER_VOLUME) && (cmdf != SOUND_MIXER_BASS) &&
 	if ((cmdf != SOUND_MIXER_VOLUME) && (cmdf != SOUND_MIXER_BASS) &&

+ 2 - 2
sound/pci/Kconfig

@@ -858,8 +858,8 @@ config SND_VIRTUOSO
 	select SND_JACK if INPUT=y || INPUT=SND
 	select SND_JACK if INPUT=y || INPUT=SND
 	help
 	help
 	  Say Y here to include support for sound cards based on the
 	  Say Y here to include support for sound cards based on the
-	  Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS,
-	  Essence ST (Deluxe), and Essence STX.
+	  Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS, DSX,
+	  Essence ST (Deluxe), and Essence STX (II).
 	  Support for the HDAV1.3 (Deluxe) and HDAV1.3 Slim is experimental;
 	  Support for the HDAV1.3 (Deluxe) and HDAV1.3 Slim is experimental;
 	  for the Xense, missing.
 	  for the Xense, missing.
 
 

+ 0 - 6
sound/pci/echoaudio/echoaudio.c

@@ -1754,9 +1754,6 @@ static struct snd_kcontrol_new snd_echo_vumeters_switch = {
 static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol,
 static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol,
 				  struct snd_ctl_elem_info *uinfo)
 				  struct snd_ctl_elem_info *uinfo)
 {
 {
-	struct echoaudio *chip;
-
-	chip = snd_kcontrol_chip(kcontrol);
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = 96;
 	uinfo->count = 96;
 	uinfo->value.integer.min = ECHOGAIN_MINOUT;
 	uinfo->value.integer.min = ECHOGAIN_MINOUT;
@@ -1798,9 +1795,6 @@ static struct snd_kcontrol_new snd_echo_vumeters = {
 static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol,
 static int snd_echo_channels_info_info(struct snd_kcontrol *kcontrol,
 				       struct snd_ctl_elem_info *uinfo)
 				       struct snd_ctl_elem_info *uinfo)
 {
 {
-	struct echoaudio *chip;
-
-	chip = snd_kcontrol_chip(kcontrol);
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
 	uinfo->count = 6;
 	uinfo->count = 6;
 	uinfo->value.integer.min = 0;
 	uinfo->value.integer.min = 0;

+ 76 - 0
sound/pci/hda/dell_wmi_helper.c

@@ -0,0 +1,76 @@
+/* Helper functions for Dell Mic Mute LED control;
+ * to be included from codec driver
+ */
+
+#if IS_ENABLED(CONFIG_LEDS_DELL_NETBOOKS)
+#include <linux/dell-led.h>
+
+static int dell_led_value;
+static int (*dell_led_set_func)(int, int);
+static void (*dell_old_cap_hook)(struct hda_codec *,
+			         struct snd_kcontrol *,
+				 struct snd_ctl_elem_value *);
+
+static void update_dell_wmi_micmute_led(struct hda_codec *codec,
+				        struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	if (dell_old_cap_hook)
+		dell_old_cap_hook(codec, kcontrol, ucontrol);
+
+	if (!ucontrol || !dell_led_set_func)
+		return;
+	if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
+		/* TODO: How do I verify if it's a mono or stereo here? */
+		int val = (ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]) ? 0 : 1;
+		if (val == dell_led_value)
+			return;
+		dell_led_value = val;
+		if (dell_led_set_func)
+			dell_led_set_func(DELL_LED_MICMUTE, dell_led_value);
+	}
+}
+
+
+static void alc_fixup_dell_wmi(struct hda_codec *codec,
+			       const struct hda_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+	bool removefunc = false;
+
+	if (action == HDA_FIXUP_ACT_PROBE) {
+		if (!dell_led_set_func)
+			dell_led_set_func = symbol_request(dell_app_wmi_led_set);
+		if (!dell_led_set_func) {
+			codec_warn(codec, "Failed to find dell wmi symbol dell_app_wmi_led_set\n");
+			return;
+		}
+
+		removefunc = true;
+		if (dell_led_set_func(DELL_LED_MICMUTE, false) >= 0) {
+			dell_led_value = 0;
+			if (spec->gen.num_adc_nids > 1)
+				codec_dbg(codec, "Skipping micmute LED control due to several ADCs");
+			else {
+				dell_old_cap_hook = spec->gen.cap_sync_hook;
+				spec->gen.cap_sync_hook = update_dell_wmi_micmute_led;
+				removefunc = false;
+			}
+		}
+
+	}
+
+	if (dell_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
+		symbol_put(dell_app_wmi_led_set);
+		dell_led_set_func = NULL;
+		dell_old_cap_hook = NULL;
+	}
+}
+
+#else /* CONFIG_LEDS_DELL_NETBOOKS */
+static void alc_fixup_dell_wmi(struct hda_codec *codec,
+			       const struct hda_fixup *fix, int action)
+{
+}
+
+#endif /* CONFIG_LEDS_DELL_NETBOOKS */

+ 8 - 9
sound/pci/hda/hda_auto_parser.c

@@ -17,8 +17,6 @@
 #include "hda_local.h"
 #include "hda_local.h"
 #include "hda_auto_parser.h"
 #include "hda_auto_parser.h"
 
 
-#define SFX	"hda_codec: "
-
 /*
 /*
  * Helper for automatic pin configuration
  * Helper for automatic pin configuration
  */
  */
@@ -856,7 +854,7 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec,
 {
 {
 	const struct snd_hda_pin_quirk *pq;
 	const struct snd_hda_pin_quirk *pq;
 
 
-	if (codec->fixup_forced)
+	if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
 		return;
 		return;
 
 
 	for (pq = pin_quirk; pq->subvendor; pq++) {
 	for (pq = pin_quirk; pq->subvendor; pq++) {
@@ -882,14 +880,17 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
 			const struct hda_fixup *fixlist)
 			const struct hda_fixup *fixlist)
 {
 {
 	const struct snd_pci_quirk *q;
 	const struct snd_pci_quirk *q;
-	int id = -1;
+	int id = HDA_FIXUP_ID_NOT_SET;
 	const char *name = NULL;
 	const char *name = NULL;
 
 
+	if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
+		return;
+
 	/* when model=nofixup is given, don't pick up any fixups */
 	/* when model=nofixup is given, don't pick up any fixups */
 	if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
 	if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
 		codec->fixup_list = NULL;
 		codec->fixup_list = NULL;
-		codec->fixup_id = -1;
-		codec->fixup_forced = 1;
+		codec->fixup_name = NULL;
+		codec->fixup_id = HDA_FIXUP_ID_NO_FIXUP;
 		return;
 		return;
 	}
 	}
 
 
@@ -899,13 +900,12 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
 				codec->fixup_id = models->id;
 				codec->fixup_id = models->id;
 				codec->fixup_name = models->name;
 				codec->fixup_name = models->name;
 				codec->fixup_list = fixlist;
 				codec->fixup_list = fixlist;
-				codec->fixup_forced = 1;
 				return;
 				return;
 			}
 			}
 			models++;
 			models++;
 		}
 		}
 	}
 	}
-	if (id < 0 && quirk) {
+	if (quirk) {
 		q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
 		q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
 		if (q) {
 		if (q) {
 			id = q->value;
 			id = q->value;
@@ -929,7 +929,6 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
 		}
 		}
 	}
 	}
 
 
-	codec->fixup_forced = 0;
 	codec->fixup_id = id;
 	codec->fixup_id = id;
 	if (id >= 0) {
 	if (id >= 0) {
 		codec->fixup_list = fixlist;
 		codec->fixup_list = fixlist;

+ 29 - 16
sound/pci/hda/hda_codec.c

@@ -1476,6 +1476,7 @@ int snd_hda_codec_new(struct hda_bus *bus,
 
 
 	INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
 	INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
 	codec->depop_delay = -1;
 	codec->depop_delay = -1;
+	codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
 
 
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
 	spin_lock_init(&codec->power_lock);
 	spin_lock_init(&codec->power_lock);
@@ -2727,7 +2728,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
 	return 0;
 	return 0;
 }
 }
 
 
-typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *);
+typedef int (*map_slave_func_t)(struct hda_codec *, void *, struct snd_kcontrol *);
 
 
 /* apply the function to all matching slave ctls in the mixer list */
 /* apply the function to all matching slave ctls in the mixer list */
 static int map_slaves(struct hda_codec *codec, const char * const *slaves,
 static int map_slaves(struct hda_codec *codec, const char * const *slaves,
@@ -2751,7 +2752,7 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves,
 				name = tmpname;
 				name = tmpname;
 			}
 			}
 			if (!strcmp(sctl->id.name, name)) {
 			if (!strcmp(sctl->id.name, name)) {
-				err = func(data, sctl);
+				err = func(codec, data, sctl);
 				if (err)
 				if (err)
 					return err;
 					return err;
 				break;
 				break;
@@ -2761,13 +2762,15 @@ static int map_slaves(struct hda_codec *codec, const char * const *slaves,
 	return 0;
 	return 0;
 }
 }
 
 
-static int check_slave_present(void *data, struct snd_kcontrol *sctl)
+static int check_slave_present(struct hda_codec *codec,
+			       void *data, struct snd_kcontrol *sctl)
 {
 {
 	return 1;
 	return 1;
 }
 }
 
 
 /* guess the value corresponding to 0dB */
 /* guess the value corresponding to 0dB */
-static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check)
+static int get_kctl_0dB_offset(struct hda_codec *codec,
+			       struct snd_kcontrol *kctl, int *step_to_check)
 {
 {
 	int _tlv[4];
 	int _tlv[4];
 	const int *tlv = NULL;
 	const int *tlv = NULL;
@@ -2788,7 +2791,7 @@ static int get_kctl_0dB_offset(struct snd_kcontrol *kctl, int *step_to_check)
 		if (!step)
 		if (!step)
 			return -1;
 			return -1;
 		if (*step_to_check && *step_to_check != step) {
 		if (*step_to_check && *step_to_check != step) {
-			snd_printk(KERN_ERR "hda_codec: Mismatching dB step for vmaster slave (%d!=%d)\n",
+			codec_err(codec, "Mismatching dB step for vmaster slave (%d!=%d)\n",
 -				   *step_to_check, step);
 -				   *step_to_check, step);
 			return -1;
 			return -1;
 		}
 		}
@@ -2813,20 +2816,28 @@ static int put_kctl_with_value(struct snd_kcontrol *kctl, int val)
 }
 }
 
 
 /* initialize the slave volume with 0dB */
 /* initialize the slave volume with 0dB */
-static int init_slave_0dB(void *data, struct snd_kcontrol *slave)
+static int init_slave_0dB(struct hda_codec *codec,
+			  void *data, struct snd_kcontrol *slave)
 {
 {
-	int offset = get_kctl_0dB_offset(slave, data);
+	int offset = get_kctl_0dB_offset(codec, slave, data);
 	if (offset > 0)
 	if (offset > 0)
 		put_kctl_with_value(slave, offset);
 		put_kctl_with_value(slave, offset);
 	return 0;
 	return 0;
 }
 }
 
 
 /* unmute the slave */
 /* unmute the slave */
-static int init_slave_unmute(void *data, struct snd_kcontrol *slave)
+static int init_slave_unmute(struct hda_codec *codec,
+			     void *data, struct snd_kcontrol *slave)
 {
 {
 	return put_kctl_with_value(slave, 1);
 	return put_kctl_with_value(slave, 1);
 }
 }
 
 
+static int add_slave(struct hda_codec *codec,
+		     void *data, struct snd_kcontrol *slave)
+{
+	return snd_ctl_add_slave(data, slave);
+}
+
 /**
 /**
  * snd_hda_add_vmaster - create a virtual master control and add slaves
  * snd_hda_add_vmaster - create a virtual master control and add slaves
  * @codec: HD-audio codec
  * @codec: HD-audio codec
@@ -2869,8 +2880,7 @@ int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
 	if (err < 0)
 	if (err < 0)
 		return err;
 		return err;
 
 
-	err = map_slaves(codec, slaves, suffix,
-			 (map_slave_func_t)snd_ctl_add_slave, kctl);
+	err = map_slaves(codec, slaves, suffix, add_slave, kctl);
 	if (err < 0)
 	if (err < 0)
 		return err;
 		return err;
 
 
@@ -4280,6 +4290,7 @@ static struct hda_rate_tbl rate_bits[] = {
 
 
 /**
 /**
  * snd_hda_calc_stream_format - calculate format bitset
  * snd_hda_calc_stream_format - calculate format bitset
+ * @codec: HD-audio codec
  * @rate: the sample rate
  * @rate: the sample rate
  * @channels: the number of channels
  * @channels: the number of channels
  * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
  * @format: the PCM format (SNDRV_PCM_FORMAT_XXX)
@@ -4289,7 +4300,8 @@ static struct hda_rate_tbl rate_bits[] = {
  *
  *
  * Return zero if invalid.
  * Return zero if invalid.
  */
  */
-unsigned int snd_hda_calc_stream_format(unsigned int rate,
+unsigned int snd_hda_calc_stream_format(struct hda_codec *codec,
+					unsigned int rate,
 					unsigned int channels,
 					unsigned int channels,
 					unsigned int format,
 					unsigned int format,
 					unsigned int maxbps,
 					unsigned int maxbps,
@@ -4304,12 +4316,12 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
 			break;
 			break;
 		}
 		}
 	if (!rate_bits[i].hz) {
 	if (!rate_bits[i].hz) {
-		snd_printdd("invalid rate %d\n", rate);
+		codec_dbg(codec, "invalid rate %d\n", rate);
 		return 0;
 		return 0;
 	}
 	}
 
 
 	if (channels == 0 || channels > 8) {
 	if (channels == 0 || channels > 8) {
-		snd_printdd("invalid channels %d\n", channels);
+		codec_dbg(codec, "invalid channels %d\n", channels);
 		return 0;
 		return 0;
 	}
 	}
 	val |= channels - 1;
 	val |= channels - 1;
@@ -4332,7 +4344,7 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
 			val |= AC_FMT_BITS_20;
 			val |= AC_FMT_BITS_20;
 		break;
 		break;
 	default:
 	default:
-		snd_printdd("invalid format width %d\n",
+		codec_dbg(codec, "invalid format width %d\n",
 			  snd_pcm_format_width(format));
 			  snd_pcm_format_width(format));
 		return 0;
 		return 0;
 	}
 	}
@@ -5670,12 +5682,13 @@ EXPORT_SYMBOL_GPL(_snd_hda_set_pin_ctl);
  * suffix is appended to the label.  This label index number is stored
  * suffix is appended to the label.  This label index number is stored
  * to type_idx when non-NULL pointer is given.
  * to type_idx when non-NULL pointer is given.
  */
  */
-int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
+int snd_hda_add_imux_item(struct hda_codec *codec,
+			  struct hda_input_mux *imux, const char *label,
 			  int index, int *type_idx)
 			  int index, int *type_idx)
 {
 {
 	int i, label_idx = 0;
 	int i, label_idx = 0;
 	if (imux->num_items >= HDA_MAX_NUM_INPUTS) {
 	if (imux->num_items >= HDA_MAX_NUM_INPUTS) {
-		snd_printd(KERN_ERR "hda_codec: Too many imux items!\n");
+		codec_err(codec, "hda_codec: Too many imux items!\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 	for (i = 0; i < imux->num_items; i++) {
 	for (i = 0; i < imux->num_items; i++) {

+ 2 - 2
sound/pci/hda/hda_codec.h

@@ -402,7 +402,6 @@ struct hda_codec {
 
 
 	/* fix-up list */
 	/* fix-up list */
 	int fixup_id;
 	int fixup_id;
-	unsigned int fixup_forced:1; /* fixup explicitly set by user */
 	const struct hda_fixup *fixup_list;
 	const struct hda_fixup *fixup_list;
 	const char *fixup_name;
 	const char *fixup_name;
 
 
@@ -538,7 +537,8 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid,
 				    int do_now);
 				    int do_now);
 #define snd_hda_codec_cleanup_stream(codec, nid) \
 #define snd_hda_codec_cleanup_stream(codec, nid) \
 	__snd_hda_codec_cleanup_stream(codec, nid, 0)
 	__snd_hda_codec_cleanup_stream(codec, nid, 0)
-unsigned int snd_hda_calc_stream_format(unsigned int rate,
+unsigned int snd_hda_calc_stream_format(struct hda_codec *codec,
+					unsigned int rate,
 					unsigned int channels,
 					unsigned int channels,
 					unsigned int format,
 					unsigned int format,
 					unsigned int maxbps,
 					unsigned int maxbps,

+ 72 - 131
sound/pci/hda/hda_controller.c

@@ -27,6 +27,7 @@
 #include <linux/module.h>
 #include <linux/module.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
+#include <linux/reboot.h>
 #include <sound/core.h>
 #include <sound/core.h>
 #include <sound/initval.h>
 #include <sound/initval.h>
 #include "hda_priv.h"
 #include "hda_priv.h"
@@ -152,11 +153,11 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
 		      upper_32_bits(azx_dev->bdl.addr));
 		      upper_32_bits(azx_dev->bdl.addr));
 
 
 	/* enable the position buffer */
 	/* enable the position buffer */
-	if (chip->position_fix[0] != POS_FIX_LPIB ||
-	    chip->position_fix[1] != POS_FIX_LPIB) {
-		if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE))
+	if (chip->get_position[0] != azx_get_pos_lpib ||
+	    chip->get_position[1] != azx_get_pos_lpib) {
+		if (!(azx_readl(chip, DPLBASE) & AZX_DPLBASE_ENABLE))
 			azx_writel(chip, DPLBASE,
 			azx_writel(chip, DPLBASE,
-				(u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE);
+				(u32)chip->posbuf.addr | AZX_DPLBASE_ENABLE);
 	}
 	}
 
 
 	/* set the interrupt enable bits in the descriptor control register */
 	/* set the interrupt enable bits in the descriptor control register */
@@ -482,7 +483,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
 	}
 	}
 
 
 	azx_stream_reset(chip, azx_dev);
 	azx_stream_reset(chip, azx_dev);
-	format_val = snd_hda_calc_stream_format(runtime->rate,
+	format_val = snd_hda_calc_stream_format(apcm->codec,
+						runtime->rate,
 						runtime->channels,
 						runtime->channels,
 						runtime->format,
 						runtime->format,
 						hinfo->maxbps,
 						hinfo->maxbps,
@@ -673,125 +675,40 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 	return 0;
 	return 0;
 }
 }
 
 
-/* get the current DMA position with correction on VIA chips */
-static unsigned int azx_via_get_position(struct azx *chip,
-					 struct azx_dev *azx_dev)
+unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev)
 {
 {
-	unsigned int link_pos, mini_pos, bound_pos;
-	unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos;
-	unsigned int fifo_size;
-
-	link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
-	if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-		/* Playback, no problem using link position */
-		return link_pos;
-	}
-
-	/* Capture */
-	/* For new chipset,
-	 * use mod to get the DMA position just like old chipset
-	 */
-	mod_dma_pos = le32_to_cpu(*azx_dev->posbuf);
-	mod_dma_pos %= azx_dev->period_bytes;
-
-	/* azx_dev->fifo_size can't get FIFO size of in stream.
-	 * Get from base address + offset.
-	 */
-	fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET);
-
-	if (azx_dev->insufficient) {
-		/* Link position never gather than FIFO size */
-		if (link_pos <= fifo_size)
-			return 0;
-
-		azx_dev->insufficient = 0;
-	}
-
-	if (link_pos <= fifo_size)
-		mini_pos = azx_dev->bufsize + link_pos - fifo_size;
-	else
-		mini_pos = link_pos - fifo_size;
-
-	/* Find nearest previous boudary */
-	mod_mini_pos = mini_pos % azx_dev->period_bytes;
-	mod_link_pos = link_pos % azx_dev->period_bytes;
-	if (mod_link_pos >= fifo_size)
-		bound_pos = link_pos - mod_link_pos;
-	else if (mod_dma_pos >= mod_mini_pos)
-		bound_pos = mini_pos - mod_mini_pos;
-	else {
-		bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes;
-		if (bound_pos >= azx_dev->bufsize)
-			bound_pos = 0;
-	}
+	return azx_sd_readl(chip, azx_dev, SD_LPIB);
+}
+EXPORT_SYMBOL_GPL(azx_get_pos_lpib);
 
 
-	/* Calculate real DMA position we want */
-	return bound_pos + mod_dma_pos;
+unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev)
+{
+	return le32_to_cpu(*azx_dev->posbuf);
 }
 }
+EXPORT_SYMBOL_GPL(azx_get_pos_posbuf);
 
 
 unsigned int azx_get_position(struct azx *chip,
 unsigned int azx_get_position(struct azx *chip,
-			      struct azx_dev *azx_dev,
-			      bool with_check)
+			      struct azx_dev *azx_dev)
 {
 {
 	struct snd_pcm_substream *substream = azx_dev->substream;
 	struct snd_pcm_substream *substream = azx_dev->substream;
-	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
 	unsigned int pos;
 	unsigned int pos;
 	int stream = substream->stream;
 	int stream = substream->stream;
-	struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
 	int delay = 0;
 	int delay = 0;
 
 
-	switch (chip->position_fix[stream]) {
-	case POS_FIX_LPIB:
-		/* read LPIB */
-		pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
-		break;
-	case POS_FIX_VIACOMBO:
-		pos = azx_via_get_position(chip, azx_dev);
-		break;
-	default:
-		/* use the position buffer */
-		pos = le32_to_cpu(*azx_dev->posbuf);
-		if (with_check && chip->position_fix[stream] == POS_FIX_AUTO) {
-			if (!pos || pos == (u32)-1) {
-				dev_info(chip->card->dev,
-					 "Invalid position buffer, using LPIB read method instead.\n");
-				chip->position_fix[stream] = POS_FIX_LPIB;
-				pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
-			} else
-				chip->position_fix[stream] = POS_FIX_POSBUF;
-		}
-		break;
-	}
+	if (chip->get_position[stream])
+		pos = chip->get_position[stream](chip, azx_dev);
+	else /* use the position buffer as default */
+		pos = azx_get_pos_posbuf(chip, azx_dev);
 
 
 	if (pos >= azx_dev->bufsize)
 	if (pos >= azx_dev->bufsize)
 		pos = 0;
 		pos = 0;
 
 
-	/* calculate runtime delay from LPIB */
-	if (substream->runtime &&
-	    chip->position_fix[stream] == POS_FIX_POSBUF &&
-	    (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
-		unsigned int lpib_pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
-		if (stream == SNDRV_PCM_STREAM_PLAYBACK)
-			delay = pos - lpib_pos;
-		else
-			delay = lpib_pos - pos;
-		if (delay < 0) {
-			if (delay >= azx_dev->delay_negative_threshold)
-				delay = 0;
-			else
-				delay += azx_dev->bufsize;
-		}
-		if (delay >= azx_dev->period_bytes) {
-			dev_info(chip->card->dev,
-				 "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n",
-				 delay, azx_dev->period_bytes);
-			delay = 0;
-			chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
-		}
-		delay = bytes_to_frames(substream->runtime, delay);
-	}
-
 	if (substream->runtime) {
 	if (substream->runtime) {
+		struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+		struct hda_pcm_stream *hinfo = apcm->hinfo[stream];
+
+		if (chip->get_delay[stream])
+			delay += chip->get_delay[stream](chip, azx_dev, pos);
 		if (hinfo->ops.get_delay)
 		if (hinfo->ops.get_delay)
 			delay += hinfo->ops.get_delay(hinfo, apcm->codec,
 			delay += hinfo->ops.get_delay(hinfo, apcm->codec,
 						      substream);
 						      substream);
@@ -809,7 +726,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
 	struct azx *chip = apcm->chip;
 	struct azx *chip = apcm->chip;
 	struct azx_dev *azx_dev = get_azx_dev(substream);
 	struct azx_dev *azx_dev = get_azx_dev(substream);
 	return bytes_to_frames(substream->runtime,
 	return bytes_to_frames(substream->runtime,
-			       azx_get_position(chip, azx_dev, false));
+			       azx_get_position(chip, azx_dev));
 }
 }
 
 
 static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
 static int azx_get_wallclock_tstamp(struct snd_pcm_substream *substream,
@@ -1059,10 +976,10 @@ static void azx_init_cmd_io(struct azx *chip)
 	azx_writew(chip, CORBWP, 0);
 	azx_writew(chip, CORBWP, 0);
 
 
 	/* reset the corb hw read pointer */
 	/* reset the corb hw read pointer */
-	azx_writew(chip, CORBRP, ICH6_CORBRP_RST);
+	azx_writew(chip, CORBRP, AZX_CORBRP_RST);
 	if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) {
 	if (!(chip->driver_caps & AZX_DCAPS_CORBRP_SELF_CLEAR)) {
 		for (timeout = 1000; timeout > 0; timeout--) {
 		for (timeout = 1000; timeout > 0; timeout--) {
-			if ((azx_readw(chip, CORBRP) & ICH6_CORBRP_RST) == ICH6_CORBRP_RST)
+			if ((azx_readw(chip, CORBRP) & AZX_CORBRP_RST) == AZX_CORBRP_RST)
 				break;
 				break;
 			udelay(1);
 			udelay(1);
 		}
 		}
@@ -1082,7 +999,7 @@ static void azx_init_cmd_io(struct azx *chip)
 	}
 	}
 
 
 	/* enable corb dma */
 	/* enable corb dma */
-	azx_writeb(chip, CORBCTL, ICH6_CORBCTL_RUN);
+	azx_writeb(chip, CORBCTL, AZX_CORBCTL_RUN);
 
 
 	/* RIRB set up */
 	/* RIRB set up */
 	chip->rirb.addr = chip->rb.addr + 2048;
 	chip->rirb.addr = chip->rb.addr + 2048;
@@ -1095,14 +1012,14 @@ static void azx_init_cmd_io(struct azx *chip)
 	/* set the rirb size to 256 entries (ULI requires explicitly) */
 	/* set the rirb size to 256 entries (ULI requires explicitly) */
 	azx_writeb(chip, RIRBSIZE, 0x02);
 	azx_writeb(chip, RIRBSIZE, 0x02);
 	/* reset the rirb hw write pointer */
 	/* reset the rirb hw write pointer */
-	azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST);
+	azx_writew(chip, RIRBWP, AZX_RIRBWP_RST);
 	/* set N=1, get RIRB response interrupt for new entry */
 	/* set N=1, get RIRB response interrupt for new entry */
 	if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
 	if (chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND)
 		azx_writew(chip, RINTCNT, 0xc0);
 		azx_writew(chip, RINTCNT, 0xc0);
 	else
 	else
 		azx_writew(chip, RINTCNT, 1);
 		azx_writew(chip, RINTCNT, 1);
 	/* enable rirb dma and response irq */
 	/* enable rirb dma and response irq */
-	azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN);
+	azx_writeb(chip, RIRBCTL, AZX_RBCTL_DMA_EN | AZX_RBCTL_IRQ_EN);
 	spin_unlock_irq(&chip->reg_lock);
 	spin_unlock_irq(&chip->reg_lock);
 }
 }
 EXPORT_SYMBOL_GPL(azx_init_cmd_io);
 EXPORT_SYMBOL_GPL(azx_init_cmd_io);
@@ -1146,7 +1063,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
 		return -EIO;
 		return -EIO;
 	}
 	}
 	wp++;
 	wp++;
-	wp %= ICH6_MAX_CORB_ENTRIES;
+	wp %= AZX_MAX_CORB_ENTRIES;
 
 
 	rp = azx_readw(chip, CORBRP);
 	rp = azx_readw(chip, CORBRP);
 	if (wp == rp) {
 	if (wp == rp) {
@@ -1164,7 +1081,7 @@ static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
 	return 0;
 	return 0;
 }
 }
 
 
-#define ICH6_RIRB_EX_UNSOL_EV	(1<<4)
+#define AZX_RIRB_EX_UNSOL_EV	(1<<4)
 
 
 /* retrieve RIRB entry - called from interrupt handler */
 /* retrieve RIRB entry - called from interrupt handler */
 static void azx_update_rirb(struct azx *chip)
 static void azx_update_rirb(struct azx *chip)
@@ -1185,7 +1102,7 @@ static void azx_update_rirb(struct azx *chip)
 
 
 	while (chip->rirb.rp != wp) {
 	while (chip->rirb.rp != wp) {
 		chip->rirb.rp++;
 		chip->rirb.rp++;
-		chip->rirb.rp %= ICH6_MAX_RIRB_ENTRIES;
+		chip->rirb.rp %= AZX_MAX_RIRB_ENTRIES;
 
 
 		rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
 		rp = chip->rirb.rp << 1; /* an RIRB entry is 8-bytes */
 		res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
 		res_ex = le32_to_cpu(chip->rirb.buf[rp + 1]);
@@ -1196,8 +1113,7 @@ static void azx_update_rirb(struct azx *chip)
 				res, res_ex,
 				res, res_ex,
 				chip->rirb.rp, wp);
 				chip->rirb.rp, wp);
 			snd_BUG();
 			snd_BUG();
-		}
-		else if (res_ex & ICH6_RIRB_EX_UNSOL_EV)
+		} else if (res_ex & AZX_RIRB_EX_UNSOL_EV)
 			snd_hda_queue_unsol_event(chip->bus, res, res_ex);
 			snd_hda_queue_unsol_event(chip->bus, res, res_ex);
 		else if (chip->rirb.cmds[addr]) {
 		else if (chip->rirb.cmds[addr]) {
 			chip->rirb.res[addr] = res;
 			chip->rirb.res[addr] = res;
@@ -1305,7 +1221,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus,
 	/* release CORB/RIRB */
 	/* release CORB/RIRB */
 	azx_free_cmd_io(chip);
 	azx_free_cmd_io(chip);
 	/* disable unsolicited responses */
 	/* disable unsolicited responses */
-	azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_UNSOL);
+	azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_UNSOL);
 	return -1;
 	return -1;
 }
 }
 
 
@@ -1326,7 +1242,7 @@ static int azx_single_wait_for_response(struct azx *chip, unsigned int addr)
 
 
 	while (timeout--) {
 	while (timeout--) {
 		/* check IRV busy bit */
 		/* check IRV busy bit */
-		if (azx_readw(chip, IRS) & ICH6_IRS_VALID) {
+		if (azx_readw(chip, IRS) & AZX_IRS_VALID) {
 			/* reuse rirb.res as the response return value */
 			/* reuse rirb.res as the response return value */
 			chip->rirb.res[addr] = azx_readl(chip, IR);
 			chip->rirb.res[addr] = azx_readl(chip, IR);
 			return 0;
 			return 0;
@@ -1350,13 +1266,13 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
 	bus->rirb_error = 0;
 	bus->rirb_error = 0;
 	while (timeout--) {
 	while (timeout--) {
 		/* check ICB busy bit */
 		/* check ICB busy bit */
-		if (!((azx_readw(chip, IRS) & ICH6_IRS_BUSY))) {
+		if (!((azx_readw(chip, IRS) & AZX_IRS_BUSY))) {
 			/* Clear IRV valid bit */
 			/* Clear IRV valid bit */
 			azx_writew(chip, IRS, azx_readw(chip, IRS) |
 			azx_writew(chip, IRS, azx_readw(chip, IRS) |
-				   ICH6_IRS_VALID);
+				   AZX_IRS_VALID);
 			azx_writel(chip, IC, val);
 			azx_writel(chip, IC, val);
 			azx_writew(chip, IRS, azx_readw(chip, IRS) |
 			azx_writew(chip, IRS, azx_readw(chip, IRS) |
-				   ICH6_IRS_BUSY);
+				   AZX_IRS_BUSY);
 			return azx_single_wait_for_response(chip, addr);
 			return azx_single_wait_for_response(chip, addr);
 		}
 		}
 		udelay(1);
 		udelay(1);
@@ -1585,10 +1501,10 @@ void azx_enter_link_reset(struct azx *chip)
 	unsigned long timeout;
 	unsigned long timeout;
 
 
 	/* reset controller */
 	/* reset controller */
-	azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~ICH6_GCTL_RESET);
+	azx_writel(chip, GCTL, azx_readl(chip, GCTL) & ~AZX_GCTL_RESET);
 
 
 	timeout = jiffies + msecs_to_jiffies(100);
 	timeout = jiffies + msecs_to_jiffies(100);
-	while ((azx_readb(chip, GCTL) & ICH6_GCTL_RESET) &&
+	while ((azx_readb(chip, GCTL) & AZX_GCTL_RESET) &&
 			time_before(jiffies, timeout))
 			time_before(jiffies, timeout))
 		usleep_range(500, 1000);
 		usleep_range(500, 1000);
 }
 }
@@ -1599,7 +1515,7 @@ static void azx_exit_link_reset(struct azx *chip)
 {
 {
 	unsigned long timeout;
 	unsigned long timeout;
 
 
-	azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | ICH6_GCTL_RESET);
+	azx_writeb(chip, GCTL, azx_readb(chip, GCTL) | AZX_GCTL_RESET);
 
 
 	timeout = jiffies + msecs_to_jiffies(100);
 	timeout = jiffies + msecs_to_jiffies(100);
 	while (!azx_readb(chip, GCTL) &&
 	while (!azx_readb(chip, GCTL) &&
@@ -1640,7 +1556,7 @@ static int azx_reset(struct azx *chip, bool full_reset)
 	/* Accept unsolicited responses */
 	/* Accept unsolicited responses */
 	if (!chip->single_cmd)
 	if (!chip->single_cmd)
 		azx_writel(chip, GCTL, azx_readl(chip, GCTL) |
 		azx_writel(chip, GCTL, azx_readl(chip, GCTL) |
-			   ICH6_GCTL_UNSOL);
+			   AZX_GCTL_UNSOL);
 
 
 	/* detect codecs */
 	/* detect codecs */
 	if (!chip->codec_mask) {
 	if (!chip->codec_mask) {
@@ -1657,7 +1573,7 @@ static void azx_int_enable(struct azx *chip)
 {
 {
 	/* enable controller CIE and GIE */
 	/* enable controller CIE and GIE */
 	azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) |
 	azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) |
-		   ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN);
+		   AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN);
 }
 }
 
 
 /* disable interrupts */
 /* disable interrupts */
@@ -1678,7 +1594,7 @@ static void azx_int_disable(struct azx *chip)
 
 
 	/* disable controller CIE and GIE */
 	/* disable controller CIE and GIE */
 	azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) &
 	azx_writel(chip, INTCTL, azx_readl(chip, INTCTL) &
-		   ~(ICH6_INT_CTRL_EN | ICH6_INT_GLOBAL_EN));
+		   ~(AZX_INT_CTRL_EN | AZX_INT_GLOBAL_EN));
 }
 }
 
 
 /* clear interrupts */
 /* clear interrupts */
@@ -1699,7 +1615,7 @@ static void azx_int_clear(struct azx *chip)
 	azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
 	azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
 
 
 	/* clear int status */
 	/* clear int status */
-	azx_writel(chip, INTSTS, ICH6_INT_CTRL_EN | ICH6_INT_ALL_STREAM);
+	azx_writel(chip, INTSTS, AZX_INT_CTRL_EN | AZX_INT_ALL_STREAM);
 }
 }
 
 
 /*
 /*
@@ -2031,5 +1947,30 @@ int azx_init_stream(struct azx *chip)
 }
 }
 EXPORT_SYMBOL_GPL(azx_init_stream);
 EXPORT_SYMBOL_GPL(azx_init_stream);
 
 
+/*
+ * reboot notifier for hang-up problem at power-down
+ */
+static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf)
+{
+	struct azx *chip = container_of(nb, struct azx, reboot_notifier);
+	snd_hda_bus_reboot_notify(chip->bus);
+	azx_stop_chip(chip);
+	return NOTIFY_OK;
+}
+
+void azx_notifier_register(struct azx *chip)
+{
+	chip->reboot_notifier.notifier_call = azx_halt;
+	register_reboot_notifier(&chip->reboot_notifier);
+}
+EXPORT_SYMBOL_GPL(azx_notifier_register);
+
+void azx_notifier_unregister(struct azx *chip)
+{
+	if (chip->reboot_notifier.notifier_call)
+		unregister_reboot_notifier(&chip->reboot_notifier);
+}
+EXPORT_SYMBOL_GPL(azx_notifier_unregister);
+
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Common HDA driver funcitons");
 MODULE_DESCRIPTION("Common HDA driver funcitons");

+ 6 - 3
sound/pci/hda/hda_controller.h

@@ -25,9 +25,9 @@ static inline struct azx_dev *get_azx_dev(struct snd_pcm_substream *substream)
 {
 {
 	return substream->runtime->private_data;
 	return substream->runtime->private_data;
 }
 }
-unsigned int azx_get_position(struct azx *chip,
-			      struct azx_dev *azx_dev,
-			      bool with_check);
+unsigned int azx_get_position(struct azx *chip, struct azx_dev *azx_dev);
+unsigned int azx_get_pos_lpib(struct azx *chip, struct azx_dev *azx_dev);
+unsigned int azx_get_pos_posbuf(struct azx *chip, struct azx_dev *azx_dev);
 
 
 /* Stream control. */
 /* Stream control. */
 void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev);
 void azx_stream_stop(struct azx *chip, struct azx_dev *azx_dev);
@@ -50,4 +50,7 @@ int azx_codec_configure(struct azx *chip);
 int azx_mixer_create(struct azx *chip);
 int azx_mixer_create(struct azx *chip);
 int azx_init_stream(struct azx *chip);
 int azx_init_stream(struct azx *chip);
 
 
+void azx_notifier_register(struct azx *chip);
+void azx_notifier_unregister(struct azx *chip);
+
 #endif /* __SOUND_HDA_CONTROLLER_H */
 #endif /* __SOUND_HDA_CONTROLLER_H */

+ 22 - 24
sound/pci/hda/hda_eld.c

@@ -167,7 +167,8 @@ static unsigned int hdmi_get_eld_data(struct hda_codec *codec, hda_nid_t nid,
 	(buf[byte] >> (lowbit)) & ((1 << (bits)) - 1);	\
 	(buf[byte] >> (lowbit)) & ((1 << (bits)) - 1);	\
 })
 })
 
 
-static void hdmi_update_short_audio_desc(struct cea_sad *a,
+static void hdmi_update_short_audio_desc(struct hda_codec *codec,
+					 struct cea_sad *a,
 					 const unsigned char *buf)
 					 const unsigned char *buf)
 {
 {
 	int i;
 	int i;
@@ -188,8 +189,7 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
 	a->format = GRAB_BITS(buf, 0, 3, 4);
 	a->format = GRAB_BITS(buf, 0, 3, 4);
 	switch (a->format) {
 	switch (a->format) {
 	case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
 	case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
-		snd_printd(KERN_INFO
-				"HDMI: audio coding type 0 not expected\n");
+		codec_info(codec, "HDMI: audio coding type 0 not expected\n");
 		break;
 		break;
 
 
 	case AUDIO_CODING_TYPE_LPCM:
 	case AUDIO_CODING_TYPE_LPCM:
@@ -233,9 +233,9 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
 		a->format = GRAB_BITS(buf, 2, 3, 5);
 		a->format = GRAB_BITS(buf, 2, 3, 5);
 		if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT ||
 		if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT ||
 		    a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) {
 		    a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) {
-			snd_printd(KERN_INFO
-				"HDMI: audio coding xtype %d not expected\n",
-				a->format);
+			codec_info(codec,
+				   "HDMI: audio coding xtype %d not expected\n",
+				   a->format);
 			a->format = 0;
 			a->format = 0;
 		} else
 		} else
 			a->format += AUDIO_CODING_TYPE_HE_AAC -
 			a->format += AUDIO_CODING_TYPE_HE_AAC -
@@ -247,7 +247,7 @@ static void hdmi_update_short_audio_desc(struct cea_sad *a,
 /*
 /*
  * Be careful, ELD buf could be totally rubbish!
  * Be careful, ELD buf could be totally rubbish!
  */
  */
-int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e,
+int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e,
 			  const unsigned char *buf, int size)
 			  const unsigned char *buf, int size)
 {
 {
 	int mnl;
 	int mnl;
@@ -256,8 +256,7 @@ int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e,
 	e->eld_ver = GRAB_BITS(buf, 0, 3, 5);
 	e->eld_ver = GRAB_BITS(buf, 0, 3, 5);
 	if (e->eld_ver != ELD_VER_CEA_861D &&
 	if (e->eld_ver != ELD_VER_CEA_861D &&
 	    e->eld_ver != ELD_VER_PARTIAL) {
 	    e->eld_ver != ELD_VER_PARTIAL) {
-		snd_printd(KERN_INFO "HDMI: Unknown ELD version %d\n",
-								e->eld_ver);
+		codec_info(codec, "HDMI: Unknown ELD version %d\n", e->eld_ver);
 		goto out_fail;
 		goto out_fail;
 	}
 	}
 
 
@@ -280,20 +279,20 @@ int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e,
 	e->product_id	  = get_unaligned_le16(buf + 18);
 	e->product_id	  = get_unaligned_le16(buf + 18);
 
 
 	if (mnl > ELD_MAX_MNL) {
 	if (mnl > ELD_MAX_MNL) {
-		snd_printd(KERN_INFO "HDMI: MNL is reserved value %d\n", mnl);
+		codec_info(codec, "HDMI: MNL is reserved value %d\n", mnl);
 		goto out_fail;
 		goto out_fail;
 	} else if (ELD_FIXED_BYTES + mnl > size) {
 	} else if (ELD_FIXED_BYTES + mnl > size) {
-		snd_printd(KERN_INFO "HDMI: out of range MNL %d\n", mnl);
+		codec_info(codec, "HDMI: out of range MNL %d\n", mnl);
 		goto out_fail;
 		goto out_fail;
 	} else
 	} else
 		strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1);
 		strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1);
 
 
 	for (i = 0; i < e->sad_count; i++) {
 	for (i = 0; i < e->sad_count; i++) {
 		if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) {
 		if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) {
-			snd_printd(KERN_INFO "HDMI: out of range SAD %d\n", i);
+			codec_info(codec, "HDMI: out of range SAD %d\n", i);
 			goto out_fail;
 			goto out_fail;
 		}
 		}
-		hdmi_update_short_audio_desc(e->sad + i,
+		hdmi_update_short_audio_desc(codec, e->sad + i,
 					buf + ELD_FIXED_BYTES + mnl + 3 * i);
 					buf + ELD_FIXED_BYTES + mnl + 3 * i);
 	}
 	}
 
 
@@ -394,7 +393,8 @@ static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
 
 
 #define SND_PRINT_RATES_ADVISED_BUFSIZE	80
 #define SND_PRINT_RATES_ADVISED_BUFSIZE	80
 
 
-static void hdmi_show_short_audio_desc(struct cea_sad *a)
+static void hdmi_show_short_audio_desc(struct hda_codec *codec,
+				       struct cea_sad *a)
 {
 {
 	char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
 	char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
 	char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits =";
 	char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits =";
@@ -412,12 +412,10 @@ static void hdmi_show_short_audio_desc(struct cea_sad *a)
 	else
 	else
 		buf2[0] = '\0';
 		buf2[0] = '\0';
 
 
-	_snd_printd(SND_PR_VERBOSE, "HDMI: supports coding type %s:"
-			" channels = %d, rates =%s%s\n",
-			cea_audio_coding_type_names[a->format],
-			a->channels,
-			buf,
-			buf2);
+	codec_dbg(codec,
+		  "HDMI: supports coding type %s: channels = %d, rates =%s%s\n",
+		  cea_audio_coding_type_names[a->format],
+		  a->channels, buf, buf2);
 }
 }
 
 
 void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
 void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
@@ -432,22 +430,22 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
 	buf[j] = '\0';	/* necessary when j == 0 */
 	buf[j] = '\0';	/* necessary when j == 0 */
 }
 }
 
 
-void snd_hdmi_show_eld(struct parsed_hdmi_eld *e)
+void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e)
 {
 {
 	int i;
 	int i;
 
 
-	_snd_printd(SND_PR_VERBOSE, "HDMI: detected monitor %s at connection type %s\n",
+	codec_dbg(codec, "HDMI: detected monitor %s at connection type %s\n",
 			e->monitor_name,
 			e->monitor_name,
 			eld_connection_type_names[e->conn_type]);
 			eld_connection_type_names[e->conn_type]);
 
 
 	if (e->spk_alloc) {
 	if (e->spk_alloc) {
 		char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
 		char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
 		snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
 		snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
-		_snd_printd(SND_PR_VERBOSE, "HDMI: available speakers:%s\n", buf);
+		codec_dbg(codec, "HDMI: available speakers:%s\n", buf);
 	}
 	}
 
 
 	for (i = 0; i < e->sad_count; i++)
 	for (i = 0; i < e->sad_count; i++)
-		hdmi_show_short_audio_desc(e->sad + i);
+		hdmi_show_short_audio_desc(codec, e->sad + i);
 }
 }
 
 
 #ifdef CONFIG_PROC_FS
 #ifdef CONFIG_PROC_FS

+ 12 - 10
sound/pci/hda/hda_generic.c

@@ -350,16 +350,16 @@ static void print_nid_path(struct hda_codec *codec,
 			   const char *pfx, struct nid_path *path)
 			   const char *pfx, struct nid_path *path)
 {
 {
 	char buf[40];
 	char buf[40];
+	char *pos = buf;
 	int i;
 	int i;
 
 
+	*pos = 0;
+	for (i = 0; i < path->depth; i++)
+		pos += scnprintf(pos, sizeof(buf) - (pos - buf), "%s%02x",
+				 pos != buf ? ":" : "",
+				 path->path[i]);
 
 
-	buf[0] = 0;
-	for (i = 0; i < path->depth; i++) {
-		char tmp[4];
-		sprintf(tmp, ":%02x", path->path[i]);
-		strlcat(buf, tmp, sizeof(buf));
-	}
-	codec_dbg(codec, "%s path: depth=%d %s\n", pfx, path->depth, buf);
+	codec_dbg(codec, "%s path: depth=%d '%s'\n", pfx, path->depth, buf);
 }
 }
 
 
 /* called recursively */
 /* called recursively */
@@ -1700,9 +1700,11 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
 #define DEBUG_BADNESS
 #define DEBUG_BADNESS
 
 
 #ifdef DEBUG_BADNESS
 #ifdef DEBUG_BADNESS
-#define debug_badness(fmt, args...)	codec_dbg(codec, fmt, ##args)
+#define debug_badness(fmt, ...)						\
+	codec_dbg(codec, fmt, ##__VA_ARGS__)
 #else
 #else
-#define debug_badness(...)
+#define debug_badness(fmt, ...)						\
+	do { if (0) codec_dbg(codec, fmt, ##__VA_ARGS__); } while (0)
 #endif
 #endif
 
 
 #ifdef DEBUG_BADNESS
 #ifdef DEBUG_BADNESS
@@ -3054,7 +3056,7 @@ static int parse_capture_source(struct hda_codec *codec, hda_nid_t pin,
 			if (spec->hp_mic_pin == pin)
 			if (spec->hp_mic_pin == pin)
 				spec->hp_mic_mux_idx = imux->num_items;
 				spec->hp_mic_mux_idx = imux->num_items;
 			spec->imux_pins[imux->num_items] = pin;
 			spec->imux_pins[imux->num_items] = pin;
-			snd_hda_add_imux_item(imux, label, cfg_idx, NULL);
+			snd_hda_add_imux_item(codec, imux, label, cfg_idx, NULL);
 			imux_added = true;
 			imux_added = true;
 			if (spec->dyn_adc_switch)
 			if (spec->dyn_adc_switch)
 				spec->dyn_adc_idx[imux_idx] = c;
 				spec->dyn_adc_idx[imux_idx] = c;

+ 2 - 2
sound/pci/hda/hda_i915.c

@@ -28,8 +28,8 @@
  * Clock) to 24MHz BCLK: BCLK = CDCLK * M / N
  * Clock) to 24MHz BCLK: BCLK = CDCLK * M / N
  * The values will be lost when the display power well is disabled.
  * The values will be lost when the display power well is disabled.
  */
  */
-#define ICH6_REG_EM4			0x100c
-#define ICH6_REG_EM5			0x1010
+#define AZX_REG_EM4			0x100c
+#define AZX_REG_EM5			0x1010
 
 
 static int (*get_power)(void);
 static int (*get_power)(void);
 static int (*put_power)(void);
 static int (*put_power)(void);

+ 293 - 79
sound/pci/hda/hda_intel.c

@@ -44,7 +44,6 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/pci.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
-#include <linux/reboot.h>
 #include <linux/io.h>
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_runtime.h>
 #include <linux/clocksource.h>
 #include <linux/clocksource.h>
@@ -66,6 +65,52 @@
 #include "hda_priv.h"
 #include "hda_priv.h"
 #include "hda_i915.h"
 #include "hda_i915.h"
 
 
+/* position fix mode */
+enum {
+	POS_FIX_AUTO,
+	POS_FIX_LPIB,
+	POS_FIX_POSBUF,
+	POS_FIX_VIACOMBO,
+	POS_FIX_COMBO,
+};
+
+/* Defines for ATI HD Audio support in SB450 south bridge */
+#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR   0x42
+#define ATI_SB450_HDAUDIO_ENABLE_SNOOP      0x02
+
+/* Defines for Nvidia HDA support */
+#define NVIDIA_HDA_TRANSREG_ADDR      0x4e
+#define NVIDIA_HDA_ENABLE_COHBITS     0x0f
+#define NVIDIA_HDA_ISTRM_COH          0x4d
+#define NVIDIA_HDA_OSTRM_COH          0x4c
+#define NVIDIA_HDA_ENABLE_COHBIT      0x01
+
+/* Defines for Intel SCH HDA snoop control */
+#define INTEL_SCH_HDA_DEVC      0x78
+#define INTEL_SCH_HDA_DEVC_NOSNOOP       (0x1<<11)
+
+/* Define IN stream 0 FIFO size offset in VIA controller */
+#define VIA_IN_STREAM0_FIFO_SIZE_OFFSET	0x90
+/* Define VIA HD Audio Device ID*/
+#define VIA_HDAC_DEVICE_ID		0x3288
+
+/* max number of SDs */
+/* ICH, ATI and VIA have 4 playback and 4 capture */
+#define ICH6_NUM_CAPTURE	4
+#define ICH6_NUM_PLAYBACK	4
+
+/* ULI has 6 playback and 5 capture */
+#define ULI_NUM_CAPTURE		5
+#define ULI_NUM_PLAYBACK	6
+
+/* ATI HDMI may have up to 8 playbacks and 0 capture */
+#define ATIHDMI_NUM_CAPTURE	0
+#define ATIHDMI_NUM_PLAYBACK	8
+
+/* TERA has 4 playback and 3 capture */
+#define TERA_NUM_CAPTURE	3
+#define TERA_NUM_PLAYBACK	4
+
 
 
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
@@ -290,8 +335,28 @@ static char *driver_short_names[] = {
 
 
 struct hda_intel {
 struct hda_intel {
 	struct azx chip;
 	struct azx chip;
-};
 
 
+	/* for pending irqs */
+	struct work_struct irq_pending_work;
+
+	/* sync probing */
+	struct completion probe_wait;
+	struct work_struct probe_work;
+
+	/* card list (for power_save trigger) */
+	struct list_head list;
+
+	/* extra flags */
+	unsigned int irq_pending_warned:1;
+
+	/* VGA-switcheroo setup */
+	unsigned int use_vga_switcheroo:1;
+	unsigned int vga_switcheroo_registered:1;
+	unsigned int init_failed:1; /* delayed init failed */
+
+	/* secondary power domain for hdmi audio under vga device */
+	struct dev_pm_domain hdmi_pm_domain;
+};
 
 
 #ifdef CONFIG_X86
 #ifdef CONFIG_X86
 static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on)
 static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on)
@@ -373,7 +438,7 @@ static void azx_init_pci(struct azx *chip)
 	 */
 	 */
 	if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) {
 	if (!(chip->driver_caps & AZX_DCAPS_NO_TCSEL)) {
 		dev_dbg(chip->card->dev, "Clearing TCSEL\n");
 		dev_dbg(chip->card->dev, "Clearing TCSEL\n");
-		update_pci_byte(chip->pci, ICH6_PCIREG_TCSEL, 0x07, 0);
+		update_pci_byte(chip->pci, AZX_PCIREG_TCSEL, 0x07, 0);
 	}
 	}
 
 
 	/* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio,
 	/* For ATI SB450/600/700/800/900 and AMD Hudson azalia HD audio,
@@ -421,11 +486,44 @@ static void azx_init_pci(struct azx *chip)
         }
         }
 }
 }
 
 
+/* calculate runtime delay from LPIB */
+static int azx_get_delay_from_lpib(struct azx *chip, struct azx_dev *azx_dev,
+				   unsigned int pos)
+{
+	struct snd_pcm_substream *substream = azx_dev->substream;
+	int stream = substream->stream;
+	unsigned int lpib_pos = azx_get_pos_lpib(chip, azx_dev);
+	int delay;
+
+	if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+		delay = pos - lpib_pos;
+	else
+		delay = lpib_pos - pos;
+	if (delay < 0) {
+		if (delay >= azx_dev->delay_negative_threshold)
+			delay = 0;
+		else
+			delay += azx_dev->bufsize;
+	}
+
+	if (delay >= azx_dev->period_bytes) {
+		dev_info(chip->card->dev,
+			 "Unstable LPIB (%d >= %d); disabling LPIB delay counting\n",
+			 delay, azx_dev->period_bytes);
+		delay = 0;
+		chip->driver_caps &= ~AZX_DCAPS_COUNT_LPIB_DELAY;
+		chip->get_delay[stream] = NULL;
+	}
+
+	return bytes_to_frames(substream->runtime, delay);
+}
+
 static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev);
 static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev);
 
 
 /* called from IRQ */
 /* called from IRQ */
 static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
 static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
 {
 {
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	int ok;
 	int ok;
 
 
 	ok = azx_position_ok(chip, azx_dev);
 	ok = azx_position_ok(chip, azx_dev);
@@ -435,7 +533,7 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
 	} else if (ok == 0 && chip->bus && chip->bus->workq) {
 	} else if (ok == 0 && chip->bus && chip->bus->workq) {
 		/* bogus IRQ, process it later */
 		/* bogus IRQ, process it later */
 		azx_dev->irq_pending = 1;
 		azx_dev->irq_pending = 1;
-		queue_work(chip->bus->workq, &chip->irq_pending_work);
+		queue_work(chip->bus->workq, &hda->irq_pending_work);
 	}
 	}
 	return 0;
 	return 0;
 }
 }
@@ -451,6 +549,8 @@ static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
  */
  */
 static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
 static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
 {
 {
+	struct snd_pcm_substream *substream = azx_dev->substream;
+	int stream = substream->stream;
 	u32 wallclk;
 	u32 wallclk;
 	unsigned int pos;
 	unsigned int pos;
 
 
@@ -458,7 +558,25 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
 	if (wallclk < (azx_dev->period_wallclk * 2) / 3)
 	if (wallclk < (azx_dev->period_wallclk * 2) / 3)
 		return -1;	/* bogus (too early) interrupt */
 		return -1;	/* bogus (too early) interrupt */
 
 
-	pos = azx_get_position(chip, azx_dev, true);
+	if (chip->get_position[stream])
+		pos = chip->get_position[stream](chip, azx_dev);
+	else { /* use the position buffer as default */
+		pos = azx_get_pos_posbuf(chip, azx_dev);
+		if (!pos || pos == (u32)-1) {
+			dev_info(chip->card->dev,
+				 "Invalid position buffer, using LPIB read method instead.\n");
+			chip->get_position[stream] = azx_get_pos_lpib;
+			pos = azx_get_pos_lpib(chip, azx_dev);
+			chip->get_delay[stream] = NULL;
+		} else {
+			chip->get_position[stream] = azx_get_pos_posbuf;
+			if (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)
+				chip->get_delay[stream] = azx_get_delay_from_lpib;
+		}
+	}
+
+	if (pos >= azx_dev->bufsize)
+		pos = 0;
 
 
 	if (WARN_ONCE(!azx_dev->period_bytes,
 	if (WARN_ONCE(!azx_dev->period_bytes,
 		      "hda-intel: zero azx_dev->period_bytes"))
 		      "hda-intel: zero azx_dev->period_bytes"))
@@ -476,14 +594,15 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
  */
  */
 static void azx_irq_pending_work(struct work_struct *work)
 static void azx_irq_pending_work(struct work_struct *work)
 {
 {
-	struct azx *chip = container_of(work, struct azx, irq_pending_work);
+	struct hda_intel *hda = container_of(work, struct hda_intel, irq_pending_work);
+	struct azx *chip = &hda->chip;
 	int i, pending, ok;
 	int i, pending, ok;
 
 
-	if (!chip->irq_pending_warned) {
+	if (!hda->irq_pending_warned) {
 		dev_info(chip->card->dev,
 		dev_info(chip->card->dev,
 			 "IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n",
 			 "IRQ timing workaround is activated for card #%d. Suggest a bigger bdl_pos_adj.\n",
 			 chip->card->number);
 			 chip->card->number);
-		chip->irq_pending_warned = 1;
+		hda->irq_pending_warned = 1;
 	}
 	}
 
 
 	for (;;) {
 	for (;;) {
@@ -541,27 +660,86 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect)
 	return 0;
 	return 0;
 }
 }
 
 
+/* get the current DMA position with correction on VIA chips */
+static unsigned int azx_via_get_position(struct azx *chip,
+					 struct azx_dev *azx_dev)
+{
+	unsigned int link_pos, mini_pos, bound_pos;
+	unsigned int mod_link_pos, mod_dma_pos, mod_mini_pos;
+	unsigned int fifo_size;
+
+	link_pos = azx_sd_readl(chip, azx_dev, SD_LPIB);
+	if (azx_dev->substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		/* Playback, no problem using link position */
+		return link_pos;
+	}
+
+	/* Capture */
+	/* For new chipset,
+	 * use mod to get the DMA position just like old chipset
+	 */
+	mod_dma_pos = le32_to_cpu(*azx_dev->posbuf);
+	mod_dma_pos %= azx_dev->period_bytes;
+
+	/* azx_dev->fifo_size can't get FIFO size of in stream.
+	 * Get from base address + offset.
+	 */
+	fifo_size = readw(chip->remap_addr + VIA_IN_STREAM0_FIFO_SIZE_OFFSET);
+
+	if (azx_dev->insufficient) {
+		/* Link position never gather than FIFO size */
+		if (link_pos <= fifo_size)
+			return 0;
+
+		azx_dev->insufficient = 0;
+	}
+
+	if (link_pos <= fifo_size)
+		mini_pos = azx_dev->bufsize + link_pos - fifo_size;
+	else
+		mini_pos = link_pos - fifo_size;
+
+	/* Find nearest previous boudary */
+	mod_mini_pos = mini_pos % azx_dev->period_bytes;
+	mod_link_pos = link_pos % azx_dev->period_bytes;
+	if (mod_link_pos >= fifo_size)
+		bound_pos = link_pos - mod_link_pos;
+	else if (mod_dma_pos >= mod_mini_pos)
+		bound_pos = mini_pos - mod_mini_pos;
+	else {
+		bound_pos = mini_pos - mod_mini_pos + azx_dev->period_bytes;
+		if (bound_pos >= azx_dev->bufsize)
+			bound_pos = 0;
+	}
+
+	/* Calculate real DMA position we want */
+	return bound_pos + mod_dma_pos;
+}
+
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
 static DEFINE_MUTEX(card_list_lock);
 static DEFINE_MUTEX(card_list_lock);
 static LIST_HEAD(card_list);
 static LIST_HEAD(card_list);
 
 
 static void azx_add_card_list(struct azx *chip)
 static void azx_add_card_list(struct azx *chip)
 {
 {
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	mutex_lock(&card_list_lock);
 	mutex_lock(&card_list_lock);
-	list_add(&chip->list, &card_list);
+	list_add(&hda->list, &card_list);
 	mutex_unlock(&card_list_lock);
 	mutex_unlock(&card_list_lock);
 }
 }
 
 
 static void azx_del_card_list(struct azx *chip)
 static void azx_del_card_list(struct azx *chip)
 {
 {
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	mutex_lock(&card_list_lock);
 	mutex_lock(&card_list_lock);
-	list_del_init(&chip->list);
+	list_del_init(&hda->list);
 	mutex_unlock(&card_list_lock);
 	mutex_unlock(&card_list_lock);
 }
 }
 
 
 /* trigger power-save check at writing parameter */
 /* trigger power-save check at writing parameter */
 static int param_set_xint(const char *val, const struct kernel_param *kp)
 static int param_set_xint(const char *val, const struct kernel_param *kp)
 {
 {
+	struct hda_intel *hda;
 	struct azx *chip;
 	struct azx *chip;
 	struct hda_codec *c;
 	struct hda_codec *c;
 	int prev = power_save;
 	int prev = power_save;
@@ -571,7 +749,8 @@ static int param_set_xint(const char *val, const struct kernel_param *kp)
 		return ret;
 		return ret;
 
 
 	mutex_lock(&card_list_lock);
 	mutex_lock(&card_list_lock);
-	list_for_each_entry(chip, &card_list, list) {
+	list_for_each_entry(hda, &card_list, list) {
+		chip = &hda->chip;
 		if (!chip->bus || chip->disabled)
 		if (!chip->bus || chip->disabled)
 			continue;
 			continue;
 		list_for_each_entry(c, &chip->bus->codec_list, list)
 		list_for_each_entry(c, &chip->bus->codec_list, list)
@@ -593,10 +772,16 @@ static int azx_suspend(struct device *dev)
 {
 {
 	struct pci_dev *pci = to_pci_dev(dev);
 	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
-	struct azx *chip = card->private_data;
+	struct azx *chip;
+	struct hda_intel *hda;
 	struct azx_pcm *p;
 	struct azx_pcm *p;
 
 
-	if (chip->disabled || chip->init_failed)
+	if (!card)
+		return 0;
+
+	chip = card->private_data;
+	hda = container_of(chip, struct hda_intel, chip);
+	if (chip->disabled || hda->init_failed)
 		return 0;
 		return 0;
 
 
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
@@ -626,9 +811,15 @@ static int azx_resume(struct device *dev)
 {
 {
 	struct pci_dev *pci = to_pci_dev(dev);
 	struct pci_dev *pci = to_pci_dev(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
-	struct azx *chip = card->private_data;
+	struct azx *chip;
+	struct hda_intel *hda;
 
 
-	if (chip->disabled || chip->init_failed)
+	if (!card)
+		return 0;
+
+	chip = card->private_data;
+	hda = container_of(chip, struct hda_intel, chip);
+	if (chip->disabled || hda->init_failed)
 		return 0;
 		return 0;
 
 
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
 	if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) {
@@ -663,9 +854,15 @@ static int azx_resume(struct device *dev)
 static int azx_runtime_suspend(struct device *dev)
 static int azx_runtime_suspend(struct device *dev)
 {
 {
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
-	struct azx *chip = card->private_data;
+	struct azx *chip;
+	struct hda_intel *hda;
+
+	if (!card)
+		return 0;
 
 
-	if (chip->disabled || chip->init_failed)
+	chip = card->private_data;
+	hda = container_of(chip, struct hda_intel, chip);
+	if (chip->disabled || hda->init_failed)
 		return 0;
 		return 0;
 
 
 	if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
 	if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
@@ -687,12 +884,18 @@ static int azx_runtime_suspend(struct device *dev)
 static int azx_runtime_resume(struct device *dev)
 static int azx_runtime_resume(struct device *dev)
 {
 {
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
-	struct azx *chip = card->private_data;
+	struct azx *chip;
+	struct hda_intel *hda;
 	struct hda_bus *bus;
 	struct hda_bus *bus;
 	struct hda_codec *codec;
 	struct hda_codec *codec;
 	int status;
 	int status;
 
 
-	if (chip->disabled || chip->init_failed)
+	if (!card)
+		return 0;
+
+	chip = card->private_data;
+	hda = container_of(chip, struct hda_intel, chip);
+	if (chip->disabled || hda->init_failed)
 		return 0;
 		return 0;
 
 
 	if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
 	if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
@@ -727,9 +930,15 @@ static int azx_runtime_resume(struct device *dev)
 static int azx_runtime_idle(struct device *dev)
 static int azx_runtime_idle(struct device *dev)
 {
 {
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
-	struct azx *chip = card->private_data;
+	struct azx *chip;
+	struct hda_intel *hda;
+
+	if (!card)
+		return 0;
 
 
-	if (chip->disabled || chip->init_failed)
+	chip = card->private_data;
+	hda = container_of(chip, struct hda_intel, chip);
+	if (chip->disabled || hda->init_failed)
 		return 0;
 		return 0;
 
 
 	if (!power_save_controller ||
 	if (!power_save_controller ||
@@ -753,29 +962,6 @@ static const struct dev_pm_ops azx_pm = {
 #endif /* CONFIG_PM */
 #endif /* CONFIG_PM */
 
 
 
 
-/*
- * reboot notifier for hang-up problem at power-down
- */
-static int azx_halt(struct notifier_block *nb, unsigned long event, void *buf)
-{
-	struct azx *chip = container_of(nb, struct azx, reboot_notifier);
-	snd_hda_bus_reboot_notify(chip->bus);
-	azx_stop_chip(chip);
-	return NOTIFY_OK;
-}
-
-static void azx_notifier_register(struct azx *chip)
-{
-	chip->reboot_notifier.notifier_call = azx_halt;
-	register_reboot_notifier(&chip->reboot_notifier);
-}
-
-static void azx_notifier_unregister(struct azx *chip)
-{
-	if (chip->reboot_notifier.notifier_call)
-		unregister_reboot_notifier(&chip->reboot_notifier);
-}
-
 static int azx_probe_continue(struct azx *chip);
 static int azx_probe_continue(struct azx *chip);
 
 
 #ifdef SUPPORT_VGA_SWITCHEROO
 #ifdef SUPPORT_VGA_SWITCHEROO
@@ -786,10 +972,11 @@ static void azx_vs_set_state(struct pci_dev *pci,
 {
 {
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct azx *chip = card->private_data;
 	struct azx *chip = card->private_data;
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	bool disabled;
 	bool disabled;
 
 
-	wait_for_completion(&chip->probe_wait);
-	if (chip->init_failed)
+	wait_for_completion(&hda->probe_wait);
+	if (hda->init_failed)
 		return;
 		return;
 
 
 	disabled = (state == VGA_SWITCHEROO_OFF);
 	disabled = (state == VGA_SWITCHEROO_OFF);
@@ -803,7 +990,7 @@ static void azx_vs_set_state(struct pci_dev *pci,
 				 "Start delayed initialization\n");
 				 "Start delayed initialization\n");
 			if (azx_probe_continue(chip) < 0) {
 			if (azx_probe_continue(chip) < 0) {
 				dev_err(chip->card->dev, "initialization error\n");
 				dev_err(chip->card->dev, "initialization error\n");
-				chip->init_failed = true;
+				hda->init_failed = true;
 			}
 			}
 		}
 		}
 	} else {
 	} else {
@@ -833,9 +1020,10 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
 {
 {
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct snd_card *card = pci_get_drvdata(pci);
 	struct azx *chip = card->private_data;
 	struct azx *chip = card->private_data;
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 
 
-	wait_for_completion(&chip->probe_wait);
-	if (chip->init_failed)
+	wait_for_completion(&hda->probe_wait);
+	if (hda->init_failed)
 		return false;
 		return false;
 	if (chip->disabled || !chip->bus)
 	if (chip->disabled || !chip->bus)
 		return true;
 		return true;
@@ -847,11 +1035,12 @@ static bool azx_vs_can_switch(struct pci_dev *pci)
 
 
 static void init_vga_switcheroo(struct azx *chip)
 static void init_vga_switcheroo(struct azx *chip)
 {
 {
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	struct pci_dev *p = get_bound_vga(chip->pci);
 	struct pci_dev *p = get_bound_vga(chip->pci);
 	if (p) {
 	if (p) {
 		dev_info(chip->card->dev,
 		dev_info(chip->card->dev,
 			 "Handle VGA-switcheroo audio client\n");
 			 "Handle VGA-switcheroo audio client\n");
-		chip->use_vga_switcheroo = 1;
+		hda->use_vga_switcheroo = 1;
 		pci_dev_put(p);
 		pci_dev_put(p);
 	}
 	}
 }
 }
@@ -863,9 +1052,10 @@ static const struct vga_switcheroo_client_ops azx_vs_ops = {
 
 
 static int register_vga_switcheroo(struct azx *chip)
 static int register_vga_switcheroo(struct azx *chip)
 {
 {
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	int err;
 	int err;
 
 
-	if (!chip->use_vga_switcheroo)
+	if (!hda->use_vga_switcheroo)
 		return 0;
 		return 0;
 	/* FIXME: currently only handling DIS controller
 	/* FIXME: currently only handling DIS controller
 	 * is there any machine with two switchable HDMI audio controllers?
 	 * is there any machine with two switchable HDMI audio controllers?
@@ -875,11 +1065,11 @@ static int register_vga_switcheroo(struct azx *chip)
 						    chip->bus != NULL);
 						    chip->bus != NULL);
 	if (err < 0)
 	if (err < 0)
 		return err;
 		return err;
-	chip->vga_switcheroo_registered = 1;
+	hda->vga_switcheroo_registered = 1;
 
 
 	/* register as an optimus hdmi audio power domain */
 	/* register as an optimus hdmi audio power domain */
 	vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev,
 	vga_switcheroo_init_domain_pm_optimus_hdmi_audio(chip->card->dev,
-							 &chip->hdmi_pm_domain);
+							 &hda->hdmi_pm_domain);
 	return 0;
 	return 0;
 }
 }
 #else
 #else
@@ -895,7 +1085,6 @@ static int azx_free(struct azx *chip)
 {
 {
 	struct pci_dev *pci = chip->pci;
 	struct pci_dev *pci = chip->pci;
 	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
-
 	int i;
 	int i;
 
 
 	if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME)
 	if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME)
@@ -906,13 +1095,13 @@ static int azx_free(struct azx *chip)
 
 
 	azx_notifier_unregister(chip);
 	azx_notifier_unregister(chip);
 
 
-	chip->init_failed = 1; /* to be sure */
-	complete_all(&chip->probe_wait);
+	hda->init_failed = 1; /* to be sure */
+	complete_all(&hda->probe_wait);
 
 
-	if (use_vga_switcheroo(chip)) {
+	if (use_vga_switcheroo(hda)) {
 		if (chip->disabled && chip->bus)
 		if (chip->disabled && chip->bus)
 			snd_hda_unlock_devices(chip->bus);
 			snd_hda_unlock_devices(chip->bus);
-		if (chip->vga_switcheroo_registered)
+		if (hda->vga_switcheroo_registered)
 			vga_switcheroo_unregister_client(chip->pci);
 			vga_switcheroo_unregister_client(chip->pci);
 	}
 	}
 
 
@@ -1048,6 +1237,30 @@ static int check_position_fix(struct azx *chip, int fix)
 	return POS_FIX_AUTO;
 	return POS_FIX_AUTO;
 }
 }
 
 
+static void assign_position_fix(struct azx *chip, int fix)
+{
+	static azx_get_pos_callback_t callbacks[] = {
+		[POS_FIX_AUTO] = NULL,
+		[POS_FIX_LPIB] = azx_get_pos_lpib,
+		[POS_FIX_POSBUF] = azx_get_pos_posbuf,
+		[POS_FIX_VIACOMBO] = azx_via_get_position,
+		[POS_FIX_COMBO] = azx_get_pos_lpib,
+	};
+
+	chip->get_position[0] = chip->get_position[1] = callbacks[fix];
+
+	/* combo mode uses LPIB only for playback */
+	if (fix == POS_FIX_COMBO)
+		chip->get_position[1] = NULL;
+
+	if (fix == POS_FIX_POSBUF &&
+	    (chip->driver_caps & AZX_DCAPS_COUNT_LPIB_DELAY)) {
+		chip->get_delay[0] = chip->get_delay[1] =
+			azx_get_delay_from_lpib;
+	}
+
+}
+
 /*
 /*
  * black-lists for probe_mask
  * black-lists for probe_mask
  */
  */
@@ -1173,7 +1386,8 @@ static void azx_check_snoop_available(struct azx *chip)
 
 
 static void azx_probe_work(struct work_struct *work)
 static void azx_probe_work(struct work_struct *work)
 {
 {
-	azx_probe_continue(container_of(work, struct azx, probe_work));
+	struct hda_intel *hda = container_of(work, struct hda_intel, probe_work);
+	azx_probe_continue(&hda->chip);
 }
 }
 
 
 /*
 /*
@@ -1216,19 +1430,13 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
 	check_msi(chip);
 	check_msi(chip);
 	chip->dev_index = dev;
 	chip->dev_index = dev;
 	chip->jackpoll_ms = jackpoll_ms;
 	chip->jackpoll_ms = jackpoll_ms;
-	INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
 	INIT_LIST_HEAD(&chip->pcm_list);
 	INIT_LIST_HEAD(&chip->pcm_list);
-	INIT_LIST_HEAD(&chip->list);
+	INIT_WORK(&hda->irq_pending_work, azx_irq_pending_work);
+	INIT_LIST_HEAD(&hda->list);
 	init_vga_switcheroo(chip);
 	init_vga_switcheroo(chip);
-	init_completion(&chip->probe_wait);
-
-	chip->position_fix[0] = chip->position_fix[1] =
-		check_position_fix(chip, position_fix[dev]);
-	/* combo mode uses LPIB for playback */
-	if (chip->position_fix[0] == POS_FIX_COMBO) {
-		chip->position_fix[0] = POS_FIX_LPIB;
-		chip->position_fix[1] = POS_FIX_AUTO;
-	}
+	init_completion(&hda->probe_wait);
+
+	assign_position_fix(chip, check_position_fix(chip, position_fix[dev]));
 
 
 	check_probe_mask(chip, dev);
 	check_probe_mask(chip, dev);
 
 
@@ -1257,7 +1465,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
 	}
 	}
 
 
 	/* continue probing in work context as may trigger request module */
 	/* continue probing in work context as may trigger request module */
-	INIT_WORK(&chip->probe_work, azx_probe_work);
+	INIT_WORK(&hda->probe_work, azx_probe_work);
 
 
 	*rchip = chip;
 	*rchip = chip;
 
 
@@ -1315,7 +1523,7 @@ static int azx_first_init(struct azx *chip)
 					 NULL);
 					 NULL);
 		if (p_smbus) {
 		if (p_smbus) {
 			if (p_smbus->revision < 0x30)
 			if (p_smbus->revision < 0x30)
-				gcap &= ~ICH6_GCAP_64OK;
+				gcap &= ~AZX_GCAP_64OK;
 			pci_dev_put(p_smbus);
 			pci_dev_put(p_smbus);
 		}
 		}
 	}
 	}
@@ -1323,7 +1531,7 @@ static int azx_first_init(struct azx *chip)
 	/* disable 64bit DMA address on some devices */
 	/* disable 64bit DMA address on some devices */
 	if (chip->driver_caps & AZX_DCAPS_NO_64BIT) {
 	if (chip->driver_caps & AZX_DCAPS_NO_64BIT) {
 		dev_dbg(card->dev, "Disabling 64bit DMA\n");
 		dev_dbg(card->dev, "Disabling 64bit DMA\n");
-		gcap &= ~ICH6_GCAP_64OK;
+		gcap &= ~AZX_GCAP_64OK;
 	}
 	}
 
 
 	/* disable buffer size rounding to 128-byte multiples if supported */
 	/* disable buffer size rounding to 128-byte multiples if supported */
@@ -1339,7 +1547,7 @@ static int azx_first_init(struct azx *chip)
 	}
 	}
 
 
 	/* allow 64bit DMA address if supported by H/W */
 	/* allow 64bit DMA address if supported by H/W */
-	if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
+	if ((gcap & AZX_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
 		pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64));
 		pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64));
 	else {
 	else {
 		pci_set_dma_mask(pci, DMA_BIT_MASK(32));
 		pci_set_dma_mask(pci, DMA_BIT_MASK(32));
@@ -1583,6 +1791,7 @@ static int azx_probe(struct pci_dev *pci,
 {
 {
 	static int dev;
 	static int dev;
 	struct snd_card *card;
 	struct snd_card *card;
+	struct hda_intel *hda;
 	struct azx *chip;
 	struct azx *chip;
 	bool schedule_probe;
 	bool schedule_probe;
 	int err;
 	int err;
@@ -1606,6 +1815,7 @@ static int azx_probe(struct pci_dev *pci,
 	if (err < 0)
 	if (err < 0)
 		goto out_free;
 		goto out_free;
 	card->private_data = chip;
 	card->private_data = chip;
+	hda = container_of(chip, struct hda_intel, chip);
 
 
 	pci_set_drvdata(pci, card);
 	pci_set_drvdata(pci, card);
 
 
@@ -1642,11 +1852,11 @@ static int azx_probe(struct pci_dev *pci,
 #endif
 #endif
 
 
 	if (schedule_probe)
 	if (schedule_probe)
-		schedule_work(&chip->probe_work);
+		schedule_work(&hda->probe_work);
 
 
 	dev++;
 	dev++;
 	if (chip->disabled)
 	if (chip->disabled)
-		complete_all(&chip->probe_wait);
+		complete_all(&hda->probe_wait);
 	return 0;
 	return 0;
 
 
 out_free:
 out_free:
@@ -1662,6 +1872,7 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
 
 
 static int azx_probe_continue(struct azx *chip)
 static int azx_probe_continue(struct azx *chip)
 {
 {
+	struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
 	struct pci_dev *pci = chip->pci;
 	struct pci_dev *pci = chip->pci;
 	int dev = chip->dev_index;
 	int dev = chip->dev_index;
 	int err;
 	int err;
@@ -1735,13 +1946,13 @@ static int azx_probe_continue(struct azx *chip)
 	power_down_all_codecs(chip);
 	power_down_all_codecs(chip);
 	azx_notifier_register(chip);
 	azx_notifier_register(chip);
 	azx_add_card_list(chip);
 	azx_add_card_list(chip);
-	if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || chip->use_vga_switcheroo)
+	if ((chip->driver_caps & AZX_DCAPS_PM_RUNTIME) || hda->use_vga_switcheroo)
 		pm_runtime_put_noidle(&pci->dev);
 		pm_runtime_put_noidle(&pci->dev);
 
 
 out_free:
 out_free:
 	if (err < 0)
 	if (err < 0)
-		chip->init_failed = 1;
-	complete_all(&chip->probe_wait);
+		hda->init_failed = 1;
+	complete_all(&hda->probe_wait);
 	return err;
 	return err;
 }
 }
 
 
@@ -1806,6 +2017,9 @@ static const struct pci_device_id azx_ids[] = {
 	/* BayTrail */
 	/* BayTrail */
 	{ PCI_DEVICE(0x8086, 0x0f04),
 	{ PCI_DEVICE(0x8086, 0x0f04),
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
+	/* Braswell */
+	{ PCI_DEVICE(0x8086, 0x2284),
+	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
 	/* ICH */
 	/* ICH */
 	{ PCI_DEVICE(0x8086, 0x2668),
 	{ PCI_DEVICE(0x8086, 0x2668),
 	  .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
 	  .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |

+ 6 - 3
sound/pci/hda/hda_local.h

@@ -268,7 +268,8 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
 			  const struct hda_input_mux *imux,
 			  const struct hda_input_mux *imux,
 			  struct snd_ctl_elem_value *ucontrol, hda_nid_t nid,
 			  struct snd_ctl_elem_value *ucontrol, hda_nid_t nid,
 			  unsigned int *cur_val);
 			  unsigned int *cur_val);
-int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
+int snd_hda_add_imux_item(struct hda_codec *codec,
+			  struct hda_input_mux *imux, const char *label,
 			  int index, int *type_index_ret);
 			  int index, int *type_index_ret);
 
 
 /*
 /*
@@ -437,6 +438,8 @@ struct snd_hda_pin_quirk {
 
 
 #endif
 #endif
 
 
+#define HDA_FIXUP_ID_NOT_SET -1
+#define HDA_FIXUP_ID_NO_FIXUP -2
 
 
 /* fixup types */
 /* fixup types */
 enum {
 enum {
@@ -773,9 +776,9 @@ struct hdmi_eld {
 int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid);
 int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid);
 int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid,
 int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid,
 		     unsigned char *buf, int *eld_size);
 		     unsigned char *buf, int *eld_size);
-int snd_hdmi_parse_eld(struct parsed_hdmi_eld *e,
+int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e,
 		       const unsigned char *buf, int size);
 		       const unsigned char *buf, int size);
-void snd_hdmi_show_eld(struct parsed_hdmi_eld *e);
+void snd_hdmi_show_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e);
 void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e,
 void snd_hdmi_eld_update_pcm_info(struct parsed_hdmi_eld *e,
 			      struct hda_pcm_stream *hinfo);
 			      struct hda_pcm_stream *hinfo);
 
 

+ 93 - 160
sound/pci/hda/hda_priv.h

@@ -22,107 +22,87 @@
 /*
 /*
  * registers
  * registers
  */
  */
-#define ICH6_REG_GCAP			0x00
-#define   ICH6_GCAP_64OK	(1 << 0)   /* 64bit address support */
-#define   ICH6_GCAP_NSDO	(3 << 1)   /* # of serial data out signals */
-#define   ICH6_GCAP_BSS		(31 << 3)  /* # of bidirectional streams */
-#define   ICH6_GCAP_ISS		(15 << 8)  /* # of input streams */
-#define   ICH6_GCAP_OSS		(15 << 12) /* # of output streams */
-#define ICH6_REG_VMIN			0x02
-#define ICH6_REG_VMAJ			0x03
-#define ICH6_REG_OUTPAY			0x04
-#define ICH6_REG_INPAY			0x06
-#define ICH6_REG_GCTL			0x08
-#define   ICH6_GCTL_RESET	(1 << 0)   /* controller reset */
-#define   ICH6_GCTL_FCNTRL	(1 << 1)   /* flush control */
-#define   ICH6_GCTL_UNSOL	(1 << 8)   /* accept unsol. response enable */
-#define ICH6_REG_WAKEEN			0x0c
-#define ICH6_REG_STATESTS		0x0e
-#define ICH6_REG_GSTS			0x10
-#define   ICH6_GSTS_FSTS	(1 << 1)   /* flush status */
-#define ICH6_REG_INTCTL			0x20
-#define ICH6_REG_INTSTS			0x24
-#define ICH6_REG_WALLCLK		0x30	/* 24Mhz source */
-#define ICH6_REG_OLD_SSYNC		0x34	/* SSYNC for old ICH */
-#define ICH6_REG_SSYNC			0x38
-#define ICH6_REG_CORBLBASE		0x40
-#define ICH6_REG_CORBUBASE		0x44
-#define ICH6_REG_CORBWP			0x48
-#define ICH6_REG_CORBRP			0x4a
-#define   ICH6_CORBRP_RST	(1 << 15)  /* read pointer reset */
-#define ICH6_REG_CORBCTL		0x4c
-#define   ICH6_CORBCTL_RUN	(1 << 1)   /* enable DMA */
-#define   ICH6_CORBCTL_CMEIE	(1 << 0)   /* enable memory error irq */
-#define ICH6_REG_CORBSTS		0x4d
-#define   ICH6_CORBSTS_CMEI	(1 << 0)   /* memory error indication */
-#define ICH6_REG_CORBSIZE		0x4e
-
-#define ICH6_REG_RIRBLBASE		0x50
-#define ICH6_REG_RIRBUBASE		0x54
-#define ICH6_REG_RIRBWP			0x58
-#define   ICH6_RIRBWP_RST	(1 << 15)  /* write pointer reset */
-#define ICH6_REG_RINTCNT		0x5a
-#define ICH6_REG_RIRBCTL		0x5c
-#define   ICH6_RBCTL_IRQ_EN	(1 << 0)   /* enable IRQ */
-#define   ICH6_RBCTL_DMA_EN	(1 << 1)   /* enable DMA */
-#define   ICH6_RBCTL_OVERRUN_EN	(1 << 2)   /* enable overrun irq */
-#define ICH6_REG_RIRBSTS		0x5d
-#define   ICH6_RBSTS_IRQ	(1 << 0)   /* response irq */
-#define   ICH6_RBSTS_OVERRUN	(1 << 2)   /* overrun irq */
-#define ICH6_REG_RIRBSIZE		0x5e
-
-#define ICH6_REG_IC			0x60
-#define ICH6_REG_IR			0x64
-#define ICH6_REG_IRS			0x68
-#define   ICH6_IRS_VALID	(1<<1)
-#define   ICH6_IRS_BUSY		(1<<0)
-
-#define ICH6_REG_DPLBASE		0x70
-#define ICH6_REG_DPUBASE		0x74
-#define   ICH6_DPLBASE_ENABLE	0x1	/* Enable position buffer */
+#define AZX_REG_GCAP			0x00
+#define   AZX_GCAP_64OK		(1 << 0)   /* 64bit address support */
+#define   AZX_GCAP_NSDO		(3 << 1)   /* # of serial data out signals */
+#define   AZX_GCAP_BSS		(31 << 3)  /* # of bidirectional streams */
+#define   AZX_GCAP_ISS		(15 << 8)  /* # of input streams */
+#define   AZX_GCAP_OSS		(15 << 12) /* # of output streams */
+#define AZX_REG_VMIN			0x02
+#define AZX_REG_VMAJ			0x03
+#define AZX_REG_OUTPAY			0x04
+#define AZX_REG_INPAY			0x06
+#define AZX_REG_GCTL			0x08
+#define   AZX_GCTL_RESET	(1 << 0)   /* controller reset */
+#define   AZX_GCTL_FCNTRL	(1 << 1)   /* flush control */
+#define   AZX_GCTL_UNSOL	(1 << 8)   /* accept unsol. response enable */
+#define AZX_REG_WAKEEN			0x0c
+#define AZX_REG_STATESTS		0x0e
+#define AZX_REG_GSTS			0x10
+#define   AZX_GSTS_FSTS		(1 << 1)   /* flush status */
+#define AZX_REG_INTCTL			0x20
+#define AZX_REG_INTSTS			0x24
+#define AZX_REG_WALLCLK			0x30	/* 24Mhz source */
+#define AZX_REG_OLD_SSYNC		0x34	/* SSYNC for old ICH */
+#define AZX_REG_SSYNC			0x38
+#define AZX_REG_CORBLBASE		0x40
+#define AZX_REG_CORBUBASE		0x44
+#define AZX_REG_CORBWP			0x48
+#define AZX_REG_CORBRP			0x4a
+#define   AZX_CORBRP_RST	(1 << 15)  /* read pointer reset */
+#define AZX_REG_CORBCTL			0x4c
+#define   AZX_CORBCTL_RUN	(1 << 1)   /* enable DMA */
+#define   AZX_CORBCTL_CMEIE	(1 << 0)   /* enable memory error irq */
+#define AZX_REG_CORBSTS			0x4d
+#define   AZX_CORBSTS_CMEI	(1 << 0)   /* memory error indication */
+#define AZX_REG_CORBSIZE		0x4e
+
+#define AZX_REG_RIRBLBASE		0x50
+#define AZX_REG_RIRBUBASE		0x54
+#define AZX_REG_RIRBWP			0x58
+#define   AZX_RIRBWP_RST	(1 << 15)  /* write pointer reset */
+#define AZX_REG_RINTCNT			0x5a
+#define AZX_REG_RIRBCTL			0x5c
+#define   AZX_RBCTL_IRQ_EN	(1 << 0)   /* enable IRQ */
+#define   AZX_RBCTL_DMA_EN	(1 << 1)   /* enable DMA */
+#define   AZX_RBCTL_OVERRUN_EN	(1 << 2)   /* enable overrun irq */
+#define AZX_REG_RIRBSTS			0x5d
+#define   AZX_RBSTS_IRQ		(1 << 0)   /* response irq */
+#define   AZX_RBSTS_OVERRUN	(1 << 2)   /* overrun irq */
+#define AZX_REG_RIRBSIZE		0x5e
+
+#define AZX_REG_IC			0x60
+#define AZX_REG_IR			0x64
+#define AZX_REG_IRS			0x68
+#define   AZX_IRS_VALID		(1<<1)
+#define   AZX_IRS_BUSY		(1<<0)
+
+#define AZX_REG_DPLBASE			0x70
+#define AZX_REG_DPUBASE			0x74
+#define   AZX_DPLBASE_ENABLE	0x1	/* Enable position buffer */
 
 
 /* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
 /* SD offset: SDI0=0x80, SDI1=0xa0, ... SDO3=0x160 */
 enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 
 
 /* stream register offsets from stream base */
 /* stream register offsets from stream base */
-#define ICH6_REG_SD_CTL			0x00
-#define ICH6_REG_SD_STS			0x03
-#define ICH6_REG_SD_LPIB		0x04
-#define ICH6_REG_SD_CBL			0x08
-#define ICH6_REG_SD_LVI			0x0c
-#define ICH6_REG_SD_FIFOW		0x0e
-#define ICH6_REG_SD_FIFOSIZE		0x10
-#define ICH6_REG_SD_FORMAT		0x12
-#define ICH6_REG_SD_BDLPL		0x18
-#define ICH6_REG_SD_BDLPU		0x1c
+#define AZX_REG_SD_CTL			0x00
+#define AZX_REG_SD_STS			0x03
+#define AZX_REG_SD_LPIB			0x04
+#define AZX_REG_SD_CBL			0x08
+#define AZX_REG_SD_LVI			0x0c
+#define AZX_REG_SD_FIFOW		0x0e
+#define AZX_REG_SD_FIFOSIZE		0x10
+#define AZX_REG_SD_FORMAT		0x12
+#define AZX_REG_SD_BDLPL		0x18
+#define AZX_REG_SD_BDLPU		0x1c
 
 
 /* PCI space */
 /* PCI space */
-#define ICH6_PCIREG_TCSEL	0x44
+#define AZX_PCIREG_TCSEL		0x44
 
 
 /*
 /*
  * other constants
  * other constants
  */
  */
 
 
-/* max number of SDs */
-/* ICH, ATI and VIA have 4 playback and 4 capture */
-#define ICH6_NUM_CAPTURE	4
-#define ICH6_NUM_PLAYBACK	4
-
-/* ULI has 6 playback and 5 capture */
-#define ULI_NUM_CAPTURE		5
-#define ULI_NUM_PLAYBACK	6
-
-/* ATI HDMI may have up to 8 playbacks and 0 capture */
-#define ATIHDMI_NUM_CAPTURE	0
-#define ATIHDMI_NUM_PLAYBACK	8
-
-/* TERA has 4 playback and 3 capture */
-#define TERA_NUM_CAPTURE	3
-#define TERA_NUM_PLAYBACK	4
-
-/* this number is statically defined for simplicity */
-#define MAX_AZX_DEV		16
-
 /* max number of fragments - we may use more if allocating more pages for BDL */
 /* max number of fragments - we may use more if allocating more pages for BDL */
 #define BDL_SIZE		4096
 #define BDL_SIZE		4096
 #define AZX_MAX_BDL_ENTRIES	(BDL_SIZE / 16)
 #define AZX_MAX_BDL_ENTRIES	(BDL_SIZE / 16)
@@ -160,13 +140,13 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define SD_STS_FIFO_READY	0x20	/* FIFO ready */
 #define SD_STS_FIFO_READY	0x20	/* FIFO ready */
 
 
 /* INTCTL and INTSTS */
 /* INTCTL and INTSTS */
-#define ICH6_INT_ALL_STREAM	0xff	   /* all stream interrupts */
-#define ICH6_INT_CTRL_EN	0x40000000 /* controller interrupt enable bit */
-#define ICH6_INT_GLOBAL_EN	0x80000000 /* global interrupt enable bit */
+#define AZX_INT_ALL_STREAM	0xff	   /* all stream interrupts */
+#define AZX_INT_CTRL_EN	0x40000000 /* controller interrupt enable bit */
+#define AZX_INT_GLOBAL_EN	0x80000000 /* global interrupt enable bit */
 
 
 /* below are so far hardcoded - should read registers in future */
 /* below are so far hardcoded - should read registers in future */
-#define ICH6_MAX_CORB_ENTRIES	256
-#define ICH6_MAX_RIRB_ENTRIES	256
+#define AZX_MAX_CORB_ENTRIES	256
+#define AZX_MAX_RIRB_ENTRIES	256
 
 
 /* driver quirks (capabilities) */
 /* driver quirks (capabilities) */
 /* bits 0-7 are used for indicating driver type */
 /* bits 0-7 are used for indicating driver type */
@@ -192,35 +172,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
 #define AZX_DCAPS_I915_POWERWELL (1 << 27)	/* HSW i915 powerwell support */
 #define AZX_DCAPS_I915_POWERWELL (1 << 27)	/* HSW i915 powerwell support */
 #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28)	/* CORBRP clears itself after reset */
 #define AZX_DCAPS_CORBRP_SELF_CLEAR (1 << 28)	/* CORBRP clears itself after reset */
 
 
-/* position fix mode */
-enum {
-	POS_FIX_AUTO,
-	POS_FIX_LPIB,
-	POS_FIX_POSBUF,
-	POS_FIX_VIACOMBO,
-	POS_FIX_COMBO,
-};
-
-/* Defines for ATI HD Audio support in SB450 south bridge */
-#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR   0x42
-#define ATI_SB450_HDAUDIO_ENABLE_SNOOP      0x02
-
-/* Defines for Nvidia HDA support */
-#define NVIDIA_HDA_TRANSREG_ADDR      0x4e
-#define NVIDIA_HDA_ENABLE_COHBITS     0x0f
-#define NVIDIA_HDA_ISTRM_COH          0x4d
-#define NVIDIA_HDA_OSTRM_COH          0x4c
-#define NVIDIA_HDA_ENABLE_COHBIT      0x01
-
-/* Defines for Intel SCH HDA snoop control */
-#define INTEL_SCH_HDA_DEVC      0x78
-#define INTEL_SCH_HDA_DEVC_NOSNOOP       (0x1<<11)
-
-/* Define IN stream 0 FIFO size offset in VIA controller */
-#define VIA_IN_STREAM0_FIFO_SIZE_OFFSET	0x90
-/* Define VIA HD Audio Device ID*/
-#define VIA_HDAC_DEVICE_ID		0x3288
-
 /* HD Audio class code */
 /* HD Audio class code */
 #define PCI_CLASS_MULTIMEDIA_HD_AUDIO	0x0403
 #define PCI_CLASS_MULTIMEDIA_HD_AUDIO	0x0403
 
 
@@ -325,6 +276,9 @@ struct azx_pcm {
 	struct list_head list;
 	struct list_head list;
 };
 };
 
 
+typedef unsigned int (*azx_get_pos_callback_t)(struct azx *, struct azx_dev *);
+typedef int (*azx_get_delay_callback_t)(struct azx *, struct azx_dev *, unsigned int pos);
+
 struct azx {
 struct azx {
 	struct snd_card *card;
 	struct snd_card *card;
 	struct pci_dev *pci;
 	struct pci_dev *pci;
@@ -343,6 +297,10 @@ struct azx {
 	/* Register interaction. */
 	/* Register interaction. */
 	const struct hda_controller_ops *ops;
 	const struct hda_controller_ops *ops;
 
 
+	/* position adjustment callbacks */
+	azx_get_pos_callback_t get_position[2];
+	azx_get_delay_callback_t get_delay[2];
+
 	/* pci resources */
 	/* pci resources */
 	unsigned long addr;
 	unsigned long addr;
 	void __iomem *remap_addr;
 	void __iomem *remap_addr;
@@ -351,7 +309,6 @@ struct azx {
 	/* locks */
 	/* locks */
 	spinlock_t reg_lock;
 	spinlock_t reg_lock;
 	struct mutex open_mutex; /* Prevents concurrent open/close operations */
 	struct mutex open_mutex; /* Prevents concurrent open/close operations */
-	struct completion probe_wait;
 
 
 	/* streams (x num_streams) */
 	/* streams (x num_streams) */
 	struct azx_dev *azx_dev;
 	struct azx_dev *azx_dev;
@@ -378,7 +335,6 @@ struct azx {
 #endif
 #endif
 
 
 	/* flags */
 	/* flags */
-	int position_fix[2]; /* for both playback/capture streams */
 	const int *bdl_pos_adj;
 	const int *bdl_pos_adj;
 	int poll_count;
 	int poll_count;
 	unsigned int running:1;
 	unsigned int running:1;
@@ -386,46 +342,23 @@ struct azx {
 	unsigned int single_cmd:1;
 	unsigned int single_cmd:1;
 	unsigned int polling_mode:1;
 	unsigned int polling_mode:1;
 	unsigned int msi:1;
 	unsigned int msi:1;
-	unsigned int irq_pending_warned:1;
 	unsigned int probing:1; /* codec probing phase */
 	unsigned int probing:1; /* codec probing phase */
 	unsigned int snoop:1;
 	unsigned int snoop:1;
 	unsigned int align_buffer_size:1;
 	unsigned int align_buffer_size:1;
 	unsigned int region_requested:1;
 	unsigned int region_requested:1;
-
-	/* VGA-switcheroo setup */
-	unsigned int use_vga_switcheroo:1;
-	unsigned int vga_switcheroo_registered:1;
-	unsigned int init_failed:1; /* delayed init failed */
 	unsigned int disabled:1; /* disabled by VGA-switcher */
 	unsigned int disabled:1; /* disabled by VGA-switcher */
 
 
 	/* for debugging */
 	/* for debugging */
 	unsigned int last_cmd[AZX_MAX_CODECS];
 	unsigned int last_cmd[AZX_MAX_CODECS];
 
 
-	/* for pending irqs */
-	struct work_struct irq_pending_work;
-
-	struct work_struct probe_work;
-
 	/* reboot notifier (for mysterious hangup problem at power-down) */
 	/* reboot notifier (for mysterious hangup problem at power-down) */
 	struct notifier_block reboot_notifier;
 	struct notifier_block reboot_notifier;
 
 
-	/* card list (for power_save trigger) */
-	struct list_head list;
-
 #ifdef CONFIG_SND_HDA_DSP_LOADER
 #ifdef CONFIG_SND_HDA_DSP_LOADER
 	struct azx_dev saved_azx_dev;
 	struct azx_dev saved_azx_dev;
 #endif
 #endif
-
-	/* secondary power domain for hdmi audio under vga device */
-	struct dev_pm_domain hdmi_pm_domain;
 };
 };
 
 
-#ifdef CONFIG_SND_VERBOSE_PRINTK
-#define SFX	/* nop */
-#else
-#define SFX	"hda-intel "
-#endif
-
 #ifdef CONFIG_X86
 #ifdef CONFIG_X86
 #define azx_snoop(chip)		((chip)->snoop)
 #define azx_snoop(chip)		((chip)->snoop)
 #else
 #else
@@ -437,29 +370,29 @@ struct azx {
  */
  */
 
 
 #define azx_writel(chip, reg, value) \
 #define azx_writel(chip, reg, value) \
-	((chip)->ops->reg_writel(value, (chip)->remap_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_writel(value, (chip)->remap_addr + AZX_REG_##reg))
 #define azx_readl(chip, reg) \
 #define azx_readl(chip, reg) \
-	((chip)->ops->reg_readl((chip)->remap_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_readl((chip)->remap_addr + AZX_REG_##reg))
 #define azx_writew(chip, reg, value) \
 #define azx_writew(chip, reg, value) \
-	((chip)->ops->reg_writew(value, (chip)->remap_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_writew(value, (chip)->remap_addr + AZX_REG_##reg))
 #define azx_readw(chip, reg) \
 #define azx_readw(chip, reg) \
-	((chip)->ops->reg_readw((chip)->remap_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_readw((chip)->remap_addr + AZX_REG_##reg))
 #define azx_writeb(chip, reg, value) \
 #define azx_writeb(chip, reg, value) \
-	((chip)->ops->reg_writeb(value, (chip)->remap_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_writeb(value, (chip)->remap_addr + AZX_REG_##reg))
 #define azx_readb(chip, reg) \
 #define azx_readb(chip, reg) \
-	((chip)->ops->reg_readb((chip)->remap_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_readb((chip)->remap_addr + AZX_REG_##reg))
 
 
 #define azx_sd_writel(chip, dev, reg, value) \
 #define azx_sd_writel(chip, dev, reg, value) \
-	((chip)->ops->reg_writel(value, (dev)->sd_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_writel(value, (dev)->sd_addr + AZX_REG_##reg))
 #define azx_sd_readl(chip, dev, reg) \
 #define azx_sd_readl(chip, dev, reg) \
-	((chip)->ops->reg_readl((dev)->sd_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_readl((dev)->sd_addr + AZX_REG_##reg))
 #define azx_sd_writew(chip, dev, reg, value) \
 #define azx_sd_writew(chip, dev, reg, value) \
-	((chip)->ops->reg_writew(value, (dev)->sd_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_writew(value, (dev)->sd_addr + AZX_REG_##reg))
 #define azx_sd_readw(chip, dev, reg) \
 #define azx_sd_readw(chip, dev, reg) \
-	((chip)->ops->reg_readw((dev)->sd_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_readw((dev)->sd_addr + AZX_REG_##reg))
 #define azx_sd_writeb(chip, dev, reg, value) \
 #define azx_sd_writeb(chip, dev, reg, value) \
-	((chip)->ops->reg_writeb(value, (dev)->sd_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_writeb(value, (dev)->sd_addr + AZX_REG_##reg))
 #define azx_sd_readb(chip, dev, reg) \
 #define azx_sd_readb(chip, dev, reg) \
-	((chip)->ops->reg_readb((dev)->sd_addr + ICH6_REG_##reg))
+	((chip)->ops->reg_readb((dev)->sd_addr + AZX_REG_##reg))
 
 
 #endif /* __SOUND_HDA_PRIV_H */
 #endif /* __SOUND_HDA_PRIV_H */

+ 2 - 34
sound/pci/hda/hda_tegra.c

@@ -29,7 +29,6 @@
 #include <linux/moduleparam.h>
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/of_device.h>
 #include <linux/of_device.h>
-#include <linux/reboot.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/time.h>
 
 
@@ -272,13 +271,9 @@ static int hda_tegra_resume(struct device *dev)
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct snd_card *card = dev_get_drvdata(dev);
 	struct azx *chip = card->private_data;
 	struct azx *chip = card->private_data;
 	struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
 	struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
-	int status;
 
 
 	hda_tegra_enable_clocks(hda);
 	hda_tegra_enable_clocks(hda);
 
 
-	/* Read STATESTS before controller reset */
-	status = azx_readw(chip, STATESTS);
-
 	hda_tegra_init(hda);
 	hda_tegra_init(hda);
 
 
 	azx_init_chip(chip, 1);
 	azx_init_chip(chip, 1);
@@ -294,30 +289,6 @@ static const struct dev_pm_ops hda_tegra_pm = {
 	SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
 	SET_SYSTEM_SLEEP_PM_OPS(hda_tegra_suspend, hda_tegra_resume)
 };
 };
 
 
-/*
- * reboot notifier for hang-up problem at power-down
- */
-static int hda_tegra_halt(struct notifier_block *nb, unsigned long event,
-			  void *buf)
-{
-	struct azx *chip = container_of(nb, struct azx, reboot_notifier);
-	snd_hda_bus_reboot_notify(chip->bus);
-	azx_stop_chip(chip);
-	return NOTIFY_OK;
-}
-
-static void hda_tegra_notifier_register(struct azx *chip)
-{
-	chip->reboot_notifier.notifier_call = hda_tegra_halt;
-	register_reboot_notifier(&chip->reboot_notifier);
-}
-
-static void hda_tegra_notifier_unregister(struct azx *chip)
-{
-	if (chip->reboot_notifier.notifier_call)
-		unregister_reboot_notifier(&chip->reboot_notifier);
-}
-
 /*
 /*
  * destructor
  * destructor
  */
  */
@@ -326,7 +297,7 @@ static int hda_tegra_dev_free(struct snd_device *device)
 	int i;
 	int i;
 	struct azx *chip = device->device_data;
 	struct azx *chip = device->device_data;
 
 
-	hda_tegra_notifier_unregister(chip);
+	azx_notifier_unregister(chip);
 
 
 	if (chip->initialized) {
 	if (chip->initialized) {
 		for (i = 0; i < chip->num_streams; i++)
 		for (i = 0; i < chip->num_streams; i++)
@@ -478,10 +449,7 @@ static int hda_tegra_create(struct snd_card *card,
 	chip->driver_type = driver_caps & 0xff;
 	chip->driver_type = driver_caps & 0xff;
 	chip->dev_index = 0;
 	chip->dev_index = 0;
 	INIT_LIST_HEAD(&chip->pcm_list);
 	INIT_LIST_HEAD(&chip->pcm_list);
-	INIT_LIST_HEAD(&chip->list);
 
 
-	chip->position_fix[0] = POS_FIX_AUTO;
-	chip->position_fix[1] = POS_FIX_AUTO;
 	chip->codec_probe_mask = -1;
 	chip->codec_probe_mask = -1;
 
 
 	chip->single_cmd = false;
 	chip->single_cmd = false;
@@ -559,7 +527,7 @@ static int hda_tegra_probe(struct platform_device *pdev)
 
 
 	chip->running = 1;
 	chip->running = 1;
 	power_down_all_codecs(chip);
 	power_down_all_codecs(chip);
-	hda_tegra_notifier_register(chip);
+	azx_notifier_register(chip);
 
 
 	return 0;
 	return 0;
 
 

+ 3 - 3
sound/pci/hda/patch_ca0132.c

@@ -2046,14 +2046,14 @@ enum dma_state {
 	DMA_STATE_RUN   = 1
 	DMA_STATE_RUN   = 1
 };
 };
 
 
-static int dma_convert_to_hda_format(
+static int dma_convert_to_hda_format(struct hda_codec *codec,
 		unsigned int sample_rate,
 		unsigned int sample_rate,
 		unsigned short channels,
 		unsigned short channels,
 		unsigned short *hda_format)
 		unsigned short *hda_format)
 {
 {
 	unsigned int format_val;
 	unsigned int format_val;
 
 
-	format_val = snd_hda_calc_stream_format(
+	format_val = snd_hda_calc_stream_format(codec,
 				sample_rate,
 				sample_rate,
 				channels,
 				channels,
 				SNDRV_PCM_FORMAT_S32_LE,
 				SNDRV_PCM_FORMAT_S32_LE,
@@ -2452,7 +2452,7 @@ static int dspxfr_image(struct hda_codec *codec,
 	}
 	}
 
 
 	dma_engine->codec = codec;
 	dma_engine->codec = codec;
-	dma_convert_to_hda_format(sample_rate, channels, &hda_format);
+	dma_convert_to_hda_format(codec, sample_rate, channels, &hda_format);
 	dma_engine->m_converter_format = hda_format;
 	dma_engine->m_converter_format = hda_format;
 	dma_engine->buf_size = (ovly ? DSP_DMA_WRITE_BUFLEN_OVLY :
 	dma_engine->buf_size = (ovly ? DSP_DMA_WRITE_BUFLEN_OVLY :
 			DSP_DMA_WRITE_BUFLEN_INIT) * 2;
 			DSP_DMA_WRITE_BUFLEN_INIT) * 2;

+ 3 - 1
sound/pci/hda/patch_cirrus.c

@@ -657,8 +657,10 @@ static void cs4208_fixup_mac(struct hda_codec *codec,
 {
 {
 	if (action != HDA_FIXUP_ACT_PRE_PROBE)
 	if (action != HDA_FIXUP_ACT_PRE_PROBE)
 		return;
 		return;
+
+	codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
 	snd_hda_pick_fixup(codec, NULL, cs4208_mac_fixup_tbl, cs4208_fixups);
 	snd_hda_pick_fixup(codec, NULL, cs4208_mac_fixup_tbl, cs4208_fixups);
-	if (codec->fixup_id < 0 || codec->fixup_id == CS4208_MAC_AUTO)
+	if (codec->fixup_id == HDA_FIXUP_ID_NOT_SET)
 		codec->fixup_id = CS4208_GPIO0; /* default fixup */
 		codec->fixup_id = CS4208_GPIO0; /* default fixup */
 	snd_hda_apply_fixup(codec, action);
 	snd_hda_apply_fixup(codec, action);
 }
 }

+ 9 - 615
sound/pci/hda/patch_cmedia.c

@@ -31,549 +31,10 @@
 #include "hda_jack.h"
 #include "hda_jack.h"
 #include "hda_generic.h"
 #include "hda_generic.h"
 
 
-#undef ENABLE_CMI_STATIC_QUIRKS
-
-#ifdef ENABLE_CMI_STATIC_QUIRKS
-#define NUM_PINS	11
-
-
-/* board config type */
-enum {
-	CMI_MINIMAL,	/* back 3-jack */
-	CMI_MIN_FP,	/* back 3-jack + front-panel 2-jack */
-	CMI_FULL,	/* back 6-jack + front-panel 2-jack */
-	CMI_FULL_DIG,	/* back 6-jack + front-panel 2-jack + digital I/O */
-	CMI_ALLOUT,	/* back 5-jack + front-panel 2-jack + digital out */
-	CMI_AUTO,	/* let driver guess it */
-	CMI_MODELS
-};
-#endif /* ENABLE_CMI_STATIC_QUIRKS */
-
 struct cmi_spec {
 struct cmi_spec {
 	struct hda_gen_spec gen;
 	struct hda_gen_spec gen;
-
-#ifdef ENABLE_CMI_STATIC_QUIRKS
-	/* below are only for static models */
-
-	int board_config;
-	unsigned int no_line_in: 1;	/* no line-in (5-jack) */
-	unsigned int front_panel: 1;	/* has front-panel 2-jack */
-
-	/* playback */
-	struct hda_multi_out multiout;
-	hda_nid_t dac_nids[AUTO_CFG_MAX_OUTS];	/* NID for each DAC */
-	int num_dacs;
-
-	/* capture */
-	const hda_nid_t *adc_nids;
-	hda_nid_t dig_in_nid;
-
-	/* capture source */
-	const struct hda_input_mux *input_mux;
-	unsigned int cur_mux[2];
-
-	/* channel mode */
-	int num_channel_modes;
-	const struct hda_channel_mode *channel_modes;
-
-	struct hda_pcm pcm_rec[2];	/* PCM information */
-
-	/* pin default configuration */
-	hda_nid_t pin_nid[NUM_PINS];
-	unsigned int def_conf[NUM_PINS];
-	unsigned int pin_def_confs;
-
-	/* multichannel pins */
-	struct hda_verb multi_init[9];	/* 2 verbs for each pin + terminator */
-#endif /* ENABLE_CMI_STATIC_QUIRKS */
-};
-
-#ifdef ENABLE_CMI_STATIC_QUIRKS
-/*
- * input MUX
- */
-static int cmi_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_input_mux_info(spec->input_mux, uinfo);
-}
-
-static int cmi_mux_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct cmi_spec *spec = codec->spec;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
-	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
-	return 0;
-}
-
-static int cmi_mux_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct cmi_spec *spec = codec->spec;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
-	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
-				     spec->adc_nids[adc_idx], &spec->cur_mux[adc_idx]);
-}
-
-/*
- * shared line-in, mic for surrounds
- */
-
-/* 3-stack / 2 channel */
-static const struct hda_verb cmi9880_ch2_init[] = {
-	/* set line-in PIN for input */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	/* set mic PIN for input, also enable vref */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	/* route front PCM (DAC1) to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	{}
-};
-
-/* 3-stack / 6 channel */
-static const struct hda_verb cmi9880_ch6_init[] = {
-	/* set line-in PIN for output */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	/* set mic PIN for output */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	/* route front PCM (DAC1) to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	{}
-};
-
-/* 3-stack+front / 8 channel */
-static const struct hda_verb cmi9880_ch8_init[] = {
-	/* set line-in PIN for output */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	/* set mic PIN for output */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-	/* route rear-surround PCM (DAC4) to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x03 },
-	{}
-};
-
-static const struct hda_channel_mode cmi9880_channel_modes[3] = {
-	{ 2, cmi9880_ch2_init },
-	{ 6, cmi9880_ch6_init },
-	{ 8, cmi9880_ch8_init },
-};
-
-static int cmi_ch_mode_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_modes,
-				    spec->num_channel_modes);
-}
-
-static int cmi_ch_mode_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_modes,
-				   spec->num_channel_modes, spec->multiout.max_channels);
-}
-
-static int cmi_ch_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_modes,
-				   spec->num_channel_modes, &spec->multiout.max_channels);
-}
-
-/*
- */
-static const struct snd_kcontrol_new cmi9880_basic_mixer[] = {
-	/* CMI9880 has no playback volumes! */
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), /* front */
-	HDA_CODEC_MUTE("Surround Playback Switch", 0x04, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Side Playback Switch", 0x06, 0x0, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		/* The multiple "Capture Source" controls confuse alsamixer
-		 * So call somewhat different..
-		 */
-		/* .name = "Capture Source", */
-		.name = "Input Source",
-		.count = 2,
-		.info = cmi_mux_enum_info,
-		.get = cmi_mux_enum_get,
-		.put = cmi_mux_enum_put,
-	},
-	HDA_CODEC_VOLUME("Capture Volume", 0x08, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x08, 0, HDA_INPUT),
-	HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Beep Playback Volume", 0x23, 0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Beep Playback Switch", 0x23, 0, HDA_OUTPUT),
-	{ } /* end */
 };
 };
 
 
-/*
- * shared I/O pins
- */
-static const struct snd_kcontrol_new cmi9880_ch_mode_mixer[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Channel Mode",
-		.info = cmi_ch_mode_info,
-		.get = cmi_ch_mode_get,
-		.put = cmi_ch_mode_put,
-	},
-	{ } /* end */
-};
-
-/* AUD-in selections:
- * 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x1f 0x20
- */
-static const struct hda_input_mux cmi9880_basic_mux = {
-	.num_items = 4,
-	.items = {
-		{ "Front Mic", 0x5 },
-		{ "Rear Mic", 0x2 },
-		{ "Line", 0x1 },
-		{ "CD", 0x7 },
-	}
-};
-
-static const struct hda_input_mux cmi9880_no_line_mux = {
-	.num_items = 3,
-	.items = {
-		{ "Front Mic", 0x5 },
-		{ "Rear Mic", 0x2 },
-		{ "CD", 0x7 },
-	}
-};
-
-/* front, rear, clfe, rear_surr */
-static const hda_nid_t cmi9880_dac_nids[4] = {
-	0x03, 0x04, 0x05, 0x06
-};
-/* ADC0, ADC1 */
-static const hda_nid_t cmi9880_adc_nids[2] = {
-	0x08, 0x09
-};
-
-#define CMI_DIG_OUT_NID	0x07
-#define CMI_DIG_IN_NID	0x0a
-
-/*
- */
-static const struct hda_verb cmi9880_basic_init[] = {
-	/* port-D for line out (rear panel) */
-	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	/* port-E for HP out (front panel) */
-	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	/* route front PCM to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* port-A for surround (rear panel) */
-	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	/* port-G for CLFE (rear panel) */
-	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
-	/* port-H for side (rear panel) */
-	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	/* port-C for line-in (rear panel) */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	/* port-B for mic-in (rear panel) with vref */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	/* port-F for mic-in (front panel) with vref */
-	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	/* CD-in */
-	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	/* route front mic to ADC1/2 */
-	{ 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
-	{ 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
-	{} /* terminator */
-};
-
-static const struct hda_verb cmi9880_allout_init[] = {
-	/* port-D for line out (rear panel) */
-	{ 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	/* port-E for HP out (front panel) */
-	{ 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	/* route front PCM to HP */
-	{ 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
-	/* port-A for side (rear panel) */
-	{ 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	/* port-G for CLFE (rear panel) */
-	{ 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ 0x1f, AC_VERB_SET_CONNECT_SEL, 0x02 },
-	/* port-H for side (rear panel) */
-	{ 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{ 0x20, AC_VERB_SET_CONNECT_SEL, 0x01 },
-	/* port-C for surround (rear panel) */
-	{ 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	/* port-B for mic-in (rear panel) with vref */
-	{ 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	/* port-F for mic-in (front panel) with vref */
-	{ 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
-	/* CD-in */
-	{ 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	/* route front mic to ADC1/2 */
-	{ 0x08, AC_VERB_SET_CONNECT_SEL, 0x05 },
-	{ 0x09, AC_VERB_SET_CONNECT_SEL, 0x05 },
-	{} /* terminator */
-};
-
-/*
- */
-static int cmi9880_build_controls(struct hda_codec *codec)
-{
-	struct cmi_spec *spec = codec->spec;
-	struct snd_kcontrol *kctl;
-	int i, err;
-
-	err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer);
-	if (err < 0)
-		return err;
-	if (spec->channel_modes) {
-		err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer);
-		if (err < 0)
-			return err;
-	}
-	if (spec->multiout.dig_out_nid) {
-		err = snd_hda_create_spdif_out_ctls(codec,
-						    spec->multiout.dig_out_nid,
-						    spec->multiout.dig_out_nid);
-		if (err < 0)
-			return err;
-		err = snd_hda_create_spdif_share_sw(codec,
-						    &spec->multiout);
-		if (err < 0)
-			return err;
-		spec->multiout.share_spdif = 1;
-	}
-	if (spec->dig_in_nid) {
-		err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
-		if (err < 0)
-			return err;
-	}
-
-	/* assign Capture Source enums to NID */
-	kctl = snd_hda_find_mixer_ctl(codec, "Capture Source");
-	for (i = 0; kctl && i < kctl->count; i++) {
-		err = snd_hda_add_nid(codec, kctl, i, spec->adc_nids[i]);
-		if (err < 0)
-			return err;
-	}
-	return 0;
-}
-
-static int cmi9880_init(struct hda_codec *codec)
-{
-	struct cmi_spec *spec = codec->spec;
-	if (spec->board_config == CMI_ALLOUT)
-		snd_hda_sequence_write(codec, cmi9880_allout_init);
-	else
-		snd_hda_sequence_write(codec, cmi9880_basic_init);
-	if (spec->board_config == CMI_AUTO)
-		snd_hda_sequence_write(codec, spec->multi_init);
-	return 0;
-}
-
-/*
- * Analog playback callbacks
- */
-static int cmi9880_playback_pcm_open(struct hda_pcm_stream *hinfo,
-				     struct hda_codec *codec,
-				     struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
-					     hinfo);
-}
-
-static int cmi9880_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-					struct hda_codec *codec,
-					unsigned int stream_tag,
-					unsigned int format,
-					struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout, stream_tag,
-						format, substream);
-}
-
-static int cmi9880_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				       struct hda_codec *codec,
-				       struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
-}
-
-/*
- * Digital out
- */
-static int cmi9880_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
-					 struct hda_codec *codec,
-					 struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int cmi9880_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
-					  struct hda_codec *codec,
-					  struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-static int cmi9880_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-					    struct hda_codec *codec,
-					    unsigned int stream_tag,
-					    unsigned int format,
-					    struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
-					     format, substream);
-}
-
-/*
- * Analog capture
- */
-static int cmi9880_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      unsigned int stream_tag,
-				      unsigned int format,
-				      struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
-				   stream_tag, 0, format);
-	return 0;
-}
-
-static int cmi9880_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      struct snd_pcm_substream *substream)
-{
-	struct cmi_spec *spec = codec->spec;
-
-	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
-	return 0;
-}
-
-
-/*
- */
-static const struct hda_pcm_stream cmi9880_pcm_analog_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 8,
-	.nid = 0x03, /* NID to query formats and rates */
-	.ops = {
-		.open = cmi9880_playback_pcm_open,
-		.prepare = cmi9880_playback_pcm_prepare,
-		.cleanup = cmi9880_playback_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream cmi9880_pcm_analog_capture = {
-	.substreams = 2,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0x08, /* NID to query formats and rates */
-	.ops = {
-		.prepare = cmi9880_capture_pcm_prepare,
-		.cleanup = cmi9880_capture_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream cmi9880_pcm_digital_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in cmi9880_build_pcms */
-	.ops = {
-		.open = cmi9880_dig_playback_pcm_open,
-		.close = cmi9880_dig_playback_pcm_close,
-		.prepare = cmi9880_dig_playback_pcm_prepare
-	},
-};
-
-static const struct hda_pcm_stream cmi9880_pcm_digital_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in cmi9880_build_pcms */
-};
-
-static int cmi9880_build_pcms(struct hda_codec *codec)
-{
-	struct cmi_spec *spec = codec->spec;
-	struct hda_pcm *info = spec->pcm_rec;
-
-	codec->num_pcms = 1;
-	codec->pcm_info = info;
-
-	info->name = "CMI9880";
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_analog_playback;
-	info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_analog_capture;
-
-	if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
-		codec->num_pcms++;
-		info++;
-		info->name = "CMI9880 Digital";
-		info->pcm_type = HDA_PCM_TYPE_SPDIF;
-		if (spec->multiout.dig_out_nid) {
-			info->stream[SNDRV_PCM_STREAM_PLAYBACK] = cmi9880_pcm_digital_playback;
-			info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
-		}
-		if (spec->dig_in_nid) {
-			info->stream[SNDRV_PCM_STREAM_CAPTURE] = cmi9880_pcm_digital_capture;
-			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
-		}
-	}
-
-	return 0;
-}
-
-static void cmi9880_free(struct hda_codec *codec)
-{
-	kfree(codec->spec);
-}
-
-/*
- */
-
-static const char * const cmi9880_models[CMI_MODELS] = {
-	[CMI_MINIMAL]	= "minimal",
-	[CMI_MIN_FP]	= "min_fp",
-	[CMI_FULL]	= "full",
-	[CMI_FULL_DIG]	= "full_dig",
-	[CMI_ALLOUT]	= "allout",
-	[CMI_AUTO]	= "auto",
-};
-
-static const struct snd_pci_quirk cmi9880_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", CMI_FULL_DIG),
-	SND_PCI_QUIRK(0x1854, 0x002b, "LG LS75", CMI_MINIMAL),
-	SND_PCI_QUIRK(0x1854, 0x0032, "LG", CMI_FULL_DIG),
-	{} /* terminator */
-};
-
-static const struct hda_codec_ops cmi9880_patch_ops = {
-	.build_controls = cmi9880_build_controls,
-	.build_pcms = cmi9880_build_pcms,
-	.init = cmi9880_init,
-	.free = cmi9880_free,
-};
-#endif /* ENABLE_CMI_STATIC_QUIRKS */
-
 /*
 /*
  * stuff for auto-parser
  * stuff for auto-parser
  */
  */
@@ -585,12 +46,18 @@ static const struct hda_codec_ops cmi_auto_patch_ops = {
 	.unsol_event = snd_hda_jack_unsol_event,
 	.unsol_event = snd_hda_jack_unsol_event,
 };
 };
 
 
-static int cmi_parse_auto_config(struct hda_codec *codec)
+static int patch_cmi9880(struct hda_codec *codec)
 {
 {
-	struct cmi_spec *spec = codec->spec;
-	struct auto_pin_cfg *cfg = &spec->gen.autocfg;
+	struct cmi_spec *spec;
+	struct auto_pin_cfg *cfg;
 	int err;
 	int err;
 
 
+	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+	if (spec == NULL)
+		return -ENOMEM;
+
+	codec->spec = spec;
+	cfg = &spec->gen.autocfg;
 	snd_hda_gen_spec_init(&spec->gen);
 	snd_hda_gen_spec_init(&spec->gen);
 
 
 	err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
 	err = snd_hda_parse_pin_defcfg(codec, cfg, NULL, 0);
@@ -608,79 +75,6 @@ static int cmi_parse_auto_config(struct hda_codec *codec)
 	return err;
 	return err;
 }
 }
 
 
-
-static int patch_cmi9880(struct hda_codec *codec)
-{
-	struct cmi_spec *spec;
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (spec == NULL)
-		return -ENOMEM;
-
-	codec->spec = spec;
-#ifdef ENABLE_CMI_STATIC_QUIRKS
-	spec->board_config = snd_hda_check_board_config(codec, CMI_MODELS,
-							cmi9880_models,
-							cmi9880_cfg_tbl);
-	if (spec->board_config < 0) {
-		codec_dbg(codec, "%s: BIOS auto-probing.\n",
-			    codec->chip_name);
-		spec->board_config = CMI_AUTO; /* try everything */
-	}
-
-	if (spec->board_config == CMI_AUTO)
-		return cmi_parse_auto_config(codec);
-
-	/* copy default DAC NIDs */
-	memcpy(spec->dac_nids, cmi9880_dac_nids, sizeof(spec->dac_nids));
-	spec->num_dacs = 4;
-
-	switch (spec->board_config) {
-	case CMI_MINIMAL:
-	case CMI_MIN_FP:
-		spec->channel_modes = cmi9880_channel_modes;
-		if (spec->board_config == CMI_MINIMAL)
-			spec->num_channel_modes = 2;
-		else {
-			spec->front_panel = 1;
-			spec->num_channel_modes = 3;
-		}
-		spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
-		spec->input_mux = &cmi9880_basic_mux;
-		break;
-	case CMI_FULL:
-	case CMI_FULL_DIG:
-		spec->front_panel = 1;
-		spec->multiout.max_channels = 8;
-		spec->input_mux = &cmi9880_basic_mux;
-		if (spec->board_config == CMI_FULL_DIG) {
-			spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
-			spec->dig_in_nid = CMI_DIG_IN_NID;
-		}
-		break;
-	case CMI_ALLOUT:
-	default:
-		spec->front_panel = 1;
-		spec->multiout.max_channels = 8;
-		spec->no_line_in = 1;
-		spec->input_mux = &cmi9880_no_line_mux;
-		spec->multiout.dig_out_nid = CMI_DIG_OUT_NID;
-		break;
-	}
-
-	spec->multiout.num_dacs = spec->num_dacs;
-	spec->multiout.dac_nids = spec->dac_nids;
-
-	spec->adc_nids = cmi9880_adc_nids;
-
-	codec->patch_ops = cmi9880_patch_ops;
-
-	return 0;
-#else
-	return cmi_parse_auto_config(codec);
-#endif
-}
-
 /*
 /*
  * patch entries
  * patch entries
  */
  */

+ 51 - 2664
sound/pci/hda/patch_conexant.c

@@ -34,2671 +34,65 @@
 #include "hda_jack.h"
 #include "hda_jack.h"
 #include "hda_generic.h"
 #include "hda_generic.h"
 
 
-#undef ENABLE_CXT_STATIC_QUIRKS
-
-#define CXT_PIN_DIR_IN              0x00
-#define CXT_PIN_DIR_OUT             0x01
-#define CXT_PIN_DIR_INOUT           0x02
-#define CXT_PIN_DIR_IN_NOMICBIAS    0x03
-#define CXT_PIN_DIR_INOUT_NOMICBIAS 0x04
-
-#define CONEXANT_HP_EVENT	0x37
-#define CONEXANT_MIC_EVENT	0x38
-#define CONEXANT_LINE_EVENT	0x39
-
-/* Conexant 5051 specific */
-
-#define CXT5051_SPDIF_OUT	0x12
-#define CXT5051_PORTB_EVENT	0x38
-#define CXT5051_PORTC_EVENT	0x39
-
-#define AUTO_MIC_PORTB		(1 << 1)
-#define AUTO_MIC_PORTC		(1 << 2)
-
-struct conexant_spec {
-	struct hda_gen_spec gen;
-
-	unsigned int beep_amp;
-
-	/* extra EAPD pins */
-	unsigned int num_eapds;
-	hda_nid_t eapds[4];
-	bool dynamic_eapd;
-
-	unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
-
-	/* OPLC XO specific */
-	bool recording;
-	bool dc_enable;
-	unsigned int dc_input_bias; /* offset into olpc_xo_dc_bias */
-	struct nid_path *dc_mode_path;
-
-#ifdef ENABLE_CXT_STATIC_QUIRKS
-	const struct snd_kcontrol_new *mixers[5];
-	int num_mixers;
-	hda_nid_t vmaster_nid;
-
-	const struct hda_verb *init_verbs[5];	/* initialization verbs
-						 * don't forget NULL
-						 * termination!
-						 */
-	unsigned int num_init_verbs;
-
-	/* playback */
-	struct hda_multi_out multiout;	/* playback set-up
-					 * max_channels, dacs must be set
-					 * dig_out_nid and hp_nid are optional
-					 */
-	unsigned int cur_eapd;
-	unsigned int hp_present;
-	unsigned int line_present;
-	unsigned int auto_mic;
-
-	/* capture */
-	unsigned int num_adc_nids;
-	const hda_nid_t *adc_nids;
-	hda_nid_t dig_in_nid;		/* digital-in NID; optional */
-
-	unsigned int cur_adc_idx;
-	hda_nid_t cur_adc;
-	unsigned int cur_adc_stream_tag;
-	unsigned int cur_adc_format;
-
-	const struct hda_pcm_stream *capture_stream;
-
-	/* capture source */
-	const struct hda_input_mux *input_mux;
-	const hda_nid_t *capsrc_nids;
-	unsigned int cur_mux[3];
-
-	/* channel model */
-	const struct hda_channel_mode *channel_mode;
-	int num_channel_mode;
-
-	/* PCM information */
-	struct hda_pcm pcm_rec[2];	/* used in build_pcms() */
-
-	unsigned int spdif_route;
-
-	unsigned int port_d_mode;
-	unsigned int dell_automute:1;
-	unsigned int dell_vostro:1;
-	unsigned int ideapad:1;
-	unsigned int thinkpad:1;
-	unsigned int hp_laptop:1;
-	unsigned int asus:1;
-
-	unsigned int mic_boost; /* offset into cxt5066_analog_mic_boost */
-#endif /* ENABLE_CXT_STATIC_QUIRKS */
-};
-
-
-#ifdef CONFIG_SND_HDA_INPUT_BEEP
-static inline void set_beep_amp(struct conexant_spec *spec, hda_nid_t nid,
-				int idx, int dir)
-{
-	spec->gen.beep_nid = nid;
-	spec->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir);
-}
-/* additional beep mixers; the actual parameters are overwritten at build */
-static const struct snd_kcontrol_new cxt_beep_mixer[] = {
-	HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
-	HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
-	{ } /* end */
-};
-
-/* create beep controls if needed */
-static int add_beep_ctls(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	int err;
-
-	if (spec->beep_amp) {
-		const struct snd_kcontrol_new *knew;
-		for (knew = cxt_beep_mixer; knew->name; knew++) {
-			struct snd_kcontrol *kctl;
-			kctl = snd_ctl_new1(knew, codec);
-			if (!kctl)
-				return -ENOMEM;
-			kctl->private_value = spec->beep_amp;
-			err = snd_hda_ctl_add(codec, 0, kctl);
-			if (err < 0)
-				return err;
-		}
-	}
-	return 0;
-}
-#else
-#define set_beep_amp(spec, nid, idx, dir) /* NOP */
-#define add_beep_ctls(codec)	0
-#endif
-
-
-#ifdef ENABLE_CXT_STATIC_QUIRKS
-static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
-					     hinfo);
-}
-
-static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-					 struct hda_codec *codec,
-					 unsigned int stream_tag,
-					 unsigned int format,
-					 struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
-						stream_tag,
-						format, substream);
-}
-
-static int conexant_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
-					 struct hda_codec *codec,
-					 struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
-}
-
-/*
- * Digital out
- */
-static int conexant_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
-					  struct hda_codec *codec,
-					  struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
-					 struct hda_codec *codec,
-					 struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-static int conexant_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
-					 struct hda_codec *codec,
-					 unsigned int stream_tag,
-					 unsigned int format,
-					 struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_multi_out_dig_prepare(codec, &spec->multiout,
-					     stream_tag,
-					     format, substream);
-}
-
-/*
- * Analog capture
- */
-static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      unsigned int stream_tag,
-				      unsigned int format,
-				      struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
-				   stream_tag, 0, format);
-	return 0;
-}
-
-static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	snd_hda_codec_cleanup_stream(codec, spec->adc_nids[substream->number]);
-	return 0;
-}
-
-
-
-static const struct hda_pcm_stream conexant_pcm_analog_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0, /* fill later */
-	.ops = {
-		.open = conexant_playback_pcm_open,
-		.prepare = conexant_playback_pcm_prepare,
-		.cleanup = conexant_playback_pcm_cleanup
-	},
-};
-
-static const struct hda_pcm_stream conexant_pcm_analog_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0, /* fill later */
-	.ops = {
-		.prepare = conexant_capture_pcm_prepare,
-		.cleanup = conexant_capture_pcm_cleanup
-	},
-};
-
-
-static const struct hda_pcm_stream conexant_pcm_digital_playback = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0, /* fill later */
-	.ops = {
-		.open = conexant_dig_playback_pcm_open,
-		.close = conexant_dig_playback_pcm_close,
-		.prepare = conexant_dig_playback_pcm_prepare
-	},
-};
-
-static const struct hda_pcm_stream conexant_pcm_digital_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	/* NID is set in alc_build_pcms */
-};
-
-static int cx5051_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      unsigned int stream_tag,
-				      unsigned int format,
-				      struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	spec->cur_adc = spec->adc_nids[spec->cur_adc_idx];
-	spec->cur_adc_stream_tag = stream_tag;
-	spec->cur_adc_format = format;
-	snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
-	return 0;
-}
-
-static int cx5051_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
-				      struct hda_codec *codec,
-				      struct snd_pcm_substream *substream)
-{
-	struct conexant_spec *spec = codec->spec;
-	snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
-	spec->cur_adc = 0;
-	return 0;
-}
-
-static const struct hda_pcm_stream cx5051_pcm_analog_capture = {
-	.substreams = 1,
-	.channels_min = 2,
-	.channels_max = 2,
-	.nid = 0, /* fill later */
-	.ops = {
-		.prepare = cx5051_capture_pcm_prepare,
-		.cleanup = cx5051_capture_pcm_cleanup
-	},
-};
-
-static int conexant_build_pcms(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	struct hda_pcm *info = spec->pcm_rec;
-
-	codec->num_pcms = 1;
-	codec->pcm_info = info;
-
-	info->name = "CONEXANT Analog";
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback;
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
-		spec->multiout.max_channels;
-	info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
-		spec->multiout.dac_nids[0];
-	if (spec->capture_stream)
-		info->stream[SNDRV_PCM_STREAM_CAPTURE] = *spec->capture_stream;
-	else {
-		if (codec->vendor_id == 0x14f15051)
-			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
-				cx5051_pcm_analog_capture;
-		else {
-			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
-				conexant_pcm_analog_capture;
-			info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
-				spec->num_adc_nids;
-		}
-	}
-	info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
-
-	if (spec->multiout.dig_out_nid) {
-		info++;
-		codec->num_pcms++;
-		info->name = "Conexant Digital";
-		info->pcm_type = HDA_PCM_TYPE_SPDIF;
-		info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
-			conexant_pcm_digital_playback;
-		info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
-			spec->multiout.dig_out_nid;
-		if (spec->dig_in_nid) {
-			info->stream[SNDRV_PCM_STREAM_CAPTURE] =
-				conexant_pcm_digital_capture;
-			info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
-				spec->dig_in_nid;
-		}
-	}
-
-	return 0;
-}
-
-static int conexant_mux_enum_info(struct snd_kcontrol *kcontrol,
-	       			  struct snd_ctl_elem_info *uinfo)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-
-	return snd_hda_input_mux_info(spec->input_mux, uinfo);
-}
-
-static int conexant_mux_enum_get(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
-	ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
-	return 0;
-}
-
-static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
-
-	return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
-				     spec->capsrc_nids[adc_idx],
-				     &spec->cur_mux[adc_idx]);
-}
-
-static void conexant_set_power(struct hda_codec *codec, hda_nid_t fg,
-			       unsigned int power_state)
-{
-	if (power_state == AC_PWRST_D3)
-		msleep(100);
-	snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
-			    power_state);
-	/* partial workaround for "azx_get_response timeout" */
-	if (power_state == AC_PWRST_D0)
-		msleep(10);
-	snd_hda_codec_set_power_to_all(codec, fg, power_state);
-}
-
-static int conexant_init(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	int i;
-
-	for (i = 0; i < spec->num_init_verbs; i++)
-		snd_hda_sequence_write(codec, spec->init_verbs[i]);
-	return 0;
-}
-
-static void conexant_free(struct hda_codec *codec)
-{
-	kfree(codec->spec);
-}
-
-static const struct snd_kcontrol_new cxt_capture_mixers[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Capture Source",
-		.info = conexant_mux_enum_info,
-		.get = conexant_mux_enum_get,
-		.put = conexant_mux_enum_put
-	},
-	{}
-};
-
-static const char * const slave_pfxs[] = {
-	"Headphone", "Speaker", "Bass Speaker", "Front", "Surround", "CLFE",
-	NULL
-};
-
-static int conexant_build_controls(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int i;
-	int err;
-
-	for (i = 0; i < spec->num_mixers; i++) {
-		err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
-		if (err < 0)
-			return err;
-	}
-	if (spec->multiout.dig_out_nid) {
-		err = snd_hda_create_spdif_out_ctls(codec,
-						    spec->multiout.dig_out_nid,
-						    spec->multiout.dig_out_nid);
-		if (err < 0)
-			return err;
-		err = snd_hda_create_spdif_share_sw(codec,
-						    &spec->multiout);
-		if (err < 0)
-			return err;
-		spec->multiout.share_spdif = 1;
-	} 
-	if (spec->dig_in_nid) {
-		err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid);
-		if (err < 0)
-			return err;
-	}
-
-	/* if we have no master control, let's create it */
-	if (spec->vmaster_nid &&
-	    !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
-		unsigned int vmaster_tlv[4];
-		snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
-					HDA_OUTPUT, vmaster_tlv);
-		err = snd_hda_add_vmaster(codec, "Master Playback Volume",
-					  vmaster_tlv, slave_pfxs,
-					  "Playback Volume");
-		if (err < 0)
-			return err;
-	}
-	if (spec->vmaster_nid &&
-	    !snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
-		err = snd_hda_add_vmaster(codec, "Master Playback Switch",
-					  NULL, slave_pfxs,
-					  "Playback Switch");
-		if (err < 0)
-			return err;
-	}
-
-	if (spec->input_mux) {
-		err = snd_hda_add_new_ctls(codec, cxt_capture_mixers);
-		if (err < 0)
-			return err;
-	}
-
-	err = add_beep_ctls(codec);
-	if (err < 0)
-		return err;
-
-	return 0;
-}
-
-static const struct hda_codec_ops conexant_patch_ops = {
-	.build_controls = conexant_build_controls,
-	.build_pcms = conexant_build_pcms,
-	.init = conexant_init,
-	.free = conexant_free,
-	.set_power_state = conexant_set_power,
-};
-
-static int patch_conexant_auto(struct hda_codec *codec);
-/*
- * EAPD control
- * the private value = nid | (invert << 8)
- */
-
-#define cxt_eapd_info		snd_ctl_boolean_mono_info
-
-static int cxt_eapd_get(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	int invert = (kcontrol->private_value >> 8) & 1;
-	if (invert)
-		ucontrol->value.integer.value[0] = !spec->cur_eapd;
-	else
-		ucontrol->value.integer.value[0] = spec->cur_eapd;
-	return 0;
-
-}
-
-static int cxt_eapd_put(struct snd_kcontrol *kcontrol,
-			     struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	int invert = (kcontrol->private_value >> 8) & 1;
-	hda_nid_t nid = kcontrol->private_value & 0xff;
-	unsigned int eapd;
-
-	eapd = !!ucontrol->value.integer.value[0];
-	if (invert)
-		eapd = !eapd;
-	if (eapd == spec->cur_eapd)
-		return 0;
-	
-	spec->cur_eapd = eapd;
-	snd_hda_codec_write_cache(codec, nid,
-				  0, AC_VERB_SET_EAPD_BTLENABLE,
-				  eapd ? 0x02 : 0x00);
-	return 1;
-}
-
-/* controls for test mode */
-#ifdef CONFIG_SND_DEBUG
-
-#define CXT_EAPD_SWITCH(xname, nid, mask) \
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
-	  .info = cxt_eapd_info, \
-	  .get = cxt_eapd_get, \
-	  .put = cxt_eapd_put, \
-	  .private_value = nid | (mask<<16) }
-
-
-
-static int conexant_ch_mode_info(struct snd_kcontrol *kcontrol,
-				 struct snd_ctl_elem_info *uinfo)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
-				    spec->num_channel_mode);
-}
-
-static int conexant_ch_mode_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
-				   spec->num_channel_mode,
-				   spec->multiout.max_channels);
-}
-
-static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
-				      spec->num_channel_mode,
-				      &spec->multiout.max_channels);
-	return err;
-}
-
-#define CXT_PIN_MODE(xname, nid, dir) \
-	{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0,  \
-	  .info = conexant_ch_mode_info, \
-	  .get = conexant_ch_mode_get, \
-	  .put = conexant_ch_mode_put, \
-	  .private_value = nid | (dir<<16) }
-
-#endif /* CONFIG_SND_DEBUG */
-
-/* Conexant 5045 specific */
-
-static const hda_nid_t cxt5045_dac_nids[1] = { 0x19 };
-static const hda_nid_t cxt5045_adc_nids[1] = { 0x1a };
-static const hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a };
-#define CXT5045_SPDIF_OUT	0x18
-
-static const struct hda_channel_mode cxt5045_modes[1] = {
-	{ 2, NULL },
-};
-
-static const struct hda_input_mux cxt5045_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "Internal Mic", 0x1 },
-		{ "Mic",          0x2 },
-	}
-};
-
-static const struct hda_input_mux cxt5045_capture_source_benq = {
-	.num_items = 4,
-	.items = {
-		{ "Internal Mic", 0x1 },
-		{ "Mic",          0x2 },
-		{ "Line",         0x3 },
-		{ "Mixer",        0x0 },
-	}
-};
-
-/* turn on/off EAPD (+ mute HP) as a master switch */
-static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	unsigned int bits;
-
-	if (!cxt_eapd_put(kcontrol, ucontrol))
-		return 0;
-
-	/* toggle internal speakers mute depending of presence of
-	 * the headphone jack
-	 */
-	bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
-	snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-
-	bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
-	snd_hda_codec_amp_stereo(codec, 0x11, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	return 1;
-}
-
-/* bind volumes of both NID 0x10 and 0x11 */
-static const struct hda_bind_ctls cxt5045_hp_bind_master_vol = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x10, 3, 0, HDA_OUTPUT),
-		HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
-		0
-	},
-};
-
-/* toggle input of built-in and mic jack appropriately */
-static void cxt5045_hp_automic(struct hda_codec *codec)
-{
-	static const struct hda_verb mic_jack_on[] = {
-		{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-		{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-		{}
-	};
-	static const struct hda_verb mic_jack_off[] = {
-		{0x12, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
-		{0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
-		{}
-	};
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x12);
-	if (present)
-		snd_hda_sequence_write(codec, mic_jack_on);
-	else
-		snd_hda_sequence_write(codec, mic_jack_off);
-}
-
-
-/* mute internal speaker if HP is plugged */
-static void cxt5045_hp_automute(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int bits;
-
-	spec->hp_present = snd_hda_jack_detect(codec, 0x11);
-
-	bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0; 
-	snd_hda_codec_amp_stereo(codec, 0x10, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-}
-
-/* unsolicited event for HP jack sensing */
-static void cxt5045_hp_unsol_event(struct hda_codec *codec,
-				   unsigned int res)
-{
-	res >>= 26;
-	switch (res) {
-	case CONEXANT_HP_EVENT:
-		cxt5045_hp_automute(codec);
-		break;
-	case CONEXANT_MIC_EVENT:
-		cxt5045_hp_automic(codec);
-		break;
-
-	}
-}
-
-static const struct snd_kcontrol_new cxt5045_mixers[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("PCM Playback Volume", 0x17, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("PCM Playback Switch", 0x17, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x17, 0x2, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x17, 0x2, HDA_INPUT),
-	HDA_BIND_VOL("Master Playback Volume", &cxt5045_hp_bind_master_vol),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.info = cxt_eapd_info,
-		.get = cxt_eapd_get,
-		.put = cxt5045_hp_master_sw_put,
-		.private_value = 0x10,
-	},
-
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5045_benq_mixers[] = {
-	HDA_CODEC_VOLUME("Line Playback Volume", 0x17, 0x3, HDA_INPUT),
-	HDA_CODEC_MUTE("Line Playback Switch", 0x17, 0x3, HDA_INPUT),
-
-	{}
-};
-
-static const struct hda_verb cxt5045_init_verbs[] = {
-	/* Line in, Mic */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
-	/* HP, Amp  */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x10, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Record selector: Internal mic */
-	{0x1a, AC_VERB_SET_CONNECT_SEL,0x1},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
-	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
-	/* SPDIF route: PCM */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{ 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 },
-	/* EAPD */
-	{0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2 }, /* default on */ 
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5045_benq_init_verbs[] = {
-	/* Internal Mic, Mic */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_80 },
-	/* Line In,HP, Amp  */
-	{0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x10, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x11, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	/* Record selector: Internal mic */
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x1},
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE,
-	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
-	/* SPDIF route: PCM */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* EAPD */
-	{0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5045_hp_sense_init_verbs[] = {
-	/* pin sensing on HP jack */
-	{0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5045_mic_sense_init_verbs[] = {
-	/* pin sensing on HP jack */
-	{0x12, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
-	{ } /* end */
-};
-
-#ifdef CONFIG_SND_DEBUG
-/* Test configuration for debugging, modelled after the ALC260 test
- * configuration.
- */
-static const struct hda_input_mux cxt5045_test_capture_source = {
-	.num_items = 5,
-	.items = {
-		{ "MIXER", 0x0 },
-		{ "MIC1 pin", 0x1 },
-		{ "LINE1 pin", 0x2 },
-		{ "HP-OUT pin", 0x3 },
-		{ "CD pin", 0x4 },
-        },
-};
-
-static const struct snd_kcontrol_new cxt5045_test_mixer[] = {
-
-	/* Output controls */
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("HP-OUT Playback Volume", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("HP-OUT Playback Switch", 0x11, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x12, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("LINE1 Playback Switch", 0x12, 0x0, HDA_OUTPUT),
-	
-	/* Modes for retasking pin widgets */
-	CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT),
-	CXT_PIN_MODE("LINE1 pin mode", 0x12, CXT_PIN_DIR_INOUT),
-
-	/* EAPD Switch Control */
-	CXT_EAPD_SWITCH("External Amplifier", 0x10, 0x0),
-
-	/* Loopback mixer controls */
-
-	HDA_CODEC_VOLUME("PCM Volume", 0x17, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("PCM Switch", 0x17, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("MIC1 pin Volume", 0x17, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("MIC1 pin Switch", 0x17, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("LINE1 pin Volume", 0x17, 0x2, HDA_INPUT),
-	HDA_CODEC_MUTE("LINE1 pin Switch", 0x17, 0x2, HDA_INPUT),
-	HDA_CODEC_VOLUME("HP-OUT pin Volume", 0x17, 0x3, HDA_INPUT),
-	HDA_CODEC_MUTE("HP-OUT pin Switch", 0x17, 0x3, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD pin Volume", 0x17, 0x4, HDA_INPUT),
-	HDA_CODEC_MUTE("CD pin Switch", 0x17, 0x4, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Input Source",
-		.info = conexant_mux_enum_info,
-		.get = conexant_mux_enum_get,
-		.put = conexant_mux_enum_put,
-	},
-	/* Audio input controls */
-	HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x0, HDA_INPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5045_test_init_verbs[] = {
-	/* Set connections */
-	{ 0x10, AC_VERB_SET_CONNECT_SEL, 0x0 },
-	{ 0x11, AC_VERB_SET_CONNECT_SEL, 0x0 },
-	{ 0x12, AC_VERB_SET_CONNECT_SEL, 0x0 },
-	/* Enable retasking pins as output, initially without power amp */
-	{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* Disable digital (SPDIF) pins initially, but users can enable
-	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
-	 * payload also sets the generation to 0, output to be in "consumer"
-	 * PCM format, copyright asserted, no pre-emphasis and no validity
-	 * control.
-	 */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x18, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
-	/* Unmute retasking pin widget output buffers since the default
-	 * state appears to be output.  As the pin mode is changed by the
-	 * user the pin mode control will take care of enabling the pin's
-	 * input/output buffers as needed.
-	 */
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Mute capture amp left and right */
-	{0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-
-	/* Set ADC connection select to match default mixer setting (mic1
-	 * pin)
-	 */
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
-	{0x17, AC_VERB_SET_CONNECT_SEL, 0x01},
-
-	/* Mute all inputs to mixer widget (even unconnected ones) */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Mic1 pin */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* Line pin */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* HP pin */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
-
-	{ }
-};
-#endif
-
-
-/* initialize jack-sensing, too */
-static int cxt5045_init(struct hda_codec *codec)
-{
-	conexant_init(codec);
-	cxt5045_hp_automute(codec);
-	return 0;
-}
-
-
-enum {
-	CXT5045_LAPTOP_HPSENSE,
-	CXT5045_LAPTOP_MICSENSE,
-	CXT5045_LAPTOP_HPMICSENSE,
-	CXT5045_BENQ,
-#ifdef CONFIG_SND_DEBUG
-	CXT5045_TEST,
-#endif
-	CXT5045_AUTO,
-	CXT5045_MODELS
-};
-
-static const char * const cxt5045_models[CXT5045_MODELS] = {
-	[CXT5045_LAPTOP_HPSENSE]	= "laptop-hpsense",
-	[CXT5045_LAPTOP_MICSENSE]	= "laptop-micsense",
-	[CXT5045_LAPTOP_HPMICSENSE]	= "laptop-hpmicsense",
-	[CXT5045_BENQ]			= "benq",
-#ifdef CONFIG_SND_DEBUG
-	[CXT5045_TEST]		= "test",
-#endif
-	[CXT5045_AUTO]			= "auto",
-};
-
-static const struct snd_pci_quirk cxt5045_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ),
-	SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE),
-	SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP_HPMICSENSE),
-	SND_PCI_QUIRK(0x1734, 0x110e, "Fujitsu V5505",
-		      CXT5045_LAPTOP_HPMICSENSE),
-	SND_PCI_QUIRK(0x1509, 0x1e40, "FIC", CXT5045_LAPTOP_HPMICSENSE),
-	SND_PCI_QUIRK(0x1509, 0x2f05, "FIC", CXT5045_LAPTOP_HPMICSENSE),
-	SND_PCI_QUIRK(0x1509, 0x2f06, "FIC", CXT5045_LAPTOP_HPMICSENSE),
-	SND_PCI_QUIRK_MASK(0x1631, 0xff00, 0xc100, "Packard Bell",
-			   CXT5045_LAPTOP_HPMICSENSE),
-	SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP_HPSENSE),
-	{}
-};
-
-static int patch_cxt5045(struct hda_codec *codec)
-{
-	struct conexant_spec *spec;
-	int board_config;
-
-	board_config = snd_hda_check_board_config(codec, CXT5045_MODELS,
-						  cxt5045_models,
-						  cxt5045_cfg_tbl);
-	if (board_config < 0)
-		board_config = CXT5045_AUTO; /* model=auto as default */
-	if (board_config == CXT5045_AUTO)
-		return patch_conexant_auto(codec);
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (!spec)
-		return -ENOMEM;
-	codec->spec = spec;
-	codec->single_adc_amp = 1;
-
-	spec->multiout.max_channels = 2;
-	spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids);
-	spec->multiout.dac_nids = cxt5045_dac_nids;
-	spec->multiout.dig_out_nid = CXT5045_SPDIF_OUT;
-	spec->num_adc_nids = 1;
-	spec->adc_nids = cxt5045_adc_nids;
-	spec->capsrc_nids = cxt5045_capsrc_nids;
-	spec->input_mux = &cxt5045_capture_source;
-	spec->num_mixers = 1;
-	spec->mixers[0] = cxt5045_mixers;
-	spec->num_init_verbs = 1;
-	spec->init_verbs[0] = cxt5045_init_verbs;
-	spec->spdif_route = 0;
-	spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes);
-	spec->channel_mode = cxt5045_modes;
-
-	set_beep_amp(spec, 0x16, 0, 1);
-
-	codec->patch_ops = conexant_patch_ops;
-
-	switch (board_config) {
-	case CXT5045_LAPTOP_HPSENSE:
-		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
-		spec->input_mux = &cxt5045_capture_source;
-		spec->num_init_verbs = 2;
-		spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
-		spec->mixers[0] = cxt5045_mixers;
-		codec->patch_ops.init = cxt5045_init;
-		break;
-	case CXT5045_LAPTOP_MICSENSE:
-		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
-		spec->input_mux = &cxt5045_capture_source;
-		spec->num_init_verbs = 2;
-		spec->init_verbs[1] = cxt5045_mic_sense_init_verbs;
-		spec->mixers[0] = cxt5045_mixers;
-		codec->patch_ops.init = cxt5045_init;
-		break;
-	default:
-	case CXT5045_LAPTOP_HPMICSENSE:
-		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
-		spec->input_mux = &cxt5045_capture_source;
-		spec->num_init_verbs = 3;
-		spec->init_verbs[1] = cxt5045_hp_sense_init_verbs;
-		spec->init_verbs[2] = cxt5045_mic_sense_init_verbs;
-		spec->mixers[0] = cxt5045_mixers;
-		codec->patch_ops.init = cxt5045_init;
-		break;
-	case CXT5045_BENQ:
-		codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
-		spec->input_mux = &cxt5045_capture_source_benq;
-		spec->num_init_verbs = 1;
-		spec->init_verbs[0] = cxt5045_benq_init_verbs;
-		spec->mixers[0] = cxt5045_mixers;
-		spec->mixers[1] = cxt5045_benq_mixers;
-		spec->num_mixers = 2;
-		codec->patch_ops.init = cxt5045_init;
-		break;
-#ifdef CONFIG_SND_DEBUG
-	case CXT5045_TEST:
-		spec->input_mux = &cxt5045_test_capture_source;
-		spec->mixers[0] = cxt5045_test_mixer;
-		spec->init_verbs[0] = cxt5045_test_init_verbs;
-		break;
-		
-#endif	
-	}
-
-	switch (codec->subsystem_id >> 16) {
-	case 0x103c:
-	case 0x1631:
-	case 0x1734:
-	case 0x17aa:
-		/* HP, Packard Bell, Fujitsu-Siemens & Lenovo laptops have
-		 * really bad sound over 0dB on NID 0x17. Fix max PCM level to
-		 * 0 dB (originally it has 0x2b steps with 0dB offset 0x14)
-		 */
-		snd_hda_override_amp_caps(codec, 0x17, HDA_INPUT,
-					  (0x14 << AC_AMPCAP_OFFSET_SHIFT) |
-					  (0x14 << AC_AMPCAP_NUM_STEPS_SHIFT) |
-					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
-					  (1 << AC_AMPCAP_MUTE_SHIFT));
-		break;
-	}
-
-	if (spec->beep_amp)
-		snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
-
-	return 0;
-}
-
-
-/* Conexant 5047 specific */
-#define CXT5047_SPDIF_OUT	0x11
-
-static const hda_nid_t cxt5047_dac_nids[1] = { 0x10 }; /* 0x1c */
-static const hda_nid_t cxt5047_adc_nids[1] = { 0x12 };
-static const hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a };
-
-static const struct hda_channel_mode cxt5047_modes[1] = {
-	{ 2, NULL },
-};
-
-static const struct hda_input_mux cxt5047_toshiba_capture_source = {
-	.num_items = 2,
-	.items = {
-		{ "ExtMic", 0x2 },
-		{ "Line-In", 0x1 },
-	}
-};
-
-/* turn on/off EAPD (+ mute HP) as a master switch */
-static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	unsigned int bits;
-
-	if (!cxt_eapd_put(kcontrol, ucontrol))
-		return 0;
-
-	/* toggle internal speakers mute depending of presence of
-	 * the headphone jack
-	 */
-	bits = (!spec->hp_present && spec->cur_eapd) ? 0 : HDA_AMP_MUTE;
-	/* NOTE: Conexat codec needs the index for *OUTPUT* amp of
-	 * pin widgets unlike other codecs.  In this case, we need to
-	 * set index 0x01 for the volume from the mixer amp 0x19.
-	 */
-	snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01,
-				 HDA_AMP_MUTE, bits);
-	bits = spec->cur_eapd ? 0 : HDA_AMP_MUTE;
-	snd_hda_codec_amp_stereo(codec, 0x13, HDA_OUTPUT, 0,
-				 HDA_AMP_MUTE, bits);
-	return 1;
-}
-
-/* mute internal speaker if HP is plugged */
-static void cxt5047_hp_automute(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int bits;
-
-	spec->hp_present = snd_hda_jack_detect(codec, 0x13);
-
-	bits = (spec->hp_present || !spec->cur_eapd) ? HDA_AMP_MUTE : 0;
-	/* See the note in cxt5047_hp_master_sw_put */
-	snd_hda_codec_amp_stereo(codec, 0x1d, HDA_OUTPUT, 0x01,
-				 HDA_AMP_MUTE, bits);
-}
-
-/* toggle input of built-in and mic jack appropriately */
-static void cxt5047_hp_automic(struct hda_codec *codec)
-{
-	static const struct hda_verb mic_jack_on[] = {
-		{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-		{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-		{}
-	};
-	static const struct hda_verb mic_jack_off[] = {
-		{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-		{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-		{}
-	};
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x15);
-	if (present)
-		snd_hda_sequence_write(codec, mic_jack_on);
-	else
-		snd_hda_sequence_write(codec, mic_jack_off);
-}
-
-/* unsolicited event for HP jack sensing */
-static void cxt5047_hp_unsol_event(struct hda_codec *codec,
-				  unsigned int res)
-{
-	switch (res >> 26) {
-	case CONEXANT_HP_EVENT:
-		cxt5047_hp_automute(codec);
-		break;
-	case CONEXANT_MIC_EVENT:
-		cxt5047_hp_automic(codec);
-		break;
-	}
-}
-
-static const struct snd_kcontrol_new cxt5047_base_mixers[] = {
-	HDA_CODEC_VOLUME("Mic Playback Volume", 0x19, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Playback Switch", 0x19, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
-	HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
-	HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.info = cxt_eapd_info,
-		.get = cxt_eapd_get,
-		.put = cxt5047_hp_master_sw_put,
-		.private_value = 0x13,
-	},
-
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5047_hp_spk_mixers[] = {
-	/* See the note in cxt5047_hp_master_sw_put */
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x01, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Headphone Playback Volume", 0x13, 0x00, HDA_OUTPUT),
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5047_hp_only_mixers[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT),
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5047_init_verbs[] = {
-	/* Line in, Mic, Built-in Mic */
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
-	/* HP, Speaker  */
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
-	{0x13, AC_VERB_SET_CONNECT_SEL, 0x0}, /* mixer(0x19) */
-	{0x1d, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mixer(0x19) */
-	/* Record selector: Mic */
-	{0x12, AC_VERB_SET_CONNECT_SEL,0x03},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE,
-	 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
-	{0x1A, AC_VERB_SET_CONNECT_SEL,0x02},
-	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
-	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00},
-	{0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
-	 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03},
-	/* SPDIF route: PCM */
-	{ 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 },
-	/* Enable unsolicited events */
-	{0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
-	{ } /* end */
-};
-
-/* configuration for Toshiba Laptops */
-static const struct hda_verb cxt5047_toshiba_init_verbs[] = {
-	{0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0}, /* default off */
-	{}
-};
-
-/* Test configuration for debugging, modelled after the ALC260 test
- * configuration.
- */
-#ifdef CONFIG_SND_DEBUG
-static const struct hda_input_mux cxt5047_test_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "LINE1 pin", 0x0 },
-		{ "MIC1 pin", 0x1 },
-		{ "MIC2 pin", 0x2 },
-		{ "CD pin", 0x3 },
-        },
-};
-
-static const struct snd_kcontrol_new cxt5047_test_mixer[] = {
-
-	/* Output only controls */
-	HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("OutAmp-1 Switch", 0x10,0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("OutAmp-2 Volume", 0x1c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("OutAmp-2 Switch", 0x1c, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("HeadPhone Playback Volume", 0x13, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("HeadPhone Playback Switch", 0x13, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line1-Out Playback Volume", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Line1-Out Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-	HDA_CODEC_VOLUME("Line2-Out Playback Volume", 0x15, 0x0, HDA_OUTPUT),
-	HDA_CODEC_MUTE("Line2-Out Playback Switch", 0x15, 0x0, HDA_OUTPUT),
-
-	/* Modes for retasking pin widgets */
-	CXT_PIN_MODE("LINE1 pin mode", 0x14, CXT_PIN_DIR_INOUT),
-	CXT_PIN_MODE("MIC1 pin mode", 0x15, CXT_PIN_DIR_INOUT),
-
-	/* EAPD Switch Control */
-	CXT_EAPD_SWITCH("External Amplifier", 0x13, 0x0),
-
-	/* Loopback mixer controls */
-	HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x12, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("MIC1 Playback Switch", 0x12, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x12, 0x02, HDA_INPUT),
-	HDA_CODEC_MUTE("MIC2 Playback Switch", 0x12, 0x02, HDA_INPUT),
-	HDA_CODEC_VOLUME("LINE Playback Volume", 0x12, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("LINE Playback Switch", 0x12, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("CD Playback Volume", 0x12, 0x04, HDA_INPUT),
-	HDA_CODEC_MUTE("CD Playback Switch", 0x12, 0x04, HDA_INPUT),
-
-	HDA_CODEC_VOLUME("Capture-1 Volume", 0x19, 0x0, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture-1 Switch", 0x19, 0x0, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture-2 Volume", 0x19, 0x1, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture-2 Switch", 0x19, 0x1, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture-3 Volume", 0x19, 0x2, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture-3 Switch", 0x19, 0x2, HDA_INPUT),
-	HDA_CODEC_VOLUME("Capture-4 Volume", 0x19, 0x3, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture-4 Switch", 0x19, 0x3, HDA_INPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Input Source",
-		.info = conexant_mux_enum_info,
-		.get = conexant_mux_enum_get,
-		.put = conexant_mux_enum_put,
-	},
-	HDA_CODEC_VOLUME("Mic Boost Volume", 0x1a, 0x0, HDA_OUTPUT),
-
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5047_test_init_verbs[] = {
-	/* Enable retasking pins as output, initially without power amp */
-	{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* Disable digital (SPDIF) pins initially, but users can enable
-	 * them via a mixer switch.  In the case of SPDIF-out, this initverb
-	 * payload also sets the generation to 0, output to be in "consumer"
-	 * PCM format, copyright asserted, no pre-emphasis and no validity
-	 * control.
-	 */
-	{0x18, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
-	/* Ensure mic1, mic2, line1 pin widgets take input from the 
-	 * OUT1 sum bus when acting as an output.
-	 */
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0},
-
-	/* Start with output sum widgets muted and their output gains at min */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
-	/* Unmute retasking pin widget output buffers since the default
-	 * state appears to be output.  As the pin mode is changed by the
-	 * user the pin mode control will take care of enabling the pin's
-	 * input/output buffers as needed.
-	 */
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	{0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Mute capture amp left and right */
-	{0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-
-	/* Set ADC connection select to match default mixer setting (mic1
-	 * pin)
-	 */
-	{0x12, AC_VERB_SET_CONNECT_SEL, 0x00},
-
-	/* Mute all inputs to mixer widget (even unconnected ones) */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
-	{0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
-	{ }
-};
-#endif
-
-
-/* initialize jack-sensing, too */
-static int cxt5047_hp_init(struct hda_codec *codec)
-{
-	conexant_init(codec);
-	cxt5047_hp_automute(codec);
-	return 0;
-}
-
-
-enum {
-	CXT5047_LAPTOP,		/* Laptops w/o EAPD support */
-	CXT5047_LAPTOP_HP,	/* Some HP laptops */
-	CXT5047_LAPTOP_EAPD,	/* Laptops with EAPD support */
-#ifdef CONFIG_SND_DEBUG
-	CXT5047_TEST,
-#endif
-	CXT5047_AUTO,
-	CXT5047_MODELS
-};
-
-static const char * const cxt5047_models[CXT5047_MODELS] = {
-	[CXT5047_LAPTOP]	= "laptop",
-	[CXT5047_LAPTOP_HP]	= "laptop-hp",
-	[CXT5047_LAPTOP_EAPD]	= "laptop-eapd",
-#ifdef CONFIG_SND_DEBUG
-	[CXT5047_TEST]		= "test",
-#endif
-	[CXT5047_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk cxt5047_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP),
-	SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
-			   CXT5047_LAPTOP),
-	SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD),
-	{}
-};
-
-static int patch_cxt5047(struct hda_codec *codec)
-{
-	struct conexant_spec *spec;
-	int board_config;
-
-	board_config = snd_hda_check_board_config(codec, CXT5047_MODELS,
-						  cxt5047_models,
-						  cxt5047_cfg_tbl);
-	if (board_config < 0)
-		board_config = CXT5047_AUTO; /* model=auto as default */
-	if (board_config == CXT5047_AUTO)
-		return patch_conexant_auto(codec);
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (!spec)
-		return -ENOMEM;
-	codec->spec = spec;
-	codec->pin_amp_workaround = 1;
-
-	spec->multiout.max_channels = 2;
-	spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids);
-	spec->multiout.dac_nids = cxt5047_dac_nids;
-	spec->multiout.dig_out_nid = CXT5047_SPDIF_OUT;
-	spec->num_adc_nids = 1;
-	spec->adc_nids = cxt5047_adc_nids;
-	spec->capsrc_nids = cxt5047_capsrc_nids;
-	spec->num_mixers = 1;
-	spec->mixers[0] = cxt5047_base_mixers;
-	spec->num_init_verbs = 1;
-	spec->init_verbs[0] = cxt5047_init_verbs;
-	spec->spdif_route = 0;
-	spec->num_channel_mode = ARRAY_SIZE(cxt5047_modes),
-	spec->channel_mode = cxt5047_modes,
-
-	codec->patch_ops = conexant_patch_ops;
-
-	switch (board_config) {
-	case CXT5047_LAPTOP:
-		spec->num_mixers = 2;
-		spec->mixers[1] = cxt5047_hp_spk_mixers;
-		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
-		break;
-	case CXT5047_LAPTOP_HP:
-		spec->num_mixers = 2;
-		spec->mixers[1] = cxt5047_hp_only_mixers;
-		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
-		codec->patch_ops.init = cxt5047_hp_init;
-		break;
-	case CXT5047_LAPTOP_EAPD:
-		spec->input_mux = &cxt5047_toshiba_capture_source;
-		spec->num_mixers = 2;
-		spec->mixers[1] = cxt5047_hp_spk_mixers;
-		spec->num_init_verbs = 2;
-		spec->init_verbs[1] = cxt5047_toshiba_init_verbs;
-		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
-		break;
-#ifdef CONFIG_SND_DEBUG
-	case CXT5047_TEST:
-		spec->input_mux = &cxt5047_test_capture_source;
-		spec->mixers[0] = cxt5047_test_mixer;
-		spec->init_verbs[0] = cxt5047_test_init_verbs;
-		codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
-#endif	
-	}
-	spec->vmaster_nid = 0x13;
-
-	switch (codec->subsystem_id >> 16) {
-	case 0x103c:
-		/* HP laptops have really bad sound over 0 dB on NID 0x10.
-		 * Fix max PCM level to 0 dB (originally it has 0x1e steps
-		 * with 0 dB offset 0x17)
-		 */
-		snd_hda_override_amp_caps(codec, 0x10, HDA_INPUT,
-					  (0x17 << AC_AMPCAP_OFFSET_SHIFT) |
-					  (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) |
-					  (0x05 << AC_AMPCAP_STEP_SIZE_SHIFT) |
-					  (1 << AC_AMPCAP_MUTE_SHIFT));
-		break;
-	}
-
-	return 0;
-}
-
-/* Conexant 5051 specific */
-static const hda_nid_t cxt5051_dac_nids[1] = { 0x10 };
-static const hda_nid_t cxt5051_adc_nids[2] = { 0x14, 0x15 };
-
-static const struct hda_channel_mode cxt5051_modes[1] = {
-	{ 2, NULL },
-};
-
-static void cxt5051_update_speaker(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int pinctl;
-	/* headphone pin */
-	pinctl = (spec->hp_present && spec->cur_eapd) ? PIN_HP : 0;
-	snd_hda_set_pin_ctl(codec, 0x16, pinctl);
-	/* speaker pin */
-	pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
-	snd_hda_set_pin_ctl(codec, 0x1a, pinctl);
-	/* on ideapad there is an additional speaker (subwoofer) to mute */
-	if (spec->ideapad)
-		snd_hda_set_pin_ctl(codec, 0x1b, pinctl);
-}
-
-/* turn on/off EAPD (+ mute HP) as a master switch */
-static int cxt5051_hp_master_sw_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-
-	if (!cxt_eapd_put(kcontrol, ucontrol))
-		return 0;
-	cxt5051_update_speaker(codec);
-	return 1;
-}
-
-/* toggle input of built-in and mic jack appropriately */
-static void cxt5051_portb_automic(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int present;
-
-	if (!(spec->auto_mic & AUTO_MIC_PORTB))
-		return;
-	present = snd_hda_jack_detect(codec, 0x17);
-	snd_hda_codec_write(codec, 0x14, 0,
-			    AC_VERB_SET_CONNECT_SEL,
-			    present ? 0x01 : 0x00);
-}
-
-/* switch the current ADC according to the jack state */
-static void cxt5051_portc_automic(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int present;
-	hda_nid_t new_adc;
-
-	if (!(spec->auto_mic & AUTO_MIC_PORTC))
-		return;
-	present = snd_hda_jack_detect(codec, 0x18);
-	if (present)
-		spec->cur_adc_idx = 1;
-	else
-		spec->cur_adc_idx = 0;
-	new_adc = spec->adc_nids[spec->cur_adc_idx];
-	if (spec->cur_adc && spec->cur_adc != new_adc) {
-		/* stream is running, let's swap the current ADC */
-		__snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
-		spec->cur_adc = new_adc;
-		snd_hda_codec_setup_stream(codec, new_adc,
-					   spec->cur_adc_stream_tag, 0,
-					   spec->cur_adc_format);
-	}
-}
-
-/* mute internal speaker if HP is plugged */
-static void cxt5051_hp_automute(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-
-	spec->hp_present = snd_hda_jack_detect(codec, 0x16);
-	cxt5051_update_speaker(codec);
-}
-
-/* unsolicited event for HP jack sensing */
-static void cxt5051_hp_unsol_event(struct hda_codec *codec,
-				   unsigned int res)
-{
-	switch (res >> 26) {
-	case CONEXANT_HP_EVENT:
-		cxt5051_hp_automute(codec);
-		break;
-	case CXT5051_PORTB_EVENT:
-		cxt5051_portb_automic(codec);
-		break;
-	case CXT5051_PORTC_EVENT:
-		cxt5051_portc_automic(codec);
-		break;
-	}
-}
-
-static const struct snd_kcontrol_new cxt5051_playback_mixers[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.info = cxt_eapd_info,
-		.get = cxt_eapd_get,
-		.put = cxt5051_hp_master_sw_put,
-		.private_value = 0x1a,
-	},
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5051_capture_mixers[] = {
-	HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT),
-	HDA_CODEC_VOLUME("Dock Mic Volume", 0x15, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Dock Mic Switch", 0x15, 0x00, HDA_INPUT),
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5051_hp_mixers[] = {
-	HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Volume", 0x15, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Switch", 0x15, 0x00, HDA_INPUT),
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5051_hp_dv6736_mixers[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x14, 0x00, HDA_INPUT),
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5051_f700_mixers[] = {
-	HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Capture Switch", 0x14, 0x01, HDA_INPUT),
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5051_toshiba_mixers[] = {
-	HDA_CODEC_VOLUME("Internal Mic Volume", 0x14, 0x00, HDA_INPUT),
-	HDA_CODEC_MUTE("Internal Mic Switch", 0x14, 0x00, HDA_INPUT),
-	HDA_CODEC_VOLUME("Mic Volume", 0x14, 0x01, HDA_INPUT),
-	HDA_CODEC_MUTE("Mic Switch", 0x14, 0x01, HDA_INPUT),
-	{}
-};
-
-static const struct hda_verb cxt5051_init_verbs[] = {
-	/* Line in, Mic */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-	{0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-	/* SPK  */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* HP, Amp  */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* DAC1 */	
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Record selector: Internal mic */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
-	/* SPDIF route: PCM */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* EAPD */
-	{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */ 
-	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
-	/* Line in, Mic */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
-	/* SPK  */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* HP, Amp  */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* DAC1 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Record selector: Internal mic */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x1},
-	/* SPDIF route: PCM */
-	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* EAPD */
-	{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5051_f700_init_verbs[] = {
-	/* Line in, Mic */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
-	{0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-	{0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0},
-	/* SPK  */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* HP, Amp  */
-	{0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
-	/* DAC1 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-	/* Record selector: Internal mic */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x1},
-	/* SPDIF route: PCM */
-	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
-	/* EAPD */
-	{0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-	{0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
-	{ } /* end */
-};
-
-static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid,
-				 unsigned int event)
-{
-	snd_hda_codec_write(codec, nid, 0,
-			    AC_VERB_SET_UNSOLICITED_ENABLE,
-			    AC_USRSP_EN | event);
-}
-
-static const struct hda_verb cxt5051_ideapad_init_verbs[] = {
-	/* Subwoofer */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-	{ } /* end */
-};
-
-/* initialize jack-sensing, too */
-static int cxt5051_init(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-
-	conexant_init(codec);
-
-	if (spec->auto_mic & AUTO_MIC_PORTB)
-		cxt5051_init_mic_port(codec, 0x17, CXT5051_PORTB_EVENT);
-	if (spec->auto_mic & AUTO_MIC_PORTC)
-		cxt5051_init_mic_port(codec, 0x18, CXT5051_PORTC_EVENT);
-
-	if (codec->patch_ops.unsol_event) {
-		cxt5051_hp_automute(codec);
-		cxt5051_portb_automic(codec);
-		cxt5051_portc_automic(codec);
-	}
-	return 0;
-}
-
-
-enum {
-	CXT5051_LAPTOP,	 /* Laptops w/ EAPD support */
-	CXT5051_HP,	/* no docking */
-	CXT5051_HP_DV6736,	/* HP without mic switch */
-	CXT5051_F700,       /* HP Compaq Presario F700 */
-	CXT5051_TOSHIBA,	/* Toshiba M300 & co */
-	CXT5051_IDEAPAD,	/* Lenovo IdeaPad Y430 */
-	CXT5051_AUTO,		/* auto-parser */
-	CXT5051_MODELS
-};
-
-static const char *const cxt5051_models[CXT5051_MODELS] = {
-	[CXT5051_LAPTOP]	= "laptop",
-	[CXT5051_HP]		= "hp",
-	[CXT5051_HP_DV6736]	= "hp-dv6736",
-	[CXT5051_F700]          = "hp-700",
-	[CXT5051_TOSHIBA]	= "toshiba",
-	[CXT5051_IDEAPAD]	= "ideapad",
-	[CXT5051_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk cxt5051_cfg_tbl[] = {
-	SND_PCI_QUIRK(0x103c, 0x30cf, "HP DV6736", CXT5051_HP_DV6736),
-	SND_PCI_QUIRK(0x103c, 0x360b, "Compaq Presario CQ60", CXT5051_HP),
-	SND_PCI_QUIRK(0x103c, 0x30ea, "Compaq Presario F700", CXT5051_F700),
-	SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba M30x", CXT5051_TOSHIBA),
-	SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
-		      CXT5051_LAPTOP),
-	SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
-	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo IdeaPad", CXT5051_IDEAPAD),
-	{}
-};
-
-static int patch_cxt5051(struct hda_codec *codec)
-{
-	struct conexant_spec *spec;
-	int board_config;
-
-	board_config = snd_hda_check_board_config(codec, CXT5051_MODELS,
-						  cxt5051_models,
-						  cxt5051_cfg_tbl);
-	if (board_config < 0)
-		board_config = CXT5051_AUTO; /* model=auto as default */
-	if (board_config == CXT5051_AUTO)
-		return patch_conexant_auto(codec);
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (!spec)
-		return -ENOMEM;
-	codec->spec = spec;
-	codec->pin_amp_workaround = 1;
-
-	codec->patch_ops = conexant_patch_ops;
-	codec->patch_ops.init = cxt5051_init;
-
-	spec->multiout.max_channels = 2;
-	spec->multiout.num_dacs = ARRAY_SIZE(cxt5051_dac_nids);
-	spec->multiout.dac_nids = cxt5051_dac_nids;
-	spec->multiout.dig_out_nid = CXT5051_SPDIF_OUT;
-	spec->num_adc_nids = 1; /* not 2; via auto-mic switch */
-	spec->adc_nids = cxt5051_adc_nids;
-	spec->num_mixers = 2;
-	spec->mixers[0] = cxt5051_capture_mixers;
-	spec->mixers[1] = cxt5051_playback_mixers;
-	spec->num_init_verbs = 1;
-	spec->init_verbs[0] = cxt5051_init_verbs;
-	spec->spdif_route = 0;
-	spec->num_channel_mode = ARRAY_SIZE(cxt5051_modes);
-	spec->channel_mode = cxt5051_modes;
-	spec->cur_adc = 0;
-	spec->cur_adc_idx = 0;
-
-	set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
-
-	codec->patch_ops.unsol_event = cxt5051_hp_unsol_event;
-
-	spec->auto_mic = AUTO_MIC_PORTB | AUTO_MIC_PORTC;
-	switch (board_config) {
-	case CXT5051_HP:
-		spec->mixers[0] = cxt5051_hp_mixers;
-		break;
-	case CXT5051_HP_DV6736:
-		spec->init_verbs[0] = cxt5051_hp_dv6736_init_verbs;
-		spec->mixers[0] = cxt5051_hp_dv6736_mixers;
-		spec->auto_mic = 0;
-		break;
-	case CXT5051_F700:
-		spec->init_verbs[0] = cxt5051_f700_init_verbs;
-		spec->mixers[0] = cxt5051_f700_mixers;
-		spec->auto_mic = 0;
-		break;
-	case CXT5051_TOSHIBA:
-		spec->mixers[0] = cxt5051_toshiba_mixers;
-		spec->auto_mic = AUTO_MIC_PORTB;
-		break;
-	case CXT5051_IDEAPAD:
-		spec->init_verbs[spec->num_init_verbs++] =
-			cxt5051_ideapad_init_verbs;
-		spec->ideapad = 1;
-		break;
-	}
-
-	if (spec->beep_amp)
-		snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
-
-	return 0;
-}
-
-/* Conexant 5066 specific */
-
-static const hda_nid_t cxt5066_dac_nids[1] = { 0x10 };
-static const hda_nid_t cxt5066_adc_nids[3] = { 0x14, 0x15, 0x16 };
-static const hda_nid_t cxt5066_capsrc_nids[1] = { 0x17 };
-static const hda_nid_t cxt5066_digout_pin_nids[2] = { 0x20, 0x22 };
-
-static const struct hda_channel_mode cxt5066_modes[1] = {
-	{ 2, NULL },
-};
-
-#define HP_PRESENT_PORT_A	(1 << 0)
-#define HP_PRESENT_PORT_D	(1 << 1)
-#define hp_port_a_present(spec)	((spec)->hp_present & HP_PRESENT_PORT_A)
-#define hp_port_d_present(spec)	((spec)->hp_present & HP_PRESENT_PORT_D)
-
-static void cxt5066_update_speaker(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int pinctl;
-
-	codec_dbg(codec,
-		  "CXT5066: update speaker, hp_present=%d, cur_eapd=%d\n",
-		    spec->hp_present, spec->cur_eapd);
-
-	/* Port A (HP) */
-	pinctl = (hp_port_a_present(spec) && spec->cur_eapd) ? PIN_HP : 0;
-	snd_hda_set_pin_ctl(codec, 0x19, pinctl);
-
-	/* Port D (HP/LO) */
-	pinctl = spec->cur_eapd ? spec->port_d_mode : 0;
-	if (spec->dell_automute || spec->thinkpad) {
-		/* Mute if Port A is connected */
-		if (hp_port_a_present(spec))
-			pinctl = 0;
-	} else {
-		/* Thinkpad/Dell doesn't give pin-D status */
-		if (!hp_port_d_present(spec))
-			pinctl = 0;
-	}
-	snd_hda_set_pin_ctl(codec, 0x1c, pinctl);
-
-	/* CLASS_D AMP */
-	pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
-	snd_hda_set_pin_ctl(codec, 0x1f, pinctl);
-}
-
-/* turn on/off EAPD (+ mute HP) as a master switch */
-static int cxt5066_hp_master_sw_put(struct snd_kcontrol *kcontrol,
-				    struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-
-	if (!cxt_eapd_put(kcontrol, ucontrol))
-		return 0;
-
-	cxt5066_update_speaker(codec);
-	return 1;
-}
-
-/* toggle input of built-in digital mic and mic jack appropriately */
-static void cxt5066_vostro_automic(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	struct hda_verb ext_mic_present[] = {
-		/* enable external mic, port B */
-		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-
-		/* switch to external mic input */
-		{0x17, AC_VERB_SET_CONNECT_SEL, 0},
-		{0x14, AC_VERB_SET_CONNECT_SEL, 0},
-
-		/* disable internal digital mic */
-		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{}
-	};
-	static const struct hda_verb ext_mic_absent[] = {
-		/* enable internal mic, port C */
-		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-		/* switch to internal mic input */
-		{0x14, AC_VERB_SET_CONNECT_SEL, 2},
-
-		/* disable external mic, port B */
-		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{}
-	};
-
-	present = snd_hda_jack_detect(codec, 0x1a);
-	if (present) {
-		codec_dbg(codec, "CXT5066: external microphone detected\n");
-		snd_hda_sequence_write(codec, ext_mic_present);
-	} else {
-		codec_dbg(codec, "CXT5066: external microphone absent\n");
-		snd_hda_sequence_write(codec, ext_mic_absent);
-	}
-}
-
-/* toggle input of built-in digital mic and mic jack appropriately */
-static void cxt5066_ideapad_automic(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	struct hda_verb ext_mic_present[] = {
-		{0x14, AC_VERB_SET_CONNECT_SEL, 0},
-		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{}
-	};
-	static const struct hda_verb ext_mic_absent[] = {
-		{0x14, AC_VERB_SET_CONNECT_SEL, 2},
-		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{}
-	};
-
-	present = snd_hda_jack_detect(codec, 0x1b);
-	if (present) {
-		codec_dbg(codec, "CXT5066: external microphone detected\n");
-		snd_hda_sequence_write(codec, ext_mic_present);
-	} else {
-		codec_dbg(codec, "CXT5066: external microphone absent\n");
-		snd_hda_sequence_write(codec, ext_mic_absent);
-	}
-}
-
-
-/* toggle input of built-in digital mic and mic jack appropriately */
-static void cxt5066_asus_automic(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x1b);
-	codec_dbg(codec, "CXT5066: external microphone present=%d\n", present);
-	snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL,
-			    present ? 1 : 0);
-}
-
-
-/* toggle input of built-in digital mic and mic jack appropriately */
-static void cxt5066_hp_laptop_automic(struct hda_codec *codec)
-{
-	unsigned int present;
-
-	present = snd_hda_jack_detect(codec, 0x1b);
-	codec_dbg(codec, "CXT5066: external microphone present=%d\n", present);
-	snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_CONNECT_SEL,
-			    present ? 1 : 3);
-}
-
-
-/* toggle input of built-in digital mic and mic jack appropriately
-   order is: external mic -> dock mic -> interal mic */
-static void cxt5066_thinkpad_automic(struct hda_codec *codec)
-{
-	unsigned int ext_present, dock_present;
-
-	static const struct hda_verb ext_mic_present[] = {
-		{0x14, AC_VERB_SET_CONNECT_SEL, 0},
-		{0x17, AC_VERB_SET_CONNECT_SEL, 1},
-		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{}
-	};
-	static const struct hda_verb dock_mic_present[] = {
-		{0x14, AC_VERB_SET_CONNECT_SEL, 0},
-		{0x17, AC_VERB_SET_CONNECT_SEL, 0},
-		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{}
-	};
-	static const struct hda_verb ext_mic_absent[] = {
-		{0x14, AC_VERB_SET_CONNECT_SEL, 2},
-		{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-		{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-		{}
-	};
-
-	ext_present = snd_hda_jack_detect(codec, 0x1b);
-	dock_present = snd_hda_jack_detect(codec, 0x1a);
-	if (ext_present) {
-		codec_dbg(codec, "CXT5066: external microphone detected\n");
-		snd_hda_sequence_write(codec, ext_mic_present);
-	} else if (dock_present) {
-		codec_dbg(codec, "CXT5066: dock microphone detected\n");
-		snd_hda_sequence_write(codec, dock_mic_present);
-	} else {
-		codec_dbg(codec, "CXT5066: external microphone absent\n");
-		snd_hda_sequence_write(codec, ext_mic_absent);
-	}
-}
-
-/* mute internal speaker if HP is plugged */
-static void cxt5066_hp_automute(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	unsigned int portA, portD;
-
-	/* Port A */
-	portA = snd_hda_jack_detect(codec, 0x19);
-
-	/* Port D */
-	portD = snd_hda_jack_detect(codec, 0x1c);
-
-	spec->hp_present = portA ? HP_PRESENT_PORT_A : 0;
-	spec->hp_present |= portD ? HP_PRESENT_PORT_D : 0;
-	codec_dbg(codec, "CXT5066: hp automute portA=%x portD=%x present=%d\n",
-		portA, portD, spec->hp_present);
-	cxt5066_update_speaker(codec);
-}
-
-/* Dispatch the right mic autoswitch function */
-static void cxt5066_automic(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
+struct conexant_spec {
+	struct hda_gen_spec gen;
 
 
-	if (spec->dell_vostro)
-		cxt5066_vostro_automic(codec);
-	else if (spec->ideapad)
-		cxt5066_ideapad_automic(codec);
-	else if (spec->thinkpad)
-		cxt5066_thinkpad_automic(codec);
-	else if (spec->hp_laptop)
-		cxt5066_hp_laptop_automic(codec);
-	else if (spec->asus)
-		cxt5066_asus_automic(codec);
-}
+	unsigned int beep_amp;
 
 
-/* unsolicited event for jack sensing */
-static void cxt5066_unsol_event(struct hda_codec *codec, unsigned int res)
-{
-	codec_dbg(codec, "CXT5066: unsol event %x (%x)\n", res, res >> 26);
-	switch (res >> 26) {
-	case CONEXANT_HP_EVENT:
-		cxt5066_hp_automute(codec);
-		break;
-	case CONEXANT_MIC_EVENT:
-		cxt5066_automic(codec);
-		break;
-	}
-}
+	/* extra EAPD pins */
+	unsigned int num_eapds;
+	hda_nid_t eapds[4];
+	bool dynamic_eapd;
 
 
+	unsigned int parse_flags; /* flag for snd_hda_parse_pin_defcfg() */
 
 
-static const struct hda_input_mux cxt5066_analog_mic_boost = {
-	.num_items = 5,
-	.items = {
-		{ "0dB",  0 },
-		{ "10dB", 1 },
-		{ "20dB", 2 },
-		{ "30dB", 3 },
-		{ "40dB", 4 },
-	},
+	/* OPLC XO specific */
+	bool recording;
+	bool dc_enable;
+	unsigned int dc_input_bias; /* offset into olpc_xo_dc_bias */
+	struct nid_path *dc_mode_path;
 };
 };
 
 
-static void cxt5066_set_mic_boost(struct hda_codec *codec)
-{
-	struct conexant_spec *spec = codec->spec;
-	snd_hda_codec_write_cache(codec, 0x17, 0,
-		AC_VERB_SET_AMP_GAIN_MUTE,
-		AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_OUTPUT |
-			cxt5066_analog_mic_boost.items[spec->mic_boost].index);
-	if (spec->ideapad || spec->thinkpad) {
-		/* adjust the internal mic as well...it is not through 0x17 */
-		snd_hda_codec_write_cache(codec, 0x23, 0,
-			AC_VERB_SET_AMP_GAIN_MUTE,
-			AC_AMP_SET_RIGHT | AC_AMP_SET_LEFT | AC_AMP_SET_INPUT |
-				cxt5066_analog_mic_boost.
-					items[spec->mic_boost].index);
-	}
-}
-
-static int cxt5066_mic_boost_mux_enum_info(struct snd_kcontrol *kcontrol,
-					   struct snd_ctl_elem_info *uinfo)
-{
-	return snd_hda_input_mux_info(&cxt5066_analog_mic_boost, uinfo);
-}
-
-static int cxt5066_mic_boost_mux_enum_get(struct snd_kcontrol *kcontrol,
-					  struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	ucontrol->value.enumerated.item[0] = spec->mic_boost;
-	return 0;
-}
-
-static int cxt5066_mic_boost_mux_enum_put(struct snd_kcontrol *kcontrol,
-					  struct snd_ctl_elem_value *ucontrol)
-{
-	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
-	struct conexant_spec *spec = codec->spec;
-	const struct hda_input_mux *imux = &cxt5066_analog_mic_boost;
-	unsigned int idx;
-	idx = ucontrol->value.enumerated.item[0];
-	if (idx >= imux->num_items)
-		idx = imux->num_items - 1;
-
-	spec->mic_boost = idx;
-	cxt5066_set_mic_boost(codec);
-	return 1;
-}
 
 
-static void conexant_check_dig_outs(struct hda_codec *codec,
-				    const hda_nid_t *dig_pins,
-				    int num_pins)
+#ifdef CONFIG_SND_HDA_INPUT_BEEP
+static inline void set_beep_amp(struct conexant_spec *spec, hda_nid_t nid,
+				int idx, int dir)
 {
 {
-	struct conexant_spec *spec = codec->spec;
-	hda_nid_t *nid_loc = &spec->multiout.dig_out_nid;
-	int i;
-
-	for (i = 0; i < num_pins; i++, dig_pins++) {
-		unsigned int cfg = snd_hda_codec_get_pincfg(codec, *dig_pins);
-		if (get_defcfg_connect(cfg) == AC_JACK_PORT_NONE)
-			continue;
-		if (snd_hda_get_connections(codec, *dig_pins, nid_loc, 1) != 1)
-			continue;
-	}
+	spec->gen.beep_nid = nid;
+	spec->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 1, idx, dir);
 }
 }
-
-static const struct hda_input_mux cxt5066_capture_source = {
-	.num_items = 4,
-	.items = {
-		{ "Mic B", 0 },
-		{ "Mic C", 1 },
-		{ "Mic E", 2 },
-		{ "Mic F", 3 },
-	},
-};
-
-static const struct hda_bind_ctls cxt5066_bind_capture_vol_others = {
-	.ops = &snd_hda_bind_vol,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
-		HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT),
-		0
-	},
-};
-
-static const struct hda_bind_ctls cxt5066_bind_capture_sw_others = {
-	.ops = &snd_hda_bind_sw,
-	.values = {
-		HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_INPUT),
-		HDA_COMPOSE_AMP_VAL(0x14, 3, 2, HDA_INPUT),
-		0
-	},
-};
-
-static const struct snd_kcontrol_new cxt5066_mixer_master[] = {
-	HDA_CODEC_VOLUME("Master Playback Volume", 0x10, 0x00, HDA_OUTPUT),
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5066_mixers[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Master Playback Switch",
-		.info = cxt_eapd_info,
-		.get = cxt_eapd_get,
-		.put = cxt5066_hp_master_sw_put,
-		.private_value = 0x1d,
-	},
-
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Analog Mic Boost Capture Enum",
-		.info = cxt5066_mic_boost_mux_enum_info,
-		.get = cxt5066_mic_boost_mux_enum_get,
-		.put = cxt5066_mic_boost_mux_enum_put,
-	},
-
-	HDA_BIND_VOL("Capture Volume", &cxt5066_bind_capture_vol_others),
-	HDA_BIND_SW("Capture Switch", &cxt5066_bind_capture_sw_others),
-	{}
-};
-
-static const struct snd_kcontrol_new cxt5066_vostro_mixers[] = {
-	{
-		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-		.name = "Internal Mic Boost Capture Enum",
-		.info = cxt5066_mic_boost_mux_enum_info,
-		.get = cxt5066_mic_boost_mux_enum_get,
-		.put = cxt5066_mic_boost_mux_enum_put,
-		.private_value = 0x23 | 0x100,
-	},
-	{}
-};
-
-static const struct hda_verb cxt5066_init_verbs[] = {
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
-	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
-
-	/* Speakers  */
-	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* HP, Amp  */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* DAC1 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
-	/* no digital microphone support yet */
-	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* Audio input selector */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
-
-	/* SPDIF route: PCM */
-	{0x20, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x22, AC_VERB_SET_CONNECT_SEL, 0x0},
-
-	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* EAPD */
-	{0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-
-	/* not handling these yet */
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{0x1d, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{0x1e, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{0x20, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{0x22, AC_VERB_SET_UNSOLICITED_ENABLE, 0},
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5066_init_verbs_vostro[] = {
-	/* Port A: headphones */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* Port B: external microphone */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* Port C: unused */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* Port D: unused */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* Port E: unused, but has primary EAPD */
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-
-	/* Port F: unused */
-	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* Port G: internal speakers */
-	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* DAC1 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* DAC2: unused */
-	{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
-	{0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-
-	/* Digital microphone port */
-	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
-	/* Audio input selectors */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x3},
-	{0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-
-	/* Disable SPDIF */
-	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* enable unsolicited events for Port A and B */
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5066_init_verbs_ideapad[] = {
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port B */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, /* Port C */
-	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
-
-	/* Speakers  */
-	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* HP, Amp  */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* DAC1 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 2},	/* default to internal mic */
-
-	/* Audio input selector */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2},
-	{0x17, AC_VERB_SET_CONNECT_SEL, 1},	/* route ext mic */
-
-	/* SPDIF route: PCM */
-	{0x20, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x22, AC_VERB_SET_CONNECT_SEL, 0x0},
-
-	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* internal microphone */
-	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */
-
-	/* EAPD */
-	{0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5066_init_verbs_thinkpad[] = {
-	{0x1e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port F */
-	{0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Port E */
-
-	/* Port G: internal speakers  */
-	{0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x1f, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* Port A: HP, Amp  */
-	{0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x19, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* Port B: Mic Dock */
-	{0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* Port C: Mic */
-	{0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-
-	/* Port D: HP Dock, Amp */
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
-	{0x1c, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC1 */
-
-	/* DAC1 */
-	{0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
-	/* Node 14 connections: 0x17 0x18 0x23 0x24 0x27 */
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x50},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2) | 0x50},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
-	{0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-	{0x14, AC_VERB_SET_CONNECT_SEL, 2},	/* default to internal mic */
-
-	/* Audio input selector */
-	{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x2},
-	{0x17, AC_VERB_SET_CONNECT_SEL, 1},	/* route ext mic */
-
-	/* SPDIF route: PCM */
-	{0x20, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x22, AC_VERB_SET_CONNECT_SEL, 0x0},
-
-	{0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{0x22, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-	/* internal microphone */
-	{0x23, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* enable internal mic */
-
-	/* EAPD */
-	{0x1d, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
-
-	/* enable unsolicited events for Port A, B, C and D */
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{0x1c, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
-	{ } /* end */
-};
-
-static const struct hda_verb cxt5066_init_verbs_portd_lo[] = {
-	{0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-	{ } /* end */
-};
-
-
-static const struct hda_verb cxt5066_init_verbs_hp_laptop[] = {
-	{0x14, AC_VERB_SET_CONNECT_SEL, 0x0},
-	{0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
-	{0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
+/* additional beep mixers; the actual parameters are overwritten at build */
+static const struct snd_kcontrol_new cxt_beep_mixer[] = {
+	HDA_CODEC_VOLUME_MONO("Beep Playback Volume", 0, 1, 0, HDA_OUTPUT),
+	HDA_CODEC_MUTE_BEEP_MONO("Beep Playback Switch", 0, 1, 0, HDA_OUTPUT),
 	{ } /* end */
 	{ } /* end */
 };
 };
 
 
-/* initialize jack-sensing, too */
-static int cxt5066_init(struct hda_codec *codec)
-{
-	codec_dbg(codec, "CXT5066: init\n");
-	conexant_init(codec);
-	if (codec->patch_ops.unsol_event) {
-		cxt5066_hp_automute(codec);
-		cxt5066_automic(codec);
-	}
-	cxt5066_set_mic_boost(codec);
-	return 0;
-}
-
-enum {
-	CXT5066_LAPTOP,		/* Laptops w/ EAPD support */
-	CXT5066_DELL_LAPTOP,	/* Dell Laptop */
-	CXT5066_DELL_VOSTRO,	/* Dell Vostro 1015i */
-	CXT5066_IDEAPAD,	/* Lenovo IdeaPad U150 */
-	CXT5066_THINKPAD,	/* Lenovo ThinkPad T410s, others? */
-	CXT5066_ASUS,		/* Asus K52JU, Lenovo G560 - Int mic at 0x1a and Ext mic at 0x1b */
-	CXT5066_HP_LAPTOP,      /* HP Laptop */
-	CXT5066_AUTO,		/* BIOS auto-parser */
-	CXT5066_MODELS
-};
-
-static const char * const cxt5066_models[CXT5066_MODELS] = {
-	[CXT5066_LAPTOP]	= "laptop",
-	[CXT5066_DELL_LAPTOP]	= "dell-laptop",
-	[CXT5066_DELL_VOSTRO]	= "dell-vostro",
-	[CXT5066_IDEAPAD]	= "ideapad",
-	[CXT5066_THINKPAD]	= "thinkpad",
-	[CXT5066_ASUS]		= "asus",
-	[CXT5066_HP_LAPTOP]	= "hp-laptop",
-	[CXT5066_AUTO]		= "auto",
-};
-
-static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
-	SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD),
-	SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO),
-	SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD),
-	SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO),
-	SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD),
-	SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD),
-	SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP),
-	SND_PCI_QUIRK(0x1043, 0x13f3, "Asus A52J", CXT5066_ASUS),
-	SND_PCI_QUIRK(0x1043, 0x1643, "Asus K52JU", CXT5066_ASUS),
-	SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS),
-	SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD),
-	SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
-		      CXT5066_LAPTOP),
-	SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
-	SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
-	SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
-	SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),
-	SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
-	{}
-};
-
-static int patch_cxt5066(struct hda_codec *codec)
+/* create beep controls if needed */
+static int add_beep_ctls(struct hda_codec *codec)
 {
 {
-	struct conexant_spec *spec;
-	int board_config;
-
-	board_config = snd_hda_check_board_config(codec, CXT5066_MODELS,
-						  cxt5066_models, cxt5066_cfg_tbl);
-	if (board_config < 0)
-		board_config = CXT5066_AUTO; /* model=auto as default */
-	if (board_config == CXT5066_AUTO)
-		return patch_conexant_auto(codec);
-
-	spec = kzalloc(sizeof(*spec), GFP_KERNEL);
-	if (!spec)
-		return -ENOMEM;
-	codec->spec = spec;
-
-	codec->patch_ops = conexant_patch_ops;
-	codec->patch_ops.init = conexant_init;
-
-	spec->dell_automute = 0;
-	spec->multiout.max_channels = 2;
-	spec->multiout.num_dacs = ARRAY_SIZE(cxt5066_dac_nids);
-	spec->multiout.dac_nids = cxt5066_dac_nids;
-	conexant_check_dig_outs(codec, cxt5066_digout_pin_nids,
-	    ARRAY_SIZE(cxt5066_digout_pin_nids));
-	spec->num_adc_nids = 1;
-	spec->adc_nids = cxt5066_adc_nids;
-	spec->capsrc_nids = cxt5066_capsrc_nids;
-	spec->input_mux = &cxt5066_capture_source;
-
-	spec->port_d_mode = PIN_HP;
-
-	spec->num_init_verbs = 1;
-	spec->init_verbs[0] = cxt5066_init_verbs;
-	spec->num_channel_mode = ARRAY_SIZE(cxt5066_modes);
-	spec->channel_mode = cxt5066_modes;
-	spec->cur_adc = 0;
-	spec->cur_adc_idx = 0;
-
-	set_beep_amp(spec, 0x13, 0, HDA_OUTPUT);
-
-	switch (board_config) {
-	default:
-	case CXT5066_LAPTOP:
-		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
-		break;
-	case CXT5066_DELL_LAPTOP:
-		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
-
-		spec->port_d_mode = PIN_OUT;
-		spec->init_verbs[spec->num_init_verbs] = cxt5066_init_verbs_portd_lo;
-		spec->num_init_verbs++;
-		spec->dell_automute = 1;
-		break;
-	case CXT5066_ASUS:
-	case CXT5066_HP_LAPTOP:
-		codec->patch_ops.init = cxt5066_init;
-		codec->patch_ops.unsol_event = cxt5066_unsol_event;
-		spec->init_verbs[spec->num_init_verbs] =
-			cxt5066_init_verbs_hp_laptop;
-		spec->num_init_verbs++;
-		spec->hp_laptop = board_config == CXT5066_HP_LAPTOP;
-		spec->asus = board_config == CXT5066_ASUS;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
-		/* no S/PDIF out */
-		if (board_config == CXT5066_HP_LAPTOP)
-			spec->multiout.dig_out_nid = 0;
-		/* input source automatically selected */
-		spec->input_mux = NULL;
-		spec->port_d_mode = 0;
-		spec->mic_boost = 3; /* default 30dB gain */
-		break;
+	struct conexant_spec *spec = codec->spec;
+	int err;
 
 
-	case CXT5066_DELL_VOSTRO:
-		codec->patch_ops.init = cxt5066_init;
-		codec->patch_ops.unsol_event = cxt5066_unsol_event;
-		spec->init_verbs[0] = cxt5066_init_verbs_vostro;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
-		spec->mixers[spec->num_mixers++] = cxt5066_vostro_mixers;
-		spec->port_d_mode = 0;
-		spec->dell_vostro = 1;
-		spec->mic_boost = 3; /* default 30dB gain */
-
-		/* no S/PDIF out */
-		spec->multiout.dig_out_nid = 0;
-
-		/* input source automatically selected */
-		spec->input_mux = NULL;
-		break;
-	case CXT5066_IDEAPAD:
-		codec->patch_ops.init = cxt5066_init;
-		codec->patch_ops.unsol_event = cxt5066_unsol_event;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
-		spec->init_verbs[0] = cxt5066_init_verbs_ideapad;
-		spec->port_d_mode = 0;
-		spec->ideapad = 1;
-		spec->mic_boost = 2;	/* default 20dB gain */
-
-		/* no S/PDIF out */
-		spec->multiout.dig_out_nid = 0;
-
-		/* input source automatically selected */
-		spec->input_mux = NULL;
-		break;
-	case CXT5066_THINKPAD:
-		codec->patch_ops.init = cxt5066_init;
-		codec->patch_ops.unsol_event = cxt5066_unsol_event;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixer_master;
-		spec->mixers[spec->num_mixers++] = cxt5066_mixers;
-		spec->init_verbs[0] = cxt5066_init_verbs_thinkpad;
-		spec->thinkpad = 1;
-		spec->port_d_mode = PIN_OUT;
-		spec->mic_boost = 2;	/* default 20dB gain */
-
-		/* no S/PDIF out */
-		spec->multiout.dig_out_nid = 0;
-
-		/* input source automatically selected */
-		spec->input_mux = NULL;
-		break;
+	if (spec->beep_amp) {
+		const struct snd_kcontrol_new *knew;
+		for (knew = cxt_beep_mixer; knew->name; knew++) {
+			struct snd_kcontrol *kctl;
+			kctl = snd_ctl_new1(knew, codec);
+			if (!kctl)
+				return -ENOMEM;
+			kctl->private_value = spec->beep_amp;
+			err = snd_hda_ctl_add(codec, 0, kctl);
+			if (err < 0)
+				return err;
+		}
 	}
 	}
-
-	if (spec->beep_amp)
-		snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
-
 	return 0;
 	return 0;
 }
 }
-
-#endif /* ENABLE_CXT_STATIC_QUIRKS */
-
+#else
+#define set_beep_amp(spec, nid, idx, dir) /* NOP */
+#define add_beep_ctls(codec)	0
+#endif
 
 
 /*
 /*
  * Automatic parser for CX20641 & co
  * Automatic parser for CX20641 & co
@@ -3487,35 +881,28 @@ static int patch_conexant_auto(struct hda_codec *codec)
 	return err;
 	return err;
 }
 }
 
 
-#ifndef ENABLE_CXT_STATIC_QUIRKS
-#define patch_cxt5045	patch_conexant_auto
-#define patch_cxt5047	patch_conexant_auto
-#define patch_cxt5051	patch_conexant_auto
-#define patch_cxt5066	patch_conexant_auto
-#endif
-
 /*
 /*
  */
  */
 
 
 static const struct hda_codec_preset snd_hda_preset_conexant[] = {
 static const struct hda_codec_preset snd_hda_preset_conexant[] = {
 	{ .id = 0x14f15045, .name = "CX20549 (Venice)",
 	{ .id = 0x14f15045, .name = "CX20549 (Venice)",
-	  .patch = patch_cxt5045 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15047, .name = "CX20551 (Waikiki)",
 	{ .id = 0x14f15047, .name = "CX20551 (Waikiki)",
-	  .patch = patch_cxt5047 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15051, .name = "CX20561 (Hermosa)",
 	{ .id = 0x14f15051, .name = "CX20561 (Hermosa)",
-	  .patch = patch_cxt5051 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15066, .name = "CX20582 (Pebble)",
 	{ .id = 0x14f15066, .name = "CX20582 (Pebble)",
-	  .patch = patch_cxt5066 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15067, .name = "CX20583 (Pebble HSF)",
 	{ .id = 0x14f15067, .name = "CX20583 (Pebble HSF)",
-	  .patch = patch_cxt5066 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15068, .name = "CX20584",
 	{ .id = 0x14f15068, .name = "CX20584",
-	  .patch = patch_cxt5066 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15069, .name = "CX20585",
 	{ .id = 0x14f15069, .name = "CX20585",
-	  .patch = patch_cxt5066 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f1506c, .name = "CX20588",
 	{ .id = 0x14f1506c, .name = "CX20588",
-	  .patch = patch_cxt5066 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f1506e, .name = "CX20590",
 	{ .id = 0x14f1506e, .name = "CX20590",
-	  .patch = patch_cxt5066 },
+	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15097, .name = "CX20631",
 	{ .id = 0x14f15097, .name = "CX20631",
 	  .patch = patch_conexant_auto },
 	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15098, .name = "CX20632",
 	{ .id = 0x14f15098, .name = "CX20632",

+ 8 - 5
sound/pci/hda/patch_hdmi.c

@@ -648,7 +648,8 @@ static int get_channel_allocation_order(int ca)
  *
  *
  * TODO: it could select the wrong CA from multiple candidates.
  * TODO: it could select the wrong CA from multiple candidates.
 */
 */
-static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels)
+static int hdmi_channel_allocation(struct hda_codec *codec,
+				   struct hdmi_eld *eld, int channels)
 {
 {
 	int i;
 	int i;
 	int ca = 0;
 	int ca = 0;
@@ -694,7 +695,7 @@ static int hdmi_channel_allocation(struct hdmi_eld *eld, int channels)
 	}
 	}
 
 
 	snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf));
 	snd_print_channel_allocation(eld->info.spk_alloc, buf, sizeof(buf));
-	snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n",
+	codec_dbg(codec, "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
 		    ca, channels, buf);
 		    ca, channels, buf);
 
 
 	return ca;
 	return ca;
@@ -1131,7 +1132,7 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
 	if (!non_pcm && per_pin->chmap_set)
 	if (!non_pcm && per_pin->chmap_set)
 		ca = hdmi_manual_channel_allocation(channels, per_pin->chmap);
 		ca = hdmi_manual_channel_allocation(channels, per_pin->chmap);
 	else
 	else
-		ca = hdmi_channel_allocation(eld, channels);
+		ca = hdmi_channel_allocation(codec, eld, channels);
 	if (ca < 0)
 	if (ca < 0)
 		ca = 0;
 		ca = 0;
 
 
@@ -1557,13 +1558,13 @@ static bool hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
 			eld->eld_valid = false;
 			eld->eld_valid = false;
 		else {
 		else {
 			memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld));
 			memset(&eld->info, 0, sizeof(struct parsed_hdmi_eld));
-			if (snd_hdmi_parse_eld(&eld->info, eld->eld_buffer,
+			if (snd_hdmi_parse_eld(codec, &eld->info, eld->eld_buffer,
 						    eld->eld_size) < 0)
 						    eld->eld_size) < 0)
 				eld->eld_valid = false;
 				eld->eld_valid = false;
 		}
 		}
 
 
 		if (eld->eld_valid) {
 		if (eld->eld_valid) {
-			snd_hdmi_show_eld(&eld->info);
+			snd_hdmi_show_eld(codec, &eld->info);
 			update_eld = true;
 			update_eld = true;
 		}
 		}
 		else if (repoll) {
 		else if (repoll) {
@@ -3355,6 +3356,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
 { .id = 0x80862808, .name = "Broadwell HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x80862808, .name = "Broadwell HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x80862880, .name = "CedarTrail HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x80862880, .name = "CedarTrail HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x80862882, .name = "Valleyview2 HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x80862882, .name = "Valleyview2 HDMI",	.patch = patch_generic_hdmi },
+{ .id = 0x80862883, .name = "Braswell HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x808629fb, .name = "Crestline HDMI",	.patch = patch_generic_hdmi },
 { .id = 0x808629fb, .name = "Crestline HDMI",	.patch = patch_generic_hdmi },
 {} /* terminator */
 {} /* terminator */
 };
 };
@@ -3414,6 +3416,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862807");
 MODULE_ALIAS("snd-hda-codec-id:80862808");
 MODULE_ALIAS("snd-hda-codec-id:80862808");
 MODULE_ALIAS("snd-hda-codec-id:80862880");
 MODULE_ALIAS("snd-hda-codec-id:80862880");
 MODULE_ALIAS("snd-hda-codec-id:80862882");
 MODULE_ALIAS("snd-hda-codec-id:80862882");
+MODULE_ALIAS("snd-hda-codec-id:80862883");
 MODULE_ALIAS("snd-hda-codec-id:808629fb");
 MODULE_ALIAS("snd-hda-codec-id:808629fb");
 
 
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");

+ 165 - 5
sound/pci/hda/patch_realtek.c

@@ -101,6 +101,7 @@ struct alc_spec {
 	/* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */
 	/* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */
 	int mute_led_polarity;
 	int mute_led_polarity;
 	hda_nid_t mute_led_nid;
 	hda_nid_t mute_led_nid;
+	hda_nid_t cap_mute_led_nid;
 
 
 	unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */
 	unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */
 
 
@@ -3402,7 +3403,8 @@ static unsigned int led_power_filter(struct hda_codec *codec,
 {
 {
 	struct alc_spec *spec = codec->spec;
 	struct alc_spec *spec = codec->spec;
 
 
-	if (power_state != AC_PWRST_D3 || nid != spec->mute_led_nid)
+	if (power_state != AC_PWRST_D3 || nid == 0 ||
+	    (nid != spec->mute_led_nid && nid != spec->cap_mute_led_nid))
 		return power_state;
 		return power_state;
 
 
 	/* Set pin ctl again, it might have just been set to 0 */
 	/* Set pin ctl again, it might have just been set to 0 */
@@ -3520,6 +3522,68 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
 	}
 	}
 }
 }
 
 
+/* turn on/off mic-mute LED per capture hook */
+static void alc269_fixup_hp_cap_mic_mute_hook(struct hda_codec *codec,
+					       struct snd_kcontrol *kcontrol,
+					       struct snd_ctl_elem_value *ucontrol)
+{
+	struct alc_spec *spec = codec->spec;
+	unsigned int pinval, enable, disable;
+
+	pinval = snd_hda_codec_get_pin_target(codec, spec->cap_mute_led_nid);
+	pinval &= ~AC_PINCTL_VREFEN;
+	enable  = pinval | AC_PINCTL_VREF_80;
+	disable = pinval | AC_PINCTL_VREF_HIZ;
+
+	if (!ucontrol)
+		return;
+
+	if (ucontrol->value.integer.value[0] ||
+	    ucontrol->value.integer.value[1])
+		pinval = disable;
+	else
+		pinval = enable;
+
+	if (spec->cap_mute_led_nid)
+		snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval);
+}
+
+static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec,
+				const struct hda_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+	static const struct hda_verb gpio_init[] = {
+		{ 0x01, AC_VERB_SET_GPIO_MASK, 0x08 },
+		{ 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x08 },
+		{}
+	};
+
+	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+		spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook;
+		spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
+		spec->gpio_led = 0;
+		spec->cap_mute_led_nid = 0x18;
+		snd_hda_add_verbs(codec, gpio_init);
+		codec->power_filter = led_power_filter;
+	}
+}
+
+static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
+				const struct hda_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+
+	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+		spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
+		spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
+		spec->mute_led_polarity = 0;
+		spec->mute_led_nid = 0x1a;
+		spec->cap_mute_led_nid = 0x18;
+		spec->gen.vmaster_mute_enum = 1;
+		codec->power_filter = led_power_filter;
+	}
+}
+
 static void alc_headset_mode_unplugged(struct hda_codec *codec)
 static void alc_headset_mode_unplugged(struct hda_codec *codec)
 {
 {
 	int val;
 	int val;
@@ -4231,6 +4295,9 @@ static void alc290_fixup_mono_speakers(struct hda_codec *codec,
 /* for hda_fixup_thinkpad_acpi() */
 /* for hda_fixup_thinkpad_acpi() */
 #include "thinkpad_helper.c"
 #include "thinkpad_helper.c"
 
 
+/* for dell wmi mic mute led */
+#include "dell_wmi_helper.c"
+
 enum {
 enum {
 	ALC269_FIXUP_SONY_VAIO,
 	ALC269_FIXUP_SONY_VAIO,
 	ALC275_FIXUP_SONY_VAIO_GPIO2,
 	ALC275_FIXUP_SONY_VAIO_GPIO2,
@@ -4255,6 +4322,8 @@ enum {
 	ALC269_FIXUP_HP_MUTE_LED_MIC1,
 	ALC269_FIXUP_HP_MUTE_LED_MIC1,
 	ALC269_FIXUP_HP_MUTE_LED_MIC2,
 	ALC269_FIXUP_HP_MUTE_LED_MIC2,
 	ALC269_FIXUP_HP_GPIO_LED,
 	ALC269_FIXUP_HP_GPIO_LED,
+	ALC269_FIXUP_HP_GPIO_MIC1_LED,
+	ALC269_FIXUP_HP_LINE1_MIC1_LED,
 	ALC269_FIXUP_INV_DMIC,
 	ALC269_FIXUP_INV_DMIC,
 	ALC269_FIXUP_LENOVO_DOCK,
 	ALC269_FIXUP_LENOVO_DOCK,
 	ALC269_FIXUP_NO_SHUTUP,
 	ALC269_FIXUP_NO_SHUTUP,
@@ -4292,6 +4361,8 @@ enum {
 	ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
 	ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
 	ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
 	ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
 	ALC292_FIXUP_TPT440_DOCK,
 	ALC292_FIXUP_TPT440_DOCK,
+	ALC283_FIXUP_BXBT2807_MIC,
+	ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
 };
 };
 
 
 static const struct hda_fixup alc269_fixups[] = {
 static const struct hda_fixup alc269_fixups[] = {
@@ -4447,6 +4518,14 @@ static const struct hda_fixup alc269_fixups[] = {
 		.type = HDA_FIXUP_FUNC,
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc269_fixup_hp_gpio_led,
 		.v.func = alc269_fixup_hp_gpio_led,
 	},
 	},
+	[ALC269_FIXUP_HP_GPIO_MIC1_LED] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc269_fixup_hp_gpio_mic1_led,
+	},
+	[ALC269_FIXUP_HP_LINE1_MIC1_LED] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc269_fixup_hp_line1_mic1_led,
+	},
 	[ALC269_FIXUP_INV_DMIC] = {
 	[ALC269_FIXUP_INV_DMIC] = {
 		.type = HDA_FIXUP_FUNC,
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc_fixup_inv_dmic_0x12,
 		.v.func = alc_fixup_inv_dmic_0x12,
@@ -4718,6 +4797,20 @@ static const struct hda_fixup alc269_fixups[] = {
 		.chained = true,
 		.chained = true,
 		.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
 		.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
 	},
 	},
+	[ALC283_FIXUP_BXBT2807_MIC] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x19, 0x04a110f0 },
+			{ },
+		},
+	},
+	[ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc_fixup_dell_wmi,
+		.chained_before = true,
+		.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
+	},
+
 };
 };
 
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -4727,7 +4820,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
 	SND_PCI_QUIRK(0x1025, 0x047c, "Acer AC700", ALC269_FIXUP_ACER_AC700),
 	SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
 	SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
 	SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
 	SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
-	SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
 	SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
 	SND_PCI_QUIRK(0x1025, 0x0775, "Acer Aspire E1-572", ALC271_FIXUP_HP_GATE_MIC_JACK_E1_572),
 	SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
 	SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
 	SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x05bd, "Dell", ALC269_FIXUP_DELL2_MIC_NO_PRESENCE),
@@ -4761,10 +4853,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+	SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
 	SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
 	SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
 	SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
 	SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
+	SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
 	SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
 	SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
 	SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
@@ -4782,6 +4876,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x1983, "HP Pavilion", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
 	SND_PCI_QUIRK(0x103c, 0x218b, "HP", ALC269_FIXUP_LIMIT_INT_MIC_BOOST_MUTE_LED),
 	/* ALC282 */
 	/* ALC282 */
+	SND_PCI_QUIRK(0x103c, 0x21f8, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x21f9, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x220d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x220d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x220e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x220e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x220f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -4790,6 +4886,20 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x2212, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2212, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2213, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2214, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2234, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2235, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2236, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2237, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2238, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2239, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x224a, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x224b, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x224c, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x224d, "HP", ALC269_FIXUP_HP_LINE1_MIC1_LED),
 	SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2266, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2267, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2268, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -4814,13 +4924,43 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x22ce, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x22cf, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x22d0, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x22da, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x22db, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x22dc, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x22fb, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x8004, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
 	/* ALC290 */
 	/* ALC290 */
+	SND_PCI_QUIRK(0x103c, 0x221b, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x221c, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x221d, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2220, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2221, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2222, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2223, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2224, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2225, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2246, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2247, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2248, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2249, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2253, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2254, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2255, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2256, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2257, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2258, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2259, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x225a, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
 	SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2260, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2261, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2262, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2263, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2264, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2265, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
+	SND_PCI_QUIRK(0x103c, 0x2272, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2273, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2277, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
+	SND_PCI_QUIRK(0x103c, 0x2278, "HP", ALC269_FIXUP_HP_GPIO_MIC1_LED),
 	SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x227d, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x227e, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x227f, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
@@ -4843,7 +4983,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2335, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2336, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
 	SND_PCI_QUIRK(0x103c, 0x2337, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC1),
-	SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
 	SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
 	SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
 	SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
 	SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
 	SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
 	SND_PCI_QUIRK(0x1043, 0x115d, "Asus 1015E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -4864,9 +5003,9 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
 	SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
 	SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
 	SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
 	SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX),
 	SND_PCI_QUIRK(0x104d, 0x9099, "Sony VAIO S13", ALC275_FIXUP_SONY_DISABLE_AAMIX),
-	SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
 	SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
 	SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
 	SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
 	SND_PCI_QUIRK(0x10cf, 0x1845, "Lifebook U904", ALC269_FIXUP_LIFEBOOK_EXTMIC),
+	SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_BXBT2807_MIC),
 	SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
 	SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
@@ -4891,7 +5030,6 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
 	SND_PCI_QUIRK(0x17aa, 0x5109, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
 	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
 	SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
 	SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
 	SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
-	SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI),
 	SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
 	SND_PCI_QUIRK(0x1b7d, 0xa831, "Ordissimo EVE2 ", ALC269VB_FIXUP_ORDISSIMO_EVE2), /* Also known as Malata PC-B1303 */
 
 
 #if 0
 #if 0
@@ -4945,6 +5083,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	{}
 	{}
 };
 };
 
 
+static const struct snd_pci_quirk alc269_fixup_vendor_tbl[] = {
+	SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
+	SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
+	SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
+	SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI),
+	{}
+};
+
 static const struct hda_model_fixup alc269_fixup_models[] = {
 static const struct hda_model_fixup alc269_fixup_models[] = {
 	{.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"},
 	{.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"},
 	{.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"},
 	{.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"},
@@ -5040,6 +5186,17 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
 		{0x1d, 0x40700001},
 		{0x1d, 0x40700001},
 		{0x1e, 0x411111f0},
 		{0x1e, 0x411111f0},
 		{0x21, 0x02211040}),
 		{0x21, 0x02211040}),
+	SND_HDA_PIN_QUIRK(0x10ec0282, 0x103c, "HP 15 Touchsmart", ALC269_FIXUP_HP_MUTE_LED_MIC1,
+		{0x12, 0x99a30130},
+		{0x14, 0x90170110},
+		{0x17, 0x40000000},
+		{0x18, 0x411111f0},
+		{0x19, 0x03a11020},
+		{0x1a, 0x411111f0},
+		{0x1b, 0x411111f0},
+		{0x1d, 0x40f41905},
+		{0x1e, 0x411111f0},
+		{0x21, 0x0321101f}),
 	SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
 	SND_HDA_PIN_QUIRK(0x10ec0283, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
 		{0x12, 0x90a60130},
 		{0x12, 0x90a60130},
 		{0x14, 0x90170110},
 		{0x14, 0x90170110},
@@ -5162,6 +5319,8 @@ static int patch_alc269(struct hda_codec *codec)
 	snd_hda_pick_fixup(codec, alc269_fixup_models,
 	snd_hda_pick_fixup(codec, alc269_fixup_models,
 		       alc269_fixup_tbl, alc269_fixups);
 		       alc269_fixup_tbl, alc269_fixups);
 	snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups);
 	snd_hda_pick_pin_fixup(codec, alc269_pin_fixup_tbl, alc269_fixups);
+	snd_hda_pick_fixup(codec, NULL,	alc269_fixup_vendor_tbl,
+			   alc269_fixups);
 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
 
 	alc_auto_parse_customize_define(codec);
 	alc_auto_parse_customize_define(codec);
@@ -5858,6 +6017,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
 	SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
 	SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x05d8, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x05db, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
+	SND_PCI_QUIRK(0x1028, 0x05fe, "Dell XPS 15", ALC668_FIXUP_DELL_XPS13),
 	SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13),
 	SND_PCI_QUIRK(0x1028, 0x060a, "Dell XPS 13", ALC668_FIXUP_DELL_XPS13),
 	SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0625, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0626, "Dell", ALC668_FIXUP_DELL_MIC_NO_PRESENCE),

+ 27 - 2
sound/pci/hda/patch_sigmatel.c

@@ -84,6 +84,7 @@ enum {
 	STAC_DELL_EQ,
 	STAC_DELL_EQ,
 	STAC_ALIENWARE_M17X,
 	STAC_ALIENWARE_M17X,
 	STAC_92HD89XX_HP_FRONT_JACK,
 	STAC_92HD89XX_HP_FRONT_JACK,
+	STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK,
 	STAC_92HD73XX_MODELS
 	STAC_92HD73XX_MODELS
 };
 };
 
 
@@ -103,6 +104,7 @@ enum {
 	STAC_92HD83XXX_HP,
 	STAC_92HD83XXX_HP,
 	STAC_HP_ENVY_BASS,
 	STAC_HP_ENVY_BASS,
 	STAC_HP_BNB13_EQ,
 	STAC_HP_BNB13_EQ,
+	STAC_HP_ENVY_TS_BASS,
 	STAC_92HD83XXX_MODELS
 	STAC_92HD83XXX_MODELS
 };
 };
 
 
@@ -1017,7 +1019,7 @@ static int stac_create_spdif_mux_ctls(struct hda_codec *codec)
 	for (i = 0; i < num_cons; i++) {
 	for (i = 0; i < num_cons; i++) {
 		if (snd_BUG_ON(!labels[i]))
 		if (snd_BUG_ON(!labels[i]))
 			return -EINVAL;
 			return -EINVAL;
-		snd_hda_add_imux_item(&spec->spdif_mux, labels[i], i, NULL);
+		snd_hda_add_imux_item(codec, &spec->spdif_mux, labels[i], i, NULL);
 	}
 	}
 
 
 	kctl = snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_smux_mixer);
 	kctl = snd_hda_gen_add_kctl(&spec->gen, NULL, &stac_smux_mixer);
@@ -1809,6 +1811,11 @@ static const struct hda_pintbl stac92hd89xx_hp_front_jack_pin_configs[] = {
 	{}
 	{}
 };
 };
 
 
+static const struct hda_pintbl stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs[] = {
+	{ 0x0e, 0x400000f0 },
+	{}
+};
+
 static void stac92hd73xx_fixup_ref(struct hda_codec *codec,
 static void stac92hd73xx_fixup_ref(struct hda_codec *codec,
 				   const struct hda_fixup *fix, int action)
 				   const struct hda_fixup *fix, int action)
 {
 {
@@ -1931,6 +1938,10 @@ static const struct hda_fixup stac92hd73xx_fixups[] = {
 	[STAC_92HD89XX_HP_FRONT_JACK] = {
 	[STAC_92HD89XX_HP_FRONT_JACK] = {
 		.type = HDA_FIXUP_PINS,
 		.type = HDA_FIXUP_PINS,
 		.v.pins = stac92hd89xx_hp_front_jack_pin_configs,
 		.v.pins = stac92hd89xx_hp_front_jack_pin_configs,
+	},
+	[STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = stac92hd89xx_hp_z1_g2_right_mic_jack_pin_configs,
 	}
 	}
 };
 };
 
 
@@ -1991,6 +2002,8 @@ static const struct snd_pci_quirk stac92hd73xx_fixup_tbl[] = {
 		      "Alienware M17x", STAC_ALIENWARE_M17X),
 		      "Alienware M17x", STAC_ALIENWARE_M17X),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490,
 	SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490,
 		      "Alienware M17x R3", STAC_DELL_EQ),
 		      "Alienware M17x R3", STAC_DELL_EQ),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1927,
+				"HP Z1 G2", STAC_92HD89XX_HP_Z1_G2_RIGHT_MIC_JACK),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17,
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x2b17,
 				"unknown HP", STAC_92HD89XX_HP_FRONT_JACK),
 				"unknown HP", STAC_92HD89XX_HP_FRONT_JACK),
 	{} /* terminator */
 	{} /* terminator */
@@ -2668,6 +2681,13 @@ static const struct hda_fixup stac92hd83xxx_fixups[] = {
 		.chained = true,
 		.chained = true,
 		.chain_id = STAC_92HD83XXX_HP_MIC_LED,
 		.chain_id = STAC_92HD83XXX_HP_MIC_LED,
 	},
 	},
+	[STAC_HP_ENVY_TS_BASS] = {
+		.type = HDA_FIXUP_PINS,
+		.v.pins = (const struct hda_pintbl[]) {
+			{ 0x10, 0x92170111 },
+			{}
+		},
+	},
 };
 };
 
 
 static const struct hda_model_fixup stac92hd83xxx_models[] = {
 static const struct hda_model_fixup stac92hd83xxx_models[] = {
@@ -2684,6 +2704,7 @@ static const struct hda_model_fixup stac92hd83xxx_models[] = {
 	{ .id = STAC_92HD83XXX_HEADSET_JACK, .name = "headset-jack" },
 	{ .id = STAC_92HD83XXX_HEADSET_JACK, .name = "headset-jack" },
 	{ .id = STAC_HP_ENVY_BASS, .name = "hp-envy-bass" },
 	{ .id = STAC_HP_ENVY_BASS, .name = "hp-envy-bass" },
 	{ .id = STAC_HP_BNB13_EQ, .name = "hp-bnb13-eq" },
 	{ .id = STAC_HP_BNB13_EQ, .name = "hp-bnb13-eq" },
+	{ .id = STAC_HP_ENVY_TS_BASS, .name = "hp-envy-ts-bass" },
 	{}
 	{}
 };
 };
 
 
@@ -2739,6 +2760,8 @@ static const struct snd_pci_quirk stac92hd83xxx_fixup_tbl[] = {
 			  "HP bNB13", STAC_HP_BNB13_EQ),
 			  "HP bNB13", STAC_HP_BNB13_EQ),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190A,
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190A,
 			  "HP bNB13", STAC_HP_BNB13_EQ),
 			  "HP bNB13", STAC_HP_BNB13_EQ),
+	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x190e,
+			  "HP ENVY TS", STAC_HP_ENVY_TS_BASS),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1940,
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1940,
 			  "HP bNB13", STAC_HP_BNB13_EQ),
 			  "HP bNB13", STAC_HP_BNB13_EQ),
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1941,
 	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1941,
@@ -3438,9 +3461,11 @@ static void stac922x_fixup_intel_mac_auto(struct hda_codec *codec,
 {
 {
 	if (action != HDA_FIXUP_ACT_PRE_PROBE)
 	if (action != HDA_FIXUP_ACT_PRE_PROBE)
 		return;
 		return;
+
+	codec->fixup_id = HDA_FIXUP_ID_NOT_SET;
 	snd_hda_pick_fixup(codec, NULL, stac922x_intel_mac_fixup_tbl,
 	snd_hda_pick_fixup(codec, NULL, stac922x_intel_mac_fixup_tbl,
 			   stac922x_fixups);
 			   stac922x_fixups);
-	if (codec->fixup_id != STAC_INTEL_MAC_AUTO)
+	if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
 		snd_hda_apply_fixup(codec, action);
 		snd_hda_apply_fixup(codec, action);
 }
 }
 
 

+ 9 - 6
sound/pci/ice1712/ice1712.h

@@ -41,14 +41,17 @@
 #define ICEREG(ice, x) ((ice)->port + ICE1712_REG_##x)
 #define ICEREG(ice, x) ((ice)->port + ICE1712_REG_##x)
 
 
 #define ICE1712_REG_CONTROL		0x00	/* byte */
 #define ICE1712_REG_CONTROL		0x00	/* byte */
-#define   ICE1712_RESET			0x80	/* reset whole chip */
-#define   ICE1712_SERR_LEVEL		0x04	/* SERR# level otherwise edge */
+#define   ICE1712_RESET			0x80	/* soft reset whole chip */
+#define   ICE1712_SERR_ASSERT_DS_DMA	0x40    /* disabled SERR# assertion for the DS DMA Ch-C irq otherwise enabled */
+#define   ICE1712_DOS_VOL		0x10    /* DOS WT/FM volume control */
+#define   ICE1712_SERR_LEVEL		0x08	/* SERR# level otherwise edge */
+#define   ICE1712_SERR_ASSERT_SB	0x02	/* disabled SERR# assertion for SB irq otherwise enabled */
 #define   ICE1712_NATIVE		0x01	/* native mode otherwise SB */
 #define   ICE1712_NATIVE		0x01	/* native mode otherwise SB */
 #define ICE1712_REG_IRQMASK		0x01	/* byte */
 #define ICE1712_REG_IRQMASK		0x01	/* byte */
-#define   ICE1712_IRQ_MPU1		0x80
-#define   ICE1712_IRQ_TIMER		0x40
-#define   ICE1712_IRQ_MPU2		0x20
-#define   ICE1712_IRQ_PROPCM		0x10
+#define   ICE1712_IRQ_MPU1		0x80	/* MIDI irq mask */
+#define   ICE1712_IRQ_TIMER		0x40	/* Timer mask */
+#define   ICE1712_IRQ_MPU2		0x20	/* Secondary MIDI irq mask */
+#define   ICE1712_IRQ_PROPCM		0x10	/* professional multi-track */
 #define   ICE1712_IRQ_FM		0x08	/* FM/MIDI - legacy */
 #define   ICE1712_IRQ_FM		0x08	/* FM/MIDI - legacy */
 #define   ICE1712_IRQ_PBKDS		0x04	/* playback DS channels */
 #define   ICE1712_IRQ_PBKDS		0x04	/* playback DS channels */
 #define   ICE1712_IRQ_CONCAP		0x02	/* consumer capture */
 #define   ICE1712_IRQ_CONCAP		0x02	/* consumer capture */

+ 1 - 3
sound/pci/mixart/mixart_core.c

@@ -151,13 +151,11 @@ static int send_msg( struct mixart_mgr *mgr,
 {
 {
 	u32 headptr, tailptr;
 	u32 headptr, tailptr;
 	u32 msg_frame_address;
 	u32 msg_frame_address;
-	int err, i;
+	int i;
 
 
 	if (snd_BUG_ON(msg->size % 4))
 	if (snd_BUG_ON(msg->size % 4))
 		return -EINVAL;
 		return -EINVAL;
 
 
-	err = 0;
-
 	/* get message frame address */
 	/* get message frame address */
 	tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL));
 	tailptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_TAIL));
 	headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD));
 	headptr = readl_be(MIXART_MEM(mgr, MSG_INBOUND_FREE_HEAD));

+ 1 - 0
sound/pci/oxygen/virtuoso.c

@@ -53,6 +53,7 @@ static DEFINE_PCI_DEVICE_TABLE(xonar_ids) = {
 	{ OXYGEN_PCI_SUBID(0x1043, 0x835e) },
 	{ OXYGEN_PCI_SUBID(0x1043, 0x835e) },
 	{ OXYGEN_PCI_SUBID(0x1043, 0x838e) },
 	{ OXYGEN_PCI_SUBID(0x1043, 0x838e) },
 	{ OXYGEN_PCI_SUBID(0x1043, 0x8522) },
 	{ OXYGEN_PCI_SUBID(0x1043, 0x8522) },
+	{ OXYGEN_PCI_SUBID(0x1043, 0x85f4) },
 	{ OXYGEN_PCI_SUBID_BROKEN_EEPROM },
 	{ OXYGEN_PCI_SUBID_BROKEN_EEPROM },
 	{ }
 	{ }
 };
 };

+ 10 - 2
sound/pci/oxygen/xonar_pcm179x.c

@@ -100,8 +100,8 @@
  */
  */
 
 
 /*
 /*
- * Xonar Essence ST (Deluxe)/STX
- * -----------------------------
+ * Xonar Essence ST (Deluxe)/STX (II)
+ * ----------------------------------
  *
  *
  * CMI8788:
  * CMI8788:
  *
  *
@@ -1138,6 +1138,14 @@ int get_xonar_pcm179x_model(struct oxygen *chip,
 		chip->model.resume = xonar_stx_resume;
 		chip->model.resume = xonar_stx_resume;
 		chip->model.set_dac_params = set_pcm1796_params;
 		chip->model.set_dac_params = set_pcm1796_params;
 		break;
 		break;
+	case 0x85f4:
+		chip->model = model_xonar_st;
+		/* TODO: daughterboard support */
+		chip->model.shortname = "Xonar STX II";
+		chip->model.init = xonar_stx_init;
+		chip->model.resume = xonar_stx_resume;
+		chip->model.set_dac_params = set_pcm1796_params;
+		break;
 	default:
 	default:
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}

+ 2 - 2
sound/pci/riptide/riptide.c

@@ -941,7 +941,7 @@ setmixer(struct cmdif *cif, short num, unsigned short rval, unsigned short lval)
 	union cmdret rptr = CMDRET_ZERO;
 	union cmdret rptr = CMDRET_ZERO;
 	int i = 0;
 	int i = 0;
 
 
-	snd_printdd("sent mixer %d: 0x%d 0x%d\n", num, rval, lval);
+	snd_printdd("sent mixer %d: 0x%x 0x%x\n", num, rval, lval);
 	do {
 	do {
 		SEND_SDGV(cif, num, num, rval, lval);
 		SEND_SDGV(cif, num, num, rval, lval);
 		SEND_RDGV(cif, num, num, &rptr);
 		SEND_RDGV(cif, num, num, &rptr);
@@ -1080,7 +1080,7 @@ getmixer(struct cmdif *cif, short num, unsigned short *rval,
 		return -EIO;
 		return -EIO;
 	*rval = rptr.retwords[0];
 	*rval = rptr.retwords[0];
 	*lval = rptr.retwords[1];
 	*lval = rptr.retwords[1];
-	snd_printdd("got mixer %d: 0x%d 0x%d\n", num, *rval, *lval);
+	snd_printdd("got mixer %d: 0x%x 0x%x\n", num, *rval, *lval);
 	return 0;
 	return 0;
 }
 }
 
 

+ 0 - 2
sound/pci/trident/trident_main.c

@@ -3880,14 +3880,12 @@ void snd_trident_free_voice(struct snd_trident * trident, struct snd_trident_voi
 {
 {
 	unsigned long flags;
 	unsigned long flags;
 	void (*private_free)(struct snd_trident_voice *);
 	void (*private_free)(struct snd_trident_voice *);
-	void *private_data;
 
 
 	if (voice == NULL || !voice->use)
 	if (voice == NULL || !voice->use)
 		return;
 		return;
 	snd_trident_clear_voices(trident, voice->number, voice->number);
 	snd_trident_clear_voices(trident, voice->number, voice->number);
 	spin_lock_irqsave(&trident->voice_alloc, flags);
 	spin_lock_irqsave(&trident->voice_alloc, flags);
 	private_free = voice->private_free;
 	private_free = voice->private_free;
-	private_data = voice->private_data;
 	voice->private_free = NULL;
 	voice->private_free = NULL;
 	voice->private_data = NULL;
 	voice->private_data = NULL;
 	if (voice->pcm)
 	if (voice->pcm)

+ 1 - 2
sound/pci/trident/trident_memory.c

@@ -139,12 +139,11 @@ static inline void *offset_ptr(struct snd_trident *trident, int offset)
 static struct snd_util_memblk *
 static struct snd_util_memblk *
 search_empty(struct snd_util_memhdr *hdr, int size)
 search_empty(struct snd_util_memhdr *hdr, int size)
 {
 {
-	struct snd_util_memblk *blk, *prev;
+	struct snd_util_memblk *blk;
 	int page, psize;
 	int page, psize;
 	struct list_head *p;
 	struct list_head *p;
 
 
 	psize = get_aligned_page(size + ALIGN_PAGE_SIZE -1);
 	psize = get_aligned_page(size + ALIGN_PAGE_SIZE -1);
-	prev = NULL;
 	page = 0;
 	page = 0;
 	list_for_each(p, &hdr->block) {
 	list_for_each(p, &hdr->block) {
 		blk = list_entry(p, struct snd_util_memblk, list);
 		blk = list_entry(p, struct snd_util_memblk, list);

+ 1 - 0
sound/soc/Kconfig

@@ -47,6 +47,7 @@ source "sound/soc/kirkwood/Kconfig"
 source "sound/soc/intel/Kconfig"
 source "sound/soc/intel/Kconfig"
 source "sound/soc/mxs/Kconfig"
 source "sound/soc/mxs/Kconfig"
 source "sound/soc/pxa/Kconfig"
 source "sound/soc/pxa/Kconfig"
+source "sound/soc/rockchip/Kconfig"
 source "sound/soc/samsung/Kconfig"
 source "sound/soc/samsung/Kconfig"
 source "sound/soc/s6000/Kconfig"
 source "sound/soc/s6000/Kconfig"
 source "sound/soc/sh/Kconfig"
 source "sound/soc/sh/Kconfig"

+ 1 - 0
sound/soc/Makefile

@@ -24,6 +24,7 @@ obj-$(CONFIG_SND_SOC)	+= nuc900/
 obj-$(CONFIG_SND_SOC)	+= omap/
 obj-$(CONFIG_SND_SOC)	+= omap/
 obj-$(CONFIG_SND_SOC)	+= kirkwood/
 obj-$(CONFIG_SND_SOC)	+= kirkwood/
 obj-$(CONFIG_SND_SOC)	+= pxa/
 obj-$(CONFIG_SND_SOC)	+= pxa/
+obj-$(CONFIG_SND_SOC)	+= rockchip/
 obj-$(CONFIG_SND_SOC)	+= samsung/
 obj-$(CONFIG_SND_SOC)	+= samsung/
 obj-$(CONFIG_SND_SOC)	+= s6000/
 obj-$(CONFIG_SND_SOC)	+= s6000/
 obj-$(CONFIG_SND_SOC)	+= sh/
 obj-$(CONFIG_SND_SOC)	+= sh/

+ 18 - 16
sound/soc/atmel/atmel_ssc_dai.c

@@ -347,6 +347,7 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 	u32 tfmr, rfmr, tcmr, rcmr;
 	u32 tfmr, rfmr, tcmr, rcmr;
 	int start_event;
 	int start_event;
 	int ret;
 	int ret;
+	int fslen, fslen_ext;
 
 
 	/*
 	/*
 	 * Currently, there is only one set of dma params for
 	 * Currently, there is only one set of dma params for
@@ -387,18 +388,6 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 
 
-	/*
-	 * The SSC only supports up to 16-bit samples in I2S format, due
-	 * to the size of the Frame Mode Register FSLEN field.
-	 */
-	if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
-		&& bits > 16) {
-		printk(KERN_WARNING
-				"atmel_ssc_dai: sample size %d "
-				"is too large for I2S\n", bits);
-		return -EINVAL;
-	}
-
 	/*
 	/*
 	 * Compute SSC register settings.
 	 * Compute SSC register settings.
 	 */
 	 */
@@ -413,6 +402,17 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 		 * from the MCK divider, and the BCLK signal
 		 * from the MCK divider, and the BCLK signal
 		 * is output on the SSC TK line.
 		 * is output on the SSC TK line.
 		 */
 		 */
+
+		if (bits > 16 && !ssc->pdata->has_fslen_ext) {
+			dev_err(dai->dev,
+				"sample size %d is too large for SSC device\n",
+				bits);
+			return -EINVAL;
+		}
+
+		fslen_ext = (bits - 1) / 16;
+		fslen = (bits - 1) % 16;
+
 		rcmr =	  SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
 		rcmr =	  SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
 			| SSC_BF(RCMR_STTDLY, START_DELAY)
 			| SSC_BF(RCMR_STTDLY, START_DELAY)
 			| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
 			| SSC_BF(RCMR_START, SSC_START_FALLING_RF)
@@ -420,9 +420,10 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 			| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
 			| SSC_BF(RCMR_CKO, SSC_CKO_NONE)
 			| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
 			| SSC_BF(RCMR_CKS, SSC_CKS_DIV);
 
 
-		rfmr =	  SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+		rfmr =    SSC_BF(RFMR_FSLEN_EXT, fslen_ext)
+			| SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
 			| SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
 			| SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
-			| SSC_BF(RFMR_FSLEN, (bits - 1))
+			| SSC_BF(RFMR_FSLEN, fslen)
 			| SSC_BF(RFMR_DATNB, (channels - 1))
 			| SSC_BF(RFMR_DATNB, (channels - 1))
 			| SSC_BIT(RFMR_MSBF)
 			| SSC_BIT(RFMR_MSBF)
 			| SSC_BF(RFMR_LOOP, 0)
 			| SSC_BF(RFMR_LOOP, 0)
@@ -435,10 +436,11 @@ static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
 			| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
 			| SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
 			| SSC_BF(TCMR_CKS, SSC_CKS_DIV);
 			| SSC_BF(TCMR_CKS, SSC_CKS_DIV);
 
 
-		tfmr =	  SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
+		tfmr =    SSC_BF(TFMR_FSLEN_EXT, fslen_ext)
+			| SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
 			| SSC_BF(TFMR_FSDEN, 0)
 			| SSC_BF(TFMR_FSDEN, 0)
 			| SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
 			| SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
-			| SSC_BF(TFMR_FSLEN, (bits - 1))
+			| SSC_BF(TFMR_FSLEN, fslen)
 			| SSC_BF(TFMR_DATNB, (channels - 1))
 			| SSC_BF(TFMR_DATNB, (channels - 1))
 			| SSC_BIT(TFMR_MSBF)
 			| SSC_BIT(TFMR_MSBF)
 			| SSC_BF(TFMR_DATDEF, 0)
 			| SSC_BF(TFMR_DATDEF, 0)

+ 0 - 50
sound/soc/atmel/atmel_wm8904.c

@@ -18,10 +18,6 @@
 #include "../codecs/wm8904.h"
 #include "../codecs/wm8904.h"
 #include "atmel_ssc_dai.h"
 #include "atmel_ssc_dai.h"
 
 
-#define MCLK_RATE 32768
-
-static struct clk *mclk;
-
 static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = {
 static const struct snd_soc_dapm_widget atmel_asoc_wm8904_dapm_widgets[] = {
 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
 	SND_SOC_DAPM_HP("Headphone Jack", NULL),
 	SND_SOC_DAPM_MIC("Mic", NULL),
 	SND_SOC_DAPM_MIC("Mic", NULL),
@@ -61,26 +57,6 @@ static struct snd_soc_ops atmel_asoc_wm8904_ops = {
 	.hw_params = atmel_asoc_wm8904_hw_params,
 	.hw_params = atmel_asoc_wm8904_hw_params,
 };
 };
 
 
-static int atmel_set_bias_level(struct snd_soc_card *card,
-		struct snd_soc_dapm_context *dapm,
-		enum snd_soc_bias_level level)
-{
-	if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
-		switch (level) {
-		case SND_SOC_BIAS_PREPARE:
-			clk_prepare_enable(mclk);
-			break;
-		case SND_SOC_BIAS_OFF:
-			clk_disable_unprepare(mclk);
-			break;
-		default:
-			break;
-		}
-	}
-
-	return 0;
-};
-
 static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = {
 static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = {
 	.name = "WM8904",
 	.name = "WM8904",
 	.stream_name = "WM8904 PCM",
 	.stream_name = "WM8904 PCM",
@@ -94,7 +70,6 @@ static struct snd_soc_dai_link atmel_asoc_wm8904_dailink = {
 static struct snd_soc_card atmel_asoc_wm8904_card = {
 static struct snd_soc_card atmel_asoc_wm8904_card = {
 	.name = "atmel_asoc_wm8904",
 	.name = "atmel_asoc_wm8904",
 	.owner = THIS_MODULE,
 	.owner = THIS_MODULE,
-	.set_bias_level = atmel_set_bias_level,
 	.dai_link = &atmel_asoc_wm8904_dailink,
 	.dai_link = &atmel_asoc_wm8904_dailink,
 	.num_links = 1,
 	.num_links = 1,
 	.dapm_widgets = atmel_asoc_wm8904_dapm_widgets,
 	.dapm_widgets = atmel_asoc_wm8904_dapm_widgets,
@@ -153,7 +128,6 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev)
 {
 {
 	struct snd_soc_card *card = &atmel_asoc_wm8904_card;
 	struct snd_soc_card *card = &atmel_asoc_wm8904_card;
 	struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
 	struct snd_soc_dai_link *dailink = &atmel_asoc_wm8904_dailink;
-	struct clk *clk_src;
 	int id, ret;
 	int id, ret;
 
 
 	card->dev = &pdev->dev;
 	card->dev = &pdev->dev;
@@ -170,30 +144,6 @@ static int atmel_asoc_wm8904_probe(struct platform_device *pdev)
 		return ret;
 		return ret;
 	}
 	}
 
 
-	mclk = clk_get(NULL, "pck0");
-	if (IS_ERR(mclk)) {
-		dev_err(&pdev->dev, "failed to get pck0\n");
-		ret = PTR_ERR(mclk);
-		goto err_set_audio;
-	}
-
-	clk_src = clk_get(NULL, "clk32k");
-	if (IS_ERR(clk_src)) {
-		dev_err(&pdev->dev, "failed to get clk32k\n");
-		ret = PTR_ERR(clk_src);
-		goto err_set_audio;
-	}
-
-	ret = clk_set_parent(mclk, clk_src);
-	clk_put(clk_src);
-	if (ret != 0) {
-		dev_err(&pdev->dev, "failed to set MCLK parent\n");
-		goto err_set_audio;
-	}
-
-	dev_info(&pdev->dev, "setting pck0 to %dHz\n", MCLK_RATE);
-	clk_set_rate(mclk, MCLK_RATE);
-
 	ret = snd_soc_register_card(card);
 	ret = snd_soc_register_card(card);
 	if (ret) {
 	if (ret) {
 		dev_err(&pdev->dev, "snd_soc_register_card failed\n");
 		dev_err(&pdev->dev, "snd_soc_register_card failed\n");

+ 4 - 4
sound/soc/blackfin/bf5xx-i2s-pcm.c

@@ -290,19 +290,19 @@ static int bf5xx_pcm_silence(struct snd_pcm_substream *substream,
 	unsigned int sample_size = runtime->sample_bits / 8;
 	unsigned int sample_size = runtime->sample_bits / 8;
 	void *buf = runtime->dma_area;
 	void *buf = runtime->dma_area;
 	struct bf5xx_i2s_pcm_data *dma_data;
 	struct bf5xx_i2s_pcm_data *dma_data;
-	unsigned int offset, size;
+	unsigned int offset, samples;
 
 
 	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 	dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
 
 	if (dma_data->tdm_mode) {
 	if (dma_data->tdm_mode) {
 		offset = pos * 8 * sample_size;
 		offset = pos * 8 * sample_size;
-		size = count * 8 * sample_size;
+		samples = count * 8;
 	} else {
 	} else {
 		offset = frames_to_bytes(runtime, pos);
 		offset = frames_to_bytes(runtime, pos);
-		size = frames_to_bytes(runtime, count);
+		samples = count * runtime->channels;
 	}
 	}
 
 
-	snd_pcm_format_set_silence(runtime->format, buf + offset, size);
+	snd_pcm_format_set_silence(runtime->format, buf + offset, samples);
 
 
 	return 0;
 	return 0;
 }
 }

+ 6 - 6
sound/soc/codecs/88pm860x-codec.c

@@ -945,11 +945,11 @@ static int pm860x_pcm_hw_params(struct snd_pcm_substream *substream,
 	unsigned char inf = 0, mask = 0;
 	unsigned char inf = 0, mask = 0;
 
 
 	/* bit size */
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		inf &= ~PCM_INF2_18WL;
 		inf &= ~PCM_INF2_18WL;
 		break;
 		break;
-	case SNDRV_PCM_FORMAT_S18_3LE:
+	case 18:
 		inf |= PCM_INF2_18WL;
 		inf |= PCM_INF2_18WL;
 		break;
 		break;
 	default:
 	default:
@@ -1044,11 +1044,11 @@ static int pm860x_i2s_hw_params(struct snd_pcm_substream *substream,
 	unsigned char inf;
 	unsigned char inf;
 
 
 	/* bit size */
 	/* bit size */
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		inf = 0;
 		inf = 0;
 		break;
 		break;
-	case SNDRV_PCM_FORMAT_S18_3LE:
+	case 18:
 		inf = PCM_INF2_18WL;
 		inf = PCM_INF2_18WL;
 		break;
 		break;
 	default:
 	default:

+ 26 - 1
sound/soc/codecs/Kconfig

@@ -47,6 +47,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_CS42L52 if I2C && INPUT
 	select SND_SOC_CS42L52 if I2C && INPUT
 	select SND_SOC_CS42L56 if I2C && INPUT
 	select SND_SOC_CS42L56 if I2C && INPUT
 	select SND_SOC_CS42L73 if I2C
 	select SND_SOC_CS42L73 if I2C
+	select SND_SOC_CS4265 if I2C
 	select SND_SOC_CS4270 if I2C
 	select SND_SOC_CS4270 if I2C
 	select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
 	select SND_SOC_CS42XX8_I2C if I2C
 	select SND_SOC_CS42XX8_I2C if I2C
@@ -74,10 +75,12 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_PCM3008
 	select SND_SOC_PCM3008
 	select SND_SOC_PCM512x_I2C if I2C
 	select SND_SOC_PCM512x_I2C if I2C
 	select SND_SOC_PCM512x_SPI if SPI_MASTER
 	select SND_SOC_PCM512x_SPI if SPI_MASTER
+	select SND_SOC_RT286 if I2C
 	select SND_SOC_RT5631 if I2C
 	select SND_SOC_RT5631 if I2C
 	select SND_SOC_RT5640 if I2C
 	select SND_SOC_RT5640 if I2C
 	select SND_SOC_RT5645 if I2C
 	select SND_SOC_RT5645 if I2C
 	select SND_SOC_RT5651 if I2C
 	select SND_SOC_RT5651 if I2C
+	select SND_SOC_RT5670 if I2C
 	select SND_SOC_RT5677 if I2C
 	select SND_SOC_RT5677 if I2C
 	select SND_SOC_SGTL5000 if I2C
 	select SND_SOC_SGTL5000 if I2C
 	select SND_SOC_SI476X if MFD_SI476X_CORE
 	select SND_SOC_SI476X if MFD_SI476X_CORE
@@ -91,6 +94,7 @@ config SND_SOC_ALL_CODECS
 	select SND_SOC_STA350 if I2C
 	select SND_SOC_STA350 if I2C
 	select SND_SOC_STA529 if I2C
 	select SND_SOC_STA529 if I2C
 	select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
 	select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
+	select SND_SOC_TAS2552 if I2C
 	select SND_SOC_TAS5086 if I2C
 	select SND_SOC_TAS5086 if I2C
 	select SND_SOC_TLV320AIC23_I2C if I2C
 	select SND_SOC_TLV320AIC23_I2C if I2C
 	select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
 	select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
@@ -338,6 +342,11 @@ config SND_SOC_CS42L73
 	tristate "Cirrus Logic CS42L73 CODEC"
 	tristate "Cirrus Logic CS42L73 CODEC"
 	depends on I2C
 	depends on I2C
 
 
+config SND_SOC_CS4265
+	tristate "Cirrus Logic CS4265 CODEC"
+	depends on I2C
+	select REGMAP_I2C
+
 # Cirrus Logic CS4270 Codec
 # Cirrus Logic CS4270 Codec
 config SND_SOC_CS4270
 config SND_SOC_CS4270
 	tristate "Cirrus Logic CS4270 CODEC"
 	tristate "Cirrus Logic CS4270 CODEC"
@@ -445,9 +454,16 @@ config SND_SOC_RL6231
 	default y if SND_SOC_RT5640=y
 	default y if SND_SOC_RT5640=y
 	default y if SND_SOC_RT5645=y
 	default y if SND_SOC_RT5645=y
 	default y if SND_SOC_RT5651=y
 	default y if SND_SOC_RT5651=y
+	default y if SND_SOC_RT5670=y
+	default y if SND_SOC_RT5677=y
 	default m if SND_SOC_RT5640=m
 	default m if SND_SOC_RT5640=m
 	default m if SND_SOC_RT5645=m
 	default m if SND_SOC_RT5645=m
 	default m if SND_SOC_RT5651=m
 	default m if SND_SOC_RT5651=m
+	default m if SND_SOC_RT5670=m
+	default m if SND_SOC_RT5677=m
+
+config SND_SOC_RT286
+	tristate
 
 
 config SND_SOC_RT5631
 config SND_SOC_RT5631
 	tristate
 	tristate
@@ -461,6 +477,9 @@ config SND_SOC_RT5645
 config SND_SOC_RT5651
 config SND_SOC_RT5651
 	tristate
 	tristate
 
 
+config SND_SOC_RT5670
+	tristate
+
 config SND_SOC_RT5677
 config SND_SOC_RT5677
 	tristate
 	tristate
 
 
@@ -521,6 +540,10 @@ config SND_SOC_STA529
 config SND_SOC_STAC9766
 config SND_SOC_STAC9766
 	tristate
 	tristate
 
 
+config SND_SOC_TAS2552
+	tristate "Texas Instruments TAS2552 Mono Audio amplifier"
+	depends on I2C
+
 config SND_SOC_TAS5086
 config SND_SOC_TAS5086
 	tristate "Texas Instruments TAS5086 speaker amplifier"
 	tristate "Texas Instruments TAS5086 speaker amplifier"
 	depends on I2C
 	depends on I2C
@@ -541,7 +564,9 @@ config SND_SOC_TLV320AIC26
 	depends on SPI
 	depends on SPI
 
 
 config SND_SOC_TLV320AIC31XX
 config SND_SOC_TLV320AIC31XX
-        tristate
+	tristate "Texas Instruments TLV320AIC31xx CODECs"
+	depends on I2C
+	select REGMAP_I2C
 
 
 config SND_SOC_TLV320AIC32X4
 config SND_SOC_TLV320AIC32X4
 	tristate
 	tristate

+ 8 - 0
sound/soc/codecs/Makefile

@@ -37,6 +37,7 @@ snd-soc-cs42l51-i2c-objs := cs42l51-i2c.o
 snd-soc-cs42l52-objs := cs42l52.o
 snd-soc-cs42l52-objs := cs42l52.o
 snd-soc-cs42l56-objs := cs42l56.o
 snd-soc-cs42l56-objs := cs42l56.o
 snd-soc-cs42l73-objs := cs42l73.o
 snd-soc-cs42l73-objs := cs42l73.o
+snd-soc-cs4265-objs := cs4265.o
 snd-soc-cs4270-objs := cs4270.o
 snd-soc-cs4270-objs := cs4270.o
 snd-soc-cs4271-objs := cs4271.o
 snd-soc-cs4271-objs := cs4271.o
 snd-soc-cs42xx8-objs := cs42xx8.o
 snd-soc-cs42xx8-objs := cs42xx8.o
@@ -68,10 +69,12 @@ snd-soc-pcm512x-objs := pcm512x.o
 snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
 snd-soc-pcm512x-i2c-objs := pcm512x-i2c.o
 snd-soc-pcm512x-spi-objs := pcm512x-spi.o
 snd-soc-pcm512x-spi-objs := pcm512x-spi.o
 snd-soc-rl6231-objs := rl6231.o
 snd-soc-rl6231-objs := rl6231.o
+snd-soc-rt286-objs := rt286.o
 snd-soc-rt5631-objs := rt5631.o
 snd-soc-rt5631-objs := rt5631.o
 snd-soc-rt5640-objs := rt5640.o
 snd-soc-rt5640-objs := rt5640.o
 snd-soc-rt5645-objs := rt5645.o
 snd-soc-rt5645-objs := rt5645.o
 snd-soc-rt5651-objs := rt5651.o
 snd-soc-rt5651-objs := rt5651.o
+snd-soc-rt5670-objs := rt5670.o
 snd-soc-rt5677-objs := rt5677.o
 snd-soc-rt5677-objs := rt5677.o
 snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-sgtl5000-objs := sgtl5000.o
 snd-soc-alc5623-objs := alc5623.o
 snd-soc-alc5623-objs := alc5623.o
@@ -162,6 +165,7 @@ snd-soc-wm-hubs-objs := wm_hubs.o
 # Amp
 # Amp
 snd-soc-max9877-objs := max9877.o
 snd-soc-max9877-objs := max9877.o
 snd-soc-tpa6130a2-objs := tpa6130a2.o
 snd-soc-tpa6130a2-objs := tpa6130a2.o
+snd-soc-tas2552-objs := tas2552.o
 
 
 obj-$(CONFIG_SND_SOC_88PM860X)	+= snd-soc-88pm860x.o
 obj-$(CONFIG_SND_SOC_88PM860X)	+= snd-soc-88pm860x.o
 obj-$(CONFIG_SND_SOC_AB8500_CODEC)	+= snd-soc-ab8500-codec.o
 obj-$(CONFIG_SND_SOC_AB8500_CODEC)	+= snd-soc-ab8500-codec.o
@@ -204,6 +208,7 @@ obj-$(CONFIG_SND_SOC_CS42L51_I2C)	+= snd-soc-cs42l51-i2c.o
 obj-$(CONFIG_SND_SOC_CS42L52)	+= snd-soc-cs42l52.o
 obj-$(CONFIG_SND_SOC_CS42L52)	+= snd-soc-cs42l52.o
 obj-$(CONFIG_SND_SOC_CS42L56)	+= snd-soc-cs42l56.o
 obj-$(CONFIG_SND_SOC_CS42L56)	+= snd-soc-cs42l56.o
 obj-$(CONFIG_SND_SOC_CS42L73)	+= snd-soc-cs42l73.o
 obj-$(CONFIG_SND_SOC_CS42L73)	+= snd-soc-cs42l73.o
+obj-$(CONFIG_SND_SOC_CS4265)	+= snd-soc-cs4265.o
 obj-$(CONFIG_SND_SOC_CS4270)	+= snd-soc-cs4270.o
 obj-$(CONFIG_SND_SOC_CS4270)	+= snd-soc-cs4270.o
 obj-$(CONFIG_SND_SOC_CS4271)	+= snd-soc-cs4271.o
 obj-$(CONFIG_SND_SOC_CS4271)	+= snd-soc-cs4271.o
 obj-$(CONFIG_SND_SOC_CS42XX8)	+= snd-soc-cs42xx8.o
 obj-$(CONFIG_SND_SOC_CS42XX8)	+= snd-soc-cs42xx8.o
@@ -235,10 +240,12 @@ obj-$(CONFIG_SND_SOC_PCM512x)	+= snd-soc-pcm512x.o
 obj-$(CONFIG_SND_SOC_PCM512x_I2C)	+= snd-soc-pcm512x-i2c.o
 obj-$(CONFIG_SND_SOC_PCM512x_I2C)	+= snd-soc-pcm512x-i2c.o
 obj-$(CONFIG_SND_SOC_PCM512x_SPI)	+= snd-soc-pcm512x-spi.o
 obj-$(CONFIG_SND_SOC_PCM512x_SPI)	+= snd-soc-pcm512x-spi.o
 obj-$(CONFIG_SND_SOC_RL6231)	+= snd-soc-rl6231.o
 obj-$(CONFIG_SND_SOC_RL6231)	+= snd-soc-rl6231.o
+obj-$(CONFIG_SND_SOC_RT286)	+= snd-soc-rt286.o
 obj-$(CONFIG_SND_SOC_RT5631)	+= snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_RT5631)	+= snd-soc-rt5631.o
 obj-$(CONFIG_SND_SOC_RT5640)	+= snd-soc-rt5640.o
 obj-$(CONFIG_SND_SOC_RT5640)	+= snd-soc-rt5640.o
 obj-$(CONFIG_SND_SOC_RT5645)	+= snd-soc-rt5645.o
 obj-$(CONFIG_SND_SOC_RT5645)	+= snd-soc-rt5645.o
 obj-$(CONFIG_SND_SOC_RT5651)	+= snd-soc-rt5651.o
 obj-$(CONFIG_SND_SOC_RT5651)	+= snd-soc-rt5651.o
+obj-$(CONFIG_SND_SOC_RT5670)	+= snd-soc-rt5670.o
 obj-$(CONFIG_SND_SOC_RT5677)	+= snd-soc-rt5677.o
 obj-$(CONFIG_SND_SOC_RT5677)	+= snd-soc-rt5677.o
 obj-$(CONFIG_SND_SOC_SGTL5000)  += snd-soc-sgtl5000.o
 obj-$(CONFIG_SND_SOC_SGTL5000)  += snd-soc-sgtl5000.o
 obj-$(CONFIG_SND_SOC_SIGMADSP)	+= snd-soc-sigmadsp.o
 obj-$(CONFIG_SND_SOC_SIGMADSP)	+= snd-soc-sigmadsp.o
@@ -255,6 +262,7 @@ obj-$(CONFIG_SND_SOC_STA32X)   += snd-soc-sta32x.o
 obj-$(CONFIG_SND_SOC_STA350)   += snd-soc-sta350.o
 obj-$(CONFIG_SND_SOC_STA350)   += snd-soc-sta350.o
 obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STA529)   += snd-soc-sta529.o
 obj-$(CONFIG_SND_SOC_STAC9766)	+= snd-soc-stac9766.o
 obj-$(CONFIG_SND_SOC_STAC9766)	+= snd-soc-stac9766.o
+obj-$(CONFIG_SND_SOC_TAS2552)	+= snd-soc-tas2552.o
 obj-$(CONFIG_SND_SOC_TAS5086)	+= snd-soc-tas5086.o
 obj-$(CONFIG_SND_SOC_TAS5086)	+= snd-soc-tas5086.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)	+= snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23)	+= snd-soc-tlv320aic23.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C)	+= snd-soc-tlv320aic23-i2c.o
 obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C)	+= snd-soc-tlv320aic23-i2c.o

+ 2 - 2
sound/soc/codecs/ac97.c

@@ -89,8 +89,8 @@ static int ac97_soc_probe(struct snd_soc_codec *codec)
 	int ret;
 	int ret;
 
 
 	/* add codec as bus device for standard ac97 */
 	/* add codec as bus device for standard ac97 */
-	ret = snd_ac97_bus(codec->card->snd_card, 0, soc_ac97_ops, NULL,
-			   &ac97_bus);
+	ret = snd_ac97_bus(codec->component.card->snd_card, 0, soc_ac97_ops,
+			   NULL, &ac97_bus);
 	if (ret < 0)
 	if (ret < 0)
 		return ret;
 		return ret;
 
 

+ 4 - 2
sound/soc/codecs/adau1701.c

@@ -230,8 +230,10 @@ static int adau1701_reg_read(void *context, unsigned int reg,
 
 
 	*value = 0;
 	*value = 0;
 
 
-	for (i = 0; i < size; i++)
-		*value |= recv_buf[i] << (i * 8);
+	for (i = 0; i < size; i++) {
+		*value <<= 8;
+		*value |= recv_buf[i];
+	}
 
 
 	return 0;
 	return 0;
 }
 }

+ 4 - 4
sound/soc/codecs/adau17x1.c

@@ -359,14 +359,14 @@ static int adau17x1_hw_params(struct snd_pcm_substream *substream,
 	if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J)
 	if (adau->dai_fmt != SND_SOC_DAIFMT_RIGHT_J)
 		return 0;
 		return 0;
 
 
-	switch (params_format(params)) {
-	case SNDRV_PCM_FORMAT_S16_LE:
+	switch (params_width(params)) {
+	case 16:
 		val = ADAU17X1_SERIAL_PORT1_DELAY16;
 		val = ADAU17X1_SERIAL_PORT1_DELAY16;
 		break;
 		break;
-	case SNDRV_PCM_FORMAT_S24_LE:
+	case 24:
 		val = ADAU17X1_SERIAL_PORT1_DELAY8;
 		val = ADAU17X1_SERIAL_PORT1_DELAY8;
 		break;
 		break;
-	case SNDRV_PCM_FORMAT_S32_LE:
+	case 32:
 		val = ADAU17X1_SERIAL_PORT1_DELAY0;
 		val = ADAU17X1_SERIAL_PORT1_DELAY0;
 		break;
 		break;
 	default:
 	default:

+ 1 - 1
sound/soc/codecs/adau1977.c

@@ -968,7 +968,7 @@ int adau1977_probe(struct device *dev, struct regmap *regmap,
 	if (adau1977->dvdd_reg)
 	if (adau1977->dvdd_reg)
 		power_off_mask = ~0;
 		power_off_mask = ~0;
 	else
 	else
-		power_off_mask = ~ADAU1977_BLOCK_POWER_SAI_LDO_EN;
+		power_off_mask = (unsigned int)~ADAU1977_BLOCK_POWER_SAI_LDO_EN;
 
 
 	ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI,
 	ret = regmap_update_bits(adau1977->regmap, ADAU1977_REG_BLOCK_POWER_SAI,
 				power_off_mask, 0x00);
 				power_off_mask, 0x00);

+ 2 - 2
sound/soc/codecs/ak4642.c

@@ -547,7 +547,7 @@ static const struct ak4642_drvdata ak4648_drvdata = {
 	.extended_frequencies = 1,
 	.extended_frequencies = 1,
 };
 };
 
 
-static struct of_device_id ak4642_of_match[];
+static const struct of_device_id ak4642_of_match[];
 static int ak4642_i2c_probe(struct i2c_client *i2c,
 static int ak4642_i2c_probe(struct i2c_client *i2c,
 			    const struct i2c_device_id *id)
 			    const struct i2c_device_id *id)
 {
 {
@@ -593,7 +593,7 @@ static int ak4642_i2c_remove(struct i2c_client *client)
 	return 0;
 	return 0;
 }
 }
 
 
-static struct of_device_id ak4642_of_match[] = {
+static const struct of_device_id ak4642_of_match[] = {
 	{ .compatible = "asahi-kasei,ak4642",	.data = &ak4642_drvdata},
 	{ .compatible = "asahi-kasei,ak4642",	.data = &ak4642_drvdata},
 	{ .compatible = "asahi-kasei,ak4643",	.data = &ak4643_drvdata},
 	{ .compatible = "asahi-kasei,ak4643",	.data = &ak4643_drvdata},
 	{ .compatible = "asahi-kasei,ak4648",	.data = &ak4648_drvdata},
 	{ .compatible = "asahi-kasei,ak4648",	.data = &ak4648_drvdata},

+ 50 - 0
sound/soc/codecs/ak5386.c

@@ -14,12 +14,18 @@
 #include <linux/of.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/of_gpio.h>
 #include <linux/of_device.h>
 #include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
 #include <sound/soc.h>
 #include <sound/soc.h>
 #include <sound/pcm.h>
 #include <sound/pcm.h>
 #include <sound/initval.h>
 #include <sound/initval.h>
 
 
+static const char * const supply_names[] = {
+	"va", "vd"
+};
+
 struct ak5386_priv {
 struct ak5386_priv {
 	int reset_gpio;
 	int reset_gpio;
+	struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
 };
 };
 
 
 static const struct snd_soc_dapm_widget ak5386_dapm_widgets[] = {
 static const struct snd_soc_dapm_widget ak5386_dapm_widgets[] = {
@@ -32,7 +38,42 @@ static const struct snd_soc_dapm_route ak5386_dapm_routes[] = {
 	{ "Capture", NULL, "AINR" },
 	{ "Capture", NULL, "AINR" },
 };
 };
 
 
+static int ak5386_soc_probe(struct snd_soc_codec *codec)
+{
+	struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
+	return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
+}
+
+static int ak5386_soc_remove(struct snd_soc_codec *codec)
+{
+	struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
+	regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int ak5386_soc_suspend(struct snd_soc_codec *codec)
+{
+	struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
+	regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
+	return 0;
+}
+
+static int ak5386_soc_resume(struct snd_soc_codec *codec)
+{
+	struct ak5386_priv *priv = snd_soc_codec_get_drvdata(codec);
+	return regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
+}
+#else
+#define ak5386_soc_suspend	NULL
+#define ak5386_soc_resume	NULL
+#endif /* CONFIG_PM */
+
 static struct snd_soc_codec_driver soc_codec_ak5386 = {
 static struct snd_soc_codec_driver soc_codec_ak5386 = {
+	.probe = ak5386_soc_probe,
+	.remove = ak5386_soc_remove,
+	.suspend = ak5386_soc_suspend,
+	.resume = ak5386_soc_resume,
 	.dapm_widgets = ak5386_dapm_widgets,
 	.dapm_widgets = ak5386_dapm_widgets,
 	.num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets),
 	.num_dapm_widgets = ARRAY_SIZE(ak5386_dapm_widgets),
 	.dapm_routes = ak5386_dapm_routes,
 	.dapm_routes = ak5386_dapm_routes,
@@ -122,6 +163,7 @@ static int ak5386_probe(struct platform_device *pdev)
 {
 {
 	struct device *dev = &pdev->dev;
 	struct device *dev = &pdev->dev;
 	struct ak5386_priv *priv;
 	struct ak5386_priv *priv;
+	int ret, i;
 
 
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 	if (!priv)
@@ -130,6 +172,14 @@ static int ak5386_probe(struct platform_device *pdev)
 	priv->reset_gpio = -EINVAL;
 	priv->reset_gpio = -EINVAL;
 	dev_set_drvdata(dev, priv);
 	dev_set_drvdata(dev, priv);
 
 
+	for (i = 0; i < ARRAY_SIZE(supply_names); i++)
+		priv->supplies[i].supply = supply_names[i];
+
+	ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies),
+				      priv->supplies);
+	if (ret < 0)
+		return ret;
+
 	if (of_match_device(of_match_ptr(ak5386_dt_ids), dev))
 	if (of_match_device(of_match_ptr(ak5386_dt_ids), dev))
 		priv->reset_gpio = of_get_named_gpio(dev->of_node,
 		priv->reset_gpio = of_get_named_gpio(dev->of_node,
 						      "reset-gpio", 0);
 						      "reset-gpio", 0);

+ 244 - 44
sound/soc/codecs/arizona.c

@@ -243,6 +243,31 @@ int arizona_init_spk(struct snd_soc_codec *codec)
 }
 }
 EXPORT_SYMBOL_GPL(arizona_init_spk);
 EXPORT_SYMBOL_GPL(arizona_init_spk);
 
 
+static const struct snd_soc_dapm_route arizona_mono_routes[] = {
+	{ "OUT1R", NULL, "OUT1L" },
+	{ "OUT2R", NULL, "OUT2L" },
+	{ "OUT3R", NULL, "OUT3L" },
+	{ "OUT4R", NULL, "OUT4L" },
+	{ "OUT5R", NULL, "OUT5L" },
+	{ "OUT6R", NULL, "OUT6L" },
+};
+
+int arizona_init_mono(struct snd_soc_codec *codec)
+{
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct arizona *arizona = priv->arizona;
+	int i;
+
+	for (i = 0; i < ARIZONA_MAX_OUTPUT; ++i) {
+		if (arizona->pdata.out_mono[i])
+			snd_soc_dapm_add_routes(&codec->dapm,
+						&arizona_mono_routes[i], 1);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(arizona_init_mono);
+
 int arizona_init_gpio(struct snd_soc_codec *codec)
 int arizona_init_gpio(struct snd_soc_codec *codec)
 {
 {
 	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
 	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
@@ -1127,6 +1152,31 @@ static int arizona_startup(struct snd_pcm_substream *substream,
 					  constraint);
 					  constraint);
 }
 }
 
 
+static void arizona_wm5102_set_dac_comp(struct snd_soc_codec *codec,
+					unsigned int rate)
+{
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct arizona *arizona = priv->arizona;
+	struct reg_default dac_comp[] = {
+		{ 0x80, 0x3 },
+		{ ARIZONA_DAC_COMP_1, 0 },
+		{ ARIZONA_DAC_COMP_2, 0 },
+		{ 0x80, 0x0 },
+	};
+
+	mutex_lock(&codec->mutex);
+
+	dac_comp[1].def = arizona->dac_comp_coeff;
+	if (rate >= 176400)
+		dac_comp[2].def = arizona->dac_comp_enabled;
+
+	mutex_unlock(&codec->mutex);
+
+	regmap_multi_reg_write(arizona->regmap,
+			       dac_comp,
+			       ARRAY_SIZE(dac_comp));
+}
+
 static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
 static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
 				  struct snd_pcm_hw_params *params,
 				  struct snd_pcm_hw_params *params,
 				  struct snd_soc_dai *dai)
 				  struct snd_soc_dai *dai)
@@ -1153,6 +1203,15 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
 
 
 	switch (dai_priv->clk) {
 	switch (dai_priv->clk) {
 	case ARIZONA_CLK_SYSCLK:
 	case ARIZONA_CLK_SYSCLK:
+		switch (priv->arizona->type) {
+		case WM5102:
+			arizona_wm5102_set_dac_comp(codec,
+						    params_rate(params));
+			break;
+		default:
+			break;
+		}
+
 		snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
 		snd_soc_update_bits(codec, ARIZONA_SAMPLE_RATE_1,
 				    ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
 				    ARIZONA_SAMPLE_RATE_1_MASK, sr_val);
 		if (base)
 		if (base)
@@ -1175,6 +1234,27 @@ static int arizona_hw_params_rate(struct snd_pcm_substream *substream,
 	return 0;
 	return 0;
 }
 }
 
 
+static bool arizona_aif_cfg_changed(struct snd_soc_codec *codec,
+				    int base, int bclk, int lrclk, int frame)
+{
+	int val;
+
+	val = snd_soc_read(codec, base + ARIZONA_AIF_BCLK_CTRL);
+	if (bclk != (val & ARIZONA_AIF1_BCLK_FREQ_MASK))
+		return true;
+
+	val = snd_soc_read(codec, base + ARIZONA_AIF_TX_BCLK_RATE);
+	if (lrclk != (val & ARIZONA_AIF1TX_BCPF_MASK))
+		return true;
+
+	val = snd_soc_read(codec, base + ARIZONA_AIF_FRAME_CTRL_1);
+	if (frame != (val & (ARIZONA_AIF1TX_WL_MASK |
+			     ARIZONA_AIF1TX_SLOT_LEN_MASK)))
+		return true;
+
+	return false;
+}
+
 static int arizona_hw_params(struct snd_pcm_substream *substream,
 static int arizona_hw_params(struct snd_pcm_substream *substream,
 			     struct snd_pcm_hw_params *params,
 			     struct snd_pcm_hw_params *params,
 			     struct snd_soc_dai *dai)
 			     struct snd_soc_dai *dai)
@@ -1185,26 +1265,40 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
 	int base = dai->driver->base;
 	int base = dai->driver->base;
 	const int *rates;
 	const int *rates;
 	int i, ret, val;
 	int i, ret, val;
+	int channels = params_channels(params);
 	int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
 	int chan_limit = arizona->pdata.max_channels_clocked[dai->id - 1];
+	int tdm_width = arizona->tdm_width[dai->id - 1];
+	int tdm_slots = arizona->tdm_slots[dai->id - 1];
 	int bclk, lrclk, wl, frame, bclk_target;
 	int bclk, lrclk, wl, frame, bclk_target;
+	bool reconfig;
+	unsigned int aif_tx_state, aif_rx_state;
 
 
 	if (params_rate(params) % 8000)
 	if (params_rate(params) % 8000)
 		rates = &arizona_44k1_bclk_rates[0];
 		rates = &arizona_44k1_bclk_rates[0];
 	else
 	else
 		rates = &arizona_48k_bclk_rates[0];
 		rates = &arizona_48k_bclk_rates[0];
 
 
-	bclk_target = snd_soc_params_to_bclk(params);
-	if (chan_limit && chan_limit < params_channels(params)) {
+	if (tdm_slots) {
+		arizona_aif_dbg(dai, "Configuring for %d %d bit TDM slots\n",
+				tdm_slots, tdm_width);
+		bclk_target = tdm_slots * tdm_width * params_rate(params);
+		channels = tdm_slots;
+	} else {
+		bclk_target = snd_soc_params_to_bclk(params);
+	}
+
+	if (chan_limit && chan_limit < channels) {
 		arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
 		arizona_aif_dbg(dai, "Limiting to %d channels\n", chan_limit);
-		bclk_target /= params_channels(params);
+		bclk_target /= channels;
 		bclk_target *= chan_limit;
 		bclk_target *= chan_limit;
 	}
 	}
 
 
-	/* Force stereo for I2S mode */
+	/* Force multiple of 2 channels for I2S mode */
 	val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
 	val = snd_soc_read(codec, base + ARIZONA_AIF_FORMAT);
-	if (params_channels(params) == 1 && (val & ARIZONA_AIF1_FMT_MASK)) {
+	if ((channels & 1) && (val & ARIZONA_AIF1_FMT_MASK)) {
 		arizona_aif_dbg(dai, "Forcing stereo mode\n");
 		arizona_aif_dbg(dai, "Forcing stereo mode\n");
-		bclk_target *= 2;
+		bclk_target /= channels;
+		bclk_target *= channels + 1;
 	}
 	}
 
 
 	for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
 	for (i = 0; i < ARRAY_SIZE(arizona_44k1_bclk_rates); i++) {
@@ -1228,28 +1322,56 @@ static int arizona_hw_params(struct snd_pcm_substream *substream,
 	wl = snd_pcm_format_width(params_format(params));
 	wl = snd_pcm_format_width(params_format(params));
 	frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
 	frame = wl << ARIZONA_AIF1TX_WL_SHIFT | wl;
 
 
+	reconfig = arizona_aif_cfg_changed(codec, base, bclk, lrclk, frame);
+
+	if (reconfig) {
+		/* Save AIF TX/RX state */
+		aif_tx_state = snd_soc_read(codec,
+					    base + ARIZONA_AIF_TX_ENABLES);
+		aif_rx_state = snd_soc_read(codec,
+					    base + ARIZONA_AIF_RX_ENABLES);
+		/* Disable AIF TX/RX before reconfiguring it */
+		regmap_update_bits_async(arizona->regmap,
+				    base + ARIZONA_AIF_TX_ENABLES, 0xff, 0x0);
+		regmap_update_bits(arizona->regmap,
+				    base + ARIZONA_AIF_RX_ENABLES, 0xff, 0x0);
+	}
+
 	ret = arizona_hw_params_rate(substream, params, dai);
 	ret = arizona_hw_params_rate(substream, params, dai);
 	if (ret != 0)
 	if (ret != 0)
-		return ret;
+		goto restore_aif;
 
 
-	regmap_update_bits_async(arizona->regmap,
-				 base + ARIZONA_AIF_BCLK_CTRL,
-				 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
-	regmap_update_bits_async(arizona->regmap,
-				 base + ARIZONA_AIF_TX_BCLK_RATE,
-				 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
-	regmap_update_bits_async(arizona->regmap,
-				 base + ARIZONA_AIF_RX_BCLK_RATE,
-				 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
-	regmap_update_bits_async(arizona->regmap,
-				 base + ARIZONA_AIF_FRAME_CTRL_1,
-				 ARIZONA_AIF1TX_WL_MASK |
-				 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
-	regmap_update_bits(arizona->regmap, base + ARIZONA_AIF_FRAME_CTRL_2,
-			   ARIZONA_AIF1RX_WL_MASK |
-			   ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
+	if (reconfig) {
+		regmap_update_bits_async(arizona->regmap,
+					 base + ARIZONA_AIF_BCLK_CTRL,
+					 ARIZONA_AIF1_BCLK_FREQ_MASK, bclk);
+		regmap_update_bits_async(arizona->regmap,
+					 base + ARIZONA_AIF_TX_BCLK_RATE,
+					 ARIZONA_AIF1TX_BCPF_MASK, lrclk);
+		regmap_update_bits_async(arizona->regmap,
+					 base + ARIZONA_AIF_RX_BCLK_RATE,
+					 ARIZONA_AIF1RX_BCPF_MASK, lrclk);
+		regmap_update_bits_async(arizona->regmap,
+					 base + ARIZONA_AIF_FRAME_CTRL_1,
+					 ARIZONA_AIF1TX_WL_MASK |
+					 ARIZONA_AIF1TX_SLOT_LEN_MASK, frame);
+		regmap_update_bits(arizona->regmap,
+				   base + ARIZONA_AIF_FRAME_CTRL_2,
+				   ARIZONA_AIF1RX_WL_MASK |
+				   ARIZONA_AIF1RX_SLOT_LEN_MASK, frame);
+	}
 
 
-	return 0;
+restore_aif:
+	if (reconfig) {
+		/* Restore AIF TX/RX state */
+		regmap_update_bits_async(arizona->regmap,
+					 base + ARIZONA_AIF_TX_ENABLES,
+					 0xff, aif_tx_state);
+		regmap_update_bits(arizona->regmap,
+				   base + ARIZONA_AIF_RX_ENABLES,
+				   0xff, aif_rx_state);
+	}
+	return ret;
 }
 }
 
 
 static const char *arizona_dai_clk_str(int clk_id)
 static const char *arizona_dai_clk_str(int clk_id)
@@ -1324,9 +1446,63 @@ static int arizona_set_tristate(struct snd_soc_dai *dai, int tristate)
 				   ARIZONA_AIF1_TRI, reg);
 				   ARIZONA_AIF1_TRI, reg);
 }
 }
 
 
+static void arizona_set_channels_to_mask(struct snd_soc_dai *dai,
+					 unsigned int base,
+					 int channels, unsigned int mask)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct arizona *arizona = priv->arizona;
+	int slot, i;
+
+	for (i = 0; i < channels; ++i) {
+		slot = ffs(mask) - 1;
+		if (slot < 0)
+			return;
+
+		regmap_write(arizona->regmap, base + i, slot);
+
+		mask &= ~(1 << slot);
+	}
+
+	if (mask)
+		arizona_aif_warn(dai, "Too many channels in TDM mask\n");
+}
+
+static int arizona_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+				unsigned int rx_mask, int slots, int slot_width)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec);
+	struct arizona *arizona = priv->arizona;
+	int base = dai->driver->base;
+	int rx_max_chan = dai->driver->playback.channels_max;
+	int tx_max_chan = dai->driver->capture.channels_max;
+
+	/* Only support TDM for the physical AIFs */
+	if (dai->id > ARIZONA_MAX_AIF)
+		return -ENOTSUPP;
+
+	if (slots == 0) {
+		tx_mask = (1 << tx_max_chan) - 1;
+		rx_mask = (1 << rx_max_chan) - 1;
+	}
+
+	arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_3,
+				     tx_max_chan, tx_mask);
+	arizona_set_channels_to_mask(dai, base + ARIZONA_AIF_FRAME_CTRL_11,
+				     rx_max_chan, rx_mask);
+
+	arizona->tdm_width[dai->id - 1] = slot_width;
+	arizona->tdm_slots[dai->id - 1] = slots;
+
+	return 0;
+}
+
 const struct snd_soc_dai_ops arizona_dai_ops = {
 const struct snd_soc_dai_ops arizona_dai_ops = {
 	.startup = arizona_startup,
 	.startup = arizona_startup,
 	.set_fmt = arizona_set_fmt,
 	.set_fmt = arizona_set_fmt,
+	.set_tdm_slot = arizona_set_tdm_slot,
 	.hw_params = arizona_hw_params,
 	.hw_params = arizona_hw_params,
 	.set_sysclk = arizona_dai_set_sysclk,
 	.set_sysclk = arizona_dai_set_sysclk,
 	.set_tristate = arizona_set_tristate,
 	.set_tristate = arizona_set_tristate,
@@ -1400,6 +1576,12 @@ static int arizona_validate_fll(struct arizona_fll *fll,
 {
 {
 	unsigned int Fvco_min;
 	unsigned int Fvco_min;
 
 
+	if (fll->fout && Fout != fll->fout) {
+		arizona_fll_err(fll,
+				"Can't change output on active FLL\n");
+		return -EINVAL;
+	}
+
 	if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
 	if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
 		arizona_fll_err(fll,
 		arizona_fll_err(fll,
 				"Can't scale %dMHz in to <=13.5MHz\n",
 				"Can't scale %dMHz in to <=13.5MHz\n",
@@ -1478,6 +1660,10 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
 	while (div <= ARIZONA_FLL_MAX_REFDIV) {
 	while (div <= ARIZONA_FLL_MAX_REFDIV) {
 		for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO;
 		for (ratio = init_ratio; ratio <= ARIZONA_FLL_MAX_FRATIO;
 		     ratio++) {
 		     ratio++) {
+			if ((ARIZONA_FLL_VCO_CORNER / 2) /
+			    (fll->vco_mult * ratio) < Fref)
+				break;
+
 			if (target % (ratio * Fref)) {
 			if (target % (ratio * Fref)) {
 				cfg->refdiv = refdiv;
 				cfg->refdiv = refdiv;
 				cfg->fratio = ratio - 1;
 				cfg->fratio = ratio - 1;
@@ -1485,11 +1671,7 @@ static int arizona_calc_fratio(struct arizona_fll *fll,
 			}
 			}
 		}
 		}
 
 
-		for (ratio = init_ratio - 1; ratio >= 0; ratio--) {
-			if (ARIZONA_FLL_VCO_CORNER / (fll->vco_mult * ratio) <
-			    Fref)
-				break;
-
+		for (ratio = init_ratio - 1; ratio > 0; ratio--) {
 			if (target % (ratio * Fref)) {
 			if (target % (ratio * Fref)) {
 				cfg->refdiv = refdiv;
 				cfg->refdiv = refdiv;
 				cfg->fratio = ratio - 1;
 				cfg->fratio = ratio - 1;
@@ -1616,7 +1798,7 @@ static void arizona_apply_fll(struct arizona *arizona, unsigned int base,
 				 ARIZONA_FLL1_CTRL_UPD | cfg->n);
 				 ARIZONA_FLL1_CTRL_UPD | cfg->n);
 }
 }
 
 
-static bool arizona_is_enabled_fll(struct arizona_fll *fll)
+static int arizona_is_enabled_fll(struct arizona_fll *fll)
 {
 {
 	struct arizona *arizona = fll->arizona;
 	struct arizona *arizona = fll->arizona;
 	unsigned int reg;
 	unsigned int reg;
@@ -1632,13 +1814,26 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll)
 	return reg & ARIZONA_FLL1_ENA;
 	return reg & ARIZONA_FLL1_ENA;
 }
 }
 
 
-static void arizona_enable_fll(struct arizona_fll *fll)
+static int arizona_enable_fll(struct arizona_fll *fll)
 {
 {
 	struct arizona *arizona = fll->arizona;
 	struct arizona *arizona = fll->arizona;
 	int ret;
 	int ret;
 	bool use_sync = false;
 	bool use_sync = false;
+	int already_enabled = arizona_is_enabled_fll(fll);
 	struct arizona_fll_cfg cfg;
 	struct arizona_fll_cfg cfg;
 
 
+	if (already_enabled < 0)
+		return already_enabled;
+
+	if (already_enabled) {
+		/* Facilitate smooth refclk across the transition */
+		regmap_update_bits_async(fll->arizona->regmap, fll->base + 0x7,
+					 ARIZONA_FLL1_GAIN_MASK, 0);
+		regmap_update_bits_async(fll->arizona->regmap, fll->base + 1,
+					 ARIZONA_FLL1_FREERUN,
+					 ARIZONA_FLL1_FREERUN);
+	}
+
 	/*
 	/*
 	 * If we have both REFCLK and SYNCCLK then enable both,
 	 * If we have both REFCLK and SYNCCLK then enable both,
 	 * otherwise apply the SYNCCLK settings to REFCLK.
 	 * otherwise apply the SYNCCLK settings to REFCLK.
@@ -1666,7 +1861,7 @@ static void arizona_enable_fll(struct arizona_fll *fll)
 					 ARIZONA_FLL1_SYNC_ENA, 0);
 					 ARIZONA_FLL1_SYNC_ENA, 0);
 	} else {
 	} else {
 		arizona_fll_err(fll, "No clocks provided\n");
 		arizona_fll_err(fll, "No clocks provided\n");
-		return;
+		return -EINVAL;
 	}
 	}
 
 
 	/*
 	/*
@@ -1681,14 +1876,12 @@ static void arizona_enable_fll(struct arizona_fll *fll)
 					 ARIZONA_FLL1_SYNC_BW,
 					 ARIZONA_FLL1_SYNC_BW,
 					 ARIZONA_FLL1_SYNC_BW);
 					 ARIZONA_FLL1_SYNC_BW);
 
 
-	if (!arizona_is_enabled_fll(fll))
+	if (!already_enabled)
 		pm_runtime_get(arizona->dev);
 		pm_runtime_get(arizona->dev);
 
 
 	/* Clear any pending completions */
 	/* Clear any pending completions */
 	try_wait_for_completion(&fll->ok);
 	try_wait_for_completion(&fll->ok);
 
 
-	regmap_update_bits_async(arizona->regmap, fll->base + 1,
-				 ARIZONA_FLL1_FREERUN, 0);
 	regmap_update_bits_async(arizona->regmap, fll->base + 1,
 	regmap_update_bits_async(arizona->regmap, fll->base + 1,
 				 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
 				 ARIZONA_FLL1_ENA, ARIZONA_FLL1_ENA);
 	if (use_sync)
 	if (use_sync)
@@ -1696,10 +1889,16 @@ static void arizona_enable_fll(struct arizona_fll *fll)
 					 ARIZONA_FLL1_SYNC_ENA,
 					 ARIZONA_FLL1_SYNC_ENA,
 					 ARIZONA_FLL1_SYNC_ENA);
 					 ARIZONA_FLL1_SYNC_ENA);
 
 
+	if (already_enabled)
+		regmap_update_bits_async(arizona->regmap, fll->base + 1,
+					 ARIZONA_FLL1_FREERUN, 0);
+
 	ret = wait_for_completion_timeout(&fll->ok,
 	ret = wait_for_completion_timeout(&fll->ok,
 					  msecs_to_jiffies(250));
 					  msecs_to_jiffies(250));
 	if (ret == 0)
 	if (ret == 0)
 		arizona_fll_warn(fll, "Timed out waiting for lock\n");
 		arizona_fll_warn(fll, "Timed out waiting for lock\n");
+
+	return 0;
 }
 }
 
 
 static void arizona_disable_fll(struct arizona_fll *fll)
 static void arizona_disable_fll(struct arizona_fll *fll)
@@ -1713,6 +1912,8 @@ static void arizona_disable_fll(struct arizona_fll *fll)
 				 ARIZONA_FLL1_ENA, 0, &change);
 				 ARIZONA_FLL1_ENA, 0, &change);
 	regmap_update_bits(arizona->regmap, fll->base + 0x11,
 	regmap_update_bits(arizona->regmap, fll->base + 0x11,
 			   ARIZONA_FLL1_SYNC_ENA, 0);
 			   ARIZONA_FLL1_SYNC_ENA, 0);
+	regmap_update_bits_async(arizona->regmap, fll->base + 1,
+				 ARIZONA_FLL1_FREERUN, 0);
 
 
 	if (change)
 	if (change)
 		pm_runtime_put_autosuspend(arizona->dev);
 		pm_runtime_put_autosuspend(arizona->dev);
@@ -1721,7 +1922,7 @@ static void arizona_disable_fll(struct arizona_fll *fll)
 int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
 int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
 			   unsigned int Fref, unsigned int Fout)
 			   unsigned int Fref, unsigned int Fout)
 {
 {
-	int ret;
+	int ret = 0;
 
 
 	if (fll->ref_src == source && fll->ref_freq == Fref)
 	if (fll->ref_src == source && fll->ref_freq == Fref)
 		return 0;
 		return 0;
@@ -1736,17 +1937,17 @@ int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
 	fll->ref_freq = Fref;
 	fll->ref_freq = Fref;
 
 
 	if (fll->fout && Fref > 0) {
 	if (fll->fout && Fref > 0) {
-		arizona_enable_fll(fll);
+		ret = arizona_enable_fll(fll);
 	}
 	}
 
 
-	return 0;
+	return ret;
 }
 }
 EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
 EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
 
 
 int arizona_set_fll(struct arizona_fll *fll, int source,
 int arizona_set_fll(struct arizona_fll *fll, int source,
 		    unsigned int Fref, unsigned int Fout)
 		    unsigned int Fref, unsigned int Fout)
 {
 {
-	int ret;
+	int ret = 0;
 
 
 	if (fll->sync_src == source &&
 	if (fll->sync_src == source &&
 	    fll->sync_freq == Fref && fll->fout == Fout)
 	    fll->sync_freq == Fref && fll->fout == Fout)
@@ -1768,13 +1969,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
 	fll->sync_freq = Fref;
 	fll->sync_freq = Fref;
 	fll->fout = Fout;
 	fll->fout = Fout;
 
 
-	if (Fout) {
-		arizona_enable_fll(fll);
-	} else {
+	if (Fout)
+		ret = arizona_enable_fll(fll);
+	else
 		arizona_disable_fll(fll);
 		arizona_disable_fll(fll);
-	}
 
 
-	return 0;
+	return ret;
 }
 }
 EXPORT_SYMBOL_GPL(arizona_set_fll);
 EXPORT_SYMBOL_GPL(arizona_set_fll);
 
 

+ 1 - 0
sound/soc/codecs/arizona.h

@@ -249,6 +249,7 @@ extern int arizona_set_fll(struct arizona_fll *fll, int source,
 
 
 extern int arizona_init_spk(struct snd_soc_codec *codec);
 extern int arizona_init_spk(struct snd_soc_codec *codec);
 extern int arizona_init_gpio(struct snd_soc_codec *codec);
 extern int arizona_init_gpio(struct snd_soc_codec *codec);
+extern int arizona_init_mono(struct snd_soc_codec *codec);
 
 
 extern int arizona_init_dai(struct arizona_priv *priv, int dai);
 extern int arizona_init_dai(struct arizona_priv *priv, int dai);
 
 

+ 682 - 0
sound/soc/codecs/cs4265.c

@@ -0,0 +1,682 @@
+/*
+ * cs4265.c -- CS4265 ALSA SoC audio driver
+ *
+ * Copyright 2014 Cirrus Logic, Inc.
+ *
+ * Author: Paul Handrigan <paul.handrigan@cirrus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/gpio/consumer.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include "cs4265.h"
+
+struct cs4265_private {
+	struct device *dev;
+	struct regmap *regmap;
+	struct gpio_desc *reset_gpio;
+	u8 format;
+	u32 sysclk;
+};
+
+static const struct reg_default cs4265_reg_defaults[] = {
+	{ CS4265_PWRCTL, 0x0F },
+	{ CS4265_DAC_CTL, 0x08 },
+	{ CS4265_ADC_CTL, 0x00 },
+	{ CS4265_MCLK_FREQ, 0x00 },
+	{ CS4265_SIG_SEL, 0x40 },
+	{ CS4265_CHB_PGA_CTL, 0x00 },
+	{ CS4265_CHA_PGA_CTL, 0x00 },
+	{ CS4265_ADC_CTL2, 0x19 },
+	{ CS4265_DAC_CHA_VOL, 0x00 },
+	{ CS4265_DAC_CHB_VOL, 0x00 },
+	{ CS4265_DAC_CTL2, 0xC0 },
+	{ CS4265_SPDIF_CTL1, 0x00 },
+	{ CS4265_SPDIF_CTL2, 0x00 },
+	{ CS4265_INT_MASK, 0x00 },
+	{ CS4265_STATUS_MODE_MSB, 0x00 },
+	{ CS4265_STATUS_MODE_LSB, 0x00 },
+};
+
+static bool cs4265_readable_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case CS4265_PWRCTL:
+	case CS4265_DAC_CTL:
+	case CS4265_ADC_CTL:
+	case CS4265_MCLK_FREQ:
+	case CS4265_SIG_SEL:
+	case CS4265_CHB_PGA_CTL:
+	case CS4265_CHA_PGA_CTL:
+	case CS4265_ADC_CTL2:
+	case CS4265_DAC_CHA_VOL:
+	case CS4265_DAC_CHB_VOL:
+	case CS4265_DAC_CTL2:
+	case CS4265_SPDIF_CTL1:
+	case CS4265_SPDIF_CTL2:
+	case CS4265_INT_MASK:
+	case CS4265_STATUS_MODE_MSB:
+	case CS4265_STATUS_MODE_LSB:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool cs4265_volatile_register(struct device *dev, unsigned int reg)
+{
+	switch (reg) {
+	case CS4265_INT_STATUS:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static DECLARE_TLV_DB_SCALE(pga_tlv, -1200, 50, 0);
+
+static DECLARE_TLV_DB_SCALE(dac_tlv, -12750, 50, 0);
+
+static const char * const digital_input_mux_text[] = {
+	"SDIN1", "SDIN2"
+};
+
+static SOC_ENUM_SINGLE_DECL(digital_input_mux_enum, CS4265_SIG_SEL, 7,
+		digital_input_mux_text);
+
+static const struct snd_kcontrol_new digital_input_mux =
+	SOC_DAPM_ENUM("Digital Input Mux", digital_input_mux_enum);
+
+static const char * const mic_linein_text[] = {
+	"MIC", "LINEIN"
+};
+
+static SOC_ENUM_SINGLE_DECL(mic_linein_enum, CS4265_ADC_CTL2, 0,
+		mic_linein_text);
+
+static const char * const cam_mode_text[] = {
+	"One Byte", "Two Byte"
+};
+
+static SOC_ENUM_SINGLE_DECL(cam_mode_enum, CS4265_SPDIF_CTL1, 5,
+		cam_mode_text);
+
+static const char * const cam_mono_stereo_text[] = {
+	"Stereo", "Mono"
+};
+
+static SOC_ENUM_SINGLE_DECL(spdif_mono_stereo_enum, CS4265_SPDIF_CTL2, 2,
+		cam_mono_stereo_text);
+
+static const char * const mono_select_text[] = {
+	"Channel A", "Channel B"
+};
+
+static SOC_ENUM_SINGLE_DECL(spdif_mono_select_enum, CS4265_SPDIF_CTL2, 0,
+		mono_select_text);
+
+static const struct snd_kcontrol_new mic_linein_mux =
+	SOC_DAPM_ENUM("ADC Input Capture Mux", mic_linein_enum);
+
+static const struct snd_kcontrol_new loopback_ctl =
+	SOC_DAPM_SINGLE("Switch", CS4265_SIG_SEL, 1, 1, 0);
+
+static const struct snd_kcontrol_new spdif_switch =
+	SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 0, 0);
+
+static const struct snd_kcontrol_new dac_switch =
+	SOC_DAPM_SINGLE("Switch", CS4265_PWRCTL, 1, 1, 0);
+
+static const struct snd_kcontrol_new cs4265_snd_controls[] = {
+
+	SOC_DOUBLE_R_SX_TLV("PGA Volume", CS4265_CHA_PGA_CTL,
+			      CS4265_CHB_PGA_CTL, 0, 0x28, 0x30, pga_tlv),
+	SOC_DOUBLE_R_TLV("DAC Volume", CS4265_DAC_CHA_VOL,
+		      CS4265_DAC_CHB_VOL, 0, 0xFF, 1, dac_tlv),
+	SOC_SINGLE("De-emp 44.1kHz Switch", CS4265_DAC_CTL, 1,
+				1, 0),
+	SOC_SINGLE("DAC INV Switch", CS4265_DAC_CTL2, 5,
+				1, 0),
+	SOC_SINGLE("DAC Zero Cross Switch", CS4265_DAC_CTL2, 6,
+				1, 0),
+	SOC_SINGLE("DAC Soft Ramp Switch", CS4265_DAC_CTL2, 7,
+				1, 0),
+	SOC_SINGLE("ADC HPF Switch", CS4265_ADC_CTL, 1,
+				1, 0),
+	SOC_SINGLE("ADC Zero Cross Switch", CS4265_ADC_CTL2, 3,
+				1, 1),
+	SOC_SINGLE("ADC Soft Ramp Switch", CS4265_ADC_CTL2, 7,
+				1, 0),
+	SOC_SINGLE("E to F Buffer Disable Switch", CS4265_SPDIF_CTL1,
+				6, 1, 0),
+	SOC_ENUM("C Data Access", cam_mode_enum),
+	SOC_SINGLE("Validity Bit Control Switch", CS4265_SPDIF_CTL2,
+				3, 1, 0),
+	SOC_ENUM("SPDIF Mono/Stereo", spdif_mono_stereo_enum),
+	SOC_SINGLE("MMTLR Data Switch", 0,
+				1, 1, 0),
+	SOC_ENUM("Mono Channel Select", spdif_mono_select_enum),
+	SND_SOC_BYTES("C Data Buffer", CS4265_C_DATA_BUFF, 24),
+};
+
+static const struct snd_soc_dapm_widget cs4265_dapm_widgets[] = {
+
+	SND_SOC_DAPM_INPUT("LINEINL"),
+	SND_SOC_DAPM_INPUT("LINEINR"),
+	SND_SOC_DAPM_INPUT("MICL"),
+	SND_SOC_DAPM_INPUT("MICR"),
+
+	SND_SOC_DAPM_AIF_OUT("DOUT", NULL,  0,
+			SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_OUT("SPDIFOUT", NULL,  0,
+			SND_SOC_NOPM, 0, 0),
+
+	SND_SOC_DAPM_MUX("ADC Mux", SND_SOC_NOPM, 0, 0, &mic_linein_mux),
+
+	SND_SOC_DAPM_ADC("ADC", NULL, CS4265_PWRCTL, 2, 1),
+	SND_SOC_DAPM_PGA("Pre-amp MIC", CS4265_PWRCTL, 3,
+			1, NULL, 0),
+
+	SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM,
+			 0, 0, &digital_input_mux),
+
+	SND_SOC_DAPM_MIXER("SDIN1 Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("SDIN2 Input Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+	SND_SOC_DAPM_MIXER("SPDIF Transmitter", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+	SND_SOC_DAPM_SWITCH("Loopback", SND_SOC_NOPM, 0, 0,
+			&loopback_ctl),
+	SND_SOC_DAPM_SWITCH("SPDIF", SND_SOC_NOPM, 0, 0,
+			&spdif_switch),
+	SND_SOC_DAPM_SWITCH("DAC", CS4265_PWRCTL, 1, 1,
+			&dac_switch),
+
+	SND_SOC_DAPM_AIF_IN("DIN1", NULL,  0,
+			SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("DIN2", NULL,  0,
+			SND_SOC_NOPM, 0, 0),
+	SND_SOC_DAPM_AIF_IN("TXIN", NULL,  0,
+			CS4265_SPDIF_CTL2, 5, 1),
+
+	SND_SOC_DAPM_OUTPUT("LINEOUTL"),
+	SND_SOC_DAPM_OUTPUT("LINEOUTR"),
+
+};
+
+static const struct snd_soc_dapm_route cs4265_audio_map[] = {
+
+	{"DIN1", NULL, "DAI1 Playback"},
+	{"DIN2", NULL, "DAI2 Playback"},
+	{"SDIN1 Input Mixer", NULL, "DIN1"},
+	{"SDIN2 Input Mixer", NULL, "DIN2"},
+	{"Input Mux", "SDIN1", "SDIN1 Input Mixer"},
+	{"Input Mux", "SDIN2", "SDIN2 Input Mixer"},
+	{"DAC", "Switch", "Input Mux"},
+	{"SPDIF", "Switch", "Input Mux"},
+	{"LINEOUTL", NULL, "DAC"},
+	{"LINEOUTR", NULL, "DAC"},
+	{"SPDIFOUT", NULL, "SPDIF"},
+
+	{"ADC Mux", "LINEIN", "LINEINL"},
+	{"ADC Mux", "LINEIN", "LINEINR"},
+	{"ADC Mux", "MIC", "MICL"},
+	{"ADC Mux", "MIC", "MICR"},
+	{"ADC", NULL, "ADC Mux"},
+	{"DOUT", NULL, "ADC"},
+	{"DAI1 Capture", NULL, "DOUT"},
+	{"DAI2 Capture", NULL, "DOUT"},
+
+	/* Loopback */
+	{"Loopback", "Switch", "ADC"},
+	{"DAC", NULL, "Loopback"},
+};
+
+struct cs4265_clk_para {
+	u32 mclk;
+	u32 rate;
+	u8 fm_mode; /* values 1, 2, or 4 */
+	u8 mclkdiv;
+};
+
+static const struct cs4265_clk_para clk_map_table[] = {
+	/*32k*/
+	{8192000, 32000, 0, 0},
+	{12288000, 32000, 0, 1},
+	{16384000, 32000, 0, 2},
+	{24576000, 32000, 0, 3},
+	{32768000, 32000, 0, 4},
+
+	/*44.1k*/
+	{11289600, 44100, 0, 0},
+	{16934400, 44100, 0, 1},
+	{22579200, 44100, 0, 2},
+	{33868000, 44100, 0, 3},
+	{45158400, 44100, 0, 4},
+
+	/*48k*/
+	{12288000, 48000, 0, 0},
+	{18432000, 48000, 0, 1},
+	{24576000, 48000, 0, 2},
+	{36864000, 48000, 0, 3},
+	{49152000, 48000, 0, 4},
+
+	/*64k*/
+	{8192000, 64000, 1, 0},
+	{1228800, 64000, 1, 1},
+	{1693440, 64000, 1, 2},
+	{2457600, 64000, 1, 3},
+	{3276800, 64000, 1, 4},
+
+	/* 88.2k */
+	{11289600, 88200, 1, 0},
+	{16934400, 88200, 1, 1},
+	{22579200, 88200, 1, 2},
+	{33868000, 88200, 1, 3},
+	{45158400, 88200, 1, 4},
+
+	/* 96k */
+	{12288000, 96000, 1, 0},
+	{18432000, 96000, 1, 1},
+	{24576000, 96000, 1, 2},
+	{36864000, 96000, 1, 3},
+	{49152000, 96000, 1, 4},
+
+	/* 128k */
+	{8192000, 128000, 2, 0},
+	{12288000, 128000, 2, 1},
+	{16934400, 128000, 2, 2},
+	{24576000, 128000, 2, 3},
+	{32768000, 128000, 2, 4},
+
+	/* 176.4k */
+	{11289600, 176400, 2, 0},
+	{16934400, 176400, 2, 1},
+	{22579200, 176400, 2, 2},
+	{33868000, 176400, 2, 3},
+	{49152000, 176400, 2, 4},
+
+	/* 192k */
+	{12288000, 192000, 2, 0},
+	{18432000, 192000, 2, 1},
+	{24576000, 192000, 2, 2},
+	{36864000, 192000, 2, 3},
+	{49152000, 192000, 2, 4},
+};
+
+static int cs4265_get_clk_index(int mclk, int rate)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
+		if (clk_map_table[i].rate == rate &&
+				clk_map_table[i].mclk == mclk)
+			return i;
+	}
+	return -EINVAL;
+}
+
+static int cs4265_set_sysclk(struct snd_soc_dai *codec_dai, int clk_id,
+			unsigned int freq, int dir)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
+	int i;
+
+	if (clk_id != 0) {
+		dev_err(codec->dev, "Invalid clk_id %d\n", clk_id);
+		return -EINVAL;
+	}
+	for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
+		if (clk_map_table[i].mclk == freq) {
+			cs4265->sysclk = freq;
+			return 0;
+		}
+	}
+	cs4265->sysclk = 0;
+	dev_err(codec->dev, "Invalid freq parameter %d\n", freq);
+	return -EINVAL;
+}
+
+static int cs4265_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+	struct snd_soc_codec *codec = codec_dai->codec;
+	struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
+	u8 iface = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+	case SND_SOC_DAIFMT_CBM_CFM:
+		snd_soc_update_bits(codec, CS4265_ADC_CTL,
+				CS4265_ADC_MASTER,
+				CS4265_ADC_MASTER);
+		break;
+	case SND_SOC_DAIFMT_CBS_CFS:
+		snd_soc_update_bits(codec, CS4265_ADC_CTL,
+				CS4265_ADC_MASTER,
+				0);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	 /* interface format */
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		iface |= SND_SOC_DAIFMT_I2S;
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		iface |= SND_SOC_DAIFMT_RIGHT_J;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		iface |= SND_SOC_DAIFMT_LEFT_J;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	cs4265->format = iface;
+	return 0;
+}
+
+static int cs4265_digital_mute(struct snd_soc_dai *dai, int mute)
+{
+	struct snd_soc_codec *codec = dai->codec;
+
+	if (mute) {
+		snd_soc_update_bits(codec, CS4265_DAC_CTL,
+			CS4265_DAC_CTL_MUTE,
+			CS4265_DAC_CTL_MUTE);
+		snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
+			CS4265_SPDIF_CTL2_MUTE,
+			CS4265_SPDIF_CTL2_MUTE);
+	} else {
+		snd_soc_update_bits(codec, CS4265_DAC_CTL,
+			CS4265_DAC_CTL_MUTE,
+			0);
+		snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
+			CS4265_SPDIF_CTL2_MUTE,
+			0);
+	}
+	return 0;
+}
+
+static int cs4265_pcm_hw_params(struct snd_pcm_substream *substream,
+				     struct snd_pcm_hw_params *params,
+				     struct snd_soc_dai *dai)
+{
+	struct snd_soc_codec *codec = dai->codec;
+	struct cs4265_private *cs4265 = snd_soc_codec_get_drvdata(codec);
+	int index;
+
+	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
+		((cs4265->format & SND_SOC_DAIFMT_FORMAT_MASK)
+		== SND_SOC_DAIFMT_RIGHT_J))
+		return -EINVAL;
+
+	index = cs4265_get_clk_index(cs4265->sysclk, params_rate(params));
+	if (index >= 0) {
+		snd_soc_update_bits(codec, CS4265_ADC_CTL,
+			CS4265_ADC_FM, clk_map_table[index].fm_mode);
+		snd_soc_update_bits(codec, CS4265_MCLK_FREQ,
+			CS4265_MCLK_FREQ_MASK,
+			clk_map_table[index].mclkdiv);
+
+	} else {
+		dev_err(codec->dev, "can't get correct mclk\n");
+		return -EINVAL;
+	}
+
+	switch (cs4265->format & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		snd_soc_update_bits(codec, CS4265_DAC_CTL,
+			CS4265_DAC_CTL_DIF, (1 << 4));
+		snd_soc_update_bits(codec, CS4265_ADC_CTL,
+			CS4265_ADC_DIF, (1 << 4));
+		snd_soc_update_bits(codec, CS4265_SPDIF_CTL2,
+			CS4265_SPDIF_CTL2_DIF, (1 << 6));
+		break;
+	case SND_SOC_DAIFMT_RIGHT_J:
+		if (params_width(params) == 16) {
+			snd_soc_update_bits(codec, CS4265_DAC_CTL,
+				CS4265_DAC_CTL_DIF, (1 << 5));
+			snd_soc_update_bits(codec, CS4265_ADC_CTL,
+				CS4265_SPDIF_CTL2_DIF, (1 << 7));
+		} else {
+			snd_soc_update_bits(codec, CS4265_DAC_CTL,
+				CS4265_DAC_CTL_DIF, (3 << 5));
+			snd_soc_update_bits(codec, CS4265_ADC_CTL,
+				CS4265_SPDIF_CTL2_DIF, (1 << 7));
+		}
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		snd_soc_update_bits(codec, CS4265_DAC_CTL,
+			CS4265_DAC_CTL_DIF, 0);
+		snd_soc_update_bits(codec, CS4265_ADC_CTL,
+			CS4265_ADC_DIF, 0);
+		snd_soc_update_bits(codec, CS4265_ADC_CTL,
+			CS4265_SPDIF_CTL2_DIF, (1 << 6));
+
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int cs4265_set_bias_level(struct snd_soc_codec *codec,
+					enum snd_soc_bias_level level)
+{
+	switch (level) {
+	case SND_SOC_BIAS_ON:
+		break;
+	case SND_SOC_BIAS_PREPARE:
+		snd_soc_update_bits(codec, CS4265_PWRCTL,
+			CS4265_PWRCTL_PDN, 0);
+		break;
+	case SND_SOC_BIAS_STANDBY:
+		snd_soc_update_bits(codec, CS4265_PWRCTL,
+			CS4265_PWRCTL_PDN,
+			CS4265_PWRCTL_PDN);
+		break;
+	case SND_SOC_BIAS_OFF:
+		snd_soc_update_bits(codec, CS4265_PWRCTL,
+			CS4265_PWRCTL_PDN,
+			CS4265_PWRCTL_PDN);
+		break;
+	}
+	codec->dapm.bias_level = level;
+	return 0;
+}
+
+#define CS4265_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+			SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
+			SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
+			SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
+
+#define CS4265_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \
+			SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_U24_LE)
+
+static const struct snd_soc_dai_ops cs4265_ops = {
+	.hw_params	= cs4265_pcm_hw_params,
+	.digital_mute	= cs4265_digital_mute,
+	.set_fmt	= cs4265_set_fmt,
+	.set_sysclk	= cs4265_set_sysclk,
+};
+
+static struct snd_soc_dai_driver cs4265_dai[] = {
+	{
+		.name = "cs4265-dai1",
+		.playback = {
+			.stream_name = "DAI1 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = CS4265_RATES,
+			.formats = CS4265_FORMATS,
+		},
+		.capture = {
+			.stream_name = "DAI1 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = CS4265_RATES,
+			.formats = CS4265_FORMATS,
+		},
+		.ops = &cs4265_ops,
+	},
+	{
+		.name = "cs4265-dai2",
+		.playback = {
+			.stream_name = "DAI2 Playback",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = CS4265_RATES,
+			.formats = CS4265_FORMATS,
+		},
+		.capture = {
+			.stream_name = "DAI2 Capture",
+			.channels_min = 1,
+			.channels_max = 2,
+			.rates = CS4265_RATES,
+			.formats = CS4265_FORMATS,
+		},
+		.ops = &cs4265_ops,
+	},
+};
+
+static const struct snd_soc_codec_driver soc_codec_cs4265 = {
+	.set_bias_level = cs4265_set_bias_level,
+
+	.dapm_widgets = cs4265_dapm_widgets,
+	.num_dapm_widgets = ARRAY_SIZE(cs4265_dapm_widgets),
+	.dapm_routes = cs4265_audio_map,
+	.num_dapm_routes = ARRAY_SIZE(cs4265_audio_map),
+
+	.controls = cs4265_snd_controls,
+	.num_controls = ARRAY_SIZE(cs4265_snd_controls),
+};
+
+static const struct regmap_config cs4265_regmap = {
+	.reg_bits = 8,
+	.val_bits = 8,
+
+	.max_register = CS4265_MAX_REGISTER,
+	.reg_defaults = cs4265_reg_defaults,
+	.num_reg_defaults = ARRAY_SIZE(cs4265_reg_defaults),
+	.readable_reg = cs4265_readable_register,
+	.volatile_reg = cs4265_volatile_register,
+	.cache_type = REGCACHE_RBTREE,
+};
+
+static int cs4265_i2c_probe(struct i2c_client *i2c_client,
+			     const struct i2c_device_id *id)
+{
+	struct cs4265_private *cs4265;
+	int ret = 0;
+	unsigned int devid = 0;
+	unsigned int reg;
+
+	cs4265 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4265_private),
+			       GFP_KERNEL);
+	if (cs4265 == NULL)
+		return -ENOMEM;
+	cs4265->dev = &i2c_client->dev;
+
+	cs4265->regmap = devm_regmap_init_i2c(i2c_client, &cs4265_regmap);
+	if (IS_ERR(cs4265->regmap)) {
+		ret = PTR_ERR(cs4265->regmap);
+		dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+		return ret;
+	}
+
+	cs4265->reset_gpio = devm_gpiod_get(&i2c_client->dev,
+		"reset-gpios");
+	if (IS_ERR(cs4265->reset_gpio)) {
+		ret = PTR_ERR(cs4265->reset_gpio);
+		if (ret != -ENOENT && ret != -ENOSYS)
+			return ret;
+
+		cs4265->reset_gpio = NULL;
+	} else {
+		ret = gpiod_direction_output(cs4265->reset_gpio, 0);
+		if (ret)
+			return ret;
+		mdelay(1);
+		gpiod_set_value_cansleep(cs4265->reset_gpio, 1);
+
+	}
+
+	i2c_set_clientdata(i2c_client, cs4265);
+
+	ret = regmap_read(cs4265->regmap, CS4265_CHIP_ID, &reg);
+	devid = reg & CS4265_CHIP_ID_MASK;
+	if (devid != CS4265_CHIP_ID_VAL) {
+		ret = -ENODEV;
+		dev_err(&i2c_client->dev,
+			"CS4265 Device ID (%X). Expected %X\n",
+			devid, CS4265_CHIP_ID);
+		return ret;
+	}
+	dev_info(&i2c_client->dev,
+		"CS4265 Version %x\n",
+			reg & CS4265_REV_ID_MASK);
+
+	regmap_write(cs4265->regmap, CS4265_PWRCTL, 0x0F);
+
+	ret =  snd_soc_register_codec(&i2c_client->dev,
+			&soc_codec_cs4265, cs4265_dai,
+			ARRAY_SIZE(cs4265_dai));
+	return ret;
+}
+
+static int cs4265_i2c_remove(struct i2c_client *client)
+{
+	snd_soc_unregister_codec(&client->dev);
+	return 0;
+}
+
+static const struct of_device_id cs4265_of_match[] = {
+	{ .compatible = "cirrus,cs4265", },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, cs4265_of_match);
+
+static const struct i2c_device_id cs4265_id[] = {
+	{ "cs4265", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, cs4265_id);
+
+static struct i2c_driver cs4265_i2c_driver = {
+	.driver = {
+		.name = "cs4265",
+		.owner = THIS_MODULE,
+		.of_match_table = cs4265_of_match,
+	},
+	.id_table = cs4265_id,
+	.probe =    cs4265_i2c_probe,
+	.remove =   cs4265_i2c_remove,
+};
+
+module_i2c_driver(cs4265_i2c_driver);
+
+MODULE_DESCRIPTION("ASoC CS4265 driver");
+MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <paul.handrigan@cirrus.com>");
+MODULE_LICENSE("GPL");

+ 64 - 0
sound/soc/codecs/cs4265.h

@@ -0,0 +1,64 @@
+/*
+ * cs4265.h -- CS4265 ALSA SoC audio driver
+ *
+ * Copyright 2014 Cirrus Logic, Inc.
+ *
+ * Author: Paul Handrigan <paul.handrigan@cirrus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __CS4265_H__
+#define __CS4265_H__
+
+#define CS4265_CHIP_ID				0x1
+#define CS4265_CHIP_ID_VAL			0xD0
+#define CS4265_CHIP_ID_MASK			0xF0
+#define CS4265_REV_ID_MASK			0x0F
+
+#define CS4265_PWRCTL				0x02
+#define CS4265_PWRCTL_PDN			1
+
+#define CS4265_DAC_CTL				0x3
+#define CS4265_DAC_CTL_MUTE			(1 << 2)
+#define CS4265_DAC_CTL_DIF			(3 << 4)
+
+#define CS4265_ADC_CTL				0x4
+#define CS4265_ADC_MASTER			1
+#define CS4265_ADC_DIF				(1 << 4)
+#define CS4265_ADC_FM				(3 << 6)
+
+#define CS4265_MCLK_FREQ			0x5
+#define CS4265_MCLK_FREQ_MASK			(7 << 4)
+
+#define CS4265_SIG_SEL				0x6
+#define CS4265_SIG_SEL_LOOP			(1 << 1)
+
+#define CS4265_CHB_PGA_CTL			0x7
+#define CS4265_CHA_PGA_CTL			0x8
+
+#define CS4265_ADC_CTL2				0x9
+
+#define CS4265_DAC_CHA_VOL			0xA
+#define CS4265_DAC_CHB_VOL			0xB
+
+#define CS4265_DAC_CTL2				0xC
+
+#define CS4265_INT_STATUS			0xD
+#define CS4265_INT_MASK				0xE
+#define CS4265_STATUS_MODE_MSB			0xF
+#define CS4265_STATUS_MODE_LSB			0x10
+
+#define CS4265_SPDIF_CTL1			0x11
+
+#define CS4265_SPDIF_CTL2			0x12
+#define CS4265_SPDIF_CTL2_MUTE			(1 << 4)
+#define CS4265_SPDIF_CTL2_DIF			(3 << 6)
+
+#define CS4265_C_DATA_BUFF			0x13
+#define CS4265_MAX_REGISTER			0x2A
+
+#endif

+ 1 - 3
sound/soc/codecs/cs4270.c

@@ -664,10 +664,8 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
 
 
 	cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private),
 	cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private),
 			      GFP_KERNEL);
 			      GFP_KERNEL);
-	if (!cs4270) {
-		dev_err(&i2c_client->dev, "could not allocate codec\n");
+	if (!cs4270)
 		return -ENOMEM;
 		return -ENOMEM;
-	}
 
 
 	/* get the power supply regulators */
 	/* get the power supply regulators */
 	for (i = 0; i < ARRAY_SIZE(supply_names); i++)
 	for (i = 0; i < ARRAY_SIZE(supply_names); i++)

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно