xref: /OK3568_Linux_fs/kernel/sound/i2c/other/ak4113.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  Routines for control of the AK4113 via I2C/4-wire serial interface
4*4882a593Smuzhiyun  *  IEC958 (S/PDIF) receiver by Asahi Kasei
5*4882a593Smuzhiyun  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
6*4882a593Smuzhiyun  *  Copyright (c) by Pavel Hofman <pavel.hofman@ivitera.com>
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun 
9*4882a593Smuzhiyun #include <linux/slab.h>
10*4882a593Smuzhiyun #include <linux/delay.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <sound/core.h>
13*4882a593Smuzhiyun #include <sound/control.h>
14*4882a593Smuzhiyun #include <sound/pcm.h>
15*4882a593Smuzhiyun #include <sound/ak4113.h>
16*4882a593Smuzhiyun #include <sound/asoundef.h>
17*4882a593Smuzhiyun #include <sound/info.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun MODULE_AUTHOR("Pavel Hofman <pavel.hofman@ivitera.com>");
20*4882a593Smuzhiyun MODULE_DESCRIPTION("AK4113 IEC958 (S/PDIF) receiver by Asahi Kasei");
21*4882a593Smuzhiyun MODULE_LICENSE("GPL");
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #define AK4113_ADDR			0x00 /* fixed address */
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun static void ak4113_stats(struct work_struct *work);
26*4882a593Smuzhiyun static void ak4113_init_regs(struct ak4113 *chip);
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun 
reg_write(struct ak4113 * ak4113,unsigned char reg,unsigned char val)29*4882a593Smuzhiyun static void reg_write(struct ak4113 *ak4113, unsigned char reg,
30*4882a593Smuzhiyun 		unsigned char val)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun 	ak4113->write(ak4113->private_data, reg, val);
33*4882a593Smuzhiyun 	if (reg < sizeof(ak4113->regmap))
34*4882a593Smuzhiyun 		ak4113->regmap[reg] = val;
35*4882a593Smuzhiyun }
36*4882a593Smuzhiyun 
reg_read(struct ak4113 * ak4113,unsigned char reg)37*4882a593Smuzhiyun static inline unsigned char reg_read(struct ak4113 *ak4113, unsigned char reg)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	return ak4113->read(ak4113->private_data, reg);
40*4882a593Smuzhiyun }
41*4882a593Smuzhiyun 
snd_ak4113_free(struct ak4113 * chip)42*4882a593Smuzhiyun static void snd_ak4113_free(struct ak4113 *chip)
43*4882a593Smuzhiyun {
44*4882a593Smuzhiyun 	atomic_inc(&chip->wq_processing);	/* don't schedule new work */
45*4882a593Smuzhiyun 	cancel_delayed_work_sync(&chip->work);
46*4882a593Smuzhiyun 	kfree(chip);
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun 
snd_ak4113_dev_free(struct snd_device * device)49*4882a593Smuzhiyun static int snd_ak4113_dev_free(struct snd_device *device)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun 	struct ak4113 *chip = device->device_data;
52*4882a593Smuzhiyun 	snd_ak4113_free(chip);
53*4882a593Smuzhiyun 	return 0;
54*4882a593Smuzhiyun }
55*4882a593Smuzhiyun 
snd_ak4113_create(struct snd_card * card,ak4113_read_t * read,ak4113_write_t * write,const unsigned char * pgm,void * private_data,struct ak4113 ** r_ak4113)56*4882a593Smuzhiyun int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read,
57*4882a593Smuzhiyun 		ak4113_write_t *write, const unsigned char *pgm,
58*4882a593Smuzhiyun 		void *private_data, struct ak4113 **r_ak4113)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	struct ak4113 *chip;
61*4882a593Smuzhiyun 	int err;
62*4882a593Smuzhiyun 	unsigned char reg;
63*4882a593Smuzhiyun 	static const struct snd_device_ops ops = {
64*4882a593Smuzhiyun 		.dev_free =     snd_ak4113_dev_free,
65*4882a593Smuzhiyun 	};
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
68*4882a593Smuzhiyun 	if (chip == NULL)
69*4882a593Smuzhiyun 		return -ENOMEM;
70*4882a593Smuzhiyun 	spin_lock_init(&chip->lock);
71*4882a593Smuzhiyun 	chip->card = card;
72*4882a593Smuzhiyun 	chip->read = read;
73*4882a593Smuzhiyun 	chip->write = write;
74*4882a593Smuzhiyun 	chip->private_data = private_data;
75*4882a593Smuzhiyun 	INIT_DELAYED_WORK(&chip->work, ak4113_stats);
76*4882a593Smuzhiyun 	atomic_set(&chip->wq_processing, 0);
77*4882a593Smuzhiyun 	mutex_init(&chip->reinit_mutex);
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	for (reg = 0; reg < AK4113_WRITABLE_REGS ; reg++)
80*4882a593Smuzhiyun 		chip->regmap[reg] = pgm[reg];
81*4882a593Smuzhiyun 	ak4113_init_regs(chip);
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	chip->rcs0 = reg_read(chip, AK4113_REG_RCS0) & ~(AK4113_QINT |
84*4882a593Smuzhiyun 			AK4113_CINT | AK4113_STC);
85*4882a593Smuzhiyun 	chip->rcs1 = reg_read(chip, AK4113_REG_RCS1);
86*4882a593Smuzhiyun 	chip->rcs2 = reg_read(chip, AK4113_REG_RCS2);
87*4882a593Smuzhiyun 	err = snd_device_new(card, SNDRV_DEV_CODEC, chip, &ops);
88*4882a593Smuzhiyun 	if (err < 0)
89*4882a593Smuzhiyun 		goto __fail;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	if (r_ak4113)
92*4882a593Smuzhiyun 		*r_ak4113 = chip;
93*4882a593Smuzhiyun 	return 0;
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun __fail:
96*4882a593Smuzhiyun 	snd_ak4113_free(chip);
97*4882a593Smuzhiyun 	return err;
98*4882a593Smuzhiyun }
99*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_ak4113_create);
100*4882a593Smuzhiyun 
snd_ak4113_reg_write(struct ak4113 * chip,unsigned char reg,unsigned char mask,unsigned char val)101*4882a593Smuzhiyun void snd_ak4113_reg_write(struct ak4113 *chip, unsigned char reg,
102*4882a593Smuzhiyun 		unsigned char mask, unsigned char val)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	if (reg >= AK4113_WRITABLE_REGS)
105*4882a593Smuzhiyun 		return;
106*4882a593Smuzhiyun 	reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val);
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_ak4113_reg_write);
109*4882a593Smuzhiyun 
ak4113_init_regs(struct ak4113 * chip)110*4882a593Smuzhiyun static void ak4113_init_regs(struct ak4113 *chip)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun 	unsigned char old = chip->regmap[AK4113_REG_PWRDN], reg;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	/* bring the chip to reset state and powerdown state */
115*4882a593Smuzhiyun 	reg_write(chip, AK4113_REG_PWRDN, old & ~(AK4113_RST|AK4113_PWN));
116*4882a593Smuzhiyun 	udelay(200);
117*4882a593Smuzhiyun 	/* release reset, but leave powerdown */
118*4882a593Smuzhiyun 	reg_write(chip, AK4113_REG_PWRDN, (old | AK4113_RST) & ~AK4113_PWN);
119*4882a593Smuzhiyun 	udelay(200);
120*4882a593Smuzhiyun 	for (reg = 1; reg < AK4113_WRITABLE_REGS; reg++)
121*4882a593Smuzhiyun 		reg_write(chip, reg, chip->regmap[reg]);
122*4882a593Smuzhiyun 	/* release powerdown, everything is initialized now */
123*4882a593Smuzhiyun 	reg_write(chip, AK4113_REG_PWRDN, old | AK4113_RST | AK4113_PWN);
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun 
snd_ak4113_reinit(struct ak4113 * chip)126*4882a593Smuzhiyun void snd_ak4113_reinit(struct ak4113 *chip)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun 	if (atomic_inc_return(&chip->wq_processing) == 1)
129*4882a593Smuzhiyun 		cancel_delayed_work_sync(&chip->work);
130*4882a593Smuzhiyun 	mutex_lock(&chip->reinit_mutex);
131*4882a593Smuzhiyun 	ak4113_init_regs(chip);
132*4882a593Smuzhiyun 	mutex_unlock(&chip->reinit_mutex);
133*4882a593Smuzhiyun 	/* bring up statistics / event queing */
134*4882a593Smuzhiyun 	if (atomic_dec_and_test(&chip->wq_processing))
135*4882a593Smuzhiyun 		schedule_delayed_work(&chip->work, HZ / 10);
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_ak4113_reinit);
138*4882a593Smuzhiyun 
external_rate(unsigned char rcs1)139*4882a593Smuzhiyun static unsigned int external_rate(unsigned char rcs1)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun 	switch (rcs1 & (AK4113_FS0|AK4113_FS1|AK4113_FS2|AK4113_FS3)) {
142*4882a593Smuzhiyun 	case AK4113_FS_8000HZ:
143*4882a593Smuzhiyun 		return 8000;
144*4882a593Smuzhiyun 	case AK4113_FS_11025HZ:
145*4882a593Smuzhiyun 		return 11025;
146*4882a593Smuzhiyun 	case AK4113_FS_16000HZ:
147*4882a593Smuzhiyun 		return 16000;
148*4882a593Smuzhiyun 	case AK4113_FS_22050HZ:
149*4882a593Smuzhiyun 		return 22050;
150*4882a593Smuzhiyun 	case AK4113_FS_24000HZ:
151*4882a593Smuzhiyun 		return 24000;
152*4882a593Smuzhiyun 	case AK4113_FS_32000HZ:
153*4882a593Smuzhiyun 		return 32000;
154*4882a593Smuzhiyun 	case AK4113_FS_44100HZ:
155*4882a593Smuzhiyun 		return 44100;
156*4882a593Smuzhiyun 	case AK4113_FS_48000HZ:
157*4882a593Smuzhiyun 		return 48000;
158*4882a593Smuzhiyun 	case AK4113_FS_64000HZ:
159*4882a593Smuzhiyun 		return 64000;
160*4882a593Smuzhiyun 	case AK4113_FS_88200HZ:
161*4882a593Smuzhiyun 		return 88200;
162*4882a593Smuzhiyun 	case AK4113_FS_96000HZ:
163*4882a593Smuzhiyun 		return 96000;
164*4882a593Smuzhiyun 	case AK4113_FS_176400HZ:
165*4882a593Smuzhiyun 		return 176400;
166*4882a593Smuzhiyun 	case AK4113_FS_192000HZ:
167*4882a593Smuzhiyun 		return 192000;
168*4882a593Smuzhiyun 	default:
169*4882a593Smuzhiyun 		return 0;
170*4882a593Smuzhiyun 	}
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun 
snd_ak4113_in_error_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)173*4882a593Smuzhiyun static int snd_ak4113_in_error_info(struct snd_kcontrol *kcontrol,
174*4882a593Smuzhiyun 				    struct snd_ctl_elem_info *uinfo)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
177*4882a593Smuzhiyun 	uinfo->count = 1;
178*4882a593Smuzhiyun 	uinfo->value.integer.min = 0;
179*4882a593Smuzhiyun 	uinfo->value.integer.max = LONG_MAX;
180*4882a593Smuzhiyun 	return 0;
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun 
snd_ak4113_in_error_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)183*4882a593Smuzhiyun static int snd_ak4113_in_error_get(struct snd_kcontrol *kcontrol,
184*4882a593Smuzhiyun 				   struct snd_ctl_elem_value *ucontrol)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun 	struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	spin_lock_irq(&chip->lock);
189*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] =
190*4882a593Smuzhiyun 		chip->errors[kcontrol->private_value];
191*4882a593Smuzhiyun 	chip->errors[kcontrol->private_value] = 0;
192*4882a593Smuzhiyun 	spin_unlock_irq(&chip->lock);
193*4882a593Smuzhiyun 	return 0;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun #define snd_ak4113_in_bit_info		snd_ctl_boolean_mono_info
197*4882a593Smuzhiyun 
snd_ak4113_in_bit_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)198*4882a593Smuzhiyun static int snd_ak4113_in_bit_get(struct snd_kcontrol *kcontrol,
199*4882a593Smuzhiyun 				 struct snd_ctl_elem_value *ucontrol)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun 	struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
202*4882a593Smuzhiyun 	unsigned char reg = kcontrol->private_value & 0xff;
203*4882a593Smuzhiyun 	unsigned char bit = (kcontrol->private_value >> 8) & 0xff;
204*4882a593Smuzhiyun 	unsigned char inv = (kcontrol->private_value >> 31) & 1;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] =
207*4882a593Smuzhiyun 		((reg_read(chip, reg) & (1 << bit)) ? 1 : 0) ^ inv;
208*4882a593Smuzhiyun 	return 0;
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun 
snd_ak4113_rx_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)211*4882a593Smuzhiyun static int snd_ak4113_rx_info(struct snd_kcontrol *kcontrol,
212*4882a593Smuzhiyun 			      struct snd_ctl_elem_info *uinfo)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
215*4882a593Smuzhiyun 	uinfo->count = 1;
216*4882a593Smuzhiyun 	uinfo->value.integer.min = 0;
217*4882a593Smuzhiyun 	uinfo->value.integer.max = 5;
218*4882a593Smuzhiyun 	return 0;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun 
snd_ak4113_rx_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)221*4882a593Smuzhiyun static int snd_ak4113_rx_get(struct snd_kcontrol *kcontrol,
222*4882a593Smuzhiyun 			     struct snd_ctl_elem_value *ucontrol)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] =
227*4882a593Smuzhiyun 		(AK4113_IPS(chip->regmap[AK4113_REG_IO1]));
228*4882a593Smuzhiyun 	return 0;
229*4882a593Smuzhiyun }
230*4882a593Smuzhiyun 
snd_ak4113_rx_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)231*4882a593Smuzhiyun static int snd_ak4113_rx_put(struct snd_kcontrol *kcontrol,
232*4882a593Smuzhiyun 			     struct snd_ctl_elem_value *ucontrol)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun 	struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
235*4882a593Smuzhiyun 	int change;
236*4882a593Smuzhiyun 	u8 old_val;
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	spin_lock_irq(&chip->lock);
239*4882a593Smuzhiyun 	old_val = chip->regmap[AK4113_REG_IO1];
240*4882a593Smuzhiyun 	change = ucontrol->value.integer.value[0] != AK4113_IPS(old_val);
241*4882a593Smuzhiyun 	if (change)
242*4882a593Smuzhiyun 		reg_write(chip, AK4113_REG_IO1,
243*4882a593Smuzhiyun 				(old_val & (~AK4113_IPS(0xff))) |
244*4882a593Smuzhiyun 				(AK4113_IPS(ucontrol->value.integer.value[0])));
245*4882a593Smuzhiyun 	spin_unlock_irq(&chip->lock);
246*4882a593Smuzhiyun 	return change;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
snd_ak4113_rate_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)249*4882a593Smuzhiyun static int snd_ak4113_rate_info(struct snd_kcontrol *kcontrol,
250*4882a593Smuzhiyun 				struct snd_ctl_elem_info *uinfo)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
253*4882a593Smuzhiyun 	uinfo->count = 1;
254*4882a593Smuzhiyun 	uinfo->value.integer.min = 0;
255*4882a593Smuzhiyun 	uinfo->value.integer.max = 192000;
256*4882a593Smuzhiyun 	return 0;
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun 
snd_ak4113_rate_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)259*4882a593Smuzhiyun static int snd_ak4113_rate_get(struct snd_kcontrol *kcontrol,
260*4882a593Smuzhiyun 			       struct snd_ctl_elem_value *ucontrol)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun 	struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = external_rate(reg_read(chip,
265*4882a593Smuzhiyun 				AK4113_REG_RCS1));
266*4882a593Smuzhiyun 	return 0;
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun 
snd_ak4113_spdif_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)269*4882a593Smuzhiyun static int snd_ak4113_spdif_info(struct snd_kcontrol *kcontrol,
270*4882a593Smuzhiyun 		struct snd_ctl_elem_info *uinfo)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
273*4882a593Smuzhiyun 	uinfo->count = 1;
274*4882a593Smuzhiyun 	return 0;
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun 
snd_ak4113_spdif_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)277*4882a593Smuzhiyun static int snd_ak4113_spdif_get(struct snd_kcontrol *kcontrol,
278*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun 	struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
281*4882a593Smuzhiyun 	unsigned i;
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun 	for (i = 0; i < AK4113_REG_RXCSB_SIZE; i++)
284*4882a593Smuzhiyun 		ucontrol->value.iec958.status[i] = reg_read(chip,
285*4882a593Smuzhiyun 				AK4113_REG_RXCSB0 + i);
286*4882a593Smuzhiyun 	return 0;
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun 
snd_ak4113_spdif_mask_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)289*4882a593Smuzhiyun static int snd_ak4113_spdif_mask_info(struct snd_kcontrol *kcontrol,
290*4882a593Smuzhiyun 		struct snd_ctl_elem_info *uinfo)
291*4882a593Smuzhiyun {
292*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
293*4882a593Smuzhiyun 	uinfo->count = 1;
294*4882a593Smuzhiyun 	return 0;
295*4882a593Smuzhiyun }
296*4882a593Smuzhiyun 
snd_ak4113_spdif_mask_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)297*4882a593Smuzhiyun static int snd_ak4113_spdif_mask_get(struct snd_kcontrol *kcontrol,
298*4882a593Smuzhiyun 				      struct snd_ctl_elem_value *ucontrol)
299*4882a593Smuzhiyun {
300*4882a593Smuzhiyun 	memset(ucontrol->value.iec958.status, 0xff, AK4113_REG_RXCSB_SIZE);
301*4882a593Smuzhiyun 	return 0;
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun 
snd_ak4113_spdif_pinfo(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)304*4882a593Smuzhiyun static int snd_ak4113_spdif_pinfo(struct snd_kcontrol *kcontrol,
305*4882a593Smuzhiyun 		struct snd_ctl_elem_info *uinfo)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
308*4882a593Smuzhiyun 	uinfo->value.integer.min = 0;
309*4882a593Smuzhiyun 	uinfo->value.integer.max = 0xffff;
310*4882a593Smuzhiyun 	uinfo->count = 4;
311*4882a593Smuzhiyun 	return 0;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun 
snd_ak4113_spdif_pget(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)314*4882a593Smuzhiyun static int snd_ak4113_spdif_pget(struct snd_kcontrol *kcontrol,
315*4882a593Smuzhiyun 				 struct snd_ctl_elem_value *ucontrol)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun 	struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
318*4882a593Smuzhiyun 	unsigned short tmp;
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = 0xf8f2;
321*4882a593Smuzhiyun 	ucontrol->value.integer.value[1] = 0x4e1f;
322*4882a593Smuzhiyun 	tmp = reg_read(chip, AK4113_REG_Pc0) |
323*4882a593Smuzhiyun 		(reg_read(chip, AK4113_REG_Pc1) << 8);
324*4882a593Smuzhiyun 	ucontrol->value.integer.value[2] = tmp;
325*4882a593Smuzhiyun 	tmp = reg_read(chip, AK4113_REG_Pd0) |
326*4882a593Smuzhiyun 		(reg_read(chip, AK4113_REG_Pd1) << 8);
327*4882a593Smuzhiyun 	ucontrol->value.integer.value[3] = tmp;
328*4882a593Smuzhiyun 	return 0;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun 
snd_ak4113_spdif_qinfo(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)331*4882a593Smuzhiyun static int snd_ak4113_spdif_qinfo(struct snd_kcontrol *kcontrol,
332*4882a593Smuzhiyun 		struct snd_ctl_elem_info *uinfo)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
335*4882a593Smuzhiyun 	uinfo->count = AK4113_REG_QSUB_SIZE;
336*4882a593Smuzhiyun 	return 0;
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun 
snd_ak4113_spdif_qget(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)339*4882a593Smuzhiyun static int snd_ak4113_spdif_qget(struct snd_kcontrol *kcontrol,
340*4882a593Smuzhiyun 				 struct snd_ctl_elem_value *ucontrol)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun 	struct ak4113 *chip = snd_kcontrol_chip(kcontrol);
343*4882a593Smuzhiyun 	unsigned i;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	for (i = 0; i < AK4113_REG_QSUB_SIZE; i++)
346*4882a593Smuzhiyun 		ucontrol->value.bytes.data[i] = reg_read(chip,
347*4882a593Smuzhiyun 				AK4113_REG_QSUB_ADDR + i);
348*4882a593Smuzhiyun 	return 0;
349*4882a593Smuzhiyun }
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun /* Don't forget to change AK4113_CONTROLS define!!! */
352*4882a593Smuzhiyun static const struct snd_kcontrol_new snd_ak4113_iec958_controls[] = {
353*4882a593Smuzhiyun {
354*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
355*4882a593Smuzhiyun 	.name =		"IEC958 Parity Errors",
356*4882a593Smuzhiyun 	.access =	SNDRV_CTL_ELEM_ACCESS_READ |
357*4882a593Smuzhiyun 		SNDRV_CTL_ELEM_ACCESS_VOLATILE,
358*4882a593Smuzhiyun 	.info =		snd_ak4113_in_error_info,
359*4882a593Smuzhiyun 	.get =		snd_ak4113_in_error_get,
360*4882a593Smuzhiyun 	.private_value = AK4113_PARITY_ERRORS,
361*4882a593Smuzhiyun },
362*4882a593Smuzhiyun {
363*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
364*4882a593Smuzhiyun 	.name =		"IEC958 V-Bit Errors",
365*4882a593Smuzhiyun 	.access =	SNDRV_CTL_ELEM_ACCESS_READ |
366*4882a593Smuzhiyun 		SNDRV_CTL_ELEM_ACCESS_VOLATILE,
367*4882a593Smuzhiyun 	.info =		snd_ak4113_in_error_info,
368*4882a593Smuzhiyun 	.get =		snd_ak4113_in_error_get,
369*4882a593Smuzhiyun 	.private_value = AK4113_V_BIT_ERRORS,
370*4882a593Smuzhiyun },
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
373*4882a593Smuzhiyun 	.name =		"IEC958 C-CRC Errors",
374*4882a593Smuzhiyun 	.access =	SNDRV_CTL_ELEM_ACCESS_READ |
375*4882a593Smuzhiyun 		SNDRV_CTL_ELEM_ACCESS_VOLATILE,
376*4882a593Smuzhiyun 	.info =		snd_ak4113_in_error_info,
377*4882a593Smuzhiyun 	.get =		snd_ak4113_in_error_get,
378*4882a593Smuzhiyun 	.private_value = AK4113_CCRC_ERRORS,
379*4882a593Smuzhiyun },
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
382*4882a593Smuzhiyun 	.name =		"IEC958 Q-CRC Errors",
383*4882a593Smuzhiyun 	.access =	SNDRV_CTL_ELEM_ACCESS_READ |
384*4882a593Smuzhiyun 		SNDRV_CTL_ELEM_ACCESS_VOLATILE,
385*4882a593Smuzhiyun 	.info =		snd_ak4113_in_error_info,
386*4882a593Smuzhiyun 	.get =		snd_ak4113_in_error_get,
387*4882a593Smuzhiyun 	.private_value = AK4113_QCRC_ERRORS,
388*4882a593Smuzhiyun },
389*4882a593Smuzhiyun {
390*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
391*4882a593Smuzhiyun 	.name =		"IEC958 External Rate",
392*4882a593Smuzhiyun 	.access =	SNDRV_CTL_ELEM_ACCESS_READ |
393*4882a593Smuzhiyun 		SNDRV_CTL_ELEM_ACCESS_VOLATILE,
394*4882a593Smuzhiyun 	.info =		snd_ak4113_rate_info,
395*4882a593Smuzhiyun 	.get =		snd_ak4113_rate_get,
396*4882a593Smuzhiyun },
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
399*4882a593Smuzhiyun 	.name =		SNDRV_CTL_NAME_IEC958("", CAPTURE, MASK),
400*4882a593Smuzhiyun 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
401*4882a593Smuzhiyun 	.info =		snd_ak4113_spdif_mask_info,
402*4882a593Smuzhiyun 	.get =		snd_ak4113_spdif_mask_get,
403*4882a593Smuzhiyun },
404*4882a593Smuzhiyun {
405*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
406*4882a593Smuzhiyun 	.name =		SNDRV_CTL_NAME_IEC958("", CAPTURE, DEFAULT),
407*4882a593Smuzhiyun 	.access =	SNDRV_CTL_ELEM_ACCESS_READ |
408*4882a593Smuzhiyun 		SNDRV_CTL_ELEM_ACCESS_VOLATILE,
409*4882a593Smuzhiyun 	.info =		snd_ak4113_spdif_info,
410*4882a593Smuzhiyun 	.get =		snd_ak4113_spdif_get,
411*4882a593Smuzhiyun },
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
414*4882a593Smuzhiyun 	.name =		"IEC958 Preamble Capture Default",
415*4882a593Smuzhiyun 	.access =	SNDRV_CTL_ELEM_ACCESS_READ |
416*4882a593Smuzhiyun 		SNDRV_CTL_ELEM_ACCESS_VOLATILE,
417*4882a593Smuzhiyun 	.info =		snd_ak4113_spdif_pinfo,
418*4882a593Smuzhiyun 	.get =		snd_ak4113_spdif_pget,
419*4882a593Smuzhiyun },
420*4882a593Smuzhiyun {
421*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
422*4882a593Smuzhiyun 	.name =		"IEC958 Q-subcode Capture Default",
423*4882a593Smuzhiyun 	.access =	SNDRV_CTL_ELEM_ACCESS_READ |
424*4882a593Smuzhiyun 		SNDRV_CTL_ELEM_ACCESS_VOLATILE,
425*4882a593Smuzhiyun 	.info =		snd_ak4113_spdif_qinfo,
426*4882a593Smuzhiyun 	.get =		snd_ak4113_spdif_qget,
427*4882a593Smuzhiyun },
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
430*4882a593Smuzhiyun 	.name =		"IEC958 Audio",
431*4882a593Smuzhiyun 	.access =	SNDRV_CTL_ELEM_ACCESS_READ |
432*4882a593Smuzhiyun 		SNDRV_CTL_ELEM_ACCESS_VOLATILE,
433*4882a593Smuzhiyun 	.info =		snd_ak4113_in_bit_info,
434*4882a593Smuzhiyun 	.get =		snd_ak4113_in_bit_get,
435*4882a593Smuzhiyun 	.private_value = (1<<31) | (1<<8) | AK4113_REG_RCS0,
436*4882a593Smuzhiyun },
437*4882a593Smuzhiyun {
438*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
439*4882a593Smuzhiyun 	.name =		"IEC958 Non-PCM Bitstream",
440*4882a593Smuzhiyun 	.access =	SNDRV_CTL_ELEM_ACCESS_READ |
441*4882a593Smuzhiyun 		SNDRV_CTL_ELEM_ACCESS_VOLATILE,
442*4882a593Smuzhiyun 	.info =		snd_ak4113_in_bit_info,
443*4882a593Smuzhiyun 	.get =		snd_ak4113_in_bit_get,
444*4882a593Smuzhiyun 	.private_value = (0<<8) | AK4113_REG_RCS1,
445*4882a593Smuzhiyun },
446*4882a593Smuzhiyun {
447*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
448*4882a593Smuzhiyun 	.name =		"IEC958 DTS Bitstream",
449*4882a593Smuzhiyun 	.access =	SNDRV_CTL_ELEM_ACCESS_READ |
450*4882a593Smuzhiyun 		SNDRV_CTL_ELEM_ACCESS_VOLATILE,
451*4882a593Smuzhiyun 	.info =		snd_ak4113_in_bit_info,
452*4882a593Smuzhiyun 	.get =		snd_ak4113_in_bit_get,
453*4882a593Smuzhiyun 	.private_value = (1<<8) | AK4113_REG_RCS1,
454*4882a593Smuzhiyun },
455*4882a593Smuzhiyun {
456*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
457*4882a593Smuzhiyun 	.name =		"AK4113 Input Select",
458*4882a593Smuzhiyun 	.access =	SNDRV_CTL_ELEM_ACCESS_READ |
459*4882a593Smuzhiyun 		SNDRV_CTL_ELEM_ACCESS_WRITE,
460*4882a593Smuzhiyun 	.info =		snd_ak4113_rx_info,
461*4882a593Smuzhiyun 	.get =		snd_ak4113_rx_get,
462*4882a593Smuzhiyun 	.put =		snd_ak4113_rx_put,
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun };
465*4882a593Smuzhiyun 
snd_ak4113_proc_regs_read(struct snd_info_entry * entry,struct snd_info_buffer * buffer)466*4882a593Smuzhiyun static void snd_ak4113_proc_regs_read(struct snd_info_entry *entry,
467*4882a593Smuzhiyun 		struct snd_info_buffer *buffer)
468*4882a593Smuzhiyun {
469*4882a593Smuzhiyun 	struct ak4113 *ak4113 = entry->private_data;
470*4882a593Smuzhiyun 	int reg, val;
471*4882a593Smuzhiyun 	/* all ak4113 registers 0x00 - 0x1c */
472*4882a593Smuzhiyun 	for (reg = 0; reg < 0x1d; reg++) {
473*4882a593Smuzhiyun 		val = reg_read(ak4113, reg);
474*4882a593Smuzhiyun 		snd_iprintf(buffer, "0x%02x = 0x%02x\n", reg, val);
475*4882a593Smuzhiyun 	}
476*4882a593Smuzhiyun }
477*4882a593Smuzhiyun 
snd_ak4113_proc_init(struct ak4113 * ak4113)478*4882a593Smuzhiyun static void snd_ak4113_proc_init(struct ak4113 *ak4113)
479*4882a593Smuzhiyun {
480*4882a593Smuzhiyun 	snd_card_ro_proc_new(ak4113->card, "ak4113", ak4113,
481*4882a593Smuzhiyun 			     snd_ak4113_proc_regs_read);
482*4882a593Smuzhiyun }
483*4882a593Smuzhiyun 
snd_ak4113_build(struct ak4113 * ak4113,struct snd_pcm_substream * cap_substream)484*4882a593Smuzhiyun int snd_ak4113_build(struct ak4113 *ak4113,
485*4882a593Smuzhiyun 		struct snd_pcm_substream *cap_substream)
486*4882a593Smuzhiyun {
487*4882a593Smuzhiyun 	struct snd_kcontrol *kctl;
488*4882a593Smuzhiyun 	unsigned int idx;
489*4882a593Smuzhiyun 	int err;
490*4882a593Smuzhiyun 
491*4882a593Smuzhiyun 	if (snd_BUG_ON(!cap_substream))
492*4882a593Smuzhiyun 		return -EINVAL;
493*4882a593Smuzhiyun 	ak4113->substream = cap_substream;
494*4882a593Smuzhiyun 	for (idx = 0; idx < AK4113_CONTROLS; idx++) {
495*4882a593Smuzhiyun 		kctl = snd_ctl_new1(&snd_ak4113_iec958_controls[idx], ak4113);
496*4882a593Smuzhiyun 		if (kctl == NULL)
497*4882a593Smuzhiyun 			return -ENOMEM;
498*4882a593Smuzhiyun 		kctl->id.device = cap_substream->pcm->device;
499*4882a593Smuzhiyun 		kctl->id.subdevice = cap_substream->number;
500*4882a593Smuzhiyun 		err = snd_ctl_add(ak4113->card, kctl);
501*4882a593Smuzhiyun 		if (err < 0)
502*4882a593Smuzhiyun 			return err;
503*4882a593Smuzhiyun 		ak4113->kctls[idx] = kctl;
504*4882a593Smuzhiyun 	}
505*4882a593Smuzhiyun 	snd_ak4113_proc_init(ak4113);
506*4882a593Smuzhiyun 	/* trigger workq */
507*4882a593Smuzhiyun 	schedule_delayed_work(&ak4113->work, HZ / 10);
508*4882a593Smuzhiyun 	return 0;
509*4882a593Smuzhiyun }
510*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_ak4113_build);
511*4882a593Smuzhiyun 
snd_ak4113_external_rate(struct ak4113 * ak4113)512*4882a593Smuzhiyun int snd_ak4113_external_rate(struct ak4113 *ak4113)
513*4882a593Smuzhiyun {
514*4882a593Smuzhiyun 	unsigned char rcs1;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	rcs1 = reg_read(ak4113, AK4113_REG_RCS1);
517*4882a593Smuzhiyun 	return external_rate(rcs1);
518*4882a593Smuzhiyun }
519*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_ak4113_external_rate);
520*4882a593Smuzhiyun 
snd_ak4113_check_rate_and_errors(struct ak4113 * ak4113,unsigned int flags)521*4882a593Smuzhiyun int snd_ak4113_check_rate_and_errors(struct ak4113 *ak4113, unsigned int flags)
522*4882a593Smuzhiyun {
523*4882a593Smuzhiyun 	struct snd_pcm_runtime *runtime =
524*4882a593Smuzhiyun 		ak4113->substream ? ak4113->substream->runtime : NULL;
525*4882a593Smuzhiyun 	unsigned long _flags;
526*4882a593Smuzhiyun 	int res = 0;
527*4882a593Smuzhiyun 	unsigned char rcs0, rcs1, rcs2;
528*4882a593Smuzhiyun 	unsigned char c0, c1;
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	rcs1 = reg_read(ak4113, AK4113_REG_RCS1);
531*4882a593Smuzhiyun 	if (flags & AK4113_CHECK_NO_STAT)
532*4882a593Smuzhiyun 		goto __rate;
533*4882a593Smuzhiyun 	rcs0 = reg_read(ak4113, AK4113_REG_RCS0);
534*4882a593Smuzhiyun 	rcs2 = reg_read(ak4113, AK4113_REG_RCS2);
535*4882a593Smuzhiyun 	spin_lock_irqsave(&ak4113->lock, _flags);
536*4882a593Smuzhiyun 	if (rcs0 & AK4113_PAR)
537*4882a593Smuzhiyun 		ak4113->errors[AK4113_PARITY_ERRORS]++;
538*4882a593Smuzhiyun 	if (rcs0 & AK4113_V)
539*4882a593Smuzhiyun 		ak4113->errors[AK4113_V_BIT_ERRORS]++;
540*4882a593Smuzhiyun 	if (rcs2 & AK4113_CCRC)
541*4882a593Smuzhiyun 		ak4113->errors[AK4113_CCRC_ERRORS]++;
542*4882a593Smuzhiyun 	if (rcs2 & AK4113_QCRC)
543*4882a593Smuzhiyun 		ak4113->errors[AK4113_QCRC_ERRORS]++;
544*4882a593Smuzhiyun 	c0 = (ak4113->rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC |
545*4882a593Smuzhiyun 				AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK)) ^
546*4882a593Smuzhiyun 		(rcs0 & (AK4113_QINT | AK4113_CINT | AK4113_STC |
547*4882a593Smuzhiyun 			 AK4113_AUDION | AK4113_AUTO | AK4113_UNLCK));
548*4882a593Smuzhiyun 	c1 = (ak4113->rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM |
549*4882a593Smuzhiyun 				AK4113_DAT | 0xf0)) ^
550*4882a593Smuzhiyun 		(rcs1 & (AK4113_DTSCD | AK4113_NPCM | AK4113_PEM |
551*4882a593Smuzhiyun 			 AK4113_DAT | 0xf0));
552*4882a593Smuzhiyun 	ak4113->rcs0 = rcs0 & ~(AK4113_QINT | AK4113_CINT | AK4113_STC);
553*4882a593Smuzhiyun 	ak4113->rcs1 = rcs1;
554*4882a593Smuzhiyun 	ak4113->rcs2 = rcs2;
555*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ak4113->lock, _flags);
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	if (rcs0 & AK4113_PAR)
558*4882a593Smuzhiyun 		snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
559*4882a593Smuzhiyun 				&ak4113->kctls[0]->id);
560*4882a593Smuzhiyun 	if (rcs0 & AK4113_V)
561*4882a593Smuzhiyun 		snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
562*4882a593Smuzhiyun 				&ak4113->kctls[1]->id);
563*4882a593Smuzhiyun 	if (rcs2 & AK4113_CCRC)
564*4882a593Smuzhiyun 		snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
565*4882a593Smuzhiyun 				&ak4113->kctls[2]->id);
566*4882a593Smuzhiyun 	if (rcs2 & AK4113_QCRC)
567*4882a593Smuzhiyun 		snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
568*4882a593Smuzhiyun 				&ak4113->kctls[3]->id);
569*4882a593Smuzhiyun 
570*4882a593Smuzhiyun 	/* rate change */
571*4882a593Smuzhiyun 	if (c1 & 0xf0)
572*4882a593Smuzhiyun 		snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
573*4882a593Smuzhiyun 				&ak4113->kctls[4]->id);
574*4882a593Smuzhiyun 
575*4882a593Smuzhiyun 	if ((c1 & AK4113_PEM) | (c0 & AK4113_CINT))
576*4882a593Smuzhiyun 		snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
577*4882a593Smuzhiyun 				&ak4113->kctls[6]->id);
578*4882a593Smuzhiyun 	if (c0 & AK4113_QINT)
579*4882a593Smuzhiyun 		snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
580*4882a593Smuzhiyun 				&ak4113->kctls[8]->id);
581*4882a593Smuzhiyun 
582*4882a593Smuzhiyun 	if (c0 & AK4113_AUDION)
583*4882a593Smuzhiyun 		snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
584*4882a593Smuzhiyun 				&ak4113->kctls[9]->id);
585*4882a593Smuzhiyun 	if (c1 & AK4113_NPCM)
586*4882a593Smuzhiyun 		snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
587*4882a593Smuzhiyun 				&ak4113->kctls[10]->id);
588*4882a593Smuzhiyun 	if (c1 & AK4113_DTSCD)
589*4882a593Smuzhiyun 		snd_ctl_notify(ak4113->card, SNDRV_CTL_EVENT_MASK_VALUE,
590*4882a593Smuzhiyun 				&ak4113->kctls[11]->id);
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 	if (ak4113->change_callback && (c0 | c1) != 0)
593*4882a593Smuzhiyun 		ak4113->change_callback(ak4113, c0, c1);
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun __rate:
596*4882a593Smuzhiyun 	/* compare rate */
597*4882a593Smuzhiyun 	res = external_rate(rcs1);
598*4882a593Smuzhiyun 	if (!(flags & AK4113_CHECK_NO_RATE) && runtime &&
599*4882a593Smuzhiyun 			(runtime->rate != res)) {
600*4882a593Smuzhiyun 		snd_pcm_stream_lock_irqsave(ak4113->substream, _flags);
601*4882a593Smuzhiyun 		if (snd_pcm_running(ak4113->substream)) {
602*4882a593Smuzhiyun 			/*printk(KERN_DEBUG "rate changed (%i <- %i)\n",
603*4882a593Smuzhiyun 			 * runtime->rate, res); */
604*4882a593Smuzhiyun 			snd_pcm_stop(ak4113->substream,
605*4882a593Smuzhiyun 					SNDRV_PCM_STATE_DRAINING);
606*4882a593Smuzhiyun 			wake_up(&runtime->sleep);
607*4882a593Smuzhiyun 			res = 1;
608*4882a593Smuzhiyun 		}
609*4882a593Smuzhiyun 		snd_pcm_stream_unlock_irqrestore(ak4113->substream, _flags);
610*4882a593Smuzhiyun 	}
611*4882a593Smuzhiyun 	return res;
612*4882a593Smuzhiyun }
613*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(snd_ak4113_check_rate_and_errors);
614*4882a593Smuzhiyun 
ak4113_stats(struct work_struct * work)615*4882a593Smuzhiyun static void ak4113_stats(struct work_struct *work)
616*4882a593Smuzhiyun {
617*4882a593Smuzhiyun 	struct ak4113 *chip = container_of(work, struct ak4113, work.work);
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 	if (atomic_inc_return(&chip->wq_processing) == 1)
620*4882a593Smuzhiyun 		snd_ak4113_check_rate_and_errors(chip, chip->check_flags);
621*4882a593Smuzhiyun 
622*4882a593Smuzhiyun 	if (atomic_dec_and_test(&chip->wq_processing))
623*4882a593Smuzhiyun 		schedule_delayed_work(&chip->work, HZ / 10);
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun #ifdef CONFIG_PM
snd_ak4113_suspend(struct ak4113 * chip)627*4882a593Smuzhiyun void snd_ak4113_suspend(struct ak4113 *chip)
628*4882a593Smuzhiyun {
629*4882a593Smuzhiyun 	atomic_inc(&chip->wq_processing); /* don't schedule new work */
630*4882a593Smuzhiyun 	cancel_delayed_work_sync(&chip->work);
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun EXPORT_SYMBOL(snd_ak4113_suspend);
633*4882a593Smuzhiyun 
snd_ak4113_resume(struct ak4113 * chip)634*4882a593Smuzhiyun void snd_ak4113_resume(struct ak4113 *chip)
635*4882a593Smuzhiyun {
636*4882a593Smuzhiyun 	atomic_dec(&chip->wq_processing);
637*4882a593Smuzhiyun 	snd_ak4113_reinit(chip);
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun EXPORT_SYMBOL(snd_ak4113_resume);
640*4882a593Smuzhiyun #endif
641