sound/pci/mixart/mixart_mixer.c

Source file repositories/reference/linux-study-clean/sound/pci/mixart/mixart_mixer.c

File Facts

System
Linux kernel
Corpus path
sound/pci/mixart/mixart_mixer.c
Extension
.c
Size
46732 bytes
Lines
1191
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

if(is_capture) {
			io_level.level[i].analog_level = mixart_analog_level[chip->analog_capture_volume[i]];
		} else {
			if(chip->analog_playback_active[i])
				io_level.level[i].analog_level = mixart_analog_level[chip->analog_playback_volume[i]];
			else
				io_level.level[i].analog_level = mixart_analog_level[MIXART_ANALOG_PLAYBACK_LEVEL_MIN];
		}
	}

	if(is_capture)	request.uid = chip->uid_in_analog_physio;
	else		request.uid = chip->uid_out_analog_physio;
	request.message_id = MSG_PHYSICALIO_SET_LEVEL;
	request.data = &io_level;
	request.size = sizeof(io_level);

	err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp);
	if((err<0) || (resp.error_code)) {
		dev_dbg(chip->card->dev,
			"error MSG_PHYSICALIO_SET_LEVEL card(%d) is_capture(%d) error_code(%x)\n",
			chip->chip_idx, is_capture, resp.error_code);
		return -EINVAL;
	}
	return 0;
}

/*
 * analog level control
 */
static int mixart_analog_vol_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
	uinfo->count = 2;
	if(kcontrol->private_value == 0) {	/* playback */
		uinfo->value.integer.min = MIXART_ANALOG_PLAYBACK_LEVEL_MIN;  /* -96 dB */
		uinfo->value.integer.max = MIXART_ANALOG_PLAYBACK_LEVEL_MAX;  /* 0 dB */
	} else {				/* capture */
		uinfo->value.integer.min = MIXART_ANALOG_CAPTURE_LEVEL_MIN;   /* -96 dB */
		uinfo->value.integer.max = MIXART_ANALOG_CAPTURE_LEVEL_MAX;   /* 31.5 dB */
	}
	return 0;
}

static int mixart_analog_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
	struct snd_mixart *chip = snd_kcontrol_chip(kcontrol);

	guard(mutex)(&chip->mgr->mixer_mutex);
	if(kcontrol->private_value == 0) {	/* playback */
		ucontrol->value.integer.value[0] = chip->analog_playback_volume[0];
		ucontrol->value.integer.value[1] = chip->analog_playback_volume[1];
	} else {				/* capture */
		ucontrol->value.integer.value[0] = chip->analog_capture_volume[0];
		ucontrol->value.integer.value[1] = chip->analog_capture_volume[1];
	}
	return 0;
}

static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
	struct snd_mixart *chip = snd_kcontrol_chip(kcontrol);
	int changed = 0;
	int is_capture, i;

	guard(mutex)(&chip->mgr->mixer_mutex);
	is_capture = (kcontrol->private_value != 0);
	for (i = 0; i < 2; i++) {
		int new_volume = ucontrol->value.integer.value[i];
		int *stored_volume = is_capture ?
			&chip->analog_capture_volume[i] :
			&chip->analog_playback_volume[i];
		if (is_capture) {
			if (new_volume < MIXART_ANALOG_CAPTURE_LEVEL_MIN ||
			    new_volume > MIXART_ANALOG_CAPTURE_LEVEL_MAX)
				continue;
		} else {
			if (new_volume < MIXART_ANALOG_PLAYBACK_LEVEL_MIN ||
			    new_volume > MIXART_ANALOG_PLAYBACK_LEVEL_MAX)
				continue;
		}
		if (*stored_volume != new_volume) {
			*stored_volume = new_volume;
			changed = 1;
		}
	}
	if (changed)
		mixart_update_analog_audio_level(chip, is_capture);
	return changed;
}

Annotation

Implementation Notes