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