1 /* 2 * Driver for Digigram pcxhr compatible soundcards 3 * 4 * low level interface with interrupt and message handling implementation 5 * 6 * Copyright (c) 2004 by Digigram <alsa@digigram.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 */ 22 23 #include <sound/driver.h> 24 #include <linux/delay.h> 25 #include <linux/firmware.h> 26 #include <linux/interrupt.h> 27 #include <asm/io.h> 28 #include <sound/core.h> 29 #include "pcxhr.h" 30 #include "pcxhr_mixer.h" 31 #include "pcxhr_hwdep.h" 32 #include "pcxhr_core.h" 33 34 35 /* registers used on the PLX (port 1) */ 36 #define PCXHR_PLX_OFFSET_MIN 0x40 37 #define PCXHR_PLX_MBOX0 0x40 38 #define PCXHR_PLX_MBOX1 0x44 39 #define PCXHR_PLX_MBOX2 0x48 40 #define PCXHR_PLX_MBOX3 0x4C 41 #define PCXHR_PLX_MBOX4 0x50 42 #define PCXHR_PLX_MBOX5 0x54 43 #define PCXHR_PLX_MBOX6 0x58 44 #define PCXHR_PLX_MBOX7 0x5C 45 #define PCXHR_PLX_L2PCIDB 0x64 46 #define PCXHR_PLX_IRQCS 0x68 47 #define PCXHR_PLX_CHIPSC 0x6C 48 49 /* registers used on the DSP (port 2) */ 50 #define PCXHR_DSP_ICR 0x00 51 #define PCXHR_DSP_CVR 0x04 52 #define PCXHR_DSP_ISR 0x08 53 #define PCXHR_DSP_IVR 0x0C 54 #define PCXHR_DSP_RXH 0x14 55 #define PCXHR_DSP_TXH 0x14 56 #define PCXHR_DSP_RXM 0x18 57 #define PCXHR_DSP_TXM 0x18 58 #define PCXHR_DSP_RXL 0x1C 59 #define PCXHR_DSP_TXL 0x1C 60 #define PCXHR_DSP_RESET 0x20 61 #define PCXHR_DSP_OFFSET_MAX 0x20 62 63 /* access to the card */ 64 #define PCXHR_PLX 1 65 #define PCXHR_DSP 2 66 67 #if (PCXHR_DSP_OFFSET_MAX > PCXHR_PLX_OFFSET_MIN) 68 #undef PCXHR_REG_TO_PORT(x) 69 #else 70 #define PCXHR_REG_TO_PORT(x) ((x)>PCXHR_DSP_OFFSET_MAX ? PCXHR_PLX : PCXHR_DSP) 71 #endif 72 #define PCXHR_INPB(mgr,x) inb((mgr)->port[PCXHR_REG_TO_PORT(x)] + (x)) 73 #define PCXHR_INPL(mgr,x) inl((mgr)->port[PCXHR_REG_TO_PORT(x)] + (x)) 74 #define PCXHR_OUTPB(mgr,x,data) outb((data), (mgr)->port[PCXHR_REG_TO_PORT(x)] + (x)) 75 #define PCXHR_OUTPL(mgr,x,data) outl((data), (mgr)->port[PCXHR_REG_TO_PORT(x)] + (x)) 76 /* attention : access the PCXHR_DSP_* registers with inb and outb only ! */ 77 78 /* params used with PCXHR_PLX_MBOX0 */ 79 #define PCXHR_MBOX0_HF5 (1 << 0) 80 #define PCXHR_MBOX0_HF4 (1 << 1) 81 #define PCXHR_MBOX0_BOOT_HERE (1 << 23) 82 /* params used with PCXHR_PLX_IRQCS */ 83 #define PCXHR_IRQCS_ENABLE_PCIIRQ (1 << 8) 84 #define PCXHR_IRQCS_ENABLE_PCIDB (1 << 9) 85 #define PCXHR_IRQCS_ACTIVE_PCIDB (1 << 13) 86 /* params used with PCXHR_PLX_CHIPSC */ 87 #define PCXHR_CHIPSC_INIT_VALUE 0x100D767E 88 #define PCXHR_CHIPSC_RESET_XILINX (1 << 16) 89 #define PCXHR_CHIPSC_GPI_USERI (1 << 17) 90 #define PCXHR_CHIPSC_DATA_CLK (1 << 24) 91 #define PCXHR_CHIPSC_DATA_IN (1 << 26) 92 93 /* params used with PCXHR_DSP_ICR */ 94 #define PCXHR_ICR_HI08_RREQ 0x01 95 #define PCXHR_ICR_HI08_TREQ 0x02 96 #define PCXHR_ICR_HI08_HDRQ 0x04 97 #define PCXHR_ICR_HI08_HF0 0x08 98 #define PCXHR_ICR_HI08_HF1 0x10 99 #define PCXHR_ICR_HI08_HLEND 0x20 100 #define PCXHR_ICR_HI08_INIT 0x80 101 /* params used with PCXHR_DSP_CVR */ 102 #define PCXHR_CVR_HI08_HC 0x80 103 /* params used with PCXHR_DSP_ISR */ 104 #define PCXHR_ISR_HI08_RXDF 0x01 105 #define PCXHR_ISR_HI08_TXDE 0x02 106 #define PCXHR_ISR_HI08_TRDY 0x04 107 #define PCXHR_ISR_HI08_ERR 0x08 108 #define PCXHR_ISR_HI08_CHK 0x10 109 #define PCXHR_ISR_HI08_HREQ 0x80 110 111 112 /* constants used for delay in msec */ 113 #define PCXHR_WAIT_DEFAULT 2 114 #define PCXHR_WAIT_IT 25 115 #define PCXHR_WAIT_IT_EXTRA 65 116 117 /* 118 * pcxhr_check_reg_bit - wait for the specified bit is set/reset on a register 119 * @reg: register to check 120 * @mask: bit mask 121 * @bit: resultant bit to be checked 122 * @time: time-out of loop in msec 123 * 124 * returns zero if a bit matches, or a negative error code. 125 */ 126 static int pcxhr_check_reg_bit(struct pcxhr_mgr *mgr, unsigned int reg, 127 unsigned char mask, unsigned char bit, int time, 128 unsigned char* read) 129 { 130 int i = 0; 131 unsigned long end_time = jiffies + (time * HZ + 999) / 1000; 132 do { 133 *read = PCXHR_INPB(mgr, reg); 134 if ((*read & mask) == bit) { 135 if (i > 100) 136 snd_printdd("ATTENTION! check_reg(%x) loopcount=%d\n", 137 reg, i); 138 return 0; 139 } 140 i++; 141 } while (time_after_eq(end_time, jiffies)); 142 snd_printk(KERN_ERR "pcxhr_check_reg_bit: timeout, reg=%x, mask=0x%x, val=0x%x\n", 143 reg, mask, *read); 144 return -EIO; 145 } 146 147 /* constants used with pcxhr_check_reg_bit() */ 148 #define PCXHR_TIMEOUT_DSP 200 149 150 151 #define PCXHR_MASK_EXTRA_INFO 0x0000FE 152 #define PCXHR_MASK_IT_HF0 0x000100 153 #define PCXHR_MASK_IT_HF1 0x000200 154 #define PCXHR_MASK_IT_NO_HF0_HF1 0x000400 155 #define PCXHR_MASK_IT_MANAGE_HF5 0x000800 156 #define PCXHR_MASK_IT_WAIT 0x010000 157 #define PCXHR_MASK_IT_WAIT_EXTRA 0x020000 158 159 #define PCXHR_IT_SEND_BYTE_XILINX (0x0000003C | PCXHR_MASK_IT_HF0) 160 #define PCXHR_IT_TEST_XILINX (0x0000003C | PCXHR_MASK_IT_HF1 | \ 161 PCXHR_MASK_IT_MANAGE_HF5) 162 #define PCXHR_IT_DOWNLOAD_BOOT (0x0000000C | PCXHR_MASK_IT_HF1 | \ 163 PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT) 164 #define PCXHR_IT_RESET_BOARD_FUNC (0x0000000C | PCXHR_MASK_IT_HF0 | \ 165 PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT_EXTRA) 166 #define PCXHR_IT_DOWNLOAD_DSP (0x0000000C | \ 167 PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT) 168 #define PCXHR_IT_DEBUG (0x0000005A | PCXHR_MASK_IT_NO_HF0_HF1) 169 #define PCXHR_IT_RESET_SEMAPHORE (0x0000005C | PCXHR_MASK_IT_NO_HF0_HF1) 170 #define PCXHR_IT_MESSAGE (0x00000074 | PCXHR_MASK_IT_NO_HF0_HF1) 171 #define PCXHR_IT_RESET_CHK (0x00000076 | PCXHR_MASK_IT_NO_HF0_HF1) 172 #define PCXHR_IT_UPDATE_RBUFFER (0x00000078 | PCXHR_MASK_IT_NO_HF0_HF1) 173 174 static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr, unsigned int itdsp, int atomic) 175 { 176 int err; 177 unsigned char reg; 178 179 if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) { 180 /* clear hf5 bit */ 181 PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0, 182 PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & ~PCXHR_MBOX0_HF5); 183 } 184 if ((itdsp & PCXHR_MASK_IT_NO_HF0_HF1) == 0) { 185 reg = PCXHR_ICR_HI08_RREQ | PCXHR_ICR_HI08_TREQ | PCXHR_ICR_HI08_HDRQ; 186 if (itdsp & PCXHR_MASK_IT_HF0) 187 reg |= PCXHR_ICR_HI08_HF0; 188 if (itdsp & PCXHR_MASK_IT_HF1) 189 reg |= PCXHR_ICR_HI08_HF1; 190 PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg); 191 } 192 reg = (unsigned char)(((itdsp & PCXHR_MASK_EXTRA_INFO) >> 1) | PCXHR_CVR_HI08_HC); 193 PCXHR_OUTPB(mgr, PCXHR_DSP_CVR, reg); 194 if (itdsp & PCXHR_MASK_IT_WAIT) { 195 if (atomic) 196 mdelay(PCXHR_WAIT_IT); 197 else 198 msleep(PCXHR_WAIT_IT); 199 } 200 if (itdsp & PCXHR_MASK_IT_WAIT_EXTRA) { 201 if (atomic) 202 mdelay(PCXHR_WAIT_IT_EXTRA); 203 else 204 msleep(PCXHR_WAIT_IT); 205 } 206 /* wait for CVR_HI08_HC == 0 */ 207 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_CVR, PCXHR_CVR_HI08_HC, 0, 208 PCXHR_TIMEOUT_DSP, ®); 209 if (err) { 210 snd_printk(KERN_ERR "pcxhr_send_it_dsp : TIMEOUT CVR\n"); 211 return err; 212 } 213 if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) { 214 /* wait for hf5 bit */ 215 err = pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0, PCXHR_MBOX0_HF5, 216 PCXHR_MBOX0_HF5, PCXHR_TIMEOUT_DSP, ®); 217 if (err) { 218 snd_printk(KERN_ERR "pcxhr_send_it_dsp : TIMEOUT HF5\n"); 219 return err; 220 } 221 } 222 return 0; /* retry not handled here */ 223 } 224 225 void pcxhr_reset_xilinx_com(struct pcxhr_mgr *mgr) 226 { 227 /* reset second xilinx */ 228 PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, 229 PCXHR_CHIPSC_INIT_VALUE & ~PCXHR_CHIPSC_RESET_XILINX); 230 } 231 232 static void pcxhr_enable_irq(struct pcxhr_mgr *mgr, int enable) 233 { 234 unsigned int reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS); 235 /* enable/disable interrupts */ 236 if (enable) 237 reg |= (PCXHR_IRQCS_ENABLE_PCIIRQ | PCXHR_IRQCS_ENABLE_PCIDB); 238 else 239 reg &= ~(PCXHR_IRQCS_ENABLE_PCIIRQ | PCXHR_IRQCS_ENABLE_PCIDB); 240 PCXHR_OUTPL(mgr, PCXHR_PLX_IRQCS, reg); 241 } 242 243 void pcxhr_reset_dsp(struct pcxhr_mgr *mgr) 244 { 245 /* disable interrupts */ 246 pcxhr_enable_irq(mgr, 0); 247 248 /* let's reset the DSP */ 249 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, 0); 250 msleep( PCXHR_WAIT_DEFAULT ); /* wait 2 msec */ 251 PCXHR_OUTPB(mgr, PCXHR_DSP_RESET, 3); 252 msleep( PCXHR_WAIT_DEFAULT ); /* wait 2 msec */ 253 254 /* reset mailbox */ 255 PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0, 0); 256 } 257 258 void pcxhr_enable_dsp(struct pcxhr_mgr *mgr) 259 { 260 /* enable interrupts */ 261 pcxhr_enable_irq(mgr, 1); 262 } 263 264 /* 265 * load the xilinx image 266 */ 267 int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, const struct firmware *xilinx, int second) 268 { 269 unsigned int i; 270 unsigned int chipsc; 271 unsigned char data; 272 unsigned char mask; 273 unsigned char *image; 274 275 /* test first xilinx */ 276 chipsc = PCXHR_INPL(mgr, PCXHR_PLX_CHIPSC); 277 /* REV01 cards do not support the PCXHR_CHIPSC_GPI_USERI bit anymore */ 278 /* this bit will always be 1; no possibility to test presence of first xilinx */ 279 if(second) { 280 if ((chipsc & PCXHR_CHIPSC_GPI_USERI) == 0) { 281 snd_printk(KERN_ERR "error loading first xilinx\n"); 282 return -EINVAL; 283 } 284 /* activate second xilinx */ 285 chipsc |= PCXHR_CHIPSC_RESET_XILINX; 286 PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc); 287 msleep( PCXHR_WAIT_DEFAULT ); /* wait 2 msec */ 288 } 289 image = xilinx->data; 290 for (i = 0; i < xilinx->size; i++, image++) { 291 data = *image; 292 mask = 0x80; 293 while (mask) { 294 chipsc &= ~(PCXHR_CHIPSC_DATA_CLK | PCXHR_CHIPSC_DATA_IN); 295 if (data & mask) 296 chipsc |= PCXHR_CHIPSC_DATA_IN; 297 PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc); 298 chipsc |= PCXHR_CHIPSC_DATA_CLK; 299 PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc); 300 mask >>= 1; 301 } 302 /* don't take too much time in this loop... */ 303 cond_resched(); 304 } 305 chipsc &= ~(PCXHR_CHIPSC_DATA_CLK | PCXHR_CHIPSC_DATA_IN); 306 PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc); 307 /* wait 2 msec (time to boot the xilinx before any access) */ 308 msleep( PCXHR_WAIT_DEFAULT ); 309 return 0; 310 } 311 312 /* 313 * send an executable file to the DSP 314 */ 315 static int pcxhr_download_dsp(struct pcxhr_mgr *mgr, const struct firmware *dsp) 316 { 317 int err; 318 unsigned int i; 319 unsigned int len; 320 unsigned char *data; 321 unsigned char dummy; 322 /* check the length of boot image */ 323 snd_assert(dsp->size > 0, return -EINVAL); 324 snd_assert(dsp->size % 3 == 0, return -EINVAL); 325 snd_assert(dsp->data, return -EINVAL); 326 /* transfert data buffer from PC to DSP */ 327 for (i = 0; i < dsp->size; i += 3) { 328 data = dsp->data + i; 329 if (i == 0) { 330 /* test data header consistency */ 331 len = (unsigned int)((data[0]<<16) + (data[1]<<8) + data[2]); 332 snd_assert((len==0) || (dsp->size == (len+2)*3), return -EINVAL); 333 } 334 /* wait DSP ready for new transfer */ 335 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY, 336 PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, &dummy); 337 if (err) { 338 snd_printk(KERN_ERR "dsp loading error at position %d\n", i); 339 return err; 340 } 341 /* send host data */ 342 PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, data[0]); 343 PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, data[1]); 344 PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, data[2]); 345 346 /* don't take too much time in this loop... */ 347 cond_resched(); 348 } 349 /* give some time to boot the DSP */ 350 msleep(PCXHR_WAIT_DEFAULT); 351 return 0; 352 } 353 354 /* 355 * load the eeprom image 356 */ 357 int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr, const struct firmware *eeprom) 358 { 359 int err; 360 unsigned char reg; 361 362 /* init value of the ICR register */ 363 reg = PCXHR_ICR_HI08_RREQ | PCXHR_ICR_HI08_TREQ | PCXHR_ICR_HI08_HDRQ; 364 if (PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & PCXHR_MBOX0_BOOT_HERE) { 365 /* no need to load the eeprom binary, but init the HI08 interface */ 366 PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg | PCXHR_ICR_HI08_INIT); 367 msleep(PCXHR_WAIT_DEFAULT); 368 PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg); 369 msleep(PCXHR_WAIT_DEFAULT); 370 snd_printdd("no need to load eeprom boot\n"); 371 return 0; 372 } 373 PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg); 374 375 err = pcxhr_download_dsp(mgr, eeprom); 376 if (err) 377 return err; 378 /* wait for chk bit */ 379 return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, 380 PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, ®); 381 } 382 383 /* 384 * load the boot image 385 */ 386 int pcxhr_load_boot_binary(struct pcxhr_mgr *mgr, const struct firmware *boot) 387 { 388 int err; 389 unsigned int physaddr = mgr->hostport.addr; 390 unsigned char dummy; 391 392 /* send the hostport address to the DSP (only the upper 24 bit !) */ 393 snd_assert((physaddr & 0xff) == 0, return -EINVAL); 394 PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX1, (physaddr >> 8)); 395 396 err = pcxhr_send_it_dsp(mgr, PCXHR_IT_DOWNLOAD_BOOT, 0); 397 if (err) 398 return err; 399 /* clear hf5 bit */ 400 PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0, 401 PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & ~PCXHR_MBOX0_HF5); 402 403 err = pcxhr_download_dsp(mgr, boot); 404 if (err) 405 return err; 406 /* wait for hf5 bit */ 407 return pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0, PCXHR_MBOX0_HF5, 408 PCXHR_MBOX0_HF5, PCXHR_TIMEOUT_DSP, &dummy); 409 } 410 411 /* 412 * load the final dsp image 413 */ 414 int pcxhr_load_dsp_binary(struct pcxhr_mgr *mgr, const struct firmware *dsp) 415 { 416 int err; 417 unsigned char dummy; 418 err = pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_BOARD_FUNC, 0); 419 if (err) 420 return err; 421 err = pcxhr_send_it_dsp(mgr, PCXHR_IT_DOWNLOAD_DSP, 0); 422 if (err) 423 return err; 424 err = pcxhr_download_dsp(mgr, dsp); 425 if (err) 426 return err; 427 /* wait for chk bit */ 428 return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, 429 PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, &dummy); 430 } 431 432 433 struct pcxhr_cmd_info { 434 u32 opcode; /* command word */ 435 u16 st_length; /* status length */ 436 u16 st_type; /* status type (RMH_SSIZE_XXX) */ 437 }; 438 439 /* RMH status type */ 440 enum { 441 RMH_SSIZE_FIXED = 0, /* status size fix (st_length = 0..x) */ 442 RMH_SSIZE_ARG = 1, /* status size given in the LSB byte (used with st_length = 1) */ 443 RMH_SSIZE_MASK = 2, /* status size given in bitmask (used with st_length = 1) */ 444 }; 445 446 /* 447 * Array of DSP commands 448 */ 449 static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = { 450 [CMD_VERSION] = { 0x010000, 1, RMH_SSIZE_FIXED }, 451 [CMD_SUPPORTED] = { 0x020000, 4, RMH_SSIZE_FIXED }, 452 [CMD_TEST_IT] = { 0x040000, 1, RMH_SSIZE_FIXED }, 453 [CMD_SEND_IRQA] = { 0x070001, 0, RMH_SSIZE_FIXED }, 454 [CMD_ACCESS_IO_WRITE] = { 0x090000, 1, RMH_SSIZE_ARG }, 455 [CMD_ACCESS_IO_READ] = { 0x094000, 1, RMH_SSIZE_ARG }, 456 [CMD_ASYNC] = { 0x0a0000, 1, RMH_SSIZE_ARG }, 457 [CMD_MODIFY_CLOCK] = { 0x0d0000, 0, RMH_SSIZE_FIXED }, 458 [CMD_RESYNC_AUDIO_INPUTS] = { 0x0e0000, 0, RMH_SSIZE_FIXED }, 459 [CMD_GET_DSP_RESOURCES] = { 0x100000, 4, RMH_SSIZE_FIXED }, 460 [CMD_SET_TIMER_INTERRUPT] = { 0x110000, 0, RMH_SSIZE_FIXED }, 461 [CMD_RES_PIPE] = { 0x400000, 0, RMH_SSIZE_FIXED }, 462 [CMD_FREE_PIPE] = { 0x410000, 0, RMH_SSIZE_FIXED }, 463 [CMD_CONF_PIPE] = { 0x422101, 0, RMH_SSIZE_FIXED }, 464 [CMD_STOP_PIPE] = { 0x470004, 0, RMH_SSIZE_FIXED }, 465 [CMD_PIPE_SAMPLE_COUNT] = { 0x49a000, 2, RMH_SSIZE_FIXED }, 466 [CMD_CAN_START_PIPE] = { 0x4b0000, 1, RMH_SSIZE_FIXED }, 467 [CMD_START_STREAM] = { 0x802000, 0, RMH_SSIZE_FIXED }, 468 [CMD_STREAM_OUT_LEVEL_ADJUST] = { 0x822000, 0, RMH_SSIZE_FIXED }, 469 [CMD_STOP_STREAM] = { 0x832000, 0, RMH_SSIZE_FIXED }, 470 [CMD_UPDATE_R_BUFFERS] = { 0x840000, 0, RMH_SSIZE_FIXED }, 471 [CMD_FORMAT_STREAM_OUT] = { 0x860000, 0, RMH_SSIZE_FIXED }, 472 [CMD_FORMAT_STREAM_IN] = { 0x870000, 0, RMH_SSIZE_FIXED }, 473 [CMD_STREAM_SAMPLE_COUNT] = { 0x902000, 2, RMH_SSIZE_FIXED }, /* stat_len = nb_streams * 2 */ 474 [CMD_AUDIO_LEVEL_ADJUST] = { 0xc22000, 0, RMH_SSIZE_FIXED }, 475 }; 476 477 #ifdef CONFIG_SND_DEBUG_DETECT 478 static char* cmd_names[] = { 479 [CMD_VERSION] = "CMD_VERSION", 480 [CMD_SUPPORTED] = "CMD_SUPPORTED", 481 [CMD_TEST_IT] = "CMD_TEST_IT", 482 [CMD_SEND_IRQA] = "CMD_SEND_IRQA", 483 [CMD_ACCESS_IO_WRITE] = "CMD_ACCESS_IO_WRITE", 484 [CMD_ACCESS_IO_READ] = "CMD_ACCESS_IO_READ", 485 [CMD_ASYNC] = "CMD_ASYNC", 486 [CMD_MODIFY_CLOCK] = "CMD_MODIFY_CLOCK", 487 [CMD_RESYNC_AUDIO_INPUTS] = "CMD_RESYNC_AUDIO_INPUTS", 488 [CMD_GET_DSP_RESOURCES] = "CMD_GET_DSP_RESOURCES", 489 [CMD_SET_TIMER_INTERRUPT] = "CMD_SET_TIMER_INTERRUPT", 490 [CMD_RES_PIPE] = "CMD_RES_PIPE", 491 [CMD_FREE_PIPE] = "CMD_FREE_PIPE", 492 [CMD_CONF_PIPE] = "CMD_CONF_PIPE", 493 [CMD_STOP_PIPE] = "CMD_STOP_PIPE", 494 [CMD_PIPE_SAMPLE_COUNT] = "CMD_PIPE_SAMPLE_COUNT", 495 [CMD_CAN_START_PIPE] = "CMD_CAN_START_PIPE", 496 [CMD_START_STREAM] = "CMD_START_STREAM", 497 [CMD_STREAM_OUT_LEVEL_ADJUST] = "CMD_STREAM_OUT_LEVEL_ADJUST", 498 [CMD_STOP_STREAM] = "CMD_STOP_STREAM", 499 [CMD_UPDATE_R_BUFFERS] = "CMD_UPDATE_R_BUFFERS", 500 [CMD_FORMAT_STREAM_OUT] = "CMD_FORMAT_STREAM_OUT", 501 [CMD_FORMAT_STREAM_IN] = "CMD_FORMAT_STREAM_IN", 502 [CMD_STREAM_SAMPLE_COUNT] = "CMD_STREAM_SAMPLE_COUNT", 503 [CMD_AUDIO_LEVEL_ADJUST] = "CMD_AUDIO_LEVEL_ADJUST", 504 }; 505 #endif 506 507 508 static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) 509 { 510 int err; 511 int i; 512 u32 data; 513 u32 size_mask; 514 unsigned char reg; 515 int max_stat_len; 516 517 if (rmh->stat_len < PCXHR_SIZE_MAX_STATUS) 518 max_stat_len = PCXHR_SIZE_MAX_STATUS; 519 else max_stat_len = rmh->stat_len; 520 521 for (i = 0; i < rmh->stat_len; i++) { 522 /* wait for receiver full */ 523 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_RXDF, 524 PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, ®); 525 if (err) { 526 snd_printk(KERN_ERR "ERROR RMH stat: ISR:RXDF=1 (ISR = %x; i=%d )\n", 527 reg, i); 528 return err; 529 } 530 /* read data */ 531 data = PCXHR_INPB(mgr, PCXHR_DSP_TXH) << 16; 532 data |= PCXHR_INPB(mgr, PCXHR_DSP_TXM) << 8; 533 data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL); 534 535 /* need to update rmh->stat_len on the fly ?? */ 536 if (i==0) { 537 if (rmh->dsp_stat != RMH_SSIZE_FIXED) { 538 if (rmh->dsp_stat == RMH_SSIZE_ARG) { 539 rmh->stat_len = (u16)(data & 0x0000ff) + 1; 540 data &= 0xffff00; 541 } else { 542 /* rmh->dsp_stat == RMH_SSIZE_MASK */ 543 rmh->stat_len = 1; 544 size_mask = data; 545 while (size_mask) { 546 if (size_mask & 1) 547 rmh->stat_len++; 548 size_mask >>= 1; 549 } 550 } 551 } 552 } 553 #ifdef CONFIG_SND_DEBUG_DETECT 554 if (rmh->cmd_idx < CMD_LAST_INDEX) 555 snd_printdd(" stat[%d]=%x\n", i, data); 556 #endif 557 if (i < max_stat_len) 558 rmh->stat[i] = data; 559 } 560 if (rmh->stat_len > max_stat_len) { 561 snd_printdd("PCXHR : rmh->stat_len=%x too big\n", rmh->stat_len); 562 rmh->stat_len = max_stat_len; 563 } 564 return 0; 565 } 566 567 static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) 568 { 569 int err; 570 int i; 571 u32 data; 572 unsigned char reg; 573 574 snd_assert(rmh->cmd_len<PCXHR_SIZE_MAX_CMD, return -EINVAL); 575 err = pcxhr_send_it_dsp(mgr, PCXHR_IT_MESSAGE, 1); 576 if (err) { 577 snd_printk(KERN_ERR "pcxhr_send_message : ED_DSP_CRASHED\n"); 578 return err; 579 } 580 /* wait for chk bit */ 581 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, 582 PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, ®); 583 if (err) 584 return err; 585 /* reset irq chk */ 586 err = pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_CHK, 1); 587 if (err) 588 return err; 589 /* wait for chk bit == 0*/ 590 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, 0, 591 PCXHR_TIMEOUT_DSP, ®); 592 if (err) 593 return err; 594 595 data = rmh->cmd[0]; 596 597 if (rmh->cmd_len > 1) 598 data |= 0x008000; /* MASK_MORE_THAN_1_WORD_COMMAND */ 599 else 600 data &= 0xff7fff; /* MASK_1_WORD_COMMAND */ 601 #ifdef CONFIG_SND_DEBUG_DETECT 602 if (rmh->cmd_idx < CMD_LAST_INDEX) 603 snd_printdd("MSG cmd[0]=%x (%s)\n", data, cmd_names[rmh->cmd_idx]); 604 #endif 605 606 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY, 607 PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, ®); 608 if (err) 609 return err; 610 PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF); 611 PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF); 612 PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF)); 613 614 if (rmh->cmd_len > 1) { 615 /* send length */ 616 data = rmh->cmd_len - 1; 617 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY, 618 PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, ®); 619 if (err) 620 return err; 621 PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF); 622 PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF); 623 PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF)); 624 625 for (i=1; i < rmh->cmd_len; i++) { 626 /* send other words */ 627 data = rmh->cmd[i]; 628 #ifdef CONFIG_SND_DEBUG_DETECT 629 if (rmh->cmd_idx < CMD_LAST_INDEX) 630 snd_printdd(" cmd[%d]=%x\n", i, data); 631 #endif 632 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, 633 PCXHR_ISR_HI08_TRDY, 634 PCXHR_ISR_HI08_TRDY, 635 PCXHR_TIMEOUT_DSP, ®); 636 if (err) 637 return err; 638 PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF); 639 PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF); 640 PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF)); 641 } 642 } 643 /* wait for chk bit */ 644 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, 645 PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, ®); 646 if (err) 647 return err; 648 /* test status ISR */ 649 if (reg & PCXHR_ISR_HI08_ERR) { 650 /* ERROR, wait for receiver full */ 651 err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_RXDF, 652 PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, ®); 653 if (err) { 654 snd_printk(KERN_ERR "ERROR RMH: ISR:RXDF=1 (ISR = %x)\n", reg); 655 return err; 656 } 657 /* read error code */ 658 data = PCXHR_INPB(mgr, PCXHR_DSP_TXH) << 16; 659 data |= PCXHR_INPB(mgr, PCXHR_DSP_TXM) << 8; 660 data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL); 661 snd_printk(KERN_ERR "ERROR RMH(%d): 0x%x\n", rmh->cmd_idx, data); 662 err = -EINVAL; 663 } else { 664 /* read the response data */ 665 err = pcxhr_read_rmh_status(mgr, rmh); 666 } 667 /* reset semaphore */ 668 if (pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_SEMAPHORE, 1) < 0) 669 return -EIO; 670 return err; 671 } 672 673 674 /** 675 * pcxhr_init_rmh - initialize the RMH instance 676 * @rmh: the rmh pointer to be initialized 677 * @cmd: the rmh command to be set 678 */ 679 void pcxhr_init_rmh(struct pcxhr_rmh *rmh, int cmd) 680 { 681 snd_assert(cmd < CMD_LAST_INDEX, return); 682 rmh->cmd[0] = pcxhr_dsp_cmds[cmd].opcode; 683 rmh->cmd_len = 1; 684 rmh->stat_len = pcxhr_dsp_cmds[cmd].st_length; 685 rmh->dsp_stat = pcxhr_dsp_cmds[cmd].st_type; 686 rmh->cmd_idx = cmd; 687 } 688 689 690 void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh *rmh, int capture, 691 unsigned int param1, unsigned int param2, 692 unsigned int param3) 693 { 694 snd_assert(param1 <= MASK_FIRST_FIELD); 695 if (capture) 696 rmh->cmd[0] |= 0x800; /* COMMAND_RECORD_MASK */ 697 if (param1) 698 rmh->cmd[0] |= (param1 << FIELD_SIZE); 699 if (param2) { 700 snd_assert(param2 <= MASK_FIRST_FIELD); 701 rmh->cmd[0] |= param2; 702 } 703 if(param3) { 704 snd_assert(param3 <= MASK_DSP_WORD); 705 rmh->cmd[1] = param3; 706 rmh->cmd_len = 2; 707 } 708 } 709 710 /* 711 * pcxhr_send_msg - send a DSP message with spinlock 712 * @rmh: the rmh record to send and receive 713 * 714 * returns 0 if successful, or a negative error code. 715 */ 716 int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh) 717 { 718 unsigned long flags; 719 int err; 720 spin_lock_irqsave(&mgr->msg_lock, flags); 721 err = pcxhr_send_msg_nolock(mgr, rmh); 722 spin_unlock_irqrestore(&mgr->msg_lock, flags); 723 return err; 724 } 725 726 static inline int pcxhr_pipes_running(struct pcxhr_mgr *mgr) 727 { 728 int start_mask = PCXHR_INPL(mgr, PCXHR_PLX_MBOX2); 729 /* least segnificant 12 bits are the pipe states for the playback audios */ 730 /* next 12 bits are the pipe states for the capture audios 731 * (PCXHR_PIPE_STATE_CAPTURE_OFFSET) 732 */ 733 start_mask &= 0xffffff; 734 snd_printdd("CMD_PIPE_STATE MBOX2=0x%06x\n", start_mask); 735 return start_mask; 736 } 737 738 #define PCXHR_PIPE_STATE_CAPTURE_OFFSET 12 739 #define MAX_WAIT_FOR_DSP 20 740 741 static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr, int audio_mask, int *retry) 742 { 743 struct pcxhr_rmh rmh; 744 int err; 745 int audio = 0; 746 747 *retry = 0; 748 while (audio_mask) { 749 if (audio_mask & 1) { 750 pcxhr_init_rmh(&rmh, CMD_CAN_START_PIPE); 751 if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET) { 752 /* can start playback pipe */ 753 pcxhr_set_pipe_cmd_params(&rmh, 0, audio, 0, 0); 754 } else { 755 /* can start capture pipe */ 756 pcxhr_set_pipe_cmd_params(&rmh, 1, audio - 757 PCXHR_PIPE_STATE_CAPTURE_OFFSET, 758 0, 0); 759 } 760 err = pcxhr_send_msg(mgr, &rmh); 761 if (err) { 762 snd_printk(KERN_ERR 763 "error pipe start (CMD_CAN_START_PIPE) err=%x!\n", 764 err); 765 return err; 766 } 767 /* if the pipe couldn't be prepaired for start, retry it later */ 768 if (rmh.stat[0] == 0) 769 *retry |= (1<<audio); 770 } 771 audio_mask>>=1; 772 audio++; 773 } 774 return 0; 775 } 776 777 static int pcxhr_stop_pipes(struct pcxhr_mgr *mgr, int audio_mask) 778 { 779 struct pcxhr_rmh rmh; 780 int err; 781 int audio = 0; 782 783 while (audio_mask) { 784 if (audio_mask & 1) { 785 pcxhr_init_rmh(&rmh, CMD_STOP_PIPE); 786 if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET) { 787 /* stop playback pipe */ 788 pcxhr_set_pipe_cmd_params(&rmh, 0, audio, 0, 0); 789 } else { 790 /* stop capture pipe */ 791 pcxhr_set_pipe_cmd_params(&rmh, 1, audio - 792 PCXHR_PIPE_STATE_CAPTURE_OFFSET, 793 0, 0); 794 } 795 err = pcxhr_send_msg(mgr, &rmh); 796 if (err) { 797 snd_printk(KERN_ERR 798 "error pipe stop (CMD_STOP_PIPE) err=%x!\n", 799 err); 800 return err; 801 } 802 } 803 audio_mask>>=1; 804 audio++; 805 } 806 return 0; 807 } 808 809 static int pcxhr_toggle_pipes(struct pcxhr_mgr *mgr, int audio_mask) 810 { 811 struct pcxhr_rmh rmh; 812 int err; 813 int audio = 0; 814 815 while (audio_mask) { 816 if (audio_mask & 1) { 817 pcxhr_init_rmh(&rmh, CMD_CONF_PIPE); 818 if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET) 819 pcxhr_set_pipe_cmd_params(&rmh, 0, 0, 0, 1 << audio); 820 else 821 pcxhr_set_pipe_cmd_params(&rmh, 1, 0, 0, 822 1 << (audio - PCXHR_PIPE_STATE_CAPTURE_OFFSET)); 823 err = pcxhr_send_msg(mgr, &rmh); 824 if (err) { 825 snd_printk(KERN_ERR 826 "error pipe start (CMD_CONF_PIPE) err=%x!\n", 827 err); 828 return err; 829 } 830 } 831 audio_mask>>=1; 832 audio++; 833 } 834 /* now fire the interrupt on the card */ 835 pcxhr_init_rmh(&rmh, CMD_SEND_IRQA); 836 err = pcxhr_send_msg(mgr, &rmh); 837 if (err) { 838 snd_printk(KERN_ERR "error pipe start (CMD_SEND_IRQA) err=%x!\n", err ); 839 return err; 840 } 841 return 0; 842 } 843 844 845 846 int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_mask, int start) 847 { 848 int state, i, err; 849 int audio_mask; 850 851 #ifdef CONFIG_SND_DEBUG_DETECT 852 struct timeval my_tv1, my_tv2; 853 do_gettimeofday(&my_tv1); 854 #endif 855 audio_mask = (playback_mask | (capture_mask << PCXHR_PIPE_STATE_CAPTURE_OFFSET)); 856 /* current pipe state (playback + record) */ 857 state = pcxhr_pipes_running(mgr); 858 snd_printdd("pcxhr_set_pipe_state %s (mask %x current %x)\n", 859 start ? "START" : "STOP", audio_mask, state); 860 if (start) { 861 audio_mask &= ~state; /* start only pipes that are not yet started */ 862 state = audio_mask; 863 for (i = 0; i < MAX_WAIT_FOR_DSP; i++) { 864 err = pcxhr_prepair_pipe_start(mgr, state, &state); 865 if (err) 866 return err; 867 if (state == 0) 868 break; /* success, all pipes prepaired for start */ 869 mdelay(1); /* otherwise wait 1 millisecond and retry */ 870 } 871 } else { 872 audio_mask &= state; /* stop only pipes that are started */ 873 } 874 if (audio_mask == 0) 875 return 0; 876 877 err = pcxhr_toggle_pipes(mgr, audio_mask); 878 if (err) 879 return err; 880 881 i = 0; 882 while (1) { 883 state = pcxhr_pipes_running(mgr); 884 /* have all pipes the new state ? */ 885 if ((state & audio_mask) == (start ? audio_mask : 0)) 886 break; 887 if (++i >= MAX_WAIT_FOR_DSP * 100) { 888 snd_printk(KERN_ERR "error pipe start/stop (ED_NO_RESPONSE_AT_IRQA)\n"); 889 return -EBUSY; 890 } 891 udelay(10); /* wait 10 microseconds */ 892 } 893 if (!start) { 894 err = pcxhr_stop_pipes(mgr, audio_mask); 895 if (err) 896 return err; 897 } 898 #ifdef CONFIG_SND_DEBUG_DETECT 899 do_gettimeofday(&my_tv2); 900 snd_printdd("***SET PIPE STATE*** TIME = %ld (err = %x)\n", 901 my_tv2.tv_usec - my_tv1.tv_usec, err); 902 #endif 903 return 0; 904 } 905 906 int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask, 907 unsigned int value, int *changed) 908 { 909 struct pcxhr_rmh rmh; 910 unsigned long flags; 911 int err; 912 913 spin_lock_irqsave(&mgr->msg_lock, flags); 914 if ((mgr->io_num_reg_cont & mask) == value) { 915 snd_printdd("IO_NUM_REG_CONT mask %x already is set to %x\n", mask, value); 916 if (changed) 917 *changed = 0; 918 spin_unlock_irqrestore(&mgr->msg_lock, flags); 919 return 0; /* already programmed */ 920 } 921 pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); 922 rmh.cmd[0] |= IO_NUM_REG_CONT; 923 rmh.cmd[1] = mask; 924 rmh.cmd[2] = value; 925 rmh.cmd_len = 3; 926 err = pcxhr_send_msg_nolock(mgr, &rmh); 927 if (err == 0) { 928 mgr->io_num_reg_cont &= ~mask; 929 mgr->io_num_reg_cont |= value; 930 if (changed) 931 *changed = 1; 932 } 933 spin_unlock_irqrestore(&mgr->msg_lock, flags); 934 return err; 935 } 936 937 #define PCXHR_IRQ_TIMER 0x000300 938 #define PCXHR_IRQ_FREQ_CHANGE 0x000800 939 #define PCXHR_IRQ_TIME_CODE 0x001000 940 #define PCXHR_IRQ_NOTIFY 0x002000 941 #define PCXHR_IRQ_ASYNC 0x008000 942 #define PCXHR_IRQ_MASK 0x00bb00 943 #define PCXHR_FATAL_DSP_ERR 0xff0000 944 945 enum pcxhr_async_err_src { 946 PCXHR_ERR_PIPE, 947 PCXHR_ERR_STREAM, 948 PCXHR_ERR_AUDIO 949 }; 950 951 static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err, 952 enum pcxhr_async_err_src err_src, int pipe, 953 int is_capture) 954 { 955 #ifdef CONFIG_SND_DEBUG_DETECT 956 static char* err_src_name[] = { 957 [PCXHR_ERR_PIPE] = "Pipe", 958 [PCXHR_ERR_STREAM] = "Stream", 959 [PCXHR_ERR_AUDIO] = "Audio" 960 }; 961 #endif 962 if (err & 0xfff) 963 err &= 0xfff; 964 else 965 err = ((err >> 12) & 0xfff); 966 if (!err) 967 return 0; 968 snd_printdd("CMD_ASYNC : Error %s %s Pipe %d err=%x\n", err_src_name[err_src], 969 is_capture ? "Record" : "Play", pipe, err); 970 if (err == 0xe01) 971 mgr->async_err_stream_xrun++; 972 else if (err == 0xe10) 973 mgr->async_err_pipe_xrun++; 974 else 975 mgr->async_err_other_last = (int)err; 976 return 1; 977 } 978 979 980 void pcxhr_msg_tasklet(unsigned long arg) 981 { 982 struct pcxhr_mgr *mgr = (struct pcxhr_mgr *)(arg); 983 struct pcxhr_rmh *prmh = mgr->prmh; 984 int err; 985 int i, j; 986 987 if (mgr->src_it_dsp & PCXHR_IRQ_FREQ_CHANGE) 988 snd_printdd("TASKLET : PCXHR_IRQ_FREQ_CHANGE event occured\n"); 989 if (mgr->src_it_dsp & PCXHR_IRQ_TIME_CODE) 990 snd_printdd("TASKLET : PCXHR_IRQ_TIME_CODE event occured\n"); 991 if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY) 992 snd_printdd("TASKLET : PCXHR_IRQ_NOTIFY event occured\n"); 993 if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) { 994 snd_printdd("TASKLET : PCXHR_IRQ_ASYNC event occured\n"); 995 996 pcxhr_init_rmh(prmh, CMD_ASYNC); 997 prmh->cmd[0] |= 1; /* add SEL_ASYNC_EVENTS */ 998 /* this is the only one extra long response command */ 999 prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS; 1000 err = pcxhr_send_msg(mgr, prmh); 1001 if (err) 1002 snd_printk(KERN_ERR "ERROR pcxhr_msg_tasklet=%x;\n", err); 1003 i = 1; 1004 while (i < prmh->stat_len) { 1005 int nb_audio = (prmh->stat[i] >> FIELD_SIZE) & MASK_FIRST_FIELD; 1006 int nb_stream = (prmh->stat[i] >> (2*FIELD_SIZE)) & MASK_FIRST_FIELD; 1007 int pipe = prmh->stat[i] & MASK_FIRST_FIELD; 1008 int is_capture = prmh->stat[i] & 0x400000; 1009 u32 err; 1010 1011 if (prmh->stat[i] & 0x800000) { /* if BIT_END */ 1012 snd_printdd("TASKLET : End%sPipe %d\n", 1013 is_capture ? "Record" : "Play", pipe); 1014 } 1015 i++; 1016 err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1]; 1017 if (err) 1018 pcxhr_handle_async_err(mgr, err, PCXHR_ERR_PIPE, 1019 pipe, is_capture); 1020 i += 2; 1021 for (j = 0; j < nb_stream; j++) { 1022 err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1]; 1023 if (err) 1024 pcxhr_handle_async_err(mgr, err, PCXHR_ERR_STREAM, 1025 pipe, is_capture); 1026 i += 2; 1027 } 1028 for (j = 0; j < nb_audio; j++) { 1029 err = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1]; 1030 if (err) 1031 pcxhr_handle_async_err(mgr, err, PCXHR_ERR_AUDIO, 1032 pipe, is_capture); 1033 i += 2; 1034 } 1035 } 1036 } 1037 } 1038 1039 static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr, 1040 struct pcxhr_stream *stream) 1041 { 1042 u_int64_t hw_sample_count; 1043 struct pcxhr_rmh rmh; 1044 int err, stream_mask; 1045 1046 stream_mask = stream->pipe->is_capture ? 1 : 1<<stream->substream->number; 1047 1048 /* get sample count for one stream */ 1049 pcxhr_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT); 1050 pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture, 1051 stream->pipe->first_audio, 0, stream_mask); 1052 /* rmh.stat_len = 2; */ /* 2 resp data for each stream of the pipe */ 1053 1054 err = pcxhr_send_msg(mgr, &rmh); 1055 if (err) 1056 return 0; 1057 1058 hw_sample_count = ((u_int64_t)rmh.stat[0]) << 24; 1059 hw_sample_count += (u_int64_t)rmh.stat[1]; 1060 1061 snd_printdd("stream %c%d : abs samples real(%ld) timer(%ld)\n", 1062 stream->pipe->is_capture ? 'C':'P', stream->substream->number, 1063 (long unsigned int)hw_sample_count, 1064 (long unsigned int)(stream->timer_abs_periods + 1065 stream->timer_period_frag + PCXHR_GRANULARITY)); 1066 1067 return hw_sample_count; 1068 } 1069 1070 static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr, 1071 struct pcxhr_stream *stream, int samples_to_add) 1072 { 1073 if (stream->substream && (stream->status == PCXHR_STREAM_STATUS_RUNNING)) { 1074 u_int64_t new_sample_count; 1075 int elapsed = 0; 1076 int hardware_read = 0; 1077 struct snd_pcm_runtime *runtime = stream->substream->runtime; 1078 1079 if (samples_to_add < 0) { 1080 stream->timer_is_synced = 0; 1081 /* add default if no hardware_read possible */ 1082 samples_to_add = PCXHR_GRANULARITY; 1083 } 1084 1085 if (!stream->timer_is_synced) { 1086 if (stream->timer_abs_periods != 0 || 1087 stream->timer_period_frag + PCXHR_GRANULARITY >= 1088 runtime->period_size) { 1089 new_sample_count = pcxhr_stream_read_position(mgr, stream); 1090 hardware_read = 1; 1091 if (new_sample_count >= PCXHR_GRANULARITY_MIN) { 1092 /* sub security offset because of jitter and 1093 * finer granularity of dsp time (MBOX4) 1094 */ 1095 new_sample_count -= PCXHR_GRANULARITY_MIN; 1096 stream->timer_is_synced = 1; 1097 } 1098 } 1099 } 1100 if (!hardware_read) { 1101 /* if we didn't try to sync the position, increment it 1102 * by PCXHR_GRANULARITY every timer interrupt 1103 */ 1104 new_sample_count = stream->timer_abs_periods + 1105 stream->timer_period_frag + samples_to_add; 1106 } 1107 while (1) { 1108 u_int64_t new_elapse_pos = stream->timer_abs_periods + 1109 runtime->period_size; 1110 if (new_elapse_pos > new_sample_count) 1111 break; 1112 elapsed = 1; 1113 stream->timer_buf_periods++; 1114 if (stream->timer_buf_periods >= runtime->periods) 1115 stream->timer_buf_periods = 0; 1116 stream->timer_abs_periods = new_elapse_pos; 1117 } 1118 if (new_sample_count >= stream->timer_abs_periods) 1119 stream->timer_period_frag = (u_int32_t)(new_sample_count - 1120 stream->timer_abs_periods); 1121 else 1122 snd_printk(KERN_ERR "ERROR new_sample_count too small ??? %lx\n", 1123 (long unsigned int)new_sample_count); 1124 1125 if (elapsed) { 1126 spin_unlock(&mgr->lock); 1127 snd_pcm_period_elapsed(stream->substream); 1128 spin_lock(&mgr->lock); 1129 } 1130 } 1131 } 1132 1133 1134 irqreturn_t pcxhr_interrupt(int irq, void *dev_id) 1135 { 1136 struct pcxhr_mgr *mgr = dev_id; 1137 unsigned int reg; 1138 int i, j; 1139 struct snd_pcxhr *chip; 1140 1141 spin_lock(&mgr->lock); 1142 1143 reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS); 1144 if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) { 1145 spin_unlock(&mgr->lock); 1146 return IRQ_NONE; /* this device did not cause the interrupt */ 1147 } 1148 1149 /* clear interrupt */ 1150 reg = PCXHR_INPL(mgr, PCXHR_PLX_L2PCIDB); 1151 PCXHR_OUTPL(mgr, PCXHR_PLX_L2PCIDB, reg); 1152 1153 /* timer irq occured */ 1154 if (reg & PCXHR_IRQ_TIMER) { 1155 int timer_toggle = reg & PCXHR_IRQ_TIMER; 1156 /* is a 24 bit counter */ 1157 int dsp_time_new = PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK; 1158 int dsp_time_diff = dsp_time_new - mgr->dsp_time_last; 1159 1160 if (dsp_time_diff < 0 && mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID) { 1161 snd_printdd("ERROR DSP TIME old(%d) new(%d) -> " 1162 "resynchronize all streams\n", 1163 mgr->dsp_time_last, dsp_time_new); 1164 mgr->dsp_time_err++; 1165 } 1166 #ifdef CONFIG_SND_DEBUG_DETECT 1167 if (dsp_time_diff == 0) 1168 snd_printdd("ERROR DSP TIME NO DIFF time(%d)\n", dsp_time_new); 1169 else if (dsp_time_diff >= (2*PCXHR_GRANULARITY)) 1170 snd_printdd("ERROR DSP TIME TOO BIG old(%d) add(%d)\n", 1171 mgr->dsp_time_last, dsp_time_new - mgr->dsp_time_last); 1172 #endif 1173 mgr->dsp_time_last = dsp_time_new; 1174 1175 if (timer_toggle == mgr->timer_toggle) 1176 snd_printdd("ERROR TIMER TOGGLE\n"); 1177 mgr->timer_toggle = timer_toggle; 1178 1179 reg &= ~PCXHR_IRQ_TIMER; 1180 for (i = 0; i < mgr->num_cards; i++) { 1181 chip = mgr->chip[i]; 1182 for (j = 0; j < chip->nb_streams_capt; j++) 1183 pcxhr_update_timer_pos(mgr, &chip->capture_stream[j], 1184 dsp_time_diff); 1185 } 1186 for (i = 0; i < mgr->num_cards; i++) { 1187 chip = mgr->chip[i]; 1188 for (j = 0; j < chip->nb_streams_play; j++) 1189 pcxhr_update_timer_pos(mgr, &chip->playback_stream[j], 1190 dsp_time_diff); 1191 } 1192 } 1193 /* other irq's handled in the tasklet */ 1194 if (reg & PCXHR_IRQ_MASK) { 1195 1196 /* as we didn't request any notifications, some kind of xrun error 1197 * will probably occured 1198 */ 1199 /* better resynchronize all streams next interrupt : */ 1200 mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID; 1201 1202 mgr->src_it_dsp = reg; 1203 tasklet_hi_schedule(&mgr->msg_taskq); 1204 } 1205 #ifdef CONFIG_SND_DEBUG_DETECT 1206 if (reg & PCXHR_FATAL_DSP_ERR) 1207 snd_printdd("FATAL DSP ERROR : %x\n", reg); 1208 #endif 1209 spin_unlock(&mgr->lock); 1210 return IRQ_HANDLED; /* this device caused the interrupt */ 1211 } 1212