sound/soc/meson/axg-spdifin.c
Source file repositories/reference/linux-study-clean/sound/soc/meson/axg-spdifin.c
File Facts
- System
- Linux kernel
- Corpus path
sound/soc/meson/axg-spdifin.c- Extension
.c- Size
- 13180 bytes
- Lines
- 497
- 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/module.hlinux/of_platform.hlinux/regmap.hsound/soc.hsound/soc-dai.hsound/pcm_params.h
Detected Declarations
struct axg_spdifin_cfgstruct axg_spdifinfunction hw_paramsfunction axg_spdifin_preparefunction axg_spdifin_write_mode_paramfunction axg_spdifin_write_timerfunction axg_spdifin_write_thresholdfunction axg_spdifin_mode_timerfunction axg_spdifin_sample_mode_configfunction axg_spdifin_dai_probefunction axg_spdifin_dai_removefunction axg_spdifin_iec958_infofunction axg_spdifin_get_status_maskfunction axg_spdifin_get_statusfunction axg_spdifin_rate_lock_infofunction axg_spdifin_rate_lock_getfunction axg_spdifin_get_dai_drvfunction axg_spdifin_probe
Annotated Snippet
struct axg_spdifin_cfg {
const unsigned int *mode_rates;
unsigned int ref_rate;
};
struct axg_spdifin {
const struct axg_spdifin_cfg *conf;
struct regmap *map;
struct clk *refclk;
struct clk *pclk;
};
/*
* TODO:
* It would have been nice to check the actual rate against the sample rate
* requested in hw_params(). Unfortunately, I was not able to make the mode
* detection and IRQ work reliably:
*
* 1. IRQs are generated on mode change only, so there is no notification
* on transition between no signal and mode 0 (32kHz).
* 2. Mode detection very often has glitches, and may detects the
* lowest or the highest mode before zeroing in on the actual mode.
*
* This makes calling snd_pcm_stop() difficult to get right. Even notifying
* the kcontrol would be very unreliable at this point.
* Let's keep things simple until the magic spell that makes this work is
* found.
*/
static unsigned int axg_spdifin_get_rate(struct axg_spdifin *priv)
{
unsigned int stat, mode, rate = 0;
regmap_read(priv->map, SPDIFIN_STAT0, &stat);
mode = FIELD_GET(SPDIFIN_STAT0_MODE, stat);
/*
* If max width is zero, we are not capturing anything.
* Also Sometimes, when the capture is on but there is no data,
* mode is SPDIFIN_MODE_NUM, but not always ...
*/
if (FIELD_GET(SPDIFIN_STAT0_MAXW, stat) &&
mode < SPDIFIN_MODE_NUM)
rate = priv->conf->mode_rates[mode];
return rate;
}
static int axg_spdifin_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct axg_spdifin *priv = snd_soc_dai_get_drvdata(dai);
/* Apply both reset */
regmap_update_bits(priv->map, SPDIFIN_CTRL0,
SPDIFIN_CTRL0_RST_OUT |
SPDIFIN_CTRL0_RST_IN,
0);
/* Clear out reset before in reset */
regmap_update_bits(priv->map, SPDIFIN_CTRL0,
SPDIFIN_CTRL0_RST_OUT, SPDIFIN_CTRL0_RST_OUT);
regmap_update_bits(priv->map, SPDIFIN_CTRL0,
SPDIFIN_CTRL0_RST_IN, SPDIFIN_CTRL0_RST_IN);
return 0;
}
static void axg_spdifin_write_mode_param(struct regmap *map, int mode,
unsigned int val,
unsigned int num_per_reg,
unsigned int base_reg,
unsigned int width)
{
uint64_t offset = mode;
unsigned int reg, shift, rem;
rem = do_div(offset, num_per_reg);
reg = offset * regmap_get_reg_stride(map) + base_reg;
shift = width * (num_per_reg - 1 - rem);
regmap_update_bits(map, reg, GENMASK(width - 1, 0) << shift,
val << shift);
}
static void axg_spdifin_write_timer(struct regmap *map, int mode,
unsigned int val)
{
axg_spdifin_write_mode_param(map, mode, val, SPDIFIN_TIMER_PER_REG,
Annotation
- Immediate include surface: `linux/bitfield.h`, `linux/clk.h`, `linux/module.h`, `linux/of_platform.h`, `linux/regmap.h`, `sound/soc.h`, `sound/soc-dai.h`, `sound/pcm_params.h`.
- Detected declarations: `struct axg_spdifin_cfg`, `struct axg_spdifin`, `function hw_params`, `function axg_spdifin_prepare`, `function axg_spdifin_write_mode_param`, `function axg_spdifin_write_timer`, `function axg_spdifin_write_threshold`, `function axg_spdifin_mode_timer`, `function axg_spdifin_sample_mode_config`, `function axg_spdifin_dai_probe`.
- 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.