Mercurial > pt1
comparison driver/pt1_pci.c @ 9:07b2fc07ff48
updated to current driver to support signal strength.
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Mon, 23 Feb 2009 14:28:35 +0900 |
parents | 67e8eca28a80 |
children | eb694d8e4c7e |
comparison
equal
deleted
inserted
replaced
8:6da603afd363 | 9:07b2fc07ff48 |
---|---|
65 }; | 65 }; |
66 MODULE_DEVICE_TABLE(pci, pt1_pci_tbl); | 66 MODULE_DEVICE_TABLE(pci, pt1_pci_tbl); |
67 #define DEV_NAME "pt1video" | 67 #define DEV_NAME "pt1video" |
68 | 68 |
69 #define MAX_READ_BLOCK 4 // 1度に読み出す最大DMAバッファ数 | 69 #define MAX_READ_BLOCK 4 // 1度に読み出す最大DMAバッファ数 |
70 #define MAX_PCI_DEVICE 64 // 最大64枚 | 70 #define MAX_PCI_DEVICE 128 // 最大64枚 |
71 #define DMA_SIZE 4096 // DMAバッファサイズ | 71 #define DMA_SIZE 4096 // DMAバッファサイズ |
72 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) | 72 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) |
73 #define DMA_RING_SIZE 64 // RINGサイズ | 73 #define DMA_RING_SIZE 128 // RINGサイズ |
74 #define DMA_RING_MAX 511 // 1RINGにいくつ詰めるか(1023はNGで511まで) | 74 #define DMA_RING_MAX 511 // 1RINGにいくつ詰めるか(1023はNGで511まで) |
75 #define CHANEL_DMA_SIZE (1*1024*1024) // 地デジ用(16Mbps) | 75 #define CHANEL_DMA_SIZE (2*1024*1024) // 地デジ用(16Mbps) |
76 #define BS_CHANEL_DMA_SIZE (1*1024*1024) // BS用(32Mbps) | 76 #define BS_CHANEL_DMA_SIZE (4*1024*1024) // BS用(32Mbps) |
77 #else | 77 #else |
78 #define DMA_RING_SIZE 28 // RINGサイズ | 78 #define DMA_RING_SIZE 28 // RINGサイズ |
79 #define DMA_RING_MAX 511 // 1RINGにいくつ詰めるか(1023はNGで511まで) | 79 #define DMA_RING_MAX 511 // 1RINGにいくつ詰めるか(1023はNGで511まで) |
80 #define CHANEL_DMA_SIZE (1*128*1024) // 地デジ用(16Mbps) | 80 #define CHANEL_DMA_SIZE (1*128*1024) // 地デジ用(16Mbps) |
81 #define BS_CHANEL_DMA_SIZE (1*128*1024) // BS用(32Mbps) | 81 #define BS_CHANEL_DMA_SIZE (1*128*1024) // BS用(32Mbps) |
134 int real_chanel[MAX_CHANNEL] = {0, 2, 1, 3}; | 134 int real_chanel[MAX_CHANNEL] = {0, 2, 1, 3}; |
135 int channeltype[MAX_CHANNEL] = {CHANNEL_TYPE_ISDB_S, CHANNEL_TYPE_ISDB_S, | 135 int channeltype[MAX_CHANNEL] = {CHANNEL_TYPE_ISDB_S, CHANNEL_TYPE_ISDB_S, |
136 CHANNEL_TYPE_ISDB_T, CHANNEL_TYPE_ISDB_T}; | 136 CHANNEL_TYPE_ISDB_T, CHANNEL_TYPE_ISDB_T}; |
137 | 137 |
138 static PT1_DEVICE *device[MAX_PCI_DEVICE]; | 138 static PT1_DEVICE *device[MAX_PCI_DEVICE]; |
139 static struct class *pt1video_class; | |
139 | 140 |
140 #define PT1MAJOR 251 | 141 #define PT1MAJOR 251 |
141 #define DRIVERNAME "pt1video" | 142 #define DRIVERNAME "pt1video" |
142 | 143 |
143 static void reset_dma(PT1_DEVICE *dev_conf) | 144 static void reset_dma(PT1_DEVICE *dev_conf) |
151 | 152 |
152 // データ初期化 | 153 // データ初期化 |
153 for(ring_pos = 0 ; ring_pos < DMA_RING_SIZE ; ring_pos++){ | 154 for(ring_pos = 0 ; ring_pos < DMA_RING_SIZE ; ring_pos++){ |
154 for(data_pos = 0 ; data_pos < DMA_RING_MAX ; data_pos++){ | 155 for(data_pos = 0 ; data_pos < DMA_RING_MAX ; data_pos++){ |
155 dataptr = dev_conf->dmactl[ring_pos].data[data_pos]; | 156 dataptr = dev_conf->dmactl[ring_pos].data[data_pos]; |
156 // データあり? | 157 dataptr[(DMA_SIZE / sizeof(__u32)) - 2] = 0; |
157 if(dataptr[(DMA_SIZE / sizeof(__u32)) - 2] == 0){ | |
158 break ; | |
159 } | |
160 } | 158 } |
161 } | 159 } |
162 // 転送カウンタをリセット | 160 // 転送カウンタをリセット |
163 writel(0x00000010, dev_conf->regs); | 161 writel(0x00000010, dev_conf->regs); |
164 // 転送カウンタをインクリメント | 162 // 転送カウンタをインクリメント |
293 | 291 |
294 for(lp = 0 ; lp < MAX_PCI_DEVICE ; lp++){ | 292 for(lp = 0 ; lp < MAX_PCI_DEVICE ; lp++){ |
295 if(device[lp] == NULL){ | 293 if(device[lp] == NULL){ |
296 return -EIO ; | 294 return -EIO ; |
297 } | 295 } |
298 printk(KERN_INFO "(%d)base_minor=%d: MAX=%d(%d)\n", | |
299 lp, device[lp]->base_minor, | |
300 (device[lp]->base_minor + MAX_CHANNEL), minor); | |
301 if((device[lp]->base_minor <= minor) && | 296 if((device[lp]->base_minor <= minor) && |
302 ((device[lp]->base_minor + MAX_CHANNEL) > minor)){ | 297 ((device[lp]->base_minor + MAX_CHANNEL) > minor)){ |
303 mutex_lock(&device[lp]->lock); | 298 mutex_lock(&device[lp]->lock); |
304 for(lp2 = 0 ; lp2 < MAX_CHANNEL ; lp2++){ | 299 for(lp2 = 0 ; lp2 < MAX_CHANNEL ; lp2++){ |
305 channel = device[lp]->channel[lp2] ; | 300 channel = device[lp]->channel[lp2] ; |
306 printk(KERN_INFO "Minor(%d:%d)\n", channel->minor, minor); | |
307 if(channel->minor == minor){ | 301 if(channel->minor == minor){ |
308 if(channel->valid == TRUE){ | 302 if(channel->valid == TRUE){ |
309 mutex_unlock(&device[lp]->lock); | 303 mutex_unlock(&device[lp]->lock); |
310 return -EIO ; | 304 return -EIO ; |
311 } | 305 } |
376 copy_to_user(buf, channel->buf, size); | 370 copy_to_user(buf, channel->buf, size); |
377 channel->size = 0 ; | 371 channel->size = 0 ; |
378 } | 372 } |
379 } | 373 } |
380 // 読み終わったかつ使用しているのがが4K以下 | 374 // 読み終わったかつ使用しているのがが4K以下 |
381 if((channel->req_dma == TRUE) && (channel->size < DMA_SIZE)){ | 375 if(channel->req_dma == TRUE){ |
382 channel->req_dma = FALSE ; | 376 channel->req_dma = FALSE ; |
383 wake_up(&channel->ptr->dma_wait_q); | 377 wake_up(&channel->ptr->dma_wait_q); |
384 } | 378 } |
385 mutex_unlock(&channel->lock); | 379 mutex_unlock(&channel->lock); |
386 return size ; | 380 return size ; |
390 | 384 |
391 switch(channel->type){ | 385 switch(channel->type){ |
392 case CHANNEL_TYPE_ISDB_S: | 386 case CHANNEL_TYPE_ISDB_S: |
393 { | 387 { |
394 ISDB_S_TMCC tmcc ; | 388 ISDB_S_TMCC tmcc ; |
395 int lp ; | |
396 | |
397 if(bs_tune(channel->ptr->regs, | 389 if(bs_tune(channel->ptr->regs, |
398 &channel->ptr->lock, | 390 &channel->ptr->lock, |
399 channel->address, | 391 channel->address, |
400 freq->frequencyno, | 392 freq->frequencyno, |
401 &tmcc) < 0){ | 393 &tmcc) < 0){ |
402 return -EIO ; | 394 return -EIO ; |
403 } | 395 } |
404 printk(KERN_INFO "cn = (%x:%x)\n", (tmcc.cn[0] & 0xFF), | |
405 (tmcc.cn[1] & 0xFF)); | |
406 printk(KERN_INFO "agc = (%x)\n", (tmcc.agc & 0xFF)); | |
407 | 396 |
408 #if 0 | 397 #if 0 |
409 printk(KERN_INFO "clockmargin = (%x)\n", (tmcc.clockmargin & 0xFF)); | 398 printk(KERN_INFO "clockmargin = (%x)\n", (tmcc.clockmargin & 0xFF)); |
410 printk(KERN_INFO "carriermargin = (%x)\n", (tmcc.carriermargin & 0xFF)); | 399 printk(KERN_INFO "carriermargin = (%x)\n", (tmcc.carriermargin & 0xFF)); |
411 | 400 |
440 return 0 ; | 429 return 0 ; |
441 } | 430 } |
442 static int pt1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) | 431 static int pt1_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) |
443 { | 432 { |
444 PT1_CHANNEL *channel = file->private_data; | 433 PT1_CHANNEL *channel = file->private_data; |
434 int signal ; | |
445 | 435 |
446 switch(cmd){ | 436 switch(cmd){ |
447 case SET_CHANNEL: | 437 case SET_CHANNEL: |
448 { | 438 { |
449 FREQUENCY freq ; | 439 FREQUENCY freq ; |
453 case START_REC: | 443 case START_REC: |
454 SetStream(channel->ptr->regs, channel->channel, TRUE); | 444 SetStream(channel->ptr->regs, channel->channel, TRUE); |
455 return 0 ; | 445 return 0 ; |
456 case STOP_REC: | 446 case STOP_REC: |
457 SetStream(channel->ptr->regs, channel->channel, FALSE); | 447 SetStream(channel->ptr->regs, channel->channel, FALSE); |
448 return 0 ; | |
449 case GET_SIGNAL_STRENGTH: | |
450 switch(channel->type){ | |
451 case CHANNEL_TYPE_ISDB_S: | |
452 { | |
453 signal = isdb_s_read_signal_strength(channel->ptr->regs, | |
454 &channel->ptr->lock, | |
455 channel->address); | |
456 } | |
457 break ; | |
458 case CHANNEL_TYPE_ISDB_T: | |
459 // calc C/N | |
460 signal = isdb_t_read_signal_strength(channel->ptr->regs, | |
461 &channel->ptr->lock, channel->address); | |
462 break ; | |
463 } | |
464 copy_to_user(arg, &signal, sizeof(int)); | |
465 return 0 ; | |
466 case LNB_ENABLE: | |
467 if(lnb){ | |
468 settuner_reset(channel->ptr->regs, lnb, TUNER_POWER_ON_RESET_DISABLE); | |
469 } | |
470 return 0 ; | |
471 case LNB_DISABLE: | |
472 if(lnb){ | |
473 settuner_reset(channel->ptr->regs, LNB_OFF, TUNER_POWER_ON_RESET_DISABLE); | |
474 } | |
458 return 0 ; | 475 return 0 ; |
459 } | 476 } |
460 return -EINVAL; | 477 return -EINVAL; |
461 } | 478 } |
462 | 479 |
604 } | 621 } |
605 // チューナリセット | 622 // チューナリセット |
606 settuner_reset(dev_conf->regs, LNB_OFF, TUNER_POWER_ON_RESET_ENABLE); | 623 settuner_reset(dev_conf->regs, LNB_OFF, TUNER_POWER_ON_RESET_ENABLE); |
607 schedule_timeout_interruptible(msecs_to_jiffies(50)); | 624 schedule_timeout_interruptible(msecs_to_jiffies(50)); |
608 | 625 |
609 settuner_reset(dev_conf->regs, lnb, TUNER_POWER_ON_RESET_DISABLE); | 626 settuner_reset(dev_conf->regs, LNB_OFF, TUNER_POWER_ON_RESET_DISABLE); |
610 schedule_timeout_interruptible(msecs_to_jiffies(10)); | 627 schedule_timeout_interruptible(msecs_to_jiffies(10)); |
611 mutex_init(&dev_conf->lock); | 628 mutex_init(&dev_conf->lock); |
612 | 629 |
613 // Tuner 初期化処理 | 630 // Tuner 初期化処理 |
614 for(lp = 0 ; lp < MAX_TUNER ; lp++){ | 631 for(lp = 0 ; lp < MAX_TUNER ; lp++){ |
636 minor = MINOR(dev_conf->dev) ; | 653 minor = MINOR(dev_conf->dev) ; |
637 dev_conf->base_minor = minor ; | 654 dev_conf->base_minor = minor ; |
638 for(lp = 0 ; lp < MAX_PCI_DEVICE ; lp++){ | 655 for(lp = 0 ; lp < MAX_PCI_DEVICE ; lp++){ |
639 if(device[lp] == NULL){ | 656 if(device[lp] == NULL){ |
640 device[lp] = dev_conf ; | 657 device[lp] = dev_conf ; |
641 printk(KERN_INFO "Alloc[%d]\n", lp); | |
642 break ; | 658 break ; |
643 } | 659 } |
644 } | 660 } |
645 for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ | 661 for(lp = 0 ; lp < MAX_CHANNEL ; lp++){ |
646 cdev_init(&dev_conf->cdev[lp], &pt1_fops); | 662 cdev_init(&dev_conf->cdev[lp], &pt1_fops); |
655 mutex_init(&channel->lock); | 671 mutex_init(&channel->lock); |
656 // 待ち状態を解除 | 672 // 待ち状態を解除 |
657 channel->req_dma = FALSE ; | 673 channel->req_dma = FALSE ; |
658 // マイナー番号設定 | 674 // マイナー番号設定 |
659 channel->minor = MINOR(dev_conf->dev) + lp ; | 675 channel->minor = MINOR(dev_conf->dev) + lp ; |
660 printk(KERN_INFO "Minor[%d]\n", channel->minor); | |
661 // 対象のI2Cデバイス | 676 // 対象のI2Cデバイス |
662 channel->address = i2c_address[lp] ; | 677 channel->address = i2c_address[lp] ; |
663 channel->type = channeltype[lp] ; | 678 channel->type = channeltype[lp] ; |
664 // 実際のチューナ番号 | 679 // 実際のチューナ番号 |
665 channel->channel = real_chanel[lp] ; | 680 channel->channel = real_chanel[lp] ; |
680 break ; | 695 break ; |
681 } | 696 } |
682 if(channel->buf == NULL){ | 697 if(channel->buf == NULL){ |
683 goto out_err_v4l; | 698 goto out_err_v4l; |
684 } | 699 } |
700 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) | |
701 device_create(pt1video_class, NULL, MKDEV(MAJOR(dev_conf->dev), | |
702 (MINOR(dev_conf->dev) + lp)), NULL, | |
703 "pt1video%u", MINOR(dev_conf->dev) + lp); | |
704 #else | |
705 device_create(pt1video_class, NULL, MKDEV(MAJOR(dev_conf->dev), | |
706 (MINOR(dev_conf->dev) + lp)), | |
707 "pt1video%u", MINOR(dev_conf->dev) + lp); | |
708 #endif | |
709 | |
685 #if 0 | 710 #if 0 |
686 dev_conf->vdev[lp] = video_device_alloc(); | 711 dev_conf->vdev[lp] = video_device_alloc(); |
687 memcpy(dev_conf->vdev[lp], &pt1_template, sizeof(pt1_template)); | 712 memcpy(dev_conf->vdev[lp], &pt1_template, sizeof(pt1_template)); |
688 video_set_drvdata(dev_conf->vdev[lp], channel); | 713 video_set_drvdata(dev_conf->vdev[lp], channel); |
689 video_register_device(dev_conf->vdev[lp], VFL_TYPE_GRABBER, -1); | 714 video_register_device(dev_conf->vdev[lp], VFL_TYPE_GRABBER, -1); |
745 if(dev_conf->channel[lp] != NULL){ | 770 if(dev_conf->channel[lp] != NULL){ |
746 cdev_del(&dev_conf->cdev[lp]); | 771 cdev_del(&dev_conf->cdev[lp]); |
747 kfree(dev_conf->channel[lp]->buf); | 772 kfree(dev_conf->channel[lp]->buf); |
748 kfree(dev_conf->channel[lp]); | 773 kfree(dev_conf->channel[lp]); |
749 } | 774 } |
775 device_destroy(pt1video_class, | |
776 MKDEV(MAJOR(dev_conf->dev), (MINOR(dev_conf->dev) + lp))); | |
750 } | 777 } |
751 unregister_chrdev_region(dev_conf->dev, MAX_CHANNEL); | 778 unregister_chrdev_region(dev_conf->dev, MAX_CHANNEL); |
752 writel(0xb0b0000, dev_conf->regs); | 779 writel(0xb0b0000, dev_conf->regs); |
753 writel(0, dev_conf->regs + 4); | 780 writel(0, dev_conf->regs + 4); |
754 settuner_reset(dev_conf->regs, LNB_OFF, TUNER_POWER_OFF); | 781 settuner_reset(dev_conf->regs, LNB_OFF, TUNER_POWER_OFF); |
786 }; | 813 }; |
787 | 814 |
788 | 815 |
789 static int __init pt1_pci_init(void) | 816 static int __init pt1_pci_init(void) |
790 { | 817 { |
818 pt1video_class = class_create(THIS_MODULE, DRIVERNAME); | |
819 if (IS_ERR(pt1video_class)) | |
820 return PTR_ERR(pt1video_class); | |
791 return pci_register_driver(&pt1_driver); | 821 return pci_register_driver(&pt1_driver); |
792 } | 822 } |
793 | 823 |
794 | 824 |
795 static void __exit pt1_pci_cleanup(void) | 825 static void __exit pt1_pci_cleanup(void) |
796 { | 826 { |
827 class_destroy(pt1video_class); | |
797 pci_unregister_driver (&pt1_driver); | 828 pci_unregister_driver (&pt1_driver); |
798 } | 829 } |
799 | 830 |
800 module_init(pt1_pci_init); | 831 module_init(pt1_pci_init); |
801 module_exit(pt1_pci_cleanup); | 832 module_exit(pt1_pci_cleanup); |