Merge tag 'riscv-for-linus-5.11-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / sound / ppc / daca.c
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 const 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 }