sound/soc/tegra/tegra20_spdif.c

Source file repositories/reference/linux-study-clean/sound/soc/tegra/tegra20_spdif.c

File Facts

System
Linux kernel
Corpus path
sound/soc/tegra/tegra20_spdif.c
Extension
.c
Size
10990 bytes
Lines
430
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/*
 * tegra20_spdif.c - Tegra20 SPDIF driver
 *
 * Author: Stephen Warren <swarren@nvidia.com>
 * Copyright (C) 2011-2012 - NVIDIA, Inc.
 */

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>

#include "tegra20_spdif.h"

static int tegra20_spdif_runtime_suspend(struct device *dev)
{
	struct tegra20_spdif *spdif = dev_get_drvdata(dev);

	regcache_cache_only(spdif->regmap, true);

	clk_disable_unprepare(spdif->clk_spdif_out);

	return 0;
}

static int tegra20_spdif_runtime_resume(struct device *dev)
{
	struct tegra20_spdif *spdif = dev_get_drvdata(dev);
	int ret;

	ret = reset_control_assert(spdif->reset);
	if (ret)
		return ret;

	ret = clk_prepare_enable(spdif->clk_spdif_out);
	if (ret) {
		dev_err(dev, "clk_enable failed: %d\n", ret);
		return ret;
	}

	usleep_range(10, 100);

	ret = reset_control_deassert(spdif->reset);
	if (ret)
		goto disable_clocks;

	regcache_cache_only(spdif->regmap, false);
	regcache_mark_dirty(spdif->regmap);

	ret = regcache_sync(spdif->regmap);
	if (ret)
		goto disable_clocks;

	return 0;

disable_clocks:
	clk_disable_unprepare(spdif->clk_spdif_out);

	return ret;
}

static int tegra20_spdif_hw_params(struct snd_pcm_substream *substream,
				   struct snd_pcm_hw_params *params,
				   struct snd_soc_dai *dai)
{
	struct tegra20_spdif *spdif = dev_get_drvdata(dai->dev);
	unsigned int mask = 0, val = 0;
	int ret, spdifclock;
	long rate;

	mask |= TEGRA20_SPDIF_CTRL_PACK |
		TEGRA20_SPDIF_CTRL_BIT_MODE_MASK;
	switch (params_format(params)) {
	case SNDRV_PCM_FORMAT_S16_LE:
		val |= TEGRA20_SPDIF_CTRL_PACK |
		       TEGRA20_SPDIF_CTRL_BIT_MODE_16BIT;
		break;

Annotation

Implementation Notes