sound/soc/sti/uniperif_player.c

Source file repositories/reference/linux-study-clean/sound/soc/sti/uniperif_player.c

File Facts

System
Linux kernel
Corpus path
sound/soc/sti/uniperif_player.c
Extension
.c
Size
31833 bytes
Lines
1144
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

if (player->underflow_enabled) {
			/* Update state to underflow */
			player->state = UNIPERIF_STATE_UNDERFLOW;

		} else {
			/* Disable interrupt so doesn't continually fire */
			SET_UNIPERIF_ITM_BCLR_FIFO_ERROR(player);

			/* Stop the player */
			snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);
		}

		ret = IRQ_HANDLED;
	}

	/* Check for dma error (overrun) */
	if (unlikely(status & UNIPERIF_ITS_DMA_ERROR_MASK(player))) {
		dev_err(player->dev, "DMA error detected\n");

		/* Disable interrupt so doesn't continually fire */
		SET_UNIPERIF_ITM_BCLR_DMA_ERROR(player);

		/* Stop the player */
		snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);

		ret = IRQ_HANDLED;
	}

	/* Check for underflow recovery done */
	if (unlikely(status & UNIPERIF_ITM_UNDERFLOW_REC_DONE_MASK(player))) {
		if (!player->underflow_enabled) {
			dev_err(player->dev,
				"unexpected Underflow recovering\n");
			ret = -EPERM;
			snd_pcm_stream_unlock(player->substream);
			return ret;
		}
		/* Read the underflow recovery duration */
		tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player);
		dev_dbg(player->dev, "Underflow recovered (%d LR clocks max)\n",
			tmp);

		/* Clear the underflow recovery duration */
		SET_UNIPERIF_BIT_CONTROL_CLR_UNDERFLOW_DURATION(player);

		/* Update state to started */
		player->state = UNIPERIF_STATE_STARTED;

		ret = IRQ_HANDLED;
	}

	/* Check if underflow recovery failed */
	if (unlikely(status &
		     UNIPERIF_ITM_UNDERFLOW_REC_FAILED_MASK(player))) {
		dev_err(player->dev, "Underflow recovery failed\n");

		/* Stop the player */
		snd_pcm_stop(player->substream, SNDRV_PCM_STATE_XRUN);

		ret = IRQ_HANDLED;
	}

	snd_pcm_stream_unlock(player->substream);

	return ret;
}

static int uni_player_clk_set_rate(struct uniperif *player, unsigned long rate)
{
	int rate_adjusted, rate_achieved, delta, ret;
	int adjustment = player->clk_adj;

	/*
	 *             a
	 * F = f + --------- * f = f + d
	 *          1000000
	 *
	 *         a
	 * d = --------- * f
	 *      1000000
	 *
	 * where:
	 *   f - nominal rate
	 *   a - adjustment in ppm (parts per milion)
	 *   F - rate to be set in synthesizer
	 *   d - delta (difference) between f and F
	 */
	if (adjustment < 0) {
		/* div64_64 operates on unsigned values... */
		delta = -1;

Annotation

Implementation Notes