/* max number of SDs */ #define NUM_CAPTURE_SD 1 #define NUM_PLAYBACK_SD 1
/* * Tegra194 does not reflect correct number of SDO lines. Below macro * is used to update the GCAP register to workaround the issue.
*/ #define TEGRA194_NUM_SDO_LINES 4
/* Enable PCI access */
v = readl(hda->regs + HDA_IPFS_CONFIG);
v |= HDA_IPFS_EN_FPCI;
writel(v, hda->regs + HDA_IPFS_CONFIG);
/* Enable MEM/IO space and bus master */
v = readl(hda->regs + HDA_CFG_CMD);
v &= ~HDA_DISABLE_INTR;
v |= HDA_ENABLE_MEM_SPACE | HDA_ENABLE_IO_SPACE |
HDA_ENABLE_BUS_MASTER | HDA_ENABLE_SERR;
writel(v, hda->regs + HDA_CFG_CMD);
/* * Tegra194 has 4 SDO lines and the STRIPE can be used to * indicate how many of the SDO lines the stream should be * striped. But GCAP register does not reflect the true * capability of HW. Below workaround helps to fix this. * * GCAP_NSDO is bits 19:18 in T_AZA_DBG_CFG_2, * 0 for 1 SDO, 1 for 2 SDO, 2 for 4 SDO lines.
*/ if (of_device_is_compatible(np, "nvidia,tegra194-hda")) {
u32 val;
dev_info(card->dev, "Override SDO lines to %u\n",
TEGRA194_NUM_SDO_LINES);
val = readl(hda->regs + FPCI_DBG_CFG_2) & ~FPCI_GCAP_NSDO_MASK;
val |= (TEGRA194_NUM_SDO_LINES >> 1) << FPCI_GCAP_NSDO_SHIFT;
writel(val, hda->regs + FPCI_DBG_CFG_2);
}
/* read number of streams from GCAP register instead of using * hardcoded value
*/
chip->capture_streams = (gcap >> 8) & 0x0f;
/* The GCAP register on Tegra234 implies no Input Streams(ISS) support, * but the HW output stream descriptor programming should start with * offset 0x20*4 from base stream descriptor address. This will be a * problem while calculating the offset for output stream descriptor * which will be considering input stream also. So here output stream * starts with offset 0 which is wrong as HW register for output stream * offset starts with 4.
*/ if (!hda->soc->input_stream)
chip->capture_streams = 4;
chip->playback_streams = (gcap >> 12) & 0x0f; if (!chip->playback_streams && !chip->capture_streams) { /* gcap didn't give any info, switching to old method */
chip->playback_streams = NUM_PLAYBACK_SD;
chip->capture_streams = NUM_CAPTURE_SD;
}
chip->capture_index_offset = 0;
chip->playback_index_offset = chip->capture_streams;
chip->num_streams = chip->playback_streams + chip->capture_streams;
err = azx_alloc_stream_pages(chip); if (err < 0) {
dev_err(card->dev, "failed to allocate stream pages: %d\n",
err); return err;
}
/* initialize chip */
azx_init_chip(chip, 1);
/* * Playback (for 44.1K/48K, 2-channel, 16-bps) fails with * 4 SDO lines due to legacy design limitation. Following * is, from HD Audio Specification (Revision 1.0a), used to * control striping of the stream across multiple SDO lines * for sample rates <= 48K. * * { ((num_channels * bits_per_sample) / number of SDOs) >= 8 } * * Due to legacy design issue it is recommended that above * ratio must be greater than 8. Since number of SDO lines is * in powers of 2, next available ratio is 16 which can be * used as a limiting factor here.
*/ if (of_device_is_compatible(np, "nvidia,tegra30-hda"))
chip->bus.core.sdo_limit = 16;
/* codec detection */ if (!bus->codec_mask) {
dev_err(card->dev, "no codecs found!\n"); return -ENODEV;
}
/* driver name */
strscpy(card->driver, drv_name); /* shortname for card */
sname = of_get_property(np, "nvidia,model", NULL); if (!sname)
sname = drv_name; if (strlen(sname) > sizeof(card->shortname))
dev_info(card->dev, "truncating shortname for card\n");
strscpy(card->shortname, sname);
/* longname for card */
snprintf(card->longname, sizeof(card->longname), "%s at 0x%lx irq %i",
card->shortname, bus->addr, bus->irq);
/* * HDA power domain and clocks are always on for Tegra264 and * the jack detection logic would work always, so no need of * jack polling mechanism running.
*/ if (!hda->soc->always_on) {
chip->jackpoll_interval = msecs_to_jiffies(5000);
chip->bus.jackpoll_in_suspend = 1;
}
/* * "hda2hdmi" is not applicable for Tegra234. This is because the * codec is separate IP and not under display SOR partition now.
*/ if (hda->soc->has_hda2hdmi)
hda->resets[hda->nresets++].id = "hda2hdmi";
/* * "hda2codec_2x" reset is not present on Tegra194. Though DT would * be updated to reflect this, but to have backward compatibility * below is necessary.
*/ if (hda->soc->has_hda2codec_2x_reset)
hda->resets[hda->nresets++].id = "hda2codec_2x";
err = devm_reset_control_bulk_get_exclusive(&pdev->dev, hda->nresets,
hda->resets); if (err) goto out_free;
hda->clocks[hda->nclocks++].id = "hda"; if (hda->soc->has_hda2hdmi)
hda->clocks[hda->nclocks++].id = "hda2hdmi";
if (hda->soc->has_hda2codec_2x)
hda->clocks[hda->nclocks++].id = "hda2codec_2x";
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.