linux/sound/soc/atmel/mchp-i2s-mcc.c

// SPDX-License-Identifier: GPL-2.0
//
// Driver for Microchip I2S Multi-channel controller
//
// Copyright (C) 2018 Microchip Technology Inc. and its subsidiaries
//
// Author: Codrin Ciubotariu <[email protected]>

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/slab.h>

#include <linux/delay.h>
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/mfd/syscon.h>
#include <linux/lcm.h>
#include <linux/of.h>

#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>

/*
 * ---- I2S Controller Register map ----
 */
#define MCHP_I2SMCC_CR
#define MCHP_I2SMCC_MRA
#define MCHP_I2SMCC_MRB
#define MCHP_I2SMCC_SR
#define MCHP_I2SMCC_IERA
#define MCHP_I2SMCC_IDRA
#define MCHP_I2SMCC_IMRA
#define MCHP_I2SMCC_ISRA

#define MCHP_I2SMCC_IERB
#define MCHP_I2SMCC_IDRB
#define MCHP_I2SMCC_IMRB
#define MCHP_I2SMCC_ISRB

#define MCHP_I2SMCC_RHR
#define MCHP_I2SMCC_THR

#define MCHP_I2SMCC_RHL0R
#define MCHP_I2SMCC_RHR0R

#define MCHP_I2SMCC_RHL1R
#define MCHP_I2SMCC_RHR1R

#define MCHP_I2SMCC_RHL2R
#define MCHP_I2SMCC_RHR2R

#define MCHP_I2SMCC_RHL3R
#define MCHP_I2SMCC_RHR3R

#define MCHP_I2SMCC_THL0R
#define MCHP_I2SMCC_THR0R

#define MCHP_I2SMCC_THL1R
#define MCHP_I2SMCC_THR1R

#define MCHP_I2SMCC_THL2R
#define MCHP_I2SMCC_THR2R

#define MCHP_I2SMCC_THL3R
#define MCHP_I2SMCC_THR3R

#define MCHP_I2SMCC_VERSION

/*
 * ---- Control Register (Write-only) ----
 */
#define MCHP_I2SMCC_CR_RXEN
#define MCHP_I2SMCC_CR_RXDIS
#define MCHP_I2SMCC_CR_CKEN
#define MCHP_I2SMCC_CR_CKDIS
#define MCHP_I2SMCC_CR_TXEN
#define MCHP_I2SMCC_CR_TXDIS
#define MCHP_I2SMCC_CR_SWRST

/*
 * ---- Mode Register A (Read/Write) ----
 */
#define MCHP_I2SMCC_MRA_MODE_MASK
#define MCHP_I2SMCC_MRA_MODE_SLAVE
#define MCHP_I2SMCC_MRA_MODE_MASTER

#define MCHP_I2SMCC_MRA_DATALENGTH_MASK
#define MCHP_I2SMCC_MRA_DATALENGTH_32_BITS
#define MCHP_I2SMCC_MRA_DATALENGTH_24_BITS
#define MCHP_I2SMCC_MRA_DATALENGTH_20_BITS
#define MCHP_I2SMCC_MRA_DATALENGTH_18_BITS
#define MCHP_I2SMCC_MRA_DATALENGTH_16_BITS
#define MCHP_I2SMCC_MRA_DATALENGTH_16_BITS_COMPACT
#define MCHP_I2SMCC_MRA_DATALENGTH_8_BITS
#define MCHP_I2SMCC_MRA_DATALENGTH_8_BITS_COMPACT

#define MCHP_I2SMCC_MRA_WIRECFG_MASK
#define MCHP_I2SMCC_MRA_WIRECFG_TDM(pin)
#define MCHP_I2SMCC_MRA_WIRECFG_I2S_1_TDM_0
#define MCHP_I2SMCC_MRA_WIRECFG_I2S_2_TDM_1
#define MCHP_I2SMCC_MRA_WIRECFG_I2S_4_TDM_2
#define MCHP_I2SMCC_MRA_WIRECFG_TDM_3

#define MCHP_I2SMCC_MRA_FORMAT_MASK
#define MCHP_I2SMCC_MRA_FORMAT_I2S
#define MCHP_I2SMCC_MRA_FORMAT_LJ
#define MCHP_I2SMCC_MRA_FORMAT_TDM
#define MCHP_I2SMCC_MRA_FORMAT_TDMLJ

/* Transmitter uses one DMA channel ... */
/* Left audio samples duplicated to right audio channel */
#define MCHP_I2SMCC_MRA_RXMONO

/* I2SDO output of I2SC is internally connected to I2SDI input */
#define MCHP_I2SMCC_MRA_RXLOOP

/* Receiver uses one DMA channel ... */
/* Left audio samples duplicated to right audio channel */
#define MCHP_I2SMCC_MRA_TXMONO

/* x sample transmitted when underrun */
#define MCHP_I2SMCC_MRA_TXSAME_ZERO
#define MCHP_I2SMCC_MRA_TXSAME_PREVIOUS

/* select between peripheral clock and generated clock */
#define MCHP_I2SMCC_MRA_SRCCLK_PCLK
#define MCHP_I2SMCC_MRA_SRCCLK_GCLK

/* Number of TDM Channels - 1 */
#define MCHP_I2SMCC_MRA_NBCHAN_MASK
#define MCHP_I2SMCC_MRA_NBCHAN(ch)

/* Selected Clock to I2SMCC Master Clock ratio */
#define MCHP_I2SMCC_MRA_IMCKDIV_MASK
#define MCHP_I2SMCC_MRA_IMCKDIV(div)

/* TDM Frame Synchronization */
#define MCHP_I2SMCC_MRA_TDMFS_MASK
#define MCHP_I2SMCC_MRA_TDMFS_SLOT
#define MCHP_I2SMCC_MRA_TDMFS_HALF
#define MCHP_I2SMCC_MRA_TDMFS_BIT

/* Selected Clock to I2SMC Serial Clock ratio */
#define MCHP_I2SMCC_MRA_ISCKDIV_MASK
#define MCHP_I2SMCC_MRA_ISCKDIV(div)

/* Master Clock mode */
#define MCHP_I2SMCC_MRA_IMCKMODE_MASK
/* 0: No master clock generated*/
#define MCHP_I2SMCC_MRA_IMCKMODE_NONE
/* 1: master clock generated (internally generated clock drives I2SMCK pin) */
#define MCHP_I2SMCC_MRA_IMCKMODE_GEN

/* Slot Width */
/* 0: slot is 32 bits wide for DATALENGTH = 18/20/24 bits. */
/* 1: slot is 24 bits wide for DATALENGTH = 18/20/24 bits. */
#define MCHP_I2SMCC_MRA_IWS

/*
 * ---- Mode Register B (Read/Write) ----
 */
/* all enabled I2S left channels are filled first, then I2S right channels */
#define MCHP_I2SMCC_MRB_CRAMODE_LEFT_FIRST
/*
 * an enabled I2S left channel is filled, then the corresponding right
 * channel, until all channels are filled
 */
#define MCHP_I2SMCC_MRB_CRAMODE_REGULAR

#define MCHP_I2SMCC_MRB_FIFOEN

#define MCHP_I2SMCC_MRB_DMACHUNK_MASK
#define MCHP_I2SMCC_MRB_DMACHUNK(no_words)

#define MCHP_I2SMCC_MRB_CLKSEL_MASK
#define MCHP_I2SMCC_MRB_CLKSEL_EXT
#define MCHP_I2SMCC_MRB_CLKSEL_INT

/*
 * ---- Status Registers (Read-only) ----
 */
#define MCHP_I2SMCC_SR_RXEN
#define MCHP_I2SMCC_SR_TXEN

/*
 * ---- Interrupt Enable/Disable/Mask/Status Registers A ----
 */
#define MCHP_I2SMCC_INT_TXRDY_MASK(ch)
#define MCHP_I2SMCC_INT_TXRDYCH(ch)
#define MCHP_I2SMCC_INT_TXUNF_MASK(ch)
#define MCHP_I2SMCC_INT_TXUNFCH(ch)
#define MCHP_I2SMCC_INT_RXRDY_MASK(ch)
#define MCHP_I2SMCC_INT_RXRDYCH(ch)
#define MCHP_I2SMCC_INT_RXOVF_MASK(ch)
#define MCHP_I2SMCC_INT_RXOVFCH(ch)

/*
 * ---- Interrupt Enable/Disable/Mask/Status Registers B ----
 */
#define MCHP_I2SMCC_INT_WERR
#define MCHP_I2SMCC_INT_TXFFRDY
#define MCHP_I2SMCC_INT_TXFFEMP
#define MCHP_I2SMCC_INT_RXFFRDY
#define MCHP_I2SMCC_INT_RXFFFUL

/*
 * ---- Version Register (Read-only) ----
 */
#define MCHP_I2SMCC_VERSION_MASK

#define MCHP_I2SMCC_MAX_CHANNELS
#define MCHP_I2MCC_TDM_SLOT_WIDTH

static const struct regmap_config mchp_i2s_mcc_regmap_config =;

struct mchp_i2s_mcc_soc_data {};

struct mchp_i2s_mcc_dev {};

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

static int mchp_i2s_mcc_set_sysclk(struct snd_soc_dai *dai,
				   int clk_id, unsigned int freq, int dir)
{}

static int mchp_i2s_mcc_set_bclk_ratio(struct snd_soc_dai *dai,
				       unsigned int ratio)
{}

static int mchp_i2s_mcc_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{}

static int mchp_i2s_mcc_set_dai_tdm_slot(struct snd_soc_dai *dai,
					 unsigned int tx_mask,
					 unsigned int rx_mask,
					 int slots, int slot_width)
{}

static int mchp_i2s_mcc_clk_get_rate_diff(struct clk *clk,
					  unsigned long rate,
					  struct clk **best_clk,
					  unsigned long *best_rate,
					  unsigned long *best_diff_rate)
{}

static int mchp_i2s_mcc_config_divs(struct mchp_i2s_mcc_dev *dev,
				    unsigned int bclk, unsigned int *mra,
				    unsigned long *best_rate)
{}

static int mchp_i2s_mcc_is_running(struct mchp_i2s_mcc_dev *dev)
{}

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

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

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

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

static int mchp_i2s_mcc_dai_probe(struct snd_soc_dai *dai)
{}

static const struct snd_soc_dai_ops mchp_i2s_mcc_dai_ops =;

#define MCHP_I2SMCC_RATES

#define MCHP_I2SMCC_FORMATS

static struct snd_soc_dai_driver mchp_i2s_mcc_dai =;

static const struct snd_soc_component_driver mchp_i2s_mcc_component =;

#ifdef CONFIG_OF
static struct mchp_i2s_mcc_soc_data mchp_i2s_mcc_sam9x60 =;

static struct mchp_i2s_mcc_soc_data mchp_i2s_mcc_sama7g5 =;

static const struct of_device_id mchp_i2s_mcc_dt_ids[] =;
MODULE_DEVICE_TABLE(of, mchp_i2s_mcc_dt_ids);
#endif

static int mchp_i2s_mcc_soc_data_parse(struct platform_device *pdev,
				       struct mchp_i2s_mcc_dev *dev)
{}

static int mchp_i2s_mcc_probe(struct platform_device *pdev)
{}

static void mchp_i2s_mcc_remove(struct platform_device *pdev)
{}

static struct platform_driver mchp_i2s_mcc_driver =;
module_platform_driver();

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