diff options
Diffstat (limited to 'include/sound')
120 files changed, 5737 insertions, 1448 deletions
diff --git a/include/sound/ac97/codec.h b/include/sound/ac97/codec.h index 2fc641cb1982..882b849b9255 100644 --- a/include/sound/ac97/codec.h +++ b/include/sound/ac97/codec.h @@ -73,10 +73,7 @@ static inline struct ac97_codec_device *to_ac97_device(struct device *d) return container_of(d, struct ac97_codec_device, dev); } -static inline struct ac97_codec_driver *to_ac97_driver(struct device_driver *d) -{ - return container_of(d, struct ac97_codec_driver, driver); -} +#define to_ac97_driver(__drv) container_of_const(__drv, struct ac97_codec_driver, driver) #if IS_ENABLED(CONFIG_AC97_BUS_NEW) int snd_ac97_codec_driver_register(struct ac97_codec_driver *drv); diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h index c495c6d5fbe0..4bd3be3a3192 100644 --- a/include/sound/ac97_codec.h +++ b/include/sound/ac97_codec.h @@ -410,7 +410,7 @@ int snd_ac97_pcm_close(struct ac97_pcm *pcm); int snd_ac97_pcm_double_rate_rules(struct snd_pcm_runtime *runtime); /* ad hoc AC97 device driver access */ -extern struct bus_type ac97_bus_type; +extern const struct bus_type ac97_bus_type; /* AC97 platform_data adding function */ static inline void snd_ac97_dev_add_pdata(struct snd_ac97 *ac97, void *data) diff --git a/include/sound/aci.h b/include/sound/aci.h index 6ebbd4223f12..36a761c9820d 100644 --- a/include/sound/aci.h +++ b/include/sound/aci.h @@ -72,6 +72,7 @@ #define ACI_SET_EQ7 0x46 /* ... to Treble */ struct snd_miro_aci { + struct snd_card *card; unsigned long aci_port; int aci_vendor; int aci_product; diff --git a/include/sound/adau1373.h b/include/sound/adau1373.h deleted file mode 100644 index 4c32ba1328ed..000000000000 --- a/include/sound/adau1373.h +++ /dev/null @@ -1,33 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -/* - * Analog Devices ADAU1373 Audio Codec drive - * - * Copyright 2011 Analog Devices Inc. - * Author: Lars-Peter Clausen <lars@metafoo.de> - */ - -#ifndef __SOUND_ADAU1373_H__ -#define __SOUND_ADAU1373_H__ - -enum adau1373_micbias_voltage { - ADAU1373_MICBIAS_2_9V = 0, - ADAU1373_MICBIAS_2_2V = 1, - ADAU1373_MICBIAS_2_6V = 2, - ADAU1373_MICBIAS_1_8V = 3, -}; - -#define ADAU1373_DRC_SIZE 13 - -struct adau1373_platform_data { - bool input_differential[4]; - bool lineout_differential; - bool lineout_ground_sense; - - unsigned int num_drc; - uint8_t drc_setting[3][ADAU1373_DRC_SIZE]; - - enum adau1373_micbias_voltage micbias1; - enum adau1373_micbias_voltage micbias2; -}; - -#endif diff --git a/include/sound/ak4531_codec.h b/include/sound/ak4531_codec.h index 9a4429970d92..64402347d7a2 100644 --- a/include/sound/ak4531_codec.h +++ b/include/sound/ak4531_codec.h @@ -65,6 +65,9 @@ int snd_ak4531_mixer(struct snd_card *card, struct snd_ak4531 *_ak4531, #ifdef CONFIG_PM void snd_ak4531_suspend(struct snd_ak4531 *ak4531); void snd_ak4531_resume(struct snd_ak4531 *ak4531); +#else +static inline void snd_ak4531_suspend(struct snd_ak4531 *ak4531) {} +static inline void snd_ak4531_resume(struct snd_ak4531 *ak4531) {} #endif #endif /* __SOUND_AK4531_CODEC_H */ diff --git a/include/sound/asoundef.h b/include/sound/asoundef.h index 9fdeac19dadb..c4a929d4fd51 100644 --- a/include/sound/asoundef.h +++ b/include/sound/asoundef.h @@ -12,6 +12,15 @@ * Digital audio interface * * * ****************************************************************************/ +/* IEC958 subframe format */ +#define IEC958_SUBFRAME_PREAMBLE_MASK (0xfU) +#define IEC958_SUBFRAME_AUXILIARY_MASK (0xfU << 4) +#define IEC958_SUBFRAME_SAMPLE_24_MASK (0xffffffU << 4) +#define IEC958_SUBFRAME_SAMPLE_20_MASK (0xfffffU << 8) +#define IEC958_SUBFRAME_VALIDITY (0x1U << 28) +#define IEC958_SUBFRAME_USER_DATA (0x1U << 29) +#define IEC958_SUBFRAME_CHANNEL_STATUS (0x1U << 30) +#define IEC958_SUBFRAME_PARITY (0x1U << 31) /* AES/IEC958 channel status bits */ #define IEC958_AES0_PROFESSIONAL (1<<0) /* 0 = consumer, 1 = professional */ @@ -110,18 +119,22 @@ #define IEC958_AES2_CON_SOURCE_UNSPEC (0<<0) /* unspecified */ #define IEC958_AES2_CON_CHANNEL (15<<4) /* mask - channel number */ #define IEC958_AES2_CON_CHANNEL_UNSPEC (0<<4) /* unspecified */ -#define IEC958_AES3_CON_FS (15<<0) /* mask - sample frequency */ +#define IEC958_AES3_CON_FS ((1<<7) | (15<<0)) /* mask - sample frequency */ #define IEC958_AES3_CON_FS_44100 (0<<0) /* 44.1kHz */ #define IEC958_AES3_CON_FS_NOTID (1<<0) /* non indicated */ #define IEC958_AES3_CON_FS_48000 (2<<0) /* 48kHz */ #define IEC958_AES3_CON_FS_32000 (3<<0) /* 32kHz */ #define IEC958_AES3_CON_FS_22050 (4<<0) /* 22.05kHz */ +#define IEC958_AES3_CON_FS_384000 (5<<0) /* 384kHz */ #define IEC958_AES3_CON_FS_24000 (6<<0) /* 24kHz */ #define IEC958_AES3_CON_FS_88200 (8<<0) /* 88.2kHz */ #define IEC958_AES3_CON_FS_768000 (9<<0) /* 768kHz */ #define IEC958_AES3_CON_FS_96000 (10<<0) /* 96kHz */ #define IEC958_AES3_CON_FS_176400 (12<<0) /* 176.4kHz */ +#define IEC958_AES3_CON_FS_352400 (13<<0) /* 352.4kHz */ #define IEC958_AES3_CON_FS_192000 (14<<0) /* 192kHz */ +#define IEC958_AES3_CON_FS_128000 ((1<<7) | (11<<0)) /* 128kHz */ +#define IEC958_AES3_CON_FS_705600 ((1<<7) | (13<<0)) /* 705.6kHz */ #define IEC958_AES3_CON_CLOCK (3<<4) /* mask - clock accuracy */ #define IEC958_AES3_CON_CLOCK_1000PPM (0<<4) /* 1000 ppm */ #define IEC958_AES3_CON_CLOCK_50PPM (1<<4) /* 50 ppm */ diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index d91289c6f00e..9e3d801e45ec 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -20,6 +20,30 @@ struct snd_compr_ops; /** + * struct snd_compr_task_runtime: task runtime description + * @list: list of all managed tasks + * @input: input DMA buffer + * @output: output DMA buffer + * @seqno: sequence number + * @input_size: really used data in the input buffer + * @output_size: really used data in the output buffer + * @flags: see SND_COMPRESS_TFLG_* + * @state: actual task state + * @private_value: used by the lowlevel driver (opaque) + */ +struct snd_compr_task_runtime { + struct list_head list; + struct dma_buf *input; + struct dma_buf *output; + u64 seqno; + u64 input_size; + u64 output_size; + u32 flags; + u8 state; + void *private_value; +}; + +/** * struct snd_compr_runtime: runtime stream description * @state: stream state * @ops: pointer to DSP callbacks @@ -37,6 +61,10 @@ struct snd_compr_ops; * @dma_addr: physical buffer address (not accessible from main CPU) * @dma_bytes: size of DMA area * @dma_buffer_p: runtime dma buffer pointer + * @active_tasks: count of active tasks + * @total_tasks: count of all tasks + * @task_seqno: last task sequence number (!= 0) + * @tasks: list of all tasks */ struct snd_compr_runtime { snd_pcm_state_t state; @@ -54,6 +82,13 @@ struct snd_compr_runtime { dma_addr_t dma_addr; size_t dma_bytes; struct snd_dma_buffer *dma_buffer_p; + +#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL) + u32 active_tasks; + u32 total_tasks; + u64 task_seqno; + struct list_head tasks; +#endif }; /** @@ -108,6 +143,10 @@ struct snd_compr_stream { * Not valid if copy is implemented * @get_caps: Retrieve DSP capabilities, mandatory * @get_codec_caps: Retrieve capabilities for a specific codec, mandatory + * @task_create: Create a set of input/output buffers for accel operations + * @task_start: Start (queue) a task for accel operations + * @task_stop: Stop (dequeue) a task for accel operations + * @task_free: Free a set of input/output buffers for accel operations */ struct snd_compr_ops { int (*open)(struct snd_compr_stream *stream); @@ -122,7 +161,7 @@ struct snd_compr_ops { struct snd_compr_metadata *metadata); int (*trigger)(struct snd_compr_stream *stream, int cmd); int (*pointer)(struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp); + struct snd_compr_tstamp64 *tstamp); int (*copy)(struct snd_compr_stream *stream, char __user *buf, size_t count); int (*mmap)(struct snd_compr_stream *stream, @@ -132,6 +171,12 @@ struct snd_compr_ops { struct snd_compr_caps *caps); int (*get_codec_caps) (struct snd_compr_stream *stream, struct snd_compr_codec_caps *codec); +#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL) + int (*task_create) (struct snd_compr_stream *stream, struct snd_compr_task_runtime *task); + int (*task_start) (struct snd_compr_stream *stream, struct snd_compr_task_runtime *task); + int (*task_stop) (struct snd_compr_stream *stream, struct snd_compr_task_runtime *task); + int (*task_free) (struct snd_compr_stream *stream, struct snd_compr_task_runtime *task); +#endif }; /** @@ -148,7 +193,7 @@ struct snd_compr_ops { */ struct snd_compr { const char *name; - struct device dev; + struct device *dev; struct snd_compr_ops *ops; void *private_data; struct snd_card *card; @@ -242,4 +287,9 @@ int snd_compr_free_pages(struct snd_compr_stream *stream); int snd_compr_stop_error(struct snd_compr_stream *stream, snd_pcm_state_t state); +#if IS_ENABLED(CONFIG_SND_COMPRESS_ACCEL) +void snd_compr_task_finished(struct snd_compr_stream *stream, + struct snd_compr_task_runtime *task); +#endif + #endif diff --git a/include/sound/control.h b/include/sound/control.h index cc3dcc6cfb0f..e07f6b960641 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -81,7 +81,7 @@ struct snd_kcontrol { unsigned long private_value; void *private_data; void (*private_free)(struct snd_kcontrol *kcontrol); - struct snd_kcontrol_volatile vd[]; /* volatile data */ + struct snd_kcontrol_volatile vd[] __counted_by(count); /* volatile data */ }; #define snd_kcontrol(n) list_entry(n, struct snd_kcontrol, list) @@ -140,8 +140,30 @@ int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id); int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id); void snd_ctl_rename(struct snd_card *card, struct snd_kcontrol *kctl, const char *name); int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, int active); -struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid); -struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id); +struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid); +struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, const struct snd_ctl_elem_id *id); + +/** + * snd_ctl_find_id_mixer - find the control instance with the given name string + * @card: the card instance + * @name: the name string + * + * Finds the control instance with the given name and + * @SNDRV_CTL_ELEM_IFACE_MIXER. Other fields are set to zero. + * + * This is merely a wrapper to snd_ctl_find_id(). + * + * Return: The pointer of the instance if found, or %NULL if not. + */ +static inline struct snd_kcontrol * +snd_ctl_find_id_mixer(struct snd_card *card, const char *name) +{ + struct snd_ctl_elem_id id = {}; + + id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + strscpy(id.name, name, sizeof(id.name)); + return snd_ctl_find_id(card, &id); +} int snd_ctl_create(struct snd_card *card); @@ -238,6 +260,9 @@ snd_ctl_add_follower(struct snd_kcontrol *master, struct snd_kcontrol *follower) return _snd_ctl_add_follower(master, follower, 0); } +int snd_ctl_add_followers(struct snd_card *card, struct snd_kcontrol *master, + const char * const *list); + /** * snd_ctl_add_follower_uncached - Add a virtual follower control * @master: vmaster element diff --git a/include/sound/core.h b/include/sound/core.h index f6e0dd648b80..64327e971122 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -96,10 +96,10 @@ struct snd_card { private data */ struct list_head devices; /* devices */ - struct device ctl_dev; /* control device */ + struct device *ctl_dev; /* control device */ unsigned int last_numid; /* last used numeric ID */ struct rw_semaphore controls_rwsem; /* controls lock (list and values) */ - rwlock_t ctl_files_rwlock; /* ctl_files list lock */ + rwlock_t controls_rwlock; /* lock for lookup and ctl_files list */ int controls_count; /* count of all controls */ size_t user_ctl_alloc_size; // current memory allocation by user controls. struct list_head controls; /* all controls for this card */ @@ -239,7 +239,7 @@ extern struct dentry *sound_debugfs_root; void snd_request_card(int card); -void snd_device_initialize(struct device *dev, struct snd_card *card); +int snd_device_alloc(struct device **dev_p, struct snd_card *card); int snd_register_device(int type, struct snd_card *card, int dev, const struct file_operations *f_ops, @@ -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 */ @@ -345,46 +344,8 @@ void release_and_free_resource(struct resource *res); /* --- */ -/* sound printk debug levels */ -enum { - SND_PR_ALWAYS, - SND_PR_DEBUG, - SND_PR_VERBOSE, -}; - -#if defined(CONFIG_SND_DEBUG) || defined(CONFIG_SND_VERBOSE_PRINTK) -__printf(4, 5) -void __snd_printk(unsigned int level, const char *file, int line, - const char *format, ...); -#else -#define __snd_printk(level, file, line, format, ...) \ - printk(format, ##__VA_ARGS__) -#endif - -/** - * snd_printk - printk wrapper - * @fmt: format string - * - * Works like printk() but prints the file and the line of the caller - * when configured with CONFIG_SND_VERBOSE_PRINTK. - */ -#define snd_printk(fmt, ...) \ - __snd_printk(0, __FILE__, __LINE__, fmt, ##__VA_ARGS__) - #ifdef CONFIG_SND_DEBUG /** - * snd_printd - debug printk - * @fmt: format string - * - * Works like snd_printk() for debugging purposes. - * Ignored when CONFIG_SND_DEBUG is not set. - */ -#define snd_printd(fmt, ...) \ - __snd_printk(1, __FILE__, __LINE__, fmt, ##__VA_ARGS__) -#define _snd_printd(level, fmt, ...) \ - __snd_printk(level, __FILE__, __LINE__, fmt, ##__VA_ARGS__) - -/** * snd_BUG - give a BUG warning message and stack trace * * Calls WARN() if CONFIG_SND_DEBUG is set. @@ -393,12 +354,6 @@ void __snd_printk(unsigned int level, const char *file, int line, #define snd_BUG() WARN(1, "BUG?\n") /** - * snd_printd_ratelimit - Suppress high rates of output when - * CONFIG_SND_DEBUG is enabled. - */ -#define snd_printd_ratelimit() printk_ratelimit() - -/** * snd_BUG_ON - debugging check macro * @cond: condition to evaluate * @@ -409,11 +364,6 @@ void __snd_printk(unsigned int level, const char *file, int line, #else /* !CONFIG_SND_DEBUG */ -__printf(1, 2) -static inline void snd_printd(const char *format, ...) {} -__printf(2, 3) -static inline void _snd_printd(int level, const char *format, ...) {} - #define snd_BUG() do { } while (0) #define snd_BUG_ON(condition) ({ \ @@ -421,26 +371,8 @@ static inline void _snd_printd(int level, const char *format, ...) {} unlikely(__ret_warn_on); \ }) -static inline bool snd_printd_ratelimit(void) { return false; } - #endif /* CONFIG_SND_DEBUG */ -#ifdef CONFIG_SND_DEBUG_VERBOSE -/** - * snd_printdd - debug printk - * @format: format string - * - * Works like snd_printk() for debugging purposes. - * Ignored when CONFIG_SND_DEBUG_VERBOSE is not set. - */ -#define snd_printdd(format, ...) \ - __snd_printk(2, __FILE__, __LINE__, format, ##__VA_ARGS__) -#else -__printf(1, 2) -static inline void snd_printdd(const char *format, ...) {} -#endif - - #define SNDRV_OSS_VERSION ((3<<16)|(8<<8)|(1<<4)|(0)) /* 3.8.1a */ /* for easier backward-porting */ diff --git a/include/sound/cs-amp-lib.h b/include/sound/cs-amp-lib.h new file mode 100644 index 000000000000..61e00017c9aa --- /dev/null +++ b/include/sound/cs-amp-lib.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2024 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef CS_AMP_LIB_H +#define CS_AMP_LIB_H + +#include <linux/efi.h> +#include <linux/types.h> + +struct cs_dsp; + +struct cirrus_amp_cal_data { + u32 calTarget[2]; + u32 calTime[2]; + s8 calAmbient; + u8 calStatus; + u16 calR; +} __packed; + +struct cirrus_amp_efi_data { + u32 size; + u32 count; + struct cirrus_amp_cal_data data[] __counted_by(count); +} __packed; + +/** + * struct cirrus_amp_cal_controls - definition of firmware calibration controls + * @alg_id: ID of algorithm containing the controls. + * @mem_region: DSP memory region containing the controls. + * @ambient: Name of control for calAmbient value. + * @calr: Name of control for calR value. + * @status: Name of control for calStatus value. + * @checksum: Name of control for checksum value. + */ +struct cirrus_amp_cal_controls { + unsigned int alg_id; + int mem_region; + const char *ambient; + const char *calr; + const char *status; + const char *checksum; +}; + +int cs_amp_write_cal_coeffs(struct cs_dsp *dsp, + const struct cirrus_amp_cal_controls *controls, + const struct cirrus_amp_cal_data *data); +int cs_amp_read_cal_coeffs(struct cs_dsp *dsp, + const struct cirrus_amp_cal_controls *controls, + struct cirrus_amp_cal_data *data); +int cs_amp_write_ambient_temp(struct cs_dsp *dsp, + const struct cirrus_amp_cal_controls *controls, + u32 temp); +int cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid, int amp_index, + struct cirrus_amp_cal_data *out_data); +int cs_amp_set_efi_calibration_data(struct device *dev, int amp_index, int num_amps, + const struct cirrus_amp_cal_data *in_data); +int cs_amp_get_vendor_spkid(struct device *dev); +struct dentry *cs_amp_create_debugfs(struct device *dev); + +static inline u64 cs_amp_cal_target_u64(const struct cirrus_amp_cal_data *data) +{ + return ((u64)data->calTarget[1] << 32) | data->calTarget[0]; +} + +struct cs_amp_test_hooks { + efi_status_t (*get_efi_variable)(efi_char16_t *name, + efi_guid_t *guid, + u32 *returned_attr, + unsigned long *size, + void *buf); + efi_status_t (*set_efi_variable)(efi_char16_t *name, + efi_guid_t *guid, + u32 attr, + unsigned long size, + void *buf); + + int (*write_cal_coeff)(struct cs_dsp *dsp, + const struct cirrus_amp_cal_controls *controls, + const char *ctl_name, u32 val); + + int (*read_cal_coeff)(struct cs_dsp *dsp, + const struct cirrus_amp_cal_controls *controls, + const char *ctl_name, u32 *val); +}; +extern const struct cs_amp_test_hooks * const cs_amp_test_hooks; + +#endif /* CS_AMP_LIB_H */ diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h index 7239d943942c..7542cabfa726 100644 --- a/include/sound/cs35l41.h +++ b/include/sound/cs35l41.h @@ -11,7 +11,6 @@ #define __CS35L41_H #include <linux/regmap.h> -#include <linux/completion.h> #include <linux/firmware/cirrus/cs_dsp.h> #define CS35L41_FIRSTREG 0x00000000 @@ -555,6 +554,11 @@ #define CS35L41_LRCLK_FRC_SHIFT 1 #define CS35L41_AMP_GAIN_PCM_MASK 0x3E0 +#define CS35L41_AMP_GAIN_PCM_SHIFT 5 +#define CS35L41_AMP_GAIN_PDM_MASK 0x1F +#define CS35L41_AMP_GAIN_PDM_SHIFT 0 +#define CS35L41_AMP_GAIN_PCM_MAX 20 +#define CS35L41_AMP_GAIN_PDM_MAX 20 #define CS35L41_AMP_GAIN_ZC_MASK 0x0400 #define CS35L41_AMP_GAIN_ZC_SHIFT 10 @@ -605,6 +609,18 @@ #define CS35L41_DSP_NG_DELAY_MASK 0x0F00 #define CS35L41_DSP_NG_DELAY_SHIFT 8 +#define CS35L41_ASP_RX1_EN_MASK 0x00010000 +#define CS35L41_ASP_RX1_EN_SHIFT 16 +#define CS35L41_ASP_RX2_EN_MASK 0x00020000 +#define CS35L41_ASP_RX2_EN_SHIFT 17 +#define CS35L41_ASP_TX1_EN_MASK 0x00000001 +#define CS35L41_ASP_TX1_EN_SHIFT 0 +#define CS35L41_ASP_TX2_EN_MASK 0x00000002 +#define CS35L41_ASP_TX2_EN_SHIFT 1 +#define CS35L41_ASP_TX3_EN_MASK 0x00000004 +#define CS35L41_ASP_TX3_EN_SHIFT 2 +#define CS35L41_ASP_TX4_EN_MASK 0x00000008 +#define CS35L41_ASP_TX4_EN_SHIFT 3 #define CS35L41_ASP_FMT_MASK 0x0700 #define CS35L41_ASP_FMT_SHIFT 8 #define CS35L41_ASP_DOUT_HIZ_MASK 0x03 @@ -736,6 +752,7 @@ #define CS35L41_REVID_B2 0xB2 #define CS35L41_HALO_CORE_RESET 0x00000200 +#define CS35L41_SOFTWARE_RESET 0x5A000000 #define CS35L41_FS1_WINDOW_MASK 0x000007FF #define CS35L41_FS2_WINDOW_MASK 0x00FFF800 @@ -816,6 +833,8 @@ struct cs35l41_otp_map_element_t { }; enum cs35l41_cspl_mbox_status { + CSPL_MBOX_STS_ERROR = U32_MAX, + CSPL_MBOX_STS_ERROR2 = 0x00ffffff, // firmware not always sign-extending 24-bit value CSPL_MBOX_STS_RUNNING = 0, CSPL_MBOX_STS_PAUSED = 1, CSPL_MBOX_STS_RDY_FOR_REINIT = 2, @@ -829,6 +848,7 @@ enum cs35l41_cspl_mbox_cmd { CSPL_MBOX_CMD_STOP_PRE_REINIT = 4, CSPL_MBOX_CMD_HIBERNATE = 5, CSPL_MBOX_CMD_OUT_OF_HIBERNATE = 6, + CSPL_MBOX_CMD_SPK_OUT_ENABLE = 7, CSPL_MBOX_CMD_UNKNOWN_CMD = -1, CSPL_MBOX_CMD_INVALID_SEQUENCE = -2, }; @@ -888,8 +908,8 @@ int cs35l41_test_key_lock(struct device *dev, struct regmap *regmap); int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap); int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsigned int reg_revid); int cs35l41_set_channels(struct device *dev, struct regmap *reg, - unsigned int tx_num, unsigned int *tx_slot, - unsigned int rx_num, unsigned int *rx_slot); + unsigned int tx_num, const unsigned int *tx_slot, + unsigned int rx_num, const unsigned int *rx_slot); int cs35l41_gpio_config(struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg); void cs35l41_configure_cs_dsp(struct device *dev, struct regmap *reg, struct cs_dsp *dsp); int cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap, @@ -901,7 +921,8 @@ int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap); int cs35l41_init_boost(struct device *dev, struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg); bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type); -int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable, - struct completion *pll_lock); +int cs35l41_mdsync_up(struct regmap *regmap); +int cs35l41_global_enable(struct device *dev, struct regmap *regmap, enum cs35l41_boost_type b_type, + int enable, struct cs_dsp *dsp); #endif /* __CS35L41_H */ diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h index 1f9713d7ca76..5928af539c46 100644 --- a/include/sound/cs35l56.h +++ b/include/sound/cs35l56.h @@ -9,9 +9,14 @@ #ifndef __CS35L56_H #define __CS35L56_H +#include <linux/debugfs.h> #include <linux/firmware/cirrus/cs_dsp.h> #include <linux/regulator/consumer.h> #include <linux/regmap.h> +#include <linux/spi/spi.h> +#include <sound/cs-amp-lib.h> + +struct snd_ctl_elem_value; #define CS35L56_DEVID 0x0000000 #define CS35L56_REVID 0x0000004 @@ -23,6 +28,9 @@ #define CS35L56_BLOCK_ENABLES2 0x000201C #define CS35L56_REFCLK_INPUT 0x0002C04 #define CS35L56_GLOBAL_SAMPLE_RATE 0x0002C0C +#define CS35L56_OTP_MEM_53 0x00300D4 +#define CS35L56_OTP_MEM_54 0x00300D8 +#define CS35L56_OTP_MEM_55 0x00300DC #define CS35L56_ASP1_ENABLES1 0x0004800 #define CS35L56_ASP1_CONTROL1 0x0004804 #define CS35L56_ASP1_CONTROL2 0x0004808 @@ -57,6 +65,9 @@ #define CS35L56_IRQ1_MASK_8 0x000E0AC #define CS35L56_IRQ1_MASK_18 0x000E0D4 #define CS35L56_IRQ1_MASK_20 0x000E0DC +#define CS35L56_MIXER_NGATE_CH1_CFG 0x0010004 +#define CS35L56_MIXER_NGATE_CH2_CFG 0x0010008 +#define CS35L56_DSP_MBOX_1_RAW 0x0011000 #define CS35L56_DSP_VIRTUAL1_MBOX_1 0x0011020 #define CS35L56_DSP_VIRTUAL1_MBOX_2 0x0011024 #define CS35L56_DSP_VIRTUAL1_MBOX_3 0x0011028 @@ -65,6 +76,8 @@ #define CS35L56_DSP_VIRTUAL1_MBOX_6 0x0011034 #define CS35L56_DSP_VIRTUAL1_MBOX_7 0x0011038 #define CS35L56_DSP_VIRTUAL1_MBOX_8 0x001103C +#define CS35L56_DIE_STS1 0x0017040 +#define CS35L56_DIE_STS2 0x0017044 #define CS35L56_DSP_RESTRICT_STS1 0x00190F0 #define CS35L56_DSP1_XMEM_PACKED_0 0x2000000 #define CS35L56_DSP1_XMEM_PACKED_6143 0x2005FFC @@ -75,10 +88,11 @@ #define CS35L56_DSP1_AHBM_WINDOW_DEBUG_0 0x25E2040 #define CS35L56_DSP1_AHBM_WINDOW_DEBUG_1 0x25E2044 #define CS35L56_DSP1_XMEM_UNPACKED24_0 0x2800000 -#define CS35L56_DSP1_HALO_STATE_A1 0x2801E58 +#define CS35L56_DSP1_FW_VER 0x2800010 #define CS35L56_DSP1_HALO_STATE 0x28021E0 -#define CS35L56_DSP1_PM_CUR_STATE_A1 0x2804000 +#define CS35L56_B2_DSP1_HALO_STATE 0x2803D20 #define CS35L56_DSP1_PM_CUR_STATE 0x2804308 +#define CS35L56_B2_DSP1_PM_CUR_STATE 0x2804678 #define CS35L56_DSP1_XMEM_UNPACKED24_8191 0x2807FFC #define CS35L56_DSP1_CORE_BASE 0x2B80000 #define CS35L56_DSP1_SCRATCH1 0x2B805C0 @@ -99,6 +113,15 @@ #define CS35L56_DSP1_PMEM_0 0x3800000 #define CS35L56_DSP1_PMEM_5114 0x3804FE8 +#define CS35L63_DSP1_FW_VER CS35L56_DSP1_FW_VER +#define CS35L63_DSP1_HALO_STATE 0x2803C04 +#define CS35L63_DSP1_PM_CUR_STATE 0x2804518 +#define CS35L63_PROTECTION_STATUS 0x340009C +#define CS35L63_TRANSDUCER_ACTUAL_PS 0x34000F4 +#define CS35L63_MAIN_RENDER_USER_MUTE 0x3400020 +#define CS35L63_MAIN_RENDER_USER_VOLUME 0x3400028 +#define CS35L63_MAIN_POSTURE_NUMBER 0x3400068 + /* DEVID */ #define CS35L56_DEVID_MASK 0x00FFFFFF @@ -159,6 +182,9 @@ /* IRQ1_EINT_8 */ #define CS35L56_TEMP_ERR_EINT1_MASK 0x80000000 +/* MIXER_NGATE_CHn_CFG */ +#define CS35L56_AUX_NGATE_CHn_EN 0x00000001 + /* Mixer input sources */ #define CS35L56_INPUT_SRC_NONE 0x00 #define CS35L56_INPUT_SRC_ASP1RX1 0x08 @@ -204,7 +230,7 @@ /* CS35L56_MAIN_RENDER_USER_VOLUME */ #define CS35L56_MAIN_RENDER_USER_VOLUME_MIN -400 -#define CS35L56_MAIN_RENDER_USER_VOLUME_MAX 400 +#define CS35L56_MAIN_RENDER_USER_VOLUME_MAX 48 #define CS35L56_MAIN_RENDER_USER_VOLUME_MASK 0x0000FFC0 #define CS35L56_MAIN_RENDER_USER_VOLUME_SHIFT 6 #define CS35L56_MAIN_RENDER_USER_VOLUME_SIGNBIT 9 @@ -221,9 +247,11 @@ #define CS35L56_HALO_STATE_SHUTDOWN 1 #define CS35L56_HALO_STATE_BOOT_DONE 2 +#define CS35L56_MBOX_CMD_PING 0x0A000000 #define CS35L56_MBOX_CMD_AUDIO_PLAY 0x0B000001 #define CS35L56_MBOX_CMD_AUDIO_PAUSE 0x0B000002 #define CS35L56_MBOX_CMD_AUDIO_REINIT 0x0B000003 +#define CS35L56_MBOX_CMD_AUDIO_CALIBRATION 0x0B000006 #define CS35L56_MBOX_CMD_HIBERNATE_NOW 0x02000001 #define CS35L56_MBOX_CMD_WAKEUP 0x02000002 #define CS35L56_MBOX_CMD_PREVENT_AUTO_HIBERNATE 0x02000003 @@ -239,12 +267,21 @@ #define CS35L56_PS3_POLL_US 500 #define CS35L56_PS3_TIMEOUT_US 300000 +#define CS35L56_CAL_STATUS_SUCCESS 1 +#define CS35L56_CAL_STATUS_OUT_OF_RANGE 3 + +#define CS35L56_CAL_SET_STATUS_UNKNOWN 0 +#define CS35L56_CAL_SET_STATUS_DEFAULT 1 +#define CS35L56_CAL_SET_STATUS_SET 2 + #define CS35L56_CONTROL_PORT_READY_US 2200 #define CS35L56_HALO_STATE_POLL_US 1000 -#define CS35L56_HALO_STATE_TIMEOUT_US 50000 -#define CS35L56_HIBERNATE_WAKE_POLL_US 500 -#define CS35L56_HIBERNATE_WAKE_TIMEOUT_US 5000 +#define CS35L56_HALO_STATE_TIMEOUT_US 250000 #define CS35L56_RESET_PULSE_MIN_US 1100 +#define CS35L56_WAKE_HOLD_TIME_US 1000 + +#define CS35L56_CALIBRATION_POLL_US (100 * USEC_PER_MSEC) +#define CS35L56_CALIBRATION_TIMEOUT_US (5 * USEC_PER_SEC) #define CS35L56_SDW1_PLAYBACK_PORT 1 #define CS35L56_SDW1_CAPTURE_PORT 3 @@ -252,15 +289,130 @@ #define CS35L56_NUM_BULK_SUPPLIES 3 #define CS35L56_NUM_DSP_REGIONS 5 -extern struct regmap_config cs35l56_regmap_i2c; -extern struct regmap_config cs35l56_regmap_spi; -extern struct regmap_config cs35l56_regmap_sdw; +/* Additional margin for SYSTEM_RESET to control port ready on SPI */ +#define CS35L56_SPI_RESET_TO_PORT_READY_US (CS35L56_CONTROL_PORT_READY_US + 2500) + +struct cs35l56_spi_payload { + __be32 addr; + __be16 pad; + __be32 value; +} __packed; +static_assert(sizeof(struct cs35l56_spi_payload) == 10); + +struct cs35l56_fw_reg { + unsigned int fw_ver; + unsigned int halo_state; + unsigned int pm_cur_stat; + unsigned int prot_sts; + unsigned int transducer_actual_ps; + unsigned int user_mute; + unsigned int user_volume; + unsigned int posture_number; +}; + +struct cs35l56_cal_debugfs_fops { + const struct debugfs_short_fops calibrate; + const struct debugfs_short_fops cal_temperature; + const struct debugfs_short_fops cal_data; +}; + +struct cs35l56_base { + struct device *dev; + struct regmap *regmap; + struct cs_dsp *dsp; + int irq; + struct mutex irq_lock; + u8 type; + u8 rev; + bool init_done; + bool fw_patched; + bool secured; + bool can_hibernate; + bool cal_data_valid; + s8 cal_index; + u8 num_amps; + struct cirrus_amp_cal_data cal_data; + struct gpio_desc *reset_gpio; + struct cs35l56_spi_payload *spi_payload_buf; + const struct cs35l56_fw_reg *fw_reg; + const struct cirrus_amp_cal_controls *calibration_controls; + struct dentry *debugfs; + u64 silicon_uid; +}; + +static inline bool cs35l56_is_otp_register(unsigned int reg) +{ + return (reg >> 16) == 3; +} + +static inline int cs35l56_init_config_for_spi(struct cs35l56_base *cs35l56, + struct spi_device *spi) +{ + cs35l56->spi_payload_buf = devm_kzalloc(&spi->dev, + sizeof(*cs35l56->spi_payload_buf), + GFP_KERNEL | GFP_DMA); + if (!cs35l56->spi_payload_buf) + return -ENOMEM; + + return 0; +} + +static inline bool cs35l56_is_spi(struct cs35l56_base *cs35l56) +{ + return IS_ENABLED(CONFIG_SPI_MASTER) && !!cs35l56->spi_payload_buf; +} + +extern const struct regmap_config cs35l56_regmap_i2c; +extern const struct regmap_config cs35l56_regmap_spi; +extern const struct regmap_config cs35l56_regmap_sdw; +extern const struct regmap_config cs35l63_regmap_i2c; +extern const struct regmap_config cs35l63_regmap_sdw; + +extern const struct cirrus_amp_cal_controls cs35l56_calibration_controls; +extern const char * const cs35l56_cal_set_status_text[3]; -extern const struct cs_dsp_region cs35l56_dsp1_regions[CS35L56_NUM_DSP_REGIONS]; extern const char * const cs35l56_tx_input_texts[CS35L56_NUM_INPUT_SRC]; extern const unsigned int cs35l56_tx_input_values[CS35L56_NUM_INPUT_SRC]; -void cs35l56_reread_firmware_registers(struct device *dev, struct regmap *regmap); +int cs35l56_set_patch(struct cs35l56_base *cs35l56_base); +int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command); +int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base); +int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base); +void cs35l56_wait_control_port_ready(void); +void cs35l56_wait_min_reset_pulse(void); +void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire); +int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq); +irqreturn_t cs35l56_irq(int irq, void *data); +int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base); +int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base); +int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire); +void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp); +int cs35l56_get_calibration(struct cs35l56_base *cs35l56_base); +int cs35l56_stash_calibration(struct cs35l56_base *cs35l56_base, + const struct cirrus_amp_cal_data *data); +ssize_t cs35l56_calibrate_debugfs_write(struct cs35l56_base *cs35l56_base, + const char __user *from, size_t count, + loff_t *ppos); +ssize_t cs35l56_cal_ambient_debugfs_write(struct cs35l56_base *cs35l56_base, + const char __user *from, size_t count, + loff_t *ppos); +ssize_t cs35l56_cal_data_debugfs_read(struct cs35l56_base *cs35l56_base, + char __user *to, size_t count, + loff_t *ppos); +ssize_t cs35l56_cal_data_debugfs_write(struct cs35l56_base *cs35l56_base, + const char __user *from, size_t count, + loff_t *ppos); +void cs35l56_create_cal_debugfs(struct cs35l56_base *cs35l56_base, + const struct cs35l56_cal_debugfs_fops *fops); +void cs35l56_remove_cal_debugfs(struct cs35l56_base *cs35l56_base); +int cs35l56_cal_set_status_get(struct cs35l56_base *cs35l56_base, + struct snd_ctl_elem_value *uvalue); +int cs35l56_read_prot_status(struct cs35l56_base *cs35l56_base, + bool *fw_missing, unsigned int *fw_version); +void cs35l56_warn_if_firmware_missing(struct cs35l56_base *cs35l56_base); +void cs35l56_log_tuning(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_dsp); +int cs35l56_hw_init(struct cs35l56_base *cs35l56_base); +int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base); int cs35l56_get_bclk_freq_id(unsigned int freq); void cs35l56_fill_supply_names(struct regulator_bulk_data *data); diff --git a/include/sound/cs4271.h b/include/sound/cs4271.h index 6ff23ab48894..5a55d135bdea 100644 --- a/include/sound/cs4271.h +++ b/include/sound/cs4271.h @@ -9,7 +9,6 @@ #define __CS4271_H struct cs4271_platform_data { - int gpio_nreset; /* GPIO driving Reset pin, if any */ bool amutec_eq_bmutec; /* flag to enable AMUTEC=BMUTEC */ /* diff --git a/include/sound/cs42l42.h b/include/sound/cs42l42.h index 3994e933db19..1bd8eee54f66 100644 --- a/include/sound/cs42l42.h +++ b/include/sound/cs42l42.h @@ -809,8 +809,7 @@ #define CS42L42_PLL_LOCK_TIMEOUT_US 1250 #define CS42L42_HP_ADC_EN_TIME_US 20000 #define CS42L42_PDN_DONE_POLL_US 1000 -#define CS42L42_PDN_DONE_TIMEOUT_US 200000 -#define CS42L42_PDN_DONE_TIME_MS 100 -#define CS42L42_FILT_DISCHARGE_TIME_MS 46 +#define CS42L42_PDN_DONE_TIMEOUT_US 235000 +#define CS42L42_PDN_DONE_TIME_MS 65 #endif /* __CS42L42_H */ diff --git a/include/sound/cs42l43.h b/include/sound/cs42l43.h new file mode 100644 index 000000000000..deb337fc4e8c --- /dev/null +++ b/include/sound/cs42l43.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * CS42L43 CODEC driver external data + * + * Copyright (C) 2022-2023 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef CS42L43_ASOC_EXT_H +#define CS42L43_ASOC_EXT_H + +#define CS42L43_SYSCLK 0 + +#define CS42L43_SYSCLK_MCLK 0 +#define CS42L43_SYSCLK_SDW 1 + +#endif /* CS42L43_ASOC_EXT_H */ diff --git a/include/sound/cs42l52.h b/include/sound/cs42l52.h deleted file mode 100644 index c20649666abe..000000000000 --- a/include/sound/cs42l52.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/sound/cs42l52.h -- Platform data for CS42L52 - * - * Copyright (c) 2012 Cirrus Logic Inc. - */ - -#ifndef __CS42L52_H -#define __CS42L52_H - -struct cs42l52_platform_data { - - /* MICBIAS Level. Check datasheet Pg48 */ - unsigned int micbias_lvl; - - /* MICA mode selection Differential or Single-ended */ - bool mica_diff_cfg; - - /* MICB mode selection Differential or Single-ended */ - bool micb_diff_cfg; - - /* Charge Pump Freq. Check datasheet Pg73 */ - unsigned int chgfreq; - - /* Reset GPIO */ - unsigned int reset_gpio; -}; - -#endif /* __CS42L52_H */ diff --git a/include/sound/cs42l56.h b/include/sound/cs42l56.h deleted file mode 100644 index 62e9f7a3b414..000000000000 --- a/include/sound/cs42l56.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/sound/cs42l56.h -- Platform data for CS42L56 - * - * Copyright (c) 2014 Cirrus Logic Inc. - */ - -#ifndef __CS42L56_H -#define __CS42L56_H - -struct cs42l56_platform_data { - - /* GPIO for Reset */ - unsigned int gpio_nreset; - - /* MICBIAS Level. Check datasheet Pg48 */ - unsigned int micbias_lvl; - - /* Analog Input 1A Reference 0=Single 1=Pseudo-Differential */ - unsigned int ain1a_ref_cfg; - - /* Analog Input 2A Reference 0=Single 1=Pseudo-Differential */ - unsigned int ain2a_ref_cfg; - - /* Analog Input 1B Reference 0=Single 1=Pseudo-Differential */ - unsigned int ain1b_ref_cfg; - - /* Analog Input 2B Reference 0=Single 1=Pseudo-Differential */ - unsigned int ain2b_ref_cfg; - - /* Charge Pump Freq. Check datasheet Pg62 */ - unsigned int chgfreq; - - /* HighPass Filter Right Channel Corner Frequency */ - unsigned int hpfb_freq; - - /* HighPass Filter Left Channel Corner Frequency */ - unsigned int hpfa_freq; - - /* Adaptive Power Control for LO/HP */ - unsigned int adaptive_pwr; - -}; - -#endif /* __CS42L56_H */ diff --git a/include/sound/cs42l73.h b/include/sound/cs42l73.h deleted file mode 100644 index 5a93393b6124..000000000000 --- a/include/sound/cs42l73.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/sound/cs42l73.h -- Platform data for CS42L73 - * - * Copyright (c) 2012 Cirrus Logic Inc. - */ - -#ifndef __CS42L73_H -#define __CS42L73_H - -struct cs42l73_platform_data { - /* RST GPIO */ - unsigned int reset_gpio; - unsigned int chgfreq; - int jack_detection; - unsigned int mclk_freq; -}; - -#endif /* __CS42L73_H */ diff --git a/include/sound/cs48l32.h b/include/sound/cs48l32.h new file mode 100644 index 000000000000..27b3e7cf999a --- /dev/null +++ b/include/sound/cs48l32.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Register definitions for Cirrus Logic CS48L32 + * + * Copyright (C) 2017-2018, 2020, 2022, 2025 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef CS48L32_H +#define CS48L32_H + +/* pll_id for snd_soc_component_set_pll() */ +#define CS48L32_FLL1_REFCLK 1 + +/* source for snd_soc_component_set_pll() */ +#define CS48L32_FLL_SRC_NONE -1 +#define CS48L32_FLL_SRC_MCLK1 0 +#define CS48L32_FLL_SRC_PDMCLK 5 +#define CS48L32_FLL_SRC_ASP1_BCLK 8 +#define CS48L32_FLL_SRC_ASP2_BCLK 9 +#define CS48L32_FLL_SRC_ASP1_FSYNC 12 +#define CS48L32_FLL_SRC_ASP2_FSYNC 13 + +/* clk_id for snd_soc_component_set_sysclk() and snd_soc_dai_set_sysclk() */ +#define CS48L32_CLK_SYSCLK_1 1 +#define CS48L32_CLK_SYSCLK_2 2 +#define CS48L32_CLK_SYSCLK_3 3 +#define CS48L32_CLK_SYSCLK_4 4 +#define CS48L32_CLK_DSPCLK 7 +#define CS48L32_CLK_PDM_FLLCLK 13 + +/* source for snd_soc_component_set_sysclk() */ +#define CS48L32_CLK_SRC_MCLK1 0x0 +#define CS48L32_CLK_SRC_FLL1 0x4 +#define CS48L32_CLK_SRC_ASP1_BCLK 0x8 +#define CS48L32_CLK_SRC_ASP2_BCLK 0x9 + +struct cs48l32 { + struct regmap *regmap; + struct device *dev; + struct gpio_desc *reset_gpio; + struct clk *mclk1; + struct regulator_bulk_data core_supplies[2]; + struct regulator *vdd_d; + int irq; +}; +#endif diff --git a/include/sound/cs48l32_registers.h b/include/sound/cs48l32_registers.h new file mode 100644 index 000000000000..f29410fdf76f --- /dev/null +++ b/include/sound/cs48l32_registers.h @@ -0,0 +1,530 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Register definitions for Cirrus Logic CS48L32 + * + * Copyright (C) 2017-2018, 2020, 2022, 2025 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef CS48L32_REGISTERS_H +#define CS48L32_REGISTERS_H + +/* Register Addresses. */ +#define CS48L32_DEVID 0x0 +#define CS48L32_REVID 0x4 +#define CS48L32_OTPID 0x10 +#define CS48L32_SFT_RESET 0x20 +#define CS48L32_CTRL_IF_DEBUG3 0xA8 +#define CS48L32_MCU_CTRL1 0x804 +#define CS48L32_GPIO1_CTRL1 0xc08 +#define CS48L32_GPIO3_CTRL1 0xc10 +#define CS48L32_GPIO7_CTRL1 0xc20 +#define CS48L32_GPIO16_CTRL1 0xc44 +#define CS48L32_OUTPUT_SYS_CLK 0x1020 +#define CS48L32_AUXPDM_CTRL 0x1044 +#define CS48L32_AUXPDM_CTRL2 0x105c +#define CS48L32_CLOCK32K 0x1400 +#define CS48L32_SYSTEM_CLOCK1 0x1404 +#define CS48L32_SYSTEM_CLOCK2 0x1408 +#define CS48L32_SAMPLE_RATE1 0x1420 +#define CS48L32_SAMPLE_RATE2 0x1424 +#define CS48L32_SAMPLE_RATE3 0x1428 +#define CS48L32_SAMPLE_RATE4 0x142c +#define CS48L32_DSP_CLOCK1 0x1510 +#define CS48L32_FLL1_CONTROL1 0x1c00 +#define CS48L32_FLL1_CONTROL5 0x1c10 +#define CS48L32_FLL1_CONTROL6 0x1c14 +#define CS48L32_FLL1_GPIO_CLOCK 0x1ca0 +#define CS48L32_CHARGE_PUMP1 0x2000 +#define CS48L32_LDO2_CTRL1 0x2408 +#define CS48L32_MICBIAS_CTRL1 0x2410 +#define CS48L32_MICBIAS_CTRL5 0x2418 +#define CS48L32_IRQ1_CTRL_AOD 0x2710 +#define CS48L32_AOD_PAD_CTRL 0x2718 +#define CS48L32_INPUT_CONTROL 0x4000 +#define CS48L32_INPUT_STATUS 0x4004 +#define CS48L32_INPUT_RATE_CONTROL 0x4008 +#define CS48L32_INPUT_CONTROL2 0x400c +#define CS48L32_INPUT_CONTROL3 0x4014 +#define CS48L32_INPUT1_CONTROL1 0x4020 +#define CS48L32_IN1L_CONTROL1 0x4024 +#define CS48L32_IN1L_CONTROL2 0x4028 +#define CS48L32_IN1R_CONTROL1 0x4044 +#define CS48L32_IN1R_CONTROL2 0x4048 +#define CS48L32_INPUT2_CONTROL1 0x4060 +#define CS48L32_IN2L_CONTROL1 0x4064 +#define CS48L32_IN2L_CONTROL2 0x4068 +#define CS48L32_IN2R_CONTROL1 0x4084 +#define CS48L32_IN2R_CONTROL2 0x4088 +#define CS48L32_INPUT_HPF_CONTROL 0x4244 +#define CS48L32_INPUT_VOL_CONTROL 0x4248 +#define CS48L32_AUXPDM_CONTROL1 0x4300 +#define CS48L32_AUXPDM_CONTROL2 0x4304 +#define CS48L32_AUXPDM1_CONTROL1 0x4308 +#define CS48L32_AUXPDM2_CONTROL1 0x4310 +#define CS48L32_ADC1L_ANA_CONTROL1 0x4688 +#define CS48L32_ADC1R_ANA_CONTROL1 0x468c +#define CS48L32_ASP1_ENABLES1 0x6000 +#define CS48L32_ASP1_CONTROL3 0x600C +#define CS48L32_ASP1_DATA_CONTROL5 0x6040 +#define CS48L32_ASP2_ENABLES1 0x6080 +#define CS48L32_ASP2_CONTROL3 0x608C +#define CS48L32_ASP2_DATA_CONTROL5 0x60c0 +#define CS48L32_ASP1TX1_INPUT1 0x8200 +#define CS48L32_ASP1TX2_INPUT1 0x8210 +#define CS48L32_ASP1TX3_INPUT1 0x8220 +#define CS48L32_ASP1TX4_INPUT1 0x8230 +#define CS48L32_ASP1TX5_INPUT1 0x8240 +#define CS48L32_ASP1TX6_INPUT1 0x8250 +#define CS48L32_ASP1TX7_INPUT1 0x8260 +#define CS48L32_ASP1TX8_INPUT1 0x8270 +#define CS48L32_ASP1TX8_INPUT4 0x827c +#define CS48L32_ASP2TX1_INPUT1 0x8300 +#define CS48L32_ASP2TX2_INPUT1 0x8310 +#define CS48L32_ASP2TX3_INPUT1 0x8320 +#define CS48L32_ASP2TX4_INPUT1 0x8330 +#define CS48L32_ASP2TX4_INPUT4 0x833c +#define CS48L32_ISRC1INT1_INPUT1 0x8980 +#define CS48L32_ISRC1INT2_INPUT1 0x8990 +#define CS48L32_ISRC1INT3_INPUT1 0x89a0 +#define CS48L32_ISRC1INT4_INPUT1 0x89b0 +#define CS48L32_ISRC1DEC1_INPUT1 0x89c0 +#define CS48L32_ISRC1DEC2_INPUT1 0x89d0 +#define CS48L32_ISRC1DEC3_INPUT1 0x89e0 +#define CS48L32_ISRC1DEC4_INPUT1 0x89f0 +#define CS48L32_ISRC2INT1_INPUT1 0x8a00 +#define CS48L32_ISRC2INT2_INPUT1 0x8a10 +#define CS48L32_ISRC2DEC1_INPUT1 0x8a40 +#define CS48L32_ISRC2DEC2_INPUT1 0x8a50 +#define CS48L32_ISRC3INT1_INPUT1 0x8a80 +#define CS48L32_ISRC3INT2_INPUT1 0x8a90 +#define CS48L32_ISRC3DEC1_INPUT1 0x8ac0 +#define CS48L32_ISRC3DEC2_INPUT1 0x8ad0 +#define CS48L32_EQ1_INPUT1 0x8b80 +#define CS48L32_EQ2_INPUT1 0x8b90 +#define CS48L32_EQ3_INPUT1 0x8ba0 +#define CS48L32_EQ4_INPUT1 0x8bb0 +#define CS48L32_EQ4_INPUT4 0x8bbc +#define CS48L32_DRC1L_INPUT1 0x8c00 +#define CS48L32_DRC1R_INPUT1 0x8c10 +#define CS48L32_DRC1R_INPUT4 0x8c1c +#define CS48L32_DRC2L_INPUT1 0x8c20 +#define CS48L32_DRC2R_INPUT1 0x8c30 +#define CS48L32_DRC2R_INPUT4 0x8c3c +#define CS48L32_LHPF1_INPUT1 0x8c80 +#define CS48L32_LHPF1_INPUT4 0x8c8c +#define CS48L32_LHPF2_INPUT1 0x8c90 +#define CS48L32_LHPF2_INPUT4 0x8c9c +#define CS48L32_LHPF3_INPUT1 0x8ca0 +#define CS48L32_LHPF3_INPUT4 0x8cac +#define CS48L32_LHPF4_INPUT1 0x8cb0 +#define CS48L32_LHPF4_INPUT4 0x8cbc +#define CS48L32_DSP1RX1_INPUT1 0x9000 +#define CS48L32_DSP1RX2_INPUT1 0x9010 +#define CS48L32_DSP1RX3_INPUT1 0x9020 +#define CS48L32_DSP1RX4_INPUT1 0x9030 +#define CS48L32_DSP1RX5_INPUT1 0x9040 +#define CS48L32_DSP1RX6_INPUT1 0x9050 +#define CS48L32_DSP1RX7_INPUT1 0x9060 +#define CS48L32_DSP1RX8_INPUT1 0x9070 +#define CS48L32_DSP1RX8_INPUT4 0x907c +#define CS48L32_ISRC1_CONTROL1 0xa400 +#define CS48L32_ISRC1_CONTROL2 0xa404 +#define CS48L32_ISRC2_CONTROL1 0xa510 +#define CS48L32_ISRC2_CONTROL2 0xa514 +#define CS48L32_ISRC3_CONTROL1 0xa620 +#define CS48L32_ISRC3_CONTROL2 0xa624 +#define CS48L32_FX_SAMPLE_RATE 0xa800 +#define CS48L32_EQ_CONTROL1 0xa808 +#define CS48L32_EQ_CONTROL2 0xa80c +#define CS48L32_EQ1_GAIN1 0xa810 +#define CS48L32_EQ1_GAIN2 0xa814 +#define CS48L32_EQ1_BAND1_COEFF1 0xa818 +#define CS48L32_EQ1_BAND1_COEFF2 0xa81c +#define CS48L32_EQ1_BAND1_PG 0xa820 +#define CS48L32_EQ1_BAND2_COEFF1 0xa824 +#define CS48L32_EQ1_BAND2_COEFF2 0xa828 +#define CS48L32_EQ1_BAND2_PG 0xa82c +#define CS48L32_EQ1_BAND3_COEFF1 0xa830 +#define CS48L32_EQ1_BAND3_COEFF2 0xa834 +#define CS48L32_EQ1_BAND3_PG 0xa838 +#define CS48L32_EQ1_BAND4_COEFF1 0xa83c +#define CS48L32_EQ1_BAND4_COEFF2 0xa840 +#define CS48L32_EQ1_BAND4_PG 0xa844 +#define CS48L32_EQ1_BAND5_COEFF1 0xa848 +#define CS48L32_EQ1_BAND5_PG 0xa850 +#define CS48L32_EQ2_GAIN1 0xa854 +#define CS48L32_EQ2_GAIN2 0xa858 +#define CS48L32_EQ2_BAND1_COEFF1 0xa85c +#define CS48L32_EQ2_BAND1_COEFF2 0xa860 +#define CS48L32_EQ2_BAND1_PG 0xa864 +#define CS48L32_EQ2_BAND2_COEFF1 0xa868 +#define CS48L32_EQ2_BAND2_COEFF2 0xa86c +#define CS48L32_EQ2_BAND2_PG 0xa870 +#define CS48L32_EQ2_BAND3_COEFF1 0xa874 +#define CS48L32_EQ2_BAND3_COEFF2 0xa878 +#define CS48L32_EQ2_BAND3_PG 0xa87c +#define CS48L32_EQ2_BAND4_COEFF1 0xa880 +#define CS48L32_EQ2_BAND4_COEFF2 0xa884 +#define CS48L32_EQ2_BAND4_PG 0xa888 +#define CS48L32_EQ2_BAND5_COEFF1 0xa88c +#define CS48L32_EQ2_BAND5_PG 0xa894 +#define CS48L32_EQ3_GAIN1 0xa898 +#define CS48L32_EQ3_GAIN2 0xa89c +#define CS48L32_EQ3_BAND1_COEFF1 0xa8a0 +#define CS48L32_EQ3_BAND1_COEFF2 0xa8a4 +#define CS48L32_EQ3_BAND1_PG 0xa8a8 +#define CS48L32_EQ3_BAND2_COEFF1 0xa8ac +#define CS48L32_EQ3_BAND2_COEFF2 0xa8b0 +#define CS48L32_EQ3_BAND2_PG 0xa8b4 +#define CS48L32_EQ3_BAND3_COEFF1 0xa8b8 +#define CS48L32_EQ3_BAND3_COEFF2 0xa8bc +#define CS48L32_EQ3_BAND3_PG 0xa8c0 +#define CS48L32_EQ3_BAND4_COEFF1 0xa8c4 +#define CS48L32_EQ3_BAND4_COEFF2 0xa8c8 +#define CS48L32_EQ3_BAND4_PG 0xa8cc +#define CS48L32_EQ3_BAND5_COEFF1 0xa8d0 +#define CS48L32_EQ3_BAND5_PG 0xa8d8 +#define CS48L32_EQ4_GAIN1 0xa8dc +#define CS48L32_EQ4_GAIN2 0xa8e0 +#define CS48L32_EQ4_BAND1_COEFF1 0xa8e4 +#define CS48L32_EQ4_BAND1_COEFF2 0xa8e8 +#define CS48L32_EQ4_BAND1_PG 0xa8ec +#define CS48L32_EQ4_BAND2_COEFF1 0xa8f0 +#define CS48L32_EQ4_BAND2_COEFF2 0xa8f4 +#define CS48L32_EQ4_BAND2_PG 0xa8f8 +#define CS48L32_EQ4_BAND3_COEFF1 0xa8fc +#define CS48L32_EQ4_BAND3_COEFF2 0xa900 +#define CS48L32_EQ4_BAND3_PG 0xa904 +#define CS48L32_EQ4_BAND4_COEFF1 0xa908 +#define CS48L32_EQ4_BAND4_COEFF2 0xa90c +#define CS48L32_EQ4_BAND4_PG 0xa910 +#define CS48L32_EQ4_BAND5_COEFF1 0xa914 +#define CS48L32_EQ4_BAND5_PG 0xa91c +#define CS48L32_LHPF_CONTROL1 0xaa30 +#define CS48L32_LHPF_CONTROL2 0xaa34 +#define CS48L32_LHPF1_COEFF 0xaa38 +#define CS48L32_LHPF2_COEFF 0xaa3c +#define CS48L32_LHPF3_COEFF 0xaa40 +#define CS48L32_LHPF4_COEFF 0xaa44 +#define CS48L32_DRC1_CONTROL1 0xab00 +#define CS48L32_DRC1_CONTROL4 0xab0c +#define CS48L32_DRC2_CONTROL1 0xab14 +#define CS48L32_DRC2_CONTROL4 0xab20 +#define CS48L32_TONE_GENERATOR1 0xb000 +#define CS48L32_TONE_GENERATOR2 0xb004 +#define CS48L32_COMFORT_NOISE_GENERATOR 0xb400 +#define CS48L32_US_CONTROL 0xb800 +#define CS48L32_US1_CONTROL 0xb804 +#define CS48L32_US1_DET_CONTROL 0xb808 +#define CS48L32_US2_CONTROL 0xb814 +#define CS48L32_US2_DET_CONTROL 0xb818 +#define CS48L32_DSP1_XM_SRAM_IBUS_SETUP_0 0x1700c +#define CS48L32_DSP1_XM_SRAM_IBUS_SETUP_1 0x17010 +#define CS48L32_DSP1_XM_SRAM_IBUS_SETUP_24 0x1706c +#define CS48L32_DSP1_YM_SRAM_IBUS_SETUP_0 0x17070 +#define CS48L32_DSP1_YM_SRAM_IBUS_SETUP_1 0x17074 +#define CS48L32_DSP1_YM_SRAM_IBUS_SETUP_8 0x17090 +#define CS48L32_DSP1_PM_SRAM_IBUS_SETUP_0 0x17094 +#define CS48L32_DSP1_PM_SRAM_IBUS_SETUP_1 0x17098 +#define CS48L32_DSP1_PM_SRAM_IBUS_SETUP_7 0x170b0 +#define CS48L32_IRQ1_STATUS 0x18004 +#define CS48L32_IRQ1_EINT_1 0x18010 +#define CS48L32_IRQ1_EINT_2 0x18014 +#define CS48L32_IRQ1_EINT_7 0x18028 +#define CS48L32_IRQ1_EINT_9 0x18030 +#define CS48L32_IRQ1_EINT_11 0x18038 +#define CS48L32_IRQ1_STS_1 0x18090 +#define CS48L32_IRQ1_STS_6 0x180a4 +#define CS48L32_IRQ1_STS_11 0x180b8 +#define CS48L32_IRQ1_MASK_1 0x18110 +#define CS48L32_IRQ1_MASK_2 0x18114 +#define CS48L32_IRQ1_MASK_7 0x18128 +#define CS48L32_IRQ1_MASK_9 0x18130 +#define CS48L32_IRQ1_MASK_11 0x18138 +#define CS48L32_DSP1_XMEM_PACKED_0 0x2000000 +#define CS48L32_DSP1_XMEM_PACKED_LAST 0x208fff0 +#define CS48L32_DSP1_SYS_INFO_ID 0x25e0000 +#define CS48L32_DSP1_AHBM_WINDOW_DEBUG_1 0x25e2044 +#define CS48L32_DSP1_XMEM_UNPACKED24_0 0x2800000 +#define CS48L32_DSP1_XMEM_UNPACKED24_LAST 0x28bfff4 +#define CS48L32_DSP1_CLOCK_FREQ 0x2b80000 +#define CS48L32_DSP1_SAMPLE_RATE_TX8 0x2b802b8 +#define CS48L32_DSP1_SCRATCH1 0x2b805c0 +#define CS48L32_DSP1_SCRATCH4 0x2b805d8 +#define CS48L32_DSP1_CCM_CORE_CONTROL 0x2bc1000 +#define CS48L32_DSP1_STREAM_ARB_RESYNC_MSK1 0x2bc5a00 +#define CS48L32_DSP1_YMEM_PACKED_0 0x2c00000 +#define CS48L32_DSP1_YMEM_PACKED_LAST 0x2c2fff0 +#define CS48L32_DSP1_YMEM_UNPACKED24_0 0x3400000 +#define CS48L32_DSP1_YMEM_UNPACKED24_LAST 0x343fff4 +#define CS48L32_DSP1_PMEM_0 0x3800000 +#define CS48L32_DSP1_PMEM_LAST 0x3845fe8 + +/* (0x0) DEVID */ +#define CS48L32_DEVID_MASK 0x00ffffff +#define CS48L32_DEVID_SHIFT 0 + +/* (0x4) REVID */ +#define CS48L32_AREVID_MASK 0x000000f0 +#define CS48L32_AREVID_SHIFT 4 +#define CS48L32_MTLREVID_MASK 0x0000000f +#define CS48L32_MTLREVID_SHIFT 0 + +/* (0x10) OTPID */ +#define CS48L32_OTPID_MASK 0x0000000f + +/* (0x0804) MCU_CTRL1 */ +#define CS48L32_MCU_STS_MASK 0x0000ff00 +#define CS48L32_MCU_STS_SHIFT 8 + +/* (0xc08) GPIO1_CTRL1 */ +#define CS48L32_GPIOX_CTRL1_FN_MASK 0x000003ff + +/* (0x1020) OUTPUT_SYS_CLK */ +#define CS48L32_OPCLK_EN_SHIFT 15 +#define CS48L32_OPCLK_DIV_MASK 0x000000f8 +#define CS48L32_OPCLK_DIV_SHIFT 3 +#define CS48L32_OPCLK_SEL_MASK 0x00000007 + +/* (0x105c) AUXPDM_CTRL2 */ +#define CS48L32_AUXPDMDAT2_SRC_SHIFT 4 +#define CS48L32_AUXPDMDAT1_SRC_SHIFT 0 + +/* (0x1400) CLOCK32K */ +#define CS48L32_CLK_32K_EN_MASK 0x00000040 +#define CS48L32_CLK_32K_SRC_MASK 0x00000003 + +/* (0x1404) SYSTEM_CLOCK1 */ +#define CS48L32_SYSCLK_FRAC_MASK 0x00008000 +#define CS48L32_SYSCLK_FREQ_MASK 0x00000700 +#define CS48L32_SYSCLK_FREQ_SHIFT 8 +#define CS48L32_SYSCLK_EN_SHIFT 6 +#define CS48L32_SYSCLK_SRC_MASK 0x0000001f +#define CS48L32_SYSCLK_SRC_SHIFT 0 + +/* (0x1408) SYSTEM_CLOCK2 */ +#define CS48L32_SYSCLK_FREQ_STS_MASK 0x00000700 +#define CS48L32_SYSCLK_FREQ_STS_SHIFT 8 + +/* (0x1420) SAMPLE_RATE1 */ +#define CS48L32_SAMPLE_RATE_1_MASK 0x0000001f +#define CS48L32_SAMPLE_RATE_1_SHIFT 0 + +/* (0x1510) DSP_CLOCK1 */ +#define CS48L32_DSP_CLK_FREQ_MASK 0xffff0000 +#define CS48L32_DSP_CLK_FREQ_SHIFT 16 + +/* (0x1c00) FLL_CONTROL1 */ +#define CS48L32_FLL_CTRL_UPD_MASK 0x00000004 +#define CS48L32_FLL_HOLD_MASK 0x00000002 +#define CS48L32_FLL_EN_MASK 0x00000001 + +/* (0x1c04) FLL_CONTROL2 */ +#define CS48L32_FLL_LOCKDET_THR_MASK 0xf0000000 +#define CS48L32_FLL_LOCKDET_THR_SHIFT 28 +#define CS48L32_FLL_LOCKDET_MASK 0x08000000 +#define CS48L32_FLL_PHASEDET_MASK 0x00400000 +#define CS48L32_FLL_PHASEDET_SHIFT 22 +#define CS48L32_FLL_REFCLK_DIV_MASK 0x00030000 +#define CS48L32_FLL_REFCLK_DIV_SHIFT 16 +#define CS48L32_FLL_REFCLK_SRC_MASK 0x0000f000 +#define CS48L32_FLL_REFCLK_SRC_SHIFT 12 +#define CS48L32_FLL_N_MASK 0x000003ff +#define CS48L32_FLL_N_SHIFT 0 + +/* (0x1c08) FLL_CONTROL3 */ +#define CS48L32_FLL_LAMBDA_MASK 0xffff0000 +#define CS48L32_FLL_LAMBDA_SHIFT 16 +#define CS48L32_FLL_THETA_MASK 0x0000ffff +#define CS48L32_FLL_THETA_SHIFT 0 + +/* (0x1c0c) FLL_CONTROL4 */ +#define CS48L32_FLL_FD_GAIN_COARSE_SHIFT 16 +#define CS48L32_FLL_HP_MASK 0x00003000 +#define CS48L32_FLL_HP_SHIFT 12 +#define CS48L32_FLL_FB_DIV_MASK 0x000003ff +#define CS48L32_FLL_FB_DIV_SHIFT 0 + +/* (0x1c10) FLL_CONTROL5 */ +#define CS48L32_FLL_FRC_INTEG_UPD_MASK 0x00008000 + +/* (0x2000) CHARGE_PUMP1 */ +#define CS48L32_CP2_BYPASS_SHIFT 1 +#define CS48L32_CP2_EN_SHIFT 0 + +/* (0x2408) LDO2_CTRL1 */ +#define CS48L32_LDO2_VSEL_MASK 0x000007e0 +#define CS48L32_LDO2_VSEL_SHIFT 5 + +/* (0x2410) MICBIAS_CTRL1 */ +#define CS48L32_MICB1_LVL_MASK 0x000001e0 +#define CS48L32_MICB1_LVL_SHIFT 5 +#define CS48L32_MICB1_EN_SHIFT 0 + +/* (0x2418) MICBIAS_CTRL5 */ +#define CS48L32_MICB1C_EN_SHIFT 8 +#define CS48L32_MICB1B_EN_SHIFT 4 +#define CS48L32_MICB1A_EN_SHIFT 0 + +/* (0x2710) IRQ1_CTRL_AOD */ +#define CS48L32_IRQ_POL_MASK 0x00000400 + +/* (0x4000) INPUT_CONTROL */ +#define CS48L32_IN2L_EN_SHIFT 3 +#define CS48L32_IN2R_EN_SHIFT 2 +#define CS48L32_IN1L_EN_SHIFT 1 +#define CS48L32_IN1R_EN_SHIFT 0 + +/* (0x400c) INPUT_CONTROL2 */ +#define CS48L32_PDM_FLLCLK_SRC_MASK 0x0000000f +#define CS48L32_PDM_FLLCLK_SRC_SHIFT 0 + +/* (0x4014) INPUT_CONTROL3 */ +#define CS48L32_IN_VU 0x20000000 +#define CS48L32_IN_VU_MASK 0x20000000 +#define CS48L32_IN_VU_SHIFT 29 +#define CS48L32_IN_VU_WIDTH 1 + +/* (0x4020) INPUT1_CONTROL1 */ +#define CS48L32_IN1_OSR_SHIFT 16 +#define CS48L32_IN1_PDM_SUP_MASK 0x00000300 +#define CS48L32_IN1_PDM_SUP_SHIFT 8 +#define CS48L32_IN1_MODE_SHIFT 0 + +/* + * (0x4024) IN1L_CONTROL1 + * (0x4044) IN1R_CONTROL1 + */ +#define CS48L32_INx_SRC_MASK 0x30000000 +#define CS48L32_INx_SRC_SHIFT 28 +#define CS48L32_INx_RATE_MASK 0x0000f800 +#define CS48L32_INx_RATE_SHIFT 11 +#define CS48L32_INx_HPF_SHIFT 2 +#define CS48L32_INx_LP_MODE_SHIFT 0 + +/* + * (0x4028) IN1L_CONTROL2 + * (0x4048) IN1R_CONTROL2 + */ +#define CS48L32_INx_MUTE_MASK 0x10000000 +#define CS48L32_INx_VOL_SHIFT 16 +#define CS48L32_INx_PGA_VOL_SHIFT 1 + +/* (0x4244) INPUT_HPF_CONTROL */ +#define CS48L32_IN_HPF_CUT_SHIFT 0 + +/* (0x4248) INPUT_VOL_CONTROL */ +#define CS48L32_IN_VD_RAMP_SHIFT 4 +#define CS48L32_IN_VI_RAMP_SHIFT 0 + +/* (0x4308) AUXPDM1_CONTROL1 */ +#define CS48L32_AUXPDM1_FREQ_SHIFT 16 +#define CS48L32_AUXPDM1_SRC_MASK 0x00000f00 +#define CS48L32_AUXPDM1_SRC_SHIFT 8 + +/* (0x4688) ADC1L_ANA_CONTROL1 */ +/* (0x468c) ADC1R_ANA_CONTROL1 */ +#define CS48L32_ADC1x_INT_ENA_FRC_MASK 0x00000002 + +/* (0x6004) ASPn_CONTROL1 */ +#define CS48L32_ASP_RATE_MASK 0x00001f00 +#define CS48L32_ASP_RATE_SHIFT 8 +#define CS48L32_ASP_BCLK_FREQ_MASK 0x0000003f + +/* (0x6008) ASPn_CONTROL2 */ +#define CS48L32_ASP_RX_WIDTH_MASK 0xff000000 +#define CS48L32_ASP_RX_WIDTH_SHIFT 24 +#define CS48L32_ASP_TX_WIDTH_MASK 0x00ff0000 +#define CS48L32_ASP_TX_WIDTH_SHIFT 16 +#define CS48L32_ASP_FMT_MASK 0x00000700 +#define CS48L32_ASP_FMT_SHIFT 8 +#define CS48L32_ASP_BCLK_INV_MASK 0x00000040 +#define CS48L32_ASP_BCLK_MSTR_MASK 0x00000010 +#define CS48L32_ASP_FSYNC_INV_MASK 0x00000004 +#define CS48L32_ASP_FSYNC_MSTR_MASK 0x00000001 + +/* (0x6010) ASPn_CONTROL3 */ +#define CS48L32_ASP_DOUT_HIZ_MASK 0x00000003 + +/* (0x6030) ASPn_DATA_CONTROL1 */ +#define CS48L32_ASP_TX_WL_MASK 0x0000003f + +/* (0x6040) ASPn_DATA_CONTROL5 */ +#define CS48L32_ASP_RX_WL_MASK 0x0000003f + +/* (0x82xx - 0x90xx) *_INPUT[1-4] */ +#define CS48L32_MIXER_VOL_MASK 0x00FE0000 +#define CS48L32_MIXER_VOL_SHIFT 17 +#define CS48L32_MIXER_VOL_WIDTH 7 +#define CS48L32_MIXER_SRC_MASK 0x000001ff +#define CS48L32_MIXER_SRC_SHIFT 0 +#define CS48L32_MIXER_SRC_WIDTH 9 + +/* (0xa400) ISRC1_CONTROL1 */ +#define CS48L32_ISRC1_FSL_MASK 0xf8000000 +#define CS48L32_ISRC1_FSL_SHIFT 27 +#define CS48L32_ISRC1_FSH_MASK 0x0000f800 +#define CS48L32_ISRC1_FSH_SHIFT 11 + +/* (0xa404) ISRC1_CONTROL2 */ +#define CS48L32_ISRC1_INT4_EN_SHIFT 11 +#define CS48L32_ISRC1_INT3_EN_SHIFT 10 +#define CS48L32_ISRC1_INT2_EN_SHIFT 9 +#define CS48L32_ISRC1_INT1_EN_SHIFT 8 +#define CS48L32_ISRC1_DEC4_EN_SHIFT 3 +#define CS48L32_ISRC1_DEC3_EN_SHIFT 2 +#define CS48L32_ISRC1_DEC2_EN_SHIFT 1 +#define CS48L32_ISRC1_DEC1_EN_SHIFT 0 + +/* (0xa800) FX_SAMPLE_RATE */ +#define CS48L32_FX_RATE_MASK 0x0000f800 +#define CS48L32_FX_RATE_SHIFT 11 + +/* (0xab00) DRC1_CONTROL1 */ +#define CS48L32_DRC1L_EN_SHIFT 1 +#define CS48L32_DRC1R_EN_SHIFT 0 + +/* (0xb400) Comfort_Noise_Generator */ +#define CS48L32_NOISE_GEN_RATE_MASK 0x0000f800 +#define CS48L32_NOISE_GEN_RATE_SHIFT 11 +#define CS48L32_NOISE_GEN_EN_SHIFT 5 +#define CS48L32_NOISE_GEN_GAIN_SHIFT 0 + +/* (0xb800) US_CONTROL */ +#define CS48L32_US1_DET_EN_SHIFT 8 + +/* (0xb804) US1_CONTROL */ +#define CS48L32_US1_RATE_MASK 0xf8000000 +#define CS48L32_US1_RATE_SHIFT 27 +#define CS48L32_US1_GAIN_SHIFT 12 +#define CS48L32_US1_SRC_MASK 0x00000f00 +#define CS48L32_US1_SRC_SHIFT 8 +#define CS48L32_US1_FREQ_MASK 0x00000070 +#define CS48L32_US1_FREQ_SHIFT 4 + +/* (0xb808) US1_DET_CONTROL */ +#define CS48L32_US1_DET_DCY_SHIFT 28 +#define CS48L32_US1_DET_HOLD_SHIFT 24 +#define CS48L32_US1_DET_NUM_SHIFT 20 +#define CS48L32_US1_DET_THR_SHIFT 16 +#define CS48L32_US1_DET_LPF_CUT_SHIFT 5 +#define CS48L32_US1_DET_LPF_SHIFT 4 + +/* (0x18004) IRQ1_STATUS */ +#define CS48L32_IRQ1_STS_MASK 0x00000001 + +/* (0x18014) IRQ1_EINT_2 */ +#define CS48L32_BOOT_DONE_EINT1_MASK 0x00000008 + +/* (0x18028) IRQ1_EINT_7 */ +#define CS48L32_DSP1_MPU_ERR_EINT1_MASK 0x00200000 +#define CS48L32_DSP1_WDT_EXPIRE_EINT1_MASK 0x00100000 + +/* (0x18030) IRQ1_EINT_9 */ +#define CS48L32_DSP1_IRQ0_EINT1_MASK 0x00000001 + +/* (0x180a4) IRQ1_STS_6 */ +#define CS48L32_FLL1_LOCK_STS1_MASK 0x00000001 + +#endif diff --git a/include/sound/designware_i2s.h b/include/sound/designware_i2s.h index 80d275b9ae0d..f6803205a9fb 100644 --- a/include/sound/designware_i2s.h +++ b/include/sound/designware_i2s.h @@ -21,6 +21,8 @@ struct i2s_clk_config_data { u32 sample_rate; }; +struct dw_i2s_dev; + struct i2s_platform_data { #define DWC_I2S_PLAY (1 << 0) #define DWC_I2S_RECORD (1 << 1) @@ -42,6 +44,7 @@ struct i2s_platform_data { void *capture_dma_data; bool (*filter)(struct dma_chan *chan, void *slave); int (*i2s_clk_cfg)(struct i2s_clk_config_data *config); + int (*i2s_pd_init)(struct dw_i2s_dev *dev); }; struct i2s_dma_data { diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h index 2df54cf02cb3..9472f0a966a2 100644 --- a/include/sound/dmaengine_pcm.h +++ b/include/sound/dmaengine_pcm.h @@ -36,9 +36,8 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer_no_residue(struct snd_pcm_substream int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream, struct dma_chan *chan); 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, @@ -70,6 +69,10 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) * @peripheral_config: peripheral configuration for programming peripheral * for dmaengine transfer * @peripheral_size: peripheral configuration buffer size + * @port_window_size: The length of the register area in words the data need + * to be accessed on the device side. It is only used for devices which is using + * an area instead of a single register to send/receive the data. Typically the + * DMA loops in this area in order to transfer the data. */ struct snd_dmaengine_dai_dma_data { dma_addr_t addr; @@ -81,6 +84,7 @@ struct snd_dmaengine_dai_dma_data { unsigned int flags; void *peripheral_config; size_t peripheral_size; + u32 port_window_size; }; void snd_dmaengine_pcm_set_config_from_dai_data( @@ -118,6 +122,7 @@ int snd_dmaengine_pcm_refine_runtime_hwparams( * which do not use devicetree. * @process: Callback used to apply processing on samples transferred from/to * user space. + * @name: Component name. If null, dev_name will be used. * @compat_filter_fn: Will be used as the filter function when requesting a * channel for platforms which do not use devicetree. The filter parameter * will be the DAI's DMA data. @@ -142,7 +147,8 @@ struct snd_dmaengine_pcm_config { struct snd_pcm_substream *substream); int (*process)(struct snd_pcm_substream *substream, int channel, unsigned long hwoff, - void *buf, unsigned long bytes); + unsigned long bytes); + const char *name; dma_filter_fn compat_filter_fn; struct device *dma_dev; const char *chan_names[SNDRV_PCM_STREAM_LAST + 1]; diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 386a5f3be3e0..4f94565c9d15 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -598,17 +598,25 @@ SUB_REG(PEFE, FILTERAMOUNT, 0x000000ff) /* Filter envlope amount */ // In stereo mode, the two channels' caches are concatenated into one, // and hold the interleaved frames. // The cache holds 64 frames, so the upper half is not used in 8-bit mode. -// All registers mentioned below count in frames. -// The cache is a ring buffer; CCR_READADDRESS operates modulo 64. -// The cache is filled from (CCCA_CURRADDR - CCR_CACHEINVALIDSIZE) -// into (CCR_READADDRESS - CCR_CACHEINVALIDSIZE). +// All registers mentioned below count in frames. Shortcuts: +// CA = CCCA_CURRADDR, CRA = CCR_READADDRESS, +// CLA = CCR_CACHELOOPADDRHI:CLP_CACHELOOPADDR, +// CIS = CCR_CACHEINVALIDSIZE, LIS = CCR_LOOPINVALSIZE, +// CLF = CCR_CACHELOOPFLAG, LF = CCR_LOOPFLAG +// The cache is a ring buffer; CRA operates modulo 64. +// The cache is filled from (CA - CIS) into (CRA - CIS). // The engine has a fetch threshold of 32 bytes, so it tries to keep -// CCR_CACHEINVALIDSIZE below 8 (16-bit stereo), 16 (16-bit mono, -// 8-bit stereo), or 32 (8-bit mono). The actual transfers are pretty -// unpredictable, especially if several voices are running. -// Frames are consumed at CCR_READADDRESS, which is incremented afterwards, -// along with CCCA_CURRADDR and CCR_CACHEINVALIDSIZE. This implies that the -// actual playback position always lags CCCA_CURRADDR by exactly 64 frames. +// CIS below 8 (16-bit stereo), 16 (16-bit mono, 8-bit stereo), or +// 32 (8-bit mono). The actual transfers are pretty unpredictable, +// especially if several voices are running. +// Frames are consumed at CRA, which is incremented afterwards, +// along with CA and CIS. This implies that the actual playback +// position always lags CA by exactly 64 frames. +// When CA reaches DSL_LOOPENDADDR, LF is set for one frame's time. +// LF's rising edge causes the current values of CA and CIS to be +// copied into CLA and LIS, resp., and CLF to be set. +// If CLF is set, the first LIS of the CIS frames are instead +// filled from (CLA - LIS), and CLF is subsequently reset. #define CD0 0x20 /* Cache data registers 0 .. 0x1f */ #define PTB 0x40 /* Page table base register */ @@ -902,6 +910,11 @@ SUB_REG_NC(A_EHC, A_I2S_CAPTURE_RATE, 0x00000e00) /* This sets the capture PCM #define A_TTDA 0x7a /* Tank Table DMA Address */ #define A_TTDD 0x7b /* Tank Table DMA Data */ +// In A_FXRT1 & A_FXRT2, the 0x80 bit of each byte completely disables the +// filter (CVCF_CURRENTFILTER) for the corresponding channel. There is no +// effect on the volume (CVCF_CURRENTVOLUME) or the interpolator's filter +// (CCCA_INTERPROM_MASK). + #define A_FXRT2 0x7c #define A_FXRT_CHANNELE 0x0000003f /* Effects send bus number for channel's effects send E */ #define A_FXRT_CHANNELF 0x00003f00 /* Effects send bus number for channel's effects send F */ @@ -914,8 +927,6 @@ SUB_REG_NC(A_EHC, A_I2S_CAPTURE_RATE, 0x00000e00) /* This sets the capture PCM #define A_FXSENDAMOUNT_G_MASK 0x0000FF00 #define A_FXSENDAMOUNT_H_MASK 0x000000FF -/* 0x7c, 0x7e "high bit is used for filtering" */ - /* The send amounts for this one are the same as used with the emu10k1 */ #define A_FXRT1 0x7e #define A_FXRT_CHANNELA 0x0000003f @@ -992,6 +1003,9 @@ SUB_REG_NC(A_EHC, A_I2S_CAPTURE_RATE, 0x00000e00) /* This sets the capture PCM #define EMU_HANA_WCLOCK_4X 0x10 #define EMU_HANA_WCLOCK_MULT_RESERVED 0x18 +// If the selected external clock source is/becomes invalid or incompatible +// with the clock multiplier, the clock source is reset to this value, and +// a WCLK_CHANGED interrupt is raised. #define EMU_HANA_DEFCLOCK 0x06 /* 000000x 1 bits Default Word Clock */ #define EMU_HANA_DEFCLOCK_48K 0x00 #define EMU_HANA_DEFCLOCK_44_1K 0x01 @@ -1523,10 +1537,10 @@ struct snd_emu10k1_pcm_mixer { ((route[0] | (route[1] << 4) | (route[2] << 8) | (route[3] << 12)) << 16) #define snd_emu10k1_compose_audigy_fxrt1(route) \ -((unsigned int)route[0] | ((unsigned int)route[1] << 8) | ((unsigned int)route[2] << 16) | ((unsigned int)route[3] << 24)) +((unsigned int)route[0] | ((unsigned int)route[1] << 8) | ((unsigned int)route[2] << 16) | ((unsigned int)route[3] << 24) | 0x80808080) #define snd_emu10k1_compose_audigy_fxrt2(route) \ -((unsigned int)route[4] | ((unsigned int)route[5] << 8) | ((unsigned int)route[6] << 16) | ((unsigned int)route[7] << 24)) +((unsigned int)route[4] | ((unsigned int)route[5] << 8) | ((unsigned int)route[6] << 16) | ((unsigned int)route[7] << 24) | 0x80808080) #define snd_emu10k1_compose_audigy_sendamounts(vol) \ (((unsigned int)vol[4] << 24) | ((unsigned int)vol[5] << 16) | ((unsigned int)vol[6] << 8) | (unsigned int)vol[7]) @@ -1678,8 +1692,8 @@ struct snd_emu1010 { unsigned int clock_fallback; unsigned int optical_in; /* 0:SPDIF, 1:ADAT */ unsigned int optical_out; /* 0:SPDIF, 1:ADAT */ - struct delayed_work firmware_work; - u32 last_reg; + struct work_struct work; + struct mutex lock; }; struct snd_emu10k1 { @@ -1754,6 +1768,7 @@ struct snd_emu10k1 { struct snd_kcontrol *ctl_efx_send_routing; struct snd_kcontrol *ctl_efx_send_volume; struct snd_kcontrol *ctl_efx_attn; + struct snd_kcontrol *ctl_clock_source; void (*hwvol_interrupt)(struct snd_emu10k1 *emu, unsigned int status); void (*capture_interrupt)(struct snd_emu10k1 *emu, unsigned int status); @@ -1761,6 +1776,7 @@ struct snd_emu10k1 { void (*capture_efx_interrupt)(struct snd_emu10k1 *emu, unsigned int status); void (*spdif_interrupt)(struct snd_emu10k1 *emu, unsigned int status); void (*dsp_interrupt)(struct snd_emu10k1 *emu); + void (*gpio_interrupt)(struct snd_emu10k1 *emu); void (*p16v_interrupt)(struct snd_emu10k1 *emu); struct snd_pcm_substream *pcm_capture_substream; @@ -1826,12 +1842,15 @@ unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data); int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data); int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value); +DEFINE_GUARD(snd_emu1010_fpga_lock, struct snd_emu10k1 *, mutex_lock(&(_T)->emu1010.lock), mutex_unlock(&(_T)->emu1010.lock)) +void snd_emu1010_fpga_write_lock(struct snd_emu10k1 *emu, u32 reg, u32 value); void snd_emu1010_fpga_write(struct snd_emu10k1 *emu, u32 reg, u32 value); void snd_emu1010_fpga_read(struct snd_emu10k1 *emu, u32 reg, u32 *value); void snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 *emu, u32 dst, u32 src); u32 snd_emu1010_fpga_link_dst_src_read(struct snd_emu10k1 *emu, u32 dst); int snd_emu1010_get_raw_rate(struct snd_emu10k1 *emu, u8 src); void snd_emu1010_update_clock(struct snd_emu10k1 *emu); +void snd_emu1010_load_firmware_entry(struct snd_emu10k1 *emu, int dock, const struct firmware *fw_entry); unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc); void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb); void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb); @@ -1874,8 +1893,8 @@ int snd_emu10k1_alloc_pages_maybe_wider(struct snd_emu10k1 *emu, size_t size, struct snd_dma_buffer *dmab); struct snd_util_memblk *snd_emu10k1_synth_alloc(struct snd_emu10k1 *emu, unsigned int size); int snd_emu10k1_synth_free(struct snd_emu10k1 *emu, struct snd_util_memblk *blk); -int snd_emu10k1_synth_bzero(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, int offset, int size); -int snd_emu10k1_synth_copy_from_user(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, int offset, const char __user *data, int size); +int snd_emu10k1_synth_memset(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, int offset, int size, u8 value); +int snd_emu10k1_synth_copy_from_user(struct snd_emu10k1 *emu, struct snd_util_memblk *blk, int offset, const char __user *data, int size, u32 xor); int snd_emu10k1_memblk_map(struct snd_emu10k1 *emu, struct snd_emu10k1_memblk *blk); /* voice allocation */ diff --git a/include/sound/emux_synth.h b/include/sound/emux_synth.h index 1cc530434b97..3f7f365ed248 100644 --- a/include/sound/emux_synth.h +++ b/include/sound/emux_synth.h @@ -103,7 +103,7 @@ struct snd_emux { int ports[SNDRV_EMUX_MAX_PORTS]; /* The ports for this device */ struct snd_emux_port *portptrs[SNDRV_EMUX_MAX_PORTS]; int used; /* use counter */ - char *name; /* name of the device (internal) */ + const char *name; /* name of the device (internal) */ struct snd_rawmidi **vmidi; struct timer_list tlist; /* for pending note-offs */ int timer_active; diff --git a/include/sound/es1688.h b/include/sound/es1688.h index 099569c31fbb..425a3717d77a 100644 --- a/include/sound/es1688.h +++ b/include/sound/es1688.h @@ -17,6 +17,7 @@ #define ES1688_HW_UNDEF 0x0003 struct snd_es1688 { + struct snd_card *card; unsigned long port; /* port of ESS chip */ struct resource *res_port; unsigned long mpu_port; /* MPU-401 port of ESS chip */ diff --git a/include/sound/graph_card.h b/include/sound/graph_card.h index 4c8b94c77b8e..8e2e15dfcb1e 100644 --- a/include/sound/graph_card.h +++ b/include/sound/graph_card.h @@ -9,27 +9,27 @@ #include <sound/simple_card_utils.h> -typedef int (*GRAPH2_CUSTOM)(struct asoc_simple_priv *priv, +typedef int (*GRAPH2_CUSTOM)(struct simple_util_priv *priv, struct device_node *lnk, struct link_info *li); struct graph2_custom_hooks { - int (*hook_pre)(struct asoc_simple_priv *priv); - int (*hook_post)(struct asoc_simple_priv *priv); + int (*hook_pre)(struct simple_util_priv *priv); + int (*hook_post)(struct simple_util_priv *priv); GRAPH2_CUSTOM custom_normal; GRAPH2_CUSTOM custom_dpcm; GRAPH2_CUSTOM custom_c2c; }; -int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev); -int audio_graph2_parse_of(struct asoc_simple_priv *priv, struct device *dev, +int audio_graph_parse_of(struct simple_util_priv *priv, struct device *dev); +int audio_graph2_parse_of(struct simple_util_priv *priv, struct device *dev, struct graph2_custom_hooks *hooks); -int audio_graph2_link_normal(struct asoc_simple_priv *priv, +int audio_graph2_link_normal(struct simple_util_priv *priv, struct device_node *lnk, struct link_info *li); -int audio_graph2_link_dpcm(struct asoc_simple_priv *priv, +int audio_graph2_link_dpcm(struct simple_util_priv *priv, struct device_node *lnk, struct link_info *li); -int audio_graph2_link_c2c(struct asoc_simple_priv *priv, +int audio_graph2_link_c2c(struct simple_util_priv *priv, struct device_node *lnk, struct link_info *li); #endif /* __GRAPH_CARD_H */ diff --git a/include/sound/gus.h b/include/sound/gus.h index cd8da68cab92..321ae93625eb 100644 --- a/include/sound/gus.h +++ b/include/sound/gus.h @@ -513,25 +513,8 @@ 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); int snd_gf1_mem_xfree(struct snd_gf1_mem * alloc, struct snd_gf1_mem_block * block); struct snd_gf1_mem_block *snd_gf1_mem_alloc(struct snd_gf1_mem * alloc, int owner, char *name, int size, int w_16, @@ -578,14 +561,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/hda-mlink.h b/include/sound/hda-mlink.h index 4f44f0bd5388..4327317be6af 100644 --- a/include/sound/hda-mlink.h +++ b/include/sound/hda-mlink.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2022-2023 Intel Corporation. All rights reserved. + * Copyright(c) 2022-2023 Intel Corporation */ struct hdac_bus; @@ -15,6 +15,7 @@ int hda_bus_ml_init(struct hdac_bus *bus); void hda_bus_ml_free(struct hdac_bus *bus); int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid); +void hdac_bus_eml_enable_interrupt_unlocked(struct hdac_bus *bus, bool alt, int elid, bool enable); void hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable); bool hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid); @@ -42,6 +43,7 @@ int hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, i int hdac_bus_eml_sdw_power_up_unlocked(struct hdac_bus *bus, int sublink); int hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink); +int hdac_bus_eml_sdw_get_lsdiid_unlocked(struct hdac_bus *bus, int sublink, u16 *lsdiid); int hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num); int hdac_bus_eml_sdw_map_stream_ch(struct hdac_bus *bus, int sublink, int y, @@ -60,6 +62,12 @@ struct mutex *hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid); int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable); +/* microphone privacy specific function supported by ACE3+ architecture */ +void hdac_bus_eml_set_mic_privacy_mask(struct hdac_bus *bus, bool alt, int elid, + unsigned long mask); +bool hdac_bus_eml_is_mic_privacy_changed(struct hdac_bus *bus, bool alt, int elid); +bool hdac_bus_eml_get_mic_privacy_state(struct hdac_bus *bus, bool alt, int elid); + #else static inline int @@ -71,6 +79,9 @@ static inline int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid) { return 0; } static inline void +hdac_bus_eml_enable_interrupt_unlocked(struct hdac_bus *bus, bool alt, int elid, bool enable) { } + +static inline void hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable) { } static inline bool @@ -146,6 +157,9 @@ static inline int hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink) { return 0; } static inline int +hdac_bus_eml_sdw_get_lsdiid_unlocked(struct hdac_bus *bus, int sublink, u16 *lsdiid) { return 0; } + +static inline int hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num) { return 0; } static inline int @@ -177,4 +191,23 @@ hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enabl { return 0; } -#endif /* CONFIG_SND_SOC_SOF_HDA */ + +static inline void +hdac_bus_eml_set_mic_privacy_mask(struct hdac_bus *bus, bool alt, int elid, + unsigned long mask) +{ +} + +static inline bool +hdac_bus_eml_is_mic_privacy_changed(struct hdac_bus *bus, bool alt, int elid) +{ + return false; +} + +static inline bool +hdac_bus_eml_get_mic_privacy_state(struct hdac_bus *bus, bool alt, int elid) +{ + return false; +} + +#endif /* CONFIG_SND_SOC_SOF_HDA_MLINK */ diff --git a/include/sound/hda-sdw-bpt.h b/include/sound/hda-sdw-bpt.h new file mode 100644 index 000000000000..f649549b75d5 --- /dev/null +++ b/include/sound/hda-sdw-bpt.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2025 Intel Corporation. + */ + +#ifndef __HDA_SDW_BPT_H +#define __HDA_SDW_BPT_H + +#include <linux/device.h> + +struct hdac_ext_stream; +struct snd_dma_buffer; + +#if IS_ENABLED(CONFIG_SND_SOF_SOF_HDA_SDW_BPT) +int hda_sdw_bpt_open(struct device *dev, int link_id, struct hdac_ext_stream **bpt_tx_stream, + struct snd_dma_buffer *dmab_tx_bdl, u32 bpt_tx_num_bytes, + u32 tx_dma_bandwidth, struct hdac_ext_stream **bpt_rx_stream, + struct snd_dma_buffer *dmab_rx_bdl, u32 bpt_rx_num_bytes, + u32 rx_dma_bandwidth); + +int hda_sdw_bpt_send_async(struct device *dev, struct hdac_ext_stream *bpt_tx_stream, + struct hdac_ext_stream *bpt_rx_stream); + +int hda_sdw_bpt_wait(struct device *dev, struct hdac_ext_stream *bpt_tx_stream, + struct hdac_ext_stream *bpt_rx_stream); + +int hda_sdw_bpt_close(struct device *dev, struct hdac_ext_stream *bpt_tx_stream, + struct snd_dma_buffer *dmab_tx_bdl, struct hdac_ext_stream *bpt_rx_stream, + struct snd_dma_buffer *dmab_rx_bdl); +#else +static inline int hda_sdw_bpt_open(struct device *dev, int link_id, + struct hdac_ext_stream **bpt_tx_stream, + struct snd_dma_buffer *dmab_tx_bdl, u32 bpt_tx_num_bytes, + u32 tx_dma_bandwidth, struct hdac_ext_stream **bpt_rx_stream, + struct snd_dma_buffer *dmab_rx_bdl, u32 bpt_rx_num_bytes, + u32 rx_dma_bandwidth) +{ + WARN_ONCE(1, "SoundWire BPT is disabled"); + return -EOPNOTSUPP; +} + +static inline int hda_sdw_bpt_send_async(struct device *dev, struct hdac_ext_stream *bpt_tx_stream, + struct hdac_ext_stream *bpt_rx_stream) +{ + WARN_ONCE(1, "SoundWire BPT is disabled"); + return -EOPNOTSUPP; +} + +static inline int hda_sdw_bpt_wait(struct device *dev, struct hdac_ext_stream *bpt_tx_stream, + struct hdac_ext_stream *bpt_rx_stream) +{ + WARN_ONCE(1, "SoundWire BPT is disabled"); + return -EOPNOTSUPP; +} + +static inline int hda_sdw_bpt_close(struct device *dev, struct hdac_ext_stream *bpt_tx_stream, + struct snd_dma_buffer *dmab_tx_bdl, + struct hdac_ext_stream *bpt_rx_stream, + struct snd_dma_buffer *dmab_rx_bdl) +{ + WARN_ONCE(1, "SoundWire BPT is disabled"); + return -EOPNOTSUPP; +} +#endif + +#endif /* __HDA_SDW_BPT_H */ diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index bbb7805e85d8..5d9f0ef228af 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -18,9 +18,6 @@ #include <sound/hda_verbs.h> #include <sound/hda_regmap.h> -#define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98) -#define IS_CFL(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0xa348) - /* * Structures */ @@ -30,6 +27,7 @@ struct hda_beep; struct hda_codec; struct hda_pcm; struct hda_pcm_stream; +struct hda_codec_ops; /* * codec bus @@ -72,28 +70,31 @@ struct hda_bus { /* * codec preset - * - * Known codecs have the patch to build and set up the controls/PCMs - * better than the generic parser. */ -typedef int (*hda_codec_patch_t)(struct hda_codec *); - + #define HDA_CODEC_ID_SKIP_PROBE 0x00000001 #define HDA_CODEC_ID_GENERIC_HDMI 0x00000101 #define HDA_CODEC_ID_GENERIC 0x00000201 -#define HDA_CODEC_REV_ENTRY(_vid, _rev, _name, _patch) \ +#define HDA_CODEC_ID_REV_MODEL(_vid, _rev, _name, _model) \ { .vendor_id = (_vid), .rev_id = (_rev), .name = (_name), \ - .api_version = HDA_DEV_LEGACY, \ - .driver_data = (unsigned long)(_patch) } -#define HDA_CODEC_ENTRY(_vid, _name, _patch) \ - HDA_CODEC_REV_ENTRY(_vid, 0, _name, _patch) + .api_version = HDA_DEV_LEGACY, .driver_data = (_model) } +#define HDA_CODEC_ID_MODEL(_vid, _name, _model) \ + HDA_CODEC_ID_REV_MODEL(_vid, 0, _name, _model) +#define HDA_CODEC_ID_REV(_vid, _rev, _name) \ + HDA_CODEC_ID_REV_MODEL(_vid, _rev, _name, 0) +#define HDA_CODEC_ID(_vid, _name) \ + HDA_CODEC_ID_REV(_vid, 0, _name) struct hda_codec_driver { struct hdac_driver core; const struct hda_device_id *id; + const struct hda_codec_ops *ops; }; +#define hda_codec_to_driver(codec) \ + container_of((codec)->core.dev.driver, struct hda_codec_driver, core.driver) + int __hda_codec_driver_register(struct hda_codec_driver *drv, const char *name, struct module *owner); #define hda_codec_driver_register(drv) \ @@ -103,20 +104,19 @@ void hda_codec_driver_unregister(struct hda_codec_driver *drv); module_driver(drv, hda_codec_driver_register, \ hda_codec_driver_unregister) -/* ops set by the preset patch */ +/* ops for hda codec driver */ struct hda_codec_ops { + int (*probe)(struct hda_codec *codec, const struct hda_device_id *id); + void (*remove)(struct hda_codec *codec); int (*build_controls)(struct hda_codec *codec); int (*build_pcms)(struct hda_codec *codec); int (*init)(struct hda_codec *codec); - void (*free)(struct hda_codec *codec); void (*unsol_event)(struct hda_codec *codec, unsigned int res); void (*set_power_state)(struct hda_codec *codec, hda_nid_t fg, unsigned int power_state); -#ifdef CONFIG_PM int (*suspend)(struct hda_codec *codec); int (*resume)(struct hda_codec *codec); int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid); -#endif void (*stream_pm)(struct hda_codec *codec, hda_nid_t nid, bool on); }; @@ -144,6 +144,7 @@ struct hda_pcm_stream { hda_nid_t nid; /* default NID to query rates/formats/bps, or set up */ u32 rates; /* supported rates */ u64 formats; /* supported formats (SNDRV_PCM_FMTBIT_) */ + u32 subformats; /* for S32_LE format, SNDRV_PCM_SUBFMTBIT_* */ unsigned int maxbps; /* supported max. bit per sample */ const struct snd_pcm_chmap_elem *chmap; /* chmap to override */ struct hda_pcm_ops ops; @@ -185,10 +186,7 @@ struct hda_codec { const struct hda_device_id *preset; const char *modelname; /* model name for preset */ - /* set by patch */ - struct hda_codec_ops patch_ops; - - /* PCM to create, set by patch_ops.build_pcms callback */ + /* PCM to create, set by hda_codec_ops.build_pcms callback */ struct list_head pcm_list_head; refcount_t pcm_ref; wait_queue_head_t remove_sleep; @@ -199,6 +197,7 @@ struct hda_codec { /* beep device */ struct hda_beep *beep; unsigned int beep_mode; + bool beep_just_power_on; /* widget capabilities cache */ u32 *wcaps; @@ -261,11 +260,9 @@ struct hda_codec { unsigned int no_stream_clean_at_suspend:1; /* do not clean streams at suspend */ unsigned int ctl_dev_id:1; /* old control element id build behaviour */ -#ifdef CONFIG_PM unsigned long power_on_acct; unsigned long power_off_acct; unsigned long power_jiffies; -#endif /* filter the requested power state per nid */ unsigned int (*power_filter)(struct hda_codec *codec, hda_nid_t nid, @@ -363,8 +360,8 @@ int snd_hda_override_conn_list(struct hda_codec *codec, hda_nid_t nid, int nums, int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux, hda_nid_t nid, int recursive); unsigned int snd_hda_get_num_devices(struct hda_codec *codec, hda_nid_t nid); -int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, - u8 *dev_list, int max_devices); +unsigned int snd_hda_get_devices(struct hda_codec *codec, hda_nid_t nid, + u8 *dev_list, unsigned int max_devices); int snd_hda_get_dev_select(struct hda_codec *codec, hda_nid_t nid); int snd_hda_set_dev_select(struct hda_codec *codec, hda_nid_t nid, int dev_id); @@ -451,8 +448,8 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid, #define snd_hda_codec_cleanup_stream(codec, nid) \ __snd_hda_codec_cleanup_stream(codec, nid, 0) -#define snd_hda_query_supported_pcm(codec, nid, ratesp, fmtsp, bpsp) \ - snd_hdac_query_supported_pcm(&(codec)->core, nid, ratesp, fmtsp, bpsp) +#define snd_hda_query_supported_pcm(codec, nid, ratesp, fmtsp, subfmtp, bpsp) \ + snd_hdac_query_supported_pcm(&(codec)->core, nid, ratesp, fmtsp, subfmtp, bpsp) #define snd_hda_is_supported_format(codec, nid, fmt) \ snd_hdac_is_supported_format(&(codec)->core, nid, fmt) @@ -483,10 +480,10 @@ extern const struct dev_pm_ops hda_codec_driver_pm; static inline int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid) { -#ifdef CONFIG_PM - if (codec->patch_ops.check_power_status) - return codec->patch_ops.check_power_status(codec, nid); -#endif + struct hda_codec_driver *driver = hda_codec_to_driver(codec); + + if (driver->ops && driver->ops->check_power_status) + return driver->ops->check_power_status(codec, nid); return 0; } @@ -497,20 +494,45 @@ int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid) #define snd_hda_power_up_pm(codec) snd_hdac_power_up_pm(&(codec)->core) #define snd_hda_power_down(codec) snd_hdac_power_down(&(codec)->core) #define snd_hda_power_down_pm(codec) snd_hdac_power_down_pm(&(codec)->core) -#ifdef CONFIG_PM void snd_hda_codec_set_power_save(struct hda_codec *codec, int delay); void snd_hda_set_power_save(struct hda_bus *bus, int delay); void snd_hda_update_power_acct(struct hda_codec *codec); -#else -static inline void snd_hda_codec_set_power_save(struct hda_codec *codec, int delay) {} -static inline void snd_hda_set_power_save(struct hda_bus *bus, int delay) {} -#endif static inline bool hda_codec_need_resume(struct hda_codec *codec) { return !codec->relaxed_resume && codec->jacktbl.used; } +/* + * PM with auto-cleanup: call like CLASS(snd_hda_power, pm)(codec) + * If the error handling is needed, refer pm.err. + */ +struct __hda_power_obj { + struct hda_codec *codec; + int err; +}; + +static inline struct __hda_power_obj __snd_hda_power_up(struct hda_codec *codec) +{ + struct __hda_power_obj T = { .codec = codec }; + T.err = snd_hda_power_up(codec); + return T; +} + +static inline struct __hda_power_obj __snd_hda_power_up_pm(struct hda_codec *codec) +{ + struct __hda_power_obj T = { .codec = codec }; + T.err = snd_hda_power_up_pm(codec); + return T; +} + +DEFINE_CLASS(snd_hda_power, struct __hda_power_obj, + snd_hda_power_down((_T).codec), __snd_hda_power_up(codec), + struct hda_codec *codec) +DEFINE_CLASS(snd_hda_power_pm, struct __hda_power_obj, + snd_hda_power_down_pm((_T).codec), __snd_hda_power_up_pm(codec), + struct hda_codec *codec) + #ifdef CONFIG_SND_HDA_PATCH_LOADER /* * patch firmware diff --git a/include/sound/hda_register.h b/include/sound/hda_register.h index 9c7872c0ca79..db1cc0b897fd 100644 --- a/include/sound/hda_register.h +++ b/include/sound/hda_register.h @@ -91,6 +91,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define AZX_REG_SD_BDLPL 0x18 #define AZX_REG_SD_BDLPU 0x1c +#define AZX_SD_FIFOSIZE_MASK GENMASK(15, 0) + /* GTS registers */ #define AZX_REG_LLCH 0x14 @@ -129,6 +131,8 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define AZX_REG_VS_SDXEFIFOS_XBASE 0x1094 #define AZX_REG_VS_SDXEFIFOS_XINTERVAL 0x20 +#define AZX_REG_VS_LTRP_GB_MASK GENMASK(6, 0) + /* PCI space */ #define AZX_PCIREG_TCSEL 0x44 @@ -176,7 +180,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define SD_STS_FIFO_READY 0x20 /* FIFO ready */ /* INTCTL and INTSTS */ -#define AZX_INT_ALL_STREAM 0xff /* all stream interrupts */ +#define AZX_INT_ALL_STREAM 0x3fffffff /* all stream interrupts */ #define AZX_INT_CTRL_EN 0x40000000 /* controller interrupt enable bit */ #define AZX_INT_GLOBAL_EN 0x80000000 /* global interrupt enable bit */ diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index 2ffdf58bd6d4..4e0c1d8af09f 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -11,13 +11,14 @@ #include <linux/io.h> #include <linux/io-64-nonatomic-lo-hi.h> #include <linux/iopoll.h> +#include <linux/pci.h> #include <linux/pm_runtime.h> #include <linux/timecounter.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/memalloc.h> #include <sound/hda_verbs.h> -#include <drm/i915_component.h> +#include <drm/intel/i915_component.h> /* codec node id */ typedef u16 hda_nid_t; @@ -32,7 +33,7 @@ struct hda_device_id; /* * exported bus type */ -extern struct bus_type snd_hda_bus_type; +extern const struct bus_type snd_hda_bus_type; /* * generic arrays @@ -139,13 +140,14 @@ int snd_hdac_get_connections(struct hdac_device *codec, hda_nid_t nid, hda_nid_t *conn_list, int max_conns); int snd_hdac_get_sub_nodes(struct hdac_device *codec, hda_nid_t nid, hda_nid_t *start_id); -unsigned int snd_hdac_calc_stream_format(unsigned int rate, - unsigned int channels, - snd_pcm_format_t format, - unsigned int maxbps, - unsigned short spdif_ctls); +unsigned int snd_hdac_stream_format_bits(snd_pcm_format_t format, snd_pcm_subformat_t subformat, + unsigned int maxbits); +unsigned int snd_hdac_stream_format(unsigned int channels, unsigned int bits, unsigned int rate); +unsigned int snd_hdac_spdif_stream_format(unsigned int channels, unsigned int bits, + unsigned int rate, unsigned short spdif_ctls); int snd_hdac_query_supported_pcm(struct hdac_device *codec, hda_nid_t nid, - u32 *ratesp, u64 *formatsp, unsigned int *bpsp); + u32 *ratesp, u64 *formatsp, u32 *subformatsp, + unsigned int *bpsp); bool snd_hdac_is_supported_format(struct hdac_device *codec, hda_nid_t nid, unsigned int format); @@ -221,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 */ @@ -233,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 @@ -349,6 +351,7 @@ struct hdac_bus { bool needs_damn_long_delay:1; bool not_use_interrupts:1; /* prohibiting the RIRB IRQ */ bool access_sdnctl_in_dword:1; /* accessing the sdnctl register by dword */ + bool use_pio_for_commands:1; /* Use PIO instead of CORB for commands */ int poll_count; @@ -572,7 +575,7 @@ void snd_hdac_stream_release(struct hdac_stream *azx_dev); struct hdac_stream *snd_hdac_get_stream(struct hdac_bus *bus, int dir, int stream_tag); -int snd_hdac_stream_setup(struct hdac_stream *azx_dev); +int snd_hdac_stream_setup(struct hdac_stream *azx_dev, bool code_loading); void snd_hdac_stream_cleanup(struct hdac_stream *azx_dev); int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev); int snd_hdac_stream_set_params(struct hdac_stream *azx_dev, @@ -587,7 +590,7 @@ void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set, void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start, unsigned int streams); void snd_hdac_stream_timecounter_init(struct hdac_stream *azx_dev, - unsigned int streams); + unsigned int streams, bool start); int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus, struct snd_pcm_substream *substream); @@ -595,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); @@ -623,6 +624,9 @@ int snd_hdac_stream_set_lpib(struct hdac_stream *azx_dev, u32 value); #define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \ read_poll_timeout_atomic(snd_hdac_reg_readb, val, cond, delay_us, timeout_us, \ false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg) +#define snd_hdac_stream_readw_poll(dev, reg, val, cond, delay_us, timeout_us) \ + read_poll_timeout_atomic(snd_hdac_reg_readw, val, cond, delay_us, timeout_us, \ + false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg) #define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \ read_poll_timeout_atomic(snd_hdac_reg_readl, val, cond, delay_us, timeout_us, \ false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg) @@ -647,6 +651,7 @@ int snd_hdac_stream_set_lpib(struct hdac_stream *azx_dev, u32 value); #define snd_hdac_dsp_lock(dev) mutex_lock(&(dev)->dsp_mutex) #define snd_hdac_dsp_unlock(dev) mutex_unlock(&(dev)->dsp_mutex) #define snd_hdac_stream_is_locked(dev) ((dev)->locked) +DEFINE_GUARD(snd_hdac_dsp_lock, struct hdac_stream *, snd_hdac_dsp_lock(_T), snd_hdac_dsp_unlock(_T)) /* DSP loader helpers */ int snd_hdac_dsp_prepare(struct hdac_stream *azx_dev, unsigned int format, unsigned int byte_size, struct snd_dma_buffer *bufp); @@ -676,6 +681,30 @@ static inline void snd_hdac_dsp_cleanup(struct hdac_stream *azx_dev, } #endif /* CONFIG_SND_HDA_DSP_LOADER */ +/* + * Easy macros for widget capabilities + */ +#define snd_hdac_get_wcaps(codec, nid) \ + snd_hdac_read_parm(codec, nid, AC_PAR_AUDIO_WIDGET_CAP) + +/* get the widget type from widget capability bits */ +static inline int snd_hdac_get_wcaps_type(unsigned int wcaps) +{ + if (!wcaps) + return -1; /* invalid type */ + return (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; +} + +/* get the number of supported channels */ +static inline unsigned int snd_hdac_get_wcaps_channels(u32 wcaps) +{ + unsigned int chans; + + chans = (wcaps & AC_WCAP_CHAN_CNT_EXT) >> 13; + chans = (chans + 1) * 2; + + return chans; +} /* * generic array helpers @@ -704,4 +733,30 @@ static inline unsigned int snd_array_index(struct snd_array *array, void *ptr) for ((idx) = 0, (ptr) = (array)->list; (idx) < (array)->used; \ (ptr) = snd_array_elem(array, ++(idx))) +/* + * Device matching + */ + +#define HDA_CONTROLLER_IS_HSW(pci) (pci_match_id((struct pci_device_id []){ \ + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_HSW_0) }, \ + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_HSW_2) }, \ + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_HSW_3) }, \ + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_BDW) }, \ + { } \ + }, pci)) + +#define HDA_CONTROLLER_IS_APL(pci) (pci_match_id((struct pci_device_id []){ \ + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_APL) }, \ + { } \ + }, pci)) + +#define HDA_CONTROLLER_IN_GPU(pci) (pci_match_id((struct pci_device_id []){ \ + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG1) }, \ + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG2_0) }, \ + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG2_1) }, \ + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_DG2_2) }, \ + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HDA_BMG) }, \ + { } \ + }, pci) || HDA_CONTROLLER_IS_HSW(pci)) + #endif /* __SOUND_HDAUDIO_H */ diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index 511211f4a2b6..7de390022ac2 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -2,8 +2,6 @@ #ifndef __SOUND_HDAUDIO_EXT_H #define __SOUND_HDAUDIO_EXT_H -#include <linux/io-64-nonatomic-lo-hi.h> -#include <linux/iopoll.h> #include <sound/hdaudio.h> int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, @@ -24,6 +22,7 @@ void snd_hdac_ext_bus_ppcap_enable(struct hdac_bus *chip, bool enable); void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_bus *chip, bool enable); int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_bus *bus); +struct hdac_ext_link *snd_hdac_ext_bus_get_hlink_by_id(struct hdac_bus *bus, u32 id); struct hdac_ext_link *snd_hdac_ext_bus_get_hlink_by_addr(struct hdac_bus *bus, int addr); struct hdac_ext_link *snd_hdac_ext_bus_get_hlink_by_name(struct hdac_bus *bus, const char *codec_name); @@ -56,10 +55,15 @@ struct hdac_ext_stream { u32 pphcldpl; u32 pphcldpu; + u32 pplcllpl; + u32 pplcllpu; + bool decoupled:1; bool link_locked:1; bool link_prepared; + int (*host_setup)(struct hdac_stream *, bool); + struct snd_pcm_substream *link_substream; }; @@ -86,6 +90,7 @@ void snd_hdac_ext_stream_start(struct hdac_ext_stream *hext_stream); void snd_hdac_ext_stream_clear(struct hdac_ext_stream *hext_stream); void snd_hdac_ext_stream_reset(struct hdac_ext_stream *hext_stream); int snd_hdac_ext_stream_setup(struct hdac_ext_stream *hext_stream, int fmt); +int snd_hdac_ext_host_stream_setup(struct hdac_ext_stream *hext_stream, bool code_loading); struct hdac_ext_link { struct hdac_bus *bus; @@ -93,12 +98,17 @@ struct hdac_ext_link { void __iomem *ml_addr; /* link output stream reg pointer */ u32 lcaps; /* link capablities */ u16 lsdiid; /* link sdi identifier */ + u32 id; + u8 slcount; int ref_count; struct list_head list; }; +#define hdac_ext_link_alt(link) ((link)->lcaps & AZX_ML_HDA_LCAP_ALT) +#define hdac_ext_link_ofls(link) ((link)->lcaps & AZX_ML_HDA_LCAP_OFLS) + int snd_hdac_ext_bus_link_power_up(struct hdac_ext_link *hlink); int snd_hdac_ext_bus_link_power_down(struct hdac_ext_link *hlink); int snd_hdac_ext_bus_link_power_up_all(struct hdac_bus *bus); @@ -113,49 +123,6 @@ int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *hlink) void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable); -#define snd_hdac_adsp_writeb(chip, reg, value) \ - snd_hdac_reg_writeb(chip, (chip)->dsp_ba + (reg), value) -#define snd_hdac_adsp_readb(chip, reg) \ - snd_hdac_reg_readb(chip, (chip)->dsp_ba + (reg)) -#define snd_hdac_adsp_writew(chip, reg, value) \ - snd_hdac_reg_writew(chip, (chip)->dsp_ba + (reg), value) -#define snd_hdac_adsp_readw(chip, reg) \ - snd_hdac_reg_readw(chip, (chip)->dsp_ba + (reg)) -#define snd_hdac_adsp_writel(chip, reg, value) \ - snd_hdac_reg_writel(chip, (chip)->dsp_ba + (reg), value) -#define snd_hdac_adsp_readl(chip, reg) \ - snd_hdac_reg_readl(chip, (chip)->dsp_ba + (reg)) -#define snd_hdac_adsp_writeq(chip, reg, value) \ - snd_hdac_reg_writeq(chip, (chip)->dsp_ba + (reg), value) -#define snd_hdac_adsp_readq(chip, reg) \ - snd_hdac_reg_readq(chip, (chip)->dsp_ba + (reg)) - -#define snd_hdac_adsp_updateb(chip, reg, mask, val) \ - snd_hdac_adsp_writeb(chip, reg, \ - (snd_hdac_adsp_readb(chip, reg) & ~(mask)) | (val)) -#define snd_hdac_adsp_updatew(chip, reg, mask, val) \ - snd_hdac_adsp_writew(chip, reg, \ - (snd_hdac_adsp_readw(chip, reg) & ~(mask)) | (val)) -#define snd_hdac_adsp_updatel(chip, reg, mask, val) \ - snd_hdac_adsp_writel(chip, reg, \ - (snd_hdac_adsp_readl(chip, reg) & ~(mask)) | (val)) -#define snd_hdac_adsp_updateq(chip, reg, mask, val) \ - snd_hdac_adsp_writeq(chip, reg, \ - (snd_hdac_adsp_readq(chip, reg) & ~(mask)) | (val)) - -#define snd_hdac_adsp_readb_poll(chip, reg, val, cond, delay_us, timeout_us) \ - readb_poll_timeout((chip)->dsp_ba + (reg), val, cond, \ - delay_us, timeout_us) -#define snd_hdac_adsp_readw_poll(chip, reg, val, cond, delay_us, timeout_us) \ - readw_poll_timeout((chip)->dsp_ba + (reg), val, cond, \ - delay_us, timeout_us) -#define snd_hdac_adsp_readl_poll(chip, reg, val, cond, delay_us, timeout_us) \ - readl_poll_timeout((chip)->dsp_ba + (reg), val, cond, \ - delay_us, timeout_us) -#define snd_hdac_adsp_readq_poll(chip, reg, val, cond, delay_us, timeout_us) \ - readq_poll_timeout((chip)->dsp_ba + (reg), val, cond, \ - delay_us, timeout_us) - struct hdac_ext_device; /* ops common to all codec drivers */ diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h index 9b162ac1e08e..273f4c36fad9 100644 --- a/include/sound/hdmi-codec.h +++ b/include/sound/hdmi-codec.h @@ -12,7 +12,6 @@ #include <linux/of_graph.h> #include <linux/hdmi.h> -#include <drm/drm_edid.h> #include <sound/asoundef.h> #include <sound/soc.h> #include <uapi/sound/asound.h> @@ -106,7 +105,8 @@ struct hdmi_codec_ops { * Optional */ int (*get_dai_id)(struct snd_soc_component *comment, - struct device_node *endpoint); + struct device_node *endpoint, + void *data); /* * Hook callback function to handle connector plug event. @@ -115,20 +115,19 @@ struct hdmi_codec_ops { int (*hook_plugged_cb)(struct device *dev, void *data, hdmi_codec_plugged_cb fn, struct device *codec_dev); - - /* bit field */ - unsigned int no_capture_mute:1; }; /* HDMI codec initalization data */ struct hdmi_codec_pdata { const struct hdmi_codec_ops *ops; + u64 i2s_formats; uint i2s:1; uint no_i2s_playback:1; uint no_i2s_capture:1; uint spdif:1; uint no_spdif_playback:1; uint no_spdif_capture:1; + uint no_capture_mute:1; int max_i2s_channels; void *data; }; diff --git a/include/sound/hwdep.h b/include/sound/hwdep.h index 8d6cdb254039..b0da633184cd 100644 --- a/include/sound/hwdep.h +++ b/include/sound/hwdep.h @@ -53,7 +53,7 @@ struct snd_hwdep { wait_queue_head_t open_wait; void *private_data; void (*private_free) (struct snd_hwdep *hwdep); - struct device dev; + struct device *dev; struct mutex open_mutex; int used; /* reference counter */ diff --git a/include/sound/info.h b/include/sound/info.h index 7c13bf52cc81..adbc506860d6 100644 --- a/include/sound/info.h +++ b/include/sound/info.h @@ -118,8 +118,6 @@ struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card, const char *name, struct snd_info_entry *parent); void snd_info_free_entry(struct snd_info_entry *entry); -int snd_info_store_text(struct snd_info_entry *entry); -int snd_info_restore_text(struct snd_info_entry *entry); int snd_info_card_create(struct snd_card *card); int snd_info_card_register(struct snd_card *card); diff --git a/include/sound/intel-nhlt.h b/include/sound/intel-nhlt.h index 53470d6a28d6..24dbe16684ae 100644 --- a/include/sound/intel-nhlt.h +++ b/include/sound/intel-nhlt.h @@ -143,6 +143,9 @@ intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt, u32 bus_id, u8 link_type, u8 vbps, u8 bps, u8 num_ch, u32 rate, u8 dir, u8 dev_type); +int intel_nhlt_ssp_device_type(struct device *dev, struct nhlt_acpi_table *nhlt, + u8 virtual_bus_id); + #else static inline struct nhlt_acpi_table *intel_nhlt_init(struct device *dev) @@ -184,6 +187,13 @@ intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt, return NULL; } +static inline int intel_nhlt_ssp_device_type(struct device *dev, + struct nhlt_acpi_table *nhlt, + u8 virtual_bus_id) +{ + return -EINVAL; +} + #endif #endif diff --git a/include/sound/jack.h b/include/sound/jack.h index 1ed90e2109e9..715b95983188 100644 --- a/include/sound/jack.h +++ b/include/sound/jack.h @@ -22,6 +22,7 @@ struct input_dev; * @SND_JACK_VIDEOOUT: Video out * @SND_JACK_AVOUT: AV (Audio Video) out * @SND_JACK_LINEIN: Line in + * @SND_JACK_USB: USB audio device * @SND_JACK_BTN_0: Button 0 * @SND_JACK_BTN_1: Button 1 * @SND_JACK_BTN_2: Button 2 @@ -43,6 +44,7 @@ enum snd_jack_types { SND_JACK_VIDEOOUT = 0x0010, SND_JACK_AVOUT = SND_JACK_LINEOUT | SND_JACK_VIDEOOUT, SND_JACK_LINEIN = 0x0020, + SND_JACK_USB = 0x0040, /* Kept separate from switches to facilitate implementation */ SND_JACK_BTN_0 = 0x4000, @@ -54,7 +56,7 @@ enum snd_jack_types { }; /* Keep in sync with definitions above */ -#define SND_JACK_SWITCH_TYPES 6 +#define SND_JACK_SWITCH_TYPES 7 struct snd_jack { struct list_head kctl_list; @@ -79,7 +81,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 +105,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/l3.h b/include/sound/l3.h deleted file mode 100644 index b6f58072237a..000000000000 --- a/include/sound/l3.h +++ /dev/null @@ -1,28 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _L3_H_ -#define _L3_H_ 1 - -struct l3_pins { - void (*setdat)(struct l3_pins *, int); - void (*setclk)(struct l3_pins *, int); - void (*setmode)(struct l3_pins *, int); - - int gpio_data; - int gpio_clk; - int gpio_mode; - int use_gpios; - - int data_hold; - int data_setup; - int clock_high; - int mode_hold; - int mode; - int mode_setup; -}; - -struct device; - -int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len); -int l3_set_gpio_ops(struct device *dev, struct l3_pins *adap); - -#endif diff --git a/include/sound/max9768.h b/include/sound/max9768.h index 0f78b41d030e..8509ba0079b0 100644 --- a/include/sound/max9768.h +++ b/include/sound/max9768.h @@ -9,14 +9,10 @@ /** * struct max9768_pdata - optional platform specific MAX9768 configuration - * @shdn_gpio: GPIO to SHDN pin. If not valid, pin must be hardwired HIGH - * @mute_gpio: GPIO to MUTE pin. If not valid, control for mute won't be added * @flags: configuration flags, e.g. set classic PWM mode (check datasheet * regarding "filterless modulation" which is default). */ struct max9768_pdata { - int shdn_gpio; - int mute_gpio; unsigned flags; #define MAX9768_FLAG_CLASSIC_PWM (1 << 0) }; diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h index 43d524580bd2..9dd475cf4e8c 100644 --- a/include/sound/memalloc.h +++ b/include/sound/memalloc.h @@ -42,17 +42,12 @@ struct snd_dma_device { #define SNDRV_DMA_TYPE_NONCONTIG 8 /* non-coherent SG buffer */ #define SNDRV_DMA_TYPE_NONCOHERENT 9 /* non-coherent buffer */ #ifdef CONFIG_SND_DMA_SGBUF -#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_NONCONTIG +#define SNDRV_DMA_TYPE_DEV_SG 3 /* S/G pages */ #define SNDRV_DMA_TYPE_DEV_WC_SG 6 /* SG write-combined */ #else #define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */ #define SNDRV_DMA_TYPE_DEV_WC_SG SNDRV_DMA_TYPE_DEV_WC #endif -/* fallback types, don't use those directly */ -#ifdef CONFIG_SND_DMA_SGBUF -#define SNDRV_DMA_TYPE_DEV_SG_FALLBACK 10 -#define SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK 11 -#endif /* * info for buffer allocation diff --git a/include/sound/opl3.h b/include/sound/opl3.h index ebf3852da9fe..052395a2f876 100644 --- a/include/sound/opl3.h +++ b/include/sound/opl3.h @@ -229,7 +229,7 @@ struct fm_operator { unsigned char attack_decay; unsigned char sustain_release; unsigned char wave_select; -} __attribute__((packed)); +} __packed; /* Instrument data */ struct fm_instrument { diff --git a/include/sound/pcm.h b/include/sound/pcm.h index 19f564606ac4..58fd6e84f961 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -16,6 +16,7 @@ #include <linux/bitops.h> #include <linux/pm_qos.h> #include <linux/refcount.h> +#include <linux/uio.h> #define snd_pcm_substream_chip(substream) ((substream)->private_data) #define snd_pcm_chip(pcm) ((pcm)->private_data) @@ -31,6 +32,7 @@ struct snd_pcm_hardware { unsigned int info; /* SNDRV_PCM_INFO_* */ u64 formats; /* SNDRV_PCM_FMTBIT_* */ + u32 subformats; /* for S32_LE, SNDRV_PCM_SUBFMTBIT_* */ unsigned int rates; /* SNDRV_PCM_RATE_* */ unsigned int rate_min; /* min rate */ unsigned int rate_max; /* max rate */ @@ -68,11 +70,8 @@ struct snd_pcm_ops { struct snd_pcm_audio_tstamp_report *audio_tstamp_report); int (*fill_silence)(struct snd_pcm_substream *substream, int channel, unsigned long pos, unsigned long bytes); - int (*copy_user)(struct snd_pcm_substream *substream, int channel, - unsigned long pos, void __user *buf, - unsigned long bytes); - int (*copy_kernel)(struct snd_pcm_substream *substream, int channel, - unsigned long pos, void *buf, unsigned long bytes); + int (*copy)(struct snd_pcm_substream *substream, int channel, + unsigned long pos, struct iov_iter *iter, unsigned long bytes); struct page *(*page)(struct snd_pcm_substream *substream, unsigned long offset); int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct *vma); @@ -94,14 +93,15 @@ struct snd_pcm_ops { #define SNDRV_PCM_IOCTL1_CHANNEL_INFO 2 /* 3 is absent slot. */ #define SNDRV_PCM_IOCTL1_FIFO_SIZE 4 +#define SNDRV_PCM_IOCTL1_SYNC_ID 5 #define SNDRV_PCM_TRIGGER_STOP 0 #define SNDRV_PCM_TRIGGER_START 1 -#define SNDRV_PCM_TRIGGER_PAUSE_PUSH 3 -#define SNDRV_PCM_TRIGGER_PAUSE_RELEASE 4 -#define SNDRV_PCM_TRIGGER_SUSPEND 5 -#define SNDRV_PCM_TRIGGER_RESUME 6 -#define SNDRV_PCM_TRIGGER_DRAIN 7 +#define SNDRV_PCM_TRIGGER_PAUSE_PUSH 2 +#define SNDRV_PCM_TRIGGER_PAUSE_RELEASE 3 +#define SNDRV_PCM_TRIGGER_SUSPEND 4 +#define SNDRV_PCM_TRIGGER_RESUME 5 +#define SNDRV_PCM_TRIGGER_DRAIN 6 #define SNDRV_PCM_POS_XRUN ((snd_pcm_uframes_t)-1) @@ -121,9 +121,15 @@ struct snd_pcm_ops { #define SNDRV_PCM_RATE_192000 (1U<<12) /* 192000Hz */ #define SNDRV_PCM_RATE_352800 (1U<<13) /* 352800Hz */ #define SNDRV_PCM_RATE_384000 (1U<<14) /* 384000Hz */ +#define SNDRV_PCM_RATE_705600 (1U<<15) /* 705600Hz */ +#define SNDRV_PCM_RATE_768000 (1U<<16) /* 768000Hz */ +/* extended rates since 6.12 */ +#define SNDRV_PCM_RATE_12000 (1U<<17) /* 12000Hz */ +#define SNDRV_PCM_RATE_24000 (1U<<18) /* 24000Hz */ +#define SNDRV_PCM_RATE_128000 (1U<<19) /* 128000Hz */ #define SNDRV_PCM_RATE_CONTINUOUS (1U<<30) /* continuous range */ -#define SNDRV_PCM_RATE_KNOT (1U<<31) /* supports more non-continuos rates */ +#define SNDRV_PCM_RATE_KNOT (1U<<31) /* supports more non-continuous rates */ #define SNDRV_PCM_RATE_8000_44100 (SNDRV_PCM_RATE_8000|SNDRV_PCM_RATE_11025|\ SNDRV_PCM_RATE_16000|SNDRV_PCM_RATE_22050|\ @@ -136,6 +142,9 @@ struct snd_pcm_ops { #define SNDRV_PCM_RATE_8000_384000 (SNDRV_PCM_RATE_8000_192000|\ SNDRV_PCM_RATE_352800|\ SNDRV_PCM_RATE_384000) +#define SNDRV_PCM_RATE_8000_768000 (SNDRV_PCM_RATE_8000_384000|\ + SNDRV_PCM_RATE_705600|\ + SNDRV_PCM_RATE_768000) #define _SNDRV_PCM_FMTBIT(fmt) (1ULL << (__force int)SNDRV_PCM_FORMAT_##fmt) #define SNDRV_PCM_FMTBIT_S8 _SNDRV_PCM_FMTBIT(S8) #define SNDRV_PCM_FMTBIT_U8 _SNDRV_PCM_FMTBIT(U8) @@ -219,6 +228,12 @@ struct snd_pcm_ops { #define SNDRV_PCM_FMTBIT_U20 SNDRV_PCM_FMTBIT_U20_BE #endif +#define _SNDRV_PCM_SUBFMTBIT(fmt) BIT((__force int)SNDRV_PCM_SUBFORMAT_##fmt) +#define SNDRV_PCM_SUBFMTBIT_STD _SNDRV_PCM_SUBFMTBIT(STD) +#define SNDRV_PCM_SUBFMTBIT_MSBITS_MAX _SNDRV_PCM_SUBFMTBIT(MSBITS_MAX) +#define SNDRV_PCM_SUBFMTBIT_MSBITS_20 _SNDRV_PCM_SUBFMTBIT(MSBITS_20) +#define SNDRV_PCM_SUBFMTBIT_MSBITS_24 _SNDRV_PCM_SUBFMTBIT(MSBITS_24) + struct snd_pcm_file { struct snd_pcm_substream *substream; int no_compat_mmap; @@ -391,7 +406,7 @@ struct snd_pcm_runtime { snd_pcm_uframes_t silence_start; /* starting pointer to silence area */ snd_pcm_uframes_t silence_filled; /* already filled part of silence area */ - union snd_pcm_sync_id sync; /* hardware synchronization ID */ + bool std_sync_id; /* hardware synchronization - standard per card ID */ /* -- mmap -- */ struct snd_pcm_mmap_status *status; @@ -487,6 +502,9 @@ struct snd_pcm_substream { /* misc flags */ unsigned int hw_opened: 1; unsigned int managed_buffer_alloc:1; +#ifdef CONFIG_SND_PCM_XRUN_DEBUG + unsigned int xrun_counter; /* number of times xrun happens */ +#endif /* CONFIG_SND_PCM_XRUN_DEBUG */ }; #define SUBSTREAM_BUSY(substream) ((substream)->ref_count > 0) @@ -510,7 +528,7 @@ struct snd_pcm_str { #endif #endif struct snd_kcontrol *chmap_kctl; /* channel-mapping controls */ - struct device dev; + struct device *dev; }; struct snd_pcm { @@ -654,6 +672,18 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, flags = _snd_pcm_stream_lock_irqsave_nested(substream); \ } while (0) +/* definitions for guard(); use like guard(pcm_stream_lock) */ +DEFINE_LOCK_GUARD_1(pcm_stream_lock, struct snd_pcm_substream, + snd_pcm_stream_lock(_T->lock), + snd_pcm_stream_unlock(_T->lock)) +DEFINE_LOCK_GUARD_1(pcm_stream_lock_irq, struct snd_pcm_substream, + snd_pcm_stream_lock_irq(_T->lock), + snd_pcm_stream_unlock_irq(_T->lock)) +DEFINE_LOCK_GUARD_1(pcm_stream_lock_irqsave, struct snd_pcm_substream, + snd_pcm_stream_lock_irqsave(_T->lock, _T->flags), + snd_pcm_stream_unlock_irqrestore(_T->lock, _T->flags), + unsigned long flags) + /** * snd_pcm_group_for_each_entry - iterate over the linked substreams * @s: the iterator @@ -1133,7 +1163,18 @@ int snd_pcm_format_set_silence(snd_pcm_format_t format, void *buf, unsigned int void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, const struct snd_pcm_ops *ops); -void snd_pcm_set_sync(struct snd_pcm_substream *substream); +void snd_pcm_set_sync_per_card(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, + const unsigned char *id, unsigned int len); +/** + * snd_pcm_set_sync - set the PCM sync id + * @substream: the pcm substream + * + * Use the default PCM sync identifier for the specific card. + */ +static inline void snd_pcm_set_sync(struct snd_pcm_substream *substream) +{ + substream->runtime->std_sync_id = true; +} int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); void snd_pcm_period_elapsed_under_stream_lock(struct snd_pcm_substream *substream); @@ -1210,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 @@ -1321,48 +1360,6 @@ snd_pcm_set_fixed_buffer_all(struct snd_pcm *pcm, int type, return snd_pcm_set_managed_buffer_all(pcm, type, data, size, 0); } -int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream, - size_t size, gfp_t gfp_flags); -int snd_pcm_lib_free_vmalloc_buffer(struct snd_pcm_substream *substream); -struct page *snd_pcm_lib_get_vmalloc_page(struct snd_pcm_substream *substream, - unsigned long offset); -/** - * snd_pcm_lib_alloc_vmalloc_buffer - allocate virtual DMA buffer - * @substream: the substream to allocate the buffer to - * @size: the requested buffer size, in bytes - * - * Allocates the PCM substream buffer using vmalloc(), i.e., the memory is - * contiguous in kernel virtual space, but not in physical memory. Use this - * if the buffer is accessed by kernel code but not by device DMA. - * - * Return: 1 if the buffer was changed, 0 if not changed, or a negative error - * code. - */ -static inline int snd_pcm_lib_alloc_vmalloc_buffer - (struct snd_pcm_substream *substream, size_t size) -{ - return _snd_pcm_lib_alloc_vmalloc_buffer(substream, size, - GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); -} - -/** - * snd_pcm_lib_alloc_vmalloc_32_buffer - allocate 32-bit-addressable buffer - * @substream: the substream to allocate the buffer to - * @size: the requested buffer size, in bytes - * - * This function works like snd_pcm_lib_alloc_vmalloc_buffer(), but uses - * vmalloc_32(), i.e., the pages are allocated from 32-bit-addressable memory. - * - * Return: 1 if the buffer was changed, 0 if not changed, or a negative error - * code. - */ -static inline int snd_pcm_lib_alloc_vmalloc_32_buffer - (struct snd_pcm_substream *substream, size_t size) -{ - return _snd_pcm_lib_alloc_vmalloc_buffer(substream, size, - GFP_KERNEL | GFP_DMA32 | __GFP_ZERO); -} - #define snd_pcm_get_dma_buf(substream) ((substream)->runtime->dma_buffer_p) /** @@ -1394,30 +1391,6 @@ snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, return snd_sgbuf_get_chunk_size(snd_pcm_get_dma_buf(substream), ofs, size); } -/** - * snd_pcm_mmap_data_open - increase the mmap counter - * @area: VMA - * - * PCM mmap callback should handle this counter properly - */ -static inline void snd_pcm_mmap_data_open(struct vm_area_struct *area) -{ - struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; - atomic_inc(&substream->mmap_count); -} - -/** - * snd_pcm_mmap_data_close - decrease the mmap counter - * @area: VMA - * - * PCM mmap callback should handle this counter properly - */ -static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area) -{ - struct snd_pcm_substream *substream = (struct snd_pcm_substream *)area->vm_private_data; - atomic_dec(&substream->mmap_count); -} - int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *area); /* mmap for io-memory area */ @@ -1429,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 @@ -1556,6 +1531,12 @@ static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format) #define pcm_dbg(pcm, fmt, args...) \ dev_dbg((pcm)->card->dev, fmt, ##args) +/* helpers for copying between iov_iter and iomem */ +size_t copy_to_iter_fromio(const void __iomem *src, size_t bytes, + struct iov_iter *iter) __must_check; +size_t copy_from_iter_toio(void __iomem *dst, size_t bytes, + struct iov_iter *iter) __must_check; + struct snd_pcm_status64 { snd_pcm_state_t state; /* stream state */ u8 rsvd[4]; diff --git a/include/sound/pcm_drm_eld.h b/include/sound/pcm_drm_eld.h index 28a55a8beb28..5a38413ada91 100644 --- a/include/sound/pcm_drm_eld.h +++ b/include/sound/pcm_drm_eld.h @@ -2,6 +2,97 @@ #ifndef __SOUND_PCM_DRM_ELD_H #define __SOUND_PCM_DRM_ELD_H +enum eld_versions { + ELD_VER_CEA_861D = 2, + ELD_VER_PARTIAL = 31, +}; + +enum cea_audio_coding_types { + AUDIO_CODING_TYPE_REF_STREAM_HEADER = 0, + AUDIO_CODING_TYPE_LPCM = 1, + AUDIO_CODING_TYPE_AC3 = 2, + AUDIO_CODING_TYPE_MPEG1 = 3, + AUDIO_CODING_TYPE_MP3 = 4, + AUDIO_CODING_TYPE_MPEG2 = 5, + AUDIO_CODING_TYPE_AACLC = 6, + AUDIO_CODING_TYPE_DTS = 7, + AUDIO_CODING_TYPE_ATRAC = 8, + AUDIO_CODING_TYPE_SACD = 9, + AUDIO_CODING_TYPE_EAC3 = 10, + AUDIO_CODING_TYPE_DTS_HD = 11, + AUDIO_CODING_TYPE_MLP = 12, + AUDIO_CODING_TYPE_DST = 13, + AUDIO_CODING_TYPE_WMAPRO = 14, + AUDIO_CODING_TYPE_REF_CXT = 15, + /* also include valid xtypes below */ + AUDIO_CODING_TYPE_HE_AAC = 15, + AUDIO_CODING_TYPE_HE_AAC2 = 16, + AUDIO_CODING_TYPE_MPEG_SURROUND = 17, +}; + +enum cea_audio_coding_xtypes { + AUDIO_CODING_XTYPE_HE_REF_CT = 0, + AUDIO_CODING_XTYPE_HE_AAC = 1, + AUDIO_CODING_XTYPE_HE_AAC2 = 2, + AUDIO_CODING_XTYPE_MPEG_SURROUND = 3, + AUDIO_CODING_XTYPE_FIRST_RESERVED = 4, +}; + +/* + * CEA Short Audio Descriptor data + */ +struct snd_cea_sad { + int channels; + int format; /* (format == 0) indicates invalid SAD */ + int rates; + int sample_bits; /* for LPCM */ + int max_bitrate; /* for AC3...ATRAC */ + int profile; /* for WMAPRO */ +}; + +#define ELD_FIXED_BYTES 20 +#define ELD_MAX_SIZE 256 +#define ELD_MAX_MNL 16 +#define ELD_MAX_SAD 16 + +#define ELD_PCM_BITS_8 BIT(0) +#define ELD_PCM_BITS_16 BIT(1) +#define ELD_PCM_BITS_20 BIT(2) +#define ELD_PCM_BITS_24 BIT(3) +#define ELD_PCM_BITS_32 BIT(4) + +/* + * ELD: EDID Like Data + */ +struct snd_parsed_hdmi_eld { + /* + * all fields will be cleared before updating ELD + */ + int baseline_len; + int eld_ver; + int cea_edid_ver; + char monitor_name[ELD_MAX_MNL + 1]; + int manufacture_id; + int product_id; + u64 port_id; + int support_hdcp; + int support_ai; + int conn_type; + int aud_synch_delay; + int spk_alloc; + int sad_count; + struct snd_cea_sad sad[ELD_MAX_SAD]; +}; + int snd_pcm_hw_constraint_eld(struct snd_pcm_runtime *runtime, void *eld); +int snd_parse_eld(struct device *dev, struct snd_parsed_hdmi_eld *e, + const unsigned char *buf, int size); +void snd_show_eld(struct device *dev, struct snd_parsed_hdmi_eld *e); + +#ifdef CONFIG_SND_PROC_FS +void snd_print_eld_info(struct snd_parsed_hdmi_eld *eld, + struct snd_info_buffer *buffer); +#endif + #endif diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h index ba184f49f7e1..fbf35df6e5cf 100644 --- a/include/sound/pcm_params.h +++ b/include/sound/pcm_params.h @@ -362,6 +362,8 @@ static inline int params_physical_width(const struct snd_pcm_hw_params *p) return snd_pcm_format_physical_width(params_format(p)); } +int snd_pcm_hw_params_bits(const struct snd_pcm_hw_params *p); + static inline void params_set_format(struct snd_pcm_hw_params *p, snd_pcm_format_t fmt) { diff --git a/include/sound/q6usboffload.h b/include/sound/q6usboffload.h new file mode 100644 index 000000000000..f7e2449fe1b3 --- /dev/null +++ b/include/sound/q6usboffload.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * sound/q6usboffload.h -- QDSP6 USB offload + * + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +/** + * struct q6usb_offload - USB backend DAI link offload parameters + * @dev: dev handle to usb be + * @domain: allocated iommu domain + * @intr_num: usb interrupter number + * @sid: streamID for iommu + **/ +struct q6usb_offload { + struct device *dev; + struct iommu_domain *domain; + u16 intr_num; + u8 sid; +}; diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index b0197b1d1fe4..6916f7133597 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h @@ -89,6 +89,7 @@ struct snd_rawmidi_substream { unsigned int framing; /* whether to frame input data */ unsigned int clock_type; /* clock source to use for input framing */ int use_count; /* use counter (for output) */ + bool inactive; /* inactive substream (for UMP legacy) */ size_t bytes; spinlock_t lock; struct snd_rawmidi *rmidi; @@ -118,6 +119,7 @@ struct snd_rawmidi { struct list_head list; unsigned int device; /* device number */ unsigned int info_flags; /* SNDRV_RAWMIDI_INFO_XXXX */ + unsigned int tied_device; char id[64]; char name[80]; @@ -135,7 +137,7 @@ struct snd_rawmidi { struct mutex open_mutex; wait_queue_head_t open_wait; - struct device dev; + struct device *dev; struct snd_info_entry *proc_entry; @@ -189,4 +191,13 @@ long snd_rawmidi_kernel_read(struct snd_rawmidi_substream *substream, long snd_rawmidi_kernel_write(struct snd_rawmidi_substream *substream, const unsigned char *buf, long count); +/* set up the tied devices */ +static inline void snd_rawmidi_tie_devices(struct snd_rawmidi *r1, + struct snd_rawmidi *r2) +{ + /* tied_device field keeps the device+1 (so that 0 being unknown) */ + r1->tied_device = r2->device + 1; + r2->tied_device = r1->device + 1; +} + #endif /* __SOUND_RAWMIDI_H */ diff --git a/include/sound/rt1318.h b/include/sound/rt1318.h new file mode 100644 index 000000000000..fe6bff06036c --- /dev/null +++ b/include/sound/rt1318.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * linux/sound/rt1318.h -- Platform data for RT1318 + * + * Copyright 2024 Realtek Semiconductor Corp. + */ + +#ifndef __LINUX_SND_RT1318_H +#define __LINUX_SND_RT1318_H + +struct rt1318_platform_data { + unsigned int init_r0_l; + unsigned int init_r0_r; +}; + +#endif diff --git a/include/sound/rt5665.h b/include/sound/rt5665.h index 3b3d6a19ca49..e865f041929b 100644 --- a/include/sound/rt5665.h +++ b/include/sound/rt5665.h @@ -31,8 +31,6 @@ struct rt5665_platform_data { bool in3_diff; bool in4_diff; - int ldo1_en; /* GPIO for LDO1_EN */ - enum rt5665_dmic1_data_pin dmic1_data_pin; enum rt5665_dmic2_data_pin dmic2_data_pin; enum rt5665_jd_src jd_src; diff --git a/include/sound/rt5668.h b/include/sound/rt5668.h index 182edfbc9e7a..b682418c6cd6 100644 --- a/include/sound/rt5668.h +++ b/include/sound/rt5668.h @@ -25,9 +25,6 @@ enum rt5668_jd_src { }; struct rt5668_platform_data { - - int ldo1_en; /* GPIO for LDO1_EN */ - enum rt5668_dmic1_data_pin dmic1_data_pin; enum rt5668_dmic1_clk_pin dmic1_clk_pin; enum rt5668_jd_src jd_src; diff --git a/include/sound/rt5682.h b/include/sound/rt5682.h index 3900a07e3935..4256df721e3a 100644 --- a/include/sound/rt5682.h +++ b/include/sound/rt5682.h @@ -31,9 +31,6 @@ enum rt5682_dai_clks { }; struct rt5682_platform_data { - - int ldo1_en; /* GPIO for LDO1_EN */ - enum rt5682_dmic1_data_pin dmic1_data_pin; enum rt5682_dmic1_clk_pin dmic1_clk_pin; enum rt5682_jd_src jd_src; diff --git a/include/sound/rt5682s.h b/include/sound/rt5682s.h index f18d91308b9a..006e6003d11c 100644 --- a/include/sound/rt5682s.h +++ b/include/sound/rt5682s.h @@ -31,16 +31,21 @@ enum rt5682s_dai_clks { RT5682S_DAI_NUM_CLKS, }; -struct rt5682s_platform_data { - - int ldo1_en; /* GPIO for LDO1_EN */ +enum { + RT5682S_LDO_1_607V, + RT5682S_LDO_1_5V, + RT5682S_LDO_1_406V, + RT5682S_LDO_1_731V, +}; +struct rt5682s_platform_data { enum rt5682s_dmic1_data_pin dmic1_data_pin; enum rt5682s_dmic1_clk_pin dmic1_clk_pin; enum rt5682s_jd_src jd_src; unsigned int dmic_clk_rate; unsigned int dmic_delay; unsigned int amic_delay; + unsigned int ldo_dacref; bool dmic_clk_driving_high; const char *dai_clk_names[RT5682S_DAI_NUM_CLKS]; diff --git a/include/sound/sb.h b/include/sound/sb.h index f540339fb0c7..24970f36c38a 100644 --- a/include/sound/sb.h +++ b/include/sound/sb.h @@ -290,6 +290,9 @@ int snd_sbmixer_new(struct snd_sb *chip); #ifdef CONFIG_PM void snd_sbmixer_suspend(struct snd_sb *chip); void snd_sbmixer_resume(struct snd_sb *chip); +#else +static inline void snd_sbmixer_suspend(struct snd_sb *chip) {} +static inline void snd_sbmixer_resume(struct snd_sb *chip) {} #endif /* sb8_init.c */ diff --git a/include/sound/sdca.h b/include/sound/sdca.h new file mode 100644 index 000000000000..67ff3c88705d --- /dev/null +++ b/include/sound/sdca.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * The MIPI SDCA specification is available for public downloads at + * https://www.mipi.org/mipi-sdca-v1-0-download + * + * Copyright(c) 2024 Intel Corporation + */ + +#ifndef __SDCA_H__ +#define __SDCA_H__ + +#include <linux/types.h> +#include <linux/kconfig.h> + +struct acpi_table_swft; +struct fwnode_handle; +struct sdw_slave; +struct sdca_dev; + +#define SDCA_MAX_FUNCTION_COUNT 8 + +/** + * struct sdca_function_desc - short descriptor for an SDCA Function + * @node: firmware node for the Function. + * @func_dev: pointer to SDCA function device. + * @name: Human-readable string. + * @type: Function topology type. + * @adr: ACPI address (used for SDCA register access). + */ +struct sdca_function_desc { + struct fwnode_handle *node; + struct sdca_dev *func_dev; + const char *name; + u32 type; + u8 adr; +}; + +/** + * struct sdca_device_data - structure containing all SDCA related information + * @interface_revision: Value read from _DSD property, mainly to check + * for changes between silicon versions. + * @num_functions: Total number of supported SDCA functions. Invalid/unsupported + * functions will be skipped. + * @function: Array of function descriptors. + * @swft: Pointer to the SWFT table, if available. + */ +struct sdca_device_data { + u32 interface_revision; + int num_functions; + struct sdca_function_desc function[SDCA_MAX_FUNCTION_COUNT]; + struct acpi_table_swft *swft; +}; + +enum sdca_quirk { + SDCA_QUIRKS_RT712_VB, + SDCA_QUIRKS_SKIP_FUNC_TYPE_PATCHING, +}; + +#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_SOC_SDCA) + +void sdca_lookup_functions(struct sdw_slave *slave); +void sdca_lookup_swft(struct sdw_slave *slave); +void sdca_lookup_interface_revision(struct sdw_slave *slave); +bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk); +int sdca_dev_register_functions(struct sdw_slave *slave); +void sdca_dev_unregister_functions(struct sdw_slave *slave); + +#else + +static inline void sdca_lookup_functions(struct sdw_slave *slave) {} +static inline void sdca_lookup_swft(struct sdw_slave *slave) {} +static inline void sdca_lookup_interface_revision(struct sdw_slave *slave) {} +static inline bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk) +{ + return false; +} + +static inline int sdca_dev_register_functions(struct sdw_slave *slave) +{ + return 0; +} + +static inline void sdca_dev_unregister_functions(struct sdw_slave *slave) {} + +#endif + +#endif diff --git a/include/sound/sdca_asoc.h b/include/sound/sdca_asoc.h new file mode 100644 index 000000000000..aa9124f93218 --- /dev/null +++ b/include/sound/sdca_asoc.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * The MIPI SDCA specification is available for public downloads at + * https://www.mipi.org/mipi-sdca-v1-0-download + * + * Copyright (C) 2025 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef __SDCA_ASOC_H__ +#define __SDCA_ASOC_H__ + +struct device; +struct regmap; +struct sdca_function_data; +struct snd_kcontrol_new; +struct snd_pcm_hw_params; +struct snd_pcm_substream; +struct snd_soc_component_driver; +struct snd_soc_dai; +struct snd_soc_dai_driver; +struct snd_soc_dai_ops; +struct snd_soc_dapm_route; +struct snd_soc_dapm_widget; + +int sdca_asoc_count_component(struct device *dev, struct sdca_function_data *function, + int *num_widgets, int *num_routes, int *num_controls, + int *num_dais); + +int sdca_asoc_populate_dapm(struct device *dev, struct sdca_function_data *function, + struct snd_soc_dapm_widget *widgets, + struct snd_soc_dapm_route *routes); +int sdca_asoc_populate_controls(struct device *dev, + struct sdca_function_data *function, + struct snd_kcontrol_new *kctl); +int sdca_asoc_populate_dais(struct device *dev, struct sdca_function_data *function, + struct snd_soc_dai_driver *dais, + const struct snd_soc_dai_ops *ops); + +int sdca_asoc_populate_component(struct device *dev, + struct sdca_function_data *function, + struct snd_soc_component_driver *component_drv, + struct snd_soc_dai_driver **dai_drv, int *num_dai_drv, + const struct snd_soc_dai_ops *ops); + +int sdca_asoc_set_constraints(struct device *dev, struct regmap *regmap, + struct sdca_function_data *function, + struct snd_pcm_substream *substream, + struct snd_soc_dai *dai); +void sdca_asoc_free_constraints(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai); +int sdca_asoc_get_port(struct device *dev, struct regmap *regmap, + struct sdca_function_data *function, + struct snd_soc_dai *dai); +int sdca_asoc_hw_params(struct device *dev, struct regmap *regmap, + struct sdca_function_data *function, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai); + +#endif // __SDCA_ASOC_H__ diff --git a/include/sound/sdca_fdl.h b/include/sound/sdca_fdl.h new file mode 100644 index 000000000000..fbaf4b384c8a --- /dev/null +++ b/include/sound/sdca_fdl.h @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * The MIPI SDCA specification is available for public downloads at + * https://www.mipi.org/mipi-sdca-v1-0-download + * + * Copyright (C) 2025 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef __SDCA_FDL_H__ +#define __SDCA_FDL_H__ + +#include <linux/completion.h> +#include <linux/workqueue.h> + +struct device; +struct regmap; +struct sdca_fdl_set; +struct sdca_function_data; +struct sdca_interrupt; +struct sdca_interrupt_info; + +/** + * struct fdl_state - FDL state structure to keep data between interrupts + * @begin: Completion indicating the start of an FDL download cycle. + * @done: Completion indicating the end of an FDL download cycle. + * @timeout: Delayed work used for timing out UMP transactions. + * @lock: Mutex to protect between the timeout work and IRQ handlers. + * @interrupt: Pointer to the interrupt struct to which this FDL is attached. + * @set: Pointer to the FDL set currently being downloaded. + * @file_index: Index of the current file being processed. + */ +struct fdl_state { + struct completion begin; + struct completion done; + struct delayed_work timeout; + struct mutex lock; + + struct sdca_interrupt *interrupt; + struct sdca_fdl_set *set; + int file_index; +}; + +#define SDCA_CTL_XU_FDLH_COMPLETE 0 +#define SDCA_CTL_XU_FDLH_MORE_FILES SDCA_CTL_XU_FDLH_SET_IN_PROGRESS +#define SDCA_CTL_XU_FDLH_FILE_AVAILABLE (SDCA_CTL_XU_FDLH_TRANSFERRED_FILE | \ + SDCA_CTL_XU_FDLH_SET_IN_PROGRESS) +#define SDCA_CTL_XU_FDLH_MASK (SDCA_CTL_XU_FDLH_TRANSFERRED_CHUNK | \ + SDCA_CTL_XU_FDLH_TRANSFERRED_FILE | \ + SDCA_CTL_XU_FDLH_SET_IN_PROGRESS | \ + SDCA_CTL_XU_FDLH_RESET_ACK | \ + SDCA_CTL_XU_FDLH_REQ_ABORT) + +#define SDCA_CTL_XU_FDLD_COMPLETE 0 +#define SDCA_CTL_XU_FDLD_FILE_OK (SDCA_CTL_XU_FDLH_TRANSFERRED_FILE | \ + SDCA_CTL_XU_FDLH_SET_IN_PROGRESS | \ + SDCA_CTL_XU_FDLD_ACK_TRANSFER | \ + SDCA_CTL_XU_FDLD_NEEDS_SET) +#define SDCA_CTL_XU_FDLD_MORE_FILES_OK (SDCA_CTL_XU_FDLH_SET_IN_PROGRESS | \ + SDCA_CTL_XU_FDLD_ACK_TRANSFER | \ + SDCA_CTL_XU_FDLD_NEEDS_SET) +#define SDCA_CTL_XU_FDLD_MASK (SDCA_CTL_XU_FDLD_REQ_RESET | \ + SDCA_CTL_XU_FDLD_REQ_ABORT | \ + SDCA_CTL_XU_FDLD_ACK_TRANSFER | \ + SDCA_CTL_XU_FDLD_NEEDS_SET) + +#if IS_ENABLED(CONFIG_SND_SOC_SDCA_FDL) + +int sdca_fdl_alloc_state(struct sdca_interrupt *interrupt); +int sdca_fdl_process(struct sdca_interrupt *interrupt); +int sdca_fdl_sync(struct device *dev, struct sdca_function_data *function, + struct sdca_interrupt_info *info); + +int sdca_reset_function(struct device *dev, struct sdca_function_data *function, + struct regmap *regmap); + +#else + +static inline int sdca_fdl_alloc_state(struct sdca_interrupt *interrupt) +{ + return 0; +} + +static inline int sdca_fdl_process(struct sdca_interrupt *interrupt) +{ + return 0; +} + +static inline int sdca_fdl_sync(struct device *dev, + struct sdca_function_data *function, + struct sdca_interrupt_info *info) +{ + return 0; +} + +static inline int sdca_reset_function(struct device *dev, + struct sdca_function_data *function, + struct regmap *regmap) +{ + return 0; +} + +#endif // CONFIG_SND_SOC_SDCA_FDL + +#endif // __SDCA_FDL_H__ diff --git a/include/sound/sdca_function.h b/include/sound/sdca_function.h new file mode 100644 index 000000000000..6e9391b3816c --- /dev/null +++ b/include/sound/sdca_function.h @@ -0,0 +1,1475 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * The MIPI SDCA specification is available for public downloads at + * https://www.mipi.org/mipi-sdca-v1-0-download + * + * Copyright(c) 2024 Intel Corporation + */ + +#ifndef __SDCA_FUNCTION_H__ +#define __SDCA_FUNCTION_H__ + +#include <linux/bits.h> +#include <linux/types.h> +#include <linux/hid.h> + +struct acpi_table_swft; +struct device; +struct sdca_entity; +struct sdca_function_desc; + +#define SDCA_NO_INTERRUPT -1 + +/* + * The addressing space for SDCA relies on 7 bits for Entities, so a + * maximum of 128 Entities per function can be represented. + */ +#define SDCA_MAX_ENTITY_COUNT 128 + +/* + * Sanity check on number of initialization writes, can be expanded if needed. + */ +#define SDCA_MAX_INIT_COUNT 2048 + +/* + * The Cluster IDs are 16-bit, so a maximum of 65535 Clusters per + * function can be represented, however limit this to a slightly + * more reasonable value. Can be expanded if needed. + */ +#define SDCA_MAX_CLUSTER_COUNT 256 + +/* + * Sanity check on number of channels per Cluster, can be expanded if needed. + */ +#define SDCA_MAX_CHANNEL_COUNT 32 + +/* + * Sanity check on number of PDE delays, can be expanded if needed. + */ +#define SDCA_MAX_DELAY_COUNT 256 + +/* + * Sanity check on size of affected controls data, can be expanded if needed. + */ +#define SDCA_MAX_AFFECTED_COUNT 2048 + +/** + * enum sdca_function_type - SDCA Function Type codes + * @SDCA_FUNCTION_TYPE_SMART_AMP: Amplifier with protection features. + * @SDCA_FUNCTION_TYPE_SIMPLE_AMP: Subset of SmartAmp. + * @SDCA_FUNCTION_TYPE_SMART_MIC: Smart microphone with acoustic triggers. + * @SDCA_FUNCTION_TYPE_SIMPLE_MIC: Subset of SmartMic. + * @SDCA_FUNCTION_TYPE_SPEAKER_MIC: Combination of SmartMic and SmartAmp. + * @SDCA_FUNCTION_TYPE_UAJ: 3.5mm Universal Audio jack. + * @SDCA_FUNCTION_TYPE_RJ: Retaskable jack. + * @SDCA_FUNCTION_TYPE_SIMPLE_JACK: Subset of UAJ. + * @SDCA_FUNCTION_TYPE_HID: Human Interface Device, for e.g. buttons. + * @SDCA_FUNCTION_TYPE_COMPANION_AMP: Sources audio from another amp. + * @SDCA_FUNCTION_TYPE_IMP_DEF: Implementation-defined function. + * + * SDCA Function Types from SDCA specification v1.0a Section 5.1.2 + * all Function types not described are reserved. + * + * Note that SIMPLE_AMP, SIMPLE_MIC and SIMPLE_JACK Function Types + * are NOT defined in SDCA 1.0a, but they were defined in earlier + * drafts and are planned for 1.1. + */ +enum sdca_function_type { + SDCA_FUNCTION_TYPE_SMART_AMP = 0x01, + SDCA_FUNCTION_TYPE_SIMPLE_AMP = 0x02, + SDCA_FUNCTION_TYPE_SMART_MIC = 0x03, + SDCA_FUNCTION_TYPE_SIMPLE_MIC = 0x04, + SDCA_FUNCTION_TYPE_SPEAKER_MIC = 0x05, + SDCA_FUNCTION_TYPE_UAJ = 0x06, + SDCA_FUNCTION_TYPE_RJ = 0x07, + SDCA_FUNCTION_TYPE_SIMPLE_JACK = 0x08, + SDCA_FUNCTION_TYPE_HID = 0x0A, + SDCA_FUNCTION_TYPE_COMPANION_AMP = 0x0B, + SDCA_FUNCTION_TYPE_IMP_DEF = 0x1F, +}; + +/* Human-readable names used for kernel logs and Function device registration/bind */ +#define SDCA_FUNCTION_TYPE_SMART_AMP_NAME "SmartAmp" +#define SDCA_FUNCTION_TYPE_SIMPLE_AMP_NAME "SimpleAmp" +#define SDCA_FUNCTION_TYPE_SMART_MIC_NAME "SmartMic" +#define SDCA_FUNCTION_TYPE_SIMPLE_MIC_NAME "SimpleMic" +#define SDCA_FUNCTION_TYPE_SPEAKER_MIC_NAME "SpeakerMic" +#define SDCA_FUNCTION_TYPE_UAJ_NAME "UAJ" +#define SDCA_FUNCTION_TYPE_RJ_NAME "RJ" +#define SDCA_FUNCTION_TYPE_SIMPLE_NAME "SimpleJack" +#define SDCA_FUNCTION_TYPE_HID_NAME "HID" +#define SDCA_FUNCTION_TYPE_COMPANION_AMP_NAME "CompanionAmp" +#define SDCA_FUNCTION_TYPE_IMP_DEF_NAME "ImplementationDefined" + +/** + * struct sdca_init_write - a single initialization write + * @addr: Register address to be written + * @val: Single byte value to be written + */ +struct sdca_init_write { + u32 addr; + u8 val; +}; + +/** + * define SDCA_CTL_TYPE - create a unique identifier for an SDCA Control + * @ent: Entity Type code. + * @sel: Control Selector code. + * + * Sometimes there is a need to identify a type of Control, for example to + * determine what name the control should have. SDCA Selectors are reused + * across Entity types, as such it is necessary to combine both the Entity + * Type and the Control Selector to obtain a unique identifier. + */ +#define SDCA_CTL_TYPE(ent, sel) ((ent) << 8 | (sel)) + +/** + * define SDCA_CTL_TYPE_S - static version of SDCA_CTL_TYPE + * @ent: Entity name, for example IT, MFPU, etc. this string can be read + * from the last characters of the SDCA_ENTITY_TYPE_* macros. + * @sel: Control Selector name, for example MIC_BIAS, MUTE, etc. this + * string can be read from the last characters of the SDCA_CTL_*_* + * macros. + * + * Short hand to specific a Control type statically for example: + * SDCA_CTL_TYPE_S(IT, MIC_BIAS). + */ +#define SDCA_CTL_TYPE_S(ent, sel) SDCA_CTL_TYPE(SDCA_ENTITY_TYPE_##ent, \ + SDCA_CTL_##ent##_##sel) + +/** + * enum sdca_messageoffset_range - Column definitions UMP MessageOffset + */ +enum sdca_messageoffset_range { + SDCA_MESSAGEOFFSET_BUFFER_START_ADDRESS = 0, + SDCA_MESSAGEOFFSET_BUFFER_LENGTH = 1, + SDCA_MESSAGEOFFSET_UMP_MODE = 2, + SDCA_MESSAGEOFFSET_NCOLS = 3, +}; + +/** + * enum sdca_ump_mode - SDCA UMP Mode + */ +enum sdca_ump_mode { + SDCA_UMP_MODE_DIRECT = 0x00, + SDCA_UMP_MODE_INDIRECT = 0x01, +}; + +/** + * enum sdca_ump_owner - SDCA UMP Owner + */ +enum sdca_ump_owner { + SDCA_UMP_OWNER_HOST = 0x00, + SDCA_UMP_OWNER_DEVICE = 0x01, +}; + +/** + * enum sdca_it_controls - SDCA Controls for Input Terminal + * + * Control Selectors for Input Terminal from SDCA specification v1.0 + * section 6.2.1.3. + */ +enum sdca_it_controls { + SDCA_CTL_IT_MIC_BIAS = 0x03, + SDCA_CTL_IT_USAGE = 0x04, + SDCA_CTL_IT_LATENCY = 0x08, + SDCA_CTL_IT_CLUSTERINDEX = 0x10, + SDCA_CTL_IT_DATAPORT_SELECTOR = 0x11, + SDCA_CTL_IT_MATCHING_GUID = 0x12, + SDCA_CTL_IT_KEEP_ALIVE = 0x13, + SDCA_CTL_IT_NDAI_STREAM = 0x14, + SDCA_CTL_IT_NDAI_CATEGORY = 0x15, + SDCA_CTL_IT_NDAI_CODINGTYPE = 0x16, + SDCA_CTL_IT_NDAI_PACKETTYPE = 0x17, +}; + +/** + * enum sdca_ot_controls - SDCA Controls for Output Terminal + * + * Control Selectors for Output Terminal from SDCA specification v1.0 + * section 6.2.2.3. + */ +enum sdca_ot_controls { + SDCA_CTL_OT_USAGE = 0x04, + SDCA_CTL_OT_LATENCY = 0x08, + SDCA_CTL_OT_DATAPORT_SELECTOR = 0x11, + SDCA_CTL_OT_MATCHING_GUID = 0x12, + SDCA_CTL_OT_KEEP_ALIVE = 0x13, + SDCA_CTL_OT_NDAI_STREAM = 0x14, + SDCA_CTL_OT_NDAI_CATEGORY = 0x15, + SDCA_CTL_OT_NDAI_CODINGTYPE = 0x16, + SDCA_CTL_OT_NDAI_PACKETTYPE = 0x17, +}; + +/** + * enum sdca_usage_range - Column definitions for Usage + */ +enum sdca_usage_range { + SDCA_USAGE_NUMBER = 0, + SDCA_USAGE_CBN = 1, + SDCA_USAGE_SAMPLE_RATE = 2, + SDCA_USAGE_SAMPLE_WIDTH = 3, + SDCA_USAGE_FULL_SCALE = 4, + SDCA_USAGE_NOISE_FLOOR = 5, + SDCA_USAGE_TAG = 6, + SDCA_USAGE_NCOLS = 7, +}; + +/** + * enum sdca_dataport_selector_range - Column definitions for DataPort_Selector + */ +enum sdca_dataport_selector_range { + SDCA_DATAPORT_SELECTOR_NCOLS = 16, + SDCA_DATAPORT_SELECTOR_NROWS = 4, +}; + +/** + * enum sdca_mu_controls - SDCA Controls for Mixer Unit + * + * Control Selectors for Mixer Unit from SDCA specification v1.0 + * section 6.3.4.2. + */ +enum sdca_mu_controls { + SDCA_CTL_MU_MIXER = 0x01, + SDCA_CTL_MU_LATENCY = 0x06, +}; + +/** + * enum sdca_su_controls - SDCA Controls for Selector Unit + * + * Control Selectors for Selector Unit from SDCA specification v1.0 + * section 6.3.8.3. + */ +enum sdca_su_controls { + SDCA_CTL_SU_SELECTOR = 0x01, + SDCA_CTL_SU_LATENCY = 0x02, +}; + +/** + * enum sdca_fu_controls - SDCA Controls for Feature Unit + * + * Control Selectors for Feature Unit from SDCA specification v1.0 + * section 6.3.2.3. + */ +enum sdca_fu_controls { + SDCA_CTL_FU_MUTE = 0x01, + SDCA_CTL_FU_CHANNEL_VOLUME = 0x02, + SDCA_CTL_FU_AGC = 0x07, + SDCA_CTL_FU_BASS_BOOST = 0x09, + SDCA_CTL_FU_LOUDNESS = 0x0A, + SDCA_CTL_FU_GAIN = 0x0B, + SDCA_CTL_FU_LATENCY = 0x10, +}; + +/** + * enum sdca_volume_range - Column definitions for Q7.8dB volumes/gains + */ +enum sdca_volume_range { + SDCA_VOLUME_LINEAR_MIN = 0, + SDCA_VOLUME_LINEAR_MAX = 1, + SDCA_VOLUME_LINEAR_STEP = 2, + SDCA_VOLUME_LINEAR_NCOLS = 3, +}; + +/** + * enum sdca_xu_controls - SDCA Controls for Extension Unit + * + * Control Selectors for Extension Unit from SDCA specification v1.0 + * section 6.3.10.3. + */ +enum sdca_xu_controls { + SDCA_CTL_XU_BYPASS = 0x01, + SDCA_CTL_XU_LATENCY = 0x06, + SDCA_CTL_XU_XU_ID = 0x07, + SDCA_CTL_XU_XU_VERSION = 0x08, + SDCA_CTL_XU_FDL_CURRENTOWNER = 0x10, + SDCA_CTL_XU_FDL_MESSAGEOFFSET = 0x12, + SDCA_CTL_XU_FDL_MESSAGELENGTH = 0x13, + SDCA_CTL_XU_FDL_STATUS = 0x14, + SDCA_CTL_XU_FDL_SET_INDEX = 0x15, + SDCA_CTL_XU_FDL_HOST_REQUEST = 0x16, + + /* FDL Status Host->Device bit definitions */ + SDCA_CTL_XU_FDLH_TRANSFERRED_CHUNK = BIT(0), + SDCA_CTL_XU_FDLH_TRANSFERRED_FILE = BIT(1), + SDCA_CTL_XU_FDLH_SET_IN_PROGRESS = BIT(2), + SDCA_CTL_XU_FDLH_RESET_ACK = BIT(4), + SDCA_CTL_XU_FDLH_REQ_ABORT = BIT(5), + /* FDL Status Device->Host bit definitions */ + SDCA_CTL_XU_FDLD_REQ_RESET = BIT(4), + SDCA_CTL_XU_FDLD_REQ_ABORT = BIT(5), + SDCA_CTL_XU_FDLD_ACK_TRANSFER = BIT(6), + SDCA_CTL_XU_FDLD_NEEDS_SET = BIT(7), +}; + +/** + * enum sdca_set_index_range - Column definitions UMP SetIndex + */ +enum sdca_fdl_set_index_range { + SDCA_FDL_SET_INDEX_SET_NUMBER = 0, + SDCA_FDL_SET_INDEX_FILE_SET_ID = 1, + SDCA_FDL_SET_INDEX_NCOLS = 2, +}; + +/** + * enum sdca_cs_controls - SDCA Controls for Clock Source + * + * Control Selectors for Clock Source from SDCA specification v1.0 + * section 6.4.1.3. + */ +enum sdca_cs_controls { + SDCA_CTL_CS_CLOCK_VALID = 0x02, + SDCA_CTL_CS_SAMPLERATEINDEX = 0x10, +}; + +/** + * enum sdca_samplerateindex_range - Column definitions for SampleRateIndex + */ +enum sdca_samplerateindex_range { + SDCA_SAMPLERATEINDEX_INDEX = 0, + SDCA_SAMPLERATEINDEX_RATE = 1, + SDCA_SAMPLERATEINDEX_NCOLS = 2, +}; + +/** + * enum sdca_cx_controls - SDCA Controls for Clock Selector + * + * Control Selectors for Clock Selector from SDCA specification v1.0 + * section 6.4.2.3. + */ +enum sdca_cx_controls { + SDCA_CTL_CX_CLOCK_SELECT = 0x01, +}; + +/** + * enum sdca_pde_controls - SDCA Controls for Power Domain Entity + * + * Control Selectors for Power Domain Entity from SDCA specification + * v1.0 section 6.5.2.2. + */ +enum sdca_pde_controls { + SDCA_CTL_PDE_REQUESTED_PS = 0x01, + SDCA_CTL_PDE_ACTUAL_PS = 0x10, +}; + +/** + * enum sdca_requested_ps_range - Column definitions for Requested PS + */ +enum sdca_requested_ps_range { + SDCA_REQUESTED_PS_STATE = 0, + SDCA_REQUESTED_PS_NCOLS = 1, +}; + +/** + * enum sdca_ge_controls - SDCA Controls for Group Unit + * + * Control Selectors for Group Unit from SDCA specification v1.0 + * section 6.5.1.4. + */ +enum sdca_ge_controls { + SDCA_CTL_GE_SELECTED_MODE = 0x01, + SDCA_CTL_GE_DETECTED_MODE = 0x02, +}; + +/** + * enum sdca_selected_mode_range - Column definitions for Selected Mode + */ +enum sdca_selected_mode_range { + SDCA_SELECTED_MODE_INDEX = 0, + SDCA_SELECTED_MODE_TERM_TYPE = 1, + SDCA_SELECTED_MODE_NCOLS = 2, +}; + +/** + * enum sdca_detected_mode_values - Predefined GE Detected Mode values + */ +enum sdca_detected_mode_values { + SDCA_DETECTED_MODE_JACK_UNPLUGGED = 0, + SDCA_DETECTED_MODE_JACK_UNKNOWN = 1, + SDCA_DETECTED_MODE_DETECTION_IN_PROGRESS = 2, +}; + +/** + * enum sdca_spe_controls - SDCA Controls for Security & Privacy Unit + * + * Control Selectors for Security & Privacy Unit from SDCA + * specification v1.0 Section 6.5.3.2. + */ +enum sdca_spe_controls { + SDCA_CTL_SPE_PRIVATE = 0x01, + SDCA_CTL_SPE_PRIVACY_POLICY = 0x02, + SDCA_CTL_SPE_PRIVACY_LOCKSTATE = 0x03, + SDCA_CTL_SPE_PRIVACY_OWNER = 0x04, + SDCA_CTL_SPE_AUTHTX_CURRENTOWNER = 0x10, + SDCA_CTL_SPE_AUTHTX_MESSAGEOFFSET = 0x12, + SDCA_CTL_SPE_AUTHTX_MESSAGELENGTH = 0x13, + SDCA_CTL_SPE_AUTHRX_CURRENTOWNER = 0x14, + SDCA_CTL_SPE_AUTHRX_MESSAGEOFFSET = 0x16, + SDCA_CTL_SPE_AUTHRX_MESSAGELENGTH = 0x17, +}; + +/** + * enum sdca_cru_controls - SDCA Controls for Channel Remapping Unit + * + * Control Selectors for Channel Remapping Unit from SDCA + * specification v1.0 Section 6.3.1.3. + */ +enum sdca_cru_controls { + SDCA_CTL_CRU_LATENCY = 0x06, + SDCA_CTL_CRU_CLUSTERINDEX = 0x10, +}; + +/** + * enum sdca_udmpu_controls - SDCA Controls for Up-Down Mixer Processing Unit + * + * Control Selectors for Up-Down Mixer Processing Unit from SDCA + * specification v1.0 Section 6.3.9.3. + */ +enum sdca_udmpu_controls { + SDCA_CTL_UDMPU_LATENCY = 0x06, + SDCA_CTL_UDMPU_CLUSTERINDEX = 0x10, + SDCA_CTL_UDMPU_ACOUSTIC_ENERGY_LEVEL_MONITOR = 0x11, + SDCA_CTL_UDMPU_ULTRASOUND_LOOP_GAIN = 0x12, + SDCA_CTL_UDMPU_OPAQUESET_0 = 0x18, + SDCA_CTL_UDMPU_OPAQUESET_1 = 0x19, + SDCA_CTL_UDMPU_OPAQUESET_2 = 0x1A, + SDCA_CTL_UDMPU_OPAQUESET_3 = 0x1B, + SDCA_CTL_UDMPU_OPAQUESET_4 = 0x1C, + SDCA_CTL_UDMPU_OPAQUESET_5 = 0x1D, + SDCA_CTL_UDMPU_OPAQUESET_6 = 0x1E, + SDCA_CTL_UDMPU_OPAQUESET_7 = 0x1F, + SDCA_CTL_UDMPU_OPAQUESET_8 = 0x20, + SDCA_CTL_UDMPU_OPAQUESET_9 = 0x21, + SDCA_CTL_UDMPU_OPAQUESET_10 = 0x22, + SDCA_CTL_UDMPU_OPAQUESET_11 = 0x23, + SDCA_CTL_UDMPU_OPAQUESET_12 = 0x24, + SDCA_CTL_UDMPU_OPAQUESET_13 = 0x25, + SDCA_CTL_UDMPU_OPAQUESET_14 = 0x26, + SDCA_CTL_UDMPU_OPAQUESET_15 = 0x27, + SDCA_CTL_UDMPU_OPAQUESET_16 = 0x28, + SDCA_CTL_UDMPU_OPAQUESET_17 = 0x29, + SDCA_CTL_UDMPU_OPAQUESET_18 = 0x2A, + SDCA_CTL_UDMPU_OPAQUESET_19 = 0x2B, + SDCA_CTL_UDMPU_OPAQUESET_20 = 0x2C, + SDCA_CTL_UDMPU_OPAQUESET_21 = 0x2D, + SDCA_CTL_UDMPU_OPAQUESET_22 = 0x2E, + SDCA_CTL_UDMPU_OPAQUESET_23 = 0x2F, +}; + +/** + * enum sdca_mfpu_controls - SDCA Controls for Multi-Function Processing Unit + * + * Control Selectors for Multi-Function Processing Unit from SDCA + * specification v1.0 Section 6.3.3.4. + */ +enum sdca_mfpu_controls { + SDCA_CTL_MFPU_BYPASS = 0x01, + SDCA_CTL_MFPU_ALGORITHM_READY = 0x04, + SDCA_CTL_MFPU_ALGORITHM_ENABLE = 0x05, + SDCA_CTL_MFPU_LATENCY = 0x08, + SDCA_CTL_MFPU_ALGORITHM_PREPARE = 0x09, + SDCA_CTL_MFPU_CLUSTERINDEX = 0x10, + SDCA_CTL_MFPU_CENTER_FREQUENCY_INDEX = 0x11, + SDCA_CTL_MFPU_ULTRASOUND_LEVEL = 0x12, + SDCA_CTL_MFPU_AE_NUMBER = 0x13, + SDCA_CTL_MFPU_AE_CURRENTOWNER = 0x14, + SDCA_CTL_MFPU_AE_MESSAGEOFFSET = 0x16, + SDCA_CTL_MFPU_AE_MESSAGELENGTH = 0x17, +}; + +/** + * enum sdca_smpu_controls - SDCA Controls for Smart Mic Processing Unit + * + * Control Selectors for Smart Mic Processing Unit from SDCA + * specification v1.0 Section 6.3.7.3. + */ +enum sdca_smpu_controls { + SDCA_CTL_SMPU_LATENCY = 0x06, + SDCA_CTL_SMPU_TRIGGER_ENABLE = 0x10, + SDCA_CTL_SMPU_TRIGGER_STATUS = 0x11, + SDCA_CTL_SMPU_HIST_BUFFER_MODE = 0x12, + SDCA_CTL_SMPU_HIST_BUFFER_PREAMBLE = 0x13, + SDCA_CTL_SMPU_HIST_ERROR = 0x14, + SDCA_CTL_SMPU_TRIGGER_EXTENSION = 0x15, + SDCA_CTL_SMPU_TRIGGER_READY = 0x16, + SDCA_CTL_SMPU_HIST_CURRENTOWNER = 0x18, + SDCA_CTL_SMPU_HIST_MESSAGEOFFSET = 0x1A, + SDCA_CTL_SMPU_HIST_MESSAGELENGTH = 0x1B, + SDCA_CTL_SMPU_DTODTX_CURRENTOWNER = 0x1C, + SDCA_CTL_SMPU_DTODTX_MESSAGEOFFSET = 0x1E, + SDCA_CTL_SMPU_DTODTX_MESSAGELENGTH = 0x1F, + SDCA_CTL_SMPU_DTODRX_CURRENTOWNER = 0x20, + SDCA_CTL_SMPU_DTODRX_MESSAGEOFFSET = 0x22, + SDCA_CTL_SMPU_DTODRX_MESSAGELENGTH = 0x23, +}; + +/** + * enum sdca_sapu_controls - SDCA Controls for Smart Amp Processing Unit + * + * Control Selectors for Smart Amp Processing Unit from SDCA + * specification v1.0 Section 6.3.6.3. + */ +enum sdca_sapu_controls { + SDCA_CTL_SAPU_LATENCY = 0x05, + SDCA_CTL_SAPU_PROTECTION_MODE = 0x10, + SDCA_CTL_SAPU_PROTECTION_STATUS = 0x11, + SDCA_CTL_SAPU_OPAQUESETREQ_INDEX = 0x12, + SDCA_CTL_SAPU_DTODTX_CURRENTOWNER = 0x14, + SDCA_CTL_SAPU_DTODTX_MESSAGEOFFSET = 0x16, + SDCA_CTL_SAPU_DTODTX_MESSAGELENGTH = 0x17, + SDCA_CTL_SAPU_DTODRX_CURRENTOWNER = 0x18, + SDCA_CTL_SAPU_DTODRX_MESSAGEOFFSET = 0x1A, + SDCA_CTL_SAPU_DTODRX_MESSAGELENGTH = 0x1B, +}; + +/** + * enum sdca_ppu_controls - SDCA Controls for Post Processing Unit + * + * Control Selectors for Post Processing Unit from SDCA specification + * v1.0 Section 6.3.5.3. + */ +enum sdca_ppu_controls { + SDCA_CTL_PPU_LATENCY = 0x06, + SDCA_CTL_PPU_POSTURENUMBER = 0x10, + SDCA_CTL_PPU_POSTUREEXTENSION = 0x11, + SDCA_CTL_PPU_HORIZONTALBALANCE = 0x12, + SDCA_CTL_PPU_VERTICALBALANCE = 0x13, +}; + +/** + * enum sdca_tg_controls - SDCA Controls for Tone Generator Entity + * + * Control Selectors for Tone Generator from SDCA specification v1.0 + * Section 6.5.4.4. + */ +enum sdca_tg_controls { + SDCA_CTL_TG_TONE_DIVIDER = 0x10, +}; + +/** + * enum sdca_hide_controls - SDCA Controls for HIDE Entity + * + * Control Selectors for HIDE from SDCA specification v1.0 Section + * 6.6.1.2. + */ +enum sdca_hide_controls { + SDCA_CTL_HIDE_HIDTX_CURRENTOWNER = 0x10, + SDCA_CTL_HIDE_HIDTX_MESSAGEOFFSET = 0x12, + SDCA_CTL_HIDE_HIDTX_MESSAGELENGTH = 0x13, + SDCA_CTL_HIDE_HIDRX_CURRENTOWNER = 0x14, + SDCA_CTL_HIDE_HIDRX_MESSAGEOFFSET = 0x16, + SDCA_CTL_HIDE_HIDRX_MESSAGELENGTH = 0x17, +}; + +/** + * enum sdca_entity0_controls - SDCA Controls for Entity 0 + * + * Control Selectors for Entity 0 from SDCA specification v1.0 Section + * 6.7.1.1. + */ +enum sdca_entity0_controls { + SDCA_CTL_ENTITY_0_COMMIT_GROUP_MASK = 0x01, + SDCA_CTL_ENTITY_0_FUNCTION_SDCA_VERSION = 0x04, + SDCA_CTL_ENTITY_0_FUNCTION_TYPE = 0x05, + SDCA_CTL_ENTITY_0_FUNCTION_MANUFACTURER_ID = 0x06, + SDCA_CTL_ENTITY_0_FUNCTION_ID = 0x07, + SDCA_CTL_ENTITY_0_FUNCTION_VERSION = 0x08, + SDCA_CTL_ENTITY_0_FUNCTION_EXTENSION_ID = 0x09, + SDCA_CTL_ENTITY_0_FUNCTION_EXTENSION_VERSION = 0x0A, + SDCA_CTL_ENTITY_0_FUNCTION_STATUS = 0x10, + SDCA_CTL_ENTITY_0_FUNCTION_ACTION = 0x11, + SDCA_CTL_ENTITY_0_MATCHING_GUID = 0x12, + SDCA_CTL_ENTITY_0_DEVICE_MANUFACTURER_ID = 0x2C, + SDCA_CTL_ENTITY_0_DEVICE_PART_ID = 0x2D, + SDCA_CTL_ENTITY_0_DEVICE_VERSION = 0x2E, + SDCA_CTL_ENTITY_0_DEVICE_SDCA_VERSION = 0x2F, + + /* Function Status Bits */ + SDCA_CTL_ENTITY_0_DEVICE_NEWLY_ATTACHED = BIT(0), + SDCA_CTL_ENTITY_0_INTS_DISABLED_ABNORMALLY = BIT(1), + SDCA_CTL_ENTITY_0_STREAMING_STOPPED_ABNORMALLY = BIT(2), + SDCA_CTL_ENTITY_0_FUNCTION_FAULT = BIT(3), + SDCA_CTL_ENTITY_0_UMP_SEQUENCE_FAULT = BIT(4), + SDCA_CTL_ENTITY_0_FUNCTION_NEEDS_INITIALIZATION = BIT(5), + SDCA_CTL_ENTITY_0_FUNCTION_HAS_BEEN_RESET = BIT(6), + SDCA_CTL_ENTITY_0_FUNCTION_BUSY = BIT(7), + + /* Function Action Bits */ + SDCA_CTL_ENTITY_0_RESET_FUNCTION_NOW = BIT(0), +}; + +#define SDCA_CTL_MIC_BIAS_NAME "Mic Bias" +#define SDCA_CTL_USAGE_NAME "Usage" +#define SDCA_CTL_LATENCY_NAME "Latency" +#define SDCA_CTL_CLUSTERINDEX_NAME "Cluster Index" +#define SDCA_CTL_DATAPORT_SELECTOR_NAME "Dataport Selector" +#define SDCA_CTL_MATCHING_GUID_NAME "Matching GUID" +#define SDCA_CTL_KEEP_ALIVE_NAME "Keep Alive" +#define SDCA_CTL_NDAI_STREAM_NAME "NDAI Stream" +#define SDCA_CTL_NDAI_CATEGORY_NAME "NDAI Category" +#define SDCA_CTL_NDAI_CODINGTYPE_NAME "NDAI Coding Type" +#define SDCA_CTL_NDAI_PACKETTYPE_NAME "NDAI Packet Type" +#define SDCA_CTL_MIXER_NAME "Mixer" +#define SDCA_CTL_SELECTOR_NAME "Selector" +#define SDCA_CTL_MUTE_NAME "Channel" +#define SDCA_CTL_CHANNEL_VOLUME_NAME "Channel Volume" +#define SDCA_CTL_AGC_NAME "AGC" +#define SDCA_CTL_BASS_BOOST_NAME "Bass Boost" +#define SDCA_CTL_LOUDNESS_NAME "Loudness" +#define SDCA_CTL_GAIN_NAME "Gain" +#define SDCA_CTL_BYPASS_NAME "Bypass" +#define SDCA_CTL_XU_ID_NAME "XU ID" +#define SDCA_CTL_XU_VERSION_NAME "XU Version" +#define SDCA_CTL_FDL_CURRENTOWNER_NAME "FDL Current Owner" +#define SDCA_CTL_FDL_MESSAGEOFFSET_NAME "FDL Message Offset" +#define SDCA_CTL_FDL_MESSAGELENGTH_NAME "FDL Message Length" +#define SDCA_CTL_FDL_STATUS_NAME "FDL Status" +#define SDCA_CTL_FDL_SET_INDEX_NAME "FDL Set Index" +#define SDCA_CTL_FDL_HOST_REQUEST_NAME "FDL Host Request" +#define SDCA_CTL_CLOCK_VALID_NAME "Clock Valid" +#define SDCA_CTL_SAMPLERATEINDEX_NAME "Sample Rate Index" +#define SDCA_CTL_CLOCK_SELECT_NAME "Clock Select" +#define SDCA_CTL_REQUESTED_PS_NAME "Requested PS" +#define SDCA_CTL_ACTUAL_PS_NAME "Actual PS" +#define SDCA_CTL_SELECTED_MODE_NAME "Selected Mode" +#define SDCA_CTL_DETECTED_MODE_NAME "Detected Mode" +#define SDCA_CTL_PRIVATE_NAME "Private" +#define SDCA_CTL_PRIVACY_POLICY_NAME "Privacy Policy" +#define SDCA_CTL_PRIVACY_LOCKSTATE_NAME "Privacy Lockstate" +#define SDCA_CTL_PRIVACY_OWNER_NAME "Privacy Owner" +#define SDCA_CTL_AUTHTX_CURRENTOWNER_NAME "AuthTX Current Owner" +#define SDCA_CTL_AUTHTX_MESSAGEOFFSET_NAME "AuthTX Message Offset" +#define SDCA_CTL_AUTHTX_MESSAGELENGTH_NAME "AuthTX Message Length" +#define SDCA_CTL_AUTHRX_CURRENTOWNER_NAME "AuthRX Current Owner" +#define SDCA_CTL_AUTHRX_MESSAGEOFFSET_NAME "AuthRX Message Offset" +#define SDCA_CTL_AUTHRX_MESSAGELENGTH_NAME "AuthRX Message Length" +#define SDCA_CTL_ACOUSTIC_ENERGY_LEVEL_MONITOR_NAME "Acoustic Energy Level Monitor" +#define SDCA_CTL_ULTRASOUND_LOOP_GAIN_NAME "Ultrasound Loop Gain" +#define SDCA_CTL_OPAQUESET_0_NAME "Opaqueset 0" +#define SDCA_CTL_OPAQUESET_1_NAME "Opaqueset 1" +#define SDCA_CTL_OPAQUESET_2_NAME "Opaqueset 2" +#define SDCA_CTL_OPAQUESET_3_NAME "Opaqueset 3" +#define SDCA_CTL_OPAQUESET_4_NAME "Opaqueset 4" +#define SDCA_CTL_OPAQUESET_5_NAME "Opaqueset 5" +#define SDCA_CTL_OPAQUESET_6_NAME "Opaqueset 6" +#define SDCA_CTL_OPAQUESET_7_NAME "Opaqueset 7" +#define SDCA_CTL_OPAQUESET_8_NAME "Opaqueset 8" +#define SDCA_CTL_OPAQUESET_9_NAME "Opaqueset 9" +#define SDCA_CTL_OPAQUESET_10_NAME "Opaqueset 10" +#define SDCA_CTL_OPAQUESET_11_NAME "Opaqueset 11" +#define SDCA_CTL_OPAQUESET_12_NAME "Opaqueset 12" +#define SDCA_CTL_OPAQUESET_13_NAME "Opaqueset 13" +#define SDCA_CTL_OPAQUESET_14_NAME "Opaqueset 14" +#define SDCA_CTL_OPAQUESET_15_NAME "Opaqueset 15" +#define SDCA_CTL_OPAQUESET_16_NAME "Opaqueset 16" +#define SDCA_CTL_OPAQUESET_17_NAME "Opaqueset 17" +#define SDCA_CTL_OPAQUESET_18_NAME "Opaqueset 18" +#define SDCA_CTL_OPAQUESET_19_NAME "Opaqueset 19" +#define SDCA_CTL_OPAQUESET_20_NAME "Opaqueset 20" +#define SDCA_CTL_OPAQUESET_21_NAME "Opaqueset 21" +#define SDCA_CTL_OPAQUESET_22_NAME "Opaqueset 22" +#define SDCA_CTL_OPAQUESET_23_NAME "Opaqueset 23" +#define SDCA_CTL_ALGORITHM_READY_NAME "Algorithm Ready" +#define SDCA_CTL_ALGORITHM_ENABLE_NAME "Algorithm Enable" +#define SDCA_CTL_ALGORITHM_PREPARE_NAME "Algorithm Prepare" +#define SDCA_CTL_CENTER_FREQUENCY_INDEX_NAME "Center Frequency Index" +#define SDCA_CTL_ULTRASOUND_LEVEL_NAME "Ultrasound Level" +#define SDCA_CTL_AE_NUMBER_NAME "AE Number" +#define SDCA_CTL_AE_CURRENTOWNER_NAME "AE Current Owner" +#define SDCA_CTL_AE_MESSAGEOFFSET_NAME "AE Message Offset" +#define SDCA_CTL_AE_MESSAGELENGTH_NAME "AE Message Length" +#define SDCA_CTL_TRIGGER_ENABLE_NAME "Trigger Enable" +#define SDCA_CTL_TRIGGER_STATUS_NAME "Trigger Status" +#define SDCA_CTL_HIST_BUFFER_MODE_NAME "Hist Buffer Mode" +#define SDCA_CTL_HIST_BUFFER_PREAMBLE_NAME "Hist Buffer Preamble" +#define SDCA_CTL_HIST_ERROR_NAME "Hist Error" +#define SDCA_CTL_TRIGGER_EXTENSION_NAME "Trigger Extension" +#define SDCA_CTL_TRIGGER_READY_NAME "Trigger Ready" +#define SDCA_CTL_HIST_CURRENTOWNER_NAME "Hist Current Owner" +#define SDCA_CTL_HIST_MESSAGEOFFSET_NAME "Hist Message Offset" +#define SDCA_CTL_HIST_MESSAGELENGTH_NAME "Hist Message Length" +#define SDCA_CTL_DTODTX_CURRENTOWNER_NAME "DTODTX Current Owner" +#define SDCA_CTL_DTODTX_MESSAGEOFFSET_NAME "DTODTX Message Offset" +#define SDCA_CTL_DTODTX_MESSAGELENGTH_NAME "DTODTX Message Length" +#define SDCA_CTL_DTODRX_CURRENTOWNER_NAME "DTODRX Current Owner" +#define SDCA_CTL_DTODRX_MESSAGEOFFSET_NAME "DTODRX Message Offset" +#define SDCA_CTL_DTODRX_MESSAGELENGTH_NAME "DTODRX Message Length" +#define SDCA_CTL_PROTECTION_MODE_NAME "Protection Mode" +#define SDCA_CTL_PROTECTION_STATUS_NAME "Protection Status" +#define SDCA_CTL_OPAQUESETREQ_INDEX_NAME "Opaqueset Req Index" +#define SDCA_CTL_DTODTX_CURRENTOWNER_NAME "DTODTX Current Owner" +#define SDCA_CTL_DTODTX_MESSAGEOFFSET_NAME "DTODTX Message Offset" +#define SDCA_CTL_DTODTX_MESSAGELENGTH_NAME "DTODTX Message Length" +#define SDCA_CTL_DTODRX_CURRENTOWNER_NAME "DTODRX Current Owner" +#define SDCA_CTL_DTODRX_MESSAGEOFFSET_NAME "DTODRX Message Offset" +#define SDCA_CTL_DTODRX_MESSAGELENGTH_NAME "DTODRX Message Length" +#define SDCA_CTL_POSTURENUMBER_NAME "Posture Number" +#define SDCA_CTL_POSTUREEXTENSION_NAME "Posture Extension" +#define SDCA_CTL_HORIZONTALBALANCE_NAME "Horizontal Balance" +#define SDCA_CTL_VERTICALBALANCE_NAME "Vertical Balance" +#define SDCA_CTL_TONE_DIVIDER_NAME "Tone Divider" +#define SDCA_CTL_HIDTX_CURRENTOWNER_NAME "HIDTX Current Owner" +#define SDCA_CTL_HIDTX_MESSAGEOFFSET_NAME "HIDTX Message Offset" +#define SDCA_CTL_HIDTX_MESSAGELENGTH_NAME "HIDTX Message Length" +#define SDCA_CTL_HIDRX_CURRENTOWNER_NAME "HIDRX Current Owner" +#define SDCA_CTL_HIDRX_MESSAGEOFFSET_NAME "HIDRX Message Offset" +#define SDCA_CTL_HIDRX_MESSAGELENGTH_NAME "HIDRX Message Length" +#define SDCA_CTL_COMMIT_GROUP_MASK_NAME "Commit Group Mask" +#define SDCA_CTL_FUNCTION_SDCA_VERSION_NAME "Function SDCA Version" +#define SDCA_CTL_FUNCTION_TYPE_NAME "Function Type" +#define SDCA_CTL_FUNCTION_MANUFACTURER_ID_NAME "Function Manufacturer ID" +#define SDCA_CTL_FUNCTION_ID_NAME "Function ID" +#define SDCA_CTL_FUNCTION_VERSION_NAME "Function Version" +#define SDCA_CTL_FUNCTION_EXTENSION_ID_NAME "Function Extension ID" +#define SDCA_CTL_FUNCTION_EXTENSION_VERSION_NAME "Function Extension Version" +#define SDCA_CTL_FUNCTION_STATUS_NAME "Function Status" +#define SDCA_CTL_FUNCTION_ACTION_NAME "Function Action" +#define SDCA_CTL_DEVICE_MANUFACTURER_ID_NAME "Device Manufacturer ID" +#define SDCA_CTL_DEVICE_PART_ID_NAME "Device Part ID" +#define SDCA_CTL_DEVICE_VERSION_NAME "Device Version" +#define SDCA_CTL_DEVICE_SDCA_VERSION_NAME "Device SDCA Version" + +/** + * enum sdca_control_datatype - SDCA Control Data Types + * + * Data Types as described in the SDCA specification v1.0 section + * 7.3. + */ +enum sdca_control_datatype { + SDCA_CTL_DATATYPE_ONEBIT, + SDCA_CTL_DATATYPE_INTEGER, + SDCA_CTL_DATATYPE_SPEC_ENCODED_VALUE, + SDCA_CTL_DATATYPE_BCD, + SDCA_CTL_DATATYPE_Q7P8DB, + SDCA_CTL_DATATYPE_BYTEINDEX, + SDCA_CTL_DATATYPE_POSTURENUMBER, + SDCA_CTL_DATATYPE_DP_INDEX, + SDCA_CTL_DATATYPE_BITINDEX, + SDCA_CTL_DATATYPE_BITMAP, + SDCA_CTL_DATATYPE_GUID, + SDCA_CTL_DATATYPE_IMPDEF, +}; + +/** + * enum sdca_access_mode - SDCA Control access mode + * + * Access modes as described in the SDCA specification v1.0 section + * 7.1.8.2. + */ +enum sdca_access_mode { + SDCA_ACCESS_MODE_RW = 0x0, + SDCA_ACCESS_MODE_DUAL = 0x1, + SDCA_ACCESS_MODE_RW1C = 0x2, + SDCA_ACCESS_MODE_RO = 0x3, + SDCA_ACCESS_MODE_RW1S = 0x4, + SDCA_ACCESS_MODE_DC = 0x5, +}; + +/** + * enum sdca_access_layer - SDCA Control access layer + * + * Access layers as described in the SDCA specification v1.0 section + * 7.1.9. + */ +enum sdca_access_layer { + SDCA_ACCESS_LAYER_USER = 1 << 0, + SDCA_ACCESS_LAYER_APPLICATION = 1 << 1, + SDCA_ACCESS_LAYER_CLASS = 1 << 2, + SDCA_ACCESS_LAYER_PLATFORM = 1 << 3, + SDCA_ACCESS_LAYER_DEVICE = 1 << 4, + SDCA_ACCESS_LAYER_EXTENSION = 1 << 5, +}; + +/** + * struct sdca_control_range - SDCA Control range table + * @cols: Number of columns in the range table. + * @rows: Number of rows in the range table. + * @data: Array of values contained in the range table. + */ +struct sdca_control_range { + unsigned int cols; + unsigned int rows; + u32 *data; +}; + +/** + * struct sdca_control - information for one SDCA Control + * @label: Name for the Control, from SDCA Specification v1.0, section 7.1.7. + * @sel: Identifier used for addressing. + * @nbits: Number of bits used in the Control. + * @values: Holds the Control value for constants and defaults. + * @cn_list: A bitmask showing the valid Control Numbers within this Control, + * Control Numbers typically represent channels. + * @interrupt_position: SCDA interrupt line that will alert to changes on this + * Control. + * @type: Format of the data in the Control. + * @range: Buffer describing valid range of values for the Control. + * @mode: Access mode of the Control. + * @layers: Bitmask of access layers of the Control. + * @deferrable: Indicates if the access to the Control can be deferred. + * @has_default: Indicates the Control has a default value to be written. + * @has_fixed: Indicates the Control only supports a single value. + */ +struct sdca_control { + const char *label; + int sel; + + int nbits; + int *values; + u64 cn_list; + int interrupt_position; + + enum sdca_control_datatype type; + struct sdca_control_range range; + enum sdca_access_mode mode; + u8 layers; + + bool deferrable; + bool is_volatile; + bool has_default; + bool has_fixed; +}; + +/** + * enum sdca_terminal_type - SDCA Terminal Types + * + * Indicate what a Terminal Entity is used for, see in section 6.2.3 + * of the SDCA v1.0 specification. + */ +enum sdca_terminal_type { + /* Table 77 - Data Port*/ + SDCA_TERM_TYPE_GENERIC = 0x101, + SDCA_TERM_TYPE_ULTRASOUND = 0x180, + SDCA_TERM_TYPE_CAPTURE_DIRECT_PCM_MIC = 0x181, + SDCA_TERM_TYPE_RAW_PDM_MIC = 0x182, + SDCA_TERM_TYPE_SPEECH = 0x183, + SDCA_TERM_TYPE_VOICE = 0x184, + SDCA_TERM_TYPE_SECONDARY_PCM_MIC = 0x185, + SDCA_TERM_TYPE_ACOUSTIC_CONTEXT_AWARENESS = 0x186, + SDCA_TERM_TYPE_DTOD_STREAM = 0x187, + SDCA_TERM_TYPE_REFERENCE_STREAM = 0x188, + SDCA_TERM_TYPE_SENSE_CAPTURE = 0x189, + SDCA_TERM_TYPE_STREAMING_MIC = 0x18A, + SDCA_TERM_TYPE_OPTIMIZATION_STREAM = 0x190, + SDCA_TERM_TYPE_PDM_RENDER_STREAM = 0x191, + SDCA_TERM_TYPE_COMPANION_DATA = 0x192, + /* Table 78 - Transducer */ + SDCA_TERM_TYPE_MICROPHONE_TRANSDUCER = 0x201, + SDCA_TERM_TYPE_MICROPHONE_ARRAY_TRANSDUCER = 0x205, + SDCA_TERM_TYPE_PRIMARY_FULL_RANGE_SPEAKER = 0x380, + SDCA_TERM_TYPE_PRIMARY_LFE_SPEAKER = 0x381, + SDCA_TERM_TYPE_PRIMARY_TWEETER_SPEAKER = 0x382, + SDCA_TERM_TYPE_PRIMARY_ULTRASOUND_SPEAKER = 0x383, + SDCA_TERM_TYPE_SECONDARY_FULL_RANGE_SPEAKER = 0x390, + SDCA_TERM_TYPE_SECONDARY_LFE_SPEAKER = 0x391, + SDCA_TERM_TYPE_SECONDARY_TWEETER_SPEAKER = 0x392, + SDCA_TERM_TYPE_SECONDARY_ULTRASOUND_SPEAKER = 0x393, + SDCA_TERM_TYPE_TERTIARY_FULL_RANGE_SPEAKER = 0x3A0, + SDCA_TERM_TYPE_TERTIARY_LFE_SPEAKER = 0x3A1, + SDCA_TERM_TYPE_TERTIARY_TWEETER_SPEAKER = 0x3A2, + SDCA_TERM_TYPE_TERTIARY_ULTRASOUND_SPEAKER = 0x3A3, + SDCA_TERM_TYPE_SPDIF = 0x605, + SDCA_TERM_TYPE_NDAI_DISPLAY_AUDIO = 0x610, + SDCA_TERM_TYPE_NDAI_USB = 0x612, + SDCA_TERM_TYPE_NDAI_BLUETOOTH_MAIN = 0x614, + SDCA_TERM_TYPE_NDAI_BLUETOOTH_ALTERNATE = 0x615, + SDCA_TERM_TYPE_NDAI_BLUETOOTH_BOTH = 0x616, + SDCA_TERM_TYPE_LINEIN_STEREO = 0x680, + SDCA_TERM_TYPE_LINEIN_FRONT_LR = 0x681, + SDCA_TERM_TYPE_LINEIN_CENTER_LFE = 0x682, + SDCA_TERM_TYPE_LINEIN_SURROUND_LR = 0x683, + SDCA_TERM_TYPE_LINEIN_REAR_LR = 0x684, + SDCA_TERM_TYPE_LINEOUT_STEREO = 0x690, + SDCA_TERM_TYPE_LINEOUT_FRONT_LR = 0x691, + SDCA_TERM_TYPE_LINEOUT_CENTER_LFE = 0x692, + SDCA_TERM_TYPE_LINEOUT_SURROUND_LR = 0x693, + SDCA_TERM_TYPE_LINEOUT_REAR_LR = 0x694, + SDCA_TERM_TYPE_MIC_JACK = 0x6A0, + SDCA_TERM_TYPE_STEREO_JACK = 0x6B0, + SDCA_TERM_TYPE_FRONT_LR_JACK = 0x6B1, + SDCA_TERM_TYPE_CENTER_LFE_JACK = 0x6B2, + SDCA_TERM_TYPE_SURROUND_LR_JACK = 0x6B3, + SDCA_TERM_TYPE_REAR_LR_JACK = 0x6B4, + SDCA_TERM_TYPE_HEADPHONE_JACK = 0x6C0, + SDCA_TERM_TYPE_HEADSET_JACK = 0x6D0, + /* Table 79 - System */ + SDCA_TERM_TYPE_SENSE_DATA = 0x280, + SDCA_TERM_TYPE_PRIVACY_SIGNALING = 0x741, + SDCA_TERM_TYPE_PRIVACY_INDICATORS = 0x747, +}; + +#define SDCA_TERM_TYPE_LINEIN_STEREO_NAME "LineIn Stereo" +#define SDCA_TERM_TYPE_LINEIN_FRONT_LR_NAME "LineIn Front-LR" +#define SDCA_TERM_TYPE_LINEIN_CENTER_LFE_NAME "LineIn Center-LFE" +#define SDCA_TERM_TYPE_LINEIN_SURROUND_LR_NAME "LineIn Surround-LR" +#define SDCA_TERM_TYPE_LINEIN_REAR_LR_NAME "LineIn Rear-LR" +#define SDCA_TERM_TYPE_LINEOUT_STEREO_NAME "LineOut Stereo" +#define SDCA_TERM_TYPE_LINEOUT_FRONT_LR_NAME "LineOut Front-LR" +#define SDCA_TERM_TYPE_LINEOUT_CENTER_LFE_NAME "LineOut Center-LFE" +#define SDCA_TERM_TYPE_LINEOUT_SURROUND_LR_NAME "LineOut Surround-LR" +#define SDCA_TERM_TYPE_LINEOUT_REAR_LR_NAME "LineOut Rear-LR" +#define SDCA_TERM_TYPE_MIC_JACK_NAME "Microphone" +#define SDCA_TERM_TYPE_STEREO_JACK_NAME "Speaker Stereo" +#define SDCA_TERM_TYPE_FRONT_LR_JACK_NAME "Speaker Front-LR" +#define SDCA_TERM_TYPE_CENTER_LFE_JACK_NAME "Speaker Center-LFE" +#define SDCA_TERM_TYPE_SURROUND_LR_JACK_NAME "Speaker Surround-LR" +#define SDCA_TERM_TYPE_REAR_LR_JACK_NAME "Speaker Rear-LR" +#define SDCA_TERM_TYPE_HEADPHONE_JACK_NAME "Headphone" +#define SDCA_TERM_TYPE_HEADSET_JACK_NAME "Headset" + +/** + * enum sdca_connector_type - SDCA Connector Types + * + * Indicate the type of Connector that a Terminal Entity represents, + * see section 6.2.4 of the SDCA v1.0 specification. + */ +enum sdca_connector_type { + SDCA_CONN_TYPE_UNKNOWN = 0x00, + SDCA_CONN_TYPE_2P5MM_JACK = 0x01, + SDCA_CONN_TYPE_3P5MM_JACK = 0x02, + SDCA_CONN_TYPE_QUARTER_INCH_JACK = 0x03, + SDCA_CONN_TYPE_XLR = 0x05, + SDCA_CONN_TYPE_SPDIF_OPTICAL = 0x06, + SDCA_CONN_TYPE_RCA = 0x07, + SDCA_CONN_TYPE_DIN = 0x0E, + SDCA_CONN_TYPE_MINI_DIN = 0x0F, + SDCA_CONN_TYPE_EIAJ_OPTICAL = 0x13, + SDCA_CONN_TYPE_HDMI = 0x14, + SDCA_CONN_TYPE_DISPLAYPORT = 0x17, + SDCA_CONN_TYPE_LIGHTNING = 0x1B, + SDCA_CONN_TYPE_USB_C = 0x1E, + SDCA_CONN_TYPE_OTHER = 0xFF, +}; + +/** + * struct sdca_entity_iot - information specific to Input/Output Entities + * @clock: Pointer to the Entity providing this Terminal's clock. + * @type: Usage of the Terminal Entity. + * @connector: Physical Connector of the Terminal Entity. + * @reference: Physical Jack number of the Terminal Entity. + * @num_transducer: Number of transducers attached to the Terminal Entity. + * @is_dataport: Boolean indicating if this Terminal represents a Dataport. + */ +struct sdca_entity_iot { + struct sdca_entity *clock; + + enum sdca_terminal_type type; + enum sdca_connector_type connector; + int reference; + int num_transducer; + + bool is_dataport; +}; + +/** + * enum sdca_clock_type - SDCA Clock Types + * + * Indicate the synchronicity of an Clock Entity, see section 6.4.1.3 + * of the SDCA v1.0 specification. + */ +enum sdca_clock_type { + SDCA_CLOCK_TYPE_EXTERNAL = 0x00, + SDCA_CLOCK_TYPE_INTERNAL_ASYNC = 0x01, + SDCA_CLOCK_TYPE_INTERNAL_SYNC = 0x02, + SDCA_CLOCK_TYPE_INTERNAL_SOURCE_SYNC = 0x03, +}; + +/** + * struct sdca_entity_cs - information specific to Clock Source Entities + * @type: Synchronicity of the Clock Source. + * @max_delay: The maximum delay in microseconds before the clock is stable. + */ +struct sdca_entity_cs { + enum sdca_clock_type type; + unsigned int max_delay; +}; + +/** + * enum sdca_pde_power_state - SDCA Power States + * + * SDCA Power State values from SDCA specification v1.0 Section 7.12.4. + */ +enum sdca_pde_power_state { + SDCA_PDE_PS0 = 0x0, + SDCA_PDE_PS1 = 0x1, + SDCA_PDE_PS2 = 0x2, + SDCA_PDE_PS3 = 0x3, + SDCA_PDE_PS4 = 0x4, +}; + +/** + * struct sdca_pde_delay - describes the delay changing between 2 power states + * @from_ps: The power state being exited. + * @to_ps: The power state being entered. + * @us: The delay in microseconds switching between the two states. + */ +struct sdca_pde_delay { + int from_ps; + int to_ps; + unsigned int us; +}; + +/** + * struct sdca_entity_pde - information specific to Power Domain Entities + * @managed: Dynamically allocated array pointing to each Entity + * controlled by this PDE. + * @max_delay: Dynamically allocated array of delays for switching + * between power states. + * @num_managed: Number of Entities controlled by this PDE. + * @num_max_delay: Number of delays specified for state changes. + */ +struct sdca_entity_pde { + struct sdca_entity **managed; + struct sdca_pde_delay *max_delay; + int num_managed; + int num_max_delay; +}; + +/** + * enum sdca_entity_type - SDCA Entity Type codes + * @SDCA_ENTITY_TYPE_ENTITY_0: Entity 0, not actually from the + * specification but useful internally as an Entity structure + * is allocated for Entity 0, to hold Entity 0 controls. + * @SDCA_ENTITY_TYPE_IT: Input Terminal. + * @SDCA_ENTITY_TYPE_OT: Output Terminal. + * @SDCA_ENTITY_TYPE_MU: Mixer Unit. + * @SDCA_ENTITY_TYPE_SU: Selector Unit. + * @SDCA_ENTITY_TYPE_FU: Feature Unit. + * @SDCA_ENTITY_TYPE_XU: Extension Unit. + * @SDCA_ENTITY_TYPE_CS: Clock Source. + * @SDCA_ENTITY_TYPE_CX: Clock selector. + * @SDCA_ENTITY_TYPE_PDE: Power-Domain Entity. + * @SDCA_ENTITY_TYPE_GE: Group Entity. + * @SDCA_ENTITY_TYPE_SPE: Security & Privacy Entity. + * @SDCA_ENTITY_TYPE_CRU: Channel Remapping Unit. + * @SDCA_ENTITY_TYPE_UDMPU: Up-Down Mixer Processing Unit. + * @SDCA_ENTITY_TYPE_MFPU: Multi-Function Processing Unit. + * @SDCA_ENTITY_TYPE_SMPU: Smart Microphone Processing Unit. + * @SDCA_ENTITY_TYPE_SAPU: Smart Amp Processing Unit. + * @SDCA_ENTITY_TYPE_PPU: Posture Processing Unit. + * @SDCA_ENTITY_TYPE_TG: Tone Generator. + * @SDCA_ENTITY_TYPE_HIDE: Human Interface Device Entity. + * + * SDCA Entity Types from SDCA specification v1.0 Section 6.1.2 + * all Entity Types not described are reserved. + */ +enum sdca_entity_type { + SDCA_ENTITY_TYPE_ENTITY_0 = 0x00, + SDCA_ENTITY_TYPE_IT = 0x02, + SDCA_ENTITY_TYPE_OT = 0x03, + SDCA_ENTITY_TYPE_MU = 0x05, + SDCA_ENTITY_TYPE_SU = 0x06, + SDCA_ENTITY_TYPE_FU = 0x07, + SDCA_ENTITY_TYPE_XU = 0x0A, + SDCA_ENTITY_TYPE_CS = 0x0B, + SDCA_ENTITY_TYPE_CX = 0x0C, + SDCA_ENTITY_TYPE_PDE = 0x11, + SDCA_ENTITY_TYPE_GE = 0x12, + SDCA_ENTITY_TYPE_SPE = 0x13, + SDCA_ENTITY_TYPE_CRU = 0x20, + SDCA_ENTITY_TYPE_UDMPU = 0x21, + SDCA_ENTITY_TYPE_MFPU = 0x22, + SDCA_ENTITY_TYPE_SMPU = 0x23, + SDCA_ENTITY_TYPE_SAPU = 0x24, + SDCA_ENTITY_TYPE_PPU = 0x25, + SDCA_ENTITY_TYPE_TG = 0x30, + SDCA_ENTITY_TYPE_HIDE = 0x31, +}; + +/** + * struct sdca_ge_control - control entry in the affected controls list + * @id: Entity ID of the Control affected. + * @sel: Control Selector of the Control affected. + * @cn: Control Number of the Control affected. + * @val: Value written to Control for this Mode. + */ +struct sdca_ge_control { + int id; + int sel; + int cn; + int val; +}; + +/** + * struct sdca_ge_mode - mode entry in the affected controls list + * @controls: Dynamically allocated array of controls written for this Mode. + * @num_controls: Number of controls written in this Mode. + * @val: GE Selector Mode value. + */ +struct sdca_ge_mode { + struct sdca_ge_control *controls; + int num_controls; + int val; +}; + +/** + * struct sdca_entity_ge - information specific to Group Entities + * @kctl: ALSA control pointer that can be used by linked Entities. + * @modes: Dynamically allocated array of Modes and the Controls written + * in each mode. + * @num_modes: Number of Modes. + */ +struct sdca_entity_ge { + struct snd_kcontrol_new *kctl; + struct sdca_ge_mode *modes; + int num_modes; +}; + +/** + * struct sdca_entity_hide - information specific to HIDE Entities + * @hid: HID device structure + * @num_hidtx_ids: number of HIDTx Report ID + * @num_hidrx_ids: number of HIDRx Report ID + * @hidtx_ids: HIDTx Report ID + * @hidrx_ids: HIDRx Report ID + * @af_number_list: which Audio Function Numbers within this Device are + * sending/receiving the messages in this HIDE + * @hide_reside_function_num: indicating which Audio Function Numbers + * within this Device + * @max_delay: the maximum time in microseconds allowed for the Device + * to change the ownership from Device to Host + * @hid_report_desc: HID Report Descriptor for the HIDE Entity + * @hid_desc: HID descriptor for the HIDE Entity + */ +struct sdca_entity_hide { + struct hid_device *hid; + unsigned int *hidtx_ids; + unsigned int *hidrx_ids; + int num_hidtx_ids; + int num_hidrx_ids; + unsigned int af_number_list[SDCA_MAX_FUNCTION_COUNT]; + unsigned int hide_reside_function_num; + unsigned int max_delay; + unsigned char *hid_report_desc; + struct hid_descriptor hid_desc; +}; + +/** + * enum sdca_xu_reset_machanism - SDCA FDL Resets + */ +enum sdca_xu_reset_mechanism { + SDCA_XU_RESET_FUNCTION = 0x0, + SDCA_XU_RESET_DEVICE = 0x1, + SDCA_XU_RESET_BUS = 0x2, +}; + +/** + * struct sdca_entity_xu - information specific to XU Entities + * @max_delay: the maximum time in microseconds allowed for the Device + * to change the ownership from Device to Host + * @reset_mechanism: indicates the type of reset that can be requested + * the end of an FDL. + */ +struct sdca_entity_xu { + unsigned int max_delay; + enum sdca_xu_reset_mechanism reset_mechanism; +}; + +/** + * struct sdca_entity - information for one SDCA Entity + * @label: String such as "OT 12". + * @id: Identifier used for addressing. + * @type: Type code for the Entity. + * @group: Pointer to Group Entity controlling this one, NULL if N/A. + * @sources: Dynamically allocated array pointing to each input Entity + * connected to this Entity. + * @controls: Dynamically allocated array of Controls. + * @num_sources: Number of sources for the Entity. + * @num_controls: Number of Controls for the Entity. + * @iot: Input/Output Terminal specific Entity properties. + * @cs: Clock Source specific Entity properties. + * @pde: Power Domain Entity specific Entity properties. + * @ge: Group Entity specific Entity properties. + * @hide: HIDE Entity specific Entity properties. + * @xu: XU Entity specific Entity properties. + */ +struct sdca_entity { + const char *label; + int id; + enum sdca_entity_type type; + + struct sdca_entity *group; + struct sdca_entity **sources; + struct sdca_control *controls; + int num_sources; + int num_controls; + union { + struct sdca_entity_iot iot; + struct sdca_entity_cs cs; + struct sdca_entity_pde pde; + struct sdca_entity_ge ge; + struct sdca_entity_hide hide; + struct sdca_entity_xu xu; + }; +}; + +/** + * enum sdca_channel_purpose - SDCA Channel Purpose code + * + * Channel Purpose codes as described in the SDCA specification v1.0 + * section 11.4.3. + */ +enum sdca_channel_purpose { + /* Table 210 - Purpose */ + SDCA_CHAN_PURPOSE_GENERIC_AUDIO = 0x01, + SDCA_CHAN_PURPOSE_VOICE = 0x02, + SDCA_CHAN_PURPOSE_SPEECH = 0x03, + SDCA_CHAN_PURPOSE_AMBIENT = 0x04, + SDCA_CHAN_PURPOSE_REFERENCE = 0x05, + SDCA_CHAN_PURPOSE_ULTRASOUND = 0x06, + SDCA_CHAN_PURPOSE_SENSE = 0x08, + SDCA_CHAN_PURPOSE_SILENCE = 0xFE, + SDCA_CHAN_PURPOSE_NON_AUDIO = 0xFF, + /* Table 211 - Amp Sense */ + SDCA_CHAN_PURPOSE_SENSE_V1 = 0x09, + SDCA_CHAN_PURPOSE_SENSE_V2 = 0x0A, + SDCA_CHAN_PURPOSE_SENSE_V12_INTERLEAVED = 0x10, + SDCA_CHAN_PURPOSE_SENSE_V21_INTERLEAVED = 0x11, + SDCA_CHAN_PURPOSE_SENSE_V12_PACKED = 0x12, + SDCA_CHAN_PURPOSE_SENSE_V21_PACKED = 0x13, + SDCA_CHAN_PURPOSE_SENSE_V1212_INTERLEAVED = 0x14, + SDCA_CHAN_PURPOSE_SENSE_V2121_INTERLEAVED = 0x15, + SDCA_CHAN_PURPOSE_SENSE_V1122_INTERLEAVED = 0x16, + SDCA_CHAN_PURPOSE_SENSE_V2211_INTERLEAVED = 0x17, + SDCA_CHAN_PURPOSE_SENSE_V1212_PACKED = 0x18, + SDCA_CHAN_PURPOSE_SENSE_V2121_PACKED = 0x19, + SDCA_CHAN_PURPOSE_SENSE_V1122_PACKED = 0x1A, + SDCA_CHAN_PURPOSE_SENSE_V2211_PACKED = 0x1B, +}; + +/** + * enum sdca_channel_relationship - SDCA Channel Relationship code + * + * Channel Relationship codes as described in the SDCA specification + * v1.0 section 11.4.2. + */ +enum sdca_channel_relationship { + /* Table 206 - Streaming */ + SDCA_CHAN_REL_UNDEFINED = 0x00, + SDCA_CHAN_REL_GENERIC_MONO = 0x01, + SDCA_CHAN_REL_GENERIC_LEFT = 0x02, + SDCA_CHAN_REL_GENERIC_RIGHT = 0x03, + SDCA_CHAN_REL_GENERIC_TOP = 0x48, + SDCA_CHAN_REL_GENERIC_BOTTOM = 0x49, + SDCA_CHAN_REL_CAPTURE_DIRECT = 0x4E, + SDCA_CHAN_REL_RENDER_DIRECT = 0x4F, + SDCA_CHAN_REL_FRONT_LEFT = 0x0B, + SDCA_CHAN_REL_FRONT_RIGHT = 0x0C, + SDCA_CHAN_REL_FRONT_CENTER = 0x0D, + SDCA_CHAN_REL_SIDE_LEFT = 0x12, + SDCA_CHAN_REL_SIDE_RIGHT = 0x13, + SDCA_CHAN_REL_BACK_LEFT = 0x16, + SDCA_CHAN_REL_BACK_RIGHT = 0x17, + SDCA_CHAN_REL_LOW_FREQUENCY_EFFECTS = 0x43, + SDCA_CHAN_REL_SOUNDWIRE_MIC = 0x55, + SDCA_CHAN_REL_SENSE_TRANSDUCER_1 = 0x58, + SDCA_CHAN_REL_SENSE_TRANSDUCER_2 = 0x59, + SDCA_CHAN_REL_SENSE_TRANSDUCER_12 = 0x5A, + SDCA_CHAN_REL_SENSE_TRANSDUCER_21 = 0x5B, + SDCA_CHAN_REL_ECHOREF_NONE = 0x70, + SDCA_CHAN_REL_ECHOREF_1 = 0x71, + SDCA_CHAN_REL_ECHOREF_2 = 0x72, + SDCA_CHAN_REL_ECHOREF_3 = 0x73, + SDCA_CHAN_REL_ECHOREF_4 = 0x74, + SDCA_CHAN_REL_ECHOREF_ALL = 0x75, + SDCA_CHAN_REL_ECHOREF_LFE_ALL = 0x76, + /* Table 207 - Speaker */ + SDCA_CHAN_REL_PRIMARY_TRANSDUCER = 0x50, + SDCA_CHAN_REL_SECONDARY_TRANSDUCER = 0x51, + SDCA_CHAN_REL_TERTIARY_TRANSDUCER = 0x52, + SDCA_CHAN_REL_LOWER_LEFT_ALLTRANSDUCER = 0x60, + SDCA_CHAN_REL_LOWER_RIGHT_ALLTRANSDUCER = 0x61, + SDCA_CHAN_REL_UPPER_LEFT_ALLTRANSDUCER = 0x62, + SDCA_CHAN_REL_UPPER_RIGHT_ALLTRANSDUCER = 0x63, + SDCA_CHAN_REL_LOWER_LEFT_PRIMARY = 0x64, + SDCA_CHAN_REL_LOWER_RIGHT_PRIMARY = 0x65, + SDCA_CHAN_REL_UPPER_LEFT_PRIMARY = 0x66, + SDCA_CHAN_REL_UPPER_RIGHT_PRIMARY = 0x67, + SDCA_CHAN_REL_LOWER_LEFT_SECONDARY = 0x68, + SDCA_CHAN_REL_LOWER_RIGHT_SECONDARY = 0x69, + SDCA_CHAN_REL_UPPER_LEFT_SECONDARY = 0x6A, + SDCA_CHAN_REL_UPPER_RIGHT_SECONDARY = 0x6B, + SDCA_CHAN_REL_LOWER_LEFT_TERTIARY = 0x6C, + SDCA_CHAN_REL_LOWER_RIGHT_TERTIARY = 0x6D, + SDCA_CHAN_REL_UPPER_LEFT_TERTIARY = 0x6E, + SDCA_CHAN_REL_UPPER_RIGHT_TERTIARY = 0x6F, + SDCA_CHAN_REL_DERIVED_LOWER_LEFT_PRIMARY = 0x94, + SDCA_CHAN_REL_DERIVED_LOWER_RIGHT_PRIMARY = 0x95, + SDCA_CHAN_REL_DERIVED_UPPER_LEFT_PRIMARY = 0x96, + SDCA_CHAN_REL_DERIVED_UPPER_RIGHT_PRIMARY = 0x97, + SDCA_CHAN_REL_DERIVED_LOWER_LEFT_SECONDARY = 0x98, + SDCA_CHAN_REL_DERIVED_LOWER_RIGHT_SECONDARY = 0x99, + SDCA_CHAN_REL_DERIVED_UPPER_LEFT_SECONDARY = 0x9A, + SDCA_CHAN_REL_DERIVED_UPPER_RIGHT_SECONDARY = 0x9B, + SDCA_CHAN_REL_DERIVED_LOWER_LEFT_TERTIARY = 0x9C, + SDCA_CHAN_REL_DERIVED_LOWER_RIGHT_TERTIARY = 0x9D, + SDCA_CHAN_REL_DERIVED_UPPER_LEFT_TERTIARY = 0x9E, + SDCA_CHAN_REL_DERIVED_UPPER_RIGHT_TERTIARY = 0x9F, + SDCA_CHAN_REL_DERIVED_MONO_PRIMARY = 0xA0, + SDCA_CHAN_REL_DERIVED_MONO_SECONDARY = 0xAB, + SDCA_CHAN_REL_DERIVED_MONO_TERTIARY = 0xAC, + /* Table 208 - Equipment */ + SDCA_CHAN_REL_EQUIPMENT_LEFT = 0x02, + SDCA_CHAN_REL_EQUIPMENT_RIGHT = 0x03, + SDCA_CHAN_REL_EQUIPMENT_COMBINED = 0x47, + SDCA_CHAN_REL_EQUIPMENT_TOP = 0x48, + SDCA_CHAN_REL_EQUIPMENT_BOTTOM = 0x49, + SDCA_CHAN_REL_EQUIPMENT_TOP_LEFT = 0x4A, + SDCA_CHAN_REL_EQUIPMENT_BOTTOM_LEFT = 0x4B, + SDCA_CHAN_REL_EQUIPMENT_TOP_RIGHT = 0x4C, + SDCA_CHAN_REL_EQUIPMENT_BOTTOM_RIGHT = 0x4D, + SDCA_CHAN_REL_EQUIPMENT_SILENCED_OUTPUT = 0x57, + /* Table 209 - Other */ + SDCA_CHAN_REL_ARRAY = 0x04, + SDCA_CHAN_REL_MIC = 0x53, + SDCA_CHAN_REL_RAW = 0x54, + SDCA_CHAN_REL_SILENCED_MIC = 0x56, + SDCA_CHAN_REL_MULTI_SOURCE_1 = 0x78, + SDCA_CHAN_REL_MULTI_SOURCE_2 = 0x79, + SDCA_CHAN_REL_MULTI_SOURCE_3 = 0x7A, + SDCA_CHAN_REL_MULTI_SOURCE_4 = 0x7B, +}; + +/** + * struct sdca_channel - a single Channel with a Cluster + * @id: Identifier used for addressing. + * @purpose: Indicates the purpose of the Channel, usually to give + * semantic meaning to the audio, eg. voice, ultrasound. + * @relationship: Indicates the relationship of this Channel to others + * in the Cluster, often used to identify the physical position of the + * Channel eg. left. + */ +struct sdca_channel { + int id; + enum sdca_channel_purpose purpose; + enum sdca_channel_relationship relationship; +}; + +/** + * struct sdca_cluster - information about an SDCA Channel Cluster + * @id: Identifier used for addressing. + * @num_channels: Number of Channels within this Cluster. + * @channels: Dynamically allocated array of Channels. + */ +struct sdca_cluster { + int id; + int num_channels; + struct sdca_channel *channels; +}; + +/** + * enum sdca_cluster_range - SDCA Range column definitions for ClusterIndex + */ +enum sdca_cluster_range { + SDCA_CLUSTER_BYTEINDEX = 0, + SDCA_CLUSTER_CLUSTERID = 1, + SDCA_CLUSTER_NCOLS = 2, +}; + +/** + * struct sdca_fdl_file - information about a file from a fileset used in FDL + * @vendor_id: Vendor ID of the file. + * @file_id: File ID of the file. + * @fdl_offset: Offset information for FDL. + */ +struct sdca_fdl_file { + u16 vendor_id; + u32 file_id; + u32 fdl_offset; +}; + +/** + * struct sdca_fdl_set - information about a set of files used in FDL + * @files: Array of files in this FDL set. + * @num_files: Number of files in this FDL set. + * @id: ID of the FDL set. + */ +struct sdca_fdl_set { + struct sdca_fdl_file *files; + int num_files; + u32 id; +}; + +/** + * struct sdca_fdl_data - information about a function's FDL data + * @swft: Pointer to the SoundWire File Table. + * @sets: Array of FDL sets used by this function. + * @num_sets: Number of FDL sets used by this function. + */ +struct sdca_fdl_data { + struct acpi_table_swft *swft; + struct sdca_fdl_set *sets; + int num_sets; +}; + +/** + * struct sdca_function_data - top-level information for one SDCA function + * @desc: Pointer to short descriptor from initial parsing. + * @init_table: Pointer to a table of initialization writes. + * @entities: Dynamically allocated array of Entities. + * @clusters: Dynamically allocated array of Channel Clusters. + * @num_init_table: Number of initialization writes. + * @num_entities: Number of Entities reported in this Function. + * @num_clusters: Number of Channel Clusters reported in this Function. + * @busy_max_delay: Maximum Function busy delay in microseconds, before an + * error should be reported. + * @reset_max_delay: Maximum Function reset delay in microseconds, before an + * error should be reported. + * @fdl_data: FDL data for this Function, if available. + */ +struct sdca_function_data { + struct sdca_function_desc *desc; + + struct sdca_init_write *init_table; + struct sdca_entity *entities; + struct sdca_cluster *clusters; + int num_init_table; + int num_entities; + int num_clusters; + + unsigned int busy_max_delay; + unsigned int reset_max_delay; + + struct sdca_fdl_data fdl_data; +}; + +static inline u32 sdca_range(struct sdca_control_range *range, + unsigned int col, unsigned int row) +{ + return range->data[(row * range->cols) + col]; +} + +static inline u32 sdca_range_search(struct sdca_control_range *range, + int search_col, int value, int result_col) +{ + int i; + + for (i = 0; i < range->rows; i++) { + if (sdca_range(range, search_col, i) == value) + return sdca_range(range, result_col, i); + } + + return 0; +} + +int sdca_parse_function(struct device *dev, struct sdw_slave *sdw, + struct sdca_function_desc *desc, + struct sdca_function_data *function); + +const char *sdca_find_terminal_name(enum sdca_terminal_type type); + +struct sdca_control *sdca_selector_find_control(struct device *dev, + struct sdca_entity *entity, + const int sel); +struct sdca_control_range *sdca_control_find_range(struct device *dev, + struct sdca_entity *entity, + struct sdca_control *control, + int cols, int rows); +struct sdca_control_range *sdca_selector_find_range(struct device *dev, + struct sdca_entity *entity, + int sel, int cols, int rows); +struct sdca_cluster *sdca_id_find_cluster(struct device *dev, + struct sdca_function_data *function, + const int id); + +#endif diff --git a/include/sound/sdca_hid.h b/include/sound/sdca_hid.h new file mode 100644 index 000000000000..18bebbe428c9 --- /dev/null +++ b/include/sound/sdca_hid.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * The MIPI SDCA specification is available for public downloads at + * https://www.mipi.org/mipi-sdca-v1-0-download + * + */ + +#ifndef __SDCA_HID_H__ +#define __SDCA_HID_H__ + +struct device; +struct sdw_slave; + +struct sdca_entity; +struct sdca_interrupt; + +#if IS_ENABLED(CONFIG_SND_SOC_SDCA_HID) + +int sdca_add_hid_device(struct device *dev, struct sdw_slave *sdw, + struct sdca_entity *entity); +int sdca_hid_process_report(struct sdca_interrupt *interrupt); + +#else + +static inline int sdca_add_hid_device(struct device *dev, struct sdw_slave *sdw, + struct sdca_entity *entity) +{ + return 0; +} + +static inline int sdca_hid_process_report(struct sdca_interrupt *interrupt) +{ + return 0; +} + +#endif + +#endif /* __SDCA_HID_H__ */ diff --git a/include/sound/sdca_interrupts.h b/include/sound/sdca_interrupts.h new file mode 100644 index 000000000000..8f13417d129a --- /dev/null +++ b/include/sound/sdca_interrupts.h @@ -0,0 +1,87 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * The MIPI SDCA specification is available for public downloads at + * https://www.mipi.org/mipi-sdca-v1-0-download + * + * Copyright (C) 2025 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef __SDCA_INTERRUPTS_H__ +#define __SDCA_INTERRUPTS_H__ + +#include <linux/interrupt.h> +#include <linux/mutex.h> +#include <linux/regmap.h> + +struct device; +struct snd_soc_component; +struct sdca_function_data; + +#define SDCA_MAX_INTERRUPTS 31 /* the last bit is reserved for future extensions */ + +/** + * struct sdca_interrupt - contains information about a single SDCA interrupt + * @name: The name of the interrupt. + * @dev: Pointer to the Function device. + * @device_regmap: Pointer to the IRQ regmap. + * @function_regmap: Pointer to the SDCA Function regmap. + * @component: Pointer to the ASoC component owns the interrupt. + * @function: Pointer to the Function that the interrupt is associated with. + * @entity: Pointer to the Entity that the interrupt is associated with. + * @control: Pointer to the Control that the interrupt is associated with. + * @priv: Pointer to private data for use by the handler. + * @irq: IRQ number allocated to this interrupt, also used internally to track + * the IRQ being assigned. + */ +struct sdca_interrupt { + const char *name; + + struct device *dev; + struct regmap *device_regmap; + struct regmap *function_regmap; + struct snd_soc_component *component; + struct sdca_function_data *function; + struct sdca_entity *entity; + struct sdca_control *control; + + void *priv; + + int irq; +}; + +/** + * struct sdca_interrupt_info - contains top-level SDCA interrupt information + * @irq_chip: regmap irq chip structure. + * @irq_data: regmap irq chip data structure. + * @irqs: Array of data for each individual IRQ. + * @irq_lock: Protects access to the list of sdca_interrupt structures. + */ +struct sdca_interrupt_info { + struct regmap_irq_chip irq_chip; + struct regmap_irq_chip_data *irq_data; + + struct sdca_interrupt irqs[SDCA_MAX_INTERRUPTS]; + + struct mutex irq_lock; /* Protect irqs list across functions */ +}; + +int sdca_irq_request(struct device *dev, struct sdca_interrupt_info *interrupt_info, + int sdca_irq, const char *name, irq_handler_t handler, + void *data); +int sdca_irq_data_populate(struct device *dev, struct regmap *function_regmap, + struct snd_soc_component *component, + struct sdca_function_data *function, + struct sdca_entity *entity, + struct sdca_control *control, + struct sdca_interrupt *interrupt); +int sdca_irq_populate_early(struct device *dev, struct regmap *function_regmap, + struct sdca_function_data *function, + struct sdca_interrupt_info *info); +int sdca_irq_populate(struct sdca_function_data *function, + struct snd_soc_component *component, + struct sdca_interrupt_info *info); +struct sdca_interrupt_info *sdca_irq_allocate(struct device *dev, + struct regmap *regmap, int irq); + +#endif diff --git a/include/sound/sdca_regmap.h b/include/sound/sdca_regmap.h new file mode 100644 index 000000000000..792540a530fc --- /dev/null +++ b/include/sound/sdca_regmap.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * The MIPI SDCA specification is available for public downloads at + * https://www.mipi.org/mipi-sdca-v1-0-download + * + * Copyright (C) 2025 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef __SDCA_REGMAP_H__ +#define __SDCA_REGMAP_H__ + +struct device; +struct sdca_function_data; +struct regmap; +struct reg_default; + +bool sdca_regmap_readable(struct sdca_function_data *function, unsigned int reg); +bool sdca_regmap_writeable(struct sdca_function_data *function, unsigned int reg); +bool sdca_regmap_volatile(struct sdca_function_data *function, unsigned int reg); +bool sdca_regmap_deferrable(struct sdca_function_data *function, unsigned int reg); +int sdca_regmap_mbq_size(struct sdca_function_data *function, unsigned int reg); + +int sdca_regmap_count_constants(struct device *dev, struct sdca_function_data *function); +int sdca_regmap_populate_constants(struct device *dev, struct sdca_function_data *function, + struct reg_default *consts); + +int sdca_regmap_write_defaults(struct device *dev, struct regmap *regmap, + struct sdca_function_data *function); +int sdca_regmap_write_init(struct device *dev, struct regmap *regmap, + struct sdca_function_data *function); + +#endif // __SDCA_REGMAP_H__ diff --git a/include/sound/sdca_ump.h b/include/sound/sdca_ump.h new file mode 100644 index 000000000000..f54f9d48c64c --- /dev/null +++ b/include/sound/sdca_ump.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * The MIPI SDCA specification is available for public downloads at + * https://www.mipi.org/mipi-sdca-v1-0-download + * + * Copyright (C) 2025 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + */ + +#ifndef __SDCA_UMP_H__ +#define __SDCA_UMP_H__ + +struct regmap; +struct sdca_control; +struct sdca_entity; +struct sdca_function_data; +struct snd_soc_component; +struct delayed_work; + +int sdca_ump_get_owner_host(struct device *dev, + struct regmap *function_regmap, + struct sdca_function_data *function, + struct sdca_entity *entity, + struct sdca_control *control); +int sdca_ump_set_owner_device(struct device *dev, + struct regmap *function_regmap, + struct sdca_function_data *function, + struct sdca_entity *entity, + struct sdca_control *control); +int sdca_ump_read_message(struct device *dev, + struct regmap *device_regmap, + struct regmap *function_regmap, + struct sdca_function_data *function, + struct sdca_entity *entity, + unsigned int offset_sel, unsigned int length_sel, + void **msg); +int sdca_ump_write_message(struct device *dev, + struct regmap *device_regmap, + struct regmap *function_regmap, + struct sdca_function_data *function, + struct sdca_entity *entity, + unsigned int offset_sel, unsigned int msg_offset, + unsigned int length_sel, + void *msg, int msg_len); + +void sdca_ump_cancel_timeout(struct delayed_work *work); +void sdca_ump_schedule_timeout(struct delayed_work *work, + unsigned int timeout_us); + +#endif // __SDCA_UMP_H__ diff --git a/include/sound/seq_kernel.h b/include/sound/seq_kernel.h index c8621671fa70..00c32eed2124 100644 --- a/include/sound/seq_kernel.h +++ b/include/sound/seq_kernel.h @@ -86,10 +86,6 @@ static inline size_t snd_seq_event_packet_size(struct snd_seq_event *ev) /* interface for OSS emulation */ int snd_seq_set_queue_tempo(int client, struct snd_seq_queue_tempo *tempo); -/* port callback routines */ -void snd_port_init_callback(struct snd_seq_port_callback *p); -struct snd_seq_port_callback *snd_port_alloc_callback(void); - /* port attach/detach */ int snd_seq_event_port_attach(int client, struct snd_seq_port_callback *pcbp, int cap, int type, int midi_channels, int midi_voices, char *portname); diff --git a/include/sound/simple_card.h b/include/sound/simple_card.h index d264e5463f22..2e999916dbd7 100644 --- a/include/sound/simple_card.h +++ b/include/sound/simple_card.h @@ -12,15 +12,15 @@ #include <sound/soc.h> #include <sound/simple_card_utils.h> -struct asoc_simple_card_info { +struct simple_util_info { const char *name; const char *card; const char *codec; const char *platform; unsigned int daifmt; - struct asoc_simple_dai cpu_dai; - struct asoc_simple_dai codec_dai; + struct simple_util_dai cpu_dai; + struct simple_util_dai codec_dai; }; #endif /* __SIMPLE_CARD_H */ diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index b450d5873227..69a9c9c4d0e9 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -11,18 +11,18 @@ #include <linux/clk.h> #include <sound/soc.h> -#define asoc_simple_init_hp(card, sjack, prefix) \ - asoc_simple_init_jack(card, sjack, 1, prefix, NULL) -#define asoc_simple_init_mic(card, sjack, prefix) \ - asoc_simple_init_jack(card, sjack, 0, prefix, NULL) +#define simple_util_init_hp(card, sjack, prefix) \ + simple_util_init_jack(card, sjack, 1, prefix, NULL) +#define simple_util_init_mic(card, sjack, prefix) \ + simple_util_init_jack(card, sjack, 0, prefix, NULL) -struct asoc_simple_tdm_width_map { +struct simple_util_tdm_width_map { u8 sample_bits; u8 slot_count; u16 slot_width; }; -struct asoc_simple_dai { +struct simple_util_dai { const char *name; unsigned int sysclk; int clk_direction; @@ -32,17 +32,17 @@ struct asoc_simple_dai { unsigned int rx_slot_mask; struct clk *clk; bool clk_fixed; - struct asoc_simple_tdm_width_map *tdm_width_map; + struct simple_util_tdm_width_map *tdm_width_map; int n_tdm_widths; }; -struct asoc_simple_data { +struct simple_util_data { u32 convert_rate; u32 convert_channels; const char *convert_sample_format; }; -struct asoc_simple_jack { +struct simple_util_jack { struct snd_soc_jack jack; struct snd_soc_jack_pin pin; struct snd_soc_jack_gpio gpio; @@ -54,21 +54,21 @@ struct prop_nums { int platforms; }; -struct asoc_simple_priv { +struct simple_util_priv { struct snd_soc_card snd_card; struct simple_dai_props { - struct asoc_simple_dai *cpu_dai; - struct asoc_simple_dai *codec_dai; - struct asoc_simple_data adata; + struct simple_util_dai *cpu_dai; + struct simple_util_dai *codec_dai; + struct simple_util_data adata; struct snd_soc_codec_conf *codec_conf; struct prop_nums num; unsigned int mclk_fs; } *dai_props; - struct asoc_simple_jack hp_jack; - struct asoc_simple_jack mic_jack; + struct simple_util_jack hp_jack; + struct simple_util_jack mic_jack; struct snd_soc_jack *aux_jacks; struct snd_soc_dai_link *dai_link; - struct asoc_simple_dai *dais; + struct simple_util_dai *dais; struct snd_soc_dai_link_component *dlcs; struct snd_soc_codec_conf *codec_conf; struct gpio_desc *pa_gpio; @@ -89,6 +89,13 @@ struct asoc_simple_priv { #define simple_props_to_dai_codec(props, i) ((props)->codec_dai + i) #define simple_props_to_codec_conf(props, i) ((props)->codec_conf + i) +/* has the same effect as simple_priv_to_props(). Preferred over + * simple_priv_to_props() when dealing with PCM runtime data as + * the ID stored in rtd->id may not be a valid array index. + */ +#define runtime_simple_priv_to_props(priv, rtd) \ + ((priv)->dai_props + ((rtd)->dai_link - (priv)->dai_link)) + #define for_each_prop_dlc_cpus(props, i, cpu) \ for ((i) = 0; \ ((i) < (props)->num.cpus) && \ @@ -130,76 +137,84 @@ struct link_info { struct prop_nums num[SNDRV_MAX_LINKS]; }; -int asoc_simple_parse_daifmt(struct device *dev, +int simple_util_parse_daifmt(struct device *dev, struct device_node *node, struct device_node *codec, char *prefix, unsigned int *retfmt); -int asoc_simple_parse_tdm_width_map(struct device *dev, struct device_node *np, - struct asoc_simple_dai *dai); +int simple_util_parse_tdm_width_map(struct simple_util_priv *priv, struct device_node *np, + struct simple_util_dai *dai); __printf(3, 4) -int asoc_simple_set_dailink_name(struct device *dev, +int simple_util_set_dailink_name(struct simple_util_priv *priv, struct snd_soc_dai_link *dai_link, const char *fmt, ...); -int asoc_simple_parse_card_name(struct snd_soc_card *card, +int simple_util_parse_card_name(struct simple_util_priv *priv, char *prefix); -int asoc_simple_parse_clk(struct device *dev, +int simple_util_parse_clk(struct device *dev, struct device_node *node, - struct asoc_simple_dai *simple_dai, + struct simple_util_dai *simple_dai, struct snd_soc_dai_link_component *dlc); -int asoc_simple_startup(struct snd_pcm_substream *substream); -void asoc_simple_shutdown(struct snd_pcm_substream *substream); -int asoc_simple_hw_params(struct snd_pcm_substream *substream, +int simple_util_startup(struct snd_pcm_substream *substream); +void simple_util_shutdown(struct snd_pcm_substream *substream); +int simple_util_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); -int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd); -int asoc_simple_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, +int simple_util_dai_init(struct snd_soc_pcm_runtime *rtd); +int simple_util_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); -#define asoc_simple_parse_tdm(np, dai) \ +#define simple_util_parse_tdm(np, dai) \ snd_soc_of_parse_tdm_slot(np, &(dai)->tx_slot_mask, \ &(dai)->rx_slot_mask, \ &(dai)->slots, \ &(dai)->slot_width); -void asoc_simple_canonicalize_platform(struct snd_soc_dai_link_component *platforms, +void simple_util_canonicalize_platform(struct snd_soc_dai_link_component *platforms, struct snd_soc_dai_link_component *cpus); -void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link_component *cpus, +void simple_util_canonicalize_cpu(struct snd_soc_dai_link_component *cpus, int is_single_links); -void asoc_simple_clean_reference(struct snd_soc_card *card); +void simple_util_clean_reference(struct snd_soc_card *card); -void asoc_simple_parse_convert(struct device_node *np, char *prefix, - struct asoc_simple_data *data); -bool asoc_simple_is_convert_required(const struct asoc_simple_data *data); +void simple_util_parse_convert(struct device_node *np, char *prefix, + struct simple_util_data *data); +bool simple_util_is_convert_required(const struct simple_util_data *data); -int asoc_simple_parse_routing(struct snd_soc_card *card, +int simple_util_get_sample_fmt(struct simple_util_data *data); + +int simple_util_parse_routing(struct snd_soc_card *card, char *prefix); -int asoc_simple_parse_widgets(struct snd_soc_card *card, +int simple_util_parse_widgets(struct snd_soc_card *card, char *prefix); -int asoc_simple_parse_pin_switches(struct snd_soc_card *card, +int simple_util_parse_pin_switches(struct snd_soc_card *card, char *prefix); -int asoc_simple_init_jack(struct snd_soc_card *card, - struct asoc_simple_jack *sjack, +int simple_util_init_jack(struct snd_soc_card *card, + struct simple_util_jack *sjack, int is_hp, char *prefix, char *pin); -int asoc_simple_init_aux_jacks(struct asoc_simple_priv *priv, +int simple_util_init_aux_jacks(struct simple_util_priv *priv, char *prefix); -int asoc_simple_init_priv(struct asoc_simple_priv *priv, +int simple_util_init_priv(struct simple_util_priv *priv, struct link_info *li); -int asoc_simple_remove(struct platform_device *pdev); +void simple_util_remove(struct platform_device *pdev); + +int graph_util_card_probe(struct snd_soc_card *card); +int graph_util_is_ports0(struct device_node *port); +int graph_util_parse_dai(struct simple_util_priv *priv, struct device_node *ep, + struct snd_soc_dai_link_component *dlc, int *is_single_link); -int asoc_graph_card_probe(struct snd_soc_card *card); -int asoc_graph_is_ports0(struct device_node *port); -int asoc_graph_parse_dai(struct device_node *ep, - struct snd_soc_dai_link_component *dlc, - int *is_single_link); +void graph_util_parse_link_direction(struct device_node *np, + bool *is_playback_only, bool *is_capture_only); +void graph_util_parse_trigger_order(struct simple_util_priv *priv, + struct device_node *np, + enum snd_soc_trigger_order *trigger_start, + enum snd_soc_trigger_order *trigger_stop); #ifdef DEBUG -static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, +static inline void simple_util_debug_dai(struct simple_util_priv *priv, char *name, - struct asoc_simple_dai *dai) + struct simple_util_dai *dai) { struct device *dev = simple_priv_to_dev(priv); @@ -229,7 +244,7 @@ static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, name, dai->clk_direction ? "OUT" : "IN"); } -static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv) +static inline void simple_util_debug_info(struct simple_util_priv *priv) { struct snd_soc_card *card = simple_priv_to_card(priv); struct device *dev = simple_priv_to_dev(priv); @@ -242,7 +257,7 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv) for (i = 0; i < card->num_links; i++) { struct simple_dai_props *props = simple_priv_to_props(priv, i); struct snd_soc_dai_link *link = simple_priv_to_link(priv, i); - struct asoc_simple_dai *dai; + struct simple_util_dai *dai; struct snd_soc_codec_conf *cnf; int j; @@ -250,15 +265,19 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv) dev_dbg(dev, "cpu num = %d\n", link->num_cpus); for_each_prop_dai_cpu(props, j, dai) - asoc_simple_debug_dai(priv, "cpu", dai); + simple_util_debug_dai(priv, "cpu", dai); dev_dbg(dev, "codec num = %d\n", link->num_codecs); for_each_prop_dai_codec(props, j, dai) - asoc_simple_debug_dai(priv, "codec", dai); + simple_util_debug_dai(priv, "codec", dai); if (link->name) - dev_dbg(dev, "dai name = %s\n", link->name); + dev_dbg(dev, "link name = %s\n", link->name); if (link->dai_fmt) - dev_dbg(dev, "dai format = %04x\n", link->dai_fmt); + dev_dbg(dev, "link format = %04x\n", link->dai_fmt); + if (link->playback_only) + dev_dbg(dev, "link has playback_only"); + if (link->capture_only) + dev_dbg(dev, "link has capture_only"); if (props->adata.convert_rate) dev_dbg(dev, "convert_rate = %d\n", props->adata.convert_rate); if (props->adata.convert_channels) @@ -271,7 +290,7 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv) } } #else -#define asoc_simple_debug_info(priv) +#define simple_util_debug_info(priv) #endif /* DEBUG */ #endif /* __SIMPLE_CARD_UTILS_H */ diff --git a/include/sound/snd_wavefront.h b/include/sound/snd_wavefront.h index 55053557c898..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 *); @@ -137,8 +133,4 @@ extern int snd_wavefront_fx_ioctl (struct snd_hwdep *, extern int snd_wavefront_fx_open (struct snd_hwdep *, struct file *); extern int snd_wavefront_fx_release (struct snd_hwdep *, struct file *); -/* prefix in all snd_printk() delivered messages */ - -#define LOGNAME "WaveFront: " - #endif /* __SOUND_SND_WAVEFRONT_H__ */ diff --git a/include/sound/soc-acpi-intel-match.h b/include/sound/soc-acpi-intel-match.h index e49b97d9e3ff..382029724e85 100644 --- a/include/sound/soc-acpi-intel-match.h +++ b/include/sound/soc-acpi-intel-match.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 * - * Copyright (C) 2017, Intel Corporation. All rights reserved. + * Copyright (C) 2017, Intel Corporation */ #ifndef __LINUX_SND_SOC_ACPI_INTEL_MATCH_H @@ -32,6 +32,9 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_nvl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_sdw_machines[]; @@ -42,6 +45,9 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_lnl_sdw_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_nvl_sdw_machines[]; /* * generic table used for HDA codec-based platforms, possibly with diff --git a/include/sound/soc-acpi-intel-ssp-common.h b/include/sound/soc-acpi-intel-ssp-common.h new file mode 100644 index 000000000000..b4597c8dac78 --- /dev/null +++ b/include/sound/soc-acpi-intel-ssp-common.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright(c) 2023 Intel Corporation. + */ + +#ifndef __LINUX_SND_SOC_ACPI_INTEL_SSP_COMMON_H +#define __LINUX_SND_SOC_ACPI_INTEL_SSP_COMMON_H + +/* Cirrus Logic */ +#define CS35L41_ACPI_HID "CSC3541" +#define CS42L42_ACPI_HID "10134242" + +/* Dialog */ +#define DA7219_ACPI_HID "DLGS7219" + +/* Everest */ +#define ES8316_ACPI_HID "ESSX8316" +#define ES8326_ACPI_HID "ESSX8326" +#define ES8336_ACPI_HID "ESSX8336" + +#define MAX_98357A_ACPI_HID "MX98357A" +#define MAX_98360A_ACPI_HID "MX98360A" +#define MAX_98373_ACPI_HID "MX98373" +#define MAX_98390_ACPI_HID "MX98390" + +/* Nuvoton */ +#define NAU8318_ACPI_HID "NVTN2012" +#define NAU8825_ACPI_HID "10508825" + +/* Realtek */ +#define RT1011_ACPI_HID "10EC1011" +#define RT1015_ACPI_HID "10EC1015" +#define RT1015P_ACPI_HID "RTL1015" +#define RT1019P_ACPI_HID "RTL1019" +#define RT1308_ACPI_HID "10EC1308" +#define RT5650_ACPI_HID "10EC5650" +#define RT5682_ACPI_HID "10EC5682" +#define RT5682S_ACPI_HID "RTL5682" + +enum snd_soc_acpi_intel_codec { + CODEC_NONE, + + /* headphone codec */ + CODEC_CS42L42, + CODEC_DA7219, + CODEC_ES8316, + CODEC_ES8326, + CODEC_ES8336, + CODEC_NAU8825, + CODEC_RT5650, + CODEC_RT5682, + CODEC_RT5682S, + + /* speaker amplifier */ + CODEC_CS35L41, + CODEC_MAX98357A, + CODEC_MAX98360A, + CODEC_MAX98373, + CODEC_MAX98390, + CODEC_NAU8318, + CODEC_RT1011, + CODEC_RT1015, + CODEC_RT1015P, + CODEC_RT1019P, + CODEC_RT1308, +}; + +enum snd_soc_acpi_intel_codec +snd_soc_acpi_intel_detect_codec_type(struct device *dev); +enum snd_soc_acpi_intel_codec +snd_soc_acpi_intel_detect_amp_type(struct device *dev); + +const char * +snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type); + +const char * +snd_soc_acpi_intel_get_codec_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type); +const char * +snd_soc_acpi_intel_get_amp_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type); + +#endif /* __LINUX_SND_SOC_ACPI_INTEL_SSP_COMMON_H */ diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index 528279056b3a..90d73b9bddab 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only * - * Copyright (C) 2013-15, Intel Corporation. All rights reserved. + * Copyright (C) 2013-15, Intel Corporation */ #ifndef __LINUX_SND_SOC_ACPI_H @@ -9,6 +9,8 @@ #include <linux/stddef.h> #include <linux/acpi.h> #include <linux/mod_devicetable.h> +#include <linux/soundwire/sdw.h> +#include <sound/soc.h> struct snd_soc_acpi_package_context { char *name; /* package name */ @@ -61,24 +63,33 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg) * @platform: string used for HDAudio codec support * @codec_mask: used for HDAudio support * @dmic_num: number of SoC- or chipset-attached PDM digital microphones - * @common_hdmi_codec_drv: use commom HDAudio HDMI codec driver * @link_mask: SoundWire links enabled on the board * @links: array of SoundWire link _ADR descriptors, null terminated * @i2s_link_mask: I2S/TDM links enabled on the board * @num_dai_drivers: number of elements in @dai_drivers * @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode + * @subsystem_vendor: optional PCI SSID vendor value + * @subsystem_device: optional PCI SSID device value + * @subsystem_rev: optional PCI SSID revision value + * @subsystem_id_set: true if a value has been written to + * subsystem_vendor and subsystem_device. + * @bt_link_mask: BT offload link enabled on the board */ struct snd_soc_acpi_mach_params { u32 acpi_ipc_irq_index; const char *platform; u32 codec_mask; u32 dmic_num; - bool common_hdmi_codec_drv; u32 link_mask; const struct snd_soc_acpi_link_adr *links; u32 i2s_link_mask; u32 num_dai_drivers; struct snd_soc_dai_driver *dai_drivers; + unsigned short subsystem_vendor; + unsigned short subsystem_device; + unsigned short subsystem_rev; + bool subsystem_id_set; + u32 bt_link_mask; }; /** @@ -103,8 +114,8 @@ struct snd_soc_acpi_endpoint { * @name_prefix: string used for codec controls */ struct snd_soc_acpi_adr_device { - const u64 adr; - const u8 num_endpoints; + u64 adr; + u8 num_endpoints; const struct snd_soc_acpi_endpoint *endpoints; const char *name_prefix; }; @@ -120,8 +131,8 @@ struct snd_soc_acpi_adr_device { */ struct snd_soc_acpi_link_adr { - const u32 mask; - const u32 num_adr; + u32 mask; + u32 num_adr; const struct snd_soc_acpi_adr_device *adr_d; }; @@ -143,6 +154,18 @@ struct snd_soc_acpi_link_adr { */ #define SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER BIT(2) +/* + * when set the speaker amplifier name suffix (i.e. "-max98360a") will be + * appended to topology file name + */ +#define SND_SOC_ACPI_TPLG_INTEL_AMP_NAME BIT(3) + +/* + * when set the headphone codec name suffix (i.e. "-rt5682") will be appended to + * topology file name + */ +#define SND_SOC_ACPI_TPLG_INTEL_CODEC_NAME BIT(4) + /** * snd_soc_acpi_mach: ACPI-based machine descriptor. Most of the fields are * related to the hardware, except for the firmware and topology file names. @@ -150,6 +173,7 @@ struct snd_soc_acpi_link_adr { * all firmware/topology related fields. * * @id: ACPI ID (usually the codec's) used to find a matching machine driver. + * @uid: ACPI Unique ID, can be used to disambiguate matches. * @comp_ids: list of compatible audio codecs using the same machine driver, * firmware and topology * @link_mask: describes required board layout, e.g. for SoundWire. @@ -162,10 +186,23 @@ struct snd_soc_acpi_link_adr { * ACPI ID alone is not sufficient, wrong or misleading * @quirk_data: data used to uniquely identify a machine, usually a list of * audio codecs whose presence if checked with ACPI + * @machine_check: pointer to quirk function. The functionality is similar to + * the use of @machine_quirk, except that the return value is a boolean: the intent + * is to skip a machine if the additional hardware/firmware verification invalidates + * the initial selection in the snd_soc_acpi_mach table. * @pdata: intended for platform data or machine specific-ops. This structure * is not constant since this field may be updated at run-time * @sof_tplg_filename: Sound Open Firmware topology file name, if enabled * @tplg_quirk_mask: quirks to select different topology files dynamically + * @get_function_tplg_files: This is an optional callback, if specified then instead of + * the single sof_tplg_filename the callback will return the list of function topology + * files to be loaded. + * Return value: The number of the files or negative ERRNO. 0 means that the single topology + * file should be used, no function topology split can be used on the machine. + * @card: the pointer of the card + * @mach: the pointer of the machine driver + * @prefix: the prefix of the topology file name. Typically, it is the path. + * @tplg_files: the pointer of the array of the topology file names. */ /* Descriptor for SST ASoC machine driver */ struct snd_soc_acpi_mach { @@ -180,10 +217,14 @@ struct snd_soc_acpi_mach { const char *board; struct snd_soc_acpi_mach * (*machine_quirk)(void *arg); const void *quirk_data; + bool (*machine_check)(void *arg); void *pdata; struct snd_soc_acpi_mach_params mach_params; const char *sof_tplg_filename; const u32 tplg_quirk_mask; + int (*get_function_tplg_files)(struct snd_soc_card *card, + const struct snd_soc_acpi_mach *mach, + const char *prefix, const char ***tplg_files); }; #define SND_SOC_ACPI_MAX_CODECS 3 @@ -208,4 +249,8 @@ static inline bool snd_soc_acpi_sof_parent(struct device *dev) !strncmp(dev->parent->driver->name, "sof-audio-acpi", strlen("sof-audio-acpi")); } +bool snd_soc_acpi_sdw_link_slaves_found(struct device *dev, + const struct snd_soc_acpi_link_adr *link, + struct sdw_peripherals *peripherals); + #endif diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h index fc94dfb0021f..ecc02e955279 100644 --- a/include/sound/soc-card.h +++ b/include/sound/soc-card.h @@ -59,6 +59,43 @@ int snd_soc_card_add_dai_link(struct snd_soc_card *card, void snd_soc_card_remove_dai_link(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); +#ifdef CONFIG_PCI +static inline void snd_soc_card_set_pci_ssid(struct snd_soc_card *card, + unsigned short vendor, + unsigned short device) +{ + card->pci_subsystem_vendor = vendor; + card->pci_subsystem_device = device; + card->pci_subsystem_set = true; +} + +static inline int snd_soc_card_get_pci_ssid(struct snd_soc_card *card, + unsigned short *vendor, + unsigned short *device) +{ + if (!card->pci_subsystem_set) + return -ENOENT; + + *vendor = card->pci_subsystem_vendor; + *device = card->pci_subsystem_device; + + return 0; +} +#else /* !CONFIG_PCI */ +static inline void snd_soc_card_set_pci_ssid(struct snd_soc_card *card, + unsigned short vendor, + unsigned short device) +{ +} + +static inline int snd_soc_card_get_pci_ssid(struct snd_soc_card *card, + unsigned short *vendor, + unsigned short *device) +{ + return -ENOENT; +} +#endif /* CONFIG_PCI */ + /* device driver data */ static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, void *data) @@ -78,8 +115,8 @@ struct snd_soc_dai *snd_soc_card_get_codec_dai(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd; for_each_card_rtds(card, rtd) { - if (!strcmp(asoc_rtd_to_codec(rtd, 0)->name, dai_name)) - return asoc_rtd_to_codec(rtd, 0); + if (!strcmp(snd_soc_rtd_to_codec(rtd, 0)->name, dai_name)) + return snd_soc_rtd_to_codec(rtd, 0); } return NULL; diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 87f248a06271..d78cda866888 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -47,7 +47,7 @@ struct snd_compress_ops { struct snd_compr_stream *stream, int cmd); int (*pointer)(struct snd_soc_component *component, struct snd_compr_stream *stream, - struct snd_compr_tstamp *tstamp); + struct snd_compr_tstamp64 *tstamp); int (*copy)(struct snd_soc_component *component, struct snd_compr_stream *stream, char __user *buf, size_t count); @@ -137,10 +137,10 @@ struct snd_soc_component_driver { struct timespec64 *audio_ts, struct snd_pcm_audio_tstamp_config *audio_tstamp_config, struct snd_pcm_audio_tstamp_report *audio_tstamp_report); - int (*copy_user)(struct snd_soc_component *component, - struct snd_pcm_substream *substream, int channel, - unsigned long pos, void __user *buf, - unsigned long bytes); + int (*copy)(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int channel, + unsigned long pos, struct iov_iter *iter, + unsigned long bytes); struct page *(*page)(struct snd_soc_component *component, struct snd_pcm_substream *substream, unsigned long offset); @@ -206,7 +206,6 @@ struct snd_soc_component_driver { struct snd_soc_component { const char *name; - int id; const char *name_prefix; struct device *dev; struct snd_soc_card *card; @@ -262,89 +261,18 @@ struct snd_soc_component { list_for_each_entry_safe(dai, _dai, &(component)->dai_list, list) /** - * snd_soc_dapm_to_component() - Casts a DAPM context to the component it is - * embedded in - * @dapm: The DAPM context to cast to the component - * - * This function must only be used on DAPM contexts that are known to be part of - * a component (e.g. in a component driver). Otherwise the behavior is - * undefined. - */ -static inline struct snd_soc_component *snd_soc_dapm_to_component( - struct snd_soc_dapm_context *dapm) -{ - return container_of(dapm, struct snd_soc_component, dapm); -} - -/** - * snd_soc_component_get_dapm() - Returns the DAPM context associated with a + * snd_soc_component_to_dapm() - Returns the DAPM context associated with a * component * @component: The component for which to get the DAPM context */ -static inline struct snd_soc_dapm_context *snd_soc_component_get_dapm( +static inline struct snd_soc_dapm_context *snd_soc_component_to_dapm( struct snd_soc_component *component) { return &component->dapm; } -/** - * snd_soc_component_init_bias_level() - Initialize COMPONENT DAPM bias level - * @component: The COMPONENT for which to initialize the DAPM bias level - * @level: The DAPM level to initialize to - * - * Initializes the COMPONENT DAPM bias level. See snd_soc_dapm_init_bias_level() - */ -static inline void -snd_soc_component_init_bias_level(struct snd_soc_component *component, - enum snd_soc_bias_level level) -{ - snd_soc_dapm_init_bias_level( - snd_soc_component_get_dapm(component), level); -} - -/** - * snd_soc_component_get_bias_level() - Get current COMPONENT DAPM bias level - * @component: The COMPONENT for which to get the DAPM bias level - * - * Returns: The current DAPM bias level of the COMPONENT. - */ -static inline enum snd_soc_bias_level -snd_soc_component_get_bias_level(struct snd_soc_component *component) -{ - return snd_soc_dapm_get_bias_level( - snd_soc_component_get_dapm(component)); -} - -/** - * snd_soc_component_force_bias_level() - Set the COMPONENT DAPM bias level - * @component: The COMPONENT for which to set the level - * @level: The level to set to - * - * Forces the COMPONENT bias level to a specific state. See - * snd_soc_dapm_force_bias_level(). - */ -static inline int -snd_soc_component_force_bias_level(struct snd_soc_component *component, - enum snd_soc_bias_level level) -{ - return snd_soc_dapm_force_bias_level( - snd_soc_component_get_dapm(component), - level); -} - -/** - * snd_soc_dapm_kcontrol_component() - Returns the component associated to a - * kcontrol - * @kcontrol: The kcontrol - * - * This function must only be used on DAPM contexts that are known to be part of - * a COMPONENT (e.g. in a COMPONENT driver). Otherwise the behavior is undefined - */ -static inline struct snd_soc_component *snd_soc_dapm_kcontrol_component( - struct snd_kcontrol *kcontrol) -{ - return snd_soc_dapm_to_component(snd_soc_dapm_kcontrol_dapm(kcontrol)); -} +// FIXME +#define snd_soc_component_get_dapm snd_soc_component_to_dapm /** * snd_soc_component_cache_sync() - Sync the register cache with the hardware @@ -462,6 +390,8 @@ int snd_soc_component_force_enable_pin_unlocked( const char *pin); /* component controls */ +struct snd_kcontrol *snd_soc_component_get_kcontrol(struct snd_soc_component *component, + const char * const ctl); int snd_soc_component_notify_control(struct snd_soc_component *component, const char * const ctl); @@ -497,7 +427,7 @@ int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream, struct snd_compr_codec_caps *codec); int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes); int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp); + struct snd_compr_tstamp64 *tstamp); int snd_soc_component_compr_copy(struct snd_compr_stream *cstream, char __user *buf, size_t count); int snd_soc_component_compr_set_metadata(struct snd_compr_stream *cstream, @@ -509,9 +439,9 @@ int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream); int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); int snd_soc_pcm_component_sync_stop(struct snd_pcm_substream *substream); -int snd_soc_pcm_component_copy_user(struct snd_pcm_substream *substream, - int channel, unsigned long pos, - void __user *buf, unsigned long bytes); +int snd_soc_pcm_component_copy(struct snd_pcm_substream *substream, + int channel, unsigned long pos, + struct iov_iter *iter, unsigned long bytes); struct page *snd_soc_pcm_component_page(struct snd_pcm_substream *substream, unsigned long offset); int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index e3906ecda740..224396927aef 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -118,12 +118,6 @@ struct snd_compr_stream; #define SND_SOC_DAIFMT_CBP_CFC (3 << 12) /* codec clk provider & frame consumer */ #define SND_SOC_DAIFMT_CBC_CFC (4 << 12) /* codec clk consumer & frame consumer */ -/* previous definitions kept for backwards-compatibility, do not use in new contributions */ -#define SND_SOC_DAIFMT_CBM_CFM SND_SOC_DAIFMT_CBP_CFP -#define SND_SOC_DAIFMT_CBS_CFM SND_SOC_DAIFMT_CBC_CFP -#define SND_SOC_DAIFMT_CBM_CFS SND_SOC_DAIFMT_CBP_CFC -#define SND_SOC_DAIFMT_CBS_CFS SND_SOC_DAIFMT_CBC_CFC - /* when passed to set_fmt directly indicate if the device is provider or consumer */ #define SND_SOC_DAIFMT_BP_FP SND_SOC_DAIFMT_CBP_CFP #define SND_SOC_DAIFMT_BC_FP SND_SOC_DAIFMT_CBC_CFP @@ -180,29 +174,32 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio); /* Digital Audio interface formatting */ -int snd_soc_dai_get_fmt_max_priority(struct snd_soc_pcm_runtime *rtd); -u64 snd_soc_dai_get_fmt(struct snd_soc_dai *dai, int priority); +int snd_soc_dai_get_fmt_max_priority(const struct snd_soc_pcm_runtime *rtd); +u64 snd_soc_dai_get_fmt(const struct snd_soc_dai *dai, int priority); int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt); int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width); int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai, - unsigned int tx_num, unsigned int *tx_slot, - unsigned int rx_num, unsigned int *rx_slot); + unsigned int tx_num, const unsigned int *tx_slot, + unsigned int rx_num, const unsigned int *rx_slot); int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate); +int snd_soc_dai_prepare(struct snd_soc_dai *dai, + struct snd_pcm_substream *substream); + /* Digital Audio Interface mute */ int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute, int direction); +int snd_soc_dai_mute_is_ctrled_at_trigger(struct snd_soc_dai *dai); - -int snd_soc_dai_get_channel_map(struct snd_soc_dai *dai, +int snd_soc_dai_get_channel_map(const struct snd_soc_dai *dai, unsigned int *tx_num, unsigned int *tx_slot, unsigned int *rx_num, unsigned int *rx_slot); -int snd_soc_dai_is_dummy(struct snd_soc_dai *dai); +int snd_soc_dai_is_dummy(const struct snd_soc_dai *dai); int snd_soc_dai_hw_params(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, @@ -216,10 +213,8 @@ void snd_soc_dai_shutdown(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, int rollback); void snd_soc_dai_suspend(struct snd_soc_dai *dai); void snd_soc_dai_resume(struct snd_soc_dai *dai); -int snd_soc_dai_compress_new(struct snd_soc_dai *dai, - struct snd_soc_pcm_runtime *rtd, int num); -bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); -void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link); +int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd); +bool snd_soc_dai_stream_valid(const struct snd_soc_dai *dai, int stream); void snd_soc_dai_action(struct snd_soc_dai *dai, int stream, int action); static inline void snd_soc_dai_activate(struct snd_soc_dai *dai, @@ -232,7 +227,7 @@ static inline void snd_soc_dai_deactivate(struct snd_soc_dai *dai, { snd_soc_dai_action(dai, stream, -1); } -int snd_soc_dai_active(struct snd_soc_dai *dai); +int snd_soc_dai_active(const struct snd_soc_dai *dai); int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order); int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order); @@ -240,8 +235,6 @@ int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream); int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd, int rollback); -int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, - int cmd); void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream, snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay); @@ -263,7 +256,7 @@ int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, size_t bytes); int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, - struct snd_compr_tstamp *tstamp); + struct snd_compr_tstamp64 *tstamp); int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, struct snd_compr_metadata *metadata); @@ -271,7 +264,18 @@ int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai, struct snd_compr_stream *cstream, struct snd_compr_metadata *metadata); +const char *snd_soc_dai_name_get(const struct snd_soc_dai *dai); + struct snd_soc_dai_ops { + /* DAI driver callbacks */ + int (*probe)(struct snd_soc_dai *dai); + int (*remove)(struct snd_soc_dai *dai); + /* compress dai */ + int (*compress_new)(struct snd_soc_pcm_runtime *rtd); + /* Optional Callback used at pcm creation*/ + int (*pcm_new)(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *dai); + /* * DAI clocking configuration, all optional. * Called by soc_card drivers, normally in their hw_params. @@ -294,9 +298,9 @@ struct snd_soc_dai_ops { unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width); int (*set_channel_map)(struct snd_soc_dai *dai, - unsigned int tx_num, unsigned int *tx_slot, - unsigned int rx_num, unsigned int *rx_slot); - int (*get_channel_map)(struct snd_soc_dai *dai, + unsigned int tx_num, const unsigned int *tx_slot, + unsigned int rx_num, const unsigned int *rx_slot); + int (*get_channel_map)(const struct snd_soc_dai *dai, unsigned int *tx_num, unsigned int *tx_slot, unsigned int *rx_num, unsigned int *rx_slot); int (*set_tristate)(struct snd_soc_dai *dai, int tristate); @@ -334,8 +338,7 @@ struct snd_soc_dai_ops { */ int (*trigger)(struct snd_pcm_substream *, int, struct snd_soc_dai *); - int (*bespoke_trigger)(struct snd_pcm_substream *, int, - struct snd_soc_dai *); + /* * For hardware based FIFO caused delay reporting. * Optional. @@ -350,11 +353,16 @@ struct snd_soc_dai_ops { * see * snd_soc_dai_get_fmt() */ - u64 *auto_selectable_formats; + const u64 *auto_selectable_formats; int num_auto_selectable_formats; + /* probe ordering - for components with runtime dependencies */ + int probe_order; + int remove_order; + /* bit field */ unsigned int no_capture_mute:1; + unsigned int mute_unmute_on_trigger:1; }; struct snd_soc_cdai_ops { @@ -375,8 +383,9 @@ struct snd_soc_cdai_ops { struct snd_compr_metadata *, struct snd_soc_dai *); int (*trigger)(struct snd_compr_stream *, int, struct snd_soc_dai *); - int (*pointer)(struct snd_compr_stream *, - struct snd_compr_tstamp *, struct snd_soc_dai *); + int (*pointer)(struct snd_compr_stream *stream, + struct snd_compr_tstamp64 *tstamp, + struct snd_soc_dai *dai); int (*ack)(struct snd_compr_stream *, size_t, struct snd_soc_dai *); }; @@ -397,15 +406,7 @@ struct snd_soc_dai_driver { unsigned int id; unsigned int base; struct snd_soc_dobj dobj; - - /* DAI driver callbacks */ - int (*probe)(struct snd_soc_dai *dai); - int (*remove)(struct snd_soc_dai *dai); - /* compress dai */ - int (*compress_new)(struct snd_soc_pcm_runtime *rtd, int num); - /* Optional Callback used at pcm creation*/ - int (*pcm_new)(struct snd_soc_pcm_runtime *rtd, - struct snd_soc_dai *dai); + const struct of_phandle_args *dai_args; /* ops */ const struct snd_soc_dai_ops *ops; @@ -417,10 +418,6 @@ struct snd_soc_dai_driver { unsigned int symmetric_rate:1; unsigned int symmetric_channels:1; unsigned int symmetric_sample_bits:1; - - /* probe ordering - for components with runtime dependencies */ - int probe_order; - int remove_order; }; /* for Playback/Capture */ @@ -450,9 +447,9 @@ struct snd_soc_dai { struct snd_soc_dai_stream stream[SNDRV_PCM_STREAM_LAST + 1]; /* Symmetry data - only valid if symmetry is being enforced */ - unsigned int rate; - unsigned int channels; - unsigned int sample_bits; + unsigned int symmetric_rate; + unsigned int symmetric_channels; + unsigned int symmetric_sample_bits; /* parent platform/codec */ struct snd_soc_component *component; @@ -467,9 +464,12 @@ struct snd_soc_dai { /* bit field */ unsigned int probed:1; + + /* DAI private data */ + void *priv; }; -static inline struct snd_soc_pcm_stream * +static inline const struct snd_soc_pcm_stream * snd_soc_dai_get_pcm_stream(const struct snd_soc_dai *dai, int stream) { return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? @@ -514,7 +514,8 @@ static inline void snd_soc_dai_init_dma_data(struct snd_soc_dai *dai, void *play snd_soc_dai_dma_data_set_capture(dai, capture); } -static inline unsigned int snd_soc_dai_tdm_mask_get(struct snd_soc_dai *dai, int stream) +static inline unsigned int snd_soc_dai_tdm_mask_get(const struct snd_soc_dai *dai, + int stream) { return dai->stream[stream].tdm_mask; } @@ -525,7 +526,8 @@ static inline void snd_soc_dai_tdm_mask_set(struct snd_soc_dai *dai, int stream, dai->stream[stream].tdm_mask = tdm_mask; } -static inline unsigned int snd_soc_dai_stream_active(struct snd_soc_dai *dai, int stream) +static inline unsigned int snd_soc_dai_stream_active(const struct snd_soc_dai *dai, + int stream) { /* see snd_soc_dai_action() for setup */ return dai->stream[stream].active; diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 87f8e1793af1..75941324886b 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -16,9 +16,10 @@ #include <sound/asoc.h> struct device; +struct regulator; +struct soc_enum; struct snd_pcm_substream; struct snd_soc_pcm_runtime; -struct soc_enum; /* widget has no PM register bit */ #define SND_SOC_NOPM -1 @@ -42,36 +43,45 @@ struct soc_enum; /* codec domain */ #define SND_SOC_DAPM_VMID(wname) \ -{ .id = snd_soc_dapm_vmid, .name = wname, .kcontrol_news = NULL, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_vmid, .name = wname, .kcontrol_news = NULL, \ .num_kcontrols = 0} /* platform domain */ #define SND_SOC_DAPM_SIGGEN(wname) \ -{ .id = snd_soc_dapm_siggen, .name = wname, .kcontrol_news = NULL, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_siggen, .name = wname, .kcontrol_news = NULL, \ .num_kcontrols = 0, .reg = SND_SOC_NOPM } #define SND_SOC_DAPM_SINK(wname) \ -{ .id = snd_soc_dapm_sink, .name = wname, .kcontrol_news = NULL, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_sink, .name = wname, .kcontrol_news = NULL, \ .num_kcontrols = 0, .reg = SND_SOC_NOPM } #define SND_SOC_DAPM_INPUT(wname) \ -{ .id = snd_soc_dapm_input, .name = wname, .kcontrol_news = NULL, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_input, .name = wname, .kcontrol_news = NULL, \ .num_kcontrols = 0, .reg = SND_SOC_NOPM } #define SND_SOC_DAPM_OUTPUT(wname) \ -{ .id = snd_soc_dapm_output, .name = wname, .kcontrol_news = NULL, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_output, .name = wname, .kcontrol_news = NULL, \ .num_kcontrols = 0, .reg = SND_SOC_NOPM } #define SND_SOC_DAPM_MIC(wname, wevent) \ -{ .id = snd_soc_dapm_mic, .name = wname, .kcontrol_news = NULL, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_mic, .name = wname, .kcontrol_news = NULL, \ .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD} #define SND_SOC_DAPM_HP(wname, wevent) \ -{ .id = snd_soc_dapm_hp, .name = wname, .kcontrol_news = NULL, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_hp, .name = wname, .kcontrol_news = NULL, \ .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} #define SND_SOC_DAPM_SPK(wname, wevent) \ -{ .id = snd_soc_dapm_spk, .name = wname, .kcontrol_news = NULL, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_spk, .name = wname, .kcontrol_news = NULL, \ .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} #define SND_SOC_DAPM_LINE(wname, wevent) \ -{ .id = snd_soc_dapm_line, .name = wname, .kcontrol_news = NULL, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_line, .name = wname, .kcontrol_news = NULL, \ .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD} @@ -82,93 +92,110 @@ struct soc_enum; /* path domain */ #define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\ wcontrols, wncontrols) \ -{ .id = snd_soc_dapm_pga, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_pga, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} #define SND_SOC_DAPM_OUT_DRV(wname, wreg, wshift, winvert,\ wcontrols, wncontrols) \ -{ .id = snd_soc_dapm_out_drv, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_out_drv, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} #define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \ wcontrols, wncontrols)\ -{ .id = snd_soc_dapm_mixer, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_mixer, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} #define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \ wcontrols, wncontrols)\ -{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = wncontrols} /* DEPRECATED: use SND_SOC_DAPM_SUPPLY */ #define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \ -{ .id = snd_soc_dapm_micbias, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_micbias, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = NULL, .num_kcontrols = 0} #define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \ -{ .id = snd_soc_dapm_switch, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_switch, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = 1} #define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \ -{ .id = snd_soc_dapm_mux, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_mux, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = 1} #define SND_SOC_DAPM_DEMUX(wname, wreg, wshift, winvert, wcontrols) \ -{ .id = snd_soc_dapm_demux, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_demux, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = 1} /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ #define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\ wcontrols) \ -{ .id = snd_soc_dapm_pga, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_pga, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} #define SOC_MIXER_ARRAY(wname, wreg, wshift, winvert, \ wcontrols)\ -{ .id = snd_soc_dapm_mixer, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_mixer, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} #define SOC_MIXER_NAMED_CTL_ARRAY(wname, wreg, wshift, winvert, \ wcontrols)\ -{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)} /* path domain with event - event handler must return 0 for success */ #define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \ wncontrols, wevent, wflags) \ -{ .id = snd_soc_dapm_pga, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_pga, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ .event = wevent, .event_flags = wflags} #define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \ wncontrols, wevent, wflags) \ -{ .id = snd_soc_dapm_out_drv, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_out_drv, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ .event = wevent, .event_flags = wflags} #define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \ wncontrols, wevent, wflags) \ -{ .id = snd_soc_dapm_mixer, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_mixer, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \ .event = wevent, .event_flags = wflags} #define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \ wcontrols, wncontrols, wevent, wflags) \ -{ .id = snd_soc_dapm_mixer, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_mixer, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, \ .num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags} #define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \ wevent, wflags) \ -{ .id = snd_soc_dapm_switch, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_switch, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = 1, \ .event = wevent, .event_flags = wflags} #define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \ wevent, wflags) \ -{ .id = snd_soc_dapm_mux, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_mux, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = 1, \ .event = wevent, .event_flags = wflags} @@ -176,159 +203,168 @@ struct soc_enum; /* additional sequencing control within an event type */ #define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \ wevent, wflags) \ -{ .id = snd_soc_dapm_pga, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_pga, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .event = wevent, .event_flags = wflags, \ .subseq = wsubseq} #define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \ wflags) \ -{ .id = snd_soc_dapm_supply, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_supply, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .event = wevent, .event_flags = wflags, .subseq = wsubseq} /* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */ #define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \ wevent, wflags) \ -{ .id = snd_soc_dapm_pga, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_pga, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ .event = wevent, .event_flags = wflags} #define SOC_MIXER_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \ wevent, wflags) \ -{ .id = snd_soc_dapm_mixer, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_mixer, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ .event = wevent, .event_flags = wflags} #define SOC_MIXER_NAMED_CTL_E_ARRAY(wname, wreg, wshift, winvert, \ wcontrols, wevent, wflags) \ -{ .id = snd_soc_dapm_mixer, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_mixer, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \ .event = wevent, .event_flags = wflags} /* events that are pre and post DAPM */ #define SND_SOC_DAPM_PRE(wname, wevent) \ -{ .id = snd_soc_dapm_pre, .name = wname, .kcontrol_news = NULL, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_pre, .name = wname, .kcontrol_news = NULL, \ .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD} #define SND_SOC_DAPM_POST(wname, wevent) \ -{ .id = snd_soc_dapm_post, .name = wname, .kcontrol_news = NULL, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_post, .name = wname, .kcontrol_news = NULL, \ .num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \ .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD} /* stream domain */ #define SND_SOC_DAPM_AIF_IN(wname, stname, wchan, wreg, wshift, winvert) \ -{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ .channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), } #define SND_SOC_DAPM_AIF_IN_E(wname, stname, wchan, wreg, wshift, winvert, \ wevent, wflags) \ -{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \ .channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .event = wevent, .event_flags = wflags } #define SND_SOC_DAPM_AIF_OUT(wname, stname, wchan, wreg, wshift, winvert) \ -{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ .channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), } #define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wchan, wreg, wshift, winvert, \ wevent, wflags) \ -{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \ .channel = wchan, SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .event = wevent, .event_flags = wflags } #define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \ -{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) } #define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \ wevent, wflags) \ -{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .event = wevent, .event_flags = wflags} #define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \ -{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), } #define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \ wevent, wflags) \ -{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .event = wevent, .event_flags = wflags} #define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \ -{ .id = snd_soc_dapm_clock_supply, .name = wname, \ - .reg = SND_SOC_NOPM, .event = dapm_clock_event, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_clock_supply, .name = wname, \ + .reg = SND_SOC_NOPM, .event = snd_soc_dapm_clock_event, \ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD } /* generic widgets */ #define SND_SOC_DAPM_REG(wid, wname, wreg, wshift, wmask, won_val, woff_val) \ -{ .id = wid, .name = wname, .kcontrol_news = NULL, .num_kcontrols = 0, \ +(struct snd_soc_dapm_widget) { \ + .id = wid, .name = wname, .kcontrol_news = NULL, .num_kcontrols = 0, \ .reg = wreg, .shift = wshift, .mask = wmask, \ .on_val = won_val, .off_val = woff_val, } #define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \ -{ .id = snd_soc_dapm_supply, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_supply, .name = wname, \ SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \ .event = wevent, .event_flags = wflags} #define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \ -{ .id = snd_soc_dapm_regulator_supply, .name = wname, \ - .reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_regulator_supply, .name = wname, \ + .reg = SND_SOC_NOPM, .shift = wdelay, .event = snd_soc_dapm_regulator_event, \ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \ .on_val = wflags} #define SND_SOC_DAPM_PINCTRL(wname, active, sleep) \ -{ .id = snd_soc_dapm_pinctrl, .name = wname, \ +(struct snd_soc_dapm_widget) { \ + .id = snd_soc_dapm_pinctrl, .name = wname, \ .priv = (&(struct snd_soc_dapm_pinctrl_priv) \ { .active_state = active, .sleep_state = sleep,}), \ - .reg = SND_SOC_NOPM, .event = dapm_pinctrl_event, \ + .reg = SND_SOC_NOPM, .event = snd_soc_dapm_pinctrl_event, \ .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD } /* dapm kcontrol types */ #define SOC_DAPM_DOUBLE(xname, reg, lshift, rshift, max, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ - .private_value = SOC_DOUBLE_VALUE(reg, lshift, rshift, max, invert, 0) } + SOC_DOUBLE_EXT(xname, reg, lshift, rshift, max, invert, \ + snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw) #define SOC_DAPM_DOUBLE_R(xname, lreg, rreg, shift, max, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ - .private_value = SOC_DOUBLE_R_VALUE(lreg, rreg, shift, max, invert) } + SOC_DOUBLE_R_EXT(xname, lreg, rreg, shift, max, invert, \ + snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw) #define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } -#define SOC_DAPM_SINGLE_AUTODISABLE(xname, reg, shift, max, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_volsw, \ - .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) } + SOC_SINGLE_EXT(xname, reg, shift, max, invert, \ + snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw) #define SOC_DAPM_SINGLE_VIRT(xname, max) \ SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0) +#define SOC_DAPM_DOUBLE_R_TLV(xname, lreg, rreg, shift, max, invert, tlv_array) \ + SOC_DOUBLE_R_EXT_TLV(xname, lreg, rreg, shift, max, invert, \ + snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw, \ + tlv_array) #define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ + SOC_SINGLE_EXT_TLV(xname, reg, shift, max, invert, \ + snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw, \ + tlv_array) +#define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \ + SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array) +#define SOC_DAPM_ENUM(xname, xenum) \ + SOC_ENUM_EXT(xname, xenum, snd_soc_dapm_get_enum_double, \ + snd_soc_dapm_put_enum_double) +#define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \ + SOC_ENUM_EXT(xname, xenum, xget, xput) + +#define SOC_DAPM_SINGLE_AUTODISABLE(xname, reg, shift, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } + .private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 1) } #define SOC_DAPM_SINGLE_TLV_AUTODISABLE(xname, reg, shift, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) } -#define SOC_DAPM_SINGLE_TLV_VIRT(xname, max, tlv_array) \ - SOC_DAPM_SINGLE(xname, SND_SOC_NOPM, 0, max, 0, tlv_array) -#define SOC_DAPM_ENUM(xname, xenum) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = snd_soc_dapm_get_enum_double, \ - .put = snd_soc_dapm_put_enum_double, \ - .private_value = (unsigned long)&xenum } -#define SOC_DAPM_ENUM_EXT(xname, xenum, xget, xput) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_soc_info_enum_double, \ - .get = xget, \ - .put = xput, \ - .private_value = (unsigned long)&xenum } + .private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 1) } #define SOC_DAPM_PIN_SWITCH(xname) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname " Switch", \ .info = snd_soc_dapm_info_pin_switch, \ @@ -364,17 +400,6 @@ struct soc_enum; /* regulator widget flags */ #define SND_SOC_DAPM_REGULATOR_BYPASS 0x1 /* bypass when disabled */ -struct snd_soc_dapm_widget; -enum snd_soc_dapm_type; -struct snd_soc_dapm_path; -struct snd_soc_dapm_pin; -struct snd_soc_dapm_route; -struct snd_soc_dapm_context; -struct regulator; -struct snd_soc_dapm_widget_list; -struct snd_soc_dapm_update; -enum snd_soc_dapm_direction; - /* * Bias levels * @@ -393,95 +418,6 @@ enum snd_soc_bias_level { SND_SOC_BIAS_ON = 3, }; -int dapm_regulator_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); -int dapm_clock_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); -int dapm_pinctrl_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); - -/* dapm controls */ -int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo); -int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *uncontrol); -int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *uncontrol); -int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, - const struct snd_soc_dapm_widget *widget, int num); -struct snd_soc_dapm_widget *snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, - const struct snd_soc_dapm_widget *widget); -struct snd_soc_dapm_widget *snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, - const struct snd_soc_dapm_widget *widget); -int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, struct snd_soc_dai *dai); -void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w); -int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card); -void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card); - -int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params, struct snd_soc_dai *dai); - -/* dapm path setup */ -int snd_soc_dapm_new_widgets(struct snd_soc_card *card); -void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm); -void snd_soc_dapm_init(struct snd_soc_dapm_context *dapm, - struct snd_soc_card *card, struct snd_soc_component *component); -int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, - const struct snd_soc_dapm_route *route, int num); -int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm, - const struct snd_soc_dapm_route *route, int num); -int snd_soc_dapm_weak_routes(struct snd_soc_dapm_context *dapm, - const struct snd_soc_dapm_route *route, int num); -void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w); - -/* dapm events */ -void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, int event); -void snd_soc_dapm_stream_stop(struct snd_soc_pcm_runtime *rtd, int stream); -void snd_soc_dapm_shutdown(struct snd_soc_card *card); - -/* external DAPM widget events */ -int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, - struct snd_kcontrol *kcontrol, int connect, struct snd_soc_dapm_update *update); -int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, - struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e, - struct snd_soc_dapm_update *update); - -/* dapm sys fs - used by the core */ -extern struct attribute *soc_dapm_dev_attrs[]; -void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, struct dentry *parent); - -/* dapm audio pin control and status */ -int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin); -int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, const char *pin); -int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, const char *pin); -int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm, const char *pin); -int snd_soc_dapm_nc_pin(struct snd_soc_dapm_context *dapm, const char *pin); -int snd_soc_dapm_nc_pin_unlocked(struct snd_soc_dapm_context *dapm, const char *pin); -int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm, const char *pin); -int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm); -int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm); -int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin); -int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, const char *pin); -int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, const char *pin); -unsigned int dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol); - -/* Mostly internal - should not normally be used */ -void dapm_mark_endpoints_dirty(struct snd_soc_card *card); - -/* dapm path query */ -int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, - struct snd_soc_dapm_widget_list **list, - bool (*custom_stop_condition)(struct snd_soc_dapm_widget *, enum snd_soc_dapm_direction)); -void snd_soc_dapm_dai_free_widgets(struct snd_soc_dapm_widget_list **list); - -struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm(struct snd_kcontrol *kcontrol); -struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_widget(struct snd_kcontrol *kcontrol); - -int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); - /* dapm widget types */ enum snd_soc_dapm_type { snd_soc_dapm_input = 0, /* input pin */ @@ -565,7 +501,6 @@ struct snd_soc_dapm_path { /* status */ u32 connect:1; /* source and sink widgets are connected */ u32 walking:1; /* path is in the process of being walked */ - u32 weak:1; /* path ignored for power management */ u32 is_supply:1; /* At least one of the connected widgets is a supply */ int (*connected)(struct snd_soc_dapm_widget *source, @@ -604,6 +539,7 @@ struct snd_soc_dapm_widget { unsigned char power_checked:1; /* power checked this run */ unsigned char is_supply:1; /* Widget is a supply type widget */ unsigned char is_ep:2; /* Widget is a endpoint type widget */ + unsigned char no_wname_in_kcontrol_name:1; /* No widget name prefix in kcontrol name */ int subseq; /* sort within widget type */ int (*power_check)(struct snd_soc_dapm_widget *w); @@ -647,11 +583,9 @@ struct snd_soc_dapm_update { struct snd_soc_dapm_context { enum snd_soc_bias_level bias_level; - /* bit field */ - unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ - unsigned int suspend_bias_off:1; /* Use BIAS_OFF in suspend if the DAPM is idle */ + bool idle_bias; /* Use BIAS_OFF instead of STANDBY when false */ - struct device *dev; /* from parent - for debug */ + struct device *dev; /* from parent - for debug */ /* REMOVE ME */ struct snd_soc_component *component; /* parent component */ struct snd_soc_card *card; /* parent card */ @@ -670,14 +604,9 @@ struct snd_soc_dapm_context { /* A list of widgets associated with an object, typically a snd_kcontrol */ struct snd_soc_dapm_widget_list { int num_widgets; - struct snd_soc_dapm_widget *widgets[]; + struct snd_soc_dapm_widget *widgets[] __counted_by(num_widgets); }; -#define for_each_dapm_widgets(list, i, widget) \ - for ((i) = 0; \ - (i) < list->num_widgets && (widget = list->widgets[i]); \ - (i)++) - struct snd_soc_dapm_stats { int power_checks; int path_checks; @@ -689,37 +618,6 @@ struct snd_soc_dapm_pinctrl_priv { const char *sleep_state; }; -/** - * snd_soc_dapm_init_bias_level() - Initialize DAPM bias level - * @dapm: The DAPM context to initialize - * @level: The DAPM level to initialize to - * - * This function only sets the driver internal state of the DAPM level and will - * not modify the state of the device. Hence it should not be used during normal - * operation, but only to synchronize the internal state to the device state. - * E.g. during driver probe to set the DAPM level to the one corresponding with - * the power-on reset state of the device. - * - * To change the DAPM state of the device use snd_soc_dapm_set_bias_level(). - */ -static inline void snd_soc_dapm_init_bias_level( - struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level) -{ - dapm->bias_level = level; -} - -/** - * snd_soc_dapm_get_bias_level() - Get current DAPM bias level - * @dapm: The context for which to get the bias level - * - * Returns: The current bias level of the passed DAPM context. - */ -static inline enum snd_soc_bias_level snd_soc_dapm_get_bias_level( - struct snd_soc_dapm_context *dapm) -{ - return dapm->bias_level; -} - enum snd_soc_dapm_direction { SND_SOC_DAPM_DIR_IN, SND_SOC_DAPM_DIR_OUT @@ -730,6 +628,122 @@ enum snd_soc_dapm_direction { #define SND_SOC_DAPM_EP_SOURCE SND_SOC_DAPM_DIR_TO_EP(SND_SOC_DAPM_DIR_IN) #define SND_SOC_DAPM_EP_SINK SND_SOC_DAPM_DIR_TO_EP(SND_SOC_DAPM_DIR_OUT) +int snd_soc_dapm_regulator_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); +int snd_soc_dapm_clock_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); +int snd_soc_dapm_pinctrl_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); + +/* dapm controls */ +int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); +int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); +int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *uncontrol); +int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *uncontrol); +int snd_soc_dapm_get_component_pin_switch(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uncontrol); +int snd_soc_dapm_put_component_pin_switch(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *uncontrol); +int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm, + const struct snd_soc_dapm_widget *widget, unsigned int num); +struct snd_soc_dapm_widget *snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm, + const struct snd_soc_dapm_widget *widget); +struct snd_soc_dapm_widget *snd_soc_dapm_new_control_unlocked(struct snd_soc_dapm_context *dapm, + const struct snd_soc_dapm_widget *widget); +int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, struct snd_soc_dai *dai); +void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w); +int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card); +void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card); + +int snd_soc_dapm_update_dai(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai); +int snd_soc_dapm_widget_name_cmp(struct snd_soc_dapm_widget *widget, const char *s); +struct device *snd_soc_dapm_to_dev(struct snd_soc_dapm_context *dapm); +struct snd_soc_card *snd_soc_dapm_to_card(struct snd_soc_dapm_context *dapm); +struct snd_soc_component *snd_soc_dapm_to_component(struct snd_soc_dapm_context *dapm); + +bool snd_soc_dapm_get_idle_bias(struct snd_soc_dapm_context *dapm); +void snd_soc_dapm_set_idle_bias(struct snd_soc_dapm_context *dapm, bool on); + +/* dapm path setup */ +int snd_soc_dapm_new_widgets(struct snd_soc_card *card); +void snd_soc_dapm_free(struct snd_soc_dapm_context *dapm); +void snd_soc_dapm_init(struct snd_soc_dapm_context *dapm, + struct snd_soc_card *card, struct snd_soc_component *component); +int snd_soc_dapm_add_routes(struct snd_soc_dapm_context *dapm, + const struct snd_soc_dapm_route *route, int num); +int snd_soc_dapm_del_routes(struct snd_soc_dapm_context *dapm, + const struct snd_soc_dapm_route *route, int num); +void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w); + +/* dapm events */ +void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, int event); +void snd_soc_dapm_stream_stop(struct snd_soc_pcm_runtime *rtd, int stream); +void snd_soc_dapm_shutdown(struct snd_soc_card *card); + +/* external DAPM widget events */ +int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_context *dapm, + struct snd_kcontrol *kcontrol, int connect, struct snd_soc_dapm_update *update); +int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_context *dapm, + struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e, + struct snd_soc_dapm_update *update); + +/* dapm sys fs - used by the core */ +extern struct attribute *snd_soc_dapm_dev_attrs[]; +void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm, struct dentry *parent); + +/* dapm audio pin control and status */ +int snd_soc_dapm_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin); +int snd_soc_dapm_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, const char *pin); +int snd_soc_dapm_disable_pin(struct snd_soc_dapm_context *dapm, const char *pin); +int snd_soc_dapm_disable_pin_unlocked(struct snd_soc_dapm_context *dapm, const char *pin); +int snd_soc_dapm_get_pin_status(struct snd_soc_dapm_context *dapm, const char *pin); +int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm); +int snd_soc_dapm_sync_unlocked(struct snd_soc_dapm_context *dapm); +int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm, const char *pin); +int snd_soc_dapm_force_enable_pin_unlocked(struct snd_soc_dapm_context *dapm, const char *pin); +int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm, const char *pin); +void snd_soc_dapm_mark_endpoints_dirty(struct snd_soc_card *card); + +/* + * Marks the specified pin as being not connected, disabling it along + * any parent or child widgets. At present this is identical to + * snd_soc_dapm_disable_pin[_unlocked]() but in future it will be extended to do + * additional things such as disabling controls which only affect + * paths through the pin. + */ +#define snd_soc_dapm_nc_pin snd_soc_dapm_disable_pin +#define snd_soc_dapm_nc_pin_unlocked snd_soc_dapm_disable_pin_unlocked + +/* dapm path query */ +int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, + struct snd_soc_dapm_widget_list **list, + bool (*custom_stop_condition)(struct snd_soc_dapm_widget *, enum snd_soc_dapm_direction)); +void snd_soc_dapm_dai_free_widgets(struct snd_soc_dapm_widget_list **list); + +struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_to_dapm(struct snd_kcontrol *kcontrol); +struct snd_soc_dapm_widget *snd_soc_dapm_kcontrol_to_widget(struct snd_kcontrol *kcontrol); +struct snd_soc_component *snd_soc_dapm_kcontrol_to_component(struct snd_kcontrol *kcontrol); +unsigned int snd_soc_dapm_kcontrol_get_value(const struct snd_kcontrol *kcontrol); + +int snd_soc_dapm_force_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); +enum snd_soc_bias_level snd_soc_dapm_get_bias_level(struct snd_soc_dapm_context *dapm); +void snd_soc_dapm_init_bias_level(struct snd_soc_dapm_context *dapm, enum snd_soc_bias_level level); + +// REMOVE ME !! +#define snd_soc_component_force_bias_level(c, l) snd_soc_dapm_force_bias_level(&(c)->dapm, l) +#define snd_soc_component_get_bias_level(c) snd_soc_dapm_get_bias_level(&(c)->dapm) +#define snd_soc_component_init_bias_level(c, l) snd_soc_dapm_init_bias_level(&(c)->dapm, l) +#define snd_soc_dapm_kcontrol_widget snd_soc_dapm_kcontrol_to_widget +#define snd_soc_dapm_kcontrol_dapm snd_soc_dapm_kcontrol_to_dapm +#define dapm_kcontrol_get_value snd_soc_dapm_kcontrol_get_value +#define snd_soc_dapm_kcontrol_component snd_soc_dapm_kcontrol_to_component + +#define for_each_dapm_widgets(list, i, widget) \ + for ((i) = 0; \ + (i) < list->num_widgets && (widget = list->widgets[i]); \ + (i)++) + /** * snd_soc_dapm_widget_for_each_path - Iterates over all paths in the * specified direction of a widget diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index ebd24753dd00..af24665e37e8 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -58,7 +58,6 @@ enum snd_soc_dpcm_state { enum snd_soc_dpcm_trigger { SND_SOC_DPCM_TRIGGER_PRE = 0, SND_SOC_DPCM_TRIGGER_POST, - SND_SOC_DPCM_TRIGGER_BESPOKE, }; /* @@ -114,24 +113,6 @@ struct snd_soc_dpcm_runtime { #define for_each_dpcm_be_rollback(fe, stream, _dpcm) \ list_for_each_entry_continue_reverse(_dpcm, &(fe)->dpcm[stream].be_clients, list_be) -/* can this BE stop and free */ -int snd_soc_dpcm_can_be_free_stop(struct snd_soc_pcm_runtime *fe, - struct snd_soc_pcm_runtime *be, int stream); - -/* can this BE perform a hw_params() */ -int snd_soc_dpcm_can_be_params(struct snd_soc_pcm_runtime *fe, - struct snd_soc_pcm_runtime *be, int stream); - -/* can this BE perform prepare */ -int snd_soc_dpcm_can_be_prepared(struct snd_soc_pcm_runtime *fe, - struct snd_soc_pcm_runtime *be, int stream); - -/* is the current PCM operation for this FE ? */ -int snd_soc_dpcm_fe_can_update(struct snd_soc_pcm_runtime *fe, int stream); - -/* is the current PCM operation for this BE ? */ -int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe, - struct snd_soc_pcm_runtime *be, int stream); /* get the substream for this BE */ struct snd_pcm_substream * @@ -151,8 +132,8 @@ static inline void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) int dpcm_path_get(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list **list_); void dpcm_path_put(struct snd_soc_dapm_widget_list **list); -int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, - int stream, struct snd_soc_dapm_widget_list **list, int new); +int dpcm_add_paths(struct snd_soc_pcm_runtime *fe, int stream, + struct snd_soc_dapm_widget_list **list_); int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream); void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream, int do_hw_free, struct snd_soc_dpcm *last); @@ -162,8 +143,8 @@ void dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream); int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int tream); int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd); int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream); -int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, - int event); +void dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, int event); + bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, enum snd_soc_dapm_direction dir); int widget_in_list(struct snd_soc_dapm_widget_list *list, struct snd_soc_dapm_widget *widget); diff --git a/include/sound/soc-jack.h b/include/sound/soc-jack.h index a0abb1ee5110..3a81d4b8ca8a 100644 --- a/include/sound/soc-jack.h +++ b/include/sound/soc-jack.h @@ -44,7 +44,6 @@ struct snd_soc_jack_zone { /** * struct snd_soc_jack_gpio - Describes a gpio pin for jack detection * - * @gpio: legacy gpio number * @idx: gpio descriptor index within the function of the GPIO * consumer device * @gpiod_dev: GPIO consumer device @@ -59,7 +58,6 @@ struct snd_soc_jack_zone { * ADC). */ struct snd_soc_jack_gpio { - unsigned int gpio; unsigned int idx; struct device *gpiod_dev; const char *name; diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h index f055c6917f6c..1eedd203ac29 100644 --- a/include/sound/soc-topology.h +++ b/include/sound/soc-topology.h @@ -178,7 +178,7 @@ static inline const void *snd_soc_tplg_get_data(struct snd_soc_tplg_hdr *hdr) /* Dynamic Object loading and removal for component drivers */ int snd_soc_tplg_component_load(struct snd_soc_component *comp, - struct snd_soc_tplg_ops *ops, const struct firmware *fw); + const struct snd_soc_tplg_ops *ops, const struct firmware *fw); int snd_soc_tplg_component_remove(struct snd_soc_component *comp); /* Binds event handlers to dynamic widgets */ diff --git a/include/sound/soc-usb.h b/include/sound/soc-usb.h new file mode 100644 index 000000000000..124acb1939e5 --- /dev/null +++ b/include/sound/soc-usb.h @@ -0,0 +1,138 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#ifndef __LINUX_SND_SOC_USB_H +#define __LINUX_SND_SOC_USB_H + +#include <sound/soc.h> + +enum snd_soc_usb_kctl { + SND_SOC_USB_KCTL_CARD_ROUTE, + SND_SOC_USB_KCTL_PCM_ROUTE, +}; + +/** + * struct snd_soc_usb_device - SoC USB representation of a USB sound device + * @card_idx: sound card index associated with USB device + * @chip_idx: USB sound chip array index + * @cpcm_idx: capture PCM index array associated with USB device + * @ppcm_idx: playback PCM index array associated with USB device + * @num_capture: number of capture streams + * @num_playback: number of playback streams + * @list: list head for SoC USB devices + **/ +struct snd_soc_usb_device { + int card_idx; + int chip_idx; + + /* PCM index arrays */ + unsigned int *cpcm_idx; /* TODO: capture path is not tested yet */ + unsigned int *ppcm_idx; + int num_capture; /* TODO: capture path is not tested yet */ + int num_playback; + + struct list_head list; +}; + +/** + * struct snd_soc_usb - representation of a SoC USB backend entity + * @list: list head for SND SOC struct list + * @component: reference to ASoC component + * @connection_status_cb: callback to notify connection events + * @update_offload_route_info: callback to fetch mapped ASoC card and pcm + * device pair. This is unrelated to the concept + * of DAPM route. The "route" argument carries + * an array used for a kcontrol output for either + * the card or pcm index. "path" determines the + * which entry to look for. (ie mapped card or pcm) + * @priv_data: driver data + **/ +struct snd_soc_usb { + struct list_head list; + struct snd_soc_component *component; + int (*connection_status_cb)(struct snd_soc_usb *usb, + struct snd_soc_usb_device *sdev, + bool connected); + int (*update_offload_route_info)(struct snd_soc_component *component, + int card, int pcm, int direction, + enum snd_soc_usb_kctl path, + long *route); + void *priv_data; +}; + +#if IS_ENABLED(CONFIG_SND_SOC_USB) +int snd_soc_usb_find_supported_format(int card_idx, + struct snd_pcm_hw_params *params, + int direction); + +int snd_soc_usb_connect(struct device *usbdev, struct snd_soc_usb_device *sdev); +int snd_soc_usb_disconnect(struct device *usbdev, struct snd_soc_usb_device *sdev); +void *snd_soc_usb_find_priv_data(struct device *usbdev); + +int snd_soc_usb_setup_offload_jack(struct snd_soc_component *component, + struct snd_soc_jack *jack); +int snd_soc_usb_update_offload_route(struct device *dev, int card, int pcm, + int direction, enum snd_soc_usb_kctl path, + long *route); + +struct snd_soc_usb *snd_soc_usb_allocate_port(struct snd_soc_component *component, + void *data); +void snd_soc_usb_free_port(struct snd_soc_usb *usb); +void snd_soc_usb_add_port(struct snd_soc_usb *usb); +void snd_soc_usb_remove_port(struct snd_soc_usb *usb); +#else +static inline int +snd_soc_usb_find_supported_format(int card_idx, struct snd_pcm_hw_params *params, + int direction) +{ + return -EINVAL; +} + +static inline int snd_soc_usb_connect(struct device *usbdev, + struct snd_soc_usb_device *sdev) +{ + return -ENODEV; +} + +static inline int snd_soc_usb_disconnect(struct device *usbdev, + struct snd_soc_usb_device *sdev) +{ + return -EINVAL; +} + +static inline void *snd_soc_usb_find_priv_data(struct device *usbdev) +{ + return NULL; +} + +static inline int snd_soc_usb_setup_offload_jack(struct snd_soc_component *component, + struct snd_soc_jack *jack) +{ + return 0; +} + +static int snd_soc_usb_update_offload_route(struct device *dev, int card, int pcm, + int direction, enum snd_soc_usb_kctl path, + long *route) +{ + return -ENODEV; +} + +static inline struct snd_soc_usb * +snd_soc_usb_allocate_port(struct snd_soc_component *component, void *data) +{ + return ERR_PTR(-ENOMEM); +} + +static inline void snd_soc_usb_free_port(struct snd_soc_usb *usb) +{ } + +static inline void snd_soc_usb_add_port(struct snd_soc_usb *usb) +{ } + +static inline void snd_soc_usb_remove_port(struct snd_soc_usb *usb) +{ } +#endif /* IS_ENABLED(CONFIG_SND_SOC_USB) */ +#endif /*__LINUX_SND_SOC_USB_H */ diff --git a/include/sound/soc.h b/include/sound/soc.h index b27f84580c5b..aa0fe6b80293 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -10,65 +10,64 @@ #ifndef __LINUX_SND_SOC_H #define __LINUX_SND_SOC_H +#include <linux/args.h> +#include <linux/array_size.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/interrupt.h> +#include <linux/lockdep.h> +#include <linux/log2.h> +#include <linux/mutex.h> +#include <linux/notifier.h> #include <linux/of.h> -#include <linux/platform_device.h> #include <linux/types.h> -#include <linux/notifier.h> #include <linux/workqueue.h> -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/regmap.h> -#include <linux/log2.h> -#include <sound/core.h> -#include <sound/pcm.h> + +#include <sound/ac97_codec.h> #include <sound/compress_driver.h> #include <sound/control.h> -#include <sound/ac97_codec.h> +#include <sound/core.h> +#include <sound/pcm.h> + +struct module; +struct platform_device; + +/* For the current users of sound/soc.h to avoid build issues */ +#include <linux/platform_device.h> +#include <linux/regmap.h> /* * Convenience kcontrol builders */ -#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert, xautodisable) \ - ((unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, .shift = shift_left, \ - .rshift = shift_right, .max = xmax, \ - .invert = xinvert, .autodisable = xautodisable}) -#define SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, xsign_bit, xinvert, xautodisable) \ +#define SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, xsign_bit, \ + xinvert, xautodisable) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .rreg = xreg, .shift = shift_left, \ .rshift = shift_right, .min = xmin, .max = xmax, \ .sign_bit = xsign_bit, .invert = xinvert, .autodisable = xautodisable}) -#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \ - SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable) -#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ - ((unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .max = xmax, .invert = xinvert}) -#define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmax, xinvert) \ - ((unsigned long)&(struct soc_mixer_control) \ - {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ - .max = xmax, .invert = xinvert}) +#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmin, xmax, xinvert, xautodisable) \ + SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, 0, xinvert, \ + xautodisable) +#define SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, xautodisable) \ + SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmin, xmax, xinvert, xautodisable) #define SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, xsign_bit, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ .max = xmax, .min = xmin, .sign_bit = xsign_bit, \ .invert = xinvert}) -#define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \ - ((unsigned long)&(struct soc_mixer_control) \ - {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ - .min = xmin, .max = xmax, .invert = xinvert}) +#define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \ + SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, 0, xinvert) + #define SOC_SINGLE(xname, reg, shift, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ .put = snd_soc_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } + .private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 0) } #define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \ - .put = snd_soc_put_volsw_range, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, .shift = xshift, \ - .rshift = xshift, .min = xmin, .max = xmax, \ - .invert = xinvert} } + .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ + .put = snd_soc_put_volsw, \ + .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -76,7 +75,7 @@ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ .put = snd_soc_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) } + .private_value = SOC_SINGLE_VALUE(reg, shift, 0, max, invert, 0) } #define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ @@ -85,27 +84,21 @@ .info = snd_soc_info_volsw_sx, \ .get = snd_soc_get_volsw_sx,\ .put = snd_soc_put_volsw_sx, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, \ - .shift = xshift, .rshift = xshift, \ - .max = xmax, .min = xmin} } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, 0, 0) } #define SOC_SINGLE_RANGE_TLV(xname, xreg, xshift, xmin, xmax, xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_range, \ - .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, .shift = xshift, \ - .rshift = xshift, .min = xmin, .max = xmax, \ - .invert = xinvert} } + .info = snd_soc_info_volsw, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ + .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ - max, invert, 0) } + 0, max, invert, 0) } #define SOC_DOUBLE_STS(xname, reg, shift_left, shift_right, max, invert) \ { \ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -113,19 +106,19 @@ .access = SNDRV_CTL_ELEM_ACCESS_READ | \ SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ - max, invert, 0) } + 0, max, invert, 0) } #define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .info = snd_soc_info_volsw, \ .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } + 0, xmax, xinvert) } #define SOC_DOUBLE_R_RANGE(xname, reg_left, reg_right, xshift, xmin, \ xmax, xinvert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ - .info = snd_soc_info_volsw_range, \ - .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ - .private_value = SOC_DOUBLE_R_RANGE_VALUE(reg_left, reg_right, \ + .info = snd_soc_info_volsw, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ + .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, \ xshift, xmin, xmax, xinvert) } #define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ @@ -135,7 +128,7 @@ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ - max, invert, 0) } + 0, max, invert, 0) } #define SOC_DOUBLE_SX_TLV(xname, xreg, shift_left, shift_right, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ @@ -144,10 +137,18 @@ .info = snd_soc_info_volsw_sx, \ .get = snd_soc_get_volsw_sx, \ .put = snd_soc_put_volsw_sx, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xreg, \ - .shift = shift_left, .rshift = shift_right, \ - .max = xmax, .min = xmin} } + .private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \ + xmin, xmax, 0, 0) } +#define SOC_DOUBLE_RANGE_TLV(xname, xreg, xshift_left, xshift_right, xmin, xmax, \ + xinvert, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ + SNDRV_CTL_ELEM_ACCESS_READWRITE,\ + .tlv.p = (tlv_array), \ + .info = snd_soc_info_volsw, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ + .private_value = SOC_DOUBLE_VALUE(xreg, xshift_left, xshift_right, \ + xmin, xmax, xinvert, 0) } #define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -156,16 +157,16 @@ .info = snd_soc_info_volsw, \ .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } + 0, xmax, xinvert) } #define SOC_DOUBLE_R_RANGE_TLV(xname, reg_left, reg_right, xshift, xmin, \ xmax, xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_range, \ - .get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \ - .private_value = SOC_DOUBLE_R_RANGE_VALUE(reg_left, reg_right, \ + .info = snd_soc_info_volsw, \ + .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ + .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, \ xshift, xmin, xmax, xinvert) } #define SOC_DOUBLE_R_SX_TLV(xname, xreg, xrreg, xshift, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -175,10 +176,7 @@ .info = snd_soc_info_volsw_sx, \ .get = snd_soc_get_volsw_sx, \ .put = snd_soc_put_volsw_sx, \ - .private_value = (unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .rreg = xrreg, \ - .shift = xshift, .rshift = xshift, \ - .max = xmax, .min = xmin} } + .private_value = SOC_DOUBLE_R_VALUE(xreg, xrreg, xshift, xmin, xmax, 0) } #define SOC_DOUBLE_R_S_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -238,21 +236,21 @@ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ - .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, 0, xmax, xinvert, 0) } #define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\ xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = \ - SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert, 0) } + SOC_DOUBLE_VALUE(reg, shift_left, shift_right, 0, max, invert, 0) } #define SOC_DOUBLE_R_EXT(xname, reg_left, reg_right, xshift, xmax, xinvert,\ xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } + 0, xmax, xinvert) } #define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -261,19 +259,16 @@ .tlv.p = (tlv_array), \ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ - .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, 0) } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, 0, xmax, xinvert, 0) } #define SOC_SINGLE_RANGE_EXT_TLV(xname, xreg, xshift, xmin, xmax, xinvert, \ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ SNDRV_CTL_ELEM_ACCESS_READWRITE,\ .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw_range, \ + .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} } + .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmin, xmax, xinvert, 0) } #define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -283,7 +278,7 @@ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \ - xmax, xinvert, 0) } + 0, xmax, xinvert, 0) } #define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -293,7 +288,7 @@ .info = snd_soc_info_volsw, \ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ - xmax, xinvert) } + 0, xmax, xinvert) } #define SOC_DOUBLE_R_S_EXT_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, \ xsign_bit, xinvert, xhandler_get, xhandler_put, \ tlv_array) \ @@ -324,6 +319,13 @@ #define SOC_VALUE_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \ SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) +#define SOC_ENUM_EXT_ACC(xname, xenum, xhandler_get, xhandler_put, xaccess) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .access = xaccess, \ + .info = snd_soc_info_enum_double, \ + .get = xhandler_get, .put = xhandler_put, \ + .private_value = (unsigned long)&xenum } + #define SND_SOC_BYTES(xname, xbase, xregs) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_bytes_info, .get = snd_soc_bytes_get, \ @@ -336,6 +338,13 @@ .put = xhandler_put, .private_value = \ ((unsigned long)&(struct soc_bytes) \ {.base = xbase, .num_regs = xregs }) } +#define SND_SOC_BYTES_E_ACC(xname, xbase, xregs, xhandler_get, xhandler_put, xaccess) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ + .access = xaccess, \ + .info = snd_soc_bytes_info, .get = xhandler_get, \ + .put = xhandler_put, .private_value = \ + ((unsigned long)&(struct soc_bytes) \ + {.base = xbase, .num_regs = xregs }) } #define SND_SOC_BYTES_MASK(xname, xbase, xregs, xmask) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ @@ -399,27 +408,20 @@ #define SOC_ENUM_SINGLE_VIRT_DECL(name, xtexts) \ const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts) -struct device_node; -struct snd_jack; struct snd_soc_card; -struct snd_soc_pcm_stream; -struct snd_soc_ops; struct snd_soc_pcm_runtime; struct snd_soc_dai; struct snd_soc_dai_driver; struct snd_soc_dai_link; struct snd_soc_component; struct snd_soc_component_driver; -struct soc_enum; struct snd_soc_jack; -struct snd_soc_jack_zone; struct snd_soc_jack_pin; + #include <sound/soc-dapm.h> #include <sound/soc-dpcm.h> #include <sound/soc-topology.h> -struct snd_soc_jack_gpio; - enum snd_soc_pcm_subclass { SND_SOC_PCM_CLASS_PCM = 0, SND_SOC_PCM_CLASS_BE = 1, @@ -428,6 +430,7 @@ enum snd_soc_pcm_subclass { int snd_soc_register_card(struct snd_soc_card *card); void snd_soc_unregister_card(struct snd_soc_card *card); int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card); +int devm_snd_soc_register_deferrable_card(struct device *dev, struct snd_soc_card *card); #ifdef CONFIG_PM_SLEEP int snd_soc_suspend(struct device *dev); int snd_soc_resume(struct device *dev); @@ -455,7 +458,7 @@ int snd_soc_register_component(struct device *dev, int devm_snd_soc_register_component(struct device *dev, const struct snd_soc_component_driver *component_driver, struct snd_soc_dai_driver *dai_drv, int num_dai); -void snd_soc_unregister_component(struct device *dev); +#define snd_soc_unregister_component(dev) snd_soc_unregister_component_by_driver(dev, NULL) void snd_soc_unregister_component_by_driver(struct device *dev, const struct snd_soc_component_driver *component_driver); struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev, @@ -463,18 +466,16 @@ struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev, struct snd_soc_component *snd_soc_lookup_component(struct device *dev, const char *driver_name); -int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num); +int soc_new_pcm(struct snd_soc_pcm_runtime *rtd); #ifdef CONFIG_SND_SOC_COMPRESS -int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num); +int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd); #else -static inline int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) +static inline int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd) { return 0; } #endif -void snd_soc_disconnect_sync(struct device *dev); - struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); @@ -499,27 +500,23 @@ int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, unsigned int dai_fmt); -#ifdef CONFIG_DMI -int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour); -#else -static inline int snd_soc_set_dmi_name(struct snd_soc_card *card, - const char *flavour) -{ - return 0; -} -#endif - /* Utility functions to get clock rates from various things */ int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); -int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); +int snd_soc_params_to_frame_size(const struct snd_pcm_hw_params *params); int snd_soc_calc_bclk(int fs, int sample_size, int channels, int tdm_slots); -int snd_soc_params_to_bclk(struct snd_pcm_hw_params *parms); -int snd_soc_tdm_params_to_bclk(struct snd_pcm_hw_params *params, +int snd_soc_params_to_bclk(const struct snd_pcm_hw_params *parms); +int snd_soc_tdm_params_to_bclk(const struct snd_pcm_hw_params *params, int tdm_width, int tdm_slots, int slot_multiple); +int snd_soc_ret(const struct device *dev, int ret, const char *fmt, ...); /* set runtime hw params */ -int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, - const struct snd_pcm_hardware *hw); +static inline int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, + const struct snd_pcm_hardware *hw) +{ + substream->runtime->hw = *hw; + + return 0; +} struct snd_ac97 *snd_soc_alloc_ac97_component(struct snd_soc_component *component); struct snd_ac97 *snd_soc_new_ac97_component(struct snd_soc_component *component, @@ -578,12 +575,6 @@ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -int snd_soc_info_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo); -int snd_soc_put_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); -int snd_soc_get_volsw_range(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol); int snd_soc_limit_volume(struct snd_soc_card *card, const char *name, int max); int snd_soc_bytes_info(struct snd_kcontrol *kcontrol, @@ -619,6 +610,7 @@ enum snd_soc_trigger_order { struct snd_soc_pcm_stream { const char *stream_name; u64 formats; /* SNDRV_PCM_FMTBIT_* */ + u32 subformats; /* for S32_LE format, SNDRV_PCM_SUBFMTBIT_* */ unsigned int rates; /* SNDRV_PCM_RATE_* */ unsigned int rate_min; /* min rate */ unsigned int rate_max; /* max rate */ @@ -651,10 +643,59 @@ struct snd_soc_dai_link_component { const char *name; struct device_node *of_node; const char *dai_name; + const struct of_phandle_args *dai_args; + + /* + * Extra format = SND_SOC_DAIFMT_Bx_Fx + * + * [Note] it is Bx_Fx base, not CBx_CFx + * + * It will be used with dai_link->dai_fmt + * see + * snd_soc_runtime_set_dai_fmt() + */ + unsigned int ext_fmt; }; -struct snd_soc_dai_link_codec_ch_map { - unsigned int connected_cpu_id; +/* + * [dai_link->ch_maps Image sample] + * + *------------------------- + * CPU0 <---> Codec0 + * + * ch-map[0].cpu = 0 ch-map[0].codec = 0 + * + *------------------------- + * CPU0 <---> Codec0 + * CPU1 <---> Codec1 + * CPU2 <---> Codec2 + * + * ch-map[0].cpu = 0 ch-map[0].codec = 0 + * ch-map[1].cpu = 1 ch-map[1].codec = 1 + * ch-map[2].cpu = 2 ch-map[2].codec = 2 + * + *------------------------- + * CPU0 <---> Codec0 + * CPU1 <-+-> Codec1 + * CPU2 <-/ + * + * ch-map[0].cpu = 0 ch-map[0].codec = 0 + * ch-map[1].cpu = 1 ch-map[1].codec = 1 + * ch-map[2].cpu = 2 ch-map[2].codec = 1 + * + *------------------------- + * CPU0 <---> Codec0 + * CPU1 <-+-> Codec1 + * \-> Codec2 + * + * ch-map[0].cpu = 0 ch-map[0].codec = 0 + * ch-map[1].cpu = 1 ch-map[1].codec = 1 + * ch-map[2].cpu = 1 ch-map[2].codec = 2 + * + */ +struct snd_soc_dai_link_ch_map { + unsigned int cpu; + unsigned int codec; unsigned int ch_mask; }; @@ -686,7 +727,9 @@ struct snd_soc_dai_link { struct snd_soc_dai_link_component *codecs; unsigned int num_codecs; - struct snd_soc_dai_link_codec_ch_map *codec_ch_maps; + /* num_ch_maps = max(num_cpu, num_codecs) */ + struct snd_soc_dai_link_ch_map *ch_maps; + /* * You MAY specify the link's platform/PCM/DMA driver, either by * device name, or by DT/OF node, but not both. Some forms of link @@ -751,10 +794,6 @@ struct snd_soc_dai_link { /* This DAI link can route to other DAI links at runtime (Frontend)*/ unsigned int dynamic:1; - /* DPCM capture and Playback support */ - unsigned int dpcm_capture:1; - unsigned int dpcm_playback:1; - /* DPCM used FE & BE merged format */ unsigned int dpcm_merged_format:1; /* DPCM used FE & BE merged channel */ @@ -773,37 +812,48 @@ struct snd_soc_dai_link { #endif }; +static inline int snd_soc_link_num_ch_map(const struct snd_soc_dai_link *link) +{ + return max(link->num_cpus, link->num_codecs); +} + static inline struct snd_soc_dai_link_component* -asoc_link_to_cpu(struct snd_soc_dai_link *link, int n) { +snd_soc_link_to_cpu(struct snd_soc_dai_link *link, int n) { return &(link)->cpus[n]; } static inline struct snd_soc_dai_link_component* -asoc_link_to_codec(struct snd_soc_dai_link *link, int n) { +snd_soc_link_to_codec(struct snd_soc_dai_link *link, int n) { return &(link)->codecs[n]; } static inline struct snd_soc_dai_link_component* -asoc_link_to_platform(struct snd_soc_dai_link *link, int n) { +snd_soc_link_to_platform(struct snd_soc_dai_link *link, int n) { return &(link)->platforms[n]; } #define for_each_link_codecs(link, i, codec) \ for ((i) = 0; \ ((i) < link->num_codecs) && \ - ((codec) = asoc_link_to_codec(link, i)); \ + ((codec) = snd_soc_link_to_codec(link, i)); \ (i)++) #define for_each_link_platforms(link, i, platform) \ for ((i) = 0; \ ((i) < link->num_platforms) && \ - ((platform) = asoc_link_to_platform(link, i)); \ + ((platform) = snd_soc_link_to_platform(link, i)); \ (i)++) #define for_each_link_cpus(link, i, cpu) \ for ((i) = 0; \ ((i) < link->num_cpus) && \ - ((cpu) = asoc_link_to_cpu(link, i)); \ + ((cpu) = snd_soc_link_to_cpu(link, i)); \ + (i)++) + +#define for_each_link_ch_maps(link, i, ch_map) \ + for ((i) = 0; \ + ((i) < snd_soc_link_num_ch_map(link) && \ + ((ch_map) = link->ch_maps + i)); \ (i)++) /* @@ -869,12 +919,8 @@ asoc_link_to_platform(struct snd_soc_dai_link *link, int n) { .platforms = platform, \ .num_platforms = ARRAY_SIZE(platform) -#define SND_SOC_DAILINK_REGx(_1, _2, _3, func, ...) func #define SND_SOC_DAILINK_REG(...) \ - SND_SOC_DAILINK_REGx(__VA_ARGS__, \ - SND_SOC_DAILINK_REG3, \ - SND_SOC_DAILINK_REG2, \ - SND_SOC_DAILINK_REG1)(__VA_ARGS__) + CONCATENATE(SND_SOC_DAILINK_REG, COUNT_ARGS(__VA_ARGS__))(__VA_ARGS__) #define SND_SOC_DAILINK_DEF(name, def...) \ static struct snd_soc_dai_link_component name[] = { def } @@ -891,11 +937,11 @@ asoc_link_to_platform(struct snd_soc_dai_link *link, int n) { #define COMP_PLATFORM(_name) { .name = _name } #define COMP_AUX(_name) { .name = _name } #define COMP_CODEC_CONF(_name) { .name = _name } -#define COMP_DUMMY() { .name = "snd-soc-dummy", .dai_name = "snd-soc-dummy-dai", } +#define COMP_DUMMY() /* see snd_soc_fill_dummy_dai() */ extern struct snd_soc_dai_link_component null_dailink_component[0]; -extern struct snd_soc_dai_link_component asoc_dummy_dlc; - +extern struct snd_soc_dai_link_component snd_soc_dummy_dlc; +int snd_soc_dlc_is_dummy(struct snd_soc_dai_link_component *dlc); struct snd_soc_codec_conf { /* @@ -931,6 +977,17 @@ struct snd_soc_card { #ifdef CONFIG_DMI char dmi_longname[80]; #endif /* CONFIG_DMI */ + +#ifdef CONFIG_PCI + /* + * PCI does not define 0 as invalid, so pci_subsystem_set indicates + * whether a value has been written to these fields. + */ + unsigned short pci_subsystem_vendor; + unsigned short pci_subsystem_device; + bool pci_subsystem_set; +#endif /* CONFIG_PCI */ + char topology_shortname[32]; struct device *dev; @@ -1021,7 +1078,6 @@ struct snd_soc_card { /* Generic DAPM context for the card */ struct snd_soc_dapm_context dapm; struct snd_soc_dapm_stats dapm_stats; - struct snd_soc_dapm_update *update; #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_card_root; @@ -1035,9 +1091,9 @@ struct snd_soc_card { unsigned int instantiated:1; unsigned int topology_shortname_created:1; unsigned int fully_routed:1; - unsigned int disable_route_checks:1; unsigned int probed:1; unsigned int component_chaining:1; + struct device *devres_dev; void *drvdata; }; @@ -1078,6 +1134,11 @@ static inline int snd_soc_card_is_instantiated(struct snd_soc_card *card) return card && card->instantiated; } +static inline struct snd_soc_dapm_context *snd_soc_card_to_dapm(struct snd_soc_card *card) +{ + return &card->dapm; +} + /* SoC machine DAI configuration, glues a codec and cpu DAI together */ struct snd_soc_pcm_runtime { struct device *dev; @@ -1101,8 +1162,8 @@ struct snd_soc_pcm_runtime { * dais = cpu_dai + codec_dai * see * soc_new_pcm_runtime() - * asoc_rtd_to_cpu() - * asoc_rtd_to_codec() + * snd_soc_rtd_to_cpu() + * snd_soc_rtd_to_codec() */ struct snd_soc_dai **dais; @@ -1112,7 +1173,7 @@ struct snd_soc_pcm_runtime { struct dentry *debugfs_dpcm_root; #endif - unsigned int num; /* 0-based and monotonic increasing */ + unsigned int id; /* 0-based and monotonic increasing */ struct list_head list; /* rtd list of the soc card */ /* function mark */ @@ -1124,15 +1185,22 @@ struct snd_soc_pcm_runtime { /* bit field */ unsigned int pop_wait:1; unsigned int fe_compr:1; /* for Dynamic PCM */ + unsigned int initialized:1; + /* CPU/Codec/Platform */ int num_components; - struct snd_soc_component *components[]; /* CPU/Codec/Platform */ + struct snd_soc_component *components[] __counted_by(num_components); }; + /* see soc_new_pcm_runtime() */ -#define asoc_rtd_to_cpu(rtd, n) (rtd)->dais[n] -#define asoc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->dai_link->num_cpus] -#define asoc_substream_to_rtd(substream) \ - (struct snd_soc_pcm_runtime *)snd_pcm_substream_chip(substream) +#define snd_soc_rtd_to_cpu(rtd, n) (rtd)->dais[n] +#define snd_soc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->dai_link->num_cpus] + +static inline struct snd_soc_pcm_runtime * +snd_soc_substream_to_rtd(const struct snd_pcm_substream *substream) +{ + return snd_pcm_substream_chip(substream); +} #define for_each_rtd_components(rtd, i, component) \ for ((i) = 0, component = NULL; \ @@ -1140,28 +1208,38 @@ struct snd_soc_pcm_runtime { (i)++) #define for_each_rtd_cpu_dais(rtd, i, dai) \ for ((i) = 0; \ - ((i) < rtd->dai_link->num_cpus) && ((dai) = asoc_rtd_to_cpu(rtd, i)); \ + ((i) < rtd->dai_link->num_cpus) && ((dai) = snd_soc_rtd_to_cpu(rtd, i)); \ (i)++) #define for_each_rtd_codec_dais(rtd, i, dai) \ for ((i) = 0; \ - ((i) < rtd->dai_link->num_codecs) && ((dai) = asoc_rtd_to_codec(rtd, i)); \ + ((i) < rtd->dai_link->num_codecs) && ((dai) = snd_soc_rtd_to_codec(rtd, i)); \ (i)++) #define for_each_rtd_dais(rtd, i, dai) \ for ((i) = 0; \ ((i) < (rtd)->dai_link->num_cpus + (rtd)->dai_link->num_codecs) && \ ((dai) = (rtd)->dais[i]); \ (i)++) +#define for_each_rtd_dais_reverse(rtd, i, dai) \ + for ((i) = (rtd)->dai_link->num_cpus + (rtd)->dai_link->num_codecs - 1; \ + (i) >= 0 && ((dai) = (rtd)->dais[i]); \ + (i)--) +#define for_each_rtd_ch_maps(rtd, i, ch_maps) for_each_link_ch_maps(rtd->dai_link, i, ch_maps) void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd); /* mixer control */ struct soc_mixer_control { - int min, max, platform_max; + /* Minimum and maximum specified as written to the hardware */ + int min, max; + /* Limited maximum value specified as presented through the control */ + int platform_max; int reg, rreg; unsigned int shift, rshift; + u32 num_channels; unsigned int sign_bit; unsigned int invert:1; unsigned int autodisable:1; + unsigned int sdca_q78:1; #ifdef CONFIG_SND_SOC_TOPOLOGY struct snd_soc_dobj dobj; #endif @@ -1206,7 +1284,7 @@ struct soc_enum { #endif }; -static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) +static inline bool snd_soc_volsw_is_stereo(const struct soc_mixer_control *mc) { if (mc->reg == mc->rreg && mc->shift == mc->rshift) return false; @@ -1218,7 +1296,7 @@ static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) return true; } -static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e, +static inline unsigned int snd_soc_enum_val_to_item(const struct soc_enum *e, unsigned int val) { unsigned int i; @@ -1233,7 +1311,7 @@ static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e, return 0; } -static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e, +static inline unsigned int snd_soc_enum_item_to_val(const struct soc_enum *e, unsigned int item) { if (!e->values) @@ -1242,22 +1320,6 @@ static inline unsigned int snd_soc_enum_item_to_val(struct soc_enum *e, return e->values[item]; } -/** - * snd_soc_kcontrol_component() - Returns the component that registered the - * control - * @kcontrol: The control for which to get the component - * - * Note: This function will work correctly if the control has been registered - * for a component. With snd_soc_add_codec_controls() or via table based - * setup for either a CODEC or component driver. Otherwise the behavior is - * undefined. - */ -static inline struct snd_soc_component *snd_soc_kcontrol_component( - struct snd_kcontrol *kcontrol) -{ - return snd_kcontrol_chip(kcontrol); -} - int snd_soc_util_init(void); void snd_soc_util_exit(void); @@ -1308,7 +1370,7 @@ unsigned int snd_soc_daifmt_parse_clock_provider_raw(struct device_node *np, snd_soc_daifmt_clock_provider_from_bitmap( \ snd_soc_daifmt_parse_clock_provider_as_bitmap(np, prefix)) -int snd_soc_get_stream_cpu(struct snd_soc_dai_link *dai_link, int stream); +int snd_soc_get_stream_cpu(const struct snd_soc_dai_link *dai_link, int stream); int snd_soc_get_dlc(const struct of_phandle_args *args, struct snd_soc_dai_link_component *dlc); int snd_soc_of_get_dlc(struct device_node *of_node, @@ -1335,13 +1397,14 @@ int snd_soc_add_pcm_runtimes(struct snd_soc_card *card, void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, struct snd_soc_pcm_runtime *rtd); +void snd_soc_dlc_use_cpu_as_platform(struct snd_soc_dai_link_component *platforms, + struct snd_soc_dai_link_component *cpus); +struct of_phandle_args *snd_soc_copy_dai_args(struct device *dev, + const struct of_phandle_args *args); +struct snd_soc_dai *snd_soc_get_dai_via_args(const struct of_phandle_args *dai_args); struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv, bool legacy_dai_naming); -struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev, - struct snd_soc_component *component, - struct snd_soc_dai_driver *dai_drv, - bool legacy_dai_naming); void snd_soc_unregister_dai(struct snd_soc_dai *dai); struct snd_soc_dai *snd_soc_find_dai( @@ -1418,22 +1481,22 @@ static inline void _snd_soc_dapm_mutex_assert_held_c(struct snd_soc_card *card) static inline void _snd_soc_dapm_mutex_lock_root_d(struct snd_soc_dapm_context *dapm) { - _snd_soc_dapm_mutex_lock_root_c(dapm->card); + _snd_soc_dapm_mutex_lock_root_c(snd_soc_dapm_to_card(dapm)); } static inline void _snd_soc_dapm_mutex_lock_d(struct snd_soc_dapm_context *dapm) { - _snd_soc_dapm_mutex_lock_c(dapm->card); + _snd_soc_dapm_mutex_lock_c(snd_soc_dapm_to_card(dapm)); } static inline void _snd_soc_dapm_mutex_unlock_d(struct snd_soc_dapm_context *dapm) { - _snd_soc_dapm_mutex_unlock_c(dapm->card); + _snd_soc_dapm_mutex_unlock_c(snd_soc_dapm_to_card(dapm)); } static inline void _snd_soc_dapm_mutex_assert_held_d(struct snd_soc_dapm_context *dapm) { - _snd_soc_dapm_mutex_assert_held_c(dapm->card); + _snd_soc_dapm_mutex_assert_held_c(snd_soc_dapm_to_card(dapm)); } #define snd_soc_dapm_mutex_lock_root(x) _Generic((x), \ diff --git a/include/sound/soc_sdw_utils.h b/include/sound/soc_sdw_utils.h new file mode 100644 index 000000000000..227347c8f0b3 --- /dev/null +++ b/include/sound/soc_sdw_utils.h @@ -0,0 +1,273 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * This file incorporates work covered by the following copyright notice: + * Copyright (c) 2020 Intel Corporation + * Copyright(c) 2024 Advanced Micro Devices, Inc. + * + */ + +#ifndef SOC_SDW_UTILS_H +#define SOC_SDW_UTILS_H + +#include <sound/soc.h> +#include <sound/soc-acpi.h> + +#define SOC_SDW_MAX_DAI_NUM 8 +#define SOC_SDW_MAX_AUX_NUM 2 +#define SOC_SDW_MAX_NO_PROPS 2 +#define SOC_SDW_JACK_JDSRC(quirk) ((quirk) & GENMASK(3, 0)) + +/* If a CODEC has an optional speaker output, this quirk will enable it */ +#define SOC_SDW_CODEC_SPKR BIT(15) +/* + * If the CODEC has additional devices attached directly to it. + * + * For the cs42l43: + * - 0 - No speaker output + * - SOC_SDW_CODEC_SPKR - CODEC internal speaker + * - SOC_SDW_SIDECAR_AMPS - 2x Sidecar amplifiers + CODEC internal speaker + * - SOC_SDW_CODEC_SPKR | SOF_SIDECAR_AMPS - Not currently supported + */ +#define SOC_SDW_SIDECAR_AMPS BIT(16) +#define SOC_SDW_CODEC_MIC BIT(17) + +#define SOC_SDW_UNUSED_DAI_ID -1 +#define SOC_SDW_JACK_OUT_DAI_ID 0 +#define SOC_SDW_JACK_IN_DAI_ID 1 +#define SOC_SDW_AMP_OUT_DAI_ID 2 +#define SOC_SDW_AMP_IN_DAI_ID 3 +#define SOC_SDW_DMIC_DAI_ID 4 + +#define SOC_SDW_DAI_TYPE_JACK 0 +#define SOC_SDW_DAI_TYPE_AMP 1 +#define SOC_SDW_DAI_TYPE_MIC 2 + +struct asoc_sdw_codec_info; + +struct asoc_sdw_dai_info { + const bool direction[2]; /* playback & capture support */ + const char *codec_name; + const char *dai_name; + const char *component_name; + const int dai_type; + const int dailink[2]; /* dailink id for each direction */ + const struct snd_kcontrol_new *controls; + const int num_controls; + const struct snd_soc_dapm_widget *widgets; + const int num_widgets; + int (*init)(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); + int (*exit)(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); + int (*rtd_init)(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); + bool rtd_init_done; /* Indicate that the rtd_init callback is done */ + unsigned long quirk; + bool quirk_exclude; +}; + +struct asoc_sdw_aux_info { + const char *codec_name; +}; + +struct asoc_sdw_codec_info { + const int part_id; + const int version_id; + const char *name_prefix; + int amp_num; + const u8 acpi_id[ACPI_ID_LEN]; + const bool ignore_internal_dmic; + const struct snd_soc_ops *ops; + struct asoc_sdw_dai_info dais[SOC_SDW_MAX_DAI_NUM]; + const int dai_num; + struct asoc_sdw_aux_info auxs[SOC_SDW_MAX_AUX_NUM]; + const int aux_num; + + int (*codec_card_late_probe)(struct snd_soc_card *card); + + int (*count_sidecar)(struct snd_soc_card *card, + int *num_dais, int *num_devs); + int (*add_sidecar)(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, + struct snd_soc_codec_conf **codec_conf); +}; + +struct asoc_sdw_mc_private { + struct snd_soc_card card; + struct snd_soc_jack sdw_headset; + struct device *headset_codec_dev; /* only one headset per card */ + struct device *amp_dev1, *amp_dev2; + bool append_dai_type; + bool ignore_internal_dmic; + void *private; + unsigned long mc_quirk; + int codec_info_list_count; +}; + +struct asoc_sdw_endpoint { + struct list_head list; + + u32 link_mask; + const char *codec_name; + const char *name_prefix; + bool include_sidecar; + + struct asoc_sdw_codec_info *codec_info; + const struct asoc_sdw_dai_info *dai_info; +}; + +struct asoc_sdw_dailink { + bool initialised; + + u8 group_id; + u32 link_mask[SNDRV_PCM_STREAM_LAST + 1]; + int num_devs[SNDRV_PCM_STREAM_LAST + 1]; + struct list_head endpoints; +}; + +extern struct asoc_sdw_codec_info codec_info_list[]; +int asoc_sdw_get_codec_info_list_count(void); + +int asoc_sdw_startup(struct snd_pcm_substream *substream); +int asoc_sdw_prepare(struct snd_pcm_substream *substream); +int asoc_sdw_prepare(struct snd_pcm_substream *substream); +int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd); +int asoc_sdw_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); +int asoc_sdw_hw_free(struct snd_pcm_substream *substream); +void asoc_sdw_shutdown(struct snd_pcm_substream *substream); + +const char *asoc_sdw_get_codec_name(struct device *dev, + const struct asoc_sdw_dai_info *dai_info, + const struct snd_soc_acpi_link_adr *adr_link, + int adr_index); + +struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_part(const u64 adr); + +struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_acpi(const u8 *acpi_id); + +struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_dai(const char *dai_name, + int *dai_index); + +struct snd_soc_dai_link *asoc_sdw_mc_find_codec_dai_used(struct snd_soc_card *card, + const char *dai_name); + +void asoc_sdw_mc_dailink_exit_loop(struct snd_soc_card *card); + +int asoc_sdw_card_late_probe(struct snd_soc_card *card); + +void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, + int *be_id, char *name, int playback, int capture, + struct snd_soc_dai_link_component *cpus, int cpus_num, + struct snd_soc_dai_link_component *platform_component, + int num_platforms, struct snd_soc_dai_link_component *codecs, + int codecs_num, int no_pcm, + int (*init)(struct snd_soc_pcm_runtime *rtd), + const struct snd_soc_ops *ops); + +int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links, + int *be_id, char *name, int playback, int capture, + const char *cpu_dai_name, const char *platform_comp_name, + const char *codec_name, const char *codec_dai_name, + int no_pcm, int (*init)(struct snd_soc_pcm_runtime *rtd), + const struct snd_soc_ops *ops); + +int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card, + int *num_devs, int *num_ends, int *num_aux); + +struct asoc_sdw_dailink *asoc_sdw_find_dailink(struct asoc_sdw_dailink *dailinks, + const struct snd_soc_acpi_endpoint *new); +int asoc_sdw_get_dai_type(u32 type); + +int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card, + struct snd_soc_aux_dev *soc_aux, + struct asoc_sdw_dailink *soc_dais, + struct asoc_sdw_endpoint *soc_ends, + int *num_devs); + +int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd); + +/* DMIC support */ +int asoc_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd); + +/* RT711 support */ +int asoc_sdw_rt711_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); +int asoc_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); + +/* RT711-SDCA support */ +int asoc_sdw_rt_sdca_jack_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); +int asoc_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); + +/* RT1308 I2S support */ +extern const struct snd_soc_ops soc_sdw_rt1308_i2s_ops; + +/* generic amp support */ +int asoc_sdw_rt_amp_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); +int asoc_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); + +/* CS42L43 support */ +int asoc_sdw_cs42l43_spk_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); + +/* CS AMP support */ +int asoc_sdw_bridge_cs35l56_count_sidecar(struct snd_soc_card *card, + int *num_dais, int *num_devs); +int asoc_sdw_bridge_cs35l56_add_sidecar(struct snd_soc_card *card, + struct snd_soc_dai_link **dai_links, + struct snd_soc_codec_conf **codec_conf); +int asoc_sdw_bridge_cs35l56_spk_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); + +int asoc_sdw_cs_amp_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); +int asoc_sdw_cs_spk_feedback_rtd_init(struct snd_soc_pcm_runtime *rtd, + struct snd_soc_dai *dai); +int asoc_sdw_cs35l56_volume_limit(struct snd_soc_card *card, const char *name_prefix); + +/* MAXIM codec support */ +int asoc_sdw_maxim_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); + +/* dai_link init callbacks */ +int asoc_sdw_rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_rt_mf_sdca_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_cs42l45_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_cs42l45_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +/* TI */ +int asoc_sdw_ti_amp_init(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_links, + struct asoc_sdw_codec_info *info, + bool playback); +int asoc_sdw_ti_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai); +int asoc_sdw_ti_amp_initial_settings(struct snd_soc_card *card, + const char *name_prefix); + +#endif diff --git a/include/sound/sof.h b/include/sound/sof.h index d3c41f87ac31..eddea82c7b5a 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation * * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com> */ @@ -52,11 +52,23 @@ enum sof_dsp_power_states { /* Definitions for multiple IPCs */ enum sof_ipc_type { - SOF_IPC, - SOF_INTEL_IPC4, + SOF_IPC_TYPE_3, + SOF_IPC_TYPE_4, SOF_IPC_TYPE_COUNT }; +struct sof_loadable_file_profile { + enum sof_ipc_type ipc_type; + + const char *fw_path; + const char *fw_path_postfix; + const char *fw_name; + const char *fw_lib_path; + const char *fw_lib_path_postfix; + const char *tplg_path; + const char *tplg_name; +}; + /* * SOF Platform data. */ @@ -64,6 +76,14 @@ struct snd_sof_pdata { const char *name; const char *platform; + /* + * PCI SSID. As PCI does not define 0 as invalid, the subsystem_id_set + * flag indicates that a value has been written to these members. + */ + unsigned short subsystem_vendor; + unsigned short subsystem_device; + bool subsystem_id_set; + struct device *dev; /* @@ -78,11 +98,15 @@ struct snd_sof_pdata { /* descriptor */ const struct sof_dev_desc *desc; + /* platform's preferred IPC type and path overrides */ + struct sof_loadable_file_profile ipc_file_profile_base; + /* firmware and topology filenames */ const char *fw_filename_prefix; const char *fw_filename; const char *tplg_filename_prefix; const char *tplg_filename; + bool disable_function_topology; /* loadable external libraries available under this directory */ const char *fw_lib_prefix; @@ -143,12 +167,13 @@ struct sof_dev_desc { /* default firmware name */ const char *default_fw_filename[SOF_IPC_TYPE_COUNT]; - struct snd_sof_dsp_ops *ops; + const struct snd_sof_dsp_ops *ops; int (*ops_init)(struct snd_sof_dev *sdev); void (*ops_free)(struct snd_sof_dev *sdev); }; int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd); int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd); +int sof_dai_get_tdm_slots(struct snd_soc_pcm_runtime *rtd); #endif diff --git a/include/sound/sof/channel_map.h b/include/sound/sof/channel_map.h index d363f0ca6979..2a177a1938e9 100644 --- a/include/sound/sof/channel_map.h +++ b/include/sound/sof/channel_map.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2019 Intel Corporation. All rights reserved. + * Copyright(c) 2019 Intel Corporation */ #ifndef __IPC_CHANNEL_MAP_H__ diff --git a/include/sound/sof/control.h b/include/sound/sof/control.h index 983d374fe511..8d3300dd9d8c 100644 --- a/include/sound/sof/control.h +++ b/include/sound/sof/control.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation */ #ifndef __INCLUDE_SOUND_SOF_CONTROL_H__ diff --git a/include/sound/sof/dai-amd.h b/include/sound/sof/dai-amd.h index 9df7ac824efe..59cd014392c1 100644 --- a/include/sound/sof/dai-amd.h +++ b/include/sound/sof/dai-amd.h @@ -26,4 +26,11 @@ struct sof_ipc_dai_acpdmic_params { uint32_t pdm_ch; } __packed; +/* ACP_SDW Configuration Request - SOF_IPC_DAI_AMD_SDW_CONFIG */ +struct sof_ipc_dai_acp_sdw_params { + struct sof_ipc_hdr hdr; + u32 rate; + u32 channels; +} __packed; + #endif diff --git a/include/sound/sof/dai-imx.h b/include/sound/sof/dai-imx.h index ca8325353d41..6bc987bd4761 100644 --- a/include/sound/sof/dai-imx.h +++ b/include/sound/sof/dai-imx.h @@ -51,4 +51,11 @@ struct sof_ipc_dai_sai_params { uint16_t tdm_slot_width; uint16_t reserved2; /* alignment */ } __packed; + +/* MICFIL Configuration Request - SOF_IPC_DAI_MICFIL_CONFIG */ +struct sof_ipc_dai_micfil_params { + uint32_t pdm_rate; + uint32_t pdm_ch; +} __packed; + #endif diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 5b93b7292f5e..e4e710b43d2d 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation */ #ifndef __INCLUDE_SOUND_SOF_DAI_INTEL_H__ diff --git a/include/sound/sof/dai.h b/include/sound/sof/dai.h index 3041f5805b7b..36809f712723 100644 --- a/include/sound/sof/dai.h +++ b/include/sound/sof/dai.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation */ #ifndef __INCLUDE_SOUND_SOF_DAI_H__ @@ -88,6 +88,8 @@ enum sof_ipc_dai_type { SOF_DAI_AMD_HS, /**< Amd HS */ SOF_DAI_AMD_SP_VIRTUAL, /**< AMD ACP SP VIRTUAL */ SOF_DAI_AMD_HS_VIRTUAL, /**< AMD ACP HS VIRTUAL */ + SOF_DAI_IMX_MICFIL, /** < i.MX MICFIL PDM */ + SOF_DAI_AMD_SDW, /**< AMD ACP SDW */ }; /* general purpose DAI configuration */ @@ -117,6 +119,8 @@ struct sof_ipc_dai_config { struct sof_ipc_dai_acpdmic_params acpdmic; struct sof_ipc_dai_acp_params acphs; struct sof_ipc_dai_mtk_afe_params afe; + struct sof_ipc_dai_micfil_params micfil; + struct sof_ipc_dai_acp_sdw_params acp_sdw; }; } __packed; diff --git a/include/sound/sof/debug.h b/include/sound/sof/debug.h index 38693e3fb514..8b308d7e5eee 100644 --- a/include/sound/sof/debug.h +++ b/include/sound/sof/debug.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2020 Intel Corporation. All rights reserved. + * Copyright(c) 2020 Intel Corporation * * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> */ diff --git a/include/sound/sof/ext_manifest.h b/include/sound/sof/ext_manifest.h index 2a7e055584f9..7dfe3ccf1fe4 100644 --- a/include/sound/sof/ext_manifest.h +++ b/include/sound/sof/ext_manifest.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2020 Intel Corporation. All rights reserved. + * Copyright(c) 2020 Intel Corporation */ /* @@ -60,6 +60,7 @@ enum sof_ext_man_elem_type { SOF_EXT_MAN_ELEM_FW_VERSION = 0, SOF_EXT_MAN_ELEM_WINDOW = 1, SOF_EXT_MAN_ELEM_CC_VERSION = 2, + SOF_EXT_MAN_ELEM_PROBE_INFO = 3, SOF_EXT_MAN_ELEM_DBG_ABI = 4, SOF_EXT_MAN_ELEM_CONFIG_DATA = 5, /**< ABI3.17 */ SOF_EXT_MAN_ELEM_PLATFORM_CONFIG_DATA = 6, diff --git a/include/sound/sof/ext_manifest4.h b/include/sound/sof/ext_manifest4.h index ec97edcbbfc3..4e1d379d96ad 100644 --- a/include/sound/sof/ext_manifest4.h +++ b/include/sound/sof/ext_manifest4.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2022 Intel Corporation. All rights reserved. + * Copyright(c) 2022 Intel Corporation */ /* diff --git a/include/sound/sof/header.h b/include/sound/sof/header.h index b22e925c70e2..4e406dc22f31 100644 --- a/include/sound/sof/header.h +++ b/include/sound/sof/header.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation */ #ifndef __INCLUDE_SOUND_SOF_HEADER_H__ diff --git a/include/sound/sof/info.h b/include/sound/sof/info.h index 75193850ead0..08400fbe5402 100644 --- a/include/sound/sof/info.h +++ b/include/sound/sof/info.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation */ #ifndef __INCLUDE_SOUND_SOF_INFO_H__ diff --git a/include/sound/sof/ipc4/header.h b/include/sound/sof/ipc4/header.h index 78568abe2673..15fac532688e 100644 --- a/include/sound/sof/ipc4/header.h +++ b/include/sound/sof/ipc4/header.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2022 Intel Corporation. All rights reserved. + * Copyright(c) 2022 Intel Corporation */ #ifndef __INCLUDE_SOUND_SOF_IPC4_HEADER_H__ @@ -106,12 +106,19 @@ enum sof_ipc4_global_msg { SOF_IPC4_GLB_SAVE_PIPELINE, SOF_IPC4_GLB_RESTORE_PIPELINE, - /* Loads library (using Code Load or HD/A Host Output DMA) */ + /* + * library loading + * + * Loads library (using Code Load or HD/A Host Output DMA) + */ SOF_IPC4_GLB_LOAD_LIBRARY, + /* + * Prepare the host DMA channel for library loading, must be followed by + * a SOF_IPC4_GLB_LOAD_LIBRARY message as the library loading step + */ + SOF_IPC4_GLB_LOAD_LIBRARY_PREPARE, - /* 25: RESERVED - do not use */ - - SOF_IPC4_GLB_INTERNAL_MESSAGE = 26, + SOF_IPC4_GLB_INTERNAL_MESSAGE, /* Notification (FW to SW driver) */ SOF_IPC4_GLB_NOTIFICATION, @@ -319,10 +326,14 @@ struct sof_ipc4_base_module_cfg { #define SOF_IPC4_MOD_INSTANCE_SHIFT 16 #define SOF_IPC4_MOD_INSTANCE_MASK GENMASK(23, 16) #define SOF_IPC4_MOD_INSTANCE(x) ((x) << SOF_IPC4_MOD_INSTANCE_SHIFT) +#define SOF_IPC4_MOD_INSTANCE_GET(x) (((x) & SOF_IPC4_MOD_INSTANCE_MASK) \ + >> SOF_IPC4_MOD_INSTANCE_SHIFT) #define SOF_IPC4_MOD_ID_SHIFT 0 #define SOF_IPC4_MOD_ID_MASK GENMASK(15, 0) #define SOF_IPC4_MOD_ID(x) ((x) << SOF_IPC4_MOD_ID_SHIFT) +#define SOF_IPC4_MOD_ID_GET(x) (((x) & SOF_IPC4_MOD_ID_MASK) \ + >> SOF_IPC4_MOD_ID_SHIFT) /* init module ipc msg */ #define SOF_IPC4_MOD_EXT_PARAM_SIZE_SHIFT 0 @@ -389,6 +400,7 @@ enum sof_ipc4_base_fw_params { SOF_IPC4_FW_PARAM_MODULES_INFO_GET, SOF_IPC4_FW_PARAM_LIBRARIES_INFO_GET = 16, SOF_IPC4_FW_PARAM_SYSTEM_TIME = 20, + SOF_IPC4_FW_PARAM_MIC_PRIVACY_STATE_CHANGE = 35, }; enum sof_ipc4_fw_config_params { @@ -416,6 +428,12 @@ enum sof_ipc4_fw_config_params { SOF_IPC4_FW_CFG_RESERVED, SOF_IPC4_FW_CFG_POWER_GATING_POLICY, SOF_IPC4_FW_CFG_ASSERT_MODE, + SOF_IPC4_FW_RESERVED1, + SOF_IPC4_FW_RESERVED2, + SOF_IPC4_FW_RESERVED3, + SOF_IPC4_FW_RESERVED4, + SOF_IPC4_FW_RESERVED5, + SOF_IPC4_FW_CONTEXT_SAVE }; struct sof_ipc4_fw_version { @@ -433,6 +451,18 @@ struct sof_ipc4_dx_state_info { uint32_t dx_mask; } __packed __aligned(4); +enum sof_ipc4_hw_config_params { + SOF_IPC4_HW_CFG_INTEL_MIC_PRIVACY_CAPS = 11, +}; + +#define SOF_IPC_INTEL_MIC_PRIVACY_VERSION_PTL 1 + +struct sof_ipc4_intel_mic_privacy_cap { + uint32_t version; + uint32_t capabilities_length; + uint32_t capabilities[]; +} __packed; + /* Reply messages */ /* @@ -472,6 +502,8 @@ struct sof_ipc4_dx_state_info { #define SOF_IPC4_LOG_CORE_GET(x) (((x) & SOF_IPC4_LOG_CORE_MASK) >> \ SOF_IPC4_LOG_CORE_SHIFT) +#define SOF_IPC4_FW_READY_LIB_RESTORED BIT(15) + /* Value of notification type field - must fit into 8 bits */ enum sof_ipc4_notification_type { /* Phrase detected (notification from WoV module) */ @@ -508,6 +540,52 @@ struct sof_ipc4_notify_resource_data { uint32_t data[6]; } __packed __aligned(4); +#define SOF_IPC4_DEBUG_DESCRIPTOR_SIZE 12 /* 3 x u32 */ + +/* + * The debug memory window is divided into 16 slots, and the + * first slot is used as a recorder for the other 15 slots. + */ +#define SOF_IPC4_MAX_DEBUG_SLOTS 15 +#define SOF_IPC4_DEBUG_SLOT_SIZE 0x1000 + +/* debug log slot types */ +#define SOF_IPC4_DEBUG_SLOT_UNUSED 0x00000000 +#define SOF_IPC4_DEBUG_SLOT_CRITICAL_LOG 0x54524300 /* byte 0: core ID */ +#define SOF_IPC4_DEBUG_SLOT_DEBUG_LOG 0x474f4c00 /* byte 0: core ID */ +#define SOF_IPC4_DEBUG_SLOT_GDB_STUB 0x42444700 +#define SOF_IPC4_DEBUG_SLOT_TELEMETRY 0x4c455400 +#define SOF_IPC4_DEBUG_SLOT_BROKEN 0x44414544 + +/** + * struct sof_ipc4_notify_module_data - payload for module notification + * @instance_id: instance ID of the originator module of the notification + * @module_id: module ID of the originator of the notification + * @event_id: module specific event id + * @event_data_size: Size of the @event_data (if any) in bytes + * @event_data: Optional notification data, module and notification dependent + */ +struct sof_ipc4_notify_module_data { + uint16_t instance_id; + uint16_t module_id; + uint32_t event_id; + uint32_t event_data_size; + uint8_t event_data[]; +} __packed __aligned(4); + +/* + * ALSA kcontrol change notification + * + * The event_id of struct sof_ipc4_notify_module_data is divided into two u16: + * upper u16: magic number for ALSA kcontrol types: 0xA15A + * lower u16: param_id of the control, which is the type of the control + * The event_data contains the struct sof_ipc4_control_msg_payload of the control + * which sent the notification. + */ +#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_MASK GENMASK(31, 16) +#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_MAGIC_VAL 0xA15A0000 +#define SOF_IPC4_NOTIFY_MODULE_EVENTID_ALSA_PARAMID_MASK GENMASK(15, 0) + /** @}*/ #endif diff --git a/include/sound/sof/pm.h b/include/sound/sof/pm.h index 366aa6ec442b..df55bfe58304 100644 --- a/include/sound/sof/pm.h +++ b/include/sound/sof/pm.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation */ #ifndef __INCLUDE_SOUND_SOF_PM_H__ diff --git a/include/sound/sof/stream.h b/include/sound/sof/stream.h index 9377113f13e4..1bb25487d120 100644 --- a/include/sound/sof/stream.h +++ b/include/sound/sof/stream.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation */ #ifndef __INCLUDE_SOUND_SOF_STREAM_H__ diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 88560281d420..449e93c25184 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation */ #ifndef __INCLUDE_SOUND_SOF_TOPOLOGY_H__ @@ -26,9 +26,9 @@ enum sof_comp_type { SOF_COMP_MIXER, SOF_COMP_MUX, SOF_COMP_SRC, - SOF_COMP_SPLITTER, + SOF_COMP_DEPRECATED0, /* Formerly SOF_COMP_SPLITTER */ SOF_COMP_TONE, - SOF_COMP_SWITCH, + SOF_COMP_DEPRECATED1, /* Formerly SOF_COMP_SWITCH */ SOF_COMP_BUFFER, SOF_COMP_EQ_IIR, SOF_COMP_EQ_FIR, @@ -39,6 +39,7 @@ enum sof_comp_type { SOF_COMP_ASRC, /**< Asynchronous sample rate converter */ SOF_COMP_DCBLOCK, SOF_COMP_SMART_AMP, /**< smart amplifier component */ + SOF_COMP_MODULE_ADAPTER, /**< module adapter */ /* keep FILEREAD/FILEWRITE as the last ones */ SOF_COMP_FILEREAD = 10000, /**< host test based file IO */ SOF_COMP_FILEWRITE = 10001, /**< host test based file IO */ @@ -53,13 +54,13 @@ enum sof_comp_type { struct sof_ipc_comp { struct sof_ipc_cmd_hdr hdr; uint32_t id; - enum sof_comp_type type; + uint32_t type; uint32_t pipeline_id; uint32_t core; /* extended data length, 0 if no extended data */ uint32_t ext_data_length; -} __packed; +} __packed __aligned(4); /* * Component Buffers @@ -68,14 +69,15 @@ struct sof_ipc_comp { /* * SOF memory capabilities, add new ones at the end */ -#define SOF_MEM_CAPS_RAM (1 << 0) -#define SOF_MEM_CAPS_ROM (1 << 1) -#define SOF_MEM_CAPS_EXT (1 << 2) /**< external */ -#define SOF_MEM_CAPS_LP (1 << 3) /**< low power */ -#define SOF_MEM_CAPS_HP (1 << 4) /**< high performance */ -#define SOF_MEM_CAPS_DMA (1 << 5) /**< DMA'able */ -#define SOF_MEM_CAPS_CACHE (1 << 6) /**< cacheable */ -#define SOF_MEM_CAPS_EXEC (1 << 7) /**< executable */ +#define SOF_MEM_CAPS_RAM BIT(0) +#define SOF_MEM_CAPS_ROM BIT(1) +#define SOF_MEM_CAPS_EXT BIT(2) /**< external */ +#define SOF_MEM_CAPS_LP BIT(3) /**< low power */ +#define SOF_MEM_CAPS_HP BIT(4) /**< high performance */ +#define SOF_MEM_CAPS_DMA BIT(5) /**< DMA'able */ +#define SOF_MEM_CAPS_CACHE BIT(6) /**< cacheable */ +#define SOF_MEM_CAPS_EXEC BIT(7) /**< executable */ +#define SOF_MEM_CAPS_L3 BIT(8) /**< L3 memory */ /* * overrun will cause ring buffer overwrite, instead of XRUN. @@ -87,6 +89,9 @@ struct sof_ipc_comp { */ #define SOF_BUF_UNDERRUN_PERMITTED BIT(1) +/* the UUID size in bytes, shared between FW and host */ +#define SOF_UUID_SIZE 16 + /* create new component buffer - SOF_IPC_TPLG_BUFFER_NEW */ struct sof_ipc_buffer { struct sof_ipc_comp comp; @@ -94,7 +99,7 @@ struct sof_ipc_buffer { uint32_t caps; /**< SOF_MEM_CAPS_ */ uint32_t flags; /**< SOF_BUF_ flags defined above */ uint32_t reserved; /**< reserved for future use */ -} __packed; +} __packed __aligned(4); /* generic component config data - must always be after struct sof_ipc_comp */ struct sof_ipc_comp_config { @@ -107,7 +112,7 @@ struct sof_ipc_comp_config { /* reserved for future use */ uint32_t reserved[2]; -} __packed; +} __packed __aligned(4); /* generic host component */ struct sof_ipc_comp_host { @@ -116,7 +121,7 @@ struct sof_ipc_comp_host { uint32_t direction; /**< SOF_IPC_STREAM_ */ uint32_t no_irq; /**< don't send periodic IRQ to host/DSP */ uint32_t dmac_config; /**< DMA engine specific */ -} __packed; +} __packed __aligned(4); /* generic DAI component */ struct sof_ipc_comp_dai { @@ -126,13 +131,13 @@ struct sof_ipc_comp_dai { uint32_t dai_index; /**< index of this type dai */ uint32_t type; /**< DAI type - SOF_DAI_ */ uint32_t reserved; /**< reserved */ -} __packed; +} __packed __aligned(4); /* generic mixer component */ struct sof_ipc_comp_mixer { struct sof_ipc_comp comp; struct sof_ipc_comp_config config; -} __packed; +} __packed __aligned(4); /* volume ramping types */ enum sof_volume_ramp { @@ -140,6 +145,8 @@ enum sof_volume_ramp { SOF_VOLUME_LOG, SOF_VOLUME_LINEAR_ZC, SOF_VOLUME_LOG_ZC, + SOF_VOLUME_WINDOWS_FADE, + SOF_VOLUME_WINDOWS_NO_FADE, }; /* generic volume component */ @@ -151,7 +158,7 @@ struct sof_ipc_comp_volume { uint32_t max_value; uint32_t ramp; /**< SOF_VOLUME_ */ uint32_t initial_ramp; /**< ramp space in ms */ -} __packed; +} __packed __aligned(4); /* generic SRC component */ struct sof_ipc_comp_src { @@ -161,7 +168,7 @@ struct sof_ipc_comp_src { uint32_t source_rate; /**< source rate or 0 for variable */ uint32_t sink_rate; /**< sink rate or 0 for variable */ uint32_t rate_mask; /**< SOF_RATE_ supported rates */ -} __packed; +} __packed __aligned(4); /* generic ASRC component */ struct sof_ipc_comp_asrc { @@ -187,13 +194,13 @@ struct sof_ipc_comp_asrc { /* reserved for future use */ uint32_t reserved[4]; -} __attribute__((packed)); +} __packed __aligned(4); /* generic MUX component */ struct sof_ipc_comp_mux { struct sof_ipc_comp comp; struct sof_ipc_comp_config config; -} __packed; +} __packed __aligned(4); /* generic tone generator component */ struct sof_ipc_comp_tone { @@ -208,7 +215,7 @@ struct sof_ipc_comp_tone { int32_t period; int32_t repeats; int32_t ramp_step; -} __packed; +} __packed __aligned(4); /** \brief Types of processing components */ enum sof_ipc_process_type { @@ -234,8 +241,8 @@ struct sof_ipc_comp_process { /* reserved for future use */ uint32_t reserved[7]; - uint8_t data[]; -} __packed; + unsigned char data[]; +} __packed __aligned(4); /* frees components, buffers and pipelines * SOF_IPC_TPLG_COMP_FREE, SOF_IPC_TPLG_PIPE_FREE, SOF_IPC_TPLG_BUFFER_FREE @@ -243,13 +250,13 @@ struct sof_ipc_comp_process { struct sof_ipc_free { struct sof_ipc_cmd_hdr hdr; uint32_t id; -} __packed; +} __packed __aligned(4); struct sof_ipc_comp_reply { struct sof_ipc_reply rhdr; uint32_t id; uint32_t offset; -} __packed; +} __packed __aligned(4); /* * Pipeline @@ -274,25 +281,25 @@ struct sof_ipc_pipe_new { uint32_t frames_per_sched;/**< output frames of pipeline, 0 is variable */ uint32_t xrun_limit_usecs; /**< report xruns greater than limit */ uint32_t time_domain; /**< scheduling time domain */ -} __packed; +} __packed __aligned(4); /* pipeline construction complete - SOF_IPC_TPLG_PIPE_COMPLETE */ struct sof_ipc_pipe_ready { struct sof_ipc_cmd_hdr hdr; uint32_t comp_id; -} __packed; +} __packed __aligned(4); struct sof_ipc_pipe_free { struct sof_ipc_cmd_hdr hdr; uint32_t comp_id; -} __packed; +} __packed __aligned(4); /* connect two components in pipeline - SOF_IPC_TPLG_COMP_CONNECT */ struct sof_ipc_pipe_comp_connect { struct sof_ipc_cmd_hdr hdr; uint32_t source_id; uint32_t sink_id; -} __packed; +} __packed __aligned(4); /* external events */ enum sof_event_types { diff --git a/include/sound/sof/trace.h b/include/sound/sof/trace.h index 25ea99f62d37..ac2ebb6fb38f 100644 --- a/include/sound/sof/trace.h +++ b/include/sound/sof/trace.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation */ #ifndef __INCLUDE_SOUND_SOF_TRACE_H__ diff --git a/include/sound/sof/xtensa.h b/include/sound/sof/xtensa.h index 87a07e520415..ef70f8e266a2 100644 --- a/include/sound/sof/xtensa.h +++ b/include/sound/sof/xtensa.h @@ -3,7 +3,7 @@ * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. * - * Copyright(c) 2018 Intel Corporation. All rights reserved. + * Copyright(c) 2018 Intel Corporation */ #ifndef __INCLUDE_SOUND_SOF_XTENSA_H__ diff --git a/include/sound/soundfont.h b/include/sound/soundfont.h index e445688a4f4f..48f8cf6de3ac 100644 --- a/include/sound/soundfont.h +++ b/include/sound/soundfont.h @@ -86,10 +86,12 @@ struct snd_sf_list { }; /* Prototypes for soundfont.c */ -int snd_soundfont_load(struct snd_sf_list *sflist, const void __user *data, +int snd_soundfont_load(struct snd_card *card, + struct snd_sf_list *sflist, const void __user *data, long count, int client); -int snd_soundfont_load_guspatch(struct snd_sf_list *sflist, const char __user *data, - long count, int client); +int snd_soundfont_load_guspatch(struct snd_card *card, + struct snd_sf_list *sflist, const char __user *data, + long count); int snd_soundfont_close_check(struct snd_sf_list *sflist, int client); struct snd_sf_list *snd_sf_new(struct snd_sf_callback *callback, @@ -112,5 +114,23 @@ int snd_sf_calc_parm_decay(int msec); extern int snd_sf_vol_table[128]; int snd_sf_linear_to_log(unsigned int amount, int offset, int ratio); +/* lock access to sflist */ +static inline void snd_soundfont_lock_preset(struct snd_sf_list *sflist) +{ + mutex_lock(&sflist->presets_mutex); + guard(spinlock_irqsave)(&sflist->lock); + sflist->presets_locked = 1; +} + +/* remove lock */ +static inline void snd_soundfont_unlock_preset(struct snd_sf_list *sflist) +{ + guard(spinlock_irqsave)(&sflist->lock); + sflist->presets_locked = 0; + mutex_unlock(&sflist->presets_mutex); +} + +DEFINE_GUARD(snd_soundfont_lock_preset, struct snd_sf_list *, + snd_soundfont_lock_preset(_T), snd_soundfont_unlock_preset(_T)) #endif /* __SOUND_SOUNDFONT_H */ diff --git a/include/sound/tas2563-tlv.h b/include/sound/tas2563-tlv.h new file mode 100644 index 000000000000..bb269b21f460 --- /dev/null +++ b/include/sound/tas2563-tlv.h @@ -0,0 +1,279 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// +// ALSA SoC Texas Instruments TAS2563 Audio Smart Amplifier +// +// Copyright (C) 2022 - 2024 Texas Instruments Incorporated +// https://www.ti.com +// +// The TAS2563 driver implements a flexible and configurable +// algo coefficient setting for one, two, or even multiple +// TAS2563 chips. +// +// Author: Shenghao Ding <shenghao-ding@ti.com> +// + +#ifndef __TAS2563_TLV_H__ +#define __TAS2563_TLV_H__ + +static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2563_dvc_tlv, -12150, 50, 1); + +/* pow(10, db/20) * pow(2,30) */ +static const __maybe_unused unsigned char tas2563_dvc_table[][4] = { + { 0X00, 0X00, 0X00, 0X00 }, /* -121.5db */ + { 0X00, 0X00, 0X03, 0XBC }, /* -121.0db */ + { 0X00, 0X00, 0X03, 0XF5 }, /* -120.5db */ + { 0X00, 0X00, 0X04, 0X31 }, /* -120.0db */ + { 0X00, 0X00, 0X04, 0X71 }, /* -119.5db */ + { 0X00, 0X00, 0X04, 0XB4 }, /* -119.0db */ + { 0X00, 0X00, 0X04, 0XFC }, /* -118.5db */ + { 0X00, 0X00, 0X05, 0X47 }, /* -118.0db */ + { 0X00, 0X00, 0X05, 0X97 }, /* -117.5db */ + { 0X00, 0X00, 0X05, 0XEC }, /* -117.0db */ + { 0X00, 0X00, 0X06, 0X46 }, /* -116.5db */ + { 0X00, 0X00, 0X06, 0XA5 }, /* -116.0db */ + { 0X00, 0X00, 0X07, 0X0A }, /* -115.5db */ + { 0X00, 0X00, 0X07, 0X75 }, /* -115.0db */ + { 0X00, 0X00, 0X07, 0XE6 }, /* -114.5db */ + { 0X00, 0X00, 0X08, 0X5E }, /* -114.0db */ + { 0X00, 0X00, 0X08, 0XDD }, /* -113.5db */ + { 0X00, 0X00, 0X09, 0X63 }, /* -113.0db */ + { 0X00, 0X00, 0X09, 0XF2 }, /* -112.5db */ + { 0X00, 0X00, 0X0A, 0X89 }, /* -112.0db */ + { 0X00, 0X00, 0X0B, 0X28 }, /* -111.5db */ + { 0X00, 0X00, 0X0B, 0XD2 }, /* -111.0db */ + { 0X00, 0X00, 0X0C, 0X85 }, /* -110.5db */ + { 0X00, 0X00, 0X0D, 0X43 }, /* -110.0db */ + { 0X00, 0X00, 0X0E, 0X0C }, /* -109.5db */ + { 0X00, 0X00, 0X0E, 0XE1 }, /* -109.0db */ + { 0X00, 0X00, 0X0F, 0XC3 }, /* -108.5db */ + { 0X00, 0X00, 0X10, 0XB2 }, /* -108.0db */ + { 0X00, 0X00, 0X11, 0XAF }, /* -107.5db */ + { 0X00, 0X00, 0X12, 0XBC }, /* -107.0db */ + { 0X00, 0X00, 0X13, 0XD8 }, /* -106.5db */ + { 0X00, 0X00, 0X15, 0X05 }, /* -106.0db */ + { 0X00, 0X00, 0X16, 0X44 }, /* -105.5db */ + { 0X00, 0X00, 0X17, 0X96 }, /* -105.0db */ + { 0X00, 0X00, 0X18, 0XFB }, /* -104.5db */ + { 0X00, 0X00, 0X1A, 0X76 }, /* -104.0db */ + { 0X00, 0X00, 0X1C, 0X08 }, /* -103.5db */ + { 0X00, 0X00, 0X1D, 0XB1 }, /* -103.0db */ + { 0X00, 0X00, 0X1F, 0X73 }, /* -102.5db */ + { 0X00, 0X00, 0X21, 0X51 }, /* -102.0db */ + { 0X00, 0X00, 0X23, 0X4A }, /* -101.5db */ + { 0X00, 0X00, 0X25, 0X61 }, /* -101.0db */ + { 0X00, 0X00, 0X27, 0X98 }, /* -100.5db */ + { 0X00, 0X00, 0X29, 0XF1 }, /* -100.0db */ + { 0X00, 0X00, 0X2C, 0X6D }, /* -99.5db */ + { 0X00, 0X00, 0X2F, 0X0F }, /* -99.0db */ + { 0X00, 0X00, 0X31, 0XD9 }, /* -98.5db */ + { 0X00, 0X00, 0X34, 0XCD }, /* -98.0db */ + { 0X00, 0X00, 0X37, 0XEE }, /* -97.5db */ + { 0X00, 0X00, 0X3B, 0X3F }, /* -97.0db */ + { 0X00, 0X00, 0X3E, 0XC1 }, /* -96.5db */ + { 0X00, 0X00, 0X42, 0X79 }, /* -96.0db */ + { 0X00, 0X00, 0X46, 0X6A }, /* -95.5db */ + { 0X00, 0X00, 0X4A, 0X96 }, /* -95.0db */ + { 0X00, 0X00, 0X4F, 0X01 }, /* -94.5db */ + { 0X00, 0X00, 0X53, 0XAF }, /* -94.0db */ + { 0X00, 0X00, 0X58, 0XA5 }, /* -93.5db */ + { 0X00, 0X00, 0X5D, 0XE6 }, /* -93.0db */ + { 0X00, 0X00, 0X63, 0X76 }, /* -92.5db */ + { 0X00, 0X00, 0X69, 0X5B }, /* -92.0db */ + { 0X00, 0X00, 0X6F, 0X99 }, /* -91.5db */ + { 0X00, 0X00, 0X76, 0X36 }, /* -91.0db */ + { 0X00, 0X00, 0X7D, 0X37 }, /* -90.5db */ + { 0X00, 0X00, 0X84, 0XA2 }, /* -90.0db */ + { 0X00, 0X00, 0X8C, 0X7E }, /* -89.5db */ + { 0X00, 0X00, 0X94, 0XD1 }, /* -89.0db */ + { 0X00, 0X00, 0X9D, 0XA3 }, /* -88.5db */ + { 0X00, 0X00, 0XA6, 0XFA }, /* -88.0db */ + { 0X00, 0X00, 0XB0, 0XDF }, /* -87.5db */ + { 0X00, 0X00, 0XBB, 0X5A }, /* -87.0db */ + { 0X00, 0X00, 0XC6, 0X74 }, /* -86.5db */ + { 0X00, 0X00, 0XD2, 0X36 }, /* -86.0db */ + { 0X00, 0X00, 0XDE, 0XAB }, /* -85.5db */ + { 0X00, 0X00, 0XEB, 0XDC }, /* -85.0db */ + { 0X00, 0X00, 0XF9, 0XD6 }, /* -84.5db */ + { 0X00, 0X01, 0X08, 0XA4 }, /* -84.0db */ + { 0X00, 0X01, 0X18, 0X52 }, /* -83.5db */ + { 0X00, 0X01, 0X28, 0XEF }, /* -83.0db */ + { 0X00, 0X01, 0X3A, 0X87 }, /* -82.5db */ + { 0X00, 0X01, 0X4D, 0X2A }, /* -82.0db */ + { 0X00, 0X01, 0X60, 0XE8 }, /* -81.5db */ + { 0X00, 0X01, 0X75, 0XD1 }, /* -81.0db */ + { 0X00, 0X01, 0X8B, 0XF7 }, /* -80.5db */ + { 0X00, 0X01, 0XA3, 0X6E }, /* -80.0db */ + { 0X00, 0X01, 0XBC, 0X48 }, /* -79.5db */ + { 0X00, 0X01, 0XD6, 0X9B }, /* -79.0db */ + { 0X00, 0X01, 0XF2, 0X7E }, /* -78.5db */ + { 0X00, 0X02, 0X10, 0X08 }, /* -78.0db */ + { 0X00, 0X02, 0X2F, 0X51 }, /* -77.5db */ + { 0X00, 0X02, 0X50, 0X76 }, /* -77.0db */ + { 0X00, 0X02, 0X73, 0X91 }, /* -76.5db */ + { 0X00, 0X02, 0X98, 0XC0 }, /* -76.0db */ + { 0X00, 0X02, 0XC0, 0X24 }, /* -75.5db */ + { 0X00, 0X02, 0XE9, 0XDD }, /* -75.0db */ + { 0X00, 0X03, 0X16, 0X0F }, /* -74.5db */ + { 0X00, 0X03, 0X44, 0XDF }, /* -74.0db */ + { 0X00, 0X03, 0X76, 0X76 }, /* -73.5db */ + { 0X00, 0X03, 0XAA, 0XFC }, /* -73.0db */ + { 0X00, 0X03, 0XE2, 0XA0 }, /* -72.5db */ + { 0X00, 0X04, 0X1D, 0X8F }, /* -72.0db */ + { 0X00, 0X04, 0X5B, 0XFD }, /* -71.5db */ + { 0X00, 0X04, 0X9E, 0X1D }, /* -71.0db */ + { 0X00, 0X04, 0XE4, 0X29 }, /* -70.5db */ + { 0X00, 0X05, 0X2E, 0X5A }, /* -70.0db */ + { 0X00, 0X05, 0X7C, 0XF2 }, /* -69.5db */ + { 0X00, 0X05, 0XD0, 0X31 }, /* -69.0db */ + { 0X00, 0X06, 0X28, 0X60 }, /* -68.5db */ + { 0X00, 0X06, 0X85, 0XC8 }, /* -68.0db */ + { 0X00, 0X06, 0XE8, 0XB9 }, /* -67.5db */ + { 0X00, 0X07, 0X51, 0X86 }, /* -67.0db */ + { 0X00, 0X07, 0XC0, 0X8A }, /* -66.5db */ + { 0X00, 0X08, 0X36, 0X21 }, /* -66.0db */ + { 0X00, 0X08, 0XB2, 0XB0 }, /* -65.5db */ + { 0X00, 0X09, 0X36, 0XA1 }, /* -65.0db */ + { 0X00, 0X09, 0XC2, 0X63 }, /* -64.5db */ + { 0X00, 0X0A, 0X56, 0X6D }, /* -64.0db */ + { 0X00, 0X0A, 0XF3, 0X3C }, /* -63.5db */ + { 0X00, 0X0B, 0X99, 0X56 }, /* -63.0db */ + { 0X00, 0X0C, 0X49, 0X48 }, /* -62.5db */ + { 0X00, 0X0D, 0X03, 0XA7 }, /* -62.0db */ + { 0X00, 0X0D, 0XC9, 0X11 }, /* -61.5db */ + { 0X00, 0X0E, 0X9A, 0X2D }, /* -61.0db */ + { 0X00, 0X0F, 0X77, 0XAD }, /* -60.5db */ + { 0X00, 0X10, 0X62, 0X4D }, /* -60.0db */ + { 0X00, 0X11, 0X5A, 0XD5 }, /* -59.5db */ + { 0X00, 0X12, 0X62, 0X16 }, /* -59.0db */ + { 0X00, 0X13, 0X78, 0XF0 }, /* -58.5db */ + { 0X00, 0X14, 0XA0, 0X50 }, /* -58.0db */ + { 0X00, 0X15, 0XD9, 0X31 }, /* -57.5db */ + { 0X00, 0X17, 0X24, 0X9C }, /* -57.0db */ + { 0X00, 0X18, 0X83, 0XAA }, /* -56.5db */ + { 0X00, 0X19, 0XF7, 0X86 }, /* -56.0db */ + { 0X00, 0X1B, 0X81, 0X6A }, /* -55.5db */ + { 0X00, 0X1D, 0X22, 0XA4 }, /* -55.0db */ + { 0X00, 0X1E, 0XDC, 0X98 }, /* -54.5db */ + { 0X00, 0X20, 0XB0, 0XBC }, /* -54.0db */ + { 0X00, 0X22, 0XA0, 0X9D }, /* -53.5db */ + { 0X00, 0X24, 0XAD, 0XE0 }, /* -53.0db */ + { 0X00, 0X26, 0XDA, 0X43 }, /* -52.5db */ + { 0X00, 0X29, 0X27, 0X9D }, /* -52.0db */ + { 0X00, 0X2B, 0X97, 0XE3 }, /* -51.5db */ + { 0X00, 0X2E, 0X2D, 0X27 }, /* -51.0db */ + { 0X00, 0X30, 0XE9, 0X9A }, /* -50.5db */ + { 0X00, 0X33, 0XCF, 0X8D }, /* -50.0db */ + { 0X00, 0X36, 0XE1, 0X78 }, /* -49.5db */ + { 0X00, 0X3A, 0X21, 0XF3 }, /* -49.0db */ + { 0X00, 0X3D, 0X93, 0XC3 }, /* -48.5db */ + { 0X00, 0X41, 0X39, 0XD3 }, /* -48.0db */ + { 0X00, 0X45, 0X17, 0X3B }, /* -47.5db */ + { 0X00, 0X49, 0X2F, 0X44 }, /* -47.0db */ + { 0X00, 0X4D, 0X85, 0X66 }, /* -46.5db */ + { 0X00, 0X52, 0X1D, 0X50 }, /* -46.0db */ + { 0X00, 0X56, 0XFA, 0XE8 }, /* -45.5db */ + { 0X00, 0X5C, 0X22, 0X4E }, /* -45.0db */ + { 0X00, 0X61, 0X97, 0XE1 }, /* -44.5db */ + { 0X00, 0X67, 0X60, 0X44 }, /* -44.0db */ + { 0X00, 0X6D, 0X80, 0X60 }, /* -43.5db */ + { 0X00, 0X73, 0XFD, 0X65 }, /* -43.0db */ + { 0X00, 0X7A, 0XDC, 0XD7 }, /* -42.5db */ + { 0X00, 0X82, 0X24, 0X8A }, /* -42.0db */ + { 0X00, 0X89, 0XDA, 0XAB }, /* -41.5db */ + { 0X00, 0X92, 0X05, 0XC6 }, /* -41.0db */ + { 0X00, 0X9A, 0XAC, 0XC8 }, /* -40.5db */ + { 0X00, 0XA3, 0XD7, 0X0A }, /* -40.0db */ + { 0X00, 0XAD, 0X8C, 0X52 }, /* -39.5db */ + { 0X00, 0XB7, 0XD4, 0XDD }, /* -39.0db */ + { 0X00, 0XC2, 0XB9, 0X65 }, /* -38.5db */ + { 0X00, 0XCE, 0X43, 0X28 }, /* -38.0db */ + { 0X00, 0XDA, 0X7B, 0XF1 }, /* -37.5db */ + { 0X00, 0XE7, 0X6E, 0X1E }, /* -37.0db */ + { 0X00, 0XF5, 0X24, 0XAC }, /* -36.5db */ + { 0X01, 0X03, 0XAB, 0X3D }, /* -36.0db */ + { 0X01, 0X13, 0X0E, 0X24 }, /* -35.5db */ + { 0X01, 0X23, 0X5A, 0X71 }, /* -35.0db */ + { 0X01, 0X34, 0X9D, 0XF8 }, /* -34.5db */ + { 0X01, 0X46, 0XE7, 0X5D }, /* -34.0db */ + { 0X01, 0X5A, 0X46, 0X27 }, /* -33.5db */ + { 0X01, 0X6E, 0XCA, 0XC5 }, /* -33.0db */ + { 0X01, 0X84, 0X86, 0X9F }, /* -32.5db */ + { 0X01, 0X9B, 0X8C, 0X27 }, /* -32.0db */ + { 0X01, 0XB3, 0XEE, 0XE5 }, /* -31.5db */ + { 0X01, 0XCD, 0XC3, 0X8C }, /* -31.0db */ + { 0X01, 0XE9, 0X20, 0X05 }, /* -30.5db */ + { 0X02, 0X06, 0X1B, 0X89 }, /* -30.0db */ + { 0X02, 0X24, 0XCE, 0XB0 }, /* -29.5db */ + { 0X02, 0X45, 0X53, 0X85 }, /* -29.0db */ + { 0X02, 0X67, 0XC5, 0XA2 }, /* -28.5db */ + { 0X02, 0X8C, 0X42, 0X3F }, /* -28.0db */ + { 0X02, 0XB2, 0XE8, 0X55 }, /* -27.5db */ + { 0X02, 0XDB, 0XD8, 0XAD }, /* -27.0db */ + { 0X03, 0X07, 0X36, 0X05 }, /* -26.5db */ + { 0X03, 0X35, 0X25, 0X29 }, /* -26.0db */ + { 0X03, 0X65, 0XCD, 0X13 }, /* -25.5db */ + { 0X03, 0X99, 0X57, 0X0C }, /* -25.0db */ + { 0X03, 0XCF, 0XEE, 0XCF }, /* -24.5db */ + { 0X04, 0X09, 0XC2, 0XB0 }, /* -24.0db */ + { 0X04, 0X47, 0X03, 0XC1 }, /* -23.5db */ + { 0X04, 0X87, 0XE5, 0XFB }, /* -23.0db */ + { 0X04, 0XCC, 0XA0, 0X6D }, /* -22.5db */ + { 0X05, 0X15, 0X6D, 0X68 }, /* -22.0db */ + { 0X05, 0X62, 0X8A, 0XB3 }, /* -21.5db */ + { 0X05, 0XB4, 0X39, 0XBC }, /* -21.0db */ + { 0X06, 0X0A, 0XBF, 0XD4 }, /* -20.5db */ + { 0X06, 0X66, 0X66, 0X66 }, /* -20.0db */ + { 0X06, 0XC7, 0X7B, 0X36 }, /* -19.5db */ + { 0X07, 0X2E, 0X50, 0XA6 }, /* -19.0db */ + { 0X07, 0X9B, 0X3D, 0XF6 }, /* -18.5db */ + { 0X08, 0X0E, 0X9F, 0X96 }, /* -18.0db */ + { 0X08, 0X88, 0XD7, 0X6D }, /* -17.5db */ + { 0X09, 0X0A, 0X4D, 0X2F }, /* -17.0db */ + { 0X09, 0X93, 0X6E, 0XB8 }, /* -16.5db */ + { 0X0A, 0X24, 0XB0, 0X62 }, /* -16.0db */ + { 0X0A, 0XBE, 0X8D, 0X70 }, /* -15.5db */ + { 0X0B, 0X61, 0X88, 0X71 }, /* -15.0db */ + { 0X0C, 0X0E, 0X2B, 0XB0 }, /* -14.5db */ + { 0X0C, 0XC5, 0X09, 0XAB }, /* -14.0db */ + { 0X0D, 0X86, 0XBD, 0X8D }, /* -13.5db */ + { 0X0E, 0X53, 0XEB, 0XB3 }, /* -13.0db */ + { 0X0F, 0X2D, 0X42, 0X38 }, /* -12.5db */ + { 0X10, 0X13, 0X79, 0X87 }, /* -12.0db */ + { 0X11, 0X07, 0X54, 0XF9 }, /* -11.5db */ + { 0X12, 0X09, 0XA3, 0X7A }, /* -11.0db */ + { 0X13, 0X1B, 0X40, 0X39 }, /* -10.5db */ + { 0X14, 0X3D, 0X13, 0X62 }, /* -10.0db */ + { 0X15, 0X70, 0X12, 0XE1 }, /* -9.5db */ + { 0X16, 0XB5, 0X43, 0X37 }, /* -9.0db */ + { 0X18, 0X0D, 0XB8, 0X54 }, /* -8.5db */ + { 0X19, 0X7A, 0X96, 0X7F }, /* -8.0db */ + { 0X1A, 0XFD, 0X13, 0X54 }, /* -7.5db */ + { 0X1C, 0X96, 0X76, 0XC6 }, /* -7.0db */ + { 0X1E, 0X48, 0X1C, 0X37 }, /* -6.5db */ + { 0X20, 0X13, 0X73, 0X9E }, /* -6.0db */ + { 0X21, 0XFA, 0X02, 0XBF }, /* -5.5db */ + { 0X23, 0XFD, 0X66, 0X78 }, /* -5.0db */ + { 0X26, 0X1F, 0X54, 0X1C }, /* -4.5db */ + { 0X28, 0X61, 0X9A, 0XE9 }, /* -4.0db */ + { 0X2A, 0XC6, 0X25, 0X91 }, /* -3.5db */ + { 0X2D, 0X4E, 0XFB, 0XD5 }, /* -3.0db */ + { 0X2F, 0XFE, 0X44, 0X48 }, /* -2.5db */ + { 0X32, 0XD6, 0X46, 0X17 }, /* -2.0db */ + { 0X35, 0XD9, 0X6B, 0X02 }, /* -1.5db */ + { 0X39, 0X0A, 0X41, 0X5F }, /* -1.0db */ + { 0X3C, 0X6B, 0X7E, 0X4F }, /* -0.5db */ + { 0X40, 0X00, 0X00, 0X00 }, /* 0.0db */ + { 0X43, 0XCA, 0XD0, 0X22 }, /* 0.5db */ + { 0X47, 0XCF, 0X26, 0X7D }, /* 1.0db */ + { 0X4C, 0X10, 0X6B, 0XA5 }, /* 1.5db */ + { 0X50, 0X92, 0X3B, 0XE3 }, /* 2.0db */ + { 0X55, 0X58, 0X6A, 0X46 }, /* 2.5db */ + { 0X5A, 0X67, 0X03, 0XDF }, /* 3.0db */ + { 0X5F, 0XC2, 0X53, 0X32 }, /* 3.5db */ + { 0X65, 0X6E, 0XE3, 0XDB }, /* 4.0db */ + { 0X6B, 0X71, 0X86, 0X68 }, /* 4.5db */ + { 0X71, 0XCF, 0X54, 0X71 }, /* 5.0db */ + { 0X78, 0X8D, 0XB4, 0XE9 }, /* 5.5db */ + { 0X7F, 0XFF, 0XFF, 0XFF }, /* 6.0db */ +}; +#endif diff --git a/include/sound/tas2770-tlv.h b/include/sound/tas2770-tlv.h new file mode 100644 index 000000000000..c7380925417a --- /dev/null +++ b/include/sound/tas2770-tlv.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// +// ALSA SoC Texas Instruments TAS2770 Audio Smart Amplifier +// +// Copyright (C) 2025 Texas Instruments Incorporated +// https://www.ti.com +// +// The TAS2770 hda driver implements for one, two, or even multiple +// TAS2770 chips. +// +// Author: Baojun Xu <baojun.xu@ti.com> +// + +#ifndef __TAS2770_TLV_H__ +#define __TAS2770_TLV_H__ + +#define TAS2770_DVC_LEVEL TASDEVICE_REG(0x0, 0x0, 0x05) +#define TAS2770_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x03) + +static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2770_dvc_tlv, -10000, 50, 0); +static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2770_amp_tlv, 1100, 50, 0); + +#endif 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-dsp.h b/include/sound/tas2781-dsp.h index bd1b72bf47a5..dd6ee45ad096 100644 --- a/include/sound/tas2781-dsp.h +++ b/include/sound/tas2781-dsp.h @@ -2,7 +2,7 @@ // // ALSA SoC Texas Instruments TAS2781 Audio Smart Amplifier // -// Copyright (C) 2022 - 2023 Texas Instruments Incorporated +// Copyright (C) 2022 - 2025 Texas Instruments Incorporated // https://www.ti.com // // The TAS2781 driver implements a flexible and configurable @@ -13,8 +13,8 @@ // Author: Kevin Lu <kevin-lu@ti.com> // -#ifndef __TASDEVICE_DSP_H__ -#define __TASDEVICE_DSP_H__ +#ifndef __TAS2781_DSP_H__ +#define __TAS2781_DSP_H__ #define MAIN_ALL_DEVICES 0x0d #define MAIN_DEVICE_A 0x01 @@ -30,8 +30,11 @@ #define PRE_DEVICE_C 0x12 #define PRE_DEVICE_D 0x16 -#define PPC3_VERSION 0x4100 -#define PPC3_VERSION_TAS2781 0x14600 +#define PPC3_VERSION_BASE 0x4100 +#define PPC3_VERSION_TAS2781_BASIC_MIN 0x14600 +#define PPC3_VERSION_TAS2781_ALPHA_MIN 0x4a00 +#define PPC3_VERSION_TAS2781_BETA_MIN 0x19400 +#define PPC3_VERSION_TAS5825_BASE 0x114200 #define TASDEVICE_DEVICE_SUM 8 #define TASDEVICE_CONFIG_SUM 64 @@ -51,6 +54,8 @@ enum tasdevice_dsp_dev_idx { TASDEVICE_DSP_TAS_2781_DUAL_MONO, TASDEVICE_DSP_TAS_2781_21, TASDEVICE_DSP_TAS_2781_QUAD, + TASDEVICE_DSP_TAS_5825_MONO, + TASDEVICE_DSP_TAS_5825_DUAL, TASDEVICE_DSP_TAS_MAX_DEVICE }; @@ -77,6 +82,11 @@ struct tasdev_blk { unsigned int nr_cmds; unsigned int blk_size; unsigned int nr_subblocks; + /* fixed m68k compiling issue, storing the dev_idx as a member of block + * can reduce unnecessary timeand system resource comsumption of + * dev_idx mapping every time the block data writing to the dsp. + */ + unsigned char dev_idx; unsigned char *data; }; @@ -101,6 +111,27 @@ struct tasdevice_calibration { struct tasdevice_data dev_data; }; +struct fct_param_address { + /* Thermal data for PG 1.0 device */ + unsigned char thr[3]; + /* Thermal data for PG 2.0 device */ + unsigned char thr2[3]; + /* Pilot tone enable flag, usually the sine wave */ + unsigned char plt_flg[3]; + /* Pilot tone gain for calibration */ + unsigned char sin_gn[3]; + /* Pilot tone gain for calibration */ + unsigned char sin_gn2[3]; + /* high 32-bit of real-time spk impedance */ + unsigned char r0_reg[3]; + /* check spk connection */ + unsigned char tf_reg[3]; + /* check spk resonant frequency */ + unsigned char a1_reg[3]; + /* check spk resonant frequency */ + unsigned char a2_reg[3]; +}; + struct tasdevice_fw { struct tasdevice_dspfw_hdr fw_hdr; unsigned short nr_programs; @@ -109,13 +140,21 @@ struct tasdevice_fw { struct tasdevice_config *configs; unsigned short nr_calibrations; struct tasdevice_calibration *calibrations; + struct fct_param_address fct_par_addr; struct device *dev; }; -enum tasdevice_dsp_fw_state { - TASDEVICE_DSP_FW_NONE = 0, +enum tasdevice_fw_state { + /* Driver in startup mode, not load any firmware. */ TASDEVICE_DSP_FW_PENDING, + /* DSP firmware in the system, but parsing error. */ TASDEVICE_DSP_FW_FAIL, + /* + * Only RCA (Reconfigurable Architecture) firmware load + * successfully. + */ + TASDEVICE_RCA_FW_OK, + /* Both RCA and DSP firmware load successfully. */ TASDEVICE_DSP_FW_ALL_OK, }; @@ -162,6 +201,14 @@ struct tasdevice_rca { int ncfgs; struct tasdevice_config_info **cfg_info; int profile_cfg_id; + /* + * Since version 0x105, the keyword 'init' was introduced into the + * profile, which is used for chip initialization, particularly to + * store common settings for other non-initialization profiles. + * if (init_profile_id < 0) + * No init profile inside the RCA firmware. + */ + int init_profile_id; }; void tasdevice_select_cfg_blk(void *context, int conf_no, @@ -175,7 +222,6 @@ void tasdevice_calbin_remove(void *context); int tasdevice_select_tuningprm_cfg(void *context, int prm, int cfg_no, int rca_conf_no); int tasdevice_prmg_load(void *context, int prm_no); -int tasdevice_prmg_calibdata_load(void *context, int prm_no); void tasdevice_tuning_switch(void *context, int state); int tas2781_load_calibration(void *context, char *file_name, unsigned short i); diff --git a/include/sound/tas2781-tlv.h b/include/sound/tas2781-tlv.h index 4038dd421150..273224df9282 100644 --- a/include/sound/tas2781-tlv.h +++ b/include/sound/tas2781-tlv.h @@ -2,7 +2,7 @@ // // ALSA SoC Texas Instruments TAS2781 Audio Smart Amplifier // -// Copyright (C) 2022 - 2023 Texas Instruments Incorporated +// Copyright (C) 2022 - 2025 Texas Instruments Incorporated // https://www.ti.com // // The TAS2781 driver implements a flexible and configurable @@ -15,7 +15,7 @@ #ifndef __TAS2781_TLV_H__ #define __TAS2781_TLV_H__ -static const DECLARE_TLV_DB_SCALE(dvc_tlv, -10000, 100, 0); -static const DECLARE_TLV_DB_SCALE(amp_vol_tlv, 1100, 50, 0); +static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2781_dvc_tlv, -10000, 50, 0); +static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2781_amp_tlv, 1100, 50, 0); #endif diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h index a6c808b22318..9d3c54cb8223 100644 --- a/include/sound/tas2781.h +++ b/include/sound/tas2781.h @@ -1,27 +1,33 @@ /* SPDX-License-Identifier: GPL-2.0 */ // -// ALSA SoC Texas Instruments TAS2781 Audio Smart Amplifier +// ALSA SoC Texas Instruments TAS2563/TAS2781 Audio Smart Amplifier // -// Copyright (C) 2022 - 2023 Texas Instruments Incorporated +// Copyright (C) 2022 - 2025 Texas Instruments Incorporated // https://www.ti.com // -// The TAS2781 driver implements a flexible and configurable +// The TAS2563/TAS2781 driver implements a flexible and configurable // algo coefficient setting for one, two, or even multiple -// TAS2781 chips. +// TAS2563/TAS2781 chips. // // Author: Shenghao Ding <shenghao-ding@ti.com> // Author: Kevin Lu <kevin-lu@ti.com> +// Author: Baojun Xu <baojun.xu@ti.com> // #ifndef __TAS2781_H__ #define __TAS2781_H__ +#ifdef CONFIG_SND_SOC_TAS2781_ACOUST_I2C +#include <linux/debugfs.h> +#endif + #include "tas2781-dsp.h" /* version number */ #define TAS2781_DRV_VER 1 #define SMARTAMP_MODULE_NAME "tas2781" #define TAS2781_GLOBAL_ADDR 0x40 +#define TAS2563_GLOBAL_ADDR 0x48 #define TASDEVICE_RATES (SNDRV_PCM_RATE_44100 |\ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |\ SNDRV_PCM_RATE_88200) @@ -30,7 +36,9 @@ SNDRV_PCM_FMTBIT_S24_LE | \ SNDRV_PCM_FMTBIT_S32_LE) -/*PAGE Control Register (available in page0 of each book) */ +#define TASDEVICE_CRC8_POLYNOMIAL 0x4d + +/* PAGE Control Register (available in page0 of each book) */ #define TASDEVICE_PAGE_SELECT 0x00 #define TASDEVICE_BOOKCTL_PAGE 0x00 #define TASDEVICE_BOOKCTL_REG 127 @@ -41,33 +49,107 @@ #define TASDEVICE_REG(book, page, reg) (((book * 256 * 128) + \ (page * 128)) + reg) -/*Software Reset */ -#define TAS2781_REG_SWRESET TASDEVICE_REG(0x0, 0X0, 0x01) -#define TAS2781_REG_SWRESET_RESET BIT(0) +/* Software Reset, compatble with new device (TAS5825). */ +#define TASDEVICE_REG_SWRESET TASDEVICE_REG(0x0, 0x0, 0x01) +#define TASDEVICE_REG_SWRESET_RESET BIT(0) + +#define TAS5825_REG_SWRESET_RESET (BIT(0) | BIT(4)) + +/* Checksum */ +#define TASDEVICE_CHECKSUM_REG TASDEVICE_REG(0x0, 0x0, 0x7e) -/*I2C Checksum */ -#define TASDEVICE_I2CChecksum TASDEVICE_REG(0x0, 0x0, 0x7E) +/* XM_340 */ +#define TASDEVICE_XM_A1_REG TASDEVICE_REG(0x64, 0x63, 0x3c) +/* XM_341 */ +#define TASDEVICE_XM_A2_REG TASDEVICE_REG(0x64, 0x63, 0x38) /* Volume control */ -#define TAS2781_DVC_LVL TASDEVICE_REG(0x0, 0x0, 0x1A) +#define TAS2563_DVC_LVL TASDEVICE_REG(0x00, 0x02, 0x0c) +#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 TAS2563_IDLE TASDEVICE_REG(0x00, 0x00, 0x3e) +#define TAS2563_PRM_R0_REG TASDEVICE_REG(0x00, 0x0f, 0x34) + +#define TAS2563_RUNTIME_RE_REG_TF TASDEVICE_REG(0x64, 0x02, 0x70) +#define TAS2563_RUNTIME_RE_REG TASDEVICE_REG(0x64, 0x02, 0x48) + +#define TAS2563_PRM_ENFF_REG TASDEVICE_REG(0x00, 0x0d, 0x54) +#define TAS2563_PRM_DISTCK_REG TASDEVICE_REG(0x00, 0x0d, 0x58) +#define TAS2563_PRM_TE_SCTHR_REG TASDEVICE_REG(0x00, 0x0f, 0x60) +#define TAS2563_PRM_PLT_FLAG_REG TASDEVICE_REG(0x00, 0x0d, 0x74) +#define TAS2563_PRM_SINEGAIN_REG TASDEVICE_REG(0x00, 0x0d, 0x7c) +/* prm_Int_B0 */ +#define TAS2563_TE_TA1_REG TASDEVICE_REG(0x00, 0x10, 0x0c) +/* prm_Int_A1 */ +#define TAS2563_TE_TA1_AT_REG TASDEVICE_REG(0x00, 0x10, 0x10) +/* prm_TE_Beta */ +#define TAS2563_TE_TA2_REG TASDEVICE_REG(0x00, 0x0f, 0x64) +/* prm_TE_Beta1 */ +#define TAS2563_TE_AT_REG TASDEVICE_REG(0x00, 0x0f, 0x68) +/* prm_TE_1_Beta1 */ +#define TAS2563_TE_DT_REG TASDEVICE_REG(0x00, 0x0f, 0x70) + +#define TAS2781_PRM_INT_MASK_REG TASDEVICE_REG(0x00, 0x00, 0x3b) +#define TAS2781_PRM_CLK_CFG_REG TASDEVICE_REG(0x00, 0x00, 0x5c) +#define TAS2781_PRM_RSVD_REG TASDEVICE_REG(0x00, 0x01, 0x19) +#define TAS2781_PRM_TEST_57_REG TASDEVICE_REG(0x00, 0xfd, 0x39) +#define TAS2781_PRM_TEST_62_REG TASDEVICE_REG(0x00, 0xfd, 0x3e) +#define TAS2781_PRM_PVDD_UVLO_REG TASDEVICE_REG(0x00, 0x00, 0x71) +#define TAS2781_PRM_CHNL_0_REG TASDEVICE_REG(0x00, 0x00, 0x03) +#define TAS2781_PRM_NG_CFG0_REG TASDEVICE_REG(0x00, 0x00, 0x35) +#define TAS2781_PRM_IDLE_CH_DET_REG TASDEVICE_REG(0x00, 0x00, 0x66) +#define TAS2781_PRM_PLT_FLAG_REG TASDEVICE_REG(0x00, 0x14, 0x38) +#define TAS2781_PRM_SINEGAIN_REG TASDEVICE_REG(0x00, 0x14, 0x40) +#define TAS2781_PRM_SINEGAIN2_REG TASDEVICE_REG(0x00, 0x14, 0x44) + +#define TAS2781_TEST_UNLOCK_REG TASDEVICE_REG(0x00, 0xfd, 0x0d) +#define TAS2781_TEST_PAGE_UNLOCK 0x0d + +#define TAS2781_RUNTIME_LATCH_RE_REG TASDEVICE_REG(0x00, 0x00, 0x49) +#define TAS2781_RUNTIME_RE_REG_TF TASDEVICE_REG(0x64, 0x62, 0x48) +#define TAS2781_RUNTIME_RE_REG TASDEVICE_REG(0x64, 0x63, 0x44) enum audio_device { - TAS2781 = 0, + TAS2020, + TAS2118, + TAS2120, + TAS2320, + TAS2563, + TAS2568, + TAS2570, + TAS2572, + TAS2574, + TAS2781, + TAS5802, + TAS5806M, + TAS5806MD, + TAS5815, + TAS5822, + TAS5825, + TAS5827, + TAS5828, + TAS5830, + TAS_OTHERS, +}; + +enum dspbin_type { + TASDEV_BASIC, + TASDEV_ALPHA, + TASDEV_BETA, }; -enum device_catlog_id { - LENOVO = 0, - OTHERS +struct bulk_reg_val { + int reg; + unsigned char val[4]; + unsigned char val_len; + bool is_locked; }; struct tasdevice { + struct bulk_reg_val *cali_data_backup; + struct bulk_reg_val alp_cali_bckp; struct tasdevice_fw *cali_data_fmw; unsigned int dev_addr; unsigned int err_code; @@ -78,40 +160,69 @@ struct tasdevice { bool is_loaderr; }; -struct tasdevice_irqinfo { - int irq_gpio; - int irq; +struct cali_reg { + unsigned int r0_reg; + unsigned int r0_low_reg; + unsigned int invr0_reg; + unsigned int pow_reg; + unsigned int tlimit_reg; }; struct calidata { unsigned char *data; unsigned long total_sz; + struct cali_reg cali_reg_array; + unsigned int cali_dat_sz_per_dev; +}; + +/* + * To enable CONFIG_SND_SOC_TAS2781_ACOUST_I2C will create a bridge to the + * acoustic tuning tool which can tune the chips' acoustic effect. Due to the + * whole directly exposing the registers, there exist some potential risks. So + * this define is invisible in Kconfig, anyone who wants to use acoustic tool + * have to edit the source manually. + */ +#ifdef CONFIG_SND_SOC_TAS2781_ACOUST_I2C +#define TASDEV_DATA_PAYLOAD_SIZE 128 +struct acoustic_data { + unsigned char len; + unsigned char id; + unsigned char addr; + unsigned char book; + unsigned char page; + unsigned char reg; + unsigned char data[TASDEV_DATA_PAYLOAD_SIZE]; }; +#endif struct tasdevice_priv { struct tasdevice tasdevice[TASDEVICE_MAX_CHANNELS]; - struct tasdevice_irqinfo irq_info; struct tasdevice_rca rcabin; struct calidata cali_data; +#ifdef CONFIG_SND_SOC_TAS2781_ACOUST_I2C + struct acoustic_data acou_data; +#endif struct tasdevice_fw *fmw; struct gpio_desc *reset; struct mutex codec_lock; struct regmap *regmap; struct device *dev; - struct tm tm; - enum device_catlog_id catlog_id; - const char *acpi_subsystem_id; unsigned char cal_binaryname[TASDEVICE_MAX_CHANNELS][64]; unsigned char crc8_lkp_tbl[CRC8_TABLE_SIZE]; unsigned char coef_binaryname[64]; unsigned char rca_binaryname[64]; unsigned char dev_name[32]; + const unsigned char (*dvc_tlv_table)[4]; + const char *name_prefix; unsigned char ndev; + unsigned int dspbin_typ; unsigned int magic_num; unsigned int chip_id; unsigned int sysclk; + int speaker_id; + int irq; int cur_prog; int cur_conf; int fw_state; @@ -121,6 +232,10 @@ struct tasdevice_priv { bool force_fwload_status; bool playback_started; bool isacpi; + bool isspi; + bool is_user_space_calidata; + unsigned int global_addr; + 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, @@ -129,36 +244,33 @@ struct tasdevice_priv { int (*fw_parse_configuration_data)(struct tasdevice_priv *tas_priv, struct tasdevice_fw *tas_fmw, const struct firmware *fmw, int offset); + int (*fw_parse_fct_param_address)(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 (*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 tas2781_reset(struct tasdevice_priv *tas_dev); -int tascodec_init(struct tasdevice_priv *tas_priv, void *codec, - 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_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/include/sound/tas2x20-tlv.h b/include/sound/tas2x20-tlv.h new file mode 100644 index 000000000000..6e6bcec4a0a1 --- /dev/null +++ b/include/sound/tas2x20-tlv.h @@ -0,0 +1,259 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// +// ALSA SoC Texas Instruments TAS2x20/TAS2118 Audio Smart Amplifier +// +// Copyright (C) 2025 Texas Instruments Incorporated +// https://www.ti.com +// +// The TAS2x20/TAS2118 hda driver implements for one, two, or even multiple +// TAS2x20/TAS2118 chips. +// +// Author: Baojun Xu <baojun.xu@ti.com> +// + +#ifndef __TAS2X20_TLV_H__ +#define __TAS2X20_TLV_H__ + +#define TAS2X20_DVC_LEVEL TASDEVICE_REG(0x0, 0x2, 0x0c) +#define TAS2X20_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x07) + +static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2x20_dvc_tlv, 1650, 50, 0); +static const __maybe_unused DECLARE_TLV_DB_SCALE(tas2x20_amp_tlv, 2100, 50, 0); + +/* pow(10, db/20) * pow(2,22) */ +static const __maybe_unused unsigned char tas2x20_dvc_table[][4] = { + { 0X00, 0X00, 0X0D, 0X00 }, /* -110.0db */ + { 0X00, 0X00, 0X0E, 0X00 }, /* -109.5db */ + { 0X00, 0X00, 0X0E, 0X00 }, /* -109.0db */ + { 0X00, 0X00, 0X0F, 0X00 }, /* -108.5db */ + { 0X00, 0X00, 0X10, 0X00 }, /* -108.0db */ + { 0X00, 0X00, 0X11, 0X00 }, /* -107.5db */ + { 0X00, 0X00, 0X12, 0X00 }, /* -107.0db */ + { 0X00, 0X00, 0X13, 0X00 }, /* -106.5db */ + { 0X00, 0X00, 0X15, 0X00 }, /* -106.0db */ + { 0X00, 0X00, 0X16, 0X00 }, /* -105.5db */ + { 0X00, 0X00, 0X17, 0X00 }, /* -105.0db */ + { 0X00, 0X00, 0X18, 0X00 }, /* -104.5db */ + { 0X00, 0X00, 0X1A, 0X00 }, /* -104.0db */ + { 0X00, 0X00, 0X1C, 0X00 }, /* -103.5db */ + { 0X00, 0X00, 0X1D, 0X00 }, /* -103.0db */ + { 0X00, 0X00, 0X1F, 0X00 }, /* -102.5db */ + { 0X00, 0X00, 0X21, 0X00 }, /* -102.0db */ + { 0X00, 0X00, 0X23, 0X00 }, /* -101.5db */ + { 0X00, 0X00, 0X25, 0X00 }, /* -101.0db */ + { 0X00, 0X00, 0X27, 0X00 }, /* -100.5db */ + { 0X00, 0X00, 0X29, 0X00 }, /* -100.0db */ + { 0X00, 0X00, 0X2C, 0X00 }, /* -99.5db */ + { 0X00, 0X00, 0X2F, 0X00 }, /* -99.0db */ + { 0X00, 0X00, 0X31, 0X00 }, /* -98.5db */ + { 0X00, 0X00, 0X34, 0X00 }, /* -98.0db */ + { 0X00, 0X00, 0X37, 0X00 }, /* -97.5db */ + { 0X00, 0X00, 0X3B, 0X00 }, /* -97.0db */ + { 0X00, 0X00, 0X3E, 0X00 }, /* -96.5db */ + { 0X00, 0X00, 0X42, 0X00 }, /* -96.0db */ + { 0X00, 0X00, 0X46, 0X00 }, /* -95.5db */ + { 0X00, 0X00, 0X4A, 0X00 }, /* -95.0db */ + { 0X00, 0X00, 0X4F, 0X00 }, /* -94.5db */ + { 0X00, 0X00, 0X53, 0X00 }, /* -94.0db */ + { 0X00, 0X00, 0X58, 0X00 }, /* -93.5db */ + { 0X00, 0X00, 0X5D, 0X00 }, /* -93.0db */ + { 0X00, 0X00, 0X63, 0X00 }, /* -92.5db */ + { 0X00, 0X00, 0X69, 0X00 }, /* -92.0db */ + { 0X00, 0X00, 0X6F, 0X00 }, /* -91.5db */ + { 0X00, 0X00, 0X76, 0X00 }, /* -91.0db */ + { 0X00, 0X00, 0X7D, 0X00 }, /* -90.5db */ + { 0X00, 0X00, 0X84, 0X00 }, /* -90.0db */ + { 0X00, 0X00, 0X8C, 0X00 }, /* -89.5db */ + { 0X00, 0X00, 0X94, 0X00 }, /* -89.0db */ + { 0X00, 0X00, 0X9D, 0X00 }, /* -88.5db */ + { 0X00, 0X00, 0XA6, 0X00 }, /* -88.0db */ + { 0X00, 0X00, 0XB0, 0X00 }, /* -87.5db */ + { 0X00, 0X00, 0XBB, 0X00 }, /* -87.0db */ + { 0X00, 0X00, 0XC6, 0X00 }, /* -86.5db */ + { 0X00, 0X00, 0XD2, 0X00 }, /* -86.0db */ + { 0X00, 0X00, 0XDE, 0X00 }, /* -85.5db */ + { 0X00, 0X00, 0XEB, 0X00 }, /* -85.0db */ + { 0X00, 0X00, 0XF9, 0X00 }, /* -84.5db */ + { 0X00, 0X01, 0X08, 0X00 }, /* -84.0db */ + { 0X00, 0X01, 0X18, 0X00 }, /* -83.5db */ + { 0X00, 0X01, 0X28, 0X00 }, /* -83.0db */ + { 0X00, 0X01, 0X3A, 0X00 }, /* -82.5db */ + { 0X00, 0X01, 0X4D, 0X00 }, /* -82.0db */ + { 0X00, 0X01, 0X60, 0X00 }, /* -81.5db */ + { 0X00, 0X01, 0X75, 0X00 }, /* -81.0db */ + { 0X00, 0X01, 0X8B, 0X00 }, /* -80.5db */ + { 0X00, 0X01, 0XA3, 0X00 }, /* -80.0db */ + { 0X00, 0X01, 0XBC, 0X00 }, /* -79.5db */ + { 0X00, 0X01, 0XD6, 0X00 }, /* -79.0db */ + { 0X00, 0X01, 0XF2, 0X00 }, /* -78.5db */ + { 0X00, 0X02, 0X10, 0X00 }, /* -78.0db */ + { 0X00, 0X02, 0X2F, 0X00 }, /* -77.5db */ + { 0X00, 0X02, 0X50, 0X00 }, /* -77.0db */ + { 0X00, 0X02, 0X73, 0X00 }, /* -76.5db */ + { 0X00, 0X02, 0X98, 0X00 }, /* -76.0db */ + { 0X00, 0X02, 0XC0, 0X00 }, /* -75.5db */ + { 0X00, 0X02, 0XE9, 0X00 }, /* -75.0db */ + { 0X00, 0X03, 0X16, 0X00 }, /* -74.5db */ + { 0X00, 0X03, 0X44, 0X00 }, /* -74.0db */ + { 0X00, 0X03, 0X76, 0X00 }, /* -73.5db */ + { 0X00, 0X03, 0XAA, 0X00 }, /* -73.0db */ + { 0X00, 0X03, 0XE2, 0X00 }, /* -72.5db */ + { 0X00, 0X04, 0X1D, 0X00 }, /* -72.0db */ + { 0X00, 0X04, 0X5B, 0X00 }, /* -71.5db */ + { 0X00, 0X04, 0X9E, 0X00 }, /* -71.0db */ + { 0X00, 0X04, 0XE4, 0X00 }, /* -70.5db */ + { 0X00, 0X05, 0X2E, 0X00 }, /* -70.0db */ + { 0X00, 0X05, 0X7C, 0X00 }, /* -69.5db */ + { 0X00, 0X05, 0XD0, 0X00 }, /* -69.0db */ + { 0X00, 0X06, 0X28, 0X00 }, /* -68.5db */ + { 0X00, 0X06, 0X85, 0X00 }, /* -68.0db */ + { 0X00, 0X06, 0XE8, 0X00 }, /* -67.5db */ + { 0X00, 0X07, 0X51, 0X00 }, /* -67.0db */ + { 0X00, 0X07, 0XC0, 0X00 }, /* -66.5db */ + { 0X00, 0X08, 0X36, 0X00 }, /* -66.0db */ + { 0X00, 0X08, 0XB2, 0X00 }, /* -65.5db */ + { 0X00, 0X09, 0X36, 0X00 }, /* -65.0db */ + { 0X00, 0X09, 0XC2, 0X00 }, /* -64.5db */ + { 0X00, 0X0A, 0X56, 0X00 }, /* -64.0db */ + { 0X00, 0X0A, 0XF3, 0X00 }, /* -63.5db */ + { 0X00, 0X0B, 0X99, 0X00 }, /* -63.0db */ + { 0X00, 0X0C, 0X49, 0X00 }, /* -62.5db */ + { 0X00, 0X0D, 0X03, 0X00 }, /* -62.0db */ + { 0X00, 0X0D, 0XC9, 0X00 }, /* -61.5db */ + { 0X00, 0X0E, 0X9A, 0X00 }, /* -61.0db */ + { 0X00, 0X0F, 0X77, 0X00 }, /* -60.5db */ + { 0X00, 0X10, 0X62, 0X00 }, /* -60.0db */ + { 0X00, 0X11, 0X5A, 0X00 }, /* -59.5db */ + { 0X00, 0X12, 0X62, 0X00 }, /* -59.0db */ + { 0X00, 0X13, 0X78, 0X00 }, /* -58.5db */ + { 0X00, 0X14, 0XA0, 0X00 }, /* -58.0db */ + { 0X00, 0X15, 0XD9, 0X00 }, /* -57.5db */ + { 0X00, 0X17, 0X24, 0X00 }, /* -57.0db */ + { 0X00, 0X18, 0X83, 0X00 }, /* -56.5db */ + { 0X00, 0X19, 0XF7, 0X00 }, /* -56.0db */ + { 0X00, 0X1B, 0X81, 0X00 }, /* -55.5db */ + { 0X00, 0X1D, 0X22, 0X00 }, /* -55.0db */ + { 0X00, 0X1E, 0XDC, 0X00 }, /* -54.5db */ + { 0X00, 0X20, 0XB0, 0X00 }, /* -54.0db */ + { 0X00, 0X22, 0XA0, 0X00 }, /* -53.5db */ + { 0X00, 0X24, 0XAD, 0X00 }, /* -53.0db */ + { 0X00, 0X26, 0XDA, 0X00 }, /* -52.5db */ + { 0X00, 0X29, 0X27, 0X00 }, /* -52.0db */ + { 0X00, 0X2B, 0X97, 0X00 }, /* -51.5db */ + { 0X00, 0X2E, 0X2D, 0X00 }, /* -51.0db */ + { 0X00, 0X30, 0XE9, 0X00 }, /* -50.5db */ + { 0X00, 0X33, 0XCF, 0X00 }, /* -50.0db */ + { 0X00, 0X36, 0XE1, 0X00 }, /* -49.5db */ + { 0X00, 0X3A, 0X21, 0X00 }, /* -49.0db */ + { 0X00, 0X3D, 0X93, 0X00 }, /* -48.5db */ + { 0X00, 0X41, 0X39, 0X00 }, /* -48.0db */ + { 0X00, 0X45, 0X17, 0X00 }, /* -47.5db */ + { 0X00, 0X49, 0X2F, 0X00 }, /* -47.0db */ + { 0X00, 0X4D, 0X85, 0X00 }, /* -46.5db */ + { 0X00, 0X52, 0X1D, 0X00 }, /* -46.0db */ + { 0X00, 0X56, 0XFA, 0X00 }, /* -45.5db */ + { 0X00, 0X5C, 0X22, 0X00 }, /* -45.0db */ + { 0X00, 0X61, 0X97, 0X00 }, /* -44.5db */ + { 0X00, 0X67, 0X60, 0X00 }, /* -44.0db */ + { 0X00, 0X6D, 0X80, 0X00 }, /* -43.5db */ + { 0X00, 0X73, 0XFD, 0X00 }, /* -43.0db */ + { 0X00, 0X7A, 0XDC, 0X00 }, /* -42.5db */ + { 0X00, 0X82, 0X24, 0X00 }, /* -42.0db */ + { 0X00, 0X89, 0XDA, 0X00 }, /* -41.5db */ + { 0X00, 0X92, 0X05, 0X00 }, /* -41.0db */ + { 0X00, 0X9A, 0XAC, 0X00 }, /* -40.5db */ + { 0X00, 0XA3, 0XD7, 0X00 }, /* -40.0db */ + { 0X00, 0XAD, 0X8C, 0X00 }, /* -39.5db */ + { 0X00, 0XB7, 0XD4, 0X00 }, /* -39.0db */ + { 0X00, 0XC2, 0XB9, 0X00 }, /* -38.5db */ + { 0X00, 0XCE, 0X43, 0X00 }, /* -38.0db */ + { 0X00, 0XDA, 0X7B, 0X00 }, /* -37.5db */ + { 0X00, 0XE7, 0X6E, 0X00 }, /* -37.0db */ + { 0X00, 0XF5, 0X24, 0X00 }, /* -36.5db */ + { 0X01, 0X03, 0XAB, 0X00 }, /* -36.0db */ + { 0X01, 0X13, 0X0E, 0X00 }, /* -35.5db */ + { 0X01, 0X23, 0X5A, 0X00 }, /* -35.0db */ + { 0X01, 0X34, 0X9D, 0X00 }, /* -34.5db */ + { 0X01, 0X46, 0XE7, 0X00 }, /* -34.0db */ + { 0X01, 0X5A, 0X46, 0X00 }, /* -33.5db */ + { 0X01, 0X6E, 0XCA, 0X00 }, /* -33.0db */ + { 0X01, 0X84, 0X86, 0X00 }, /* -32.5db */ + { 0X01, 0X9B, 0X8C, 0X00 }, /* -32.0db */ + { 0X01, 0XB3, 0XEE, 0X00 }, /* -31.5db */ + { 0X01, 0XCD, 0XC3, 0X00 }, /* -31.0db */ + { 0X01, 0XE9, 0X20, 0X00 }, /* -30.5db */ + { 0X02, 0X06, 0X1B, 0X00 }, /* -30.0db */ + { 0X02, 0X24, 0XCE, 0X00 }, /* -29.5db */ + { 0X02, 0X45, 0X53, 0X00 }, /* -29.0db */ + { 0X02, 0X67, 0XC5, 0X00 }, /* -28.5db */ + { 0X02, 0X8C, 0X42, 0X00 }, /* -28.0db */ + { 0X02, 0XB2, 0XE8, 0X00 }, /* -27.5db */ + { 0X02, 0XDB, 0XD8, 0X00 }, /* -27.0db */ + { 0X03, 0X07, 0X36, 0X00 }, /* -26.5db */ + { 0X03, 0X35, 0X25, 0X00 }, /* -26.0db */ + { 0X03, 0X65, 0XCD, 0X00 }, /* -25.5db */ + { 0X03, 0X99, 0X57, 0X00 }, /* -25.0db */ + { 0X03, 0XCF, 0XEE, 0X00 }, /* -24.5db */ + { 0X04, 0X09, 0XC2, 0X00 }, /* -24.0db */ + { 0X04, 0X47, 0X03, 0X00 }, /* -23.5db */ + { 0X04, 0X87, 0XE5, 0X00 }, /* -23.0db */ + { 0X04, 0XCC, 0XA0, 0X00 }, /* -22.5db */ + { 0X05, 0X15, 0X6D, 0X00 }, /* -22.0db */ + { 0X05, 0X62, 0X8A, 0X00 }, /* -21.5db */ + { 0X05, 0XB4, 0X39, 0X00 }, /* -21.0db */ + { 0X06, 0X0A, 0XBF, 0X00 }, /* -20.5db */ + { 0X06, 0X66, 0X66, 0X00 }, /* -20.0db */ + { 0X06, 0XC7, 0X7B, 0X00 }, /* -19.5db */ + { 0X07, 0X2E, 0X50, 0X00 }, /* -19.0db */ + { 0X07, 0X9B, 0X3D, 0X00 }, /* -18.5db */ + { 0X08, 0X0E, 0X9F, 0X00 }, /* -18.0db */ + { 0X08, 0X88, 0XD7, 0X00 }, /* -17.5db */ + { 0X09, 0X0A, 0X4D, 0X00 }, /* -17.0db */ + { 0X09, 0X93, 0X6E, 0X00 }, /* -16.5db */ + { 0X0A, 0X24, 0XB0, 0X00 }, /* -16.0db */ + { 0X0A, 0XBE, 0X8D, 0X00 }, /* -15.5db */ + { 0X0B, 0X61, 0X88, 0X00 }, /* -15.0db */ + { 0X0C, 0X0E, 0X2B, 0X00 }, /* -14.5db */ + { 0X0C, 0XC5, 0X09, 0X00 }, /* -14.0db */ + { 0X0D, 0X86, 0XBD, 0X00 }, /* -13.5db */ + { 0X0E, 0X53, 0XEB, 0X00 }, /* -13.0db */ + { 0X0F, 0X2D, 0X42, 0X00 }, /* -12.5db */ + { 0X10, 0X13, 0X79, 0X00 }, /* -12.0db */ + { 0X11, 0X07, 0X54, 0X00 }, /* -11.5db */ + { 0X12, 0X09, 0XA3, 0X00 }, /* -11.0db */ + { 0X13, 0X1B, 0X40, 0X00 }, /* -10.5db */ + { 0X14, 0X3D, 0X13, 0X00 }, /* -10.0db */ + { 0X15, 0X70, 0X12, 0X00 }, /* -9.5db */ + { 0X16, 0XB5, 0X43, 0X00 }, /* -9.0db */ + { 0X18, 0X0D, 0XB8, 0X00 }, /* -8.5db */ + { 0X19, 0X7A, 0X96, 0X00 }, /* -8.0db */ + { 0X1A, 0XFD, 0X13, 0X00 }, /* -7.5db */ + { 0X1C, 0X96, 0X76, 0X00 }, /* -7.0db */ + { 0X1E, 0X48, 0X1C, 0X00 }, /* -6.5db */ + { 0X20, 0X13, 0X73, 0X00 }, /* -6.0db */ + { 0X21, 0XFA, 0X02, 0X00 }, /* -5.5db */ + { 0X23, 0XFD, 0X66, 0X00 }, /* -5.0db */ + { 0X26, 0X1F, 0X54, 0X00 }, /* -4.5db */ + { 0X28, 0X61, 0X9A, 0X00 }, /* -4.0db */ + { 0X2A, 0XC6, 0X25, 0X00 }, /* -3.5db */ + { 0X2D, 0X4E, 0XFB, 0X00 }, /* -3.0db */ + { 0X2F, 0XFE, 0X44, 0X00 }, /* -2.5db */ + { 0X32, 0XD6, 0X46, 0X00 }, /* -2.0db */ + { 0X35, 0XD9, 0X6B, 0X00 }, /* -1.5db */ + { 0X39, 0X0A, 0X41, 0X00 }, /* -1.0db */ + { 0X3C, 0X6B, 0X7E, 0X00 }, /* -0.5db */ + { 0X40, 0X00, 0X00, 0X00 }, /* 0.0db */ + { 0X43, 0XCA, 0XD0, 0X00 }, /* 0.5db */ + { 0X47, 0XCF, 0X26, 0X00 }, /* 1.0db */ + { 0X4C, 0X10, 0X6B, 0X00 }, /* 1.5db */ + { 0X50, 0X92, 0X3B, 0X00 }, /* 2.0db */ + { 0X55, 0X58, 0X6A, 0X00 }, /* 2.5db */ + { 0X5A, 0X67, 0X03, 0X00 }, /* 3.0db */ + { 0X5F, 0XC2, 0X53, 0X00 }, /* 3.5db */ + { 0X65, 0X6E, 0XE3, 0X00 }, /* 4.0db */ + { 0X6B, 0X71, 0X86, 0X00 }, /* 4.5db */ + { 0X71, 0XCF, 0X54, 0X00 }, /* 5.0db */ + { 0X78, 0X8D, 0XB4, 0X00 }, /* 5.5db */ + { 0X7F, 0XB2, 0X61, 0X00 }, /* 6.0db */ +}; +#endif diff --git a/include/sound/tas5825-tlv.h b/include/sound/tas5825-tlv.h new file mode 100644 index 000000000000..95f2d3fad120 --- /dev/null +++ b/include/sound/tas5825-tlv.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +// +// ALSA SoC Texas Instruments TAS5825 Audio Smart Amplifier +// +// Copyright (C) 2025 Texas Instruments Incorporated +// https://www.ti.com +// +// The TAS5825 hda driver implements for one or two TAS5825 chips. +// +// Author: Baojun Xu <baojun.xu@ti.com> +// + +#ifndef __TAS5825_TLV_H__ +#define __TAS5825_TLV_H__ + +#define TAS5825_DVC_LEVEL TASDEVICE_REG(0x0, 0x0, 0x4c) +#define TAS5825_AMP_LEVEL TASDEVICE_REG(0x0, 0x0, 0x54) + +static const __maybe_unused DECLARE_TLV_DB_SCALE( + tas5825_dvc_tlv, -10300, 50, 0); +static const __maybe_unused DECLARE_TLV_DB_SCALE( + tas5825_amp_tlv, -1550, 50, 0); + +#endif diff --git a/include/sound/tlv320aic32x4.h b/include/sound/tlv320aic32x4.h index 0abf74d7edbd..b779d671a995 100644 --- a/include/sound/tlv320aic32x4.h +++ b/include/sound/tlv320aic32x4.h @@ -40,13 +40,4 @@ struct aic32x4_setup_data { unsigned int gpio_func[5]; }; - -struct aic32x4_pdata { - struct aic32x4_setup_data *setup; - u32 power_cfg; - u32 micpga_routing; - bool swapdacs; - int rstn_gpio; -}; - #endif diff --git a/include/sound/tlv320dac33-plat.h b/include/sound/tlv320dac33-plat.h deleted file mode 100644 index 7a7249a896e3..000000000000 --- a/include/sound/tlv320dac33-plat.h +++ /dev/null @@ -1,21 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Platform header for Texas Instruments TLV320DAC33 codec driver - * - * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> - * - * Copyright: (C) 2009 Nokia Corporation - */ - -#ifndef __TLV320DAC33_PLAT_H -#define __TLV320DAC33_PLAT_H - -struct tlv320dac33_platform_data { - int power_gpio; - int mode1_latency; /* latency caused by the i2c writes in us */ - int auto_fifo_config; /* FIFO config based on the period size */ - int keep_bclk; /* Keep the BCLK running in FIFO modes */ - u8 burst_bclkdiv; -}; - -#endif /* __TLV320DAC33_PLAT_H */ diff --git a/include/sound/tpa6130a2-plat.h b/include/sound/tpa6130a2-plat.h deleted file mode 100644 index a60930e36e93..000000000000 --- a/include/sound/tpa6130a2-plat.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * TPA6130A2 driver platform header - * - * Copyright (C) Nokia Corporation - * - * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> - */ - -#ifndef TPA6130A2_PLAT_H -#define TPA6130A2_PLAT_H - -struct tpa6130a2_platform_data { - int power_gpio; -}; - -#endif diff --git a/include/sound/uda134x.h b/include/sound/uda134x.h deleted file mode 100644 index db82516da162..000000000000 --- a/include/sound/uda134x.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * uda134x.h -- UDA134x ALSA SoC Codec driver - * - * Copyright 2007 Dension Audio Systems Ltd. - * Author: Zoltan Devai - */ - -#ifndef _UDA134X_H -#define _UDA134X_H - -#include <sound/l3.h> - -struct uda134x_platform_data { - struct l3_pins l3; - void (*power) (int); - int model; -#define UDA134X_UDA1340 1 -#define UDA134X_UDA1341 2 -#define UDA134X_UDA1344 3 -#define UDA134X_UDA1345 4 -}; - -#endif /* _UDA134X_H */ diff --git a/include/sound/ump.h b/include/sound/ump.h index 44d2c2fd021d..73f97f88e2ed 100644 --- a/include/sound/ump.h +++ b/include/sound/ump.h @@ -13,6 +13,15 @@ struct snd_ump_ops; struct ump_cvt_to_ump; struct snd_seq_ump_ops; +struct snd_ump_group { + int group; /* group index (0-based) */ + unsigned int dir_bits; /* directions */ + bool active; /* activeness */ + bool valid; /* valid group (referred by blocks) */ + bool is_midi1; /* belongs to a MIDI1 FB */ + char name[64]; /* group name */ +}; + struct snd_ump_endpoint { struct snd_rawmidi core; /* raw UMP access */ @@ -41,10 +50,13 @@ struct snd_ump_endpoint { struct mutex open_mutex; + struct snd_ump_group groups[SNDRV_UMP_MAX_GROUPS]; /* table of groups */ + #if IS_ENABLED(CONFIG_SND_UMP_LEGACY_RAWMIDI) spinlock_t legacy_locks[2]; struct snd_rawmidi *legacy_rmidi; struct snd_rawmidi_substream *legacy_substreams[2][SNDRV_UMP_MAX_GROUPS]; + unsigned char legacy_mapping[SNDRV_UMP_MAX_GROUPS]; /* for legacy output; need to open the actual substream unlike input */ int legacy_out_opens; @@ -71,6 +83,7 @@ struct snd_ump_ops { struct snd_seq_ump_ops { void (*input_receive)(struct snd_ump_endpoint *ump, const u32 *data, int words); + int (*notify_ep_change)(struct snd_ump_endpoint *ump); int (*notify_fb_change)(struct snd_ump_endpoint *ump, struct snd_ump_block *fb); int (*switch_protocol)(struct snd_ump_endpoint *ump); @@ -111,6 +124,7 @@ static inline int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump, int snd_ump_receive_ump_val(struct snd_ump_endpoint *ump, u32 val); int snd_ump_switch_protocol(struct snd_ump_endpoint *ump, unsigned int protocol); +void snd_ump_update_group_attrs(struct snd_ump_endpoint *ump); /* * Some definitions for UMP diff --git a/include/sound/ump_convert.h b/include/sound/ump_convert.h index 28c364c63245..682499b871ea 100644 --- a/include/sound/ump_convert.h +++ b/include/sound/ump_convert.h @@ -13,12 +13,13 @@ struct ump_cvt_to_ump_bank { unsigned char cc_nrpn_msb, cc_nrpn_lsb; unsigned char cc_data_msb, cc_data_lsb; unsigned char cc_bank_msb, cc_bank_lsb; + bool cc_data_msb_set, cc_data_lsb_set; }; /* context for converting from MIDI1 byte stream to UMP packet */ struct ump_cvt_to_ump { /* MIDI1 intermediate buffer */ - unsigned char buf[4]; + unsigned char buf[6]; /* up to 6 bytes for SysEx */ int len; int cmd_bytes; diff --git a/include/sound/ump_msg.h b/include/sound/ump_msg.h index 72f60ddfea75..9556b4755a1e 100644 --- a/include/sound/ump_msg.h +++ b/include/sound/ump_msg.h @@ -604,7 +604,7 @@ struct snd_ump_stream_msg_ep_info { } __packed; /* UMP Stream Message: Device Info Notification (128bit) */ -struct snd_ump_stream_msg_devince_info { +struct snd_ump_stream_msg_device_info { #ifdef __BIG_ENDIAN_BITFIELD /* 0 */ u32 type:4; @@ -754,7 +754,7 @@ struct snd_ump_stream_msg_fb_name { union snd_ump_stream_msg { struct snd_ump_stream_msg_ep_discovery ep_discovery; struct snd_ump_stream_msg_ep_info ep_info; - struct snd_ump_stream_msg_devince_info device_info; + struct snd_ump_stream_msg_device_info device_info; struct snd_ump_stream_msg_stream_cfg stream_cfg; struct snd_ump_stream_msg_fb_discovery fb_discovery; struct snd_ump_stream_msg_fb_info fb_info; diff --git a/include/sound/vx_core.h b/include/sound/vx_core.h index 1ddd3036bdfc..ca87fa6a8135 100644 --- a/include/sound/vx_core.h +++ b/include/sound/vx_core.h @@ -155,7 +155,6 @@ struct vx_core { unsigned int chip_status; unsigned int pcm_running; - struct device *dev; struct snd_hwdep *hwdep; struct vx_rmh irq_rmh; /* RMH used in interrupts */ diff --git a/include/sound/wavefront.h b/include/sound/wavefront.h index 37ed437e2123..ef6f46accf29 100644 --- a/include/sound/wavefront.h +++ b/include/sound/wavefront.h @@ -8,34 +8,6 @@ * Copyright (c) by Paul Barton-Davis <pbd@op.net> */ -#if (!defined(__GNUC__) && !defined(__GNUG__)) - - You will not be able to compile this file correctly without gcc, because - it is necessary to pack the "wavefront_alias" structure to a size - of 22 bytes, corresponding to 16-bit alignment (as would have been - the case on the original platform, MS-DOS). If this is not done, - then WavePatch-format files cannot be read/written correctly. - The method used to do this here ("__attribute__((packed)") is - completely compiler dependent. - - All other wavefront_* types end up aligned to 32 bit values and - still have the same (correct) size. - -#else - - /* However, note that as of G++ 2.7.3.2, g++ was unable to - correctly parse *type* __attribute__ tags. It will do the - right thing if we use the "packed" attribute on each struct - member, which has the same semantics anyway. - */ - -#endif /* __GNUC__ */ - -/***************************** WARNING ******************************** - PLEASE DO NOT MODIFY THIS FILE IN ANY WAY THAT AFFECTS ITS ABILITY TO - BE USED WITH EITHER C *OR* C++. - **********************************************************************/ - #ifndef NUM_MIDIKEYS #define NUM_MIDIKEYS 128 #endif /* NUM_MIDIKEYS */ @@ -44,29 +16,6 @@ #define NUM_MIDICHANNELS 16 #endif /* NUM_MIDICHANNELS */ -/* These are very useful/important. the original wavefront interface - was developed on a 16 bit system, where sizeof(int) = 2 - bytes. Defining things like this makes the code much more portable, and - easier to understand without having to toggle back and forth - between a 16-bit view of the world and a 32-bit one. - */ - -#ifndef __KERNEL__ -/* keep them for compatibility */ -typedef short s16; -typedef unsigned short u16; -typedef int s32; -typedef unsigned int u32; -typedef char s8; -typedef unsigned char u8; -typedef s16 INT16; -typedef u16 UINT16; -typedef s32 INT32; -typedef u32 UINT32; -typedef s8 CHAR8; -typedef u8 UCHAR8; -#endif - /* Pseudo-commands not part of the WaveFront command set. These are used for various driver controls and direct hardware control. @@ -468,7 +417,7 @@ typedef struct wf_alias { */ u8 sixteen_bit_padding; -} __attribute__((packed)) wavefront_alias; +} __packed wavefront_alias; typedef struct wf_drum { u8 PatchNumber; diff --git a/include/sound/wm0010.h b/include/sound/wm0010.h index 13b473935ca1..14ff9056c5d0 100644 --- a/include/sound/wm0010.h +++ b/include/sound/wm0010.h @@ -11,12 +11,6 @@ #define WM0010_PDATA_H struct wm0010_pdata { - int gpio_reset; - - /* Set if there is an inverter between the GPIO controlling - * the reset signal and the device. - */ - int reset_active_high; int irq_flags; }; diff --git a/include/sound/wm1250-ev1.h b/include/sound/wm1250-ev1.h deleted file mode 100644 index d16614ebecb4..000000000000 --- a/include/sound/wm1250-ev1.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/sound/wm1250-ev1.h - Platform data for WM1250-EV1 - * - * Copyright 2011 Wolfson Microelectronics. PLC. - */ - -#ifndef __LINUX_SND_WM1250_EV1_H -#define __LINUX_SND_WM1250_EV1_H - -#define WM1250_EV1_NUM_GPIOS 5 - -#define WM1250_EV1_GPIO_CLK_ENA 0 -#define WM1250_EV1_GPIO_CLK_SEL0 1 -#define WM1250_EV1_GPIO_CLK_SEL1 2 -#define WM1250_EV1_GPIO_OSR 3 -#define WM1250_EV1_GPIO_MASTER 4 - - -struct wm1250_ev1_pdata { - int gpios[WM1250_EV1_NUM_GPIOS]; -}; - -#endif diff --git a/include/sound/wm2200.h b/include/sound/wm2200.h index 9987e6c09bdc..2e4913ee2505 100644 --- a/include/sound/wm2200.h +++ b/include/sound/wm2200.h @@ -42,8 +42,6 @@ struct wm2200_micbias { }; struct wm2200_pdata { - int reset; /** GPIO controlling /RESET, if any */ - int ldo_ena; /** GPIO controlling LODENA, if any */ int irq_flags; int gpio_defaults[4]; diff --git a/include/sound/wm5100.h b/include/sound/wm5100.h index b94badf72947..1c48090fdb2c 100644 --- a/include/sound/wm5100.h +++ b/include/sound/wm5100.h @@ -36,11 +36,7 @@ struct wm5100_jack_mode { #define WM5100_GPIO_SET 0x10000 struct wm5100_pdata { - int reset; /** GPIO controlling /RESET, if any */ - int ldo_ena; /** GPIO controlling LODENA, if any */ - int hp_pol; /** GPIO controlling headset polarity, if any */ int irq_flags; - int gpio_base; struct wm5100_jack_mode jack_modes[2]; diff --git a/include/sound/wm8904.h b/include/sound/wm8904.h index 88ac1870510e..8b2c16b524f7 100644 --- a/include/sound/wm8904.h +++ b/include/sound/wm8904.h @@ -151,6 +151,9 @@ struct wm8904_pdata { int num_retune_mobile_cfgs; struct wm8904_retune_mobile_cfg *retune_mobile_cfgs; + bool in1l_as_dmicdat1; + bool in1r_as_dmicdat2; + u32 gpio_cfg[WM8904_GPIO_REGS]; u32 mic_cfg[WM8904_MIC_REGS]; }; diff --git a/include/sound/wm8996.h b/include/sound/wm8996.h index 247f9917e33d..342abeef288f 100644 --- a/include/sound/wm8996.h +++ b/include/sound/wm8996.h @@ -33,8 +33,6 @@ struct wm8996_retune_mobile_config { struct wm8996_pdata { int irq_flags; /** Set IRQ trigger flags; default active low */ - int ldo_ena; /** GPIO for LDO1; -1 for none */ - int micdet_def; /** Default MICDET_SRC/HP1FB_SRC/MICD_BIAS */ enum wm8996_inmode inl_mode; @@ -42,7 +40,6 @@ struct wm8996_pdata { u32 spkmute_seq; /** Value for register 0x802 */ - int gpio_base; u32 gpio_default[5]; int num_retune_mobile_cfgs; |
