cx88-alsa.c (7b61ba8ff838dbee422d428fbd882ab83db4b2d9) | cx88-alsa.c (399426cadf5b0539a5b2a4d805257ce8acc6aba2) |
---|---|
1/* 2 * Support for audio capture 3 * PCI function #1 of the cx2388x. 4 * 5 * (c) 2007 Trent Piepho <xyzzy@speakeasy.org> 6 * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org> 7 * (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org> 8 * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org> --- 10 unchanged lines hidden (view full) --- 19 * GNU General Public License for more details. 20 */ 21 22#include "cx88.h" 23#include "cx88-reg.h" 24 25#include <linux/module.h> 26#include <linux/init.h> | 1/* 2 * Support for audio capture 3 * PCI function #1 of the cx2388x. 4 * 5 * (c) 2007 Trent Piepho <xyzzy@speakeasy.org> 6 * (c) 2005,2006 Ricardo Cerqueira <v4l@cerqueira.org> 7 * (c) 2005 Mauro Carvalho Chehab <mchehab@infradead.org> 8 * Based on a dummy cx88 module by Gerd Knorr <kraxel@bytesex.org> --- 10 unchanged lines hidden (view full) --- 19 * GNU General Public License for more details. 20 */ 21 22#include "cx88.h" 23#include "cx88-reg.h" 24 25#include <linux/module.h> 26#include <linux/init.h> |
27#include <linux/delay.h> |
|
27#include <linux/device.h> 28#include <linux/interrupt.h> 29#include <linux/vmalloc.h> 30#include <linux/dma-mapping.h> 31#include <linux/pci.h> 32#include <linux/slab.h> 33 | 28#include <linux/device.h> 29#include <linux/interrupt.h> 30#include <linux/vmalloc.h> 31#include <linux/dma-mapping.h> 32#include <linux/pci.h> 33#include <linux/slab.h> 34 |
34#include <asm/delay.h> | |
35#include <sound/core.h> 36#include <sound/pcm.h> 37#include <sound/pcm_params.h> 38#include <sound/control.h> 39#include <sound/initval.h> 40#include <sound/tlv.h> 41#include <media/i2c/wm8775.h> 42 43#define dprintk(level, fmt, arg...) do { \ 44 if (debug + 1 > level) \ 45 printk(KERN_DEBUG pr_fmt("%s: alsa: " fmt), \ 46 chip->core->name, ##arg); \ 47} while (0) 48 | 35#include <sound/core.h> 36#include <sound/pcm.h> 37#include <sound/pcm_params.h> 38#include <sound/control.h> 39#include <sound/initval.h> 40#include <sound/tlv.h> 41#include <media/i2c/wm8775.h> 42 43#define dprintk(level, fmt, arg...) do { \ 44 if (debug + 1 > level) \ 45 printk(KERN_DEBUG pr_fmt("%s: alsa: " fmt), \ 46 chip->core->name, ##arg); \ 47} while (0) 48 |
49/**************************************************************************** 50 Data type declarations - Can be moded to a header file later 51 ****************************************************************************/ | 49/* 50 * Data type declarations - Can be moded to a header file later 51 */ |
52 53struct cx88_audio_buffer { 54 unsigned int bpl; 55 struct cx88_riscmem risc; 56 void *vaddr; 57 struct scatterlist *sglist; 58 int sglen; 59 int nr_pages; --- 17 unchanged lines hidden (view full) --- 77 unsigned int dma_size; 78 unsigned int period_size; 79 unsigned int num_periods; 80 81 struct cx88_audio_buffer *buf; 82 83 struct snd_pcm_substream *substream; 84}; | 52 53struct cx88_audio_buffer { 54 unsigned int bpl; 55 struct cx88_riscmem risc; 56 void *vaddr; 57 struct scatterlist *sglist; 58 int sglen; 59 int nr_pages; --- 17 unchanged lines hidden (view full) --- 77 unsigned int dma_size; 78 unsigned int period_size; 79 unsigned int num_periods; 80 81 struct cx88_audio_buffer *buf; 82 83 struct snd_pcm_substream *substream; 84}; |
85typedef struct cx88_audio_dev snd_cx88_card_t; | |
86 | 85 |
86/* 87 * Module global static vars 88 */ |
|
87 | 89 |
88 89/**************************************************************************** 90 Module global static vars 91 ****************************************************************************/ 92 | |
93static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 94static const char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 95static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; 96 97module_param_array(enable, bool, NULL, 0444); 98MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled."); 99 100module_param_array(index, int, NULL, 0444); 101MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s)."); 102 | 90static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 91static const char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 92static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; 93 94module_param_array(enable, bool, NULL, 0444); 95MODULE_PARM_DESC(enable, "Enable cx88x soundcard. default enabled."); 96 97module_param_array(index, int, NULL, 0444); 98MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s)."); 99 |
100/* 101 * Module macros 102 */ |
|
103 | 103 |
104/**************************************************************************** 105 Module macros 106 ****************************************************************************/ 107 | |
108MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards"); 109MODULE_AUTHOR("Ricardo Cerqueira"); 110MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); 111MODULE_LICENSE("GPL"); 112MODULE_VERSION(CX88_VERSION); 113 114MODULE_SUPPORTED_DEVICE("{{Conexant,23881},{{Conexant,23882},{{Conexant,23883}"); 115static unsigned int debug; 116module_param(debug, int, 0644); 117MODULE_PARM_DESC(debug, "enable debug messages"); 118 | 104MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards"); 105MODULE_AUTHOR("Ricardo Cerqueira"); 106MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); 107MODULE_LICENSE("GPL"); 108MODULE_VERSION(CX88_VERSION); 109 110MODULE_SUPPORTED_DEVICE("{{Conexant,23881},{{Conexant,23882},{{Conexant,23883}"); 111static unsigned int debug; 112module_param(debug, int, 0644); 113MODULE_PARM_DESC(debug, "enable debug messages"); 114 |
119/**************************************************************************** 120 Module specific funtions 121 ****************************************************************************/ | 115/* 116 * Module specific functions 117 */ |
122 123/* 124 * BOARD Specific: Sets audio DMA 125 */ 126 | 118 119/* 120 * BOARD Specific: Sets audio DMA 121 */ 122 |
127static int _cx88_start_audio_dma(snd_cx88_card_t *chip) | 123static int _cx88_start_audio_dma(struct cx88_audio_dev *chip) |
128{ 129 struct cx88_audio_buffer *buf = chip->buf; 130 struct cx88_core *core = chip->core; 131 const struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; 132 133 /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */ 134 cx_clear(MO_AUD_DMACNTRL, 0x11); 135 136 /* setup fifo + format - out channel */ 137 cx88_sram_channel_setup(chip->core, audio_ch, buf->bpl, buf->risc.dma); 138 139 /* sets bpl size */ 140 cx_write(MO_AUDD_LNGTH, buf->bpl); 141 142 /* reset counter */ 143 cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET); 144 atomic_set(&chip->count, 0); 145 | 124{ 125 struct cx88_audio_buffer *buf = chip->buf; 126 struct cx88_core *core = chip->core; 127 const struct sram_channel *audio_ch = &cx88_sram_channels[SRAM_CH25]; 128 129 /* Make sure RISC/FIFO are off before changing FIFO/RISC settings */ 130 cx_clear(MO_AUD_DMACNTRL, 0x11); 131 132 /* setup fifo + format - out channel */ 133 cx88_sram_channel_setup(chip->core, audio_ch, buf->bpl, buf->risc.dma); 134 135 /* sets bpl size */ 136 cx_write(MO_AUDD_LNGTH, buf->bpl); 137 138 /* reset counter */ 139 cx_write(MO_AUDD_GPCNTRL, GP_COUNT_CONTROL_RESET); 140 atomic_set(&chip->count, 0); 141 |
146 dprintk(1, "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d byte buffer\n", 147 buf->bpl, cx_read(audio_ch->cmds_start + 8)>>1, | 142 dprintk(1, 143 "Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d byte buffer\n", 144 buf->bpl, cx_read(audio_ch->cmds_start + 8) >> 1, |
148 chip->num_periods, buf->bpl * chip->num_periods); 149 150 /* Enables corresponding bits at AUD_INT_STAT */ 151 cx_write(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | 152 AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); 153 154 /* Clean any pending interrupt bits already set */ 155 cx_write(MO_AUD_INTSTAT, ~0); 156 157 /* enable audio irqs */ 158 cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | PCI_INT_AUDINT); 159 160 /* start dma */ | 145 chip->num_periods, buf->bpl * chip->num_periods); 146 147 /* Enables corresponding bits at AUD_INT_STAT */ 148 cx_write(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | 149 AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); 150 151 /* Clean any pending interrupt bits already set */ 152 cx_write(MO_AUD_INTSTAT, ~0); 153 154 /* enable audio irqs */ 155 cx_set(MO_PCI_INTMSK, chip->core->pci_irqmask | PCI_INT_AUDINT); 156 157 /* start dma */ |
161 cx_set(MO_DEV_CNTRL2, (1<<5)); /* Enables Risc Processor */ 162 cx_set(MO_AUD_DMACNTRL, 0x11); /* audio downstream FIFO and RISC enable */ | |
163 | 158 |
159 /* Enables Risc Processor */ 160 cx_set(MO_DEV_CNTRL2, (1 << 5)); 161 /* audio downstream FIFO and RISC enable */ 162 cx_set(MO_AUD_DMACNTRL, 0x11); 163 |
|
164 if (debug) 165 cx88_sram_channel_dump(chip->core, audio_ch); 166 167 return 0; 168} 169 170/* 171 * BOARD Specific: Resets audio DMA 172 */ | 164 if (debug) 165 cx88_sram_channel_dump(chip->core, audio_ch); 166 167 return 0; 168} 169 170/* 171 * BOARD Specific: Resets audio DMA 172 */ |
173static int _cx88_stop_audio_dma(snd_cx88_card_t *chip) | 173static int _cx88_stop_audio_dma(struct cx88_audio_dev *chip) |
174{ 175 struct cx88_core *core = chip->core; 176 177 dprintk(1, "Stopping audio DMA\n"); 178 179 /* stop dma */ 180 cx_clear(MO_AUD_DMACNTRL, 0x11); 181 182 /* disable irqs */ 183 cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT); 184 cx_clear(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | 185 AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); 186 187 if (debug) | 174{ 175 struct cx88_core *core = chip->core; 176 177 dprintk(1, "Stopping audio DMA\n"); 178 179 /* stop dma */ 180 cx_clear(MO_AUD_DMACNTRL, 0x11); 181 182 /* disable irqs */ 183 cx_clear(MO_PCI_INTMSK, PCI_INT_AUDINT); 184 cx_clear(MO_AUD_INTMSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | 185 AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); 186 187 if (debug) |
188 cx88_sram_channel_dump(chip->core, &cx88_sram_channels[SRAM_CH25]); | 188 cx88_sram_channel_dump(chip->core, 189 &cx88_sram_channels[SRAM_CH25]); |
189 190 return 0; 191} 192 193#define MAX_IRQ_LOOP 50 194 195/* 196 * BOARD Specific: IRQ dma bits --- 9 unchanged lines hidden (view full) --- 206 NULL, /* reserved */ 207 "opc_err", "par_err", "rip_err", /* 16-18 */ 208 "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */ 209}; 210 211/* 212 * BOARD Specific: Threats IRQ audio specific calls 213 */ | 190 191 return 0; 192} 193 194#define MAX_IRQ_LOOP 50 195 196/* 197 * BOARD Specific: IRQ dma bits --- 9 unchanged lines hidden (view full) --- 207 NULL, /* reserved */ 208 "opc_err", "par_err", "rip_err", /* 16-18 */ 209 "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */ 210}; 211 212/* 213 * BOARD Specific: Threats IRQ audio specific calls 214 */ |
214static void cx8801_aud_irq(snd_cx88_card_t *chip) | 215static void cx8801_aud_irq(struct cx88_audio_dev *chip) |
215{ 216 struct cx88_core *core = chip->core; 217 u32 status, mask; 218 219 status = cx_read(MO_AUD_INTSTAT); 220 mask = cx_read(MO_AUD_INTMSK); 221 if (0 == (status & mask)) 222 return; --- 21 unchanged lines hidden (view full) --- 244 /* FIXME: Any other status should deserve a special handling? */ 245} 246 247/* 248 * BOARD Specific: Handles IRQ calls 249 */ 250static irqreturn_t cx8801_irq(int irq, void *dev_id) 251{ | 216{ 217 struct cx88_core *core = chip->core; 218 u32 status, mask; 219 220 status = cx_read(MO_AUD_INTSTAT); 221 mask = cx_read(MO_AUD_INTMSK); 222 if (0 == (status & mask)) 223 return; --- 21 unchanged lines hidden (view full) --- 245 /* FIXME: Any other status should deserve a special handling? */ 246} 247 248/* 249 * BOARD Specific: Handles IRQ calls 250 */ 251static irqreturn_t cx8801_irq(int irq, void *dev_id) 252{ |
252 snd_cx88_card_t *chip = dev_id; | 253 struct cx88_audio_dev *chip = dev_id; |
253 struct cx88_core *core = chip->core; 254 u32 status; 255 int loop, handled = 0; 256 257 for (loop = 0; loop < MAX_IRQ_LOOP; loop++) { 258 status = cx_read(MO_PCI_INTSTAT) & 259 (core->pci_irqmask | PCI_INT_AUDINT); 260 if (status == 0) --- 20 unchanged lines hidden (view full) --- 281 282static int cx88_alsa_dma_init(struct cx88_audio_dev *chip, int nr_pages) 283{ 284 struct cx88_audio_buffer *buf = chip->buf; 285 struct page *pg; 286 int i; 287 288 buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT); | 254 struct cx88_core *core = chip->core; 255 u32 status; 256 int loop, handled = 0; 257 258 for (loop = 0; loop < MAX_IRQ_LOOP; loop++) { 259 status = cx_read(MO_PCI_INTSTAT) & 260 (core->pci_irqmask | PCI_INT_AUDINT); 261 if (status == 0) --- 20 unchanged lines hidden (view full) --- 282 283static int cx88_alsa_dma_init(struct cx88_audio_dev *chip, int nr_pages) 284{ 285 struct cx88_audio_buffer *buf = chip->buf; 286 struct page *pg; 287 int i; 288 289 buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT); |
289 if (buf->vaddr == NULL) { | 290 if (!buf->vaddr) { |
290 dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages); 291 return -ENOMEM; 292 } 293 294 dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n", | 291 dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages); 292 return -ENOMEM; 293 } 294 295 dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n", |
295 (unsigned long)buf->vaddr, 296 nr_pages << PAGE_SHIFT); | 296 (unsigned long)buf->vaddr, nr_pages << PAGE_SHIFT); |
297 298 memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT); 299 buf->nr_pages = nr_pages; 300 301 buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist)); | 297 298 memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT); 299 buf->nr_pages = nr_pages; 300 301 buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist)); |
302 if (buf->sglist == NULL) | 302 if (!buf->sglist) |
303 goto vzalloc_err; 304 305 sg_init_table(buf->sglist, buf->nr_pages); 306 for (i = 0; i < buf->nr_pages; i++) { 307 pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE); | 303 goto vzalloc_err; 304 305 sg_init_table(buf->sglist, buf->nr_pages); 306 for (i = 0; i < buf->nr_pages; i++) { 307 pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE); |
308 if (pg == NULL) | 308 if (!pg) |
309 goto vmalloc_to_page_err; 310 sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0); 311 } 312 return 0; 313 314vmalloc_to_page_err: 315 vfree(buf->sglist); 316 buf->sglist = NULL; --- 19 unchanged lines hidden (view full) --- 336 337static int cx88_alsa_dma_unmap(struct cx88_audio_dev *dev) 338{ 339 struct cx88_audio_buffer *buf = dev->buf; 340 341 if (!buf->sglen) 342 return 0; 343 | 309 goto vmalloc_to_page_err; 310 sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0); 311 } 312 return 0; 313 314vmalloc_to_page_err: 315 vfree(buf->sglist); 316 buf->sglist = NULL; --- 19 unchanged lines hidden (view full) --- 336 337static int cx88_alsa_dma_unmap(struct cx88_audio_dev *dev) 338{ 339 struct cx88_audio_buffer *buf = dev->buf; 340 341 if (!buf->sglen) 342 return 0; 343 |
344 dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen, PCI_DMA_FROMDEVICE); | 344 dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen, 345 PCI_DMA_FROMDEVICE); |
345 buf->sglen = 0; 346 return 0; 347} 348 349static int cx88_alsa_dma_free(struct cx88_audio_buffer *buf) 350{ 351 vfree(buf->sglist); 352 buf->sglist = NULL; 353 vfree(buf->vaddr); 354 buf->vaddr = NULL; 355 return 0; 356} 357 | 346 buf->sglen = 0; 347 return 0; 348} 349 350static int cx88_alsa_dma_free(struct cx88_audio_buffer *buf) 351{ 352 vfree(buf->sglist); 353 buf->sglist = NULL; 354 vfree(buf->vaddr); 355 buf->vaddr = NULL; 356 return 0; 357} 358 |
358 359static int dsp_buffer_free(snd_cx88_card_t *chip) | 359static int dsp_buffer_free(struct cx88_audio_dev *chip) |
360{ 361 struct cx88_riscmem *risc = &chip->buf->risc; 362 | 360{ 361 struct cx88_riscmem *risc = &chip->buf->risc; 362 |
363 BUG_ON(!chip->dma_size); | 363 WARN_ON(!chip->dma_size); |
364 365 dprintk(2, "Freeing buffer\n"); 366 cx88_alsa_dma_unmap(chip); 367 cx88_alsa_dma_free(chip->buf); 368 if (risc->cpu) | 364 365 dprintk(2, "Freeing buffer\n"); 366 cx88_alsa_dma_unmap(chip); 367 cx88_alsa_dma_free(chip->buf); 368 if (risc->cpu) |
369 pci_free_consistent(chip->pci, risc->size, risc->cpu, risc->dma); | 369 pci_free_consistent(chip->pci, risc->size, 370 risc->cpu, risc->dma); |
370 kfree(chip->buf); 371 372 chip->buf = NULL; 373 374 return 0; 375} 376 | 371 kfree(chip->buf); 372 373 chip->buf = NULL; 374 375 return 0; 376} 377 |
377/**************************************************************************** 378 ALSA PCM Interface 379 ****************************************************************************/ | 378/* 379 * ALSA PCM Interface 380 */ |
380 381/* 382 * Digital hardware definition 383 */ 384#define DEFAULT_FIFO_SIZE 4096 385static const struct snd_pcm_hardware snd_cx88_digital_hw = { 386 .info = SNDRV_PCM_INFO_MMAP | 387 SNDRV_PCM_INFO_INTERLEAVED | 388 SNDRV_PCM_INFO_BLOCK_TRANSFER | 389 SNDRV_PCM_INFO_MMAP_VALID, 390 .formats = SNDRV_PCM_FMTBIT_S16_LE, 391 392 .rates = SNDRV_PCM_RATE_48000, 393 .rate_min = 48000, 394 .rate_max = 48000, 395 .channels_min = 2, 396 .channels_max = 2, | 381 382/* 383 * Digital hardware definition 384 */ 385#define DEFAULT_FIFO_SIZE 4096 386static const struct snd_pcm_hardware snd_cx88_digital_hw = { 387 .info = SNDRV_PCM_INFO_MMAP | 388 SNDRV_PCM_INFO_INTERLEAVED | 389 SNDRV_PCM_INFO_BLOCK_TRANSFER | 390 SNDRV_PCM_INFO_MMAP_VALID, 391 .formats = SNDRV_PCM_FMTBIT_S16_LE, 392 393 .rates = SNDRV_PCM_RATE_48000, 394 .rate_min = 48000, 395 .rate_max = 48000, 396 .channels_min = 2, 397 .channels_max = 2, |
397 /* Analog audio output will be full of clicks and pops if there 398 are not exactly four lines in the SRAM FIFO buffer. */ 399 .period_bytes_min = DEFAULT_FIFO_SIZE/4, 400 .period_bytes_max = DEFAULT_FIFO_SIZE/4, | 398 /* 399 * Analog audio output will be full of clicks and pops if there 400 * are not exactly four lines in the SRAM FIFO buffer. 401 */ 402 .period_bytes_min = DEFAULT_FIFO_SIZE / 4, 403 .period_bytes_max = DEFAULT_FIFO_SIZE / 4, |
401 .periods_min = 1, 402 .periods_max = 1024, | 404 .periods_min = 1, 405 .periods_max = 1024, |
403 .buffer_bytes_max = (1024*1024), | 406 .buffer_bytes_max = (1024 * 1024), |
404}; 405 406/* 407 * audio pcm capture open callback 408 */ 409static int snd_cx88_pcm_open(struct snd_pcm_substream *substream) 410{ | 407}; 408 409/* 410 * audio pcm capture open callback 411 */ 412static int snd_cx88_pcm_open(struct snd_pcm_substream *substream) 413{ |
411 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | 414 struct cx88_audio_dev *chip = snd_pcm_substream_chip(substream); |
412 struct snd_pcm_runtime *runtime = substream->runtime; 413 int err; 414 415 if (!chip) { 416 pr_err("BUG: cx88 can't find device struct. Can't proceed with open\n"); 417 return -ENODEV; 418 } 419 | 415 struct snd_pcm_runtime *runtime = substream->runtime; 416 int err; 417 418 if (!chip) { 419 pr_err("BUG: cx88 can't find device struct. Can't proceed with open\n"); 420 return -ENODEV; 421 } 422 |
420 err = snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS); | 423 err = snd_pcm_hw_constraint_pow2(runtime, 0, 424 SNDRV_PCM_HW_PARAM_PERIODS); |
421 if (err < 0) 422 goto _error; 423 424 chip->substream = substream; 425 426 runtime->hw = snd_cx88_digital_hw; 427 428 if (cx88_sram_channels[SRAM_CH25].fifo_size != DEFAULT_FIFO_SIZE) { --- 19 unchanged lines hidden (view full) --- 448} 449 450/* 451 * hw_params callback 452 */ 453static int snd_cx88_hw_params(struct snd_pcm_substream *substream, 454 struct snd_pcm_hw_params *hw_params) 455{ | 425 if (err < 0) 426 goto _error; 427 428 chip->substream = substream; 429 430 runtime->hw = snd_cx88_digital_hw; 431 432 if (cx88_sram_channels[SRAM_CH25].fifo_size != DEFAULT_FIFO_SIZE) { --- 19 unchanged lines hidden (view full) --- 452} 453 454/* 455 * hw_params callback 456 */ 457static int snd_cx88_hw_params(struct snd_pcm_substream *substream, 458 struct snd_pcm_hw_params *hw_params) 459{ |
456 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | 460 struct cx88_audio_dev *chip = snd_pcm_substream_chip(substream); |
457 458 struct cx88_audio_buffer *buf; 459 int ret; 460 461 if (substream->runtime->dma_area) { 462 dsp_buffer_free(chip); 463 substream->runtime->dma_area = NULL; 464 } 465 466 chip->period_size = params_period_bytes(hw_params); 467 chip->num_periods = params_periods(hw_params); 468 chip->dma_size = chip->period_size * params_periods(hw_params); 469 | 461 462 struct cx88_audio_buffer *buf; 463 int ret; 464 465 if (substream->runtime->dma_area) { 466 dsp_buffer_free(chip); 467 substream->runtime->dma_area = NULL; 468 } 469 470 chip->period_size = params_period_bytes(hw_params); 471 chip->num_periods = params_periods(hw_params); 472 chip->dma_size = chip->period_size * params_periods(hw_params); 473 |
470 BUG_ON(!chip->dma_size); 471 BUG_ON(chip->num_periods & (chip->num_periods-1)); | 474 WARN_ON(!chip->dma_size); 475 WARN_ON(chip->num_periods & (chip->num_periods - 1)); |
472 473 buf = kzalloc(sizeof(*buf), GFP_KERNEL); | 476 477 buf = kzalloc(sizeof(*buf), GFP_KERNEL); |
474 if (buf == NULL) | 478 if (!buf) |
475 return -ENOMEM; 476 477 chip->buf = buf; 478 buf->bpl = chip->period_size; 479 480 ret = cx88_alsa_dma_init(chip, | 479 return -ENOMEM; 480 481 chip->buf = buf; 482 buf->bpl = chip->period_size; 483 484 ret = cx88_alsa_dma_init(chip, |
481 (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); | 485 (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); |
482 if (ret < 0) 483 goto error; 484 485 ret = cx88_alsa_dma_map(chip); 486 if (ret < 0) 487 goto error; 488 489 ret = cx88_risc_databuffer(chip->pci, &buf->risc, buf->sglist, 490 chip->period_size, chip->num_periods, 1); 491 if (ret < 0) 492 goto error; 493 494 /* Loop back to start of program */ | 486 if (ret < 0) 487 goto error; 488 489 ret = cx88_alsa_dma_map(chip); 490 if (ret < 0) 491 goto error; 492 493 ret = cx88_risc_databuffer(chip->pci, &buf->risc, buf->sglist, 494 chip->period_size, chip->num_periods, 1); 495 if (ret < 0) 496 goto error; 497 498 /* Loop back to start of program */ |
495 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC); | 499 buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); |
496 buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); 497 498 substream->runtime->dma_area = chip->buf->vaddr; 499 substream->runtime->dma_bytes = chip->dma_size; 500 substream->runtime->dma_addr = 0; 501 return 0; 502 503error: 504 kfree(buf); 505 return ret; 506} 507 508/* 509 * hw free callback 510 */ 511static int snd_cx88_hw_free(struct snd_pcm_substream *substream) 512{ | 500 buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma); 501 502 substream->runtime->dma_area = chip->buf->vaddr; 503 substream->runtime->dma_bytes = chip->dma_size; 504 substream->runtime->dma_addr = 0; 505 return 0; 506 507error: 508 kfree(buf); 509 return ret; 510} 511 512/* 513 * hw free callback 514 */ 515static int snd_cx88_hw_free(struct snd_pcm_substream *substream) 516{ |
517 struct cx88_audio_dev *chip = snd_pcm_substream_chip(substream); |
|
513 | 518 |
514 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); 515 | |
516 if (substream->runtime->dma_area) { 517 dsp_buffer_free(chip); 518 substream->runtime->dma_area = NULL; 519 } 520 521 return 0; 522} 523 --- 5 unchanged lines hidden (view full) --- 529 return 0; 530} 531 532/* 533 * trigger callback 534 */ 535static int snd_cx88_card_trigger(struct snd_pcm_substream *substream, int cmd) 536{ | 519 if (substream->runtime->dma_area) { 520 dsp_buffer_free(chip); 521 substream->runtime->dma_area = NULL; 522 } 523 524 return 0; 525} 526 --- 5 unchanged lines hidden (view full) --- 532 return 0; 533} 534 535/* 536 * trigger callback 537 */ 538static int snd_cx88_card_trigger(struct snd_pcm_substream *substream, int cmd) 539{ |
537 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | 540 struct cx88_audio_dev *chip = snd_pcm_substream_chip(substream); |
538 int err; 539 540 /* Local interrupts are already disabled by ALSA */ 541 spin_lock(&chip->reg_lock); 542 543 switch (cmd) { 544 case SNDRV_PCM_TRIGGER_START: 545 err = _cx88_start_audio_dma(chip); --- 11 unchanged lines hidden (view full) --- 557 return err; 558} 559 560/* 561 * pointer callback 562 */ 563static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream) 564{ | 541 int err; 542 543 /* Local interrupts are already disabled by ALSA */ 544 spin_lock(&chip->reg_lock); 545 546 switch (cmd) { 547 case SNDRV_PCM_TRIGGER_START: 548 err = _cx88_start_audio_dma(chip); --- 11 unchanged lines hidden (view full) --- 560 return err; 561} 562 563/* 564 * pointer callback 565 */ 566static snd_pcm_uframes_t snd_cx88_pointer(struct snd_pcm_substream *substream) 567{ |
565 snd_cx88_card_t *chip = snd_pcm_substream_chip(substream); | 568 struct cx88_audio_dev *chip = snd_pcm_substream_chip(substream); |
566 struct snd_pcm_runtime *runtime = substream->runtime; 567 u16 count; 568 569 count = atomic_read(&chip->count); 570 571// dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __func__, 572// count, new, count & (runtime->periods-1), 573// runtime->period_size * (count & (runtime->periods-1))); | 569 struct snd_pcm_runtime *runtime = substream->runtime; 570 u16 count; 571 572 count = atomic_read(&chip->count); 573 574// dprintk(2, "%s - count %d (+%u), period %d, frame %lu\n", __func__, 575// count, new, count & (runtime->periods-1), 576// runtime->period_size * (count & (runtime->periods-1))); |
574 return runtime->period_size * (count & (runtime->periods-1)); | 577 return runtime->period_size * (count & (runtime->periods - 1)); |
575} 576 577/* 578 * page callback (needed for mmap) 579 */ 580static struct page *snd_cx88_page(struct snd_pcm_substream *substream, | 578} 579 580/* 581 * page callback (needed for mmap) 582 */ 583static struct page *snd_cx88_page(struct snd_pcm_substream *substream, |
581 unsigned long offset) | 584 unsigned long offset) |
582{ 583 void *pageptr = substream->runtime->dma_area + offset; 584 585 return vmalloc_to_page(pageptr); 586} 587 588/* 589 * operators --- 8 unchanged lines hidden (view full) --- 598 .trigger = snd_cx88_card_trigger, 599 .pointer = snd_cx88_pointer, 600 .page = snd_cx88_page, 601}; 602 603/* 604 * create a PCM device 605 */ | 585{ 586 void *pageptr = substream->runtime->dma_area + offset; 587 588 return vmalloc_to_page(pageptr); 589} 590 591/* 592 * operators --- 8 unchanged lines hidden (view full) --- 601 .trigger = snd_cx88_card_trigger, 602 .pointer = snd_cx88_pointer, 603 .page = snd_cx88_page, 604}; 605 606/* 607 * create a PCM device 608 */ |
606static int snd_cx88_pcm(snd_cx88_card_t *chip, int device, const char *name) | 609static int snd_cx88_pcm(struct cx88_audio_dev *chip, int device, 610 const char *name) |
607{ 608 int err; 609 struct snd_pcm *pcm; 610 611 err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); 612 if (err < 0) 613 return err; 614 pcm->private_data = chip; 615 strcpy(pcm->name, name); 616 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops); 617 618 return 0; 619} 620 | 611{ 612 int err; 613 struct snd_pcm *pcm; 614 615 err = snd_pcm_new(chip->card, name, device, 0, 1, &pcm); 616 if (err < 0) 617 return err; 618 pcm->private_data = chip; 619 strcpy(pcm->name, name); 620 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cx88_pcm_ops); 621 622 return 0; 623} 624 |
621/**************************************************************************** 622 CONTROL INTERFACE 623 ****************************************************************************/ | 625/* 626 * CONTROL INTERFACE 627 */ |
624static int snd_cx88_volume_info(struct snd_kcontrol *kcontrol, 625 struct snd_ctl_elem_info *info) 626{ 627 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 628 info->count = 2; 629 info->value.integer.min = 0; 630 info->value.integer.max = 0x3f; 631 632 return 0; 633} 634 635static int snd_cx88_volume_get(struct snd_kcontrol *kcontrol, 636 struct snd_ctl_elem_value *value) 637{ | 628static int snd_cx88_volume_info(struct snd_kcontrol *kcontrol, 629 struct snd_ctl_elem_info *info) 630{ 631 info->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 632 info->count = 2; 633 info->value.integer.min = 0; 634 info->value.integer.max = 0x3f; 635 636 return 0; 637} 638 639static int snd_cx88_volume_get(struct snd_kcontrol *kcontrol, 640 struct snd_ctl_elem_value *value) 641{ |
638 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | 642 struct cx88_audio_dev *chip = snd_kcontrol_chip(kcontrol); |
639 struct cx88_core *core = chip->core; 640 int vol = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f), 641 bal = cx_read(AUD_BAL_CTL); 642 643 value->value.integer.value[(bal & 0x40) ? 0 : 1] = vol; 644 vol -= (bal & 0x3f); 645 value->value.integer.value[(bal & 0x40) ? 1 : 0] = vol < 0 ? 0 : vol; 646 647 return 0; 648} 649 650static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol, | 643 struct cx88_core *core = chip->core; 644 int vol = 0x3f - (cx_read(AUD_VOL_CTL) & 0x3f), 645 bal = cx_read(AUD_BAL_CTL); 646 647 value->value.integer.value[(bal & 0x40) ? 0 : 1] = vol; 648 vol -= (bal & 0x3f); 649 value->value.integer.value[(bal & 0x40) ? 1 : 0] = vol < 0 ? 0 : vol; 650 651 return 0; 652} 653 654static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol, |
651 struct snd_ctl_elem_value *value) | 655 struct snd_ctl_elem_value *value) |
652{ | 656{ |
653 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | 657 struct cx88_audio_dev *chip = snd_kcontrol_chip(kcontrol); |
654 struct cx88_core *core = chip->core; 655 int left = value->value.integer.value[0]; 656 int right = value->value.integer.value[1]; 657 int v, b; 658 659 /* Pass volume & balance onto any WM8775 */ 660 if (left >= right) { 661 v = left << 10; --- 5 unchanged lines hidden (view full) --- 667 wm8775_s_ctrl(core, V4L2_CID_AUDIO_VOLUME, v); 668 wm8775_s_ctrl(core, V4L2_CID_AUDIO_BALANCE, b); 669} 670 671/* OK - TODO: test it */ 672static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol, 673 struct snd_ctl_elem_value *value) 674{ | 658 struct cx88_core *core = chip->core; 659 int left = value->value.integer.value[0]; 660 int right = value->value.integer.value[1]; 661 int v, b; 662 663 /* Pass volume & balance onto any WM8775 */ 664 if (left >= right) { 665 v = left << 10; --- 5 unchanged lines hidden (view full) --- 671 wm8775_s_ctrl(core, V4L2_CID_AUDIO_VOLUME, v); 672 wm8775_s_ctrl(core, V4L2_CID_AUDIO_BALANCE, b); 673} 674 675/* OK - TODO: test it */ 676static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol, 677 struct snd_ctl_elem_value *value) 678{ |
675 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | 679 struct cx88_audio_dev *chip = snd_kcontrol_chip(kcontrol); |
676 struct cx88_core *core = chip->core; 677 int left, right, v, b; 678 int changed = 0; 679 u32 old; 680 681 if (core->sd_wm8775) 682 snd_cx88_wm8775_volume_put(kcontrol, value); 683 --- 33 unchanged lines hidden (view full) --- 717 .get = snd_cx88_volume_get, 718 .put = snd_cx88_volume_put, 719 .tlv.p = snd_cx88_db_scale, 720}; 721 722static int snd_cx88_switch_get(struct snd_kcontrol *kcontrol, 723 struct snd_ctl_elem_value *value) 724{ | 680 struct cx88_core *core = chip->core; 681 int left, right, v, b; 682 int changed = 0; 683 u32 old; 684 685 if (core->sd_wm8775) 686 snd_cx88_wm8775_volume_put(kcontrol, value); 687 --- 33 unchanged lines hidden (view full) --- 721 .get = snd_cx88_volume_get, 722 .put = snd_cx88_volume_put, 723 .tlv.p = snd_cx88_db_scale, 724}; 725 726static int snd_cx88_switch_get(struct snd_kcontrol *kcontrol, 727 struct snd_ctl_elem_value *value) 728{ |
725 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | 729 struct cx88_audio_dev *chip = snd_kcontrol_chip(kcontrol); |
726 struct cx88_core *core = chip->core; 727 u32 bit = kcontrol->private_value; 728 729 value->value.integer.value[0] = !(cx_read(AUD_VOL_CTL) & bit); 730 return 0; 731} 732 733static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol, | 730 struct cx88_core *core = chip->core; 731 u32 bit = kcontrol->private_value; 732 733 value->value.integer.value[0] = !(cx_read(AUD_VOL_CTL) & bit); 734 return 0; 735} 736 737static int snd_cx88_switch_put(struct snd_kcontrol *kcontrol, |
734 struct snd_ctl_elem_value *value) | 738 struct snd_ctl_elem_value *value) |
735{ | 739{ |
736 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | 740 struct cx88_audio_dev *chip = snd_kcontrol_chip(kcontrol); |
737 struct cx88_core *core = chip->core; 738 u32 bit = kcontrol->private_value; 739 int ret = 0; 740 u32 vol; 741 742 spin_lock_irq(&chip->reg_lock); 743 vol = cx_read(AUD_VOL_CTL); 744 if (value->value.integer.value[0] != !(vol & bit)) { 745 vol ^= bit; 746 cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol); 747 /* Pass mute onto any WM8775 */ | 741 struct cx88_core *core = chip->core; 742 u32 bit = kcontrol->private_value; 743 int ret = 0; 744 u32 vol; 745 746 spin_lock_irq(&chip->reg_lock); 747 vol = cx_read(AUD_VOL_CTL); 748 if (value->value.integer.value[0] != !(vol & bit)) { 749 vol ^= bit; 750 cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol); 751 /* Pass mute onto any WM8775 */ |
748 if (core->sd_wm8775 && ((1<<6) == bit)) 749 wm8775_s_ctrl(core, V4L2_CID_AUDIO_MUTE, 0 != (vol & bit)); | 752 if (core->sd_wm8775 && ((1 << 6) == bit)) 753 wm8775_s_ctrl(core, 754 V4L2_CID_AUDIO_MUTE, 0 != (vol & bit)); |
750 ret = 1; 751 } 752 spin_unlock_irq(&chip->reg_lock); 753 return ret; 754} 755 756static const struct snd_kcontrol_new snd_cx88_dac_switch = { 757 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 758 .name = "Audio-Out Switch", 759 .info = snd_ctl_boolean_mono_info, 760 .get = snd_cx88_switch_get, 761 .put = snd_cx88_switch_put, | 755 ret = 1; 756 } 757 spin_unlock_irq(&chip->reg_lock); 758 return ret; 759} 760 761static const struct snd_kcontrol_new snd_cx88_dac_switch = { 762 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 763 .name = "Audio-Out Switch", 764 .info = snd_ctl_boolean_mono_info, 765 .get = snd_cx88_switch_get, 766 .put = snd_cx88_switch_put, |
762 .private_value = (1<<8), | 767 .private_value = (1 << 8), |
763}; 764 765static const struct snd_kcontrol_new snd_cx88_source_switch = { 766 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 767 .name = "Analog-TV Switch", 768 .info = snd_ctl_boolean_mono_info, 769 .get = snd_cx88_switch_get, 770 .put = snd_cx88_switch_put, | 768}; 769 770static const struct snd_kcontrol_new snd_cx88_source_switch = { 771 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 772 .name = "Analog-TV Switch", 773 .info = snd_ctl_boolean_mono_info, 774 .get = snd_cx88_switch_get, 775 .put = snd_cx88_switch_put, |
771 .private_value = (1<<6), | 776 .private_value = (1 << 6), |
772}; 773 774static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol, | 777}; 778 779static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol, |
775 struct snd_ctl_elem_value *value) | 780 struct snd_ctl_elem_value *value) |
776{ | 781{ |
777 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | 782 struct cx88_audio_dev *chip = snd_kcontrol_chip(kcontrol); |
778 struct cx88_core *core = chip->core; 779 s32 val; 780 781 val = wm8775_g_ctrl(core, V4L2_CID_AUDIO_LOUDNESS); 782 value->value.integer.value[0] = val ? 1 : 0; 783 return 0; 784} 785 786static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol, | 783 struct cx88_core *core = chip->core; 784 s32 val; 785 786 val = wm8775_g_ctrl(core, V4L2_CID_AUDIO_LOUDNESS); 787 value->value.integer.value[0] = val ? 1 : 0; 788 return 0; 789} 790 791static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol, |
787 struct snd_ctl_elem_value *value) | 792 struct snd_ctl_elem_value *value) |
788{ | 793{ |
789 snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol); | 794 struct cx88_audio_dev *chip = snd_kcontrol_chip(kcontrol); |
790 struct cx88_core *core = chip->core; 791 792 wm8775_s_ctrl(core, V4L2_CID_AUDIO_LOUDNESS, 793 value->value.integer.value[0] != 0); 794 return 0; 795} 796 797static struct snd_kcontrol_new snd_cx88_alc_switch = { 798 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 799 .name = "Line-In ALC Switch", 800 .info = snd_ctl_boolean_mono_info, 801 .get = snd_cx88_alc_get, 802 .put = snd_cx88_alc_put, 803}; 804 | 795 struct cx88_core *core = chip->core; 796 797 wm8775_s_ctrl(core, V4L2_CID_AUDIO_LOUDNESS, 798 value->value.integer.value[0] != 0); 799 return 0; 800} 801 802static struct snd_kcontrol_new snd_cx88_alc_switch = { 803 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 804 .name = "Line-In ALC Switch", 805 .info = snd_ctl_boolean_mono_info, 806 .get = snd_cx88_alc_get, 807 .put = snd_cx88_alc_put, 808}; 809 |
805/**************************************************************************** 806 Basic Flow for Sound Devices 807 ****************************************************************************/ | 810/* 811 * Basic Flow for Sound Devices 812 */ |
808 809/* 810 * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio 811 * Only boards with eeprom and byte 1 at eeprom=1 have it 812 */ 813 814static const struct pci_device_id cx88_audio_pci_tbl[] = { 815 {0x14f1, 0x8801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 816 {0x14f1, 0x8811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 817 {0, } 818}; 819MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl); 820 821/* 822 * Chip-specific destructor 823 */ 824 | 813 814/* 815 * PCI ID Table - 14f1:8801 and 14f1:8811 means function 1: Audio 816 * Only boards with eeprom and byte 1 at eeprom=1 have it 817 */ 818 819static const struct pci_device_id cx88_audio_pci_tbl[] = { 820 {0x14f1, 0x8801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 821 {0x14f1, 0x8811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 822 {0, } 823}; 824MODULE_DEVICE_TABLE(pci, cx88_audio_pci_tbl); 825 826/* 827 * Chip-specific destructor 828 */ 829 |
825static int snd_cx88_free(snd_cx88_card_t *chip) | 830static int snd_cx88_free(struct cx88_audio_dev *chip) |
826{ | 831{ |
827 | |
828 if (chip->irq >= 0) 829 free_irq(chip->irq, chip); 830 831 cx88_core_put(chip->core, chip->pci); 832 833 pci_disable_device(chip->pci); 834 return 0; 835} 836 837/* 838 * Component Destructor 839 */ 840static void snd_cx88_dev_free(struct snd_card *card) 841{ | 832 if (chip->irq >= 0) 833 free_irq(chip->irq, chip); 834 835 cx88_core_put(chip->core, chip->pci); 836 837 pci_disable_device(chip->pci); 838 return 0; 839} 840 841/* 842 * Component Destructor 843 */ 844static void snd_cx88_dev_free(struct snd_card *card) 845{ |
842 snd_cx88_card_t *chip = card->private_data; | 846 struct cx88_audio_dev *chip = card->private_data; |
843 844 snd_cx88_free(chip); 845} 846 | 847 848 snd_cx88_free(chip); 849} 850 |
847 | |
848/* 849 * Alsa Constructor - Component probe 850 */ 851 852static int devno; 853static int snd_cx88_create(struct snd_card *card, struct pci_dev *pci, | 851/* 852 * Alsa Constructor - Component probe 853 */ 854 855static int devno; 856static int snd_cx88_create(struct snd_card *card, struct pci_dev *pci, |
854 snd_cx88_card_t **rchip, | 857 struct cx88_audio_dev **rchip, |
855 struct cx88_core **core_ptr) 856{ | 858 struct cx88_core **core_ptr) 859{ |
857 snd_cx88_card_t *chip; 858 struct cx88_core *core; 859 int err; 860 unsigned char pci_lat; | 860 struct cx88_audio_dev *chip; 861 struct cx88_core *core; 862 int err; 863 unsigned char pci_lat; |
861 862 *rchip = NULL; 863 864 err = pci_enable_device(pci); 865 if (err < 0) 866 return err; 867 868 pci_set_master(pci); 869 870 chip = card->private_data; 871 872 core = cx88_core_get(pci); | 864 865 *rchip = NULL; 866 867 err = pci_enable_device(pci); 868 if (err < 0) 869 return err; 870 871 pci_set_master(pci); 872 873 chip = card->private_data; 874 875 core = cx88_core_get(pci); |
873 if (core == NULL) { | 876 if (!core) { |
874 err = -EINVAL; 875 return err; 876 } 877 878 err = pci_set_dma_mask(pci, DMA_BIT_MASK(32)); 879 if (err) { 880 dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n", core->name); 881 cx88_core_put(core, pci); 882 return err; 883 } 884 | 877 err = -EINVAL; 878 return err; 879 } 880 881 err = pci_set_dma_mask(pci, DMA_BIT_MASK(32)); 882 if (err) { 883 dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n", core->name); 884 cx88_core_put(core, pci); 885 return err; 886 } 887 |
885 | |
886 /* pci init */ 887 chip->card = card; 888 chip->pci = pci; 889 chip->irq = -1; 890 spin_lock_init(&chip->reg_lock); 891 892 chip->core = core; 893 894 /* get irq */ 895 err = request_irq(chip->pci->irq, cx8801_irq, 896 IRQF_SHARED, chip->core->name, chip); 897 if (err < 0) { 898 dprintk(0, "%s: can't get IRQ %d\n", | 888 /* pci init */ 889 chip->card = card; 890 chip->pci = pci; 891 chip->irq = -1; 892 spin_lock_init(&chip->reg_lock); 893 894 chip->core = core; 895 896 /* get irq */ 897 err = request_irq(chip->pci->irq, cx8801_irq, 898 IRQF_SHARED, chip->core->name, chip); 899 if (err < 0) { 900 dprintk(0, "%s: can't get IRQ %d\n", |
899 chip->core->name, chip->pci->irq); | 901 chip->core->name, chip->pci->irq); |
900 return err; 901 } 902 903 /* print pci info */ 904 pci_read_config_byte(pci, PCI_LATENCY_TIMER, &pci_lat); 905 | 902 return err; 903 } 904 905 /* print pci info */ 906 pci_read_config_byte(pci, PCI_LATENCY_TIMER, &pci_lat); 907 |
906 dprintk(1, "ALSA %s/%i: found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx\n", | 908 dprintk(1, 909 "ALSA %s/%i: found at %s, rev: %d, irq: %d, latency: %d, mmio: 0x%llx\n", |
907 core->name, devno, | 910 core->name, devno, |
908 pci_name(pci), pci->revision, pci->irq, 909 pci_lat, (unsigned long long)pci_resource_start(pci, 0)); | 911 pci_name(pci), pci->revision, pci->irq, 912 pci_lat, (unsigned long long)pci_resource_start(pci, 0)); |
910 911 chip->irq = pci->irq; 912 synchronize_irq(chip->irq); 913 914 *rchip = chip; 915 *core_ptr = core; 916 917 return 0; 918} 919 920static int cx88_audio_initdev(struct pci_dev *pci, 921 const struct pci_device_id *pci_id) 922{ | 913 914 chip->irq = pci->irq; 915 synchronize_irq(chip->irq); 916 917 *rchip = chip; 918 *core_ptr = core; 919 920 return 0; 921} 922 923static int cx88_audio_initdev(struct pci_dev *pci, 924 const struct pci_device_id *pci_id) 925{ |
923 struct snd_card *card; 924 snd_cx88_card_t *chip; 925 struct cx88_core *core = NULL; 926 int err; | 926 struct snd_card *card; 927 struct cx88_audio_dev *chip; 928 struct cx88_core *core = NULL; 929 int err; |
927 928 if (devno >= SNDRV_CARDS) 929 return (-ENODEV); 930 931 if (!enable[devno]) { 932 ++devno; 933 return (-ENOENT); 934 } 935 936 err = snd_card_new(&pci->dev, index[devno], id[devno], THIS_MODULE, | 930 931 if (devno >= SNDRV_CARDS) 932 return (-ENODEV); 933 934 if (!enable[devno]) { 935 ++devno; 936 return (-ENOENT); 937 } 938 939 err = snd_card_new(&pci->dev, index[devno], id[devno], THIS_MODULE, |
937 sizeof(snd_cx88_card_t), &card); | 940 sizeof(struct cx88_audio_dev), &card); |
938 if (err < 0) 939 return err; 940 941 card->private_free = snd_cx88_dev_free; 942 943 err = snd_cx88_create(card, pci, &chip, &core); 944 if (err < 0) 945 goto error; --- 19 unchanged lines hidden (view full) --- 965 strcpy(card->driver, "CX88x"); 966 sprintf(card->shortname, "Conexant CX%x", pci->device); 967 sprintf(card->longname, "%s at %#llx", 968 card->shortname, 969 (unsigned long long)pci_resource_start(pci, 0)); 970 strcpy(card->mixername, "CX88"); 971 972 dprintk(0, "%s/%i: ALSA support for cx2388x boards\n", | 941 if (err < 0) 942 return err; 943 944 card->private_free = snd_cx88_dev_free; 945 946 err = snd_cx88_create(card, pci, &chip, &core); 947 if (err < 0) 948 goto error; --- 19 unchanged lines hidden (view full) --- 968 strcpy(card->driver, "CX88x"); 969 sprintf(card->shortname, "Conexant CX%x", pci->device); 970 sprintf(card->longname, "%s at %#llx", 971 card->shortname, 972 (unsigned long long)pci_resource_start(pci, 0)); 973 strcpy(card->mixername, "CX88"); 974 975 dprintk(0, "%s/%i: ALSA support for cx2388x boards\n", |
973 card->driver, devno); | 976 card->driver, devno); |
974 975 err = snd_card_register(card); 976 if (err < 0) 977 goto error; 978 pci_set_drvdata(pci, card); 979 980 devno++; 981 return 0; 982 983error: 984 snd_card_free(card); 985 return err; 986} | 977 978 err = snd_card_register(card); 979 if (err < 0) 980 goto error; 981 pci_set_drvdata(pci, card); 982 983 devno++; 984 return 0; 985 986error: 987 snd_card_free(card); 988 return err; 989} |
990 |
|
987/* 988 * ALSA destructor 989 */ 990static void cx88_audio_finidev(struct pci_dev *pci) 991{ 992 struct snd_card *card = pci_get_drvdata(pci); 993 994 snd_card_free(card); --- 16 unchanged lines hidden --- | 991/* 992 * ALSA destructor 993 */ 994static void cx88_audio_finidev(struct pci_dev *pci) 995{ 996 struct snd_card *card = pci_get_drvdata(pci); 997 998 snd_card_free(card); --- 16 unchanged lines hidden --- |