1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * ALSA driver for ICEnsemble VT1724 (Envy24HT)
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Lowlevel functions for Ego Sys Waveterminal 192M
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Copyright (c) 2006 Guedez Clement <klem.dev@gmail.com>
8*4882a593Smuzhiyun * Some functions are taken from the Prodigy192 driver
9*4882a593Smuzhiyun * source
10*4882a593Smuzhiyun */
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <linux/delay.h>
15*4882a593Smuzhiyun #include <linux/interrupt.h>
16*4882a593Smuzhiyun #include <linux/init.h>
17*4882a593Smuzhiyun #include <sound/core.h>
18*4882a593Smuzhiyun #include <sound/tlv.h>
19*4882a593Smuzhiyun #include <linux/slab.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun #include "ice1712.h"
22*4882a593Smuzhiyun #include "envy24ht.h"
23*4882a593Smuzhiyun #include "wtm.h"
24*4882a593Smuzhiyun #include "stac946x.h"
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun struct wtm_spec {
27*4882a593Smuzhiyun /* rate change needs atomic mute/unmute of all dacs*/
28*4882a593Smuzhiyun struct mutex mute_mutex;
29*4882a593Smuzhiyun };
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /*
33*4882a593Smuzhiyun * 2*ADC 6*DAC no1 ringbuffer r/w on i2c bus
34*4882a593Smuzhiyun */
stac9460_put(struct snd_ice1712 * ice,int reg,unsigned char val)35*4882a593Smuzhiyun static inline void stac9460_put(struct snd_ice1712 *ice, int reg,
36*4882a593Smuzhiyun unsigned char val)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val);
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun
stac9460_get(struct snd_ice1712 * ice,int reg)41*4882a593Smuzhiyun static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg);
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /*
47*4882a593Smuzhiyun * 2*ADC 2*DAC no2 ringbuffer r/w on i2c bus
48*4882a593Smuzhiyun */
stac9460_2_put(struct snd_ice1712 * ice,int reg,unsigned char val)49*4882a593Smuzhiyun static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg,
50*4882a593Smuzhiyun unsigned char val)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val);
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun
stac9460_2_get(struct snd_ice1712 * ice,int reg)55*4882a593Smuzhiyun static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg);
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /*
62*4882a593Smuzhiyun * DAC mute control
63*4882a593Smuzhiyun */
stac9460_dac_mute_all(struct snd_ice1712 * ice,unsigned char mute,unsigned short int * change_mask)64*4882a593Smuzhiyun static void stac9460_dac_mute_all(struct snd_ice1712 *ice, unsigned char mute,
65*4882a593Smuzhiyun unsigned short int *change_mask)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun unsigned char new, old;
68*4882a593Smuzhiyun int id, idx, change;
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /*stac9460 1*/
71*4882a593Smuzhiyun for (id = 0; id < 7; id++) {
72*4882a593Smuzhiyun if (*change_mask & (0x01 << id)) {
73*4882a593Smuzhiyun if (id == 0)
74*4882a593Smuzhiyun idx = STAC946X_MASTER_VOLUME;
75*4882a593Smuzhiyun else
76*4882a593Smuzhiyun idx = STAC946X_LF_VOLUME - 1 + id;
77*4882a593Smuzhiyun old = stac9460_get(ice, idx);
78*4882a593Smuzhiyun new = (~mute << 7 & 0x80) | (old & ~0x80);
79*4882a593Smuzhiyun change = (new != old);
80*4882a593Smuzhiyun if (change) {
81*4882a593Smuzhiyun stac9460_put(ice, idx, new);
82*4882a593Smuzhiyun *change_mask = *change_mask | (0x01 << id);
83*4882a593Smuzhiyun } else {
84*4882a593Smuzhiyun *change_mask = *change_mask & ~(0x01 << id);
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun /*stac9460 2*/
90*4882a593Smuzhiyun for (id = 0; id < 3; id++) {
91*4882a593Smuzhiyun if (*change_mask & (0x01 << (id + 7))) {
92*4882a593Smuzhiyun if (id == 0)
93*4882a593Smuzhiyun idx = STAC946X_MASTER_VOLUME;
94*4882a593Smuzhiyun else
95*4882a593Smuzhiyun idx = STAC946X_LF_VOLUME - 1 + id;
96*4882a593Smuzhiyun old = stac9460_2_get(ice, idx);
97*4882a593Smuzhiyun new = (~mute << 7 & 0x80) | (old & ~0x80);
98*4882a593Smuzhiyun change = (new != old);
99*4882a593Smuzhiyun if (change) {
100*4882a593Smuzhiyun stac9460_2_put(ice, idx, new);
101*4882a593Smuzhiyun *change_mask = *change_mask | (0x01 << id);
102*4882a593Smuzhiyun } else {
103*4882a593Smuzhiyun *change_mask = *change_mask & ~(0x01 << id);
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun #define stac9460_dac_mute_info snd_ctl_boolean_mono_info
112*4882a593Smuzhiyun
stac9460_dac_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)113*4882a593Smuzhiyun static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,
114*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
117*4882a593Smuzhiyun struct wtm_spec *spec = ice->spec;
118*4882a593Smuzhiyun unsigned char val;
119*4882a593Smuzhiyun int idx, id;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun mutex_lock(&spec->mute_mutex);
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun if (kcontrol->private_value) {
124*4882a593Smuzhiyun idx = STAC946X_MASTER_VOLUME;
125*4882a593Smuzhiyun id = 0;
126*4882a593Smuzhiyun } else {
127*4882a593Smuzhiyun id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
128*4882a593Smuzhiyun idx = id + STAC946X_LF_VOLUME;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun if (id < 6)
131*4882a593Smuzhiyun val = stac9460_get(ice, idx);
132*4882a593Smuzhiyun else
133*4882a593Smuzhiyun val = stac9460_2_get(ice, idx - 6);
134*4882a593Smuzhiyun ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun mutex_unlock(&spec->mute_mutex);
137*4882a593Smuzhiyun return 0;
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
stac9460_dac_mute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)140*4882a593Smuzhiyun static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol,
141*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
144*4882a593Smuzhiyun unsigned char new, old;
145*4882a593Smuzhiyun int id, idx;
146*4882a593Smuzhiyun int change;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun if (kcontrol->private_value) {
149*4882a593Smuzhiyun idx = STAC946X_MASTER_VOLUME;
150*4882a593Smuzhiyun old = stac9460_get(ice, idx);
151*4882a593Smuzhiyun new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |
152*4882a593Smuzhiyun (old & ~0x80);
153*4882a593Smuzhiyun change = (new != old);
154*4882a593Smuzhiyun if (change) {
155*4882a593Smuzhiyun stac9460_put(ice, idx, new);
156*4882a593Smuzhiyun stac9460_2_put(ice, idx, new);
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun } else {
159*4882a593Smuzhiyun id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
160*4882a593Smuzhiyun idx = id + STAC946X_LF_VOLUME;
161*4882a593Smuzhiyun if (id < 6)
162*4882a593Smuzhiyun old = stac9460_get(ice, idx);
163*4882a593Smuzhiyun else
164*4882a593Smuzhiyun old = stac9460_2_get(ice, idx - 6);
165*4882a593Smuzhiyun new = (~ucontrol->value.integer.value[0] << 7 & 0x80) |
166*4882a593Smuzhiyun (old & ~0x80);
167*4882a593Smuzhiyun change = (new != old);
168*4882a593Smuzhiyun if (change) {
169*4882a593Smuzhiyun if (id < 6)
170*4882a593Smuzhiyun stac9460_put(ice, idx, new);
171*4882a593Smuzhiyun else
172*4882a593Smuzhiyun stac9460_2_put(ice, idx - 6, new);
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun return change;
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun
178*4882a593Smuzhiyun /*
179*4882a593Smuzhiyun * DAC volume attenuation mixer control
180*4882a593Smuzhiyun */
stac9460_dac_vol_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)181*4882a593Smuzhiyun static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol,
182*4882a593Smuzhiyun struct snd_ctl_elem_info *uinfo)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
185*4882a593Smuzhiyun uinfo->count = 1;
186*4882a593Smuzhiyun uinfo->value.integer.min = 0; /* mute */
187*4882a593Smuzhiyun uinfo->value.integer.max = 0x7f; /* 0dB */
188*4882a593Smuzhiyun return 0;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
stac9460_dac_vol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)191*4882a593Smuzhiyun static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol,
192*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
195*4882a593Smuzhiyun int idx, id;
196*4882a593Smuzhiyun unsigned char vol;
197*4882a593Smuzhiyun
198*4882a593Smuzhiyun if (kcontrol->private_value) {
199*4882a593Smuzhiyun idx = STAC946X_MASTER_VOLUME;
200*4882a593Smuzhiyun id = 0;
201*4882a593Smuzhiyun } else {
202*4882a593Smuzhiyun id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
203*4882a593Smuzhiyun idx = id + STAC946X_LF_VOLUME;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun if (id < 6)
206*4882a593Smuzhiyun vol = stac9460_get(ice, idx) & 0x7f;
207*4882a593Smuzhiyun else
208*4882a593Smuzhiyun vol = stac9460_2_get(ice, idx - 6) & 0x7f;
209*4882a593Smuzhiyun ucontrol->value.integer.value[0] = 0x7f - vol;
210*4882a593Smuzhiyun return 0;
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun
stac9460_dac_vol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)213*4882a593Smuzhiyun static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,
214*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
217*4882a593Smuzhiyun int idx, id;
218*4882a593Smuzhiyun unsigned char tmp, ovol, nvol;
219*4882a593Smuzhiyun int change;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun if (kcontrol->private_value) {
222*4882a593Smuzhiyun idx = STAC946X_MASTER_VOLUME;
223*4882a593Smuzhiyun nvol = ucontrol->value.integer.value[0] & 0x7f;
224*4882a593Smuzhiyun tmp = stac9460_get(ice, idx);
225*4882a593Smuzhiyun ovol = 0x7f - (tmp & 0x7f);
226*4882a593Smuzhiyun change = (ovol != nvol);
227*4882a593Smuzhiyun if (change) {
228*4882a593Smuzhiyun stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
229*4882a593Smuzhiyun stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun } else {
232*4882a593Smuzhiyun id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
233*4882a593Smuzhiyun idx = id + STAC946X_LF_VOLUME;
234*4882a593Smuzhiyun nvol = ucontrol->value.integer.value[0] & 0x7f;
235*4882a593Smuzhiyun if (id < 6)
236*4882a593Smuzhiyun tmp = stac9460_get(ice, idx);
237*4882a593Smuzhiyun else
238*4882a593Smuzhiyun tmp = stac9460_2_get(ice, idx - 6);
239*4882a593Smuzhiyun ovol = 0x7f - (tmp & 0x7f);
240*4882a593Smuzhiyun change = (ovol != nvol);
241*4882a593Smuzhiyun if (change) {
242*4882a593Smuzhiyun if (id < 6)
243*4882a593Smuzhiyun stac9460_put(ice, idx, (0x7f - nvol) |
244*4882a593Smuzhiyun (tmp & 0x80));
245*4882a593Smuzhiyun else
246*4882a593Smuzhiyun stac9460_2_put(ice, idx-6, (0x7f - nvol) |
247*4882a593Smuzhiyun (tmp & 0x80));
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun }
250*4882a593Smuzhiyun return change;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun /*
254*4882a593Smuzhiyun * ADC mute control
255*4882a593Smuzhiyun */
256*4882a593Smuzhiyun #define stac9460_adc_mute_info snd_ctl_boolean_stereo_info
257*4882a593Smuzhiyun
stac9460_adc_mute_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)258*4882a593Smuzhiyun static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,
259*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
262*4882a593Smuzhiyun unsigned char val;
263*4882a593Smuzhiyun int i, id;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
266*4882a593Smuzhiyun if (id == 0) {
267*4882a593Smuzhiyun for (i = 0; i < 2; ++i) {
268*4882a593Smuzhiyun val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);
269*4882a593Smuzhiyun ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun } else {
272*4882a593Smuzhiyun for (i = 0; i < 2; ++i) {
273*4882a593Smuzhiyun val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i);
274*4882a593Smuzhiyun ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun return 0;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun
stac9460_adc_mute_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)280*4882a593Smuzhiyun static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol,
281*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
284*4882a593Smuzhiyun unsigned char new, old;
285*4882a593Smuzhiyun int i, reg, id;
286*4882a593Smuzhiyun int change;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
289*4882a593Smuzhiyun if (id == 0) {
290*4882a593Smuzhiyun for (i = 0; i < 2; ++i) {
291*4882a593Smuzhiyun reg = STAC946X_MIC_L_VOLUME + i;
292*4882a593Smuzhiyun old = stac9460_get(ice, reg);
293*4882a593Smuzhiyun new = (~ucontrol->value.integer.value[i]<<7&0x80) |
294*4882a593Smuzhiyun (old&~0x80);
295*4882a593Smuzhiyun change = (new != old);
296*4882a593Smuzhiyun if (change)
297*4882a593Smuzhiyun stac9460_put(ice, reg, new);
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun } else {
300*4882a593Smuzhiyun for (i = 0; i < 2; ++i) {
301*4882a593Smuzhiyun reg = STAC946X_MIC_L_VOLUME + i;
302*4882a593Smuzhiyun old = stac9460_2_get(ice, reg);
303*4882a593Smuzhiyun new = (~ucontrol->value.integer.value[i]<<7&0x80) |
304*4882a593Smuzhiyun (old&~0x80);
305*4882a593Smuzhiyun change = (new != old);
306*4882a593Smuzhiyun if (change)
307*4882a593Smuzhiyun stac9460_2_put(ice, reg, new);
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun return change;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun /*
314*4882a593Smuzhiyun *ADC gain mixer control
315*4882a593Smuzhiyun */
stac9460_adc_vol_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)316*4882a593Smuzhiyun static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol,
317*4882a593Smuzhiyun struct snd_ctl_elem_info *uinfo)
318*4882a593Smuzhiyun {
319*4882a593Smuzhiyun uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
320*4882a593Smuzhiyun uinfo->count = 2;
321*4882a593Smuzhiyun uinfo->value.integer.min = 0; /* 0dB */
322*4882a593Smuzhiyun uinfo->value.integer.max = 0x0f; /* 22.5dB */
323*4882a593Smuzhiyun return 0;
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun
stac9460_adc_vol_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)326*4882a593Smuzhiyun static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol,
327*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
330*4882a593Smuzhiyun int i, reg, id;
331*4882a593Smuzhiyun unsigned char vol;
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
334*4882a593Smuzhiyun if (id == 0) {
335*4882a593Smuzhiyun for (i = 0; i < 2; ++i) {
336*4882a593Smuzhiyun reg = STAC946X_MIC_L_VOLUME + i;
337*4882a593Smuzhiyun vol = stac9460_get(ice, reg) & 0x0f;
338*4882a593Smuzhiyun ucontrol->value.integer.value[i] = 0x0f - vol;
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun } else {
341*4882a593Smuzhiyun for (i = 0; i < 2; ++i) {
342*4882a593Smuzhiyun reg = STAC946X_MIC_L_VOLUME + i;
343*4882a593Smuzhiyun vol = stac9460_2_get(ice, reg) & 0x0f;
344*4882a593Smuzhiyun ucontrol->value.integer.value[i] = 0x0f - vol;
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun return 0;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun
stac9460_adc_vol_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)350*4882a593Smuzhiyun static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,
351*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
352*4882a593Smuzhiyun {
353*4882a593Smuzhiyun struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
354*4882a593Smuzhiyun int i, reg, id;
355*4882a593Smuzhiyun unsigned char ovol, nvol;
356*4882a593Smuzhiyun int change;
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
359*4882a593Smuzhiyun if (id == 0) {
360*4882a593Smuzhiyun for (i = 0; i < 2; ++i) {
361*4882a593Smuzhiyun reg = STAC946X_MIC_L_VOLUME + i;
362*4882a593Smuzhiyun nvol = ucontrol->value.integer.value[i] & 0x0f;
363*4882a593Smuzhiyun ovol = 0x0f - stac9460_get(ice, reg);
364*4882a593Smuzhiyun change = ((ovol & 0x0f) != nvol);
365*4882a593Smuzhiyun if (change)
366*4882a593Smuzhiyun stac9460_put(ice, reg, (0x0f - nvol) |
367*4882a593Smuzhiyun (ovol & ~0x0f));
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun } else {
370*4882a593Smuzhiyun for (i = 0; i < 2; ++i) {
371*4882a593Smuzhiyun reg = STAC946X_MIC_L_VOLUME + i;
372*4882a593Smuzhiyun nvol = ucontrol->value.integer.value[i] & 0x0f;
373*4882a593Smuzhiyun ovol = 0x0f - stac9460_2_get(ice, reg);
374*4882a593Smuzhiyun change = ((ovol & 0x0f) != nvol);
375*4882a593Smuzhiyun if (change)
376*4882a593Smuzhiyun stac9460_2_put(ice, reg, (0x0f - nvol) |
377*4882a593Smuzhiyun (ovol & ~0x0f));
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun }
380*4882a593Smuzhiyun return change;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun /*
384*4882a593Smuzhiyun * MIC / LINE switch fonction
385*4882a593Smuzhiyun */
stac9460_mic_sw_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)386*4882a593Smuzhiyun static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,
387*4882a593Smuzhiyun struct snd_ctl_elem_info *uinfo)
388*4882a593Smuzhiyun {
389*4882a593Smuzhiyun static const char * const texts[2] = { "Line In", "Mic" };
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun return snd_ctl_enum_info(uinfo, 1, 2, texts);
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun
stac9460_mic_sw_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)395*4882a593Smuzhiyun static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
396*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
399*4882a593Smuzhiyun unsigned char val;
400*4882a593Smuzhiyun int id;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
403*4882a593Smuzhiyun if (id == 0)
404*4882a593Smuzhiyun val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
405*4882a593Smuzhiyun else
406*4882a593Smuzhiyun val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
407*4882a593Smuzhiyun ucontrol->value.enumerated.item[0] = (val >> 7) & 0x1;
408*4882a593Smuzhiyun return 0;
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun
stac9460_mic_sw_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)411*4882a593Smuzhiyun static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
412*4882a593Smuzhiyun struct snd_ctl_elem_value *ucontrol)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
415*4882a593Smuzhiyun unsigned char new, old;
416*4882a593Smuzhiyun int change, id;
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
419*4882a593Smuzhiyun if (id == 0)
420*4882a593Smuzhiyun old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
421*4882a593Smuzhiyun else
422*4882a593Smuzhiyun old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
423*4882a593Smuzhiyun new = (ucontrol->value.enumerated.item[0] << 7 & 0x80) | (old & ~0x80);
424*4882a593Smuzhiyun change = (new != old);
425*4882a593Smuzhiyun if (change) {
426*4882a593Smuzhiyun if (id == 0)
427*4882a593Smuzhiyun stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
428*4882a593Smuzhiyun else
429*4882a593Smuzhiyun stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new);
430*4882a593Smuzhiyun }
431*4882a593Smuzhiyun return change;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun
435*4882a593Smuzhiyun /*
436*4882a593Smuzhiyun * Handler for setting correct codec rate - called when rate change is detected
437*4882a593Smuzhiyun */
stac9460_set_rate_val(struct snd_ice1712 * ice,unsigned int rate)438*4882a593Smuzhiyun static void stac9460_set_rate_val(struct snd_ice1712 *ice, unsigned int rate)
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun unsigned char old, new;
441*4882a593Smuzhiyun unsigned short int changed;
442*4882a593Smuzhiyun struct wtm_spec *spec = ice->spec;
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun if (rate == 0) /* no hint - S/PDIF input is master, simply return */
445*4882a593Smuzhiyun return;
446*4882a593Smuzhiyun else if (rate <= 48000)
447*4882a593Smuzhiyun new = 0x08; /* 256x, base rate mode */
448*4882a593Smuzhiyun else if (rate <= 96000)
449*4882a593Smuzhiyun new = 0x11; /* 256x, mid rate mode */
450*4882a593Smuzhiyun else
451*4882a593Smuzhiyun new = 0x12; /* 128x, high rate mode */
452*4882a593Smuzhiyun
453*4882a593Smuzhiyun old = stac9460_get(ice, STAC946X_MASTER_CLOCKING);
454*4882a593Smuzhiyun if (old == new)
455*4882a593Smuzhiyun return;
456*4882a593Smuzhiyun /* change detected, setting master clock, muting first */
457*4882a593Smuzhiyun /* due to possible conflicts with mute controls - mutexing */
458*4882a593Smuzhiyun mutex_lock(&spec->mute_mutex);
459*4882a593Smuzhiyun /* we have to remember current mute status for each DAC */
460*4882a593Smuzhiyun changed = 0xFFFF;
461*4882a593Smuzhiyun stac9460_dac_mute_all(ice, 0, &changed);
462*4882a593Smuzhiyun /*printk(KERN_DEBUG "Rate change: %d, new MC: 0x%02x\n", rate, new);*/
463*4882a593Smuzhiyun stac9460_put(ice, STAC946X_MASTER_CLOCKING, new);
464*4882a593Smuzhiyun stac9460_2_put(ice, STAC946X_MASTER_CLOCKING, new);
465*4882a593Smuzhiyun udelay(10);
466*4882a593Smuzhiyun /* unmuting - only originally unmuted dacs -
467*4882a593Smuzhiyun * i.e. those changed when muting */
468*4882a593Smuzhiyun stac9460_dac_mute_all(ice, 1, &changed);
469*4882a593Smuzhiyun mutex_unlock(&spec->mute_mutex);
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun /*Limits value in dB for fader*/
474*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
475*4882a593Smuzhiyun static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
476*4882a593Smuzhiyun
477*4882a593Smuzhiyun /*
478*4882a593Smuzhiyun * Control tabs
479*4882a593Smuzhiyun */
480*4882a593Smuzhiyun static const struct snd_kcontrol_new stac9640_controls[] = {
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
483*4882a593Smuzhiyun .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
484*4882a593Smuzhiyun SNDRV_CTL_ELEM_ACCESS_TLV_READ),
485*4882a593Smuzhiyun .name = "Master Playback Switch",
486*4882a593Smuzhiyun .info = stac9460_dac_mute_info,
487*4882a593Smuzhiyun .get = stac9460_dac_mute_get,
488*4882a593Smuzhiyun .put = stac9460_dac_mute_put,
489*4882a593Smuzhiyun .private_value = 1,
490*4882a593Smuzhiyun .tlv = { .p = db_scale_dac }
491*4882a593Smuzhiyun },
492*4882a593Smuzhiyun {
493*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
494*4882a593Smuzhiyun .name = "Master Playback Volume",
495*4882a593Smuzhiyun .info = stac9460_dac_vol_info,
496*4882a593Smuzhiyun .get = stac9460_dac_vol_get,
497*4882a593Smuzhiyun .put = stac9460_dac_vol_put,
498*4882a593Smuzhiyun .private_value = 1,
499*4882a593Smuzhiyun },
500*4882a593Smuzhiyun {
501*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
502*4882a593Smuzhiyun .name = "MIC/Line Input Enum",
503*4882a593Smuzhiyun .count = 2,
504*4882a593Smuzhiyun .info = stac9460_mic_sw_info,
505*4882a593Smuzhiyun .get = stac9460_mic_sw_get,
506*4882a593Smuzhiyun .put = stac9460_mic_sw_put,
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun },
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
511*4882a593Smuzhiyun .name = "DAC Switch",
512*4882a593Smuzhiyun .count = 8,
513*4882a593Smuzhiyun .info = stac9460_dac_mute_info,
514*4882a593Smuzhiyun .get = stac9460_dac_mute_get,
515*4882a593Smuzhiyun .put = stac9460_dac_mute_put,
516*4882a593Smuzhiyun },
517*4882a593Smuzhiyun {
518*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
519*4882a593Smuzhiyun .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
520*4882a593Smuzhiyun SNDRV_CTL_ELEM_ACCESS_TLV_READ),
521*4882a593Smuzhiyun
522*4882a593Smuzhiyun .name = "DAC Volume",
523*4882a593Smuzhiyun .count = 8,
524*4882a593Smuzhiyun .info = stac9460_dac_vol_info,
525*4882a593Smuzhiyun .get = stac9460_dac_vol_get,
526*4882a593Smuzhiyun .put = stac9460_dac_vol_put,
527*4882a593Smuzhiyun .tlv = { .p = db_scale_dac }
528*4882a593Smuzhiyun },
529*4882a593Smuzhiyun {
530*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
531*4882a593Smuzhiyun .name = "ADC Switch",
532*4882a593Smuzhiyun .count = 2,
533*4882a593Smuzhiyun .info = stac9460_adc_mute_info,
534*4882a593Smuzhiyun .get = stac9460_adc_mute_get,
535*4882a593Smuzhiyun .put = stac9460_adc_mute_put,
536*4882a593Smuzhiyun },
537*4882a593Smuzhiyun {
538*4882a593Smuzhiyun .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
539*4882a593Smuzhiyun .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
540*4882a593Smuzhiyun SNDRV_CTL_ELEM_ACCESS_TLV_READ),
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun .name = "ADC Volume",
543*4882a593Smuzhiyun .count = 2,
544*4882a593Smuzhiyun .info = stac9460_adc_vol_info,
545*4882a593Smuzhiyun .get = stac9460_adc_vol_get,
546*4882a593Smuzhiyun .put = stac9460_adc_vol_put,
547*4882a593Smuzhiyun .tlv = { .p = db_scale_adc }
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun };
550*4882a593Smuzhiyun
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun
553*4882a593Smuzhiyun /*INIT*/
wtm_add_controls(struct snd_ice1712 * ice)554*4882a593Smuzhiyun static int wtm_add_controls(struct snd_ice1712 *ice)
555*4882a593Smuzhiyun {
556*4882a593Smuzhiyun unsigned int i;
557*4882a593Smuzhiyun int err;
558*4882a593Smuzhiyun
559*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) {
560*4882a593Smuzhiyun err = snd_ctl_add(ice->card,
561*4882a593Smuzhiyun snd_ctl_new1(&stac9640_controls[i], ice));
562*4882a593Smuzhiyun if (err < 0)
563*4882a593Smuzhiyun return err;
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun return 0;
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun
wtm_init(struct snd_ice1712 * ice)568*4882a593Smuzhiyun static int wtm_init(struct snd_ice1712 *ice)
569*4882a593Smuzhiyun {
570*4882a593Smuzhiyun static const unsigned short stac_inits_wtm[] = {
571*4882a593Smuzhiyun STAC946X_RESET, 0,
572*4882a593Smuzhiyun STAC946X_MASTER_CLOCKING, 0x11,
573*4882a593Smuzhiyun (unsigned short)-1
574*4882a593Smuzhiyun };
575*4882a593Smuzhiyun const unsigned short *p;
576*4882a593Smuzhiyun struct wtm_spec *spec;
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun /*WTM 192M*/
579*4882a593Smuzhiyun ice->num_total_dacs = 8;
580*4882a593Smuzhiyun ice->num_total_adcs = 4;
581*4882a593Smuzhiyun ice->force_rdma1 = 1;
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun /*init mutex for dac mute conflict*/
584*4882a593Smuzhiyun spec = kzalloc(sizeof(*spec), GFP_KERNEL);
585*4882a593Smuzhiyun if (!spec)
586*4882a593Smuzhiyun return -ENOMEM;
587*4882a593Smuzhiyun ice->spec = spec;
588*4882a593Smuzhiyun mutex_init(&spec->mute_mutex);
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun /*initialize codec*/
592*4882a593Smuzhiyun p = stac_inits_wtm;
593*4882a593Smuzhiyun for (; *p != (unsigned short)-1; p += 2) {
594*4882a593Smuzhiyun stac9460_put(ice, p[0], p[1]);
595*4882a593Smuzhiyun stac9460_2_put(ice, p[0], p[1]);
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun ice->gpio.set_pro_rate = stac9460_set_rate_val;
598*4882a593Smuzhiyun return 0;
599*4882a593Smuzhiyun }
600*4882a593Smuzhiyun
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun static const unsigned char wtm_eeprom[] = {
603*4882a593Smuzhiyun [ICE_EEP2_SYSCONF] = 0x67, /*SYSCONF: clock 192KHz, mpu401,
604*4882a593Smuzhiyun 4ADC, 8DAC */
605*4882a593Smuzhiyun [ICE_EEP2_ACLINK] = 0x80, /* ACLINK : I2S */
606*4882a593Smuzhiyun [ICE_EEP2_I2S] = 0xf8, /* I2S: vol; 96k, 24bit, 192k */
607*4882a593Smuzhiyun [ICE_EEP2_SPDIF] = 0xc1, /*SPDIF: out-en, spidf ext out*/
608*4882a593Smuzhiyun [ICE_EEP2_GPIO_DIR] = 0x9f,
609*4882a593Smuzhiyun [ICE_EEP2_GPIO_DIR1] = 0xff,
610*4882a593Smuzhiyun [ICE_EEP2_GPIO_DIR2] = 0x7f,
611*4882a593Smuzhiyun [ICE_EEP2_GPIO_MASK] = 0x9f,
612*4882a593Smuzhiyun [ICE_EEP2_GPIO_MASK1] = 0xff,
613*4882a593Smuzhiyun [ICE_EEP2_GPIO_MASK2] = 0x7f,
614*4882a593Smuzhiyun [ICE_EEP2_GPIO_STATE] = 0x16,
615*4882a593Smuzhiyun [ICE_EEP2_GPIO_STATE1] = 0x80,
616*4882a593Smuzhiyun [ICE_EEP2_GPIO_STATE2] = 0x00,
617*4882a593Smuzhiyun };
618*4882a593Smuzhiyun
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun /*entry point*/
621*4882a593Smuzhiyun struct snd_ice1712_card_info snd_vt1724_wtm_cards[] = {
622*4882a593Smuzhiyun {
623*4882a593Smuzhiyun .subvendor = VT1724_SUBDEVICE_WTM,
624*4882a593Smuzhiyun .name = "ESI Waveterminal 192M",
625*4882a593Smuzhiyun .model = "WT192M",
626*4882a593Smuzhiyun .chip_init = wtm_init,
627*4882a593Smuzhiyun .build_controls = wtm_add_controls,
628*4882a593Smuzhiyun .eeprom_size = sizeof(wtm_eeprom),
629*4882a593Smuzhiyun .eeprom_data = wtm_eeprom,
630*4882a593Smuzhiyun },
631*4882a593Smuzhiyun {} /*terminator*/
632*4882a593Smuzhiyun };
633