188447a05SGarrett D'Amore /*
288447a05SGarrett D'Amore * CDDL HEADER START
388447a05SGarrett D'Amore *
488447a05SGarrett D'Amore * The contents of this file are subject to the terms of the
588447a05SGarrett D'Amore * Common Development and Distribution License (the "License").
688447a05SGarrett D'Amore * You may not use this file except in compliance with the License.
788447a05SGarrett D'Amore *
888447a05SGarrett D'Amore * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
988447a05SGarrett D'Amore * or http://www.opensolaris.org/os/licensing.
1088447a05SGarrett D'Amore * See the License for the specific language governing permissions
1188447a05SGarrett D'Amore * and limitations under the License.
1288447a05SGarrett D'Amore *
1388447a05SGarrett D'Amore * When distributing Covered Code, include this CDDL HEADER in each
1488447a05SGarrett D'Amore * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1588447a05SGarrett D'Amore * If applicable, add the following below this CDDL HEADER, with the
1688447a05SGarrett D'Amore * fields enclosed by brackets "[]" replaced with your own identifying
1788447a05SGarrett D'Amore * information: Portions Copyright [yyyy] [name of copyright owner]
1888447a05SGarrett D'Amore *
1988447a05SGarrett D'Amore * CDDL HEADER END
2088447a05SGarrett D'Amore */
2188447a05SGarrett D'Amore /*
22*68c47f65SGarrett D'Amore * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
2388447a05SGarrett D'Amore * Use is subject to license terms.
2488447a05SGarrett D'Amore */
2588447a05SGarrett D'Amore
2688447a05SGarrett D'Amore /*
2788447a05SGarrett D'Amore * Platform specifc code for the EB2 DMA controller. The EB2 is a PCI bus
2888447a05SGarrett D'Amore * IC that includes play and record DMA engines and an interface for
2988447a05SGarrett D'Amore * the CS4231.
3088447a05SGarrett D'Amore */
3188447a05SGarrett D'Amore
3288447a05SGarrett D'Amore #include <sys/systm.h>
3388447a05SGarrett D'Amore #include <sys/ddi.h>
3488447a05SGarrett D'Amore #include <sys/sunddi.h>
3588447a05SGarrett D'Amore #include <sys/note.h>
3688447a05SGarrett D'Amore #include <sys/audio/audio_driver.h>
3788447a05SGarrett D'Amore #include "audio_4231.h"
3888447a05SGarrett D'Amore
3988447a05SGarrett D'Amore /*
4088447a05SGarrett D'Amore * Attribute structure for the APC, used to create DMA handles.
4188447a05SGarrett D'Amore */
4288447a05SGarrett D'Amore static ddi_dma_attr_t eb2_dma_attr = {
4388447a05SGarrett D'Amore DMA_ATTR_V0, /* version */
4488447a05SGarrett D'Amore 0x0000000000000000LL, /* dlim_addr_lo */
4588447a05SGarrett D'Amore 0x00000000ffffffffLL, /* dlim_addr_hi */
4688447a05SGarrett D'Amore 0x0000000000ffffffLL, /* DMA counter register */
4788447a05SGarrett D'Amore 0x0000000000000001LL, /* DMA address alignment */
4888447a05SGarrett D'Amore 0x00000074, /* 4 and 16 byte burst sizes */
4988447a05SGarrett D'Amore 0x00000001, /* min effective DMA size */
5088447a05SGarrett D'Amore 0x000000000000ffffLL, /* maximum transfer size, 8k */
5188447a05SGarrett D'Amore 0x000000000000ffffLL, /* segment boundary, 32k */
5288447a05SGarrett D'Amore 0x00000001, /* s/g list length, no s/g */
5388447a05SGarrett D'Amore 0x00000001, /* granularity of device, don't care */
5488447a05SGarrett D'Amore 0 /* DMA flags */
5588447a05SGarrett D'Amore };
5688447a05SGarrett D'Amore
5788447a05SGarrett D'Amore static ddi_device_acc_attr_t codec_attr = {
5888447a05SGarrett D'Amore DDI_DEVICE_ATTR_V0,
5988447a05SGarrett D'Amore DDI_STRUCTURE_BE_ACC,
6088447a05SGarrett D'Amore DDI_STRICTORDER_ACC
6188447a05SGarrett D'Amore };
6288447a05SGarrett D'Amore
6388447a05SGarrett D'Amore static ddi_device_acc_attr_t eb2_attr = {
6488447a05SGarrett D'Amore DDI_DEVICE_ATTR_V0,
6588447a05SGarrett D'Amore DDI_STRUCTURE_LE_ACC,
6688447a05SGarrett D'Amore DDI_STRICTORDER_ACC
6788447a05SGarrett D'Amore };
6888447a05SGarrett D'Amore
6988447a05SGarrett D'Amore /*
7088447a05SGarrett D'Amore * DMA ops vector functions
7188447a05SGarrett D'Amore */
7288447a05SGarrett D'Amore static int eb2_map_regs(CS_state_t *);
7388447a05SGarrett D'Amore static void eb2_unmap_regs(CS_state_t *);
7488447a05SGarrett D'Amore static void eb2_reset(CS_state_t *);
7588447a05SGarrett D'Amore static int eb2_start_engine(CS_engine_t *);
7688447a05SGarrett D'Amore static void eb2_stop_engine(CS_engine_t *);
7788447a05SGarrett D'Amore static void eb2_power(CS_state_t *, int);
78*68c47f65SGarrett D'Amore static void eb2_reload(CS_engine_t *);
79*68c47f65SGarrett D'Amore static uint32_t eb2_addr(CS_engine_t *);
8088447a05SGarrett D'Amore
8188447a05SGarrett D'Amore cs4231_dma_ops_t cs4231_eb2dma_ops = {
8288447a05SGarrett D'Amore "EB2 DMA controller",
8388447a05SGarrett D'Amore &eb2_dma_attr,
8488447a05SGarrett D'Amore eb2_map_regs,
8588447a05SGarrett D'Amore eb2_unmap_regs,
8688447a05SGarrett D'Amore eb2_reset,
8788447a05SGarrett D'Amore eb2_start_engine,
8888447a05SGarrett D'Amore eb2_stop_engine,
8988447a05SGarrett D'Amore eb2_power,
90*68c47f65SGarrett D'Amore eb2_reload,
91*68c47f65SGarrett D'Amore eb2_addr,
9288447a05SGarrett D'Amore };
9388447a05SGarrett D'Amore
9488447a05SGarrett D'Amore /*
9588447a05SGarrett D'Amore * eb2_map_regs()
9688447a05SGarrett D'Amore *
9788447a05SGarrett D'Amore * Description:
9888447a05SGarrett D'Amore * This routine allocates the DMA handles and the memory for the
9988447a05SGarrett D'Amore * DMA engines to use. It then binds each of the buffers to its
10088447a05SGarrett D'Amore * respective handle, getting a DMA cookie. Finally, the registers
10188447a05SGarrett D'Amore * are mapped in.
10288447a05SGarrett D'Amore *
10388447a05SGarrett D'Amore * NOTE: All of the ddi_dma_... routines sleep if they cannot get
10488447a05SGarrett D'Amore * memory. This means these calls will almost always succeed.
10588447a05SGarrett D'Amore *
10688447a05SGarrett D'Amore * Arguments:
10788447a05SGarrett D'Amore * CS_state_t *state The device's state
10888447a05SGarrett D'Amore *
10988447a05SGarrett D'Amore * Returns:
11088447a05SGarrett D'Amore * DDI_SUCCESS Registers successfully mapped
11188447a05SGarrett D'Amore * DDI_FAILURE Registers not successfully mapped
11288447a05SGarrett D'Amore */
11388447a05SGarrett D'Amore static int
eb2_map_regs(CS_state_t * state)11488447a05SGarrett D'Amore eb2_map_regs(CS_state_t *state)
11588447a05SGarrett D'Amore {
11688447a05SGarrett D'Amore dev_info_t *dip = state->cs_dip;
11788447a05SGarrett D'Amore
11888447a05SGarrett D'Amore /* now, map the codec */
11988447a05SGarrett D'Amore if (ddi_regs_map_setup(dip, 0, (caddr_t *)&state->cs_regs, 0,
12088447a05SGarrett D'Amore sizeof (cs4231_pioregs_t), &codec_attr, &CODEC_HANDLE) !=
12188447a05SGarrett D'Amore DDI_SUCCESS) {
12288447a05SGarrett D'Amore audio_dev_warn(state->cs_adev, "failed mapping codec regs");
12388447a05SGarrett D'Amore goto error;
12488447a05SGarrett D'Amore }
12588447a05SGarrett D'Amore
12688447a05SGarrett D'Amore /* next the play registers */
12788447a05SGarrett D'Amore if (ddi_regs_map_setup(dip, 1, (caddr_t *)&state->cs_eb2_regs.play, 0,
12888447a05SGarrett D'Amore sizeof (cs4231_eb2regs_t), &eb2_attr, &EB2_PLAY_HNDL) !=
12988447a05SGarrett D'Amore DDI_SUCCESS) {
13088447a05SGarrett D'Amore audio_dev_warn(state->cs_adev, "failed mapping play regs");
13188447a05SGarrett D'Amore goto error;
13288447a05SGarrett D'Amore }
13388447a05SGarrett D'Amore state->cs_engines[CS4231_PLAY]->ce_regsh = EB2_PLAY_HNDL;
13488447a05SGarrett D'Amore state->cs_engines[CS4231_PLAY]->ce_eb2regs = state->cs_eb2_regs.play;
13588447a05SGarrett D'Amore
13688447a05SGarrett D'Amore /* now the capture registers */
13788447a05SGarrett D'Amore if (ddi_regs_map_setup(dip, 2, (caddr_t *)&state->cs_eb2_regs.record, 0,
13888447a05SGarrett D'Amore sizeof (cs4231_eb2regs_t), &eb2_attr, &EB2_REC_HNDL) !=
13988447a05SGarrett D'Amore DDI_SUCCESS) {
14088447a05SGarrett D'Amore audio_dev_warn(state->cs_adev, "failed mapping rec regs");
14188447a05SGarrett D'Amore goto error;
14288447a05SGarrett D'Amore }
14388447a05SGarrett D'Amore state->cs_engines[CS4231_REC]->ce_regsh = EB2_REC_HNDL;
14488447a05SGarrett D'Amore state->cs_engines[CS4231_REC]->ce_eb2regs = state->cs_eb2_regs.record;
14588447a05SGarrett D'Amore
14688447a05SGarrett D'Amore /* finally the auxio register */
14788447a05SGarrett D'Amore if (ddi_regs_map_setup(dip, 3, (caddr_t *)&state->cs_eb2_regs.auxio, 0,
14888447a05SGarrett D'Amore sizeof (uint_t), &eb2_attr, &EB2_AUXIO_HNDL) != DDI_SUCCESS) {
14988447a05SGarrett D'Amore audio_dev_warn(state->cs_adev, "failed mapping auxio reg");
15088447a05SGarrett D'Amore goto error;
15188447a05SGarrett D'Amore }
15288447a05SGarrett D'Amore
15388447a05SGarrett D'Amore /* disable play and record interrupts */
15488447a05SGarrett D'Amore ddi_put32(EB2_PLAY_HNDL, &EB2_PLAY_CSR, EB2_PCLEAR_RESET_VALUE);
15588447a05SGarrett D'Amore ddi_put32(EB2_REC_HNDL, &EB2_REC_CSR, EB2_RCLEAR_RESET_VALUE);
15688447a05SGarrett D'Amore
15788447a05SGarrett D'Amore return (DDI_SUCCESS);
15888447a05SGarrett D'Amore
15988447a05SGarrett D'Amore error:
16088447a05SGarrett D'Amore eb2_unmap_regs(state);
16188447a05SGarrett D'Amore return (DDI_FAILURE);
16288447a05SGarrett D'Amore
16388447a05SGarrett D'Amore } /* eb2_map_regs() */
16488447a05SGarrett D'Amore
16588447a05SGarrett D'Amore /*
16688447a05SGarrett D'Amore * eb2_unmap_regs()
16788447a05SGarrett D'Amore *
16888447a05SGarrett D'Amore * Description:
16988447a05SGarrett D'Amore * This routine unmaps the Codec's and DMA engine's registers.
17088447a05SGarrett D'Amore * It must be idempotent.
17188447a05SGarrett D'Amore *
17288447a05SGarrett D'Amore * Arguments:
17388447a05SGarrett D'Amore * CS_state_t *state The device's state
17488447a05SGarrett D'Amore */
17588447a05SGarrett D'Amore static void
eb2_unmap_regs(CS_state_t * state)17688447a05SGarrett D'Amore eb2_unmap_regs(CS_state_t *state)
17788447a05SGarrett D'Amore {
17888447a05SGarrett D'Amore if (CODEC_HANDLE)
17988447a05SGarrett D'Amore ddi_regs_map_free(&CODEC_HANDLE);
18088447a05SGarrett D'Amore if (EB2_PLAY_HNDL)
18188447a05SGarrett D'Amore ddi_regs_map_free(&EB2_PLAY_HNDL);
18288447a05SGarrett D'Amore if (EB2_REC_HNDL)
18388447a05SGarrett D'Amore ddi_regs_map_free(&EB2_REC_HNDL);
18488447a05SGarrett D'Amore if (EB2_AUXIO_HNDL)
18588447a05SGarrett D'Amore ddi_regs_map_free(&EB2_AUXIO_HNDL);
18688447a05SGarrett D'Amore
18788447a05SGarrett D'Amore } /* eb2_unmap_regs() */
18888447a05SGarrett D'Amore
18988447a05SGarrett D'Amore /*
19088447a05SGarrett D'Amore * eb2_reset()
19188447a05SGarrett D'Amore *
19288447a05SGarrett D'Amore * Description:
19388447a05SGarrett D'Amore * Reset both the play and record DMA engines. The engines are left
19488447a05SGarrett D'Amore * with interrupts and the DMA engine disabled.
19588447a05SGarrett D'Amore *
19688447a05SGarrett D'Amore * Arguments:
19788447a05SGarrett D'Amore * dev_info_t *dip Pointer to the device's devinfo structure
19888447a05SGarrett D'Amore * CS_state_t *state The device's state structure
19988447a05SGarrett D'Amore */
20088447a05SGarrett D'Amore static void
eb2_reset(CS_state_t * state)20188447a05SGarrett D'Amore eb2_reset(CS_state_t *state)
20288447a05SGarrett D'Amore {
20388447a05SGarrett D'Amore ddi_acc_handle_t phandle = EB2_PLAY_HNDL;
20488447a05SGarrett D'Amore ddi_acc_handle_t rhandle = EB2_REC_HNDL;
20588447a05SGarrett D'Amore uint_t reg;
20688447a05SGarrett D'Amore int x;
20788447a05SGarrett D'Amore
20888447a05SGarrett D'Amore /* start with the play side */
20988447a05SGarrett D'Amore ddi_put32(phandle, &EB2_PLAY_CSR, EB2_RESET);
21088447a05SGarrett D'Amore /* wait for play data to drain */
21188447a05SGarrett D'Amore reg = ddi_get32(phandle, &EB2_PLAY_CSR);
21288447a05SGarrett D'Amore for (x = 0; (reg & EB2_FIFO_DRAIN) && x < CS4231_TIMEOUT; x++) {
21388447a05SGarrett D'Amore drv_usecwait(1); /* don't beat on the bus */
21488447a05SGarrett D'Amore reg = ddi_get32(phandle, &EB2_PLAY_CSR);
21588447a05SGarrett D'Amore }
21688447a05SGarrett D'Amore /* clear the reset bit and program for chaining */
21788447a05SGarrett D'Amore ddi_put32(phandle, &EB2_PLAY_CSR, EB2_PCLEAR_RESET_VALUE);
21888447a05SGarrett D'Amore
21988447a05SGarrett D'Amore /* now do the record side and program for chaining */
22088447a05SGarrett D'Amore ddi_put32(rhandle, &EB2_REC_CSR, EB2_RESET);
22188447a05SGarrett D'Amore /* wait for record data to drain */
22288447a05SGarrett D'Amore reg = ddi_get32(rhandle, &EB2_REC_CSR);
22388447a05SGarrett D'Amore for (x = 0; (reg & EB2_FIFO_DRAIN) && x < CS4231_TIMEOUT; x++) {
22488447a05SGarrett D'Amore drv_usecwait(1); /* don't beat on the bus */
22588447a05SGarrett D'Amore reg = ddi_get32(rhandle, &EB2_REC_CSR);
22688447a05SGarrett D'Amore }
22788447a05SGarrett D'Amore /* clear the reset bit */
22888447a05SGarrett D'Amore ddi_put32(rhandle, &EB2_REC_CSR, EB2_RCLEAR_RESET_VALUE);
22988447a05SGarrett D'Amore
23088447a05SGarrett D'Amore } /* eb2_reset() */
23188447a05SGarrett D'Amore
23288447a05SGarrett D'Amore /*
23388447a05SGarrett D'Amore * eb2_start_engine()
23488447a05SGarrett D'Amore *
23588447a05SGarrett D'Amore * Description:
23688447a05SGarrett D'Amore * This routine starts the DMA engine.
23788447a05SGarrett D'Amore *
23888447a05SGarrett D'Amore * NOTE: The state structure must be locked before this routine is called.
23988447a05SGarrett D'Amore *
24088447a05SGarrett D'Amore * Arguments:
24188447a05SGarrett D'Amore * CS_engine_t *eng The DMA engine's state structure
24288447a05SGarrett D'Amore *
24388447a05SGarrett D'Amore * Returns:
24488447a05SGarrett D'Amore * DDI_SUCCESS The DMA engine was started
24588447a05SGarrett D'Amore * DDI_FAILURE The DMA engine was not started
24688447a05SGarrett D'Amore */
24788447a05SGarrett D'Amore static int
eb2_start_engine(CS_engine_t * eng)24888447a05SGarrett D'Amore eb2_start_engine(CS_engine_t *eng)
24988447a05SGarrett D'Amore {
25088447a05SGarrett D'Amore CS_state_t *state = eng->ce_state;
25188447a05SGarrett D'Amore ddi_acc_handle_t handle = eng->ce_regsh;
25288447a05SGarrett D'Amore cs4231_eb2regs_t *regs = eng->ce_eb2regs;
25388447a05SGarrett D'Amore uint_t csr;
25488447a05SGarrett D'Amore int x;
25588447a05SGarrett D'Amore uint32_t reset;
25688447a05SGarrett D'Amore uint32_t enable;
25788447a05SGarrett D'Amore
25888447a05SGarrett D'Amore if (eng->ce_num == CS4231_PLAY) {
25988447a05SGarrett D'Amore reset = EB2_PCLEAR_RESET_VALUE;
26088447a05SGarrett D'Amore enable = EB2_PLAY_ENABLE;
26188447a05SGarrett D'Amore } else {
26288447a05SGarrett D'Amore reset = EB2_RCLEAR_RESET_VALUE;
26388447a05SGarrett D'Amore enable = EB2_REC_ENABLE;
26488447a05SGarrett D'Amore }
26588447a05SGarrett D'Amore
26688447a05SGarrett D'Amore ASSERT(mutex_owned(&state->cs_lock));
26788447a05SGarrett D'Amore
26888447a05SGarrett D'Amore /* reset the DMA engine so we have a good starting place */
26988447a05SGarrett D'Amore OR_SET_WORD(handle, ®s->eb2csr, EB2_RESET);
27088447a05SGarrett D'Amore
27188447a05SGarrett D'Amore /* wait for the FIFO to drain, it should be empty */
27288447a05SGarrett D'Amore csr = ddi_get32(handle, ®s->eb2csr);
27388447a05SGarrett D'Amore for (x = 0; (csr & EB2_FIFO_DRAIN) && x < CS4231_TIMEOUT; x++) {
27488447a05SGarrett D'Amore drv_usecwait(1); /* no reason to beat on the bus */
27588447a05SGarrett D'Amore csr = ddi_get32(handle, ®s->eb2csr);
27688447a05SGarrett D'Amore }
27788447a05SGarrett D'Amore if (x >= CS4231_TIMEOUT) {
27888447a05SGarrett D'Amore audio_dev_warn(state->cs_adev,
27988447a05SGarrett D'Amore "timeout waiting for engine, not started!");
28088447a05SGarrett D'Amore return (DDI_FAILURE);
28188447a05SGarrett D'Amore }
28288447a05SGarrett D'Amore
28388447a05SGarrett D'Amore /* now clear the RESET and EN_DMA bits */
28488447a05SGarrett D'Amore AND_SET_WORD(handle, ®s->eb2csr, ~(EB2_RESET|EB2_EN_DMA));
28588447a05SGarrett D'Amore
28688447a05SGarrett D'Amore /* put into chaining mode, enable byte counts */
28788447a05SGarrett D'Amore OR_SET_WORD(handle, ®s->eb2csr, reset);
28888447a05SGarrett D'Amore
28988447a05SGarrett D'Amore /*
29088447a05SGarrett D'Amore * Program the DMA engine.
29188447a05SGarrett D'Amore */
292*68c47f65SGarrett D'Amore eb2_reload(eng);
29388447a05SGarrett D'Amore
29488447a05SGarrett D'Amore /*
29588447a05SGarrett D'Amore * Start playing before we load the next fragment.
29688447a05SGarrett D'Amore */
29788447a05SGarrett D'Amore OR_SET_WORD(handle, ®s->eb2csr, enable);
29888447a05SGarrett D'Amore
29988447a05SGarrett D'Amore /*
300*68c47f65SGarrett D'Amore * Program the next address, too.
30188447a05SGarrett D'Amore */
302*68c47f65SGarrett D'Amore eb2_reload(eng);
30388447a05SGarrett D'Amore
30488447a05SGarrett D'Amore return (DDI_SUCCESS);
30588447a05SGarrett D'Amore
30688447a05SGarrett D'Amore } /* eb2_start_engine() */
30788447a05SGarrett D'Amore
30888447a05SGarrett D'Amore /*
30988447a05SGarrett D'Amore * eb2_stop_engine()
31088447a05SGarrett D'Amore *
31188447a05SGarrett D'Amore * Description:
31288447a05SGarrett D'Amore * This routine stops the DMA engine.
31388447a05SGarrett D'Amore *
31488447a05SGarrett D'Amore * NOTE: The state structure must be locked before this routine is called.
31588447a05SGarrett D'Amore *
31688447a05SGarrett D'Amore * Arguments:
31788447a05SGarrett D'Amore * CS_engine_t *eng The engine to stop
31888447a05SGarrett D'Amore */
31988447a05SGarrett D'Amore static void
eb2_stop_engine(CS_engine_t * eng)32088447a05SGarrett D'Amore eb2_stop_engine(CS_engine_t *eng)
32188447a05SGarrett D'Amore {
32288447a05SGarrett D'Amore ddi_acc_handle_t handle = eng->ce_regsh;
32388447a05SGarrett D'Amore cs4231_eb2regs_t *regs = eng->ce_eb2regs;
32488447a05SGarrett D'Amore uint_t csr;
32588447a05SGarrett D'Amore
32688447a05SGarrett D'Amore /* shut off DMA and disable interrupts */
32788447a05SGarrett D'Amore AND_SET_WORD(handle, ®s->eb2csr, ~(EB2_EN_DMA | EB2_INT_EN));
32888447a05SGarrett D'Amore
32988447a05SGarrett D'Amore csr = ddi_get32(handle, ®s->eb2csr);
33088447a05SGarrett D'Amore for (int x = 0; (csr & EB2_CYC_PENDING) && x < CS4231_TIMEOUT; x++) {
33188447a05SGarrett D'Amore drv_usecwait(1);
33288447a05SGarrett D'Amore csr = ddi_get32(handle, ®s->eb2csr);
33388447a05SGarrett D'Amore }
33488447a05SGarrett D'Amore
33588447a05SGarrett D'Amore /* set the RESET bit to stop audio, also clear any TC interrupt */
33688447a05SGarrett D'Amore OR_SET_WORD(handle, ®s->eb2csr, EB2_RESET | EB2_TC);
33788447a05SGarrett D'Amore
33888447a05SGarrett D'Amore /* wait for the FIFO to drain */
33988447a05SGarrett D'Amore csr = ddi_get32(handle, ®s->eb2csr);
34088447a05SGarrett D'Amore for (int x = 0; (csr & EB2_FIFO_DRAIN) && x < CS4231_TIMEOUT; x++) {
34188447a05SGarrett D'Amore drv_usecwait(1); /* don't beat on the bus */
34288447a05SGarrett D'Amore csr = ddi_get32(handle, ®s->eb2csr);
34388447a05SGarrett D'Amore }
34488447a05SGarrett D'Amore
34588447a05SGarrett D'Amore /* clear the RESET and EN_DMA bits */
34688447a05SGarrett D'Amore AND_SET_WORD(handle, ®s->eb2csr, ~(EB2_RESET|EB2_EN_DMA));
34788447a05SGarrett D'Amore
34888447a05SGarrett D'Amore } /* eb2_stop_engine() */
34988447a05SGarrett D'Amore
35088447a05SGarrett D'Amore /*
35188447a05SGarrett D'Amore * eb2_power()
35288447a05SGarrett D'Amore *
35388447a05SGarrett D'Amore * Description:
35488447a05SGarrett D'Amore * This routine turns the Codec on or off using the auxio register
35588447a05SGarrett D'Amore * in the eb2 device (cheerio or rio). Fortunately we don't need
35688447a05SGarrett D'Amore * to delay like we do with the APC.
35788447a05SGarrett D'Amore *
35888447a05SGarrett D'Amore * NOTE: The state structure must be locked when this routine is called.
35988447a05SGarrett D'Amore *
36088447a05SGarrett D'Amore * Arguments:
36188447a05SGarrett D'Amore * CS_state_t *state Ptr to the device's state structure
36288447a05SGarrett D'Amore * int level Power level to set
36388447a05SGarrett D'Amore */
36488447a05SGarrett D'Amore static void
eb2_power(CS_state_t * state,int level)36588447a05SGarrett D'Amore eb2_power(CS_state_t *state, int level)
36688447a05SGarrett D'Amore {
36788447a05SGarrett D'Amore ddi_acc_handle_t xhandle = EB2_AUXIO_HNDL;
36888447a05SGarrett D'Amore
36988447a05SGarrett D'Amore if (level == CS4231_PWR_ON) { /* turn power on */
37088447a05SGarrett D'Amore AND_SET_WORD(xhandle, EB2_AUXIO_REG, ~EB2_AUXIO_COD_PDWN);
37188447a05SGarrett D'Amore } else { /* turn power off */
37288447a05SGarrett D'Amore OR_SET_WORD(xhandle, EB2_AUXIO_REG, EB2_AUXIO_COD_PDWN);
37388447a05SGarrett D'Amore }
37488447a05SGarrett D'Amore
37588447a05SGarrett D'Amore } /* eb2_power() */
37688447a05SGarrett D'Amore
37788447a05SGarrett D'Amore /*
378*68c47f65SGarrett D'Amore * eb2_reload()
37988447a05SGarrett D'Amore *
38088447a05SGarrett D'Amore * Description:
381*68c47f65SGarrett D'Amore * This routine reloads the DMA address, so that we can continue
382*68c47f65SGarrett D'Amore * double buffer round-robin fashion.
38388447a05SGarrett D'Amore *
38488447a05SGarrett D'Amore * Arguments:
385*68c47f65SGarrett D'Amore * CS_engine_t *eng The engine
38688447a05SGarrett D'Amore */
38788447a05SGarrett D'Amore static void
eb2_reload(CS_engine_t * eng)388*68c47f65SGarrett D'Amore eb2_reload(CS_engine_t *eng)
38988447a05SGarrett D'Amore {
39088447a05SGarrett D'Amore ddi_acc_handle_t handle = eng->ce_regsh;
39188447a05SGarrett D'Amore cs4231_eb2regs_t *regs = eng->ce_eb2regs;
39288447a05SGarrett D'Amore
39388447a05SGarrett D'Amore /* if next address already loaded, then we're done */
39488447a05SGarrett D'Amore if ((ddi_get32(handle, ®s->eb2csr) & EB2_NA_LOADED)) {
39588447a05SGarrett D'Amore return;
39688447a05SGarrett D'Amore }
39788447a05SGarrett D'Amore
39888447a05SGarrett D'Amore /*
39988447a05SGarrett D'Amore * For eb2 we first program the Next Byte Count Register.
40088447a05SGarrett D'Amore */
401*68c47f65SGarrett D'Amore ddi_put32(handle, ®s->eb2bcr, CS4231_FRAGSZ);
40288447a05SGarrett D'Amore
40388447a05SGarrett D'Amore /* now program the Next Address Register */
404*68c47f65SGarrett D'Amore ddi_put32(handle, ®s->eb2acr,
405*68c47f65SGarrett D'Amore eng->ce_paddr + (CS4231_FRAGSZ * eng->ce_curidx));
406*68c47f65SGarrett D'Amore
407*68c47f65SGarrett D'Amore eng->ce_curidx++;
408*68c47f65SGarrett D'Amore eng->ce_curidx %= CS4231_NFRAGS;
409*68c47f65SGarrett D'Amore }
410*68c47f65SGarrett D'Amore
411*68c47f65SGarrett D'Amore /*
412*68c47f65SGarrett D'Amore * eb2_addr()
413*68c47f65SGarrett D'Amore *
414*68c47f65SGarrett D'Amore * Description:
415*68c47f65SGarrett D'Amore * This routine returns the current DMA address for the engine (the
416*68c47f65SGarrett D'Amore * next address being accessed).
417*68c47f65SGarrett D'Amore *
418*68c47f65SGarrett D'Amore * Arguments:
419*68c47f65SGarrett D'Amore * CS_engine_t *eng The engine
420*68c47f65SGarrett D'Amore *
421*68c47f65SGarrett D'Amore * Returns:
422*68c47f65SGarrett D'Amore * Physical DMA address for current transfer.
423*68c47f65SGarrett D'Amore */
424*68c47f65SGarrett D'Amore static uint32_t
eb2_addr(CS_engine_t * eng)425*68c47f65SGarrett D'Amore eb2_addr(CS_engine_t *eng)
426*68c47f65SGarrett D'Amore {
427*68c47f65SGarrett D'Amore ddi_acc_handle_t handle = eng->ce_regsh;
428*68c47f65SGarrett D'Amore cs4231_eb2regs_t *regs = eng->ce_eb2regs;
42988447a05SGarrett D'Amore
430*68c47f65SGarrett D'Amore return (ddi_get32(handle, ®s->eb2acr));
43188447a05SGarrett D'Amore }
432