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 load_dsp(struct echoaudio *chip, u16 *code) { u32 address, data; int index, words, i; if (chip->dsp_code == code) { dev_warn(chip->card->dev, "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 */ dev_dbg(chip->card->dev, "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) { dev_err(chip->card->dev, "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) { dev_err(chip->card->dev, "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) { dev_err(chip->card->dev, "load_dsp: failed to write number of DSP words\n"); return -EIO; } if (write_dsp(chip, address) < 0) { dev_err(chip->card->dev, "load_dsp: failed to write DSP address\n"); return -EIO; } if (write_dsp(chip, mem_type) < 0) { dev_err(chip->card->dev, "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) { dev_err(chip->card->dev, "load_dsp: failed to write DSP data\n"); return -EIO; } } } if (write_dsp(chip, 0) < 0) { /* We're done!!! */ dev_err(chip->card->dev, "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) { dev_err(chip->card->dev, "load_dsp: Failed to write DSP_FNC_SET_COMMPAGE_ADDR\n"); return -EIO; } if (write_dsp(chip, chip->comm_page_phys) < 0) { dev_err(chip->card->dev, "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) { dev_err(chip->card->dev, "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 */ return 0; } udelay(100); } dev_err(chip->card->dev, "load_dsp: DSP load timed out waiting for HF4\n"); return -EIO; }