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 APC DMA controller. The APC is an SBus
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 apc_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 0x0000000000000fffLL, /* DMA counter register */
4788447a05SGarrett D'Amore 0x0000000000000001LL, /* DMA address alignment */
4888447a05SGarrett D'Amore 0x00000014, /* 4 and 16 byte burst sizes */
4988447a05SGarrett D'Amore 0x00000001, /* min effective DMA size */
5088447a05SGarrett D'Amore 0x0000000000000fffLL, /* 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 acc_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 /*
6488447a05SGarrett D'Amore * DMA ops vector functions
6588447a05SGarrett D'Amore */
6688447a05SGarrett D'Amore static int apc_map_regs(CS_state_t *);
6788447a05SGarrett D'Amore static void apc_unmap_regs(CS_state_t *);
6888447a05SGarrett D'Amore static void apc_reset(CS_state_t *);
6988447a05SGarrett D'Amore static int apc_start_engine(CS_engine_t *);
7088447a05SGarrett D'Amore static void apc_stop_engine(CS_engine_t *);
7188447a05SGarrett D'Amore static void apc_power(CS_state_t *, int);
72*68c47f65SGarrett D'Amore static void apc_reload(CS_engine_t *);
73*68c47f65SGarrett D'Amore static uint32_t apc_addr(CS_engine_t *);
7488447a05SGarrett D'Amore
7588447a05SGarrett D'Amore cs4231_dma_ops_t cs4231_apcdma_ops = {
7688447a05SGarrett D'Amore "APC DMA controller",
7788447a05SGarrett D'Amore &apc_dma_attr,
7888447a05SGarrett D'Amore apc_map_regs,
7988447a05SGarrett D'Amore apc_unmap_regs,
8088447a05SGarrett D'Amore apc_reset,
8188447a05SGarrett D'Amore apc_start_engine,
8288447a05SGarrett D'Amore apc_stop_engine,
8388447a05SGarrett D'Amore apc_power,
84*68c47f65SGarrett D'Amore apc_reload,
85*68c47f65SGarrett D'Amore apc_addr,
8688447a05SGarrett D'Amore };
8788447a05SGarrett D'Amore
8888447a05SGarrett D'Amore /*
8988447a05SGarrett D'Amore * apc_map_regs()
9088447a05SGarrett D'Amore *
9188447a05SGarrett D'Amore * Description:
9288447a05SGarrett D'Amore * This routine allocates the DMA handles and the memory for the
9388447a05SGarrett D'Amore * DMA engines to use. It then binds each of the buffers to its
9488447a05SGarrett D'Amore * respective handle, getting a DMA cookie. Finally, the registers
9588447a05SGarrett D'Amore * are mapped in.
9688447a05SGarrett D'Amore *
9788447a05SGarrett D'Amore * NOTE: All of the ddi_dma_... routines sleep if they cannot get
9888447a05SGarrett D'Amore * memory. This means these calls will almost always succeed.
9988447a05SGarrett D'Amore *
10088447a05SGarrett D'Amore * Arguments:
10188447a05SGarrett D'Amore * CS_state_t *state The device's state structure
10288447a05SGarrett D'Amore *
10388447a05SGarrett D'Amore * Returns:
10488447a05SGarrett D'Amore * AUDIO_SUCCESS Registers successfully mapped
10588447a05SGarrett D'Amore * AUDIO_FAILURE Registers not successfully mapped
10688447a05SGarrett D'Amore */
10788447a05SGarrett D'Amore static int
apc_map_regs(CS_state_t * state)10888447a05SGarrett D'Amore apc_map_regs(CS_state_t *state)
10988447a05SGarrett D'Amore {
11088447a05SGarrett D'Amore ddi_acc_handle_t *handle = &APC_HANDLE;
11188447a05SGarrett D'Amore dev_info_t *dip = state->cs_dip;
11288447a05SGarrett D'Amore
11388447a05SGarrett D'Amore /* map in the registers, getting a handle */
11488447a05SGarrett D'Amore if (ddi_regs_map_setup(dip, 0, (caddr_t *)&state->cs_regs, 0,
11588447a05SGarrett D'Amore sizeof (cs4231_regs_t), &acc_attr, handle) != DDI_SUCCESS) {
11688447a05SGarrett D'Amore audio_dev_warn(state->cs_adev, "ddi_regs_map_setup() failed");
11788447a05SGarrett D'Amore return (DDI_FAILURE);
11888447a05SGarrett D'Amore }
11988447a05SGarrett D'Amore
12088447a05SGarrett D'Amore /* clear the CSR so we have all interrupts disabled */
12188447a05SGarrett D'Amore ddi_put32(*handle, &APC_DMACSR, APC_CLEAR_RESET_VALUE);
12288447a05SGarrett D'Amore
12388447a05SGarrett D'Amore return (DDI_SUCCESS);
12488447a05SGarrett D'Amore } /* apc_map_regs() */
12588447a05SGarrett D'Amore
12688447a05SGarrett D'Amore /*
12788447a05SGarrett D'Amore * apc_unmap_regs()
12888447a05SGarrett D'Amore *
12988447a05SGarrett D'Amore * Description:
13088447a05SGarrett D'Amore * This routine unmaps the Codec's and DMA engine's registers.
13188447a05SGarrett D'Amore * It must be idempotent.
13288447a05SGarrett D'Amore *
13388447a05SGarrett D'Amore * Arguments:
13488447a05SGarrett D'Amore * CS_state_t *state The device's state structure
13588447a05SGarrett D'Amore *
13688447a05SGarrett D'Amore * Returns:
13788447a05SGarrett D'Amore * void
13888447a05SGarrett D'Amore */
13988447a05SGarrett D'Amore static void
apc_unmap_regs(CS_state_t * state)14088447a05SGarrett D'Amore apc_unmap_regs(CS_state_t *state)
14188447a05SGarrett D'Amore {
14288447a05SGarrett D'Amore if (APC_HANDLE)
14388447a05SGarrett D'Amore ddi_regs_map_free(&APC_HANDLE);
14488447a05SGarrett D'Amore
14588447a05SGarrett D'Amore } /* apc_unmap_regs() */
14688447a05SGarrett D'Amore
14788447a05SGarrett D'Amore /*
14888447a05SGarrett D'Amore * apc_reset()
14988447a05SGarrett D'Amore *
15088447a05SGarrett D'Amore * Description:
15188447a05SGarrett D'Amore * Reset both the play and record DMA engines. The engines are left
15288447a05SGarrett D'Amore * with interrupts and the DMA engine disabled.
15388447a05SGarrett D'Amore *
15488447a05SGarrett D'Amore * Arguments:
15588447a05SGarrett D'Amore * dev_info_t *dip Pointer to the device's devinfo structure
15688447a05SGarrett D'Amore * CS_state_t *state The device's state structure
15788447a05SGarrett D'Amore *
15888447a05SGarrett D'Amore * Returns:
15988447a05SGarrett D'Amore * void
16088447a05SGarrett D'Amore */
16188447a05SGarrett D'Amore static void
apc_reset(CS_state_t * state)16288447a05SGarrett D'Amore apc_reset(CS_state_t *state)
16388447a05SGarrett D'Amore {
16488447a05SGarrett D'Amore ddi_acc_handle_t handle = APC_HANDLE;
16588447a05SGarrett D'Amore
16688447a05SGarrett D'Amore /*
16788447a05SGarrett D'Amore * The APC has a bug where the reset is not done
16888447a05SGarrett D'Amore * until you do the next pio to the APC. This
16988447a05SGarrett D'Amore * next write to the CSR causes the posted reset to
17088447a05SGarrett D'Amore * happen.
17188447a05SGarrett D'Amore */
17288447a05SGarrett D'Amore
17388447a05SGarrett D'Amore ddi_put32(handle, &APC_DMACSR, APC_RESET);
17488447a05SGarrett D'Amore ddi_put32(handle, &APC_DMACSR, APC_CLEAR_RESET_VALUE);
17588447a05SGarrett D'Amore
17688447a05SGarrett D'Amore } /* apc_reset() */
17788447a05SGarrett D'Amore
17888447a05SGarrett D'Amore /*
17988447a05SGarrett D'Amore * apc_start_engine()
18088447a05SGarrett D'Amore *
18188447a05SGarrett D'Amore * Description:
18288447a05SGarrett D'Amore * This routine starts the DMA engine.
18388447a05SGarrett D'Amore *
18488447a05SGarrett D'Amore * For hard starts the DMA engine is started by programming the
18588447a05SGarrett D'Amore * Next Virtual Address and then the Next Counter twice, and
18688447a05SGarrett D'Amore * finally enabling the DMA engine.
18788447a05SGarrett D'Amore *
18888447a05SGarrett D'Amore * NOTE: The state structure must be locked before this routine is called.
18988447a05SGarrett D'Amore *
19088447a05SGarrett D'Amore * CAUTION: ?!? This routine doesn't start the Codec because the first
19188447a05SGarrett D'Amore * interrupt causes a recursive mutex_enter.
19288447a05SGarrett D'Amore *
19388447a05SGarrett D'Amore * Arguments:
19488447a05SGarrett D'Amore * CS_engine_t *eng The engine to start
19588447a05SGarrett D'Amore *
19688447a05SGarrett D'Amore * Returns:
19788447a05SGarrett D'Amore * DDI_SUCCESS The DMA engine was started
19888447a05SGarrett D'Amore * DDI_FAILURE The DMA engine was not started
19988447a05SGarrett D'Amore */
20088447a05SGarrett D'Amore static int
apc_start_engine(CS_engine_t * eng)20188447a05SGarrett D'Amore apc_start_engine(CS_engine_t *eng)
20288447a05SGarrett D'Amore {
20388447a05SGarrett D'Amore CS_state_t *state = eng->ce_state;
20488447a05SGarrett D'Amore ddi_acc_handle_t handle = APC_HANDLE;
20588447a05SGarrett D'Amore uint32_t csr;
20688447a05SGarrett D'Amore uint32_t enable;
20788447a05SGarrett D'Amore uint32_t dirty;
20888447a05SGarrett D'Amore int x;
20988447a05SGarrett D'Amore
21088447a05SGarrett D'Amore ASSERT(mutex_owned(&state->cs_lock));
21188447a05SGarrett D'Amore
21288447a05SGarrett D'Amore if (eng->ce_num == CS4231_PLAY) {
213*68c47f65SGarrett D'Amore enable = APC_PDMA_GO;
21488447a05SGarrett D'Amore dirty = APC_PD;
21588447a05SGarrett D'Amore } else {
216*68c47f65SGarrett D'Amore enable = APC_CDMA_GO;
21788447a05SGarrett D'Amore dirty = APC_CD;
21888447a05SGarrett D'Amore }
21988447a05SGarrett D'Amore
22088447a05SGarrett D'Amore /* make sure it's okay to program the Next Address/Count registers */
22188447a05SGarrett D'Amore csr = ddi_get32(handle, &APC_DMACSR);
22288447a05SGarrett D'Amore for (x = 0; !(csr & dirty) && x < CS4231_TIMEOUT; x++) {
22388447a05SGarrett D'Amore drv_usecwait(1); /* no reason to beat on the bus */
22488447a05SGarrett D'Amore csr = ddi_get32(handle, &APC_DMACSR);
22588447a05SGarrett D'Amore }
22688447a05SGarrett D'Amore if (x >= CS4231_TIMEOUT) {
22788447a05SGarrett D'Amore audio_dev_warn(state->cs_adev,
22888447a05SGarrett D'Amore "timeout waiting for engine, not started!");
22988447a05SGarrett D'Amore return (DDI_FAILURE);
23088447a05SGarrett D'Amore }
23188447a05SGarrett D'Amore
23288447a05SGarrett D'Amore /*
23388447a05SGarrett D'Amore * Program the first fragment.
23488447a05SGarrett D'Amore */
235*68c47f65SGarrett D'Amore apc_reload(eng);
23688447a05SGarrett D'Amore
23788447a05SGarrett D'Amore /*
23888447a05SGarrett D'Amore * Start the DMA engine, including interrupts.
23988447a05SGarrett D'Amore */
24088447a05SGarrett D'Amore OR_SET_WORD(handle, &APC_DMACSR, enable);
24188447a05SGarrett D'Amore
24288447a05SGarrett D'Amore /*
243*68c47f65SGarrett D'Amore * Program the double buffering.
24488447a05SGarrett D'Amore */
245*68c47f65SGarrett D'Amore apc_reload(eng);
24688447a05SGarrett D'Amore
24788447a05SGarrett D'Amore return (DDI_SUCCESS);
24888447a05SGarrett D'Amore }
24988447a05SGarrett D'Amore
25088447a05SGarrett D'Amore /*
25188447a05SGarrett D'Amore * apc_stop_engine()
25288447a05SGarrett D'Amore *
25388447a05SGarrett D'Amore * Description:
25488447a05SGarrett D'Amore * This routine stops the engine.
25588447a05SGarrett D'Amore *
25688447a05SGarrett D'Amore * The DMA engine is stopped by using the CAP_ABORT bit.
25788447a05SGarrett D'Amore *
25888447a05SGarrett D'Amore * NOTE: The state structure must be locked before this routine is called.
25988447a05SGarrett D'Amore *
26088447a05SGarrett D'Amore * Arguments:
26188447a05SGarrett D'Amore * CS_engine_t *eng The engine to sotp
26288447a05SGarrett D'Amore *
26388447a05SGarrett D'Amore * Returns:
26488447a05SGarrett D'Amore * void
26588447a05SGarrett D'Amore */
26688447a05SGarrett D'Amore static void
apc_stop_engine(CS_engine_t * eng)26788447a05SGarrett D'Amore apc_stop_engine(CS_engine_t *eng)
26888447a05SGarrett D'Amore {
26988447a05SGarrett D'Amore CS_state_t *state = eng->ce_state;
27088447a05SGarrett D'Amore ddi_acc_handle_t handle = APC_HANDLE;
27188447a05SGarrett D'Amore uint32_t reg;
27288447a05SGarrett D'Amore uint32_t abort;
27388447a05SGarrett D'Amore uint32_t drainbit;
27488447a05SGarrett D'Amore uint32_t disable;
27588447a05SGarrett D'Amore
27688447a05SGarrett D'Amore ASSERT(mutex_owned(&state->cs_lock));
27788447a05SGarrett D'Amore
27888447a05SGarrett D'Amore if (eng->ce_num == CS4231_PLAY) {
27988447a05SGarrett D'Amore abort = APC_P_ABORT;
28088447a05SGarrett D'Amore drainbit = APC_PM;
28188447a05SGarrett D'Amore disable = APC_PLAY_DISABLE;
28288447a05SGarrett D'Amore } else {
28388447a05SGarrett D'Amore abort = APC_C_ABORT;
28488447a05SGarrett D'Amore drainbit = APC_CX;
28588447a05SGarrett D'Amore disable = APC_CAP_DISABLE;
28688447a05SGarrett D'Amore }
28788447a05SGarrett D'Amore
28888447a05SGarrett D'Amore /* first, abort the DMA engine */
28988447a05SGarrett D'Amore OR_SET_WORD(handle, &APC_DMACSR, abort);
29088447a05SGarrett D'Amore
29188447a05SGarrett D'Amore /* wait for the pipeline to empty */
29288447a05SGarrett D'Amore reg = ddi_get32(handle, &APC_DMACSR);
29388447a05SGarrett D'Amore for (int x = 0; (!(reg & drainbit)) && (x < CS4231_TIMEOUT); x++) {
29488447a05SGarrett D'Amore drv_usecwait(1); /* don't beat on bus */
29588447a05SGarrett D'Amore reg = ddi_get32(handle, &APC_DMACSR);
29688447a05SGarrett D'Amore }
29788447a05SGarrett D'Amore
29888447a05SGarrett D'Amore /* now clear the enable and abort bits */
29988447a05SGarrett D'Amore AND_SET_WORD(handle, &APC_DMACSR, ~(abort|disable));
30088447a05SGarrett D'Amore }
30188447a05SGarrett D'Amore
30288447a05SGarrett D'Amore
30388447a05SGarrett D'Amore /*
30488447a05SGarrett D'Amore * apc_power()
30588447a05SGarrett D'Amore *
30688447a05SGarrett D'Amore * Description:
30788447a05SGarrett D'Amore * This routine turns the Codec off by using the COD_PDWN bit in the
30888447a05SGarrett D'Amore * apc chip. To turn power on we have to reset the APC, which clears
30988447a05SGarrett D'Amore * the COD_PDWN bit. However, this is a settling bug in the APC which
31088447a05SGarrett D'Amore * requires the driver to delay quite a while before we may continue.
31188447a05SGarrett D'Amore * Since this is the first time this feature has actually been used
31288447a05SGarrett D'Amore * it isn't too surprising that it has some problems.
31388447a05SGarrett D'Amore *
31488447a05SGarrett D'Amore * NOTE: The state structure must be locked when this routine is called.
31588447a05SGarrett D'Amore *
31688447a05SGarrett D'Amore * Arguments:
31788447a05SGarrett D'Amore * CS_state_t *state Ptr to the device's state structure
31888447a05SGarrett D'Amore * int level Power level to set
31988447a05SGarrett D'Amore */
32088447a05SGarrett D'Amore static void
apc_power(CS_state_t * state,int level)32188447a05SGarrett D'Amore apc_power(CS_state_t *state, int level)
32288447a05SGarrett D'Amore {
32388447a05SGarrett D'Amore ddi_acc_handle_t handle = APC_HANDLE;
32488447a05SGarrett D'Amore
32588447a05SGarrett D'Amore if (level == CS4231_PWR_ON) { /* turn power on */
32688447a05SGarrett D'Amore AND_SET_WORD(handle, &APC_DMACSR, ~APC_COD_PDWN);
32788447a05SGarrett D'Amore OR_SET_WORD(handle, &APC_DMACSR, APC_RESET);
32888447a05SGarrett D'Amore AND_SET_WORD(handle, &APC_DMACSR, ~APC_RESET);
32988447a05SGarrett D'Amore
33088447a05SGarrett D'Amore /*
33188447a05SGarrett D'Amore * wait for state change,
33288447a05SGarrett D'Amore */
33388447a05SGarrett D'Amore delay(drv_usectohz(CS4231_300MS));
33488447a05SGarrett D'Amore } else { /* turn power off */
33588447a05SGarrett D'Amore ASSERT(level == CS4231_PWR_OFF);
33688447a05SGarrett D'Amore OR_SET_WORD(handle, &APC_DMACSR, APC_COD_PDWN);
33788447a05SGarrett D'Amore }
33888447a05SGarrett D'Amore
33988447a05SGarrett D'Amore } /* apc_power() */
34088447a05SGarrett D'Amore
34188447a05SGarrett D'Amore
34288447a05SGarrett D'Amore static void
apc_reload(CS_engine_t * eng)343*68c47f65SGarrett D'Amore apc_reload(CS_engine_t *eng)
34488447a05SGarrett D'Amore {
34588447a05SGarrett D'Amore CS_state_t *state = eng->ce_state;
34688447a05SGarrett D'Amore ddi_acc_handle_t handle = APC_HANDLE;
34788447a05SGarrett D'Amore uint32_t dirty;
34888447a05SGarrett D'Amore uint32_t *nva; /* next VA reg */
34988447a05SGarrett D'Amore uint32_t *nc; /* next count reg */
35088447a05SGarrett D'Amore
35188447a05SGarrett D'Amore if (eng->ce_num == CS4231_PLAY) {
35288447a05SGarrett D'Amore dirty = APC_PD;
35388447a05SGarrett D'Amore nva = &APC_DMAPNVA;
35488447a05SGarrett D'Amore nc = &APC_DMAPNC;
35588447a05SGarrett D'Amore } else {
35688447a05SGarrett D'Amore dirty = APC_CD;
35788447a05SGarrett D'Amore nva = &APC_DMACNVA;
35888447a05SGarrett D'Amore nc = &APC_DMACNC;
35988447a05SGarrett D'Amore }
36088447a05SGarrett D'Amore
36188447a05SGarrett D'Amore /* if we can't load another address, then don't */
36288447a05SGarrett D'Amore if ((ddi_get32(handle, &APC_DMACSR) & dirty) == 0) {
36388447a05SGarrett D'Amore return;
36488447a05SGarrett D'Amore }
36588447a05SGarrett D'Amore
36688447a05SGarrett D'Amore /* read the NVA, as per APC document */
36788447a05SGarrett D'Amore (void) ddi_get32(handle, nva);
36888447a05SGarrett D'Amore
36988447a05SGarrett D'Amore /* write the address of the next fragment */
370*68c47f65SGarrett D'Amore ddi_put32(handle, nva,
371*68c47f65SGarrett D'Amore eng->ce_paddr + (CS4231_FRAGSZ * eng->ce_curidx));
372*68c47f65SGarrett D'Amore eng->ce_curidx++;
373*68c47f65SGarrett D'Amore eng->ce_curidx %= CS4231_NFRAGS;
37488447a05SGarrett D'Amore
37588447a05SGarrett D'Amore /* now program the NC reg., which enables the state machine */
376*68c47f65SGarrett D'Amore ddi_put32(handle, nc, CS4231_FRAGSZ);
377*68c47f65SGarrett D'Amore }
37888447a05SGarrett D'Amore
379*68c47f65SGarrett D'Amore /*
380*68c47f65SGarrett D'Amore * apc_addr()
381*68c47f65SGarrett D'Amore *
382*68c47f65SGarrett D'Amore * Description:
383*68c47f65SGarrett D'Amore * This routine returns the current DMA address for the engine (the
384*68c47f65SGarrett D'Amore * next address being accessed).
385*68c47f65SGarrett D'Amore *
386*68c47f65SGarrett D'Amore * Arguments:
387*68c47f65SGarrett D'Amore * CS_engine_t *eng The engine
388*68c47f65SGarrett D'Amore *
389*68c47f65SGarrett D'Amore * Returns:
390*68c47f65SGarrett D'Amore * Physical DMA address for current transfer.
391*68c47f65SGarrett D'Amore */
392*68c47f65SGarrett D'Amore static uint32_t
apc_addr(CS_engine_t * eng)393*68c47f65SGarrett D'Amore apc_addr(CS_engine_t *eng)
394*68c47f65SGarrett D'Amore {
395*68c47f65SGarrett D'Amore CS_state_t *state = eng->ce_state;
396*68c47f65SGarrett D'Amore ddi_acc_handle_t handle = APC_HANDLE;
397*68c47f65SGarrett D'Amore uint32_t *va; /* VA reg */
398*68c47f65SGarrett D'Amore
399*68c47f65SGarrett D'Amore if (eng->ce_num == CS4231_PLAY) {
400*68c47f65SGarrett D'Amore va = &APC_DMAPVA;
401*68c47f65SGarrett D'Amore } else {
402*68c47f65SGarrett D'Amore va = &APC_DMACVA;
403*68c47f65SGarrett D'Amore }
404*68c47f65SGarrett D'Amore
405*68c47f65SGarrett D'Amore return (ddi_get32(handle, va));
40688447a05SGarrett D'Amore }
407