Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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