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