if (state < 0 || state >= ARRAY_SIZE(state_to_str)) return"null"; return state_to_str[state];
}
/* Called with wm0010->lock held */ staticvoid wm0010_halt(struct snd_soc_component *component)
{ struct wm0010_priv *wm0010 = snd_soc_component_get_drvdata(component); unsignedlong flags; enum wm0010_state state;
/* Fetch the wm0010 state */
spin_lock_irqsave(&wm0010->irq_lock, flags);
state = wm0010->state;
spin_unlock_irqrestore(&wm0010->irq_lock, flags);
switch (state) { case WM0010_POWER_OFF: /* If there's nothing to do, bail out */ return; case WM0010_OUT_OF_RESET: case WM0010_BOOTROM: case WM0010_STAGE2: case WM0010_FIRMWARE: /* Remember to put chip back into reset */
gpiod_set_value_cansleep(wm0010->reset, 1); /* Disable the regulators */
regulator_disable(wm0010->dbvdd);
regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies),
wm0010->core_supplies); break;
}
if (xfer->m.status != 0) {
dev_err(component->dev, "SPI transfer failed: %d\n",
xfer->m.status);
wm0010_mark_boot_failure(wm0010); if (xfer->done)
complete(xfer->done); return;
}
for (i = 0; i < xfer->t.len / 4; i++) {
dev_dbg(component->dev, "%d: %04x\n", i, out32[i]);
switch (be32_to_cpu(out32[i])) { case 0xe0e0e0e0:
dev_err(component->dev, "%d: ROM error reported in stage 2\n", i);
wm0010_mark_boot_failure(wm0010); break;
case 0x55555555: if (wm0010->state < WM0010_STAGE2) break;
dev_err(component->dev, "%d: ROM bootloader running in stage 2\n", i);
wm0010_mark_boot_failure(wm0010); break;
case 0x0fed0000:
dev_dbg(component->dev, "Stage2 loader running\n"); break;
case 0x0fed0007:
dev_dbg(component->dev, "CODE_HDR packet received\n"); break;
case 0x0fed0008:
dev_dbg(component->dev, "CODE_DATA packet received\n"); break;
case 0x0fed0009:
dev_dbg(component->dev, "Download complete\n"); break;
case 0x0fed000c:
dev_dbg(component->dev, "Application start\n"); break;
case 0x0fed000e:
dev_dbg(component->dev, "PLL packet received\n");
wm0010->pll_running = true; break;
case 0x0fed0025:
dev_err(component->dev, "Device reports image too long\n");
wm0010_mark_boot_failure(wm0010); break;
case 0x0fed002c:
dev_err(component->dev, "Device reports bad SPI packet\n");
wm0010_mark_boot_failure(wm0010); break;
case 0x0fed0031:
dev_err(component->dev, "Device reports SPI read overflow\n");
wm0010_mark_boot_failure(wm0010); break;
case 0x0fed0032:
dev_err(component->dev, "Device reports SPI underclock\n");
wm0010_mark_boot_failure(wm0010); break;
case 0x0fed0033:
dev_err(component->dev, "Device reports bad header packet\n");
wm0010_mark_boot_failure(wm0010); break;
case 0x0fed0034:
dev_err(component->dev, "Device reports invalid packet type\n");
wm0010_mark_boot_failure(wm0010); break;
case 0x0fed0035:
dev_err(component->dev, "Device reports data before header error\n");
wm0010_mark_boot_failure(wm0010); break;
case 0x0fed0038:
dev_err(component->dev, "Device reports invalid PLL packet\n"); break;
case 0x0fed003a:
dev_err(component->dev, "Device reports packet alignment error\n");
wm0010_mark_boot_failure(wm0010); break;
/* First record should be INFO */ if (rec->command != DFW_CMD_INFO) {
dev_err(component->dev, "First record not INFO\r\n");
ret = -EINVAL; goto abort;
}
if (inforec->info_version != INFO_VERSION) {
dev_err(component->dev, "Unsupported version (%02d) of INFO record\r\n",
inforec->info_version);
ret = -EINVAL; goto abort;
}
dev_dbg(component->dev, "Version v%02d INFO record found\r\n",
inforec->info_version);
/* Check it's a DSP file */ if (dsp != DEVICE_ID_WM0010) {
dev_err(component->dev, "Not a WM0010 firmware file.\r\n");
ret = -EINVAL; goto abort;
}
/* Skip the info record as we don't need to send it */
offset += ((rec->length) + 8);
rec = (void *)&rec->data[rec->length];
while (offset < fw->size) {
dev_dbg(component->dev, "Packet: command %d, data length = 0x%x\r\n",
rec->command, rec->length);
len = rec->length + 8;
xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); if (!xfer) {
ret = -ENOMEM; goto abort;
}
/* Copy to local buffer first as vmalloc causes problems for dma */
img = kmemdup(&fw->data[0], fw->size, GFP_KERNEL | GFP_DMA); if (!img) {
ret = -ENOMEM; goto abort2;
}
out = kzalloc(fw->size, GFP_KERNEL | GFP_DMA); if (!out) {
ret = -ENOMEM; goto abort1;
}
dev_dbg(component->dev, "Starting initial download at %dHz\n",
t.speed_hz);
ret = spi_sync(spi, &m); if (ret != 0) {
dev_err(component->dev, "Initial download failed: %d\n", ret); goto abort;
}
/* Look for errors from the boot ROM */ for (i = 0; i < fw->size; i++) { if (out[i] != 0x55) {
dev_err(component->dev, "Boot ROM error: %x in %d\n",
out[i], i);
wm0010_mark_boot_failure(wm0010);
ret = -EBUSY; goto abort;
}
}
abort:
kfree(out);
abort1:
kfree(img);
abort2:
release_firmware(fw);
ret = wm0010_stage2_load(component); if (ret) goto abort;
if (!wait_for_completion_timeout(&wm0010->boot_completion,
msecs_to_jiffies(20)))
dev_err(component->dev, "Failed to get interrupt from DSP loader.\n");
ret = spi_sync(spi, &m); if (ret) {
dev_err(component->dev, "First PLL write failed: %d\n", ret); goto abort_swap;
}
/* Use a second send of the message to get the return status */
ret = spi_sync(spi, &m); if (ret) {
dev_err(component->dev, "Second PLL write failed: %d\n", ret); goto abort_swap;
}
p = (u32 *)out;
/* Look for PLL active code from the DSP */ for (i = 0; i < len / 4; i++) { if (*p == 0x0e00ed0f) {
dev_dbg(component->dev, "PLL packet received\n");
wm0010->pll_running = true; break;
}
p++;
}
abort_swap:
kfree(img_swap);
abort_out:
kfree(out);
abort: /* Put the chip back into reset */
wm0010_halt(component);
mutex_unlock(&wm0010->lock); return ret;
switch (level) { case SND_SOC_BIAS_ON: if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_PREPARE)
wm0010_boot(component); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_PREPARE) {
mutex_lock(&wm0010->lock);
wm0010_halt(component);
mutex_unlock(&wm0010->lock);
} break; case SND_SOC_BIAS_OFF: break;
}
return 0;
}
staticint wm0010_set_sysclk(struct snd_soc_component *component, int source, int clk_id, unsignedint freq, int dir)
{ struct wm0010_priv *wm0010 = snd_soc_component_get_drvdata(component); unsignedint i;
wm0010->sysclk = freq;
if (freq < pll_clock_map[ARRAY_SIZE(pll_clock_map)-1].max_sysclk) {
wm0010->max_spi_freq = 0;
} else { for (i = 0; i < ARRAY_SIZE(pll_clock_map); i++) if (freq >= pll_clock_map[i].max_sysclk) {
wm0010->max_spi_freq = pll_clock_map[i].max_pll_spi_speed;
wm0010->pll_clkctrl1 = pll_clock_map[i].pll_clkctrl1; break;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.