162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 262306a36Sopenharmony_ci#ifndef __SOUND_WSS_H 362306a36Sopenharmony_ci#define __SOUND_WSS_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci/* 662306a36Sopenharmony_ci * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 762306a36Sopenharmony_ci * Definitions for CS4231 & InterWave chips & compatible chips 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <sound/control.h> 1162306a36Sopenharmony_ci#include <sound/pcm.h> 1262306a36Sopenharmony_ci#include <sound/timer.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <sound/cs4231-regs.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* defines for codec.mode */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define WSS_MODE_NONE 0x0000 1962306a36Sopenharmony_ci#define WSS_MODE_PLAY 0x0001 2062306a36Sopenharmony_ci#define WSS_MODE_RECORD 0x0002 2162306a36Sopenharmony_ci#define WSS_MODE_TIMER 0x0004 2262306a36Sopenharmony_ci#define WSS_MODE_OPEN (WSS_MODE_PLAY|WSS_MODE_RECORD|WSS_MODE_TIMER) 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci/* defines for codec.hardware */ 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define WSS_HW_DETECT 0x0000 /* let CS4231 driver detect chip */ 2762306a36Sopenharmony_ci#define WSS_HW_DETECT3 0x0001 /* allow mode 3 */ 2862306a36Sopenharmony_ci#define WSS_HW_TYPE_MASK 0xff00 /* type mask */ 2962306a36Sopenharmony_ci#define WSS_HW_CS4231_MASK 0x0100 /* CS4231 serie */ 3062306a36Sopenharmony_ci#define WSS_HW_CS4231 0x0100 /* CS4231 chip */ 3162306a36Sopenharmony_ci#define WSS_HW_CS4231A 0x0101 /* CS4231A chip */ 3262306a36Sopenharmony_ci#define WSS_HW_AD1845 0x0102 /* AD1845 chip */ 3362306a36Sopenharmony_ci#define WSS_HW_CS4232_MASK 0x0200 /* CS4232 serie (has control ports) */ 3462306a36Sopenharmony_ci#define WSS_HW_CS4232 0x0200 /* CS4232 */ 3562306a36Sopenharmony_ci#define WSS_HW_CS4232A 0x0201 /* CS4232A */ 3662306a36Sopenharmony_ci#define WSS_HW_CS4236 0x0202 /* CS4236 */ 3762306a36Sopenharmony_ci#define WSS_HW_CS4236B_MASK 0x0400 /* CS4236B serie (has extended control regs) */ 3862306a36Sopenharmony_ci#define WSS_HW_CS4235 0x0400 /* CS4235 - Crystal Clear (tm) stereo enhancement */ 3962306a36Sopenharmony_ci#define WSS_HW_CS4236B 0x0401 /* CS4236B */ 4062306a36Sopenharmony_ci#define WSS_HW_CS4237B 0x0402 /* CS4237B - SRS 3D */ 4162306a36Sopenharmony_ci#define WSS_HW_CS4238B 0x0403 /* CS4238B - QSOUND 3D */ 4262306a36Sopenharmony_ci#define WSS_HW_CS4239 0x0404 /* CS4239 - Crystal Clear (tm) stereo enhancement */ 4362306a36Sopenharmony_ci#define WSS_HW_AD1848_MASK 0x0800 /* AD1848 serie (half duplex) */ 4462306a36Sopenharmony_ci#define WSS_HW_AD1847 0x0801 /* AD1847 chip */ 4562306a36Sopenharmony_ci#define WSS_HW_AD1848 0x0802 /* AD1848 chip */ 4662306a36Sopenharmony_ci#define WSS_HW_CS4248 0x0803 /* CS4248 chip */ 4762306a36Sopenharmony_ci#define WSS_HW_CMI8330 0x0804 /* CMI8330 chip */ 4862306a36Sopenharmony_ci#define WSS_HW_THINKPAD 0x0805 /* Thinkpad 360/750/755 */ 4962306a36Sopenharmony_ci/* compatible, but clones */ 5062306a36Sopenharmony_ci#define WSS_HW_INTERWAVE 0x1000 /* InterWave chip */ 5162306a36Sopenharmony_ci#define WSS_HW_OPL3SA2 0x1101 /* OPL3-SA2 chip, similar to cs4231 */ 5262306a36Sopenharmony_ci#define WSS_HW_OPTI93X 0x1102 /* Opti 930/931/933 */ 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* defines for codec.hwshare */ 5562306a36Sopenharmony_ci#define WSS_HWSHARE_IRQ (1<<0) 5662306a36Sopenharmony_ci#define WSS_HWSHARE_DMA1 (1<<1) 5762306a36Sopenharmony_ci#define WSS_HWSHARE_DMA2 (1<<2) 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci/* IBM Thinkpad specific stuff */ 6062306a36Sopenharmony_ci#define AD1848_THINKPAD_CTL_PORT1 0x15e8 6162306a36Sopenharmony_ci#define AD1848_THINKPAD_CTL_PORT2 0x15e9 6262306a36Sopenharmony_ci#define AD1848_THINKPAD_CS4248_ENABLE_BIT 0x02 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistruct snd_wss { 6562306a36Sopenharmony_ci unsigned long port; /* base i/o port */ 6662306a36Sopenharmony_ci struct resource *res_port; 6762306a36Sopenharmony_ci unsigned long cport; /* control base i/o port (CS4236) */ 6862306a36Sopenharmony_ci struct resource *res_cport; 6962306a36Sopenharmony_ci int irq; /* IRQ line */ 7062306a36Sopenharmony_ci int dma1; /* playback DMA */ 7162306a36Sopenharmony_ci int dma2; /* record DMA */ 7262306a36Sopenharmony_ci unsigned short version; /* version of CODEC chip */ 7362306a36Sopenharmony_ci unsigned short mode; /* see to WSS_MODE_XXXX */ 7462306a36Sopenharmony_ci unsigned short hardware; /* see to WSS_HW_XXXX */ 7562306a36Sopenharmony_ci unsigned short hwshare; /* shared resources */ 7662306a36Sopenharmony_ci unsigned short single_dma:1, /* forced single DMA mode (GUS 16-bit */ 7762306a36Sopenharmony_ci /* daughter board) or dma1 == dma2 */ 7862306a36Sopenharmony_ci ebus_flag:1, /* SPARC: EBUS present */ 7962306a36Sopenharmony_ci thinkpad_flag:1; /* Thinkpad CS4248 needs extra help */ 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci struct snd_card *card; 8262306a36Sopenharmony_ci struct snd_pcm *pcm; 8362306a36Sopenharmony_ci struct snd_pcm_substream *playback_substream; 8462306a36Sopenharmony_ci struct snd_pcm_substream *capture_substream; 8562306a36Sopenharmony_ci struct snd_timer *timer; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci unsigned char image[32]; /* registers image */ 8862306a36Sopenharmony_ci unsigned char eimage[32]; /* extended registers image */ 8962306a36Sopenharmony_ci unsigned char cimage[16]; /* control registers image */ 9062306a36Sopenharmony_ci int mce_bit; 9162306a36Sopenharmony_ci int calibrate_mute; 9262306a36Sopenharmony_ci int sw_3d_bit; 9362306a36Sopenharmony_ci unsigned int p_dma_size; 9462306a36Sopenharmony_ci unsigned int c_dma_size; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci spinlock_t reg_lock; 9762306a36Sopenharmony_ci struct mutex mce_mutex; 9862306a36Sopenharmony_ci struct mutex open_mutex; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci int (*rate_constraint) (struct snd_pcm_runtime *runtime); 10162306a36Sopenharmony_ci void (*set_playback_format) (struct snd_wss *chip, 10262306a36Sopenharmony_ci struct snd_pcm_hw_params *hw_params, 10362306a36Sopenharmony_ci unsigned char pdfr); 10462306a36Sopenharmony_ci void (*set_capture_format) (struct snd_wss *chip, 10562306a36Sopenharmony_ci struct snd_pcm_hw_params *hw_params, 10662306a36Sopenharmony_ci unsigned char cdfr); 10762306a36Sopenharmony_ci void (*trigger) (struct snd_wss *chip, unsigned int what, int start); 10862306a36Sopenharmony_ci#ifdef CONFIG_PM 10962306a36Sopenharmony_ci void (*suspend) (struct snd_wss *chip); 11062306a36Sopenharmony_ci void (*resume) (struct snd_wss *chip); 11162306a36Sopenharmony_ci#endif 11262306a36Sopenharmony_ci void *dma_private_data; 11362306a36Sopenharmony_ci int (*claim_dma) (struct snd_wss *chip, 11462306a36Sopenharmony_ci void *dma_private_data, int dma); 11562306a36Sopenharmony_ci int (*release_dma) (struct snd_wss *chip, 11662306a36Sopenharmony_ci void *dma_private_data, int dma); 11762306a36Sopenharmony_ci}; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci/* exported functions */ 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_civoid snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char val); 12262306a36Sopenharmony_ciunsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg); 12362306a36Sopenharmony_civoid snd_cs4236_ext_out(struct snd_wss *chip, 12462306a36Sopenharmony_ci unsigned char reg, unsigned char val); 12562306a36Sopenharmony_ciunsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg); 12662306a36Sopenharmony_civoid snd_wss_mce_up(struct snd_wss *chip); 12762306a36Sopenharmony_civoid snd_wss_mce_down(struct snd_wss *chip); 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_civoid snd_wss_overrange(struct snd_wss *chip); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ciirqreturn_t snd_wss_interrupt(int irq, void *dev_id); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ciconst char *snd_wss_chip_id(struct snd_wss *chip); 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ciint snd_wss_create(struct snd_card *card, 13662306a36Sopenharmony_ci unsigned long port, 13762306a36Sopenharmony_ci unsigned long cport, 13862306a36Sopenharmony_ci int irq, int dma1, int dma2, 13962306a36Sopenharmony_ci unsigned short hardware, 14062306a36Sopenharmony_ci unsigned short hwshare, 14162306a36Sopenharmony_ci struct snd_wss **rchip); 14262306a36Sopenharmony_ciint snd_wss_pcm(struct snd_wss *chip, int device); 14362306a36Sopenharmony_ciint snd_wss_timer(struct snd_wss *chip, int device); 14462306a36Sopenharmony_ciint snd_wss_mixer(struct snd_wss *chip); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ciconst struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ciint snd_cs4236_create(struct snd_card *card, 14962306a36Sopenharmony_ci unsigned long port, 15062306a36Sopenharmony_ci unsigned long cport, 15162306a36Sopenharmony_ci int irq, int dma1, int dma2, 15262306a36Sopenharmony_ci unsigned short hardware, 15362306a36Sopenharmony_ci unsigned short hwshare, 15462306a36Sopenharmony_ci struct snd_wss **rchip); 15562306a36Sopenharmony_ciint snd_cs4236_pcm(struct snd_wss *chip, int device); 15662306a36Sopenharmony_ciint snd_cs4236_mixer(struct snd_wss *chip); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci/* 15962306a36Sopenharmony_ci * mixer library 16062306a36Sopenharmony_ci */ 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci#define WSS_SINGLE(xname, xindex, reg, shift, mask, invert) \ 16362306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 16462306a36Sopenharmony_ci .name = xname, \ 16562306a36Sopenharmony_ci .index = xindex, \ 16662306a36Sopenharmony_ci .info = snd_wss_info_single, \ 16762306a36Sopenharmony_ci .get = snd_wss_get_single, \ 16862306a36Sopenharmony_ci .put = snd_wss_put_single, \ 16962306a36Sopenharmony_ci .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ciint snd_wss_info_single(struct snd_kcontrol *kcontrol, 17262306a36Sopenharmony_ci struct snd_ctl_elem_info *uinfo); 17362306a36Sopenharmony_ciint snd_wss_get_single(struct snd_kcontrol *kcontrol, 17462306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol); 17562306a36Sopenharmony_ciint snd_wss_put_single(struct snd_kcontrol *kcontrol, 17662306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol); 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci#define WSS_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ 17962306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 18062306a36Sopenharmony_ci .name = xname, \ 18162306a36Sopenharmony_ci .index = xindex, \ 18262306a36Sopenharmony_ci .info = snd_wss_info_double, \ 18362306a36Sopenharmony_ci .get = snd_wss_get_double, \ 18462306a36Sopenharmony_ci .put = snd_wss_put_double, \ 18562306a36Sopenharmony_ci .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \ 18662306a36Sopenharmony_ci (shift_right << 19) | (mask << 24) | (invert << 22) } 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci#define WSS_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \ 18962306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 19062306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ 19162306a36Sopenharmony_ci .name = xname, \ 19262306a36Sopenharmony_ci .index = xindex, \ 19362306a36Sopenharmony_ci .info = snd_wss_info_single, \ 19462306a36Sopenharmony_ci .get = snd_wss_get_single, \ 19562306a36Sopenharmony_ci .put = snd_wss_put_single, \ 19662306a36Sopenharmony_ci .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \ 19762306a36Sopenharmony_ci .tlv = { .p = (xtlv) } } 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci#define WSS_DOUBLE_TLV(xname, xindex, left_reg, right_reg, \ 20062306a36Sopenharmony_ci shift_left, shift_right, mask, invert, xtlv) \ 20162306a36Sopenharmony_ci{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 20262306a36Sopenharmony_ci .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \ 20362306a36Sopenharmony_ci .name = xname, \ 20462306a36Sopenharmony_ci .index = xindex, \ 20562306a36Sopenharmony_ci .info = snd_wss_info_double, \ 20662306a36Sopenharmony_ci .get = snd_wss_get_double, \ 20762306a36Sopenharmony_ci .put = snd_wss_put_double, \ 20862306a36Sopenharmony_ci .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \ 20962306a36Sopenharmony_ci (shift_right << 19) | (mask << 24) | (invert << 22), \ 21062306a36Sopenharmony_ci .tlv = { .p = (xtlv) } } 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ciint snd_wss_info_double(struct snd_kcontrol *kcontrol, 21462306a36Sopenharmony_ci struct snd_ctl_elem_info *uinfo); 21562306a36Sopenharmony_ciint snd_wss_get_double(struct snd_kcontrol *kcontrol, 21662306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol); 21762306a36Sopenharmony_ciint snd_wss_put_double(struct snd_kcontrol *kcontrol, 21862306a36Sopenharmony_ci struct snd_ctl_elem_value *ucontrol); 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci#endif /* __SOUND_WSS_H */ 221