sound/soc/codecs/framer-codec.c

Source file repositories/reference/linux-study-clean/sound/soc/codecs/framer-codec.c

File Facts

System
Linux kernel
Corpus path
sound/soc/codecs/framer-codec.c
Extension
.c
Size
11549 bytes
Lines
412
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.

Dependency Surface

Detected Declarations

Annotated Snippet

struct framer_codec {
	struct framer *framer;
	struct device *dev;
	struct snd_soc_jack jack;
	struct notifier_block nb;
	struct work_struct carrier_work;
	int max_chan_playback;
	int max_chan_capture;
};

static int framer_dai_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
				   unsigned int rx_mask, int slots, int width)
{
	struct framer_codec *framer = snd_soc_component_get_drvdata(dai->component);

	switch (width) {
	case 0:
		/* Not set -> default 8 */
	case 8:
		break;
	default:
		dev_err(dai->dev, "tdm slot width %d not supported\n", width);
		return -EINVAL;
	}

	framer->max_chan_playback = hweight32(tx_mask);
	if (framer->max_chan_playback > FRAMER_NB_CHANNEL) {
		dev_err(dai->dev, "too many tx slots defined (mask = 0x%x) supported max %d\n",
			tx_mask, FRAMER_NB_CHANNEL);
		return -EINVAL;
	}

	framer->max_chan_capture = hweight32(rx_mask);
	if (framer->max_chan_capture > FRAMER_NB_CHANNEL) {
		dev_err(dai->dev, "too many rx slots defined (mask = 0x%x) supported max %d\n",
			rx_mask, FRAMER_NB_CHANNEL);
		return -EINVAL;
	}

	return 0;
}

/*
 * The constraints for format/channel is to match with the number of 8bit
 * time-slots available.
 */
static int framer_dai_hw_rule_channels_by_format(struct snd_soc_dai *dai,
						 struct snd_pcm_hw_params *params,
						 unsigned int nb_ts)
{
	struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
	snd_pcm_format_t format = params_format(params);
	struct snd_interval ch = {0};
	int width;

	width = snd_pcm_format_physical_width(format);
	if (width == 8 || width == 16 || width == 32 || width == 64) {
		ch.max = nb_ts * 8 / width;
	} else {
		dev_err(dai->dev, "format physical width %d not supported\n", width);
		return -EINVAL;
	}

	ch.min = ch.max ? 1 : 0;

	return snd_interval_refine(c, &ch);
}

static int framer_dai_hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params,
							  struct snd_pcm_hw_rule *rule)
{
	struct snd_soc_dai *dai = rule->private;
	struct framer_codec *framer = snd_soc_component_get_drvdata(dai->component);

	return framer_dai_hw_rule_channels_by_format(dai, params, framer->max_chan_playback);
}

static int framer_dai_hw_rule_capture_channels_by_format(struct snd_pcm_hw_params *params,
							 struct snd_pcm_hw_rule *rule)
{
	struct snd_soc_dai *dai = rule->private;
	struct framer_codec *framer = snd_soc_component_get_drvdata(dai->component);

	return framer_dai_hw_rule_channels_by_format(dai, params, framer->max_chan_capture);
}

static int framer_dai_hw_rule_format_by_channels(struct snd_soc_dai *dai,
						 struct snd_pcm_hw_params *params,
						 unsigned int nb_ts)
{

Annotation

Implementation Notes