/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Purpose: Driver for CMEDIA CM8738 PCI audio controller. */ /* * This file is part of Open Sound System * * Copyright (C) 4Front Technologies 1996-2008. * * This software is released under CDDL 1.0 source license. * See the COPYING file included in the main directory of this source * distribution for the license terms and conditions. */ #ifndef _AUDIOCMI_H #define _AUDIOCMI_H #define CMEDIA_VENDOR_ID 0x13F6 #define CMEDIA_CM8738 0x0111 #define CMEDIA_CM8338A 0x0100 #define CMEDIA_CM8338B 0x0101 /* * CM8338 registers definition */ #define REG_FUNCTRL0 0x00 #define REG_FUNCTRL1 0x04 #define REG_CHFORMAT 0x08 #define REG_INTCTRL 0x0C #define REG_INTSTAT 0x10 #define REG_LEGACY 0x14 #define REG_MISC 0x18 #define REG_TDMAPOS 0x1C #define REG_SBVER 0x20 /* 8 bit access only */ #define REG_IDXDATA 0x22 /* 8 bit access only */ #define REG_IDXADDR 0x23 /* 8 bit access only */ #define REG_MIX2 0x24 #define REG_MIX3 0x25 #define REG_VAUX 0x26 #define REG_CH0_PADDR 0x80 /* buffer address (32b) */ #define REG_CH0_BUFSZ 0x84 /* buffer size in samples (16b) */ #define REG_CH0_FRAGSZ 0x86 /* fragment size in samples (16b) */ #define REG_CH1_PADDR 0x88 #define REG_CH1_BUFSZ 0x8C #define REG_CH1_FRAGSZ 0x8E #define REG_SPDIF_STAT 0x90 #define REG_MISC2 0x92 #define FUNCTRL0_CH1_RST BIT(19) #define FUNCTRL0_CH0_RST BIT(18) #define FUNCTRL0_CH1_EN BIT(17) #define FUNCTRL0_CH0_EN BIT(16) #define FUNCTRL0_CH1_PAUSE BIT(3) #define FUNCTRL0_CH0_PAUSE BIT(2) #define FUNCTRL0_CH1_REC BIT(1) #define FUNCTRL0_CH0_REC BIT(0) #define FUNCTRL1_DAC_RATE_MASK (0x7 << 13) #define FUNCTRL1_DAC_RATE_48K (0x7 << 13) #define FUNCTRL1_DAC_RATE_32K (0x6 << 13) #define FUNCTRL1_DAC_RATE_16K (0x5 << 13) #define FUNCTRL1_DAC_RATE_8K (0x4 << 13) #define FUNCTRL1_DAC_RATE_44K (0x3 << 13) #define FUNCTRL1_DAC_RATE_22K (0x2 << 13) #define FUNCTRL1_DAC_RATE_11K (0x1 << 13) #define FUNCTRL1_DAC_RATE_5K (0x0 << 13) #define FUNCTRL1_ADC_RATE_MASK (0x7 << 10) #define FUNCTRL1_ADC_RATE_48K (0x7 << 10) #define FUNCTRL1_ADC_RATE_32K (0x6 << 10) #define FUNCTRL1_ADC_RATE_16K (0x5 << 10) #define FUNCTRL1_ADC_RATE_8K (0x4 << 10) #define FUNCTRL1_ADC_RATE_44K (0x3 << 10) #define FUNCTRL1_ADC_RATE_22K (0x2 << 10) #define FUNCTRL1_ADC_RATE_11K (0x1 << 10) #define FUNCTRL1_ADC_RATE_5K (0x0 << 10) #define FUNCTRL1_INTRM BIT(5) /* enable MCB intr */ #define FUNCTRL1_BREQ BIT(4) /* bus master enable */ #define FUNCTRL1_VOICE_EN BIT(3) #define FUNCTRL1_UART_EN BIT(2) #define FUNCTRL1_JYSTK_EN BIT(1) #define CHFORMAT_CHB3D5C BIT(31) /* 5 channel surround */ #define CHFORMAT_CHB3D BIT(29) /* 4 channel surround */ #define CHFORMAT_VER_MASK (0x1f << 24) #define CHFORMAT_VER_033 0 #define CHFORMAT_VER_037 1 #define CHFORMAT_CH1_MASK (0x3 << 2) #define CHFORMAT_CH1_16ST (0x3 << 2) #define CHFORMAT_CH1_16MO (0x2 << 2) #define CHFORMAT_CH1_8ST (0x1 << 2) #define CHFORMAT_CH1_8MO (0x0 << 2) #define CHFORMAT_CH0_MASK (0x3 << 0) #define CHFORMAT_CH0_16ST (0x3 << 0) #define CHFORMAT_CH0_16MO (0x2 << 0) #define CHFORMAT_CH0_8ST (0x1 << 0) #define CHFORMAT_CH0_8MO (0x0 << 0) #define INTCTRL_MDL_MASK (0xffU << 24) #define INTCTRL_MDL_068 (0x28 << 24) #define INTCTRL_MDL_055 (0x8 << 24) #define INTCTRL_MDL_039 (0x4 << 24) #define INTCTRL_TDMA_EN BIT(18) #define INTCTRL_CH1_EN BIT(17) #define INTCTRL_CH0_EN BIT(16) #define INTSTAT_INTR BIT(31) #define INTSTAT_MCB_INT BIT(26) #define INTSTAT_UART_INT BIT(16) #define INTSTAT_LTDMA_INT BIT(15) #define INTSTAT_HTDMA_INT BIT(14) #define INTSTAT_LHBTOG BIT(7) #define INTSTAT_LEGDMA BIT(6) #define INTSTAT_LEGHIGH BIT(5) #define INTSTAT_LEGSTEREO BIT(4) #define INTSTAT_CH1_BUSY BIT(3) #define INTSTAT_CH0_BUSY BIT(2) #define INTSTAT_CH1_INT BIT(1) #define INTSTAT_CH0_INT BIT(0) #define LEGACY_NXCHG BIT(31) #define LEGACY_CHB3D6C BIT(15) /* 6 channel surround */ #define LEGACY_CENTR2LN BIT(14) /* line in as center out */ #define LEGACY_BASS2LN BIT(13) /* line in as lfe */ #define LEGACY_EXBASSEN BIT(12) /* external bass input enable */ #define MISC_PWD BIT(31) /* power down */ #define MISC_RESET BIT(30) #define MISC_N4SPK3D BIT(26) /* 4 channel emulation */ #define MISC_ENDBDAC BIT(23) /* dual dac */ #define MISC_XCHGDAC BIT(22) /* swap front/rear dacs */ #define MISC_SPD32SEL BIT(21) /* 32-bit SPDIF (default 16-bit) */ #define MISC_FM_EN BIT(19) /* enable legacy FM */ #define MISC_SPDF_AC97 BIT(15) /* spdif out 44.1k (0), 48 k (1) */ #define MISC_ENCENTER BIT(7) /* enable center */ #define MISC_REAR2LN BIT(6) /* send rear to line in */ #define MIX2_FMMUTE BIT(7) #define MIX2_WSMUTE BIT(6) #define MIX2_SPK4 BIT(5) /* line-in is rear out */ #define MIX2_REAR2FRONT BIT(4) /* swap front and rear */ #define MIX2_WAVEIN_L BIT(3) /* for recording wave out */ #define MIX2_WAVEIN_R BIT(2) /* for recording wave out */ #define MIX2_X3DEN BIT(1) /* 3D surround enable */ #define MIX2_CDPLAY BIT(0) /* spdif-in PCM to DAC */ #define MIX3_RAUXREN BIT(7) #define MIX3_RAUXLEN BIT(6) #define MIX3_VAUXRM BIT(5) /* r-aux mute */ #define MIX3_VAUXLM BIT(4) /* l-aux mute */ #define MIX3_VADCMIC_MASK (0x7 << 1) /* rec mic volume */ #define MIX3_CEN2MIC BIT(2) #define MIX3_MICGAINZ BIT(0) /* mic gain */ #define VAUX_L_MASK 0xf0 #define VAUX_R_MASK 0x0f #define MISC2_CHB3D8C BIT(5) /* 8 channel surround */ #define MISC2_SPD32FMT BIT(4) /* spdif at 32 kHz */ #define MISC2_ADC2SPDIF BIT(3) /* send adc to spdif out */ #define MISC2_SHAREADC BIT(2) /* use adc for cen/lfe */ /* Indexes via SBINDEX */ #define IDX_MASTER_LEFT 0x30 #define IDX_MASTER_RIGHT 0x31 #define IDX_VOICE_LEFT 0x32 /* PCM volume */ #define IDX_VOICE_RIGHT 0x33 #define IDX_CDDA_LEFT 0x36 #define IDX_CDDA_RIGHT 0x37 #define IDX_LINEIN_LEFT 0x38 #define IDX_LINEIN_RIGHT 0x39 #define IDX_MIC 0x3A #define IDX_SPEAKER 0x3B #define IDX_OUTMIX 0x3C #define OUTMIX_MIC 0x01 #define OUTMIX_CD_R 0x02 #define OUTMIX_CD_L 0x04 #define OUTMIX_LINE_R 0x08 #define OUTMIX_LINE_L 0x10 #define IDX_INMIX_L 0x3D #define IDX_INMIX_R 0x3E #define INMIX_LINE_R 0x08 #define INMIX_LINE_L 0x10 #define INMIX_CD_R 0x20 #define INMIX_CD_L 0x40 #define INMIX_MIC 0x01 #define IDX_IGAIN_L 0x3F #define IDX_IGAIN_R 0x40 #define IDX_OGAIN_L 0x41 #define IDX_OGAIN_R 0x42 #define IDX_AGC 0x43 #define IDX_TREBLE_L 0x44 #define IDX_TREBLE_R 0x45 #define IDX_BASS_L 0x46 #define IDX_BASS_R 0x47 #define IDX_EXTENSION 0xf0 #define EXTENSION_VPHONE_MASK (0x7 << 5) #define EXTENSION_VPHONE_MUTE BIT(4) #define EXTENSION_BEEPER_MUTE BIT(3) #define EXTENSION_VADCMIC3 BIT(0) enum { SRC_MIC = 0, SRC_LINE, SRC_CD, SRC_AUX, SRC_MIX, }; enum { CTL_VOLUME = 0, CTL_LINEOUT, CTL_SPEAKER, CTL_MIC, CTL_LINEIN, CTL_CD, CTL_AUX, CTL_RECSRCS, CTL_MONSRCS, CTL_MICBOOST, CTL_NUM }; typedef struct cmpci_port cmpci_port_t; typedef struct cmpci_dev cmpci_dev_t; typedef struct cmpci_ctrl cmpci_ctrl_t; struct cmpci_ctrl { cmpci_dev_t *dev; audio_ctrl_t *ctrl; uint64_t value; }; struct cmpci_port { cmpci_dev_t *dev; audio_engine_t *engine; int num; ddi_acc_handle_t acch; ddi_dma_handle_t dmah; caddr_t kaddr; uint32_t paddr; unsigned nframes; unsigned bufsz; unsigned nchan; boolean_t capture; boolean_t open; /* registers & bit masks */ uint8_t reg_paddr; uint8_t reg_bufsz; uint8_t reg_fragsz; uint32_t fc0_rst_bit; uint32_t fc0_rec_bit; uint32_t fc0_en_bit; uint32_t int_en_bit; uint32_t fc1_rate_mask; uint32_t chformat_mask; int sync_dir; uint32_t offset; /* in bytes */ uint64_t count; /* in bytes */ void (*callb)(audio_engine_t *); cmpci_ctrl_t controls[CTL_NUM]; }; #define PORT_MAX 2 struct cmpci_dev { audio_dev_t *adev; dev_info_t *dip; ddi_acc_handle_t acch; caddr_t regs; boolean_t softvol; int pintrs; int rintrs; ddi_intr_handle_t ihandle; kstat_t *ksp; int maxch; kmutex_t mutex; cmpci_port_t port[PORT_MAX]; cmpci_ctrl_t controls[CTL_NUM]; }; /* * The hardware appears to be able to address up to 16-bits worth of samples, * giving a total address space of 256K. Note, however, that we will restrict * this further when we do fragment and memory allocation. */ #define DEFINTS 175 #define GET8(dev, offset) \ ddi_get8(dev->acch, (uint8_t *)(dev->regs + (offset))) #define GET16(dev, offset) \ ddi_get16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset))) #define GET32(dev, offset) \ ddi_get32(dev->acch, (uint32_t *)(void *)(dev->regs + (offset))) #define PUT8(dev, offset, v) \ ddi_put8(dev->acch, (uint8_t *)(dev->regs + (offset)), v) #define PUT16(dev, offset, v) \ ddi_put16(dev->acch, (uint16_t *)(void *)(dev->regs + (offset)), v) #define PUT32(dev, offset, v) \ ddi_put32(dev->acch, (uint32_t *)(void *)(dev->regs + (offset)), v) #define CLR8(dev, offset, v) PUT8(dev, offset, GET8(dev, offset) & ~(v)) #define SET8(dev, offset, v) PUT8(dev, offset, GET8(dev, offset) | (v)) #define CLR16(dev, offset, v) PUT16(dev, offset, GET16(dev, offset) & ~(v)) #define SET16(dev, offset, v) PUT16(dev, offset, GET16(dev, offset) | (v)) #define CLR32(dev, offset, v) PUT32(dev, offset, GET32(dev, offset) & ~(v)) #define SET32(dev, offset, v) PUT32(dev, offset, GET32(dev, offset) | (v)) #define BIT(n) (1U << (n)) #endif /* _AUDIOCMI_H */