1 /* 2 * Copyright (C) 2010-2013 Bluecherry, LLC <http://www.bluecherrydvr.com> 3 * 4 * Original author: 5 * Ben Collins <bcollins@ubuntu.com> 6 * 7 * Additional work by: 8 * John Brooks <john.brooks@bluecherry.net> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 */ 20 21 #include <linux/kernel.h> 22 #include <linux/module.h> 23 #include <linux/pci.h> 24 #include <linux/interrupt.h> 25 #include <linux/videodev2.h> 26 #include <linux/delay.h> 27 #include <linux/sysfs.h> 28 #include <linux/ktime.h> 29 #include <linux/slab.h> 30 31 #include "solo6x10.h" 32 #include "solo6x10-tw28.h" 33 34 MODULE_DESCRIPTION("Softlogic 6x10 MPEG4/H.264/G.723 CODEC V4L2/ALSA Driver"); 35 MODULE_AUTHOR("Bluecherry <maintainers@bluecherrydvr.com>"); 36 MODULE_VERSION(SOLO6X10_VERSION); 37 MODULE_LICENSE("GPL"); 38 39 static unsigned video_nr = -1; 40 module_param(video_nr, uint, 0644); 41 MODULE_PARM_DESC(video_nr, "videoX start number, -1 is autodetect (default)"); 42 43 static int full_eeprom; /* default is only top 64B */ 44 module_param(full_eeprom, uint, 0644); 45 MODULE_PARM_DESC(full_eeprom, "Allow access to full 128B EEPROM (dangerous)"); 46 47 48 static void solo_set_time(struct solo_dev *solo_dev) 49 { 50 struct timespec ts; 51 52 ktime_get_ts(&ts); 53 54 solo_reg_write(solo_dev, SOLO_TIMER_SEC, ts.tv_sec); 55 solo_reg_write(solo_dev, SOLO_TIMER_USEC, ts.tv_nsec / NSEC_PER_USEC); 56 } 57 58 static void solo_timer_sync(struct solo_dev *solo_dev) 59 { 60 u32 sec, usec; 61 struct timespec ts; 62 long diff; 63 64 if (solo_dev->type != SOLO_DEV_6110) 65 return; 66 67 if (++solo_dev->time_sync < 60) 68 return; 69 70 solo_dev->time_sync = 0; 71 72 sec = solo_reg_read(solo_dev, SOLO_TIMER_SEC); 73 usec = solo_reg_read(solo_dev, SOLO_TIMER_USEC); 74 75 ktime_get_ts(&ts); 76 77 diff = (long)ts.tv_sec - (long)sec; 78 diff = (diff * 1000000) 79 + ((long)(ts.tv_nsec / NSEC_PER_USEC) - (long)usec); 80 81 if (diff > 1000 || diff < -1000) { 82 solo_set_time(solo_dev); 83 } else if (diff) { 84 long usec_lsb = solo_dev->usec_lsb; 85 86 usec_lsb -= diff / 4; 87 if (usec_lsb < 0) 88 usec_lsb = 0; 89 else if (usec_lsb > 255) 90 usec_lsb = 255; 91 92 solo_dev->usec_lsb = usec_lsb; 93 solo_reg_write(solo_dev, SOLO_TIMER_USEC_LSB, 94 solo_dev->usec_lsb); 95 } 96 } 97 98 static irqreturn_t solo_isr(int irq, void *data) 99 { 100 struct solo_dev *solo_dev = data; 101 u32 status; 102 int i; 103 104 status = solo_reg_read(solo_dev, SOLO_IRQ_STAT); 105 if (!status) 106 return IRQ_NONE; 107 108 /* Acknowledge all interrupts immediately */ 109 solo_reg_write(solo_dev, SOLO_IRQ_STAT, status); 110 111 if (status & SOLO_IRQ_PCI_ERR) 112 solo_p2m_error_isr(solo_dev); 113 114 for (i = 0; i < SOLO_NR_P2M; i++) 115 if (status & SOLO_IRQ_P2M(i)) 116 solo_p2m_isr(solo_dev, i); 117 118 if (status & SOLO_IRQ_IIC) 119 solo_i2c_isr(solo_dev); 120 121 if (status & SOLO_IRQ_VIDEO_IN) { 122 solo_video_in_isr(solo_dev); 123 solo_timer_sync(solo_dev); 124 } 125 126 if (status & SOLO_IRQ_ENCODER) 127 solo_enc_v4l2_isr(solo_dev); 128 129 if (status & SOLO_IRQ_G723) 130 solo_g723_isr(solo_dev); 131 132 return IRQ_HANDLED; 133 } 134 135 static void free_solo_dev(struct solo_dev *solo_dev) 136 { 137 struct pci_dev *pdev = solo_dev->pdev; 138 139 if (solo_dev->dev.parent) 140 device_unregister(&solo_dev->dev); 141 142 if (solo_dev->reg_base) { 143 /* Bring down the sub-devices first */ 144 solo_g723_exit(solo_dev); 145 solo_enc_v4l2_exit(solo_dev); 146 solo_enc_exit(solo_dev); 147 solo_v4l2_exit(solo_dev); 148 solo_disp_exit(solo_dev); 149 solo_gpio_exit(solo_dev); 150 solo_p2m_exit(solo_dev); 151 solo_i2c_exit(solo_dev); 152 153 /* Now cleanup the PCI device */ 154 solo_irq_off(solo_dev, ~0); 155 free_irq(pdev->irq, solo_dev); 156 pci_iounmap(pdev, solo_dev->reg_base); 157 } 158 159 pci_release_regions(pdev); 160 pci_disable_device(pdev); 161 v4l2_device_unregister(&solo_dev->v4l2_dev); 162 pci_set_drvdata(pdev, NULL); 163 164 kfree(solo_dev); 165 } 166 167 static ssize_t eeprom_store(struct device *dev, struct device_attribute *attr, 168 const char *buf, size_t count) 169 { 170 struct solo_dev *solo_dev = 171 container_of(dev, struct solo_dev, dev); 172 u16 *p = (u16 *)buf; 173 int i; 174 175 if (count & 0x1) 176 dev_warn(dev, "EEPROM Write not aligned (truncating)\n"); 177 178 if (!full_eeprom && count > 64) { 179 dev_warn(dev, "EEPROM Write truncated to 64 bytes\n"); 180 count = 64; 181 } else if (full_eeprom && count > 128) { 182 dev_warn(dev, "EEPROM Write truncated to 128 bytes\n"); 183 count = 128; 184 } 185 186 solo_eeprom_ewen(solo_dev, 1); 187 188 for (i = full_eeprom ? 0 : 32; i < min((int)(full_eeprom ? 64 : 32), 189 (int)(count / 2)); i++) 190 solo_eeprom_write(solo_dev, i, cpu_to_be16(p[i])); 191 192 solo_eeprom_ewen(solo_dev, 0); 193 194 return count; 195 } 196 197 static ssize_t eeprom_show(struct device *dev, struct device_attribute *attr, 198 char *buf) 199 { 200 struct solo_dev *solo_dev = 201 container_of(dev, struct solo_dev, dev); 202 u16 *p = (u16 *)buf; 203 int count = (full_eeprom ? 128 : 64); 204 int i; 205 206 for (i = (full_eeprom ? 0 : 32); i < (count / 2); i++) 207 p[i] = be16_to_cpu(solo_eeprom_read(solo_dev, i)); 208 209 return count; 210 } 211 212 static ssize_t p2m_timeouts_show(struct device *dev, 213 struct device_attribute *attr, 214 char *buf) 215 { 216 struct solo_dev *solo_dev = 217 container_of(dev, struct solo_dev, dev); 218 219 return sprintf(buf, "%d\n", solo_dev->p2m_timeouts); 220 } 221 222 static ssize_t sdram_size_show(struct device *dev, 223 struct device_attribute *attr, 224 char *buf) 225 { 226 struct solo_dev *solo_dev = 227 container_of(dev, struct solo_dev, dev); 228 229 return sprintf(buf, "%dMegs\n", solo_dev->sdram_size >> 20); 230 } 231 232 static ssize_t tw28xx_show(struct device *dev, 233 struct device_attribute *attr, 234 char *buf) 235 { 236 struct solo_dev *solo_dev = 237 container_of(dev, struct solo_dev, dev); 238 239 return sprintf(buf, "tw2815[%d] tw2864[%d] tw2865[%d]\n", 240 hweight32(solo_dev->tw2815), 241 hweight32(solo_dev->tw2864), 242 hweight32(solo_dev->tw2865)); 243 } 244 245 static ssize_t input_map_show(struct device *dev, 246 struct device_attribute *attr, 247 char *buf) 248 { 249 struct solo_dev *solo_dev = 250 container_of(dev, struct solo_dev, dev); 251 unsigned int val; 252 char *out = buf; 253 254 val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_0); 255 out += sprintf(out, "Channel 0 => Input %d\n", val & 0x1f); 256 out += sprintf(out, "Channel 1 => Input %d\n", (val >> 5) & 0x1f); 257 out += sprintf(out, "Channel 2 => Input %d\n", (val >> 10) & 0x1f); 258 out += sprintf(out, "Channel 3 => Input %d\n", (val >> 15) & 0x1f); 259 out += sprintf(out, "Channel 4 => Input %d\n", (val >> 20) & 0x1f); 260 out += sprintf(out, "Channel 5 => Input %d\n", (val >> 25) & 0x1f); 261 262 val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_1); 263 out += sprintf(out, "Channel 6 => Input %d\n", val & 0x1f); 264 out += sprintf(out, "Channel 7 => Input %d\n", (val >> 5) & 0x1f); 265 out += sprintf(out, "Channel 8 => Input %d\n", (val >> 10) & 0x1f); 266 out += sprintf(out, "Channel 9 => Input %d\n", (val >> 15) & 0x1f); 267 out += sprintf(out, "Channel 10 => Input %d\n", (val >> 20) & 0x1f); 268 out += sprintf(out, "Channel 11 => Input %d\n", (val >> 25) & 0x1f); 269 270 val = solo_reg_read(solo_dev, SOLO_VI_CH_SWITCH_2); 271 out += sprintf(out, "Channel 12 => Input %d\n", val & 0x1f); 272 out += sprintf(out, "Channel 13 => Input %d\n", (val >> 5) & 0x1f); 273 out += sprintf(out, "Channel 14 => Input %d\n", (val >> 10) & 0x1f); 274 out += sprintf(out, "Channel 15 => Input %d\n", (val >> 15) & 0x1f); 275 out += sprintf(out, "Spot Output => Input %d\n", (val >> 20) & 0x1f); 276 277 return out - buf; 278 } 279 280 static ssize_t p2m_timeout_store(struct device *dev, 281 struct device_attribute *attr, 282 const char *buf, size_t count) 283 { 284 struct solo_dev *solo_dev = 285 container_of(dev, struct solo_dev, dev); 286 unsigned long ms; 287 int ret = kstrtoul(buf, 10, &ms); 288 289 if (ret < 0 || ms > 200) 290 return -EINVAL; 291 solo_dev->p2m_jiffies = msecs_to_jiffies(ms); 292 293 return count; 294 } 295 296 static ssize_t p2m_timeout_show(struct device *dev, 297 struct device_attribute *attr, 298 char *buf) 299 { 300 struct solo_dev *solo_dev = 301 container_of(dev, struct solo_dev, dev); 302 303 return sprintf(buf, "%ums\n", jiffies_to_msecs(solo_dev->p2m_jiffies)); 304 } 305 306 static ssize_t intervals_show(struct device *dev, 307 struct device_attribute *attr, 308 char *buf) 309 { 310 struct solo_dev *solo_dev = 311 container_of(dev, struct solo_dev, dev); 312 char *out = buf; 313 int fps = solo_dev->fps; 314 int i; 315 316 for (i = 0; i < solo_dev->nr_chans; i++) { 317 out += sprintf(out, "Channel %d: %d/%d (0x%08x)\n", 318 i, solo_dev->v4l2_enc[i]->interval, fps, 319 solo_reg_read(solo_dev, SOLO_CAP_CH_INTV(i))); 320 } 321 322 return out - buf; 323 } 324 325 static ssize_t sdram_offsets_show(struct device *dev, 326 struct device_attribute *attr, 327 char *buf) 328 { 329 struct solo_dev *solo_dev = 330 container_of(dev, struct solo_dev, dev); 331 char *out = buf; 332 333 out += sprintf(out, "DISP: 0x%08x @ 0x%08x\n", 334 SOLO_DISP_EXT_ADDR, 335 SOLO_DISP_EXT_SIZE); 336 337 out += sprintf(out, "EOSD: 0x%08x @ 0x%08x (0x%08x * %d)\n", 338 SOLO_EOSD_EXT_ADDR, 339 SOLO_EOSD_EXT_AREA(solo_dev), 340 SOLO_EOSD_EXT_SIZE(solo_dev), 341 SOLO_EOSD_EXT_AREA(solo_dev) / 342 SOLO_EOSD_EXT_SIZE(solo_dev)); 343 344 out += sprintf(out, "MOTI: 0x%08x @ 0x%08x\n", 345 SOLO_MOTION_EXT_ADDR(solo_dev), 346 SOLO_MOTION_EXT_SIZE); 347 348 out += sprintf(out, "G723: 0x%08x @ 0x%08x\n", 349 SOLO_G723_EXT_ADDR(solo_dev), 350 SOLO_G723_EXT_SIZE); 351 352 out += sprintf(out, "CAPT: 0x%08x @ 0x%08x (0x%08x * %d)\n", 353 SOLO_CAP_EXT_ADDR(solo_dev), 354 SOLO_CAP_EXT_SIZE(solo_dev), 355 SOLO_CAP_PAGE_SIZE, 356 SOLO_CAP_EXT_SIZE(solo_dev) / SOLO_CAP_PAGE_SIZE); 357 358 out += sprintf(out, "EREF: 0x%08x @ 0x%08x (0x%08x * %d)\n", 359 SOLO_EREF_EXT_ADDR(solo_dev), 360 SOLO_EREF_EXT_AREA(solo_dev), 361 SOLO_EREF_EXT_SIZE, 362 SOLO_EREF_EXT_AREA(solo_dev) / SOLO_EREF_EXT_SIZE); 363 364 out += sprintf(out, "MPEG: 0x%08x @ 0x%08x\n", 365 SOLO_MP4E_EXT_ADDR(solo_dev), 366 SOLO_MP4E_EXT_SIZE(solo_dev)); 367 368 out += sprintf(out, "JPEG: 0x%08x @ 0x%08x\n", 369 SOLO_JPEG_EXT_ADDR(solo_dev), 370 SOLO_JPEG_EXT_SIZE(solo_dev)); 371 372 return out - buf; 373 } 374 375 static ssize_t sdram_show(struct file *file, struct kobject *kobj, 376 struct bin_attribute *a, char *buf, 377 loff_t off, size_t count) 378 { 379 struct device *dev = container_of(kobj, struct device, kobj); 380 struct solo_dev *solo_dev = 381 container_of(dev, struct solo_dev, dev); 382 const int size = solo_dev->sdram_size; 383 384 if (off >= size) 385 return 0; 386 387 if (off + count > size) 388 count = size - off; 389 390 if (solo_p2m_dma(solo_dev, 0, buf, off, count, 0, 0)) 391 return -EIO; 392 393 return count; 394 } 395 396 static const struct device_attribute solo_dev_attrs[] = { 397 __ATTR(eeprom, 0640, eeprom_show, eeprom_store), 398 __ATTR(p2m_timeout, 0644, p2m_timeout_show, p2m_timeout_store), 399 __ATTR_RO(p2m_timeouts), 400 __ATTR_RO(sdram_size), 401 __ATTR_RO(tw28xx), 402 __ATTR_RO(input_map), 403 __ATTR_RO(intervals), 404 __ATTR_RO(sdram_offsets), 405 }; 406 407 static void solo_device_release(struct device *dev) 408 { 409 /* Do nothing */ 410 } 411 412 static int solo_sysfs_init(struct solo_dev *solo_dev) 413 { 414 struct bin_attribute *sdram_attr = &solo_dev->sdram_attr; 415 struct device *dev = &solo_dev->dev; 416 const char *driver; 417 int i; 418 419 if (solo_dev->type == SOLO_DEV_6110) 420 driver = "solo6110"; 421 else 422 driver = "solo6010"; 423 424 dev->release = solo_device_release; 425 dev->parent = &solo_dev->pdev->dev; 426 set_dev_node(dev, dev_to_node(&solo_dev->pdev->dev)); 427 dev_set_name(dev, "%s-%d-%d", driver, solo_dev->vfd->num, 428 solo_dev->nr_chans); 429 430 if (device_register(dev)) { 431 dev->parent = NULL; 432 return -ENOMEM; 433 } 434 435 for (i = 0; i < ARRAY_SIZE(solo_dev_attrs); i++) { 436 if (device_create_file(dev, &solo_dev_attrs[i])) { 437 device_unregister(dev); 438 return -ENOMEM; 439 } 440 } 441 442 sysfs_attr_init(&sdram_attr->attr); 443 sdram_attr->attr.name = "sdram"; 444 sdram_attr->attr.mode = 0440; 445 sdram_attr->read = sdram_show; 446 sdram_attr->size = solo_dev->sdram_size; 447 448 if (device_create_bin_file(dev, sdram_attr)) { 449 device_unregister(dev); 450 return -ENOMEM; 451 } 452 453 return 0; 454 } 455 456 static int solo_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 457 { 458 struct solo_dev *solo_dev; 459 int ret; 460 u8 chip_id; 461 462 solo_dev = kzalloc(sizeof(*solo_dev), GFP_KERNEL); 463 if (solo_dev == NULL) 464 return -ENOMEM; 465 466 if (id->driver_data == SOLO_DEV_6010) 467 dev_info(&pdev->dev, "Probing Softlogic 6010\n"); 468 else 469 dev_info(&pdev->dev, "Probing Softlogic 6110\n"); 470 471 solo_dev->type = id->driver_data; 472 solo_dev->pdev = pdev; 473 ret = v4l2_device_register(&pdev->dev, &solo_dev->v4l2_dev); 474 if (ret) 475 goto fail_probe; 476 477 /* Only for during init */ 478 solo_dev->p2m_jiffies = msecs_to_jiffies(100); 479 480 ret = pci_enable_device(pdev); 481 if (ret) 482 goto fail_probe; 483 484 pci_set_master(pdev); 485 486 /* RETRY/TRDY Timeout disabled */ 487 pci_write_config_byte(pdev, 0x40, 0x00); 488 pci_write_config_byte(pdev, 0x41, 0x00); 489 490 ret = pci_request_regions(pdev, SOLO6X10_NAME); 491 if (ret) 492 goto fail_probe; 493 494 solo_dev->reg_base = pci_ioremap_bar(pdev, 0); 495 if (solo_dev->reg_base == NULL) { 496 ret = -ENOMEM; 497 goto fail_probe; 498 } 499 500 chip_id = solo_reg_read(solo_dev, SOLO_CHIP_OPTION) & 501 SOLO_CHIP_ID_MASK; 502 switch (chip_id) { 503 case 7: 504 solo_dev->nr_chans = 16; 505 solo_dev->nr_ext = 5; 506 break; 507 case 6: 508 solo_dev->nr_chans = 8; 509 solo_dev->nr_ext = 2; 510 break; 511 default: 512 dev_warn(&pdev->dev, "Invalid chip_id 0x%02x, assuming 4 ch\n", 513 chip_id); 514 case 5: 515 solo_dev->nr_chans = 4; 516 solo_dev->nr_ext = 1; 517 } 518 519 /* Disable all interrupts to start */ 520 solo_irq_off(solo_dev, ~0); 521 522 /* Initial global settings */ 523 if (solo_dev->type == SOLO_DEV_6010) { 524 solo_dev->clock_mhz = 108; 525 solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT 526 | SOLO_SYS_CFG_INPUTDIV(25) 527 | SOLO_SYS_CFG_FEEDBACKDIV(solo_dev->clock_mhz * 2 - 2) 528 | SOLO_SYS_CFG_OUTDIV(3); 529 solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config); 530 } else { 531 u32 divq, divf; 532 533 solo_dev->clock_mhz = 135; 534 535 if (solo_dev->clock_mhz < 125) { 536 divq = 3; 537 divf = (solo_dev->clock_mhz * 4) / 3 - 1; 538 } else { 539 divq = 2; 540 divf = (solo_dev->clock_mhz * 2) / 3 - 1; 541 } 542 543 solo_reg_write(solo_dev, SOLO_PLL_CONFIG, 544 (1 << 20) | /* PLL_RANGE */ 545 (8 << 15) | /* PLL_DIVR */ 546 (divq << 12) | 547 (divf << 4) | 548 (1 << 1) /* PLL_FSEN */); 549 550 solo_dev->sys_config = SOLO_SYS_CFG_SDRAM64BIT; 551 } 552 553 solo_reg_write(solo_dev, SOLO_SYS_CFG, solo_dev->sys_config); 554 solo_reg_write(solo_dev, SOLO_TIMER_CLOCK_NUM, 555 solo_dev->clock_mhz - 1); 556 557 /* PLL locking time of 1ms */ 558 mdelay(1); 559 560 ret = request_irq(pdev->irq, solo_isr, IRQF_SHARED, SOLO6X10_NAME, 561 solo_dev); 562 if (ret) 563 goto fail_probe; 564 565 /* Handle this from the start */ 566 solo_irq_on(solo_dev, SOLO_IRQ_PCI_ERR); 567 568 ret = solo_i2c_init(solo_dev); 569 if (ret) 570 goto fail_probe; 571 572 /* Setup the DMA engine */ 573 solo_reg_write(solo_dev, SOLO_DMA_CTRL, 574 SOLO_DMA_CTRL_REFRESH_CYCLE(1) | 575 SOLO_DMA_CTRL_SDRAM_SIZE(2) | 576 SOLO_DMA_CTRL_SDRAM_CLK_INVERT | 577 SOLO_DMA_CTRL_READ_CLK_SELECT | 578 SOLO_DMA_CTRL_LATENCY(1)); 579 580 /* Undocumented crap */ 581 solo_reg_write(solo_dev, SOLO_DMA_CTRL1, 582 solo_dev->type == SOLO_DEV_6010 ? 0x100 : 0x300); 583 584 if (solo_dev->type != SOLO_DEV_6010) { 585 solo_dev->usec_lsb = 0x3f; 586 solo_set_time(solo_dev); 587 } 588 589 /* Disable watchdog */ 590 solo_reg_write(solo_dev, SOLO_WATCHDOG, 0); 591 592 /* Initialize sub components */ 593 594 ret = solo_p2m_init(solo_dev); 595 if (ret) 596 goto fail_probe; 597 598 ret = solo_disp_init(solo_dev); 599 if (ret) 600 goto fail_probe; 601 602 ret = solo_gpio_init(solo_dev); 603 if (ret) 604 goto fail_probe; 605 606 ret = solo_tw28_init(solo_dev); 607 if (ret) 608 goto fail_probe; 609 610 ret = solo_v4l2_init(solo_dev, video_nr); 611 if (ret) 612 goto fail_probe; 613 614 ret = solo_enc_init(solo_dev); 615 if (ret) 616 goto fail_probe; 617 618 ret = solo_enc_v4l2_init(solo_dev, video_nr); 619 if (ret) 620 goto fail_probe; 621 622 ret = solo_g723_init(solo_dev); 623 if (ret) 624 goto fail_probe; 625 626 ret = solo_sysfs_init(solo_dev); 627 if (ret) 628 goto fail_probe; 629 630 /* Now that init is over, set this lower */ 631 solo_dev->p2m_jiffies = msecs_to_jiffies(20); 632 633 return 0; 634 635 fail_probe: 636 free_solo_dev(solo_dev); 637 return ret; 638 } 639 640 static void solo_pci_remove(struct pci_dev *pdev) 641 { 642 struct v4l2_device *v4l2_dev = pci_get_drvdata(pdev); 643 struct solo_dev *solo_dev = container_of(v4l2_dev, struct solo_dev, v4l2_dev); 644 645 free_solo_dev(solo_dev); 646 } 647 648 static const struct pci_device_id solo_id_table[] = { 649 /* 6010 based cards */ 650 { PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6010), 651 .driver_data = SOLO_DEV_6010 }, 652 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_4), 653 .driver_data = SOLO_DEV_6010 }, 654 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_9), 655 .driver_data = SOLO_DEV_6010 }, 656 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_NEUSOLO_16), 657 .driver_data = SOLO_DEV_6010 }, 658 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_4), 659 .driver_data = SOLO_DEV_6010 }, 660 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_9), 661 .driver_data = SOLO_DEV_6010 }, 662 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_SOLO_16), 663 .driver_data = SOLO_DEV_6010 }, 664 /* 6110 based cards */ 665 { PCI_DEVICE(PCI_VENDOR_ID_SOFTLOGIC, PCI_DEVICE_ID_SOLO6110), 666 .driver_data = SOLO_DEV_6110 }, 667 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_4), 668 .driver_data = SOLO_DEV_6110 }, 669 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_8), 670 .driver_data = SOLO_DEV_6110 }, 671 { PCI_DEVICE(PCI_VENDOR_ID_BLUECHERRY, PCI_DEVICE_ID_BC_6110_16), 672 .driver_data = SOLO_DEV_6110 }, 673 {0,} 674 }; 675 676 MODULE_DEVICE_TABLE(pci, solo_id_table); 677 678 static struct pci_driver solo_pci_driver = { 679 .name = SOLO6X10_NAME, 680 .id_table = solo_id_table, 681 .probe = solo_pci_probe, 682 .remove = solo_pci_remove, 683 }; 684 685 module_pci_driver(solo_pci_driver); 686