sound/drivers/vx/vx_mixer.c

Source file repositories/reference/linux-study-clean/sound/drivers/vx/vx_mixer.c

File Facts

System
Linux kernel
Corpus path
sound/drivers/vx/vx_mixer.c
Extension
.c
Size
27424 bytes
Lines
983
Domain
Driver Families
Bucket
sound/drivers
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 w {
		u16 h;
		u16 l;
	} w;
	struct b {
		u8 hh;
		u8 mh;
		u8 ml;
		u8 ll;
	} b;
#else /* LITTLE_ENDIAN */
	struct w {
		u16 l;
		u16 h;
	} w;
	struct b {
		u8 ll;
		u8 ml;
		u8 mh;
		u8 hh;
	} b;
#endif
};

#define SET_CDC_DATA_SEL(di,s)          ((di).b.mh = (u8) (s))
#define SET_CDC_DATA_REG(di,r)          ((di).b.ml = (u8) (r))
#define SET_CDC_DATA_VAL(di,d)          ((di).b.ll = (u8) (d))
#define SET_CDC_DATA_INIT(di)           ((di).l = 0L, SET_CDC_DATA_SEL(di,XX_CODEC_SELECTOR))

/*
 * set up codec register and write the value
 * @codec: the codec id, 0 or 1
 * @reg: register index
 * @val: data value
 */
static void vx_set_codec_reg(struct vx_core *chip, int codec, int reg, int val)
{
	union vx_codec_data data;
	/* DAC control register */
	SET_CDC_DATA_INIT(data);
	SET_CDC_DATA_REG(data, reg);
	SET_CDC_DATA_VAL(data, val);
	vx_write_codec_reg(chip, codec, data.l);
}


/*
 * vx_set_analog_output_level - set the output attenuation level
 * @codec: the output codec, 0 or 1.  (1 for VXP440 only)
 * @left: left output level, 0 = mute
 * @right: right output level
 */
static void vx_set_analog_output_level(struct vx_core *chip, int codec, int left, int right)
{
	left  = chip->hw->output_level_max - left;
	right = chip->hw->output_level_max - right;

	if (chip->ops->akm_write) {
		chip->ops->akm_write(chip, XX_CODEC_LEVEL_LEFT_REGISTER, left);
		chip->ops->akm_write(chip, XX_CODEC_LEVEL_RIGHT_REGISTER, right);
	} else {
		/* convert to attenuation level: 0 = 0dB (max), 0xe3 = -113.5 dB (min) */
		vx_set_codec_reg(chip, codec, XX_CODEC_LEVEL_LEFT_REGISTER, left);
		vx_set_codec_reg(chip, codec, XX_CODEC_LEVEL_RIGHT_REGISTER, right);
	}
}


/*
 * vx_toggle_dac_mute -  mute/unmute DAC
 * @mute: 0 = unmute, 1 = mute
 */

#define DAC_ATTEN_MIN	0x08
#define DAC_ATTEN_MAX	0x38

void vx_toggle_dac_mute(struct vx_core *chip, int mute)
{
	unsigned int i;
	for (i = 0; i < chip->hw->num_codecs; i++) {
		if (chip->ops->akm_write)
			chip->ops->akm_write(chip, XX_CODEC_DAC_CONTROL_REGISTER, mute); /* XXX */
		else
			vx_set_codec_reg(chip, i, XX_CODEC_DAC_CONTROL_REGISTER,
					 mute ? DAC_ATTEN_MAX : DAC_ATTEN_MIN);
	}
}

/*
 * vx_reset_codec - reset and initialize the codecs

Annotation

Implementation Notes