linux/include/sound/wss.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-or-later */
   2#ifndef __SOUND_WSS_H
   3#define __SOUND_WSS_H
   4
   5/*
   6 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   7 *  Definitions for CS4231 & InterWave chips & compatible chips
   8 */
   9
  10#include <sound/control.h>
  11#include <sound/pcm.h>
  12#include <sound/timer.h>
  13
  14#include <sound/cs4231-regs.h>
  15
  16/* defines for codec.mode */
  17
  18#define WSS_MODE_NONE   0x0000
  19#define WSS_MODE_PLAY   0x0001
  20#define WSS_MODE_RECORD 0x0002
  21#define WSS_MODE_TIMER  0x0004
  22#define WSS_MODE_OPEN   (WSS_MODE_PLAY|WSS_MODE_RECORD|WSS_MODE_TIMER)
  23
  24/* defines for codec.hardware */
  25
  26#define WSS_HW_DETECT        0x0000     /* let CS4231 driver detect chip */
  27#define WSS_HW_DETECT3  0x0001  /* allow mode 3 */
  28#define WSS_HW_TYPE_MASK        0xff00  /* type mask */
  29#define WSS_HW_CS4231_MASK   0x0100     /* CS4231 serie */
  30#define WSS_HW_CS4231        0x0100     /* CS4231 chip */
  31#define WSS_HW_CS4231A       0x0101     /* CS4231A chip */
  32#define WSS_HW_AD1845   0x0102  /* AD1845 chip */
  33#define WSS_HW_CS4232_MASK   0x0200     /* CS4232 serie (has control ports) */
  34#define WSS_HW_CS4232        0x0200     /* CS4232 */
  35#define WSS_HW_CS4232A       0x0201     /* CS4232A */
  36#define WSS_HW_CS4236   0x0202  /* CS4236 */
  37#define WSS_HW_CS4236B_MASK     0x0400  /* CS4236B serie (has extended control regs) */
  38#define WSS_HW_CS4235   0x0400  /* CS4235 - Crystal Clear (tm) stereo enhancement */
  39#define WSS_HW_CS4236B       0x0401     /* CS4236B */
  40#define WSS_HW_CS4237B       0x0402     /* CS4237B - SRS 3D */
  41#define WSS_HW_CS4238B  0x0403  /* CS4238B - QSOUND 3D */
  42#define WSS_HW_CS4239   0x0404  /* CS4239 - Crystal Clear (tm) stereo enhancement */
  43#define WSS_HW_AD1848_MASK      0x0800  /* AD1848 serie (half duplex) */
  44#define WSS_HW_AD1847           0x0801  /* AD1847 chip */
  45#define WSS_HW_AD1848           0x0802  /* AD1848 chip */
  46#define WSS_HW_CS4248           0x0803  /* CS4248 chip */
  47#define WSS_HW_CMI8330          0x0804  /* CMI8330 chip */
  48#define WSS_HW_THINKPAD         0x0805  /* Thinkpad 360/750/755 */
  49/* compatible, but clones */
  50#define WSS_HW_INTERWAVE     0x1000     /* InterWave chip */
  51#define WSS_HW_OPL3SA2       0x1101     /* OPL3-SA2 chip, similar to cs4231 */
  52#define WSS_HW_OPTI93X  0x1102  /* Opti 930/931/933 */
  53
  54/* defines for codec.hwshare */
  55#define WSS_HWSHARE_IRQ (1<<0)
  56#define WSS_HWSHARE_DMA1        (1<<1)
  57#define WSS_HWSHARE_DMA2        (1<<2)
  58
  59/* IBM Thinkpad specific stuff */
  60#define AD1848_THINKPAD_CTL_PORT1               0x15e8
  61#define AD1848_THINKPAD_CTL_PORT2               0x15e9
  62#define AD1848_THINKPAD_CS4248_ENABLE_BIT       0x02
  63
  64struct snd_wss {
  65        unsigned long port;             /* base i/o port */
  66        struct resource *res_port;
  67        unsigned long cport;            /* control base i/o port (CS4236) */
  68        struct resource *res_cport;
  69        int irq;                        /* IRQ line */
  70        int dma1;                       /* playback DMA */
  71        int dma2;                       /* record DMA */
  72        unsigned short version;         /* version of CODEC chip */
  73        unsigned short mode;            /* see to WSS_MODE_XXXX */
  74        unsigned short hardware;        /* see to WSS_HW_XXXX */
  75        unsigned short hwshare;         /* shared resources */
  76        unsigned short single_dma:1,    /* forced single DMA mode (GUS 16-bit */
  77                                        /* daughter board) or dma1 == dma2 */
  78                       ebus_flag:1,     /* SPARC: EBUS present */
  79                       thinkpad_flag:1; /* Thinkpad CS4248 needs extra help */
  80
  81        struct snd_card *card;
  82        struct snd_pcm *pcm;
  83        struct snd_pcm_substream *playback_substream;
  84        struct snd_pcm_substream *capture_substream;
  85        struct snd_timer *timer;
  86
  87        unsigned char image[32];        /* registers image */
  88        unsigned char eimage[32];       /* extended registers image */
  89        unsigned char cimage[16];       /* control registers image */
  90        int mce_bit;
  91        int calibrate_mute;
  92        int sw_3d_bit;
  93        unsigned int p_dma_size;
  94        unsigned int c_dma_size;
  95
  96        spinlock_t reg_lock;
  97        struct mutex mce_mutex;
  98        struct mutex open_mutex;
  99
 100        int (*rate_constraint) (struct snd_pcm_runtime *runtime);
 101        void (*set_playback_format) (struct snd_wss *chip,
 102                                     struct snd_pcm_hw_params *hw_params,
 103                                     unsigned char pdfr);
 104        void (*set_capture_format) (struct snd_wss *chip,
 105                                    struct snd_pcm_hw_params *hw_params,
 106                                    unsigned char cdfr);
 107        void (*trigger) (struct snd_wss *chip, unsigned int what, int start);
 108#ifdef CONFIG_PM
 109        void (*suspend) (struct snd_wss *chip);
 110        void (*resume) (struct snd_wss *chip);
 111#endif
 112        void *dma_private_data;
 113        int (*claim_dma) (struct snd_wss *chip,
 114                          void *dma_private_data, int dma);
 115        int (*release_dma) (struct snd_wss *chip,
 116                            void *dma_private_data, int dma);
 117};
 118
 119/* exported functions */
 120
 121void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char val);
 122unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg);
 123void snd_cs4236_ext_out(struct snd_wss *chip,
 124                        unsigned char reg, unsigned char val);
 125unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg);
 126void snd_wss_mce_up(struct snd_wss *chip);
 127void snd_wss_mce_down(struct snd_wss *chip);
 128
 129void snd_wss_overrange(struct snd_wss *chip);
 130
 131irqreturn_t snd_wss_interrupt(int irq, void *dev_id);
 132
 133const char *snd_wss_chip_id(struct snd_wss *chip);
 134
 135int snd_wss_create(struct snd_card *card,
 136                      unsigned long port,
 137                      unsigned long cport,
 138                      int irq, int dma1, int dma2,
 139                      unsigned short hardware,
 140                      unsigned short hwshare,
 141                      struct snd_wss **rchip);
 142int snd_wss_pcm(struct snd_wss *chip, int device);
 143int snd_wss_timer(struct snd_wss *chip, int device);
 144int snd_wss_mixer(struct snd_wss *chip);
 145
 146const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction);
 147
 148int snd_cs4236_create(struct snd_card *card,
 149                      unsigned long port,
 150                      unsigned long cport,
 151                      int irq, int dma1, int dma2,
 152                      unsigned short hardware,
 153                      unsigned short hwshare,
 154                      struct snd_wss **rchip);
 155int snd_cs4236_pcm(struct snd_wss *chip, int device);
 156int snd_cs4236_mixer(struct snd_wss *chip);
 157
 158/*
 159 *  mixer library
 160 */
 161
 162#define WSS_SINGLE(xname, xindex, reg, shift, mask, invert) \
 163{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
 164  .name = xname, \
 165  .index = xindex, \
 166  .info = snd_wss_info_single, \
 167  .get = snd_wss_get_single, \
 168  .put = snd_wss_put_single, \
 169  .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
 170
 171int snd_wss_info_single(struct snd_kcontrol *kcontrol,
 172                        struct snd_ctl_elem_info *uinfo);
 173int snd_wss_get_single(struct snd_kcontrol *kcontrol,
 174                        struct snd_ctl_elem_value *ucontrol);
 175int snd_wss_put_single(struct snd_kcontrol *kcontrol,
 176                        struct snd_ctl_elem_value *ucontrol);
 177
 178#define WSS_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
 179{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
 180  .name = xname, \
 181  .index = xindex, \
 182  .info = snd_wss_info_double, \
 183  .get = snd_wss_get_double, \
 184  .put = snd_wss_put_double, \
 185  .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
 186                   (shift_right << 19) | (mask << 24) | (invert << 22) }
 187
 188#define WSS_SINGLE_TLV(xname, xindex, reg, shift, mask, invert, xtlv) \
 189{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
 190  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
 191  .name = xname, \
 192  .index = xindex, \
 193  .info = snd_wss_info_single, \
 194  .get = snd_wss_get_single, \
 195  .put = snd_wss_put_single, \
 196  .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24), \
 197  .tlv = { .p = (xtlv) } }
 198
 199#define WSS_DOUBLE_TLV(xname, xindex, left_reg, right_reg, \
 200                        shift_left, shift_right, mask, invert, xtlv) \
 201{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
 202  .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
 203  .name = xname, \
 204  .index = xindex, \
 205  .info = snd_wss_info_double, \
 206  .get = snd_wss_get_double, \
 207  .put = snd_wss_put_double, \
 208  .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | \
 209                   (shift_right << 19) | (mask << 24) | (invert << 22), \
 210  .tlv = { .p = (xtlv) } }
 211
 212
 213int snd_wss_info_double(struct snd_kcontrol *kcontrol,
 214                        struct snd_ctl_elem_info *uinfo);
 215int snd_wss_get_double(struct snd_kcontrol *kcontrol,
 216                        struct snd_ctl_elem_value *ucontrol);
 217int snd_wss_put_double(struct snd_kcontrol *kcontrol,
 218                        struct snd_ctl_elem_value *ucontrol);
 219
 220#endif /* __SOUND_WSS_H */
 221