sound/soc/renesas/ssi.c

Source file repositories/reference/linux-study-clean/sound/soc/renesas/ssi.c

File Facts

System
Linux kernel
Corpus path
sound/soc/renesas/ssi.c
Extension
.c
Size
10196 bytes
Lines
404
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 ssi_priv {
	unsigned long mmio;
	unsigned long sysclk;
	int inuse;
} ssi_cpu_data[] = {
#if defined(CONFIG_CPU_SUBTYPE_SH7760)
	{
		.mmio	= 0xFE680000,
	},
	{
		.mmio	= 0xFE690000,
	},
#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
	{
		.mmio	= 0xFFE70000,
	},
#else
#error "Unsupported SuperH SoC"
#endif
};

/*
 * track usage of the SSI; it is simplex-only so prevent attempts of
 * concurrent playback + capture. FIXME: any locking required?
 */
static int ssi_startup(struct snd_pcm_substream *substream,
		       struct snd_soc_dai *dai)
{
	struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
	if (ssi->inuse) {
		pr_debug("ssi: already in use!\n");
		return -EBUSY;
	} else
		ssi->inuse = 1;
	return 0;
}

static void ssi_shutdown(struct snd_pcm_substream *substream,
			 struct snd_soc_dai *dai)
{
	struct ssi_priv *ssi = &ssi_cpu_data[dai->id];

	ssi->inuse = 0;
}

static int ssi_trigger(struct snd_pcm_substream *substream, int cmd,
		       struct snd_soc_dai *dai)
{
	struct ssi_priv *ssi = &ssi_cpu_data[dai->id];

	switch (cmd) {
	case SNDRV_PCM_TRIGGER_START:
		SSIREG(SSICR) |= CR_DMAEN | CR_EN;
		break;
	case SNDRV_PCM_TRIGGER_STOP:
		SSIREG(SSICR) &= ~(CR_DMAEN | CR_EN);
		break;
	default:
		return -EINVAL;
	}

	return 0;
}

static int ssi_hw_params(struct snd_pcm_substream *substream,
			 struct snd_pcm_hw_params *params,
			 struct snd_soc_dai *dai)
{
	struct ssi_priv *ssi = &ssi_cpu_data[dai->id];
	unsigned long ssicr = SSIREG(SSICR);
	unsigned int bits, channels, swl, recv, i;

	channels = params_channels(params);
	bits = params->msbits;
	recv = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 0 : 1;

	pr_debug("ssi_hw_params() enter\nssicr was    %08lx\n", ssicr);
	pr_debug("bits: %u channels: %u\n", bits, channels);

	ssicr &= ~(CR_TRMD | CR_CHNL_MASK | CR_DWL_MASK | CR_PDTA |
		   CR_SWL_MASK);

	/* direction (send/receive) */
	if (!recv)
		ssicr |= CR_TRMD;	/* transmit */

	/* channels */
	if ((channels < 2) || (channels > 8) || (channels & 1)) {
		pr_debug("ssi: invalid number of channels\n");
		return -EINVAL;

Annotation

Implementation Notes