ASoC: Updates for v5.7

This is a very big update for the core since Morimoto-san has been
rather busy continuing his refactorings to clean up a lot of the cruft
that we have accumilated over the years.  We've also gained several new
drivers, including initial (but still not complete) parts of the Intel
SoundWire support.

 - Lots of refactorings to modernize the code from Morimoto-san.
 - Conversion of SND_SOC_ALL_CODECS to use imply from Geert Uytterhoeven.
 - Continued refactoring and fixing of the Intel support.
 - Soundwire and more advanced clocking support for Realtek RT5682.
 - Support for amlogic GX, Meson 8, Meson 8B and T9015 DAC, Broadcom
   DSL/PON, Ingenic JZ4760 and JZ4770, Realtek RL6231, and TI TAS2563 and
   TLV320ADCX140.
This commit is contained in:
Takashi Iwai
2020-03-30 13:43:00 +02:00
1917 changed files with 39331 additions and 17486 deletions

View File

@@ -23,7 +23,6 @@ struct snd_compr_ops;
* struct snd_compr_runtime: runtime stream description
* @state: stream state
* @ops: pointer to DSP callbacks
* @dma_buffer_p: runtime dma buffer pointer
* @buffer: pointer to kernel buffer, valid only when not in mmap mode or
* DSP doesn't implement copy
* @buffer_size: size of the above buffer
@@ -34,11 +33,14 @@ struct snd_compr_ops;
* @total_bytes_transferred: cumulative bytes transferred by offload DSP
* @sleep: poll sleep
* @private_data: driver private data pointer
* @dma_area: virtual buffer address
* @dma_addr: physical buffer address (not accessible from main CPU)
* @dma_bytes: size of DMA area
* @dma_buffer_p: runtime dma buffer pointer
*/
struct snd_compr_runtime {
snd_pcm_state_t state;
struct snd_compr_ops *ops;
struct snd_dma_buffer *dma_buffer_p;
void *buffer;
u64 buffer_size;
u32 fragment_size;
@@ -47,6 +49,11 @@ struct snd_compr_runtime {
u64 total_bytes_transferred;
wait_queue_head_t sleep;
void *private_data;
unsigned char *dma_area;
dma_addr_t dma_addr;
size_t dma_bytes;
struct snd_dma_buffer *dma_buffer_p;
};
/**
@@ -60,6 +67,7 @@ struct snd_compr_runtime {
* @metadata_set: metadata set flag, true when set
* @next_track: has userspace signal next track transition, true when set
* @private_data: pointer to DSP private data
* @dma_buffer: allocated buffer if any
*/
struct snd_compr_stream {
const char *name;
@@ -71,6 +79,7 @@ struct snd_compr_stream {
bool metadata_set;
bool next_track;
void *private_data;
struct snd_dma_buffer dma_buffer;
};
/**
@@ -180,21 +189,34 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
/**
* snd_compr_set_runtime_buffer - Set the Compress runtime buffer
* @substream: compress substream to set
* @stream: compress stream to set
* @bufp: the buffer information, NULL to clear
*
* Copy the buffer information to runtime buffer when @bufp is non-NULL.
* Otherwise it clears the current buffer information.
*/
static inline void snd_compr_set_runtime_buffer(
struct snd_compr_stream *substream,
struct snd_dma_buffer *bufp)
static inline void
snd_compr_set_runtime_buffer(struct snd_compr_stream *stream,
struct snd_dma_buffer *bufp)
{
struct snd_compr_runtime *runtime = substream->runtime;
struct snd_compr_runtime *runtime = stream->runtime;
runtime->dma_buffer_p = bufp;
if (bufp) {
runtime->dma_buffer_p = bufp;
runtime->dma_area = bufp->area;
runtime->dma_addr = bufp->addr;
runtime->dma_bytes = bufp->bytes;
} else {
runtime->dma_buffer_p = NULL;
runtime->dma_area = NULL;
runtime->dma_addr = 0;
runtime->dma_bytes = 0;
}
}
int snd_compr_malloc_pages(struct snd_compr_stream *stream, size_t size);
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);

View File

@@ -513,6 +513,7 @@ struct hdac_stream {
struct snd_pcm_substream *substream; /* assigned substream,
* set in PCM open
*/
struct snd_compr_stream *cstream;
unsigned int format_val; /* format value to be set in the
* controller and the codec
*/
@@ -527,6 +528,7 @@ struct hdac_stream {
bool locked:1;
bool stripe:1; /* apply stripe control */
u64 curr_pos;
/* timestamp */
unsigned long start_wallclk; /* start + minimum wallclk */
unsigned long period_wallclk; /* wallclk for period */

View File

@@ -644,6 +644,11 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream,
#define snd_pcm_group_for_each_entry(s, substream) \
list_for_each_entry(s, &substream->group->substreams, link_list)
#define for_each_pcm_streams(stream) \
for (stream = SNDRV_PCM_STREAM_PLAYBACK; \
stream <= SNDRV_PCM_STREAM_LAST; \
stream++)
/**
* snd_pcm_running - Check whether the substream is in a running state
* @substream: substream to check
@@ -1122,7 +1127,14 @@ snd_pcm_kernel_readv(struct snd_pcm_substream *substream,
return __snd_pcm_lib_xfer(substream, bufs, false, frames, true);
}
int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime);
int snd_pcm_hw_limit_rates(struct snd_pcm_hardware *hw);
static inline int
snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime)
{
return snd_pcm_hw_limit_rates(&runtime->hw);
}
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,

View File

@@ -24,6 +24,12 @@ enum rt5682_jd_src {
RT5682_JD1,
};
enum rt5682_dai_clks {
RT5682_DAI_WCLK_IDX,
RT5682_DAI_BCLK_IDX,
RT5682_DAI_NUM_CLKS,
};
struct rt5682_platform_data {
int ldo1_en; /* GPIO for LDO1_EN */
@@ -32,6 +38,10 @@ struct rt5682_platform_data {
enum rt5682_dmic1_clk_pin dmic1_clk_pin;
enum rt5682_jd_src jd_src;
unsigned int btndet_delay;
unsigned int dmic_clk_rate;
unsigned int dmic_delay;
const char *dai_clk_names[RT5682_DAI_NUM_CLKS];
};
#endif

View File

@@ -75,18 +75,45 @@ struct snd_soc_acpi_mach_params {
};
/**
* snd_soc_acpi_link_adr: ACPI-based list of _ADR, with a variable
* number of devices per link
*
* snd_soc_acpi_endpoint - endpoint descriptor
* @num: endpoint number (mandatory, unique per device)
* @aggregated: 0 (independent) or 1 (logically grouped)
* @group_position: zero-based order (only when @aggregated is 1)
* @group_id: platform-unique group identifier (only when @aggregrated is 1)
*/
struct snd_soc_acpi_endpoint {
u8 num;
u8 aggregated;
u8 group_position;
u8 group_id;
};
/**
* snd_soc_acpi_adr_device - descriptor for _ADR-enumerated device
* @adr: 64 bit ACPI _ADR value
* @num_endpoints: number of endpoints for this device
* @endpoints: array of endpoints
*/
struct snd_soc_acpi_adr_device {
const u64 adr;
const u8 num_endpoints;
const struct snd_soc_acpi_endpoint *endpoints;
};
/**
* snd_soc_acpi_link_adr - ACPI-based list of _ADR enumerated devices
* @mask: one bit set indicates the link this list applies to
* @num_adr: ARRAY_SIZE of adr
* @adr: array of _ADR (represented as u64).
* @num_adr: ARRAY_SIZE of devices
* @adr_d: array of devices
*
* The number of devices per link can be more than 1, e.g. in SoundWire
* multi-drop configurations.
*/
struct snd_soc_acpi_link_adr {
const u32 mask;
const u32 num_adr;
const u64 *adr;
const struct snd_soc_acpi_adr_device *adr_d;
};
/**

View File

@@ -202,6 +202,8 @@ struct snd_soc_dai_ops {
int (*set_sdw_stream)(struct snd_soc_dai *dai,
void *stream, int direction);
void *(*get_sdw_stream)(struct snd_soc_dai *dai, int direction);
/*
* DAI digital mute - optional.
* Called by soc-core to minimise any pops.
@@ -322,9 +324,7 @@ struct snd_soc_dai {
struct snd_soc_dai_driver *driver;
/* DAI runtime info */
unsigned int capture_active; /* stream usage count */
unsigned int playback_active; /* stream usage count */
unsigned int probed:1;
unsigned int stream_active[SNDRV_PCM_STREAM_LAST + 1]; /* usage count */
unsigned int active;
@@ -348,8 +348,27 @@ struct snd_soc_dai {
unsigned int rx_mask;
struct list_head list;
/* bit field */
unsigned int probed:1;
unsigned int started:1;
};
static inline 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) ?
&dai->driver->playback : &dai->driver->capture;
}
static inline
struct snd_soc_dapm_widget *snd_soc_dai_get_widget(
struct snd_soc_dai *dai, int stream)
{
return (stream == SNDRV_PCM_STREAM_PLAYBACK) ?
dai->playback_widget : dai->capture_widget;
}
static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai,
const struct snd_pcm_substream *ss)
{
@@ -406,4 +425,23 @@ static inline int snd_soc_dai_set_sdw_stream(struct snd_soc_dai *dai,
return -ENOTSUPP;
}
/**
* snd_soc_dai_get_sdw_stream() - Retrieves SDW stream from DAI
* @dai: DAI
* @direction: Stream direction(Playback/Capture)
*
* This routine only retrieves that was previously configured
* with snd_soc_dai_get_sdw_stream()
*
* Returns pointer to stream or -ENOTSUPP if callback is not supported;
*/
static inline void *snd_soc_dai_get_sdw_stream(struct snd_soc_dai *dai,
int direction)
{
if (dai->driver->ops->get_sdw_stream)
return dai->driver->ops->get_sdw_stream(dai, direction);
else
return ERR_PTR(-ENOTSUPP);
}
#endif

View File

@@ -482,6 +482,7 @@ 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);
@@ -691,6 +692,11 @@ struct snd_soc_dapm_widget_list {
struct snd_soc_dapm_widget *widgets[0];
};
#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;

View File

@@ -132,17 +132,8 @@ int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe,
struct snd_pcm_substream *
snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream);
/* get the BE runtime state */
enum snd_soc_dpcm_state
snd_soc_dpcm_be_get_state(struct snd_soc_pcm_runtime *be, int stream);
/* set the BE runtime state */
void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream,
enum snd_soc_dpcm_state state);
/* internal use only */
int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute);
int soc_dpcm_runtime_update(struct snd_soc_card *);
/* update audio routing between PCMs and any DAI links */
int snd_soc_dpcm_runtime_update(struct snd_soc_card *card);
#ifdef CONFIG_DEBUG_FS
void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd);
@@ -154,6 +145,7 @@ 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_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream);
@@ -167,10 +159,4 @@ 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);
static inline void dpcm_path_put(struct snd_soc_dapm_widget_list **list)
{
kfree(*list);
}
#endif

View File

@@ -471,6 +471,9 @@ bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd);
void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream);
void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream);
int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hardware *hw, int stream);
int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd,
unsigned int dai_fmt);
@@ -855,6 +858,11 @@ struct snd_soc_dai_link {
((platform) = &link->platforms[i]); \
(i)++)
#define for_each_link_cpus(link, i, cpu) \
for ((i) = 0; \
((i) < link->num_cpus) && ((cpu) = &link->cpus[i]); \
(i)++)
/*
* Sample 1 : Single CPU/Codec/Platform
*
@@ -1058,6 +1066,7 @@ struct snd_soc_card {
const struct snd_soc_dapm_route *of_dapm_routes;
int num_of_dapm_routes;
bool fully_routed;
bool disable_route_checks;
/* lists of probed devices belonging to this card */
struct list_head component_dev_list;
@@ -1109,6 +1118,14 @@ struct snd_soc_card {
#define for_each_card_components(card, component) \
list_for_each_entry(component, &(card)->component_dev_list, card_list)
#define for_each_card_dapms(card, dapm) \
list_for_each_entry(dapm, &card->dapm_list, list)
#define for_each_card_widgets(card, w)\
list_for_each_entry(w, &card->widgets, list)
#define for_each_card_widgets_safe(card, w, _w) \
list_for_each_entry_safe(w, _w, &card->widgets, list)
/* SoC machine DAI configuration, glues a codec and cpu DAI together */
struct snd_soc_pcm_runtime {
struct device *dev;
@@ -1128,10 +1145,14 @@ struct snd_soc_pcm_runtime {
struct snd_compr *compr;
struct snd_soc_dai *codec_dai;
struct snd_soc_dai *cpu_dai;
struct snd_soc_dai **dais;
struct snd_soc_dai **codec_dais;
unsigned int num_codecs;
struct snd_soc_dai **cpu_dais;
unsigned int num_cpus;
struct delayed_work delayed_work;
void (*close_delayed_work_func)(struct snd_soc_pcm_runtime *rtd);
#ifdef CONFIG_DEBUG_FS
@@ -1148,16 +1169,31 @@ struct snd_soc_pcm_runtime {
int num_components;
struct snd_soc_component *components[0]; /* CPU/Codec/Platform */
};
/* 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)->num_cpus]
#define for_each_rtd_components(rtd, i, component) \
for ((i) = 0; \
((i) < rtd->num_components) && ((component) = rtd->components[i]);\
(i)++)
#define for_each_rtd_codec_dai(rtd, i, dai)\
for ((i) = 0; \
((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \
#define for_each_rtd_cpu_dais(rtd, i, dai) \
for ((i) = 0; \
((i) < rtd->num_cpus) && ((dai) = rtd->cpu_dais[i]); \
(i)++)
#define for_each_rtd_codec_dai_rollback(rtd, i, dai) \
#define for_each_rtd_cpu_dais_rollback(rtd, i, dai) \
for (; (--(i) >= 0) && ((dai) = rtd->cpu_dais[i]);)
#define for_each_rtd_codec_dais(rtd, i, dai) \
for ((i) = 0; \
((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \
(i)++)
#define for_each_rtd_codec_dais_rollback(rtd, i, dai) \
for (; (--(i) >= 0) && ((dai) = rtd->codec_dais[i]);)
#define for_each_rtd_dais(rtd, i, dai) \
for ((i) = 0; \
((i) < (rtd)->num_cpus + (rtd)->num_codecs) && \
((dai) = (rtd)->dais[i]); \
(i)++)
void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd);

View File

@@ -87,6 +87,15 @@ struct sof_ipc_dai_hda_params {
uint32_t link_dma_ch;
} __packed;
/* ALH Configuration Request - SOF_IPC_DAI_ALH_CONFIG */
struct sof_ipc_dai_alh_params {
struct sof_ipc_hdr hdr;
uint32_t stream_id;
/* reserved for future use */
uint32_t reserved[15];
} __packed;
/* DMIC Configuration Request - SOF_IPC_DAI_DMIC_CONFIG */
/* This struct is defined per 2ch PDM controller available in the platform.
@@ -179,13 +188,4 @@ struct sof_ipc_dai_dmic_params {
struct sof_ipc_dai_dmic_pdm_ctrl pdm[0];
} __packed;
/* ALH Configuration Request - SOF_IPC_DAI_ALH_CONFIG */
struct sof_ipc_dai_alh_params {
struct sof_ipc_hdr hdr;
uint32_t stream_id;
/* reserved for future use */
uint32_t reserved[15];
} __packed;
#endif

View File

@@ -51,6 +51,7 @@
#define SOF_IPC_GLB_TRACE_MSG SOF_GLB_TYPE(0x9U)
#define SOF_IPC_GLB_GDB_DEBUG SOF_GLB_TYPE(0xAU)
#define SOF_IPC_GLB_TEST_MSG SOF_GLB_TYPE(0xBU)
#define SOF_IPC_GLB_PROBE SOF_GLB_TYPE(0xCU)
/*
* DSP Command Message Types
@@ -102,6 +103,16 @@
#define SOF_IPC_STREAM_VORBIS_PARAMS SOF_CMD_TYPE(0x010)
#define SOF_IPC_STREAM_VORBIS_FREE SOF_CMD_TYPE(0x011)
/* probe */
#define SOF_IPC_PROBE_INIT SOF_CMD_TYPE(0x001)
#define SOF_IPC_PROBE_DEINIT SOF_CMD_TYPE(0x002)
#define SOF_IPC_PROBE_DMA_ADD SOF_CMD_TYPE(0x003)
#define SOF_IPC_PROBE_DMA_INFO SOF_CMD_TYPE(0x004)
#define SOF_IPC_PROBE_DMA_REMOVE SOF_CMD_TYPE(0x005)
#define SOF_IPC_PROBE_POINT_ADD SOF_CMD_TYPE(0x006)
#define SOF_IPC_PROBE_POINT_INFO SOF_CMD_TYPE(0x007)
#define SOF_IPC_PROBE_POINT_REMOVE SOF_CMD_TYPE(0x008)
/* trace */
#define SOF_IPC_TRACE_DMA_PARAMS SOF_CMD_TYPE(0x001)
#define SOF_IPC_TRACE_DMA_POSITION SOF_CMD_TYPE(0x002)

View File

@@ -28,9 +28,9 @@
/* extended data types that can be appended onto end of sof_ipc_fw_ready */
enum sof_ipc_ext_data {
SOF_IPC_EXT_DMA_BUFFER = 0,
SOF_IPC_EXT_WINDOW,
SOF_IPC_EXT_CC_INFO,
SOF_IPC_EXT_UNUSED = 0,
SOF_IPC_EXT_WINDOW = 1,
SOF_IPC_EXT_CC_INFO = 2,
};
/* FW version - SOF_IPC_GLB_VERSION */
@@ -83,22 +83,6 @@ struct sof_ipc_ext_data_hdr {
uint32_t type; /**< SOF_IPC_EXT_ */
} __packed;
struct sof_ipc_dma_buffer_elem {
struct sof_ipc_hdr hdr;
uint32_t type; /**< SOF_IPC_REGION_ */
uint32_t id; /**< platform specific - used to map to host memory */
struct sof_ipc_host_buffer buffer;
} __packed;
/* extended data DMA buffers for IPC, trace and debug */
struct sof_ipc_dma_buffer_data {
struct sof_ipc_ext_data_hdr ext_hdr;
uint32_t num_buffers;
/* host files in buffer[n].buffer */
struct sof_ipc_dma_buffer_elem buffer[];
} __packed;
struct sof_ipc_window_elem {
struct sof_ipc_hdr hdr;
uint32_t type; /**< SOF_IPC_REGION_ */

View File

@@ -53,9 +53,10 @@ struct sof_ipc_comp {
uint32_t id;
enum sof_comp_type type;
uint32_t pipeline_id;
uint32_t core;
/* reserved for future use */
uint32_t reserved[2];
uint32_t reserved[1];
} __packed;
/*