xref: /openbmc/linux/include/sound/wss.h (revision 75bf465f0bc33e9b776a46d6a1b9b990f5fb7c37)
1*1a59d1b8SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
27779f75fSKrzysztof Helt #ifndef __SOUND_WSS_H
37779f75fSKrzysztof Helt #define __SOUND_WSS_H
461ef19d7SKrzysztof Helt 
561ef19d7SKrzysztof Helt /*
661ef19d7SKrzysztof Helt  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
761ef19d7SKrzysztof Helt  *  Definitions for CS4231 & InterWave chips & compatible chips
861ef19d7SKrzysztof Helt  */
961ef19d7SKrzysztof Helt 
10a1ce3928SDavid Howells #include <sound/control.h>
11a1ce3928SDavid Howells #include <sound/pcm.h>
12a1ce3928SDavid Howells #include <sound/timer.h>
1361ef19d7SKrzysztof Helt 
14a1ce3928SDavid Howells #include <sound/cs4231-regs.h>
1561ef19d7SKrzysztof Helt 
1661ef19d7SKrzysztof Helt /* defines for codec.mode */
1761ef19d7SKrzysztof Helt 
187779f75fSKrzysztof Helt #define WSS_MODE_NONE	0x0000
197779f75fSKrzysztof Helt #define WSS_MODE_PLAY	0x0001
207779f75fSKrzysztof Helt #define WSS_MODE_RECORD	0x0002
217779f75fSKrzysztof Helt #define WSS_MODE_TIMER	0x0004
227779f75fSKrzysztof Helt #define WSS_MODE_OPEN	(WSS_MODE_PLAY|WSS_MODE_RECORD|WSS_MODE_TIMER)
2361ef19d7SKrzysztof Helt 
2461ef19d7SKrzysztof Helt /* defines for codec.hardware */
2561ef19d7SKrzysztof Helt 
267779f75fSKrzysztof Helt #define WSS_HW_DETECT        0x0000	/* let CS4231 driver detect chip */
277779f75fSKrzysztof Helt #define WSS_HW_DETECT3	0x0001	/* allow mode 3 */
287779f75fSKrzysztof Helt #define WSS_HW_TYPE_MASK	0xff00	/* type mask */
297779f75fSKrzysztof Helt #define WSS_HW_CS4231_MASK   0x0100	/* CS4231 serie */
307779f75fSKrzysztof Helt #define WSS_HW_CS4231        0x0100	/* CS4231 chip */
317779f75fSKrzysztof Helt #define WSS_HW_CS4231A       0x0101	/* CS4231A chip */
327779f75fSKrzysztof Helt #define WSS_HW_AD1845	0x0102	/* AD1845 chip */
337779f75fSKrzysztof Helt #define WSS_HW_CS4232_MASK   0x0200	/* CS4232 serie (has control ports) */
347779f75fSKrzysztof Helt #define WSS_HW_CS4232        0x0200	/* CS4232 */
357779f75fSKrzysztof Helt #define WSS_HW_CS4232A       0x0201	/* CS4232A */
367779f75fSKrzysztof Helt #define WSS_HW_CS4236	0x0202	/* CS4236 */
377779f75fSKrzysztof Helt #define WSS_HW_CS4236B_MASK	0x0400	/* CS4236B serie (has extended control regs) */
387779f75fSKrzysztof Helt #define WSS_HW_CS4235	0x0400	/* CS4235 - Crystal Clear (tm) stereo enhancement */
397779f75fSKrzysztof Helt #define WSS_HW_CS4236B       0x0401	/* CS4236B */
407779f75fSKrzysztof Helt #define WSS_HW_CS4237B       0x0402	/* CS4237B - SRS 3D */
417779f75fSKrzysztof Helt #define WSS_HW_CS4238B	0x0403	/* CS4238B - QSOUND 3D */
427779f75fSKrzysztof Helt #define WSS_HW_CS4239	0x0404	/* CS4239 - Crystal Clear (tm) stereo enhancement */
43ece11c9bSKrzysztof Helt #define WSS_HW_AD1848_MASK	0x0800	/* AD1848 serie (half duplex) */
44ece11c9bSKrzysztof Helt #define WSS_HW_AD1847		0x0801	/* AD1847 chip */
45ece11c9bSKrzysztof Helt #define WSS_HW_AD1848		0x0802	/* AD1848 chip */
46ece11c9bSKrzysztof Helt #define WSS_HW_CS4248		0x0803	/* CS4248 chip */
47ece11c9bSKrzysztof Helt #define WSS_HW_CMI8330		0x0804	/* CMI8330 chip */
48ece11c9bSKrzysztof Helt #define WSS_HW_THINKPAD		0x0805	/* Thinkpad 360/750/755 */
4961ef19d7SKrzysztof Helt /* compatible, but clones */
507779f75fSKrzysztof Helt #define WSS_HW_INTERWAVE     0x1000	/* InterWave chip */
517779f75fSKrzysztof Helt #define WSS_HW_OPL3SA2       0x1101	/* OPL3-SA2 chip, similar to cs4231 */
527779f75fSKrzysztof Helt #define WSS_HW_OPTI93X 	0x1102	/* Opti 930/931/933 */
5361ef19d7SKrzysztof Helt 
5461ef19d7SKrzysztof Helt /* defines for codec.hwshare */
557779f75fSKrzysztof Helt #define WSS_HWSHARE_IRQ	(1<<0)
567779f75fSKrzysztof Helt #define WSS_HWSHARE_DMA1	(1<<1)
577779f75fSKrzysztof Helt #define WSS_HWSHARE_DMA2	(1<<2)
5861ef19d7SKrzysztof Helt 
59ead893c0SKrzysztof Helt /* IBM Thinkpad specific stuff */
60ead893c0SKrzysztof Helt #define AD1848_THINKPAD_CTL_PORT1		0x15e8
61ead893c0SKrzysztof Helt #define AD1848_THINKPAD_CTL_PORT2		0x15e9
62ead893c0SKrzysztof Helt #define AD1848_THINKPAD_CS4248_ENABLE_BIT	0x02
63ead893c0SKrzysztof Helt 
647779f75fSKrzysztof Helt struct snd_wss {
6561ef19d7SKrzysztof Helt 	unsigned long port;		/* base i/o port */
6661ef19d7SKrzysztof Helt 	struct resource *res_port;
6761ef19d7SKrzysztof Helt 	unsigned long cport;		/* control base i/o port (CS4236) */
6861ef19d7SKrzysztof Helt 	struct resource *res_cport;
6961ef19d7SKrzysztof Helt 	int irq;			/* IRQ line */
7061ef19d7SKrzysztof Helt 	int dma1;			/* playback DMA */
7161ef19d7SKrzysztof Helt 	int dma2;			/* record DMA */
7261ef19d7SKrzysztof Helt 	unsigned short version;		/* version of CODEC chip */
737779f75fSKrzysztof Helt 	unsigned short mode;		/* see to WSS_MODE_XXXX */
747779f75fSKrzysztof Helt 	unsigned short hardware;	/* see to WSS_HW_XXXX */
7561ef19d7SKrzysztof Helt 	unsigned short hwshare;		/* shared resources */
76241b3ee7SKrzysztof Helt 	unsigned short single_dma:1,	/* forced single DMA mode (GUS 16-bit */
77241b3ee7SKrzysztof Helt 					/* daughter board) or dma1 == dma2 */
78241b3ee7SKrzysztof Helt 		       ebus_flag:1,	/* SPARC: EBUS present */
79241b3ee7SKrzysztof Helt 		       thinkpad_flag:1;	/* Thinkpad CS4248 needs extra help */
8061ef19d7SKrzysztof Helt 
8161ef19d7SKrzysztof Helt 	struct snd_card *card;
8261ef19d7SKrzysztof Helt 	struct snd_pcm *pcm;
8361ef19d7SKrzysztof Helt 	struct snd_pcm_substream *playback_substream;
8461ef19d7SKrzysztof Helt 	struct snd_pcm_substream *capture_substream;
8561ef19d7SKrzysztof Helt 	struct snd_timer *timer;
8661ef19d7SKrzysztof Helt 
8761ef19d7SKrzysztof Helt 	unsigned char image[32];	/* registers image */
8861ef19d7SKrzysztof Helt 	unsigned char eimage[32];	/* extended registers image */
8961ef19d7SKrzysztof Helt 	unsigned char cimage[16];	/* control registers image */
9061ef19d7SKrzysztof Helt 	int mce_bit;
9161ef19d7SKrzysztof Helt 	int calibrate_mute;
9261ef19d7SKrzysztof Helt 	int sw_3d_bit;
9361ef19d7SKrzysztof Helt 	unsigned int p_dma_size;
9461ef19d7SKrzysztof Helt 	unsigned int c_dma_size;
9561ef19d7SKrzysztof Helt 
9661ef19d7SKrzysztof Helt 	spinlock_t reg_lock;
9761ef19d7SKrzysztof Helt 	struct mutex mce_mutex;
9861ef19d7SKrzysztof Helt 	struct mutex open_mutex;
9961ef19d7SKrzysztof Helt 
10061ef19d7SKrzysztof Helt 	int (*rate_constraint) (struct snd_pcm_runtime *runtime);
1017779f75fSKrzysztof Helt 	void (*set_playback_format) (struct snd_wss *chip,
1027779f75fSKrzysztof Helt 				     struct snd_pcm_hw_params *hw_params,
1037779f75fSKrzysztof Helt 				     unsigned char pdfr);
1047779f75fSKrzysztof Helt 	void (*set_capture_format) (struct snd_wss *chip,
1057779f75fSKrzysztof Helt 				    struct snd_pcm_hw_params *hw_params,
1067779f75fSKrzysztof Helt 				    unsigned char cdfr);
1077779f75fSKrzysztof Helt 	void (*trigger) (struct snd_wss *chip, unsigned int what, int start);
10861ef19d7SKrzysztof Helt #ifdef CONFIG_PM
1097779f75fSKrzysztof Helt 	void (*suspend) (struct snd_wss *chip);
1107779f75fSKrzysztof Helt 	void (*resume) (struct snd_wss *chip);
11161ef19d7SKrzysztof Helt #endif
11261ef19d7SKrzysztof Helt 	void *dma_private_data;
1137779f75fSKrzysztof Helt 	int (*claim_dma) (struct snd_wss *chip,
1147779f75fSKrzysztof Helt 			  void *dma_private_data, int dma);
1157779f75fSKrzysztof Helt 	int (*release_dma) (struct snd_wss *chip,
1167779f75fSKrzysztof Helt 			    void *dma_private_data, int dma);
11761ef19d7SKrzysztof Helt };
11861ef19d7SKrzysztof Helt 
11961ef19d7SKrzysztof Helt /* exported functions */
12061ef19d7SKrzysztof Helt 
1217779f75fSKrzysztof Helt void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char val);
1227779f75fSKrzysztof Helt unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg);
1237779f75fSKrzysztof Helt void snd_cs4236_ext_out(struct snd_wss *chip,
1247779f75fSKrzysztof Helt 			unsigned char reg, unsigned char val);
1257779f75fSKrzysztof Helt unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg);
1267779f75fSKrzysztof Helt void snd_wss_mce_up(struct snd_wss *chip);
1277779f75fSKrzysztof Helt void snd_wss_mce_down(struct snd_wss *chip);
12861ef19d7SKrzysztof Helt 
1297779f75fSKrzysztof Helt void snd_wss_overrange(struct snd_wss *chip);
13061ef19d7SKrzysztof Helt 
1317779f75fSKrzysztof Helt irqreturn_t snd_wss_interrupt(int irq, void *dev_id);
13261ef19d7SKrzysztof Helt 
1337779f75fSKrzysztof Helt const char *snd_wss_chip_id(struct snd_wss *chip);
13461ef19d7SKrzysztof Helt 
1357779f75fSKrzysztof Helt int snd_wss_create(struct snd_card *card,
13661ef19d7SKrzysztof Helt 		      unsigned long port,
13761ef19d7SKrzysztof Helt 		      unsigned long cport,
13861ef19d7SKrzysztof Helt 		      int irq, int dma1, int dma2,
13961ef19d7SKrzysztof Helt 		      unsigned short hardware,
14061ef19d7SKrzysztof Helt 		      unsigned short hwshare,
1417779f75fSKrzysztof Helt 		      struct snd_wss **rchip);
142fa60c065SLars-Peter Clausen int snd_wss_pcm(struct snd_wss *chip, int device);
143fa60c065SLars-Peter Clausen int snd_wss_timer(struct snd_wss *chip, int device);
1447779f75fSKrzysztof Helt int snd_wss_mixer(struct snd_wss *chip);
14561ef19d7SKrzysztof Helt 
146ead893c0SKrzysztof Helt const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction);
147ead893c0SKrzysztof Helt 
14861ef19d7SKrzysztof Helt int snd_cs4236_create(struct snd_card *card,
14961ef19d7SKrzysztof Helt 		      unsigned long port,
15061ef19d7SKrzysztof Helt 		      unsigned long cport,
15161ef19d7SKrzysztof Helt 		      int irq, int dma1, int dma2,
15261ef19d7SKrzysztof Helt 		      unsigned short hardware,
15361ef19d7SKrzysztof Helt 		      unsigned short hwshare,
1547779f75fSKrzysztof Helt 		      struct snd_wss **rchip);
155fa60c065SLars-Peter Clausen int snd_cs4236_pcm(struct snd_wss *chip, int device);
1567779f75fSKrzysztof Helt int snd_cs4236_mixer(struct snd_wss *chip);
15761ef19d7SKrzysztof Helt 
15861ef19d7SKrzysztof Helt /*
15961ef19d7SKrzysztof Helt  *  mixer library
16061ef19d7SKrzysztof Helt  */
16161ef19d7SKrzysztof Helt 
1627779f75fSKrzysztof Helt #define WSS_SINGLE(xname, xindex, reg, shift, mask, invert) \
1637779f75fSKrzysztof Helt { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1647779f75fSKrzysztof Helt   .name = xname, \
1657779f75fSKrzysztof Helt   .index = xindex, \
1667779f75fSKrzysztof Helt   .info = snd_wss_info_single, \
1677779f75fSKrzysztof Helt   .get = snd_wss_get_single, \
1687779f75fSKrzysztof Helt   .put = snd_wss_put_single, \
16961ef19d7SKrzysztof Helt   .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
17061ef19d7SKrzysztof Helt 
1717779f75fSKrzysztof Helt int snd_wss_info_single(struct snd_kcontrol *kcontrol,
1727779f75fSKrzysztof Helt 			struct snd_ctl_elem_info *uinfo);
1737779f75fSKrzysztof Helt int snd_wss_get_single(struct snd_kcontrol *kcontrol,
1747779f75fSKrzysztof Helt 			struct snd_ctl_elem_value *ucontrol);
1757779f75fSKrzysztof Helt int snd_wss_put_single(struct snd_kcontrol *kcontrol,
1767779f75fSKrzysztof Helt 			struct snd_ctl_elem_value *ucontrol);
17761ef19d7SKrzysztof Helt 
1787779f75fSKrzysztof Helt #define WSS_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
1797779f75fSKrzysztof Helt { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1807779f75fSKrzysztof Helt   .name = xname, \
1817779f75fSKrzysztof Helt   .index = xindex, \
1827779f75fSKrzysztof Helt   .info = snd_wss_info_double, \
1837779f75fSKrzysztof Helt   .get = snd_wss_get_double, \
1847779f75fSKrzysztof Helt   .put = snd_wss_put_double, \
1857779f75fSKrzysztof Helt   .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
1867779f75fSKrzysztof Helt 		   (shift_right << 19) | (mask << 24) | (invert << 22) }
18761ef19d7SKrzysztof Helt 
1885664daa1SKrzysztof Helt #define WSS_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
1895664daa1SKrzysztof Helt { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1905664daa1SKrzysztof Helt   .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
1915664daa1SKrzysztof Helt   .name = xname, \
1925664daa1SKrzysztof Helt   .index = xindex, \
1935664daa1SKrzysztof Helt   .info = snd_wss_info_single, \
1945664daa1SKrzysztof Helt   .get = snd_wss_get_single, \
1955664daa1SKrzysztof Helt   .put = snd_wss_put_single, \
1965664daa1SKrzysztof Helt   .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
1975664daa1SKrzysztof Helt   .tlv = { .p = (xtlv) } }
1985664daa1SKrzysztof Helt 
1995664daa1SKrzysztof Helt #define WSS_DOUBLE_TLV(xname, xindex, left_reg, right_reg, \
2005664daa1SKrzysztof Helt 			shift_left, shift_right, mask, invert, xtlv) \
2015664daa1SKrzysztof Helt { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2025664daa1SKrzysztof Helt   .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
2035664daa1SKrzysztof Helt   .name = xname, \
2045664daa1SKrzysztof Helt   .index = xindex, \
2055664daa1SKrzysztof Helt   .info = snd_wss_info_double, \
2065664daa1SKrzysztof Helt   .get = snd_wss_get_double, \
2075664daa1SKrzysztof Helt   .put = snd_wss_put_double, \
2085664daa1SKrzysztof Helt   .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
2095664daa1SKrzysztof Helt 		   (shift_right << 19) | (mask << 24) | (invert << 22), \
2105664daa1SKrzysztof Helt   .tlv = { .p = (xtlv) } }
2115664daa1SKrzysztof Helt 
2125664daa1SKrzysztof Helt 
2137779f75fSKrzysztof Helt int snd_wss_info_double(struct snd_kcontrol *kcontrol,
2147779f75fSKrzysztof Helt 			struct snd_ctl_elem_info *uinfo);
2157779f75fSKrzysztof Helt int snd_wss_get_double(struct snd_kcontrol *kcontrol,
2167779f75fSKrzysztof Helt 			struct snd_ctl_elem_value *ucontrol);
2177779f75fSKrzysztof Helt int snd_wss_put_double(struct snd_kcontrol *kcontrol,
2187779f75fSKrzysztof Helt 			struct snd_ctl_elem_value *ucontrol);
21961ef19d7SKrzysztof Helt 
2207779f75fSKrzysztof Helt #endif /* __SOUND_WSS_H */
221