sound/soc/fsl/fsl_audmix.c
Source file repositories/reference/linux-study-clean/sound/soc/fsl/fsl_audmix.c
File Facts
- System
- Linux kernel
- Corpus path
sound/soc/fsl/fsl_audmix.c- Extension
.c- Size
- 16319 bytes
- Lines
- 579
- 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.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- 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/clk.hlinux/module.hlinux/of_platform.hlinux/pm_runtime.hsound/soc.hsound/pcm_params.hfsl_audmix.h
Detected Declarations
struct fsl_audmix_statefunction fsl_audmix_state_transfunction fsl_audmix_put_mix_clk_srcfunction fsl_audmix_put_out_srcfunction fsl_audmix_dai_set_fmtfunction fsl_audmix_dai_triggerfunction fsl_audmix_readable_regfunction fsl_audmix_writeable_regfunction fsl_audmix_probefunction fsl_audmix_removefunction fsl_audmix_runtime_resumefunction fsl_audmix_runtime_suspend
Annotated Snippet
struct fsl_audmix_state {
u8 tdms;
u8 clk;
char msg[64];
};
static const struct fsl_audmix_state prms[4][4] = {{
/* DIS->DIS, do nothing */
{ .tdms = 0, .clk = 0, .msg = "" },
/* DIS->TDM1*/
{ .tdms = 1, .clk = 1, .msg = "DIS->TDM1: TDM1 not started!\n" },
/* DIS->TDM2*/
{ .tdms = 2, .clk = 2, .msg = "DIS->TDM2: TDM2 not started!\n" },
/* DIS->MIX */
{ .tdms = 3, .clk = 0, .msg = "DIS->MIX: Please start both TDMs!\n" }
}, { /* TDM1->DIS */
{ .tdms = 1, .clk = 0, .msg = "TDM1->DIS: TDM1 not started!\n" },
/* TDM1->TDM1, do nothing */
{ .tdms = 0, .clk = 0, .msg = "" },
/* TDM1->TDM2 */
{ .tdms = 3, .clk = 2, .msg = "TDM1->TDM2: Please start both TDMs!\n" },
/* TDM1->MIX */
{ .tdms = 3, .clk = 0, .msg = "TDM1->MIX: Please start both TDMs!\n" }
}, { /* TDM2->DIS */
{ .tdms = 2, .clk = 0, .msg = "TDM2->DIS: TDM2 not started!\n" },
/* TDM2->TDM1 */
{ .tdms = 3, .clk = 1, .msg = "TDM2->TDM1: Please start both TDMs!\n" },
/* TDM2->TDM2, do nothing */
{ .tdms = 0, .clk = 0, .msg = "" },
/* TDM2->MIX */
{ .tdms = 3, .clk = 0, .msg = "TDM2->MIX: Please start both TDMs!\n" }
}, { /* MIX->DIS */
{ .tdms = 3, .clk = 0, .msg = "MIX->DIS: Please start both TDMs!\n" },
/* MIX->TDM1 */
{ .tdms = 3, .clk = 1, .msg = "MIX->TDM1: Please start both TDMs!\n" },
/* MIX->TDM2 */
{ .tdms = 3, .clk = 2, .msg = "MIX->TDM2: Please start both TDMs!\n" },
/* MIX->MIX, do nothing */
{ .tdms = 0, .clk = 0, .msg = "" }
}, };
static int fsl_audmix_state_trans(struct snd_soc_component *comp,
unsigned int *mask, unsigned int *ctr,
const struct fsl_audmix_state prm)
{
struct fsl_audmix *priv = snd_soc_component_get_drvdata(comp);
/* Enforce all required TDMs are started */
if ((priv->tdms & prm.tdms) != prm.tdms) {
dev_dbg(comp->dev, "%s", prm.msg);
return -EINVAL;
}
switch (prm.clk) {
case 1:
case 2:
/* Set mix clock */
(*mask) |= FSL_AUDMIX_CTR_MIXCLK_MASK;
(*ctr) |= FSL_AUDMIX_CTR_MIXCLK(prm.clk - 1);
break;
default:
break;
}
return 0;
}
static int fsl_audmix_put_mix_clk_src(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
struct fsl_audmix *priv = snd_soc_component_get_drvdata(comp);
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int *item = ucontrol->value.enumerated.item;
unsigned int reg_val, val, mix_clk;
if (item[0] >= e->items)
return -EINVAL;
/* Get current state */
reg_val = snd_soc_component_read(comp, FSL_AUDMIX_CTR);
mix_clk = ((reg_val & FSL_AUDMIX_CTR_MIXCLK_MASK)
>> FSL_AUDMIX_CTR_MIXCLK_SHIFT);
val = snd_soc_enum_item_to_val(e, item[0]);
dev_dbg(comp->dev, "TDMs=x%08x, val=x%08x\n", priv->tdms, val);
/**
* Ensure the current selected mixer clock is available
* for configuration propagation
*/
Annotation
- Immediate include surface: `linux/clk.h`, `linux/module.h`, `linux/of_platform.h`, `linux/pm_runtime.h`, `sound/soc.h`, `sound/pcm_params.h`, `fsl_audmix.h`.
- Detected declarations: `struct fsl_audmix_state`, `function fsl_audmix_state_trans`, `function fsl_audmix_put_mix_clk_src`, `function fsl_audmix_put_out_src`, `function fsl_audmix_dai_set_fmt`, `function fsl_audmix_dai_trigger`, `function fsl_audmix_readable_reg`, `function fsl_audmix_writeable_reg`, `function fsl_audmix_probe`, `function fsl_audmix_remove`.
- Atlas domain: Driver Families / sound/soc.
- Implementation status: source implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
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.