Преглед на файлове

Merge branch 'topic/misc' into for-linus

Takashi Iwai преди 14 години
родител
ревизия
d351cf4603
променени са 91 файла, в които са добавени 6274 реда и са изтрити 3876 реда
  1. 5 0
      include/sound/ac97_codec.h
  2. 137 42
      include/sound/hdspm.h
  3. 3 0
      include/sound/mixer_oss.h
  4. 46 45
      include/sound/pcm.h
  5. 1 1
      include/sound/version.h
  6. 10 12
      sound/core/control.c
  7. 4 3
      sound/core/device.c
  8. 2 1
      sound/core/memalloc.c
  9. 4 3
      sound/core/oss/linear.c
  10. 6 4
      sound/core/oss/mixer_oss.c
  11. 1 1
      sound/core/oss/mulaw.c
  12. 28 23
      sound/core/oss/pcm_oss.c
  13. 22 18
      sound/core/oss/pcm_plugin.c
  14. 6 5
      sound/core/oss/pcm_plugin.h
  15. 3 3
      sound/core/oss/route.c
  16. 5 5
      sound/core/pcm.c
  17. 19 16
      sound/core/pcm_misc.c
  18. 1 1
      sound/core/pcm_native.c
  19. 2 5
      sound/core/seq/seq_clientmgr.c
  20. 3 3
      sound/core/seq/seq_memory.c
  21. 4 0
      sound/core/seq/seq_memory.h
  22. 1 1
      sound/core/seq/seq_ports.c
  23. 3 5
      sound/core/timer.c
  24. 1 1
      sound/core/vmaster.c
  25. 9 10
      sound/drivers/aloop.c
  26. 20 36
      sound/oss/soundcard.c
  27. 9 3
      sound/pci/Kconfig
  28. 56 34
      sound/pci/ac97/ac97_codec.c
  29. 52 0
      sound/pci/ac97/ac97_patch.c
  30. 259 272
      sound/pci/asihpi/asihpi.c
  31. 448 766
      sound/pci/asihpi/hpi.h
  32. 137 162
      sound/pci/asihpi/hpi6000.c
  33. 208 267
      sound/pci/asihpi/hpi6205.c
  34. 2 5
      sound/pci/asihpi/hpi6205.h
  35. 377 496
      sound/pci/asihpi/hpi_internal.h
  36. 265 215
      sound/pci/asihpi/hpicmn.c
  37. 11 13
      sound/pci/asihpi/hpicmn.h
  38. 5 152
      sound/pci/asihpi/hpidebug.c
  39. 20 303
      sound/pci/asihpi/hpidebug.h
  40. 20 17
      sound/pci/asihpi/hpidspcd.c
  41. 1 1
      sound/pci/asihpi/hpidspcd.h
  42. 150 407
      sound/pci/asihpi/hpifunc.c
  43. 2 16
      sound/pci/asihpi/hpimsginit.c
  44. 9 3
      sound/pci/asihpi/hpimsginit.h
  45. 51 152
      sound/pci/asihpi/hpimsgx.c
  46. 46 44
      sound/pci/asihpi/hpioctl.c
  47. 4 6
      sound/pci/asihpi/hpios.h
  48. 1 1
      sound/pci/atiixp.c
  49. 1 1
      sound/pci/atiixp_modem.c
  50. 2 1
      sound/pci/au88x0/au88x0_eq.c
  51. 402 48
      sound/pci/azt3328.c
  52. 1 1
      sound/pci/ctxfi/ctatc.c
  53. 2 0
      sound/pci/ctxfi/ctdaio.c
  54. 18 10
      sound/pci/ctxfi/cthw20k2.c
  55. 5 14
      sound/pci/ctxfi/ctmixer.c
  56. 1 2
      sound/pci/ctxfi/ctvmem.c
  57. 1 1
      sound/pci/emu10k1/emu10k1_main.c
  58. 1 1
      sound/pci/hda/patch_realtek.c
  59. 54 53
      sound/pci/intel8x0m.c
  60. 595 120
      sound/pci/rme9652/hdspm.c
  61. 5 1
      sound/ppc/pmac.c
  62. 3 0
      sound/sound_core.c
  63. 3 0
      sound/usb/6fire/Makefile
  64. 232 0
      sound/usb/6fire/chip.c
  65. 32 0
      sound/usb/6fire/chip.h
  66. 176 0
      sound/usb/6fire/comm.c
  67. 44 0
      sound/usb/6fire/comm.h
  68. 30 0
      sound/usb/6fire/common.h
  69. 275 0
      sound/usb/6fire/control.c
  70. 37 0
      sound/usb/6fire/control.h
  71. 426 0
      sound/usb/6fire/firmware.c
  72. 27 0
      sound/usb/6fire/firmware.h
  73. 203 0
      sound/usb/6fire/midi.c
  74. 46 0
      sound/usb/6fire/midi.h
  75. 688 0
      sound/usb/6fire/pcm.c
  76. 76 0
      sound/usb/6fire/pcm.h
  77. 17 0
      sound/usb/Kconfig
  78. 1 1
      sound/usb/Makefile
  79. 1 0
      sound/usb/caiaq/audio.c
  80. 6 0
      sound/usb/caiaq/device.c
  81. 1 0
      sound/usb/caiaq/device.h
  82. 55 9
      sound/usb/card.c
  83. 8 0
      sound/usb/midi.c
  84. 61 4
      sound/usb/mixer.c
  85. 2 0
      sound/usb/mixer.h
  86. 161 13
      sound/usb/mixer_quirks.c
  87. 15 5
      sound/usb/pcm.c
  88. 17 0
      sound/usb/power.h
  89. 14 0
      sound/usb/quirks-table.h
  90. 45 11
      sound/usb/quirks.c
  91. 5 1
      sound/usb/usbaudio.h

+ 5 - 0
include/sound/ac97_codec.h

@@ -96,6 +96,10 @@
 #define AC97_FUNC_INFO		0x68	/* Function Information */
 #define AC97_FUNC_INFO		0x68	/* Function Information */
 #define AC97_SENSE_INFO		0x6a	/* Sense Details */
 #define AC97_SENSE_INFO		0x6a	/* Sense Details */
 
 
+/* volume controls */
+#define AC97_MUTE_MASK_MONO	0x8000
+#define AC97_MUTE_MASK_STEREO	0x8080
+
 /* slot allocation */
 /* slot allocation */
 #define AC97_SLOT_TAG		0
 #define AC97_SLOT_TAG		0
 #define AC97_SLOT_CMD_ADDR	1
 #define AC97_SLOT_CMD_ADDR	1
@@ -138,6 +142,7 @@
 #define AC97_BC_18BIT_ADC	0x0100	/* 18-bit ADC resolution */
 #define AC97_BC_18BIT_ADC	0x0100	/* 18-bit ADC resolution */
 #define AC97_BC_20BIT_ADC	0x0200	/* 20-bit ADC resolution */
 #define AC97_BC_20BIT_ADC	0x0200	/* 20-bit ADC resolution */
 #define AC97_BC_ADC_MASK	0x0300
 #define AC97_BC_ADC_MASK	0x0300
+#define AC97_BC_3D_TECH_ID_MASK	0x7c00	/* Per-vendor ID of 3D enhancement */
 
 
 /* general purpose */
 /* general purpose */
 #define AC97_GP_DRSS_MASK	0x0c00	/* double rate slot select */
 #define AC97_GP_DRSS_MASK	0x0c00	/* double rate slot select */

+ 137 - 42
include/sound/hdspm.h

@@ -3,8 +3,8 @@
 /*
 /*
  *   Copyright (C) 2003 Winfried Ritsch (IEM)
  *   Copyright (C) 2003 Winfried Ritsch (IEM)
  *   based on hdsp.h from Thomas Charbonnel (thomas@undata.org)
  *   based on hdsp.h from Thomas Charbonnel (thomas@undata.org)
- *                      
- *    
+ *
+ *
  *   This program is free software; you can redistribute it and/or modify
  *   This program is free software; you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
  *   it under the terms of the GNU General Public License as published by
  *   the Free Software Foundation; either version 2 of the License, or
  *   the Free Software Foundation; either version 2 of the License, or
@@ -23,50 +23,41 @@
 /* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
 /* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
 #define HDSPM_MAX_CHANNELS      64
 #define HDSPM_MAX_CHANNELS      64
 
 
-/* -------------------- IOCTL Peak/RMS Meters -------------------- */
-
-/* peam rms level structure like we get from hardware 
-  
-   maybe in future we can memory map it so I just copy it
-   to user on ioctl call now an dont change anything
-   rms are made out of low and high values
-   where (long) ????_rms = (????_rms_l >> 8) + ((????_rms_h & 0xFFFFFF00)<<24)
-   (i asume so from the code)
-*/
-
-struct hdspm_peak_rms {
-
-	unsigned int level_offset[1024];
+enum hdspm_io_type {
+	MADI,
+	MADIface,
+	AIO,
+	AES32,
+	RayDAT
+};
 
 
-	unsigned int input_peak[64];
-	unsigned int playback_peak[64];
-	unsigned int output_peak[64];
-	unsigned int xxx_peak[64];	/* not used */
+enum hdspm_speed {
+	ss,
+	ds,
+	qs
+};
 
 
-	unsigned int reserved[256];	/* not used */
+/* -------------------- IOCTL Peak/RMS Meters -------------------- */
 
 
-	unsigned int input_rms_l[64];
-	unsigned int playback_rms_l[64];
-	unsigned int output_rms_l[64];
-	unsigned int xxx_rms_l[64];	/* not used */
+struct hdspm_peak_rms {
+	uint32_t input_peaks[64];
+	uint32_t playback_peaks[64];
+	uint32_t output_peaks[64];
 
 
-	unsigned int input_rms_h[64];
-	unsigned int playback_rms_h[64];
-	unsigned int output_rms_h[64];
-	unsigned int xxx_rms_h[64];	/* not used */
-};
+	uint64_t input_rms[64];
+	uint64_t playback_rms[64];
+	uint64_t output_rms[64];
 
 
-struct hdspm_peak_rms_ioctl {
-	struct hdspm_peak_rms *peak;
+	uint8_t speed; /* enum {ss, ds, qs} */
+	int status2;
 };
 };
 
 
-/* use indirect access due to the limit of ioctl bit size */
 #define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \
 #define SNDRV_HDSPM_IOCTL_GET_PEAK_RMS \
-	_IOR('H', 0x40, struct hdspm_peak_rms_ioctl)
+	_IOR('H', 0x42, struct hdspm_peak_rms)
 
 
 /* ------------ CONFIG block IOCTL ---------------------- */
 /* ------------ CONFIG block IOCTL ---------------------- */
 
 
-struct hdspm_config_info {
+struct hdspm_config {
 	unsigned char pref_sync_ref;
 	unsigned char pref_sync_ref;
 	unsigned char wordclock_sync_check;
 	unsigned char wordclock_sync_check;
 	unsigned char madi_sync_check;
 	unsigned char madi_sync_check;
@@ -80,18 +71,121 @@ struct hdspm_config_info {
 	unsigned int analog_out;
 	unsigned int analog_out;
 };
 };
 
 
-#define SNDRV_HDSPM_IOCTL_GET_CONFIG_INFO \
-	_IOR('H', 0x41, struct hdspm_config_info)
+#define SNDRV_HDSPM_IOCTL_GET_CONFIG \
+	_IOR('H', 0x41, struct hdspm_config)
+
+/**
+ * If there's a TCO (TimeCode Option) board installed,
+ * there are further options and status data available.
+ * The hdspm_ltc structure contains the current SMPTE
+ * timecode and some status information and can be
+ * obtained via SNDRV_HDSPM_IOCTL_GET_LTC or in the
+ * hdspm_status struct.
+ **/
+
+enum hdspm_ltc_format {
+	format_invalid,
+	fps_24,
+	fps_25,
+	fps_2997,
+	fps_30
+};
+
+enum hdspm_ltc_frame {
+	frame_invalid,
+	drop_frame,
+	full_frame
+};
+
+enum hdspm_ltc_input_format {
+	ntsc,
+	pal,
+	no_video
+};
+
+struct hdspm_ltc {
+	unsigned int ltc;
 
 
+	enum hdspm_ltc_format format;
+	enum hdspm_ltc_frame frame;
+	enum hdspm_ltc_input_format input_format;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_LTC _IOR('H', 0x46, struct hdspm_mixer_ioctl)
+
+/**
+ * The status data reflects the device's current state
+ * as determined by the card's configuration and
+ * connection status.
+ **/
+
+enum hdspm_sync {
+	hdspm_sync_no_lock = 0,
+	hdspm_sync_lock = 1,
+	hdspm_sync_sync = 2
+};
 
 
-/* get Soundcard Version */
+enum hdspm_madi_input {
+	hdspm_input_optical = 0,
+	hdspm_input_coax = 1
+};
+
+enum hdspm_madi_channel_format {
+	hdspm_format_ch_64 = 0,
+	hdspm_format_ch_56 = 1
+};
+
+enum hdspm_madi_frame_format {
+	hdspm_frame_48 = 0,
+	hdspm_frame_96 = 1
+};
+
+enum hdspm_syncsource {
+	syncsource_wc = 0,
+	syncsource_madi = 1,
+	syncsource_tco = 2,
+	syncsource_sync = 3,
+	syncsource_none = 4
+};
+
+struct hdspm_status {
+	uint8_t card_type; /* enum hdspm_io_type */
+	enum hdspm_syncsource autosync_source;
+
+	uint64_t card_clock;
+	uint32_t master_period;
+
+	union {
+		struct {
+			uint8_t sync_wc; /* enum hdspm_sync */
+			uint8_t sync_madi; /* enum hdspm_sync */
+			uint8_t sync_tco; /* enum hdspm_sync */
+			uint8_t sync_in; /* enum hdspm_sync */
+			uint8_t madi_input; /* enum hdspm_madi_input */
+			uint8_t channel_format; /* enum hdspm_madi_channel_format */
+			uint8_t frame_format; /* enum hdspm_madi_frame_format */
+		} madi;
+	} card_specific;
+};
+
+#define SNDRV_HDSPM_IOCTL_GET_STATUS \
+	_IOR('H', 0x47, struct hdspm_status)
+
+/**
+ * Get information about the card and its add-ons.
+ **/
+
+#define HDSPM_ADDON_TCO 1
 
 
 struct hdspm_version {
 struct hdspm_version {
+	uint8_t card_type; /* enum hdspm_io_type */
+	char cardname[20];
+	unsigned int serial;
 	unsigned short firmware_rev;
 	unsigned short firmware_rev;
+	int addons;
 };
 };
 
 
-#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x43, struct hdspm_version)
-
+#define SNDRV_HDSPM_IOCTL_GET_VERSION _IOR('H', 0x48, struct hdspm_version)
 
 
 /* ------------- get Matrix Mixer IOCTL --------------- */
 /* ------------- get Matrix Mixer IOCTL --------------- */
 
 
@@ -103,7 +197,7 @@ struct hdspm_version {
 /* equivalent to hardware definition, maybe for future feature of mmap of
 /* equivalent to hardware definition, maybe for future feature of mmap of
  * them
  * them
  */
  */
-/* each of 64 outputs has 64 infader and 64 outfader: 
+/* each of 64 outputs has 64 infader and 64 outfader:
    Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */
    Ins to Outs mixer[out].in[in], Outstreams to Outs mixer[out].pb[pb] */
 
 
 #define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS
 #define HDSPM_MIXER_CHANNELS HDSPM_MAX_CHANNELS
@@ -131,4 +225,5 @@ typedef struct hdspm_version hdspm_version_t;
 typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
 typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
 typedef struct hdspm_mixer hdspm_mixer_t;
 typedef struct hdspm_mixer hdspm_mixer_t;
 
 
-#endif				/* __SOUND_HDSPM_H */
+
+#endif

+ 3 - 0
include/sound/mixer_oss.h

@@ -73,6 +73,9 @@ struct snd_mixer_oss_file {
 	struct snd_mixer_oss *mixer;
 	struct snd_mixer_oss *mixer;
 };
 };
 
 
+int snd_mixer_oss_ioctl_card(struct snd_card *card,
+			     unsigned int cmd, unsigned long arg);
+
 #endif /* CONFIG_SND_MIXER_OSS */
 #endif /* CONFIG_SND_MIXER_OSS */
 
 
 #endif /* __SOUND_MIXER_OSS_H */
 #endif /* __SOUND_MIXER_OSS_H */

+ 46 - 45
include/sound/pcm.h

@@ -136,48 +136,49 @@ struct snd_pcm_ops {
 					 SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000)
 					 SNDRV_PCM_RATE_88200|SNDRV_PCM_RATE_96000)
 #define SNDRV_PCM_RATE_8000_192000	(SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\
 #define SNDRV_PCM_RATE_8000_192000	(SNDRV_PCM_RATE_8000_96000|SNDRV_PCM_RATE_176400|\
 					 SNDRV_PCM_RATE_192000)
 					 SNDRV_PCM_RATE_192000)
-#define SNDRV_PCM_FMTBIT_S8		(1ULL << SNDRV_PCM_FORMAT_S8)
-#define SNDRV_PCM_FMTBIT_U8		(1ULL << SNDRV_PCM_FORMAT_U8)
-#define SNDRV_PCM_FMTBIT_S16_LE		(1ULL << SNDRV_PCM_FORMAT_S16_LE)
-#define SNDRV_PCM_FMTBIT_S16_BE		(1ULL << SNDRV_PCM_FORMAT_S16_BE)
-#define SNDRV_PCM_FMTBIT_U16_LE		(1ULL << SNDRV_PCM_FORMAT_U16_LE)
-#define SNDRV_PCM_FMTBIT_U16_BE		(1ULL << SNDRV_PCM_FORMAT_U16_BE)
-#define SNDRV_PCM_FMTBIT_S24_LE		(1ULL << SNDRV_PCM_FORMAT_S24_LE)
-#define SNDRV_PCM_FMTBIT_S24_BE		(1ULL << SNDRV_PCM_FORMAT_S24_BE)
-#define SNDRV_PCM_FMTBIT_U24_LE		(1ULL << SNDRV_PCM_FORMAT_U24_LE)
-#define SNDRV_PCM_FMTBIT_U24_BE		(1ULL << SNDRV_PCM_FORMAT_U24_BE)
-#define SNDRV_PCM_FMTBIT_S32_LE		(1ULL << SNDRV_PCM_FORMAT_S32_LE)
-#define SNDRV_PCM_FMTBIT_S32_BE		(1ULL << SNDRV_PCM_FORMAT_S32_BE)
-#define SNDRV_PCM_FMTBIT_U32_LE		(1ULL << SNDRV_PCM_FORMAT_U32_LE)
-#define SNDRV_PCM_FMTBIT_U32_BE		(1ULL << SNDRV_PCM_FORMAT_U32_BE)
-#define SNDRV_PCM_FMTBIT_FLOAT_LE	(1ULL << SNDRV_PCM_FORMAT_FLOAT_LE)
-#define SNDRV_PCM_FMTBIT_FLOAT_BE	(1ULL << SNDRV_PCM_FORMAT_FLOAT_BE)
-#define SNDRV_PCM_FMTBIT_FLOAT64_LE	(1ULL << SNDRV_PCM_FORMAT_FLOAT64_LE)
-#define SNDRV_PCM_FMTBIT_FLOAT64_BE	(1ULL << SNDRV_PCM_FORMAT_FLOAT64_BE)
-#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE)
-#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE (1ULL << SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE)
-#define SNDRV_PCM_FMTBIT_MU_LAW		(1ULL << SNDRV_PCM_FORMAT_MU_LAW)
-#define SNDRV_PCM_FMTBIT_A_LAW		(1ULL << SNDRV_PCM_FORMAT_A_LAW)
-#define SNDRV_PCM_FMTBIT_IMA_ADPCM	(1ULL << SNDRV_PCM_FORMAT_IMA_ADPCM)
-#define SNDRV_PCM_FMTBIT_MPEG		(1ULL << SNDRV_PCM_FORMAT_MPEG)
-#define SNDRV_PCM_FMTBIT_GSM		(1ULL << SNDRV_PCM_FORMAT_GSM)
-#define SNDRV_PCM_FMTBIT_SPECIAL	(1ULL << SNDRV_PCM_FORMAT_SPECIAL)
-#define SNDRV_PCM_FMTBIT_S24_3LE	(1ULL << SNDRV_PCM_FORMAT_S24_3LE)
-#define SNDRV_PCM_FMTBIT_U24_3LE	(1ULL << SNDRV_PCM_FORMAT_U24_3LE)
-#define SNDRV_PCM_FMTBIT_S24_3BE	(1ULL << SNDRV_PCM_FORMAT_S24_3BE)
-#define SNDRV_PCM_FMTBIT_U24_3BE	(1ULL << SNDRV_PCM_FORMAT_U24_3BE)
-#define SNDRV_PCM_FMTBIT_S20_3LE	(1ULL << SNDRV_PCM_FORMAT_S20_3LE)
-#define SNDRV_PCM_FMTBIT_U20_3LE	(1ULL << SNDRV_PCM_FORMAT_U20_3LE)
-#define SNDRV_PCM_FMTBIT_S20_3BE	(1ULL << SNDRV_PCM_FORMAT_S20_3BE)
-#define SNDRV_PCM_FMTBIT_U20_3BE	(1ULL << SNDRV_PCM_FORMAT_U20_3BE)
-#define SNDRV_PCM_FMTBIT_S18_3LE	(1ULL << SNDRV_PCM_FORMAT_S18_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_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)
+#define _SNDRV_PCM_FMTBIT(fmt)		(1ULL << (__force int)SNDRV_PCM_FORMAT_##fmt)
+#define SNDRV_PCM_FMTBIT_S8		_SNDRV_PCM_FMTBIT(S8)
+#define SNDRV_PCM_FMTBIT_U8		_SNDRV_PCM_FMTBIT(U8)
+#define SNDRV_PCM_FMTBIT_S16_LE		_SNDRV_PCM_FMTBIT(S16_LE)
+#define SNDRV_PCM_FMTBIT_S16_BE		_SNDRV_PCM_FMTBIT(S16_BE)
+#define SNDRV_PCM_FMTBIT_U16_LE		_SNDRV_PCM_FMTBIT(U16_LE)
+#define SNDRV_PCM_FMTBIT_U16_BE		_SNDRV_PCM_FMTBIT(U16_BE)
+#define SNDRV_PCM_FMTBIT_S24_LE		_SNDRV_PCM_FMTBIT(S24_LE)
+#define SNDRV_PCM_FMTBIT_S24_BE		_SNDRV_PCM_FMTBIT(S24_BE)
+#define SNDRV_PCM_FMTBIT_U24_LE		_SNDRV_PCM_FMTBIT(U24_LE)
+#define SNDRV_PCM_FMTBIT_U24_BE		_SNDRV_PCM_FMTBIT(U24_BE)
+#define SNDRV_PCM_FMTBIT_S32_LE		_SNDRV_PCM_FMTBIT(S32_LE)
+#define SNDRV_PCM_FMTBIT_S32_BE		_SNDRV_PCM_FMTBIT(S32_BE)
+#define SNDRV_PCM_FMTBIT_U32_LE		_SNDRV_PCM_FMTBIT(U32_LE)
+#define SNDRV_PCM_FMTBIT_U32_BE		_SNDRV_PCM_FMTBIT(U32_BE)
+#define SNDRV_PCM_FMTBIT_FLOAT_LE	_SNDRV_PCM_FMTBIT(FLOAT_LE)
+#define SNDRV_PCM_FMTBIT_FLOAT_BE	_SNDRV_PCM_FMTBIT(FLOAT_BE)
+#define SNDRV_PCM_FMTBIT_FLOAT64_LE	_SNDRV_PCM_FMTBIT(FLOAT64_LE)
+#define SNDRV_PCM_FMTBIT_FLOAT64_BE	_SNDRV_PCM_FMTBIT(FLOAT64_BE)
+#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE _SNDRV_PCM_FMTBIT(IEC958_SUBFRAME_LE)
+#define SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_BE _SNDRV_PCM_FMTBIT(IEC958_SUBFRAME_BE)
+#define SNDRV_PCM_FMTBIT_MU_LAW		_SNDRV_PCM_FMTBIT(MU_LAW)
+#define SNDRV_PCM_FMTBIT_A_LAW		_SNDRV_PCM_FMTBIT(A_LAW)
+#define SNDRV_PCM_FMTBIT_IMA_ADPCM	_SNDRV_PCM_FMTBIT(IMA_ADPCM)
+#define SNDRV_PCM_FMTBIT_MPEG		_SNDRV_PCM_FMTBIT(MPEG)
+#define SNDRV_PCM_FMTBIT_GSM		_SNDRV_PCM_FMTBIT(GSM)
+#define SNDRV_PCM_FMTBIT_SPECIAL	_SNDRV_PCM_FMTBIT(SPECIAL)
+#define SNDRV_PCM_FMTBIT_S24_3LE	_SNDRV_PCM_FMTBIT(S24_3LE)
+#define SNDRV_PCM_FMTBIT_U24_3LE	_SNDRV_PCM_FMTBIT(U24_3LE)
+#define SNDRV_PCM_FMTBIT_S24_3BE	_SNDRV_PCM_FMTBIT(S24_3BE)
+#define SNDRV_PCM_FMTBIT_U24_3BE	_SNDRV_PCM_FMTBIT(U24_3BE)
+#define SNDRV_PCM_FMTBIT_S20_3LE	_SNDRV_PCM_FMTBIT(S20_3LE)
+#define SNDRV_PCM_FMTBIT_U20_3LE	_SNDRV_PCM_FMTBIT(U20_3LE)
+#define SNDRV_PCM_FMTBIT_S20_3BE	_SNDRV_PCM_FMTBIT(S20_3BE)
+#define SNDRV_PCM_FMTBIT_U20_3BE	_SNDRV_PCM_FMTBIT(U20_3BE)
+#define SNDRV_PCM_FMTBIT_S18_3LE	_SNDRV_PCM_FMTBIT(S18_3LE)
+#define SNDRV_PCM_FMTBIT_U18_3LE	_SNDRV_PCM_FMTBIT(U18_3LE)
+#define SNDRV_PCM_FMTBIT_S18_3BE	_SNDRV_PCM_FMTBIT(S18_3BE)
+#define SNDRV_PCM_FMTBIT_U18_3BE	_SNDRV_PCM_FMTBIT(U18_3BE)
+#define SNDRV_PCM_FMTBIT_G723_24	_SNDRV_PCM_FMTBIT(G723_24)
+#define SNDRV_PCM_FMTBIT_G723_24_1B	_SNDRV_PCM_FMTBIT(G723_24_1B)
+#define SNDRV_PCM_FMTBIT_G723_40	_SNDRV_PCM_FMTBIT(G723_40)
+#define SNDRV_PCM_FMTBIT_G723_40_1B	_SNDRV_PCM_FMTBIT(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
@@ -490,7 +491,7 @@ int snd_pcm_info_user(struct snd_pcm_substream *substream,
 int snd_pcm_status(struct snd_pcm_substream *substream,
 int snd_pcm_status(struct snd_pcm_substream *substream,
 		   struct snd_pcm_status *status);
 		   struct snd_pcm_status *status);
 int snd_pcm_start(struct snd_pcm_substream *substream);
 int snd_pcm_start(struct snd_pcm_substream *substream);
-int snd_pcm_stop(struct snd_pcm_substream *substream, int status);
+int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t status);
 int snd_pcm_drain_done(struct snd_pcm_substream *substream);
 int snd_pcm_drain_done(struct snd_pcm_substream *substream);
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
 int snd_pcm_suspend(struct snd_pcm_substream *substream);
 int snd_pcm_suspend(struct snd_pcm_substream *substream);
@@ -748,8 +749,8 @@ static inline const struct snd_interval *hw_param_interval_c(const struct snd_pc
 	return &params->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
 	return &params->intervals[var - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL];
 }
 }
 
 
-#define params_access(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS))
-#define params_format(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT))
+#define params_access(p) ((__force snd_pcm_access_t)snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_ACCESS)))
+#define params_format(p) ((__force snd_pcm_format_t)snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_FORMAT)))
 #define params_subformat(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_SUBFORMAT))
 #define params_subformat(p) snd_mask_min(hw_param_mask((p), SNDRV_PCM_HW_PARAM_SUBFORMAT))
 #define params_channels(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_CHANNELS)->min
 #define params_channels(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_CHANNELS)->min
 #define params_rate(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_RATE)->min
 #define params_rate(p) hw_param_interval((p), SNDRV_PCM_HW_PARAM_RATE)->min

+ 1 - 1
include/sound/version.h

@@ -1,3 +1,3 @@
 /* include/version.h */
 /* include/version.h */
-#define CONFIG_SND_VERSION "1.0.23"
+#define CONFIG_SND_VERSION "1.0.24"
 #define CONFIG_SND_DATE ""
 #define CONFIG_SND_DATE ""

+ 10 - 12
sound/core/control.c

@@ -279,33 +279,31 @@ void snd_ctl_free_one(struct snd_kcontrol *kcontrol)
 
 
 EXPORT_SYMBOL(snd_ctl_free_one);
 EXPORT_SYMBOL(snd_ctl_free_one);
 
 
-static unsigned int snd_ctl_hole_check(struct snd_card *card,
-				       unsigned int count)
+static bool snd_ctl_remove_numid_conflict(struct snd_card *card,
+					  unsigned int count)
 {
 {
 	struct snd_kcontrol *kctl;
 	struct snd_kcontrol *kctl;
 
 
 	list_for_each_entry(kctl, &card->controls, list) {
 	list_for_each_entry(kctl, &card->controls, list) {
-		if ((kctl->id.numid <= card->last_numid &&
-		     kctl->id.numid + kctl->count > card->last_numid) ||
-		    (kctl->id.numid <= card->last_numid + count - 1 &&
-		     kctl->id.numid + kctl->count > card->last_numid + count - 1))
-		    	return card->last_numid = kctl->id.numid + kctl->count - 1;
+		if (kctl->id.numid < card->last_numid + 1 + count &&
+		    kctl->id.numid + kctl->count > card->last_numid + 1) {
+		    	card->last_numid = kctl->id.numid + kctl->count - 1;
+			return true;
+		}
 	}
 	}
-	return card->last_numid;
+	return false;
 }
 }
 
 
 static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
 static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
 {
 {
-	unsigned int last_numid, iter = 100000;
+	unsigned int iter = 100000;
 
 
-	last_numid = card->last_numid;
-	while (last_numid != snd_ctl_hole_check(card, count)) {
+	while (snd_ctl_remove_numid_conflict(card, count)) {
 		if (--iter == 0) {
 		if (--iter == 0) {
 			/* this situation is very unlikely */
 			/* this situation is very unlikely */
 			snd_printk(KERN_ERR "unable to allocate new control numid\n");
 			snd_printk(KERN_ERR "unable to allocate new control numid\n");
 			return -ENOMEM;
 			return -ENOMEM;
 		}
 		}
-		last_numid = card->last_numid;
 	}
 	}
 	return 0;
 	return 0;
 }
 }

+ 4 - 3
sound/core/device.c

@@ -225,15 +225,16 @@ int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd)
 {
 {
 	struct snd_device *dev;
 	struct snd_device *dev;
 	int err;
 	int err;
-	unsigned int range_low, range_high;
+	unsigned int range_low, range_high, type;
 
 
 	if (snd_BUG_ON(!card))
 	if (snd_BUG_ON(!card))
 		return -ENXIO;
 		return -ENXIO;
-	range_low = cmd * SNDRV_DEV_TYPE_RANGE_SIZE;
+	range_low = (__force unsigned int)cmd * SNDRV_DEV_TYPE_RANGE_SIZE;
 	range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1;
 	range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1;
       __again:
       __again:
 	list_for_each_entry(dev, &card->devices, list) {
 	list_for_each_entry(dev, &card->devices, list) {
-		if (dev->type >= range_low && dev->type <= range_high) {
+		type = (__force unsigned int)dev->type;
+		if (type >= range_low && type <= range_high) {
 			if ((err = snd_device_free(card, dev->device_data)) < 0)
 			if ((err = snd_device_free(card, dev->device_data)) < 0)
 				return err;
 				return err;
 			goto __again;
 			goto __again;

+ 2 - 1
sound/core/memalloc.c

@@ -192,7 +192,8 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
 	dmab->bytes = 0;
 	dmab->bytes = 0;
 	switch (type) {
 	switch (type) {
 	case SNDRV_DMA_TYPE_CONTINUOUS:
 	case SNDRV_DMA_TYPE_CONTINUOUS:
-		dmab->area = snd_malloc_pages(size, (unsigned long)device);
+		dmab->area = snd_malloc_pages(size,
+					(__force gfp_t)(unsigned long)device);
 		dmab->addr = 0;
 		dmab->addr = 0;
 		break;
 		break;
 #ifdef CONFIG_HAS_DMA
 #ifdef CONFIG_HAS_DMA

+ 4 - 3
sound/core/oss/linear.c

@@ -114,7 +114,8 @@ static snd_pcm_sframes_t linear_transfer(struct snd_pcm_plugin *plugin,
 	return frames;
 	return frames;
 }
 }
 
 
-static void init_data(struct linear_priv *data, int src_format, int dst_format)
+static void init_data(struct linear_priv *data,
+		      snd_pcm_format_t src_format, snd_pcm_format_t dst_format)
 {
 {
 	int src_le, dst_le, src_bytes, dst_bytes;
 	int src_le, dst_le, src_bytes, dst_bytes;
 
 
@@ -140,9 +141,9 @@ static void init_data(struct linear_priv *data, int src_format, int dst_format)
 	if (snd_pcm_format_signed(src_format) !=
 	if (snd_pcm_format_signed(src_format) !=
 	    snd_pcm_format_signed(dst_format)) {
 	    snd_pcm_format_signed(dst_format)) {
 		if (dst_le)
 		if (dst_le)
-			data->flip = cpu_to_le32(0x80000000);
+			data->flip = (__force u32)cpu_to_le32(0x80000000);
 		else
 		else
-			data->flip = cpu_to_be32(0x80000000);
+			data->flip = (__force u32)cpu_to_be32(0x80000000);
 	}
 	}
 }
 }
 
 

+ 6 - 4
sound/core/oss/mixer_oss.c

@@ -190,9 +190,10 @@ static int snd_mixer_oss_get_recsrc(struct snd_mixer_oss_file *fmixer)
 		return -EIO;
 		return -EIO;
 	if (mixer->put_recsrc && mixer->get_recsrc) {	/* exclusive */
 	if (mixer->put_recsrc && mixer->get_recsrc) {	/* exclusive */
 		int err;
 		int err;
-		if ((err = mixer->get_recsrc(fmixer, &result)) < 0)
+		unsigned int index;
+		if ((err = mixer->get_recsrc(fmixer, &index)) < 0)
 			return err;
 			return err;
-		result = 1 << result;
+		result = 1 << index;
 	} else {
 	} else {
 		struct snd_mixer_oss_slot *pslot;
 		struct snd_mixer_oss_slot *pslot;
 		int chn;
 		int chn;
@@ -214,6 +215,7 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr
 	struct snd_mixer_oss *mixer = fmixer->mixer;
 	struct snd_mixer_oss *mixer = fmixer->mixer;
 	struct snd_mixer_oss_slot *pslot;
 	struct snd_mixer_oss_slot *pslot;
 	int chn, active;
 	int chn, active;
+	unsigned int index;
 	int result = 0;
 	int result = 0;
 
 
 	if (mixer == NULL)
 	if (mixer == NULL)
@@ -222,8 +224,8 @@ static int snd_mixer_oss_set_recsrc(struct snd_mixer_oss_file *fmixer, int recsr
 		if (recsrc & ~mixer->oss_recsrc)
 		if (recsrc & ~mixer->oss_recsrc)
 			recsrc &= ~mixer->oss_recsrc;
 			recsrc &= ~mixer->oss_recsrc;
 		mixer->put_recsrc(fmixer, ffz(~recsrc));
 		mixer->put_recsrc(fmixer, ffz(~recsrc));
-		mixer->get_recsrc(fmixer, &result);
-		result = 1 << result;
+		mixer->get_recsrc(fmixer, &index);
+		result = 1 << index;
 	}
 	}
 	for (chn = 0; chn < 31; chn++) {
 	for (chn = 0; chn < 31; chn++) {
 		pslot = &mixer->slots[chn];
 		pslot = &mixer->slots[chn];

+ 1 - 1
sound/core/oss/mulaw.c

@@ -274,7 +274,7 @@ static snd_pcm_sframes_t mulaw_transfer(struct snd_pcm_plugin *plugin,
 	return frames;
 	return frames;
 }
 }
 
 
-static void init_data(struct mulaw_priv *data, int format)
+static void init_data(struct mulaw_priv *data, snd_pcm_format_t format)
 {
 {
 #ifdef SNDRV_LITTLE_ENDIAN
 #ifdef SNDRV_LITTLE_ENDIAN
 	data->cvt_endian = snd_pcm_format_big_endian(format) > 0;
 	data->cvt_endian = snd_pcm_format_big_endian(format) > 0;

+ 28 - 23
sound/core/oss/pcm_oss.c

@@ -41,6 +41,7 @@
 #include <sound/info.h>
 #include <sound/info.h>
 #include <linux/soundcard.h>
 #include <linux/soundcard.h>
 #include <sound/initval.h>
 #include <sound/initval.h>
+#include <sound/mixer_oss.h>
 
 
 #define OSS_ALSAEMULVER		_SIOR ('M', 249, int)
 #define OSS_ALSAEMULVER		_SIOR ('M', 249, int)
 
 
@@ -60,7 +61,6 @@ MODULE_PARM_DESC(nonblock_open, "Don't block opening busy PCM devices.");
 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM);
 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM);
 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1);
 MODULE_ALIAS_SNDRV_MINOR(SNDRV_MINOR_OSS_PCM1);
 
 
-extern int snd_mixer_oss_ioctl_card(struct snd_card *card, unsigned int cmd, unsigned long arg);
 static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file);
 static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file *pcm_oss_file);
 static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file);
 static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file);
 static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file);
 static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file);
@@ -656,7 +656,7 @@ snd_pcm_uframes_t get_hw_ptr_period(struct snd_pcm_runtime *runtime)
 #define AFMT_AC3         0x00000400
 #define AFMT_AC3         0x00000400
 #define AFMT_VORBIS      0x00000800
 #define AFMT_VORBIS      0x00000800
 
 
-static int snd_pcm_oss_format_from(int format)
+static snd_pcm_format_t snd_pcm_oss_format_from(int format)
 {
 {
 	switch (format) {
 	switch (format) {
 	case AFMT_MU_LAW:	return SNDRV_PCM_FORMAT_MU_LAW;
 	case AFMT_MU_LAW:	return SNDRV_PCM_FORMAT_MU_LAW;
@@ -680,7 +680,7 @@ static int snd_pcm_oss_format_from(int format)
 	}
 	}
 }
 }
 
 
-static int snd_pcm_oss_format_to(int format)
+static int snd_pcm_oss_format_to(snd_pcm_format_t format)
 {
 {
 	switch (format) {
 	switch (format) {
 	case SNDRV_PCM_FORMAT_MU_LAW:	return AFMT_MU_LAW;
 	case SNDRV_PCM_FORMAT_MU_LAW:	return AFMT_MU_LAW;
@@ -843,7 +843,8 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
 	size_t oss_frame_size;
 	size_t oss_frame_size;
 	int err;
 	int err;
 	int direct;
 	int direct;
-	int format, sformat, n;
+	snd_pcm_format_t format, sformat;
+	int n;
 	struct snd_mask sformat_mask;
 	struct snd_mask sformat_mask;
 	struct snd_mask mask;
 	struct snd_mask mask;
 
 
@@ -868,11 +869,11 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
 	_snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0);
 	_snd_pcm_hw_param_min(sparams, SNDRV_PCM_HW_PARAM_PERIODS, 2, 0);
 	snd_mask_none(&mask);
 	snd_mask_none(&mask);
 	if (atomic_read(&substream->mmap_count))
 	if (atomic_read(&substream->mmap_count))
-		snd_mask_set(&mask, SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
+		snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
 	else {
 	else {
-		snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_INTERLEAVED);
+		snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED);
 		if (!direct)
 		if (!direct)
-			snd_mask_set(&mask, SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
+			snd_mask_set(&mask, (__force int)SNDRV_PCM_ACCESS_RW_NONINTERLEAVED);
 	}
 	}
 	err = snd_pcm_hw_param_mask(substream, sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask);
 	err = snd_pcm_hw_param_mask(substream, sparams, SNDRV_PCM_HW_PARAM_ACCESS, &mask);
 	if (err < 0) {
 	if (err < 0) {
@@ -891,19 +892,22 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
 	else
 	else
 		sformat = snd_pcm_plug_slave_format(format, &sformat_mask);
 		sformat = snd_pcm_plug_slave_format(format, &sformat_mask);
 
 
-	if (sformat < 0 || !snd_mask_test(&sformat_mask, sformat)) {
-		for (sformat = 0; sformat <= SNDRV_PCM_FORMAT_LAST; sformat++) {
-			if (snd_mask_test(&sformat_mask, sformat) &&
+	if ((__force int)sformat < 0 ||
+	    !snd_mask_test(&sformat_mask, (__force int)sformat)) {
+		for (sformat = (__force snd_pcm_format_t)0;
+		     (__force int)sformat <= (__force int)SNDRV_PCM_FORMAT_LAST;
+		     sformat = (__force snd_pcm_format_t)((__force int)sformat + 1)) {
+			if (snd_mask_test(&sformat_mask, (__force int)sformat) &&
 			    snd_pcm_oss_format_to(sformat) >= 0)
 			    snd_pcm_oss_format_to(sformat) >= 0)
 				break;
 				break;
 		}
 		}
-		if (sformat > SNDRV_PCM_FORMAT_LAST) {
+		if ((__force int)sformat > (__force int)SNDRV_PCM_FORMAT_LAST) {
 			snd_printd("Cannot find a format!!!\n");
 			snd_printd("Cannot find a format!!!\n");
 			err = -EINVAL;
 			err = -EINVAL;
 			goto failure;
 			goto failure;
 		}
 		}
 	}
 	}
-	err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, sformat, 0);
+	err = _snd_pcm_hw_param_set(sparams, SNDRV_PCM_HW_PARAM_FORMAT, (__force int)sformat, 0);
 	if (err < 0)
 	if (err < 0)
 		goto failure;
 		goto failure;
 
 
@@ -912,9 +916,9 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
 	} else {
 	} else {
 		_snd_pcm_hw_params_any(params);
 		_snd_pcm_hw_params_any(params);
 		_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS,
 		_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_ACCESS,
-				      SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
+				      (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED, 0);
 		_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT,
 		_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_FORMAT,
-				      snd_pcm_oss_format_from(runtime->oss.format), 0);
+				      (__force int)snd_pcm_oss_format_from(runtime->oss.format), 0);
 		_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS,
 		_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_CHANNELS,
 				      runtime->oss.channels, 0);
 				      runtime->oss.channels, 0);
 		_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE,
 		_snd_pcm_hw_param_set(params, SNDRV_PCM_HW_PARAM_RATE,
@@ -1185,10 +1189,10 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct snd_pcm_substream *substream, const
 		if (in_kernel) {
 		if (in_kernel) {
 			mm_segment_t fs;
 			mm_segment_t fs;
 			fs = snd_enter_user();
 			fs = snd_enter_user();
-			ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
+			ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
 			snd_leave_user(fs);
 			snd_leave_user(fs);
 		} else {
 		} else {
-			ret = snd_pcm_lib_write(substream, (void __user *)ptr, frames);
+			ret = snd_pcm_lib_write(substream, (void __force __user *)ptr, frames);
 		}
 		}
 		if (ret != -EPIPE && ret != -ESTRPIPE)
 		if (ret != -EPIPE && ret != -ESTRPIPE)
 			break;
 			break;
@@ -1230,10 +1234,10 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream, char *p
 		if (in_kernel) {
 		if (in_kernel) {
 			mm_segment_t fs;
 			mm_segment_t fs;
 			fs = snd_enter_user();
 			fs = snd_enter_user();
-			ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
+			ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
 			snd_leave_user(fs);
 			snd_leave_user(fs);
 		} else {
 		} else {
-			ret = snd_pcm_lib_read(substream, (void __user *)ptr, frames);
+			ret = snd_pcm_lib_read(substream, (void __force __user *)ptr, frames);
 		}
 		}
 		if (ret == -EPIPE) {
 		if (ret == -EPIPE) {
 			if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
 			if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) {
@@ -1333,7 +1337,7 @@ static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const cha
 		struct snd_pcm_plugin_channel *channels;
 		struct snd_pcm_plugin_channel *channels;
 		size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
 		size_t oss_frame_bytes = (runtime->oss.plugin_first->src_width * runtime->oss.plugin_first->src_format.channels) / 8;
 		if (!in_kernel) {
 		if (!in_kernel) {
-			if (copy_from_user(runtime->oss.buffer, (const char __user *)buf, bytes))
+			if (copy_from_user(runtime->oss.buffer, (const char __force __user *)buf, bytes))
 				return -EFAULT;
 				return -EFAULT;
 			buf = runtime->oss.buffer;
 			buf = runtime->oss.buffer;
 		}
 		}
@@ -1429,7 +1433,7 @@ static ssize_t snd_pcm_oss_read2(struct snd_pcm_substream *substream, char *buf,
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	snd_pcm_sframes_t frames, frames1;
 	snd_pcm_sframes_t frames, frames1;
 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
-	char __user *final_dst = (char __user *)buf;
+	char __user *final_dst = (char __force __user *)buf;
 	if (runtime->oss.plugin_first) {
 	if (runtime->oss.plugin_first) {
 		struct snd_pcm_plugin_channel *channels;
 		struct snd_pcm_plugin_channel *channels;
 		size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;
 		size_t oss_frame_bytes = (runtime->oss.plugin_last->dst_width * runtime->oss.plugin_last->dst_format.channels) / 8;
@@ -1549,6 +1553,7 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size)
 {
 {
 	struct snd_pcm_runtime *runtime;
 	struct snd_pcm_runtime *runtime;
 	ssize_t result = 0;
 	ssize_t result = 0;
+	snd_pcm_state_t state;
 	long res;
 	long res;
 	wait_queue_t wait;
 	wait_queue_t wait;
 
 
@@ -1570,9 +1575,9 @@ static int snd_pcm_oss_sync1(struct snd_pcm_substream *substream, size_t size)
 		result = 0;
 		result = 0;
 		set_current_state(TASK_INTERRUPTIBLE);
 		set_current_state(TASK_INTERRUPTIBLE);
 		snd_pcm_stream_lock_irq(substream);
 		snd_pcm_stream_lock_irq(substream);
-		res = runtime->status->state;
+		state = runtime->status->state;
 		snd_pcm_stream_unlock_irq(substream);
 		snd_pcm_stream_unlock_irq(substream);
-		if (res != SNDRV_PCM_STATE_RUNNING) {
+		if (state != SNDRV_PCM_STATE_RUNNING) {
 			set_current_state(TASK_RUNNING);
 			set_current_state(TASK_RUNNING);
 			break;
 			break;
 		}
 		}
@@ -1658,7 +1663,7 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file *pcm_oss_file)
 								   size1);
 								   size1);
 					size1 /= runtime->channels; /* frames */
 					size1 /= runtime->channels; /* frames */
 					fs = snd_enter_user();
 					fs = snd_enter_user();
-					snd_pcm_lib_write(substream, (void __user *)runtime->oss.buffer, size1);
+					snd_pcm_lib_write(substream, (void __force __user *)runtime->oss.buffer, size1);
 					snd_leave_user(fs);
 					snd_leave_user(fs);
 				}
 				}
 			} else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {
 			} else if (runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) {

+ 22 - 18
sound/core/oss/pcm_plugin.c

@@ -264,7 +264,7 @@ snd_pcm_sframes_t snd_pcm_plug_slave_size(struct snd_pcm_substream *plug, snd_pc
 	return frames;
 	return frames;
 }
 }
 
 
-static int snd_pcm_plug_formats(struct snd_mask *mask, int format)
+static int snd_pcm_plug_formats(struct snd_mask *mask, snd_pcm_format_t format)
 {
 {
 	struct snd_mask formats = *mask;
 	struct snd_mask formats = *mask;
 	u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
 	u64 linfmts = (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
@@ -276,16 +276,16 @@ static int snd_pcm_plug_formats(struct snd_mask *mask, int format)
 		       SNDRV_PCM_FMTBIT_U24_3BE | SNDRV_PCM_FMTBIT_S24_3BE |
 		       SNDRV_PCM_FMTBIT_U24_3BE | SNDRV_PCM_FMTBIT_S24_3BE |
 		       SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |
 		       SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_S32_LE |
 		       SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE);
 		       SNDRV_PCM_FMTBIT_U32_BE | SNDRV_PCM_FMTBIT_S32_BE);
-	snd_mask_set(&formats, SNDRV_PCM_FORMAT_MU_LAW);
+	snd_mask_set(&formats, (__force int)SNDRV_PCM_FORMAT_MU_LAW);
 	
 	
 	if (formats.bits[0] & (u32)linfmts)
 	if (formats.bits[0] & (u32)linfmts)
 		formats.bits[0] |= (u32)linfmts;
 		formats.bits[0] |= (u32)linfmts;
 	if (formats.bits[1] & (u32)(linfmts >> 32))
 	if (formats.bits[1] & (u32)(linfmts >> 32))
 		formats.bits[1] |= (u32)(linfmts >> 32);
 		formats.bits[1] |= (u32)(linfmts >> 32);
-	return snd_mask_test(&formats, format);
+	return snd_mask_test(&formats, (__force int)format);
 }
 }
 
 
-static int preferred_formats[] = {
+static snd_pcm_format_t preferred_formats[] = {
 	SNDRV_PCM_FORMAT_S16_LE,
 	SNDRV_PCM_FORMAT_S16_LE,
 	SNDRV_PCM_FORMAT_S16_BE,
 	SNDRV_PCM_FORMAT_S16_BE,
 	SNDRV_PCM_FORMAT_U16_LE,
 	SNDRV_PCM_FORMAT_U16_LE,
@@ -306,24 +306,25 @@ static int preferred_formats[] = {
 	SNDRV_PCM_FORMAT_U8
 	SNDRV_PCM_FORMAT_U8
 };
 };
 
 
-int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask)
+snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
+					   struct snd_mask *format_mask)
 {
 {
 	int i;
 	int i;
 
 
-	if (snd_mask_test(format_mask, format))
+	if (snd_mask_test(format_mask, (__force int)format))
 		return format;
 		return format;
-	if (! snd_pcm_plug_formats(format_mask, format))
-		return -EINVAL;
+	if (!snd_pcm_plug_formats(format_mask, format))
+		return (__force snd_pcm_format_t)-EINVAL;
 	if (snd_pcm_format_linear(format)) {
 	if (snd_pcm_format_linear(format)) {
 		unsigned int width = snd_pcm_format_width(format);
 		unsigned int width = snd_pcm_format_width(format);
 		int unsignd = snd_pcm_format_unsigned(format) > 0;
 		int unsignd = snd_pcm_format_unsigned(format) > 0;
 		int big = snd_pcm_format_big_endian(format) > 0;
 		int big = snd_pcm_format_big_endian(format) > 0;
 		unsigned int badness, best = -1;
 		unsigned int badness, best = -1;
-		int best_format = -1;
+		snd_pcm_format_t best_format = (__force snd_pcm_format_t)-1;
 		for (i = 0; i < ARRAY_SIZE(preferred_formats); i++) {
 		for (i = 0; i < ARRAY_SIZE(preferred_formats); i++) {
-			int f = preferred_formats[i];
+			snd_pcm_format_t f = preferred_formats[i];
 			unsigned int w;
 			unsigned int w;
-			if (!snd_mask_test(format_mask, f))
+			if (!snd_mask_test(format_mask, (__force int)f))
 				continue;
 				continue;
 			w = snd_pcm_format_width(f);
 			w = snd_pcm_format_width(f);
 			if (w >= width)
 			if (w >= width)
@@ -337,17 +338,20 @@ int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask)
 				best = badness;
 				best = badness;
 			}
 			}
 		}
 		}
-		return best_format >= 0 ? best_format : -EINVAL;
+		if ((__force int)best_format >= 0)
+			return best_format;
+		else
+			return (__force snd_pcm_format_t)-EINVAL;
 	} else {
 	} else {
 		switch (format) {
 		switch (format) {
 		case SNDRV_PCM_FORMAT_MU_LAW:
 		case SNDRV_PCM_FORMAT_MU_LAW:
 			for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) {
 			for (i = 0; i < ARRAY_SIZE(preferred_formats); ++i) {
-				int format1 = preferred_formats[i];
-				if (snd_mask_test(format_mask, format1))
+				snd_pcm_format_t format1 = preferred_formats[i];
+				if (snd_mask_test(format_mask, (__force int)format1))
 					return format1;
 					return format1;
 			}
 			}
 		default:
 		default:
-			return -EINVAL;
+			return (__force snd_pcm_format_t)-EINVAL;
 		}
 		}
 	}
 	}
 }
 }
@@ -359,7 +363,7 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *plug,
 	struct snd_pcm_plugin_format tmpformat;
 	struct snd_pcm_plugin_format tmpformat;
 	struct snd_pcm_plugin_format dstformat;
 	struct snd_pcm_plugin_format dstformat;
 	struct snd_pcm_plugin_format srcformat;
 	struct snd_pcm_plugin_format srcformat;
-	int src_access, dst_access;
+	snd_pcm_access_t src_access, dst_access;
 	struct snd_pcm_plugin *plugin = NULL;
 	struct snd_pcm_plugin *plugin = NULL;
 	int err;
 	int err;
 	int stream = snd_pcm_plug_stream(plug);
 	int stream = snd_pcm_plug_stream(plug);
@@ -641,7 +645,7 @@ snd_pcm_sframes_t snd_pcm_plug_read_transfer(struct snd_pcm_substream *plug, str
 }
 }
 
 
 int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_area, size_t dst_offset,
 int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_area, size_t dst_offset,
-			 size_t samples, int format)
+			 size_t samples, snd_pcm_format_t format)
 {
 {
 	/* FIXME: sub byte resolution and odd dst_offset */
 	/* FIXME: sub byte resolution and odd dst_offset */
 	unsigned char *dst;
 	unsigned char *dst;
@@ -688,7 +692,7 @@ int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_area, size_t dst
 
 
 int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_offset,
 int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_area, size_t src_offset,
 		      const struct snd_pcm_channel_area *dst_area, size_t dst_offset,
 		      const struct snd_pcm_channel_area *dst_area, size_t dst_offset,
-		      size_t samples, int format)
+		      size_t samples, snd_pcm_format_t format)
 {
 {
 	/* FIXME: sub byte resolution and odd dst_offset */
 	/* FIXME: sub byte resolution and odd dst_offset */
 	char *src, *dst;
 	char *src, *dst;

+ 6 - 5
sound/core/oss/pcm_plugin.h

@@ -46,7 +46,7 @@ struct snd_pcm_plugin_channel {
 };
 };
 
 
 struct snd_pcm_plugin_format {
 struct snd_pcm_plugin_format {
-	int format;
+	snd_pcm_format_t format;
 	unsigned int rate;
 	unsigned int rate;
 	unsigned int channels;
 	unsigned int channels;
 };
 };
@@ -58,7 +58,7 @@ struct snd_pcm_plugin {
 	struct snd_pcm_plugin_format dst_format;	/* destination format */
 	struct snd_pcm_plugin_format dst_format;	/* destination format */
 	int src_width;			/* sample width in bits */
 	int src_width;			/* sample width in bits */
 	int dst_width;			/* sample width in bits */
 	int dst_width;			/* sample width in bits */
-	int access;
+	snd_pcm_access_t access;
 	snd_pcm_sframes_t (*src_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t dst_frames);
 	snd_pcm_sframes_t (*src_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t dst_frames);
 	snd_pcm_sframes_t (*dst_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t src_frames);
 	snd_pcm_sframes_t (*dst_frames)(struct snd_pcm_plugin *plugin, snd_pcm_uframes_t src_frames);
 	snd_pcm_sframes_t (*client_channels)(struct snd_pcm_plugin *plugin,
 	snd_pcm_sframes_t (*client_channels)(struct snd_pcm_plugin *plugin,
@@ -125,7 +125,8 @@ int snd_pcm_plug_format_plugins(struct snd_pcm_substream *substream,
 				struct snd_pcm_hw_params *params,
 				struct snd_pcm_hw_params *params,
 				struct snd_pcm_hw_params *slave_params);
 				struct snd_pcm_hw_params *slave_params);
 
 
-int snd_pcm_plug_slave_format(int format, struct snd_mask *format_mask);
+snd_pcm_format_t snd_pcm_plug_slave_format(snd_pcm_format_t format,
+					   struct snd_mask *format_mask);
 
 
 int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin);
 int snd_pcm_plugin_append(struct snd_pcm_plugin *plugin);
 
 
@@ -146,12 +147,12 @@ snd_pcm_sframes_t snd_pcm_plugin_client_channels(struct snd_pcm_plugin *plugin,
 
 
 int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_channel,
 int snd_pcm_area_silence(const struct snd_pcm_channel_area *dst_channel,
 			 size_t dst_offset,
 			 size_t dst_offset,
-			 size_t samples, int format);
+			 size_t samples, snd_pcm_format_t format);
 int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_channel,
 int snd_pcm_area_copy(const struct snd_pcm_channel_area *src_channel,
 		      size_t src_offset,
 		      size_t src_offset,
 		      const struct snd_pcm_channel_area *dst_channel,
 		      const struct snd_pcm_channel_area *dst_channel,
 		      size_t dst_offset,
 		      size_t dst_offset,
-		      size_t samples, int format);
+		      size_t samples, snd_pcm_format_t format);
 
 
 void *snd_pcm_plug_buf_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t size);
 void *snd_pcm_plug_buf_alloc(struct snd_pcm_substream *plug, snd_pcm_uframes_t size);
 void snd_pcm_plug_buf_unlock(struct snd_pcm_substream *plug, void *ptr);
 void snd_pcm_plug_buf_unlock(struct snd_pcm_substream *plug, void *ptr);

+ 3 - 3
sound/core/oss/route.c

@@ -25,7 +25,7 @@
 #include "pcm_plugin.h"
 #include "pcm_plugin.h"
 
 
 static void zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts,
 static void zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts,
-		       snd_pcm_uframes_t frames, int format)
+		       snd_pcm_uframes_t frames, snd_pcm_format_t format)
 {
 {
 	int dst = 0;
 	int dst = 0;
 	for (; dst < ndsts; ++dst) {
 	for (; dst < ndsts; ++dst) {
@@ -38,7 +38,7 @@ static void zero_areas(struct snd_pcm_plugin_channel *dvp, int ndsts,
 
 
 static inline void copy_area(const struct snd_pcm_plugin_channel *src_channel,
 static inline void copy_area(const struct snd_pcm_plugin_channel *src_channel,
 			     struct snd_pcm_plugin_channel *dst_channel,
 			     struct snd_pcm_plugin_channel *dst_channel,
-			     snd_pcm_uframes_t frames, int format)
+			     snd_pcm_uframes_t frames, snd_pcm_format_t format)
 {
 {
 	dst_channel->enabled = 1;
 	dst_channel->enabled = 1;
 	snd_pcm_area_copy(&src_channel->area, 0, &dst_channel->area, 0, frames, format);
 	snd_pcm_area_copy(&src_channel->area, 0, &dst_channel->area, 0, frames, format);
@@ -51,7 +51,7 @@ static snd_pcm_sframes_t route_transfer(struct snd_pcm_plugin *plugin,
 {
 {
 	int nsrcs, ndsts, dst;
 	int nsrcs, ndsts, dst;
 	struct snd_pcm_plugin_channel *dvp;
 	struct snd_pcm_plugin_channel *dvp;
-	int format;
+	snd_pcm_format_t format;
 
 
 	if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
 	if (snd_BUG_ON(!plugin || !src_channels || !dst_channels))
 		return -ENXIO;
 		return -ENXIO;

+ 5 - 5
sound/core/pcm.c

@@ -211,9 +211,9 @@ static char *snd_pcm_format_names[] = {
 
 
 const char *snd_pcm_format_name(snd_pcm_format_t format)
 const char *snd_pcm_format_name(snd_pcm_format_t format)
 {
 {
-	if (format >= ARRAY_SIZE(snd_pcm_format_names))
+	if ((__force unsigned int)format >= ARRAY_SIZE(snd_pcm_format_names))
 		return "Unknown";
 		return "Unknown";
-	return snd_pcm_format_names[format];
+	return snd_pcm_format_names[(__force unsigned int)format];
 }
 }
 EXPORT_SYMBOL_GPL(snd_pcm_format_name);
 EXPORT_SYMBOL_GPL(snd_pcm_format_name);
 
 
@@ -269,12 +269,12 @@ static const char *snd_pcm_stream_name(int stream)
 
 
 static const char *snd_pcm_access_name(snd_pcm_access_t access)
 static const char *snd_pcm_access_name(snd_pcm_access_t access)
 {
 {
-	return snd_pcm_access_names[access];
+	return snd_pcm_access_names[(__force int)access];
 }
 }
 
 
 static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat)
 static const char *snd_pcm_subformat_name(snd_pcm_subformat_t subformat)
 {
 {
-	return snd_pcm_subformat_names[subformat];
+	return snd_pcm_subformat_names[(__force int)subformat];
 }
 }
 
 
 static const char *snd_pcm_tstamp_mode_name(int mode)
 static const char *snd_pcm_tstamp_mode_name(int mode)
@@ -284,7 +284,7 @@ static const char *snd_pcm_tstamp_mode_name(int mode)
 
 
 static const char *snd_pcm_state_name(snd_pcm_state_t state)
 static const char *snd_pcm_state_name(snd_pcm_state_t state)
 {
 {
-	return snd_pcm_state_names[state];
+	return snd_pcm_state_names[(__force int)state];
 }
 }
 
 
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
 #if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)

+ 19 - 16
sound/core/pcm_misc.c

@@ -35,7 +35,10 @@ struct pcm_format_data {
 	unsigned char silence[8];	/* silence data to fill */
 	unsigned char silence[8];	/* silence data to fill */
 };
 };
 
 
-static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
+/* we do lots of calculations on snd_pcm_format_t; shut up sparse */
+#define INT	__force int
+
+static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
 	[SNDRV_PCM_FORMAT_S8] = {
 	[SNDRV_PCM_FORMAT_S8] = {
 		.width = 8, .phys = 8, .le = -1, .signd = 1,
 		.width = 8, .phys = 8, .le = -1, .signd = 1,
 		.silence = {},
 		.silence = {},
@@ -215,9 +218,9 @@ static struct pcm_format_data pcm_formats[SNDRV_PCM_FORMAT_LAST+1] = {
 int snd_pcm_format_signed(snd_pcm_format_t format)
 int snd_pcm_format_signed(snd_pcm_format_t format)
 {
 {
 	int val;
 	int val;
-	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+	if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
 		return -EINVAL;
-	if ((val = pcm_formats[format].signd) < 0)
+	if ((val = pcm_formats[(INT)format].signd) < 0)
 		return -EINVAL;
 		return -EINVAL;
 	return val;
 	return val;
 }
 }
@@ -266,9 +269,9 @@ EXPORT_SYMBOL(snd_pcm_format_linear);
 int snd_pcm_format_little_endian(snd_pcm_format_t format)
 int snd_pcm_format_little_endian(snd_pcm_format_t format)
 {
 {
 	int val;
 	int val;
-	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+	if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
 		return -EINVAL;
-	if ((val = pcm_formats[format].le) < 0)
+	if ((val = pcm_formats[(INT)format].le) < 0)
 		return -EINVAL;
 		return -EINVAL;
 	return val;
 	return val;
 }
 }
@@ -304,9 +307,9 @@ EXPORT_SYMBOL(snd_pcm_format_big_endian);
 int snd_pcm_format_width(snd_pcm_format_t format)
 int snd_pcm_format_width(snd_pcm_format_t format)
 {
 {
 	int val;
 	int val;
-	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+	if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
 		return -EINVAL;
-	if ((val = pcm_formats[format].width) == 0)
+	if ((val = pcm_formats[(INT)format].width) == 0)
 		return -EINVAL;
 		return -EINVAL;
 	return val;
 	return val;
 }
 }
@@ -323,9 +326,9 @@ EXPORT_SYMBOL(snd_pcm_format_width);
 int snd_pcm_format_physical_width(snd_pcm_format_t format)
 int snd_pcm_format_physical_width(snd_pcm_format_t format)
 {
 {
 	int val;
 	int val;
-	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+	if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
 		return -EINVAL;
-	if ((val = pcm_formats[format].phys) == 0)
+	if ((val = pcm_formats[(INT)format].phys) == 0)
 		return -EINVAL;
 		return -EINVAL;
 	return val;
 	return val;
 }
 }
@@ -358,11 +361,11 @@ EXPORT_SYMBOL(snd_pcm_format_size);
  */
  */
 const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
 const unsigned char *snd_pcm_format_silence_64(snd_pcm_format_t format)
 {
 {
-	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+	if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
 		return NULL;
 		return NULL;
-	if (! pcm_formats[format].phys)
+	if (! pcm_formats[(INT)format].phys)
 		return NULL;
 		return NULL;
-	return pcm_formats[format].silence;
+	return pcm_formats[(INT)format].silence;
 }
 }
 
 
 EXPORT_SYMBOL(snd_pcm_format_silence_64);
 EXPORT_SYMBOL(snd_pcm_format_silence_64);
@@ -382,16 +385,16 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int
 	int width;
 	int width;
 	unsigned char *dst, *pat;
 	unsigned char *dst, *pat;
 
 
-	if (format < 0 || format > SNDRV_PCM_FORMAT_LAST)
+	if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
 		return -EINVAL;
 		return -EINVAL;
 	if (samples == 0)
 	if (samples == 0)
 		return 0;
 		return 0;
-	width = pcm_formats[format].phys; /* physical width */
-	pat = pcm_formats[format].silence;
+	width = pcm_formats[(INT)format].phys; /* physical width */
+	pat = pcm_formats[(INT)format].silence;
 	if (! width)
 	if (! width)
 		return -EINVAL;
 		return -EINVAL;
 	/* signed or 1 byte data */
 	/* signed or 1 byte data */
-	if (pcm_formats[format].signd == 1 || width <= 8) {
+	if (pcm_formats[(INT)format].signd == 1 || width <= 8) {
 		unsigned int bytes = samples * width / 8;
 		unsigned int bytes = samples * width / 8;
 		memset(data, *pat, bytes);
 		memset(data, *pat, bytes);
 		return 0;
 		return 0;

+ 1 - 1
sound/core/pcm_native.c

@@ -941,7 +941,7 @@ static struct action_ops snd_pcm_action_stop = {
  *
  *
  * The state of each stream is then changed to the given state unconditionally.
  * The state of each stream is then changed to the given state unconditionally.
  */
  */
-int snd_pcm_stop(struct snd_pcm_substream *substream, int state)
+int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t state)
 {
 {
 	return snd_pcm_action(&snd_pcm_action_stop, substream, state);
 	return snd_pcm_action(&snd_pcm_action_stop, substream, state);
 }
 }

+ 2 - 5
sound/core/seq/seq_clientmgr.c

@@ -1052,7 +1052,7 @@ static ssize_t snd_seq_write(struct file *file, const char __user *buf,
 		} else {
 		} else {
 #ifdef CONFIG_COMPAT
 #ifdef CONFIG_COMPAT
 			if (client->convert32 && snd_seq_ev_is_varusr(&event)) {
 			if (client->convert32 && snd_seq_ev_is_varusr(&event)) {
-				void *ptr = compat_ptr(event.data.raw32.d[1]);
+				void *ptr = (void __force *)compat_ptr(event.data.raw32.d[1]);
 				event.data.ext.ptr = ptr;
 				event.data.ext.ptr = ptr;
 			}
 			}
 #endif
 #endif
@@ -2407,7 +2407,7 @@ int snd_seq_kernel_client_ctl(int clientid, unsigned int cmd, void *arg)
 	if (client == NULL)
 	if (client == NULL)
 		return -ENXIO;
 		return -ENXIO;
 	fs = snd_enter_user();
 	fs = snd_enter_user();
-	result = snd_seq_do_ioctl(client, cmd, (void __user *)arg);
+	result = snd_seq_do_ioctl(client, cmd, (void __force __user *)arg);
 	snd_leave_user(fs);
 	snd_leave_user(fs);
 	return result;
 	return result;
 }
 }
@@ -2497,9 +2497,6 @@ static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer,
 }
 }
 
 
 
 
-void snd_seq_info_pool(struct snd_info_buffer *buffer,
-		       struct snd_seq_pool *pool, char *space);
-
 /* exported to seq_info.c */
 /* exported to seq_info.c */
 void snd_seq_info_clients_read(struct snd_info_entry *entry, 
 void snd_seq_info_clients_read(struct snd_info_entry *entry, 
 			       struct snd_info_buffer *buffer)
 			       struct snd_info_buffer *buffer)

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

@@ -86,7 +86,7 @@ int snd_seq_dump_var_event(const struct snd_seq_event *event,
 
 
 	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
 	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
 		char buf[32];
 		char buf[32];
-		char __user *curptr = (char __user *)event->data.ext.ptr;
+		char __user *curptr = (char __force __user *)event->data.ext.ptr;
 		while (len > 0) {
 		while (len > 0) {
 			int size = sizeof(buf);
 			int size = sizeof(buf);
 			if (len < size)
 			if (len < size)
@@ -157,7 +157,7 @@ int snd_seq_expand_var_event(const struct snd_seq_event *event, int count, char
 	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
 	if (event->data.ext.len & SNDRV_SEQ_EXT_USRPTR) {
 		if (! in_kernel)
 		if (! in_kernel)
 			return -EINVAL;
 			return -EINVAL;
-		if (copy_from_user(buf, (void __user *)event->data.ext.ptr, len))
+		if (copy_from_user(buf, (void __force __user *)event->data.ext.ptr, len))
 			return -EFAULT;
 			return -EFAULT;
 		return newlen;
 		return newlen;
 	}
 	}
@@ -343,7 +343,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
 				tmp->event = src->event;
 				tmp->event = src->event;
 				src = src->next;
 				src = src->next;
 			} else if (is_usrptr) {
 			} else if (is_usrptr) {
-				if (copy_from_user(&tmp->event, (char __user *)buf, size)) {
+				if (copy_from_user(&tmp->event, (char __force __user *)buf, size)) {
 					err = -EFAULT;
 					err = -EFAULT;
 					goto __error;
 					goto __error;
 				}
 				}

+ 4 - 0
sound/core/seq/seq_memory.h

@@ -24,6 +24,8 @@
 #include <sound/seq_kernel.h>
 #include <sound/seq_kernel.h>
 #include <linux/poll.h>
 #include <linux/poll.h>
 
 
+struct snd_info_buffer;
+
 /* container for sequencer event (internal use) */
 /* container for sequencer event (internal use) */
 struct snd_seq_event_cell {
 struct snd_seq_event_cell {
 	struct snd_seq_event event;
 	struct snd_seq_event event;
@@ -99,5 +101,7 @@ void snd_sequencer_memory_done(void);
 /* polling */
 /* polling */
 int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, poll_table *wait);
 int snd_seq_pool_poll_wait(struct snd_seq_pool *pool, struct file *file, poll_table *wait);
 
 
+void snd_seq_info_pool(struct snd_info_buffer *buffer,
+		       struct snd_seq_pool *pool, char *space);
 
 
 #endif
 #endif

+ 1 - 1
sound/core/seq/seq_ports.c

@@ -412,7 +412,7 @@ int snd_seq_get_port_info(struct snd_seq_client_port * port,
  * initialization or termination of devices (see seq_midi.c).
  * initialization or termination of devices (see seq_midi.c).
  *
  *
  * If callback_all option is set, the callback function is invoked
  * If callback_all option is set, the callback function is invoked
- * at each connnection/disconnection. 
+ * at each connection/disconnection. 
  */
  */
 
 
 static int subscribe_port(struct snd_seq_client *client,
 static int subscribe_port(struct snd_seq_client *client,

+ 3 - 5
sound/core/timer.c

@@ -186,9 +186,8 @@ static void snd_timer_check_slave(struct snd_timer_instance *slave)
 		list_for_each_entry(master, &timer->open_list_head, open_list) {
 		list_for_each_entry(master, &timer->open_list_head, open_list) {
 			if (slave->slave_class == master->slave_class &&
 			if (slave->slave_class == master->slave_class &&
 			    slave->slave_id == master->slave_id) {
 			    slave->slave_id == master->slave_id) {
-				list_del(&slave->open_list);
-				list_add_tail(&slave->open_list,
-					      &master->slave_list_head);
+				list_move_tail(&slave->open_list,
+					       &master->slave_list_head);
 				spin_lock_irq(&slave_active_lock);
 				spin_lock_irq(&slave_active_lock);
 				slave->master = master;
 				slave->master = master;
 				slave->timer = master->timer;
 				slave->timer = master->timer;
@@ -414,8 +413,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
 static int snd_timer_start1(struct snd_timer *timer, struct snd_timer_instance *timeri,
 static int snd_timer_start1(struct snd_timer *timer, struct snd_timer_instance *timeri,
 			    unsigned long sticks)
 			    unsigned long sticks)
 {
 {
-	list_del(&timeri->active_list);
-	list_add_tail(&timeri->active_list, &timer->active_list_head);
+	list_move_tail(&timeri->active_list, &timer->active_list_head);
 	if (timer->running) {
 	if (timer->running) {
 		if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
 		if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
 			goto __start_now;
 			goto __start_now;

+ 1 - 1
sound/core/vmaster.c

@@ -18,7 +18,7 @@
  * a subset of information returned via ctl info callback
  * a subset of information returned via ctl info callback
  */
  */
 struct link_ctl_info {
 struct link_ctl_info {
-	int type;		/* value type */
+	snd_ctl_elem_type_t type; /* value type */
 	int count;		/* item count */
 	int count;		/* item count */
 	int min_val, max_val;	/* min, max values */
 	int min_val, max_val;	/* min, max values */
 };
 };

+ 9 - 10
sound/drivers/aloop.c

@@ -482,8 +482,9 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
 			cable->streams[SNDRV_PCM_STREAM_CAPTURE];
 			cable->streams[SNDRV_PCM_STREAM_CAPTURE];
 	unsigned long delta_play = 0, delta_capt = 0;
 	unsigned long delta_play = 0, delta_capt = 0;
 	unsigned int running;
 	unsigned int running;
+	unsigned long flags;
 
 
-	spin_lock(&cable->lock);	
+	spin_lock_irqsave(&cable->lock, flags);
 	running = cable->running ^ cable->pause;
 	running = cable->running ^ cable->pause;
 	if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
 	if (running & (1 << SNDRV_PCM_STREAM_PLAYBACK)) {
 		delta_play = jiffies - dpcm_play->last_jiffies;
 		delta_play = jiffies - dpcm_play->last_jiffies;
@@ -495,10 +496,8 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
 		dpcm_capt->last_jiffies += delta_capt;
 		dpcm_capt->last_jiffies += delta_capt;
 	}
 	}
 
 
-	if (delta_play == 0 && delta_capt == 0) {
-		spin_unlock(&cable->lock);
-		return running;
-	}
+	if (delta_play == 0 && delta_capt == 0)
+		goto unlock;
 		
 		
 	if (delta_play > delta_capt) {
 	if (delta_play > delta_capt) {
 		loopback_bytepos_update(dpcm_play, delta_play - delta_capt,
 		loopback_bytepos_update(dpcm_play, delta_play - delta_capt,
@@ -510,14 +509,14 @@ static unsigned int loopback_pos_update(struct loopback_cable *cable)
 		delta_capt = delta_play;
 		delta_capt = delta_play;
 	}
 	}
 
 
-	if (delta_play == 0 && delta_capt == 0) {
-		spin_unlock(&cable->lock);
-		return running;
-	}
+	if (delta_play == 0 && delta_capt == 0)
+		goto unlock;
+
 	/* note delta_capt == delta_play at this moment */
 	/* note delta_capt == delta_play at this moment */
 	loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY);
 	loopback_bytepos_update(dpcm_capt, delta_capt, BYTEPOS_UPDATE_COPY);
 	loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY);
 	loopback_bytepos_update(dpcm_play, delta_play, BYTEPOS_UPDATE_POSONLY);
-	spin_unlock(&cable->lock);
+ unlock:
+	spin_unlock_irqrestore(&cable->lock, flags);
 	return running;
 	return running;
 }
 }
 
 

+ 20 - 36
sound/oss/soundcard.c

@@ -526,31 +526,21 @@ bad:
 }
 }
 
 
 
 
-/* These device names follow the official Linux device list,
- * Documentation/devices.txt.  Let us know if there are other
- * common names we should support for compatibility.
- * Only those devices not created by the generic code in sound_core.c are
- * registered here.
- */
-static const struct {
-	unsigned short minor;
-	char *name;
-	umode_t mode;
-	int *num;
-} dev_list[] = { /* list of minor devices */
-/* seems to be some confusion here -- this device is not in the device list */
-	{SND_DEV_DSP16,     "dspW",	 S_IWUGO | S_IRUSR | S_IRGRP,
-	 &num_audiodevs},
-	{SND_DEV_AUDIO,     "audio",	 S_IWUGO | S_IRUSR | S_IRGRP,
-	 &num_audiodevs},
-};
-
 static int dmabuf;
 static int dmabuf;
 static int dmabug;
 static int dmabug;
 
 
 module_param(dmabuf, int, 0444);
 module_param(dmabuf, int, 0444);
 module_param(dmabug, int, 0444);
 module_param(dmabug, int, 0444);
 
 
+/* additional minors for compatibility */
+struct oss_minor_dev {
+	unsigned short minor;
+	unsigned int enabled;
+} dev_list[] = {
+	{ SND_DEV_DSP16 },
+	{ SND_DEV_AUDIO },
+};
+
 static int __init oss_init(void)
 static int __init oss_init(void)
 {
 {
 	int             err;
 	int             err;
@@ -571,18 +561,12 @@ static int __init oss_init(void)
 	sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
 	sound_dmap_flag = (dmabuf > 0 ? 1 : 0);
 
 
 	for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
 	for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
-		device_create(sound_class, NULL,
-			      MKDEV(SOUND_MAJOR, dev_list[i].minor), NULL,
-			      "%s", dev_list[i].name);
-
-		if (!dev_list[i].num)
-			continue;
-
-		for (j = 1; j < *dev_list[i].num; j++)
-			device_create(sound_class, NULL,
-				      MKDEV(SOUND_MAJOR,
-					    dev_list[i].minor + (j*0x10)),
-				      NULL, "%s%d", dev_list[i].name, j);
+		j = 0;
+		do {
+			unsigned short minor = dev_list[i].minor + j * 0x10;
+			if (!register_sound_special(&oss_sound_fops, minor))
+				dev_list[i].enabled = (1 << j);
+		} while (++j < num_audiodevs);
 	}
 	}
 
 
 	if (sound_nblocks >= MAX_MEM_BLOCKS - 1)
 	if (sound_nblocks >= MAX_MEM_BLOCKS - 1)
@@ -596,11 +580,11 @@ static void __exit oss_cleanup(void)
 	int i, j;
 	int i, j;
 
 
 	for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
 	for (i = 0; i < ARRAY_SIZE(dev_list); i++) {
-		device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor));
-		if (!dev_list[i].num)
-			continue;
-		for (j = 1; j < *dev_list[i].num; j++)
-			device_destroy(sound_class, MKDEV(SOUND_MAJOR, dev_list[i].minor + (j*0x10)));
+		j = 0;
+		do {
+			if (dev_list[i].enabled & (1 << j))
+				unregister_sound_special(dev_list[i].minor);
+		} while (++j < num_audiodevs);
 	}
 	}
 	
 	
 	unregister_sound_special(1);
 	unregister_sound_special(1);

+ 9 - 3
sound/pci/Kconfig

@@ -152,10 +152,16 @@ config SND_AZT3328
 	select SND_MPU401_UART
 	select SND_MPU401_UART
 	select SND_PCM
 	select SND_PCM
 	select SND_RAWMIDI
 	select SND_RAWMIDI
+	select SND_AC97_CODEC
 	help
 	help
 	  Say Y here to include support for Aztech AZF3328 (PCI168)
 	  Say Y here to include support for Aztech AZF3328 (PCI168)
 	  soundcards.
 	  soundcards.
 
 
+	  Supported features: AC97-"conformant" mixer, MPU401/OPL3, analog I/O
+	  (16bit/8bit, many sample rates [<= 66.2kHz], NO hardware mixing),
+	  Digital Enhanced Game Port, 1.024MHz multimedia sequencer timer,
+	  ext. codec (I2S port), onboard amp (4W/4Ohms/ch), suspend/resume.
+
 	  To compile this driver as a module, choose M here: the module
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-azt3328.
 	  will be called snd-azt3328.
 
 
@@ -572,13 +578,13 @@ comment "Don't forget to add built-in firmwares for HDSP driver"
 	depends on SND_HDSP=y
 	depends on SND_HDSP=y
 
 
 config SND_HDSPM
 config SND_HDSPM
-	tristate "RME Hammerfall DSP MADI"
+	tristate "RME Hammerfall DSP MADI/RayDAT/AIO"
 	select SND_HWDEP
 	select SND_HWDEP
 	select SND_RAWMIDI
 	select SND_RAWMIDI
 	select SND_PCM
 	select SND_PCM
 	help
 	help
-	  Say Y here to include support for RME Hammerfall DSP MADI
-	  soundcards.
+	  Say Y here to include support for RME Hammerfall DSP MADI,
+	  RayDAT and AIO soundcards.
 
 
 	  To compile this driver as a module, choose M here: the module
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-hdspm.
 	  will be called snd-hdspm.

+ 56 - 34
sound/pci/ac97/ac97_codec.c

@@ -71,6 +71,12 @@ static const struct ac97_codec_id snd_ac97_codec_id_vendors[] = {
 { 0x414b4d00, 0xffffff00, "Asahi Kasei",	NULL,	NULL },
 { 0x414b4d00, 0xffffff00, "Asahi Kasei",	NULL,	NULL },
 { 0x414c4300, 0xffffff00, "Realtek",		NULL,	NULL },
 { 0x414c4300, 0xffffff00, "Realtek",		NULL,	NULL },
 { 0x414c4700, 0xffffff00, "Realtek",		NULL,	NULL },
 { 0x414c4700, 0xffffff00, "Realtek",		NULL,	NULL },
+/*
+ * This is an _inofficial_ Aztech Labs entry
+ * (value might differ from unknown official Aztech ID),
+ * currently used by the AC97 emulation of the almost-AC97 PCI168 card.
+ */
+{ 0x415a5400, 0xffffff00, "Aztech Labs (emulated)",	NULL,	NULL },
 { 0x434d4900, 0xffffff00, "C-Media Electronics", NULL,	NULL },
 { 0x434d4900, 0xffffff00, "C-Media Electronics", NULL,	NULL },
 { 0x43525900, 0xffffff00, "Cirrus Logic",	NULL,	NULL },
 { 0x43525900, 0xffffff00, "Cirrus Logic",	NULL,	NULL },
 { 0x43585400, 0xffffff00, "Conexant",           NULL,	NULL },
 { 0x43585400, 0xffffff00, "Conexant",           NULL,	NULL },
@@ -127,6 +133,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
 { 0x414c4781, 0xffffffff, "ALC658D",		NULL,	NULL }, /* already patched */
 { 0x414c4781, 0xffffffff, "ALC658D",		NULL,	NULL }, /* already patched */
 { 0x414c4780, 0xfffffff0, "ALC658",		patch_alc655,	NULL },
 { 0x414c4780, 0xfffffff0, "ALC658",		patch_alc655,	NULL },
 { 0x414c4790, 0xfffffff0, "ALC850",		patch_alc850,	NULL },
 { 0x414c4790, 0xfffffff0, "ALC850",		patch_alc850,	NULL },
+{ 0x415a5401, 0xffffffff, "AZF3328",		patch_aztech_azf3328,	NULL },
 { 0x434d4941, 0xffffffff, "CMI9738",		patch_cm9738,	NULL },
 { 0x434d4941, 0xffffffff, "CMI9738",		patch_cm9738,	NULL },
 { 0x434d4961, 0xffffffff, "CMI9739",		patch_cm9739,	NULL },
 { 0x434d4961, 0xffffffff, "CMI9739",		patch_cm9739,	NULL },
 { 0x434d4969, 0xffffffff, "CMI9780",		patch_cm9780,	NULL },
 { 0x434d4969, 0xffffffff, "CMI9780",		patch_cm9780,	NULL },
@@ -590,9 +597,9 @@ static int snd_ac97_put_volsw(struct snd_kcontrol *kcontrol,
 	snd_ac97_page_restore(ac97, page_save);
 	snd_ac97_page_restore(ac97, page_save);
 #ifdef CONFIG_SND_AC97_POWER_SAVE
 #ifdef CONFIG_SND_AC97_POWER_SAVE
 	/* check analog mixer power-down */
 	/* check analog mixer power-down */
-	if ((val_mask & 0x8000) &&
+	if ((val_mask & AC97_PD_EAPD) &&
 	    (kcontrol->private_value & (1<<30))) {
 	    (kcontrol->private_value & (1<<30))) {
-		if (val & 0x8000)
+		if (val & AC97_PD_EAPD)
 			ac97->power_up &= ~(1 << (reg>>1));
 			ac97->power_up &= ~(1 << (reg>>1));
 		else
 		else
 			ac97->power_up |= 1 << (reg>>1);
 			ac97->power_up |= 1 << (reg>>1);
@@ -1035,20 +1042,20 @@ static int snd_ac97_dev_free(struct snd_device *device)
 
 
 static int snd_ac97_try_volume_mix(struct snd_ac97 * ac97, int reg)
 static int snd_ac97_try_volume_mix(struct snd_ac97 * ac97, int reg)
 {
 {
-	unsigned short val, mask = 0x8000;
+	unsigned short val, mask = AC97_MUTE_MASK_MONO;
 
 
 	if (! snd_ac97_valid_reg(ac97, reg))
 	if (! snd_ac97_valid_reg(ac97, reg))
 		return 0;
 		return 0;
 
 
 	switch (reg) {
 	switch (reg) {
 	case AC97_MASTER_TONE:
 	case AC97_MASTER_TONE:
-		return ac97->caps & 0x04 ? 1 : 0;
+		return ac97->caps & AC97_BC_BASS_TREBLE ? 1 : 0;
 	case AC97_HEADPHONE:
 	case AC97_HEADPHONE:
-		return ac97->caps & 0x10 ? 1 : 0;
+		return ac97->caps & AC97_BC_HEADPHONE ? 1 : 0;
 	case AC97_REC_GAIN_MIC:
 	case AC97_REC_GAIN_MIC:
-		return ac97->caps & 0x01 ? 1 : 0;
+		return ac97->caps & AC97_BC_DEDICATED_MIC ? 1 : 0;
 	case AC97_3D_CONTROL:
 	case AC97_3D_CONTROL:
-		if (ac97->caps & 0x7c00) {
+		if (ac97->caps & AC97_BC_3D_TECH_ID_MASK) {
 			val = snd_ac97_read(ac97, reg);
 			val = snd_ac97_read(ac97, reg);
 			/* if nonzero - fixed and we can't set it */
 			/* if nonzero - fixed and we can't set it */
 			return val == 0;
 			return val == 0;
@@ -1104,7 +1111,10 @@ static void check_volume_resolution(struct snd_ac97 *ac97, int reg, unsigned cha
 	*lo_max = *hi_max = 0;
 	*lo_max = *hi_max = 0;
 	for (i = 0 ; i < ARRAY_SIZE(cbit); i++) {
 	for (i = 0 ; i < ARRAY_SIZE(cbit); i++) {
 		unsigned short val;
 		unsigned short val;
-		snd_ac97_write(ac97, reg, 0x8080 | cbit[i] | (cbit[i] << 8));
+		snd_ac97_write(
+			ac97, reg,
+			AC97_MUTE_MASK_STEREO | cbit[i] | (cbit[i] << 8)
+		);
 		/* Do the read twice due to buffers on some ac97 codecs.
 		/* Do the read twice due to buffers on some ac97 codecs.
 		 * e.g. The STAC9704 returns exactly what you wrote to the register
 		 * e.g. The STAC9704 returns exactly what you wrote to the register
 		 * if you read it immediately. This causes the detect routine to fail.
 		 * if you read it immediately. This causes the detect routine to fail.
@@ -1139,14 +1149,14 @@ static void snd_ac97_change_volume_params2(struct snd_ac97 * ac97, int reg, int
 	unsigned short val, val1;
 	unsigned short val, val1;
 
 
 	*max = 63;
 	*max = 63;
-	val = 0x8080 | (0x20 << shift);
+	val = AC97_MUTE_MASK_STEREO | (0x20 << shift);
 	snd_ac97_write(ac97, reg, val);
 	snd_ac97_write(ac97, reg, val);
 	val1 = snd_ac97_read(ac97, reg);
 	val1 = snd_ac97_read(ac97, reg);
 	if (val != val1) {
 	if (val != val1) {
 		*max = 31;
 		*max = 31;
 	}
 	}
 	/* reset volume to zero */
 	/* reset volume to zero */
-	snd_ac97_write_cache(ac97, reg, 0x8080);
+	snd_ac97_write_cache(ac97, reg, AC97_MUTE_MASK_STEREO);
 }
 }
 
 
 static inline int printable(unsigned int x)
 static inline int printable(unsigned int x)
@@ -1183,16 +1193,16 @@ static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg,
 	if (! snd_ac97_valid_reg(ac97, reg))
 	if (! snd_ac97_valid_reg(ac97, reg))
 		return 0;
 		return 0;
 
 
-	mute_mask = 0x8000;
+	mute_mask = AC97_MUTE_MASK_MONO;
 	val = snd_ac97_read(ac97, reg);
 	val = snd_ac97_read(ac97, reg);
 	if (check_stereo || (ac97->flags & AC97_STEREO_MUTES)) {
 	if (check_stereo || (ac97->flags & AC97_STEREO_MUTES)) {
 		/* check whether both mute bits work */
 		/* check whether both mute bits work */
-		val1 = val | 0x8080;
+		val1 = val | AC97_MUTE_MASK_STEREO;
 		snd_ac97_write(ac97, reg, val1);
 		snd_ac97_write(ac97, reg, val1);
 		if (val1 == snd_ac97_read(ac97, reg))
 		if (val1 == snd_ac97_read(ac97, reg))
-			mute_mask = 0x8080;
+			mute_mask = AC97_MUTE_MASK_STEREO;
 	}
 	}
-	if (mute_mask == 0x8080) {
+	if (mute_mask == AC97_MUTE_MASK_STEREO) {
 		struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1);
 		struct snd_kcontrol_new tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1);
 		if (check_amix)
 		if (check_amix)
 			tmp.private_value |= (1 << 30);
 			tmp.private_value |= (1 << 30);
@@ -1268,9 +1278,11 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne
 	err = snd_ctl_add(card, kctl);
 	err = snd_ctl_add(card, kctl);
 	if (err < 0)
 	if (err < 0)
 		return err;
 		return err;
-	snd_ac97_write_cache(ac97, reg,
-			     (snd_ac97_read(ac97, reg) & 0x8080) |
-			     lo_max | (hi_max << 8));
+	snd_ac97_write_cache(
+		ac97, reg,
+		(snd_ac97_read(ac97, reg) & AC97_MUTE_MASK_STEREO)
+		| lo_max | (hi_max << 8)
+	);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1332,7 +1344,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
 			return err;
 			return err;
 	}
 	}
 
 
-	ac97->regs[AC97_CENTER_LFE_MASTER] = 0x8080;
+	ac97->regs[AC97_CENTER_LFE_MASTER] = AC97_MUTE_MASK_STEREO;
 
 
 	/* build center controls */
 	/* build center controls */
 	if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) 
 	if ((snd_ac97_try_volume_mix(ac97, AC97_CENTER_LFE_MASTER)) 
@@ -1410,8 +1422,12 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
 			if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0)
 			if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_pc_beep[idx], ac97))) < 0)
 				return err;
 				return err;
 		set_tlv_db_scale(kctl, db_scale_4bit);
 		set_tlv_db_scale(kctl, db_scale_4bit);
-		snd_ac97_write_cache(ac97, AC97_PC_BEEP,
-				     snd_ac97_read(ac97, AC97_PC_BEEP) | 0x801e);
+		snd_ac97_write_cache(
+			ac97,
+			AC97_PC_BEEP,
+			(snd_ac97_read(ac97, AC97_PC_BEEP)
+				| AC97_MUTE_MASK_MONO | 0x001e)
+		);
 	}
 	}
 	
 	
 	/* build Phone controls */
 	/* build Phone controls */
@@ -1545,7 +1561,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
 	}
 	}
 
 
 	/* build Simulated Stereo Enhancement control */
 	/* build Simulated Stereo Enhancement control */
-	if (ac97->caps & 0x0008) {
+	if (ac97->caps & AC97_BC_SIM_STEREO) {
 		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_STEREO_ENHANCEMENT], ac97))) < 0)
 		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_STEREO_ENHANCEMENT], ac97))) < 0)
 			return err;
 			return err;
 	}
 	}
@@ -1557,7 +1573,7 @@ static int snd_ac97_mixer_build(struct snd_ac97 * ac97)
 	}
 	}
 
 
 	/* build Loudness control */
 	/* build Loudness control */
-	if (ac97->caps & 0x0020) {
+	if (ac97->caps & AC97_BC_LOUDNESS) {
 		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_LOUDNESS], ac97))) < 0)
 		if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_general[AC97_GENERAL_LOUDNESS], ac97))) < 0)
 			return err;
 			return err;
 	}
 	}
@@ -2542,8 +2558,8 @@ void snd_ac97_resume(struct snd_ac97 *ac97)
 			schedule_timeout_uninterruptible(1);
 			schedule_timeout_uninterruptible(1);
 		} while (time_after_eq(end_time, jiffies));
 		} while (time_after_eq(end_time, jiffies));
 		/* FIXME: extra delay */
 		/* FIXME: extra delay */
-		ac97->bus->ops->write(ac97, AC97_MASTER, 0x8000);
-		if (snd_ac97_read(ac97, AC97_MASTER) != 0x8000)
+		ac97->bus->ops->write(ac97, AC97_MASTER, AC97_MUTE_MASK_MONO);
+		if (snd_ac97_read(ac97, AC97_MASTER) != AC97_MUTE_MASK_MONO)
 			msleep(250);
 			msleep(250);
 	} else {
 	} else {
 		end_time = jiffies + msecs_to_jiffies(100);
 		end_time = jiffies + msecs_to_jiffies(100);
@@ -2747,12 +2763,12 @@ static int master_mute_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
 		int rshift = (kcontrol->private_value >> 12) & 0x0f;
 		int rshift = (kcontrol->private_value >> 12) & 0x0f;
 		unsigned short mask;
 		unsigned short mask;
 		if (shift != rshift)
 		if (shift != rshift)
-			mask = 0x8080;
+			mask = AC97_MUTE_MASK_STEREO;
 		else
 		else
-			mask = 0x8000;
-		snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000,
+			mask = AC97_MUTE_MASK_MONO;
+		snd_ac97_update_bits(ac97, AC97_POWERDOWN, AC97_PD_EAPD,
 				     (ac97->regs[AC97_MASTER] & mask) == mask ?
 				     (ac97->regs[AC97_MASTER] & mask) == mask ?
-				     0x8000 : 0);
+				     AC97_PD_EAPD : 0);
 	}
 	}
 	return err;
 	return err;
 }
 }
@@ -2765,7 +2781,10 @@ static int tune_mute_led(struct snd_ac97 *ac97)
 		return -ENOENT;
 		return -ENOENT;
 	msw->put = master_mute_sw_put;
 	msw->put = master_mute_sw_put;
 	snd_ac97_remove_ctl(ac97, "External Amplifier", NULL);
 	snd_ac97_remove_ctl(ac97, "External Amplifier", NULL);
-	snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, 0x8000); /* mute LED on */
+	snd_ac97_update_bits(
+		ac97, AC97_POWERDOWN,
+		AC97_PD_EAPD, AC97_PD_EAPD /* mute LED on */
+	);
 	ac97->scaps |= AC97_SCAP_EAPD_LED;
 	ac97->scaps |= AC97_SCAP_EAPD_LED;
 	return 0;
 	return 0;
 }
 }
@@ -2780,12 +2799,12 @@ static int hp_master_mute_sw_put(struct snd_kcontrol *kcontrol,
 		int rshift = (kcontrol->private_value >> 12) & 0x0f;
 		int rshift = (kcontrol->private_value >> 12) & 0x0f;
 		unsigned short mask;
 		unsigned short mask;
 		if (shift != rshift)
 		if (shift != rshift)
-			mask = 0x8080;
+			mask = AC97_MUTE_MASK_STEREO;
 		else
 		else
-			mask = 0x8000;
-		snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000,
+			mask = AC97_MUTE_MASK_MONO;
+		snd_ac97_update_bits(ac97, AC97_POWERDOWN, AC97_PD_EAPD,
 				     (ac97->regs[AC97_MASTER] & mask) == mask ?
 				     (ac97->regs[AC97_MASTER] & mask) == mask ?
-				     0x8000 : 0);
+				     AC97_PD_EAPD : 0);
 	}
 	}
 	return err;
 	return err;
 }
 }
@@ -2801,7 +2820,10 @@ static int tune_hp_mute_led(struct snd_ac97 *ac97)
 	snd_ac97_remove_ctl(ac97, "External Amplifier", NULL);
 	snd_ac97_remove_ctl(ac97, "External Amplifier", NULL);
 	snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch");
 	snd_ac97_remove_ctl(ac97, "Headphone Playback", "Switch");
 	snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume");
 	snd_ac97_remove_ctl(ac97, "Headphone Playback", "Volume");
-	snd_ac97_update_bits(ac97, AC97_POWERDOWN, 0x8000, 0x8000); /* mute LED on */
+	snd_ac97_update_bits(
+		ac97, AC97_POWERDOWN,
+		AC97_PD_EAPD, AC97_PD_EAPD /* mute LED on */
+	);
 	return 0;
 	return 0;
 }
 }
 
 

+ 52 - 0
sound/pci/ac97/ac97_patch.c

@@ -26,6 +26,15 @@
 #include "ac97_local.h"
 #include "ac97_local.h"
 #include "ac97_patch.h"
 #include "ac97_patch.h"
 
 
+/*
+ *  Forward declarations
+ */
+
+static struct snd_kcontrol *snd_ac97_find_mixer_ctl(struct snd_ac97 *ac97,
+						    const char *name);
+static int snd_ac97_add_vmaster(struct snd_ac97 *ac97, char *name,
+				const unsigned int *tlv, const char **slaves);
+
 /*
 /*
  *  Chip specific initialization
  *  Chip specific initialization
  */
  */
@@ -2940,6 +2949,49 @@ static int patch_alc850(struct snd_ac97 *ac97)
 	return 0;
 	return 0;
 }
 }
 
 
+static int patch_aztech_azf3328_specific(struct snd_ac97 *ac97)
+{
+	struct snd_kcontrol *kctl_3d_center =
+		snd_ac97_find_mixer_ctl(ac97, "3D Control - Center");
+	struct snd_kcontrol *kctl_3d_depth =
+		snd_ac97_find_mixer_ctl(ac97, "3D Control - Depth");
+
+	/*
+	 * 3D register is different from AC97 standard layout
+	 * (also do some renaming, to resemble Windows driver naming)
+	 */
+	if (kctl_3d_center) {
+		kctl_3d_center->private_value =
+			AC97_SINGLE_VALUE(AC97_3D_CONTROL, 1, 0x07, 0);
+		snd_ac97_rename_vol_ctl(ac97,
+			"3D Control - Center", "3D Control - Width"
+		);
+	}
+	if (kctl_3d_depth)
+		kctl_3d_depth->private_value =
+			AC97_SINGLE_VALUE(AC97_3D_CONTROL, 8, 0x03, 0);
+
+	/* Aztech Windows driver calls the
+	   equivalent control "Modem Playback", thus rename it: */
+	snd_ac97_rename_vol_ctl(ac97,
+		"Master Mono Playback", "Modem Playback"
+	);
+	snd_ac97_rename_vol_ctl(ac97,
+		"Headphone Playback", "FM Synth Playback"
+	);
+
+	return 0;
+}
+
+static const struct snd_ac97_build_ops patch_aztech_azf3328_ops = {
+	.build_specific	= patch_aztech_azf3328_specific
+};
+
+static int patch_aztech_azf3328(struct snd_ac97 *ac97)
+{
+	ac97->build_ops = &patch_aztech_azf3328_ops;
+	return 0;
+}
 
 
 /*
 /*
  * C-Media CM97xx codecs
  * C-Media CM97xx codecs

Файловите разлики са ограничени, защото са твърде много
+ 259 - 272
sound/pci/asihpi/asihpi.c


+ 448 - 766
sound/pci/asihpi/hpi.h

@@ -24,17 +24,10 @@
 
 
  The HPI is a low-level hardware abstraction layer to all
  The HPI is a low-level hardware abstraction layer to all
  AudioScience digital audio adapters
  AudioScience digital audio adapters
-*/
-/*
- You must define one operating system that the HPI is to be compiled under
- HPI_OS_WIN32_USER   32bit Windows
- HPI_OS_DSP_C6000    DSP TI C6000  (automatically set)
- HPI_OS_WDM          Windows WDM kernel driver
- HPI_OS_LINUX        Linux userspace
- HPI_OS_LINUX_KERNEL Linux kernel (automatically set)
 
 
 (C) Copyright AudioScience Inc. 1998-2010
 (C) Copyright AudioScience Inc. 1998-2010
-******************************************************************************/
+*/
+
 #ifndef _HPI_H_
 #ifndef _HPI_H_
 #define _HPI_H_
 #define _HPI_H_
 /* HPI Version
 /* HPI Version
@@ -50,20 +43,20 @@ 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, 4, 1)
-#define HPI_VER_STRING "4.04.01"
+#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 6, 0)
+#define HPI_VER_STRING "4.06.00"
 
 
 /* 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)
 
 
 #include <linux/types.h>
 #include <linux/types.h>
-#define HPI_EXCLUDE_DEPRECATED
+#define HPI_BUILD_EXCLUDE_DEPRECATED
+#define HPI_BUILD_KERNEL_MODE
 
 
-/******************************************************************************/
 /******************************************************************************/
 /******************************************************************************/
 /********       HPI API DEFINITIONS                                       *****/
 /********       HPI API DEFINITIONS                                       *****/
 /******************************************************************************/
 /******************************************************************************/
-/******************************************************************************/
+
 /*******************************************/
 /*******************************************/
 /**  Audio format types
 /**  Audio format types
 \ingroup stream
 \ingroup stream
@@ -174,7 +167,6 @@ The range is +1.0 to -1.0, which corresponds to digital fullscale.
 	HPI_FORMAT_UNDEFINED = 0xffff
 	HPI_FORMAT_UNDEFINED = 0xffff
 };
 };
 
 
-/******************************************* in/out Stream states */
 /*******************************************/
 /*******************************************/
 /** Stream States
 /** Stream States
 \ingroup stream
 \ingroup stream
@@ -194,7 +186,7 @@ enum HPI_STREAM_STATES {
 		cards to be ready. */
 		cards to be ready. */
 	HPI_STATE_WAIT = 6
 	HPI_STATE_WAIT = 6
 };
 };
-/******************************************* mixer source node types */
+/*******************************************/
 /** Source node types
 /** Source node types
 \ingroup mixer
 \ingroup mixer
 */
 */
@@ -224,7 +216,7 @@ enum HPI_SOURCENODES {
 		/* AX6 max sourcenode types = 15 */
 		/* AX6 max sourcenode types = 15 */
 };
 };
 
 
-/******************************************* mixer dest node types */
+/*******************************************/
 /** Destination node types
 /** Destination node types
 \ingroup mixer
 \ingroup mixer
 */
 */
@@ -262,11 +254,11 @@ enum HPI_CONTROLS {
 	HPI_CONTROL_MUTE = 4,	/*mute control - not used at present. */
 	HPI_CONTROL_MUTE = 4,	/*mute control - not used at present. */
 	HPI_CONTROL_MULTIPLEXER = 5,	/**< multiplexer control. */
 	HPI_CONTROL_MULTIPLEXER = 5,	/**< multiplexer control. */
 
 
-	HPI_CONTROL_AESEBU_TRANSMITTER = 6,	/**< AES/EBU transmitter control. */
-	HPI_CONTROL_AESEBUTX = HPI_CONTROL_AESEBU_TRANSMITTER,
+	HPI_CONTROL_AESEBU_TRANSMITTER = 6, /**< AES/EBU transmitter control */
+	HPI_CONTROL_AESEBUTX = 6,	/* HPI_CONTROL_AESEBU_TRANSMITTER */
 
 
 	HPI_CONTROL_AESEBU_RECEIVER = 7, /**< AES/EBU receiver control. */
 	HPI_CONTROL_AESEBU_RECEIVER = 7, /**< AES/EBU receiver control. */
-	HPI_CONTROL_AESEBURX = HPI_CONTROL_AESEBU_RECEIVER,
+	HPI_CONTROL_AESEBURX = 7,	/* HPI_CONTROL_AESEBU_RECEIVER */
 
 
 	HPI_CONTROL_LEVEL = 8, /**< level/trim control - works in d_bu. */
 	HPI_CONTROL_LEVEL = 8, /**< level/trim control - works in d_bu. */
 	HPI_CONTROL_TUNER = 9,	/**< tuner control. */
 	HPI_CONTROL_TUNER = 9,	/**< tuner control. */
@@ -281,7 +273,7 @@ enum HPI_CONTROLS {
 	HPI_CONTROL_SAMPLECLOCK = 17,	/**< sample clock control. */
 	HPI_CONTROL_SAMPLECLOCK = 17,	/**< sample clock control. */
 	HPI_CONTROL_MICROPHONE = 18,	/**< microphone control. */
 	HPI_CONTROL_MICROPHONE = 18,	/**< microphone control. */
 	HPI_CONTROL_PARAMETRIC_EQ = 19,	/**< parametric EQ control. */
 	HPI_CONTROL_PARAMETRIC_EQ = 19,	/**< parametric EQ control. */
-	HPI_CONTROL_EQUALIZER = HPI_CONTROL_PARAMETRIC_EQ,
+	HPI_CONTROL_EQUALIZER = 19,	/*HPI_CONTROL_PARAMETRIC_EQ */
 
 
 	HPI_CONTROL_COMPANDER = 20,	/**< compander control. */
 	HPI_CONTROL_COMPANDER = 20,	/**< compander control. */
 	HPI_CONTROL_COBRANET = 21,	/**< cobranet control. */
 	HPI_CONTROL_COBRANET = 21,	/**< cobranet control. */
@@ -296,10 +288,7 @@ enum HPI_CONTROLS {
 /* WARNING types 256 or greater impact bit packing in all AX6 DSP code */
 /* WARNING types 256 or greater impact bit packing in all AX6 DSP code */
 };
 };
 
 
-/* Shorthand names that match attribute names */
-
-/******************************************* ADAPTER ATTRIBUTES ****/
-
+/*******************************************/
 /** Adapter properties
 /** Adapter properties
 These are used in HPI_AdapterSetProperty() and HPI_AdapterGetProperty()
 These are used in HPI_AdapterSetProperty() and HPI_AdapterGetProperty()
 \ingroup adapter
 \ingroup adapter
@@ -330,12 +319,21 @@ by the driver and is not passed on to the DSP at all.
 Indicates the state of the adapter's SSX2 setting. This setting is stored in
 Indicates the state of the adapter's SSX2 setting. This setting is stored in
 non-volatile memory on the adapter. A typical call sequence would be to use
 non-volatile memory on the adapter. A typical call sequence would be to use
 HPI_ADAPTER_PROPERTY_SSX2_SETTING to set SSX2 on the adapter and then to reload
 HPI_ADAPTER_PROPERTY_SSX2_SETTING to set SSX2 on the adapter and then to reload
-the driver. The driver would query HPI_ADAPTER_PROPERTY_SSX2_SETTING during startup
-and if SSX2 is set, it would then call HPI_ADAPTER_PROPERTY_ENABLE_SSX2 to enable
-SSX2 stream mapping within the kernel level of the driver.
+the driver. The driver would query HPI_ADAPTER_PROPERTY_SSX2_SETTING during
+startup and if SSX2 is set, it would then call HPI_ADAPTER_PROPERTY_ENABLE_SSX2
+to enable SSX2 stream mapping within the kernel level of the driver.
 */
 */
 	HPI_ADAPTER_PROPERTY_SSX2_SETTING = 4,
 	HPI_ADAPTER_PROPERTY_SSX2_SETTING = 4,
 
 
+/** Enables/disables PCI(e) IRQ.
+A setting of 0 indicates that no interrupts are being generated. A DSP boot
+this property is set to 0. Setting to a non-zero value specifies the number
+of frames of audio that should be processed between interrupts. This property
+should be set to multiple of the mixer interval as read back from the
+HPI_ADAPTER_PROPERTY_INTERVAL property.
+*/
+	HPI_ADAPTER_PROPERTY_IRQ_RATE = 5,
+
 /** Base number for readonly properties */
 /** Base number for readonly properties */
 	HPI_ADAPTER_PROPERTY_READONLYBASE = 256,
 	HPI_ADAPTER_PROPERTY_READONLYBASE = 256,
 
 
@@ -440,21 +438,30 @@ return value is true (1) or false (0). If the current adapter
 mode is MONO SSX2 is disabled, even though this property will
 mode is MONO SSX2 is disabled, even though this property will
 return true.
 return true.
 */
 */
-	HPI_ADAPTER_PROPERTY_SUPPORTS_SSX2 = 271
+	HPI_ADAPTER_PROPERTY_SUPPORTS_SSX2 = 271,
+/** Readonly supports PCI(e) IRQ.
+Indicates that the adapter in it's current mode supports interrupts
+across the host bus. Note, this does not imply that interrupts are
+enabled. Instead it indicates that they can be enabled.
+*/
+	HPI_ADAPTER_PROPERTY_SUPPORTS_IRQ = 272
 };
 };
 
 
 /** Adapter mode commands
 /** Adapter mode commands
 
 
-Used in wQueryOrSet field of HPI_AdapterSetModeEx().
+Used in wQueryOrSet parameter of HPI_AdapterSetModeEx().
 \ingroup adapter
 \ingroup adapter
 */
 */
 enum HPI_ADAPTER_MODE_CMDS {
 enum HPI_ADAPTER_MODE_CMDS {
+	/** Set the mode to the given parameter */
 	HPI_ADAPTER_MODE_SET = 0,
 	HPI_ADAPTER_MODE_SET = 0,
+	/** Return 0 or error depending whether mode is valid,
+	but don't set the mode */
 	HPI_ADAPTER_MODE_QUERY = 1
 	HPI_ADAPTER_MODE_QUERY = 1
 };
 };
 
 
 /** Adapter Modes
 /** Adapter Modes
-	These are used by HPI_AdapterSetModeEx()
+ These are used by HPI_AdapterSetModeEx()
 
 
 \warning - more than 16 possible modes breaks
 \warning - more than 16 possible modes breaks
 a bitmask in the Windows WAVE DLL
 a bitmask in the Windows WAVE DLL
@@ -629,10 +636,13 @@ enum HPI_MIXER_STORE_COMMAND {
 	HPI_MIXER_STORE_SAVE_SINGLE = 6
 	HPI_MIXER_STORE_SAVE_SINGLE = 6
 };
 };
 
 
-/************************************* CONTROL ATTRIBUTE VALUES ****/
+/****************************/
+/* CONTROL ATTRIBUTE VALUES */
+/****************************/
+
 /** Used by mixer plugin enable functions
 /** Used by mixer plugin enable functions
 
 
-E.g. HPI_ParametricEQ_SetState()
+E.g. HPI_ParametricEq_SetState()
 \ingroup mixer
 \ingroup mixer
 */
 */
 enum HPI_SWITCH_STATES {
 enum HPI_SWITCH_STATES {
@@ -641,6 +651,7 @@ enum HPI_SWITCH_STATES {
 };
 };
 
 
 /* Volume control special gain values */
 /* Volume control special gain values */
+
 /** volumes units are 100ths of a dB
 /** volumes units are 100ths of a dB
 \ingroup volume
 \ingroup volume
 */
 */
@@ -650,6 +661,11 @@ enum HPI_SWITCH_STATES {
 */
 */
 #define HPI_GAIN_OFF                    (-100 * HPI_UNITS_PER_dB)
 #define HPI_GAIN_OFF                    (-100 * HPI_UNITS_PER_dB)
 
 
+/** channel mask specifying all channels
+\ingroup volume
+*/
+#define HPI_BITMASK_ALL_CHANNELS        (0xFFFFFFFF)
+
 /** value returned for no signal
 /** value returned for no signal
 \ingroup meter
 \ingroup meter
 */
 */
@@ -667,7 +683,7 @@ enum HPI_VOLUME_AUTOFADES {
 
 
 /** The physical encoding format of the AESEBU I/O.
 /** The physical encoding format of the AESEBU I/O.
 
 
-Used in HPI_AESEBU_Transmitter_SetFormat(), HPI_AESEBU_Receiver_SetFormat()
+Used in HPI_Aesebu_Transmitter_SetFormat(), HPI_Aesebu_Receiver_SetFormat()
 along with related Get and Query functions
 along with related Get and Query functions
 \ingroup aestx
 \ingroup aestx
 */
 */
@@ -680,7 +696,7 @@ enum HPI_AESEBU_FORMATS {
 
 
 /** AES/EBU error status bits
 /** AES/EBU error status bits
 
 
-Returned by HPI_AESEBU_Receiver_GetErrorStatus()
+Returned by HPI_Aesebu_Receiver_GetErrorStatus()
 \ingroup aesrx
 \ingroup aesrx
 */
 */
 enum HPI_AESEBU_ERRORS {
 enum HPI_AESEBU_ERRORS {
@@ -767,14 +783,6 @@ enum HPI_TUNER_MODE_VALUES {
 	HPI_TUNER_MODE_RDS_RBDS = 2 /**<  RDS - RBDS mode */
 	HPI_TUNER_MODE_RDS_RBDS = 2 /**<  RDS - RBDS mode */
 };
 };
 
 
-/** Tuner Level settings
-\ingroup tuner
-*/
-enum HPI_TUNER_LEVEL {
-	HPI_TUNER_LEVEL_AVERAGE = 0,
-	HPI_TUNER_LEVEL_RAW = 1
-};
-
 /** Tuner Status Bits
 /** Tuner Status Bits
 
 
 These bitfield values are returned by a call to HPI_Tuner_GetStatus().
 These bitfield values are returned by a call to HPI_Tuner_GetStatus().
@@ -783,13 +791,13 @@ Multiple fields are returned from a single call.
 */
 */
 enum HPI_TUNER_STATUS_BITS {
 enum HPI_TUNER_STATUS_BITS {
 	HPI_TUNER_VIDEO_COLOR_PRESENT = 0x0001,	/**< video color is present. */
 	HPI_TUNER_VIDEO_COLOR_PRESENT = 0x0001,	/**< video color is present. */
-	HPI_TUNER_VIDEO_IS_60HZ = 0x0020,	/**< 60 hz video detected. */
-	HPI_TUNER_VIDEO_HORZ_SYNC_MISSING = 0x0040,	/**< video HSYNC is missing. */
-	HPI_TUNER_VIDEO_STATUS_VALID = 0x0100,	/**< video status is valid. */
-	HPI_TUNER_PLL_LOCKED = 0x1000,		/**< the tuner's PLL is locked. */
-	HPI_TUNER_FM_STEREO = 0x2000,		/**< tuner reports back FM stereo. */
-	HPI_TUNER_DIGITAL = 0x0200,		/**< tuner reports digital programming. */
-	HPI_TUNER_MULTIPROGRAM = 0x0400		/**< tuner reports multiple programs. */
+	HPI_TUNER_VIDEO_IS_60HZ = 0x0020, /**< 60 hz video detected. */
+	HPI_TUNER_VIDEO_HORZ_SYNC_MISSING = 0x0040, /**< video HSYNC is missing. */
+	HPI_TUNER_VIDEO_STATUS_VALID = 0x0100, /**< video status is valid. */
+	HPI_TUNER_DIGITAL = 0x0200, /**< tuner reports digital programming. */
+	HPI_TUNER_MULTIPROGRAM = 0x0400, /**< tuner reports multiple programs. */
+	HPI_TUNER_PLL_LOCKED = 0x1000, /**< the tuner's PLL is locked. */
+	HPI_TUNER_FM_STEREO = 0x2000 /**< tuner reports back FM stereo. */
 };
 };
 
 
 /** Channel Modes
 /** Channel Modes
@@ -839,7 +847,7 @@ enum HPI_SAMPLECLOCK_SOURCES {
 	HPI_SAMPLECLOCK_SOURCE_LAST = 10
 	HPI_SAMPLECLOCK_SOURCE_LAST = 10
 };
 };
 
 
-/** Equalizer filter types. Used by HPI_ParametricEQ_SetBand()
+/** Equalizer filter types. Used by HPI_ParametricEq_SetBand()
 \ingroup parmeq
 \ingroup parmeq
 */
 */
 enum HPI_FILTER_TYPE {
 enum HPI_FILTER_TYPE {
@@ -882,7 +890,7 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_INVALID_OBJ = 101,
 	HPI_ERROR_INVALID_OBJ = 101,
 	/** Function does not exist. */
 	/** Function does not exist. */
 	HPI_ERROR_INVALID_FUNC = 102,
 	HPI_ERROR_INVALID_FUNC = 102,
-	/** The specified object (adapter/Stream) does not exist. */
+	/** The specified object does not exist. */
 	HPI_ERROR_INVALID_OBJ_INDEX = 103,
 	HPI_ERROR_INVALID_OBJ_INDEX = 103,
 	/** Trying to access an object that has not been opened yet. */
 	/** Trying to access an object that has not been opened yet. */
 	HPI_ERROR_OBJ_NOT_OPEN = 104,
 	HPI_ERROR_OBJ_NOT_OPEN = 104,
@@ -890,8 +898,7 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_OBJ_ALREADY_OPEN = 105,
 	HPI_ERROR_OBJ_ALREADY_OPEN = 105,
 	/** PCI, ISA resource not valid. */
 	/** PCI, ISA resource not valid. */
 	HPI_ERROR_INVALID_RESOURCE = 106,
 	HPI_ERROR_INVALID_RESOURCE = 106,
-	/** GetInfo call from SubSysFindAdapters failed. */
-	HPI_ERROR_SUBSYSFINDADAPTERS_GETINFO = 107,
+	/* HPI_ERROR_SUBSYSFINDADAPTERS_GETINFO= 107 */
 	/** Default response was never updated with actual error code. */
 	/** Default response was never updated with actual error code. */
 	HPI_ERROR_INVALID_RESPONSE = 108,
 	HPI_ERROR_INVALID_RESPONSE = 108,
 	/** wSize field of response was not updated,
 	/** wSize field of response was not updated,
@@ -899,38 +906,44 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_PROCESSING_MESSAGE = 109,
 	HPI_ERROR_PROCESSING_MESSAGE = 109,
 	/** The network did not respond in a timely manner. */
 	/** The network did not respond in a timely manner. */
 	HPI_ERROR_NETWORK_TIMEOUT = 110,
 	HPI_ERROR_NETWORK_TIMEOUT = 110,
-	/** An HPI handle is invalid (uninitialised?). */
+	/* An HPI handle is invalid (uninitialised?). */
 	HPI_ERROR_INVALID_HANDLE = 111,
 	HPI_ERROR_INVALID_HANDLE = 111,
 	/** A function or attribute has not been implemented yet. */
 	/** A function or attribute has not been implemented yet. */
 	HPI_ERROR_UNIMPLEMENTED = 112,
 	HPI_ERROR_UNIMPLEMENTED = 112,
-	/** There are too many clients attempting to access a network resource. */
+	/** There are too many clients attempting
+	    to access a network resource. */
 	HPI_ERROR_NETWORK_TOO_MANY_CLIENTS = 113,
 	HPI_ERROR_NETWORK_TOO_MANY_CLIENTS = 113,
-	/** Response buffer passed to HPI_Message was smaller than returned response */
+	/** Response buffer passed to HPI_Message
+	    was smaller than returned response.
+	    wSpecificError field of hpi response contains the required size.
+	*/
 	HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL = 114,
 	HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL = 114,
 	/** The returned response did not match the sent message */
 	/** The returned response did not match the sent message */
 	HPI_ERROR_RESPONSE_MISMATCH = 115,
 	HPI_ERROR_RESPONSE_MISMATCH = 115,
+	/** A control setting that should have been cached was not. */
+	HPI_ERROR_CONTROL_CACHING = 116,
+	/** A message buffer in the path to the adapter was smaller
+	    than the message size.
+	    wSpecificError field of hpi response contains the actual size.
+	*/
+	HPI_ERROR_MESSAGE_BUFFER_TOO_SMALL = 117,
 
 
-	/** Too many adapters.*/
-	HPI_ERROR_TOO_MANY_ADAPTERS = 200,
+	/* HPI_ERROR_TOO_MANY_ADAPTERS= 200 */
 	/** Bad adpater. */
 	/** Bad adpater. */
 	HPI_ERROR_BAD_ADAPTER = 201,
 	HPI_ERROR_BAD_ADAPTER = 201,
 	/** Adapter number out of range or not set properly. */
 	/** Adapter number out of range or not set properly. */
 	HPI_ERROR_BAD_ADAPTER_NUMBER = 202,
 	HPI_ERROR_BAD_ADAPTER_NUMBER = 202,
 	/** 2 adapters with the same adapter number. */
 	/** 2 adapters with the same adapter number. */
-	HPI_DUPLICATE_ADAPTER_NUMBER = 203,
-	/** DSP code failed to bootload. */
+	HPI_ERROR_DUPLICATE_ADAPTER_NUMBER = 203,
+	/** DSP code failed to bootload. (unused?) */
 	HPI_ERROR_DSP_BOOTLOAD = 204,
 	HPI_ERROR_DSP_BOOTLOAD = 204,
-	/** Adapter failed DSP code self test. */
-	HPI_ERROR_DSP_SELFTEST = 205,
 	/** Couldn't find or open the DSP code file. */
 	/** Couldn't find or open the DSP code file. */
 	HPI_ERROR_DSP_FILE_NOT_FOUND = 206,
 	HPI_ERROR_DSP_FILE_NOT_FOUND = 206,
 	/** Internal DSP hardware error. */
 	/** Internal DSP hardware error. */
 	HPI_ERROR_DSP_HARDWARE = 207,
 	HPI_ERROR_DSP_HARDWARE = 207,
-	/** Could not allocate memory in DOS. */
-	HPI_ERROR_DOS_MEMORY_ALLOC = 208,
 	/** Could not allocate memory */
 	/** Could not allocate memory */
 	HPI_ERROR_MEMORY_ALLOC = 208,
 	HPI_ERROR_MEMORY_ALLOC = 208,
-	/** Failed to correctly load/config PLD .*/
+	/** Failed to correctly load/config PLD. (unused) */
 	HPI_ERROR_PLD_LOAD = 209,
 	HPI_ERROR_PLD_LOAD = 209,
 	/** Unexpected end of file, block length too big etc. */
 	/** Unexpected end of file, block length too big etc. */
 	HPI_ERROR_DSP_FILE_FORMAT = 210,
 	HPI_ERROR_DSP_FILE_FORMAT = 210,
@@ -939,8 +952,7 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_DSP_FILE_ACCESS_DENIED = 211,
 	HPI_ERROR_DSP_FILE_ACCESS_DENIED = 211,
 	/** First DSP code section header not found in DSP file. */
 	/** First DSP code section header not found in DSP file. */
 	HPI_ERROR_DSP_FILE_NO_HEADER = 212,
 	HPI_ERROR_DSP_FILE_NO_HEADER = 212,
-	/** File read operation on DSP code file failed. */
-	HPI_ERROR_DSP_FILE_READ_ERROR = 213,
+	/* HPI_ERROR_DSP_FILE_READ_ERROR= 213, */
 	/** DSP code for adapter family not found. */
 	/** DSP code for adapter family not found. */
 	HPI_ERROR_DSP_SECTION_NOT_FOUND = 214,
 	HPI_ERROR_DSP_SECTION_NOT_FOUND = 214,
 	/** Other OS specific error opening DSP file. */
 	/** Other OS specific error opening DSP file. */
@@ -950,23 +962,21 @@ enum HPI_ERROR_CODES {
 	/** DSP code section header had size == 0. */
 	/** DSP code section header had size == 0. */
 	HPI_ERROR_DSP_FILE_NULL_HEADER = 217,
 	HPI_ERROR_DSP_FILE_NULL_HEADER = 217,
 
 
-	/** Base number for flash errors. */
-	HPI_ERROR_FLASH = 220,
+	/* HPI_ERROR_FLASH = 220, */
 
 
 	/** Flash has bad checksum */
 	/** Flash has bad checksum */
-	HPI_ERROR_BAD_CHECKSUM = (HPI_ERROR_FLASH + 1),
-	HPI_ERROR_BAD_SEQUENCE = (HPI_ERROR_FLASH + 2),
-	HPI_ERROR_FLASH_ERASE = (HPI_ERROR_FLASH + 3),
-	HPI_ERROR_FLASH_PROGRAM = (HPI_ERROR_FLASH + 4),
-	HPI_ERROR_FLASH_VERIFY = (HPI_ERROR_FLASH + 5),
-	HPI_ERROR_FLASH_TYPE = (HPI_ERROR_FLASH + 6),
-	HPI_ERROR_FLASH_START = (HPI_ERROR_FLASH + 7),
+	HPI_ERROR_BAD_CHECKSUM = 221,
+	HPI_ERROR_BAD_SEQUENCE = 222,
+	HPI_ERROR_FLASH_ERASE = 223,
+	HPI_ERROR_FLASH_PROGRAM = 224,
+	HPI_ERROR_FLASH_VERIFY = 225,
+	HPI_ERROR_FLASH_TYPE = 226,
+	HPI_ERROR_FLASH_START = 227,
 
 
 	/** Reserved for OEMs. */
 	/** Reserved for OEMs. */
 	HPI_ERROR_RESERVED_1 = 290,
 	HPI_ERROR_RESERVED_1 = 290,
 
 
-	/** Stream does not exist. */
-	HPI_ERROR_INVALID_STREAM = 300,
+	/* HPI_ERROR_INVALID_STREAM = 300 use HPI_ERROR_INVALID_OBJ_INDEX */
 	/** Invalid compression format. */
 	/** Invalid compression format. */
 	HPI_ERROR_INVALID_FORMAT = 301,
 	HPI_ERROR_INVALID_FORMAT = 301,
 	/** Invalid format samplerate */
 	/** Invalid format samplerate */
@@ -977,21 +987,19 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_INVALID_BITRATE = 304,
 	HPI_ERROR_INVALID_BITRATE = 304,
 	/** Invalid datasize used for stream read/write. */
 	/** Invalid datasize used for stream read/write. */
 	HPI_ERROR_INVALID_DATASIZE = 305,
 	HPI_ERROR_INVALID_DATASIZE = 305,
-	/** Stream buffer is full during stream write. */
-	HPI_ERROR_BUFFER_FULL = 306,
-	/** Stream buffer is empty during stream read. */
-	HPI_ERROR_BUFFER_EMPTY = 307,
-	/** Invalid datasize used for stream read/write. */
-	HPI_ERROR_INVALID_DATA_TRANSFER = 308,
+	/* HPI_ERROR_BUFFER_FULL = 306 use HPI_ERROR_INVALID_DATASIZE */
+	/* HPI_ERROR_BUFFER_EMPTY = 307 use HPI_ERROR_INVALID_DATASIZE */
+	/** Null data pointer used for stream read/write. */
+	HPI_ERROR_INVALID_DATA_POINTER = 308,
 	/** Packet ordering error for stream read/write. */
 	/** Packet ordering error for stream read/write. */
 	HPI_ERROR_INVALID_PACKET_ORDER = 309,
 	HPI_ERROR_INVALID_PACKET_ORDER = 309,
 
 
 	/** Object can't do requested operation in its current
 	/** Object can't do requested operation in its current
-	state, eg set format, change rec mux state while recording.*/
+	    state, eg set format, change rec mux state while recording.*/
 	HPI_ERROR_INVALID_OPERATION = 310,
 	HPI_ERROR_INVALID_OPERATION = 310,
 
 
-	/** Where an SRG is shared amongst streams, an incompatible samplerate is one
-	that is different to any currently playing or recording stream. */
+	/** Where a SRG is shared amongst streams, an incompatible samplerate
+	    is one that is different to any currently active stream. */
 	HPI_ERROR_INCOMPATIBLE_SAMPLERATE = 311,
 	HPI_ERROR_INCOMPATIBLE_SAMPLERATE = 311,
 	/** Adapter mode is illegal.*/
 	/** Adapter mode is illegal.*/
 	HPI_ERROR_BAD_ADAPTER_MODE = 312,
 	HPI_ERROR_BAD_ADAPTER_MODE = 312,
@@ -1004,6 +1012,8 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_NO_INTERADAPTER_GROUPS = 314,
 	HPI_ERROR_NO_INTERADAPTER_GROUPS = 314,
 	/** Streams on different DSPs cannot be grouped. */
 	/** Streams on different DSPs cannot be grouped. */
 	HPI_ERROR_NO_INTERDSP_GROUPS = 315,
 	HPI_ERROR_NO_INTERDSP_GROUPS = 315,
+	/** Stream wait cancelled before threshold reached. */
+	HPI_ERROR_WAIT_CANCELLED = 316,
 
 
 	/** Invalid mixer node for this adapter. */
 	/** Invalid mixer node for this adapter. */
 	HPI_ERROR_INVALID_NODE = 400,
 	HPI_ERROR_INVALID_NODE = 400,
@@ -1017,6 +1027,7 @@ 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,
+	HPI_ERROR_I2C_MISSING_ACK = 405,
 	/** 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,
@@ -1027,7 +1038,6 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_NVMEM_FAIL = 452,
 	HPI_ERROR_NVMEM_FAIL = 452,
 
 
 	/** I2C */
 	/** I2C */
-	HPI_ERROR_I2C_MISSING_ACK = HPI_ERROR_CONTROL_I2C_MISSING_ACK,
 	HPI_ERROR_I2C_BAD_ADR = 460,
 	HPI_ERROR_I2C_BAD_ADR = 460,
 
 
 	/** Entity errors */
 	/** Entity errors */
@@ -1035,6 +1045,7 @@ enum HPI_ERROR_CODES {
 	HPI_ERROR_ENTITY_ITEM_COUNT = 471,
 	HPI_ERROR_ENTITY_ITEM_COUNT = 471,
 	HPI_ERROR_ENTITY_TYPE_INVALID = 472,
 	HPI_ERROR_ENTITY_TYPE_INVALID = 472,
 	HPI_ERROR_ENTITY_ROLE_INVALID = 473,
 	HPI_ERROR_ENTITY_ROLE_INVALID = 473,
+	HPI_ERROR_ENTITY_SIZE_MISMATCH = 474,
 
 
 	/* AES18 specific errors were 500..507 */
 	/* AES18 specific errors were 500..507 */
 
 
@@ -1044,11 +1055,18 @@ enum HPI_ERROR_CODES {
 	/** hpioct32.c can't obtain mutex */
 	/** hpioct32.c can't obtain mutex */
 	HPI_ERROR_MUTEX_TIMEOUT = 700,
 	HPI_ERROR_MUTEX_TIMEOUT = 700,
 
 
-	/** errors from HPI backends have values >= this */
+	/** Backend errors used to be greater than this.
+	    \deprecated Now, all backends return only errors defined here in hpi.h
+	*/
 	HPI_ERROR_BACKEND_BASE = 900,
 	HPI_ERROR_BACKEND_BASE = 900,
 
 
-	/** indicates a cached u16 value is invalid. */
-	HPI_ERROR_ILLEGAL_CACHE_VALUE = 0xffff
+	/** Communication with DSP failed */
+	HPI_ERROR_DSP_COMMUNICATION = 900
+		/* Note that the dsp communication error is set to this value so that
+		   it remains compatible with any software that expects such errors
+		   to be backend errors i.e. >= 900.
+		   Do not define any new error codes with values > 900.
+		 */
 };
 };
 
 
 /** \defgroup maximums HPI maximum values
 /** \defgroup maximums HPI maximum values
@@ -1075,7 +1093,7 @@ enum HPI_ERROR_CODES {
 
 
 /**\}*/
 /**\}*/
 
 
-/* ////////////////////////////////////////////////////////////////////// */
+/**************/
 /* STRUCTURES */
 /* STRUCTURES */
 #ifndef DISABLE_PRAGMA_PACK1
 #ifndef DISABLE_PRAGMA_PACK1
 #pragma pack(push, 1)
 #pragma pack(push, 1)
@@ -1092,7 +1110,7 @@ struct hpi_format {
 				/**< Stereo/JointStereo/Mono */
 				/**< Stereo/JointStereo/Mono */
 	u16 mode_legacy;
 	u16 mode_legacy;
 				/**< Legacy ancillary mode or idle bit  */
 				/**< Legacy ancillary mode or idle bit  */
-	u16 unused;	      /**< unused */
+	u16 unused;	      /**< Unused */
 	u16 channels; /**< 1,2..., (or ancillary mode or idle bit */
 	u16 channels; /**< 1,2..., (or ancillary mode or idle bit */
 	u16 format;   /**< HPI_FORMAT_PCM16, _MPEG etc. see #HPI_FORMATS. */
 	u16 format;   /**< HPI_FORMAT_PCM16, _MPEG etc. see #HPI_FORMATS. */
 };
 };
@@ -1106,930 +1124,594 @@ struct hpi_anc_frame {
 */
 */
 struct hpi_async_event {
 struct hpi_async_event {
 	u16 event_type;	/**< type of event. \sa async_event  */
 	u16 event_type;	/**< type of event. \sa async_event  */
-	u16 sequence;  /**< sequence number, allows lost event detection */
-	u32 state;    /**< new state */
-	u32 h_object;	 /**< handle to the object returning the event. */
+	u16 sequence; /**< Sequence number, allows lost event detection */
+	u32 state; /**< New state */
+	u32 h_object; /**< handle to the object returning the event. */
 	union {
 	union {
 		struct {
 		struct {
 			u16 index; /**< GPIO bit index. */
 			u16 index; /**< GPIO bit index. */
 		} gpio;
 		} gpio;
 		struct {
 		struct {
 			u16 node_index;	/**< what node is the control on ? */
 			u16 node_index;	/**< what node is the control on ? */
-			u16 node_type;	/**< what type of node is the control on ? */
+			u16 node_type; /**< what type of node is the control on ? */
 		} control;
 		} control;
 	} u;
 	} u;
 };
 };
 
 
-/*/////////////////////////////////////////////////////////////////////////// */
-/* Public HPI Entity related definitions                                     */
-
-struct hpi_entity;
-
-enum e_entity_type {
-	entity_type_null,
-	entity_type_sequence,	/* sequence of potentially heterogeneous TLV entities */
-
-	entity_type_reference,	/* refers to a TLV entity or NULL */
-
-	entity_type_int,	/* 32 bit */
-	entity_type_float,	/* ieee754 binary 32 bit encoding */
-	entity_type_double,
-
-	entity_type_cstring,
-	entity_type_octet,
-	entity_type_ip4_address,
-	entity_type_ip6_address,
-	entity_type_mac_address,
-
-	LAST_ENTITY_TYPE
-};
-
-enum e_entity_role {
-	entity_role_null,
-	entity_role_value,
-	entity_role_classname,
-
-	entity_role_units,
-	entity_role_flags,
-	entity_role_range,
-
-	entity_role_mapping,
-	entity_role_enum,
-
-	entity_role_instance_of,
-	entity_role_depends_on,
-	entity_role_member_of_group,
-	entity_role_value_constraint,
-	entity_role_parameter_port,
-
-	entity_role_block,
-	entity_role_node_group,
-	entity_role_audio_port,
-	entity_role_clock_port,
-	LAST_ENTITY_ROLE
-};
-
 /* skip host side function declarations for
 /* skip host side function declarations for
    DSP compile and documentation extraction */
    DSP compile and documentation extraction */
 
 
-struct hpi_hsubsys {
-	int not_really_used;
-};
-
 #ifndef DISABLE_PRAGMA_PACK1
 #ifndef DISABLE_PRAGMA_PACK1
 #pragma pack(pop)
 #pragma pack(pop)
 #endif
 #endif
 
 
-/*////////////////////////////////////////////////////////////////////////// */
+/*****************/
 /* HPI FUNCTIONS */
 /* HPI FUNCTIONS */
+/*****************/
 
 
-/*/////////////////////////// */
-/* DATA and FORMAT and STREAM */
-
+/* Stream */
 u16 hpi_stream_estimate_buffer_size(struct hpi_format *pF,
 u16 hpi_stream_estimate_buffer_size(struct hpi_format *pF,
 	u32 host_polling_rate_in_milli_seconds, u32 *recommended_buffer_size);
 	u32 host_polling_rate_in_milli_seconds, u32 *recommended_buffer_size);
 
 
-/*/////////// */
-/* SUB SYSTEM */
-struct hpi_hsubsys *hpi_subsys_create(void
-	);
-
-void hpi_subsys_free(const struct hpi_hsubsys *ph_subsys);
-
-u16 hpi_subsys_get_version(const struct hpi_hsubsys *ph_subsys,
-	u32 *pversion);
-
-u16 hpi_subsys_get_version_ex(const struct hpi_hsubsys *ph_subsys,
-	u32 *pversion_ex);
-
-u16 hpi_subsys_get_info(const struct hpi_hsubsys *ph_subsys, u32 *pversion,
-	u16 *pw_num_adapters, u16 aw_adapter_list[], u16 list_length);
-
-u16 hpi_subsys_find_adapters(const struct hpi_hsubsys *ph_subsys,
-	u16 *pw_num_adapters, u16 aw_adapter_list[], u16 list_length);
-
-u16 hpi_subsys_get_num_adapters(const struct hpi_hsubsys *ph_subsys,
-	int *pn_num_adapters);
-
-u16 hpi_subsys_get_adapter(const struct hpi_hsubsys *ph_subsys, int iterator,
-	u32 *padapter_index, u16 *pw_adapter_type);
-
-u16 hpi_subsys_ssx2_bypass(const struct hpi_hsubsys *ph_subsys, u16 bypass);
+/*************/
+/* SubSystem */
+/*************/
 
 
-u16 hpi_subsys_set_host_network_interface(const struct hpi_hsubsys *ph_subsys,
-	const char *sz_interface);
+u16 hpi_subsys_get_version_ex(u32 *pversion_ex);
 
 
-/*///////// */
-/* ADAPTER */
+u16 hpi_subsys_get_num_adapters(int *pn_num_adapters);
 
 
-u16 hpi_adapter_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index);
+u16 hpi_subsys_get_adapter(int iterator, u32 *padapter_index,
+	u16 *pw_adapter_type);
 
 
-u16 hpi_adapter_close(const struct hpi_hsubsys *ph_subsys, u16 adapter_index);
+/***********/
+/* Adapter */
+/***********/
 
 
-u16 hpi_adapter_get_info(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 *pw_num_outstreams, u16 *pw_num_instreams,
-	u16 *pw_version, u32 *pserial_number, u16 *pw_adapter_type);
+u16 hpi_adapter_open(u16 adapter_index);
 
 
-u16 hpi_adapter_get_module_by_index(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 module_index, u16 *pw_num_outputs,
-	u16 *pw_num_inputs, u16 *pw_version, u32 *pserial_number,
-	u16 *pw_module_type, u32 *ph_module);
+u16 hpi_adapter_close(u16 adapter_index);
 
 
-u16 hpi_adapter_set_mode(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 adapter_mode);
+u16 hpi_adapter_get_info(u16 adapter_index, u16 *pw_num_outstreams,
+	u16 *pw_num_instreams, u16 *pw_version, u32 *pserial_number,
+	u16 *pw_adapter_type);
 
 
-u16 hpi_adapter_set_mode_ex(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 adapter_mode, u16 query_or_set);
-
-u16 hpi_adapter_get_mode(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 *padapter_mode);
-
-u16 hpi_adapter_get_assert(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 *assert_present, char *psz_assert,
-	u16 *pw_line_number);
-
-u16 hpi_adapter_get_assert_ex(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 *assert_present, char *psz_assert,
-	u32 *pline_number, u16 *pw_assert_on_dsp);
-
-u16 hpi_adapter_test_assert(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 assert_id);
-
-u16 hpi_adapter_enable_capability(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 capability, u32 key);
-
-u16 hpi_adapter_self_test(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index);
-
-u16 hpi_adapter_debug_read(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 dsp_address, char *p_bytes, int *count_bytes);
-
-u16 hpi_adapter_set_property(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 property, u16 paramter1, u16 paramter2);
-
-u16 hpi_adapter_get_property(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 property, u16 *pw_paramter1,
-	u16 *pw_paramter2);
-
-u16 hpi_adapter_enumerate_property(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 index, u16 what_to_enumerate,
-	u16 property_index, u32 *psetting);
-
-/*////////////// */
-/* NonVol Memory */
-u16 hpi_nv_memory_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u32 *ph_nv_memory, u16 *pw_size_in_bytes);
-
-u16 hpi_nv_memory_read_byte(const struct hpi_hsubsys *ph_subsys,
-	u32 h_nv_memory, u16 index, u16 *pw_data);
-
-u16 hpi_nv_memory_write_byte(const struct hpi_hsubsys *ph_subsys,
-	u32 h_nv_memory, u16 index, u16 data);
-
-/*////////////// */
-/* Digital I/O */
-u16 hpi_gpio_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u32 *ph_gpio, u16 *pw_number_input_bits, u16 *pw_number_output_bits);
-
-u16 hpi_gpio_read_bit(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
-	u16 bit_index, u16 *pw_bit_data);
-
-u16 hpi_gpio_read_all_bits(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
-	u16 aw_all_bit_data[4]
-	);
+u16 hpi_adapter_get_module_by_index(u16 adapter_index, u16 module_index,
+	u16 *pw_num_outputs, u16 *pw_num_inputs, u16 *pw_version,
+	u32 *pserial_number, u16 *pw_module_type, u32 *ph_module);
 
 
-u16 hpi_gpio_write_bit(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
-	u16 bit_index, u16 bit_data);
+u16 hpi_adapter_set_mode(u16 adapter_index, u32 adapter_mode);
 
 
-u16 hpi_gpio_write_status(const struct hpi_hsubsys *ph_subsys, u32 h_gpio,
-	u16 aw_all_bit_data[4]
-	);
+u16 hpi_adapter_set_mode_ex(u16 adapter_index, u32 adapter_mode,
+	u16 query_or_set);
 
 
-/**********************/
-/* Async Event Object */
-/**********************/
-u16 hpi_async_event_open(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u32 *ph_async);
+u16 hpi_adapter_get_mode(u16 adapter_index, u32 *padapter_mode);
 
 
-u16 hpi_async_event_close(const struct hpi_hsubsys *ph_subsys, u32 h_async);
+u16 hpi_adapter_get_assert2(u16 adapter_index, u16 *p_assert_count,
+	char *psz_assert, u32 *p_param1, u32 *p_param2,
+	u32 *p_dsp_string_addr, u16 *p_processor_id);
 
 
-u16 hpi_async_event_wait(const struct hpi_hsubsys *ph_subsys, u32 h_async,
-	u16 maximum_events, struct hpi_async_event *p_events,
-	u16 *pw_number_returned);
+u16 hpi_adapter_test_assert(u16 adapter_index, u16 assert_id);
 
 
-u16 hpi_async_event_get_count(const struct hpi_hsubsys *ph_subsys,
-	u32 h_async, u16 *pw_count);
+u16 hpi_adapter_enable_capability(u16 adapter_index, u16 capability, u32 key);
 
 
-u16 hpi_async_event_get(const struct hpi_hsubsys *ph_subsys, u32 h_async,
-	u16 maximum_events, struct hpi_async_event *p_events,
-	u16 *pw_number_returned);
+u16 hpi_adapter_self_test(u16 adapter_index);
 
 
-/*/////////// */
-/* WATCH-DOG  */
-u16 hpi_watchdog_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u32 *ph_watchdog);
+u16 hpi_adapter_debug_read(u16 adapter_index, u32 dsp_address, char *p_bytes,
+	int *count_bytes);
 
 
-u16 hpi_watchdog_set_time(const struct hpi_hsubsys *ph_subsys, u32 h_watchdog,
-	u32 time_millisec);
+u16 hpi_adapter_set_property(u16 adapter_index, u16 property, u16 paramter1,
+	u16 paramter2);
 
 
-u16 hpi_watchdog_ping(const struct hpi_hsubsys *ph_subsys, u32 h_watchdog);
+u16 hpi_adapter_get_property(u16 adapter_index, u16 property,
+	u16 *pw_paramter1, u16 *pw_paramter2);
 
 
-/**************/
-/* OUT STREAM */
-/**************/
-u16 hpi_outstream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u16 outstream_index, u32 *ph_outstream);
+u16 hpi_adapter_enumerate_property(u16 adapter_index, u16 index,
+	u16 what_to_enumerate, u16 property_index, u32 *psetting);
+/*************/
+/* OutStream */
+/*************/
+u16 hpi_outstream_open(u16 adapter_index, u16 outstream_index,
+	u32 *ph_outstream);
 
 
-u16 hpi_outstream_close(const struct hpi_hsubsys *ph_subsys, u32 h_outstream);
+u16 hpi_outstream_close(u32 h_outstream);
 
 
-u16 hpi_outstream_get_info_ex(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u16 *pw_state, u32 *pbuffer_size, u32 *pdata_to_play,
-	u32 *psamples_played, u32 *pauxiliary_data_to_play);
+u16 hpi_outstream_get_info_ex(u32 h_outstream, u16 *pw_state,
+	u32 *pbuffer_size, u32 *pdata_to_play, u32 *psamples_played,
+	u32 *pauxiliary_data_to_play);
 
 
-u16 hpi_outstream_write_buf(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, const u8 *pb_write_buf, u32 bytes_to_write,
-	const struct hpi_format *p_format);
+u16 hpi_outstream_write_buf(u32 h_outstream, const u8 *pb_write_buf,
+	u32 bytes_to_write, const struct hpi_format *p_format);
 
 
-u16 hpi_outstream_start(const struct hpi_hsubsys *ph_subsys, u32 h_outstream);
+u16 hpi_outstream_start(u32 h_outstream);
 
 
-u16 hpi_outstream_wait_start(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream);
+u16 hpi_outstream_wait_start(u32 h_outstream);
 
 
-u16 hpi_outstream_stop(const struct hpi_hsubsys *ph_subsys, u32 h_outstream);
+u16 hpi_outstream_stop(u32 h_outstream);
 
 
-u16 hpi_outstream_sinegen(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream);
+u16 hpi_outstream_sinegen(u32 h_outstream);
 
 
-u16 hpi_outstream_reset(const struct hpi_hsubsys *ph_subsys, u32 h_outstream);
+u16 hpi_outstream_reset(u32 h_outstream);
 
 
-u16 hpi_outstream_query_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, struct hpi_format *p_format);
+u16 hpi_outstream_query_format(u32 h_outstream, struct hpi_format *p_format);
 
 
-u16 hpi_outstream_set_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, struct hpi_format *p_format);
+u16 hpi_outstream_set_format(u32 h_outstream, struct hpi_format *p_format);
 
 
-u16 hpi_outstream_set_punch_in_out(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 punch_in_sample, u32 punch_out_sample);
+u16 hpi_outstream_set_punch_in_out(u32 h_outstream, u32 punch_in_sample,
+	u32 punch_out_sample);
 
 
-u16 hpi_outstream_set_velocity(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, short velocity);
+u16 hpi_outstream_set_velocity(u32 h_outstream, short velocity);
 
 
-u16 hpi_outstream_ancillary_reset(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u16 mode);
+u16 hpi_outstream_ancillary_reset(u32 h_outstream, u16 mode);
 
 
-u16 hpi_outstream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 *pframes_available);
+u16 hpi_outstream_ancillary_get_info(u32 h_outstream, u32 *pframes_available);
 
 
-u16 hpi_outstream_ancillary_read(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, struct hpi_anc_frame *p_anc_frame_buffer,
+u16 hpi_outstream_ancillary_read(u32 h_outstream,
+	struct hpi_anc_frame *p_anc_frame_buffer,
 	u32 anc_frame_buffer_size_in_bytes,
 	u32 anc_frame_buffer_size_in_bytes,
 	u32 number_of_ancillary_frames_to_read);
 	u32 number_of_ancillary_frames_to_read);
 
 
-u16 hpi_outstream_set_time_scale(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 time_scaleX10000);
+u16 hpi_outstream_set_time_scale(u32 h_outstream, u32 time_scaleX10000);
 
 
-u16 hpi_outstream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 size_in_bytes);
+u16 hpi_outstream_host_buffer_allocate(u32 h_outstream, u32 size_in_bytes);
 
 
-u16 hpi_outstream_host_buffer_free(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream);
+u16 hpi_outstream_host_buffer_free(u32 h_outstream);
 
 
-u16 hpi_outstream_group_add(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 h_stream);
+u16 hpi_outstream_group_add(u32 h_outstream, u32 h_stream);
 
 
-u16 hpi_outstream_group_get_map(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream, u32 *poutstream_map, u32 *pinstream_map);
+u16 hpi_outstream_group_get_map(u32 h_outstream, u32 *poutstream_map,
+	u32 *pinstream_map);
 
 
-u16 hpi_outstream_group_reset(const struct hpi_hsubsys *ph_subsys,
-	u32 h_outstream);
+u16 hpi_outstream_group_reset(u32 h_outstream);
 
 
-/*////////// */
-/* IN_STREAM */
-u16 hpi_instream_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u16 instream_index, u32 *ph_instream);
+/************/
+/* InStream */
+/************/
+u16 hpi_instream_open(u16 adapter_index, u16 instream_index,
+	u32 *ph_instream);
 
 
-u16 hpi_instream_close(const struct hpi_hsubsys *ph_subsys, u32 h_instream);
+u16 hpi_instream_close(u32 h_instream);
 
 
-u16 hpi_instream_query_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, const struct hpi_format *p_format);
+u16 hpi_instream_query_format(u32 h_instream,
+	const struct hpi_format *p_format);
 
 
-u16 hpi_instream_set_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, const struct hpi_format *p_format);
+u16 hpi_instream_set_format(u32 h_instream,
+	const struct hpi_format *p_format);
 
 
-u16 hpi_instream_read_buf(const struct hpi_hsubsys *ph_subsys, u32 h_instream,
-	u8 *pb_read_buf, u32 bytes_to_read);
+u16 hpi_instream_read_buf(u32 h_instream, u8 *pb_read_buf, u32 bytes_to_read);
 
 
-u16 hpi_instream_start(const struct hpi_hsubsys *ph_subsys, u32 h_instream);
+u16 hpi_instream_start(u32 h_instream);
 
 
-u16 hpi_instream_wait_start(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream);
+u16 hpi_instream_wait_start(u32 h_instream);
 
 
-u16 hpi_instream_stop(const struct hpi_hsubsys *ph_subsys, u32 h_instream);
+u16 hpi_instream_stop(u32 h_instream);
 
 
-u16 hpi_instream_reset(const struct hpi_hsubsys *ph_subsys, u32 h_instream);
+u16 hpi_instream_reset(u32 h_instream);
 
 
-u16 hpi_instream_get_info_ex(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u16 *pw_state, u32 *pbuffer_size, u32 *pdata_recorded,
-	u32 *psamples_recorded, u32 *pauxiliary_data_recorded);
+u16 hpi_instream_get_info_ex(u32 h_instream, u16 *pw_state, u32 *pbuffer_size,
+	u32 *pdata_recorded, u32 *psamples_recorded,
+	u32 *pauxiliary_data_recorded);
 
 
-u16 hpi_instream_ancillary_reset(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u16 bytes_per_frame, u16 mode, u16 alignment,
-	u16 idle_bit);
+u16 hpi_instream_ancillary_reset(u32 h_instream, u16 bytes_per_frame,
+	u16 mode, u16 alignment, u16 idle_bit);
 
 
-u16 hpi_instream_ancillary_get_info(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u32 *pframe_space);
+u16 hpi_instream_ancillary_get_info(u32 h_instream, u32 *pframe_space);
 
 
-u16 hpi_instream_ancillary_write(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, const struct hpi_anc_frame *p_anc_frame_buffer,
+u16 hpi_instream_ancillary_write(u32 h_instream,
+	const struct hpi_anc_frame *p_anc_frame_buffer,
 	u32 anc_frame_buffer_size_in_bytes,
 	u32 anc_frame_buffer_size_in_bytes,
 	u32 number_of_ancillary_frames_to_write);
 	u32 number_of_ancillary_frames_to_write);
 
 
-u16 hpi_instream_host_buffer_allocate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u32 size_in_bytes);
+u16 hpi_instream_host_buffer_allocate(u32 h_instream, u32 size_in_bytes);
 
 
-u16 hpi_instream_host_buffer_free(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream);
+u16 hpi_instream_host_buffer_free(u32 h_instream);
 
 
-u16 hpi_instream_group_add(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u32 h_stream);
+u16 hpi_instream_group_add(u32 h_instream, u32 h_stream);
 
 
-u16 hpi_instream_group_get_map(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream, u32 *poutstream_map, u32 *pinstream_map);
+u16 hpi_instream_group_get_map(u32 h_instream, u32 *poutstream_map,
+	u32 *pinstream_map);
 
 
-u16 hpi_instream_group_reset(const struct hpi_hsubsys *ph_subsys,
-	u32 h_instream);
+u16 hpi_instream_group_reset(u32 h_instream);
 
 
 /*********/
 /*********/
-/* MIXER */
+/* Mixer */
 /*********/
 /*********/
-u16 hpi_mixer_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u32 *ph_mixer);
-
-u16 hpi_mixer_close(const struct hpi_hsubsys *ph_subsys, u32 h_mixer);
-
-u16 hpi_mixer_get_control(const struct hpi_hsubsys *ph_subsys, u32 h_mixer,
-	u16 src_node_type, u16 src_node_type_index, u16 dst_node_type,
-	u16 dst_node_type_index, u16 control_type, u32 *ph_control);
-
-u16 hpi_mixer_get_control_by_index(const struct hpi_hsubsys *ph_subsys,
-	u32 h_mixer, u16 control_index, u16 *pw_src_node_type,
-	u16 *pw_src_node_index, u16 *pw_dst_node_type, u16 *pw_dst_node_index,
-	u16 *pw_control_type, u32 *ph_control);
-
-u16 hpi_mixer_store(const struct hpi_hsubsys *ph_subsys, u32 h_mixer,
-	enum HPI_MIXER_STORE_COMMAND command, u16 index);
-/*************************/
-/* mixer CONTROLS                */
-/*************************/
-/*************************/
-/* volume control                */
-/*************************/
-u16 hpi_volume_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_gain0_01dB[HPI_MAX_CHANNELS]
+u16 hpi_mixer_open(u16 adapter_index, u32 *ph_mixer);
+
+u16 hpi_mixer_close(u32 h_mixer);
+
+u16 hpi_mixer_get_control(u32 h_mixer, u16 src_node_type,
+	u16 src_node_type_index, u16 dst_node_type, u16 dst_node_type_index,
+	u16 control_type, u32 *ph_control);
+
+u16 hpi_mixer_get_control_by_index(u32 h_mixer, u16 control_index,
+	u16 *pw_src_node_type, u16 *pw_src_node_index, u16 *pw_dst_node_type,
+	u16 *pw_dst_node_index, u16 *pw_control_type, u32 *ph_control);
+
+u16 hpi_mixer_store(u32 h_mixer, enum HPI_MIXER_STORE_COMMAND command,
+	u16 index);
+/************/
+/* Controls */
+/************/
+/******************/
+/* Volume control */
+/******************/
+u16 hpi_volume_set_gain(u32 h_control, short an_gain0_01dB[HPI_MAX_CHANNELS]
 	);
 	);
 
 
-u16 hpi_volume_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
+u16 hpi_volume_get_gain(u32 h_control,
 	short an_gain0_01dB_out[HPI_MAX_CHANNELS]
 	short an_gain0_01dB_out[HPI_MAX_CHANNELS]
 	);
 	);
 
 
+u16 hpi_volume_set_mute(u32 h_control, u32 mute);
+
+u16 hpi_volume_get_mute(u32 h_control, u32 *mute);
+
 #define hpi_volume_get_range hpi_volume_query_range
 #define hpi_volume_get_range hpi_volume_query_range
-u16 hpi_volume_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB);
+u16 hpi_volume_query_range(u32 h_control, short *min_gain_01dB,
+	short *max_gain_01dB, short *step_gain_01dB);
 
 
-u16 hpi_volume_query_channels(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_volume, u32 *p_channels);
+u16 hpi_volume_query_channels(const u32 h_volume, u32 *p_channels);
 
 
-u16 hpi_volume_auto_fade(const struct hpi_hsubsys *ph_subsys, u32 h_control,
+u16 hpi_volume_auto_fade(u32 h_control,
 	short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms);
 	short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms);
 
 
-u16 hpi_volume_auto_fade_profile(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, short an_stop_gain0_01dB[HPI_MAX_CHANNELS],
-	u32 duration_ms, u16 profile);
+u16 hpi_volume_auto_fade_profile(u32 h_control,
+	short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms,
+	u16 profile);
 
 
-/*************************/
-/* level control         */
-/*************************/
-u16 hpi_level_query_range(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *min_gain_01dB, short *max_gain_01dB, short *step_gain_01dB);
+/*****************/
+/* Level control */
+/*****************/
+u16 hpi_level_query_range(u32 h_control, short *min_gain_01dB,
+	short *max_gain_01dB, short *step_gain_01dB);
 
 
-u16 hpi_level_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_gain0_01dB[HPI_MAX_CHANNELS]
+u16 hpi_level_set_gain(u32 h_control, short an_gain0_01dB[HPI_MAX_CHANNELS]
 	);
 	);
 
 
-u16 hpi_level_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
+u16 hpi_level_get_gain(u32 h_control,
 	short an_gain0_01dB_out[HPI_MAX_CHANNELS]
 	short an_gain0_01dB_out[HPI_MAX_CHANNELS]
 	);
 	);
 
 
-/*************************/
-/* meter control                 */
-/*************************/
-u16 hpi_meter_query_channels(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_meter, u32 *p_channels);
+/*****************/
+/* Meter control */
+/*****************/
+u16 hpi_meter_query_channels(const u32 h_meter, u32 *p_channels);
 
 
-u16 hpi_meter_get_peak(const struct hpi_hsubsys *ph_subsys, u32 h_control,
+u16 hpi_meter_get_peak(u32 h_control,
 	short an_peak0_01dB_out[HPI_MAX_CHANNELS]
 	short an_peak0_01dB_out[HPI_MAX_CHANNELS]
 	);
 	);
 
 
-u16 hpi_meter_get_rms(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_peak0_01dB_out[HPI_MAX_CHANNELS]
+u16 hpi_meter_get_rms(u32 h_control, short an_peak0_01dB_out[HPI_MAX_CHANNELS]
 	);
 	);
 
 
-u16 hpi_meter_set_peak_ballistics(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 attack, u16 decay);
+u16 hpi_meter_set_peak_ballistics(u32 h_control, u16 attack, u16 decay);
 
 
-u16 hpi_meter_set_rms_ballistics(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 attack, u16 decay);
+u16 hpi_meter_set_rms_ballistics(u32 h_control, u16 attack, u16 decay);
 
 
-u16 hpi_meter_get_peak_ballistics(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *attack, u16 *decay);
+u16 hpi_meter_get_peak_ballistics(u32 h_control, u16 *attack, u16 *decay);
 
 
-u16 hpi_meter_get_rms_ballistics(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *attack, u16 *decay);
+u16 hpi_meter_get_rms_ballistics(u32 h_control, u16 *attack, u16 *decay);
 
 
-/*************************/
-/* channel mode control  */
-/*************************/
-u16 hpi_channel_mode_query_mode(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_mode, const u32 index, u16 *pw_mode);
+/************************/
+/* ChannelMode control */
+/************************/
+u16 hpi_channel_mode_query_mode(const u32 h_mode, const u32 index,
+	u16 *pw_mode);
 
 
-u16 hpi_channel_mode_set(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 mode);
+u16 hpi_channel_mode_set(u32 h_control, u16 mode);
 
 
-u16 hpi_channel_mode_get(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 *mode);
+u16 hpi_channel_mode_get(u32 h_control, u16 *mode);
 
 
-/*************************/
-/* Tuner control                 */
-/*************************/
-u16 hpi_tuner_query_band(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, const u32 index, u16 *pw_band);
+/*****************/
+/* Tuner control */
+/*****************/
+u16 hpi_tuner_query_band(const u32 h_tuner, const u32 index, u16 *pw_band);
 
 
-u16 hpi_tuner_set_band(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 band);
+u16 hpi_tuner_set_band(u32 h_control, u16 band);
 
 
-u16 hpi_tuner_get_band(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 *pw_band);
+u16 hpi_tuner_get_band(u32 h_control, u16 *pw_band);
 
 
-u16 hpi_tuner_query_frequency(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, const u32 index, const u16 band, u32 *pfreq);
+u16 hpi_tuner_query_frequency(const u32 h_tuner, const u32 index,
+	const u16 band, u32 *pfreq);
 
 
-u16 hpi_tuner_set_frequency(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 freq_ink_hz);
+u16 hpi_tuner_set_frequency(u32 h_control, u32 freq_ink_hz);
 
 
-u16 hpi_tuner_get_frequency(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pw_freq_ink_hz);
+u16 hpi_tuner_get_frequency(u32 h_control, u32 *pw_freq_ink_hz);
 
 
-u16 hpi_tuner_getRF_level(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *pw_level);
+u16 hpi_tuner_get_rf_level(u32 h_control, short *pw_level);
 
 
-u16 hpi_tuner_get_rawRF_level(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, short *pw_level);
+u16 hpi_tuner_get_raw_rf_level(u32 h_control, short *pw_level);
 
 
-u16 hpi_tuner_query_gain(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, const u32 index, u16 *pw_gain);
+u16 hpi_tuner_query_gain(const u32 h_tuner, const u32 index, u16 *pw_gain);
 
 
-u16 hpi_tuner_set_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short gain);
+u16 hpi_tuner_set_gain(u32 h_control, short gain);
 
 
-u16 hpi_tuner_get_gain(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *pn_gain);
+u16 hpi_tuner_get_gain(u32 h_control, short *pn_gain);
 
 
-u16 hpi_tuner_get_status(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u16 *pw_status_mask, u16 *pw_status);
+u16 hpi_tuner_get_status(u32 h_control, u16 *pw_status_mask, u16 *pw_status);
 
 
-u16 hpi_tuner_set_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 mode, u32 value);
+u16 hpi_tuner_set_mode(u32 h_control, u32 mode, u32 value);
 
 
-u16 hpi_tuner_get_mode(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 mode, u32 *pn_value);
+u16 hpi_tuner_get_mode(u32 h_control, u32 mode, u32 *pn_value);
 
 
-u16 hpi_tuner_getRDS(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	char *p_rds_data);
+u16 hpi_tuner_get_rds(u32 h_control, char *p_rds_data);
 
 
-u16 hpi_tuner_query_deemphasis(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, const u32 index, const u16 band, u32 *pdeemphasis);
+u16 hpi_tuner_query_deemphasis(const u32 h_tuner, const u32 index,
+	const u16 band, u32 *pdeemphasis);
 
 
-u16 hpi_tuner_set_deemphasis(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 deemphasis);
-u16 hpi_tuner_get_deemphasis(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pdeemphasis);
+u16 hpi_tuner_set_deemphasis(u32 h_control, u32 deemphasis);
+u16 hpi_tuner_get_deemphasis(u32 h_control, u32 *pdeemphasis);
 
 
-u16 hpi_tuner_query_program(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_tuner, u32 *pbitmap_program);
+u16 hpi_tuner_query_program(const u32 h_tuner, u32 *pbitmap_program);
 
 
-u16 hpi_tuner_set_program(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 program);
+u16 hpi_tuner_set_program(u32 h_control, u32 program);
 
 
-u16 hpi_tuner_get_program(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 *pprogram);
+u16 hpi_tuner_get_program(u32 h_control, u32 *pprogram);
 
 
-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);
+u16 hpi_tuner_get_hd_radio_dsp_version(u32 h_control, char *psz_dsp_version,
+	const u32 string_size);
 
 
-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);
+u16 hpi_tuner_get_hd_radio_sdk_version(u32 h_control, char *psz_sdk_version,
+	const u32 string_size);
 
 
-u16 hpi_tuner_get_hd_radio_signal_quality(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pquality);
+u16 hpi_tuner_get_hd_radio_signal_quality(u32 h_control, u32 *pquality);
 
 
-u16 hpi_tuner_get_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pblend);
+u16 hpi_tuner_get_hd_radio_signal_blend(u32 h_control, u32 *pblend);
 
 
-u16 hpi_tuner_set_hd_radio_signal_blend(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, const u32 blend);
+u16 hpi_tuner_set_hd_radio_signal_blend(u32 h_control, const u32 blend);
 
 
-/****************************/
-/* PADs control             */
-/****************************/
+/***************/
+/* PAD control */
+/***************/
 
 
-u16 HPI_PAD__get_channel_name(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, char *psz_string, const u32 string_length);
+u16 hpi_pad_get_channel_name(u32 h_control, char *psz_string,
+	const u32 string_length);
 
 
-u16 HPI_PAD__get_artist(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	char *psz_string, const u32 string_length);
+u16 hpi_pad_get_artist(u32 h_control, char *psz_string,
+	const u32 string_length);
 
 
-u16 HPI_PAD__get_title(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	char *psz_string, const u32 string_length);
+u16 hpi_pad_get_title(u32 h_control, char *psz_string,
+	const u32 string_length);
 
 
-u16 HPI_PAD__get_comment(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	char *psz_string, const u32 string_length);
+u16 hpi_pad_get_comment(u32 h_control, char *psz_string,
+	const u32 string_length);
 
 
-u16 HPI_PAD__get_program_type(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *ppTY);
+u16 hpi_pad_get_program_type(u32 h_control, u32 *ppTY);
 
 
-u16 HPI_PAD__get_rdsPI(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 *ppI);
+u16 hpi_pad_get_rdsPI(u32 h_control, u32 *ppI);
 
 
-u16 HPI_PAD__get_program_type_string(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, const u32 data_type, const u32 pTY, char *psz_string,
-	const u32 string_length);
+u16 hpi_pad_get_program_type_string(u32 h_control, const u32 data_type,
+	const u32 pTY, char *psz_string, const u32 string_length);
 
 
 /****************************/
 /****************************/
 /* AES/EBU Receiver control */
 /* AES/EBU Receiver control */
 /****************************/
 /****************************/
-u16 HPI_AESEBU__receiver_query_format(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_aes_rx, const u32 index, u16 *pw_format);
+u16 hpi_aesebu_receiver_query_format(const u32 h_aes_rx, const u32 index,
+	u16 *pw_format);
 
 
-u16 HPI_AESEBU__receiver_set_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 source);
+u16 hpi_aesebu_receiver_set_format(u32 h_control, u16 source);
 
 
-u16 HPI_AESEBU__receiver_get_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_source);
+u16 hpi_aesebu_receiver_get_format(u32 h_control, u16 *pw_source);
 
 
-u16 HPI_AESEBU__receiver_get_sample_rate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *psample_rate);
+u16 hpi_aesebu_receiver_get_sample_rate(u32 h_control, u32 *psample_rate);
 
 
-u16 HPI_AESEBU__receiver_get_user_data(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 *pw_data);
+u16 hpi_aesebu_receiver_get_user_data(u32 h_control, u16 index, u16 *pw_data);
 
 
-u16 HPI_AESEBU__receiver_get_channel_status(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, u16 index, u16 *pw_data);
+u16 hpi_aesebu_receiver_get_channel_status(u32 h_control, u16 index,
+	u16 *pw_data);
 
 
-u16 HPI_AESEBU__receiver_get_error_status(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_error_data);
+u16 hpi_aesebu_receiver_get_error_status(u32 h_control, u16 *pw_error_data);
 
 
 /*******************************/
 /*******************************/
 /* AES/EBU Transmitter control */
 /* AES/EBU Transmitter control */
 /*******************************/
 /*******************************/
-u16 HPI_AESEBU__transmitter_set_sample_rate(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, u32 sample_rate);
+u16 hpi_aesebu_transmitter_set_sample_rate(u32 h_control, u32 sample_rate);
 
 
-u16 HPI_AESEBU__transmitter_set_user_data(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 data);
+u16 hpi_aesebu_transmitter_set_user_data(u32 h_control, u16 index, u16 data);
 
 
-u16 HPI_AESEBU__transmitter_set_channel_status(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, u16 index, u16 data);
+u16 hpi_aesebu_transmitter_set_channel_status(u32 h_control, u16 index,
+	u16 data);
 
 
-u16 HPI_AESEBU__transmitter_get_channel_status(const struct hpi_hsubsys
-	*ph_subsys, u32 h_control, u16 index, u16 *pw_data);
+u16 hpi_aesebu_transmitter_get_channel_status(u32 h_control, u16 index,
+	u16 *pw_data);
 
 
-u16 HPI_AESEBU__transmitter_query_format(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_aes_tx, const u32 index, u16 *pw_format);
+u16 hpi_aesebu_transmitter_query_format(const u32 h_aes_tx, const u32 index,
+	u16 *pw_format);
 
 
-u16 HPI_AESEBU__transmitter_set_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 output_format);
+u16 hpi_aesebu_transmitter_set_format(u32 h_control, u16 output_format);
 
 
-u16 HPI_AESEBU__transmitter_get_format(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_output_format);
+u16 hpi_aesebu_transmitter_get_format(u32 h_control, u16 *pw_output_format);
 
 
 /***********************/
 /***********************/
-/* multiplexer control */
+/* Multiplexer control */
 /***********************/
 /***********************/
-u16 hpi_multiplexer_set_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 source_node_type, u16 source_node_index);
-
-u16 hpi_multiplexer_get_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *source_node_type, u16 *source_node_index);
+u16 hpi_multiplexer_set_source(u32 h_control, u16 source_node_type,
+	u16 source_node_index);
 
 
-u16 hpi_multiplexer_query_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 *source_node_type,
+u16 hpi_multiplexer_get_source(u32 h_control, u16 *source_node_type,
 	u16 *source_node_index);
 	u16 *source_node_index);
 
 
+u16 hpi_multiplexer_query_source(u32 h_control, u16 index,
+	u16 *source_node_type, u16 *source_node_index);
+
 /***************/
 /***************/
-/* VOX control */
+/* Vox control */
 /***************/
 /***************/
-u16 hpi_vox_set_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short an_gain0_01dB);
+u16 hpi_vox_set_threshold(u32 h_control, short an_gain0_01dB);
 
 
-u16 hpi_vox_get_threshold(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	short *an_gain0_01dB);
+u16 hpi_vox_get_threshold(u32 h_control, short *an_gain0_01dB);
 
 
 /*********************/
 /*********************/
 /* Bitstream control */
 /* Bitstream control */
 /*********************/
 /*********************/
-u16 hpi_bitstream_set_clock_edge(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 edge_type);
+u16 hpi_bitstream_set_clock_edge(u32 h_control, u16 edge_type);
 
 
-u16 hpi_bitstream_set_data_polarity(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 polarity);
+u16 hpi_bitstream_set_data_polarity(u32 h_control, u16 polarity);
 
 
-u16 hpi_bitstream_get_activity(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_clk_activity, u16 *pw_data_activity);
+u16 hpi_bitstream_get_activity(u32 h_control, u16 *pw_clk_activity,
+	u16 *pw_data_activity);
 
 
 /***********************/
 /***********************/
 /* SampleClock control */
 /* SampleClock control */
 /***********************/
 /***********************/
 
 
-u16 hpi_sample_clock_query_source(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_clock, const u32 index, u16 *pw_source);
+u16 hpi_sample_clock_query_source(const u32 h_clock, const u32 index,
+	u16 *pw_source);
 
 
-u16 hpi_sample_clock_set_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 source);
+u16 hpi_sample_clock_set_source(u32 h_control, u16 source);
 
 
-u16 hpi_sample_clock_get_source(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_source);
+u16 hpi_sample_clock_get_source(u32 h_control, u16 *pw_source);
 
 
-u16 hpi_sample_clock_query_source_index(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_clock, const u32 index, const u32 source,
-	u16 *pw_source_index);
+u16 hpi_sample_clock_query_source_index(const u32 h_clock, const u32 index,
+	const u32 source, u16 *pw_source_index);
 
 
-u16 hpi_sample_clock_set_source_index(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 source_index);
+u16 hpi_sample_clock_set_source_index(u32 h_control, u16 source_index);
 
 
-u16 hpi_sample_clock_get_source_index(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_source_index);
+u16 hpi_sample_clock_get_source_index(u32 h_control, u16 *pw_source_index);
 
 
-u16 hpi_sample_clock_get_sample_rate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *psample_rate);
+u16 hpi_sample_clock_get_sample_rate(u32 h_control, u32 *psample_rate);
 
 
-u16 hpi_sample_clock_query_local_rate(const struct hpi_hsubsys *ph_subsys,
-	const u32 h_clock, const u32 index, u32 *psource);
+u16 hpi_sample_clock_query_local_rate(const u32 h_clock, const u32 index,
+	u32 *psource);
 
 
-u16 hpi_sample_clock_set_local_rate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 sample_rate);
+u16 hpi_sample_clock_set_local_rate(u32 h_control, u32 sample_rate);
 
 
-u16 hpi_sample_clock_get_local_rate(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *psample_rate);
+u16 hpi_sample_clock_get_local_rate(u32 h_control, u32 *psample_rate);
 
 
-u16 hpi_sample_clock_set_auto(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 enable);
+u16 hpi_sample_clock_set_auto(u32 h_control, u32 enable);
 
 
-u16 hpi_sample_clock_get_auto(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *penable);
+u16 hpi_sample_clock_get_auto(u32 h_control, u32 *penable);
 
 
-u16 hpi_sample_clock_set_local_rate_lock(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 lock);
+u16 hpi_sample_clock_set_local_rate_lock(u32 h_control, u32 lock);
 
 
-u16 hpi_sample_clock_get_local_rate_lock(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *plock);
+u16 hpi_sample_clock_get_local_rate_lock(u32 h_control, u32 *plock);
 
 
 /***********************/
 /***********************/
 /* Microphone control */
 /* Microphone control */
 /***********************/
 /***********************/
-u16 hpi_microphone_set_phantom_power(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 on_off);
+u16 hpi_microphone_set_phantom_power(u32 h_control, u16 on_off);
 
 
-u16 hpi_microphone_get_phantom_power(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_on_off);
+u16 hpi_microphone_get_phantom_power(u32 h_control, u16 *pw_on_off);
 
 
-/*******************************
-  Parametric Equalizer control
-*******************************/
-u16 hpi_parametricEQ__get_info(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 *pw_number_of_bands, u16 *pw_enabled);
+/********************************/
+/* Parametric Equalizer control */
+/********************************/
+u16 hpi_parametric_eq_get_info(u32 h_control, u16 *pw_number_of_bands,
+	u16 *pw_enabled);
 
 
-u16 hpi_parametricEQ__set_state(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 on_off);
+u16 hpi_parametric_eq_set_state(u32 h_control, u16 on_off);
 
 
-u16 hpi_parametricEQ__set_band(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 type, u32 frequency_hz, short q100,
-	short gain0_01dB);
+u16 hpi_parametric_eq_set_band(u32 h_control, u16 index, u16 type,
+	u32 frequency_hz, short q100, short gain0_01dB);
 
 
-u16 hpi_parametricEQ__get_band(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, u16 *pn_type, u32 *pfrequency_hz,
-	short *pnQ100, short *pn_gain0_01dB);
+u16 hpi_parametric_eq_get_band(u32 h_control, u16 index, u16 *pn_type,
+	u32 *pfrequency_hz, short *pnQ100, short *pn_gain0_01dB);
 
 
-u16 hpi_parametricEQ__get_coeffs(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u16 index, short coeffs[5]
+u16 hpi_parametric_eq_get_coeffs(u32 h_control, u16 index, short coeffs[5]
 	);
 	);
 
 
-/*******************************
-  Compressor Expander control
-*******************************/
-
-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_ratio(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 index, u32 *pw_ratio100);
-
-/*******************************
-  Cobranet HMI control
-*******************************/
-u16 hpi_cobranet_hmi_write(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 hmi_address, u32 byte_count, u8 *pb_data);
-
-u16 hpi_cobranet_hmi_read(const struct hpi_hsubsys *ph_subsys, u32 h_control,
-	u32 hmi_address, u32 max_byte_count, u32 *pbyte_count, u8 *pb_data);
-
-u16 hpi_cobranet_hmi_get_status(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pstatus, u32 *preadable_size,
-	u32 *pwriteable_size);
-
-/*Read the current IP address
-*/
-u16 hpi_cobranet_getI_paddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pi_paddress);
-
-/* Write the current IP address
-*/
-u16 hpi_cobranet_setI_paddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 i_paddress);
-
-/* Read the static IP address
-*/
-u16 hpi_cobranet_get_staticI_paddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pi_paddress);
+/*******************************/
+/* Compressor Expander control */
+/*******************************/
 
 
-/* Write the static IP address
-*/
-u16 hpi_cobranet_set_staticI_paddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 i_paddress);
+u16 hpi_compander_set_enable(u32 h_control, u32 on);
 
 
-/* Read the MAC address
-*/
-u16 hpi_cobranet_getMA_caddress(const struct hpi_hsubsys *ph_subsys,
-	u32 h_control, u32 *pmAC_MS_bs, u32 *pmAC_LS_bs);
+u16 hpi_compander_get_enable(u32 h_control, u32 *pon);
 
 
-/*******************************
-  Tone Detector control
-*******************************/
-u16 hpi_tone_detector_get_state(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	u32 *state);
+u16 hpi_compander_set_makeup_gain(u32 h_control, short makeup_gain0_01dB);
 
 
-u16 hpi_tone_detector_set_enable(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	u32 enable);
+u16 hpi_compander_get_makeup_gain(u32 h_control, short *pn_makeup_gain0_01dB);
 
 
-u16 hpi_tone_detector_get_enable(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	u32 *enable);
+u16 hpi_compander_set_attack_time_constant(u32 h_control, u32 index,
+	u32 attack);
 
 
-u16 hpi_tone_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 event_enable);
+u16 hpi_compander_get_attack_time_constant(u32 h_control, u32 index,
+	u32 *pw_attack);
 
 
-u16 hpi_tone_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 *event_enable);
+u16 hpi_compander_set_decay_time_constant(u32 h_control, u32 index,
+	u32 decay);
 
 
-u16 hpi_tone_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, int threshold);
+u16 hpi_compander_get_decay_time_constant(u32 h_control, u32 index,
+	u32 *pw_decay);
 
 
-u16 hpi_tone_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, int *threshold);
+u16 hpi_compander_set_threshold(u32 h_control, u32 index,
+	short threshold0_01dB);
 
 
-u16 hpi_tone_detector_get_frequency(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 index, u32 *frequency);
+u16 hpi_compander_get_threshold(u32 h_control, u32 index,
+	short *pn_threshold0_01dB);
 
 
-/*******************************
-  Silence Detector control
-*******************************/
-u16 hpi_silence_detector_get_state(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 *state);
+u16 hpi_compander_set_ratio(u32 h_control, u32 index, u32 ratio100);
 
 
-u16 hpi_silence_detector_set_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 enable);
+u16 hpi_compander_get_ratio(u32 h_control, u32 index, u32 *pw_ratio100);
 
 
-u16 hpi_silence_detector_get_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 *enable);
+/********************/
+/* Cobranet control */
+/********************/
+u16 hpi_cobranet_hmi_write(u32 h_control, u32 hmi_address, u32 byte_count,
+	u8 *pb_data);
 
 
-u16 hpi_silence_detector_set_event_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 event_enable);
+u16 hpi_cobranet_hmi_read(u32 h_control, u32 hmi_address, u32 max_byte_count,
+	u32 *pbyte_count, u8 *pb_data);
 
 
-u16 hpi_silence_detector_get_event_enable(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 *event_enable);
+u16 hpi_cobranet_hmi_get_status(u32 h_control, u32 *pstatus,
+	u32 *preadable_size, u32 *pwriteable_size);
 
 
-u16 hpi_silence_detector_set_delay(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 delay);
+u16 hpi_cobranet_get_ip_address(u32 h_control, u32 *pdw_ip_address);
 
 
-u16 hpi_silence_detector_get_delay(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, u32 *delay);
+u16 hpi_cobranet_set_ip_address(u32 h_control, u32 dw_ip_address);
 
 
-u16 hpi_silence_detector_set_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, int threshold);
+u16 hpi_cobranet_get_static_ip_address(u32 h_control, u32 *pdw_ip_address);
 
 
-u16 hpi_silence_detector_get_threshold(const struct hpi_hsubsys *ph_subsys,
-	u32 hC, int *threshold);
+u16 hpi_cobranet_set_static_ip_address(u32 h_control, u32 dw_ip_address);
 
 
-/*******************************
-  Universal control
-*******************************/
-u16 hpi_entity_find_next(struct hpi_entity *container_entity,
-	enum e_entity_type type, enum e_entity_role role, int recursive_flag,
-	struct hpi_entity **current_match);
+u16 hpi_cobranet_get_macaddress(u32 h_control, u32 *p_mac_msbs,
+	u32 *p_mac_lsbs);
 
 
-u16 hpi_entity_copy_value_from(struct hpi_entity *entity,
-	enum e_entity_type type, size_t item_count, void *value_dst_p);
+/*************************/
+/* Tone Detector control */
+/*************************/
+u16 hpi_tone_detector_get_state(u32 hC, u32 *state);
 
 
-u16 hpi_entity_unpack(struct hpi_entity *entity, enum e_entity_type *type,
-	size_t *items, enum e_entity_role *role, void **value);
+u16 hpi_tone_detector_set_enable(u32 hC, u32 enable);
 
 
-u16 hpi_entity_alloc_and_pack(const enum e_entity_type type,
-	const size_t item_count, const enum e_entity_role role, void *value,
-	struct hpi_entity **entity);
+u16 hpi_tone_detector_get_enable(u32 hC, u32 *enable);
 
 
-void hpi_entity_free(struct hpi_entity *entity);
+u16 hpi_tone_detector_set_event_enable(u32 hC, u32 event_enable);
 
 
-u16 hpi_universal_info(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	struct hpi_entity **info);
+u16 hpi_tone_detector_get_event_enable(u32 hC, u32 *event_enable);
 
 
-u16 hpi_universal_get(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	struct hpi_entity **value);
+u16 hpi_tone_detector_set_threshold(u32 hC, int threshold);
 
 
-u16 hpi_universal_set(const struct hpi_hsubsys *ph_subsys, u32 hC,
-	struct hpi_entity *value);
+u16 hpi_tone_detector_get_threshold(u32 hC, int *threshold);
 
 
-/*/////////// */
-/* DSP CLOCK  */
-/*/////////// */
-u16 hpi_clock_open(const struct hpi_hsubsys *ph_subsys, u16 adapter_index,
-	u32 *ph_dsp_clock);
+u16 hpi_tone_detector_get_frequency(u32 hC, u32 index, u32 *frequency);
 
 
-u16 hpi_clock_set_time(const struct hpi_hsubsys *ph_subsys, u32 h_clock,
-	u16 hour, u16 minute, u16 second, u16 milli_second);
+/****************************/
+/* Silence Detector control */
+/****************************/
+u16 hpi_silence_detector_get_state(u32 hC, u32 *state);
 
 
-u16 hpi_clock_get_time(const struct hpi_hsubsys *ph_subsys, u32 h_clock,
-	u16 *pw_hour, u16 *pw_minute, u16 *pw_second, u16 *pw_milli_second);
+u16 hpi_silence_detector_set_enable(u32 hC, u32 enable);
 
 
-/*/////////// */
-/* PROFILE        */
-/*/////////// */
-u16 hpi_profile_open_all(const struct hpi_hsubsys *ph_subsys,
-	u16 adapter_index, u16 profile_index, u32 *ph_profile,
-	u16 *pw_max_profiles);
+u16 hpi_silence_detector_get_enable(u32 hC, u32 *enable);
 
 
-u16 hpi_profile_get(const struct hpi_hsubsys *ph_subsys, u32 h_profile,
-	u16 index, u16 *pw_seconds, u32 *pmicro_seconds, u32 *pcall_count,
-	u32 *pmax_micro_seconds, u32 *pmin_micro_seconds);
+u16 hpi_silence_detector_set_event_enable(u32 hC, u32 event_enable);
 
 
-u16 hpi_profile_start_all(const struct hpi_hsubsys *ph_subsys, u32 h_profile);
+u16 hpi_silence_detector_get_event_enable(u32 hC, u32 *event_enable);
 
 
-u16 hpi_profile_stop_all(const struct hpi_hsubsys *ph_subsys, u32 h_profile);
+u16 hpi_silence_detector_set_delay(u32 hC, u32 delay);
 
 
-u16 hpi_profile_get_name(const struct hpi_hsubsys *ph_subsys, u32 h_profile,
-	u16 index, char *sz_profile_name, u16 profile_name_length);
+u16 hpi_silence_detector_get_delay(u32 hC, u32 *delay);
 
 
-u16 hpi_profile_get_utilization(const struct hpi_hsubsys *ph_subsys,
-	u32 h_profile, u32 *putilization);
+u16 hpi_silence_detector_set_threshold(u32 hC, int threshold);
 
 
-/*//////////////////// */
-/* UTILITY functions */
+u16 hpi_silence_detector_get_threshold(u32 hC, int *threshold);
+/*********************/
+/* Utility functions */
+/*********************/
 
 
 u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format,
 u16 hpi_format_create(struct hpi_format *p_format, u16 channels, u16 format,
 	u32 sample_rate, u32 bit_rate, u32 attributes);
 	u32 sample_rate, u32 bit_rate, u32 attributes);
 
 
-/* Until it's verified, this function is for Windows OSs only */
-
-#endif	 /*_H_HPI_ */
-/*
-///////////////////////////////////////////////////////////////////////////////
-// See CVS for history.  Last complete set in rev 1.146
-////////////////////////////////////////////////////////////////////////////////
-*/
+#endif	 /*_HPI_H_ */

+ 137 - 162
sound/pci/asihpi/hpi6000.c

@@ -43,16 +43,17 @@
 #define HPI_HIF_ERROR_MASK      0x4000
 #define HPI_HIF_ERROR_MASK      0x4000
 
 
 /* HPI6000 specific error codes */
 /* HPI6000 specific error codes */
+#define HPI6000_ERROR_BASE 900	/* not actually used anywhere */
 
 
-#define HPI6000_ERROR_BASE                              900
+/* operational/messaging errors */
 #define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT             901
 #define HPI6000_ERROR_MSG_RESP_IDLE_TIMEOUT             901
-#define HPI6000_ERROR_MSG_RESP_SEND_MSG_ACK             902
+
 #define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK             903
 #define HPI6000_ERROR_MSG_RESP_GET_RESP_ACK             903
 #define HPI6000_ERROR_MSG_GET_ADR                       904
 #define HPI6000_ERROR_MSG_GET_ADR                       904
 #define HPI6000_ERROR_RESP_GET_ADR                      905
 #define HPI6000_ERROR_RESP_GET_ADR                      905
 #define HPI6000_ERROR_MSG_RESP_BLOCKWRITE32             906
 #define HPI6000_ERROR_MSG_RESP_BLOCKWRITE32             906
 #define HPI6000_ERROR_MSG_RESP_BLOCKREAD32              907
 #define HPI6000_ERROR_MSG_RESP_BLOCKREAD32              907
-#define HPI6000_ERROR_MSG_INVALID_DSP_INDEX             908
+
 #define HPI6000_ERROR_CONTROL_CACHE_PARAMS              909
 #define HPI6000_ERROR_CONTROL_CACHE_PARAMS              909
 
 
 #define HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT            911
 #define HPI6000_ERROR_SEND_DATA_IDLE_TIMEOUT            911
@@ -62,7 +63,6 @@
 #define HPI6000_ERROR_SEND_DATA_CMD                     915
 #define HPI6000_ERROR_SEND_DATA_CMD                     915
 #define HPI6000_ERROR_SEND_DATA_WRITE                   916
 #define HPI6000_ERROR_SEND_DATA_WRITE                   916
 #define HPI6000_ERROR_SEND_DATA_IDLECMD                 917
 #define HPI6000_ERROR_SEND_DATA_IDLECMD                 917
-#define HPI6000_ERROR_SEND_DATA_VERIFY                  918
 
 
 #define HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT             921
 #define HPI6000_ERROR_GET_DATA_IDLE_TIMEOUT             921
 #define HPI6000_ERROR_GET_DATA_ACK                      922
 #define HPI6000_ERROR_GET_DATA_ACK                      922
@@ -76,9 +76,8 @@
 
 
 #define HPI6000_ERROR_MSG_RESP_GETRESPCMD               961
 #define HPI6000_ERROR_MSG_RESP_GETRESPCMD               961
 #define HPI6000_ERROR_MSG_RESP_IDLECMD                  962
 #define HPI6000_ERROR_MSG_RESP_IDLECMD                  962
-#define HPI6000_ERROR_MSG_RESP_BLOCKVERIFY32            963
 
 
-/* adapter init errors */
+/* Initialisation/bootload errors */
 #define HPI6000_ERROR_UNHANDLED_SUBSYS_ID               930
 #define HPI6000_ERROR_UNHANDLED_SUBSYS_ID               930
 
 
 /* can't access PCI2040 */
 /* can't access PCI2040 */
@@ -210,6 +209,8 @@ static void adapter_get_asserts(struct hpi_adapter_obj *pao,
 static short create_adapter_obj(struct hpi_adapter_obj *pao,
 static short create_adapter_obj(struct hpi_adapter_obj *pao,
 	u32 *pos_error_code);
 	u32 *pos_error_code);
 
 
+static void delete_adapter_obj(struct hpi_adapter_obj *pao);
+
 /* local globals */
 /* local globals */
 
 
 static u16 gw_pci_read_asserts;	/* used to count PCI2040 errors */
 static u16 gw_pci_read_asserts;	/* used to count PCI2040 errors */
@@ -217,17 +218,7 @@ static u16 gw_pci_write_asserts;	/* used to count PCI2040 errors */
 
 
 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
 {
 {
-
 	switch (phm->function) {
 	switch (phm->function) {
-	case HPI_SUBSYS_OPEN:
-	case HPI_SUBSYS_CLOSE:
-	case HPI_SUBSYS_GET_INFO:
-	case HPI_SUBSYS_DRIVER_UNLOAD:
-	case HPI_SUBSYS_DRIVER_LOAD:
-	case HPI_SUBSYS_FIND_ADAPTERS:
-		/* messages that should not get here */
-		phr->error = HPI_ERROR_UNIMPLEMENTED;
-		break;
 	case HPI_SUBSYS_CREATE_ADAPTER:
 	case HPI_SUBSYS_CREATE_ADAPTER:
 		subsys_create_adapter(phm, phr);
 		subsys_create_adapter(phm, phr);
 		break;
 		break;
@@ -243,7 +234,6 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
 static void control_message(struct hpi_adapter_obj *pao,
 static void control_message(struct hpi_adapter_obj *pao,
 	struct hpi_message *phm, struct hpi_response *phr)
 	struct hpi_message *phm, struct hpi_response *phr)
 {
 {
-
 	switch (phm->function) {
 	switch (phm->function) {
 	case HPI_CONTROL_GET_STATE:
 	case HPI_CONTROL_GET_STATE:
 		if (pao->has_control_cache) {
 		if (pao->has_control_cache) {
@@ -251,7 +241,13 @@ static void control_message(struct hpi_adapter_obj *pao,
 			err = hpi6000_update_control_cache(pao, phm);
 			err = hpi6000_update_control_cache(pao, phm);
 
 
 			if (err) {
 			if (err) {
-				phr->error = err;
+				if (err >= HPI_ERROR_BACKEND_BASE) {
+					phr->error =
+						HPI_ERROR_CONTROL_CACHING;
+					phr->specific_error = err;
+				} else {
+					phr->error = err;
+				}
 				break;
 				break;
 			}
 			}
 
 
@@ -262,16 +258,15 @@ static void control_message(struct hpi_adapter_obj *pao,
 		}
 		}
 		hw_message(pao, phm, phr);
 		hw_message(pao, phm, phr);
 		break;
 		break;
-	case HPI_CONTROL_GET_INFO:
-		hw_message(pao, phm, phr);
-		break;
 	case HPI_CONTROL_SET_STATE:
 	case HPI_CONTROL_SET_STATE:
 		hw_message(pao, phm, phr);
 		hw_message(pao, phm, phr);
-		hpi_sync_control_cache(((struct hpi_hw_obj *)pao->priv)->
-			p_cache, phm, phr);
+		hpi_cmn_control_cache_sync_to_msg(((struct hpi_hw_obj *)pao->
+				priv)->p_cache, phm, phr);
 		break;
 		break;
+
+	case HPI_CONTROL_GET_INFO:
 	default:
 	default:
-		phr->error = HPI_ERROR_INVALID_FUNC;
+		hw_message(pao, phm, phr);
 		break;
 		break;
 	}
 	}
 }
 }
@@ -280,26 +275,12 @@ static void adapter_message(struct hpi_adapter_obj *pao,
 	struct hpi_message *phm, struct hpi_response *phr)
 	struct hpi_message *phm, struct hpi_response *phr)
 {
 {
 	switch (phm->function) {
 	switch (phm->function) {
-	case HPI_ADAPTER_GET_INFO:
-		hw_message(pao, phm, phr);
-		break;
 	case HPI_ADAPTER_GET_ASSERT:
 	case HPI_ADAPTER_GET_ASSERT:
 		adapter_get_asserts(pao, phm, phr);
 		adapter_get_asserts(pao, phm, phr);
 		break;
 		break;
-	case HPI_ADAPTER_OPEN:
-	case HPI_ADAPTER_CLOSE:
-	case HPI_ADAPTER_TEST_ASSERT:
-	case HPI_ADAPTER_SELFTEST:
-	case HPI_ADAPTER_GET_MODE:
-	case HPI_ADAPTER_SET_MODE:
-	case HPI_ADAPTER_FIND_OBJECT:
-	case HPI_ADAPTER_GET_PROPERTY:
-	case HPI_ADAPTER_SET_PROPERTY:
-	case HPI_ADAPTER_ENUM_PROPERTY:
-		hw_message(pao, phm, phr);
-		break;
+
 	default:
 	default:
-		phr->error = HPI_ERROR_INVALID_FUNC;
+		hw_message(pao, phm, phr);
 		break;
 		break;
 	}
 	}
 }
 }
@@ -311,7 +292,7 @@ static void outstream_message(struct hpi_adapter_obj *pao,
 	case HPI_OSTREAM_HOSTBUFFER_ALLOC:
 	case HPI_OSTREAM_HOSTBUFFER_ALLOC:
 	case HPI_OSTREAM_HOSTBUFFER_FREE:
 	case HPI_OSTREAM_HOSTBUFFER_FREE:
 		/* Don't let these messages go to the HW function because
 		/* Don't let these messages go to the HW function because
-		 * they're called without allocating the spinlock.
+		 * they're called without locking the spinlock.
 		 * For the HPI6000 adapters the HW would return
 		 * For the HPI6000 adapters the HW would return
 		 * HPI_ERROR_INVALID_FUNC anyway.
 		 * HPI_ERROR_INVALID_FUNC anyway.
 		 */
 		 */
@@ -331,7 +312,7 @@ static void instream_message(struct hpi_adapter_obj *pao,
 	case HPI_ISTREAM_HOSTBUFFER_ALLOC:
 	case HPI_ISTREAM_HOSTBUFFER_ALLOC:
 	case HPI_ISTREAM_HOSTBUFFER_FREE:
 	case HPI_ISTREAM_HOSTBUFFER_FREE:
 		/* Don't let these messages go to the HW function because
 		/* Don't let these messages go to the HW function because
-		 * they're called without allocating the spinlock.
+		 * they're called without locking the spinlock.
 		 * For the HPI6000 adapters the HW would return
 		 * For the HPI6000 adapters the HW would return
 		 * HPI_ERROR_INVALID_FUNC anyway.
 		 * HPI_ERROR_INVALID_FUNC anyway.
 		 */
 		 */
@@ -355,7 +336,7 @@ void HPI_6000(struct hpi_message *phm, struct hpi_response *phr)
 	/* subsytem messages get executed by every HPI. */
 	/* subsytem messages get executed by every HPI. */
 	/* All other messages are ignored unless the adapter index matches */
 	/* All other messages are ignored unless the adapter index matches */
 	/* an adapter in the HPI */
 	/* an adapter in the HPI */
-	HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->object, phm->function);
+	/*HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->wObject, phm->wFunction); */
 
 
 	/* if Dsp has crashed then do not communicate with it any more */
 	/* if Dsp has crashed then do not communicate with it any more */
 	if (phm->object != HPI_OBJ_SUBSYSTEM) {
 	if (phm->object != HPI_OBJ_SUBSYSTEM) {
@@ -433,21 +414,13 @@ static void subsys_create_adapter(struct hpi_message *phm,
 	struct hpi_adapter_obj ao;
 	struct hpi_adapter_obj ao;
 	struct hpi_adapter_obj *pao;
 	struct hpi_adapter_obj *pao;
 	u32 os_error_code;
 	u32 os_error_code;
-	short error = 0;
+	u16 err = 0;
 	u32 dsp_index = 0;
 	u32 dsp_index = 0;
 
 
 	HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n");
 	HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n");
 
 
 	memset(&ao, 0, sizeof(ao));
 	memset(&ao, 0, sizeof(ao));
 
 
-	/* this HPI only creates adapters for TI/PCI2040 based devices */
-	if (phm->u.s.resource.bus_type != HPI_BUS_PCI)
-		return;
-	if (phm->u.s.resource.r.pci->vendor_id != HPI_PCI_VENDOR_ID_TI)
-		return;
-	if (phm->u.s.resource.r.pci->device_id != HPI_PCI_DEV_ID_PCI2040)
-		return;
-
 	ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL);
 	ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL);
 	if (!ao.priv) {
 	if (!ao.priv) {
 		HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n");
 		HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n");
@@ -456,16 +429,19 @@ static void subsys_create_adapter(struct hpi_message *phm,
 	}
 	}
 
 
 	/* create the adapter object based on the resource information */
 	/* create the adapter object based on the resource information */
-	/*? memcpy(&ao.Pci,&phm->u.s.Resource.r.Pci,sizeof(ao.Pci)); */
 	ao.pci = *phm->u.s.resource.r.pci;
 	ao.pci = *phm->u.s.resource.r.pci;
 
 
-	error = create_adapter_obj(&ao, &os_error_code);
-	if (!error)
-		error = hpi_add_adapter(&ao);
-	if (error) {
+	err = create_adapter_obj(&ao, &os_error_code);
+	if (err) {
+		delete_adapter_obj(&ao);
+		if (err >= HPI_ERROR_BACKEND_BASE) {
+			phr->error = HPI_ERROR_DSP_BOOTLOAD;
+			phr->specific_error = err;
+		} else {
+			phr->error = err;
+		}
+
 		phr->u.s.data = os_error_code;
 		phr->u.s.data = os_error_code;
-		kfree(ao.priv);
-		phr->error = error;
 		return;
 		return;
 	}
 	}
 	/* need to update paParentAdapter */
 	/* need to update paParentAdapter */
@@ -473,7 +449,7 @@ static void subsys_create_adapter(struct hpi_message *phm,
 	if (!pao) {
 	if (!pao) {
 		/* We just added this adapter, why can't we find it!? */
 		/* We just added this adapter, why can't we find it!? */
 		HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n");
 		HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n");
-		phr->error = 950;
+		phr->error = HPI_ERROR_BAD_ADAPTER;
 		return;
 		return;
 	}
 	}
 
 
@@ -482,9 +458,8 @@ static void subsys_create_adapter(struct hpi_message *phm,
 		phw->ado[dsp_index].pa_parent_adapter = pao;
 		phw->ado[dsp_index].pa_parent_adapter = pao;
 	}
 	}
 
 
-	phr->u.s.aw_adapter_list[ao.index] = ao.adapter_type;
+	phr->u.s.adapter_type = ao.adapter_type;
 	phr->u.s.adapter_index = ao.index;
 	phr->u.s.adapter_index = ao.index;
-	phr->u.s.num_adapters++;
 	phr->error = 0;
 	phr->error = 0;
 }
 }
 
 
@@ -492,20 +467,13 @@ static void subsys_delete_adapter(struct hpi_message *phm,
 	struct hpi_response *phr)
 	struct hpi_response *phr)
 {
 {
 	struct hpi_adapter_obj *pao = NULL;
 	struct hpi_adapter_obj *pao = NULL;
-	struct hpi_hw_obj *phw;
 
 
-	pao = hpi_find_adapter(phm->adapter_index);
+	pao = hpi_find_adapter(phm->obj_index);
 	if (!pao)
 	if (!pao)
 		return;
 		return;
 
 
-	phw = (struct hpi_hw_obj *)pao->priv;
-
-	if (pao->has_control_cache)
-		hpi_free_control_cache(phw->p_cache);
-
+	delete_adapter_obj(pao);
 	hpi_delete_adapter(pao);
 	hpi_delete_adapter(pao);
-	kfree(phw);
-
 	phr->error = 0;
 	phr->error = 0;
 }
 }
 
 
@@ -519,9 +487,6 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao,
 	u32 control_cache_count = 0;
 	u32 control_cache_count = 0;
 	struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
 	struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
 
 
-	/* init error reporting */
-	pao->dsp_crashed = 0;
-
 	/* The PCI2040 has the following address map */
 	/* The PCI2040 has the following address map */
 	/* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */
 	/* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */
 	/* BAR1 - 32K = HPI registers on DSP */
 	/* BAR1 - 32K = HPI registers on DSP */
@@ -575,36 +540,36 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao,
 	/* get info about the adapter by asking the adapter */
 	/* get info about the adapter by asking the adapter */
 	/* send a HPI_ADAPTER_GET_INFO message */
 	/* send a HPI_ADAPTER_GET_INFO message */
 	{
 	{
-		struct hpi_message hM;
-		struct hpi_response hR0;	/* response from DSP 0 */
-		struct hpi_response hR1;	/* response from DSP 1 */
+		struct hpi_message hm;
+		struct hpi_response hr0;	/* response from DSP 0 */
+		struct hpi_response hr1;	/* response from DSP 1 */
 		u16 error = 0;
 		u16 error = 0;
 
 
 		HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n");
 		HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n");
-		memset(&hM, 0, sizeof(hM));
-		hM.type = HPI_TYPE_MESSAGE;
-		hM.size = sizeof(struct hpi_message);
-		hM.object = HPI_OBJ_ADAPTER;
-		hM.function = HPI_ADAPTER_GET_INFO;
-		hM.adapter_index = 0;
-		memset(&hR0, 0, sizeof(hR0));
-		memset(&hR1, 0, sizeof(hR1));
-		hR0.size = sizeof(hR0);
-		hR1.size = sizeof(hR1);
-
-		error = hpi6000_message_response_sequence(pao, 0, &hM, &hR0);
-		if (hR0.error) {
-			HPI_DEBUG_LOG(DEBUG, "message error %d\n", hR0.error);
-			return hR0.error;
+		memset(&hm, 0, sizeof(hm));
+		hm.type = HPI_TYPE_MESSAGE;
+		hm.size = sizeof(struct hpi_message);
+		hm.object = HPI_OBJ_ADAPTER;
+		hm.function = HPI_ADAPTER_GET_INFO;
+		hm.adapter_index = 0;
+		memset(&hr0, 0, sizeof(hr0));
+		memset(&hr1, 0, sizeof(hr1));
+		hr0.size = sizeof(hr0);
+		hr1.size = sizeof(hr1);
+
+		error = hpi6000_message_response_sequence(pao, 0, &hm, &hr0);
+		if (hr0.error) {
+			HPI_DEBUG_LOG(DEBUG, "message error %d\n", hr0.error);
+			return hr0.error;
 		}
 		}
 		if (phw->num_dsp == 2) {
 		if (phw->num_dsp == 2) {
-			error = hpi6000_message_response_sequence(pao, 1, &hM,
-				&hR1);
+			error = hpi6000_message_response_sequence(pao, 1, &hm,
+				&hr1);
 			if (error)
 			if (error)
 				return error;
 				return error;
 		}
 		}
-		pao->adapter_type = hR0.u.a.adapter_type;
-		pao->index = hR0.u.a.adapter_index;
+		pao->adapter_type = hr0.u.ax.info.adapter_type;
+		pao->index = hr0.u.ax.info.adapter_index;
 	}
 	}
 
 
 	memset(&phw->control_cache[0], 0,
 	memset(&phw->control_cache[0], 0,
@@ -618,22 +583,37 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao,
 		control_cache_count =
 		control_cache_count =
 			hpi_read_word(&phw->ado[0],
 			hpi_read_word(&phw->ado[0],
 			HPI_HIF_ADDR(control_cache_count));
 			HPI_HIF_ADDR(control_cache_count));
-		pao->has_control_cache = 1;
 
 
 		phw->p_cache =
 		phw->p_cache =
 			hpi_alloc_control_cache(control_cache_count,
 			hpi_alloc_control_cache(control_cache_count,
-			control_cache_size, (struct hpi_control_cache_info *)
+			control_cache_size, (unsigned char *)
 			&phw->control_cache[0]
 			&phw->control_cache[0]
 			);
 			);
-		if (!phw->p_cache)
-			pao->has_control_cache = 0;
-	} else
-		pao->has_control_cache = 0;
+		if (phw->p_cache)
+			pao->has_control_cache = 1;
+	}
 
 
 	HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n",
 	HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n",
 		pao->adapter_type, pao->index);
 		pao->adapter_type, pao->index);
 	pao->open = 0;	/* upon creation the adapter is closed */
 	pao->open = 0;	/* upon creation the adapter is closed */
-	return 0;
+
+	if (phw->p_cache)
+		phw->p_cache->adap_idx = pao->index;
+
+	return hpi_add_adapter(pao);
+}
+
+static void delete_adapter_obj(struct hpi_adapter_obj *pao)
+{
+	struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
+
+	if (pao->has_control_cache)
+		hpi_free_control_cache(phw->p_cache);
+
+	/* reset DSPs on adapter */
+	iowrite32(0x0003000F, phw->dw2040_HPICSR + HPI_RESET);
+
+	kfree(phw);
 }
 }
 
 
 /************************************************************************/
 /************************************************************************/
@@ -645,11 +625,13 @@ static void adapter_get_asserts(struct hpi_adapter_obj *pao,
 #ifndef HIDE_PCI_ASSERTS
 #ifndef HIDE_PCI_ASSERTS
 	/* if we have PCI2040 asserts then collect them */
 	/* if we have PCI2040 asserts then collect them */
 	if ((gw_pci_read_asserts > 0) || (gw_pci_write_asserts > 0)) {
 	if ((gw_pci_read_asserts > 0) || (gw_pci_write_asserts > 0)) {
-		phr->u.a.serial_number =
+		phr->u.ax.assert.p1 =
 			gw_pci_read_asserts * 100 + gw_pci_write_asserts;
 			gw_pci_read_asserts * 100 + gw_pci_write_asserts;
-		phr->u.a.adapter_index = 1;	/* assert count */
-		phr->u.a.adapter_type = -1;	/* "dsp index" */
-		strcpy(phr->u.a.sz_adapter_assert, "PCI2040 error");
+		phr->u.ax.assert.p2 = 0;
+		phr->u.ax.assert.count = 1;	/* assert count */
+		phr->u.ax.assert.dsp_index = -1;	/* "dsp index" */
+		strcpy(phr->u.ax.assert.sz_message, "PCI2040 error");
+		phr->u.ax.assert.dsp_msg_addr = 0;
 		gw_pci_read_asserts = 0;
 		gw_pci_read_asserts = 0;
 		gw_pci_write_asserts = 0;
 		gw_pci_write_asserts = 0;
 		phr->error = 0;
 		phr->error = 0;
@@ -686,10 +668,10 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 
 
 	/* NOTE don't use wAdapterType in this routine. It is not setup yet */
 	/* NOTE don't use wAdapterType in this routine. It is not setup yet */
 
 
-	switch (pao->pci.subsys_device_id) {
+	switch (pao->pci.pci_dev->subsystem_device) {
 	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 0x5200:	/* ASI5200 PCIe 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);
@@ -709,8 +691,9 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 	 * note that bits 4..15 are read-only and so should always return zero,
 	 * note that bits 4..15 are read-only and so should always return zero,
 	 * even though we wrote 1 to them
 	 * even though we wrote 1 to them
 	 */
 	 */
-	for (i = 0; i < 1000; i++)
-		delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
+	hpios_delay_micro_seconds(1000);
+	delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
+
 	if (delay != dw2040_reset) {
 	if (delay != dw2040_reset) {
 		HPI_DEBUG_LOG(ERROR, "INIT_PCI2040 %x %x\n", dw2040_reset,
 		HPI_DEBUG_LOG(ERROR, "INIT_PCI2040 %x %x\n", dw2040_reset,
 			delay);
 			delay);
@@ -743,8 +726,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 	dw2040_reset = dw2040_reset & (~0x00000008);
 	dw2040_reset = dw2040_reset & (~0x00000008);
 	iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
 	iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
 	/*delay to allow DSP to get going */
 	/*delay to allow DSP to get going */
-	for (i = 0; i < 100; i++)
-		delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
+	hpios_delay_micro_seconds(100);
 
 
 	/* loop through all DSPs, downloading DSP code */
 	/* loop through all DSPs, downloading DSP code */
 	for (dsp_index = 0; dsp_index < phw->num_dsp; dsp_index++) {
 	for (dsp_index = 0; dsp_index < phw->num_dsp; dsp_index++) {
@@ -783,27 +765,27 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 			 */
 			 */
 			/* bypass PLL */
 			/* bypass PLL */
 			hpi_write_word(pdo, 0x01B7C100, 0x0000);
 			hpi_write_word(pdo, 0x01B7C100, 0x0000);
-			for (i = 0; i < 100; i++)
-				delay = ioread32(phw->dw2040_HPICSR +
-					HPI_RESET);
+			hpios_delay_micro_seconds(100);
 
 
 			/*  ** use default of PLL  x7 ** */
 			/*  ** use default of PLL  x7 ** */
 			/* EMIF = 225/3=75MHz */
 			/* EMIF = 225/3=75MHz */
 			hpi_write_word(pdo, 0x01B7C120, 0x8002);
 			hpi_write_word(pdo, 0x01B7C120, 0x8002);
+			hpios_delay_micro_seconds(100);
+
 			/* peri = 225/2 */
 			/* peri = 225/2 */
 			hpi_write_word(pdo, 0x01B7C11C, 0x8001);
 			hpi_write_word(pdo, 0x01B7C11C, 0x8001);
+			hpios_delay_micro_seconds(100);
+
 			/* cpu  = 225/1 */
 			/* cpu  = 225/1 */
 			hpi_write_word(pdo, 0x01B7C118, 0x8000);
 			hpi_write_word(pdo, 0x01B7C118, 0x8000);
-			/* ~200us delay */
-			for (i = 0; i < 2000; i++)
-				delay = ioread32(phw->dw2040_HPICSR +
-					HPI_RESET);
+
+			/* ~2ms delay */
+			hpios_delay_micro_seconds(2000);
+
 			/* PLL not bypassed */
 			/* PLL not bypassed */
 			hpi_write_word(pdo, 0x01B7C100, 0x0001);
 			hpi_write_word(pdo, 0x01B7C100, 0x0001);
-			/* ~200us delay */
-			for (i = 0; i < 2000; i++)
-				delay = ioread32(phw->dw2040_HPICSR +
-					HPI_RESET);
+			/* ~2ms delay */
+			hpios_delay_micro_seconds(2000);
 		}
 		}
 
 
 		/* test r/w to internal DSP memory
 		/* test r/w to internal DSP memory
@@ -927,9 +909,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 		}
 		}
 
 
 		/* delay a little to allow SDRAM and DSP to "get going" */
 		/* delay a little to allow SDRAM and DSP to "get going" */
-
-		for (i = 0; i < 1000; i++)
-			delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
+		hpios_delay_micro_seconds(1000);
 
 
 		/* test access to SDRAM */
 		/* test access to SDRAM */
 		{
 		{
@@ -976,7 +956,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 
 
 		/* write the DSP code down into the DSPs memory */
 		/* write the DSP code down into the DSPs memory */
 		/*HpiDspCode_Open(nBootLoadFamily,&DspCode,pdwOsErrorCode); */
 		/*HpiDspCode_Open(nBootLoadFamily,&DspCode,pdwOsErrorCode); */
-		dsp_code.ps_dev = pao->pci.p_os_data;
+		dsp_code.ps_dev = pao->pci.pci_dev;
 
 
 		error = hpi_dsp_code_open(boot_load_family, &dsp_code,
 		error = hpi_dsp_code_open(boot_load_family, &dsp_code,
 			pos_error_code);
 			pos_error_code);
@@ -1073,8 +1053,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 
 
 		/* step 3. Start code by sending interrupt */
 		/* step 3. Start code by sending interrupt */
 		iowrite32(0x00030003, pdo->prHPI_control);
 		iowrite32(0x00030003, pdo->prHPI_control);
-		for (i = 0; i < 10000; i++)
-			delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);
+		hpios_delay_micro_seconds(10000);
 
 
 		/* wait for a non-zero value in hostcmd -
 		/* wait for a non-zero value in hostcmd -
 		 * indicating initialization is complete
 		 * indicating initialization is complete
@@ -1101,7 +1080,7 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 			 * locks up with a bluescreen (NOT GPF or pagefault).
 			 * locks up with a bluescreen (NOT GPF or pagefault).
 			 */
 			 */
 			else
 			else
-				hpios_delay_micro_seconds(1000);
+				hpios_delay_micro_seconds(10000);
 		}
 		}
 		if (timeout == 0)
 		if (timeout == 0)
 			return HPI6000_ERROR_INIT_NOACK;
 			return HPI6000_ERROR_INIT_NOACK;
@@ -1132,14 +1111,14 @@ static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
 				mask = 0xFFFFFF00L;
 				mask = 0xFFFFFF00L;
 				/* ASI5100 uses AX6 code, */
 				/* ASI5100 uses AX6 code, */
 				/* but has no PLD r/w register to test */
 				/* but has no PLD r/w register to test */
-				if (HPI_ADAPTER_FAMILY_ASI(pao->pci.
-						subsys_device_id) ==
+				if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev->
+						subsystem_device) ==
 					HPI_ADAPTER_FAMILY_ASI(0x5100))
 					HPI_ADAPTER_FAMILY_ASI(0x5100))
 					mask = 0x00000000L;
 					mask = 0x00000000L;
 				/* ASI5200 uses AX6 code, */
 				/* ASI5200 uses AX6 code, */
 				/* but has no PLD r/w register to test */
 				/* but has no PLD r/w register to test */
-				if (HPI_ADAPTER_FAMILY_ASI(pao->pci.
-						subsys_device_id) ==
+				if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev->
+						subsystem_device) ==
 					HPI_ADAPTER_FAMILY_ASI(0x5200))
 					HPI_ADAPTER_FAMILY_ASI(0x5200))
 					mask = 0x00000000L;
 					mask = 0x00000000L;
 				break;
 				break;
@@ -1204,7 +1183,7 @@ static u32 hpi_read_word(struct dsp_obj *pdo, u32 address)
 	u32 data = 0;
 	u32 data = 0;
 
 
 	if (hpi_set_address(pdo, address))
 	if (hpi_set_address(pdo, address))
-		return 0;	/*? no way to return error */
+		return 0;	/*? No way to return error */
 
 
 	/* take care of errata in revB DSP (2.0.1) */
 	/* take care of errata in revB DSP (2.0.1) */
 	data = ioread32(pdo->prHPI_data);
 	data = ioread32(pdo->prHPI_data);
@@ -1340,10 +1319,6 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
 	u32 *p_data;
 	u32 *p_data;
 	u16 error = 0;
 	u16 error = 0;
 
 
-	/* does the DSP we are referencing exist? */
-	if (dsp_index >= phw->num_dsp)
-		return HPI6000_ERROR_MSG_INVALID_DSP_INDEX;
-
 	ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
 	ack = hpi6000_wait_dsp_ack(pao, dsp_index, HPI_HIF_IDLE);
 	if (ack & HPI_HIF_ERROR_MASK) {
 	if (ack & HPI_HIF_ERROR_MASK) {
 		pao->dsp_crashed++;
 		pao->dsp_crashed++;
@@ -1351,9 +1326,7 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
 	}
 	}
 	pao->dsp_crashed = 0;
 	pao->dsp_crashed = 0;
 
 
-	/* send the message */
-
-	/* get the address and size */
+	/* get the message address and size */
 	if (phw->message_buffer_address_on_dsp == 0) {
 	if (phw->message_buffer_address_on_dsp == 0) {
 		timeout = TIMEOUT;
 		timeout = TIMEOUT;
 		do {
 		do {
@@ -1368,10 +1341,9 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
 	} else
 	} else
 		address = phw->message_buffer_address_on_dsp;
 		address = phw->message_buffer_address_on_dsp;
 
 
-	/*        dwLength = sizeof(struct hpi_message); */
 	length = phm->size;
 	length = phm->size;
 
 
-	/* send it */
+	/* send the message */
 	p_data = (u32 *)phm;
 	p_data = (u32 *)phm;
 	if (hpi6000_dsp_block_write32(pao, dsp_index, address, p_data,
 	if (hpi6000_dsp_block_write32(pao, dsp_index, address, p_data,
 			(u16)length / 4))
 			(u16)length / 4))
@@ -1385,7 +1357,7 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
 	if (ack & HPI_HIF_ERROR_MASK)
 	if (ack & HPI_HIF_ERROR_MASK)
 		return HPI6000_ERROR_MSG_RESP_GET_RESP_ACK;
 		return HPI6000_ERROR_MSG_RESP_GET_RESP_ACK;
 
 
-	/* get the address and size */
+	/* get the response address */
 	if (phw->response_buffer_address_on_dsp == 0) {
 	if (phw->response_buffer_address_on_dsp == 0) {
 		timeout = TIMEOUT;
 		timeout = TIMEOUT;
 		do {
 		do {
@@ -1409,7 +1381,7 @@ static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
 	if (!timeout)
 	if (!timeout)
 		length = sizeof(struct hpi_response);
 		length = sizeof(struct hpi_response);
 
 
-	/* get it */
+	/* get the response */
 	p_data = (u32 *)phr;
 	p_data = (u32 *)phr;
 	if (hpi6000_dsp_block_read32(pao, dsp_index, address, p_data,
 	if (hpi6000_dsp_block_read32(pao, dsp_index, address, p_data,
 			(u16)length / 4))
 			(u16)length / 4))
@@ -1805,17 +1777,11 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
 	hpios_dsplock_lock(pao);
 	hpios_dsplock_lock(pao);
 	error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr);
 	error = hpi6000_message_response_sequence(pao, dsp_index, phm, phr);
 
 
-	/* maybe an error response */
-	if (error) {
-		/* something failed in the HPI/DSP interface */
-		phr->error = error;
-		/* just the header of the response is valid */
-		phr->size = sizeof(struct hpi_response_header);
+	if (error)	/* something failed in the HPI/DSP interface */
 		goto err;
 		goto err;
-	}
 
 
-	if (phr->error != 0)	/* something failed in the DSP */
-		goto err;
+	if (phr->error)	/* something failed in the DSP */
+		goto out;
 
 
 	switch (phm->function) {
 	switch (phm->function) {
 	case HPI_OSTREAM_WRITE:
 	case HPI_OSTREAM_WRITE:
@@ -1827,21 +1793,30 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
 		error = hpi6000_get_data(pao, dsp_index, phm, phr);
 		error = hpi6000_get_data(pao, dsp_index, phm, phr);
 		break;
 		break;
 	case HPI_ADAPTER_GET_ASSERT:
 	case HPI_ADAPTER_GET_ASSERT:
-		phr->u.a.adapter_index = 0;	/* dsp 0 default */
+		phr->u.ax.assert.dsp_index = 0;	/* dsp 0 default */
 		if (num_dsp == 2) {
 		if (num_dsp == 2) {
-			if (!phr->u.a.adapter_type) {
+			if (!phr->u.ax.assert.count) {
 				/* no assert from dsp 0, check dsp 1 */
 				/* no assert from dsp 0, check dsp 1 */
 				error = hpi6000_message_response_sequence(pao,
 				error = hpi6000_message_response_sequence(pao,
 					1, phm, phr);
 					1, phm, phr);
-				phr->u.a.adapter_index = 1;
+				phr->u.ax.assert.dsp_index = 1;
 			}
 			}
 		}
 		}
 	}
 	}
 
 
-	if (error)
-		phr->error = error;
-
 err:
 err:
+	if (error) {
+		if (error >= HPI_ERROR_BACKEND_BASE) {
+			phr->error = HPI_ERROR_DSP_COMMUNICATION;
+			phr->specific_error = error;
+		} else {
+			phr->error = error;
+		}
+
+		/* just the header of the response is valid */
+		phr->size = sizeof(struct hpi_response_header);
+	}
+out:
 	hpios_dsplock_unlock(pao);
 	hpios_dsplock_unlock(pao);
 	return;
 	return;
 }
 }

Файловите разлики са ограничени, защото са твърде много
+ 208 - 267
sound/pci/asihpi/hpi6205.c


+ 2 - 5
sound/pci/asihpi/hpi6205.h

@@ -25,9 +25,6 @@ Copyright AudioScience, Inc., 2003
 #ifndef _HPI6205_H_
 #ifndef _HPI6205_H_
 #define _HPI6205_H_
 #define _HPI6205_H_
 
 
-/* transitional conditional compile shared between host and DSP */
-/* #define HPI6205_NO_HSR_POLL */
-
 #include "hpi_internal.h"
 #include "hpi_internal.h"
 
 
 /***********************************************************
 /***********************************************************
@@ -78,8 +75,8 @@ struct bus_master_interface {
 	u32 dsp_ack;
 	u32 dsp_ack;
 	u32 transfer_size_in_bytes;
 	u32 transfer_size_in_bytes;
 	union {
 	union {
-		struct hpi_message message_buffer;
-		struct hpi_response response_buffer;
+		struct hpi_message_header message_buffer;
+		struct hpi_response_header response_buffer;
 		u8 b_data[HPI6205_SIZEOF_DATA];
 		u8 b_data[HPI6205_SIZEOF_DATA];
 	} u;
 	} u;
 	struct controlcache_6205 control_cache;
 	struct controlcache_6205 control_cache;

Файловите разлики са ограничени, защото са твърде много
+ 377 - 496
sound/pci/asihpi/hpi_internal.h


+ 265 - 215
sound/pci/asihpi/hpicmn.c

@@ -26,6 +26,8 @@
 
 
 #include "hpi_internal.h"
 #include "hpi_internal.h"
 #include "hpidebug.h"
 #include "hpidebug.h"
+#include "hpimsginit.h"
+
 #include "hpicmn.h"
 #include "hpicmn.h"
 
 
 struct hpi_adapters_list {
 struct hpi_adapters_list {
@@ -43,14 +45,24 @@ static struct hpi_adapters_list adapters;
 **/
 **/
 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
 {
 {
-	u16 error = 0;
+	if (phr->type != HPI_TYPE_RESPONSE) {
+		HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type);
+		return HPI_ERROR_INVALID_RESPONSE;
+	}
 
 
-	if ((phr->type != HPI_TYPE_RESPONSE)
-		|| (phr->object != phm->object)
-		|| (phr->function != phm->function))
-		error = HPI_ERROR_INVALID_RESPONSE;
+	if (phr->object != phm->object) {
+		HPI_DEBUG_LOG(ERROR, "header object %d invalid\n",
+			phr->object);
+		return HPI_ERROR_INVALID_RESPONSE;
+	}
+
+	if (phr->function != phm->function) {
+		HPI_DEBUG_LOG(ERROR, "header type %d invalid\n",
+			phr->function);
+		return HPI_ERROR_INVALID_RESPONSE;
+	}
 
 
-	return error;
+	return 0;
 }
 }
 
 
 u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
 u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
@@ -66,8 +78,18 @@ u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
 	}
 	}
 
 
 	if (adapters.adapter[pao->index].adapter_type) {
 	if (adapters.adapter[pao->index].adapter_type) {
-		{
-			retval = HPI_DUPLICATE_ADAPTER_NUMBER;
+		int a;
+		for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) {
+			if (!adapters.adapter[a].adapter_type) {
+				HPI_DEBUG_LOG(WARNING,
+					"ASI%X duplicate index %d moved to %d\n",
+					pao->adapter_type, pao->index, a);
+				pao->index = a;
+				break;
+			}
+		}
+		if (a < 0) {
+			retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER;
 			goto unlock;
 			goto unlock;
 		}
 		}
 	}
 	}
@@ -76,17 +98,22 @@ u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
 	adapters.gw_num_adapters++;
 	adapters.gw_num_adapters++;
 
 
 unlock:
 unlock:
-	hpios_alistlock_un_lock(&adapters);
+	hpios_alistlock_unlock(&adapters);
 	return retval;
 	return retval;
 }
 }
 
 
 void hpi_delete_adapter(struct hpi_adapter_obj *pao)
 void hpi_delete_adapter(struct hpi_adapter_obj *pao)
 {
 {
-	memset(pao, 0, sizeof(struct hpi_adapter_obj));
+	if (!pao->adapter_type) {
+		HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
+		return;
+	}
 
 
 	hpios_alistlock_lock(&adapters);
 	hpios_alistlock_lock(&adapters);
-	adapters.gw_num_adapters--;	/* dec the number of adapters */
-	hpios_alistlock_un_lock(&adapters);
+	if (adapters.adapter[pao->index].adapter_type)
+		adapters.gw_num_adapters--;
+	memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
+	hpios_alistlock_unlock(&adapters);
 }
 }
 
 
 /**
 /**
@@ -99,7 +126,7 @@ struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
 	struct hpi_adapter_obj *pao = NULL;
 	struct hpi_adapter_obj *pao = NULL;
 
 
 	if (adapter_index >= HPI_MAX_ADAPTERS) {
 	if (adapter_index >= HPI_MAX_ADAPTERS) {
-		HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d ",
+		HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
 			adapter_index);
 			adapter_index);
 		return NULL;
 		return NULL;
 	}
 	}
@@ -125,51 +152,34 @@ struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
 * wipe an HPI_ADAPTERS_LIST structure.
 * wipe an HPI_ADAPTERS_LIST structure.
 *
 *
 **/
 **/
-static void wipe_adapter_list(void
-	)
+static void wipe_adapter_list(void)
 {
 {
 	memset(&adapters, 0, sizeof(adapters));
 	memset(&adapters, 0, sizeof(adapters));
 }
 }
 
 
-/**
-* SubSysGetAdapters fills awAdapterList in an struct hpi_response structure
-* with all adapters in the given HPI_ADAPTERS_LIST.
-*
-*/
-static void subsys_get_adapters(struct hpi_response *phr)
+static void subsys_get_adapter(struct hpi_message *phm,
+	struct hpi_response *phr)
 {
 {
-	/* fill in the response adapter array with the position */
-	/* identified by the adapter number/index of the adapters in */
-	/* this HPI */
-	/* i.e. if we have an A120 with it's jumper set to */
-	/* Adapter Number 2 then put an Adapter type A120 in the */
-	/* array in position 1 */
-	/* NOTE: AdapterNumber is 1..N, Index is 0..N-1 */
-
-	/* input:  NONE */
-	/* output: wNumAdapters */
-	/*                 awAdapter[] */
-	/* */
-
-	short i;
-	struct hpi_adapter_obj *pao = NULL;
+	int count = phm->obj_index;
+	u16 index = 0;
 
 
-	HPI_DEBUG_LOG(VERBOSE, "subsys_get_adapters\n");
-
-	/* for each adapter, place it's type in the position of the array */
-	/* corresponding to it's adapter number */
-	for (i = 0; i < adapters.gw_num_adapters; i++) {
-		pao = &adapters.adapter[i];
-		if (phr->u.s.aw_adapter_list[pao->index] != 0) {
-			phr->error = HPI_DUPLICATE_ADAPTER_NUMBER;
-			phr->specific_error = pao->index;
-			return;
+	/* find the nCount'th nonzero adapter in array */
+	for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
+		if (adapters.adapter[index].adapter_type) {
+			if (!count)
+				break;
+			count--;
 		}
 		}
-		phr->u.s.aw_adapter_list[pao->index] = pao->adapter_type;
 	}
 	}
 
 
-	phr->u.s.num_adapters = adapters.gw_num_adapters;
-	phr->error = 0;	/* the function completed OK; */
+	if (index < HPI_MAX_ADAPTERS) {
+		phr->u.s.adapter_index = adapters.adapter[index].index;
+		phr->u.s.adapter_type = adapters.adapter[index].adapter_type;
+	} else {
+		phr->u.s.adapter_index = 0;
+		phr->u.s.adapter_type = 0;
+		phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER;
+	}
 }
 }
 
 
 static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
 static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
@@ -178,67 +188,98 @@ static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
 	int cached = 0;
 	int cached = 0;
 	if (!pC)
 	if (!pC)
 		return 0;
 		return 0;
-	if ((!pC->init) && (pC->p_cache != NULL) && (pC->control_count)
-		&& (pC->cache_size_in_bytes)
-		) {
-		u32 *p_master_cache;
-		pC->init = 1;
-
-		p_master_cache = (u32 *)pC->p_cache;
-		HPI_DEBUG_LOG(VERBOSE, "check %d controls\n",
+
+	if (pC->init)
+		return pC->init;
+
+	if (!pC->p_cache)
+		return 0;
+
+	if (pC->control_count && pC->cache_size_in_bytes) {
+		char *p_master_cache;
+		unsigned int byte_count = 0;
+
+		p_master_cache = (char *)pC->p_cache;
+		HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
 			pC->control_count);
 			pC->control_count);
 		for (i = 0; i < pC->control_count; i++) {
 		for (i = 0; i < pC->control_count; i++) {
 			struct hpi_control_cache_info *info =
 			struct hpi_control_cache_info *info =
 				(struct hpi_control_cache_info *)
 				(struct hpi_control_cache_info *)
-				p_master_cache;
+				&p_master_cache[byte_count];
+
+			if (!info->size_in32bit_words) {
+				if (!i) {
+					HPI_DEBUG_LOG(INFO,
+						"adap %d cache not ready?\n",
+						pC->adap_idx);
+					return 0;
+				}
+				/* The cache is invalid.
+				 * Minimum valid entry size is
+				 * sizeof(struct hpi_control_cache_info)
+				 */
+				HPI_DEBUG_LOG(ERROR,
+					"adap %d zero size cache entry %d\n",
+					pC->adap_idx, i);
+				break;
+			}
 
 
 			if (info->control_type) {
 			if (info->control_type) {
-				pC->p_info[i] = info;
+				pC->p_info[info->control_index] = info;
 				cached++;
 				cached++;
-			} else
-				pC->p_info[i] = NULL;
+			} else	/* dummy cache entry */
+				pC->p_info[info->control_index] = NULL;
 
 
-			if (info->size_in32bit_words)
-				p_master_cache += info->size_in32bit_words;
-			else
-				p_master_cache +=
-					sizeof(struct
-					hpi_control_cache_single) /
-					sizeof(u32);
+			byte_count += info->size_in32bit_words * 4;
 
 
 			HPI_DEBUG_LOG(VERBOSE,
 			HPI_DEBUG_LOG(VERBOSE,
-				"cached %d, pinfo %p index %d type %d\n",
-				cached, pC->p_info[i], info->control_index,
-				info->control_type);
+				"cached %d, pinfo %p index %d type %d size %d\n",
+				cached, pC->p_info[info->control_index],
+				info->control_index, info->control_type,
+				info->size_in32bit_words);
+
+			/* quit loop early if whole cache has been scanned.
+			 * dwControlCount is the maximum possible entries
+			 * but some may be absent from the cache
+			 */
+			if (byte_count >= pC->cache_size_in_bytes)
+				break;
+			/* have seen last control index */
+			if (info->control_index == pC->control_count - 1)
+				break;
 		}
 		}
-		/*
-		   We didn't find anything to cache, so try again later !
-		 */
-		if (!cached)
-			pC->init = 0;
+
+		if (byte_count != pC->cache_size_in_bytes)
+			HPI_DEBUG_LOG(WARNING,
+				"adap %d bytecount %d != cache size %d\n",
+				pC->adap_idx, byte_count,
+				pC->cache_size_in_bytes);
+		else
+			HPI_DEBUG_LOG(DEBUG,
+				"adap %d cache good, bytecount == cache size = %d\n",
+				pC->adap_idx, byte_count);
+
+		pC->init = (u16)cached;
 	}
 	}
 	return pC->init;
 	return pC->init;
 }
 }
 
 
 /** Find a control.
 /** Find a control.
 */
 */
-static short find_control(struct hpi_message *phm,
-	struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI,
-	u16 *pw_control_index)
+static short find_control(u16 control_index,
+	struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
 {
 {
-	*pw_control_index = phm->obj_index;
-
 	if (!control_cache_alloc_check(p_cache)) {
 	if (!control_cache_alloc_check(p_cache)) {
 		HPI_DEBUG_LOG(VERBOSE,
 		HPI_DEBUG_LOG(VERBOSE,
-			"control_cache_alloc_check() failed. adap%d ci%d\n",
-			phm->adapter_index, *pw_control_index);
+			"control_cache_alloc_check() failed %d\n",
+			control_index);
 		return 0;
 		return 0;
 	}
 	}
 
 
-	*pI = p_cache->p_info[*pw_control_index];
+	*pI = p_cache->p_info[control_index];
 	if (!*pI) {
 	if (!*pI) {
-		HPI_DEBUG_LOG(VERBOSE, "uncached adap %d, control %d\n",
-			phm->adapter_index, *pw_control_index);
+		HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
+			control_index);
 		return 0;
 		return 0;
 	} else {
 	} else {
 		HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
 		HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
@@ -247,25 +288,6 @@ static short find_control(struct hpi_message *phm,
 	return 1;
 	return 1;
 }
 }
 
 
-/** Used by the kernel driver to figure out if a buffer needs mapping.
- */
-short hpi_check_buffer_mapping(struct hpi_control_cache *p_cache,
-	struct hpi_message *phm, void **p, unsigned int *pN)
-{
-	*pN = 0;
-	*p = NULL;
-	if ((phm->function == HPI_CONTROL_GET_STATE)
-		&& (phm->object == HPI_OBJ_CONTROLEX)
-		) {
-		u16 control_index;
-		struct hpi_control_cache_info *pI;
-
-		if (!find_control(phm, p_cache, &pI, &control_index))
-			return 0;
-	}
-	return 0;
-}
-
 /* allow unified treatment of several string fields within struct */
 /* allow unified treatment of several string fields within struct */
 #define HPICMN_PAD_OFS_AND_SIZE(m)  {\
 #define HPICMN_PAD_OFS_AND_SIZE(m)  {\
 	offsetof(struct hpi_control_cache_pad, m), \
 	offsetof(struct hpi_control_cache_pad, m), \
@@ -290,13 +312,16 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 	struct hpi_message *phm, struct hpi_response *phr)
 	struct hpi_message *phm, struct hpi_response *phr)
 {
 {
 	short found = 1;
 	short found = 1;
-	u16 control_index;
 	struct hpi_control_cache_info *pI;
 	struct hpi_control_cache_info *pI;
 	struct hpi_control_cache_single *pC;
 	struct hpi_control_cache_single *pC;
 	struct hpi_control_cache_pad *p_pad;
 	struct hpi_control_cache_pad *p_pad;
 
 
-	if (!find_control(phm, p_cache, &pI, &control_index))
+	if (!find_control(phm->obj_index, p_cache, &pI)) {
+		HPI_DEBUG_LOG(VERBOSE,
+			"HPICMN find_control() failed for adap %d\n",
+			phm->adapter_index);
 		return 0;
 		return 0;
+	}
 
 
 	phr->error = 0;
 	phr->error = 0;
 
 
@@ -310,55 +335,79 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 
 
 	case HPI_CONTROL_METER:
 	case HPI_CONTROL_METER:
 		if (phm->u.c.attribute == HPI_METER_PEAK) {
 		if (phm->u.c.attribute == HPI_METER_PEAK) {
-			phr->u.c.an_log_value[0] = pC->u.p.an_log_peak[0];
-			phr->u.c.an_log_value[1] = pC->u.p.an_log_peak[1];
+			phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
+			phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
 		} else if (phm->u.c.attribute == HPI_METER_RMS) {
 		} else if (phm->u.c.attribute == HPI_METER_RMS) {
-			phr->u.c.an_log_value[0] = pC->u.p.an_logRMS[0];
-			phr->u.c.an_log_value[1] = pC->u.p.an_logRMS[1];
+			if (pC->u.meter.an_logRMS[0] ==
+				HPI_CACHE_INVALID_SHORT) {
+				phr->error =
+					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
+				phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
+				phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
+			} else {
+				phr->u.c.an_log_value[0] =
+					pC->u.meter.an_logRMS[0];
+				phr->u.c.an_log_value[1] =
+					pC->u.meter.an_logRMS[1];
+			}
 		} else
 		} else
 			found = 0;
 			found = 0;
 		break;
 		break;
 	case HPI_CONTROL_VOLUME:
 	case HPI_CONTROL_VOLUME:
 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
-			phr->u.c.an_log_value[0] = pC->u.v.an_log[0];
-			phr->u.c.an_log_value[1] = pC->u.v.an_log[1];
-		} else
+			phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
+			phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
+		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
+			if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
+				if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
+					phr->u.c.param1 =
+						HPI_BITMASK_ALL_CHANNELS;
+				else
+					phr->u.c.param1 = 0;
+			} else {
+				phr->error =
+					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
+				phr->u.c.param1 = 0;
+			}
+		} else {
 			found = 0;
 			found = 0;
+		}
 		break;
 		break;
 	case HPI_CONTROL_MULTIPLEXER:
 	case HPI_CONTROL_MULTIPLEXER:
 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
-			phr->u.c.param1 = pC->u.x.source_node_type;
-			phr->u.c.param2 = pC->u.x.source_node_index;
+			phr->u.c.param1 = pC->u.mux.source_node_type;
+			phr->u.c.param2 = pC->u.mux.source_node_index;
 		} else {
 		} else {
 			found = 0;
 			found = 0;
 		}
 		}
 		break;
 		break;
 	case HPI_CONTROL_CHANNEL_MODE:
 	case HPI_CONTROL_CHANNEL_MODE:
 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
-			phr->u.c.param1 = pC->u.m.mode;
+			phr->u.c.param1 = pC->u.mode.mode;
 		else
 		else
 			found = 0;
 			found = 0;
 		break;
 		break;
 	case HPI_CONTROL_LEVEL:
 	case HPI_CONTROL_LEVEL:
 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
-			phr->u.c.an_log_value[0] = pC->u.l.an_log[0];
-			phr->u.c.an_log_value[1] = pC->u.l.an_log[1];
+			phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
+			phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
 		} else
 		} else
 			found = 0;
 			found = 0;
 		break;
 		break;
 	case HPI_CONTROL_TUNER:
 	case HPI_CONTROL_TUNER:
 		if (phm->u.c.attribute == HPI_TUNER_FREQ)
 		if (phm->u.c.attribute == HPI_TUNER_FREQ)
-			phr->u.c.param1 = pC->u.t.freq_ink_hz;
+			phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
 		else if (phm->u.c.attribute == HPI_TUNER_BAND)
 		else if (phm->u.c.attribute == HPI_TUNER_BAND)
-			phr->u.c.param1 = pC->u.t.band;
-		else if ((phm->u.c.attribute == HPI_TUNER_LEVEL)
-			&& (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE))
-			if (pC->u.t.level == HPI_ERROR_ILLEGAL_CACHE_VALUE) {
-				phr->u.c.param1 = 0;
+			phr->u.c.param1 = pC->u.tuner.band;
+		else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
+			if (pC->u.tuner.s_level_avg ==
+				HPI_CACHE_INVALID_SHORT) {
+				phr->u.cu.tuner.s_level = 0;
 				phr->error =
 				phr->error =
 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 			} else
 			} else
-				phr->u.c.param1 = pC->u.t.level;
+				phr->u.cu.tuner.s_level =
+					pC->u.tuner.s_level_avg;
 		else
 		else
 			found = 0;
 			found = 0;
 		break;
 		break;
@@ -366,7 +415,7 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 		if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
 		if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
 			phr->u.c.param1 = pC->u.aes3rx.error_status;
 			phr->u.c.param1 = pC->u.aes3rx.error_status;
 		else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
 		else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
-			phr->u.c.param1 = pC->u.aes3rx.source;
+			phr->u.c.param1 = pC->u.aes3rx.format;
 		else
 		else
 			found = 0;
 			found = 0;
 		break;
 		break;
@@ -385,13 +434,12 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 	case HPI_CONTROL_SILENCEDETECTOR:
 	case HPI_CONTROL_SILENCEDETECTOR:
 		if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
 		if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
 			phr->u.c.param1 = pC->u.silence.state;
 			phr->u.c.param1 = pC->u.silence.state;
-			phr->u.c.param2 = pC->u.silence.count;
 		} else
 		} else
 			found = 0;
 			found = 0;
 		break;
 		break;
 	case HPI_CONTROL_MICROPHONE:
 	case HPI_CONTROL_MICROPHONE:
 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
-			phr->u.c.param1 = pC->u.phantom_power.state;
+			phr->u.c.param1 = pC->u.microphone.phantom_state;
 		else
 		else
 			found = 0;
 			found = 0;
 		break;
 		break;
@@ -400,7 +448,7 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 			phr->u.c.param1 = pC->u.clk.source;
 			phr->u.c.param1 = pC->u.clk.source;
 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
 			if (pC->u.clk.source_index ==
 			if (pC->u.clk.source_index ==
-				HPI_ERROR_ILLEGAL_CACHE_VALUE) {
+				HPI_CACHE_INVALID_UINT16) {
 				phr->u.c.param1 = 0;
 				phr->u.c.param1 = 0;
 				phr->error =
 				phr->error =
 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
@@ -411,60 +459,63 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 		else
 		else
 			found = 0;
 			found = 0;
 		break;
 		break;
-	case HPI_CONTROL_PAD:
+	case HPI_CONTROL_PAD:{
+			struct hpi_control_cache_pad *p_pad;
+			p_pad = (struct hpi_control_cache_pad *)pI;
 
 
-		if (!(p_pad->field_valid_flags & (1 <<
-					HPI_CTL_ATTR_INDEX(phm->u.c.
-						attribute)))) {
-			phr->error = HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
-			break;
-		}
-
-		if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
-			phr->u.c.param1 = p_pad->pI;
-		else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
-			phr->u.c.param1 = p_pad->pTY;
-		else {
-			unsigned int index =
-				HPI_CTL_ATTR_INDEX(phm->u.c.attribute) - 1;
-			unsigned int offset = phm->u.c.param1;
-			unsigned int pad_string_len, field_size;
-			char *pad_string;
-			unsigned int tocopy;
-
-			HPI_DEBUG_LOG(VERBOSE, "PADS HPI_PADS_ %d\n",
-				phm->u.c.attribute);
-
-			if (index > ARRAY_SIZE(pad_desc) - 1) {
+			if (!(p_pad->field_valid_flags & (1 <<
+						HPI_CTL_ATTR_INDEX(phm->u.c.
+							attribute)))) {
 				phr->error =
 				phr->error =
 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
 				break;
 				break;
 			}
 			}
 
 
-			pad_string = ((char *)p_pad) + pad_desc[index].offset;
-			field_size = pad_desc[index].field_size;
-			/* Ensure null terminator */
-			pad_string[field_size - 1] = 0;
-
-			pad_string_len = strlen(pad_string) + 1;
-
-			if (offset > pad_string_len) {
-				phr->error = HPI_ERROR_INVALID_CONTROL_VALUE;
-				break;
+			if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
+				phr->u.c.param1 = p_pad->pI;
+			else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
+				phr->u.c.param1 = p_pad->pTY;
+			else {
+				unsigned int index =
+					HPI_CTL_ATTR_INDEX(phm->u.c.
+					attribute) - 1;
+				unsigned int offset = phm->u.c.param1;
+				unsigned int pad_string_len, field_size;
+				char *pad_string;
+				unsigned int tocopy;
+
+				if (index > ARRAY_SIZE(pad_desc) - 1) {
+					phr->error =
+						HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
+					break;
+				}
+
+				pad_string =
+					((char *)p_pad) +
+					pad_desc[index].offset;
+				field_size = pad_desc[index].field_size;
+				/* Ensure null terminator */
+				pad_string[field_size - 1] = 0;
+
+				pad_string_len = strlen(pad_string) + 1;
+
+				if (offset > pad_string_len) {
+					phr->error =
+						HPI_ERROR_INVALID_CONTROL_VALUE;
+					break;
+				}
+
+				tocopy = pad_string_len - offset;
+				if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
+					tocopy = sizeof(phr->u.cu.chars8.
+						sz_data);
+
+				memcpy(phr->u.cu.chars8.sz_data,
+					&pad_string[offset], tocopy);
+
+				phr->u.cu.chars8.remaining_chars =
+					pad_string_len - offset - tocopy;
 			}
 			}
-
-			tocopy = pad_string_len - offset;
-			if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
-				tocopy = sizeof(phr->u.cu.chars8.sz_data);
-
-			HPI_DEBUG_LOG(VERBOSE,
-				"PADS memcpy(%d), offset %d \n", tocopy,
-				offset);
-			memcpy(phr->u.cu.chars8.sz_data, &pad_string[offset],
-				tocopy);
-
-			phr->u.cu.chars8.remaining_chars =
-				pad_string_len - offset - tocopy;
 		}
 		}
 		break;
 		break;
 	default:
 	default:
@@ -472,16 +523,9 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
 		break;
 		break;
 	}
 	}
 
 
-	if (found)
-		HPI_DEBUG_LOG(VERBOSE,
-			"cached adap %d, ctl %d, type %d, attr %d\n",
-			phm->adapter_index, pI->control_index,
-			pI->control_type, phm->u.c.attribute);
-	else
-		HPI_DEBUG_LOG(VERBOSE,
-			"uncached adap %d, ctl %d, ctl type %d\n",
-			phm->adapter_index, pI->control_index,
-			pI->control_type);
+	HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
+		found ? "Cached" : "Uncached", phm->adapter_index,
+		pI->control_index, pI->control_type, phm->u.c.attribute);
 
 
 	if (found)
 	if (found)
 		phr->size =
 		phr->size =
@@ -497,18 +541,21 @@ Only update if no error.
 Volume and Level return the limited values in the response, so use these
 Volume and Level return the limited values in the response, so use these
 Multiplexer does so use sent values
 Multiplexer does so use sent values
 */
 */
-void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
+void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
 	struct hpi_message *phm, struct hpi_response *phr)
 	struct hpi_message *phm, struct hpi_response *phr)
 {
 {
-	u16 control_index;
 	struct hpi_control_cache_single *pC;
 	struct hpi_control_cache_single *pC;
 	struct hpi_control_cache_info *pI;
 	struct hpi_control_cache_info *pI;
 
 
 	if (phr->error)
 	if (phr->error)
 		return;
 		return;
 
 
-	if (!find_control(phm, p_cache, &pI, &control_index))
+	if (!find_control(phm->obj_index, p_cache, &pI)) {
+		HPI_DEBUG_LOG(VERBOSE,
+			"HPICMN find_control() failed for adap %d\n",
+			phm->adapter_index);
 		return;
 		return;
+	}
 
 
 	/* pC is the default cached control strucure.
 	/* pC is the default cached control strucure.
 	   May be cast to something else in the following switch statement.
 	   May be cast to something else in the following switch statement.
@@ -518,31 +565,36 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
 	switch (pI->control_type) {
 	switch (pI->control_type) {
 	case HPI_CONTROL_VOLUME:
 	case HPI_CONTROL_VOLUME:
 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
-			pC->u.v.an_log[0] = phr->u.c.an_log_value[0];
-			pC->u.v.an_log[1] = phr->u.c.an_log_value[1];
+			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
+			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
+		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
+			if (phm->u.c.param1)
+				pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
+			else
+				pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
 		}
 		}
 		break;
 		break;
 	case HPI_CONTROL_MULTIPLEXER:
 	case HPI_CONTROL_MULTIPLEXER:
 		/* mux does not return its setting on Set command. */
 		/* mux does not return its setting on Set command. */
 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
-			pC->u.x.source_node_type = (u16)phm->u.c.param1;
-			pC->u.x.source_node_index = (u16)phm->u.c.param2;
+			pC->u.mux.source_node_type = (u16)phm->u.c.param1;
+			pC->u.mux.source_node_index = (u16)phm->u.c.param2;
 		}
 		}
 		break;
 		break;
 	case HPI_CONTROL_CHANNEL_MODE:
 	case HPI_CONTROL_CHANNEL_MODE:
 		/* mode does not return its setting on Set command. */
 		/* mode does not return its setting on Set command. */
 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
-			pC->u.m.mode = (u16)phm->u.c.param1;
+			pC->u.mode.mode = (u16)phm->u.c.param1;
 		break;
 		break;
 	case HPI_CONTROL_LEVEL:
 	case HPI_CONTROL_LEVEL:
 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
-			pC->u.v.an_log[0] = phr->u.c.an_log_value[0];
-			pC->u.v.an_log[1] = phr->u.c.an_log_value[1];
+			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
+			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
 		}
 		}
 		break;
 		break;
 	case HPI_CONTROL_MICROPHONE:
 	case HPI_CONTROL_MICROPHONE:
 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
-			pC->u.phantom_power.state = (u16)phm->u.c.param1;
+			pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
 		break;
 		break;
 	case HPI_CONTROL_AESEBU_TRANSMITTER:
 	case HPI_CONTROL_AESEBU_TRANSMITTER:
 		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
 		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
@@ -550,7 +602,7 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
 		break;
 		break;
 	case HPI_CONTROL_AESEBU_RECEIVER:
 	case HPI_CONTROL_AESEBU_RECEIVER:
 		if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
 		if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
-			pC->u.aes3rx.source = phm->u.c.param1;
+			pC->u.aes3rx.format = phm->u.c.param1;
 		break;
 		break;
 	case HPI_CONTROL_SAMPLECLOCK:
 	case HPI_CONTROL_SAMPLECLOCK:
 		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
 		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
@@ -565,59 +617,57 @@ void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
 	}
 	}
 }
 }
 
 
-struct hpi_control_cache *hpi_alloc_control_cache(const u32
-	number_of_controls, const u32 size_in_bytes,
-	struct hpi_control_cache_info *pDSP_control_buffer)
+struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
+	const u32 size_in_bytes, u8 *p_dsp_control_buffer)
 {
 {
 	struct hpi_control_cache *p_cache =
 	struct hpi_control_cache *p_cache =
 		kmalloc(sizeof(*p_cache), GFP_KERNEL);
 		kmalloc(sizeof(*p_cache), GFP_KERNEL);
 	if (!p_cache)
 	if (!p_cache)
 		return NULL;
 		return NULL;
+
 	p_cache->p_info =
 	p_cache->p_info =
-		kmalloc(sizeof(*p_cache->p_info) * number_of_controls,
-			GFP_KERNEL);
+		kmalloc(sizeof(*p_cache->p_info) * control_count, GFP_KERNEL);
 	if (!p_cache->p_info) {
 	if (!p_cache->p_info) {
 		kfree(p_cache);
 		kfree(p_cache);
 		return NULL;
 		return NULL;
 	}
 	}
+	memset(p_cache->p_info, 0, sizeof(*p_cache->p_info) * control_count);
 	p_cache->cache_size_in_bytes = size_in_bytes;
 	p_cache->cache_size_in_bytes = size_in_bytes;
-	p_cache->control_count = number_of_controls;
-	p_cache->p_cache =
-		(struct hpi_control_cache_single *)pDSP_control_buffer;
+	p_cache->control_count = control_count;
+	p_cache->p_cache = p_dsp_control_buffer;
 	p_cache->init = 0;
 	p_cache->init = 0;
 	return p_cache;
 	return p_cache;
 }
 }
 
 
 void hpi_free_control_cache(struct hpi_control_cache *p_cache)
 void hpi_free_control_cache(struct hpi_control_cache *p_cache)
 {
 {
-	if (p_cache->init) {
+	if (p_cache) {
 		kfree(p_cache->p_info);
 		kfree(p_cache->p_info);
-		p_cache->p_info = NULL;
-		p_cache->init = 0;
 		kfree(p_cache);
 		kfree(p_cache);
 	}
 	}
 }
 }
 
 
 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
 {
 {
+	hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
 
 
 	switch (phm->function) {
 	switch (phm->function) {
 	case HPI_SUBSYS_OPEN:
 	case HPI_SUBSYS_OPEN:
 	case HPI_SUBSYS_CLOSE:
 	case HPI_SUBSYS_CLOSE:
 	case HPI_SUBSYS_DRIVER_UNLOAD:
 	case HPI_SUBSYS_DRIVER_UNLOAD:
-		phr->error = 0;
 		break;
 		break;
 	case HPI_SUBSYS_DRIVER_LOAD:
 	case HPI_SUBSYS_DRIVER_LOAD:
 		wipe_adapter_list();
 		wipe_adapter_list();
 		hpios_alistlock_init(&adapters);
 		hpios_alistlock_init(&adapters);
-		phr->error = 0;
 		break;
 		break;
-	case HPI_SUBSYS_GET_INFO:
-		subsys_get_adapters(phr);
+	case HPI_SUBSYS_GET_ADAPTER:
+		subsys_get_adapter(phm, phr);
+		break;
+	case HPI_SUBSYS_GET_NUM_ADAPTERS:
+		phr->u.s.num_adapters = adapters.gw_num_adapters;
 		break;
 		break;
 	case HPI_SUBSYS_CREATE_ADAPTER:
 	case HPI_SUBSYS_CREATE_ADAPTER:
 	case HPI_SUBSYS_DELETE_ADAPTER:
 	case HPI_SUBSYS_DELETE_ADAPTER:
-		phr->error = 0;
 		break;
 		break;
 	default:
 	default:
 		phr->error = HPI_ERROR_INVALID_FUNC;
 		phr->error = HPI_ERROR_INVALID_FUNC;

+ 11 - 13
sound/pci/asihpi/hpicmn.h

@@ -33,18 +33,19 @@ struct hpi_adapter_obj {
 };
 };
 
 
 struct hpi_control_cache {
 struct hpi_control_cache {
-	u32 init;	     /**< indicates whether the
-				structures are initialized */
+	/** indicates whether the structures are initialized */
+	u16 init;
+	u16 adap_idx;
 	u32 control_count;
 	u32 control_count;
 	u32 cache_size_in_bytes;
 	u32 cache_size_in_bytes;
-	struct hpi_control_cache_info
-	**p_info;		 /**< pointer to allocated memory of
-				lookup pointers. */
-	struct hpi_control_cache_single
-	*p_cache;		 /**< pointer to DSP's control cache. */
+	/** pointer to allocated memory of lookup pointers. */
+	struct hpi_control_cache_info **p_info;
+	/** pointer to DSP's control cache. */
+	u8 *p_cache;
 };
 };
 
 
 struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index);
 struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index);
+
 u16 hpi_add_adapter(struct hpi_adapter_obj *pao);
 u16 hpi_add_adapter(struct hpi_adapter_obj *pao);
 
 
 void hpi_delete_adapter(struct hpi_adapter_obj *pao);
 void hpi_delete_adapter(struct hpi_adapter_obj *pao);
@@ -52,13 +53,10 @@ void hpi_delete_adapter(struct hpi_adapter_obj *pao);
 short hpi_check_control_cache(struct hpi_control_cache *pC,
 short hpi_check_control_cache(struct hpi_control_cache *pC,
 	struct hpi_message *phm, struct hpi_response *phr);
 	struct hpi_message *phm, struct hpi_response *phr);
 struct hpi_control_cache *hpi_alloc_control_cache(const u32
 struct hpi_control_cache *hpi_alloc_control_cache(const u32
-	number_of_controls, const u32 size_in_bytes,
-	struct hpi_control_cache_info
-	*pDSP_control_buffer);
+	number_of_controls, const u32 size_in_bytes, u8 *pDSP_control_buffer);
 void hpi_free_control_cache(struct hpi_control_cache *p_cache);
 void hpi_free_control_cache(struct hpi_control_cache *p_cache);
 
 
-void hpi_sync_control_cache(struct hpi_control_cache *pC,
+void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *pC,
 	struct hpi_message *phm, struct hpi_response *phr);
 	struct hpi_message *phm, struct hpi_response *phr);
+
 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr);
 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr);
-short hpi_check_buffer_mapping(struct hpi_control_cache *p_cache,
-	struct hpi_message *phm, void **p, unsigned int *pN);

+ 5 - 152
sound/pci/asihpi/hpidebug.c

@@ -45,161 +45,14 @@ int hpi_debug_level_get(void)
 	return hpi_debug_level;
 	return hpi_debug_level;
 }
 }
 
 
-#ifdef HPIOS_DEBUG_PRINT
-/* implies OS has no printf-like function */
-#include <stdarg.h>
-
-void hpi_debug_printf(char *fmt, ...)
-{
-	va_list arglist;
-	char buffer[128];
-
-	va_start(arglist, fmt);
-
-	if (buffer[0])
-		HPIOS_DEBUG_PRINT(buffer);
-	va_end(arglist);
-}
-#endif
-
-struct treenode {
-	void *array;
-	unsigned int num_elements;
-};
-
-#define make_treenode_from_array(nodename, array) \
-static void *tmp_strarray_##nodename[] = array; \
-static struct treenode nodename = { \
-	&tmp_strarray_##nodename, \
-	ARRAY_SIZE(tmp_strarray_##nodename) \
-};
-
-#define get_treenode_elem(node_ptr, idx, type)  \
-	(&(*((type *)(node_ptr)->array)[idx]))
-
-make_treenode_from_array(hpi_control_type_strings, HPI_CONTROL_TYPE_STRINGS)
-
-	make_treenode_from_array(hpi_subsys_strings, HPI_SUBSYS_STRINGS)
-	make_treenode_from_array(hpi_adapter_strings, HPI_ADAPTER_STRINGS)
-	make_treenode_from_array(hpi_istream_strings, HPI_ISTREAM_STRINGS)
-	make_treenode_from_array(hpi_ostream_strings, HPI_OSTREAM_STRINGS)
-	make_treenode_from_array(hpi_mixer_strings, HPI_MIXER_STRINGS)
-	make_treenode_from_array(hpi_node_strings,
-	{
-	"NODE is invalid object"})
-
-	make_treenode_from_array(hpi_control_strings, HPI_CONTROL_STRINGS)
-	make_treenode_from_array(hpi_nvmemory_strings, HPI_OBJ_STRINGS)
-	make_treenode_from_array(hpi_digitalio_strings, HPI_DIGITALIO_STRINGS)
-	make_treenode_from_array(hpi_watchdog_strings, HPI_WATCHDOG_STRINGS)
-	make_treenode_from_array(hpi_clock_strings, HPI_CLOCK_STRINGS)
-	make_treenode_from_array(hpi_profile_strings, HPI_PROFILE_STRINGS)
-	make_treenode_from_array(hpi_asyncevent_strings, HPI_ASYNCEVENT_STRINGS)
-#define HPI_FUNCTION_STRINGS \
-{ \
-  &hpi_subsys_strings,\
-  &hpi_adapter_strings,\
-  &hpi_ostream_strings,\
-  &hpi_istream_strings,\
-  &hpi_mixer_strings,\
-  &hpi_node_strings,\
-  &hpi_control_strings,\
-  &hpi_nvmemory_strings,\
-  &hpi_digitalio_strings,\
-  &hpi_watchdog_strings,\
-  &hpi_clock_strings,\
-  &hpi_profile_strings,\
-  &hpi_control_strings, \
-  &hpi_asyncevent_strings \
-}
-	make_treenode_from_array(hpi_function_strings, HPI_FUNCTION_STRINGS)
-
-	compile_time_assert(HPI_OBJ_MAXINDEX == 14, obj_list_doesnt_match);
-
-static char *hpi_function_string(unsigned int function)
-{
-	unsigned int object;
-	struct treenode *tmp;
-
-	object = function / HPI_OBJ_FUNCTION_SPACING;
-	function = function - object * HPI_OBJ_FUNCTION_SPACING;
-
-	if (object == 0 || object == HPI_OBJ_NODE
-		|| object > hpi_function_strings.num_elements)
-		return "invalid object";
-
-	tmp = get_treenode_elem(&hpi_function_strings, object - 1,
-		struct treenode *);
-
-	if (function == 0 || function > tmp->num_elements)
-		return "invalid function";
-
-	return get_treenode_elem(tmp, function - 1, char *);
-}
-
 void hpi_debug_message(struct hpi_message *phm, char *sz_fileline)
 void hpi_debug_message(struct hpi_message *phm, char *sz_fileline)
 {
 {
 	if (phm) {
 	if (phm) {
-		if ((phm->object <= HPI_OBJ_MAXINDEX) && phm->object) {
-			u16 index = 0;
-			u16 attrib = 0;
-			int is_control = 0;
-
-			index = phm->obj_index;
-			switch (phm->object) {
-			case HPI_OBJ_ADAPTER:
-			case HPI_OBJ_PROFILE:
-				break;
-			case HPI_OBJ_MIXER:
-				if (phm->function ==
-					HPI_MIXER_GET_CONTROL_BY_INDEX)
-					index = phm->u.m.control_index;
-				break;
-			case HPI_OBJ_OSTREAM:
-			case HPI_OBJ_ISTREAM:
-				break;
-
-			case HPI_OBJ_CONTROLEX:
-			case HPI_OBJ_CONTROL:
-				if (phm->version == 1)
-					attrib = HPI_CTL_ATTR(UNIVERSAL, 1);
-				else
-					attrib = phm->u.c.attribute;
-				is_control = 1;
-				break;
-			default:
-				break;
-			}
-
-			if (is_control && (attrib & 0xFF00)) {
-				int control_type = (attrib & 0xFF00) >> 8;
-				int attr_index = HPI_CTL_ATTR_INDEX(attrib);
-				/* note the KERN facility level
-				   is in szFileline already */
-				printk("%s adapter %d %s "
-					"ctrl_index x%04x %s %d\n",
-					sz_fileline, phm->adapter_index,
-					hpi_function_string(phm->function),
-					index,
-					get_treenode_elem
-					(&hpi_control_type_strings,
-						control_type, char *),
-					attr_index);
-
-			} else
-				printk("%s adapter %d %s "
-					"idx x%04x attr x%04x \n",
-					sz_fileline, phm->adapter_index,
-					hpi_function_string(phm->function),
-					index, attrib);
-		} else {
-			printk("adap=%d, invalid obj=%d, func=0x%x\n",
-				phm->adapter_index, phm->object,
-				phm->function);
-		}
-	} else
-		printk(KERN_ERR
-			"NULL message pointer to hpi_debug_message!\n");
+		printk(KERN_DEBUG "HPI_MSG%d,%d,%d,%d,%d\n", phm->version,
+			phm->adapter_index, phm->obj_index, phm->function,
+			phm->u.c.attribute);
+	}
+
 }
 }
 
 
 void hpi_debug_data(u16 *pdata, u32 len)
 void hpi_debug_data(u16 *pdata, u32 len)

+ 20 - 303
sound/pci/asihpi/hpidebug.h

@@ -37,7 +37,7 @@ enum { HPI_DEBUG_LEVEL_ERROR = 0,	/* always log errors */
 #define HPI_DEBUG_LEVEL_DEFAULT HPI_DEBUG_LEVEL_NOTICE
 #define HPI_DEBUG_LEVEL_DEFAULT HPI_DEBUG_LEVEL_NOTICE
 
 
 /* an OS can define an extra flag string that is appended to
 /* an OS can define an extra flag string that is appended to
-   the start of each message, eg see hpios_linux.h */
+   the start of each message, eg see linux kernel hpios.h */
 
 
 #ifdef SOURCEFILE_NAME
 #ifdef SOURCEFILE_NAME
 #define FILE_LINE  SOURCEFILE_NAME ":" __stringify(__LINE__) " "
 #define FILE_LINE  SOURCEFILE_NAME ":" __stringify(__LINE__) " "
@@ -45,18 +45,11 @@ enum { HPI_DEBUG_LEVEL_ERROR = 0,	/* always log errors */
 #define FILE_LINE  __FILE__ ":" __stringify(__LINE__) " "
 #define FILE_LINE  __FILE__ ":" __stringify(__LINE__) " "
 #endif
 #endif
 
 
-#if defined(HPI_DEBUG) && defined(_WINDOWS)
-#define HPI_DEBUGBREAK() debug_break()
-#else
-#define HPI_DEBUGBREAK()
-#endif
-
 #define HPI_DEBUG_ASSERT(expression) \
 #define HPI_DEBUG_ASSERT(expression) \
 	do { \
 	do { \
-		if (!(expression)) {\
-			printk(KERN_ERR  FILE_LINE\
-				"ASSERT " __stringify(expression));\
-			HPI_DEBUGBREAK();\
+		if (!(expression)) { \
+			printk(KERN_ERR  FILE_LINE \
+				"ASSERT " __stringify(expression)); \
 		} \
 		} \
 	} while (0)
 	} while (0)
 
 
@@ -78,28 +71,27 @@ void hpi_debug_message(struct hpi_message *phm, char *sz_fileline);
 
 
 void hpi_debug_data(u16 *pdata, u32 len);
 void hpi_debug_data(u16 *pdata, u32 len);
 
 
-#define HPI_DEBUG_DATA(pdata, len)                                      \
-	do {                                                            \
+#define HPI_DEBUG_DATA(pdata, len) \
+	do { \
 		if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE) \
 		if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE) \
 			hpi_debug_data(pdata, len); \
 			hpi_debug_data(pdata, len); \
 	} while (0)
 	} while (0)
 
 
-#define HPI_DEBUG_MESSAGE(level, phm)                                   \
-	do {                                                            \
-		if (hpi_debug_level >= HPI_DEBUG_LEVEL_##level) {         \
-			hpi_debug_message(phm,HPI_DEBUG_FLAG_##level    \
-				FILE_LINE __stringify(level));\
-		}                                                       \
+#define HPI_DEBUG_MESSAGE(level, phm) \
+	do { \
+		if (hpi_debug_level >= HPI_DEBUG_LEVEL_##level) { \
+			hpi_debug_message(phm, HPI_DEBUG_FLAG_##level \
+				FILE_LINE __stringify(level)); \
+		} \
 	} while (0)
 	} while (0)
 
 
-#define HPI_DEBUG_RESPONSE(phr)                                         \
-	do {                                                            \
-		if ((hpi_debug_level >= HPI_DEBUG_LEVEL_DEBUG) && (phr->error))\
-			HPI_DEBUG_LOG(ERROR, \
-				"HPI response - error# %d\n", \
-				phr->error); \
-		else if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE) \
-			HPI_DEBUG_LOG(VERBOSE, "HPI response OK\n");\
+#define HPI_DEBUG_RESPONSE(phr) \
+	do { \
+		if (((hpi_debug_level >= HPI_DEBUG_LEVEL_DEBUG) && \
+			(phr->error)) ||\
+		(hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE)) \
+			printk(KERN_DEBUG "HPI_RES%d,%d,%d\n", \
+				phr->version, phr->error, phr->specific_error); \
 	} while (0)
 	} while (0)
 
 
 #ifndef compile_time_assert
 #ifndef compile_time_assert
@@ -107,279 +99,4 @@ void hpi_debug_data(u16 *pdata, u32 len);
     typedef char msg[(cond) ? 1 : -1]
     typedef char msg[(cond) ? 1 : -1]
 #endif
 #endif
 
 
-	  /* check that size is exactly some number */
-#define function_count_check(sym, size) \
-    compile_time_assert((sym##_FUNCTION_COUNT) == (size),\
-	    strings_match_defs_##sym)
-
-/* These strings should be generated using a macro which defines
-   the corresponding symbol values.  */
-#define HPI_OBJ_STRINGS \
-{                               \
-  "HPI_OBJ_SUBSYSTEM",        \
-  "HPI_OBJ_ADAPTER",          \
-  "HPI_OBJ_OSTREAM",          \
-  "HPI_OBJ_ISTREAM",          \
-  "HPI_OBJ_MIXER",            \
-  "HPI_OBJ_NODE",             \
-  "HPI_OBJ_CONTROL",          \
-  "HPI_OBJ_NVMEMORY",         \
-  "HPI_OBJ_DIGITALIO",        \
-  "HPI_OBJ_WATCHDOG",         \
-  "HPI_OBJ_CLOCK",            \
-  "HPI_OBJ_PROFILE",          \
-  "HPI_OBJ_CONTROLEX"         \
-}
-
-#define HPI_SUBSYS_STRINGS      \
-{                               \
-  "HPI_SUBSYS_OPEN",          \
-  "HPI_SUBSYS_GET_VERSION",   \
-  "HPI_SUBSYS_GET_INFO",      \
-  "HPI_SUBSYS_FIND_ADAPTERS", \
-  "HPI_SUBSYS_CREATE_ADAPTER",\
-  "HPI_SUBSYS_CLOSE",         \
-  "HPI_SUBSYS_DELETE_ADAPTER", \
-  "HPI_SUBSYS_DRIVER_LOAD", \
-  "HPI_SUBSYS_DRIVER_UNLOAD", \
-  "HPI_SUBSYS_READ_PORT_8",   \
-  "HPI_SUBSYS_WRITE_PORT_8",  \
-  "HPI_SUBSYS_GET_NUM_ADAPTERS",\
-  "HPI_SUBSYS_GET_ADAPTER",   \
-  "HPI_SUBSYS_SET_NETWORK_INTERFACE"\
-}
-function_count_check(HPI_SUBSYS, 14);
-
-#define HPI_ADAPTER_STRINGS     \
-{                               \
-  "HPI_ADAPTER_OPEN",         \
-  "HPI_ADAPTER_CLOSE",        \
-  "HPI_ADAPTER_GET_INFO",     \
-  "HPI_ADAPTER_GET_ASSERT",   \
-  "HPI_ADAPTER_TEST_ASSERT",    \
-  "HPI_ADAPTER_SET_MODE",       \
-  "HPI_ADAPTER_GET_MODE",       \
-  "HPI_ADAPTER_ENABLE_CAPABILITY",\
-  "HPI_ADAPTER_SELFTEST",        \
-  "HPI_ADAPTER_FIND_OBJECT",     \
-  "HPI_ADAPTER_QUERY_FLASH",     \
-  "HPI_ADAPTER_START_FLASH",     \
-  "HPI_ADAPTER_PROGRAM_FLASH",   \
-  "HPI_ADAPTER_SET_PROPERTY",    \
-  "HPI_ADAPTER_GET_PROPERTY",    \
-  "HPI_ADAPTER_ENUM_PROPERTY",    \
-  "HPI_ADAPTER_MODULE_INFO",    \
-  "HPI_ADAPTER_DEBUG_READ"    \
-}
-
-function_count_check(HPI_ADAPTER, 18);
-
-#define HPI_OSTREAM_STRINGS     \
-{                               \
-  "HPI_OSTREAM_OPEN",         \
-  "HPI_OSTREAM_CLOSE",        \
-  "HPI_OSTREAM_WRITE",        \
-  "HPI_OSTREAM_START",        \
-  "HPI_OSTREAM_STOP",         \
-  "HPI_OSTREAM_RESET",                \
-  "HPI_OSTREAM_GET_INFO",     \
-  "HPI_OSTREAM_QUERY_FORMAT", \
-  "HPI_OSTREAM_DATA",         \
-  "HPI_OSTREAM_SET_VELOCITY", \
-  "HPI_OSTREAM_SET_PUNCHINOUT", \
-  "HPI_OSTREAM_SINEGEN",        \
-  "HPI_OSTREAM_ANC_RESET",      \
-  "HPI_OSTREAM_ANC_GET_INFO",   \
-  "HPI_OSTREAM_ANC_READ",       \
-  "HPI_OSTREAM_SET_TIMESCALE",\
-  "HPI_OSTREAM_SET_FORMAT", \
-  "HPI_OSTREAM_HOSTBUFFER_ALLOC", \
-  "HPI_OSTREAM_HOSTBUFFER_FREE", \
-  "HPI_OSTREAM_GROUP_ADD",\
-  "HPI_OSTREAM_GROUP_GETMAP", \
-  "HPI_OSTREAM_GROUP_RESET", \
-  "HPI_OSTREAM_HOSTBUFFER_GET_INFO", \
-  "HPI_OSTREAM_WAIT_START", \
-}
-function_count_check(HPI_OSTREAM, 24);
-
-#define HPI_ISTREAM_STRINGS     \
-{                               \
-  "HPI_ISTREAM_OPEN",         \
-  "HPI_ISTREAM_CLOSE",        \
-  "HPI_ISTREAM_SET_FORMAT",   \
-  "HPI_ISTREAM_READ",         \
-  "HPI_ISTREAM_START",        \
-  "HPI_ISTREAM_STOP",         \
-  "HPI_ISTREAM_RESET",        \
-  "HPI_ISTREAM_GET_INFO",     \
-  "HPI_ISTREAM_QUERY_FORMAT", \
-  "HPI_ISTREAM_ANC_RESET",      \
-  "HPI_ISTREAM_ANC_GET_INFO",   \
-  "HPI_ISTREAM_ANC_WRITE",   \
-  "HPI_ISTREAM_HOSTBUFFER_ALLOC",\
-  "HPI_ISTREAM_HOSTBUFFER_FREE", \
-  "HPI_ISTREAM_GROUP_ADD", \
-  "HPI_ISTREAM_GROUP_GETMAP", \
-  "HPI_ISTREAM_GROUP_RESET", \
-  "HPI_ISTREAM_HOSTBUFFER_GET_INFO", \
-  "HPI_ISTREAM_WAIT_START", \
-}
-function_count_check(HPI_ISTREAM, 19);
-
-#define HPI_MIXER_STRINGS       \
-{                               \
-  "HPI_MIXER_OPEN",           \
-  "HPI_MIXER_CLOSE",          \
-  "HPI_MIXER_GET_INFO",       \
-  "HPI_MIXER_GET_NODE_INFO",  \
-  "HPI_MIXER_GET_CONTROL",    \
-  "HPI_MIXER_SET_CONNECTION", \
-  "HPI_MIXER_GET_CONNECTIONS",        \
-  "HPI_MIXER_GET_CONTROL_BY_INDEX",   \
-  "HPI_MIXER_GET_CONTROL_ARRAY_BY_INDEX",     \
-  "HPI_MIXER_GET_CONTROL_MULTIPLE_VALUES",    \
-  "HPI_MIXER_STORE",  \
-}
-function_count_check(HPI_MIXER, 11);
-
-#define HPI_CONTROL_STRINGS     \
-{                               \
-  "HPI_CONTROL_GET_INFO",     \
-  "HPI_CONTROL_GET_STATE",    \
-  "HPI_CONTROL_SET_STATE"     \
-}
-function_count_check(HPI_CONTROL, 3);
-
-#define HPI_NVMEMORY_STRINGS    \
-{                               \
-  "HPI_NVMEMORY_OPEN",        \
-  "HPI_NVMEMORY_READ_BYTE",   \
-  "HPI_NVMEMORY_WRITE_BYTE"   \
-}
-function_count_check(HPI_NVMEMORY, 3);
-
-#define HPI_DIGITALIO_STRINGS   \
-{                               \
-  "HPI_GPIO_OPEN",            \
-  "HPI_GPIO_READ_BIT",        \
-  "HPI_GPIO_WRITE_BIT",       \
-  "HPI_GPIO_READ_ALL",                \
-  "HPI_GPIO_WRITE_STATUS"\
-}
-function_count_check(HPI_GPIO, 5);
-
-#define HPI_WATCHDOG_STRINGS    \
-{                               \
-  "HPI_WATCHDOG_OPEN",        \
-  "HPI_WATCHDOG_SET_TIME",    \
-  "HPI_WATCHDOG_PING"         \
-}
-
-#define HPI_CLOCK_STRINGS       \
-{                               \
-  "HPI_CLOCK_OPEN",           \
-  "HPI_CLOCK_SET_TIME",       \
-  "HPI_CLOCK_GET_TIME"        \
-}
-
-#define HPI_PROFILE_STRINGS     \
-{                               \
-  "HPI_PROFILE_OPEN_ALL",     \
-  "HPI_PROFILE_START_ALL",    \
-  "HPI_PROFILE_STOP_ALL",     \
-  "HPI_PROFILE_GET",          \
-  "HPI_PROFILE_GET_IDLECOUNT",  \
-  "HPI_PROFILE_GET_NAME",       \
-  "HPI_PROFILE_GET_UTILIZATION" \
-}
-function_count_check(HPI_PROFILE, 7);
-
-#define HPI_ASYNCEVENT_STRINGS  \
-{                               \
-  "HPI_ASYNCEVENT_OPEN",\
-  "HPI_ASYNCEVENT_CLOSE  ",\
-  "HPI_ASYNCEVENT_WAIT",\
-  "HPI_ASYNCEVENT_GETCOUNT",\
-  "HPI_ASYNCEVENT_GET",\
-  "HPI_ASYNCEVENT_SENDEVENTS"\
-}
-function_count_check(HPI_ASYNCEVENT, 6);
-
-#define HPI_CONTROL_TYPE_STRINGS \
-{ \
-	"null control", \
-	"HPI_CONTROL_CONNECTION", \
-	"HPI_CONTROL_VOLUME", \
-	"HPI_CONTROL_METER", \
-	"HPI_CONTROL_MUTE", \
-	"HPI_CONTROL_MULTIPLEXER", \
-	"HPI_CONTROL_AESEBU_TRANSMITTER", \
-	"HPI_CONTROL_AESEBU_RECEIVER", \
-	"HPI_CONTROL_LEVEL", \
-	"HPI_CONTROL_TUNER", \
-	"HPI_CONTROL_ONOFFSWITCH", \
-	"HPI_CONTROL_VOX", \
-	"HPI_CONTROL_AES18_TRANSMITTER", \
-	"HPI_CONTROL_AES18_RECEIVER", \
-	"HPI_CONTROL_AES18_BLOCKGENERATOR", \
-	"HPI_CONTROL_CHANNEL_MODE", \
-	"HPI_CONTROL_BITSTREAM", \
-	"HPI_CONTROL_SAMPLECLOCK", \
-	"HPI_CONTROL_MICROPHONE", \
-	"HPI_CONTROL_PARAMETRIC_EQ", \
-	"HPI_CONTROL_COMPANDER", \
-	"HPI_CONTROL_COBRANET", \
-	"HPI_CONTROL_TONE_DETECT", \
-	"HPI_CONTROL_SILENCE_DETECT", \
-	"HPI_CONTROL_PAD", \
-	"HPI_CONTROL_SRC" ,\
-	"HPI_CONTROL_UNIVERSAL" \
-}
-
-compile_time_assert((HPI_CONTROL_LAST_INDEX + 1 == 27),
-	controltype_strings_match_defs);
-
-#define HPI_SOURCENODE_STRINGS \
-{ \
-	"no source", \
-	"HPI_SOURCENODE_OSTREAM", \
-	"HPI_SOURCENODE_LINEIN", \
-	"HPI_SOURCENODE_AESEBU_IN", \
-	"HPI_SOURCENODE_TUNER", \
-	"HPI_SOURCENODE_RF", \
-	"HPI_SOURCENODE_CLOCK_SOURCE", \
-	"HPI_SOURCENODE_RAW_BITSTREAM", \
-	"HPI_SOURCENODE_MICROPHONE", \
-	"HPI_SOURCENODE_COBRANET", \
-	"HPI_SOURCENODE_ANALOG", \
-	"HPI_SOURCENODE_ADAPTER" \
-}
-
-compile_time_assert((HPI_SOURCENODE_LAST_INDEX - HPI_SOURCENODE_NONE + 1) ==
-	(12), sourcenode_strings_match_defs);
-
-#define HPI_DESTNODE_STRINGS \
-{ \
-	"no destination", \
-	"HPI_DESTNODE_ISTREAM", \
-	"HPI_DESTNODE_LINEOUT", \
-	"HPI_DESTNODE_AESEBU_OUT", \
-	"HPI_DESTNODE_RF", \
-	"HPI_DESTNODE_SPEAKER", \
-	"HPI_DESTNODE_COBRANET", \
-	"HPI_DESTNODE_ANALOG" \
-}
-compile_time_assert((HPI_DESTNODE_LAST_INDEX - HPI_DESTNODE_NONE + 1) == (8),
-	destnode_strings_match_defs);
-
-#define HPI_CONTROL_CHANNEL_MODE_STRINGS \
-{ \
-	"XXX HPI_CHANNEL_MODE_ERROR XXX", \
-	"HPI_CHANNEL_MODE_NORMAL", \
-	"HPI_CHANNEL_MODE_SWAP", \
-	"HPI_CHANNEL_MODE_LEFT_ONLY", \
-	"HPI_CHANNEL_MODE_RIGHT_ONLY" \
-}
-
-#endif				/* _HPIDEBUG_H  */
+#endif				/* _HPIDEBUG_H_  */

+ 20 - 17
sound/pci/asihpi/hpidspcd.c

@@ -71,47 +71,50 @@ short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code,
 	int err;
 	int err;
 
 
 	sprintf(fw_name, "asihpi/dsp%04x.bin", adapter);
 	sprintf(fw_name, "asihpi/dsp%04x.bin", adapter);
-	HPI_DEBUG_LOG(INFO, "requesting firmware for %s\n", fw_name);
 
 
 	err = request_firmware(&ps_firmware, fw_name,
 	err = request_firmware(&ps_firmware, fw_name,
 		&ps_dsp_code->ps_dev->dev);
 		&ps_dsp_code->ps_dev->dev);
+
 	if (err != 0) {
 	if (err != 0) {
-		HPI_DEBUG_LOG(ERROR, "%d, request_firmware failed for  %s\n",
-			err, fw_name);
+		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
+			"%d, request_firmware failed for  %s\n", err,
+			fw_name);
 		goto error1;
 		goto error1;
 	}
 	}
 	if (ps_firmware->size < sizeof(header)) {
 	if (ps_firmware->size < sizeof(header)) {
-		HPI_DEBUG_LOG(ERROR, "header size too small %s\n", fw_name);
+		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
+			"Header size too small %s\n", fw_name);
 		goto error2;
 		goto error2;
 	}
 	}
 	memcpy(&header, ps_firmware->data, sizeof(header));
 	memcpy(&header, ps_firmware->data, sizeof(header));
 	if (header.adapter != adapter) {
 	if (header.adapter != adapter) {
-		HPI_DEBUG_LOG(ERROR, "adapter type incorrect %4x != %4x\n",
-			header.adapter, adapter);
+		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
+			"Adapter type incorrect %4x != %4x\n", header.adapter,
+			adapter);
 		goto error2;
 		goto error2;
 	}
 	}
 	if (header.size != ps_firmware->size) {
 	if (header.size != ps_firmware->size) {
-		HPI_DEBUG_LOG(ERROR, "code size wrong  %d != %ld\n",
-			header.size, (unsigned long)ps_firmware->size);
+		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
+			"Code size wrong  %d != %ld\n", header.size,
+			(unsigned long)ps_firmware->size);
 		goto error2;
 		goto error2;
 	}
 	}
 
 
-	if (header.version / 10000 != HPI_VER_DECIMAL / 10000) {
-		HPI_DEBUG_LOG(ERROR,
-			"firmware major version mismatch "
-			"DSP image %d != driver %d\n", header.version,
+	if (header.version / 100 != HPI_VER_DECIMAL / 100) {
+		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
+			"Incompatible firmware version "
+			"DSP image %d != Driver %d\n", header.version,
 			HPI_VER_DECIMAL);
 			HPI_VER_DECIMAL);
 		goto error2;
 		goto error2;
 	}
 	}
 
 
 	if (header.version != HPI_VER_DECIMAL) {
 	if (header.version != HPI_VER_DECIMAL) {
-		HPI_DEBUG_LOG(WARNING,
-			"version mismatch  DSP image %d != driver %d\n",
+		dev_printk(KERN_WARNING, &ps_dsp_code->ps_dev->dev,
+			"Firmware: release version mismatch  DSP image %d != Driver %d\n",
 			header.version, HPI_VER_DECIMAL);
 			header.version, HPI_VER_DECIMAL);
-		/* goto error2;  still allow driver to load */
 	}
 	}
 
 
-	HPI_DEBUG_LOG(INFO, "dsp code %s opened\n", fw_name);
+	HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name);
 	ps_dsp_code->ps_firmware = ps_firmware;
 	ps_dsp_code->ps_firmware = ps_firmware;
 	ps_dsp_code->block_length = header.size / sizeof(u32);
 	ps_dsp_code->block_length = header.size / sizeof(u32);
 	ps_dsp_code->word_count = sizeof(header) / sizeof(u32);
 	ps_dsp_code->word_count = sizeof(header) / sizeof(u32);
@@ -148,7 +151,7 @@ void hpi_dsp_code_rewind(struct dsp_code *ps_dsp_code)
 short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code, u32 *pword)
 short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code, u32 *pword)
 {
 {
 	if (ps_dsp_code->word_count + 1 > ps_dsp_code->block_length)
 	if (ps_dsp_code->word_count + 1 > ps_dsp_code->block_length)
-		return (HPI_ERROR_DSP_FILE_FORMAT);
+		return HPI_ERROR_DSP_FILE_FORMAT;
 
 
 	*pword = ((u32 *)(ps_dsp_code->ps_firmware->data))[ps_dsp_code->
 	*pword = ((u32 *)(ps_dsp_code->ps_firmware->data))[ps_dsp_code->
 		word_count];
 		word_count];

+ 1 - 1
sound/pci/asihpi/hpidspcd.h

@@ -87,7 +87,7 @@ void hpi_dsp_code_rewind(struct dsp_code *ps_dsp_code);
 */
 */
 short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code,
 short hpi_dsp_code_read_word(struct dsp_code *ps_dsp_code,
 				      /**< DSP code descriptor */
 				      /**< DSP code descriptor */
-	u32 *pword /**< where to store the read word */
+	u32 *pword /**< Where to store the read word */
 	);
 	);
 
 
 /** Get a block of dsp code into an internal buffer, and provide a pointer to
 /** Get a block of dsp code into an internal buffer, and provide a pointer to

Файловите разлики са ограничени, защото са твърде много
+ 150 - 407
sound/pci/asihpi/hpifunc.c


+ 2 - 16
sound/pci/asihpi/hpimsginit.c

@@ -31,21 +31,6 @@ static u16 res_size[HPI_OBJ_MAXINDEX + 1] = HPI_RESPONSE_SIZE_BY_OBJECT;
 /* Flag to enable alternate message type for SSX2 bypass. */
 /* Flag to enable alternate message type for SSX2 bypass. */
 static u16 gwSSX2_bypass;
 static u16 gwSSX2_bypass;
 
 
-/** \internal
-  * Used by ASIO driver to disable SSX2 for a single process
-  * \param phSubSys Pointer to HPI subsystem handle.
-  * \param wBypass New bypass setting 0 = off, nonzero = on
-  * \return Previous bypass setting.
-  */
-u16 hpi_subsys_ssx2_bypass(const struct hpi_hsubsys *ph_subsys, u16 bypass)
-{
-	u16 old_value = gwSSX2_bypass;
-
-	gwSSX2_bypass = bypass;
-
-	return old_value;
-}
-
 /** \internal
 /** \internal
   * initialize the HPI message structure
   * initialize the HPI message structure
   */
   */
@@ -65,7 +50,8 @@ static void hpi_init_message(struct hpi_message *phm, u16 object,
 	phm->object = object;
 	phm->object = object;
 	phm->function = function;
 	phm->function = function;
 	phm->version = 0;
 	phm->version = 0;
-	/* Expect adapter index to be set by caller */
+	phm->adapter_index = HPI_ADAPTER_INDEX_INVALID;
+	/* Expect actual adapter index to be set by caller */
 }
 }
 
 
 /** \internal
 /** \internal

+ 9 - 3
sound/pci/asihpi/hpimsginit.h

@@ -21,11 +21,15 @@
  (C) Copyright AudioScience Inc. 2007
  (C) Copyright AudioScience Inc. 2007
 *******************************************************************************/
 *******************************************************************************/
 /* Initialise response headers, or msg/response pairs.
 /* Initialise response headers, or msg/response pairs.
-Note that it is valid to just init a response e.g. when a lower level is preparing
-a response to a message.
-However, when sending a message, a matching response buffer always must be prepared
+Note that it is valid to just init a response e.g. when a lower level is
+preparing a response to a message.
+However, when sending a message, a matching response buffer must always be
+prepared.
 */
 */
 
 
+#ifndef _HPIMSGINIT_H_
+#define _HPIMSGINIT_H_
+
 void hpi_init_response(struct hpi_response *phr, u16 object, u16 function,
 void hpi_init_response(struct hpi_response *phr, u16 object, u16 function,
 	u16 error);
 	u16 error);
 
 
@@ -38,3 +42,5 @@ void hpi_init_responseV1(struct hpi_response_header *phr, u16 size,
 void hpi_init_message_responseV1(struct hpi_message_header *phm, u16 msg_size,
 void hpi_init_message_responseV1(struct hpi_message_header *phm, u16 msg_size,
 	struct hpi_response_header *phr, u16 res_size, u16 object,
 	struct hpi_response_header *phr, u16 res_size, u16 object,
 	u16 function);
 	u16 function);
+
+#endif				/* _HPIMSGINIT_H_ */

+ 51 - 152
sound/pci/asihpi/hpimsgx.c

@@ -23,6 +23,7 @@ Extended Message Function With Response Cacheing
 #define SOURCEFILE_NAME "hpimsgx.c"
 #define SOURCEFILE_NAME "hpimsgx.c"
 #include "hpi_internal.h"
 #include "hpi_internal.h"
 #include "hpimsginit.h"
 #include "hpimsginit.h"
+#include "hpicmn.h"
 #include "hpimsgx.h"
 #include "hpimsgx.h"
 #include "hpidebug.h"
 #include "hpidebug.h"
 
 
@@ -42,22 +43,24 @@ static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci
 
 
 	for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) {
 	for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) {
 		if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID
 		if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID
-			&& asihpi_pci_tbl[i].vendor != pci_info->vendor_id)
+			&& asihpi_pci_tbl[i].vendor !=
+			pci_info->pci_dev->vendor)
 			continue;
 			continue;
 		if (asihpi_pci_tbl[i].device != PCI_ANY_ID
 		if (asihpi_pci_tbl[i].device != PCI_ANY_ID
-			&& asihpi_pci_tbl[i].device != pci_info->device_id)
+			&& asihpi_pci_tbl[i].device !=
+			pci_info->pci_dev->device)
 			continue;
 			continue;
 		if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID
 		if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID
 			&& asihpi_pci_tbl[i].subvendor !=
 			&& asihpi_pci_tbl[i].subvendor !=
-			pci_info->subsys_vendor_id)
+			pci_info->pci_dev->subsystem_vendor)
 			continue;
 			continue;
 		if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID
 		if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID
 			&& asihpi_pci_tbl[i].subdevice !=
 			&& asihpi_pci_tbl[i].subdevice !=
-			pci_info->subsys_device_id)
+			pci_info->pci_dev->subsystem_device)
 			continue;
 			continue;
 
 
-		HPI_DEBUG_LOG(DEBUG, " %x,%lu\n", i,
-			asihpi_pci_tbl[i].driver_data);
+		/* HPI_DEBUG_LOG(DEBUG, " %x,%lx\n", i,
+		   asihpi_pci_tbl[i].driver_data); */
 		return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data;
 		return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data;
 	}
 	}
 
 
@@ -67,21 +70,12 @@ static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci
 static inline void hw_entry_point(struct hpi_message *phm,
 static inline void hw_entry_point(struct hpi_message *phm,
 	struct hpi_response *phr)
 	struct hpi_response *phr)
 {
 {
-
-	hpi_handler_func *ep;
-
-	if (phm->adapter_index < HPI_MAX_ADAPTERS) {
-		ep = (hpi_handler_func *) hpi_entry_points[phm->
-			adapter_index];
-		if (ep) {
-			HPI_DEBUG_MESSAGE(DEBUG, phm);
-			ep(phm, phr);
-			HPI_DEBUG_RESPONSE(phr);
-			return;
-		}
-	}
-	hpi_init_response(phr, phm->object, phm->function,
-		HPI_ERROR_PROCESSING_MESSAGE);
+	if ((phm->adapter_index < HPI_MAX_ADAPTERS)
+		&& hpi_entry_points[phm->adapter_index])
+		hpi_entry_points[phm->adapter_index] (phm, phr);
+	else
+		hpi_init_response(phr, phm->object, phm->function,
+			HPI_ERROR_PROCESSING_MESSAGE);
 }
 }
 
 
 static void adapter_open(struct hpi_message *phm, struct hpi_response *phr);
 static void adapter_open(struct hpi_message *phm, struct hpi_response *phr);
@@ -100,6 +94,7 @@ static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
 	void *h_owner);
 	void *h_owner);
 
 
 static void HPIMSGX__reset(u16 adapter_index);
 static void HPIMSGX__reset(u16 adapter_index);
+
 static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr);
 static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr);
 static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner);
 static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner);
 
 
@@ -153,8 +148,6 @@ static struct hpi_stream_response
 
 
 static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS];
 static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS];
 
 
-static struct hpi_subsys_response gRESP_HPI_SUBSYS_FIND_ADAPTERS;
-
 static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS];
 static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS];
 
 
 /* use these to keep track of opens from user mode apps/DLLs */
 /* use these to keep track of opens from user mode apps/DLLs */
@@ -167,6 +160,11 @@ static struct asi_open_state
 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
 	void *h_owner)
 	void *h_owner)
 {
 {
+	if (phm->adapter_index != HPI_ADAPTER_INDEX_INVALID)
+		HPI_DEBUG_LOG(WARNING,
+			"suspicious adapter index %d in subsys message 0x%x.\n",
+			phm->adapter_index, phm->function);
+
 	switch (phm->function) {
 	switch (phm->function) {
 	case HPI_SUBSYS_GET_VERSION:
 	case HPI_SUBSYS_GET_VERSION:
 		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
 		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
@@ -204,85 +202,37 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
 			HPI_SUBSYS_DRIVER_UNLOAD, 0);
 			HPI_SUBSYS_DRIVER_UNLOAD, 0);
 		return;
 		return;
 
 
-	case HPI_SUBSYS_GET_INFO:
-		HPI_COMMON(phm, phr);
-		break;
-
-	case HPI_SUBSYS_FIND_ADAPTERS:
-		memcpy(phr, &gRESP_HPI_SUBSYS_FIND_ADAPTERS,
-			sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
-		break;
 	case HPI_SUBSYS_GET_NUM_ADAPTERS:
 	case HPI_SUBSYS_GET_NUM_ADAPTERS:
-		memcpy(phr, &gRESP_HPI_SUBSYS_FIND_ADAPTERS,
-			sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
-		phr->function = HPI_SUBSYS_GET_NUM_ADAPTERS;
-		break;
 	case HPI_SUBSYS_GET_ADAPTER:
 	case HPI_SUBSYS_GET_ADAPTER:
-		{
-			int count = phm->adapter_index;
-			int index = 0;
-			hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
-				HPI_SUBSYS_GET_ADAPTER, 0);
-
-			/* This is complicated by the fact that we want to
-			 * "skip" 0's in the adapter list.
-			 * First, make sure we are pointing to a
-			 * non-zero adapter type.
-			 */
-			while (gRESP_HPI_SUBSYS_FIND_ADAPTERS.
-				s.aw_adapter_list[index] == 0) {
-				index++;
-				if (index >= HPI_MAX_ADAPTERS)
-					break;
-			}
-			while (count) {
-				/* move on to the next adapter */
-				index++;
-				if (index >= HPI_MAX_ADAPTERS)
-					break;
-				while (gRESP_HPI_SUBSYS_FIND_ADAPTERS.
-					s.aw_adapter_list[index] == 0) {
-					index++;
-					if (index >= HPI_MAX_ADAPTERS)
-						break;
-				}
-				count--;
-			}
+		HPI_COMMON(phm, phr);
+		break;
 
 
-			if (index < HPI_MAX_ADAPTERS) {
-				phr->u.s.adapter_index = (u16)index;
-				phr->u.s.aw_adapter_list[0] =
-					gRESP_HPI_SUBSYS_FIND_ADAPTERS.
-					s.aw_adapter_list[index];
-			} else {
-				phr->u.s.adapter_index = 0;
-				phr->u.s.aw_adapter_list[0] = 0;
-				phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER;
-			}
-			break;
-		}
 	case HPI_SUBSYS_CREATE_ADAPTER:
 	case HPI_SUBSYS_CREATE_ADAPTER:
 		HPIMSGX__init(phm, phr);
 		HPIMSGX__init(phm, phr);
 		break;
 		break;
+
 	case HPI_SUBSYS_DELETE_ADAPTER:
 	case HPI_SUBSYS_DELETE_ADAPTER:
-		HPIMSGX__cleanup(phm->adapter_index, h_owner);
+		HPIMSGX__cleanup(phm->obj_index, h_owner);
 		{
 		{
 			struct hpi_message hm;
 			struct hpi_message hm;
 			struct hpi_response hr;
 			struct hpi_response hr;
-			/* call to HPI_ADAPTER_CLOSE */
 			hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
 			hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
 				HPI_ADAPTER_CLOSE);
 				HPI_ADAPTER_CLOSE);
-			hm.adapter_index = phm->adapter_index;
+			hm.adapter_index = phm->obj_index;
 			hw_entry_point(&hm, &hr);
 			hw_entry_point(&hm, &hr);
 		}
 		}
-		hw_entry_point(phm, phr);
-		gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.
-			aw_adapter_list[phm->adapter_index]
-			= 0;
-		hpi_entry_points[phm->adapter_index] = NULL;
+		if ((phm->obj_index < HPI_MAX_ADAPTERS)
+			&& hpi_entry_points[phm->obj_index]) {
+			hpi_entry_points[phm->obj_index] (phm, phr);
+			hpi_entry_points[phm->obj_index] = NULL;
+		} else
+			phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
+
 		break;
 		break;
 	default:
 	default:
-		hw_entry_point(phm, phr);
+		/* Must explicitly handle every subsys message in this switch */
+		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function,
+			HPI_ERROR_INVALID_FUNC);
 		break;
 		break;
 	}
 	}
 }
 }
@@ -409,33 +359,7 @@ void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr,
 		break;
 		break;
 	}
 	}
 	HPI_DEBUG_RESPONSE(phr);
 	HPI_DEBUG_RESPONSE(phr);
-#if 1
-	if (phr->error >= HPI_ERROR_BACKEND_BASE) {
-		void *ep = NULL;
-		char *ep_name;
-
-		HPI_DEBUG_MESSAGE(ERROR, phm);
-
-		if (phm->adapter_index < HPI_MAX_ADAPTERS)
-			ep = hpi_entry_points[phm->adapter_index];
-
-		/* Don't need this? Have adapter index in debug info
-		   Know at driver load time index->backend mapping */
-		if (ep == HPI_6000)
-			ep_name = "HPI_6000";
-		else if (ep == HPI_6205)
-			ep_name = "HPI_6205";
-		else
-			ep_name = "unknown";
-
-		HPI_DEBUG_LOG(ERROR, "HPI %s response - error# %d\n", ep_name,
-			phr->error);
-
-		if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE)
-			hpi_debug_data((u16 *)phm,
-				sizeof(*phm) / sizeof(u16));
-	}
-#endif
+
 }
 }
 
 
 static void adapter_open(struct hpi_message *phm, struct hpi_response *phr)
 static void adapter_open(struct hpi_message *phm, struct hpi_response *phr)
@@ -484,7 +408,7 @@ static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
 	else {
 	else {
 		instream_user_open[phm->adapter_index][phm->
 		instream_user_open[phm->adapter_index][phm->
 			obj_index].open_flag = 1;
 			obj_index].open_flag = 1;
-		hpios_msgxlock_un_lock(&msgx_lock);
+		hpios_msgxlock_unlock(&msgx_lock);
 
 
 		/* issue a reset */
 		/* issue a reset */
 		hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
@@ -509,7 +433,7 @@ static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
 				sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
 				sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
 		}
 		}
 	}
 	}
-	hpios_msgxlock_un_lock(&msgx_lock);
+	hpios_msgxlock_unlock(&msgx_lock);
 }
 }
 
 
 static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
 static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
@@ -530,7 +454,7 @@ static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
 		   phm->wAdapterIndex, phm->wObjIndex, hOwner); */
 		   phm->wAdapterIndex, phm->wObjIndex, hOwner); */
 		instream_user_open[phm->adapter_index][phm->
 		instream_user_open[phm->adapter_index][phm->
 			obj_index].h_owner = NULL;
 			obj_index].h_owner = NULL;
-		hpios_msgxlock_un_lock(&msgx_lock);
+		hpios_msgxlock_unlock(&msgx_lock);
 		/* issue a reset */
 		/* issue a reset */
 		hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 		hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
 			HPI_ISTREAM_RESET);
 			HPI_ISTREAM_RESET);
@@ -556,7 +480,7 @@ static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
 				obj_index].h_owner);
 				obj_index].h_owner);
 		phr->error = HPI_ERROR_OBJ_NOT_OPEN;
 		phr->error = HPI_ERROR_OBJ_NOT_OPEN;
 	}
 	}
-	hpios_msgxlock_un_lock(&msgx_lock);
+	hpios_msgxlock_unlock(&msgx_lock);
 }
 }
 
 
 static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
 static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
@@ -581,7 +505,7 @@ static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
 	else {
 	else {
 		outstream_user_open[phm->adapter_index][phm->
 		outstream_user_open[phm->adapter_index][phm->
 			obj_index].open_flag = 1;
 			obj_index].open_flag = 1;
-		hpios_msgxlock_un_lock(&msgx_lock);
+		hpios_msgxlock_unlock(&msgx_lock);
 
 
 		/* issue a reset */
 		/* issue a reset */
 		hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
@@ -606,7 +530,7 @@ static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
 				sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
 				sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
 		}
 		}
 	}
 	}
-	hpios_msgxlock_un_lock(&msgx_lock);
+	hpios_msgxlock_unlock(&msgx_lock);
 }
 }
 
 
 static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
 static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
@@ -628,7 +552,7 @@ static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
 		   phm->wAdapterIndex, phm->wObjIndex, hOwner); */
 		   phm->wAdapterIndex, phm->wObjIndex, hOwner); */
 		outstream_user_open[phm->adapter_index][phm->
 		outstream_user_open[phm->adapter_index][phm->
 			obj_index].h_owner = NULL;
 			obj_index].h_owner = NULL;
-		hpios_msgxlock_un_lock(&msgx_lock);
+		hpios_msgxlock_unlock(&msgx_lock);
 		/* issue a reset */
 		/* issue a reset */
 		hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 		hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
 			HPI_OSTREAM_RESET);
 			HPI_OSTREAM_RESET);
@@ -654,7 +578,7 @@ static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
 				obj_index].h_owner);
 				obj_index].h_owner);
 		phr->error = HPI_ERROR_OBJ_NOT_OPEN;
 		phr->error = HPI_ERROR_OBJ_NOT_OPEN;
 	}
 	}
-	hpios_msgxlock_un_lock(&msgx_lock);
+	hpios_msgxlock_unlock(&msgx_lock);
 }
 }
 
 
 static u16 adapter_prepare(u16 adapter)
 static u16 adapter_prepare(u16 adapter)
@@ -683,16 +607,9 @@ static u16 adapter_prepare(u16 adapter)
 	if (hr.error)
 	if (hr.error)
 		return hr.error;
 		return hr.error;
 
 
-	aDAPTER_INFO[adapter].num_outstreams = hr.u.a.num_outstreams;
-	aDAPTER_INFO[adapter].num_instreams = hr.u.a.num_instreams;
-	aDAPTER_INFO[adapter].type = hr.u.a.adapter_type;
-
-	gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list[adapter] =
-		hr.u.a.adapter_type;
-	gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters++;
-	if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters > HPI_MAX_ADAPTERS)
-		gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters =
-			HPI_MAX_ADAPTERS;
+	aDAPTER_INFO[adapter].num_outstreams = hr.u.ax.info.num_outstreams;
+	aDAPTER_INFO[adapter].num_instreams = hr.u.ax.info.num_instreams;
+	aDAPTER_INFO[adapter].type = hr.u.ax.info.adapter_type;
 
 
 	/* call to HPI_OSTREAM_OPEN */
 	/* call to HPI_OSTREAM_OPEN */
 	for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) {
 	for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) {
@@ -727,7 +644,7 @@ static u16 adapter_prepare(u16 adapter)
 	memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
 	memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
 		sizeof(rESP_HPI_MIXER_OPEN[0]));
 		sizeof(rESP_HPI_MIXER_OPEN[0]));
 
 
-	return gRESP_HPI_SUBSYS_FIND_ADAPTERS.h.error;
+	return 0;
 }
 }
 
 
 static void HPIMSGX__reset(u16 adapter_index)
 static void HPIMSGX__reset(u16 adapter_index)
@@ -737,12 +654,6 @@ static void HPIMSGX__reset(u16 adapter_index)
 	struct hpi_response hr;
 	struct hpi_response hr;
 
 
 	if (adapter_index == HPIMSGX_ALLADAPTERS) {
 	if (adapter_index == HPIMSGX_ALLADAPTERS) {
-		/* reset all responses to contain errors */
-		hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM,
-			HPI_SUBSYS_FIND_ADAPTERS, 0);
-		memcpy(&gRESP_HPI_SUBSYS_FIND_ADAPTERS, &hr,
-			sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
-
 		for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) {
 		for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) {
 
 
 			hpi_init_response(&hr, HPI_OBJ_ADAPTER,
 			hpi_init_response(&hr, HPI_OBJ_ADAPTER,
@@ -783,12 +694,6 @@ static void HPIMSGX__reset(u16 adapter_index)
 			rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error =
 			rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error =
 				HPI_ERROR_INVALID_OBJ;
 				HPI_ERROR_INVALID_OBJ;
 		}
 		}
-		if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.
-			s.aw_adapter_list[adapter_index]) {
-			gRESP_HPI_SUBSYS_FIND_ADAPTERS.
-				s.aw_adapter_list[adapter_index] = 0;
-			gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters--;
-		}
 	}
 	}
 }
 }
 
 
@@ -802,15 +707,9 @@ static u16 HPIMSGX__init(struct hpi_message *phm,
 	hpi_handler_func *entry_point_func;
 	hpi_handler_func *entry_point_func;
 	struct hpi_response hr;
 	struct hpi_response hr;
 
 
-	if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters >= HPI_MAX_ADAPTERS)
-		return HPI_ERROR_BAD_ADAPTER_NUMBER;
-
 	/* Init response here so we can pass in previous adapter list */
 	/* Init response here so we can pass in previous adapter list */
 	hpi_init_response(&hr, phm->object, phm->function,
 	hpi_init_response(&hr, phm->object, phm->function,
 		HPI_ERROR_INVALID_OBJ);
 		HPI_ERROR_INVALID_OBJ);
-	memcpy(hr.u.s.aw_adapter_list,
-		gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list,
-		sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list));
 
 
 	entry_point_func =
 	entry_point_func =
 		hpi_lookup_entry_point_function(phm->u.s.resource.r.pci);
 		hpi_lookup_entry_point_function(phm->u.s.resource.r.pci);
@@ -860,7 +759,7 @@ static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner)
 				struct hpi_response hr;
 				struct hpi_response hr;
 
 
 				HPI_DEBUG_LOG(DEBUG,
 				HPI_DEBUG_LOG(DEBUG,
-					"close adapter %d ostream %d\n",
+					"Close adapter %d ostream %d\n",
 					adapter, i);
 					adapter, i);
 
 
 				hpi_init_message_response(&hm, &hr,
 				hpi_init_message_response(&hm, &hr,
@@ -884,7 +783,7 @@ static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner)
 				struct hpi_response hr;
 				struct hpi_response hr;
 
 
 				HPI_DEBUG_LOG(DEBUG,
 				HPI_DEBUG_LOG(DEBUG,
-					"close adapter %d istream %d\n",
+					"Close adapter %d istream %d\n",
 					adapter, i);
 					adapter, i);
 
 
 				hpi_init_message_response(&hm, &hr,
 				hpi_init_message_response(&hm, &hr,

+ 46 - 44
sound/pci/asihpi/hpioctl.c

@@ -30,6 +30,7 @@ Common Linux HPI ioctl and module probe/remove functions
 #include <linux/slab.h>
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
 #include <linux/moduleparam.h>
 #include <asm/uaccess.h>
 #include <asm/uaccess.h>
+#include <linux/pci.h>
 #include <linux/stringify.h>
 #include <linux/stringify.h>
 
 
 #ifdef MODULE_FIRMWARE
 #ifdef MODULE_FIRMWARE
@@ -45,7 +46,7 @@ MODULE_FIRMWARE("asihpi/dsp8900.bin");
 static int prealloc_stream_buf;
 static int prealloc_stream_buf;
 module_param(prealloc_stream_buf, int, S_IRUGO);
 module_param(prealloc_stream_buf, int, S_IRUGO);
 MODULE_PARM_DESC(prealloc_stream_buf,
 MODULE_PARM_DESC(prealloc_stream_buf,
-	"preallocate size for per-adapter stream buffer");
+	"Preallocate size for per-adapter stream buffer");
 
 
 /* Allow the debug level to be changed after module load.
 /* Allow the debug level to be changed after module load.
  E.g.   echo 2 > /sys/module/asihpi/parameters/hpiDebugLevel
  E.g.   echo 2 > /sys/module/asihpi/parameters/hpiDebugLevel
@@ -121,8 +122,8 @@ 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.  */
-	if (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;
 		err = -EFAULT;
 		goto out;
 		goto out;
 	}
 	}
@@ -135,7 +136,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	if (hm->h.size > sizeof(*hm))
 	if (hm->h.size > sizeof(*hm))
 		hm->h.size = sizeof(*hm);
 		hm->h.size = sizeof(*hm);
 
 
-	/*printk(KERN_INFO "message size %d\n", hm->h.wSize); */
+	/* printk(KERN_INFO "message size %d\n", hm->h.wSize); */
 
 
 	uncopied_bytes = copy_from_user(hm, puhm, hm->h.size);
 	uncopied_bytes = copy_from_user(hm, puhm, hm->h.size);
 	if (uncopied_bytes) {
 	if (uncopied_bytes) {
@@ -155,8 +156,13 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 		goto out;
 		goto out;
 	}
 	}
 
 
+	if (hm->h.adapter_index >= HPI_MAX_ADAPTERS) {
+		err = -EINVAL;
+		goto out;
+	}
+
 	pa = &adapters[hm->h.adapter_index];
 	pa = &adapters[hm->h.adapter_index];
-	hr->h.size = 0;
+	hr->h.size = res_max_size;
 	if (hm->h.object == HPI_OBJ_SUBSYSTEM) {
 	if (hm->h.object == HPI_OBJ_SUBSYSTEM) {
 		switch (hm->h.function) {
 		switch (hm->h.function) {
 		case HPI_SUBSYS_CREATE_ADAPTER:
 		case HPI_SUBSYS_CREATE_ADAPTER:
@@ -216,7 +222,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 				 */
 				 */
 				if (pa->buffer_size < size) {
 				if (pa->buffer_size < size) {
 					HPI_DEBUG_LOG(DEBUG,
 					HPI_DEBUG_LOG(DEBUG,
-						"realloc adapter %d stream "
+						"Realloc adapter %d stream "
 						"buffer from %zd to %d\n",
 						"buffer from %zd to %d\n",
 						hm->h.adapter_index,
 						hm->h.adapter_index,
 						pa->buffer_size, size);
 						pa->buffer_size, size);
@@ -259,7 +265,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 				copy_from_user(pa->p_buffer, ptr, size);
 				copy_from_user(pa->p_buffer, ptr, size);
 			if (uncopied_bytes)
 			if (uncopied_bytes)
 				HPI_DEBUG_LOG(WARNING,
 				HPI_DEBUG_LOG(WARNING,
-					"missed %d of %d "
+					"Missed %d of %d "
 					"bytes from user\n", uncopied_bytes,
 					"bytes from user\n", uncopied_bytes,
 					size);
 					size);
 		}
 		}
@@ -271,7 +277,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 				copy_to_user(ptr, pa->p_buffer, size);
 				copy_to_user(ptr, pa->p_buffer, size);
 			if (uncopied_bytes)
 			if (uncopied_bytes)
 				HPI_DEBUG_LOG(WARNING,
 				HPI_DEBUG_LOG(WARNING,
-					"missed %d of %d " "bytes to user\n",
+					"Missed %d of %d " "bytes to user\n",
 					uncopied_bytes, size);
 					uncopied_bytes, size);
 		}
 		}
 
 
@@ -290,9 +296,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	if (hr->h.size > res_max_size) {
 	if (hr->h.size > res_max_size) {
 		HPI_DEBUG_LOG(ERROR, "response too big %d %d\n", hr->h.size,
 		HPI_DEBUG_LOG(ERROR, "response too big %d %d\n", hr->h.size,
 			res_max_size);
 			res_max_size);
-		/*HPI_DEBUG_MESSAGE(ERROR, hm); */
-		err = -EFAULT;
-		goto out;
+		hr->h.error = HPI_ERROR_RESPONSE_BUFFER_TOO_SMALL;
+		hr->h.specific_error = hr->h.size;
+		hr->h.size = sizeof(hr->h);
 	}
 	}
 
 
 	uncopied_bytes = copy_to_user(puhr, hr, hr->h.size);
 	uncopied_bytes = copy_to_user(puhr, hr, hr->h.size);
@@ -320,18 +326,26 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
 
 
 	memset(&adapter, 0, sizeof(adapter));
 	memset(&adapter, 0, sizeof(adapter));
 
 
-	printk(KERN_DEBUG "probe PCI device (%04x:%04x,%04x:%04x,%04x)\n",
-		pci_dev->vendor, pci_dev->device, pci_dev->subsystem_vendor,
+	dev_printk(KERN_DEBUG, &pci_dev->dev,
+		"probe %04x:%04x,%04x:%04x,%04x\n", pci_dev->vendor,
+		pci_dev->device, pci_dev->subsystem_vendor,
 		pci_dev->subsystem_device, pci_dev->devfn);
 		pci_dev->subsystem_device, pci_dev->devfn);
 
 
+	if (pci_enable_device(pci_dev) < 0) {
+		dev_printk(KERN_ERR, &pci_dev->dev,
+			"pci_enable_device failed, disabling device\n");
+		return -EIO;
+	}
+
+	pci_set_master(pci_dev);	/* also sets latency timer if < 16 */
+
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
 		HPI_SUBSYS_CREATE_ADAPTER);
 		HPI_SUBSYS_CREATE_ADAPTER);
 	hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER,
 	hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER,
 		HPI_ERROR_PROCESSING_MESSAGE);
 		HPI_ERROR_PROCESSING_MESSAGE);
 
 
-	hm.adapter_index = -1;	/* an invalid index */
+	hm.adapter_index = HPI_ADAPTER_INDEX_INVALID;
 
 
-	/* fill in HPI_PCI information from kernel provided information */
 	adapter.pci = pci_dev;
 	adapter.pci = pci_dev;
 
 
 	nm = HPI_MAX_ADAPTER_MEM_SPACES;
 	nm = HPI_MAX_ADAPTER_MEM_SPACES;
@@ -359,19 +373,7 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
 		pci.ap_mem_base[idx] = adapter.ap_remapped_mem_base[idx];
 		pci.ap_mem_base[idx] = adapter.ap_remapped_mem_base[idx];
 	}
 	}
 
 
-	/* could replace Pci with direct pointer to pci_dev for linux
-	   Instead wrap accessor functions for IDs etc.
-	   Would it work for windows?
-	 */
-	pci.bus_number = pci_dev->bus->number;
-	pci.vendor_id = (u16)pci_dev->vendor;
-	pci.device_id = (u16)pci_dev->device;
-	pci.subsys_vendor_id = (u16)(pci_dev->subsystem_vendor & 0xffff);
-	pci.subsys_device_id = (u16)(pci_dev->subsystem_device & 0xffff);
-	pci.device_number = pci_dev->devfn;
-	pci.interrupt = pci_dev->irq;
-	pci.p_os_data = pci_dev;
-
+	pci.pci_dev = pci_dev;
 	hm.u.s.resource.bus_type = HPI_BUS_PCI;
 	hm.u.s.resource.bus_type = HPI_BUS_PCI;
 	hm.u.s.resource.r.pci = &pci;
 	hm.u.s.resource.r.pci = &pci;
 
 
@@ -392,10 +394,10 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
 	}
 	}
 
 
 	adapter.index = hr.u.s.adapter_index;
 	adapter.index = hr.u.s.adapter_index;
-	adapter.type = hr.u.s.aw_adapter_list[adapter.index];
+	adapter.type = hr.u.s.adapter_type;
 	hm.adapter_index = adapter.index;
 	hm.adapter_index = adapter.index;
 
 
-	err = hpi_adapter_open(NULL, adapter.index);
+	err = hpi_adapter_open(adapter.index);
 	if (err)
 	if (err)
 		goto err;
 		goto err;
 
 
@@ -407,8 +409,9 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
 	mutex_init(&adapters[adapter.index].mutex);
 	mutex_init(&adapters[adapter.index].mutex);
 	pci_set_drvdata(pci_dev, &adapters[adapter.index]);
 	pci_set_drvdata(pci_dev, &adapters[adapter.index]);
 
 
-	printk(KERN_INFO "probe found adapter ASI%04X HPI index #%d.\n",
-		adapter.type, adapter.index);
+	dev_printk(KERN_INFO, &pci_dev->dev,
+		"probe succeeded for ASI%04X HPI index %d\n", adapter.type,
+		adapter.index);
 
 
 	return 0;
 	return 0;
 
 
@@ -439,7 +442,8 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
 
 
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
 	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
 		HPI_SUBSYS_DELETE_ADAPTER);
 		HPI_SUBSYS_DELETE_ADAPTER);
-	hm.adapter_index = pa->index;
+	hm.obj_index = pa->index;
+	hm.adapter_index = HPI_ADAPTER_INDEX_INVALID;
 	hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
 	hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
 
 
 	/* unmap PCI memory space, mapped during device init. */
 	/* unmap PCI memory space, mapped during device init. */
@@ -450,20 +454,18 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
 		}
 		}
 	}
 	}
 
 
-	if (pa->p_buffer) {
-		pa->buffer_size = 0;
+	if (pa->p_buffer)
 		vfree(pa->p_buffer);
 		vfree(pa->p_buffer);
-	}
 
 
 	pci_set_drvdata(pci_dev, NULL);
 	pci_set_drvdata(pci_dev, NULL);
-	/*
-	   printk(KERN_INFO "PCI device (%04x:%04x,%04x:%04x,%04x),"
-	   " HPI index # %d, removed.\n",
-	   pci_dev->vendor, pci_dev->device,
-	   pci_dev->subsystem_vendor,
-	   pci_dev->subsystem_device, pci_dev->devfn,
-	   pa->index);
-	 */
+	if (1)
+		dev_printk(KERN_INFO, &pci_dev->dev,
+			"remove %04x:%04x,%04x:%04x,%04x," " HPI index %d.\n",
+			pci_dev->vendor, pci_dev->device,
+			pci_dev->subsystem_vendor, pci_dev->subsystem_device,
+			pci_dev->devfn, pa->index);
+
+	memset(pa, 0, sizeof(*pa));
 }
 }
 
 
 void __init asihpi_init(void)
 void __init asihpi_init(void)

+ 4 - 6
sound/pci/asihpi/hpios.h

@@ -27,9 +27,7 @@ HPI Operating System Specific macros for Linux Kernel driver
 #define HPI_OS_LINUX_KERNEL
 #define HPI_OS_LINUX_KERNEL
 
 
 #define HPI_OS_DEFINED
 #define HPI_OS_DEFINED
-#define HPI_KERNEL_MODE
-
-#define HPI_REASSIGN_DUPLICATE_ADAPTER_IDX
+#define HPI_BUILD_KERNEL_MODE
 
 
 #include <linux/io.h>
 #include <linux/io.h>
 #include <asm/system.h>
 #include <asm/system.h>
@@ -135,20 +133,20 @@ static inline void cond_unlock(struct hpios_spinlock *l)
 
 
 #define hpios_msgxlock_init(obj)      spin_lock_init(&(obj)->lock)
 #define hpios_msgxlock_init(obj)      spin_lock_init(&(obj)->lock)
 #define hpios_msgxlock_lock(obj)   cond_lock(obj)
 #define hpios_msgxlock_lock(obj)   cond_lock(obj)
-#define hpios_msgxlock_un_lock(obj) cond_unlock(obj)
+#define hpios_msgxlock_unlock(obj) cond_unlock(obj)
 
 
 #define hpios_dsplock_init(obj)       spin_lock_init(&(obj)->dsp_lock.lock)
 #define hpios_dsplock_init(obj)       spin_lock_init(&(obj)->dsp_lock.lock)
 #define hpios_dsplock_lock(obj)    cond_lock(&(obj)->dsp_lock)
 #define hpios_dsplock_lock(obj)    cond_lock(&(obj)->dsp_lock)
 #define hpios_dsplock_unlock(obj)  cond_unlock(&(obj)->dsp_lock)
 #define hpios_dsplock_unlock(obj)  cond_unlock(&(obj)->dsp_lock)
 
 
 #ifdef CONFIG_SND_DEBUG
 #ifdef CONFIG_SND_DEBUG
-#define HPI_DEBUG
+#define HPI_BUILD_DEBUG
 #endif
 #endif
 
 
 #define HPI_ALIST_LOCKING
 #define HPI_ALIST_LOCKING
 #define hpios_alistlock_init(obj)    spin_lock_init(&((obj)->list_lock.lock))
 #define hpios_alistlock_init(obj)    spin_lock_init(&((obj)->list_lock.lock))
 #define hpios_alistlock_lock(obj) spin_lock(&((obj)->list_lock.lock))
 #define hpios_alistlock_lock(obj) spin_lock(&((obj)->list_lock.lock))
-#define hpios_alistlock_un_lock(obj) spin_unlock(&((obj)->list_lock.lock))
+#define hpios_alistlock_unlock(obj) spin_unlock(&((obj)->list_lock.lock))
 
 
 struct hpi_adapter {
 struct hpi_adapter {
 	/* mutex prevents contention for one card
 	/* mutex prevents contention for one card

+ 1 - 1
sound/pci/atiixp.c

@@ -522,7 +522,7 @@ static int snd_atiixp_aclink_reset(struct atiixp *chip)
 		atiixp_read(chip, CMD);
 		atiixp_read(chip, CMD);
 		mdelay(1);
 		mdelay(1);
 		atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET);
 		atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET);
-		if (--timeout) {
+		if (!--timeout) {
 			snd_printk(KERN_ERR "atiixp: codec reset timeout\n");
 			snd_printk(KERN_ERR "atiixp: codec reset timeout\n");
 			break;
 			break;
 		}
 		}

+ 1 - 1
sound/pci/atiixp_modem.c

@@ -498,7 +498,7 @@ static int snd_atiixp_aclink_reset(struct atiixp_modem *chip)
 		atiixp_read(chip, CMD);
 		atiixp_read(chip, CMD);
 		msleep(1);
 		msleep(1);
 		atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET);
 		atiixp_update(chip, CMD, ATI_REG_CMD_AC_RESET, ATI_REG_CMD_AC_RESET);
-		if (--timeout) {
+		if (!--timeout) {
 			snd_printk(KERN_ERR "atiixp-modem: codec reset timeout\n");
 			snd_printk(KERN_ERR "atiixp-modem: codec reset timeout\n");
 			break;
 			break;
 		}
 		}

+ 2 - 1
sound/pci/au88x0/au88x0_eq.c

@@ -896,7 +896,8 @@ static int __devinit vortex_eq_init(vortex_t * vortex)
 		if ((kcontrol =
 		if ((kcontrol =
 		     snd_ctl_new1(&vortex_eq_kcontrol, vortex)) == NULL)
 		     snd_ctl_new1(&vortex_eq_kcontrol, vortex)) == NULL)
 			return -ENOMEM;
 			return -ENOMEM;
-		strcpy(kcontrol->id.name, EqBandLabels[i]);
+		snprintf(kcontrol->id.name, sizeof(kcontrol->id.name),
+			"%s Playback Volume", EqBandLabels[i]);
 		kcontrol->private_value = i;
 		kcontrol->private_value = i;
 		if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
 		if ((err = snd_ctl_add(vortex->card, kcontrol)) < 0)
 			return err;
 			return err;

+ 402 - 48
sound/pci/azt3328.c

@@ -1,6 +1,5 @@
-/*
- *  azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168).
- *  Copyright (C) 2002, 2005 - 2010 by Andreas Mohr <andi AT lisas.de>
+/*  azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168).
+ *  Copyright (C) 2002, 2005 - 2011 by Andreas Mohr <andi AT lisas.de>
  *
  *
  *  Framework borrowed from Bart Hartgers's als4000.c.
  *  Framework borrowed from Bart Hartgers's als4000.c.
  *  Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801),
  *  Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801),
@@ -66,6 +65,13 @@
  *    addresses illegally. So far unfortunately it looks like the very flexible
  *    addresses illegally. So far unfortunately it looks like the very flexible
  *    ALSA AC97 support is still not enough to easily compensate for such a
  *    ALSA AC97 support is still not enough to easily compensate for such a
  *    grave layout violation despite all tweaks and quirks mechanisms it offers.
  *    grave layout violation despite all tweaks and quirks mechanisms it offers.
+ *    Well, not quite: now ac97 layer is much improved (bus-specific ops!),
+ *    thus I was able to implement support - it's actually working quite well.
+ *    An interesting item might be Aztech AMR 2800-W, since it's an AC97
+ *    modem card which might reveal the Aztech-specific codec ID which
+ *    we might want to pretend, too. Dito PCI168's brother, PCI368,
+ *    where the advertising datasheet says it's AC97-based and has a
+ *    Digital Enhanced Game Port.
  *  - builtin genuine OPL3 - verified to work fine, 20080506
  *  - builtin genuine OPL3 - verified to work fine, 20080506
  *  - full duplex 16bit playback/record at independent sampling rate
  *  - full duplex 16bit playback/record at independent sampling rate
  *  - MPU401 (+ legacy address support, claimed by one official spec sheet)
  *  - MPU401 (+ legacy address support, claimed by one official spec sheet)
@@ -189,6 +195,16 @@
 #include <sound/mpu401.h>
 #include <sound/mpu401.h>
 #include <sound/opl3.h>
 #include <sound/opl3.h>
 #include <sound/initval.h>
 #include <sound/initval.h>
+/*
+ * Config switch, to use ALSA's AC97 layer instead of old custom mixer crap.
+ * If the AC97 compatibility parts we needed to implement locally turn out
+ * to work nicely, then remove the old implementation eventually.
+ */
+#define AZF_USE_AC97_LAYER 1
+
+#ifdef AZF_USE_AC97_LAYER
+#include <sound/ac97_codec.h>
+#endif
 #include "azt3328.h"
 #include "azt3328.h"
 
 
 MODULE_AUTHOR("Andreas Mohr <andi AT lisas.de>");
 MODULE_AUTHOR("Andreas Mohr <andi AT lisas.de>");
@@ -328,6 +344,10 @@ struct snd_azf3328 {
 	/* playback, recording and I2S out codecs */
 	/* playback, recording and I2S out codecs */
 	struct snd_azf3328_codec_data codecs[3];
 	struct snd_azf3328_codec_data codecs[3];
 
 
+#ifdef AZF_USE_AC97_LAYER
+	struct snd_ac97 *ac97;
+#endif
+
 	struct snd_card *card;
 	struct snd_card *card;
 	struct snd_rawmidi *rmidi;
 	struct snd_rawmidi *rmidi;
 
 
@@ -506,7 +526,7 @@ snd_azf3328_mixer_inw(const struct snd_azf3328 *chip, unsigned reg)
 #define AZF_MUTE_BIT 0x80
 #define AZF_MUTE_BIT 0x80
 
 
 static bool
 static bool
-snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip,
+snd_azf3328_mixer_mute_control(const struct snd_azf3328 *chip,
 			   unsigned reg, bool do_mute
 			   unsigned reg, bool do_mute
 )
 )
 {
 {
@@ -521,6 +541,323 @@ snd_azf3328_mixer_set_mute(const struct snd_azf3328 *chip,
 	return (do_mute) ? !updated : updated;
 	return (do_mute) ? !updated : updated;
 }
 }
 
 
+static inline bool
+snd_azf3328_mixer_mute_control_master(const struct snd_azf3328 *chip,
+			   bool do_mute
+)
+{
+	return snd_azf3328_mixer_mute_control(
+		chip,
+		IDX_MIXER_PLAY_MASTER,
+		do_mute
+	);
+}
+
+static inline bool
+snd_azf3328_mixer_mute_control_pcm(const struct snd_azf3328 *chip,
+			   bool do_mute
+)
+{
+	return snd_azf3328_mixer_mute_control(
+		chip,
+		IDX_MIXER_WAVEOUT,
+		do_mute
+	);
+}
+
+static inline void
+snd_azf3328_mixer_reset(const struct snd_azf3328 *chip)
+{
+	/* reset (close) mixer:
+	 * first mute master volume, then reset
+	 */
+	snd_azf3328_mixer_mute_control_master(chip, 1);
+	snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000);
+}
+
+#ifdef AZF_USE_AC97_LAYER
+
+static inline void
+snd_azf3328_mixer_ac97_map_unsupported(unsigned short reg, const char *mode)
+{
+	/* need to add some more or less clever emulation? */
+	printk(KERN_WARNING
+		"azt3328: missing %s emulation for AC97 register 0x%02x!\n",
+		mode, reg);
+}
+
+/*
+ * Need to have _special_ AC97 mixer hardware register index mapper,
+ * to compensate for the issue of a rather AC97-incompatible hardware layout.
+ */
+#define AZF_REG_MASK 0x3f
+#define AZF_AC97_REG_UNSUPPORTED 0x8000
+#define AZF_AC97_REG_REAL_IO_READ 0x4000
+#define AZF_AC97_REG_REAL_IO_WRITE 0x2000
+#define AZF_AC97_REG_REAL_IO_RW \
+	(AZF_AC97_REG_REAL_IO_READ | AZF_AC97_REG_REAL_IO_WRITE)
+#define AZF_AC97_REG_EMU_IO_READ 0x0400
+#define AZF_AC97_REG_EMU_IO_WRITE 0x0200
+#define AZF_AC97_REG_EMU_IO_RW \
+	(AZF_AC97_REG_EMU_IO_READ | AZF_AC97_REG_EMU_IO_WRITE)
+static unsigned short
+snd_azf3328_mixer_ac97_map_reg_idx(unsigned short reg)
+{
+	static const struct {
+		unsigned short azf_reg;
+	} azf_reg_mapper[] = {
+		/* Especially when taking into consideration
+		 * mono/stereo-based sequence of azf vs. AC97 control series,
+		 * it's quite obvious that azf simply got rid
+		 * of the AC97_HEADPHONE control at its intended offset,
+		 * thus shifted _all_ controls by one,
+		 * and _then_ simply added it as an FMSYNTH control at the end,
+		 * to make up for the offset.
+		 * This means we'll have to translate indices here as
+		 * needed and then do some tiny AC97 patch action
+		 * (snd_ac97_rename_vol_ctl() etc.) - that's it.
+		 */
+		{ /* AC97_RESET */ IDX_MIXER_RESET
+			| AZF_AC97_REG_REAL_IO_WRITE
+			| AZF_AC97_REG_EMU_IO_READ },
+		{ /* AC97_MASTER */ IDX_MIXER_PLAY_MASTER },
+		 /* note large shift: AC97_HEADPHONE to IDX_MIXER_FMSYNTH! */
+		{ /* AC97_HEADPHONE */ IDX_MIXER_FMSYNTH },
+		{ /* AC97_MASTER_MONO */ IDX_MIXER_MODEMOUT },
+		{ /* AC97_MASTER_TONE */ IDX_MIXER_BASSTREBLE },
+		{ /* AC97_PC_BEEP */ IDX_MIXER_PCBEEP },
+		{ /* AC97_PHONE */ IDX_MIXER_MODEMIN },
+		{ /* AC97_MIC */ IDX_MIXER_MIC },
+		{ /* AC97_LINE */ IDX_MIXER_LINEIN },
+		{ /* AC97_CD */ IDX_MIXER_CDAUDIO },
+		{ /* AC97_VIDEO */ IDX_MIXER_VIDEO },
+		{ /* AC97_AUX */ IDX_MIXER_AUX },
+		{ /* AC97_PCM */ IDX_MIXER_WAVEOUT },
+		{ /* AC97_REC_SEL */ IDX_MIXER_REC_SELECT },
+		{ /* AC97_REC_GAIN */ IDX_MIXER_REC_VOLUME },
+		{ /* AC97_REC_GAIN_MIC */ AZF_AC97_REG_EMU_IO_RW },
+		{ /* AC97_GENERAL_PURPOSE */ IDX_MIXER_ADVCTL2 },
+		{ /* AC97_3D_CONTROL */ IDX_MIXER_ADVCTL1 },
+	};
+
+	unsigned short reg_azf = AZF_AC97_REG_UNSUPPORTED;
+
+	/* azf3328 supports the low-numbered and low-spec:ed range
+	   of AC97 regs only */
+	if (reg <= AC97_3D_CONTROL) {
+		unsigned short reg_idx = reg / 2;
+		reg_azf = azf_reg_mapper[reg_idx].azf_reg;
+		/* a translation-only entry means it's real read/write: */
+		if (!(reg_azf & ~AZF_REG_MASK))
+			reg_azf |= AZF_AC97_REG_REAL_IO_RW;
+	} else {
+		switch (reg) {
+		case AC97_POWERDOWN:
+			reg_azf = AZF_AC97_REG_EMU_IO_RW;
+			break;
+		case AC97_EXTENDED_ID:
+			reg_azf = AZF_AC97_REG_EMU_IO_READ;
+			break;
+		case AC97_EXTENDED_STATUS:
+			/* I don't know what the h*ll AC97 layer
+			 * would consult this _extended_ register for
+			 * given a base-AC97-advertised card,
+			 * but let's just emulate it anyway :-P
+			 */
+			reg_azf = AZF_AC97_REG_EMU_IO_RW;
+			break;
+		case AC97_VENDOR_ID1:
+		case AC97_VENDOR_ID2:
+			reg_azf = AZF_AC97_REG_EMU_IO_READ;
+			break;
+		}
+	}
+	return reg_azf;
+}
+
+static const unsigned short
+azf_emulated_ac97_caps =
+	AC97_BC_DEDICATED_MIC |
+	AC97_BC_BASS_TREBLE |
+	/* Headphone is an FM Synth control here */
+	AC97_BC_HEADPHONE |
+	/* no AC97_BC_LOUDNESS! */
+	/* mask 0x7c00 is
+	   vendor-specific 3D enhancement
+	   vendor indicator.
+	   Since there actually _is_ an
+	   entry for Aztech Labs
+	   (13), make damn sure
+	   to indicate it. */
+	(13 << 10);
+
+static const unsigned short
+azf_emulated_ac97_powerdown =
+	/* pretend everything to be active */
+		AC97_PD_ADC_STATUS |
+		AC97_PD_DAC_STATUS |
+		AC97_PD_MIXER_STATUS |
+		AC97_PD_VREF_STATUS;
+
+/*
+ * Emulated, _inofficial_ vendor ID
+ * (there might be some devices such as the MR 2800-W
+ * which could reveal the real Aztech AC97 ID).
+ * We choose to use "AZT" prefix, and then use 1 to indicate PCI168
+ * (better don't use 0x68 since there's a PCI368 as well).
+ */
+static const unsigned int
+azf_emulated_ac97_vendor_id = 0x415a5401;
+
+static unsigned short
+snd_azf3328_mixer_ac97_read(struct snd_ac97 *ac97, unsigned short reg_ac97)
+{
+	const struct snd_azf3328 *chip = ac97->private_data;
+	unsigned short reg_azf = snd_azf3328_mixer_ac97_map_reg_idx(reg_ac97);
+	unsigned short reg_val = 0;
+	bool unsupported = 0;
+
+	snd_azf3328_dbgmixer(
+		"snd_azf3328_mixer_ac97_read reg_ac97 %u\n",
+			reg_ac97
+	);
+	if (reg_azf & AZF_AC97_REG_UNSUPPORTED)
+		unsupported = 1;
+	else {
+		if (reg_azf & AZF_AC97_REG_REAL_IO_READ)
+			reg_val = snd_azf3328_mixer_inw(chip,
+						reg_azf & AZF_REG_MASK);
+		else {
+			/*
+			 * Proceed with dummy I/O read,
+			 * to ensure compatible timing where this may matter.
+			 * (ALSA AC97 layer usually doesn't call I/O functions
+			 * due to intelligent I/O caching anyway)
+			 * Choose a mixer register that's thoroughly unrelated
+			 * to common audio (try to minimize distortion).
+			 */
+			snd_azf3328_mixer_inw(chip, IDX_MIXER_SOMETHING30H);
+		}
+
+		if (reg_azf & AZF_AC97_REG_EMU_IO_READ) {
+			switch (reg_ac97) {
+			case AC97_RESET:
+				reg_val |= azf_emulated_ac97_caps;
+				break;
+			case AC97_POWERDOWN:
+				reg_val |= azf_emulated_ac97_powerdown;
+				break;
+			case AC97_EXTENDED_ID:
+			case AC97_EXTENDED_STATUS:
+				/* AFAICS we simply can't support anything: */
+				reg_val |= 0;
+				break;
+			case AC97_VENDOR_ID1:
+				reg_val = azf_emulated_ac97_vendor_id >> 16;
+				break;
+			case AC97_VENDOR_ID2:
+				reg_val = azf_emulated_ac97_vendor_id & 0xffff;
+				break;
+			default:
+				unsupported = 1;
+				break;
+			}
+		}
+	}
+	if (unsupported)
+		snd_azf3328_mixer_ac97_map_unsupported(reg_ac97, "read");
+
+	return reg_val;
+}
+
+static void
+snd_azf3328_mixer_ac97_write(struct snd_ac97 *ac97,
+		     unsigned short reg_ac97, unsigned short val)
+{
+	const struct snd_azf3328 *chip = ac97->private_data;
+	unsigned short reg_azf = snd_azf3328_mixer_ac97_map_reg_idx(reg_ac97);
+	bool unsupported = 0;
+
+	snd_azf3328_dbgmixer(
+		"snd_azf3328_mixer_ac97_write reg_ac97 %u val %u\n",
+			reg_ac97, val
+	);
+	if (reg_azf & AZF_AC97_REG_UNSUPPORTED)
+		unsupported = 1;
+	else {
+		if (reg_azf & AZF_AC97_REG_REAL_IO_WRITE)
+			snd_azf3328_mixer_outw(
+				chip,
+				reg_azf & AZF_REG_MASK,
+				val
+			);
+		else
+		if (reg_azf & AZF_AC97_REG_EMU_IO_WRITE) {
+			switch (reg_ac97) {
+			case AC97_REC_GAIN_MIC:
+			case AC97_POWERDOWN:
+			case AC97_EXTENDED_STATUS:
+				/*
+				 * Silently swallow these writes.
+				 * Since for most registers our card doesn't
+				 * actually support a comparable feature,
+				 * this is exactly what we should do here.
+				 * The AC97 layer's I/O caching probably
+				 * automatically takes care of all the rest...
+				 * (remembers written values etc.)
+				 */
+				break;
+			default:
+				unsupported = 1;
+				break;
+			}
+		}
+	}
+	if (unsupported)
+		snd_azf3328_mixer_ac97_map_unsupported(reg_ac97, "write");
+}
+
+static int __devinit
+snd_azf3328_mixer_new(struct snd_azf3328 *chip)
+{
+	struct snd_ac97_bus *bus;
+	struct snd_ac97_template ac97;
+	static struct snd_ac97_bus_ops ops = {
+		.write = snd_azf3328_mixer_ac97_write,
+		.read = snd_azf3328_mixer_ac97_read,
+	};
+	int rc;
+
+	memset(&ac97, 0, sizeof(ac97));
+	ac97.scaps = AC97_SCAP_SKIP_MODEM
+			| AC97_SCAP_AUDIO /* we support audio! */
+			| AC97_SCAP_NO_SPDIF;
+	ac97.private_data = chip;
+	ac97.pci = chip->pci;
+
+	/*
+	 * ALSA's AC97 layer has terrible init crackling issues,
+	 * unfortunately, and since it makes use of AC97_RESET,
+	 * there's no use trying to mute Master Playback proactively.
+	 */
+
+	rc = snd_ac97_bus(chip->card, 0, &ops, NULL, &bus);
+	if (!rc)
+		rc = snd_ac97_mixer(bus, &ac97, &chip->ac97);
+		/*
+		 * Make sure to complain loudly in case of AC97 init failure,
+		 * since failure may happen quite often,
+		 * due to this card being a very quirky AC97 "lookalike".
+		 */
+	if (rc)
+		printk(KERN_ERR "azt3328: AC97 init failed, err %d!\n", rc);
+
+	/* If we return an error here, then snd_card_free() should
+	 * free up any ac97 codecs that got created, as well as the bus.
+	 */
+	return rc;
+}
+#else /* AZF_USE_AC97_LAYER */
 static void
 static void
 snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip,
 snd_azf3328_mixer_write_volume_gradually(const struct snd_azf3328 *chip,
 					 unsigned reg,
 					 unsigned reg,
@@ -945,6 +1282,7 @@ snd_azf3328_mixer_new(struct snd_azf3328 *chip)
 	snd_azf3328_dbgcallleave();
 	snd_azf3328_dbgcallleave();
 	return 0;
 	return 0;
 }
 }
+#endif /* AZF_USE_AC97_LAYER */
 
 
 static int
 static int
 snd_azf3328_hw_params(struct snd_pcm_substream *substream,
 snd_azf3328_hw_params(struct snd_pcm_substream *substream,
@@ -1233,8 +1571,8 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 		if (is_main_mixer_playback_codec) {
 		if (is_main_mixer_playback_codec) {
 			/* mute WaveOut (avoid clicking during setup) */
 			/* mute WaveOut (avoid clicking during setup) */
 			previously_muted =
 			previously_muted =
-				snd_azf3328_mixer_set_mute(
-						chip, IDX_MIXER_WAVEOUT, 1
+				snd_azf3328_mixer_mute_control_pcm(
+						chip, 1
 				);
 				);
 		}
 		}
 
 
@@ -1290,8 +1628,8 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 		if (is_main_mixer_playback_codec) {
 		if (is_main_mixer_playback_codec) {
 			/* now unmute WaveOut */
 			/* now unmute WaveOut */
 			if (!previously_muted)
 			if (!previously_muted)
-				snd_azf3328_mixer_set_mute(
-						chip, IDX_MIXER_WAVEOUT, 0
+				snd_azf3328_mixer_mute_control_pcm(
+						chip, 0
 				);
 				);
 		}
 		}
 
 
@@ -1315,8 +1653,8 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 		if (is_main_mixer_playback_codec) {
 		if (is_main_mixer_playback_codec) {
 			/* mute WaveOut (avoid clicking during setup) */
 			/* mute WaveOut (avoid clicking during setup) */
 			previously_muted =
 			previously_muted =
-				snd_azf3328_mixer_set_mute(
-						chip, IDX_MIXER_WAVEOUT, 1
+				snd_azf3328_mixer_mute_control_pcm(
+						chip, 1
 				);
 				);
 		}
 		}
 
 
@@ -1341,8 +1679,8 @@ snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 		if (is_main_mixer_playback_codec) {
 		if (is_main_mixer_playback_codec) {
 			/* now unmute WaveOut */
 			/* now unmute WaveOut */
 			if (!previously_muted)
 			if (!previously_muted)
-				snd_azf3328_mixer_set_mute(
-						chip, IDX_MIXER_WAVEOUT, 0
+				snd_azf3328_mixer_mute_control_pcm(
+						chip, 0
 				);
 				);
 		}
 		}
 
 
@@ -2050,11 +2388,7 @@ snd_azf3328_free(struct snd_azf3328 *chip)
 	if (chip->irq < 0)
 	if (chip->irq < 0)
 		goto __end_hw;
 		goto __end_hw;
 
 
-	/* reset (close) mixer:
-	 * first mute master volume, then reset
-	 */
-	snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1);
-	snd_azf3328_mixer_outw(chip, IDX_MIXER_RESET, 0x0000);
+	snd_azf3328_mixer_reset(chip);
 
 
 	snd_azf3328_timer_stop(chip->timer);
 	snd_azf3328_timer_stop(chip->timer);
 	snd_azf3328_gameport_free(chip);
 	snd_azf3328_gameport_free(chip);
@@ -2407,6 +2741,55 @@ snd_azf3328_suspend_regs(unsigned long io_addr, unsigned count, u32 *saved_regs)
 	}
 	}
 }
 }
 
 
+static inline void
+snd_azf3328_resume_regs(const u32 *saved_regs,
+			unsigned long io_addr,
+			unsigned count
+)
+{
+	unsigned reg;
+
+	for (reg = 0; reg < count; ++reg) {
+		outl(*saved_regs, io_addr);
+		snd_azf3328_dbgpm("resume: io 0x%04lx: 0x%08x --> 0x%08x\n",
+			io_addr, *saved_regs, inl(io_addr));
+		++saved_regs;
+		io_addr += sizeof(*saved_regs);
+	}
+}
+
+static inline void
+snd_azf3328_suspend_ac97(struct snd_azf3328 *chip)
+{
+#ifdef AZF_USE_AC97_LAYER
+	snd_ac97_suspend(chip->ac97);
+#else
+	snd_azf3328_suspend_regs(chip->mixer_io,
+		ARRAY_SIZE(chip->saved_regs_mixer), chip->saved_regs_mixer);
+
+	/* make sure to disable master volume etc. to prevent looping sound */
+	snd_azf3328_mixer_mute_control_master(chip, 1);
+	snd_azf3328_mixer_mute_control_pcm(chip, 1);
+#endif /* AZF_USE_AC97_LAYER */
+}
+
+static inline void
+snd_azf3328_resume_ac97(const struct snd_azf3328 *chip)
+{
+#ifdef AZF_USE_AC97_LAYER
+	snd_ac97_resume(chip->ac97);
+#else
+	snd_azf3328_resume_regs(chip->saved_regs_mixer, chip->mixer_io,
+					ARRAY_SIZE(chip->saved_regs_mixer));
+
+	/* unfortunately with 32bit transfers, IDX_MIXER_PLAY_MASTER (0x02)
+	   and IDX_MIXER_RESET (offset 0x00) get touched at the same time,
+	   resulting in a mixer reset condition persisting until _after_
+	   master vol was restored. Thus master vol needs an extra restore. */
+	outw(((u16 *)chip->saved_regs_mixer)[1], chip->mixer_io + 2);
+#endif /* AZF_USE_AC97_LAYER */
+}
+
 static int
 static int
 snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
 snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
 {
 {
@@ -2420,12 +2803,7 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
 	snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]);
 	snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]);
 	snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]);
 	snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]);
 
 
-	snd_azf3328_suspend_regs(chip->mixer_io,
-		ARRAY_SIZE(chip->saved_regs_mixer), chip->saved_regs_mixer);
-
-	/* make sure to disable master volume etc. to prevent looping sound */
-	snd_azf3328_mixer_set_mute(chip, IDX_MIXER_PLAY_MASTER, 1);
-	snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1);
+	snd_azf3328_suspend_ac97(chip);
 
 
 	snd_azf3328_suspend_regs(chip->ctrl_io,
 	snd_azf3328_suspend_regs(chip->ctrl_io,
 		ARRAY_SIZE(chip->saved_regs_ctrl), chip->saved_regs_ctrl);
 		ARRAY_SIZE(chip->saved_regs_ctrl), chip->saved_regs_ctrl);
@@ -2447,23 +2825,6 @@ snd_azf3328_suspend(struct pci_dev *pci, pm_message_t state)
 	return 0;
 	return 0;
 }
 }
 
 
-static inline void
-snd_azf3328_resume_regs(const u32 *saved_regs,
-			unsigned long io_addr,
-			unsigned count
-)
-{
-	unsigned reg;
-
-	for (reg = 0; reg < count; ++reg) {
-		outl(*saved_regs, io_addr);
-		snd_azf3328_dbgpm("resume: io 0x%04lx: 0x%08x --> 0x%08x\n",
-			io_addr, *saved_regs, inl(io_addr));
-		++saved_regs;
-		io_addr += sizeof(*saved_regs);
-	}
-}
-
 static int
 static int
 snd_azf3328_resume(struct pci_dev *pci)
 snd_azf3328_resume(struct pci_dev *pci)
 {
 {
@@ -2487,14 +2848,7 @@ snd_azf3328_resume(struct pci_dev *pci)
 	snd_azf3328_resume_regs(chip->saved_regs_opl3, chip->opl3_io,
 	snd_azf3328_resume_regs(chip->saved_regs_opl3, chip->opl3_io,
 					ARRAY_SIZE(chip->saved_regs_opl3));
 					ARRAY_SIZE(chip->saved_regs_opl3));
 
 
-	snd_azf3328_resume_regs(chip->saved_regs_mixer, chip->mixer_io,
-					ARRAY_SIZE(chip->saved_regs_mixer));
-
-	/* unfortunately with 32bit transfers, IDX_MIXER_PLAY_MASTER (0x02)
-	   and IDX_MIXER_RESET (offset 0x00) get touched at the same time,
-	   resulting in a mixer reset condition persisting until _after_
-	   master vol was restored. Thus master vol needs an extra restore. */
-	outw(((u16 *)chip->saved_regs_mixer)[1], chip->mixer_io + 2);
+	snd_azf3328_resume_ac97(chip);
 
 
 	snd_azf3328_resume_regs(chip->saved_regs_ctrl, chip->ctrl_io,
 	snd_azf3328_resume_regs(chip->saved_regs_ctrl, chip->ctrl_io,
 					ARRAY_SIZE(chip->saved_regs_ctrl));
 					ARRAY_SIZE(chip->saved_regs_ctrl));

+ 1 - 1
sound/pci/ctxfi/ctatc.c

@@ -869,7 +869,7 @@ spdif_passthru_playback_setup(struct ct_atc *atc, struct ct_atc_pcm *apcm)
 	mutex_lock(&atc->atc_mutex);
 	mutex_lock(&atc->atc_mutex);
 	dao->ops->get_spos(dao, &status);
 	dao->ops->get_spos(dao, &status);
 	if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) {
 	if (((status >> 24) & IEC958_AES3_CON_FS) != iec958_con_fs) {
-		status &= ((~IEC958_AES3_CON_FS) << 24);
+		status &= ~(IEC958_AES3_CON_FS << 24);
 		status |= (iec958_con_fs << 24);
 		status |= (iec958_con_fs << 24);
 		dao->ops->set_spos(dao, status);
 		dao->ops->set_spos(dao, status);
 		dao->ops->commit_write(dao);
 		dao->ops->commit_write(dao);

+ 2 - 0
sound/pci/ctxfi/ctdaio.c

@@ -176,6 +176,7 @@ static int dao_set_left_input(struct dao *dao, struct rsc *input)
 	if (!entry)
 	if (!entry)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
+	dao->ops->clear_left_input(dao);
 	/* Program master and conjugate resources */
 	/* Program master and conjugate resources */
 	input->ops->master(input);
 	input->ops->master(input);
 	daio->rscl.ops->master(&daio->rscl);
 	daio->rscl.ops->master(&daio->rscl);
@@ -204,6 +205,7 @@ static int dao_set_right_input(struct dao *dao, struct rsc *input)
 	if (!entry)
 	if (!entry)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
+	dao->ops->clear_right_input(dao);
 	/* Program master and conjugate resources */
 	/* Program master and conjugate resources */
 	input->ops->master(input);
 	input->ops->master(input);
 	daio->rscr.ops->master(&daio->rscr);
 	daio->rscr.ops->master(&daio->rscr);

+ 18 - 10
sound/pci/ctxfi/cthw20k2.c

@@ -1307,10 +1307,10 @@ static int hw_pll_init(struct hw *hw, unsigned int rsr)
 	set_field(&pllctl, PLLCTL_B, 0);
 	set_field(&pllctl, PLLCTL_B, 0);
 	if (48000 == rsr) {
 	if (48000 == rsr) {
 		set_field(&pllctl, PLLCTL_FD, 16 - 2);
 		set_field(&pllctl, PLLCTL_FD, 16 - 2);
-		set_field(&pllctl, PLLCTL_RD, 1 - 1);
+		set_field(&pllctl, PLLCTL_RD, 1 - 1); /* 3000*16/1 = 48000 */
 	} else { /* 44100 */
 	} else { /* 44100 */
 		set_field(&pllctl, PLLCTL_FD, 147 - 2);
 		set_field(&pllctl, PLLCTL_FD, 147 - 2);
-		set_field(&pllctl, PLLCTL_RD, 10 - 1);
+		set_field(&pllctl, PLLCTL_RD, 10 - 1); /* 3000*147/10 = 44100 */
 	}
 	}
 	hw_write_20kx(hw, PLL_CTL, pllctl);
 	hw_write_20kx(hw, PLL_CTL, pllctl);
 	mdelay(40);
 	mdelay(40);
@@ -1740,6 +1740,10 @@ static int hw_is_adc_input_selected(struct hw *hw, enum ADCSRC type)
 	return data;
 	return data;
 }
 }
 
 
+#define MIC_BOOST_0DB 0xCF
+#define MIC_BOOST_STEPS_PER_DB 2
+#define MIC_BOOST_20DB (MIC_BOOST_0DB + 20 * MIC_BOOST_STEPS_PER_DB)
+
 static int hw_adc_input_select(struct hw *hw, enum ADCSRC type)
 static int hw_adc_input_select(struct hw *hw, enum ADCSRC type)
 {
 {
 	u32 data;
 	u32 data;
@@ -1751,10 +1755,12 @@ static int hw_adc_input_select(struct hw *hw, enum ADCSRC type)
 		hw_write_20kx(hw, GPIO_DATA, data);
 		hw_write_20kx(hw, GPIO_DATA, data);
 		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101),
 		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101),
 				MAKE_WM8775_DATA(0x101)); /* Mic-in */
 				MAKE_WM8775_DATA(0x101)); /* Mic-in */
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xE7),
-				MAKE_WM8775_DATA(0xE7)); /* +12dB boost */
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xE7),
-				MAKE_WM8775_DATA(0xE7)); /* +12dB boost */
+		hw20k2_i2c_write(hw,
+				MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB),
+				MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
+		hw20k2_i2c_write(hw,
+				MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB),
+				MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
 		break;
 		break;
 	case ADC_LINEIN:
 	case ADC_LINEIN:
 		data &= ~(0x1 << 14);
 		data &= ~(0x1 << 14);
@@ -1827,10 +1833,12 @@ static int hw_adc_init(struct hw *hw, const struct adc_conf *info)
 
 
 		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101),
 		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_ADCMC, 0x101),
 				MAKE_WM8775_DATA(0x101)); /* Mic-in */
 				MAKE_WM8775_DATA(0x101)); /* Mic-in */
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCL, 0xE7),
-				MAKE_WM8775_DATA(0xE7)); /* +12dB boost */
-		hw20k2_i2c_write(hw, MAKE_WM8775_ADDR(WM8775_AADCR, 0xE7),
-				MAKE_WM8775_DATA(0xE7)); /* +12dB boost */
+		hw20k2_i2c_write(hw,
+				MAKE_WM8775_ADDR(WM8775_AADCL, MIC_BOOST_20DB),
+				MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
+		hw20k2_i2c_write(hw,
+				MAKE_WM8775_ADDR(WM8775_AADCR, MIC_BOOST_20DB),
+				MAKE_WM8775_DATA(MIC_BOOST_20DB)); /* +20dB */
 	} else if (mux == 2) {
 	} else if (mux == 2) {
 		/* Configures GPIO data to select Line-in */
 		/* Configures GPIO data to select Line-in */
 		data &= ~(0x1 << 14);
 		data &= ~(0x1 << 14);

+ 5 - 14
sound/pci/ctxfi/ctmixer.c

@@ -566,19 +566,6 @@ static int ct_spdif_get_mask(struct snd_kcontrol *kcontrol,
 	return 0;
 	return 0;
 }
 }
 
 
-static int ct_spdif_default_get(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	unsigned int status = SNDRV_PCM_DEFAULT_CON_SPDIF;
-
-	ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
-	ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
-	ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
-	ucontrol->value.iec958.status[3] = (status >> 24) & 0xff;
-
-	return 0;
-}
-
 static int ct_spdif_get(struct snd_kcontrol *kcontrol,
 static int ct_spdif_get(struct snd_kcontrol *kcontrol,
 			struct snd_ctl_elem_value *ucontrol)
 			struct snd_ctl_elem_value *ucontrol)
 {
 {
@@ -586,6 +573,10 @@ static int ct_spdif_get(struct snd_kcontrol *kcontrol,
 	unsigned int status;
 	unsigned int status;
 
 
 	atc->spdif_out_get_status(atc, &status);
 	atc->spdif_out_get_status(atc, &status);
+
+	if (status == 0)
+		status = SNDRV_PCM_DEFAULT_CON_SPDIF;
+
 	ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
 	ucontrol->value.iec958.status[0] = (status >> 0) & 0xff;
 	ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
 	ucontrol->value.iec958.status[1] = (status >> 8) & 0xff;
 	ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
 	ucontrol->value.iec958.status[2] = (status >> 16) & 0xff;
@@ -629,7 +620,7 @@ static struct snd_kcontrol_new iec958_default_ctl = {
 	.name		= SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
 	.name		= SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
 	.count		= 1,
 	.count		= 1,
 	.info		= ct_spdif_info,
 	.info		= ct_spdif_info,
-	.get		= ct_spdif_default_get,
+	.get		= ct_spdif_get,
 	.put		= ct_spdif_put,
 	.put		= ct_spdif_put,
 	.private_value	= MIXER_IEC958_DEFAULT
 	.private_value	= MIXER_IEC958_DEFAULT
 };
 };

+ 1 - 2
sound/pci/ctxfi/ctvmem.c

@@ -52,8 +52,7 @@ get_vm_block(struct ct_vm *vm, unsigned int size)
 
 
 	if (entry->size == size) {
 	if (entry->size == size) {
 		/* Move the vm node from unused list to used list directly */
 		/* Move the vm node from unused list to used list directly */
-		list_del(&entry->list);
-		list_add(&entry->list, &vm->used);
+		list_move(&entry->list, &vm->used);
 		vm->size -= size;
 		vm->size -= size;
 		block = entry;
 		block = entry;
 		goto out;
 		goto out;

+ 1 - 1
sound/pci/emu10k1/emu10k1_main.c

@@ -926,7 +926,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
 	snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19);
 	snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19);
 	/* Unknown. */
 	/* Unknown. */
 	snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c);
 	snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c);
-	/* IRQ Enable: Alll on */
+	/* IRQ Enable: All on */
 	/* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); */
 	/* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); */
 	/* IRQ Enable: All off */
 	/* IRQ Enable: All off */
 	snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00);
 	snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00);

+ 1 - 1
sound/pci/hda/patch_realtek.c

@@ -4635,7 +4635,7 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = {
 	SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
 	SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
 	SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
 	SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
 	SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
 	SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
-	SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734),
+	SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_F1734),
 	SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
 	SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
 	SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
 	SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
 	SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
 	SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),

+ 54 - 53
sound/pci/intel8x0m.c

@@ -341,9 +341,9 @@ static int snd_intel8x0m_codec_semaphore(struct intel8x0m *chip, unsigned int co
 	return -EBUSY;
 	return -EBUSY;
 }
 }
  
  
-static void snd_intel8x0_codec_write(struct snd_ac97 *ac97,
-				     unsigned short reg,
-				     unsigned short val)
+static void snd_intel8x0m_codec_write(struct snd_ac97 *ac97,
+				      unsigned short reg,
+				      unsigned short val)
 {
 {
 	struct intel8x0m *chip = ac97->private_data;
 	struct intel8x0m *chip = ac97->private_data;
 	
 	
@@ -354,8 +354,8 @@ static void snd_intel8x0_codec_write(struct snd_ac97 *ac97,
 	iaputword(chip, reg + ac97->num * 0x80, val);
 	iaputword(chip, reg + ac97->num * 0x80, val);
 }
 }
 
 
-static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97,
-					      unsigned short reg)
+static unsigned short snd_intel8x0m_codec_read(struct snd_ac97 *ac97,
+					       unsigned short reg)
 {
 {
 	struct intel8x0m *chip = ac97->private_data;
 	struct intel8x0m *chip = ac97->private_data;
 	unsigned short res;
 	unsigned short res;
@@ -385,7 +385,7 @@ static unsigned short snd_intel8x0_codec_read(struct snd_ac97 *ac97,
 /*
 /*
  * DMA I/O
  * DMA I/O
  */
  */
-static void snd_intel8x0_setup_periods(struct intel8x0m *chip, struct ichdev *ichdev) 
+static void snd_intel8x0m_setup_periods(struct intel8x0m *chip, struct ichdev *ichdev)
 {
 {
 	int idx;
 	int idx;
 	u32 *bdbar = ichdev->bdbar;
 	u32 *bdbar = ichdev->bdbar;
@@ -437,7 +437,7 @@ static void snd_intel8x0_setup_periods(struct intel8x0m *chip, struct ichdev *ic
  *  Interrupt handler
  *  Interrupt handler
  */
  */
 
 
-static inline void snd_intel8x0_update(struct intel8x0m *chip, struct ichdev *ichdev)
+static inline void snd_intel8x0m_update(struct intel8x0m *chip, struct ichdev *ichdev)
 {
 {
 	unsigned long port = ichdev->reg_offset;
 	unsigned long port = ichdev->reg_offset;
 	int civ, i, step;
 	int civ, i, step;
@@ -489,7 +489,7 @@ static inline void snd_intel8x0_update(struct intel8x0m *chip, struct ichdev *ic
 	iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
 	iputbyte(chip, port + ichdev->roff_sr, ICH_FIFOE | ICH_BCIS | ICH_LVBCI);
 }
 }
 
 
-static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id)
+static irqreturn_t snd_intel8x0m_interrupt(int irq, void *dev_id)
 {
 {
 	struct intel8x0m *chip = dev_id;
 	struct intel8x0m *chip = dev_id;
 	struct ichdev *ichdev;
 	struct ichdev *ichdev;
@@ -512,7 +512,7 @@ static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id)
 	for (i = 0; i < chip->bdbars_count; i++) {
 	for (i = 0; i < chip->bdbars_count; i++) {
 		ichdev = &chip->ichd[i];
 		ichdev = &chip->ichd[i];
 		if (status & ichdev->int_sta_mask)
 		if (status & ichdev->int_sta_mask)
-			snd_intel8x0_update(chip, ichdev);
+			snd_intel8x0m_update(chip, ichdev);
 	}
 	}
 
 
 	/* ack them */
 	/* ack them */
@@ -526,7 +526,7 @@ static irqreturn_t snd_intel8x0_interrupt(int irq, void *dev_id)
  *  PCM part
  *  PCM part
  */
  */
 
 
-static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+static int snd_intel8x0m_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
 {
 	struct intel8x0m *chip = snd_pcm_substream_chip(substream);
 	struct intel8x0m *chip = snd_pcm_substream_chip(substream);
 	struct ichdev *ichdev = get_ichdev(substream);
 	struct ichdev *ichdev = get_ichdev(substream);
@@ -561,18 +561,18 @@ static int snd_intel8x0_pcm_trigger(struct snd_pcm_substream *substream, int cmd
 	return 0;
 	return 0;
 }
 }
 
 
-static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream,
+static int snd_intel8x0m_hw_params(struct snd_pcm_substream *substream,
 				  struct snd_pcm_hw_params *hw_params)
 				  struct snd_pcm_hw_params *hw_params)
 {
 {
 	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
 	return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
 }
 }
 
 
-static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream)
+static int snd_intel8x0m_hw_free(struct snd_pcm_substream *substream)
 {
 {
 	return snd_pcm_lib_free_pages(substream);
 	return snd_pcm_lib_free_pages(substream);
 }
 }
 
 
-static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *substream)
+static snd_pcm_uframes_t snd_intel8x0m_pcm_pointer(struct snd_pcm_substream *substream)
 {
 {
 	struct intel8x0m *chip = snd_pcm_substream_chip(substream);
 	struct intel8x0m *chip = snd_pcm_substream_chip(substream);
 	struct ichdev *ichdev = get_ichdev(substream);
 	struct ichdev *ichdev = get_ichdev(substream);
@@ -600,7 +600,7 @@ static int snd_intel8x0m_pcm_prepare(struct snd_pcm_substream *substream)
 	ichdev->fragsize = snd_pcm_lib_period_bytes(substream);
 	ichdev->fragsize = snd_pcm_lib_period_bytes(substream);
 	snd_ac97_write(ichdev->ac97, AC97_LINE1_RATE, runtime->rate);
 	snd_ac97_write(ichdev->ac97, AC97_LINE1_RATE, runtime->rate);
 	snd_ac97_write(ichdev->ac97, AC97_LINE1_LEVEL, 0);
 	snd_ac97_write(ichdev->ac97, AC97_LINE1_LEVEL, 0);
-	snd_intel8x0_setup_periods(chip, ichdev);
+	snd_intel8x0m_setup_periods(chip, ichdev);
 	return 0;
 	return 0;
 }
 }
 
 
@@ -682,22 +682,22 @@ static struct snd_pcm_ops snd_intel8x0m_playback_ops = {
 	.open =		snd_intel8x0m_playback_open,
 	.open =		snd_intel8x0m_playback_open,
 	.close =	snd_intel8x0m_playback_close,
 	.close =	snd_intel8x0m_playback_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.ioctl =	snd_pcm_lib_ioctl,
-	.hw_params =	snd_intel8x0_hw_params,
-	.hw_free =	snd_intel8x0_hw_free,
+	.hw_params =	snd_intel8x0m_hw_params,
+	.hw_free =	snd_intel8x0m_hw_free,
 	.prepare =	snd_intel8x0m_pcm_prepare,
 	.prepare =	snd_intel8x0m_pcm_prepare,
-	.trigger =	snd_intel8x0_pcm_trigger,
-	.pointer =	snd_intel8x0_pcm_pointer,
+	.trigger =	snd_intel8x0m_pcm_trigger,
+	.pointer =	snd_intel8x0m_pcm_pointer,
 };
 };
 
 
 static struct snd_pcm_ops snd_intel8x0m_capture_ops = {
 static struct snd_pcm_ops snd_intel8x0m_capture_ops = {
 	.open =		snd_intel8x0m_capture_open,
 	.open =		snd_intel8x0m_capture_open,
 	.close =	snd_intel8x0m_capture_close,
 	.close =	snd_intel8x0m_capture_close,
 	.ioctl =	snd_pcm_lib_ioctl,
 	.ioctl =	snd_pcm_lib_ioctl,
-	.hw_params =	snd_intel8x0_hw_params,
-	.hw_free =	snd_intel8x0_hw_free,
+	.hw_params =	snd_intel8x0m_hw_params,
+	.hw_free =	snd_intel8x0m_hw_free,
 	.prepare =	snd_intel8x0m_pcm_prepare,
 	.prepare =	snd_intel8x0m_pcm_prepare,
-	.trigger =	snd_intel8x0_pcm_trigger,
-	.pointer =	snd_intel8x0_pcm_pointer,
+	.trigger =	snd_intel8x0m_pcm_trigger,
+	.pointer =	snd_intel8x0m_pcm_pointer,
 };
 };
 
 
 
 
@@ -710,7 +710,7 @@ struct ich_pcm_table {
 	int ac97_idx;
 	int ac97_idx;
 };
 };
 
 
-static int __devinit snd_intel8x0_pcm1(struct intel8x0m *chip, int device,
+static int __devinit snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
 				       struct ich_pcm_table *rec)
 				       struct ich_pcm_table *rec)
 {
 {
 	struct snd_pcm *pcm;
 	struct snd_pcm *pcm;
@@ -759,7 +759,7 @@ static struct ich_pcm_table intel_pcms[] __devinitdata = {
 	},
 	},
 };
 };
 
 
-static int __devinit snd_intel8x0_pcm(struct intel8x0m *chip)
+static int __devinit snd_intel8x0m_pcm(struct intel8x0m *chip)
 {
 {
 	int i, tblsize, device, err;
 	int i, tblsize, device, err;
 	struct ich_pcm_table *tbl, *rec;
 	struct ich_pcm_table *tbl, *rec;
@@ -791,7 +791,7 @@ static int __devinit snd_intel8x0_pcm(struct intel8x0m *chip)
 			if (! chip->ichd[rec->ac97_idx].ac97)
 			if (! chip->ichd[rec->ac97_idx].ac97)
 				continue;
 				continue;
 		}
 		}
-		err = snd_intel8x0_pcm1(chip, device, rec);
+		err = snd_intel8x0m_pcm1(chip, device, rec);
 		if (err < 0)
 		if (err < 0)
 			return err;
 			return err;
 		device++;
 		device++;
@@ -806,20 +806,20 @@ static int __devinit snd_intel8x0_pcm(struct intel8x0m *chip)
  *  Mixer part
  *  Mixer part
  */
  */
 
 
-static void snd_intel8x0_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
+static void snd_intel8x0m_mixer_free_ac97_bus(struct snd_ac97_bus *bus)
 {
 {
 	struct intel8x0m *chip = bus->private_data;
 	struct intel8x0m *chip = bus->private_data;
 	chip->ac97_bus = NULL;
 	chip->ac97_bus = NULL;
 }
 }
 
 
-static void snd_intel8x0_mixer_free_ac97(struct snd_ac97 *ac97)
+static void snd_intel8x0m_mixer_free_ac97(struct snd_ac97 *ac97)
 {
 {
 	struct intel8x0m *chip = ac97->private_data;
 	struct intel8x0m *chip = ac97->private_data;
 	chip->ac97 = NULL;
 	chip->ac97 = NULL;
 }
 }
 
 
 
 
-static int __devinit snd_intel8x0_mixer(struct intel8x0m *chip, int ac97_clock)
+static int __devinit snd_intel8x0m_mixer(struct intel8x0m *chip, int ac97_clock)
 {
 {
 	struct snd_ac97_bus *pbus;
 	struct snd_ac97_bus *pbus;
 	struct snd_ac97_template ac97;
 	struct snd_ac97_template ac97;
@@ -827,22 +827,22 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0m *chip, int ac97_clock)
 	int err;
 	int err;
 	unsigned int glob_sta = 0;
 	unsigned int glob_sta = 0;
 	static struct snd_ac97_bus_ops ops = {
 	static struct snd_ac97_bus_ops ops = {
-		.write = snd_intel8x0_codec_write,
-		.read = snd_intel8x0_codec_read,
+		.write = snd_intel8x0m_codec_write,
+		.read = snd_intel8x0m_codec_read,
 	};
 	};
 
 
 	chip->in_ac97_init = 1;
 	chip->in_ac97_init = 1;
 	
 	
 	memset(&ac97, 0, sizeof(ac97));
 	memset(&ac97, 0, sizeof(ac97));
 	ac97.private_data = chip;
 	ac97.private_data = chip;
-	ac97.private_free = snd_intel8x0_mixer_free_ac97;
+	ac97.private_free = snd_intel8x0m_mixer_free_ac97;
 	ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;
 	ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;
 
 
 	glob_sta = igetdword(chip, ICHREG(GLOB_STA));
 	glob_sta = igetdword(chip, ICHREG(GLOB_STA));
 
 
 	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)
 	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &pbus)) < 0)
 		goto __err;
 		goto __err;
-	pbus->private_free = snd_intel8x0_mixer_free_ac97_bus;
+	pbus->private_free = snd_intel8x0m_mixer_free_ac97_bus;
 	if (ac97_clock >= 8000 && ac97_clock <= 48000)
 	if (ac97_clock >= 8000 && ac97_clock <= 48000)
 		pbus->clock = ac97_clock;
 		pbus->clock = ac97_clock;
 	chip->ac97_bus = pbus;
 	chip->ac97_bus = pbus;
@@ -894,7 +894,8 @@ static int snd_intel8x0m_ich_chip_init(struct intel8x0m *chip, int probing)
 	/* finish cold or do warm reset */
 	/* finish cold or do warm reset */
 	cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM;
 	cnt |= (cnt & ICH_AC97COLD) == 0 ? ICH_AC97COLD : ICH_AC97WARM;
 	iputdword(chip, ICHREG(GLOB_CNT), cnt);
 	iputdword(chip, ICHREG(GLOB_CNT), cnt);
-	end_time = (jiffies + (HZ / 4)) + 1;
+	usleep_range(500, 1000); /* give warm reset some time */
+	end_time = jiffies + HZ / 4;
 	do {
 	do {
 		if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0)
 		if ((igetdword(chip, ICHREG(GLOB_CNT)) & ICH_AC97WARM) == 0)
 			goto __ok;
 			goto __ok;
@@ -959,7 +960,7 @@ static int snd_intel8x0m_ich_chip_init(struct intel8x0m *chip, int probing)
       	return 0;
       	return 0;
 }
 }
 
 
-static int snd_intel8x0_chip_init(struct intel8x0m *chip, int probing)
+static int snd_intel8x0m_chip_init(struct intel8x0m *chip, int probing)
 {
 {
 	unsigned int i;
 	unsigned int i;
 	int err;
 	int err;
@@ -980,7 +981,7 @@ static int snd_intel8x0_chip_init(struct intel8x0m *chip, int probing)
 	return 0;
 	return 0;
 }
 }
 
 
-static int snd_intel8x0_free(struct intel8x0m *chip)
+static int snd_intel8x0m_free(struct intel8x0m *chip)
 {
 {
 	unsigned int i;
 	unsigned int i;
 
 
@@ -1045,7 +1046,7 @@ static int intel8x0m_resume(struct pci_dev *pci)
 		return -EIO;
 		return -EIO;
 	}
 	}
 	pci_set_master(pci);
 	pci_set_master(pci);
-	if (request_irq(pci->irq, snd_intel8x0_interrupt,
+	if (request_irq(pci->irq, snd_intel8x0m_interrupt,
 			IRQF_SHARED, card->shortname, chip)) {
 			IRQF_SHARED, card->shortname, chip)) {
 		printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, "
 		printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, "
 		       "disabling device\n", pci->irq);
 		       "disabling device\n", pci->irq);
@@ -1053,7 +1054,7 @@ static int intel8x0m_resume(struct pci_dev *pci)
 		return -EIO;
 		return -EIO;
 	}
 	}
 	chip->irq = pci->irq;
 	chip->irq = pci->irq;
-	snd_intel8x0_chip_init(chip, 0);
+	snd_intel8x0m_chip_init(chip, 0);
 	snd_ac97_resume(chip->ac97);
 	snd_ac97_resume(chip->ac97);
 
 
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
 	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -1094,10 +1095,10 @@ static void __devinit snd_intel8x0m_proc_init(struct intel8x0m * chip)
 #endif /* CONFIG_PROC_FS */
 #endif /* CONFIG_PROC_FS */
 
 
 
 
-static int snd_intel8x0_dev_free(struct snd_device *device)
+static int snd_intel8x0m_dev_free(struct snd_device *device)
 {
 {
 	struct intel8x0m *chip = device->device_data;
 	struct intel8x0m *chip = device->device_data;
-	return snd_intel8x0_free(chip);
+	return snd_intel8x0m_free(chip);
 }
 }
 
 
 struct ich_reg_info {
 struct ich_reg_info {
@@ -1108,7 +1109,7 @@ struct ich_reg_info {
 static int __devinit snd_intel8x0m_create(struct snd_card *card,
 static int __devinit snd_intel8x0m_create(struct snd_card *card,
 					 struct pci_dev *pci,
 					 struct pci_dev *pci,
 					 unsigned long device_type,
 					 unsigned long device_type,
-					 struct intel8x0m ** r_intel8x0)
+					 struct intel8x0m **r_intel8x0m)
 {
 {
 	struct intel8x0m *chip;
 	struct intel8x0m *chip;
 	int err;
 	int err;
@@ -1116,7 +1117,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
 	unsigned int int_sta_masks;
 	unsigned int int_sta_masks;
 	struct ichdev *ichdev;
 	struct ichdev *ichdev;
 	static struct snd_device_ops ops = {
 	static struct snd_device_ops ops = {
-		.dev_free =	snd_intel8x0_dev_free,
+		.dev_free =	snd_intel8x0m_dev_free,
 	};
 	};
 	static struct ich_reg_info intel_regs[2] = {
 	static struct ich_reg_info intel_regs[2] = {
 		{ ICH_MIINT, 0 },
 		{ ICH_MIINT, 0 },
@@ -1124,7 +1125,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
 	};
 	};
 	struct ich_reg_info *tbl;
 	struct ich_reg_info *tbl;
 
 
-	*r_intel8x0 = NULL;
+	*r_intel8x0m = NULL;
 
 
 	if ((err = pci_enable_device(pci)) < 0)
 	if ((err = pci_enable_device(pci)) < 0)
 		return err;
 		return err;
@@ -1158,7 +1159,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
 		chip->addr = pci_iomap(pci, 0, 0);
 		chip->addr = pci_iomap(pci, 0, 0);
 	if (!chip->addr) {
 	if (!chip->addr) {
 		snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
 		snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
-		snd_intel8x0_free(chip);
+		snd_intel8x0m_free(chip);
 		return -EIO;
 		return -EIO;
 	}
 	}
 	if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
 	if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
@@ -1167,15 +1168,15 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
 		chip->bmaddr = pci_iomap(pci, 1, 0);
 		chip->bmaddr = pci_iomap(pci, 1, 0);
 	if (!chip->bmaddr) {
 	if (!chip->bmaddr) {
 		snd_printk(KERN_ERR "Controller space ioremap problem\n");
 		snd_printk(KERN_ERR "Controller space ioremap problem\n");
-		snd_intel8x0_free(chip);
+		snd_intel8x0m_free(chip);
 		return -EIO;
 		return -EIO;
 	}
 	}
 
 
  port_inited:
  port_inited:
-	if (request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_SHARED,
+	if (request_irq(pci->irq, snd_intel8x0m_interrupt, IRQF_SHARED,
 			card->shortname, chip)) {
 			card->shortname, chip)) {
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
 		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);
-		snd_intel8x0_free(chip);
+		snd_intel8x0m_free(chip);
 		return -EBUSY;
 		return -EBUSY;
 	}
 	}
 	chip->irq = pci->irq;
 	chip->irq = pci->irq;
@@ -1210,7 +1211,7 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
 	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
 	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
 				chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,
 				chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,
 				&chip->bdbars) < 0) {
 				&chip->bdbars) < 0) {
-		snd_intel8x0_free(chip);
+		snd_intel8x0m_free(chip);
 		return -ENOMEM;
 		return -ENOMEM;
 	}
 	}
 	/* tables must be aligned to 8 bytes here, but the kernel pages
 	/* tables must be aligned to 8 bytes here, but the kernel pages
@@ -1225,19 +1226,19 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
 	chip->int_sta_reg = ICH_REG_GLOB_STA;
 	chip->int_sta_reg = ICH_REG_GLOB_STA;
 	chip->int_sta_mask = int_sta_masks;
 	chip->int_sta_mask = int_sta_masks;
 
 
-	if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) {
-		snd_intel8x0_free(chip);
+	if ((err = snd_intel8x0m_chip_init(chip, 1)) < 0) {
+		snd_intel8x0m_free(chip);
 		return err;
 		return err;
 	}
 	}
 
 
 	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
 	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
-		snd_intel8x0_free(chip);
+		snd_intel8x0m_free(chip);
 		return err;
 		return err;
 	}
 	}
 
 
 	snd_card_set_dev(card, &pci->dev);
 	snd_card_set_dev(card, &pci->dev);
 
 
-	*r_intel8x0 = chip;
+	*r_intel8x0m = chip;
 	return 0;
 	return 0;
 }
 }
 
 
@@ -1295,11 +1296,11 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
 	}
 	}
 	card->private_data = chip;
 	card->private_data = chip;
 
 
-	if ((err = snd_intel8x0_mixer(chip, ac97_clock)) < 0) {
+	if ((err = snd_intel8x0m_mixer(chip, ac97_clock)) < 0) {
 		snd_card_free(card);
 		snd_card_free(card);
 		return err;
 		return err;
 	}
 	}
-	if ((err = snd_intel8x0_pcm(chip)) < 0) {
+	if ((err = snd_intel8x0m_pcm(chip)) < 0) {
 		snd_card_free(card);
 		snd_card_free(card);
 		return err;
 		return err;
 	}
 	}

Файловите разлики са ограничени, защото са твърде много
+ 595 - 120
sound/pci/rme9652/hdspm.c


+ 5 - 1
sound/ppc/pmac.c

@@ -1034,7 +1034,11 @@ static int __devinit snd_pmac_detect(struct snd_pmac *chip)
 	if (of_device_is_compatible(sound, "tumbler")) {
 	if (of_device_is_compatible(sound, "tumbler")) {
 		chip->model = PMAC_TUMBLER;
 		chip->model = PMAC_TUMBLER;
 		chip->can_capture = of_machine_is_compatible("PowerMac4,2")
 		chip->can_capture = of_machine_is_compatible("PowerMac4,2")
-				|| of_machine_is_compatible("PowerBook4,1");
+				|| of_machine_is_compatible("PowerBook3,2")
+				|| of_machine_is_compatible("PowerBook3,3")
+				|| of_machine_is_compatible("PowerBook4,1")
+				|| of_machine_is_compatible("PowerBook4,2")
+				|| of_machine_is_compatible("PowerBook4,3");
 		chip->can_duplex = 0;
 		chip->can_duplex = 0;
 		// chip->can_byte_swap = 0; /* FIXME: check this */
 		// chip->can_byte_swap = 0; /* FIXME: check this */
 		chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
 		chip->num_freqs = ARRAY_SIZE(tumbler_freqs);

+ 3 - 0
sound/sound_core.c

@@ -384,6 +384,9 @@ int register_sound_special_device(const struct file_operations *fops, int unit,
 	    case 4:
 	    case 4:
 		name = "audio";
 		name = "audio";
 		break;
 		break;
+	    case 5:
+		name = "dspW";
+		break;
 	    case 8:
 	    case 8:
 		name = "sequencer2";
 		name = "sequencer2";
 		if (unit >= SOUND_STEP)
 		if (unit >= SOUND_STEP)

+ 3 - 0
sound/usb/6fire/Makefile

@@ -0,0 +1,3 @@
+snd-usb-6fire-objs += chip.o comm.o midi.o control.o firmware.o pcm.o
+obj-$(CONFIG_SND_USB_6FIRE) += snd-usb-6fire.o
+

+ 232 - 0
sound/usb/6fire/chip.c

@@ -0,0 +1,232 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Main routines and module definitions.
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "chip.h"
+#include "firmware.h"
+#include "pcm.h"
+#include "control.h"
+#include "comm.h"
+#include "midi.h"
+
+#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <sound/initval.h>
+
+MODULE_AUTHOR("Torsten Schenk <torsten.schenk@zoho.com>");
+MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver, version 0.3.0");
+MODULE_LICENSE("GPL v2");
+MODULE_SUPPORTED_DEVICE("{{TerraTec, DMX 6Fire USB}}");
+
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable card */
+static struct sfire_chip *chips[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+static struct usb_device *devices[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for the 6fire sound device");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for the 6fire sound device.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable the 6fire sound device.");
+
+static DEFINE_MUTEX(register_mutex);
+
+static void usb6fire_chip_abort(struct sfire_chip *chip)
+{
+	if (chip) {
+		if (chip->pcm)
+			usb6fire_pcm_abort(chip);
+		if (chip->midi)
+			usb6fire_midi_abort(chip);
+		if (chip->comm)
+			usb6fire_comm_abort(chip);
+		if (chip->control)
+			usb6fire_control_abort(chip);
+		if (chip->card) {
+			snd_card_disconnect(chip->card);
+			snd_card_free_when_closed(chip->card);
+			chip->card = NULL;
+		}
+	}
+}
+
+static void usb6fire_chip_destroy(struct sfire_chip *chip)
+{
+	if (chip) {
+		if (chip->pcm)
+			usb6fire_pcm_destroy(chip);
+		if (chip->midi)
+			usb6fire_midi_destroy(chip);
+		if (chip->comm)
+			usb6fire_comm_destroy(chip);
+		if (chip->control)
+			usb6fire_control_destroy(chip);
+		if (chip->card)
+			snd_card_free(chip->card);
+	}
+}
+
+static int __devinit usb6fire_chip_probe(struct usb_interface *intf,
+		const struct usb_device_id *usb_id)
+{
+	int ret;
+	int i;
+	struct sfire_chip *chip = NULL;
+	struct usb_device *device = interface_to_usbdev(intf);
+	int regidx = -1; /* index in module parameter array */
+	struct snd_card *card = NULL;
+
+	/* look if we already serve this card and return if so */
+	mutex_lock(&register_mutex);
+	for (i = 0; i < SNDRV_CARDS; i++) {
+		if (devices[i] == device) {
+			if (chips[i])
+				chips[i]->intf_count++;
+			usb_set_intfdata(intf, chips[i]);
+			mutex_unlock(&register_mutex);
+			return 0;
+		} else if (regidx < 0)
+			regidx = i;
+	}
+	if (regidx < 0) {
+		mutex_unlock(&register_mutex);
+		snd_printk(KERN_ERR PREFIX "too many cards registered.\n");
+		return -ENODEV;
+	}
+	devices[regidx] = device;
+	mutex_unlock(&register_mutex);
+
+	/* check, if firmware is present on device, upload it if not */
+	ret = usb6fire_fw_init(intf);
+	if (ret < 0)
+		return ret;
+	else if (ret == FW_NOT_READY) /* firmware update performed */
+		return 0;
+
+	/* if we are here, card can be registered in alsa. */
+	if (usb_set_interface(device, 0, 0) != 0) {
+		snd_printk(KERN_ERR PREFIX "can't set first interface.\n");
+		return -EIO;
+	}
+	ret = snd_card_create(index[regidx], id[regidx], THIS_MODULE,
+			sizeof(struct sfire_chip), &card);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "cannot create alsa card.\n");
+		return ret;
+	}
+	strcpy(card->driver, "6FireUSB");
+	strcpy(card->shortname, "TerraTec DMX6FireUSB");
+	sprintf(card->longname, "%s at %d:%d", card->shortname,
+			device->bus->busnum, device->devnum);
+	snd_card_set_dev(card, &intf->dev);
+
+	chip = card->private_data;
+	chips[regidx] = chip;
+	chip->dev = device;
+	chip->regidx = regidx;
+	chip->intf_count = 1;
+	chip->card = card;
+
+	ret = usb6fire_comm_init(chip);
+	if (ret < 0) {
+		usb6fire_chip_destroy(chip);
+		return ret;
+	}
+
+	ret = usb6fire_midi_init(chip);
+	if (ret < 0) {
+		usb6fire_chip_destroy(chip);
+		return ret;
+	}
+
+	ret = usb6fire_pcm_init(chip);
+	if (ret < 0) {
+		usb6fire_chip_destroy(chip);
+		return ret;
+	}
+
+	ret = usb6fire_control_init(chip);
+	if (ret < 0) {
+		usb6fire_chip_destroy(chip);
+		return ret;
+	}
+
+	ret = snd_card_register(card);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "cannot register card.");
+		usb6fire_chip_destroy(chip);
+		return ret;
+	}
+	usb_set_intfdata(intf, chip);
+	return 0;
+}
+
+static void usb6fire_chip_disconnect(struct usb_interface *intf)
+{
+	struct sfire_chip *chip;
+	struct snd_card *card;
+
+	chip = usb_get_intfdata(intf);
+	if (chip) { /* if !chip, fw upload has been performed */
+		card = chip->card;
+		chip->intf_count--;
+		if (!chip->intf_count) {
+			mutex_lock(&register_mutex);
+			devices[chip->regidx] = NULL;
+			chips[chip->regidx] = NULL;
+			mutex_unlock(&register_mutex);
+
+			chip->shutdown = true;
+			usb6fire_chip_abort(chip);
+			usb6fire_chip_destroy(chip);
+		}
+	}
+}
+
+static struct usb_device_id device_table[] = {
+	{
+		.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor = 0x0ccd,
+		.idProduct = 0x0080
+	},
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+static struct usb_driver driver = {
+	.name = "snd-usb-6fire",
+	.probe = usb6fire_chip_probe,
+	.disconnect = usb6fire_chip_disconnect,
+	.id_table = device_table,
+};
+
+static int __init usb6fire_chip_init(void)
+{
+	return usb_register(&driver);
+}
+
+static void __exit usb6fire_chip_cleanup(void)
+{
+	usb_deregister(&driver);
+}
+
+module_init(usb6fire_chip_init);
+module_exit(usb6fire_chip_cleanup);

+ 32 - 0
sound/usb/6fire/chip.h

@@ -0,0 +1,32 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef USB6FIRE_CHIP_H
+#define USB6FIRE_CHIP_H
+
+#include "common.h"
+
+struct sfire_chip {
+	struct usb_device *dev;
+	struct snd_card *card;
+	int intf_count; /* number of registered interfaces */
+	int regidx; /* index in module parameter arrays */
+	bool shutdown;
+
+	struct midi_runtime *midi;
+	struct pcm_runtime *pcm;
+	struct control_runtime *control;
+	struct comm_runtime *comm;
+};
+#endif /* USB6FIRE_CHIP_H */
+

+ 176 - 0
sound/usb/6fire/comm.c

@@ -0,0 +1,176 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Device communications
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "comm.h"
+#include "chip.h"
+#include "midi.h"
+
+enum {
+	COMM_EP = 1,
+	COMM_FPGA_EP = 2
+};
+
+static void usb6fire_comm_init_urb(struct comm_runtime *rt, struct urb *urb,
+		u8 *buffer, void *context, void(*handler)(struct urb *urb))
+{
+	usb_init_urb(urb);
+	urb->transfer_buffer = buffer;
+	urb->pipe = usb_sndintpipe(rt->chip->dev, COMM_EP);
+	urb->complete = handler;
+	urb->context = context;
+	urb->interval = 1;
+	urb->dev = rt->chip->dev;
+}
+
+static void usb6fire_comm_receiver_handler(struct urb *urb)
+{
+	struct comm_runtime *rt = urb->context;
+	struct midi_runtime *midi_rt = rt->chip->midi;
+
+	if (!urb->status) {
+		if (rt->receiver_buffer[0] == 0x10) /* midi in event */
+			if (midi_rt)
+				midi_rt->in_received(midi_rt,
+						rt->receiver_buffer + 2,
+						rt->receiver_buffer[1]);
+	}
+
+	if (!rt->chip->shutdown) {
+		urb->status = 0;
+		urb->actual_length = 0;
+		if (usb_submit_urb(urb, GFP_ATOMIC) < 0)
+			snd_printk(KERN_WARNING PREFIX
+					"comm data receiver aborted.\n");
+	}
+}
+
+static void usb6fire_comm_init_buffer(u8 *buffer, u8 id, u8 request,
+		u8 reg, u8 vl, u8 vh)
+{
+	buffer[0] = 0x01;
+	buffer[2] = request;
+	buffer[3] = id;
+	switch (request) {
+	case 0x02:
+		buffer[1] = 0x05; /* length (starting at buffer[2]) */
+		buffer[4] = reg;
+		buffer[5] = vl;
+		buffer[6] = vh;
+		break;
+
+	case 0x12:
+		buffer[1] = 0x0b; /* length (starting at buffer[2]) */
+		buffer[4] = 0x00;
+		buffer[5] = 0x18;
+		buffer[6] = 0x05;
+		buffer[7] = 0x00;
+		buffer[8] = 0x01;
+		buffer[9] = 0x00;
+		buffer[10] = 0x9e;
+		buffer[11] = reg;
+		buffer[12] = vl;
+		break;
+
+	case 0x20:
+	case 0x21:
+	case 0x22:
+		buffer[1] = 0x04;
+		buffer[4] = reg;
+		buffer[5] = vl;
+		break;
+	}
+}
+
+static int usb6fire_comm_send_buffer(u8 *buffer, struct usb_device *dev)
+{
+	int ret;
+	int actual_len;
+
+	ret = usb_interrupt_msg(dev, usb_sndintpipe(dev, COMM_EP),
+			buffer, buffer[1] + 2, &actual_len, HZ);
+	if (ret < 0)
+		return ret;
+	else if (actual_len != buffer[1] + 2)
+		return -EIO;
+	return 0;
+}
+
+static int usb6fire_comm_write8(struct comm_runtime *rt, u8 request,
+		u8 reg, u8 value)
+{
+	u8 buffer[13]; /* 13: maximum length of message */
+
+	usb6fire_comm_init_buffer(buffer, 0x00, request, reg, value, 0x00);
+	return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+}
+
+static int usb6fire_comm_write16(struct comm_runtime *rt, u8 request,
+		u8 reg, u8 vl, u8 vh)
+{
+	u8 buffer[13]; /* 13: maximum length of message */
+
+	usb6fire_comm_init_buffer(buffer, 0x00, request, reg, vl, vh);
+	return usb6fire_comm_send_buffer(buffer, rt->chip->dev);
+}
+
+int __devinit usb6fire_comm_init(struct sfire_chip *chip)
+{
+	struct comm_runtime *rt = kzalloc(sizeof(struct comm_runtime),
+			GFP_KERNEL);
+	struct urb *urb = &rt->receiver;
+	int ret;
+
+	if (!rt)
+		return -ENOMEM;
+
+	rt->serial = 1;
+	rt->chip = chip;
+	usb_init_urb(urb);
+	rt->init_urb = usb6fire_comm_init_urb;
+	rt->write8 = usb6fire_comm_write8;
+	rt->write16 = usb6fire_comm_write16;
+
+	/* submit an urb that receives communication data from device */
+	urb->transfer_buffer = rt->receiver_buffer;
+	urb->transfer_buffer_length = COMM_RECEIVER_BUFSIZE;
+	urb->pipe = usb_rcvintpipe(chip->dev, COMM_EP);
+	urb->dev = chip->dev;
+	urb->complete = usb6fire_comm_receiver_handler;
+	urb->context = rt;
+	urb->interval = 1;
+	ret = usb_submit_urb(urb, GFP_KERNEL);
+	if (ret < 0) {
+		kfree(rt);
+		snd_printk(KERN_ERR PREFIX "cannot create comm data receiver.");
+		return ret;
+	}
+	chip->comm = rt;
+	return 0;
+}
+
+void usb6fire_comm_abort(struct sfire_chip *chip)
+{
+	struct comm_runtime *rt = chip->comm;
+
+	if (rt)
+		usb_poison_urb(&rt->receiver);
+}
+
+void usb6fire_comm_destroy(struct sfire_chip *chip)
+{
+	kfree(chip->comm);
+	chip->comm = NULL;
+}

+ 44 - 0
sound/usb/6fire/comm.h

@@ -0,0 +1,44 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+#ifndef USB6FIRE_COMM_H
+#define USB6FIRE_COMM_H
+
+#include "common.h"
+
+enum /* settings for comm */
+{
+	COMM_RECEIVER_BUFSIZE = 64,
+};
+
+struct comm_runtime {
+	struct sfire_chip *chip;
+
+	struct urb receiver;
+	u8 receiver_buffer[COMM_RECEIVER_BUFSIZE];
+
+	u8 serial; /* urb serial */
+
+	void (*init_urb)(struct comm_runtime *rt, struct urb *urb, u8 *buffer,
+			void *context, void(*handler)(struct urb *urb));
+	/* writes control data to the device */
+	int (*write8)(struct comm_runtime *rt, u8 request, u8 reg, u8 value);
+	int (*write16)(struct comm_runtime *rt, u8 request, u8 reg,
+			u8 vh, u8 vl);
+};
+
+int __devinit usb6fire_comm_init(struct sfire_chip *chip);
+void usb6fire_comm_abort(struct sfire_chip *chip);
+void usb6fire_comm_destroy(struct sfire_chip *chip);
+#endif /* USB6FIRE_COMM_H */
+

+ 30 - 0
sound/usb/6fire/common.h

@@ -0,0 +1,30 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef USB6FIRE_COMMON_H
+#define USB6FIRE_COMMON_H
+
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <sound/core.h>
+
+#define PREFIX "6fire: "
+
+struct sfire_chip;
+struct midi_runtime;
+struct pcm_runtime;
+struct control_runtime;
+struct comm_runtime;
+#endif /* USB6FIRE_COMMON_H */
+

+ 275 - 0
sound/usb/6fire/control.c

@@ -0,0 +1,275 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Mixer control
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/interrupt.h>
+#include <sound/control.h>
+
+#include "control.h"
+#include "comm.h"
+#include "chip.h"
+
+static char *opt_coax_texts[2] = { "Optical", "Coax" };
+static char *line_phono_texts[2] = { "Line", "Phono" };
+
+/*
+ * calculated with $value\[i\] = 128 \cdot sqrt[3]{\frac{i}{128}}$
+ * this is done because the linear values cause rapid degredation
+ * of volume in the uppermost region.
+ */
+static const u8 log_volume_table[128] = {
+	0x00, 0x19, 0x20, 0x24, 0x28, 0x2b, 0x2e, 0x30, 0x32, 0x34,
+	0x36, 0x38, 0x3a, 0x3b, 0x3d, 0x3e, 0x40, 0x41, 0x42, 0x43,
+	0x44, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
+	0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56,
+	0x56, 0x57, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c,
+	0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62,
+	0x63, 0x63, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
+	0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c,
+	0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
+	0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75,
+	0x75, 0x76, 0x76, 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79,
+	0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c,
+	0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f };
+
+/*
+ * data that needs to be sent to device. sets up card internal stuff.
+ * values dumped from windows driver and filtered by trial'n'error.
+ */
+static const struct {
+	u8 type;
+	u8 reg;
+	u8 value;
+}
+init_data[] = {
+	{ 0x22, 0x00, 0x00 }, { 0x20, 0x00, 0x08 }, { 0x22, 0x01, 0x01 },
+	{ 0x20, 0x01, 0x08 }, { 0x22, 0x02, 0x00 }, { 0x20, 0x02, 0x08 },
+	{ 0x22, 0x03, 0x00 }, { 0x20, 0x03, 0x08 }, { 0x22, 0x04, 0x00 },
+	{ 0x20, 0x04, 0x08 }, { 0x22, 0x05, 0x01 }, { 0x20, 0x05, 0x08 },
+	{ 0x22, 0x04, 0x01 }, { 0x12, 0x04, 0x00 }, { 0x12, 0x05, 0x00 },
+	{ 0x12, 0x0d, 0x78 }, { 0x12, 0x21, 0x82 }, { 0x12, 0x22, 0x80 },
+	{ 0x12, 0x23, 0x00 }, { 0x12, 0x06, 0x02 }, { 0x12, 0x03, 0x00 },
+	{ 0x12, 0x02, 0x00 }, { 0x22, 0x03, 0x01 },
+	{ 0 } /* TERMINATING ENTRY */
+};
+
+static void usb6fire_control_master_vol_update(struct control_runtime *rt)
+{
+	struct comm_runtime *comm_rt = rt->chip->comm;
+	if (comm_rt) {
+		/* set volume */
+		comm_rt->write8(comm_rt, 0x12, 0x0f, 0x7f -
+				log_volume_table[rt->master_vol]);
+		 /* unmute */
+		comm_rt->write8(comm_rt, 0x12, 0x0e, 0x00);
+	}
+}
+
+static void usb6fire_control_line_phono_update(struct control_runtime *rt)
+{
+	struct comm_runtime *comm_rt = rt->chip->comm;
+	if (comm_rt) {
+		comm_rt->write8(comm_rt, 0x22, 0x02, rt->line_phono_switch);
+		comm_rt->write8(comm_rt, 0x21, 0x02, rt->line_phono_switch);
+	}
+}
+
+static void usb6fire_control_opt_coax_update(struct control_runtime *rt)
+{
+	struct comm_runtime *comm_rt = rt->chip->comm;
+	if (comm_rt) {
+		comm_rt->write8(comm_rt, 0x22, 0x00, rt->opt_coax_switch);
+		comm_rt->write8(comm_rt, 0x21, 0x00, rt->opt_coax_switch);
+	}
+}
+
+static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+	uinfo->count = 1;
+	uinfo->value.integer.min = 0;
+	uinfo->value.integer.max = 127;
+	return 0;
+}
+
+static int usb6fire_control_master_vol_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+	if (rt->master_vol != ucontrol->value.integer.value[0]) {
+		rt->master_vol = ucontrol->value.integer.value[0];
+		usb6fire_control_master_vol_update(rt);
+		changed = 1;
+	}
+	return changed;
+}
+
+static int usb6fire_control_master_vol_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.integer.value[0] = rt->master_vol;
+	return 0;
+}
+
+static int usb6fire_control_line_phono_info(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item > 1)
+		uinfo->value.enumerated.item = 1;
+	strcpy(uinfo->value.enumerated.name,
+			line_phono_texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int usb6fire_control_line_phono_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+	if (rt->line_phono_switch != ucontrol->value.integer.value[0]) {
+		rt->line_phono_switch = ucontrol->value.integer.value[0];
+		usb6fire_control_line_phono_update(rt);
+		changed = 1;
+	}
+	return changed;
+}
+
+static int usb6fire_control_line_phono_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.integer.value[0] = rt->line_phono_switch;
+	return 0;
+}
+
+static int usb6fire_control_opt_coax_info(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_info *uinfo)
+{
+	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+	uinfo->count = 1;
+	uinfo->value.enumerated.items = 2;
+	if (uinfo->value.enumerated.item > 1)
+		uinfo->value.enumerated.item = 1;
+	strcpy(uinfo->value.enumerated.name,
+			opt_coax_texts[uinfo->value.enumerated.item]);
+	return 0;
+}
+
+static int usb6fire_control_opt_coax_put(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	int changed = 0;
+
+	if (rt->opt_coax_switch != ucontrol->value.enumerated.item[0]) {
+		rt->opt_coax_switch = ucontrol->value.enumerated.item[0];
+		usb6fire_control_opt_coax_update(rt);
+		changed = 1;
+	}
+	return changed;
+}
+
+static int usb6fire_control_opt_coax_get(struct snd_kcontrol *kcontrol,
+		struct snd_ctl_elem_value *ucontrol)
+{
+	struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+	ucontrol->value.enumerated.item[0] = rt->opt_coax_switch;
+	return 0;
+}
+
+static struct __devinitdata snd_kcontrol_new elements[] = {
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Master Playback Volume",
+		.index = 0,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.info = usb6fire_control_master_vol_info,
+		.get = usb6fire_control_master_vol_get,
+		.put = usb6fire_control_master_vol_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Line/Phono Capture Route",
+		.index = 0,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.info = usb6fire_control_line_phono_info,
+		.get = usb6fire_control_line_phono_get,
+		.put = usb6fire_control_line_phono_put
+	},
+	{
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.name = "Opt/Coax Capture Route",
+		.index = 0,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.info = usb6fire_control_opt_coax_info,
+		.get = usb6fire_control_opt_coax_get,
+		.put = usb6fire_control_opt_coax_put
+	},
+	{}
+};
+
+int __devinit usb6fire_control_init(struct sfire_chip *chip)
+{
+	int i;
+	int ret;
+	struct control_runtime *rt = kzalloc(sizeof(struct control_runtime),
+			GFP_KERNEL);
+	struct comm_runtime *comm_rt = chip->comm;
+
+	if (!rt)
+		return -ENOMEM;
+
+	rt->chip = chip;
+
+	i = 0;
+	while (init_data[i].type) {
+		comm_rt->write8(comm_rt, init_data[i].type, init_data[i].reg,
+				init_data[i].value);
+		i++;
+	}
+
+	usb6fire_control_opt_coax_update(rt);
+	usb6fire_control_line_phono_update(rt);
+	usb6fire_control_master_vol_update(rt);
+
+	i = 0;
+	while (elements[i].name) {
+		ret = snd_ctl_add(chip->card, snd_ctl_new1(&elements[i], rt));
+		if (ret < 0) {
+			kfree(rt);
+			snd_printk(KERN_ERR PREFIX "cannot add control.\n");
+			return ret;
+		}
+		i++;
+	}
+
+	chip->control = rt;
+	return 0;
+}
+
+void usb6fire_control_abort(struct sfire_chip *chip)
+{}
+
+void usb6fire_control_destroy(struct sfire_chip *chip)
+{
+	kfree(chip->control);
+	chip->control = NULL;
+}

+ 37 - 0
sound/usb/6fire/control.h

@@ -0,0 +1,37 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef USB6FIRE_CONTROL_H
+#define USB6FIRE_CONTROL_H
+
+#include "common.h"
+
+enum {
+	CONTROL_MAX_ELEMENTS = 32
+};
+
+struct control_runtime {
+	struct sfire_chip *chip;
+
+	struct snd_kcontrol *element[CONTROL_MAX_ELEMENTS];
+	bool opt_coax_switch;
+	bool line_phono_switch;
+	u8 master_vol;
+};
+
+int __devinit usb6fire_control_init(struct sfire_chip *chip);
+void usb6fire_control_abort(struct sfire_chip *chip);
+void usb6fire_control_destroy(struct sfire_chip *chip);
+#endif /* USB6FIRE_CONTROL_H */
+

+ 426 - 0
sound/usb/6fire/firmware.c

@@ -0,0 +1,426 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Firmware loader
+ *
+ * Currently not working for all devices. To be able to use the device
+ * in linux, it is also possible to let the windows driver upload the firmware.
+ * For that, start the computer in windows and reboot.
+ * As long as the device is connected to the power supply, no firmware reload
+ * needs to be performed.
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/firmware.h>
+
+#include "firmware.h"
+#include "chip.h"
+
+MODULE_FIRMWARE("6fire/dmx6firel2.ihx");
+MODULE_FIRMWARE("6fire/dmx6fireap.ihx");
+MODULE_FIRMWARE("6fire/dmx6firecf.bin");
+
+enum {
+	FPGA_BUFSIZE = 512, FPGA_EP = 2
+};
+
+static const u8 BIT_REVERSE_TABLE[256] = {
+	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50,
+	0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8,
+	0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04,
+	0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4,
+	0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c,
+	0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82,
+	0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32,
+	0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46,
+	0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6,
+	0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e,
+	0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1,
+	0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71,
+	0xf1, 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99,
+	0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85, 0x45, 0xc5, 0x25,
+	0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d,
+	0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3,
+	0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b,
+	0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb,
+	0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67,
+	0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f,
+	0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f,
+	0xbf, 0x7f, 0xff };
+
+/*
+ * wMaxPacketSize of pcm endpoints.
+ * keep synced with rates_in_packet_size and rates_out_packet_size in pcm.c
+ * fpp: frames per isopacket
+ *
+ * CAUTION: keep sizeof <= buffer[] in usb6fire_fw_init
+ */
+static const u8 ep_w_max_packet_size[] = {
+	0xe4, 0x00, 0xe4, 0x00, /* alt 1: 228 EP2 and EP6 (7 fpp) */
+	0xa4, 0x01, 0xa4, 0x01, /* alt 2: 420 EP2 and EP6 (13 fpp)*/
+	0x94, 0x01, 0x5c, 0x02  /* alt 3: 404 EP2 and 604 EP6 (25 fpp) */
+};
+
+struct ihex_record {
+	u16 address;
+	u8 len;
+	u8 data[256];
+	char error; /* true if an error occured parsing this record */
+
+	u8 max_len; /* maximum record length in whole ihex */
+
+	/* private */
+	const char *txt_data;
+	unsigned int txt_length;
+	unsigned int txt_offset; /* current position in txt_data */
+};
+
+static u8 usb6fire_fw_ihex_nibble(const u8 n)
+{
+	if (n >= '0' && n <= '9')
+		return n - '0';
+	else if (n >= 'A' && n <= 'F')
+		return n - ('A' - 10);
+	else if (n >= 'a' && n <= 'f')
+		return n - ('a' - 10);
+	return 0;
+}
+
+static u8 usb6fire_fw_ihex_hex(const u8 *data, u8 *crc)
+{
+	u8 val = (usb6fire_fw_ihex_nibble(data[0]) << 4) |
+			usb6fire_fw_ihex_nibble(data[1]);
+	*crc += val;
+	return val;
+}
+
+/*
+ * returns true if record is available, false otherwise.
+ * iff an error occured, false will be returned and record->error will be true.
+ */
+static bool usb6fire_fw_ihex_next_record(struct ihex_record *record)
+{
+	u8 crc = 0;
+	u8 type;
+	int i;
+
+	record->error = false;
+
+	/* find begin of record (marked by a colon) */
+	while (record->txt_offset < record->txt_length
+			&& record->txt_data[record->txt_offset] != ':')
+		record->txt_offset++;
+	if (record->txt_offset == record->txt_length)
+		return false;
+
+	/* number of characters needed for len, addr and type entries */
+	record->txt_offset++;
+	if (record->txt_offset + 8 > record->txt_length) {
+		record->error = true;
+		return false;
+	}
+
+	record->len = usb6fire_fw_ihex_hex(record->txt_data +
+			record->txt_offset, &crc);
+	record->txt_offset += 2;
+	record->address = usb6fire_fw_ihex_hex(record->txt_data +
+			record->txt_offset, &crc) << 8;
+	record->txt_offset += 2;
+	record->address |= usb6fire_fw_ihex_hex(record->txt_data +
+			record->txt_offset, &crc);
+	record->txt_offset += 2;
+	type = usb6fire_fw_ihex_hex(record->txt_data +
+			record->txt_offset, &crc);
+	record->txt_offset += 2;
+
+	/* number of characters needed for data and crc entries */
+	if (record->txt_offset + 2 * (record->len + 1) > record->txt_length) {
+		record->error = true;
+		return false;
+	}
+	for (i = 0; i < record->len; i++) {
+		record->data[i] = usb6fire_fw_ihex_hex(record->txt_data
+				+ record->txt_offset, &crc);
+		record->txt_offset += 2;
+	}
+	usb6fire_fw_ihex_hex(record->txt_data + record->txt_offset, &crc);
+	if (crc) {
+		record->error = true;
+		return false;
+	}
+
+	if (type == 1 || !record->len) /* eof */
+		return false;
+	else if (type == 0)
+		return true;
+	else {
+		record->error = true;
+		return false;
+	}
+}
+
+static int usb6fire_fw_ihex_init(const struct firmware *fw,
+		struct ihex_record *record)
+{
+	record->txt_data = fw->data;
+	record->txt_length = fw->size;
+	record->txt_offset = 0;
+	record->max_len = 0;
+	/* read all records, if loop ends, record->error indicates,
+	 * whether ihex is valid. */
+	while (usb6fire_fw_ihex_next_record(record))
+		record->max_len = max(record->len, record->max_len);
+	if (record->error)
+		return -EINVAL;
+	record->txt_offset = 0;
+	return 0;
+}
+
+static int usb6fire_fw_ezusb_write(struct usb_device *device,
+		int type, int value, char *data, int len)
+{
+	int ret;
+
+	ret = usb_control_msg(device, usb_sndctrlpipe(device, 0), type,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			value, 0, data, len, HZ);
+	if (ret < 0)
+		return ret;
+	else if (ret != len)
+		return -EIO;
+	return 0;
+}
+
+static int usb6fire_fw_ezusb_read(struct usb_device *device,
+		int type, int value, char *data, int len)
+{
+	int ret = usb_control_msg(device, usb_rcvctrlpipe(device, 0), type,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, value,
+			0, data, len, HZ);
+	if (ret < 0)
+		return ret;
+	else if (ret != len)
+		return -EIO;
+	return 0;
+}
+
+static int usb6fire_fw_fpga_write(struct usb_device *device,
+		char *data, int len)
+{
+	int actual_len;
+	int ret;
+
+	ret = usb_bulk_msg(device, usb_sndbulkpipe(device, FPGA_EP), data, len,
+			&actual_len, HZ);
+	if (ret < 0)
+		return ret;
+	else if (actual_len != len)
+		return -EIO;
+	return 0;
+}
+
+static int usb6fire_fw_ezusb_upload(
+		struct usb_interface *intf, const char *fwname,
+		unsigned int postaddr, u8 *postdata, unsigned int postlen)
+{
+	int ret;
+	u8 data;
+	struct usb_device *device = interface_to_usbdev(intf);
+	const struct firmware *fw = 0;
+	struct ihex_record *rec = kmalloc(sizeof(struct ihex_record),
+			GFP_KERNEL);
+
+	if (!rec)
+		return -ENOMEM;
+
+	ret = request_firmware(&fw, fwname, &device->dev);
+	if (ret < 0) {
+		kfree(rec);
+		snd_printk(KERN_ERR PREFIX "error requesting ezusb "
+				"firmware %s.\n", fwname);
+		return ret;
+	}
+	ret = usb6fire_fw_ihex_init(fw, rec);
+	if (ret < 0) {
+		kfree(rec);
+		snd_printk(KERN_ERR PREFIX "error validating ezusb "
+				"firmware %s.\n", fwname);
+		return ret;
+	}
+	/* upload firmware image */
+	data = 0x01; /* stop ezusb cpu */
+	ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1);
+	if (ret < 0) {
+		kfree(rec);
+		release_firmware(fw);
+		snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
+				"firmware %s: begin message.\n", fwname);
+		return ret;
+	}
+
+	while (usb6fire_fw_ihex_next_record(rec)) { /* write firmware */
+		ret = usb6fire_fw_ezusb_write(device, 0xa0, rec->address,
+				rec->data, rec->len);
+		if (ret < 0) {
+			kfree(rec);
+			release_firmware(fw);
+			snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
+					"firmware %s: data urb.\n", fwname);
+			return ret;
+		}
+	}
+
+	release_firmware(fw);
+	kfree(rec);
+	if (postdata) { /* write data after firmware has been uploaded */
+		ret = usb6fire_fw_ezusb_write(device, 0xa0, postaddr,
+				postdata, postlen);
+		if (ret < 0) {
+			snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
+					"firmware %s: post urb.\n", fwname);
+			return ret;
+		}
+	}
+
+	data = 0x00; /* resume ezusb cpu */
+	ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1);
+	if (ret < 0) {
+		release_firmware(fw);
+		snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
+				"firmware %s: end message.\n", fwname);
+		return ret;
+	}
+	return 0;
+}
+
+static int usb6fire_fw_fpga_upload(
+		struct usb_interface *intf, const char *fwname)
+{
+	int ret;
+	int i;
+	struct usb_device *device = interface_to_usbdev(intf);
+	u8 *buffer = kmalloc(FPGA_BUFSIZE, GFP_KERNEL);
+	const char *c;
+	const char *end;
+	const struct firmware *fw;
+
+	if (!buffer)
+		return -ENOMEM;
+
+	ret = request_firmware(&fw, fwname, &device->dev);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "unable to get fpga firmware %s.\n",
+				fwname);
+		kfree(buffer);
+		return -EIO;
+	}
+
+	c = fw->data;
+	end = fw->data + fw->size;
+
+	ret = usb6fire_fw_ezusb_write(device, 8, 0, NULL, 0);
+	if (ret < 0) {
+		kfree(buffer);
+		release_firmware(fw);
+		snd_printk(KERN_ERR PREFIX "unable to upload fpga firmware: "
+				"begin urb.\n");
+		return ret;
+	}
+
+	while (c != end) {
+		for (i = 0; c != end && i < FPGA_BUFSIZE; i++, c++)
+			buffer[i] = BIT_REVERSE_TABLE[(u8) *c];
+
+		ret = usb6fire_fw_fpga_write(device, buffer, i);
+		if (ret < 0) {
+			release_firmware(fw);
+			kfree(buffer);
+			snd_printk(KERN_ERR PREFIX "unable to upload fpga "
+					"firmware: fw urb.\n");
+			return ret;
+		}
+	}
+	release_firmware(fw);
+	kfree(buffer);
+
+	ret = usb6fire_fw_ezusb_write(device, 9, 0, NULL, 0);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "unable to upload fpga firmware: "
+				"end urb.\n");
+		return ret;
+	}
+	return 0;
+}
+
+int usb6fire_fw_init(struct usb_interface *intf)
+{
+	int i;
+	int ret;
+	struct usb_device *device = interface_to_usbdev(intf);
+	/* buffer: 8 receiving bytes from device and
+	 * sizeof(EP_W_MAX_PACKET_SIZE) bytes for non-const copy */
+	u8 buffer[12];
+
+	ret = usb6fire_fw_ezusb_read(device, 1, 0, buffer, 8);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "unable to receive device "
+				"firmware state.\n");
+		return ret;
+	}
+	if (buffer[0] != 0xeb || buffer[1] != 0xaa || buffer[2] != 0x55
+			|| buffer[4] != 0x03 || buffer[5] != 0x01 || buffer[7]
+			!= 0x00) {
+		snd_printk(KERN_ERR PREFIX "unknown device firmware state "
+				"received from device: ");
+		for (i = 0; i < 8; i++)
+			snd_printk("%02x ", buffer[i]);
+		snd_printk("\n");
+		return -EIO;
+	}
+	/* do we need fpga loader ezusb firmware? */
+	if (buffer[3] == 0x01 && buffer[6] == 0x19) {
+		ret = usb6fire_fw_ezusb_upload(intf,
+				"6fire/dmx6firel2.ihx", 0, NULL, 0);
+		if (ret < 0)
+			return ret;
+		return FW_NOT_READY;
+	}
+	/* do we need fpga firmware and application ezusb firmware? */
+	else if (buffer[3] == 0x02 && buffer[6] == 0x0b) {
+		ret = usb6fire_fw_fpga_upload(intf, "6fire/dmx6firecf.bin");
+		if (ret < 0)
+			return ret;
+		memcpy(buffer, ep_w_max_packet_size,
+				sizeof(ep_w_max_packet_size));
+		ret = usb6fire_fw_ezusb_upload(intf, "6fire/dmx6fireap.ihx",
+				0x0003,	buffer, sizeof(ep_w_max_packet_size));
+		if (ret < 0)
+			return ret;
+		return FW_NOT_READY;
+	}
+	/* all fw loaded? */
+	else if (buffer[3] == 0x03 && buffer[6] == 0x0b)
+		return 0;
+	/* unknown data? */
+	else {
+		snd_printk(KERN_ERR PREFIX "unknown device firmware state "
+				"received from device: ");
+		for (i = 0; i < 8; i++)
+			snd_printk("%02x ", buffer[i]);
+		snd_printk("\n");
+		return -EIO;
+	}
+	return 0;
+}
+

+ 27 - 0
sound/usb/6fire/firmware.h

@@ -0,0 +1,27 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Author: Torsten Schenk
+ * Created: Jan 01, 2011
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef USB6FIRE_FIRMWARE_H
+#define USB6FIRE_FIRMWARE_H
+
+#include "common.h"
+
+enum /* firmware state of device */
+{
+	FW_READY = 0,
+	FW_NOT_READY = 1
+};
+
+int __devinit usb6fire_fw_init(struct usb_interface *intf);
+#endif /* USB6FIRE_FIRMWARE_H */
+

+ 203 - 0
sound/usb/6fire/midi.c

@@ -0,0 +1,203 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Rawmidi driver
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <sound/rawmidi.h>
+
+#include "midi.h"
+#include "chip.h"
+#include "comm.h"
+
+static void usb6fire_midi_out_handler(struct urb *urb)
+{
+	struct midi_runtime *rt = urb->context;
+	int ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rt->out_lock, flags);
+
+	if (rt->out) {
+		ret = snd_rawmidi_transmit(rt->out, rt->out_buffer + 4,
+				MIDI_BUFSIZE - 4);
+		if (ret > 0) { /* more data available, send next packet */
+			rt->out_buffer[1] = ret + 2;
+			rt->out_buffer[3] = rt->out_serial++;
+			urb->transfer_buffer_length = ret + 4;
+
+			ret = usb_submit_urb(urb, GFP_ATOMIC);
+			if (ret < 0)
+				snd_printk(KERN_ERR PREFIX "midi out urb "
+						"submit failed: %d\n", ret);
+		} else /* no more data to transmit */
+			rt->out = NULL;
+	}
+	spin_unlock_irqrestore(&rt->out_lock, flags);
+}
+
+static void usb6fire_midi_in_received(
+		struct midi_runtime *rt, u8 *data, int length)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rt->in_lock, flags);
+	if (rt->in)
+		snd_rawmidi_receive(rt->in, data, length);
+	spin_unlock_irqrestore(&rt->in_lock, flags);
+}
+
+static int usb6fire_midi_out_open(struct snd_rawmidi_substream *alsa_sub)
+{
+	return 0;
+}
+
+static int usb6fire_midi_out_close(struct snd_rawmidi_substream *alsa_sub)
+{
+	return 0;
+}
+
+static void usb6fire_midi_out_trigger(
+		struct snd_rawmidi_substream *alsa_sub, int up)
+{
+	struct midi_runtime *rt = alsa_sub->rmidi->private_data;
+	struct urb *urb = &rt->out_urb;
+	__s8 ret;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rt->out_lock, flags);
+	if (up) { /* start transfer */
+		if (rt->out) { /* we are already transmitting so just return */
+			spin_unlock_irqrestore(&rt->out_lock, flags);
+			return;
+		}
+
+		ret = snd_rawmidi_transmit(alsa_sub, rt->out_buffer + 4,
+				MIDI_BUFSIZE - 4);
+		if (ret > 0) {
+			rt->out_buffer[1] = ret + 2;
+			rt->out_buffer[3] = rt->out_serial++;
+			urb->transfer_buffer_length = ret + 4;
+
+			ret = usb_submit_urb(urb, GFP_ATOMIC);
+			if (ret < 0)
+				snd_printk(KERN_ERR PREFIX "midi out urb "
+						"submit failed: %d\n", ret);
+			else
+				rt->out = alsa_sub;
+		}
+	} else if (rt->out == alsa_sub)
+		rt->out = NULL;
+	spin_unlock_irqrestore(&rt->out_lock, flags);
+}
+
+static void usb6fire_midi_out_drain(struct snd_rawmidi_substream *alsa_sub)
+{
+	struct midi_runtime *rt = alsa_sub->rmidi->private_data;
+	int retry = 0;
+
+	while (rt->out && retry++ < 100)
+		msleep(10);
+}
+
+static int usb6fire_midi_in_open(struct snd_rawmidi_substream *alsa_sub)
+{
+	return 0;
+}
+
+static int usb6fire_midi_in_close(struct snd_rawmidi_substream *alsa_sub)
+{
+	return 0;
+}
+
+static void usb6fire_midi_in_trigger(
+		struct snd_rawmidi_substream *alsa_sub, int up)
+{
+	struct midi_runtime *rt = alsa_sub->rmidi->private_data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rt->in_lock, flags);
+	if (up)
+		rt->in = alsa_sub;
+	else
+		rt->in = NULL;
+	spin_unlock_irqrestore(&rt->in_lock, flags);
+}
+
+static struct snd_rawmidi_ops out_ops = {
+	.open = usb6fire_midi_out_open,
+	.close = usb6fire_midi_out_close,
+	.trigger = usb6fire_midi_out_trigger,
+	.drain = usb6fire_midi_out_drain
+};
+
+static struct snd_rawmidi_ops in_ops = {
+	.open = usb6fire_midi_in_open,
+	.close = usb6fire_midi_in_close,
+	.trigger = usb6fire_midi_in_trigger
+};
+
+int __devinit usb6fire_midi_init(struct sfire_chip *chip)
+{
+	int ret;
+	struct midi_runtime *rt = kzalloc(sizeof(struct midi_runtime),
+			GFP_KERNEL);
+	struct comm_runtime *comm_rt = chip->comm;
+
+	if (!rt)
+		return -ENOMEM;
+
+	rt->chip = chip;
+	rt->in_received = usb6fire_midi_in_received;
+	rt->out_buffer[0] = 0x80; /* 'send midi' command */
+	rt->out_buffer[1] = 0x00; /* size of data */
+	rt->out_buffer[2] = 0x00; /* always 0 */
+	spin_lock_init(&rt->in_lock);
+	spin_lock_init(&rt->out_lock);
+
+	comm_rt->init_urb(comm_rt, &rt->out_urb, rt->out_buffer, rt,
+			usb6fire_midi_out_handler);
+
+	ret = snd_rawmidi_new(chip->card, "6FireUSB", 0, 1, 1, &rt->instance);
+	if (ret < 0) {
+		kfree(rt);
+		snd_printk(KERN_ERR PREFIX "unable to create midi.\n");
+		return ret;
+	}
+	rt->instance->private_data = rt;
+	strcpy(rt->instance->name, "DMX6FireUSB MIDI");
+	rt->instance->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
+			SNDRV_RAWMIDI_INFO_INPUT |
+			SNDRV_RAWMIDI_INFO_DUPLEX;
+	snd_rawmidi_set_ops(rt->instance, SNDRV_RAWMIDI_STREAM_OUTPUT,
+			&out_ops);
+	snd_rawmidi_set_ops(rt->instance, SNDRV_RAWMIDI_STREAM_INPUT,
+			&in_ops);
+
+	chip->midi = rt;
+	return 0;
+}
+
+void usb6fire_midi_abort(struct sfire_chip *chip)
+{
+	struct midi_runtime *rt = chip->midi;
+
+	if (rt)
+		usb_poison_urb(&rt->out_urb);
+}
+
+void usb6fire_midi_destroy(struct sfire_chip *chip)
+{
+	kfree(chip->midi);
+	chip->midi = NULL;
+}

+ 46 - 0
sound/usb/6fire/midi.h

@@ -0,0 +1,46 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef USB6FIRE_MIDI_H
+#define USB6FIRE_MIDI_H
+
+#include "common.h"
+
+enum {
+	MIDI_BUFSIZE = 64
+};
+
+struct midi_runtime {
+	struct sfire_chip *chip;
+	struct snd_rawmidi *instance;
+
+	struct snd_rawmidi_substream *in;
+	char in_active;
+
+	spinlock_t in_lock;
+	spinlock_t out_lock;
+	struct snd_rawmidi_substream *out;
+	struct urb out_urb;
+	u8 out_serial; /* serial number of out packet */
+	u8 out_buffer[MIDI_BUFSIZE];
+	int buffer_offset;
+
+	void (*in_received)(struct midi_runtime *rt, u8 *data, int length);
+};
+
+int __devinit usb6fire_midi_init(struct sfire_chip *chip);
+void usb6fire_midi_abort(struct sfire_chip *chip);
+void usb6fire_midi_destroy(struct sfire_chip *chip);
+#endif /* USB6FIRE_MIDI_H */
+

+ 688 - 0
sound/usb/6fire/pcm.c

@@ -0,0 +1,688 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * PCM driver
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include "pcm.h"
+#include "chip.h"
+#include "comm.h"
+
+enum {
+	OUT_N_CHANNELS = 6, IN_N_CHANNELS = 4
+};
+
+/* keep next two synced with
+ * FW_EP_W_MAX_PACKET_SIZE[] and RATES_MAX_PACKET_SIZE */
+static const int rates_in_packet_size[] = { 228, 228, 420, 420, 404, 404 };
+static const int rates_out_packet_size[] = { 228, 228, 420, 420, 604, 604 };
+static const int rates[] = { 44100, 48000, 88200, 96000, 176400, 192000 };
+static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 };
+static const int rates_alsaid[] = {
+	SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_48000,
+	SNDRV_PCM_RATE_88200, SNDRV_PCM_RATE_96000,
+	SNDRV_PCM_RATE_176400, SNDRV_PCM_RATE_192000 };
+
+/* values to write to soundcard register for all samplerates */
+static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
+static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00};
+
+enum { /* settings for pcm */
+	OUT_EP = 6, IN_EP = 2, MAX_BUFSIZE = 128 * 1024
+};
+
+enum { /* pcm streaming states */
+	STREAM_DISABLED, /* no pcm streaming */
+	STREAM_STARTING, /* pcm streaming requested, waiting to become ready */
+	STREAM_RUNNING, /* pcm streaming running */
+	STREAM_STOPPING
+};
+
+enum { /* pcm sample rates (also index into RATES_XXX[]) */
+	RATE_44KHZ,
+	RATE_48KHZ,
+	RATE_88KHZ,
+	RATE_96KHZ,
+	RATE_176KHZ,
+	RATE_192KHZ
+};
+
+static const struct snd_pcm_hardware pcm_hw = {
+	.info = SNDRV_PCM_INFO_MMAP |
+		SNDRV_PCM_INFO_INTERLEAVED |
+		SNDRV_PCM_INFO_BLOCK_TRANSFER |
+		SNDRV_PCM_INFO_MMAP_VALID |
+		SNDRV_PCM_INFO_BATCH,
+
+	.formats = SNDRV_PCM_FMTBIT_S24_LE,
+
+	.rates = SNDRV_PCM_RATE_44100 |
+		SNDRV_PCM_RATE_48000 |
+		SNDRV_PCM_RATE_88200 |
+		SNDRV_PCM_RATE_96000 |
+		SNDRV_PCM_RATE_176400 |
+		SNDRV_PCM_RATE_192000,
+
+	.rate_min = 44100,
+	.rate_max = 192000,
+	.channels_min = 1,
+	.channels_max = 0, /* set in pcm_open, depending on capture/playback */
+	.buffer_bytes_max = MAX_BUFSIZE,
+	.period_bytes_min = PCM_N_PACKETS_PER_URB * (PCM_MAX_PACKET_SIZE - 4),
+	.period_bytes_max = MAX_BUFSIZE,
+	.periods_min = 2,
+	.periods_max = 1024
+};
+
+static int usb6fire_pcm_set_rate(struct pcm_runtime *rt)
+{
+	int ret;
+	struct usb_device *device = rt->chip->dev;
+	struct comm_runtime *comm_rt = rt->chip->comm;
+
+	if (rt->rate >= ARRAY_SIZE(rates))
+		return -EINVAL;
+	/* disable streaming */
+	ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x00);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "error stopping streaming while "
+				"setting samplerate %d.\n", rates[rt->rate]);
+		return ret;
+	}
+
+	ret = usb_set_interface(device, 1, rates_altsetting[rt->rate]);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "error setting interface "
+				"altsetting %d for samplerate %d.\n",
+				rates_altsetting[rt->rate], rates[rt->rate]);
+		return ret;
+	}
+
+	/* set soundcard clock */
+	ret = comm_rt->write16(comm_rt, 0x02, 0x01, rates_6fire_vl[rt->rate],
+			rates_6fire_vh[rt->rate]);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "error setting samplerate %d.\n",
+				rates[rt->rate]);
+		return ret;
+	}
+
+	/* enable analog inputs and outputs
+	 * (one bit per stereo-channel) */
+	ret = comm_rt->write16(comm_rt, 0x02, 0x02,
+			(1 << (OUT_N_CHANNELS / 2)) - 1,
+			(1 << (IN_N_CHANNELS / 2)) - 1);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "error initializing analog channels "
+				"while setting samplerate %d.\n",
+				rates[rt->rate]);
+		return ret;
+	}
+	/* disable digital inputs and outputs */
+	ret = comm_rt->write16(comm_rt, 0x02, 0x03, 0x00, 0x00);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "error initializing digital "
+				"channels while setting samplerate %d.\n",
+				rates[rt->rate]);
+		return ret;
+	}
+
+	ret = comm_rt->write16(comm_rt, 0x02, 0x00, 0x00, 0x01);
+	if (ret < 0) {
+		snd_printk(KERN_ERR PREFIX "error starting streaming while "
+				"setting samplerate %d.\n", rates[rt->rate]);
+		return ret;
+	}
+
+	rt->in_n_analog = IN_N_CHANNELS;
+	rt->out_n_analog = OUT_N_CHANNELS;
+	rt->in_packet_size = rates_in_packet_size[rt->rate];
+	rt->out_packet_size = rates_out_packet_size[rt->rate];
+	return 0;
+}
+
+static struct pcm_substream *usb6fire_pcm_get_substream(
+		struct snd_pcm_substream *alsa_sub)
+{
+	struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
+
+	if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
+		return &rt->playback;
+	else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE)
+		return &rt->capture;
+	snd_printk(KERN_ERR PREFIX "error getting pcm substream slot.\n");
+	return NULL;
+}
+
+/* call with stream_mutex locked */
+static void usb6fire_pcm_stream_stop(struct pcm_runtime *rt)
+{
+	int i;
+
+	if (rt->stream_state != STREAM_DISABLED) {
+		for (i = 0; i < PCM_N_URBS; i++) {
+			usb_kill_urb(&rt->in_urbs[i].instance);
+			usb_kill_urb(&rt->out_urbs[i].instance);
+		}
+		rt->stream_state = STREAM_DISABLED;
+	}
+}
+
+/* call with stream_mutex locked */
+static int usb6fire_pcm_stream_start(struct pcm_runtime *rt)
+{
+	int ret;
+	int i;
+	int k;
+	struct usb_iso_packet_descriptor *packet;
+
+	if (rt->stream_state == STREAM_DISABLED) {
+		/* submit our in urbs */
+		rt->stream_wait_cond = false;
+		rt->stream_state = STREAM_STARTING;
+		for (i = 0; i < PCM_N_URBS; i++) {
+			for (k = 0; k < PCM_N_PACKETS_PER_URB; k++) {
+				packet = &rt->in_urbs[i].packets[k];
+				packet->offset = k * rt->in_packet_size;
+				packet->length = rt->in_packet_size;
+				packet->actual_length = 0;
+				packet->status = 0;
+			}
+			ret = usb_submit_urb(&rt->in_urbs[i].instance,
+					GFP_ATOMIC);
+			if (ret) {
+				usb6fire_pcm_stream_stop(rt);
+				return ret;
+			}
+		}
+
+		/* wait for first out urb to return (sent in in urb handler) */
+		wait_event_timeout(rt->stream_wait_queue, rt->stream_wait_cond,
+				HZ);
+		if (rt->stream_wait_cond)
+			rt->stream_state = STREAM_RUNNING;
+		else {
+			usb6fire_pcm_stream_stop(rt);
+			return -EIO;
+		}
+	}
+	return 0;
+}
+
+/* call with substream locked */
+static void usb6fire_pcm_capture(struct pcm_substream *sub, struct pcm_urb *urb)
+{
+	int i;
+	int frame;
+	int frame_count;
+	unsigned int total_length = 0;
+	struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance);
+	struct snd_pcm_runtime *alsa_rt = sub->instance->runtime;
+	u32 *src = (u32 *) urb->buffer;
+	u32 *dest = (u32 *) (alsa_rt->dma_area + sub->dma_off
+			* (alsa_rt->frame_bits >> 3));
+	u32 *dest_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size
+			* (alsa_rt->frame_bits >> 3));
+	int bytes_per_frame = alsa_rt->channels << 2;
+
+	for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
+		/* at least 4 header bytes for valid packet.
+		 * after that: 32 bits per sample for analog channels */
+		if (urb->packets[i].actual_length > 4)
+			frame_count = (urb->packets[i].actual_length - 4)
+					/ (rt->in_n_analog << 2);
+		else
+			frame_count = 0;
+
+		src = (u32 *) (urb->buffer + total_length);
+		src++; /* skip leading 4 bytes of every packet */
+		total_length += urb->packets[i].length;
+		for (frame = 0; frame < frame_count; frame++) {
+			memcpy(dest, src, bytes_per_frame);
+			dest += alsa_rt->channels;
+			src += rt->in_n_analog;
+			sub->dma_off++;
+			sub->period_off++;
+			if (dest == dest_end) {
+				sub->dma_off = 0;
+				dest = (u32 *) alsa_rt->dma_area;
+			}
+		}
+	}
+}
+
+/* call with substream locked */
+static void usb6fire_pcm_playback(struct pcm_substream *sub,
+		struct pcm_urb *urb)
+{
+	int i;
+	int frame;
+	int frame_count;
+	struct pcm_runtime *rt = snd_pcm_substream_chip(sub->instance);
+	struct snd_pcm_runtime *alsa_rt = sub->instance->runtime;
+	u32 *src = (u32 *) (alsa_rt->dma_area + sub->dma_off
+			* (alsa_rt->frame_bits >> 3));
+	u32 *src_end = (u32 *) (alsa_rt->dma_area + alsa_rt->buffer_size
+			* (alsa_rt->frame_bits >> 3));
+	u32 *dest = (u32 *) urb->buffer;
+	int bytes_per_frame = alsa_rt->channels << 2;
+
+	for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
+		/* at least 4 header bytes for valid packet.
+		 * after that: 32 bits per sample for analog channels */
+		if (urb->packets[i].length > 4)
+			frame_count = (urb->packets[i].length - 4)
+					/ (rt->out_n_analog << 2);
+		else
+			frame_count = 0;
+		dest++; /* skip leading 4 bytes of every frame */
+		for (frame = 0; frame < frame_count; frame++) {
+			memcpy(dest, src, bytes_per_frame);
+			src += alsa_rt->channels;
+			dest += rt->out_n_analog;
+			sub->dma_off++;
+			sub->period_off++;
+			if (src == src_end) {
+				src = (u32 *) alsa_rt->dma_area;
+				sub->dma_off = 0;
+			}
+		}
+	}
+}
+
+static void usb6fire_pcm_in_urb_handler(struct urb *usb_urb)
+{
+	struct pcm_urb *in_urb = usb_urb->context;
+	struct pcm_urb *out_urb = in_urb->peer;
+	struct pcm_runtime *rt = in_urb->chip->pcm;
+	struct pcm_substream *sub;
+	unsigned long flags;
+	int total_length = 0;
+	int frame_count;
+	int frame;
+	int channel;
+	int i;
+	u8 *dest;
+
+	if (usb_urb->status || rt->panic || rt->stream_state == STREAM_STOPPING)
+		return;
+	for (i = 0; i < PCM_N_PACKETS_PER_URB; i++)
+		if (in_urb->packets[i].status) {
+			rt->panic = true;
+			return;
+		}
+
+	if (rt->stream_state == STREAM_DISABLED) {
+		snd_printk(KERN_ERR PREFIX "internal error: "
+				"stream disabled in in-urb handler.\n");
+		return;
+	}
+
+	/* receive our capture data */
+	sub = &rt->capture;
+	spin_lock_irqsave(&sub->lock, flags);
+	if (sub->active) {
+		usb6fire_pcm_capture(sub, in_urb);
+		if (sub->period_off >= sub->instance->runtime->period_size) {
+			sub->period_off %= sub->instance->runtime->period_size;
+			spin_unlock_irqrestore(&sub->lock, flags);
+			snd_pcm_period_elapsed(sub->instance);
+		} else
+			spin_unlock_irqrestore(&sub->lock, flags);
+	} else
+		spin_unlock_irqrestore(&sub->lock, flags);
+
+	/* setup out urb structure */
+	for (i = 0; i < PCM_N_PACKETS_PER_URB; i++) {
+		out_urb->packets[i].offset = total_length;
+		out_urb->packets[i].length = (in_urb->packets[i].actual_length
+				- 4) / (rt->in_n_analog << 2)
+				* (rt->out_n_analog << 2) + 4;
+		out_urb->packets[i].status = 0;
+		total_length += out_urb->packets[i].length;
+	}
+	memset(out_urb->buffer, 0, total_length);
+
+	/* now send our playback data (if a free out urb was found) */
+	sub = &rt->playback;
+	spin_lock_irqsave(&sub->lock, flags);
+	if (sub->active) {
+		usb6fire_pcm_playback(sub, out_urb);
+		if (sub->period_off >= sub->instance->runtime->period_size) {
+			sub->period_off %= sub->instance->runtime->period_size;
+			spin_unlock_irqrestore(&sub->lock, flags);
+			snd_pcm_period_elapsed(sub->instance);
+		} else
+			spin_unlock_irqrestore(&sub->lock, flags);
+	} else
+		spin_unlock_irqrestore(&sub->lock, flags);
+
+	/* setup the 4th byte of each sample (0x40 for analog channels) */
+	dest = out_urb->buffer;
+	for (i = 0; i < PCM_N_PACKETS_PER_URB; i++)
+		if (out_urb->packets[i].length >= 4) {
+			frame_count = (out_urb->packets[i].length - 4)
+					/ (rt->out_n_analog << 2);
+			*(dest++) = 0xaa;
+			*(dest++) = 0xaa;
+			*(dest++) = frame_count;
+			*(dest++) = 0x00;
+			for (frame = 0; frame < frame_count; frame++)
+				for (channel = 0;
+						channel < rt->out_n_analog;
+						channel++) {
+					dest += 3; /* skip sample data */
+					*(dest++) = 0x40;
+				}
+		}
+	usb_submit_urb(&out_urb->instance, GFP_ATOMIC);
+	usb_submit_urb(&in_urb->instance, GFP_ATOMIC);
+}
+
+static void usb6fire_pcm_out_urb_handler(struct urb *usb_urb)
+{
+	struct pcm_urb *urb = usb_urb->context;
+	struct pcm_runtime *rt = urb->chip->pcm;
+
+	if (rt->stream_state == STREAM_STARTING) {
+		rt->stream_wait_cond = true;
+		wake_up(&rt->stream_wait_queue);
+	}
+}
+
+static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub)
+{
+	struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
+	struct pcm_substream *sub = NULL;
+	struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
+
+	if (rt->panic)
+		return -EPIPE;
+
+	mutex_lock(&rt->stream_mutex);
+	alsa_rt->hw = pcm_hw;
+
+	if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+		if (rt->rate >= 0)
+			alsa_rt->hw.rates = rates_alsaid[rt->rate];
+		alsa_rt->hw.channels_max = OUT_N_CHANNELS;
+		sub = &rt->playback;
+	} else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE) {
+		if (rt->rate >= 0)
+			alsa_rt->hw.rates = rates_alsaid[rt->rate];
+		alsa_rt->hw.channels_max = IN_N_CHANNELS;
+		sub = &rt->capture;
+	}
+
+	if (!sub) {
+		mutex_unlock(&rt->stream_mutex);
+		snd_printk(KERN_ERR PREFIX "invalid stream type.\n");
+		return -EINVAL;
+	}
+
+	sub->instance = alsa_sub;
+	sub->active = false;
+	mutex_unlock(&rt->stream_mutex);
+	return 0;
+}
+
+static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub)
+{
+	struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
+	struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
+	unsigned long flags;
+
+	if (rt->panic)
+		return 0;
+
+	mutex_lock(&rt->stream_mutex);
+	if (sub) {
+		/* deactivate substream */
+		spin_lock_irqsave(&sub->lock, flags);
+		sub->instance = NULL;
+		sub->active = false;
+		spin_unlock_irqrestore(&sub->lock, flags);
+
+		/* all substreams closed? if so, stop streaming */
+		if (!rt->playback.instance && !rt->capture.instance) {
+			usb6fire_pcm_stream_stop(rt);
+			rt->rate = -1;
+		}
+	}
+	mutex_unlock(&rt->stream_mutex);
+	return 0;
+}
+
+static int usb6fire_pcm_hw_params(struct snd_pcm_substream *alsa_sub,
+		struct snd_pcm_hw_params *hw_params)
+{
+	return snd_pcm_lib_malloc_pages(alsa_sub,
+			params_buffer_bytes(hw_params));
+}
+
+static int usb6fire_pcm_hw_free(struct snd_pcm_substream *alsa_sub)
+{
+	return snd_pcm_lib_free_pages(alsa_sub);
+}
+
+static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
+{
+	struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
+	struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
+	struct snd_pcm_runtime *alsa_rt = alsa_sub->runtime;
+	int i;
+	int ret;
+
+	if (rt->panic)
+		return -EPIPE;
+	if (!sub)
+		return -ENODEV;
+
+	mutex_lock(&rt->stream_mutex);
+	sub->dma_off = 0;
+	sub->period_off = 0;
+
+	if (rt->stream_state == STREAM_DISABLED) {
+		for (i = 0; i < ARRAY_SIZE(rates); i++)
+			if (alsa_rt->rate == rates[i]) {
+				rt->rate = i;
+				break;
+			}
+		if (i == ARRAY_SIZE(rates)) {
+			mutex_unlock(&rt->stream_mutex);
+			snd_printk("invalid rate %d in prepare.\n",
+					alsa_rt->rate);
+			return -EINVAL;
+		}
+
+		ret = usb6fire_pcm_set_rate(rt);
+		if (ret) {
+			mutex_unlock(&rt->stream_mutex);
+			return ret;
+		}
+		ret = usb6fire_pcm_stream_start(rt);
+		if (ret) {
+			mutex_unlock(&rt->stream_mutex);
+			snd_printk(KERN_ERR PREFIX
+					"could not start pcm stream.\n");
+			return ret;
+		}
+	}
+	mutex_unlock(&rt->stream_mutex);
+	return 0;
+}
+
+static int usb6fire_pcm_trigger(struct snd_pcm_substream *alsa_sub, int cmd)
+{
+	struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
+	struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
+	unsigned long flags;
+
+	if (rt->panic)
+		return -EPIPE;
+	if (!sub)
+		return -ENODEV;
+
+	switch (cmd) {
+	case SNDRV_PCM_TRIGGER_START:
+	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+		spin_lock_irqsave(&sub->lock, flags);
+		sub->active = true;
+		spin_unlock_irqrestore(&sub->lock, flags);
+		return 0;
+
+	case SNDRV_PCM_TRIGGER_STOP:
+	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+		spin_lock_irqsave(&sub->lock, flags);
+		sub->active = false;
+		spin_unlock_irqrestore(&sub->lock, flags);
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static snd_pcm_uframes_t usb6fire_pcm_pointer(
+		struct snd_pcm_substream *alsa_sub)
+{
+	struct pcm_substream *sub = usb6fire_pcm_get_substream(alsa_sub);
+	struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
+	unsigned long flags;
+	snd_pcm_uframes_t ret;
+
+	if (rt->panic || !sub)
+		return SNDRV_PCM_STATE_XRUN;
+
+	spin_lock_irqsave(&sub->lock, flags);
+	ret = sub->dma_off;
+	spin_unlock_irqrestore(&sub->lock, flags);
+	return ret;
+}
+
+static struct snd_pcm_ops pcm_ops = {
+	.open = usb6fire_pcm_open,
+	.close = usb6fire_pcm_close,
+	.ioctl = snd_pcm_lib_ioctl,
+	.hw_params = usb6fire_pcm_hw_params,
+	.hw_free = usb6fire_pcm_hw_free,
+	.prepare = usb6fire_pcm_prepare,
+	.trigger = usb6fire_pcm_trigger,
+	.pointer = usb6fire_pcm_pointer,
+};
+
+static void __devinit usb6fire_pcm_init_urb(struct pcm_urb *urb,
+		struct sfire_chip *chip, bool in, int ep,
+		void (*handler)(struct urb *))
+{
+	urb->chip = chip;
+	usb_init_urb(&urb->instance);
+	urb->instance.transfer_buffer = urb->buffer;
+	urb->instance.transfer_buffer_length =
+			PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE;
+	urb->instance.dev = chip->dev;
+	urb->instance.pipe = in ? usb_rcvisocpipe(chip->dev, ep)
+			: usb_sndisocpipe(chip->dev, ep);
+	urb->instance.interval = 1;
+	urb->instance.transfer_flags = URB_ISO_ASAP;
+	urb->instance.complete = handler;
+	urb->instance.context = urb;
+	urb->instance.number_of_packets = PCM_N_PACKETS_PER_URB;
+}
+
+int __devinit usb6fire_pcm_init(struct sfire_chip *chip)
+{
+	int i;
+	int ret;
+	struct snd_pcm *pcm;
+	struct pcm_runtime *rt =
+			kzalloc(sizeof(struct pcm_runtime), GFP_KERNEL);
+
+	if (!rt)
+		return -ENOMEM;
+
+	rt->chip = chip;
+	rt->stream_state = STREAM_DISABLED;
+	rt->rate = -1;
+	init_waitqueue_head(&rt->stream_wait_queue);
+	mutex_init(&rt->stream_mutex);
+
+	spin_lock_init(&rt->playback.lock);
+	spin_lock_init(&rt->capture.lock);
+
+	for (i = 0; i < PCM_N_URBS; i++) {
+		usb6fire_pcm_init_urb(&rt->in_urbs[i], chip, true, IN_EP,
+				usb6fire_pcm_in_urb_handler);
+		usb6fire_pcm_init_urb(&rt->out_urbs[i], chip, false, OUT_EP,
+				usb6fire_pcm_out_urb_handler);
+
+		rt->in_urbs[i].peer = &rt->out_urbs[i];
+		rt->out_urbs[i].peer = &rt->in_urbs[i];
+	}
+
+	ret = snd_pcm_new(chip->card, "DMX6FireUSB", 0, 1, 1, &pcm);
+	if (ret < 0) {
+		kfree(rt);
+		snd_printk(KERN_ERR PREFIX "cannot create pcm instance.\n");
+		return ret;
+	}
+
+	pcm->private_data = rt;
+	strcpy(pcm->name, "DMX 6Fire USB");
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops);
+	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_ops);
+
+	ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
+			SNDRV_DMA_TYPE_CONTINUOUS,
+			snd_dma_continuous_data(GFP_KERNEL),
+			MAX_BUFSIZE, MAX_BUFSIZE);
+	if (ret) {
+		kfree(rt);
+		snd_printk(KERN_ERR PREFIX
+				"error preallocating pcm buffers.\n");
+		return ret;
+	}
+	rt->instance = pcm;
+
+	chip->pcm = rt;
+	return 0;
+}
+
+void usb6fire_pcm_abort(struct sfire_chip *chip)
+{
+	struct pcm_runtime *rt = chip->pcm;
+	int i;
+
+	if (rt) {
+		rt->panic = true;
+
+		if (rt->playback.instance)
+			snd_pcm_stop(rt->playback.instance,
+					SNDRV_PCM_STATE_XRUN);
+		if (rt->capture.instance)
+			snd_pcm_stop(rt->capture.instance,
+					SNDRV_PCM_STATE_XRUN);
+
+		for (i = 0; i < PCM_N_URBS; i++) {
+			usb_poison_urb(&rt->in_urbs[i].instance);
+			usb_poison_urb(&rt->out_urbs[i].instance);
+		}
+
+	}
+}
+
+void usb6fire_pcm_destroy(struct sfire_chip *chip)
+{
+	kfree(chip->pcm);
+	chip->pcm = NULL;
+}

+ 76 - 0
sound/usb/6fire/pcm.h

@@ -0,0 +1,76 @@
+/*
+ * Linux driver for TerraTec DMX 6Fire USB
+ *
+ * Author:	Torsten Schenk <torsten.schenk@zoho.com>
+ * Created:	Jan 01, 2011
+ * Version:	0.3.0
+ * Copyright:	(C) Torsten Schenk
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef USB6FIRE_PCM_H
+#define USB6FIRE_PCM_H
+
+#include <sound/pcm.h>
+#include <linux/mutex.h>
+
+#include "common.h"
+
+enum /* settings for pcm */
+{
+	/* maximum of EP_W_MAX_PACKET_SIZE[] (see firmware.c) */
+	PCM_N_URBS = 16, PCM_N_PACKETS_PER_URB = 8, PCM_MAX_PACKET_SIZE = 604
+};
+
+struct pcm_urb {
+	struct sfire_chip *chip;
+
+	/* BEGIN DO NOT SEPARATE */
+	struct urb instance;
+	struct usb_iso_packet_descriptor packets[PCM_N_PACKETS_PER_URB];
+	/* END DO NOT SEPARATE */
+	u8 buffer[PCM_N_PACKETS_PER_URB * PCM_MAX_PACKET_SIZE];
+
+	struct pcm_urb *peer;
+};
+
+struct pcm_substream {
+	spinlock_t lock;
+	struct snd_pcm_substream *instance;
+
+	bool active;
+
+	snd_pcm_uframes_t dma_off; /* current position in alsa dma_area */
+	snd_pcm_uframes_t period_off; /* current position in current period */
+};
+
+struct pcm_runtime {
+	struct sfire_chip *chip;
+	struct snd_pcm *instance;
+
+	struct pcm_substream playback;
+	struct pcm_substream capture;
+	bool panic; /* if set driver won't do anymore pcm on device */
+
+	struct pcm_urb in_urbs[PCM_N_URBS];
+	struct pcm_urb out_urbs[PCM_N_URBS];
+	int in_packet_size;
+	int out_packet_size;
+	int in_n_analog; /* number of analog channels soundcard sends */
+	int out_n_analog; /* number of analog channels soundcard receives */
+
+	struct mutex stream_mutex;
+	u8 stream_state; /* one of STREAM_XXX (pcm.c) */
+	u8 rate; /* one of PCM_RATE_XXX */
+	wait_queue_head_t stream_wait_queue;
+	bool stream_wait_cond;
+};
+
+int __devinit usb6fire_pcm_init(struct sfire_chip *chip);
+void usb6fire_pcm_abort(struct sfire_chip *chip);
+void usb6fire_pcm_destroy(struct sfire_chip *chip);
+#endif /* USB6FIRE_PCM_H */

+ 17 - 0
sound/usb/Kconfig

@@ -62,6 +62,7 @@ config SND_USB_CAIAQ
 	    * Native Instruments Audio 2 DJ
 	    * Native Instruments Audio 2 DJ
 	    * Native Instruments Audio 4 DJ
 	    * Native Instruments Audio 4 DJ
 	    * Native Instruments Audio 8 DJ
 	    * Native Instruments Audio 8 DJ
+	    * Native Instruments Traktor Audio 2
 	    * Native Instruments Guitar Rig Session I/O
 	    * Native Instruments Guitar Rig Session I/O
 	    * Native Instruments Guitar Rig mobile
 	    * Native Instruments Guitar Rig mobile
 	    * Native Instruments Traktor Kontrol X1
 	    * Native Instruments Traktor Kontrol X1
@@ -97,5 +98,21 @@ config SND_USB_US122L
 	  To compile this driver as a module, choose M here: the module
 	  To compile this driver as a module, choose M here: the module
 	  will be called snd-usb-us122l.
 	  will be called snd-usb-us122l.
 
 
+config SND_USB_6FIRE
+        tristate "TerraTec DMX 6Fire USB"
+        depends on EXPERIMENTAL
+        select FW_LOADER
+        select SND_RAWMIDI
+        select SND_PCM
+        help
+          Say Y here to include support for TerraTec 6fire DMX USB interface.
+
+          You will need firmware files in order to be able to use the device
+          after it has been coldstarted. This driver currently does not support
+          firmware loading for all devices. If you own such a device,
+          you could start windows and let the windows driver upload
+          the firmware. As long as you do not unplug your device from power,
+          it should be usable.
+
 endif	# SND_USB
 endif	# SND_USB
 
 

+ 1 - 1
sound/usb/Makefile

@@ -23,4 +23,4 @@ obj-$(CONFIG_SND_USB_UA101) += snd-usbmidi-lib.o
 obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o
 obj-$(CONFIG_SND_USB_USX2Y) += snd-usbmidi-lib.o
 obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o
 obj-$(CONFIG_SND_USB_US122L) += snd-usbmidi-lib.o
 
 
-obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/
+obj-$(CONFIG_SND) += misc/ usx2y/ caiaq/ 6fire/

+ 1 - 0
sound/usb/caiaq/audio.c

@@ -805,6 +805,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *dev)
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO2DJ):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO4DJ):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
 	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
+	case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORAUDIO2):
 		dev->samplerates |= SNDRV_PCM_RATE_88200;
 		dev->samplerates |= SNDRV_PCM_RATE_88200;
 		break;
 		break;
 	}
 	}

+ 6 - 0
sound/usb/caiaq/device.c

@@ -46,6 +46,7 @@ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
 			 "{Native Instruments, Audio 2 DJ},"
 			 "{Native Instruments, Audio 2 DJ},"
 			 "{Native Instruments, Audio 4 DJ},"
 			 "{Native Instruments, Audio 4 DJ},"
 			 "{Native Instruments, Audio 8 DJ},"
 			 "{Native Instruments, Audio 8 DJ},"
+			 "{Native Instruments, Traktor Audio 2},"
 			 "{Native Instruments, Session I/O},"
 			 "{Native Instruments, Session I/O},"
 			 "{Native Instruments, GuitarRig mobile}"
 			 "{Native Instruments, GuitarRig mobile}"
 			 "{Native Instruments, Traktor Kontrol X1}"
 			 "{Native Instruments, Traktor Kontrol X1}"
@@ -140,6 +141,11 @@ static struct usb_device_id snd_usb_id_table[] = {
 		.idVendor =     USB_VID_NATIVEINSTRUMENTS,
 		.idVendor =     USB_VID_NATIVEINSTRUMENTS,
 		.idProduct =    USB_PID_TRAKTORKONTROLS4
 		.idProduct =    USB_PID_TRAKTORKONTROLS4
 	},
 	},
+	{
+		.match_flags =  USB_DEVICE_ID_MATCH_DEVICE,
+		.idVendor =     USB_VID_NATIVEINSTRUMENTS,
+		.idProduct =    USB_PID_TRAKTORAUDIO2
+	},
 	{ /* terminator */ }
 	{ /* terminator */ }
 };
 };
 
 

+ 1 - 0
sound/usb/caiaq/device.h

@@ -17,6 +17,7 @@
 #define USB_PID_GUITARRIGMOBILE		0x0d8d
 #define USB_PID_GUITARRIGMOBILE		0x0d8d
 #define USB_PID_TRAKTORKONTROLX1	0x2305
 #define USB_PID_TRAKTORKONTROLX1	0x2305
 #define USB_PID_TRAKTORKONTROLS4	0xbaff
 #define USB_PID_TRAKTORKONTROLS4	0xbaff
+#define USB_PID_TRAKTORAUDIO2		0x041d
 
 
 #define EP1_BUFSIZE 64
 #define EP1_BUFSIZE 64
 #define EP4_BUFSIZE 512
 #define EP4_BUFSIZE 512

+ 55 - 9
sound/usb/card.c

@@ -65,6 +65,7 @@
 #include "pcm.h"
 #include "pcm.h"
 #include "urb.h"
 #include "urb.h"
 #include "format.h"
 #include "format.h"
+#include "power.h"
 
 
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
 MODULE_DESCRIPTION("USB Audio");
 MODULE_DESCRIPTION("USB Audio");
@@ -330,6 +331,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,
 	chip->setup = device_setup[idx];
 	chip->setup = device_setup[idx];
 	chip->nrpacks = nrpacks;
 	chip->nrpacks = nrpacks;
 	chip->async_unlink = async_unlink;
 	chip->async_unlink = async_unlink;
+	chip->probing = 1;
 
 
 	chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
 	chip->usb_id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
 			      le16_to_cpu(dev->descriptor.idProduct));
 			      le16_to_cpu(dev->descriptor.idProduct));
@@ -451,6 +453,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
 				goto __error;
 				goto __error;
 			}
 			}
 			chip = usb_chip[i];
 			chip = usb_chip[i];
+			chip->probing = 1;
 			break;
 			break;
 		}
 		}
 	}
 	}
@@ -466,6 +469,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
 					goto __error;
 					goto __error;
 				}
 				}
 				snd_card_set_dev(chip->card, &intf->dev);
 				snd_card_set_dev(chip->card, &intf->dev);
+				chip->pm_intf = intf;
 				break;
 				break;
 			}
 			}
 		if (!chip) {
 		if (!chip) {
@@ -505,6 +509,7 @@ static void *snd_usb_audio_probe(struct usb_device *dev,
 
 
 	usb_chip[chip->index] = chip;
 	usb_chip[chip->index] = chip;
 	chip->num_interfaces++;
 	chip->num_interfaces++;
+	chip->probing = 0;
 	mutex_unlock(&register_mutex);
 	mutex_unlock(&register_mutex);
 	return chip;
 	return chip;
 
 
@@ -581,29 +586,61 @@ static void usb_audio_disconnect(struct usb_interface *intf)
 }
 }
 
 
 #ifdef CONFIG_PM
 #ifdef CONFIG_PM
+
+int snd_usb_autoresume(struct snd_usb_audio *chip)
+{
+	int err = -ENODEV;
+
+	if (!chip->shutdown && !chip->probing)
+		err = usb_autopm_get_interface(chip->pm_intf);
+
+	return err;
+}
+
+void snd_usb_autosuspend(struct snd_usb_audio *chip)
+{
+	if (!chip->shutdown && !chip->probing)
+		usb_autopm_put_interface(chip->pm_intf);
+}
+
 static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
 static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
 {
 {
 	struct snd_usb_audio *chip = usb_get_intfdata(intf);
 	struct snd_usb_audio *chip = usb_get_intfdata(intf);
 	struct list_head *p;
 	struct list_head *p;
 	struct snd_usb_stream *as;
 	struct snd_usb_stream *as;
+	struct usb_mixer_interface *mixer;
 
 
 	if (chip == (void *)-1L)
 	if (chip == (void *)-1L)
 		return 0;
 		return 0;
 
 
-	snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
-	if (!chip->num_suspended_intf++) {
-		list_for_each(p, &chip->pcm_list) {
-			as = list_entry(p, struct snd_usb_stream, list);
-			snd_pcm_suspend_all(as->pcm);
-		}
+	if (!(message.event & PM_EVENT_AUTO)) {
+		snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
+		if (!chip->num_suspended_intf++) {
+			list_for_each(p, &chip->pcm_list) {
+				as = list_entry(p, struct snd_usb_stream, list);
+				snd_pcm_suspend_all(as->pcm);
+			}
+ 		}
+	} else {
+		/*
+		 * otherwise we keep the rest of the system in the dark
+		 * to keep this transparent
+		 */
+		if (!chip->num_suspended_intf++)
+			chip->autosuspended = 1;
 	}
 	}
 
 
+	list_for_each_entry(mixer, &chip->mixer_list, list)
+		snd_usb_mixer_inactivate(mixer);
+
 	return 0;
 	return 0;
 }
 }
 
 
 static int usb_audio_resume(struct usb_interface *intf)
 static int usb_audio_resume(struct usb_interface *intf)
 {
 {
 	struct snd_usb_audio *chip = usb_get_intfdata(intf);
 	struct snd_usb_audio *chip = usb_get_intfdata(intf);
+	struct usb_mixer_interface *mixer;
+	int err = 0;
 
 
 	if (chip == (void *)-1L)
 	if (chip == (void *)-1L)
 		return 0;
 		return 0;
@@ -611,12 +648,20 @@ static int usb_audio_resume(struct usb_interface *intf)
 		return 0;
 		return 0;
 	/*
 	/*
 	 * ALSA leaves material resumption to user space
 	 * ALSA leaves material resumption to user space
-	 * we just notify
+	 * we just notify and restart the mixers
 	 */
 	 */
+	list_for_each_entry(mixer, &chip->mixer_list, list) {
+		err = snd_usb_mixer_activate(mixer);
+		if (err < 0)
+			goto err_out;
+	}
 
 
-	snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
+	if (!chip->autosuspended)
+		snd_power_change_state(chip->card, SNDRV_CTL_POWER_D0);
+	chip->autosuspended = 0;
 
 
-	return 0;
+err_out:
+	return err;
 }
 }
 #else
 #else
 #define usb_audio_suspend	NULL
 #define usb_audio_suspend	NULL
@@ -644,6 +689,7 @@ static struct usb_driver usb_audio_driver = {
 	.suspend =	usb_audio_suspend,
 	.suspend =	usb_audio_suspend,
 	.resume =	usb_audio_resume,
 	.resume =	usb_audio_resume,
 	.id_table =	usb_audio_ids,
 	.id_table =	usb_audio_ids,
+	.supports_autosuspend = 1,
 };
 };
 
 
 static int __init snd_usb_audio_init(void)
 static int __init snd_usb_audio_init(void)

+ 8 - 0
sound/usb/midi.c

@@ -54,6 +54,7 @@
 #include <sound/asequencer.h>
 #include <sound/asequencer.h>
 #include "usbaudio.h"
 #include "usbaudio.h"
 #include "midi.h"
 #include "midi.h"
+#include "power.h"
 #include "helper.h"
 #include "helper.h"
 
 
 /*
 /*
@@ -1044,6 +1045,7 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
 	struct snd_usb_midi* umidi = substream->rmidi->private_data;
 	struct snd_usb_midi* umidi = substream->rmidi->private_data;
 	struct usbmidi_out_port* port = NULL;
 	struct usbmidi_out_port* port = NULL;
 	int i, j;
 	int i, j;
+	int err;
 
 
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
 		if (umidi->endpoints[i].out)
 		if (umidi->endpoints[i].out)
@@ -1056,6 +1058,9 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
 		snd_BUG();
 		snd_BUG();
 		return -ENXIO;
 		return -ENXIO;
 	}
 	}
+	err = usb_autopm_get_interface(umidi->iface);
+	if (err < 0)
+		return -EIO;
 	substream->runtime->private_data = port;
 	substream->runtime->private_data = port;
 	port->state = STATE_UNKNOWN;
 	port->state = STATE_UNKNOWN;
 	substream_open(substream, 1);
 	substream_open(substream, 1);
@@ -1064,7 +1069,10 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
 
 
 static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
 static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
 {
 {
+	struct snd_usb_midi* umidi = substream->rmidi->private_data;
+
 	substream_open(substream, 0);
 	substream_open(substream, 0);
+	usb_autopm_put_interface(umidi->iface);
 	return 0;
 	return 0;
 }
 }
 
 

+ 61 - 4
sound/usb/mixer.c

@@ -61,6 +61,7 @@
 #include "mixer.h"
 #include "mixer.h"
 #include "helper.h"
 #include "helper.h"
 #include "mixer_quirks.h"
 #include "mixer_quirks.h"
+#include "power.h"
 
 
 #define MAX_ID_ELEMS	256
 #define MAX_ID_ELEMS	256
 
 
@@ -295,16 +296,22 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
 	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;
+	int err;
 
 
+	err = snd_usb_autoresume(cval->mixer->chip);
+	if (err < 0)
+		return -EIO;
 	while (timeout-- > 0) {
 	while (timeout-- > 0) {
 		if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(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, snd_usb_ctrl_intf(chip) | (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));
+			snd_usb_autosuspend(cval->mixer->chip);
 			return 0;
 			return 0;
 		}
 		}
 	}
 	}
+	snd_usb_autosuspend(cval->mixer->chip);
 	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, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
 		    request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
 	return -EINVAL;
 	return -EINVAL;
@@ -328,12 +335,18 @@ 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_autoresume(chip) ? -EIO : 0;
+	if (ret)
+		goto error;
+
 	ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(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, snd_usb_ctrl_intf(chip) | (cval->id << 8),
 			      validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
 			      buf, size, 1000);
 			      buf, size, 1000);
+	snd_usb_autosuspend(chip);
 
 
 	if (ret < 0) {
 	if (ret < 0) {
+error:
 		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, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
 			   request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type);
 		return ret;
 		return ret;
@@ -413,7 +426,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 {
 {
 	struct snd_usb_audio *chip = cval->mixer->chip;
 	struct snd_usb_audio *chip = cval->mixer->chip;
 	unsigned char buf[2];
 	unsigned char buf[2];
-	int val_len, timeout = 10;
+	int val_len, err, timeout = 10;
 
 
 	if (cval->mixer->protocol == UAC_VERSION_1) {
 	if (cval->mixer->protocol == UAC_VERSION_1) {
 		val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
 		val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;
@@ -433,13 +446,19 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
 	value_set = convert_bytes_value(cval, value_set);
 	value_set = convert_bytes_value(cval, value_set);
 	buf[0] = value_set & 0xff;
 	buf[0] = value_set & 0xff;
 	buf[1] = (value_set >> 8) & 0xff;
 	buf[1] = (value_set >> 8) & 0xff;
+	err = snd_usb_autoresume(chip);
+	if (err < 0)
+		return -EIO;
 	while (timeout-- > 0)
 	while (timeout-- > 0)
 		if (snd_usb_ctl_msg(chip->dev,
 		if (snd_usb_ctl_msg(chip->dev,
 				    usb_sndctrlpipe(chip->dev, 0), request,
 				    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, snd_usb_ctrl_intf(chip) | (cval->id << 8),
 				    validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
-				    buf, val_len, 100) >= 0)
+				    buf, val_len, 100) >= 0) {
+			snd_usb_autosuspend(chip);
 			return 0;
 			return 0;
+		}
+	snd_usb_autosuspend(chip);
 	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, snd_usb_ctrl_intf(chip) | (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;
@@ -987,6 +1006,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
 	struct snd_kcontrol *kctl;
 	struct snd_kcontrol *kctl;
 	struct usb_mixer_elem_info *cval;
 	struct usb_mixer_elem_info *cval;
 	const struct usbmix_name_map *map;
 	const struct usbmix_name_map *map;
+	unsigned int range;
 
 
 	control++; /* change from zero-based to 1-based value */
 	control++; /* change from zero-based to 1-based value */
 
 
@@ -1121,6 +1141,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
 		}
 		}
 		break;
 		break;
 
 
+	case USB_ID(0x046d, 0x0808):
 	case USB_ID(0x046d, 0x0809):
 	case USB_ID(0x046d, 0x0809):
 	case USB_ID(0x046d, 0x0991):
 	case USB_ID(0x046d, 0x0991):
 	/* Most audio usb devices lie about volume resolution.
 	/* Most audio usb devices lie about volume resolution.
@@ -1136,6 +1157,21 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
 
 
 	}
 	}
 
 
+	range = (cval->max - cval->min) / cval->res;
+	/* Are there devices with volume range more than 255? I use a bit more
+	 * to be sure. 384 is a resolution magic number found on Logitech
+	 * devices. It will definitively catch all buggy Logitech devices.
+	 */
+	if (range > 384) {
+		snd_printk(KERN_WARNING "usb_audio: Warning! Unlikely big "
+			   "volume range (=%u), cval->res is probably wrong.",
+			   range);
+		snd_printk(KERN_WARNING "usb_audio: [%d] FU [%s] ch = %d, "
+			   "val = %d/%d/%d", cval->id,
+			   kctl->id.name, cval->channels,
+			   cval->min, cval->max, cval->res);
+	}
+
 	snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
 	snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n",
 		    cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
 		    cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res);
 	add_control_to_empty(state, kctl);
 	add_control_to_empty(state, kctl);
@@ -2058,8 +2094,9 @@ static void snd_usb_mixer_interrupt(struct urb *urb)
 {
 {
 	struct usb_mixer_interface *mixer = urb->context;
 	struct usb_mixer_interface *mixer = urb->context;
 	int len = urb->actual_length;
 	int len = urb->actual_length;
+	int ustatus = urb->status;
 
 
-	if (urb->status != 0)
+	if (ustatus != 0)
 		goto requeue;
 		goto requeue;
 
 
 	if (mixer->protocol == UAC_VERSION_1) {
 	if (mixer->protocol == UAC_VERSION_1) {
@@ -2100,12 +2137,32 @@ static void snd_usb_mixer_interrupt(struct urb *urb)
 	}
 	}
 
 
 requeue:
 requeue:
-	if (urb->status != -ENOENT && urb->status != -ECONNRESET) {
+	if (ustatus != -ENOENT && ustatus != -ECONNRESET && ustatus != -ESHUTDOWN) {
 		urb->dev = mixer->chip->dev;
 		urb->dev = mixer->chip->dev;
 		usb_submit_urb(urb, GFP_ATOMIC);
 		usb_submit_urb(urb, GFP_ATOMIC);
 	}
 	}
 }
 }
 
 
+/* stop any bus activity of a mixer */
+void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer)
+{
+	usb_kill_urb(mixer->urb);
+	usb_kill_urb(mixer->rc_urb);
+}
+
+int snd_usb_mixer_activate(struct usb_mixer_interface *mixer)
+{
+	int err;
+
+	if (mixer->urb) {
+		err = usb_submit_urb(mixer->urb, GFP_NOIO);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
 /* create the handler for the optional status interrupt endpoint */
 /* create the handler for the optional status interrupt endpoint */
 static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
 static int snd_usb_mixer_status_create(struct usb_mixer_interface *mixer)
 {
 {

+ 2 - 0
sound/usb/mixer.h

@@ -52,5 +52,7 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid);
 
 
 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);
+void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer);
+int snd_usb_mixer_activate(struct usb_mixer_interface *mixer);
 
 
 #endif /* __USBMIXER_H */
 #endif /* __USBMIXER_H */

+ 161 - 13
sound/usb/mixer_quirks.c

@@ -346,6 +346,141 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
 	return 0;
 	return 0;
 }
 }
 
 
+/* Native Instruments device quirks */
+
+#define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex))
+
+static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
+					     struct snd_ctl_elem_value *ucontrol)
+{
+	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+	struct usb_device *dev = mixer->chip->dev;
+	u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
+	u16 wIndex = kcontrol->private_value & 0xffff;
+	u8 tmp;
+
+	int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
+				  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
+				  0, cpu_to_le16(wIndex),
+				  &tmp, sizeof(tmp), 1000);
+
+	if (ret < 0) {
+		snd_printk(KERN_ERR
+			   "unable to issue vendor read request (ret = %d)", ret);
+		return ret;
+	}
+
+	ucontrol->value.integer.value[0] = tmp;
+
+	return 0;
+}
+
+static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
+					     struct snd_ctl_elem_value *ucontrol)
+{
+	struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
+	struct usb_device *dev = mixer->chip->dev;
+	u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
+	u16 wIndex = kcontrol->private_value & 0xffff;
+	u16 wValue = ucontrol->value.integer.value[0];
+
+	int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
+				  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
+				  cpu_to_le16(wValue), cpu_to_le16(wIndex),
+				  NULL, 0, 1000);
+
+	if (ret < 0) {
+		snd_printk(KERN_ERR
+			   "unable to issue vendor write request (ret = %d)", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = {
+	{
+		.name = "Direct Thru Channel A",
+		.private_value = _MAKE_NI_CONTROL(0x01, 0x03),
+	},
+	{
+		.name = "Direct Thru Channel B",
+		.private_value = _MAKE_NI_CONTROL(0x01, 0x05),
+	},
+	{
+		.name = "Phono Input Channel A",
+		.private_value = _MAKE_NI_CONTROL(0x02, 0x03),
+	},
+	{
+		.name = "Phono Input Channel B",
+		.private_value = _MAKE_NI_CONTROL(0x02, 0x05),
+	},
+};
+
+static struct snd_kcontrol_new snd_nativeinstruments_ta10_mixers[] = {
+	{
+		.name = "Direct Thru Channel A",
+		.private_value = _MAKE_NI_CONTROL(0x01, 0x03),
+	},
+	{
+		.name = "Direct Thru Channel B",
+		.private_value = _MAKE_NI_CONTROL(0x01, 0x05),
+	},
+	{
+		.name = "Direct Thru Channel C",
+		.private_value = _MAKE_NI_CONTROL(0x01, 0x07),
+	},
+	{
+		.name = "Direct Thru Channel D",
+		.private_value = _MAKE_NI_CONTROL(0x01, 0x09),
+	},
+	{
+		.name = "Phono Input Channel A",
+		.private_value = _MAKE_NI_CONTROL(0x02, 0x03),
+	},
+	{
+		.name = "Phono Input Channel B",
+		.private_value = _MAKE_NI_CONTROL(0x02, 0x05),
+	},
+	{
+		.name = "Phono Input Channel C",
+		.private_value = _MAKE_NI_CONTROL(0x02, 0x07),
+	},
+	{
+		.name = "Phono Input Channel D",
+		.private_value = _MAKE_NI_CONTROL(0x02, 0x09),
+	},
+};
+
+static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
+					      const struct snd_kcontrol_new *kc,
+					      unsigned int count)
+{
+	int i, err = 0;
+	struct snd_kcontrol_new template = {
+		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+		.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+		.get = snd_nativeinstruments_control_get,
+		.put = snd_nativeinstruments_control_put,
+		.info = snd_ctl_boolean_mono_info,
+	};
+
+	for (i = 0; i < count; i++) {
+		struct snd_kcontrol *c;
+
+		template.name = kc[i].name;
+		template.private_value = kc[i].private_value;
+
+		c = snd_ctl_new1(&template, mixer);
+		err = snd_ctl_add(mixer->chip->card, c);
+
+		if (err < 0)
+			break;
+	}
+
+	return err;
+}
+
 void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
 void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
 			       unsigned char samplerate_id)
 			       unsigned char samplerate_id)
 {
 {
@@ -367,31 +502,44 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
 
 
 int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
 int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
 {
 {
-	int err;
+	int err = 0;
 	struct snd_info_entry *entry;
 	struct snd_info_entry *entry;
 
 
 	if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
 	if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
 		return err;
 		return err;
 
 
-	if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) ||
-	    mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
-	    mixer->chip->usb_id == USB_ID(0x041e, 0x3042) ||
-	    mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) {
-		if ((err = snd_audigy2nx_controls_create(mixer)) < 0)
-			return err;
+	switch (mixer->chip->usb_id) {
+	case USB_ID(0x041e, 0x3020):
+	case USB_ID(0x041e, 0x3040):
+	case USB_ID(0x041e, 0x3042):
+	case USB_ID(0x041e, 0x3048):
+		err = snd_audigy2nx_controls_create(mixer);
+		if (err < 0)
+			break;
 		if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry))
 		if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry))
 			snd_info_set_text_ops(entry, mixer,
 			snd_info_set_text_ops(entry, mixer,
 					      snd_audigy2nx_proc_read);
 					      snd_audigy2nx_proc_read);
-	}
+		break;
 
 
-	if (mixer->chip->usb_id == USB_ID(0x0b05, 0x1739) ||
-	    mixer->chip->usb_id == USB_ID(0x0b05, 0x1743)) {
+	case USB_ID(0x0b05, 0x1739):
+	case USB_ID(0x0b05, 0x1743):
 		err = snd_xonar_u1_controls_create(mixer);
 		err = snd_xonar_u1_controls_create(mixer);
-		if (err < 0)
-			return err;
+		break;
+
+	case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */
+		err = snd_nativeinstruments_create_mixer(mixer,
+				snd_nativeinstruments_ta6_mixers,
+				ARRAY_SIZE(snd_nativeinstruments_ta6_mixers));
+		break;
+
+	case USB_ID(0x17cc, 0x1021): /* Traktor Audio 10 */
+		err = snd_nativeinstruments_create_mixer(mixer,
+				snd_nativeinstruments_ta10_mixers,
+				ARRAY_SIZE(snd_nativeinstruments_ta10_mixers));
+		break;
 	}
 	}
 
 
-	return 0;
+	return err;
 }
 }
 
 
 void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
 void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,

+ 15 - 5
sound/usb/pcm.c

@@ -32,6 +32,7 @@
 #include "helper.h"
 #include "helper.h"
 #include "pcm.h"
 #include "pcm.h"
 #include "clock.h"
 #include "clock.h"
+#include "power.h"
 
 
 /*
 /*
  * return the current pcm pointer.  just based on the hwptr_done value.
  * return the current pcm pointer.  just based on the hwptr_done value.
@@ -739,6 +740,9 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 		pt = 125 * (1 << fp->datainterval);
 		pt = 125 * (1 << fp->datainterval);
 		ptmin = min(ptmin, pt);
 		ptmin = min(ptmin, pt);
 	}
 	}
+	err = snd_usb_autoresume(subs->stream->chip);
+	if (err < 0)
+		return err;
 
 
 	param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
 	param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME;
 	if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
 	if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
@@ -756,21 +760,21 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 				       SNDRV_PCM_HW_PARAM_CHANNELS,
 				       SNDRV_PCM_HW_PARAM_CHANNELS,
 				       param_period_time_if_needed,
 				       param_period_time_if_needed,
 				       -1)) < 0)
 				       -1)) < 0)
-		return err;
+		goto rep_err;
 	if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 	if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
 				       hw_rule_channels, subs,
 				       hw_rule_channels, subs,
 				       SNDRV_PCM_HW_PARAM_FORMAT,
 				       SNDRV_PCM_HW_PARAM_FORMAT,
 				       SNDRV_PCM_HW_PARAM_RATE,
 				       SNDRV_PCM_HW_PARAM_RATE,
 				       param_period_time_if_needed,
 				       param_period_time_if_needed,
 				       -1)) < 0)
 				       -1)) < 0)
-		return err;
+		goto rep_err;
 	if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
 	if ((err = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
 				       hw_rule_format, subs,
 				       hw_rule_format, subs,
 				       SNDRV_PCM_HW_PARAM_RATE,
 				       SNDRV_PCM_HW_PARAM_RATE,
 				       SNDRV_PCM_HW_PARAM_CHANNELS,
 				       SNDRV_PCM_HW_PARAM_CHANNELS,
 				       param_period_time_if_needed,
 				       param_period_time_if_needed,
 				       -1)) < 0)
 				       -1)) < 0)
-		return err;
+		goto rep_err;
 	if (param_period_time_if_needed >= 0) {
 	if (param_period_time_if_needed >= 0) {
 		err = snd_pcm_hw_rule_add(runtime, 0,
 		err = snd_pcm_hw_rule_add(runtime, 0,
 					  SNDRV_PCM_HW_PARAM_PERIOD_TIME,
 					  SNDRV_PCM_HW_PARAM_PERIOD_TIME,
@@ -780,11 +784,15 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
 					  SNDRV_PCM_HW_PARAM_RATE,
 					  SNDRV_PCM_HW_PARAM_RATE,
 					  -1);
 					  -1);
 		if (err < 0)
 		if (err < 0)
-			return err;
+			goto rep_err;
 	}
 	}
 	if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0)
 	if ((err = snd_usb_pcm_check_knot(runtime, subs)) < 0)
-		return err;
+		goto rep_err;
 	return 0;
 	return 0;
+
+rep_err:
+	snd_usb_autosuspend(subs->stream->chip);
+	return err;
 }
 }
 
 
 static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
 static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
@@ -798,6 +806,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
 	runtime->hw = snd_usb_hardware;
 	runtime->hw = snd_usb_hardware;
 	runtime->private_data = subs;
 	runtime->private_data = subs;
 	subs->pcm_substream = substream;
 	subs->pcm_substream = substream;
+	/* runtime PM is also done there */
 	return setup_hw_info(runtime, subs);
 	return setup_hw_info(runtime, subs);
 }
 }
 
 
@@ -811,6 +820,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
 		subs->interface = -1;
 		subs->interface = -1;
 	}
 	}
 	subs->pcm_substream = NULL;
 	subs->pcm_substream = NULL;
+	snd_usb_autosuspend(subs->stream->chip);
 	return 0;
 	return 0;
 }
 }
 
 

+ 17 - 0
sound/usb/power.h

@@ -0,0 +1,17 @@
+#ifndef __USBAUDIO_POWER_H
+#define __USBAUDIO_POWER_H
+
+#ifdef CONFIG_PM
+int snd_usb_autoresume(struct snd_usb_audio *chip);
+void snd_usb_autosuspend(struct snd_usb_audio *chip);
+#else
+static inline int snd_usb_autoresume(struct snd_usb_audio *chip)
+{
+	return 0;
+}
+static inline void snd_usb_autosuspend(struct snd_usb_audio *chip)
+{
+}
+#endif
+
+#endif /* __USBAUDIO_POWER_H */

+ 14 - 0
sound/usb/quirks-table.h

@@ -2290,6 +2290,20 @@ YAMAHA_DEVICE(0x7010, "UB99"),
 	}
 	}
 },
 },
 
 
+/* Native Instruments MK2 series */
+{
+	/* Traktor Audio 6 */
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor = 0x17cc,
+	.idProduct = 0x1010,
+},
+{
+	/* Traktor Audio 10 */
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+	.idVendor = 0x17cc,
+	.idProduct = 0x1020,
+},
+
 /* Miditech devices */
 /* Miditech devices */
 {
 {
 	USB_DEVICE(0x4752, 0x0011),
 	USB_DEVICE(0x4752, 0x0011),

+ 45 - 11
sound/usb/quirks.c

@@ -424,6 +424,34 @@ static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev)
 	return 0;
 	return 0;
 }
 }
 
 
+/*
+ * Some sound cards from Native Instruments are in fact compliant to the USB
+ * audio standard of version 2 and other approved USB standards, even though
+ * they come up as vendor-specific device when first connected.
+ *
+ * However, they can be told to come up with a new set of descriptors
+ * upon their next enumeration, and the interfaces announced by the new
+ * descriptors will then be handled by the kernel's class drivers. As the
+ * product ID will also change, no further checks are required.
+ */
+
+static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev)
+{
+	int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+				  0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+				  cpu_to_le16(1), 0, NULL, 0, 1000);
+
+	if (ret < 0)
+		return ret;
+
+	usb_reset_device(dev);
+
+	/* return -EAGAIN, so the creation of an audio interface for this
+	 * temporary device is aborted. The device will reconnect with a
+	 * new product ID */
+	return -EAGAIN;
+}
+
 /*
 /*
  * Setup quirks
  * Setup quirks
  */
  */
@@ -489,27 +517,33 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 	u32 id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
 	u32 id = USB_ID(le16_to_cpu(dev->descriptor.idVendor),
 			le16_to_cpu(dev->descriptor.idProduct));
 			le16_to_cpu(dev->descriptor.idProduct));
 
 
-	/* SB Extigy needs special boot-up sequence */
-	/* if more models come, this will go to the quirk list. */
-	if (id == USB_ID(0x041e, 0x3000))
+	switch (id) {
+	case USB_ID(0x041e, 0x3000):
+		/* SB Extigy needs special boot-up sequence */
+		/* if more models come, this will go to the quirk list. */
 		return snd_usb_extigy_boot_quirk(dev, intf);
 		return snd_usb_extigy_boot_quirk(dev, intf);
 
 
-	/* SB Audigy 2 NX needs its own boot-up magic, too */
-	if (id == USB_ID(0x041e, 0x3020))
+	case USB_ID(0x041e, 0x3020):
+		/* SB Audigy 2 NX needs its own boot-up magic, too */
 		return snd_usb_audigy2nx_boot_quirk(dev);
 		return snd_usb_audigy2nx_boot_quirk(dev);
 
 
-	/* C-Media CM106 / Turtle Beach Audio Advantage Roadie */
-	if (id == USB_ID(0x10f5, 0x0200))
+	case USB_ID(0x10f5, 0x0200):
+		/* C-Media CM106 / Turtle Beach Audio Advantage Roadie */
 		return snd_usb_cm106_boot_quirk(dev);
 		return snd_usb_cm106_boot_quirk(dev);
 
 
-	/* C-Media CM6206 / CM106-Like Sound Device */
-	if (id == USB_ID(0x0d8c, 0x0102))
+	case USB_ID(0x0d8c, 0x0102):
+		/* C-Media CM6206 / CM106-Like Sound Device */
 		return snd_usb_cm6206_boot_quirk(dev);
 		return snd_usb_cm6206_boot_quirk(dev);
 
 
-	/* Access Music VirusTI Desktop */
-	if (id == USB_ID(0x133e, 0x0815))
+	case USB_ID(0x133e, 0x0815):
+		/* Access Music VirusTI Desktop */
 		return snd_usb_accessmusic_boot_quirk(dev);
 		return snd_usb_accessmusic_boot_quirk(dev);
 
 
+	case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */
+	case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */
+		return snd_usb_nativeinstruments_boot_quirk(dev);
+	}
+
 	return 0;
 	return 0;
 }
 }
 
 

+ 5 - 1
sound/usb/usbaudio.h

@@ -34,10 +34,14 @@ struct snd_usb_audio {
 	int index;
 	int index;
 	struct usb_device *dev;
 	struct usb_device *dev;
 	struct snd_card *card;
 	struct snd_card *card;
+	struct usb_interface *pm_intf;
 	u32 usb_id;
 	u32 usb_id;
-	int shutdown;
 	struct mutex shutdown_mutex;
 	struct mutex shutdown_mutex;
+	unsigned int shutdown:1;
+	unsigned int probing:1;
+	unsigned int autosuspended:1;	
 	unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
 	unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
+	
 	int num_interfaces;
 	int num_interfaces;
 	int num_suspended_intf;
 	int num_suspended_intf;
 
 

Някои файлове не бяха показани, защото твърде много файлове са промени