root/sys/dev/pci/cs428x.h
/*      $NetBSD: cs428x.h,v 1.18 2021/02/03 14:44:32 isaki Exp $        */

/*
 * Copyright (c) 2000 Tatoku Ogaito.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by Tatoku Ogaito
 *      for the NetBSD Project.
 * 4. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/* Common functions and variables for CS4280 and CS4281 */

#ifndef _CS428X_H_
#define _CS428X_H_

#define PCI_BA0               (0x10)
#define PCI_BA1               (0x14)

#define CS428X_SAVE_REG_MAX   (0x10)
#define TYPE_CS4280           (0x4280)
#define TYPE_CS4281           (0x4281)

#define BA0READ4(sc, r) bus_space_read_4((sc)->ba0t, (sc)->ba0h, (r))
#define BA0WRITE4(sc, r, x) bus_space_write_4((sc)->ba0t, (sc)->ba0h, (r), (x))

/* DMA */
struct cs428x_dma {
        bus_dmamap_t map;
        void *addr;             /* real DMA buffer */
        void *dum;              /* dummy buffer for audio driver */
        bus_dma_segment_t segs[1];
        int nsegs;
        size_t size;
        struct cs428x_dma *next;
};
#define DMAADDR(p) ((p)->map->dm_segs[0].ds_addr)
#define KERNADDR(p) ((void *)((p)->addr)) /* buffer for real DMA */
#define BUFADDR(p)  ((void *)((p)->dum))  /* buffer for audio driver */

/*
 * Flags (currently used only for CS4280)
 */
enum cs428x_flags {
        CS428X_FLAG_NONE        = 0x0,
        CS428X_FLAG_INVAC97EAMP = 0x1,  /* inverted AC97 external amp */
        CS428X_FLAG_CLKRUNHACK  = 0x2   /* needs CLKRUN hack */
};

/*
 * Software state
 */
struct cs428x_softc {
        device_t              sc_dev;
        kmutex_t              sc_lock;
        kmutex_t              sc_intr_lock;

        pci_chipset_tag_t sc_pc;
        pcitag_t sc_pt;
        pci_intr_handle_t *   sc_ih;
        pci_intr_handle_t intrh;

        /* I/O (BA0) */
        bus_space_tag_t       ba0t;
        bus_space_handle_t    ba0h;

        /* BA1 */
        bus_space_tag_t       ba1t;
        bus_space_handle_t    ba1h;

        /* DMA */
        bus_dma_tag_t    sc_dmatag;
        struct cs428x_dma *sc_dmas;
        size_t dma_size;
        size_t dma_align;

        int     hw_blocksize;
        int     type;

        /* playback */
        void    (*sc_pintr)(void *);    /* DMA completion intr handler */
        void    *sc_parg;               /* arg for sc_intr() */
        char    *sc_ps, *sc_pe, *sc_pn;
        int     sc_pcount;
        int     sc_pi;
        struct  cs428x_dma *sc_pdma;
        char    *sc_pbuf;
        char    sc_prun;                /* playback status */
        int     sc_prate;               /* playback sample rate */

        /* capturing */
        void    (*sc_rintr)(void *);    /* DMA completion intr handler */
        void    *sc_rarg;               /* arg for sc_intr() */
        char    *sc_rs, *sc_re, *sc_rn;
        int     sc_rcount;
        int     sc_ri;
        struct  cs428x_dma *sc_rdma;
        char    *sc_rbuf;
        char    sc_rrun;                /* recording status */
        int     sc_rrate;               /* recording sample rate */

        /* Although cs4281 does not support midi (yet),
         * don't remove these definition.
         */
        void    (*sc_iintr)(void *, int); /* midi input ready handler */
        void    (*sc_ointr)(void *);      /* midi output ready handler */
        void    *sc_arg;

        /*
         * XXX
         * Actually these 3 variables are needed only for CS4280.
         */
        enum cs428x_flags sc_flags;
        uint32_t pctl;
        uint32_t cctl;

        /* AC97 CODEC */
        struct ac97_codec_if *codec_if;
        struct ac97_host_if host_if;

        /* Power Management */
        union {
                struct {
                        uint32_t pctl;
                        uint32_t pba;
                        uint32_t pfie;
                        uint32_t pdtc;
                        uint32_t cctl;
                        uint32_t cba;
                        uint32_t cie;
                } cs4280;
                struct {
                        uint32_t dba0;
                        uint32_t dbc0;
                        uint32_t dmr0;
                        uint32_t dcr0;
                        uint32_t dba1;
                        uint32_t dbc1;
                        uint32_t dmr1;
                        uint32_t dcr1;
                } cs4281;
        } sc_suspend_state;

        /* CLKRUN hack (CS428X_FLAG_CLKRUN), only for CS4280 */
        int sc_active;
        bus_space_tag_t    sc_pm_iot;
        bus_space_handle_t sc_pm_ioh;
};


int  cs428x_round_blocksize(void *, int, int, const audio_params_t *);
int  cs428x_get_props(void *);
int  cs428x_attach_codec(void *, struct ac97_codec_if *);
int  cs428x_read_codec(void *, u_int8_t, u_int16_t *);
int  cs428x_write_codec(void *, u_int8_t, u_int16_t);

int  cs428x_mixer_set_port(void *, mixer_ctrl_t *);
int  cs428x_mixer_get_port(void *, mixer_ctrl_t *);
int  cs428x_query_devinfo(void *, mixer_devinfo_t *);
void *cs428x_malloc(void *, int, size_t);
size_t cs428x_round_buffersize(void *, int, size_t);
void cs428x_free(void *, void *, size_t);
void cs428x_get_locks(void *, kmutex_t **, kmutex_t **);

/* internal functions */
int cs428x_allocmem(struct cs428x_softc *, size_t, struct cs428x_dma *);
int cs428x_src_wait(struct cs428x_softc *);


/* DEBUG */
/* #define CS4280_DEBUG */
/* #define CS4281_DEBUG */

#if defined(CS4280_DEBUG) || defined(CS4281_DEBUG)
#define DPRINTF(x)          if (cs428x_debug) printf x
#define DPRINTFN(n,x)       if (cs428x_debug>(n)) printf x
extern int cs428x_debug;
#if CS4280_DEBUG + 0 == 0
#undef CS4280_DEBUG
#define CS4280_DEBUG 0
#endif
#else
#define DPRINTF(x)
#define DPRINTFN(n,x)
#endif

#endif /* _CS428X_H_ */