cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

cygnus-ssp.c (38805B)


      1/*
      2 * Copyright (C) 2014-2015 Broadcom Corporation
      3 *
      4 * This program is free software; you can redistribute it and/or
      5 * modify it under the terms of the GNU General Public License as
      6 * published by the Free Software Foundation version 2.
      7 *
      8 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
      9 * kind, whether express or implied; without even the implied warranty
     10 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     11 * GNU General Public License for more details.
     12 */
     13#include <linux/clk.h>
     14#include <linux/delay.h>
     15#include <linux/init.h>
     16#include <linux/io.h>
     17#include <linux/module.h>
     18#include <linux/of_device.h>
     19#include <linux/slab.h>
     20#include <sound/core.h>
     21#include <sound/pcm.h>
     22#include <sound/pcm_params.h>
     23#include <sound/soc.h>
     24#include <sound/soc-dai.h>
     25
     26#include "cygnus-ssp.h"
     27
     28#define DEFAULT_VCO    1354750204
     29
     30#define CAPTURE_FCI_ID_BASE 0x180
     31#define CYGNUS_SSP_TRISTATE_MASK 0x001fff
     32#define CYGNUS_PLLCLKSEL_MASK 0xf
     33
     34/* Used with stream_on field to indicate which streams are active */
     35#define  PLAYBACK_STREAM_MASK   BIT(0)
     36#define  CAPTURE_STREAM_MASK    BIT(1)
     37
     38#define I2S_STREAM_CFG_MASK      0xff003ff
     39#define I2S_CAP_STREAM_CFG_MASK  0xf0
     40#define SPDIF_STREAM_CFG_MASK    0x3ff
     41#define CH_GRP_STEREO            0x1
     42
     43/* Begin register offset defines */
     44#define AUD_MISC_SEROUT_OE_REG_BASE  0x01c
     45#define AUD_MISC_SEROUT_SPDIF_OE  12
     46#define AUD_MISC_SEROUT_MCLK_OE   3
     47#define AUD_MISC_SEROUT_LRCK_OE   2
     48#define AUD_MISC_SEROUT_SCLK_OE   1
     49#define AUD_MISC_SEROUT_SDAT_OE   0
     50
     51/* AUD_FMM_BF_CTRL_xxx regs */
     52#define BF_DST_CFG0_OFFSET  0x100
     53#define BF_DST_CFG1_OFFSET  0x104
     54#define BF_DST_CFG2_OFFSET  0x108
     55
     56#define BF_DST_CTRL0_OFFSET 0x130
     57#define BF_DST_CTRL1_OFFSET 0x134
     58#define BF_DST_CTRL2_OFFSET 0x138
     59
     60#define BF_SRC_CFG0_OFFSET  0x148
     61#define BF_SRC_CFG1_OFFSET  0x14c
     62#define BF_SRC_CFG2_OFFSET  0x150
     63#define BF_SRC_CFG3_OFFSET  0x154
     64
     65#define BF_SRC_CTRL0_OFFSET 0x1c0
     66#define BF_SRC_CTRL1_OFFSET 0x1c4
     67#define BF_SRC_CTRL2_OFFSET 0x1c8
     68#define BF_SRC_CTRL3_OFFSET 0x1cc
     69
     70#define BF_SRC_GRP0_OFFSET  0x1fc
     71#define BF_SRC_GRP1_OFFSET  0x200
     72#define BF_SRC_GRP2_OFFSET  0x204
     73#define BF_SRC_GRP3_OFFSET  0x208
     74
     75#define BF_SRC_GRP_EN_OFFSET        0x320
     76#define BF_SRC_GRP_FLOWON_OFFSET    0x324
     77#define BF_SRC_GRP_SYNC_DIS_OFFSET  0x328
     78
     79/* AUD_FMM_IOP_OUT_I2S_xxx regs */
     80#define OUT_I2S_0_STREAM_CFG_OFFSET 0xa00
     81#define OUT_I2S_0_CFG_OFFSET        0xa04
     82#define OUT_I2S_0_MCLK_CFG_OFFSET   0xa0c
     83
     84#define OUT_I2S_1_STREAM_CFG_OFFSET 0xa40
     85#define OUT_I2S_1_CFG_OFFSET        0xa44
     86#define OUT_I2S_1_MCLK_CFG_OFFSET   0xa4c
     87
     88#define OUT_I2S_2_STREAM_CFG_OFFSET 0xa80
     89#define OUT_I2S_2_CFG_OFFSET        0xa84
     90#define OUT_I2S_2_MCLK_CFG_OFFSET   0xa8c
     91
     92/* AUD_FMM_IOP_OUT_SPDIF_xxx regs */
     93#define SPDIF_STREAM_CFG_OFFSET  0xac0
     94#define SPDIF_CTRL_OFFSET        0xac4
     95#define SPDIF_FORMAT_CFG_OFFSET  0xad8
     96#define SPDIF_MCLK_CFG_OFFSET    0xadc
     97
     98/* AUD_FMM_IOP_PLL_0_xxx regs */
     99#define IOP_PLL_0_MACRO_OFFSET    0xb00
    100#define IOP_PLL_0_MDIV_Ch0_OFFSET 0xb14
    101#define IOP_PLL_0_MDIV_Ch1_OFFSET 0xb18
    102#define IOP_PLL_0_MDIV_Ch2_OFFSET 0xb1c
    103
    104#define IOP_PLL_0_ACTIVE_MDIV_Ch0_OFFSET 0xb30
    105#define IOP_PLL_0_ACTIVE_MDIV_Ch1_OFFSET 0xb34
    106#define IOP_PLL_0_ACTIVE_MDIV_Ch2_OFFSET 0xb38
    107
    108/* AUD_FMM_IOP_xxx regs */
    109#define IOP_PLL_0_CONTROL_OFFSET     0xb04
    110#define IOP_PLL_0_USER_NDIV_OFFSET   0xb08
    111#define IOP_PLL_0_ACTIVE_NDIV_OFFSET 0xb20
    112#define IOP_PLL_0_RESET_OFFSET       0xb5c
    113
    114/* AUD_FMM_IOP_IN_I2S_xxx regs */
    115#define IN_I2S_0_STREAM_CFG_OFFSET 0x00
    116#define IN_I2S_0_CFG_OFFSET        0x04
    117#define IN_I2S_1_STREAM_CFG_OFFSET 0x40
    118#define IN_I2S_1_CFG_OFFSET        0x44
    119#define IN_I2S_2_STREAM_CFG_OFFSET 0x80
    120#define IN_I2S_2_CFG_OFFSET        0x84
    121
    122/* AUD_FMM_IOP_MISC_xxx regs */
    123#define IOP_SW_INIT_LOGIC          0x1c0
    124
    125/* End register offset defines */
    126
    127
    128/* AUD_FMM_IOP_OUT_I2S_x_MCLK_CFG_0_REG */
    129#define I2S_OUT_MCLKRATE_SHIFT 16
    130
    131/* AUD_FMM_IOP_OUT_I2S_x_MCLK_CFG_REG */
    132#define I2S_OUT_PLLCLKSEL_SHIFT  0
    133
    134/* AUD_FMM_IOP_OUT_I2S_x_STREAM_CFG */
    135#define I2S_OUT_STREAM_ENA  31
    136#define I2S_OUT_STREAM_CFG_GROUP_ID  20
    137#define I2S_OUT_STREAM_CFG_CHANNEL_GROUPING  24
    138
    139/* AUD_FMM_IOP_IN_I2S_x_CAP */
    140#define I2S_IN_STREAM_CFG_CAP_ENA   31
    141#define I2S_IN_STREAM_CFG_0_GROUP_ID 4
    142
    143/* AUD_FMM_IOP_OUT_I2S_x_I2S_CFG_REG */
    144#define I2S_OUT_CFGX_CLK_ENA         0
    145#define I2S_OUT_CFGX_DATA_ENABLE     1
    146#define I2S_OUT_CFGX_DATA_ALIGNMENT  6
    147#define I2S_OUT_CFGX_BITS_PER_SLOT  13
    148#define I2S_OUT_CFGX_VALID_SLOT     14
    149#define I2S_OUT_CFGX_FSYNC_WIDTH    18
    150#define I2S_OUT_CFGX_SCLKS_PER_1FS_DIV32 26
    151#define I2S_OUT_CFGX_SLAVE_MODE     30
    152#define I2S_OUT_CFGX_TDM_MODE       31
    153
    154/* AUD_FMM_BF_CTRL_SOURCECH_CFGx_REG */
    155#define BF_SRC_CFGX_SFIFO_ENA              0
    156#define BF_SRC_CFGX_BUFFER_PAIR_ENABLE     1
    157#define BF_SRC_CFGX_SAMPLE_CH_MODE         2
    158#define BF_SRC_CFGX_SFIFO_SZ_DOUBLE        5
    159#define BF_SRC_CFGX_NOT_PAUSE_WHEN_EMPTY  10
    160#define BF_SRC_CFGX_BIT_RES               20
    161#define BF_SRC_CFGX_PROCESS_SEQ_ID_VALID  31
    162
    163/* AUD_FMM_BF_CTRL_DESTCH_CFGx_REG */
    164#define BF_DST_CFGX_CAP_ENA              0
    165#define BF_DST_CFGX_BUFFER_PAIR_ENABLE   1
    166#define BF_DST_CFGX_DFIFO_SZ_DOUBLE      2
    167#define BF_DST_CFGX_NOT_PAUSE_WHEN_FULL 11
    168#define BF_DST_CFGX_FCI_ID              12
    169#define BF_DST_CFGX_CAP_MODE            24
    170#define BF_DST_CFGX_PROC_SEQ_ID_VALID   31
    171
    172/* AUD_FMM_IOP_OUT_SPDIF_xxx */
    173#define SPDIF_0_OUT_DITHER_ENA     3
    174#define SPDIF_0_OUT_STREAM_ENA    31
    175
    176/* AUD_FMM_IOP_PLL_0_USER */
    177#define IOP_PLL_0_USER_NDIV_FRAC   10
    178
    179/* AUD_FMM_IOP_PLL_0_ACTIVE */
    180#define IOP_PLL_0_ACTIVE_NDIV_FRAC 10
    181
    182
    183#define INIT_SSP_REGS(num) (struct cygnus_ssp_regs){ \
    184		.i2s_stream_cfg = OUT_I2S_ ##num## _STREAM_CFG_OFFSET, \
    185		.i2s_cap_stream_cfg = IN_I2S_ ##num## _STREAM_CFG_OFFSET, \
    186		.i2s_cfg = OUT_I2S_ ##num## _CFG_OFFSET, \
    187		.i2s_cap_cfg = IN_I2S_ ##num## _CFG_OFFSET, \
    188		.i2s_mclk_cfg = OUT_I2S_ ##num## _MCLK_CFG_OFFSET, \
    189		.bf_destch_ctrl = BF_DST_CTRL ##num## _OFFSET, \
    190		.bf_destch_cfg = BF_DST_CFG ##num## _OFFSET, \
    191		.bf_sourcech_ctrl = BF_SRC_CTRL ##num## _OFFSET, \
    192		.bf_sourcech_cfg = BF_SRC_CFG ##num## _OFFSET, \
    193		.bf_sourcech_grp = BF_SRC_GRP ##num## _OFFSET \
    194}
    195
    196struct pll_macro_entry {
    197	u32 mclk;
    198	u32 pll_ch_num;
    199};
    200
    201/*
    202 * PLL has 3 output channels (1x, 2x, and 4x). Below are
    203 * the common MCLK frequencies used by audio driver
    204 */
    205static const struct pll_macro_entry pll_predef_mclk[] = {
    206	{ 4096000, 0},
    207	{ 8192000, 1},
    208	{16384000, 2},
    209
    210	{ 5644800, 0},
    211	{11289600, 1},
    212	{22579200, 2},
    213
    214	{ 6144000, 0},
    215	{12288000, 1},
    216	{24576000, 2},
    217
    218	{12288000, 0},
    219	{24576000, 1},
    220	{49152000, 2},
    221
    222	{22579200, 0},
    223	{45158400, 1},
    224	{90316800, 2},
    225
    226	{24576000, 0},
    227	{49152000, 1},
    228	{98304000, 2},
    229};
    230
    231#define CYGNUS_RATE_MIN     8000
    232#define CYGNUS_RATE_MAX   384000
    233
    234/* List of valid frame sizes for tdm mode */
    235static const int ssp_valid_tdm_framesize[] = {32, 64, 128, 256, 512};
    236
    237static const unsigned int cygnus_rates[] = {
    238	 8000, 11025,  16000,  22050,  32000,  44100, 48000,
    239	88200, 96000, 176400, 192000, 352800, 384000
    240};
    241
    242static const struct snd_pcm_hw_constraint_list cygnus_rate_constraint = {
    243	.count = ARRAY_SIZE(cygnus_rates),
    244	.list = cygnus_rates,
    245};
    246
    247static struct cygnus_aio_port *cygnus_dai_get_portinfo(struct snd_soc_dai *dai)
    248{
    249	struct cygnus_audio *cygaud = snd_soc_dai_get_drvdata(dai);
    250
    251	return &cygaud->portinfo[dai->id];
    252}
    253
    254static int audio_ssp_init_portregs(struct cygnus_aio_port *aio)
    255{
    256	u32 value, fci_id;
    257	int status = 0;
    258
    259	switch (aio->port_type) {
    260	case PORT_TDM:
    261		value = readl(aio->cygaud->audio + aio->regs.i2s_stream_cfg);
    262		value &= ~I2S_STREAM_CFG_MASK;
    263
    264		/* Set Group ID */
    265		writel(aio->portnum,
    266			aio->cygaud->audio + aio->regs.bf_sourcech_grp);
    267
    268		/* Configure the AUD_FMM_IOP_OUT_I2S_x_STREAM_CFG reg */
    269		value |= aio->portnum << I2S_OUT_STREAM_CFG_GROUP_ID;
    270		value |= aio->portnum; /* FCI ID is the port num */
    271		value |= CH_GRP_STEREO << I2S_OUT_STREAM_CFG_CHANNEL_GROUPING;
    272		writel(value, aio->cygaud->audio + aio->regs.i2s_stream_cfg);
    273
    274		/* Configure the AUD_FMM_BF_CTRL_SOURCECH_CFGX reg */
    275		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    276		value &= ~BIT(BF_SRC_CFGX_NOT_PAUSE_WHEN_EMPTY);
    277		value |= BIT(BF_SRC_CFGX_SFIFO_SZ_DOUBLE);
    278		value |= BIT(BF_SRC_CFGX_PROCESS_SEQ_ID_VALID);
    279		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    280
    281		/* Configure the AUD_FMM_IOP_IN_I2S_x_CAP_STREAM_CFG_0 reg */
    282		value = readl(aio->cygaud->i2s_in +
    283			aio->regs.i2s_cap_stream_cfg);
    284		value &= ~I2S_CAP_STREAM_CFG_MASK;
    285		value |= aio->portnum << I2S_IN_STREAM_CFG_0_GROUP_ID;
    286		writel(value, aio->cygaud->i2s_in +
    287			aio->regs.i2s_cap_stream_cfg);
    288
    289		/* Configure the AUD_FMM_BF_CTRL_DESTCH_CFGX_REG_BASE reg */
    290		fci_id = CAPTURE_FCI_ID_BASE + aio->portnum;
    291
    292		value = readl(aio->cygaud->audio + aio->regs.bf_destch_cfg);
    293		value |= BIT(BF_DST_CFGX_DFIFO_SZ_DOUBLE);
    294		value &= ~BIT(BF_DST_CFGX_NOT_PAUSE_WHEN_FULL);
    295		value |= (fci_id << BF_DST_CFGX_FCI_ID);
    296		value |= BIT(BF_DST_CFGX_PROC_SEQ_ID_VALID);
    297		writel(value, aio->cygaud->audio + aio->regs.bf_destch_cfg);
    298
    299		/* Enable the transmit pin for this port */
    300		value = readl(aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
    301		value &= ~BIT((aio->portnum * 4) + AUD_MISC_SEROUT_SDAT_OE);
    302		writel(value, aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
    303		break;
    304	case PORT_SPDIF:
    305		writel(aio->portnum, aio->cygaud->audio + BF_SRC_GRP3_OFFSET);
    306
    307		value = readl(aio->cygaud->audio + SPDIF_CTRL_OFFSET);
    308		value |= BIT(SPDIF_0_OUT_DITHER_ENA);
    309		writel(value, aio->cygaud->audio + SPDIF_CTRL_OFFSET);
    310
    311		/* Enable and set the FCI ID for the SPDIF channel */
    312		value = readl(aio->cygaud->audio + SPDIF_STREAM_CFG_OFFSET);
    313		value &= ~SPDIF_STREAM_CFG_MASK;
    314		value |= aio->portnum; /* FCI ID is the port num */
    315		value |= BIT(SPDIF_0_OUT_STREAM_ENA);
    316		writel(value, aio->cygaud->audio + SPDIF_STREAM_CFG_OFFSET);
    317
    318		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    319		value &= ~BIT(BF_SRC_CFGX_NOT_PAUSE_WHEN_EMPTY);
    320		value |= BIT(BF_SRC_CFGX_SFIFO_SZ_DOUBLE);
    321		value |= BIT(BF_SRC_CFGX_PROCESS_SEQ_ID_VALID);
    322		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    323
    324		/* Enable the spdif output pin */
    325		value = readl(aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
    326		value &= ~BIT(AUD_MISC_SEROUT_SPDIF_OE);
    327		writel(value, aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
    328		break;
    329	default:
    330		dev_err(aio->cygaud->dev, "Port not supported\n");
    331		status = -EINVAL;
    332	}
    333
    334	return status;
    335}
    336
    337static void audio_ssp_in_enable(struct cygnus_aio_port *aio)
    338{
    339	u32 value;
    340
    341	value = readl(aio->cygaud->audio + aio->regs.bf_destch_cfg);
    342	value |= BIT(BF_DST_CFGX_CAP_ENA);
    343	writel(value, aio->cygaud->audio + aio->regs.bf_destch_cfg);
    344
    345	writel(0x1, aio->cygaud->audio + aio->regs.bf_destch_ctrl);
    346
    347	value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
    348	value |= BIT(I2S_OUT_CFGX_CLK_ENA);
    349	value |= BIT(I2S_OUT_CFGX_DATA_ENABLE);
    350	writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
    351
    352	value = readl(aio->cygaud->i2s_in + aio->regs.i2s_cap_stream_cfg);
    353	value |= BIT(I2S_IN_STREAM_CFG_CAP_ENA);
    354	writel(value, aio->cygaud->i2s_in + aio->regs.i2s_cap_stream_cfg);
    355
    356	aio->streams_on |= CAPTURE_STREAM_MASK;
    357}
    358
    359static void audio_ssp_in_disable(struct cygnus_aio_port *aio)
    360{
    361	u32 value;
    362
    363	value = readl(aio->cygaud->i2s_in + aio->regs.i2s_cap_stream_cfg);
    364	value &= ~BIT(I2S_IN_STREAM_CFG_CAP_ENA);
    365	writel(value, aio->cygaud->i2s_in + aio->regs.i2s_cap_stream_cfg);
    366
    367	aio->streams_on &= ~CAPTURE_STREAM_MASK;
    368
    369	/* If both playback and capture are off */
    370	if (!aio->streams_on) {
    371		value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
    372		value &= ~BIT(I2S_OUT_CFGX_CLK_ENA);
    373		value &= ~BIT(I2S_OUT_CFGX_DATA_ENABLE);
    374		writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
    375	}
    376
    377	writel(0x0, aio->cygaud->audio + aio->regs.bf_destch_ctrl);
    378
    379	value = readl(aio->cygaud->audio + aio->regs.bf_destch_cfg);
    380	value &= ~BIT(BF_DST_CFGX_CAP_ENA);
    381	writel(value, aio->cygaud->audio + aio->regs.bf_destch_cfg);
    382}
    383
    384static int audio_ssp_out_enable(struct cygnus_aio_port *aio)
    385{
    386	u32 value;
    387	int status = 0;
    388
    389	switch (aio->port_type) {
    390	case PORT_TDM:
    391		value = readl(aio->cygaud->audio + aio->regs.i2s_stream_cfg);
    392		value |= BIT(I2S_OUT_STREAM_ENA);
    393		writel(value, aio->cygaud->audio + aio->regs.i2s_stream_cfg);
    394
    395		writel(1, aio->cygaud->audio + aio->regs.bf_sourcech_ctrl);
    396
    397		value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
    398		value |= BIT(I2S_OUT_CFGX_CLK_ENA);
    399		value |= BIT(I2S_OUT_CFGX_DATA_ENABLE);
    400		writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
    401
    402		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    403		value |= BIT(BF_SRC_CFGX_SFIFO_ENA);
    404		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    405
    406		aio->streams_on |= PLAYBACK_STREAM_MASK;
    407		break;
    408	case PORT_SPDIF:
    409		value = readl(aio->cygaud->audio + SPDIF_FORMAT_CFG_OFFSET);
    410		value |= 0x3;
    411		writel(value, aio->cygaud->audio + SPDIF_FORMAT_CFG_OFFSET);
    412
    413		writel(1, aio->cygaud->audio + aio->regs.bf_sourcech_ctrl);
    414
    415		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    416		value |= BIT(BF_SRC_CFGX_SFIFO_ENA);
    417		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    418		break;
    419	default:
    420		dev_err(aio->cygaud->dev,
    421			"Port not supported %d\n", aio->portnum);
    422		status = -EINVAL;
    423	}
    424
    425	return status;
    426}
    427
    428static int audio_ssp_out_disable(struct cygnus_aio_port *aio)
    429{
    430	u32 value;
    431	int status = 0;
    432
    433	switch (aio->port_type) {
    434	case PORT_TDM:
    435		aio->streams_on &= ~PLAYBACK_STREAM_MASK;
    436
    437		/* If both playback and capture are off */
    438		if (!aio->streams_on) {
    439			value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
    440			value &= ~BIT(I2S_OUT_CFGX_CLK_ENA);
    441			value &= ~BIT(I2S_OUT_CFGX_DATA_ENABLE);
    442			writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
    443		}
    444
    445		/* set group_sync_dis = 1 */
    446		value = readl(aio->cygaud->audio + BF_SRC_GRP_SYNC_DIS_OFFSET);
    447		value |= BIT(aio->portnum);
    448		writel(value, aio->cygaud->audio + BF_SRC_GRP_SYNC_DIS_OFFSET);
    449
    450		writel(0, aio->cygaud->audio + aio->regs.bf_sourcech_ctrl);
    451
    452		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    453		value &= ~BIT(BF_SRC_CFGX_SFIFO_ENA);
    454		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    455
    456		/* set group_sync_dis = 0 */
    457		value = readl(aio->cygaud->audio + BF_SRC_GRP_SYNC_DIS_OFFSET);
    458		value &= ~BIT(aio->portnum);
    459		writel(value, aio->cygaud->audio + BF_SRC_GRP_SYNC_DIS_OFFSET);
    460
    461		value = readl(aio->cygaud->audio + aio->regs.i2s_stream_cfg);
    462		value &= ~BIT(I2S_OUT_STREAM_ENA);
    463		writel(value, aio->cygaud->audio + aio->regs.i2s_stream_cfg);
    464
    465		/* IOP SW INIT on OUT_I2S_x */
    466		value = readl(aio->cygaud->i2s_in + IOP_SW_INIT_LOGIC);
    467		value |= BIT(aio->portnum);
    468		writel(value, aio->cygaud->i2s_in + IOP_SW_INIT_LOGIC);
    469		value &= ~BIT(aio->portnum);
    470		writel(value, aio->cygaud->i2s_in + IOP_SW_INIT_LOGIC);
    471		break;
    472	case PORT_SPDIF:
    473		value = readl(aio->cygaud->audio + SPDIF_FORMAT_CFG_OFFSET);
    474		value &= ~0x3;
    475		writel(value, aio->cygaud->audio + SPDIF_FORMAT_CFG_OFFSET);
    476		writel(0, aio->cygaud->audio + aio->regs.bf_sourcech_ctrl);
    477
    478		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    479		value &= ~BIT(BF_SRC_CFGX_SFIFO_ENA);
    480		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    481		break;
    482	default:
    483		dev_err(aio->cygaud->dev,
    484			"Port not supported %d\n", aio->portnum);
    485		status = -EINVAL;
    486	}
    487
    488	return status;
    489}
    490
    491static int pll_configure_mclk(struct cygnus_audio *cygaud, u32 mclk,
    492	struct cygnus_aio_port *aio)
    493{
    494	int i = 0, error;
    495	bool found = false;
    496	const struct pll_macro_entry *p_entry;
    497	struct clk *ch_clk;
    498
    499	for (i = 0; i < ARRAY_SIZE(pll_predef_mclk); i++) {
    500		p_entry = &pll_predef_mclk[i];
    501		if (p_entry->mclk == mclk) {
    502			found = true;
    503			break;
    504		}
    505	}
    506	if (!found) {
    507		dev_err(cygaud->dev,
    508			"%s No valid mclk freq (%u) found!\n", __func__, mclk);
    509		return -EINVAL;
    510	}
    511
    512	ch_clk = cygaud->audio_clk[p_entry->pll_ch_num];
    513
    514	if ((aio->clk_trace.cap_en) && (!aio->clk_trace.cap_clk_en)) {
    515		error = clk_prepare_enable(ch_clk);
    516		if (error) {
    517			dev_err(cygaud->dev, "%s clk_prepare_enable failed %d\n",
    518				__func__, error);
    519			return error;
    520		}
    521		aio->clk_trace.cap_clk_en = true;
    522	}
    523
    524	if ((aio->clk_trace.play_en) && (!aio->clk_trace.play_clk_en)) {
    525		error = clk_prepare_enable(ch_clk);
    526		if (error) {
    527			dev_err(cygaud->dev, "%s clk_prepare_enable failed %d\n",
    528				__func__, error);
    529			return error;
    530		}
    531		aio->clk_trace.play_clk_en = true;
    532	}
    533
    534	error = clk_set_rate(ch_clk, mclk);
    535	if (error) {
    536		dev_err(cygaud->dev, "%s Set MCLK rate failed: %d\n",
    537			__func__, error);
    538		return error;
    539	}
    540
    541	return p_entry->pll_ch_num;
    542}
    543
    544static int cygnus_ssp_set_clocks(struct cygnus_aio_port *aio)
    545{
    546	u32 value;
    547	u32 mask = 0xf;
    548	u32 sclk;
    549	u32 mclk_rate;
    550	unsigned int bit_rate;
    551	unsigned int ratio;
    552
    553	bit_rate = aio->bit_per_frame * aio->lrclk;
    554
    555	/*
    556	 * Check if the bit clock can be generated from the given MCLK.
    557	 * MCLK must be a perfect multiple of bit clock and must be one of the
    558	 * following values... (2,4,6,8,10,12,14)
    559	 */
    560	if ((aio->mclk % bit_rate) != 0)
    561		return -EINVAL;
    562
    563	ratio = aio->mclk / bit_rate;
    564	switch (ratio) {
    565	case 2:
    566	case 4:
    567	case 6:
    568	case 8:
    569	case 10:
    570	case 12:
    571	case 14:
    572		mclk_rate = ratio / 2;
    573		break;
    574
    575	default:
    576		dev_err(aio->cygaud->dev,
    577			"Invalid combination of MCLK and BCLK\n");
    578		dev_err(aio->cygaud->dev, "lrclk = %u, bits/frame = %u, mclk = %u\n",
    579			aio->lrclk, aio->bit_per_frame, aio->mclk);
    580		return -EINVAL;
    581	}
    582
    583	/* Set sclk rate */
    584	switch (aio->port_type) {
    585	case PORT_TDM:
    586		sclk = aio->bit_per_frame;
    587		if (sclk == 512)
    588			sclk = 0;
    589
    590		/* sclks_per_1fs_div = sclk cycles/32 */
    591		sclk /= 32;
    592
    593		/* Set number of bitclks per frame */
    594		value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
    595		value &= ~(mask << I2S_OUT_CFGX_SCLKS_PER_1FS_DIV32);
    596		value |= sclk << I2S_OUT_CFGX_SCLKS_PER_1FS_DIV32;
    597		writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
    598		dev_dbg(aio->cygaud->dev,
    599			"SCLKS_PER_1FS_DIV32 = 0x%x\n", value);
    600		break;
    601	case PORT_SPDIF:
    602		break;
    603	default:
    604		dev_err(aio->cygaud->dev, "Unknown port type\n");
    605		return -EINVAL;
    606	}
    607
    608	/* Set MCLK_RATE ssp port (spdif and ssp are the same) */
    609	value = readl(aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
    610	value &= ~(0xf << I2S_OUT_MCLKRATE_SHIFT);
    611	value |= (mclk_rate << I2S_OUT_MCLKRATE_SHIFT);
    612	writel(value, aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
    613
    614	dev_dbg(aio->cygaud->dev, "mclk cfg reg = 0x%x\n", value);
    615	dev_dbg(aio->cygaud->dev, "bits per frame = %u, mclk = %u Hz, lrclk = %u Hz\n",
    616			aio->bit_per_frame, aio->mclk, aio->lrclk);
    617	return 0;
    618}
    619
    620static int cygnus_ssp_hw_params(struct snd_pcm_substream *substream,
    621				 struct snd_pcm_hw_params *params,
    622				 struct snd_soc_dai *dai)
    623{
    624	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
    625	int rate, bitres;
    626	u32 value;
    627	u32 mask = 0x1f;
    628	int ret = 0;
    629
    630	dev_dbg(aio->cygaud->dev, "%s port = %d\n", __func__, aio->portnum);
    631	dev_dbg(aio->cygaud->dev, "params_channels %d\n",
    632			params_channels(params));
    633	dev_dbg(aio->cygaud->dev, "rate %d\n", params_rate(params));
    634	dev_dbg(aio->cygaud->dev, "format %d\n", params_format(params));
    635
    636	rate = params_rate(params);
    637
    638	switch (aio->mode) {
    639	case CYGNUS_SSPMODE_TDM:
    640		if ((rate == 192000) && (params_channels(params) > 4)) {
    641			dev_err(aio->cygaud->dev, "Cannot run %d channels at %dHz\n",
    642				params_channels(params), rate);
    643			return -EINVAL;
    644		}
    645		break;
    646	case CYGNUS_SSPMODE_I2S:
    647		aio->bit_per_frame = 64; /* I2S must be 64 bit per frame */
    648		break;
    649	default:
    650		dev_err(aio->cygaud->dev,
    651			"%s port running in unknown mode\n", __func__);
    652		return -EINVAL;
    653	}
    654
    655	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    656		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    657		value &= ~BIT(BF_SRC_CFGX_BUFFER_PAIR_ENABLE);
    658		value &= ~BIT(BF_SRC_CFGX_SAMPLE_CH_MODE);
    659		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    660
    661		switch (params_format(params)) {
    662		case SNDRV_PCM_FORMAT_S16_LE:
    663			bitres = 16;
    664			break;
    665
    666		case SNDRV_PCM_FORMAT_S32_LE:
    667			/* 32 bit mode is coded as 0 */
    668			bitres = 0;
    669			break;
    670
    671		default:
    672			return -EINVAL;
    673		}
    674
    675		value = readl(aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    676		value &= ~(mask << BF_SRC_CFGX_BIT_RES);
    677		value |= (bitres << BF_SRC_CFGX_BIT_RES);
    678		writel(value, aio->cygaud->audio + aio->regs.bf_sourcech_cfg);
    679
    680	} else {
    681
    682		switch (params_format(params)) {
    683		case SNDRV_PCM_FORMAT_S16_LE:
    684			value = readl(aio->cygaud->audio +
    685					aio->regs.bf_destch_cfg);
    686			value |= BIT(BF_DST_CFGX_CAP_MODE);
    687			writel(value, aio->cygaud->audio +
    688					aio->regs.bf_destch_cfg);
    689			break;
    690
    691		case SNDRV_PCM_FORMAT_S32_LE:
    692			value = readl(aio->cygaud->audio +
    693					aio->regs.bf_destch_cfg);
    694			value &= ~BIT(BF_DST_CFGX_CAP_MODE);
    695			writel(value, aio->cygaud->audio +
    696					aio->regs.bf_destch_cfg);
    697			break;
    698
    699		default:
    700			return -EINVAL;
    701		}
    702	}
    703
    704	aio->lrclk = rate;
    705
    706	if (!aio->is_slave)
    707		ret = cygnus_ssp_set_clocks(aio);
    708
    709	return ret;
    710}
    711
    712/*
    713 * This function sets the mclk frequency for pll clock
    714 */
    715static int cygnus_ssp_set_sysclk(struct snd_soc_dai *dai,
    716			int clk_id, unsigned int freq, int dir)
    717{
    718	int sel;
    719	u32 value;
    720	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
    721	struct cygnus_audio *cygaud = snd_soc_dai_get_drvdata(dai);
    722
    723	dev_dbg(aio->cygaud->dev,
    724		"%s Enter port = %d\n", __func__, aio->portnum);
    725	sel = pll_configure_mclk(cygaud, freq, aio);
    726	if (sel < 0) {
    727		dev_err(aio->cygaud->dev,
    728			"%s Setting mclk failed.\n", __func__);
    729		return -EINVAL;
    730	}
    731
    732	aio->mclk = freq;
    733
    734	dev_dbg(aio->cygaud->dev, "%s Setting MCLKSEL to %d\n", __func__, sel);
    735	value = readl(aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
    736	value &= ~(0xf << I2S_OUT_PLLCLKSEL_SHIFT);
    737	value |= (sel << I2S_OUT_PLLCLKSEL_SHIFT);
    738	writel(value, aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
    739
    740	return 0;
    741}
    742
    743static int cygnus_ssp_startup(struct snd_pcm_substream *substream,
    744			       struct snd_soc_dai *dai)
    745{
    746	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
    747
    748	snd_soc_dai_set_dma_data(dai, substream, aio);
    749	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    750		aio->clk_trace.play_en = true;
    751	else
    752		aio->clk_trace.cap_en = true;
    753
    754	substream->runtime->hw.rate_min = CYGNUS_RATE_MIN;
    755	substream->runtime->hw.rate_max = CYGNUS_RATE_MAX;
    756
    757	snd_pcm_hw_constraint_list(substream->runtime, 0,
    758			SNDRV_PCM_HW_PARAM_RATE, &cygnus_rate_constraint);
    759	return 0;
    760}
    761
    762static void cygnus_ssp_shutdown(struct snd_pcm_substream *substream,
    763			       struct snd_soc_dai *dai)
    764{
    765	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
    766
    767	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    768		aio->clk_trace.play_en = false;
    769	else
    770		aio->clk_trace.cap_en = false;
    771
    772	if (!aio->is_slave) {
    773		u32 val;
    774
    775		val = readl(aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
    776		val &= CYGNUS_PLLCLKSEL_MASK;
    777		if (val >= ARRAY_SIZE(aio->cygaud->audio_clk)) {
    778			dev_err(aio->cygaud->dev, "Clk index %u is out of bounds\n",
    779				val);
    780			return;
    781		}
    782
    783		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
    784			if (aio->clk_trace.play_clk_en) {
    785				clk_disable_unprepare(aio->cygaud->
    786						audio_clk[val]);
    787				aio->clk_trace.play_clk_en = false;
    788			}
    789		} else {
    790			if (aio->clk_trace.cap_clk_en) {
    791				clk_disable_unprepare(aio->cygaud->
    792						audio_clk[val]);
    793				aio->clk_trace.cap_clk_en = false;
    794			}
    795		}
    796	}
    797}
    798
    799/*
    800 * Bit    Update  Notes
    801 * 31     Yes     TDM Mode        (1 = TDM, 0 = i2s)
    802 * 30     Yes     Slave Mode	  (1 = Slave, 0 = Master)
    803 * 29:26  No      Sclks per frame
    804 * 25:18  Yes     FS Width
    805 * 17:14  No      Valid Slots
    806 * 13     No      Bits		  (1 = 16 bits, 0 = 32 bits)
    807 * 12:08  No     Bits per samp
    808 * 07     Yes     Justifcation    (1 = LSB, 0 = MSB)
    809 * 06     Yes     Alignment       (1 = Delay 1 clk, 0 = no delay
    810 * 05     Yes     SCLK polarity   (1 = Rising, 0 = Falling)
    811 * 04     Yes     LRCLK Polarity  (1 = High for left, 0 = Low for left)
    812 * 03:02  Yes     Reserved - write as zero
    813 * 01     No      Data Enable
    814 * 00     No      CLK Enable
    815 */
    816#define I2S_OUT_CFG_REG_UPDATE_MASK   0x3C03FF03
    817
    818/* Input cfg is same as output, but the FS width is not a valid field */
    819#define I2S_IN_CFG_REG_UPDATE_MASK  (I2S_OUT_CFG_REG_UPDATE_MASK | 0x03FC0000)
    820
    821int cygnus_ssp_set_custom_fsync_width(struct snd_soc_dai *cpu_dai, int len)
    822{
    823	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
    824
    825	if ((len > 0) && (len < 256)) {
    826		aio->fsync_width = len;
    827		return 0;
    828	} else {
    829		return -EINVAL;
    830	}
    831}
    832EXPORT_SYMBOL_GPL(cygnus_ssp_set_custom_fsync_width);
    833
    834static int cygnus_ssp_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
    835{
    836	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
    837	u32 ssp_curcfg;
    838	u32 ssp_newcfg;
    839	u32 ssp_outcfg;
    840	u32 ssp_incfg;
    841	u32 val;
    842	u32 mask;
    843
    844	dev_dbg(aio->cygaud->dev, "%s Enter  fmt: %x\n", __func__, fmt);
    845
    846	if (aio->port_type == PORT_SPDIF)
    847		return -EINVAL;
    848
    849	ssp_newcfg = 0;
    850
    851	switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
    852	case SND_SOC_DAIFMT_CBP_CFP:
    853		ssp_newcfg |= BIT(I2S_OUT_CFGX_SLAVE_MODE);
    854		aio->is_slave = 1;
    855		break;
    856	case SND_SOC_DAIFMT_CBC_CFC:
    857		ssp_newcfg &= ~BIT(I2S_OUT_CFGX_SLAVE_MODE);
    858		aio->is_slave = 0;
    859		break;
    860	default:
    861		return -EINVAL;
    862	}
    863
    864	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
    865	case SND_SOC_DAIFMT_I2S:
    866		ssp_newcfg |= BIT(I2S_OUT_CFGX_DATA_ALIGNMENT);
    867		ssp_newcfg |= BIT(I2S_OUT_CFGX_FSYNC_WIDTH);
    868		aio->mode = CYGNUS_SSPMODE_I2S;
    869		break;
    870
    871	case SND_SOC_DAIFMT_DSP_A:
    872	case SND_SOC_DAIFMT_DSP_B:
    873		ssp_newcfg |= BIT(I2S_OUT_CFGX_TDM_MODE);
    874
    875		/* DSP_A = data after FS, DSP_B = data during FS */
    876		if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_DSP_A)
    877			ssp_newcfg |= BIT(I2S_OUT_CFGX_DATA_ALIGNMENT);
    878
    879		if ((aio->fsync_width > 0) && (aio->fsync_width < 256))
    880			ssp_newcfg |=
    881				(aio->fsync_width << I2S_OUT_CFGX_FSYNC_WIDTH);
    882		else
    883			ssp_newcfg |= BIT(I2S_OUT_CFGX_FSYNC_WIDTH);
    884
    885		aio->mode = CYGNUS_SSPMODE_TDM;
    886		break;
    887
    888	default:
    889		return -EINVAL;
    890	}
    891
    892	/*
    893	 * SSP out cfg.
    894	 * Retain bits we do not want to update, then OR in new bits
    895	 */
    896	ssp_curcfg = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
    897	ssp_outcfg = (ssp_curcfg & I2S_OUT_CFG_REG_UPDATE_MASK) | ssp_newcfg;
    898	writel(ssp_outcfg, aio->cygaud->audio + aio->regs.i2s_cfg);
    899
    900	/*
    901	 * SSP in cfg.
    902	 * Retain bits we do not want to update, then OR in new bits
    903	 */
    904	ssp_curcfg = readl(aio->cygaud->i2s_in + aio->regs.i2s_cap_cfg);
    905	ssp_incfg = (ssp_curcfg & I2S_IN_CFG_REG_UPDATE_MASK) | ssp_newcfg;
    906	writel(ssp_incfg, aio->cygaud->i2s_in + aio->regs.i2s_cap_cfg);
    907
    908	val = readl(aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
    909
    910	/*
    911	 * Configure the word clk and bit clk as output or tristate
    912	 * Each port has 4 bits for controlling its pins.
    913	 * Shift the mask based upon port number.
    914	 */
    915	mask = BIT(AUD_MISC_SEROUT_LRCK_OE)
    916			| BIT(AUD_MISC_SEROUT_SCLK_OE)
    917			| BIT(AUD_MISC_SEROUT_MCLK_OE);
    918	mask = mask << (aio->portnum * 4);
    919	if (aio->is_slave)
    920		/* Set bit for tri-state */
    921		val |= mask;
    922	else
    923		/* Clear bit for drive */
    924		val &= ~mask;
    925
    926	dev_dbg(aio->cygaud->dev, "%s  Set OE bits 0x%x\n", __func__, val);
    927	writel(val, aio->cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
    928
    929	return 0;
    930}
    931
    932static int cygnus_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
    933			       struct snd_soc_dai *dai)
    934{
    935	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(dai);
    936	struct cygnus_audio *cygaud = snd_soc_dai_get_drvdata(dai);
    937
    938	dev_dbg(aio->cygaud->dev,
    939		"%s cmd %d at port = %d\n", __func__, cmd, aio->portnum);
    940
    941	switch (cmd) {
    942	case SNDRV_PCM_TRIGGER_START:
    943	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
    944	case SNDRV_PCM_TRIGGER_RESUME:
    945		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    946			audio_ssp_out_enable(aio);
    947		else
    948			audio_ssp_in_enable(aio);
    949		cygaud->active_ports++;
    950
    951		break;
    952
    953	case SNDRV_PCM_TRIGGER_STOP:
    954	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
    955	case SNDRV_PCM_TRIGGER_SUSPEND:
    956		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
    957			audio_ssp_out_disable(aio);
    958		else
    959			audio_ssp_in_disable(aio);
    960		cygaud->active_ports--;
    961		break;
    962
    963	default:
    964		return -EINVAL;
    965	}
    966
    967	return 0;
    968}
    969
    970static int cygnus_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
    971	unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
    972{
    973	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
    974	u32 value;
    975	int bits_per_slot = 0;     /* default to 32-bits per slot */
    976	int frame_bits;
    977	unsigned int active_slots;
    978	bool found = false;
    979	int i;
    980
    981	if (tx_mask != rx_mask) {
    982		dev_err(aio->cygaud->dev,
    983			"%s tx_mask must equal rx_mask\n", __func__);
    984		return -EINVAL;
    985	}
    986
    987	active_slots = hweight32(tx_mask);
    988
    989	if (active_slots > 16)
    990		return -EINVAL;
    991
    992	/* Slot value must be even */
    993	if (active_slots % 2)
    994		return -EINVAL;
    995
    996	/* We encode 16 slots as 0 in the reg */
    997	if (active_slots == 16)
    998		active_slots = 0;
    999
   1000	/* Slot Width is either 16 or 32 */
   1001	switch (slot_width) {
   1002	case 16:
   1003		bits_per_slot = 1;
   1004		break;
   1005	case 32:
   1006		bits_per_slot = 0;
   1007		break;
   1008	default:
   1009		bits_per_slot = 0;
   1010		dev_warn(aio->cygaud->dev,
   1011			"%s Defaulting Slot Width to 32\n", __func__);
   1012	}
   1013
   1014	frame_bits = slots * slot_width;
   1015
   1016	for (i = 0; i < ARRAY_SIZE(ssp_valid_tdm_framesize); i++) {
   1017		if (ssp_valid_tdm_framesize[i] == frame_bits) {
   1018			found = true;
   1019			break;
   1020		}
   1021	}
   1022
   1023	if (!found) {
   1024		dev_err(aio->cygaud->dev,
   1025			"%s In TDM mode, frame bits INVALID (%d)\n",
   1026			__func__, frame_bits);
   1027		return -EINVAL;
   1028	}
   1029
   1030	aio->bit_per_frame = frame_bits;
   1031
   1032	dev_dbg(aio->cygaud->dev, "%s active_slots %u, bits per frame %d\n",
   1033			__func__, active_slots, frame_bits);
   1034
   1035	/* Set capture side of ssp port */
   1036	value = readl(aio->cygaud->i2s_in + aio->regs.i2s_cap_cfg);
   1037	value &= ~(0xf << I2S_OUT_CFGX_VALID_SLOT);
   1038	value |= (active_slots << I2S_OUT_CFGX_VALID_SLOT);
   1039	value &= ~BIT(I2S_OUT_CFGX_BITS_PER_SLOT);
   1040	value |= (bits_per_slot << I2S_OUT_CFGX_BITS_PER_SLOT);
   1041	writel(value, aio->cygaud->i2s_in + aio->regs.i2s_cap_cfg);
   1042
   1043	/* Set playback side of ssp port */
   1044	value = readl(aio->cygaud->audio + aio->regs.i2s_cfg);
   1045	value &= ~(0xf << I2S_OUT_CFGX_VALID_SLOT);
   1046	value |= (active_slots << I2S_OUT_CFGX_VALID_SLOT);
   1047	value &= ~BIT(I2S_OUT_CFGX_BITS_PER_SLOT);
   1048	value |= (bits_per_slot << I2S_OUT_CFGX_BITS_PER_SLOT);
   1049	writel(value, aio->cygaud->audio + aio->regs.i2s_cfg);
   1050
   1051	return 0;
   1052}
   1053
   1054#ifdef CONFIG_PM_SLEEP
   1055static int __cygnus_ssp_suspend(struct snd_soc_dai *cpu_dai)
   1056{
   1057	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
   1058
   1059	if (!snd_soc_dai_active(cpu_dai))
   1060		return 0;
   1061
   1062	if (!aio->is_slave) {
   1063		u32 val;
   1064
   1065		val = readl(aio->cygaud->audio + aio->regs.i2s_mclk_cfg);
   1066		val &= CYGNUS_PLLCLKSEL_MASK;
   1067		if (val >= ARRAY_SIZE(aio->cygaud->audio_clk)) {
   1068			dev_err(aio->cygaud->dev, "Clk index %u is out of bounds\n",
   1069				val);
   1070			return -EINVAL;
   1071		}
   1072
   1073		if (aio->clk_trace.cap_clk_en)
   1074			clk_disable_unprepare(aio->cygaud->audio_clk[val]);
   1075		if (aio->clk_trace.play_clk_en)
   1076			clk_disable_unprepare(aio->cygaud->audio_clk[val]);
   1077
   1078		aio->pll_clk_num = val;
   1079	}
   1080
   1081	return 0;
   1082}
   1083
   1084static int cygnus_ssp_suspend(struct snd_soc_component *component)
   1085{
   1086	struct snd_soc_dai *dai;
   1087	int ret = 0;
   1088
   1089	for_each_component_dais(component, dai)
   1090		ret |= __cygnus_ssp_suspend(dai);
   1091
   1092	return ret;
   1093}
   1094
   1095static int __cygnus_ssp_resume(struct snd_soc_dai *cpu_dai)
   1096{
   1097	struct cygnus_aio_port *aio = cygnus_dai_get_portinfo(cpu_dai);
   1098	int error;
   1099
   1100	if (!snd_soc_dai_active(cpu_dai))
   1101		return 0;
   1102
   1103	if (!aio->is_slave) {
   1104		if (aio->clk_trace.cap_clk_en) {
   1105			error = clk_prepare_enable(aio->cygaud->
   1106					audio_clk[aio->pll_clk_num]);
   1107			if (error) {
   1108				dev_err(aio->cygaud->dev, "%s clk_prepare_enable failed\n",
   1109					__func__);
   1110				return -EINVAL;
   1111			}
   1112		}
   1113		if (aio->clk_trace.play_clk_en) {
   1114			error = clk_prepare_enable(aio->cygaud->
   1115					audio_clk[aio->pll_clk_num]);
   1116			if (error) {
   1117				if (aio->clk_trace.cap_clk_en)
   1118					clk_disable_unprepare(aio->cygaud->
   1119						audio_clk[aio->pll_clk_num]);
   1120				dev_err(aio->cygaud->dev, "%s clk_prepare_enable failed\n",
   1121					__func__);
   1122				return -EINVAL;
   1123			}
   1124		}
   1125	}
   1126
   1127	return 0;
   1128}
   1129
   1130static int cygnus_ssp_resume(struct snd_soc_component *component)
   1131{
   1132	struct snd_soc_dai *dai;
   1133	int ret = 0;
   1134
   1135	for_each_component_dais(component, dai)
   1136		ret |= __cygnus_ssp_resume(dai);
   1137
   1138	return ret;
   1139}
   1140
   1141#else
   1142#define cygnus_ssp_suspend NULL
   1143#define cygnus_ssp_resume  NULL
   1144#endif
   1145
   1146static const struct snd_soc_dai_ops cygnus_ssp_dai_ops = {
   1147	.startup	= cygnus_ssp_startup,
   1148	.shutdown	= cygnus_ssp_shutdown,
   1149	.trigger	= cygnus_ssp_trigger,
   1150	.hw_params	= cygnus_ssp_hw_params,
   1151	.set_fmt	= cygnus_ssp_set_fmt,
   1152	.set_sysclk	= cygnus_ssp_set_sysclk,
   1153	.set_tdm_slot	= cygnus_set_dai_tdm_slot,
   1154};
   1155
   1156static const struct snd_soc_dai_ops cygnus_spdif_dai_ops = {
   1157	.startup	= cygnus_ssp_startup,
   1158	.shutdown	= cygnus_ssp_shutdown,
   1159	.trigger	= cygnus_ssp_trigger,
   1160	.hw_params	= cygnus_ssp_hw_params,
   1161	.set_sysclk	= cygnus_ssp_set_sysclk,
   1162};
   1163
   1164#define INIT_CPU_DAI(num) { \
   1165	.name = "cygnus-ssp" #num, \
   1166	.playback = { \
   1167		.channels_min = 2, \
   1168		.channels_max = 16, \
   1169		.rates = SNDRV_PCM_RATE_KNOT, \
   1170		.formats = SNDRV_PCM_FMTBIT_S16_LE | \
   1171				SNDRV_PCM_FMTBIT_S32_LE, \
   1172	}, \
   1173	.capture = { \
   1174		.channels_min = 2, \
   1175		.channels_max = 16, \
   1176		.rates = SNDRV_PCM_RATE_KNOT, \
   1177		.formats =  SNDRV_PCM_FMTBIT_S16_LE | \
   1178				SNDRV_PCM_FMTBIT_S32_LE, \
   1179	}, \
   1180	.ops = &cygnus_ssp_dai_ops, \
   1181}
   1182
   1183static const struct snd_soc_dai_driver cygnus_ssp_dai_info[] = {
   1184	INIT_CPU_DAI(0),
   1185	INIT_CPU_DAI(1),
   1186	INIT_CPU_DAI(2),
   1187};
   1188
   1189static const struct snd_soc_dai_driver cygnus_spdif_dai_info = {
   1190	.name = "cygnus-spdif",
   1191	.playback = {
   1192		.channels_min = 2,
   1193		.channels_max = 2,
   1194		.rates = SNDRV_PCM_RATE_KNOT,
   1195		.formats = SNDRV_PCM_FMTBIT_S16_LE |
   1196			SNDRV_PCM_FMTBIT_S32_LE,
   1197	},
   1198	.ops = &cygnus_spdif_dai_ops,
   1199};
   1200
   1201static struct snd_soc_dai_driver cygnus_ssp_dai[CYGNUS_MAX_PORTS];
   1202
   1203static const struct snd_soc_component_driver cygnus_ssp_component = {
   1204	.name		= "cygnus-audio",
   1205	.suspend	= cygnus_ssp_suspend,
   1206	.resume		= cygnus_ssp_resume,
   1207};
   1208
   1209/*
   1210 * Return < 0 if error
   1211 * Return 0 if disabled
   1212 * Return 1 if enabled and node is parsed successfully
   1213 */
   1214static int parse_ssp_child_node(struct platform_device *pdev,
   1215				struct device_node *dn,
   1216				struct cygnus_audio *cygaud,
   1217				struct snd_soc_dai_driver *p_dai)
   1218{
   1219	struct cygnus_aio_port *aio;
   1220	struct cygnus_ssp_regs ssp_regs[3];
   1221	u32 rawval;
   1222	int portnum = -1;
   1223	enum cygnus_audio_port_type port_type;
   1224
   1225	if (of_property_read_u32(dn, "reg", &rawval)) {
   1226		dev_err(&pdev->dev, "Missing reg property\n");
   1227		return -EINVAL;
   1228	}
   1229
   1230	portnum = rawval;
   1231	switch (rawval) {
   1232	case 0:
   1233		ssp_regs[0] = INIT_SSP_REGS(0);
   1234		port_type = PORT_TDM;
   1235		break;
   1236	case 1:
   1237		ssp_regs[1] = INIT_SSP_REGS(1);
   1238		port_type = PORT_TDM;
   1239		break;
   1240	case 2:
   1241		ssp_regs[2] = INIT_SSP_REGS(2);
   1242		port_type = PORT_TDM;
   1243		break;
   1244	case 3:
   1245		port_type = PORT_SPDIF;
   1246		break;
   1247	default:
   1248		dev_err(&pdev->dev, "Bad value for reg %u\n", rawval);
   1249		return -EINVAL;
   1250	}
   1251
   1252	aio = &cygaud->portinfo[portnum];
   1253	aio->cygaud = cygaud;
   1254	aio->portnum = portnum;
   1255	aio->port_type = port_type;
   1256	aio->fsync_width = -1;
   1257
   1258	switch (port_type) {
   1259	case PORT_TDM:
   1260		aio->regs = ssp_regs[portnum];
   1261		*p_dai = cygnus_ssp_dai_info[portnum];
   1262		aio->mode = CYGNUS_SSPMODE_UNKNOWN;
   1263		break;
   1264
   1265	case PORT_SPDIF:
   1266		aio->regs.bf_sourcech_cfg = BF_SRC_CFG3_OFFSET;
   1267		aio->regs.bf_sourcech_ctrl = BF_SRC_CTRL3_OFFSET;
   1268		aio->regs.i2s_mclk_cfg = SPDIF_MCLK_CFG_OFFSET;
   1269		aio->regs.i2s_stream_cfg = SPDIF_STREAM_CFG_OFFSET;
   1270		*p_dai = cygnus_spdif_dai_info;
   1271
   1272		/* For the purposes of this code SPDIF can be I2S mode */
   1273		aio->mode = CYGNUS_SSPMODE_I2S;
   1274		break;
   1275	default:
   1276		dev_err(&pdev->dev, "Bad value for port_type %d\n", port_type);
   1277		return -EINVAL;
   1278	}
   1279
   1280	dev_dbg(&pdev->dev, "%s portnum = %d\n", __func__, aio->portnum);
   1281	aio->streams_on = 0;
   1282	aio->cygaud->dev = &pdev->dev;
   1283	aio->clk_trace.play_en = false;
   1284	aio->clk_trace.cap_en = false;
   1285
   1286	audio_ssp_init_portregs(aio);
   1287	return 0;
   1288}
   1289
   1290static int audio_clk_init(struct platform_device *pdev,
   1291						struct cygnus_audio *cygaud)
   1292{
   1293	int i;
   1294	char clk_name[PROP_LEN_MAX];
   1295
   1296	for (i = 0; i < ARRAY_SIZE(cygaud->audio_clk); i++) {
   1297		snprintf(clk_name, PROP_LEN_MAX, "ch%d_audio", i);
   1298
   1299		cygaud->audio_clk[i] = devm_clk_get(&pdev->dev, clk_name);
   1300		if (IS_ERR(cygaud->audio_clk[i]))
   1301			return PTR_ERR(cygaud->audio_clk[i]);
   1302	}
   1303
   1304	return 0;
   1305}
   1306
   1307static int cygnus_ssp_probe(struct platform_device *pdev)
   1308{
   1309	struct device *dev = &pdev->dev;
   1310	struct device_node *child_node;
   1311	struct cygnus_audio *cygaud;
   1312	int err;
   1313	int node_count;
   1314	int active_port_count;
   1315
   1316	cygaud = devm_kzalloc(dev, sizeof(struct cygnus_audio), GFP_KERNEL);
   1317	if (!cygaud)
   1318		return -ENOMEM;
   1319
   1320	dev_set_drvdata(dev, cygaud);
   1321
   1322	cygaud->audio = devm_platform_ioremap_resource_byname(pdev, "aud");
   1323	if (IS_ERR(cygaud->audio))
   1324		return PTR_ERR(cygaud->audio);
   1325
   1326	cygaud->i2s_in = devm_platform_ioremap_resource_byname(pdev, "i2s_in");
   1327	if (IS_ERR(cygaud->i2s_in))
   1328		return PTR_ERR(cygaud->i2s_in);
   1329
   1330	/* Tri-state all controlable pins until we know that we need them */
   1331	writel(CYGNUS_SSP_TRISTATE_MASK,
   1332			cygaud->audio + AUD_MISC_SEROUT_OE_REG_BASE);
   1333
   1334	node_count = of_get_child_count(pdev->dev.of_node);
   1335	if ((node_count < 1) || (node_count > CYGNUS_MAX_PORTS)) {
   1336		dev_err(dev, "child nodes is %d.  Must be between 1 and %d\n",
   1337			node_count, CYGNUS_MAX_PORTS);
   1338		return -EINVAL;
   1339	}
   1340
   1341	active_port_count = 0;
   1342
   1343	for_each_available_child_of_node(pdev->dev.of_node, child_node) {
   1344		err = parse_ssp_child_node(pdev, child_node, cygaud,
   1345					&cygnus_ssp_dai[active_port_count]);
   1346
   1347		/* negative is err, 0 is active and good, 1 is disabled */
   1348		if (err < 0) {
   1349			of_node_put(child_node);
   1350			return err;
   1351		}
   1352		else if (!err) {
   1353			dev_dbg(dev, "Activating DAI: %s\n",
   1354				cygnus_ssp_dai[active_port_count].name);
   1355			active_port_count++;
   1356		}
   1357	}
   1358
   1359	cygaud->dev = dev;
   1360	cygaud->active_ports = 0;
   1361
   1362	dev_dbg(dev, "Registering %d DAIs\n", active_port_count);
   1363	err = devm_snd_soc_register_component(dev, &cygnus_ssp_component,
   1364				cygnus_ssp_dai, active_port_count);
   1365	if (err) {
   1366		dev_err(dev, "snd_soc_register_dai failed\n");
   1367		return err;
   1368	}
   1369
   1370	cygaud->irq_num = platform_get_irq(pdev, 0);
   1371	if (cygaud->irq_num <= 0)
   1372		return cygaud->irq_num;
   1373
   1374	err = audio_clk_init(pdev, cygaud);
   1375	if (err) {
   1376		dev_err(dev, "audio clock initialization failed\n");
   1377		return err;
   1378	}
   1379
   1380	err = cygnus_soc_platform_register(dev, cygaud);
   1381	if (err) {
   1382		dev_err(dev, "platform reg error %d\n", err);
   1383		return err;
   1384	}
   1385
   1386	return 0;
   1387}
   1388
   1389static int cygnus_ssp_remove(struct platform_device *pdev)
   1390{
   1391	cygnus_soc_platform_unregister(&pdev->dev);
   1392
   1393	return 0;
   1394}
   1395
   1396static const struct of_device_id cygnus_ssp_of_match[] = {
   1397	{ .compatible = "brcm,cygnus-audio" },
   1398	{},
   1399};
   1400MODULE_DEVICE_TABLE(of, cygnus_ssp_of_match);
   1401
   1402static struct platform_driver cygnus_ssp_driver = {
   1403	.probe		= cygnus_ssp_probe,
   1404	.remove		= cygnus_ssp_remove,
   1405	.driver		= {
   1406		.name	= "cygnus-ssp",
   1407		.of_match_table = cygnus_ssp_of_match,
   1408	},
   1409};
   1410
   1411module_platform_driver(cygnus_ssp_driver);
   1412
   1413MODULE_ALIAS("platform:cygnus-ssp");
   1414MODULE_LICENSE("GPL v2");
   1415MODULE_AUTHOR("Broadcom");
   1416MODULE_DESCRIPTION("Cygnus ASoC SSP Interface");