sound/pci/oxygen/xonar_dg.c

Source file repositories/reference/linux-study-clean/sound/pci/oxygen/xonar_dg.c

File Facts

System
Linux kernel
Corpus path
sound/pci/oxygen/xonar_dg.c
Extension
.c
Size
8088 bytes
Lines
286
Domain
Driver Families
Bucket
sound/pci
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-only
/*
 * card driver for the Xonar DG/DGX
 *
 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
 * Copyright (c) Roman Volkov <v1ron@mail.ru>
 */

/*
 * Xonar DG/DGX
 * ------------
 *
 * CS4245 and CS4361 both will mute all outputs if any clock ratio
 * is invalid.
 *
 * CMI8788:
 *
 *   SPI 0 -> CS4245
 *
 *   Playback:
 *   I²S 1 -> CS4245
 *   I²S 2 -> CS4361 (center/LFE)
 *   I²S 3 -> CS4361 (surround)
 *   I²S 4 -> CS4361 (front)
 *   Capture:
 *   I²S ADC 1 <- CS4245
 *
 *   GPIO 3 <- ?
 *   GPIO 4 <- headphone detect
 *   GPIO 5 -> enable ADC analog circuit for the left channel
 *   GPIO 6 -> enable ADC analog circuit for the right channel
 *   GPIO 7 -> switch green rear output jack between CS4245 and the first
 *             channel of CS4361 (mechanical relay)
 *   GPIO 8 -> enable output to speakers
 *
 * CS4245:
 *
 *   input 0 <- mic
 *   input 1 <- aux
 *   input 2 <- front mic
 *   input 4 <- line
 *   DAC out -> headphones
 *   aux out -> front panel headphones
 */

#include <linux/pci.h>
#include <linux/delay.h>
#include <sound/control.h>
#include <sound/core.h>
#include <sound/info.h>
#include <sound/pcm.h>
#include <sound/tlv.h>
#include "oxygen.h"
#include "xonar_dg.h"
#include "cs4245.h"

int cs4245_write_spi(struct oxygen *chip, u8 reg)
{
	struct dg *data = chip->model_data;
	unsigned int packet;

	packet = reg << 8;
	packet |= (CS4245_SPI_ADDRESS | CS4245_SPI_WRITE) << 16;
	packet |= data->cs4245_shadow[reg];

	return oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
				OXYGEN_SPI_DATA_LENGTH_3 |
				OXYGEN_SPI_CLOCK_1280 |
				(0 << OXYGEN_SPI_CODEC_SHIFT) |
				OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
				packet);
}

int cs4245_read_spi(struct oxygen *chip, u8 addr)
{
	struct dg *data = chip->model_data;
	int ret;

	ret = oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
		OXYGEN_SPI_DATA_LENGTH_2 |
		OXYGEN_SPI_CEN_LATCH_CLOCK_HI |
		OXYGEN_SPI_CLOCK_1280 | (0 << OXYGEN_SPI_CODEC_SHIFT),
		((CS4245_SPI_ADDRESS | CS4245_SPI_WRITE) << 8) | addr);
	if (ret < 0)
		return ret;

	ret = oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
		OXYGEN_SPI_DATA_LENGTH_2 |
		OXYGEN_SPI_CEN_LATCH_CLOCK_HI |
		OXYGEN_SPI_CLOCK_1280 | (0 << OXYGEN_SPI_CODEC_SHIFT),

Annotation

Implementation Notes