1 /* 2 * 3 * Support for CX23885 analog audio capture 4 * 5 * (c) 2008 Mijhail Moreyra <mijhail.moreyra@gmail.com> 6 * Adapted from cx88-alsa.c 7 * (c) 2009 Steven Toth <stoth@kernellabs.com> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 */ 23 24 #include <linux/module.h> 25 #include <linux/init.h> 26 #include <linux/device.h> 27 #include <linux/interrupt.h> 28 #include <linux/vmalloc.h> 29 #include <linux/dma-mapping.h> 30 #include <linux/pci.h> 31 32 #include <asm/delay.h> 33 34 #include <sound/core.h> 35 #include <sound/pcm.h> 36 #include <sound/pcm_params.h> 37 #include <sound/control.h> 38 #include <sound/initval.h> 39 40 #include <sound/tlv.h> 41 42 43 #include "cx23885.h" 44 #include "cx23885-reg.h" 45 46 #define AUDIO_SRAM_CHANNEL SRAM_CH07 47 48 #define dprintk(level, fmt, arg...) do { \ 49 if (audio_debug + 1 > level) \ 50 printk(KERN_INFO "%s: " fmt, chip->dev->name , ## arg); \ 51 } while(0) 52 53 #define dprintk_core(level, fmt, arg...) if (audio_debug >= level) \ 54 printk(KERN_DEBUG "%s: " fmt, chip->dev->name , ## arg) 55 56 /**************************************************************************** 57 Module global static vars 58 ****************************************************************************/ 59 60 static unsigned int disable_analog_audio; 61 module_param(disable_analog_audio, int, 0644); 62 MODULE_PARM_DESC(disable_analog_audio, "disable analog audio ALSA driver"); 63 64 static unsigned int audio_debug; 65 module_param(audio_debug, int, 0644); 66 MODULE_PARM_DESC(audio_debug, "enable debug messages [analog audio]"); 67 68 /**************************************************************************** 69 Board specific funtions 70 ****************************************************************************/ 71 72 /* Constants taken from cx88-reg.h */ 73 #define AUD_INT_DN_RISCI1 (1 << 0) 74 #define AUD_INT_UP_RISCI1 (1 << 1) 75 #define AUD_INT_RDS_DN_RISCI1 (1 << 2) 76 #define AUD_INT_DN_RISCI2 (1 << 4) /* yes, 3 is skipped */ 77 #define AUD_INT_UP_RISCI2 (1 << 5) 78 #define AUD_INT_RDS_DN_RISCI2 (1 << 6) 79 #define AUD_INT_DN_SYNC (1 << 12) 80 #define AUD_INT_UP_SYNC (1 << 13) 81 #define AUD_INT_RDS_DN_SYNC (1 << 14) 82 #define AUD_INT_OPC_ERR (1 << 16) 83 #define AUD_INT_BER_IRQ (1 << 20) 84 #define AUD_INT_MCHG_IRQ (1 << 21) 85 #define GP_COUNT_CONTROL_RESET 0x3 86 87 /* 88 * BOARD Specific: Sets audio DMA 89 */ 90 91 static int cx23885_start_audio_dma(struct cx23885_audio_dev *chip) 92 { 93 struct cx23885_audio_buffer *buf = chip->buf; 94 struct cx23885_dev *dev = chip->dev; 95 struct sram_channel *audio_ch = 96 &dev->sram_channels[AUDIO_SRAM_CHANNEL]; 97 98 dprintk(1, "%s()\n", __func__); 99 100 /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */ 101 cx_clear(AUD_INT_DMA_CTL, 0x11); 102 103 /* setup fifo + format - out channel */ 104 cx23885_sram_channel_setup(chip->dev, audio_ch, buf->bpl, 105 buf->risc.dma); 106 107 /* sets bpl size */ 108 cx_write(AUD_INT_A_LNGTH, buf->bpl); 109 110 /* This is required to get good audio (1 seems to be ok) */ 111 cx_write(AUD_INT_A_MODE, 1); 112 113 /* reset counter */ 114 cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); 115 atomic_set(&chip->count, 0); 116 117 dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d " 118 "byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start+12)>>1, 119 chip->num_periods, buf->bpl * chip->num_periods); 120 121 /* Enables corresponding bits at AUD_INT_STAT */ 122 cx_write(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | 123 AUD_INT_DN_RISCI1); 124 125 /* Clean any pending interrupt bits already set */ 126 cx_write(AUDIO_INT_INT_STAT, ~0); 127 128 /* enable audio irqs */ 129 cx_set(PCI_INT_MSK, chip->dev->pci_irqmask | PCI_MSK_AUD_INT); 130 131 /* start dma */ 132 cx_set(DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */ 133 cx_set(AUD_INT_DMA_CTL, 0x11); /* audio downstream FIFO and 134 RISC enable */ 135 if (audio_debug) 136 cx23885_sram_channel_dump(chip->dev, audio_ch); 137 138 return 0; 139 } 140 141 /* 142 * BOARD Specific: Resets audio DMA 143 */ 144 static int cx23885_stop_audio_dma(struct cx23885_audio_dev *chip) 145 { 146 struct cx23885_dev *dev = chip->dev; 147 dprintk(1, "Stopping audio DMA\n"); 148 149 /* stop dma */ 150 cx_clear(AUD_INT_DMA_CTL, 0x11); 151 152 /* disable irqs */ 153 cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT); 154 cx_clear(AUDIO_INT_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | 155 AUD_INT_DN_RISCI1); 156 157 if (audio_debug) 158 cx23885_sram_channel_dump(chip->dev, 159 &dev->sram_channels[AUDIO_SRAM_CHANNEL]); 160 161 return 0; 162 } 163 164 /* 165 * BOARD Specific: Handles audio IRQ 166 */ 167 int cx23885_audio_irq(struct cx23885_dev *dev, u32 status, u32 mask) 168 { 169 struct cx23885_audio_dev *chip = dev->audio_dev; 170 171 if (0 == (status & mask)) 172 return 0; 173 174 cx_write(AUDIO_INT_INT_STAT, status); 175 176 /* risc op code error */ 177 if (status & AUD_INT_OPC_ERR) { 178 printk(KERN_WARNING "%s/1: Audio risc op code error\n", 179 dev->name); 180 cx_clear(AUD_INT_DMA_CTL, 0x11); 181 cx23885_sram_channel_dump(dev, 182 &dev->sram_channels[AUDIO_SRAM_CHANNEL]); 183 } 184 if (status & AUD_INT_DN_SYNC) { 185 dprintk(1, "Downstream sync error\n"); 186 cx_write(AUD_INT_A_GPCNT_CTL, GP_COUNT_CONTROL_RESET); 187 return 1; 188 } 189 /* risc1 downstream */ 190 if (status & AUD_INT_DN_RISCI1) { 191 atomic_set(&chip->count, cx_read(AUD_INT_A_GPCNT)); 192 snd_pcm_period_elapsed(chip->substream); 193 } 194 /* FIXME: Any other status should deserve a special handling? */ 195 196 return 1; 197 } 198 199 static int dsp_buffer_free(struct cx23885_audio_dev *chip) 200 { 201 BUG_ON(!chip->dma_size); 202 203 dprintk(2, "Freeing buffer\n"); 204 videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc); 205 videobuf_dma_free(chip->dma_risc); 206 btcx_riscmem_free(chip->pci, &chip->buf->risc); 207 kfree(chip->buf); 208 209 chip->dma_risc = NULL; 210 chip->dma_size = 0; 211 212 return 0; 213 } 214 215 /**************************************************************************** 216 ALSA PCM Interface 217 ****************************************************************************/ 218 219 /* 220 * Digital hardware definition 221 */ 222 #define DEFAULT_FIFO_SIZE 4096 223 224 static struct snd_pcm_hardware snd_cx23885_digital_hw = { 225 .info = SNDRV_PCM_INFO_MMAP | 226 SNDRV_PCM_INFO_INTERLEAVED | 227 SNDRV_PCM_INFO_BLOCK_TRANSFER | 228 SNDRV_PCM_INFO_MMAP_VALID, 229 .formats = SNDRV_PCM_FMTBIT_S16_LE, 230 231 .rates = SNDRV_PCM_RATE_48000, 232 .rate_min = 48000, 233 .rate_max = 48000, 234 .channels_min = 2, 235 .channels_max = 2, 236 /* Analog audio output will be full of clicks and pops if there 237 are not exactly four lines in the SRAM FIFO buffer. */ 238 .period_bytes_min = DEFAULT_FIFO_SIZE/4, 239 .period_bytes_max = DEFAULT_FIFO_SIZE/4, 240 .periods_min = 1, 241 .periods_max = 1024, 242 .buffer_bytes_max = (1024*1024), 243 }; 244 245 /* 246 * audio pcm capture open callback 247 */ 248 static int snd_cx23885_pcm_open(struct snd_pcm_substream *substream) 249 { 250 struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream); 251 struct snd_pcm_runtime *runtime = substream->runtime; 252 int err; 253 254 if (!chip) { 255 printk(KERN_ERR "BUG: cx23885 can't find device struct." 256 " Can't proceed with open\n"); 257 return -ENODEV; 258 } 259 260 err = snd_pcm_hw_constraint_pow2(runtime, 0, 261 SNDRV_PCM_HW_PARAM_PERIODS); 262 if (err < 0) 263 goto _error; 264 265 chip->substream = substream; 266 267 runtime->hw = snd_cx23885_digital_hw; 268 269 if (chip->dev->sram_channels[AUDIO_SRAM_CHANNEL].fifo_size != 270 DEFAULT_FIFO_SIZE) { 271 unsigned int bpl = chip->dev-> 272 sram_channels[AUDIO_SRAM_CHANNEL].fifo_size / 4; 273 bpl &= ~7; /* must be multiple of 8 */ 274 runtime->hw.period_bytes_min = bpl; 275 runtime->hw.period_bytes_max = bpl; 276 } 277 278 return 0; 279 _error: 280 dprintk(1, "Error opening PCM!\n"); 281 return err; 282 } 283 284 /* 285 * audio close callback 286 */ 287 static int snd_cx23885_close(struct snd_pcm_substream *substream) 288 { 289 return 0; 290 } 291 292 /* 293 * hw_params callback 294 */ 295 static int snd_cx23885_hw_params(struct snd_pcm_substream *substream, 296 struct snd_pcm_hw_params *hw_params) 297 { 298 struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream); 299 struct videobuf_dmabuf *dma; 300 301 struct cx23885_audio_buffer *buf; 302 int ret; 303 304 if (substream->runtime->dma_area) { 305 dsp_buffer_free(chip); 306 substream->runtime->dma_area = NULL; 307 } 308 309 chip->period_size = params_period_bytes(hw_params); 310 chip->num_periods = params_periods(hw_params); 311 chip->dma_size = chip->period_size * params_periods(hw_params); 312 313 BUG_ON(!chip->dma_size); 314 BUG_ON(chip->num_periods & (chip->num_periods-1)); 315 316 buf = kzalloc(sizeof(*buf), GFP_KERNEL); 317 if (NULL == buf) 318 return -ENOMEM; 319 320 buf->bpl = chip->period_size; 321 322 dma = &buf->dma; 323 videobuf_dma_init(dma); 324 ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, 325 (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); 326 if (ret < 0) 327 goto error; 328 329 ret = videobuf_dma_map(&chip->pci->dev, dma); 330 if (ret < 0) 331 goto error; 332 333 ret = cx23885_risc_databuffer(chip->pci, &buf->risc, dma->sglist, 334 chip->period_size, chip->num_periods, 1); 335 if (ret < 0) 336 goto error; 337 338 /* Loop back to start of program */ 339 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC); 340 buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); 341 buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ 342 343 chip->buf = buf; 344 chip->dma_risc = dma; 345 346 substream->runtime->dma_area = chip->dma_risc->vaddr; 347 substream->runtime->dma_bytes = chip->dma_size; 348 substream->runtime->dma_addr = 0; 349 350 return 0; 351 352 error: 353 kfree(buf); 354 return ret; 355 } 356 357 /* 358 * hw free callback 359 */ 360 static int snd_cx23885_hw_free(struct snd_pcm_substream *substream) 361 { 362 363 struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream); 364 365 if (substream->runtime->dma_area) { 366 dsp_buffer_free(chip); 367 substream->runtime->dma_area = NULL; 368 } 369 370 return 0; 371 } 372 373 /* 374 * prepare callback 375 */ 376 static int snd_cx23885_prepare(struct snd_pcm_substream *substream) 377 { 378 return 0; 379 } 380 381 /* 382 * trigger callback 383 */ 384 static int snd_cx23885_card_trigger(struct snd_pcm_substream *substream, 385 int cmd) 386 { 387 struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream); 388 int err; 389 390 /* Local interrupts are already disabled by ALSA */ 391 spin_lock(&chip->lock); 392 393 switch (cmd) { 394 case SNDRV_PCM_TRIGGER_START: 395 err = cx23885_start_audio_dma(chip); 396 break; 397 case SNDRV_PCM_TRIGGER_STOP: 398 err = cx23885_stop_audio_dma(chip); 399 break; 400 default: 401 err = -EINVAL; 402 break; 403 } 404 405 spin_unlock(&chip->lock); 406 407 return err; 408 } 409 410 /* 411 * pointer callback 412 */ 413 static snd_pcm_uframes_t snd_cx23885_pointer( 414 struct snd_pcm_substream *substream) 415 { 416 struct cx23885_audio_dev *chip = snd_pcm_substream_chip(substream); 417 struct snd_pcm_runtime *runtime = substream->runtime; 418 u16 count; 419 420 count = atomic_read(&chip->count); 421 422 return runtime->period_size * (count & (runtime->periods-1)); 423 } 424 425 /* 426 * page callback (needed for mmap) 427 */ 428 static struct page *snd_cx23885_page(struct snd_pcm_substream *substream, 429 unsigned long offset) 430 { 431 void *pageptr = substream->runtime->dma_area + offset; 432 return vmalloc_to_page(pageptr); 433 } 434 435 /* 436 * operators 437 */ 438 static struct snd_pcm_ops snd_cx23885_pcm_ops = { 439 .open = snd_cx23885_pcm_open, 440 .close = snd_cx23885_close, 441 .ioctl = snd_pcm_lib_ioctl, 442 .hw_params = snd_cx23885_hw_params, 443 .hw_free = snd_cx23885_hw_free, 444 .prepare = snd_cx23885_prepare, 445 .trigger = snd_cx23885_card_trigger, 446 .pointer = snd_cx23885_pointer, 447 .page = snd_cx23885_page, 448 }; 449 450 /* 451 * create a PCM device 452 */ 453 static int snd_cx23885_pcm(struct cx23885_audio_dev *chip, int device, 454 char *name) 455 { 456 int err; 457 struct snd_pcm *pcm; 458 459 err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); 460 if (err < 0) 461 return err; 462 pcm->private_data = chip; 463 strcpy(pcm->name, name); 464 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx23885_pcm_ops); 465 466 return 0; 467 } 468 469 /**************************************************************************** 470 Basic Flow for Sound Devices 471 ****************************************************************************/ 472 473 /* 474 * Alsa Constructor - Component probe 475 */ 476 477 struct cx23885_audio_dev *cx23885_audio_register(struct cx23885_dev *dev) 478 { 479 struct snd_card *card; 480 struct cx23885_audio_dev *chip; 481 int err; 482 483 if (disable_analog_audio) 484 return NULL; 485 486 if (dev->sram_channels[AUDIO_SRAM_CHANNEL].cmds_start == 0) { 487 printk(KERN_WARNING "%s(): Missing SRAM channel configuration " 488 "for analog TV Audio\n", __func__); 489 return NULL; 490 } 491 492 err = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, 493 THIS_MODULE, sizeof(struct cx23885_audio_dev), &card); 494 if (err < 0) 495 goto error; 496 497 chip = (struct cx23885_audio_dev *) card->private_data; 498 chip->dev = dev; 499 chip->pci = dev->pci; 500 chip->card = card; 501 spin_lock_init(&chip->lock); 502 503 snd_card_set_dev(card, &dev->pci->dev); 504 505 err = snd_cx23885_pcm(chip, 0, "CX23885 Digital"); 506 if (err < 0) 507 goto error; 508 509 strcpy(card->driver, "CX23885"); 510 sprintf(card->shortname, "Conexant CX23885"); 511 sprintf(card->longname, "%s at %s", card->shortname, dev->name); 512 513 err = snd_card_register(card); 514 if (err < 0) 515 goto error; 516 517 dprintk(0, "registered ALSA audio device\n"); 518 519 return chip; 520 521 error: 522 snd_card_free(card); 523 printk(KERN_ERR "%s(): Failed to register analog " 524 "audio adapter\n", __func__); 525 526 return NULL; 527 } 528 529 /* 530 * ALSA destructor 531 */ 532 void cx23885_audio_unregister(struct cx23885_dev *dev) 533 { 534 struct cx23885_audio_dev *chip = dev->audio_dev; 535 536 snd_card_free(chip->card); 537 } 538