static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) { int err; DE_INIT(("init_hw() - Layla20\n")); snd_assert((subdevice_id & 0xfff0) == LAYLA20, return -ENODEV); if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); return err; } chip->device_id = device_id; chip->subdevice_id = subdevice_id; chip->bad_board = TRUE; chip->has_midi = TRUE; chip->dsp_code_to_load = &card_fw[FW_LAYLA20_DSP]; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER; chip->output_clock_types = ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER; if ((err = load_firmware(chip)) < 0) return err; chip->bad_board = FALSE; if ((err = init_line_levels(chip)) < 0) return err; err = set_professional_spdif(chip, TRUE); DE_INIT(("init_hw done\n")); return err; }
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) { int err; DE_INIT(("init_hw() - Gina20\n")); if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA20)) return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); return err; } chip->device_id = device_id; chip->subdevice_id = subdevice_id; chip->bad_board = TRUE; chip->dsp_code_to_load = FW_GINA20_DSP; chip->spdif_status = GD_SPDIF_STATUS_UNDEF; chip->clock_state = GD_CLOCK_UNDEF; /* Since this card has no ASIC, mark it as loaded so everything works OK */ chip->asic_loaded = TRUE; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF; if ((err = load_firmware(chip)) < 0) return err; chip->bad_board = FALSE; DE_INIT(("init_hw done\n")); return err; }
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) { int err; DE_INIT(("init_hw() - Indigo DJ\n")); if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO_DJ)) return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); return err; } chip->device_id = device_id; chip->subdevice_id = subdevice_id; chip->bad_board = TRUE; chip->dsp_code_to_load = FW_INDIGO_DJ_DSP; /* */ chip->asic_loaded = TRUE; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; if ((err = load_firmware(chip)) < 0) return err; chip->bad_board = FALSE; DE_INIT(("init_hw done\n")); return err; }
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) { int err; DE_INIT(("init_hw() - Darla24\n")); if (snd_BUG_ON((subdevice_id & 0xfff0) != DARLA24)) return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); return err; } chip->device_id = device_id; chip->subdevice_id = subdevice_id; chip->bad_board = TRUE; chip->dsp_code_to_load = FW_DARLA24_DSP; /* Since this card has no ASIC, mark it as loaded so everything works OK */ chip->asic_loaded = TRUE; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_ESYNC; if ((err = load_firmware(chip)) < 0) return err; chip->bad_board = FALSE; DE_INIT(("init_hw done\n")); return err; }
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) { int err; DE_INIT(("init_hw() - Layla20\n")); if (snd_BUG_ON((subdevice_id & 0xfff0) != LAYLA20)) return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); return err; } chip->device_id = device_id; chip->subdevice_id = subdevice_id; chip->bad_board = TRUE; chip->has_midi = TRUE; chip->dsp_code_to_load = FW_LAYLA20_DSP; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER; chip->output_clock_types = ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_SUPER; if ((err = load_firmware(chip)) < 0) return err; chip->bad_board = FALSE; DE_INIT(("init_hw done\n")); return err; }
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) { int err; DE_INIT(("init_hw() - Mona\n")); if (snd_BUG_ON((subdevice_id & 0xfff0) != MONA)) return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); return err; } chip->device_id = device_id; chip->subdevice_id = subdevice_id; chip->bad_board = TRUE; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | ECHO_CLOCK_BIT_WORD | ECHO_CLOCK_BIT_ADAT; chip->digital_modes = ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | ECHOCAPS_HAS_DIGITAL_MODE_ADAT; /* Mona comes in both '301 and '361 flavors */ if (chip->device_id == DEVICE_ID_56361) chip->dsp_code_to_load = &card_fw[FW_MONA_361_DSP]; else chip->dsp_code_to_load = &card_fw[FW_MONA_301_DSP]; chip->digital_mode = DIGITAL_MODE_SPDIF_RCA; chip->professional_spdif = FALSE; chip->digital_in_automute = TRUE; if ((err = load_firmware(chip)) < 0) return err; chip->bad_board = FALSE; if ((err = init_line_levels(chip)) < 0) return err; err = set_digital_mode(chip, DIGITAL_MODE_SPDIF_RCA); if (err < 0) return err; err = set_professional_spdif(chip, TRUE); DE_INIT(("init_hw done\n")); return err; }
static int restore_dsp_rettings(struct echoaudio *chip) { int err; DE_INIT(("restore_dsp_settings\n")); if ((err = check_asic_status(chip)) < 0) return err; /* @ Gina20/Darla20 only. Should be harmless for other cards. */ chip->comm_page->gd_clock_state = GD_CLOCK_UNDEF; chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_UNDEF; chip->comm_page->handshake = 0xffffffff; if ((err = set_sample_rate(chip, chip->sample_rate)) < 0) return err; if (chip->meters_enabled) if (send_vector(chip, DSP_VC_METERS_ON) < 0) return -EIO; #ifdef ECHOCARD_HAS_EXTERNAL_CLOCK if (set_input_clock(chip, chip->input_clock) < 0) return -EIO; #endif #ifdef ECHOCARD_HAS_OUTPUT_CLOCK_SWITCH if (set_output_clock(chip, chip->output_clock) < 0) return -EIO; #endif if (update_output_line_level(chip) < 0) return -EIO; if (update_input_line_level(chip) < 0) return -EIO; #ifdef ECHOCARD_HAS_VMIXER if (update_vmixer_level(chip) < 0) return -EIO; #endif if (wait_handshake(chip) < 0) return -EIO; clear_handshake(chip); DE_INIT(("restore_dsp_rettings done\n")); return send_vector(chip, DSP_VC_UPDATE_FLAGS); }
static int init_dsp_comm_page(struct echoaudio *chip) { /* */ if (offsetof(struct comm_page, midi_output) != 0xbe0) { DE_INIT(("init_dsp_comm_page() - Invalid struct comm_page structure\n")); return -EPERM; } /* */ chip->card_name = ECHOCARD_NAME; chip->bad_board = TRUE; /* */ chip->dsp_code = NULL; /* */ chip->asic_loaded = FALSE; memset(chip->comm_page, 0, sizeof(struct comm_page)); /* */ chip->comm_page->comm_size = cpu_to_le32(sizeof(struct comm_page)); chip->comm_page->handshake = 0xffffffff; chip->comm_page->midi_out_free_count = cpu_to_le32(DSP_MIDI_OUT_FIFO_SIZE); chip->comm_page->sample_rate = cpu_to_le32(44100); /* */ memset(chip->comm_page->monitors, ECHOGAIN_MUTED, MONITOR_ARRAY_SIZE); memset(chip->comm_page->vmixer, ECHOGAIN_MUTED, VMIXER_ARRAY_SIZE); return 0; }
static int check_asic_status(struct echoaudio *chip) { u32 box_status; if (wait_handshake(chip)) return -EIO; chip->comm_page->ext_box_status = __constant_cpu_to_le32(E3G_ASIC_NOT_LOADED); chip->asic_loaded = FALSE; clear_handshake(chip); send_vector(chip, DSP_VC_TEST_ASIC); if (wait_handshake(chip)) { chip->dsp_code = NULL; return -EIO; } box_status = le32_to_cpu(chip->comm_page->ext_box_status); DE_INIT(("box_status=%x\n", box_status)); if (box_status == E3G_ASIC_NOT_LOADED) return -ENODEV; chip->asic_loaded = TRUE; return box_status & E3G_BOX_TYPE_MASK; }
/* Fills the comm page with default values */ static int init_dsp_comm_page(struct echoaudio *chip) { /* Check if the compiler added extra padding inside the structure */ if (offsetof(struct comm_page, midi_output) != 0xbe0) { DE_INIT(("init_dsp_comm_page() - Invalid struct comm_page structure\n")); return -EPERM; } /* Init all the basic stuff */ chip->card_name = ECHOCARD_NAME; chip->bad_board = TRUE; /* Set TRUE until DSP loaded */ chip->dsp_code = NULL; /* Current DSP code not loaded */ chip->asic_loaded = FALSE; memset(chip->comm_page, 0, sizeof(struct comm_page)); /* Init the comm page */ chip->comm_page->comm_size = cpu_to_le32(sizeof(struct comm_page)); chip->comm_page->handshake = 0xffffffff; chip->comm_page->midi_out_free_count = cpu_to_le32(DSP_MIDI_OUT_FIFO_SIZE); chip->comm_page->sample_rate = cpu_to_le32(44100); /* Set line levels so we don't blast any inputs on startup */ memset(chip->comm_page->monitors, ECHOGAIN_MUTED, MONITOR_ARRAY_SIZE); memset(chip->comm_page->vmixer, ECHOGAIN_MUTED, VMIXER_ARRAY_SIZE); return 0; }
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) { int err; DE_INIT(("init_hw() - Mia\n")); if (snd_BUG_ON((subdevice_id & 0xfff0) != MIA)) return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); return err; } chip->device_id = device_id; chip->subdevice_id = subdevice_id; chip->bad_board = TRUE; chip->dsp_code_to_load = &card_fw[FW_MIA_DSP]; /* Since this card has no ASIC, mark it as loaded so everything works OK */ chip->asic_loaded = TRUE; if ((subdevice_id & 0x0000f) == MIA_MIDI_REV) chip->has_midi = TRUE; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF; if ((err = load_firmware(chip)) < 0) return err; chip->bad_board = FALSE; if ((err = init_line_levels(chip))) return err; /* Default routing of the virtual channels: vchannels 0-3 go to analog outputs and vchannels 4-7 go to S/PDIF outputs */ set_vmixer_gain(chip, 0, 0, 0); set_vmixer_gain(chip, 1, 1, 0); set_vmixer_gain(chip, 0, 2, 0); set_vmixer_gain(chip, 1, 3, 0); set_vmixer_gain(chip, 2, 4, 0); set_vmixer_gain(chip, 3, 5, 0); set_vmixer_gain(chip, 2, 6, 0); set_vmixer_gain(chip, 3, 7, 0); err = update_vmixer_level(chip); DE_INIT(("init_hw done\n")); return err; }
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) { int err; DE_INIT(("init_hw() - Gina24\n")); if (snd_BUG_ON((subdevice_id & 0xfff0) != GINA24)) return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); return err; } chip->device_id = device_id; chip->subdevice_id = subdevice_id; chip->bad_board = TRUE; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL | ECHO_CLOCK_BIT_SPDIF | ECHO_CLOCK_BIT_ESYNC | ECHO_CLOCK_BIT_ESYNC96 | ECHO_CLOCK_BIT_ADAT; /* Gina24 comes in both '301 and '361 flavors */ if (chip->device_id == DEVICE_ID_56361) { chip->dsp_code_to_load = FW_GINA24_361_DSP; chip->digital_modes = ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | ECHOCAPS_HAS_DIGITAL_MODE_ADAT; } else { chip->dsp_code_to_load = FW_GINA24_301_DSP; chip->digital_modes = ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | ECHOCAPS_HAS_DIGITAL_MODE_ADAT | ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_CDROM; } if ((err = load_firmware(chip)) < 0) return err; chip->bad_board = FALSE; DE_INIT(("init_hw done\n")); return err; }
static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) { int err; DE_INIT(("init_hw() - Indigo\n")); if (snd_BUG_ON((subdevice_id & 0xfff0) != INDIGO)) return -ENODEV; if ((err = init_dsp_comm_page(chip))) { DE_INIT(("init_hw - could not initialize DSP comm page\n")); return err; } chip->device_id = device_id; chip->subdevice_id = subdevice_id; chip->bad_board = TRUE; chip->dsp_code_to_load = &card_fw[FW_INDIGO_DSP]; /* Since this card has no ASIC, mark it as loaded so everything works OK */ chip->asic_loaded = TRUE; chip->input_clock_types = ECHO_CLOCK_BIT_INTERNAL; if ((err = load_firmware(chip)) < 0) return err; chip->bad_board = FALSE; if ((err = init_line_levels(chip)) < 0) return err; /* Default routing of the virtual channels: all vchannels are routed to the stereo output */ set_vmixer_gain(chip, 0, 0, 0); set_vmixer_gain(chip, 1, 1, 0); set_vmixer_gain(chip, 0, 2, 0); set_vmixer_gain(chip, 1, 3, 0); set_vmixer_gain(chip, 0, 4, 0); set_vmixer_gain(chip, 1, 5, 0); set_vmixer_gain(chip, 0, 6, 0); set_vmixer_gain(chip, 1, 7, 0); err = update_vmixer_level(chip); DE_INIT(("init_hw done\n")); return err; }
static int init_line_levels(struct echoaudio *chip) { DE_INIT(("init_line_levels\n")); memset(chip->output_gain, ECHOGAIN_MUTED, sizeof(chip->output_gain)); memset(chip->input_gain, ECHOGAIN_MUTED, sizeof(chip->input_gain)); memset(chip->monitor_gain, ECHOGAIN_MUTED, sizeof(chip->monitor_gain)); memset(chip->vmixer_gain, ECHOGAIN_MUTED, sizeof(chip->vmixer_gain)); chip->input_clock = ECHO_CLOCK_INTERNAL; chip->output_clock = ECHO_CLOCK_WORD; chip->sample_rate = 44100; return restore_dsp_rettings(chip); }
/* Load ASIC code - done after the DSP is loaded */ static int load_asic_generic(struct echoaudio *chip, u32 cmd, const struct firmware *asic) { const struct firmware *fw; int err; u32 i, size; u8 *code; if ((err = get_firmware(&fw, asic, chip)) < 0) { snd_printk(KERN_WARNING "Firmware not found !\n"); return err; } code = (u8 *)fw->data; size = fw->size; /* Send the "Here comes the ASIC" command */ if (write_dsp(chip, cmd) < 0) goto la_error; /* Write length of ASIC file in bytes */ if (write_dsp(chip, size) < 0) goto la_error; for (i = 0; i < size; i++) { if (write_dsp(chip, code[i]) < 0) goto la_error; } DE_INIT(("ASIC loaded\n")); free_firmware(fw); return 0; la_error: DE_INIT(("failed on write_dsp\n")); free_firmware(fw); return -EIO; }
static int load_asic_generic(struct echoaudio *chip, u32 cmd, short asic) { const struct firmware *fw; int err; u32 i, size; u8 *code; err = get_firmware(&fw, chip, asic); if (err < 0) { snd_printk(KERN_WARNING "Firmware not found !\n"); return err; } code = (u8 *)fw->data; size = fw->size; /* */ if (write_dsp(chip, cmd) < 0) goto la_error; /* */ if (write_dsp(chip, size) < 0) goto la_error; for (i = 0; i < size; i++) { if (write_dsp(chip, code[i]) < 0) goto la_error; } DE_INIT(("ASIC loaded\n")); free_firmware(fw); return 0; la_error: DE_INIT(("failed on write_dsp\n")); free_firmware(fw); return -EIO; }
static int read_sn(struct echoaudio *chip) { int i; u32 sn[6]; for (i = 0; i < 5; i++) { if (read_dsp(chip, &sn[i])) { snd_printk(KERN_ERR "Failed to read serial number\n"); return -EIO; } } DE_INIT(("Read serial number %08x %08x %08x %08x %08x\n", sn[0], sn[1], sn[2], sn[3], sn[4])); return 0; }
static int check_asic_status(struct echoaudio *chip) { u32 asic_status; send_vector(chip, DSP_VC_TEST_ASIC); if (read_dsp(chip, &asic_status) < 0) { DE_INIT(("check_asic_status: failed on read_dsp\n")); chip->asic_loaded = FALSE; return -EIO; } chip->asic_loaded = (asic_status == ASIC_ALREADY_LOADED); return chip->asic_loaded ? 0 : -EIO; }
static int check_asic_status(struct echoaudio *chip) { u32 asic_status; send_vector(chip, DSP_VC_TEST_ASIC); /* The DSP will return a value to indicate whether or not the ASIC is currently loaded */ if (read_dsp(chip, &asic_status) < 0) { DE_INIT(("check_asic_status: failed on read_dsp\n")); chip->asic_loaded = FALSE; return -EIO; } chip->asic_loaded = (asic_status == ASIC_ALREADY_LOADED); return chip->asic_loaded ? 0 : -EIO; }
static int read_dsp(struct echoaudio *chip, u32 *data) { u32 status, i; for (i = 0; i < READ_DSP_TIMEOUT; i++) { status = get_dsp_register(chip, CHI32_STATUS_REG); if ((status & CHI32_STATUS_HOST_READ_FULL) != 0) { *data = get_dsp_register(chip, CHI32_DATA_REG); return 0; } udelay(1); cond_resched(); } chip->bad_board = TRUE; /* */ DE_INIT((KERN_ERR "read_dsp: Set bad_board to TRUE\n")); return -EIO; }
/* This function initializes the several volume controls for busses and pipes. This MUST be called after the DSP is up and running ! */ static int init_line_levels(struct echoaudio *chip) { int st, i, o; DE_INIT(("init_line_levels\n")); /* Mute output busses */ for (i = 0; i < num_busses_out(chip); i++) if ((st = set_output_gain(chip, i, ECHOGAIN_MUTED))) return st; if ((st = update_output_line_level(chip))) return st; #ifdef ECHOCARD_HAS_VMIXER /* Mute the Vmixer */ for (i = 0; i < num_pipes_out(chip); i++) for (o = 0; o < num_busses_out(chip); o++) if ((st = set_vmixer_gain(chip, o, i, ECHOGAIN_MUTED))) return st; if ((st = update_vmixer_level(chip))) return st; #endif /* ECHOCARD_HAS_VMIXER */ #ifdef ECHOCARD_HAS_MONITOR /* Mute the monitor mixer */ for (o = 0; o < num_busses_out(chip); o++) for (i = 0; i < num_busses_in(chip); i++) if ((st = set_monitor_gain(chip, o, i, ECHOGAIN_MUTED))) return st; if ((st = update_output_line_level(chip))) return st; #endif /* ECHOCARD_HAS_MONITOR */ #ifdef ECHOCARD_HAS_INPUT_GAIN for (i = 0; i < num_busses_in(chip); i++) if ((st = set_input_gain(chip, i, ECHOGAIN_MUTED))) return st; if ((st = update_input_line_level(chip))) return st; #endif /* ECHOCARD_HAS_INPUT_GAIN */ return 0; }
/* <--snd_echo_probe() */ static int snd_echo_midi_create(struct snd_card *card, struct echoaudio *chip) { int err; if ((err = snd_rawmidi_new(card, card->shortname, 0, 1, 1, &chip->rmidi)) < 0) return err; strcpy(chip->rmidi->name, card->shortname); chip->rmidi->private_data = chip; snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_echo_midi_input); snd_rawmidi_set_ops(chip->rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_echo_midi_output); chip->rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX; DE_INIT(("MIDI ok\n")); return 0; }
/* Gina24 has an ASIC on the PCI card which must be loaded for anything interesting to happen. */ static int load_asic(struct echoaudio *chip) { u32 control_reg; int err; short asic; if (chip->asic_loaded) return 1; /* Give the DSP a few milliseconds to settle down */ mdelay(10); /* Pick the correct ASIC for '301 or '361 Gina24 */ if (chip->device_id == DEVICE_ID_56361) asic = FW_GINA24_361_ASIC; else asic = FW_GINA24_301_ASIC; err = load_asic_generic(chip, DSP_FNC_LOAD_GINA24_ASIC, asic); if (err < 0) return err; chip->asic_code = asic; /* Now give the new ASIC a little time to set up */ mdelay(10); /* See if it worked */ err = check_asic_status(chip); /* Set up the control register if the load succeeded - 48 kHz, internal clock, S/PDIF RCA mode */ if (!err) { control_reg = GML_CONVERTER_ENABLE | GML_48KHZ; err = write_control_reg(chip, control_reg, TRUE); } DE_INIT(("load_asic() done\n")); return err; }
static int load_asic(struct echoaudio *chip) { u32 control_reg; int err; short asic; if (chip->asic_loaded) return 1; mdelay(10); if (chip->device_id == DEVICE_ID_56361) asic = FW_GINA24_361_ASIC; else asic = FW_GINA24_301_ASIC; err = load_asic_generic(chip, DSP_FNC_LOAD_GINA24_ASIC, asic); if (err < 0) return err; chip->asic_code = asic; mdelay(10); err = check_asic_status(chip); if (!err) { control_reg = GML_CONVERTER_ENABLE | GML_48KHZ; err = write_control_reg(chip, control_reg, TRUE); } DE_INIT(("load_asic() done\n")); return err; }
static int load_dsp(struct echoaudio *chip, u16 *code) { u32 address, data; int index, words, i; if (chip->dsp_code == code) { DE_INIT(("DSP is already loaded!\n")); return 0; } chip->bad_board = TRUE; /* */ chip->dsp_code = NULL; /* */ chip->asic_loaded = FALSE; /* */ DE_INIT(("load_dsp: Set bad_board to TRUE\n")); /* */ #ifdef DSP_56361 if ((i = install_resident_loader(chip)) < 0) return i; #endif /* */ if (send_vector(chip, DSP_VC_RESET) < 0) { DE_INIT(("LoadDsp: send_vector DSP_VC_RESET failed, Critical Failure\n")); return -EIO; } /* */ udelay(10); /* */ for (i = 0; i < 1000; i++) { /* */ if (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_REG_HF3) break; udelay(10); } if (i == 1000) { DE_INIT(("load_dsp: Timeout waiting for CHI32_STATUS_REG_HF3\n")); return -EIO; } /* */ set_dsp_register(chip, CHI32_CONTROL_REG, get_dsp_register(chip, CHI32_CONTROL_REG) | 0x900); /* */ index = code[0]; for (;;) { int block_type, mem_type; /* */ index++; /* */ block_type = code[index]; if (block_type == 4) /* */ break; index++; /* */ mem_type = code[index++]; /* */ words = code[index++]; if (words == 0) /* */ break; /* */ address = ((u32)code[index] << 16) + code[index + 1]; index += 2; if (write_dsp(chip, words) < 0) { DE_INIT(("load_dsp: failed to write number of DSP words\n")); return -EIO; } if (write_dsp(chip, address) < 0) { DE_INIT(("load_dsp: failed to write DSP address\n")); return -EIO; } if (write_dsp(chip, mem_type) < 0) { DE_INIT(("load_dsp: failed to write DSP memory type\n")); return -EIO; } /* */ for (i = 0; i < words; i++, index+=2) { data = ((u32)code[index] << 16) + code[index + 1]; if (write_dsp(chip, data) < 0) { DE_INIT(("load_dsp: failed to write DSP data\n")); return -EIO; } } } if (write_dsp(chip, 0) < 0) { /* */ DE_INIT(("load_dsp: Failed to write final zero\n")); return -EIO; } udelay(10); for (i = 0; i < 5000; i++) { /* */ /* */ if (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_REG_HF4) { set_dsp_register(chip, CHI32_CONTROL_REG, get_dsp_register(chip, CHI32_CONTROL_REG) & ~0x1b00); if (write_dsp(chip, DSP_FNC_SET_COMMPAGE_ADDR) < 0) { DE_INIT(("load_dsp: Failed to write DSP_FNC_SET_COMMPAGE_ADDR\n")); return -EIO; } if (write_dsp(chip, chip->comm_page_phys) < 0) { DE_INIT(("load_dsp: Failed to write comm page address\n")); return -EIO; } /* */ if (read_sn(chip) < 0) { DE_INIT(("load_dsp: Failed to read serial number\n")); return -EIO; } chip->dsp_code = code; /* */ chip->bad_board = FALSE; /* */ DE_INIT(("load_dsp: OK!\n")); return 0; } udelay(100); } DE_INIT(("load_dsp: DSP load timed out waiting for HF4\n")); return -EIO; }
static int install_resident_loader(struct echoaudio *chip) { u32 address; int index, words, i; u16 *code; u32 status; const struct firmware *fw; /* */ if (chip->device_id != DEVICE_ID_56361) return 0; /* */ status = get_dsp_register(chip, CHI32_STATUS_REG); if (status & CHI32_STATUS_REG_HF5) { DE_INIT(("Resident loader already installed; status is 0x%x\n", status)); return 0; } i = get_firmware(&fw, chip, FW_361_LOADER); if (i < 0) { snd_printk(KERN_WARNING "Firmware not found !\n"); return i; } /* */ /* */ set_dsp_register(chip, CHI32_CONTROL_REG, get_dsp_register(chip, CHI32_CONTROL_REG) | 0x900); code = (u16 *)fw->data; /* */ index = code[0]; /* */ index += 3; /* */ words = code[index++]; /* */ address = ((u32)code[index] << 16) + code[index + 1]; index += 2; /* */ if (write_dsp(chip, words)) { DE_INIT(("install_resident_loader: Failed to write word count!\n")); goto irl_error; } /* */ if (write_dsp(chip, address)) { DE_INIT(("install_resident_loader: Failed to write DSP address!\n")); goto irl_error; } /* */ for (i = 0; i < words; i++) { u32 data; data = ((u32)code[index] << 16) + code[index + 1]; if (write_dsp(chip, data)) { DE_INIT(("install_resident_loader: Failed to write DSP code\n")); goto irl_error; } index += 2; } /* */ for (i = 0; i < 200; i++) { /* */ udelay(50); status = get_dsp_register(chip, CHI32_STATUS_REG); if (status & CHI32_STATUS_REG_HF5) break; } if (i == 200) { DE_INIT(("Resident loader failed to set HF5\n")); goto irl_error; } DE_INIT(("Resident loader successfully installed\n")); free_firmware(fw); return 0; irl_error: free_firmware(fw); return -EIO; }
static int install_resident_loader(struct echoaudio *chip) { u32 address; int index, words, i; u16 *code; u32 status; const struct firmware *fw; /* 56361 cards only! This check is required by the old 56301-based Mona and Gina24 */ if (chip->device_id != DEVICE_ID_56361) return 0; /* Look to see if the resident loader is present. If the resident loader is already installed, host flag 5 will be on. */ status = get_dsp_register(chip, CHI32_STATUS_REG); if (status & CHI32_STATUS_REG_HF5) { DE_INIT(("Resident loader already installed; status is 0x%x\n", status)); return 0; } i = get_firmware(&fw, chip, FW_361_LOADER); if (i < 0) { snd_printk(KERN_WARNING "Firmware not found !\n"); return i; } /* The DSP code is an array of 16 bit words. The array is divided up into sections. The first word of each section is the size in words, followed by the section type. Since DSP addresses and data are 24 bits wide, they each take up two 16 bit words in the array. This is a lot like the other loader loop, but it's not a loop, you don't write the memory type, and you don't write a zero at the end. */ /* Set DSP format bits for 24 bit mode */ set_dsp_register(chip, CHI32_CONTROL_REG, get_dsp_register(chip, CHI32_CONTROL_REG) | 0x900); code = (u16 *)fw->data; /* Skip the header section; the first word in the array is the size of the first section, so the first real section of code is pointed to by Code[0]. */ index = code[0]; /* Skip the section size, LRS block type, and DSP memory type */ index += 3; /* Get the number of DSP words to write */ words = code[index++]; /* Get the DSP address for this block; 24 bits, so build from two words */ address = ((u32)code[index] << 16) + code[index + 1]; index += 2; /* Write the count to the DSP */ if (write_dsp(chip, words)) { DE_INIT(("install_resident_loader: Failed to write word count!\n")); goto irl_error; } /* Write the DSP address */ if (write_dsp(chip, address)) { DE_INIT(("install_resident_loader: Failed to write DSP address!\n")); goto irl_error; } /* Write out this block of code to the DSP */ for (i = 0; i < words; i++) { u32 data; data = ((u32)code[index] << 16) + code[index + 1]; if (write_dsp(chip, data)) { DE_INIT(("install_resident_loader: Failed to write DSP code\n")); goto irl_error; } index += 2; } /* Wait for flag 5 to come up */ for (i = 0; i < 200; i++) { /* Timeout is 50us * 200 = 10ms */ udelay(50); status = get_dsp_register(chip, CHI32_STATUS_REG); if (status & CHI32_STATUS_REG_HF5) break; } if (i == 200) { DE_INIT(("Resident loader failed to set HF5\n")); goto irl_error; } DE_INIT(("Resident loader successfully installed\n")); free_firmware(fw); return 0; irl_error: free_firmware(fw); return -EIO; }
static int restore_dsp_rettings(struct echoaudio *chip) { int i, o, err; DE_INIT(("restore_dsp_settings\n")); if ((err = check_asic_status(chip)) < 0) return err; /* */ chip->comm_page->gd_clock_state = GD_CLOCK_UNDEF; chip->comm_page->gd_spdif_status = GD_SPDIF_STATUS_UNDEF; chip->comm_page->handshake = 0xffffffff; /* */ for (i = 0; i < num_busses_out(chip); i++) { err = set_output_gain(chip, i, chip->output_gain[i]); if (err < 0) return err; } #ifdef ECHOCARD_HAS_VMIXER for (i = 0; i < num_pipes_out(chip); i++) for (o = 0; o < num_busses_out(chip); o++) { err = set_vmixer_gain(chip, o, i, chip->vmixer_gain[o][i]); if (err < 0) return err; } if (update_vmixer_level(chip) < 0) return -EIO; #endif /* */ #ifdef ECHOCARD_HAS_MONITOR for (o = 0; o < num_busses_out(chip); o++) for (i = 0; i < num_busses_in(chip); i++) { err = set_monitor_gain(chip, o, i, chip->monitor_gain[o][i]); if (err < 0) return err; } #endif /* */ #ifdef ECHOCARD_HAS_INPUT_GAIN for (i = 0; i < num_busses_in(chip); i++) { err = set_input_gain(chip, i, chip->input_gain[i]); if (err < 0) return err; } #endif /* */ err = update_output_line_level(chip); if (err < 0) return err; err = update_input_line_level(chip); if (err < 0) return err; err = set_sample_rate(chip, chip->sample_rate); if (err < 0) return err; if (chip->meters_enabled) { err = send_vector(chip, DSP_VC_METERS_ON); if (err < 0) return err; } #ifdef ECHOCARD_HAS_DIGITAL_MODE_SWITCH if (set_digital_mode(chip, chip->digital_mode) < 0) return -EIO; #endif #ifdef ECHOCARD_HAS_DIGITAL_IO if (set_professional_spdif(chip, chip->professional_spdif) < 0) return -EIO; #endif #ifdef ECHOCARD_HAS_PHANTOM_POWER if (set_phantom_power(chip, chip->phantom_power) < 0) return -EIO; #endif #ifdef ECHOCARD_HAS_EXTERNAL_CLOCK /* */ if (set_input_clock(chip, chip->input_clock) < 0) return -EIO; #endif #ifdef ECHOCARD_HAS_OUTPUT_CLOCK_SWITCH if (set_output_clock(chip, chip->output_clock) < 0) return -EIO; #endif if (wait_handshake(chip) < 0) return -EIO; clear_handshake(chip); if (send_vector(chip, DSP_VC_UPDATE_FLAGS) < 0) return -EIO; DE_INIT(("restore_dsp_rettings done\n")); return 0; }
static int load_dsp(struct echoaudio *chip, u16 *code) { u32 address, data; int index, words, i; if (chip->dsp_code == code) { DE_INIT(("DSP is already loaded!\n")); return 0; } chip->bad_board = TRUE; /* Set TRUE until DSP loaded */ chip->dsp_code = NULL; /* Current DSP code not loaded */ chip->asic_loaded = FALSE; /* Loading the DSP code will reset the ASIC */ DE_INIT(("load_dsp: Set bad_board to TRUE\n")); /* If this board requires a resident loader, install it. */ #ifdef DSP_56361 if ((i = install_resident_loader(chip)) < 0) return i; #endif /* Send software reset command */ if (send_vector(chip, DSP_VC_RESET) < 0) { DE_INIT(("LoadDsp: send_vector DSP_VC_RESET failed, Critical Failure\n")); return -EIO; } /* Delay 10us */ udelay(10); /* Wait 10ms for HF3 to indicate that software reset is complete */ for (i = 0; i < 1000; i++) { /* Timeout is 10us * 1000 = 10ms */ if (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_REG_HF3) break; udelay(10); } if (i == 1000) { DE_INIT(("load_dsp: Timeout waiting for CHI32_STATUS_REG_HF3\n")); return -EIO; } /* Set DSP format bits for 24 bit mode now that soft reset is done */ set_dsp_register(chip, CHI32_CONTROL_REG, get_dsp_register(chip, CHI32_CONTROL_REG) | 0x900); /* Main loader loop */ index = code[0]; for (;;) { int block_type, mem_type; /* Total Block Size */ index++; /* Block Type */ block_type = code[index]; if (block_type == 4) /* We're finished */ break; index++; /* Memory Type P=0,X=1,Y=2 */ mem_type = code[index++]; /* Block Code Size */ words = code[index++]; if (words == 0) /* We're finished */ break; /* Start Address */ address = ((u32)code[index] << 16) + code[index + 1]; index += 2; if (write_dsp(chip, words) < 0) { DE_INIT(("load_dsp: failed to write number of DSP words\n")); return -EIO; } if (write_dsp(chip, address) < 0) { DE_INIT(("load_dsp: failed to write DSP address\n")); return -EIO; } if (write_dsp(chip, mem_type) < 0) { DE_INIT(("load_dsp: failed to write DSP memory type\n")); return -EIO; } /* Code */ for (i = 0; i < words; i++, index+=2) { data = ((u32)code[index] << 16) + code[index + 1]; if (write_dsp(chip, data) < 0) { DE_INIT(("load_dsp: failed to write DSP data\n")); return -EIO; } } } if (write_dsp(chip, 0) < 0) { /* We're done!!! */ DE_INIT(("load_dsp: Failed to write final zero\n")); return -EIO; } udelay(10); for (i = 0; i < 5000; i++) { /* Timeout is 100us * 5000 = 500ms */ /* Wait for flag 4 - indicates that the DSP loaded OK */ if (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_REG_HF4) { set_dsp_register(chip, CHI32_CONTROL_REG, get_dsp_register(chip, CHI32_CONTROL_REG) & ~0x1b00); if (write_dsp(chip, DSP_FNC_SET_COMMPAGE_ADDR) < 0) { DE_INIT(("load_dsp: Failed to write DSP_FNC_SET_COMMPAGE_ADDR\n")); return -EIO; } if (write_dsp(chip, chip->comm_page_phys) < 0) { DE_INIT(("load_dsp: Failed to write comm page address\n")); return -EIO; } /* Get the serial number via slave mode. This is triggered by the SET_COMMPAGE_ADDR command. We don't actually use the serial number but we have to get it as part of the DSP init voodoo. */ if (read_sn(chip) < 0) { DE_INIT(("load_dsp: Failed to read serial number\n")); return -EIO; } chip->dsp_code = code; /* Show which DSP code loaded */ chip->bad_board = FALSE; /* DSP OK */ DE_INIT(("load_dsp: OK!\n")); return 0; } udelay(100); } DE_INIT(("load_dsp: DSP load timed out waiting for HF4\n")); return -EIO; }