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