···31/* these minors can still be used for autoloading devices (/dev/aload*) */32#define SNDRV_MINOR_CONTROL 0 /* 0 */33#define SNDRV_MINOR_GLOBAL 1 /* 1 */34-#define SNDRV_MINOR_SEQUENCER (SNDRV_MINOR_GLOBAL + 0 * 32)35-#define SNDRV_MINOR_TIMER (SNDRV_MINOR_GLOBAL + 1 * 32)3637#ifndef CONFIG_SND_DYNAMIC_MINORS38 /* 2 - 3 (reserved) */
···31/* these minors can still be used for autoloading devices (/dev/aload*) */32#define SNDRV_MINOR_CONTROL 0 /* 0 */33#define SNDRV_MINOR_GLOBAL 1 /* 1 */34+#define SNDRV_MINOR_SEQUENCER 1 /* SNDRV_MINOR_GLOBAL + 0 * 32 */35+#define SNDRV_MINOR_TIMER 33 /* SNDRV_MINOR_GLOBAL + 1 * 32 */3637#ifndef CONFIG_SND_DYNAMIC_MINORS38 /* 2 - 3 (reserved) */
+1
include/sound/pcm.h
···297 unsigned int info;298 unsigned int rate_num;299 unsigned int rate_den;0300301 /* -- SW params -- */302 int tstamp_mode; /* mmap timestamp is updated */
···297 unsigned int info;298 unsigned int rate_num;299 unsigned int rate_den;300+ unsigned int no_period_wakeup: 1;301302 /* -- SW params -- */303 int tstamp_mode; /* mmap timestamp is updated */
+2-2
sound/ac97_bus.c
···1920/*21 * Let drivers decide whether they want to support given codec from their22- * probe method. Drivers have direct access to the struct snd_ac97 structure and may23- * decide based on the id field amongst other things.24 */25static int ac97_bus_match(struct device *dev, struct device_driver *drv)26{
···1920/*21 * Let drivers decide whether they want to support given codec from their22+ * probe method. Drivers have direct access to the struct snd_ac9723+ * structure and may decide based on the id field amongst other things.24 */25static int ac97_bus_match(struct device *dev, struct device_driver *drv)26{
-1
sound/aoa/codecs/onyx.c
···1114 of_node_put(onyx->codec.node);1115 if (onyx->codec_info)1116 kfree(onyx->codec_info);1117- i2c_set_clientdata(client, onyx);1118 kfree(onyx);1119 return 0;1120}
···1114 of_node_put(onyx->codec.node);1115 if (onyx->codec_info)1116 kfree(onyx->codec_info);01117 kfree(onyx);1118 return 0;1119}
···107108 /* make sure no work is pending before freeing109 * all things */110- cancel_delayed_work(&rt->headphone_notify.work);111- cancel_delayed_work(&rt->line_in_notify.work);112- cancel_delayed_work(&rt->line_out_notify.work);113- flush_scheduled_work();114115 mutex_destroy(&rt->headphone_notify.mutex);116 mutex_destroy(&rt->line_in_notify.mutex);
···107108 /* make sure no work is pending before freeing109 * all things */110+ cancel_delayed_work_sync(&rt->headphone_notify.work);111+ cancel_delayed_work_sync(&rt->line_in_notify.work);112+ cancel_delayed_work_sync(&rt->line_out_notify.work);0113114 mutex_destroy(&rt->headphone_notify.mutex);115 mutex_destroy(&rt->line_in_notify.mutex);
+27-1
sound/core/control.c
···1488}14891490/*1491- * Frequently used control callbacks1492 */1493int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,1494 struct snd_ctl_elem_info *uinfo)···1513}15141515EXPORT_SYMBOL(snd_ctl_boolean_stereo_info);00000000000000000000000000
···1488}14891490/*1491+ * Frequently used control callbacks/helpers1492 */1493int snd_ctl_boolean_mono_info(struct snd_kcontrol *kcontrol,1494 struct snd_ctl_elem_info *uinfo)···1513}15141515EXPORT_SYMBOL(snd_ctl_boolean_stereo_info);1516+1517+/**1518+ * snd_ctl_enum_info - fills the info structure for an enumerated control1519+ * @info: the structure to be filled1520+ * @channels: the number of the control's channels; often one1521+ * @items: the number of control values; also the size of @names1522+ * @names: an array containing the names of all control values1523+ *1524+ * Sets all required fields in @info to their appropriate values.1525+ * If the control's accessibility is not the default (readable and writable),1526+ * the caller has to fill @info->access.1527+ */1528+int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,1529+ unsigned int items, const char *const names[])1530+{1531+ info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;1532+ info->count = channels;1533+ info->value.enumerated.items = items;1534+ if (info->value.enumerated.item >= items)1535+ info->value.enumerated.item = items - 1;1536+ strlcpy(info->value.enumerated.name,1537+ names[info->value.enumerated.item],1538+ sizeof(info->value.enumerated.name));1539+ return 0;1540+}1541+EXPORT_SYMBOL(snd_ctl_enum_info);
+3-1
sound/core/oss/pcm_oss.c
···453 } else {454 *params = *save;455 max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);456- if (max < 0)0457 return max;0458 last = 1;459 }460 _end:
···453 } else {454 *params = *save;455 max = snd_pcm_hw_param_max(pcm, params, var, max, &maxdir);456+ if (max < 0) {457+ kfree(save);458 return max;459+ }460 last = 1;461 }462 _end:
+22
sound/core/pcm_lib.c
···373 (unsigned long)new_hw_ptr,374 (unsigned long)runtime->hw_ptr_base);375 }000000000000000000000376 /* something must be really wrong */377 if (delta >= runtime->buffer_size + runtime->period_size) {378 hw_ptr_error(substream,···463 (long)old_hw_ptr);464 }4650466 if (runtime->status->hw_ptr == new_hw_ptr)467 return 0;468
···373 (unsigned long)new_hw_ptr,374 (unsigned long)runtime->hw_ptr_base);375 }376+377+ if (runtime->no_period_wakeup) {378+ /*379+ * Without regular period interrupts, we have to check380+ * the elapsed time to detect xruns.381+ */382+ jdelta = jiffies - runtime->hw_ptr_jiffies;383+ if (jdelta < runtime->hw_ptr_buffer_jiffies / 2)384+ goto no_delta_check;385+ hdelta = jdelta - delta * HZ / runtime->rate;386+ while (hdelta > runtime->hw_ptr_buffer_jiffies / 2 + 1) {387+ delta += runtime->buffer_size;388+ hw_base += runtime->buffer_size;389+ if (hw_base >= runtime->boundary)390+ hw_base = 0;391+ new_hw_ptr = hw_base + pos;392+ hdelta -= runtime->hw_ptr_buffer_jiffies;393+ }394+ goto no_delta_check;395+ }396+397 /* something must be really wrong */398 if (delta >= runtime->buffer_size + runtime->period_size) {399 hw_ptr_error(substream,···442 (long)old_hw_ptr);443 }444445+ no_delta_check:446 if (runtime->status->hw_ptr == new_hw_ptr)447 return 0;448
···32#include "seq_timer.h"33#include "seq_system.h"34#include "seq_info.h"035#include <sound/seq_device.h>3637#if defined(CONFIG_SND_SEQ_DUMMY_MODULE)···73MODULE_PARM_DESC(seq_default_timer_subdevice, "The default timer subdevice number.");74module_param(seq_default_timer_resolution, int, 0644);75MODULE_PARM_DESC(seq_default_timer_resolution, "The default timer resolution in Hz.");0007677/*78 * INIT PART
···32#include "seq_timer.h"33#include "seq_system.h"34#include "seq_info.h"35+#include <sound/minors.h>36#include <sound/seq_device.h>3738#if defined(CONFIG_SND_SEQ_DUMMY_MODULE)···72MODULE_PARM_DESC(seq_default_timer_subdevice, "The default timer subdevice number.");73module_param(seq_default_timer_resolution, int, 0644);74MODULE_PARM_DESC(seq_default_timer_resolution, "The default timer resolution in Hz.");75+76+MODULE_ALIAS_CHARDEV(CONFIG_SND_MAJOR, SNDRV_MINOR_SEQUENCER);77+MODULE_ALIAS("devname:snd/seq");7879/*80 * INIT PART
+13-5
sound/core/sound.c
···188};189190#ifdef CONFIG_SND_DYNAMIC_MINORS191-static int snd_find_free_minor(void)192{193 int minor;194000000195 for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) {196- /* skip minors still used statically for autoloading devices */197- if (SNDRV_MINOR_DEVICE(minor) == SNDRV_MINOR_CONTROL ||198- minor == SNDRV_MINOR_SEQUENCER)00199 continue;200 if (!snd_minors[minor])201 return minor;···277 preg->private_data = private_data;278 mutex_lock(&sound_mutex);279#ifdef CONFIG_SND_DYNAMIC_MINORS280- minor = snd_find_free_minor();281#else282 minor = snd_kernel_minor(type, card, dev);283 if (minor >= 0 && snd_minors[minor])
···188};189190#ifdef CONFIG_SND_DYNAMIC_MINORS191+static int snd_find_free_minor(int type)192{193 int minor;194195+ /* static minors for module auto loading */196+ if (type == SNDRV_DEVICE_TYPE_SEQUENCER)197+ return SNDRV_MINOR_SEQUENCER;198+ if (type == SNDRV_DEVICE_TYPE_TIMER)199+ return SNDRV_MINOR_TIMER;200+201 for (minor = 0; minor < ARRAY_SIZE(snd_minors); ++minor) {202+ /* skip static minors still used for module auto loading */203+ if (SNDRV_MINOR_DEVICE(minor) == SNDRV_MINOR_CONTROL)204+ continue;205+ if (minor == SNDRV_MINOR_SEQUENCER ||206+ minor == SNDRV_MINOR_TIMER)207 continue;208 if (!snd_minors[minor])209 return minor;···269 preg->private_data = private_data;270 mutex_lock(&sound_mutex);271#ifdef CONFIG_SND_DYNAMIC_MINORS272+ minor = snd_find_free_minor(type);273#else274 minor = snd_kernel_minor(type, card, dev);275 if (minor >= 0 && snd_minors[minor])
···67{68 chip->init = 1; /* don't schedule new work */69 mb();70+ cancel_delayed_work_sync(&chip->work);071 kfree(chip);72}73···154{155 chip->init = 1;156 mb();157+ flush_delayed_work_sync(&chip->work);158 ak4114_init_regs(chip);159 /* bring up statistics / event queing */160 chip->init = 0;
+8-15
sound/pci/Kconfig
···209 tristate210211config SND_OXYGEN212- tristate "C-Media 8788 (Oxygen)"213 select SND_OXYGEN_LIB214 select SND_PCM215 select SND_MPU401_UART···217 Say Y here to include support for sound cards based on the218 C-Media CMI8788 (Oxygen HD Audio) chip:219 * Asound A-87880220 * AuzenTech X-Meridian0221 * Bgears b-Enspirer222 * Club3D Theatron DTS223 * HT-Omega Claro (plus)224 * HT-Omega Claro halo (XT)0225 * Razer Barracuda AC-1226 * Sondigo Inferno00227228 To compile this driver as a module, choose M here: the module229 will be called snd-oxygen.···583 To compile this driver as a module, choose M here: the module584 will be called snd-hdspm.585586-config SND_HIFIER587- tristate "TempoTec HiFier Fantasia"588- select SND_OXYGEN_LIB589- select SND_PCM590- select SND_MPU401_UART591- help592- Say Y here to include support for the MediaTek/TempoTec HiFier593- Fantasia sound card.594-595- To compile this driver as a module, choose M here: the module596- will be called snd-hifier.597-598config SND_ICE1712599 tristate "ICEnsemble ICE1712 (Envy24)"600 select SND_MPU401_UART···819 Say Y here to include support for sound cards based on the820 Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS,821 Essence ST (Deluxe), and Essence STX.822- Support for the HDAV1.3 (Deluxe) is incomplete; for the823- HDAV1.3 Slim and Xense, missing.824825 To compile this driver as a module, choose M here: the module826 will be called snd-virtuoso.
···209 tristate210211config SND_OXYGEN212+ tristate "C-Media 8786, 8787, 8788 (Oxygen)"213 select SND_OXYGEN_LIB214 select SND_PCM215 select SND_MPU401_UART···217 Say Y here to include support for sound cards based on the218 C-Media CMI8788 (Oxygen HD Audio) chip:219 * Asound A-8788220+ * Asus Xonar DG221 * AuzenTech X-Meridian222+ * AuzenTech X-Meridian 2G223 * Bgears b-Enspirer224 * Club3D Theatron DTS225 * HT-Omega Claro (plus)226 * HT-Omega Claro halo (XT)227+ * Kuroutoshikou CMI8787-HG2PCI228 * Razer Barracuda AC-1229 * Sondigo Inferno230+ * TempoTec/MediaTek HiFier Fantasia231+ * TempoTec/MediaTek HiFier Serenade232233 To compile this driver as a module, choose M here: the module234 will be called snd-oxygen.···578 To compile this driver as a module, choose M here: the module579 will be called snd-hdspm.580000000000000581config SND_ICE1712582 tristate "ICEnsemble ICE1712 (Envy24)"583 select SND_MPU401_UART···826 Say Y here to include support for sound cards based on the827 Asus AV66/AV100/AV200 chips, i.e., Xonar D1, DX, D2, D2X, DS,828 Essence ST (Deluxe), and Essence STX.829+ Support for the HDAV1.3 (Deluxe) and HDAV1.3 Slim is experimental;830+ for the Xense, missing.831832 To compile this driver as a module, choose M here: the module833 will be called snd-virtuoso.
+2-4
sound/pci/ac97/ac97_codec.c
···1014{1015 if (ac97) {1016#ifdef CONFIG_SND_AC97_POWER_SAVE1017- cancel_delayed_work(&ac97->power_work);1018- flush_scheduled_work();1019#endif1020 snd_ac97_proc_done(ac97);1021 if (ac97->bus)···2455 if (ac97->build_ops->suspend)2456 ac97->build_ops->suspend(ac97);2457#ifdef CONFIG_SND_AC97_POWER_SAVE2458- cancel_delayed_work(&ac97->power_work);2459- flush_scheduled_work();2460#endif2461 snd_ac97_powerdown(ac97);2462}
···1014{1015 if (ac97) {1016#ifdef CONFIG_SND_AC97_POWER_SAVE1017+ cancel_delayed_work_sync(&ac97->power_work);01018#endif1019 snd_ac97_proc_done(ac97);1020 if (ac97->bus)···2456 if (ac97->build_ops->suspend)2457 ac97->build_ops->suspend(ac97);2458#ifdef CONFIG_SND_AC97_POWER_SAVE2459+ cancel_delayed_work_sync(&ac97->power_work);02460#endif2461 snd_ac97_powerdown(ac97);2462}
+205-201
sound/pci/azt3328.c
···1/*2 * azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168).3- * Copyright (C) 2002, 2005 - 2009 by Andreas Mohr <andi AT lisas.de>4 *5 * Framework borrowed from Bart Hartgers's als4000.c.6 * Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801),···175176#include <asm/io.h>177#include <linux/init.h>0178#include <linux/pci.h>179#include <linux/delay.h>180#include <linux/slab.h>···202203/* === Debug settings ===204 Further diagnostic functionality than the settings below205- does not need to be provided, since one can easily write a bash script206 to dump the card's I/O ports (those listed in lspci -v -v):207- function dump()208 {209 local descr=$1; local addr=$2; local count=$3210211 echo "${descr}: ${count} @ ${addr}:"212- dd if=/dev/port skip=$[${addr}] count=${count} bs=1 2>/dev/null| hexdump -C0213 }214 and then use something like215 "dump joy200 0x200 8", "dump mpu388 0x388 4", "dump joy 0xb400 8",···218 possibly within a "while true; do ... sleep 1; done" loop.219 Tweaking ports could be done using220 VALSTRING="`printf "%02x" $value`"221- printf "\x""$VALSTRING"|dd of=/dev/port seek=$[${addr}] bs=1 2>/dev/null0222*/223224#define DEBUG_MISC 0225#define DEBUG_CALLS 0226#define DEBUG_MIXER 0227#define DEBUG_CODEC 0228-#define DEBUG_IO 0229#define DEBUG_TIMER 0230#define DEBUG_GAME 0231#define DEBUG_PM 0···293module_param(seqtimer_scaling, int, 0444);294MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128.");295296-struct snd_azf3328_codec_data {297- unsigned long io_base;298- struct snd_pcm_substream *substream;299- bool running;300- const char *name;301-};302-303enum snd_azf3328_codec_type {0304 AZF_CODEC_PLAYBACK = 0,305 AZF_CODEC_CAPTURE = 1,306 AZF_CODEC_I2S_OUT = 2,0000000000307};308309struct snd_azf3328 {···368static int369snd_azf3328_io_reg_setb(unsigned reg, u8 mask, bool do_set)370{000371 u8 prev = inb(reg), new;372373 new = (do_set) ? (prev|mask) : (prev & ~mask);···420)421{422 outl(value, codec->io_base + reg);000000000000000423}424425static inline u32···967}968969static void970-snd_azf3328_codec_setfmt(struct snd_azf3328 *chip,971- enum snd_azf3328_codec_type codec_type,972 enum azf_freq_t bitrate,973 unsigned int format_width,974 unsigned int channels975)976{977 unsigned long flags;978- const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];979 u16 val = 0xff00;0980981 snd_azf3328_dbgcallenter();982 switch (bitrate) {983- case AZF_FREQ_4000: val |= SOUNDFORMAT_FREQ_SUSPECTED_4000; break;984- case AZF_FREQ_4800: val |= SOUNDFORMAT_FREQ_SUSPECTED_4800; break;985- case AZF_FREQ_5512:986- /* the AZF3328 names it "5510" for some strange reason */987- val |= SOUNDFORMAT_FREQ_5510; break;988- case AZF_FREQ_6620: val |= SOUNDFORMAT_FREQ_6620; break;989- case AZF_FREQ_8000: val |= SOUNDFORMAT_FREQ_8000; break;990- case AZF_FREQ_9600: val |= SOUNDFORMAT_FREQ_9600; break;991- case AZF_FREQ_11025: val |= SOUNDFORMAT_FREQ_11025; break;992- case AZF_FREQ_13240: val |= SOUNDFORMAT_FREQ_SUSPECTED_13240; break;993- case AZF_FREQ_16000: val |= SOUNDFORMAT_FREQ_16000; break;994- case AZF_FREQ_22050: val |= SOUNDFORMAT_FREQ_22050; break;995- case AZF_FREQ_32000: val |= SOUNDFORMAT_FREQ_32000; break;00000996 default:997 snd_printk(KERN_WARNING "unknown bitrate %d, assuming 44.1kHz!\n", bitrate);998 /* fall-through */999- case AZF_FREQ_44100: val |= SOUNDFORMAT_FREQ_44100; break;1000- case AZF_FREQ_48000: val |= SOUNDFORMAT_FREQ_48000; break;1001- case AZF_FREQ_66200: val |= SOUNDFORMAT_FREQ_SUSPECTED_66200; break;01002 }1003 /* val = 0xff07; 3m27.993s (65301Hz; -> 64000Hz???) hmm, 66120, 65967, 66123 */1004 /* val = 0xff09; 17m15.098s (13123,478Hz; -> 12000Hz???) hmm, 13237.2Hz? */···1015 /* val = 0xff0d; 41m23.135s (5523,600Hz; -> 5512Hz???) */1016 /* val = 0xff0e; 28m30.777s (8017Hz; -> 8000Hz???) */1017001018 if (channels == 2)1019 val |= SOUNDFORMAT_FLAG_2CHANNELS;10201021 if (format_width == 16)1022 val |= SOUNDFORMAT_FLAG_16BIT;10231024- spin_lock_irqsave(&chip->reg_lock, flags);10251026 /* set bitrate/format */1027 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val);···1035 * (FIXME: yes, it works, but what exactly am I doing here?? :)1036 * FIXME: does this have some side effects for full-duplex1037 * or other dramatic side effects? */1038- if (codec_type == AZF_CODEC_PLAYBACK) /* only do it for playback */01039 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,1040 snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS) |1041 DMA_RUN_SOMETHING1 |···1046 DMA_SOMETHING_ELSE1047 );10481049- spin_unlock_irqrestore(&chip->reg_lock, flags);1050 snd_azf3328_dbgcallleave();1051}10521053static inline void1054-snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328 *chip,1055- enum snd_azf3328_codec_type codec_type1056)1057{1058 /* choose lowest frequency for low power consumption.1059 * While this will cause louder noise due to rather coarse frequency,1060 * it should never matter since output should always1061 * get disabled properly when idle anyway. */1062- snd_azf3328_codec_setfmt(chip, codec_type, AZF_FREQ_4000, 8, 1);1063}10641065static void···1132 /* ...and adjust clock, too1133 * (reduce noise and power consumption) */1134 if (!enable)1135- snd_azf3328_codec_setfmt_lowpower(1136- chip,1137- codec_type1138- );1139 codec->running = enable;1140 }1141}11421143static void1144-snd_azf3328_codec_setdmaa(struct snd_azf3328 *chip,1145- enum snd_azf3328_codec_type codec_type,1146 unsigned long addr,1147- unsigned int count,1148- unsigned int size1149)1150{1151- const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];1152 snd_azf3328_dbgcallenter();00001153 if (!codec->running) {1154 /* AZF3328 uses a two buffer pointer DMA transfer approach */11551156- unsigned long flags, addr_area2;11571158 /* width 32bit (prevent overflow): */1159- u32 count_areas, lengths;0000011601161- count_areas = size/2;1162- addr_area2 = addr+count_areas;1163- snd_azf3328_dbgcodec("setdma: buffers %08lx[%u] / %08lx[%u]\n",1164- addr, count_areas, addr_area2, count_areas);11651166- count_areas--; /* max. index */00000000000000011671168 /* build combined I/O buffer length word */1169- lengths = (count_areas << 16) | (count_areas);1170- spin_lock_irqsave(&chip->reg_lock, flags);1171- snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_1, addr);1172- snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_START_2,1173- addr_area2);1174- snd_azf3328_codec_outl(codec, IDX_IO_CODEC_DMA_LENGTHS,1175- lengths);1176- spin_unlock_irqrestore(&chip->reg_lock, flags);1177 }1178 snd_azf3328_dbgcallleave();1179}11801181static int1182-snd_azf3328_codec_prepare(struct snd_pcm_substream *substream)1183{1184-#if 01185- struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);1186 struct snd_pcm_runtime *runtime = substream->runtime;001187 unsigned int size = snd_pcm_lib_buffer_bytes(substream);1188 unsigned int count = snd_pcm_lib_period_bytes(substream);1189#endif11901191 snd_azf3328_dbgcallenter();0001192#if 01193- snd_azf3328_codec_setfmt(chip, AZF_CODEC_...,1194 runtime->rate,1195 snd_pcm_format_width(runtime->format),1196 runtime->channels);1197- snd_azf3328_codec_setdmaa(chip, AZF_CODEC_...,1198 runtime->dma_addr, count, size);1199#endif1200 snd_azf3328_dbgcallleave();···1220}12211222static int1223-snd_azf3328_codec_trigger(enum snd_azf3328_codec_type codec_type,1224- struct snd_pcm_substream *substream, int cmd)1225{1226 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);1227- const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];1228 struct snd_pcm_runtime *runtime = substream->runtime;01229 int result = 0;1230 u16 flags1;1231 bool previously_muted = 0;1232- bool is_playback_codec = (AZF_CODEC_PLAYBACK == codec_type);12331234- snd_azf3328_dbgcalls("snd_azf3328_codec_trigger cmd %d\n", cmd);12351236 switch (cmd) {1237 case SNDRV_PCM_TRIGGER_START:1238 snd_azf3328_dbgcodec("START %s\n", codec->name);12391240- if (is_playback_codec) {1241 /* mute WaveOut (avoid clicking during setup) */1242 previously_muted =1243 snd_azf3328_mixer_set_mute(···1244 );1245 }12461247- snd_azf3328_codec_setfmt(chip, codec_type,1248 runtime->rate,1249 snd_pcm_format_width(runtime->format),1250 runtime->channels);12511252- spin_lock(&chip->reg_lock);1253 /* first, remember current value: */1254 flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS);1255···12591260 /* FIXME: clear interrupts or what??? */1261 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff);1262- spin_unlock(&chip->reg_lock);12631264- snd_azf3328_codec_setdmaa(chip, codec_type, runtime->dma_addr,1265 snd_pcm_lib_period_bytes(substream),1266 snd_pcm_lib_buffer_bytes(substream)1267 );12681269- spin_lock(&chip->reg_lock);1270#ifdef WIN9X1271 /* FIXME: enable playback/recording??? */1272 flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2;···1290 DMA_EPILOGUE_SOMETHING |1291 DMA_SOMETHING_ELSE);1292#endif1293- spin_unlock(&chip->reg_lock);1294- snd_azf3328_ctrl_codec_activity(chip, codec_type, 1);12951296- if (is_playback_codec) {1297 /* now unmute WaveOut */1298 if (!previously_muted)1299 snd_azf3328_mixer_set_mute(···1306 case SNDRV_PCM_TRIGGER_RESUME:1307 snd_azf3328_dbgcodec("RESUME %s\n", codec->name);1308 /* resume codec if we were active */1309- spin_lock(&chip->reg_lock);1310 if (codec->running)1311 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,1312 snd_azf3328_codec_inw(1313 codec, IDX_IO_CODEC_DMA_FLAGS1314 ) | DMA_RESUME1315 );1316- spin_unlock(&chip->reg_lock);1317 break;1318 case SNDRV_PCM_TRIGGER_STOP:1319 snd_azf3328_dbgcodec("STOP %s\n", codec->name);13201321- if (is_playback_codec) {1322 /* mute WaveOut (avoid clicking during setup) */1323 previously_muted =1324 snd_azf3328_mixer_set_mute(···1326 );1327 }13281329- spin_lock(&chip->reg_lock);1330 /* first, remember current value: */1331 flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS);1332···13411342 flags1 &= ~DMA_RUN_SOMETHING1;1343 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);1344- spin_unlock(&chip->reg_lock);1345- snd_azf3328_ctrl_codec_activity(chip, codec_type, 0);13461347- if (is_playback_codec) {1348 /* now unmute WaveOut */1349 if (!previously_muted)1350 snd_azf3328_mixer_set_mute(···1378 return result;1379}13801381-static int1382-snd_azf3328_codec_playback_trigger(struct snd_pcm_substream *substream, int cmd)1383-{1384- return snd_azf3328_codec_trigger(AZF_CODEC_PLAYBACK, substream, cmd);1385-}1386-1387-static int1388-snd_azf3328_codec_capture_trigger(struct snd_pcm_substream *substream, int cmd)1389-{1390- return snd_azf3328_codec_trigger(AZF_CODEC_CAPTURE, substream, cmd);1391-}1392-1393-static int1394-snd_azf3328_codec_i2s_out_trigger(struct snd_pcm_substream *substream, int cmd)1395-{1396- return snd_azf3328_codec_trigger(AZF_CODEC_I2S_OUT, substream, cmd);1397-}1398-1399static snd_pcm_uframes_t1400-snd_azf3328_codec_pointer(struct snd_pcm_substream *substream,1401- enum snd_azf3328_codec_type codec_type1402)1403{1404- const struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);1405- const struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];1406- unsigned long bufptr, result;1407 snd_pcm_uframes_t frmres;14081409-#ifdef QUERY_HARDWARE1410- bufptr = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_START_1);1411-#else1412- bufptr = substream->runtime->dma_addr;1413-#endif1414 result = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_CURRPOS);14151416 /* calculate offset */1417- result -= bufptr;00001418 frmres = bytes_to_frames( substream->runtime, result);1419- snd_azf3328_dbgcodec("%s @ 0x%8lx, frames %8ld\n",1420- codec->name, result, frmres);1421 return frmres;1422-}1423-1424-static snd_pcm_uframes_t1425-snd_azf3328_codec_playback_pointer(struct snd_pcm_substream *substream)1426-{1427- return snd_azf3328_codec_pointer(substream, AZF_CODEC_PLAYBACK);1428-}1429-1430-static snd_pcm_uframes_t1431-snd_azf3328_codec_capture_pointer(struct snd_pcm_substream *substream)1432-{1433- return snd_azf3328_codec_pointer(substream, AZF_CODEC_CAPTURE);1434-}1435-1436-static snd_pcm_uframes_t1437-snd_azf3328_codec_i2s_out_pointer(struct snd_pcm_substream *substream)1438-{1439- return snd_azf3328_codec_pointer(substream, AZF_CODEC_I2S_OUT);1440}14411442/******************************************************************/···1542 }1543 }15441545- /* trigger next axes sampling, to be evaluated the next time we1546 * enter this function */15471548 /* for some very, very strange reason we cannot enable···1634}16351636static inline void1637-snd_azf3328_codec_interrupt(struct snd_azf3328 *chip, u8 status)001638{1639 u8 which;1640 enum snd_azf3328_codec_type codec_type;1641- const struct snd_azf3328_codec_data *codec;16421643 for (codec_type = AZF_CODEC_PLAYBACK;1644 codec_type <= AZF_CODEC_I2S_OUT;1645- ++codec_type) {16461647 /* skip codec if there's no interrupt for it */1648 if (!(status & (1 << codec_type)))1649 continue;16501651- codec = &chip->codecs[codec_type];1652-1653- spin_lock(&chip->reg_lock);1654 which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE);1655 /* ack all IRQ types immediately */1656 snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which);1657- spin_unlock(&chip->reg_lock);16581659- if ((chip->pcm[codec_type]) && (codec->substream)) {1660 snd_pcm_period_elapsed(codec->substream);1661 snd_azf3328_dbgcodec("%s period done (#%x), @ %x\n",1662 codec->name,···1711 }17121713 if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT))1714- snd_azf3328_codec_interrupt(chip, status);17151716 if (status & IRQ_GAMEPORT)1717 snd_azf3328_gameport_interrupt(chip);···1799{1800 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);1801 struct snd_pcm_runtime *runtime = substream->runtime;018021803 snd_azf3328_dbgcallenter();1804- chip->codecs[codec_type].substream = substream;18051806 /* same parameters for all our codecs - at least we think so... */1807 runtime->hw = snd_azf3328_hardware;18081809 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,1810 &snd_azf3328_hw_constraints_rates);01811 snd_azf3328_dbgcallleave();1812 return 0;1813}18141815static int1816-snd_azf3328_playback_open(struct snd_pcm_substream *substream)1817{1818 return snd_azf3328_pcm_open(substream, AZF_CODEC_PLAYBACK);1819}18201821static int1822-snd_azf3328_capture_open(struct snd_pcm_substream *substream)1823{1824 return snd_azf3328_pcm_open(substream, AZF_CODEC_CAPTURE);1825}18261827static int1828-snd_azf3328_i2s_out_open(struct snd_pcm_substream *substream)1829{1830 return snd_azf3328_pcm_open(substream, AZF_CODEC_I2S_OUT);1831}18321833static int1834-snd_azf3328_pcm_close(struct snd_pcm_substream *substream,1835- enum snd_azf3328_codec_type codec_type1836)1837{1838- struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);018391840 snd_azf3328_dbgcallenter();1841- chip->codecs[codec_type].substream = NULL;1842 snd_azf3328_dbgcallleave();1843 return 0;1844-}1845-1846-static int1847-snd_azf3328_playback_close(struct snd_pcm_substream *substream)1848-{1849- return snd_azf3328_pcm_close(substream, AZF_CODEC_PLAYBACK);1850-}1851-1852-static int1853-snd_azf3328_capture_close(struct snd_pcm_substream *substream)1854-{1855- return snd_azf3328_pcm_close(substream, AZF_CODEC_CAPTURE);1856-}1857-1858-static int1859-snd_azf3328_i2s_out_close(struct snd_pcm_substream *substream)1860-{1861- return snd_azf3328_pcm_close(substream, AZF_CODEC_I2S_OUT);1862}18631864/******************************************************************/18651866static struct snd_pcm_ops snd_azf3328_playback_ops = {1867- .open = snd_azf3328_playback_open,1868- .close = snd_azf3328_playback_close,1869 .ioctl = snd_pcm_lib_ioctl,1870 .hw_params = snd_azf3328_hw_params,1871 .hw_free = snd_azf3328_hw_free,1872- .prepare = snd_azf3328_codec_prepare,1873- .trigger = snd_azf3328_codec_playback_trigger,1874- .pointer = snd_azf3328_codec_playback_pointer1875};18761877static struct snd_pcm_ops snd_azf3328_capture_ops = {1878- .open = snd_azf3328_capture_open,1879- .close = snd_azf3328_capture_close,1880 .ioctl = snd_pcm_lib_ioctl,1881 .hw_params = snd_azf3328_hw_params,1882 .hw_free = snd_azf3328_hw_free,1883- .prepare = snd_azf3328_codec_prepare,1884- .trigger = snd_azf3328_codec_capture_trigger,1885- .pointer = snd_azf3328_codec_capture_pointer1886};18871888static struct snd_pcm_ops snd_azf3328_i2s_out_ops = {1889- .open = snd_azf3328_i2s_out_open,1890- .close = snd_azf3328_i2s_out_close,1891 .ioctl = snd_pcm_lib_ioctl,1892 .hw_params = snd_azf3328_hw_params,1893 .hw_free = snd_azf3328_hw_free,1894- .prepare = snd_azf3328_codec_prepare,1895- .trigger = snd_azf3328_codec_i2s_out_trigger,1896- .pointer = snd_azf3328_codec_i2s_out_pointer1897};18981899static int __devinit···1960 snd_azf3328_dbgtimer("delay was too low (%d)!\n", delay);1961 delay = 49; /* minimum time is 49 ticks */1962 }1963- snd_azf3328_dbgtimer("setting timer countdown value %d, add COUNTDOWN|IRQ\n", delay);1964 delay |= TIMER_COUNTDOWN_ENABLE | TIMER_IRQ_ENABLE;1965 spin_lock_irqsave(&chip->reg_lock, flags);1966 snd_azf3328_ctrl_outl(chip, IDX_IO_TIMER_VALUE, delay);···2174 };2175 u8 dma_init;2176 enum snd_azf3328_codec_type codec_type;021772178 *rchip = NULL;2179···2212 chip->opl3_io = pci_resource_start(pci, 3);2213 chip->mixer_io = pci_resource_start(pci, 4);22142215- chip->codecs[AZF_CODEC_PLAYBACK].io_base =2216- chip->ctrl_io + AZF_IO_OFFS_CODEC_PLAYBACK;2217- chip->codecs[AZF_CODEC_PLAYBACK].name = "PLAYBACK";2218- chip->codecs[AZF_CODEC_CAPTURE].io_base =2219- chip->ctrl_io + AZF_IO_OFFS_CODEC_CAPTURE;2220- chip->codecs[AZF_CODEC_CAPTURE].name = "CAPTURE";2221- chip->codecs[AZF_CODEC_I2S_OUT].io_base =2222- chip->ctrl_io + AZF_IO_OFFS_CODEC_I2S_OUT;2223- chip->codecs[AZF_CODEC_I2S_OUT].name = "I2S_OUT";0000000022242225 if (request_irq(pci->irq, snd_azf3328_interrupt,2226 IRQF_SHARED, card->shortname, chip)) {···2260 struct snd_azf3328_codec_data *codec =2261 &chip->codecs[codec_type];22622263- /* shutdown codecs to save power */2264 /* have ...ctrl_codec_activity() act properly */2265 codec->running = 1;2266 snd_azf3328_ctrl_codec_activity(chip, codec_type, 0);22672268- spin_lock_irq(&chip->reg_lock);2269 snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS,2270 dma_init);2271- spin_unlock_irq(&chip->reg_lock);2272 }22732274 snd_card_set_dev(card, &pci->dev);···24222423 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);242402425 snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]);2426 snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]);2427
···1/*2 * azt3328.c - driver for Aztech AZF3328 based soundcards (e.g. PCI168).3+ * Copyright (C) 2002, 2005 - 2010 by Andreas Mohr <andi AT lisas.de>4 *5 * Framework borrowed from Bart Hartgers's als4000.c.6 * Driver developed on PCI168 AP(W) version (PCI rev. 10, subsystem ID 1801),···175176#include <asm/io.h>177#include <linux/init.h>178+#include <linux/bug.h> /* WARN_ONCE */179#include <linux/pci.h>180#include <linux/delay.h>181#include <linux/slab.h>···201202/* === Debug settings ===203 Further diagnostic functionality than the settings below204+ does not need to be provided, since one can easily write a POSIX shell script205 to dump the card's I/O ports (those listed in lspci -v -v):206+ dump()207 {208 local descr=$1; local addr=$2; local count=$3209210 echo "${descr}: ${count} @ ${addr}:"211+ dd if=/dev/port skip=`printf %d ${addr}` count=${count} bs=1 \212+ 2>/dev/null| hexdump -C213 }214 and then use something like215 "dump joy200 0x200 8", "dump mpu388 0x388 4", "dump joy 0xb400 8",···216 possibly within a "while true; do ... sleep 1; done" loop.217 Tweaking ports could be done using218 VALSTRING="`printf "%02x" $value`"219+ printf "\x""$VALSTRING"|dd of=/dev/port seek=`printf %d ${addr}` bs=1 \220+ 2>/dev/null221*/222223#define DEBUG_MISC 0224#define DEBUG_CALLS 0225#define DEBUG_MIXER 0226#define DEBUG_CODEC 00227#define DEBUG_TIMER 0228#define DEBUG_GAME 0229#define DEBUG_PM 0···291module_param(seqtimer_scaling, int, 0444);292MODULE_PARM_DESC(seqtimer_scaling, "Set 1024000Hz sequencer timer scale factor (lockup danger!). Default 128.");2930000000294enum snd_azf3328_codec_type {295+ /* warning: fixed indices (also used for bitmask checks!) */296 AZF_CODEC_PLAYBACK = 0,297 AZF_CODEC_CAPTURE = 1,298 AZF_CODEC_I2S_OUT = 2,299+};300+301+struct snd_azf3328_codec_data {302+ unsigned long io_base; /* keep first! (avoid offset calc) */303+ unsigned int dma_base; /* helper to avoid an indirection in hotpath */304+ spinlock_t *lock; /* TODO: convert to our own per-codec lock member */305+ struct snd_pcm_substream *substream;306+ bool running;307+ enum snd_azf3328_codec_type type;308+ const char *name;309};310311struct snd_azf3328 {···362static int363snd_azf3328_io_reg_setb(unsigned reg, u8 mask, bool do_set)364{365+ /* Well, strictly spoken, the inb/outb sequence isn't atomic366+ and would need locking. However we currently don't care367+ since it potentially complicates matters. */368 u8 prev = inb(reg), new;369370 new = (do_set) ? (prev|mask) : (prev & ~mask);···411)412{413 outl(value, codec->io_base + reg);414+}415+416+static inline void417+snd_azf3328_codec_outl_multi(const struct snd_azf3328_codec_data *codec,418+ unsigned reg, const void *buffer, int count419+)420+{421+ unsigned long addr = codec->io_base + reg;422+ if (count) {423+ const u32 *buf = buffer;424+ do {425+ outl(*buf++, addr);426+ addr += 4;427+ } while (--count);428+ }429}430431static inline u32···943}944945static void946+snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec,0947 enum azf_freq_t bitrate,948 unsigned int format_width,949 unsigned int channels950)951{952 unsigned long flags;0953 u16 val = 0xff00;954+ u8 freq = 0;955956 snd_azf3328_dbgcallenter();957 switch (bitrate) {958+#define AZF_FMT_XLATE(in_freq, out_bits) \959+ do { \960+ case AZF_FREQ_ ## in_freq: \961+ freq = SOUNDFORMAT_FREQ_ ## out_bits; \962+ break; \963+ } while (0);964+ AZF_FMT_XLATE(4000, SUSPECTED_4000)965+ AZF_FMT_XLATE(4800, SUSPECTED_4800)966+ /* the AZF3328 names it "5510" for some strange reason: */967+ AZF_FMT_XLATE(5512, 5510)968+ AZF_FMT_XLATE(6620, 6620)969+ AZF_FMT_XLATE(8000, 8000)970+ AZF_FMT_XLATE(9600, 9600)971+ AZF_FMT_XLATE(11025, 11025)972+ AZF_FMT_XLATE(13240, SUSPECTED_13240)973+ AZF_FMT_XLATE(16000, 16000)974+ AZF_FMT_XLATE(22050, 22050)975+ AZF_FMT_XLATE(32000, 32000)976 default:977 snd_printk(KERN_WARNING "unknown bitrate %d, assuming 44.1kHz!\n", bitrate);978 /* fall-through */979+ AZF_FMT_XLATE(44100, 44100)980+ AZF_FMT_XLATE(48000, 48000)981+ AZF_FMT_XLATE(66200, SUSPECTED_66200)982+#undef AZF_FMT_XLATE983 }984 /* val = 0xff07; 3m27.993s (65301Hz; -> 64000Hz???) hmm, 66120, 65967, 66123 */985 /* val = 0xff09; 17m15.098s (13123,478Hz; -> 12000Hz???) hmm, 13237.2Hz? */···986 /* val = 0xff0d; 41m23.135s (5523,600Hz; -> 5512Hz???) */987 /* val = 0xff0e; 28m30.777s (8017Hz; -> 8000Hz???) */988989+ val |= freq;990+991 if (channels == 2)992 val |= SOUNDFORMAT_FLAG_2CHANNELS;993994 if (format_width == 16)995 val |= SOUNDFORMAT_FLAG_16BIT;996997+ spin_lock_irqsave(codec->lock, flags);998999 /* set bitrate/format */1000 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_SOUNDFORMAT, val);···1004 * (FIXME: yes, it works, but what exactly am I doing here?? :)1005 * FIXME: does this have some side effects for full-duplex1006 * or other dramatic side effects? */1007+ /* do it for non-capture codecs only */1008+ if (codec->type != AZF_CODEC_CAPTURE)1009 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,1010 snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS) |1011 DMA_RUN_SOMETHING1 |···1014 DMA_SOMETHING_ELSE1015 );10161017+ spin_unlock_irqrestore(codec->lock, flags);1018 snd_azf3328_dbgcallleave();1019}10201021static inline void1022+snd_azf3328_codec_setfmt_lowpower(struct snd_azf3328_codec_data *codec01023)1024{1025 /* choose lowest frequency for low power consumption.1026 * While this will cause louder noise due to rather coarse frequency,1027 * it should never matter since output should always1028 * get disabled properly when idle anyway. */1029+ snd_azf3328_codec_setfmt(codec, AZF_FREQ_4000, 8, 1);1030}10311032static void···1101 /* ...and adjust clock, too1102 * (reduce noise and power consumption) */1103 if (!enable)1104+ snd_azf3328_codec_setfmt_lowpower(codec);0001105 codec->running = enable;1106 }1107}11081109static void1110+snd_azf3328_codec_setdmaa(struct snd_azf3328_codec_data *codec,01111 unsigned long addr,1112+ unsigned int period_bytes,1113+ unsigned int buffer_bytes1114)1115{01116 snd_azf3328_dbgcallenter();1117+ WARN_ONCE(period_bytes & 1, "odd period length!?\n");1118+ WARN_ONCE(buffer_bytes != 2 * period_bytes,1119+ "missed our input expectations! %u vs. %u\n",1120+ buffer_bytes, period_bytes);1121 if (!codec->running) {1122 /* AZF3328 uses a two buffer pointer DMA transfer approach */11231124+ unsigned long flags;11251126 /* width 32bit (prevent overflow): */1127+ u32 area_length;1128+ struct codec_setup_io {1129+ u32 dma_start_1;1130+ u32 dma_start_2;1131+ u32 dma_lengths;1132+ } __attribute__((packed)) setup_io;11331134+ area_length = buffer_bytes/2;00011351136+ setup_io.dma_start_1 = addr;1137+ setup_io.dma_start_2 = addr+area_length;1138+1139+ snd_azf3328_dbgcodec(1140+ "setdma: buffers %08x[%u] / %08x[%u], %u, %u\n",1141+ setup_io.dma_start_1, area_length,1142+ setup_io.dma_start_2, area_length,1143+ period_bytes, buffer_bytes);1144+1145+ /* Hmm, are we really supposed to decrement this by 1??1146+ Most definitely certainly not: configuring full length does1147+ work properly (i.e. likely better), and BTW we1148+ violated possibly differing frame sizes with this...1149+1150+ area_length--; |* max. index *|1151+ */11521153 /* build combined I/O buffer length word */1154+ setup_io.dma_lengths = (area_length << 16) | (area_length);1155+1156+ spin_lock_irqsave(codec->lock, flags);1157+ snd_azf3328_codec_outl_multi(1158+ codec, IDX_IO_CODEC_DMA_START_1, &setup_io, 31159+ );1160+ spin_unlock_irqrestore(codec->lock, flags);01161 }1162 snd_azf3328_dbgcallleave();1163}11641165static int1166+snd_azf3328_pcm_prepare(struct snd_pcm_substream *substream)1167{001168 struct snd_pcm_runtime *runtime = substream->runtime;1169+ struct snd_azf3328_codec_data *codec = runtime->private_data;1170+#if 01171 unsigned int size = snd_pcm_lib_buffer_bytes(substream);1172 unsigned int count = snd_pcm_lib_period_bytes(substream);1173#endif11741175 snd_azf3328_dbgcallenter();1176+1177+ codec->dma_base = runtime->dma_addr;1178+1179#if 01180+ snd_azf3328_codec_setfmt(codec,1181 runtime->rate,1182 snd_pcm_format_width(runtime->format),1183 runtime->channels);1184+ snd_azf3328_codec_setdmaa(codec,1185 runtime->dma_addr, count, size);1186#endif1187 snd_azf3328_dbgcallleave();···1171}11721173static int1174+snd_azf3328_pcm_trigger(struct snd_pcm_substream *substream, int cmd)01175{1176 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);01177 struct snd_pcm_runtime *runtime = substream->runtime;1178+ struct snd_azf3328_codec_data *codec = runtime->private_data;1179 int result = 0;1180 u16 flags1;1181 bool previously_muted = 0;1182+ bool is_main_mixer_playback_codec = (AZF_CODEC_PLAYBACK == codec->type);11831184+ snd_azf3328_dbgcalls("snd_azf3328_pcm_trigger cmd %d\n", cmd);11851186 switch (cmd) {1187 case SNDRV_PCM_TRIGGER_START:1188 snd_azf3328_dbgcodec("START %s\n", codec->name);11891190+ if (is_main_mixer_playback_codec) {1191 /* mute WaveOut (avoid clicking during setup) */1192 previously_muted =1193 snd_azf3328_mixer_set_mute(···1196 );1197 }11981199+ snd_azf3328_codec_setfmt(codec,1200 runtime->rate,1201 snd_pcm_format_width(runtime->format),1202 runtime->channels);12031204+ spin_lock(codec->lock);1205 /* first, remember current value: */1206 flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS);1207···12111212 /* FIXME: clear interrupts or what??? */1213 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_IRQTYPE, 0xffff);1214+ spin_unlock(codec->lock);12151216+ snd_azf3328_codec_setdmaa(codec, runtime->dma_addr,1217 snd_pcm_lib_period_bytes(substream),1218 snd_pcm_lib_buffer_bytes(substream)1219 );12201221+ spin_lock(codec->lock);1222#ifdef WIN9X1223 /* FIXME: enable playback/recording??? */1224 flags1 |= DMA_RUN_SOMETHING1 | DMA_RUN_SOMETHING2;···1242 DMA_EPILOGUE_SOMETHING |1243 DMA_SOMETHING_ELSE);1244#endif1245+ spin_unlock(codec->lock);1246+ snd_azf3328_ctrl_codec_activity(chip, codec->type, 1);12471248+ if (is_main_mixer_playback_codec) {1249 /* now unmute WaveOut */1250 if (!previously_muted)1251 snd_azf3328_mixer_set_mute(···1258 case SNDRV_PCM_TRIGGER_RESUME:1259 snd_azf3328_dbgcodec("RESUME %s\n", codec->name);1260 /* resume codec if we were active */1261+ spin_lock(codec->lock);1262 if (codec->running)1263 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS,1264 snd_azf3328_codec_inw(1265 codec, IDX_IO_CODEC_DMA_FLAGS1266 ) | DMA_RESUME1267 );1268+ spin_unlock(codec->lock);1269 break;1270 case SNDRV_PCM_TRIGGER_STOP:1271 snd_azf3328_dbgcodec("STOP %s\n", codec->name);12721273+ if (is_main_mixer_playback_codec) {1274 /* mute WaveOut (avoid clicking during setup) */1275 previously_muted =1276 snd_azf3328_mixer_set_mute(···1278 );1279 }12801281+ spin_lock(codec->lock);1282 /* first, remember current value: */1283 flags1 = snd_azf3328_codec_inw(codec, IDX_IO_CODEC_DMA_FLAGS);1284···12931294 flags1 &= ~DMA_RUN_SOMETHING1;1295 snd_azf3328_codec_outw(codec, IDX_IO_CODEC_DMA_FLAGS, flags1);1296+ spin_unlock(codec->lock);1297+ snd_azf3328_ctrl_codec_activity(chip, codec->type, 0);12981299+ if (is_main_mixer_playback_codec) {1300 /* now unmute WaveOut */1301 if (!previously_muted)1302 snd_azf3328_mixer_set_mute(···1330 return result;1331}13320000000000000000001333static snd_pcm_uframes_t1334+snd_azf3328_pcm_pointer(struct snd_pcm_substream *substream01335)1336{1337+ const struct snd_azf3328_codec_data *codec =1338+ substream->runtime->private_data;1339+ unsigned long result;1340 snd_pcm_uframes_t frmres;1341000001342 result = snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_CURRPOS);13431344 /* calculate offset */1345+#ifdef QUERY_HARDWARE1346+ result -= snd_azf3328_codec_inl(codec, IDX_IO_CODEC_DMA_START_1);1347+#else1348+ result -= codec->dma_base;1349+#endif1350 frmres = bytes_to_frames( substream->runtime, result);1351+ snd_azf3328_dbgcodec("%08li %s @ 0x%8lx, frames %8ld\n",1352+ jiffies, codec->name, result, frmres);1353 return frmres;0000000000000000001354}13551356/******************************************************************/···1532 }1533 }15341535+ /* trigger next sampling of axes, to be evaluated the next time we1536 * enter this function */15371538 /* for some very, very strange reason we cannot enable···1624}16251626static inline void1627+snd_azf3328_pcm_interrupt(const struct snd_azf3328_codec_data *first_codec,1628+ u8 status1629+)1630{1631 u8 which;1632 enum snd_azf3328_codec_type codec_type;1633+ const struct snd_azf3328_codec_data *codec = first_codec;16341635 for (codec_type = AZF_CODEC_PLAYBACK;1636 codec_type <= AZF_CODEC_I2S_OUT;1637+ ++codec_type, ++codec) {16381639 /* skip codec if there's no interrupt for it */1640 if (!(status & (1 << codec_type)))1641 continue;16421643+ spin_lock(codec->lock);001644 which = snd_azf3328_codec_inb(codec, IDX_IO_CODEC_IRQTYPE);1645 /* ack all IRQ types immediately */1646 snd_azf3328_codec_outb(codec, IDX_IO_CODEC_IRQTYPE, which);1647+ spin_unlock(codec->lock);16481649+ if (codec->substream) {1650 snd_pcm_period_elapsed(codec->substream);1651 snd_azf3328_dbgcodec("%s period done (#%x), @ %x\n",1652 codec->name,···1701 }17021703 if (status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_I2S_OUT))1704+ snd_azf3328_pcm_interrupt(chip->codecs, status);17051706 if (status & IRQ_GAMEPORT)1707 snd_azf3328_gameport_interrupt(chip);···1789{1790 struct snd_azf3328 *chip = snd_pcm_substream_chip(substream);1791 struct snd_pcm_runtime *runtime = substream->runtime;1792+ struct snd_azf3328_codec_data *codec = &chip->codecs[codec_type];17931794 snd_azf3328_dbgcallenter();1795+ codec->substream = substream;17961797 /* same parameters for all our codecs - at least we think so... */1798 runtime->hw = snd_azf3328_hardware;17991800 snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,1801 &snd_azf3328_hw_constraints_rates);1802+ runtime->private_data = codec;1803 snd_azf3328_dbgcallleave();1804 return 0;1805}18061807static int1808+snd_azf3328_pcm_playback_open(struct snd_pcm_substream *substream)1809{1810 return snd_azf3328_pcm_open(substream, AZF_CODEC_PLAYBACK);1811}18121813static int1814+snd_azf3328_pcm_capture_open(struct snd_pcm_substream *substream)1815{1816 return snd_azf3328_pcm_open(substream, AZF_CODEC_CAPTURE);1817}18181819static int1820+snd_azf3328_pcm_i2s_out_open(struct snd_pcm_substream *substream)1821{1822 return snd_azf3328_pcm_open(substream, AZF_CODEC_I2S_OUT);1823}18241825static int1826+snd_azf3328_pcm_close(struct snd_pcm_substream *substream01827)1828{1829+ struct snd_azf3328_codec_data *codec =1830+ substream->runtime->private_data;18311832 snd_azf3328_dbgcallenter();1833+ codec->substream = NULL;1834 snd_azf3328_dbgcallleave();1835 return 0;0000000000000000001836}18371838/******************************************************************/18391840static struct snd_pcm_ops snd_azf3328_playback_ops = {1841+ .open = snd_azf3328_pcm_playback_open,1842+ .close = snd_azf3328_pcm_close,1843 .ioctl = snd_pcm_lib_ioctl,1844 .hw_params = snd_azf3328_hw_params,1845 .hw_free = snd_azf3328_hw_free,1846+ .prepare = snd_azf3328_pcm_prepare,1847+ .trigger = snd_azf3328_pcm_trigger,1848+ .pointer = snd_azf3328_pcm_pointer1849};18501851static struct snd_pcm_ops snd_azf3328_capture_ops = {1852+ .open = snd_azf3328_pcm_capture_open,1853+ .close = snd_azf3328_pcm_close,1854 .ioctl = snd_pcm_lib_ioctl,1855 .hw_params = snd_azf3328_hw_params,1856 .hw_free = snd_azf3328_hw_free,1857+ .prepare = snd_azf3328_pcm_prepare,1858+ .trigger = snd_azf3328_pcm_trigger,1859+ .pointer = snd_azf3328_pcm_pointer1860};18611862static struct snd_pcm_ops snd_azf3328_i2s_out_ops = {1863+ .open = snd_azf3328_pcm_i2s_out_open,1864+ .close = snd_azf3328_pcm_close,1865 .ioctl = snd_pcm_lib_ioctl,1866 .hw_params = snd_azf3328_hw_params,1867 .hw_free = snd_azf3328_hw_free,1868+ .prepare = snd_azf3328_pcm_prepare,1869+ .trigger = snd_azf3328_pcm_trigger,1870+ .pointer = snd_azf3328_pcm_pointer1871};18721873static int __devinit···1966 snd_azf3328_dbgtimer("delay was too low (%d)!\n", delay);1967 delay = 49; /* minimum time is 49 ticks */1968 }1969+ snd_azf3328_dbgtimer("setting timer countdown value %d\n", delay);1970 delay |= TIMER_COUNTDOWN_ENABLE | TIMER_IRQ_ENABLE;1971 spin_lock_irqsave(&chip->reg_lock, flags);1972 snd_azf3328_ctrl_outl(chip, IDX_IO_TIMER_VALUE, delay);···2180 };2181 u8 dma_init;2182 enum snd_azf3328_codec_type codec_type;2183+ struct snd_azf3328_codec_data *codec_setup;21842185 *rchip = NULL;2186···2217 chip->opl3_io = pci_resource_start(pci, 3);2218 chip->mixer_io = pci_resource_start(pci, 4);22192220+ codec_setup = &chip->codecs[AZF_CODEC_PLAYBACK];2221+ codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_PLAYBACK;2222+ codec_setup->lock = &chip->reg_lock;2223+ codec_setup->type = AZF_CODEC_PLAYBACK;2224+ codec_setup->name = "PLAYBACK";2225+2226+ codec_setup = &chip->codecs[AZF_CODEC_CAPTURE];2227+ codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_CAPTURE;2228+ codec_setup->lock = &chip->reg_lock;2229+ codec_setup->type = AZF_CODEC_CAPTURE;2230+ codec_setup->name = "CAPTURE";2231+2232+ codec_setup = &chip->codecs[AZF_CODEC_I2S_OUT];2233+ codec_setup->io_base = chip->ctrl_io + AZF_IO_OFFS_CODEC_I2S_OUT;2234+ codec_setup->lock = &chip->reg_lock;2235+ codec_setup->type = AZF_CODEC_I2S_OUT;2236+ codec_setup->name = "I2S_OUT";22372238 if (request_irq(pci->irq, snd_azf3328_interrupt,2239 IRQF_SHARED, card->shortname, chip)) {···2257 struct snd_azf3328_codec_data *codec =2258 &chip->codecs[codec_type];22592260+ /* shutdown codecs to reduce power / noise */2261 /* have ...ctrl_codec_activity() act properly */2262 codec->running = 1;2263 snd_azf3328_ctrl_codec_activity(chip, codec_type, 0);22642265+ spin_lock_irq(codec->lock);2266 snd_azf3328_codec_outb(codec, IDX_IO_CODEC_DMA_FLAGS,2267 dma_init);2268+ spin_unlock_irq(codec->lock);2269 }22702271 snd_card_set_dev(card, &pci->dev);···24192420 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);24212422+ /* same pcm object for playback/capture */2423 snd_pcm_suspend_all(chip->pcm[AZF_CODEC_PLAYBACK]);2424 snd_pcm_suspend_all(chip->pcm[AZF_CODEC_I2S_OUT]);2425
···10857 return 0;10858}1085900010860/* almost identical with ALC880 parser... */10861static int alc882_parse_auto_config(struct hda_codec *codec)10862{···10877 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);10878 if (err < 0)10879 return err;10880- err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);00010881 if (err < 0)10882 return err;10883 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],···17049#define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c)1705017051/* add playback controls from the parsed DAC table */17052-/* Based on ALC880 version. But ALC861VD has separate,17053 * different NIDs for mute/unmute switch and volume control */17054static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,17055 const struct auto_pin_cfg *cfg)
···10857 return 0;10858}1085910860+static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,10861+ const struct auto_pin_cfg *cfg);10862+10863/* almost identical with ALC880 parser... */10864static int alc882_parse_auto_config(struct hda_codec *codec)10865{···10874 err = alc880_auto_fill_dac_nids(spec, &spec->autocfg);10875 if (err < 0)10876 return err;10877+ if (codec->vendor_id == 0x10ec0887)10878+ err = alc861vd_auto_create_multi_out_ctls(spec, &spec->autocfg);10879+ else10880+ err = alc880_auto_create_multi_out_ctls(spec, &spec->autocfg);10881 if (err < 0)10882 return err;10883 err = alc880_auto_create_extra_out(spec, spec->autocfg.hp_pins[0],···17043#define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c)1704417045/* add playback controls from the parsed DAC table */17046+/* Based on ALC880 version. But ALC861VD and ALC887 have separate,17047 * different NIDs for mute/unmute switch and volume control */17048static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,17049 const struct auto_pin_cfg *cfg)
···197{198 unsigned int count;199200- /* should not need more than 7.68 us (24 * 320 ns) */201 count = 10;202 while ((oxygen_read8(chip, OXYGEN_SPI_CONTROL) & OXYGEN_SPI_BUSY)203 && count > 0) {204- udelay(1);205 --count;206 }207
···197{198 unsigned int count;199200+ /* should not need more than 30.72 us (24 * 1.28 us) */201 count = 10;202 while ((oxygen_read8(chip, OXYGEN_SPI_CONTROL) & OXYGEN_SPI_BUSY)203 && count > 0) {204+ udelay(4);205 --count;206 }207
+44-27
sound/pci/oxygen/oxygen_lib.c
···202 struct oxygen *chip = entry->private_data;203 int i, j;204205- snd_iprintf(buffer, "CMI8788\n\n");000000206 for (i = 0; i < OXYGEN_IO_SIZE; i += 0x10) {207 snd_iprintf(buffer, "%02x:", i);208 for (j = 0; j < 0x10; ++j)···218 if (mutex_lock_interruptible(&chip->mutex) < 0)219 return;220 if (chip->has_ac97_0) {221- snd_iprintf(buffer, "\nAC97\n");222 for (i = 0; i < 0x80; i += 0x10) {223 snd_iprintf(buffer, "%02x:", i);224 for (j = 0; j < 0x10; j += 2)···228 }229 }230 if (chip->has_ac97_1) {231- snd_iprintf(buffer, "\nAC97 2\n");232 for (i = 0; i < 0x80; i += 0x10) {233 snd_iprintf(buffer, "%02x:", i);234 for (j = 0; j < 0x10; j += 2)···238 }239 }240 mutex_unlock(&chip->mutex);00241}242243static void oxygen_proc_init(struct oxygen *chip)244{245 struct snd_info_entry *entry;246247- if (!snd_card_proc_new(chip->card, "cmi8788", &entry))248 snd_info_set_text_ops(entry, chip, oxygen_proc_read);249}250#else···270 */271 subdevice = oxygen_read_eeprom(chip, 2);272 /* use default ID if EEPROM is missing */273- if (subdevice == 0xffff)274 subdevice = 0x8788;275 /*276 * We use only the subsystem device ID for searching because it is···372 (IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT);373 chip->spdif_pcm_bits = chip->spdif_bits;374375- if (oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_REVISION_2)376- chip->revision = 2;377- else378- chip->revision = 1;379-380- if (chip->revision == 1)381 oxygen_set_bits8(chip, OXYGEN_MISC,382 OXYGEN_MISC_PCI_MEM_W_1_CLOCK);383···409 (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT));410 oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2);411 oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT,412- OXYGEN_RATE_48000 | chip->model.dac_i2s_format |413- OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |414- OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);000415 if (chip->model.device_config & CAPTURE_0_FROM_I2S_1)416 oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,417- OXYGEN_RATE_48000 | chip->model.adc_i2s_format |418- OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |419- OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);000420 else421 oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,422- OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);0423 if (chip->model.device_config & (CAPTURE_0_FROM_I2S_2 |424 CAPTURE_2_FROM_I2S_2))425 oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,426- OXYGEN_RATE_48000 | chip->model.adc_i2s_format |427- OXYGEN_I2S_MCLK_256 | OXYGEN_I2S_BITS_16 |428- OXYGEN_I2S_MASTER | OXYGEN_I2S_BCLK_64);000429 else430 oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,431- OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);0432 oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,433- OXYGEN_I2S_MASTER | OXYGEN_I2S_MUTE_MCLK);0434 oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,435 OXYGEN_SPDIF_OUT_ENABLE |436 OXYGEN_SPDIF_LOOPBACK);···572 oxygen_shutdown(chip);573 if (chip->irq >= 0)574 free_irq(chip->irq, chip);575- flush_scheduled_work();0576 chip->model.cleanup(chip);577 kfree(chip->model_data);578 mutex_destroy(&chip->mutex);···664665 strcpy(card->driver, chip->model.chip);666 strcpy(card->shortname, chip->model.shortname);667- sprintf(card->longname, "%s (rev %u) at %#lx, irq %i",668- chip->model.longname, chip->revision, chip->addr, chip->irq);669 strcpy(card->mixername, chip->model.chip);670 snd_component_add(card, chip->model.chip);671···749 spin_unlock_irq(&chip->reg_lock);750751 synchronize_irq(chip->irq);752- flush_scheduled_work();0753 chip->interrupt_mask = saved_interrupt_mask;754755 pci_disable_device(pci);
···202 struct oxygen *chip = entry->private_data;203 int i, j;204205+ switch (oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_PACKAGE_ID_MASK) {206+ case OXYGEN_PACKAGE_ID_8786: i = '6'; break;207+ case OXYGEN_PACKAGE_ID_8787: i = '7'; break;208+ case OXYGEN_PACKAGE_ID_8788: i = '8'; break;209+ default: i = '?'; break;210+ }211+ snd_iprintf(buffer, "CMI878%c:\n", i);212 for (i = 0; i < OXYGEN_IO_SIZE; i += 0x10) {213 snd_iprintf(buffer, "%02x:", i);214 for (j = 0; j < 0x10; ++j)···212 if (mutex_lock_interruptible(&chip->mutex) < 0)213 return;214 if (chip->has_ac97_0) {215+ snd_iprintf(buffer, "\nAC97:\n");216 for (i = 0; i < 0x80; i += 0x10) {217 snd_iprintf(buffer, "%02x:", i);218 for (j = 0; j < 0x10; j += 2)···222 }223 }224 if (chip->has_ac97_1) {225+ snd_iprintf(buffer, "\nAC97 2:\n");226 for (i = 0; i < 0x80; i += 0x10) {227 snd_iprintf(buffer, "%02x:", i);228 for (j = 0; j < 0x10; j += 2)···232 }233 }234 mutex_unlock(&chip->mutex);235+ if (chip->model.dump_registers)236+ chip->model.dump_registers(chip, buffer);237}238239static void oxygen_proc_init(struct oxygen *chip)240{241 struct snd_info_entry *entry;242243+ if (!snd_card_proc_new(chip->card, "oxygen", &entry))244 snd_info_set_text_ops(entry, chip, oxygen_proc_read);245}246#else···262 */263 subdevice = oxygen_read_eeprom(chip, 2);264 /* use default ID if EEPROM is missing */265+ if (subdevice == 0xffff && oxygen_read_eeprom(chip, 1) == 0xffff)266 subdevice = 0x8788;267 /*268 * We use only the subsystem device ID for searching because it is···364 (IEC958_AES1_CON_PCM_CODER << OXYGEN_SPDIF_CATEGORY_SHIFT);365 chip->spdif_pcm_bits = chip->spdif_bits;366367+ if (!(oxygen_read8(chip, OXYGEN_REVISION) & OXYGEN_REVISION_2))00000368 oxygen_set_bits8(chip, OXYGEN_MISC,369 OXYGEN_MISC_PCI_MEM_W_1_CLOCK);370···406 (OXYGEN_FORMAT_16 << OXYGEN_MULTICH_FORMAT_SHIFT));407 oxygen_write8(chip, OXYGEN_REC_CHANNELS, OXYGEN_REC_CHANNELS_2_2_2);408 oxygen_write16(chip, OXYGEN_I2S_MULTICH_FORMAT,409+ OXYGEN_RATE_48000 |410+ chip->model.dac_i2s_format |411+ OXYGEN_I2S_MCLK(chip->model.dac_mclks) |412+ OXYGEN_I2S_BITS_16 |413+ OXYGEN_I2S_MASTER |414+ OXYGEN_I2S_BCLK_64);415 if (chip->model.device_config & CAPTURE_0_FROM_I2S_1)416 oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,417+ OXYGEN_RATE_48000 |418+ chip->model.adc_i2s_format |419+ OXYGEN_I2S_MCLK(chip->model.adc_mclks) |420+ OXYGEN_I2S_BITS_16 |421+ OXYGEN_I2S_MASTER |422+ OXYGEN_I2S_BCLK_64);423 else424 oxygen_write16(chip, OXYGEN_I2S_A_FORMAT,425+ OXYGEN_I2S_MASTER |426+ OXYGEN_I2S_MUTE_MCLK);427 if (chip->model.device_config & (CAPTURE_0_FROM_I2S_2 |428 CAPTURE_2_FROM_I2S_2))429 oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,430+ OXYGEN_RATE_48000 |431+ chip->model.adc_i2s_format |432+ OXYGEN_I2S_MCLK(chip->model.adc_mclks) |433+ OXYGEN_I2S_BITS_16 |434+ OXYGEN_I2S_MASTER |435+ OXYGEN_I2S_BCLK_64);436 else437 oxygen_write16(chip, OXYGEN_I2S_B_FORMAT,438+ OXYGEN_I2S_MASTER |439+ OXYGEN_I2S_MUTE_MCLK);440 oxygen_write16(chip, OXYGEN_I2S_C_FORMAT,441+ OXYGEN_I2S_MASTER |442+ OXYGEN_I2S_MUTE_MCLK);443 oxygen_clear_bits32(chip, OXYGEN_SPDIF_CONTROL,444 OXYGEN_SPDIF_OUT_ENABLE |445 OXYGEN_SPDIF_LOOPBACK);···557 oxygen_shutdown(chip);558 if (chip->irq >= 0)559 free_irq(chip->irq, chip);560+ flush_work_sync(&chip->spdif_input_bits_work);561+ flush_work_sync(&chip->gpio_work);562 chip->model.cleanup(chip);563 kfree(chip->model_data);564 mutex_destroy(&chip->mutex);···648649 strcpy(card->driver, chip->model.chip);650 strcpy(card->shortname, chip->model.shortname);651+ sprintf(card->longname, "%s at %#lx, irq %i",652+ chip->model.longname, chip->addr, chip->irq);653 strcpy(card->mixername, chip->model.chip);654 snd_component_add(card, chip->model.chip);655···733 spin_unlock_irq(&chip->reg_lock);734735 synchronize_irq(chip->irq);736+ flush_work_sync(&chip->spdif_input_bits_work);737+ flush_work_sync(&chip->gpio_work);738 chip->interrupt_mask = saved_interrupt_mask;739740 pci_disable_device(pci);
···1626{1627 struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec);1628 struct wm8350 *wm8350 = dev_get_platdata(codec->dev);1629- int ret;16301631 wm8350_clear_bits(wm8350, WM8350_JACK_DETECT,1632 WM8350_JDL_ENA | WM8350_JDR_ENA);···1640 priv->hpr.jack = NULL;1641 priv->mic.jack = NULL;16421643- /* cancel any work waiting to be queued. */1644- ret = cancel_delayed_work(&codec->delayed_work);1645-1646 /* if there was any work waiting then we run it now and1647 * wait for its completion */1648- if (ret) {1649- schedule_delayed_work(&codec->delayed_work, 0);1650- flush_scheduled_work();1651- }16521653 wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);1654
···1626{1627 struct wm8350_data *priv = snd_soc_codec_get_drvdata(codec);1628 struct wm8350 *wm8350 = dev_get_platdata(codec->dev);016291630 wm8350_clear_bits(wm8350, WM8350_JACK_DETECT,1631 WM8350_JDL_ENA | WM8350_JDR_ENA);···1641 priv->hpr.jack = NULL;1642 priv->mic.jack = NULL;16430001644 /* if there was any work waiting then we run it now and1645 * wait for its completion */1646+ flush_delayed_work_sync(&codec->delayed_work);00016471648 wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);1649
+1-20
sound/soc/codecs/wm8753.c
···1476 return 0;1477}14781479-/*1480- * This function forces any delayed work to be queued and run.1481- */1482-static int run_delayed_work(struct delayed_work *dwork)1483-{1484- int ret;1485-1486- /* cancel any work waiting to be queued. */1487- ret = cancel_delayed_work(dwork);1488-1489- /* if there was any work waiting then we run it now and1490- * wait for it's completion */1491- if (ret) {1492- schedule_delayed_work(dwork, 0);1493- flush_scheduled_work();1494- }1495- return ret;1496-}1497-1498static int wm8753_probe(struct snd_soc_codec *codec)1499{1500 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);···1525/* power down chip */1526static int wm8753_remove(struct snd_soc_codec *codec)1527{1528- run_delayed_work(&codec->delayed_work);1529 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);15301531 return 0;
···1476 return 0;1477}147800000000000000000001479static int wm8753_probe(struct snd_soc_codec *codec)1480{1481 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);···1544/* power down chip */1545static int wm8753_remove(struct snd_soc_codec *codec)1546{1547+ flush_delayed_work_sync(&codec->delayed_work);1548 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);15491550 return 0;
+3-22
sound/soc/soc-core.c
···67module_param(pmdown_time, int, 0);68MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)");6970-/*71- * This function forces any delayed work to be queued and run.72- */73-static int run_delayed_work(struct delayed_work *dwork)74-{75- int ret;76-77- /* cancel any work waiting to be queued. */78- ret = cancel_delayed_work(dwork);79-80- /* if there was any work waiting then we run it now and81- * wait for it's completion */82- if (ret) {83- schedule_delayed_work(dwork, 0);84- flush_scheduled_work();85- }86- return ret;87-}88-89/* codec register dump */90static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)91{···997998 /* close any waiting streams and save state */999 for (i = 0; i < card->num_rtd; i++) {1000- run_delayed_work(&card->rtd[i].delayed_work);1001 card->rtd[i].codec->suspend_bias_level = card->rtd[i].codec->bias_level;1002 }1003···1670 /* make sure any delayed work runs */1671 for (i = 0; i < card->num_rtd; i++) {1672 struct snd_soc_pcm_runtime *rtd = &card->rtd[i];1673- run_delayed_work(&rtd->delayed_work);1674 }16751676 /* remove and free each DAI */···1701 * now, we're shutting down so no imminent restart. */1702 for (i = 0; i < card->num_rtd; i++) {1703 struct snd_soc_pcm_runtime *rtd = &card->rtd[i];1704- run_delayed_work(&rtd->delayed_work);1705 }17061707 snd_soc_dapm_shutdown(card);
···67module_param(pmdown_time, int, 0);68MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)");69000000000000000000070/* codec register dump */71static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)72{···10161017 /* close any waiting streams and save state */1018 for (i = 0; i < card->num_rtd; i++) {1019+ flush_delayed_work_sync(&card->rtd[i].delayed_work);1020 card->rtd[i].codec->suspend_bias_level = card->rtd[i].codec->bias_level;1021 }1022···1689 /* make sure any delayed work runs */1690 for (i = 0; i < card->num_rtd; i++) {1691 struct snd_soc_pcm_runtime *rtd = &card->rtd[i];1692+ flush_delayed_work_sync(&rtd->delayed_work);1693 }16941695 /* remove and free each DAI */···1720 * now, we're shutting down so no imminent restart. */1721 for (i = 0; i < card->num_rtd; i++) {1722 struct snd_soc_pcm_runtime *rtd = &card->rtd[i];1723+ flush_delayed_work_sync(&rtd->delayed_work);1724 }17251726 snd_soc_dapm_shutdown(card);
+4-1
sound/usb/format.c
···76 format = 1 << UAC_FORMAT_TYPE_I_PCM;77 }78 if (format & (1 << UAC_FORMAT_TYPE_I_PCM)) {79- if (sample_width > sample_bytes * 8) {00080 snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n",81 chip->dev->devnum, fp->iface, fp->altsetting,82 sample_width, sample_bytes);
···76 format = 1 << UAC_FORMAT_TYPE_I_PCM;77 }78 if (format & (1 << UAC_FORMAT_TYPE_I_PCM)) {79+ if (chip->usb_id == USB_ID(0x0582, 0x0016) /* Edirol SD-90 */ &&80+ sample_width == 24 && sample_bytes == 2)81+ sample_bytes = 3;82+ else if (sample_width > sample_bytes * 8) {83 snd_printk(KERN_INFO "%d:%u:%d : sample bitwidth %d in over sample bytes %d\n",84 chip->dev->devnum, fp->iface, fp->altsetting,85 sample_width, sample_bytes);