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

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
Extension
.c
Size
5778 bytes
Lines
240
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

// SPDX-License-Identifier: GPL-2.0
/*
 * dw-hdmi-i2s-audio.c
 *
 * Copyright (c) 2017 Renesas Solutions Corp.
 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
 */

#include <linux/dma-mapping.h>
#include <linux/module.h>

#include <drm/bridge/dw_hdmi.h>
#include <drm/drm_crtc.h>

#include <sound/hdmi-codec.h>

#include "dw-hdmi.h"
#include "dw-hdmi-audio.h"

#define DRIVER_NAME "dw-hdmi-i2s-audio"

static inline void hdmi_write(struct dw_hdmi_i2s_audio_data *audio,
			      u8 val, int offset)
{
	struct dw_hdmi *hdmi = audio->hdmi;

	audio->write(hdmi, val, offset);
}

static inline u8 hdmi_read(struct dw_hdmi_i2s_audio_data *audio, int offset)
{
	struct dw_hdmi *hdmi = audio->hdmi;

	return audio->read(hdmi, offset);
}

static int dw_hdmi_i2s_hw_params(struct device *dev, void *data,
				 struct hdmi_codec_daifmt *fmt,
				 struct hdmi_codec_params *hparms)
{
	struct dw_hdmi_i2s_audio_data *audio = data;
	struct dw_hdmi *hdmi = audio->hdmi;
	u8 conf0 = 0;
	u8 conf1 = 0;
	u8 inputclkfs = 0;

	/* it cares I2S only */
	if (fmt->bit_clk_provider | fmt->frame_clk_provider) {
		dev_err(dev, "unsupported clock settings\n");
		return -EINVAL;
	}

	/* Reset the FIFOs before applying new params */
	hdmi_write(audio, HDMI_AUD_CONF0_SW_RESET, HDMI_AUD_CONF0);
	hdmi_write(audio, (u8)~HDMI_MC_SWRSTZ_I2SSWRST_REQ, HDMI_MC_SWRSTZ);

	inputclkfs	= HDMI_AUD_INPUTCLKFS_64FS;
	conf0		= (HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_EN0);

	/* Enable the required i2s lanes */
	switch (hparms->channels) {
	case 7 ... 8:
		conf0 |= HDMI_AUD_CONF0_I2S_EN3;
		fallthrough;
	case 5 ... 6:
		conf0 |= HDMI_AUD_CONF0_I2S_EN2;
		fallthrough;
	case 3 ... 4:
		conf0 |= HDMI_AUD_CONF0_I2S_EN1;
		/* Fall-thru */
	}

	switch (hparms->sample_width) {
	case 16:
		conf1 = HDMI_AUD_CONF1_WIDTH_16;
		break;
	case 24:
	case 32:
		conf1 = HDMI_AUD_CONF1_WIDTH_24;
		break;
	}

	switch (fmt->fmt) {
	case HDMI_I2S:
		conf1 |= HDMI_AUD_CONF1_MODE_I2S;
		break;
	case HDMI_RIGHT_J:
		conf1 |= HDMI_AUD_CONF1_MODE_RIGHT_J;
		break;
	case HDMI_LEFT_J:

Annotation

Implementation Notes