Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *  Routines for control of ICS 2101 chip and "mixer" in GF1 chip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/time.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <sound/gus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #define GF1_SINGLE(xname, xindex, shift, invert) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)   .info = snd_gf1_info_single, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)   .get = snd_gf1_get_single, .put = snd_gf1_put_single, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)   .private_value = shift | (invert << 8) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define snd_gf1_info_single	snd_ctl_boolean_mono_info
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) static int snd_gf1_get_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	int shift = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	int invert = (kcontrol->private_value >> 8) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	ucontrol->value.integer.value[0] = (gus->mix_cntrl_reg >> shift) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	if (invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 		ucontrol->value.integer.value[0] ^= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) static int snd_gf1_put_single(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	int shift = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	int invert = (kcontrol->private_value >> 8) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	unsigned char oval, nval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	nval = ucontrol->value.integer.value[0] & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	if (invert)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 		nval ^= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	nval <<= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	spin_lock_irqsave(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	oval = gus->mix_cntrl_reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	nval = (oval & ~(1 << shift)) | nval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	change = nval != oval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	outb(gus->mix_cntrl_reg = nval, GUSP(gus, MIXCNTRLREG));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	outb(gus->gf1.active_voice = 0, GUSP(gus, GF1PAGE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	spin_unlock_irqrestore(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) #define ICS_DOUBLE(xname, xindex, addr) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)   .info = snd_ics_info_double, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)   .get = snd_ics_get_double, .put = snd_ics_put_double, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)   .private_value = addr }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) static int snd_ics_info_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	uinfo->count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	uinfo->value.integer.min = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	uinfo->value.integer.max = 127;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) static int snd_ics_get_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	int addr = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	unsigned char left, right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	spin_lock_irqsave(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	left = gus->gf1.ics_regs[addr][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	right = gus->gf1.ics_regs[addr][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	spin_unlock_irqrestore(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	ucontrol->value.integer.value[0] = left & 127;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	ucontrol->value.integer.value[1] = right & 127;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) static int snd_ics_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	struct snd_gus_card *gus = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	int addr = kcontrol->private_value & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	int change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	unsigned char val1, val2, oval1, oval2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	val1 = ucontrol->value.integer.value[0] & 127;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	val2 = ucontrol->value.integer.value[1] & 127;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	spin_lock_irqsave(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	oval1 = gus->gf1.ics_regs[addr][0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	oval2 = gus->gf1.ics_regs[addr][1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	change = val1 != oval1 || val2 != oval2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	gus->gf1.ics_regs[addr][0] = val1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	gus->gf1.ics_regs[addr][1] = val2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	if (gus->ics_flag && gus->ics_flipped &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	    (addr == SNDRV_ICS_GF1_DEV || addr == SNDRV_ICS_MASTER_DEV))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		swap(val1, val2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	addr <<= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	outb(addr | 0, GUSP(gus, MIXCNTRLPORT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	outb(1, GUSP(gus, MIXDATAPORT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	outb(addr | 2, GUSP(gus, MIXCNTRLPORT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	outb((unsigned char) val1, GUSP(gus, MIXDATAPORT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	outb(addr | 1, GUSP(gus, MIXCNTRLPORT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	outb(2, GUSP(gus, MIXDATAPORT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	outb(addr | 3, GUSP(gus, MIXCNTRLPORT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 	outb((unsigned char) val2, GUSP(gus, MIXDATAPORT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	spin_unlock_irqrestore(&gus->reg_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	return change;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static const struct snd_kcontrol_new snd_gf1_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) GF1_SINGLE("Master Playback Switch", 0, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) GF1_SINGLE("Line Switch", 0, 0, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) GF1_SINGLE("Mic Switch", 0, 2, 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static const struct snd_kcontrol_new snd_ics_controls[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) GF1_SINGLE("Master Playback Switch", 0, 1, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) ICS_DOUBLE("Master Playback Volume", 0, SNDRV_ICS_MASTER_DEV),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) ICS_DOUBLE("Synth Playback Volume", 0, SNDRV_ICS_GF1_DEV),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) GF1_SINGLE("Line Switch", 0, 0, 1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ICS_DOUBLE("Line Playback Volume", 0, SNDRV_ICS_LINE_DEV),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) GF1_SINGLE("Mic Switch", 0, 2, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) ICS_DOUBLE("Mic Playback Volume", 0, SNDRV_ICS_MIC_DEV),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ICS_DOUBLE("CD Playback Volume", 0, SNDRV_ICS_CD_DEV)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int snd_gf1_new_mixer(struct snd_gus_card * gus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	unsigned int idx, max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	if (snd_BUG_ON(!gus))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	card = gus->card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	if (snd_BUG_ON(!card))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	if (gus->ics_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		snd_component_add(card, "ICS2101");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	if (card->mixername[0] == '\0') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		strcpy(card->mixername, gus->ics_flag ? "GF1,ICS2101" : "GF1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 		if (gus->ics_flag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			strcat(card->mixername, ",ICS2101");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		strcat(card->mixername, ",GF1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	if (!gus->ics_flag) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		max = gus->ess_flag ? 1 : ARRAY_SIZE(snd_gf1_controls);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		for (idx = 0; idx < max; idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_gf1_controls[idx], gus))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 				return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		for (idx = 0; idx < ARRAY_SIZE(snd_ics_controls); idx++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 			if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_ics_controls[idx], gus))) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 				return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }