Blame view

sound/ppc/daca.c 6.19 KB
1a59d1b8e   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
  /*
   * PMac DACA lowlevel functions
   *
   * Copyright (c) by Takashi Iwai <tiwai@suse.de>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
6
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
8
  #include <linux/init.h>
  #include <linux/i2c.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  #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   Takashi Iwai   [ALSA] Remove xxx...
24
25
  struct pmac_daca {
  	struct pmac_keywest i2c;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
  	int left_vol, right_vol;
  	unsigned int deemphasis : 1;
  	unsigned int amp_on : 1;
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
29
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
34
  
  
  /*
   * initialize / detect DACA
   */
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
35
  static int daca_init_client(struct pmac_keywest *i2c)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
37
38
39
40
41
42
43
44
45
46
47
48
49
  {
  	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   Takashi Iwai   [ALSA] Remove xxx...
50
  static int daca_set_volume(struct pmac_daca *mix)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  {
  	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   Takashi Iwai   ALSA: powermac - ...
68
69
  		snd_printk(KERN_ERR "failed to set volume 
  ");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
70
71
72
73
74
75
76
  		return -EINVAL;
  	}
  	return 0;
  }
  
  
  /* deemphasis switch */
a5ce88909   Takashi Iwai   [ALSA] Clean up w...
77
  #define daca_info_deemphasis		snd_ctl_boolean_mono_info
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78

65b29f503   Takashi Iwai   [ALSA] Remove xxx...
79
80
  static int daca_get_deemphasis(struct snd_kcontrol *kcontrol,
  			       struct snd_ctl_elem_value *ucontrol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
81
  {
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
82
83
  	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
  	struct pmac_daca *mix;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
84
85
86
87
88
  	if (! (mix = chip->mixer_data))
  		return -ENODEV;
  	ucontrol->value.integer.value[0] = mix->deemphasis ? 1 : 0;
  	return 0;
  }
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
89
90
  static int daca_put_deemphasis(struct snd_kcontrol *kcontrol,
  			       struct snd_ctl_elem_value *ucontrol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
  {
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
92
93
  	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
  	struct pmac_daca *mix;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
94
95
96
97
98
99
  	int change;
  
  	if (! (mix = chip->mixer_data))
  		return -ENODEV;
  	change = mix->deemphasis != ucontrol->value.integer.value[0];
  	if (change) {
d4079ac49   Takashi Iwai   [ALSA] powermac -...
100
  		mix->deemphasis = !!ucontrol->value.integer.value[0];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
101
102
103
104
105
106
  		daca_set_volume(mix);
  	}
  	return change;
  }
  
  /* output volume */
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
107
108
  static int daca_info_volume(struct snd_kcontrol *kcontrol,
  			    struct snd_ctl_elem_info *uinfo)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
112
113
114
115
  {
  	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   Takashi Iwai   [ALSA] Remove xxx...
116
117
  static int daca_get_volume(struct snd_kcontrol *kcontrol,
  			   struct snd_ctl_elem_value *ucontrol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
118
  {
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
119
120
  	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
  	struct pmac_daca *mix;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
121
122
123
124
125
126
  	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   Takashi Iwai   [ALSA] Remove xxx...
127
128
  static int daca_put_volume(struct snd_kcontrol *kcontrol,
  			   struct snd_ctl_elem_value *ucontrol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
129
  {
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
130
131
  	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
  	struct pmac_daca *mix;
d4079ac49   Takashi Iwai   [ALSA] powermac -...
132
  	unsigned int vol[2];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
134
135
136
  	int change;
  
  	if (! (mix = chip->mixer_data))
  		return -ENODEV;
d4079ac49   Takashi Iwai   [ALSA] powermac -...
137
138
139
140
141
142
  	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   Linus Torvalds   Linux-2.6.12-rc2
143
  	if (change) {
d4079ac49   Takashi Iwai   [ALSA] powermac -...
144
145
  		mix->left_vol = vol[0];
  		mix->right_vol = vol[1];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
146
147
148
149
150
151
152
  		daca_set_volume(mix);
  	}
  	return change;
  }
  
  /* amplifier switch */
  #define daca_info_amp	daca_info_deemphasis
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
153
154
  static int daca_get_amp(struct snd_kcontrol *kcontrol,
  			struct snd_ctl_elem_value *ucontrol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
155
  {
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
156
157
  	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
  	struct pmac_daca *mix;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
158
159
160
161
162
  	if (! (mix = chip->mixer_data))
  		return -ENODEV;
  	ucontrol->value.integer.value[0] = mix->amp_on ? 1 : 0;
  	return 0;
  }
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
163
164
  static int daca_put_amp(struct snd_kcontrol *kcontrol,
  			struct snd_ctl_elem_value *ucontrol)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
  {
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
166
167
  	struct snd_pmac *chip = snd_kcontrol_chip(kcontrol);
  	struct pmac_daca *mix;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
168
169
170
171
172
173
  	int change;
  
  	if (! (mix = chip->mixer_data))
  		return -ENODEV;
  	change = mix->amp_on != ucontrol->value.integer.value[0];
  	if (change) {
d4079ac49   Takashi Iwai   [ALSA] powermac -...
174
  		mix->amp_on = !!ucontrol->value.integer.value[0];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
177
178
179
  		i2c_smbus_write_byte_data(mix->i2c.client, DACA_REG_GCFG,
  					  mix->amp_on ? 0x05 : 0x04);
  	}
  	return change;
  }
c031b0cc7   Takashi Iwai   ALSA: ppc: Consti...
180
  static const struct snd_kcontrol_new daca_mixers[] = {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
  	{ .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   Benjamin Herrenschmidt   [PATCH] ppc32: Re...
200
  #ifdef CONFIG_PM
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
201
  static void daca_resume(struct snd_pmac *chip)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
  {
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
203
  	struct pmac_daca *mix = chip->mixer_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
204
205
206
207
208
  	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   Benjamin Herrenschmidt   [PATCH] ppc32: Re...
209
  #endif /* CONFIG_PM */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
210

65b29f503   Takashi Iwai   [ALSA] Remove xxx...
211
  static void daca_cleanup(struct snd_pmac *chip)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212
  {
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
213
  	struct pmac_daca *mix = chip->mixer_data;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
215
216
217
218
219
220
221
  	if (! mix)
  		return;
  	snd_pmac_keywest_cleanup(&mix->i2c);
  	kfree(mix);
  	chip->mixer_data = NULL;
  }
  
  /* exported */
15afafc25   Bill Pemberton   ALSA: ppc: remove...
222
  int snd_pmac_daca_init(struct snd_pmac *chip)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
224
  {
  	int i, err;
65b29f503   Takashi Iwai   [ALSA] Remove xxx...
225
  	struct pmac_daca *mix;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
226

0d63e4f9e   Jan Blunck   Dont touch fs_str...
227
  	request_module("i2c-powermac");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228

59feddb25   Panagiotis Issaris   [ALSA] Conversion...
229
  	mix = kzalloc(sizeof(*mix), GFP_KERNEL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
  	if (! mix)
  		return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
  	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   Benjamin Herrenschmidt   [PATCH] ppc32: Re...
251
  #ifdef CONFIG_PM
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
252
253
254
255
256
  	chip->resume = daca_resume;
  #endif
  
  	return 0;
  }