浏览代码

Merge branch 'topic/misc' into for-linus

Takashi Iwai 15 年之前
父节点
当前提交
74bf40f079
共有 56 个文件被更改,包括 991 次插入612 次删除
  1. 6 161
      Documentation/kernel-parameters.txt
  2. 8 0
      Documentation/sound/alsa/Procfile.txt
  3. 135 0
      Documentation/sound/alsa/alsa-parameters.txt
  4. 51 0
      Documentation/sound/oss/oss-parameters.txt
  5. 6 0
      arch/um/drivers/hostaudio_kern.c
  6. 3 3
      drivers/usb/gadget/f_audio.c
  7. 1 1
      drivers/usb/gadget/gmidi.c
  8. 16 1
      include/linux/usb/audio-v2.h
  9. 6 6
      include/linux/usb/audio.h
  10. 5 1
      include/sound/asound.h
  11. 5 1
      include/sound/pcm.h
  12. 17 8
      sound/core/pcm_lib.c
  13. 16 0
      sound/core/pcm_misc.c
  14. 21 3
      sound/drivers/Kconfig
  15. 4 1
      sound/isa/msnd/msnd_pinnacle.c
  16. 6 3
      sound/isa/sb/emu8000_pcm.c
  17. 52 39
      sound/oss/au1550_ac97.c
  18. 50 13
      sound/oss/dmasound/dmasound_core.c
  19. 3 1
      sound/oss/midi_synth.c
  20. 24 11
      sound/oss/msnd_pinnacle.c
  21. 22 5
      sound/oss/sh_dac_audio.c
  22. 11 9
      sound/oss/soundcard.c
  23. 35 6
      sound/oss/swarm_cs4297a.c
  24. 0 3
      sound/oss/vidc.c
  25. 21 11
      sound/oss/vwsnd.c
  26. 2 8
      sound/oss/waveartist.c
  27. 2 2
      sound/pci/als4000.c
  28. 9 7
      sound/pci/asihpi/asihpi.c
  29. 48 20
      sound/pci/asihpi/hpi.h
  30. 7 0
      sound/pci/asihpi/hpi6000.c
  31. 22 18
      sound/pci/asihpi/hpi_internal.h
  32. 8 2
      sound/pci/asihpi/hpicmn.c
  33. 1 1
      sound/pci/asihpi/hpidebug.c
  34. 2 2
      sound/pci/asihpi/hpidebug.h
  35. 195 132
      sound/pci/asihpi/hpifunc.c
  36. 1 1
      sound/pci/asihpi/hpimsgx.c
  37. 14 7
      sound/pci/asihpi/hpioctl.c
  38. 2 0
      sound/pci/echoaudio/echoaudio.c
  39. 6 4
      sound/pci/hda/hda_codec.c
  40. 4 1
      sound/pci/hda/hda_codec.h
  41. 6 1
      sound/pci/hda/hda_proc.c
  42. 12 6
      sound/pci/riptide/riptide.c
  43. 9 7
      sound/pci/sis7019.c
  44. 7 2
      sound/pci/via82xx.c
  45. 4 5
      sound/sound_core.c
  46. 1 1
      sound/usb/card.c
  47. 25 34
      sound/usb/clock.c
  48. 1 3
      sound/usb/clock.h
  49. 3 2
      sound/usb/endpoint.c
  50. 4 5
      sound/usb/format.c
  51. 7 7
      sound/usb/midi.c
  52. 42 35
      sound/usb/mixer.c
  53. 0 1
      sound/usb/mixer.h
  54. 0 3
      sound/usb/pcm.h
  55. 22 8
      sound/usb/quirks-table.h
  56. 1 0
      sound/usb/quirks.c

+ 6 - 161
Documentation/kernel-parameters.txt

@@ -280,19 +280,12 @@ and is between 256 and 4096 characters. It is defined in the file
 			no: ACPI OperationRegions are not marked as reserved,
 			no: ACPI OperationRegions are not marked as reserved,
 			no further checks are performed.
 			no further checks are performed.
 
 
-	ad1848=		[HW,OSS]
-			Format: <io>,<irq>,<dma>,<dma2>,<type>
-
 	add_efi_memmap	[EFI; X86] Include EFI memory map in
 	add_efi_memmap	[EFI; X86] Include EFI memory map in
 			kernel's map of available physical RAM.
 			kernel's map of available physical RAM.
 
 
 	advansys=	[HW,SCSI]
 	advansys=	[HW,SCSI]
 			See header of drivers/scsi/advansys.c.
 			See header of drivers/scsi/advansys.c.
 
 
-	aedsp16=	[HW,OSS] Audio Excel DSP 16
-			Format: <io>,<irq>,<dma>,<mss_io>,<mpu_io>,<mpu_irq>
-			See also header of sound/oss/aedsp16.c.
-
 	agp=		[AGP]
 	agp=		[AGP]
 			{ off | try_unsupported }
 			{ off | try_unsupported }
 			off: disable AGP support
 			off: disable AGP support
@@ -311,6 +304,9 @@ and is between 256 and 4096 characters. It is defined in the file
 	aic79xx=	[HW,SCSI]
 	aic79xx=	[HW,SCSI]
 			See Documentation/scsi/aic79xx.txt.
 			See Documentation/scsi/aic79xx.txt.
 
 
+	ALSA		[HW,ALSA]
+			See Documentation/sound/alsa/alsa-parameters.txt
+
 	alignment=	[KNL,ARM]
 	alignment=	[KNL,ARM]
 			Allow the default userspace alignment fault handler
 			Allow the default userspace alignment fault handler
 			behaviour to be specified.  Bit 0 enables warnings,
 			behaviour to be specified.  Bit 0 enables warnings,
@@ -655,8 +651,6 @@ and is between 256 and 4096 characters. It is defined in the file
 			Disable PIN 1 of APIC timer
 			Disable PIN 1 of APIC timer
 			Can be useful to work around chipset bugs.
 			Can be useful to work around chipset bugs.
 
 
-	dmasound=	[HW,OSS] Sound subsystem buffers
-
 	dma_debug=off	If the kernel is compiled with DMA_API_DEBUG support,
 	dma_debug=off	If the kernel is compiled with DMA_API_DEBUG support,
 			this option disables the debugging code at boot.
 			this option disables the debugging code at boot.
 
 
@@ -1523,9 +1517,6 @@ and is between 256 and 4096 characters. It is defined in the file
 			that the amount of memory usable for all allocations
 			that the amount of memory usable for all allocations
 			is not too small.
 			is not too small.
 
 
-	mpu401=		[HW,OSS]
-			Format: <io>,<irq>
-
 	MTD_Partition=	[MTD]
 	MTD_Partition=	[MTD]
 			Format: <name>,<region-number>,<size>,<offset>
 			Format: <name>,<region-number>,<size>,<offset>
 
 
@@ -1849,9 +1840,6 @@ and is between 256 and 4096 characters. It is defined in the file
 			For example, to override I2C bus2:
 			For example, to override I2C bus2:
 			omap_mux=i2c2_scl.i2c2_scl=0x100,i2c2_sda.i2c2_sda=0x100
 			omap_mux=i2c2_scl.i2c2_scl=0x100,i2c2_sda.i2c2_sda=0x100
 
 
-	opl3=		[HW,OSS]
-			Format: <io>
-
 	oprofile.timer=	[HW]
 	oprofile.timer=	[HW]
 			Use timer interrupt instead of performance counters
 			Use timer interrupt instead of performance counters
 
 
@@ -1863,6 +1851,9 @@ and is between 256 and 4096 characters. It is defined in the file
 				perfmon on Intel CPUs instead of the
 				perfmon on Intel CPUs instead of the
 				CPU specific event set.
 				CPU specific event set.
 
 
+	OSS		[HW,OSS]
+			See Documentation/sound/oss/oss-parameters.txt
+
 	osst=		[HW,SCSI] SCSI Tape Driver
 	osst=		[HW,SCSI] SCSI Tape Driver
 			Format: <buffer_size>,<write_threshold>
 			Format: <buffer_size>,<write_threshold>
 			See also Documentation/scsi/st.txt.
 			See also Documentation/scsi/st.txt.
@@ -1899,9 +1890,6 @@ and is between 256 and 4096 characters. It is defined in the file
 			Currently this function knows 686a and 8231 chips.
 			Currently this function knows 686a and 8231 chips.
 			Format: [spp|ps2|epp|ecp|ecpepp]
 			Format: [spp|ps2|epp|ecp|ecpepp]
 
 
-	pas2=		[HW,OSS] Format:
-			<io>,<irq>,<dma>,<dma16>,<sb_io>,<sb_irq>,<sb_dma>,<sb_dma16>
-
 	pas16=		[HW,SCSI]
 	pas16=		[HW,SCSI]
 			See header of drivers/scsi/pas16.c.
 			See header of drivers/scsi/pas16.c.
 
 
@@ -2171,10 +2159,6 @@ and is between 256 and 4096 characters. It is defined in the file
 			[HW,MOUSE] Controls Logitech smartscroll autorepeat.
 			[HW,MOUSE] Controls Logitech smartscroll autorepeat.
 			0 = disabled, 1 = enabled (default).
 			0 = disabled, 1 = enabled (default).
 
 
-	pss=		[HW,OSS] Personal Sound System (ECHO ESC614)
-			Format:
-			<io>,<mss_io>,<mss_irq>,<mss_dma>,<mpu_io>,<mpu_irq>
-
 	pt.		[PARIDE]
 	pt.		[PARIDE]
 			See Documentation/blockdev/paride.txt.
 			See Documentation/blockdev/paride.txt.
 
 
@@ -2383,128 +2367,6 @@ and is between 256 and 4096 characters. It is defined in the file
 				1: Fast pin select (default)
 				1: Fast pin select (default)
 				2: ATC IRMode
 				2: ATC IRMode
 
 
-	snd-ad1816a=	[HW,ALSA]
-
-	snd-ad1848=	[HW,ALSA]
-
-	snd-ali5451=	[HW,ALSA]
-
-	snd-als100=	[HW,ALSA]
-
-	snd-als4000=	[HW,ALSA]
-
-	snd-azt2320=	[HW,ALSA]
-
-	snd-cmi8330=	[HW,ALSA]
-
-	snd-cmipci=	[HW,ALSA]
-
-	snd-cs4231=	[HW,ALSA]
-
-	snd-cs4232=	[HW,ALSA]
-
-	snd-cs4236=	[HW,ALSA]
-
-	snd-cs4281=	[HW,ALSA]
-
-	snd-cs46xx=	[HW,ALSA]
-
-	snd-dt019x=	[HW,ALSA]
-
-	snd-dummy=	[HW,ALSA]
-
-	snd-emu10k1=	[HW,ALSA]
-
-	snd-ens1370=	[HW,ALSA]
-
-	snd-ens1371=	[HW,ALSA]
-
-	snd-es968=	[HW,ALSA]
-
-	snd-es1688=	[HW,ALSA]
-
-	snd-es18xx=	[HW,ALSA]
-
-	snd-es1938=	[HW,ALSA]
-
-	snd-es1968=	[HW,ALSA]
-
-	snd-fm801=	[HW,ALSA]
-
-	snd-gusclassic=	[HW,ALSA]
-
-	snd-gusextreme=	[HW,ALSA]
-
-	snd-gusmax=	[HW,ALSA]
-
-	snd-hdsp=	[HW,ALSA]
-
-	snd-ice1712=	[HW,ALSA]
-
-	snd-intel8x0=	[HW,ALSA]
-
-	snd-interwave=	[HW,ALSA]
-
-	snd-interwave-stb=
-			[HW,ALSA]
-
-	snd-korg1212=	[HW,ALSA]
-
-	snd-maestro3=	[HW,ALSA]
-
-	snd-mpu401=	[HW,ALSA]
-
-	snd-mtpav=	[HW,ALSA]
-
-	snd-nm256=	[HW,ALSA]
-
-	snd-opl3sa2=	[HW,ALSA]
-
-	snd-opti92x-ad1848=
-			[HW,ALSA]
-
-	snd-opti92x-cs4231=
-			[HW,ALSA]
-
-	snd-opti93x=	[HW,ALSA]
-
-	snd-pmac=	[HW,ALSA]
-
-	snd-rme32=	[HW,ALSA]
-
-	snd-rme96=	[HW,ALSA]
-
-	snd-rme9652=	[HW,ALSA]
-
-	snd-sb8=	[HW,ALSA]
-
-	snd-sb16=	[HW,ALSA]
-
-	snd-sbawe=	[HW,ALSA]
-
-	snd-serial=	[HW,ALSA]
-
-	snd-sgalaxy=	[HW,ALSA]
-
-	snd-sonicvibes=	[HW,ALSA]
-
-	snd-sun-amd7930=
-			[HW,ALSA]
-
-	snd-sun-cs4231=	[HW,ALSA]
-
-	snd-trident=	[HW,ALSA]
-
-	snd-usb-audio=	[HW,ALSA,USB]
-
-	snd-via82xx=	[HW,ALSA]
-
-	snd-virmidi=	[HW,ALSA]
-
-	snd-wavefront=	[HW,ALSA]
-
-	snd-ymfpci=	[HW,ALSA]
-
 	softlockup_panic=
 	softlockup_panic=
 			[KNL] Should the soft-lockup detector generate panics.
 			[KNL] Should the soft-lockup detector generate panics.
 
 
@@ -2519,9 +2381,6 @@ and is between 256 and 4096 characters. It is defined in the file
 	spia_pedr=
 	spia_pedr=
 	spia_peddr=
 	spia_peddr=
 
 
-	sscape=		[HW,OSS]
-			Format: <io>,<irq>,<dma>,<mpu_io>,<mpu_irq>
-
 	st=		[HW,SCSI] SCSI tape parameters (buffers, etc.)
 	st=		[HW,SCSI] SCSI tape parameters (buffers, etc.)
 			See Documentation/scsi/st.txt.
 			See Documentation/scsi/st.txt.
 
 
@@ -2661,10 +2520,6 @@ and is between 256 and 4096 characters. It is defined in the file
 			to facilitate early boot debugging.
 			to facilitate early boot debugging.
 			See also Documentation/trace/events.txt
 			See also Documentation/trace/events.txt
 
 
-	trix=		[HW,OSS] MediaTrix AudioTrix Pro
-			Format:
-			<io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq>
-
 	tsc=		Disable clocksource-must-verify flag for TSC.
 	tsc=		Disable clocksource-must-verify flag for TSC.
 			Format: <string>
 			Format: <string>
 			[x86] reliable: mark tsc clocksource as reliable, this
 			[x86] reliable: mark tsc clocksource as reliable, this
@@ -2681,12 +2536,6 @@ and is between 256 and 4096 characters. It is defined in the file
 	u14-34f=	[HW,SCSI] UltraStor 14F/34F SCSI host adapter
 	u14-34f=	[HW,SCSI] UltraStor 14F/34F SCSI host adapter
 			See header of drivers/scsi/u14-34f.c.
 			See header of drivers/scsi/u14-34f.c.
 
 
-	uart401=	[HW,OSS]
-			Format: <io>,<irq>
-
-	uart6850=	[HW,OSS]
-			Format: <io>,<irq>
-
 	uhash_entries=	[KNL,NET]
 	uhash_entries=	[KNL,NET]
 			Set number of hash buckets for UDP/UDP-Lite connections
 			Set number of hash buckets for UDP/UDP-Lite connections
 
 
@@ -2852,9 +2701,6 @@ and is between 256 and 4096 characters. It is defined in the file
 			overridden by individual drivers. 0 will hide
 			overridden by individual drivers. 0 will hide
 			cursors, 1 will display them.
 			cursors, 1 will display them.
 
 
-	waveartist=	[HW,OSS]
-			Format: <io>,<irq>,<dma>,<dma2>
-
 	wd33c93=	[HW,SCSI]
 	wd33c93=	[HW,SCSI]
 			See header of drivers/scsi/wd33c93.c.
 			See header of drivers/scsi/wd33c93.c.
 
 
@@ -2887,5 +2733,4 @@ ______________________________________________________________________
 
 
 TODO:
 TODO:
 
 
-	Add documentation for ALSA options.
 	Add more DRM drivers.
 	Add more DRM drivers.

+ 8 - 0
Documentation/sound/alsa/Procfile.txt

@@ -103,6 +103,8 @@ card*/pcm*/xrun_debug
 	  bit 2 = Enable additional jiffies check
 	  bit 2 = Enable additional jiffies check
 	  bit 3 = Log hwptr update at each period interrupt
 	  bit 3 = Log hwptr update at each period interrupt
 	  bit 4 = Log hwptr update at each snd_pcm_update_hw_ptr()
 	  bit 4 = Log hwptr update at each snd_pcm_update_hw_ptr()
+	  bit 5 = Show last 10 positions on error
+	  bit 6 = Do above only once
 
 
 	When the bit 0 is set, the driver will show the messages to
 	When the bit 0 is set, the driver will show the messages to
 	kernel log when an xrun is detected.  The debug message is
 	kernel log when an xrun is detected.  The debug message is
@@ -122,6 +124,12 @@ card*/pcm*/xrun_debug
 	Bits 3 and 4 are for logging the hwptr records.  Note that
 	Bits 3 and 4 are for logging the hwptr records.  Note that
 	these will give flood of kernel messages.
 	these will give flood of kernel messages.
 
 
+	When bit 5 is set, the driver logs the last 10 xrun errors and
+	the proc file shows each jiffies, position, period_size,
+	buffer_size, old_hw_ptr, and hw_ptr_base values.
+
+	When bit 6 is set, the full xrun log is shown only once.
+
 card*/pcm*/sub*/info
 card*/pcm*/sub*/info
 	The general information of this PCM sub-stream.
 	The general information of this PCM sub-stream.
 
 

+ 135 - 0
Documentation/sound/alsa/alsa-parameters.txt

@@ -0,0 +1,135 @@
+                          ALSA Kernel Parameters
+                          ~~~~~~~~~~~~~~~~~~~~~~
+
+See Documentation/kernel-parameters.txt for general information on
+specifying module parameters.
+
+This document may not be entirely up to date and comprehensive. The command
+"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
+module. Loadable modules, after being loaded into the running kernel, also
+reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
+parameters may be changed at runtime by the command
+"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}".
+
+
+	snd-ad1816a=	[HW,ALSA]
+
+	snd-ad1848=	[HW,ALSA]
+
+	snd-ali5451=	[HW,ALSA]
+
+	snd-als100=	[HW,ALSA]
+
+	snd-als4000=	[HW,ALSA]
+
+	snd-azt2320=	[HW,ALSA]
+
+	snd-cmi8330=	[HW,ALSA]
+
+	snd-cmipci=	[HW,ALSA]
+
+	snd-cs4231=	[HW,ALSA]
+
+	snd-cs4232=	[HW,ALSA]
+
+	snd-cs4236=	[HW,ALSA]
+
+	snd-cs4281=	[HW,ALSA]
+
+	snd-cs46xx=	[HW,ALSA]
+
+	snd-dt019x=	[HW,ALSA]
+
+	snd-dummy=	[HW,ALSA]
+
+	snd-emu10k1=	[HW,ALSA]
+
+	snd-ens1370=	[HW,ALSA]
+
+	snd-ens1371=	[HW,ALSA]
+
+	snd-es968=	[HW,ALSA]
+
+	snd-es1688=	[HW,ALSA]
+
+	snd-es18xx=	[HW,ALSA]
+
+	snd-es1938=	[HW,ALSA]
+
+	snd-es1968=	[HW,ALSA]
+
+	snd-fm801=	[HW,ALSA]
+
+	snd-gusclassic=	[HW,ALSA]
+
+	snd-gusextreme=	[HW,ALSA]
+
+	snd-gusmax=	[HW,ALSA]
+
+	snd-hdsp=	[HW,ALSA]
+
+	snd-ice1712=	[HW,ALSA]
+
+	snd-intel8x0=	[HW,ALSA]
+
+	snd-interwave=	[HW,ALSA]
+
+	snd-interwave-stb=
+			[HW,ALSA]
+
+	snd-korg1212=	[HW,ALSA]
+
+	snd-maestro3=	[HW,ALSA]
+
+	snd-mpu401=	[HW,ALSA]
+
+	snd-mtpav=	[HW,ALSA]
+
+	snd-nm256=	[HW,ALSA]
+
+	snd-opl3sa2=	[HW,ALSA]
+
+	snd-opti92x-ad1848=
+			[HW,ALSA]
+
+	snd-opti92x-cs4231=
+			[HW,ALSA]
+
+	snd-opti93x=	[HW,ALSA]
+
+	snd-pmac=	[HW,ALSA]
+
+	snd-rme32=	[HW,ALSA]
+
+	snd-rme96=	[HW,ALSA]
+
+	snd-rme9652=	[HW,ALSA]
+
+	snd-sb8=	[HW,ALSA]
+
+	snd-sb16=	[HW,ALSA]
+
+	snd-sbawe=	[HW,ALSA]
+
+	snd-serial=	[HW,ALSA]
+
+	snd-sgalaxy=	[HW,ALSA]
+
+	snd-sonicvibes=	[HW,ALSA]
+
+	snd-sun-amd7930=
+			[HW,ALSA]
+
+	snd-sun-cs4231=	[HW,ALSA]
+
+	snd-trident=	[HW,ALSA]
+
+	snd-usb-audio=	[HW,ALSA,USB]
+
+	snd-via82xx=	[HW,ALSA]
+
+	snd-virmidi=	[HW,ALSA]
+
+	snd-wavefront=	[HW,ALSA]
+
+	snd-ymfpci=	[HW,ALSA]

+ 51 - 0
Documentation/sound/oss/oss-parameters.txt

@@ -0,0 +1,51 @@
+                          OSS Kernel Parameters
+                          ~~~~~~~~~~~~~~~~~~~~~
+
+See Documentation/kernel-parameters.txt for general information on
+specifying module parameters.
+
+This document may not be entirely up to date and comprehensive. The command
+"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
+module. Loadable modules, after being loaded into the running kernel, also
+reveal their parameters in /sys/module/${modulename}/parameters/. Some of these
+parameters may be changed at runtime by the command
+"echo -n ${value} > /sys/module/${modulename}/parameters/${parm}".
+
+
+	ad1848=		[HW,OSS]
+			Format: <io>,<irq>,<dma>,<dma2>,<type>
+
+	aedsp16=	[HW,OSS] Audio Excel DSP 16
+			Format: <io>,<irq>,<dma>,<mss_io>,<mpu_io>,<mpu_irq>
+			See also header of sound/oss/aedsp16.c.
+
+	dmasound=	[HW,OSS] Sound subsystem buffers
+
+	mpu401=		[HW,OSS]
+			Format: <io>,<irq>
+
+	opl3=		[HW,OSS]
+			Format: <io>
+
+	pas2=		[HW,OSS] Format:
+			<io>,<irq>,<dma>,<dma16>,<sb_io>,<sb_irq>,<sb_dma>,<sb_dma16>
+
+	pss=		[HW,OSS] Personal Sound System (ECHO ESC614)
+			Format:
+			<io>,<mss_io>,<mss_irq>,<mss_dma>,<mpu_io>,<mpu_irq>
+
+	sscape=		[HW,OSS]
+			Format: <io>,<irq>,<dma>,<mpu_io>,<mpu_irq>
+
+	trix=		[HW,OSS] MediaTrix AudioTrix Pro
+			Format:
+			<io>,<irq>,<dma>,<dma2>,<sb_io>,<sb_irq>,<sb_dma>,<mpu_io>,<mpu_irq>
+
+	uart401=	[HW,OSS]
+			Format: <io>,<irq>
+
+	uart6850=	[HW,OSS]
+			Format: <io>,<irq>
+
+	waveartist=	[HW,OSS]
+			Format: <io>,<irq>,<dma>,<dma2>

+ 6 - 0
arch/um/drivers/hostaudio_kern.c

@@ -8,6 +8,7 @@
 #include "linux/slab.h"
 #include "linux/slab.h"
 #include "linux/sound.h"
 #include "linux/sound.h"
 #include "linux/soundcard.h"
 #include "linux/soundcard.h"
+#include "linux/smp_lock.h"
 #include "asm/uaccess.h"
 #include "asm/uaccess.h"
 #include "init.h"
 #include "init.h"
 #include "os.h"
 #include "os.h"
@@ -198,7 +199,10 @@ static int hostaudio_open(struct inode *inode, struct file *file)
 	if (file->f_mode & FMODE_WRITE)
 	if (file->f_mode & FMODE_WRITE)
 		w = 1;
 		w = 1;
 
 
+	lock_kernel();
 	ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
 	ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
+	unlock_kernel();
+
 	if (ret < 0) {
 	if (ret < 0) {
 		kfree(state);
 		kfree(state);
 		return ret;
 		return ret;
@@ -254,7 +258,9 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
 	if (file->f_mode & FMODE_WRITE)
 	if (file->f_mode & FMODE_WRITE)
 		w = 1;
 		w = 1;
 
 
+	lock_kernel();
 	ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
 	ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
+	unlock_kernel();
 
 
 	if (ret < 0) {
 	if (ret < 0) {
 		printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', "
 		printk(KERN_ERR "hostaudio_open_mixdev failed to open '%s', "

+ 3 - 3
drivers/usb/gadget/f_audio.c

@@ -61,7 +61,7 @@ DECLARE_UAC_AC_HEADER_DESCRIPTOR(2);
 #define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH + UAC_DT_INPUT_TERMINAL_SIZE \
 #define UAC_DT_TOTAL_LENGTH (UAC_DT_AC_HEADER_LENGTH + UAC_DT_INPUT_TERMINAL_SIZE \
 	+ UAC_DT_OUTPUT_TERMINAL_SIZE + UAC_DT_FEATURE_UNIT_SIZE(0))
 	+ UAC_DT_OUTPUT_TERMINAL_SIZE + UAC_DT_FEATURE_UNIT_SIZE(0))
 /* B.3.2  Class-Specific AC Interface Descriptor */
 /* B.3.2  Class-Specific AC Interface Descriptor */
-static struct uac_ac_header_descriptor_v1_2 ac_header_desc = {
+static struct uac1_ac_header_descriptor_2 ac_header_desc = {
 	.bLength =		UAC_DT_AC_HEADER_LENGTH,
 	.bLength =		UAC_DT_AC_HEADER_LENGTH,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubtype =	UAC_HEADER,
 	.bDescriptorSubtype =	UAC_HEADER,
@@ -125,7 +125,7 @@ static struct usb_audio_control_selector feature_unit = {
 };
 };
 
 
 #define OUTPUT_TERMINAL_ID	3
 #define OUTPUT_TERMINAL_ID	3
-static struct uac_output_terminal_descriptor_v1 output_terminal_desc = {
+static struct uac1_output_terminal_descriptor output_terminal_desc = {
 	.bLength		= UAC_DT_OUTPUT_TERMINAL_SIZE,
 	.bLength		= UAC_DT_OUTPUT_TERMINAL_SIZE,
 	.bDescriptorType	= USB_DT_CS_INTERFACE,
 	.bDescriptorType	= USB_DT_CS_INTERFACE,
 	.bDescriptorSubtype	= UAC_OUTPUT_TERMINAL,
 	.bDescriptorSubtype	= UAC_OUTPUT_TERMINAL,
@@ -155,7 +155,7 @@ static struct usb_interface_descriptor as_interface_alt_1_desc = {
 };
 };
 
 
 /* B.4.2  Class-Specific AS Interface Descriptor */
 /* B.4.2  Class-Specific AS Interface Descriptor */
-static struct uac_as_header_descriptor_v1 as_header_desc = {
+static struct uac1_as_header_descriptor as_header_desc = {
 	.bLength =		UAC_DT_AS_HEADER_SIZE,
 	.bLength =		UAC_DT_AS_HEADER_SIZE,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubtype =	UAC_AS_GENERAL,
 	.bDescriptorSubtype =	UAC_AS_GENERAL,

+ 1 - 1
drivers/usb/gadget/gmidi.c

@@ -238,7 +238,7 @@ static const struct usb_interface_descriptor ac_interface_desc = {
 };
 };
 
 
 /* B.3.2  Class-Specific AC Interface Descriptor */
 /* B.3.2  Class-Specific AC Interface Descriptor */
-static const struct uac_ac_header_descriptor_v1_1 ac_header_desc = {
+static const struct uac1_ac_header_descriptor_1 ac_header_desc = {
 	.bLength =		UAC_DT_AC_HEADER_SIZE(1),
 	.bLength =		UAC_DT_AC_HEADER_SIZE(1),
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorType =	USB_DT_CS_INTERFACE,
 	.bDescriptorSubtype =	USB_MS_HEADER,
 	.bDescriptorSubtype =	USB_MS_HEADER,

+ 16 - 1
include/linux/usb/audio-v2.h

@@ -18,6 +18,21 @@
 /* v1.0 and v2.0 of this standard have many things in common. For the rest
 /* v1.0 and v2.0 of this standard have many things in common. For the rest
  * of the definitions, please refer to audio.h */
  * of the definitions, please refer to audio.h */
 
 
+/*
+ * bmControl field decoders
+ *
+ * From the USB Audio spec v2.0:
+ *
+ *   bmaControls() is a (ch+1)-element array of 4-byte bitmaps,
+ *   each containing a set of bit pairs. If a Control is present,
+ *   it must be Host readable. If a certain Control is not
+ *   present then the bit pair must be set to 0b00.
+ *   If a Control is present but read-only, the bit pair must be
+ *   set to 0b01. If a Control is also Host programmable, the bit
+ *   pair must be set to 0b11. The value 0b10 is not allowed.
+ *
+ */
+
 static inline bool uac2_control_is_readable(u32 bmControls, u8 control)
 static inline bool uac2_control_is_readable(u32 bmControls, u8 control)
 {
 {
 	return (bmControls >> (control * 2)) & 0x1;
 	return (bmControls >> (control * 2)) & 0x1;
@@ -121,7 +136,7 @@ struct uac2_feature_unit_descriptor {
 
 
 /* 4.9.2 Class-Specific AS Interface Descriptor */
 /* 4.9.2 Class-Specific AS Interface Descriptor */
 
 
-struct uac_as_header_descriptor_v2 {
+struct uac2_as_header_descriptor {
 	__u8 bLength;
 	__u8 bLength;
 	__u8 bDescriptorType;
 	__u8 bDescriptorType;
 	__u8 bDescriptorSubtype;
 	__u8 bDescriptorSubtype;

+ 6 - 6
include/linux/usb/audio.h

@@ -39,8 +39,8 @@
 #define UAC_MIXER_UNIT			0x04
 #define UAC_MIXER_UNIT			0x04
 #define UAC_SELECTOR_UNIT		0x05
 #define UAC_SELECTOR_UNIT		0x05
 #define UAC_FEATURE_UNIT		0x06
 #define UAC_FEATURE_UNIT		0x06
-#define UAC_PROCESSING_UNIT_V1		0x07
-#define UAC_EXTENSION_UNIT_V1		0x08
+#define UAC1_PROCESSING_UNIT		0x07
+#define UAC1_EXTENSION_UNIT		0x08
 
 
 /* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */
 /* A.6 Audio Class-Specific AS Interface Descriptor Subtypes */
 #define UAC_AS_GENERAL			0x01
 #define UAC_AS_GENERAL			0x01
@@ -151,7 +151,7 @@
 
 
 /* Terminal Control Selectors */
 /* Terminal Control Selectors */
 /* 4.3.2  Class-Specific AC Interface Descriptor */
 /* 4.3.2  Class-Specific AC Interface Descriptor */
-struct uac_ac_header_descriptor_v1 {
+struct uac1_ac_header_descriptor {
 	__u8  bLength;			/* 8 + n */
 	__u8  bLength;			/* 8 + n */
 	__u8  bDescriptorType;		/* USB_DT_CS_INTERFACE */
 	__u8  bDescriptorType;		/* USB_DT_CS_INTERFACE */
 	__u8  bDescriptorSubtype;	/* UAC_MS_HEADER */
 	__u8  bDescriptorSubtype;	/* UAC_MS_HEADER */
@@ -165,7 +165,7 @@ struct uac_ac_header_descriptor_v1 {
 
 
 /* As above, but more useful for defining your own descriptors: */
 /* As above, but more useful for defining your own descriptors: */
 #define DECLARE_UAC_AC_HEADER_DESCRIPTOR(n)			\
 #define DECLARE_UAC_AC_HEADER_DESCRIPTOR(n)			\
-struct uac_ac_header_descriptor_v1_##n {			\
+struct uac1_ac_header_descriptor_##n {			\
 	__u8  bLength;						\
 	__u8  bLength;						\
 	__u8  bDescriptorType;					\
 	__u8  bDescriptorType;					\
 	__u8  bDescriptorSubtype;				\
 	__u8  bDescriptorSubtype;				\
@@ -205,7 +205,7 @@ struct uac_input_terminal_descriptor {
 #define UAC_TERMINAL_CS_COPY_PROTECT_CONTROL		0x01
 #define UAC_TERMINAL_CS_COPY_PROTECT_CONTROL		0x01
 
 
 /* 4.3.2.2 Output Terminal Descriptor */
 /* 4.3.2.2 Output Terminal Descriptor */
-struct uac_output_terminal_descriptor_v1 {
+struct uac1_output_terminal_descriptor {
 	__u8  bLength;			/* in bytes: 9 */
 	__u8  bLength;			/* in bytes: 9 */
 	__u8  bDescriptorType;		/* CS_INTERFACE descriptor type */
 	__u8  bDescriptorType;		/* CS_INTERFACE descriptor type */
 	__u8  bDescriptorSubtype;	/* OUTPUT_TERMINAL descriptor subtype */
 	__u8  bDescriptorSubtype;	/* OUTPUT_TERMINAL descriptor subtype */
@@ -395,7 +395,7 @@ static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_desc
 }
 }
 
 
 /* 4.5.2 Class-Specific AS Interface Descriptor */
 /* 4.5.2 Class-Specific AS Interface Descriptor */
-struct uac_as_header_descriptor_v1 {
+struct uac1_as_header_descriptor {
 	__u8  bLength;			/* in bytes: 7 */
 	__u8  bLength;			/* in bytes: 7 */
 	__u8  bDescriptorType;		/* USB_DT_CS_INTERFACE */
 	__u8  bDescriptorType;		/* USB_DT_CS_INTERFACE */
 	__u8  bDescriptorSubtype;	/* AS_GENERAL */
 	__u8  bDescriptorSubtype;	/* AS_GENERAL */

+ 5 - 1
include/sound/asound.h

@@ -212,7 +212,11 @@ typedef int __bitwise snd_pcm_format_t;
 #define	SNDRV_PCM_FORMAT_S18_3BE	((__force snd_pcm_format_t) 41)	/* in three bytes */
 #define	SNDRV_PCM_FORMAT_S18_3BE	((__force snd_pcm_format_t) 41)	/* in three bytes */
 #define	SNDRV_PCM_FORMAT_U18_3LE	((__force snd_pcm_format_t) 42)	/* in three bytes */
 #define	SNDRV_PCM_FORMAT_U18_3LE	((__force snd_pcm_format_t) 42)	/* in three bytes */
 #define	SNDRV_PCM_FORMAT_U18_3BE	((__force snd_pcm_format_t) 43)	/* in three bytes */
 #define	SNDRV_PCM_FORMAT_U18_3BE	((__force snd_pcm_format_t) 43)	/* in three bytes */
-#define	SNDRV_PCM_FORMAT_LAST		SNDRV_PCM_FORMAT_U18_3BE
+#define	SNDRV_PCM_FORMAT_G723_24	((__force snd_pcm_format_t) 44) /* 8 samples in 3 bytes */
+#define	SNDRV_PCM_FORMAT_G723_24_1B	((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */
+#define	SNDRV_PCM_FORMAT_G723_40	((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */
+#define	SNDRV_PCM_FORMAT_G723_40_1B	((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */
+#define	SNDRV_PCM_FORMAT_LAST		SNDRV_PCM_FORMAT_G723_40_1B
 
 
 #ifdef SNDRV_LITTLE_ENDIAN
 #ifdef SNDRV_LITTLE_ENDIAN
 #define	SNDRV_PCM_FORMAT_S16		SNDRV_PCM_FORMAT_S16_LE
 #define	SNDRV_PCM_FORMAT_S16		SNDRV_PCM_FORMAT_S16_LE

+ 5 - 1
include/sound/pcm.h

@@ -174,6 +174,10 @@ struct snd_pcm_ops {
 #define SNDRV_PCM_FMTBIT_U18_3LE	(1ULL << SNDRV_PCM_FORMAT_U18_3LE)
 #define SNDRV_PCM_FMTBIT_U18_3LE	(1ULL << SNDRV_PCM_FORMAT_U18_3LE)
 #define SNDRV_PCM_FMTBIT_S18_3BE	(1ULL << SNDRV_PCM_FORMAT_S18_3BE)
 #define SNDRV_PCM_FMTBIT_S18_3BE	(1ULL << SNDRV_PCM_FORMAT_S18_3BE)
 #define SNDRV_PCM_FMTBIT_U18_3BE	(1ULL << SNDRV_PCM_FORMAT_U18_3BE)
 #define SNDRV_PCM_FMTBIT_U18_3BE	(1ULL << SNDRV_PCM_FORMAT_U18_3BE)
+#define SNDRV_PCM_FMTBIT_G723_24	(1ULL << SNDRV_PCM_FORMAT_G723_24)
+#define SNDRV_PCM_FMTBIT_G723_24_1B	(1ULL << SNDRV_PCM_FORMAT_G723_24_1B)
+#define SNDRV_PCM_FMTBIT_G723_40	(1ULL << SNDRV_PCM_FORMAT_G723_40)
+#define SNDRV_PCM_FMTBIT_G723_40_1B	(1ULL << SNDRV_PCM_FORMAT_G723_40_1B)
 
 
 #ifdef SNDRV_LITTLE_ENDIAN
 #ifdef SNDRV_LITTLE_ENDIAN
 #define SNDRV_PCM_FMTBIT_S16		SNDRV_PCM_FMTBIT_S16_LE
 #define SNDRV_PCM_FMTBIT_S16		SNDRV_PCM_FMTBIT_S16_LE
@@ -313,7 +317,7 @@ struct snd_pcm_runtime {
 	struct snd_pcm_mmap_control *control;
 	struct snd_pcm_mmap_control *control;
 
 
 	/* -- locking / scheduling -- */
 	/* -- locking / scheduling -- */
-	unsigned int twake: 1;		/* do transfer (!poll) wakeup */
+	snd_pcm_uframes_t twake; 	/* do transfer (!poll) wakeup if non-zero */
 	wait_queue_head_t sleep;	/* poll sleep */
 	wait_queue_head_t sleep;	/* poll sleep */
 	wait_queue_head_t tsleep;	/* transfer sleep */
 	wait_queue_head_t tsleep;	/* transfer sleep */
 	struct fasync_struct *fasync;
 	struct fasync_struct *fasync;

+ 17 - 8
sound/core/pcm_lib.c

@@ -67,6 +67,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream *substream, snd_pcm_ufram
 	} else {
 	} else {
 		if (new_hw_ptr == ULONG_MAX) {	/* initialization */
 		if (new_hw_ptr == ULONG_MAX) {	/* initialization */
 			snd_pcm_sframes_t avail = snd_pcm_playback_hw_avail(runtime);
 			snd_pcm_sframes_t avail = snd_pcm_playback_hw_avail(runtime);
+			if (avail > runtime->buffer_size)
+				avail = runtime->buffer_size;
 			runtime->silence_filled = avail > 0 ? avail : 0;
 			runtime->silence_filled = avail > 0 ? avail : 0;
 			runtime->silence_start = (runtime->status->hw_ptr +
 			runtime->silence_start = (runtime->status->hw_ptr +
 						  runtime->silence_filled) %
 						  runtime->silence_filled) %
@@ -287,8 +289,11 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
 			return -EPIPE;
 			return -EPIPE;
 		}
 		}
 	}
 	}
-	if (avail >= runtime->control->avail_min)
-		wake_up(runtime->twake ? &runtime->tsleep : &runtime->sleep);
+	if (runtime->twake) {
+		if (avail >= runtime->twake)
+			wake_up(&runtime->tsleep);
+	} else if (avail >= runtime->control->avail_min)
+		wake_up(&runtime->sleep);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1707,7 +1712,7 @@ EXPORT_SYMBOL(snd_pcm_period_elapsed);
  * The available space is stored on availp.  When err = 0 and avail = 0
  * The available space is stored on availp.  When err = 0 and avail = 0
  * on the capture stream, it indicates the stream is in DRAINING state.
  * on the capture stream, it indicates the stream is in DRAINING state.
  */
  */
-static int wait_for_avail_min(struct snd_pcm_substream *substream,
+static int wait_for_avail(struct snd_pcm_substream *substream,
 			      snd_pcm_uframes_t *availp)
 			      snd_pcm_uframes_t *availp)
 {
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1757,7 +1762,7 @@ static int wait_for_avail_min(struct snd_pcm_substream *substream,
 			avail = snd_pcm_playback_avail(runtime);
 			avail = snd_pcm_playback_avail(runtime);
 		else
 		else
 			avail = snd_pcm_capture_avail(runtime);
 			avail = snd_pcm_capture_avail(runtime);
-		if (avail >= runtime->control->avail_min)
+		if (avail >= runtime->twake)
 			break;
 			break;
 	}
 	}
  _endloop:
  _endloop:
@@ -1820,7 +1825,7 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
 		goto _end_unlock;
 		goto _end_unlock;
 	}
 	}
 
 
-	runtime->twake = 1;
+	runtime->twake = runtime->control->avail_min ? : 1;
 	while (size > 0) {
 	while (size > 0) {
 		snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
 		snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
 		snd_pcm_uframes_t avail;
 		snd_pcm_uframes_t avail;
@@ -1833,7 +1838,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream *substream,
 				err = -EAGAIN;
 				err = -EAGAIN;
 				goto _end_unlock;
 				goto _end_unlock;
 			}
 			}
-			err = wait_for_avail_min(substream, &avail);
+			runtime->twake = min_t(snd_pcm_uframes_t, size,
+					runtime->control->avail_min ? : 1);
+			err = wait_for_avail(substream, &avail);
 			if (err < 0)
 			if (err < 0)
 				goto _end_unlock;
 				goto _end_unlock;
 		}
 		}
@@ -2042,7 +2049,7 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
 		goto _end_unlock;
 		goto _end_unlock;
 	}
 	}
 
 
-	runtime->twake = 1;
+	runtime->twake = runtime->control->avail_min ? : 1;
 	while (size > 0) {
 	while (size > 0) {
 		snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
 		snd_pcm_uframes_t frames, appl_ptr, appl_ofs;
 		snd_pcm_uframes_t avail;
 		snd_pcm_uframes_t avail;
@@ -2060,7 +2067,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct snd_pcm_substream *substream,
 				err = -EAGAIN;
 				err = -EAGAIN;
 				goto _end_unlock;
 				goto _end_unlock;
 			}
 			}
-			err = wait_for_avail_min(substream, &avail);
+			runtime->twake = min_t(snd_pcm_uframes_t, size,
+					runtime->control->avail_min ? : 1);
+			err = wait_for_avail(substream, &avail);
 			if (err < 0)
 			if (err < 0)
 				goto _end_unlock;
 				goto _end_unlock;
 			if (!avail)
 			if (!avail)

+ 16 - 0
sound/core/pcm_misc.c

@@ -128,6 +128,14 @@ static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
 		.width = 4, .phys = 4, .le = -1, .signd = -1,
 		.width = 4, .phys = 4, .le = -1, .signd = -1,
 		.silence = {},
 		.silence = {},
 	},
 	},
+	[SNDRV_PCM_FORMAT_G723_24] = {
+		.width = 3, .phys = 3, .le = -1, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_G723_40] = {
+		.width = 5, .phys = 5, .le = -1, .signd = -1,
+		.silence = {},
+	},
 	/* FIXME: the following three formats are not defined properly yet */
 	/* FIXME: the following three formats are not defined properly yet */
 	[SNDRV_PCM_FORMAT_MPEG] = {
 	[SNDRV_PCM_FORMAT_MPEG] = {
 		.le = -1, .signd = -1,
 		.le = -1, .signd = -1,
@@ -186,6 +194,14 @@ static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
 		.width = 18, .phys = 24, .le = 0, .signd = 0,
 		.width = 18, .phys = 24, .le = 0, .signd = 0,
 		.silence = { 0x02, 0x00, 0x00 },
 		.silence = { 0x02, 0x00, 0x00 },
 	},
 	},
+	[SNDRV_PCM_FORMAT_G723_24_1B] = {
+		.width = 3, .phys = 8, .le = -1, .signd = -1,
+		.silence = {},
+	},
+	[SNDRV_PCM_FORMAT_G723_40_1B] = {
+		.width = 5, .phys = 8, .le = -1, .signd = -1,
+		.silence = {},
+	},
 };
 };
 
 
 
 

+ 21 - 3
sound/drivers/Kconfig

@@ -170,9 +170,25 @@ config SND_AC97_POWER_SAVE
 	  AC97 codecs.  In this mode, the power-mode is dynamically
 	  AC97 codecs.  In this mode, the power-mode is dynamically
 	  controlled at each open/close.
 	  controlled at each open/close.
 
 
-	  The mode is activated by passing power_save=1 option to
-	  snd-ac97-codec driver.  You can toggle it dynamically over
-	  sysfs, too.
+	  The mode is activated by passing 'power_save=X' to the
+	  snd-ac97-codec driver module, where 'X' is the time-out
+	  value, a nonnegative integer that specifies how many
+	  seconds of idle time the driver must count before it may
+	  put the AC97 into power-save mode;  a value of 0 (zero)
+	  disables the use of this power-save mode.
+
+	  After the snd-ac97-codec driver module has been loaded,
+	  the 'power_save' parameter can be set via sysfs as follows:
+
+	    echo 10 > /sys/module/snd_ac97_codec/parameters/power_save
+
+	  In this case, the time-out is set to 10 seconds; setting
+	  the time-out to 1 second (the minimum activation value)
+	  isn't recommended because many applications try to reopen
+	  the device frequently.  A value of 10 seconds would be a
+	  good choice for normal operations.
+
+	  See Documentation/sound/alsa/powersave.txt for more details.
 
 
 config SND_AC97_POWER_SAVE_DEFAULT
 config SND_AC97_POWER_SAVE_DEFAULT
 	int "Default time-out for AC97 power-save mode"
 	int "Default time-out for AC97 power-save mode"
@@ -182,4 +198,6 @@ config SND_AC97_POWER_SAVE_DEFAULT
 	  The default time-out value in seconds for AC97 automatic
 	  The default time-out value in seconds for AC97 automatic
 	  power-save mode.  0 means to disable the power-save mode.
 	  power-save mode.  0 means to disable the power-save mode.
 
 
+	  See SND_AC97_POWER_SAVE for more details.
+
 endif	# SND_DRIVERS
 endif	# SND_DRIVERS

+ 4 - 1
sound/isa/msnd/msnd_pinnacle.c

@@ -549,7 +549,10 @@ static int __devinit snd_msnd_attach(struct snd_card *card)
 		printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq);
 		printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq);
 		return err;
 		return err;
 	}
 	}
-	request_region(chip->io, DSP_NUMIO, card->shortname);
+	if (request_region(chip->io, DSP_NUMIO, card->shortname) == NULL) {
+		free_irq(chip->irq, chip);
+		return -EBUSY;
+	}
 
 
 	if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) {
 	if (!request_mem_region(chip->base, BUFFSIZE, card->shortname)) {
 		printk(KERN_ERR LOGNAME
 		printk(KERN_ERR LOGNAME

+ 6 - 3
sound/isa/sb/emu8000_pcm.c

@@ -433,7 +433,8 @@ static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned sh
 	while (count > 0) {
 	while (count > 0) {
 		unsigned short sval;
 		unsigned short sval;
 		CHECK_SCHEDULER();
 		CHECK_SCHEDULER();
-		get_user(sval, buf);
+		if (get_user(sval, buf))
+			return -EFAULT;
 		EMU8000_SMLD_WRITE(emu, sval);
 		EMU8000_SMLD_WRITE(emu, sval);
 		buf++;
 		buf++;
 		count--;
 		count--;
@@ -525,12 +526,14 @@ static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
 	while (count-- > 0) {
 	while (count-- > 0) {
 		unsigned short sval;
 		unsigned short sval;
 		CHECK_SCHEDULER();
 		CHECK_SCHEDULER();
-		get_user(sval, buf);
+		if (get_user(sval, buf))
+			return -EFAULT;
 		EMU8000_SMLD_WRITE(emu, sval);
 		EMU8000_SMLD_WRITE(emu, sval);
 		buf++;
 		buf++;
 		if (rec->voices > 1) {
 		if (rec->voices > 1) {
 			CHECK_SCHEDULER();
 			CHECK_SCHEDULER();
-			get_user(sval, buf);
+			if (get_user(sval, buf))
+				return -EFAULT;
 			EMU8000_SMRD_WRITE(emu, sval);
 			EMU8000_SMRD_WRITE(emu, sval);
 			buf++;
 			buf++;
 		}
 		}

+ 52 - 39
sound/oss/au1550_ac97.c

@@ -43,6 +43,7 @@
 #include <linux/sound.h>
 #include <linux/sound.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/soundcard.h>
+#include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/kernel.h>
@@ -162,19 +163,10 @@ ld2(unsigned int x)
 static void
 static void
 au1550_delay(int msec)
 au1550_delay(int msec)
 {
 {
-	unsigned long   tmo;
-	signed long     tmo2;
-
 	if (in_interrupt())
 	if (in_interrupt())
 		return;
 		return;
 
 
-	tmo = jiffies + (msec * HZ) / 1000;
-	for (;;) {
-		tmo2 = tmo - jiffies;
-		if (tmo2 <= 0)
-			break;
-		schedule_timeout(tmo2);
-	}
+	schedule_timeout_uninterruptible(msecs_to_jiffies(msec));
 }
 }
 
 
 static u16
 static u16
@@ -807,7 +799,9 @@ au1550_llseek(struct file *file, loff_t offset, int origin)
 static int
 static int
 au1550_open_mixdev(struct inode *inode, struct file *file)
 au1550_open_mixdev(struct inode *inode, struct file *file)
 {
 {
+	lock_kernel();
 	file->private_data = &au1550_state;
 	file->private_data = &au1550_state;
+	unlock_kernel();
 	return 0;
 	return 0;
 }
 }
 
 
@@ -824,22 +818,26 @@ mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd,
 	return codec->mixer_ioctl(codec, cmd, arg);
 	return codec->mixer_ioctl(codec, cmd, arg);
 }
 }
 
 
-static int
-au1550_ioctl_mixdev(struct inode *inode, struct file *file,
-			       unsigned int cmd, unsigned long arg)
+static long
+au1550_ioctl_mixdev(struct file *file, unsigned int cmd, unsigned long arg)
 {
 {
 	struct au1550_state *s = (struct au1550_state *)file->private_data;
 	struct au1550_state *s = (struct au1550_state *)file->private_data;
 	struct ac97_codec *codec = s->codec;
 	struct ac97_codec *codec = s->codec;
+	int ret;
 
 
-	return mixdev_ioctl(codec, cmd, arg);
+	lock_kernel();
+	ret = mixdev_ioctl(codec, cmd, arg);
+	unlock_kernel();
+
+	return ret;
 }
 }
 
 
 static /*const */ struct file_operations au1550_mixer_fops = {
 static /*const */ struct file_operations au1550_mixer_fops = {
-	owner:THIS_MODULE,
-	llseek:au1550_llseek,
-	ioctl:au1550_ioctl_mixdev,
-	open:au1550_open_mixdev,
-	release:au1550_release_mixdev,
+	.owner		= THIS_MODULE,
+	.llseek		= au1550_llseek,
+	.unlocked_ioctl	= au1550_ioctl_mixdev,
+	.open		= au1550_open_mixdev,
+	.release	= au1550_release_mixdev,
 };
 };
 
 
 static int
 static int
@@ -1343,8 +1341,7 @@ dma_count_done(struct dmabuf *db)
 
 
 
 
 static int
 static int
-au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-							unsigned long arg)
+au1550_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 {
 	struct au1550_state *s = (struct au1550_state *)file->private_data;
 	struct au1550_state *s = (struct au1550_state *)file->private_data;
 	unsigned long   flags;
 	unsigned long   flags;
@@ -1780,6 +1777,17 @@ au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	return mixdev_ioctl(s->codec, cmd, arg);
 	return mixdev_ioctl(s->codec, cmd, arg);
 }
 }
 
 
+static long
+au1550_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int ret;
+
+	lock_kernel();
+	ret = au1550_ioctl(file, cmd, arg);
+	unlock_kernel();
+
+	return ret;
+}
 
 
 static int
 static int
 au1550_open(struct inode *inode, struct file *file)
 au1550_open(struct inode *inode, struct file *file)
@@ -1797,21 +1805,22 @@ au1550_open(struct inode *inode, struct file *file)
 #endif
 #endif
 
 
 	file->private_data = s;
 	file->private_data = s;
+	lock_kernel();
 	/* wait for device to become free */
 	/* wait for device to become free */
 	mutex_lock(&s->open_mutex);
 	mutex_lock(&s->open_mutex);
 	while (s->open_mode & file->f_mode) {
 	while (s->open_mode & file->f_mode) {
-		if (file->f_flags & O_NONBLOCK) {
-			mutex_unlock(&s->open_mutex);
-			return -EBUSY;
-		}
+		ret = -EBUSY;
+		if (file->f_flags & O_NONBLOCK)
+			goto out;
 		add_wait_queue(&s->open_wait, &wait);
 		add_wait_queue(&s->open_wait, &wait);
 		__set_current_state(TASK_INTERRUPTIBLE);
 		__set_current_state(TASK_INTERRUPTIBLE);
 		mutex_unlock(&s->open_mutex);
 		mutex_unlock(&s->open_mutex);
 		schedule();
 		schedule();
 		remove_wait_queue(&s->open_wait, &wait);
 		remove_wait_queue(&s->open_wait, &wait);
 		set_current_state(TASK_RUNNING);
 		set_current_state(TASK_RUNNING);
+		ret = -ERESTARTSYS;
 		if (signal_pending(current))
 		if (signal_pending(current))
-			return -ERESTARTSYS;
+			goto out2;
 		mutex_lock(&s->open_mutex);
 		mutex_lock(&s->open_mutex);
 	}
 	}
 
 
@@ -1840,17 +1849,21 @@ au1550_open(struct inode *inode, struct file *file)
 
 
 	if (file->f_mode & FMODE_READ) {
 	if (file->f_mode & FMODE_READ) {
 		if ((ret = prog_dmabuf_adc(s)))
 		if ((ret = prog_dmabuf_adc(s)))
-			return ret;
+			goto out;
 	}
 	}
 	if (file->f_mode & FMODE_WRITE) {
 	if (file->f_mode & FMODE_WRITE) {
 		if ((ret = prog_dmabuf_dac(s)))
 		if ((ret = prog_dmabuf_dac(s)))
-			return ret;
+			goto out;
 	}
 	}
 
 
 	s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
 	s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
-	mutex_unlock(&s->open_mutex);
 	mutex_init(&s->sem);
 	mutex_init(&s->sem);
-	return 0;
+	ret = 0;
+out:
+	mutex_unlock(&s->open_mutex);
+out2:
+	unlock_kernel();
+	return ret;
 }
 }
 
 
 static int
 static int
@@ -1885,15 +1898,15 @@ au1550_release(struct inode *inode, struct file *file)
 }
 }
 
 
 static /*const */ struct file_operations au1550_audio_fops = {
 static /*const */ struct file_operations au1550_audio_fops = {
-	owner:		THIS_MODULE,
-	llseek:		au1550_llseek,
-	read:		au1550_read,
-	write:		au1550_write,
-	poll:		au1550_poll,
-	ioctl:		au1550_ioctl,
-	mmap:		au1550_mmap,
-	open:		au1550_open,
-	release:	au1550_release,
+	.owner		= THIS_MODULE,
+	.llseek		= au1550_llseek,
+	.read		= au1550_read,
+	.write		= au1550_write,
+	.poll		= au1550_poll,
+	.unlocked_ioctl	= au1550_unlocked_ioctl,
+	.mmap		= au1550_mmap,
+	.open		= au1550_open,
+	.release	= au1550_release,
 };
 };
 
 
 MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com");
 MODULE_AUTHOR("Advanced Micro Devices (AMD), dan@embeddededge.com");

+ 50 - 13
sound/oss/dmasound/dmasound_core.c

@@ -323,9 +323,13 @@ static struct {
 
 
 static int mixer_open(struct inode *inode, struct file *file)
 static int mixer_open(struct inode *inode, struct file *file)
 {
 {
-	if (!try_module_get(dmasound.mach.owner))
+	lock_kernel();
+	if (!try_module_get(dmasound.mach.owner)) {
+		unlock_kernel();
 		return -ENODEV;
 		return -ENODEV;
+	}
 	mixer.busy = 1;
 	mixer.busy = 1;
+	unlock_kernel();
 	return 0;
 	return 0;
 }
 }
 
 
@@ -337,8 +341,8 @@ static int mixer_release(struct inode *inode, struct file *file)
 	unlock_kernel();
 	unlock_kernel();
 	return 0;
 	return 0;
 }
 }
-static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		       u_long arg)
+
+static int mixer_ioctl(struct file *file, u_int cmd, u_long arg)
 {
 {
 	if (_SIOC_DIR(cmd) & _SIOC_WRITE)
 	if (_SIOC_DIR(cmd) & _SIOC_WRITE)
 	    mixer.modify_counter++;
 	    mixer.modify_counter++;
@@ -362,11 +366,22 @@ static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
 	return -EINVAL;
 	return -EINVAL;
 }
 }
 
 
+static long mixer_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
+{
+	int ret;
+
+	lock_kernel();
+	ret = mixer_ioctl(file, cmd, arg);
+	unlock_kernel();
+
+	return ret;
+}
+
 static const struct file_operations mixer_fops =
 static const struct file_operations mixer_fops =
 {
 {
 	.owner		= THIS_MODULE,
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.llseek		= no_llseek,
-	.ioctl		= mixer_ioctl,
+	.unlocked_ioctl	= mixer_unlocked_ioctl,
 	.open		= mixer_open,
 	.open		= mixer_open,
 	.release	= mixer_release,
 	.release	= mixer_release,
 };
 };
@@ -737,8 +752,11 @@ static int sq_open(struct inode *inode, struct file *file)
 {
 {
 	int rc;
 	int rc;
 
 
-	if (!try_module_get(dmasound.mach.owner))
+	lock_kernel();
+	if (!try_module_get(dmasound.mach.owner)) {
+		unlock_kernel();
 		return -ENODEV;
 		return -ENODEV;
+	}
 
 
 	rc = write_sq_open(file); /* checks the f_mode */
 	rc = write_sq_open(file); /* checks the f_mode */
 	if (rc)
 	if (rc)
@@ -781,10 +799,11 @@ static int sq_open(struct inode *inode, struct file *file)
 		sound_set_format(AFMT_MU_LAW);
 		sound_set_format(AFMT_MU_LAW);
 	}
 	}
 #endif
 #endif
-
+	unlock_kernel();
 	return 0;
 	return 0;
  out:
  out:
 	module_put(dmasound.mach.owner);
 	module_put(dmasound.mach.owner);
+	unlock_kernel();
 	return rc;
 	return rc;
 }
 }
 
 
@@ -955,8 +974,7 @@ printk("dmasound_core: tried to set_queue_frags on a locked queue\n") ;
 	return 0 ;
 	return 0 ;
 }
 }
 
 
-static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
-		    u_long arg)
+static int sq_ioctl(struct file *file, u_int cmd, u_long arg)
 {
 {
 	int val, result;
 	int val, result;
 	u_long fmt;
 	u_long fmt;
@@ -1114,18 +1132,29 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
 		return IOCTL_OUT(arg,val);
 		return IOCTL_OUT(arg,val);
 
 
 	default:
 	default:
-		return mixer_ioctl(inode, file, cmd, arg);
+		return mixer_ioctl(file, cmd, arg);
 	}
 	}
 	return -EINVAL;
 	return -EINVAL;
 }
 }
 
 
+static long sq_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
+{
+	int ret;
+
+	lock_kernel();
+	ret = sq_ioctl(file, cmd, arg);
+	unlock_kernel();
+
+	return ret;
+}
+
 static const struct file_operations sq_fops =
 static const struct file_operations sq_fops =
 {
 {
 	.owner		= THIS_MODULE,
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.llseek		= no_llseek,
 	.write		= sq_write,
 	.write		= sq_write,
 	.poll		= sq_poll,
 	.poll		= sq_poll,
-	.ioctl		= sq_ioctl,
+	.unlocked_ioctl	= sq_unlocked_ioctl,
 	.open		= sq_open,
 	.open		= sq_open,
 	.release	= sq_release,
 	.release	= sq_release,
 };
 };
@@ -1226,12 +1255,17 @@ static int state_open(struct inode *inode, struct file *file)
 {
 {
 	char *buffer = state.buf;
 	char *buffer = state.buf;
 	int len = 0;
 	int len = 0;
+	int ret;
 
 
+	lock_kernel();
+	ret = -EBUSY;
 	if (state.busy)
 	if (state.busy)
-		return -EBUSY;
+		goto out;
 
 
+	ret = -ENODEV;
 	if (!try_module_get(dmasound.mach.owner))
 	if (!try_module_get(dmasound.mach.owner))
-		return -ENODEV;
+		goto out;
+
 	state.ptr = 0;
 	state.ptr = 0;
 	state.busy = 1;
 	state.busy = 1;
 
 
@@ -1293,7 +1327,10 @@ printk("dmasound: stat buffer used %d bytes\n", len) ;
 		printk(KERN_ERR "dmasound_core: stat buffer overflowed!\n");
 		printk(KERN_ERR "dmasound_core: stat buffer overflowed!\n");
 
 
 	state.len = len;
 	state.len = len;
-	return 0;
+	ret = 0;
+out:
+	unlock_kernel();
+	return ret;
 }
 }
 
 
 static int state_release(struct inode *inode, struct file *file)
 static int state_release(struct inode *inode, struct file *file)

+ 3 - 1
sound/oss/midi_synth.c

@@ -523,7 +523,9 @@ midi_synth_load_patch(int dev, int format, const char __user *addr,
 	{
 	{
 		unsigned char   data;
 		unsigned char   data;
 
 
-		get_user(*(unsigned char *) &data, (unsigned char __user *) &((addr)[hdr_size + i]));
+		if (get_user(data,
+		    (unsigned char __user *)(addr + hdr_size + i)))
+			return -EFAULT;
 
 
 		eox_seen = (i > 0 && data & 0x80);	/* End of sysex */
 		eox_seen = (i > 0 && data & 0x80);	/* End of sysex */
 
 

+ 24 - 11
sound/oss/msnd_pinnacle.c

@@ -639,21 +639,26 @@ static int mixer_ioctl(unsigned int cmd, unsigned long arg)
 	return -EINVAL;
 	return -EINVAL;
 }
 }
 
 
-static int dev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 {
-	int minor = iminor(inode);
+	int minor = iminor(file->f_path.dentry->d_inode);
+	int ret;
 
 
 	if (cmd == OSS_GETVERSION) {
 	if (cmd == OSS_GETVERSION) {
 		int sound_version = SOUND_VERSION;
 		int sound_version = SOUND_VERSION;
 		return put_user(sound_version, (int __user *)arg);
 		return put_user(sound_version, (int __user *)arg);
 	}
 	}
 
 
+	ret = -EINVAL;
+
+	lock_kernel();
 	if (minor == dev.dsp_minor)
 	if (minor == dev.dsp_minor)
-		return dsp_ioctl(file, cmd, arg);
+		ret = dsp_ioctl(file, cmd, arg);
 	else if (minor == dev.mixer_minor)
 	else if (minor == dev.mixer_minor)
-		return mixer_ioctl(cmd, arg);
+		ret = mixer_ioctl(cmd, arg);
+	unlock_kernel();
 
 
-	return -EINVAL;
+	return ret;
 }
 }
 
 
 static void dsp_write_flush(void)
 static void dsp_write_flush(void)
@@ -756,12 +761,15 @@ static int dev_open(struct inode *inode, struct file *file)
 	int minor = iminor(inode);
 	int minor = iminor(inode);
 	int err = 0;
 	int err = 0;
 
 
+	lock_kernel();
 	if (minor == dev.dsp_minor) {
 	if (minor == dev.dsp_minor) {
 		if ((file->f_mode & FMODE_WRITE &&
 		if ((file->f_mode & FMODE_WRITE &&
 		     test_bit(F_AUDIO_WRITE_INUSE, &dev.flags)) ||
 		     test_bit(F_AUDIO_WRITE_INUSE, &dev.flags)) ||
 		    (file->f_mode & FMODE_READ &&
 		    (file->f_mode & FMODE_READ &&
-		     test_bit(F_AUDIO_READ_INUSE, &dev.flags)))
-			return -EBUSY;
+		     test_bit(F_AUDIO_READ_INUSE, &dev.flags))) {
+			err = -EBUSY;
+			goto out;
+		}
 
 
 		if ((err = dsp_open(file)) >= 0) {
 		if ((err = dsp_open(file)) >= 0) {
 			dev.nresets = 0;
 			dev.nresets = 0;
@@ -782,7 +790,8 @@ static int dev_open(struct inode *inode, struct file *file)
 		/* nothing */
 		/* nothing */
 	} else
 	} else
 		err = -EINVAL;
 		err = -EINVAL;
-
+out:
+	unlock_kernel();
 	return err;
 	return err;
 }
 }
 
 
@@ -1105,7 +1114,7 @@ static const struct file_operations dev_fileops = {
 	.owner		= THIS_MODULE,
 	.owner		= THIS_MODULE,
 	.read		= dev_read,
 	.read		= dev_read,
 	.write		= dev_write,
 	.write		= dev_write,
-	.ioctl		= dev_ioctl,
+	.unlocked_ioctl	= dev_ioctl,
 	.open		= dev_open,
 	.open		= dev_open,
 	.release	= dev_release,
 	.release	= dev_release,
 };
 };
@@ -1391,9 +1400,13 @@ static int __init attach_multisound(void)
 		printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", dev.irq);
 		printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", dev.irq);
 		return err;
 		return err;
 	}
 	}
-	request_region(dev.io, dev.numio, dev.name);
+	if (request_region(dev.io, dev.numio, dev.name) == NULL) {
+		free_irq(dev.irq, &dev);
+		return -EBUSY;
+	}
 
 
-        if ((err = dsp_full_reset()) < 0) {
+	err = dsp_full_reset();
+	if (err < 0) {
 		release_region(dev.io, dev.numio);
 		release_region(dev.io, dev.numio);
 		free_irq(dev.irq, &dev);
 		free_irq(dev.irq, &dev);
 		return err;
 		return err;

+ 22 - 5
sound/oss/sh_dac_audio.c

@@ -15,7 +15,9 @@
 #include <linux/linkage.h>
 #include <linux/linkage.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/fs.h>
+#include <linux/smp_lock.h>
 #include <linux/sound.h>
 #include <linux/sound.h>
+#include <linux/smp_lock.h>
 #include <linux/soundcard.h>
 #include <linux/soundcard.h>
 #include <linux/interrupt.h>
 #include <linux/interrupt.h>
 #include <linux/hrtimer.h>
 #include <linux/hrtimer.h>
@@ -92,7 +94,7 @@ static void dac_audio_set_rate(void)
 	wakeups_per_second = ktime_set(0, 1000000000 / rate);
 	wakeups_per_second = ktime_set(0, 1000000000 / rate);
 }
 }
 
 
-static int dac_audio_ioctl(struct inode *inode, struct file *file,
+static int dac_audio_ioctl(struct file *file,
 			   unsigned int cmd, unsigned long arg)
 			   unsigned int cmd, unsigned long arg)
 {
 {
 	int val;
 	int val;
@@ -158,6 +160,17 @@ static int dac_audio_ioctl(struct inode *inode, struct file *file,
 	return -EINVAL;
 	return -EINVAL;
 }
 }
 
 
+static long dac_audio_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
+{
+	int ret;
+
+	lock_kernel();
+	ret = dac_audio_ioctl(file, cmd, arg);
+	unlock_kernel();
+
+	return ret;
+}
+
 static ssize_t dac_audio_write(struct file *file, const char *buf, size_t count,
 static ssize_t dac_audio_write(struct file *file, const char *buf, size_t count,
 			       loff_t * ppos)
 			       loff_t * ppos)
 {
 {
@@ -216,13 +229,17 @@ static int dac_audio_open(struct inode *inode, struct file *file)
 {
 {
 	if (file->f_mode & FMODE_READ)
 	if (file->f_mode & FMODE_READ)
 		return -ENODEV;
 		return -ENODEV;
-	if (in_use)
+
+	lock_kernel();
+	if (in_use) {
+		unlock_kernel();
 		return -EBUSY;
 		return -EBUSY;
+	}
 
 
 	in_use = 1;
 	in_use = 1;
 
 
 	dac_audio_start();
 	dac_audio_start();
-
+	unlock_kernel();
 	return 0;
 	return 0;
 }
 }
 
 
@@ -237,8 +254,8 @@ static int dac_audio_release(struct inode *inode, struct file *file)
 
 
 const struct file_operations dac_audio_fops = {
 const struct file_operations dac_audio_fops = {
       .read =		dac_audio_read,
       .read =		dac_audio_read,
-      .write =	dac_audio_write,
-      .ioctl =	dac_audio_ioctl,
+      .write =		dac_audio_write,
+      .unlocked_ioctl =	dac_audio_unlocked_ioctl,
       .open =		dac_audio_open,
       .open =		dac_audio_open,
       .release =	dac_audio_release,
       .release =	dac_audio_release,
 };
 };

+ 11 - 9
sound/oss/soundcard.c

@@ -210,42 +210,44 @@ static int sound_open(struct inode *inode, struct file *file)
 		printk(KERN_ERR "Invalid minor device %d\n", dev);
 		printk(KERN_ERR "Invalid minor device %d\n", dev);
 		return -ENXIO;
 		return -ENXIO;
 	}
 	}
+	lock_kernel();
 	switch (dev & 0x0f) {
 	switch (dev & 0x0f) {
 	case SND_DEV_CTL:
 	case SND_DEV_CTL:
 		dev >>= 4;
 		dev >>= 4;
 		if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) {
 		if (dev >= 0 && dev < MAX_MIXER_DEV && mixer_devs[dev] == NULL) {
 			request_module("mixer%d", dev);
 			request_module("mixer%d", dev);
 		}
 		}
+		retval = -ENXIO;
 		if (dev && (dev >= num_mixers || mixer_devs[dev] == NULL))
 		if (dev && (dev >= num_mixers || mixer_devs[dev] == NULL))
-			return -ENXIO;
+			break;
 	
 	
 		if (!try_module_get(mixer_devs[dev]->owner))
 		if (!try_module_get(mixer_devs[dev]->owner))
-			return -ENXIO;
+			break;
+
+		retval = 0;
 		break;
 		break;
 
 
 	case SND_DEV_SEQ:
 	case SND_DEV_SEQ:
 	case SND_DEV_SEQ2:
 	case SND_DEV_SEQ2:
-		if ((retval = sequencer_open(dev, file)) < 0)
-			return retval;
+		retval = sequencer_open(dev, file);
 		break;
 		break;
 
 
 	case SND_DEV_MIDIN:
 	case SND_DEV_MIDIN:
-		if ((retval = MIDIbuf_open(dev, file)) < 0)
-			return retval;
+		retval = MIDIbuf_open(dev, file);
 		break;
 		break;
 
 
 	case SND_DEV_DSP:
 	case SND_DEV_DSP:
 	case SND_DEV_DSP16:
 	case SND_DEV_DSP16:
 	case SND_DEV_AUDIO:
 	case SND_DEV_AUDIO:
-		if ((retval = audio_open(dev, file)) < 0)
-			return retval;
+		retval = audio_open(dev, file);
 		break;
 		break;
 
 
 	default:
 	default:
 		printk(KERN_ERR "Invalid minor device %d\n", dev);
 		printk(KERN_ERR "Invalid minor device %d\n", dev);
-		return -ENXIO;
+		retval = -ENXIO;
 	}
 	}
 
 
+	unlock_kernel();
 	return 0;
 	return 0;
 }
 }
 
 

+ 35 - 6
sound/oss/swarm_cs4297a.c

@@ -68,6 +68,7 @@
 #include <linux/delay.h>
 #include <linux/delay.h>
 #include <linux/sound.h>
 #include <linux/sound.h>
 #include <linux/slab.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/soundcard.h>
 #include <linux/soundcard.h>
 #include <linux/ac97_codec.h>
 #include <linux/ac97_codec.h>
 #include <linux/pci.h>
 #include <linux/pci.h>
@@ -1534,6 +1535,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
 	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
 	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
 		  printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()+\n"));
 		  printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()+\n"));
 
 
+	lock_kernel();
 	list_for_each(entry, &cs4297a_devs)
 	list_for_each(entry, &cs4297a_devs)
 	{
 	{
 		s = list_entry(entry, struct cs4297a_state, list);
 		s = list_entry(entry, struct cs4297a_state, list);
@@ -1544,6 +1546,8 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
 	{
 	{
 		CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
 		CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
 			printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- -ENODEV\n"));
 			printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- -ENODEV\n"));
+
+		unlock_kernel();
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 	VALIDATE_STATE(s);
 	VALIDATE_STATE(s);
@@ -1551,6 +1555,7 @@ static int cs4297a_open_mixdev(struct inode *inode, struct file *file)
 
 
 	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
 	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
 		  printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- 0\n"));
 		  printk(KERN_INFO "cs4297a: cs4297a_open_mixdev()- 0\n"));
+	unlock_kernel();
 
 
 	return nonseekable_open(inode, file);
 	return nonseekable_open(inode, file);
 }
 }
@@ -1566,11 +1571,15 @@ static int cs4297a_release_mixdev(struct inode *inode, struct file *file)
 }
 }
 
 
 
 
-static int cs4297a_ioctl_mixdev(struct inode *inode, struct file *file,
+static int cs4297a_ioctl_mixdev(struct file *file,
 			       unsigned int cmd, unsigned long arg)
 			       unsigned int cmd, unsigned long arg)
 {
 {
-	return mixer_ioctl((struct cs4297a_state *) file->private_data, cmd,
+	int ret;
+	lock_kernel();
+	ret = mixer_ioctl((struct cs4297a_state *) file->private_data, cmd,
 			   arg);
 			   arg);
+	unlock_kernel();
+	return ret;
 }
 }
 
 
 
 
@@ -1580,7 +1589,7 @@ static int cs4297a_ioctl_mixdev(struct inode *inode, struct file *file,
 static const struct file_operations cs4297a_mixer_fops = {
 static const struct file_operations cs4297a_mixer_fops = {
 	.owner		= THIS_MODULE,
 	.owner		= THIS_MODULE,
 	.llseek		= no_llseek,
 	.llseek		= no_llseek,
-	.ioctl		= cs4297a_ioctl_mixdev,
+	.unlocked_ioctl	= cs4297a_ioctl_mixdev,
 	.open		= cs4297a_open_mixdev,
 	.open		= cs4297a_open_mixdev,
 	.release	= cs4297a_release_mixdev,
 	.release	= cs4297a_release_mixdev,
 };
 };
@@ -1944,7 +1953,7 @@ static int cs4297a_mmap(struct file *file, struct vm_area_struct *vma)
 }
 }
 
 
 
 
-static int cs4297a_ioctl(struct inode *inode, struct file *file,
+static int cs4297a_ioctl(struct file *file,
 			unsigned int cmd, unsigned long arg)
 			unsigned int cmd, unsigned long arg)
 {
 {
 	struct cs4297a_state *s =
 	struct cs4297a_state *s =
@@ -2337,6 +2346,16 @@ static int cs4297a_ioctl(struct inode *inode, struct file *file,
 	return mixer_ioctl(s, cmd, arg);
 	return mixer_ioctl(s, cmd, arg);
 }
 }
 
 
+static long cs4297a_unlocked_ioctl(struct file *file, u_int cmd, u_long arg)
+{
+	int ret;
+
+	lock_kernel();
+	ret = cs4297a_ioctl(file, cmd, arg);
+	unlock_kernel();
+
+	return ret;
+}
 
 
 static int cs4297a_release(struct inode *inode, struct file *file)
 static int cs4297a_release(struct inode *inode, struct file *file)
 {
 {
@@ -2369,7 +2388,7 @@ static int cs4297a_release(struct inode *inode, struct file *file)
 	return 0;
 	return 0;
 }
 }
 
 
-static int cs4297a_open(struct inode *inode, struct file *file)
+static int cs4297a_locked_open(struct inode *inode, struct file *file)
 {
 {
 	int minor = iminor(inode);
 	int minor = iminor(inode);
 	struct cs4297a_state *s=NULL;
 	struct cs4297a_state *s=NULL;
@@ -2486,6 +2505,16 @@ static int cs4297a_open(struct inode *inode, struct file *file)
 	return nonseekable_open(inode, file);
 	return nonseekable_open(inode, file);
 }
 }
 
 
+static int cs4297a_open(struct inode *inode, struct file *file)
+{
+	int ret;
+
+	lock_kernel();
+	ret = cs4297a_open(inode, file);
+	unlock_kernel();
+
+	return ret;
+}
 
 
 // ******************************************************************************************
 // ******************************************************************************************
 //   Wave (audio) file operations struct.
 //   Wave (audio) file operations struct.
@@ -2496,7 +2525,7 @@ static const struct file_operations cs4297a_audio_fops = {
 	.read		= cs4297a_read,
 	.read		= cs4297a_read,
 	.write		= cs4297a_write,
 	.write		= cs4297a_write,
 	.poll		= cs4297a_poll,
 	.poll		= cs4297a_poll,
-	.ioctl		= cs4297a_ioctl,
+	.unlocked_ioctl	= cs4297a_unlocked_ioctl,
 	.mmap		= cs4297a_mmap,
 	.mmap		= cs4297a_mmap,
 	.open		= cs4297a_open,
 	.open		= cs4297a_open,
 	.release	= cs4297a_release,
 	.release	= cs4297a_release,

+ 0 - 3
sound/oss/vidc.c

@@ -491,9 +491,6 @@ static void __init attach_vidc(struct address_info *hw_config)
 	vidc_adev = adev;
 	vidc_adev = adev;
 	vidc_mixer_set(SOUND_MIXER_VOLUME, (85 | 85 << 8));
 	vidc_mixer_set(SOUND_MIXER_VOLUME, (85 | 85 << 8));
 
 
-#if defined(CONFIG_SOUND_SOFTOSS) || defined(CONFIG_SOUND_SOFTOSS_MODULE)
-	softoss_dev = adev;
-#endif
 	return;
 	return;
 
 
 irq_failed:
 irq_failed:

+ 21 - 11
sound/oss/vwsnd.c

@@ -2429,8 +2429,7 @@ static unsigned int vwsnd_audio_poll(struct file *file,
 	return mask;
 	return mask;
 }
 }
 
 
-static int vwsnd_audio_do_ioctl(struct inode *inode,
-				struct file *file,
+static int vwsnd_audio_do_ioctl(struct file *file,
 				unsigned int cmd,
 				unsigned int cmd,
 				unsigned long arg)
 				unsigned long arg)
 {
 {
@@ -2446,8 +2445,8 @@ static int vwsnd_audio_do_ioctl(struct inode *inode,
 	int ival;
 	int ival;
 
 
 	
 	
-	DBGEV("(inode=0x%p, file=0x%p, cmd=0x%x, arg=0x%lx)\n",
-	      inode, file, cmd, arg);
+	DBGEV("(file=0x%p, cmd=0x%x, arg=0x%lx)\n",
+	      file, cmd, arg);
 	switch (cmd) {
 	switch (cmd) {
 	case OSS_GETVERSION:		/* _SIOR ('M', 118, int) */
 	case OSS_GETVERSION:		/* _SIOR ('M', 118, int) */
 		DBGX("OSS_GETVERSION\n");
 		DBGX("OSS_GETVERSION\n");
@@ -2885,17 +2884,19 @@ static int vwsnd_audio_do_ioctl(struct inode *inode,
 	return -EINVAL;
 	return -EINVAL;
 }
 }
 
 
-static int vwsnd_audio_ioctl(struct inode *inode,
-				struct file *file,
+static long vwsnd_audio_ioctl(struct file *file,
 				unsigned int cmd,
 				unsigned int cmd,
 				unsigned long arg)
 				unsigned long arg)
 {
 {
 	vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
 	vwsnd_dev_t *devc = (vwsnd_dev_t *) file->private_data;
 	int ret;
 	int ret;
 
 
+	lock_kernel();
 	mutex_lock(&devc->io_mutex);
 	mutex_lock(&devc->io_mutex);
-	ret = vwsnd_audio_do_ioctl(inode, file, cmd, arg);
+	ret = vwsnd_audio_do_ioctl(file, cmd, arg);
 	mutex_unlock(&devc->io_mutex);
 	mutex_unlock(&devc->io_mutex);
+	unlock_kernel();
+
 	return ret;
 	return ret;
 }
 }
 
 
@@ -2921,6 +2922,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
 
 
 	DBGE("(inode=0x%p, file=0x%p)\n", inode, file);
 	DBGE("(inode=0x%p, file=0x%p)\n", inode, file);
 
 
+	lock_kernel();
 	INC_USE_COUNT;
 	INC_USE_COUNT;
 	for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
 	for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
 		if ((devc->audio_minor & ~0x0F) == (minor & ~0x0F))
 		if ((devc->audio_minor & ~0x0F) == (minor & ~0x0F))
@@ -2928,6 +2930,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
 
 
 	if (devc == NULL) {
 	if (devc == NULL) {
 		DEC_USE_COUNT;
 		DEC_USE_COUNT;
+		unlock_kernel();
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 
 
@@ -2936,11 +2939,13 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
 		mutex_unlock(&devc->open_mutex);
 		mutex_unlock(&devc->open_mutex);
 		if (file->f_flags & O_NONBLOCK) {
 		if (file->f_flags & O_NONBLOCK) {
 			DEC_USE_COUNT;
 			DEC_USE_COUNT;
+			unlock_kernel();
 			return -EBUSY;
 			return -EBUSY;
 		}
 		}
 		interruptible_sleep_on(&devc->open_wait);
 		interruptible_sleep_on(&devc->open_wait);
 		if (signal_pending(current)) {
 		if (signal_pending(current)) {
 			DEC_USE_COUNT;
 			DEC_USE_COUNT;
+			unlock_kernel();
 			return -ERESTARTSYS;
 			return -ERESTARTSYS;
 		}
 		}
 		mutex_lock(&devc->open_mutex);
 		mutex_lock(&devc->open_mutex);
@@ -2993,6 +2998,7 @@ static int vwsnd_audio_open(struct inode *inode, struct file *file)
 
 
 	file->private_data = devc;
 	file->private_data = devc;
 	DBGRV();
 	DBGRV();
+	unlock_kernel();
 	return 0;
 	return 0;
 }
 }
 
 
@@ -3044,7 +3050,7 @@ static const struct file_operations vwsnd_audio_fops = {
 	.read =		vwsnd_audio_read,
 	.read =		vwsnd_audio_read,
 	.write =	vwsnd_audio_write,
 	.write =	vwsnd_audio_write,
 	.poll =		vwsnd_audio_poll,
 	.poll =		vwsnd_audio_poll,
-	.ioctl =	vwsnd_audio_ioctl,
+	.unlocked_ioctl = vwsnd_audio_ioctl,
 	.mmap =		vwsnd_audio_mmap,
 	.mmap =		vwsnd_audio_mmap,
 	.open =		vwsnd_audio_open,
 	.open =		vwsnd_audio_open,
 	.release =	vwsnd_audio_release,
 	.release =	vwsnd_audio_release,
@@ -3062,15 +3068,18 @@ static int vwsnd_mixer_open(struct inode *inode, struct file *file)
 	DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
 	DBGEV("(inode=0x%p, file=0x%p)\n", inode, file);
 
 
 	INC_USE_COUNT;
 	INC_USE_COUNT;
+	lock_kernel();
 	for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
 	for (devc = vwsnd_dev_list; devc; devc = devc->next_dev)
 		if (devc->mixer_minor == iminor(inode))
 		if (devc->mixer_minor == iminor(inode))
 			break;
 			break;
 
 
 	if (devc == NULL) {
 	if (devc == NULL) {
 		DEC_USE_COUNT;
 		DEC_USE_COUNT;
+		unlock_kernel();
 		return -ENODEV;
 		return -ENODEV;
 	}
 	}
 	file->private_data = devc;
 	file->private_data = devc;
+	unlock_kernel();
 	return 0;
 	return 0;
 }
 }
 
 
@@ -3203,8 +3212,7 @@ static int mixer_write_ioctl(vwsnd_dev_t *devc, unsigned int nr, void __user *ar
 
 
 /* This is the ioctl entry to the mixer driver. */
 /* This is the ioctl entry to the mixer driver. */
 
 
-static int vwsnd_mixer_ioctl(struct inode *ioctl,
-			      struct file *file,
+static long vwsnd_mixer_ioctl(struct file *file,
 			      unsigned int cmd,
 			      unsigned int cmd,
 			      unsigned long arg)
 			      unsigned long arg)
 {
 {
@@ -3215,6 +3223,7 @@ static int vwsnd_mixer_ioctl(struct inode *ioctl,
 
 
 	DBGEV("(devc=0x%p, cmd=0x%x, arg=0x%lx)\n", devc, cmd, arg);
 	DBGEV("(devc=0x%p, cmd=0x%x, arg=0x%lx)\n", devc, cmd, arg);
 
 
+	lock_kernel();
 	mutex_lock(&devc->mix_mutex);
 	mutex_lock(&devc->mix_mutex);
 	{
 	{
 		if ((cmd & ~nrmask) == MIXER_READ(0))
 		if ((cmd & ~nrmask) == MIXER_READ(0))
@@ -3225,13 +3234,14 @@ static int vwsnd_mixer_ioctl(struct inode *ioctl,
 			retval = -EINVAL;
 			retval = -EINVAL;
 	}
 	}
 	mutex_unlock(&devc->mix_mutex);
 	mutex_unlock(&devc->mix_mutex);
+	unlock_kernel();
 	return retval;
 	return retval;
 }
 }
 
 
 static const struct file_operations vwsnd_mixer_fops = {
 static const struct file_operations vwsnd_mixer_fops = {
 	.owner =	THIS_MODULE,
 	.owner =	THIS_MODULE,
 	.llseek =	no_llseek,
 	.llseek =	no_llseek,
-	.ioctl =	vwsnd_mixer_ioctl,
+	.unlocked_ioctl = vwsnd_mixer_ioctl,
 	.open =		vwsnd_mixer_open,
 	.open =		vwsnd_mixer_open,
 	.release =	vwsnd_mixer_release,
 	.release =	vwsnd_mixer_release,
 };
 };

+ 2 - 8
sound/oss/waveartist.c

@@ -184,14 +184,8 @@ waveartist_iack(wavnc_info *devc)
 static inline int
 static inline int
 waveartist_sleep(int timeout_ms)
 waveartist_sleep(int timeout_ms)
 {
 {
-	unsigned int timeout = timeout_ms * 10 * HZ / 100;
-
-	do {
-		set_current_state(TASK_INTERRUPTIBLE);
-		timeout = schedule_timeout(timeout);
-	} while (timeout);
-
-	return 0;
+	unsigned int timeout = msecs_to_jiffies(timeout_ms*100);
+	return schedule_timeout_interruptible(timeout);
 }
 }
 
 
 static int
 static int

+ 2 - 2
sound/pci/als4000.c

@@ -763,9 +763,9 @@ static void snd_als4000_configure(struct snd_sb *chip)
 	/* SPECS_PAGE: 39 */
 	/* SPECS_PAGE: 39 */
 	for (i = ALS4K_GCR91_DMA0_ADDR; i <= ALS4K_GCR96_DMA3_MODE_COUNT; ++i)
 	for (i = ALS4K_GCR91_DMA0_ADDR; i <= ALS4K_GCR96_DMA3_MODE_COUNT; ++i)
 		snd_als4k_gcr_write(chip, i, 0);
 		snd_als4k_gcr_write(chip, i, 0);
-	
+	/* enable burst mode to prevent dropouts during high PCI bus usage */
 	snd_als4k_gcr_write(chip, ALS4K_GCR99_DMA_EMULATION_CTRL,
 	snd_als4k_gcr_write(chip, ALS4K_GCR99_DMA_EMULATION_CTRL,
-		snd_als4k_gcr_read(chip, ALS4K_GCR99_DMA_EMULATION_CTRL));
+		(snd_als4k_gcr_read(chip, ALS4K_GCR99_DMA_EMULATION_CTRL) & ~0x07) | 0x04);
 	spin_unlock_irq(&chip->reg_lock);
 	spin_unlock_irq(&chip->reg_lock);
 }
 }
 
 

+ 9 - 7
sound/pci/asihpi/asihpi.c

@@ -460,6 +460,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
 	struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
 	struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
 	int err;
 	int err;
 	u16 format;
 	u16 format;
+	int width;
 	unsigned int bytes_per_sec;
 	unsigned int bytes_per_sec;
 
 
 	print_hwparams(params);
 	print_hwparams(params);
@@ -512,9 +513,10 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
 				dpcm->hpi_buffer_attached);
 				dpcm->hpi_buffer_attached);
 	}
 	}
 	bytes_per_sec = params_rate(params) * params_channels(params);
 	bytes_per_sec = params_rate(params) * params_channels(params);
-	bytes_per_sec *= snd_pcm_format_width(params_format(params));
+	width = snd_pcm_format_width(params_format(params));
+	bytes_per_sec *= width;
 	bytes_per_sec /= 8;
 	bytes_per_sec /= 8;
-	if (bytes_per_sec <= 0)
+	if (width < 0 || bytes_per_sec == 0)
 		return -EINVAL;
 		return -EINVAL;
 
 
 	dpcm->bytes_per_sec = bytes_per_sec;
 	dpcm->bytes_per_sec = bytes_per_sec;
@@ -1383,7 +1385,7 @@ static char *asihpi_src_names[] =
 
 
 compile_time_assert(
 compile_time_assert(
 	(ARRAY_SIZE(asihpi_src_names) ==
 	(ARRAY_SIZE(asihpi_src_names) ==
-		(HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_BASE+1)),
+		(HPI_SOURCENODE_LAST_INDEX-HPI_SOURCENODE_NONE+1)),
 	assert_src_names_size);
 	assert_src_names_size);
 
 
 #if ASI_STYLE_NAMES
 #if ASI_STYLE_NAMES
@@ -1414,7 +1416,7 @@ static char *asihpi_dst_names[] =
 
 
 compile_time_assert(
 compile_time_assert(
 	(ARRAY_SIZE(asihpi_dst_names) ==
 	(ARRAY_SIZE(asihpi_dst_names) ==
-		(HPI_DESTNODE_LAST_INDEX-HPI_DESTNODE_BASE+1)),
+		(HPI_DESTNODE_LAST_INDEX-HPI_DESTNODE_NONE+1)),
 	assert_dst_names_size);
 	assert_dst_names_size);
 
 
 static inline int ctl_add(struct snd_card *card, struct snd_kcontrol_new *ctl,
 static inline int ctl_add(struct snd_card *card, struct snd_kcontrol_new *ctl,
@@ -2171,7 +2173,7 @@ static int snd_asihpi_mux_info(struct snd_kcontrol *kcontrol,
 					&src_node_type, &src_node_index);
 					&src_node_type, &src_node_index);
 
 
 	sprintf(uinfo->value.enumerated.name, "%s %d",
 	sprintf(uinfo->value.enumerated.name, "%s %d",
-		asihpi_src_names[src_node_type - HPI_SOURCENODE_BASE],
+		asihpi_src_names[src_node_type - HPI_SOURCENODE_NONE],
 		src_node_index);
 		src_node_index);
 	return 0;
 	return 0;
 }
 }
@@ -2603,8 +2605,8 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
 
 
 		}
 		}
 
 
-		hpi_ctl.src_node_type -= HPI_SOURCENODE_BASE;
-		hpi_ctl.dst_node_type -= HPI_DESTNODE_BASE;
+		hpi_ctl.src_node_type -= HPI_SOURCENODE_NONE;
+		hpi_ctl.dst_node_type -= HPI_DESTNODE_NONE;
 
 
 		/* ASI50xx in SSX mode has multiple meters on the same node.
 		/* ASI50xx in SSX mode has multiple meters on the same node.
 		   Use subindex to create distinct ALSA controls
 		   Use subindex to create distinct ALSA controls

+ 48 - 20
sound/pci/asihpi/hpi.h

@@ -50,7 +50,8 @@ i.e 3.05.02 is a development version
 #define HPI_VER_RELEASE(v) ((int)(v & 0xFF))
 #define HPI_VER_RELEASE(v) ((int)(v & 0xFF))
 
 
 /* Use single digits for versions less that 10 to avoid octal. */
 /* Use single digits for versions less that 10 to avoid octal. */
-#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 3, 25)
+#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 4, 1)
+#define HPI_VER_STRING "4.04.01"
 
 
 /* Library version as documented in hpi-api-versions.txt */
 /* Library version as documented in hpi-api-versions.txt */
 #define HPI_LIB_VER  HPI_VERSION_CONSTRUCTOR(9, 0, 0)
 #define HPI_LIB_VER  HPI_VERSION_CONSTRUCTOR(9, 0, 0)
@@ -203,8 +204,6 @@ enum HPI_SOURCENODES {
 	exists on a destination node can be searched for using a source
 	exists on a destination node can be searched for using a source
 	node value of either 0, or HPI_SOURCENODE_NONE */
 	node value of either 0, or HPI_SOURCENODE_NONE */
 	HPI_SOURCENODE_NONE = 100,
 	HPI_SOURCENODE_NONE = 100,
-	/** \deprecated Use HPI_SOURCENODE_NONE instead. */
-	HPI_SOURCENODE_BASE = 100,
 	/** Out Stream (Play) node. */
 	/** Out Stream (Play) node. */
 	HPI_SOURCENODE_OSTREAM = 101,
 	HPI_SOURCENODE_OSTREAM = 101,
 	/** Line in node - could be analog, AES/EBU or network. */
 	/** Line in node - could be analog, AES/EBU or network. */
@@ -235,8 +234,6 @@ enum HPI_DESTNODES {
 	exists on a source node can be searched for using a destination
 	exists on a source node can be searched for using a destination
 	node value of either 0, or HPI_DESTNODE_NONE */
 	node value of either 0, or HPI_DESTNODE_NONE */
 	HPI_DESTNODE_NONE = 200,
 	HPI_DESTNODE_NONE = 200,
-	/** \deprecated Use HPI_DESTNODE_NONE instead. */
-	HPI_DESTNODE_BASE = 200,
 	/** In Stream (Record) node. */
 	/** In Stream (Record) node. */
 	HPI_DESTNODE_ISTREAM = 201,
 	HPI_DESTNODE_ISTREAM = 201,
 	HPI_DESTNODE_LINEOUT = 202,	    /**< line out node. */
 	HPI_DESTNODE_LINEOUT = 202,	    /**< line out node. */
@@ -432,7 +429,18 @@ Property 2 - adapter can do stream grouping (supports SSX2)
 Property 1 - adapter can do samplerate conversion (MRX)
 Property 1 - adapter can do samplerate conversion (MRX)
 Property 2 - adapter can do timestretch (TSX)
 Property 2 - adapter can do timestretch (TSX)
 */
 */
-	HPI_ADAPTER_PROPERTY_CAPS2 = 269
+	HPI_ADAPTER_PROPERTY_CAPS2 = 269,
+
+/** Readonly adapter sync header connection count.
+*/
+	HPI_ADAPTER_PROPERTY_SYNC_HEADER_CONNECTIONS = 270,
+/** Readonly supports SSX2 property.
+Indicates the adapter supports SSX2 in some mode setting. The
+return value is true (1) or false (0). If the current adapter
+mode is MONO SSX2 is disabled, even though this property will
+return true.
+*/
+	HPI_ADAPTER_PROPERTY_SUPPORTS_SSX2 = 271
 };
 };
 
 
 /** Adapter mode commands
 /** Adapter mode commands
@@ -813,8 +821,6 @@ enum HPI_SAMPLECLOCK_SOURCES {
 /** The sampleclock output is derived from its local samplerate generator.
 /** The sampleclock output is derived from its local samplerate generator.
     The local samplerate may be set using HPI_SampleClock_SetLocalRate(). */
     The local samplerate may be set using HPI_SampleClock_SetLocalRate(). */
 	HPI_SAMPLECLOCK_SOURCE_LOCAL = 1,
 	HPI_SAMPLECLOCK_SOURCE_LOCAL = 1,
-/** \deprecated Use HPI_SAMPLECLOCK_SOURCE_LOCAL instead */
-	HPI_SAMPLECLOCK_SOURCE_ADAPTER = 1,
 /** The adapter is clocked from a dedicated AES/EBU SampleClock input.*/
 /** The adapter is clocked from a dedicated AES/EBU SampleClock input.*/
 	HPI_SAMPLECLOCK_SOURCE_AESEBU_SYNC = 2,
 	HPI_SAMPLECLOCK_SOURCE_AESEBU_SYNC = 2,
 /** From external wordclock connector */
 /** From external wordclock connector */
@@ -825,10 +831,6 @@ enum HPI_SAMPLECLOCK_SOURCES {
 	HPI_SAMPLECLOCK_SOURCE_SMPTE = 5,
 	HPI_SAMPLECLOCK_SOURCE_SMPTE = 5,
 /** One of the aesebu inputs */
 /** One of the aesebu inputs */
 	HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT = 6,
 	HPI_SAMPLECLOCK_SOURCE_AESEBU_INPUT = 6,
-/** \deprecated The first aesebu input with a valid signal
-Superseded by separate Auto enable flag
-*/
-	HPI_SAMPLECLOCK_SOURCE_AESEBU_AUTO = 7,
 /** From a network interface e.g. Cobranet or Livewire at either 48 or 96kHz */
 /** From a network interface e.g. Cobranet or Livewire at either 48 or 96kHz */
 	HPI_SAMPLECLOCK_SOURCE_NETWORK = 8,
 	HPI_SAMPLECLOCK_SOURCE_NETWORK = 8,
 /** From previous adjacent module (ASI2416 only)*/
 /** From previous adjacent module (ASI2416 only)*/
@@ -1015,8 +1017,6 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_CONTROL_DISABLED = 404,
 	HPI_ERROR_CONTROL_DISABLED = 404,
 	/** I2C transaction failed due to a missing ACK. */
 	/** I2C transaction failed due to a missing ACK. */
 	HPI_ERROR_CONTROL_I2C_MISSING_ACK = 405,
 	HPI_ERROR_CONTROL_I2C_MISSING_ACK = 405,
-	/** Control attribute is valid, but not supported by this hardware. */
-	HPI_ERROR_UNSUPPORTED_CONTROL_ATTRIBUTE = 406,
 	/** Control is busy, or coming out of
 	/** Control is busy, or coming out of
 	reset and cannot be accessed at this time. */
 	reset and cannot be accessed at this time. */
 	HPI_ERROR_CONTROL_NOT_READY = 407,
 	HPI_ERROR_CONTROL_NOT_READY = 407,
@@ -1827,13 +1827,41 @@ u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys,
   Compressor Expander control
   Compressor Expander control
 *******************************/
 *******************************/
 
 
-u16 hpi_compander_set(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 attack, u16 decay, short ratio100, short threshold0_01dB,
-	short makeup_gain0_01dB);
+u16 hpi_compander_set_enable(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, u32 on);
+
+u16 hpi_compander_get_enable(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, u32 *pon);
+
+u16 hpi_compander_set_makeup_gain(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, short makeup_gain0_01dB);
+
+u16 hpi_compander_get_makeup_gain(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, short *pn_makeup_gain0_01dB);
+
+u16 hpi_compander_set_attack_time_constant(const struct hpi_hsubsys
+	*ph_subsys, u32 h_control, u32 index, u32 attack);
+
+u16 hpi_compander_get_attack_time_constant(const struct hpi_hsubsys
+	*ph_subsys, u32 h_control, u32 index, u32 *pw_attack);
+
+u16 hpi_compander_set_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, u32 index, u32 decay);
+
+u16 hpi_compander_get_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, u32 index, u32 *pw_decay);
+
+u16 hpi_compander_set_threshold(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, u32 index, short threshold0_01dB);
+
+u16 hpi_compander_get_threshold(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, u32 index, short *pn_threshold0_01dB);
+
+u16 hpi_compander_set_ratio(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, u32 index, u32 ratio100);
 
 
-u16 hpi_compander_get(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 *pw_attack, u16 *pw_decay, short *pw_ratio100,
-	short *pn_threshold0_01dB, short *pn_makeup_gain0_01dB);
+u16 hpi_compander_get_ratio(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, u32 index, u32 *pw_ratio100);
 
 
 /*******************************
 /*******************************
   Cobranet HMI control
   Cobranet HMI control

+ 7 - 0
sound/pci/asihpi/hpi6000.c

@@ -687,6 +687,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 	switch (pao->pci.subsys_device_id) {
 	switch (pao->pci.subsys_device_id) {
 	case 0x5100:
 	case 0x5100:
 	case 0x5110:	/* ASI5100 revB or higher with C6711D */
 	case 0x5110:	/* ASI5100 revB or higher with C6711D */
+	case 0x5200:	/* ASI5200 PC_ie version of ASI5100 */
 	case 0x6100:
 	case 0x6100:
 	case 0x6200:
 	case 0x6200:
 		boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200);
 		boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200);
@@ -1133,6 +1134,12 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 						subsys_device_id) ==
 						subsys_device_id) ==
 					HPI_ADAPTER_FAMILY_ASI(0x5100))
 					HPI_ADAPTER_FAMILY_ASI(0x5100))
 					mask = 0x00000000L;
 					mask = 0x00000000L;
+				/* ASI5200 uses AX6 code, */
+				/* but has no PLD r/w register to test */
+				if (HPI_ADAPTER_FAMILY_ASI(pao->pci.
+						subsys_device_id) ==
+					HPI_ADAPTER_FAMILY_ASI(0x5200))
+					mask = 0x00000000L;
 				break;
 				break;
 			case HPI_ADAPTER_FAMILY_ASI(0x8800):
 			case HPI_ADAPTER_FAMILY_ASI(0x8800):
 				/* ASI8800 has 16bit path to FPGA */
 				/* ASI8800 has 16bit path to FPGA */

+ 22 - 18
sound/pci/asihpi/hpi_internal.h

@@ -104,9 +104,9 @@ typedef void hpi_handler_func(struct hpi_message *, struct hpi_response *);
 #define STR_ROLE_FIELD_MAX 255U
 #define STR_ROLE_FIELD_MAX 255U
 
 
 struct hpi_entity_str {
 struct hpi_entity_str {
-	uint16_t size;
-	uint8_t type;
-	uint8_t role;
+	u16 size;
+	u8 type;
+	u8 role;
 };
 };
 
 
 #if defined(_MSC_VER)
 #if defined(_MSC_VER)
@@ -119,11 +119,11 @@ struct hpi_entity {
 #if ! defined(HPI_OS_DSP_C6000) || (defined(HPI_OS_DSP_C6000) && (__TI_COMPILER_VERSION__ > 6000008))
 #if ! defined(HPI_OS_DSP_C6000) || (defined(HPI_OS_DSP_C6000) && (__TI_COMPILER_VERSION__ > 6000008))
 	/* DSP C6000 compiler v6.0.8 and lower
 	/* DSP C6000 compiler v6.0.8 and lower
 	   do not support  flexible array member */
 	   do not support  flexible array member */
-	uint8_t value[];
+	u8 value[];
 #else
 #else
 	/* NOTE! Using sizeof(struct hpi_entity) will give erroneous results */
 	/* NOTE! Using sizeof(struct hpi_entity) will give erroneous results */
 #define HPI_INTERNAL_WARN_ABOUT_ENTITY_VALUE
 #define HPI_INTERNAL_WARN_ABOUT_ENTITY_VALUE
-	uint8_t value[1];
+	u8 value[1];
 #endif
 #endif
 };
 };
 
 
@@ -142,12 +142,15 @@ enum HPI_BUSES {
 /******************************************* CONTROL ATTRIBUTES ****/
 /******************************************* CONTROL ATTRIBUTES ****/
 /* (in order of control type ID */
 /* (in order of control type ID */
 
 
-	/* This allows for 255 control types, 256 unique attributes each */
+/* This allows for 255 control types, 256 unique attributes each */
 #define HPI_CTL_ATTR(ctl, ai) (HPI_CONTROL_##ctl * 0x100 + ai)
 #define HPI_CTL_ATTR(ctl, ai) (HPI_CONTROL_##ctl * 0x100 + ai)
 
 
 /* Get the sub-index of the attribute for a control type */
 /* Get the sub-index of the attribute for a control type */
 #define HPI_CTL_ATTR_INDEX(i) (i&0xff)
 #define HPI_CTL_ATTR_INDEX(i) (i&0xff)
 
 
+/* Extract the control from the control attribute */
+#define HPI_CTL_ATTR_CONTROL(i) (i>>8)
+
 /* Generic control attributes.  */
 /* Generic control attributes.  */
 
 
 /** Enable a control.
 /** Enable a control.
@@ -311,8 +314,7 @@ Used for HPI_ChannelModeSet/Get()
 /* Microphone control attributes */
 /* Microphone control attributes */
 #define HPI_MICROPHONE_PHANTOM_POWER HPI_CTL_ATTR(MICROPHONE, 1)
 #define HPI_MICROPHONE_PHANTOM_POWER HPI_CTL_ATTR(MICROPHONE, 1)
 
 
-/** Equalizer control attributes
-*/
+/** Equalizer control attributes */
 /** Used to get number of filters in an EQ. (Can't set) */
 /** Used to get number of filters in an EQ. (Can't set) */
 #define HPI_EQUALIZER_NUM_FILTERS HPI_CTL_ATTR(EQUALIZER, 1)
 #define HPI_EQUALIZER_NUM_FILTERS HPI_CTL_ATTR(EQUALIZER, 1)
 /** Set/get the filter by type, freq, Q, gain */
 /** Set/get the filter by type, freq, Q, gain */
@@ -320,13 +322,15 @@ Used for HPI_ChannelModeSet/Get()
 /** Get the biquad coefficients */
 /** Get the biquad coefficients */
 #define HPI_EQUALIZER_COEFFICIENTS HPI_CTL_ATTR(EQUALIZER, 3)
 #define HPI_EQUALIZER_COEFFICIENTS HPI_CTL_ATTR(EQUALIZER, 3)
 
 
-#define HPI_COMPANDER_PARAMS HPI_CTL_ATTR(COMPANDER, 1)
+/* Note compander also uses HPI_GENERIC_ENABLE */
+#define HPI_COMPANDER_PARAMS     HPI_CTL_ATTR(COMPANDER, 1)
+#define HPI_COMPANDER_MAKEUPGAIN HPI_CTL_ATTR(COMPANDER, 2)
+#define HPI_COMPANDER_THRESHOLD  HPI_CTL_ATTR(COMPANDER, 3)
+#define HPI_COMPANDER_RATIO      HPI_CTL_ATTR(COMPANDER, 4)
+#define HPI_COMPANDER_ATTACK     HPI_CTL_ATTR(COMPANDER, 5)
+#define HPI_COMPANDER_DECAY      HPI_CTL_ATTR(COMPANDER, 6)
 
 
-/* Cobranet control attributes.
-   MUST be distinct from all other control attributes.
-   This is so that host side processing can easily identify a Cobranet control
-   and apply additional host side operations (like copying data) as required.
-*/
+/* Cobranet control attributes. */
 #define HPI_COBRANET_SET         HPI_CTL_ATTR(COBRANET, 1)
 #define HPI_COBRANET_SET         HPI_CTL_ATTR(COBRANET, 1)
 #define HPI_COBRANET_GET         HPI_CTL_ATTR(COBRANET, 2)
 #define HPI_COBRANET_GET         HPI_CTL_ATTR(COBRANET, 2)
 #define HPI_COBRANET_SET_DATA    HPI_CTL_ATTR(COBRANET, 3)
 #define HPI_COBRANET_SET_DATA    HPI_CTL_ATTR(COBRANET, 3)
@@ -1512,11 +1516,11 @@ struct hpi_control_cache_single {
 	struct hpi_control_cache_info i;
 	struct hpi_control_cache_info i;
 	union {
 	union {
 		struct {	/* volume */
 		struct {	/* volume */
-			u16 an_log[2];
+			short an_log[2];
 		} v;
 		} v;
 		struct {	/* peak meter */
 		struct {	/* peak meter */
-			u16 an_log_peak[2];
-			u16 an_logRMS[2];
+			short an_log_peak[2];
+			short an_logRMS[2];
 		} p;
 		} p;
 		struct {	/* channel mode */
 		struct {	/* channel mode */
 			u16 mode;
 			u16 mode;
@@ -1526,7 +1530,7 @@ struct hpi_control_cache_single {
 			u16 source_node_index;
 			u16 source_node_index;
 		} x;
 		} x;
 		struct {	/* level/trim */
 		struct {	/* level/trim */
-			u16 an_log[2];
+			short an_log[2];
 		} l;
 		} l;
 		struct {	/* tuner - partial caching.
 		struct {	/* tuner - partial caching.
 				   some attributes go to the DSP. */
 				   some attributes go to the DSP. */

+ 8 - 2
sound/pci/asihpi/hpicmn.c

@@ -353,7 +353,12 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 			phr->u.c.param1 = pC->u.t.band;
 			phr->u.c.param1 = pC->u.t.band;
 		else if ((phm->u.c.attribute == HPI_TUNER_LEVEL)
 		else if ((phm->u.c.attribute == HPI_TUNER_LEVEL)
 			&& (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE))
 			&& (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE))
-			phr->u.c.param1 = pC->u.t.level;
+			if (pC->u.t.level == HPI_ERROR_ILLEGAL_CACHE_VALUE) {
+				phr->u.c.param1 = 0;
+				phr->error =
+					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
+			} else
+				phr->u.c.param1 = pC->u.t.level;
 		else
 		else
 			found = 0;
 			found = 0;
 		break;
 		break;
@@ -397,7 +402,8 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 			if (pC->u.clk.source_index ==
 			if (pC->u.clk.source_index ==
 				HPI_ERROR_ILLEGAL_CACHE_VALUE) {
 				HPI_ERROR_ILLEGAL_CACHE_VALUE) {
 				phr->u.c.param1 = 0;
 				phr->u.c.param1 = 0;
-				phr->error = HPI_ERROR_INVALID_OPERATION;
+				phr->error =
+					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 			} else
 			} else
 				phr->u.c.param1 = pC->u.clk.source_index;
 				phr->u.c.param1 = pC->u.clk.source_index;
 		} else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
 		} else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)

+ 1 - 1
sound/pci/asihpi/hpidebug.c

@@ -111,7 +111,7 @@ make_treenode_from_array(hpi_control_type_strings, HPI_CONTROL_TYPE_STRINGS)
   &hpi_profile_strings,\
   &hpi_profile_strings,\
   &hpi_control_strings, \
   &hpi_control_strings, \
   &hpi_asyncevent_strings \
   &hpi_asyncevent_strings \
-};
+}
 	make_treenode_from_array(hpi_function_strings, HPI_FUNCTION_STRINGS)
 	make_treenode_from_array(hpi_function_strings, HPI_FUNCTION_STRINGS)
 
 
 	compile_time_assert(HPI_OBJ_MAXINDEX == 14, obj_list_doesnt_match);
 	compile_time_assert(HPI_OBJ_MAXINDEX == 14, obj_list_doesnt_match);

+ 2 - 2
sound/pci/asihpi/hpidebug.h

@@ -356,7 +356,7 @@ compile_time_assert((HPI_CONTROL_LAST_INDEX + 1 == 27),
 	"HPI_SOURCENODE_ADAPTER" \
 	"HPI_SOURCENODE_ADAPTER" \
 }
 }
 
 
-compile_time_assert((HPI_SOURCENODE_LAST_INDEX - HPI_SOURCENODE_BASE + 1) ==
+compile_time_assert((HPI_SOURCENODE_LAST_INDEX - HPI_SOURCENODE_NONE + 1) ==
 	(12), sourcenode_strings_match_defs);
 	(12), sourcenode_strings_match_defs);
 
 
 #define HPI_DESTNODE_STRINGS \
 #define HPI_DESTNODE_STRINGS \
@@ -370,7 +370,7 @@ compile_time_assert((HPI_SOURCENODE_LAST_INDEX - HPI_SOURCENODE_BASE + 1) ==
 	"HPI_DESTNODE_COBRANET", \
 	"HPI_DESTNODE_COBRANET", \
 	"HPI_DESTNODE_ANALOG" \
 	"HPI_DESTNODE_ANALOG" \
 }
 }
-compile_time_assert((HPI_DESTNODE_LAST_INDEX - HPI_DESTNODE_BASE + 1) == (8),
+compile_time_assert((HPI_DESTNODE_LAST_INDEX - HPI_DESTNODE_NONE + 1) == (8),
 	destnode_strings_match_defs);
 	destnode_strings_match_defs);
 
 
 #define HPI_CONTROL_CHANNEL_MODE_STRINGS \
 #define HPI_CONTROL_CHANNEL_MODE_STRINGS \

+ 195 - 132
sound/pci/asihpi/hpifunc.c

@@ -96,8 +96,7 @@ void hpi_stream_response_to_legacy(struct hpi_stream_res *pSR)
 
 
 static struct hpi_hsubsys gh_subsys;
 static struct hpi_hsubsys gh_subsys;
 
 
-struct hpi_hsubsys *hpi_subsys_create(void
-	)
+struct hpi_hsubsys *hpi_subsys_create(void)
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
@@ -302,6 +301,7 @@ u16 hpi_adapter_set_mode_ex(const struct hpi_hsubsys *ph_subsys,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
 		HPI_ADAPTER_SET_MODE);
 		HPI_ADAPTER_SET_MODE);
 	hm.adapter_index = adapter_index;
 	hm.adapter_index = adapter_index;
@@ -510,7 +510,7 @@ u16 hpi_adapter_debug_read(const struct hpi_hsubsys *ph_subsys,
 	hm.adapter_index = adapter_index;
 	hm.adapter_index = adapter_index;
 	hm.u.ax.debug_read.dsp_address = dsp_address;
 	hm.u.ax.debug_read.dsp_address = dsp_address;
 
 
-	if (*count_bytes > sizeof(hr.u.bytes))
+	if (*count_bytes > (int)sizeof(hr.u.bytes))
 		*count_bytes = sizeof(hr.u.bytes);
 		*count_bytes = sizeof(hr.u.bytes);
 
 
 	hm.u.ax.debug_read.count_bytes = *count_bytes;
 	hm.u.ax.debug_read.count_bytes = *count_bytes;
@@ -976,6 +976,7 @@ u16 hpi_outstream_ancillary_read(const struct hpi_hsubsys *ph_subsys,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		HPI_OSTREAM_ANC_READ);
 		HPI_OSTREAM_ANC_READ);
 	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_outstream, &hm.adapter_index, &hm.obj_index);
@@ -1581,6 +1582,7 @@ u16 hpi_control_param_set(const struct hpi_hsubsys *ph_subsys,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_SET_STATE);
 		HPI_CONTROL_SET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -1591,6 +1593,22 @@ u16 hpi_control_param_set(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 	return hr.error;
 }
 }
 
 
+static u16 hpi_control_log_set2(u32 h_control, u16 attrib, short sv0,
+	short sv1)
+{
+	struct hpi_message hm;
+	struct hpi_response hr;
+
+	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
+		HPI_CONTROL_SET_STATE);
+	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	hm.u.c.attribute = attrib;
+	hm.u.c.an_log_value[0] = sv0;
+	hm.u.c.an_log_value[1] = sv1;
+	hpi_send_recv(&hm, &hr);
+	return hr.error;
+}
+
 static
 static
 u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
 	const u32 h_control, const u16 attrib, u32 param1, u32 param2,
 	const u32 h_control, const u16 attrib, u32 param1, u32 param2,
@@ -1598,6 +1616,7 @@ u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
 		HPI_CONTROL_GET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -1605,8 +1624,8 @@ u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
 	hm.u.c.param1 = param1;
 	hm.u.c.param1 = param1;
 	hm.u.c.param2 = param2;
 	hm.u.c.param2 = param2;
 	hpi_send_recv(&hm, &hr);
 	hpi_send_recv(&hm, &hr);
-	if (pparam1)
-		*pparam1 = hr.u.c.param1;
+
+	*pparam1 = hr.u.c.param1;
 	if (pparam2)
 	if (pparam2)
 		*pparam2 = hr.u.c.param2;
 		*pparam2 = hr.u.c.param2;
 
 
@@ -1617,10 +1636,23 @@ u16 hpi_control_param_get(const struct hpi_hsubsys *ph_subsys,
 		hpi_control_param_get(s, h, a, 0, 0, p1, NULL)
 		hpi_control_param_get(s, h, a, 0, 0, p1, NULL)
 #define hpi_control_param2_get(s, h, a, p1, p2) \
 #define hpi_control_param2_get(s, h, a, p1, p2) \
 		hpi_control_param_get(s, h, a, 0, 0, p1, p2)
 		hpi_control_param_get(s, h, a, 0, 0, p1, p2)
-#define hpi_control_ex_param1_get(s, h, a, p1) \
-		hpi_control_ex_param_get(s, h, a, 0, 0, p1, NULL)
-#define hpi_control_ex_param2_get(s, h, a, p1, p2) \
-		hpi_control_ex_param_get(s, h, a, 0, 0, p1, p2)
+
+static u16 hpi_control_log_get2(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, u16 attrib, short *sv0, short *sv1)
+{
+	struct hpi_message hm;
+	struct hpi_response hr;
+	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
+		HPI_CONTROL_GET_STATE);
+	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
+	hm.u.c.attribute = attrib;
+
+	hpi_send_recv(&hm, &hr);
+	*sv0 = hr.u.c.an_log_value[0];
+	if (sv1)
+		*sv1 = hr.u.c.an_log_value[1];
+	return hr.error;
+}
 
 
 static
 static
 u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys,
@@ -1629,6 +1661,7 @@ u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_INFO);
 		HPI_CONTROL_GET_INFO);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -1643,9 +1676,8 @@ u16 hpi_control_query(const struct hpi_hsubsys *ph_subsys,
 	return hr.error;
 	return hr.error;
 }
 }
 
 
-static u16 hpi_control_get_string(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_control, const u16 attribute, char *psz_string,
-	const u32 string_length)
+static u16 hpi_control_get_string(const u32 h_control, const u16 attribute,
+	char *psz_string, const u32 string_length)
 {
 {
 	unsigned int sub_string_index = 0, j = 0;
 	unsigned int sub_string_index = 0, j = 0;
 	char c = 0;
 	char c = 0;
@@ -1916,6 +1948,7 @@ u16 hpi_cobranet_hmi_write(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
 		HPI_CONTROL_SET_STATE);
 		HPI_CONTROL_SET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -1941,6 +1974,7 @@ u16 hpi_cobranet_hmi_read(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
 		HPI_CONTROL_GET_STATE);
 		HPI_CONTROL_GET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -1980,6 +2014,7 @@ u16 hpi_cobranet_hmi_get_status(const struct hpi_hsubsys *ph_subsys,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROLEX,
 		HPI_CONTROL_GET_STATE);
 		HPI_CONTROL_GET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2006,6 +2041,7 @@ u16 hpi_cobranet_getI_paddress(const struct hpi_hsubsys *ph_subsys,
 	u32 byte_count;
 	u32 byte_count;
 	u32 iP;
 	u32 iP;
 	u16 error;
 	u16 error;
+
 	error = hpi_cobranet_hmi_read(ph_subsys, h_control,
 	error = hpi_cobranet_hmi_read(ph_subsys, h_control,
 		HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, &byte_count,
 		HPI_COBRANET_HMI_cobra_ip_mon_currentIP, 4, &byte_count,
 		(u8 *)&iP);
 		(u8 *)&iP);
@@ -2082,6 +2118,7 @@ u16 hpi_cobranet_getMA_caddress(const struct hpi_hsubsys *ph_subsys,
 	u32 byte_count;
 	u32 byte_count;
 	u16 error;
 	u16 error;
 	u32 mAC;
 	u32 mAC;
+
 	error = hpi_cobranet_hmi_read(ph_subsys, h_control,
 	error = hpi_cobranet_hmi_read(ph_subsys, h_control,
 		HPI_COBRANET_HMI_cobra_if_phy_address, 4, &byte_count,
 		HPI_COBRANET_HMI_cobra_if_phy_address, 4, &byte_count,
 		(u8 *)&mAC);
 		(u8 *)&mAC);
@@ -2103,53 +2140,111 @@ u16 hpi_cobranet_getMA_caddress(const struct hpi_hsubsys *ph_subsys,
 	return error;
 	return error;
 }
 }
 
 
-u16 hpi_compander_set(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 attack, u16 decay, short ratio100, short threshold0_01dB,
-	short makeup_gain0_01dB)
+u16 hpi_compander_set_enable(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, u32 enable)
+{
+	return hpi_control_param_set(ph_subsys, h_control, HPI_GENERIC_ENABLE,
+		enable, 0);
+}
+
+u16 hpi_compander_get_enable(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, u32 *enable)
+{
+	return hpi_control_param1_get(ph_subsys, h_control,
+		HPI_GENERIC_ENABLE, enable);
+}
+
+u16 hpi_compander_set_makeup_gain(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, short makeup_gain0_01dB)
+{
+	return hpi_control_log_set2(h_control, HPI_COMPANDER_MAKEUPGAIN,
+		makeup_gain0_01dB, 0);
+}
+
+u16 hpi_compander_get_makeup_gain(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, short *makeup_gain0_01dB)
+{
+	return hpi_control_log_get2(ph_subsys, h_control,
+		HPI_COMPANDER_MAKEUPGAIN, makeup_gain0_01dB, NULL);
+}
+
+u16 hpi_compander_set_attack_time_constant(const struct hpi_hsubsys
+	*ph_subsys, u32 h_control, unsigned int index, u32 attack)
+{
+	return hpi_control_param_set(ph_subsys, h_control,
+		HPI_COMPANDER_ATTACK, attack, index);
+}
+
+u16 hpi_compander_get_attack_time_constant(const struct hpi_hsubsys
+	*ph_subsys, u32 h_control, unsigned int index, u32 *attack)
+{
+	return hpi_control_param_get(ph_subsys, h_control,
+		HPI_COMPANDER_ATTACK, 0, index, attack, NULL);
+}
+
+u16 hpi_compander_set_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, unsigned int index, u32 decay)
+{
+	return hpi_control_param_set(ph_subsys, h_control,
+		HPI_COMPANDER_DECAY, decay, index);
+}
+
+u16 hpi_compander_get_decay_time_constant(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, unsigned int index, u32 *decay)
+{
+	return hpi_control_param_get(ph_subsys, h_control,
+		HPI_COMPANDER_DECAY, 0, index, decay, NULL);
+
+}
+
+u16 hpi_compander_set_threshold(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, unsigned int index, short threshold0_01dB)
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_SET_STATE);
 		HPI_CONTROL_SET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
-
-	hm.u.c.param1 = attack + ((u32)ratio100 << 16);
-	hm.u.c.param2 = (decay & 0xFFFFL);
+	hm.u.c.attribute = HPI_COMPANDER_THRESHOLD;
+	hm.u.c.param2 = index;
 	hm.u.c.an_log_value[0] = threshold0_01dB;
 	hm.u.c.an_log_value[0] = threshold0_01dB;
-	hm.u.c.an_log_value[1] = makeup_gain0_01dB;
-	hm.u.c.attribute = HPI_COMPANDER_PARAMS;
 
 
 	hpi_send_recv(&hm, &hr);
 	hpi_send_recv(&hm, &hr);
 
 
 	return hr.error;
 	return hr.error;
 }
 }
 
 
-u16 hpi_compander_get(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 *pw_attack, u16 *pw_decay, short *pw_ratio100,
-	short *pn_threshold0_01dB, short *pn_makeup_gain0_01dB)
+u16 hpi_compander_get_threshold(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, unsigned int index, short *threshold0_01dB)
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
 		HPI_CONTROL_GET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
-	hm.u.c.attribute = HPI_COMPANDER_PARAMS;
+	hm.u.c.attribute = HPI_COMPANDER_THRESHOLD;
+	hm.u.c.param2 = index;
 
 
 	hpi_send_recv(&hm, &hr);
 	hpi_send_recv(&hm, &hr);
+	*threshold0_01dB = hr.u.c.an_log_value[0];
 
 
-	if (pw_attack)
-		*pw_attack = (short)(hr.u.c.param1 & 0xFFFF);
-	if (pw_decay)
-		*pw_decay = (short)(hr.u.c.param2 & 0xFFFF);
-	if (pw_ratio100)
-		*pw_ratio100 = (short)(hr.u.c.param1 >> 16);
+	return hr.error;
+}
 
 
-	if (pn_threshold0_01dB)
-		*pn_threshold0_01dB = hr.u.c.an_log_value[0];
-	if (pn_makeup_gain0_01dB)
-		*pn_makeup_gain0_01dB = hr.u.c.an_log_value[1];
+u16 hpi_compander_set_ratio(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, u32 index, u32 ratio100)
+{
+	return hpi_control_param_set(ph_subsys, h_control,
+		HPI_COMPANDER_RATIO, ratio100, index);
+}
 
 
-	return hr.error;
+u16 hpi_compander_get_ratio(const struct hpi_hsubsys *ph_subsys,
+	u32 h_control, u32 index, u32 *ratio100)
+{
+	return hpi_control_param_get(ph_subsys, h_control,
+		HPI_COMPANDER_RATIO, 0, index, ratio100, NULL);
 }
 }
 
 
 u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
@@ -2157,6 +2252,7 @@ u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
 		HPI_CONTROL_GET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2181,37 +2277,16 @@ u16 hpi_level_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	short an_gain0_01dB[HPI_MAX_CHANNELS]
 	short an_gain0_01dB[HPI_MAX_CHANNELS]
 	)
 	)
 {
 {
-	struct hpi_message hm;
-	struct hpi_response hr;
-
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
-		HPI_CONTROL_SET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
-	memcpy(hm.u.c.an_log_value, an_gain0_01dB,
-		sizeof(short) * HPI_MAX_CHANNELS);
-	hm.u.c.attribute = HPI_LEVEL_GAIN;
-
-	hpi_send_recv(&hm, &hr);
-
-	return hr.error;
+	return hpi_control_log_set2(h_control, HPI_LEVEL_GAIN,
+		an_gain0_01dB[0], an_gain0_01dB[1]);
 }
 }
 
 
 u16 hpi_level_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 u16 hpi_level_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	short an_gain0_01dB[HPI_MAX_CHANNELS]
 	short an_gain0_01dB[HPI_MAX_CHANNELS]
 	)
 	)
 {
 {
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
-		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
-	hm.u.c.attribute = HPI_LEVEL_GAIN;
-
-	hpi_send_recv(&hm, &hr);
-
-	memcpy(an_gain0_01dB, hr.u.c.an_log_value,
-		sizeof(short) * HPI_MAX_CHANNELS);
-	return hr.error;
+	return hpi_control_log_get2(ph_subsys, h_control, HPI_LEVEL_GAIN,
+		&an_gain0_01dB[0], &an_gain0_01dB[1]);
 }
 }
 
 
 u16 hpi_meter_query_channels(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_meter_query_channels(const struct hpi_hsubsys *ph_subsys,
@@ -2413,6 +2488,7 @@ u16 hpi_parametricEQ__get_band(const struct hpi_hsubsys *ph_subsys,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
 		HPI_CONTROL_GET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2439,6 +2515,7 @@ u16 hpi_parametricEQ__set_band(const struct hpi_hsubsys *ph_subsys,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_SET_STATE);
 		HPI_CONTROL_SET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2460,6 +2537,7 @@ u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
 		HPI_CONTROL_GET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2623,8 +2701,8 @@ u16 hpi_tone_detector_get_frequency(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tone_detector_get_state(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tone_detector_get_state(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, u32 *state)
 	u32 h_control, u32 *state)
 {
 {
-	return hpi_control_param_get(ph_subsys, h_control,
-		HPI_TONEDETECTOR_STATE, 0, 0, (u32 *)state, NULL);
+	return hpi_control_param1_get(ph_subsys, h_control,
+		HPI_TONEDETECTOR_STATE, state);
 }
 }
 
 
 u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
@@ -2637,8 +2715,8 @@ u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tone_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tone_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, u32 *enable)
 	u32 h_control, u32 *enable)
 {
 {
-	return hpi_control_param_get(ph_subsys, h_control, HPI_GENERIC_ENABLE,
-		0, 0, (u32 *)enable, NULL);
+	return hpi_control_param1_get(ph_subsys, h_control,
+		HPI_GENERIC_ENABLE, enable);
 }
 }
 
 
 u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
@@ -2651,8 +2729,8 @@ u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tone_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tone_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, u32 *event_enable)
 	u32 h_control, u32 *event_enable)
 {
 {
-	return hpi_control_param_get(ph_subsys, h_control,
-		HPI_GENERIC_EVENT_ENABLE, 0, 0, (u32 *)event_enable, NULL);
+	return hpi_control_param1_get(ph_subsys, h_control,
+		HPI_GENERIC_EVENT_ENABLE, event_enable);
 }
 }
 
 
 u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
@@ -2665,15 +2743,15 @@ u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tone_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tone_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, int *threshold)
 	u32 h_control, int *threshold)
 {
 {
-	return hpi_control_param_get(ph_subsys, h_control,
-		HPI_TONEDETECTOR_THRESHOLD, 0, 0, (u32 *)threshold, NULL);
+	return hpi_control_param1_get(ph_subsys, h_control,
+		HPI_TONEDETECTOR_THRESHOLD, (u32 *)threshold);
 }
 }
 
 
 u16 hpi_silence_detector_get_state(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_silence_detector_get_state(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, u32 *state)
 	u32 h_control, u32 *state)
 {
 {
-	return hpi_control_param_get(ph_subsys, h_control,
-		HPI_SILENCEDETECTOR_STATE, 0, 0, (u32 *)state, NULL);
+	return hpi_control_param1_get(ph_subsys, h_control,
+		HPI_SILENCEDETECTOR_STATE, state);
 }
 }
 
 
 u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
@@ -2686,50 +2764,50 @@ u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_silence_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_silence_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, u32 *enable)
 	u32 h_control, u32 *enable)
 {
 {
-	return hpi_control_param_get(ph_subsys, h_control, HPI_GENERIC_ENABLE,
-		0, 0, (u32 *)enable, NULL);
+	return hpi_control_param1_get(ph_subsys, h_control,
+		HPI_GENERIC_ENABLE, enable);
 }
 }
 
 
 u16 hpi_silence_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_silence_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, u32 event_enable)
 	u32 h_control, u32 event_enable)
 {
 {
 	return hpi_control_param_set(ph_subsys, h_control,
 	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_GENERIC_EVENT_ENABLE, (u32)event_enable, 0);
+		HPI_GENERIC_EVENT_ENABLE, event_enable, 0);
 }
 }
 
 
 u16 hpi_silence_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_silence_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, u32 *event_enable)
 	u32 h_control, u32 *event_enable)
 {
 {
-	return hpi_control_param_get(ph_subsys, h_control,
-		HPI_GENERIC_EVENT_ENABLE, 0, 0, (u32 *)event_enable, NULL);
+	return hpi_control_param1_get(ph_subsys, h_control,
+		HPI_GENERIC_EVENT_ENABLE, event_enable);
 }
 }
 
 
 u16 hpi_silence_detector_set_delay(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_silence_detector_set_delay(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, u32 delay)
 	u32 h_control, u32 delay)
 {
 {
 	return hpi_control_param_set(ph_subsys, h_control,
 	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_SILENCEDETECTOR_DELAY, (u32)delay, 0);
+		HPI_SILENCEDETECTOR_DELAY, delay, 0);
 }
 }
 
 
 u16 hpi_silence_detector_get_delay(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_silence_detector_get_delay(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, u32 *delay)
 	u32 h_control, u32 *delay)
 {
 {
-	return hpi_control_param_get(ph_subsys, h_control,
-		HPI_SILENCEDETECTOR_DELAY, 0, 0, (u32 *)delay, NULL);
+	return hpi_control_param1_get(ph_subsys, h_control,
+		HPI_SILENCEDETECTOR_DELAY, delay);
 }
 }
 
 
 u16 hpi_silence_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_silence_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, int threshold)
 	u32 h_control, int threshold)
 {
 {
 	return hpi_control_param_set(ph_subsys, h_control,
 	return hpi_control_param_set(ph_subsys, h_control,
-		HPI_SILENCEDETECTOR_THRESHOLD, (u32)threshold, 0);
+		HPI_SILENCEDETECTOR_THRESHOLD, threshold, 0);
 }
 }
 
 
 u16 hpi_silence_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_silence_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, int *threshold)
 	u32 h_control, int *threshold)
 {
 {
-	return hpi_control_param_get(ph_subsys, h_control,
-		HPI_SILENCEDETECTOR_THRESHOLD, 0, 0, (u32 *)threshold, NULL);
+	return hpi_control_param1_get(ph_subsys, h_control,
+		HPI_SILENCEDETECTOR_THRESHOLD, (u32 *)threshold);
 }
 }
 
 
 u16 hpi_tuner_query_band(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tuner_query_band(const struct hpi_hsubsys *ph_subsys,
@@ -2822,6 +2900,7 @@ u16 hpi_tuner_getRF_level(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
 		HPI_CONTROL_GET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2838,6 +2917,7 @@ u16 hpi_tuner_get_rawRF_level(const struct hpi_hsubsys *ph_subsys,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
 		HPI_CONTROL_GET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2894,14 +2974,14 @@ u16 hpi_tuner_get_program(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 u16 hpi_tuner_get_hd_radio_dsp_version(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tuner_get_hd_radio_dsp_version(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, char *psz_dsp_version, const u32 string_size)
 	u32 h_control, char *psz_dsp_version, const u32 string_size)
 {
 {
-	return hpi_control_get_string(ph_subsys, h_control,
+	return hpi_control_get_string(h_control,
 		HPI_TUNER_HDRADIO_DSP_VERSION, psz_dsp_version, string_size);
 		HPI_TUNER_HDRADIO_DSP_VERSION, psz_dsp_version, string_size);
 }
 }
 
 
 u16 hpi_tuner_get_hd_radio_sdk_version(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tuner_get_hd_radio_sdk_version(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, char *psz_sdk_version, const u32 string_size)
 	u32 h_control, char *psz_sdk_version, const u32 string_size)
 {
 {
-	return hpi_control_get_string(ph_subsys, h_control,
+	return hpi_control_get_string(h_control,
 		HPI_TUNER_HDRADIO_SDK_VERSION, psz_sdk_version, string_size);
 		HPI_TUNER_HDRADIO_SDK_VERSION, psz_sdk_version, string_size);
 }
 }
 
 
@@ -2942,15 +3022,15 @@ u16 hpi_tuner_get_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, u32 *pquality)
 	u32 h_control, u32 *pquality)
 {
 {
-	return hpi_control_param_get(ph_subsys, h_control,
-		HPI_TUNER_HDRADIO_SIGNAL_QUALITY, 0, 0, pquality, NULL);
+	return hpi_control_param1_get(ph_subsys, h_control,
+		HPI_TUNER_HDRADIO_SIGNAL_QUALITY, pquality);
 }
 }
 
 
 u16 hpi_tuner_get_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tuner_get_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, u32 *pblend)
 	u32 h_control, u32 *pblend)
 {
 {
-	return hpi_control_param_get(ph_subsys, h_control,
-		HPI_TUNER_HDRADIO_BLEND, 0, 0, pblend, NULL);
+	return hpi_control_param1_get(ph_subsys, h_control,
+		HPI_TUNER_HDRADIO_BLEND, pblend);
 }
 }
 
 
 u16 hpi_tuner_set_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_tuner_set_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
@@ -2965,6 +3045,7 @@ u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
 		HPI_CONTROL_GET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -2981,43 +3062,43 @@ u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 u16 HPI_PAD__get_channel_name(const struct hpi_hsubsys *ph_subsys,
 u16 HPI_PAD__get_channel_name(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, char *psz_string, const u32 data_length)
 	u32 h_control, char *psz_string, const u32 data_length)
 {
 {
-	return hpi_control_get_string(ph_subsys, h_control,
-		HPI_PAD_CHANNEL_NAME, psz_string, data_length);
+	return hpi_control_get_string(h_control, HPI_PAD_CHANNEL_NAME,
+		psz_string, data_length);
 }
 }
 
 
 u16 HPI_PAD__get_artist(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 u16 HPI_PAD__get_artist(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	char *psz_string, const u32 data_length)
 	char *psz_string, const u32 data_length)
 {
 {
-	return hpi_control_get_string(ph_subsys, h_control, HPI_PAD_ARTIST,
-		psz_string, data_length);
+	return hpi_control_get_string(h_control, HPI_PAD_ARTIST, psz_string,
+		data_length);
 }
 }
 
 
 u16 HPI_PAD__get_title(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 u16 HPI_PAD__get_title(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	char *psz_string, const u32 data_length)
 	char *psz_string, const u32 data_length)
 {
 {
-	return hpi_control_get_string(ph_subsys, h_control, HPI_PAD_TITLE,
-		psz_string, data_length);
+	return hpi_control_get_string(h_control, HPI_PAD_TITLE, psz_string,
+		data_length);
 }
 }
 
 
 u16 HPI_PAD__get_comment(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 u16 HPI_PAD__get_comment(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	char *psz_string, const u32 data_length)
 	char *psz_string, const u32 data_length)
 {
 {
-	return hpi_control_get_string(ph_subsys, h_control, HPI_PAD_COMMENT,
-		psz_string, data_length);
+	return hpi_control_get_string(h_control, HPI_PAD_COMMENT, psz_string,
+		data_length);
 }
 }
 
 
 u16 HPI_PAD__get_program_type(const struct hpi_hsubsys *ph_subsys,
 u16 HPI_PAD__get_program_type(const struct hpi_hsubsys *ph_subsys,
 	u32 h_control, u32 *ppTY)
 	u32 h_control, u32 *ppTY)
 {
 {
-	return hpi_control_param_get(ph_subsys, h_control,
-		HPI_PAD_PROGRAM_TYPE, 0, 0, ppTY, NULL);
+	return hpi_control_param1_get(ph_subsys, h_control,
+		HPI_PAD_PROGRAM_TYPE, ppTY);
 }
 }
 
 
 u16 HPI_PAD__get_rdsPI(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 u16 HPI_PAD__get_rdsPI(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	u32 *ppI)
 	u32 *ppI)
 {
 {
-	return hpi_control_param_get(ph_subsys, h_control, HPI_PAD_PROGRAM_ID,
-		0, 0, ppI, NULL);
+	return hpi_control_param1_get(ph_subsys, h_control,
+		HPI_PAD_PROGRAM_ID, ppI);
 }
 }
 
 
 u16 hpi_volume_query_channels(const struct hpi_hsubsys *ph_subsys,
 u16 hpi_volume_query_channels(const struct hpi_hsubsys *ph_subsys,
@@ -3031,36 +3112,16 @@ u16 hpi_volume_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	short an_log_gain[HPI_MAX_CHANNELS]
 	short an_log_gain[HPI_MAX_CHANNELS]
 	)
 	)
 {
 {
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
-		HPI_CONTROL_SET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
-	memcpy(hm.u.c.an_log_value, an_log_gain,
-		sizeof(short) * HPI_MAX_CHANNELS);
-	hm.u.c.attribute = HPI_VOLUME_GAIN;
-
-	hpi_send_recv(&hm, &hr);
-
-	return hr.error;
+	return hpi_control_log_set2(h_control, HPI_VOLUME_GAIN,
+		an_log_gain[0], an_log_gain[1]);
 }
 }
 
 
 u16 hpi_volume_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 u16 hpi_volume_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 	short an_log_gain[HPI_MAX_CHANNELS]
 	short an_log_gain[HPI_MAX_CHANNELS]
 	)
 	)
 {
 {
-	struct hpi_message hm;
-	struct hpi_response hr;
-	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
-		HPI_CONTROL_GET_STATE);
-	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
-	hm.u.c.attribute = HPI_VOLUME_GAIN;
-
-	hpi_send_recv(&hm, &hr);
-
-	memcpy(an_log_gain, hr.u.c.an_log_value,
-		sizeof(short) * HPI_MAX_CHANNELS);
-	return hr.error;
+	return hpi_control_log_get2(ph_subsys, h_control, HPI_VOLUME_GAIN,
+		&an_log_gain[0], &an_log_gain[1]);
 }
 }
 
 
 u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
@@ -3068,6 +3129,7 @@ u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_GET_STATE);
 		HPI_CONTROL_GET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -3094,6 +3156,7 @@ u16 hpi_volume_auto_fade_profile(const struct hpi_hsubsys *ph_subsys,
 {
 {
 	struct hpi_message hm;
 	struct hpi_message hm;
 	struct hpi_response hr;
 	struct hpi_response hr;
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_CONTROL,
 		HPI_CONTROL_SET_STATE);
 		HPI_CONTROL_SET_STATE);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
 	u32TOINDEXES(h_control, &hm.adapter_index, &hm.obj_index);
@@ -3170,43 +3233,42 @@ static size_t entity_type_to_size[LAST_ENTITY_TYPE] = {
 	6 * sizeof(char),
 	6 * sizeof(char),
 };
 };
 
 
-inline size_t hpi_entity_size(struct hpi_entity *entity_ptr)
+static inline size_t hpi_entity_size(struct hpi_entity *entity_ptr)
 {
 {
 	return entity_ptr->header.size;
 	return entity_ptr->header.size;
 }
 }
 
 
-inline size_t hpi_entity_header_size(struct hpi_entity *entity_ptr)
+static inline size_t hpi_entity_header_size(struct hpi_entity *entity_ptr)
 {
 {
 	return sizeof(entity_ptr->header);
 	return sizeof(entity_ptr->header);
 }
 }
 
 
-inline size_t hpi_entity_value_size(struct hpi_entity *entity_ptr)
+static inline size_t hpi_entity_value_size(struct hpi_entity *entity_ptr)
 {
 {
 	return hpi_entity_size(entity_ptr) -
 	return hpi_entity_size(entity_ptr) -
 		hpi_entity_header_size(entity_ptr);
 		hpi_entity_header_size(entity_ptr);
 }
 }
 
 
-inline size_t hpi_entity_item_count(struct hpi_entity *entity_ptr)
+static inline size_t hpi_entity_item_count(struct hpi_entity *entity_ptr)
 {
 {
 	return hpi_entity_value_size(entity_ptr) /
 	return hpi_entity_value_size(entity_ptr) /
 		entity_type_to_size[entity_ptr->header.type];
 		entity_type_to_size[entity_ptr->header.type];
 }
 }
 
 
-inline struct hpi_entity *hpi_entity_ptr_to_next(struct hpi_entity
+static inline struct hpi_entity *hpi_entity_ptr_to_next(struct hpi_entity
 	*entity_ptr)
 	*entity_ptr)
 {
 {
-	return (void *)(((uint8_t *) entity_ptr) +
-		hpi_entity_size(entity_ptr));
+	return (void *)(((u8 *)entity_ptr) + hpi_entity_size(entity_ptr));
 }
 }
 
 
-inline u16 hpi_entity_check_type(const enum e_entity_type t)
+static inline u16 hpi_entity_check_type(const enum e_entity_type t)
 {
 {
 	if (t >= 0 && t < STR_TYPE_FIELD_MAX)
 	if (t >= 0 && t < STR_TYPE_FIELD_MAX)
 		return 0;
 		return 0;
 	return HPI_ERROR_ENTITY_TYPE_INVALID;
 	return HPI_ERROR_ENTITY_TYPE_INVALID;
 }
 }
 
 
-inline u16 hpi_entity_check_role(const enum e_entity_role r)
+static inline u16 hpi_entity_check_role(const enum e_entity_role r)
 {
 {
 	if (r >= 0 && r < STR_ROLE_FIELD_MAX)
 	if (r >= 0 && r < STR_ROLE_FIELD_MAX)
 		return 0;
 		return 0;
@@ -3624,6 +3686,7 @@ u16 hpi_async_event_wait(const struct hpi_hsubsys *ph_subsys, u32 h_async,
 	u16 maximum_events, struct hpi_async_event *p_events,
 	u16 maximum_events, struct hpi_async_event *p_events,
 	u16 *pw_number_returned)
 	u16 *pw_number_returned)
 {
 {
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 1 - 1
sound/pci/asihpi/hpimsgx.c

@@ -741,7 +741,7 @@ static void HPIMSGX__reset(u16 adapter_index)
 		hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM,
 		hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM,
 			HPI_SUBSYS_FIND_ADAPTERS, 0);
 			HPI_SUBSYS_FIND_ADAPTERS, 0);
 		memcpy(&gRESP_HPI_SUBSYS_FIND_ADAPTERS, &hr,
 		memcpy(&gRESP_HPI_SUBSYS_FIND_ADAPTERS, &hr,
-			sizeof(&gRESP_HPI_SUBSYS_FIND_ADAPTERS));
+			sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
 
 
 		for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) {
 		for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) {
 
 

+ 14 - 7
sound/pci/asihpi/hpioctl.c

@@ -121,11 +121,17 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg;
 	phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg;
 
 
 	/* Read the message and response pointers from user space.  */
 	/* Read the message and response pointers from user space.  */
-	get_user(puhm, &phpi_ioctl_data->phm);
-	get_user(puhr, &phpi_ioctl_data->phr);
+	if (get_user(puhm, &phpi_ioctl_data->phm) ||
+	    get_user(puhr, &phpi_ioctl_data->phr)) {
+		err = -EFAULT;
+		goto out;
+	}
 
 
 	/* Now read the message size and data from user space.  */
 	/* Now read the message size and data from user space.  */
-	get_user(hm->h.size, (u16 __user *)puhm);
+	if (get_user(hm->h.size, (u16 __user *)puhm)) {
+		err = -EFAULT;
+		goto out;
+	}
 	if (hm->h.size > sizeof(*hm))
 	if (hm->h.size > sizeof(*hm))
 		hm->h.size = sizeof(*hm);
 		hm->h.size = sizeof(*hm);
 
 
@@ -138,7 +144,10 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		goto out;
 		goto out;
 	}
 	}
 
 
-	get_user(res_max_size, (u16 __user *)puhr);
+	if (get_user(res_max_size, (u16 __user *)puhr)) {
+		err = -EFAULT;
+		goto out;
+	}
 	/* printk(KERN_INFO "user response size %d\n", res_max_size); */
 	/* printk(KERN_INFO "user response size %d\n", res_max_size); */
 	if (res_max_size < sizeof(struct hpi_response_header)) {
 	if (res_max_size < sizeof(struct hpi_response_header)) {
 		HPI_DEBUG_LOG(WARNING, "small res size %d\n", res_max_size);
 		HPI_DEBUG_LOG(WARNING, "small res size %d\n", res_max_size);
@@ -464,9 +473,7 @@ void __init asihpi_init(void)
 
 
 	memset(adapters, 0, sizeof(adapters));
 	memset(adapters, 0, sizeof(adapters));
 
 
-	printk(KERN_INFO "ASIHPI driver %d.%02d.%02d\n",
-		HPI_VER_MAJOR(HPI_VER), HPI_VER_MINOR(HPI_VER),
-		HPI_VER_RELEASE(HPI_VER));
+	printk(KERN_INFO "ASIHPI driver " HPI_VER_STRING "\n");
 
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
 		HPI_SUBSYS_DRIVER_LOAD);
 		HPI_SUBSYS_DRIVER_LOAD);

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

@@ -2250,6 +2250,8 @@ static int snd_echo_resume(struct pci_dev *pci)
 	DE_INIT(("resume start\n"));
 	DE_INIT(("resume start\n"));
 	pci_restore_state(pci);
 	pci_restore_state(pci);
 	commpage_bak = kmalloc(sizeof(struct echoaudio), GFP_KERNEL);
 	commpage_bak = kmalloc(sizeof(struct echoaudio), GFP_KERNEL);
+	if (commpage_bak == NULL)
+		return -ENOMEM;
 	commpage = chip->comm_page;
 	commpage = chip->comm_page;
 	memcpy(commpage_bak, commpage, sizeof(struct comm_page));
 	memcpy(commpage_bak, commpage, sizeof(struct comm_page));
 
 

+ 6 - 4
sound/pci/hda/hda_codec.c

@@ -733,15 +733,17 @@ static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
 	total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
 	total_nodes = snd_hda_get_sub_nodes(codec, AC_NODE_ROOT, &nid);
 	for (i = 0; i < total_nodes; i++, nid++) {
 	for (i = 0; i < total_nodes; i++, nid++) {
 		function_id = snd_hda_param_read(codec, nid,
 		function_id = snd_hda_param_read(codec, nid,
-						AC_PAR_FUNCTION_TYPE) & 0xff;
-		switch (function_id) {
+						AC_PAR_FUNCTION_TYPE);
+		switch (function_id & 0xff) {
 		case AC_GRP_AUDIO_FUNCTION:
 		case AC_GRP_AUDIO_FUNCTION:
 			codec->afg = nid;
 			codec->afg = nid;
-			codec->function_id = function_id;
+			codec->afg_function_id = function_id & 0xff;
+			codec->afg_unsol = (function_id >> 8) & 1;
 			break;
 			break;
 		case AC_GRP_MODEM_FUNCTION:
 		case AC_GRP_MODEM_FUNCTION:
 			codec->mfg = nid;
 			codec->mfg = nid;
-			codec->function_id = function_id;
+			codec->mfg_function_id = function_id & 0xff;
+			codec->mfg_unsol = (function_id >> 8) & 1;
 			break;
 			break;
 		default:
 		default:
 			break;
 			break;

+ 4 - 1
sound/pci/hda/hda_codec.h

@@ -784,7 +784,10 @@ struct hda_codec {
 	hda_nid_t mfg;	/* MFG node id */
 	hda_nid_t mfg;	/* MFG node id */
 
 
 	/* ids */
 	/* ids */
-	u32 function_id;
+	u8 afg_function_id;
+	u8 mfg_function_id;
+	u8 afg_unsol;
+	u8 mfg_unsol;
 	u32 vendor_id;
 	u32 vendor_id;
 	u32 subsystem_id;
 	u32 subsystem_id;
 	u32 revision_id;
 	u32 revision_id;

+ 6 - 1
sound/pci/hda/hda_proc.c

@@ -557,7 +557,12 @@ static void print_codec_info(struct snd_info_entry *entry,
 	else
 	else
 		snd_iprintf(buffer, "Not Set\n");
 		snd_iprintf(buffer, "Not Set\n");
 	snd_iprintf(buffer, "Address: %d\n", codec->addr);
 	snd_iprintf(buffer, "Address: %d\n", codec->addr);
-	snd_iprintf(buffer, "Function Id: 0x%x\n", codec->function_id);
+	if (codec->afg)
+		snd_iprintf(buffer, "AFG Function Id: 0x%x (unsol %u)\n",
+			codec->afg_function_id, codec->afg_unsol);
+	if (codec->mfg)
+		snd_iprintf(buffer, "MFG Function Id: 0x%x (unsol %u)\n",
+			codec->mfg_function_id, codec->mfg_unsol);
 	snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id);
 	snd_iprintf(buffer, "Vendor Id: 0x%08x\n", codec->vendor_id);
 	snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id);
 	snd_iprintf(buffer, "Subsystem Id: 0x%08x\n", codec->subsystem_id);
 	snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);
 	snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id);

+ 12 - 6
sound/pci/riptide/riptide.c

@@ -97,6 +97,7 @@
 #include <linux/gameport.h>
 #include <linux/gameport.h>
 #include <linux/device.h>
 #include <linux/device.h>
 #include <linux/firmware.h>
 #include <linux/firmware.h>
+#include <linux/kernel.h>
 #include <asm/io.h>
 #include <asm/io.h>
 #include <sound/core.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/info.h>
@@ -667,13 +668,12 @@ static u32 atoh(const unsigned char *in, unsigned int len)
 	unsigned char c;
 	unsigned char c;
 
 
 	while (len) {
 	while (len) {
+		int value;
+
 		c = in[len - 1];
 		c = in[len - 1];
-		if ((c >= '0') && (c <= '9'))
-			sum += mult * (c - '0');
-		else if ((c >= 'A') && (c <= 'F'))
-			sum += mult * (c - ('A' - 10));
-		else if ((c >= 'a') && (c <= 'f'))
-			sum += mult * (c - ('a' - 10));
+		value = hex_to_bin(c);
+		if (value >= 0)
+			sum += mult * value;
 		mult *= 16;
 		mult *= 16;
 		--len;
 		--len;
 	}
 	}
@@ -1615,7 +1615,10 @@ static int snd_riptide_playback_open(struct snd_pcm_substream *substream)
 
 
 	chip->playback_substream[sub_num] = substream;
 	chip->playback_substream[sub_num] = substream;
 	runtime->hw = snd_riptide_playback;
 	runtime->hw = snd_riptide_playback;
+
 	data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
 	data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
 	data->paths = lbus_play_paths[sub_num];
 	data->paths = lbus_play_paths[sub_num];
 	data->id = play_ids[sub_num];
 	data->id = play_ids[sub_num];
 	data->source = play_sources[sub_num];
 	data->source = play_sources[sub_num];
@@ -1635,7 +1638,10 @@ static int snd_riptide_capture_open(struct snd_pcm_substream *substream)
 
 
 	chip->capture_substream = substream;
 	chip->capture_substream = substream;
 	runtime->hw = snd_riptide_capture;
 	runtime->hw = snd_riptide_capture;
+
 	data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
 	data = kzalloc(sizeof(struct pcmhw), GFP_KERNEL);
+	if (data == NULL)
+		return -ENOMEM;
 	data->paths = lbus_rec_path;
 	data->paths = lbus_rec_path;
 	data->id = PADC;
 	data->id = PADC;
 	data->source = ACLNK2PADC;
 	data->source = ACLNK2PADC;

+ 9 - 7
sound/pci/sis7019.c

@@ -264,11 +264,13 @@ static void sis_update_voice(struct voice *voice)
 		 * if using small periods.
 		 * if using small periods.
 		 *
 		 *
 		 * If we're less than 9 samples behind, we're on target.
 		 * If we're less than 9 samples behind, we're on target.
+		 * Otherwise, shorten the next vperiod by the amount we've
+		 * been delayed.
 		 */
 		 */
 		if (sync > -9)
 		if (sync > -9)
 			voice->vperiod = voice->sync_period_size + 1;
 			voice->vperiod = voice->sync_period_size + 1;
 		else
 		else
-			voice->vperiod = voice->sync_period_size - 4;
+			voice->vperiod = voice->sync_period_size + sync + 10;
 
 
 		if (voice->vperiod < voice->buffer_size) {
 		if (voice->vperiod < voice->buffer_size) {
 			sis_update_sso(voice, voice->vperiod);
 			sis_update_sso(voice, voice->vperiod);
@@ -736,7 +738,7 @@ static void sis_prepare_timing_voice(struct voice *voice,
 	period_size = buffer_size;
 	period_size = buffer_size;
 
 
 	/* Initially, we want to interrupt just a bit behind the end of
 	/* Initially, we want to interrupt just a bit behind the end of
-	 * the period we're clocking out. 10 samples seems to give a good
+	 * the period we're clocking out. 12 samples seems to give a good
 	 * delay.
 	 * delay.
 	 *
 	 *
 	 * We want to spread our interrupts throughout the virtual period,
 	 * We want to spread our interrupts throughout the virtual period,
@@ -747,7 +749,7 @@ static void sis_prepare_timing_voice(struct voice *voice,
 	 *
 	 *
 	 * This is all moot if we don't need to use virtual periods.
 	 * This is all moot if we don't need to use virtual periods.
 	 */
 	 */
-	vperiod = runtime->period_size + 10;
+	vperiod = runtime->period_size + 12;
 	if (vperiod > period_size) {
 	if (vperiod > period_size) {
 		u16 tail = vperiod % period_size;
 		u16 tail = vperiod % period_size;
 		u16 quarter_period = period_size / 4;
 		u16 quarter_period = period_size / 4;
@@ -776,7 +778,7 @@ static void sis_prepare_timing_voice(struct voice *voice,
 	 */
 	 */
 	timing->flags |= VOICE_SYNC_TIMING;
 	timing->flags |= VOICE_SYNC_TIMING;
 	timing->sync_base = voice->ctrl_base;
 	timing->sync_base = voice->ctrl_base;
-	timing->sync_cso = runtime->period_size - 1;
+	timing->sync_cso = runtime->period_size;
 	timing->sync_period_size = runtime->period_size;
 	timing->sync_period_size = runtime->period_size;
 	timing->sync_buffer_size = runtime->buffer_size;
 	timing->sync_buffer_size = runtime->buffer_size;
 	timing->period_size = period_size;
 	timing->period_size = period_size;
@@ -1047,7 +1049,7 @@ static int sis_chip_free(struct sis7019 *sis)
 	/* Reset the chip, and disable all interrputs.
 	/* Reset the chip, and disable all interrputs.
 	 */
 	 */
 	outl(SIS_GCR_SOFTWARE_RESET, sis->ioport + SIS_GCR);
 	outl(SIS_GCR_SOFTWARE_RESET, sis->ioport + SIS_GCR);
-	udelay(10);
+	udelay(25);
 	outl(0, sis->ioport + SIS_GCR);
 	outl(0, sis->ioport + SIS_GCR);
 	outl(0, sis->ioport + SIS_GIER);
 	outl(0, sis->ioport + SIS_GIER);
 
 
@@ -1083,7 +1085,7 @@ static int sis_chip_init(struct sis7019 *sis)
 	/* Reset the audio controller
 	/* Reset the audio controller
 	 */
 	 */
 	outl(SIS_GCR_SOFTWARE_RESET, io + SIS_GCR);
 	outl(SIS_GCR_SOFTWARE_RESET, io + SIS_GCR);
-	udelay(10);
+	udelay(25);
 	outl(0, io + SIS_GCR);
 	outl(0, io + SIS_GCR);
 
 
 	/* Get the AC-link semaphore, and reset the codecs
 	/* Get the AC-link semaphore, and reset the codecs
@@ -1096,7 +1098,7 @@ static int sis_chip_init(struct sis7019 *sis)
 		return -EIO;
 		return -EIO;
 
 
 	outl(SIS_AC97_CMD_CODEC_COLD_RESET, io + SIS_AC97_CMD);
 	outl(SIS_AC97_CMD_CODEC_COLD_RESET, io + SIS_AC97_CMD);
-	udelay(10);
+	udelay(250);
 
 
 	count = 0xffff;
 	count = 0xffff;
 	while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count)
 	while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count)

+ 7 - 2
sound/pci/via82xx.c

@@ -85,6 +85,7 @@ static int joystick;
 static int ac97_clock = 48000;
 static int ac97_clock = 48000;
 static char *ac97_quirk;
 static char *ac97_quirk;
 static int dxs_support;
 static int dxs_support;
+static int dxs_init_volume = 31;
 static int nodelay;
 static int nodelay;
 
 
 module_param(index, int, 0444);
 module_param(index, int, 0444);
@@ -103,6 +104,8 @@ module_param(ac97_quirk, charp, 0444);
 MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
 MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
 module_param(dxs_support, int, 0444);
 module_param(dxs_support, int, 0444);
 MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)");
 MODULE_PARM_DESC(dxs_support, "Support for DXS channels (0 = auto, 1 = enable, 2 = disable, 3 = 48k only, 4 = no VRA, 5 = enable any sample rate)");
+module_param(dxs_init_volume, int, 0644);
+MODULE_PARM_DESC(dxs_init_volume, "initial DXS volume (0-31)");
 module_param(nodelay, int, 0444);
 module_param(nodelay, int, 0444);
 MODULE_PARM_DESC(nodelay, "Disable 500ms init delay");
 MODULE_PARM_DESC(nodelay, "Disable 500ms init delay");
 
 
@@ -1245,8 +1248,10 @@ static int snd_via8233_playback_open(struct snd_pcm_substream *substream)
 		return err;
 		return err;
 	stream = viadev->reg_offset / 0x10;
 	stream = viadev->reg_offset / 0x10;
 	if (chip->dxs_controls[stream]) {
 	if (chip->dxs_controls[stream]) {
-		chip->playback_volume[stream][0] = 0;
-		chip->playback_volume[stream][1] = 0;
+		chip->playback_volume[stream][0] =
+				VIA_DXS_MAX_VOLUME - (dxs_init_volume & 31);
+		chip->playback_volume[stream][1] =
+				VIA_DXS_MAX_VOLUME - (dxs_init_volume & 31);
 		chip->dxs_controls[stream]->vd[0].access &=
 		chip->dxs_controls[stream]->vd[0].access &=
 			~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 			~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
 		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |
 		snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE |

+ 4 - 5
sound/sound_core.c

@@ -576,8 +576,6 @@ static int soundcore_open(struct inode *inode, struct file *file)
 	struct sound_unit *s;
 	struct sound_unit *s;
 	const struct file_operations *new_fops = NULL;
 	const struct file_operations *new_fops = NULL;
 
 
-	lock_kernel ();
-
 	chain=unit&0x0F;
 	chain=unit&0x0F;
 	if(chain==4 || chain==5)	/* dsp/audio/dsp16 */
 	if(chain==4 || chain==5)	/* dsp/audio/dsp16 */
 	{
 	{
@@ -630,18 +628,19 @@ static int soundcore_open(struct inode *inode, struct file *file)
 		const struct file_operations *old_fops = file->f_op;
 		const struct file_operations *old_fops = file->f_op;
 		file->f_op = new_fops;
 		file->f_op = new_fops;
 		spin_unlock(&sound_loader_lock);
 		spin_unlock(&sound_loader_lock);
-		if(file->f_op->open)
+
+		if (file->f_op->open)
 			err = file->f_op->open(inode,file);
 			err = file->f_op->open(inode,file);
+
 		if (err) {
 		if (err) {
 			fops_put(file->f_op);
 			fops_put(file->f_op);
 			file->f_op = fops_get(old_fops);
 			file->f_op = fops_get(old_fops);
 		}
 		}
+
 		fops_put(old_fops);
 		fops_put(old_fops);
-		unlock_kernel();
 		return err;
 		return err;
 	}
 	}
 	spin_unlock(&sound_loader_lock);
 	spin_unlock(&sound_loader_lock);
-	unlock_kernel();
 	return -ENODEV;
 	return -ENODEV;
 }
 }
 
 

+ 1 - 1
sound/usb/card.c

@@ -217,7 +217,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
 
 
 	switch (protocol) {
 	switch (protocol) {
 	case UAC_VERSION_1: {
 	case UAC_VERSION_1: {
-		struct uac_ac_header_descriptor_v1 *h1 = control_header;
+		struct uac1_ac_header_descriptor *h1 = control_header;
 
 
 		if (!h1->bInCollection) {
 		if (!h1->bInCollection) {
 			snd_printk(KERN_INFO "skipping empty audio interface (v1)\n");
 			snd_printk(KERN_INFO "skipping empty audio interface (v1)\n");

+ 25 - 34
sound/usb/clock.c

@@ -19,33 +19,19 @@
 
 
 #include <linux/bitops.h>
 #include <linux/bitops.h>
 #include <linux/init.h>
 #include <linux/init.h>
-#include <linux/list.h>
-#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/string.h>
 #include <linux/usb.h>
 #include <linux/usb.h>
-#include <linux/moduleparam.h>
-#include <linux/mutex.h>
 #include <linux/usb/audio.h>
 #include <linux/usb/audio.h>
 #include <linux/usb/audio-v2.h>
 #include <linux/usb/audio-v2.h>
 
 
 #include <sound/core.h>
 #include <sound/core.h>
 #include <sound/info.h>
 #include <sound/info.h>
 #include <sound/pcm.h>
 #include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
 
 
 #include "usbaudio.h"
 #include "usbaudio.h"
 #include "card.h"
 #include "card.h"
-#include "midi.h"
-#include "mixer.h"
-#include "proc.h"
-#include "quirks.h"
-#include "endpoint.h"
 #include "helper.h"
 #include "helper.h"
-#include "debug.h"
-#include "pcm.h"
-#include "urb.h"
-#include "format.h"
+#include "clock.h"
 
 
 static struct uac_clock_source_descriptor *
 static struct uac_clock_source_descriptor *
 	snd_usb_find_clock_source(struct usb_host_interface *ctrl_iface,
 	snd_usb_find_clock_source(struct usb_host_interface *ctrl_iface,
@@ -134,10 +120,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
 	return !!data;
 	return !!data;
 }
 }
 
 
-/* Try to find the clock source ID of a given clock entity */
-
 static int __uac_clock_find_source(struct snd_usb_audio *chip,
 static int __uac_clock_find_source(struct snd_usb_audio *chip,
-				   struct usb_host_interface *host_iface,
 				   int entity_id, unsigned long *visited)
 				   int entity_id, unsigned long *visited)
 {
 {
 	struct uac_clock_source_descriptor *source;
 	struct uac_clock_source_descriptor *source;
@@ -154,11 +137,11 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
 	}
 	}
 
 
 	/* first, see if the ID we're looking for is a clock source already */
 	/* first, see if the ID we're looking for is a clock source already */
-	source = snd_usb_find_clock_source(host_iface, entity_id);
+	source = snd_usb_find_clock_source(chip->ctrl_intf, entity_id);
 	if (source)
 	if (source)
 		return source->bClockID;
 		return source->bClockID;
 
 
-	selector = snd_usb_find_clock_selector(host_iface, entity_id);
+	selector = snd_usb_find_clock_selector(chip->ctrl_intf, entity_id);
 	if (selector) {
 	if (selector) {
 		int ret;
 		int ret;
 
 
@@ -168,6 +151,8 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
 		if (ret < 0)
 		if (ret < 0)
 			return ret;
 			return ret;
 
 
+		/* Selector values are one-based */
+
 		if (ret > selector->bNrInPins || ret < 1) {
 		if (ret > selector->bNrInPins || ret < 1) {
 			printk(KERN_ERR
 			printk(KERN_ERR
 				"%s(): selector reported illegal value, id %d, ret %d\n",
 				"%s(): selector reported illegal value, id %d, ret %d\n",
@@ -176,27 +161,35 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
 
 
-		return __uac_clock_find_source(chip, host_iface,
-					       selector->baCSourceID[ret-1],
+		return __uac_clock_find_source(chip, selector->baCSourceID[ret-1],
 					       visited);
 					       visited);
 	}
 	}
 
 
 	/* FIXME: multipliers only act as pass-thru element for now */
 	/* FIXME: multipliers only act as pass-thru element for now */
-	multiplier = snd_usb_find_clock_multiplier(host_iface, entity_id);
+	multiplier = snd_usb_find_clock_multiplier(chip->ctrl_intf, entity_id);
 	if (multiplier)
 	if (multiplier)
-		return __uac_clock_find_source(chip, host_iface,
-					       multiplier->bCSourceID, visited);
+		return __uac_clock_find_source(chip, multiplier->bCSourceID,
+						visited);
 
 
 	return -EINVAL;
 	return -EINVAL;
 }
 }
 
 
-int snd_usb_clock_find_source(struct snd_usb_audio *chip,
-			      struct usb_host_interface *host_iface,
-			      int entity_id)
+/*
+ * For all kinds of sample rate settings and other device queries,
+ * the clock source (end-leaf) must be used. However, clock selectors,
+ * clock multipliers and sample rate converters may be specified as
+ * clock source input to terminal. This functions walks the clock path
+ * to its end and tries to find the source.
+ *
+ * The 'visited' bitfield is used internally to detect recursive loops.
+ *
+ * Returns the clock source UnitID (>=0) on success, or an error.
+ */
+int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id)
 {
 {
 	DECLARE_BITMAP(visited, 256);
 	DECLARE_BITMAP(visited, 256);
 	memset(visited, 0, sizeof(visited));
 	memset(visited, 0, sizeof(visited));
-	return __uac_clock_find_source(chip, host_iface, entity_id, visited);
+	return __uac_clock_find_source(chip, entity_id, visited);
 }
 }
 
 
 static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
 static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
@@ -211,11 +204,8 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
 	ep = get_endpoint(alts, 0)->bEndpointAddress;
 	ep = get_endpoint(alts, 0)->bEndpointAddress;
 
 
 	/* if endpoint doesn't have sampling rate control, bail out */
 	/* if endpoint doesn't have sampling rate control, bail out */
-	if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE)) {
-		snd_printk(KERN_WARNING "%d:%d:%d: endpoint lacks sample rate attribute bit, cannot set.\n",
-				   dev->devnum, iface, fmt->altsetting);
+	if (!(fmt->attributes & UAC_EP_CS_ATTR_SAMPLE_RATE))
 		return 0;
 		return 0;
-	}
 
 
 	data[0] = rate;
 	data[0] = rate;
 	data[1] = rate >> 8;
 	data[1] = rate >> 8;
@@ -254,12 +244,13 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
 	struct usb_device *dev = chip->dev;
 	struct usb_device *dev = chip->dev;
 	unsigned char data[4];
 	unsigned char data[4];
 	int err, crate;
 	int err, crate;
-	int clock = snd_usb_clock_find_source(chip, chip->ctrl_intf, fmt->clock);
+	int clock = snd_usb_clock_find_source(chip, fmt->clock);
 
 
 	if (clock < 0)
 	if (clock < 0)
 		return clock;
 		return clock;
 
 
 	if (!uac_clock_source_is_valid(chip, clock)) {
 	if (!uac_clock_source_is_valid(chip, clock)) {
+		/* TODO: should we try to find valid clock setups by ourself? */
 		snd_printk(KERN_ERR "%d:%d:%d: clock source %d is not valid, cannot use\n",
 		snd_printk(KERN_ERR "%d:%d:%d: clock source %d is not valid, cannot use\n",
 			   dev->devnum, iface, fmt->altsetting, clock);
 			   dev->devnum, iface, fmt->altsetting, clock);
 		return -ENXIO;
 		return -ENXIO;

+ 1 - 3
sound/usb/clock.h

@@ -5,8 +5,6 @@ int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
 			     struct usb_host_interface *alts,
 			     struct usb_host_interface *alts,
 			     struct audioformat *fmt, int rate);
 			     struct audioformat *fmt, int rate);
 
 
-int snd_usb_clock_find_source(struct snd_usb_audio *chip,
-			      struct usb_host_interface *host_iface,
-			      int entity_id);
+int snd_usb_clock_find_source(struct snd_usb_audio *chip, int entity_id);
 
 
 #endif /* __USBAUDIO_CLOCK_H */
 #endif /* __USBAUDIO_CLOCK_H */

+ 3 - 2
sound/usb/endpoint.c

@@ -33,6 +33,7 @@
 #include "pcm.h"
 #include "pcm.h"
 #include "helper.h"
 #include "helper.h"
 #include "format.h"
 #include "format.h"
+#include "clock.h"
 
 
 /*
 /*
  * free a substream
  * free a substream
@@ -275,7 +276,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
 		/* get audio formats */
 		/* get audio formats */
 		switch (protocol) {
 		switch (protocol) {
 		case UAC_VERSION_1: {
 		case UAC_VERSION_1: {
-			struct uac_as_header_descriptor_v1 *as =
+			struct uac1_as_header_descriptor *as =
 				snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
 				snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
 
 
 			if (!as) {
 			if (!as) {
@@ -297,7 +298,7 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
 		case UAC_VERSION_2: {
 		case UAC_VERSION_2: {
 			struct uac2_input_terminal_descriptor *input_term;
 			struct uac2_input_terminal_descriptor *input_term;
 			struct uac2_output_terminal_descriptor *output_term;
 			struct uac2_output_terminal_descriptor *output_term;
-			struct uac_as_header_descriptor_v2 *as =
+			struct uac2_as_header_descriptor *as =
 				snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
 				snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
 
 
 			if (!as) {
 			if (!as) {

+ 4 - 5
sound/usb/format.c

@@ -264,13 +264,12 @@ static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,
  * on the audioformat table (audio class v2).
  * on the audioformat table (audio class v2).
  */
  */
 static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
 static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
-				       struct audioformat *fp,
-				       struct usb_host_interface *iface)
+				       struct audioformat *fp)
 {
 {
 	struct usb_device *dev = chip->dev;
 	struct usb_device *dev = chip->dev;
 	unsigned char tmp[2], *data;
 	unsigned char tmp[2], *data;
 	int nr_triplets, data_size, ret = 0;
 	int nr_triplets, data_size, ret = 0;
-	int clock = snd_usb_clock_find_source(chip, chip->ctrl_intf, fp->clock);
+	int clock = snd_usb_clock_find_source(chip, fp->clock);
 
 
 	if (clock < 0) {
 	if (clock < 0) {
 		snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n",
 		snd_printk(KERN_ERR "%s(): unable to find clock source (clock %d)\n",
@@ -391,7 +390,7 @@ static int parse_audio_format_i(struct snd_usb_audio *chip,
 		break;
 		break;
 	case UAC_VERSION_2:
 	case UAC_VERSION_2:
 		/* fp->channels is already set in this case */
 		/* fp->channels is already set in this case */
-		ret = parse_audio_format_rates_v2(chip, fp, iface);
+		ret = parse_audio_format_rates_v2(chip, fp);
 		break;
 		break;
 	}
 	}
 
 
@@ -450,7 +449,7 @@ static int parse_audio_format_ii(struct snd_usb_audio *chip,
 		framesize = le16_to_cpu(fmt->wSamplesPerFrame);
 		framesize = le16_to_cpu(fmt->wSamplesPerFrame);
 		snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
 		snd_printd(KERN_INFO "found format II with max.bitrate = %d, frame size=%d\n", brate, framesize);
 		fp->frame_size = framesize;
 		fp->frame_size = framesize;
-		ret = parse_audio_format_rates_v2(chip, fp, iface);
+		ret = parse_audio_format_rates_v2(chip, fp);
 		break;
 		break;
 	}
 	}
 	}
 	}

+ 7 - 7
sound/usb/midi.c

@@ -434,7 +434,7 @@ static void snd_usbmidi_maudio_broken_running_status_input(
 			u8 cin = buffer[i] & 0x0f;
 			u8 cin = buffer[i] & 0x0f;
 			struct usbmidi_in_port *port = &ep->ports[cable];
 			struct usbmidi_in_port *port = &ep->ports[cable];
 			int length;
 			int length;
-			
+
 			length = snd_usbmidi_cin_length[cin];
 			length = snd_usbmidi_cin_length[cin];
 			if (cin == 0xf && buffer[i + 1] >= 0xf8)
 			if (cin == 0xf && buffer[i + 1] >= 0xf8)
 				; /* realtime msg: no running status change */
 				; /* realtime msg: no running status change */
@@ -628,13 +628,13 @@ static struct usb_protocol_ops snd_usbmidi_standard_ops = {
 
 
 static struct usb_protocol_ops snd_usbmidi_midiman_ops = {
 static struct usb_protocol_ops snd_usbmidi_midiman_ops = {
 	.input = snd_usbmidi_midiman_input,
 	.input = snd_usbmidi_midiman_input,
-	.output = snd_usbmidi_standard_output, 
+	.output = snd_usbmidi_standard_output,
 	.output_packet = snd_usbmidi_output_midiman_packet,
 	.output_packet = snd_usbmidi_output_midiman_packet,
 };
 };
 
 
 static struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = {
 static struct usb_protocol_ops snd_usbmidi_maudio_broken_running_status_ops = {
 	.input = snd_usbmidi_maudio_broken_running_status_input,
 	.input = snd_usbmidi_maudio_broken_running_status_input,
-	.output = snd_usbmidi_standard_output, 
+	.output = snd_usbmidi_standard_output,
 	.output_packet = snd_usbmidi_output_standard_packet,
 	.output_packet = snd_usbmidi_output_standard_packet,
 };
 };
 
 
@@ -1248,7 +1248,7 @@ static void snd_usbmidi_out_endpoint_delete(struct snd_usb_midi_out_endpoint *ep
  */
  */
 static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
 static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
 					   struct snd_usb_midi_endpoint_info* ep_info,
 					   struct snd_usb_midi_endpoint_info* ep_info,
-			 		   struct snd_usb_midi_endpoint* rep)
+					   struct snd_usb_midi_endpoint* rep)
 {
 {
 	struct snd_usb_midi_out_endpoint* ep;
 	struct snd_usb_midi_out_endpoint* ep;
 	unsigned int i;
 	unsigned int i;
@@ -1398,7 +1398,7 @@ static void snd_usbmidi_rawmidi_free(struct snd_rawmidi *rmidi)
 }
 }
 
 
 static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_midi* umidi,
 static struct snd_rawmidi_substream *snd_usbmidi_find_substream(struct snd_usb_midi* umidi,
-							   int stream, int number)
+								int stream, int number)
 {
 {
 	struct list_head* list;
 	struct list_head* list;
 
 
@@ -1811,7 +1811,7 @@ static int snd_usbmidi_detect_endpoints(struct snd_usb_midi* umidi,
 		snd_usbmidi_switch_roland_altsetting(umidi);
 		snd_usbmidi_switch_roland_altsetting(umidi);
 
 
 	if (endpoint[0].out_ep || endpoint[0].in_ep)
 	if (endpoint[0].out_ep || endpoint[0].in_ep)
-		return 0;	
+		return 0;
 
 
 	intf = umidi->iface;
 	intf = umidi->iface;
 	if (!intf || intf->num_altsetting < 1)
 	if (!intf || intf->num_altsetting < 1)
@@ -1849,7 +1849,7 @@ static int snd_usbmidi_detect_per_port_endpoints(struct snd_usb_midi* umidi,
 						 struct snd_usb_midi_endpoint_info* endpoints)
 						 struct snd_usb_midi_endpoint_info* endpoints)
 {
 {
 	int err, i;
 	int err, i;
-	
+
 	err = snd_usbmidi_detect_endpoints(umidi, endpoints, MIDI_MAX_ENDPOINTS);
 	err = snd_usbmidi_detect_endpoints(umidi, endpoints, MIDI_MAX_ENDPOINTS);
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
 		if (endpoints[i].out_ep)
 		if (endpoints[i].out_ep)

+ 42 - 35
sound/usb/mixer.c

@@ -26,6 +26,22 @@
  *
  *
  */
  */
 
 
+/*
+ * TODOs, for both the mixer and the streaming interfaces:
+ *
+ *  - support for UAC2 effect units
+ *  - support for graphical equalizers
+ *  - RANGE and MEM set commands (UAC2)
+ *  - RANGE and MEM interrupt dispatchers (UAC2)
+ *  - audio channel clustering (UAC2)
+ *  - audio sample rate converter units (UAC2)
+ *  - proper handling of clock multipliers (UAC2)
+ *  - dispatch clock change notifications (UAC2)
+ *  	- stop PCM streams which use a clock that became invalid
+ *  	- stop PCM streams which use a clock selector that has changed
+ *  	- parse available sample rates again when clock sources changed
+ */
+
 #include <linux/bitops.h>
 #include <linux/bitops.h>
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/list.h>
 #include <linux/list.h>
@@ -275,28 +291,28 @@ static int get_abs_value(struct usb_mixer_elem_info *cval, int val)
 
 
 static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
 static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
 {
 {
+	struct snd_usb_audio *chip = cval->mixer->chip;
 	unsigned char buf[2];
 	unsigned char buf[2];
 	int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
 	int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
 	int timeout = 10;
 	int timeout = 10;
 
 
 	while (timeout-- > 0) {
 	while (timeout-- > 0) {
-		if (snd_usb_ctl_msg(cval->mixer->chip->dev,
-				    usb_rcvctrlpipe(cval->mixer->chip->dev, 0),
-				    request,
+		if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
 				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
 				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-				    validx, cval->mixer->ctrlif | (cval->id << 8),
+				    validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
 				    buf, val_len, 100) >= val_len) {
 				    buf, val_len, 100) >= val_len) {
 			*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
 			*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
 			return 0;
 			return 0;
 		}
 		}
 	}
 	}
 	snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
 	snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
-		    request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type);
+		    request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
 	return -EINVAL;
 	return -EINVAL;
 }
 }
 
 
 static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
 static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret)
 {
 {
+	struct snd_usb_audio *chip = cval->mixer->chip;
 	unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */
 	unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */
 	unsigned char *val;
 	unsigned char *val;
 	int ret, size;
 	int ret, size;
@@ -312,16 +328,14 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
 
 
 	memset(buf, 0, sizeof(buf));
 	memset(buf, 0, sizeof(buf));
 
 
-	ret = snd_usb_ctl_msg(cval->mixer->chip->dev,
-			      usb_rcvctrlpipe(cval->mixer->chip->dev, 0),
-			      bRequest,
+	ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
 			      USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
 			      USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
-			      validx, cval->mixer->ctrlif | (cval->id << 8),
+			      validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
 			      buf, size, 1000);
 			      buf, size, 1000);
 
 
 	if (ret < 0) {
 	if (ret < 0) {
 		snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
 		snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n",
-			   request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type);
+			   request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
 		return ret;
 		return ret;
 	}
 	}
 
 
@@ -397,6 +411,7 @@ static int get_cur_mix_value(struct usb_mixer_elem_info *cval,
 int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 				int request, int validx, int value_set)
 				int request, int validx, int value_set)
 {
 {
+	struct snd_usb_audio *chip = cval->mixer->chip;
 	unsigned char buf[2];
 	unsigned char buf[2];
 	int val_len, timeout = 10;
 	int val_len, timeout = 10;
 
 
@@ -419,15 +434,14 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 	buf[0] = value_set & 0xff;
 	buf[0] = value_set & 0xff;
 	buf[1] = (value_set >> 8) & 0xff;
 	buf[1] = (value_set >> 8) & 0xff;
 	while (timeout-- > 0)
 	while (timeout-- > 0)
-		if (snd_usb_ctl_msg(cval->mixer->chip->dev,
-				    usb_sndctrlpipe(cval->mixer->chip->dev, 0),
-				    request,
+		if (snd_usb_ctl_msg(chip->dev,
+				    usb_sndctrlpipe(chip->dev, 0), request,
 				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
 				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
-				    validx, cval->mixer->ctrlif | (cval->id << 8),
+				    validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
 				    buf, val_len, 100) >= 0)
 				    buf, val_len, 100) >= 0)
 			return 0;
 			return 0;
 	snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
 	snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n",
-		    request, validx, cval->mixer->ctrlif | (cval->id << 8), cval->val_type, buf[0], buf[1]);
+		    request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]);
 	return -EINVAL;
 	return -EINVAL;
 }
 }
 
 
@@ -582,9 +596,9 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm
 		switch (iterm->type >> 16) {
 		switch (iterm->type >> 16) {
 		case UAC_SELECTOR_UNIT:
 		case UAC_SELECTOR_UNIT:
 			strcpy(name, "Selector"); return 8;
 			strcpy(name, "Selector"); return 8;
-		case UAC_PROCESSING_UNIT_V1:
+		case UAC1_PROCESSING_UNIT:
 			strcpy(name, "Process Unit"); return 12;
 			strcpy(name, "Process Unit"); return 12;
-		case UAC_EXTENSION_UNIT_V1:
+		case UAC1_EXTENSION_UNIT:
 			strcpy(name, "Ext Unit"); return 8;
 			strcpy(name, "Ext Unit"); return 8;
 		case UAC_MIXER_UNIT:
 		case UAC_MIXER_UNIT:
 			strcpy(name, "Mixer"); return 5;
 			strcpy(name, "Mixer"); return 5;
@@ -672,8 +686,8 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
 			term->name = uac_selector_unit_iSelector(d);
 			term->name = uac_selector_unit_iSelector(d);
 			return 0;
 			return 0;
 		}
 		}
-		case UAC_PROCESSING_UNIT_V1:
-		case UAC_EXTENSION_UNIT_V1: {
+		case UAC1_PROCESSING_UNIT:
+		case UAC1_EXTENSION_UNIT: {
 			struct uac_processing_unit_descriptor *d = p1;
 			struct uac_processing_unit_descriptor *d = p1;
 			if (d->bNrInPins) {
 			if (d->bNrInPins) {
 				id = d->baSourceID[0];
 				id = d->baSourceID[0];
@@ -745,6 +759,8 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
  */
  */
 static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
 static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
 {
 {
+	struct snd_usb_audio *chip = cval->mixer->chip;
+
 	/* for failsafe */
 	/* for failsafe */
 	cval->min = default_min;
 	cval->min = default_min;
 	cval->max = cval->min + 1;
 	cval->max = cval->min + 1;
@@ -767,7 +783,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
 		if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
 		if (get_ctl_value(cval, UAC_GET_MAX, (cval->control << 8) | minchn, &cval->max) < 0 ||
 		    get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
 		    get_ctl_value(cval, UAC_GET_MIN, (cval->control << 8) | minchn, &cval->min) < 0) {
 			snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n",
 			snd_printd(KERN_ERR "%d:%d: cannot get min/max values for control %d (id %d)\n",
-				   cval->id, cval->mixer->ctrlif, cval->control, cval->id);
+				   cval->id, snd_usb_ctrl_intf(chip), cval->control, cval->id);
 			return -EINVAL;
 			return -EINVAL;
 		}
 		}
 		if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) {
 		if (get_ctl_value(cval, UAC_GET_RES, (cval->control << 8) | minchn, &cval->res) < 0) {
@@ -1199,14 +1215,6 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
 		}
 		}
 	} else { /* UAC_VERSION_2 */
 	} else { /* UAC_VERSION_2 */
 		for (i = 0; i < 30/2; i++) {
 		for (i = 0; i < 30/2; i++) {
-			/* From the USB Audio spec v2.0:
-			   bmaControls() is a (ch+1)-element array of 4-byte bitmaps,
-			   each containing a set of bit pairs. If a Control is present,
-			   it must be Host readable. If a certain Control is not
-			   present then the bit pair must be set to 0b00.
-			   If a Control is present but read-only, the bit pair must be
-			   set to 0b01. If a Control is also Host programmable, the bit
-			   pair must be set to 0b11. The value 0b10 is not allowed. */
 			unsigned int ch_bits = 0;
 			unsigned int ch_bits = 0;
 			unsigned int ch_read_only = 0;
 			unsigned int ch_read_only = 0;
 
 
@@ -1855,13 +1863,13 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
 		return parse_audio_selector_unit(state, unitid, p1);
 		return parse_audio_selector_unit(state, unitid, p1);
 	case UAC_FEATURE_UNIT:
 	case UAC_FEATURE_UNIT:
 		return parse_audio_feature_unit(state, unitid, p1);
 		return parse_audio_feature_unit(state, unitid, p1);
-	case UAC_PROCESSING_UNIT_V1:
+	case UAC1_PROCESSING_UNIT:
 	/*   UAC2_EFFECT_UNIT has the same value */
 	/*   UAC2_EFFECT_UNIT has the same value */
 		if (state->mixer->protocol == UAC_VERSION_1)
 		if (state->mixer->protocol == UAC_VERSION_1)
 			return parse_audio_processing_unit(state, unitid, p1);
 			return parse_audio_processing_unit(state, unitid, p1);
 		else
 		else
 			return 0; /* FIXME - effect units not implemented yet */
 			return 0; /* FIXME - effect units not implemented yet */
-	case UAC_EXTENSION_UNIT_V1:
+	case UAC1_EXTENSION_UNIT:
 	/*   UAC2_PROCESSING_UNIT_V2 has the same value */
 	/*   UAC2_PROCESSING_UNIT_V2 has the same value */
 		if (state->mixer->protocol == UAC_VERSION_1)
 		if (state->mixer->protocol == UAC_VERSION_1)
 			return parse_audio_extension_unit(state, unitid, p1);
 			return parse_audio_extension_unit(state, unitid, p1);
@@ -1905,7 +1913,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
 	struct usb_host_interface *hostif;
 	struct usb_host_interface *hostif;
 	void *p;
 	void *p;
 
 
-	hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0];
+	hostif = mixer->chip->ctrl_intf;
 	memset(&state, 0, sizeof(state));
 	memset(&state, 0, sizeof(state));
 	state.chip = mixer->chip;
 	state.chip = mixer->chip;
 	state.mixer = mixer;
 	state.mixer = mixer;
@@ -1925,7 +1933,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
 	p = NULL;
 	p = NULL;
 	while ((p = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, p, UAC_OUTPUT_TERMINAL)) != NULL) {
 	while ((p = snd_usb_find_csint_desc(hostif->extra, hostif->extralen, p, UAC_OUTPUT_TERMINAL)) != NULL) {
 		if (mixer->protocol == UAC_VERSION_1) {
 		if (mixer->protocol == UAC_VERSION_1) {
-			struct uac_output_terminal_descriptor_v1 *desc = p;
+			struct uac1_output_terminal_descriptor *desc = p;
 
 
 			if (desc->bLength < sizeof(*desc))
 			if (desc->bLength < sizeof(*desc))
 				continue; /* invalid descriptor? */
 				continue; /* invalid descriptor? */
@@ -1997,7 +2005,7 @@ static void snd_usb_mixer_proc_read(struct snd_info_entry *entry,
 	list_for_each_entry(mixer, &chip->mixer_list, list) {
 	list_for_each_entry(mixer, &chip->mixer_list, list) {
 		snd_iprintf(buffer,
 		snd_iprintf(buffer,
 			"USB Mixer: usb_id=0x%08x, ctrlif=%i, ctlerr=%i\n",
 			"USB Mixer: usb_id=0x%08x, ctrlif=%i, ctlerr=%i\n",
-				chip->usb_id, mixer->ctrlif,
+				chip->usb_id, snd_usb_ctrl_intf(chip),
 				mixer->ignore_ctl_error);
 				mixer->ignore_ctl_error);
 		snd_iprintf(buffer, "Card: %s\n", chip->card->longname);
 		snd_iprintf(buffer, "Card: %s\n", chip->card->longname);
 		for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) {
 		for (unitid = 0; unitid < MAX_ID_ELEMS; unitid++) {
@@ -2115,7 +2123,7 @@ static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
 	int buffer_length;
 	int buffer_length;
 	unsigned int epnum;
 	unsigned int epnum;
 
 
-	hostif = &usb_ifnum_to_if(mixer->chip->dev, mixer->ctrlif)->altsetting[0];
+	hostif = mixer->chip->ctrl_intf;
 	/* we need one interrupt input endpoint */
 	/* we need one interrupt input endpoint */
 	if (get_iface_desc(hostif)->bNumEndpoints < 1)
 	if (get_iface_desc(hostif)->bNumEndpoints < 1)
 		return 0;
 		return 0;
@@ -2158,7 +2166,6 @@ int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
 	if (!mixer)
 	if (!mixer)
 		return -ENOMEM;
 		return -ENOMEM;
 	mixer->chip = chip;
 	mixer->chip = chip;
-	mixer->ctrlif = ctrlif;
 	mixer->ignore_ctl_error = ignore_error;
 	mixer->ignore_ctl_error = ignore_error;
 	mixer->id_elems = kcalloc(MAX_ID_ELEMS, sizeof(*mixer->id_elems),
 	mixer->id_elems = kcalloc(MAX_ID_ELEMS, sizeof(*mixer->id_elems),
 				  GFP_KERNEL);
 				  GFP_KERNEL);

+ 0 - 1
sound/usb/mixer.h

@@ -3,7 +3,6 @@
 
 
 struct usb_mixer_interface {
 struct usb_mixer_interface {
 	struct snd_usb_audio *chip;
 	struct snd_usb_audio *chip;
-	unsigned int ctrlif;
 	struct list_head list;
 	struct list_head list;
 	unsigned int ignore_ctl_error;
 	unsigned int ignore_ctl_error;
 	struct urb *urb;
 	struct urb *urb;

+ 0 - 3
sound/usb/pcm.h

@@ -7,8 +7,5 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
 		       struct usb_host_interface *alts,
 		       struct usb_host_interface *alts,
 		       struct audioformat *fmt);
 		       struct audioformat *fmt);
 
 
-int snd_usb_init_sample_rate(struct snd_usb_audio *chip, int iface,
-			     struct usb_host_interface *alts,
-			     struct audioformat *fmt, int rate);
 
 
 #endif /* __USBAUDIO_PCM_H */
 #endif /* __USBAUDIO_PCM_H */

+ 22 - 8
sound/usb/quirks-table.h

@@ -2152,7 +2152,21 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 	}
 },
 },
 {
 {
-	USB_DEVICE_VENDOR_SPEC(0x2040, 0x7201),
+	USB_DEVICE_VENDOR_SPEC(0x2040, 0x7240),
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
+		       USB_DEVICE_ID_MATCH_INT_CLASS |
+		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+	.bInterfaceClass = USB_CLASS_AUDIO,
+	.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
+	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+		.vendor_name = "Hauppauge",
+		.product_name = "HVR-850",
+		.ifnum = QUIRK_ANY_INTERFACE,
+		.type = QUIRK_AUDIO_ALIGN_TRANSFER,
+	}
+},
+{
+	USB_DEVICE_VENDOR_SPEC(0x2040, 0x7210),
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 		       USB_DEVICE_ID_MATCH_INT_CLASS |
 		       USB_DEVICE_ID_MATCH_INT_CLASS |
 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2166,7 +2180,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 	}
 },
 },
 {
 {
-	USB_DEVICE_VENDOR_SPEC(0x2040, 0x7202),
+	USB_DEVICE_VENDOR_SPEC(0x2040, 0x7217),
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 		       USB_DEVICE_ID_MATCH_INT_CLASS |
 		       USB_DEVICE_ID_MATCH_INT_CLASS |
 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2180,7 +2194,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 	}
 },
 },
 {
 {
-	USB_DEVICE_VENDOR_SPEC(0x2040, 0x7203),
+	USB_DEVICE_VENDOR_SPEC(0x2040, 0x721b),
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 		       USB_DEVICE_ID_MATCH_INT_CLASS |
 		       USB_DEVICE_ID_MATCH_INT_CLASS |
 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2194,7 +2208,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 	}
 },
 },
 {
 {
-	USB_DEVICE_VENDOR_SPEC(0x2040, 0x7204),
+	USB_DEVICE_VENDOR_SPEC(0x2040, 0x721e),
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 		       USB_DEVICE_ID_MATCH_INT_CLASS |
 		       USB_DEVICE_ID_MATCH_INT_CLASS |
 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2208,7 +2222,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 	}
 },
 },
 {
 {
-	USB_DEVICE_VENDOR_SPEC(0x2040, 0x7205),
+	USB_DEVICE_VENDOR_SPEC(0x2040, 0x721f),
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 		       USB_DEVICE_ID_MATCH_INT_CLASS |
 		       USB_DEVICE_ID_MATCH_INT_CLASS |
 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2222,7 +2236,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 	}
 },
 },
 {
 {
-	USB_DEVICE_VENDOR_SPEC(0x2040, 0x7250),
+	USB_DEVICE_VENDOR_SPEC(0x2040, 0x7280),
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 		       USB_DEVICE_ID_MATCH_INT_CLASS |
 		       USB_DEVICE_ID_MATCH_INT_CLASS |
 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2236,7 +2250,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 	}
 },
 },
 {
 {
-	USB_DEVICE_VENDOR_SPEC(0x2040, 0x7230),
+	USB_DEVICE_VENDOR_SPEC(0x0fd9, 0x0008),
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 	.match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 		       USB_DEVICE_ID_MATCH_INT_CLASS |
 		       USB_DEVICE_ID_MATCH_INT_CLASS |
 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 		       USB_DEVICE_ID_MATCH_INT_SUBCLASS,
@@ -2244,7 +2258,7 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
 	.bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
 	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
 	.driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
 		.vendor_name = "Hauppauge",
 		.vendor_name = "Hauppauge",
-		.product_name = "HVR-850",
+		.product_name = "HVR-950Q",
 		.ifnum = QUIRK_ANY_INTERFACE,
 		.ifnum = QUIRK_ANY_INTERFACE,
 		.type = QUIRK_AUDIO_ALIGN_TRANSFER,
 		.type = QUIRK_AUDIO_ALIGN_TRANSFER,
 	}
 	}

+ 1 - 0
sound/usb/quirks.c

@@ -32,6 +32,7 @@
 #include "helper.h"
 #include "helper.h"
 #include "endpoint.h"
 #include "endpoint.h"
 #include "pcm.h"
 #include "pcm.h"
+#include "clock.h"
 
 
 /*
 /*
  * handle the quirks for the contained interfaces
  * handle the quirks for the contained interfaces