linux/sound/soc/fsl/fsl_easrc.c

// SPDX-License-Identifier: GPL-2.0
// Copyright 2019 NXP

#include <linux/atomic.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
#include <linux/interrupt.h>
#include <linux/kobject.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/sched/signal.h>
#include <linux/sysfs.h>
#include <linux/types.h>
#include <linux/gcd.h>
#include <sound/dmaengine_pcm.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include <sound/core.h>

#include "fsl_easrc.h"
#include "imx-pcm.h"

#define FSL_EASRC_FORMATS

static int fsl_easrc_iec958_put_bits(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_value *ucontrol)
{}

static int fsl_easrc_iec958_get_bits(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_value *ucontrol)
{}

static int fsl_easrc_get_reg(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{}

static int fsl_easrc_set_reg(struct snd_kcontrol *kcontrol,
			     struct snd_ctl_elem_value *ucontrol)
{}

#define SOC_SINGLE_REG_RW(xname, xreg)

#define SOC_SINGLE_VAL_RW(xname, xreg)

static const struct snd_kcontrol_new fsl_easrc_snd_controls[] =;

/*
 * fsl_easrc_set_rs_ratio
 *
 * According to the resample taps, calculate the resample ratio
 * ratio = in_rate / out_rate
 */
static int fsl_easrc_set_rs_ratio(struct fsl_asrc_pair *ctx)
{}

/* Normalize input and output sample rates */
static void fsl_easrc_normalize_rates(struct fsl_asrc_pair *ctx)
{}

/* Resets the pointer of the coeff memory pointers */
static int fsl_easrc_coeff_mem_ptr_reset(struct fsl_asrc *easrc,
					 unsigned int ctx_id, int mem_type)
{}

static inline uint32_t bits_taps_to_val(unsigned int t)
{}

static int fsl_easrc_resampler_config(struct fsl_asrc *easrc)
{}

/**
 *  fsl_easrc_normalize_filter - Scale filter coefficients (64 bits float)
 *  For input float32 normalized range (1.0,-1.0) -> output int[16,24,32]:
 *      scale it by multiplying filter coefficients by 2^31
 *  For input int[16, 24, 32] -> output float32
 *      scale it by multiplying filter coefficients by 2^-15, 2^-23, 2^-31
 *  input:
 *      @easrc:  Structure pointer of fsl_asrc
 *      @infilter : Pointer to non-scaled input filter
 *      @shift:  The multiply factor
 *  output:
 *      @outfilter: scaled filter
 */
static int fsl_easrc_normalize_filter(struct fsl_asrc *easrc,
				      u64 *infilter,
				      u64 *outfilter,
				      int shift)
{}

static int fsl_easrc_write_pf_coeff_mem(struct fsl_asrc *easrc, int ctx_id,
					u64 *coef, int n_taps, int shift)
{}

static int fsl_easrc_prefilter_config(struct fsl_asrc *easrc,
				      unsigned int ctx_id)
{}

static int fsl_easrc_max_ch_for_slot(struct fsl_asrc_pair *ctx,
				     struct fsl_easrc_slot *slot)
{}

static int fsl_easrc_config_one_slot(struct fsl_asrc_pair *ctx,
				     struct fsl_easrc_slot *slot,
				     unsigned int slot_ctx_idx,
				     unsigned int *req_channels,
				     unsigned int *start_channel,
				     unsigned int *avail_channel)
{}

/*
 * fsl_easrc_config_slot
 *
 * A single context can be split amongst any of the 4 context processing pipes
 * in the design.
 * The total number of channels consumed within the context processor must be
 * less than or equal to 8. if a single context is configured to contain more
 * than 8 channels then it must be distributed across multiple context
 * processing pipe slots.
 *
 */
static int fsl_easrc_config_slot(struct fsl_asrc *easrc, unsigned int ctx_id)
{}

/*
 * fsl_easrc_release_slot
 *
 * Clear the slot configuration
 */
static int fsl_easrc_release_slot(struct fsl_asrc *easrc, unsigned int ctx_id)
{}

/*
 * fsl_easrc_config_context
 *
 * Configure the register relate with context.
 */
static int fsl_easrc_config_context(struct fsl_asrc *easrc, unsigned int ctx_id)
{}

static int fsl_easrc_process_format(struct fsl_asrc_pair *ctx,
				    struct fsl_easrc_data_fmt *fmt,
				    snd_pcm_format_t raw_fmt)
{}

static int fsl_easrc_set_ctx_format(struct fsl_asrc_pair *ctx,
				    snd_pcm_format_t *in_raw_format,
				    snd_pcm_format_t *out_raw_format)
{}

/*
 * The ASRC provides interleaving support in hardware to ensure that a
 * variety of sample sources can be internally combined
 * to conform with this format. Interleaving parameters are accessed
 * through the ASRC_CTRL_IN_ACCESSa and ASRC_CTRL_OUT_ACCESSa registers
 */
static int fsl_easrc_set_ctx_organziation(struct fsl_asrc_pair *ctx)
{}

/*
 * Request one of the available contexts
 *
 * Returns a negative number on error and >=0 as context id
 * on success
 */
static int fsl_easrc_request_context(int channels, struct fsl_asrc_pair *ctx)
{}

/*
 * Release the context
 *
 * This funciton is mainly doing the revert thing in request context
 */
static void fsl_easrc_release_context(struct fsl_asrc_pair *ctx)
{}

/*
 * Start the context
 *
 * Enable the DMA request and context
 */
static int fsl_easrc_start_context(struct fsl_asrc_pair *ctx)
{}

/*
 * Stop the context
 *
 * Disable the DMA request and context
 */
static int fsl_easrc_stop_context(struct fsl_asrc_pair *ctx)
{}

static struct dma_chan *fsl_easrc_get_dma_channel(struct fsl_asrc_pair *ctx,
						  bool dir)
{
	struct fsl_asrc *easrc = ctx->asrc;
	enum asrc_pair_index index = ctx->index;
	char name[8];

	/* Example of dma name: ctx0_rx */
	sprintf(name, "ctx%c_%cx", index + '0', dir == IN ? 'r' : 't');

	return dma_request_slave_channel(&easrc->pdev->dev, name);
};

static const unsigned int easrc_rates[] =;

static const struct snd_pcm_hw_constraint_list easrc_rate_constraints =;

static int fsl_easrc_startup(struct snd_pcm_substream *substream,
			     struct snd_soc_dai *dai)
{}

static int fsl_easrc_trigger(struct snd_pcm_substream *substream,
			     int cmd, struct snd_soc_dai *dai)
{}

static int fsl_easrc_hw_params(struct snd_pcm_substream *substream,
			       struct snd_pcm_hw_params *params,
			       struct snd_soc_dai *dai)
{}

static int fsl_easrc_hw_free(struct snd_pcm_substream *substream,
			     struct snd_soc_dai *dai)
{}

static int fsl_easrc_dai_probe(struct snd_soc_dai *cpu_dai)
{}

static const struct snd_soc_dai_ops fsl_easrc_dai_ops =;

static struct snd_soc_dai_driver fsl_easrc_dai =;

static const struct snd_soc_component_driver fsl_easrc_component =;

static const struct reg_default fsl_easrc_reg_defaults[] =;

static const struct regmap_range fsl_easrc_readable_ranges[] =;

static const struct regmap_access_table fsl_easrc_readable_table =;

static const struct regmap_range fsl_easrc_writeable_ranges[] =;

static const struct regmap_access_table fsl_easrc_writeable_table =;

static const struct regmap_range fsl_easrc_volatileable_ranges[] =;

static const struct regmap_access_table fsl_easrc_volatileable_table =;

static const struct regmap_config fsl_easrc_regmap_config =;

#ifdef DEBUG
static void fsl_easrc_dump_firmware(struct fsl_asrc *easrc)
{
	struct fsl_easrc_priv *easrc_priv = easrc->private;
	struct asrc_firmware_hdr *firm = easrc_priv->firmware_hdr;
	struct interp_params *interp = easrc_priv->interp;
	struct prefil_params *prefil = easrc_priv->prefil;
	struct device *dev = &easrc->pdev->dev;
	int i;

	if (firm->magic != FIRMWARE_MAGIC) {
		dev_err(dev, "Wrong magic. Something went wrong!");
		return;
	}

	dev_dbg(dev, "Firmware v%u dump:\n", firm->firmware_version);
	dev_dbg(dev, "Num prefilter scenarios: %u\n", firm->prefil_scen);
	dev_dbg(dev, "Num interpolation scenarios: %u\n", firm->interp_scen);
	dev_dbg(dev, "\nInterpolation scenarios:\n");

	for (i = 0; i < firm->interp_scen; i++) {
		if (interp[i].magic != FIRMWARE_MAGIC) {
			dev_dbg(dev, "%d. wrong interp magic: %x\n",
				i, interp[i].magic);
			continue;
		}
		dev_dbg(dev, "%d. taps: %u, phases: %u, center: %llu\n", i,
			interp[i].num_taps, interp[i].num_phases,
			interp[i].center_tap);
	}

	for (i = 0; i < firm->prefil_scen; i++) {
		if (prefil[i].magic != FIRMWARE_MAGIC) {
			dev_dbg(dev, "%d. wrong prefil magic: %x\n",
				i, prefil[i].magic);
			continue;
		}
		dev_dbg(dev, "%d. insr: %u, outsr: %u, st1: %u, st2: %u\n", i,
			prefil[i].insr, prefil[i].outsr,
			prefil[i].st1_taps, prefil[i].st2_taps);
	}

	dev_dbg(dev, "end of firmware dump\n");
}
#endif

static int fsl_easrc_get_firmware(struct fsl_asrc *easrc)
{}

static irqreturn_t fsl_easrc_isr(int irq, void *dev_id)
{}

static int fsl_easrc_get_fifo_addr(u8 dir, enum asrc_pair_index index)
{}

static const struct of_device_id fsl_easrc_dt_ids[] =;
MODULE_DEVICE_TABLE(of, fsl_easrc_dt_ids);

static int fsl_easrc_probe(struct platform_device *pdev)
{}

static void fsl_easrc_remove(struct platform_device *pdev)
{}

static int fsl_easrc_runtime_suspend(struct device *dev)
{}

static int fsl_easrc_runtime_resume(struct device *dev)
{}

static const struct dev_pm_ops fsl_easrc_pm_ops =;

static struct platform_driver fsl_easrc_driver =;
module_platform_driver();

MODULE_DESCRIPTION();
MODULE_LICENSE();