root/sys/dev/sound/pci/hda/hdac_private.h
/*-
 * SPDX-License-Identifier: BSD-2-Clause
 *
 * Copyright (c) 2006 Stephane E. Potvin <sepotvin@videotron.ca>
 * Copyright (c) 2008-2012 Alexander Motin <mav@FreeBSD.org>
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
 */

#ifndef _HDAC_PRIVATE_H_
#define _HDAC_PRIVATE_H_

/****************************************************************************
 * Miscellaneous defines
 ****************************************************************************/
#define HDAC_CODEC_MAX          16

/****************************************************************************
 * Helper Macros
 ****************************************************************************/
#define HDAC_READ_1(mem, offset)                                        \
        bus_space_read_1((mem)->mem_tag, (mem)->mem_handle, (offset))
#define HDAC_READ_2(mem, offset)                                        \
        bus_space_read_2((mem)->mem_tag, (mem)->mem_handle, (offset))
#define HDAC_READ_4(mem, offset)                                        \
        bus_space_read_4((mem)->mem_tag, (mem)->mem_handle, (offset))
#define HDAC_WRITE_1(mem, offset, value)                                \
        bus_space_write_1((mem)->mem_tag, (mem)->mem_handle, (offset), (value))
#define HDAC_WRITE_2(mem, offset, value)                                \
        bus_space_write_2((mem)->mem_tag, (mem)->mem_handle, (offset), (value))
#define HDAC_WRITE_4(mem, offset, value)                                \
        bus_space_write_4((mem)->mem_tag, (mem)->mem_handle, (offset), (value))

#define HDAC_ISDCTL(sc, n)      (_HDAC_ISDCTL((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_ISDSTS(sc, n)      (_HDAC_ISDSTS((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_ISDPICB(sc, n)     (_HDAC_ISDPICB((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_ISDCBL(sc, n)      (_HDAC_ISDCBL((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_ISDLVI(sc, n)      (_HDAC_ISDLVI((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_ISDFIFOD(sc, n)    (_HDAC_ISDFIFOD((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_ISDFMT(sc, n)      (_HDAC_ISDFMT((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_ISDBDPL(sc, n)     (_HDAC_ISDBDPL((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_ISDBDPU(sc, n)     (_HDAC_ISDBDPU((n), (sc)->num_iss, (sc)->num_oss))

#define HDAC_OSDCTL(sc, n)      (_HDAC_OSDCTL((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_OSDSTS(sc, n)      (_HDAC_OSDSTS((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_OSDPICB(sc, n)     (_HDAC_OSDPICB((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_OSDCBL(sc, n)      (_HDAC_OSDCBL((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_OSDLVI(sc, n)      (_HDAC_OSDLVI((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_OSDFIFOD(sc, n)    (_HDAC_OSDFIFOD((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_OSDBDPL(sc, n)     (_HDAC_OSDBDPL((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_OSDBDPU(sc, n)     (_HDAC_OSDBDPU((n), (sc)->num_iss, (sc)->num_oss))

#define HDAC_BSDCTL(sc, n)      (_HDAC_BSDCTL((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_BSDSTS(sc, n)      (_HDAC_BSDSTS((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_BSDPICB(sc, n)     (_HDAC_BSDPICB((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_BSDCBL(sc, n)      (_HDAC_BSDCBL((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_BSDLVI(sc, n)      (_HDAC_BSDLVI((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_BSDFIFOD(sc, n)    (_HDAC_BSDFIFOD((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_BSDBDPL(sc, n)     (_HDAC_BSDBDPL((n), (sc)->num_iss, (sc)->num_oss))
#define HDAC_BSDBDPU(sc, n)     (_HDAC_BSDBDPU((n), (sc)->num_iss, (sc)->num_oss))

/****************************************************************************
 * Custom hdac malloc type
 ****************************************************************************/
MALLOC_DECLARE(M_HDAC);

/****************************************************************************
 * struct hdac_mem
 *
 * Holds the resources necessary to describe the physical memory associated
 * with the device.
 ****************************************************************************/
struct hdac_mem {
        struct resource         *mem_res;
        int                     mem_rid;
        bus_space_tag_t         mem_tag;
        bus_space_handle_t      mem_handle;
};

/****************************************************************************
 * struct hdac_irq
 *
 * Holds the resources necessary to describe the irq associated with the
 * device.
 ****************************************************************************/
struct hdac_irq {
        struct resource         *irq_res;
        int                     irq_rid;
        void                    *irq_handle;
};

/****************************************************************************
 * struct hdac_dma
 *
 * This structure is used to hold all the information to manage the dma
 * states.
 ****************************************************************************/
struct hdac_dma {
        bus_dma_tag_t   dma_tag;
        bus_dmamap_t    dma_map;
        bus_addr_t      dma_paddr;
        bus_size_t      dma_size;
        caddr_t         dma_vaddr;
};

/****************************************************************************
 * struct hdac_rirb
 *
 * Hold a response from a verb sent to a codec received via the rirb.
 ****************************************************************************/
struct hdac_rirb {
        uint32_t        response;
        uint32_t        response_ex;
};

#define HDAC_RIRB_RESPONSE_EX_SDATA_IN_MASK     0x0000000f
#define HDAC_RIRB_RESPONSE_EX_SDATA_IN_OFFSET   0
#define HDAC_RIRB_RESPONSE_EX_UNSOLICITED       0x00000010

#define HDAC_RIRB_RESPONSE_EX_SDATA_IN(response_ex)                     \
    (((response_ex) & HDAC_RIRB_RESPONSE_EX_SDATA_IN_MASK) >>           \
    HDAC_RIRB_RESPONSE_EX_SDATA_IN_OFFSET)

struct hdac_bdle {
        volatile uint32_t addrl;
        volatile uint32_t addrh;
        volatile uint32_t len;
        volatile uint32_t ioc;
} __packed;

struct hdac_stream {
        device_t        dev;
        struct hdac_dma bdl;
        int             dir;
        int             stream;
        int             blksz;
        int             running;
        int             bw;
        int             stripe;
        uint16_t        format;
};

struct hdac_softc {
        device_t        dev;
        struct mtx      lock;

        struct intr_config_hook intrhook;

        struct hdac_mem mem;
        struct hdac_irq irq;

        uint32_t        quirks_on;
        uint32_t        quirks_off;
        uint32_t        flags;
#define HDAC_F_DMA_NOCACHE      0x00000001

        int             num_iss;
        int             num_oss;
        int             num_bss;
        int             num_ss;
        int             num_sdo;
        int             support_64bit;

        int             corb_size;
        struct hdac_dma corb_dma;
        int             corb_wp;

        int             rirb_size;
        struct hdac_dma rirb_dma;
        int             rirb_rp;

        struct hdac_dma pos_dma;

        bus_dma_tag_t           chan_dmat;

        /* Polling */
        int                     polling;
        int                     poll_ival;
        struct callout          poll_callout;

        int                     unsol_registered;
        struct task             unsolq_task;
#define HDAC_UNSOLQ_MAX         64
#define HDAC_UNSOLQ_READY       0
#define HDAC_UNSOLQ_BUSY        1
        int             unsolq_rp;
        int             unsolq_wp;
        int             unsolq_st;
        uint32_t        unsolq[HDAC_UNSOLQ_MAX];

        int                     sdo_bw_used;

        struct hdac_stream      *streams;

        struct {
                device_t        dev;
                uint16_t        vendor_id;
                uint16_t        device_id;
                uint8_t         revision_id;
                uint8_t         stepping_id;
                int             pending;
                uint32_t        response;
                int             sdi_bw_used;
        } codecs[HDAC_CODEC_MAX];
};

#endif