mirror of
https://github.com/alsa-project/alsa-tools.git
synced 2025-11-24 07:00:00 -05:00
552 lines
15 KiB
C
552 lines
15 KiB
C
/*
|
|
* EMU10k1 loader
|
|
*
|
|
* Copyright (c) 2003,2004 by Peter Zubaj
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <sys/ioctl.h>
|
|
#include <alsa/asoundlib.h>
|
|
#include <alsa/sound/emu10k1.h>
|
|
#include <stdint.h>
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include "bitops.h"
|
|
#include "ld10k1.h"
|
|
#include "ld10k1_driver.h"
|
|
#include "ld10k1_error.h"
|
|
#include "ld10k1_fnc.h"
|
|
#include "ld10k1_fnc_int.h"
|
|
|
|
//#define DEBUG_DRIVER 1
|
|
|
|
extern snd_hwdep_t *handle;
|
|
|
|
void ld10k1_syntetize_instr(int audigy, int op, int arg1, int arg2, int arg3, int arg4, unsigned int *out)
|
|
{
|
|
if (audigy) {
|
|
*out = ((arg3 & 0x7ff) << 12) | (arg4 & 0x7ff);
|
|
*(out + 1) = ((op & 0x0f) << 24) | ((arg1 & 0x7ff) << 12) | (arg2 & 0x7ff);
|
|
} else {
|
|
*out = ((arg3 & 0x3ff) << 10) | (arg4 & 0x3ff);
|
|
*(out + 1) = ((op & 0x0f) << 20) | ((arg1 & 0x3ff) << 10) | (arg2 & 0x3ff);
|
|
}
|
|
}
|
|
|
|
void ld10k1_init_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr);
|
|
void ld10k1_set_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, int reg);
|
|
void ld10k1_check_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, emu10k1_fx8010_code_t *code);
|
|
|
|
/* outputs what must be initialized on audigy */
|
|
static int audigy_must_init_output[] = {
|
|
0x68, 0,
|
|
0x69, 0,
|
|
0x6a, 0,
|
|
0x6b, 0,
|
|
0x6e, 0,
|
|
0x6f, 0,
|
|
-1};
|
|
|
|
#define LD10K1_SIGNATURE "LD10K1 ver. " VERSION " managed DSP code"
|
|
|
|
void ld10k1_free_code_struct(emu10k1_fx8010_code_t *code)
|
|
{
|
|
if (code->gpr_map)
|
|
free(code->gpr_map);
|
|
if (code->tram_data_map)
|
|
free(code->tram_data_map);
|
|
if (code->tram_addr_map)
|
|
free(code->tram_addr_map);
|
|
if (code->code)
|
|
free(code->code);
|
|
}
|
|
|
|
int ld10k1_alloc_code_struct(emu10k1_fx8010_code_t *code)
|
|
{
|
|
/* alloc code structure */
|
|
code->gpr_map = NULL;
|
|
code->tram_data_map = NULL;
|
|
code->tram_addr_map = NULL;
|
|
code->code = NULL;
|
|
|
|
code->gpr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x200);
|
|
if (!code->gpr_map)
|
|
goto err;
|
|
memset(code->gpr_map, 0, sizeof(uint32_t) * 0x200);
|
|
|
|
code->tram_data_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100);
|
|
if (!code->tram_data_map)
|
|
goto err;
|
|
memset(code->tram_data_map, 0, sizeof(uint32_t) * 0x100);
|
|
|
|
code->tram_addr_map = (uint32_t *)malloc(sizeof(uint32_t) * 0x100);
|
|
if (!code->tram_addr_map)
|
|
goto err;
|
|
memset(code->tram_addr_map, 0, sizeof(uint32_t) * 0x100);
|
|
|
|
code->code = (uint32_t *)malloc(sizeof(uint32_t) * 1024 * 2);
|
|
if (!code->code)
|
|
goto err;
|
|
memset(code->code, 0, sizeof(uint32_t) * 1024 * 2);
|
|
|
|
return 0;
|
|
err:
|
|
ld10k1_free_code_struct(code);
|
|
return LD10K1_ERR_NO_MEM;
|
|
}
|
|
|
|
int ld10k1_update_driver(ld10k1_dsp_mgr_t *dsp_mgr)
|
|
{
|
|
emu10k1_fx8010_code_t code;
|
|
emu10k1_fx8010_control_gpr_t *add_ctrl;
|
|
emu10k1_ctl_elem_id_t *del_ids;
|
|
|
|
ld10k1_ctl_list_item_t *item;
|
|
unsigned int i, j;
|
|
int max;
|
|
int modified;
|
|
unsigned int addr;
|
|
unsigned int vaddr;
|
|
unsigned int op;
|
|
unsigned int idx_offset;
|
|
unsigned int *iptr;
|
|
ld10k1_ctl_t gctl;
|
|
|
|
int err;
|
|
|
|
if ((err = ld10k1_alloc_code_struct(&code)) < 0)
|
|
return err;
|
|
|
|
/* new name */
|
|
strcpy(code.name, LD10K1_SIGNATURE);
|
|
|
|
for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
|
|
code.gpr_valid[i] = 0;
|
|
for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
|
|
code.tram_valid[i] = 0;
|
|
for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
|
|
code.code_valid[i] = 0;
|
|
|
|
/* registers */
|
|
for (i = 0; i < dsp_mgr->regs_max_count; i++)
|
|
if (dsp_mgr->regs[i].modified) {
|
|
set_bit(i, code.gpr_valid);
|
|
code.gpr_map[i] = dsp_mgr->regs[i].val;
|
|
}
|
|
|
|
/* tram addr + data */
|
|
for (j = 0; j < 2; j++) {
|
|
max = (j == 0 ? dsp_mgr->max_itram_hwacc : dsp_mgr->max_etram_hwacc);
|
|
for (i = 0; i < max; i++) {
|
|
modified = (j == 0 ? dsp_mgr->itram_hwacc[i].modified : dsp_mgr->etram_hwacc[i].modified);
|
|
if (modified) {
|
|
addr = (j == 0 ? dsp_mgr->itram_hwacc[i].addr_val : dsp_mgr->etram_hwacc[i].addr_val);
|
|
vaddr = addr & 0xFFFFF;
|
|
idx_offset = (j == 0 ? 0 : dsp_mgr->max_itram_hwacc);
|
|
op = (j == 0 ? dsp_mgr->itram_hwacc[i].op : dsp_mgr->etram_hwacc[i].op);
|
|
|
|
set_bit(i + idx_offset, code.tram_valid);
|
|
switch(op) {
|
|
case TRAM_OP_READ:
|
|
if (dsp_mgr->audigy)
|
|
vaddr = vaddr | 0x2 << 20;
|
|
else
|
|
vaddr = vaddr | TANKMEMADDRREG_READ | TANKMEMADDRREG_ALIGN;
|
|
break;
|
|
case TRAM_OP_WRITE:
|
|
if (dsp_mgr->audigy)
|
|
vaddr = vaddr | 0x6 << 20;
|
|
else
|
|
vaddr = vaddr | TANKMEMADDRREG_WRITE | TANKMEMADDRREG_ALIGN;
|
|
break;
|
|
case TRAM_OP_NULL:
|
|
default:
|
|
vaddr = 0;
|
|
break;
|
|
}
|
|
|
|
code.tram_addr_map[i + idx_offset] = vaddr;
|
|
code.tram_data_map[i + idx_offset] = (j == 0 ? dsp_mgr->itram_hwacc[i].data_val : dsp_mgr->etram_hwacc[i].data_val);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* controls to add */
|
|
if (dsp_mgr->add_list_count > 0) {
|
|
add_ctrl = calloc(dsp_mgr->add_list_count,
|
|
sizeof(emu10k1_fx8010_control_gpr_t));
|
|
if (!add_ctrl)
|
|
return LD10K1_ERR_NO_MEM;
|
|
for (i = 0, item = dsp_mgr->add_ctl_list; item != NULL; item = item->next, i++) {
|
|
strcpy((char *)add_ctrl[i].id.name, item->ctl.name);
|
|
add_ctrl[i].id.iface = EMU10K1_CTL_ELEM_IFACE_MIXER;
|
|
add_ctrl[i].id.index = item->ctl.index;
|
|
add_ctrl[i].vcount = item->ctl.vcount;
|
|
add_ctrl[i].count = item->ctl.count;
|
|
for (j = 0; j < 32; j++) {
|
|
add_ctrl[i].gpr[j] = item->ctl.gpr_idx[j];
|
|
add_ctrl[i].value[j] = item->ctl.value[j];
|
|
}
|
|
add_ctrl[i].min = item->ctl.min;
|
|
add_ctrl[i].max = item->ctl.max;
|
|
add_ctrl[i].translation = item->ctl.translation;
|
|
}
|
|
} else
|
|
add_ctrl = NULL;
|
|
|
|
code.gpr_add_control_count = dsp_mgr->add_list_count;
|
|
code.gpr_add_controls = add_ctrl;
|
|
|
|
/* controls to del */
|
|
if (dsp_mgr->del_list_count > 0) {
|
|
del_ids = calloc(dsp_mgr->del_list_count,
|
|
sizeof(emu10k1_ctl_elem_id_t));
|
|
if (!del_ids)
|
|
return LD10K1_ERR_NO_MEM;
|
|
for (i = 0, item = dsp_mgr->del_ctl_list; item != NULL; item = item->next, i++) {
|
|
strcpy((char *)del_ids[i].name, item->ctl.name);
|
|
del_ids[i].iface = EMU10K1_CTL_ELEM_IFACE_MIXER;
|
|
del_ids[i].index = item->ctl.index;
|
|
}
|
|
} else
|
|
del_ids = NULL;
|
|
|
|
code.gpr_del_control_count = dsp_mgr->del_list_count;
|
|
code.gpr_del_controls = del_ids;
|
|
|
|
code.gpr_list_control_count = 0;
|
|
|
|
for (iptr = code.code, i = 0; i < dsp_mgr->instr_count; i++, iptr += 2) {
|
|
if (dsp_mgr->instr[i].modified) {
|
|
set_bit(i, code.code_valid);
|
|
if (dsp_mgr->instr[i].used) {
|
|
if (dsp_mgr->audigy) {
|
|
ld10k1_syntetize_instr(dsp_mgr->audigy,
|
|
dsp_mgr->instr[i].op_code,
|
|
dsp_mgr->instr[i].arg[0], dsp_mgr->instr[i].arg[1], dsp_mgr->instr[i].arg[2], dsp_mgr->instr[i].arg[3], iptr);
|
|
} else {
|
|
if (i < 0x200) {
|
|
ld10k1_syntetize_instr(dsp_mgr->audigy,
|
|
dsp_mgr->instr[i].op_code,
|
|
dsp_mgr->instr[i].arg[0], dsp_mgr->instr[i].arg[1], dsp_mgr->instr[i].arg[2], dsp_mgr->instr[i].arg[3], iptr);
|
|
}
|
|
}
|
|
} else {
|
|
if (dsp_mgr->audigy) {
|
|
ld10k1_syntetize_instr(dsp_mgr->audigy,
|
|
0x0f,
|
|
0xc0, 0xc0, 0xcf, 0xc0, iptr);
|
|
} else {
|
|
if (i < 0x200) {
|
|
ld10k1_syntetize_instr(dsp_mgr->audigy,
|
|
0x06,
|
|
0x40, 0x40, 0x40, 0x40, iptr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* check initialization of i2s outputs on audigy */
|
|
if (dsp_mgr->audigy)
|
|
ld10k1_check_must_init_output(dsp_mgr, &code);
|
|
|
|
|
|
#ifndef DEBUG_DRIVER
|
|
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) {
|
|
error("unable to poke code");
|
|
ld10k1_free_code_struct(&code);
|
|
if (add_ctrl)
|
|
free(add_ctrl);
|
|
if (del_ids)
|
|
free(del_ids);
|
|
return LD10K1_ERR_DRIVER_CODE_POKE;
|
|
}
|
|
#endif
|
|
|
|
/* update state */
|
|
for (item = dsp_mgr->del_ctl_list; item != NULL; item = item->next) {
|
|
strcpy(gctl.name, item->ctl.name);
|
|
ld10k1_del_control_from_list(&(dsp_mgr->ctl_list), &(dsp_mgr->ctl_list_count), &gctl);
|
|
}
|
|
|
|
ld10k1_del_all_controls_from_list(&(dsp_mgr->del_ctl_list), &dsp_mgr->del_list_count);
|
|
|
|
for (item = dsp_mgr->add_ctl_list; item != NULL; item = item->next)
|
|
ld10k1_add_control_to_list(&(dsp_mgr->ctl_list), &(dsp_mgr->ctl_list_count), &(item->ctl));
|
|
|
|
ld10k1_del_all_controls_from_list(&(dsp_mgr->add_ctl_list), &dsp_mgr->add_list_count);
|
|
|
|
for (i = 0; i < dsp_mgr->regs_max_count; i++)
|
|
dsp_mgr->regs[i].modified = 0;
|
|
|
|
for (i = 0; i < dsp_mgr->instr_count; i++)
|
|
dsp_mgr->instr[i].modified = 0;
|
|
|
|
for (j = 0; j < 2; j++) {
|
|
max = (j == 0 ? dsp_mgr->max_itram_hwacc : dsp_mgr->max_etram_hwacc);
|
|
for (i = 0; i < max; i++) {
|
|
if (j == 0)
|
|
dsp_mgr->itram_hwacc[i].modified = 0;
|
|
else
|
|
dsp_mgr->etram_hwacc[i].modified = 0;
|
|
}
|
|
}
|
|
|
|
ld10k1_free_code_struct(&code);
|
|
|
|
if (add_ctrl)
|
|
free(add_ctrl);
|
|
if (del_ids)
|
|
free(del_ids);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int ld10k1_init_driver(ld10k1_dsp_mgr_t *dsp_mgr, int tram_size)
|
|
{
|
|
emu10k1_fx8010_info_t info;
|
|
int i;
|
|
emu10k1_fx8010_code_t code;
|
|
emu10k1_fx8010_control_gpr_t *ctrl;
|
|
emu10k1_ctl_elem_id_t *ids;
|
|
emu10k1_fx8010_pcm_t ipcm;
|
|
|
|
unsigned int *iptr;
|
|
|
|
int err;
|
|
|
|
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_PVERSION, &i) < 0) {
|
|
error("Cannot get emu10k1 driver version, likely an old driver is running.");
|
|
return LD10K1_ERR_DRIVER_INFO;
|
|
}
|
|
|
|
if ((err = ld10k1_alloc_code_struct(&code)) < 0)
|
|
return err;
|
|
|
|
/* setup tram size */
|
|
if (tram_size >= 0 && snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_TRAM_SETUP, &tram_size) < 0) {
|
|
error("unable to setup tram");
|
|
if (dsp_mgr->audigy)
|
|
error("You are probably user of audigy, audigy 2 and you not aplyed patch to enable tram");
|
|
/* this is not fatal, but do not use tram */
|
|
dsp_mgr->i_tram.size = 0;
|
|
dsp_mgr->e_tram.size = 0;
|
|
} else {
|
|
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_INFO, &info) < 0) {
|
|
error("unable to get info ");
|
|
ld10k1_free_code_struct(&code);
|
|
return LD10K1_ERR_DRIVER_INFO;
|
|
}
|
|
|
|
dsp_mgr->i_tram.size = info.internal_tram_size;
|
|
dsp_mgr->e_tram.size = info.external_tram_size;
|
|
}
|
|
|
|
/* get count of controls */
|
|
code.gpr_list_control_count = 0;
|
|
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) {
|
|
error("unable to peek code");
|
|
ld10k1_free_code_struct(&code);
|
|
return LD10K1_ERR_DRIVER_CODE_PEEK;
|
|
}
|
|
|
|
ctrl = calloc(code.gpr_list_control_total,
|
|
sizeof(emu10k1_fx8010_control_gpr_t));
|
|
if (!ctrl) {
|
|
ld10k1_free_code_struct(&code);
|
|
return LD10K1_ERR_NO_MEM;
|
|
}
|
|
|
|
code.gpr_list_control_count = code.gpr_list_control_total;
|
|
code.gpr_list_controls = ctrl;
|
|
|
|
for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
|
|
code.gpr_valid[i] = 0x0;
|
|
for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
|
|
code.tram_valid[i] = 0x0;
|
|
for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
|
|
code.code_valid[i] = 0x0;;
|
|
|
|
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_PEEK, &code) < 0) {
|
|
error("unable to peek code");
|
|
ld10k1_free_code_struct(&code);
|
|
free(ctrl);
|
|
return LD10K1_ERR_DRIVER_CODE_PEEK;
|
|
}
|
|
|
|
|
|
|
|
/* new name */
|
|
strcpy(code.name, LD10K1_SIGNATURE);
|
|
for (i = 0; i < sizeof(code.gpr_valid) / sizeof(unsigned long); i++)
|
|
code.gpr_valid[i] = ~0;
|
|
|
|
for (i = 0; i < sizeof(code.gpr_valid) * 8; i++) {
|
|
code.gpr_map[i] = 0;
|
|
}
|
|
|
|
ids = calloc(code.gpr_list_control_total,
|
|
sizeof(emu10k1_ctl_elem_id_t));
|
|
if (!ids) {
|
|
ld10k1_free_code_struct(&code);
|
|
free(ctrl);
|
|
return LD10K1_ERR_NO_MEM;
|
|
}
|
|
|
|
code.gpr_del_control_count = code.gpr_list_control_total;
|
|
if (code.gpr_del_control_count) {
|
|
for (i = 0; i < code.gpr_del_control_count; i++) {
|
|
memcpy(&(ids[i]), &(ctrl[i].id), sizeof(emu10k1_ctl_elem_id_t));
|
|
}
|
|
}
|
|
|
|
free(ctrl);
|
|
|
|
code.gpr_del_controls = ids;
|
|
code.gpr_list_control_count = 0;
|
|
code.gpr_add_control_count = 0;
|
|
code.gpr_list_control_count = 0;
|
|
|
|
for (i = 0; i < sizeof(code.tram_valid) / sizeof(unsigned long); i++)
|
|
code.tram_valid[i] = ~0;
|
|
for (i = 0; i < sizeof(code.code_valid) / sizeof(unsigned long); i++)
|
|
code.code_valid[i] = ~0;
|
|
|
|
for (i = 0; i < sizeof(code.tram_valid) * 8; i++) {
|
|
code.tram_addr_map[i] = 0;
|
|
code.tram_data_map[i] = 0;
|
|
}
|
|
|
|
for (iptr = code.code, i = 0; i < sizeof(code.code_valid) * 8; i++, iptr += 2)
|
|
if (dsp_mgr->audigy) {
|
|
ld10k1_syntetize_instr(dsp_mgr->audigy,
|
|
0x0f,
|
|
0xc0, 0xc0, 0xcf, 0xc0, iptr);
|
|
} else {
|
|
ld10k1_syntetize_instr(dsp_mgr->audigy,
|
|
0x06,
|
|
0x40, 0x40, 0x40, 0x40, iptr);
|
|
}
|
|
|
|
/* initialize i2s outputs on audigy */
|
|
if (dsp_mgr->audigy) {
|
|
for (iptr = code.code, i = 0; audigy_must_init_output[i] > 0; i += 2, iptr += 2)
|
|
ld10k1_syntetize_instr(dsp_mgr->audigy, 0x00,
|
|
audigy_must_init_output[i], 0xc0, 0xc0, 0xc0, iptr);
|
|
}
|
|
|
|
#ifndef DEBUG_DRIVER
|
|
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_CODE_POKE, &code) < 0) {
|
|
error("unable to poke code");
|
|
ld10k1_free_code_struct(&code);
|
|
free(ids);
|
|
return LD10K1_ERR_DRIVER_CODE_POKE;
|
|
}
|
|
#endif
|
|
|
|
free(ids);
|
|
|
|
/* delete tram pcm dsp part */
|
|
if (!dsp_mgr->audigy) {
|
|
for (i = 0; i < EMU10K1_FX8010_PCM_COUNT; i++) {
|
|
ipcm.substream = i;
|
|
ipcm.channels = 0;
|
|
#ifndef DEBUG_DRIVER
|
|
if (snd_hwdep_ioctl(handle, SNDRV_EMU10K1_IOCTL_PCM_POKE, &ipcm) < 0) {
|
|
error("unable to poke code");
|
|
ld10k1_free_code_struct(&code);
|
|
return LD10K1_ERR_DRIVER_PCM_POKE;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
ld10k1_free_code_struct(&code);
|
|
return 0;
|
|
}
|
|
|
|
void ld10k1_init_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr)
|
|
{
|
|
int i;
|
|
if (dsp_mgr->audigy) {
|
|
for (i = 0; audigy_must_init_output[i] > 0; i += 2)
|
|
audigy_must_init_output[i + 1] = 1;
|
|
}
|
|
}
|
|
|
|
void ld10k1_set_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, int reg)
|
|
{
|
|
int i ;
|
|
if (dsp_mgr->audigy) {
|
|
for (i = 0; audigy_must_init_output[i] > 0; i += 2) {
|
|
if (audigy_must_init_output[i] == reg) {
|
|
audigy_must_init_output[i + 1] = 0;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ld10k1_check_must_init_output(ld10k1_dsp_mgr_t *dsp_mgr, emu10k1_fx8010_code_t *code)
|
|
{
|
|
int j;
|
|
|
|
ld10k1_init_must_init_output(dsp_mgr);
|
|
for (j = 0; j < dsp_mgr->instr_count; j++) {
|
|
if (dsp_mgr->instr[j].used)
|
|
ld10k1_set_must_init_output(dsp_mgr, dsp_mgr->instr[j].arg[0]);
|
|
}
|
|
|
|
int i;
|
|
int l;
|
|
int ioffset = dsp_mgr->instr_count - 1;
|
|
if (dsp_mgr->audigy) {
|
|
for (i = 0; audigy_must_init_output[i] > 0; i += 2) {
|
|
if (audigy_must_init_output[i + 1]) {
|
|
/* find free instruction slot */
|
|
for (;ioffset >= 0; ioffset--) {
|
|
if (!dsp_mgr->instr[ioffset].used) {
|
|
ld10k1_instr_t *instr = &(dsp_mgr->instr[ioffset]);
|
|
ld10k1_syntetize_instr(dsp_mgr->audigy,
|
|
0x0,
|
|
audigy_must_init_output[i], 0xc0, 0xc0, 0xc0,
|
|
code->code + ioffset * 2);
|
|
instr->op_code = 0;
|
|
instr->arg[0] = audigy_must_init_output[i];
|
|
for (l = 1; l < 4; l++)
|
|
instr->arg[l] = 0xc0;
|
|
set_bit(ioffset, code->code_valid);
|
|
dsp_mgr->instr[ioffset].used = 1;
|
|
ioffset--;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ioffset < 0)
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|