PageRenderTime 77ms CodeModel.GetById 27ms app.highlight 46ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/media/video/cx88/cx88-alsa.c

https://bitbucket.org/ndreys/linux-sunxi
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 */