sound/i2c/other/pt2258.c

Source file repositories/reference/linux-study-clean/sound/i2c/other/pt2258.c

File Facts

System
Linux kernel
Corpus path
sound/i2c/other/pt2258.c
Extension
.c
Size
5558 bytes
Lines
214
Domain
Driver Families
Bucket
sound/i2c
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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-or-later
/*
 *   ALSA Driver for the PT2258 volume controller.
 *
 *	Copyright (c) 2006  Jochen Voss <voss@seehuhn.de>
 */      

#include <sound/core.h>
#include <sound/control.h>
#include <sound/tlv.h>
#include <sound/i2c.h>
#include <sound/pt2258.h>
#include <linux/module.h>

MODULE_AUTHOR("Jochen Voss <voss@seehuhn.de>");
MODULE_DESCRIPTION("PT2258 volume controller (Princeton Technology Corp.)");
MODULE_LICENSE("GPL");

#define PT2258_CMD_RESET 0xc0
#define PT2258_CMD_UNMUTE 0xf8
#define PT2258_CMD_MUTE 0xf9

static const unsigned char pt2258_channel_code[12] = {
	0x80, 0x90,		/* channel 1: -10dB, -1dB */
	0x40, 0x50,		/* channel 2: -10dB, -1dB */
	0x00, 0x10,		/* channel 3: -10dB, -1dB */
	0x20, 0x30,		/* channel 4: -10dB, -1dB */
	0x60, 0x70,		/* channel 5: -10dB, -1dB */
	0xa0, 0xb0		/* channel 6: -10dB, -1dB */
};

int snd_pt2258_reset(struct snd_pt2258 *pt)
{
	unsigned char bytes[2];
	int i;

	/* reset chip */
	bytes[0] = PT2258_CMD_RESET;
	snd_i2c_lock(pt->i2c_bus);
	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1)
		goto __error;
	snd_i2c_unlock(pt->i2c_bus);

	/* mute all channels */
	pt->mute = 1;
	bytes[0] = PT2258_CMD_MUTE;
	snd_i2c_lock(pt->i2c_bus);
	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1)
		goto __error;
	snd_i2c_unlock(pt->i2c_bus);

	/* set all channels to 0dB */
	for (i = 0; i < 6; ++i)
		pt->volume[i] = 0;
	bytes[0] = 0xd0;
	bytes[1] = 0xe0;
	snd_i2c_lock(pt->i2c_bus);
	if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2)
		goto __error;
	snd_i2c_unlock(pt->i2c_bus);

	return 0;

      __error:
	snd_i2c_unlock(pt->i2c_bus);
	dev_err(pt->card->dev, "PT2258 reset failed\n");
	return -EIO;
}

static int pt2258_stereo_volume_info(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_info *uinfo)
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 2;
	uinfo->value.integer.min = 0;
	uinfo->value.integer.max = 79;
	return 0;
}

static int pt2258_stereo_volume_get(struct snd_kcontrol *kcontrol,
				    struct snd_ctl_elem_value *ucontrol)
{
	struct snd_pt2258 *pt = snd_kcontrol_chip(kcontrol);
	int base = kcontrol->private_value;

	/* chip does not support register reads */
	ucontrol->value.integer.value[0] = 79 - pt->volume[base];
	ucontrol->value.integer.value[1] = 79 - pt->volume[base + 1];
	return 0;
}

Annotation

Implementation Notes