sound/soc/apple/mca.c
Source file repositories/reference/linux-study-clean/sound/soc/apple/mca.c
File Facts
- System
- Linux kernel
- Corpus path
sound/soc/apple/mca.c- Extension
.c- Size
- 31697 bytes
- Lines
- 1209
- Domain
- Driver Families
- Bucket
- sound/soc
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/bitfield.hlinux/clk.hlinux/dma-mapping.hlinux/init.hlinux/kernel.hlinux/module.hlinux/of.hlinux/of_clk.hlinux/of_dma.hlinux/platform_device.hlinux/pm_domain.hlinux/regmap.hlinux/reset.hlinux/slab.hsound/core.hsound/pcm.hsound/pcm_params.hsound/soc.hsound/dmaengine_pcm.h
Detected Declarations
struct mca_clusterstruct mca_datafunction mca_modifyfunction mca_fe_early_triggerfunction mca_fe_triggerfunction mca_fe_enable_clocksfunction mca_fe_disable_clocksfunction mca_fe_clocks_in_usefunction for_each_pcm_streamsfunction mca_be_preparefunction latestfunction mca_be_hw_freefunction mca_crop_maskfunction mca_configure_serdesfunction mca_fe_startupfunction mca_fe_set_tdm_slotfunction mca_fe_set_fmtfunction mca_set_bclk_ratiofunction mca_fe_get_portfunction mca_fe_hw_paramsfunction mca_be_startedfunction mca_be_startupfunction for_each_dpcm_fefunction mca_be_shutdownfunction mca_set_runtime_hwparamsfunction mca_pcm_openfunction mca_hw_paramsfunction mca_closefunction mca_triggerfunction mca_pointerfunction mca_pcm_freefunction for_each_pcm_streamsfunction mca_pcm_newfunction for_each_pcm_streamsfunction apple_mca_releasefunction apple_mca_probefunction apple_mca_remove
Annotated Snippet
struct mca_cluster {
int no;
__iomem void *base;
struct mca_data *host;
struct device *pd_dev;
struct clk *clk_parent;
struct dma_chan *dma_chans[SNDRV_PCM_STREAM_LAST + 1];
bool port_started[SNDRV_PCM_STREAM_LAST + 1];
int port_driver; /* The cluster driving this cluster's port */
bool clocks_in_use[SNDRV_PCM_STREAM_LAST + 1];
struct device_link *pd_link;
unsigned int bclk_ratio;
/* Masks etc. picked up via the set_tdm_slot method */
int tdm_slots;
int tdm_slot_width;
unsigned int tdm_tx_mask;
unsigned int tdm_rx_mask;
};
struct mca_data {
struct device *dev;
__iomem void *switch_base;
struct device *pd_dev;
struct reset_control *rstc;
struct device_link *pd_link;
/* Mutex for accessing port_driver of foreign clusters */
struct mutex port_mutex;
int nclusters;
struct mca_cluster clusters[] __counted_by(nclusters);
};
static void mca_modify(struct mca_cluster *cl, int regoffset, u32 mask, u32 val)
{
__iomem void *ptr = cl->base + regoffset;
u32 newval;
newval = (val & mask) | (readl_relaxed(ptr) & ~mask);
writel_relaxed(newval, ptr);
}
/*
* Get the cluster of FE or BE DAI
*/
static struct mca_cluster *mca_dai_to_cluster(struct snd_soc_dai *dai)
{
struct mca_data *mca = snd_soc_dai_get_drvdata(dai);
/*
* FE DAIs are 0 ... nclusters - 1
* BE DAIs are nclusters ... 2*nclusters - 1
*/
int cluster_no = dai->id % mca->nclusters;
return &mca->clusters[cluster_no];
}
/* called before PCM trigger */
static void mca_fe_early_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct mca_cluster *cl = mca_dai_to_cluster(dai);
bool is_tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
int serdes_unit = is_tx ? CLUSTER_TX_OFF : CLUSTER_RX_OFF;
int serdes_conf =
serdes_unit + (is_tx ? REG_TX_SERDES_CONF : REG_RX_SERDES_CONF);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
FIELD_PREP(SERDES_CONF_SYNC_SEL, 0));
mca_modify(cl, serdes_conf, SERDES_CONF_SYNC_SEL,
FIELD_PREP(SERDES_CONF_SYNC_SEL, 7));
mca_modify(cl, serdes_unit + REG_SERDES_STATUS,
SERDES_STATUS_EN | SERDES_STATUS_RST,
SERDES_STATUS_RST);
/*
* Experiments suggest that it takes at most ~1 us
* for the bit to clear, so wait 2 us for good measure.
*/
udelay(2);
WARN_ON(readl_relaxed(cl->base + serdes_unit + REG_SERDES_STATUS) &
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk.h`, `linux/dma-mapping.h`, `linux/init.h`, `linux/kernel.h`, `linux/module.h`, `linux/of.h`, `linux/of_clk.h`.
- Detected declarations: `struct mca_cluster`, `struct mca_data`, `function mca_modify`, `function mca_fe_early_trigger`, `function mca_fe_trigger`, `function mca_fe_enable_clocks`, `function mca_fe_disable_clocks`, `function mca_fe_clocks_in_use`, `function for_each_pcm_streams`, `function mca_be_prepare`.
- Atlas domain: Driver Families / sound/soc.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.