xref: /OK3568_Linux_fs/kernel/sound/i2c/cs8427.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  Routines for control of the CS8427 via i2c bus
4*4882a593Smuzhiyun  *  IEC958 (S/PDIF) receiver & transmitter by Cirrus Logic
5*4882a593Smuzhiyun  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/slab.h>
9*4882a593Smuzhiyun #include <linux/delay.h>
10*4882a593Smuzhiyun #include <linux/init.h>
11*4882a593Smuzhiyun #include <linux/bitrev.h>
12*4882a593Smuzhiyun #include <linux/module.h>
13*4882a593Smuzhiyun #include <asm/unaligned.h>
14*4882a593Smuzhiyun #include <sound/core.h>
15*4882a593Smuzhiyun #include <sound/control.h>
16*4882a593Smuzhiyun #include <sound/pcm.h>
17*4882a593Smuzhiyun #include <sound/cs8427.h>
18*4882a593Smuzhiyun #include <sound/asoundef.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun static void snd_cs8427_reset(struct snd_i2c_device *cs8427);
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
23*4882a593Smuzhiyun MODULE_DESCRIPTION("IEC958 (S/PDIF) receiver & transmitter by Cirrus Logic");
24*4882a593Smuzhiyun MODULE_LICENSE("GPL");
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define CS8427_ADDR			(0x20>>1) /* fixed address */
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun struct cs8427_stream {
29*4882a593Smuzhiyun 	struct snd_pcm_substream *substream;
30*4882a593Smuzhiyun 	char hw_status[24];		/* hardware status */
31*4882a593Smuzhiyun 	char def_status[24];		/* default status */
32*4882a593Smuzhiyun 	char pcm_status[24];		/* PCM private status */
33*4882a593Smuzhiyun 	char hw_udata[32];
34*4882a593Smuzhiyun 	struct snd_kcontrol *pcm_ctl;
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun struct cs8427 {
38*4882a593Smuzhiyun 	unsigned char regmap[0x14];	/* map of first 1 + 13 registers */
39*4882a593Smuzhiyun 	unsigned int rate;
40*4882a593Smuzhiyun 	unsigned int reset_timeout;
41*4882a593Smuzhiyun 	struct cs8427_stream playback;
42*4882a593Smuzhiyun 	struct cs8427_stream capture;
43*4882a593Smuzhiyun };
44*4882a593Smuzhiyun 
snd_cs8427_reg_write(struct snd_i2c_device * device,unsigned char reg,unsigned char val)45*4882a593Smuzhiyun int snd_cs8427_reg_write(struct snd_i2c_device *device, unsigned char reg,
46*4882a593Smuzhiyun 			 unsigned char val)
47*4882a593Smuzhiyun {
48*4882a593Smuzhiyun 	int err;
49*4882a593Smuzhiyun 	unsigned char buf[2];
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	buf[0] = reg & 0x7f;
52*4882a593Smuzhiyun 	buf[1] = val;
53*4882a593Smuzhiyun 	if ((err = snd_i2c_sendbytes(device, buf, 2)) != 2) {
54*4882a593Smuzhiyun 		snd_printk(KERN_ERR "unable to send bytes 0x%02x:0x%02x "
55*4882a593Smuzhiyun 			   "to CS8427 (%i)\n", buf[0], buf[1], err);
56*4882a593Smuzhiyun 		return err < 0 ? err : -EIO;
57*4882a593Smuzhiyun 	}
58*4882a593Smuzhiyun 	return 0;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun EXPORT_SYMBOL(snd_cs8427_reg_write);
62*4882a593Smuzhiyun 
snd_cs8427_reg_read(struct snd_i2c_device * device,unsigned char reg)63*4882a593Smuzhiyun static int snd_cs8427_reg_read(struct snd_i2c_device *device, unsigned char reg)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun 	int err;
66*4882a593Smuzhiyun 	unsigned char buf;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	if ((err = snd_i2c_sendbytes(device, &reg, 1)) != 1) {
69*4882a593Smuzhiyun 		snd_printk(KERN_ERR "unable to send register 0x%x byte "
70*4882a593Smuzhiyun 			   "to CS8427\n", reg);
71*4882a593Smuzhiyun 		return err < 0 ? err : -EIO;
72*4882a593Smuzhiyun 	}
73*4882a593Smuzhiyun 	if ((err = snd_i2c_readbytes(device, &buf, 1)) != 1) {
74*4882a593Smuzhiyun 		snd_printk(KERN_ERR "unable to read register 0x%x byte "
75*4882a593Smuzhiyun 			   "from CS8427\n", reg);
76*4882a593Smuzhiyun 		return err < 0 ? err : -EIO;
77*4882a593Smuzhiyun 	}
78*4882a593Smuzhiyun 	return buf;
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun 
snd_cs8427_select_corudata(struct snd_i2c_device * device,int udata)81*4882a593Smuzhiyun static int snd_cs8427_select_corudata(struct snd_i2c_device *device, int udata)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun 	struct cs8427 *chip = device->private_data;
84*4882a593Smuzhiyun 	int err;
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	udata = udata ? CS8427_BSEL : 0;
87*4882a593Smuzhiyun 	if (udata != (chip->regmap[CS8427_REG_CSDATABUF] & udata)) {
88*4882a593Smuzhiyun 		chip->regmap[CS8427_REG_CSDATABUF] &= ~CS8427_BSEL;
89*4882a593Smuzhiyun 		chip->regmap[CS8427_REG_CSDATABUF] |= udata;
90*4882a593Smuzhiyun 		err = snd_cs8427_reg_write(device, CS8427_REG_CSDATABUF,
91*4882a593Smuzhiyun 					   chip->regmap[CS8427_REG_CSDATABUF]);
92*4882a593Smuzhiyun 		if (err < 0)
93*4882a593Smuzhiyun 			return err;
94*4882a593Smuzhiyun 	}
95*4882a593Smuzhiyun 	return 0;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun 
snd_cs8427_send_corudata(struct snd_i2c_device * device,int udata,unsigned char * ndata,int count)98*4882a593Smuzhiyun static int snd_cs8427_send_corudata(struct snd_i2c_device *device,
99*4882a593Smuzhiyun 				    int udata,
100*4882a593Smuzhiyun 				    unsigned char *ndata,
101*4882a593Smuzhiyun 				    int count)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun 	struct cs8427 *chip = device->private_data;
104*4882a593Smuzhiyun 	char *hw_data = udata ?
105*4882a593Smuzhiyun 		chip->playback.hw_udata : chip->playback.hw_status;
106*4882a593Smuzhiyun 	unsigned char data[32];
107*4882a593Smuzhiyun 	int err, idx;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	if (!memcmp(hw_data, ndata, count))
110*4882a593Smuzhiyun 		return 0;
111*4882a593Smuzhiyun 	if ((err = snd_cs8427_select_corudata(device, udata)) < 0)
112*4882a593Smuzhiyun 		return err;
113*4882a593Smuzhiyun 	memcpy(hw_data, ndata, count);
114*4882a593Smuzhiyun 	if (udata) {
115*4882a593Smuzhiyun 		memset(data, 0, sizeof(data));
116*4882a593Smuzhiyun 		if (memcmp(hw_data, data, count) == 0) {
117*4882a593Smuzhiyun 			chip->regmap[CS8427_REG_UDATABUF] &= ~CS8427_UBMMASK;
118*4882a593Smuzhiyun 			chip->regmap[CS8427_REG_UDATABUF] |= CS8427_UBMZEROS |
119*4882a593Smuzhiyun 				CS8427_EFTUI;
120*4882a593Smuzhiyun 			err = snd_cs8427_reg_write(device, CS8427_REG_UDATABUF,
121*4882a593Smuzhiyun 						   chip->regmap[CS8427_REG_UDATABUF]);
122*4882a593Smuzhiyun 			return err < 0 ? err : 0;
123*4882a593Smuzhiyun 		}
124*4882a593Smuzhiyun 	}
125*4882a593Smuzhiyun 	data[0] = CS8427_REG_AUTOINC | CS8427_REG_CORU_DATABUF;
126*4882a593Smuzhiyun 	for (idx = 0; idx < count; idx++)
127*4882a593Smuzhiyun 		data[idx + 1] = bitrev8(ndata[idx]);
128*4882a593Smuzhiyun 	if (snd_i2c_sendbytes(device, data, count + 1) != count + 1)
129*4882a593Smuzhiyun 		return -EIO;
130*4882a593Smuzhiyun 	return 1;
131*4882a593Smuzhiyun }
132*4882a593Smuzhiyun 
snd_cs8427_free(struct snd_i2c_device * device)133*4882a593Smuzhiyun static void snd_cs8427_free(struct snd_i2c_device *device)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	kfree(device->private_data);
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun 
snd_cs8427_init(struct snd_i2c_bus * bus,struct snd_i2c_device * device)138*4882a593Smuzhiyun int snd_cs8427_init(struct snd_i2c_bus *bus,
139*4882a593Smuzhiyun 		    struct snd_i2c_device *device)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun 	static unsigned char initvals1[] = {
142*4882a593Smuzhiyun 	  CS8427_REG_CONTROL1 | CS8427_REG_AUTOINC,
143*4882a593Smuzhiyun 	  /* CS8427_REG_CONTROL1: RMCK to OMCK, valid PCM audio, disable mutes,
144*4882a593Smuzhiyun 	     TCBL=output */
145*4882a593Smuzhiyun 	  CS8427_SWCLK | CS8427_TCBLDIR,
146*4882a593Smuzhiyun 	  /* CS8427_REG_CONTROL2: hold last valid audio sample, RMCK=256*Fs,
147*4882a593Smuzhiyun 	     normal stereo operation */
148*4882a593Smuzhiyun 	  0x00,
149*4882a593Smuzhiyun 	  /* CS8427_REG_DATAFLOW: output drivers normal operation, Tx<=serial,
150*4882a593Smuzhiyun 	     Rx=>serial */
151*4882a593Smuzhiyun 	  CS8427_TXDSERIAL | CS8427_SPDAES3RECEIVER,
152*4882a593Smuzhiyun 	  /* CS8427_REG_CLOCKSOURCE: Run off, CMCK=256*Fs,
153*4882a593Smuzhiyun 	     output time base = OMCK, input time base = recovered input clock,
154*4882a593Smuzhiyun 	     recovered input clock source is ILRCK changed to AES3INPUT
155*4882a593Smuzhiyun 	     (workaround, see snd_cs8427_reset) */
156*4882a593Smuzhiyun 	  CS8427_RXDILRCK,
157*4882a593Smuzhiyun 	  /* CS8427_REG_SERIALINPUT: Serial audio input port data format = I2S,
158*4882a593Smuzhiyun 	     24-bit, 64*Fsi */
159*4882a593Smuzhiyun 	  CS8427_SIDEL | CS8427_SILRPOL,
160*4882a593Smuzhiyun 	  /* CS8427_REG_SERIALOUTPUT: Serial audio output port data format
161*4882a593Smuzhiyun 	     = I2S, 24-bit, 64*Fsi */
162*4882a593Smuzhiyun 	  CS8427_SODEL | CS8427_SOLRPOL,
163*4882a593Smuzhiyun 	};
164*4882a593Smuzhiyun 	static unsigned char initvals2[] = {
165*4882a593Smuzhiyun 	  CS8427_REG_RECVERRMASK | CS8427_REG_AUTOINC,
166*4882a593Smuzhiyun 	  /* CS8427_REG_RECVERRMASK: unmask the input PLL clock, V, confidence,
167*4882a593Smuzhiyun 	     biphase, parity status bits */
168*4882a593Smuzhiyun 	  /* CS8427_UNLOCK | CS8427_V | CS8427_CONF | CS8427_BIP | CS8427_PAR,*/
169*4882a593Smuzhiyun 	  0xff, /* set everything */
170*4882a593Smuzhiyun 	  /* CS8427_REG_CSDATABUF:
171*4882a593Smuzhiyun 	     Registers 32-55 window to CS buffer
172*4882a593Smuzhiyun 	     Inhibit D->E transfers from overwriting first 5 bytes of CS data.
173*4882a593Smuzhiyun 	     Inhibit D->E transfers (all) of CS data.
174*4882a593Smuzhiyun 	     Allow E->F transfer of CS data.
175*4882a593Smuzhiyun 	     One byte mode; both A/B channels get same written CB data.
176*4882a593Smuzhiyun 	     A channel info is output to chip's EMPH* pin. */
177*4882a593Smuzhiyun 	  CS8427_CBMR | CS8427_DETCI,
178*4882a593Smuzhiyun 	  /* CS8427_REG_UDATABUF:
179*4882a593Smuzhiyun 	     Use internal buffer to transmit User (U) data.
180*4882a593Smuzhiyun 	     Chip's U pin is an output.
181*4882a593Smuzhiyun 	     Transmit all O's for user data.
182*4882a593Smuzhiyun 	     Inhibit D->E transfers.
183*4882a593Smuzhiyun 	     Inhibit E->F transfers. */
184*4882a593Smuzhiyun 	  CS8427_UD | CS8427_EFTUI | CS8427_DETUI,
185*4882a593Smuzhiyun 	};
186*4882a593Smuzhiyun 	struct cs8427 *chip = device->private_data;
187*4882a593Smuzhiyun 	int err;
188*4882a593Smuzhiyun 	unsigned char buf[24];
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	snd_i2c_lock(bus);
191*4882a593Smuzhiyun 	err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER);
192*4882a593Smuzhiyun 	if (err != CS8427_VER8427A) {
193*4882a593Smuzhiyun 		/* give second chance */
194*4882a593Smuzhiyun 		snd_printk(KERN_WARNING "invalid CS8427 signature 0x%x: "
195*4882a593Smuzhiyun 			   "let me try again...\n", err);
196*4882a593Smuzhiyun 		err = snd_cs8427_reg_read(device, CS8427_REG_ID_AND_VER);
197*4882a593Smuzhiyun 	}
198*4882a593Smuzhiyun 	if (err != CS8427_VER8427A) {
199*4882a593Smuzhiyun 		snd_i2c_unlock(bus);
200*4882a593Smuzhiyun 		snd_printk(KERN_ERR "unable to find CS8427 signature "
201*4882a593Smuzhiyun 			   "(expected 0x%x, read 0x%x),\n",
202*4882a593Smuzhiyun 			   CS8427_VER8427A, err);
203*4882a593Smuzhiyun 		snd_printk(KERN_ERR "   initialization is not completed\n");
204*4882a593Smuzhiyun 		return -EFAULT;
205*4882a593Smuzhiyun 	}
206*4882a593Smuzhiyun 	/* turn off run bit while making changes to configuration */
207*4882a593Smuzhiyun 	err = snd_cs8427_reg_write(device, CS8427_REG_CLOCKSOURCE, 0x00);
208*4882a593Smuzhiyun 	if (err < 0)
209*4882a593Smuzhiyun 		goto __fail;
210*4882a593Smuzhiyun 	/* send initial values */
211*4882a593Smuzhiyun 	memcpy(chip->regmap + (initvals1[0] & 0x7f), initvals1 + 1, 6);
212*4882a593Smuzhiyun 	if ((err = snd_i2c_sendbytes(device, initvals1, 7)) != 7) {
213*4882a593Smuzhiyun 		err = err < 0 ? err : -EIO;
214*4882a593Smuzhiyun 		goto __fail;
215*4882a593Smuzhiyun 	}
216*4882a593Smuzhiyun 	/* Turn off CS8427 interrupt stuff that is not used in hardware */
217*4882a593Smuzhiyun 	memset(buf, 0, 7);
218*4882a593Smuzhiyun 	/* from address 9 to 15 */
219*4882a593Smuzhiyun 	buf[0] = 9;	/* register */
220*4882a593Smuzhiyun 	if ((err = snd_i2c_sendbytes(device, buf, 7)) != 7)
221*4882a593Smuzhiyun 		goto __fail;
222*4882a593Smuzhiyun 	/* send transfer initialization sequence */
223*4882a593Smuzhiyun 	memcpy(chip->regmap + (initvals2[0] & 0x7f), initvals2 + 1, 3);
224*4882a593Smuzhiyun 	if ((err = snd_i2c_sendbytes(device, initvals2, 4)) != 4) {
225*4882a593Smuzhiyun 		err = err < 0 ? err : -EIO;
226*4882a593Smuzhiyun 		goto __fail;
227*4882a593Smuzhiyun 	}
228*4882a593Smuzhiyun 	/* write default channel status bytes */
229*4882a593Smuzhiyun 	put_unaligned_le32(SNDRV_PCM_DEFAULT_CON_SPDIF, buf);
230*4882a593Smuzhiyun 	memset(buf + 4, 0, 24 - 4);
231*4882a593Smuzhiyun 	if (snd_cs8427_send_corudata(device, 0, buf, 24) < 0)
232*4882a593Smuzhiyun 		goto __fail;
233*4882a593Smuzhiyun 	memcpy(chip->playback.def_status, buf, 24);
234*4882a593Smuzhiyun 	memcpy(chip->playback.pcm_status, buf, 24);
235*4882a593Smuzhiyun 	snd_i2c_unlock(bus);
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun 	/* turn on run bit and rock'n'roll */
238*4882a593Smuzhiyun 	snd_cs8427_reset(device);
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	return 0;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun __fail:
243*4882a593Smuzhiyun 	snd_i2c_unlock(bus);
244*4882a593Smuzhiyun 
245*4882a593Smuzhiyun 	return err;
246*4882a593Smuzhiyun }
247*4882a593Smuzhiyun EXPORT_SYMBOL(snd_cs8427_init);
248*4882a593Smuzhiyun 
snd_cs8427_create(struct snd_i2c_bus * bus,unsigned char addr,unsigned int reset_timeout,struct snd_i2c_device ** r_cs8427)249*4882a593Smuzhiyun int snd_cs8427_create(struct snd_i2c_bus *bus,
250*4882a593Smuzhiyun 		      unsigned char addr,
251*4882a593Smuzhiyun 		      unsigned int reset_timeout,
252*4882a593Smuzhiyun 		      struct snd_i2c_device **r_cs8427)
253*4882a593Smuzhiyun {
254*4882a593Smuzhiyun 	int err;
255*4882a593Smuzhiyun 	struct cs8427 *chip;
256*4882a593Smuzhiyun 	struct snd_i2c_device *device;
257*4882a593Smuzhiyun 
258*4882a593Smuzhiyun 	err = snd_i2c_device_create(bus, "CS8427", CS8427_ADDR | (addr & 7),
259*4882a593Smuzhiyun 				    &device);
260*4882a593Smuzhiyun 	if (err < 0)
261*4882a593Smuzhiyun 		return err;
262*4882a593Smuzhiyun 	chip = device->private_data = kzalloc(sizeof(*chip), GFP_KERNEL);
263*4882a593Smuzhiyun 	if (chip == NULL) {
264*4882a593Smuzhiyun 		snd_i2c_device_free(device);
265*4882a593Smuzhiyun 		return -ENOMEM;
266*4882a593Smuzhiyun 	}
267*4882a593Smuzhiyun 	device->private_free = snd_cs8427_free;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	if (reset_timeout < 1)
270*4882a593Smuzhiyun 		reset_timeout = 1;
271*4882a593Smuzhiyun 	chip->reset_timeout = reset_timeout;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	err = snd_cs8427_init(bus, device);
274*4882a593Smuzhiyun 	if (err)
275*4882a593Smuzhiyun 		goto __fail;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun #if 0	// it's nice for read tests
278*4882a593Smuzhiyun 	{
279*4882a593Smuzhiyun 	char buf[128];
280*4882a593Smuzhiyun 	int xx;
281*4882a593Smuzhiyun 	buf[0] = 0x81;
282*4882a593Smuzhiyun 	snd_i2c_sendbytes(device, buf, 1);
283*4882a593Smuzhiyun 	snd_i2c_readbytes(device, buf, 127);
284*4882a593Smuzhiyun 	for (xx = 0; xx < 127; xx++)
285*4882a593Smuzhiyun 		printk(KERN_DEBUG "reg[0x%x] = 0x%x\n", xx+1, buf[xx]);
286*4882a593Smuzhiyun 	}
287*4882a593Smuzhiyun #endif
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	if (r_cs8427)
290*4882a593Smuzhiyun 		*r_cs8427 = device;
291*4882a593Smuzhiyun 	return 0;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun       __fail:
294*4882a593Smuzhiyun       	snd_i2c_device_free(device);
295*4882a593Smuzhiyun       	return err < 0 ? err : -EIO;
296*4882a593Smuzhiyun }
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun EXPORT_SYMBOL(snd_cs8427_create);
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun /*
301*4882a593Smuzhiyun  * Reset the chip using run bit, also lock PLL using ILRCK and
302*4882a593Smuzhiyun  * put back AES3INPUT. This workaround is described in latest
303*4882a593Smuzhiyun  * CS8427 datasheet, otherwise TXDSERIAL will not work.
304*4882a593Smuzhiyun  */
snd_cs8427_reset(struct snd_i2c_device * cs8427)305*4882a593Smuzhiyun static void snd_cs8427_reset(struct snd_i2c_device *cs8427)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun 	struct cs8427 *chip;
308*4882a593Smuzhiyun 	unsigned long end_time;
309*4882a593Smuzhiyun 	int data, aes3input = 0;
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	if (snd_BUG_ON(!cs8427))
312*4882a593Smuzhiyun 		return;
313*4882a593Smuzhiyun 	chip = cs8427->private_data;
314*4882a593Smuzhiyun 	snd_i2c_lock(cs8427->bus);
315*4882a593Smuzhiyun 	if ((chip->regmap[CS8427_REG_CLOCKSOURCE] & CS8427_RXDAES3INPUT) ==
316*4882a593Smuzhiyun 	    CS8427_RXDAES3INPUT)  /* AES3 bit is set */
317*4882a593Smuzhiyun 		aes3input = 1;
318*4882a593Smuzhiyun 	chip->regmap[CS8427_REG_CLOCKSOURCE] &= ~(CS8427_RUN | CS8427_RXDMASK);
319*4882a593Smuzhiyun 	snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE,
320*4882a593Smuzhiyun 			     chip->regmap[CS8427_REG_CLOCKSOURCE]);
321*4882a593Smuzhiyun 	udelay(200);
322*4882a593Smuzhiyun 	chip->regmap[CS8427_REG_CLOCKSOURCE] |= CS8427_RUN | CS8427_RXDILRCK;
323*4882a593Smuzhiyun 	snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE,
324*4882a593Smuzhiyun 			     chip->regmap[CS8427_REG_CLOCKSOURCE]);
325*4882a593Smuzhiyun 	udelay(200);
326*4882a593Smuzhiyun 	snd_i2c_unlock(cs8427->bus);
327*4882a593Smuzhiyun 	end_time = jiffies + chip->reset_timeout;
328*4882a593Smuzhiyun 	while (time_after_eq(end_time, jiffies)) {
329*4882a593Smuzhiyun 		snd_i2c_lock(cs8427->bus);
330*4882a593Smuzhiyun 		data = snd_cs8427_reg_read(cs8427, CS8427_REG_RECVERRORS);
331*4882a593Smuzhiyun 		snd_i2c_unlock(cs8427->bus);
332*4882a593Smuzhiyun 		if (!(data & CS8427_UNLOCK))
333*4882a593Smuzhiyun 			break;
334*4882a593Smuzhiyun 		schedule_timeout_uninterruptible(1);
335*4882a593Smuzhiyun 	}
336*4882a593Smuzhiyun 	snd_i2c_lock(cs8427->bus);
337*4882a593Smuzhiyun 	chip->regmap[CS8427_REG_CLOCKSOURCE] &= ~CS8427_RXDMASK;
338*4882a593Smuzhiyun 	if (aes3input)
339*4882a593Smuzhiyun 		chip->regmap[CS8427_REG_CLOCKSOURCE] |= CS8427_RXDAES3INPUT;
340*4882a593Smuzhiyun 	snd_cs8427_reg_write(cs8427, CS8427_REG_CLOCKSOURCE,
341*4882a593Smuzhiyun 			     chip->regmap[CS8427_REG_CLOCKSOURCE]);
342*4882a593Smuzhiyun 	snd_i2c_unlock(cs8427->bus);
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun 
snd_cs8427_in_status_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)345*4882a593Smuzhiyun static int snd_cs8427_in_status_info(struct snd_kcontrol *kcontrol,
346*4882a593Smuzhiyun 				     struct snd_ctl_elem_info *uinfo)
347*4882a593Smuzhiyun {
348*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
349*4882a593Smuzhiyun 	uinfo->count = 1;
350*4882a593Smuzhiyun 	uinfo->value.integer.min = 0;
351*4882a593Smuzhiyun 	uinfo->value.integer.max = 255;
352*4882a593Smuzhiyun 	return 0;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun 
snd_cs8427_in_status_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)355*4882a593Smuzhiyun static int snd_cs8427_in_status_get(struct snd_kcontrol *kcontrol,
356*4882a593Smuzhiyun 				    struct snd_ctl_elem_value *ucontrol)
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun 	struct snd_i2c_device *device = snd_kcontrol_chip(kcontrol);
359*4882a593Smuzhiyun 	int data;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	snd_i2c_lock(device->bus);
362*4882a593Smuzhiyun 	data = snd_cs8427_reg_read(device, kcontrol->private_value);
363*4882a593Smuzhiyun 	snd_i2c_unlock(device->bus);
364*4882a593Smuzhiyun 	if (data < 0)
365*4882a593Smuzhiyun 		return data;
366*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = data;
367*4882a593Smuzhiyun 	return 0;
368*4882a593Smuzhiyun }
369*4882a593Smuzhiyun 
snd_cs8427_qsubcode_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)370*4882a593Smuzhiyun static int snd_cs8427_qsubcode_info(struct snd_kcontrol *kcontrol,
371*4882a593Smuzhiyun 				    struct snd_ctl_elem_info *uinfo)
372*4882a593Smuzhiyun {
373*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
374*4882a593Smuzhiyun 	uinfo->count = 10;
375*4882a593Smuzhiyun 	return 0;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun 
snd_cs8427_qsubcode_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)378*4882a593Smuzhiyun static int snd_cs8427_qsubcode_get(struct snd_kcontrol *kcontrol,
379*4882a593Smuzhiyun 				   struct snd_ctl_elem_value *ucontrol)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun 	struct snd_i2c_device *device = snd_kcontrol_chip(kcontrol);
382*4882a593Smuzhiyun 	unsigned char reg = CS8427_REG_QSUBCODE;
383*4882a593Smuzhiyun 	int err;
384*4882a593Smuzhiyun 
385*4882a593Smuzhiyun 	snd_i2c_lock(device->bus);
386*4882a593Smuzhiyun 	if ((err = snd_i2c_sendbytes(device, &reg, 1)) != 1) {
387*4882a593Smuzhiyun 		snd_printk(KERN_ERR "unable to send register 0x%x byte "
388*4882a593Smuzhiyun 			   "to CS8427\n", reg);
389*4882a593Smuzhiyun 		snd_i2c_unlock(device->bus);
390*4882a593Smuzhiyun 		return err < 0 ? err : -EIO;
391*4882a593Smuzhiyun 	}
392*4882a593Smuzhiyun 	err = snd_i2c_readbytes(device, ucontrol->value.bytes.data, 10);
393*4882a593Smuzhiyun 	if (err != 10) {
394*4882a593Smuzhiyun 		snd_printk(KERN_ERR "unable to read Q-subcode bytes "
395*4882a593Smuzhiyun 			   "from CS8427\n");
396*4882a593Smuzhiyun 		snd_i2c_unlock(device->bus);
397*4882a593Smuzhiyun 		return err < 0 ? err : -EIO;
398*4882a593Smuzhiyun 	}
399*4882a593Smuzhiyun 	snd_i2c_unlock(device->bus);
400*4882a593Smuzhiyun 	return 0;
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun 
snd_cs8427_spdif_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)403*4882a593Smuzhiyun static int snd_cs8427_spdif_info(struct snd_kcontrol *kcontrol,
404*4882a593Smuzhiyun 				 struct snd_ctl_elem_info *uinfo)
405*4882a593Smuzhiyun {
406*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
407*4882a593Smuzhiyun 	uinfo->count = 1;
408*4882a593Smuzhiyun 	return 0;
409*4882a593Smuzhiyun }
410*4882a593Smuzhiyun 
snd_cs8427_spdif_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)411*4882a593Smuzhiyun static int snd_cs8427_spdif_get(struct snd_kcontrol *kcontrol,
412*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
413*4882a593Smuzhiyun {
414*4882a593Smuzhiyun 	struct snd_i2c_device *device = snd_kcontrol_chip(kcontrol);
415*4882a593Smuzhiyun 	struct cs8427 *chip = device->private_data;
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun 	snd_i2c_lock(device->bus);
418*4882a593Smuzhiyun 	memcpy(ucontrol->value.iec958.status, chip->playback.def_status, 24);
419*4882a593Smuzhiyun 	snd_i2c_unlock(device->bus);
420*4882a593Smuzhiyun 	return 0;
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun 
snd_cs8427_spdif_put(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)423*4882a593Smuzhiyun static int snd_cs8427_spdif_put(struct snd_kcontrol *kcontrol,
424*4882a593Smuzhiyun 				struct snd_ctl_elem_value *ucontrol)
425*4882a593Smuzhiyun {
426*4882a593Smuzhiyun 	struct snd_i2c_device *device = snd_kcontrol_chip(kcontrol);
427*4882a593Smuzhiyun 	struct cs8427 *chip = device->private_data;
428*4882a593Smuzhiyun 	unsigned char *status = kcontrol->private_value ?
429*4882a593Smuzhiyun 		chip->playback.pcm_status : chip->playback.def_status;
430*4882a593Smuzhiyun 	struct snd_pcm_runtime *runtime = chip->playback.substream ?
431*4882a593Smuzhiyun 		chip->playback.substream->runtime : NULL;
432*4882a593Smuzhiyun 	int err, change;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	snd_i2c_lock(device->bus);
435*4882a593Smuzhiyun 	change = memcmp(ucontrol->value.iec958.status, status, 24) != 0;
436*4882a593Smuzhiyun 	memcpy(status, ucontrol->value.iec958.status, 24);
437*4882a593Smuzhiyun 	if (change && (kcontrol->private_value ?
438*4882a593Smuzhiyun 		       runtime != NULL : runtime == NULL)) {
439*4882a593Smuzhiyun 		err = snd_cs8427_send_corudata(device, 0, status, 24);
440*4882a593Smuzhiyun 		if (err < 0)
441*4882a593Smuzhiyun 			change = err;
442*4882a593Smuzhiyun 	}
443*4882a593Smuzhiyun 	snd_i2c_unlock(device->bus);
444*4882a593Smuzhiyun 	return change;
445*4882a593Smuzhiyun }
446*4882a593Smuzhiyun 
snd_cs8427_spdif_mask_info(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)447*4882a593Smuzhiyun static int snd_cs8427_spdif_mask_info(struct snd_kcontrol *kcontrol,
448*4882a593Smuzhiyun 				      struct snd_ctl_elem_info *uinfo)
449*4882a593Smuzhiyun {
450*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
451*4882a593Smuzhiyun 	uinfo->count = 1;
452*4882a593Smuzhiyun 	return 0;
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun 
snd_cs8427_spdif_mask_get(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)455*4882a593Smuzhiyun static int snd_cs8427_spdif_mask_get(struct snd_kcontrol *kcontrol,
456*4882a593Smuzhiyun 				      struct snd_ctl_elem_value *ucontrol)
457*4882a593Smuzhiyun {
458*4882a593Smuzhiyun 	memset(ucontrol->value.iec958.status, 0xff, 24);
459*4882a593Smuzhiyun 	return 0;
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun 
462*4882a593Smuzhiyun static const struct snd_kcontrol_new snd_cs8427_iec958_controls[] = {
463*4882a593Smuzhiyun {
464*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
465*4882a593Smuzhiyun 	.info =		snd_cs8427_in_status_info,
466*4882a593Smuzhiyun 	.name =		"IEC958 CS8427 Input Status",
467*4882a593Smuzhiyun 	.access =	(SNDRV_CTL_ELEM_ACCESS_READ |
468*4882a593Smuzhiyun 			 SNDRV_CTL_ELEM_ACCESS_VOLATILE),
469*4882a593Smuzhiyun 	.get =		snd_cs8427_in_status_get,
470*4882a593Smuzhiyun 	.private_value = 15,
471*4882a593Smuzhiyun },
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
474*4882a593Smuzhiyun 	.info =		snd_cs8427_in_status_info,
475*4882a593Smuzhiyun 	.name =		"IEC958 CS8427 Error Status",
476*4882a593Smuzhiyun 	.access =	(SNDRV_CTL_ELEM_ACCESS_READ |
477*4882a593Smuzhiyun 			 SNDRV_CTL_ELEM_ACCESS_VOLATILE),
478*4882a593Smuzhiyun 	.get =		snd_cs8427_in_status_get,
479*4882a593Smuzhiyun 	.private_value = 16,
480*4882a593Smuzhiyun },
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun 	.access =	SNDRV_CTL_ELEM_ACCESS_READ,
483*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
484*4882a593Smuzhiyun 	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
485*4882a593Smuzhiyun 	.info =		snd_cs8427_spdif_mask_info,
486*4882a593Smuzhiyun 	.get =		snd_cs8427_spdif_mask_get,
487*4882a593Smuzhiyun },
488*4882a593Smuzhiyun {
489*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
490*4882a593Smuzhiyun 	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
491*4882a593Smuzhiyun 	.info =		snd_cs8427_spdif_info,
492*4882a593Smuzhiyun 	.get =		snd_cs8427_spdif_get,
493*4882a593Smuzhiyun 	.put =		snd_cs8427_spdif_put,
494*4882a593Smuzhiyun 	.private_value = 0
495*4882a593Smuzhiyun },
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun 	.access =	(SNDRV_CTL_ELEM_ACCESS_READWRITE |
498*4882a593Smuzhiyun 			 SNDRV_CTL_ELEM_ACCESS_INACTIVE),
499*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
500*4882a593Smuzhiyun 	.name =		SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
501*4882a593Smuzhiyun 	.info =		snd_cs8427_spdif_info,
502*4882a593Smuzhiyun 	.get =		snd_cs8427_spdif_get,
503*4882a593Smuzhiyun 	.put =		snd_cs8427_spdif_put,
504*4882a593Smuzhiyun 	.private_value = 1
505*4882a593Smuzhiyun },
506*4882a593Smuzhiyun {
507*4882a593Smuzhiyun 	.iface =	SNDRV_CTL_ELEM_IFACE_PCM,
508*4882a593Smuzhiyun 	.info =		snd_cs8427_qsubcode_info,
509*4882a593Smuzhiyun 	.name =		"IEC958 Q-subcode Capture Default",
510*4882a593Smuzhiyun 	.access =	(SNDRV_CTL_ELEM_ACCESS_READ |
511*4882a593Smuzhiyun 			 SNDRV_CTL_ELEM_ACCESS_VOLATILE),
512*4882a593Smuzhiyun 	.get =		snd_cs8427_qsubcode_get
513*4882a593Smuzhiyun }};
514*4882a593Smuzhiyun 
snd_cs8427_iec958_build(struct snd_i2c_device * cs8427,struct snd_pcm_substream * play_substream,struct snd_pcm_substream * cap_substream)515*4882a593Smuzhiyun int snd_cs8427_iec958_build(struct snd_i2c_device *cs8427,
516*4882a593Smuzhiyun 			    struct snd_pcm_substream *play_substream,
517*4882a593Smuzhiyun 			    struct snd_pcm_substream *cap_substream)
518*4882a593Smuzhiyun {
519*4882a593Smuzhiyun 	struct cs8427 *chip = cs8427->private_data;
520*4882a593Smuzhiyun 	struct snd_kcontrol *kctl;
521*4882a593Smuzhiyun 	unsigned int idx;
522*4882a593Smuzhiyun 	int err;
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun 	if (snd_BUG_ON(!play_substream || !cap_substream))
525*4882a593Smuzhiyun 		return -EINVAL;
526*4882a593Smuzhiyun 	for (idx = 0; idx < ARRAY_SIZE(snd_cs8427_iec958_controls); idx++) {
527*4882a593Smuzhiyun 		kctl = snd_ctl_new1(&snd_cs8427_iec958_controls[idx], cs8427);
528*4882a593Smuzhiyun 		if (kctl == NULL)
529*4882a593Smuzhiyun 			return -ENOMEM;
530*4882a593Smuzhiyun 		kctl->id.device = play_substream->pcm->device;
531*4882a593Smuzhiyun 		kctl->id.subdevice = play_substream->number;
532*4882a593Smuzhiyun 		err = snd_ctl_add(cs8427->bus->card, kctl);
533*4882a593Smuzhiyun 		if (err < 0)
534*4882a593Smuzhiyun 			return err;
535*4882a593Smuzhiyun 		if (! strcmp(kctl->id.name,
536*4882a593Smuzhiyun 			     SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM)))
537*4882a593Smuzhiyun 			chip->playback.pcm_ctl = kctl;
538*4882a593Smuzhiyun 	}
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	chip->playback.substream = play_substream;
541*4882a593Smuzhiyun 	chip->capture.substream = cap_substream;
542*4882a593Smuzhiyun 	if (snd_BUG_ON(!chip->playback.pcm_ctl))
543*4882a593Smuzhiyun 		return -EIO;
544*4882a593Smuzhiyun 	return 0;
545*4882a593Smuzhiyun }
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun EXPORT_SYMBOL(snd_cs8427_iec958_build);
548*4882a593Smuzhiyun 
snd_cs8427_iec958_active(struct snd_i2c_device * cs8427,int active)549*4882a593Smuzhiyun int snd_cs8427_iec958_active(struct snd_i2c_device *cs8427, int active)
550*4882a593Smuzhiyun {
551*4882a593Smuzhiyun 	struct cs8427 *chip;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	if (snd_BUG_ON(!cs8427))
554*4882a593Smuzhiyun 		return -ENXIO;
555*4882a593Smuzhiyun 	chip = cs8427->private_data;
556*4882a593Smuzhiyun 	if (active)
557*4882a593Smuzhiyun 		memcpy(chip->playback.pcm_status,
558*4882a593Smuzhiyun 		       chip->playback.def_status, 24);
559*4882a593Smuzhiyun 	chip->playback.pcm_ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
560*4882a593Smuzhiyun 	snd_ctl_notify(cs8427->bus->card,
561*4882a593Smuzhiyun 		       SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
562*4882a593Smuzhiyun 		       &chip->playback.pcm_ctl->id);
563*4882a593Smuzhiyun 	return 0;
564*4882a593Smuzhiyun }
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun EXPORT_SYMBOL(snd_cs8427_iec958_active);
567*4882a593Smuzhiyun 
snd_cs8427_iec958_pcm(struct snd_i2c_device * cs8427,unsigned int rate)568*4882a593Smuzhiyun int snd_cs8427_iec958_pcm(struct snd_i2c_device *cs8427, unsigned int rate)
569*4882a593Smuzhiyun {
570*4882a593Smuzhiyun 	struct cs8427 *chip;
571*4882a593Smuzhiyun 	char *status;
572*4882a593Smuzhiyun 	int err, reset;
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 	if (snd_BUG_ON(!cs8427))
575*4882a593Smuzhiyun 		return -ENXIO;
576*4882a593Smuzhiyun 	chip = cs8427->private_data;
577*4882a593Smuzhiyun 	status = chip->playback.pcm_status;
578*4882a593Smuzhiyun 	snd_i2c_lock(cs8427->bus);
579*4882a593Smuzhiyun 	if (status[0] & IEC958_AES0_PROFESSIONAL) {
580*4882a593Smuzhiyun 		status[0] &= ~IEC958_AES0_PRO_FS;
581*4882a593Smuzhiyun 		switch (rate) {
582*4882a593Smuzhiyun 		case 32000: status[0] |= IEC958_AES0_PRO_FS_32000; break;
583*4882a593Smuzhiyun 		case 44100: status[0] |= IEC958_AES0_PRO_FS_44100; break;
584*4882a593Smuzhiyun 		case 48000: status[0] |= IEC958_AES0_PRO_FS_48000; break;
585*4882a593Smuzhiyun 		default: status[0] |= IEC958_AES0_PRO_FS_NOTID; break;
586*4882a593Smuzhiyun 		}
587*4882a593Smuzhiyun 	} else {
588*4882a593Smuzhiyun 		status[3] &= ~IEC958_AES3_CON_FS;
589*4882a593Smuzhiyun 		switch (rate) {
590*4882a593Smuzhiyun 		case 32000: status[3] |= IEC958_AES3_CON_FS_32000; break;
591*4882a593Smuzhiyun 		case 44100: status[3] |= IEC958_AES3_CON_FS_44100; break;
592*4882a593Smuzhiyun 		case 48000: status[3] |= IEC958_AES3_CON_FS_48000; break;
593*4882a593Smuzhiyun 		}
594*4882a593Smuzhiyun 	}
595*4882a593Smuzhiyun 	err = snd_cs8427_send_corudata(cs8427, 0, status, 24);
596*4882a593Smuzhiyun 	if (err > 0)
597*4882a593Smuzhiyun 		snd_ctl_notify(cs8427->bus->card,
598*4882a593Smuzhiyun 			       SNDRV_CTL_EVENT_MASK_VALUE,
599*4882a593Smuzhiyun 			       &chip->playback.pcm_ctl->id);
600*4882a593Smuzhiyun 	reset = chip->rate != rate;
601*4882a593Smuzhiyun 	chip->rate = rate;
602*4882a593Smuzhiyun 	snd_i2c_unlock(cs8427->bus);
603*4882a593Smuzhiyun 	if (reset)
604*4882a593Smuzhiyun 		snd_cs8427_reset(cs8427);
605*4882a593Smuzhiyun 	return err < 0 ? err : 0;
606*4882a593Smuzhiyun }
607*4882a593Smuzhiyun 
608*4882a593Smuzhiyun EXPORT_SYMBOL(snd_cs8427_iec958_pcm);
609