summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.yaml108
-rw-r--r--MAINTAINERS1
-rw-r--r--include/linux/pci_ids.h1
-rw-r--r--include/sound/core.h1
-rw-r--r--include/sound/dmaengine_pcm.h2
-rw-r--r--include/sound/gus.h22
-rw-r--r--include/sound/hdaudio.h6
-rw-r--r--include/sound/jack.h6
-rw-r--r--include/sound/pcm.h4
-rw-r--r--include/sound/snd_wavefront.h4
-rw-r--r--include/sound/tas2781-comlib-i2c.h37
-rw-r--r--include/sound/tas2781.h51
-rw-r--r--sound/atmel/ac97c.c9
-rw-r--r--sound/core/control.c14
-rw-r--r--sound/core/device.c23
-rw-r--r--sound/core/jack.c19
-rw-r--r--sound/core/oss/pcm_oss.c3
-rw-r--r--sound/core/pcm_dmaengine.c21
-rw-r--r--sound/core/pcm_memory.c2
-rw-r--r--sound/core/pcm_misc.c30
-rw-r--r--sound/core/pcm_native.c11
-rw-r--r--sound/core/seq/seq_queue.c16
-rw-r--r--sound/core/seq/seq_queue.h1
-rw-r--r--sound/core/seq_device.c2
-rw-r--r--sound/hda/hda_bus_type.c6
-rw-r--r--sound/hda/hdac_stream.c19
-rw-r--r--sound/hda/intel-dsp-config.c6
-rw-r--r--sound/hda/intel-nhlt.c19
-rw-r--r--sound/i2c/other/pt2258.c8
-rw-r--r--sound/isa/gus/gus_io.c229
-rw-r--r--sound/isa/gus/gus_main.c14
-rw-r--r--sound/isa/gus/gus_reset.c16
-rw-r--r--sound/isa/msnd/Makefile2
-rw-r--r--sound/isa/msnd/msnd.h4
-rw-r--r--sound/isa/msnd/msnd_midi.c163
-rw-r--r--sound/isa/msnd/msnd_pinnacle.c5
-rw-r--r--sound/isa/sb/emu8000.c3
-rw-r--r--sound/isa/sb/jazz16.c5
-rw-r--r--sound/isa/sb/sb16.c5
-rw-r--r--sound/isa/sb/sb8.c5
-rw-r--r--sound/isa/sb/sb8_midi.c3
-rw-r--r--sound/isa/sb/sb_mixer.c5
-rw-r--r--sound/mips/snd-n64.c9
-rw-r--r--sound/pci/ad1889.c7
-rw-r--r--sound/pci/ali5451/ali5451.c6
-rw-r--r--sound/pci/als300.c2
-rw-r--r--sound/pci/als4000.c2
-rw-r--r--sound/pci/asihpi/asihpi.c9
-rw-r--r--sound/pci/atiixp.c7
-rw-r--r--sound/pci/atiixp_modem.c7
-rw-r--r--sound/pci/au88x0/au88x0.c7
-rw-r--r--sound/pci/au88x0/au88x0_a3d.c10
-rw-r--r--sound/pci/aw2/aw2-alsa.c7
-rw-r--r--sound/pci/azt3328.c2
-rw-r--r--sound/pci/bt87x.c7
-rw-r--r--sound/pci/ca0106/ca0106_main.c2
-rw-r--r--sound/pci/cmipci.c2
-rw-r--r--sound/pci/cs4281.c13
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c2
-rw-r--r--sound/pci/cs46xx/dsp_spos_scb_lib.c7
-rw-r--r--sound/pci/cs5530.c7
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c2
-rw-r--r--sound/pci/echoaudio/echoaudio.c2
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c2
-rw-r--r--sound/pci/emu10k1/emu10k1x.c2
-rw-r--r--sound/pci/ens1370.c2
-rw-r--r--sound/pci/es1938.c2
-rw-r--r--sound/pci/es1968.c2
-rw-r--r--sound/pci/fm801.c2
-rw-r--r--sound/pci/hda/Kconfig33
-rw-r--r--sound/pci/hda/Makefile8
-rw-r--r--sound/pci/hda/cirrus_scodec_test.c110
-rw-r--r--sound/pci/hda/cs35l41_hda.c53
-rw-r--r--sound/pci/hda/cs35l41_hda_property.c6
-rw-r--r--sound/pci/hda/cs35l56_hda.c14
-rw-r--r--sound/pci/hda/hda_acpi.c325
-rw-r--r--sound/pci/hda/hda_bind.c6
-rw-r--r--sound/pci/hda/hda_codec.c31
-rw-r--r--sound/pci/hda/hda_cs_dsp_ctl.c249
-rw-r--r--sound/pci/hda/hda_cs_dsp_ctl.h39
-rw-r--r--sound/pci/hda/hda_intel.c35
-rw-r--r--sound/pci/hda/hda_local.h2
-rw-r--r--sound/pci/hda/hda_tegra.c55
-rw-r--r--sound/pci/hda/patch_hdmi.c13
-rw-r--r--sound/pci/hda/patch_realtek.c19
-rw-r--r--sound/pci/hda/tas2781-spi.h157
-rw-r--r--sound/pci/hda/tas2781_hda.c377
-rw-r--r--sound/pci/hda/tas2781_hda.h90
-rw-r--r--sound/pci/hda/tas2781_hda_i2c.c498
-rw-r--r--sound/pci/hda/tas2781_hda_spi.c890
-rw-r--r--sound/pci/hda/tas2781_spi_fwlib.c2006
-rw-r--r--sound/pci/ice1712/ice1712.c2
-rw-r--r--sound/pci/ice1712/ice1724.c2
-rw-r--r--sound/pci/intel8x0.c2
-rw-r--r--sound/pci/intel8x0m.c2
-rw-r--r--sound/pci/korg1212/korg1212.c75
-rw-r--r--sound/pci/lola/lola.c16
-rw-r--r--sound/pci/lx6464es/lx6464es.c2
-rw-r--r--sound/pci/maestro3.c2
-rw-r--r--sound/pci/nm256/nm256.c2
-rw-r--r--sound/pci/oxygen/oxygen_lib.c2
-rw-r--r--sound/pci/riptide/riptide.c2
-rw-r--r--sound/pci/rme32.c2
-rw-r--r--sound/pci/rme96.c2
-rw-r--r--sound/pci/rme9652/hdsp.c2
-rw-r--r--sound/pci/rme9652/hdspm.c7
-rw-r--r--sound/pci/rme9652/rme9652.c2
-rw-r--r--sound/pci/sis7019.c2
-rw-r--r--sound/pci/sonicvibes.c2
-rw-r--r--sound/pci/trident/trident_main.c2
-rw-r--r--sound/pci/via82xx.c2
-rw-r--r--sound/pci/via82xx_modem.c2
-rw-r--r--sound/pci/vx222/vx222.c2
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c2
-rw-r--r--sound/sh/aica.c8
-rw-r--r--sound/soc/apple/mca.c23
-rw-r--r--sound/soc/codecs/Kconfig9
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/tas2781-comlib-i2c.c369
-rw-r--r--sound/soc/codecs/tas2781-comlib.c397
-rw-r--r--sound/soc/codecs/tas2781-fmwlib.c17
-rw-r--r--sound/soc/codecs/tas2781-i2c.c1
-rw-r--r--sound/soc/mediatek/Kconfig1
-rw-r--r--sound/soc/qcom/sdm845.c4
-rw-r--r--sound/soc/sof/intel/hda-bus.c2
-rw-r--r--sound/soc/sof/intel/hda.c16
-rw-r--r--sound/soc/sof/intel/hda.h1
-rw-r--r--sound/soc/sof/intel/pci-ptl.c30
-rw-r--r--sound/soc/sof/intel/ptl.c23
-rw-r--r--sound/soc/sof/ipc4-control.c11
-rw-r--r--sound/soc/sof/ipc4-pcm.c3
-rw-r--r--sound/soc/sof/topology.c18
-rw-r--r--sound/sparc/amd7930.c9
-rw-r--r--sound/sparc/dbri.c9
-rw-r--r--sound/usb/fcp.c3
-rw-r--r--sound/usb/implicit.c1
-rw-r--r--sound/usb/midi.c5
-rw-r--r--sound/usb/mixer.c22
-rw-r--r--sound/usb/mixer_quirks.c154
-rw-r--r--sound/usb/mixer_scarlett2.c3
-rw-r--r--sound/usb/mixer_us16x08.c32
-rw-r--r--sound/usb/quirks-table.h51
-rw-r--r--sound/usb/quirks.c3
-rw-r--r--sound/virtio/virtio_kctl.c8
-rw-r--r--sound/x86/intel_hdmi_audio.c7
145 files changed, 2499 insertions, 4939 deletions
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.yaml
index 3ca9affb79a2..8a8767589ee0 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra30-hda.yaml
@@ -20,11 +20,13 @@ properties:
compatible:
oneOf:
- - const: nvidia,tegra30-hda
+ - enum:
+ - nvidia,tegra30-hda
+ - nvidia,tegra194-hda
+ - nvidia,tegra234-hda
+ - nvidia,tegra264-hda
- items:
- enum:
- - nvidia,tegra234-hda
- - nvidia,tegra194-hda
- nvidia,tegra186-hda
- nvidia,tegra210-hda
- nvidia,tegra124-hda
@@ -43,15 +45,12 @@ properties:
maxItems: 1
clocks:
- minItems: 2
+ minItems: 1
maxItems: 3
clock-names:
- minItems: 2
- items:
- - const: hda
- - const: hda2hdmi
- - const: hda2codec_2x
+ minItems: 1
+ maxItems: 3
resets:
minItems: 2
@@ -59,10 +58,7 @@ properties:
reset-names:
minItems: 2
- items:
- - const: hda
- - const: hda2hdmi
- - const: hda2codec_2x
+ maxItems: 3
power-domains:
maxItems: 1
@@ -93,6 +89,92 @@ required:
additionalProperties: false
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nvidia,tegra30-hda
+ then:
+ properties:
+ clocks:
+ minItems: 3
+ clock-names:
+ items:
+ - const: hda
+ - const: hda2hdmi
+ - const: hda2codec_2x
+ resets:
+ minItems: 3
+ reset-names:
+ items:
+ - const: hda
+ - const: hda2hdmi
+ - const: hda2codec_2x
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nvidia,tegra194-hda
+ then:
+ properties:
+ clocks:
+ minItems: 3
+ clock-names:
+ items:
+ - const: hda
+ - const: hda2hdmi
+ - const: hda2codec_2x
+ resets:
+ maxItems: 2
+ reset-names:
+ items:
+ - const: hda
+ - const: hda2hdmi
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nvidia,tegra234-hda
+ then:
+ properties:
+ clocks:
+ minItems: 2
+ maxItems: 2
+ clock-names:
+ items:
+ - const: hda
+ - const: hda2codec_2x
+ resets:
+ maxItems: 2
+ reset-names:
+ items:
+ - const: hda
+ - const: hda2codec_2x
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nvidia,tegra264-hda
+ then:
+ properties:
+ clocks:
+ maxItems: 1
+ clock-names:
+ items:
+ - const: hda
+ resets:
+ maxItems: 2
+ reset-names:
+ items:
+ - const: hda
+ - const: hda2codec_2x
+ power-domains: false
+
examples:
- |
#include<dt-bindings/clock/tegra124-car-common.h>
diff --git a/MAINTAINERS b/MAINTAINERS
index c95f48f6635a..ea6af33219b5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5655,7 +5655,6 @@ F: include/sound/cs*
F: sound/pci/hda/cirrus*
F: sound/pci/hda/cs*
F: sound/pci/hda/hda_component*
-F: sound/pci/hda/hda_cs_dsp_ctl.*
F: sound/soc/codecs/cs*
CIRRUS LOGIC HAPTIC DRIVERS
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 981ed45cc45e..e2d71b6fdd84 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -3049,6 +3049,7 @@
#define PCI_DEVICE_ID_INTEL_HDA_DG1 0x490d
#define PCI_DEVICE_ID_INTEL_HDA_EHL_0 0x4b55
#define PCI_DEVICE_ID_INTEL_HDA_EHL_3 0x4b58
+#define PCI_DEVICE_ID_INTEL_HDA_WCL 0x4d28
#define PCI_DEVICE_ID_INTEL_HDA_JSL_N 0x4dc8
#define PCI_DEVICE_ID_INTEL_HDA_DG2_0 0x4f90
#define PCI_DEVICE_ID_INTEL_HDA_DG2_1 0x4f91
diff --git a/include/sound/core.h b/include/sound/core.h
index 1f3f5dccd736..64327e971122 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -326,7 +326,6 @@ void snd_device_disconnect(struct snd_card *card, void *device_data);
void snd_device_disconnect_all(struct snd_card *card);
void snd_device_free(struct snd_card *card, void *device_data);
void snd_device_free_all(struct snd_card *card);
-int snd_device_get_state(struct snd_card *card, void *device_data);
/* isadma.c */
diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h
index f6baa9a01868..1ef13bcdc43f 100644
--- a/include/sound/dmaengine_pcm.h
+++ b/include/sound/dmaengine_pcm.h
@@ -38,8 +38,6 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream);
int snd_dmaengine_pcm_sync_stop(struct snd_pcm_substream *substream);
-int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
- dma_filter_fn filter_fn, void *filter_data);
int snd_dmaengine_pcm_close_release_chan(struct snd_pcm_substream *substream);
struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn,
diff --git a/include/sound/gus.h b/include/sound/gus.h
index cd8da68cab92..1c8fb6c93e50 100644
--- a/include/sound/gus.h
+++ b/include/sound/gus.h
@@ -513,22 +513,6 @@ struct _SND_IW_LFO_PROGRAM {
unsigned short depth;
};
-#if 0
-extern irqreturn_t snd_gf1_lfo_effect_interrupt(struct snd_gus_card * gus, snd_gf1_voice_t * voice);
-#endif
-extern void snd_gf1_lfo_init(struct snd_gus_card * gus);
-extern void snd_gf1_lfo_done(struct snd_gus_card * gus);
-extern void snd_gf1_lfo_program(struct snd_gus_card * gus, int voice, int lfo_type, struct _SND_IW_LFO_PROGRAM *program);
-extern void snd_gf1_lfo_enable(struct snd_gus_card * gus, int voice, int lfo_type);
-extern void snd_gf1_lfo_disable(struct snd_gus_card * gus, int voice, int lfo_type);
-extern void snd_gf1_lfo_change_freq(struct snd_gus_card * gus, int voice, int lfo_type, int freq);
-extern void snd_gf1_lfo_change_depth(struct snd_gus_card * gus, int voice, int lfo_type, int depth);
-extern void snd_gf1_lfo_setup(struct snd_gus_card * gus, int voice, int lfo_type, int freq, int current_depth, int depth, int sweep, int shape);
-extern void snd_gf1_lfo_shutdown(struct snd_gus_card * gus, int voice, int lfo_type);
-#if 0
-extern void snd_gf1_lfo_command(struct snd_gus_card * gus, int voice, unsigned char *command);
-#endif
-
/* gus_mem.c */
void snd_gf1_mem_lock(struct snd_gf1_mem * alloc, int xup);
@@ -578,14 +562,8 @@ int snd_gf1_new_mixer(struct snd_gus_card * gus);
int snd_gf1_pcm_new(struct snd_gus_card *gus, int pcm_dev, int control_index);
-#ifdef CONFIG_SND_DEBUG
-extern void snd_gf1_print_voice_registers(struct snd_gus_card * gus);
-#endif
-
/* gus.c */
-int snd_gus_use_inc(struct snd_gus_card * gus);
-void snd_gus_use_dec(struct snd_gus_card * gus);
int snd_gus_create(struct snd_card *card,
unsigned long port,
int irq, int dma1, int dma2,
diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h
index b098ceadbe74..25668eee65cf 100644
--- a/include/sound/hdaudio.h
+++ b/include/sound/hdaudio.h
@@ -223,7 +223,7 @@ struct hdac_driver {
struct device_driver driver;
int type;
const struct hda_device_id *id_table;
- int (*match)(struct hdac_device *dev, struct hdac_driver *drv);
+ int (*match)(struct hdac_device *dev, const struct hdac_driver *drv);
void (*unsol_event)(struct hdac_device *dev, unsigned int event);
/* fields used by ext bus APIs */
@@ -235,7 +235,7 @@ struct hdac_driver {
#define drv_to_hdac_driver(_drv) container_of(_drv, struct hdac_driver, driver)
const struct hda_device_id *
-hdac_get_device_id(struct hdac_device *hdev, struct hdac_driver *drv);
+hdac_get_device_id(struct hdac_device *hdev, const struct hdac_driver *drv);
/*
* Bus verb operators
@@ -598,8 +598,6 @@ void snd_hdac_stream_spbcap_enable(struct hdac_bus *chip,
bool enable, int index);
int snd_hdac_stream_set_spib(struct hdac_bus *bus,
struct hdac_stream *azx_dev, u32 value);
-int snd_hdac_stream_get_spbmaxfifo(struct hdac_bus *bus,
- struct hdac_stream *azx_dev);
void snd_hdac_stream_drsm_enable(struct hdac_bus *bus,
bool enable, int index);
int snd_hdac_stream_wait_drsm(struct hdac_stream *azx_dev);
diff --git a/include/sound/jack.h b/include/sound/jack.h
index 1ed90e2109e9..36dc104c1145 100644
--- a/include/sound/jack.h
+++ b/include/sound/jack.h
@@ -79,7 +79,6 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
struct snd_jack **jack, bool initial_kctl, bool phantom_jack);
int snd_jack_add_new_kctl(struct snd_jack *jack, const char * name, int mask);
#ifdef CONFIG_SND_JACK_INPUT_DEV
-void snd_jack_set_parent(struct snd_jack *jack, struct device *parent);
int snd_jack_set_key(struct snd_jack *jack, enum snd_jack_types type,
int keytype);
#endif
@@ -104,11 +103,6 @@ static inline void snd_jack_report(struct snd_jack *jack, int status)
#endif
#if !defined(CONFIG_SND_JACK) || !defined(CONFIG_SND_JACK_INPUT_DEV)
-static inline void snd_jack_set_parent(struct snd_jack *jack,
- struct device *parent)
-{
-}
-
static inline int snd_jack_set_key(struct snd_jack *jack,
enum snd_jack_types type,
int keytype)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 8becb4504887..58fd6e84f961 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -1251,8 +1251,6 @@ unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate);
unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit);
unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a,
unsigned int rates_b);
-unsigned int snd_pcm_rate_range_to_bits(unsigned int rate_min,
- unsigned int rate_max);
/**
* snd_pcm_set_runtime_buffer - Set the PCM runtime buffer
@@ -1404,6 +1402,8 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_s
#define snd_pcm_lib_mmap_iomem NULL
#endif
+void snd_pcm_runtime_buffer_set_silence(struct snd_pcm_runtime *runtime);
+
/**
* snd_pcm_limit_isa_dma_size - Get the max size fitting with ISA DMA transfer
* @dma: DMA number
diff --git a/include/sound/snd_wavefront.h b/include/sound/snd_wavefront.h
index 27f7e8a477c2..30f508a56766 100644
--- a/include/sound/snd_wavefront.h
+++ b/include/sound/snd_wavefront.h
@@ -110,12 +110,8 @@ struct _snd_wavefront_card {
};
extern void snd_wavefront_internal_interrupt (snd_wavefront_card_t *card);
-extern int snd_wavefront_detect_irq (snd_wavefront_t *dev) ;
-extern int snd_wavefront_check_irq (snd_wavefront_t *dev, int irq);
-extern int snd_wavefront_restart (snd_wavefront_t *dev);
extern int snd_wavefront_start (snd_wavefront_t *dev);
extern int snd_wavefront_detect (snd_wavefront_card_t *card);
-extern int snd_wavefront_config_midi (snd_wavefront_t *dev) ;
extern int snd_wavefront_cmd (snd_wavefront_t *, int, unsigned char *,
unsigned char *);
diff --git a/include/sound/tas2781-comlib-i2c.h b/include/sound/tas2781-comlib-i2c.h
new file mode 100644
index 000000000000..a1afa5c444ba
--- /dev/null
+++ b/include/sound/tas2781-comlib-i2c.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+//
+// ALSA SoC Texas Instruments TAS2563/TAS2781 Audio Smart Amplifier
+//
+// Copyright (C) 2025 Texas Instruments Incorporated
+// https://www.ti.com
+//
+// The TAS2563/TAS2781 driver implements a flexible and configurable
+// algo coefficient setting for one, two, or even multiple
+// TAS2563/TAS2781 chips.
+//
+// Author: Shenghao Ding <shenghao-ding@ti.com>
+//
+
+#ifndef __TAS2781_COMLIB_I2C_H__
+#define __TAS2781_COMLIB_I2C_H__
+
+void tasdevice_reset(struct tasdevice_priv *tas_dev);
+int tascodec_init(struct tasdevice_priv *tas_priv, void *codec,
+ struct module *module,
+ void (*cont)(const struct firmware *fw, void *context));
+struct tasdevice_priv *tasdevice_kzalloc(struct i2c_client *i2c);
+int tasdevice_init(struct tasdevice_priv *tas_priv);
+int tasdev_chn_switch(struct tasdevice_priv *tas_priv,
+ unsigned short chn);
+int tasdevice_dev_update_bits(
+ struct tasdevice_priv *tasdevice, unsigned short chn,
+ unsigned int reg, unsigned int mask, unsigned int value);
+int tasdevice_amp_putvol(struct tasdevice_priv *tas_priv,
+ struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc);
+int tasdevice_amp_getvol(struct tasdevice_priv *tas_priv,
+ struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc);
+int tasdevice_digital_getvol(struct tasdevice_priv *tas_priv,
+ struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc);
+int tasdevice_digital_putvol(struct tasdevice_priv *tas_priv,
+ struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc);
+#endif /* __TAS2781_COMLIB_I2C_H__ */
diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h
index 2b3acd2fdff0..40cd3bd079b5 100644
--- a/include/sound/tas2781.h
+++ b/include/sound/tas2781.h
@@ -32,6 +32,8 @@
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
+#define TASDEVICE_CRC8_POLYNOMIAL 0x4d
+
/* PAGE Control Register (available in page0 of each book) */
#define TASDEVICE_PAGE_SELECT 0x00
#define TASDEVICE_BOOKCTL_PAGE 0x00
@@ -114,11 +116,6 @@ enum dspbin_type {
TASDEV_BETA,
};
-enum device_catlog_id {
- LENOVO = 0,
- OTHERS
-};
-
struct bulk_reg_val {
int reg;
unsigned char val[4];
@@ -188,7 +185,6 @@ struct tasdevice_priv {
struct regmap *regmap;
struct device *dev;
- enum device_catlog_id catlog_id;
unsigned char cal_binaryname[TASDEVICE_MAX_CHANNELS][64];
unsigned char crc8_lkp_tbl[CRC8_TABLE_SIZE];
unsigned char coef_binaryname[64];
@@ -211,6 +207,7 @@ struct tasdevice_priv {
bool force_fwload_status;
bool playback_started;
bool isacpi;
+ bool isspi;
bool is_user_space_calidata;
unsigned int global_addr;
@@ -228,41 +225,27 @@ struct tasdevice_priv {
int (*tasdevice_load_block)(struct tasdevice_priv *tas_priv,
struct tasdev_blk *block);
- int (*save_calibration)(struct tasdevice_priv *tas_priv);
- void (*apply_calibration)(struct tasdevice_priv *tas_priv);
+ int (*change_chn_book)(struct tasdevice_priv *tas_priv,
+ unsigned short chn, int book);
+ int (*update_bits)(struct tasdevice_priv *tas_priv,
+ unsigned short chn, unsigned int reg, unsigned int mask,
+ unsigned int value);
+ int (*dev_read)(struct tasdevice_priv *tas_priv,
+ unsigned short chn, unsigned int reg, unsigned int *value);
+ int (*dev_bulk_read)(struct tasdevice_priv *tas_priv,
+ unsigned short chn, unsigned int reg, unsigned char *p_data,
+ unsigned int n_length);
};
-void tasdevice_reset(struct tasdevice_priv *tas_dev);
-int tascodec_init(struct tasdevice_priv *tas_priv, void *codec,
- struct module *module,
- void (*cont)(const struct firmware *fw, void *context));
-struct tasdevice_priv *tasdevice_kzalloc(struct i2c_client *i2c);
-int tasdevice_init(struct tasdevice_priv *tas_priv);
-void tasdevice_remove(struct tasdevice_priv *tas_priv);
-int tasdevice_save_calibration(struct tasdevice_priv *tas_priv);
-void tasdevice_apply_calibration(struct tasdevice_priv *tas_priv);
-int tasdev_chn_switch(struct tasdevice_priv *tas_priv,
- unsigned short chn);
int tasdevice_dev_read(struct tasdevice_priv *tas_priv,
unsigned short chn, unsigned int reg, unsigned int *value);
+int tasdevice_dev_bulk_read(struct tasdevice_priv *tas_priv,
+ unsigned short chn, unsigned int reg, unsigned char *p_data,
+ unsigned int n_length);
int tasdevice_dev_write(struct tasdevice_priv *tas_priv,
unsigned short chn, unsigned int reg, unsigned int value);
int tasdevice_dev_bulk_write(
struct tasdevice_priv *tas_priv, unsigned short chn,
unsigned int reg, unsigned char *p_data, unsigned int n_length);
-int tasdevice_dev_bulk_read(struct tasdevice_priv *tas_priv,
- unsigned short chn, unsigned int reg, unsigned char *p_data,
- unsigned int n_length);
-int tasdevice_dev_update_bits(
- struct tasdevice_priv *tasdevice, unsigned short chn,
- unsigned int reg, unsigned int mask, unsigned int value);
-int tasdevice_amp_putvol(struct tasdevice_priv *tas_priv,
- struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc);
-int tasdevice_amp_getvol(struct tasdevice_priv *tas_priv,
- struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc);
-int tasdevice_digital_putvol(struct tasdevice_priv *tas_priv,
- struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc);
-int tasdevice_digital_getvol(struct tasdevice_priv *tas_priv,
- struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc);
-
+void tasdevice_remove(struct tasdevice_priv *tas_priv);
#endif /* __TAS2781_H__ */
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index 84e264f335ca..693d48f08b88 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
+#include <linux/string.h>
#include <linux/types.h>
#include <linux/io.h>
@@ -589,7 +590,7 @@ static int atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
pcm->private_data = chip;
pcm->info_flags = 0;
- strcpy(pcm->name, chip->card->shortname);
+ strscpy(pcm->name, chip->card->shortname);
chip->pcm = pcm;
return 0;
@@ -748,9 +749,9 @@ static int atmel_ac97c_probe(struct platform_device *pdev)
spin_lock_init(&chip->lock);
- strcpy(card->driver, "Atmel AC97C");
- strcpy(card->shortname, "Atmel AC97C");
- sprintf(card->longname, "Atmel AC97 controller");
+ strscpy(card->driver, "Atmel AC97C");
+ strscpy(card->shortname, "Atmel AC97C");
+ strscpy(card->longname, "Atmel AC97 controller");
chip->card = card;
chip->pclk = pclk;
diff --git a/sound/core/control.c b/sound/core/control.c
index 0ddade871b52..11f660fc6f2b 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1405,7 +1405,7 @@ static bool check_user_elem_overflow(struct snd_card *card, ssize_t add)
static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- struct user_element *ue = kcontrol->private_data;
+ struct user_element *ue = snd_kcontrol_chip(kcontrol);
unsigned int offset;
offset = snd_ctl_get_ioff(kcontrol, &uinfo->id);
@@ -1418,7 +1418,7 @@ static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol,
static int snd_ctl_elem_user_enum_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- struct user_element *ue = kcontrol->private_data;
+ struct user_element *ue = snd_kcontrol_chip(kcontrol);
const char *names;
unsigned int item;
unsigned int offset;
@@ -1443,7 +1443,7 @@ static int snd_ctl_elem_user_enum_info(struct snd_kcontrol *kcontrol,
static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct user_element *ue = kcontrol->private_data;
+ struct user_element *ue = snd_kcontrol_chip(kcontrol);
unsigned int size = ue->elem_data_size;
char *src = ue->elem_data +
snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size;
@@ -1456,7 +1456,7 @@ static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int err, change;
- struct user_element *ue = kcontrol->private_data;
+ struct user_element *ue = snd_kcontrol_chip(kcontrol);
unsigned int size = ue->elem_data_size;
char *dst = ue->elem_data +
snd_ctl_get_ioff(kcontrol, &ucontrol->id) * size;
@@ -1475,7 +1475,7 @@ static int snd_ctl_elem_user_put(struct snd_kcontrol *kcontrol,
static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
unsigned int size)
{
- struct user_element *ue = kctl->private_data;
+ struct user_element *ue = snd_kcontrol_chip(kctl);
unsigned int *container;
unsigned int mask = 0;
int i;
@@ -1528,7 +1528,7 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
static int read_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
unsigned int size)
{
- struct user_element *ue = kctl->private_data;
+ struct user_element *ue = snd_kcontrol_chip(kctl);
if (ue->tlv_data_size == 0 || ue->tlv_data == NULL)
return -ENXIO;
@@ -1598,7 +1598,7 @@ static size_t compute_user_elem_size(size_t size, unsigned int count)
static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol)
{
- struct user_element *ue = kcontrol->private_data;
+ struct user_element *ue = snd_kcontrol_chip(kcontrol);
// decrement the allocation size.
ue->card->user_ctl_alloc_size -= compute_user_elem_size(ue->elem_data_size, kcontrol->count);
diff --git a/sound/core/device.c b/sound/core/device.c
index b57d80a17052..cdc5af526739 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -237,26 +237,3 @@ void snd_device_free_all(struct snd_card *card)
list_for_each_entry_safe_reverse(dev, next, &card->devices, list)
__snd_device_free(dev);
}
-
-/**
- * snd_device_get_state - Get the current state of the given device
- * @card: the card instance
- * @device_data: the data pointer to release
- *
- * Returns the current state of the given device object. For the valid
- * device, either @SNDRV_DEV_BUILD, @SNDRV_DEV_REGISTERED or
- * @SNDRV_DEV_DISCONNECTED is returned.
- * Or for a non-existing device, -1 is returned as an error.
- *
- * Return: the current state, or -1 if not found
- */
-int snd_device_get_state(struct snd_card *card, void *device_data)
-{
- struct snd_device *dev;
-
- dev = look_for_dev(card, device_data);
- if (dev)
- return dev->state;
- return -1;
-}
-EXPORT_SYMBOL_GPL(snd_device_get_state);
diff --git a/sound/core/jack.c b/sound/core/jack.c
index e4bcecdf89b7..850f82340278 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -575,25 +575,6 @@ EXPORT_SYMBOL(snd_jack_new);
#ifdef CONFIG_SND_JACK_INPUT_DEV
/**
- * snd_jack_set_parent - Set the parent device for a jack
- *
- * @jack: The jack to configure
- * @parent: The device to set as parent for the jack.
- *
- * Set the parent for the jack devices in the device tree. This
- * function is only valid prior to registration of the jack. If no
- * parent is configured then the parent device will be the sound card.
- */
-void snd_jack_set_parent(struct snd_jack *jack, struct device *parent)
-{
- WARN_ON(jack->registered);
- guard(mutex)(&jack->input_dev_lock);
- if (jack->input_dev)
- jack->input_dev->dev.parent = parent;
-}
-EXPORT_SYMBOL(snd_jack_set_parent);
-
-/**
* snd_jack_set_key - Set a key mapping on a jack
*
* @jack: The jack to configure
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 4683b9139c56..4ecb17bd5436 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1074,8 +1074,7 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
runtime->oss.params = 0;
runtime->oss.prepare = 1;
runtime->oss.buffer_used = 0;
- if (runtime->dma_area)
- snd_pcm_format_set_silence(runtime->format, runtime->dma_area, bytes_to_samples(runtime, runtime->dma_bytes));
+ snd_pcm_runtime_buffer_set_silence(runtime);
runtime->oss.period_frames = snd_pcm_alsa_frames(substream, oss_period_size);
diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index b134a51b3fd5..72040964b6fd 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -328,27 +328,6 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
}
EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open);
-/**
- * snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel
- * @substream: PCM substream
- * @filter_fn: Filter function used to request the DMA channel
- * @filter_data: Data passed to the DMA filter function
- *
- * This function will request a DMA channel using the passed filter function and
- * data. The function should usually be called from the pcm open callback. Note
- * that this function will use private_data field of the substream's runtime. So
- * it is not available to your pcm driver implementation.
- *
- * Return: 0 on success, a negative error code otherwise
- */
-int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream,
- dma_filter_fn filter_fn, void *filter_data)
-{
- return snd_dmaengine_pcm_open(substream,
- snd_dmaengine_pcm_request_channel(filter_fn, filter_data));
-}
-EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan);
-
int snd_dmaengine_pcm_sync_stop(struct snd_pcm_substream *substream)
{
struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index ea3941f8666b..56725d36825b 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -458,7 +458,7 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
substream->stream,
size, dmab) < 0) {
kfree(dmab);
- pr_debug("ALSA pcmC%dD%d%c,%d:%s: cannot preallocate for size %zu\n",
+ pr_debug("ALSA pcmC%dD%d%c,%d:%s: cannot allocate for size %zu\n",
substream->pcm->card->number, substream->pcm->device,
substream->stream ? 'c' : 'p', substream->number,
substream->pcm->name, size);
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index d3a08e292072..71eec32a7a0a 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -586,33 +586,3 @@ unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a,
return rates_a & rates_b;
}
EXPORT_SYMBOL_GPL(snd_pcm_rate_mask_intersect);
-
-/**
- * snd_pcm_rate_range_to_bits - converts rate range to SNDRV_PCM_RATE_xxx bit
- * @rate_min: the minimum sample rate
- * @rate_max: the maximum sample rate
- *
- * This function has an implicit assumption: the rates in the given range have
- * only the pre-defined rates like 44100 or 16000.
- *
- * Return: The SNDRV_PCM_RATE_xxx flag that corresponds to the given rate range,
- * or SNDRV_PCM_RATE_KNOT for an unknown range.
- */
-unsigned int snd_pcm_rate_range_to_bits(unsigned int rate_min,
- unsigned int rate_max)
-{
- unsigned int rates = 0;
- int i;
-
- for (i = 0; i < snd_pcm_known_rates.count; i++) {
- if (snd_pcm_known_rates.list[i] >= rate_min
- && snd_pcm_known_rates.list[i] <= rate_max)
- rates |= 1 << i;
- }
-
- if (!rates)
- rates = SNDRV_PCM_RATE_KNOT;
-
- return rates;
-}
-EXPORT_SYMBOL_GPL(snd_pcm_rate_range_to_bits);
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 6c2b6a62d9d2..853ac5bb33ff 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -723,6 +723,17 @@ static void snd_pcm_buffer_access_unlock(struct snd_pcm_runtime *runtime)
atomic_inc(&runtime->buffer_accessing);
}
+/* fill the PCM buffer with the current silence format; called from pcm_oss.c */
+void snd_pcm_runtime_buffer_set_silence(struct snd_pcm_runtime *runtime)
+{
+ snd_pcm_buffer_access_lock(runtime);
+ if (runtime->dma_area)
+ snd_pcm_format_set_silence(runtime->format, runtime->dma_area,
+ bytes_to_samples(runtime, runtime->dma_bytes));
+ snd_pcm_buffer_access_unlock(runtime);
+}
+EXPORT_SYMBOL_GPL(snd_pcm_runtime_buffer_set_silence);
+
#if IS_ENABLED(CONFIG_SND_PCM_OSS)
#define is_oss_stream(substream) ((substream)->oss.oss)
#else
diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index 5df26788dda4..10add922323d 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -564,22 +564,6 @@ void snd_seq_queue_client_leave(int client)
/*----------------------------------------------------------------*/
-/* remove cells from all queues */
-void snd_seq_queue_client_leave_cells(int client)
-{
- int i;
- struct snd_seq_queue *q;
-
- for (i = 0; i < SNDRV_SEQ_MAX_QUEUES; i++) {
- q = queueptr(i);
- if (!q)
- continue;
- snd_seq_prioq_leave(q->tickq, client, 0);
- snd_seq_prioq_leave(q->timeq, client, 0);
- queuefree(q);
- }
-}
-
/* remove cells based on flush criteria */
void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info)
{
diff --git a/sound/core/seq/seq_queue.h b/sound/core/seq/seq_queue.h
index 74cc31aacdac..b81379c9af43 100644
--- a/sound/core/seq/seq_queue.h
+++ b/sound/core/seq/seq_queue.h
@@ -66,7 +66,6 @@ void snd_seq_queue_client_leave(int client);
int snd_seq_enqueue_event(struct snd_seq_event_cell *cell, int atomic, int hop);
/* Remove events */
-void snd_seq_queue_client_leave_cells(int client);
void snd_seq_queue_remove_cells(int client, struct snd_seq_remove_events *info);
/* return pointer to queue structure for specified id */
diff --git a/sound/core/seq_device.c b/sound/core/seq_device.c
index 4492be5d2317..bac9f8603734 100644
--- a/sound/core/seq_device.c
+++ b/sound/core/seq_device.c
@@ -43,7 +43,7 @@ MODULE_LICENSE("GPL");
static int snd_seq_bus_match(struct device *dev, const struct device_driver *drv)
{
struct snd_seq_device *sdev = to_seq_dev(dev);
- struct snd_seq_driver *sdrv = to_seq_drv(drv);
+ const struct snd_seq_driver *sdrv = to_seq_drv(drv);
return strcmp(sdrv->id, sdev->id) == 0 &&
sdrv->argsize == sdev->argsize;
diff --git a/sound/hda/hda_bus_type.c b/sound/hda/hda_bus_type.c
index 7545ace7b0ee..eb72a7af2e56 100644
--- a/sound/hda/hda_bus_type.c
+++ b/sound/hda/hda_bus_type.c
@@ -21,7 +21,7 @@ MODULE_LICENSE("GPL");
* driver id_table and returns the matching device id entry.
*/
const struct hda_device_id *
-hdac_get_device_id(struct hdac_device *hdev, struct hdac_driver *drv)
+hdac_get_device_id(struct hdac_device *hdev, const struct hdac_driver *drv)
{
if (drv->id_table) {
const struct hda_device_id *id = drv->id_table;
@@ -38,7 +38,7 @@ hdac_get_device_id(struct hdac_device *hdev, struct hdac_driver *drv)
}
EXPORT_SYMBOL_GPL(hdac_get_device_id);
-static int hdac_codec_match(struct hdac_device *dev, struct hdac_driver *drv)
+static int hdac_codec_match(struct hdac_device *dev, const struct hdac_driver *drv)
{
if (hdac_get_device_id(dev, drv))
return 1;
@@ -49,7 +49,7 @@ static int hdac_codec_match(struct hdac_device *dev, struct hdac_driver *drv)
static int hda_bus_match(struct device *dev, const struct device_driver *drv)
{
struct hdac_device *hdev = dev_to_hdac_dev(dev);
- struct hdac_driver *hdrv = drv_to_hdac_driver(drv);
+ const struct hdac_driver *hdrv = drv_to_hdac_driver(drv);
if (hdev->type != hdrv->type)
return 0;
diff --git a/sound/hda/hdac_stream.c b/sound/hda/hdac_stream.c
index 4e85a838ad7e..e7f6208af5b0 100644
--- a/sound/hda/hdac_stream.c
+++ b/sound/hda/hdac_stream.c
@@ -826,25 +826,6 @@ int snd_hdac_stream_set_spib(struct hdac_bus *bus,
EXPORT_SYMBOL_GPL(snd_hdac_stream_set_spib);
/**
- * snd_hdac_stream_get_spbmaxfifo - gets the spib value of a stream
- * @bus: HD-audio core bus
- * @azx_dev: hdac_stream
- *
- * Return maxfifo for the stream
- */
-int snd_hdac_stream_get_spbmaxfifo(struct hdac_bus *bus,
- struct hdac_stream *azx_dev)
-{
- if (!bus->spbcap) {
- dev_err(bus->dev, "Address of SPB capability is NULL\n");
- return -EINVAL;
- }
-
- return readl(azx_dev->fifo_addr);
-}
-EXPORT_SYMBOL_GPL(snd_hdac_stream_get_spbmaxfifo);
-
-/**
* snd_hdac_stream_drsm_enable - enable DMA resume for a stream
* @bus: HD-audio core bus
* @enable: flag to enable/disable DRSM
diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
index 01594f858129..3cb1e7fc3b3b 100644
--- a/sound/hda/intel-dsp-config.c
+++ b/sound/hda/intel-dsp-config.c
@@ -541,7 +541,7 @@ static const struct config_entry config_table[] = {
},
#endif
- /* Panther Lake */
+ /* Panther Lake, Wildcat Lake */
#if IS_ENABLED(CONFIG_SND_SOC_SOF_PANTHERLAKE)
{
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
@@ -551,6 +551,10 @@ static const struct config_entry config_table[] = {
.flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
.device = PCI_DEVICE_ID_INTEL_HDA_PTL_H,
},
+ {
+ .flags = FLAG_SOF | FLAG_SOF_ONLY_IF_DMIC_OR_SOUNDWIRE,
+ .device = PCI_DEVICE_ID_INTEL_HDA_WCL,
+ },
#endif
diff --git a/sound/hda/intel-nhlt.c b/sound/hda/intel-nhlt.c
index 088cff799e0b..6d72a871bda0 100644
--- a/sound/hda/intel-nhlt.c
+++ b/sound/hda/intel-nhlt.c
@@ -350,8 +350,11 @@ int intel_nhlt_ssp_device_type(struct device *dev, struct nhlt_acpi_table *nhlt,
struct nhlt_endpoint *epnt;
int i;
- if (!nhlt)
+ if (!nhlt) {
+ dev_err(dev, "%s: NHLT table is missing (query for SSP%d)\n",
+ __func__, virtual_bus_id);
return -EINVAL;
+ }
epnt = (struct nhlt_endpoint *)nhlt->desc;
for (i = 0; i < nhlt->endpoint_count; i++) {
@@ -366,6 +369,20 @@ int intel_nhlt_ssp_device_type(struct device *dev, struct nhlt_acpi_table *nhlt,
epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
}
+ dev_err(dev, "%s: No match for SSP%d in NHLT table\n", __func__,
+ virtual_bus_id);
+
+ dev_dbg(dev, "Available endpoints:\n");
+ epnt = (struct nhlt_endpoint *)nhlt->desc;
+ for (i = 0; i < nhlt->endpoint_count; i++) {
+ dev_dbg(dev,
+ "%d: link_type: %d, vbus_id: %d, dir: %d, dev_type: %d\n",
+ i, epnt->linktype, epnt->virtual_bus_id,
+ epnt->direction, epnt->device_type);
+
+ epnt = (struct nhlt_endpoint *)((u8 *)epnt + epnt->length);
+ }
+
return -EINVAL;
}
EXPORT_SYMBOL(intel_nhlt_ssp_device_type);
diff --git a/sound/i2c/other/pt2258.c b/sound/i2c/other/pt2258.c
index ba38c285241c..0fbac827124b 100644
--- a/sound/i2c/other/pt2258.c
+++ b/sound/i2c/other/pt2258.c
@@ -80,7 +80,7 @@ static int pt2258_stereo_volume_info(struct snd_kcontrol *kcontrol,
static int pt2258_stereo_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_pt2258 *pt = kcontrol->private_data;
+ struct snd_pt2258 *pt = snd_kcontrol_chip(kcontrol);
int base = kcontrol->private_value;
/* chip does not support register reads */
@@ -92,7 +92,7 @@ static int pt2258_stereo_volume_get(struct snd_kcontrol *kcontrol,
static int pt2258_stereo_volume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_pt2258 *pt = kcontrol->private_data;
+ struct snd_pt2258 *pt = snd_kcontrol_chip(kcontrol);
int base = kcontrol->private_value;
unsigned char bytes[2];
int val0, val1;
@@ -133,7 +133,7 @@ static int pt2258_stereo_volume_put(struct snd_kcontrol *kcontrol,
static int pt2258_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_pt2258 *pt = kcontrol->private_data;
+ struct snd_pt2258 *pt = snd_kcontrol_chip(kcontrol);
ucontrol->value.integer.value[0] = !pt->mute;
return 0;
@@ -142,7 +142,7 @@ static int pt2258_switch_get(struct snd_kcontrol *kcontrol,
static int pt2258_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_pt2258 *pt = kcontrol->private_data;
+ struct snd_pt2258 *pt = snd_kcontrol_chip(kcontrol);
unsigned char bytes[2];
int val;
diff --git a/sound/isa/gus/gus_io.c b/sound/isa/gus/gus_io.c
index 1dc9e0edb3d9..f167eb8d516b 100644
--- a/sound/isa/gus/gus_io.c
+++ b/sound/isa/gus/gus_io.c
@@ -228,49 +228,6 @@ unsigned short snd_gf1_i_look16(struct snd_gus_card * gus, unsigned char reg)
return res;
}
-#if 0
-
-void snd_gf1_i_adlib_write(struct snd_gus_card * gus,
- unsigned char reg,
- unsigned char data)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&gus->reg_lock, flags);
- __snd_gf1_adlib_write(gus, reg, data);
- spin_unlock_irqrestore(&gus->reg_lock, flags);
-}
-
-void snd_gf1_i_write_addr(struct snd_gus_card * gus, unsigned char reg,
- unsigned int addr, short w_16bit)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&gus->reg_lock, flags);
- __snd_gf1_write_addr(gus, reg, addr, w_16bit);
- spin_unlock_irqrestore(&gus->reg_lock, flags);
-}
-
-#endif /* 0 */
-
-#ifdef CONFIG_SND_DEBUG
-static unsigned int snd_gf1_i_read_addr(struct snd_gus_card * gus,
- unsigned char reg, short w_16bit)
-{
- unsigned int res;
- unsigned long flags;
-
- spin_lock_irqsave(&gus->reg_lock, flags);
- res = __snd_gf1_read_addr(gus, reg, w_16bit);
- spin_unlock_irqrestore(&gus->reg_lock, flags);
- return res;
-}
-#endif
-
-/*
-
- */
-
void snd_gf1_dram_addr(struct snd_gus_card * gus, unsigned int addr)
{
outb(0x43, gus->gf1.reg_regsel);
@@ -418,189 +375,3 @@ void snd_gf1_select_active_voices(struct snd_gus_card * gus)
udelay(100);
}
}
-
-#ifdef CONFIG_SND_DEBUG
-
-void snd_gf1_print_voice_registers(struct snd_gus_card * gus)
-{
- unsigned char mode;
- int voice, ctrl;
-
- voice = gus->gf1.active_voice;
- dev_info(gus->card->dev,
- " -%i- GF1 voice ctrl, ramp ctrl = 0x%x, 0x%x\n",
- voice, ctrl = snd_gf1_i_read8(gus, 0), snd_gf1_i_read8(gus, 0x0d));
- dev_info(gus->card->dev,
- " -%i- GF1 frequency = 0x%x\n",
- voice, snd_gf1_i_read16(gus, 1));
- dev_info(gus->card->dev,
- " -%i- GF1 loop start, end = 0x%x (0x%x), 0x%x (0x%x)\n",
- voice, snd_gf1_i_read_addr(gus, 2, ctrl & 4),
- snd_gf1_i_read_addr(gus, 2, (ctrl & 4) ^ 4),
- snd_gf1_i_read_addr(gus, 4, ctrl & 4),
- snd_gf1_i_read_addr(gus, 4, (ctrl & 4) ^ 4));
- dev_info(gus->card->dev,
- " -%i- GF1 ramp start, end, rate = 0x%x, 0x%x, 0x%x\n",
- voice, snd_gf1_i_read8(gus, 7), snd_gf1_i_read8(gus, 8),
- snd_gf1_i_read8(gus, 6));
- dev_info(gus->card->dev,
- " -%i- GF1 volume = 0x%x\n",
- voice, snd_gf1_i_read16(gus, 9));
- dev_info(gus->card->dev,
- " -%i- GF1 position = 0x%x (0x%x)\n",
- voice, snd_gf1_i_read_addr(gus, 0x0a, ctrl & 4),
- snd_gf1_i_read_addr(gus, 0x0a, (ctrl & 4) ^ 4));
- if (gus->interwave && snd_gf1_i_read8(gus, 0x19) & 0x01) { /* enhanced mode */
- mode = snd_gf1_i_read8(gus, 0x15);
- dev_info(gus->card->dev,
- " -%i- GFA1 mode = 0x%x\n",
- voice, mode);
- if (mode & 0x01) { /* Effect processor */
- dev_info(gus->card->dev,
- " -%i- GFA1 effect address = 0x%x\n",
- voice, snd_gf1_i_read_addr(gus, 0x11, ctrl & 4));
- dev_info(gus->card->dev,
- " -%i- GFA1 effect volume = 0x%x\n",
- voice, snd_gf1_i_read16(gus, 0x16));
- dev_info(gus->card->dev,
- " -%i- GFA1 effect volume final = 0x%x\n",
- voice, snd_gf1_i_read16(gus, 0x1d));
- dev_info(gus->card->dev,
- " -%i- GFA1 effect accumulator = 0x%x\n",
- voice, snd_gf1_i_read8(gus, 0x14));
- }
- if (mode & 0x20) {
- dev_info(gus->card->dev,
- " -%i- GFA1 left offset = 0x%x (%i)\n",
- voice, snd_gf1_i_read16(gus, 0x13),
- snd_gf1_i_read16(gus, 0x13) >> 4);
- dev_info(gus->card->dev,
- " -%i- GFA1 left offset final = 0x%x (%i)\n",
- voice, snd_gf1_i_read16(gus, 0x1c),
- snd_gf1_i_read16(gus, 0x1c) >> 4);
- dev_info(gus->card->dev,
- " -%i- GFA1 right offset = 0x%x (%i)\n",
- voice, snd_gf1_i_read16(gus, 0x0c),
- snd_gf1_i_read16(gus, 0x0c) >> 4);
- dev_info(gus->card->dev,
- " -%i- GFA1 right offset final = 0x%x (%i)\n",
- voice, snd_gf1_i_read16(gus, 0x1b),
- snd_gf1_i_read16(gus, 0x1b) >> 4);
- } else
- dev_info(gus->card->dev,
- " -%i- GF1 pan = 0x%x\n",
- voice, snd_gf1_i_read8(gus, 0x0c));
- } else
- dev_info(gus->card->dev,
- " -%i- GF1 pan = 0x%x\n",
- voice, snd_gf1_i_read8(gus, 0x0c));
-}
-
-#if 0
-
-void snd_gf1_print_global_registers(struct snd_gus_card * gus)
-{
- unsigned char global_mode = 0x00;
-
- dev_info(gus->card->dev,
- " -G- GF1 active voices = 0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_ACTIVE_VOICES));
- if (gus->interwave) {
- global_mode = snd_gf1_i_read8(gus, SNDRV_GF1_GB_GLOBAL_MODE);
- dev_info(gus->card->dev,
- " -G- GF1 global mode = 0x%x\n",
- global_mode);
- }
- if (global_mode & 0x02) /* LFO enabled? */
- dev_info(gus->card->dev,
- " -G- GF1 LFO base = 0x%x\n",
- snd_gf1_i_look16(gus, SNDRV_GF1_GW_LFO_BASE));
- dev_info(gus->card->dev,
- " -G- GF1 voices IRQ read = 0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_VOICES_IRQ_READ));
- dev_info(gus->card->dev,
- " -G- GF1 DRAM DMA control = 0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_CONTROL));
- dev_info(gus->card->dev,
- " -G- GF1 DRAM DMA high/low = 0x%x/0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_DMA_HIGH),
- snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_DMA_LOW));
- dev_info(gus->card->dev,
- " -G- GF1 DRAM IO high/low = 0x%x/0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_DRAM_IO_HIGH),
- snd_gf1_i_read16(gus, SNDRV_GF1_GW_DRAM_IO_LOW));
- if (!gus->interwave)
- dev_info(gus->card->dev,
- " -G- GF1 record DMA control = 0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_REC_DMA_CONTROL));
- dev_info(gus->card->dev,
- " -G- GF1 DRAM IO 16 = 0x%x\n",
- snd_gf1_i_look16(gus, SNDRV_GF1_GW_DRAM_IO16));
- if (gus->gf1.enh_mode) {
- dev_info(gus->card->dev,
- " -G- GFA1 memory config = 0x%x\n",
- snd_gf1_i_look16(gus, SNDRV_GF1_GW_MEMORY_CONFIG));
- dev_info(gus->card->dev,
- " -G- GFA1 memory control = 0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_MEMORY_CONTROL));
- dev_info(gus->card->dev,
- " -G- GFA1 FIFO record base = 0x%x\n",
- snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_RECORD_BASE_ADDR));
- dev_info(gus->card->dev,
- " -G- GFA1 FIFO playback base = 0x%x\n",
- snd_gf1_i_look16(gus, SNDRV_GF1_GW_FIFO_PLAY_BASE_ADDR));
- dev_info(gus->card->dev,
- " -G- GFA1 interleave control = 0x%x\n",
- snd_gf1_i_look16(gus, SNDRV_GF1_GW_INTERLEAVE));
- }
-}
-
-void snd_gf1_print_setup_registers(struct snd_gus_card * gus)
-{
- dev_info(gus->card->dev,
- " -S- mix control = 0x%x\n",
- inb(GUSP(gus, MIXCNTRLREG)));
- dev_info(gus->card->dev,
- " -S- IRQ status = 0x%x\n",
- inb(GUSP(gus, IRQSTAT)));
- dev_info(gus->card->dev,
- " -S- timer control = 0x%x\n",
- inb(GUSP(gus, TIMERCNTRL)));
- dev_info(gus->card->dev,
- " -S- timer data = 0x%x\n",
- inb(GUSP(gus, TIMERDATA)));
- dev_info(gus->card->dev,
- " -S- status read = 0x%x\n",
- inb(GUSP(gus, REGCNTRLS)));
- dev_info(gus->card->dev,
- " -S- Sound Blaster control = 0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_SOUND_BLASTER_CONTROL));
- dev_info(gus->card->dev,
- " -S- AdLib timer 1/2 = 0x%x/0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_1),
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_ADLIB_TIMER_2));
- dev_info(gus->card->dev,
- " -S- reset = 0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_RESET));
- if (gus->interwave) {
- dev_info(gus->card->dev,
- " -S- compatibility = 0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_COMPATIBILITY));
- dev_info(gus->card->dev,
- " -S- decode control = 0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_DECODE_CONTROL));
- dev_info(gus->card->dev,
- " -S- version number = 0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_VERSION_NUMBER));
- dev_info(gus->card->dev,
- " -S- MPU-401 emul. control A/B = 0x%x/0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_A),
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_MPU401_CONTROL_B));
- dev_info(gus->card->dev,
- " -S- emulation IRQ = 0x%x\n",
- snd_gf1_i_look8(gus, SNDRV_GF1_GB_EMULATION_IRQ));
- }
-}
-#endif /* 0 */
-
-#endif
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index 51ce405eba7a..7166869e423d 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -22,18 +22,6 @@ MODULE_LICENSE("GPL");
static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches);
-int snd_gus_use_inc(struct snd_gus_card * gus)
-{
- if (!try_module_get(gus->card->module))
- return 0;
- return 1;
-}
-
-void snd_gus_use_dec(struct snd_gus_card * gus)
-{
- module_put(gus->card->module);
-}
-
static int snd_gus_joystick_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
@@ -443,8 +431,6 @@ EXPORT_SYMBOL(snd_gf1_new_mixer);
/* gus_pcm.c */
EXPORT_SYMBOL(snd_gf1_pcm_new);
/* gus.c */
-EXPORT_SYMBOL(snd_gus_use_inc);
-EXPORT_SYMBOL(snd_gus_use_dec);
EXPORT_SYMBOL(snd_gus_create);
EXPORT_SYMBOL(snd_gus_initialize);
/* gus_irq.c */
diff --git a/sound/isa/gus/gus_reset.c b/sound/isa/gus/gus_reset.c
index ac5da1281042..326bc6028885 100644
--- a/sound/isa/gus/gus_reset.c
+++ b/sound/isa/gus/gus_reset.c
@@ -141,10 +141,6 @@ void snd_gf1_stop_voice(struct snd_gus_card * gus, unsigned short voice)
if (gus->gf1.enh_mode)
snd_gf1_write8(gus, SNDRV_GF1_VB_ACCUMULATOR, 0);
spin_unlock_irqrestore(&gus->reg_lock, flags);
-#if 0
- snd_gf1_lfo_shutdown(gus, voice, ULTRA_LFO_VIBRATO);
- snd_gf1_lfo_shutdown(gus, voice, ULTRA_LFO_TREMOLO);
-#endif
}
static void snd_gf1_clear_voices(struct snd_gus_card * gus, unsigned short v_min,
@@ -182,10 +178,6 @@ static void snd_gf1_clear_voices(struct snd_gus_card * gus, unsigned short v_min
snd_gf1_write16(gus, SNDRV_GF1_VW_EFFECT_VOLUME_FINAL, 0);
}
spin_unlock_irqrestore(&gus->reg_lock, flags);
-#if 0
- snd_gf1_lfo_shutdown(gus, i, ULTRA_LFO_VIBRATO);
- snd_gf1_lfo_shutdown(gus, i, ULTRA_LFO_TREMOLO);
-#endif
}
}
@@ -335,9 +327,7 @@ int snd_gf1_start(struct snd_gus_card * gus)
} else {
gus->gf1.sw_lfo = 1;
}
-#if 0
- snd_gf1_lfo_init(gus);
-#endif
+
if (gus->gf1.memory > 0)
for (i = 0; i < 4; i++)
snd_gf1_poke(gus, gus->gf1.default_voice_address + i, 0);
@@ -391,8 +381,6 @@ int snd_gf1_stop(struct snd_gus_card * gus)
snd_gf1_i_write8(gus, SNDRV_GF1_GB_RESET, 1); /* disable IRQ & DAC */
snd_gf1_timers_done(gus);
snd_gf1_mem_done(gus);
-#if 0
- snd_gf1_lfo_done(gus);
-#endif
+
return 0;
}
diff --git a/sound/isa/msnd/Makefile b/sound/isa/msnd/Makefile
index 5f8d6b472722..d56412aae857 100644
--- a/sound/isa/msnd/Makefile
+++ b/sound/isa/msnd/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
-snd-msnd-lib-y := msnd.o msnd_midi.o msnd_pinnacle_mixer.o
+snd-msnd-lib-y := msnd.o msnd_pinnacle_mixer.o
snd-msnd-pinnacle-y := msnd_pinnacle.o
snd-msnd-classic-y := msnd_classic.o
diff --git a/sound/isa/msnd/msnd.h b/sound/isa/msnd/msnd.h
index 533d71cee9ba..3d7810ed9186 100644
--- a/sound/isa/msnd/msnd.h
+++ b/sound/isa/msnd/msnd.h
@@ -216,7 +216,6 @@ struct snd_msnd {
int captureLimit;
int capturePeriods;
struct snd_card *card;
- void *msndmidi_mpu;
struct snd_rawmidi *rmidi;
/* Hardware resources */
@@ -286,9 +285,6 @@ int snd_msnd_DAPQ(struct snd_msnd *chip, int start);
int snd_msnd_DARQ(struct snd_msnd *chip, int start);
int snd_msnd_pcm(struct snd_card *card, int device);
-int snd_msndmidi_new(struct snd_card *card, int device);
-void snd_msndmidi_input_read(void *mpu);
-
void snd_msndmix_setup(struct snd_msnd *chip);
int snd_msndmix_new(struct snd_card *card);
int snd_msndmix_force_recsrc(struct snd_msnd *chip, int recsrc);
diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c
deleted file mode 100644
index 3ffc8758bec2..000000000000
--- a/sound/isa/msnd/msnd_midi.c
+++ /dev/null
@@ -1,163 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
- * Copyright (c) 2009 by Krzysztof Helt
- * Routines for control of MPU-401 in UART mode
- *
- * MPU-401 supports UART mode which is not capable generate transmit
- * interrupts thus output is done via polling. Also, if irq < 0, then
- * input is done also via polling. Do not expect good performance.
- */
-
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <linux/export.h>
-#include <sound/core.h>
-#include <sound/rawmidi.h>
-
-#include "msnd.h"
-
-#define MSNDMIDI_MODE_BIT_INPUT 0
-#define MSNDMIDI_MODE_BIT_OUTPUT 1
-#define MSNDMIDI_MODE_BIT_INPUT_TRIGGER 2
-#define MSNDMIDI_MODE_BIT_OUTPUT_TRIGGER 3
-
-struct snd_msndmidi {
- struct snd_msnd *dev;
-
- unsigned long mode; /* MSNDMIDI_MODE_XXXX */
-
- struct snd_rawmidi_substream *substream_input;
-
- spinlock_t input_lock;
-};
-
-/*
- * input/output open/close - protected by open_mutex in rawmidi.c
- */
-static int snd_msndmidi_input_open(struct snd_rawmidi_substream *substream)
-{
- struct snd_msndmidi *mpu;
-
- mpu = substream->rmidi->private_data;
-
- mpu->substream_input = substream;
-
- snd_msnd_enable_irq(mpu->dev);
-
- snd_msnd_send_dsp_cmd(mpu->dev, HDEX_MIDI_IN_START);
- set_bit(MSNDMIDI_MODE_BIT_INPUT, &mpu->mode);
- return 0;
-}
-
-static int snd_msndmidi_input_close(struct snd_rawmidi_substream *substream)
-{
- struct snd_msndmidi *mpu;
-
- mpu = substream->rmidi->private_data;
- snd_msnd_send_dsp_cmd(mpu->dev, HDEX_MIDI_IN_STOP);
- clear_bit(MSNDMIDI_MODE_BIT_INPUT, &mpu->mode);
- mpu->substream_input = NULL;
- snd_msnd_disable_irq(mpu->dev);
- return 0;
-}
-
-static void snd_msndmidi_input_drop(struct snd_msndmidi *mpu)
-{
- u16 tail;
-
- tail = readw(mpu->dev->MIDQ + JQS_wTail);
- writew(tail, mpu->dev->MIDQ + JQS_wHead);
-}
-
-/*
- * trigger input
- */
-static void snd_msndmidi_input_trigger(struct snd_rawmidi_substream *substream,
- int up)
-{
- unsigned long flags;
- struct snd_msndmidi *mpu;
-
- mpu = substream->rmidi->private_data;
- spin_lock_irqsave(&mpu->input_lock, flags);
- if (up) {
- if (!test_and_set_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER,
- &mpu->mode))
- snd_msndmidi_input_drop(mpu);
- } else {
- clear_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
- }
- spin_unlock_irqrestore(&mpu->input_lock, flags);
- if (up)
- snd_msndmidi_input_read(mpu);
-}
-
-void snd_msndmidi_input_read(void *mpuv)
-{
- unsigned long flags;
- struct snd_msndmidi *mpu = mpuv;
- void __iomem *pwMIDQData = mpu->dev->mappedbase + MIDQ_DATA_BUFF;
- u16 head, tail, size;
-
- spin_lock_irqsave(&mpu->input_lock, flags);
- head = readw(mpu->dev->MIDQ + JQS_wHead);
- tail = readw(mpu->dev->MIDQ + JQS_wTail);
- size = readw(mpu->dev->MIDQ + JQS_wSize);
- if (head > size || tail > size)
- goto out;
- while (head != tail) {
- unsigned char val = readw(pwMIDQData + 2 * head);
-
- if (test_bit(MSNDMIDI_MODE_BIT_INPUT_TRIGGER, &mpu->mode))
- snd_rawmidi_receive(mpu->substream_input, &val, 1);
- if (++head > size)
- head = 0;
- writew(head, mpu->dev->MIDQ + JQS_wHead);
- }
- out:
- spin_unlock_irqrestore(&mpu->input_lock, flags);
-}
-EXPORT_SYMBOL(snd_msndmidi_input_read);
-
-static const struct snd_rawmidi_ops snd_msndmidi_input = {
- .open = snd_msndmidi_input_open,
- .close = snd_msndmidi_input_close,
- .trigger = snd_msndmidi_input_trigger,
-};
-
-static void snd_msndmidi_free(struct snd_rawmidi *rmidi)
-{
- struct snd_msndmidi *mpu = rmidi->private_data;
- kfree(mpu);
-}
-
-int snd_msndmidi_new(struct snd_card *card, int device)
-{
- struct snd_msnd *chip = card->private_data;
- struct snd_msndmidi *mpu;
- struct snd_rawmidi *rmidi;
- int err;
-
- err = snd_rawmidi_new(card, "MSND-MIDI", device, 1, 1, &rmidi);
- if (err < 0)
- return err;
- mpu = kzalloc(sizeof(*mpu), GFP_KERNEL);
- if (mpu == NULL) {
- snd_device_free(card, rmidi);
- return -ENOMEM;
- }
- mpu->dev = chip;
- chip->msndmidi_mpu = mpu;
- rmidi->private_data = mpu;
- rmidi->private_free = snd_msndmidi_free;
- spin_lock_init(&mpu->input_lock);
- strcpy(rmidi->name, "MSND MIDI");
- snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
- &snd_msndmidi_input);
- rmidi->info_flags |= SNDRV_RAWMIDI_INFO_INPUT;
- return 0;
-}
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c
index 635403301a15..8caf431677e5 100644
--- a/sound/isa/msnd/msnd_pinnacle.c
+++ b/sound/isa/msnd/msnd_pinnacle.c
@@ -142,11 +142,6 @@ static void snd_msnd_eval_dsp_msg(struct snd_msnd *chip, u16 wMessage)
}
break;
- case HIMT_MIDI_IN_UCHAR:
- if (chip->msndmidi_mpu)
- snd_msndmidi_input_read(chip->msndmidi_mpu);
- break;
-
default:
dev_dbg(chip->card->dev, LOGNAME ": HIMT message %d 0x%02x\n",
HIBYTE(wMessage), HIBYTE(wMessage));
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index 52884e6b9193..312b217491d4 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -14,6 +14,7 @@
#include <linux/export.h>
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/emu8000.h>
#include <sound/emu8000_reg.h>
@@ -1096,7 +1097,7 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
#if IS_ENABLED(CONFIG_SND_SEQUENCER)
if (snd_seq_device_new(card, index, SNDRV_SEQ_DEV_ID_EMU8000,
sizeof(struct snd_emu8000*), &awe) >= 0) {
- strcpy(awe->name, "EMU-8000");
+ strscpy(awe->name, "EMU-8000");
*(struct snd_emu8000 **)SNDRV_SEQ_DEVICE_ARGPTR(awe) = hw;
}
#else
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c
index b28490973892..69d9bfb6c14c 100644
--- a/sound/isa/sb/jazz16.c
+++ b/sound/isa/sb/jazz16.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/io.h>
#include <linux/delay.h>
+#include <linux/string.h>
#include <asm/dma.h>
#include <linux/isa.h>
#include <sound/core.h>
@@ -286,8 +287,8 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
jazz16->chip = chip;
- strcpy(card->driver, "jazz16");
- strcpy(card->shortname, "Media Vision Jazz16");
+ strscpy(card->driver, "jazz16");
+ strscpy(card->shortname, "Media Vision Jazz16");
sprintf(card->longname,
"Media Vision Jazz16 at 0x%lx, irq %d, dma8 %d, dma16 %d",
port[dev], xirq, xdma8, xdma16);
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 2f7505ad855c..752762117338 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -10,6 +10,7 @@
#include <linux/err.h>
#include <linux/isa.h>
#include <linux/module.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/sb.h>
#include <sound/sb16_csp.h>
@@ -337,12 +338,12 @@ static int snd_sb16_probe(struct snd_card *card, int dev)
if (err < 0)
return err;
- strcpy(card->driver,
+ strscpy(card->driver,
#ifdef SNDRV_SBAWE_EMU8000
awe_port[dev] > 0 ? "SB AWE" :
#endif
"SB16");
- strcpy(card->shortname, chip->name);
+ strscpy(card->shortname, chip->name);
sprintf(card->longname, "%s at 0x%lx, irq %i, dma ",
chip->name,
chip->port,
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index 8726778c815e..6d5131265913 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -9,6 +9,7 @@
#include <linux/isa.h>
#include <linux/ioport.h>
#include <linux/module.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/sb.h>
#include <sound/opl3.h>
@@ -162,8 +163,8 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
if (err < 0)
return err;
- strcpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8");
- strcpy(card->shortname, chip->name);
+ strscpy(card->driver, chip->hardware == SB_HW_PRO ? "SB Pro" : "SB8");
+ strscpy(card->shortname, chip->name);
sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
chip->name,
chip->port,
diff --git a/sound/isa/sb/sb8_midi.c b/sound/isa/sb/sb8_midi.c
index d2908fc280f8..57867e51d367 100644
--- a/sound/isa/sb/sb8_midi.c
+++ b/sound/isa/sb/sb8_midi.c
@@ -14,6 +14,7 @@
*/
#include <linux/io.h>
+#include <linux/string.h>
#include <linux/time.h>
#include <sound/core.h>
#include <sound/sb.h>
@@ -254,7 +255,7 @@ int snd_sb8dsp_midi(struct snd_sb *chip, int device)
err = snd_rawmidi_new(chip->card, "SB8 MIDI", device, 1, 1, &rmidi);
if (err < 0)
return err;
- strcpy(rmidi->name, "SB8 MIDI");
+ strscpy(rmidi->name, "SB8 MIDI");
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_sb8dsp_midi_output);
snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_sb8dsp_midi_input);
rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT;
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c
index 9d23b7a4570b..b2709ed134b4 100644
--- a/sound/isa/sb/sb_mixer.c
+++ b/sound/isa/sb/sb_mixer.c
@@ -6,6 +6,7 @@
#include <linux/io.h>
#include <linux/delay.h>
+#include <linux/string.h>
#include <linux/time.h>
#include <sound/core.h>
#include <sound/sb.h>
@@ -718,7 +719,7 @@ static int snd_sbmixer_init(struct snd_sb *chip,
return err;
}
snd_component_add(card, name);
- strcpy(card->mixername, name);
+ strscpy(card->mixername, name);
return 0;
}
@@ -799,7 +800,7 @@ int snd_sbmixer_new(struct snd_sb *chip)
return err;
break;
default:
- strcpy(card->mixername, "???");
+ strscpy(card->mixername, "???");
}
return 0;
}
diff --git a/sound/mips/snd-n64.c b/sound/mips/snd-n64.c
index bff6d85b8fe2..e1b2ff65d850 100644
--- a/sound/mips/snd-n64.c
+++ b/sound/mips/snd-n64.c
@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
+#include <linux/string.h>
#include <sound/control.h>
#include <sound/core.h>
@@ -327,14 +328,14 @@ static int __init n64audio_probe(struct platform_device *pdev)
goto fail_dma_alloc;
pcm->private_data = priv;
- strcpy(pcm->name, "N64 Audio");
+ strscpy(pcm->name, "N64 Audio");
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &n64audio_pcm_ops);
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, card->dev, 0, 0);
- strcpy(card->driver, "N64 Audio");
- strcpy(card->shortname, "N64 Audio");
- strcpy(card->longname, "N64 Audio");
+ strscpy(card->driver, "N64 Audio");
+ strscpy(card->shortname, "N64 Audio");
+ strscpy(card->longname, "N64 Audio");
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index 9ed778b6b03c..ac27a93ce4ff 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -810,12 +810,11 @@ snd_ad1889_create(struct snd_card *card, struct pci_dev *pci)
chip->irq = -1;
/* (1) PCI resource allocation */
- err = pcim_iomap_regions(pci, 1 << 0, card->driver);
- if (err < 0)
- return err;
+ chip->iobase = pcim_iomap_region(pci, 0, card->driver);
+ if (IS_ERR(chip->iobase))
+ return PTR_ERR(chip->iobase);
chip->bar = pci_resource_start(pci, 0);
- chip->iobase = pcim_iomap_table(pci)[0];
pci_set_master(pci);
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 793d2f13267e..69c02bdd38ce 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -1688,7 +1688,7 @@ static int snd_ali_build_pcms(struct snd_ali *codec)
static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_ali *codec = kcontrol->private_data;
+ struct snd_ali *codec = snd_kcontrol_chip(kcontrol);
unsigned int spdif_enable;
spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0;
@@ -1716,7 +1716,7 @@ static int snd_ali5451_spdif_get(struct snd_kcontrol *kcontrol,
static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_ali *codec = kcontrol->private_data;
+ struct snd_ali *codec = snd_kcontrol_chip(kcontrol);
unsigned int change = 0, spdif_enable = 0;
spdif_enable = ucontrol->value.integer.value[0] ? 1 : 0;
@@ -1989,7 +1989,7 @@ static int snd_ali_resources(struct snd_ali *codec)
int err;
dev_dbg(codec->card->dev, "resources allocation ...\n");
- err = pci_request_regions(codec->pci, "ALI 5451");
+ err = pcim_request_all_regions(codec->pci, "ALI 5451");
if (err < 0)
return err;
codec->port = pci_resource_start(codec->pci, 0);
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index c7c481203ef8..43f98719e61b 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -617,7 +617,7 @@ static int snd_als300_create(struct snd_card *card,
chip->chip_type = chip_type;
spin_lock_init(&chip->reg_lock);
- err = pci_request_regions(pci, "ALS300");
+ err = pcim_request_all_regions(pci, "ALS300");
if (err < 0)
return err;
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 022473594c73..3f4f3037f71f 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -836,7 +836,7 @@ static int __snd_card_als4000_probe(struct pci_dev *pci,
return -ENXIO;
}
- err = pci_request_regions(pci, "ALS4000");
+ err = pcim_request_all_regions(pci, "ALS4000");
if (err < 0)
return err;
iobase = pci_resource_start(pci, 0);
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index 65100f925b72..7e5ce96954b9 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -2300,8 +2300,7 @@ static const char * const sampleclock_sources[] = {
static int snd_asihpi_clksrc_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- struct snd_card_asihpi *asihpi =
- (struct snd_card_asihpi *)(kcontrol->private_data);
+ struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);
struct clk_cache *clkcache = &asihpi->cc;
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
@@ -2319,8 +2318,7 @@ static int snd_asihpi_clksrc_info(struct snd_kcontrol *kcontrol,
static int snd_asihpi_clksrc_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_card_asihpi *asihpi =
- (struct snd_card_asihpi *)(kcontrol->private_data);
+ struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);
struct clk_cache *clkcache = &asihpi->cc;
u32 h_control = kcontrol->private_value;
u16 source, srcindex = 0;
@@ -2347,8 +2345,7 @@ static int snd_asihpi_clksrc_get(struct snd_kcontrol *kcontrol,
static int snd_asihpi_clksrc_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_card_asihpi *asihpi =
- (struct snd_card_asihpi *)(kcontrol->private_data);
+ struct snd_card_asihpi *asihpi = snd_kcontrol_chip(kcontrol);
struct clk_cache *clkcache = &asihpi->cc;
unsigned int item;
int change;
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index df2fef726d60..427006be240b 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -1544,11 +1544,10 @@ static int snd_atiixp_init(struct snd_card *card, struct pci_dev *pci)
chip->card = card;
chip->pci = pci;
chip->irq = -1;
- err = pcim_iomap_regions(pci, 1 << 0, "ATI IXP AC97");
- if (err < 0)
- return err;
+ chip->remap_addr = pcim_iomap_region(pci, 0, "ATI IXP AC97");
+ if (IS_ERR(chip->remap_addr))
+ return PTR_ERR(chip->remap_addr);
chip->addr = pci_resource_start(pci, 0);
- chip->remap_addr = pcim_iomap_table(pci)[0];
if (devm_request_irq(&pci->dev, pci->irq, snd_atiixp_interrupt,
IRQF_SHARED, KBUILD_MODNAME, chip)) {
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index eb569539f322..8d3083b9b024 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1174,11 +1174,10 @@ static int snd_atiixp_init(struct snd_card *card, struct pci_dev *pci)
chip->card = card;
chip->pci = pci;
chip->irq = -1;
- err = pcim_iomap_regions(pci, 1 << 0, "ATI IXP MC97");
- if (err < 0)
- return err;
+ chip->remap_addr = pcim_iomap_region(pci, 0, "ATI IXP MC97");
+ if (IS_ERR(chip->remap_addr))
+ return PTR_ERR(chip->remap_addr);
chip->addr = pci_resource_start(pci, 0);
- chip->remap_addr = pcim_iomap_table(pci)[0];
if (devm_request_irq(&pci->dev, pci->irq, snd_atiixp_interrupt,
IRQF_SHARED, KBUILD_MODNAME, chip)) {
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index 62b10b0e07b1..fd986247331a 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -160,12 +160,11 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci)
// (1) PCI resource allocation
// Get MMIO area
//
- err = pcim_iomap_regions(pci, 1 << 0, CARD_NAME_SHORT);
- if (err)
- return err;
+ chip->mmio = pcim_iomap_region(pci, 0, KBUILD_MODNAME);
+ if (IS_ERR(chip->mmio))
+ return PTR_ERR(chip->mmio);
chip->io = pci_resource_start(pci, 0);
- chip->mmio = pcim_iomap_table(pci)[0];
/* Init audio core.
* This must be done before we do request_irq otherwise we can get spurious
diff --git a/sound/pci/au88x0/au88x0_a3d.c b/sound/pci/au88x0/au88x0_a3d.c
index eabaee0463fe..d5cafaa229f1 100644
--- a/sound/pci/au88x0/au88x0_a3d.c
+++ b/sound/pci/au88x0/au88x0_a3d.c
@@ -754,7 +754,7 @@ snd_vortex_a3d_filter_info(struct snd_kcontrol *kcontrol,
static int
snd_vortex_a3d_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
- //a3dsrc_t *a = kcontrol->private_data;
+ //a3dsrc_t *a = snd_kcontrol_chip(kcontrol);
/* No read yet. Would this be really useable/needed ? */
return 0;
@@ -764,7 +764,7 @@ static int
snd_vortex_a3d_hrtf_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- a3dsrc_t *a = kcontrol->private_data;
+ a3dsrc_t *a = snd_kcontrol_chip(kcontrol);
int i;
int coord[6];
for (i = 0; i < 6; i++)
@@ -781,7 +781,7 @@ static int
snd_vortex_a3d_itd_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- a3dsrc_t *a = kcontrol->private_data;
+ a3dsrc_t *a = snd_kcontrol_chip(kcontrol);
int coord[6];
int i;
for (i = 0; i < 6; i++)
@@ -800,7 +800,7 @@ static int
snd_vortex_a3d_ild_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- a3dsrc_t *a = kcontrol->private_data;
+ a3dsrc_t *a = snd_kcontrol_chip(kcontrol);
int l, r;
/* There may be some scale tranlation needed here. */
l = ucontrol->value.integer.value[0];
@@ -816,7 +816,7 @@ static int
snd_vortex_a3d_filter_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- a3dsrc_t *a = kcontrol->private_data;
+ a3dsrc_t *a = snd_kcontrol_chip(kcontrol);
int i;
int params[6];
for (i = 0; i < 6; i++)
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index 29a4bcdec237..7b4b8f785517 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -225,11 +225,10 @@ static int snd_aw2_create(struct snd_card *card,
chip->irq = -1;
/* (1) PCI resource allocation */
- err = pcim_iomap_regions(pci, 1 << 0, "Audiowerk2");
- if (err < 0)
- return err;
+ chip->iobase_virt = pcim_iomap_region(pci, 0, "Audiowerk2");
+ if (IS_ERR(chip->iobase_virt))
+ return PTR_ERR(chip->iobase_virt);
chip->iobase_phys = pci_resource_start(pci, 0);
- chip->iobase_virt = pcim_iomap_table(pci)[0];
/* (2) initialization of the chip hardware */
snd_aw2_saa7146_setup(&chip->saa7146, chip->iobase_virt);
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 8a895d838005..053a18f434bf 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -2347,7 +2347,7 @@ snd_azf3328_create(struct snd_card *card,
return -ENXIO;
}
- err = pci_request_regions(pci, "Aztech AZF3328");
+ err = pcim_request_all_regions(pci, "Aztech AZF3328");
if (err < 0)
return err;
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 621985bfee5d..91492dd2b38a 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -696,10 +696,9 @@ static int snd_bt87x_create(struct snd_card *card,
chip->irq = -1;
spin_lock_init(&chip->reg_lock);
- err = pcim_iomap_regions(pci, 1 << 0, "Bt87x audio");
- if (err < 0)
- return err;
- chip->mmio = pcim_iomap_table(pci)[0];
+ chip->mmio = pcim_iomap_region(pci, 0, "Bt87x audio");
+ if (IS_ERR(chip->mmio))
+ return PTR_ERR(chip->mmio);
chip->reg_control = CTL_A_PWRDN | CTL_DA_ES2 |
CTL_PKTP_16 | (15 << CTL_DA_SDR_SHIFT);
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index cf1bac7a435f..7c7119cad63c 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1593,7 +1593,7 @@ static int snd_ca0106_create(int dev, struct snd_card *card,
spin_lock_init(&chip->emu_lock);
- err = pci_request_regions(pci, "snd_ca0106");
+ err = pcim_request_all_regions(pci, "snd_ca0106");
if (err < 0)
return err;
chip->port = pci_resource_start(pci, 0);
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index cb8593c376ee..b00df0a60d3f 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -2980,7 +2980,7 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
cm->channel[1].ch = 1;
cm->channel[0].is_dac = cm->channel[1].is_dac = 1; /* dual DAC mode */
- err = pci_request_regions(pci, card->driver);
+ err = pcim_request_all_regions(pci, card->driver);
if (err < 0)
return err;
cm->iobase = pci_resource_start(pci, 0);
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 0cc86e73cc62..90958a422b75 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1302,14 +1302,15 @@ static int snd_cs4281_create(struct snd_card *card,
}
chip->dual_codec = dual_codec;
- err = pcim_iomap_regions(pci, 0x03, "CS4281"); /* 2 BARs */
- if (err < 0)
- return err;
+ chip->ba0 = pcim_iomap_region(pci, 0, "CS4281");
+ if (IS_ERR(chip->ba0))
+ return PTR_ERR(chip->ba0);
chip->ba0_addr = pci_resource_start(pci, 0);
- chip->ba1_addr = pci_resource_start(pci, 1);
- chip->ba0 = pcim_iomap_table(pci)[0];
- chip->ba1 = pcim_iomap_table(pci)[1];
+ chip->ba1 = pcim_iomap_region(pci, 1, "CS4281");
+ if (IS_ERR(chip->ba1))
+ return PTR_ERR(chip->ba1);
+ chip->ba1_addr = pci_resource_start(pci, 1);
if (devm_request_irq(&pci->dev, pci->irq, snd_cs4281_interrupt,
IRQF_SHARED, KBUILD_MODNAME, chip)) {
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index f3a94bb537bd..fb733633740b 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -3839,7 +3839,7 @@ int snd_cs46xx_create(struct snd_card *card,
chip->pci = pci;
chip->irq = -1;
- err = pci_request_regions(pci, "CS46xx");
+ err = pcim_request_all_regions(pci, "CS46xx");
if (err < 0)
return err;
chip->ba0_addr = pci_resource_start(pci, 0);
diff --git a/sound/pci/cs46xx/dsp_spos_scb_lib.c b/sound/pci/cs46xx/dsp_spos_scb_lib.c
index 1f90ca723f4d..28faca268196 100644
--- a/sound/pci/cs46xx/dsp_spos_scb_lib.c
+++ b/sound/pci/cs46xx/dsp_spos_scb_lib.c
@@ -201,13 +201,6 @@ void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor *
if (ins->scb_highest_frag_index > ins->nscb) {
ins->scb_highest_frag_index = ins->nscb;
}
-
-#if 0
- /* !!!! THIS IS A PIECE OF SHIT MADE BY ME !!! */
- for(i = scb->index + 1;i < ins->nscb; ++i) {
- ins->scbs[i - 1].index = i - 1;
- }
-#endif
}
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c
index 93ff029e6583..532891e67c34 100644
--- a/sound/pci/cs5530.c
+++ b/sound/pci/cs5530.c
@@ -91,11 +91,10 @@ static int snd_cs5530_create(struct snd_card *card,
chip->card = card;
chip->pci = pci;
- err = pcim_iomap_regions(pci, 1 << 0, "CS5530");
- if (err < 0)
- return err;
+ mem = pcim_iomap_region(pci, 0, "CS5530");
+ if (IS_ERR(mem))
+ return PTR_ERR(mem);
chip->pci_base = pci_resource_start(pci, 0);
- mem = pcim_iomap_table(pci)[0];
map = readw(mem + 0x18);
/* Map bits
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 440b8f9b40c9..0f319013a2a2 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -262,7 +262,7 @@ static int snd_cs5535audio_create(struct snd_card *card,
cs5535au->pci = pci;
cs5535au->irq = -1;
- err = pci_request_regions(pci, "CS5535 Audio");
+ err = pcim_request_all_regions(pci, "CS5535 Audio");
if (err < 0)
return err;
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 4effcc0090ac..80d8ce75fdbb 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -1910,7 +1910,7 @@ static int snd_echo_create(struct snd_card *card,
chip->can_set_rate = 1;
/* PCI resource allocation */
- err = pci_request_regions(pci, ECHOCARD_NAME);
+ err = pcim_request_all_regions(pci, ECHOCARD_NAME);
if (err < 0)
return err;
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 5b8a5ba825bd..bbe252b8916c 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -1563,7 +1563,7 @@ int snd_emu10k1_create(struct snd_card *card,
else
emu->gpr_base = FXGPREGBASE;
- err = pci_request_regions(pci, "EMU10K1");
+ err = pcim_request_all_regions(pci, "EMU10K1");
if (err < 0)
return err;
emu->port = pci_resource_start(pci, 0);
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 89043392f3ec..30ac37b5a214 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -884,7 +884,7 @@ static int snd_emu10k1x_create(struct snd_card *card,
spin_lock_init(&chip->emu_lock);
spin_lock_init(&chip->voice_lock);
- err = pci_request_regions(pci, "EMU10K1X");
+ err = pcim_request_all_regions(pci, "EMU10K1X");
if (err < 0)
return err;
chip->port = pci_resource_start(pci, 0);
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 71c89e4e3090..1e6adf1ae304 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -2022,7 +2022,7 @@ static int snd_ensoniq_create(struct snd_card *card,
ensoniq->card = card;
ensoniq->pci = pci;
ensoniq->irq = -1;
- err = pci_request_regions(pci, "Ensoniq AudioPCI");
+ err = pcim_request_all_regions(pci, "Ensoniq AudioPCI");
if (err < 0)
return err;
ensoniq->port = pci_resource_start(pci, 0);
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 018a8d53ca53..27728bdfac57 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1531,7 +1531,7 @@ static int snd_es1938_create(struct snd_card *card,
chip->card = card;
chip->pci = pci;
chip->irq = -1;
- err = pci_request_regions(pci, "ESS Solo-1");
+ err = pcim_request_all_regions(pci, "ESS Solo-1");
if (err < 0)
return err;
chip->io_port = pci_resource_start(pci, 0);
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 4e0693f0ab0f..37bac890613e 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -2649,7 +2649,7 @@ static int snd_es1968_create(struct snd_card *card,
chip->playback_streams = play_streams;
chip->capture_streams = capt_streams;
- err = pci_request_regions(pci, "ESS Maestro");
+ err = pcim_request_all_regions(pci, "ESS Maestro");
if (err < 0)
return err;
chip->io_port = pci_resource_start(pci, 0);
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 7f4834c2d5e6..f283256eda0d 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1191,7 +1191,7 @@ static int snd_fm801_create(struct snd_card *card,
chip->dev = &pci->dev;
chip->irq = -1;
chip->tea575x_tuner = tea575x_tuner;
- err = pci_request_regions(pci, "FM801");
+ err = pcim_request_all_regions(pci, "FM801");
if (err < 0)
return err;
chip->port = pci_resource_start(pci, 0);
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 9c427270ff4f..745f120a5cee 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -42,6 +42,17 @@ config SND_HDA_TEGRA
To compile this driver as a module, choose M here: the module
will be called snd-hda-tegra.
+config SND_HDA_ACPI
+ tristate "HD Audio ACPI"
+ depends on ACPI
+ select SND_HDA
+ help
+ Say Y here to include support for Azalia-compatible HDA controllers
+ which are advertised via ACPI objects.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-hda-acpi.
+
if SND_HDA
config SND_HDA_HWDEP
@@ -109,9 +120,6 @@ config SND_HDA_SCODEC_CS35L41
tristate
select SND_HDA_GENERIC
select REGMAP_IRQ
-
-config SND_HDA_CS_DSP_CONTROLS
- tristate
select FW_CS_DSP
config SND_HDA_SCODEC_COMPONENT
@@ -125,7 +133,6 @@ config SND_HDA_SCODEC_CS35L41_I2C
depends on SND_SOC
select SND_SOC_CS35L41_LIB
select SND_HDA_SCODEC_CS35L41
- select SND_HDA_CS_DSP_CONTROLS
select SND_SOC_CS_AMP_LIB
help
Say Y or M here to include CS35L41 I2C HD-audio side codec support
@@ -142,7 +149,6 @@ config SND_HDA_SCODEC_CS35L41_SPI
depends on SND_SOC
select SND_SOC_CS35L41_LIB
select SND_HDA_SCODEC_CS35L41
- select SND_HDA_CS_DSP_CONTROLS
select SND_SOC_CS_AMP_LIB
help
Say Y or M here to include CS35L41 SPI HD-audio side codec support
@@ -157,7 +163,7 @@ config SND_HDA_SCODEC_CS35L56
config SND_HDA_SCODEC_CS35L56_I2C
tristate "Build CS35L56 HD-audio side codec support for I2C Bus"
depends on I2C
- depends on ACPI || COMPILE_TEST
+ depends on ACPI
depends on SND_SOC
select FW_CS_DSP
imply SERIAL_MULTI_INSTANTIATE
@@ -165,7 +171,6 @@ config SND_HDA_SCODEC_CS35L56_I2C
select SND_SOC_CS35L56_SHARED
select SND_HDA_SCODEC_CS35L56
select SND_HDA_CIRRUS_SCODEC
- select SND_HDA_CS_DSP_CONTROLS
select SND_SOC_CS_AMP_LIB
help
Say Y or M here to include CS35L56 amplifier support with
@@ -174,7 +179,7 @@ config SND_HDA_SCODEC_CS35L56_I2C
config SND_HDA_SCODEC_CS35L56_SPI
tristate "Build CS35L56 HD-audio side codec support for SPI Bus"
depends on SPI_MASTER
- depends on ACPI || COMPILE_TEST
+ depends on ACPI
depends on SND_SOC
select FW_CS_DSP
imply SERIAL_MULTI_INSTANTIATE
@@ -182,19 +187,23 @@ config SND_HDA_SCODEC_CS35L56_SPI
select SND_SOC_CS35L56_SHARED
select SND_HDA_SCODEC_CS35L56
select SND_HDA_CIRRUS_SCODEC
- select SND_HDA_CS_DSP_CONTROLS
select SND_SOC_CS_AMP_LIB
help
Say Y or M here to include CS35L56 amplifier support with
SPI control.
+config SND_HDA_SCODEC_TAS2781
+ tristate
+ select SND_HDA_GENERIC
+
config SND_HDA_SCODEC_TAS2781_I2C
tristate "Build TAS2781 HD-audio side codec support for I2C Bus"
depends on I2C
depends on ACPI
depends on EFI
depends on SND_SOC
- select SND_SOC_TAS2781_COMLIB
+ select SND_HDA_SCODEC_TAS2781
+ select SND_SOC_TAS2781_COMLIB_I2C
select SND_SOC_TAS2781_FMWLIB
select CRC32
help
@@ -210,6 +219,10 @@ config SND_HDA_SCODEC_TAS2781_SPI
depends on ACPI
depends on EFI
depends on SND_SOC
+ select SND_HDA_SCODEC_TAS2781
+ select SND_SOC_TAS2781_COMLIB
+ select SND_SOC_TAS2781_FMWLIB
+ select CRC8
select CRC32
help
Say Y or M here to include TAS2781 SPI HD-audio side codec support
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 210c406dfbc5..a5ab8ee2d7f9 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
snd-hda-intel-y := hda_intel.o
snd-hda-tegra-y := hda_tegra.o
+snd-hda-acpi-y := hda_acpi.o
snd-hda-codec-y := hda_bind.o hda_codec.o hda_jack.o hda_auto_parser.o hda_sysfs.o
snd-hda-codec-y += hda_controller.o
@@ -37,10 +38,10 @@ snd-hda-scodec-cs35l41-spi-y := cs35l41_hda_spi.o
snd-hda-scodec-cs35l56-y := cs35l56_hda.o
snd-hda-scodec-cs35l56-i2c-y := cs35l56_hda_i2c.o
snd-hda-scodec-cs35l56-spi-y := cs35l56_hda_spi.o
-snd-hda-cs-dsp-ctls-y := hda_cs_dsp_ctl.o
snd-hda-scodec-component-y := hda_component.o
+snd-hda-scodec-tas2781-y := tas2781_hda.o
snd-hda-scodec-tas2781-i2c-y := tas2781_hda_i2c.o
-snd-hda-scodec-tas2781-spi-y := tas2781_hda_spi.o tas2781_spi_fwlib.o
+snd-hda-scodec-tas2781-spi-y := tas2781_hda_spi.o
# common driver
obj-$(CONFIG_SND_HDA) := snd-hda-codec.o
@@ -70,8 +71,8 @@ obj-$(CONFIG_SND_HDA_SCODEC_CS35L41_SPI) += snd-hda-scodec-cs35l41-spi.o
obj-$(CONFIG_SND_HDA_SCODEC_CS35L56) += snd-hda-scodec-cs35l56.o
obj-$(CONFIG_SND_HDA_SCODEC_CS35L56_I2C) += snd-hda-scodec-cs35l56-i2c.o
obj-$(CONFIG_SND_HDA_SCODEC_CS35L56_SPI) += snd-hda-scodec-cs35l56-spi.o
-obj-$(CONFIG_SND_HDA_CS_DSP_CONTROLS) += snd-hda-cs-dsp-ctls.o
obj-$(CONFIG_SND_HDA_SCODEC_COMPONENT) += snd-hda-scodec-component.o
+obj-$(CONFIG_SND_HDA_SCODEC_TAS2781) += snd-hda-scodec-tas2781.o
obj-$(CONFIG_SND_HDA_SCODEC_TAS2781_I2C) += snd-hda-scodec-tas2781-i2c.o
obj-$(CONFIG_SND_HDA_SCODEC_TAS2781_SPI) += snd-hda-scodec-tas2781-spi.o
@@ -80,3 +81,4 @@ obj-$(CONFIG_SND_HDA_SCODEC_TAS2781_SPI) += snd-hda-scodec-tas2781-spi.o
# when built in kernel
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o
obj-$(CONFIG_SND_HDA_TEGRA) += snd-hda-tegra.o
+obj-$(CONFIG_SND_HDA_ACPI) += snd-hda-acpi.o
diff --git a/sound/pci/hda/cirrus_scodec_test.c b/sound/pci/hda/cirrus_scodec_test.c
index 08b0bde1a461..93b9cbf1f08a 100644
--- a/sound/pci/hda/cirrus_scodec_test.c
+++ b/sound/pci/hda/cirrus_scodec_test.c
@@ -5,20 +5,30 @@
// Copyright (C) 2023 Cirrus Logic, Inc. and
// Cirrus Logic International Semiconductor Ltd.
+#include <kunit/platform_device.h>
+#include <kunit/resource.h>
#include <kunit/test.h>
+#include <linux/device.h>
+#include <linux/device/faux.h>
#include <linux/gpio/driver.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include "cirrus_scodec.h"
+KUNIT_DEFINE_ACTION_WRAPPER(faux_device_destroy_wrapper, faux_device_destroy,
+ struct faux_device *)
+KUNIT_DEFINE_ACTION_WRAPPER(device_remove_software_node_wrapper,
+ device_remove_software_node,
+ struct device *)
+
struct cirrus_scodec_test_gpio {
unsigned int pin_state;
struct gpio_chip chip;
};
struct cirrus_scodec_test_priv {
- struct platform_device amp_pdev;
+ struct faux_device *amp_dev;
struct platform_device *gpio_pdev;
struct cirrus_scodec_test_gpio *gpio_priv;
};
@@ -104,6 +114,7 @@ static int cirrus_scodec_test_gpio_probe(struct platform_device *pdev)
static struct platform_driver cirrus_scodec_test_gpio_driver = {
.driver.name = "cirrus_scodec_test_gpio_drv",
+ .driver.owner = THIS_MODULE,
.probe = cirrus_scodec_test_gpio_probe,
};
@@ -112,37 +123,28 @@ static const struct software_node cirrus_scodec_test_gpio_swnode = {
.name = "cirrus_scodec_test_gpio",
};
-static int cirrus_scodec_test_create_gpio(struct kunit *test)
+static void cirrus_scodec_test_create_gpio(struct kunit *test)
{
struct cirrus_scodec_test_priv *priv = test->priv;
- int ret;
- priv->gpio_pdev = platform_device_alloc(cirrus_scodec_test_gpio_driver.driver.name, -1);
- if (!priv->gpio_pdev)
- return -ENOMEM;
+ KUNIT_ASSERT_EQ(test, 0,
+ kunit_platform_driver_register(test, &cirrus_scodec_test_gpio_driver));
- ret = device_add_software_node(&priv->gpio_pdev->dev, &cirrus_scodec_test_gpio_swnode);
- if (ret) {
- platform_device_put(priv->gpio_pdev);
- KUNIT_FAIL(test, "Failed to add swnode to gpio: %d\n", ret);
- return ret;
- }
+ priv->gpio_pdev = kunit_platform_device_alloc(test,
+ cirrus_scodec_test_gpio_driver.driver.name,
+ PLATFORM_DEVID_NONE);
+ KUNIT_ASSERT_NOT_NULL(test, priv->gpio_pdev);
- ret = platform_device_add(priv->gpio_pdev);
- if (ret) {
- platform_device_put(priv->gpio_pdev);
- KUNIT_FAIL(test, "Failed to add gpio platform device: %d\n", ret);
- return ret;
- }
+ KUNIT_ASSERT_EQ(test, 0, device_add_software_node(&priv->gpio_pdev->dev,
+ &cirrus_scodec_test_gpio_swnode));
+ KUNIT_ASSERT_EQ(test, 0, kunit_add_action_or_reset(test,
+ device_remove_software_node_wrapper,
+ &priv->gpio_pdev->dev));
- priv->gpio_priv = dev_get_drvdata(&priv->gpio_pdev->dev);
- if (!priv->gpio_priv) {
- platform_device_put(priv->gpio_pdev);
- KUNIT_FAIL(test, "Failed to get gpio private data\n");
- return -EINVAL;
- }
+ KUNIT_ASSERT_EQ(test, 0, kunit_platform_device_add(test, priv->gpio_pdev));
- return 0;
+ priv->gpio_priv = dev_get_drvdata(&priv->gpio_pdev->dev);
+ KUNIT_ASSERT_NOT_NULL(test, priv->gpio_priv);
}
static void cirrus_scodec_test_set_gpio_ref_arg(struct software_node_ref_args *arg,
@@ -192,7 +194,7 @@ static void cirrus_scodec_test_spkid_parse(struct kunit *test)
const struct cirrus_scodec_test_spkid_param *param = test->param_value;
int num_spk_id_refs = param->num_amps * param->gpios_per_amp;
struct software_node_ref_args *refs;
- struct device *dev = &priv->amp_pdev.dev;
+ struct device *dev = &priv->amp_dev->dev;
unsigned int v;
int i, ret;
@@ -235,21 +237,16 @@ static void cirrus_scodec_test_spkid_parse(struct kunit *test)
static void cirrus_scodec_test_no_spkid(struct kunit *test)
{
struct cirrus_scodec_test_priv *priv = test->priv;
- struct device *dev = &priv->amp_pdev.dev;
+ struct device *dev = &priv->amp_dev->dev;
int ret;
ret = cirrus_scodec_get_speaker_id(dev, 0, 4, -1);
KUNIT_EXPECT_EQ(test, ret, -ENOENT);
}
-static void cirrus_scodec_test_dev_release(struct device *dev)
-{
-}
-
static int cirrus_scodec_test_case_init(struct kunit *test)
{
struct cirrus_scodec_test_priv *priv;
- int ret;
priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -258,52 +255,18 @@ static int cirrus_scodec_test_case_init(struct kunit *test)
test->priv = priv;
/* Create dummy GPIO */
- ret = cirrus_scodec_test_create_gpio(test);
- if (ret < 0)
- return ret;
+ cirrus_scodec_test_create_gpio(test);
/* Create dummy amp driver dev */
- priv->amp_pdev.name = "cirrus_scodec_test_amp_drv";
- priv->amp_pdev.id = -1;
- priv->amp_pdev.dev.release = cirrus_scodec_test_dev_release;
- ret = platform_device_register(&priv->amp_pdev);
- KUNIT_ASSERT_GE_MSG(test, ret, 0, "Failed to register amp platform device\n");
+ priv->amp_dev = faux_device_create("cirrus_scodec_test_amp_drv", NULL, NULL);
+ KUNIT_ASSERT_NOT_NULL(test, priv->amp_dev);
+ KUNIT_ASSERT_EQ(test, 0, kunit_add_action_or_reset(test,
+ faux_device_destroy_wrapper,
+ priv->amp_dev));
return 0;
}
-static void cirrus_scodec_test_case_exit(struct kunit *test)
-{
- struct cirrus_scodec_test_priv *priv = test->priv;
-
- if (priv->amp_pdev.name)
- platform_device_unregister(&priv->amp_pdev);
-
- if (priv->gpio_pdev) {
- device_remove_software_node(&priv->gpio_pdev->dev);
- platform_device_unregister(priv->gpio_pdev);
- }
-}
-
-static int cirrus_scodec_test_suite_init(struct kunit_suite *suite)
-{
- int ret;
-
- /* Register mock GPIO driver */
- ret = platform_driver_register(&cirrus_scodec_test_gpio_driver);
- if (ret < 0) {
- kunit_err(suite, "Failed to register gpio platform driver, %d\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-static void cirrus_scodec_test_suite_exit(struct kunit_suite *suite)
-{
- platform_driver_unregister(&cirrus_scodec_test_gpio_driver);
-}
-
static const struct cirrus_scodec_test_spkid_param cirrus_scodec_test_spkid_param_cases[] = {
{ .num_amps = 2, .gpios_per_amp = 1, .num_amps_sharing = 1 },
{ .num_amps = 2, .gpios_per_amp = 2, .num_amps_sharing = 1 },
@@ -357,10 +320,7 @@ static struct kunit_case cirrus_scodec_test_cases[] = {
static struct kunit_suite cirrus_scodec_test_suite = {
.name = "snd-hda-scodec-cs35l56-test",
- .suite_init = cirrus_scodec_test_suite_init,
- .suite_exit = cirrus_scodec_test_suite_exit,
.init = cirrus_scodec_test_case_init,
- .exit = cirrus_scodec_test_case_exit,
.test_cases = cirrus_scodec_test_cases,
};
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index 5dc021976c79..d5bc81099d0d 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -20,7 +20,6 @@
#include "hda_generic.h"
#include "hda_component.h"
#include "cs35l41_hda.h"
-#include "hda_cs_dsp_ctl.h"
#include "cs35l41_hda_property.h"
#define CS35L41_PART "cs35l41"
@@ -74,6 +73,21 @@ static const struct cirrus_amp_cal_controls cs35l41_calibration_controls = {
.checksum = CAL_CHECKSUM_DSP_CTL_NAME,
};
+enum cs35l41_hda_fw_id {
+ CS35L41_HDA_FW_SPK_PROT,
+ CS35L41_HDA_FW_SPK_CALI,
+ CS35L41_HDA_FW_SPK_DIAG,
+ CS35L41_HDA_FW_MISC,
+ CS35L41_HDA_NUM_FW
+};
+
+static const char * const cs35l41_hda_fw_ids[CS35L41_HDA_NUM_FW] = {
+ [CS35L41_HDA_FW_SPK_PROT] = "spk-prot",
+ [CS35L41_HDA_FW_SPK_CALI] = "spk-cali",
+ [CS35L41_HDA_FW_SPK_DIAG] = "spk-diag",
+ [CS35L41_HDA_FW_MISC] = "misc",
+};
+
static bool firmware_autostart = 1;
module_param(firmware_autostart, bool, 0444);
MODULE_PARM_DESC(firmware_autostart, "Allow automatic firmware download on boot"
@@ -169,23 +183,23 @@ static int cs35l41_request_firmware_file(struct cs35l41_hda *cs35l41,
if (spkid > -1 && ssid && amp_name)
*filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s-%s-spkid%d-%s.%s", CS35L41_PART,
- dsp_name, hda_cs_dsp_fw_ids[cs35l41->firmware_type],
+ dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],
ssid, spkid, amp_name, filetype);
else if (spkid > -1 && ssid)
*filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s-%s-spkid%d.%s", CS35L41_PART,
- dsp_name, hda_cs_dsp_fw_ids[cs35l41->firmware_type],
+ dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],
ssid, spkid, filetype);
else if (ssid && amp_name)
*filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s-%s-%s.%s", CS35L41_PART,
- dsp_name, hda_cs_dsp_fw_ids[cs35l41->firmware_type],
+ dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],
ssid, amp_name, filetype);
else if (ssid)
*filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s-%s.%s", CS35L41_PART,
- dsp_name, hda_cs_dsp_fw_ids[cs35l41->firmware_type],
+ dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],
ssid, filetype);
else
*filename = kasprintf(GFP_KERNEL, "cirrus/%s-%s-%s.%s", CS35L41_PART,
- dsp_name, hda_cs_dsp_fw_ids[cs35l41->firmware_type],
+ dsp_name, cs35l41_hda_fw_ids[cs35l41->firmware_type],
filetype);
if (*filename == NULL)
@@ -588,7 +602,7 @@ static int cs35l41_init_dsp(struct cs35l41_hda *cs35l41)
}
ret = cs_dsp_power_up(dsp, wmfw_firmware, wmfw_filename, coeff_firmware, coeff_filename,
- hda_cs_dsp_fw_ids[cs35l41->firmware_type]);
+ cs35l41_hda_fw_ids[cs35l41->firmware_type]);
if (ret)
goto err;
@@ -1108,6 +1122,18 @@ err:
return ret;
}
+static int cs35l41_hda_read_ctl(struct cs_dsp *dsp, const char *name, int type,
+ unsigned int alg, void *buf, size_t len)
+{
+ int ret;
+
+ mutex_lock(&dsp->pwr_lock);
+ ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(dsp, name, type, alg), 0, buf, len);
+ mutex_unlock(&dsp->pwr_lock);
+
+ return ret;
+}
+
static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41)
{
unsigned int fw_status;
@@ -1137,7 +1163,7 @@ static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41)
goto clean_dsp;
}
- ret = read_poll_timeout(hda_cs_dsp_read_ctl, ret,
+ ret = read_poll_timeout(cs35l41_hda_read_ctl, ret,
be32_to_cpu(halo_sts) == HALO_STATE_CODE_RUN,
1000, 15000, false, &cs35l41->cs_dsp, HALO_STATE_DSP_CTL_NAME,
HALO_STATE_DSP_CTL_TYPE, HALO_STATE_DSP_CTL_ALG,
@@ -1174,7 +1200,7 @@ static int cs35l41_smart_amp(struct cs35l41_hda *cs35l41)
}
dev_info(cs35l41->dev, "Firmware Loaded - Type: %s, Gain: %d\n",
- hda_cs_dsp_fw_ids[cs35l41->firmware_type], cs35l41->tuning_gain);
+ cs35l41_hda_fw_ids[cs35l41->firmware_type], cs35l41->tuning_gain);
return 0;
@@ -1276,7 +1302,7 @@ static int cs35l41_fw_type_ctl_put(struct snd_kcontrol *kcontrol,
{
struct cs35l41_hda *cs35l41 = snd_kcontrol_chip(kcontrol);
- if (ucontrol->value.enumerated.item[0] < HDA_CS_DSP_NUM_FW) {
+ if (ucontrol->value.enumerated.item[0] < CS35L41_HDA_NUM_FW) {
if (cs35l41->firmware_type != ucontrol->value.enumerated.item[0]) {
cs35l41->firmware_type = ucontrol->value.enumerated.item[0];
return 1;
@@ -1290,7 +1316,7 @@ static int cs35l41_fw_type_ctl_put(struct snd_kcontrol *kcontrol,
static int cs35l41_fw_type_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
- return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(hda_cs_dsp_fw_ids), hda_cs_dsp_fw_ids);
+ return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(cs35l41_hda_fw_ids), cs35l41_hda_fw_ids);
}
static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)
@@ -1430,7 +1456,7 @@ static int cs35l41_hda_bind(struct device *dev, struct device *master, void *mas
strscpy(comp->name, dev_name(dev), sizeof(comp->name));
- cs35l41->firmware_type = HDA_CS_DSP_FW_SPK_PROT;
+ cs35l41->firmware_type = CS35L41_HDA_FW_SPK_PROT;
if (firmware_autostart) {
dev_dbg(cs35l41->dev, "Firmware Autostart.\n");
@@ -1577,7 +1603,7 @@ static const struct regmap_irq cs35l41_reg_irqs[] = {
CS35L41_REG_IRQ(IRQ1_STATUS1, AMP_SHORT_ERR),
};
-static struct regmap_irq_chip cs35l41_regmap_irq_chip = {
+static const struct regmap_irq_chip cs35l41_regmap_irq_chip = {
.name = "cs35l41 IRQ1 Controller",
.status_base = CS35L41_IRQ1_STATUS1,
.mask_base = CS35L41_IRQ1_MASK1,
@@ -2055,7 +2081,6 @@ const struct dev_pm_ops cs35l41_hda_pm_ops = {
EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, "SND_HDA_SCODEC_CS35L41");
MODULE_DESCRIPTION("CS35L41 HDA Driver");
-MODULE_IMPORT_NS("SND_HDA_CS_DSP_CONTROLS");
MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");
MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l41_hda_property.c b/sound/pci/hda/cs35l41_hda_property.c
index 61d2314834e7..d8249d997c2a 100644
--- a/sound/pci/hda/cs35l41_hda_property.c
+++ b/sound/pci/hda/cs35l41_hda_property.c
@@ -31,6 +31,9 @@ struct cs35l41_config {
};
static const struct cs35l41_config cs35l41_config_table[] = {
+ { "10251826", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
+ { "1025182C", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
+ { "10251844", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
{ "10280B27", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
{ "10280B28", 2, INTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, 2, 0, 1000, 4500, 24 },
{ "10280BEB", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 1, -1, 0, 0, 0, 0 },
@@ -452,6 +455,9 @@ struct cs35l41_prop_model {
static const struct cs35l41_prop_model cs35l41_prop_model_table[] = {
{ "CLSA0100", NULL, lenovo_legion_no_acpi },
{ "CLSA0101", NULL, lenovo_legion_no_acpi },
+ { "CSC3551", "10251826", generic_dsd_config },
+ { "CSC3551", "1025182C", generic_dsd_config },
+ { "CSC3551", "10251844", generic_dsd_config },
{ "CSC3551", "10280B27", generic_dsd_config },
{ "CSC3551", "10280B28", generic_dsd_config },
{ "CSC3551", "10280BEB", generic_dsd_config },
diff --git a/sound/pci/hda/cs35l56_hda.c b/sound/pci/hda/cs35l56_hda.c
index aed7d7284231..3f2fd32f4ad9 100644
--- a/sound/pci/hda/cs35l56_hda.c
+++ b/sound/pci/hda/cs35l56_hda.c
@@ -20,7 +20,6 @@
#include "cirrus_scodec.h"
#include "cs35l56_hda.h"
#include "hda_component.h"
-#include "hda_cs_dsp_ctl.h"
#include "hda_generic.h"
/*
@@ -180,7 +179,7 @@ static int cs35l56_hda_mixer_info(struct snd_kcontrol *kcontrol,
static int cs35l56_hda_mixer_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data;
+ struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
unsigned int reg_val;
int i;
@@ -202,7 +201,7 @@ static int cs35l56_hda_mixer_get(struct snd_kcontrol *kcontrol,
static int cs35l56_hda_mixer_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data;
+ struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
unsigned int item = ucontrol->value.enumerated.item[0];
bool changed;
@@ -231,7 +230,7 @@ static int cs35l56_hda_posture_info(struct snd_kcontrol *kcontrol,
static int cs35l56_hda_posture_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data;
+ struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
unsigned int pos;
int ret;
@@ -250,7 +249,7 @@ static int cs35l56_hda_posture_get(struct snd_kcontrol *kcontrol,
static int cs35l56_hda_posture_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data;
+ struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
unsigned long pos = ucontrol->value.integer.value[0];
bool changed;
int ret;
@@ -297,7 +296,7 @@ static int cs35l56_hda_vol_info(struct snd_kcontrol *kcontrol,
static int cs35l56_hda_vol_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data;
+ struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
unsigned int raw_vol;
int vol;
int ret;
@@ -323,7 +322,7 @@ static int cs35l56_hda_vol_get(struct snd_kcontrol *kcontrol,
static int cs35l56_hda_vol_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct cs35l56_hda *cs35l56 = (struct cs35l56_hda *)kcontrol->private_data;
+ struct cs35l56_hda *cs35l56 = snd_kcontrol_chip(kcontrol);
long vol = ucontrol->value.integer.value[0];
unsigned int raw_vol;
bool changed;
@@ -1118,7 +1117,6 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_hda_pm_ops, "SND_HDA_SCODEC_CS35L56");
MODULE_DESCRIPTION("CS35L56 HDA Driver");
MODULE_IMPORT_NS("FW_CS_DSP");
MODULE_IMPORT_NS("SND_HDA_CIRRUS_SCODEC");
-MODULE_IMPORT_NS("SND_HDA_CS_DSP_CONTROLS");
MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED");
MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
diff --git a/sound/pci/hda/hda_acpi.c b/sound/pci/hda/hda_acpi.c
new file mode 100644
index 000000000000..505cc97e0ee9
--- /dev/null
+++ b/sound/pci/hda/hda_acpi.c
@@ -0,0 +1,325 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ALSA driver for ACPI-based HDA Controllers.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/acpi.h>
+
+#include <sound/hda_codec.h>
+
+#include "hda_controller.h"
+
+struct hda_acpi {
+ struct azx azx;
+ struct snd_card *card;
+ struct platform_device *pdev;
+ void __iomem *regs;
+ struct work_struct probe_work;
+ const struct hda_data *data;
+};
+
+/**
+ * struct hda_data - Optional device-specific data
+ * @short_name: Used for the ALSA card name; defaults to KBUILD_MODNAME
+ * @long_name: Used for longer description; defaults to short_name
+ * @flags: Passed to &azx->driver_caps
+ *
+ * A pointer to a record of this type may be stored in the
+ * &acpi_device_id->driver_data field of an ACPI match table entry in order to
+ * customize the naming and behavior of a particular device. All fields are
+ * optional and sensible defaults will be selected in their absence.
+ */
+struct hda_data {
+ const char *short_name;
+ const char *long_name;
+ unsigned long flags;
+};
+
+static int hda_acpi_dev_disconnect(struct snd_device *device)
+{
+ struct azx *chip = device->device_data;
+
+ chip->bus.shutdown = 1;
+ return 0;
+}
+
+static int hda_acpi_dev_free(struct snd_device *device)
+{
+ struct azx *azx = device->device_data;
+ struct hda_acpi *hda = container_of(azx, struct hda_acpi, azx);
+
+ cancel_work_sync(&hda->probe_work);
+ if (azx_bus(azx)->chip_init) {
+ azx_stop_all_streams(azx);
+ azx_stop_chip(azx);
+ }
+
+ azx_free_stream_pages(azx);
+ azx_free_streams(azx);
+ snd_hdac_bus_exit(azx_bus(azx));
+
+ return 0;
+}
+
+static int hda_acpi_init(struct hda_acpi *hda)
+{
+ struct hdac_bus *bus = azx_bus(&hda->azx);
+ struct snd_card *card = hda->azx.card;
+ struct device *dev = &hda->pdev->dev;
+ struct azx *azx = &hda->azx;
+ struct resource *res;
+ unsigned short gcap;
+ const char *sname, *lname;
+ int err, irq;
+
+ /* The base address for the HDA registers and the interrupt are wrapped
+ * in an ACPI _CRS object which can be parsed by platform_get_irq() and
+ * devm_platform_get_and_ioremap_resource()
+ */
+
+ irq = platform_get_irq(hda->pdev, 0);
+ if (irq < 0)
+ return irq;
+
+ hda->regs = devm_platform_get_and_ioremap_resource(hda->pdev, 0, &res);
+ if (IS_ERR(hda->regs))
+ return PTR_ERR(hda->regs);
+
+ bus->remap_addr = hda->regs;
+ bus->addr = res->start;
+
+ err = devm_request_irq(dev, irq, azx_interrupt,
+ IRQF_SHARED, KBUILD_MODNAME, azx);
+ if (err) {
+ dev_err(dev, "unable to request IRQ %d, disabling device\n",
+ irq);
+ return err;
+ }
+ bus->irq = irq;
+ bus->dma_stop_delay = 100;
+ card->sync_irq = bus->irq;
+
+ gcap = azx_readw(azx, GCAP);
+ dev_dbg(dev, "chipset global capabilities = 0x%x\n", gcap);
+
+ azx->align_buffer_size = 1;
+
+ azx->capture_streams = (gcap >> 8) & 0x0f;
+ azx->playback_streams = (gcap >> 12) & 0x0f;
+
+ azx->capture_index_offset = 0;
+ azx->playback_index_offset = azx->capture_streams;
+ azx->num_streams = azx->playback_streams + azx->capture_streams;
+
+ err = azx_init_streams(azx);
+ if (err < 0) {
+ dev_err(dev, "failed to initialize streams: %d\n", err);
+ return err;
+ }
+
+ err = azx_alloc_stream_pages(azx);
+ if (err < 0) {
+ dev_err(dev, "failed to allocate stream pages: %d\n", err);
+ return err;
+ }
+
+ azx_init_chip(azx, 1);
+
+ if (!bus->codec_mask) {
+ dev_err(dev, "no codecs found!\n");
+ return -ENODEV;
+ }
+
+ strscpy(card->driver, "hda-acpi");
+
+ sname = hda->data->short_name ? hda->data->short_name : KBUILD_MODNAME;
+
+ if (strlen(sname) > sizeof(card->shortname))
+ dev_info(dev, "truncating shortname for card %s\n", sname);
+ strscpy(card->shortname, sname);
+
+ lname = hda->data->long_name ? hda->data->long_name : sname;
+
+ snprintf(card->longname, sizeof(card->longname),
+ "%s at 0x%lx irq %i", lname, bus->addr, bus->irq);
+
+ return 0;
+}
+
+static void hda_acpi_probe_work(struct work_struct *work)
+{
+ struct hda_acpi *hda = container_of(work, struct hda_acpi, probe_work);
+ struct azx *chip = &hda->azx;
+ int err;
+
+ err = hda_acpi_init(hda);
+ if (err < 0)
+ return;
+
+ err = azx_probe_codecs(chip, 8);
+ if (err < 0)
+ return;
+
+ err = azx_codec_configure(chip);
+ if (err < 0)
+ return;
+
+ err = snd_card_register(chip->card);
+ if (err < 0)
+ return;
+
+ chip->running = 1;
+}
+
+static int hda_acpi_create(struct hda_acpi *hda)
+{
+ static const struct snd_device_ops ops = {
+ .dev_disconnect = hda_acpi_dev_disconnect,
+ .dev_free = hda_acpi_dev_free,
+ };
+ static const struct hda_controller_ops null_ops;
+ struct azx *azx = &hda->azx;
+ int err;
+
+ mutex_init(&azx->open_mutex);
+ azx->card = hda->card;
+ INIT_LIST_HEAD(&azx->pcm_list);
+
+ azx->ops = &null_ops;
+ azx->driver_caps = hda->data->flags;
+ azx->driver_type = hda->data->flags & 0xff;
+ azx->codec_probe_mask = -1;
+
+ err = azx_bus_init(azx, NULL);
+ if (err < 0)
+ return err;
+
+ err = snd_device_new(hda->card, SNDRV_DEV_LOWLEVEL, &hda->azx, &ops);
+ if (err < 0) {
+ dev_err(&hda->pdev->dev, "Error creating device\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static int hda_acpi_probe(struct platform_device *pdev)
+{
+ struct hda_acpi *hda;
+ int err;
+
+ hda = devm_kzalloc(&pdev->dev, sizeof(*hda), GFP_KERNEL);
+ if (!hda)
+ return -ENOMEM;
+
+ hda->pdev = pdev;
+ hda->data = acpi_device_get_match_data(&pdev->dev);
+
+ /* Fall back to defaults if the table didn't have a *struct hda_data */
+ if (!hda->data)
+ hda->data = devm_kzalloc(&pdev->dev, sizeof(*hda->data),
+ GFP_KERNEL);
+ if (!hda->data)
+ return -ENOMEM;
+
+ err = snd_card_new(&pdev->dev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+ THIS_MODULE, 0, &hda->card);
+ if (err < 0) {
+ dev_err(&pdev->dev, "Error creating card!\n");
+ return err;
+ }
+
+ INIT_WORK(&hda->probe_work, hda_acpi_probe_work);
+
+ err = hda_acpi_create(hda);
+ if (err < 0)
+ goto out_free;
+ hda->card->private_data = &hda->azx;
+
+ dev_set_drvdata(&pdev->dev, hda->card);
+
+ schedule_work(&hda->probe_work);
+
+ return 0;
+
+out_free:
+ snd_card_free(hda->card);
+ return err;
+}
+
+static void hda_acpi_remove(struct platform_device *pdev)
+{
+ snd_card_free(dev_get_drvdata(&pdev->dev));
+}
+
+static void hda_acpi_shutdown(struct platform_device *pdev)
+{
+ struct snd_card *card = dev_get_drvdata(&pdev->dev);
+ struct azx *chip;
+
+ if (!card)
+ return;
+ chip = card->private_data;
+ if (chip && chip->running)
+ azx_stop_chip(chip);
+}
+
+static int hda_acpi_suspend(struct device *dev)
+{
+ struct snd_card *card = dev_get_drvdata(dev);
+ int rc;
+
+ rc = pm_runtime_force_suspend(dev);
+ if (rc < 0)
+ return rc;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+
+ return 0;
+}
+
+static int hda_acpi_resume(struct device *dev)
+{
+ struct snd_card *card = dev_get_drvdata(dev);
+ int rc;
+
+ rc = pm_runtime_force_resume(dev);
+ if (rc < 0)
+ return rc;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+
+ return 0;
+}
+
+static const struct dev_pm_ops hda_acpi_pm = {
+ SYSTEM_SLEEP_PM_OPS(hda_acpi_suspend, hda_acpi_resume)
+};
+
+static const struct hda_data nvidia_hda_data = {
+ .short_name = "NVIDIA",
+ .long_name = "NVIDIA HDA Controller",
+ .flags = AZX_DCAPS_CORBRP_SELF_CLEAR,
+};
+
+static const struct acpi_device_id hda_acpi_match[] = {
+ { .id = "NVDA2014", .driver_data = (uintptr_t) &nvidia_hda_data },
+ { .id = "NVDA2015", .driver_data = (uintptr_t) &nvidia_hda_data },
+ {},
+};
+MODULE_DEVICE_TABLE(acpi, hda_acpi_match);
+
+static struct platform_driver hda_acpi_platform_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .pm = &hda_acpi_pm,
+ .acpi_match_table = hda_acpi_match,
+ },
+ .probe = hda_acpi_probe,
+ .remove = hda_acpi_remove,
+ .shutdown = hda_acpi_shutdown,
+};
+module_platform_driver(hda_acpi_platform_driver);
+
+MODULE_DESCRIPTION("Driver for ACPI-based HDA Controllers");
+MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/hda_bind.c b/sound/pci/hda/hda_bind.c
index 9521e5e0e6e6..df8f88beddd0 100644
--- a/sound/pci/hda/hda_bind.c
+++ b/sound/pci/hda/hda_bind.c
@@ -18,10 +18,10 @@
/*
* find a matching codec id
*/
-static int hda_codec_match(struct hdac_device *dev, struct hdac_driver *drv)
+static int hda_codec_match(struct hdac_device *dev, const struct hdac_driver *drv)
{
struct hda_codec *codec = container_of(dev, struct hda_codec, core);
- struct hda_codec_driver *driver =
+ const struct hda_codec_driver *driver =
container_of(drv, struct hda_codec_driver, core);
const struct hda_device_id *list;
/* check probe_id instead of vendor_id if set */
@@ -44,7 +44,7 @@ static void hda_codec_unsol_event(struct hdac_device *dev, unsigned int ev)
struct hda_codec *codec = container_of(dev, struct hda_codec, core);
/* ignore unsol events during shutdown */
- if (codec->bus->shutdown)
+ if (codec->card->shutdown || codec->bus->shutdown)
return;
/* ignore unsol events during system suspend/resume */
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index b436d436831b..c018beeecd3d 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1732,37 +1732,6 @@ int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
EXPORT_SYMBOL_GPL(snd_hda_ctl_add);
/**
- * snd_hda_add_nid - Assign a NID to a control element
- * @codec: HD-audio codec
- * @kctl: the control element to assign
- * @index: index to kctl
- * @nid: corresponding NID (optional)
- *
- * Add the given control element to an array inside the codec instance.
- * This function is used when #snd_hda_ctl_add cannot be used for 1:1
- * NID:KCTL mapping - for example "Capture Source" selector.
- */
-int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl,
- unsigned int index, hda_nid_t nid)
-{
- struct hda_nid_item *item;
-
- if (nid > 0) {
- item = snd_array_new(&codec->nids);
- if (!item)
- return -ENOMEM;
- item->kctl = kctl;
- item->index = index;
- item->nid = nid;
- return 0;
- }
- codec_err(codec, "no NID for mapping control %s:%d:%d\n",
- kctl->id.name, kctl->id.index, index);
- return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(snd_hda_add_nid);
-
-/**
* snd_hda_ctls_clear - Clear all controls assigned to the given codec
* @codec: HD-audio codec
*/
diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c
deleted file mode 100644
index 18fa6e7edb49..000000000000
--- a/sound/pci/hda/hda_cs_dsp_ctl.c
+++ /dev/null
@@ -1,249 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// HDA DSP ALSA Control Driver
-//
-// Copyright 2022 Cirrus Logic, Inc.
-//
-// Author: Stefan Binding <sbinding@opensource.cirrus.com>
-
-#include <linux/module.h>
-#include <sound/soc.h>
-#include <linux/cleanup.h>
-#include <linux/firmware/cirrus/cs_dsp.h>
-#include <linux/firmware/cirrus/wmfw.h>
-#include "hda_cs_dsp_ctl.h"
-
-#define ADSP_MAX_STD_CTRL_SIZE 512
-
-struct hda_cs_dsp_coeff_ctl {
- struct cs_dsp_coeff_ctl *cs_ctl;
- struct snd_card *card;
- struct snd_kcontrol *kctl;
-};
-
-static const char * const hda_cs_dsp_fw_text[HDA_CS_DSP_NUM_FW] = {
- [HDA_CS_DSP_FW_SPK_PROT] = "Prot",
- [HDA_CS_DSP_FW_SPK_CALI] = "Cali",
- [HDA_CS_DSP_FW_SPK_DIAG] = "Diag",
- [HDA_CS_DSP_FW_MISC] = "Misc",
-};
-
-const char * const hda_cs_dsp_fw_ids[HDA_CS_DSP_NUM_FW] = {
- [HDA_CS_DSP_FW_SPK_PROT] = "spk-prot",
- [HDA_CS_DSP_FW_SPK_CALI] = "spk-cali",
- [HDA_CS_DSP_FW_SPK_DIAG] = "spk-diag",
- [HDA_CS_DSP_FW_MISC] = "misc",
-};
-EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_fw_ids, "SND_HDA_CS_DSP_CONTROLS");
-
-static int hda_cs_dsp_coeff_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
-{
- struct hda_cs_dsp_coeff_ctl *ctl = (struct hda_cs_dsp_coeff_ctl *)snd_kcontrol_chip(kctl);
- struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
- uinfo->count = cs_ctl->len;
-
- return 0;
-}
-
-static int hda_cs_dsp_coeff_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_cs_dsp_coeff_ctl *ctl = (struct hda_cs_dsp_coeff_ctl *)snd_kcontrol_chip(kctl);
- struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
- char *p = ucontrol->value.bytes.data;
-
- return cs_dsp_coeff_lock_and_write_ctrl(cs_ctl, 0, p, cs_ctl->len);
-}
-
-static int hda_cs_dsp_coeff_get(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_cs_dsp_coeff_ctl *ctl = (struct hda_cs_dsp_coeff_ctl *)snd_kcontrol_chip(kctl);
- struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
- char *p = ucontrol->value.bytes.data;
-
- return cs_dsp_coeff_lock_and_read_ctrl(cs_ctl, 0, p, cs_ctl->len);
-}
-
-static unsigned int wmfw_convert_flags(unsigned int in)
-{
- unsigned int out, rd, wr, vol;
-
- rd = SNDRV_CTL_ELEM_ACCESS_READ;
- wr = SNDRV_CTL_ELEM_ACCESS_WRITE;
- vol = SNDRV_CTL_ELEM_ACCESS_VOLATILE;
-
- out = 0;
-
- if (in) {
- out |= rd;
- if (in & WMFW_CTL_FLAG_WRITEABLE)
- out |= wr;
- if (in & WMFW_CTL_FLAG_VOLATILE)
- out |= vol;
- } else {
- out |= rd | wr | vol;
- }
-
- return out;
-}
-
-static void hda_cs_dsp_free_kcontrol(struct snd_kcontrol *kctl)
-{
- struct hda_cs_dsp_coeff_ctl *ctl = (struct hda_cs_dsp_coeff_ctl *)snd_kcontrol_chip(kctl);
- struct cs_dsp_coeff_ctl *cs_ctl = ctl->cs_ctl;
-
- /* NULL priv to prevent a double-free in hda_cs_dsp_control_remove() */
- cs_ctl->priv = NULL;
- kfree(ctl);
-}
-
-static void hda_cs_dsp_add_kcontrol(struct cs_dsp_coeff_ctl *cs_ctl,
- const struct hda_cs_dsp_ctl_info *info,
- const char *name)
-{
- struct snd_kcontrol_new kcontrol = {0};
- struct snd_kcontrol *kctl;
- struct hda_cs_dsp_coeff_ctl *ctl __free(kfree) = NULL;
- int ret = 0;
-
- if (cs_ctl->len > ADSP_MAX_STD_CTRL_SIZE) {
- dev_err(cs_ctl->dsp->dev, "KControl %s: length %zu exceeds maximum %d\n", name,
- cs_ctl->len, ADSP_MAX_STD_CTRL_SIZE);
- return;
- }
-
- ctl = kzalloc(sizeof(*ctl), GFP_KERNEL);
- if (!ctl)
- return;
-
- ctl->cs_ctl = cs_ctl;
- ctl->card = info->card;
-
- kcontrol.name = name;
- kcontrol.info = hda_cs_dsp_coeff_info;
- kcontrol.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- kcontrol.access = wmfw_convert_flags(cs_ctl->flags);
- kcontrol.get = hda_cs_dsp_coeff_get;
- kcontrol.put = hda_cs_dsp_coeff_put;
-
- kctl = snd_ctl_new1(&kcontrol, (void *)ctl);
- if (!kctl)
- return;
-
- kctl->private_free = hda_cs_dsp_free_kcontrol;
- ctl->kctl = kctl;
-
- /* snd_ctl_add() calls our private_free on error, which will kfree(ctl) */
- cs_ctl->priv = no_free_ptr(ctl);
- ret = snd_ctl_add(info->card, kctl);
- if (ret) {
- dev_err(cs_ctl->dsp->dev, "Failed to add KControl %s = %d\n", kcontrol.name, ret);
- return;
- }
-
- dev_dbg(cs_ctl->dsp->dev, "Added KControl: %s\n", kcontrol.name);
-}
-
-static void hda_cs_dsp_control_add(struct cs_dsp_coeff_ctl *cs_ctl,
- const struct hda_cs_dsp_ctl_info *info)
-{
- struct cs_dsp *cs_dsp = cs_ctl->dsp;
- char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
- const char *region_name;
- int ret;
-
- region_name = cs_dsp_mem_region_name(cs_ctl->alg_region.type);
- if (!region_name) {
- dev_warn(cs_dsp->dev, "Unknown region type: %d\n", cs_ctl->alg_region.type);
- return;
- }
-
- ret = scnprintf(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s %s %.12s %x", info->device_name,
- cs_dsp->name, hda_cs_dsp_fw_text[info->fw_type], cs_ctl->alg_region.alg);
-
- if (cs_ctl->subname) {
- int avail = SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret - 2;
- int skip = 0;
-
- /* Truncate the subname from the start if it is too long */
- if (cs_ctl->subname_len > avail)
- skip = cs_ctl->subname_len - avail;
-
- snprintf(name + ret, SNDRV_CTL_ELEM_ID_NAME_MAXLEN - ret,
- " %.*s", cs_ctl->subname_len - skip, cs_ctl->subname + skip);
- }
-
- hda_cs_dsp_add_kcontrol(cs_ctl, info, name);
-}
-
-void hda_cs_dsp_add_controls(struct cs_dsp *dsp, const struct hda_cs_dsp_ctl_info *info)
-{
- struct cs_dsp_coeff_ctl *cs_ctl;
-
- /*
- * pwr_lock would cause mutex inversion with ALSA control lock compared
- * to the get/put functions.
- * It is safe to walk the list without holding a mutex because entries
- * are persistent and only cs_dsp_power_up() or cs_dsp_remove() can
- * change the list.
- */
- lockdep_assert_not_held(&dsp->pwr_lock);
-
- list_for_each_entry(cs_ctl, &dsp->ctl_list, list) {
- if (cs_ctl->flags & WMFW_CTL_FLAG_SYS)
- continue;
-
- if (cs_ctl->priv)
- continue;
-
- hda_cs_dsp_control_add(cs_ctl, info);
- }
-}
-EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_add_controls, "SND_HDA_CS_DSP_CONTROLS");
-
-void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl)
-{
- struct hda_cs_dsp_coeff_ctl *ctl = cs_ctl->priv;
-
- /* ctl and kctl may already have been removed by ALSA private_free */
- if (ctl)
- snd_ctl_remove(ctl->card, ctl->kctl);
-}
-EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_remove, "SND_HDA_CS_DSP_CONTROLS");
-
-int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type,
- unsigned int alg, const void *buf, size_t len)
-{
- struct cs_dsp_coeff_ctl *cs_ctl;
- int ret;
-
- mutex_lock(&dsp->pwr_lock);
- cs_ctl = cs_dsp_get_ctl(dsp, name, type, alg);
- ret = cs_dsp_coeff_write_ctrl(cs_ctl, 0, buf, len);
- mutex_unlock(&dsp->pwr_lock);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_write_ctl, "SND_HDA_CS_DSP_CONTROLS");
-
-int hda_cs_dsp_read_ctl(struct cs_dsp *dsp, const char *name, int type,
- unsigned int alg, void *buf, size_t len)
-{
- int ret;
-
- mutex_lock(&dsp->pwr_lock);
- ret = cs_dsp_coeff_read_ctrl(cs_dsp_get_ctl(dsp, name, type, alg), 0, buf, len);
- mutex_unlock(&dsp->pwr_lock);
-
- return ret;
-
-}
-EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_read_ctl, "SND_HDA_CS_DSP_CONTROLS");
-
-MODULE_DESCRIPTION("CS_DSP ALSA Control HDA Library");
-MODULE_AUTHOR("Stefan Binding, <sbinding@opensource.cirrus.com>");
-MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS("FW_CS_DSP");
diff --git a/sound/pci/hda/hda_cs_dsp_ctl.h b/sound/pci/hda/hda_cs_dsp_ctl.h
deleted file mode 100644
index 2cf93359c4f2..000000000000
--- a/sound/pci/hda/hda_cs_dsp_ctl.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0
- *
- * HDA DSP ALSA Control Driver
- *
- * Copyright 2022 Cirrus Logic, Inc.
- *
- * Author: Stefan Binding <sbinding@opensource.cirrus.com>
- */
-
-#ifndef __HDA_CS_DSP_CTL_H__
-#define __HDA_CS_DSP_CTL_H__
-
-#include <sound/soc.h>
-#include <linux/firmware/cirrus/cs_dsp.h>
-
-enum hda_cs_dsp_fw_id {
- HDA_CS_DSP_FW_SPK_PROT,
- HDA_CS_DSP_FW_SPK_CALI,
- HDA_CS_DSP_FW_SPK_DIAG,
- HDA_CS_DSP_FW_MISC,
- HDA_CS_DSP_NUM_FW
-};
-
-struct hda_cs_dsp_ctl_info {
- struct snd_card *card;
- enum hda_cs_dsp_fw_id fw_type;
- const char *device_name;
-};
-
-extern const char * const hda_cs_dsp_fw_ids[HDA_CS_DSP_NUM_FW];
-
-void hda_cs_dsp_add_controls(struct cs_dsp *dsp, const struct hda_cs_dsp_ctl_info *info);
-void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl);
-int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type,
- unsigned int alg, const void *buf, size_t len);
-int hda_cs_dsp_read_ctl(struct cs_dsp *dsp, const char *name, int type,
- unsigned int alg, void *buf, size_t len);
-
-#endif /*__HDA_CS_DSP_CTL_H__*/
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 512fb22f5e5e..e5210ed48ddf 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -240,6 +240,7 @@ enum {
AZX_DRIVER_CTHDA,
AZX_DRIVER_CMEDIA,
AZX_DRIVER_ZHAOXIN,
+ AZX_DRIVER_ZHAOXINHDMI,
AZX_DRIVER_LOONGSON,
AZX_DRIVER_GENERIC,
AZX_NUM_DRIVERS, /* keep this as last entry */
@@ -355,6 +356,7 @@ static const char * const driver_short_names[] = {
[AZX_DRIVER_CTHDA] = "HDA Creative",
[AZX_DRIVER_CMEDIA] = "HDA C-Media",
[AZX_DRIVER_ZHAOXIN] = "HDA Zhaoxin",
+ [AZX_DRIVER_ZHAOXINHDMI] = "HDA Zhaoxin HDMI",
[AZX_DRIVER_LOONGSON] = "HDA Loongson",
[AZX_DRIVER_GENERIC] = "HD-Audio Generic",
};
@@ -1750,6 +1752,8 @@ static int default_bdl_pos_adj(struct azx *chip)
case AZX_DRIVER_ICH:
case AZX_DRIVER_PCH:
return 1;
+ case AZX_DRIVER_ZHAOXINHDMI:
+ return 128;
default:
return 32;
}
@@ -1877,12 +1881,14 @@ static int azx_first_init(struct azx *chip)
chip->jackpoll_interval = msecs_to_jiffies(1500);
}
- err = pcim_iomap_regions(pci, 1 << 0, "ICH HD audio");
- if (err < 0)
- return err;
+ if (chip->driver_type == AZX_DRIVER_ZHAOXINHDMI)
+ bus->polling_mode = 1;
+
+ bus->remap_addr = pcim_iomap_region(pci, 0, "ICH HD audio");
+ if (IS_ERR(bus->remap_addr))
+ return PTR_ERR(bus->remap_addr);
bus->addr = pci_resource_start(pci, 0);
- bus->remap_addr = pcim_iomap_table(pci)[0];
if (chip->driver_type == AZX_DRIVER_SKL)
snd_hdac_bus_parse_capabilities(bus);
@@ -1974,6 +1980,7 @@ static int azx_first_init(struct azx *chip)
chip->capture_streams = ATIHDMI_NUM_CAPTURE;
break;
case AZX_DRIVER_GFHDMI:
+ case AZX_DRIVER_ZHAOXINHDMI:
case AZX_DRIVER_GENERIC:
default:
chip->playback_streams = ICH6_NUM_PLAYBACK;
@@ -2542,6 +2549,8 @@ static const struct pci_device_id azx_ids[] = {
{ PCI_DEVICE_DATA(INTEL, HDA_PTL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) },
/* Panther Lake-H */
{ PCI_DEVICE_DATA(INTEL, HDA_PTL_H, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) },
+ /* Wildcat Lake */
+ { PCI_DEVICE_DATA(INTEL, HDA_WCL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_LNL) },
/* Apollolake (Broxton-P) */
{ PCI_DEVICE_DATA(INTEL, HDA_APL, AZX_DRIVER_SKL | AZX_DCAPS_INTEL_BROXTON) },
/* Gemini-Lake */
@@ -2715,6 +2724,9 @@ static const struct pci_device_id azx_ids[] = {
{ PCI_VDEVICE(ATI, 0xab38),
.driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
AZX_DCAPS_PM_RUNTIME },
+ { PCI_VDEVICE(ATI, 0xab40),
+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS |
+ AZX_DCAPS_PM_RUNTIME },
/* GLENFLY */
{ PCI_DEVICE(PCI_VENDOR_ID_GLENFLY, PCI_ANY_ID),
.class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
@@ -2782,6 +2794,21 @@ static const struct pci_device_id azx_ids[] = {
.driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_HDMI },
/* Zhaoxin */
{ PCI_VDEVICE(ZHAOXIN, 0x3288), .driver_data = AZX_DRIVER_ZHAOXIN },
+ { PCI_VDEVICE(ZHAOXIN, 0x9141),
+ .driver_data = AZX_DRIVER_ZHAOXINHDMI | AZX_DCAPS_POSFIX_LPIB |
+ AZX_DCAPS_NO_MSI | AZX_DCAPS_NO_64BIT },
+ { PCI_VDEVICE(ZHAOXIN, 0x9142),
+ .driver_data = AZX_DRIVER_ZHAOXINHDMI | AZX_DCAPS_POSFIX_LPIB |
+ AZX_DCAPS_NO_MSI | AZX_DCAPS_NO_64BIT },
+ { PCI_VDEVICE(ZHAOXIN, 0x9144),
+ .driver_data = AZX_DRIVER_ZHAOXINHDMI | AZX_DCAPS_POSFIX_LPIB |
+ AZX_DCAPS_NO_MSI | AZX_DCAPS_NO_64BIT },
+ { PCI_VDEVICE(ZHAOXIN, 0x9145),
+ .driver_data = AZX_DRIVER_ZHAOXINHDMI | AZX_DCAPS_POSFIX_LPIB |
+ AZX_DCAPS_NO_MSI | AZX_DCAPS_NO_64BIT },
+ { PCI_VDEVICE(ZHAOXIN, 0x9146),
+ .driver_data = AZX_DRIVER_ZHAOXINHDMI | AZX_DCAPS_POSFIX_LPIB |
+ AZX_DCAPS_NO_MSI | AZX_DCAPS_NO_64BIT },
/* Loongson HDAudio*/
{ PCI_VDEVICE(LOONGSON, PCI_DEVICE_ID_LOONGSON_HDA),
.driver_data = AZX_DRIVER_LOONGSON | AZX_DCAPS_NO_TCSEL },
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 4714057dba85..68c31f5354b7 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -571,8 +571,6 @@ struct hda_nid_item {
int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
struct snd_kcontrol *kctl);
-int snd_hda_add_nid(struct hda_codec *codec, struct snd_kcontrol *kctl,
- unsigned int index, hda_nid_t nid);
void snd_hda_ctls_clear(struct hda_codec *codec);
/*
diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c
index a590d431c5ff..6ab338f37db5 100644
--- a/sound/pci/hda/hda_tegra.c
+++ b/sound/pci/hda/hda_tegra.c
@@ -72,6 +72,10 @@
struct hda_tegra_soc {
bool has_hda2codec_2x_reset;
bool has_hda2hdmi;
+ bool has_hda2codec_2x;
+ bool input_stream;
+ bool always_on;
+ bool requires_init;
};
struct hda_tegra {
@@ -187,7 +191,9 @@ static int hda_tegra_runtime_resume(struct device *dev)
if (rc != 0)
return rc;
if (chip->running) {
- hda_tegra_init(hda);
+ if (hda->soc->requires_init)
+ hda_tegra_init(hda);
+
azx_init_chip(chip, 1);
/* disable controller wake up event*/
azx_writew(chip, WAKEEN, azx_readw(chip, WAKEEN) &
@@ -250,7 +256,8 @@ static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev)
bus->remap_addr = hda->regs + HDA_BAR0;
bus->addr = res->start + HDA_BAR0;
- hda_tegra_init(hda);
+ if (hda->soc->requires_init)
+ hda_tegra_init(hda);
return 0;
}
@@ -323,7 +330,7 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
* starts with offset 0 which is wrong as HW register for output stream
* offset starts with 4.
*/
- if (of_device_is_compatible(np, "nvidia,tegra234-hda"))
+ if (!hda->soc->input_stream)
chip->capture_streams = 4;
chip->playback_streams = (gcap >> 12) & 0x0f;
@@ -377,14 +384,14 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
}
/* driver name */
- strscpy(card->driver, drv_name, sizeof(card->driver));
+ strscpy(card->driver, drv_name);
/* shortname for card */
sname = of_get_property(np, "nvidia,model", NULL);
if (!sname)
sname = drv_name;
if (strlen(sname) > sizeof(card->shortname))
dev_info(card->dev, "truncating shortname for card\n");
- strscpy(card->shortname, sname, sizeof(card->shortname));
+ strscpy(card->shortname, sname);
/* longname for card */
snprintf(card->longname, sizeof(card->longname),
@@ -419,7 +426,6 @@ static int hda_tegra_create(struct snd_card *card,
chip->driver_caps = driver_caps;
chip->driver_type = driver_caps & 0xff;
chip->dev_index = 0;
- chip->jackpoll_interval = msecs_to_jiffies(5000);
INIT_LIST_HEAD(&chip->pcm_list);
chip->codec_probe_mask = -1;
@@ -436,7 +442,16 @@ static int hda_tegra_create(struct snd_card *card,
chip->bus.core.sync_write = 0;
chip->bus.core.needs_damn_long_delay = 1;
chip->bus.core.aligned_mmio = 1;
- chip->bus.jackpoll_in_suspend = 1;
+
+ /*
+ * HDA power domain and clocks are always on for Tegra264 and
+ * the jack detection logic would work always, so no need of
+ * jack polling mechanism running.
+ */
+ if (!hda->soc->always_on) {
+ chip->jackpoll_interval = msecs_to_jiffies(5000);
+ chip->bus.jackpoll_in_suspend = 1;
+ }
err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
if (err < 0) {
@@ -450,22 +465,44 @@ static int hda_tegra_create(struct snd_card *card,
static const struct hda_tegra_soc tegra30_data = {
.has_hda2codec_2x_reset = true,
.has_hda2hdmi = true,
+ .has_hda2codec_2x = true,
+ .input_stream = true,
+ .always_on = false,
+ .requires_init = true,
};
static const struct hda_tegra_soc tegra194_data = {
.has_hda2codec_2x_reset = false,
.has_hda2hdmi = true,
+ .has_hda2codec_2x = true,
+ .input_stream = true,
+ .always_on = false,
+ .requires_init = true,
};
static const struct hda_tegra_soc tegra234_data = {
.has_hda2codec_2x_reset = true,
.has_hda2hdmi = false,
+ .has_hda2codec_2x = true,
+ .input_stream = false,
+ .always_on = false,
+ .requires_init = true,
+};
+
+static const struct hda_tegra_soc tegra264_data = {
+ .has_hda2codec_2x_reset = true,
+ .has_hda2hdmi = false,
+ .has_hda2codec_2x = false,
+ .input_stream = false,
+ .always_on = true,
+ .requires_init = false,
};
static const struct of_device_id hda_tegra_match[] = {
{ .compatible = "nvidia,tegra30-hda", .data = &tegra30_data },
{ .compatible = "nvidia,tegra194-hda", .data = &tegra194_data },
{ .compatible = "nvidia,tegra234-hda", .data = &tegra234_data },
+ { .compatible = "nvidia,tegra264-hda", .data = &tegra264_data },
{},
};
MODULE_DEVICE_TABLE(of, hda_tegra_match);
@@ -520,7 +557,9 @@ static int hda_tegra_probe(struct platform_device *pdev)
hda->clocks[hda->nclocks++].id = "hda";
if (hda->soc->has_hda2hdmi)
hda->clocks[hda->nclocks++].id = "hda2hdmi";
- hda->clocks[hda->nclocks++].id = "hda2codec_2x";
+
+ if (hda->soc->has_hda2codec_2x)
+ hda->clocks[hda->nclocks++].id = "hda2codec_2x";
err = devm_clk_bulk_get(&pdev->dev, hda->nclocks, hda->clocks);
if (err < 0)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 7167989a8d86..08308231b4ed 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -4551,6 +4551,7 @@ HDA_CODEC_ENTRY(0x10de002e, "Tegra186 HDMI/DP1", patch_tegra_hdmi),
HDA_CODEC_ENTRY(0x10de002f, "Tegra194 HDMI/DP2", patch_tegra_hdmi),
HDA_CODEC_ENTRY(0x10de0030, "Tegra194 HDMI/DP3", patch_tegra_hdmi),
HDA_CODEC_ENTRY(0x10de0031, "Tegra234 HDMI/DP", patch_tegra234_hdmi),
+HDA_CODEC_ENTRY(0x10de0034, "Tegra264 HDMI/DP", patch_tegra234_hdmi),
HDA_CODEC_ENTRY(0x10de0040, "GPU 40 HDMI/DP", patch_nvhdmi),
HDA_CODEC_ENTRY(0x10de0041, "GPU 41 HDMI/DP", patch_nvhdmi),
HDA_CODEC_ENTRY(0x10de0042, "GPU 42 HDMI/DP", patch_nvhdmi),
@@ -4610,6 +4611,17 @@ HDA_CODEC_ENTRY(0x11069f80, "VX900 HDMI/DP", patch_via_hdmi),
HDA_CODEC_ENTRY(0x11069f81, "VX900 HDMI/DP", patch_via_hdmi),
HDA_CODEC_ENTRY(0x11069f84, "VX11 HDMI/DP", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x11069f85, "VX11 HDMI/DP", patch_generic_hdmi),
+HDA_CODEC_ENTRY(0x1d179f86, "ZX-100S HDMI/DP", patch_gf_hdmi),
+HDA_CODEC_ENTRY(0x1d179f87, "ZX-100S HDMI/DP", patch_gf_hdmi),
+HDA_CODEC_ENTRY(0x1d179f88, "KX-5000 HDMI/DP", patch_gf_hdmi),
+HDA_CODEC_ENTRY(0x1d179f89, "KX-5000 HDMI/DP", patch_gf_hdmi),
+HDA_CODEC_ENTRY(0x1d179f8a, "KX-6000 HDMI/DP", patch_gf_hdmi),
+HDA_CODEC_ENTRY(0x1d179f8b, "KX-6000 HDMI/DP", patch_gf_hdmi),
+HDA_CODEC_ENTRY(0x1d179f8c, "KX-6000G HDMI/DP", patch_gf_hdmi),
+HDA_CODEC_ENTRY(0x1d179f8d, "KX-6000G HDMI/DP", patch_gf_hdmi),
+HDA_CODEC_ENTRY(0x1d179f8e, "KX-7000 HDMI/DP", patch_gf_hdmi),
+HDA_CODEC_ENTRY(0x1d179f8f, "KX-7000 HDMI/DP", patch_gf_hdmi),
+HDA_CODEC_ENTRY(0x1d179f90, "KX-7000 HDMI/DP", patch_gf_hdmi),
HDA_CODEC_ENTRY(0x80860054, "IbexPeak HDMI", patch_i915_cpt_hdmi),
HDA_CODEC_ENTRY(0x80862800, "Geminilake HDMI", patch_i915_glk_hdmi),
HDA_CODEC_ENTRY(0x80862801, "Bearlake HDMI", patch_generic_hdmi),
@@ -4640,6 +4652,7 @@ HDA_CODEC_ENTRY(0x8086281e, "Battlemage HDMI", patch_i915_adlp_hdmi),
HDA_CODEC_ENTRY(0x8086281f, "Raptor Lake P HDMI", patch_i915_adlp_hdmi),
HDA_CODEC_ENTRY(0x80862820, "Lunar Lake HDMI", patch_i915_adlp_hdmi),
HDA_CODEC_ENTRY(0x80862822, "Panther Lake HDMI", patch_i915_adlp_hdmi),
+HDA_CODEC_ENTRY(0x80862823, "Wildcat Lake HDMI", patch_i915_adlp_hdmi),
HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi),
HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI", patch_i915_byt_hdmi),
HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI", patch_i915_byt_hdmi),
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 8a2b09e4a7d5..cd0d7ba7320e 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6830,7 +6830,10 @@ static void alc256_fixup_chromebook(struct hda_codec *codec,
switch (action) {
case HDA_FIXUP_ACT_PRE_PROBE:
- spec->gen.suppress_auto_mute = 1;
+ if (codec->core.subsystem_id == 0x10280d76)
+ spec->gen.suppress_auto_mute = 0;
+ else
+ spec->gen.suppress_auto_mute = 1;
spec->gen.suppress_auto_mic = 1;
spec->en_3kpull_low = false;
break;
@@ -8026,6 +8029,7 @@ enum {
ALC283_FIXUP_DELL_HP_RESUME,
ALC294_FIXUP_ASUS_CS35L41_SPI_2,
ALC274_FIXUP_HP_AIO_BIND_DACS,
+ ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2,
};
/* A special fixup for Lenovo C940 and Yoga Duet 7;
@@ -9298,6 +9302,12 @@ static const struct hda_fixup alc269_fixups[] = {
{ }
}
},
+ [ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = cs35l41_fixup_i2c_two,
+ .chained = true,
+ .chain_id = ALC255_FIXUP_PREDATOR_SUBWOOFER
+ },
[ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
@@ -10453,6 +10463,9 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x1534, "Acer Predator PH315-54", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
+ SND_PCI_QUIRK(0x1025, 0x1826, "Acer Helios ZPC", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x1025, 0x182c, "Acer Helios ZPD", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x1025, 0x1844, "Acer Helios ZPS", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
SND_PCI_QUIRK(0x1028, 0x053c, "Dell Latitude E5430", ALC292_FIXUP_DELL_E7X),
SND_PCI_QUIRK(0x1028, 0x054b, "Dell XPS one 2710", ALC275_FIXUP_DELL_XPS),
@@ -10882,9 +10895,12 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8e1a, "HP ZBook Firefly 14 G12A", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A),
SND_PCI_QUIRK(0x103c, 0x8e1b, "HP EliteBook G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A),
SND_PCI_QUIRK(0x103c, 0x8e1c, "HP EliteBook G12", ALC245_FIXUP_HP_ZBOOK_FIREFLY_G12A),
+ SND_PCI_QUIRK(0x103c, 0x8e1d, "HP ZBook X Gli 16 G12", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8e2c, "HP EliteBook 16 G12", ALC285_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8e36, "HP 14 Enstrom OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8e37, "HP 16 Piston OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x103c, 0x8e3a, "HP Agusta", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x103c, 0x8e3b, "HP Agusta", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8e60, "HP Trekker ", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8e61, "HP Trekker ", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8e62, "HP Trekker ", ALC287_FIXUP_CS35L41_I2C_2),
@@ -11300,6 +11316,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x38fa, "Thinkbook 16P Gen5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x38fd, "ThinkBook plus Gen5 Hybrid", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
+ SND_PCI_QUIRK(0x17aa, 0x390d, "Lenovo Yoga Pro 7 14ASP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
SND_PCI_QUIRK(0x17aa, 0x3913, "Lenovo 145", ALC236_FIXUP_LENOVO_INV_DMIC),
SND_PCI_QUIRK(0x17aa, 0x391f, "Yoga S990-16 pro Quad YC Quad", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3920, "Yoga S990-16 pro Quad VECO Quad", ALC287_FIXUP_TAS2781_I2C),
diff --git a/sound/pci/hda/tas2781-spi.h b/sound/pci/hda/tas2781-spi.h
deleted file mode 100644
index 7a0faceeb675..000000000000
--- a/sound/pci/hda/tas2781-spi.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-//
-// ALSA SoC Texas Instruments TAS2781 Audio Smart Amplifier
-//
-// Copyright (C) 2024 Texas Instruments Incorporated
-// https://www.ti.com
-//
-// The TAS2781 driver implements a flexible and configurable
-// algo coefficient setting for TAS2781 chips.
-//
-// Author: Baojun Xu <baojun.xu@ti.com>
-//
-
-#ifndef __TAS2781_SPI_H__
-#define __TAS2781_SPI_H__
-
-#define TASDEVICE_RATES \
- (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
- SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_88200)
-
-#define TASDEVICE_FORMATS \
- (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | \
- SNDRV_PCM_FMTBIT_S32_LE)
-
-#define TASDEVICE_MAX_BOOK_NUM 256
-#define TASDEVICE_MAX_PAGE 256
-
-#define TASDEVICE_MAX_SIZE (TASDEVICE_MAX_BOOK_NUM * TASDEVICE_MAX_PAGE)
-
-/* PAGE Control Register (available in page0 of each book) */
-#define TASDEVICE_PAGE_SELECT 0x00
-#define TASDEVICE_BOOKCTL_PAGE 0x00
-#define TASDEVICE_BOOKCTL_REG GENMASK(7, 1)
-#define TASDEVICE_BOOK_ID(reg) (((reg) & GENMASK(24, 16)) >> 16)
-#define TASDEVICE_PAGE_ID(reg) (((reg) & GENMASK(15, 8)) >> 8)
-#define TASDEVICE_REG_ID(reg) (((reg) & GENMASK(7, 1)) >> 1)
-#define TASDEVICE_PAGE_REG(reg) ((reg) & GENMASK(15, 1))
-#define TASDEVICE_REG(book, page, reg) \
- (((book) << 16) | ((page) << 8) | ((reg) << 1))
-
-/* Software Reset */
-#define TAS2781_REG_SWRESET TASDEVICE_REG(0x0, 0x0, 0x01)
-#define TAS2781_REG_SWRESET_RESET BIT(0)
-
-/* System Reset Check Register */
-#define TAS2781_REG_CLK_CONFIG TASDEVICE_REG(0x0, 0x0, 0x5c)
-#define TAS2781_REG_CLK_CONFIG_RESET (0x19)
-#define TAS2781_PRE_POST_RESET_CFG 3
-
-/* Block Checksum */
-#define TASDEVICE_CHECKSUM TASDEVICE_REG(0x0, 0x0, 0x7e)
-
-/* Volume control */
-#define TAS2781_DVC_LVL TASDEVICE_REG(0x0, 0x0, 0x1a)
-#define TAS2781_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x03)
-#define TAS2781_AMP_LEVEL_MASK GENMASK(5, 1)
-
-#define TASDEVICE_CMD_SING_W 0x1
-#define TASDEVICE_CMD_BURST 0x2
-#define TASDEVICE_CMD_DELAY 0x3
-#define TASDEVICE_CMD_FIELD_W 0x4
-
-#define TAS2781_SPI_MAX_FREQ (4 * HZ_PER_MHZ)
-
-#define TASDEVICE_CRC8_POLYNOMIAL 0x4d
-#define TASDEVICE_SPEAKER_CALIBRATION_SIZE 20
-
-/* Flag of calibration registers address. */
-#define TASDEVICE_CALIBRATION_REG_ADDRESS BIT(7)
-
-#define TASDEVICE_CALIBRATION_DATA_NAME L"CALI_DATA"
-#define TASDEVICE_CALIBRATION_DATA_SIZE 256
-
-enum calib_data {
- R0_VAL = 0,
- INV_R0,
- R0LOW,
- POWER,
- TLIM,
- CALIB_MAX
-};
-
-struct tasdevice_priv {
- struct tasdevice_fw *cali_data_fmw;
- struct tasdevice_rca rcabin;
- struct tasdevice_fw *fmw;
- struct gpio_desc *reset;
- struct mutex codec_lock;
- struct regmap *regmap;
- struct device *dev;
-
- unsigned char crc8_lkp_tbl[CRC8_TABLE_SIZE];
- unsigned char coef_binaryname[64];
- unsigned char rca_binaryname[64];
- unsigned char dev_name[32];
-
- bool force_fwload_status;
- bool playback_started;
- bool is_loading;
- bool is_loaderr;
- unsigned int cali_reg_array[CALIB_MAX];
- unsigned int cali_data[CALIB_MAX];
- unsigned int err_code;
- void *codec;
- int cur_book;
- int cur_prog;
- int cur_conf;
- int fw_state;
- int index;
- int irq;
-
- int (*fw_parse_variable_header)(struct tasdevice_priv *tas_priv,
- const struct firmware *fmw,
- int offset);
- int (*fw_parse_program_data)(struct tasdevice_priv *tas_priv,
- struct tasdevice_fw *tas_fmw,
- const struct firmware *fmw, int offset);
- int (*fw_parse_configuration_data)(struct tasdevice_priv *tas_priv,
- struct tasdevice_fw *tas_fmw,
- const struct firmware *fmw,
- int offset);
- int (*tasdevice_load_block)(struct tasdevice_priv *tas_priv,
- struct tasdev_blk *block);
-
- int (*save_calibration)(struct tasdevice_priv *tas_priv);
- void (*apply_calibration)(struct tasdevice_priv *tas_priv);
-};
-
-int tasdevice_spi_dev_read(struct tasdevice_priv *tas_priv,
- unsigned int reg, unsigned int *value);
-int tasdevice_spi_dev_write(struct tasdevice_priv *tas_priv,
- unsigned int reg, unsigned int value);
-int tasdevice_spi_dev_bulk_write(struct tasdevice_priv *tas_priv,
- unsigned int reg, unsigned char *p_data,
- unsigned int n_length);
-int tasdevice_spi_dev_bulk_read(struct tasdevice_priv *tas_priv,
- unsigned int reg, unsigned char *p_data,
- unsigned int n_length);
-int tasdevice_spi_dev_update_bits(struct tasdevice_priv *tasdevice,
- unsigned int reg, unsigned int mask,
- unsigned int value);
-
-void tasdevice_spi_select_cfg_blk(void *context, int conf_no,
- unsigned char block_type);
-void tasdevice_spi_config_info_remove(void *context);
-int tasdevice_spi_dsp_parser(void *context);
-int tasdevice_spi_rca_parser(void *context, const struct firmware *fmw);
-void tasdevice_spi_dsp_remove(void *context);
-void tasdevice_spi_calbin_remove(void *context);
-int tasdevice_spi_select_tuningprm_cfg(void *context, int prm, int cfg_no,
- int rca_conf_no);
-int tasdevice_spi_prmg_load(void *context, int prm_no);
-int tasdevice_spi_prmg_calibdata_load(void *context, int prm_no);
-void tasdevice_spi_tuning_switch(void *context, int state);
-int tas2781_spi_load_calibration(void *context, char *file_name,
- unsigned short i);
-#endif /* __TAS2781_SPI_H__ */
diff --git a/sound/pci/hda/tas2781_hda.c b/sound/pci/hda/tas2781_hda.c
new file mode 100644
index 000000000000..5f1d4b3e9688
--- /dev/null
+++ b/sound/pci/hda/tas2781_hda.c
@@ -0,0 +1,377 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// TAS2781 HDA Shared Lib for I2C&SPI driver
+//
+// Copyright 2025 Texas Instruments, Inc.
+//
+// Author: Shenghao Ding <shenghao-ding@ti.com>
+
+#include <linux/component.h>
+#include <linux/crc8.h>
+#include <linux/crc32.h>
+#include <linux/efi.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <sound/soc.h>
+#include <sound/tas2781.h>
+
+#include "tas2781_hda.h"
+
+const efi_guid_t tasdev_fct_efi_guid[] = {
+ /* DELL */
+ EFI_GUID(0xcc92382d, 0x6337, 0x41cb, 0xa8, 0x8b, 0x8e, 0xce, 0x74,
+ 0x91, 0xea, 0x9f),
+ /* HP */
+ EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d, 0x93, 0xfe, 0x5a,
+ 0xa3, 0x5d, 0xb3),
+ /* LENOVO & OTHERS */
+ EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, 0x09, 0x43, 0xa3, 0xf4,
+ 0x31, 0x0a, 0x92),
+};
+EXPORT_SYMBOL_NS_GPL(tasdev_fct_efi_guid, "SND_HDA_SCODEC_TAS2781");
+
+static void tas2781_apply_calib(struct tasdevice_priv *p)
+{
+ struct calidata *cali_data = &p->cali_data;
+ struct cali_reg *r = &cali_data->cali_reg_array;
+ unsigned char *data = cali_data->data;
+ unsigned int *tmp_val = (unsigned int *)data;
+ unsigned int cali_reg[TASDEV_CALIB_N] = {
+ TASDEVICE_REG(0, 0x17, 0x74),
+ TASDEVICE_REG(0, 0x18, 0x0c),
+ TASDEVICE_REG(0, 0x18, 0x14),
+ TASDEVICE_REG(0, 0x13, 0x70),
+ TASDEVICE_REG(0, 0x18, 0x7c),
+ };
+ unsigned int crc, oft;
+ unsigned char *buf;
+ int i, j, k, l;
+
+ if (tmp_val[0] == 2781) {
+ /*
+ * New features were added in calibrated Data V3:
+ * 1. Added calibration registers address define in
+ * a node, marked as Device id == 0x80.
+ * New features were added in calibrated Data V2:
+ * 1. Added some the fields to store the link_id and
+ * uniqie_id for multi-link solutions
+ * 2. Support flexible number of devices instead of
+ * fixed one in V1.
+ * Layout of calibrated data V2 in UEFI(total 256 bytes):
+ * ChipID (2781, 4 bytes)
+ * Data-Group-Sum (4 bytes)
+ * TimeStamp of Calibration (4 bytes)
+ * for (i = 0; i < Data-Group-Sum; i++) {
+ * if (Data type != 0x80) (4 bytes)
+ * Calibrated Data of Device #i (20 bytes)
+ * else
+ * Calibration registers address (5*4 = 20 bytes)
+ * # V2: No reg addr in data grp section.
+ * # V3: Normally the last grp is the reg addr.
+ * }
+ * CRC (4 bytes)
+ * Reserved (the rest)
+ */
+ crc = crc32(~0, data, (3 + tmp_val[1] * 6) * 4) ^ ~0;
+
+ if (crc != tmp_val[3 + tmp_val[1] * 6]) {
+ cali_data->total_sz = 0;
+ dev_err(p->dev, "%s: CRC error\n", __func__);
+ return;
+ }
+
+ for (j = 0, k = 0; j < tmp_val[1]; j++) {
+ oft = j * 6 + 3;
+ if (tmp_val[oft] == TASDEV_UEFI_CALI_REG_ADDR_FLG) {
+ for (i = 0; i < TASDEV_CALIB_N; i++) {
+ buf = &data[(oft + i + 1) * 4];
+ cali_reg[i] = TASDEVICE_REG(buf[1],
+ buf[2], buf[3]);
+ }
+ } else {
+ l = j * (cali_data->cali_dat_sz_per_dev + 1);
+ if (k >= p->ndev || l > oft * 4) {
+ dev_err(p->dev, "%s: dev sum error\n",
+ __func__);
+ cali_data->total_sz = 0;
+ return;
+ }
+
+ data[l] = k;
+ for (i = 0; i < TASDEV_CALIB_N * 4; i++)
+ data[l + i] = data[4 * oft + i];
+ k++;
+ }
+ }
+ } else {
+ /*
+ * Calibration data is in V1 format.
+ * struct cali_data {
+ * char cali_data[20];
+ * }
+ *
+ * struct {
+ * struct cali_data cali_data[4];
+ * int TimeStamp of Calibration (4 bytes)
+ * int CRC (4 bytes)
+ * } ueft;
+ */
+ crc = crc32(~0, data, 84) ^ ~0;
+ if (crc != tmp_val[21]) {
+ cali_data->total_sz = 0;
+ dev_err(p->dev, "%s: V1 CRC error\n", __func__);
+ return;
+ }
+
+ for (j = p->ndev - 1; j >= 0; j--) {
+ l = j * (cali_data->cali_dat_sz_per_dev + 1);
+ for (i = TASDEV_CALIB_N * 4; i > 0 ; i--)
+ data[l + i] = data[p->index * 5 + i];
+ data[l+i] = j;
+ }
+ }
+
+ if (p->dspbin_typ == TASDEV_BASIC) {
+ r->r0_reg = cali_reg[0];
+ r->invr0_reg = cali_reg[1];
+ r->r0_low_reg = cali_reg[2];
+ r->pow_reg = cali_reg[3];
+ r->tlimit_reg = cali_reg[4];
+ }
+
+ p->is_user_space_calidata = true;
+ cali_data->total_sz = p->ndev * (cali_data->cali_dat_sz_per_dev + 1);
+}
+
+/*
+ * Update the calibration data, including speaker impedance, f0, etc,
+ * into algo. Calibrate data is done by manufacturer in the factory.
+ * The data is used by Algo for calculating the speaker temperature,
+ * speaker membrane excursion and f0 in real time during playback.
+ * Calibration data format in EFI is V2, since 2024.
+ */
+int tas2781_save_calibration(struct tas2781_hda *hda)
+{
+ /*
+ * GUID was used for data access in BIOS, it was provided by board
+ * manufactory.
+ */
+ efi_guid_t efi_guid = tasdev_fct_efi_guid[LENOVO];
+ static efi_char16_t efi_name[] = TASDEVICE_CALIBRATION_DATA_NAME;
+ struct tasdevice_priv *p = hda->priv;
+ struct calidata *cali_data = &p->cali_data;
+ unsigned long total_sz = 0;
+ unsigned int attr, size;
+ unsigned char *data;
+ efi_status_t status;
+
+ if (hda->catlog_id < LENOVO)
+ efi_guid = tasdev_fct_efi_guid[hda->catlog_id];
+
+ cali_data->cali_dat_sz_per_dev = 20;
+ size = p->ndev * (cali_data->cali_dat_sz_per_dev + 1);
+ /* Get real size of UEFI variable */
+ status = efi.get_variable(efi_name, &efi_guid, &attr, &total_sz, NULL);
+ cali_data->total_sz = total_sz > size ? total_sz : size;
+ if (status == EFI_BUFFER_TOO_SMALL) {
+ /* Allocate data buffer of data_size bytes */
+ data = p->cali_data.data = devm_kzalloc(p->dev,
+ p->cali_data.total_sz, GFP_KERNEL);
+ if (!data) {
+ p->cali_data.total_sz = 0;
+ return -ENOMEM;
+ }
+ /* Get variable contents into buffer */
+ status = efi.get_variable(efi_name, &efi_guid, &attr,
+ &p->cali_data.total_sz, data);
+ }
+ if (status != EFI_SUCCESS) {
+ p->cali_data.total_sz = 0;
+ return status;
+ }
+
+ tas2781_apply_calib(p);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(tas2781_save_calibration, "SND_HDA_SCODEC_TAS2781");
+
+void tas2781_hda_remove(struct device *dev,
+ const struct component_ops *ops)
+{
+ struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
+
+ component_del(tas_hda->dev, ops);
+
+ pm_runtime_get_sync(tas_hda->dev);
+ pm_runtime_disable(tas_hda->dev);
+
+ pm_runtime_put_noidle(tas_hda->dev);
+
+ tasdevice_remove(tas_hda->priv);
+}
+EXPORT_SYMBOL_NS_GPL(tas2781_hda_remove, "SND_HDA_SCODEC_TAS2781");
+
+int tasdevice_info_profile(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = tas_priv->rcabin.ncfgs - 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(tasdevice_info_profile, "SND_HDA_SCODEC_TAS2781");
+
+int tasdevice_info_programs(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = tas_priv->fmw->nr_programs - 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(tasdevice_info_programs, "SND_HDA_SCODEC_TAS2781");
+
+int tasdevice_info_config(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+ struct tasdevice_fw *tas_fw = tas_priv->fmw;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = tas_fw->nr_configurations - 1;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(tasdevice_info_config, "SND_HDA_SCODEC_TAS2781");
+
+int tasdevice_get_profile_id(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = tas_priv->rcabin.profile_cfg_id;
+
+ dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", __func__,
+ kcontrol->id.name, tas_priv->rcabin.profile_cfg_id);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(tasdevice_get_profile_id, "SND_HDA_SCODEC_TAS2781");
+
+int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+ int profile_id = ucontrol->value.integer.value[0];
+ int max = tas_priv->rcabin.ncfgs - 1;
+ int val, ret = 0;
+
+ val = clamp(profile_id, 0, max);
+
+ guard(mutex)(&tas_priv->codec_lock);
+
+ dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", __func__,
+ kcontrol->id.name, tas_priv->rcabin.profile_cfg_id, val);
+
+ if (tas_priv->rcabin.profile_cfg_id != val) {
+ tas_priv->rcabin.profile_cfg_id = val;
+ ret = 1;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(tasdevice_set_profile_id, "SND_HDA_SCODEC_TAS2781");
+
+int tasdevice_program_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = tas_priv->cur_prog;
+
+ dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", __func__,
+ kcontrol->id.name, tas_priv->cur_prog);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(tasdevice_program_get, "SND_HDA_SCODEC_TAS2781");
+
+int tasdevice_program_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+ struct tasdevice_fw *tas_fw = tas_priv->fmw;
+ int nr_program = ucontrol->value.integer.value[0];
+ int max = tas_fw->nr_programs - 1;
+ int val, ret = 0;
+
+ val = clamp(nr_program, 0, max);
+
+ guard(mutex)(&tas_priv->codec_lock);
+
+ dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", __func__,
+ kcontrol->id.name, tas_priv->cur_prog, val);
+
+ if (tas_priv->cur_prog != val) {
+ tas_priv->cur_prog = val;
+ ret = 1;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(tasdevice_program_put, "SND_HDA_SCODEC_TAS2781");
+
+int tasdevice_config_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = tas_priv->cur_conf;
+
+ dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n", __func__,
+ kcontrol->id.name, tas_priv->cur_conf);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(tasdevice_config_get, "SND_HDA_SCODEC_TAS2781");
+
+int tasdevice_config_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
+ struct tasdevice_fw *tas_fw = tas_priv->fmw;
+ int nr_config = ucontrol->value.integer.value[0];
+ int max = tas_fw->nr_configurations - 1;
+ int val, ret = 0;
+
+ val = clamp(nr_config, 0, max);
+
+ guard(mutex)(&tas_priv->codec_lock);
+
+ dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n", __func__,
+ kcontrol->id.name, tas_priv->cur_conf, val);
+
+ if (tas_priv->cur_conf != val) {
+ tas_priv->cur_conf = val;
+ ret = 1;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(tasdevice_config_put, "SND_HDA_SCODEC_TAS2781");
+
+MODULE_DESCRIPTION("TAS2781 HDA Driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>");
diff --git a/sound/pci/hda/tas2781_hda.h b/sound/pci/hda/tas2781_hda.h
new file mode 100644
index 000000000000..575a701c8dfb
--- /dev/null
+++ b/sound/pci/hda/tas2781_hda.h
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0-only
+ *
+ * HDA audio driver for Texas Instruments TAS2781 smart amp
+ *
+ * Copyright (C) 2025 Texas Instruments, Inc.
+ */
+#ifndef __TAS2781_HDA_H__
+#define __TAS2781_HDA_H__
+
+#include <sound/asound.h>
+
+/* Flag of calibration registers address. */
+#define TASDEV_UEFI_CALI_REG_ADDR_FLG BIT(7)
+#define TASDEVICE_CALIBRATION_DATA_NAME L"CALI_DATA"
+#define TASDEV_CALIB_N 5
+
+/*
+ * No standard control callbacks for SNDRV_CTL_ELEM_IFACE_CARD
+ * Define two controls, one is Volume control callbacks, the other is
+ * flag setting control callbacks.
+ */
+
+/* Volume control callbacks for tas2781 */
+#define ACARD_SINGLE_RANGE_EXT_TLV(xname, xreg, xshift, xmin, xmax, xinvert, \
+ xhandler_get, xhandler_put, tlv_array) { \
+ .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = (xname), \
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
+ SNDRV_CTL_ELEM_ACCESS_READWRITE, \
+ .tlv.p = (tlv_array), \
+ .info = snd_soc_info_volsw, \
+ .get = xhandler_get, .put = xhandler_put, \
+ .private_value = (unsigned long)&(struct soc_mixer_control) { \
+ .reg = xreg, .rreg = xreg, \
+ .shift = xshift, .rshift = xshift,\
+ .min = xmin, .max = xmax, .invert = xinvert, \
+ } \
+}
+
+/* Flag control callbacks for tas2781 */
+#define ACARD_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) { \
+ .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
+ .name = xname, \
+ .info = snd_ctl_boolean_mono_info, \
+ .get = xhandler_get, \
+ .put = xhandler_put, \
+ .private_value = xdata, \
+}
+
+enum device_catlog_id {
+ DELL = 0,
+ HP,
+ LENOVO,
+ OTHERS
+};
+
+struct tas2781_hda {
+ struct device *dev;
+ struct tasdevice_priv *priv;
+ struct snd_kcontrol *dsp_prog_ctl;
+ struct snd_kcontrol *dsp_conf_ctl;
+ struct snd_kcontrol *prof_ctl;
+ enum device_catlog_id catlog_id;
+ void *hda_priv;
+};
+
+extern const efi_guid_t tasdev_fct_efi_guid[];
+
+int tas2781_save_calibration(struct tas2781_hda *p);
+void tas2781_hda_remove(struct device *dev,
+ const struct component_ops *ops);
+int tasdevice_info_profile(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_info *uctl);
+int tasdevice_info_programs(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_info *uctl);
+int tasdevice_info_config(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_info *uctl);
+int tasdevice_set_profile_id(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *uctl);
+int tasdevice_get_profile_id(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *uctl);
+int tasdevice_program_get(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *uctl);
+int tasdevice_program_put(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *uctl);
+int tasdevice_config_put(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *uctl);
+int tasdevice_config_get(struct snd_kcontrol *kctl,
+ struct snd_ctl_elem_value *uctl);
+
+#endif
diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c
index 29dc4f500580..d91eed9f7804 100644
--- a/sound/pci/hda/tas2781_hda_i2c.c
+++ b/sound/pci/hda/tas2781_hda_i2c.c
@@ -2,7 +2,7 @@
//
// TAS2781 HDA I2C driver
//
-// Copyright 2023 - 2024 Texas Instruments, Inc.
+// Copyright 2023 - 2025 Texas Instruments, Inc.
//
// Author: Shenghao Ding <shenghao-ding@ti.com>
// Current maintainer: Baojun Xu <baojun.xu@ti.com>
@@ -22,6 +22,7 @@
#include <sound/hda_codec.h>
#include <sound/soc.h>
#include <sound/tas2781.h>
+#include <sound/tas2781-comlib-i2c.h>
#include <sound/tlv.h>
#include <sound/tas2781-tlv.h>
@@ -30,69 +31,23 @@
#include "hda_component.h"
#include "hda_jack.h"
#include "hda_generic.h"
+#include "tas2781_hda.h"
-#define TASDEVICE_SPEAKER_CALIBRATION_SIZE 20
-
-/* No standard control callbacks for SNDRV_CTL_ELEM_IFACE_CARD
- * Define two controls, one is Volume control callbacks, the other is
- * flag setting control callbacks.
- */
-
-/* Volume control callbacks for tas2781 */
-#define ACARD_SINGLE_RANGE_EXT_TLV(xname, xreg, xshift, xmin, xmax, xinvert, \
- xhandler_get, xhandler_put, tlv_array) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = (xname),\
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
- SNDRV_CTL_ELEM_ACCESS_READWRITE,\
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw, \
- .get = xhandler_get, .put = xhandler_put, \
- .private_value = (unsigned long)&(struct soc_mixer_control) \
- {.reg = xreg, .rreg = xreg, .shift = xshift, \
- .rshift = xshift, .min = xmin, .max = xmax, \
- .invert = xinvert} }
-
-/* Flag control callbacks for tas2781 */
-#define ACARD_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = xname, \
- .info = snd_ctl_boolean_mono_info, \
- .get = xhandler_get, .put = xhandler_put, \
- .private_value = xdata }
-
-enum calib_data {
- R0_VAL = 0,
- INV_R0,
- R0LOW,
- POWER,
- TLIM,
- CALIB_MAX
-};
-
-#define TAS2563_MAX_CHANNELS 4
-
-#define TAS2563_CAL_POWER TASDEVICE_REG(0, 0x0d, 0x3c)
-#define TAS2563_CAL_R0 TASDEVICE_REG(0, 0x0f, 0x34)
-#define TAS2563_CAL_INVR0 TASDEVICE_REG(0, 0x0f, 0x40)
-#define TAS2563_CAL_R0_LOW TASDEVICE_REG(0, 0x0f, 0x48)
-#define TAS2563_CAL_TLIM TASDEVICE_REG(0, 0x10, 0x14)
-#define TAS2563_CAL_N 5
-#define TAS2563_CAL_DATA_SIZE 4
-#define TAS2563_CAL_CH_SIZE 20
-#define TAS2563_CAL_ARRAY_SIZE 80
-
-static unsigned int cal_regs[TAS2563_CAL_N] = {
- TAS2563_CAL_POWER, TAS2563_CAL_R0, TAS2563_CAL_INVR0,
- TAS2563_CAL_R0_LOW, TAS2563_CAL_TLIM,
-};
+#define TAS2563_CAL_VAR_NAME_MAX 16
+#define TAS2563_CAL_ARRAY_SIZE 80
+#define TAS2563_CAL_DATA_SIZE 4
+#define TAS2563_MAX_CHANNELS 4
+#define TAS2563_CAL_CH_SIZE 20
+#define TAS2563_CAL_R0_LOW TASDEVICE_REG(0, 0x0f, 0x48)
+#define TAS2563_CAL_POWER TASDEVICE_REG(0, 0x0d, 0x3c)
+#define TAS2563_CAL_INVR0 TASDEVICE_REG(0, 0x0f, 0x40)
+#define TAS2563_CAL_TLIM TASDEVICE_REG(0, 0x10, 0x14)
+#define TAS2563_CAL_R0 TASDEVICE_REG(0, 0x0f, 0x34)
-struct tas2781_hda {
- struct device *dev;
- struct tasdevice_priv *priv;
- struct snd_kcontrol *dsp_prog_ctl;
- struct snd_kcontrol *dsp_conf_ctl;
- struct snd_kcontrol *prof_ctl;
+struct tas2781_hda_i2c_priv {
struct snd_kcontrol *snd_ctls[2];
+ int (*save_calibration)(struct tas2781_hda *h);
};
static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data)
@@ -210,176 +165,6 @@ static void tas2781_hda_playback_hook(struct device *dev, int action)
}
}
-static int tasdevice_info_profile(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = tas_priv->rcabin.ncfgs - 1;
-
- return 0;
-}
-
-static int tasdevice_get_profile_id(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- mutex_lock(&tas_priv->codec_lock);
-
- ucontrol->value.integer.value[0] = tas_priv->rcabin.profile_cfg_id;
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n",
- __func__, kcontrol->id.name, tas_priv->rcabin.profile_cfg_id);
-
- mutex_unlock(&tas_priv->codec_lock);
-
- return 0;
-}
-
-static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- int nr_profile = ucontrol->value.integer.value[0];
- int max = tas_priv->rcabin.ncfgs - 1;
- int val, ret = 0;
-
- val = clamp(nr_profile, 0, max);
-
- mutex_lock(&tas_priv->codec_lock);
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n",
- __func__, kcontrol->id.name,
- tas_priv->rcabin.profile_cfg_id, val);
-
- if (tas_priv->rcabin.profile_cfg_id != val) {
- tas_priv->rcabin.profile_cfg_id = val;
- ret = 1;
- }
-
- mutex_unlock(&tas_priv->codec_lock);
-
- return ret;
-}
-
-static int tasdevice_info_programs(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- struct tasdevice_fw *tas_fw = tas_priv->fmw;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = tas_fw->nr_programs - 1;
-
- return 0;
-}
-
-static int tasdevice_info_config(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- struct tasdevice_fw *tas_fw = tas_priv->fmw;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = tas_fw->nr_configurations - 1;
-
- return 0;
-}
-
-static int tasdevice_program_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- mutex_lock(&tas_priv->codec_lock);
-
- ucontrol->value.integer.value[0] = tas_priv->cur_prog;
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n",
- __func__, kcontrol->id.name, tas_priv->cur_prog);
-
- mutex_unlock(&tas_priv->codec_lock);
-
- return 0;
-}
-
-static int tasdevice_program_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- struct tasdevice_fw *tas_fw = tas_priv->fmw;
- int nr_program = ucontrol->value.integer.value[0];
- int max = tas_fw->nr_programs - 1;
- int val, ret = 0;
-
- val = clamp(nr_program, 0, max);
-
- mutex_lock(&tas_priv->codec_lock);
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n",
- __func__, kcontrol->id.name, tas_priv->cur_prog, val);
-
- if (tas_priv->cur_prog != val) {
- tas_priv->cur_prog = val;
- ret = 1;
- }
-
- mutex_unlock(&tas_priv->codec_lock);
-
- return ret;
-}
-
-static int tasdevice_config_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- mutex_lock(&tas_priv->codec_lock);
-
- ucontrol->value.integer.value[0] = tas_priv->cur_conf;
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d\n",
- __func__, kcontrol->id.name, tas_priv->cur_conf);
-
- mutex_unlock(&tas_priv->codec_lock);
-
- return 0;
-}
-
-static int tasdevice_config_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- struct tasdevice_fw *tas_fw = tas_priv->fmw;
- int nr_config = ucontrol->value.integer.value[0];
- int max = tas_fw->nr_configurations - 1;
- int val, ret = 0;
-
- val = clamp(nr_config, 0, max);
-
- mutex_lock(&tas_priv->codec_lock);
-
- dev_dbg(tas_priv->dev, "%s: kcontrol %s: %d -> %d\n",
- __func__, kcontrol->id.name, tas_priv->cur_conf, val);
-
- if (tas_priv->cur_conf != val) {
- tas_priv->cur_conf = val;
- ret = 1;
- }
-
- mutex_unlock(&tas_priv->codec_lock);
-
- return ret;
-}
-
static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -493,170 +278,103 @@ static const struct snd_kcontrol_new tas2781_dsp_conf_ctrl = {
.put = tasdevice_config_put,
};
-static void tas2563_apply_calib(struct tasdevice_priv *tas_priv)
+static int tas2563_save_calibration(struct tas2781_hda *h)
{
- int offset = 0;
- __be32 data;
- int ret;
-
- for (int i = 0; i < tas_priv->ndev; i++) {
- for (int j = 0; j < TAS2563_CAL_N; ++j) {
- data = cpu_to_be32(
- *(uint32_t *)&tas_priv->cali_data.data[offset]);
- ret = tasdevice_dev_bulk_write(tas_priv, i, cal_regs[j],
- (unsigned char *)&data, TAS2563_CAL_DATA_SIZE);
- if (ret)
- dev_err(tas_priv->dev,
- "Error writing calib regs\n");
- offset += TAS2563_CAL_DATA_SIZE;
- }
- }
-}
-
-static int tas2563_save_calibration(struct tasdevice_priv *tas_priv)
-{
- static efi_guid_t efi_guid = EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc,
- 0x09, 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92);
-
- static efi_char16_t *efi_vars[TAS2563_MAX_CHANNELS][TAS2563_CAL_N] = {
- { L"Power_1", L"R0_1", L"InvR0_1", L"R0_Low_1", L"TLim_1" },
- { L"Power_2", L"R0_2", L"InvR0_2", L"R0_Low_2", L"TLim_2" },
- { L"Power_3", L"R0_3", L"InvR0_3", L"R0_Low_3", L"TLim_3" },
- { L"Power_4", L"R0_4", L"InvR0_4", L"R0_Low_4", L"TLim_4" },
+ efi_guid_t efi_guid = tasdev_fct_efi_guid[LENOVO];
+ char *vars[TASDEV_CALIB_N] = {
+ "R0_%d", "InvR0_%d", "R0_Low_%d", "Power_%d", "TLim_%d"
};
-
+ efi_char16_t efi_name[TAS2563_CAL_VAR_NAME_MAX];
unsigned long max_size = TAS2563_CAL_DATA_SIZE;
+ unsigned char var8[TAS2563_CAL_VAR_NAME_MAX];
+ struct tasdevice_priv *p = h->hda_priv;
+ struct calidata *cd = &p->cali_data;
+ struct cali_reg *r = &cd->cali_reg_array;
unsigned int offset = 0;
+ unsigned char *data;
efi_status_t status;
unsigned int attr;
+ int ret, i, j, k;
+
+ cd->cali_dat_sz_per_dev = TAS2563_CAL_DATA_SIZE * TASDEV_CALIB_N;
- tas_priv->cali_data.data = devm_kzalloc(tas_priv->dev,
- TAS2563_CAL_ARRAY_SIZE, GFP_KERNEL);
- if (!tas_priv->cali_data.data)
+ /* extra byte for each device is the device number */
+ cd->total_sz = (cd->cali_dat_sz_per_dev + 1) * p->ndev;
+ data = cd->data = devm_kzalloc(p->dev, cd->total_sz,
+ GFP_KERNEL);
+ if (!data)
return -ENOMEM;
- for (int i = 0; i < tas_priv->ndev; ++i) {
- for (int j = 0; j < TAS2563_CAL_N; ++j) {
- status = efi.get_variable(efi_vars[i][j],
+ for (i = 0; i < p->ndev; ++i) {
+ data[offset] = i;
+ offset++;
+ for (j = 0; j < TASDEV_CALIB_N; ++j) {
+ ret = snprintf(var8, sizeof(var8), vars[j], i);
+
+ if (ret < 0 || ret >= sizeof(var8) - 1) {
+ dev_err(p->dev, "%s: Read %s failed\n",
+ __func__, var8);
+ return -EINVAL;
+ }
+ /*
+ * Our variable names are ASCII by construction, but
+ * EFI names are wide chars. Convert and zero-pad.
+ */
+ memset(efi_name, 0, sizeof(efi_name));
+ for (k = 0; k < sizeof(var8) && var8[k]; k++)
+ efi_name[k] = var8[k];
+ status = efi.get_variable(efi_name,
&efi_guid, &attr, &max_size,
- &tas_priv->cali_data.data[offset]);
+ &data[offset]);
if (status != EFI_SUCCESS ||
max_size != TAS2563_CAL_DATA_SIZE) {
- dev_warn(tas_priv->dev,
- "Calibration data read failed %ld\n", status);
+ dev_warn(p->dev,
+ "Dev %d: Caldat[%d] read failed %ld\n",
+ i, j, status);
return -EINVAL;
}
offset += TAS2563_CAL_DATA_SIZE;
}
}
- tas_priv->cali_data.total_sz = offset;
- tasdevice_apply_calibration(tas_priv);
-
- return 0;
-}
-
-static void tas2781_apply_calib(struct tasdevice_priv *tas_priv)
-{
- struct calidata *cali_data = &tas_priv->cali_data;
- struct cali_reg *r = &cali_data->cali_reg_array;
- unsigned int cali_reg[CALIB_MAX] = {
- TASDEVICE_REG(0, 0x17, 0x74),
- TASDEVICE_REG(0, 0x18, 0x0c),
- TASDEVICE_REG(0, 0x18, 0x14),
- TASDEVICE_REG(0, 0x13, 0x70),
- TASDEVICE_REG(0, 0x18, 0x7c),
- };
- int i, j, rc;
- int oft = 0;
- __be32 data;
-
- if (tas_priv->dspbin_typ != TASDEV_BASIC) {
- cali_reg[0] = r->r0_reg;
- cali_reg[1] = r->invr0_reg;
- cali_reg[2] = r->r0_low_reg;
- cali_reg[3] = r->pow_reg;
- cali_reg[4] = r->tlimit_reg;
- }
-
- for (i = 0; i < tas_priv->ndev; i++) {
- for (j = 0; j < CALIB_MAX; j++) {
- data = cpu_to_be32(
- *(uint32_t *)&tas_priv->cali_data.data[oft]);
- rc = tasdevice_dev_bulk_write(tas_priv, i,
- cali_reg[j], (unsigned char *)&data, 4);
- if (rc < 0)
- dev_err(tas_priv->dev,
- "chn %d calib %d bulk_wr err = %d\n",
- i, j, rc);
- oft += 4;
- }
- }
-}
-
-/* Update the calibration data, including speaker impedance, f0, etc, into algo.
- * Calibrate data is done by manufacturer in the factory. These data are used
- * by Algo for calculating the speaker temperature, speaker membrane excursion
- * and f0 in real time during playback.
- */
-static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
-{
- efi_guid_t efi_guid = EFI_GUID(0x02f9af02, 0x7734, 0x4233, 0xb4, 0x3d,
- 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3);
- static efi_char16_t efi_name[] = L"CALI_DATA";
- unsigned int attr, crc;
- unsigned int *tmp_val;
- efi_status_t status;
-
- /* Lenovo devices */
- if (tas_priv->catlog_id == LENOVO)
- efi_guid = EFI_GUID(0x1f52d2a1, 0xbb3a, 0x457d, 0xbc, 0x09,
- 0x43, 0xa3, 0xf4, 0x31, 0x0a, 0x92);
-
- tas_priv->cali_data.total_sz = 0;
- /* Get real size of UEFI variable */
- status = efi.get_variable(efi_name, &efi_guid, &attr,
- &tas_priv->cali_data.total_sz, tas_priv->cali_data.data);
- if (status == EFI_BUFFER_TOO_SMALL) {
- /* Allocate data buffer of data_size bytes */
- tas_priv->cali_data.data = devm_kzalloc(tas_priv->dev,
- tas_priv->cali_data.total_sz, GFP_KERNEL);
- if (!tas_priv->cali_data.data)
- return -ENOMEM;
- /* Get variable contents into buffer */
- status = efi.get_variable(efi_name, &efi_guid, &attr,
- &tas_priv->cali_data.total_sz,
- tas_priv->cali_data.data);
- }
- if (status != EFI_SUCCESS)
+ if (cd->total_sz != offset) {
+ dev_err(p->dev, "%s: tot_size(%lu) and offset(%u) dismatch\n",
+ __func__, cd->total_sz, offset);
return -EINVAL;
+ }
- tmp_val = (unsigned int *)tas_priv->cali_data.data;
-
- crc = crc32(~0, tas_priv->cali_data.data, 84) ^ ~0;
- dev_dbg(tas_priv->dev, "cali crc 0x%08x PK tmp_val 0x%08x\n",
- crc, tmp_val[21]);
-
- if (crc == tmp_val[21]) {
- time64_t seconds = tmp_val[20];
+ r->r0_reg = TAS2563_CAL_R0;
+ r->invr0_reg = TAS2563_CAL_INVR0;
+ r->r0_low_reg = TAS2563_CAL_R0_LOW;
+ r->pow_reg = TAS2563_CAL_POWER;
+ r->tlimit_reg = TAS2563_CAL_TLIM;
- dev_dbg(tas_priv->dev, "%ptTsr\n", &seconds);
- tasdevice_apply_calibration(tas_priv);
- } else
- tas_priv->cali_data.total_sz = 0;
+ /*
+ * TAS2781_FMWLIB supports two solutions of calibrated data. One is
+ * from the driver itself: driver reads the calibrated files directly
+ * during probe; The other from user space: during init of audio hal,
+ * the audio hal will pass the calibrated data via kcontrol interface.
+ * Driver will store this data in "struct calidata" for use. For hda
+ * device, calibrated data are usunally saved into UEFI. So Hda side
+ * codec driver use the mixture of these two solutions, driver reads
+ * the data from UEFI, then store this data in "struct calidata" for
+ * use.
+ */
+ p->is_user_space_calidata = true;
return 0;
}
static void tas2781_hda_remove_controls(struct tas2781_hda *tas_hda)
{
+ struct tas2781_hda_i2c_priv *hda_priv = tas_hda->hda_priv;
struct hda_codec *codec = tas_hda->priv->codec;
snd_ctl_remove(codec->card, tas_hda->dsp_prog_ctl);
snd_ctl_remove(codec->card, tas_hda->dsp_conf_ctl);
- for (int i = ARRAY_SIZE(tas_hda->snd_ctls) - 1; i >= 0; i--)
- snd_ctl_remove(codec->card, tas_hda->snd_ctls[i]);
+ for (int i = ARRAY_SIZE(hda_priv->snd_ctls) - 1; i >= 0; i--)
+ snd_ctl_remove(codec->card, hda_priv->snd_ctls[i]);
snd_ctl_remove(codec->card, tas_hda->prof_ctl);
}
@@ -665,6 +383,7 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
{
struct tasdevice_priv *tas_priv = context;
struct tas2781_hda *tas_hda = dev_get_drvdata(tas_priv->dev);
+ struct tas2781_hda_i2c_priv *hda_priv = tas_hda->hda_priv;
struct hda_codec *codec = tas_priv->codec;
int i, ret, spk_id;
@@ -685,9 +404,9 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
}
for (i = 0; i < ARRAY_SIZE(tas2781_snd_controls); i++) {
- tas_hda->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_controls[i],
+ hda_priv->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_controls[i],
tas_priv);
- ret = snd_ctl_add(codec->card, tas_hda->snd_ctls[i]);
+ ret = snd_ctl_add(codec->card, hda_priv->snd_ctls[i]);
if (ret) {
dev_err(tas_priv->dev,
"Failed to add KControl %s = %d\n",
@@ -756,7 +475,7 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
/* If calibrated data occurs error, dsp will still works with default
* calibrated data inside algo.
*/
- tasdevice_save_calibration(tas_priv);
+ hda_priv->save_calibration(tas_hda);
tasdevice_tuning_switch(tas_hda->priv, 0);
tas_hda->priv->playback_started = true;
@@ -789,11 +508,11 @@ static int tas2781_hda_bind(struct device *dev, struct device *master,
subid = codec->core.subsystem_id >> 16;
switch (subid) {
- case 0x17aa:
- tas_hda->priv->catlog_id = LENOVO;
+ case 0x1028:
+ tas_hda->catlog_id = DELL;
break;
default:
- tas_hda->priv->catlog_id = OTHERS;
+ tas_hda->catlog_id = LENOVO;
break;
}
@@ -840,31 +559,23 @@ static const struct component_ops tas2781_hda_comp_ops = {
.unbind = tas2781_hda_unbind,
};
-static void tas2781_hda_remove(struct device *dev)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
-
- component_del(tas_hda->dev, &tas2781_hda_comp_ops);
-
- pm_runtime_get_sync(tas_hda->dev);
- pm_runtime_disable(tas_hda->dev);
-
- pm_runtime_put_noidle(tas_hda->dev);
-
- tasdevice_remove(tas_hda->priv);
-}
-
static int tas2781_hda_i2c_probe(struct i2c_client *clt)
{
+ struct tas2781_hda_i2c_priv *hda_priv;
struct tas2781_hda *tas_hda;
const char *device_name;
int ret;
-
tas_hda = devm_kzalloc(&clt->dev, sizeof(*tas_hda), GFP_KERNEL);
if (!tas_hda)
return -ENOMEM;
+ hda_priv = devm_kzalloc(&clt->dev, sizeof(*hda_priv), GFP_KERNEL);
+ if (!hda_priv)
+ return -ENOMEM;
+
+ tas_hda->hda_priv = hda_priv;
+
dev_set_drvdata(&clt->dev, tas_hda);
tas_hda->dev = &clt->dev;
@@ -874,13 +585,11 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt)
if (strstr(dev_name(&clt->dev), "TIAS2781")) {
device_name = "TIAS2781";
- tas_hda->priv->save_calibration = tas2781_save_calibration;
- tas_hda->priv->apply_calibration = tas2781_apply_calib;
+ hda_priv->save_calibration = tas2781_save_calibration;
tas_hda->priv->global_addr = TAS2781_GLOBAL_ADDR;
} else if (strstr(dev_name(&clt->dev), "INT8866")) {
device_name = "INT8866";
- tas_hda->priv->save_calibration = tas2563_save_calibration;
- tas_hda->priv->apply_calibration = tas2563_apply_calib;
+ hda_priv->save_calibration = tas2563_save_calibration;
tas_hda->priv->global_addr = TAS2563_GLOBAL_ADDR;
} else
return -ENODEV;
@@ -911,13 +620,13 @@ static int tas2781_hda_i2c_probe(struct i2c_client *clt)
err:
if (ret)
- tas2781_hda_remove(&clt->dev);
+ tas2781_hda_remove(&clt->dev, &tas2781_hda_comp_ops);
return ret;
}
static void tas2781_hda_i2c_remove(struct i2c_client *clt)
{
- tas2781_hda_remove(&clt->dev);
+ tas2781_hda_remove(&clt->dev, &tas2781_hda_comp_ops);
}
static int tas2781_runtime_suspend(struct device *dev)
@@ -951,11 +660,6 @@ static int tas2781_runtime_resume(struct device *dev)
tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog);
- /* If calibrated data occurs error, dsp will still works with default
- * calibrated data inside algo.
- */
- tasdevice_apply_calibration(tas_hda->priv);
-
mutex_unlock(&tas_hda->priv->codec_lock);
return 0;
@@ -999,11 +703,6 @@ static int tas2781_system_resume(struct device *dev)
tasdevice_reset(tas_hda->priv);
tasdevice_prmg_load(tas_hda->priv, tas_hda->priv->cur_prog);
- /* If calibrated data occurs error, dsp will still work with default
- * calibrated data inside algo.
- */
- tasdevice_apply_calibration(tas_hda->priv);
-
if (tas_hda->priv->playback_started)
tasdevice_tuning_switch(tas_hda->priv, 0);
@@ -1045,3 +744,4 @@ MODULE_DESCRIPTION("TAS2781 HDA Driver");
MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS("SND_SOC_TAS2781_FMWLIB");
+MODULE_IMPORT_NS("SND_HDA_SCODEC_TAS2781");
diff --git a/sound/pci/hda/tas2781_hda_spi.c b/sound/pci/hda/tas2781_hda_spi.c
index 25175ff4b3aa..5c03e9d2283a 100644
--- a/sound/pci/hda/tas2781_hda_spi.c
+++ b/sound/pci/hda/tas2781_hda_spi.c
@@ -2,7 +2,7 @@
//
// TAS2781 HDA SPI driver
//
-// Copyright 2024 Texas Instruments, Inc.
+// Copyright 2024 - 2025 Texas Instruments, Inc.
//
// Author: Baojun Xu <baojun.xu@ti.com>
@@ -27,68 +27,41 @@
#include <sound/hda_codec.h>
#include <sound/soc.h>
-#include <sound/tas2781-dsp.h>
+#include <sound/tas2781.h>
#include <sound/tlv.h>
#include <sound/tas2781-tlv.h>
-#include "tas2781-spi.h"
-
#include "hda_local.h"
#include "hda_auto_parser.h"
#include "hda_component.h"
#include "hda_jack.h"
#include "hda_generic.h"
+#include "tas2781_hda.h"
-/*
- * No standard control callbacks for SNDRV_CTL_ELEM_IFACE_CARD
- * Define two controls, one is Volume control callbacks, the other is
- * flag setting control callbacks.
- */
-
-/* Volume control callbacks for tas2781 */
-#define ACARD_SINGLE_RANGE_EXT_TLV(xname, xreg, xshift, xmin, xmax, xinvert, \
- xhandler_get, xhandler_put, tlv_array) { \
- .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = (xname), \
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
- SNDRV_CTL_ELEM_ACCESS_READWRITE, \
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw, \
- .get = xhandler_get, .put = xhandler_put, \
- .private_value = (unsigned long)&(struct soc_mixer_control) { \
- .reg = xreg, .rreg = xreg, \
- .shift = xshift, .rshift = xshift,\
- .min = xmin, .max = xmax, .invert = xinvert, \
- } \
-}
+#define TASDEVICE_RANGE_MAX_SIZE (256 * 128)
+#define TASDEVICE_WIN_LEN 128
+#define TAS2781_SPI_MAX_FREQ (4 * HZ_PER_MHZ)
+/* Flag of calibration registers address. */
+#define TASDEVICE_CALIBRATION_REG_ADDRESS BIT(7)
+#define TASDEV_UEFI_CALI_REG_ADDR_FLG BIT(7)
-/* Flag control callbacks for tas2781 */
-#define ACARD_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) { \
- .iface = SNDRV_CTL_ELEM_IFACE_CARD, \
- .name = xname, \
- .info = snd_ctl_boolean_mono_info, \
- .get = xhandler_get, \
- .put = xhandler_put, \
- .private_value = xdata, \
-}
+/* System Reset Check Register */
+#define TAS2781_REG_CLK_CONFIG TASDEVICE_REG(0x0, 0x0, 0x5c)
+#define TAS2781_REG_CLK_CONFIG_RESET 0x19
-struct tas2781_hda {
- struct tasdevice_priv *priv;
- struct acpi_device *dacpi;
- struct snd_kcontrol *dsp_prog_ctl;
- struct snd_kcontrol *dsp_conf_ctl;
+struct tas2781_hda_spi_priv {
struct snd_kcontrol *snd_ctls[3];
- struct snd_kcontrol *prof_ctl;
};
static const struct regmap_range_cfg tasdevice_ranges[] = {
{
.range_min = 0,
- .range_max = TASDEVICE_MAX_SIZE,
+ .range_max = TASDEVICE_RANGE_MAX_SIZE,
.selector_reg = TASDEVICE_PAGE_SELECT,
.selector_mask = GENMASK(7, 0),
.selector_shift = 0,
.window_start = 0,
- .window_len = TASDEVICE_MAX_PAGE,
+ .window_len = TASDEVICE_WIN_LEN,
},
};
@@ -96,39 +69,19 @@ static const struct regmap_config tasdevice_regmap = {
.reg_bits = 8,
.val_bits = 8,
.zero_flag_mask = true,
+ .read_flag_mask = 0x01,
+ .reg_shift = -1,
.cache_type = REGCACHE_NONE,
.ranges = tasdevice_ranges,
.num_ranges = ARRAY_SIZE(tasdevice_ranges),
- .max_register = TASDEVICE_MAX_SIZE,
+ .max_register = TASDEVICE_RANGE_MAX_SIZE,
};
-static int tasdevice_spi_switch_book(struct tasdevice_priv *tas_priv, int reg)
-{
- struct regmap *map = tas_priv->regmap;
-
- if (tas_priv->cur_book != TASDEVICE_BOOK_ID(reg)) {
- int ret = regmap_write(map, TASDEVICE_BOOKCTL_REG,
- TASDEVICE_BOOK_ID(reg));
- if (ret < 0) {
- dev_err(tas_priv->dev, "Switch Book E=%d\n", ret);
- return ret;
- }
- tas_priv->cur_book = TASDEVICE_BOOK_ID(reg);
- }
- return 0;
-}
-
-int tasdevice_spi_dev_read(struct tasdevice_priv *tas_priv,
- unsigned int reg,
- unsigned int *val)
+static int tasdevice_spi_dev_read(struct tasdevice_priv *tas_priv,
+ unsigned short chn, unsigned int reg, unsigned int *val)
{
- struct regmap *map = tas_priv->regmap;
int ret;
- ret = tasdevice_spi_switch_book(tas_priv, reg);
- if (ret < 0)
- return ret;
-
/*
* In our TAS2781 SPI mode, if read from other book (not book 0),
* or read from page number larger than 1 in book 0, one more byte
@@ -137,11 +90,11 @@ int tasdevice_spi_dev_read(struct tasdevice_priv *tas_priv,
if ((TASDEVICE_BOOK_ID(reg) > 0) || (TASDEVICE_PAGE_ID(reg) > 1)) {
unsigned char data[2];
- ret = regmap_bulk_read(map, TASDEVICE_PAGE_REG(reg) | 1,
+ ret = tasdevice_dev_bulk_read(tas_priv, chn, reg,
data, sizeof(data));
*val = data[1];
} else {
- ret = regmap_read(map, TASDEVICE_PAGE_REG(reg) | 1, val);
+ ret = tasdevice_dev_read(tas_priv, chn, reg, val);
}
if (ret < 0)
dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
@@ -149,71 +102,25 @@ int tasdevice_spi_dev_read(struct tasdevice_priv *tas_priv,
return ret;
}
-int tasdevice_spi_dev_write(struct tasdevice_priv *tas_priv,
- unsigned int reg,
- unsigned int value)
-{
- struct regmap *map = tas_priv->regmap;
- int ret;
-
- ret = tasdevice_spi_switch_book(tas_priv, reg);
- if (ret < 0)
- return ret;
-
- ret = regmap_write(map, TASDEVICE_PAGE_REG(reg), value);
- if (ret < 0)
- dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
-
- return ret;
-}
-
-int tasdevice_spi_dev_bulk_write(struct tasdevice_priv *tas_priv,
- unsigned int reg,
- unsigned char *data,
- unsigned int len)
-{
- struct regmap *map = tas_priv->regmap;
- int ret;
-
- ret = tasdevice_spi_switch_book(tas_priv, reg);
- if (ret < 0)
- return ret;
-
- ret = regmap_bulk_write(map, TASDEVICE_PAGE_REG(reg), data, len);
- if (ret < 0)
- dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
-
- return ret;
-}
-
-int tasdevice_spi_dev_bulk_read(struct tasdevice_priv *tas_priv,
- unsigned int reg,
- unsigned char *data,
- unsigned int len)
+static int tasdevice_spi_dev_bulk_read(struct tasdevice_priv *tas_priv,
+ unsigned short chn, unsigned int reg, unsigned char *data,
+ unsigned int len)
{
- struct regmap *map = tas_priv->regmap;
int ret;
- ret = tasdevice_spi_switch_book(tas_priv, reg);
- if (ret < 0)
- return ret;
-
- if (len > TASDEVICE_MAX_PAGE)
- len = TASDEVICE_MAX_PAGE;
/*
* In our TAS2781 SPI mode, if read from other book (not book 0),
* or read from page number larger than 1 in book 0, one more byte
* read is needed, and first byte is a dummy byte, need to be ignored.
*/
if ((TASDEVICE_BOOK_ID(reg) > 0) || (TASDEVICE_PAGE_ID(reg) > 1)) {
- unsigned char buf[TASDEVICE_MAX_PAGE+1];
+ unsigned char buf[TASDEVICE_WIN_LEN + 1];
- ret = regmap_bulk_read(map, TASDEVICE_PAGE_REG(reg) | 1, buf,
- len + 1);
+ ret = tasdevice_dev_bulk_read(tas_priv, chn, reg,
+ buf, len + 1);
memcpy(data, buf + 1, len);
} else {
- ret = regmap_bulk_read(map, TASDEVICE_PAGE_REG(reg) | 1, data,
- len);
+ ret = tasdevice_dev_bulk_read(tas_priv, chn, reg, data, len);
}
if (ret < 0)
dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
@@ -221,31 +128,55 @@ int tasdevice_spi_dev_bulk_read(struct tasdevice_priv *tas_priv,
return ret;
}
-int tasdevice_spi_dev_update_bits(struct tasdevice_priv *tas_priv,
- unsigned int reg,
- unsigned int mask,
- unsigned int value)
+static int tasdevice_spi_dev_update_bits(struct tasdevice_priv *tas_priv,
+ unsigned short chn, unsigned int reg, unsigned int mask,
+ unsigned int value)
{
- struct regmap *map = tas_priv->regmap;
int ret, val;
/*
* In our TAS2781 SPI mode, read/write was masked in last bit of
* address, it cause regmap_update_bits() not work as expected.
*/
- ret = tasdevice_spi_dev_read(tas_priv, reg, &val);
+ ret = tasdevice_dev_read(tas_priv, chn, reg, &val);
if (ret < 0) {
dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
return ret;
}
- ret = regmap_write(map, TASDEVICE_PAGE_REG(reg),
- (val & ~mask) | (mask & value));
+
+ ret = tasdevice_dev_write(tas_priv, chn, TASDEVICE_PAGE_REG(reg),
+ (val & ~mask) | (mask & value));
if (ret < 0)
dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
return ret;
}
+static int tasdevice_spi_change_chn_book(struct tasdevice_priv *p,
+ unsigned short chn, int book)
+{
+ int ret = 0;
+
+ if (chn == p->index) {
+ struct tasdevice *tasdev = &p->tasdevice[chn];
+ struct regmap *map = p->regmap;
+
+ if (tasdev->cur_book != book) {
+ ret = regmap_write(map, TASDEVICE_BOOKCTL_REG, book);
+ if (ret < 0)
+ dev_err(p->dev, "%s, E=%d\n", __func__, ret);
+ else
+ tasdev->cur_book = book;
+ }
+ } else {
+ ret = -EXDEV;
+ dev_dbg(p->dev, "Not error, %s ignore channel(%d)\n",
+ __func__, chn);
+ }
+
+ return ret;
+}
+
static void tas2781_spi_reset(struct tasdevice_priv *tas_dev)
{
int ret;
@@ -254,12 +185,15 @@ static void tas2781_spi_reset(struct tasdevice_priv *tas_dev)
gpiod_set_value_cansleep(tas_dev->reset, 0);
fsleep(800);
gpiod_set_value_cansleep(tas_dev->reset, 1);
+ } else {
+ ret = tasdevice_dev_write(tas_dev, tas_dev->index,
+ TASDEVICE_REG_SWRESET, TASDEVICE_REG_SWRESET_RESET);
+ if (ret < 0) {
+ dev_err(tas_dev->dev, "dev sw-reset fail, %d\n", ret);
+ return;
+ }
+ fsleep(1000);
}
- ret = tasdevice_spi_dev_write(tas_dev, TAS2781_REG_SWRESET,
- TAS2781_REG_SWRESET_RESET);
- if (ret < 0)
- dev_err(tas_dev->dev, "dev sw-reset fail, %d\n", ret);
- fsleep(1000);
}
static int tascodec_spi_init(struct tasdevice_priv *tas_priv,
@@ -276,7 +210,7 @@ static int tascodec_spi_init(struct tasdevice_priv *tas_priv,
scnprintf(tas_priv->rca_binaryname,
sizeof(tas_priv->rca_binaryname), "%sRCA%d.bin",
- tas_priv->dev_name, tas_priv->index);
+ tas_priv->dev_name, tas_priv->ndev);
crc8_populate_msb(tas_priv->crc8_lkp_tbl, TASDEVICE_CRC8_POLYNOMIAL);
tas_priv->codec = codec;
ret = request_firmware_nowait(module, FW_ACTION_UEVENT,
@@ -291,26 +225,22 @@ static int tascodec_spi_init(struct tasdevice_priv *tas_priv,
static void tasdevice_spi_init(struct tasdevice_priv *tas_priv)
{
- tas_priv->cur_prog = -1;
- tas_priv->cur_conf = -1;
+ tas_priv->tasdevice[tas_priv->index].cur_book = -1;
+ tas_priv->tasdevice[tas_priv->index].cur_conf = -1;
+ tas_priv->tasdevice[tas_priv->index].cur_prog = -1;
- tas_priv->cur_book = -1;
- tas_priv->cur_prog = -1;
- tas_priv->cur_conf = -1;
+ tas_priv->isspi = true;
- /* Store default registers address for calibration data. */
- tas_priv->cali_reg_array[0] = TASDEVICE_REG(0, 0x17, 0x74);
- tas_priv->cali_reg_array[1] = TASDEVICE_REG(0, 0x18, 0x0c);
- tas_priv->cali_reg_array[2] = TASDEVICE_REG(0, 0x18, 0x14);
- tas_priv->cali_reg_array[3] = TASDEVICE_REG(0, 0x13, 0x70);
- tas_priv->cali_reg_array[4] = TASDEVICE_REG(0, 0x18, 0x7c);
+ tas_priv->update_bits = tasdevice_spi_dev_update_bits;
+ tas_priv->change_chn_book = tasdevice_spi_change_chn_book;
+ tas_priv->dev_read = tasdevice_spi_dev_read;
+ tas_priv->dev_bulk_read = tasdevice_spi_dev_bulk_read;
mutex_init(&tas_priv->codec_lock);
}
static int tasdevice_spi_amp_putvol(struct tasdevice_priv *tas_priv,
- struct snd_ctl_elem_value *ucontrol,
- struct soc_mixer_control *mc)
+ struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
{
unsigned int invert = mc->invert;
unsigned char mask;
@@ -321,7 +251,8 @@ static int tasdevice_spi_amp_putvol(struct tasdevice_priv *tas_priv,
mask <<= mc->shift;
val = clamp(invert ? max - ucontrol->value.integer.value[0] :
ucontrol->value.integer.value[0], 0, max);
- ret = tasdevice_spi_dev_update_bits(tas_priv,
+
+ ret = tasdevice_spi_dev_update_bits(tas_priv, tas_priv->index,
mc->reg, mask, (unsigned int)(val << mc->shift));
if (ret)
dev_err(tas_priv->dev, "set AMP vol error in dev %d\n",
@@ -331,16 +262,14 @@ static int tasdevice_spi_amp_putvol(struct tasdevice_priv *tas_priv,
}
static int tasdevice_spi_amp_getvol(struct tasdevice_priv *tas_priv,
- struct snd_ctl_elem_value *ucontrol,
- struct soc_mixer_control *mc)
+ struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
{
unsigned int invert = mc->invert;
unsigned char mask = 0;
int max = mc->max;
int ret, val;
- /* Read the primary device */
- ret = tasdevice_spi_dev_read(tas_priv, mc->reg, &val);
+ ret = tasdevice_spi_dev_read(tas_priv, tas_priv->index, mc->reg, &val);
if (ret) {
dev_err(tas_priv->dev, "%s, get AMP vol error\n", __func__);
return ret;
@@ -355,9 +284,8 @@ static int tasdevice_spi_amp_getvol(struct tasdevice_priv *tas_priv,
return ret;
}
-static int tasdevice_spi_digital_putvol(struct tasdevice_priv *tas_priv,
- struct snd_ctl_elem_value *ucontrol,
- struct soc_mixer_control *mc)
+static int tasdevice_spi_digital_putvol(struct tasdevice_priv *p,
+ struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
{
unsigned int invert = mc->invert;
int max = mc->max;
@@ -365,26 +293,23 @@ static int tasdevice_spi_digital_putvol(struct tasdevice_priv *tas_priv,
val = clamp(invert ? max - ucontrol->value.integer.value[0] :
ucontrol->value.integer.value[0], 0, max);
- ret = tasdevice_spi_dev_write(tas_priv, mc->reg, (unsigned int)val);
+ ret = tasdevice_dev_write(p, p->index, mc->reg, (unsigned int)val);
if (ret)
- dev_err(tas_priv->dev, "set digital vol err in dev %d\n",
- tas_priv->index);
+ dev_err(p->dev, "set digital vol err in dev %d\n", p->index);
return ret;
}
-static int tasdevice_spi_digital_getvol(struct tasdevice_priv *tas_priv,
- struct snd_ctl_elem_value *ucontrol,
- struct soc_mixer_control *mc)
+static int tasdevice_spi_digital_getvol(struct tasdevice_priv *p,
+ struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
{
unsigned int invert = mc->invert;
int max = mc->max;
int ret, val;
- /* Read the primary device as the whole */
- ret = tasdevice_spi_dev_read(tas_priv, mc->reg, &val);
+ ret = tasdevice_spi_dev_read(p, p->index, mc->reg, &val);
if (ret) {
- dev_err(tas_priv->dev, "%s, get digital vol err\n", __func__);
+ dev_err(p->dev, "%s, get digital vol err\n", __func__);
return ret;
}
@@ -395,8 +320,7 @@ static int tasdevice_spi_digital_getvol(struct tasdevice_priv *tas_priv,
}
static int tas2781_read_acpi(struct tas2781_hda *tas_hda,
- const char *hid,
- int id)
+ const char *hid, int id)
{
struct tasdevice_priv *p = tas_hda->priv;
struct acpi_device *adev;
@@ -413,7 +337,6 @@ static int tas2781_read_acpi(struct tas2781_hda *tas_hda,
}
strscpy(p->dev_name, hid, sizeof(p->dev_name));
- tas_hda->dacpi = adev;
physdev = get_device(acpi_get_first_physical_node(adev));
acpi_dev_put(adev);
@@ -423,7 +346,7 @@ static int tas2781_read_acpi(struct tas2781_hda *tas_hda,
ret = -EINVAL;
goto err;
}
- nval = ret;
+ p->ndev = nval = ret;
ret = device_property_read_u32_array(physdev, property, values, nval);
if (ret)
@@ -466,139 +389,22 @@ err:
static void tas2781_hda_playback_hook(struct device *dev, int action)
{
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
+ struct tasdevice_priv *tas_priv = tas_hda->priv;
if (action == HDA_GEN_PCM_ACT_OPEN) {
pm_runtime_get_sync(dev);
- guard(mutex)(&tas_hda->priv->codec_lock);
- tasdevice_spi_tuning_switch(tas_hda->priv, 0);
+ guard(mutex)(&tas_priv->codec_lock);
+ if (tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK)
+ tasdevice_tuning_switch(tas_hda->priv, 0);
} else if (action == HDA_GEN_PCM_ACT_CLOSE) {
- guard(mutex)(&tas_hda->priv->codec_lock);
- tasdevice_spi_tuning_switch(tas_hda->priv, 1);
+ guard(mutex)(&tas_priv->codec_lock);
+ if (tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK)
+ tasdevice_tuning_switch(tas_priv, 1);
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
}
}
-static int tasdevice_info_profile(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = tas_priv->rcabin.ncfgs - 1;
-
- return 0;
-}
-
-static int tasdevice_get_profile_id(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.integer.value[0] = tas_priv->rcabin.profile_cfg_id;
-
- return 0;
-}
-
-static int tasdevice_set_profile_id(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- int max = tas_priv->rcabin.ncfgs - 1;
- int val;
-
- val = clamp(ucontrol->value.integer.value[0], 0, max);
- if (tas_priv->rcabin.profile_cfg_id != val) {
- tas_priv->rcabin.profile_cfg_id = val;
- return 1;
- }
-
- return 0;
-}
-
-static int tasdevice_info_programs(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = tas_priv->fmw->nr_programs - 1;
-
- return 0;
-}
-
-static int tasdevice_info_config(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = tas_priv->fmw->nr_configurations - 1;
-
- return 0;
-}
-
-static int tasdevice_program_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.integer.value[0] = tas_priv->cur_prog;
-
- return 0;
-}
-
-static int tasdevice_program_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- int nr_program = ucontrol->value.integer.value[0];
- int max = tas_priv->fmw->nr_programs - 1;
- int val;
-
- val = clamp(nr_program, 0, max);
-
- if (tas_priv->cur_prog != val) {
- tas_priv->cur_prog = val;
- return 1;
- }
-
- return 0;
-}
-
-static int tasdevice_config_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
-
- ucontrol->value.integer.value[0] = tas_priv->cur_conf;
-
- return 0;
-}
-
-static int tasdevice_config_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol);
- int max = tas_priv->fmw->nr_configurations - 1;
- int val;
-
- val = clamp(ucontrol->value.integer.value[0], 0, max);
-
- if (tas_priv->cur_conf != val) {
- tas_priv->cur_conf = val;
- return 1;
- }
-
- return 0;
-}
-
/*
* tas2781_digital_getvol - get the volum control
* @kcontrol: control pointer
@@ -620,6 +426,7 @@ static int tas2781_digital_getvol(struct snd_kcontrol *kcontrol,
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
+ guard(mutex)(&tas_priv->codec_lock);
return tasdevice_spi_digital_getvol(tas_priv, ucontrol, mc);
}
@@ -630,6 +437,7 @@ static int tas2781_amp_getvol(struct snd_kcontrol *kcontrol,
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
+ guard(mutex)(&tas_priv->codec_lock);
return tasdevice_spi_amp_getvol(tas_priv, ucontrol, mc);
}
@@ -640,7 +448,7 @@ static int tas2781_digital_putvol(struct snd_kcontrol *kcontrol,
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- /* The check of the given value is in tasdevice_digital_putvol. */
+ guard(mutex)(&tas_priv->codec_lock);
return tasdevice_spi_digital_putvol(tas_priv, ucontrol, mc);
}
@@ -651,7 +459,7 @@ static int tas2781_amp_putvol(struct snd_kcontrol *kcontrol,
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- /* The check of the given value is in tasdevice_amp_putvol. */
+ guard(mutex)(&tas_priv->codec_lock);
return tasdevice_spi_amp_putvol(tas_priv, ucontrol, mc);
}
@@ -685,223 +493,139 @@ static int tas2781_force_fwload_put(struct snd_kcontrol *kcontrol,
return change;
}
-static const struct snd_kcontrol_new tas2781_snd_controls[] = {
- ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Gain 0", TAS2781_AMP_LEVEL,
- 1, 0, 20, 0, tas2781_amp_getvol,
- tas2781_amp_putvol, amp_vol_tlv),
- ACARD_SINGLE_RANGE_EXT_TLV("Speaker Digital Gain 0", TAS2781_DVC_LVL,
- 0, 0, 200, 1, tas2781_digital_getvol,
- tas2781_digital_putvol, dvc_tlv),
- ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load 0", 0,
- tas2781_force_fwload_get, tas2781_force_fwload_put),
- ACARD_SINGLE_RANGE_EXT_TLV("Speaker Analog Gain 1", TAS2781_AMP_LEVEL,
- 1, 0, 20, 0, tas2781_amp_getvol,
- tas2781_amp_putvol, amp_vol_tlv),
- ACARD_SINGLE_RANGE_EXT_TLV("Speaker Digital Gain 1", TAS2781_DVC_LVL,
- 0, 0, 200, 1, tas2781_digital_getvol,
- tas2781_digital_putvol, dvc_tlv),
- ACARD_SINGLE_BOOL_EXT("Speaker Force Firmware Load 1", 0,
- tas2781_force_fwload_get, tas2781_force_fwload_put),
+static struct snd_kcontrol_new tas2781_snd_ctls[] = {
+ ACARD_SINGLE_RANGE_EXT_TLV(NULL, TAS2781_AMP_LEVEL, 1, 0, 20, 0,
+ tas2781_amp_getvol, tas2781_amp_putvol, amp_vol_tlv),
+ ACARD_SINGLE_RANGE_EXT_TLV(NULL, TAS2781_DVC_LVL, 0, 0, 200, 1,
+ tas2781_digital_getvol, tas2781_digital_putvol, dvc_tlv),
+ ACARD_SINGLE_BOOL_EXT(NULL, 0, tas2781_force_fwload_get,
+ tas2781_force_fwload_put),
};
-static const struct snd_kcontrol_new tas2781_prof_ctrl[] = {
-{
- .name = "Speaker Profile Id - 0",
+static struct snd_kcontrol_new tas2781_prof_ctl = {
.iface = SNDRV_CTL_ELEM_IFACE_CARD,
.info = tasdevice_info_profile,
.get = tasdevice_get_profile_id,
.put = tasdevice_set_profile_id,
-},
-{
- .name = "Speaker Profile Id - 1",
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .info = tasdevice_info_profile,
- .get = tasdevice_get_profile_id,
- .put = tasdevice_set_profile_id,
-},
-};
-static const struct snd_kcontrol_new tas2781_dsp_prog_ctrl[] = {
-{
- .name = "Speaker Program Id 0",
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .info = tasdevice_info_programs,
- .get = tasdevice_program_get,
- .put = tasdevice_program_put,
-},
-{
- .name = "Speaker Program Id 1",
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .info = tasdevice_info_programs,
- .get = tasdevice_program_get,
- .put = tasdevice_program_put,
-},
};
-static const struct snd_kcontrol_new tas2781_dsp_conf_ctrl[] = {
-{
- .name = "Speaker Config Id 0",
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .info = tasdevice_info_config,
- .get = tasdevice_config_get,
- .put = tasdevice_config_put,
-},
-{
- .name = "Speaker Config Id 1",
- .iface = SNDRV_CTL_ELEM_IFACE_CARD,
- .info = tasdevice_info_config,
- .get = tasdevice_config_get,
- .put = tasdevice_config_put,
-},
+static struct snd_kcontrol_new tas2781_dsp_ctls[] = {
+ /* Speaker Program */
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ .info = tasdevice_info_programs,
+ .get = tasdevice_program_get,
+ .put = tasdevice_program_put,
+ },
+ /* Speaker Config */
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ .info = tasdevice_info_config,
+ .get = tasdevice_config_get,
+ .put = tasdevice_config_put,
+ },
};
-static void tas2781_apply_calib(struct tasdevice_priv *tas_priv)
+static void tas2781_hda_remove_controls(struct tas2781_hda *tas_hda)
{
- int i, rc;
+ struct hda_codec *codec = tas_hda->priv->codec;
+ struct tas2781_hda_spi_priv *h_priv = tas_hda->hda_priv;
- /*
- * If no calibration data exist in tasdevice_priv *tas_priv,
- * calibration apply will be ignored, and use default values
- * in firmware binary, which was loaded during firmware download.
- */
- if (tas_priv->cali_data[0] == 0)
- return;
- /*
- * Calibration data was saved in tasdevice_priv *tas_priv as:
- * unsigned int cali_data[CALIB_MAX];
- * and every data (in 4 bytes) will be saved in register which in
- * book 0, and page number in page_array[], offset was saved in
- * rgno_array[].
- */
- for (i = 0; i < CALIB_MAX; i++) {
- rc = tasdevice_spi_dev_bulk_write(tas_priv,
- tas_priv->cali_reg_array[i],
- (unsigned char *)&tas_priv->cali_data[i], 4);
- if (rc < 0)
- dev_err(tas_priv->dev,
- "chn %d calib %d bulk_wr err = %d\n",
- tas_priv->index, i, rc);
- }
+ snd_ctl_remove(codec->card, tas_hda->dsp_prog_ctl);
+
+ snd_ctl_remove(codec->card, tas_hda->dsp_conf_ctl);
+
+ for (int i = ARRAY_SIZE(h_priv->snd_ctls) - 1; i >= 0; i--)
+ snd_ctl_remove(codec->card, h_priv->snd_ctls[i]);
+
+ snd_ctl_remove(codec->card, tas_hda->prof_ctl);
}
-/*
- * Update the calibration data, including speaker impedance, f0, etc,
- * into algo. Calibrate data is done by manufacturer in the factory.
- * These data are used by Algo for calculating the speaker temperature,
- * speaker membrane excursion and f0 in real time during playback.
- * Calibration data format in EFI is V2, since 2024.
- */
-static int tas2781_save_calibration(struct tasdevice_priv *tas_priv)
-{
- /*
- * GUID was used for data access in BIOS, it was provided by board
- * manufactory, like HP: "{02f9af02-7734-4233-b43d-93fe5aa35db3}"
- */
- efi_guid_t efi_guid =
- EFI_GUID(0x02f9af02, 0x7734, 0x4233,
- 0xb4, 0x3d, 0x93, 0xfe, 0x5a, 0xa3, 0x5d, 0xb3);
- static efi_char16_t efi_name[] = TASDEVICE_CALIBRATION_DATA_NAME;
- unsigned char data[TASDEVICE_CALIBRATION_DATA_SIZE], *buf;
- unsigned int attr, crc, offset, *tmp_val;
- unsigned long total_sz = 0;
- efi_status_t status;
-
- tas_priv->cali_data[0] = 0;
- status = efi.get_variable(efi_name, &efi_guid, &attr, &total_sz, data);
- if (status == EFI_BUFFER_TOO_SMALL) {
- if (total_sz > TASDEVICE_CALIBRATION_DATA_SIZE)
- return -ENOMEM;
- /* Get variable contents into buffer */
- status = efi.get_variable(efi_name, &efi_guid, &attr,
- &total_sz, data);
+static int tas2781_hda_spi_prf_ctl(struct tas2781_hda *h)
+{
+ struct tasdevice_priv *p = h->priv;
+ struct hda_codec *c = p->codec;
+ char name[64];
+ int rc;
+
+ snprintf(name, sizeof(name), "Speaker-%d Profile Id", p->index);
+ tas2781_prof_ctl.name = name;
+ h->prof_ctl = snd_ctl_new1(&tas2781_prof_ctl, p);
+ rc = snd_ctl_add(c->card, h->prof_ctl);
+ if (rc)
+ dev_err(p->dev, "Failed to add KControl: %s, rc = %d\n",
+ tas2781_prof_ctl.name, rc);
+ return rc;
+}
+
+static int tas2781_hda_spi_snd_ctls(struct tas2781_hda *h)
+{
+ struct tas2781_hda_spi_priv *h_priv = h->hda_priv;
+ struct tasdevice_priv *p = h->priv;
+ struct hda_codec *c = p->codec;
+ char name[64];
+ int i = 0;
+ int rc;
+
+ snprintf(name, sizeof(name), "Speaker-%d Analog Volume", p->index);
+ tas2781_snd_ctls[i].name = name;
+ h_priv->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_ctls[i], p);
+ rc = snd_ctl_add(c->card, h_priv->snd_ctls[i]);
+ if (rc) {
+ dev_err(p->dev, "Failed to add KControl: %s, rc = %d\n",
+ tas2781_snd_ctls[i].name, rc);
+ return rc;
}
- if (status != EFI_SUCCESS)
- return status;
-
- tmp_val = (unsigned int *)data;
- if (tmp_val[0] == 2781) {
- /*
- * New features were added in calibrated Data V3:
- * 1. Added calibration registers address define in
- * a node, marked as Device id == 0x80.
- * New features were added in calibrated Data V2:
- * 1. Added some the fields to store the link_id and
- * uniqie_id for multi-link solutions
- * 2. Support flexible number of devices instead of
- * fixed one in V1.
- * Layout of calibrated data V2 in UEFI(total 256 bytes):
- * ChipID (2781, 4 bytes)
- * Device-Sum (4 bytes)
- * TimeStamp of Calibration (4 bytes)
- * for (i = 0; i < Device-Sum; i++) {
- * Device #i index_info () {
- * SDW link id (2bytes)
- * SDW unique_id (2bytes)
- * } // if Device number is 0x80, mean it's
- * calibration registers address.
- * Calibrated Data of Device #i (20 bytes)
- * }
- * CRC (4 bytes)
- * Reserved (the rest)
- */
- crc = crc32(~0, data, (3 + tmp_val[1] * 6) * 4) ^ ~0;
-
- if (crc != tmp_val[3 + tmp_val[1] * 6])
- return 0;
-
- for (int j = 0; j < tmp_val[1]; j++) {
- offset = j * 6 + 3;
- if (tmp_val[offset] == tas_priv->index) {
- for (int i = 0; i < CALIB_MAX; i++)
- tas_priv->cali_data[i] =
- tmp_val[offset + i + 1];
- } else if (tmp_val[offset] ==
- TASDEVICE_CALIBRATION_REG_ADDRESS) {
- for (int i = 0; i < CALIB_MAX; i++) {
- buf = &data[(offset + i + 1) * 4];
- tas_priv->cali_reg_array[i] =
- TASDEVICE_REG(buf[1], buf[2],
- buf[3]);
- }
- }
- tas_priv->apply_calibration(tas_priv);
- }
- } else {
- /*
- * Calibration data is in V1 format.
- * struct cali_data {
- * char cali_data[20];
- * }
- *
- * struct {
- * struct cali_data cali_data[4];
- * int TimeStamp of Calibration (4 bytes)
- * int CRC (4 bytes)
- * } ueft;
- */
- crc = crc32(~0, data, 84) ^ ~0;
- if (crc == tmp_val[21]) {
- for (int i = 0; i < CALIB_MAX; i++)
- tas_priv->cali_data[i] =
- tmp_val[tas_priv->index * 5 + i];
- tas_priv->apply_calibration(tas_priv);
- }
+ i++;
+ snprintf(name, sizeof(name), "Speaker-%d Digital Volume", p->index);
+ tas2781_snd_ctls[i].name = name;
+ h_priv->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_ctls[i], p);
+ rc = snd_ctl_add(c->card, h_priv->snd_ctls[i]);
+ if (rc) {
+ dev_err(p->dev, "Failed to add KControl: %s, rc = %d\n",
+ tas2781_snd_ctls[i].name, rc);
+ return rc;
}
-
- return 0;
+ i++;
+ snprintf(name, sizeof(name), "Froce Speaker-%d FW Load", p->index);
+ tas2781_snd_ctls[i].name = name;
+ h_priv->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_ctls[i], p);
+ rc = snd_ctl_add(c->card, h_priv->snd_ctls[i]);
+ if (rc) {
+ dev_err(p->dev, "Failed to add KControl: %s, rc = %d\n",
+ tas2781_snd_ctls[i].name, rc);
+ }
+ return rc;
}
-static void tas2781_hda_remove_controls(struct tas2781_hda *tas_hda)
+static int tas2781_hda_spi_dsp_ctls(struct tas2781_hda *h)
{
- struct hda_codec *codec = tas_hda->priv->codec;
+ struct tasdevice_priv *p = h->priv;
+ struct hda_codec *c = p->codec;
+ char name[64];
+ int i = 0;
+ int rc;
- snd_ctl_remove(codec->card, tas_hda->dsp_prog_ctl);
-
- snd_ctl_remove(codec->card, tas_hda->dsp_conf_ctl);
-
- for (int i = ARRAY_SIZE(tas_hda->snd_ctls) - 1; i >= 0; i--)
- snd_ctl_remove(codec->card, tas_hda->snd_ctls[i]);
+ snprintf(name, sizeof(name), "Speaker-%d Program Id", p->index);
+ tas2781_dsp_ctls[i].name = name;
+ h->dsp_prog_ctl = snd_ctl_new1(&tas2781_dsp_ctls[i], p);
+ rc = snd_ctl_add(c->card, h->dsp_prog_ctl);
+ if (rc) {
+ dev_err(p->dev, "Failed to add KControl: %s, rc = %d\n",
+ tas2781_dsp_ctls[i].name, rc);
+ return rc;
+ }
+ i++;
+ snprintf(name, sizeof(name), "Speaker-%d Config Id", p->index);
+ tas2781_dsp_ctls[i].name = name;
+ h->dsp_conf_ctl = snd_ctl_new1(&tas2781_dsp_ctls[i], p);
+ rc = snd_ctl_add(c->card, h->dsp_conf_ctl);
+ if (rc) {
+ dev_err(p->dev, "Failed to add KControl: %s, rc = %d\n",
+ tas2781_dsp_ctls[i].name, rc);
+ }
- snd_ctl_remove(codec->card, tas_hda->prof_ctl);
+ return rc;
}
static void tasdev_fw_ready(const struct firmware *fmw, void *context)
@@ -909,44 +633,30 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
struct tasdevice_priv *tas_priv = context;
struct tas2781_hda *tas_hda = dev_get_drvdata(tas_priv->dev);
struct hda_codec *codec = tas_priv->codec;
- int i, j, ret, val;
+ int ret, val;
pm_runtime_get_sync(tas_priv->dev);
guard(mutex)(&tas_priv->codec_lock);
- ret = tasdevice_spi_rca_parser(tas_priv, fmw);
+ ret = tasdevice_rca_parser(tas_priv, fmw);
if (ret)
goto out;
/* Add control one time only. */
- tas_hda->prof_ctl = snd_ctl_new1(&tas2781_prof_ctrl[tas_priv->index],
- tas_priv);
- ret = snd_ctl_add(codec->card, tas_hda->prof_ctl);
- if (ret) {
- dev_err(tas_priv->dev, "Failed to add KControl %s = %d\n",
- tas2781_prof_ctrl[tas_priv->index].name, ret);
+ ret = tas2781_hda_spi_prf_ctl(tas_hda);
+ if (ret)
+ goto out;
+
+ ret = tas2781_hda_spi_snd_ctls(tas_hda);
+ if (ret)
goto out;
- }
- j = tas_priv->index * ARRAY_SIZE(tas2781_snd_controls) / 2;
- for (i = 0; i < 3; i++) {
- tas_hda->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_controls[i+j],
- tas_priv);
- ret = snd_ctl_add(codec->card, tas_hda->snd_ctls[i]);
- if (ret) {
- dev_err(tas_priv->dev,
- "Failed to add KControl %s = %d\n",
- tas2781_snd_controls[i+tas_priv->index*3].name,
- ret);
- goto out;
- }
- }
- tasdevice_spi_dsp_remove(tas_priv);
+ tasdevice_dsp_remove(tas_priv);
tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING;
- scnprintf(tas_priv->coef_binaryname, 64, "TAS2XXX%08X-%01d.bin",
- codec->core.subsystem_id, tas_priv->index);
- ret = tasdevice_spi_dsp_parser(tas_priv);
+ scnprintf(tas_priv->coef_binaryname, 64, "TAS2XXX%04X-%01d.bin",
+ lower_16_bits(codec->core.subsystem_id), tas_priv->index);
+ ret = tasdevice_dsp_parser(tas_priv);
if (ret) {
dev_err(tas_priv->dev, "dspfw load %s error\n",
tas_priv->coef_binaryname);
@@ -954,54 +664,38 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
goto out;
}
- /* Add control one time only. */
- tas_hda->dsp_prog_ctl =
- snd_ctl_new1(&tas2781_dsp_prog_ctrl[tas_priv->index],
- tas_priv);
- ret = snd_ctl_add(codec->card, tas_hda->dsp_prog_ctl);
- if (ret) {
- dev_err(tas_priv->dev,
- "Failed to add KControl %s = %d\n",
- tas2781_dsp_prog_ctrl[tas_priv->index].name, ret);
- goto out;
- }
-
- tas_hda->dsp_conf_ctl =
- snd_ctl_new1(&tas2781_dsp_conf_ctrl[tas_priv->index],
- tas_priv);
- ret = snd_ctl_add(codec->card, tas_hda->dsp_conf_ctl);
- if (ret) {
- dev_err(tas_priv->dev, "Failed to add KControl %s = %d\n",
- tas2781_dsp_conf_ctrl[tas_priv->index].name, ret);
+ ret = tas2781_hda_spi_dsp_ctls(tas_hda);
+ if (ret)
goto out;
- }
-
/* Perform AMP reset before firmware download. */
- tas_priv->rcabin.profile_cfg_id = TAS2781_PRE_POST_RESET_CFG;
tas2781_spi_reset(tas_priv);
tas_priv->rcabin.profile_cfg_id = 0;
tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
- ret = tasdevice_spi_dev_read(tas_priv, TAS2781_REG_CLK_CONFIG, &val);
+ ret = tasdevice_spi_dev_read(tas_priv, tas_priv->index,
+ TAS2781_REG_CLK_CONFIG, &val);
if (ret < 0)
goto out;
- if (val == TAS2781_REG_CLK_CONFIG_RESET)
- ret = tasdevice_spi_prmg_load(tas_priv, 0);
- if (ret < 0) {
- dev_err(tas_priv->dev, "FW download failed = %d\n", ret);
- goto out;
+ if (val == TAS2781_REG_CLK_CONFIG_RESET) {
+ ret = tasdevice_prmg_load(tas_priv, 0);
+ if (ret < 0) {
+ dev_err(tas_priv->dev, "FW download failed = %d\n",
+ ret);
+ goto out;
+ }
+ tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
}
if (tas_priv->fmw->nr_programs > 0)
- tas_priv->cur_prog = 0;
+ tas_priv->tasdevice[tas_priv->index].cur_prog = 0;
if (tas_priv->fmw->nr_configurations > 0)
- tas_priv->cur_conf = 0;
+ tas_priv->tasdevice[tas_priv->index].cur_conf = 0;
/*
* If calibrated data occurs error, dsp will still works with default
* calibrated data inside algo.
*/
-
+ tas2781_save_calibration(tas_hda);
out:
release_firmware(fmw);
pm_runtime_mark_last_busy(tas_hda->priv->dev);
@@ -1048,9 +742,10 @@ static void tas2781_hda_unbind(struct device *dev, struct device *master,
{
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
struct hda_component_parent *parent = master_data;
+ struct tasdevice_priv *tas_priv = tas_hda->priv;
struct hda_component *comp;
- comp = hda_component_from_index(parent, tas_hda->priv->index);
+ comp = hda_component_from_index(parent, tas_priv->index);
if (comp && (comp->dev == dev)) {
comp->dev = NULL;
memset(comp->name, 0, sizeof(comp->name));
@@ -1059,8 +754,8 @@ static void tas2781_hda_unbind(struct device *dev, struct device *master,
tas2781_hda_remove_controls(tas_hda);
- tasdevice_spi_config_info_remove(tas_hda->priv);
- tasdevice_spi_dsp_remove(tas_hda->priv);
+ tasdevice_config_info_remove(tas_priv);
+ tasdevice_dsp_remove(tas_priv);
tas_hda->priv->fw_state = TASDEVICE_DSP_FW_PENDING;
}
@@ -1070,22 +765,9 @@ static const struct component_ops tas2781_hda_comp_ops = {
.unbind = tas2781_hda_unbind,
};
-static void tas2781_hda_remove(struct device *dev)
-{
- struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
-
- component_del(tas_hda->priv->dev, &tas2781_hda_comp_ops);
-
- pm_runtime_get_sync(tas_hda->priv->dev);
- pm_runtime_disable(tas_hda->priv->dev);
-
- pm_runtime_put_noidle(tas_hda->priv->dev);
-
- mutex_destroy(&tas_hda->priv->codec_lock);
-}
-
static int tas2781_hda_spi_probe(struct spi_device *spi)
{
+ struct tas2781_hda_spi_priv *hda_priv;
struct tasdevice_priv *tas_priv;
struct tas2781_hda *tas_hda;
const char *device_name;
@@ -1095,6 +777,11 @@ static int tas2781_hda_spi_probe(struct spi_device *spi)
if (!tas_hda)
return -ENOMEM;
+ hda_priv = devm_kzalloc(&spi->dev, sizeof(*hda_priv), GFP_KERNEL);
+ if (!hda_priv)
+ return -ENOMEM;
+
+ tas_hda->hda_priv = hda_priv;
spi->max_speed_hz = TAS2781_SPI_MAX_FREQ;
tas_priv = devm_kzalloc(&spi->dev, sizeof(*tas_priv), GFP_KERNEL);
@@ -1111,8 +798,6 @@ static int tas2781_hda_spi_probe(struct spi_device *spi)
}
if (strstr(dev_name(&spi->dev), "TXNW2781")) {
device_name = "TXNW2781";
- tas_priv->save_calibration = tas2781_save_calibration;
- tas_priv->apply_calibration = tas2781_apply_calib;
} else {
dev_err(tas_priv->dev, "Unmatched spi dev %s\n",
dev_name(&spi->dev));
@@ -1125,16 +810,10 @@ static int tas2781_hda_spi_probe(struct spi_device *spi)
spi_get_chipselect(spi, 0));
if (ret)
return dev_err_probe(tas_priv->dev, ret,
- "Platform not supported\n");
+ "Platform not supported\n");
tasdevice_spi_init(tas_priv);
- ret = component_add(tas_priv->dev, &tas2781_hda_comp_ops);
- if (ret) {
- dev_err(tas_priv->dev, "Register component fail: %d\n", ret);
- return ret;
- }
-
pm_runtime_set_autosuspend_delay(tas_priv->dev, 3000);
pm_runtime_use_autosuspend(tas_priv->dev);
pm_runtime_mark_last_busy(tas_priv->dev);
@@ -1144,25 +823,34 @@ static int tas2781_hda_spi_probe(struct spi_device *spi)
pm_runtime_put_autosuspend(tas_priv->dev);
- return 0;
+ ret = component_add(tas_priv->dev, &tas2781_hda_comp_ops);
+ if (ret) {
+ dev_err(tas_priv->dev, "Register component fail: %d\n", ret);
+ pm_runtime_disable(tas_priv->dev);
+ tas2781_hda_remove(&spi->dev, &tas2781_hda_comp_ops);
+ }
+
+ return ret;
}
static void tas2781_hda_spi_remove(struct spi_device *spi)
{
- tas2781_hda_remove(&spi->dev);
+ tas2781_hda_remove(&spi->dev, &tas2781_hda_comp_ops);
}
static int tas2781_runtime_suspend(struct device *dev)
{
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
+ struct tasdevice_priv *tas_priv = tas_hda->priv;
- guard(mutex)(&tas_hda->priv->codec_lock);
+ guard(mutex)(&tas_priv->codec_lock);
- if (tas_hda->priv->playback_started)
- tasdevice_spi_tuning_switch(tas_hda->priv, 1);
+ if (tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK
+ && tas_priv->playback_started)
+ tasdevice_tuning_switch(tas_priv, 1);
- tas_hda->priv->cur_book = -1;
- tas_hda->priv->cur_conf = -1;
+ tas_priv->tasdevice[tas_priv->index].cur_book = -1;
+ tas_priv->tasdevice[tas_priv->index].cur_conf = -1;
return 0;
}
@@ -1170,11 +858,13 @@ static int tas2781_runtime_suspend(struct device *dev)
static int tas2781_runtime_resume(struct device *dev)
{
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
+ struct tasdevice_priv *tas_priv = tas_hda->priv;
- guard(mutex)(&tas_hda->priv->codec_lock);
+ guard(mutex)(&tas_priv->codec_lock);
- if (tas_hda->priv->playback_started)
- tasdevice_spi_tuning_switch(tas_hda->priv, 0);
+ if (tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK
+ && tas_priv->playback_started)
+ tasdevice_tuning_switch(tas_priv, 0);
return 0;
}
@@ -1182,6 +872,7 @@ static int tas2781_runtime_resume(struct device *dev)
static int tas2781_system_suspend(struct device *dev)
{
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
+ struct tasdevice_priv *tas_priv = tas_hda->priv;
int ret;
ret = pm_runtime_force_suspend(dev);
@@ -1189,8 +880,9 @@ static int tas2781_system_suspend(struct device *dev)
return ret;
/* Shutdown chip before system suspend */
- if (tas_hda->priv->playback_started)
- tasdevice_spi_tuning_switch(tas_hda->priv, 1);
+ if (tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK
+ && tas_priv->playback_started)
+ tasdevice_tuning_switch(tas_priv, 1);
return 0;
}
@@ -1198,32 +890,34 @@ static int tas2781_system_suspend(struct device *dev)
static int tas2781_system_resume(struct device *dev)
{
struct tas2781_hda *tas_hda = dev_get_drvdata(dev);
+ struct tasdevice_priv *tas_priv = tas_hda->priv;
int ret, val;
ret = pm_runtime_force_resume(dev);
if (ret)
return ret;
- guard(mutex)(&tas_hda->priv->codec_lock);
- ret = tasdevice_spi_dev_read(tas_hda->priv, TAS2781_REG_CLK_CONFIG,
- &val);
+ guard(mutex)(&tas_priv->codec_lock);
+ ret = tas_priv->dev_read(tas_priv, tas_priv->index,
+ TAS2781_REG_CLK_CONFIG, &val);
if (ret < 0)
return ret;
if (val == TAS2781_REG_CLK_CONFIG_RESET) {
- tas_hda->priv->cur_book = -1;
- tas_hda->priv->cur_conf = -1;
- tas_hda->priv->cur_prog = -1;
+ tas_priv->tasdevice[tas_priv->index].cur_book = -1;
+ tas_priv->tasdevice[tas_priv->index].cur_conf = -1;
+ tas_priv->tasdevice[tas_priv->index].cur_prog = -1;
- ret = tasdevice_spi_prmg_load(tas_hda->priv, 0);
+ ret = tasdevice_prmg_load(tas_priv, 0);
if (ret < 0) {
- dev_err(tas_hda->priv->dev,
+ dev_err(tas_priv->dev,
"FW download failed = %d\n", ret);
return ret;
}
+ tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
- if (tas_hda->priv->playback_started)
- tasdevice_spi_tuning_switch(tas_hda->priv, 0);
+ if (tas_priv->playback_started)
+ tasdevice_tuning_switch(tas_priv, 0);
}
return ret;
@@ -1260,3 +954,5 @@ module_spi_driver(tas2781_hda_spi_driver);
MODULE_DESCRIPTION("TAS2781 HDA SPI Driver");
MODULE_AUTHOR("Baojun, Xu, <baojun.xug@ti.com>");
MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("SND_SOC_TAS2781_FMWLIB");
+MODULE_IMPORT_NS("SND_HDA_SCODEC_TAS2781");
diff --git a/sound/pci/hda/tas2781_spi_fwlib.c b/sound/pci/hda/tas2781_spi_fwlib.c
deleted file mode 100644
index d90d022d8449..000000000000
--- a/sound/pci/hda/tas2781_spi_fwlib.c
+++ /dev/null
@@ -1,2006 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// TAS2781 HDA SPI driver
-//
-// Copyright 2024 - 2025 Texas Instruments, Inc.
-//
-// Author: Baojun Xu <baojun.xu@ti.com>
-
-#include <linux/crc8.h>
-#include <linux/firmware.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/types.h>
-#include <linux/unaligned.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/tas2781-dsp.h>
-#include <sound/tlv.h>
-
-#include "tas2781-spi.h"
-
-#define OFFSET_ERROR_BIT BIT(31)
-
-#define ERROR_PRAM_CRCCHK 0x0000000
-#define ERROR_YRAM_CRCCHK 0x0000001
-#define PPC_DRIVER_CRCCHK 0x00000200
-
-#define TAS2781_SA_COEFF_SWAP_REG TASDEVICE_REG(0, 0x35, 0x2c)
-#define TAS2781_YRAM_BOOK1 140
-#define TAS2781_YRAM1_PAGE 42
-#define TAS2781_YRAM1_START_REG 88
-
-#define TAS2781_YRAM2_START_PAGE 43
-#define TAS2781_YRAM2_END_PAGE 49
-#define TAS2781_YRAM2_START_REG 8
-#define TAS2781_YRAM2_END_REG 127
-
-#define TAS2781_YRAM3_PAGE 50
-#define TAS2781_YRAM3_START_REG 8
-#define TAS2781_YRAM3_END_REG 27
-
-/* should not include B0_P53_R44-R47 */
-#define TAS2781_YRAM_BOOK2 0
-#define TAS2781_YRAM4_START_PAGE 50
-#define TAS2781_YRAM4_END_PAGE 60
-
-#define TAS2781_YRAM5_PAGE 61
-#define TAS2781_YRAM5_START_REG TAS2781_YRAM3_START_REG
-#define TAS2781_YRAM5_END_REG TAS2781_YRAM3_END_REG
-
-#define TASDEVICE_MAXPROGRAM_NUM_KERNEL 5
-#define TASDEVICE_MAXCONFIG_NUM_KERNEL_MULTIPLE_AMPS 64
-#define TASDEVICE_MAXCONFIG_NUM_KERNEL 10
-#define MAIN_ALL_DEVICES_1X 0x01
-#define MAIN_DEVICE_A_1X 0x02
-#define MAIN_DEVICE_B_1X 0x03
-#define MAIN_DEVICE_C_1X 0x04
-#define MAIN_DEVICE_D_1X 0x05
-#define COEFF_DEVICE_A_1X 0x12
-#define COEFF_DEVICE_B_1X 0x13
-#define COEFF_DEVICE_C_1X 0x14
-#define COEFF_DEVICE_D_1X 0x15
-#define PRE_DEVICE_A_1X 0x22
-#define PRE_DEVICE_B_1X 0x23
-#define PRE_DEVICE_C_1X 0x24
-#define PRE_DEVICE_D_1X 0x25
-#define PRE_SOFTWARE_RESET_DEVICE_A 0x41
-#define PRE_SOFTWARE_RESET_DEVICE_B 0x42
-#define PRE_SOFTWARE_RESET_DEVICE_C 0x43
-#define PRE_SOFTWARE_RESET_DEVICE_D 0x44
-#define POST_SOFTWARE_RESET_DEVICE_A 0x45
-#define POST_SOFTWARE_RESET_DEVICE_B 0x46
-#define POST_SOFTWARE_RESET_DEVICE_C 0x47
-#define POST_SOFTWARE_RESET_DEVICE_D 0x48
-
-struct tas_crc {
- unsigned char offset;
- unsigned char len;
-};
-
-struct blktyp_devidx_map {
- unsigned char blktyp;
- unsigned char dev_idx;
-};
-
-/* fixed m68k compiling issue: mapping table can save code field */
-static const struct blktyp_devidx_map ppc3_tas2781_mapping_table[] = {
- { MAIN_ALL_DEVICES_1X, 0x80 },
- { MAIN_DEVICE_A_1X, 0x81 },
- { COEFF_DEVICE_A_1X, 0x81 },
- { PRE_DEVICE_A_1X, 0x81 },
- { PRE_SOFTWARE_RESET_DEVICE_A, 0xC1 },
- { POST_SOFTWARE_RESET_DEVICE_A, 0xC1 },
- { MAIN_DEVICE_B_1X, 0x82 },
- { COEFF_DEVICE_B_1X, 0x82 },
- { PRE_DEVICE_B_1X, 0x82 },
- { PRE_SOFTWARE_RESET_DEVICE_B, 0xC2 },
- { POST_SOFTWARE_RESET_DEVICE_B, 0xC2 },
- { MAIN_DEVICE_C_1X, 0x83 },
- { COEFF_DEVICE_C_1X, 0x83 },
- { PRE_DEVICE_C_1X, 0x83 },
- { PRE_SOFTWARE_RESET_DEVICE_C, 0xC3 },
- { POST_SOFTWARE_RESET_DEVICE_C, 0xC3 },
- { MAIN_DEVICE_D_1X, 0x84 },
- { COEFF_DEVICE_D_1X, 0x84 },
- { PRE_DEVICE_D_1X, 0x84 },
- { PRE_SOFTWARE_RESET_DEVICE_D, 0xC4 },
- { POST_SOFTWARE_RESET_DEVICE_D, 0xC4 },
-};
-
-static const struct blktyp_devidx_map ppc3_mapping_table[] = {
- { MAIN_ALL_DEVICES_1X, 0x80 },
- { MAIN_DEVICE_A_1X, 0x81 },
- { COEFF_DEVICE_A_1X, 0xC1 },
- { PRE_DEVICE_A_1X, 0xC1 },
- { MAIN_DEVICE_B_1X, 0x82 },
- { COEFF_DEVICE_B_1X, 0xC2 },
- { PRE_DEVICE_B_1X, 0xC2 },
- { MAIN_DEVICE_C_1X, 0x83 },
- { COEFF_DEVICE_C_1X, 0xC3 },
- { PRE_DEVICE_C_1X, 0xC3 },
- { MAIN_DEVICE_D_1X, 0x84 },
- { COEFF_DEVICE_D_1X, 0xC4 },
- { PRE_DEVICE_D_1X, 0xC4 },
-};
-
-static const struct blktyp_devidx_map non_ppc3_mapping_table[] = {
- { MAIN_ALL_DEVICES, 0x80 },
- { MAIN_DEVICE_A, 0x81 },
- { COEFF_DEVICE_A, 0xC1 },
- { PRE_DEVICE_A, 0xC1 },
- { MAIN_DEVICE_B, 0x82 },
- { COEFF_DEVICE_B, 0xC2 },
- { PRE_DEVICE_B, 0xC2 },
- { MAIN_DEVICE_C, 0x83 },
- { COEFF_DEVICE_C, 0xC3 },
- { PRE_DEVICE_C, 0xC3 },
- { MAIN_DEVICE_D, 0x84 },
- { COEFF_DEVICE_D, 0xC4 },
- { PRE_DEVICE_D, 0xC4 },
-};
-
-/*
- * Device support different configurations for different scene,
- * like voice, music, calibration, was write in regbin file.
- * Will be stored into tas_priv after regbin was loaded.
- */
-static struct tasdevice_config_info *tasdevice_add_config(
- struct tasdevice_priv *tas_priv, unsigned char *config_data,
- unsigned int config_size, int *status)
-{
- struct tasdevice_config_info *cfg_info;
- struct tasdev_blk_data **bk_da;
- unsigned int config_offset = 0;
- unsigned int i;
-
- /*
- * In most projects are many audio cases, such as music, handfree,
- * receiver, games, audio-to-haptics, PMIC record, bypass mode,
- * portrait, landscape, etc. Even in multiple audios, one or
- * two of the chips will work for the special case, such as
- * ultrasonic application. In order to support these variable-numbers
- * of audio cases, flexible configs have been introduced in the
- * DSP firmware.
- */
- cfg_info = kzalloc(sizeof(*cfg_info), GFP_KERNEL);
- if (!cfg_info) {
- *status = -ENOMEM;
- return NULL;
- }
-
- if (tas_priv->rcabin.fw_hdr.binary_version_num >= 0x105) {
- if ((config_offset + 64) > config_size) {
- *status = -EINVAL;
- dev_err(tas_priv->dev, "add conf: Out of boundary\n");
- goto config_err;
- }
- config_offset += 64;
- }
-
- if ((config_offset + 4) > config_size) {
- *status = -EINVAL;
- dev_err(tas_priv->dev, "add config: Out of boundary\n");
- goto config_err;
- }
-
- /*
- * convert data[offset], data[offset + 1], data[offset + 2] and
- * data[offset + 3] into host
- */
- cfg_info->nblocks = get_unaligned_be32(&config_data[config_offset]);
- config_offset += 4;
-
- /*
- * Several kinds of dsp/algorithm firmwares can run on tas2781,
- * the number and size of blk are not fixed and different among
- * these firmwares.
- */
- bk_da = cfg_info->blk_data = kcalloc(cfg_info->nblocks,
- sizeof(*bk_da), GFP_KERNEL);
- if (!bk_da) {
- *status = -ENOMEM;
- goto config_err;
- }
- cfg_info->real_nblocks = 0;
- for (i = 0; i < cfg_info->nblocks; i++) {
- if (config_offset + 12 > config_size) {
- *status = -EINVAL;
- dev_err(tas_priv->dev,
- "%s: Out of boundary: i = %d nblocks = %u!\n",
- __func__, i, cfg_info->nblocks);
- goto block_err;
- }
- bk_da[i] = kzalloc(sizeof(*bk_da[i]), GFP_KERNEL);
- if (!bk_da[i]) {
- *status = -ENOMEM;
- goto block_err;
- }
-
- bk_da[i]->dev_idx = config_data[config_offset];
- config_offset++;
-
- bk_da[i]->block_type = config_data[config_offset];
- config_offset++;
-
- bk_da[i]->yram_checksum =
- get_unaligned_be16(&config_data[config_offset]);
- config_offset += 2;
- bk_da[i]->block_size =
- get_unaligned_be32(&config_data[config_offset]);
- config_offset += 4;
-
- bk_da[i]->n_subblks =
- get_unaligned_be32(&config_data[config_offset]);
-
- config_offset += 4;
-
- if (config_offset + bk_da[i]->block_size > config_size) {
- *status = -EINVAL;
- dev_err(tas_priv->dev,
- "%s: Out of boundary: i = %d blks = %u!\n",
- __func__, i, cfg_info->nblocks);
- goto block_err;
- }
- /* instead of kzalloc+memcpy */
- bk_da[i]->regdata = kmemdup(&config_data[config_offset],
- bk_da[i]->block_size, GFP_KERNEL);
- if (!bk_da[i]->regdata) {
- *status = -ENOMEM;
- i++;
- goto block_err;
- }
-
- config_offset += bk_da[i]->block_size;
- cfg_info->real_nblocks += 1;
- }
-
- return cfg_info;
-block_err:
- for (int j = 0; j < i; j++)
- kfree(bk_da[j]);
- kfree(bk_da);
-config_err:
- kfree(cfg_info);
- return NULL;
-}
-
-/* Regbin file parser function. */
-int tasdevice_spi_rca_parser(void *context, const struct firmware *fmw)
-{
- struct tasdevice_priv *tas_priv = context;
- struct tasdevice_config_info **cfg_info;
- struct tasdevice_rca_hdr *fw_hdr;
- struct tasdevice_rca *rca;
- unsigned int total_config_sz = 0;
- int offset = 0, ret = 0, i;
- unsigned char *buf;
-
- rca = &tas_priv->rcabin;
- fw_hdr = &rca->fw_hdr;
- if (!fmw || !fmw->data) {
- dev_err(tas_priv->dev, "Failed to read %s\n",
- tas_priv->rca_binaryname);
- tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
- return -EINVAL;
- }
- buf = (unsigned char *)fmw->data;
- fw_hdr->img_sz = get_unaligned_be32(&buf[offset]);
- offset += 4;
- if (fw_hdr->img_sz != fmw->size) {
- dev_err(tas_priv->dev,
- "File size not match, %d %u", (int)fmw->size,
- fw_hdr->img_sz);
- tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
- return -EINVAL;
- }
-
- fw_hdr->checksum = get_unaligned_be32(&buf[offset]);
- offset += 4;
- fw_hdr->binary_version_num = get_unaligned_be32(&buf[offset]);
- if (fw_hdr->binary_version_num < 0x103) {
- dev_err(tas_priv->dev, "File version 0x%04x is too low",
- fw_hdr->binary_version_num);
- tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
- return -EINVAL;
- }
- offset += 4;
- fw_hdr->drv_fw_version = get_unaligned_be32(&buf[offset]);
- offset += 8;
- fw_hdr->plat_type = buf[offset++];
- fw_hdr->dev_family = buf[offset++];
- fw_hdr->reserve = buf[offset++];
- fw_hdr->ndev = buf[offset++];
- if (offset + TASDEVICE_DEVICE_SUM > fw_hdr->img_sz) {
- dev_err(tas_priv->dev, "rca_ready: Out of boundary!\n");
- tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
- return -EINVAL;
- }
-
- for (i = 0; i < TASDEVICE_DEVICE_SUM; i++, offset++)
- fw_hdr->devs[i] = buf[offset];
-
- fw_hdr->nconfig = get_unaligned_be32(&buf[offset]);
- offset += 4;
-
- for (i = 0; i < TASDEVICE_CONFIG_SUM; i++) {
- fw_hdr->config_size[i] = get_unaligned_be32(&buf[offset]);
- offset += 4;
- total_config_sz += fw_hdr->config_size[i];
- }
-
- if (fw_hdr->img_sz - total_config_sz != (unsigned int)offset) {
- dev_err(tas_priv->dev, "Bin file err %d - %d != %d!\n",
- fw_hdr->img_sz, total_config_sz, (int)offset);
- tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
- return -EINVAL;
- }
-
- cfg_info = kcalloc(fw_hdr->nconfig, sizeof(*cfg_info), GFP_KERNEL);
- if (!cfg_info) {
- tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
- return -ENOMEM;
- }
- rca->cfg_info = cfg_info;
- rca->ncfgs = 0;
- for (i = 0; i < (int)fw_hdr->nconfig; i++) {
- rca->ncfgs += 1;
- cfg_info[i] = tasdevice_add_config(tas_priv, &buf[offset],
- fw_hdr->config_size[i], &ret);
- if (ret) {
- tas_priv->fw_state = TASDEVICE_DSP_FW_FAIL;
- return ret;
- }
- offset += (int)fw_hdr->config_size[i];
- }
-
- return ret;
-}
-
-/* fixed m68k compiling issue: mapping table can save code field */
-static unsigned char map_dev_idx(struct tasdevice_fw *tas_fmw,
- struct tasdev_blk *block)
-{
- struct blktyp_devidx_map *p =
- (struct blktyp_devidx_map *)non_ppc3_mapping_table;
- struct tasdevice_dspfw_hdr *fw_hdr = &tas_fmw->fw_hdr;
- struct tasdevice_fw_fixed_hdr *fw_fixed_hdr = &fw_hdr->fixed_hdr;
- int i, n = ARRAY_SIZE(non_ppc3_mapping_table);
- unsigned char dev_idx = 0;
-
- if (fw_fixed_hdr->ppcver >= PPC3_VERSION_TAS2781_BASIC_MIN) {
- p = (struct blktyp_devidx_map *)ppc3_tas2781_mapping_table;
- n = ARRAY_SIZE(ppc3_tas2781_mapping_table);
- } else if (fw_fixed_hdr->ppcver >= PPC3_VERSION_BASE) {
- p = (struct blktyp_devidx_map *)ppc3_mapping_table;
- n = ARRAY_SIZE(ppc3_mapping_table);
- }
-
- for (i = 0; i < n; i++) {
- if (block->type == p[i].blktyp) {
- dev_idx = p[i].dev_idx;
- break;
- }
- }
-
- return dev_idx;
-}
-
-/* Block parser function. */
-static int fw_parse_block_data_kernel(struct tasdevice_fw *tas_fmw,
- struct tasdev_blk *block, const struct firmware *fmw, int offset)
-{
- const unsigned char *data = fmw->data;
-
- if (offset + 16 > fmw->size) {
- dev_err(tas_fmw->dev, "%s: File Size error\n", __func__);
- return -EINVAL;
- }
-
- /*
- * Convert data[offset], data[offset + 1], data[offset + 2] and
- * data[offset + 3] into host.
- */
- block->type = get_unaligned_be32(&data[offset]);
- offset += 4;
-
- block->is_pchksum_present = data[offset++];
- block->pchksum = data[offset++];
- block->is_ychksum_present = data[offset++];
- block->ychksum = data[offset++];
- block->blk_size = get_unaligned_be32(&data[offset]);
- offset += 4;
- block->nr_subblocks = get_unaligned_be32(&data[offset]);
- offset += 4;
-
- /*
- * Fixed m68k compiling issue:
- * 1. mapping table can save code field.
- * 2. storing the dev_idx as a member of block can reduce unnecessary
- * time and system resource comsumption of dev_idx mapping every
- * time the block data writing to the dsp.
- */
- block->dev_idx = map_dev_idx(tas_fmw, block);
-
- if (offset + block->blk_size > fmw->size) {
- dev_err(tas_fmw->dev, "%s: nSublocks error\n", __func__);
- return -EINVAL;
- }
- /* instead of kzalloc+memcpy */
- block->data = kmemdup(&data[offset], block->blk_size, GFP_KERNEL);
- if (!block->data)
- return -ENOMEM;
-
- offset += block->blk_size;
-
- return offset;
-}
-
-/* Data of block parser function. */
-static int fw_parse_data_kernel(struct tasdevice_fw *tas_fmw,
- struct tasdevice_data *img_data, const struct firmware *fmw,
- int offset)
-{
- const unsigned char *data = fmw->data;
- struct tasdev_blk *blk;
- unsigned int i;
-
- if (offset + 4 > fmw->size) {
- dev_err(tas_fmw->dev, "%s: File Size error\n", __func__);
- return -EINVAL;
- }
- img_data->nr_blk = get_unaligned_be32(&data[offset]);
- offset += 4;
-
- img_data->dev_blks = kcalloc(img_data->nr_blk,
- sizeof(struct tasdev_blk), GFP_KERNEL);
- if (!img_data->dev_blks)
- return -ENOMEM;
-
- for (i = 0; i < img_data->nr_blk; i++) {
- blk = &img_data->dev_blks[i];
- offset = fw_parse_block_data_kernel(
- tas_fmw, blk, fmw, offset);
- if (offset < 0) {
- kfree(img_data->dev_blks);
- return -EINVAL;
- }
- }
-
- return offset;
-}
-
-/* Data of DSP program parser function. */
-static int fw_parse_program_data_kernel(
- struct tasdevice_priv *tas_priv, struct tasdevice_fw *tas_fmw,
- const struct firmware *fmw, int offset)
-{
- struct tasdevice_prog *program;
- unsigned int i;
-
- for (i = 0; i < tas_fmw->nr_programs; i++) {
- program = &tas_fmw->programs[i];
- if (offset + 72 > fmw->size) {
- dev_err(tas_priv->dev, "%s: mpName error\n", __func__);
- return -EINVAL;
- }
- /* skip 72 unused byts */
- offset += 72;
-
- offset = fw_parse_data_kernel(tas_fmw, &program->dev_data,
- fmw, offset);
- if (offset < 0)
- break;
- }
-
- return offset;
-}
-
-/* Data of DSP configurations parser function. */
-static int fw_parse_configuration_data_kernel(struct tasdevice_priv *tas_priv,
- struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
-{
- const unsigned char *data = fmw->data;
- struct tasdevice_config *config;
- unsigned int i;
-
- for (i = 0; i < tas_fmw->nr_configurations; i++) {
- config = &tas_fmw->configs[i];
- if (offset + 80 > fmw->size) {
- dev_err(tas_priv->dev, "%s: mpName error\n", __func__);
- return -EINVAL;
- }
- memcpy(config->name, &data[offset], 64);
- /* skip extra 16 bytes */
- offset += 80;
-
- offset = fw_parse_data_kernel(tas_fmw, &config->dev_data,
- fmw, offset);
- if (offset < 0)
- break;
- }
-
- return offset;
-}
-
-/* DSP firmware file header parser function for early PPC3 firmware binary. */
-static int fw_parse_variable_header_kernel(struct tasdevice_priv *tas_priv,
- const struct firmware *fmw, int offset)
-{
- struct tasdevice_fw *tas_fmw = tas_priv->fmw;
- struct tasdevice_dspfw_hdr *fw_hdr = &tas_fmw->fw_hdr;
- struct tasdevice_config *config;
- struct tasdevice_prog *program;
- const unsigned char *buf = fmw->data;
- unsigned short max_confs;
- unsigned int i;
-
- if (offset + 12 + 4 * TASDEVICE_MAXPROGRAM_NUM_KERNEL > fmw->size) {
- dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
- return -EINVAL;
- }
- fw_hdr->device_family = get_unaligned_be16(&buf[offset]);
- if (fw_hdr->device_family != 0) {
- dev_err(tas_priv->dev, "%s:not TAS device\n", __func__);
- return -EINVAL;
- }
- offset += 2;
- fw_hdr->device = get_unaligned_be16(&buf[offset]);
- if (fw_hdr->device >= TASDEVICE_DSP_TAS_MAX_DEVICE ||
- fw_hdr->device == 6) {
- dev_err(tas_priv->dev, "Unsupported dev %d\n", fw_hdr->device);
- return -EINVAL;
- }
- offset += 2;
-
- tas_fmw->nr_programs = get_unaligned_be32(&buf[offset]);
- offset += 4;
-
- if (tas_fmw->nr_programs == 0 ||
- tas_fmw->nr_programs > TASDEVICE_MAXPROGRAM_NUM_KERNEL) {
- dev_err(tas_priv->dev, "mnPrograms is invalid\n");
- return -EINVAL;
- }
-
- tas_fmw->programs = kcalloc(tas_fmw->nr_programs,
- sizeof(*tas_fmw->programs), GFP_KERNEL);
- if (!tas_fmw->programs)
- return -ENOMEM;
-
- for (i = 0; i < tas_fmw->nr_programs; i++) {
- program = &tas_fmw->programs[i];
- program->prog_size = get_unaligned_be32(&buf[offset]);
- offset += 4;
- }
-
- /* Skip the unused prog_size */
- offset += 4 * (TASDEVICE_MAXPROGRAM_NUM_KERNEL - tas_fmw->nr_programs);
-
- tas_fmw->nr_configurations = get_unaligned_be32(&buf[offset]);
- offset += 4;
-
- /*
- * The max number of config in firmware greater than 4 pieces of
- * tas2781s is different from the one lower than 4 pieces of
- * tas2781s.
- */
- max_confs = TASDEVICE_MAXCONFIG_NUM_KERNEL;
- if (tas_fmw->nr_configurations == 0 ||
- tas_fmw->nr_configurations > max_confs) {
- dev_err(tas_priv->dev, "%s: Conf is invalid\n", __func__);
- kfree(tas_fmw->programs);
- return -EINVAL;
- }
-
- if (offset + 4 * max_confs > fmw->size) {
- dev_err(tas_priv->dev, "%s: mpConfigurations err\n", __func__);
- kfree(tas_fmw->programs);
- return -EINVAL;
- }
-
- tas_fmw->configs = kcalloc(tas_fmw->nr_configurations,
- sizeof(*tas_fmw->configs), GFP_KERNEL);
- if (!tas_fmw->configs) {
- kfree(tas_fmw->programs);
- return -ENOMEM;
- }
-
- for (i = 0; i < tas_fmw->nr_programs; i++) {
- config = &tas_fmw->configs[i];
- config->cfg_size = get_unaligned_be32(&buf[offset]);
- offset += 4;
- }
-
- /* Skip the unused configs */
- offset += 4 * (max_confs - tas_fmw->nr_programs);
-
- return offset;
-}
-
-/*
- * In sub-block data, have three type sub-block:
- * 1. Single byte write.
- * 2. Multi-byte write.
- * 3. Delay.
- * 4. Bits update.
- * This function perform single byte write to device.
- */
-static int tasdevice_single_byte_wr(void *context, int dev_idx,
- unsigned char *data, int sublocksize)
-{
- struct tasdevice_priv *tas_priv = context;
- unsigned short len = get_unaligned_be16(&data[2]);
- int i, subblk_offset, rc;
-
- subblk_offset = 4;
- if (subblk_offset + 4 * len > sublocksize) {
- dev_err(tas_priv->dev, "process_block: Out of boundary\n");
- return 0;
- }
-
- for (i = 0; i < len; i++) {
- if (dev_idx == (tas_priv->index + 1) || dev_idx == 0) {
- rc = tasdevice_spi_dev_write(tas_priv,
- TASDEVICE_REG(data[subblk_offset],
- data[subblk_offset + 1],
- data[subblk_offset + 2]),
- data[subblk_offset + 3]);
- if (rc < 0) {
- dev_err(tas_priv->dev,
- "process_block: single write error\n");
- subblk_offset |= OFFSET_ERROR_BIT;
- }
- }
- subblk_offset += 4;
- }
-
- return subblk_offset;
-}
-
-/*
- * In sub-block data, have three type sub-block:
- * 1. Single byte write.
- * 2. Multi-byte write.
- * 3. Delay.
- * 4. Bits update.
- * This function perform multi-write to device.
- */
-static int tasdevice_burst_wr(void *context, int dev_idx, unsigned char *data,
- int sublocksize)
-{
- struct tasdevice_priv *tas_priv = context;
- unsigned short len = get_unaligned_be16(&data[2]);
- int subblk_offset, rc;
-
- subblk_offset = 4;
- if (subblk_offset + 4 + len > sublocksize) {
- dev_err(tas_priv->dev, "%s: BST Out of boundary\n", __func__);
- subblk_offset |= OFFSET_ERROR_BIT;
- }
- if (len % 4) {
- dev_err(tas_priv->dev, "%s:Bst-len(%u)not div by 4\n",
- __func__, len);
- subblk_offset |= OFFSET_ERROR_BIT;
- }
-
- if (dev_idx == (tas_priv->index + 1) || dev_idx == 0) {
- rc = tasdevice_spi_dev_bulk_write(tas_priv,
- TASDEVICE_REG(data[subblk_offset],
- data[subblk_offset + 1],
- data[subblk_offset + 2]),
- &data[subblk_offset + 4], len);
- if (rc < 0) {
- dev_err(tas_priv->dev, "%s: bulk_write error = %d\n",
- __func__, rc);
- subblk_offset |= OFFSET_ERROR_BIT;
- }
- }
- subblk_offset += (len + 4);
-
- return subblk_offset;
-}
-
-/* Just delay for ms.*/
-static int tasdevice_delay(void *context, int dev_idx, unsigned char *data,
- int sublocksize)
-{
- struct tasdevice_priv *tas_priv = context;
- unsigned int sleep_time, subblk_offset = 2;
-
- if (subblk_offset + 2 > sublocksize) {
- dev_err(tas_priv->dev, "%s: delay Out of boundary\n",
- __func__);
- subblk_offset |= OFFSET_ERROR_BIT;
- }
- if (dev_idx == (tas_priv->index + 1) || dev_idx == 0) {
- sleep_time = get_unaligned_be16(&data[2]) * 1000;
- fsleep(sleep_time);
- }
- subblk_offset += 2;
-
- return subblk_offset;
-}
-
-/*
- * In sub-block data, have three type sub-block:
- * 1. Single byte write.
- * 2. Multi-byte write.
- * 3. Delay.
- * 4. Bits update.
- * This function perform bits update.
- */
-static int tasdevice_field_wr(void *context, int dev_idx, unsigned char *data,
- int sublocksize)
-{
- struct tasdevice_priv *tas_priv = context;
- int rc, subblk_offset = 2;
-
- if (subblk_offset + 6 > sublocksize) {
- dev_err(tas_priv->dev, "%s: bit write Out of boundary\n",
- __func__);
- subblk_offset |= OFFSET_ERROR_BIT;
- }
- if (dev_idx == (tas_priv->index + 1) || dev_idx == 0) {
- rc = tasdevice_spi_dev_update_bits(tas_priv,
- TASDEVICE_REG(data[subblk_offset + 2],
- data[subblk_offset + 3],
- data[subblk_offset + 4]),
- data[subblk_offset + 1],
- data[subblk_offset + 5]);
- if (rc < 0) {
- dev_err(tas_priv->dev, "%s: update_bits error = %d\n",
- __func__, rc);
- subblk_offset |= OFFSET_ERROR_BIT;
- }
- }
- subblk_offset += 6;
-
- return subblk_offset;
-}
-
-/* Data block process function. */
-static int tasdevice_process_block(void *context, unsigned char *data,
- unsigned char dev_idx, int sublocksize)
-{
- struct tasdevice_priv *tas_priv = context;
- int blktyp = dev_idx & 0xC0, subblk_offset;
- unsigned char subblk_typ = data[1];
-
- switch (subblk_typ) {
- case TASDEVICE_CMD_SING_W:
- subblk_offset = tasdevice_single_byte_wr(tas_priv,
- dev_idx & 0x3f, data, sublocksize);
- break;
- case TASDEVICE_CMD_BURST:
- subblk_offset = tasdevice_burst_wr(tas_priv,
- dev_idx & 0x3f, data, sublocksize);
- break;
- case TASDEVICE_CMD_DELAY:
- subblk_offset = tasdevice_delay(tas_priv,
- dev_idx & 0x3f, data, sublocksize);
- break;
- case TASDEVICE_CMD_FIELD_W:
- subblk_offset = tasdevice_field_wr(tas_priv,
- dev_idx & 0x3f, data, sublocksize);
- break;
- default:
- subblk_offset = 2;
- break;
- }
- if (((subblk_offset & OFFSET_ERROR_BIT) != 0) && blktyp != 0) {
- if (blktyp == 0x80) {
- tas_priv->cur_prog = -1;
- tas_priv->cur_conf = -1;
- } else
- tas_priv->cur_conf = -1;
- }
- subblk_offset &= ~OFFSET_ERROR_BIT;
-
- return subblk_offset;
-}
-
-/*
- * Device support different configurations for different scene,
- * this function was used for choose different config.
- */
-void tasdevice_spi_select_cfg_blk(void *pContext, int conf_no,
- unsigned char block_type)
-{
- struct tasdevice_priv *tas_priv = pContext;
- struct tasdevice_rca *rca = &tas_priv->rcabin;
- struct tasdevice_config_info **cfg_info = rca->cfg_info;
- struct tasdev_blk_data **blk_data;
- unsigned int j, k;
-
- if (conf_no >= rca->ncfgs || conf_no < 0 || !cfg_info) {
- dev_err(tas_priv->dev, "conf_no should be not more than %u\n",
- rca->ncfgs);
- return;
- }
- blk_data = cfg_info[conf_no]->blk_data;
-
- for (j = 0; j < cfg_info[conf_no]->real_nblocks; j++) {
- unsigned int length = 0, rc = 0;
-
- if (block_type > 5 || block_type < 2) {
- dev_err(tas_priv->dev,
- "block_type should be in range from 2 to 5\n");
- break;
- }
- if (block_type != blk_data[j]->block_type)
- continue;
-
- for (k = 0; k < blk_data[j]->n_subblks; k++) {
- tas_priv->is_loading = true;
-
- rc = tasdevice_process_block(tas_priv,
- blk_data[j]->regdata + length,
- blk_data[j]->dev_idx,
- blk_data[j]->block_size - length);
- length += rc;
- if (blk_data[j]->block_size < length) {
- dev_err(tas_priv->dev,
- "%s: %u %u out of boundary\n",
- __func__, length,
- blk_data[j]->block_size);
- break;
- }
- }
- if (length != blk_data[j]->block_size)
- dev_err(tas_priv->dev, "%s: %u %u size is not same\n",
- __func__, length, blk_data[j]->block_size);
- }
-}
-
-/* Block process function. */
-static int tasdevice_load_block_kernel(
- struct tasdevice_priv *tasdevice, struct tasdev_blk *block)
-{
- const unsigned int blk_size = block->blk_size;
- unsigned char *data = block->data;
- unsigned int i, length;
-
- for (i = 0, length = 0; i < block->nr_subblocks; i++) {
- int rc = tasdevice_process_block(tasdevice, data + length,
- block->dev_idx, blk_size - length);
- if (rc < 0) {
- dev_err(tasdevice->dev,
- "%s: %u %u sublock write error\n",
- __func__, length, blk_size);
- return rc;
- }
- length += rc;
- if (blk_size < length) {
- dev_err(tasdevice->dev, "%s: %u %u out of boundary\n",
- __func__, length, blk_size);
- rc = -ENOMEM;
- return rc;
- }
- }
-
- return 0;
-}
-
-/* DSP firmware file header parser function. */
-static int fw_parse_variable_hdr(struct tasdevice_priv *tas_priv,
- struct tasdevice_dspfw_hdr *fw_hdr,
- const struct firmware *fmw, int offset)
-{
- const unsigned char *buf = fmw->data;
- int len = strlen((char *)&buf[offset]);
-
- len++;
-
- if (offset + len + 8 > fmw->size) {
- dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
- return -EINVAL;
- }
-
- offset += len;
-
- fw_hdr->device_family = get_unaligned_be32(&buf[offset]);
- if (fw_hdr->device_family != 0) {
- dev_err(tas_priv->dev, "%s: not TAS device\n", __func__);
- return -EINVAL;
- }
- offset += 4;
-
- fw_hdr->device = get_unaligned_be32(&buf[offset]);
- if (fw_hdr->device >= TASDEVICE_DSP_TAS_MAX_DEVICE ||
- fw_hdr->device == 6) {
- dev_err(tas_priv->dev, "Unsupported dev %d\n", fw_hdr->device);
- return -EINVAL;
- }
- offset += 4;
- fw_hdr->ndev = 1;
-
- return offset;
-}
-
-/* DSP firmware file header parser function for size variabled header. */
-static int fw_parse_variable_header_git(struct tasdevice_priv
- *tas_priv, const struct firmware *fmw, int offset)
-{
- struct tasdevice_fw *tas_fmw = tas_priv->fmw;
- struct tasdevice_dspfw_hdr *fw_hdr = &tas_fmw->fw_hdr;
-
- offset = fw_parse_variable_hdr(tas_priv, fw_hdr, fmw, offset);
-
- return offset;
-}
-
-/* DSP firmware file block parser function. */
-static int fw_parse_block_data(struct tasdevice_fw *tas_fmw,
- struct tasdev_blk *block, const struct firmware *fmw, int offset)
-{
- unsigned char *data = (unsigned char *)fmw->data;
- int n;
-
- if (offset + 8 > fmw->size) {
- dev_err(tas_fmw->dev, "%s: Type error\n", __func__);
- return -EINVAL;
- }
- block->type = get_unaligned_be32(&data[offset]);
- offset += 4;
-
- if (tas_fmw->fw_hdr.fixed_hdr.drv_ver >= PPC_DRIVER_CRCCHK) {
- if (offset + 8 > fmw->size) {
- dev_err(tas_fmw->dev, "PChkSumPresent error\n");
- return -EINVAL;
- }
- block->is_pchksum_present = data[offset];
- offset++;
-
- block->pchksum = data[offset];
- offset++;
-
- block->is_ychksum_present = data[offset];
- offset++;
-
- block->ychksum = data[offset];
- offset++;
- } else {
- block->is_pchksum_present = 0;
- block->is_ychksum_present = 0;
- }
-
- block->nr_cmds = get_unaligned_be32(&data[offset]);
- offset += 4;
-
- n = block->nr_cmds * 4;
- if (offset + n > fmw->size) {
- dev_err(tas_fmw->dev,
- "%s: File Size(%lu) error offset = %d n = %d\n",
- __func__, (unsigned long)fmw->size, offset, n);
- return -EINVAL;
- }
- /* instead of kzalloc+memcpy */
- block->data = kmemdup(&data[offset], n, GFP_KERNEL);
- if (!block->data)
- return -ENOMEM;
-
- offset += n;
-
- return offset;
-}
-
-/*
- * When parsing error occurs, all the memory resource will be released
- * in the end of tasdevice_rca_ready.
- */
-static int fw_parse_data(struct tasdevice_fw *tas_fmw,
- struct tasdevice_data *img_data, const struct firmware *fmw,
- int offset)
-{
- const unsigned char *data = (unsigned char *)fmw->data;
- struct tasdev_blk *blk;
- unsigned int i, n;
-
- if (offset + 64 > fmw->size) {
- dev_err(tas_fmw->dev, "%s: Name error\n", __func__);
- return -EINVAL;
- }
- memcpy(img_data->name, &data[offset], 64);
- offset += 64;
-
- n = strlen((char *)&data[offset]);
- n++;
- if (offset + n + 2 > fmw->size) {
- dev_err(tas_fmw->dev, "%s: Description error\n", __func__);
- return -EINVAL;
- }
- offset += n;
- img_data->nr_blk = get_unaligned_be16(&data[offset]);
- offset += 2;
-
- img_data->dev_blks = kcalloc(img_data->nr_blk,
- sizeof(*img_data->dev_blks), GFP_KERNEL);
- if (!img_data->dev_blks)
- return -ENOMEM;
-
- for (i = 0; i < img_data->nr_blk; i++) {
- blk = &img_data->dev_blks[i];
- offset = fw_parse_block_data(tas_fmw, blk, fmw, offset);
- if (offset < 0)
- return -EINVAL;
- }
-
- return offset;
-}
-
-/*
- * When parsing error occurs, all the memory resource will be released
- * in the end of tasdevice_rca_ready.
- */
-static int fw_parse_program_data(struct tasdevice_priv *tas_priv,
- struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
-{
- unsigned char *buf = (unsigned char *)fmw->data;
- struct tasdevice_prog *program;
- int i;
-
- if (offset + 2 > fmw->size) {
- dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
- return -EINVAL;
- }
- tas_fmw->nr_programs = get_unaligned_be16(&buf[offset]);
- offset += 2;
-
- if (tas_fmw->nr_programs == 0) {
- /* Not error in calibration Data file, return directly */
- dev_dbg(tas_priv->dev, "%s: No Programs data, maybe calbin\n",
- __func__);
- return offset;
- }
-
- tas_fmw->programs =
- kcalloc(tas_fmw->nr_programs, sizeof(*tas_fmw->programs),
- GFP_KERNEL);
- if (!tas_fmw->programs)
- return -ENOMEM;
-
- for (i = 0; i < tas_fmw->nr_programs; i++) {
- int n = 0;
-
- program = &tas_fmw->programs[i];
- if (offset + 64 > fmw->size) {
- dev_err(tas_priv->dev, "%s: mpName error\n", __func__);
- return -EINVAL;
- }
- offset += 64;
-
- n = strlen((char *)&buf[offset]);
- /* skip '\0' and 5 unused bytes */
- n += 6;
- if (offset + n > fmw->size) {
- dev_err(tas_priv->dev, "Description err\n");
- return -EINVAL;
- }
-
- offset += n;
-
- offset = fw_parse_data(tas_fmw, &program->dev_data, fmw,
- offset);
- if (offset < 0)
- return offset;
- }
-
- return offset;
-}
-
-/*
- * When parsing error occurs, all the memory resource will be released
- * in the end of tasdevice_rca_ready.
- */
-static int fw_parse_configuration_data(struct tasdevice_priv *tas_priv,
- struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
-{
- unsigned char *data = (unsigned char *)fmw->data;
- struct tasdevice_config *config;
- unsigned int i, n;
-
- if (offset + 2 > fmw->size) {
- dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
- return -EINVAL;
- }
- tas_fmw->nr_configurations = get_unaligned_be16(&data[offset]);
- offset += 2;
-
- if (tas_fmw->nr_configurations == 0) {
- dev_err(tas_priv->dev, "%s: Conf is zero\n", __func__);
- /* Not error for calibration Data file, return directly */
- return offset;
- }
- tas_fmw->configs = kcalloc(tas_fmw->nr_configurations,
- sizeof(*tas_fmw->configs), GFP_KERNEL);
- if (!tas_fmw->configs)
- return -ENOMEM;
- for (i = 0; i < tas_fmw->nr_configurations; i++) {
- config = &tas_fmw->configs[i];
- if (offset + 64 > fmw->size) {
- dev_err(tas_priv->dev, "File Size err\n");
- return -EINVAL;
- }
- memcpy(config->name, &data[offset], 64);
- offset += 64;
-
- n = strlen((char *)&data[offset]);
- n += 15;
- if (offset + n > fmw->size) {
- dev_err(tas_priv->dev, "Description err\n");
- return -EINVAL;
- }
- offset += n;
- offset = fw_parse_data(tas_fmw, &config->dev_data,
- fmw, offset);
- if (offset < 0)
- break;
- }
-
- return offset;
-}
-
-/* yram5 page check. */
-static bool check_inpage_yram_rg(struct tas_crc *cd,
- unsigned char reg, unsigned char len)
-{
- bool in = false;
-
- if (reg <= TAS2781_YRAM5_END_REG &&
- reg >= TAS2781_YRAM5_START_REG) {
- if (reg + len > TAS2781_YRAM5_END_REG)
- cd->len = TAS2781_YRAM5_END_REG - reg + 1;
- else
- cd->len = len;
- cd->offset = reg;
- in = true;
- } else if (reg < TAS2781_YRAM5_START_REG) {
- if (reg + len > TAS2781_YRAM5_START_REG) {
- cd->offset = TAS2781_YRAM5_START_REG;
- cd->len = len - TAS2781_YRAM5_START_REG + reg;
- in = true;
- }
- }
-
- return in;
-}
-
-/* DSP firmware yram block check. */
-static bool check_inpage_yram_bk1(struct tas_crc *cd,
- unsigned char page, unsigned char reg, unsigned char len)
-{
- bool in = false;
-
- if (page == TAS2781_YRAM1_PAGE) {
- if (reg >= TAS2781_YRAM1_START_REG) {
- cd->offset = reg;
- cd->len = len;
- in = true;
- } else if (reg + len > TAS2781_YRAM1_START_REG) {
- cd->offset = TAS2781_YRAM1_START_REG;
- cd->len = len - TAS2781_YRAM1_START_REG + reg;
- in = true;
- }
- } else if (page == TAS2781_YRAM3_PAGE) {
- in = check_inpage_yram_rg(cd, reg, len);
- }
-
- return in;
-}
-
-/*
- * Return Code:
- * true -- the registers are in the inpage yram
- * false -- the registers are NOT in the inpage yram
- */
-static bool check_inpage_yram(struct tas_crc *cd, unsigned char book,
- unsigned char page, unsigned char reg, unsigned char len)
-{
- bool in = false;
-
- if (book == TAS2781_YRAM_BOOK1)
- in = check_inpage_yram_bk1(cd, page, reg, len);
- else if (book == TAS2781_YRAM_BOOK2 && page == TAS2781_YRAM5_PAGE)
- in = check_inpage_yram_rg(cd, reg, len);
-
- return in;
-}
-
-/* yram4 page check. */
-static bool check_inblock_yram_bk(struct tas_crc *cd,
- unsigned char page, unsigned char reg, unsigned char len)
-{
- bool in = false;
-
- if ((page >= TAS2781_YRAM4_START_PAGE &&
- page <= TAS2781_YRAM4_END_PAGE) ||
- (page >= TAS2781_YRAM2_START_PAGE &&
- page <= TAS2781_YRAM2_END_PAGE)) {
- if (reg <= TAS2781_YRAM2_END_REG &&
- reg >= TAS2781_YRAM2_START_REG) {
- cd->offset = reg;
- cd->len = len;
- in = true;
- } else if (reg < TAS2781_YRAM2_START_REG) {
- if (reg + len - 1 >= TAS2781_YRAM2_START_REG) {
- cd->offset = TAS2781_YRAM2_START_REG;
- cd->len = reg + len - TAS2781_YRAM2_START_REG;
- in = true;
- }
- }
- }
-
- return in;
-}
-
-/*
- * Return Code:
- * true -- the registers are in the inblock yram
- * false -- the registers are NOT in the inblock yram
- */
-static bool check_inblock_yram(struct tas_crc *cd, unsigned char book,
- unsigned char page, unsigned char reg, unsigned char len)
-{
- bool in = false;
-
- if (book == TAS2781_YRAM_BOOK1 || book == TAS2781_YRAM_BOOK2)
- in = check_inblock_yram_bk(cd, page, reg, len);
-
- return in;
-}
-
-/* yram page check. */
-static bool check_yram(struct tas_crc *cd, unsigned char book,
- unsigned char page, unsigned char reg, unsigned char len)
-{
- bool in;
-
- in = check_inpage_yram(cd, book, page, reg, len);
- if (!in)
- in = check_inblock_yram(cd, book, page, reg, len);
-
- return in;
-}
-
-/* Checksum for data block. */
-static int tasdev_multibytes_chksum(struct tasdevice_priv *tasdevice,
- unsigned char book, unsigned char page,
- unsigned char reg, unsigned int len)
-{
- struct tas_crc crc_data;
- unsigned char crc_chksum = 0;
- unsigned char nBuf1[128];
- int ret = 0, i;
- bool in;
-
- if ((reg + len - 1) > 127) {
- ret = -EINVAL;
- dev_err(tasdevice->dev, "firmware error\n");
- goto end;
- }
-
- if ((book == TASDEVICE_BOOK_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
- (page == TASDEVICE_PAGE_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
- (reg == TASDEVICE_REG_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
- (len == 4)) {
- /* DSP swap command, pass */
- ret = 0;
- goto end;
- }
-
- in = check_yram(&crc_data, book, page, reg, len);
- if (!in)
- goto end;
-
- if (len == 1) {
- dev_err(tasdevice->dev, "firmware error\n");
- ret = -EINVAL;
- goto end;
- }
-
- ret = tasdevice_spi_dev_bulk_read(tasdevice,
- TASDEVICE_REG(book, page, crc_data.offset),
- nBuf1, crc_data.len);
- if (ret < 0)
- goto end;
-
- for (i = 0; i < crc_data.len; i++) {
- if ((book == TASDEVICE_BOOK_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
- (page == TASDEVICE_PAGE_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
- ((i + crc_data.offset) >=
- TASDEVICE_REG_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
- ((i + crc_data.offset) <=
- (TASDEVICE_REG_ID(TAS2781_SA_COEFF_SWAP_REG) + 4)))
- /* DSP swap command, bypass */
- continue;
- else
- crc_chksum += crc8(tasdevice->crc8_lkp_tbl, &nBuf1[i],
- 1, 0);
- }
-
- ret = crc_chksum;
-
-end:
- return ret;
-}
-
-/* Checksum for single register. */
-static int do_singlereg_checksum(struct tasdevice_priv *tasdevice,
- unsigned char book, unsigned char page,
- unsigned char reg, unsigned char val)
-{
- struct tas_crc crc_data;
- unsigned int nData1;
- int ret = 0;
- bool in;
-
- /* DSP swap command, pass */
- if ((book == TASDEVICE_BOOK_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
- (page == TASDEVICE_PAGE_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
- (reg >= TASDEVICE_REG_ID(TAS2781_SA_COEFF_SWAP_REG)) &&
- (reg <= (TASDEVICE_REG_ID(TAS2781_SA_COEFF_SWAP_REG) + 4)))
- return 0;
-
- in = check_yram(&crc_data, book, page, reg, 1);
- if (!in)
- return 0;
- ret = tasdevice_spi_dev_read(tasdevice,
- TASDEVICE_REG(book, page, reg), &nData1);
- if (ret < 0)
- return ret;
-
- if (nData1 != val) {
- dev_err(tasdevice->dev,
- "B[0x%x]P[0x%x]R[0x%x] W[0x%x], R[0x%x]\n",
- book, page, reg, val, nData1);
- tasdevice->err_code |= ERROR_YRAM_CRCCHK;
- return -EAGAIN;
- }
-
- ret = crc8(tasdevice->crc8_lkp_tbl, &val, 1, 0);
-
- return ret;
-}
-
-/* Block type check. */
-static void set_err_prg_cfg(unsigned int type, struct tasdevice_priv *p)
-{
- if ((type == MAIN_ALL_DEVICES) || (type == MAIN_DEVICE_A) ||
- (type == MAIN_DEVICE_B) || (type == MAIN_DEVICE_C) ||
- (type == MAIN_DEVICE_D))
- p->cur_prog = -1;
- else
- p->cur_conf = -1;
-}
-
-/* Checksum for data bytes. */
-static int tasdev_bytes_chksum(struct tasdevice_priv *tas_priv,
- struct tasdev_blk *block, unsigned char book,
- unsigned char page, unsigned char reg, unsigned int len,
- unsigned char val, unsigned char *crc_chksum)
-{
- int ret;
-
- if (len > 1)
- ret = tasdev_multibytes_chksum(tas_priv, book, page, reg,
- len);
- else
- ret = do_singlereg_checksum(tas_priv, book, page, reg, val);
-
- if (ret > 0) {
- *crc_chksum += ret;
- goto end;
- }
-
- if (ret != -EAGAIN)
- goto end;
-
- block->nr_retry--;
- if (block->nr_retry > 0)
- goto end;
-
- set_err_prg_cfg(block->type, tas_priv);
-
-end:
- return ret;
-}
-
-/* Multi-data byte write. */
-static int tasdev_multibytes_wr(struct tasdevice_priv *tas_priv,
- struct tasdev_blk *block, unsigned char book,
- unsigned char page, unsigned char reg, unsigned char *data,
- unsigned int len, unsigned int *nr_cmds,
- unsigned char *crc_chksum)
-{
- int ret;
-
- if (len > 1) {
- ret = tasdevice_spi_dev_bulk_write(tas_priv,
- TASDEVICE_REG(book, page, reg), data + 3, len);
- if (ret < 0)
- return ret;
- if (block->is_ychksum_present)
- ret = tasdev_bytes_chksum(tas_priv, block,
- book, page, reg, len, 0, crc_chksum);
- } else {
- ret = tasdevice_spi_dev_write(tas_priv,
- TASDEVICE_REG(book, page, reg), data[3]);
- if (ret < 0)
- return ret;
- if (block->is_ychksum_present)
- ret = tasdev_bytes_chksum(tas_priv, block, book,
- page, reg, 1, data[3], crc_chksum);
- }
-
- if (!block->is_ychksum_present || ret >= 0) {
- *nr_cmds += 1;
- if (len >= 2)
- *nr_cmds += ((len - 2) / 4) + 1;
- }
-
- return ret;
-}
-
-/* Checksum for block. */
-static int tasdev_block_chksum(struct tasdevice_priv *tas_priv,
- struct tasdev_blk *block)
-{
- unsigned int nr_value;
- int ret;
-
- ret = tasdevice_spi_dev_read(tas_priv, TASDEVICE_CHECKSUM, &nr_value);
- if (ret < 0) {
- dev_err(tas_priv->dev, "%s: read error %d.\n", __func__, ret);
- set_err_prg_cfg(block->type, tas_priv);
- return ret;
- }
-
- if ((nr_value & 0xff) != block->pchksum) {
- dev_err(tas_priv->dev, "%s: PChkSum err %d ", __func__, ret);
- dev_err(tas_priv->dev, "PChkSum = 0x%x, Reg = 0x%x\n",
- block->pchksum, (nr_value & 0xff));
- tas_priv->err_code |= ERROR_PRAM_CRCCHK;
- ret = -EAGAIN;
- block->nr_retry--;
-
- if (block->nr_retry <= 0)
- set_err_prg_cfg(block->type, tas_priv);
- } else {
- tas_priv->err_code &= ~ERROR_PRAM_CRCCHK;
- }
-
- return ret;
-}
-
-/* Firmware block load function. */
-static int tasdev_load_blk(struct tasdevice_priv *tas_priv,
- struct tasdev_blk *block)
-{
- unsigned int sleep_time, len, nr_cmds;
- unsigned char offset, book, page, val;
- unsigned char *data = block->data;
- unsigned char crc_chksum = 0;
- int ret = 0;
-
- while (block->nr_retry > 0) {
- if (block->is_pchksum_present) {
- ret = tasdevice_spi_dev_write(tas_priv,
- TASDEVICE_CHECKSUM, 0);
- if (ret < 0)
- break;
- }
-
- if (block->is_ychksum_present)
- crc_chksum = 0;
-
- nr_cmds = 0;
-
- while (nr_cmds < block->nr_cmds) {
- data = block->data + nr_cmds * 4;
-
- book = data[0];
- page = data[1];
- offset = data[2];
- val = data[3];
-
- nr_cmds++;
- /* Single byte write */
- if (offset <= 0x7F) {
- ret = tasdevice_spi_dev_write(tas_priv,
- TASDEVICE_REG(book, page, offset),
- val);
- if (ret < 0)
- break;
- if (block->is_ychksum_present) {
- ret = tasdev_bytes_chksum(tas_priv,
- block, book, page, offset,
- 1, val, &crc_chksum);
- if (ret < 0)
- break;
- }
- continue;
- }
- /* sleep command */
- if (offset == 0x81) {
- /* book -- data[0] page -- data[1] */
- sleep_time = ((book << 8) + page)*1000;
- fsleep(sleep_time);
- continue;
- }
- /* Multiple bytes write */
- if (offset == 0x85) {
- data += 4;
- len = (book << 8) + page;
- book = data[0];
- page = data[1];
- offset = data[2];
- ret = tasdev_multibytes_wr(tas_priv,
- block, book, page, offset, data,
- len, &nr_cmds, &crc_chksum);
- if (ret < 0)
- break;
- }
- }
- if (ret == -EAGAIN) {
- if (block->nr_retry > 0)
- continue;
- } else if (ret < 0) {
- /* err in current device, skip it */
- break;
- }
-
- if (block->is_pchksum_present) {
- ret = tasdev_block_chksum(tas_priv, block);
- if (ret == -EAGAIN) {
- if (block->nr_retry > 0)
- continue;
- } else if (ret < 0) {
- /* err in current device, skip it */
- break;
- }
- }
-
- if (block->is_ychksum_present) {
- /* TBD, open it when FW ready */
- dev_err(tas_priv->dev,
- "Blk YChkSum: FW = 0x%x, YCRC = 0x%x\n",
- block->ychksum, crc_chksum);
-
- tas_priv->err_code &=
- ~ERROR_YRAM_CRCCHK;
- ret = 0;
- }
- /* skip current blk */
- break;
- }
-
- return ret;
-}
-
-/* Firmware block load function. */
-static int tasdevice_load_block(struct tasdevice_priv *tas_priv,
- struct tasdev_blk *block)
-{
- int ret = 0;
-
- block->nr_retry = 6;
- if (tas_priv->is_loading == false)
- return 0;
- ret = tasdev_load_blk(tas_priv, block);
- if (ret < 0)
- dev_err(tas_priv->dev, "Blk (%d) load error\n", block->type);
-
- return ret;
-}
-
-/*
- * Select firmware binary parser & load callback functions by ppc3 version
- * and firmware binary version.
- */
-static int dspfw_default_callback(struct tasdevice_priv *tas_priv,
- unsigned int drv_ver, unsigned int ppcver)
-{
- int rc = 0;
-
- if (drv_ver == 0x100) {
- if (ppcver >= PPC3_VERSION_BASE) {
- tas_priv->fw_parse_variable_header =
- fw_parse_variable_header_kernel;
- tas_priv->fw_parse_program_data =
- fw_parse_program_data_kernel;
- tas_priv->fw_parse_configuration_data =
- fw_parse_configuration_data_kernel;
- tas_priv->tasdevice_load_block =
- tasdevice_load_block_kernel;
- } else if (ppcver == 0x00) {
- tas_priv->fw_parse_variable_header =
- fw_parse_variable_header_git;
- tas_priv->fw_parse_program_data =
- fw_parse_program_data;
- tas_priv->fw_parse_configuration_data =
- fw_parse_configuration_data;
- tas_priv->tasdevice_load_block =
- tasdevice_load_block;
- } else {
- dev_err(tas_priv->dev,
- "Wrong PPCVer :0x%08x\n", ppcver);
- rc = -EINVAL;
- }
- } else {
- dev_err(tas_priv->dev, "Wrong DrvVer : 0x%02x\n", drv_ver);
- rc = -EINVAL;
- }
-
- return rc;
-}
-
-/* DSP firmware binary file header parser function. */
-static int fw_parse_header(struct tasdevice_priv *tas_priv,
- struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset)
-{
- struct tasdevice_dspfw_hdr *fw_hdr = &tas_fmw->fw_hdr;
- struct tasdevice_fw_fixed_hdr *fw_fixed_hdr = &fw_hdr->fixed_hdr;
- static const unsigned char magic_number[] = {0x35, 0x35, 0x35, 0x32, };
- const unsigned char *buf = (unsigned char *)fmw->data;
-
- if (offset + 92 > fmw->size) {
- dev_err(tas_priv->dev, "%s: File Size error\n", __func__);
- offset = -EINVAL;
- goto out;
- }
- if (memcmp(&buf[offset], magic_number, 4)) {
- dev_err(tas_priv->dev, "%s: Magic num NOT match\n", __func__);
- offset = -EINVAL;
- goto out;
- }
- offset += 4;
-
- /*
- * Convert data[offset], data[offset + 1], data[offset + 2] and
- * data[offset + 3] into host
- */
- fw_fixed_hdr->fwsize = get_unaligned_be32(&buf[offset]);
- offset += 4;
- if (fw_fixed_hdr->fwsize != fmw->size) {
- dev_err(tas_priv->dev, "File size not match, %lu %u",
- (unsigned long)fmw->size, fw_fixed_hdr->fwsize);
- offset = -EINVAL;
- goto out;
- }
- offset += 4;
- fw_fixed_hdr->ppcver = get_unaligned_be32(&buf[offset]);
- offset += 8;
- fw_fixed_hdr->drv_ver = get_unaligned_be32(&buf[offset]);
- offset += 72;
-
-out:
- return offset;
-}
-
-/* DSP firmware binary file parser function. */
-static int tasdevice_dspfw_ready(const struct firmware *fmw, void *context)
-{
- struct tasdevice_priv *tas_priv = context;
- struct tasdevice_fw_fixed_hdr *fw_fixed_hdr;
- struct tasdevice_fw *tas_fmw;
- int offset = 0, ret = 0;
-
- if (!fmw || !fmw->data) {
- dev_err(tas_priv->dev, "%s: Failed to read firmware %s\n",
- __func__, tas_priv->coef_binaryname);
- return -EINVAL;
- }
-
- tas_priv->fmw = kzalloc(sizeof(*tas_priv->fmw), GFP_KERNEL);
- if (!tas_priv->fmw)
- return -ENOMEM;
- tas_fmw = tas_priv->fmw;
- tas_fmw->dev = tas_priv->dev;
- offset = fw_parse_header(tas_priv, tas_fmw, fmw, offset);
-
- if (offset == -EINVAL)
- return -EINVAL;
-
- fw_fixed_hdr = &tas_fmw->fw_hdr.fixed_hdr;
- /* Support different versions of firmware */
- switch (fw_fixed_hdr->drv_ver) {
- case 0x301:
- case 0x302:
- case 0x502:
- case 0x503:
- tas_priv->fw_parse_variable_header =
- fw_parse_variable_header_kernel;
- tas_priv->fw_parse_program_data =
- fw_parse_program_data_kernel;
- tas_priv->fw_parse_configuration_data =
- fw_parse_configuration_data_kernel;
- tas_priv->tasdevice_load_block =
- tasdevice_load_block_kernel;
- break;
- case 0x202:
- case 0x400:
- tas_priv->fw_parse_variable_header =
- fw_parse_variable_header_git;
- tas_priv->fw_parse_program_data =
- fw_parse_program_data;
- tas_priv->fw_parse_configuration_data =
- fw_parse_configuration_data;
- tas_priv->tasdevice_load_block =
- tasdevice_load_block;
- break;
- default:
- ret = dspfw_default_callback(tas_priv,
- fw_fixed_hdr->drv_ver, fw_fixed_hdr->ppcver);
- if (ret)
- return ret;
- break;
- }
-
- offset = tas_priv->fw_parse_variable_header(tas_priv, fmw, offset);
- if (offset < 0)
- return offset;
-
- offset = tas_priv->fw_parse_program_data(tas_priv, tas_fmw, fmw,
- offset);
- if (offset < 0)
- return offset;
-
- offset = tas_priv->fw_parse_configuration_data(tas_priv,
- tas_fmw, fmw, offset);
- if (offset < 0)
- ret = offset;
-
- return ret;
-}
-
-/* DSP firmware binary file parser function. */
-int tasdevice_spi_dsp_parser(void *context)
-{
- struct tasdevice_priv *tas_priv = context;
- const struct firmware *fw_entry;
- int ret;
-
- ret = request_firmware(&fw_entry, tas_priv->coef_binaryname,
- tas_priv->dev);
- if (ret) {
- dev_err(tas_priv->dev, "%s: load %s error\n", __func__,
- tas_priv->coef_binaryname);
- return ret;
- }
-
- ret = tasdevice_dspfw_ready(fw_entry, tas_priv);
- release_firmware(fw_entry);
- fw_entry = NULL;
-
- return ret;
-}
-
-/* DSP firmware program block data remove function. */
-static void tasdev_dsp_prog_blk_remove(struct tasdevice_prog *prog)
-{
- struct tasdevice_data *tas_dt;
- struct tasdev_blk *blk;
- unsigned int i;
-
- if (!prog)
- return;
-
- tas_dt = &prog->dev_data;
-
- if (!tas_dt->dev_blks)
- return;
-
- for (i = 0; i < tas_dt->nr_blk; i++) {
- blk = &tas_dt->dev_blks[i];
- kfree(blk->data);
- }
- kfree(tas_dt->dev_blks);
-}
-
-/* DSP firmware program block data remove function. */
-static void tasdev_dsp_prog_remove(struct tasdevice_prog *prog,
- unsigned short nr)
-{
- int i;
-
- for (i = 0; i < nr; i++)
- tasdev_dsp_prog_blk_remove(&prog[i]);
- kfree(prog);
-}
-
-/* DSP firmware config block data remove function. */
-static void tasdev_dsp_cfg_blk_remove(struct tasdevice_config *cfg)
-{
- struct tasdevice_data *tas_dt;
- struct tasdev_blk *blk;
- unsigned int i;
-
- if (cfg) {
- tas_dt = &cfg->dev_data;
-
- if (!tas_dt->dev_blks)
- return;
-
- for (i = 0; i < tas_dt->nr_blk; i++) {
- blk = &tas_dt->dev_blks[i];
- kfree(blk->data);
- }
- kfree(tas_dt->dev_blks);
- }
-}
-
-/* DSP firmware config remove function. */
-static void tasdev_dsp_cfg_remove(struct tasdevice_config *config,
- unsigned short nr)
-{
- int i;
-
- for (i = 0; i < nr; i++)
- tasdev_dsp_cfg_blk_remove(&config[i]);
- kfree(config);
-}
-
-/* DSP firmware remove function. */
-void tasdevice_spi_dsp_remove(void *context)
-{
- struct tasdevice_priv *tas_dev = context;
-
- if (!tas_dev->fmw)
- return;
-
- if (tas_dev->fmw->programs)
- tasdev_dsp_prog_remove(tas_dev->fmw->programs,
- tas_dev->fmw->nr_programs);
- if (tas_dev->fmw->configs)
- tasdev_dsp_cfg_remove(tas_dev->fmw->configs,
- tas_dev->fmw->nr_configurations);
- kfree(tas_dev->fmw);
- tas_dev->fmw = NULL;
-}
-
-/* DSP firmware calibration data remove function. */
-static void tas2781_clear_calfirmware(struct tasdevice_fw *tas_fmw)
-{
- struct tasdevice_calibration *calibration;
- struct tasdev_blk *block;
- unsigned int blks;
- int i;
-
- if (!tas_fmw->calibrations)
- goto out;
-
- for (i = 0; i < tas_fmw->nr_calibrations; i++) {
- calibration = &tas_fmw->calibrations[i];
- if (!calibration)
- continue;
-
- if (!calibration->dev_data.dev_blks)
- continue;
-
- for (blks = 0; blks < calibration->dev_data.nr_blk; blks++) {
- block = &calibration->dev_data.dev_blks[blks];
- if (!block)
- continue;
- kfree(block->data);
- }
- kfree(calibration->dev_data.dev_blks);
- }
- kfree(tas_fmw->calibrations);
-out:
- kfree(tas_fmw);
-}
-
-/* Calibration data from firmware remove function. */
-void tasdevice_spi_calbin_remove(void *context)
-{
- struct tasdevice_priv *tas_priv = context;
-
- if (tas_priv->cali_data_fmw) {
- tas2781_clear_calfirmware(tas_priv->cali_data_fmw);
- tas_priv->cali_data_fmw = NULL;
- }
-}
-
-/* Configuration remove function. */
-void tasdevice_spi_config_info_remove(void *context)
-{
- struct tasdevice_priv *tas_priv = context;
- struct tasdevice_rca *rca = &tas_priv->rcabin;
- struct tasdevice_config_info **ci = rca->cfg_info;
- unsigned int i, j;
-
- if (!ci)
- return;
- for (i = 0; i < rca->ncfgs; i++) {
- if (!ci[i])
- continue;
- if (ci[i]->blk_data) {
- for (j = 0; j < ci[i]->real_nblocks; j++) {
- if (!ci[i]->blk_data[j])
- continue;
- kfree(ci[i]->blk_data[j]->regdata);
- kfree(ci[i]->blk_data[j]);
- }
- kfree(ci[i]->blk_data);
- }
- kfree(ci[i]);
- }
- kfree(ci);
-}
-
-/* DSP firmware program block data load function. */
-static int tasdevice_load_data(struct tasdevice_priv *tas_priv,
- struct tasdevice_data *dev_data)
-{
- struct tasdev_blk *block;
- unsigned int i;
- int ret = 0;
-
- for (i = 0; i < dev_data->nr_blk; i++) {
- block = &dev_data->dev_blks[i];
- ret = tas_priv->tasdevice_load_block(tas_priv, block);
- if (ret < 0)
- break;
- }
-
- return ret;
-}
-
-/* DSP firmware program load interface function. */
-int tasdevice_spi_prmg_load(void *context, int prm_no)
-{
- struct tasdevice_priv *tas_priv = context;
- struct tasdevice_fw *tas_fmw = tas_priv->fmw;
- struct tasdevice_prog *program;
- struct tasdevice_config *conf;
- int ret = 0;
-
- if (!tas_fmw) {
- dev_err(tas_priv->dev, "%s: Firmware is NULL\n", __func__);
- return -EINVAL;
- }
- if (prm_no >= 0 && prm_no <= tas_fmw->nr_programs) {
- tas_priv->cur_conf = 0;
- tas_priv->is_loading = true;
- program = &tas_fmw->programs[prm_no];
- ret = tasdevice_load_data(tas_priv, &program->dev_data);
- if (ret < 0) {
- dev_err(tas_priv->dev, "Program failed %d.\n", ret);
- return ret;
- }
- tas_priv->cur_prog = prm_no;
-
- conf = &tas_fmw->configs[tas_priv->cur_conf];
- ret = tasdevice_load_data(tas_priv, &conf->dev_data);
- if (ret < 0)
- dev_err(tas_priv->dev, "Config failed %d.\n", ret);
- } else {
- dev_err(tas_priv->dev,
- "%s: prm(%d) is not in range of Programs %u\n",
- __func__, prm_no, tas_fmw->nr_programs);
- return -EINVAL;
- }
-
- return ret;
-}
-
-/* RCABIN configuration switch interface function. */
-void tasdevice_spi_tuning_switch(void *context, int state)
-{
- struct tasdevice_priv *tas_priv = context;
- int profile_cfg_id = tas_priv->rcabin.profile_cfg_id;
-
- if (tas_priv->fw_state == TASDEVICE_DSP_FW_FAIL) {
- dev_err(tas_priv->dev, "DSP bin file not loaded\n");
- return;
- }
-
- if (state == 0)
- tasdevice_spi_select_cfg_blk(tas_priv, profile_cfg_id,
- TASDEVICE_BIN_BLK_PRE_POWER_UP);
- else
- tasdevice_spi_select_cfg_blk(tas_priv, profile_cfg_id,
- TASDEVICE_BIN_BLK_PRE_SHUTDOWN);
-}
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 3b0c3e70987b..a8ac14887676 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -2502,7 +2502,7 @@ static int snd_ice1712_create(struct snd_card *card,
pci_write_config_word(ice->pci, 0x42, 0x0006);
snd_ice1712_proc_init(ice);
- err = pci_request_regions(pci, "ICE1712");
+ err = pcim_request_all_regions(pci, "ICE1712");
if (err < 0)
return err;
ice->port = pci_resource_start(pci, 0);
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 1dc776acd637..be22b159e65a 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -2491,7 +2491,7 @@ static int snd_vt1724_create(struct snd_card *card,
pci_set_master(pci);
snd_vt1724_proc_init(ice);
- err = pci_request_regions(pci, "ICE1724");
+ err = pcim_request_all_regions(pci, "ICE1724");
if (err < 0)
return err;
ice->port = pci_resource_start(pci, 0);
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index e4bb99f71c2c..51e7f1f1a48e 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -2926,7 +2926,7 @@ static int snd_intel8x0_init(struct snd_card *card,
pci->device == PCI_DEVICE_ID_INTEL_440MX)
chip->fix_nocache = 1; /* enable workaround */
- err = pci_request_regions(pci, card->shortname);
+ err = pcim_request_all_regions(pci, card->shortname);
if (err < 0)
return err;
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 38f8de51d641..1ce775fe8a70 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -1060,7 +1060,7 @@ static int snd_intel8x0m_init(struct snd_card *card,
chip->pci = pci;
chip->irq = -1;
- err = pci_request_regions(pci, card->shortname);
+ err = pcim_request_all_regions(pci, card->shortname);
if (err < 0)
return err;
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 49b71082c485..56dea5b10828 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -308,9 +308,6 @@ struct snd_korg1212 {
spinlock_t lock;
struct mutex open_mutex;
- struct timer_list timer; /* timer callback for checking ack of stop request */
- int stop_pending_cnt; /* counter for stop pending check */
-
wait_queue_head_t wait;
unsigned long iomem;
@@ -382,7 +379,7 @@ struct snd_korg1212 {
unsigned long totalerrorcnt; // Total Error Count
int dsp_is_loaded;
- int dsp_stop_is_processed;
+ int dsp_stop_processing;
};
@@ -565,52 +562,17 @@ static int snd_korg1212_Send1212Command(struct snd_korg1212 *korg1212,
/* spinlock already held */
static void snd_korg1212_SendStop(struct snd_korg1212 *korg1212)
{
- if (! korg1212->stop_pending_cnt) {
- korg1212->sharedBufferPtr->cardCommand = 0xffffffff;
- /* program the timer */
- korg1212->stop_pending_cnt = HZ;
- mod_timer(&korg1212->timer, jiffies + 1);
- }
+ korg1212->dsp_stop_processing = 1;
+ korg1212->sharedBufferPtr->cardCommand = 0xffffffff;
}
static void snd_korg1212_SendStopAndWait(struct snd_korg1212 *korg1212)
{
unsigned long flags;
spin_lock_irqsave(&korg1212->lock, flags);
- korg1212->dsp_stop_is_processed = 0;
snd_korg1212_SendStop(korg1212);
spin_unlock_irqrestore(&korg1212->lock, flags);
- wait_event_timeout(korg1212->wait, korg1212->dsp_stop_is_processed, (HZ * 3) / 2);
-}
-
-/* timer callback for checking the ack of stop request */
-static void snd_korg1212_timer_func(struct timer_list *t)
-{
- struct snd_korg1212 *korg1212 = from_timer(korg1212, t, timer);
- unsigned long flags;
-
- spin_lock_irqsave(&korg1212->lock, flags);
- if (korg1212->sharedBufferPtr->cardCommand == 0) {
- /* ack'ed */
- korg1212->stop_pending_cnt = 0;
- korg1212->dsp_stop_is_processed = 1;
- wake_up(&korg1212->wait);
- K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: Stop ack'ed [%s]\n",
- stateName[korg1212->cardState]);
- } else {
- if (--korg1212->stop_pending_cnt > 0) {
- /* reprogram timer */
- mod_timer(&korg1212->timer, jiffies + 1);
- } else {
- dev_dbg(korg1212->card->dev, "korg1212_timer_func timeout\n");
- korg1212->sharedBufferPtr->cardCommand = 0;
- korg1212->dsp_stop_is_processed = 1;
- wake_up(&korg1212->wait);
- K1212_DEBUG_PRINTK("K1212_DEBUG: Stop timeout [%s]\n",
- stateName[korg1212->cardState]);
- }
- }
- spin_unlock_irqrestore(&korg1212->lock, flags);
+ wait_event_timeout(korg1212->wait, !korg1212->dsp_stop_processing, HZ);
}
static int snd_korg1212_TurnOnIdleMonitor(struct snd_korg1212 *korg1212)
@@ -1135,7 +1097,9 @@ static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id)
korg1212->errorcnt++;
korg1212->totalerrorcnt++;
korg1212->sharedBufferPtr->cardCommand = 0;
+ korg1212->dsp_stop_processing = 0;
snd_korg1212_setCardState(korg1212, K1212_STATE_ERRORSTOP);
+ wake_up(&korg1212->wait);
break;
// ------------------------------------------------------------------------
@@ -1147,6 +1111,8 @@ static irqreturn_t snd_korg1212_interrupt(int irq, void *dev_id)
korg1212->irqcount, doorbellValue,
stateName[korg1212->cardState]);
korg1212->sharedBufferPtr->cardCommand = 0;
+ korg1212->dsp_stop_processing = 0;
+ wake_up(&korg1212->wait);
break;
default:
@@ -1535,6 +1501,14 @@ static int snd_korg1212_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+static int snd_korg1212_sync_stop(struct snd_pcm_substream *substream)
+{
+ struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
+
+ wait_event_timeout(korg1212->wait, !korg1212->dsp_stop_processing, HZ);
+ return 0;
+}
+
static int snd_korg1212_prepare(struct snd_pcm_substream *substream)
{
struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
@@ -1544,19 +1518,7 @@ static int snd_korg1212_prepare(struct snd_pcm_substream *substream)
stateName[korg1212->cardState]);
spin_lock_irq(&korg1212->lock);
-
- /* FIXME: we should wait for ack! */
- if (korg1212->stop_pending_cnt > 0) {
- K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_prepare - Stop is pending... [%s]\n",
- stateName[korg1212->cardState]);
- spin_unlock_irq(&korg1212->lock);
- return -EAGAIN;
- /*
- korg1212->sharedBufferPtr->cardCommand = 0;
- del_timer(&korg1212->timer);
- korg1212->stop_pending_cnt = 0;
- */
- }
+ korg1212->dsp_stop_processing = 0;
rc = snd_korg1212_SetupForPlay(korg1212);
@@ -1668,6 +1630,7 @@ static const struct snd_pcm_ops snd_korg1212_playback_ops = {
.hw_params = snd_korg1212_hw_params,
.prepare = snd_korg1212_prepare,
.trigger = snd_korg1212_trigger,
+ .sync_stop = snd_korg1212_sync_stop,
.pointer = snd_korg1212_playback_pointer,
.copy = snd_korg1212_playback_copy,
.fill_silence = snd_korg1212_playback_silence,
@@ -1680,6 +1643,7 @@ static const struct snd_pcm_ops snd_korg1212_capture_ops = {
.hw_params = snd_korg1212_hw_params,
.prepare = snd_korg1212_prepare,
.trigger = snd_korg1212_trigger,
+ .sync_stop = snd_korg1212_sync_stop,
.pointer = snd_korg1212_capture_pointer,
.copy = snd_korg1212_capture_copy,
};
@@ -2086,7 +2050,6 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci)
init_waitqueue_head(&korg1212->wait);
spin_lock_init(&korg1212->lock);
mutex_init(&korg1212->open_mutex);
- timer_setup(&korg1212->timer, snd_korg1212_timer_func, 0);
korg1212->irq = -1;
korg1212->clkSource = K1212_CLKIDX_Local;
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
index 1aa30e90b86a..fb8bd54e4c2d 100644
--- a/sound/pci/lola/lola.c
+++ b/sound/pci/lola/lola.c
@@ -541,6 +541,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci, int dev)
struct lola *chip = card->private_data;
int err;
unsigned int dever;
+ void __iomem *iomem;
err = pcim_enable_device(pci);
if (err < 0)
@@ -580,14 +581,19 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci, int dev)
chip->sample_rate_min = 16000;
}
- err = pcim_iomap_regions(pci, (1 << 0) | (1 << 2), DRVNAME);
- if (err < 0)
- return err;
+ iomem = pcim_iomap_region(pci, 0, DRVNAME);
+ if (IS_ERR(iomem))
+ return PTR_ERR(iomem);
+ chip->bar[0].remap_addr = iomem;
chip->bar[0].addr = pci_resource_start(pci, 0);
- chip->bar[0].remap_addr = pcim_iomap_table(pci)[0];
+
+ iomem = pcim_iomap_region(pci, 2, DRVNAME);
+ if (IS_ERR(iomem))
+ return PTR_ERR(iomem);
+
+ chip->bar[1].remap_addr = iomem;
chip->bar[1].addr = pci_resource_start(pci, 2);
- chip->bar[1].remap_addr = pcim_iomap_table(pci)[2];
pci_set_master(pci);
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
index bd9b6148dd6f..63ebf9803ea8 100644
--- a/sound/pci/lx6464es/lx6464es.c
+++ b/sound/pci/lx6464es/lx6464es.c
@@ -944,7 +944,7 @@ static int snd_lx6464es_create(struct snd_card *card,
mutex_init(&chip->setup_mutex);
/* request resources */
- err = pci_request_regions(pci, card_name);
+ err = pcim_request_all_regions(pci, card_name);
if (err < 0)
return err;
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index f4d211970d7e..e61e15774706 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -2552,7 +2552,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
if (err < 0)
return err;
- err = pci_request_regions(pci, card->driver);
+ err = pcim_request_all_regions(pci, card->driver);
if (err < 0)
return err;
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 44085237fb44..cd4dc43dbff1 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -1447,7 +1447,7 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci)
chip->buffer_addr = pci_resource_start(pci, 0);
chip->cport_addr = pci_resource_start(pci, 1);
- err = pci_request_regions(pci, card->driver);
+ err = pcim_request_all_regions(pci, card->driver);
if (err < 0)
return err;
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index 9340d3c9ffd6..39b8ccf37cdd 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -609,7 +609,7 @@ static int __oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
if (err < 0)
return err;
- err = pci_request_regions(pci, DRIVER);
+ err = pcim_request_all_regions(pci, DRIVER);
if (err < 0) {
dev_err(card->dev, "cannot reserve PCI resources\n");
return err;
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index 329816f37b76..578be0755b8a 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -1831,7 +1831,7 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci)
chip->cif = NULL;
card->private_free = snd_riptide_free;
- err = pci_request_regions(pci, "RIPTIDE");
+ err = pcim_request_all_regions(pci, "RIPTIDE");
if (err < 0)
return err;
hwport = (struct riptideport *)chip->port;
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index a8c2ceaadef5..4bf122abea48 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -1284,7 +1284,7 @@ static int snd_rme32_create(struct rme32 *rme32)
if (err < 0)
return err;
- err = pci_request_regions(pci, "RME32");
+ err = pcim_request_all_regions(pci, "RME32");
if (err < 0)
return err;
rme32->port = pci_resource_start(rme32->pci, 0);
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 1265a7efac60..01029843d7f3 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -1575,7 +1575,7 @@ snd_rme96_create(struct rme96 *rme96)
if (err < 0)
return err;
- err = pci_request_regions(pci, "RME96");
+ err = pcim_request_all_regions(pci, "RME96");
if (err < 0)
return err;
rme96->port = pci_resource_start(rme96->pci, 0);
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index dc326face54a..873b7eadfc50 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -5277,7 +5277,7 @@ static int snd_hdsp_create(struct snd_card *card,
pci_set_master(hdsp->pci);
- err = pci_request_regions(pci, "hdsp");
+ err = pcim_request_all_regions(pci, "hdsp");
if (err < 0)
return err;
hdsp->port = pci_resource_start(pci, 0);
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 1935de046f00..64de54089955 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -6558,13 +6558,12 @@ static int snd_hdspm_create(struct snd_card *card,
pci_set_master(hdspm->pci);
- err = pcim_iomap_regions(pci, 1 << 0, "hdspm");
- if (err < 0)
- return err;
+ hdspm->iobase = pcim_iomap_region(pci, 0, "hdspm");
+ if (IS_ERR(hdspm->iobase))
+ return PTR_ERR(hdspm->iobase);
hdspm->port = pci_resource_start(pci, 0);
io_extent = pci_resource_len(pci, 0);
- hdspm->iobase = pcim_iomap_table(pci)[0];
dev_dbg(card->dev, "remapped region (0x%lx) 0x%lx-0x%lx\n",
(unsigned long)hdspm->iobase, hdspm->port,
hdspm->port + io_extent - 1);
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 5b8dd7b0a02c..34d9c7995ddd 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -2406,7 +2406,7 @@ static int snd_rme9652_create(struct snd_card *card,
spin_lock_init(&rme9652->lock);
- err = pci_request_regions(pci, "rme9652");
+ err = pcim_request_all_regions(pci, "rme9652");
if (err < 0)
return err;
rme9652->port = pci_resource_start(pci, 0);
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index 53206beb2cb5..42b22f123fa7 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -1273,7 +1273,7 @@ static int sis_chip_create(struct snd_card *card,
sis->irq = -1;
sis->ioport = pci_resource_start(pci, 0);
- rc = pci_request_regions(pci, "SiS7019");
+ rc = pcim_request_all_regions(pci, "SiS7019");
if (rc) {
dev_err(&pci->dev, "unable request regions\n");
return rc;
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index c30eaf1038e7..808a793ff4da 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -1227,7 +1227,7 @@ static int snd_sonicvibes_create(struct snd_card *card,
sonic->pci = pci;
sonic->irq = -1;
- err = pci_request_regions(pci, "S3 SonicVibes");
+ err = pcim_request_all_regions(pci, "S3 SonicVibes");
if (err < 0)
return err;
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 8039f445bee2..4e16b79d6584 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -3533,7 +3533,7 @@ int snd_trident_create(struct snd_card *card,
trident->midi_port = TRID_REG(trident, T4D_MPU401_BASE);
pci_set_master(pci);
- err = pci_request_regions(pci, "Trident Audio");
+ err = pcim_request_all_regions(pci, "Trident Audio");
if (err < 0)
return err;
trident->port = pci_resource_start(pci, 0);
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 89838b4fb118..a04dbc0a420f 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -2326,7 +2326,7 @@ static int snd_via82xx_create(struct snd_card *card,
pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE,
chip->old_legacy & ~(VIA_FUNC_ENABLE_SB|VIA_FUNC_ENABLE_FM));
- err = pci_request_regions(pci, card->driver);
+ err = pcim_request_all_regions(pci, card->driver);
if (err < 0)
return err;
chip->port = pci_resource_start(pci, 0);
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index a0a49b8d1511..eef0f9ddaae0 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -1071,7 +1071,7 @@ static int snd_via82xx_create(struct snd_card *card,
chip->pci = pci;
chip->irq = -1;
- err = pci_request_regions(pci, card->driver);
+ err = pcim_request_all_regions(pci, card->driver);
if (err < 0)
return err;
chip->port = pci_resource_start(pci, 0);
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index fdb039896205..693a4e471cf7 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -123,7 +123,7 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
vx = to_vx222(chip);
vx->pci = pci;
- err = pci_request_regions(pci, CARD_NAME);
+ err = pcim_request_all_regions(pci, KBUILD_MODNAME);
if (err < 0)
return err;
for (i = 0; i < 2; i++)
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 6b8d8690b6b2..d495f53a8324 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -2307,7 +2307,7 @@ int snd_ymfpci_create(struct snd_card *card,
chip->device_id = pci->device;
chip->rev = pci->revision;
- err = pci_request_regions(pci, "YMFPCI");
+ err = pcim_request_all_regions(pci, "YMFPCI");
if (err < 0)
return err;
diff --git a/sound/sh/aica.c b/sound/sh/aica.c
index 5a93f4587356..f88331a48638 100644
--- a/sound/sh/aica.c
+++ b/sound/sh/aica.c
@@ -469,8 +469,8 @@ static int aica_pcmvolume_info(struct snd_kcontrol *kcontrol,
static int aica_pcmvolume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_card_aica *dreamcastcard;
- dreamcastcard = kcontrol->private_data;
+ struct snd_card_aica *dreamcastcard = snd_kcontrol_chip(kcontrol);
+
if (unlikely(!dreamcastcard->channel))
return -ETXTBSY; /* we've not yet been set up */
ucontrol->value.integer.value[0] = dreamcastcard->channel->vol;
@@ -480,9 +480,9 @@ static int aica_pcmvolume_get(struct snd_kcontrol *kcontrol,
static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_card_aica *dreamcastcard;
+ struct snd_card_aica *dreamcastcard = snd_kcontrol_chip(kcontrol);
unsigned int vol;
- dreamcastcard = kcontrol->private_data;
+
if (unlikely(!dreamcastcard->channel))
return -ETXTBSY;
vol = ucontrol->value.integer.value[0];
diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c
index b4f4696809dd..5dd24ab90d0f 100644
--- a/sound/soc/apple/mca.c
+++ b/sound/soc/apple/mca.c
@@ -464,6 +464,28 @@ err:
return -EINVAL;
}
+static int mca_fe_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mca_cluster *cl = mca_dai_to_cluster(dai);
+ unsigned int mask, nchannels;
+
+ if (cl->tdm_slots) {
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ mask = cl->tdm_tx_mask;
+ else
+ mask = cl->tdm_rx_mask;
+
+ nchannels = hweight32(mask);
+ } else {
+ nchannels = 2;
+ }
+
+ return snd_pcm_hw_constraint_minmax(substream->runtime,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ 1, nchannels);
+}
+
static int mca_fe_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
unsigned int rx_mask, int slots, int slot_width)
{
@@ -680,6 +702,7 @@ static int mca_fe_hw_params(struct snd_pcm_substream *substream,
}
static const struct snd_soc_dai_ops mca_fe_ops = {
+ .startup = mca_fe_startup,
.set_fmt = mca_fe_set_fmt,
.set_bclk_ratio = mca_set_bclk_ratio,
.set_tdm_slot = mca_fe_set_tdm_slot,
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 477d33234fdd..126f897312d4 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -264,6 +264,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_TAS2770
imply SND_SOC_TAS2780
imply SND_SOC_TAS2781_COMLIB
+ imply SND_SOC_TAS2781_COMLIB_I2C
imply SND_SOC_TAS2781_FMWLIB
imply SND_SOC_TAS2781_I2C
imply SND_SOC_TAS5086
@@ -2025,20 +2026,24 @@ config SND_SOC_TAS2780
digital input mono Class-D audio power amplifiers.
config SND_SOC_TAS2781_COMLIB
+ tristate
+
+config SND_SOC_TAS2781_COMLIB_I2C
depends on I2C
select CRC8
select REGMAP_I2C
tristate
config SND_SOC_TAS2781_FMWLIB
- depends on SND_SOC_TAS2781_COMLIB
+ select SND_SOC_TAS2781_COMLIB
+ select CRC8
tristate
default n
config SND_SOC_TAS2781_I2C
tristate "Texas Instruments TAS2781 speaker amplifier based on I2C"
depends on I2C
- select SND_SOC_TAS2781_COMLIB
+ select SND_SOC_TAS2781_COMLIB_I2C
select SND_SOC_TAS2781_FMWLIB
help
Enable support for Texas Instruments TAS2781 Smart Amplifier
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 66e2f2381d40..6d7aa109ede7 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -310,6 +310,7 @@ snd-soc-tas6424-y := tas6424.o
snd-soc-tda7419-y := tda7419.o
snd-soc-tas2770-y := tas2770.o
snd-soc-tas2781-comlib-y := tas2781-comlib.o
+snd-soc-tas2781-comlib-i2c-y := tas2781-comlib-i2c.o
snd-soc-tas2781-fmwlib-y := tas2781-fmwlib.o
snd-soc-tas2781-i2c-y := tas2781-i2c.o
snd-soc-tfa9879-y := tfa9879.o
@@ -723,6 +724,7 @@ obj-$(CONFIG_SND_SOC_TAS2562) += snd-soc-tas2562.o
obj-$(CONFIG_SND_SOC_TAS2764) += snd-soc-tas2764.o
obj-$(CONFIG_SND_SOC_TAS2780) += snd-soc-tas2780.o
obj-$(CONFIG_SND_SOC_TAS2781_COMLIB) += snd-soc-tas2781-comlib.o
+obj-$(CONFIG_SND_SOC_TAS2781_COMLIB_I2C) += snd-soc-tas2781-comlib-i2c.o
obj-$(CONFIG_SND_SOC_TAS2781_FMWLIB) += snd-soc-tas2781-fmwlib.o
obj-$(CONFIG_SND_SOC_TAS2781_I2C) += snd-soc-tas2781-i2c.o
obj-$(CONFIG_SND_SOC_TAS5086) += snd-soc-tas5086.o
diff --git a/sound/soc/codecs/tas2781-comlib-i2c.c b/sound/soc/codecs/tas2781-comlib-i2c.c
new file mode 100644
index 000000000000..c078bb0a8437
--- /dev/null
+++ b/sound/soc/codecs/tas2781-comlib-i2c.c
@@ -0,0 +1,369 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// TAS2563/TAS2781 Common functions for HDA and ASoC Audio drivers based on I2C
+//
+// Copyright 2025 Texas Instruments, Inc.
+//
+// Author: Shenghao Ding <shenghao-ding@ti.com>
+
+#include <linux/crc8.h>
+#include <linux/firmware.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/tas2781.h>
+#include <sound/tas2781-comlib-i2c.h>
+
+static const struct regmap_range_cfg tasdevice_ranges[] = {
+ {
+ .range_min = 0,
+ .range_max = 256 * 128,
+ .selector_reg = TASDEVICE_PAGE_SELECT,
+ .selector_mask = 0xff,
+ .selector_shift = 0,
+ .window_start = 0,
+ .window_len = 128,
+ },
+};
+
+static const struct regmap_config tasdevice_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .cache_type = REGCACHE_NONE,
+ .ranges = tasdevice_ranges,
+ .num_ranges = ARRAY_SIZE(tasdevice_ranges),
+ .max_register = 256 * 128,
+};
+
+static int tasdevice_change_chn_book(struct tasdevice_priv *tas_priv,
+ unsigned short chn, int book)
+{
+ struct i2c_client *client = (struct i2c_client *)tas_priv->client;
+ int ret = 0;
+
+ if (chn < tas_priv->ndev) {
+ struct tasdevice *tasdev = &tas_priv->tasdevice[chn];
+ struct regmap *map = tas_priv->regmap;
+
+ if (client->addr != tasdev->dev_addr) {
+ client->addr = tasdev->dev_addr;
+ /* All tas2781s share the same regmap, clear the page
+ * inside regmap once switching to another tas2781.
+ * Register 0 at any pages and any books inside tas2781
+ * is the same one for page-switching.
+ */
+ ret = regmap_write(map, TASDEVICE_PAGE_SELECT, 0);
+ if (ret < 0) {
+ dev_err(tas_priv->dev, "%s, E=%d channel:%d\n",
+ __func__, ret, chn);
+ goto out;
+ }
+ }
+
+ if (tasdev->cur_book != book) {
+ ret = regmap_write(map, TASDEVICE_BOOKCTL_REG, book);
+ if (ret < 0) {
+ dev_err(tas_priv->dev, "%s, E=%d\n",
+ __func__, ret);
+ goto out;
+ }
+ tasdev->cur_book = book;
+ }
+ } else {
+ ret = -EINVAL;
+ dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__,
+ chn);
+ }
+
+out:
+ return ret;
+}
+
+int tasdev_chn_switch(struct tasdevice_priv *tas_priv,
+ unsigned short chn)
+{
+ struct i2c_client *client = (struct i2c_client *)tas_priv->client;
+ struct tasdevice *tasdev = &tas_priv->tasdevice[chn];
+ struct regmap *map = tas_priv->regmap;
+ int ret;
+
+ if (client->addr != tasdev->dev_addr) {
+ client->addr = tasdev->dev_addr;
+ /* All devices share the same regmap, clear the page
+ * inside regmap once switching to another device.
+ * Register 0 at any pages and any books inside tas2781
+ * is the same one for page-switching.
+ */
+ ret = regmap_write(map, TASDEVICE_PAGE_SELECT, 0);
+ if (ret < 0) {
+ dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
+ return ret;
+ }
+ return 1;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tasdev_chn_switch);
+
+int tasdevice_dev_update_bits(
+ struct tasdevice_priv *tas_priv, unsigned short chn,
+ unsigned int reg, unsigned int mask, unsigned int value)
+{
+ int ret = 0;
+
+ if (chn < tas_priv->ndev) {
+ struct regmap *map = tas_priv->regmap;
+
+ ret = tas_priv->change_chn_book(tas_priv, chn,
+ TASDEVICE_BOOK_ID(reg));
+ if (ret < 0)
+ goto out;
+
+ ret = regmap_update_bits(map, TASDEVICE_PGRG(reg),
+ mask, value);
+ if (ret < 0)
+ dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
+ } else {
+ dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__,
+ chn);
+ ret = -EINVAL;
+ }
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tasdevice_dev_update_bits);
+
+struct tasdevice_priv *tasdevice_kzalloc(struct i2c_client *i2c)
+{
+ struct tasdevice_priv *tas_priv;
+
+ tas_priv = devm_kzalloc(&i2c->dev, sizeof(*tas_priv), GFP_KERNEL);
+ if (!tas_priv)
+ return NULL;
+ tas_priv->dev = &i2c->dev;
+ tas_priv->client = (void *)i2c;
+
+ return tas_priv;
+}
+EXPORT_SYMBOL_GPL(tasdevice_kzalloc);
+
+int tasdevice_init(struct tasdevice_priv *tas_priv)
+{
+ int ret = 0;
+ int i;
+
+ tas_priv->regmap = devm_regmap_init_i2c(tas_priv->client,
+ &tasdevice_regmap);
+ if (IS_ERR(tas_priv->regmap)) {
+ ret = PTR_ERR(tas_priv->regmap);
+ dev_err(tas_priv->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto out;
+ }
+
+ tas_priv->cur_prog = -1;
+ tas_priv->cur_conf = -1;
+ tas_priv->isspi = false;
+
+ for (i = 0; i < tas_priv->ndev; i++) {
+ tas_priv->tasdevice[i].cur_book = -1;
+ tas_priv->tasdevice[i].cur_prog = -1;
+ tas_priv->tasdevice[i].cur_conf = -1;
+ }
+
+ tas_priv->update_bits = tasdevice_dev_update_bits;
+ tas_priv->change_chn_book = tasdevice_change_chn_book;
+ tas_priv->dev_read = tasdevice_dev_read;
+ tas_priv->dev_bulk_read = tasdevice_dev_bulk_read;
+
+ mutex_init(&tas_priv->codec_lock);
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tasdevice_init);
+
+static int tasdevice_clamp(int val, int max, unsigned int invert)
+{
+ if (val > max)
+ val = max;
+ if (invert)
+ val = max - val;
+ if (val < 0)
+ val = 0;
+ return val;
+}
+
+int tasdevice_amp_putvol(struct tasdevice_priv *tas_priv,
+ struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
+{
+ unsigned int invert = mc->invert;
+ unsigned char mask;
+ int max = mc->max;
+ int err_cnt = 0;
+ int val, i, ret;
+
+ mask = (1 << fls(max)) - 1;
+ mask <<= mc->shift;
+ val = tasdevice_clamp(ucontrol->value.integer.value[0], max, invert);
+ for (i = 0; i < tas_priv->ndev; i++) {
+ ret = tasdevice_dev_update_bits(tas_priv, i,
+ mc->reg, mask, (unsigned int)(val << mc->shift));
+ if (!ret)
+ continue;
+ err_cnt++;
+ dev_err(tas_priv->dev, "set AMP vol error in dev %d\n", i);
+ }
+
+ /* All the devices set error, return 0 */
+ return (err_cnt == tas_priv->ndev) ? 0 : 1;
+}
+EXPORT_SYMBOL_GPL(tasdevice_amp_putvol);
+
+int tasdevice_amp_getvol(struct tasdevice_priv *tas_priv,
+ struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
+{
+ unsigned int invert = mc->invert;
+ unsigned char mask = 0;
+ int max = mc->max;
+ int ret = 0;
+ int val;
+
+ /* Read the primary device */
+ ret = tasdevice_dev_read(tas_priv, 0, mc->reg, &val);
+ if (ret) {
+ dev_err(tas_priv->dev, "%s, get AMP vol error\n", __func__);
+ goto out;
+ }
+
+ mask = (1 << fls(max)) - 1;
+ mask <<= mc->shift;
+ val = (val & mask) >> mc->shift;
+ val = tasdevice_clamp(val, max, invert);
+ ucontrol->value.integer.value[0] = val;
+
+out:
+ return ret;
+
+}
+EXPORT_SYMBOL_GPL(tasdevice_amp_getvol);
+
+int tasdevice_digital_getvol(struct tasdevice_priv *tas_priv,
+ struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
+{
+ unsigned int invert = mc->invert;
+ int max = mc->max;
+ int ret, val;
+
+ /* Read the primary device as the whole */
+ ret = tasdevice_dev_read(tas_priv, 0, mc->reg, &val);
+ if (ret) {
+ dev_err(tas_priv->dev, "%s, get digital vol error\n",
+ __func__);
+ goto out;
+ }
+
+ val = tasdevice_clamp(val, max, invert);
+ ucontrol->value.integer.value[0] = val;
+
+out:
+ return ret;
+
+}
+EXPORT_SYMBOL_GPL(tasdevice_digital_getvol);
+
+int tasdevice_digital_putvol(struct tasdevice_priv *tas_priv,
+ struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
+{
+ unsigned int invert = mc->invert;
+ int max = mc->max;
+ int err_cnt = 0;
+ int ret;
+ int val, i;
+
+ val = tasdevice_clamp(ucontrol->value.integer.value[0], max, invert);
+
+ for (i = 0; i < tas_priv->ndev; i++) {
+ ret = tasdevice_dev_write(tas_priv, i, mc->reg,
+ (unsigned int)val);
+ if (!ret)
+ continue;
+ err_cnt++;
+ dev_err(tas_priv->dev,
+ "set digital vol err in dev %d\n", i);
+ }
+
+ /* All the devices set error, return 0 */
+ return (err_cnt == tas_priv->ndev) ? 0 : 1;
+
+}
+EXPORT_SYMBOL_GPL(tasdevice_digital_putvol);
+
+void tasdevice_reset(struct tasdevice_priv *tas_dev)
+{
+ int ret, i;
+
+ if (tas_dev->reset) {
+ gpiod_set_value_cansleep(tas_dev->reset, 0);
+ usleep_range(500, 1000);
+ gpiod_set_value_cansleep(tas_dev->reset, 1);
+ } else {
+ for (i = 0; i < tas_dev->ndev; i++) {
+ ret = tasdevice_dev_write(tas_dev, i,
+ TASDEVICE_REG_SWRESET,
+ TASDEVICE_REG_SWRESET_RESET);
+ if (ret < 0)
+ dev_err(tas_dev->dev,
+ "dev %d swreset fail, %d\n",
+ i, ret);
+ }
+ }
+ usleep_range(1000, 1050);
+}
+EXPORT_SYMBOL_GPL(tasdevice_reset);
+
+int tascodec_init(struct tasdevice_priv *tas_priv, void *codec,
+ struct module *module,
+ void (*cont)(const struct firmware *fw, void *context))
+{
+ int ret = 0;
+
+ /* Codec Lock Hold to ensure that codec_probe and firmware parsing and
+ * loading do not simultaneously execute.
+ */
+ mutex_lock(&tas_priv->codec_lock);
+
+ if (tas_priv->name_prefix)
+ scnprintf(tas_priv->rca_binaryname, 64, "%s-%sRCA%d.bin",
+ tas_priv->name_prefix, tas_priv->dev_name,
+ tas_priv->ndev);
+ else
+ scnprintf(tas_priv->rca_binaryname, 64, "%sRCA%d.bin",
+ tas_priv->dev_name, tas_priv->ndev);
+ crc8_populate_msb(tas_priv->crc8_lkp_tbl, TASDEVICE_CRC8_POLYNOMIAL);
+ tas_priv->codec = codec;
+ ret = request_firmware_nowait(module, FW_ACTION_UEVENT,
+ tas_priv->rca_binaryname, tas_priv->dev, GFP_KERNEL, tas_priv,
+ cont);
+ if (ret)
+ dev_err(tas_priv->dev, "request_firmware_nowait err:0x%08x\n",
+ ret);
+
+ /* Codec Lock Release*/
+ mutex_unlock(&tas_priv->codec_lock);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tascodec_init);
+
+MODULE_DESCRIPTION("TAS2781 common library for I2C");
+MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tas2781-comlib.c b/sound/soc/codecs/tas2781-comlib.c
index 1e0b3aa95749..4cec9f8a00af 100644
--- a/sound/soc/codecs/tas2781-comlib.c
+++ b/sound/soc/codecs/tas2781-comlib.c
@@ -2,14 +2,14 @@
//
// TAS2563/TAS2781 Common functions for HDA and ASoC Audio drivers
//
-// Copyright 2023 - 2024 Texas Instruments, Inc.
+// Copyright 2023 - 2025 Texas Instruments, Inc.
//
// Author: Shenghao Ding <shenghao-ding@ti.com>
#include <linux/crc8.h>
+#include <linux/dev_printk.h>
#include <linux/firmware.h>
#include <linux/gpio/consumer.h>
-#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
@@ -17,67 +17,24 @@
#include <linux/of_irq.h>
#include <linux/regmap.h>
#include <linux/slab.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
#include <sound/tas2781.h>
-#define TASDEVICE_CRC8_POLYNOMIAL 0x4d
-
-static const struct regmap_range_cfg tasdevice_ranges[] = {
- {
- .range_min = 0,
- .range_max = 256 * 128,
- .selector_reg = TASDEVICE_PAGE_SELECT,
- .selector_mask = 0xff,
- .selector_shift = 0,
- .window_start = 0,
- .window_len = 128,
- },
-};
-
-static const struct regmap_config tasdevice_regmap = {
- .reg_bits = 8,
- .val_bits = 8,
- .cache_type = REGCACHE_NONE,
- .ranges = tasdevice_ranges,
- .num_ranges = ARRAY_SIZE(tasdevice_ranges),
- .max_register = 256 * 128,
-};
-
-static int tasdevice_change_chn_book(struct tasdevice_priv *tas_priv,
- unsigned short chn, int book)
+int tasdevice_dev_read(struct tasdevice_priv *tas_priv,
+ unsigned short chn, unsigned int reg, unsigned int *val)
{
- struct i2c_client *client = (struct i2c_client *)tas_priv->client;
int ret = 0;
if (chn < tas_priv->ndev) {
- struct tasdevice *tasdev = &tas_priv->tasdevice[chn];
struct regmap *map = tas_priv->regmap;
- if (client->addr != tasdev->dev_addr) {
- client->addr = tasdev->dev_addr;
- /* All tas2781s share the same regmap, clear the page
- * inside regmap once switching to another tas2781.
- * Register 0 at any pages and any books inside tas2781
- * is the same one for page-switching.
- */
- ret = regmap_write(map, TASDEVICE_PAGE_SELECT, 0);
- if (ret < 0) {
- dev_err(tas_priv->dev, "%s, E=%d channel:%d\n",
- __func__, ret, chn);
- goto out;
- }
- }
+ ret = tas_priv->change_chn_book(tas_priv, chn,
+ TASDEVICE_BOOK_ID(reg));
+ if (ret < 0)
+ goto out;
- if (tasdev->cur_book != book) {
- ret = regmap_write(map, TASDEVICE_BOOKCTL_REG, book);
- if (ret < 0) {
- dev_err(tas_priv->dev, "%s, E=%d\n",
- __func__, ret);
- goto out;
- }
- tasdev->cur_book = book;
- }
+ ret = regmap_read(map, TASDEVICE_PGRG(reg), val);
+ if (ret < 0)
+ dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
} else {
ret = -EINVAL;
dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__,
@@ -87,59 +44,33 @@ static int tasdevice_change_chn_book(struct tasdevice_priv *tas_priv,
out:
return ret;
}
+EXPORT_SYMBOL_GPL(tasdevice_dev_read);
-int tasdev_chn_switch(struct tasdevice_priv *tas_priv,
- unsigned short chn)
-{
- struct i2c_client *client = (struct i2c_client *)tas_priv->client;
- struct tasdevice *tasdev = &tas_priv->tasdevice[chn];
- struct regmap *map = tas_priv->regmap;
- int ret;
-
- if (client->addr != tasdev->dev_addr) {
- client->addr = tasdev->dev_addr;
- /* All devices share the same regmap, clear the page
- * inside regmap once switching to another device.
- * Register 0 at any pages and any books inside tas2781
- * is the same one for page-switching.
- */
- ret = regmap_write(map, TASDEVICE_PAGE_SELECT, 0);
- if (ret < 0) {
- dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
- return ret;
- }
- return 1;
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(tasdev_chn_switch);
-
-int tasdevice_dev_read(struct tasdevice_priv *tas_priv,
- unsigned short chn, unsigned int reg, unsigned int *val)
+int tasdevice_dev_bulk_read(struct tasdevice_priv *tas_priv,
+ unsigned short chn, unsigned int reg, unsigned char *data,
+ unsigned int len)
{
int ret = 0;
if (chn < tas_priv->ndev) {
struct regmap *map = tas_priv->regmap;
- ret = tasdevice_change_chn_book(tas_priv, chn,
+ ret = tas_priv->change_chn_book(tas_priv, chn,
TASDEVICE_BOOK_ID(reg));
if (ret < 0)
goto out;
- ret = regmap_read(map, TASDEVICE_PGRG(reg), val);
+ ret = regmap_bulk_read(map, TASDEVICE_PGRG(reg), data, len);
if (ret < 0)
dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
- } else {
- ret = -EINVAL;
+ } else
dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__,
chn);
- }
out:
return ret;
}
-EXPORT_SYMBOL_GPL(tasdevice_dev_read);
+EXPORT_SYMBOL_GPL(tasdevice_dev_bulk_read);
int tasdevice_dev_write(struct tasdevice_priv *tas_priv,
unsigned short chn, unsigned int reg, unsigned int value)
@@ -149,7 +80,7 @@ int tasdevice_dev_write(struct tasdevice_priv *tas_priv,
if (chn < tas_priv->ndev) {
struct regmap *map = tas_priv->regmap;
- ret = tasdevice_change_chn_book(tas_priv, chn,
+ ret = tas_priv->change_chn_book(tas_priv, chn,
TASDEVICE_BOOK_ID(reg));
if (ret < 0)
goto out;
@@ -179,7 +110,7 @@ int tasdevice_dev_bulk_write(
if (chn < tas_priv->ndev) {
struct regmap *map = tas_priv->regmap;
- ret = tasdevice_change_chn_book(tas_priv, chn,
+ ret = tas_priv->change_chn_book(tas_priv, chn,
TASDEVICE_BOOK_ID(reg));
if (ret < 0)
goto out;
@@ -199,161 +130,6 @@ out:
}
EXPORT_SYMBOL_GPL(tasdevice_dev_bulk_write);
-int tasdevice_dev_bulk_read(struct tasdevice_priv *tas_priv,
- unsigned short chn, unsigned int reg, unsigned char *data,
- unsigned int len)
-{
- int ret = 0;
-
- if (chn < tas_priv->ndev) {
- struct regmap *map = tas_priv->regmap;
-
- ret = tasdevice_change_chn_book(tas_priv, chn,
- TASDEVICE_BOOK_ID(reg));
- if (ret < 0)
- goto out;
-
- ret = regmap_bulk_read(map, TASDEVICE_PGRG(reg), data, len);
- if (ret < 0)
- dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
- } else
- dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__,
- chn);
-
-out:
- return ret;
-}
-EXPORT_SYMBOL_GPL(tasdevice_dev_bulk_read);
-
-int tasdevice_dev_update_bits(
- struct tasdevice_priv *tas_priv, unsigned short chn,
- unsigned int reg, unsigned int mask, unsigned int value)
-{
- int ret = 0;
-
- if (chn < tas_priv->ndev) {
- struct regmap *map = tas_priv->regmap;
-
- ret = tasdevice_change_chn_book(tas_priv, chn,
- TASDEVICE_BOOK_ID(reg));
- if (ret < 0)
- goto out;
-
- ret = regmap_update_bits(map, TASDEVICE_PGRG(reg),
- mask, value);
- if (ret < 0)
- dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
- } else {
- dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__,
- chn);
- ret = -EINVAL;
- }
-
-out:
- return ret;
-}
-EXPORT_SYMBOL_GPL(tasdevice_dev_update_bits);
-
-struct tasdevice_priv *tasdevice_kzalloc(struct i2c_client *i2c)
-{
- struct tasdevice_priv *tas_priv;
-
- tas_priv = devm_kzalloc(&i2c->dev, sizeof(*tas_priv), GFP_KERNEL);
- if (!tas_priv)
- return NULL;
- tas_priv->dev = &i2c->dev;
- tas_priv->client = (void *)i2c;
-
- return tas_priv;
-}
-EXPORT_SYMBOL_GPL(tasdevice_kzalloc);
-
-void tasdevice_reset(struct tasdevice_priv *tas_dev)
-{
- int ret, i;
-
- if (tas_dev->reset) {
- gpiod_set_value_cansleep(tas_dev->reset, 0);
- usleep_range(500, 1000);
- gpiod_set_value_cansleep(tas_dev->reset, 1);
- } else {
- for (i = 0; i < tas_dev->ndev; i++) {
- ret = tasdevice_dev_write(tas_dev, i,
- TASDEVICE_REG_SWRESET,
- TASDEVICE_REG_SWRESET_RESET);
- if (ret < 0)
- dev_err(tas_dev->dev,
- "dev %d swreset fail, %d\n",
- i, ret);
- }
- }
- usleep_range(1000, 1050);
-}
-EXPORT_SYMBOL_GPL(tasdevice_reset);
-
-int tascodec_init(struct tasdevice_priv *tas_priv, void *codec,
- struct module *module,
- void (*cont)(const struct firmware *fw, void *context))
-{
- int ret = 0;
-
- /* Codec Lock Hold to ensure that codec_probe and firmware parsing and
- * loading do not simultaneously execute.
- */
- mutex_lock(&tas_priv->codec_lock);
-
- if (tas_priv->name_prefix)
- scnprintf(tas_priv->rca_binaryname, 64, "%s-%sRCA%d.bin",
- tas_priv->name_prefix, tas_priv->dev_name,
- tas_priv->ndev);
- else
- scnprintf(tas_priv->rca_binaryname, 64, "%sRCA%d.bin",
- tas_priv->dev_name, tas_priv->ndev);
- crc8_populate_msb(tas_priv->crc8_lkp_tbl, TASDEVICE_CRC8_POLYNOMIAL);
- tas_priv->codec = codec;
- ret = request_firmware_nowait(module, FW_ACTION_UEVENT,
- tas_priv->rca_binaryname, tas_priv->dev, GFP_KERNEL, tas_priv,
- cont);
- if (ret)
- dev_err(tas_priv->dev, "request_firmware_nowait err:0x%08x\n",
- ret);
-
- /* Codec Lock Release*/
- mutex_unlock(&tas_priv->codec_lock);
- return ret;
-}
-EXPORT_SYMBOL_GPL(tascodec_init);
-
-int tasdevice_init(struct tasdevice_priv *tas_priv)
-{
- int ret = 0;
- int i;
-
- tas_priv->regmap = devm_regmap_init_i2c(tas_priv->client,
- &tasdevice_regmap);
- if (IS_ERR(tas_priv->regmap)) {
- ret = PTR_ERR(tas_priv->regmap);
- dev_err(tas_priv->dev, "Failed to allocate register map: %d\n",
- ret);
- goto out;
- }
-
- tas_priv->cur_prog = -1;
- tas_priv->cur_conf = -1;
-
- for (i = 0; i < tas_priv->ndev; i++) {
- tas_priv->tasdevice[i].cur_book = -1;
- tas_priv->tasdevice[i].cur_prog = -1;
- tas_priv->tasdevice[i].cur_conf = -1;
- }
-
- mutex_init(&tas_priv->codec_lock);
-
-out:
- return ret;
-}
-EXPORT_SYMBOL_GPL(tasdevice_init);
-
static void tasdev_dsp_prog_blk_remove(struct tasdevice_prog *prog)
{
struct tasdevice_data *tas_dt;
@@ -440,137 +216,6 @@ void tasdevice_remove(struct tasdevice_priv *tas_priv)
}
EXPORT_SYMBOL_GPL(tasdevice_remove);
-int tasdevice_save_calibration(struct tasdevice_priv *tas_priv)
-{
- if (tas_priv->save_calibration)
- return tas_priv->save_calibration(tas_priv);
- return -EINVAL;
-}
-EXPORT_SYMBOL_GPL(tasdevice_save_calibration);
-
-void tasdevice_apply_calibration(struct tasdevice_priv *tas_priv)
-{
- if (tas_priv->apply_calibration && tas_priv->cali_data.total_sz)
- tas_priv->apply_calibration(tas_priv);
-}
-EXPORT_SYMBOL_GPL(tasdevice_apply_calibration);
-
-static int tasdevice_clamp(int val, int max, unsigned int invert)
-{
- if (val > max)
- val = max;
- if (invert)
- val = max - val;
- if (val < 0)
- val = 0;
- return val;
-}
-
-int tasdevice_amp_putvol(struct tasdevice_priv *tas_priv,
- struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
-{
- unsigned int invert = mc->invert;
- unsigned char mask;
- int max = mc->max;
- int err_cnt = 0;
- int val, i, ret;
-
- mask = (1 << fls(max)) - 1;
- mask <<= mc->shift;
- val = tasdevice_clamp(ucontrol->value.integer.value[0], max, invert);
- for (i = 0; i < tas_priv->ndev; i++) {
- ret = tasdevice_dev_update_bits(tas_priv, i,
- mc->reg, mask, (unsigned int)(val << mc->shift));
- if (!ret)
- continue;
- err_cnt++;
- dev_err(tas_priv->dev, "set AMP vol error in dev %d\n", i);
- }
-
- /* All the devices set error, return 0 */
- return (err_cnt == tas_priv->ndev) ? 0 : 1;
-}
-EXPORT_SYMBOL_GPL(tasdevice_amp_putvol);
-
-int tasdevice_amp_getvol(struct tasdevice_priv *tas_priv,
- struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
-{
- unsigned int invert = mc->invert;
- unsigned char mask = 0;
- int max = mc->max;
- int ret = 0;
- int val;
-
- /* Read the primary device */
- ret = tasdevice_dev_read(tas_priv, 0, mc->reg, &val);
- if (ret) {
- dev_err(tas_priv->dev, "%s, get AMP vol error\n", __func__);
- goto out;
- }
-
- mask = (1 << fls(max)) - 1;
- mask <<= mc->shift;
- val = (val & mask) >> mc->shift;
- val = tasdevice_clamp(val, max, invert);
- ucontrol->value.integer.value[0] = val;
-
-out:
- return ret;
-
-}
-EXPORT_SYMBOL_GPL(tasdevice_amp_getvol);
-
-int tasdevice_digital_putvol(struct tasdevice_priv *tas_priv,
- struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
-{
- unsigned int invert = mc->invert;
- int max = mc->max;
- int err_cnt = 0;
- int ret;
- int val, i;
-
- val = tasdevice_clamp(ucontrol->value.integer.value[0], max, invert);
-
- for (i = 0; i < tas_priv->ndev; i++) {
- ret = tasdevice_dev_write(tas_priv, i, mc->reg,
- (unsigned int)val);
- if (!ret)
- continue;
- err_cnt++;
- dev_err(tas_priv->dev,
- "set digital vol err in dev %d\n", i);
- }
-
- /* All the devices set error, return 0 */
- return (err_cnt == tas_priv->ndev) ? 0 : 1;
-
-}
-EXPORT_SYMBOL_GPL(tasdevice_digital_putvol);
-
-int tasdevice_digital_getvol(struct tasdevice_priv *tas_priv,
- struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
-{
- unsigned int invert = mc->invert;
- int max = mc->max;
- int ret, val;
-
- /* Read the primary device as the whole */
- ret = tasdevice_dev_read(tas_priv, 0, mc->reg, &val);
- if (ret) {
- dev_err(tas_priv->dev, "%s, get digital vol error\n",
- __func__);
- goto out;
- }
-
- val = tasdevice_clamp(val, max, invert);
- ucontrol->value.integer.value[0] = val;
-
-out:
- return ret;
-
-}
-EXPORT_SYMBOL_GPL(tasdevice_digital_getvol);
-
MODULE_DESCRIPTION("TAS2781 common library");
MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c
index e0c095bc6b8a..c9c1e608ddb7 100644
--- a/sound/soc/codecs/tas2781-fmwlib.c
+++ b/sound/soc/codecs/tas2781-fmwlib.c
@@ -808,8 +808,13 @@ static int tasdevice_process_block(void *context, unsigned char *data,
chn = idx - 1;
chnend = idx;
} else {
- chn = 0;
- chnend = tas_priv->ndev;
+ if (tas_priv->isspi) {
+ chn = tas_priv->index;
+ chnend = chn + 1;
+ } else {
+ chn = 0;
+ chnend = tas_priv->ndev;
+ }
}
for (; chn < chnend; chn++) {
@@ -901,7 +906,7 @@ static int tasdevice_process_block(void *context, unsigned char *data,
is_err = true;
break;
}
- rc = tasdevice_dev_update_bits(tas_priv, chn,
+ rc = tas_priv->update_bits(tas_priv, chn,
TASDEVICE_REG(data[subblk_offset + 2],
data[subblk_offset + 3],
data[subblk_offset + 4]),
@@ -1466,7 +1471,7 @@ static int tasdev_multibytes_chksum(struct tasdevice_priv *tasdevice,
goto end;
}
- ret = tasdevice_dev_bulk_read(tasdevice, chn,
+ ret = tasdevice->dev_bulk_read(tasdevice, chn,
TASDEVICE_REG(book, page, crc_data.offset),
nBuf1, crc_data.len);
if (ret < 0)
@@ -1516,7 +1521,7 @@ static int do_singlereg_checksum(struct tasdevice_priv *tasdevice,
in = check_yram(&crc_data, book, page, reg, 1);
if (!in)
goto end;
- ret = tasdevice_dev_read(tasdevice, chl,
+ ret = tasdevice->dev_read(tasdevice, chl,
TASDEVICE_REG(book, page, reg), &nData1);
if (ret < 0)
goto end;
@@ -1620,7 +1625,7 @@ static int tasdev_block_chksum(struct tasdevice_priv *tas_priv,
unsigned int nr_value;
int ret;
- ret = tasdevice_dev_read(tas_priv, chn, TASDEVICE_CHECKSUM_REG,
+ ret = tas_priv->dev_read(tas_priv, chn, TASDEVICE_CHECKSUM_REG,
&nr_value);
if (ret < 0) {
dev_err(tas_priv->dev, "%s: Chn %d\n", __func__, chn);
diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c
index 68d9fe83212a..c40d8f754d89 100644
--- a/sound/soc/codecs/tas2781-i2c.c
+++ b/sound/soc/codecs/tas2781-i2c.c
@@ -31,6 +31,7 @@
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tas2781.h>
+#include <sound/tas2781-comlib-i2c.h>
#include <sound/tlv.h>
#include <sound/tas2563-tlv.h>
#include <sound/tas2781-tlv.h>
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 3033e2d3fe16..90e367586493 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -228,6 +228,7 @@ config SND_SOC_MT8188
config SND_SOC_MT8188_MT6359
tristate "ASoC Audio driver for MT8188 with MT6359 and I2S codecs"
depends on SND_SOC_MT8188 && MTK_PMIC_WRAP
+ depends on SND_SOC_MT6359_ACCDET || !SND_SOC_MT6359_ACCDET
depends on I2C
select SND_SOC_MT6359
select SND_SOC_HDMI_CODEC
diff --git a/sound/soc/qcom/sdm845.c b/sound/soc/qcom/sdm845.c
index fcc7df75346f..a233b80049ee 100644
--- a/sound/soc/qcom/sdm845.c
+++ b/sound/soc/qcom/sdm845.c
@@ -91,6 +91,10 @@ static int sdm845_slim_snd_hw_params(struct snd_pcm_substream *substream,
else
ret = snd_soc_dai_set_channel_map(cpu_dai, tx_ch_cnt,
tx_ch, 0, NULL);
+ if (ret != 0 && ret != -ENOTSUPP) {
+ dev_err(rtd->dev, "failed to set cpu chan map, err:%d\n", ret);
+ return ret;
+ }
}
return 0;
diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c
index b1be03011d7e..6492e1cefbfb 100644
--- a/sound/soc/sof/intel/hda-bus.c
+++ b/sound/soc/sof/intel/hda-bus.c
@@ -76,7 +76,7 @@ void sof_hda_bus_init(struct snd_sof_dev *sdev, struct device *dev)
snd_hdac_ext_bus_init(bus, dev, &bus_core_ops, sof_hda_ext_ops);
- if (chip && chip->hw_ip_version == SOF_INTEL_ACE_2_0)
+ if (chip && chip->hw_ip_version >= SOF_INTEL_ACE_2_0)
bus->use_pio_for_commands = true;
#else
snd_hdac_ext_bus_init(bus, dev, NULL, NULL);
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index b34e5fdf10f1..6a3932d90b43 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -1049,7 +1049,21 @@ static void hda_generic_machine_select(struct snd_sof_dev *sdev,
if (!*mach && codec_num <= 2) {
bool tplg_fixup = false;
- hda_mach = snd_soc_acpi_intel_hda_machines;
+ /*
+ * make a local copy of the match array since we might
+ * be modifying it
+ */
+ hda_mach = devm_kmemdup_array(sdev->dev,
+ snd_soc_acpi_intel_hda_machines,
+ 2, /* we have one entry + sentinel in the array */
+ sizeof(snd_soc_acpi_intel_hda_machines[0]),
+ GFP_KERNEL);
+ if (!hda_mach) {
+ dev_err(bus->dev,
+ "%s: failed to duplicate the HDA match table\n",
+ __func__);
+ return;
+ }
dev_info(bus->dev, "using HDA machine driver %s now\n",
hda_mach->drv_name);
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index 108cad04879e..e14f82c0831f 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -935,6 +935,7 @@ extern const struct sof_intel_dsp_desc mtl_chip_info;
extern const struct sof_intel_dsp_desc arl_s_chip_info;
extern const struct sof_intel_dsp_desc lnl_chip_info;
extern const struct sof_intel_dsp_desc ptl_chip_info;
+extern const struct sof_intel_dsp_desc wcl_chip_info;
/* Probes support */
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_PROBES)
diff --git a/sound/soc/sof/intel/pci-ptl.c b/sound/soc/sof/intel/pci-ptl.c
index 7d4c46f56931..68f6a9841633 100644
--- a/sound/soc/sof/intel/pci-ptl.c
+++ b/sound/soc/sof/intel/pci-ptl.c
@@ -55,10 +55,40 @@ static const struct sof_dev_desc ptl_desc = {
.ops_init = sof_ptl_ops_init,
};
+static const struct sof_dev_desc wcl_desc = {
+ .use_acpi_target_states = true,
+ .machines = snd_soc_acpi_intel_ptl_machines,
+ .alt_machines = snd_soc_acpi_intel_ptl_sdw_machines,
+ .resindex_lpe_base = 0,
+ .resindex_pcicfg_base = -1,
+ .resindex_imr_base = -1,
+ .irqindex_host_ipc = -1,
+ .chip_info = &wcl_chip_info,
+ .ipc_supported_mask = BIT(SOF_IPC_TYPE_4),
+ .ipc_default = SOF_IPC_TYPE_4,
+ .dspless_mode_supported = true,
+ .default_fw_path = {
+ [SOF_IPC_TYPE_4] = "intel/sof-ipc4/wcl",
+ },
+ .default_lib_path = {
+ [SOF_IPC_TYPE_4] = "intel/sof-ipc4-lib/wcl",
+ },
+ .default_tplg_path = {
+ [SOF_IPC_TYPE_4] = "intel/sof-ipc4-tplg",
+ },
+ .default_fw_filename = {
+ [SOF_IPC_TYPE_4] = "sof-wcl.ri",
+ },
+ .nocodec_tplg_filename = "sof-ptl-nocodec.tplg",
+ .ops = &sof_ptl_ops,
+ .ops_init = sof_ptl_ops_init,
+};
+
/* PCI IDs */
static const struct pci_device_id sof_pci_ids[] = {
{ PCI_DEVICE_DATA(INTEL, HDA_PTL, &ptl_desc) }, /* PTL */
{ PCI_DEVICE_DATA(INTEL, HDA_PTL_H, &ptl_desc) }, /* PTL-H */
+ { PCI_DEVICE_DATA(INTEL, HDA_WCL, &wcl_desc) }, /* WCL */
{ 0, }
};
MODULE_DEVICE_TABLE(pci, sof_pci_ids);
diff --git a/sound/soc/sof/intel/ptl.c b/sound/soc/sof/intel/ptl.c
index aa0b772178bc..875d18193b05 100644
--- a/sound/soc/sof/intel/ptl.c
+++ b/sound/soc/sof/intel/ptl.c
@@ -126,6 +126,29 @@ const struct sof_intel_dsp_desc ptl_chip_info = {
.hw_ip_version = SOF_INTEL_ACE_3_0,
};
+const struct sof_intel_dsp_desc wcl_chip_info = {
+ .cores_num = 3,
+ .init_core_mask = BIT(0),
+ .host_managed_cores_mask = BIT(0),
+ .ipc_req = MTL_DSP_REG_HFIPCXIDR,
+ .ipc_req_mask = MTL_DSP_REG_HFIPCXIDR_BUSY,
+ .ipc_ack = MTL_DSP_REG_HFIPCXIDA,
+ .ipc_ack_mask = MTL_DSP_REG_HFIPCXIDA_DONE,
+ .ipc_ctl = MTL_DSP_REG_HFIPCXCTL,
+ .rom_status_reg = LNL_DSP_REG_HFDSC,
+ .rom_init_timeout = 300,
+ .ssp_count = MTL_SSP_COUNT,
+ .d0i3_offset = MTL_HDA_VS_D0I3C,
+ .read_sdw_lcount = hda_sdw_check_lcount_ext,
+ .check_sdw_irq = lnl_dsp_check_sdw_irq,
+ .check_sdw_wakeen_irq = lnl_sdw_check_wakeen_irq,
+ .check_ipc_irq = mtl_dsp_check_ipc_irq,
+ .cl_init = mtl_dsp_cl_init,
+ .power_down_dsp = mtl_power_down_dsp,
+ .disable_interrupts = lnl_dsp_disable_interrupts,
+ .hw_ip_version = SOF_INTEL_ACE_3_0,
+};
+
MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL");
MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_LNL");
MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK");
diff --git a/sound/soc/sof/ipc4-control.c b/sound/soc/sof/ipc4-control.c
index 576f407cd456..976a4794d610 100644
--- a/sound/soc/sof/ipc4-control.c
+++ b/sound/soc/sof/ipc4-control.c
@@ -531,6 +531,14 @@ static int sof_ipc4_bytes_ext_put(struct snd_sof_control *scontrol,
return -EINVAL;
}
+ /* Check header id */
+ if (header.numid != SOF_CTRL_CMD_BINARY) {
+ dev_err_ratelimited(scomp->dev,
+ "Incorrect numid for bytes put %d\n",
+ header.numid);
+ return -EINVAL;
+ }
+
/* Verify the ABI header first */
if (copy_from_user(&abi_hdr, tlvd->tlv, sizeof(abi_hdr)))
return -EFAULT;
@@ -613,7 +621,8 @@ static int _sof_ipc4_bytes_ext_get(struct snd_sof_control *scontrol,
if (data_size > size)
return -ENOSPC;
- header.numid = scontrol->comp_id;
+ /* Set header id and length */
+ header.numid = SOF_CTRL_CMD_BINARY;
header.length = data_size;
if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv)))
diff --git a/sound/soc/sof/ipc4-pcm.c b/sound/soc/sof/ipc4-pcm.c
index 52903503cf3b..8eee3e1aadf9 100644
--- a/sound/soc/sof/ipc4-pcm.c
+++ b/sound/soc/sof/ipc4-pcm.c
@@ -799,7 +799,8 @@ static int sof_ipc4_pcm_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm
spcm->stream[stream].private = stream_priv;
- if (!support_info)
+ /* Delay reporting is only supported on playback */
+ if (!support_info || stream == SNDRV_PCM_STREAM_CAPTURE)
continue;
time_info = kzalloc(sizeof(*time_info), GFP_KERNEL);
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 2d4e660b19d5..d612d693efc3 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -1071,7 +1071,7 @@ static int sof_connect_dai_widget(struct snd_soc_component *scomp,
struct snd_sof_dai *dai)
{
struct snd_soc_card *card = scomp->card;
- struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_pcm_runtime *rtd, *full, *partial;
struct snd_soc_dai *cpu_dai;
int stream;
int i;
@@ -1088,12 +1088,22 @@ static int sof_connect_dai_widget(struct snd_soc_component *scomp,
else
goto end;
+ full = NULL;
+ partial = NULL;
list_for_each_entry(rtd, &card->rtd_list, list) {
/* does stream match DAI link ? */
- if (!rtd->dai_link->stream_name ||
- !strstr(rtd->dai_link->stream_name, w->sname))
- continue;
+ if (rtd->dai_link->stream_name) {
+ if (!strcmp(rtd->dai_link->stream_name, w->sname)) {
+ full = rtd;
+ break;
+ } else if (strstr(rtd->dai_link->stream_name, w->sname)) {
+ partial = rtd;
+ }
+ }
+ }
+ rtd = full ? full : partial;
+ if (rtd) {
for_each_rtd_cpu_dais(rtd, i, cpu_dai) {
/*
* Please create DAI widget in the right order
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index 9bdf3db51d62..e73d3b262f57 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -39,6 +39,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/io.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -754,7 +755,7 @@ static int snd_amd7930_pcm(struct snd_amd7930 *amd)
pcm->private_data = amd;
pcm->info_flags = 0;
- strcpy(pcm->name, amd->card->shortname);
+ strscpy(pcm->name, amd->card->shortname);
amd->pcm = pcm;
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
@@ -874,7 +875,7 @@ static int snd_amd7930_mixer(struct snd_amd7930 *amd)
return -EINVAL;
card = amd->card;
- strcpy(card->mixername, card->shortname);
+ strscpy(card->mixername, card->shortname);
for (idx = 0; idx < ARRAY_SIZE(amd7930_controls); idx++) {
if ((err = snd_ctl_add(card,
@@ -1007,8 +1008,8 @@ static int amd7930_sbus_probe(struct platform_device *op)
if (err < 0)
return err;
- strcpy(card->driver, "AMD7930");
- strcpy(card->shortname, "Sun AMD7930");
+ strscpy(card->driver, "AMD7930");
+ strscpy(card->shortname, "Sun AMD7930");
sprintf(card->longname, "%s at 0x%02lx:0x%08Lx, irq %d",
card->shortname,
rp->flags & 0xffL,
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 69f1c9e37f4b..93cbe158009f 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -60,6 +60,7 @@
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/gfp.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -2239,7 +2240,7 @@ static int snd_dbri_pcm(struct snd_card *card)
pcm->private_data = card->private_data;
pcm->info_flags = 0;
- strcpy(pcm->name, card->shortname);
+ strscpy(pcm->name, card->shortname);
snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
NULL, 64 * 1024, 64 * 1024);
@@ -2446,7 +2447,7 @@ static int snd_dbri_mixer(struct snd_card *card)
return -EINVAL;
dbri = card->private_data;
- strcpy(card->mixername, card->shortname);
+ strscpy(card->mixername, card->shortname);
for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) {
err = snd_ctl_add(card,
@@ -2613,8 +2614,8 @@ static int dbri_probe(struct platform_device *op)
if (err < 0)
return err;
- strcpy(card->driver, "DBRI");
- strcpy(card->shortname, "Sun DBRI");
+ strscpy(card->driver, "DBRI");
+ strscpy(card->shortname, "Sun DBRI");
rp = &op->resource[0];
sprintf(card->longname, "%s at 0x%02lx:0x%016llx, irq %d",
card->shortname,
diff --git a/sound/usb/fcp.c b/sound/usb/fcp.c
index 7df65041ace5..98f9964311a7 100644
--- a/sound/usb/fcp.c
+++ b/sound/usb/fcp.c
@@ -1092,8 +1092,7 @@ static int fcp_find_fc_interface(struct usb_mixer_interface *mixer)
epd = get_endpoint(intf->altsetting, 0);
private->bInterfaceNumber = desc->bInterfaceNumber;
- private->bEndpointAddress = epd->bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
+ private->bEndpointAddress = usb_endpoint_num(epd);
private->wMaxPacketSize = le16_to_cpu(epd->wMaxPacketSize);
private->bInterval = epd->bInterval;
return 0;
diff --git a/sound/usb/implicit.c b/sound/usb/implicit.c
index 4727043fd745..77f06da93151 100644
--- a/sound/usb/implicit.c
+++ b/sound/usb/implicit.c
@@ -57,6 +57,7 @@ static const struct snd_usb_implicit_fb_match playback_implicit_fb_quirks[] = {
IMPLICIT_FB_FIXED_DEV(0x31e9, 0x0002, 0x81, 2), /* Solid State Logic SSL2+ */
IMPLICIT_FB_FIXED_DEV(0x0499, 0x172f, 0x81, 2), /* Steinberg UR22C */
IMPLICIT_FB_FIXED_DEV(0x0d9a, 0x00df, 0x81, 2), /* RTX6001 */
+ IMPLICIT_FB_FIXED_DEV(0x19f7, 0x000a, 0x84, 3), /* RODE AI-1 */
IMPLICIT_FB_FIXED_DEV(0x22f0, 0x0006, 0x81, 3), /* Allen&Heath Qu-16 */
IMPLICIT_FB_FIXED_DEV(0x1686, 0xf029, 0x82, 2), /* Zoom UAC-2 */
IMPLICIT_FB_FIXED_DEV(0x2466, 0x8003, 0x86, 2), /* Fractal Audio Axe-Fx II */
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index cfed000f243a..3a8a977ed359 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -1530,6 +1530,7 @@ static void snd_usbmidi_free(struct snd_usb_midi *umidi)
snd_usbmidi_in_endpoint_delete(ep->in);
}
mutex_destroy(&umidi->mutex);
+ timer_shutdown_sync(&umidi->error_timer);
kfree(umidi);
}
@@ -1553,7 +1554,7 @@ void snd_usbmidi_disconnect(struct list_head *p)
spin_unlock_irq(&umidi->disc_lock);
up_write(&umidi->disc_rwsem);
- timer_delete_sync(&umidi->error_timer);
+ timer_shutdown_sync(&umidi->error_timer);
for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
struct snd_usb_midi_endpoint *ep = &umidi->endpoints[i];
@@ -2088,7 +2089,7 @@ static int roland_load_get(struct snd_kcontrol *kcontrol,
static int roland_load_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *value)
{
- struct snd_usb_midi *umidi = kcontrol->private_data;
+ struct snd_usb_midi *umidi = snd_kcontrol_chip(kcontrol);
int changed;
if (value->value.enumerated.item[0] > 1)
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 66976be06bc0..11be79af26db 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -547,7 +547,7 @@ int snd_usb_set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel,
int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *_tlv)
{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol);
DECLARE_TLV_DB_MINMAX(scale, 0, 0);
if (size < sizeof(scale))
@@ -1367,7 +1367,7 @@ static int get_max_exposed(struct usb_mixer_elem_info *cval)
static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol);
if (cval->val_type == USB_MIXER_BOOLEAN ||
cval->val_type == USB_MIXER_INV_BOOLEAN)
@@ -1399,7 +1399,7 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol,
static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol);
int c, cnt, val, err;
ucontrol->value.integer.value[0] = cval->min;
@@ -1431,7 +1431,7 @@ static int mixer_ctl_feature_get(struct snd_kcontrol *kcontrol,
static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol);
int max_val = get_max_exposed(cval);
int c, cnt, val, oval, err;
int changed = 0;
@@ -1475,7 +1475,7 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol,
static int mixer_ctl_master_bool_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol);
int val, err;
err = snd_usb_get_cur_mix_value(cval, 0, 0, &val);
@@ -1543,7 +1543,7 @@ error:
static int mixer_ctl_connector_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol);
int ret, val;
ret = get_connector_value(cval, kcontrol->id.name, &val);
@@ -2302,7 +2302,7 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol);
int err, val;
err = get_cur_ctl_value(cval, cval->control << 8, &val);
@@ -2319,7 +2319,7 @@ static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol,
static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol);
int val, oval, err;
err = get_cur_ctl_value(cval, cval->control << 8, &oval);
@@ -2654,7 +2654,7 @@ static int parse_audio_extension_unit(struct mixer_build *state, int unitid,
static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol);
const char **itemlist = (const char **)kcontrol->private_value;
if (snd_BUG_ON(!itemlist))
@@ -2666,7 +2666,7 @@ static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol,
static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol);
int val, err;
err = get_cur_ctl_value(cval, cval->control << 8, &val);
@@ -2683,7 +2683,7 @@ static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol,
static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol);
int val, oval, err;
err = get_cur_ctl_value(cval, cval->control << 8, &oval);
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index a90673d43822..aad205df93b2 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -2000,7 +2000,7 @@ static int realtek_hda_get(struct snd_usb_audio *chip, u32 cmd, u32 *value)
static int realtek_ctl_connector_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *cval = kcontrol->private_data;
+ struct usb_mixer_elem_info *cval = snd_kcontrol_chip(kcontrol);
struct snd_usb_audio *chip = cval->head.mixer->chip;
u32 pv = kcontrol->private_value;
u32 node_id = pv & 0xff;
@@ -3525,10 +3525,13 @@ static int snd_rme_digiface_controls_create(struct usb_mixer_interface *mixer)
#define SND_DJM_CAP_RECOUT 0x0a
#define SND_DJM_CAP_RECOUT_NOMIC 0x0e
#define SND_DJM_CAP_NONE 0x0f
+#define SND_DJM_CAP_FXSEND 0x10
#define SND_DJM_CAP_CH1PFADER 0x11
#define SND_DJM_CAP_CH2PFADER 0x12
#define SND_DJM_CAP_CH3PFADER 0x13
#define SND_DJM_CAP_CH4PFADER 0x14
+#define SND_DJM_CAP_EXT1SEND 0x21
+#define SND_DJM_CAP_EXT2SEND 0x22
#define SND_DJM_CAP_CH1PREFADER 0x31
#define SND_DJM_CAP_CH2PREFADER 0x32
#define SND_DJM_CAP_CH3PREFADER 0x33
@@ -3559,6 +3562,7 @@ static int snd_rme_digiface_controls_create(struct usb_mixer_interface *mixer)
#define SND_DJM_750MK2_IDX 0x4
#define SND_DJM_450_IDX 0x5
#define SND_DJM_A9_IDX 0x6
+#define SND_DJM_V10_IDX 0x7
#define SND_DJM_CTL(_name, suffix, _default_value, _windex) { \
@@ -3598,8 +3602,8 @@ static const char *snd_djm_get_label_caplevel_common(u16 wvalue)
}
};
-// The DJM-A9 has different capture levels than other, older models
-static const char *snd_djm_get_label_caplevel_a9(u16 wvalue)
+// Models like DJM-A9 or DJM-V10 have different capture levels than others
+static const char *snd_djm_get_label_caplevel_high(u16 wvalue)
{
switch (wvalue) {
case 0x0000: return "+15dB";
@@ -3627,6 +3631,7 @@ static const char *snd_djm_get_label_cap_common(u16 wvalue)
case SND_DJM_CAP_RECOUT_NOMIC: return "Rec Out without Mic";
case SND_DJM_CAP_AUX: return "Aux";
case SND_DJM_CAP_NONE: return "None";
+ case SND_DJM_CAP_FXSEND: return "FX SEND";
case SND_DJM_CAP_CH1PREFADER: return "Pre Fader Ch1";
case SND_DJM_CAP_CH2PREFADER: return "Pre Fader Ch2";
case SND_DJM_CAP_CH3PREFADER: return "Pre Fader Ch3";
@@ -3635,6 +3640,8 @@ static const char *snd_djm_get_label_cap_common(u16 wvalue)
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";
+ case SND_DJM_CAP_EXT1SEND: return "EXT1 SEND";
+ case SND_DJM_CAP_EXT2SEND: return "EXT2 SEND";
default: return NULL;
}
};
@@ -3653,7 +3660,8 @@ static const char *snd_djm_get_label_cap_850(u16 wvalue)
static const char *snd_djm_get_label_caplevel(u8 device_idx, u16 wvalue)
{
switch (device_idx) {
- case SND_DJM_A9_IDX: return snd_djm_get_label_caplevel_a9(wvalue);
+ case SND_DJM_A9_IDX: return snd_djm_get_label_caplevel_high(wvalue);
+ case SND_DJM_V10_IDX: return snd_djm_get_label_caplevel_high(wvalue);
default: return snd_djm_get_label_caplevel_common(wvalue);
}
};
@@ -3705,13 +3713,13 @@ 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)
+ SND_DJM_CTL("Master Input Level Capture Switch", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+ SND_DJM_CTL("Input 1 Capture Switch", 250mk2_cap1, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 2 Capture Switch", 250mk2_cap2, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 3 Capture Switch", 250mk2_cap3, 0, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Output 1 Playback Switch", 250mk2_pb1, 0, SND_DJM_WINDEX_PB),
+ SND_DJM_CTL("Output 2 Playback Switch", 250mk2_pb2, 1, SND_DJM_WINDEX_PB),
+ SND_DJM_CTL("Output 3 Playback Switch", 250mk2_pb3, 2, SND_DJM_WINDEX_PB)
};
@@ -3730,13 +3738,13 @@ static const u16 snd_djm_opts_450_pb2[] = { 0x0200, 0x0201, 0x0204 };
static const u16 snd_djm_opts_450_pb3[] = { 0x0300, 0x0301, 0x0304 };
static const struct snd_djm_ctl snd_djm_ctls_450[] = {
- SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
- SND_DJM_CTL("Ch1 Input", 450_cap1, 2, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch2 Input", 450_cap2, 2, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch3 Input", 450_cap3, 0, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch1 Output", 450_pb1, 0, SND_DJM_WINDEX_PB),
- SND_DJM_CTL("Ch2 Output", 450_pb2, 1, SND_DJM_WINDEX_PB),
- SND_DJM_CTL("Ch3 Output", 450_pb3, 2, SND_DJM_WINDEX_PB)
+ SND_DJM_CTL("Master Input Level Capture Switch", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+ SND_DJM_CTL("Input 1 Capture Switch", 450_cap1, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 2 Capture Switch", 450_cap2, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 3 Capture Switch", 450_cap3, 0, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Output 1 Playback Switch", 450_pb1, 0, SND_DJM_WINDEX_PB),
+ SND_DJM_CTL("Output 2 Playback Switch", 450_pb2, 1, SND_DJM_WINDEX_PB),
+ SND_DJM_CTL("Output 3 Playback Switch", 450_pb3, 2, SND_DJM_WINDEX_PB)
};
@@ -3751,11 +3759,11 @@ 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)
+ SND_DJM_CTL("Master Input Level Capture Switch", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+ SND_DJM_CTL("Input 1 Capture Switch", 750_cap1, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 2 Capture Switch", 750_cap2, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 3 Capture Switch", 750_cap3, 0, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 4 Capture Switch", 750_cap4, 0, SND_DJM_WINDEX_CAP)
};
@@ -3770,11 +3778,11 @@ static const u16 snd_djm_opts_850_cap4[] = {
0x0400, 0x0403, 0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040f };
static const struct snd_djm_ctl snd_djm_ctls_850[] = {
- SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
- SND_DJM_CTL("Ch1 Input", 850_cap1, 1, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch2 Input", 850_cap2, 0, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch3 Input", 850_cap3, 0, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch4 Input", 850_cap4, 1, SND_DJM_WINDEX_CAP)
+ SND_DJM_CTL("Master Input Level Capture Switch", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+ SND_DJM_CTL("Input 1 Capture Switch", 850_cap1, 1, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 2 Capture Switch", 850_cap2, 0, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 3 Capture Switch", 850_cap3, 0, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 4 Capture Switch", 850_cap4, 1, SND_DJM_WINDEX_CAP)
};
@@ -3791,12 +3799,12 @@ 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)
+ SND_DJM_CTL("Master Input Level Capture Switch", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+ SND_DJM_CTL("Input 1 Capture Switch", 900nxs2_cap1, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 2 Capture Switch", 900nxs2_cap2, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 3 Capture Switch", 900nxs2_cap3, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 4 Capture Switch", 900nxs2_cap4, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 5 Capture Switch", 900nxs2_cap5, 3, SND_DJM_WINDEX_CAP)
};
// DJM-750MK2
@@ -3817,15 +3825,15 @@ static const u16 snd_djm_opts_750mk2_pb3[] = { 0x0300, 0x0301, 0x0304 };
static const struct snd_djm_ctl snd_djm_ctls_750mk2[] = {
- SND_DJM_CTL("Capture Level", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
- SND_DJM_CTL("Ch1 Input", 750mk2_cap1, 2, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch2 Input", 750mk2_cap2, 2, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch3 Input", 750mk2_cap3, 2, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch4 Input", 750mk2_cap4, 2, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch5 Input", 750mk2_cap5, 3, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch1 Output", 750mk2_pb1, 0, SND_DJM_WINDEX_PB),
- SND_DJM_CTL("Ch2 Output", 750mk2_pb2, 1, SND_DJM_WINDEX_PB),
- SND_DJM_CTL("Ch3 Output", 750mk2_pb3, 2, SND_DJM_WINDEX_PB)
+ SND_DJM_CTL("Master Input Level Capture Switch", cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+ SND_DJM_CTL("Input 1 Capture Switch", 750mk2_cap1, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 2 Capture Switch", 750mk2_cap2, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 3 Capture Switch", 750mk2_cap3, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 4 Capture Switch", 750mk2_cap4, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 5 Capture Switch", 750mk2_cap5, 3, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Output 1 Playback Switch", 750mk2_pb1, 0, SND_DJM_WINDEX_PB),
+ SND_DJM_CTL("Output 2 Playback Switch", 750mk2_pb2, 1, SND_DJM_WINDEX_PB),
+ SND_DJM_CTL("Output 3 Playback Switch", 750mk2_pb3, 2, SND_DJM_WINDEX_PB)
};
@@ -3845,12 +3853,56 @@ static const u16 snd_djm_opts_a9_cap5[] = {
0x0501, 0x0502, 0x0503, 0x0505, 0x0506, 0x0507, 0x0508, 0x0509, 0x050a, 0x050e };
static const struct snd_djm_ctl snd_djm_ctls_a9[] = {
- SND_DJM_CTL("Capture Level", a9_cap_level, 0, SND_DJM_WINDEX_CAPLVL),
- SND_DJM_CTL("Master Input", a9_cap1, 3, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch1 Input", a9_cap2, 2, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch2 Input", a9_cap3, 2, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch3 Input", a9_cap4, 2, SND_DJM_WINDEX_CAP),
- SND_DJM_CTL("Ch4 Input", a9_cap5, 2, SND_DJM_WINDEX_CAP)
+ SND_DJM_CTL("Master Input Level Capture Switch", a9_cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+ SND_DJM_CTL("Master Input Capture Switch", a9_cap1, 3, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 1 Capture Switch", a9_cap2, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 2 Capture Switch", a9_cap3, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 3 Capture Switch", a9_cap4, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 4 Capture Switch", a9_cap5, 2, SND_DJM_WINDEX_CAP)
+};
+
+// DJM-V10
+static const u16 snd_djm_opts_v10_cap_level[] = {
+ 0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500
+};
+static const u16 snd_djm_opts_v10_cap1[] = {
+ 0x0103,
+ 0x0100, 0x0102, 0x0106, 0x0110, 0x0107,
+ 0x0108, 0x0109, 0x010a, 0x0121, 0x0122
+};
+static const u16 snd_djm_opts_v10_cap2[] = {
+ 0x0200, 0x0202, 0x0206, 0x0210, 0x0207,
+ 0x0208, 0x0209, 0x020a, 0x0221, 0x0222
+};
+static const u16 snd_djm_opts_v10_cap3[] = {
+ 0x0303,
+ 0x0300, 0x0302, 0x0306, 0x0310, 0x0307,
+ 0x0308, 0x0309, 0x030a, 0x0321, 0x0322
+};
+static const u16 snd_djm_opts_v10_cap4[] = {
+ 0x0403,
+ 0x0400, 0x0402, 0x0406, 0x0410, 0x0407,
+ 0x0408, 0x0409, 0x040a, 0x0421, 0x0422
+};
+static const u16 snd_djm_opts_v10_cap5[] = {
+ 0x0500, 0x0502, 0x0506, 0x0510, 0x0507,
+ 0x0508, 0x0509, 0x050a, 0x0521, 0x0522
+};
+static const u16 snd_djm_opts_v10_cap6[] = {
+ 0x0603,
+ 0x0600, 0x0602, 0x0606, 0x0610, 0x0607,
+ 0x0608, 0x0609, 0x060a, 0x0621, 0x0622
+};
+
+static const struct snd_djm_ctl snd_djm_ctls_v10[] = {
+ SND_DJM_CTL("Master Input Level Capture Switch", v10_cap_level, 0, SND_DJM_WINDEX_CAPLVL),
+ SND_DJM_CTL("Input 1 Capture Switch", v10_cap1, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 2 Capture Switch", v10_cap2, 2, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 3 Capture Switch", v10_cap3, 0, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 4 Capture Switch", v10_cap4, 0, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 5 Capture Switch", v10_cap5, 0, SND_DJM_WINDEX_CAP),
+ SND_DJM_CTL("Input 6 Capture Switch", v10_cap6, 0, SND_DJM_WINDEX_CAP)
+ // playback channels are fixed and controlled by hardware knobs on the mixer
};
static const struct snd_djm_device snd_djm_devices[] = {
@@ -3861,6 +3913,7 @@ static const struct snd_djm_device snd_djm_devices[] = {
[SND_DJM_750MK2_IDX] = SND_DJM_DEVICE(750mk2),
[SND_DJM_450_IDX] = SND_DJM_DEVICE(450),
[SND_DJM_A9_IDX] = SND_DJM_DEVICE(a9),
+ [SND_DJM_V10_IDX] = SND_DJM_DEVICE(v10),
};
@@ -4151,6 +4204,9 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
case USB_ID(0x2b73, 0x003c): /* Pioneer DJ / AlphaTheta DJM-A9 */
err = snd_djm_controls_create(mixer, SND_DJM_A9_IDX);
break;
+ case USB_ID(0x2b73, 0x0034): /* Pioneer DJ DJM-V10 */
+ err = snd_djm_controls_create(mixer, SND_DJM_V10_IDX);
+ break;
}
return err;
diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c
index 288d22e6a0b2..93589e86828a 100644
--- a/sound/usb/mixer_scarlett2.c
+++ b/sound/usb/mixer_scarlett2.c
@@ -8574,8 +8574,7 @@ static int scarlett2_find_fc_interface(struct usb_device *dev,
epd = get_endpoint(intf->altsetting, 0);
private->bInterfaceNumber = desc->bInterfaceNumber;
- private->bEndpointAddress = epd->bEndpointAddress &
- USB_ENDPOINT_NUMBER_MASK;
+ private->bEndpointAddress = usb_endpoint_num(epd);
private->wMaxPacketSize = le16_to_cpu(epd->wMaxPacketSize);
private->bInterval = epd->bInterval;
return 0;
diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c
index 20ac32635f1f..236b69054867 100644
--- a/sound/usb/mixer_us16x08.c
+++ b/sound/usb/mixer_us16x08.c
@@ -180,7 +180,7 @@ static int snd_us16x08_route_info(struct snd_kcontrol *kcontrol,
static int snd_us16x08_route_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
int index = ucontrol->id.index;
/* route has no bias */
@@ -192,7 +192,7 @@ static int snd_us16x08_route_get(struct snd_kcontrol *kcontrol,
static int snd_us16x08_route_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
struct snd_usb_audio *chip = elem->head.mixer->chip;
int index = ucontrol->id.index;
char buf[sizeof(route_msg)];
@@ -249,7 +249,7 @@ static int snd_us16x08_master_info(struct snd_kcontrol *kcontrol,
static int snd_us16x08_master_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
int index = ucontrol->id.index;
ucontrol->value.integer.value[0] = elem->cache_val[index];
@@ -260,7 +260,7 @@ static int snd_us16x08_master_get(struct snd_kcontrol *kcontrol,
static int snd_us16x08_master_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
struct snd_usb_audio *chip = elem->head.mixer->chip;
char buf[sizeof(mix_msg_out)];
int val, err;
@@ -297,7 +297,7 @@ static int snd_us16x08_master_put(struct snd_kcontrol *kcontrol,
static int snd_us16x08_bus_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
struct snd_usb_audio *chip = elem->head.mixer->chip;
char buf[sizeof(mix_msg_out)];
int val, err = 0;
@@ -338,7 +338,7 @@ static int snd_us16x08_bus_put(struct snd_kcontrol *kcontrol,
static int snd_us16x08_bus_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
switch (elem->head.id) {
case SND_US16X08_ID_BUSS_OUT:
@@ -359,7 +359,7 @@ static int snd_us16x08_bus_get(struct snd_kcontrol *kcontrol,
static int snd_us16x08_channel_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
int index = ucontrol->id.index;
ucontrol->value.integer.value[0] = elem->cache_val[index];
@@ -370,7 +370,7 @@ static int snd_us16x08_channel_get(struct snd_kcontrol *kcontrol,
static int snd_us16x08_channel_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
struct snd_usb_audio *chip = elem->head.mixer->chip;
char buf[sizeof(mix_msg_in)];
int val, err;
@@ -417,7 +417,7 @@ static int snd_us16x08_mix_info(struct snd_kcontrol *kcontrol,
static int snd_us16x08_comp_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
struct snd_us16x08_comp_store *store = elem->private_data;
int index = ucontrol->id.index;
int val_idx = COMP_STORE_IDX(elem->head.id);
@@ -430,7 +430,7 @@ static int snd_us16x08_comp_get(struct snd_kcontrol *kcontrol,
static int snd_us16x08_comp_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
struct snd_usb_audio *chip = elem->head.mixer->chip;
struct snd_us16x08_comp_store *store = elem->private_data;
int index = ucontrol->id.index;
@@ -485,7 +485,7 @@ static int snd_us16x08_eqswitch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int val;
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
struct snd_us16x08_eq_store *store = elem->private_data;
int index = ucontrol->id.index;
@@ -500,7 +500,7 @@ static int snd_us16x08_eqswitch_get(struct snd_kcontrol *kcontrol,
static int snd_us16x08_eqswitch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
struct snd_usb_audio *chip = elem->head.mixer->chip;
struct snd_us16x08_eq_store *store = elem->private_data;
int index = ucontrol->id.index;
@@ -544,7 +544,7 @@ static int snd_us16x08_eq_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int val;
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
struct snd_us16x08_eq_store *store = elem->private_data;
int index = ucontrol->id.index;
int b_idx = EQ_STORE_BAND_IDX(elem->head.id) - 1;
@@ -560,7 +560,7 @@ static int snd_us16x08_eq_get(struct snd_kcontrol *kcontrol,
static int snd_us16x08_eq_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
struct snd_usb_audio *chip = elem->head.mixer->chip;
struct snd_us16x08_eq_store *store = elem->private_data;
int index = ucontrol->id.index;
@@ -684,7 +684,7 @@ static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
int i, set;
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
struct snd_usb_audio *chip = elem->head.mixer->chip;
struct snd_us16x08_meter_store *store = elem->private_data;
u8 meter_urb[64] = {0};
@@ -744,7 +744,7 @@ static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol,
static int snd_us16x08_meter_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct usb_mixer_elem_info *elem = kcontrol->private_data;
+ struct usb_mixer_elem_info *elem = snd_kcontrol_chip(kcontrol);
struct snd_us16x08_meter_store *store = elem->private_data;
int val;
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 8954be23325c..eafc0d73cca1 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -3187,6 +3187,57 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
}
},
+{
+ /*
+ * Pioneer DJ DJM-V10
+ */
+ USB_DEVICE_VENDOR_SPEC(0x2b73, 0x0034),
+ QUIRK_DRIVER_INFO {
+ QUIRK_DATA_COMPOSITE {
+ {
+ QUIRK_DATA_AUDIOFORMAT(0) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 12, // outputs
+ .iface = 0,
+ .altsetting = 1,
+ .altset_idx = 1,
+ .endpoint = 0x01,
+ .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 }
+ }
+ },
+ {
+ QUIRK_DATA_AUDIOFORMAT(0) {
+ .formats = SNDRV_PCM_FMTBIT_S24_3LE,
+ .channels = 12, // 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_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 }
+ }
+ },
+ QUIRK_COMPOSITE_END
+ }
+ }
+},
/*
* MacroSilicon MS2100/MS2106 based AV capture cards
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index dbbc9eb935a4..bd24f3a78ea9 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1872,6 +1872,7 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
break;
case USB_ID(0x2b73, 0x000a): /* Pioneer DJM-900NXS2 */
case USB_ID(0x2b73, 0x0013): /* Pioneer DJM-450 */
+ case USB_ID(0x2b73, 0x0034): /* Pioneer DJM-V10 */
pioneer_djm_set_format_quirk(subs, 0x0082);
break;
case USB_ID(0x08e4, 0x017f): /* Pioneer DJM-750 */
@@ -2284,6 +2285,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_DISABLE_AUTOSUSPEND),
DEVICE_FLG(0x17aa, 0x104d, /* Lenovo ThinkStation P620 Internal Speaker + Front Headset */
QUIRK_FLAG_DISABLE_AUTOSUSPEND),
+ DEVICE_FLG(0x17ef, 0x3083, /* Lenovo TBT3 dock */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x1852, 0x5062, /* Luxman D-08u */
QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
DEVICE_FLG(0x1852, 0x5065, /* Luxman DA-06 */
diff --git a/sound/virtio/virtio_kctl.c b/sound/virtio/virtio_kctl.c
index 7aa79c05b464..ffb903d56297 100644
--- a/sound/virtio/virtio_kctl.c
+++ b/sound/virtio/virtio_kctl.c
@@ -47,7 +47,7 @@ static const unsigned int g_v2a_mask_map[] = {
static int virtsnd_kctl_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- struct virtio_snd *snd = kcontrol->private_data;
+ struct virtio_snd *snd = snd_kcontrol_chip(kcontrol);
struct virtio_kctl *kctl = &snd->kctls[kcontrol->private_value];
struct virtio_snd_ctl_info *kinfo =
&snd->kctl_infos[kcontrol->private_value];
@@ -102,7 +102,7 @@ static int virtsnd_kctl_info(struct snd_kcontrol *kcontrol,
static int virtsnd_kctl_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *uvalue)
{
- struct virtio_snd *snd = kcontrol->private_data;
+ struct virtio_snd *snd = snd_kcontrol_chip(kcontrol);
struct virtio_snd_ctl_info *kinfo =
&snd->kctl_infos[kcontrol->private_value];
unsigned int type = le32_to_cpu(kinfo->type);
@@ -175,7 +175,7 @@ on_failure:
static int virtsnd_kctl_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *uvalue)
{
- struct virtio_snd *snd = kcontrol->private_data;
+ struct virtio_snd *snd = snd_kcontrol_chip(kcontrol);
struct virtio_snd_ctl_info *kinfo =
&snd->kctl_infos[kcontrol->private_value];
unsigned int type = le32_to_cpu(kinfo->type);
@@ -239,7 +239,7 @@ static int virtsnd_kctl_put(struct snd_kcontrol *kcontrol,
static int virtsnd_kctl_tlv_op(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *utlv)
{
- struct virtio_snd *snd = kcontrol->private_data;
+ struct virtio_snd *snd = snd_kcontrol_chip(kcontrol);
struct virtio_snd_msg *msg;
struct virtio_snd_ctl_hdr *hdr;
unsigned int *tlv;
diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c
index 7fcc528a0204..fe5cb4139088 100644
--- a/sound/x86/intel_hdmi_audio.c
+++ b/sound/x86/intel_hdmi_audio.c
@@ -22,6 +22,7 @@
#include <linux/pm_runtime.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
+#include <linux/string.h>
#include <sound/core.h>
#include <sound/asoundef.h>
#include <sound/pcm.h>
@@ -1698,9 +1699,9 @@ static int __hdmi_lpe_audio_probe(struct platform_device *pdev)
card_ctx = card->private_data;
card_ctx->dev = &pdev->dev;
card_ctx->card = card;
- strcpy(card->driver, INTEL_HAD);
- strcpy(card->shortname, "Intel HDMI/DP LPE Audio");
- strcpy(card->longname, "Intel HDMI/DP LPE Audio");
+ strscpy(card->driver, INTEL_HAD);
+ strscpy(card->shortname, "Intel HDMI/DP LPE Audio");
+ strscpy(card->longname, "Intel HDMI/DP LPE Audio");
card_ctx->irq = -1;