/drivers/media/video/cx88/cx88-alsa.c
C | 1003 lines | 662 code | 183 blank | 158 comment | 65 complexity | f5094a90ff24965442cc0c987717ee1f MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
1/* 2 * 3 * Support for audio capture 4 * PCI function #1 of the cx2388x. 5 * 6 * (c) 2007 Trent Piepho <xyzzy@speakeasy.org> 7 * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org> 8 * (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org> 9 * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org> 10 * Based on dummy.c by Jaroslav Kysela <perex@perex.cz> 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License as published by 14 * the Free Software Foundation; either version 2 of the License, or 15 * (at your option) any later version. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 */ 26 27#include <linux/module.h> 28#include <linux/init.h> 29#include <linux/device.h> 30#include <linux/interrupt.h> 31#include <linux/vmalloc.h> 32#include <linux/dma-mapping.h> 33#include <linux/pci.h> 34#include <linux/slab.h> 35 36#include <asm/delay.h> 37#include <sound/core.h> 38#include <sound/pcm.h> 39#include <sound/pcm_params.h> 40#include <sound/control.h> 41#include <sound/initval.h> 42#include <sound/tlv.h> 43#include <media/wm8775.h> 44 45#include "cx88.h" 46#include "cx88-reg.h" 47 48#define dprintk(level,fmt, arg...) if (debug >= level) \ 49 printk(KERN_INFO "%s/1: " fmt, chip->core->name , ## arg) 50 51#define dprintk_core(level,fmt, arg...) if (debug >= level) \ 52 printk(KERN_DEBUG "%s/1: " fmt, chip->core->name , ## arg) 53 54/**************************************************************************** 55 Data type declarations - Can be moded to a header file later 56 ****************************************************************************/ 57 58struct cx88_audio_buffer { 59 unsigned int bpl; 60 struct btcx_riscmem risc; 61 struct videobuf_dmabuf dma; 62}; 63 64struct cx88_audio_dev { 65 struct cx88_core *core; 66 struct cx88_dmaqueue q; 67 68 /* pci i/o */ 69 struct pci_dev *pci; 70 71 /* audio controls */ 72 int irq; 73 74 struct snd_card *card; 75 76 spinlock_t reg_lock; 77 atomic_t count; 78 79 unsigned int dma_size; 80 unsigned int period_size; 81 unsigned int num_periods; 82 83 struct videobuf_dmabuf *dma_risc; 84 85 struct cx88_audio_buffer *buf; 86 87 struct snd_pcm_substream *substream; 88}; 89typedef struct cx88_audio_dev snd_cx88_card_t; 90 91 92 93/**************************************************************************** 94 Module global static vars 95 ****************************************************************************/ 96 97static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 98static const char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 99static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 1}; 100 101module_param_array(enable, bool, NULL, 0444); 102MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled."); 103 104module_param_array(index, int, NULL, 0444); 105MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s)."); 106 107 108/**************************************************************************** 109 Module macros 110 ****************************************************************************/ 111 112MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards"); 113MODULE_AUTHOR("Ricardo Cerqueira"); 114MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); 115MODULE_LICENSE("GPL"); 116MODULE_SUPPORTED_DEVICE("{{Conexant,23881}," 117 "{{Conexant,23882}," 118 "{{Conexant,23883}"); 119static unsigned int debug; 120module_param(debug,int,0644); 121MODULE_PARM_DESC(debug,"enable debug messages"); 122 123/**************************************************************************** 124 Module specific funtions 125 ****************************************************************************/ 126 127/* 128 * BOARD Specific: Sets audio DMA 129 */ 130 131static int _cx88_start_audio_dma(snd_cx88_card_t *chip) 132{ 133 struct cx88_audio_buffer *buf = chip->buf; 134 struct cx88_core *core=chip->core; 135 const struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; 136 137 /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */ 138 cx_clear(MO_AUD_DMACNTRL, 0x11); 139 140 /* setup fifo + format - out channel */ 141 cx88_sram_channel_setup(chip->core, audio_ch, buf->bpl, buf->risc.dma); 142 143 /* sets bpl size */ 144 cx_write(MO_AUDD_LNGTH, buf->bpl); 145 146 /* reset counter */ 147 cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET); 148 atomic_set(&chip->count, 0); 149 150 dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d " 151 "byte buffer\n", buf->bpl, cx_read(audio_ch->cmds_start + 8)>>1, 152 chip->num_periods, buf->bpl * chip->num_periods); 153 154 /* Enables corresponding bits at AUD_INT_STAT */ 155 cx_write(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | 156 AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); 157 158 /* Clean any pending interrupt bits already set */ 159 cx_write(MO_AUD_INTSTAT, ~0); 160 161 /* enable audio irqs */ 162 cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | PCI_INT_AUDINT); 163 164 /* start dma */ 165 cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */ 166 cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */ 167 168 if (debug) 169 cx88_sram_channel_dump(chip->core, audio_ch); 170 171 return 0; 172} 173 174/* 175 * BOARD Specific: Resets audio DMA 176 */ 177static int _cx88_stop_audio_dma(snd_cx88_card_t *chip) 178{ 179 struct cx88_core *core=chip->core; 180 dprintk(1, "Stopping audio DMA\n"); 181 182 /* stop dma */ 183 cx_clear(MO_AUD_DMACNTRL, 0x11); 184 185 /* disable irqs */ 186 cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT); 187 cx_clear(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | 188 AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); 189 190 if (debug) 191 cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]); 192 193 return 0; 194} 195 196#define MAX_IRQ_LOOP 50 197 198/* 199 * BOARD Specific: IRQ dma bits 200 */ 201static const char *cx88_aud_irqs[32] = { 202 "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */ 203 NULL, /* reserved */ 204 "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */ 205 NULL, /* reserved */ 206 "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */ 207 NULL, /* reserved */ 208 "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */ 209 NULL, /* reserved */ 210 "opc_err", "par_err", "rip_err", /* 16-18 */ 211 "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */ 212}; 213 214/* 215 * BOARD Specific: Threats IRQ audio specific calls 216 */ 217static void cx8801_aud_irq(snd_cx88_card_t *chip) 218{ 219 struct cx88_core *core = chip->core; 220 u32 status, mask; 221 222 status = cx_read(MO_AUD_INTSTAT); 223 mask = cx_read(MO_AUD_INTMSK); 224 if (0 == (status & mask)) 225 return; 226 cx_write(MO_AUD_INTSTAT, status); 227 if (debug > 1 || (status & mask & ~0xff)) 228 cx88_print_irqbits(core->name, "irq aud", 229 cx88_aud_irqs, ARRAY_SIZE(cx88_aud_irqs), 230 status, mask); 231 /* risc op code error */ 232 if (status & AUD_INT_OPC_ERR) { 233 printk(KERN_WARNING "%s/1: Audio risc op code error\n",core->name); 234 cx_clear(MO_AUD_DMACNTRL, 0x11); 235 cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH25]); 236 } 237 if (status & AUD_INT_DN_SYNC) { 238 dprintk(1, "Downstream sync error\n"); 239 cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET); 240 return; 241 } 242 /* risc1 downstream */ 243 if (status & AUD_INT_DN_RISCI1) { 244 atomic_set(&chip->count, cx_read(MO_AUDD_GPCNT)); 245 snd_pcm_period_elapsed(chip->substream); 246 } 247 /* FIXME: Any other status should deserve a special handling? */ 248} 249 250/* 251 * BOARD Specific: Handles IRQ calls 252 */ 253static irqreturn_t cx8801_irq(int irq, void *dev_id) 254{ 255 snd_cx88_card_t *chip = dev_id; 256 struct cx88_core *core = chip->core; 257 u32 status; 258 int loop, handled = 0; 259 260 for (loop = 0; loop < MAX_IRQ_LOOP; loop++) { 261 status = cx_read(MO_PCI_INTSTAT) & 262 (core->pci_irqmask | PCI_INT_AUDINT); 263 if (0 == status) 264 goto out; 265 dprintk(3, "cx8801_irq loop %d/%d, status %x\n", 266 loop, MAX_IRQ_LOOP, status); 267 handled = 1; 268 cx_write(MO_PCI_INTSTAT, status); 269 270 if (status & core->pci_irqmask) 271 cx88_core_irq(core, status); 272 if (status & PCI_INT_AUDINT) 273 cx8801_aud_irq(chip); 274 } 275 276 if (MAX_IRQ_LOOP == loop) { 277 printk(KERN_ERR 278 "%s/1: IRQ loop detected, disabling interrupts\n", 279 core->name); 280 cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT); 281 } 282 283 out: 284 return IRQ_RETVAL(handled); 285} 286 287 288static int dsp_buffer_free(snd_cx88_card_t *chip) 289{ 290 BUG_ON(!chip->dma_size); 291 292 dprintk(2,"Freeing buffer\n"); 293 videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc); 294 videobuf_dma_free(chip->dma_risc); 295 btcx_riscmem_free(chip->pci,&chip->buf->risc); 296 kfree(chip->buf); 297 298 chip->dma_risc = NULL; 299 chip->dma_size = 0; 300 301 return 0; 302} 303 304/**************************************************************************** 305 ALSA PCM Interface 306 ****************************************************************************/ 307 308/* 309 * Digital hardware definition 310 */ 311#define DEFAULT_FIFO_SIZE 4096 312static const struct snd_pcm_hardware snd_cx88_digital_hw = { 313 .info = SNDRV_PCM_INFO_MMAP | 314 SNDRV_PCM_INFO_INTERLEAVED | 315 SNDRV_PCM_INFO_BLOCK_TRANSFER | 316 SNDRV_PCM_INFO_MMAP_VALID, 317 .formats = SNDRV_PCM_FMTBIT_S16_LE, 318 319 .rates = SNDRV_PCM_RATE_48000, 320 .rate_min = 48000, 321 .rate_max = 48000, 322 .channels_min = 2, 323 .channels_max = 2, 324 /* Analog audio output will be full of clicks and pops if there 325 are not exactly four lines in the SRAM FIFO buffer. */ 326 .period_bytes_min = DEFAULT_FIFO_SIZE/4, 327 .period_bytes_max = DEFAULT_FIFO_SIZE/4, 328 .periods_min = 1, 329 .periods_max = 1024, 330 .buffer_bytes_max = (1024*1024), 331}; 332 333/* 334 * audio pcm capture open callback 335 */ 336static int snd_cx88_pcm_open(struct snd_pcm_substream *substream) 337{ 338 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); 339 struct snd_pcm_runtime *runtime = substream->runtime; 340 int err; 341 342 if (!chip) { 343 printk(KERN_ERR "BUG: cx88 can't find device struct." 344 " Can't proceed with open\n"); 345 return -ENODEV; 346 } 347 348 err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS); 349 if (err < 0) 350 goto _error; 351 352 chip->substream = substream; 353 354 runtime->hw = snd_cx88_digital_hw; 355 356 if (cx88_sram_channels[SRAM_CH25].fifo_size != DEFAULT_FIFO_SIZE) { 357 unsigned int bpl = cx88_sram_channels[SRAM_CH25].fifo_size / 4; 358 bpl &= ~7; /* must be multiple of 8 */ 359 runtime->hw.period_bytes_min = bpl; 360 runtime->hw.period_bytes_max = bpl; 361 } 362 363 return 0; 364_error: 365 dprintk(1,"Error opening PCM!\n"); 366 return err; 367} 368 369/* 370 * audio close callback 371 */ 372static int snd_cx88_close(struct snd_pcm_substream *substream) 373{ 374 return 0; 375} 376 377/* 378 * hw_params callback 379 */ 380static int snd_cx88_hw_params(struct snd_pcm_substream * substream, 381 struct snd_pcm_hw_params * hw_params) 382{ 383 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); 384 struct videobuf_dmabuf *dma; 385 386 struct cx88_audio_buffer *buf; 387 int ret; 388 389 if (substream->runtime->dma_area) { 390 dsp_buffer_free(chip); 391 substream->runtime->dma_area = NULL; 392 } 393 394 chip->period_size = params_period_bytes(hw_params); 395 chip->num_periods = params_periods(hw_params); 396 chip->dma_size = chip->period_size * params_periods(hw_params); 397 398 BUG_ON(!chip->dma_size); 399 BUG_ON(chip->num_periods & (chip->num_periods-1)); 400 401 buf = kzalloc(sizeof(*buf), GFP_KERNEL); 402 if (NULL == buf) 403 return -ENOMEM; 404 405 buf->bpl = chip->period_size; 406 407 dma = &buf->dma; 408 videobuf_dma_init(dma); 409 ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, 410 (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); 411 if (ret < 0) 412 goto error; 413 414 ret = videobuf_dma_map(&chip->pci->dev, dma); 415 if (ret < 0) 416 goto error; 417 418 ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist, 419 chip->period_size, chip->num_periods, 1); 420 if (ret < 0) 421 goto error; 422 423 /* Loop back to start of program */ 424 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC); 425 buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); 426 427 chip->buf = buf; 428 chip->dma_risc = dma; 429 430 substream->runtime->dma_area = chip->dma_risc->vaddr; 431 substream->runtime->dma_bytes = chip->dma_size; 432 substream->runtime->dma_addr = 0; 433 return 0; 434 435error: 436 kfree(buf); 437 return ret; 438} 439 440/* 441 * hw free callback 442 */ 443static int snd_cx88_hw_free(struct snd_pcm_substream * substream) 444{ 445 446 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); 447 448 if (substream->runtime->dma_area) { 449 dsp_buffer_free(chip); 450 substream->runtime->dma_area = NULL; 451 } 452 453 return 0; 454} 455 456/* 457 * prepare callback 458 */ 459static int snd_cx88_prepare(struct snd_pcm_substream *substream) 460{ 461 return 0; 462} 463 464/* 465 * trigger callback 466 */ 467static int snd_cx88_card_trigger(struct snd_pcm_substream *substream, int cmd) 468{ 469 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); 470 int err; 471 472 /* Local interrupts are already disabled by ALSA */ 473 spin_lock(&chip->reg_lock); 474 475 switch (cmd) { 476 case SNDRV_PCM_TRIGGER_START: 477 err=_cx88_start_audio_dma(chip); 478 break; 479 case SNDRV_PCM_TRIGGER_STOP: 480 err=_cx88_stop_audio_dma(chip); 481 break; 482 default: 483 err=-EINVAL; 484 break; 485 } 486 487 spin_unlock(&chip->reg_lock); 488 489 return err; 490} 491 492/* 493 * pointer callback 494 */ 495static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream) 496{ 497 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); 498 struct snd_pcm_runtime *runtime = substream->runtime; 499 u16 count; 500 501 count = atomic_read(&chip->count); 502 503// dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __func__, 504// count, new, count & (runtime->periods-1), 505// runtime->period_size * (count & (runtime->periods-1))); 506 return runtime->period_size * (count & (runtime->periods-1)); 507} 508 509/* 510 * page callback (needed for mmap) 511 */ 512static struct page *snd_cx88_page(struct snd_pcm_substream *substream, 513 unsigned long offset) 514{ 515 void *pageptr = substream->runtime->dma_area + offset; 516 return vmalloc_to_page(pageptr); 517} 518 519/* 520 * operators 521 */ 522static struct snd_pcm_ops snd_cx88_pcm_ops = { 523 .open = snd_cx88_pcm_open, 524 .close = snd_cx88_close, 525 .ioctl = snd_pcm_lib_ioctl, 526 .hw_params = snd_cx88_hw_params, 527 .hw_free = snd_cx88_hw_free, 528 .prepare = snd_cx88_prepare, 529 .trigger = snd_cx88_card_trigger, 530 .pointer = snd_cx88_pointer, 531 .page = snd_cx88_page, 532}; 533 534/* 535 * create a PCM device 536 */ 537static int __devinit snd_cx88_pcm(snd_cx88_card_t *chip, int device, const char *name) 538{ 539 int err; 540 struct snd_pcm *pcm; 541 542 err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); 543 if (err < 0) 544 return err; 545 pcm->private_data = chip; 546 strcpy(pcm->name, name); 547 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops); 548 549 return 0; 550} 551 552/**************************************************************************** 553 CONTROL INTERFACE 554 ****************************************************************************/ 555static int snd_cx88_volume_info(struct snd_kcontrol *kcontrol, 556 struct snd_ctl_elem_info *info) 557{ 558 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 559 info->count = 2; 560 info->value.integer.min = 0; 561 info->value.integer.max = 0x3f; 562 563 return 0; 564} 565 566static int snd_cx88_volume_get(struct snd_kcontrol *kcontrol, 567 struct snd_ctl_elem_value *value) 568{ 569 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); 570 struct cx88_core *core=chip->core; 571 int vol = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f), 572 bal = cx_read(AUD_BAL_CTL); 573 574 value->value.integer.value[(bal & 0x40) ? 0 : 1] = vol; 575 vol -= (bal & 0x3f); 576 value->value.integer.value[(bal & 0x40) ? 1 : 0] = vol < 0 ? 0 : vol; 577 578 return 0; 579} 580 581static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol, 582 struct snd_ctl_elem_value *value) 583{ 584 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); 585 struct cx88_core *core = chip->core; 586 struct v4l2_control client_ctl; 587 int left = value->value.integer.value[0]; 588 int right = value->value.integer.value[1]; 589 int v, b; 590 591 memset(&client_ctl, 0, sizeof(client_ctl)); 592 593 /* Pass volume & balance onto any WM8775 */ 594 if (left >= right) { 595 v = left << 10; 596 b = left ? (0x8000 * right) / left : 0x8000; 597 } else { 598 v = right << 10; 599 b = right ? 0xffff - (0x8000 * left) / right : 0x8000; 600 } 601 client_ctl.value = v; 602 client_ctl.id = V4L2_CID_AUDIO_VOLUME; 603 call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); 604 605 client_ctl.value = b; 606 client_ctl.id = V4L2_CID_AUDIO_BALANCE; 607 call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); 608} 609 610/* OK - TODO: test it */ 611static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol, 612 struct snd_ctl_elem_value *value) 613{ 614 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); 615 struct cx88_core *core=chip->core; 616 int left, right, v, b; 617 int changed = 0; 618 u32 old; 619 620 if (core->board.audio_chip == V4L2_IDENT_WM8775) 621 snd_cx88_wm8775_volume_put(kcontrol, value); 622 623 left = value->value.integer.value[0] & 0x3f; 624 right = value->value.integer.value[1] & 0x3f; 625 b = right - left; 626 if (b < 0) { 627 v = 0x3f - left; 628 b = (-b) | 0x40; 629 } else { 630 v = 0x3f - right; 631 } 632 /* Do we really know this will always be called with IRQs on? */ 633 spin_lock_irq(&chip->reg_lock); 634 old = cx_read(AUD_VOL_CTL); 635 if (v != (old & 0x3f)) { 636 cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v); 637 changed = 1; 638 } 639 if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) { 640 cx_write(AUD_BAL_CTL, b); 641 changed = 1; 642 } 643 spin_unlock_irq(&chip->reg_lock); 644 645 return changed; 646} 647 648static const DECLARE_TLV_DB_SCALE(snd_cx88_db_scale, -6300, 100, 0); 649 650static const struct snd_kcontrol_new snd_cx88_volume = { 651 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 652 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | 653 SNDRV_CTL_ELEM_ACCESS_TLV_READ, 654 .name = "Analog-TV Volume", 655 .info = snd_cx88_volume_info, 656 .get = snd_cx88_volume_get, 657 .put = snd_cx88_volume_put, 658 .tlv.p = snd_cx88_db_scale, 659}; 660 661static int snd_cx88_switch_get(struct snd_kcontrol *kcontrol, 662 struct snd_ctl_elem_value *value) 663{ 664 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); 665 struct cx88_core *core = chip->core; 666 u32 bit = kcontrol->private_value; 667 668 value->value.integer.value[0] = !(cx_read(AUD_VOL_CTL) & bit); 669 return 0; 670} 671 672static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol, 673 struct snd_ctl_elem_value *value) 674{ 675 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); 676 struct cx88_core *core = chip->core; 677 u32 bit = kcontrol->private_value; 678 int ret = 0; 679 u32 vol; 680 681 spin_lock_irq(&chip->reg_lock); 682 vol = cx_read(AUD_VOL_CTL); 683 if (value->value.integer.value[0] != !(vol & bit)) { 684 vol ^= bit; 685 cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol); 686 /* Pass mute onto any WM8775 */ 687 if ((core->board.audio_chip == V4L2_IDENT_WM8775) && 688 ((1<<6) == bit)) { 689 struct v4l2_control client_ctl; 690 691 memset(&client_ctl, 0, sizeof(client_ctl)); 692 client_ctl.value = 0 != (vol & bit); 693 client_ctl.id = V4L2_CID_AUDIO_MUTE; 694 call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); 695 } 696 ret = 1; 697 } 698 spin_unlock_irq(&chip->reg_lock); 699 return ret; 700} 701 702static const struct snd_kcontrol_new snd_cx88_dac_switch = { 703 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 704 .name = "Audio-Out Switch", 705 .info = snd_ctl_boolean_mono_info, 706 .get = snd_cx88_switch_get, 707 .put = snd_cx88_switch_put, 708 .private_value = (1<<8), 709}; 710 711static const struct snd_kcontrol_new snd_cx88_source_switch = { 712 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 713 .name = "Analog-TV Switch", 714 .info = snd_ctl_boolean_mono_info, 715 .get = snd_cx88_switch_get, 716 .put = snd_cx88_switch_put, 717 .private_value = (1<<6), 718}; 719 720static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol, 721 struct snd_ctl_elem_value *value) 722{ 723 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); 724 struct cx88_core *core = chip->core; 725 struct v4l2_control client_ctl; 726 727 memset(&client_ctl, 0, sizeof(client_ctl)); 728 client_ctl.id = V4L2_CID_AUDIO_LOUDNESS; 729 call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl); 730 value->value.integer.value[0] = client_ctl.value ? 1 : 0; 731 732 return 0; 733} 734 735static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol, 736 struct snd_ctl_elem_value *value) 737{ 738 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); 739 struct cx88_core *core = chip->core; 740 struct v4l2_control client_ctl; 741 742 memset(&client_ctl, 0, sizeof(client_ctl)); 743 client_ctl.value = 0 != value->value.integer.value[0]; 744 client_ctl.id = V4L2_CID_AUDIO_LOUDNESS; 745 call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl); 746 747 return 0; 748} 749 750static struct snd_kcontrol_new snd_cx88_alc_switch = { 751 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 752 .name = "Line-In ALC Switch", 753 .info = snd_ctl_boolean_mono_info, 754 .get = snd_cx88_alc_get, 755 .put = snd_cx88_alc_put, 756}; 757 758/**************************************************************************** 759 Basic Flow for Sound Devices 760 ****************************************************************************/ 761 762/* 763 * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio 764 * Only boards with eeprom and byte 1 at eeprom=1 have it 765 */ 766 767static const struct pci_device_id const cx88_audio_pci_tbl[] __devinitdata = { 768 {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, 769 {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0}, 770 {0, } 771}; 772MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl); 773 774/* 775 * Chip-specific destructor 776 */ 777 778static int snd_cx88_free(snd_cx88_card_t *chip) 779{ 780 781 if (chip->irq >= 0) 782 free_irq(chip->irq, chip); 783 784 cx88_core_put(chip->core,chip->pci); 785 786 pci_disable_device(chip->pci); 787 return 0; 788} 789 790/* 791 * Component Destructor 792 */ 793static void snd_cx88_dev_free(struct snd_card * card) 794{ 795 snd_cx88_card_t *chip = card->private_data; 796 797 snd_cx88_free(chip); 798} 799 800 801/* 802 * Alsa Constructor - Component probe 803 */ 804 805static int devno; 806static int __devinit snd_cx88_create(struct snd_card *card, 807 struct pci_dev *pci, 808 snd_cx88_card_t **rchip, 809 struct cx88_core **core_ptr) 810{ 811 snd_cx88_card_t *chip; 812 struct cx88_core *core; 813 int err; 814 unsigned char pci_lat; 815 816 *rchip = NULL; 817 818 err = pci_enable_device(pci); 819 if (err < 0) 820 return err; 821 822 pci_set_master(pci); 823 824 chip = card->private_data; 825 826 core = cx88_core_get(pci); 827 if (NULL == core) { 828 err = -EINVAL; 829 return err; 830 } 831 832 if (!pci_dma_supported(pci,DMA_BIT_MASK(32))) { 833 dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name); 834 err = -EIO; 835 cx88_core_put(core, pci); 836 return err; 837 } 838 839 840 /* pci init */ 841 chip->card = card; 842 chip->pci = pci; 843 chip->irq = -1; 844 spin_lock_init(&chip->reg_lock); 845 846 chip->core = core; 847 848 /* get irq */ 849 err = request_irq(chip->pci->irq, cx8801_irq, 850 IRQF_SHARED | IRQF_DISABLED, chip->core->name, chip); 851 if (err < 0) { 852 dprintk(0, "%s: can't get IRQ %d\n", 853 chip->core->name, chip->pci->irq); 854 return err; 855 } 856 857 /* print pci info */ 858 pci_read_config_byte(pci, PCI_LATENCY_TIMER, &pci_lat); 859 860 dprintk(1,"ALSA %s/%i: found at %s, rev: %d, irq: %d, " 861 "latency: %d, mmio: 0x%llx\n", core->name, devno, 862 pci_name(pci), pci->revision, pci->irq, 863 pci_lat, (unsigned long long)pci_resource_start(pci,0)); 864 865 chip->irq = pci->irq; 866 synchronize_irq(chip->irq); 867 868 snd_card_set_dev(card, &pci->dev); 869 870 *rchip = chip; 871 *core_ptr = core; 872 873 return 0; 874} 875 876static int __devinit cx88_audio_initdev(struct pci_dev *pci, 877 const struct pci_device_id *pci_id) 878{ 879 struct snd_card *card; 880 snd_cx88_card_t *chip; 881 struct cx88_core *core = NULL; 882 int err; 883 884 if (devno >= SNDRV_CARDS) 885 return (-ENODEV); 886 887 if (!enable[devno]) { 888 ++devno; 889 return (-ENOENT); 890 } 891 892 err = snd_card_create(index[devno], id[devno], THIS_MODULE, 893 sizeof(snd_cx88_card_t), &card); 894 if (err < 0) 895 return err; 896 897 card->private_free = snd_cx88_dev_free; 898 899 err = snd_cx88_create(card, pci, &chip, &core); 900 if (err < 0) 901 goto error; 902 903 err = snd_cx88_pcm(chip, 0, "CX88 Digital"); 904 if (err < 0) 905 goto error; 906 907 err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_volume, chip)); 908 if (err < 0) 909 goto error; 910 err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_dac_switch, chip)); 911 if (err < 0) 912 goto error; 913 err = snd_ctl_add(card, snd_ctl_new1(&snd_cx88_source_switch, chip)); 914 if (err < 0) 915 goto error; 916 917 /* If there's a wm8775 then add a Line-In ALC switch */ 918 if (core->board.audio_chip == V4L2_IDENT_WM8775) 919 snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, chip)); 920 921 strcpy (card->driver, "CX88x"); 922 sprintf(card->shortname, "Conexant CX%x", pci->device); 923 sprintf(card->longname, "%s at %#llx", 924 card->shortname,(unsigned long long)pci_resource_start(pci, 0)); 925 strcpy (card->mixername, "CX88"); 926 927 dprintk (0, "%s/%i: ALSA support for cx2388x boards\n", 928 card->driver,devno); 929 930 err = snd_card_register(card); 931 if (err < 0) 932 goto error; 933 pci_set_drvdata(pci,card); 934 935 devno++; 936 return 0; 937 938error: 939 snd_card_free(card); 940 return err; 941} 942/* 943 * ALSA destructor 944 */ 945static void __devexit cx88_audio_finidev(struct pci_dev *pci) 946{ 947 struct cx88_audio_dev *card = pci_get_drvdata(pci); 948 949 snd_card_free((void *)card); 950 951 pci_set_drvdata(pci, NULL); 952 953 devno--; 954} 955 956/* 957 * PCI driver definition 958 */ 959 960static struct pci_driver cx88_audio_pci_driver = { 961 .name = "cx88_audio", 962 .id_table = cx88_audio_pci_tbl, 963 .probe = cx88_audio_initdev, 964 .remove = __devexit_p(cx88_audio_finidev), 965}; 966 967/**************************************************************************** 968 LINUX MODULE INIT 969 ****************************************************************************/ 970 971/* 972 * module init 973 */ 974static int __init cx88_audio_init(void) 975{ 976 printk(KERN_INFO "cx2388x alsa driver version %d.%d.%d loaded\n", 977 (CX88_VERSION_CODE >> 16) & 0xff, 978 (CX88_VERSION_CODE >> 8) & 0xff, 979 CX88_VERSION_CODE & 0xff); 980#ifdef SNAPSHOT 981 printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", 982 SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); 983#endif 984 return pci_register_driver(&cx88_audio_pci_driver); 985} 986 987/* 988 * module remove 989 */ 990static void __exit cx88_audio_fini(void) 991{ 992 pci_unregister_driver(&cx88_audio_pci_driver); 993} 994 995module_init(cx88_audio_init); 996module_exit(cx88_audio_fini); 997 998/* ----------------------------------------------------------- */ 999/* 1000 * Local variables: 1001 * c-basic-offset: 8 1002 * End: 1003 */