Merge tag 'asoc-v5.12' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie...
authorTakashi Iwai <tiwai@suse.de>
Wed, 17 Feb 2021 20:16:27 +0000 (21:16 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 17 Feb 2021 20:16:27 +0000 (21:16 +0100)
ASoC: Updates for v5.12

Another quiet release in terms of features, though several of the
drivers got quite a bit of work and there were a lot of general changes
resulting from Morimoto-san's ongoing cleanup work.

 - As ever, lots of hard work by Morimoto-san cleaning up the code and
   making it more consistent.
 - Many improvements in the Intel drivers including a wide range of
   quirks and bug fixes.
 - A KUnit testsuite for the topology code.
 - Support for Ingenic JZ4760(B), Intel AlderLake-P, DT configured
   nVidia cards, Qualcomm lpass-rx-macro and lpass-tx-macro
 - Removal of obsolete SIRF prima/atlas, Txx9 and ZTE zx drivers.

181 files changed:
Documentation/sound/designs/index.rst
Documentation/sound/designs/jack-injection.rst [new file with mode: 0644]
drivers/base/isa.c
drivers/i2c/busses/i2c-elektor.c
drivers/i2c/busses/i2c-pca-isa.c
drivers/input/touchscreen/htcpen.c
drivers/media/radio/radio-isa.c
drivers/media/radio/radio-isa.h
drivers/media/radio/radio-sf16fmr2.c
drivers/net/can/sja1000/tscan1.c
drivers/net/ethernet/3com/3c509.c
drivers/scsi/advansys.c
drivers/scsi/aha1542.c
drivers/scsi/fdomain_isa.c
drivers/scsi/g_NCR5380.c
drivers/watchdog/pcwd.c
include/linux/isa.h
include/sound/core.h
include/sound/hdaudio.h
include/sound/hdaudio_ext.h
include/sound/jack.h
sound/ac97/bus.c
sound/aoa/codecs/onyx.c
sound/aoa/codecs/tas.c
sound/aoa/codecs/toonie.c
sound/aoa/core/alsa.c
sound/aoa/fabrics/layout.c
sound/aoa/soundbus/sysfs.c
sound/arm/aaci.c
sound/arm/pxa2xx-ac97.c
sound/core/Kconfig
sound/core/compress_offload.c
sound/core/control.c
sound/core/ctljack.c
sound/core/hwdep.c
sound/core/init.c
sound/core/jack.c
sound/core/oss/mixer_oss.c
sound/core/oss/rate.c
sound/core/pcm.c
sound/core/pcm_local.h
sound/core/pcm_memory.c
sound/core/pcm_native.c
sound/core/rawmidi.c
sound/core/seq/oss/seq_oss_midi.c
sound/core/seq/oss/seq_oss_synth.c
sound/core/seq/seq_clientmgr.c
sound/core/seq/seq_memory.c
sound/core/seq/seq_ports.c
sound/core/sound.c
sound/core/timer.c
sound/core/timer_compat.c
sound/drivers/aloop.c
sound/drivers/dummy.c
sound/drivers/opl3/opl3_oss.c
sound/drivers/opl3/opl3_synth.c
sound/drivers/vx/vx_pcm.c
sound/firewire/bebob/bebob_hwdep.c
sound/firewire/dice/Makefile
sound/firewire/dice/dice-harman.c [new file with mode: 0644]
sound/firewire/dice/dice-hwdep.c
sound/firewire/dice/dice.c
sound/firewire/dice/dice.h
sound/firewire/digi00x/digi00x-hwdep.c
sound/firewire/fireface/ff-hwdep.c
sound/firewire/fireface/ff-protocol-latter.c
sound/firewire/fireworks/fireworks_hwdep.c
sound/firewire/motu/motu-hwdep.c
sound/firewire/oxfw/oxfw-hwdep.c
sound/firewire/tascam/tascam-hwdep.c
sound/hda/Kconfig
sound/hda/ext/hdac_ext_controller.c
sound/hda/hdac_bus.c
sound/hda/hdac_controller.c
sound/hda/hdac_stream.c
sound/hda/hdac_sysfs.c
sound/hda/intel-dsp-config.c
sound/i2c/i2c.c
sound/isa/ad1848/ad1848.c
sound/isa/adlib.c
sound/isa/cmi8328.c
sound/isa/cmi8330.c
sound/isa/cs423x/cs4231.c
sound/isa/cs423x/cs4236.c
sound/isa/es1688/es1688.c
sound/isa/es18xx.c
sound/isa/galaxy/galaxy.c
sound/isa/gus/gusclassic.c
sound/isa/gus/gusextreme.c
sound/isa/gus/gusmax.c
sound/isa/gus/interwave.c
sound/isa/msnd/msnd_pinnacle.c
sound/isa/opl3sa2.c
sound/isa/opti9xx/miro.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/isa/sb/jazz16.c
sound/isa/sb/sb16.c
sound/isa/sb/sb16_csp.c
sound/isa/sb/sb8.c
sound/isa/sb/sb_mixer.c
sound/isa/sc6000.c
sound/isa/sscape.c
sound/isa/wavefront/wavefront.c
sound/oss/dmasound/dmasound_core.c
sound/pci/ad1889.c
sound/pci/ali5451/ali5451.c
sound/pci/als300.c
sound/pci/als4000.c
sound/pci/asihpi/hpidebug.c
sound/pci/au88x0/au88x0.c
sound/pci/aw2/aw2-alsa.c
sound/pci/azt3328.c
sound/pci/bt87x.c
sound/pci/ca0106/ca0106_main.c
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/cs5535audio/cs5535audio.c
sound/pci/cs5535audio/cs5535audio_olpc.c
sound/pci/ctxfi/cthw20k1.c
sound/pci/ctxfi/cthw20k2.c
sound/pci/ctxfi/ctpcm.c
sound/pci/ctxfi/ctresource.c
sound/pci/emu10k1/emu10k1.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emufx.c
sound/pci/emu10k1/memory.c
sound/pci/ens1370.c
sound/pci/es1938.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/hda_auto_parser.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_jack.c
sound/pci/hda/hda_tegra.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/juli.c
sound/pci/ice1712/psc724.c
sound/pci/ice1712/quartet.c
sound/pci/ice1712/wm8776.c
sound/pci/intel8x0m.c
sound/pci/lola/lola.c
sound/pci/lola/lola_clock.c
sound/pci/lola/lola_pcm.c
sound/pci/maestro3.c
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c
sound/pci/sis7019.c
sound/pci/sonicvibes.c
sound/pci/trident/trident_main.c
sound/ppc/keywest.c
sound/soc/qcom/qdsp6/q6afe.c
sound/soc/sh/rcar/core.c
sound/soc/sof/intel/hda-bus.c
sound/soc/sof/intel/hda.h
sound/usb/bcd2000/bcd2000.c
sound/usb/caiaq/audio.c
sound/usb/caiaq/device.c
sound/usb/caiaq/midi.c
sound/usb/card.c
sound/usb/card.h
sound/usb/clock.c
sound/usb/endpoint.c
sound/usb/hiface/chip.c
sound/usb/hiface/pcm.c
sound/usb/implicit.c
sound/usb/mixer.c
sound/usb/mixer_quirks.c
sound/usb/mixer_scarlett.c
sound/usb/mixer_scarlett_gen2.c
sound/usb/mixer_us16x08.c
sound/usb/pcm.c
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/x86/intel_hdmi_audio.c
sound/xen/xen_snd_front_cfg.c

index f074994..1eb08e7 100644 (file)
@@ -14,3 +14,4 @@ Designs and Implementations
    powersave
    oss-emulation
    seq-oss
+   jack-injection
diff --git a/Documentation/sound/designs/jack-injection.rst b/Documentation/sound/designs/jack-injection.rst
new file mode 100644 (file)
index 0000000..f979052
--- /dev/null
@@ -0,0 +1,166 @@
+============================
+ALSA Jack Software Injection
+============================
+
+Simple Introduction On Jack Injection
+=====================================
+
+Here jack injection means users could inject plugin or plugout events
+to the audio jacks through debugfs interface, it is helpful to
+validate ALSA userspace changes. For example, we change the audio
+profile switching code in the pulseaudio, and we want to verify if the
+change works as expected and if the change introduce the regression,
+in this case, we could inject plugin or plugout events to an audio
+jack or to some audio jacks, we don't need to physically access the
+machine and plug/unplug physical devices to the audio jack.
+
+In this design, an audio jack doesn't equal to a physical audio jack.
+Sometimes a physical audio jack contains multi functions, and the
+ALSA driver creates multi ``jack_kctl`` for a ``snd_jack``, here the
+``snd_jack`` represents a physical audio jack and the ``jack_kctl``
+represents a function, for example a physical jack has two functions:
+headphone and mic_in, the ALSA ASoC driver will build 2 ``jack_kctl``
+for this jack. The jack injection is implemented based on the
+``jack_kctl`` instead of ``snd_jack``.
+
+To inject events to audio jacks, we need to enable the jack injection
+via ``sw_inject_enable`` first, once it is enabled, this jack will not
+change the state by hardware events anymore, we could inject plugin or
+plugout events via ``jackin_inject`` and check the jack state via
+``status``, after we finish our test, we need to disable the jack
+injection via ``sw_inject_enable`` too, once it is disabled, the jack
+state will be restored according to the last reported hardware events
+and will change by future hardware events.
+
+The Layout of Jack Injection Interface
+======================================
+
+If users enable the SND_JACK_INJECTION_DEBUG in the kernel, the audio
+jack injection interface will be created as below:
+::
+
+   $debugfs_mount_dir/sound
+   |-- card0
+   |-- |-- HDMI_DP_pcm_10_Jack
+   |-- |-- |-- jackin_inject
+   |-- |-- |-- kctl_id
+   |-- |-- |-- mask_bits
+   |-- |-- |-- status
+   |-- |-- |-- sw_inject_enable
+   |-- |-- |-- type
+   ...
+   |-- |-- HDMI_DP_pcm_9_Jack
+   |--     |-- jackin_inject
+   |--     |-- kctl_id
+   |--     |-- mask_bits
+   |--     |-- status
+   |--     |-- sw_inject_enable
+   |--     |-- type
+   |-- card1
+       |-- HDMI_DP_pcm_5_Jack
+       |-- |-- jackin_inject
+       |-- |-- kctl_id
+       |-- |-- mask_bits
+       |-- |-- status
+       |-- |-- sw_inject_enable
+       |-- |-- type
+       ...
+       |-- Headphone_Jack
+       |-- |-- jackin_inject
+       |-- |-- kctl_id
+       |-- |-- mask_bits
+       |-- |-- status
+       |-- |-- sw_inject_enable
+       |-- |-- type
+       |-- Headset_Mic_Jack
+           |-- jackin_inject
+           |-- kctl_id
+           |-- mask_bits
+           |-- status
+           |-- sw_inject_enable
+           |-- type
+
+The Explanation Of The Nodes
+======================================
+
+kctl_id
+  read-only, get jack_kctl->kctl's id
+  ::
+
+     sound/card1/Headphone_Jack# cat kctl_id
+     Headphone Jack
+
+mask_bits
+  read-only, get jack_kctl's supported events mask_bits
+  ::
+
+     sound/card1/Headphone_Jack# cat mask_bits
+     0x0001 HEADPHONE(0x0001)
+
+status
+  read-only, get jack_kctl's current status
+
+- headphone unplugged:
+
+  ::
+
+     sound/card1/Headphone_Jack# cat status
+     Unplugged
+
+- headphone plugged:
+
+  ::
+
+     sound/card1/Headphone_Jack# cat status
+     Plugged
+
+type
+  read-only, get snd_jack's supported events from type (all supported events on the physical audio jack)
+  ::
+
+     sound/card1/Headphone_Jack# cat type
+     0x7803 HEADPHONE(0x0001) MICROPHONE(0x0002) BTN_3(0x0800) BTN_2(0x1000) BTN_1(0x2000) BTN_0(0x4000)
+
+sw_inject_enable
+  read-write, enable or disable injection
+
+- injection disabled:
+
+  ::
+
+     sound/card1/Headphone_Jack# cat sw_inject_enable
+     Jack: Headphone Jack              Inject Enabled: 0
+
+- injection enabled:
+
+  ::
+
+     sound/card1/Headphone_Jack# cat sw_inject_enable
+     Jack: Headphone Jack              Inject Enabled: 1
+
+- to enable jack injection:
+
+  ::
+
+     sound/card1/Headphone_Jack# echo 1 > sw_inject_enable
+
+- to disable jack injection:
+
+  ::
+
+     sound/card1/Headphone_Jack# echo 0 > sw_inject_enable
+
+jackin_inject
+  write-only, inject plugin or plugout
+
+- to inject plugin:
+
+  ::
+
+     sound/card1/Headphone_Jack# echo 1 > jackin_inject
+
+- to inject plugout:
+
+  ::
+
+     sound/card1/Headphone_Jack# echo 0 > jackin_inject
index 2772f5d..aa47376 100644 (file)
@@ -51,7 +51,7 @@ static int isa_bus_remove(struct device *dev)
        struct isa_driver *isa_driver = dev->platform_data;
 
        if (isa_driver && isa_driver->remove)
-               return isa_driver->remove(dev, to_isa_dev(dev)->id);
+               isa_driver->remove(dev, to_isa_dev(dev)->id);
 
        return 0;
 }
index 140426d..b72a3c3 100644 (file)
@@ -282,7 +282,7 @@ static int elektor_probe(struct device *dev, unsigned int id)
        return -ENODEV;
 }
 
-static int elektor_remove(struct device *dev, unsigned int id)
+static void elektor_remove(struct device *dev, unsigned int id)
 {
        i2c_del_adapter(&pcf_isa_ops);
 
@@ -298,8 +298,6 @@ static int elektor_remove(struct device *dev, unsigned int id)
                iounmap(base_iomem);
                release_mem_region(base, 2);
        }
-
-       return 0;
 }
 
 static struct isa_driver i2c_elektor_driver = {
index f27bc1e..85e8cf5 100644 (file)
@@ -161,7 +161,7 @@ static int pca_isa_probe(struct device *dev, unsigned int id)
        return -ENODEV;
 }
 
-static int pca_isa_remove(struct device *dev, unsigned int id)
+static void pca_isa_remove(struct device *dev, unsigned int id)
 {
        i2c_del_adapter(&pca_isa_ops);
 
@@ -170,8 +170,6 @@ static int pca_isa_remove(struct device *dev, unsigned int id)
                free_irq(irq, &pca_isa_ops);
        }
        release_region(base, IO_SIZE);
-
-       return 0;
 }
 
 static struct isa_driver pca_isa_driver = {
index 2f261a3..056ba76 100644 (file)
@@ -171,7 +171,7 @@ static int htcpen_isa_probe(struct device *dev, unsigned int id)
        return err;
 }
 
-static int htcpen_isa_remove(struct device *dev, unsigned int id)
+static void htcpen_isa_remove(struct device *dev, unsigned int id)
 {
        struct input_dev *htcpen_dev = dev_get_drvdata(dev);
 
@@ -182,8 +182,6 @@ static int htcpen_isa_remove(struct device *dev, unsigned int id)
        release_region(HTCPEN_PORT_INDEX, 2);
        release_region(HTCPEN_PORT_INIT, 1);
        release_region(HTCPEN_PORT_IRQ_CLEAR, 1);
-
-       return 0;
 }
 
 #ifdef CONFIG_PM
index ad2ac16..c591c08 100644 (file)
@@ -273,8 +273,8 @@ err_dev_reg:
        return res;
 }
 
-static int radio_isa_common_remove(struct radio_isa_card *isa,
-                                  unsigned region_size)
+static void radio_isa_common_remove(struct radio_isa_card *isa,
+                                   unsigned region_size)
 {
        const struct radio_isa_ops *ops = isa->drv->ops;
 
@@ -285,7 +285,6 @@ static int radio_isa_common_remove(struct radio_isa_card *isa,
        release_region(isa->io, region_size);
        v4l2_info(&isa->v4l2_dev, "Removed radio card %s\n", isa->drv->card);
        kfree(isa);
-       return 0;
 }
 
 int radio_isa_probe(struct device *pdev, unsigned int dev)
@@ -338,11 +337,11 @@ int radio_isa_probe(struct device *pdev, unsigned int dev)
 }
 EXPORT_SYMBOL_GPL(radio_isa_probe);
 
-int radio_isa_remove(struct device *pdev, unsigned int dev)
+void radio_isa_remove(struct device *pdev, unsigned int dev)
 {
        struct radio_isa_card *isa = dev_get_drvdata(pdev);
 
-       return radio_isa_common_remove(isa, isa->drv->region_size);
+       radio_isa_common_remove(isa, isa->drv->region_size);
 }
 EXPORT_SYMBOL_GPL(radio_isa_remove);
 
index 2f0736e..c915995 100644 (file)
@@ -91,7 +91,7 @@ struct radio_isa_driver {
 
 int radio_isa_match(struct device *pdev, unsigned int dev);
 int radio_isa_probe(struct device *pdev, unsigned int dev);
-int radio_isa_remove(struct device *pdev, unsigned int dev);
+void radio_isa_remove(struct device *pdev, unsigned int dev);
 #ifdef CONFIG_PNP
 int radio_isa_pnp_probe(struct pnp_dev *dev,
                        const struct pnp_device_id *dev_id);
index 0388894..d0dde55 100644 (file)
@@ -293,11 +293,9 @@ static void fmr2_remove(struct fmr2 *fmr2)
        kfree(fmr2);
 }
 
-static int fmr2_isa_remove(struct device *pdev, unsigned int ndev)
+static void fmr2_isa_remove(struct device *pdev, unsigned int ndev)
 {
        fmr2_remove(dev_get_drvdata(pdev));
-
-       return 0;
 }
 
 static void fmr2_pnp_remove(struct pnp_dev *pdev)
index 6ea802c..3dbba8d 100644 (file)
@@ -159,7 +159,7 @@ static int tscan1_probe(struct device *dev, unsigned id)
        return -ENXIO;
 }
 
-static int tscan1_remove(struct device *dev, unsigned id /*unused*/)
+static void tscan1_remove(struct device *dev, unsigned id /*unused*/)
 {
        struct net_device *netdev;
        struct sja1000_priv *priv;
@@ -179,8 +179,6 @@ static int tscan1_remove(struct device *dev, unsigned id /*unused*/)
        release_region(pld_base, TSCAN1_PLD_SIZE);
 
        free_sja1000dev(netdev);
-
-       return 0;
 }
 
 static struct isa_driver tscan1_isa_driver = {
index 667f38c..53e1f7e 100644 (file)
@@ -335,12 +335,11 @@ static int el3_isa_match(struct device *pdev, unsigned int ndev)
        return 1;
 }
 
-static int el3_isa_remove(struct device *pdev,
+static void el3_isa_remove(struct device *pdev,
                                    unsigned int ndev)
 {
        el3_device_remove(pdev);
        dev_set_drvdata(pdev, NULL);
-       return 0;
 }
 
 #ifdef CONFIG_PM
index 79830e7..b1e97f7 100644 (file)
@@ -11459,12 +11459,11 @@ static int advansys_isa_probe(struct device *dev, unsigned int id)
        return err;
 }
 
-static int advansys_isa_remove(struct device *dev, unsigned int id)
+static void advansys_isa_remove(struct device *dev, unsigned int id)
 {
        int ioport = _asc_def_iop_base[id];
        advansys_release(dev_get_drvdata(dev));
        release_region(ioport, ASC_IOADR_GAP);
-       return 0;
 }
 
 static struct isa_driver advansys_isa_driver = {
index dc5667a..e0d8cca 100644 (file)
@@ -1025,12 +1025,11 @@ static int aha1542_isa_match(struct device *pdev, unsigned int ndev)
        return 1;
 }
 
-static int aha1542_isa_remove(struct device *pdev,
+static void aha1542_isa_remove(struct device *pdev,
                                    unsigned int ndev)
 {
        aha1542_release(dev_get_drvdata(pdev));
        dev_set_drvdata(pdev, NULL);
-       return 0;
 }
 
 static struct isa_driver aha1542_isa_driver = {
index e0cdcd2..2b4280a 100644 (file)
@@ -175,7 +175,7 @@ static int fdomain_isa_param_match(struct device *dev, unsigned int ndev)
        return 1;
 }
 
-static int fdomain_isa_remove(struct device *dev, unsigned int ndev)
+static void fdomain_isa_remove(struct device *dev, unsigned int ndev)
 {
        struct Scsi_Host *sh = dev_get_drvdata(dev);
        int base = sh->io_port;
@@ -183,7 +183,6 @@ static int fdomain_isa_remove(struct device *dev, unsigned int ndev)
        fdomain_destroy(sh);
        release_region(base, FDOMAIN_REGION_SIZE);
        dev_set_drvdata(dev, NULL);
-       return 0;
 }
 
 static struct isa_driver fdomain_isa_driver = {
index 2df2f38..7ba3c93 100644 (file)
@@ -720,12 +720,11 @@ static int generic_NCR5380_isa_match(struct device *pdev, unsigned int ndev)
        return 1;
 }
 
-static int generic_NCR5380_isa_remove(struct device *pdev,
-                                      unsigned int ndev)
+static void generic_NCR5380_isa_remove(struct device *pdev,
+                                      unsigned int ndev)
 {
        generic_NCR5380_release_resources(dev_get_drvdata(pdev));
        dev_set_drvdata(pdev, NULL);
-       return 0;
 }
 
 static struct isa_driver generic_NCR5380_isa_driver = {
index e86fa7f..a793b03 100644 (file)
@@ -951,14 +951,11 @@ error_request_region:
        return ret;
 }
 
-static int pcwd_isa_remove(struct device *dev, unsigned int id)
+static void pcwd_isa_remove(struct device *dev, unsigned int id)
 {
        if (debug >= DEBUG)
                pr_debug("pcwd_isa_remove id=%d\n", id);
 
-       if (!pcwd_private.io_addr)
-               return 1;
-
        /*  Disable the board  */
        if (!nowayout)
                pcwd_stop();
@@ -971,8 +968,6 @@ static int pcwd_isa_remove(struct device *dev, unsigned int id)
                        (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
        pcwd_private.io_addr = 0x0000;
        cards_found--;
-
-       return 0;
 }
 
 static void pcwd_isa_shutdown(struct device *dev, unsigned int id)
index 41336da..e309631 100644 (file)
@@ -13,7 +13,7 @@
 struct isa_driver {
        int (*match)(struct device *, unsigned int);
        int (*probe)(struct device *, unsigned int);
-       int (*remove)(struct device *, unsigned int);
+       void (*remove)(struct device *, unsigned int);
        void (*shutdown)(struct device *, unsigned int);
        int (*suspend)(struct device *, unsigned int, pm_message_t);
        int (*resume)(struct device *, unsigned int);
index 0462c57..2e24f19 100644 (file)
@@ -122,6 +122,9 @@ struct snd_card {
 
        size_t total_pcm_alloc_bytes;   /* total amount of allocated buffers */
        struct mutex memory_mutex;      /* protection for the above */
+#ifdef CONFIG_SND_DEBUG
+       struct dentry *debugfs_root;    /* debugfs root for card */
+#endif
 
 #ifdef CONFIG_PM
        unsigned int power_state;       /* power state */
@@ -180,6 +183,9 @@ static inline struct device *snd_card_get_device_link(struct snd_card *card)
 extern int snd_major;
 extern int snd_ecards_limit;
 extern struct class *sound_class;
+#ifdef CONFIG_SND_DEBUG
+extern struct dentry *sound_debugfs_root;
+#endif
 
 void snd_request_card(int card);
 
index 6eed61e..22af68b 100644 (file)
@@ -241,6 +241,8 @@ struct hdac_bus_ops {
        /* get a response from the last command */
        int (*get_response)(struct hdac_bus *bus, unsigned int addr,
                            unsigned int *res);
+       /* notify of codec link power-up/down */
+       void (*link_power)(struct hdac_device *hdev, bool enable);
 };
 
 /*
@@ -378,15 +380,8 @@ void snd_hdac_bus_exit(struct hdac_bus *bus);
 int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr,
                                    unsigned int cmd, unsigned int *res);
 
-static inline void snd_hdac_codec_link_up(struct hdac_device *codec)
-{
-       set_bit(codec->addr, &codec->bus->codec_powered);
-}
-
-static inline void snd_hdac_codec_link_down(struct hdac_device *codec)
-{
-       clear_bit(codec->addr, &codec->bus->codec_powered);
-}
+void snd_hdac_codec_link_up(struct hdac_device *codec);
+void snd_hdac_codec_link_down(struct hdac_device *codec);
 
 int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val);
 int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
@@ -400,6 +395,7 @@ void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus);
 void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus);
 void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus);
 int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset);
+void snd_hdac_bus_link_power(struct hdac_device *hdev, bool enable);
 
 void snd_hdac_bus_update_rirb(struct hdac_bus *bus);
 int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status,
index 7abf74c..a125e38 100644 (file)
@@ -131,6 +131,8 @@ void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link,
 int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, struct hdac_ext_link *link);
 int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *link);
 
+void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable);
+
 /* update register macro */
 #define snd_hdac_updatel(addr, reg, mask, val)         \
        writel(((readl(addr + reg) & ~(mask)) | (val)), \
index 9eb2b5e..1181f53 100644 (file)
@@ -67,6 +67,7 @@ struct snd_jack {
        char name[100];
        unsigned int key[6];   /* Keep in sync with definitions above */
 #endif /* CONFIG_SND_JACK_INPUT_DEV */
+       int hw_status_cache;
        void *private_data;
        void (*private_free)(struct snd_jack *);
 };
index 7985dd8..d9077e9 100644 (file)
@@ -273,7 +273,7 @@ static struct attribute *ac97_controller_device_attrs[] = {
        NULL
 };
 
-static struct attribute_group ac97_adapter_attr_group = {
+static const struct attribute_group ac97_adapter_attr_group = {
        .name   = "ac97_operations",
        .attrs  = ac97_controller_device_attrs,
 };
index 12028b3..1abee84 100644 (file)
@@ -1013,7 +1013,7 @@ static int onyx_i2c_probe(struct i2c_client *client,
                goto fail;
        }
 
-       strlcpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN);
+       strscpy(onyx->codec.name, "onyx", MAX_CODEC_NAME_LEN);
        onyx->codec.owner = THIS_MODULE;
        onyx->codec.init = onyx_init_codec;
        onyx->codec.exit = onyx_exit_codec;
index d3e3757..ac246dd 100644 (file)
@@ -894,7 +894,7 @@ static int tas_i2c_probe(struct i2c_client *client,
        /* seems that half is a saner default */
        tas->drc_range = TAS3004_DRC_MAX / 2;
 
-       strlcpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN);
+       strscpy(tas->codec.name, "tas", MAX_CODEC_NAME_LEN);
        tas->codec.owner = THIS_MODULE;
        tas->codec.init = tas_init_codec;
        tas->codec.exit = tas_exit_codec;
index c2d0144..0da5af1 100644 (file)
@@ -126,7 +126,7 @@ static int __init toonie_init(void)
        if (!toonie)
                return -ENOMEM;
 
-       strlcpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name));
+       strscpy(toonie->codec.name, "toonie", sizeof(toonie->codec.name));
        toonie->codec.owner = THIS_MODULE;
        toonie->codec.init = toonie_init_codec;
        toonie->codec.exit = toonie_exit_codec;
index b610813..7fce858 100644 (file)
@@ -28,10 +28,10 @@ int aoa_alsa_init(char *name, struct module *mod, struct device *dev)
                return err;
        aoa_card = alsa_card->private_data;
        aoa_card->alsa_card = alsa_card;
-       strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver));
-       strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname));
-       strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname));
-       strlcpy(alsa_card->mixername, name, sizeof(alsa_card->mixername));
+       strscpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver));
+       strscpy(alsa_card->shortname, name, sizeof(alsa_card->shortname));
+       strscpy(alsa_card->longname, name, sizeof(alsa_card->longname));
+       strscpy(alsa_card->mixername, name, sizeof(alsa_card->mixername));
        err = snd_card_register(aoa_card->alsa_card);
        if (err < 0) {
                printk(KERN_ERR "snd-aoa: couldn't register alsa card\n");
index d2e85b8..ec4ef18 100644 (file)
@@ -948,7 +948,7 @@ static void layout_attached_codec(struct aoa_codec *codec)
                                ldev->gpio.methods->set_lineout(codec->gpio, 1);
                        ctl = snd_ctl_new1(&lineout_ctl, codec->gpio);
                        if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
-                               strlcpy(ctl->id.name,
+                               strscpy(ctl->id.name,
                                        "Headphone Switch", sizeof(ctl->id.name));
                        ldev->lineout_ctrl = ctl;
                        aoa_snd_ctl_add(ctl);
@@ -962,14 +962,14 @@ static void layout_attached_codec(struct aoa_codec *codec)
                                ctl = snd_ctl_new1(&lineout_detect_choice,
                                                   ldev);
                                if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
-                                       strlcpy(ctl->id.name,
+                                       strscpy(ctl->id.name,
                                                "Headphone Detect Autoswitch",
                                                sizeof(ctl->id.name));
                                aoa_snd_ctl_add(ctl);
                                ctl = snd_ctl_new1(&lineout_detected,
                                                   ldev);
                                if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
-                                       strlcpy(ctl->id.name,
+                                       strscpy(ctl->id.name,
                                                "Headphone Detected",
                                                sizeof(ctl->id.name));
                                ldev->lineout_detected_ctrl = ctl;
index a2d55e1..dead310 100644 (file)
@@ -13,7 +13,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
        int length;
 
        if (*sdev->modalias) {
-               strlcpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1);
+               strscpy(buf, sdev->modalias, sizeof(sdev->modalias) + 1);
                strcat(buf, "\n");
                length = strlen(buf);
        } else {
index a0996c4..f02a91b 100644 (file)
@@ -890,8 +890,8 @@ static struct aaci *aaci_init_card(struct amba_device *dev)
 
        card->private_free = aaci_free_card;
 
-       strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
-       strlcpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));
+       strscpy(card->driver, DRIVER_NAME, sizeof(card->driver));
+       strscpy(card->shortname, "ARM AC'97 Interface", sizeof(card->shortname));
        snprintf(card->longname, sizeof(card->longname),
                 "%s PL%03x rev%u at 0x%08llx, irq %d",
                 card->shortname, amba_part(dev), amba_rev(dev),
@@ -921,7 +921,7 @@ static int aaci_init_pcm(struct aaci *aaci)
                pcm->private_data = aaci;
                pcm->info_flags = 0;
 
-               strlcpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
+               strscpy(pcm->name, DRIVER_NAME, sizeof(pcm->name));
 
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);
index ea8e233..6322e63 100644 (file)
@@ -235,7 +235,7 @@ static int pxa2xx_ac97_probe(struct platform_device *dev)
        if (ret < 0)
                goto err;
 
-       strlcpy(card->driver, dev->dev.driver->name, sizeof(card->driver));
+       strscpy(card->driver, dev->dev.driver->name, sizeof(card->driver));
 
        ret = pxa2xx_ac97_pcm_new(card);
        if (ret)
index d4554f3..a4050f8 100644 (file)
@@ -187,6 +187,15 @@ config SND_CTL_VALIDATION
          from the driver are in the proper ranges or the check of the invalid
          access at out-of-array areas.
 
+config SND_JACK_INJECTION_DEBUG
+       bool "Sound jack injection interface via debugfs"
+       depends on SND_JACK && SND_DEBUG && DEBUG_FS
+       help
+         This option can be used to enable or disable sound jack
+         software injection.
+         Say Y if you are debugging via jack injection interface.
+         If unsure select "N".
+
 config SND_VMASTER
        bool
 
index debc30f..21ce4c0 100644 (file)
@@ -1132,7 +1132,7 @@ static void snd_compress_proc_done(struct snd_compr *compr)
 
 static inline void snd_compress_set_id(struct snd_compr *compr, const char *id)
 {
-       strlcpy(compr->id, id, sizeof(compr->id));
+       strscpy(compr->id, id, sizeof(compr->id));
 }
 #else
 static inline int snd_compress_proc_init(struct snd_compr *compr)
index 3b44378..5165741 100644 (file)
@@ -261,7 +261,7 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
        kctl->id.device = ncontrol->device;
        kctl->id.subdevice = ncontrol->subdevice;
        if (ncontrol->name) {
-               strlcpy(kctl->id.name, ncontrol->name, sizeof(kctl->id.name));
+               strscpy(kctl->id.name, ncontrol->name, sizeof(kctl->id.name));
                if (strcmp(ncontrol->name, kctl->id.name) != 0)
                        pr_warn("ALSA: Control name '%s' truncated to '%s'\n",
                                ncontrol->name, kctl->id.name);
@@ -701,12 +701,12 @@ static int snd_ctl_card_info(struct snd_card *card, struct snd_ctl_file * ctl,
                return -ENOMEM;
        down_read(&snd_ioctl_rwsem);
        info->card = card->number;
-       strlcpy(info->id, card->id, sizeof(info->id));
-       strlcpy(info->driver, card->driver, sizeof(info->driver));
-       strlcpy(info->name, card->shortname, sizeof(info->name));
-       strlcpy(info->longname, card->longname, sizeof(info->longname));
-       strlcpy(info->mixername, card->mixername, sizeof(info->mixername));
-       strlcpy(info->components, card->components, sizeof(info->components));
+       strscpy(info->id, card->id, sizeof(info->id));
+       strscpy(info->driver, card->driver, sizeof(info->driver));
+       strscpy(info->name, card->shortname, sizeof(info->name));
+       strscpy(info->longname, card->longname, sizeof(info->longname));
+       strscpy(info->mixername, card->mixername, sizeof(info->mixername));
+       strscpy(info->components, card->components, sizeof(info->components));
        up_read(&snd_ioctl_rwsem);
        if (copy_to_user(arg, info, sizeof(struct snd_ctl_card_info))) {
                kfree(info);
@@ -836,7 +836,7 @@ static void fill_remaining_elem_value(struct snd_ctl_elem_value *control,
 {
        size_t offset = value_sizes[info->type] * info->count;
 
-       offset = (offset + sizeof(u32) - 1) / sizeof(u32);
+       offset = DIV_ROUND_UP(offset, sizeof(u32));
        memset32((u32 *)control->value.bytes.data + offset, pattern,
                 sizeof(control->value) / sizeof(u32) - offset);
 }
@@ -928,7 +928,7 @@ static int sanity_check_elem_value(struct snd_card *card,
 
        /* check whether the remaining area kept untouched */
        offset = value_sizes[info->type] * info->count;
-       offset = (offset + sizeof(u32) - 1) / sizeof(u32);
+       offset = DIV_ROUND_UP(offset, sizeof(u32));
        p = (u32 *)control->value.bytes.data + offset;
        for (; offset < sizeof(control->value) / sizeof(u32); offset++, p++) {
                if (*p != pattern) {
@@ -2137,7 +2137,7 @@ int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels,
        WARN(strlen(names[info->value.enumerated.item]) >= sizeof(info->value.enumerated.name),
             "ALSA: too long item name '%s'\n",
             names[info->value.enumerated.item]);
-       strlcpy(info->value.enumerated.name,
+       strscpy(info->value.enumerated.name,
                names[info->value.enumerated.item],
                sizeof(info->value.enumerated.name));
        return 0;
index 9be4e28..709b1a9 100644 (file)
@@ -35,7 +35,7 @@ static int get_available_index(struct snd_card *card, const char *name)
 
        sid.index = 0;
        sid.iface = SNDRV_CTL_ELEM_IFACE_CARD;
-       strlcpy(sid.name, name, sizeof(sid.name));
+       strscpy(sid.name, name, sizeof(sid.name));
 
        while (snd_ctl_find_id(card, &sid)) {
                sid.index++;
index 0c02989..264b8ea 100644 (file)
@@ -177,8 +177,8 @@ static int snd_hwdep_info(struct snd_hwdep *hw,
        
        memset(&info, 0, sizeof(info));
        info.card = hw->card->number;
-       strlcpy(info.id, hw->id, sizeof(info.id));      
-       strlcpy(info.name, hw->name, sizeof(info.name));
+       strscpy(info.id, hw->id, sizeof(info.id));
+       strscpy(info.name, hw->name, sizeof(info.name));
        info.iface = hw->iface;
        if (copy_to_user(_info, &info, sizeof(info)))
                return -EFAULT;
@@ -379,7 +379,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device,
        hwdep->card = card;
        hwdep->device = device;
        if (id)
-               strlcpy(hwdep->id, id, sizeof(hwdep->id));
+               strscpy(hwdep->id, id, sizeof(hwdep->id));
 
        snd_device_initialize(&hwdep->dev, card);
        hwdep->dev.release = release_hwdep_device;
index 75aec71..45f4b01 100644 (file)
@@ -13,7 +13,9 @@
 #include <linux/time.h>
 #include <linux/ctype.h>
 #include <linux/pm.h>
+#include <linux/debugfs.h>
 #include <linux/completion.h>
+#include <linux/interrupt.h>
 
 #include <sound/core.h>
 #include <sound/control.h>
@@ -161,6 +163,9 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
 {
        struct snd_card *card;
        int err;
+#ifdef CONFIG_SND_DEBUG
+       char name[8];
+#endif
 
        if (snd_BUG_ON(!card_ret))
                return -EINVAL;
@@ -174,7 +179,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
        if (extra_size > 0)
                card->private_data = (char *)card + sizeof(struct snd_card);
        if (xid)
-               strlcpy(card->id, xid, sizeof(card->id));
+               strscpy(card->id, xid, sizeof(card->id));
        err = 0;
        mutex_lock(&snd_card_mutex);
        if (idx < 0) /* first check the matching module-name slot */
@@ -244,6 +249,12 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
                dev_err(parent, "unable to create card info\n");
                goto __error_ctl;
        }
+
+#ifdef CONFIG_SND_DEBUG
+       sprintf(name, "card%d", idx);
+       card->debugfs_root = debugfs_create_dir(name, sound_debugfs_root);
+#endif
+
        *card_ret = card;
        return 0;
 
@@ -416,6 +427,9 @@ int snd_card_disconnect(struct snd_card *card)
        /* notify all devices that we are disconnected */
        snd_device_disconnect_all(card);
 
+       if (card->sync_irq > 0)
+               synchronize_irq(card->sync_irq);
+
        snd_info_card_disconnect(card);
        if (card->registered) {
                device_del(&card->card_dev);
@@ -477,6 +491,10 @@ static int snd_card_do_free(struct snd_card *card)
                dev_warn(card->dev, "unable to free card info\n");
                /* Not fatal error */
        }
+#ifdef CONFIG_SND_DEBUG
+       debugfs_remove(card->debugfs_root);
+       card->debugfs_root = NULL;
+#endif
        if (card->release_completion)
                complete(card->release_completion);
        kfree(card);
@@ -526,6 +544,7 @@ int snd_card_free(struct snd_card *card)
                return ret;
        /* wait, until all devices are ready for the free operation */
        wait_for_completion(&released);
+
        return 0;
 }
 EXPORT_SYMBOL(snd_card_free);
@@ -623,7 +642,7 @@ static void snd_card_set_id_no_lock(struct snd_card *card, const char *src,
        /* last resort... */
        dev_err(card->dev, "unable to set card id (%s)\n", id);
        if (card->proc_root->name)
-               strlcpy(card->id, card->proc_root->name, sizeof(card->id));
+               strscpy(card->id, card->proc_root->name, sizeof(card->id));
 }
 
 /**
index 503c8af..32350c6 100644 (file)
@@ -8,6 +8,9 @@
 #include <linux/input.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/mm.h>
+#include <linux/debugfs.h>
 #include <sound/jack.h>
 #include <sound/core.h>
 #include <sound/control.h>
@@ -16,6 +19,11 @@ struct snd_jack_kctl {
        struct snd_kcontrol *kctl;
        struct list_head list;  /* list of controls belong to the same jack */
        unsigned int mask_bits; /* only masked status bits are reported via kctl */
+       struct snd_jack *jack;  /* pointer to struct snd_jack */
+       bool sw_inject_enable;  /* allow to inject plug event via debugfs */
+#ifdef CONFIG_SND_JACK_INJECTION_DEBUG
+       struct dentry *jack_debugfs_root; /* jack_kctl debugfs root */
+#endif
 };
 
 #ifdef CONFIG_SND_JACK_INPUT_DEV
@@ -109,12 +117,291 @@ static int snd_jack_dev_register(struct snd_device *device)
 }
 #endif /* CONFIG_SND_JACK_INPUT_DEV */
 
+#ifdef CONFIG_SND_JACK_INJECTION_DEBUG
+static void snd_jack_inject_report(struct snd_jack_kctl *jack_kctl, int status)
+{
+       struct snd_jack *jack;
+#ifdef CONFIG_SND_JACK_INPUT_DEV
+       int i;
+#endif
+       if (!jack_kctl)
+               return;
+
+       jack = jack_kctl->jack;
+
+       if (jack_kctl->sw_inject_enable)
+               snd_kctl_jack_report(jack->card, jack_kctl->kctl,
+                                    status & jack_kctl->mask_bits);
+
+#ifdef CONFIG_SND_JACK_INPUT_DEV
+       if (!jack->input_dev)
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
+               int testbit = ((SND_JACK_BTN_0 >> i) & jack_kctl->mask_bits);
+
+               if (jack->type & testbit)
+                       input_report_key(jack->input_dev, jack->key[i],
+                                        status & testbit);
+       }
+
+       for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {
+               int testbit = ((1 << i) & jack_kctl->mask_bits);
+
+               if (jack->type & testbit)
+                       input_report_switch(jack->input_dev,
+                                           jack_switch_types[i],
+                                           status & testbit);
+       }
+
+       input_sync(jack->input_dev);
+#endif /* CONFIG_SND_JACK_INPUT_DEV */
+}
+
+static ssize_t sw_inject_enable_read(struct file *file,
+                                    char __user *to, size_t count, loff_t *ppos)
+{
+       struct snd_jack_kctl *jack_kctl = file->private_data;
+       int len, ret;
+       char buf[128];
+
+       len = scnprintf(buf, sizeof(buf), "%s: %s\t\t%s: %i\n", "Jack", jack_kctl->kctl->id.name,
+                       "Inject Enabled", jack_kctl->sw_inject_enable);
+       ret = simple_read_from_buffer(to, count, ppos, buf, len);
+
+       return ret;
+}
+
+static ssize_t sw_inject_enable_write(struct file *file,
+                                     const char __user *from, size_t count, loff_t *ppos)
+{
+       struct snd_jack_kctl *jack_kctl = file->private_data;
+       int ret, err;
+       unsigned long enable;
+       char buf[8] = { 0 };
+
+       ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, from, count);
+       err = kstrtoul(buf, 0, &enable);
+       if (err)
+               return err;
+
+       if (jack_kctl->sw_inject_enable == (!!enable))
+               return ret;
+
+       jack_kctl->sw_inject_enable = !!enable;
+
+       if (!jack_kctl->sw_inject_enable)
+               snd_jack_report(jack_kctl->jack, jack_kctl->jack->hw_status_cache);
+
+       return ret;
+}
+
+static ssize_t jackin_inject_write(struct file *file,
+                                  const char __user *from, size_t count, loff_t *ppos)
+{
+       struct snd_jack_kctl *jack_kctl = file->private_data;
+       int ret, err;
+       unsigned long enable;
+       char buf[8] = { 0 };
+
+       if (!jack_kctl->sw_inject_enable)
+               return -EINVAL;
+
+       ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, from, count);
+       err = kstrtoul(buf, 0, &enable);
+       if (err)
+               return err;
+
+       snd_jack_inject_report(jack_kctl, !!enable ? jack_kctl->mask_bits : 0);
+
+       return ret;
+}
+
+static ssize_t jack_kctl_id_read(struct file *file,
+                                char __user *to, size_t count, loff_t *ppos)
+{
+       struct snd_jack_kctl *jack_kctl = file->private_data;
+       char buf[64];
+       int len, ret;
+
+       len = scnprintf(buf, sizeof(buf), "%s\n", jack_kctl->kctl->id.name);
+       ret = simple_read_from_buffer(to, count, ppos, buf, len);
+
+       return ret;
+}
+
+/* the bit definition is aligned with snd_jack_types in jack.h */
+static const char * const jack_events_name[] = {
+       "HEADPHONE(0x0001)", "MICROPHONE(0x0002)", "LINEOUT(0x0004)",
+       "MECHANICAL(0x0008)", "VIDEOOUT(0x0010)", "LINEIN(0x0020)",
+       "", "", "", "BTN_5(0x0200)", "BTN_4(0x0400)", "BTN_3(0x0800)",
+       "BTN_2(0x1000)", "BTN_1(0x2000)", "BTN_0(0x4000)", "",
+};
+
+/* the recommended buffer size is 256 */
+static int parse_mask_bits(unsigned int mask_bits, char *buf, size_t buf_size)
+{
+       int i;
+
+       scnprintf(buf, buf_size, "0x%04x", mask_bits);
+
+       for (i = 0; i < ARRAY_SIZE(jack_events_name); i++)
+               if (mask_bits & (1 << i)) {
+                       strlcat(buf, " ", buf_size);
+                       strlcat(buf, jack_events_name[i], buf_size);
+               }
+       strlcat(buf, "\n", buf_size);
+
+       return strlen(buf);
+}
+
+static ssize_t jack_kctl_mask_bits_read(struct file *file,
+                                       char __user *to, size_t count, loff_t *ppos)
+{
+       struct snd_jack_kctl *jack_kctl = file->private_data;
+       char buf[256];
+       int len, ret;
+
+       len = parse_mask_bits(jack_kctl->mask_bits, buf, sizeof(buf));
+       ret = simple_read_from_buffer(to, count, ppos, buf, len);
+
+       return ret;
+}
+
+static ssize_t jack_kctl_status_read(struct file *file,
+                                    char __user *to, size_t count, loff_t *ppos)
+{
+       struct snd_jack_kctl *jack_kctl = file->private_data;
+       char buf[16];
+       int len, ret;
+
+       len = scnprintf(buf, sizeof(buf), "%s\n", jack_kctl->kctl->private_value ?
+                       "Plugged" : "Unplugged");
+       ret = simple_read_from_buffer(to, count, ppos, buf, len);
+
+       return ret;
+}
+
+#ifdef CONFIG_SND_JACK_INPUT_DEV
+static ssize_t jack_type_read(struct file *file,
+                             char __user *to, size_t count, loff_t *ppos)
+{
+       struct snd_jack_kctl *jack_kctl = file->private_data;
+       char buf[256];
+       int len, ret;
+
+       len = parse_mask_bits(jack_kctl->jack->type, buf, sizeof(buf));
+       ret = simple_read_from_buffer(to, count, ppos, buf, len);
+
+       return ret;
+}
+
+static const struct file_operations jack_type_fops = {
+       .open = simple_open,
+       .read = jack_type_read,
+       .llseek = default_llseek,
+};
+#endif
+
+static const struct file_operations sw_inject_enable_fops = {
+       .open = simple_open,
+       .read = sw_inject_enable_read,
+       .write = sw_inject_enable_write,
+       .llseek = default_llseek,
+};
+
+static const struct file_operations jackin_inject_fops = {
+       .open = simple_open,
+       .write = jackin_inject_write,
+       .llseek = default_llseek,
+};
+
+static const struct file_operations jack_kctl_id_fops = {
+       .open = simple_open,
+       .read = jack_kctl_id_read,
+       .llseek = default_llseek,
+};
+
+static const struct file_operations jack_kctl_mask_bits_fops = {
+       .open = simple_open,
+       .read = jack_kctl_mask_bits_read,
+       .llseek = default_llseek,
+};
+
+static const struct file_operations jack_kctl_status_fops = {
+       .open = simple_open,
+       .read = jack_kctl_status_read,
+       .llseek = default_llseek,
+};
+
+static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
+                                           struct snd_jack_kctl *jack_kctl)
+{
+       char *tname;
+       int i;
+
+       /* Don't create injection interface for Phantom jacks */
+       if (strstr(jack_kctl->kctl->id.name, "Phantom"))
+               return 0;
+
+       tname = kstrdup(jack_kctl->kctl->id.name, GFP_KERNEL);
+       if (!tname)
+               return -ENOMEM;
+
+       /* replace the chars which are not suitable for folder's name with _ */
+       for (i = 0; tname[i]; i++)
+               if (!isalnum(tname[i]))
+                       tname[i] = '_';
+
+       jack_kctl->jack_debugfs_root = debugfs_create_dir(tname, jack->card->debugfs_root);
+       kfree(tname);
+
+       debugfs_create_file("sw_inject_enable", 0644, jack_kctl->jack_debugfs_root, jack_kctl,
+                           &sw_inject_enable_fops);
+
+       debugfs_create_file("jackin_inject", 0200, jack_kctl->jack_debugfs_root, jack_kctl,
+                           &jackin_inject_fops);
+
+       debugfs_create_file("kctl_id", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
+                           &jack_kctl_id_fops);
+
+       debugfs_create_file("mask_bits", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
+                           &jack_kctl_mask_bits_fops);
+
+       debugfs_create_file("status", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
+                           &jack_kctl_status_fops);
+
+#ifdef CONFIG_SND_JACK_INPUT_DEV
+       debugfs_create_file("type", 0444, jack_kctl->jack_debugfs_root, jack_kctl,
+                           &jack_type_fops);
+#endif
+       return 0;
+}
+
+static void snd_jack_debugfs_clear_inject_node(struct snd_jack_kctl *jack_kctl)
+{
+       debugfs_remove(jack_kctl->jack_debugfs_root);
+       jack_kctl->jack_debugfs_root = NULL;
+}
+#else /* CONFIG_SND_JACK_INJECTION_DEBUG */
+static int snd_jack_debugfs_add_inject_node(struct snd_jack *jack,
+                                           struct snd_jack_kctl *jack_kctl)
+{
+       return 0;
+}
+
+static void snd_jack_debugfs_clear_inject_node(struct snd_jack_kctl *jack_kctl)
+{
+}
+#endif /* CONFIG_SND_JACK_INJECTION_DEBUG */
+
 static void snd_jack_kctl_private_free(struct snd_kcontrol *kctl)
 {
        struct snd_jack_kctl *jack_kctl;
 
        jack_kctl = kctl->private_data;
        if (jack_kctl) {
+               snd_jack_debugfs_clear_inject_node(jack_kctl);
                list_del(&jack_kctl->list);
                kfree(jack_kctl);
        }
@@ -122,7 +409,9 @@ static void snd_jack_kctl_private_free(struct snd_kcontrol *kctl)
 
 static void snd_jack_kctl_add(struct snd_jack *jack, struct snd_jack_kctl *jack_kctl)
 {
+       jack_kctl->jack = jack;
        list_add_tail(&jack_kctl->list, &jack->kctl_list);
+       snd_jack_debugfs_add_inject_node(jack, jack_kctl);
 }
 
 static struct snd_jack_kctl * snd_jack_kctl_new(struct snd_card *card, const char *name, unsigned int mask)
@@ -340,6 +629,7 @@ EXPORT_SYMBOL(snd_jack_set_key);
 void snd_jack_report(struct snd_jack *jack, int status)
 {
        struct snd_jack_kctl *jack_kctl;
+       unsigned int mask_bits = 0;
 #ifdef CONFIG_SND_JACK_INPUT_DEV
        int i;
 #endif
@@ -347,16 +637,21 @@ void snd_jack_report(struct snd_jack *jack, int status)
        if (!jack)
                return;
 
+       jack->hw_status_cache = status;
+
        list_for_each_entry(jack_kctl, &jack->kctl_list, list)
-               snd_kctl_jack_report(jack->card, jack_kctl->kctl,
-                                           status & jack_kctl->mask_bits);
+               if (jack_kctl->sw_inject_enable)
+                       mask_bits |= jack_kctl->mask_bits;
+               else
+                       snd_kctl_jack_report(jack->card, jack_kctl->kctl,
+                                            status & jack_kctl->mask_bits);
 
 #ifdef CONFIG_SND_JACK_INPUT_DEV
        if (!jack->input_dev)
                return;
 
        for (i = 0; i < ARRAY_SIZE(jack->key); i++) {
-               int testbit = SND_JACK_BTN_0 >> i;
+               int testbit = ((SND_JACK_BTN_0 >> i) & ~mask_bits);
 
                if (jack->type & testbit)
                        input_report_key(jack->input_dev, jack->key[i],
@@ -364,7 +659,8 @@ void snd_jack_report(struct snd_jack *jack, int status)
        }
 
        for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++) {
-               int testbit = 1 << i;
+               int testbit = ((1 << i) & ~mask_bits);
+
                if (jack->type & testbit)
                        input_report_switch(jack->input_dev,
                                            jack_switch_types[i],
index f702c96..bec9283 100644 (file)
@@ -87,8 +87,8 @@ static int snd_mixer_oss_info(struct snd_mixer_oss_file *fmixer,
        struct mixer_info info;
        
        memset(&info, 0, sizeof(info));
-       strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id));
-       strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name));
+       strscpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id));
+       strscpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name));
        info.modify_counter = card->mixer_oss_change_count;
        if (copy_to_user(_info, &info, sizeof(info)))
                return -EFAULT;
@@ -103,8 +103,8 @@ static int snd_mixer_oss_info_obsolete(struct snd_mixer_oss_file *fmixer,
        _old_mixer_info info;
        
        memset(&info, 0, sizeof(info));
-       strlcpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id));
-       strlcpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name));
+       strscpy(info.id, mixer && mixer->id[0] ? mixer->id : card->driver, sizeof(info.id));
+       strscpy(info.name, mixer && mixer->name[0] ? mixer->name : card->mixername, sizeof(info.name));
        if (copy_to_user(_info, &info, sizeof(info)))
                return -EFAULT;
        return 0;
@@ -418,7 +418,7 @@ static long snd_mixer_oss_conv(long val, long omin, long omax, long nmin, long n
        
        if (orange == 0)
                return 0;
-       return ((nrange * (val - omin)) + (orange / 2)) / orange + nmin;
+       return DIV_ROUND_CLOSEST(nrange * (val - omin), orange) + nmin;
 }
 
 /* convert from alsa native to oss values (0-100) */
@@ -499,7 +499,7 @@ static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, c
        
        memset(&id, 0, sizeof(id));
        id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-       strlcpy(id.name, name, sizeof(id.name));
+       strscpy(id.name, name, sizeof(id.name));
        id.index = index;
        return snd_ctl_find_id(card, &id);
 }
@@ -1355,7 +1355,7 @@ static int snd_mixer_oss_notify_handler(struct snd_card *card, int cmd)
                mixer->oss_dev_alloc = 1;
                mixer->card = card;
                if (*card->mixername)
-                       strlcpy(mixer->name, card->mixername, sizeof(mixer->name));
+                       strscpy(mixer->name, card->mixername, sizeof(mixer->name));
                else
                        snprintf(mixer->name, sizeof(mixer->name),
                                 "mixer%i", card->number);
index d381f4c..9826911 100644 (file)
@@ -193,7 +193,7 @@ static snd_pcm_sframes_t rate_src_frames(struct snd_pcm_plugin *plugin, snd_pcm_
        if (plugin->src_format.rate < plugin->dst_format.rate) {
                res = (((frames * data->pitch) + (BITS/2)) >> SHIFT);
        } else {
-               res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch);          
+               res = DIV_ROUND_CLOSEST(frames << SHIFT, data->pitch);
        }
        if (data->old_src_frames > 0) {
                snd_pcm_sframes_t frames1 = frames, res1 = data->old_dst_frames;
@@ -224,7 +224,7 @@ static snd_pcm_sframes_t rate_dst_frames(struct snd_pcm_plugin *plugin, snd_pcm_
                return 0;
        data = (struct rate_priv *)plugin->extra_data;
        if (plugin->src_format.rate < plugin->dst_format.rate) {
-               res = (((frames << SHIFT) + (data->pitch / 2)) / data->pitch);
+               res = DIV_ROUND_CLOSEST(frames << SHIFT, data->pitch);
        } else {
                res = (((frames * data->pitch) + (BITS/2)) >> SHIFT);
        }
index be5714f..b163164 100644 (file)
@@ -729,7 +729,7 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
        init_waitqueue_head(&pcm->open_wait);
        INIT_LIST_HEAD(&pcm->list);
        if (id)
-               strlcpy(pcm->id, id, sizeof(pcm->id));
+               strscpy(pcm->id, id, sizeof(pcm->id));
 
        err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK,
                                 playback_count);
@@ -1095,22 +1095,23 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
        mutex_lock(&pcm->open_mutex);
        wake_up(&pcm->open_wait);
        list_del_init(&pcm->list);
-       for (cidx = 0; cidx < 2; cidx++) {
-               for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) {
-                       snd_pcm_stream_lock_irq(substream);
-                       if (substream->runtime) {
-                               if (snd_pcm_running(substream))
-                                       snd_pcm_stop(substream,
-                                                    SNDRV_PCM_STATE_DISCONNECTED);
-                               /* to be sure, set the state unconditionally */
-                               substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
-                               wake_up(&substream->runtime->sleep);
-                               wake_up(&substream->runtime->tsleep);
-                       }
-                       snd_pcm_stream_unlock_irq(substream);
+
+       for_each_pcm_substream(pcm, cidx, substream) {
+               snd_pcm_stream_lock_irq(substream);
+               if (substream->runtime) {
+                       if (snd_pcm_running(substream))
+                               snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
+                       /* to be sure, set the state unconditionally */
+                       substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED;
+                       wake_up(&substream->runtime->sleep);
+                       wake_up(&substream->runtime->tsleep);
                }
+               snd_pcm_stream_unlock_irq(substream);
        }
 
+       for_each_pcm_substream(pcm, cidx, substream)
+               snd_pcm_sync_stop(substream, false);
+
        pcm_call_notify(pcm, n_disconnect);
        for (cidx = 0; cidx < 2; cidx++) {
                snd_unregister_device(&pcm->streams[cidx].dev);
index 17a1a5d..e3b3558 100644 (file)
@@ -63,6 +63,7 @@ static inline void snd_pcm_timer_done(struct snd_pcm_substream *substream) {}
 
 void __snd_pcm_xrun(struct snd_pcm_substream *substream);
 void snd_pcm_group_init(struct snd_pcm_group *group);
+void snd_pcm_sync_stop(struct snd_pcm_substream *substream, bool sync_irq);
 
 #ifdef CONFIG_SND_DMA_SGBUF
 struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream,
@@ -71,4 +72,10 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream,
 
 #define PCM_RUNTIME_CHECK(sub) snd_BUG_ON(!(sub) || !(sub)->runtime)
 
+/* loop over all PCM substreams */
+#define for_each_pcm_substream(pcm, str, subs) \
+       for ((str) = 0; (str) < 2; (str)++) \
+               for ((subs) = (pcm)->streams[str].substream; (subs); \
+                    (subs) = (subs)->next)
+
 #endif /* __SOUND_CORE_PCM_LOCAL_H */
index ee6e9c5..289dd1f 100644 (file)
@@ -111,9 +111,8 @@ void snd_pcm_lib_preallocate_free_for_all(struct snd_pcm *pcm)
        struct snd_pcm_substream *substream;
        int stream;
 
-       for (stream = 0; stream < 2; stream++)
-               for (substream = pcm->streams[stream].substream; substream; substream = substream->next)
-                       snd_pcm_lib_preallocate_free(substream);
+       for_each_pcm_substream(pcm, stream, substream)
+               snd_pcm_lib_preallocate_free(substream);
 }
 EXPORT_SYMBOL(snd_pcm_lib_preallocate_free_for_all);
 
@@ -246,11 +245,8 @@ static void preallocate_pages_for_all(struct snd_pcm *pcm, int type,
        struct snd_pcm_substream *substream;
        int stream;
 
-       for (stream = 0; stream < 2; stream++)
-               for (substream = pcm->streams[stream].substream; substream;
-                    substream = substream->next)
-                       preallocate_pages(substream, type, data, size, max,
-                                         managed);
+       for_each_pcm_substream(pcm, stream, substream)
+               preallocate_pages(substream, type, data, size, max, managed);
 }
 
 /**
index c4aac70..17a85f4 100644 (file)
@@ -209,13 +209,13 @@ int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info)
        info->device = pcm->device;
        info->stream = substream->stream;
        info->subdevice = substream->number;
-       strlcpy(info->id, pcm->id, sizeof(info->id));
-       strlcpy(info->name, pcm->name, sizeof(info->name));
+       strscpy(info->id, pcm->id, sizeof(info->id));
+       strscpy(info->name, pcm->name, sizeof(info->name));
        info->dev_class = pcm->dev_class;
        info->dev_subclass = pcm->dev_subclass;
        info->subdevices_count = pstr->substream_count;
        info->subdevices_avail = pstr->substream_count - pstr->substream_opened;
-       strlcpy(info->subname, substream->name, sizeof(info->subname));
+       strscpy(info->subname, substream->name, sizeof(info->subname));
 
        return 0;
 }
@@ -583,13 +583,13 @@ static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream,
 #endif
 }
 
-static void snd_pcm_sync_stop(struct snd_pcm_substream *substream)
+void snd_pcm_sync_stop(struct snd_pcm_substream *substream, bool sync_irq)
 {
-       if (substream->runtime->stop_operating) {
+       if (substream->runtime && substream->runtime->stop_operating) {
                substream->runtime->stop_operating = false;
-               if (substream->ops->sync_stop)
+               if (substream->ops && substream->ops->sync_stop)
                        substream->ops->sync_stop(substream);
-               else if (substream->pcm->card->sync_irq > 0)
+               else if (sync_irq && substream->pcm->card->sync_irq > 0)
                        synchronize_irq(substream->pcm->card->sync_irq);
        }
 }
@@ -686,7 +686,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
                if (atomic_read(&substream->mmap_count))
                        return -EBADFD;
 
-       snd_pcm_sync_stop(substream);
+       snd_pcm_sync_stop(substream, true);
 
        params->rmask = ~0U;
        err = snd_pcm_hw_refine(substream, params);
@@ -809,7 +809,7 @@ static int do_hw_free(struct snd_pcm_substream *substream)
 {
        int result = 0;
 
-       snd_pcm_sync_stop(substream);
+       snd_pcm_sync_stop(substream, true);
        if (substream->ops->hw_free)
                result = substream->ops->hw_free(substream);
        if (substream->managed_buffer_alloc)
@@ -1421,8 +1421,10 @@ static int snd_pcm_do_stop(struct snd_pcm_substream *substream,
                           snd_pcm_state_t state)
 {
        if (substream->runtime->trigger_master == substream &&
-           snd_pcm_running(substream))
+           snd_pcm_running(substream)) {
                substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
+               substream->runtime->stop_operating = true;
+       }
        return 0; /* unconditonally stop all substreams */
 }
 
@@ -1435,7 +1437,6 @@ static void snd_pcm_post_stop(struct snd_pcm_substream *substream,
                runtime->status->state = state;
                snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MSTOP);
        }
-       runtime->stop_operating = true;
        wake_up(&runtime->sleep);
        wake_up(&runtime->tsleep);
 }
@@ -1615,6 +1616,7 @@ static int snd_pcm_do_suspend(struct snd_pcm_substream *substream,
        if (! snd_pcm_running(substream))
                return 0;
        substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
+       runtime->stop_operating = true;
        return 0; /* suspend unconditionally */
 }
 
@@ -1672,25 +1674,26 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm)
        if (! pcm)
                return 0;
 
-       for (stream = 0; stream < 2; stream++) {
-               for (substream = pcm->streams[stream].substream;
-                    substream; substream = substream->next) {
-                       /* FIXME: the open/close code should lock this as well */
-                       if (substream->runtime == NULL)
-                               continue;
+       for_each_pcm_substream(pcm, stream, substream) {
+               /* FIXME: the open/close code should lock this as well */
+               if (!substream->runtime)
+                       continue;
 
-                       /*
-                        * Skip BE dai link PCM's that are internal and may
-                        * not have their substream ops set.
-                        */
-                       if (!substream->ops)
-                               continue;
+               /*
+                * Skip BE dai link PCM's that are internal and may
+                * not have their substream ops set.
+                */
+               if (!substream->ops)
+                       continue;
 
-                       err = snd_pcm_suspend(substream);
-                       if (err < 0 && err != -EBUSY)
-                               return err;
-               }
+               err = snd_pcm_suspend(substream);
+               if (err < 0 && err != -EBUSY)
+                       return err;
        }
+
+       for_each_pcm_substream(pcm, stream, substream)
+               snd_pcm_sync_stop(substream, false);
+
        return 0;
 }
 EXPORT_SYMBOL(snd_pcm_suspend_all);
@@ -1736,7 +1739,6 @@ static void snd_pcm_post_resume(struct snd_pcm_substream *substream,
        snd_pcm_trigger_tstamp(substream);
        runtime->status->state = runtime->status->suspended_state;
        snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MRESUME);
-       snd_pcm_sync_stop(substream);
 }
 
 static const struct action_ops snd_pcm_action_resume = {
@@ -1866,7 +1868,7 @@ static int snd_pcm_do_prepare(struct snd_pcm_substream *substream,
                              snd_pcm_state_t state)
 {
        int err;
-       snd_pcm_sync_stop(substream);
+       snd_pcm_sync_stop(substream, true);
        err = substream->ops->prepare(substream);
        if (err < 0)
                return err;
index 257ad52..aca00af 100644 (file)
@@ -1686,7 +1686,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,
        INIT_LIST_HEAD(&rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams);
 
        if (id != NULL)
-               strlcpy(rmidi->id, id, sizeof(rmidi->id));
+               strscpy(rmidi->id, id, sizeof(rmidi->id));
 
        snd_device_initialize(&rmidi->dev, card);
        rmidi->dev.release = release_rawmidi_device;
index 2ddfe22..3f82c19 100644 (file)
@@ -173,7 +173,7 @@ snd_seq_oss_midi_check_new_port(struct snd_seq_port_info *pinfo)
        snd_use_lock_init(&mdev->use_lock);
 
        /* copy and truncate the name of synth device */
-       strlcpy(mdev->name, pinfo->name, sizeof(mdev->name));
+       strscpy(mdev->name, pinfo->name, sizeof(mdev->name));
 
        /* create MIDI coder */
        if (snd_midi_event_new(MAX_MIDI_EVENT_BUF, &mdev->coder) < 0) {
@@ -647,7 +647,7 @@ snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info
        inf->device = dev;
        inf->dev_type = 0; /* FIXME: ?? */
        inf->capabilities = 0; /* FIXME: ?? */
-       strlcpy(inf->name, mdev->name, sizeof(inf->name));
+       strscpy(inf->name, mdev->name, sizeof(inf->name));
        snd_use_lock_free(&mdev->use_lock);
        return 0;
 }
index 1b8409e..722f505 100644 (file)
@@ -107,7 +107,7 @@ snd_seq_oss_synth_probe(struct device *_dev)
        snd_use_lock_init(&rec->use_lock);
 
        /* copy and truncate the name of synth device */
-       strlcpy(rec->name, dev->name, sizeof(rec->name));
+       strscpy(rec->name, dev->name, sizeof(rec->name));
 
        /* registration */
        spin_lock_irqsave(&register_lock, flags);
@@ -617,7 +617,7 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
                inf->synth_subtype = 0;
                inf->nr_voices = 16;
                inf->device = dev;
-               strlcpy(inf->name, minf.name, sizeof(inf->name));
+               strscpy(inf->name, minf.name, sizeof(inf->name));
        } else {
                if ((rec = get_synthdev(dp, dev)) == NULL)
                        return -ENXIO;
@@ -625,7 +625,7 @@ snd_seq_oss_synth_make_info(struct seq_oss_devinfo *dp, int dev, struct synth_in
                inf->synth_subtype = rec->synth_subtype;
                inf->nr_voices = rec->nr_voices;
                inf->device = dev;
-               strlcpy(inf->name, rec->name, sizeof(inf->name));
+               strscpy(inf->name, rec->name, sizeof(inf->name));
                snd_use_lock_free(&rec->use_lock);
        }
        return 0;
index f9f2fea..b6a24fb 100644 (file)
@@ -1584,7 +1584,7 @@ static int snd_seq_ioctl_get_queue_info(struct snd_seq_client *client,
        info->queue = q->queue;
        info->owner = q->owner;
        info->locked = q->locked;
-       strlcpy(info->name, q->name, sizeof(info->name));
+       strscpy(info->name, q->name, sizeof(info->name));
        queuefree(q);
 
        return 0;
index 65db1a7..e245bb6 100644 (file)
@@ -290,7 +290,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
        extlen = 0;
        if (snd_seq_ev_is_variable(event)) {
                extlen = event->data.ext.len & ~SNDRV_SEQ_EXT_MASK;
-               ncells = (extlen + sizeof(struct snd_seq_event) - 1) / sizeof(struct snd_seq_event);
+               ncells = DIV_ROUND_UP(extlen, sizeof(struct snd_seq_event));
        }
        if (ncells >= pool->total_elements)
                return -ENOMEM;
index 83be6b9..b9c2ce2 100644 (file)
@@ -327,7 +327,7 @@ int snd_seq_set_port_info(struct snd_seq_client_port * port,
 
        /* set port name */
        if (info->name[0])
-               strlcpy(port->name, info->name, sizeof(port->name));
+               strscpy(port->name, info->name, sizeof(port->name));
        
        /* set capabilities */
        port->capability = info->capability;
@@ -356,7 +356,7 @@ int snd_seq_get_port_info(struct snd_seq_client_port * port,
                return -EINVAL;
 
        /* get port name */
-       strlcpy(info->name, port->name, sizeof(info->name));
+       strscpy(info->name, port->name, sizeof(info->name));
        
        /* get capabilities */
        info->capability = port->capability;
@@ -654,7 +654,7 @@ int snd_seq_event_port_attach(int client,
        /* Set up the port */
        memset(&portinfo, 0, sizeof(portinfo));
        portinfo.addr.client = client;
-       strlcpy(portinfo.name, portname ? portname : "Unnamed port",
+       strscpy(portinfo.name, portname ? portname : "Unnamed port",
                sizeof(portinfo.name));
 
        portinfo.capability = cap;
index b75f78f..af89e51 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/time.h>
 #include <linux/device.h>
 #include <linux/module.h>
+#include <linux/debugfs.h>
 #include <sound/core.h>
 #include <sound/minors.h>
 #include <sound/info.h>
@@ -39,6 +40,11 @@ MODULE_ALIAS_CHARDEV_MAJOR(CONFIG_SND_MAJOR);
 int snd_ecards_limit;
 EXPORT_SYMBOL(snd_ecards_limit);
 
+#ifdef CONFIG_SND_DEBUG
+struct dentry *sound_debugfs_root;
+EXPORT_SYMBOL_GPL(sound_debugfs_root);
+#endif
+
 static struct snd_minor *snd_minors[SNDRV_OS_MINORS];
 static DEFINE_MUTEX(sound_mutex);
 
@@ -337,6 +343,8 @@ static const char *snd_device_type_name(int type)
                return "sequencer";
        case SNDRV_DEVICE_TYPE_TIMER:
                return "timer";
+       case SNDRV_DEVICE_TYPE_COMPRESS:
+               return "compress";
        default:
                return "?";
        }
@@ -395,6 +403,10 @@ static int __init alsa_sound_init(void)
                unregister_chrdev(major, "alsa");
                return -ENOMEM;
        }
+
+#ifdef CONFIG_SND_DEBUG
+       sound_debugfs_root = debugfs_create_dir("sound", NULL);
+#endif
 #ifndef MODULE
        pr_info("Advanced Linux Sound Architecture Driver Initialized.\n");
 #endif
@@ -403,6 +415,9 @@ static int __init alsa_sound_init(void)
 
 static void __exit alsa_sound_exit(void)
 {
+#ifdef CONFIG_SND_DEBUG
+       debugfs_remove(sound_debugfs_root);
+#endif
        snd_info_done();
        unregister_chrdev(major, "alsa");
 }
index 765ea66..6898b1a 100644 (file)
@@ -959,7 +959,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
        timer->tmr_device = tid->device;
        timer->tmr_subdevice = tid->subdevice;
        if (id)
-               strlcpy(timer->id, id, sizeof(timer->id));
+               strscpy(timer->id, id, sizeof(timer->id));
        timer->sticks = 1;
        INIT_LIST_HEAD(&timer->device_list);
        INIT_LIST_HEAD(&timer->open_list_head);
@@ -1659,8 +1659,8 @@ static int snd_timer_user_ginfo(struct file *file,
                ginfo->card = t->card ? t->card->number : -1;
                if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
                        ginfo->flags |= SNDRV_TIMER_FLG_SLAVE;
-               strlcpy(ginfo->id, t->id, sizeof(ginfo->id));
-               strlcpy(ginfo->name, t->name, sizeof(ginfo->name));
+               strscpy(ginfo->id, t->id, sizeof(ginfo->id));
+               strscpy(ginfo->name, t->name, sizeof(ginfo->name));
                ginfo->resolution = t->hw.resolution;
                if (t->hw.resolution_min > 0) {
                        ginfo->resolution_min = t->hw.resolution_min;
@@ -1814,8 +1814,8 @@ static int snd_timer_user_info(struct file *file,
        info->card = t->card ? t->card->number : -1;
        if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
                info->flags |= SNDRV_TIMER_FLG_SLAVE;
-       strlcpy(info->id, t->id, sizeof(info->id));
-       strlcpy(info->name, t->name, sizeof(info->name));
+       strscpy(info->id, t->id, sizeof(info->id));
+       strscpy(info->name, t->name, sizeof(info->name));
        info->resolution = t->hw.resolution;
        if (copy_to_user(_info, info, sizeof(*_info)))
                err = -EFAULT;
index 0103d16..ee973b7 100644 (file)
@@ -61,8 +61,8 @@ static int snd_timer_user_info_compat(struct file *file,
        info.card = t->card ? t->card->number : -1;
        if (t->hw.flags & SNDRV_TIMER_HW_SLAVE)
                info.flags |= SNDRV_TIMER_FLG_SLAVE;
-       strlcpy(info.id, t->id, sizeof(info.id));
-       strlcpy(info.name, t->name, sizeof(info.name));
+       strscpy(info.id, t->id, sizeof(info.id));
+       strscpy(info.name, t->name, sizeof(info.name));
        info.resolution = t->hw.resolution;
        if (copy_to_user(_info, &info, sizeof(*_info)))
                return -EFAULT;
index 702f91b..8a24e5a 100644 (file)
@@ -219,7 +219,7 @@ static int loopback_jiffies_timer_start(struct loopback_pcm *dpcm)
                dpcm->period_update_pending = 1;
        }
        tick = dpcm->period_size_frac - dpcm->irq_pos;
-       tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps;
+       tick = DIV_ROUND_UP(tick, dpcm->pcm_bps);
        mod_timer(&dpcm->timer, jiffies + tick);
 
        return 0;
index b5486de..316c9af 100644 (file)
@@ -236,7 +236,7 @@ struct dummy_systimer_pcm {
 static void dummy_systimer_rearm(struct dummy_systimer_pcm *dpcm)
 {
        mod_timer(&dpcm->timer, jiffies +
-               (dpcm->frac_period_rest + dpcm->rate - 1) / dpcm->rate);
+               DIV_ROUND_UP(dpcm->frac_period_rest, dpcm->rate));
 }
 
 static void dummy_systimer_update(struct dummy_systimer_pcm *dpcm)
index 7bf0d5f..c82c7c1 100644 (file)
@@ -97,7 +97,7 @@ void snd_opl3_init_seq_oss(struct snd_opl3 *opl3, char *name)
                return;
 
        opl3->oss_seq_dev = dev;
-       strlcpy(dev->name, name, sizeof(dev->name));
+       strscpy(dev->name, name, sizeof(dev->name));
        arg = SNDRV_SEQ_DEVICE_ARGPTR(dev);
        arg->type = SYNTH_TYPE_FM;
        if (opl3->hardware < OPL3_HW_OPL3) {
index 08c10ac..97d30a8 100644 (file)
@@ -290,7 +290,7 @@ int snd_opl3_load_patch(struct snd_opl3 *opl3,
        }
 
        if (name)
-               strlcpy(patch->name, name, sizeof(patch->name));
+               strscpy(patch->name, name, sizeof(patch->name));
 
        return 0;
 }
index 3d2e3bc..daffda9 100644 (file)
@@ -1154,8 +1154,7 @@ static int vx_init_audio_io(struct vx_core *chip)
        chip->ibl.size = 0;
        vx_set_ibl(chip, &chip->ibl); /* query the info */
        if (preferred > 0) {
-               chip->ibl.size = ((preferred + chip->ibl.granularity - 1) /
-                                 chip->ibl.granularity) * chip->ibl.granularity;
+               chip->ibl.size = roundup(preferred, chip->ibl.granularity);
                if (chip->ibl.size > chip->ibl.max_size)
                        chip->ibl.size = chip->ibl.max_size;
        } else
index c362eb3..6f93316 100644 (file)
@@ -37,11 +37,9 @@ hwdep_read(struct snd_hwdep *hwdep, char __user *buf,  long count,
 
        memset(&event, 0, sizeof(event));
        count = min_t(long, count, sizeof(event.lock_status));
-       if (bebob->dev_lock_changed) {
-               event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
-               event.lock_status.status = (bebob->dev_lock_count > 0);
-               bebob->dev_lock_changed = false;
-       }
+       event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
+       event.lock_status.status = (bebob->dev_lock_count > 0);
+       bebob->dev_lock_changed = false;
 
        spin_unlock_irq(&bebob->lock);
 
@@ -80,7 +78,7 @@ hwdep_get_info(struct snd_bebob *bebob, void __user *arg)
        info.card = dev->card->index;
        *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
        *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
-       strlcpy(info.device_name, dev_name(&dev->device),
+       strscpy(info.device_name, dev_name(&dev->device),
                sizeof(info.device_name));
 
        if (copy_to_user(arg, &info, sizeof(info)))
index 7a62daf..9bf7b96 100644 (file)
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 snd-dice-objs := dice-transaction.o dice-stream.o dice-proc.o dice-midi.o \
                 dice-pcm.o dice-hwdep.o dice.o dice-tcelectronic.o \
-                dice-alesis.o dice-extension.o dice-mytek.o dice-presonus.o
+                dice-alesis.o dice-extension.o dice-mytek.o dice-presonus.o \
+                dice-harman.o
 obj-$(CONFIG_SND_DICE) += snd-dice.o
diff --git a/sound/firewire/dice/dice-harman.c b/sound/firewire/dice/dice-harman.c
new file mode 100644 (file)
index 0000000..a8ca00c
--- /dev/null
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+// dice-harman.c - a part of driver for DICE based devices
+//
+// Copyright (c) 2021 Takashi Sakamoto
+//
+// Licensed under the terms of the GNU General Public License, version 2.
+
+#include "dice.h"
+
+int snd_dice_detect_harman_formats(struct snd_dice *dice)
+{
+       int i;
+
+       // Lexicon I-ONYX FW810s supports sampling transfer frequency up to
+       // 96.0 kHz, 12 PCM channels and 1 MIDI channel in its first tx stream
+       // , 10 PCM channels and 1 MIDI channel in its first rx stream for all
+       // of the frequencies.
+       for (i = 0; i < 2; ++i) {
+               dice->tx_pcm_chs[0][i] = 12;
+               dice->tx_midi_ports[0] = 1;
+               dice->rx_pcm_chs[0][i] = 10;
+               dice->rx_midi_ports[0] = 1;
+       }
+
+       return 0;
+}
index f69f799..ffc0b97 100644 (file)
@@ -79,7 +79,7 @@ static int hwdep_get_info(struct snd_dice *dice, void __user *arg)
        info.card = dev->card->index;
        *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
        *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
-       strlcpy(info.device_name, dev_name(&dev->device),
+       strscpy(info.device_name, dev_name(&dev->device),
                sizeof(info.device_name));
 
        if (copy_to_user(arg, &info, sizeof(info)))
index 06c94f0..107a816 100644 (file)
@@ -20,10 +20,12 @@ MODULE_LICENSE("GPL v2");
 #define OUI_MYTEK              0x001ee8
 #define OUI_SSL                        0x0050c2        // Actually ID reserved by IEEE.
 #define OUI_PRESONUS           0x000a92
+#define OUI_HARMAN             0x000fd7
 
 #define DICE_CATEGORY_ID       0x04
 #define WEISS_CATEGORY_ID      0x00
 #define LOUD_CATEGORY_ID       0x10
+#define HARMAN_CATEGORY_ID     0x20
 
 #define MODEL_ALESIS_IO_BOTH   0x000001
 
@@ -56,6 +58,8 @@ static int check_dice_category(struct fw_unit *unit)
                category = WEISS_CATEGORY_ID;
        else if (vendor == OUI_LOUD)
                category = LOUD_CATEGORY_ID;
+       else if (vendor == OUI_HARMAN)
+               category = HARMAN_CATEGORY_ID;
        else
                category = DICE_CATEGORY_ID;
        if (device->config_rom[3] != ((vendor << 8) | category) ||
@@ -388,6 +392,14 @@ static const struct ieee1394_device_id dice_id_table[] = {
                .model_id       = 0x000008,
                .driver_data    = (kernel_ulong_t)snd_dice_detect_presonus_formats,
        },
+       // Lexicon I-ONYX FW810S.
+       {
+               .match_flags    = IEEE1394_MATCH_VENDOR_ID |
+                                 IEEE1394_MATCH_MODEL_ID,
+               .vendor_id      = OUI_HARMAN,
+               .model_id       = 0x000001,
+               .driver_data    = (kernel_ulong_t)snd_dice_detect_harman_formats,
+       },
        {
                .match_flags = IEEE1394_MATCH_VERSION,
                .version     = DICE_INTERFACE,
index 7fbffca..adc6f7c 100644 (file)
@@ -233,5 +233,6 @@ int snd_dice_detect_alesis_mastercontrol_formats(struct snd_dice *dice);
 int snd_dice_detect_extension_formats(struct snd_dice *dice);
 int snd_dice_detect_mytek_formats(struct snd_dice *dice);
 int snd_dice_detect_presonus_formats(struct snd_dice *dice);
+int snd_dice_detect_harman_formats(struct snd_dice *dice);
 
 #endif
index 41c5857..aadf7d7 100644 (file)
@@ -87,7 +87,7 @@ static int hwdep_get_info(struct snd_dg00x *dg00x, void __user *arg)
        info.card = dev->card->index;
        *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
        *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
-       strlcpy(info.device_name, dev_name(&dev->device),
+       strscpy(info.device_name, dev_name(&dev->device),
                sizeof(info.device_name));
 
        if (copy_to_user(arg, &info, sizeof(info)))
index e73e8d2..ea64a2a 100644 (file)
@@ -35,13 +35,11 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf,  long count,
        }
 
        memset(&event, 0, sizeof(event));
-       if (ff->dev_lock_changed) {
-               event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
-               event.lock_status.status = (ff->dev_lock_count > 0);
-               ff->dev_lock_changed = false;
+       event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
+       event.lock_status.status = (ff->dev_lock_count > 0);
+       ff->dev_lock_changed = false;
 
-               count = min_t(long, count, sizeof(event.lock_status));
-       }
+       count = min_t(long, count, sizeof(event.lock_status));
 
        spin_unlock_irq(&ff->lock);
 
@@ -79,7 +77,7 @@ static int hwdep_get_info(struct snd_ff *ff, void __user *arg)
        info.card = dev->card->index;
        *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
        *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
-       strlcpy(info.device_name, dev_name(&dev->device),
+       strscpy(info.device_name, dev_name(&dev->device),
                sizeof(info.device_name));
 
        if (copy_to_user(arg, &info, sizeof(info)))
index 8d3b237..7ddb7b9 100644 (file)
 #define LATTER_FETCH_MODE      0xffff00000010ULL
 #define LATTER_SYNC_STATUS     0x0000801c0000ULL
 
+// The content of sync status register differs between models.
+//
+// Fireface UCX:
+//  0xf0000000: (unidentified)
+//  0x0f000000: effective rate of sampling clock
+//  0x00f00000: detected rate of word clock on BNC interface
+//  0x000f0000: detected rate of ADAT or S/PDIF on optical interface
+//  0x0000f000: detected rate of S/PDIF on coaxial interface
+//  0x00000e00: effective source of sampling clock
+//    0x00000e00: Internal
+//    0x00000800: (unidentified)
+//    0x00000600: Word clock on BNC interface
+//    0x00000400: ADAT on optical interface
+//    0x00000200: S/PDIF on coaxial or optical interface
+//  0x00000100: Optical interface is used for ADAT signal
+//  0x00000080: (unidentified)
+//  0x00000040: Synchronized to word clock on BNC interface
+//  0x00000020: Synchronized to ADAT or S/PDIF on optical interface
+//  0x00000010: Synchronized to S/PDIF on coaxial interface
+//  0x00000008: (unidentified)
+//  0x00000004: Lock word clock on BNC interface
+//  0x00000002: Lock ADAT or S/PDIF on optical interface
+//  0x00000001: Lock S/PDIF on coaxial interface
+//
+// Fireface 802 (and perhaps UFX):
+//   0xf0000000: effective rate of sampling clock
+//   0x0f000000: detected rate of ADAT-B on 2nd optical interface
+//   0x00f00000: detected rate of ADAT-A on 1st optical interface
+//   0x000f0000: detected rate of AES/EBU on XLR or coaxial interface
+//   0x0000f000: detected rate of word clock on BNC interface
+//   0x00000e00: effective source of sampling clock
+//     0x00000e00: internal
+//     0x00000800: ADAT-B
+//     0x00000600: ADAT-A
+//     0x00000400: AES/EBU
+//     0x00000200: Word clock
+//   0x00000080: Synchronized to ADAT-B on 2nd optical interface
+//   0x00000040: Synchronized to ADAT-A on 1st optical interface
+//   0x00000020: Synchronized to AES/EBU on XLR or 2nd optical interface
+//   0x00000010: Synchronized to word clock on BNC interface
+//   0x00000008: Lock ADAT-B on 2nd optical interface
+//   0x00000004: Lock ADAT-A on 1st optical interface
+//   0x00000002: Lock AES/EBU on XLR or 2nd optical interface
+//   0x00000001: Lock word clock on BNC interface
+//
+// The pattern for rate bits:
+//   0x00: 32.0 kHz
+//   0x01: 44.1 kHz
+//   0x02: 48.0 kHz
+//   0x04: 64.0 kHz
+//   0x05: 88.2 kHz
+//   0x06: 96.0 kHz
+//   0x08: 128.0 kHz
+//   0x09: 176.4 kHz
+//   0x0a: 192.0 kHz
 static int parse_clock_bits(u32 data, unsigned int *rate,
                            enum snd_ff_clock_src *src,
                            enum snd_ff_unit_version unit_version)
@@ -23,35 +78,48 @@ static int parse_clock_bits(u32 data, unsigned int *rate,
                unsigned int rate;
                u32 flag;
        } *rate_entry, rate_entries[] = {
-               { 32000,        0x00000000, },
-               { 44100,        0x01000000, },
-               { 48000,        0x02000000, },
-               { 64000,        0x04000000, },
-               { 88200,        0x05000000, },
-               { 96000,        0x06000000, },
-               { 128000,       0x08000000, },
-               { 176400,       0x09000000, },
-               { 192000,       0x0a000000, },
+               { 32000,        0x00, },
+               { 44100,        0x01, },
+               { 48000,        0x02, },
+               { 64000,        0x04, },
+               { 88200,        0x05, },
+               { 96000,        0x06, },
+               { 128000,       0x08, },
+               { 176400,       0x09, },
+               { 192000,       0x0a, },
        };
        static const struct {
                enum snd_ff_clock_src src;
                u32 flag;
-       } *clk_entry, clk_entries[] = {
+       } *clk_entry, *clk_entries, ucx_clk_entries[] = {
                { SND_FF_CLOCK_SRC_SPDIF,       0x00000200, },
                { SND_FF_CLOCK_SRC_ADAT1,       0x00000400, },
                { SND_FF_CLOCK_SRC_WORD,        0x00000600, },
                { SND_FF_CLOCK_SRC_INTERNAL,    0x00000e00, },
+       }, ufx_ff802_clk_entries[] = {
+               { SND_FF_CLOCK_SRC_WORD,        0x00000200, },
+               { SND_FF_CLOCK_SRC_SPDIF,       0x00000400, },
+               { SND_FF_CLOCK_SRC_ADAT1,       0x00000600, },
+               { SND_FF_CLOCK_SRC_ADAT2,       0x00000800, },
+               { SND_FF_CLOCK_SRC_INTERNAL,    0x00000e00, },
        };
+       u32 rate_bits;
+       unsigned int clk_entry_count;
        int i;
 
-       if (unit_version != SND_FF_UNIT_VERSION_UCX) {
-               // e.g. 0x00fe0f20 but expected 0x00eff002.
-               data = ((data & 0xf0f0f0f0) >> 4) | ((data & 0x0f0f0f0f) << 4);
+       if (unit_version == SND_FF_UNIT_VERSION_UCX) {
+               rate_bits = (data & 0x0f000000) >> 24;
+               clk_entries = ucx_clk_entries;
+               clk_entry_count = ARRAY_SIZE(ucx_clk_entries);
+       } else {
+               rate_bits = (data & 0xf0000000) >> 28;
+               clk_entries = ufx_ff802_clk_entries;
+               clk_entry_count = ARRAY_SIZE(ufx_ff802_clk_entries);
        }
 
        for (i = 0; i < ARRAY_SIZE(rate_entries); ++i) {
                rate_entry = rate_entries + i;
-               if ((data & 0x0f000000) == rate_entry->flag) {
+               if (rate_bits == rate_entry->flag) {
                        *rate = rate_entry->rate;
                        break;
                }
@@ -59,14 +127,14 @@ static int parse_clock_bits(u32 data, unsigned int *rate,
        if (i == ARRAY_SIZE(rate_entries))
                return -EIO;
 
-       for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) {
+       for (i = 0; i < clk_entry_count; ++i) {
                clk_entry = clk_entries + i;
                if ((data & 0x000e00) == clk_entry->flag) {
                        *src = clk_entry->src;
                        break;
                }
        }
-       if (i == ARRAY_SIZE(clk_entries))
+       if (i == clk_entry_count)
                return -EIO;
 
        return 0;
@@ -249,16 +317,22 @@ static void latter_dump_status(struct snd_ff *ff, struct snd_info_buffer *buffer
                char *const label;
                u32 locked_mask;
                u32 synced_mask;
-       } *clk_entry, clk_entries[] = {
+       } *clk_entry, *clk_entries, ucx_clk_entries[] = {
                { "S/PDIF",     0x00000001, 0x00000010, },
                { "ADAT",       0x00000002, 0x00000020, },
                { "WDClk",      0x00000004, 0x00000040, },
+       }, ufx_ff802_clk_entries[] = {
+               { "WDClk",      0x00000001, 0x00000010, },
+               { "AES/EBU",    0x00000002, 0x00000020, },
+               { "ADAT-A",     0x00000004, 0x00000040, },
+               { "ADAT-B",     0x00000008, 0x00000080, },
        };
        __le32 reg;
        u32 data;
        unsigned int rate;
        enum snd_ff_clock_src src;
        const char *label;
+       unsigned int clk_entry_count;
        int i;
        int err;
 
@@ -270,7 +344,15 @@ static void latter_dump_status(struct snd_ff *ff, struct snd_info_buffer *buffer
 
        snd_iprintf(buffer, "External source detection:\n");
 
-       for (i = 0; i < ARRAY_SIZE(clk_entries); ++i) {
+       if (ff->unit_version == SND_FF_UNIT_VERSION_UCX) {
+               clk_entries = ucx_clk_entries;
+               clk_entry_count = ARRAY_SIZE(ucx_clk_entries);
+       } else {
+               clk_entries = ufx_ff802_clk_entries;
+               clk_entry_count = ARRAY_SIZE(ufx_ff802_clk_entries);
+       }
+
+       for (i = 0; i < clk_entry_count; ++i) {
                clk_entry = clk_entries + i;
                snd_iprintf(buffer, "%s: ", clk_entry->label);
                if (data & clk_entry->locked_mask) {
index e93eb46..626c0c3 100644 (file)
@@ -212,7 +212,7 @@ hwdep_get_info(struct snd_efw *efw, void __user *arg)
        info.card = dev->card->index;
        *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
        *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
-       strlcpy(info.device_name, dev_name(&dev->device),
+       strscpy(info.device_name, dev_name(&dev->device),
                sizeof(info.device_name));
 
        if (copy_to_user(arg, &info, sizeof(info)))
index 0764a47..b5ced5d 100644 (file)
@@ -86,7 +86,7 @@ static int hwdep_get_info(struct snd_motu *motu, void __user *arg)
        info.card = dev->card->index;
        *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
        *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
-       strlcpy(info.device_name, dev_name(&dev->device),
+       strscpy(info.device_name, dev_name(&dev->device),
                sizeof(info.device_name));
 
        if (copy_to_user(arg, &info, sizeof(info)))
index eba33d0..a0fe996 100644 (file)
@@ -35,13 +35,11 @@ static long hwdep_read(struct snd_hwdep *hwdep, char __user *buf,  long count,
        }
 
        memset(&event, 0, sizeof(event));
-       if (oxfw->dev_lock_changed) {
-               event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
-               event.lock_status.status = (oxfw->dev_lock_count > 0);
-               oxfw->dev_lock_changed = false;
+       event.lock_status.type = SNDRV_FIREWIRE_EVENT_LOCK_STATUS;
+       event.lock_status.status = (oxfw->dev_lock_count > 0);
+       oxfw->dev_lock_changed = false;
 
-               count = min_t(long, count, sizeof(event.lock_status));
-       }
+       count = min_t(long, count, sizeof(event.lock_status));
 
        spin_unlock_irq(&oxfw->lock);
 
@@ -79,7 +77,7 @@ static int hwdep_get_info(struct snd_oxfw *oxfw, void __user *arg)
        info.card = dev->card->index;
        *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
        *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
-       strlcpy(info.device_name, dev_name(&dev->device),
+       strscpy(info.device_name, dev_name(&dev->device),
                sizeof(info.device_name));
 
        if (copy_to_user(arg, &info, sizeof(info)))
index 6f38335..74eed95 100644 (file)
@@ -154,7 +154,7 @@ static int hwdep_get_info(struct snd_tscm *tscm, void __user *arg)
        info.card = dev->card->index;
        *(__be32 *)&info.guid[0] = cpu_to_be32(dev->config_rom[3]);
        *(__be32 *)&info.guid[4] = cpu_to_be32(dev->config_rom[4]);
-       strlcpy(info.device_name, dev_name(&dev->device),
+       strscpy(info.device_name, dev_name(&dev->device),
                sizeof(info.device_name));
 
        if (copy_to_user(arg, &info, sizeof(info)))
index 3bc9224..9ed5cfa 100644 (file)
@@ -46,3 +46,17 @@ config SND_INTEL_DSP_CONFIG
        select SND_INTEL_NHLT if ACPI
        # this config should be selected only for Intel DSP platforms.
        # A fallback is provided so that the code compiles in all cases.
+
+config SND_INTEL_BYT_PREFER_SOF
+       bool "Prefer SOF driver over SST on BY/CHT platforms"
+       depends on SND_SST_ATOM_HIFI2_PLATFORM_ACPI && SND_SOC_SOF_BAYTRAIL
+       default n
+       help
+         The kernel has 2 drivers for the Low Power Engine audio-block on
+         Bay- and Cherry-Trail SoCs. The old SST driver and the new SOF
+         driver. If both drivers are enabled then the kernel will default
+         to using the old SST driver, unless told otherwise through the
+         snd_intel_dspcfg.dsp_driver module-parameter.
+
+         Set this option to Y to make the kernel default to the new SOF
+         driver instead.
index b0c0ef8..a9bd39b 100644 (file)
@@ -332,3 +332,40 @@ int snd_hdac_ext_bus_link_put(struct hdac_bus *bus,
        return ret;
 }
 EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_put);
+
+static void hdac_ext_codec_link_up(struct hdac_device *codec)
+{
+       const char *devname = dev_name(&codec->dev);
+       struct hdac_ext_link *hlink =
+               snd_hdac_ext_bus_get_link(codec->bus, devname);
+
+       if (hlink)
+               snd_hdac_ext_bus_link_get(codec->bus, hlink);
+}
+
+static void hdac_ext_codec_link_down(struct hdac_device *codec)
+{
+       const char *devname = dev_name(&codec->dev);
+       struct hdac_ext_link *hlink =
+               snd_hdac_ext_bus_get_link(codec->bus, devname);
+
+       if (hlink)
+               snd_hdac_ext_bus_link_put(codec->bus, hlink);
+}
+
+void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable)
+{
+       struct hdac_bus *bus = codec->bus;
+       bool oldstate = test_bit(codec->addr, &bus->codec_powered);
+
+       if (enable == oldstate)
+               return;
+
+       snd_hdac_bus_link_power(codec, enable);
+
+       if (enable)
+               hdac_ext_codec_link_up(codec);
+       else
+               hdac_ext_codec_link_down(codec);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power);
index 9766f6a..71db859 100644 (file)
@@ -17,6 +17,7 @@ static void snd_hdac_bus_process_unsol_events(struct work_struct *work);
 static const struct hdac_bus_ops default_ops = {
        .command = snd_hdac_bus_send_cmd,
        .get_response = snd_hdac_bus_get_response,
+       .link_power = snd_hdac_bus_link_power,
 };
 
 /**
@@ -264,3 +265,25 @@ void snd_hdac_aligned_write(unsigned int val, void __iomem *addr,
 }
 EXPORT_SYMBOL_GPL(snd_hdac_aligned_write);
 #endif /* CONFIG_SND_HDA_ALIGNED_MMIO */
+
+void snd_hdac_codec_link_up(struct hdac_device *codec)
+{
+       struct hdac_bus *bus = codec->bus;
+
+       if (bus->ops->link_power)
+               bus->ops->link_power(codec, true);
+       else
+               snd_hdac_bus_link_power(codec, true);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_codec_link_up);
+
+void snd_hdac_codec_link_down(struct hdac_device *codec)
+{
+       struct hdac_bus *bus = codec->bus;
+
+       if (bus->ops->link_power)
+               bus->ops->link_power(codec, false);
+       else
+               snd_hdac_bus_link_power(codec, false);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_codec_link_down);
index b98449f..062da7a 100644 (file)
@@ -648,3 +648,17 @@ void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus)
                snd_dma_free_pages(&bus->posbuf);
 }
 EXPORT_SYMBOL_GPL(snd_hdac_bus_free_stream_pages);
+
+/**
+ * snd_hdac_bus_link_power - power up/down codec link
+ * @codec: HD-audio device
+ * @enable: whether to power-up the link
+ */
+void snd_hdac_bus_link_power(struct hdac_device *codec, bool enable)
+{
+       if (enable)
+               set_bit(codec->addr, &codec->bus->codec_powered);
+       else
+               clear_bit(codec->addr, &codec->bus->codec_powered);
+}
+EXPORT_SYMBOL_GPL(snd_hdac_bus_link_power);
index abe7a1b..a6ed3dc 100644 (file)
@@ -435,12 +435,11 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev)
        pos_adj = bus->bdl_pos_adj;
        if (!azx_dev->no_period_wakeup && pos_adj > 0) {
                pos_align = pos_adj;
-               pos_adj = (pos_adj * runtime->rate + 47999) / 48000;
+               pos_adj = DIV_ROUND_UP(pos_adj * runtime->rate, 48000);
                if (!pos_adj)
                        pos_adj = pos_align;
                else
-                       pos_adj = ((pos_adj + pos_align - 1) / pos_align) *
-                               pos_align;
+                       pos_adj = roundup(pos_adj, pos_align);
                pos_adj = frames_to_bytes(runtime, pos_adj);
                if (pos_adj >= period_bytes) {
                        dev_warn(bus->dev, "Too big adjustment %d\n",
index e56e833..0d7771f 100644 (file)
@@ -66,7 +66,7 @@ static struct attribute *hdac_dev_attrs[] = {
        NULL
 };
 
-static struct attribute_group hdac_dev_attr_group = {
+static const struct attribute_group hdac_dev_attr_group = {
        .attrs  = hdac_dev_attrs,
 };
 
index c456861..68bb977 100644 (file)
@@ -452,35 +452,30 @@ int snd_intel_dsp_driver_probe(struct pci_dev *pci)
 }
 EXPORT_SYMBOL_GPL(snd_intel_dsp_driver_probe);
 
+/* Should we default to SOF or SST for BYT/CHT ? */
+#if IS_ENABLED(CONFIG_SND_INTEL_BYT_PREFER_SOF) || \
+    !IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI)
+#define FLAG_SST_OR_SOF_BYT    FLAG_SOF
+#else
+#define FLAG_SST_OR_SOF_BYT    FLAG_SST
+#endif
+
 /*
  * configuration table
  * - the order of similar ACPI ID entries is important!
  * - the first successful match will win
  */
 static const struct config_entry acpi_config_table[] = {
+#if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI) || \
+    IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
 /* BayTrail */
-#if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI)
-       {
-               .flags = FLAG_SST,
-               .acpi_hid = "80860F28",
-       },
-#endif
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
        {
-               .flags = FLAG_SOF,
+               .flags = FLAG_SST_OR_SOF_BYT,
                .acpi_hid = "80860F28",
        },
-#endif
 /* CherryTrail */
-#if IS_ENABLED(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI)
-       {
-               .flags = FLAG_SST,
-               .acpi_hid = "808622A8",
-       },
-#endif
-#if IS_ENABLED(CONFIG_SND_SOC_SOF_BAYTRAIL)
        {
-               .flags = FLAG_SOF,
+               .flags = FLAG_SST_OR_SOF_BYT,
                .acpi_hid = "808622A8",
        },
 #endif
index a684faa..847e3b6 100644 (file)
@@ -84,7 +84,7 @@ int snd_i2c_bus_create(struct snd_card *card, const char *name,
                list_add_tail(&bus->buses, &master->buses);
                bus->master = master;
        }
-       strlcpy(bus->name, name, sizeof(bus->name));
+       strscpy(bus->name, name, sizeof(bus->name));
        err = snd_device_new(card, SNDRV_DEV_BUS, bus, &ops);
        if (err < 0) {
                snd_i2c_bus_free(bus);
@@ -108,7 +108,7 @@ int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name,
        if (device == NULL)
                return -ENOMEM;
        device->addr = addr;
-       strlcpy(device->name, name, sizeof(device->name));
+       strscpy(device->name, name, sizeof(device->name));
        list_add_tail(&device->list, &bus->devices);
        device->bus = bus;
        *rdevice = device;
index 593c6e9..6f221ee 100644 (file)
@@ -95,8 +95,8 @@ static int snd_ad1848_probe(struct device *dev, unsigned int n)
        if (error < 0)
                goto out;
 
-       strlcpy(card->driver, "AD1848", sizeof(card->driver));
-       strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
+       strscpy(card->driver, "AD1848", sizeof(card->driver));
+       strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
 
        if (!thinkpad[n])
                snprintf(card->longname, sizeof(card->longname),
@@ -118,10 +118,9 @@ out:       snd_card_free(card);
        return error;
 }
 
-static int snd_ad1848_remove(struct device *dev, unsigned int n)
+static void snd_ad1848_remove(struct device *dev, unsigned int n)
 {
        snd_card_free(dev_get_drvdata(dev));
-       return 0;
 }
 
 #ifdef CONFIG_PM
index 5105524..e6cd7c4 100644 (file)
@@ -97,10 +97,9 @@ out: snd_card_free(card);
        return error;
 }
 
-static int snd_adlib_remove(struct device *dev, unsigned int n)
+static void snd_adlib_remove(struct device *dev, unsigned int n)
 {
        snd_card_free(dev_get_drvdata(dev));
-       return 0;
 }
 
 static struct isa_driver snd_adlib_driver = {
index faca5dd..3b9fbb0 100644 (file)
@@ -403,7 +403,7 @@ error:
        return err;
 }
 
-static int snd_cmi8328_remove(struct device *pdev, unsigned int dev)
+static void snd_cmi8328_remove(struct device *pdev, unsigned int dev)
 {
        struct snd_card *card = dev_get_drvdata(pdev);
        struct snd_cmi8328 *cmi = card->private_data;
@@ -420,7 +420,6 @@ static int snd_cmi8328_remove(struct device *pdev, unsigned int dev)
        snd_cmi8328_cfg_write(cmi->port, CFG2, 0);
        snd_cmi8328_cfg_write(cmi->port, CFG3, 0);
        snd_card_free(card);
-       return 0;
 }
 
 #ifdef CONFIG_PM
index 4669eb0..19e2585 100644 (file)
@@ -631,11 +631,10 @@ static int snd_cmi8330_isa_probe(struct device *pdev,
        return 0;
 }
 
-static int snd_cmi8330_isa_remove(struct device *devptr,
+static void snd_cmi8330_isa_remove(struct device *devptr,
                                  unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
-       return 0;
 }
 
 #ifdef CONFIG_PM
index 2135963..c56cbc0 100644 (file)
@@ -95,8 +95,8 @@ static int snd_cs4231_probe(struct device *dev, unsigned int n)
        if (error < 0)
                goto out;
 
-       strlcpy(card->driver, "CS4231", sizeof(card->driver));
-       strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
+       strscpy(card->driver, "CS4231", sizeof(card->driver));
+       strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
 
        if (dma2[n] < 0)
                snprintf(card->longname, sizeof(card->longname),
@@ -135,10 +135,9 @@ out:       snd_card_free(card);
        return error;
 }
 
-static int snd_cs4231_remove(struct device *dev, unsigned int n)
+static void snd_cs4231_remove(struct device *dev, unsigned int n)
 {
        snd_card_free(dev_get_drvdata(dev));
-       return 0;
 }
 
 #ifdef CONFIG_PM
index fa3c39c..63fb0cb 100644 (file)
@@ -405,8 +405,8 @@ static int snd_cs423x_probe(struct snd_card *card, int dev)
                if (err < 0)
                        return err;
        }
-       strlcpy(card->driver, chip->pcm->name, sizeof(card->driver));
-       strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
+       strscpy(card->driver, chip->pcm->name, sizeof(card->driver));
+       strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
        if (dma2[dev] < 0)
                snprintf(card->longname, sizeof(card->longname),
                         "%s at 0x%lx, irq %i, dma %i",
@@ -487,11 +487,10 @@ static int snd_cs423x_isa_probe(struct device *pdev,
        return 0;
 }
 
-static int snd_cs423x_isa_remove(struct device *pdev,
+static void snd_cs423x_isa_remove(struct device *pdev,
                                 unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(pdev));
-       return 0;
 }
 
 #ifdef CONFIG_PM
index 6461057..4a1f61f 100644 (file)
@@ -133,8 +133,8 @@ static int snd_es1688_probe(struct snd_card *card, unsigned int n)
        if (error < 0)
                return error;
 
-       strlcpy(card->driver, "ES1688", sizeof(card->driver));
-       strlcpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
+       strscpy(card->driver, "ES1688", sizeof(card->driver));
+       strscpy(card->shortname, chip->pcm->name, sizeof(card->shortname));
        snprintf(card->longname, sizeof(card->longname),
                "%s at 0x%lx, irq %i, dma %i", chip->pcm->name, chip->port,
                 chip->irq, chip->dma8);
@@ -192,10 +192,9 @@ out:
        return error;
 }
 
-static int snd_es1688_isa_remove(struct device *dev, unsigned int n)
+static void snd_es1688_isa_remove(struct device *dev, unsigned int n)
 {
        snd_card_free(dev_get_drvdata(dev));
-       return 0;
 }
 
 static struct isa_driver snd_es1688_driver = {
index 5f8d7e8..9beef80 100644 (file)
@@ -2210,11 +2210,10 @@ static int snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
        }
 }
 
-static int snd_es18xx_isa_remove(struct device *devptr,
-                                unsigned int dev)
+static void snd_es18xx_isa_remove(struct device *devptr,
+                                 unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
-       return 0;
 }
 
 #ifdef CONFIG_PM
index 65f9f46..d33d69f 100644 (file)
@@ -608,10 +608,9 @@ error:
        return err;
 }
 
-static int snd_galaxy_remove(struct device *dev, unsigned int n)
+static void snd_galaxy_remove(struct device *dev, unsigned int n)
 {
        snd_card_free(dev_get_drvdata(dev));
-       return 0;
 }
 
 static struct isa_driver snd_galaxy_driver = {
index 7419b19..015f88a 100644 (file)
@@ -195,10 +195,9 @@ out:       snd_card_free(card);
        return error;
 }
 
-static int snd_gusclassic_remove(struct device *dev, unsigned int n)
+static void snd_gusclassic_remove(struct device *dev, unsigned int n)
 {
        snd_card_free(dev_get_drvdata(dev));
-       return 0;
 }
 
 static struct isa_driver snd_gusclassic_driver = {
index ed2f9d6..c9f31b4 100644 (file)
@@ -324,10 +324,9 @@ out:       snd_card_free(card);
        return error;
 }
 
-static int snd_gusextreme_remove(struct device *dev, unsigned int n)
+static void snd_gusextreme_remove(struct device *dev, unsigned int n)
 {
        snd_card_free(dev_get_drvdata(dev));
-       return 0;
 }
 
 static struct isa_driver snd_gusextreme_driver = {
index 05cd9be..dc09fbd 100644 (file)
@@ -338,10 +338,9 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
        return err;
 }
 
-static int snd_gusmax_remove(struct device *devptr, unsigned int dev)
+static void snd_gusmax_remove(struct device *devptr, unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
-       return 0;
 }
 
 #define DEV_NAME "gusmax"
index 3e9ad93..e4d412e 100644 (file)
@@ -825,10 +825,9 @@ static int snd_interwave_isa_probe(struct device *pdev,
        }
 }
 
-static int snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
+static void snd_interwave_isa_remove(struct device *devptr, unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
-       return 0;
 }
 
 static struct isa_driver snd_interwave_driver = {
index 24b34ec..69647b4 100644 (file)
@@ -1049,10 +1049,9 @@ cfg_error:
 #endif
 }
 
-static int snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
+static void snd_msnd_isa_remove(struct device *pdev, unsigned int dev)
 {
        snd_msnd_unload(dev_get_drvdata(pdev));
-       return 0;
 }
 
 static struct isa_driver snd_msnd_driver = {
index 85a181a..7649a8a 100644 (file)
@@ -878,11 +878,10 @@ static int snd_opl3sa2_isa_probe(struct device *pdev,
        return 0;
 }
 
-static int snd_opl3sa2_isa_remove(struct device *devptr,
+static void snd_opl3sa2_isa_remove(struct device *devptr,
                                  unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
-       return 0;
 }
 
 #ifdef CONFIG_PM
index 44ed1b6..2093334 100644 (file)
@@ -1480,11 +1480,10 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
        return 0;
 }
 
-static int snd_miro_isa_remove(struct device *devptr,
+static void snd_miro_isa_remove(struct device *devptr,
                               unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
-       return 0;
 }
 
 #define DEV_NAME "miro"
index 881d3b5..758f5b5 100644 (file)
@@ -1024,11 +1024,10 @@ static int snd_opti9xx_isa_probe(struct device *devptr,
        return 0;
 }
 
-static int snd_opti9xx_isa_remove(struct device *devptr,
-                                 unsigned int dev)
+static void snd_opti9xx_isa_remove(struct device *devptr,
+                                  unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
-       return 0;
 }
 
 #ifdef CONFIG_PM
index ee379bb..0e2e0ab 100644 (file)
@@ -339,12 +339,11 @@ err_free:
        return err;
 }
 
-static int snd_jazz16_remove(struct device *devptr, unsigned int dev)
+static void snd_jazz16_remove(struct device *devptr, unsigned int dev)
 {
        struct snd_card *card = dev_get_drvdata(devptr);
 
        snd_card_free(card);
-       return 0;
 }
 
 #ifdef CONFIG_PM
index 479197c..db284b7 100644 (file)
@@ -547,10 +547,9 @@ static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
        }
 }
 
-static int snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
+static void snd_sb16_isa_remove(struct device *pdev, unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(pdev));
-       return 0;
 }
 
 #ifdef CONFIG_PM
index 270af86..8635a2b 100644 (file)
@@ -388,7 +388,7 @@ static int snd_sb_csp_riff_load(struct snd_sb_csp * p,
                                return err;
 
                        /* fill in codec header */
-                       strlcpy(p->codec_name, info.codec_name, sizeof(p->codec_name));
+                       strscpy(p->codec_name, info.codec_name, sizeof(p->codec_name));
                        p->func_nr = func_nr;
                        p->mode = le16_to_cpu(funcdesc_h.flags_play_rec);
                        switch (le16_to_cpu(funcdesc_h.VOC_type)) {
index 438109f..8e3e67b 100644 (file)
@@ -192,10 +192,9 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
        return err;
 }
 
-static int snd_sb8_remove(struct device *pdev, unsigned int dev)
+static void snd_sb8_remove(struct device *pdev, unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(pdev));
-       return 0;
 }
 
 #ifdef CONFIG_PM
index 3f703b4..5de5506 100644 (file)
@@ -482,7 +482,7 @@ int snd_sbmixer_add_ctl(struct snd_sb *chip, const char *name, int index, int ty
        ctl = snd_ctl_new1(&newctls[type], chip);
        if (! ctl)
                return -ENOMEM;
-       strlcpy(ctl->id.name, name, sizeof(ctl->id.name));
+       strscpy(ctl->id.name, name, sizeof(ctl->id.name));
        ctl->id.index = index;
        ctl->private_value = value;
        if ((err = snd_ctl_add(chip->card, ctl)) < 0)
index 3d0bea4..def1375 100644 (file)
@@ -672,7 +672,7 @@ err_exit:
        return err;
 }
 
-static int snd_sc6000_remove(struct device *devptr, unsigned int dev)
+static void snd_sc6000_remove(struct device *devptr, unsigned int dev)
 {
        struct snd_card *card = dev_get_drvdata(devptr);
        char __iomem **vport = card->private_data;
@@ -684,7 +684,6 @@ static int snd_sc6000_remove(struct device *devptr, unsigned int dev)
        release_region(mss_port[dev], 4);
 
        snd_card_free(card);
-       return 0;
 }
 
 static struct isa_driver snd_sc6000_driver = {
index 2e5a5c5..e70ef9a 100644 (file)
@@ -1183,10 +1183,9 @@ _release_card:
        return ret;
 }
 
-static int snd_sscape_remove(struct device *devptr, unsigned int dev)
+static void snd_sscape_remove(struct device *devptr, unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
-       return 0;
 }
 
 #define DEV_NAME "sscape"
index 9e0f6b2..b750a4f 100644 (file)
@@ -565,11 +565,10 @@ static int snd_wavefront_isa_probe(struct device *pdev,
        return 0;
 }
 
-static int snd_wavefront_isa_remove(struct device *devptr,
+static void snd_wavefront_isa_remove(struct device *devptr,
                                    unsigned int dev)
 {
        snd_card_free(dev_get_drvdata(devptr));
-       return 0;
 }
 
 #define DEV_NAME "wavefront"
index 38f25e9..49679aa 100644 (file)
@@ -355,8 +355,8 @@ static int mixer_ioctl(struct file *file, u_int cmd, u_long arg)
                {
                    mixer_info info;
                    memset(&info, 0, sizeof(info));
-                   strlcpy(info.id, dmasound.mach.name2, sizeof(info.id));
-                   strlcpy(info.name, dmasound.mach.name2, sizeof(info.name));
+                   strscpy(info.id, dmasound.mach.name2, sizeof(info.id));
+                   strscpy(info.name, dmasound.mach.name2, sizeof(info.name));
                    info.modify_counter = mixer.modify_counter;
                    if (copy_to_user((void __user *)arg, &info, sizeof(info)))
                            return -EFAULT;
index 5d42c42..5d835d2 100644 (file)
@@ -857,8 +857,7 @@ snd_ad1889_create(struct snd_card *card,
                return err;
 
        /* check PCI availability (32bit DMA) */
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 ||
-           dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_err(card->dev, "error setting 32-bit DMA mask.\n");
                pci_disable_device(pci);
                return -ENXIO;
index 4462375..51f2479 100644 (file)
@@ -2057,8 +2057,7 @@ static int snd_ali_create(struct snd_card *card,
        if (err < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 31 bits */
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(31)) < 0 ||
-           dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(31)) < 0) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(31))) {
                dev_err(card->dev,
                        "architecture does not support 31bit PCI busmaster DMA\n");
                pci_disable_device(pci);
index 8d2471e..1dc8c4e 100644 (file)
@@ -625,8 +625,7 @@ static int snd_als300_create(struct snd_card *card,
        if ((err = pci_enable_device(pci)) < 0)
                return err;
 
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 ||
-               dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
                dev_err(card->dev, "error setting 28bit DMA mask\n");
                pci_disable_device(pci);
                return -ENXIO;
index ba6390e..2edc745 100644 (file)
@@ -837,8 +837,7 @@ static int snd_card_als4000_probe(struct pci_dev *pci,
                return err;
        }
        /* check, if we can restrict PCI DMA transfers to 24 bits */
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 ||
-           dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
                dev_err(&pci->dev, "architecture does not support 24bit PCI busmaster DMA\n");
                pci_disable_device(pci);
                return -ENXIO;
index f37856a..9570d9a 100644 (file)
@@ -52,7 +52,7 @@ void hpi_debug_data(u16 *pdata, u32 len)
        int lines;
        int cols = 8;
 
-       lines = (len + cols - 1) / cols;
+       lines = DIV_ROUND_UP(len, cols);
        if (lines > 8)
                lines = 8;
 
index be276fb..5dd98e6 100644 (file)
@@ -151,8 +151,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
        // check PCI availability (DMA).
        if ((err = pci_enable_device(pci)) < 0)
                return err;
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 ||
-           dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_err(card->dev, "error to set DMA mask\n");
                pci_disable_device(pci);
                return -ENXIO;
index f1865af..4339684 100644 (file)
@@ -236,8 +236,7 @@ static int snd_aw2_create(struct snd_card *card,
        pci_set_master(pci);
 
        /* check PCI availability (32bit DMA) */
-       if ((dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) ||
-           (dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0)) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_err(card->dev, "Impossible to set 32bit mask DMA\n");
                pci_disable_device(pci);
                return -ENXIO;
index 77c7030..2ac594d 100644 (file)
@@ -2379,8 +2379,7 @@ snd_azf3328_create(struct snd_card *card,
        chip->irq = -1;
 
        /* check if we can restrict PCI DMA transfers to 24 bits */
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 ||
-           dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
                dev_err(card->dev,
                        "architecture does not support 24bit PCI busmaster DMA\n"
                );
@@ -2448,7 +2447,7 @@ snd_azf3328_create(struct snd_card *card,
 
                /* shutdown codecs to reduce power / noise */
                        /* have ...ctrl_codec_activity() act properly */
-               codec->running = 1;
+               codec->running = true;
                snd_azf3328_ctrl_codec_activity(chip, codec_type, 0);
 
                spin_lock_irq(codec->lock);
index 54cb223..cf9f8d8 100644 (file)
@@ -327,7 +327,8 @@ static irqreturn_t snd_bt87x_interrupt(int irq, void *dev_id)
                current_block = chip->current_line * 16 / chip->lines;
                irq_block = status >> INT_RISCS_SHIFT;
                if (current_block != irq_block)
-                       chip->current_line = (irq_block * chip->lines + 15) / 16;
+                       chip->current_line = DIV_ROUND_UP(irq_block * chip->lines,
+                                                         16);
 
                snd_pcm_period_elapsed(chip->substream);
        }
index c189f70..ee20f9a 100644 (file)
@@ -1605,8 +1605,7 @@ static int snd_ca0106_create(int dev, struct snd_card *card,
        err = pci_enable_device(pci);
        if (err < 0)
                return err;
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 ||
-           dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_err(card->dev, "error to set 32bit mask DMA\n");
                pci_disable_device(pci);
                return -ENXIO;
index 4490dd7..37f516e 100644 (file)
@@ -813,7 +813,7 @@ static void snd_cs46xx_set_capture_sample_rate(struct snd_cs46xx *chip, unsigned
        correctionPerGOF = tmp1 / GOF_PER_SEC;
        tmp1 -= correctionPerGOF * GOF_PER_SEC;
        correctionPerSec = tmp1;
-       initialDelay = ((48000 * 24) + rate - 1) / rate;
+       initialDelay = DIV_ROUND_UP(48000 * 24, rate);
 
        /*
         *  Fill in the VariDecimate control block.
index 11ce3c4..359bc6a 100644 (file)
@@ -269,8 +269,7 @@ static int snd_cs5535audio_create(struct snd_card *card,
        if ((err = pci_enable_device(pci)) < 0)
                return err;
 
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0 ||
-           dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32))) {
                dev_warn(card->dev, "unable to get 32bit dma\n");
                err = -ENXIO;
                goto pcifail;
index 4e29530..110d320 100644 (file)
@@ -158,13 +158,13 @@ int olpc_quirks(struct snd_card *card, struct snd_ac97 *ac97)
        /* drop the original AD1888 HPF control */
        memset(&elem, 0, sizeof(elem));
        elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-       strlcpy(elem.name, "High Pass Filter Enable", sizeof(elem.name));
+       strscpy(elem.name, "High Pass Filter Enable", sizeof(elem.name));
        snd_ctl_remove_id(card, &elem);
 
        /* drop the original V_REFOUT control */
        memset(&elem, 0, sizeof(elem));
        elem.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-       strlcpy(elem.name, "V_REFOUT Enable", sizeof(elem.name));
+       strscpy(elem.name, "V_REFOUT Enable", sizeof(elem.name));
        snd_ctl_remove_id(card, &elem);
 
        /* add the OLPC-specific controls */
index 108ab44..0cea498 100644 (file)
@@ -1901,12 +1901,8 @@ static int hw_card_start(struct hw *hw)
                return err;
 
        /* Set DMA transfer mask */
-       if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) {
-               dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits));
-       } else {
-               dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
-               dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32));
-       }
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(dma_bits)))
+               dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32));
 
        if (!hw->io_base) {
                err = pci_request_regions(pci, "XFi");
index fc1bc18..a855fb8 100644 (file)
@@ -2026,12 +2026,8 @@ static int hw_card_start(struct hw *hw)
                return err;
 
        /* Set DMA transfer mask */
-       if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) {
-               dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits));
-       } else {
-               dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
-               dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32));
-       }
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(dma_bits)))
+               dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32));
 
        if (!hw->io_base) {
                err = pci_request_regions(pci, "XFi");
index 3f48ad0..81dfc6a 100644 (file)
@@ -433,7 +433,7 @@ int ct_alsa_pcm_create(struct ct_atc *atc,
        pcm->private_data = atc;
        pcm->info_flags = 0;
        pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
-       strlcpy(pcm->name, device_name, sizeof(pcm->name));
+       strscpy(pcm->name, device_name, sizeof(pcm->name));
 
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &ct_pcm_playback_ops);
 
index 61e51e3..6d0a01b 100644 (file)
@@ -209,7 +209,7 @@ int rsc_mgr_init(struct rsc_mgr *mgr, enum RSCTYP type,
 
        mgr->type = NUM_RSCTYP;
 
-       mgr->rscs = kzalloc(((amount + 8 - 1) / 8), GFP_KERNEL);
+       mgr->rscs = kzalloc(DIV_ROUND_UP(amount, 8), GFP_KERNEL);
        if (!mgr->rscs)
                return -ENOMEM;
 
index 29b7720..353934c 100644 (file)
@@ -168,9 +168,9 @@ static int snd_card_emu10k1_probe(struct pci_dev *pci,
        }
 #endif
  
-       strlcpy(card->driver, emu->card_capabilities->driver,
+       strscpy(card->driver, emu->card_capabilities->driver,
                sizeof(card->driver));
-       strlcpy(card->shortname, emu->card_capabilities->name,
+       strscpy(card->shortname, emu->card_capabilities->name,
                sizeof(card->shortname));
        snprintf(card->longname, sizeof(card->longname),
                 "%s (rev.%d, serial:0x%x) at 0x%lx, irq %i",
index bd70e11..24a2fd7 100644 (file)
@@ -1869,7 +1869,7 @@ int snd_emu10k1_create(struct snd_card *card,
                        emu->serial);
 
        if (!*card->id && c->id)
-               strlcpy(card->id, c->id, sizeof(card->id));
+               strscpy(card->id, c->id, sizeof(card->id));
 
        is_audigy = emu->audigy = c->emu10k2_chip;
 
index 4e76ed0..80ef62a 100644 (file)
@@ -940,7 +940,7 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu,
                        memset(gctl, 0, sizeof(*gctl));
                        id = &ctl->kcontrol->id;
                        gctl->id.iface = (__force int)id->iface;
-                       strlcpy(gctl->id.name, id->name, sizeof(gctl->id.name));
+                       strscpy(gctl->id.name, id->name, sizeof(gctl->id.name));
                        gctl->id.index = id->index;
                        gctl->id.device = id->device;
                        gctl->id.subdevice = id->subdevice;
@@ -976,7 +976,7 @@ static int snd_emu10k1_icode_poke(struct snd_emu10k1 *emu,
        err = snd_emu10k1_verify_controls(emu, icode, in_kernel);
        if (err < 0)
                goto __error;
-       strlcpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name));
+       strscpy(emu->fx8010.name, icode->name, sizeof(emu->fx8010.name));
        /* stop FX processor - this may be dangerous, but it's better to miss
           some samples than generate wrong ones - [jk] */
        if (emu->audigy)
@@ -1015,7 +1015,7 @@ static int snd_emu10k1_icode_peek(struct snd_emu10k1 *emu,
        int err;
 
        mutex_lock(&emu->fx8010.lock);
-       strlcpy(icode->name, emu->fx8010.name, sizeof(icode->name));
+       strscpy(icode->name, emu->fx8010.name, sizeof(icode->name));
        /* ok, do the main job */
        err = snd_emu10k1_gpr_peek(emu, icode);
        if (err >= 0)
index 94b8d5b..288e0fd 100644 (file)
@@ -375,7 +375,7 @@ int snd_emu10k1_alloc_pages_maybe_wider(struct snd_emu10k1 *emu, size_t size,
                                        struct snd_dma_buffer *dmab)
 {
        if (emu->iommu_workaround) {
-               size_t npages = (size + PAGE_SIZE - 1) / PAGE_SIZE;
+               size_t npages = DIV_ROUND_UP(size, PAGE_SIZE);
                size_t size_real = npages * PAGE_SIZE;
 
                /*
index d9acef0..93c4fd3 100644 (file)
@@ -752,7 +752,7 @@ static void snd_es1371_dac1_rate(struct ensoniq * ensoniq, unsigned int rate)
        unsigned int freq, r;
 
        mutex_lock(&ensoniq->src_mutex);
-       freq = ((rate << 15) + 1500) / 3000;
+       freq = DIV_ROUND_CLOSEST(rate << 15, 3000);
        r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
                                                   ES_1371_DIS_P2 | ES_1371_DIS_R1)) |
                ES_1371_DIS_P1;
@@ -773,7 +773,7 @@ static void snd_es1371_dac2_rate(struct ensoniq * ensoniq, unsigned int rate)
        unsigned int freq, r;
 
        mutex_lock(&ensoniq->src_mutex);
-       freq = ((rate << 15) + 1500) / 3000;
+       freq = DIV_ROUND_CLOSEST(rate << 15, 3000);
        r = (snd_es1371_wait_src_ready(ensoniq) & (ES_1371_SRC_DISABLE |
                                                   ES_1371_DIS_P1 | ES_1371_DIS_R1)) |
                ES_1371_DIS_P2;
index 09704a7..3b5d68c 100644 (file)
@@ -1560,8 +1560,7 @@ static int snd_es1938_create(struct snd_card *card,
        if ((err = pci_enable_device(pci)) < 0)
                return err;
         /* check, if we can restrict PCI DMA transfers to 24 bits */
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 ||
-           dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
                dev_err(card->dev,
                        "architecture does not support 24bit PCI busmaster DMA\n");
                pci_disable_device(pci);
index 34332d0..747fa69 100644 (file)
@@ -2668,8 +2668,7 @@ static int snd_es1968_create(struct snd_card *card,
        if ((err = pci_enable_device(pci)) < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 28 bits */
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 ||
-           dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
                dev_err(card->dev,
                        "architecture does not support 28bit PCI busmaster DMA\n");
                pci_disable_device(pci);
@@ -2768,7 +2767,7 @@ static int snd_es1968_create(struct snd_card *card,
                if (!snd_tea575x_init(&chip->tea, THIS_MODULE)) {
                        dev_info(card->dev, "detected TEA575x radio type %s\n",
                                   get_tea575x_gpio(chip)->name);
-                       strlcpy(chip->tea.card, get_tea575x_gpio(chip)->name,
+                       strscpy(chip->tea.card, get_tea575x_gpio(chip)->name,
                                sizeof(chip->tea.card));
                        break;
                }
index 0a95032..c6ad623 100644 (file)
@@ -1300,7 +1300,7 @@ static int snd_fm801_create(struct snd_card *card,
                chip->tea575x_tuner |= tuner_only;
        }
        if (!(chip->tea575x_tuner & TUNER_DISABLED)) {
-               strlcpy(chip->tea.card, get_tea575x_gpio(chip)->name,
+               strscpy(chip->tea.card, get_tea575x_gpio(chip)->name,
                        sizeof(chip->tea.card));
        }
 #endif
index 4dc0164..1a001ec 100644 (file)
@@ -764,7 +764,7 @@ int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
        }
        if (!name)
                return 0;
-       strlcpy(label, name, maxlen);
+       strscpy(label, name, maxlen);
        return 1;
 }
 EXPORT_SYMBOL_GPL(snd_hda_get_pin_label);
index eec1775..9b75506 100644 (file)
@@ -3999,7 +3999,7 @@ int snd_hda_add_imux_item(struct hda_codec *codec,
                         sizeof(imux->items[imux->num_items].label),
                         "%s %d", label, label_idx);
        else
-               strlcpy(imux->items[imux->num_items].label, label,
+               strscpy(imux->items[imux->num_items].label, label,
                        sizeof(imux->items[imux->num_items].label));
        imux->items[imux->num_items].index = index;
        imux->num_items++;
index 80016b7..9087981 100644 (file)
@@ -735,7 +735,7 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec,
                          &pcm);
        if (err < 0)
                return err;
-       strlcpy(pcm->name, cpcm->name, sizeof(pcm->name));
+       strscpy(pcm->name, cpcm->name, sizeof(pcm->name));
        apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
        if (apcm == NULL) {
                snd_device_free(chip->card, pcm);
index 136477e..9e97443 100644 (file)
@@ -260,7 +260,7 @@ int snd_hdmi_parse_eld(struct hda_codec *codec, struct parsed_hdmi_eld *e,
                codec_info(codec, "HDMI: out of range MNL %d\n", mnl);
                goto out_fail;
        } else
-               strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1);
+               strscpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl + 1);
 
        for (i = 0; i < e->sad_count; i++) {
                if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) {
index 8060cc8..5e40944 100644 (file)
@@ -5721,7 +5721,7 @@ static void fill_pcm_stream_name(char *str, size_t len, const char *sfx,
 
        if (*str)
                return;
-       strlcpy(str, chip_name, len);
+       strscpy(str, chip_name, len);
 
        /* drop non-alnum chars after a space */
        for (p = strchr(str, ' '); p; p = strchr(p + 1, ' ')) {
index 5a50d3a..7ba665e 100644 (file)
@@ -1967,12 +1967,8 @@ static int azx_first_init(struct azx *chip)
        /* allow 64bit DMA address if supported by H/W */
        if (!(gcap & AZX_GCAP_64OK))
                dma_bits = 32;
-       if (!dma_set_mask(&pci->dev, DMA_BIT_MASK(dma_bits))) {
-               dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(dma_bits));
-       } else {
-               dma_set_mask(&pci->dev, DMA_BIT_MASK(32));
-               dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(32));
-       }
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(dma_bits)))
+               dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(32));
 
        /* read number of streams from GCAP register instead of using
         * hardcoded value
@@ -2037,7 +2033,7 @@ static int azx_first_init(struct azx *chip)
                return -EBUSY;
 
        strcpy(card->driver, "HDA-Intel");
-       strlcpy(card->shortname, driver_short_names[chip->driver_type],
+       strscpy(card->shortname, driver_short_names[chip->driver_type],
                sizeof(card->shortname));
        snprintf(card->longname, sizeof(card->longname),
                 "%s at 0x%lx irq %i",
@@ -2221,8 +2217,6 @@ static const struct snd_pci_quirk power_save_denylist[] = {
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
-       SND_PCI_QUIRK(0x1558, 0x6504, "Clevo W65_67SB", 0),
-       /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        SND_PCI_QUIRK(0x1028, 0x0497, "Dell Precision T3600", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        /* Note the P55A-UD3 and Z87-D3HP share the subsys id for the HDA dev */
@@ -2304,7 +2298,7 @@ static int azx_probe_continue(struct azx *chip)
 
                /* HSW/BDW controllers need this power */
                if (CONTROLLER_IN_GPU(pci))
-                       hda->need_i915_power = 1;
+                       hda->need_i915_power = true;
        }
 
        /* Request display power well for the HDA controller or codec. For
@@ -2481,6 +2475,8 @@ static const struct pci_device_id azx_ids[] = {
        /* CometLake-H */
        { PCI_DEVICE(0x8086, 0x06C8),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+       { PCI_DEVICE(0x8086, 0xf1c8),
+         .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
        /* CometLake-S */
        { PCI_DEVICE(0x8086, 0xa3f0),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
index 5880594..b8b5680 100644 (file)
@@ -530,7 +530,7 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
                       !is_jack_detectable(codec, nid);
 
        if (base_name)
-               strlcpy(name, base_name, sizeof(name));
+               strscpy(name, base_name, sizeof(name));
        else
                snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), NULL);
        if (phantom_jack)
index 361cf20..6f2b743 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
 #include <linux/of_device.h>
+#include <linux/reset.h>
 #include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/string.h>
@@ -70,9 +71,9 @@
 struct hda_tegra {
        struct azx chip;
        struct device *dev;
-       struct clk *hda_clk;
-       struct clk *hda2codec_2x_clk;
-       struct clk *hda2hdmi_clk;
+       struct reset_control *reset;
+       struct clk_bulk_data clocks[3];
+       unsigned int nclocks;
        void __iomem *regs;
        struct work_struct probe_work;
 };
@@ -113,36 +114,6 @@ static void hda_tegra_init(struct hda_tegra *hda)
        writel(v, hda->regs + HDA_IPFS_INTR_MASK);
 }
 
-static int hda_tegra_enable_clocks(struct hda_tegra *data)
-{
-       int rc;
-
-       rc = clk_prepare_enable(data->hda_clk);
-       if (rc)
-               return rc;
-       rc = clk_prepare_enable(data->hda2codec_2x_clk);
-       if (rc)
-               goto disable_hda;
-       rc = clk_prepare_enable(data->hda2hdmi_clk);
-       if (rc)
-               goto disable_codec_2x;
-
-       return 0;
-
-disable_codec_2x:
-       clk_disable_unprepare(data->hda2codec_2x_clk);
-disable_hda:
-       clk_disable_unprepare(data->hda_clk);
-       return rc;
-}
-
-static void hda_tegra_disable_clocks(struct hda_tegra *data)
-{
-       clk_disable_unprepare(data->hda2hdmi_clk);
-       clk_disable_unprepare(data->hda2codec_2x_clk);
-       clk_disable_unprepare(data->hda_clk);
-}
-
 /*
  * power management
  */
@@ -186,7 +157,7 @@ static int __maybe_unused hda_tegra_runtime_suspend(struct device *dev)
                azx_stop_chip(chip);
                azx_enter_link_reset(chip);
        }
-       hda_tegra_disable_clocks(hda);
+       clk_bulk_disable_unprepare(hda->nclocks, hda->clocks);
 
        return 0;
 }
@@ -198,15 +169,27 @@ static int __maybe_unused hda_tegra_runtime_resume(struct device *dev)
        struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
        int rc;
 
-       rc = hda_tegra_enable_clocks(hda);
+       if (!chip->running) {
+               rc = reset_control_assert(hda->reset);
+               if (rc)
+                       return rc;
+       }
+
+       rc = clk_bulk_prepare_enable(hda->nclocks, hda->clocks);
        if (rc != 0)
                return rc;
-       if (chip && chip->running) {
+       if (chip->running) {
                hda_tegra_init(hda);
                azx_init_chip(chip, 1);
                /* disable controller wake up event*/
                azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
                           ~STATESTS_INT_MASK);
+       } else {
+               usleep_range(10, 100);
+
+               rc = reset_control_deassert(hda->reset);
+               if (rc)
+                       return rc;
        }
 
        return 0;
@@ -268,29 +251,6 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev)
        return 0;
 }
 
-static int hda_tegra_init_clk(struct hda_tegra *hda)
-{
-       struct device *dev = hda->dev;
-
-       hda->hda_clk = devm_clk_get(dev, "hda");
-       if (IS_ERR(hda->hda_clk)) {
-               dev_err(dev, "failed to get hda clock\n");
-               return PTR_ERR(hda->hda_clk);
-       }
-       hda->hda2codec_2x_clk = devm_clk_get(dev, "hda2codec_2x");
-       if (IS_ERR(hda->hda2codec_2x_clk)) {
-               dev_err(dev, "failed to get hda2codec_2x clock\n");
-               return PTR_ERR(hda->hda2codec_2x_clk);
-       }
-       hda->hda2hdmi_clk = devm_clk_get(dev, "hda2hdmi");
-       if (IS_ERR(hda->hda2hdmi_clk)) {
-               dev_err(dev, "failed to get hda2hdmi clock\n");
-               return PTR_ERR(hda->hda2hdmi_clk);
-       }
-
-       return 0;
-}
-
 static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
 {
        struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
@@ -495,7 +455,17 @@ static int hda_tegra_probe(struct platform_device *pdev)
                return err;
        }
 
-       err = hda_tegra_init_clk(hda);
+       hda->reset = devm_reset_control_array_get_exclusive(&pdev->dev);
+       if (IS_ERR(hda->reset)) {
+               err = PTR_ERR(hda->reset);
+               goto out_free;
+       }
+
+       hda->clocks[hda->nclocks++].id = "hda";
+       hda->clocks[hda->nclocks++].id = "hda2hdmi";
+       hda->clocks[hda->nclocks++].id = "hda2codec_2x";
+
+       err = devm_clk_bulk_get(&pdev->dev, hda->nclocks, hda->clocks);
        if (err < 0)
                goto out_free;
 
index d49cc44..f2aa226 100644 (file)
@@ -567,7 +567,7 @@ static void cxt_fixup_mute_led_eapd(struct hda_codec *codec,
 
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
                spec->mute_led_eapd = 0x1b;
-               spec->dynamic_eapd = 1;
+               spec->dynamic_eapd = true;
                snd_hda_gen_add_mute_led_cdev(codec, cx_auto_vmaster_mute_led);
        }
 }
index 97adff0..e405be7 100644 (file)
@@ -2130,7 +2130,6 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
                        goto unlock;
                }
                per_cvt = get_cvt(spec, cvt_idx);
-               snd_BUG_ON(!per_cvt->assigned);
                per_cvt->assigned = 0;
                hinfo->nid = 0;
 
index 2906455..1927605 100644 (file)
@@ -1905,6 +1905,7 @@ enum {
        ALC889_FIXUP_FRONT_HP_NO_PRESENCE,
        ALC889_FIXUP_VAIO_TT,
        ALC888_FIXUP_EEE1601,
+       ALC886_FIXUP_EAPD,
        ALC882_FIXUP_EAPD,
        ALC883_FIXUP_EAPD,
        ALC883_FIXUP_ACER_EAPD,
@@ -2238,6 +2239,15 @@ static const struct hda_fixup alc882_fixups[] = {
                        { }
                }
        },
+       [ALC886_FIXUP_EAPD] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* change to EAPD mode */
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x0068 },
+                       { }
+               }
+       },
        [ALC882_FIXUP_EAPD] = {
                .type = HDA_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -2510,6 +2520,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
 
        SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
+       SND_PCI_QUIRK(0x13fe, 0x1009, "Advantech MIT-W101", ALC886_FIXUP_EAPD),
        SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
        SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", ALC1220_FIXUP_GB_DUAL_CODECS),
        SND_PCI_QUIRK(0x1458, 0xa0cd, "Gigabyte X570 Aorus Master", ALC1220_FIXUP_CLEVO_P950),
@@ -4280,6 +4291,28 @@ static void alc280_fixup_hp_gpio4(struct hda_codec *codec,
        }
 }
 
+/* HP Spectre x360 14 model needs a unique workaround for enabling the amp;
+ * it needs to toggle the GPIO0 once on and off at each time (bko#210633)
+ */
+static void alc245_fixup_hp_x360_amp(struct hda_codec *codec,
+                                    const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
+               spec->gpio_mask |= 0x01;
+               spec->gpio_dir |= 0x01;
+               break;
+       case HDA_FIXUP_ACT_INIT:
+               /* need to toggle GPIO to enable the amp */
+               alc_update_gpio_data(codec, 0x01, true);
+               msleep(100);
+               alc_update_gpio_data(codec, 0x01, false);
+               break;
+       }
+}
+
 static void alc_update_coef_led(struct hda_codec *codec,
                                struct alc_coef_led *led,
                                bool polarity, bool on)
@@ -6266,6 +6299,7 @@ enum {
        ALC280_FIXUP_HP_DOCK_PINS,
        ALC269_FIXUP_HP_DOCK_GPIO_MIC1_LED,
        ALC280_FIXUP_HP_9480M,
+       ALC245_FIXUP_HP_X360_AMP,
        ALC288_FIXUP_DELL_HEADSET_MODE,
        ALC288_FIXUP_DELL1_MIC_NO_PRESENCE,
        ALC288_FIXUP_DELL_XPS_13,
@@ -6971,6 +7005,10 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc280_fixup_hp_9480m,
        },
+       [ALC245_FIXUP_HP_X360_AMP] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc245_fixup_hp_x360_amp,
+       },
        [ALC288_FIXUP_DELL_HEADSET_MODE] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_headset_mode_dell_alc288,
@@ -7985,6 +8023,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
        SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
        SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -8357,6 +8396,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc298-samsung-headphone"},
        {.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"},
        {.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"},
+       {.id = ALC245_FIXUP_HP_X360_AMP, .name = "alc245-hp-x360-amp"},
        {}
 };
 #define ALC225_STANDARD_PINS \
index 73e1e54..f814dbb 100644 (file)
@@ -2486,8 +2486,7 @@ static int snd_ice1712_create(struct snd_card *card,
        if (err < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 28 bits */
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 ||
-           dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
                dev_err(card->dev,
                        "architecture does not support 28bit PCI busmaster DMA\n");
                pci_disable_device(pci);
index e57a55c..f0f8324 100644 (file)
@@ -413,7 +413,7 @@ static struct snd_kcontrol *ctl_find(struct snd_card *card,
 {
        struct snd_ctl_elem_id sid = {0};
 
-       strlcpy(sid.name, name, sizeof(sid.name));
+       strscpy(sid.name, name, sizeof(sid.name));
        sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
        return snd_ctl_find_id(card, &sid);
 }
index 7aa3f92..82cf365 100644 (file)
@@ -189,12 +189,12 @@ static void psc724_set_jack_state(struct snd_ice1712 *ice, bool hp_connected)
        /* notify about master speaker mute change */
        memset(&elem_id, 0, sizeof(elem_id));
        elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
-       strlcpy(elem_id.name, "Master Speakers Playback Switch",
+       strscpy(elem_id.name, "Master Speakers Playback Switch",
                                                sizeof(elem_id.name));
        kctl = snd_ctl_find_id(ice->card, &elem_id);
        snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
        /* and headphone mute change */
-       strlcpy(elem_id.name, spec->wm8776.ctl[WM8776_CTL_HP_SW].name,
+       strscpy(elem_id.name, spec->wm8776.ctl[WM8776_CTL_HP_SW].name,
                                                sizeof(elem_id.name));
        kctl = snd_ctl_find_id(ice->card, &elem_id);
        snd_ctl_notify(ice->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
index 0e3e04a..0dfa093 100644 (file)
@@ -771,7 +771,7 @@ static struct snd_kcontrol *ctl_find(struct snd_card *card,
 {
        struct snd_ctl_elem_id sid = {0};
 
-       strlcpy(sid.name, name, sizeof(sid.name));
+       strscpy(sid.name, name, sizeof(sid.name));
        sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
        return snd_ctl_find_id(card, &sid);
 }
index d96008d..6eda861 100644 (file)
@@ -38,7 +38,7 @@ static void snd_wm8776_activate_ctl(struct snd_wm8776 *wm,
        unsigned int index_offset;
 
        memset(&elem_id, 0, sizeof(elem_id));
-       strlcpy(elem_id.name, ctl_name, sizeof(elem_id.name));
+       strscpy(elem_id.name, ctl_name, sizeof(elem_id.name));
        elem_id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
        kctl = snd_ctl_find_id(card, &elem_id);
        if (!kctl)
index 1b7df0c..19872ce 100644 (file)
@@ -1129,13 +1129,14 @@ static int snd_intel8x0m_create(struct snd_card *card,
                chip->bmaddr = pci_iomap(pci, 3, 0);
        else
                chip->bmaddr = pci_iomap(pci, 1, 0);
+
+port_inited:
        if (!chip->bmaddr) {
                dev_err(card->dev, "Controller space ioremap problem\n");
                snd_intel8x0m_free(chip);
                return -EIO;
        }
 
- port_inited:
        /* initialize offsets */
        chip->bdbars_count = 2;
        tbl = intel_regs;
index cdd8db7..491c90f 100644 (file)
@@ -669,7 +669,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
        }
 
        strcpy(card->driver, "Lola");
-       strlcpy(card->shortname, "Digigram Lola", sizeof(card->shortname));
+       strscpy(card->shortname, "Digigram Lola", sizeof(card->shortname));
        snprintf(card->longname, sizeof(card->longname),
                 "%s at 0x%lx irq %i",
                 card->shortname, chip->bar[0].addr, chip->irq);
index fdb85f2..cafd30e 100644 (file)
@@ -135,7 +135,7 @@ int lola_init_clock_widget(struct lola *chip, int nid)
        }
 
        nitems = chip->clock.items;
-       nb_verbs = (nitems + 3) / 4;
+       nb_verbs = DIV_ROUND_UP(nitems, 4);
        idx = 0;
        idx_list = 0;
        for (i = 0; i < nb_verbs; i++) {
index f647c7e..684faaf 100644 (file)
@@ -601,7 +601,7 @@ int lola_create_pcm(struct lola *chip)
                          &pcm);
        if (err < 0)
                return err;
-       strlcpy(pcm->name, "Digigram Lola", sizeof(pcm->name));
+       strscpy(pcm->name, "Digigram Lola", sizeof(pcm->name));
        pcm->private_data = chip;
        for (i = 0; i < 2; i++) {
                if (chip->pcm[i].num_streams)
index 40232a2..d2c2cd6 100644 (file)
@@ -1245,7 +1245,7 @@ static void snd_m3_pcm_setup2(struct snd_m3 *chip, struct m3_dma *s,
                          snd_pcm_format_width(runtime->format) == 16 ? 0 : 1);
 
        /* set up dac/adc rate */
-       freq = ((runtime->rate << 15) + 24000 ) / 48000;
+       freq = DIV_ROUND_CLOSEST(runtime->rate << 15, 48000);
        if (freq) 
                freq--;
 
@@ -2532,8 +2532,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
                return -EIO;
 
        /* check, if we can restrict PCI DMA transfers to 28 bits */
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(28)) < 0 ||
-           dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(28)) < 0) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(28))) {
                dev_err(card->dev,
                        "architecture does not support 28bit PCI busmaster DMA\n");
                pci_disable_device(pci);
index cea53a8..6d90293 100644 (file)
@@ -469,6 +469,7 @@ struct hdsp {
        unsigned char         qs_out_channels;
        unsigned char         ds_out_channels;
        unsigned char         ss_out_channels;
+       u32                   io_loopback;          /* output loopback channel states*/
 
        struct snd_dma_buffer capture_dma_buf;
        struct snd_dma_buffer playback_dma_buf;
@@ -3253,6 +3254,60 @@ static const struct snd_kcontrol_new snd_hdsp_96xx_aeb =
                        HDSP_AnalogExtensionBoard);
 static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
 
+
+static bool hdsp_loopback_get(struct hdsp *const hdsp, const u8 channel)
+{
+       return hdsp->io_loopback & (1 << channel);
+}
+
+static int hdsp_loopback_set(struct hdsp *const hdsp, const u8 channel, const bool enable)
+{
+       if (hdsp_loopback_get(hdsp, channel) == enable)
+               return 0;
+
+       hdsp->io_loopback ^= (1 << channel);
+
+       hdsp_write(hdsp, HDSP_inputEnable + (4 * (hdsp->max_channels + channel)), enable);
+
+       return 1;
+}
+
+static int snd_hdsp_loopback_get(struct snd_kcontrol *const kcontrol,
+                                struct snd_ctl_elem_value *const ucontrol)
+{
+       struct hdsp *const hdsp = snd_kcontrol_chip(kcontrol);
+       const u8 channel = snd_ctl_get_ioff(kcontrol, &ucontrol->id);
+
+       if (channel >= hdsp->max_channels)
+               return -ENOENT;
+
+       ucontrol->value.integer.value[0] = hdsp_loopback_get(hdsp, channel);
+
+       return 0;
+}
+
+static int snd_hdsp_loopback_put(struct snd_kcontrol *const kcontrol,
+                                struct snd_ctl_elem_value *const ucontrol)
+{
+       struct hdsp *const hdsp = snd_kcontrol_chip(kcontrol);
+       const u8 channel = snd_ctl_get_ioff(kcontrol, &ucontrol->id);
+       const bool enable = ucontrol->value.integer.value[0] & 1;
+
+       if (channel >= hdsp->max_channels)
+               return -ENOENT;
+
+       return hdsp_loopback_set(hdsp, channel, enable);
+}
+
+static struct snd_kcontrol_new snd_hdsp_loopback_control = {
+       .iface = SNDRV_CTL_ELEM_IFACE_HWDEP,
+       .name = "Output Loopback",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+       .info = snd_ctl_boolean_mono_info,
+       .get = snd_hdsp_loopback_get,
+       .put = snd_hdsp_loopback_put
+};
+
 static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
 {
        unsigned int idx;
@@ -3297,6 +3352,17 @@ static int snd_hdsp_create_controls(struct snd_card *card, struct hdsp *hdsp)
                }
        }
 
+       /* Output loopback controls for H9632 cards */
+       if (hdsp->io_type == H9632) {
+               snd_hdsp_loopback_control.count = hdsp->max_channels;
+               kctl = snd_ctl_new1(&snd_hdsp_loopback_control, hdsp);
+               if (kctl == NULL)
+                       return -ENOMEM;
+               err = snd_ctl_add(card, kctl);
+               if (err < 0)
+                       return err;
+       }
+
        /* AEB control for H96xx card */
        if (hdsp->io_type == H9632 || hdsp->io_type == H9652) {
                if ((err = snd_ctl_add(card, kctl = snd_ctl_new1(&snd_hdsp_96xx_aeb, hdsp))) < 0)
@@ -4956,7 +5022,7 @@ static int snd_hdsp_enable_io (struct hdsp *hdsp)
 
 static void snd_hdsp_initialize_channels(struct hdsp *hdsp)
 {
-       int status, aebi_channels, aebo_channels;
+       int status, aebi_channels, aebo_channels, i;
 
        switch (hdsp->io_type) {
        case Digiface:
@@ -4983,6 +5049,12 @@ static void snd_hdsp_initialize_channels(struct hdsp *hdsp)
                hdsp->ss_out_channels = H9632_SS_CHANNELS+aebo_channels;
                hdsp->ds_out_channels = H9632_DS_CHANNELS+aebo_channels;
                hdsp->qs_out_channels = H9632_QS_CHANNELS+aebo_channels;
+               /* Disable loopback of output channels, as the set function
+                * only sets on a change we fake all bits (channels) as enabled.
+                */
+               hdsp->io_loopback = 0xffffffff;
+               for (i = 0; i < hdsp->max_channels; ++i)
+                       hdsp_loopback_set(hdsp, i, false);
                break;
 
        case Multiface:
index 04e878a..b667115 100644 (file)
@@ -6329,7 +6329,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
                memset(&hdspm_version, 0, sizeof(hdspm_version));
 
                hdspm_version.card_type = hdspm->io_type;
-               strlcpy(hdspm_version.cardname, hdspm->card_name,
+               strscpy(hdspm_version.cardname, hdspm->card_name,
                                sizeof(hdspm_version.cardname));
                hdspm_version.serial = hdspm->serial;
                hdspm_version.firmware_rev = hdspm->firmware_rev;
index 7bf6059..8ffa2f5 100644 (file)
@@ -363,7 +363,7 @@ static u32 sis_rate_to_delta(unsigned int rate)
        else if (rate == 48000)
                delta = 0x1000;
        else
-               delta = (((rate << 12) + 24000) / 48000) & 0x0000ffff;
+               delta = DIV_ROUND_CLOSEST(rate << 12, 48000) & 0x0000ffff;
        return delta;
 }
 
index ecdd54d..26fd1d0 100644 (file)
@@ -570,7 +570,7 @@ static void snd_sonicvibes_set_dac_rate(struct sonicvibes * sonic, unsigned int
        unsigned int div;
        unsigned long flags;
 
-       div = (rate * 65536 + SV_FULLRATE / 2) / SV_FULLRATE;
+       div = DIV_ROUND_CLOSEST(rate * 65536, SV_FULLRATE);
        if (div > 65535)
                div = 65535;
        spin_lock_irqsave(&sonic->reg_lock, flags);
@@ -1230,8 +1230,7 @@ static int snd_sonicvibes_create(struct snd_card *card,
        if ((err = pci_enable_device(pci)) < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 24 bits */
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(24)) < 0 ||
-           dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(24)) < 0) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(24))) {
                dev_err(card->dev,
                        "architecture does not support 24bit PCI busmaster DMA\n");
                pci_disable_device(pci);
index 6e50376..2014514 100644 (file)
@@ -678,7 +678,7 @@ static unsigned int snd_trident_convert_rate(unsigned int rate)
        else if (rate == 48000)
                delta = 0x1000;
        else
-               delta = (((rate << 12) + 24000) / 48000) & 0x0000ffff;
+               delta = DIV_ROUND_CLOSEST(rate << 12, 48000) & 0x0000ffff;
        return delta;
 }
 
@@ -1034,7 +1034,7 @@ static int snd_trident_capture_prepare(struct snd_pcm_substream *substream)
        ESO_bytes++;
 
        // Set channel sample rate, 4.12 format
-       val = (((unsigned int) 48000L << 12) + (runtime->rate/2)) / runtime->rate;
+       val = DIV_ROUND_CLOSEST(48000U << 12, runtime->rate);
        outw(val, TRID_REG(trident, T4D_SBDELTA_DELTA_R));
 
        // Set channel interrupt blk length
@@ -3497,8 +3497,7 @@ int snd_trident_create(struct snd_card *card,
        if ((err = pci_enable_device(pci)) < 0)
                return err;
        /* check, if we can restrict PCI DMA transfers to 30 bits */
-       if (dma_set_mask(&pci->dev, DMA_BIT_MASK(30)) < 0 ||
-           dma_set_coherent_mask(&pci->dev, DMA_BIT_MASK(30)) < 0) {
+       if (dma_set_mask_and_coherent(&pci->dev, DMA_BIT_MASK(30))) {
                dev_err(card->dev,
                        "architecture does not support 30bit PCI busmaster DMA\n");
                pci_disable_device(pci);
index 9554a0c..a6c1905 100644 (file)
@@ -49,7 +49,7 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter)
                return -EINVAL; /* ignored */
 
        memset(&info, 0, sizeof(struct i2c_board_info));
-       strlcpy(info.type, "keywest", I2C_NAME_SIZE);
+       strscpy(info.type, "keywest", I2C_NAME_SIZE);
        info.addr = keywest_ctx->addr;
        client = i2c_new_client_device(adapter, &info);
        if (IS_ERR(client))
index daa58b5..cad1cd1 100644 (file)
@@ -1707,7 +1707,7 @@ int q6afe_vote_lpass_core_hw(struct device *dev, uint32_t hw_block_id,
        pkt->hdr.token = hw_block_id;
        pkt->hdr.opcode = AFE_CMD_REMOTE_LPASS_CORE_HW_VOTE_REQUEST;
        vote_cfg->hw_block_id = hw_block_id;
-       strlcpy(vote_cfg->client_name, client_name,
+       strscpy(vote_cfg->client_name, client_name,
                        sizeof(vote_cfg->client_name));
 
        ret = afe_apr_send_pkt(afe, pkt, NULL,
index c405bf3..1029d8d 100644 (file)
@@ -1472,7 +1472,7 @@ static int rsnd_kctrl_info(struct snd_kcontrol *kctrl,
                uinfo->value.enumerated.items = cfg->max;
                if (uinfo->value.enumerated.item >= cfg->max)
                        uinfo->value.enumerated.item = cfg->max - 1;
-               strlcpy(uinfo->value.enumerated.name,
+               strscpy(uinfo->value.enumerated.name,
                        cfg->texts[uinfo->value.enumerated.item],
                        sizeof(uinfo->value.enumerated.name));
        } else {
index 789148e..30025d3 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <linux/io.h>
 #include <sound/hdaudio.h>
+#include <sound/hda_i915.h>
 #include "../sof-priv.h"
 #include "hda.h"
 
 #define sof_hda_ext_ops        NULL
 #endif
 
+#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
+static void sof_hda_bus_link_power(struct hdac_device *codec, bool enable)
+{
+       struct hdac_bus *bus = codec->bus;
+       bool oldstate = test_bit(codec->addr, &bus->codec_powered);
+
+       snd_hdac_ext_bus_link_power(codec, enable);
+
+       if (enable == oldstate)
+               return;
+
+       /*
+        * Both codec driver and controller can hold references to
+        * display power. To avoid unnecessary power-up/down cycles,
+        * controller doesn't immediately release its reference.
+        *
+        * If the codec driver powers down the link, release
+        * the controller reference as well.
+        */
+       if (codec->addr == HDA_IDISP_ADDR && !enable)
+               snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
+}
+
+static const struct hdac_bus_ops bus_core_ops = {
+       .command = snd_hdac_bus_send_cmd,
+       .get_response = snd_hdac_bus_get_response,
+       .link_power = sof_hda_bus_link_power,
+};
+#endif
+
 /*
  * This can be used for both with/without hda link support.
  */
 void sof_hda_bus_init(struct hdac_bus *bus, struct device *dev)
 {
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
-       snd_hdac_ext_bus_init(bus, dev, NULL, sof_hda_ext_ops);
+       snd_hdac_ext_bus_init(bus, dev, &bus_core_ops, sof_hda_ext_ops);
 #else /* CONFIG_SND_SOC_SOF_HDA */
        memset(bus, 0, sizeof(*bus));
        bus->dev = dev;
index d979411..d1c38c3 100644 (file)
 #define SSP_SET_SFRM_SLAVE     BIT(24)
 #define SSP_SET_SLAVE          (SSP_SET_SCLK_SLAVE | SSP_SET_SFRM_SLAVE)
 
-#define HDA_IDISP_CODEC(x) ((x) & BIT(2))
+#define HDA_IDISP_ADDR         2
+#define HDA_IDISP_CODEC(x) ((x) & BIT(HDA_IDISP_ADDR))
 
 struct sof_intel_dsp_bdl {
        __le32 addr_l;
index 010976d..cd4a0bc 100644 (file)
@@ -300,7 +300,7 @@ static int bcd2000_init_midi(struct bcd2000 *bcd2k)
        if (ret < 0)
                return ret;
 
-       strlcpy(rmidi->name, bcd2k->card->shortname, sizeof(rmidi->name));
+       strscpy(rmidi->name, bcd2k->card->shortname, sizeof(rmidi->name));
 
        rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX;
        rmidi->private_data = bcd2k;
index 3b6bb2c..4981753 100644 (file)
@@ -804,7 +804,7 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev)
        }
 
        cdev->pcm->private_data = cdev;
-       strlcpy(cdev->pcm->name, cdev->product_name, sizeof(cdev->pcm->name));
+       strscpy(cdev->pcm->name, cdev->product_name, sizeof(cdev->pcm->name));
 
        memset(cdev->sub_playback, 0, sizeof(cdev->sub_playback));
        memset(cdev->sub_capture, 0, sizeof(cdev->sub_capture));
index 2af3b7e..e03481c 100644 (file)
@@ -477,9 +477,9 @@ static int init_card(struct snd_usb_caiaqdev *cdev)
        usb_string(usb_dev, usb_dev->descriptor.iProduct,
                   cdev->product_name, CAIAQ_USB_STR_LEN);
 
-       strlcpy(card->driver, MODNAME, sizeof(card->driver));
-       strlcpy(card->shortname, cdev->product_name, sizeof(card->shortname));
-       strlcpy(card->mixername, cdev->product_name, sizeof(card->mixername));
+       strscpy(card->driver, MODNAME, sizeof(card->driver));
+       strscpy(card->shortname, cdev->product_name, sizeof(card->shortname));
+       strscpy(card->mixername, cdev->product_name, sizeof(card->mixername));
 
        /* if the id was not passed as module option, fill it with a shortened
         * version of the product string which does not contain any
index 512fbb3..c656d01 100644 (file)
@@ -125,7 +125,7 @@ int snd_usb_caiaq_midi_init(struct snd_usb_caiaqdev *device)
        if (ret < 0)
                return ret;
 
-       strlcpy(rmidi->name, device->product_name, sizeof(rmidi->name));
+       strscpy(rmidi->name, device->product_name, sizeof(rmidi->name));
 
        rmidi->info_flags = SNDRV_RAWMIDI_INFO_DUPLEX;
        rmidi->private_data = device;
index e08fbf8..85ed850 100644 (file)
@@ -472,7 +472,7 @@ static void usb_audio_make_shortname(struct usb_device *dev,
        else if (quirk && quirk->product_name)
                s = quirk->product_name;
        if (s && *s) {
-               strlcpy(card->shortname, s, sizeof(card->shortname));
+               strscpy(card->shortname, s, sizeof(card->shortname));
                return;
        }
 
@@ -504,7 +504,7 @@ static void usb_audio_make_longname(struct usb_device *dev,
        if (preset && preset->profile_name)
                s = preset->profile_name;
        if (s && *s) {
-               strlcpy(card->longname, s, sizeof(card->longname));
+               strscpy(card->longname, s, sizeof(card->longname));
                return;
        }
 
@@ -512,18 +512,17 @@ static void usb_audio_make_longname(struct usb_device *dev,
                s = preset->vendor_name;
        else if (quirk && quirk->vendor_name)
                s = quirk->vendor_name;
+       *card->longname = 0;
        if (s && *s) {
-               len = strlcpy(card->longname, s, sizeof(card->longname));
+               strscpy(card->longname, s, sizeof(card->longname));
        } else {
                /* retrieve the vendor and device strings as longname */
                if (dev->descriptor.iManufacturer)
-                       len = usb_string(dev, dev->descriptor.iManufacturer,
-                                        card->longname, sizeof(card->longname));
-               else
-                       len = 0;
+                       usb_string(dev, dev->descriptor.iManufacturer,
+                                  card->longname, sizeof(card->longname));
                /* we don't really care if there isn't any vendor string */
        }
-       if (len > 0) {
+       if (*card->longname) {
                strim(card->longname);
                if (*card->longname)
                        strlcat(card->longname, " ", sizeof(card->longname));
index 37091b1..a741e7d 100644 (file)
@@ -71,7 +71,7 @@ struct snd_usb_endpoint {
        unsigned char altsetting;       /* corresponding alternate setting */
        unsigned char ep_idx;           /* endpoint array index */
 
-       unsigned long flags;    /* running bit flags */
+       atomic_t state;         /* running state */
 
        void (*prepare_data_urb) (struct snd_usb_substream *subs,
                                  struct urb *urb);
index dc68ed6..8243652 100644 (file)
@@ -298,6 +298,11 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
        if (selector) {
                int ret, i, cur;
 
+               if (selector->bNrInPins == 1) {
+                       ret = 1;
+                       goto find_source;
+               }
+
                /* the entity ID we are looking for is a selector.
                 * find out what it currently selects */
                ret = uac_clock_selector_get_val(chip, selector->bClockID);
@@ -314,6 +319,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
                        return -EINVAL;
                }
 
+       find_source:
                cur = ret;
                ret = __uac_clock_find_source(chip, fmt,
                                              selector->baCSourceID[ret - 1],
index 8e56882..102d535 100644 (file)
 #include "clock.h"
 #include "quirks.h"
 
-#define EP_FLAG_RUNNING                1
-#define EP_FLAG_STOPPING       2
+enum {
+       EP_STATE_STOPPED,
+       EP_STATE_RUNNING,
+       EP_STATE_STOPPING,
+};
 
 /* interface refcounting */
 struct snd_usb_iface_ref {
@@ -115,6 +118,16 @@ static const char *usb_error_string(int err)
        }
 }
 
+static inline bool ep_state_running(struct snd_usb_endpoint *ep)
+{
+       return atomic_read(&ep->state) == EP_STATE_RUNNING;
+}
+
+static inline bool ep_state_update(struct snd_usb_endpoint *ep, int old, int new)
+{
+       return atomic_cmpxchg(&ep->state, old, new) == old;
+}
+
 /**
  * snd_usb_endpoint_implicit_feedback_sink: Report endpoint usage type
  *
@@ -393,7 +406,7 @@ next_packet_fifo_dequeue(struct snd_usb_endpoint *ep)
  */
 static void queue_pending_output_urbs(struct snd_usb_endpoint *ep)
 {
-       while (test_bit(EP_FLAG_RUNNING, &ep->flags)) {
+       while (ep_state_running(ep)) {
 
                unsigned long flags;
                struct snd_usb_packet_info *packet;
@@ -454,13 +467,13 @@ static void snd_complete_urb(struct urb *urb)
        if (unlikely(atomic_read(&ep->chip->shutdown)))
                goto exit_clear;
 
-       if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
+       if (unlikely(!ep_state_running(ep)))
                goto exit_clear;
 
        if (usb_pipeout(ep->pipe)) {
                retire_outbound_urb(ep, ctx);
                /* can be stopped during retire callback */
-               if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
+               if (unlikely(!ep_state_running(ep)))
                        goto exit_clear;
 
                if (snd_usb_endpoint_implicit_feedback_sink(ep)) {
@@ -474,12 +487,12 @@ static void snd_complete_urb(struct urb *urb)
 
                prepare_outbound_urb(ep, ctx);
                /* can be stopped during prepare callback */
-               if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
+               if (unlikely(!ep_state_running(ep)))
                        goto exit_clear;
        } else {
                retire_inbound_urb(ep, ctx);
                /* can be stopped during retire callback */
-               if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
+               if (unlikely(!ep_state_running(ep)))
                        goto exit_clear;
 
                prepare_inbound_urb(ep, ctx);
@@ -835,7 +848,7 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
        unsigned long end_time = jiffies + msecs_to_jiffies(1000);
        int alive;
 
-       if (!test_bit(EP_FLAG_STOPPING, &ep->flags))
+       if (atomic_read(&ep->state) != EP_STATE_STOPPING)
                return 0;
 
        do {
@@ -850,10 +863,11 @@ static int wait_clear_urbs(struct snd_usb_endpoint *ep)
                usb_audio_err(ep->chip,
                        "timeout: still %d active urbs on EP #%x\n",
                        alive, ep->ep_num);
-       clear_bit(EP_FLAG_STOPPING, &ep->flags);
 
-       ep->sync_sink = NULL;
-       snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL);
+       if (ep_state_update(ep, EP_STATE_STOPPING, EP_STATE_STOPPED)) {
+               ep->sync_sink = NULL;
+               snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL);
+       }
 
        return 0;
 }
@@ -868,26 +882,20 @@ void snd_usb_endpoint_sync_pending_stop(struct snd_usb_endpoint *ep)
 }
 
 /*
- * Stop and unlink active urbs.
+ * Stop active urbs
  *
- * This function checks and clears EP_FLAG_RUNNING state.
- * When @wait_sync is set, it waits until all pending URBs are killed.
+ * This function moves the EP to STOPPING state if it's being RUNNING.
  */
-static int stop_and_unlink_urbs(struct snd_usb_endpoint *ep, bool force,
-                               bool wait_sync)
+static int stop_urbs(struct snd_usb_endpoint *ep, bool force)
 {
        unsigned int i;
 
-       if (!force && atomic_read(&ep->chip->shutdown)) /* to be sure... */
-               return -EBADFD;
-
-       if (atomic_read(&ep->running))
+       if (!force && atomic_read(&ep->running))
                return -EBUSY;
 
-       if (!test_and_clear_bit(EP_FLAG_RUNNING, &ep->flags))
-               goto out;
+       if (!ep_state_update(ep, EP_STATE_RUNNING, EP_STATE_STOPPING))
+               return 0;
 
-       set_bit(EP_FLAG_STOPPING, &ep->flags);
        INIT_LIST_HEAD(&ep->ready_playback_urbs);
        ep->next_packet_head = 0;
        ep->next_packet_queued = 0;
@@ -901,24 +909,25 @@ static int stop_and_unlink_urbs(struct snd_usb_endpoint *ep, bool force,
                }
        }
 
- out:
-       if (wait_sync)
-               return wait_clear_urbs(ep);
        return 0;
 }
 
 /*
  * release an endpoint's urbs
  */
-static void release_urbs(struct snd_usb_endpoint *ep, int force)
+static int release_urbs(struct snd_usb_endpoint *ep, bool force)
 {
-       int i;
+       int i, err;
 
        /* route incoming urbs to nirvana */
        snd_usb_endpoint_set_callback(ep, NULL, NULL, NULL);
 
-       /* stop urbs */
-       stop_and_unlink_urbs(ep, force, true);
+       /* stop and unlink urbs */
+       err = stop_urbs(ep, force);
+       if (err)
+               return err;
+
+       wait_clear_urbs(ep);
 
        for (i = 0; i < ep->nurbs; i++)
                release_urb_ctx(&ep->urb[i]);
@@ -928,6 +937,7 @@ static void release_urbs(struct snd_usb_endpoint *ep, int force)
 
        ep->syncbuf = NULL;
        ep->nurbs = 0;
+       return 0;
 }
 
 /*
@@ -1118,7 +1128,7 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep)
        return 0;
 
 out_of_memory:
-       release_urbs(ep, 0);
+       release_urbs(ep, false);
        return -ENOMEM;
 }
 
@@ -1162,7 +1172,7 @@ static int sync_ep_set_params(struct snd_usb_endpoint *ep)
        return 0;
 
 out_of_memory:
-       release_urbs(ep, 0);
+       release_urbs(ep, false);
        return -ENOMEM;
 }
 
@@ -1180,7 +1190,9 @@ static int snd_usb_endpoint_set_params(struct snd_usb_audio *chip,
        int err;
 
        /* release old buffers, if any */
-       release_urbs(ep, 0);
+       err = release_urbs(ep, false);
+       if (err < 0)
+               return err;
 
        ep->datainterval = fmt->datainterval;
        ep->maxpacksize = fmt->maxpacksize;
@@ -1360,7 +1372,8 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
         * from that context.
         */
 
-       set_bit(EP_FLAG_RUNNING, &ep->flags);
+       if (!ep_state_update(ep, EP_STATE_STOPPED, EP_STATE_RUNNING))
+               goto __error;
 
        if (snd_usb_endpoint_implicit_feedback_sink(ep)) {
                for (i = 0; i < ep->nurbs; i++) {
@@ -1433,7 +1446,7 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
                WRITE_ONCE(ep->sync_source->sync_sink, NULL);
 
        if (!atomic_dec_return(&ep->running))
-               stop_and_unlink_urbs(ep, false, false);
+               stop_urbs(ep, false);
 }
 
 /**
@@ -1446,12 +1459,12 @@ void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep)
  */
 void snd_usb_endpoint_release(struct snd_usb_endpoint *ep)
 {
-       release_urbs(ep, 1);
+       release_urbs(ep, true);
 }
 
 /**
  * snd_usb_endpoint_free_all: Free the resources of an snd_usb_endpoint
- * @card: The chip
+ * @chip: The chip
  *
  * This free all endpoints and those resources
  */
index b2d9623..c282418 100644 (file)
@@ -80,12 +80,12 @@ static int hiface_chip_create(struct usb_interface *intf,
                return ret;
        }
 
-       strlcpy(card->driver, DRIVER_NAME, sizeof(card->driver));
+       strscpy(card->driver, DRIVER_NAME, sizeof(card->driver));
 
        if (quirk && quirk->device_name)
-               strlcpy(card->shortname, quirk->device_name, sizeof(card->shortname));
+               strscpy(card->shortname, quirk->device_name, sizeof(card->shortname));
        else
-               strlcpy(card->shortname, "M2Tech generic audio", sizeof(card->shortname));
+               strscpy(card->shortname, "M2Tech generic audio", sizeof(card->shortname));
 
        strlcat(card->longname, card->shortname, sizeof(card->longname));
        len = strlcat(card->longname, " at ", sizeof(card->longname));
index d942179..71f17f0 100644 (file)
@@ -594,7 +594,7 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq)
        pcm->private_data = rt;
        pcm->private_free = hiface_pcm_free;
 
-       strlcpy(pcm->name, "USB-SPDIF Audio", sizeof(pcm->name));
+       strscpy(pcm->name, "USB-SPDIF Audio", sizeof(pcm->name));
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops);
        snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
                                       NULL, 0, 0);
index 521cc84..11a85e6 100644 (file)
@@ -73,6 +73,7 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
        /* No quirk for playback but with capture quirk (see below) */
        IMPLICIT_FB_SKIP_DEV(0x0582, 0x0130),   /* BOSS BR-80 */
        IMPLICIT_FB_SKIP_DEV(0x0582, 0x0171),   /* BOSS RC-505 */
+       IMPLICIT_FB_SKIP_DEV(0x0582, 0x0185),   /* BOSS GP-10 */
        IMPLICIT_FB_SKIP_DEV(0x0582, 0x0189),   /* BOSS GT-100v2 */
        IMPLICIT_FB_SKIP_DEV(0x0582, 0x01d6),   /* BOSS GT-1 */
        IMPLICIT_FB_SKIP_DEV(0x0582, 0x01d8),   /* BOSS Katana */
@@ -86,6 +87,7 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
 static const struct snd_usb_implicit_fb_match capture_implicit_fb_quirks[] = {
        IMPLICIT_FB_FIXED_DEV(0x0582, 0x0130, 0x0d, 0x01), /* BOSS BR-80 */
        IMPLICIT_FB_FIXED_DEV(0x0582, 0x0171, 0x0d, 0x01), /* BOSS RC-505 */
+       IMPLICIT_FB_FIXED_DEV(0x0582, 0x0185, 0x0d, 0x01), /* BOSS GP-10 */
        IMPLICIT_FB_FIXED_DEV(0x0582, 0x0189, 0x0d, 0x01), /* BOSS GT-100v2 */
        IMPLICIT_FB_FIXED_DEV(0x0582, 0x01d6, 0x0d, 0x01), /* BOSS GT-1 */
        IMPLICIT_FB_FIXED_DEV(0x0582, 0x01d8, 0x0d, 0x01), /* BOSS Katana */
@@ -302,7 +304,8 @@ static int audioformat_implicit_fb_quirk(struct snd_usb_audio *chip,
        /* Pioneer devices with vendor spec class */
        if (attr == USB_ENDPOINT_SYNC_ASYNC &&
            alts->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC &&
-           USB_ID_VENDOR(chip->usb_id) == 0x2b73 /* Pioneer */) {
+           (USB_ID_VENDOR(chip->usb_id) == 0x2b73 || /* Pioneer */
+            USB_ID_VENDOR(chip->usb_id) == 0x08e4    /* Pioneer */)) {
                if (skip_pioneer_sync_ep(chip, fmt, alts))
                        return 1;
        }
index 12b15ed..b1c78db 100644 (file)
@@ -115,11 +115,14 @@ find_map(const struct usbmix_name_map *p, int unitid, int control)
 static int
 check_mapped_name(const struct usbmix_name_map *p, char *buf, int buflen)
 {
+       int len;
+
        if (!p || !p->name)
                return 0;
 
        buflen--;
-       return strlcpy(buf, p->name, buflen);
+       len = strscpy(buf, p->name, buflen);
+       return len < 0 ? buflen : len;
 }
 
 /* ignore the error value if ignore_ctl_error flag is set */
@@ -151,12 +154,15 @@ static int check_mapped_selector_name(struct mixer_build *state, int unitid,
                                      int index, char *buf, int buflen)
 {
        const struct usbmix_selector_map *p;
+       int len;
 
        if (!state->selector_map)
                return 0;
        for (p = state->selector_map; p->id; p++) {
-               if (p->id == unitid && index < p->count)
-                       return strlcpy(buf, p->names[index], buflen);
+               if (p->id == unitid && index < p->count) {
+                       len = strscpy(buf, p->names[index], buflen);
+                       return len < 0 ? buflen : len;
+               }
        }
        return 0;
 }
@@ -254,7 +260,7 @@ static int get_relative_value(struct usb_mixer_elem_info *cval, int val)
        if (val < cval->min)
                return 0;
        else if (val >= cval->max)
-               return (cval->max - cval->min + cval->res - 1) / cval->res;
+               return DIV_ROUND_UP(cval->max - cval->min, cval->res);
        else
                return (val - cval->min) / cval->res;
 }
@@ -1232,7 +1238,7 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
                                  (cval->control << 8) | minchn,
                                  &cval->res) < 0) {
                        cval->res = 1;
-               } else {
+               } else if (cval->head.mixer->protocol == UAC_VERSION_1) {
                        int last_valid_res = cval->res;
 
                        while (cval->res > 1) {
@@ -1338,7 +1344,7 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol,
                }
                uinfo->value.integer.min = 0;
                uinfo->value.integer.max =
-                       (cval->max - cval->min + cval->res - 1) / cval->res;
+                       DIV_ROUND_UP(cval->max - cval->min, cval->res);
        }
        return 0;
 }
@@ -1556,7 +1562,7 @@ static void check_no_speaker_on_headset(struct snd_kcontrol *kctl,
        if (!found)
                return;
 
-       strlcpy(kctl->id.name, "Headphone", sizeof(kctl->id.name));
+       strscpy(kctl->id.name, "Headphone", sizeof(kctl->id.name));
 }
 
 static const struct usb_feature_control_info *get_feature_control_info(int control)
@@ -1691,7 +1697,7 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer,
                break;
        default:
                if (!len)
-                       strlcpy(kctl->id.name, audio_feature_info[control-1].name,
+                       strscpy(kctl->id.name, audio_feature_info[control-1].name,
                                sizeof(kctl->id.name));
                break;
        }
@@ -1770,7 +1776,7 @@ static void get_connector_control_name(struct usb_mixer_interface *mixer,
        int name_len = get_term_name(mixer->chip, term, name, name_size, 0);
 
        if (name_len == 0)
-               strlcpy(name, "Unknown", name_size);
+               strscpy(name, "Unknown", name_size);
 
        /*
         *  sound/core/ctljack.c has a convention of naming jack controls
@@ -2490,7 +2496,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
                if (check_mapped_name(map, kctl->id.name, sizeof(kctl->id.name))) {
                        /* nothing */ ;
                } else if (info->name) {
-                       strlcpy(kctl->id.name, info->name, sizeof(kctl->id.name));
+                       strscpy(kctl->id.name, info->name, sizeof(kctl->id.name));
                } else {
                        if (extension_unit)
                                nameid = uac_extension_unit_iExtension(desc, state->mixer->protocol);
@@ -2503,7 +2509,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
                                                               kctl->id.name,
                                                               sizeof(kctl->id.name));
                        if (!len)
-                               strlcpy(kctl->id.name, name, sizeof(kctl->id.name));
+                               strscpy(kctl->id.name, name, sizeof(kctl->id.name));
                }
                append_ctl_name(kctl, " ");
                append_ctl_name(kctl, valinfo->suffix);
@@ -2743,7 +2749,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid,
                                    kctl->id.name, sizeof(kctl->id.name), 0);
                /* ... or use the fixed string "USB" as the last resort */
                if (!len)
-                       strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name));
+                       strscpy(kctl->id.name, "USB", sizeof(kctl->id.name));
 
                /* and add the proper suffix */
                if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR ||
index df036a3..08873d2 100644 (file)
@@ -2603,141 +2603,251 @@ static int snd_bbfpro_controls_create(struct usb_mixer_interface *mixer)
 }
 
 /*
- * Pioneer DJ DJM-250MK2 and maybe other DJM models
+ * Pioneer DJ DJM Mixers
  *
- * For playback, no duplicate mapping should be set.
- * There are three mixer stereo channels (CH1, CH2, AUX)
- * and three stereo sources (Playback 1-2, Playback 3-4, Playback 5-6).
- * Each channel should be mapped just once to one source.
- * If mapped multiple times, only one source will play on given channel
- * (sources are not mixed together).
+ * These devices generally have options for soft-switching the playback and
+ * capture sources in addition to the recording level. Although different
+ * devices have different configurations, there seems to be canonical values
+ * for specific capture/playback types:  See the definitions of these below.
  *
- * For recording, duplicate mapping is OK. We will get the same signal multiple times.
- *
- * Channels 7-8 are in both directions fixed to FX SEND / FX RETURN.
- *
- * See also notes in the quirks-table.h file.
+ * The wValue is masked with the stereo channel number. e.g. Setting Ch2 to
+ * capture phono would be 0x0203. Capture, playback and capture level have
+ * different wIndexes.
  */
 
-struct snd_pioneer_djm_option {
-       const u16 wIndex;
-       const u16 wValue;
+// Capture types
+#define SND_DJM_CAP_LINE       0x00
+#define SND_DJM_CAP_CDLINE     0x01
+#define SND_DJM_CAP_DIGITAL    0x02
+#define SND_DJM_CAP_PHONO      0x03
+#define SND_DJM_CAP_PFADER     0x06
+#define SND_DJM_CAP_XFADERA    0x07
+#define SND_DJM_CAP_XFADERB    0x08
+#define SND_DJM_CAP_MIC                0x09
+#define SND_DJM_CAP_AUX                0x0d
+#define SND_DJM_CAP_RECOUT     0x0a
+#define SND_DJM_CAP_NONE       0x0f
+#define SND_DJM_CAP_CH1PFADER  0x11
+#define SND_DJM_CAP_CH2PFADER  0x12
+#define SND_DJM_CAP_CH3PFADER  0x13
+#define SND_DJM_CAP_CH4PFADER  0x14
+
+// Playback types
+#define SND_DJM_PB_CH1         0x00
+#define SND_DJM_PB_CH2         0x01
+#define SND_DJM_PB_AUX         0x04
+
+#define SND_DJM_WINDEX_CAP     0x8002
+#define SND_DJM_WINDEX_CAPLVL  0x8003
+#define SND_DJM_WINDEX_PB      0x8016
+
+// kcontrol->private_value layout
+#define SND_DJM_VALUE_MASK     0x0000ffff
+#define SND_DJM_GROUP_MASK     0x00ff0000
+#define SND_DJM_DEVICE_MASK    0xff000000
+#define SND_DJM_GROUP_SHIFT    16
+#define SND_DJM_DEVICE_SHIFT   24
+
+// device table index
+#define SND_DJM_250MK2_IDX     0x0
+#define SND_DJM_750_IDX                0x1
+#define SND_DJM_900NXS2_IDX    0x2
+
+
+#define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \
+       .name = _name, \
+       .options = snd_djm_opts_##suffix, \
+       .noptions = ARRAY_SIZE(snd_djm_opts_##suffix), \
+       .default_value = _default_value, \
+       .wIndex = _windex }
+
+#define SND_DJM_DEVICE(suffix) { \
+       .controls = snd_djm_ctls_##suffix, \
+       .ncontrols = ARRAY_SIZE(snd_djm_ctls_##suffix) }
+
+
+struct snd_djm_device {
        const char *name;
+       const struct snd_djm_ctl *controls;
+       size_t ncontrols;
 };
 
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_level[] = {
-       { .name =  "-5 dB",                  .wValue = 0x0300, .wIndex = 0x8003 },
-       { .name = "-10 dB",                  .wValue = 0x0200, .wIndex = 0x8003 },
-       { .name = "-15 dB",                  .wValue = 0x0100, .wIndex = 0x8003 },
-       { .name = "-19 dB",                  .wValue = 0x0000, .wIndex = 0x8003 }
+struct snd_djm_ctl {
+       const char *name;
+       const u16 *options;
+       size_t noptions;
+       u16 default_value;
+       u16 wIndex;
 };
 
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch12[] = {
-       { .name =  "CH1 Control Tone PHONO", .wValue = 0x0103, .wIndex = 0x8002 },
-       { .name =  "CH1 Control Tone LINE",  .wValue = 0x0100, .wIndex = 0x8002 },
-       { .name =  "Post CH1 Fader",         .wValue = 0x0106, .wIndex = 0x8002 },
-       { .name =  "Cross Fader A",          .wValue = 0x0107, .wIndex = 0x8002 },
-       { .name =  "Cross Fader B",          .wValue = 0x0108, .wIndex = 0x8002 },
-       { .name =  "MIC",                    .wValue = 0x0109, .wIndex = 0x8002 },
-       { .name =  "AUX",                    .wValue = 0x010d, .wIndex = 0x8002 },
-       { .name =  "REC OUT",                .wValue = 0x010a, .wIndex = 0x8002 }
+static const char *snd_djm_get_label_caplevel(u16 wvalue)
+{
+       switch (wvalue) {
+       case 0x0000:    return "-19dB";
+       case 0x0100:    return "-15dB";
+       case 0x0200:    return "-10dB";
+       case 0x0300:    return "-5dB";
+       default:        return NULL;
+       }
 };
 
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch34[] = {
-       { .name =  "CH2 Control Tone PHONO", .wValue = 0x0203, .wIndex = 0x8002 },
-       { .name =  "CH2 Control Tone LINE",  .wValue = 0x0200, .wIndex = 0x8002 },
-       { .name =  "Post CH2 Fader",         .wValue = 0x0206, .wIndex = 0x8002 },
-       { .name =  "Cross Fader A",          .wValue = 0x0207, .wIndex = 0x8002 },
-       { .name =  "Cross Fader B",          .wValue = 0x0208, .wIndex = 0x8002 },
-       { .name =  "MIC",                    .wValue = 0x0209, .wIndex = 0x8002 },
-       { .name =  "AUX",                    .wValue = 0x020d, .wIndex = 0x8002 },
-       { .name =  "REC OUT",                .wValue = 0x020a, .wIndex = 0x8002 }
+static const char *snd_djm_get_label_cap(u16 wvalue)
+{
+       switch (wvalue & 0x00ff) {
+       case SND_DJM_CAP_LINE:          return "Control Tone LINE";
+       case SND_DJM_CAP_CDLINE:        return "Control Tone CD/LINE";
+       case SND_DJM_CAP_DIGITAL:       return "Control Tone DIGITAL";
+       case SND_DJM_CAP_PHONO:         return "Control Tone PHONO";
+       case SND_DJM_CAP_PFADER:        return "Post Fader";
+       case SND_DJM_CAP_XFADERA:       return "Cross Fader A";
+       case SND_DJM_CAP_XFADERB:       return "Cross Fader B";
+       case SND_DJM_CAP_MIC:           return "Mic";
+       case SND_DJM_CAP_RECOUT:        return "Rec Out";
+       case SND_DJM_CAP_AUX:           return "Aux";
+       case SND_DJM_CAP_NONE:          return "None";
+       case SND_DJM_CAP_CH1PFADER:     return "Post Fader Ch1";
+       case SND_DJM_CAP_CH2PFADER:     return "Post Fader Ch2";
+       case SND_DJM_CAP_CH3PFADER:     return "Post Fader Ch3";
+       case SND_DJM_CAP_CH4PFADER:     return "Post Fader Ch4";
+       default:                        return NULL;
+       }
 };
 
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_capture_ch56[] = {
-       { .name =  "REC OUT",                .wValue = 0x030a, .wIndex = 0x8002 },
-       { .name =  "Post CH1 Fader",         .wValue = 0x0311, .wIndex = 0x8002 },
-       { .name =  "Post CH2 Fader",         .wValue = 0x0312, .wIndex = 0x8002 },
-       { .name =  "Cross Fader A",          .wValue = 0x0307, .wIndex = 0x8002 },
-       { .name =  "Cross Fader B",          .wValue = 0x0308, .wIndex = 0x8002 },
-       { .name =  "MIC",                    .wValue = 0x0309, .wIndex = 0x8002 },
-       { .name =  "AUX",                    .wValue = 0x030d, .wIndex = 0x8002 }
+static const char *snd_djm_get_label_pb(u16 wvalue)
+{
+       switch (wvalue & 0x00ff) {
+       case SND_DJM_PB_CH1:    return "Ch1";
+       case SND_DJM_PB_CH2:    return "Ch2";
+       case SND_DJM_PB_AUX:    return "Aux";
+       default:                return NULL;
+       }
 };
 
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_12[] = {
-       { .name =  "CH1",                    .wValue = 0x0100, .wIndex = 0x8016 },
-       { .name =  "CH2",                    .wValue = 0x0101, .wIndex = 0x8016 },
-       { .name =  "AUX",                    .wValue = 0x0104, .wIndex = 0x8016 }
+static const char *snd_djm_get_label(u16 wvalue, u16 windex)
+{
+       switch (windex) {
+       case SND_DJM_WINDEX_CAPLVL:     return snd_djm_get_label_caplevel(wvalue);
+       case SND_DJM_WINDEX_CAP:        return snd_djm_get_label_cap(wvalue);
+       case SND_DJM_WINDEX_PB:         return snd_djm_get_label_pb(wvalue);
+       default:                        return NULL;
+       }
 };
 
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_34[] = {
-       { .name =  "CH1",                    .wValue = 0x0200, .wIndex = 0x8016 },
-       { .name =  "CH2",                    .wValue = 0x0201, .wIndex = 0x8016 },
-       { .name =  "AUX",                    .wValue = 0x0204, .wIndex = 0x8016 }
+
+// DJM-250MK2
+static const u16 snd_djm_opts_cap_level[] = {
+       0x0000, 0x0100, 0x0200, 0x0300 };
+
+static const u16 snd_djm_opts_250mk2_cap1[] = {
+       0x0103, 0x0100, 0x0106, 0x0107, 0x0108, 0x0109, 0x010d, 0x010a };
+
+static const u16 snd_djm_opts_250mk2_cap2[] = {
+       0x0203, 0x0200, 0x0206, 0x0207, 0x0208, 0x0209, 0x020d, 0x020a };
+
+static const u16 snd_djm_opts_250mk2_cap3[] = {
+       0x030a, 0x0311, 0x0312, 0x0307, 0x0308, 0x0309, 0x030d };
+
+static const u16 snd_djm_opts_250mk2_pb1[] = { 0x0100, 0x0101, 0x0104 };
+static const u16 snd_djm_opts_250mk2_pb2[] = { 0x0200, 0x0201, 0x0204 };
+static const u16 snd_djm_opts_250mk2_pb3[] = { 0x0300, 0x0301, 0x0304 };
+
+static const struct snd_djm_ctl snd_djm_ctls_250mk2[] = {
+       SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+       SND_DJM_CTL("Ch1 Input",   250mk2_cap1, 2, SND_DJM_WINDEX_CAP),
+       SND_DJM_CTL("Ch2 Input",   250mk2_cap2, 2, SND_DJM_WINDEX_CAP),
+       SND_DJM_CTL("Ch3 Input",   250mk2_cap3, 0, SND_DJM_WINDEX_CAP),
+       SND_DJM_CTL("Ch1 Output",   250mk2_pb1, 0, SND_DJM_WINDEX_PB),
+       SND_DJM_CTL("Ch2 Output",   250mk2_pb2, 1, SND_DJM_WINDEX_PB),
+       SND_DJM_CTL("Ch3 Output",   250mk2_pb3, 2, SND_DJM_WINDEX_PB)
 };
 
-static const struct snd_pioneer_djm_option snd_pioneer_djm_options_playback_56[] = {
-       { .name =  "CH1",                    .wValue = 0x0300, .wIndex = 0x8016 },
-       { .name =  "CH2",                    .wValue = 0x0301, .wIndex = 0x8016 },
-       { .name =  "AUX",                    .wValue = 0x0304, .wIndex = 0x8016 }
+
+// DJM-750
+static const u16 snd_djm_opts_750_cap1[] = {
+       0x0101, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a, 0x010f };
+static const u16 snd_djm_opts_750_cap2[] = {
+       0x0200, 0x0201, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a, 0x020f };
+static const u16 snd_djm_opts_750_cap3[] = {
+       0x0300, 0x0301, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a, 0x030f };
+static const u16 snd_djm_opts_750_cap4[] = {
+       0x0401, 0x0403, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040f };
+
+static const struct snd_djm_ctl snd_djm_ctls_750[] = {
+       SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+       SND_DJM_CTL("Ch1 Input",   750_cap1, 2, SND_DJM_WINDEX_CAP),
+       SND_DJM_CTL("Ch2 Input",   750_cap2, 2, SND_DJM_WINDEX_CAP),
+       SND_DJM_CTL("Ch3 Input",   750_cap3, 0, SND_DJM_WINDEX_CAP),
+       SND_DJM_CTL("Ch4 Input",   750_cap4, 0, SND_DJM_WINDEX_CAP)
 };
 
-struct snd_pioneer_djm_option_group {
-       const char *name;
-       const struct snd_pioneer_djm_option *options;
-       const size_t count;
-       const u16 default_value;
+
+// DJM-900NXS2
+static const u16 snd_djm_opts_900nxs2_cap1[] = {
+       0x0100, 0x0102, 0x0103, 0x0106, 0x0107, 0x0108, 0x0109, 0x010a };
+static const u16 snd_djm_opts_900nxs2_cap2[] = {
+       0x0200, 0x0202, 0x0203, 0x0206, 0x0207, 0x0208, 0x0209, 0x020a };
+static const u16 snd_djm_opts_900nxs2_cap3[] = {
+       0x0300, 0x0302, 0x0303, 0x0306, 0x0307, 0x0308, 0x0309, 0x030a };
+static const u16 snd_djm_opts_900nxs2_cap4[] = {
+       0x0400, 0x0402, 0x0403, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a };
+static const u16 snd_djm_opts_900nxs2_cap5[] = {
+       0x0507, 0x0508, 0x0509, 0x050a, 0x0511, 0x0512, 0x0513, 0x0514 };
+
+static const struct snd_djm_ctl snd_djm_ctls_900nxs2[] = {
+       SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+       SND_DJM_CTL("Ch1 Input",   900nxs2_cap1, 2, SND_DJM_WINDEX_CAP),
+       SND_DJM_CTL("Ch2 Input",   900nxs2_cap2, 2, SND_DJM_WINDEX_CAP),
+       SND_DJM_CTL("Ch3 Input",   900nxs2_cap3, 2, SND_DJM_WINDEX_CAP),
+       SND_DJM_CTL("Ch4 Input",   900nxs2_cap4, 2, SND_DJM_WINDEX_CAP),
+       SND_DJM_CTL("Ch5 Input",   900nxs2_cap5, 3, SND_DJM_WINDEX_CAP)
 };
 
-#define snd_pioneer_djm_option_group_item(_name, suffix, _default_value) { \
-       .name = _name, \
-       .options = snd_pioneer_djm_options_##suffix, \
-       .count = ARRAY_SIZE(snd_pioneer_djm_options_##suffix), \
-       .default_value = _default_value }
-
-static const struct snd_pioneer_djm_option_group snd_pioneer_djm_option_groups[] = {
-       snd_pioneer_djm_option_group_item("Master Capture Level Capture Switch", capture_level, 0),
-       snd_pioneer_djm_option_group_item("Capture 1-2 Capture Switch",          capture_ch12,  2),
-       snd_pioneer_djm_option_group_item("Capture 3-4 Capture Switch",          capture_ch34,  2),
-       snd_pioneer_djm_option_group_item("Capture 5-6 Capture Switch",          capture_ch56,  0),
-       snd_pioneer_djm_option_group_item("Playback 1-2 Playback Switch",        playback_12,   0),
-       snd_pioneer_djm_option_group_item("Playback 3-4 Playback Switch",        playback_34,   1),
-       snd_pioneer_djm_option_group_item("Playback 5-6 Playback Switch",        playback_56,   2)
+
+static const struct snd_djm_device snd_djm_devices[] = {
+       SND_DJM_DEVICE(250mk2),
+       SND_DJM_DEVICE(750),
+       SND_DJM_DEVICE(900nxs2)
 };
 
-// layout of the kcontrol->private_value:
-#define SND_PIONEER_DJM_VALUE_MASK 0x0000ffff
-#define SND_PIONEER_DJM_GROUP_MASK 0xffff0000
-#define SND_PIONEER_DJM_GROUP_SHIFT 16
 
-static int snd_pioneer_djm_controls_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *info)
+static int snd_djm_controls_info(struct snd_kcontrol *kctl,
+                               struct snd_ctl_elem_info *info)
 {
-       u16 group_index = kctl->private_value >> SND_PIONEER_DJM_GROUP_SHIFT;
-       size_t count;
+       unsigned long private_value = kctl->private_value;
+       u8 device_idx = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT;
+       u8 ctl_idx = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT;
+       const struct snd_djm_device *device = &snd_djm_devices[device_idx];
        const char *name;
-       const struct snd_pioneer_djm_option_group *group;
+       const struct snd_djm_ctl *ctl;
+       size_t noptions;
 
-       if (group_index >= ARRAY_SIZE(snd_pioneer_djm_option_groups))
+       if (ctl_idx >= device->ncontrols)
                return -EINVAL;
 
-       group = &snd_pioneer_djm_option_groups[group_index];
-       count = group->count;
-       if (info->value.enumerated.item >= count)
-               info->value.enumerated.item = count - 1;
-       name = group->options[info->value.enumerated.item].name;
-       strlcpy(info->value.enumerated.name, name, sizeof(info->value.enumerated.name));
+       ctl = &device->controls[ctl_idx];
+       noptions = ctl->noptions;
+       if (info->value.enumerated.item >= noptions)
+               info->value.enumerated.item = noptions - 1;
+
+       name = snd_djm_get_label(ctl->options[info->value.enumerated.item],
+                               ctl->wIndex);
+       if (!name)
+               return -EINVAL;
+
+       strscpy(info->value.enumerated.name, name, sizeof(info->value.enumerated.name));
        info->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
        info->count = 1;
-       info->value.enumerated.items = count;
+       info->value.enumerated.items = noptions;
        return 0;
 }
 
-static int snd_pioneer_djm_controls_update(struct usb_mixer_interface *mixer, u16 group, u16 value)
+static int snd_djm_controls_update(struct usb_mixer_interface *mixer,
+                               u8 device_idx, u8 group, u16 value)
 {
        int err;
+       const struct snd_djm_device *device = &snd_djm_devices[device_idx];
 
-       if (group >= ARRAY_SIZE(snd_pioneer_djm_option_groups)
-                       || value >= snd_pioneer_djm_option_groups[group].count)
+       if ((group >= device->ncontrols) || value >= device->controls[group].noptions)
                return -EINVAL;
 
        err = snd_usb_lock_shutdown(mixer->chip);
@@ -2748,63 +2858,76 @@ static int snd_pioneer_djm_controls_update(struct usb_mixer_interface *mixer, u1
                mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0),
                USB_REQ_SET_FEATURE,
                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-               snd_pioneer_djm_option_groups[group].options[value].wValue,
-               snd_pioneer_djm_option_groups[group].options[value].wIndex,
+               device->controls[group].options[value],
+               device->controls[group].wIndex,
                NULL, 0);
 
        snd_usb_unlock_shutdown(mixer->chip);
        return err;
 }
 
-static int snd_pioneer_djm_controls_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem)
+static int snd_djm_controls_get(struct snd_kcontrol *kctl,
+                               struct snd_ctl_elem_value *elem)
 {
-       elem->value.enumerated.item[0] = kctl->private_value & SND_PIONEER_DJM_VALUE_MASK;
+       elem->value.enumerated.item[0] = kctl->private_value & SND_DJM_VALUE_MASK;
        return 0;
 }
 
-static int snd_pioneer_djm_controls_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem)
+static int snd_djm_controls_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *elem)
 {
        struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
        struct usb_mixer_interface *mixer = list->mixer;
        unsigned long private_value = kctl->private_value;
-       u16 group = (private_value & SND_PIONEER_DJM_GROUP_MASK) >> SND_PIONEER_DJM_GROUP_SHIFT;
+
+       u8 device = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT;
+       u8 group = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT;
        u16 value = elem->value.enumerated.item[0];
 
-       kctl->private_value = (group << SND_PIONEER_DJM_GROUP_SHIFT) | value;
+       kctl->private_value = ((device << SND_DJM_DEVICE_SHIFT) |
+                             (group << SND_DJM_GROUP_SHIFT) |
+                             value);
 
-       return snd_pioneer_djm_controls_update(mixer, group, value);
+       return snd_djm_controls_update(mixer, device, group, value);
 }
 
-static int snd_pioneer_djm_controls_resume(struct usb_mixer_elem_list *list)
+static int snd_djm_controls_resume(struct usb_mixer_elem_list *list)
 {
        unsigned long private_value = list->kctl->private_value;
-       u16 group = (private_value & SND_PIONEER_DJM_GROUP_MASK) >> SND_PIONEER_DJM_GROUP_SHIFT;
-       u16 value = (private_value & SND_PIONEER_DJM_VALUE_MASK);
+       u8 device = (private_value & SND_DJM_DEVICE_MASK) >> SND_DJM_DEVICE_SHIFT;
+       u8 group = (private_value & SND_DJM_GROUP_MASK) >> SND_DJM_GROUP_SHIFT;
+       u16 value = (private_value & SND_DJM_VALUE_MASK);
 
-       return snd_pioneer_djm_controls_update(list->mixer, group, value);
+       return snd_djm_controls_update(list->mixer, device, group, value);
 }
 
-static int snd_pioneer_djm_controls_create(struct usb_mixer_interface *mixer)
+static int snd_djm_controls_create(struct usb_mixer_interface *mixer,
+               const u8 device_idx)
 {
        int err, i;
-       const struct snd_pioneer_djm_option_group *group;
+       u16 value;
+
+       const struct snd_djm_device *device = &snd_djm_devices[device_idx];
+
        struct snd_kcontrol_new knew = {
                .iface  = SNDRV_CTL_ELEM_IFACE_MIXER,
                .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
                .index = 0,
-               .info = snd_pioneer_djm_controls_info,
-               .get  = snd_pioneer_djm_controls_get,
-               .put  = snd_pioneer_djm_controls_put
+               .info = snd_djm_controls_info,
+               .get  = snd_djm_controls_get,
+               .put  = snd_djm_controls_put
        };
 
-       for (i = 0; i < ARRAY_SIZE(snd_pioneer_djm_option_groups); i++) {
-               group = &snd_pioneer_djm_option_groups[i];
-               knew.name = group->name;
-               knew.private_value = (i << SND_PIONEER_DJM_GROUP_SHIFT) | group->default_value;
-               err = snd_pioneer_djm_controls_update(mixer, i, group->default_value);
+       for (i = 0; i < device->ncontrols; i++) {
+               value = device->controls[i].default_value;
+               knew.name = device->controls[i].name;
+               knew.private_value = (
+                       (device_idx << SND_DJM_DEVICE_SHIFT) |
+                       (i << SND_DJM_GROUP_SHIFT) |
+                       value);
+               err = snd_djm_controls_update(mixer, device_idx, i, value);
                if (err)
                        return err;
-               err = add_single_ctl_with_resume(mixer, 0, snd_pioneer_djm_controls_resume,
+               err = add_single_ctl_with_resume(mixer, 0, snd_djm_controls_resume,
                                                 &knew, NULL);
                if (err)
                        return err;
@@ -2917,7 +3040,13 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
                err = snd_bbfpro_controls_create(mixer);
                break;
        case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */
-               err = snd_pioneer_djm_controls_create(mixer);
+               err = snd_djm_controls_create(mixer, SND_DJM_250MK2_IDX);
+               break;
+       case USB_ID(0x08e4, 0x017f): /* Pioneer DJ DJM-750 */
+               err = snd_djm_controls_create(mixer, SND_DJM_750_IDX);
+               break;
+       case USB_ID(0x2b73, 0x000a): /* Pioneer DJ DJM-900NXS2 */
+               err = snd_djm_controls_create(mixer, SND_DJM_900NXS2_IDX);
                break;
        }
 
index 49fcd25..691b954 100644 (file)
@@ -569,7 +569,7 @@ static int add_new_ctl(struct usb_mixer_interface *mixer,
        }
        kctl->private_free = snd_usb_mixer_elem_free;
 
-       strlcpy(kctl->id.name, name, sizeof(kctl->id.name));
+       strscpy(kctl->id.name, name, sizeof(kctl->id.name));
 
        err = snd_usb_mixer_add_control(&elem->head, kctl);
        if (err < 0)
index 4bbec56..560c2ad 100644 (file)
@@ -961,7 +961,7 @@ static int scarlett2_add_new_ctl(struct usb_mixer_interface *mixer,
        }
        kctl->private_free = snd_usb_mixer_elem_free;
 
-       strlcpy(kctl->id.name, name, sizeof(kctl->id.name));
+       strscpy(kctl->id.name, name, sizeof(kctl->id.name));
 
        err = snd_usb_mixer_add_control(&elem->head, kctl);
        if (err < 0)
index bd63a9c..b7b6f38 100644 (file)
@@ -1076,7 +1076,7 @@ static int add_new_ctl(struct usb_mixer_interface *mixer,
        else
                kctl->private_free = snd_usb_mixer_elem_free;
 
-       strlcpy(kctl->id.name, name, sizeof(kctl->id.name));
+       strscpy(kctl->id.name, name, sizeof(kctl->id.name));
 
        err = snd_usb_mixer_add_control(&elem->head, kctl);
        if (err < 0)
index 078bb4c..bf5a0f3 100644 (file)
@@ -270,10 +270,7 @@ static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream)
 {
        struct snd_usb_substream *subs = substream->runtime->private_data;
 
-       if (!snd_usb_lock_shutdown(subs->stream->chip)) {
-               sync_pending_stops(subs);
-               snd_usb_unlock_shutdown(subs->stream->chip);
-       }
+       sync_pending_stops(subs);
        return 0;
 }
 
@@ -1558,7 +1555,7 @@ void snd_usb_preallocate_buffer(struct snd_usb_substream *subs)
 {
        struct snd_pcm *pcm = subs->stream->pcm;
        struct snd_pcm_substream *s = pcm->streams[subs->direction].substream;
-       struct device *dev = subs->dev->bus->controller;
+       struct device *dev = subs->dev->bus->sysdev;
 
        if (snd_usb_use_vmalloc)
                snd_pcm_set_managed_buffer(s, SNDRV_DMA_TYPE_VMALLOC,
index c8a4bdf..1165a5a 100644 (file)
@@ -3757,6 +3757,123 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                }
        }
 },
+{
+       /*
+        * Pioneer DJ DJM-750
+        * 8 channels playback & 8 channels capture @ 44.1/48/96kHz S24LE
+        */
+       USB_DEVICE_VENDOR_SPEC(0x08e4, 0x017f),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 0,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x05,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC|
+                                           USB_ENDPOINT_SYNC_ASYNC,
+                                       .rates = SNDRV_PCM_RATE_44100|
+                                               SNDRV_PCM_RATE_48000|
+                                               SNDRV_PCM_RATE_96000,
+                                       .rate_min = 44100,
+                                       .rate_max = 96000,
+                                       .nr_rates = 3,
+                                       .rate_table = (unsigned int[]) { 44100, 48000, 96000 }
+                               }
+                       },
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8,
+                                       .iface = 0,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x86,
+                                       .ep_idx = 1,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC|
+                                               USB_ENDPOINT_SYNC_ASYNC|
+                                               USB_ENDPOINT_USAGE_IMPLICIT_FB,
+                                       .rates = SNDRV_PCM_RATE_44100|
+                                               SNDRV_PCM_RATE_48000|
+                                               SNDRV_PCM_RATE_96000,
+                                       .rate_min = 44100,
+                                       .rate_max = 96000,
+                                       .nr_rates = 3,
+                                       .rate_table = (unsigned int[]) { 44100, 48000, 96000 }
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
+{
+       /*
+        * Pioneer DJ DJM-450
+        * PCM is 8 channels out @ 48 fixed (endpoint 0x01)
+        * and 8 channels in @ 48 fixed (endpoint 0x82).
+        */
+       USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0013),
+       .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_COMPOSITE,
+               .data = (const struct snd_usb_audio_quirk[]) {
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8, // outputs
+                                       .iface = 0,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x01,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC|
+                                               USB_ENDPOINT_SYNC_ASYNC,
+                                       .rates = SNDRV_PCM_RATE_48000,
+                                       .rate_min = 48000,
+                                       .rate_max = 48000,
+                                       .nr_rates = 1,
+                                       .rate_table = (unsigned int[]) { 48000 }
+                                       }
+                       },
+                       {
+                               .ifnum = 0,
+                               .type = QUIRK_AUDIO_FIXED_ENDPOINT,
+                               .data = &(const struct audioformat) {
+                                       .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+                                       .channels = 8, // inputs
+                                       .iface = 0,
+                                       .altsetting = 1,
+                                       .altset_idx = 1,
+                                       .endpoint = 0x82,
+                                       .ep_idx = 1,
+                                       .ep_attr = USB_ENDPOINT_XFER_ISOC|
+                                               USB_ENDPOINT_SYNC_ASYNC|
+                                               USB_ENDPOINT_USAGE_IMPLICIT_FB,
+                                       .rates = SNDRV_PCM_RATE_48000,
+                                       .rate_min = 48000,
+                                       .rate_max = 48000,
+                                       .nr_rates = 1,
+                                       .rate_table = (unsigned int[]) { 48000 }
+                               }
+                       },
+                       {
+                               .ifnum = -1
+                       }
+               }
+       }
+},
 
 #undef USB_DEVICE_VENDOR_SPEC
 #undef USB_AUDIO_DEVICE
index e196e36..9ba4682 100644 (file)
@@ -1470,6 +1470,23 @@ static void set_format_emu_quirk(struct snd_usb_substream *subs,
        subs->pkt_offset_adj = (emu_samplerate_id >= EMU_QUIRK_SR_176400HZ) ? 4 : 0;
 }
 
+static int pioneer_djm_set_format_quirk(struct snd_usb_substream *subs,
+                                       u16 windex)
+{
+       unsigned int cur_rate = subs->data_endpoint->cur_rate;
+       u8 sr[3];
+       // Convert to little endian
+       sr[0] = cur_rate & 0xff;
+       sr[1] = (cur_rate >> 8) & 0xff;
+       sr[2] = (cur_rate >> 16) & 0xff;
+       usb_set_interface(subs->dev, 0, 1);
+       // we should derive windex from fmt-sync_ep but it's not set
+       snd_usb_ctl_msg(subs->stream->chip->dev,
+               usb_rcvctrlpipe(subs->stream->chip->dev, 0),
+               0x01, 0x22, 0x0100, windex, &sr, 0x0003);
+       return 0;
+}
+
 void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
                              const struct audioformat *fmt)
 {
@@ -1483,6 +1500,9 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
        case USB_ID(0x534d, 0x2109): /* MacroSilicon MS2109 */
                subs->stream_offset_adj = 2;
                break;
+       case USB_ID(0x2b73, 0x0013): /* Pioneer DJM-450 */
+               pioneer_djm_set_format_quirk(subs, 0x0082);
+               break;
        }
 }
 
index 9f9fcd2..1d66c3a 100644 (file)
@@ -1770,8 +1770,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
        card_ctx->irq = irq;
 
        /* only 32bit addressable */
-       dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
-       dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
 
        init_channel_allocations();
 
@@ -1790,7 +1789,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
                /* setup private data which can be retrieved when required */
                pcm->private_data = ctx;
                pcm->info_flags = 0;
-               strlcpy(pcm->name, card->shortname, strlen(card->shortname));
+               strscpy(pcm->name, card->shortname, strlen(card->shortname));
                /* setup the ops for playabck */
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &had_pcm_ops);
 
index eda077c..63b0398 100644 (file)
@@ -398,7 +398,7 @@ static int cfg_device(struct xen_snd_front_info *front_info,
 
        str = xenbus_read(XBT_NIL, device_path, XENSND_FIELD_DEVICE_NAME, NULL);
        if (!IS_ERR(str)) {
-               strlcpy(pcm_instance->name, str, sizeof(pcm_instance->name));
+               strscpy(pcm_instance->name, str, sizeof(pcm_instance->name));
                kfree(str);
        }