/* * destructor */ static int hda_tegra_dev_free(struct snd_device *device) { struct azx *chip = device->device_data; struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); cancel_work_sync(&hda->probe_work); if (azx_bus(chip)->chip_init) { azx_stop_all_streams(chip); azx_stop_chip(chip); } azx_free_stream_pages(chip); azx_free_streams(chip); snd_hdac_bus_exit(azx_bus(chip)); return 0; }
static int __maybe_unused hda_tegra_runtime_suspend(struct device *dev) { struct snd_card *card = dev_get_drvdata(dev); struct azx *chip = card->private_data; struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); struct hdac_bus *bus = azx_bus(chip); if (chip && chip->running) { azx_stop_chip(chip); synchronize_irq(bus->irq); azx_enter_link_reset(chip); } hda_tegra_disable_clocks(hda); return 0; }
static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev) { struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); struct hdac_bus *bus = azx_bus(chip); struct device *dev = hda->dev; struct resource *res; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); hda->regs = devm_ioremap_resource(dev, res); if (IS_ERR(hda->regs)) return PTR_ERR(hda->regs); bus->remap_addr = hda->regs + HDA_BAR0; bus->addr = res->start + HDA_BAR0; hda_tegra_init(hda); return 0; }
static int hda_tegra_init_chip(struct azx *chip, struct platform_device *pdev) { struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip); struct hdac_bus *bus = azx_bus(chip); struct device *dev = hda->dev; struct resource *res; int err; hda->hda_clk = devm_clk_get(dev, "hda"); if (IS_ERR(hda->hda_clk)) { dev_err(dev, "failed to get hda clock\n"); return PTR_ERR(hda->hda_clk); } hda->hda2codec_2x_clk = devm_clk_get(dev, "hda2codec_2x"); if (IS_ERR(hda->hda2codec_2x_clk)) { dev_err(dev, "failed to get hda2codec_2x clock\n"); return PTR_ERR(hda->hda2codec_2x_clk); } hda->hda2hdmi_clk = devm_clk_get(dev, "hda2hdmi"); if (IS_ERR(hda->hda2hdmi_clk)) { dev_err(dev, "failed to get hda2hdmi clock\n"); return PTR_ERR(hda->hda2hdmi_clk); } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); hda->regs = devm_ioremap_resource(dev, res); if (IS_ERR(hda->regs)) return PTR_ERR(hda->regs); bus->remap_addr = hda->regs + HDA_BAR0; bus->addr = res->start + HDA_BAR0; err = hda_tegra_enable_clocks(hda); if (err) { dev_err(dev, "failed to get enable clocks\n"); return err; } hda_tegra_init(hda); return 0; }
static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) { struct hdac_bus *bus = azx_bus(chip); struct snd_card *card = chip->card; int err; unsigned short gcap; int irq_id = platform_get_irq(pdev, 0); const char *sname, *drv_name = "tegra-hda"; struct device_node *np = pdev->dev.of_node; err = hda_tegra_init_chip(chip, pdev); if (err) return err; err = devm_request_irq(chip->card->dev, irq_id, azx_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip); if (err) { dev_err(chip->card->dev, "unable to request IRQ %d, disabling device\n", irq_id); return err; } bus->irq = irq_id; synchronize_irq(bus->irq); gcap = azx_readw(chip, GCAP); dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap); /* read number of streams from GCAP register instead of using * hardcoded value */ chip->capture_streams = (gcap >> 8) & 0x0f; 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; /* initialize streams */ err = azx_init_streams(chip); if (err < 0) { dev_err(card->dev, "failed to initialize streams: %d\n", err); return err; } 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); /* codec detection */ if (!bus->codec_mask) { dev_err(card->dev, "no codecs found!\n"); return -ENODEV; } /* driver name */ strncpy(card->driver, drv_name, sizeof(card->driver)); /* 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"); strncpy(card->shortname, sname, sizeof(card->shortname)); /* longname for card */ snprintf(card->longname, sizeof(card->longname), "%s at 0x%lx irq %i", card->shortname, bus->addr, bus->irq); return 0; }