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");