drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
Extension
.c
Size
17095 bytes
Lines
661
Domain
Driver Families
Bucket
drivers/gpu
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 dw_hdmi_channel_conf {
	u8 conf1;
	u8 ca;
};

/*
 * The default mapping of ALSA channels to HDMI channels and speaker
 * allocation bits.  Note that we can't do channel remapping here -
 * channels must be in the same order.
 *
 * Mappings for alsa-lib pcm/surround*.conf files:
 *
 *		Front	Sur4.0	Sur4.1	Sur5.0	Sur5.1	Sur7.1
 * Channels	2	4	6	6	6	8
 *
 * Our mapping from ALSA channel to CEA686D speaker name and HDMI channel:
 *
 *				Number of ALSA channels
 * ALSA Channel	2	3	4	5	6	7	8
 * 0		FL:0	=	=	=	=	=	=
 * 1		FR:1	=	=	=	=	=	=
 * 2			FC:3	RL:4	LFE:2	=	=	=
 * 3				RR:5	RL:4	FC:3	=	=
 * 4					RR:5	RL:4	=	=
 * 5						RR:5	=	=
 * 6							RC:6	=
 * 7							RLC/FRC	RLC/FRC
 */
static struct dw_hdmi_channel_conf default_hdmi_channel_config[7] = {
	{ 0x03, 0x00 },	/* FL,FR */
	{ 0x0b, 0x02 },	/* FL,FR,FC */
	{ 0x33, 0x08 },	/* FL,FR,RL,RR */
	{ 0x37, 0x09 },	/* FL,FR,LFE,RL,RR */
	{ 0x3f, 0x0b },	/* FL,FR,LFE,FC,RL,RR */
	{ 0x7f, 0x0f },	/* FL,FR,LFE,FC,RL,RR,RC */
	{ 0xff, 0x13 },	/* FL,FR,LFE,FC,RL,RR,[FR]RC,[FR]LC */
};

struct snd_dw_hdmi {
	struct snd_card *card;
	struct snd_pcm *pcm;
	spinlock_t lock;
	struct dw_hdmi_audio_data data;
	struct snd_pcm_substream *substream;
	void (*reformat)(struct snd_dw_hdmi *, size_t, size_t);
	void *buf_src;
	void *buf_dst;
	dma_addr_t buf_addr;
	unsigned buf_offset;
	unsigned buf_period;
	unsigned buf_size;
	unsigned channels;
	u8 revision;
	u8 iec_offset;
	u8 cs[192][8];
};

static void dw_hdmi_writel(u32 val, void __iomem *ptr)
{
	writeb_relaxed(val, ptr);
	writeb_relaxed(val >> 8, ptr + 1);
	writeb_relaxed(val >> 16, ptr + 2);
	writeb_relaxed(val >> 24, ptr + 3);
}

/*
 * Convert to hardware format: The userspace buffer contains IEC958 samples,
 * with the PCUV bits in bits 31..28 and audio samples in bits 27..4.  We
 * need these to be in bits 27..24, with the IEC B bit in bit 28, and audio
 * samples in 23..0.
 *
 * Default preamble in bits 3..0: 8 = block start, 4 = even 2 = odd
 *
 * Ideally, we could do with having the data properly formatted in userspace.
 */
static void dw_hdmi_reformat_iec958(struct snd_dw_hdmi *dw,
	size_t offset, size_t bytes)
{
	u32 *src = dw->buf_src + offset;
	u32 *dst = dw->buf_dst + offset;
	u32 *end = dw->buf_src + offset + bytes;

	do {
		u32 b, sample = *src++;

		b = (sample & 8) << (28 - 3);

		sample >>= 4;

		*dst++ = sample | b;

Annotation

Implementation Notes