1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * PMac DACA lowlevel functions 4 * 5 * Copyright (c) by Takashi Iwai <tiwai@suse.de> 6 */ 7 8 9 #include <linux/init.h> 10 #include <linux/i2c.h> 11 #include <linux/kmod.h> 12 #include <linux/slab.h> 13 #include <sound/core.h> 14 #include "pmac.h" 15 16 /* i2c address */ 17 #define DACA_I2C_ADDR 0x4d 18 19 /* registers */ 20 #define DACA_REG_SR 0x01 21 #define DACA_REG_AVOL 0x02 22 #define DACA_REG_GCFG 0x03 23 24 /* maximum volume value */ 25 #define DACA_VOL_MAX 0x38 26 27 28 struct pmac_daca { 29 struct pmac_keywest i2c; 30 int left_vol, right_vol; 31 unsigned int deemphasis : 1; 32 unsigned int amp_on : 1; 33 }; 34 35 36 /* 37 * initialize / detect DACA 38 */ 39 static int daca_init_client(struct pmac_keywest *i2c) 40 { 41 unsigned short wdata = 0x00; 42 /* SR: no swap, 1bit delay, 32-48kHz */ 43 /* GCFG: power amp inverted, DAC on */ 44 if (i2c_smbus_write_byte_data(i2c->client, DACA_REG_SR, 0x08) < 0 || 45 i2c_smbus_write_byte_data(i2c->client, DACA_REG_GCFG, 0x05) < 0) 46 return -EINVAL; 47 return i2c_smbus_write_block_data(i2c->client, DACA_REG_AVOL, 48 2, (unsigned char*)&wdata); 49 } 50 51 /* 52 * update volume 53 */ 54 static int daca_set_volume(struct pmac_daca *mix) 55 { 56 unsigned char data[2]; 57 58 if (! mix->i2c.client) 59 return -ENODEV; 60 61 if (mix->left_vol > DACA_VOL_MAX) 62 data[0] = DACA_VOL_MAX; 63 else 64 data[0] = mix->left_vol; 65 if (mix->right_vol > DACA_VOL_MAX) 66 data[1] = DACA_VOL_MAX; 67 else 68 data[1] = mix->right_vol; 69 data[1] |= mix->deemphasis ? 0x40 : 0; 70 if (i2c_smbus_write_block_data(mix->i2c.client, DACA_REG_AVOL, 71 2, data) < 0) { 72 snd_printk(KERN_ERR "failed to set volume \n"); 73 return -EINVAL; 74 } 75 return 0; 76 } 77 78 79 /* deemphasis switch */ 80 #define daca_info_deemphasis snd_ctl_boolean_mono_info 81 82 static int daca_get_deemphasis(struct snd_kcontrol *kcontrol, 83 struct snd_ctl_elem_value *ucontrol) 84 { 85 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 86 struct pmac_daca *mix; 87 if (! (mix = chip->mixer_data)) 88 return -ENODEV; 89 ucontrol->value.integer.value[0] = mix->deemphasis ? 1 : 0; 90 return 0; 91 } 92 93 static int daca_put_deemphasis(struct snd_kcontrol *kcontrol, 94 struct snd_ctl_elem_value *ucontrol) 95 { 96 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 97 struct pmac_daca *mix; 98 int change; 99 100 if (! (mix = chip->mixer_data)) 101 return -ENODEV; 102 change = mix->deemphasis != ucontrol->value.integer.value[0]; 103 if (change) { 104 mix->deemphasis = !!ucontrol->value.integer.value[0]; 105 daca_set_volume(mix); 106 } 107 return change; 108 } 109 110 /* output volume */ 111 static int daca_info_volume(struct snd_kcontrol *kcontrol, 112 struct snd_ctl_elem_info *uinfo) 113 { 114 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 115 uinfo->count = 2; 116 uinfo->value.integer.min = 0; 117 uinfo->value.integer.max = DACA_VOL_MAX; 118 return 0; 119 } 120 121 static int daca_get_volume(struct snd_kcontrol *kcontrol, 122 struct snd_ctl_elem_value *ucontrol) 123 { 124 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 125 struct pmac_daca *mix; 126 if (! (mix = chip->mixer_data)) 127 return -ENODEV; 128 ucontrol->value.integer.value[0] = mix->left_vol; 129 ucontrol->value.integer.value[1] = mix->right_vol; 130 return 0; 131 } 132 133 static int daca_put_volume(struct snd_kcontrol *kcontrol, 134 struct snd_ctl_elem_value *ucontrol) 135 { 136 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 137 struct pmac_daca *mix; 138 unsigned int vol[2]; 139 int change; 140 141 if (! (mix = chip->mixer_data)) 142 return -ENODEV; 143 vol[0] = ucontrol->value.integer.value[0]; 144 vol[1] = ucontrol->value.integer.value[1]; 145 if (vol[0] > DACA_VOL_MAX || vol[1] > DACA_VOL_MAX) 146 return -EINVAL; 147 change = mix->left_vol != vol[0] || 148 mix->right_vol != vol[1]; 149 if (change) { 150 mix->left_vol = vol[0]; 151 mix->right_vol = vol[1]; 152 daca_set_volume(mix); 153 } 154 return change; 155 } 156 157 /* amplifier switch */ 158 #define daca_info_amp daca_info_deemphasis 159 160 static int daca_get_amp(struct snd_kcontrol *kcontrol, 161 struct snd_ctl_elem_value *ucontrol) 162 { 163 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 164 struct pmac_daca *mix; 165 if (! (mix = chip->mixer_data)) 166 return -ENODEV; 167 ucontrol->value.integer.value[0] = mix->amp_on ? 1 : 0; 168 return 0; 169 } 170 171 static int daca_put_amp(struct snd_kcontrol *kcontrol, 172 struct snd_ctl_elem_value *ucontrol) 173 { 174 struct snd_pmac *chip = snd_kcontrol_chip(kcontrol); 175 struct pmac_daca *mix; 176 int change; 177 178 if (! (mix = chip->mixer_data)) 179 return -ENODEV; 180 change = mix->amp_on != ucontrol->value.integer.value[0]; 181 if (change) { 182 mix->amp_on = !!ucontrol->value.integer.value[0]; 183 i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_GCFG, 184 mix->amp_on ? 0x05 : 0x04); 185 } 186 return change; 187 } 188 189 static struct snd_kcontrol_new daca_mixers[] = { 190 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 191 .name = "Deemphasis Switch", 192 .info = daca_info_deemphasis, 193 .get = daca_get_deemphasis, 194 .put = daca_put_deemphasis 195 }, 196 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 197 .name = "Master Playback Volume", 198 .info = daca_info_volume, 199 .get = daca_get_volume, 200 .put = daca_put_volume 201 }, 202 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 203 .name = "Power Amplifier Switch", 204 .info = daca_info_amp, 205 .get = daca_get_amp, 206 .put = daca_put_amp 207 }, 208 }; 209 210 211 #ifdef CONFIG_PM 212 static void daca_resume(struct snd_pmac *chip) 213 { 214 struct pmac_daca *mix = chip->mixer_data; 215 i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_SR, 0x08); 216 i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_GCFG, 217 mix->amp_on ? 0x05 : 0x04); 218 daca_set_volume(mix); 219 } 220 #endif /* CONFIG_PM */ 221 222 223 static void daca_cleanup(struct snd_pmac *chip) 224 { 225 struct pmac_daca *mix = chip->mixer_data; 226 if (! mix) 227 return; 228 snd_pmac_keywest_cleanup(&mix->i2c); 229 kfree(mix); 230 chip->mixer_data = NULL; 231 } 232 233 /* exported */ 234 int snd_pmac_daca_init(struct snd_pmac *chip) 235 { 236 int i, err; 237 struct pmac_daca *mix; 238 239 request_module("i2c-powermac"); 240 241 mix = kzalloc(sizeof(*mix), GFP_KERNEL); 242 if (! mix) 243 return -ENOMEM; 244 chip->mixer_data = mix; 245 chip->mixer_free = daca_cleanup; 246 mix->amp_on = 1; /* default on */ 247 248 mix->i2c.addr = DACA_I2C_ADDR; 249 mix->i2c.init_client = daca_init_client; 250 mix->i2c.name = "DACA"; 251 if ((err = snd_pmac_keywest_init(&mix->i2c)) < 0) 252 return err; 253 254 /* 255 * build mixers 256 */ 257 strcpy(chip->card->mixername, "PowerMac DACA"); 258 259 for (i = 0; i < ARRAY_SIZE(daca_mixers); i++) { 260 if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&daca_mixers[i], chip))) < 0) 261 return err; 262 } 263 264 #ifdef CONFIG_PM 265 chip->resume = daca_resume; 266 #endif 267 268 return 0; 269 } 270