sound/soc/atmel/mchp-spdifrx.c

Source file repositories/reference/linux-study-clean/sound/soc/atmel/mchp-spdifrx.c

File Facts

System
Linux kernel
Corpus path
sound/soc/atmel/mchp-spdifrx.c
Extension
.c
Size
33019 bytes
Lines
1211
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 mchp_spdifrx_ch_stat {
	unsigned char data[SPDIFRX_CS_BITS / 8];
	struct completion done;
};

/**
 * struct mchp_spdifrx_user_data: MCHP SPDIFRX user data
 * @data: user data bits
 * @done: completion to signal user data bits acquisition done
 */
struct mchp_spdifrx_user_data {
	unsigned char data[SPDIFRX_UD_BITS / 8];
	struct completion done;
};

/**
 * struct mchp_spdifrx_mixer_control: MCHP SPDIFRX mixer control data structure
 * @ch_stat: array of channel statuses
 * @user_data: array of user data
 * @ulock: ulock bit status
 * @badf: badf bit status
 * @signal: signal bit status
 */
struct mchp_spdifrx_mixer_control {
	struct mchp_spdifrx_ch_stat ch_stat[SPDIFRX_CHANNELS];
	struct mchp_spdifrx_user_data user_data[SPDIFRX_CHANNELS];
	bool ulock;
	bool badf;
	bool signal;
};

/**
 * struct mchp_spdifrx_dev: MCHP SPDIFRX device data structure
 * @capture: DAI DMA configuration data
 * @control: mixer controls
 * @mlock: mutex to protect concurency b/w configuration and control APIs
 * @dev: struct device
 * @regmap: regmap for this device
 * @pclk: peripheral clock
 * @gclk: generic clock
 * @trigger_enabled: true if enabled though trigger() ops
 */
struct mchp_spdifrx_dev {
	struct snd_dmaengine_dai_dma_data	capture;
	struct mchp_spdifrx_mixer_control	control;
	struct mutex				mlock;
	struct device				*dev;
	struct regmap				*regmap;
	struct clk				*pclk;
	struct clk				*gclk;
	unsigned int				trigger_enabled;
};

static void mchp_spdifrx_channel_status_read(struct mchp_spdifrx_dev *dev,
					     int channel)
{
	struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
	u8 *ch_stat = &ctrl->ch_stat[channel].data[0];
	u32 val;
	int i;

	for (i = 0; i < ARRAY_SIZE(ctrl->ch_stat[channel].data) / 4; i++) {
		regmap_read(dev->regmap, SPDIFRX_CHSR(channel, i), &val);
		*ch_stat++ = FIELD_GET(SPDIFRX_BYTE_0_MASK, val);
		*ch_stat++ = FIELD_GET(SPDIFRX_BYTE_1_MASK, val);
		*ch_stat++ = FIELD_GET(SPDIFRX_BYTE_2_MASK, val);
		*ch_stat++ = FIELD_GET(SPDIFRX_BYTE_3_MASK, val);
	}
}

static void mchp_spdifrx_channel_user_data_read(struct mchp_spdifrx_dev *dev,
						int channel)
{
	struct mchp_spdifrx_mixer_control *ctrl = &dev->control;
	u8 *user_data = &ctrl->user_data[channel].data[0];
	u32 val;
	int i;

	for (i = 0; i < ARRAY_SIZE(ctrl->user_data[channel].data) / 4; i++) {
		regmap_read(dev->regmap, SPDIFRX_CHUD(channel, i), &val);
		*user_data++ = FIELD_GET(SPDIFRX_BYTE_0_MASK, val);
		*user_data++ = FIELD_GET(SPDIFRX_BYTE_1_MASK, val);
		*user_data++ = FIELD_GET(SPDIFRX_BYTE_2_MASK, val);
		*user_data++ = FIELD_GET(SPDIFRX_BYTE_3_MASK, val);
	}
}

static irqreturn_t mchp_spdif_interrupt(int irq, void *dev_id)
{
	struct mchp_spdifrx_dev *dev = dev_id;

Annotation

Implementation Notes