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