linux/sound/soc/fsl/fsl_asrc.c

// SPDX-License-Identifier: GPL-2.0
//
// Freescale ASRC ALSA SoC Digital Audio Interface (DAI) driver
//
// Copyright (C) 2014 Freescale Semiconductor, Inc.
//
// Author: Nicolin Chen <[email protected]>

#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/of_platform.h>
#include <linux/dma/imx-dma.h>
#include <linux/pm_runtime.h>
#include <sound/dmaengine_pcm.h>
#include <sound/pcm_params.h>

#include "fsl_asrc.h"

#define IDEAL_RATIO_DECIMAL_DEPTH
#define DIVIDER_NUM
#define INIT_RETRY_NUM

#define pair_err(fmt, ...)

#define pair_dbg(fmt, ...)

#define pair_warn(fmt, ...)

/* Corresponding to process_option */
static unsigned int supported_asrc_rate[] =;

static struct snd_pcm_hw_constraint_list fsl_asrc_rate_constraints =;

/*
 * The following tables map the relationship between asrc_inclk/asrc_outclk in
 * fsl_asrc.h and the registers of ASRCSR
 */
static unsigned char input_clk_map_imx35[ASRC_CLK_MAP_LEN] =;

static unsigned char output_clk_map_imx35[ASRC_CLK_MAP_LEN] =;

/* i.MX53 uses the same map for input and output */
static unsigned char input_clk_map_imx53[ASRC_CLK_MAP_LEN] =;

static unsigned char output_clk_map_imx53[ASRC_CLK_MAP_LEN] =;

/*
 * i.MX8QM/i.MX8QXP uses the same map for input and output.
 * clk_map_imx8qm[0] is for i.MX8QM asrc0
 * clk_map_imx8qm[1] is for i.MX8QM asrc1
 * clk_map_imx8qxp[0] is for i.MX8QXP asrc0
 * clk_map_imx8qxp[1] is for i.MX8QXP asrc1
 */
static unsigned char clk_map_imx8qm[2][ASRC_CLK_MAP_LEN] =;

static unsigned char clk_map_imx8qxp[2][ASRC_CLK_MAP_LEN] =;

/*
 * According to RM, the divider range is 1 ~ 8,
 * prescaler is power of 2 from 1 ~ 128.
 */
static int asrc_clk_divider[DIVIDER_NUM] =;

/*
 * Check if the divider is available for internal ratio mode
 */
static bool fsl_asrc_divider_avail(int clk_rate, int rate, int *div)
{}

/**
 * fsl_asrc_sel_proc - Select the pre-processing and post-processing options
 * @inrate: input sample rate
 * @outrate: output sample rate
 * @pre_proc: return value for pre-processing option
 * @post_proc: return value for post-processing option
 *
 * Make sure to exclude following unsupported cases before
 * calling this function:
 * 1) inrate > 8.125 * outrate
 * 2) inrate > 16.125 * outrate
 *
 */
static void fsl_asrc_sel_proc(int inrate, int outrate,
			     int *pre_proc, int *post_proc)
{}

/**
 * fsl_asrc_request_pair - Request ASRC pair
 * @channels: number of channels
 * @pair: pointer to pair
 *
 * It assigns pair by the order of A->C->B because allocation of pair B,
 * within range [ANCA, ANCA+ANCB-1], depends on the channels of pair A
 * while pair A and pair C are comparatively independent.
 */
static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair)
{}

/**
 * fsl_asrc_release_pair - Release ASRC pair
 * @pair: pair to release
 *
 * It clears the resource from asrc and releases the occupied channels.
 */
static void fsl_asrc_release_pair(struct fsl_asrc_pair *pair)
{}

/**
 * fsl_asrc_set_watermarks- configure input and output thresholds
 * @pair: pointer to pair
 * @in: input threshold
 * @out: output threshold
 */
static void fsl_asrc_set_watermarks(struct fsl_asrc_pair *pair, u32 in, u32 out)
{}

/**
 * fsl_asrc_cal_asrck_divisor - Calculate the total divisor between asrck clock rate and sample rate
 * @pair: pointer to pair
 * @div: divider
 *
 * It follows the formula clk_rate = samplerate * (2 ^ prescaler) * divider
 */
static u32 fsl_asrc_cal_asrck_divisor(struct fsl_asrc_pair *pair, u32 div)
{}

/**
 * fsl_asrc_set_ideal_ratio - Calculate and set the ratio for Ideal Ratio mode only
 * @pair: pointer to pair
 * @inrate: input rate
 * @outrate: output rate
 *
 * The ratio is a 32-bit fixed point value with 26 fractional bits.
 */
static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair,
				    int inrate, int outrate)
{}

/**
 * fsl_asrc_config_pair - Configure the assigned ASRC pair
 * @pair: pointer to pair
 * @use_ideal_rate: boolean configuration
 *
 * It configures those ASRC registers according to a configuration instance
 * of struct asrc_config which includes in/output sample rate, width, channel
 * and clock settings.
 *
 * Note:
 * The ideal ratio configuration can work with a flexible clock rate setting.
 * Using IDEAL_RATIO_RATE gives a faster converting speed but overloads ASRC.
 * For a regular audio playback, the clock rate should not be slower than an
 * clock rate aligning with the output sample rate; For a use case requiring
 * faster conversion, set use_ideal_rate to have the faster speed.
 */
static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair, bool use_ideal_rate)
{}

/**
 * fsl_asrc_start_pair - Start the assigned ASRC pair
 * @pair: pointer to pair
 *
 * It enables the assigned pair and makes it stopped at the stall level.
 */
static void fsl_asrc_start_pair(struct fsl_asrc_pair *pair)
{}

/**
 * fsl_asrc_stop_pair - Stop the assigned ASRC pair
 * @pair: pointer to pair
 */
static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair)
{}

/**
 * fsl_asrc_get_dma_channel- Get DMA channel according to the pair and direction.
 * @pair: pointer to pair
 * @dir: DMA direction
 */
static struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair,
						 bool dir)
{}

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

/* Select proper clock source for internal ratio mode */
static void fsl_asrc_select_clk(struct fsl_asrc_priv *asrc_priv,
				struct fsl_asrc_pair *pair,
				int in_rate,
				int out_rate)
{}

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

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

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

static int fsl_asrc_dai_probe(struct snd_soc_dai *dai)
{}

static const struct snd_soc_dai_ops fsl_asrc_dai_ops =;

#define FSL_ASRC_FORMATS

static struct snd_soc_dai_driver fsl_asrc_dai =;

static bool fsl_asrc_readable_reg(struct device *dev, unsigned int reg)
{}

static bool fsl_asrc_volatile_reg(struct device *dev, unsigned int reg)
{}

static bool fsl_asrc_writeable_reg(struct device *dev, unsigned int reg)
{}

static struct reg_default fsl_asrc_reg[] =;

static const struct regmap_config fsl_asrc_regmap_config =;

/**
 * fsl_asrc_init - Initialize ASRC registers with a default configuration
 * @asrc: ASRC context
 */
static int fsl_asrc_init(struct fsl_asrc *asrc)
{}

/**
 * fsl_asrc_isr- Interrupt handler for ASRC
 * @irq: irq number
 * @dev_id: ASRC context
 */
static irqreturn_t fsl_asrc_isr(int irq, void *dev_id)
{}

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

static int fsl_asrc_runtime_resume(struct device *dev);
static int fsl_asrc_runtime_suspend(struct device *dev);

static int fsl_asrc_probe(struct platform_device *pdev)
{}

static void fsl_asrc_remove(struct platform_device *pdev)
{}

static int fsl_asrc_runtime_resume(struct device *dev)
{}

static int fsl_asrc_runtime_suspend(struct device *dev)
{}

static const struct dev_pm_ops fsl_asrc_pm =;

static const struct fsl_asrc_soc_data fsl_asrc_imx35_data =;

static const struct fsl_asrc_soc_data fsl_asrc_imx53_data =;

static const struct fsl_asrc_soc_data fsl_asrc_imx8qm_data =;

static const struct fsl_asrc_soc_data fsl_asrc_imx8qxp_data =;

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

static struct platform_driver fsl_asrc_driver =;
module_platform_driver();

MODULE_DESCRIPTION();
MODULE_AUTHOR();
MODULE_ALIAS();
MODULE_LICENSE();