1/* 2 * Serial Sound Interface (I2S) support for SH7760/SH7780 3 * 4 * Copyright (c) 2007 Manuel Lauss <mano@roarinelk.homelinux.net> 5 * 6 * licensed under the terms outlined in the file COPYING at the root 7 * of the linux kernel sources. 8 * 9 * dont forget to set IPSEL/OMSEL register bits (in your board code) to 10 * enable SSI output pins! 11 */ 12 13/* 14 * LIMITATIONS: 15 * The SSI unit has only one physical data line, so full duplex is 16 * impossible. This can be remedied on the SH7760 by using the 17 * other SSI unit for recording; however the SH7780 has only 1 SSI 18 * unit, and its pins are shared with the AC97 unit, among others. 19 * 20 * FEATURES: 21 * The SSI features "compressed mode": in this mode it continuously 22 * streams PCM data over the I2S lines and uses LRCK as a handshake 23 * signal. Can be used to send compressed data (AC3/DTS) to a DSP. 24 * The number of bits sent over the wire in a frame can be adjusted 25 * and can be independent from the actual sample bit depth. This is 26 * useful to support TDM mode codecs like the AD1939 which have a 27 * fixed TDM slot size, regardless of sample resolution. 28 */ 29 30#include <linux/init.h> 31#include <linux/module.h> 32#include <linux/platform_device.h> 33#include <sound/core.h> 34#include <sound/pcm.h> 35#include <sound/initval.h> 36#include <sound/soc.h> 37#include <asm/io.h> 38 39#define SSICR 0x00 40#define SSISR 0x04 41 42#define CR_DMAEN (1 << 28) 43#define CR_CHNL_SHIFT 22 44#define CR_CHNL_MASK (3 << CR_CHNL_SHIFT) 45#define CR_DWL_SHIFT 19 46#define CR_DWL_MASK (7 << CR_DWL_SHIFT) 47#define CR_SWL_SHIFT 16 48#define CR_SWL_MASK (7 << CR_SWL_SHIFT) 49#define CR_SCK_MASTER (1 << 15) /* bitclock master bit */ 50#define CR_SWS_MASTER (1 << 14) /* wordselect master bit */ 51#define CR_SCKP (1 << 13) /* I2Sclock polarity */ 52#define CR_SWSP (1 << 12) /* LRCK polarity */ 53#define CR_SPDP (1 << 11) 54#define CR_SDTA (1 << 10) /* i2s alignment (msb/lsb) */ 55#define CR_PDTA (1 << 9) /* fifo data alignment */ 56#define CR_DEL (1 << 8) /* delay data by 1 i2sclk */ 57#define CR_BREN (1 << 7) /* clock gating in burst mode */ 58#define CR_CKDIV_SHIFT 4 59#define CR_CKDIV_MASK (7 << CR_CKDIV_SHIFT) /* bitclock divider */ 60#define CR_MUTE (1 << 3) /* SSI mute */ 61#define CR_CPEN (1 << 2) /* compressed mode */ 62#define CR_TRMD (1 << 1) /* transmit/receive select */ 63#define CR_EN (1 << 0) /* enable SSI */ 64 65#define SSIREG(reg) (*(unsigned long *)(ssi->mmio + (reg))) 66 67struct ssi_priv { 68 unsigned long mmio; 69 unsigned long sysclk; 70 int inuse; 71} ssi_cpu_data[] = { 72#if defined(CONFIG_CPU_SUBTYPE_SH7760) 73 { 74 .mmio = 0xFE680000, 75 }, 76 { 77 .mmio = 0xFE690000, 78 }, 79#elif defined(CONFIG_CPU_SUBTYPE_SH7780) 80 { 81 .mmio = 0xFFE70000, 82 }, 83#else 84#error "Unsupported SuperH SoC" 85#endif 86}; 87 88static int ssi_startup(struct snd_pcm_substream *substream, 89 struct snd_soc_dai *dai) 90{ 91 struct snd_soc_pcm_runtime *rtd = substream->private_data; 92 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; 93 if (ssi->inuse) { 94 pr_debug("ssi: already in use!\n"); 95 return -EBUSY; 96 } else 97 ssi->inuse = 1; 98 return 0; 99} 100 101static void ssi_shutdown(struct snd_pcm_substream *substream, 102 struct snd_soc_dai *dai) 103{ 104 struct snd_soc_pcm_runtime *rtd = substream->private_data; 105 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; 106 107 ssi->inuse = 0; 108} 109 110static int ssi_trigger(struct snd_pcm_substream *substream, int cmd, 111 struct snd_soc_dai *dai) 112{ 113 struct snd_soc_pcm_runtime *rtd = substream->private_data; 114 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; 115 116 switch (cmd) { 117 case SNDRV_PCM_TRIGGER_START: 118 SSIREG(SSICR) |= CR_DMAEN | CR_EN; 119 break; 120 case SNDRV_PCM_TRIGGER_STOP: 121 SSIREG(SSICR) &= ~(CR_DMAEN | CR_EN); 122 break; 123 default: 124 return -EINVAL; 125 } 126 127 return 0; 128} 129 130static int ssi_hw_params(struct snd_pcm_substream *substream, 131 struct snd_pcm_hw_params *params, 132 struct snd_soc_dai *dai) 133{ 134 struct snd_soc_pcm_runtime *rtd = substream->private_data; 135 struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; 136 unsigned long ssicr = SSIREG(SSICR); 137 unsigned int bits, channels, swl, recv, i; 138 139 channels = params_channels(params); 140 bits = params->msbits; 141 recv = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 0 : 1; 142 143 pr_debug("ssi_hw_params() enter\nssicr was %08lx\n", ssicr); 144 pr_debug("bits: %u channels: %u\n", bits, channels); 145 146 ssicr &= ~(CR_TRMD | CR_CHNL_MASK | CR_DWL_MASK | CR_PDTA | 147 CR_SWL_MASK); 148 149 /* direction (send/receive) */ 150 if (!recv) 151 ssicr |= CR_TRMD; /* transmit */ 152 153 /* channels */ 154 if ((channels < 2) || (channels > 8) || (channels & 1)) { 155 pr_debug("ssi: invalid number of channels\n"); 156 return -EINVAL; 157 } 158 ssicr |= ((channels >> 1) - 1) << CR_CHNL_SHIFT; 159 160 /* DATA WORD LENGTH (DWL): databits in audio sample */ 161 i = 0; 162 switch (bits) { 163 case 32: ++i; 164 case 24: ++i; 165 case 22: ++i; 166 case 20: ++i; 167 case 18: ++i; 168 case 16: ++i; 169 ssicr |= i << CR_DWL_SHIFT; 170 case 8: break; 171 default: 172 pr_debug("ssi: invalid sample width\n"); 173 return -EINVAL; 174 } 175 176 /* 177 * SYSTEM WORD LENGTH: size in bits of half a frame over the I2S 178 * wires. This is usually bits_per_sample x channels/2; i.e. in 179 * Stereo mode the SWL equals DWL. SWL can be bigger than the 180 * product of (channels_per_slot x samplebits), e.g. for codecs 181 * like the AD1939 which only accept 32bit wide TDM slots. For 182 * "standard" I2S operation we set SWL = chans / 2 * DWL here. 183 * Waiting for ASoC to get TDM support ;-) 184 */ 185 if ((bits > 16) && (bits <= 24)) { 186 bits = 24; /* these are padded by the SSI */ 187 /*ssicr |= CR_PDTA;*/ /* cpu/data endianness ? */ 188 } 189 i = 0; 190 swl = (bits * channels) / 2; 191 switch (swl) { 192 case 256: ++i; 193 case 128: ++i; 194 case 64: ++i; 195 case 48: ++i; 196 case 32: ++i; 197 case 16: ++i; 198 ssicr |= i << CR_SWL_SHIFT; 199 case 8: break; 200 default: 201 pr_debug("ssi: invalid system word length computed\n"); 202 return -EINVAL; 203 } 204 205 SSIREG(SSICR) = ssicr; 206 207 pr_debug("ssi_hw_params() leave\nssicr is now %08lx\n", ssicr); 208 return 0; 209} 210 211static int ssi_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id, 212 unsigned int freq, int dir) 213{ 214 struct ssi_priv *ssi = &ssi_cpu_data[cpu_dai->id]; 215 216 ssi->sysclk = freq; 217 218 return 0; 219} 220 221/* 222 * This divider is used to generate the SSI_SCK (I2S bitclock) from the 223 * clock at the HAC_BIT_CLK ("oversampling clock") pin. 224 */ 225static int ssi_set_clkdiv(struct snd_soc_dai *dai, int did, int div) 226{ 227 struct ssi_priv *ssi = &ssi_cpu_data[dai->id]; 228 unsigned long ssicr; 229 int i; 230 231 i = 0; 232 ssicr = SSIREG(SSICR) & ~CR_CKDIV_MASK; 233 switch (div) { 234 case 16: ++i; 235 case 8: ++i; 236 case 4: ++i; 237 case 2: ++i; 238 SSIREG(SSICR) = ssicr | (i << CR_CKDIV_SHIFT); 239 case 1: break; 240 default: 241 pr_debug("ssi: invalid sck divider %d\n", div); 242 return -EINVAL; 243 } 244 245 return 0; 246} 247 248static int ssi_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 249{ 250 struct ssi_priv *ssi = &ssi_cpu_data[dai->id]; 251 unsigned long ssicr = SSIREG(SSICR); 252 253 pr_debug("ssi_set_fmt()\nssicr was 0x%08lx\n", ssicr); 254 255 ssicr &= ~(CR_DEL | CR_PDTA | CR_BREN | CR_SWSP | CR_SCKP | 256 CR_SWS_MASTER | CR_SCK_MASTER); 257 258 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 259 case SND_SOC_DAIFMT_I2S: 260 break; 261 case SND_SOC_DAIFMT_RIGHT_J: 262 ssicr |= CR_DEL | CR_PDTA; 263 break; 264 case SND_SOC_DAIFMT_LEFT_J: 265 ssicr |= CR_DEL; 266 break; 267 default: 268 pr_debug("ssi: unsupported format\n"); 269 return -EINVAL; 270 } 271 272 switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) { 273 case SND_SOC_DAIFMT_CONT: 274 break; 275 case SND_SOC_DAIFMT_GATED: 276 ssicr |= CR_BREN; 277 break; 278 } 279 280 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 281 case SND_SOC_DAIFMT_NB_NF: 282 ssicr |= CR_SCKP; /* sample data at low clkedge */ 283 break; 284 case SND_SOC_DAIFMT_NB_IF: 285 ssicr |= CR_SCKP | CR_SWSP; 286 break; 287 case SND_SOC_DAIFMT_IB_NF: 288 break; 289 case SND_SOC_DAIFMT_IB_IF: 290 ssicr |= CR_SWSP; /* word select starts low */ 291 break; 292 default: 293 pr_debug("ssi: invalid inversion\n"); 294 return -EINVAL; 295 } 296 297 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 298 case SND_SOC_DAIFMT_CBM_CFM: 299 break; 300 case SND_SOC_DAIFMT_CBS_CFM: 301 ssicr |= CR_SCK_MASTER; 302 break; 303 case SND_SOC_DAIFMT_CBM_CFS: 304 ssicr |= CR_SWS_MASTER; 305 break; 306 case SND_SOC_DAIFMT_CBS_CFS: 307 ssicr |= CR_SWS_MASTER | CR_SCK_MASTER; 308 break; 309 default: 310 pr_debug("ssi: invalid master/slave configuration\n"); 311 return -EINVAL; 312 } 313 314 SSIREG(SSICR) = ssicr; 315 pr_debug("ssi_set_fmt() leave\nssicr is now 0x%08lx\n", ssicr); 316 317 return 0; 318} 319 320/* the SSI depends on an external clocksource (at HAC_BIT_CLK) even in 321 * Master mode, so really this is board specific; the SSI can do any 322 * rate with the right bitclk and divider settings. 323 */ 324#define SSI_RATES \ 325 SNDRV_PCM_RATE_8000_192000 326 327/* the SSI can do 8-32 bit samples, with 8 possible channels */ 328#define SSI_FMTS \ 329 (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \ 330 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \ 331 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \ 332 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE | \ 333 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE) 334 335static struct snd_soc_dai_ops ssi_dai_ops = { 336 .startup = ssi_startup, 337 .shutdown = ssi_shutdown, 338 .trigger = ssi_trigger, 339 .hw_params = ssi_hw_params, 340 .set_sysclk = ssi_set_sysclk, 341 .set_clkdiv = ssi_set_clkdiv, 342 .set_fmt = ssi_set_fmt, 343}; 344 345struct snd_soc_dai sh4_ssi_dai[] = { 346{ 347 .name = "SSI0", 348 .id = 0, 349 .playback = { 350 .rates = SSI_RATES, 351 .formats = SSI_FMTS, 352 .channels_min = 2, 353 .channels_max = 8, 354 }, 355 .capture = { 356 .rates = SSI_RATES, 357 .formats = SSI_FMTS, 358 .channels_min = 2, 359 .channels_max = 8, 360 }, 361 .ops = &ssi_dai_ops, 362}, 363#ifdef CONFIG_CPU_SUBTYPE_SH7760 364{ 365 .name = "SSI1", 366 .id = 1, 367 .playback = { 368 .rates = SSI_RATES, 369 .formats = SSI_FMTS, 370 .channels_min = 2, 371 .channels_max = 8, 372 }, 373 .capture = { 374 .rates = SSI_RATES, 375 .formats = SSI_FMTS, 376 .channels_min = 2, 377 .channels_max = 8, 378 }, 379 .ops = &ssi_dai_ops, 380}, 381#endif 382}; 383EXPORT_SYMBOL_GPL(sh4_ssi_dai); 384 385static int __init sh4_ssi_init(void) 386{ 387 return snd_soc_register_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai)); 388} 389module_init(sh4_ssi_init); 390 391static void __exit sh4_ssi_exit(void) 392{ 393 snd_soc_unregister_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai)); 394} 395module_exit(sh4_ssi_exit); 396 397MODULE_LICENSE("GPL"); 398MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver"); 399MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); 400