sound/isa/ad1816a/ad1816a_lib.c

Source file repositories/reference/linux-study-clean/sound/isa/ad1816a/ad1816a_lib.c

File Facts

System
Linux kernel
Corpus path
sound/isa/ad1816a/ad1816a_lib.c
Extension
.c
Size
27676 bytes
Lines
881
Domain
Driver Families
Bucket
sound/isa
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

scoped_guard(spinlock, &chip->lock) {
			cmd = (cmd == SNDRV_PCM_TRIGGER_START) ? 0xff: 0x00;
			/* if (what & AD1816A_PLAYBACK_ENABLE) */
			/* That is not valid, because playback and capture enable
			 * are the same bit pattern, just to different addresses
			 */
			if (!iscapture)
				snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG,
						     AD1816A_PLAYBACK_ENABLE, cmd);
			else
				snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG,
						     AD1816A_CAPTURE_ENABLE, cmd);
		}
		break;
	default:
		dev_warn(chip->card->dev, "invalid trigger mode 0x%x.\n", what);
		error = -EINVAL;
	}

	return error;
}

static int snd_ad1816a_playback_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
	return snd_ad1816a_trigger(chip, AD1816A_PLAYBACK_ENABLE,
				   SNDRV_PCM_STREAM_PLAYBACK, cmd, 0);
}

static int snd_ad1816a_capture_trigger(struct snd_pcm_substream *substream, int cmd)
{
	struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
	return snd_ad1816a_trigger(chip, AD1816A_CAPTURE_ENABLE,
				   SNDRV_PCM_STREAM_CAPTURE, cmd, 1);
}

static int snd_ad1816a_playback_prepare(struct snd_pcm_substream *substream)
{
	struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
	struct snd_pcm_runtime *runtime = substream->runtime;
	unsigned int size, rate;

	guard(spinlock_irqsave)(&chip->lock);

	chip->p_dma_size = size = snd_pcm_lib_buffer_bytes(substream);
	snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG,
		AD1816A_PLAYBACK_ENABLE | AD1816A_PLAYBACK_PIO, 0x00);

	snd_dma_program(chip->dma1, runtime->dma_addr, size,
			DMA_MODE_WRITE | DMA_AUTOINIT);

	rate = runtime->rate;
	if (chip->clock_freq)
		rate = (rate * 33000) / chip->clock_freq;
	snd_ad1816a_write(chip, AD1816A_PLAYBACK_SAMPLE_RATE, rate);
	snd_ad1816a_out_mask(chip, AD1816A_PLAYBACK_CONFIG,
		AD1816A_FMT_ALL | AD1816A_FMT_STEREO,
		snd_ad1816a_get_format(chip, runtime->format,
			runtime->channels));

	snd_ad1816a_write(chip, AD1816A_PLAYBACK_BASE_COUNT,
		snd_pcm_lib_period_bytes(substream) / 4 - 1);
	return 0;
}

static int snd_ad1816a_capture_prepare(struct snd_pcm_substream *substream)
{
	struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
	struct snd_pcm_runtime *runtime = substream->runtime;
	unsigned int size, rate;

	guard(spinlock_irqsave)(&chip->lock);

	chip->c_dma_size = size = snd_pcm_lib_buffer_bytes(substream);
	snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG,
		AD1816A_CAPTURE_ENABLE | AD1816A_CAPTURE_PIO, 0x00);

	snd_dma_program(chip->dma2, runtime->dma_addr, size,
			DMA_MODE_READ | DMA_AUTOINIT);

	rate = runtime->rate;
	if (chip->clock_freq)
		rate = (rate * 33000) / chip->clock_freq;
	snd_ad1816a_write(chip, AD1816A_CAPTURE_SAMPLE_RATE, rate);
	snd_ad1816a_out_mask(chip, AD1816A_CAPTURE_CONFIG,
		AD1816A_FMT_ALL | AD1816A_FMT_STEREO,
		snd_ad1816a_get_format(chip, runtime->format,
			runtime->channels));

	snd_ad1816a_write(chip, AD1816A_CAPTURE_BASE_COUNT,

Annotation

Implementation Notes