Browse Source

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (430 commits)
  ALSA: hda - Add quirk for Acer Ferrari 5000
  ALSA: hda - Use cached calls to get widget caps and pin caps
  ALSA: hda - Don't create empty/single-item input source
  ALSA: hda - Fix the wrong pin-cap check in patch_realtek.c
  ALSA: hda - Cache pin-cap values
  ALSA: hda - Avoid output amp manipulation to digital mic pins
  ALSA: hda - Add function id to proc output
  ALSA: pcm - Safer boundary checks
  ALSA: hda - Detect digital-mic inputs on ALC663 / ALC272
  ALSA: sound/ali5451: typo: s/resouces/resources/
  ALSA: hda - Don't show the current connection for power widgets
  ALSA: Fix wrong pointer to dev_err() in arm/pxa2xx-ac97-lib.c
  ASoC: Declare Headset as Mic and Headphone widgets for SDP3430
  ASoC: OMAP: N810: Add more jack functions
  ASoC: OMAP: N810: Mark not connected input pins
  ASoC: Add FLL support for WM8400
  ALSA: hda - Don't reset stream at each prepare callback
  ALSA: hda - Don't reset BDL unnecessarily
  ALSA: pcm - Fix delta calculation at boundary overlap
  ALSA: pcm - Reset invalid position even without debug option
  ...
Linus Torvalds 16 years ago
parent
commit
502012534d
100 changed files with 2969 additions and 1869 deletions
  1. 2 1
      Documentation/DocBook/Makefile
  2. 13 4
      Documentation/DocBook/alsa-driver-api.tmpl
  3. 29 23
      Documentation/DocBook/writing-an-alsa-driver.tmpl
  4. 61 26
      Documentation/sound/alsa/ALSA-Configuration.txt
  5. 18 3
      Documentation/sound/alsa/HD-Audio-Models.txt
  6. 44 3
      Documentation/sound/alsa/HD-Audio.txt
  7. 3 0
      Documentation/sound/alsa/soc/dapm.txt
  8. 0 23
      Documentation/sound/oss/CS4232
  9. 1 1
      Documentation/sound/oss/Introduction
  10. 5 0
      arch/arm/mach-pxa/e740.c
  11. 5 0
      arch/arm/mach-pxa/e750.c
  12. 7 0
      arch/arm/mach-pxa/h5000.c
  13. 15 0
      arch/arm/mach-pxa/include/mach/eseries-gpio.h
  14. 6 1
      arch/arm/mach-pxa/include/mach/regs-ssp.h
  15. 6 0
      arch/arm/mach-pxa/spitz.c
  16. 1 1
      arch/arm/mach-s3c2410/dma.c
  17. 2 2
      arch/arm/mach-s3c2412/dma.c
  18. 1 1
      arch/arm/mach-s3c2440/dma.c
  19. 1 1
      arch/arm/mach-s3c2443/dma.c
  20. 0 0
      arch/arm/plat-s3c/include/plat/audio.h
  21. 5 2
      arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h
  22. 0 0
      arch/arm/plat-s3c24xx/include/plat/regs-iis.h
  23. 4 3
      drivers/media/video/cx88/cx88-alsa.c
  24. 4 3
      drivers/media/video/em28xx/em28xx-audio.c
  25. 4 4
      drivers/media/video/saa7134/saa7134-alsa.c
  26. 4 3
      drivers/staging/go7007/snd-go7007.c
  27. 3 4
      drivers/usb/gadget/gmidi.c
  28. 1 0
      include/linux/input.h
  29. 1 0
      include/linux/mfd/wm8350/audio.h
  30. 1 0
      include/linux/mfd/wm8400-audio.h
  31. 2 0
      include/linux/pci_ids.h
  32. 2 0
      include/sound/ad1816a.h
  33. 79 106
      include/sound/asound.h
  34. 23 0
      include/sound/atmel-abdac.h
  35. 40 0
      include/sound/atmel-ac97c.h
  36. 50 2
      include/sound/control.h
  37. 30 6
      include/sound/core.h
  38. 24 14
      include/sound/hwdep.h
  39. 5 0
      include/sound/jack.h
  40. 1 2
      include/sound/pcm.h
  41. 15 0
      include/sound/pxa2xx-lib.h
  42. 0 1
      include/sound/rawmidi.h
  43. 3 1
      include/sound/sb.h
  44. 6 8
      include/sound/sfnt_info.h
  45. 1 1
      include/sound/soc-dai.h
  46. 27 4
      include/sound/soc-dapm.h
  47. 68 1
      include/sound/soc.h
  48. 0 126
      include/sound/uda1341.h
  49. 1 1
      include/sound/version.h
  50. 1 0
      include/sound/wss.h
  51. 2 0
      sound/Kconfig
  52. 1 1
      sound/Makefile
  53. 2 0
      sound/aoa/aoa-gpio.h
  54. 4 3
      sound/aoa/core/alsa.c
  55. 16 1
      sound/aoa/core/gpio-feature.c
  56. 64 17
      sound/aoa/fabrics/layout.c
  57. 17 5
      sound/aoa/soundbus/i2sbus/core.c
  58. 0 11
      sound/arm/Kconfig
  59. 0 3
      sound/arm/Makefile
  60. 4 3
      sound/arm/aaci.c
  61. 66 5
      sound/arm/pxa2xx-ac97-lib.c
  62. 3 4
      sound/arm/pxa2xx-ac97.c
  63. 0 983
      sound/arm/sa11xx-uda1341.c
  64. 19 0
      sound/atmel/Kconfig
  65. 5 0
      sound/atmel/Makefile
  66. 602 0
      sound/atmel/abdac.c
  67. 932 0
      sound/atmel/ac97c.c
  68. 71 0
      sound/atmel/ac97c.h
  69. 5 4
      sound/core/hwdep.c
  70. 46 43
      sound/core/init.c
  71. 21 24
      sound/core/jack.c
  72. 6 4
      sound/core/misc.c
  73. 31 18
      sound/core/oss/pcm_oss.c
  74. 2 2
      sound/core/oss/pcm_plugin.h
  75. 1 2
      sound/core/pcm.c
  76. 102 53
      sound/core/pcm_lib.c
  77. 3 3
      sound/core/pcm_native.c
  78. 0 6
      sound/core/pcm_timer.c
  79. 195 184
      sound/core/rawmidi.c
  80. 1 1
      sound/core/seq/oss/seq_oss_device.h
  81. 2 1
      sound/core/seq/seq_prioq.c
  82. 43 19
      sound/core/vmaster.c
  83. 4 4
      sound/drivers/dummy.c
  84. 3 3
      sound/drivers/ml403-ac97cr.c
  85. 3 3
      sound/drivers/mpu401/mpu401.c
  86. 10 8
      sound/drivers/mtpav.c
  87. 4 4
      sound/drivers/mts64.c
  88. 1 1
      sound/drivers/opl3/opl3_lib.c
  89. 15 15
      sound/drivers/opl3/opl3_midi.c
  90. 5 3
      sound/drivers/opl3/opl3_oss.c
  91. 1 1
      sound/drivers/opl3/opl3_synth.c
  92. 4 4
      sound/drivers/pcsp/pcsp.c
  93. 3 3
      sound/drivers/portman2x4.c
  94. 15 9
      sound/drivers/serial-u16550.c
  95. 7 5
      sound/drivers/virmidi.c
  96. 2 1
      sound/drivers/vx/vx_core.c
  97. 0 12
      sound/drivers/vx/vx_hwdep.c
  98. 1 1
      sound/drivers/vx/vx_uer.c
  99. 0 2
      sound/i2c/Makefile
  100. 0 8
      sound/i2c/l3/Makefile

+ 2 - 1
Documentation/DocBook/Makefile

@@ -12,7 +12,8 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \
 	    kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
 	    kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \
 	    gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
 	    gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \
 	    genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
 	    genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \
-	    mac80211.xml debugobjects.xml sh.xml regulator.xml
+	    mac80211.xml debugobjects.xml sh.xml regulator.xml \
+	    alsa-driver-api.xml writing-an-alsa-driver.xml
 
 
 ###
 ###
 # The build process is as follows (targets):
 # The build process is as follows (targets):

+ 13 - 4
Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl → Documentation/DocBook/alsa-driver-api.tmpl

@@ -1,11 +1,11 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
-
-<book>
-<?dbhtml filename="index.html">
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
 
 
 <!-- ****************************************************** -->
 <!-- ****************************************************** -->
 <!-- Header  -->
 <!-- Header  -->
 <!-- ****************************************************** -->
 <!-- ****************************************************** -->
+<book id="ALSA-Driver-API">
   <bookinfo>
   <bookinfo>
     <title>The ALSA Driver API</title>
     <title>The ALSA Driver API</title>
 
 
@@ -35,6 +35,8 @@
 
 
   </bookinfo>
   </bookinfo>
 
 
+<toc></toc>
+
   <chapter><title>Management of Cards and Devices</title>
   <chapter><title>Management of Cards and Devices</title>
      <sect1><title>Card Management</title>
      <sect1><title>Card Management</title>
 !Esound/core/init.c
 !Esound/core/init.c
@@ -71,6 +73,10 @@
 !Esound/pci/ac97/ac97_codec.c
 !Esound/pci/ac97/ac97_codec.c
 !Esound/pci/ac97/ac97_pcm.c
 !Esound/pci/ac97/ac97_pcm.c
      </sect1>
      </sect1>
+     <sect1><title>Virtual Master Control API</title>
+!Esound/core/vmaster.c
+!Iinclude/sound/control.h
+     </sect1>
   </chapter>
   </chapter>
   <chapter><title>MIDI API</title>
   <chapter><title>MIDI API</title>
      <sect1><title>Raw MIDI API</title>
      <sect1><title>Raw MIDI API</title>
@@ -88,6 +94,9 @@
   <chapter><title>Miscellaneous Functions</title>
   <chapter><title>Miscellaneous Functions</title>
      <sect1><title>Hardware-Dependent Devices API</title>
      <sect1><title>Hardware-Dependent Devices API</title>
 !Esound/core/hwdep.c
 !Esound/core/hwdep.c
+     </sect1>
+     <sect1><title>Jack Abstraction Layer API</title>
+!Esound/core/jack.c
      </sect1>
      </sect1>
      <sect1><title>ISA DMA Helpers</title>
      <sect1><title>ISA DMA Helpers</title>
 !Esound/core/isadma.c
 !Esound/core/isadma.c

+ 29 - 23
Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl → Documentation/DocBook/writing-an-alsa-driver.tmpl

@@ -1,11 +1,11 @@
-<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook V4.1//EN">
-
-<book>
-<?dbhtml filename="index.html">
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+	"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
 
 
 <!-- ****************************************************** -->
 <!-- ****************************************************** -->
 <!-- Header  -->
 <!-- Header  -->
 <!-- ****************************************************** -->
 <!-- ****************************************************** -->
+<book id="Writing-an-ALSA-Driver">
   <bookinfo>
   <bookinfo>
     <title>Writing an ALSA Driver</title>
     <title>Writing an ALSA Driver</title>
     <author>
     <author>
@@ -492,9 +492,9 @@
           }
           }
 
 
           /* (2) */
           /* (2) */
-          card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-          if (card == NULL)
-                  return -ENOMEM;
+          err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+          if (err < 0)
+                  return err;
 
 
           /* (3) */
           /* (3) */
           err = snd_mychip_create(card, pci, &chip);
           err = snd_mychip_create(card, pci, &chip);
@@ -590,8 +590,9 @@
             <programlisting>
             <programlisting>
 <![CDATA[
 <![CDATA[
   struct snd_card *card;
   struct snd_card *card;
+  int err;
   ....
   ....
-  card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
+  err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
 ]]>
 ]]>
             </programlisting>
             </programlisting>
           </informalexample>
           </informalexample>
@@ -809,26 +810,28 @@
 
 
       <para>
       <para>
         As mentioned above, to create a card instance, call
         As mentioned above, to create a card instance, call
-      <function>snd_card_new()</function>.
+      <function>snd_card_create()</function>.
 
 
         <informalexample>
         <informalexample>
           <programlisting>
           <programlisting>
 <![CDATA[
 <![CDATA[
   struct snd_card *card;
   struct snd_card *card;
-  card = snd_card_new(index, id, module, extra_size);
+  int err;
+  err = snd_card_create(index, id, module, extra_size, &card);
 ]]>
 ]]>
           </programlisting>
           </programlisting>
         </informalexample>
         </informalexample>
       </para>
       </para>
 
 
       <para>
       <para>
-        The function takes four arguments, the card-index number, the
+        The function takes five arguments, the card-index number, the
         id string, the module pointer (usually
         id string, the module pointer (usually
         <constant>THIS_MODULE</constant>),
         <constant>THIS_MODULE</constant>),
-        and the size of extra-data space.  The last argument is used to
+        the size of extra-data space, and the pointer to return the
+        card instance.  The extra_size argument is used to
         allocate card-&gt;private_data for the
         allocate card-&gt;private_data for the
         chip-specific data.  Note that these data
         chip-specific data.  Note that these data
-        are allocated by <function>snd_card_new()</function>.
+        are allocated by <function>snd_card_create()</function>.
       </para>
       </para>
     </section>
     </section>
 
 
@@ -915,15 +918,16 @@
       </para>
       </para>
 
 
       <section id="card-management-chip-specific-snd-card-new">
       <section id="card-management-chip-specific-snd-card-new">
-        <title>1. Allocating via <function>snd_card_new()</function>.</title>
+        <title>1. Allocating via <function>snd_card_create()</function>.</title>
         <para>
         <para>
           As mentioned above, you can pass the extra-data-length
           As mentioned above, you can pass the extra-data-length
-	  to the 4th argument of <function>snd_card_new()</function>, i.e.
+	  to the 4th argument of <function>snd_card_create()</function>, i.e.
 
 
           <informalexample>
           <informalexample>
             <programlisting>
             <programlisting>
 <![CDATA[
 <![CDATA[
-  card = snd_card_new(index[dev], id[dev], THIS_MODULE, sizeof(struct mychip));
+  err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+                        sizeof(struct mychip), &card);
 ]]>
 ]]>
             </programlisting>
             </programlisting>
           </informalexample>
           </informalexample>
@@ -952,8 +956,8 @@
 
 
         <para>
         <para>
           After allocating a card instance via
           After allocating a card instance via
-          <function>snd_card_new()</function> (with
-          <constant>NULL</constant> on the 4th arg), call
+          <function>snd_card_create()</function> (with
+          <constant>0</constant> on the 4th arg), call
           <function>kzalloc()</function>. 
           <function>kzalloc()</function>. 
 
 
           <informalexample>
           <informalexample>
@@ -961,7 +965,7 @@
 <![CDATA[
 <![CDATA[
   struct snd_card *card;
   struct snd_card *card;
   struct mychip *chip;
   struct mychip *chip;
-  card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
+  err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
   .....
   .....
   chip = kzalloc(sizeof(*chip), GFP_KERNEL);
   chip = kzalloc(sizeof(*chip), GFP_KERNEL);
 ]]>
 ]]>
@@ -5750,8 +5754,9 @@ struct _snd_pcm_runtime {
           ....
           ....
           struct snd_card *card;
           struct snd_card *card;
           struct mychip *chip;
           struct mychip *chip;
+          int err;
           ....
           ....
-          card = snd_card_new(index[dev], id[dev], THIS_MODULE, NULL);
+          err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
           ....
           ....
           chip = kzalloc(sizeof(*chip), GFP_KERNEL);
           chip = kzalloc(sizeof(*chip), GFP_KERNEL);
           ....
           ....
@@ -5763,7 +5768,7 @@ struct _snd_pcm_runtime {
       </informalexample>
       </informalexample>
 
 
 	When you created the chip data with
 	When you created the chip data with
-	<function>snd_card_new()</function>, it's anyway accessible
+	<function>snd_card_create()</function>, it's anyway accessible
 	via <structfield>private_data</structfield> field.
 	via <structfield>private_data</structfield> field.
 
 
       <informalexample>
       <informalexample>
@@ -5775,9 +5780,10 @@ struct _snd_pcm_runtime {
           ....
           ....
           struct snd_card *card;
           struct snd_card *card;
           struct mychip *chip;
           struct mychip *chip;
+          int err;
           ....
           ....
-          card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-                              sizeof(struct mychip));
+          err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+                                sizeof(struct mychip), &card);
           ....
           ....
           chip = card->private_data;
           chip = card->private_data;
           ....
           ....

+ 61 - 26
Documentation/sound/alsa/ALSA-Configuration.txt

@@ -346,6 +346,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     sbirq	- IRQ # for CMI8330 chip (SB16)
     sbirq	- IRQ # for CMI8330 chip (SB16)
     sbdma8	- 8bit DMA # for CMI8330 chip (SB16)
     sbdma8	- 8bit DMA # for CMI8330 chip (SB16)
     sbdma16	- 16bit DMA # for CMI8330 chip (SB16)
     sbdma16	- 16bit DMA # for CMI8330 chip (SB16)
+    fmport	- (optional) OPL3 I/O port
+    mpuport	- (optional) MPU401 I/O port
+    mpuirq	- (optional) MPU401 irq #
 
 
     This module supports multiple cards and autoprobe.
     This module supports multiple cards and autoprobe.
 
 
@@ -388,34 +391,11 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
 
     The power-management is supported.
     The power-management is supported.
     
     
-  Module snd-cs4232
-  -----------------
-
-    Module for sound cards based on CS4232/CS4232A ISA chips.
-
-    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
-
-    with isapnp=0, the following options are available:
-
-    port	- port # for CS4232 chip (PnP setup - 0x534)
-    cport	- control port # for CS4232 chip (PnP setup - 0x120,0x210,0xf00)
-    mpu_port	- port # for MPU-401 UART (PnP setup - 0x300), -1 = disable
-    fm_port	- FM port # for CS4232 chip (PnP setup - 0x388), -1 = disable
-    irq		- IRQ # for CS4232 chip (5,7,9,11,12,15)
-    mpu_irq	- IRQ # for MPU-401 UART (9,11,12,15)
-    dma1	- first DMA # for CS4232 chip (0,1,3)
-    dma2	- second DMA # for Yamaha CS4232 chip (0,1,3), -1 = disable
-    
-    This module supports multiple cards. This module does not support autoprobe
-    (if ISA PnP is not used) thus main port must be specified!!! Other ports are
-    optional.
-
-    The power-management is supported.
-    
   Module snd-cs4236
   Module snd-cs4236
   -----------------
   -----------------
 
 
-    Module for sound cards based on CS4235/CS4236/CS4236B/CS4237B/
+    Module for sound cards based on CS4232/CS4232A,
+    	       	     	   	   CS4235/CS4236/CS4236B/CS4237B/
                                    CS4238B/CS4239 ISA chips.
                                    CS4238B/CS4239 ISA chips.
 
 
     isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
     isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
@@ -437,6 +417,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
 
     The power-management is supported.
     The power-management is supported.
 
 
+    This module is aliased as snd-cs4232 since it provides the old
+    snd-cs4232 functionality, too.
+
   Module snd-cs4281
   Module snd-cs4281
   -----------------
   -----------------
 
 
@@ -606,6 +589,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     Module for ESS AudioDrive ES-1688 and ES-688 sound cards.
     Module for ESS AudioDrive ES-1688 and ES-688 sound cards.
 
 
     port	- port # for ES-1688 chip (0x220,0x240,0x260)
     port	- port # for ES-1688 chip (0x220,0x240,0x260)
+    fm_port	- port # for OPL3 (option; share the same port as default)
     mpu_port	- port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
     mpu_port	- port # for MPU-401 port (0x300,0x310,0x320,0x330), -1 = disable (default)
     irq		- IRQ # for ES-1688 chip (5,7,9,10)
     irq		- IRQ # for ES-1688 chip (5,7,9,10)
     mpu_irq	- IRQ # for MPU-401 port (5,7,9,10)
     mpu_irq	- IRQ # for MPU-401 port (5,7,9,10)
@@ -757,6 +741,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     model	- force the model name
     model	- force the model name
     position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF)
     position_fix - Fix DMA pointer (0 = auto, 1 = use LPIB, 2 = POSBUF)
     probe_mask  - Bitmask to probe codecs (default = -1, meaning all slots)
     probe_mask  - Bitmask to probe codecs (default = -1, meaning all slots)
+    		  When the bit 8 (0x100) is set, the lower 8 bits are used
+		  as the "fixed" codec slots; i.e. the driver probes the
+		  slots regardless what hardware reports back
     probe_only	- Only probing and no codec initialization (default=off);
     probe_only	- Only probing and no codec initialization (default=off);
 		  Useful to check the initial codec status for debugging
 		  Useful to check the initial codec status for debugging
     bdl_pos_adj	- Specifies the DMA IRQ timing delay in samples.
     bdl_pos_adj	- Specifies the DMA IRQ timing delay in samples.
@@ -1185,6 +1172,54 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
 
 
     This module supports multiple devices and PnP.
     This module supports multiple devices and PnP.
     
     
+  Module snd-msnd-classic
+  -----------------------
+
+    Module for Turtle Beach MultiSound Classic, Tahiti or Monterey
+    soundcards.
+
+    io		- Port # for msnd-classic card
+    irq		- IRQ # for msnd-classic card
+    mem		- Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000,
+		  0xe0000 or 0xe8000)
+    write_ndelay - enable write ndelay (default = 1)
+    calibrate_signal - calibrate signal (default = 0)
+    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
+    digital	- Digital daughterboard present (default = 0)
+    cfg		- Config port (0x250, 0x260 or 0x270) default = PnP
+    reset	- Reset all devices
+    mpu_io	- MPU401 I/O port
+    mpu_irq	- MPU401 irq#
+    ide_io0	- IDE port #0
+    ide_io1	- IDE port #1
+    ide_irq	- IDE irq#
+    joystick_io	- Joystick I/O port
+
+    The driver requires firmware files "turtlebeach/msndinit.bin" and
+    "turtlebeach/msndperm.bin" in the proper firmware directory.
+
+    See Documentation/sound/oss/MultiSound for important information
+    about this driver.  Note that it has been discontinued, but the 
+    Voyetra Turtle Beach knowledge base entry for it is still available
+    at
+	http://www.turtlebeach.com/site/kb_ftp/790.asp
+
+  Module snd-msnd-pinnacle
+  ------------------------
+
+    Module for Turtle Beach MultiSound Pinnacle/Fiji soundcards.
+
+    io		- Port # for pinnacle/fiji card
+    irq		- IRQ # for pinnalce/fiji card
+    mem		- Memory address (0xb0000, 0xc8000, 0xd0000, 0xd8000,
+		  0xe0000 or 0xe8000)
+    write_ndelay - enable write ndelay (default = 1)
+    calibrate_signal - calibrate signal (default = 0)
+    isapnp	- ISA PnP detection - 0 = disable, 1 = enable (default)
+
+    The driver requires firmware files "turtlebeach/pndspini.bin" and
+    "turtlebeach/pndsperm.bin" in the proper firmware directory.
+
   Module snd-mtpav
   Module snd-mtpav
   ----------------
   ----------------
 
 
@@ -1824,7 +1859,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
   -------------------
   -------------------
 
 
     Module for sound cards based on the Asus AV100/AV200 chips,
     Module for sound cards based on the Asus AV100/AV200 chips,
-    i.e., Xonar D1, DX, D2, D2X and HDAV1.3 (Deluxe).
+    i.e., Xonar D1, DX, D2, D2X, HDAV1.3 (Deluxe), and Essence STX.
 
 
     This module supports autoprobe and multiple cards.
     This module supports autoprobe and multiple cards.
 
 

+ 18 - 3
Documentation/sound/alsa/HD-Audio-Models.txt

@@ -56,6 +56,7 @@ ALC262
   sony-assamd	Sony ASSAMD
   sony-assamd	Sony ASSAMD
   toshiba-s06	Toshiba S06
   toshiba-s06	Toshiba S06
   toshiba-rx1	Toshiba RX1
   toshiba-rx1	Toshiba RX1
+  tyan		Tyan Thunder n6650W (S2915-E)
   ultra		Samsung Q1 Ultra Vista model
   ultra		Samsung Q1 Ultra Vista model
   lenovo-3000	Lenovo 3000 y410
   lenovo-3000	Lenovo 3000 y410
   nec		NEC Versa S9100
   nec		NEC Versa S9100
@@ -261,6 +262,8 @@ Conexant 5051
 =============
 =============
   laptop	Basic Laptop config (default)
   laptop	Basic Laptop config (default)
   hp		HP Spartan laptop
   hp		HP Spartan laptop
+  hp-dv6736	HP dv6736
+  lenovo-x200	Lenovo X200 laptop
 
 
 STAC9200
 STAC9200
 ========
 ========
@@ -278,6 +281,7 @@ STAC9200
   gateway-m4	Gateway laptops with EAPD control
   gateway-m4	Gateway laptops with EAPD control
   gateway-m4-2	Gateway laptops with EAPD control
   gateway-m4-2	Gateway laptops with EAPD control
   panasonic	Panasonic CF-74
   panasonic	Panasonic CF-74
+  auto		BIOS setup (default)
 
 
 STAC9205/9254
 STAC9205/9254
 =============
 =============
@@ -285,6 +289,8 @@ STAC9205/9254
   dell-m42	Dell (unknown)
   dell-m42	Dell (unknown)
   dell-m43	Dell Precision
   dell-m43	Dell Precision
   dell-m44	Dell Inspiron
   dell-m44	Dell Inspiron
+  eapd		Keep EAPD on (e.g. Gateway T1616)
+  auto		BIOS setup (default)
 
 
 STAC9220/9221
 STAC9220/9221
 =============
 =============
@@ -308,6 +314,7 @@ STAC9220/9221
   dell-d82	Dell (unknown)
   dell-d82	Dell (unknown)
   dell-m81	Dell (unknown)
   dell-m81	Dell (unknown)
   dell-m82	Dell XPS M1210
   dell-m82	Dell XPS M1210
+  auto		BIOS setup (default)
 
 
 STAC9202/9250/9251
 STAC9202/9250/9251
 ==================
 ==================
@@ -319,6 +326,7 @@ STAC9202/9250/9251
   m3		Some Gateway MX series laptops
   m3		Some Gateway MX series laptops
   m5		Some Gateway MX series laptops (MP6954)
   m5		Some Gateway MX series laptops (MP6954)
   m6		Some Gateway NX series laptops
   m6		Some Gateway NX series laptops
+  auto		BIOS setup (default)
 
 
 STAC9227/9228/9229/927x
 STAC9227/9228/9229/927x
 =======================
 =======================
@@ -328,6 +336,7 @@ STAC9227/9228/9229/927x
   5stack	D965 5stack + SPDIF
   5stack	D965 5stack + SPDIF
   dell-3stack	Dell Dimension E520
   dell-3stack	Dell Dimension E520
   dell-bios	Fixes with Dell BIOS setup
   dell-bios	Fixes with Dell BIOS setup
+  auto		BIOS setup (default)
 
 
 STAC92HD71B*
 STAC92HD71B*
 ============
 ============
@@ -335,7 +344,10 @@ STAC92HD71B*
   dell-m4-1	Dell desktops
   dell-m4-1	Dell desktops
   dell-m4-2	Dell desktops
   dell-m4-2	Dell desktops
   dell-m4-3	Dell desktops
   dell-m4-3	Dell desktops
-  hp-m4		HP dv laptops
+  hp-m4		HP mini 1000
+  hp-dv5	HP dv series
+  hp-hdx	HP HDX series
+  auto		BIOS setup (default)
 
 
 STAC92HD73*
 STAC92HD73*
 ===========
 ===========
@@ -345,13 +357,16 @@ STAC92HD73*
   dell-m6-dmic	Dell desktops/laptops with digital mics
   dell-m6-dmic	Dell desktops/laptops with digital mics
   dell-m6	Dell desktops/laptops with both type of mics
   dell-m6	Dell desktops/laptops with both type of mics
   dell-eq	Dell desktops/laptops
   dell-eq	Dell desktops/laptops
+  auto		BIOS setup (default)
 
 
 STAC92HD83*
 STAC92HD83*
 ===========
 ===========
   ref		Reference board
   ref		Reference board
   mic-ref	Reference board with power managment for ports
   mic-ref	Reference board with power managment for ports
+  dell-s14	Dell laptop
+  auto		BIOS setup (default)
 
 
 STAC9872
 STAC9872
 ========
 ========
-  vaio		Setup for VAIO FE550G/SZ110
-  vaio-ar Setup for VAIO AR
+  vaio		VAIO laptop without SPDIF
+  auto		BIOS setup (default)

+ 44 - 3
Documentation/sound/alsa/HD-Audio.txt

@@ -109,6 +109,13 @@ slot, pass `probe_mask=1`.  For the first and the third slots, pass
 Since 2.6.29 kernel, the driver has a more robust probing method, so
 Since 2.6.29 kernel, the driver has a more robust probing method, so
 this error might happen rarely, though.
 this error might happen rarely, though.
 
 
+On a machine with a broken BIOS, sometimes you need to force the
+driver to probe the codec slots the hardware doesn't report for use.
+In such a case, turn the bit 8 (0x100) of `probe_mask` option on.
+Then the rest 8 bits are passed as the codec slots to probe
+unconditionally.  For example, `probe_mask=0x103` will force to probe
+the codec slots 0 and 1 no matter what the hardware reports.
+
 
 
 Interrupt Handling
 Interrupt Handling
 ~~~~~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~~~~~
@@ -358,10 +365,26 @@ modelname::
   to this file.
   to this file.
 init_verbs::
 init_verbs::
   The extra verbs to execute at initialization.  You can add a verb by
   The extra verbs to execute at initialization.  You can add a verb by
-  writing to this file.  Pass tree numbers, nid, verb and parameter.
+  writing to this file.  Pass three numbers: nid, verb and parameter
+  (separated with a space).
 hints::
 hints::
-  Shows hint strings for codec parsers for any use.  Right now it's
-  not used.
+  Shows / stores hint strings for codec parsers for any use.
+  Its format is `key = value`.  For example, passing `hp_detect = yes`
+  to IDT/STAC codec parser will result in the disablement of the
+  headphone detection.
+init_pin_configs::
+  Shows the initial pin default config values set by BIOS.
+driver_pin_configs::
+  Shows the pin default values set by the codec parser explicitly.
+  This doesn't show all pin values but only the changed values by
+  the parser.  That is, if the parser doesn't change the pin default
+  config values by itself, this will contain nothing.
+user_pin_configs::
+  Shows the pin default config values to override the BIOS setup.
+  Writing this (with two numbers, NID and value) appends the new
+  value.  The given will be used instead of the initial BIOS value at
+  the next reconfiguration time.  Note that this config will override
+  even the driver pin configs, too.
 reconfig::
 reconfig::
   Triggers the codec re-configuration.  When any value is written to
   Triggers the codec re-configuration.  When any value is written to
   this file, the driver re-initialize and parses the codec tree
   this file, the driver re-initialize and parses the codec tree
@@ -371,6 +394,14 @@ clear::
   Resets the codec, removes the mixer elements and PCM stuff of the
   Resets the codec, removes the mixer elements and PCM stuff of the
   specified codec, and clear all init verbs and hints.
   specified codec, and clear all init verbs and hints.
 
 
+For example, when you want to change the pin default configuration
+value of the pin widget 0x14 to 0x9993013f, and let the driver
+re-configure based on that state, run like below:
+------------------------------------------------------------------------
+  # echo 0x14 0x9993013f > /sys/class/sound/hwC0D0/user_pin_configs
+  # echo 1 > /sys/class/sound/hwC0D0/reconfig  
+------------------------------------------------------------------------
+
 
 
 Power-Saving
 Power-Saving
 ~~~~~~~~~~~~
 ~~~~~~~~~~~~
@@ -461,6 +492,16 @@ run with `--no-upload` option, and attach the generated file.
 There are some other useful options.  See `--help` option output for
 There are some other useful options.  See `--help` option output for
 details.
 details.
 
 
+When a probe error occurs or when the driver obviously assigns a
+mismatched model, it'd be helpful to load the driver with
+`probe_only=1` option (at best after the cold reboot) and run
+alsa-info at this state.  With this option, the driver won't configure
+the mixer and PCM but just tries to probe the codec slot.  After
+probing, the proc file is available, so you can get the raw codec
+information before modified by the driver.  Of course, the driver
+isn't usable with `probe_only=1`.  But you can continue the
+configuration via hwdep sysfs file if hda-reconfig option is enabled.
+
 
 
 hda-verb
 hda-verb
 ~~~~~~~~
 ~~~~~~~~

+ 3 - 0
Documentation/sound/alsa/soc/dapm.txt

@@ -116,6 +116,9 @@ SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
 SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
 SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
 	ARRAY_SIZE(wm8731_output_mixer_controls)),
 	ARRAY_SIZE(wm8731_output_mixer_controls)),
 
 
+If you dont want the mixer elements prefixed with the name of the mixer widget,
+you can use SND_SOC_DAPM_MIXER_NAMED_CTL instead. the parameters are the same
+as for SND_SOC_DAPM_MIXER.
 
 
 2.3 Platform/Machine domain Widgets
 2.3 Platform/Machine domain Widgets
 -----------------------------------
 -----------------------------------

+ 0 - 23
Documentation/sound/oss/CS4232

@@ -1,23 +0,0 @@
-To configure the Crystal CS423x sound chip and activate its DSP functions,
-modules may be loaded in this order:
-  
-	modprobe sound
-	insmod ad1848
-	insmod uart401
-	insmod cs4232 io=* irq=* dma=* dma2=*
-  
-This is the meaning of the parameters:
-  
-	io--I/O address of the Windows Sound System (normally 0x534)
-	irq--IRQ of this device
-	dma and dma2--DMA channels (DMA2 may be 0)
-  
-On some cards, the board attempts to do non-PnP setup, and fails.  If you
-have problems, use Linux' PnP facilities. 
-  
-To get MIDI facilities add
-  
-	insmod opl3 io=*
-  
-where "io" is the I/O address of the OPL3 synthesizer. This will be shown
-in /proc/sys/pnp and is normally 0x388.

+ 1 - 1
Documentation/sound/oss/Introduction

@@ -80,7 +80,7 @@ Notes:
     additional features.
     additional features.
 
 
 2.  The commercial OSS driver may be obtained from the site:
 2.  The commercial OSS driver may be obtained from the site:
-    http://www/opensound.com.  This may be used for cards that
+    http://www.opensound.com.  This may be used for cards that
     are unsupported by the kernel driver, or may be used
     are unsupported by the kernel driver, or may be used
     by other operating systems.  
     by other operating systems.  
 
 

+ 5 - 0
arch/arm/mach-pxa/e740.c

@@ -135,6 +135,11 @@ static unsigned long e740_pin_config[] __initdata = {
 	/* IrDA */
 	/* IrDA */
 	GPIO38_GPIO | MFP_LPM_DRIVE_HIGH,
 	GPIO38_GPIO | MFP_LPM_DRIVE_HIGH,
 
 
+	/* Audio power control */
+	GPIO16_GPIO,  /* AC97 codec AVDD2 supply (analogue power) */
+	GPIO40_GPIO,  /* Mic amp power */
+	GPIO41_GPIO,  /* Headphone amp power */
+
 	/* PC Card */
 	/* PC Card */
 	GPIO8_GPIO,   /* CD0 */
 	GPIO8_GPIO,   /* CD0 */
 	GPIO44_GPIO,  /* CD1 */
 	GPIO44_GPIO,  /* CD1 */

+ 5 - 0
arch/arm/mach-pxa/e750.c

@@ -133,6 +133,11 @@ static unsigned long e750_pin_config[] __initdata = {
 	/* IrDA */
 	/* IrDA */
 	GPIO38_GPIO | MFP_LPM_DRIVE_HIGH,
 	GPIO38_GPIO | MFP_LPM_DRIVE_HIGH,
 
 
+	/* Audio power control */
+	GPIO4_GPIO,  /* Headphone amp power */
+	GPIO7_GPIO,  /* Speaker amp power */
+	GPIO37_GPIO, /* Headphone detect */
+
 	/* PC Card */
 	/* PC Card */
 	GPIO8_GPIO,   /* CD0 */
 	GPIO8_GPIO,   /* CD0 */
 	GPIO44_GPIO,  /* CD1 */
 	GPIO44_GPIO,  /* CD1 */

+ 7 - 0
arch/arm/mach-pxa/h5000.c

@@ -153,6 +153,13 @@ static unsigned long h5000_pin_config[] __initdata = {
 	GPIO23_SSP1_SCLK,
 	GPIO23_SSP1_SCLK,
 	GPIO25_SSP1_TXD,
 	GPIO25_SSP1_TXD,
 	GPIO26_SSP1_RXD,
 	GPIO26_SSP1_RXD,
+
+	/* I2S */
+	GPIO28_I2S_BITCLK_OUT,
+	GPIO29_I2S_SDATA_IN,
+	GPIO30_I2S_SDATA_OUT,
+	GPIO31_I2S_SYNC,
+	GPIO32_I2S_SYSCLK,
 };
 };
 
 
 /*
 /*

+ 15 - 0
arch/arm/mach-pxa/include/mach/eseries-gpio.h

@@ -45,6 +45,21 @@
 /* e7xx IrDA power control */
 /* e7xx IrDA power control */
 #define GPIO_E7XX_IR_OFF         38
 #define GPIO_E7XX_IR_OFF         38
 
 
+/* e740 audio control GPIOs */
+#define GPIO_E740_WM9705_nAVDD2  16
+#define GPIO_E740_MIC_ON         40
+#define GPIO_E740_AMP_ON         41
+
+/* e750 audio control GPIOs */
+#define GPIO_E750_HP_AMP_OFF      4
+#define GPIO_E750_SPK_AMP_OFF     7
+#define GPIO_E750_HP_DETECT      37
+
+/* e800 audio control GPIOs */
+#define GPIO_E800_HP_DETECT      81
+#define GPIO_E800_HP_AMP_OFF     82
+#define GPIO_E800_SPK_AMP_ON     83
+
 /* ASIC related GPIOs */
 /* ASIC related GPIOs */
 #define GPIO_ESERIES_TMIO_IRQ        5
 #define GPIO_ESERIES_TMIO_IRQ        5
 #define GPIO_ESERIES_TMIO_PCLR      19
 #define GPIO_ESERIES_TMIO_PCLR      19

+ 6 - 1
arch/arm/mach-pxa/include/mach/regs-ssp.h

@@ -50,7 +50,7 @@
 #define SSCR0_TUM	(1 << 23)	/* Transmit FIFO underrun interrupt mask */
 #define SSCR0_TUM	(1 << 23)	/* Transmit FIFO underrun interrupt mask */
 #define SSCR0_FRDC	(0x07000000)	/* Frame rate divider control (mask) */
 #define SSCR0_FRDC	(0x07000000)	/* Frame rate divider control (mask) */
 #define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24)	/* Time slots per frame [1..8] */
 #define SSCR0_SlotsPerFrm(x) (((x) - 1) << 24)	/* Time slots per frame [1..8] */
-#define SSCR0_ADC	(1 << 30)	/* Audio clock select */
+#define SSCR0_ACS	(1 << 30)	/* Audio clock select */
 #define SSCR0_MOD	(1 << 31)	/* Mode (normal or network) */
 #define SSCR0_MOD	(1 << 31)	/* Mode (normal or network) */
 #endif
 #endif
 
 
@@ -109,6 +109,11 @@
 #define SSSR_TINT		(1 << 19)	/* Receiver Time-out Interrupt */
 #define SSSR_TINT		(1 << 19)	/* Receiver Time-out Interrupt */
 #define SSSR_PINT		(1 << 18)	/* Peripheral Trailing Byte Interrupt */
 #define SSSR_PINT		(1 << 18)	/* Peripheral Trailing Byte Interrupt */
 
 
+#if defined(CONFIG_PXA3xx)
+#define SSPSP_EDMYSTOP(x)	((x) << 28)     /* Extended Dummy Stop */
+#define SSPSP_EDMYSTRT(x)	((x) << 26)     /* Extended Dummy Start */
+#endif
+
 #define SSPSP_FSRT		(1 << 25)	/* Frame Sync Relative Timing */
 #define SSPSP_FSRT		(1 << 25)	/* Frame Sync Relative Timing */
 #define SSPSP_DMYSTOP(x)	((x) << 23)	/* Dummy Stop */
 #define SSPSP_DMYSTOP(x)	((x) << 23)	/* Dummy Stop */
 #define SSPSP_SFRMWDTH(x)	((x) << 16)	/* Serial Frame Width */
 #define SSPSP_SFRMWDTH(x)	((x) << 16)	/* Serial Frame Width */

+ 6 - 0
arch/arm/mach-pxa/spitz.c

@@ -105,6 +105,12 @@ static unsigned long spitz_pin_config[] __initdata = {
 	GPIO57_nIOIS16,
 	GPIO57_nIOIS16,
 	GPIO104_PSKTSEL,
 	GPIO104_PSKTSEL,
 
 
+	/* I2S */
+	GPIO28_I2S_BITCLK_OUT,
+	GPIO29_I2S_SDATA_IN,
+	GPIO30_I2S_SDATA_OUT,
+	GPIO31_I2S_SYNC,
+
 	/* MMC */
 	/* MMC */
 	GPIO32_MMC_CLK,
 	GPIO32_MMC_CLK,
 	GPIO112_MMC_CMD,
 	GPIO112_MMC_CMD,

+ 1 - 1
arch/arm/mach-s3c2410/dma.c

@@ -28,7 +28,7 @@
 #include <mach/regs-mem.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-sdi.h>
 #include <mach/regs-sdi.h>
-#include <asm/plat-s3c24xx/regs-iis.h>
+#include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 #include <plat/regs-spi.h>
 
 
 static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
 static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {

+ 2 - 2
arch/arm/mach-s3c2412/dma.c

@@ -29,8 +29,8 @@
 #include <mach/regs-mem.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-sdi.h>
 #include <mach/regs-sdi.h>
-#include <asm/plat-s3c24xx/regs-s3c2412-iis.h>
-#include <asm/plat-s3c24xx/regs-iis.h>
+#include <plat/regs-s3c2412-iis.h>
+#include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 #include <plat/regs-spi.h>
 
 
 #define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID }
 #define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID }

+ 1 - 1
arch/arm/mach-s3c2440/dma.c

@@ -28,7 +28,7 @@
 #include <mach/regs-mem.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-sdi.h>
 #include <mach/regs-sdi.h>
-#include <asm/plat-s3c24xx/regs-iis.h>
+#include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 #include <plat/regs-spi.h>
 
 
 static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
 static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {

+ 1 - 1
arch/arm/mach-s3c2443/dma.c

@@ -29,7 +29,7 @@
 #include <mach/regs-mem.h>
 #include <mach/regs-mem.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-lcd.h>
 #include <mach/regs-sdi.h>
 #include <mach/regs-sdi.h>
-#include <asm/plat-s3c24xx/regs-iis.h>
+#include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 #include <plat/regs-spi.h>
 
 
 #define MAP(x) { \
 #define MAP(x) { \

+ 0 - 0
arch/arm/mach-s3c2410/include/mach/audio.h → arch/arm/plat-s3c/include/plat/audio.h


+ 5 - 2
include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h → arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h

@@ -33,6 +33,9 @@
 #define S3C2412_IISCON_RXDMA_ACTIVE	(1 << 1)
 #define S3C2412_IISCON_RXDMA_ACTIVE	(1 << 1)
 #define S3C2412_IISCON_IIS_ACTIVE	(1 << 0)
 #define S3C2412_IISCON_IIS_ACTIVE	(1 << 0)
 
 
+#define S3C64XX_IISMOD_IMS_PCLK		(0 << 10)
+#define S3C64XX_IISMOD_IMS_SYSMUX	(1 << 10)
+
 #define S3C2412_IISMOD_MASTER_INTERNAL	(0 << 10)
 #define S3C2412_IISMOD_MASTER_INTERNAL	(0 << 10)
 #define S3C2412_IISMOD_MASTER_EXTERNAL	(1 << 10)
 #define S3C2412_IISMOD_MASTER_EXTERNAL	(1 << 10)
 #define S3C2412_IISMOD_SLAVE		(2 << 10)
 #define S3C2412_IISMOD_SLAVE		(2 << 10)
@@ -44,8 +47,8 @@
 #define S3C2412_IISMOD_LR_LLOW		(0 << 7)
 #define S3C2412_IISMOD_LR_LLOW		(0 << 7)
 #define S3C2412_IISMOD_LR_RLOW		(1 << 7)
 #define S3C2412_IISMOD_LR_RLOW		(1 << 7)
 #define S3C2412_IISMOD_SDF_IIS		(0 << 5)
 #define S3C2412_IISMOD_SDF_IIS		(0 << 5)
-#define S3C2412_IISMOD_SDF_MSB		(0 << 5)
-#define S3C2412_IISMOD_SDF_LSB		(0 << 5)
+#define S3C2412_IISMOD_SDF_MSB		(1 << 5)
+#define S3C2412_IISMOD_SDF_LSB		(2 << 5)
 #define S3C2412_IISMOD_SDF_MASK		(3 << 5)
 #define S3C2412_IISMOD_SDF_MASK		(3 << 5)
 #define S3C2412_IISMOD_RCLK_256FS	(0 << 3)
 #define S3C2412_IISMOD_RCLK_256FS	(0 << 3)
 #define S3C2412_IISMOD_RCLK_512FS	(1 << 3)
 #define S3C2412_IISMOD_RCLK_512FS	(1 << 3)

+ 0 - 0
include/asm-arm/plat-s3c24xx/regs-iis.h → arch/arm/plat-s3c24xx/include/plat/regs-iis.h


+ 4 - 3
drivers/media/video/cx88/cx88-alsa.c

@@ -803,9 +803,10 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci,
 		return (-ENOENT);
 		return (-ENOENT);
 	}
 	}
 
 
-	card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx88_card_t));
-	if (!card)
-		return (-ENOMEM);
+	err = snd_card_create(index[devno], id[devno], THIS_MODULE,
+			      sizeof(snd_cx88_card_t), &card);
+	if (err < 0)
+		return err;
 
 
 	card->private_free = snd_cx88_dev_free;
 	card->private_free = snd_cx88_dev_free;
 
 

+ 4 - 3
drivers/media/video/em28xx/em28xx-audio.c

@@ -448,9 +448,10 @@ static int em28xx_audio_init(struct em28xx *dev)
 	printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
 	printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus "
 			 "Rechberger\n");
 			 "Rechberger\n");
 
 
-	card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0,
+			      &card);
+	if (err < 0)
+		return err;
 
 
 	spin_lock_init(&adev->slock);
 	spin_lock_init(&adev->slock);
 	err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm);
 	err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm);

+ 4 - 4
drivers/media/video/saa7134/saa7134-alsa.c

@@ -990,10 +990,10 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum)
 	if (!enable[devnum])
 	if (!enable[devnum])
 		return -ENODEV;
 		return -ENODEV;
 
 
-	card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, sizeof(snd_card_saa7134_t));
-
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[devnum], id[devnum], THIS_MODULE,
+			      sizeof(snd_card_saa7134_t), &card);
+	if (err < 0)
+		return err;
 
 
 	strcpy(card->driver, "SAA7134");
 	strcpy(card->driver, "SAA7134");
 
 

+ 4 - 3
drivers/staging/go7007/snd-go7007.c

@@ -248,10 +248,11 @@ int go7007_snd_init(struct go7007 *go)
 	spin_lock_init(&gosnd->lock);
 	spin_lock_init(&gosnd->lock);
 	gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0;
 	gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0;
 	gosnd->capturing = 0;
 	gosnd->capturing = 0;
-	gosnd->card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (gosnd->card == NULL) {
+	ret = snd_card_create(index[dev], id[dev], THIS_MODULE, 0,
+			      &gosnd->card);
+	if (ret < 0) {
 		kfree(gosnd);
 		kfree(gosnd);
-		return -ENOMEM;
+		return ret;
 	}
 	}
 	ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go,
 	ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go,
 			&go7007_snd_device_ops);
 			&go7007_snd_device_ops);

+ 3 - 4
drivers/usb/gadget/gmidi.c

@@ -1099,10 +1099,9 @@ static int gmidi_register_card(struct gmidi_device *dev)
 		.dev_free = gmidi_snd_free,
 		.dev_free = gmidi_snd_free,
 	};
 	};
 
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (!card) {
-		ERROR(dev, "snd_card_new failed\n");
-		err = -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0) {
+		ERROR(dev, "snd_card_create failed\n");
 		goto fail;
 		goto fail;
 	}
 	}
 	dev->card = card;
 	dev->card = card;

+ 1 - 0
include/linux/input.h

@@ -661,6 +661,7 @@ struct input_absinfo {
 #define SW_DOCK			0x05  /* set = plugged into dock */
 #define SW_DOCK			0x05  /* set = plugged into dock */
 #define SW_LINEOUT_INSERT	0x06  /* set = inserted */
 #define SW_LINEOUT_INSERT	0x06  /* set = inserted */
 #define SW_JACK_PHYSICAL_INSERT 0x07  /* set = mechanical switch set */
 #define SW_JACK_PHYSICAL_INSERT 0x07  /* set = mechanical switch set */
+#define SW_VIDEOOUT_INSERT	0x08  /* set = inserted */
 #define SW_MAX			0x0f
 #define SW_MAX			0x0f
 #define SW_CNT			(SW_MAX+1)
 #define SW_CNT			(SW_MAX+1)
 
 

+ 1 - 0
include/linux/mfd/wm8350/audio.h

@@ -490,6 +490,7 @@
 /*
 /*
  * R231 (0xE7) - Jack Status
  * R231 (0xE7) - Jack Status
  */
  */
+#define WM8350_JACK_L_LVL			0x0800
 #define WM8350_JACK_R_LVL                       0x0400
 #define WM8350_JACK_R_LVL                       0x0400
 
 
 /*
 /*

+ 1 - 0
include/linux/mfd/wm8400-audio.h

@@ -1181,6 +1181,7 @@
 #define WM8400_FLL_OUTDIV_SHIFT                      0  /* FLL_OUTDIV - [2:0] */
 #define WM8400_FLL_OUTDIV_SHIFT                      0  /* FLL_OUTDIV - [2:0] */
 #define WM8400_FLL_OUTDIV_WIDTH                      3  /* FLL_OUTDIV - [2:0] */
 #define WM8400_FLL_OUTDIV_WIDTH                      3  /* FLL_OUTDIV - [2:0] */
 
 
+struct wm8400;
 void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400);
 void wm8400_reset_codec_reg_cache(struct wm8400 *wm8400);
 
 
 #endif
 #endif

+ 2 - 0
include/linux/pci_ids.h

@@ -2112,6 +2112,8 @@
 #define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c
 #define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c
 #define PCI_DEVICE_ID_MELLANOX_SINAI	0x6274
 #define PCI_DEVICE_ID_MELLANOX_SINAI	0x6274
 
 
+#define PCI_VENDOR_ID_DFI		0x15bd
+
 #define PCI_VENDOR_ID_QUICKNET		0x15e2
 #define PCI_VENDOR_ID_QUICKNET		0x15e2
 #define PCI_DEVICE_ID_QUICKNET_XJ	0x0500
 #define PCI_DEVICE_ID_QUICKNET_XJ	0x0500
 
 

+ 2 - 0
include/sound/ad1816a.h

@@ -169,5 +169,7 @@ extern int snd_ad1816a_create(struct snd_card *card, unsigned long port,
 
 
 extern int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm);
 extern int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device, struct snd_pcm **rpcm);
 extern int snd_ad1816a_mixer(struct snd_ad1816a *chip);
 extern int snd_ad1816a_mixer(struct snd_ad1816a *chip);
+extern int snd_ad1816a_timer(struct snd_ad1816a *chip, int device,
+			     struct snd_timer **rtimer);
 
 
 #endif	/* __SOUND_AD1816A_H */
 #endif	/* __SOUND_AD1816A_H */

+ 79 - 106
include/sound/asound.h

@@ -126,12 +126,10 @@ struct snd_hwdep_dsp_image {
 	unsigned long driver_data;	/* W: driver-specific data */
 	unsigned long driver_data;	/* W: driver-specific data */
 };
 };
 
 
-enum {
-	SNDRV_HWDEP_IOCTL_PVERSION = _IOR ('H', 0x00, int),
-	SNDRV_HWDEP_IOCTL_INFO = _IOR ('H', 0x01, struct snd_hwdep_info),
-	SNDRV_HWDEP_IOCTL_DSP_STATUS = _IOR('H', 0x02, struct snd_hwdep_dsp_status),
-	SNDRV_HWDEP_IOCTL_DSP_LOAD   = _IOW('H', 0x03, struct snd_hwdep_dsp_image)
-};
+#define SNDRV_HWDEP_IOCTL_PVERSION	_IOR ('H', 0x00, int)
+#define SNDRV_HWDEP_IOCTL_INFO		_IOR ('H', 0x01, struct snd_hwdep_info)
+#define SNDRV_HWDEP_IOCTL_DSP_STATUS	_IOR('H', 0x02, struct snd_hwdep_dsp_status)
+#define SNDRV_HWDEP_IOCTL_DSP_LOAD	_IOW('H', 0x03, struct snd_hwdep_dsp_image)
 
 
 /*****************************************************************************
 /*****************************************************************************
  *                                                                           *
  *                                                                           *
@@ -451,40 +449,35 @@ enum {
 	SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
 	SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
 };
 };
 
 
-enum {
-	SNDRV_PCM_IOCTL_PVERSION = _IOR('A', 0x00, int),
-	SNDRV_PCM_IOCTL_INFO = _IOR('A', 0x01, struct snd_pcm_info),
-	SNDRV_PCM_IOCTL_TSTAMP = _IOW('A', 0x02, int),
-	SNDRV_PCM_IOCTL_TTSTAMP = _IOW('A', 0x03, int),
-	SNDRV_PCM_IOCTL_HW_REFINE = _IOWR('A', 0x10, struct snd_pcm_hw_params),
-	SNDRV_PCM_IOCTL_HW_PARAMS = _IOWR('A', 0x11, struct snd_pcm_hw_params),
-	SNDRV_PCM_IOCTL_HW_FREE = _IO('A', 0x12),
-	SNDRV_PCM_IOCTL_SW_PARAMS = _IOWR('A', 0x13, struct snd_pcm_sw_params),
-	SNDRV_PCM_IOCTL_STATUS = _IOR('A', 0x20, struct snd_pcm_status),
-	SNDRV_PCM_IOCTL_DELAY = _IOR('A', 0x21, snd_pcm_sframes_t),
-	SNDRV_PCM_IOCTL_HWSYNC = _IO('A', 0x22),
-	SNDRV_PCM_IOCTL_SYNC_PTR = _IOWR('A', 0x23, struct snd_pcm_sync_ptr),
-	SNDRV_PCM_IOCTL_CHANNEL_INFO = _IOR('A', 0x32, struct snd_pcm_channel_info),
-	SNDRV_PCM_IOCTL_PREPARE = _IO('A', 0x40),
-	SNDRV_PCM_IOCTL_RESET = _IO('A', 0x41),
-	SNDRV_PCM_IOCTL_START = _IO('A', 0x42),
-	SNDRV_PCM_IOCTL_DROP = _IO('A', 0x43),
-	SNDRV_PCM_IOCTL_DRAIN = _IO('A', 0x44),
-	SNDRV_PCM_IOCTL_PAUSE = _IOW('A', 0x45, int),
-	SNDRV_PCM_IOCTL_REWIND = _IOW('A', 0x46, snd_pcm_uframes_t),
-	SNDRV_PCM_IOCTL_RESUME = _IO('A', 0x47),
-	SNDRV_PCM_IOCTL_XRUN = _IO('A', 0x48),
-	SNDRV_PCM_IOCTL_FORWARD = _IOW('A', 0x49, snd_pcm_uframes_t),
-	SNDRV_PCM_IOCTL_WRITEI_FRAMES = _IOW('A', 0x50, struct snd_xferi),
-	SNDRV_PCM_IOCTL_READI_FRAMES = _IOR('A', 0x51, struct snd_xferi),
-	SNDRV_PCM_IOCTL_WRITEN_FRAMES = _IOW('A', 0x52, struct snd_xfern),
-	SNDRV_PCM_IOCTL_READN_FRAMES = _IOR('A', 0x53, struct snd_xfern),
-	SNDRV_PCM_IOCTL_LINK = _IOW('A', 0x60, int),
-	SNDRV_PCM_IOCTL_UNLINK = _IO('A', 0x61),
-};
-
-/* Trick to make alsa-lib/acinclude.m4 happy */
-#define SNDRV_PCM_IOCTL_REWIND SNDRV_PCM_IOCTL_REWIND
+#define SNDRV_PCM_IOCTL_PVERSION	_IOR('A', 0x00, int)
+#define SNDRV_PCM_IOCTL_INFO		_IOR('A', 0x01, struct snd_pcm_info)
+#define SNDRV_PCM_IOCTL_TSTAMP		_IOW('A', 0x02, int)
+#define SNDRV_PCM_IOCTL_TTSTAMP		_IOW('A', 0x03, int)
+#define SNDRV_PCM_IOCTL_HW_REFINE	_IOWR('A', 0x10, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_PARAMS	_IOWR('A', 0x11, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_FREE		_IO('A', 0x12)
+#define SNDRV_PCM_IOCTL_SW_PARAMS	_IOWR('A', 0x13, struct snd_pcm_sw_params)
+#define SNDRV_PCM_IOCTL_STATUS		_IOR('A', 0x20, struct snd_pcm_status)
+#define SNDRV_PCM_IOCTL_DELAY		_IOR('A', 0x21, snd_pcm_sframes_t)
+#define SNDRV_PCM_IOCTL_HWSYNC		_IO('A', 0x22)
+#define SNDRV_PCM_IOCTL_SYNC_PTR	_IOWR('A', 0x23, struct snd_pcm_sync_ptr)
+#define SNDRV_PCM_IOCTL_CHANNEL_INFO	_IOR('A', 0x32, struct snd_pcm_channel_info)
+#define SNDRV_PCM_IOCTL_PREPARE		_IO('A', 0x40)
+#define SNDRV_PCM_IOCTL_RESET		_IO('A', 0x41)
+#define SNDRV_PCM_IOCTL_START		_IO('A', 0x42)
+#define SNDRV_PCM_IOCTL_DROP		_IO('A', 0x43)
+#define SNDRV_PCM_IOCTL_DRAIN		_IO('A', 0x44)
+#define SNDRV_PCM_IOCTL_PAUSE		_IOW('A', 0x45, int)
+#define SNDRV_PCM_IOCTL_REWIND		_IOW('A', 0x46, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_RESUME		_IO('A', 0x47)
+#define SNDRV_PCM_IOCTL_XRUN		_IO('A', 0x48)
+#define SNDRV_PCM_IOCTL_FORWARD		_IOW('A', 0x49, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_WRITEI_FRAMES	_IOW('A', 0x50, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_READI_FRAMES	_IOR('A', 0x51, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_WRITEN_FRAMES	_IOW('A', 0x52, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_READN_FRAMES	_IOR('A', 0x53, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_LINK		_IOW('A', 0x60, int)
+#define SNDRV_PCM_IOCTL_UNLINK		_IO('A', 0x61)
 
 
 /*****************************************************************************
 /*****************************************************************************
  *                                                                           *
  *                                                                           *
@@ -538,14 +531,12 @@ struct snd_rawmidi_status {
 	unsigned char reserved[16];	/* reserved for future use */
 	unsigned char reserved[16];	/* reserved for future use */
 };
 };
 
 
-enum {
-	SNDRV_RAWMIDI_IOCTL_PVERSION = _IOR('W', 0x00, int),
-	SNDRV_RAWMIDI_IOCTL_INFO = _IOR('W', 0x01, struct snd_rawmidi_info),
-	SNDRV_RAWMIDI_IOCTL_PARAMS = _IOWR('W', 0x10, struct snd_rawmidi_params),
-	SNDRV_RAWMIDI_IOCTL_STATUS = _IOWR('W', 0x20, struct snd_rawmidi_status),
-	SNDRV_RAWMIDI_IOCTL_DROP = _IOW('W', 0x30, int),
-	SNDRV_RAWMIDI_IOCTL_DRAIN = _IOW('W', 0x31, int),
-};
+#define SNDRV_RAWMIDI_IOCTL_PVERSION	_IOR('W', 0x00, int)
+#define SNDRV_RAWMIDI_IOCTL_INFO	_IOR('W', 0x01, struct snd_rawmidi_info)
+#define SNDRV_RAWMIDI_IOCTL_PARAMS	_IOWR('W', 0x10, struct snd_rawmidi_params)
+#define SNDRV_RAWMIDI_IOCTL_STATUS	_IOWR('W', 0x20, struct snd_rawmidi_status)
+#define SNDRV_RAWMIDI_IOCTL_DROP	_IOW('W', 0x30, int)
+#define SNDRV_RAWMIDI_IOCTL_DRAIN	_IOW('W', 0x31, int)
 
 
 /*
 /*
  *  Timer section - /dev/snd/timer
  *  Timer section - /dev/snd/timer
@@ -654,23 +645,21 @@ struct snd_timer_status {
 	unsigned char reserved[64];	/* reserved */
 	unsigned char reserved[64];	/* reserved */
 };
 };
 
 
-enum {
-	SNDRV_TIMER_IOCTL_PVERSION = _IOR('T', 0x00, int),
-	SNDRV_TIMER_IOCTL_NEXT_DEVICE = _IOWR('T', 0x01, struct snd_timer_id),
-	SNDRV_TIMER_IOCTL_TREAD = _IOW('T', 0x02, int),
-	SNDRV_TIMER_IOCTL_GINFO = _IOWR('T', 0x03, struct snd_timer_ginfo),
-	SNDRV_TIMER_IOCTL_GPARAMS = _IOW('T', 0x04, struct snd_timer_gparams),
-	SNDRV_TIMER_IOCTL_GSTATUS = _IOWR('T', 0x05, struct snd_timer_gstatus),
-	SNDRV_TIMER_IOCTL_SELECT = _IOW('T', 0x10, struct snd_timer_select),
-	SNDRV_TIMER_IOCTL_INFO = _IOR('T', 0x11, struct snd_timer_info),
-	SNDRV_TIMER_IOCTL_PARAMS = _IOW('T', 0x12, struct snd_timer_params),
-	SNDRV_TIMER_IOCTL_STATUS = _IOR('T', 0x14, struct snd_timer_status),
-	/* The following four ioctls are changed since 1.0.9 due to confliction */
-	SNDRV_TIMER_IOCTL_START = _IO('T', 0xa0),
-	SNDRV_TIMER_IOCTL_STOP = _IO('T', 0xa1),
-	SNDRV_TIMER_IOCTL_CONTINUE = _IO('T', 0xa2),
-	SNDRV_TIMER_IOCTL_PAUSE = _IO('T', 0xa3),
-};
+#define SNDRV_TIMER_IOCTL_PVERSION	_IOR('T', 0x00, int)
+#define SNDRV_TIMER_IOCTL_NEXT_DEVICE	_IOWR('T', 0x01, struct snd_timer_id)
+#define SNDRV_TIMER_IOCTL_TREAD		_IOW('T', 0x02, int)
+#define SNDRV_TIMER_IOCTL_GINFO		_IOWR('T', 0x03, struct snd_timer_ginfo)
+#define SNDRV_TIMER_IOCTL_GPARAMS	_IOW('T', 0x04, struct snd_timer_gparams)
+#define SNDRV_TIMER_IOCTL_GSTATUS	_IOWR('T', 0x05, struct snd_timer_gstatus)
+#define SNDRV_TIMER_IOCTL_SELECT	_IOW('T', 0x10, struct snd_timer_select)
+#define SNDRV_TIMER_IOCTL_INFO		_IOR('T', 0x11, struct snd_timer_info)
+#define SNDRV_TIMER_IOCTL_PARAMS	_IOW('T', 0x12, struct snd_timer_params)
+#define SNDRV_TIMER_IOCTL_STATUS	_IOR('T', 0x14, struct snd_timer_status)
+/* The following four ioctls are changed since 1.0.9 due to confliction */
+#define SNDRV_TIMER_IOCTL_START		_IO('T', 0xa0)
+#define SNDRV_TIMER_IOCTL_STOP		_IO('T', 0xa1)
+#define SNDRV_TIMER_IOCTL_CONTINUE	_IO('T', 0xa2)
+#define SNDRV_TIMER_IOCTL_PAUSE		_IO('T', 0xa3)
 
 
 struct snd_timer_read {
 struct snd_timer_read {
 	unsigned int resolution;
 	unsigned int resolution;
@@ -847,33 +836,31 @@ struct snd_ctl_tlv {
         unsigned int tlv[0];	/* first TLV */
         unsigned int tlv[0];	/* first TLV */
 };
 };
 
 
-enum {
-	SNDRV_CTL_IOCTL_PVERSION = _IOR('U', 0x00, int),
-	SNDRV_CTL_IOCTL_CARD_INFO = _IOR('U', 0x01, struct snd_ctl_card_info),
-	SNDRV_CTL_IOCTL_ELEM_LIST = _IOWR('U', 0x10, struct snd_ctl_elem_list),
-	SNDRV_CTL_IOCTL_ELEM_INFO = _IOWR('U', 0x11, struct snd_ctl_elem_info),
-	SNDRV_CTL_IOCTL_ELEM_READ = _IOWR('U', 0x12, struct snd_ctl_elem_value),
-	SNDRV_CTL_IOCTL_ELEM_WRITE = _IOWR('U', 0x13, struct snd_ctl_elem_value),
-	SNDRV_CTL_IOCTL_ELEM_LOCK = _IOW('U', 0x14, struct snd_ctl_elem_id),
-	SNDRV_CTL_IOCTL_ELEM_UNLOCK = _IOW('U', 0x15, struct snd_ctl_elem_id),
-	SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS = _IOWR('U', 0x16, int),
-	SNDRV_CTL_IOCTL_ELEM_ADD = _IOWR('U', 0x17, struct snd_ctl_elem_info),
-	SNDRV_CTL_IOCTL_ELEM_REPLACE = _IOWR('U', 0x18, struct snd_ctl_elem_info),
-	SNDRV_CTL_IOCTL_ELEM_REMOVE = _IOWR('U', 0x19, struct snd_ctl_elem_id),
-	SNDRV_CTL_IOCTL_TLV_READ = _IOWR('U', 0x1a, struct snd_ctl_tlv),
-	SNDRV_CTL_IOCTL_TLV_WRITE = _IOWR('U', 0x1b, struct snd_ctl_tlv),
-	SNDRV_CTL_IOCTL_TLV_COMMAND = _IOWR('U', 0x1c, struct snd_ctl_tlv),
-	SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE = _IOWR('U', 0x20, int),
-	SNDRV_CTL_IOCTL_HWDEP_INFO = _IOR('U', 0x21, struct snd_hwdep_info),
-	SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE = _IOR('U', 0x30, int),
-	SNDRV_CTL_IOCTL_PCM_INFO = _IOWR('U', 0x31, struct snd_pcm_info),
-	SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE = _IOW('U', 0x32, int),
-	SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE = _IOWR('U', 0x40, int),
-	SNDRV_CTL_IOCTL_RAWMIDI_INFO = _IOWR('U', 0x41, struct snd_rawmidi_info),
-	SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE = _IOW('U', 0x42, int),
-	SNDRV_CTL_IOCTL_POWER = _IOWR('U', 0xd0, int),
-	SNDRV_CTL_IOCTL_POWER_STATE = _IOR('U', 0xd1, int),
-};
+#define SNDRV_CTL_IOCTL_PVERSION	_IOR('U', 0x00, int)
+#define SNDRV_CTL_IOCTL_CARD_INFO	_IOR('U', 0x01, struct snd_ctl_card_info)
+#define SNDRV_CTL_IOCTL_ELEM_LIST	_IOWR('U', 0x10, struct snd_ctl_elem_list)
+#define SNDRV_CTL_IOCTL_ELEM_INFO	_IOWR('U', 0x11, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_READ	_IOWR('U', 0x12, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_WRITE	_IOWR('U', 0x13, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_LOCK	_IOW('U', 0x14, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_ELEM_UNLOCK	_IOW('U', 0x15, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
+#define SNDRV_CTL_IOCTL_ELEM_ADD	_IOWR('U', 0x17, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REPLACE	_IOWR('U', 0x18, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REMOVE	_IOWR('U', 0x19, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_TLV_READ	_IOWR('U', 0x1a, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_WRITE	_IOWR('U', 0x1b, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_COMMAND	_IOWR('U', 0x1c, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
+#define SNDRV_CTL_IOCTL_HWDEP_INFO	_IOR('U', 0x21, struct snd_hwdep_info)
+#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE	_IOR('U', 0x30, int)
+#define SNDRV_CTL_IOCTL_PCM_INFO	_IOWR('U', 0x31, struct snd_pcm_info)
+#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_INFO	_IOWR('U', 0x41, struct snd_rawmidi_info)
+#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
+#define SNDRV_CTL_IOCTL_POWER		_IOWR('U', 0xd0, int)
+#define SNDRV_CTL_IOCTL_POWER_STATE	_IOR('U', 0xd1, int)
 
 
 /*
 /*
  *  Read interface.
  *  Read interface.
@@ -919,18 +906,4 @@ struct snd_ctl_event {
 #define SNDRV_CTL_NAME_IEC958_PCM_STREAM		"PCM Stream"
 #define SNDRV_CTL_NAME_IEC958_PCM_STREAM		"PCM Stream"
 #define SNDRV_CTL_NAME_IEC958(expl,direction,what)	"IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
 #define SNDRV_CTL_NAME_IEC958(expl,direction,what)	"IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
 
 
-/*
- *
- */
-
-struct snd_xferv {
-	const struct iovec *vector;
-	unsigned long count;
-};
-
-enum {
-	SNDRV_IOCTL_READV = _IOW('K', 0x00, struct snd_xferv),
-	SNDRV_IOCTL_WRITEV = _IOW('K', 0x01, struct snd_xferv),
-};
-
 #endif /* __SOUND_ASOUND_H */
 #endif /* __SOUND_ASOUND_H */

+ 23 - 0
include/sound/atmel-abdac.h

@@ -0,0 +1,23 @@
+/*
+ * Driver for the Atmel Audio Bitstream DAC (ABDAC)
+ *
+ * Copyright (C) 2009 Atmel Corporation
+ *
+ * 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 __INCLUDE_SOUND_ATMEL_ABDAC_H
+#define __INCLUDE_SOUND_ATMEL_ABDAC_H
+
+#include <linux/dw_dmac.h>
+
+/**
+ * struct atmel_abdac_pdata - board specific ABDAC configuration
+ * @dws: DMA slave interface to use for sound playback.
+ */
+struct atmel_abdac_pdata {
+	struct dw_dma_slave	dws;
+};
+
+#endif /* __INCLUDE_SOUND_ATMEL_ABDAC_H */

+ 40 - 0
include/sound/atmel-ac97c.h

@@ -0,0 +1,40 @@
+/*
+ * Driver for the Atmel AC97C controller
+ *
+ * Copyright (C) 2005-2009 Atmel Corporation
+ *
+ * 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 __INCLUDE_SOUND_ATMEL_AC97C_H
+#define __INCLUDE_SOUND_ATMEL_AC97C_H
+
+#include <linux/dw_dmac.h>
+
+#define AC97C_CAPTURE	0x01
+#define AC97C_PLAYBACK	0x02
+#define AC97C_BOTH	(AC97C_CAPTURE | AC97C_PLAYBACK)
+
+/**
+ * struct atmel_ac97c_pdata - board specific AC97C configuration
+ * @rx_dws: DMA slave interface to use for sound capture.
+ * @tx_dws: DMA slave interface to use for sound playback.
+ * @reset_pin: GPIO pin wired to the reset input on the external AC97 codec,
+ *             optional to use, set to -ENODEV if not in use. AC97 layer will
+ *             try to do a software reset of the external codec anyway.
+ * @flags: Flags for which directions should be enabled.
+ *
+ * If the user do not want to use a DMA channel for playback or capture, i.e.
+ * only one feature is required on the board. The slave for playback or capture
+ * can be set to NULL. The AC97C driver will take use of this when setting up
+ * the sound streams.
+ */
+struct ac97c_platform_data {
+	struct dw_dma_slave	rx_dws;
+	struct dw_dma_slave	tx_dws;
+	unsigned int 		flags;
+	int			reset_pin;
+};
+
+#endif /* __INCLUDE_SOUND_ATMEL_AC97C_H */

+ 50 - 2
include/sound/control.h

@@ -171,6 +171,54 @@ int snd_ctl_boolean_stereo_info(struct snd_kcontrol *kcontrol,
  */
  */
 struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
 struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
 						 const unsigned int *tlv);
 						 const unsigned int *tlv);
-int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave);
-		      
+int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
+		       unsigned int flags);
+/* optional flags for slave */
+#define SND_CTL_SLAVE_NEED_UPDATE	(1 << 0)
+
+/**
+ * snd_ctl_add_slave - Add a virtual slave control
+ * @master: vmaster element
+ * @slave: slave element to add
+ *
+ * Add a virtual slave control to the given master element created via
+ * snd_ctl_create_virtual_master() beforehand.
+ * Returns zero if successful or a negative error code.
+ *
+ * All slaves must be the same type (returning the same information
+ * via info callback).  The fucntion doesn't check it, so it's your
+ * responsibility.
+ *
+ * Also, some additional limitations:
+ * at most two channels,
+ * logarithmic volume control (dB level) thus no linear volume,
+ * master can only attenuate the volume without gain
+ */
+static inline int
+snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
+{
+	return _snd_ctl_add_slave(master, slave, 0);
+}
+
+/**
+ * snd_ctl_add_slave_uncached - Add a virtual slave control
+ * @master: vmaster element
+ * @slave: slave element to add
+ *
+ * Add a virtual slave control to the given master.
+ * Unlike snd_ctl_add_slave(), the element added via this function
+ * is supposed to have volatile values, and get callback is called
+ * at each time quried from the master.
+ *
+ * When the control peeks the hardware values directly and the value
+ * can be changed by other means than the put callback of the element,
+ * this function should be used to keep the value always up-to-date.
+ */
+static inline int
+snd_ctl_add_slave_uncached(struct snd_kcontrol *master,
+			   struct snd_kcontrol *slave)
+{
+	return _snd_ctl_add_slave(master, slave, SND_CTL_SLAVE_NEED_UPDATE);
+}
+
 #endif	/* __SOUND_CONTROL_H */
 #endif	/* __SOUND_CONTROL_H */

+ 30 - 6
include/sound/core.h

@@ -97,9 +97,9 @@ struct snd_device {
 
 
 struct snd_monitor_file {
 struct snd_monitor_file {
 	struct file *file;
 	struct file *file;
-	struct snd_monitor_file *next;
 	const struct file_operations *disconnected_f_op;
 	const struct file_operations *disconnected_f_op;
-	struct list_head shutdown_list;
+	struct list_head shutdown_list;	/* still need to shutdown */
+	struct list_head list;	/* link of monitor files */
 };
 };
 
 
 /* main structure for soundcard */
 /* main structure for soundcard */
@@ -134,7 +134,7 @@ struct snd_card {
 	struct snd_info_entry *proc_id;	/* the card id */
 	struct snd_info_entry *proc_id;	/* the card id */
 	struct proc_dir_entry *proc_root_link;	/* number link to real id */
 	struct proc_dir_entry *proc_root_link;	/* number link to real id */
 
 
-	struct snd_monitor_file *files; /* all files associated to this card */
+	struct list_head files_list;	/* all files associated to this card */
 	struct snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown
 	struct snd_shutdown_f_ops *s_f_ops; /* file operations in the shutdown
 								state */
 								state */
 	spinlock_t files_lock;		/* lock the files for this card */
 	spinlock_t files_lock;		/* lock the files for this card */
@@ -296,8 +296,20 @@ int snd_card_locked(int card);
 extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd);
 extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd);
 #endif
 #endif
 
 
+int snd_card_create(int idx, const char *id,
+		    struct module *module, int extra_size,
+		    struct snd_card **card_ret);
+
+static inline __deprecated
 struct snd_card *snd_card_new(int idx, const char *id,
 struct snd_card *snd_card_new(int idx, const char *id,
-			 struct module *module, int extra_size);
+			      struct module *module, int extra_size)
+{
+	struct snd_card *card;
+	if (snd_card_create(idx, id, module, extra_size, &card) < 0)
+		return NULL;
+	return card;
+}
+
 int snd_card_disconnect(struct snd_card *card);
 int snd_card_disconnect(struct snd_card *card);
 int snd_card_free(struct snd_card *card);
 int snd_card_free(struct snd_card *card);
 int snd_card_free_when_closed(struct snd_card *card);
 int snd_card_free_when_closed(struct snd_card *card);
@@ -446,21 +458,33 @@ static inline int __snd_bug_on(int cond)
 struct snd_pci_quirk {
 struct snd_pci_quirk {
 	unsigned short subvendor;	/* PCI subvendor ID */
 	unsigned short subvendor;	/* PCI subvendor ID */
 	unsigned short subdevice;	/* PCI subdevice ID */
 	unsigned short subdevice;	/* PCI subdevice ID */
+	unsigned short subdevice_mask;	/* bitmask to match */
 	int value;			/* value */
 	int value;			/* value */
 #ifdef CONFIG_SND_DEBUG_VERBOSE
 #ifdef CONFIG_SND_DEBUG_VERBOSE
 	const char *name;		/* name of the device (optional) */
 	const char *name;		/* name of the device (optional) */
 #endif
 #endif
 };
 };
 
 
-#define _SND_PCI_QUIRK_ID(vend,dev) \
-	.subvendor = (vend), .subdevice = (dev)
+#define _SND_PCI_QUIRK_ID_MASK(vend, mask, dev)	\
+	.subvendor = (vend), .subdevice = (dev), .subdevice_mask = (mask)
+#define _SND_PCI_QUIRK_ID(vend, dev) \
+	_SND_PCI_QUIRK_ID_MASK(vend, 0xffff, dev)
 #define SND_PCI_QUIRK_ID(vend,dev) {_SND_PCI_QUIRK_ID(vend, dev)}
 #define SND_PCI_QUIRK_ID(vend,dev) {_SND_PCI_QUIRK_ID(vend, dev)}
 #ifdef CONFIG_SND_DEBUG_VERBOSE
 #ifdef CONFIG_SND_DEBUG_VERBOSE
 #define SND_PCI_QUIRK(vend,dev,xname,val) \
 #define SND_PCI_QUIRK(vend,dev,xname,val) \
 	{_SND_PCI_QUIRK_ID(vend, dev), .value = (val), .name = (xname)}
 	{_SND_PCI_QUIRK_ID(vend, dev), .value = (val), .name = (xname)}
+#define SND_PCI_QUIRK_VENDOR(vend, xname, val)			\
+	{_SND_PCI_QUIRK_ID_MASK(vend, 0, 0), .value = (val), .name = (xname)}
+#define SND_PCI_QUIRK_MASK(vend, mask, dev, xname, val)			\
+	{_SND_PCI_QUIRK_ID_MASK(vend, mask, dev),			\
+			.value = (val), .name = (xname)}
 #else
 #else
 #define SND_PCI_QUIRK(vend,dev,xname,val) \
 #define SND_PCI_QUIRK(vend,dev,xname,val) \
 	{_SND_PCI_QUIRK_ID(vend, dev), .value = (val)}
 	{_SND_PCI_QUIRK_ID(vend, dev), .value = (val)}
+#define SND_PCI_QUIRK_MASK(vend, mask, dev, xname, val)			\
+	{_SND_PCI_QUIRK_ID_MASK(vend, mask, dev), .value = (val)}
+#define SND_PCI_QUIRK_VENDOR(vend, xname, val)			\
+	{_SND_PCI_QUIRK_ID_MASK(vend, 0, 0), .value = (val)}
 #endif
 #endif
 
 
 const struct snd_pci_quirk *
 const struct snd_pci_quirk *

+ 24 - 14
include/sound/hwdep.h

@@ -27,18 +27,28 @@
 
 
 struct snd_hwdep;
 struct snd_hwdep;
 
 
+/* hwdep file ops; all ops can be NULL */
 struct snd_hwdep_ops {
 struct snd_hwdep_ops {
-	long long (*llseek) (struct snd_hwdep *hw, struct file * file, long long offset, int orig);
-	long (*read) (struct snd_hwdep *hw, char __user *buf, long count, loff_t *offset);
-	long (*write) (struct snd_hwdep *hw, const char __user *buf, long count, loff_t *offset);
-	int (*open) (struct snd_hwdep * hw, struct file * file);
-	int (*release) (struct snd_hwdep *hw, struct file * file);
-	unsigned int (*poll) (struct snd_hwdep *hw, struct file * file, poll_table * wait);
-	int (*ioctl) (struct snd_hwdep *hw, struct file * file, unsigned int cmd, unsigned long arg);
-	int (*ioctl_compat) (struct snd_hwdep *hw, struct file * file, unsigned int cmd, unsigned long arg);
-	int (*mmap) (struct snd_hwdep *hw, struct file * file, struct vm_area_struct * vma);
-	int (*dsp_status) (struct snd_hwdep *hw, struct snd_hwdep_dsp_status *status);
-	int (*dsp_load) (struct snd_hwdep *hw, struct snd_hwdep_dsp_image *image);
+	long long (*llseek)(struct snd_hwdep *hw, struct file *file,
+			    long long offset, int orig);
+	long (*read)(struct snd_hwdep *hw, char __user *buf,
+		     long count, loff_t *offset);
+	long (*write)(struct snd_hwdep *hw, const char __user *buf,
+		      long count, loff_t *offset);
+	int (*open)(struct snd_hwdep *hw, struct file * file);
+	int (*release)(struct snd_hwdep *hw, struct file * file);
+	unsigned int (*poll)(struct snd_hwdep *hw, struct file *file,
+			     poll_table *wait);
+	int (*ioctl)(struct snd_hwdep *hw, struct file *file,
+		     unsigned int cmd, unsigned long arg);
+	int (*ioctl_compat)(struct snd_hwdep *hw, struct file *file,
+			    unsigned int cmd, unsigned long arg);
+	int (*mmap)(struct snd_hwdep *hw, struct file *file,
+		    struct vm_area_struct *vma);
+	int (*dsp_status)(struct snd_hwdep *hw,
+			  struct snd_hwdep_dsp_status *status);
+	int (*dsp_load)(struct snd_hwdep *hw,
+			struct snd_hwdep_dsp_image *image);
 };
 };
 
 
 struct snd_hwdep {
 struct snd_hwdep {
@@ -61,9 +71,9 @@ struct snd_hwdep {
 	void (*private_free) (struct snd_hwdep *hwdep);
 	void (*private_free) (struct snd_hwdep *hwdep);
 
 
 	struct mutex open_mutex;
 	struct mutex open_mutex;
-	int used;
-	unsigned int dsp_loaded;
-	unsigned int exclusive: 1;
+	int used;			/* reference counter */
+	unsigned int dsp_loaded;	/* bit fields of loaded dsp indices */
+	unsigned int exclusive:1;	/* exclusive access mode */
 };
 };
 
 
 extern int snd_hwdep_new(struct snd_card *card, char *id, int device,
 extern int snd_hwdep_new(struct snd_card *card, char *id, int device,

+ 5 - 0
include/sound/jack.h

@@ -30,6 +30,9 @@ struct input_dev;
 /**
 /**
  * Jack types which can be reported.  These values are used as a
  * Jack types which can be reported.  These values are used as a
  * bitmask.
  * bitmask.
+ *
+ * Note that this must be kept in sync with the lookup table in
+ * sound/core/jack.c.
  */
  */
 enum snd_jack_types {
 enum snd_jack_types {
 	SND_JACK_HEADPHONE	= 0x0001,
 	SND_JACK_HEADPHONE	= 0x0001,
@@ -37,6 +40,8 @@ enum snd_jack_types {
 	SND_JACK_HEADSET	= SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
 	SND_JACK_HEADSET	= SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
 	SND_JACK_LINEOUT	= 0x0004,
 	SND_JACK_LINEOUT	= 0x0004,
 	SND_JACK_MECHANICAL	= 0x0008, /* If detected separately */
 	SND_JACK_MECHANICAL	= 0x0008, /* If detected separately */
+	SND_JACK_VIDEOOUT	= 0x0010,
+	SND_JACK_AVOUT		= SND_JACK_LINEOUT | SND_JACK_VIDEOOUT,
 };
 };
 
 
 struct snd_jack {
 struct snd_jack {

+ 1 - 2
include/sound/pcm.h

@@ -364,7 +364,6 @@ struct snd_pcm_substream {
         /* -- timer section -- */
         /* -- timer section -- */
 	struct snd_timer *timer;		/* timer */
 	struct snd_timer *timer;		/* timer */
 	unsigned timer_running: 1;	/* time is running */
 	unsigned timer_running: 1;	/* time is running */
-	spinlock_t timer_lock;
 	/* -- next substream -- */
 	/* -- next substream -- */
 	struct snd_pcm_substream *next;
 	struct snd_pcm_substream *next;
 	/* -- linked substreams -- */
 	/* -- linked substreams -- */
@@ -451,7 +450,7 @@ struct snd_pcm_notify {
 
 
 extern const struct file_operations snd_pcm_f_ops[2];
 extern const struct file_operations snd_pcm_f_ops[2];
 
 
-int snd_pcm_new(struct snd_card *card, char *id, int device,
+int snd_pcm_new(struct snd_card *card, const char *id, int device,
 		int playback_count, int capture_count,
 		int playback_count, int capture_count,
 		struct snd_pcm **rpcm);
 		struct snd_pcm **rpcm);
 int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count);
 int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count);

+ 15 - 0
include/sound/pxa2xx-lib.h

@@ -42,4 +42,19 @@ extern int pxa2xx_ac97_hw_resume(void);
 extern int pxa2xx_ac97_hw_probe(struct platform_device *dev);
 extern int pxa2xx_ac97_hw_probe(struct platform_device *dev);
 extern void pxa2xx_ac97_hw_remove(struct platform_device *dev);
 extern void pxa2xx_ac97_hw_remove(struct platform_device *dev);
 
 
+/* AC97 platform_data */
+/**
+ * struct pxa2xx_ac97_platform_data - pxa ac97 platform data
+ * @reset_gpio: AC97 reset gpio (normally gpio113 or gpio95)
+ *              a -1 value means no gpio will be used for reset
+ *
+ * Platform data should only be specified for pxa27x CPUs where a silicon bug
+ * prevents correct operation of the reset line. If not specified, the default
+ * behaviour is to consider gpio 113 as the AC97 reset line, which is the
+ * default on most boards.
+ */
+struct pxa2xx_ac97_platform_data {
+	int reset_gpio;
+};
+
 #endif
 #endif

+ 0 - 1
include/sound/rawmidi.h

@@ -42,7 +42,6 @@
 #define SNDRV_RAWMIDI_LFLG_INPUT	(1<<1)
 #define SNDRV_RAWMIDI_LFLG_INPUT	(1<<1)
 #define SNDRV_RAWMIDI_LFLG_OPEN		(3<<0)
 #define SNDRV_RAWMIDI_LFLG_OPEN		(3<<0)
 #define SNDRV_RAWMIDI_LFLG_APPEND	(1<<2)
 #define SNDRV_RAWMIDI_LFLG_APPEND	(1<<2)
-#define	SNDRV_RAWMIDI_LFLG_NOOPENLOCK	(1<<3)
 
 
 struct snd_rawmidi;
 struct snd_rawmidi;
 struct snd_rawmidi_substream;
 struct snd_rawmidi_substream;

+ 3 - 1
include/sound/sb.h

@@ -249,6 +249,7 @@ struct snd_sb {
 #define SB_ALS4000_3D_AUTO_MUTE	0x52
 #define SB_ALS4000_3D_AUTO_MUTE	0x52
 #define SB_ALS4000_ANALOG_BLOCK_CTRL 0x53
 #define SB_ALS4000_ANALOG_BLOCK_CTRL 0x53
 #define SB_ALS4000_3D_DELAYLINE_PATTERN 0x54
 #define SB_ALS4000_3D_DELAYLINE_PATTERN 0x54
+#define SB_ALS4000_CR3_CONFIGURATION	0xc3 /* bit 7 is Digital Loop Enable */
 #define SB_ALS4000_QSOUND	0xdb
 #define SB_ALS4000_QSOUND	0xdb
 
 
 /* IRQ setting bitmap */
 /* IRQ setting bitmap */
@@ -330,7 +331,8 @@ enum {
 	SB_MIX_DOUBLE,
 	SB_MIX_DOUBLE,
 	SB_MIX_INPUT_SW,
 	SB_MIX_INPUT_SW,
 	SB_MIX_CAPTURE_PRO,
 	SB_MIX_CAPTURE_PRO,
-	SB_MIX_CAPTURE_DT019X
+	SB_MIX_CAPTURE_DT019X,
+	SB_MIX_MONO_CAPTURE_ALS4K
 };
 };
 
 
 #define SB_MIXVAL_DOUBLE(left_reg, right_reg, left_shift, right_shift, mask) \
 #define SB_MIXVAL_DOUBLE(left_reg, right_reg, left_shift, right_shift, mask) \

+ 6 - 8
include/sound/sfnt_info.h

@@ -202,13 +202,11 @@ struct snd_emux_misc_mode {
 	int value2;	/* reserved */
 	int value2;	/* reserved */
 };
 };
 
 
-enum {
-	SNDRV_EMUX_IOCTL_VERSION = _IOR('H', 0x80, unsigned int),
-	SNDRV_EMUX_IOCTL_LOAD_PATCH = _IOWR('H', 0x81, struct soundfont_patch_info),
-	SNDRV_EMUX_IOCTL_RESET_SAMPLES = _IO('H', 0x82),
-	SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES = _IO('H', 0x83),
-	SNDRV_EMUX_IOCTL_MEM_AVAIL = _IOW('H', 0x84, int),
-	SNDRV_EMUX_IOCTL_MISC_MODE = _IOWR('H', 0x84, struct snd_emux_misc_mode),
-};
+#define SNDRV_EMUX_IOCTL_VERSION	_IOR('H', 0x80, unsigned int)
+#define SNDRV_EMUX_IOCTL_LOAD_PATCH	_IOWR('H', 0x81, struct soundfont_patch_info)
+#define SNDRV_EMUX_IOCTL_RESET_SAMPLES	_IO('H', 0x82)
+#define SNDRV_EMUX_IOCTL_REMOVE_LAST_SAMPLES _IO('H', 0x83)
+#define SNDRV_EMUX_IOCTL_MEM_AVAIL	_IOW('H', 0x84, int)
+#define SNDRV_EMUX_IOCTL_MISC_MODE	_IOWR('H', 0x84, struct snd_emux_misc_mode)
 
 
 #endif /* __SOUND_SFNT_INFO_H */
 #endif /* __SOUND_SFNT_INFO_H */

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

@@ -203,7 +203,7 @@ struct snd_soc_dai {
 	int (*resume)(struct snd_soc_dai *dai);
 	int (*resume)(struct snd_soc_dai *dai);
 
 
 	/* ops */
 	/* ops */
-	struct snd_soc_dai_ops ops;
+	struct snd_soc_dai_ops *ops;
 
 
 	/* DAI capabilities */
 	/* DAI capabilities */
 	struct snd_soc_pcm_stream capture;
 	struct snd_soc_pcm_stream capture;

+ 27 - 4
include/sound/soc-dapm.h

@@ -76,6 +76,11 @@
 	 wcontrols, wncontrols)\
 	 wcontrols, wncontrols)\
 {	.id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
 {	.id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
 	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols}
 	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols}
+#define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \
+	 wcontrols, wncontrols)\
+{       .id = snd_soc_dapm_mixer_named_ctl, .name = wname, .reg = wreg, \
+	.shift = wshift, .invert = winvert, .kcontrols = wcontrols, \
+	.num_kcontrols = wncontrols}
 #define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \
 #define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \
 {	.id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
 {	.id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
 	.invert = winvert, .kcontrols = NULL, .num_kcontrols = 0}
 	.invert = winvert, .kcontrols = NULL, .num_kcontrols = 0}
@@ -101,6 +106,11 @@
 {	.id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
 {	.id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
 	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \
 	.invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \
 	.event = wevent, .event_flags = wflags}
 	.event = wevent, .event_flags = wflags}
+#define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \
+	wcontrols, wncontrols, wevent, wflags) \
+{       .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
+	.invert = winvert, .kcontrols = wcontrols, \
+	.num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags}
 #define SND_SOC_DAPM_MICBIAS_E(wname, wreg, wshift, winvert, wevent, wflags) \
 #define SND_SOC_DAPM_MICBIAS_E(wname, wreg, wshift, winvert, wevent, wflags) \
 {	.id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
 {	.id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
 	.invert = winvert, .kcontrols = NULL, .num_kcontrols = 0, \
 	.invert = winvert, .kcontrols = NULL, .num_kcontrols = 0, \
@@ -182,6 +192,12 @@
 	.get = snd_soc_dapm_get_value_enum_double, \
 	.get = snd_soc_dapm_get_value_enum_double, \
 	.put = snd_soc_dapm_put_value_enum_double, \
 	.put = snd_soc_dapm_put_value_enum_double, \
 	.private_value = (unsigned long)&xenum }
 	.private_value = (unsigned long)&xenum }
+#define SOC_DAPM_PIN_SWITCH(xname) \
+{	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname " Switch", \
+	.info = snd_soc_dapm_info_pin_switch, \
+	.get = snd_soc_dapm_get_pin_switch, \
+	.put = snd_soc_dapm_put_pin_switch, \
+	.private_value = (unsigned long)xname }
 
 
 /* dapm stream operations */
 /* dapm stream operations */
 #define SND_SOC_DAPM_STREAM_NOP			0x0
 #define SND_SOC_DAPM_STREAM_NOP			0x0
@@ -228,6 +244,12 @@ int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
 	struct snd_ctl_elem_value *ucontrol);
 int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
 int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
 	struct snd_ctl_elem_value *ucontrol);
+int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_info *uinfo);
+int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *uncontrol);
+int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
+	struct snd_ctl_elem_value *uncontrol);
 int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
 int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
 	const struct snd_soc_dapm_widget *widget);
 	const struct snd_soc_dapm_widget *widget);
 int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
 int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
@@ -250,10 +272,10 @@ int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
 int snd_soc_dapm_sys_add(struct device *dev);
 int snd_soc_dapm_sys_add(struct device *dev);
 
 
 /* dapm audio pin control and status */
 /* dapm audio pin control and status */
-int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin);
-int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin);
-int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin);
-int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin);
+int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin);
+int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin);
+int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin);
+int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin);
 int snd_soc_dapm_sync(struct snd_soc_codec *codec);
 int snd_soc_dapm_sync(struct snd_soc_codec *codec);
 
 
 /* dapm widget types */
 /* dapm widget types */
@@ -263,6 +285,7 @@ enum snd_soc_dapm_type {
 	snd_soc_dapm_mux,			/* selects 1 analog signal from many inputs */
 	snd_soc_dapm_mux,			/* selects 1 analog signal from many inputs */
 	snd_soc_dapm_value_mux,			/* selects 1 analog signal from many inputs */
 	snd_soc_dapm_value_mux,			/* selects 1 analog signal from many inputs */
 	snd_soc_dapm_mixer,			/* mixes several analog signals together */
 	snd_soc_dapm_mixer,			/* mixes several analog signals together */
+	snd_soc_dapm_mixer_named_ctl,		/* mixer with named controls */
 	snd_soc_dapm_pga,			/* programmable gain/attenuation (volume) */
 	snd_soc_dapm_pga,			/* programmable gain/attenuation (volume) */
 	snd_soc_dapm_adc,			/* analog to digital converter */
 	snd_soc_dapm_adc,			/* analog to digital converter */
 	snd_soc_dapm_dac,			/* digital to analog converter */
 	snd_soc_dapm_dac,			/* digital to analog converter */

+ 68 - 1
include/sound/soc.h

@@ -16,6 +16,8 @@
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
 #include <sound/core.h>
 #include <sound/core.h>
 #include <sound/pcm.h>
 #include <sound/pcm.h>
 #include <sound/control.h>
 #include <sound/control.h>
@@ -154,6 +156,8 @@ enum snd_soc_bias_level {
 	SND_SOC_BIAS_OFF,
 	SND_SOC_BIAS_OFF,
 };
 };
 
 
+struct snd_jack;
+struct snd_soc_card;
 struct snd_soc_device;
 struct snd_soc_device;
 struct snd_soc_pcm_stream;
 struct snd_soc_pcm_stream;
 struct snd_soc_ops;
 struct snd_soc_ops;
@@ -164,6 +168,11 @@ struct snd_soc_platform;
 struct snd_soc_codec;
 struct snd_soc_codec;
 struct soc_enum;
 struct soc_enum;
 struct snd_soc_ac97_ops;
 struct snd_soc_ac97_ops;
+struct snd_soc_jack;
+struct snd_soc_jack_pin;
+#ifdef CONFIG_GPIOLIB
+struct snd_soc_jack_gpio;
+#endif
 
 
 typedef int (*hw_write_t)(void *,const char* ,int);
 typedef int (*hw_write_t)(void *,const char* ,int);
 typedef int (*hw_read_t)(void *,char* ,int);
 typedef int (*hw_read_t)(void *,char* ,int);
@@ -184,6 +193,19 @@ int snd_soc_init_card(struct snd_soc_device *socdev);
 int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
 int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
 	const struct snd_pcm_hardware *hw);
 	const struct snd_pcm_hardware *hw);
 
 
+/* Jack reporting */
+int snd_soc_jack_new(struct snd_soc_card *card, const char *id, int type,
+		     struct snd_soc_jack *jack);
+void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask);
+int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
+			  struct snd_soc_jack_pin *pins);
+#ifdef CONFIG_GPIOLIB
+int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
+			struct snd_soc_jack_gpio *gpios);
+void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
+			struct snd_soc_jack_gpio *gpios);
+#endif
+
 /* codec IO */
 /* codec IO */
 #define snd_soc_read(codec, reg) codec->read(codec, reg)
 #define snd_soc_read(codec, reg) codec->read(codec, reg)
 #define snd_soc_write(codec, reg, value) codec->write(codec, reg, value)
 #define snd_soc_write(codec, reg, value) codec->write(codec, reg, value)
@@ -203,6 +225,8 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
  */
  */
 struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
 struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
 	void *data, char *long_name);
 	void *data, char *long_name);
+int snd_soc_add_controls(struct snd_soc_codec *codec,
+	const struct snd_kcontrol_new *controls, int num_controls);
 int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
 int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_info *uinfo);
 	struct snd_ctl_elem_info *uinfo);
 int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
 int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
@@ -237,6 +261,48 @@ int snd_soc_get_volsw_s8(struct snd_kcontrol *kcontrol,
 int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
 int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
 	struct snd_ctl_elem_value *ucontrol);
 	struct snd_ctl_elem_value *ucontrol);
 
 
+/**
+ * struct snd_soc_jack_pin - Describes a pin to update based on jack detection
+ *
+ * @pin:    name of the pin to update
+ * @mask:   bits to check for in reported jack status
+ * @invert: if non-zero then pin is enabled when status is not reported
+ */
+struct snd_soc_jack_pin {
+	struct list_head list;
+	const char *pin;
+	int mask;
+	bool invert;
+};
+
+/**
+ * struct snd_soc_jack_gpio - Describes a gpio pin for jack detection
+ *
+ * @gpio:         gpio number
+ * @name:         gpio name
+ * @report:       value to report when jack detected
+ * @invert:       report presence in low state
+ * @debouce_time: debouce time in ms
+ */
+#ifdef CONFIG_GPIOLIB
+struct snd_soc_jack_gpio {
+	unsigned int gpio;
+	const char *name;
+	int report;
+	int invert;
+	int debounce_time;
+	struct snd_soc_jack *jack;
+	struct work_struct work;
+};
+#endif
+
+struct snd_soc_jack {
+	struct snd_jack *jack;
+	struct snd_soc_card *card;
+	struct list_head pins;
+	int status;
+};
+
 /* SoC PCM stream information */
 /* SoC PCM stream information */
 struct snd_soc_pcm_stream {
 struct snd_soc_pcm_stream {
 	char *stream_name;
 	char *stream_name;
@@ -384,6 +450,8 @@ struct snd_soc_card {
 
 
 	struct snd_soc_device *socdev;
 	struct snd_soc_device *socdev;
 
 
+	struct snd_soc_codec *codec;
+
 	struct snd_soc_platform *platform;
 	struct snd_soc_platform *platform;
 	struct delayed_work delayed_work;
 	struct delayed_work delayed_work;
 	struct work_struct deferred_resume_work;
 	struct work_struct deferred_resume_work;
@@ -393,7 +461,6 @@ struct snd_soc_card {
 struct snd_soc_device {
 struct snd_soc_device {
 	struct device *dev;
 	struct device *dev;
 	struct snd_soc_card *card;
 	struct snd_soc_card *card;
-	struct snd_soc_codec *codec;
 	struct snd_soc_codec_device *codec_dev;
 	struct snd_soc_codec_device *codec_dev;
 	void *codec_data;
 	void *codec_data;
 };
 };

+ 0 - 126
include/sound/uda1341.h

@@ -1,126 +0,0 @@
-/*
- *  linux/include/linux/l3/uda1341.h
- *
- * Philips UDA1341 mixer device driver for ALSA
- *
- * Copyright (c) 2002 Tomas Kasparek <tomas.kasparek@seznam.cz>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License.
- *
- * History:
- *
- * 2002-03-13 Tomas Kasparek Initial release - based on uda1341.h from OSS
- * 2002-03-30 Tomas Kasparek Proc filesystem support, complete mixer and DSP
- *                           features support
- */
-
-#define UDA1341_ALSA_NAME "snd-uda1341"
-
-/*
- * Default rate set after inicialization
- */
-#define AUDIO_RATE_DEFAULT	44100
-
-/*
- * UDA1341 L3 address and command types
- */
-#define UDA1341_L3ADDR		5
-#define UDA1341_DATA0		(UDA1341_L3ADDR << 2 | 0)
-#define UDA1341_DATA1		(UDA1341_L3ADDR << 2 | 1)
-#define UDA1341_STATUS		(UDA1341_L3ADDR << 2 | 2)
-
-enum uda1341_onoff {
-	OFF=0,
-	ON,
-};
-
-enum uda1341_format {
-	I2S=0,
-	LSB16,
-	LSB18,
-	LSB20,
-	MSB,
-	LSB16MSB,
-	LSB18MSB,
-	LSB20MSB,        
-};
-
-enum uda1341_fs {
-	F512=0,
-	F384,
-	F256,
-	Funused,
-};
-
-enum uda1341_peak {
-	BEFORE=0,
-	AFTER,
-};
-
-enum uda1341_filter {
-	FLAT=0,
-	MIN,
-	MIN2,
-	MAX,
-};
-
-enum uda1341_mixer {
-	DOUBLE,
-	LINE,
-	MIC,
-	MIXER,
-};
-
-enum uda1341_deemp {
-	NONE,
-	D32,
-	D44,
-	D48,
-};
-
-enum uda1341_config {
-	CMD_READ_REG = 0,
-	CMD_RESET,
-	CMD_FS,
-	CMD_FORMAT,
-	CMD_OGAIN,
-	CMD_IGAIN,
-	CMD_DAC,
-	CMD_ADC,
-	CMD_VOLUME,
-	CMD_BASS,
-	CMD_TREBBLE,
-	CMD_PEAK,
-	CMD_DEEMP,
-	CMD_MUTE,        
-	CMD_FILTER,
-	CMD_CH1,
-	CMD_CH2,
-	CMD_MIC,       
-	CMD_MIXER,
-	CMD_AGC,
-	CMD_IG,
-	CMD_AGC_TIME,
-	CMD_AGC_LEVEL,
-#ifdef CONFIG_PM
-	CMD_SUSPEND,
-	CMD_RESUME,
-#endif
-	CMD_LAST,
-};
-
-enum write_through {
-	//used in update_bits (write_cfg) to avoid l3_write - just update local copy of regs.
-	REGS_ONLY=0,
-	//update local regs and write value to uda1341 - do l3_write
-	FLUSH,
-};
-
-int __init snd_chip_uda1341_mixer_new(struct snd_card *card, struct l3_client **clnt);
-
-/*
- * Local variables:
- * indent-tabs-mode: t
- * End:
- */

+ 1 - 1
include/sound/version.h

@@ -1,3 +1,3 @@
 /* include/version.h */
 /* include/version.h */
-#define CONFIG_SND_VERSION "1.0.18a"
+#define CONFIG_SND_VERSION "1.0.19"
 #define CONFIG_SND_DATE ""
 #define CONFIG_SND_DATE ""

+ 1 - 0
include/sound/wss.h

@@ -154,6 +154,7 @@ int snd_wss_create(struct snd_card *card,
 		      unsigned short hardware,
 		      unsigned short hardware,
 		      unsigned short hwshare,
 		      unsigned short hwshare,
 		      struct snd_wss **rchip);
 		      struct snd_wss **rchip);
+int snd_wss_free(struct snd_wss *chip);
 int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm);
 int snd_wss_pcm(struct snd_wss *chip, int device, struct snd_pcm **rpcm);
 int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer);
 int snd_wss_timer(struct snd_wss *chip, int device, struct snd_timer **rtimer);
 int snd_wss_mixer(struct snd_wss *chip);
 int snd_wss_mixer(struct snd_wss *chip);

+ 2 - 0
sound/Kconfig

@@ -60,6 +60,8 @@ source "sound/aoa/Kconfig"
 
 
 source "sound/arm/Kconfig"
 source "sound/arm/Kconfig"
 
 
+source "sound/atmel/Kconfig"
+
 source "sound/spi/Kconfig"
 source "sound/spi/Kconfig"
 
 
 source "sound/mips/Kconfig"
 source "sound/mips/Kconfig"

+ 1 - 1
sound/Makefile

@@ -6,7 +6,7 @@ obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o
 obj-$(CONFIG_SOUND_PRIME) += oss/
 obj-$(CONFIG_SOUND_PRIME) += oss/
 obj-$(CONFIG_DMASOUND) += oss/
 obj-$(CONFIG_DMASOUND) += oss/
 obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
 obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
-	sparc/ spi/ parisc/ pcmcia/ mips/ soc/
+	sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
 obj-$(CONFIG_SND_AOA) += aoa/
 obj-$(CONFIG_SND_AOA) += aoa/
 
 
 # This one must be compilable even if sound is configured out
 # This one must be compilable even if sound is configured out

+ 2 - 0
sound/aoa/aoa-gpio.h

@@ -34,10 +34,12 @@ struct gpio_methods {
 	void (*set_headphone)(struct gpio_runtime *rt, int on);
 	void (*set_headphone)(struct gpio_runtime *rt, int on);
 	void (*set_speakers)(struct gpio_runtime *rt, int on);
 	void (*set_speakers)(struct gpio_runtime *rt, int on);
 	void (*set_lineout)(struct gpio_runtime *rt, int on);
 	void (*set_lineout)(struct gpio_runtime *rt, int on);
+	void (*set_master)(struct gpio_runtime *rt, int on);
 
 
 	int (*get_headphone)(struct gpio_runtime *rt);
 	int (*get_headphone)(struct gpio_runtime *rt);
 	int (*get_speakers)(struct gpio_runtime *rt);
 	int (*get_speakers)(struct gpio_runtime *rt);
 	int (*get_lineout)(struct gpio_runtime *rt);
 	int (*get_lineout)(struct gpio_runtime *rt);
+	int (*get_master)(struct gpio_runtime *rt);
 
 
 	void (*set_hw_reset)(struct gpio_runtime *rt, int on);
 	void (*set_hw_reset)(struct gpio_runtime *rt, int on);
 
 

+ 4 - 3
sound/aoa/core/alsa.c

@@ -23,9 +23,10 @@ int aoa_alsa_init(char *name, struct module *mod, struct device *dev)
 		/* cannot be EEXIST due to usage in aoa_fabric_register */
 		/* cannot be EEXIST due to usage in aoa_fabric_register */
 		return -EBUSY;
 		return -EBUSY;
 
 
-	alsa_card = snd_card_new(index, name, mod, sizeof(struct aoa_card));
-	if (!alsa_card)
-		return -ENOMEM;
+	err = snd_card_create(index, name, mod, sizeof(struct aoa_card),
+			      &alsa_card);
+	if (err < 0)
+		return err;
 	aoa_card = alsa_card->private_data;
 	aoa_card = alsa_card->private_data;
 	aoa_card->alsa_card = alsa_card;
 	aoa_card->alsa_card = alsa_card;
 	alsa_card->dev = dev;
 	alsa_card->dev = dev;

+ 16 - 1
sound/aoa/core/gpio-feature.c

@@ -14,7 +14,7 @@
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include "../aoa.h"
 #include "../aoa.h"
 
 
-/* TODO: these are 20 global variables
+/* TODO: these are lots of global variables
  * that aren't used on most machines...
  * that aren't used on most machines...
  * Move them into a dynamically allocated
  * Move them into a dynamically allocated
  * structure and use that.
  * structure and use that.
@@ -23,6 +23,7 @@
 /* these are the GPIO numbers (register addresses as offsets into
 /* these are the GPIO numbers (register addresses as offsets into
  * the GPIO space) */
  * the GPIO space) */
 static int headphone_mute_gpio;
 static int headphone_mute_gpio;
+static int master_mute_gpio;
 static int amp_mute_gpio;
 static int amp_mute_gpio;
 static int lineout_mute_gpio;
 static int lineout_mute_gpio;
 static int hw_reset_gpio;
 static int hw_reset_gpio;
@@ -32,6 +33,7 @@ static int linein_detect_gpio;
 
 
 /* see the SWITCH_GPIO macro */
 /* see the SWITCH_GPIO macro */
 static int headphone_mute_gpio_activestate;
 static int headphone_mute_gpio_activestate;
+static int master_mute_gpio_activestate;
 static int amp_mute_gpio_activestate;
 static int amp_mute_gpio_activestate;
 static int lineout_mute_gpio_activestate;
 static int lineout_mute_gpio_activestate;
 static int hw_reset_gpio_activestate;
 static int hw_reset_gpio_activestate;
@@ -156,6 +158,7 @@ static int ftr_gpio_get_##name(struct gpio_runtime *rt)		\
 FTR_GPIO(headphone, 0);
 FTR_GPIO(headphone, 0);
 FTR_GPIO(amp, 1);
 FTR_GPIO(amp, 1);
 FTR_GPIO(lineout, 2);
 FTR_GPIO(lineout, 2);
+FTR_GPIO(master, 3);
 
 
 static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
 static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
 {
 {
@@ -172,6 +175,8 @@ static void ftr_gpio_set_hw_reset(struct gpio_runtime *rt, int on)
 			  hw_reset_gpio, v);
 			  hw_reset_gpio, v);
 }
 }
 
 
+static struct gpio_methods methods;
+
 static void ftr_gpio_all_amps_off(struct gpio_runtime *rt)
 static void ftr_gpio_all_amps_off(struct gpio_runtime *rt)
 {
 {
 	int saved;
 	int saved;
@@ -181,6 +186,8 @@ static void ftr_gpio_all_amps_off(struct gpio_runtime *rt)
 	ftr_gpio_set_headphone(rt, 0);
 	ftr_gpio_set_headphone(rt, 0);
 	ftr_gpio_set_amp(rt, 0);
 	ftr_gpio_set_amp(rt, 0);
 	ftr_gpio_set_lineout(rt, 0);
 	ftr_gpio_set_lineout(rt, 0);
+	if (methods.set_master)
+		ftr_gpio_set_master(rt, 0);
 	rt->implementation_private = saved;
 	rt->implementation_private = saved;
 }
 }
 
 
@@ -193,6 +200,8 @@ static void ftr_gpio_all_amps_restore(struct gpio_runtime *rt)
 	ftr_gpio_set_headphone(rt, (s>>0)&1);
 	ftr_gpio_set_headphone(rt, (s>>0)&1);
 	ftr_gpio_set_amp(rt, (s>>1)&1);
 	ftr_gpio_set_amp(rt, (s>>1)&1);
 	ftr_gpio_set_lineout(rt, (s>>2)&1);
 	ftr_gpio_set_lineout(rt, (s>>2)&1);
+	if (methods.set_master)
+		ftr_gpio_set_master(rt, (s>>3)&1);
 }
 }
 
 
 static void ftr_handle_notify(struct work_struct *work)
 static void ftr_handle_notify(struct work_struct *work)
@@ -231,6 +240,12 @@ static void ftr_gpio_init(struct gpio_runtime *rt)
 	get_gpio("hw-reset", "audio-hw-reset",
 	get_gpio("hw-reset", "audio-hw-reset",
 		 &hw_reset_gpio,
 		 &hw_reset_gpio,
 		 &hw_reset_gpio_activestate);
 		 &hw_reset_gpio_activestate);
+	if (get_gpio("master-mute", NULL,
+		     &master_mute_gpio,
+		     &master_mute_gpio_activestate)) {
+		methods.set_master = ftr_gpio_set_master;
+		methods.get_master = ftr_gpio_get_master;
+	}
 
 
 	headphone_detect_node = get_gpio("headphone-detect", NULL,
 	headphone_detect_node = get_gpio("headphone-detect", NULL,
 					 &headphone_detect_gpio,
 					 &headphone_detect_gpio,

+ 64 - 17
sound/aoa/fabrics/layout.c

@@ -1,16 +1,14 @@
 /*
 /*
- * Apple Onboard Audio driver -- layout fabric
+ * Apple Onboard Audio driver -- layout/machine id fabric
  *
  *
- * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net>
  *
  *
  * GPL v2, can be found in COPYING.
  * GPL v2, can be found in COPYING.
  *
  *
  *
  *
- * This fabric module looks for sound codecs
- * based on the layout-id property in the device tree.
- *
+ * This fabric module looks for sound codecs based on the
+ * layout-id or device-id property in the device tree.
  */
  */
-
 #include <asm/prom.h>
 #include <asm/prom.h>
 #include <linux/list.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/module.h>
@@ -63,7 +61,7 @@ struct codec_connect_info {
 #define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF	(1<<0)
 #define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF	(1<<0)
 
 
 struct layout {
 struct layout {
-	unsigned int layout_id;
+	unsigned int layout_id, device_id;
 	struct codec_connect_info codecs[MAX_CODECS_PER_BUS];
 	struct codec_connect_info codecs[MAX_CODECS_PER_BUS];
 	int flags;
 	int flags;
 
 
@@ -111,6 +109,10 @@ MODULE_ALIAS("sound-layout-96");
 MODULE_ALIAS("sound-layout-98");
 MODULE_ALIAS("sound-layout-98");
 MODULE_ALIAS("sound-layout-100");
 MODULE_ALIAS("sound-layout-100");
 
 
+MODULE_ALIAS("aoa-device-id-14");
+MODULE_ALIAS("aoa-device-id-22");
+MODULE_ALIAS("aoa-device-id-35");
+
 /* onyx with all but microphone connected */
 /* onyx with all but microphone connected */
 static struct codec_connection onyx_connections_nomic[] = {
 static struct codec_connection onyx_connections_nomic[] = {
 	{
 	{
@@ -518,6 +520,27 @@ static struct layout layouts[] = {
 		.connections = onyx_connections_noheadphones,
 		.connections = onyx_connections_noheadphones,
 	  },
 	  },
 	},
 	},
+	/* PowerMac3,4 */
+	{ .device_id = 14,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_noline,
+	  },
+	},
+	/* PowerMac3,6 */
+	{ .device_id = 22,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_all,
+	  },
+	},
+	/* PowerBook5,2 */
+	{ .device_id = 35,
+	  .codecs[0] = {
+		.name = "tas",
+		.connections = tas_connections_all,
+	  },
+	},
 	{}
 	{}
 };
 };
 
 
@@ -526,7 +549,7 @@ static struct layout *find_layout_by_id(unsigned int id)
 	struct layout *l;
 	struct layout *l;
 
 
 	l = layouts;
 	l = layouts;
-	while (l->layout_id) {
+	while (l->codecs[0].name) {
 		if (l->layout_id == id)
 		if (l->layout_id == id)
 			return l;
 			return l;
 		l++;
 		l++;
@@ -534,6 +557,19 @@ static struct layout *find_layout_by_id(unsigned int id)
 	return NULL;
 	return NULL;
 }
 }
 
 
+static struct layout *find_layout_by_device(unsigned int id)
+{
+	struct layout *l;
+
+	l = layouts;
+	while (l->codecs[0].name) {
+		if (l->device_id == id)
+			return l;
+		l++;
+	}
+	return NULL;
+}
+
 static void use_layout(struct layout *l)
 static void use_layout(struct layout *l)
 {
 {
 	int i;
 	int i;
@@ -564,6 +600,7 @@ struct layout_dev {
 	struct snd_kcontrol *headphone_ctrl;
 	struct snd_kcontrol *headphone_ctrl;
 	struct snd_kcontrol *lineout_ctrl;
 	struct snd_kcontrol *lineout_ctrl;
 	struct snd_kcontrol *speaker_ctrl;
 	struct snd_kcontrol *speaker_ctrl;
+	struct snd_kcontrol *master_ctrl;
 	struct snd_kcontrol *headphone_detected_ctrl;
 	struct snd_kcontrol *headphone_detected_ctrl;
 	struct snd_kcontrol *lineout_detected_ctrl;
 	struct snd_kcontrol *lineout_detected_ctrl;
 
 
@@ -615,6 +652,7 @@ static struct snd_kcontrol_new n##_ctl = {				\
 AMP_CONTROL(headphone, "Headphone Switch");
 AMP_CONTROL(headphone, "Headphone Switch");
 AMP_CONTROL(speakers, "Speakers Switch");
 AMP_CONTROL(speakers, "Speakers Switch");
 AMP_CONTROL(lineout, "Line-Out Switch");
 AMP_CONTROL(lineout, "Line-Out Switch");
+AMP_CONTROL(master, "Master Switch");
 
 
 static int detect_choice_get(struct snd_kcontrol *kcontrol,
 static int detect_choice_get(struct snd_kcontrol *kcontrol,
 			     struct snd_ctl_elem_value *ucontrol)
 			     struct snd_ctl_elem_value *ucontrol)
@@ -855,6 +893,11 @@ static void layout_attached_codec(struct aoa_codec *codec)
  	lineout = codec->gpio->methods->get_detect(codec->gpio,
  	lineout = codec->gpio->methods->get_detect(codec->gpio,
 						   AOA_NOTIFY_LINE_OUT);
 						   AOA_NOTIFY_LINE_OUT);
 
 
+	if (codec->gpio->methods->set_master) {
+		ctl = snd_ctl_new1(&master_ctl, codec->gpio);
+		ldev->master_ctrl = ctl;
+		aoa_snd_ctl_add(ctl);
+	}
 	while (cc->connected) {
 	while (cc->connected) {
 		if (cc->connected & CC_SPEAKERS) {
 		if (cc->connected & CC_SPEAKERS) {
 			if (headphones <= 0 && lineout <= 0)
 			if (headphones <= 0 && lineout <= 0)
@@ -938,8 +981,8 @@ static struct aoa_fabric layout_fabric = {
 static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
 static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
 {
 {
 	struct device_node *sound = NULL;
 	struct device_node *sound = NULL;
-	const unsigned int *layout_id;
-	struct layout *layout;
+	const unsigned int *id;
+	struct layout *layout = NULL;
 	struct layout_dev *ldev = NULL;
 	struct layout_dev *ldev = NULL;
 	int err;
 	int err;
 
 
@@ -952,15 +995,18 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
 		if (sound->type && strcasecmp(sound->type, "soundchip") == 0)
 		if (sound->type && strcasecmp(sound->type, "soundchip") == 0)
 			break;
 			break;
 	}
 	}
-	if (!sound) return -ENODEV;
+	if (!sound)
+		return -ENODEV;
 
 
-	layout_id = of_get_property(sound, "layout-id", NULL);
-	if (!layout_id)
-		goto outnodev;
-	printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d\n",
-	       *layout_id);
+	id = of_get_property(sound, "layout-id", NULL);
+	if (id) {
+		layout = find_layout_by_id(*id);
+	} else {
+		id = of_get_property(sound, "device-id", NULL);
+		if (id)
+			layout = find_layout_by_device(*id);
+	}
 
 
-	layout = find_layout_by_id(*layout_id);
 	if (!layout) {
 	if (!layout) {
 		printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n");
 		printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n");
 		goto outnodev;
 		goto outnodev;
@@ -976,6 +1022,7 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
 	ldev->layout = layout;
 	ldev->layout = layout;
 	ldev->gpio.node = sound->parent;
 	ldev->gpio.node = sound->parent;
 	switch (layout->layout_id) {
 	switch (layout->layout_id) {
+	case 0:  /* anything with device_id, not layout_id */
 	case 41: /* that unknown machine no one seems to have */
 	case 41: /* that unknown machine no one seems to have */
 	case 51: /* PowerBook5,4 */
 	case 51: /* PowerBook5,4 */
 	case 58: /* Mac Mini */
 	case 58: /* Mac Mini */

+ 17 - 5
sound/aoa/soundbus/i2sbus/core.c

@@ -1,7 +1,7 @@
 /*
 /*
  * i2sbus driver
  * i2sbus driver
  *
  *
- * Copyright 2006 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net>
  *
  *
  * GPL v2, can be found in COPYING.
  * GPL v2, can be found in COPYING.
  */
  */
@@ -186,13 +186,25 @@ static int i2sbus_add_dev(struct macio_dev *macio,
 		}
 		}
 	}
 	}
 	if (i == 1) {
 	if (i == 1) {
-		const u32 *layout_id =
-			of_get_property(sound, "layout-id", NULL);
-		if (layout_id) {
-			layout = *layout_id;
+		const u32 *id = of_get_property(sound, "layout-id", NULL);
+
+		if (id) {
+			layout = *id;
 			snprintf(dev->sound.modalias, 32,
 			snprintf(dev->sound.modalias, 32,
 				 "sound-layout-%d", layout);
 				 "sound-layout-%d", layout);
 			ok = 1;
 			ok = 1;
+		} else {
+			id = of_get_property(sound, "device-id", NULL);
+			/*
+			 * We probably cannot handle all device-id machines,
+			 * so restrict to those we do handle for now.
+			 */
+			if (id && (*id == 22 || *id == 14 || *id == 35)) {
+				snprintf(dev->sound.modalias, 32,
+					 "aoa-device-id-%d", *id);
+				ok = 1;
+				layout = -1;
+			}
 		}
 		}
 	}
 	}
 	/* for the time being, until we can handle non-layout-id
 	/* for the time being, until we can handle non-layout-id

+ 0 - 11
sound/arm/Kconfig

@@ -11,17 +11,6 @@ menuconfig SND_ARM
 
 
 if SND_ARM
 if SND_ARM
 
 
-config SND_SA11XX_UDA1341
-	tristate "SA11xx UDA1341TS driver (iPaq H3600)"
-	depends on ARCH_SA1100 && L3
-	select SND_PCM
-	help
-	  Say Y here if you have a Compaq iPaq H3x00 handheld computer
-	  and want to use its Philips UDA 1341 audio chip.
-
-	  To compile this driver as a module, choose M here: the module
-	  will be called snd-sa11xx-uda1341.
-
 config SND_ARMAACI
 config SND_ARMAACI
 	tristate "ARM PrimeCell PL041 AC Link support"
 	tristate "ARM PrimeCell PL041 AC Link support"
 	depends on ARM_AMBA
 	depends on ARM_AMBA

+ 0 - 3
sound/arm/Makefile

@@ -2,9 +2,6 @@
 # Makefile for ALSA
 # Makefile for ALSA
 #
 #
 
 
-obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-sa11xx-uda1341.o 
-snd-sa11xx-uda1341-objs		:= sa11xx-uda1341.o
-
 obj-$(CONFIG_SND_ARMAACI)	+= snd-aaci.o
 obj-$(CONFIG_SND_ARMAACI)	+= snd-aaci.o
 snd-aaci-objs			:= aaci.o devdma.o
 snd-aaci-objs			:= aaci.o devdma.o
 
 

+ 4 - 3
sound/arm/aaci.c

@@ -995,10 +995,11 @@ static struct aaci * __devinit aaci_init_card(struct amba_device *dev)
 {
 {
 	struct aaci *aaci;
 	struct aaci *aaci;
 	struct snd_card *card;
 	struct snd_card *card;
+	int err;
 
 
-	card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
-			    THIS_MODULE, sizeof(struct aaci));
-	if (card == NULL)
+	err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			      THIS_MODULE, sizeof(struct aaci), &card);
+	if (err < 0)
 		return NULL;
 		return NULL;
 
 
 	card->private_free = aaci_free_card;
 	card->private_free = aaci_free_card;

+ 66 - 5
sound/arm/pxa2xx-ac97-lib.c

@@ -31,6 +31,7 @@ static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
 static volatile long gsr_bits;
 static volatile long gsr_bits;
 static struct clk *ac97_clk;
 static struct clk *ac97_clk;
 static struct clk *ac97conf_clk;
 static struct clk *ac97conf_clk;
+static int reset_gpio;
 
 
 /*
 /*
  * Beware PXA27x bugs:
  * Beware PXA27x bugs:
@@ -42,6 +43,45 @@ static struct clk *ac97conf_clk;
  * 1 jiffy timeout if interrupt never comes).
  * 1 jiffy timeout if interrupt never comes).
  */
  */
 
 
+enum {
+	RESETGPIO_FORCE_HIGH,
+	RESETGPIO_FORCE_LOW,
+	RESETGPIO_NORMAL_ALTFUNC
+};
+
+/**
+ * set_resetgpio_mode - computes and sets the AC97_RESET gpio mode on PXA
+ * @mode: chosen action
+ *
+ * As the PXA27x CPUs suffer from a AC97 bug, a manual control of the reset line
+ * must be done to insure proper work of AC97 reset line.  This function
+ * computes the correct gpio_mode for further use by reset functions, and
+ * applied the change through pxa_gpio_mode.
+ */
+static void set_resetgpio_mode(int resetgpio_action)
+{
+	int mode = 0;
+
+	if (reset_gpio)
+		switch (resetgpio_action) {
+		case RESETGPIO_NORMAL_ALTFUNC:
+			if (reset_gpio == 113)
+				mode = 113 | GPIO_OUT | GPIO_DFLT_LOW;
+			if (reset_gpio == 95)
+				mode = 95 | GPIO_ALT_FN_1_OUT;
+			break;
+		case RESETGPIO_FORCE_LOW:
+			mode = reset_gpio | GPIO_OUT | GPIO_DFLT_LOW;
+			break;
+		case RESETGPIO_FORCE_HIGH:
+			mode = reset_gpio | GPIO_OUT | GPIO_DFLT_HIGH;
+			break;
+		};
+
+	if (mode)
+		pxa_gpio_mode(mode);
+}
+
 unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
 {
 {
 	unsigned short val = -1;
 	unsigned short val = -1;
@@ -137,10 +177,10 @@ static inline void pxa_ac97_warm_pxa27x(void)
 
 
 	/* warm reset broken on Bulverde,
 	/* warm reset broken on Bulverde,
 	   so manually keep AC97 reset high */
 	   so manually keep AC97 reset high */
-	pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH);
+	set_resetgpio_mode(RESETGPIO_FORCE_HIGH);
 	udelay(10);
 	udelay(10);
 	GCR |= GCR_WARM_RST;
 	GCR |= GCR_WARM_RST;
-	pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+	set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC);
 	udelay(500);
 	udelay(500);
 }
 }
 
 
@@ -308,8 +348,8 @@ int pxa2xx_ac97_hw_resume(void)
 		pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
 		pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
 	}
 	}
 	if (cpu_is_pxa27x()) {
 	if (cpu_is_pxa27x()) {
-		/* Use GPIO 113 as AC97 Reset on Bulverde */
-		pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+		/* Use GPIO 113 or 95 as AC97 Reset on Bulverde */
+		set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC);
 	}
 	}
 	clk_enable(ac97_clk);
 	clk_enable(ac97_clk);
 	return 0;
 	return 0;
@@ -320,6 +360,27 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
 int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
 int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
 {
 {
 	int ret;
 	int ret;
+	struct pxa2xx_ac97_platform_data *pdata = dev->dev.platform_data;
+
+	if (pdata) {
+		switch (pdata->reset_gpio) {
+		case 95:
+		case 113:
+			reset_gpio = pdata->reset_gpio;
+			break;
+		case 0:
+			reset_gpio = 113;
+			break;
+		case -1:
+			break;
+		default:
+			dev_err(&dev->dev, "Invalid reset GPIO %d\n",
+				pdata->reset_gpio);
+		}
+	} else {
+		if (cpu_is_pxa27x())
+			reset_gpio = 113;
+	}
 
 
 	if (cpu_is_pxa25x() || cpu_is_pxa27x()) {
 	if (cpu_is_pxa25x() || cpu_is_pxa27x()) {
 		pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
 		pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
@@ -330,7 +391,7 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
 
 
 	if (cpu_is_pxa27x()) {
 	if (cpu_is_pxa27x()) {
 		/* Use GPIO 113 as AC97 Reset on Bulverde */
 		/* Use GPIO 113 as AC97 Reset on Bulverde */
-		pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
+		set_resetgpio_mode(RESETGPIO_NORMAL_ALTFUNC);
 		ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
 		ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
 		if (IS_ERR(ac97conf_clk)) {
 		if (IS_ERR(ac97conf_clk)) {
 			ret = PTR_ERR(ac97conf_clk);
 			ret = PTR_ERR(ac97conf_clk);

+ 3 - 4
sound/arm/pxa2xx-ac97.c

@@ -173,10 +173,9 @@ static int __devinit pxa2xx_ac97_probe(struct platform_device *dev)
 	struct snd_ac97_template ac97_template;
 	struct snd_ac97_template ac97_template;
 	int ret;
 	int ret;
 
 
-	ret = -ENOMEM;
-	card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
-			    THIS_MODULE, 0);
-	if (!card)
+	ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			      THIS_MODULE, 0, &card);
+	if (ret < 0)
 		goto err;
 		goto err;
 
 
 	card->dev = &dev->dev;
 	card->dev = &dev->dev;

+ 0 - 983
sound/arm/sa11xx-uda1341.c

@@ -1,983 +0,0 @@
-/*
- *  Driver for Philips UDA1341TS on Compaq iPAQ H3600 soundcard
- *  Copyright (C) 2002 Tomas Kasparek <tomas.kasparek@seznam.cz>
- *
- *   This program is free software; you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License.
- * 
- * History:
- *
- * 2002-03-13   Tomas Kasparek  initial release - based on h3600-uda1341.c from OSS
- * 2002-03-20   Tomas Kasparek  playback over ALSA is working
- * 2002-03-28   Tomas Kasparek  playback over OSS emulation is working
- * 2002-03-29   Tomas Kasparek  basic capture is working (native ALSA)
- * 2002-03-29   Tomas Kasparek  capture is working (OSS emulation)
- * 2002-04-04   Tomas Kasparek  better rates handling (allow non-standard rates)
- * 2003-02-14   Brian Avery     fixed full duplex mode, other updates
- * 2003-02-20   Tomas Kasparek  merged updates by Brian (except HAL)
- * 2003-04-19   Jaroslav Kysela recoded DMA stuff to follow 2.4.18rmk3-hh24 kernel
- *                              working suspend and resume
- * 2003-04-28   Tomas Kasparek  updated work by Jaroslav to compile it under 2.5.x again
- *                              merged HAL layer (patches from Brian)
- */
-
-/***************************************************************************************************
-*
-* To understand what Alsa Drivers should be doing look at "Writing an Alsa Driver" by Takashi Iwai
-* available in the Alsa doc section on the website		
-* 
-* A few notes to make things clearer. The UDA1341 is hooked up to Serial port 4 on the SA1100.
-* We are using  SSP mode to talk to the UDA1341. The UDA1341 bit & wordselect clocks are generated
-* by this UART. Unfortunately, the clock only runs if the transmit buffer has something in it.
-* So, if we are just recording, we feed the transmit DMA stream a bunch of 0x0000 so that the
-* transmit buffer is full and the clock keeps going. The zeroes come from FLUSH_BASE_PHYS which
-* is a mem loc that always decodes to 0's w/ no off chip access.
-*
-* Some alsa terminology:
-*	frame => num_channels * sample_size  e.g stereo 16 bit is 2 * 16 = 32 bytes
-*	period => the least number of bytes that will generate an interrupt e.g. we have a 1024 byte
-*             buffer and 4 periods in the runtime structure this means we'll get an int every 256
-*             bytes or 4 times per buffer.
-*             A number of the sizes are in frames rather than bytes, use frames_to_bytes and
-*             bytes_to_frames to convert.  The easiest way to tell the units is to look at the
-*             type i.e. runtime-> buffer_size is in frames and its type is snd_pcm_uframes_t
-*             
-*	Notes about the pointer fxn:
-*	The pointer fxn needs to return the offset into the dma buffer in frames.
-*	Interrupts must be blocked before calling the dma_get_pos fxn to avoid race with interrupts.
-*
-*	Notes about pause/resume
-*	Implementing this would be complicated so it's skipped.  The problem case is:
-*	A full duplex connection is going, then play is paused. At this point you need to start xmitting
-*	0's to keep the record active which means you cant just freeze the dma and resume it later you'd
-*	need to	save off the dma info, and restore it properly on a resume.  Yeach!
-*
-*	Notes about transfer methods:
-*	The async write calls fail.  I probably need to implement something else to support them?
-* 
-***************************************************************************************************/
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/platform_device.h>
-#include <linux/errno.h>
-#include <linux/ioctl.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-
-#ifdef CONFIG_PM
-#include <linux/pm.h>
-#endif
-
-#include <mach/hardware.h>
-#include <mach/h3600.h>
-#include <asm/mach-types.h>
-#include <asm/dma.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/initval.h>
-
-#include <linux/l3/l3.h>
-
-#undef DEBUG_MODE
-#undef DEBUG_FUNCTION_NAMES
-#include <sound/uda1341.h>
-
-/*
- * FIXME: Is this enough as autodetection of 2.4.X-rmkY-hhZ kernels?
- * We use DMA stuff from 2.4.18-rmk3-hh24 here to be able to compile this
- * module for Familiar 0.6.1
- */
-
-/* {{{ Type definitions */
-
-MODULE_AUTHOR("Tomas Kasparek <tomas.kasparek@seznam.cz>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("SA1100/SA1111 + UDA1341TS driver for ALSA");
-MODULE_SUPPORTED_DEVICE("{{UDA1341,iPAQ H3600 UDA1341TS}}");
-
-static char *id;	/* ID for this card */
-
-module_param(id, charp, 0444);
-MODULE_PARM_DESC(id, "ID string for SA1100/SA1111 + UDA1341TS soundcard.");
-
-struct audio_stream {
-	char *id;		/* identification string */
-	int stream_id;		/* numeric identification */	
-	dma_device_t dma_dev;	/* device identifier for DMA */
-#ifdef HH_VERSION
-	dmach_t dmach;		/* dma channel identification */
-#else
-	dma_regs_t *dma_regs;	/* points to our DMA registers */
-#endif
-	unsigned int active:1;	/* we are using this stream for transfer now */
-	int period;		/* current transfer period */
-	int periods;		/* current count of periods registerd in the DMA engine */
-	int tx_spin;		/* are we recoding - flag used to do DMA trans. for sync */
-	unsigned int old_offset;
-	spinlock_t dma_lock;	/* for locking in DMA operations (see dma-sa1100.c in the kernel) */
-	struct snd_pcm_substream *stream;
-};
-
-struct sa11xx_uda1341 {
-	struct snd_card *card;
-	struct l3_client *uda1341;
-	struct snd_pcm *pcm;
-	long samplerate;
-	struct audio_stream s[2];	/* playback & capture */
-};
-
-static unsigned int rates[] = {
-	8000,  10666, 10985, 14647,
-	16000, 21970, 22050, 24000,
-	29400, 32000, 44100, 48000,
-};
-
-static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
-	.count	= ARRAY_SIZE(rates),
-	.list	= rates,
-	.mask	= 0,
-};
-
-static struct platform_device *device;
-
-/* }}} */
-
-/* {{{ Clock and sample rate stuff */
-
-/*
- * Stop-gap solution until rest of hh.org HAL stuff is merged.
- */
-#define GPIO_H3600_CLK_SET0		GPIO_GPIO (12)
-#define GPIO_H3600_CLK_SET1		GPIO_GPIO (13)
-
-#ifdef CONFIG_SA1100_H3XXX
-#define	clr_sa11xx_uda1341_egpio(x)	clr_h3600_egpio(x)
-#define set_sa11xx_uda1341_egpio(x)	set_h3600_egpio(x)
-#else
-#error This driver could serve H3x00 handhelds only!
-#endif
-
-static void sa11xx_uda1341_set_audio_clock(long val)
-{
-	switch (val) {
-	case 24000: case 32000: case 48000:	/* 00: 12.288 MHz */
-		GPCR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;
-		break;
-
-	case 22050: case 29400: case 44100:	/* 01: 11.2896 MHz */
-		GPSR = GPIO_H3600_CLK_SET0;
-		GPCR = GPIO_H3600_CLK_SET1;
-		break;
-
-	case 8000: case 10666: case 16000:	/* 10: 4.096 MHz */
-		GPCR = GPIO_H3600_CLK_SET0;
-		GPSR = GPIO_H3600_CLK_SET1;
-		break;
-
-	case 10985: case 14647: case 21970:	/* 11: 5.6245 MHz */
-		GPSR = GPIO_H3600_CLK_SET0 | GPIO_H3600_CLK_SET1;
-		break;
-	}
-}
-
-static void sa11xx_uda1341_set_samplerate(struct sa11xx_uda1341 *sa11xx_uda1341, long rate)
-{
-	int clk_div = 0;
-	int clk=0;
-
-	/* We don't want to mess with clocks when frames are in flight */
-	Ser4SSCR0 &= ~SSCR0_SSE;
-	/* wait for any frame to complete */
-	udelay(125);
-
-	/*
-	 * We have the following clock sources:
-	 * 4.096 MHz, 5.6245 MHz, 11.2896 MHz, 12.288 MHz
-	 * Those can be divided either by 256, 384 or 512.
-	 * This makes up 12 combinations for the following samplerates...
-	 */
-	if (rate >= 48000)
-		rate = 48000;
-	else if (rate >= 44100)
-		rate = 44100;
-	else if (rate >= 32000)
-		rate = 32000;
-	else if (rate >= 29400)
-		rate = 29400;
-	else if (rate >= 24000)
-		rate = 24000;
-	else if (rate >= 22050)
-		rate = 22050;
-	else if (rate >= 21970)
-		rate = 21970;
-	else if (rate >= 16000)
-		rate = 16000;
-	else if (rate >= 14647)
-		rate = 14647;
-	else if (rate >= 10985)
-		rate = 10985;
-	else if (rate >= 10666)
-		rate = 10666;
-	else
-		rate = 8000;
-
-	/* Set the external clock generator */
-	
-	sa11xx_uda1341_set_audio_clock(rate);
-
-	/* Select the clock divisor */
-	switch (rate) {
-	case 8000:
-	case 10985:
-	case 22050:
-	case 24000:
-		clk = F512;
-		clk_div = SSCR0_SerClkDiv(16);
-		break;
-	case 16000:
-	case 21970:
-	case 44100:
-	case 48000:
-		clk = F256;
-		clk_div = SSCR0_SerClkDiv(8);
-		break;
-	case 10666:
-	case 14647:
-	case 29400:
-	case 32000:
-		clk = F384;
-		clk_div = SSCR0_SerClkDiv(12);
-		break;
-	}
-
-	/* FMT setting should be moved away when other FMTs are added (FIXME) */
-	l3_command(sa11xx_uda1341->uda1341, CMD_FORMAT, (void *)LSB16);
-	
-	l3_command(sa11xx_uda1341->uda1341, CMD_FS, (void *)clk);        
-	Ser4SSCR0 = (Ser4SSCR0 & ~0xff00) + clk_div + SSCR0_SSE;
-	sa11xx_uda1341->samplerate = rate;
-}
-
-/* }}} */
-
-/* {{{ HW init and shutdown */
-
-static void sa11xx_uda1341_audio_init(struct sa11xx_uda1341 *sa11xx_uda1341)
-{
-	unsigned long flags;
-
-	/* Setup DMA stuff */
-	sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].id = "UDA1341 out";
-	sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].stream_id = SNDRV_PCM_STREAM_PLAYBACK;
-	sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK].dma_dev = DMA_Ser4SSPWr;
-
-	sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].id = "UDA1341 in";
-	sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].stream_id = SNDRV_PCM_STREAM_CAPTURE;
-	sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE].dma_dev = DMA_Ser4SSPRd;
-
-	/* Initialize the UDA1341 internal state */
-       
-	/* Setup the uarts */
-	local_irq_save(flags);
-	GAFR |= (GPIO_SSP_CLK);
-	GPDR &= ~(GPIO_SSP_CLK);
-	Ser4SSCR0 = 0;
-	Ser4SSCR0 = SSCR0_DataSize(16) + SSCR0_TI + SSCR0_SerClkDiv(8);
-	Ser4SSCR1 = SSCR1_SClkIactL + SSCR1_SClk1P + SSCR1_ExtClk;
-	Ser4SSCR0 |= SSCR0_SSE;
-	local_irq_restore(flags);
-
-	/* Enable the audio power */
-
-	clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET);
-	set_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON);
-	set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);
- 
-	/* Wait for the UDA1341 to wake up */
-	mdelay(1); //FIXME - was removed by Perex - Why?
-
-	/* Initialize the UDA1341 internal state */
-	l3_open(sa11xx_uda1341->uda1341);
-	
-	/* external clock configuration (after l3_open - regs must be initialized */
-	sa11xx_uda1341_set_samplerate(sa11xx_uda1341, sa11xx_uda1341->samplerate);
-
-	/* Wait for the UDA1341 to wake up */
-	set_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET);
-	mdelay(1);	
-
-	/* make the left and right channels unswapped (flip the WS latch) */
-	Ser4SSDR = 0;
-
-	clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);
-}
-
-static void sa11xx_uda1341_audio_shutdown(struct sa11xx_uda1341 *sa11xx_uda1341)
-{
-	/* mute on */
-	set_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);
-	
-	/* disable the audio power and all signals leading to the audio chip */
-	l3_close(sa11xx_uda1341->uda1341);
-	Ser4SSCR0 = 0;
-	clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_CODEC_NRESET);
-
-	/* power off and mute off */
-	/* FIXME - is muting off necesary??? */
-
-	clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_AUDIO_ON);
-	clr_sa11xx_uda1341_egpio(IPAQ_EGPIO_QMUTE);
-}
-
-/* }}} */
-
-/* {{{ DMA staff */
-
-/*
- * these are the address and sizes used to fill the xmit buffer
- * so we can get a clock in record only mode
- */
-#define FORCE_CLOCK_ADDR		(dma_addr_t)FLUSH_BASE_PHYS
-#define FORCE_CLOCK_SIZE		4096 // was 2048
-
-// FIXME Why this value exactly - wrote comment
-#define DMA_BUF_SIZE	8176	/* <= MAX_DMA_SIZE from asm/arch-sa1100/dma.h */
-
-#ifdef HH_VERSION
-
-static int audio_dma_request(struct audio_stream *s, void (*callback)(void *, int))
-{
-	int ret;
-
-	ret = sa1100_request_dma(&s->dmach, s->id, s->dma_dev);
-	if (ret < 0) {
-		printk(KERN_ERR "unable to grab audio dma 0x%x\n", s->dma_dev);
-		return ret;
-	}
-	sa1100_dma_set_callback(s->dmach, callback);
-	return 0;
-}
-
-static inline void audio_dma_free(struct audio_stream *s)
-{
-	sa1100_free_dma(s->dmach);
-	s->dmach = -1;
-}
-
-#else
-
-static int audio_dma_request(struct audio_stream *s, void (*callback)(void *))
-{
-	int ret;
-
-	ret = sa1100_request_dma(s->dma_dev, s->id, callback, s, &s->dma_regs);
-	if (ret < 0)
-		printk(KERN_ERR "unable to grab audio dma 0x%x\n", s->dma_dev);
-	return ret;
-}
-
-static void audio_dma_free(struct audio_stream *s)
-{
-	sa1100_free_dma(s->dma_regs);
-	s->dma_regs = 0;
-}
-
-#endif
-
-static u_int audio_get_dma_pos(struct audio_stream *s)
-{
-	struct snd_pcm_substream *substream = s->stream;
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	unsigned int offset;
-	unsigned long flags;
-	dma_addr_t addr;
-	
-	// this must be called w/ interrupts locked out see dma-sa1100.c in the kernel
-	spin_lock_irqsave(&s->dma_lock, flags);
-#ifdef HH_VERSION	
-	sa1100_dma_get_current(s->dmach, NULL, &addr);
-#else
-	addr = sa1100_get_dma_pos((s)->dma_regs);
-#endif
-	offset = addr - runtime->dma_addr;
-	spin_unlock_irqrestore(&s->dma_lock, flags);
-	
-	offset = bytes_to_frames(runtime,offset);
-	if (offset >= runtime->buffer_size)
-		offset = 0;
-
-	return offset;
-}
-
-/*
- * this stops the dma and clears the dma ptrs
- */
-static void audio_stop_dma(struct audio_stream *s)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&s->dma_lock, flags);	
-	s->active = 0;
-	s->period = 0;
-	/* this stops the dma channel and clears the buffer ptrs */
-#ifdef HH_VERSION
-	sa1100_dma_flush_all(s->dmach);
-#else
-	sa1100_clear_dma(s->dma_regs);	
-#endif
-	spin_unlock_irqrestore(&s->dma_lock, flags);
-}
-
-static void audio_process_dma(struct audio_stream *s)
-{
-	struct snd_pcm_substream *substream = s->stream;
-	struct snd_pcm_runtime *runtime;
-	unsigned int dma_size;		
-	unsigned int offset;
-	int ret;
-                
-	/* we are requested to process synchronization DMA transfer */
-	if (s->tx_spin) {
-		if (snd_BUG_ON(s->stream_id != SNDRV_PCM_STREAM_PLAYBACK))
-			return;
-		/* fill the xmit dma buffers and return */
-#ifdef HH_VERSION
-		sa1100_dma_set_spin(s->dmach, FORCE_CLOCK_ADDR, FORCE_CLOCK_SIZE);
-#else
-		while (1) {
-			ret = sa1100_start_dma(s->dma_regs, FORCE_CLOCK_ADDR, FORCE_CLOCK_SIZE);
-			if (ret)
-				return;   
-		}
-#endif
-		return;
-	}
-
-	/* must be set here - only valid for running streams, not for forced_clock dma fills  */
-	runtime = substream->runtime;
-	while (s->active && s->periods < runtime->periods) {
-		dma_size = frames_to_bytes(runtime, runtime->period_size);
-		if (s->old_offset) {
-			/* a little trick, we need resume from old position */
-			offset = frames_to_bytes(runtime, s->old_offset - 1);
-			s->old_offset = 0;
-			s->periods = 0;
-			s->period = offset / dma_size;
-			offset %= dma_size;
-			dma_size = dma_size - offset;
-			if (!dma_size)
-				continue;		/* special case */
-		} else {
-			offset = dma_size * s->period;
-			snd_BUG_ON(dma_size > DMA_BUF_SIZE);
-		}
-#ifdef HH_VERSION
-		ret = sa1100_dma_queue_buffer(s->dmach, s, runtime->dma_addr + offset, dma_size);
-		if (ret)
-			return; //FIXME
-#else
-		ret = sa1100_start_dma((s)->dma_regs, runtime->dma_addr + offset, dma_size);
-		if (ret) {
-			printk(KERN_ERR "audio_process_dma: cannot queue DMA buffer (%i)\n", ret);
-			return;
-		}
-#endif
-
-		s->period++;
-		s->period %= runtime->periods;
-		s->periods++;
-	}
-}
-
-#ifdef HH_VERSION
-static void audio_dma_callback(void *data, int size)
-#else
-static void audio_dma_callback(void *data)
-#endif
-{
-	struct audio_stream *s = data;
-        
-	/* 
-	 * If we are getting a callback for an active stream then we inform
-	 * the PCM middle layer we've finished a period
-	 */
- 	if (s->active)
-		snd_pcm_period_elapsed(s->stream);
-
-	spin_lock(&s->dma_lock);
-	if (!s->tx_spin && s->periods > 0)
-		s->periods--;
-	audio_process_dma(s);
-	spin_unlock(&s->dma_lock);
-}
-
-/* }}} */
-
-/* {{{ PCM setting */
-
-/* {{{ trigger & timer */
-
-static int snd_sa11xx_uda1341_trigger(struct snd_pcm_substream *substream, int cmd)
-{
-	struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
-	int stream_id = substream->pstr->stream;
-	struct audio_stream *s = &chip->s[stream_id];
-	struct audio_stream *s1 = &chip->s[stream_id ^ 1];
-	int err = 0;
-
-	/* note local interrupts are already disabled in the midlevel code */
-	spin_lock(&s->dma_lock);
-	switch (cmd) {
-	case SNDRV_PCM_TRIGGER_START:
-		/* now we need to make sure a record only stream has a clock */
-		if (stream_id == SNDRV_PCM_STREAM_CAPTURE && !s1->active) {
-			/* we need to force fill the xmit DMA with zeros */
-			s1->tx_spin = 1;
-			audio_process_dma(s1);
-		}
-		/* this case is when you were recording then you turn on a
-		 * playback stream so we stop (also clears it) the dma first,
-		 * clear the sync flag and then we let it turned on
-		 */		
-		else {
- 			s->tx_spin = 0;
- 		}
-
-		/* requested stream startup */
-		s->active = 1;
-		audio_process_dma(s);
-		break;
-	case SNDRV_PCM_TRIGGER_STOP:
-		/* requested stream shutdown */
-		audio_stop_dma(s);
-		
-		/*
-		 * now we need to make sure a record only stream has a clock
-		 * so if we're stopping a playback with an active capture
-		 * we need to turn the 0 fill dma on for the xmit side
-		 */
-		if (stream_id == SNDRV_PCM_STREAM_PLAYBACK && s1->active) {
-			/* we need to force fill the xmit DMA with zeros */
-			s->tx_spin = 1;
-			audio_process_dma(s);
-		}
-		/*
-		 * we killed a capture only stream, so we should also kill
-		 * the zero fill transmit
-		 */
-		else {
-			if (s1->tx_spin) {
-				s1->tx_spin = 0;
-				audio_stop_dma(s1);
-			}
-		}
-		
-		break;
-	case SNDRV_PCM_TRIGGER_SUSPEND:
-		s->active = 0;
-#ifdef HH_VERSION		
-		sa1100_dma_stop(s->dmach);
-#else
-		//FIXME - DMA API
-#endif		
-		s->old_offset = audio_get_dma_pos(s) + 1;
-#ifdef HH_VERSION		
-		sa1100_dma_flush_all(s->dmach);
-#else
-		//FIXME - DMA API
-#endif		
-		s->periods = 0;
-		break;
-	case SNDRV_PCM_TRIGGER_RESUME:
-		s->active = 1;
-		s->tx_spin = 0;
-		audio_process_dma(s);
-		if (stream_id == SNDRV_PCM_STREAM_CAPTURE && !s1->active) {
-			s1->tx_spin = 1;
-			audio_process_dma(s1);
-		}
-		break;
-	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
-#ifdef HH_VERSION		
-		sa1100_dma_stop(s->dmach);
-#else
-		//FIXME - DMA API
-#endif
-		s->active = 0;
-		if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
-			if (s1->active) {
-				s->tx_spin = 1;
-				s->old_offset = audio_get_dma_pos(s) + 1;
-#ifdef HH_VERSION				
-				sa1100_dma_flush_all(s->dmach);
-#else
-				//FIXME - DMA API
-#endif				
-				audio_process_dma(s);
-			}
-		} else {
-			if (s1->tx_spin) {
-				s1->tx_spin = 0;
-#ifdef HH_VERSION				
-				sa1100_dma_flush_all(s1->dmach);
-#else
-				//FIXME - DMA API
-#endif				
-			}
-		}
-		break;
-	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-		s->active = 1;
-		if (s->old_offset) {
-			s->tx_spin = 0;
-			audio_process_dma(s);
-			break;
-		}
-		if (stream_id == SNDRV_PCM_STREAM_CAPTURE && !s1->active) {
-			s1->tx_spin = 1;
-			audio_process_dma(s1);
-		}
-#ifdef HH_VERSION		
-		sa1100_dma_resume(s->dmach);
-#else
-		//FIXME - DMA API
-#endif
-		break;
-	default:
-		err = -EINVAL;
-		break;
-	}
-	spin_unlock(&s->dma_lock);	
-	return err;
-}
-
-static int snd_sa11xx_uda1341_prepare(struct snd_pcm_substream *substream)
-{
-	struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	struct audio_stream *s = &chip->s[substream->pstr->stream];
-        
-	/* set requested samplerate */
-	sa11xx_uda1341_set_samplerate(chip, runtime->rate);
-
-	/* set requestd format when available */
-	/* set FMT here !!! FIXME */
-
-	s->period = 0;
-	s->periods = 0;
-        
-	return 0;
-}
-
-static snd_pcm_uframes_t snd_sa11xx_uda1341_pointer(struct snd_pcm_substream *substream)
-{
-	struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
-	return audio_get_dma_pos(&chip->s[substream->pstr->stream]);
-}
-
-/* }}} */
-
-static struct snd_pcm_hardware snd_sa11xx_uda1341_capture =
-{
-	.info			= (SNDRV_PCM_INFO_INTERLEAVED |
-				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				   SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
-				   SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
-	.formats		= SNDRV_PCM_FMTBIT_S16_LE,
-	.rates			= (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
-				   SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |\
-				   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
-				   SNDRV_PCM_RATE_KNOT),
-	.rate_min		= 8000,
-	.rate_max		= 48000,
-	.channels_min		= 2,
-	.channels_max		= 2,
-	.buffer_bytes_max	= 64*1024,
-	.period_bytes_min	= 64,
-	.period_bytes_max	= DMA_BUF_SIZE,
-	.periods_min		= 2,
-	.periods_max		= 255,
-	.fifo_size		= 0,
-};
-
-static struct snd_pcm_hardware snd_sa11xx_uda1341_playback =
-{
-	.info			= (SNDRV_PCM_INFO_INTERLEAVED |
-				   SNDRV_PCM_INFO_BLOCK_TRANSFER |
-				   SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
-				   SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
-	.formats		= SNDRV_PCM_FMTBIT_S16_LE,
-	.rates			= (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
-                                   SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |\
-				   SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\
-				   SNDRV_PCM_RATE_KNOT),
-	.rate_min		= 8000,
-	.rate_max		= 48000,
-	.channels_min		= 2,
-	.channels_max		= 2,
-	.buffer_bytes_max	= 64*1024,
-	.period_bytes_min	= 64,
-	.period_bytes_max	= DMA_BUF_SIZE,
-	.periods_min		= 2,
-	.periods_max		= 255,
-	.fifo_size		= 0,
-};
-
-static int snd_card_sa11xx_uda1341_open(struct snd_pcm_substream *substream)
-{
-	struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
-	struct snd_pcm_runtime *runtime = substream->runtime;
-	int stream_id = substream->pstr->stream;
-	int err;
-
-	chip->s[stream_id].stream = substream;
-
-	if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
-		runtime->hw = snd_sa11xx_uda1341_playback;
-	else
-		runtime->hw = snd_sa11xx_uda1341_capture;
-	if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
-		return err;
-	if ((err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, &hw_constraints_rates)) < 0)
-		return err;
-        
-	return 0;
-}
-
-static int snd_card_sa11xx_uda1341_close(struct snd_pcm_substream *substream)
-{
-	struct sa11xx_uda1341 *chip = snd_pcm_substream_chip(substream);
-
-	chip->s[substream->pstr->stream].stream = NULL;
-	return 0;
-}
-
-/* {{{ HW params & free */
-
-static int snd_sa11xx_uda1341_hw_params(struct snd_pcm_substream *substream,
-					struct snd_pcm_hw_params *hw_params)
-{
-        
-	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_sa11xx_uda1341_hw_free(struct snd_pcm_substream *substream)
-{
-	return snd_pcm_lib_free_pages(substream);
-}
-
-/* }}} */
-
-static struct snd_pcm_ops snd_card_sa11xx_uda1341_playback_ops = {
-	.open			= snd_card_sa11xx_uda1341_open,
-	.close			= snd_card_sa11xx_uda1341_close,
-	.ioctl			= snd_pcm_lib_ioctl,
-	.hw_params	        = snd_sa11xx_uda1341_hw_params,
-	.hw_free	        = snd_sa11xx_uda1341_hw_free,
-	.prepare		= snd_sa11xx_uda1341_prepare,
-	.trigger		= snd_sa11xx_uda1341_trigger,
-	.pointer		= snd_sa11xx_uda1341_pointer,
-};
-
-static struct snd_pcm_ops snd_card_sa11xx_uda1341_capture_ops = {
-	.open			= snd_card_sa11xx_uda1341_open,
-	.close			= snd_card_sa11xx_uda1341_close,
-	.ioctl			= snd_pcm_lib_ioctl,
-	.hw_params	        = snd_sa11xx_uda1341_hw_params,
-	.hw_free	        = snd_sa11xx_uda1341_hw_free,
-	.prepare		= snd_sa11xx_uda1341_prepare,
-	.trigger		= snd_sa11xx_uda1341_trigger,
-	.pointer		= snd_sa11xx_uda1341_pointer,
-};
-
-static int __init snd_card_sa11xx_uda1341_pcm(struct sa11xx_uda1341 *sa11xx_uda1341, int device)
-{
-	struct snd_pcm *pcm;
-	int err;
-
-	if ((err = snd_pcm_new(sa11xx_uda1341->card, "UDA1341 PCM", device, 1, 1, &pcm)) < 0)
-		return err;
-
-	/*
-	 * this sets up our initial buffers and sets the dma_type to isa.
-	 * isa works but I'm not sure why (or if) it's the right choice
-	 * this may be too large, trying it for now
-	 */
-	snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 
-					      snd_dma_isa_data(),
-					      64*1024, 64*1024);
-
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_card_sa11xx_uda1341_playback_ops);
-	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_card_sa11xx_uda1341_capture_ops);
-	pcm->private_data = sa11xx_uda1341;
-	pcm->info_flags = 0;
-	strcpy(pcm->name, "UDA1341 PCM");
-
-	sa11xx_uda1341_audio_init(sa11xx_uda1341);
-
-	/* setup DMA controller */
-	audio_dma_request(&sa11xx_uda1341->s[SNDRV_PCM_STREAM_PLAYBACK], audio_dma_callback);
-	audio_dma_request(&sa11xx_uda1341->s[SNDRV_PCM_STREAM_CAPTURE], audio_dma_callback);
-
-	sa11xx_uda1341->pcm = pcm;
-
-	return 0;
-}
-
-/* }}} */
-
-/* {{{ module init & exit */
-
-#ifdef CONFIG_PM
-
-static int snd_sa11xx_uda1341_suspend(struct platform_device *devptr,
-				      pm_message_t state)
-{
-	struct snd_card *card = platform_get_drvdata(devptr);
-	struct sa11xx_uda1341 *chip = card->private_data;
-
-	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
-	snd_pcm_suspend_all(chip->pcm);
-#ifdef HH_VERSION
-	sa1100_dma_sleep(chip->s[SNDRV_PCM_STREAM_PLAYBACK].dmach);
-	sa1100_dma_sleep(chip->s[SNDRV_PCM_STREAM_CAPTURE].dmach);
-#else
-	//FIXME
-#endif
-	l3_command(chip->uda1341, CMD_SUSPEND, NULL);
-	sa11xx_uda1341_audio_shutdown(chip);
-
-	return 0;
-}
-
-static int snd_sa11xx_uda1341_resume(struct platform_device *devptr)
-{
-	struct snd_card *card = platform_get_drvdata(devptr);
-	struct sa11xx_uda1341 *chip = card->private_data;
-
-	sa11xx_uda1341_audio_init(chip);
-	l3_command(chip->uda1341, CMD_RESUME, NULL);
-#ifdef HH_VERSION	
-	sa1100_dma_wakeup(chip->s[SNDRV_PCM_STREAM_PLAYBACK].dmach);
-	sa1100_dma_wakeup(chip->s[SNDRV_PCM_STREAM_CAPTURE].dmach);
-#else
-	//FIXME
-#endif
-	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
-	return 0;
-}
-#endif /* COMFIG_PM */
-
-void snd_sa11xx_uda1341_free(struct snd_card *card)
-{
-	struct sa11xx_uda1341 *chip = card->private_data;
-
-	audio_dma_free(&chip->s[SNDRV_PCM_STREAM_PLAYBACK]);
-	audio_dma_free(&chip->s[SNDRV_PCM_STREAM_CAPTURE]);
-}
-
-static int __devinit sa11xx_uda1341_probe(struct platform_device *devptr)
-{
-	int err;
-	struct snd_card *card;
-	struct sa11xx_uda1341 *chip;
-
-	/* register the soundcard */
-	card = snd_card_new(-1, id, THIS_MODULE, sizeof(struct sa11xx_uda1341));
-	if (card == NULL)
-		return -ENOMEM;
-
-	chip = card->private_data;
-	spin_lock_init(&chip->s[0].dma_lock);
-	spin_lock_init(&chip->s[1].dma_lock);
-
-	card->private_free = snd_sa11xx_uda1341_free;
-	chip->card = card;
-	chip->samplerate = AUDIO_RATE_DEFAULT;
-
-	// mixer
-	if ((err = snd_chip_uda1341_mixer_new(card, &chip->uda1341)))
-		goto nodev;
-
-	// PCM
-	if ((err = snd_card_sa11xx_uda1341_pcm(chip, 0)) < 0)
-		goto nodev;
-        
-	strcpy(card->driver, "UDA1341");
-	strcpy(card->shortname, "H3600 UDA1341TS");
-	sprintf(card->longname, "Compaq iPAQ H3600 with Philips UDA1341TS");
-        
-	snd_card_set_dev(card, &devptr->dev);
-
-	if ((err = snd_card_register(card)) == 0) {
-		printk( KERN_INFO "iPAQ audio support initialized\n" );
-		platform_set_drvdata(devptr, card);
-		return 0;
-	}
-        
- nodev:
-	snd_card_free(card);
-	return err;
-}
-
-static int __devexit sa11xx_uda1341_remove(struct platform_device *devptr)
-{
-	snd_card_free(platform_get_drvdata(devptr));
-	platform_set_drvdata(devptr, NULL);
-	return 0;
-}
-
-#define SA11XX_UDA1341_DRIVER	"sa11xx_uda1341"
-
-static struct platform_driver sa11xx_uda1341_driver = {
-	.probe		= sa11xx_uda1341_probe,
-	.remove		= __devexit_p(sa11xx_uda1341_remove),
-#ifdef CONFIG_PM
-	.suspend	= snd_sa11xx_uda1341_suspend,
-	.resume		= snd_sa11xx_uda1341_resume,
-#endif
-	.driver		= {
-		.name	= SA11XX_UDA1341_DRIVER,
-	},
-};
-
-static int __init sa11xx_uda1341_init(void)
-{
-	int err;
-
-	if (!machine_is_h3xxx())
-		return -ENODEV;
-	if ((err = platform_driver_register(&sa11xx_uda1341_driver)) < 0)
-		return err;
-	device = platform_device_register_simple(SA11XX_UDA1341_DRIVER, -1, NULL, 0);
-	if (!IS_ERR(device)) {
-		if (platform_get_drvdata(device))
-			return 0;
-		platform_device_unregister(device);
-		err = -ENODEV;
-	} else
-		err = PTR_ERR(device);
-	platform_driver_unregister(&sa11xx_uda1341_driver);
-	return err;
-}
-
-static void __exit sa11xx_uda1341_exit(void)
-{
-	platform_device_unregister(device);
-	platform_driver_unregister(&sa11xx_uda1341_driver);
-}
-
-module_init(sa11xx_uda1341_init);
-module_exit(sa11xx_uda1341_exit);
-
-/* }}} */
-
-/*
- * Local variables:
- * indent-tabs-mode: t
- * End:
- */

+ 19 - 0
sound/atmel/Kconfig

@@ -0,0 +1,19 @@
+menu "Atmel devices (AVR32 and AT91)"
+	depends on AVR32 || ARCH_AT91
+
+config SND_ATMEL_ABDAC
+	tristate "Atmel Audio Bitstream DAC (ABDAC) driver"
+	select SND_PCM
+	depends on DW_DMAC && AVR32
+	help
+	  ALSA sound driver for the Atmel Audio Bitstream DAC (ABDAC).
+
+config SND_ATMEL_AC97C
+	tristate "Atmel AC97 Controller (AC97C) driver"
+	select SND_PCM
+	select SND_AC97_CODEC
+	depends on DW_DMAC && AVR32
+	help
+	  ALSA sound driver for the Atmel AC97 controller.
+
+endmenu

+ 5 - 0
sound/atmel/Makefile

@@ -0,0 +1,5 @@
+snd-atmel-abdac-objs		:= abdac.o
+snd-atmel-ac97c-objs		:= ac97c.o
+
+obj-$(CONFIG_SND_ATMEL_ABDAC)	+= snd-atmel-abdac.o
+obj-$(CONFIG_SND_ATMEL_AC97C)	+= snd-atmel-ac97c.o

+ 602 - 0
sound/atmel/abdac.c

@@ -0,0 +1,602 @@
+/*
+ * Driver for the Atmel on-chip Audio Bitstream DAC (ABDAC)
+ *
+ * Copyright (C) 2006-2009 Atmel Corporation
+ *
+ * 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/clk.h>
+#include <linux/bitmap.h>
+#include <linux/dw_dmac.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/atmel-abdac.h>
+
+/* DAC register offsets */
+#define DAC_DATA                                0x0000
+#define DAC_CTRL                                0x0008
+#define DAC_INT_MASK                            0x000c
+#define DAC_INT_EN                              0x0010
+#define DAC_INT_DIS                             0x0014
+#define DAC_INT_CLR                             0x0018
+#define DAC_INT_STATUS                          0x001c
+
+/* Bitfields in CTRL */
+#define DAC_SWAP_OFFSET                         30
+#define DAC_SWAP_SIZE                           1
+#define DAC_EN_OFFSET                           31
+#define DAC_EN_SIZE                             1
+
+/* Bitfields in INT_MASK/INT_EN/INT_DIS/INT_STATUS/INT_CLR */
+#define DAC_UNDERRUN_OFFSET                     28
+#define DAC_UNDERRUN_SIZE                       1
+#define DAC_TX_READY_OFFSET                     29
+#define DAC_TX_READY_SIZE                       1
+
+/* Bit manipulation macros */
+#define DAC_BIT(name)					\
+	(1 << DAC_##name##_OFFSET)
+#define DAC_BF(name, value)				\
+	(((value) & ((1 << DAC_##name##_SIZE) - 1))	\
+	 << DAC_##name##_OFFSET)
+#define DAC_BFEXT(name, value)				\
+	(((value) >> DAC_##name##_OFFSET)		\
+	 & ((1 << DAC_##name##_SIZE) - 1))
+#define DAC_BFINS(name, value, old)			\
+	(((old) & ~(((1 << DAC_##name##_SIZE) - 1)	\
+		    << DAC_##name##_OFFSET))		\
+	 | DAC_BF(name, value))
+
+/* Register access macros */
+#define dac_readl(port, reg)				\
+	__raw_readl((port)->regs + DAC_##reg)
+#define dac_writel(port, reg, value)			\
+	__raw_writel((value), (port)->regs + DAC_##reg)
+
+/*
+ * ABDAC supports a maximum of 6 different rates from a generic clock. The
+ * generic clock has a power of two divider, which gives 6 steps from 192 kHz
+ * to 5112 Hz.
+ */
+#define MAX_NUM_RATES	6
+/* ALSA seems to use rates between 192000 Hz and 5112 Hz. */
+#define RATE_MAX	192000
+#define RATE_MIN	5112
+
+enum {
+	DMA_READY = 0,
+};
+
+struct atmel_abdac_dma {
+	struct dma_chan		*chan;
+	struct dw_cyclic_desc	*cdesc;
+};
+
+struct atmel_abdac {
+	struct clk				*pclk;
+	struct clk				*sample_clk;
+	struct platform_device			*pdev;
+	struct atmel_abdac_dma			dma;
+
+	struct snd_pcm_hw_constraint_list	constraints_rates;
+	struct snd_pcm_substream		*substream;
+	struct snd_card				*card;
+	struct snd_pcm				*pcm;
+
+	void __iomem				*regs;
+	unsigned long				flags;
+	unsigned int				rates[MAX_NUM_RATES];
+	unsigned int				rates_num;
+	int					irq;
+};
+
+#define get_dac(card) ((struct atmel_abdac *)(card)->private_data)
+
+/* This function is called by the DMA driver. */
+static void atmel_abdac_dma_period_done(void *arg)
+{
+	struct atmel_abdac *dac = arg;
+	snd_pcm_period_elapsed(dac->substream);
+}
+
+static int atmel_abdac_prepare_dma(struct atmel_abdac *dac,
+		struct snd_pcm_substream *substream,
+		enum dma_data_direction direction)
+{
+	struct dma_chan			*chan = dac->dma.chan;
+	struct dw_cyclic_desc		*cdesc;
+	struct snd_pcm_runtime		*runtime = substream->runtime;
+	unsigned long			buffer_len, period_len;
+
+	/*
+	 * We don't do DMA on "complex" transfers, i.e. with
+	 * non-halfword-aligned buffers or lengths.
+	 */
+	if (runtime->dma_addr & 1 || runtime->buffer_size & 1) {
+		dev_dbg(&dac->pdev->dev, "too complex transfer\n");
+		return -EINVAL;
+	}
+
+	buffer_len = frames_to_bytes(runtime, runtime->buffer_size);
+	period_len = frames_to_bytes(runtime, runtime->period_size);
+
+	cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len,
+			period_len, DMA_TO_DEVICE);
+	if (IS_ERR(cdesc)) {
+		dev_dbg(&dac->pdev->dev, "could not prepare cyclic DMA\n");
+		return PTR_ERR(cdesc);
+	}
+
+	cdesc->period_callback = atmel_abdac_dma_period_done;
+	cdesc->period_callback_param = dac;
+
+	dac->dma.cdesc = cdesc;
+
+	set_bit(DMA_READY, &dac->flags);
+
+	return 0;
+}
+
+static struct snd_pcm_hardware atmel_abdac_hw = {
+	.info			= (SNDRV_PCM_INFO_MMAP
+				  | SNDRV_PCM_INFO_MMAP_VALID
+				  | SNDRV_PCM_INFO_INTERLEAVED
+				  | SNDRV_PCM_INFO_BLOCK_TRANSFER
+				  | SNDRV_PCM_INFO_RESUME
+				  | SNDRV_PCM_INFO_PAUSE),
+	.formats		= (SNDRV_PCM_FMTBIT_S16_BE),
+	.rates			= (SNDRV_PCM_RATE_KNOT),
+	.rate_min		= RATE_MIN,
+	.rate_max		= RATE_MAX,
+	.channels_min		= 2,
+	.channels_max		= 2,
+	.buffer_bytes_max	= 64 * 4096,
+	.period_bytes_min	= 4096,
+	.period_bytes_max	= 4096,
+	.periods_min		= 4,
+	.periods_max		= 64,
+};
+
+static int atmel_abdac_open(struct snd_pcm_substream *substream)
+{
+	struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
+
+	dac->substream = substream;
+	atmel_abdac_hw.rate_max = dac->rates[dac->rates_num - 1];
+	atmel_abdac_hw.rate_min = dac->rates[0];
+	substream->runtime->hw = atmel_abdac_hw;
+
+	return snd_pcm_hw_constraint_list(substream->runtime, 0,
+			SNDRV_PCM_HW_PARAM_RATE, &dac->constraints_rates);
+}
+
+static int atmel_abdac_close(struct snd_pcm_substream *substream)
+{
+	struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
+	dac->substream = NULL;
+	return 0;
+}
+
+static int atmel_abdac_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *hw_params)
+{
+	struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
+	int retval;
+
+	retval = snd_pcm_lib_malloc_pages(substream,
+			params_buffer_bytes(hw_params));
+	if (retval < 0)
+		return retval;
+	/* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */
+	if (retval == 1)
+		if (test_and_clear_bit(DMA_READY, &dac->flags))
+			dw_dma_cyclic_free(dac->dma.chan);
+
+	return retval;
+}
+
+static int atmel_abdac_hw_free(struct snd_pcm_substream *substream)
+{
+	struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
+	if (test_and_clear_bit(DMA_READY, &dac->flags))
+		dw_dma_cyclic_free(dac->dma.chan);
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static int atmel_abdac_prepare(struct snd_pcm_substream *substream)
+{
+	struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
+	int retval;
+
+	retval = clk_set_rate(dac->sample_clk, 256 * substream->runtime->rate);
+	if (retval)
+		return retval;
+
+	if (!test_bit(DMA_READY, &dac->flags))
+		retval = atmel_abdac_prepare_dma(dac, substream, DMA_TO_DEVICE);
+
+	return retval;
+}
+
+static int atmel_abdac_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct atmel_abdac *dac = snd_pcm_substream_chip(substream);
+	int retval = 0;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
+	case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
+	case SNDRV_PCM_TRIGGER_START:
+		clk_enable(dac->sample_clk);
+		retval = dw_dma_cyclic_start(dac->dma.chan);
+		if (retval)
+			goto out;
+		dac_writel(dac, CTRL, DAC_BIT(EN));
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
+	case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
+	case SNDRV_PCM_TRIGGER_STOP:
+		dw_dma_cyclic_stop(dac->dma.chan);
+		dac_writel(dac, DATA, 0);
+		dac_writel(dac, CTRL, 0);
+		clk_disable(dac->sample_clk);
+		break;
+	default:
+		retval = -EINVAL;
+		break;
+	}
+out:
+	return retval;
+}
+
+static snd_pcm_uframes_t
+atmel_abdac_pointer(struct snd_pcm_substream *substream)
+{
+	struct atmel_abdac	*dac = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime	*runtime = substream->runtime;
+	snd_pcm_uframes_t	frames;
+	unsigned long		bytes;
+
+	bytes = dw_dma_get_src_addr(dac->dma.chan);
+	bytes -= runtime->dma_addr;
+
+	frames = bytes_to_frames(runtime, bytes);
+	if (frames >= runtime->buffer_size)
+		frames -= runtime->buffer_size;
+
+	return frames;
+}
+
+static irqreturn_t abdac_interrupt(int irq, void *dev_id)
+{
+	struct atmel_abdac *dac = dev_id;
+	u32 status;
+
+	status = dac_readl(dac, INT_STATUS);
+	if (status & DAC_BIT(UNDERRUN)) {
+		dev_err(&dac->pdev->dev, "underrun detected\n");
+		dac_writel(dac, INT_CLR, DAC_BIT(UNDERRUN));
+	} else {
+		dev_err(&dac->pdev->dev, "spurious interrupt (status=0x%x)\n",
+			status);
+		dac_writel(dac, INT_CLR, status);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct snd_pcm_ops atmel_abdac_ops = {
+	.open		= atmel_abdac_open,
+	.close		= atmel_abdac_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= atmel_abdac_hw_params,
+	.hw_free	= atmel_abdac_hw_free,
+	.prepare	= atmel_abdac_prepare,
+	.trigger	= atmel_abdac_trigger,
+	.pointer	= atmel_abdac_pointer,
+};
+
+static int __devinit atmel_abdac_pcm_new(struct atmel_abdac *dac)
+{
+	struct snd_pcm_hardware hw = atmel_abdac_hw;
+	struct snd_pcm *pcm;
+	int retval;
+
+	retval = snd_pcm_new(dac->card, dac->card->shortname,
+			dac->pdev->id, 1, 0, &pcm);
+	if (retval)
+		return retval;
+
+	strcpy(pcm->name, dac->card->shortname);
+	pcm->private_data = dac;
+	pcm->info_flags = 0;
+	dac->pcm = pcm;
+
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_abdac_ops);
+
+	retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+			&dac->pdev->dev, hw.periods_min * hw.period_bytes_min,
+			hw.buffer_bytes_max);
+
+	return retval;
+}
+
+static bool filter(struct dma_chan *chan, void *slave)
+{
+	struct dw_dma_slave *dws = slave;
+
+	if (dws->dma_dev == chan->device->dev) {
+		chan->private = dws;
+		return true;
+	} else
+		return false;
+}
+
+static int set_sample_rates(struct atmel_abdac *dac)
+{
+	long new_rate = RATE_MAX;
+	int retval = -EINVAL;
+	int index = 0;
+
+	/* we start at 192 kHz and work our way down to 5112 Hz */
+	while (new_rate >= RATE_MIN && index < (MAX_NUM_RATES + 1)) {
+		new_rate = clk_round_rate(dac->sample_clk, 256 * new_rate);
+		if (new_rate < 0)
+			break;
+		/* make sure we are below the ABDAC clock */
+		if (new_rate <= clk_get_rate(dac->pclk)) {
+			dac->rates[index] = new_rate / 256;
+			index++;
+		}
+		/* divide by 256 and then by two to get next rate */
+		new_rate /= 256 * 2;
+	}
+
+	if (index) {
+		int i;
+
+		/* reverse array, smallest go first */
+		for (i = 0; i < (index / 2); i++) {
+			unsigned int tmp = dac->rates[index - 1 - i];
+			dac->rates[index - 1 - i] = dac->rates[i];
+			dac->rates[i] = tmp;
+		}
+
+		dac->constraints_rates.count = index;
+		dac->constraints_rates.list = dac->rates;
+		dac->constraints_rates.mask = 0;
+		dac->rates_num = index;
+
+		retval = 0;
+	}
+
+	return retval;
+}
+
+static int __devinit atmel_abdac_probe(struct platform_device *pdev)
+{
+	struct snd_card		*card;
+	struct atmel_abdac	*dac;
+	struct resource		*regs;
+	struct atmel_abdac_pdata	*pdata;
+	struct clk		*pclk;
+	struct clk		*sample_clk;
+	int			retval;
+	int			irq;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs) {
+		dev_dbg(&pdev->dev, "no memory resource\n");
+		return -ENXIO;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_dbg(&pdev->dev, "could not get IRQ number\n");
+		return irq;
+	}
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_dbg(&pdev->dev, "no platform data\n");
+		return -ENXIO;
+	}
+
+	pclk = clk_get(&pdev->dev, "pclk");
+	if (IS_ERR(pclk)) {
+		dev_dbg(&pdev->dev, "no peripheral clock\n");
+		return PTR_ERR(pclk);
+	}
+	sample_clk = clk_get(&pdev->dev, "sample_clk");
+	if (IS_ERR(pclk)) {
+		dev_dbg(&pdev->dev, "no sample clock\n");
+		retval = PTR_ERR(pclk);
+		goto out_put_pclk;
+	}
+	clk_enable(pclk);
+
+	retval = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			THIS_MODULE, sizeof(struct atmel_abdac), &card);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not create sound card device\n");
+		goto out_put_sample_clk;
+	}
+
+	dac = get_dac(card);
+
+	dac->irq = irq;
+	dac->card = card;
+	dac->pclk = pclk;
+	dac->sample_clk = sample_clk;
+	dac->pdev = pdev;
+
+	retval = set_sample_rates(dac);
+	if (retval < 0) {
+		dev_dbg(&pdev->dev, "could not set supported rates\n");
+		goto out_free_card;
+	}
+
+	dac->regs = ioremap(regs->start, regs->end - regs->start + 1);
+	if (!dac->regs) {
+		dev_dbg(&pdev->dev, "could not remap register memory\n");
+		goto out_free_card;
+	}
+
+	/* make sure the DAC is silent and disabled */
+	dac_writel(dac, DATA, 0);
+	dac_writel(dac, CTRL, 0);
+
+	retval = request_irq(irq, abdac_interrupt, 0, "abdac", dac);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not request irq\n");
+		goto out_unmap_regs;
+	}
+
+	snd_card_set_dev(card, &pdev->dev);
+
+	if (pdata->dws.dma_dev) {
+		struct dw_dma_slave *dws = &pdata->dws;
+		dma_cap_mask_t mask;
+
+		dws->tx_reg = regs->start + DAC_DATA;
+
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+
+		dac->dma.chan = dma_request_channel(mask, filter, dws);
+	}
+	if (!pdata->dws.dma_dev || !dac->dma.chan) {
+		dev_dbg(&pdev->dev, "DMA not available\n");
+		retval = -ENODEV;
+		goto out_unset_card_dev;
+	}
+
+	strcpy(card->driver, "Atmel ABDAC");
+	strcpy(card->shortname, "Atmel ABDAC");
+	sprintf(card->longname, "Atmel Audio Bitstream DAC");
+
+	retval = atmel_abdac_pcm_new(dac);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not register ABDAC pcm device\n");
+		goto out_release_dma;
+	}
+
+	retval = snd_card_register(card);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not register sound card\n");
+		goto out_release_dma;
+	}
+
+	platform_set_drvdata(pdev, card);
+
+	dev_info(&pdev->dev, "Atmel ABDAC at 0x%p using %s\n",
+			dac->regs, dac->dma.chan->dev->device.bus_id);
+
+	return retval;
+
+out_release_dma:
+	dma_release_channel(dac->dma.chan);
+	dac->dma.chan = NULL;
+out_unset_card_dev:
+	snd_card_set_dev(card, NULL);
+	free_irq(irq, dac);
+out_unmap_regs:
+	iounmap(dac->regs);
+out_free_card:
+	snd_card_free(card);
+out_put_sample_clk:
+	clk_put(sample_clk);
+	clk_disable(pclk);
+out_put_pclk:
+	clk_put(pclk);
+	return retval;
+}
+
+#ifdef CONFIG_PM
+static int atmel_abdac_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+	struct atmel_abdac *dac = card->private_data;
+
+	dw_dma_cyclic_stop(dac->dma.chan);
+	clk_disable(dac->sample_clk);
+	clk_disable(dac->pclk);
+
+	return 0;
+}
+
+static int atmel_abdac_resume(struct platform_device *pdev)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+	struct atmel_abdac *dac = card->private_data;
+
+	clk_enable(dac->pclk);
+	clk_enable(dac->sample_clk);
+	if (test_bit(DMA_READY, &dac->flags))
+		dw_dma_cyclic_start(dac->dma.chan);
+
+	return 0;
+}
+#else
+#define atmel_abdac_suspend NULL
+#define atmel_abdac_resume NULL
+#endif
+
+static int __devexit atmel_abdac_remove(struct platform_device *pdev)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+	struct atmel_abdac *dac = get_dac(card);
+
+	clk_put(dac->sample_clk);
+	clk_disable(dac->pclk);
+	clk_put(dac->pclk);
+
+	dma_release_channel(dac->dma.chan);
+	dac->dma.chan = NULL;
+	snd_card_set_dev(card, NULL);
+	iounmap(dac->regs);
+	free_irq(dac->irq, dac);
+	snd_card_free(card);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver atmel_abdac_driver = {
+	.remove		= __devexit_p(atmel_abdac_remove),
+	.driver		= {
+		.name	= "atmel_abdac",
+	},
+	.suspend	= atmel_abdac_suspend,
+	.resume		= atmel_abdac_resume,
+};
+
+static int __init atmel_abdac_init(void)
+{
+	return platform_driver_probe(&atmel_abdac_driver,
+			atmel_abdac_probe);
+}
+module_init(atmel_abdac_init);
+
+static void __exit atmel_abdac_exit(void)
+{
+	platform_driver_unregister(&atmel_abdac_driver);
+}
+module_exit(atmel_abdac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Driver for Atmel Audio Bitstream DAC (ABDAC)");
+MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");

+ 932 - 0
sound/atmel/ac97c.c

@@ -0,0 +1,932 @@
+/*
+ * Driver for the Atmel AC97C controller
+ *
+ * Copyright (C) 2005-2009 Atmel Corporation
+ *
+ * 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/clk.h>
+#include <linux/delay.h>
+#include <linux/bitmap.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/ac97_codec.h>
+#include <sound/atmel-ac97c.h>
+#include <sound/memalloc.h>
+
+#include <linux/dw_dmac.h>
+
+#include "ac97c.h"
+
+enum {
+	DMA_TX_READY = 0,
+	DMA_RX_READY,
+	DMA_TX_CHAN_PRESENT,
+	DMA_RX_CHAN_PRESENT,
+};
+
+/* Serialize access to opened variable */
+static DEFINE_MUTEX(opened_mutex);
+
+struct atmel_ac97c_dma {
+	struct dma_chan			*rx_chan;
+	struct dma_chan			*tx_chan;
+};
+
+struct atmel_ac97c {
+	struct clk			*pclk;
+	struct platform_device		*pdev;
+	struct atmel_ac97c_dma		dma;
+
+	struct snd_pcm_substream	*playback_substream;
+	struct snd_pcm_substream	*capture_substream;
+	struct snd_card			*card;
+	struct snd_pcm			*pcm;
+	struct snd_ac97			*ac97;
+	struct snd_ac97_bus		*ac97_bus;
+
+	u64				cur_format;
+	unsigned int			cur_rate;
+	unsigned long			flags;
+	/* Serialize access to opened variable */
+	spinlock_t			lock;
+	void __iomem			*regs;
+	int				opened;
+	int				reset_pin;
+};
+
+#define get_chip(card) ((struct atmel_ac97c *)(card)->private_data)
+
+#define ac97c_writel(chip, reg, val)			\
+	__raw_writel((val), (chip)->regs + AC97C_##reg)
+#define ac97c_readl(chip, reg)				\
+	__raw_readl((chip)->regs + AC97C_##reg)
+
+/* This function is called by the DMA driver. */
+static void atmel_ac97c_dma_playback_period_done(void *arg)
+{
+	struct atmel_ac97c *chip = arg;
+	snd_pcm_period_elapsed(chip->playback_substream);
+}
+
+static void atmel_ac97c_dma_capture_period_done(void *arg)
+{
+	struct atmel_ac97c *chip = arg;
+	snd_pcm_period_elapsed(chip->capture_substream);
+}
+
+static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip,
+		struct snd_pcm_substream *substream,
+		enum dma_data_direction direction)
+{
+	struct dma_chan			*chan;
+	struct dw_cyclic_desc		*cdesc;
+	struct snd_pcm_runtime		*runtime = substream->runtime;
+	unsigned long			buffer_len, period_len;
+
+	/*
+	 * We don't do DMA on "complex" transfers, i.e. with
+	 * non-halfword-aligned buffers or lengths.
+	 */
+	if (runtime->dma_addr & 1 || runtime->buffer_size & 1) {
+		dev_dbg(&chip->pdev->dev, "too complex transfer\n");
+		return -EINVAL;
+	}
+
+	if (direction == DMA_TO_DEVICE)
+		chan = chip->dma.tx_chan;
+	else
+		chan = chip->dma.rx_chan;
+
+	buffer_len = frames_to_bytes(runtime, runtime->buffer_size);
+	period_len = frames_to_bytes(runtime, runtime->period_size);
+
+	cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len,
+			period_len, direction);
+	if (IS_ERR(cdesc)) {
+		dev_dbg(&chip->pdev->dev, "could not prepare cyclic DMA\n");
+		return PTR_ERR(cdesc);
+	}
+
+	if (direction == DMA_TO_DEVICE) {
+		cdesc->period_callback = atmel_ac97c_dma_playback_period_done;
+		set_bit(DMA_TX_READY, &chip->flags);
+	} else {
+		cdesc->period_callback = atmel_ac97c_dma_capture_period_done;
+		set_bit(DMA_RX_READY, &chip->flags);
+	}
+
+	cdesc->period_callback_param = chip;
+
+	return 0;
+}
+
+static struct snd_pcm_hardware atmel_ac97c_hw = {
+	.info			= (SNDRV_PCM_INFO_MMAP
+				  | SNDRV_PCM_INFO_MMAP_VALID
+				  | SNDRV_PCM_INFO_INTERLEAVED
+				  | SNDRV_PCM_INFO_BLOCK_TRANSFER
+				  | SNDRV_PCM_INFO_JOINT_DUPLEX
+				  | SNDRV_PCM_INFO_RESUME
+				  | SNDRV_PCM_INFO_PAUSE),
+	.formats		= (SNDRV_PCM_FMTBIT_S16_BE
+				  | SNDRV_PCM_FMTBIT_S16_LE),
+	.rates			= (SNDRV_PCM_RATE_CONTINUOUS),
+	.rate_min		= 4000,
+	.rate_max		= 48000,
+	.channels_min		= 1,
+	.channels_max		= 2,
+	.buffer_bytes_max	= 64 * 4096,
+	.period_bytes_min	= 4096,
+	.period_bytes_max	= 4096,
+	.periods_min		= 4,
+	.periods_max		= 64,
+};
+
+static int atmel_ac97c_playback_open(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	mutex_lock(&opened_mutex);
+	chip->opened++;
+	runtime->hw = atmel_ac97c_hw;
+	if (chip->cur_rate) {
+		runtime->hw.rate_min = chip->cur_rate;
+		runtime->hw.rate_max = chip->cur_rate;
+	}
+	if (chip->cur_format)
+		runtime->hw.formats = (1ULL << chip->cur_format);
+	mutex_unlock(&opened_mutex);
+	chip->playback_substream = substream;
+	return 0;
+}
+
+static int atmel_ac97c_capture_open(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+
+	mutex_lock(&opened_mutex);
+	chip->opened++;
+	runtime->hw = atmel_ac97c_hw;
+	if (chip->cur_rate) {
+		runtime->hw.rate_min = chip->cur_rate;
+		runtime->hw.rate_max = chip->cur_rate;
+	}
+	if (chip->cur_format)
+		runtime->hw.formats = (1ULL << chip->cur_format);
+	mutex_unlock(&opened_mutex);
+	chip->capture_substream = substream;
+	return 0;
+}
+
+static int atmel_ac97c_playback_close(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+
+	mutex_lock(&opened_mutex);
+	chip->opened--;
+	if (!chip->opened) {
+		chip->cur_rate = 0;
+		chip->cur_format = 0;
+	}
+	mutex_unlock(&opened_mutex);
+
+	chip->playback_substream = NULL;
+
+	return 0;
+}
+
+static int atmel_ac97c_capture_close(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+
+	mutex_lock(&opened_mutex);
+	chip->opened--;
+	if (!chip->opened) {
+		chip->cur_rate = 0;
+		chip->cur_format = 0;
+	}
+	mutex_unlock(&opened_mutex);
+
+	chip->capture_substream = NULL;
+
+	return 0;
+}
+
+static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *hw_params)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	int retval;
+
+	retval = snd_pcm_lib_malloc_pages(substream,
+					params_buffer_bytes(hw_params));
+	if (retval < 0)
+		return retval;
+	/* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */
+	if (retval == 1)
+		if (test_and_clear_bit(DMA_TX_READY, &chip->flags))
+			dw_dma_cyclic_free(chip->dma.tx_chan);
+
+	/* Set restrictions to params. */
+	mutex_lock(&opened_mutex);
+	chip->cur_rate = params_rate(hw_params);
+	chip->cur_format = params_format(hw_params);
+	mutex_unlock(&opened_mutex);
+
+	return retval;
+}
+
+static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream,
+		struct snd_pcm_hw_params *hw_params)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	int retval;
+
+	retval = snd_pcm_lib_malloc_pages(substream,
+					params_buffer_bytes(hw_params));
+	if (retval < 0)
+		return retval;
+	/* snd_pcm_lib_malloc_pages returns 1 if buffer is changed. */
+	if (retval == 1)
+		if (test_and_clear_bit(DMA_RX_READY, &chip->flags))
+			dw_dma_cyclic_free(chip->dma.rx_chan);
+
+	/* Set restrictions to params. */
+	mutex_lock(&opened_mutex);
+	chip->cur_rate = params_rate(hw_params);
+	chip->cur_format = params_format(hw_params);
+	mutex_unlock(&opened_mutex);
+
+	return retval;
+}
+
+static int atmel_ac97c_playback_hw_free(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	if (test_and_clear_bit(DMA_TX_READY, &chip->flags))
+		dw_dma_cyclic_free(chip->dma.tx_chan);
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static int atmel_ac97c_capture_hw_free(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	if (test_and_clear_bit(DMA_RX_READY, &chip->flags))
+		dw_dma_cyclic_free(chip->dma.rx_chan);
+	return snd_pcm_lib_free_pages(substream);
+}
+
+static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	unsigned long word = 0;
+	int retval;
+
+	/* assign channels to AC97C channel A */
+	switch (runtime->channels) {
+	case 1:
+		word |= AC97C_CH_ASSIGN(PCM_LEFT, A);
+		break;
+	case 2:
+		word |= AC97C_CH_ASSIGN(PCM_LEFT, A)
+			| AC97C_CH_ASSIGN(PCM_RIGHT, A);
+		break;
+	default:
+		/* TODO: support more than two channels */
+		return -EINVAL;
+		break;
+	}
+	ac97c_writel(chip, OCA, word);
+
+	/* configure sample format and size */
+	word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;
+
+	switch (runtime->format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		word |= AC97C_CMR_CEM_LITTLE;
+		break;
+	case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
+	default:
+		word &= ~(AC97C_CMR_CEM_LITTLE);
+		break;
+	}
+
+	ac97c_writel(chip, CAMR, word);
+
+	/* set variable rate if needed */
+	if (runtime->rate != 48000) {
+		word = ac97c_readl(chip, MR);
+		word |= AC97C_MR_VRA;
+		ac97c_writel(chip, MR, word);
+	} else {
+		word = ac97c_readl(chip, MR);
+		word &= ~(AC97C_MR_VRA);
+		ac97c_writel(chip, MR, word);
+	}
+
+	retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_FRONT_DAC_RATE,
+			runtime->rate);
+	if (retval)
+		dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n",
+				runtime->rate);
+
+	if (!test_bit(DMA_TX_READY, &chip->flags))
+		retval = atmel_ac97c_prepare_dma(chip, substream,
+				DMA_TO_DEVICE);
+
+	return retval;
+}
+
+static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	unsigned long word = 0;
+	int retval;
+
+	/* assign channels to AC97C channel A */
+	switch (runtime->channels) {
+	case 1:
+		word |= AC97C_CH_ASSIGN(PCM_LEFT, A);
+		break;
+	case 2:
+		word |= AC97C_CH_ASSIGN(PCM_LEFT, A)
+			| AC97C_CH_ASSIGN(PCM_RIGHT, A);
+		break;
+	default:
+		/* TODO: support more than two channels */
+		return -EINVAL;
+		break;
+	}
+	ac97c_writel(chip, ICA, word);
+
+	/* configure sample format and size */
+	word = AC97C_CMR_DMAEN | AC97C_CMR_SIZE_16;
+
+	switch (runtime->format) {
+	case SNDRV_PCM_FORMAT_S16_LE:
+		word |= AC97C_CMR_CEM_LITTLE;
+		break;
+	case SNDRV_PCM_FORMAT_S16_BE: /* fall through */
+	default:
+		word &= ~(AC97C_CMR_CEM_LITTLE);
+		break;
+	}
+
+	ac97c_writel(chip, CAMR, word);
+
+	/* set variable rate if needed */
+	if (runtime->rate != 48000) {
+		word = ac97c_readl(chip, MR);
+		word |= AC97C_MR_VRA;
+		ac97c_writel(chip, MR, word);
+	} else {
+		word = ac97c_readl(chip, MR);
+		word &= ~(AC97C_MR_VRA);
+		ac97c_writel(chip, MR, word);
+	}
+
+	retval = snd_ac97_set_rate(chip->ac97, AC97_PCM_LR_ADC_RATE,
+			runtime->rate);
+	if (retval)
+		dev_dbg(&chip->pdev->dev, "could not set rate %d Hz\n",
+				runtime->rate);
+
+	if (!test_bit(DMA_RX_READY, &chip->flags))
+		retval = atmel_ac97c_prepare_dma(chip, substream,
+				DMA_FROM_DEVICE);
+
+	return retval;
+}
+
+static int
+atmel_ac97c_playback_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	unsigned long camr;
+	int retval = 0;
+
+	camr = ac97c_readl(chip, CAMR);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
+	case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
+	case SNDRV_PCM_TRIGGER_START:
+		retval = dw_dma_cyclic_start(chip->dma.tx_chan);
+		if (retval)
+			goto out;
+		camr |= AC97C_CMR_CENA;
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
+	case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
+	case SNDRV_PCM_TRIGGER_STOP:
+		dw_dma_cyclic_stop(chip->dma.tx_chan);
+		if (chip->opened <= 1)
+			camr &= ~AC97C_CMR_CENA;
+		break;
+	default:
+		retval = -EINVAL;
+		goto out;
+	}
+
+	ac97c_writel(chip, CAMR, camr);
+out:
+	return retval;
+}
+
+static int
+atmel_ac97c_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+	struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
+	unsigned long camr;
+	int retval = 0;
+
+	camr = ac97c_readl(chip, CAMR);
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */
+	case SNDRV_PCM_TRIGGER_RESUME: /* fall through */
+	case SNDRV_PCM_TRIGGER_START:
+		retval = dw_dma_cyclic_start(chip->dma.rx_chan);
+		if (retval)
+			goto out;
+		camr |= AC97C_CMR_CENA;
+		break;
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */
+	case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */
+	case SNDRV_PCM_TRIGGER_STOP:
+		dw_dma_cyclic_stop(chip->dma.rx_chan);
+		if (chip->opened <= 1)
+			camr &= ~AC97C_CMR_CENA;
+		break;
+	default:
+		retval = -EINVAL;
+		break;
+	}
+
+	ac97c_writel(chip, CAMR, camr);
+out:
+	return retval;
+}
+
+static snd_pcm_uframes_t
+atmel_ac97c_playback_pointer(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c	*chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime	*runtime = substream->runtime;
+	snd_pcm_uframes_t	frames;
+	unsigned long		bytes;
+
+	bytes = dw_dma_get_src_addr(chip->dma.tx_chan);
+	bytes -= runtime->dma_addr;
+
+	frames = bytes_to_frames(runtime, bytes);
+	if (frames >= runtime->buffer_size)
+		frames -= runtime->buffer_size;
+	return frames;
+}
+
+static snd_pcm_uframes_t
+atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream)
+{
+	struct atmel_ac97c	*chip = snd_pcm_substream_chip(substream);
+	struct snd_pcm_runtime	*runtime = substream->runtime;
+	snd_pcm_uframes_t	frames;
+	unsigned long		bytes;
+
+	bytes = dw_dma_get_dst_addr(chip->dma.rx_chan);
+	bytes -= runtime->dma_addr;
+
+	frames = bytes_to_frames(runtime, bytes);
+	if (frames >= runtime->buffer_size)
+		frames -= runtime->buffer_size;
+	return frames;
+}
+
+static struct snd_pcm_ops atmel_ac97_playback_ops = {
+	.open		= atmel_ac97c_playback_open,
+	.close		= atmel_ac97c_playback_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= atmel_ac97c_playback_hw_params,
+	.hw_free	= atmel_ac97c_playback_hw_free,
+	.prepare	= atmel_ac97c_playback_prepare,
+	.trigger	= atmel_ac97c_playback_trigger,
+	.pointer	= atmel_ac97c_playback_pointer,
+};
+
+static struct snd_pcm_ops atmel_ac97_capture_ops = {
+	.open		= atmel_ac97c_capture_open,
+	.close		= atmel_ac97c_capture_close,
+	.ioctl		= snd_pcm_lib_ioctl,
+	.hw_params	= atmel_ac97c_capture_hw_params,
+	.hw_free	= atmel_ac97c_capture_hw_free,
+	.prepare	= atmel_ac97c_capture_prepare,
+	.trigger	= atmel_ac97c_capture_trigger,
+	.pointer	= atmel_ac97c_capture_pointer,
+};
+
+static int __devinit atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
+{
+	struct snd_pcm		*pcm;
+	struct snd_pcm_hardware	hw = atmel_ac97c_hw;
+	int			capture, playback, retval;
+
+	capture = test_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
+	playback = test_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
+
+	retval = snd_pcm_new(chip->card, chip->card->shortname,
+			chip->pdev->id, playback, capture, &pcm);
+	if (retval)
+		return retval;
+
+	if (capture)
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+				&atmel_ac97_capture_ops);
+	if (playback)
+		snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+				&atmel_ac97_playback_ops);
+
+	retval = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+			&chip->pdev->dev, hw.periods_min * hw.period_bytes_min,
+			hw.buffer_bytes_max);
+	if (retval)
+		return retval;
+
+	pcm->private_data = chip;
+	pcm->info_flags = 0;
+	strcpy(pcm->name, chip->card->shortname);
+	chip->pcm = pcm;
+
+	return 0;
+}
+
+static int atmel_ac97c_mixer_new(struct atmel_ac97c *chip)
+{
+	struct snd_ac97_template template;
+	memset(&template, 0, sizeof(template));
+	template.private_data = chip;
+	return snd_ac97_mixer(chip->ac97_bus, &template, &chip->ac97);
+}
+
+static void atmel_ac97c_write(struct snd_ac97 *ac97, unsigned short reg,
+		unsigned short val)
+{
+	struct atmel_ac97c *chip = get_chip(ac97);
+	unsigned long word;
+	int timeout = 40;
+
+	word = (reg & 0x7f) << 16 | val;
+
+	do {
+		if (ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) {
+			ac97c_writel(chip, COTHR, word);
+			return;
+		}
+		udelay(1);
+	} while (--timeout);
+
+	dev_dbg(&chip->pdev->dev, "codec write timeout\n");
+}
+
+static unsigned short atmel_ac97c_read(struct snd_ac97 *ac97,
+		unsigned short reg)
+{
+	struct atmel_ac97c *chip = get_chip(ac97);
+	unsigned long word;
+	int timeout = 40;
+	int write = 10;
+
+	word = (0x80 | (reg & 0x7f)) << 16;
+
+	if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0)
+		ac97c_readl(chip, CORHR);
+
+retry_write:
+	timeout = 40;
+
+	do {
+		if ((ac97c_readl(chip, COSR) & AC97C_CSR_TXRDY) != 0) {
+			ac97c_writel(chip, COTHR, word);
+			goto read_reg;
+		}
+		udelay(10);
+	} while (--timeout);
+
+	if (!--write)
+		goto timed_out;
+	goto retry_write;
+
+read_reg:
+	do {
+		if ((ac97c_readl(chip, COSR) & AC97C_CSR_RXRDY) != 0) {
+			unsigned short val = ac97c_readl(chip, CORHR);
+			return val;
+		}
+		udelay(10);
+	} while (--timeout);
+
+	if (!--write)
+		goto timed_out;
+	goto retry_write;
+
+timed_out:
+	dev_dbg(&chip->pdev->dev, "codec read timeout\n");
+	return 0xffff;
+}
+
+static bool filter(struct dma_chan *chan, void *slave)
+{
+	struct dw_dma_slave *dws = slave;
+
+	if (dws->dma_dev == chan->device->dev) {
+		chan->private = dws;
+		return true;
+	} else
+		return false;
+}
+
+static void atmel_ac97c_reset(struct atmel_ac97c *chip)
+{
+	ac97c_writel(chip, MR, AC97C_MR_WRST);
+
+	if (gpio_is_valid(chip->reset_pin)) {
+		gpio_set_value(chip->reset_pin, 0);
+		/* AC97 v2.2 specifications says minimum 1 us. */
+		udelay(10);
+		gpio_set_value(chip->reset_pin, 1);
+	}
+
+	udelay(1);
+	ac97c_writel(chip, MR, AC97C_MR_ENA);
+}
+
+static int __devinit atmel_ac97c_probe(struct platform_device *pdev)
+{
+	struct snd_card			*card;
+	struct atmel_ac97c		*chip;
+	struct resource			*regs;
+	struct ac97c_platform_data	*pdata;
+	struct clk			*pclk;
+	static struct snd_ac97_bus_ops	ops = {
+		.write	= atmel_ac97c_write,
+		.read	= atmel_ac97c_read,
+	};
+	int				retval;
+
+	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!regs) {
+		dev_dbg(&pdev->dev, "no memory resource\n");
+		return -ENXIO;
+	}
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_dbg(&pdev->dev, "no platform data\n");
+		return -ENXIO;
+	}
+
+	pclk = clk_get(&pdev->dev, "pclk");
+	if (IS_ERR(pclk)) {
+		dev_dbg(&pdev->dev, "no peripheral clock\n");
+		return PTR_ERR(pclk);
+	}
+	clk_enable(pclk);
+
+	retval = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+			THIS_MODULE, sizeof(struct atmel_ac97c), &card);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not create sound card device\n");
+		goto err_snd_card_new;
+	}
+
+	chip = get_chip(card);
+
+	spin_lock_init(&chip->lock);
+
+	strcpy(card->driver, "Atmel AC97C");
+	strcpy(card->shortname, "Atmel AC97C");
+	sprintf(card->longname, "Atmel AC97 controller");
+
+	chip->card = card;
+	chip->pclk = pclk;
+	chip->pdev = pdev;
+	chip->regs = ioremap(regs->start, regs->end - regs->start + 1);
+
+	if (!chip->regs) {
+		dev_dbg(&pdev->dev, "could not remap register memory\n");
+		goto err_ioremap;
+	}
+
+	if (gpio_is_valid(pdata->reset_pin)) {
+		if (gpio_request(pdata->reset_pin, "reset_pin")) {
+			dev_dbg(&pdev->dev, "reset pin not available\n");
+			chip->reset_pin = -ENODEV;
+		} else {
+			gpio_direction_output(pdata->reset_pin, 1);
+			chip->reset_pin = pdata->reset_pin;
+		}
+	}
+
+	snd_card_set_dev(card, &pdev->dev);
+
+	retval = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not register on ac97 bus\n");
+		goto err_ac97_bus;
+	}
+
+	atmel_ac97c_reset(chip);
+
+	retval = atmel_ac97c_mixer_new(chip);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not register ac97 mixer\n");
+		goto err_ac97_bus;
+	}
+
+	if (pdata->rx_dws.dma_dev) {
+		struct dw_dma_slave *dws = &pdata->rx_dws;
+		dma_cap_mask_t mask;
+
+		dws->rx_reg = regs->start + AC97C_CARHR + 2;
+
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+
+		chip->dma.rx_chan = dma_request_channel(mask, filter, dws);
+
+		dev_info(&chip->pdev->dev, "using %s for DMA RX\n",
+					chip->dma.rx_chan->dev->device.bus_id);
+		set_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
+	}
+
+	if (pdata->tx_dws.dma_dev) {
+		struct dw_dma_slave *dws = &pdata->tx_dws;
+		dma_cap_mask_t mask;
+
+		dws->tx_reg = regs->start + AC97C_CATHR + 2;
+
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+
+		chip->dma.tx_chan = dma_request_channel(mask, filter, dws);
+
+		dev_info(&chip->pdev->dev, "using %s for DMA TX\n",
+					chip->dma.tx_chan->dev->device.bus_id);
+		set_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
+	}
+
+	if (!test_bit(DMA_RX_CHAN_PRESENT, &chip->flags) &&
+			!test_bit(DMA_TX_CHAN_PRESENT, &chip->flags)) {
+		dev_dbg(&pdev->dev, "DMA not available\n");
+		retval = -ENODEV;
+		goto err_dma;
+	}
+
+	retval = atmel_ac97c_pcm_new(chip);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not register ac97 pcm device\n");
+		goto err_dma;
+	}
+
+	retval = snd_card_register(card);
+	if (retval) {
+		dev_dbg(&pdev->dev, "could not register sound card\n");
+		goto err_ac97_bus;
+	}
+
+	platform_set_drvdata(pdev, card);
+
+	dev_info(&pdev->dev, "Atmel AC97 controller at 0x%p\n",
+			chip->regs);
+
+	return 0;
+
+err_dma:
+	if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags))
+		dma_release_channel(chip->dma.rx_chan);
+	if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags))
+		dma_release_channel(chip->dma.tx_chan);
+	clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
+	clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
+	chip->dma.rx_chan = NULL;
+	chip->dma.tx_chan = NULL;
+err_ac97_bus:
+	snd_card_set_dev(card, NULL);
+
+	if (gpio_is_valid(chip->reset_pin))
+		gpio_free(chip->reset_pin);
+
+	iounmap(chip->regs);
+err_ioremap:
+	snd_card_free(card);
+err_snd_card_new:
+	clk_disable(pclk);
+	clk_put(pclk);
+	return retval;
+}
+
+#ifdef CONFIG_PM
+static int atmel_ac97c_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+	struct atmel_ac97c *chip = card->private_data;
+
+	if (test_bit(DMA_RX_READY, &chip->flags))
+		dw_dma_cyclic_stop(chip->dma.rx_chan);
+	if (test_bit(DMA_TX_READY, &chip->flags))
+		dw_dma_cyclic_stop(chip->dma.tx_chan);
+	clk_disable(chip->pclk);
+
+	return 0;
+}
+
+static int atmel_ac97c_resume(struct platform_device *pdev)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+	struct atmel_ac97c *chip = card->private_data;
+
+	clk_enable(chip->pclk);
+	if (test_bit(DMA_RX_READY, &chip->flags))
+		dw_dma_cyclic_start(chip->dma.rx_chan);
+	if (test_bit(DMA_TX_READY, &chip->flags))
+		dw_dma_cyclic_start(chip->dma.tx_chan);
+
+	return 0;
+}
+#else
+#define atmel_ac97c_suspend NULL
+#define atmel_ac97c_resume NULL
+#endif
+
+static int __devexit atmel_ac97c_remove(struct platform_device *pdev)
+{
+	struct snd_card *card = platform_get_drvdata(pdev);
+	struct atmel_ac97c *chip = get_chip(card);
+
+	if (gpio_is_valid(chip->reset_pin))
+		gpio_free(chip->reset_pin);
+
+	clk_disable(chip->pclk);
+	clk_put(chip->pclk);
+	iounmap(chip->regs);
+
+	if (test_bit(DMA_RX_CHAN_PRESENT, &chip->flags))
+		dma_release_channel(chip->dma.rx_chan);
+	if (test_bit(DMA_TX_CHAN_PRESENT, &chip->flags))
+		dma_release_channel(chip->dma.tx_chan);
+	clear_bit(DMA_RX_CHAN_PRESENT, &chip->flags);
+	clear_bit(DMA_TX_CHAN_PRESENT, &chip->flags);
+	chip->dma.rx_chan = NULL;
+	chip->dma.tx_chan = NULL;
+
+	snd_card_set_dev(card, NULL);
+	snd_card_free(card);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver atmel_ac97c_driver = {
+	.remove		= __devexit_p(atmel_ac97c_remove),
+	.driver		= {
+		.name	= "atmel_ac97c",
+	},
+	.suspend	= atmel_ac97c_suspend,
+	.resume		= atmel_ac97c_resume,
+};
+
+static int __init atmel_ac97c_init(void)
+{
+	return platform_driver_probe(&atmel_ac97c_driver,
+			atmel_ac97c_probe);
+}
+module_init(atmel_ac97c_init);
+
+static void __exit atmel_ac97c_exit(void)
+{
+	platform_driver_unregister(&atmel_ac97c_driver);
+}
+module_exit(atmel_ac97c_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Driver for Atmel AC97 controller");
+MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>");

+ 71 - 0
sound/atmel/ac97c.h

@@ -0,0 +1,71 @@
+/*
+ * Register definitions for the Atmel AC97C controller
+ *
+ * Copyright (C) 2005-2009 Atmel Corporation
+ *
+ * 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 __SOUND_ATMEL_AC97C_H
+#define __SOUND_ATMEL_AC97C_H
+
+#define AC97C_MR		0x08
+#define AC97C_ICA		0x10
+#define AC97C_OCA		0x14
+#define AC97C_CARHR		0x20
+#define AC97C_CATHR		0x24
+#define AC97C_CASR		0x28
+#define AC97C_CAMR		0x2c
+#define AC97C_CBRHR		0x30
+#define AC97C_CBTHR		0x34
+#define AC97C_CBSR		0x38
+#define AC97C_CBMR		0x3c
+#define AC97C_CORHR		0x40
+#define AC97C_COTHR		0x44
+#define AC97C_COSR		0x48
+#define AC97C_COMR		0x4c
+#define AC97C_SR		0x50
+#define AC97C_IER		0x54
+#define AC97C_IDR		0x58
+#define AC97C_IMR		0x5c
+#define AC97C_VERSION		0xfc
+
+#define AC97C_CATPR		PDC_TPR
+#define AC97C_CATCR		PDC_TCR
+#define AC97C_CATNPR		PDC_TNPR
+#define AC97C_CATNCR		PDC_TNCR
+#define AC97C_CARPR		PDC_RPR
+#define AC97C_CARCR		PDC_RCR
+#define AC97C_CARNPR		PDC_RNPR
+#define AC97C_CARNCR		PDC_RNCR
+#define AC97C_PTCR		PDC_PTCR
+
+#define AC97C_MR_ENA		(1 << 0)
+#define AC97C_MR_WRST		(1 << 1)
+#define AC97C_MR_VRA		(1 << 2)
+
+#define AC97C_CSR_TXRDY		(1 << 0)
+#define AC97C_CSR_UNRUN		(1 << 2)
+#define AC97C_CSR_RXRDY		(1 << 4)
+#define AC97C_CSR_ENDTX		(1 << 10)
+#define AC97C_CSR_ENDRX		(1 << 14)
+
+#define AC97C_CMR_SIZE_20	(0 << 16)
+#define AC97C_CMR_SIZE_18	(1 << 16)
+#define AC97C_CMR_SIZE_16	(2 << 16)
+#define AC97C_CMR_SIZE_10	(3 << 16)
+#define AC97C_CMR_CEM_LITTLE	(1 << 18)
+#define AC97C_CMR_CEM_BIG	(0 << 18)
+#define AC97C_CMR_CENA		(1 << 21)
+#define AC97C_CMR_DMAEN		(1 << 22)
+
+#define AC97C_SR_CAEVT		(1 << 3)
+
+#define AC97C_CH_ASSIGN(slot, channel)					\
+	(AC97C_CHANNEL_##channel << (3 * (AC97_SLOT_##slot - 3)))
+#define AC97C_CHANNEL_NONE	0x0
+#define AC97C_CHANNEL_A		0x1
+#define AC97C_CHANNEL_B		0x2
+
+#endif /* __SOUND_ATMEL_AC97C_H */

+ 5 - 4
sound/core/hwdep.c

@@ -99,9 +99,6 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
 	if (hw == NULL)
 	if (hw == NULL)
 		return -ENODEV;
 		return -ENODEV;
 
 
-	if (!hw->ops.open)
-		return -ENXIO;
-
 	if (!try_module_get(hw->card->module))
 	if (!try_module_get(hw->card->module))
 		return -EFAULT;
 		return -EFAULT;
 
 
@@ -113,6 +110,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
 			err = -EBUSY;
 			err = -EBUSY;
 			break;
 			break;
 		}
 		}
+		if (!hw->ops.open) {
+			err = 0;
+			break;
+		}
 		err = hw->ops.open(hw, file);
 		err = hw->ops.open(hw, file);
 		if (err >= 0)
 		if (err >= 0)
 			break;
 			break;
@@ -151,7 +152,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)
 
 
 static int snd_hwdep_release(struct inode *inode, struct file * file)
 static int snd_hwdep_release(struct inode *inode, struct file * file)
 {
 {
-	int err = -ENXIO;
+	int err = 0;
 	struct snd_hwdep *hw = file->private_data;
 	struct snd_hwdep *hw = file->private_data;
 	struct module *mod = hw->card->module;
 	struct module *mod = hw->card->module;
 
 

+ 46 - 43
sound/core/init.c

@@ -121,31 +121,44 @@ static inline int init_info_for_card(struct snd_card *card)
 #endif
 #endif
 
 
 /**
 /**
- *  snd_card_new - create and initialize a soundcard structure
+ *  snd_card_create - create and initialize a soundcard structure
  *  @idx: card index (address) [0 ... (SNDRV_CARDS-1)]
  *  @idx: card index (address) [0 ... (SNDRV_CARDS-1)]
  *  @xid: card identification (ASCII string)
  *  @xid: card identification (ASCII string)
  *  @module: top level module for locking
  *  @module: top level module for locking
  *  @extra_size: allocate this extra size after the main soundcard structure
  *  @extra_size: allocate this extra size after the main soundcard structure
+ *  @card_ret: the pointer to store the created card instance
  *
  *
  *  Creates and initializes a soundcard structure.
  *  Creates and initializes a soundcard structure.
  *
  *
- *  Returns kmallocated snd_card structure. Creates the ALSA control interface
- *  (which is blocked until snd_card_register function is called).
+ *  The function allocates snd_card instance via kzalloc with the given
+ *  space for the driver to use freely.  The allocated struct is stored
+ *  in the given card_ret pointer.
+ *
+ *  Returns zero if successful or a negative error code.
  */
  */
-struct snd_card *snd_card_new(int idx, const char *xid,
-			 struct module *module, int extra_size)
+int snd_card_create(int idx, const char *xid,
+		    struct module *module, int extra_size,
+		    struct snd_card **card_ret)
 {
 {
 	struct snd_card *card;
 	struct snd_card *card;
 	int err, idx2;
 	int err, idx2;
 
 
+	if (snd_BUG_ON(!card_ret))
+		return -EINVAL;
+	*card_ret = NULL;
+
 	if (extra_size < 0)
 	if (extra_size < 0)
 		extra_size = 0;
 		extra_size = 0;
 	card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
 	card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
-	if (card == NULL)
-		return NULL;
+	if (!card)
+		return -ENOMEM;
 	if (xid) {
 	if (xid) {
-		if (!snd_info_check_reserved_words(xid))
+		if (!snd_info_check_reserved_words(xid)) {
+			snd_printk(KERN_ERR
+				   "given id string '%s' is reserved.\n", xid);
+			err = -EBUSY;
 			goto __error;
 			goto __error;
+		}
 		strlcpy(card->id, xid, sizeof(card->id));
 		strlcpy(card->id, xid, sizeof(card->id));
 	}
 	}
 	err = 0;
 	err = 0;
@@ -195,6 +208,7 @@ struct snd_card *snd_card_new(int idx, const char *xid,
 	INIT_LIST_HEAD(&card->controls);
 	INIT_LIST_HEAD(&card->controls);
 	INIT_LIST_HEAD(&card->ctl_files);
 	INIT_LIST_HEAD(&card->ctl_files);
 	spin_lock_init(&card->files_lock);
 	spin_lock_init(&card->files_lock);
+	INIT_LIST_HEAD(&card->files_list);
 	init_waitqueue_head(&card->shutdown_sleep);
 	init_waitqueue_head(&card->shutdown_sleep);
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
 	mutex_init(&card->power_lock);
 	mutex_init(&card->power_lock);
@@ -202,26 +216,28 @@ struct snd_card *snd_card_new(int idx, const char *xid,
 #endif
 #endif
 	/* the control interface cannot be accessed from the user space until */
 	/* the control interface cannot be accessed from the user space until */
 	/* snd_cards_bitmask and snd_cards are set with snd_card_register */
 	/* snd_cards_bitmask and snd_cards are set with snd_card_register */
-	if ((err = snd_ctl_create(card)) < 0) {
-		snd_printd("unable to register control minors\n");
+	err = snd_ctl_create(card);
+	if (err < 0) {
+		snd_printk(KERN_ERR "unable to register control minors\n");
 		goto __error;
 		goto __error;
 	}
 	}
-	if ((err = snd_info_card_create(card)) < 0) {
-		snd_printd("unable to create card info\n");
+	err = snd_info_card_create(card);
+	if (err < 0) {
+		snd_printk(KERN_ERR "unable to create card info\n");
 		goto __error_ctl;
 		goto __error_ctl;
 	}
 	}
 	if (extra_size > 0)
 	if (extra_size > 0)
 		card->private_data = (char *)card + sizeof(struct snd_card);
 		card->private_data = (char *)card + sizeof(struct snd_card);
-	return card;
+	*card_ret = card;
+	return 0;
 
 
       __error_ctl:
       __error_ctl:
 	snd_device_free_all(card, SNDRV_DEV_CMD_PRE);
 	snd_device_free_all(card, SNDRV_DEV_CMD_PRE);
       __error:
       __error:
 	kfree(card);
 	kfree(card);
-      	return NULL;
+  	return err;
 }
 }
-
-EXPORT_SYMBOL(snd_card_new);
+EXPORT_SYMBOL(snd_card_create);
 
 
 /* return non-zero if a card is already locked */
 /* return non-zero if a card is already locked */
 int snd_card_locked(int card)
 int snd_card_locked(int card)
@@ -259,6 +275,7 @@ static int snd_disconnect_release(struct inode *inode, struct file *file)
 	list_for_each_entry(_df, &shutdown_files, shutdown_list) {
 	list_for_each_entry(_df, &shutdown_files, shutdown_list) {
 		if (_df->file == file) {
 		if (_df->file == file) {
 			df = _df;
 			df = _df;
+			list_del_init(&df->shutdown_list);
 			break;
 			break;
 		}
 		}
 	}
 	}
@@ -347,8 +364,7 @@ int snd_card_disconnect(struct snd_card *card)
 	/* phase 2: replace file->f_op with special dummy operations */
 	/* phase 2: replace file->f_op with special dummy operations */
 	
 	
 	spin_lock(&card->files_lock);
 	spin_lock(&card->files_lock);
-	mfile = card->files;
-	while (mfile) {
+	list_for_each_entry(mfile, &card->files_list, list) {
 		file = mfile->file;
 		file = mfile->file;
 
 
 		/* it's critical part, use endless loop */
 		/* it's critical part, use endless loop */
@@ -361,8 +377,6 @@ int snd_card_disconnect(struct snd_card *card)
 
 
 		mfile->file->f_op = &snd_shutdown_f_ops;
 		mfile->file->f_op = &snd_shutdown_f_ops;
 		fops_get(mfile->file->f_op);
 		fops_get(mfile->file->f_op);
-		
-		mfile = mfile->next;
 	}
 	}
 	spin_unlock(&card->files_lock);	
 	spin_unlock(&card->files_lock);	
 
 
@@ -442,7 +456,7 @@ int snd_card_free_when_closed(struct snd_card *card)
 		return ret;
 		return ret;
 
 
 	spin_lock(&card->files_lock);
 	spin_lock(&card->files_lock);
-	if (card->files == NULL)
+	if (list_empty(&card->files_list))
 		free_now = 1;
 		free_now = 1;
 	else
 	else
 		card->free_on_last_close = 1;
 		card->free_on_last_close = 1;
@@ -462,7 +476,7 @@ int snd_card_free(struct snd_card *card)
 		return ret;
 		return ret;
 
 
 	/* wait, until all devices are ready for the free operation */
 	/* wait, until all devices are ready for the free operation */
-	wait_event(card->shutdown_sleep, card->files == NULL);
+	wait_event(card->shutdown_sleep, list_empty(&card->files_list));
 	snd_card_do_free(card);
 	snd_card_do_free(card);
 	return 0;
 	return 0;
 }
 }
@@ -809,15 +823,13 @@ int snd_card_file_add(struct snd_card *card, struct file *file)
 		return -ENOMEM;
 		return -ENOMEM;
 	mfile->file = file;
 	mfile->file = file;
 	mfile->disconnected_f_op = NULL;
 	mfile->disconnected_f_op = NULL;
-	mfile->next = NULL;
 	spin_lock(&card->files_lock);
 	spin_lock(&card->files_lock);
 	if (card->shutdown) {
 	if (card->shutdown) {
 		spin_unlock(&card->files_lock);
 		spin_unlock(&card->files_lock);
 		kfree(mfile);
 		kfree(mfile);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
-	mfile->next = card->files;
-	card->files = mfile;
+	list_add(&mfile->list, &card->files_list);
 	spin_unlock(&card->files_lock);
 	spin_unlock(&card->files_lock);
 	return 0;
 	return 0;
 }
 }
@@ -839,29 +851,20 @@ EXPORT_SYMBOL(snd_card_file_add);
  */
  */
 int snd_card_file_remove(struct snd_card *card, struct file *file)
 int snd_card_file_remove(struct snd_card *card, struct file *file)
 {
 {
-	struct snd_monitor_file *mfile, *pfile = NULL;
+	struct snd_monitor_file *mfile, *found = NULL;
 	int last_close = 0;
 	int last_close = 0;
 
 
 	spin_lock(&card->files_lock);
 	spin_lock(&card->files_lock);
-	mfile = card->files;
-	while (mfile) {
+	list_for_each_entry(mfile, &card->files_list, list) {
 		if (mfile->file == file) {
 		if (mfile->file == file) {
-			if (pfile)
-				pfile->next = mfile->next;
-			else
-				card->files = mfile->next;
+			list_del(&mfile->list);
+			if (mfile->disconnected_f_op)
+				fops_put(mfile->disconnected_f_op);
+			found = mfile;
 			break;
 			break;
 		}
 		}
-		pfile = mfile;
-		mfile = mfile->next;
-	}
-	if (mfile && mfile->disconnected_f_op) {
-		fops_put(mfile->disconnected_f_op);
-		spin_lock(&shutdown_lock);
-		list_del(&mfile->shutdown_list);
-		spin_unlock(&shutdown_lock);
 	}
 	}
-	if (card->files == NULL)
+	if (list_empty(&card->files_list))
 		last_close = 1;
 		last_close = 1;
 	spin_unlock(&card->files_lock);
 	spin_unlock(&card->files_lock);
 	if (last_close) {
 	if (last_close) {
@@ -869,11 +872,11 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)
 		if (card->free_on_last_close)
 		if (card->free_on_last_close)
 			snd_card_do_free(card);
 			snd_card_do_free(card);
 	}
 	}
-	if (!mfile) {
+	if (!found) {
 		snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
 		snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);
 		return -ENOENT;
 		return -ENOENT;
 	}
 	}
-	kfree(mfile);
+	kfree(found);
 	return 0;
 	return 0;
 }
 }
 
 

+ 21 - 24
sound/core/jack.c

@@ -23,6 +23,14 @@
 #include <sound/jack.h>
 #include <sound/jack.h>
 #include <sound/core.h>
 #include <sound/core.h>
 
 
+static int jack_types[] = {
+	SW_HEADPHONE_INSERT,
+	SW_MICROPHONE_INSERT,
+	SW_LINEOUT_INSERT,
+	SW_JACK_PHYSICAL_INSERT,
+	SW_VIDEOOUT_INSERT,
+};
+
 static int snd_jack_dev_free(struct snd_device *device)
 static int snd_jack_dev_free(struct snd_device *device)
 {
 {
 	struct snd_jack *jack = device->device_data;
 	struct snd_jack *jack = device->device_data;
@@ -79,6 +87,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
 {
 {
 	struct snd_jack *jack;
 	struct snd_jack *jack;
 	int err;
 	int err;
+	int i;
 	static struct snd_device_ops ops = {
 	static struct snd_device_ops ops = {
 		.dev_free = snd_jack_dev_free,
 		.dev_free = snd_jack_dev_free,
 		.dev_register = snd_jack_dev_register,
 		.dev_register = snd_jack_dev_register,
@@ -100,18 +109,10 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
 
 
 	jack->type = type;
 	jack->type = type;
 
 
-	if (type & SND_JACK_HEADPHONE)
-		input_set_capability(jack->input_dev, EV_SW,
-				     SW_HEADPHONE_INSERT);
-	if (type & SND_JACK_LINEOUT)
-		input_set_capability(jack->input_dev, EV_SW,
-				     SW_LINEOUT_INSERT);
-	if (type & SND_JACK_MICROPHONE)
-		input_set_capability(jack->input_dev, EV_SW,
-				     SW_MICROPHONE_INSERT);
-	if (type & SND_JACK_MECHANICAL)
-		input_set_capability(jack->input_dev, EV_SW,
-				     SW_JACK_PHYSICAL_INSERT);
+	for (i = 0; i < ARRAY_SIZE(jack_types); i++)
+		if (type & (1 << i))
+			input_set_capability(jack->input_dev, EV_SW,
+					     jack_types[i]);
 
 
 	err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
 	err = snd_device_new(card, SNDRV_DEV_JACK, jack, &ops);
 	if (err < 0)
 	if (err < 0)
@@ -154,21 +155,17 @@ EXPORT_SYMBOL(snd_jack_set_parent);
  */
  */
 void snd_jack_report(struct snd_jack *jack, int status)
 void snd_jack_report(struct snd_jack *jack, int status)
 {
 {
+	int i;
+
 	if (!jack)
 	if (!jack)
 		return;
 		return;
 
 
-	if (jack->type & SND_JACK_HEADPHONE)
-		input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT,
-				    status & SND_JACK_HEADPHONE);
-	if (jack->type & SND_JACK_LINEOUT)
-		input_report_switch(jack->input_dev, SW_LINEOUT_INSERT,
-				    status & SND_JACK_LINEOUT);
-	if (jack->type & SND_JACK_MICROPHONE)
-		input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT,
-				    status & SND_JACK_MICROPHONE);
-	if (jack->type & SND_JACK_MECHANICAL)
-		input_report_switch(jack->input_dev, SW_JACK_PHYSICAL_INSERT,
-				    status & SND_JACK_MECHANICAL);
+	for (i = 0; i < ARRAY_SIZE(jack_types); i++) {
+		int testbit = 1 << i;
+		if (jack->type & testbit)
+			input_report_switch(jack->input_dev, jack_types[i],
+					    status & testbit);
+	}
 
 
 	input_sync(jack->input_dev);
 	input_sync(jack->input_dev);
 }
 }

+ 6 - 4
sound/core/misc.c

@@ -95,12 +95,14 @@ snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list)
 {
 {
 	const struct snd_pci_quirk *q;
 	const struct snd_pci_quirk *q;
 
 
-	for (q = list; q->subvendor; q++)
-		if (q->subvendor == pci->subsystem_vendor &&
-		    (!q->subdevice || q->subdevice == pci->subsystem_device))
+	for (q = list; q->subvendor; q++) {
+		if (q->subvendor != pci->subsystem_vendor)
+			continue;
+		if (!q->subdevice ||
+		    (pci->subsystem_device & q->subdevice_mask) == q->subdevice)
 			return q;
 			return q;
+	}
 	return NULL;
 	return NULL;
 }
 }
-
 EXPORT_SYMBOL(snd_pci_quirk_lookup);
 EXPORT_SYMBOL(snd_pci_quirk_lookup);
 #endif
 #endif

+ 31 - 18
sound/core/oss/pcm_oss.c

@@ -1160,9 +1160,11 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
 		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
 		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
 #ifdef OSS_DEBUG
 #ifdef OSS_DEBUG
 			if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
 			if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
-				printk("pcm_oss: write: recovering from XRUN\n");
+				printk(KERN_DEBUG "pcm_oss: write: "
+				       "recovering from XRUN\n");
 			else
 			else
-				printk("pcm_oss: write: recovering from SUSPEND\n");
+				printk(KERN_DEBUG "pcm_oss: write: "
+				       "recovering from SUSPEND\n");
 #endif
 #endif
 			ret = snd_pcm_oss_prepare(substream);
 			ret = snd_pcm_oss_prepare(substream);
 			if (ret < 0)
 			if (ret < 0)
@@ -1196,9 +1198,11 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
 		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
 		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
 #ifdef OSS_DEBUG
 #ifdef OSS_DEBUG
 			if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
 			if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
-				printk("pcm_oss: read: recovering from XRUN\n");
+				printk(KERN_DEBUG "pcm_oss: read: "
+				       "recovering from XRUN\n");
 			else
 			else
-				printk("pcm_oss: read: recovering from SUSPEND\n");
+				printk(KERN_DEBUG "pcm_oss: read: "
+				       "recovering from SUSPEND\n");
 #endif
 #endif
 			ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
 			ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
 			if (ret < 0)
 			if (ret < 0)
@@ -1242,9 +1246,11 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, void
 		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
 		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
 #ifdef OSS_DEBUG
 #ifdef OSS_DEBUG
 			if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
 			if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
-				printk("pcm_oss: writev: recovering from XRUN\n");
+				printk(KERN_DEBUG "pcm_oss: writev: "
+				       "recovering from XRUN\n");
 			else
 			else
-				printk("pcm_oss: writev: recovering from SUSPEND\n");
+				printk(KERN_DEBUG "pcm_oss: writev: "
+				       "recovering from SUSPEND\n");
 #endif
 #endif
 			ret = snd_pcm_oss_prepare(substream);
 			ret = snd_pcm_oss_prepare(substream);
 			if (ret < 0)
 			if (ret < 0)
@@ -1278,9 +1284,11 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void *
 		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
 		    runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) {
 #ifdef OSS_DEBUG
 #ifdef OSS_DEBUG
 			if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
 			if (runtime->status->state == SNDRV_PCM_STATE_XRUN)
-				printk("pcm_oss: readv: recovering from XRUN\n");
+				printk(KERN_DEBUG "pcm_oss: readv: "
+				       "recovering from XRUN\n");
 			else
 			else
-				printk("pcm_oss: readv: recovering from SUSPEND\n");
+				printk(KERN_DEBUG "pcm_oss: readv: "
+				       "recovering from SUSPEND\n");
 #endif
 #endif
 			ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
 			ret = snd_pcm_kernel_ioctl(substream, SNDRV_PCM_IOCTL_DRAIN, NULL);
 			if (ret < 0)
 			if (ret < 0)
@@ -1533,7 +1541,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size)
 	init_waitqueue_entry(&wait, current);
 	init_waitqueue_entry(&wait, current);
 	add_wait_queue(&runtime->sleep, &wait);
 	add_wait_queue(&runtime->sleep, &wait);
 #ifdef OSS_DEBUG
 #ifdef OSS_DEBUG
-	printk("sync1: size = %li\n", size);
+	printk(KERN_DEBUG "sync1: size = %li\n", size);
 #endif
 #endif
 	while (1) {
 	while (1) {
 		result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1);
 		result = snd_pcm_oss_write2(substream, runtime->oss.buffer, size, 1);
@@ -1590,7 +1598,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
 		mutex_lock(&runtime->oss.params_lock);
 		mutex_lock(&runtime->oss.params_lock);
 		if (runtime->oss.buffer_used > 0) {
 		if (runtime->oss.buffer_used > 0) {
 #ifdef OSS_DEBUG
 #ifdef OSS_DEBUG
-			printk("sync: buffer_used\n");
+			printk(KERN_DEBUG "sync: buffer_used\n");
 #endif
 #endif
 			size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width;
 			size = (8 * (runtime->oss.period_bytes - runtime->oss.buffer_used) + 7) / width;
 			snd_pcm_format_set_silence(format,
 			snd_pcm_format_set_silence(format,
@@ -1603,7 +1611,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
 			}
 			}
 		} else if (runtime->oss.period_ptr > 0) {
 		} else if (runtime->oss.period_ptr > 0) {
 #ifdef OSS_DEBUG
 #ifdef OSS_DEBUG
-			printk("sync: period_ptr\n");
+			printk(KERN_DEBUG "sync: period_ptr\n");
 #endif
 #endif
 			size = runtime->oss.period_bytes - runtime->oss.period_ptr;
 			size = runtime->oss.period_bytes - runtime->oss.period_ptr;
 			snd_pcm_format_set_silence(format,
 			snd_pcm_format_set_silence(format,
@@ -1952,7 +1960,7 @@ static int snd_pcm_oss_set_trigger(struct snd_pcm_oss_file *pcm_oss_file, int tr
 	int err, cmd;
 	int err, cmd;
 
 
 #ifdef OSS_DEBUG
 #ifdef OSS_DEBUG
-	printk("pcm_oss: trigger = 0x%x\n", trigger);
+	printk(KERN_DEBUG "pcm_oss: trigger = 0x%x\n", trigger);
 #endif
 #endif
 	
 	
 	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
 	psubstream = pcm_oss_file->streams[SNDRV_PCM_STREAM_PLAYBACK];
@@ -2170,7 +2178,9 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre
 	}
 	}
 
 
 #ifdef OSS_DEBUG
 #ifdef OSS_DEBUG
-	printk("pcm_oss: space: bytes = %i, fragments = %i, fragstotal = %i, fragsize = %i\n", info.bytes, info.fragments, info.fragstotal, info.fragsize);
+	printk(KERN_DEBUG "pcm_oss: space: bytes = %i, fragments = %i, "
+	       "fragstotal = %i, fragsize = %i\n",
+	       info.bytes, info.fragments, info.fragstotal, info.fragsize);
 #endif
 #endif
 	if (copy_to_user(_info, &info, sizeof(info)))
 	if (copy_to_user(_info, &info, sizeof(info)))
 		return -EFAULT;
 		return -EFAULT;
@@ -2473,7 +2483,7 @@ static long snd_pcm_oss_ioctl(struct file *file, unsigned int cmd, unsigned long
 	if (((cmd >> 8) & 0xff) != 'P')
 	if (((cmd >> 8) & 0xff) != 'P')
 		return -EINVAL;
 		return -EINVAL;
 #ifdef OSS_DEBUG
 #ifdef OSS_DEBUG
-	printk("pcm_oss: ioctl = 0x%x\n", cmd);
+	printk(KERN_DEBUG "pcm_oss: ioctl = 0x%x\n", cmd);
 #endif
 #endif
 	switch (cmd) {
 	switch (cmd) {
 	case SNDCTL_DSP_RESET:
 	case SNDCTL_DSP_RESET:
@@ -2627,7 +2637,8 @@ static ssize_t snd_pcm_oss_read(struct file *file, char __user *buf, size_t coun
 #else
 #else
 	{
 	{
 		ssize_t res = snd_pcm_oss_read1(substream, buf, count);
 		ssize_t res = snd_pcm_oss_read1(substream, buf, count);
-		printk("pcm_oss: read %li bytes (returned %li bytes)\n", (long)count, (long)res);
+		printk(KERN_DEBUG "pcm_oss: read %li bytes "
+		       "(returned %li bytes)\n", (long)count, (long)res);
 		return res;
 		return res;
 	}
 	}
 #endif
 #endif
@@ -2646,7 +2657,8 @@ static ssize_t snd_pcm_oss_write(struct file *file, const char __user *buf, size
 	substream->f_flags = file->f_flags & O_NONBLOCK;
 	substream->f_flags = file->f_flags & O_NONBLOCK;
 	result = snd_pcm_oss_write1(substream, buf, count);
 	result = snd_pcm_oss_write1(substream, buf, count);
 #ifdef OSS_DEBUG
 #ifdef OSS_DEBUG
-	printk("pcm_oss: write %li bytes (wrote %li bytes)\n", (long)count, (long)result);
+	printk(KERN_DEBUG "pcm_oss: write %li bytes (wrote %li bytes)\n",
+	       (long)count, (long)result);
 #endif
 #endif
 	return result;
 	return result;
 }
 }
@@ -2720,7 +2732,7 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
 	int err;
 	int err;
 
 
 #ifdef OSS_DEBUG
 #ifdef OSS_DEBUG
-	printk("pcm_oss: mmap begin\n");
+	printk(KERN_DEBUG "pcm_oss: mmap begin\n");
 #endif
 #endif
 	pcm_oss_file = file->private_data;
 	pcm_oss_file = file->private_data;
 	switch ((area->vm_flags & (VM_READ | VM_WRITE))) {
 	switch ((area->vm_flags & (VM_READ | VM_WRITE))) {
@@ -2770,7 +2782,8 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
 	runtime->silence_threshold = 0;
 	runtime->silence_threshold = 0;
 	runtime->silence_size = 0;
 	runtime->silence_size = 0;
 #ifdef OSS_DEBUG
 #ifdef OSS_DEBUG
-	printk("pcm_oss: mmap ok, bytes = 0x%x\n", runtime->oss.mmap_bytes);
+	printk(KERN_DEBUG "pcm_oss: mmap ok, bytes = 0x%x\n",
+	       runtime->oss.mmap_bytes);
 #endif
 #endif
 	/* In mmap mode we never stop */
 	/* In mmap mode we never stop */
 	runtime->stop_threshold = runtime->boundary;
 	runtime->stop_threshold = runtime->boundary;

+ 2 - 2
sound/core/oss/pcm_plugin.h

@@ -176,9 +176,9 @@ static inline int snd_pcm_plug_slave_format(int format, struct snd_mask *format_
 #endif
 #endif
 
 
 #ifdef PLUGIN_DEBUG
 #ifdef PLUGIN_DEBUG
-#define pdprintf( fmt, args... ) printk( "plugin: " fmt, ##args)
+#define pdprintf(fmt, args...) printk(KERN_DEBUG "plugin: " fmt, ##args)
 #else
 #else
-#define pdprintf( fmt, args... ) 
+#define pdprintf(fmt, args...)
 #endif
 #endif
 
 
 #endif				/* __PCM_PLUGIN_H */
 #endif				/* __PCM_PLUGIN_H */

+ 1 - 2
sound/core/pcm.c

@@ -667,7 +667,6 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
 		spin_lock_init(&substream->self_group.lock);
 		spin_lock_init(&substream->self_group.lock);
 		INIT_LIST_HEAD(&substream->self_group.substreams);
 		INIT_LIST_HEAD(&substream->self_group.substreams);
 		list_add_tail(&substream->link_list, &substream->self_group.substreams);
 		list_add_tail(&substream->link_list, &substream->self_group.substreams);
-		spin_lock_init(&substream->timer_lock);
 		atomic_set(&substream->mmap_count, 0);
 		atomic_set(&substream->mmap_count, 0);
 		prev = substream;
 		prev = substream;
 	}
 	}
@@ -692,7 +691,7 @@ EXPORT_SYMBOL(snd_pcm_new_stream);
  *
  *
  * Returns zero if successful, or a negative error code on failure.
  * Returns zero if successful, or a negative error code on failure.
  */
  */
-int snd_pcm_new(struct snd_card *card, char *id, int device,
+int snd_pcm_new(struct snd_card *card, const char *id, int device,
 		int playback_count, int capture_count,
 		int playback_count, int capture_count,
 	        struct snd_pcm ** rpcm)
 	        struct snd_pcm ** rpcm)
 {
 {

+ 102 - 53
sound/core/pcm_lib.c

@@ -125,23 +125,32 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
 	}
 	}
 }
 }
 
 
+#ifdef CONFIG_SND_PCM_XRUN_DEBUG
+#define xrun_debug(substream)	((substream)->pstr->xrun_debug)
+#else
+#define xrun_debug(substream)	0
+#endif
+
+#define dump_stack_on_xrun(substream) do {	\
+		if (xrun_debug(substream) > 1)	\
+			dump_stack();		\
+	} while (0)
+
 static void xrun(struct snd_pcm_substream *substream)
 static void xrun(struct snd_pcm_substream *substream)
 {
 {
 	snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
 	snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
-	if (substream->pstr->xrun_debug) {
+	if (xrun_debug(substream)) {
 		snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n",
 		snd_printd(KERN_DEBUG "XRUN: pcmC%dD%d%c\n",
 			   substream->pcm->card->number,
 			   substream->pcm->card->number,
 			   substream->pcm->device,
 			   substream->pcm->device,
 			   substream->stream ? 'c' : 'p');
 			   substream->stream ? 'c' : 'p');
-		if (substream->pstr->xrun_debug > 1)
-			dump_stack();
+		dump_stack_on_xrun(substream);
 	}
 	}
-#endif
 }
 }
 
 
-static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream,
-							  struct snd_pcm_runtime *runtime)
+static snd_pcm_uframes_t
+snd_pcm_update_hw_ptr_pos(struct snd_pcm_substream *substream,
+			  struct snd_pcm_runtime *runtime)
 {
 {
 	snd_pcm_uframes_t pos;
 	snd_pcm_uframes_t pos;
 
 
@@ -150,17 +159,21 @@ static inline snd_pcm_uframes_t snd_pcm_update_hw_ptr_pos(struct snd_pcm_substre
 	pos = substream->ops->pointer(substream);
 	pos = substream->ops->pointer(substream);
 	if (pos == SNDRV_PCM_POS_XRUN)
 	if (pos == SNDRV_PCM_POS_XRUN)
 		return pos; /* XRUN */
 		return pos; /* XRUN */
-#ifdef CONFIG_SND_DEBUG
 	if (pos >= runtime->buffer_size) {
 	if (pos >= runtime->buffer_size) {
-		snd_printk(KERN_ERR  "BUG: stream = %i, pos = 0x%lx, buffer size = 0x%lx, period size = 0x%lx\n", substream->stream, pos, runtime->buffer_size, runtime->period_size);
+		if (printk_ratelimit()) {
+			snd_printd(KERN_ERR  "BUG: stream = %i, pos = 0x%lx, "
+				   "buffer size = 0x%lx, period size = 0x%lx\n",
+				   substream->stream, pos, runtime->buffer_size,
+				   runtime->period_size);
+		}
+		pos = 0;
 	}
 	}
-#endif
 	pos -= pos % runtime->min_align;
 	pos -= pos % runtime->min_align;
 	return pos;
 	return pos;
 }
 }
 
 
-static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
-					     struct snd_pcm_runtime *runtime)
+static int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream,
+				      struct snd_pcm_runtime *runtime)
 {
 {
 	snd_pcm_uframes_t avail;
 	snd_pcm_uframes_t avail;
 
 
@@ -182,11 +195,21 @@ static inline int snd_pcm_update_hw_ptr_post(struct snd_pcm_substream *substream
 	return 0;
 	return 0;
 }
 }
 
 
-static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
+#define hw_ptr_error(substream, fmt, args...)				\
+	do {								\
+		if (xrun_debug(substream)) {				\
+			if (printk_ratelimit()) {			\
+				snd_printd("PCM: " fmt, ##args);	\
+			}						\
+			dump_stack_on_xrun(substream);			\
+		}							\
+	} while (0)
+
+static int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *substream)
 {
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	snd_pcm_uframes_t pos;
 	snd_pcm_uframes_t pos;
-	snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt;
+	snd_pcm_uframes_t new_hw_ptr, hw_ptr_interrupt, hw_base;
 	snd_pcm_sframes_t delta;
 	snd_pcm_sframes_t delta;
 
 
 	pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
 	pos = snd_pcm_update_hw_ptr_pos(substream, runtime);
@@ -194,36 +217,53 @@ static inline int snd_pcm_update_hw_ptr_interrupt(struct snd_pcm_substream *subs
 		xrun(substream);
 		xrun(substream);
 		return -EPIPE;
 		return -EPIPE;
 	}
 	}
-	if (runtime->period_size == runtime->buffer_size)
-		goto __next_buf;
-	new_hw_ptr = runtime->hw_ptr_base + pos;
+	hw_base = runtime->hw_ptr_base;
+	new_hw_ptr = hw_base + pos;
 	hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size;
 	hw_ptr_interrupt = runtime->hw_ptr_interrupt + runtime->period_size;
-
-	delta = hw_ptr_interrupt - new_hw_ptr;
-	if (delta > 0) {
-		if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) {
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
-			if (runtime->periods > 1 && substream->pstr->xrun_debug) {
-				snd_printd(KERN_ERR "Unexpected hw_pointer value [1] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2);
-				if (substream->pstr->xrun_debug > 1)
-					dump_stack();
-			}
-#endif
-			return 0;
+	delta = new_hw_ptr - hw_ptr_interrupt;
+	if (hw_ptr_interrupt >= runtime->boundary) {
+		hw_ptr_interrupt -= runtime->boundary;
+		if (hw_base < runtime->boundary / 2)
+			/* hw_base was already lapped; recalc delta */
+			delta = new_hw_ptr - hw_ptr_interrupt;
+	}
+	if (delta < 0) {
+		delta += runtime->buffer_size;
+		if (delta < 0) {
+			hw_ptr_error(substream, 
+				     "Unexpected hw_pointer value "
+				     "(stream=%i, pos=%ld, intr_ptr=%ld)\n",
+				     substream->stream, (long)pos,
+				     (long)hw_ptr_interrupt);
+			/* rebase to interrupt position */
+			hw_base = new_hw_ptr = hw_ptr_interrupt;
+			/* align hw_base to buffer_size */
+			hw_base -= hw_base % runtime->buffer_size;
+			delta = 0;
+		} else {
+			hw_base += runtime->buffer_size;
+			if (hw_base >= runtime->boundary)
+				hw_base = 0;
+			new_hw_ptr = hw_base + pos;
 		}
 		}
-	      __next_buf:
-		runtime->hw_ptr_base += runtime->buffer_size;
-		if (runtime->hw_ptr_base == runtime->boundary)
-			runtime->hw_ptr_base = 0;
-		new_hw_ptr = runtime->hw_ptr_base + pos;
 	}
 	}
-
+	if (delta > runtime->period_size) {
+		hw_ptr_error(substream,
+			     "Lost interrupts? "
+			     "(stream=%i, delta=%ld, intr_ptr=%ld)\n",
+			     substream->stream, (long)delta,
+			     (long)hw_ptr_interrupt);
+		/* rebase hw_ptr_interrupt */
+		hw_ptr_interrupt =
+			new_hw_ptr - new_hw_ptr % runtime->period_size;
+	}
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
 	    runtime->silence_size > 0)
 	    runtime->silence_size > 0)
 		snd_pcm_playback_silence(substream, new_hw_ptr);
 		snd_pcm_playback_silence(substream, new_hw_ptr);
 
 
+	runtime->hw_ptr_base = hw_base;
 	runtime->status->hw_ptr = new_hw_ptr;
 	runtime->status->hw_ptr = new_hw_ptr;
-	runtime->hw_ptr_interrupt = new_hw_ptr - new_hw_ptr % runtime->period_size;
+	runtime->hw_ptr_interrupt = hw_ptr_interrupt;
 
 
 	return snd_pcm_update_hw_ptr_post(substream, runtime);
 	return snd_pcm_update_hw_ptr_post(substream, runtime);
 }
 }
@@ -233,7 +273,7 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
 {
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	snd_pcm_uframes_t pos;
 	snd_pcm_uframes_t pos;
-	snd_pcm_uframes_t old_hw_ptr, new_hw_ptr;
+	snd_pcm_uframes_t old_hw_ptr, new_hw_ptr, hw_base;
 	snd_pcm_sframes_t delta;
 	snd_pcm_sframes_t delta;
 
 
 	old_hw_ptr = runtime->status->hw_ptr;
 	old_hw_ptr = runtime->status->hw_ptr;
@@ -242,29 +282,38 @@ int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream)
 		xrun(substream);
 		xrun(substream);
 		return -EPIPE;
 		return -EPIPE;
 	}
 	}
-	new_hw_ptr = runtime->hw_ptr_base + pos;
-
-	delta = old_hw_ptr - new_hw_ptr;
-	if (delta > 0) {
-		if ((snd_pcm_uframes_t)delta < runtime->buffer_size / 2) {
-#ifdef CONFIG_SND_PCM_XRUN_DEBUG
-			if (runtime->periods > 2 && substream->pstr->xrun_debug) {
-				snd_printd(KERN_ERR "Unexpected hw_pointer value [2] (stream = %i, delta: -%ld, max jitter = %ld): wrong interrupt acknowledge?\n", substream->stream, (long) delta, runtime->buffer_size / 2);
-				if (substream->pstr->xrun_debug > 1)
-					dump_stack();
-			}
-#endif
+	hw_base = runtime->hw_ptr_base;
+	new_hw_ptr = hw_base + pos;
+
+	delta = new_hw_ptr - old_hw_ptr;
+	if (delta < 0) {
+		delta += runtime->buffer_size;
+		if (delta < 0) {
+			hw_ptr_error(substream, 
+				     "Unexpected hw_pointer value [2] "
+				     "(stream=%i, pos=%ld, old_ptr=%ld)\n",
+				     substream->stream, (long)pos,
+				     (long)old_hw_ptr);
 			return 0;
 			return 0;
 		}
 		}
-		runtime->hw_ptr_base += runtime->buffer_size;
-		if (runtime->hw_ptr_base == runtime->boundary)
-			runtime->hw_ptr_base = 0;
-		new_hw_ptr = runtime->hw_ptr_base + pos;
+		hw_base += runtime->buffer_size;
+		if (hw_base >= runtime->boundary)
+			hw_base = 0;
+		new_hw_ptr = hw_base + pos;
+	}
+	if (delta > runtime->period_size && runtime->periods > 1) {
+		hw_ptr_error(substream,
+			     "hw_ptr skipping! "
+			     "(pos=%ld, delta=%ld, period=%ld)\n",
+			     (long)pos, (long)delta,
+			     (long)runtime->period_size);
+		return 0;
 	}
 	}
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
 	    runtime->silence_size > 0)
 	    runtime->silence_size > 0)
 		snd_pcm_playback_silence(substream, new_hw_ptr);
 		snd_pcm_playback_silence(substream, new_hw_ptr);
 
 
+	runtime->hw_ptr_base = hw_base;
 	runtime->status->hw_ptr = new_hw_ptr;
 	runtime->status->hw_ptr = new_hw_ptr;
 
 
 	return snd_pcm_update_hw_ptr_post(substream, runtime);
 	return snd_pcm_update_hw_ptr_post(substream, runtime);

+ 3 - 3
sound/core/pcm_native.c

@@ -186,7 +186,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
 		if (!(params->rmask & (1 << k)))
 		if (!(params->rmask & (1 << k)))
 			continue;
 			continue;
 #ifdef RULES_DEBUG
 #ifdef RULES_DEBUG
-		printk("%s = ", snd_pcm_hw_param_names[k]);
+		printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
 		printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
 		printk("%04x%04x%04x%04x -> ", m->bits[3], m->bits[2], m->bits[1], m->bits[0]);
 #endif
 #endif
 		changed = snd_mask_refine(m, constrs_mask(constrs, k));
 		changed = snd_mask_refine(m, constrs_mask(constrs, k));
@@ -206,7 +206,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
 		if (!(params->rmask & (1 << k)))
 		if (!(params->rmask & (1 << k)))
 			continue;
 			continue;
 #ifdef RULES_DEBUG
 #ifdef RULES_DEBUG
-		printk("%s = ", snd_pcm_hw_param_names[k]);
+		printk(KERN_DEBUG "%s = ", snd_pcm_hw_param_names[k]);
 		if (i->empty)
 		if (i->empty)
 			printk("empty");
 			printk("empty");
 		else
 		else
@@ -251,7 +251,7 @@ int snd_pcm_hw_refine(struct snd_pcm_substream *substream,
 			if (!doit)
 			if (!doit)
 				continue;
 				continue;
 #ifdef RULES_DEBUG
 #ifdef RULES_DEBUG
-			printk("Rule %d [%p]: ", k, r->func);
+			printk(KERN_DEBUG "Rule %d [%p]: ", k, r->func);
 			if (r->var >= 0) {
 			if (r->var >= 0) {
 				printk("%s = ", snd_pcm_hw_param_names[r->var]);
 				printk("%s = ", snd_pcm_hw_param_names[r->var]);
 				if (hw_is_mask(r->var)) {
 				if (hw_is_mask(r->var)) {

+ 0 - 6
sound/core/pcm_timer.c

@@ -85,25 +85,19 @@ static unsigned long snd_pcm_timer_resolution(struct snd_timer * timer)
 
 
 static int snd_pcm_timer_start(struct snd_timer * timer)
 static int snd_pcm_timer_start(struct snd_timer * timer)
 {
 {
-	unsigned long flags;
 	struct snd_pcm_substream *substream;
 	struct snd_pcm_substream *substream;
 	
 	
 	substream = snd_timer_chip(timer);
 	substream = snd_timer_chip(timer);
-	spin_lock_irqsave(&substream->timer_lock, flags);
 	substream->timer_running = 1;
 	substream->timer_running = 1;
-	spin_unlock_irqrestore(&substream->timer_lock, flags);
 	return 0;
 	return 0;
 }
 }
 
 
 static int snd_pcm_timer_stop(struct snd_timer * timer)
 static int snd_pcm_timer_stop(struct snd_timer * timer)
 {
 {
-	unsigned long flags;
 	struct snd_pcm_substream *substream;
 	struct snd_pcm_substream *substream;
 	
 	
 	substream = snd_timer_chip(timer);
 	substream = snd_timer_chip(timer);
-	spin_lock_irqsave(&substream->timer_lock, flags);
 	substream->timer_running = 0;
 	substream->timer_running = 0;
-	spin_unlock_irqrestore(&substream->timer_lock, flags);
 	return 0;
 	return 0;
 }
 }
 
 

+ 195 - 184
sound/core/rawmidi.c

@@ -224,156 +224,143 @@ int snd_rawmidi_drain_input(struct snd_rawmidi_substream *substream)
 	return 0;
 	return 0;
 }
 }
 
 
-int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
-			    int mode, struct snd_rawmidi_file * rfile)
+/* look for an available substream for the given stream direction;
+ * if a specific subdevice is given, try to assign it
+ */
+static int assign_substream(struct snd_rawmidi *rmidi, int subdevice,
+			    int stream, int mode,
+			    struct snd_rawmidi_substream **sub_ret)
+{
+	struct snd_rawmidi_substream *substream;
+	struct snd_rawmidi_str *s = &rmidi->streams[stream];
+	static unsigned int info_flags[2] = {
+		[SNDRV_RAWMIDI_STREAM_OUTPUT] = SNDRV_RAWMIDI_INFO_OUTPUT,
+		[SNDRV_RAWMIDI_STREAM_INPUT] = SNDRV_RAWMIDI_INFO_INPUT,
+	};
+
+	if (!(rmidi->info_flags & info_flags[stream]))
+		return -ENXIO;
+	if (subdevice >= 0 && subdevice >= s->substream_count)
+		return -ENODEV;
+	if (s->substream_opened >= s->substream_count)
+		return -EAGAIN;
+
+	list_for_each_entry(substream, &s->substreams, list) {
+		if (substream->opened) {
+			if (stream == SNDRV_RAWMIDI_STREAM_INPUT ||
+			    !(mode & SNDRV_RAWMIDI_LFLG_APPEND))
+				continue;
+		}
+		if (subdevice < 0 || subdevice == substream->number) {
+			*sub_ret = substream;
+			return 0;
+		}
+	}
+	return -EAGAIN;
+}
+
+/* open and do ref-counting for the given substream */
+static int open_substream(struct snd_rawmidi *rmidi,
+			  struct snd_rawmidi_substream *substream,
+			  int mode)
+{
+	int err;
+
+	err = snd_rawmidi_runtime_create(substream);
+	if (err < 0)
+		return err;
+	err = substream->ops->open(substream);
+	if (err < 0)
+		return err;
+	substream->opened = 1;
+	if (substream->use_count++ == 0)
+		substream->active_sensing = 1;
+	if (mode & SNDRV_RAWMIDI_LFLG_APPEND)
+		substream->append = 1;
+	rmidi->streams[substream->stream].substream_opened++;
+	return 0;
+}
+
+static void close_substream(struct snd_rawmidi *rmidi,
+			    struct snd_rawmidi_substream *substream,
+			    int cleanup);
+
+static int rawmidi_open_priv(struct snd_rawmidi *rmidi, int subdevice, int mode,
+			     struct snd_rawmidi_file *rfile)
 {
 {
-	struct snd_rawmidi *rmidi;
-	struct list_head *list1, *list2;
 	struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL;
 	struct snd_rawmidi_substream *sinput = NULL, *soutput = NULL;
-	struct snd_rawmidi_runtime *input = NULL, *output = NULL;
 	int err;
 	int err;
 
 
-	if (rfile)
-		rfile->input = rfile->output = NULL;
-	mutex_lock(&register_mutex);
-	rmidi = snd_rawmidi_search(card, device);
-	mutex_unlock(&register_mutex);
-	if (rmidi == NULL) {
-		err = -ENODEV;
-		goto __error1;
-	}
-	if (!try_module_get(rmidi->card->module)) {
-		err = -EFAULT;
-		goto __error1;
-	}
-	if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK))
-		mutex_lock(&rmidi->open_mutex);
+	rfile->input = rfile->output = NULL;
 	if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
 	if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
-		if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT)) {
-			err = -ENXIO;
-			goto __error;
-		}
-		if (subdevice >= 0 && (unsigned int)subdevice >= rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_count) {
-			err = -ENODEV;
-			goto __error;
-		}
-		if (rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened >=
-		    rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_count) {
-			err = -EAGAIN;
+		err = assign_substream(rmidi, subdevice,
+				       SNDRV_RAWMIDI_STREAM_INPUT,
+				       mode, &sinput);
+		if (err < 0)
 			goto __error;
 			goto __error;
-		}
 	}
 	}
 	if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
 	if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
-		if (!(rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT)) {
-			err = -ENXIO;
-			goto __error;
-		}
-		if (subdevice >= 0 && (unsigned int)subdevice >= rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_count) {
-			err = -ENODEV;
-			goto __error;
-		}
-		if (rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened >=
-		    rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_count) {
-			err = -EAGAIN;
+		err = assign_substream(rmidi, subdevice,
+				       SNDRV_RAWMIDI_STREAM_OUTPUT,
+				       mode, &soutput);
+		if (err < 0)
 			goto __error;
 			goto __error;
-		}
-	}
-	list1 = rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams.next;
-	while (1) {
-		if (list1 == &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) {
-			sinput = NULL;
-			if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
-				err = -EAGAIN;
-				goto __error;
-			}
-			break;
-		}
-		sinput = list_entry(list1, struct snd_rawmidi_substream, list);
-		if ((mode & SNDRV_RAWMIDI_LFLG_INPUT) && sinput->opened)
-			goto __nexti;
-		if (subdevice < 0 || (subdevice >= 0 && subdevice == sinput->number))
-			break;
-	      __nexti:
-		list1 = list1->next;
 	}
 	}
-	list2 = rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams.next;
-	while (1) {
-		if (list2 == &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) {
-			soutput = NULL;
-			if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
-				err = -EAGAIN;
-				goto __error;
-			}
-			break;
-		}
-		soutput = list_entry(list2, struct snd_rawmidi_substream, list);
-		if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
-			if (mode & SNDRV_RAWMIDI_LFLG_APPEND) {
-				if (soutput->opened && !soutput->append)
-					goto __nexto;
-			} else {
-				if (soutput->opened)
-					goto __nexto;
-			}
-		}
-		if (subdevice < 0 || (subdevice >= 0 && subdevice == soutput->number))
-			break;
-	      __nexto:
-		list2 = list2->next;
-	}
-	if (mode & SNDRV_RAWMIDI_LFLG_INPUT) {
-		if ((err = snd_rawmidi_runtime_create(sinput)) < 0)
-			goto __error;
-		input = sinput->runtime;
-		if ((err = sinput->ops->open(sinput)) < 0)
+
+	if (sinput) {
+		err = open_substream(rmidi, sinput, mode);
+		if (err < 0)
 			goto __error;
 			goto __error;
-		sinput->opened = 1;
-		rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened++;
-	} else {
-		sinput = NULL;
 	}
 	}
-	if (mode & SNDRV_RAWMIDI_LFLG_OUTPUT) {
-		if (soutput->opened)
-			goto __skip_output;
-		if ((err = snd_rawmidi_runtime_create(soutput)) < 0) {
-			if (mode & SNDRV_RAWMIDI_LFLG_INPUT)
-				sinput->ops->close(sinput);
-			goto __error;
-		}
-		output = soutput->runtime;
-		if ((err = soutput->ops->open(soutput)) < 0) {
-			if (mode & SNDRV_RAWMIDI_LFLG_INPUT)
-				sinput->ops->close(sinput);
+	if (soutput) {
+		err = open_substream(rmidi, soutput, mode);
+		if (err < 0) {
+			if (sinput)
+				close_substream(rmidi, sinput, 0);
 			goto __error;
 			goto __error;
 		}
 		}
-	      __skip_output:
-		soutput->opened = 1;
-		if (mode & SNDRV_RAWMIDI_LFLG_APPEND)
-			soutput->append = 1;
-	      	if (soutput->use_count++ == 0)
-			soutput->active_sensing = 1;
-		rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened++;
-	} else {
-		soutput = NULL;
-	}
-	if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK))
-		mutex_unlock(&rmidi->open_mutex);
-	if (rfile) {
-		rfile->rmidi = rmidi;
-		rfile->input = sinput;
-		rfile->output = soutput;
 	}
 	}
+
+	rfile->rmidi = rmidi;
+	rfile->input = sinput;
+	rfile->output = soutput;
 	return 0;
 	return 0;
 
 
       __error:
       __error:
-	if (input != NULL)
+	if (sinput && sinput->runtime)
 		snd_rawmidi_runtime_free(sinput);
 		snd_rawmidi_runtime_free(sinput);
-	if (output != NULL)
+	if (soutput && soutput->runtime)
 		snd_rawmidi_runtime_free(soutput);
 		snd_rawmidi_runtime_free(soutput);
-	module_put(rmidi->card->module);
-	if (!(mode & SNDRV_RAWMIDI_LFLG_NOOPENLOCK))
-		mutex_unlock(&rmidi->open_mutex);
-      __error1:
+	return err;
+}
+
+/* called from sound/core/seq/seq_midi.c */
+int snd_rawmidi_kernel_open(struct snd_card *card, int device, int subdevice,
+			    int mode, struct snd_rawmidi_file * rfile)
+{
+	struct snd_rawmidi *rmidi;
+	int err;
+
+	if (snd_BUG_ON(!rfile))
+		return -EINVAL;
+
+	mutex_lock(&register_mutex);
+	rmidi = snd_rawmidi_search(card, device);
+	if (rmidi == NULL) {
+		mutex_unlock(&register_mutex);
+		return -ENODEV;
+	}
+	if (!try_module_get(rmidi->card->module)) {
+		mutex_unlock(&register_mutex);
+		return -ENXIO;
+	}
+	mutex_unlock(&register_mutex);
+
+	mutex_lock(&rmidi->open_mutex);
+	err = rawmidi_open_priv(rmidi, subdevice, mode, rfile);
+	mutex_unlock(&rmidi->open_mutex);
+	if (err < 0)
+		module_put(rmidi->card->module);
 	return err;
 	return err;
 }
 }
 
 
@@ -385,10 +372,13 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
 	unsigned short fflags;
 	unsigned short fflags;
 	int err;
 	int err;
 	struct snd_rawmidi *rmidi;
 	struct snd_rawmidi *rmidi;
-	struct snd_rawmidi_file *rawmidi_file;
+	struct snd_rawmidi_file *rawmidi_file = NULL;
 	wait_queue_t wait;
 	wait_queue_t wait;
 	struct snd_ctl_file *kctl;
 	struct snd_ctl_file *kctl;
 
 
+	if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) 
+		return -EINVAL;		/* invalid combination */
+
 	if (maj == snd_major) {
 	if (maj == snd_major) {
 		rmidi = snd_lookup_minor_data(iminor(inode),
 		rmidi = snd_lookup_minor_data(iminor(inode),
 					      SNDRV_DEVICE_TYPE_RAWMIDI);
 					      SNDRV_DEVICE_TYPE_RAWMIDI);
@@ -402,24 +392,25 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
 
 
 	if (rmidi == NULL)
 	if (rmidi == NULL)
 		return -ENODEV;
 		return -ENODEV;
-	if ((file->f_flags & O_APPEND) && !(file->f_flags & O_NONBLOCK)) 
-		return -EINVAL;		/* invalid combination */
+
+	if (!try_module_get(rmidi->card->module))
+		return -ENXIO;
+
+	mutex_lock(&rmidi->open_mutex);
 	card = rmidi->card;
 	card = rmidi->card;
 	err = snd_card_file_add(card, file);
 	err = snd_card_file_add(card, file);
 	if (err < 0)
 	if (err < 0)
-		return -ENODEV;
+		goto __error_card;
 	fflags = snd_rawmidi_file_flags(file);
 	fflags = snd_rawmidi_file_flags(file);
 	if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */
 	if ((file->f_flags & O_APPEND) || maj == SOUND_MAJOR) /* OSS emul? */
 		fflags |= SNDRV_RAWMIDI_LFLG_APPEND;
 		fflags |= SNDRV_RAWMIDI_LFLG_APPEND;
-	fflags |= SNDRV_RAWMIDI_LFLG_NOOPENLOCK;
 	rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL);
 	rawmidi_file = kmalloc(sizeof(*rawmidi_file), GFP_KERNEL);
 	if (rawmidi_file == NULL) {
 	if (rawmidi_file == NULL) {
-		snd_card_file_remove(card, file);
-		return -ENOMEM;
+		err = -ENOMEM;
+		goto __error;
 	}
 	}
 	init_waitqueue_entry(&wait, current);
 	init_waitqueue_entry(&wait, current);
 	add_wait_queue(&rmidi->open_wait, &wait);
 	add_wait_queue(&rmidi->open_wait, &wait);
-	mutex_lock(&rmidi->open_mutex);
 	while (1) {
 	while (1) {
 		subdevice = -1;
 		subdevice = -1;
 		read_lock(&card->ctl_files_rwlock);
 		read_lock(&card->ctl_files_rwlock);
@@ -431,8 +422,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
 			}
 			}
 		}
 		}
 		read_unlock(&card->ctl_files_rwlock);
 		read_unlock(&card->ctl_files_rwlock);
-		err = snd_rawmidi_kernel_open(rmidi->card, rmidi->device,
-					      subdevice, fflags, rawmidi_file);
+		err = rawmidi_open_priv(rmidi, subdevice, fflags, rawmidi_file);
 		if (err >= 0)
 		if (err >= 0)
 			break;
 			break;
 		if (err == -EAGAIN) {
 		if (err == -EAGAIN) {
@@ -451,67 +441,89 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
 			break;
 			break;
 		}
 		}
 	}
 	}
+	remove_wait_queue(&rmidi->open_wait, &wait);
+	if (err < 0) {
+		kfree(rawmidi_file);
+		goto __error;
+	}
 #ifdef CONFIG_SND_OSSEMUL
 #ifdef CONFIG_SND_OSSEMUL
 	if (rawmidi_file->input && rawmidi_file->input->runtime)
 	if (rawmidi_file->input && rawmidi_file->input->runtime)
 		rawmidi_file->input->runtime->oss = (maj == SOUND_MAJOR);
 		rawmidi_file->input->runtime->oss = (maj == SOUND_MAJOR);
 	if (rawmidi_file->output && rawmidi_file->output->runtime)
 	if (rawmidi_file->output && rawmidi_file->output->runtime)
 		rawmidi_file->output->runtime->oss = (maj == SOUND_MAJOR);
 		rawmidi_file->output->runtime->oss = (maj == SOUND_MAJOR);
 #endif
 #endif
-	remove_wait_queue(&rmidi->open_wait, &wait);
-	if (err >= 0) {
-		file->private_data = rawmidi_file;
-	} else {
-		snd_card_file_remove(card, file);
-		kfree(rawmidi_file);
-	}
+	file->private_data = rawmidi_file;
+	mutex_unlock(&rmidi->open_mutex);
+	return 0;
+
+ __error:
+	snd_card_file_remove(card, file);
+ __error_card:
 	mutex_unlock(&rmidi->open_mutex);
 	mutex_unlock(&rmidi->open_mutex);
+	module_put(rmidi->card->module);
 	return err;
 	return err;
 }
 }
 
 
-int snd_rawmidi_kernel_release(struct snd_rawmidi_file * rfile)
+static void close_substream(struct snd_rawmidi *rmidi,
+			    struct snd_rawmidi_substream *substream,
+			    int cleanup)
 {
 {
-	struct snd_rawmidi *rmidi;
-	struct snd_rawmidi_substream *substream;
-	struct snd_rawmidi_runtime *runtime;
+	rmidi->streams[substream->stream].substream_opened--;
+	if (--substream->use_count)
+		return;
 
 
-	if (snd_BUG_ON(!rfile))
-		return -ENXIO;
-	rmidi = rfile->rmidi;
-	mutex_lock(&rmidi->open_mutex);
-	if (rfile->input != NULL) {
-		substream = rfile->input;
-		rfile->input = NULL;
-		runtime = substream->runtime;
-		snd_rawmidi_input_trigger(substream, 0);
-		substream->ops->close(substream);
-		if (runtime->private_free != NULL)
-			runtime->private_free(substream);
-		snd_rawmidi_runtime_free(substream);
-		substream->opened = 0;
-		rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substream_opened--;
-	}
-	if (rfile->output != NULL) {
-		substream = rfile->output;
-		rfile->output = NULL;
-		if (--substream->use_count == 0) {
-			runtime = substream->runtime;
+	if (cleanup) {
+		if (substream->stream == SNDRV_RAWMIDI_STREAM_INPUT)
+			snd_rawmidi_input_trigger(substream, 0);
+		else {
 			if (substream->active_sensing) {
 			if (substream->active_sensing) {
 				unsigned char buf = 0xfe;
 				unsigned char buf = 0xfe;
-				/* sending single active sensing message to shut the device up */
+				/* sending single active sensing message
+				 * to shut the device up
+				 */
 				snd_rawmidi_kernel_write(substream, &buf, 1);
 				snd_rawmidi_kernel_write(substream, &buf, 1);
 			}
 			}
 			if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS)
 			if (snd_rawmidi_drain_output(substream) == -ERESTARTSYS)
 				snd_rawmidi_output_trigger(substream, 0);
 				snd_rawmidi_output_trigger(substream, 0);
-			substream->ops->close(substream);
-			if (runtime->private_free != NULL)
-				runtime->private_free(substream);
-			snd_rawmidi_runtime_free(substream);
-			substream->opened = 0;
-			substream->append = 0;
 		}
 		}
-		rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substream_opened--;
 	}
 	}
+	substream->ops->close(substream);
+	if (substream->runtime->private_free)
+		substream->runtime->private_free(substream);
+	snd_rawmidi_runtime_free(substream);
+	substream->opened = 0;
+	substream->append = 0;
+}
+
+static void rawmidi_release_priv(struct snd_rawmidi_file *rfile)
+{
+	struct snd_rawmidi *rmidi;
+
+	rmidi = rfile->rmidi;
+	mutex_lock(&rmidi->open_mutex);
+	if (rfile->input) {
+		close_substream(rmidi, rfile->input, 1);
+		rfile->input = NULL;
+	}
+	if (rfile->output) {
+		close_substream(rmidi, rfile->output, 1);
+		rfile->output = NULL;
+	}
+	rfile->rmidi = NULL;
 	mutex_unlock(&rmidi->open_mutex);
 	mutex_unlock(&rmidi->open_mutex);
+	wake_up(&rmidi->open_wait);
+}
+
+/* called from sound/core/seq/seq_midi.c */
+int snd_rawmidi_kernel_release(struct snd_rawmidi_file *rfile)
+{
+	struct snd_rawmidi *rmidi;
+
+	if (snd_BUG_ON(!rfile))
+		return -ENXIO;
+	
+	rmidi = rfile->rmidi;
+	rawmidi_release_priv(rfile);
 	module_put(rmidi->card->module);
 	module_put(rmidi->card->module);
 	return 0;
 	return 0;
 }
 }
@@ -520,15 +532,14 @@ static int snd_rawmidi_release(struct inode *inode, struct file *file)
 {
 {
 	struct snd_rawmidi_file *rfile;
 	struct snd_rawmidi_file *rfile;
 	struct snd_rawmidi *rmidi;
 	struct snd_rawmidi *rmidi;
-	int err;
 
 
 	rfile = file->private_data;
 	rfile = file->private_data;
-	err = snd_rawmidi_kernel_release(rfile);
 	rmidi = rfile->rmidi;
 	rmidi = rfile->rmidi;
-	wake_up(&rmidi->open_wait);
+	rawmidi_release_priv(rfile);
 	kfree(rfile);
 	kfree(rfile);
 	snd_card_file_remove(rmidi->card, file);
 	snd_card_file_remove(rmidi->card, file);
-	return err;
+	module_put(rmidi->card->module);
+	return 0;
 }
 }
 
 
 static int snd_rawmidi_info(struct snd_rawmidi_substream *substream,
 static int snd_rawmidi_info(struct snd_rawmidi_substream *substream,

+ 1 - 1
sound/core/seq/oss/seq_oss_device.h

@@ -181,7 +181,7 @@ char *enabled_str(int bool);
 /* for debug */
 /* for debug */
 #ifdef SNDRV_SEQ_OSS_DEBUG
 #ifdef SNDRV_SEQ_OSS_DEBUG
 extern int seq_oss_debug;
 extern int seq_oss_debug;
-#define debug_printk(x)	do { if (seq_oss_debug > 0) snd_printk x; } while (0)
+#define debug_printk(x)	do { if (seq_oss_debug > 0) snd_printd x; } while (0)
 #else
 #else
 #define debug_printk(x)	/**/
 #define debug_printk(x)	/**/
 #endif
 #endif

+ 2 - 1
sound/core/seq/seq_prioq.c

@@ -321,7 +321,8 @@ void snd_seq_prioq_leave(struct snd_seq_prioq * f, int client, int timestamp)
 			freeprev = cell;
 			freeprev = cell;
 		} else {
 		} else {
 #if 0
 #if 0
-			printk("type = %i, source = %i, dest = %i, client = %i\n",
+			printk(KERN_DEBUG "type = %i, source = %i, dest = %i, "
+			       "client = %i\n",
 				cell->event.type,
 				cell->event.type,
 				cell->event.source.client,
 				cell->event.source.client,
 				cell->event.dest.client,
 				cell->event.dest.client,

+ 43 - 19
sound/core/vmaster.c

@@ -50,18 +50,38 @@ struct link_slave {
 	struct link_master *master;
 	struct link_master *master;
 	struct link_ctl_info info;
 	struct link_ctl_info info;
 	int vals[2];		/* current values */
 	int vals[2];		/* current values */
+	unsigned int flags;
 	struct snd_kcontrol slave; /* the copy of original control entry */
 	struct snd_kcontrol slave; /* the copy of original control entry */
 };
 };
 
 
+static int slave_update(struct link_slave *slave)
+{
+	struct snd_ctl_elem_value *uctl;
+	int err, ch;
+
+	uctl = kmalloc(sizeof(*uctl), GFP_KERNEL);
+	if (!uctl)
+		return -ENOMEM;
+	uctl->id = slave->slave.id;
+	err = slave->slave.get(&slave->slave, uctl);
+	for (ch = 0; ch < slave->info.count; ch++)
+		slave->vals[ch] = uctl->value.integer.value[ch];
+	kfree(uctl);
+	return 0;
+}
+
 /* get the slave ctl info and save the initial values */
 /* get the slave ctl info and save the initial values */
 static int slave_init(struct link_slave *slave)
 static int slave_init(struct link_slave *slave)
 {
 {
 	struct snd_ctl_elem_info *uinfo;
 	struct snd_ctl_elem_info *uinfo;
-	struct snd_ctl_elem_value *uctl;
-	int err, ch;
+	int err;
 
 
-	if (slave->info.count)
-		return 0; /* already initialized */
+	if (slave->info.count) {
+		/* already initialized */
+		if (slave->flags & SND_CTL_SLAVE_NEED_UPDATE)
+			return slave_update(slave);
+		return 0;
+	}
 
 
 	uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
 	uinfo = kmalloc(sizeof(*uinfo), GFP_KERNEL);
 	if (!uinfo)
 	if (!uinfo)
@@ -85,15 +105,7 @@ static int slave_init(struct link_slave *slave)
 	slave->info.max_val = uinfo->value.integer.max;
 	slave->info.max_val = uinfo->value.integer.max;
 	kfree(uinfo);
 	kfree(uinfo);
 
 
-	uctl = kmalloc(sizeof(*uctl), GFP_KERNEL);
-	if (!uctl)
-		return -ENOMEM;
-	uctl->id = slave->slave.id;
-	err = slave->slave.get(&slave->slave, uctl);
-	for (ch = 0; ch < slave->info.count; ch++)
-		slave->vals[ch] = uctl->value.integer.value[ch];
-	kfree(uctl);
-	return 0;
+	return slave_update(slave);
 }
 }
 
 
 /* initialize master volume */
 /* initialize master volume */
@@ -229,7 +241,8 @@ static void slave_free(struct snd_kcontrol *kcontrol)
  * - logarithmic volume control (dB level), no linear volume
  * - logarithmic volume control (dB level), no linear volume
  * - master can only attenuate the volume, no gain
  * - master can only attenuate the volume, no gain
  */
  */
-int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
+int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
+		       unsigned int flags)
 {
 {
 	struct link_master *master_link = snd_kcontrol_chip(master);
 	struct link_master *master_link = snd_kcontrol_chip(master);
 	struct link_slave *srec;
 	struct link_slave *srec;
@@ -241,6 +254,7 @@ int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
 	srec->slave = *slave;
 	srec->slave = *slave;
 	memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
 	memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
 	srec->master = master_link;
 	srec->master = master_link;
+	srec->flags = flags;
 
 
 	/* override callbacks */
 	/* override callbacks */
 	slave->info = slave_info;
 	slave->info = slave_info;
@@ -254,8 +268,7 @@ int snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave)
 	list_add_tail(&srec->list, &master_link->slaves);
 	list_add_tail(&srec->list, &master_link->slaves);
 	return 0;
 	return 0;
 }
 }
-
-EXPORT_SYMBOL(snd_ctl_add_slave);
+EXPORT_SYMBOL(_snd_ctl_add_slave);
 
 
 /*
 /*
  * ctl callbacks for master controls
  * ctl callbacks for master controls
@@ -327,8 +340,20 @@ static void master_free(struct snd_kcontrol *kcontrol)
 }
 }
 
 
 
 
-/*
- * Create a virtual master control with the given name
+/**
+ * snd_ctl_make_virtual_master - Create a virtual master control
+ * @name: name string of the control element to create
+ * @tlv: optional TLV int array for dB information
+ *
+ * Creates a virtual matster control with the given name string.
+ * Returns the created control element, or NULL for errors (ENOMEM).
+ *
+ * After creating a vmaster element, you can add the slave controls
+ * via snd_ctl_add_slave() or snd_ctl_add_slave_uncached().
+ *
+ * The optional argument @tlv can be used to specify the TLV information
+ * for dB scale of the master control.  It should be a single element
+ * with #SNDRV_CTL_TLVT_DB_SCALE type, and should be the max 0dB.
  */
  */
 struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
 struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
 						 const unsigned int *tlv)
 						 const unsigned int *tlv)
@@ -367,5 +392,4 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
 
 
 	return kctl;
 	return kctl;
 }
 }
-
 EXPORT_SYMBOL(snd_ctl_make_virtual_master);
 EXPORT_SYMBOL(snd_ctl_make_virtual_master);

+ 4 - 4
sound/drivers/dummy.c

@@ -588,10 +588,10 @@ static int __devinit snd_dummy_probe(struct platform_device *devptr)
 	int idx, err;
 	int idx, err;
 	int dev = devptr->id;
 	int dev = devptr->id;
 
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct snd_dummy));
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct snd_dummy), &card);
+	if (err < 0)
+		return err;
 	dummy = card->private_data;
 	dummy = card->private_data;
 	dummy->card = card;
 	dummy->card = card;
 	for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) {
 	for (idx = 0; idx < MAX_PCM_DEVICES && idx < pcm_devs[dev]; idx++) {

+ 3 - 3
sound/drivers/ml403-ac97cr.c

@@ -1279,9 +1279,9 @@ static int __devinit snd_ml403_ac97cr_probe(struct platform_device *pfdev)
 	if (!enable[dev])
 	if (!enable[dev])
 		return -ENOENT;
 		return -ENOENT;
 
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 	err = snd_ml403_ac97cr_create(card, pfdev, &ml403_ac97cr);
 	err = snd_ml403_ac97cr_create(card, pfdev, &ml403_ac97cr);
 	if (err < 0) {
 	if (err < 0) {
 		PDEBUG(INIT_FAILURE, "probe(): create failed!\n");
 		PDEBUG(INIT_FAILURE, "probe(): create failed!\n");

+ 3 - 3
sound/drivers/mpu401/mpu401.c

@@ -73,9 +73,9 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard)
 		snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n");
 		snd_printk(KERN_ERR "the uart_enter option is obsolete; remove it\n");
 
 
 	*rcard = NULL;
 	*rcard = NULL;
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 	strcpy(card->driver, "MPU-401 UART");
 	strcpy(card->driver, "MPU-401 UART");
 	strcpy(card->shortname, card->driver);
 	strcpy(card->shortname, card->driver);
 	sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]);
 	sprintf(card->longname, "%s at %#lx, ", card->shortname, port[dev]);

+ 10 - 8
sound/drivers/mtpav.c

@@ -303,8 +303,10 @@ static void snd_mtpav_output_port_write(struct mtpav *mtp_card,
 
 
 		snd_mtpav_send_byte(mtp_card, 0xf5);
 		snd_mtpav_send_byte(mtp_card, 0xf5);
 		snd_mtpav_send_byte(mtp_card, portp->hwport);
 		snd_mtpav_send_byte(mtp_card, portp->hwport);
-		//snd_printk("new outport: 0x%x\n", (unsigned int) portp->hwport);
-
+		/*
+		snd_printk(KERN_DEBUG "new outport: 0x%x\n",
+			   (unsigned int) portp->hwport);
+		*/
 		if (!(outbyte & 0x80) && portp->running_status)
 		if (!(outbyte & 0x80) && portp->running_status)
 			snd_mtpav_send_byte(mtp_card, portp->running_status);
 			snd_mtpav_send_byte(mtp_card, portp->running_status);
 	}
 	}
@@ -540,7 +542,7 @@ static void snd_mtpav_read_bytes(struct mtpav *mcrd)
 
 
 	u8 sbyt = snd_mtpav_getreg(mcrd, SREG);
 	u8 sbyt = snd_mtpav_getreg(mcrd, SREG);
 
 
-	//printk("snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt);
+	/* printk(KERN_DEBUG "snd_mtpav_read_bytes() sbyt: 0x%x\n", sbyt); */
 
 
 	if (!(sbyt & SIGS_BYTE))
 	if (!(sbyt & SIGS_BYTE))
 		return;
 		return;
@@ -585,12 +587,12 @@ static irqreturn_t snd_mtpav_irqh(int irq, void *dev_id)
 static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard)
 static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard)
 {
 {
 	if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) {
 	if ((mcard->res_port = request_region(port, 3, "MotuMTPAV MIDI")) == NULL) {
-		snd_printk("MTVAP port 0x%lx is busy\n", port);
+		snd_printk(KERN_ERR "MTVAP port 0x%lx is busy\n", port);
 		return -EBUSY;
 		return -EBUSY;
 	}
 	}
 	mcard->port = port;
 	mcard->port = port;
 	if (request_irq(irq, snd_mtpav_irqh, IRQF_DISABLED, "MOTU MTPAV", mcard)) {
 	if (request_irq(irq, snd_mtpav_irqh, IRQF_DISABLED, "MOTU MTPAV", mcard)) {
-		snd_printk("MTVAP IRQ %d busy\n", irq);
+		snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq);
 		return -EBUSY;
 		return -EBUSY;
 	}
 	}
 	mcard->irq = irq;
 	mcard->irq = irq;
@@ -696,9 +698,9 @@ static int __devinit snd_mtpav_probe(struct platform_device *dev)
 	int err;
 	int err;
 	struct mtpav *mtp_card;
 	struct mtpav *mtp_card;
 
 
-	card = snd_card_new(index, id, THIS_MODULE, sizeof(*mtp_card));
-	if (! card)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, sizeof(*mtp_card), &card);
+	if (err < 0)
+		return err;
 
 
 	mtp_card = card->private_data;
 	mtp_card = card->private_data;
 	spin_lock_init(&mtp_card->spinlock);
 	spin_lock_init(&mtp_card->spinlock);

+ 4 - 4
sound/drivers/mts64.c

@@ -957,10 +957,10 @@ static int __devinit snd_mts64_probe(struct platform_device *pdev)
 	if ((err = snd_mts64_probe_port(p)) < 0)
 	if ((err = snd_mts64_probe_port(p)) < 0)
 		return err;
 		return err;
 
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL) {
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0) {
 		snd_printd("Cannot create card\n");
 		snd_printd("Cannot create card\n");
-		return -ENOMEM;
+		return err;
 	}
 	}
 	strcpy(card->driver, DRIVER_NAME);
 	strcpy(card->driver, DRIVER_NAME);
 	strcpy(card->shortname, "ESI " CARD_NAME);
 	strcpy(card->shortname, "ESI " CARD_NAME);
@@ -1015,7 +1015,7 @@ static int __devinit snd_mts64_probe(struct platform_device *pdev)
 		goto __err;
 		goto __err;
 	}
 	}
 
 
-	snd_printk("ESI Miditerminal 4140 on 0x%lx\n", p->base);
+	snd_printk(KERN_INFO "ESI Miditerminal 4140 on 0x%lx\n", p->base);
 	return 0;
 	return 0;
 
 
 __err:
 __err:

+ 1 - 1
sound/drivers/opl3/opl3_lib.c

@@ -302,7 +302,7 @@ void snd_opl3_interrupt(struct snd_hwdep * hw)
 	opl3 = hw->private_data;
 	opl3 = hw->private_data;
 	status = inb(opl3->l_port);
 	status = inb(opl3->l_port);
 #if 0
 #if 0
-	snd_printk("AdLib IRQ status = 0x%x\n", status);
+	snd_printk(KERN_DEBUG "AdLib IRQ status = 0x%x\n", status);
 #endif
 #endif
 	if (!(status & 0x80))
 	if (!(status & 0x80))
 		return;
 		return;

+ 15 - 15
sound/drivers/opl3/opl3_midi.c

@@ -125,7 +125,7 @@ static void debug_alloc(struct snd_opl3 *opl3, char *s, int voice) {
 	int i;
 	int i;
 	char *str = "x.24";
 	char *str = "x.24";
 
 
-	printk("time %.5i: %s [%.2i]: ", opl3->use_time, s, voice);
+	printk(KERN_DEBUG "time %.5i: %s [%.2i]: ", opl3->use_time, s, voice);
 	for (i = 0; i < opl3->max_voices; i++)
 	for (i = 0; i < opl3->max_voices; i++)
 		printk("%c", *(str + opl3->voices[i].state + 1));
 		printk("%c", *(str + opl3->voices[i].state + 1));
 	printk("\n");
 	printk("\n");
@@ -218,7 +218,7 @@ static int opl3_get_voice(struct snd_opl3 *opl3, int instr_4op,
 	for (i = 0; i < END; i++) {
 	for (i = 0; i < END; i++) {
 		if (best[i].voice >= 0) {
 		if (best[i].voice >= 0) {
 #ifdef DEBUG_ALLOC
 #ifdef DEBUG_ALLOC
-			printk("%s %iop allocation on voice %i\n",
+			printk(KERN_DEBUG "%s %iop allocation on voice %i\n",
 			       alloc_type[i], instr_4op ? 4 : 2,
 			       alloc_type[i], instr_4op ? 4 : 2,
 			       best[i].voice);
 			       best[i].voice);
 #endif
 #endif
@@ -317,7 +317,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan)
 	opl3 = p;
 	opl3 = p;
 
 
 #ifdef DEBUG_MIDI
 #ifdef DEBUG_MIDI
-	snd_printk("Note on, ch %i, inst %i, note %i, vel %i\n",
+	snd_printk(KERN_DEBUG "Note on, ch %i, inst %i, note %i, vel %i\n",
 		   chan->number, chan->midi_program, note, vel);
 		   chan->number, chan->midi_program, note, vel);
 #endif
 #endif
 
 
@@ -372,7 +372,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan)
 		return;
 		return;
 	}
 	}
 #ifdef DEBUG_MIDI
 #ifdef DEBUG_MIDI
-	snd_printk("  --> OPL%i instrument: %s\n",
+	snd_printk(KERN_DEBUG "  --> OPL%i instrument: %s\n",
 		   instr_4op ? 3 : 2, patch->name);
 		   instr_4op ? 3 : 2, patch->name);
 #endif
 #endif
 	/* in SYNTH mode, application takes care of voices */
 	/* in SYNTH mode, application takes care of voices */
@@ -431,7 +431,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan)
 	}
 	}
 
 
 #ifdef DEBUG_MIDI
 #ifdef DEBUG_MIDI
-	snd_printk("  --> setting OPL3 connection: 0x%x\n",
+	snd_printk(KERN_DEBUG "  --> setting OPL3 connection: 0x%x\n",
 		   opl3->connection_reg);
 		   opl3->connection_reg);
 #endif
 #endif
 	/*
 	/*
@@ -466,7 +466,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan)
 	/* Program the FM voice characteristics */
 	/* Program the FM voice characteristics */
 	for (i = 0; i < (instr_4op ? 4 : 2); i++) {
 	for (i = 0; i < (instr_4op ? 4 : 2); i++) {
 #ifdef DEBUG_MIDI
 #ifdef DEBUG_MIDI
-		snd_printk("  --> programming operator %i\n", i);
+		snd_printk(KERN_DEBUG "  --> programming operator %i\n", i);
 #endif
 #endif
 		op_offset = snd_opl3_regmap[voice_offset][i];
 		op_offset = snd_opl3_regmap[voice_offset][i];
 
 
@@ -546,7 +546,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan)
 	blocknum |= OPL3_KEYON_BIT;
 	blocknum |= OPL3_KEYON_BIT;
 
 
 #ifdef DEBUG_MIDI
 #ifdef DEBUG_MIDI
-	snd_printk("  --> trigger voice %i\n", voice);
+	snd_printk(KERN_DEBUG "  --> trigger voice %i\n", voice);
 #endif
 #endif
 	/* Set OPL3 KEYON_BLOCK register of requested voice */ 
 	/* Set OPL3 KEYON_BLOCK register of requested voice */ 
 	opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
 	opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
@@ -602,7 +602,7 @@ void snd_opl3_note_on(void *p, int note, int vel, struct snd_midi_channel *chan)
 			prg = extra_prg - 1;
 			prg = extra_prg - 1;
 		}
 		}
 #ifdef DEBUG_MIDI
 #ifdef DEBUG_MIDI
-		snd_printk(" *** allocating extra program\n");
+		snd_printk(KERN_DEBUG " *** allocating extra program\n");
 #endif
 #endif
 		goto __extra_prg;
 		goto __extra_prg;
 	}
 	}
@@ -633,7 +633,7 @@ static void snd_opl3_kill_voice(struct snd_opl3 *opl3, int voice)
 
 
 	/* kill voice */
 	/* kill voice */
 #ifdef DEBUG_MIDI
 #ifdef DEBUG_MIDI
-	snd_printk("  --> kill voice %i\n", voice);
+	snd_printk(KERN_DEBUG "  --> kill voice %i\n", voice);
 #endif
 #endif
 	opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
 	opl3_reg = reg_side | (OPL3_REG_KEYON_BLOCK + voice_offset);
 	/* clear Key ON bit */
 	/* clear Key ON bit */
@@ -670,7 +670,7 @@ void snd_opl3_note_off(void *p, int note, int vel, struct snd_midi_channel *chan
 	opl3 = p;
 	opl3 = p;
 
 
 #ifdef DEBUG_MIDI
 #ifdef DEBUG_MIDI
-	snd_printk("Note off, ch %i, inst %i, note %i\n",
+	snd_printk(KERN_DEBUG "Note off, ch %i, inst %i, note %i\n",
 		   chan->number, chan->midi_program, note);
 		   chan->number, chan->midi_program, note);
 #endif
 #endif
 
 
@@ -709,7 +709,7 @@ void snd_opl3_key_press(void *p, int note, int vel, struct snd_midi_channel *cha
 
 
 	opl3 = p;
 	opl3 = p;
 #ifdef DEBUG_MIDI
 #ifdef DEBUG_MIDI
-	snd_printk("Key pressure, ch#: %i, inst#: %i\n",
+	snd_printk(KERN_DEBUG "Key pressure, ch#: %i, inst#: %i\n",
 		   chan->number, chan->midi_program);
 		   chan->number, chan->midi_program);
 #endif
 #endif
 }
 }
@@ -723,7 +723,7 @@ void snd_opl3_terminate_note(void *p, int note, struct snd_midi_channel *chan)
 
 
 	opl3 = p;
 	opl3 = p;
 #ifdef DEBUG_MIDI
 #ifdef DEBUG_MIDI
-	snd_printk("Terminate note, ch#: %i, inst#: %i\n",
+	snd_printk(KERN_DEBUG "Terminate note, ch#: %i, inst#: %i\n",
 		   chan->number, chan->midi_program);
 		   chan->number, chan->midi_program);
 #endif
 #endif
 }
 }
@@ -812,7 +812,7 @@ void snd_opl3_control(void *p, int type, struct snd_midi_channel *chan)
 
 
 	opl3 = p;
 	opl3 = p;
 #ifdef DEBUG_MIDI
 #ifdef DEBUG_MIDI
-	snd_printk("Controller, TYPE = %i, ch#: %i, inst#: %i\n",
+	snd_printk(KERN_DEBUG "Controller, TYPE = %i, ch#: %i, inst#: %i\n",
 		   type, chan->number, chan->midi_program);
 		   type, chan->number, chan->midi_program);
 #endif
 #endif
 
 
@@ -849,7 +849,7 @@ void snd_opl3_nrpn(void *p, struct snd_midi_channel *chan,
 
 
 	opl3 = p;
 	opl3 = p;
 #ifdef DEBUG_MIDI
 #ifdef DEBUG_MIDI
-	snd_printk("NRPN, ch#: %i, inst#: %i\n",
+	snd_printk(KERN_DEBUG "NRPN, ch#: %i, inst#: %i\n",
 		   chan->number, chan->midi_program);
 		   chan->number, chan->midi_program);
 #endif
 #endif
 }
 }
@@ -864,6 +864,6 @@ void snd_opl3_sysex(void *p, unsigned char *buf, int len,
 
 
 	opl3 = p;
 	opl3 = p;
 #ifdef DEBUG_MIDI
 #ifdef DEBUG_MIDI
-	snd_printk("SYSEX\n");
+	snd_printk(KERN_DEBUG "SYSEX\n");
 #endif
 #endif
 }
 }

+ 5 - 3
sound/drivers/opl3/opl3_oss.c

@@ -220,14 +220,14 @@ static int snd_opl3_load_patch_seq_oss(struct snd_seq_oss_arg *arg, int format,
 		return -EINVAL;
 		return -EINVAL;
 
 
 	if (count < (int)sizeof(sbi)) {
 	if (count < (int)sizeof(sbi)) {
-		snd_printk("FM Error: Patch record too short\n");
+		snd_printk(KERN_ERR "FM Error: Patch record too short\n");
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 	if (copy_from_user(&sbi, buf, sizeof(sbi)))
 	if (copy_from_user(&sbi, buf, sizeof(sbi)))
 		return -EFAULT;
 		return -EFAULT;
 
 
 	if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) {
 	if (sbi.channel < 0 || sbi.channel >= SBFM_MAXINSTR) {
-		snd_printk("FM Error: Invalid instrument number %d\n",
+		snd_printk(KERN_ERR "FM Error: Invalid instrument number %d\n",
 			   sbi.channel);
 			   sbi.channel);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
@@ -254,7 +254,9 @@ static int snd_opl3_ioctl_seq_oss(struct snd_seq_oss_arg *arg, unsigned int cmd,
 	opl3 = arg->private_data;
 	opl3 = arg->private_data;
 	switch (cmd) {
 	switch (cmd) {
 		case SNDCTL_FM_LOAD_INSTR:
 		case SNDCTL_FM_LOAD_INSTR:
-			snd_printk("OPL3: Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. Fix the program.\n");
+			snd_printk(KERN_ERR "OPL3: "
+				   "Obsolete ioctl(SNDCTL_FM_LOAD_INSTR) used. "
+				   "Fix the program.\n");
 			return -EINVAL;
 			return -EINVAL;
 
 
 		case SNDCTL_SYNTH_MEMAVL:
 		case SNDCTL_SYNTH_MEMAVL:

+ 1 - 1
sound/drivers/opl3/opl3_synth.c

@@ -168,7 +168,7 @@ int snd_opl3_ioctl(struct snd_hwdep * hw, struct file *file,
 
 
 #ifdef CONFIG_SND_DEBUG
 #ifdef CONFIG_SND_DEBUG
 	default:
 	default:
-		snd_printk("unknown IOCTL: 0x%x\n", cmd);
+		snd_printk(KERN_WARNING "unknown IOCTL: 0x%x\n", cmd);
 #endif
 #endif
 	}
 	}
 	return -ENOTTY;
 	return -ENOTTY;

+ 4 - 4
sound/drivers/pcsp/pcsp.c

@@ -57,7 +57,7 @@ static int __devinit snd_pcsp_create(struct snd_card *card)
 	else
 	else
 		min_div = MAX_DIV;
 		min_div = MAX_DIV;
 #if PCSP_DEBUG
 #if PCSP_DEBUG
-	printk("PCSP: lpj=%li, min_div=%i, res=%li\n",
+	printk(KERN_DEBUG "PCSP: lpj=%li, min_div=%i, res=%li\n",
 	       loops_per_jiffy, min_div, tp.tv_nsec);
 	       loops_per_jiffy, min_div, tp.tv_nsec);
 #endif
 #endif
 
 
@@ -98,9 +98,9 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
 	hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	pcsp_chip.timer.function = pcsp_do_timer;
 	pcsp_chip.timer.function = pcsp_do_timer;
 
 
-	card = snd_card_new(index, id, THIS_MODULE, 0);
-	if (!card)
-		return -ENOMEM;
+	err = snd_card_create(index, id, THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 
 	err = snd_pcsp_create(card);
 	err = snd_pcsp_create(card);
 	if (err < 0) {
 	if (err < 0) {

+ 3 - 3
sound/drivers/portman2x4.c

@@ -746,10 +746,10 @@ static int __devinit snd_portman_probe(struct platform_device *pdev)
 	if ((err = snd_portman_probe_port(p)) < 0)
 	if ((err = snd_portman_probe_port(p)) < 0)
 		return err;
 		return err;
 
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL) {
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0) {
 		snd_printd("Cannot create card\n");
 		snd_printd("Cannot create card\n");
-		return -ENOMEM;
+		return err;
 	}
 	}
 	strcpy(card->driver, DRIVER_NAME);
 	strcpy(card->driver, DRIVER_NAME);
 	strcpy(card->shortname, CARD_NAME);
 	strcpy(card->shortname, CARD_NAME);

+ 15 - 9
sound/drivers/serial-u16550.c

@@ -241,7 +241,8 @@ static void snd_uart16550_io_loop(struct snd_uart16550 * uart)
 			snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
 			snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
 
 
 		if (status & UART_LSR_OE)
 		if (status & UART_LSR_OE)
-			snd_printk("%s: Overrun on device at 0x%lx\n",
+			snd_printk(KERN_WARNING
+				   "%s: Overrun on device at 0x%lx\n",
 			       uart->rmidi->name, uart->base);
 			       uart->rmidi->name, uart->base);
 	}
 	}
 
 
@@ -636,7 +637,8 @@ static int snd_uart16550_output_byte(struct snd_uart16550 *uart,
 		}
 		}
 	} else {
 	} else {
 		if (!snd_uart16550_write_buffer(uart, midi_byte)) {
 		if (!snd_uart16550_write_buffer(uart, midi_byte)) {
-			snd_printk("%s: Buffer overrun on device at 0x%lx\n",
+			snd_printk(KERN_WARNING
+				   "%s: Buffer overrun on device at 0x%lx\n",
 				   uart->rmidi->name, uart->base);
 				   uart->rmidi->name, uart->base);
 			return 0;
 			return 0;
 		}
 		}
@@ -815,7 +817,8 @@ static int __devinit snd_uart16550_create(struct snd_card *card,
 	if (irq >= 0 && irq != SNDRV_AUTO_IRQ) {
 	if (irq >= 0 && irq != SNDRV_AUTO_IRQ) {
 		if (request_irq(irq, snd_uart16550_interrupt,
 		if (request_irq(irq, snd_uart16550_interrupt,
 				IRQF_DISABLED, "Serial MIDI", uart)) {
 				IRQF_DISABLED, "Serial MIDI", uart)) {
-			snd_printk("irq %d busy. Using Polling.\n", irq);
+			snd_printk(KERN_WARNING
+				   "irq %d busy. Using Polling.\n", irq);
 		} else {
 		} else {
 			uart->irq = irq;
 			uart->irq = irq;
 		}
 		}
@@ -919,26 +922,29 @@ static int __devinit snd_serial_probe(struct platform_device *devptr)
 	case SNDRV_SERIAL_GENERIC:
 	case SNDRV_SERIAL_GENERIC:
 		break;
 		break;
 	default:
 	default:
-		snd_printk("Adaptor type is out of range 0-%d (%d)\n",
+		snd_printk(KERN_ERR
+			   "Adaptor type is out of range 0-%d (%d)\n",
 			   SNDRV_SERIAL_MAX_ADAPTOR, adaptor[dev]);
 			   SNDRV_SERIAL_MAX_ADAPTOR, adaptor[dev]);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
 	if (outs[dev] < 1 || outs[dev] > SNDRV_SERIAL_MAX_OUTS) {
 	if (outs[dev] < 1 || outs[dev] > SNDRV_SERIAL_MAX_OUTS) {
-		snd_printk("Count of outputs is out of range 1-%d (%d)\n",
+		snd_printk(KERN_ERR
+			   "Count of outputs is out of range 1-%d (%d)\n",
 			   SNDRV_SERIAL_MAX_OUTS, outs[dev]);
 			   SNDRV_SERIAL_MAX_OUTS, outs[dev]);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
 	if (ins[dev] < 1 || ins[dev] > SNDRV_SERIAL_MAX_INS) {
 	if (ins[dev] < 1 || ins[dev] > SNDRV_SERIAL_MAX_INS) {
-		snd_printk("Count of inputs is out of range 1-%d (%d)\n",
+		snd_printk(KERN_ERR
+			   "Count of inputs is out of range 1-%d (%d)\n",
 			   SNDRV_SERIAL_MAX_INS, ins[dev]);
 			   SNDRV_SERIAL_MAX_INS, ins[dev]);
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
-	card  = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
-	if (card == NULL)
-		return -ENOMEM;
+	err  = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
+	if (err < 0)
+		return err;
 
 
 	strcpy(card->driver, "Serial");
 	strcpy(card->driver, "Serial");
 	strcpy(card->shortname, "Serial MIDI (UART16550A)");
 	strcpy(card->shortname, "Serial MIDI (UART16550A)");

+ 7 - 5
sound/drivers/virmidi.c

@@ -90,15 +90,17 @@ static int __devinit snd_virmidi_probe(struct platform_device *devptr)
 	int idx, err;
 	int idx, err;
 	int dev = devptr->id;
 	int dev = devptr->id;
 
 
-	card = snd_card_new(index[dev], id[dev], THIS_MODULE,
-			    sizeof(struct snd_card_virmidi));
-	if (card == NULL)
-		return -ENOMEM;
+	err = snd_card_create(index[dev], id[dev], THIS_MODULE,
+			      sizeof(struct snd_card_virmidi), &card);
+	if (err < 0)
+		return err;
 	vmidi = (struct snd_card_virmidi *)card->private_data;
 	vmidi = (struct snd_card_virmidi *)card->private_data;
 	vmidi->card = card;
 	vmidi->card = card;
 
 
 	if (midi_devs[dev] > MAX_MIDI_DEVICES) {
 	if (midi_devs[dev] > MAX_MIDI_DEVICES) {
-		snd_printk("too much midi devices for virmidi %d: force to use %d\n", dev, MAX_MIDI_DEVICES);
+		snd_printk(KERN_WARNING
+			   "too much midi devices for virmidi %d: "
+			   "force to use %d\n", dev, MAX_MIDI_DEVICES);
 		midi_devs[dev] = MAX_MIDI_DEVICES;
 		midi_devs[dev] = MAX_MIDI_DEVICES;
 	}
 	}
 	for (idx = 0; idx < midi_devs[dev]; idx++) {
 	for (idx = 0; idx < midi_devs[dev]; idx++) {

+ 2 - 1
sound/drivers/vx/vx_core.c

@@ -688,7 +688,8 @@ int snd_vx_dsp_load(struct vx_core *chip, const struct firmware *dsp)
 		image = dsp->data + i;
 		image = dsp->data + i;
 		/* Wait DSP ready for a new read */
 		/* Wait DSP ready for a new read */
 		if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) {
 		if ((err = vx_wait_isr_bit(chip, ISR_TX_EMPTY)) < 0) {
-			printk("dsp loading error at position %d\n", i);
+			printk(KERN_ERR
+			       "dsp loading error at position %d\n", i);
 			return err;
 			return err;
 		}
 		}
 		cptr = image;
 		cptr = image;

+ 0 - 12
sound/drivers/vx/vx_hwdep.c

@@ -119,16 +119,6 @@ void snd_vx_free_firmware(struct vx_core *chip)
 
 
 #else /* old style firmware loading */
 #else /* old style firmware loading */
 
 
-static int vx_hwdep_open(struct snd_hwdep *hw, struct file *file)
-{
-	return 0;
-}
-
-static int vx_hwdep_release(struct snd_hwdep *hw, struct file *file)
-{
-	return 0;
-}
-
 static int vx_hwdep_dsp_status(struct snd_hwdep *hw,
 static int vx_hwdep_dsp_status(struct snd_hwdep *hw,
 			       struct snd_hwdep_dsp_status *info)
 			       struct snd_hwdep_dsp_status *info)
 {
 {
@@ -243,8 +233,6 @@ int snd_vx_setup_firmware(struct vx_core *chip)
 
 
 	hw->iface = SNDRV_HWDEP_IFACE_VX;
 	hw->iface = SNDRV_HWDEP_IFACE_VX;
 	hw->private_data = chip;
 	hw->private_data = chip;
-	hw->ops.open = vx_hwdep_open;
-	hw->ops.release = vx_hwdep_release;
 	hw->ops.dsp_status = vx_hwdep_dsp_status;
 	hw->ops.dsp_status = vx_hwdep_dsp_status;
 	hw->ops.dsp_load = vx_hwdep_dsp_load;
 	hw->ops.dsp_load = vx_hwdep_dsp_load;
 	hw->exclusive = 1;
 	hw->exclusive = 1;

+ 1 - 1
sound/drivers/vx/vx_uer.c

@@ -103,7 +103,7 @@ static void vx_write_one_cbit(struct vx_core *chip, int index, int val)
  * returns the frequency of UER, or 0 if not sync,
  * returns the frequency of UER, or 0 if not sync,
  * or a negative error code.
  * or a negative error code.
  */
  */
-static int vx_read_uer_status(struct vx_core *chip, int *mode)
+static int vx_read_uer_status(struct vx_core *chip, unsigned int *mode)
 {
 {
 	int val, freq;
 	int val, freq;
 
 

+ 0 - 2
sound/i2c/Makefile

@@ -7,8 +7,6 @@ snd-i2c-objs := i2c.o
 snd-cs8427-objs := cs8427.o
 snd-cs8427-objs := cs8427.o
 snd-tea6330t-objs := tea6330t.o
 snd-tea6330t-objs := tea6330t.o
 
 
-obj-$(CONFIG_L3) += l3/
-
 obj-$(CONFIG_SND) += other/
 obj-$(CONFIG_SND) += other/
 
 
 # Toplevel Module Dependency
 # Toplevel Module Dependency

+ 0 - 8
sound/i2c/l3/Makefile

@@ -1,8 +0,0 @@
-#
-# Makefile for ALSA
-#
-
-snd-uda1341-objs := uda1341.o
-
-# Module Dependency
-obj-$(CONFIG_SND_SA11XX_UDA1341) += snd-uda1341.o

Some files were not shown because too many files changed in this diff