diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-15 15:49:56 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-15 15:49:56 -0500 |
commit | 122804ecb59493fbb4d31b3ba9ac59faaf45276f (patch) | |
tree | cff4d8a158c412e4a8d3abc8d91bb0eb52b01c9a /drivers/media/video | |
parent | 16008d641670571ff4cd750b416c7caf2d89f467 (diff) | |
parent | 126400033940afb658123517a2e80eb68259fbd7 (diff) |
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (655 commits)
[media] revert patch: HDIC HD29L2 DMB-TH USB2.0 reference design driver
mb86a20s: Add a few more register settings at the init seq
mb86a20s: Group registers into the same line
[media] [PATCH] don't reset the delivery system on DTV_CLEAR
[media] [BUG] it913x-fe fix typo error making SNR levels unstable
[media] cx23885: Query the CX25840 during enum_input for status
[media] cx25840: Add support for g_input_status
[media] rc-videomate-m1f.c Rename to match remote controler name
[media] drivers: media: au0828: Fix dependency for VIDEO_AU0828
[media] convert drivers/media/* to use module_platform_driver()
[media] drivers: video: cx231xx: Fix dependency for VIDEO_CX231XX_DVB
[media] Exynos4 JPEG codec v4l2 driver
[media] doc: v4l: selection: choose pixels as units for selection rectangles
[media] v4l: s5p-tv: mixer: fix setup of VP scaling
[media] v4l: s5p-tv: mixer: add support for selection API
[media] v4l: emulate old crop API using extended crop/compose API
[media] doc: v4l: add documentation for selection API
[media] doc: v4l: add binary images for selection API
[media] v4l: add support for selection api
[media] hd29l2: fix review findings
...
Diffstat (limited to 'drivers/media/video')
218 files changed, 15158 insertions, 5613 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index b303a3f8a9f8..9adada0d7447 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
@@ -533,6 +533,13 @@ config VIDEO_ADP1653 | |||
533 | This is a driver for the ADP1653 flash controller. It is used for | 533 | This is a driver for the ADP1653 flash controller. It is used for |
534 | example in Nokia N900. | 534 | example in Nokia N900. |
535 | 535 | ||
536 | config VIDEO_AS3645A | ||
537 | tristate "AS3645A flash driver support" | ||
538 | depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER | ||
539 | ---help--- | ||
540 | This is a driver for the AS3645A and LM3555 flash controllers. It has | ||
541 | build in control for flash, torch and indicator LEDs. | ||
542 | |||
536 | comment "Video improvement chips" | 543 | comment "Video improvement chips" |
537 | 544 | ||
538 | config VIDEO_UPD64031A | 545 | config VIDEO_UPD64031A |
@@ -580,25 +587,6 @@ config VIDEO_M52790 | |||
580 | 587 | ||
581 | endmenu # encoder / decoder chips | 588 | endmenu # encoder / decoder chips |
582 | 589 | ||
583 | config VIDEO_SH_VOU | ||
584 | tristate "SuperH VOU video output driver" | ||
585 | depends on VIDEO_DEV && ARCH_SHMOBILE | ||
586 | select VIDEOBUF_DMA_CONTIG | ||
587 | help | ||
588 | Support for the Video Output Unit (VOU) on SuperH SoCs. | ||
589 | |||
590 | config VIDEO_VIU | ||
591 | tristate "Freescale VIU Video Driver" | ||
592 | depends on VIDEO_V4L2 && PPC_MPC512x | ||
593 | select VIDEOBUF_DMA_CONTIG | ||
594 | default y | ||
595 | ---help--- | ||
596 | Support for Freescale VIU video driver. This device captures | ||
597 | video data, or overlays video on DIU frame buffer. | ||
598 | |||
599 | Say Y here if you want to enable VIU device on MPC5121e Rev2+. | ||
600 | In doubt, say N. | ||
601 | |||
602 | config VIDEO_VIVI | 590 | config VIDEO_VIVI |
603 | tristate "Virtual Video Driver" | 591 | tristate "Virtual Video Driver" |
604 | depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 | 592 | depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 |
@@ -613,66 +601,130 @@ config VIDEO_VIVI | |||
613 | Say Y here if you want to test video apps or debug V4L devices. | 601 | Say Y here if you want to test video apps or debug V4L devices. |
614 | In doubt, say N. | 602 | In doubt, say N. |
615 | 603 | ||
616 | source "drivers/media/video/davinci/Kconfig" | 604 | # |
605 | # USB Multimedia device configuration | ||
606 | # | ||
617 | 607 | ||
618 | source "drivers/media/video/omap/Kconfig" | 608 | menuconfig V4L_USB_DRIVERS |
609 | bool "V4L USB devices" | ||
610 | depends on USB | ||
611 | default y | ||
619 | 612 | ||
620 | source "drivers/media/video/bt8xx/Kconfig" | 613 | if V4L_USB_DRIVERS |
621 | 614 | ||
622 | config VIDEO_PMS | 615 | source "drivers/media/video/uvc/Kconfig" |
623 | tristate "Mediavision Pro Movie Studio Video For Linux" | 616 | |
624 | depends on ISA && VIDEO_V4L2 | 617 | source "drivers/media/video/gspca/Kconfig" |
625 | help | 618 | |
626 | Say Y if you have such a thing. | 619 | source "drivers/media/video/pvrusb2/Kconfig" |
620 | |||
621 | source "drivers/media/video/hdpvr/Kconfig" | ||
622 | |||
623 | source "drivers/media/video/em28xx/Kconfig" | ||
624 | |||
625 | source "drivers/media/video/tlg2300/Kconfig" | ||
626 | |||
627 | source "drivers/media/video/cx231xx/Kconfig" | ||
628 | |||
629 | source "drivers/media/video/tm6000/Kconfig" | ||
630 | |||
631 | source "drivers/media/video/usbvision/Kconfig" | ||
632 | |||
633 | source "drivers/media/video/et61x251/Kconfig" | ||
634 | |||
635 | source "drivers/media/video/sn9c102/Kconfig" | ||
636 | |||
637 | source "drivers/media/video/pwc/Kconfig" | ||
638 | |||
639 | source "drivers/media/video/cpia2/Kconfig" | ||
640 | |||
641 | config USB_ZR364XX | ||
642 | tristate "USB ZR364XX Camera support" | ||
643 | depends on VIDEO_V4L2 | ||
644 | select VIDEOBUF_GEN | ||
645 | select VIDEOBUF_VMALLOC | ||
646 | ---help--- | ||
647 | Say Y here if you want to connect this type of camera to your | ||
648 | computer's USB port. | ||
649 | See <file:Documentation/video4linux/zr364xx.txt> for more info | ||
650 | and list of supported cameras. | ||
627 | 651 | ||
628 | To compile this driver as a module, choose M here: the | 652 | To compile this driver as a module, choose M here: the |
629 | module will be called pms. | 653 | module will be called zr364xx. |
630 | 654 | ||
631 | config VIDEO_BWQCAM | 655 | config USB_STKWEBCAM |
632 | tristate "Quickcam BW Video For Linux" | 656 | tristate "USB Syntek DC1125 Camera support" |
633 | depends on PARPORT && VIDEO_V4L2 | 657 | depends on VIDEO_V4L2 && EXPERIMENTAL |
634 | help | 658 | ---help--- |
635 | Say Y have if you the black and white version of the QuickCam | 659 | Say Y here if you want to use this type of camera. |
636 | camera. See the next option for the color version. | 660 | Supported devices are typically found in some Asus laptops, |
661 | with USB id 174f:a311 and 05e1:0501. Other Syntek cameras | ||
662 | may be supported by the stk11xx driver, from which this is | ||
663 | derived, see <http://sourceforge.net/projects/syntekdriver/> | ||
637 | 664 | ||
638 | To compile this driver as a module, choose M here: the | 665 | To compile this driver as a module, choose M here: the |
639 | module will be called bw-qcam. | 666 | module will be called stkwebcam. |
640 | 667 | ||
641 | config VIDEO_CQCAM | 668 | config USB_S2255 |
642 | tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)" | 669 | tristate "USB Sensoray 2255 video capture device" |
643 | depends on EXPERIMENTAL && PARPORT && VIDEO_V4L2 | 670 | depends on VIDEO_V4L2 |
671 | select VIDEOBUF_VMALLOC | ||
672 | default n | ||
644 | help | 673 | help |
645 | This is the video4linux driver for the colour version of the | 674 | Say Y here if you want support for the Sensoray 2255 USB device. |
646 | Connectix QuickCam. If you have one of these cameras, say Y here, | 675 | This driver can be compiled as a module, called s2255drv. |
647 | otherwise say N. This driver does not work with the original | ||
648 | monochrome QuickCam, QuickCam VC or QuickClip. It is also available | ||
649 | as a module (c-qcam). | ||
650 | Read <file:Documentation/video4linux/CQcam.txt> for more information. | ||
651 | 676 | ||
652 | config VIDEO_W9966 | 677 | endif # V4L_USB_DRIVERS |
653 | tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux" | ||
654 | depends on PARPORT_1284 && PARPORT && VIDEO_V4L2 | ||
655 | help | ||
656 | Video4linux driver for Winbond's w9966 based Webcams. | ||
657 | Currently tested with the LifeView FlyCam Supra. | ||
658 | If you have one of these cameras, say Y here | ||
659 | otherwise say N. | ||
660 | This driver is also available as a module (w9966). | ||
661 | 678 | ||
662 | Check out <file:Documentation/video4linux/w9966.txt> for more | 679 | # |
663 | information. | 680 | # PCI drivers configuration |
681 | # | ||
664 | 682 | ||
665 | source "drivers/media/video/cpia2/Kconfig" | 683 | menuconfig V4L_PCI_DRIVERS |
684 | bool "V4L PCI(e) devices" | ||
685 | depends on PCI | ||
686 | default y | ||
687 | ---help--- | ||
688 | Say Y here to enable support for these PCI(e) drivers. | ||
666 | 689 | ||
667 | config VIDEO_VINO | 690 | if V4L_PCI_DRIVERS |
668 | tristate "SGI Vino Video For Linux (EXPERIMENTAL)" | ||
669 | depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L2 | ||
670 | select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO | ||
671 | help | ||
672 | Say Y here to build in support for the Vino video input system found | ||
673 | on SGI Indy machines. | ||
674 | 691 | ||
675 | source "drivers/media/video/zoran/Kconfig" | 692 | source "drivers/media/video/au0828/Kconfig" |
693 | |||
694 | source "drivers/media/video/bt8xx/Kconfig" | ||
695 | |||
696 | source "drivers/media/video/cx18/Kconfig" | ||
697 | |||
698 | source "drivers/media/video/cx23885/Kconfig" | ||
699 | |||
700 | source "drivers/media/video/cx25821/Kconfig" | ||
701 | |||
702 | source "drivers/media/video/cx88/Kconfig" | ||
703 | |||
704 | config VIDEO_HEXIUM_GEMINI | ||
705 | tristate "Hexium Gemini frame grabber" | ||
706 | depends on PCI && VIDEO_V4L2 && I2C | ||
707 | select VIDEO_SAA7146_VV | ||
708 | ---help--- | ||
709 | This is a video4linux driver for the Hexium Gemini frame | ||
710 | grabber card by Hexium. Please note that the Gemini Dual | ||
711 | card is *not* fully supported. | ||
712 | |||
713 | To compile this driver as a module, choose M here: the | ||
714 | module will be called hexium_gemini. | ||
715 | |||
716 | config VIDEO_HEXIUM_ORION | ||
717 | tristate "Hexium HV-PCI6 and Orion frame grabber" | ||
718 | depends on PCI && VIDEO_V4L2 && I2C | ||
719 | select VIDEO_SAA7146_VV | ||
720 | ---help--- | ||
721 | This is a video4linux driver for the Hexium HV-PCI6 and | ||
722 | Orion frame grabber cards by Hexium. | ||
723 | |||
724 | To compile this driver as a module, choose M here: the | ||
725 | module will be called hexium_orion. | ||
726 | |||
727 | source "drivers/media/video/ivtv/Kconfig" | ||
676 | 728 | ||
677 | config VIDEO_MEYE | 729 | config VIDEO_MEYE |
678 | tristate "Sony Vaio Picturebook Motion Eye Video For Linux" | 730 | tristate "Sony Vaio Picturebook Motion Eye Video For Linux" |
@@ -688,8 +740,6 @@ config VIDEO_MEYE | |||
688 | To compile this driver as a module, choose M here: the | 740 | To compile this driver as a module, choose M here: the |
689 | module will be called meye. | 741 | module will be called meye. |
690 | 742 | ||
691 | source "drivers/media/video/saa7134/Kconfig" | ||
692 | |||
693 | config VIDEO_MXB | 743 | config VIDEO_MXB |
694 | tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" | 744 | tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" |
695 | depends on PCI && VIDEO_V4L2 && I2C | 745 | depends on PCI && VIDEO_V4L2 && I2C |
@@ -706,28 +756,119 @@ config VIDEO_MXB | |||
706 | To compile this driver as a module, choose M here: the | 756 | To compile this driver as a module, choose M here: the |
707 | module will be called mxb. | 757 | module will be called mxb. |
708 | 758 | ||
709 | config VIDEO_HEXIUM_ORION | 759 | source "drivers/media/video/saa7134/Kconfig" |
710 | tristate "Hexium HV-PCI6 and Orion frame grabber" | 760 | |
711 | depends on PCI && VIDEO_V4L2 && I2C | 761 | source "drivers/media/video/saa7164/Kconfig" |
712 | select VIDEO_SAA7146_VV | 762 | |
763 | source "drivers/media/video/zoran/Kconfig" | ||
764 | |||
765 | endif # V4L_PCI_DRIVERS | ||
766 | |||
767 | # | ||
768 | # ISA & parallel port drivers configuration | ||
769 | # | ||
770 | |||
771 | menuconfig V4L_ISA_PARPORT_DRIVERS | ||
772 | bool "V4L ISA and parallel port devices" | ||
773 | depends on ISA || PARPORT | ||
774 | default n | ||
713 | ---help--- | 775 | ---help--- |
714 | This is a video4linux driver for the Hexium HV-PCI6 and | 776 | Say Y here to enable support for these ISA and parallel port drivers. |
715 | Orion frame grabber cards by Hexium. | 777 | |
778 | if V4L_ISA_PARPORT_DRIVERS | ||
779 | |||
780 | config VIDEO_BWQCAM | ||
781 | tristate "Quickcam BW Video For Linux" | ||
782 | depends on PARPORT && VIDEO_V4L2 | ||
783 | help | ||
784 | Say Y have if you the black and white version of the QuickCam | ||
785 | camera. See the next option for the color version. | ||
716 | 786 | ||
717 | To compile this driver as a module, choose M here: the | 787 | To compile this driver as a module, choose M here: the |
718 | module will be called hexium_orion. | 788 | module will be called bw-qcam. |
719 | 789 | ||
720 | config VIDEO_HEXIUM_GEMINI | 790 | config VIDEO_CQCAM |
721 | tristate "Hexium Gemini frame grabber" | 791 | tristate "QuickCam Colour Video For Linux" |
722 | depends on PCI && VIDEO_V4L2 && I2C | 792 | depends on PARPORT && VIDEO_V4L2 |
723 | select VIDEO_SAA7146_VV | 793 | help |
724 | ---help--- | 794 | This is the video4linux driver for the colour version of the |
725 | This is a video4linux driver for the Hexium Gemini frame | 795 | Connectix QuickCam. If you have one of these cameras, say Y here, |
726 | grabber card by Hexium. Please note that the Gemini Dual | 796 | otherwise say N. This driver does not work with the original |
727 | card is *not* fully supported. | 797 | monochrome QuickCam, QuickCam VC or QuickClip. It is also available |
798 | as a module (c-qcam). | ||
799 | Read <file:Documentation/video4linux/CQcam.txt> for more information. | ||
800 | |||
801 | config VIDEO_PMS | ||
802 | tristate "Mediavision Pro Movie Studio Video For Linux" | ||
803 | depends on ISA && VIDEO_V4L2 | ||
804 | help | ||
805 | Say Y if you have the ISA Mediavision Pro Movie Studio | ||
806 | capture card. | ||
728 | 807 | ||
729 | To compile this driver as a module, choose M here: the | 808 | To compile this driver as a module, choose M here: the |
730 | module will be called hexium_gemini. | 809 | module will be called pms. |
810 | |||
811 | config VIDEO_W9966 | ||
812 | tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux" | ||
813 | depends on PARPORT_1284 && PARPORT && VIDEO_V4L2 | ||
814 | help | ||
815 | Video4linux driver for Winbond's w9966 based Webcams. | ||
816 | Currently tested with the LifeView FlyCam Supra. | ||
817 | If you have one of these cameras, say Y here | ||
818 | otherwise say N. | ||
819 | This driver is also available as a module (w9966). | ||
820 | |||
821 | Check out <file:Documentation/video4linux/w9966.txt> for more | ||
822 | information. | ||
823 | |||
824 | endif # V4L_ISA_PARPORT_DRIVERS | ||
825 | |||
826 | menuconfig V4L_PLATFORM_DRIVERS | ||
827 | bool "V4L platform devices" | ||
828 | default n | ||
829 | ---help--- | ||
830 | Say Y here to enable support for platform-specific V4L drivers. | ||
831 | |||
832 | if V4L_PLATFORM_DRIVERS | ||
833 | |||
834 | source "drivers/media/video/marvell-ccic/Kconfig" | ||
835 | |||
836 | config VIDEO_VIA_CAMERA | ||
837 | tristate "VIAFB camera controller support" | ||
838 | depends on FB_VIA | ||
839 | select VIDEOBUF_DMA_SG | ||
840 | select VIDEO_OV7670 | ||
841 | help | ||
842 | Driver support for the integrated camera controller in VIA | ||
843 | Chrome9 chipsets. Currently only tested on OLPC xo-1.5 systems | ||
844 | with ov7670 sensors. | ||
845 | |||
846 | # | ||
847 | # Platform multimedia device configuration | ||
848 | # | ||
849 | |||
850 | source "drivers/media/video/davinci/Kconfig" | ||
851 | |||
852 | source "drivers/media/video/omap/Kconfig" | ||
853 | |||
854 | config VIDEO_SH_VOU | ||
855 | tristate "SuperH VOU video output driver" | ||
856 | depends on VIDEO_DEV && ARCH_SHMOBILE | ||
857 | select VIDEOBUF_DMA_CONTIG | ||
858 | help | ||
859 | Support for the Video Output Unit (VOU) on SuperH SoCs. | ||
860 | |||
861 | config VIDEO_VIU | ||
862 | tristate "Freescale VIU Video Driver" | ||
863 | depends on VIDEO_V4L2 && PPC_MPC512x | ||
864 | select VIDEOBUF_DMA_CONTIG | ||
865 | default y | ||
866 | ---help--- | ||
867 | Support for Freescale VIU video driver. This device captures | ||
868 | video data, or overlays video on DIU frame buffer. | ||
869 | |||
870 | Say Y here if you want to enable VIU device on MPC5121e Rev2+. | ||
871 | In doubt, say N. | ||
731 | 872 | ||
732 | config VIDEO_TIMBERDALE | 873 | config VIDEO_TIMBERDALE |
733 | tristate "Support for timberdale Video In/LogiWIN" | 874 | tristate "Support for timberdale Video In/LogiWIN" |
@@ -739,21 +880,13 @@ config VIDEO_TIMBERDALE | |||
739 | ---help--- | 880 | ---help--- |
740 | Add support for the Video In peripherial of the timberdale FPGA. | 881 | Add support for the Video In peripherial of the timberdale FPGA. |
741 | 882 | ||
742 | source "drivers/media/video/cx88/Kconfig" | 883 | config VIDEO_VINO |
743 | 884 | tristate "SGI Vino Video For Linux" | |
744 | source "drivers/media/video/cx23885/Kconfig" | 885 | depends on I2C && SGI_IP22 && VIDEO_V4L2 |
745 | 886 | select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO | |
746 | source "drivers/media/video/cx25821/Kconfig" | 887 | help |
747 | 888 | Say Y here to build in support for the Vino video input system found | |
748 | source "drivers/media/video/au0828/Kconfig" | 889 | on SGI Indy machines. |
749 | |||
750 | source "drivers/media/video/ivtv/Kconfig" | ||
751 | |||
752 | source "drivers/media/video/cx18/Kconfig" | ||
753 | |||
754 | source "drivers/media/video/saa7164/Kconfig" | ||
755 | |||
756 | source "drivers/media/video/marvell-ccic/Kconfig" | ||
757 | 890 | ||
758 | config VIDEO_M32R_AR | 891 | config VIDEO_M32R_AR |
759 | tristate "AR devices" | 892 | tristate "AR devices" |
@@ -774,16 +907,6 @@ config VIDEO_M32R_AR_M64278 | |||
774 | To compile this driver as a module, choose M here: the | 907 | To compile this driver as a module, choose M here: the |
775 | module will be called arv. | 908 | module will be called arv. |
776 | 909 | ||
777 | config VIDEO_VIA_CAMERA | ||
778 | tristate "VIAFB camera controller support" | ||
779 | depends on FB_VIA | ||
780 | select VIDEOBUF_DMA_SG | ||
781 | select VIDEO_OV7670 | ||
782 | help | ||
783 | Driver support for the integrated camera controller in VIA | ||
784 | Chrome9 chipsets. Currently only tested on OLPC xo-1.5 systems | ||
785 | with ov7670 sensors. | ||
786 | |||
787 | config VIDEO_OMAP3 | 910 | config VIDEO_OMAP3 |
788 | tristate "OMAP 3 Camera support (EXPERIMENTAL)" | 911 | tristate "OMAP 3 Camera support (EXPERIMENTAL)" |
789 | depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL | 912 | depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL |
@@ -1002,78 +1125,7 @@ config VIDEO_S5P_MIPI_CSIS | |||
1002 | 1125 | ||
1003 | source "drivers/media/video/s5p-tv/Kconfig" | 1126 | source "drivers/media/video/s5p-tv/Kconfig" |
1004 | 1127 | ||
1005 | # | 1128 | endif # V4L_PLATFORM_DRIVERS |
1006 | # USB Multimedia device configuration | ||
1007 | # | ||
1008 | |||
1009 | menuconfig V4L_USB_DRIVERS | ||
1010 | bool "V4L USB devices" | ||
1011 | depends on USB | ||
1012 | default y | ||
1013 | |||
1014 | if V4L_USB_DRIVERS && USB | ||
1015 | |||
1016 | source "drivers/media/video/uvc/Kconfig" | ||
1017 | |||
1018 | source "drivers/media/video/gspca/Kconfig" | ||
1019 | |||
1020 | source "drivers/media/video/pvrusb2/Kconfig" | ||
1021 | |||
1022 | source "drivers/media/video/hdpvr/Kconfig" | ||
1023 | |||
1024 | source "drivers/media/video/em28xx/Kconfig" | ||
1025 | |||
1026 | source "drivers/media/video/tlg2300/Kconfig" | ||
1027 | |||
1028 | source "drivers/media/video/cx231xx/Kconfig" | ||
1029 | |||
1030 | source "drivers/media/video/tm6000/Kconfig" | ||
1031 | |||
1032 | source "drivers/media/video/usbvision/Kconfig" | ||
1033 | |||
1034 | source "drivers/media/video/et61x251/Kconfig" | ||
1035 | |||
1036 | source "drivers/media/video/sn9c102/Kconfig" | ||
1037 | |||
1038 | source "drivers/media/video/pwc/Kconfig" | ||
1039 | |||
1040 | config USB_ZR364XX | ||
1041 | tristate "USB ZR364XX Camera support" | ||
1042 | depends on VIDEO_V4L2 | ||
1043 | select VIDEOBUF_GEN | ||
1044 | select VIDEOBUF_VMALLOC | ||
1045 | ---help--- | ||
1046 | Say Y here if you want to connect this type of camera to your | ||
1047 | computer's USB port. | ||
1048 | See <file:Documentation/video4linux/zr364xx.txt> for more info | ||
1049 | and list of supported cameras. | ||
1050 | |||
1051 | To compile this driver as a module, choose M here: the | ||
1052 | module will be called zr364xx. | ||
1053 | |||
1054 | config USB_STKWEBCAM | ||
1055 | tristate "USB Syntek DC1125 Camera support" | ||
1056 | depends on VIDEO_V4L2 && EXPERIMENTAL | ||
1057 | ---help--- | ||
1058 | Say Y here if you want to use this type of camera. | ||
1059 | Supported devices are typically found in some Asus laptops, | ||
1060 | with USB id 174f:a311 and 05e1:0501. Other Syntek cameras | ||
1061 | may be supported by the stk11xx driver, from which this is | ||
1062 | derived, see <http://sourceforge.net/projects/syntekdriver/> | ||
1063 | |||
1064 | To compile this driver as a module, choose M here: the | ||
1065 | module will be called stkwebcam. | ||
1066 | |||
1067 | config USB_S2255 | ||
1068 | tristate "USB Sensoray 2255 video capture device" | ||
1069 | depends on VIDEO_V4L2 | ||
1070 | select VIDEOBUF_VMALLOC | ||
1071 | default n | ||
1072 | help | ||
1073 | Say Y here if you want support for the Sensoray 2255 USB device. | ||
1074 | This driver can be compiled as a module, called s2255drv. | ||
1075 | |||
1076 | endif # V4L_USB_DRIVERS | ||
1077 | endif # VIDEO_CAPTURE_DRIVERS | 1129 | endif # VIDEO_CAPTURE_DRIVERS |
1078 | 1130 | ||
1079 | menuconfig V4L_MEM2MEM_DRIVERS | 1131 | menuconfig V4L_MEM2MEM_DRIVERS |
@@ -1098,6 +1150,23 @@ config VIDEO_MEM2MEM_TESTDEV | |||
1098 | This is a virtual test device for the memory-to-memory driver | 1150 | This is a virtual test device for the memory-to-memory driver |
1099 | framework. | 1151 | framework. |
1100 | 1152 | ||
1153 | config VIDEO_SAMSUNG_S5P_G2D | ||
1154 | tristate "Samsung S5P and EXYNOS4 G2D 2d graphics accelerator driver" | ||
1155 | depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P | ||
1156 | select VIDEOBUF2_DMA_CONTIG | ||
1157 | select V4L2_MEM2MEM_DEV | ||
1158 | default n | ||
1159 | ---help--- | ||
1160 | This is a v4l2 driver for Samsung S5P and EXYNOS4 G2D | ||
1161 | 2d graphics accelerator. | ||
1162 | |||
1163 | config VIDEO_SAMSUNG_S5P_JPEG | ||
1164 | tristate "Samsung S5P/Exynos4 JPEG codec driver (EXPERIMENTAL)" | ||
1165 | depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P && EXPERIMENTAL | ||
1166 | select VIDEOBUF2_DMA_CONTIG | ||
1167 | select V4L2_MEM2MEM_DEV | ||
1168 | ---help--- | ||
1169 | This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec | ||
1101 | 1170 | ||
1102 | config VIDEO_SAMSUNG_S5P_MFC | 1171 | config VIDEO_SAMSUNG_S5P_MFC |
1103 | tristate "Samsung S5P MFC 5.1 Video Codec" | 1172 | tristate "Samsung S5P MFC 5.1 Video Codec" |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 117f9c4b4cb9..354138804cda 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
@@ -74,6 +74,7 @@ obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o | |||
74 | obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/ | 74 | obj-$(CONFIG_VIDEO_M5MOLS) += m5mols/ |
75 | obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o | 75 | obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o |
76 | obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o | 76 | obj-$(CONFIG_VIDEO_ADP1653) += adp1653.o |
77 | obj-$(CONFIG_VIDEO_AS3645A) += as3645a.o | ||
77 | 78 | ||
78 | obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o | 79 | obj-$(CONFIG_SOC_CAMERA_IMX074) += imx074.o |
79 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o | 80 | obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o |
@@ -177,9 +178,12 @@ obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o | |||
177 | obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o | 178 | obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o |
178 | 179 | ||
179 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/ | 180 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/ |
181 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) += s5p-jpeg/ | ||
180 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc/ | 182 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC) += s5p-mfc/ |
181 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV) += s5p-tv/ | 183 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV) += s5p-tv/ |
182 | 184 | ||
185 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D) += s5p-g2d/ | ||
186 | |||
183 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ | 187 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ |
184 | 188 | ||
185 | obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o | 189 | obj-$(CONFIG_VIDEO_SH_VOU) += sh_vou.o |
diff --git a/drivers/media/video/adv7170.c b/drivers/media/video/adv7170.c index 23ba5c37c3e4..879f1d839760 100644 --- a/drivers/media/video/adv7170.c +++ b/drivers/media/video/adv7170.c | |||
@@ -64,6 +64,11 @@ static inline struct adv7170 *to_adv7170(struct v4l2_subdev *sd) | |||
64 | 64 | ||
65 | static char *inputs[] = { "pass_through", "play_back" }; | 65 | static char *inputs[] = { "pass_through", "play_back" }; |
66 | 66 | ||
67 | static enum v4l2_mbus_pixelcode adv7170_codes[] = { | ||
68 | V4L2_MBUS_FMT_UYVY8_2X8, | ||
69 | V4L2_MBUS_FMT_UYVY8_1X16, | ||
70 | }; | ||
71 | |||
67 | /* ----------------------------------------------------------------------- */ | 72 | /* ----------------------------------------------------------------------- */ |
68 | 73 | ||
69 | static inline int adv7170_write(struct v4l2_subdev *sd, u8 reg, u8 value) | 74 | static inline int adv7170_write(struct v4l2_subdev *sd, u8 reg, u8 value) |
@@ -258,6 +263,60 @@ static int adv7170_s_routing(struct v4l2_subdev *sd, | |||
258 | return 0; | 263 | return 0; |
259 | } | 264 | } |
260 | 265 | ||
266 | static int adv7170_enum_fmt(struct v4l2_subdev *sd, unsigned int index, | ||
267 | enum v4l2_mbus_pixelcode *code) | ||
268 | { | ||
269 | if (index >= ARRAY_SIZE(adv7170_codes)) | ||
270 | return -EINVAL; | ||
271 | |||
272 | *code = adv7170_codes[index]; | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int adv7170_g_fmt(struct v4l2_subdev *sd, | ||
277 | struct v4l2_mbus_framefmt *mf) | ||
278 | { | ||
279 | u8 val = adv7170_read(sd, 0x7); | ||
280 | |||
281 | if ((val & 0x40) == (1 << 6)) | ||
282 | mf->code = V4L2_MBUS_FMT_UYVY8_1X16; | ||
283 | else | ||
284 | mf->code = V4L2_MBUS_FMT_UYVY8_2X8; | ||
285 | |||
286 | mf->colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
287 | mf->width = 0; | ||
288 | mf->height = 0; | ||
289 | mf->field = V4L2_FIELD_ANY; | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | static int adv7170_s_fmt(struct v4l2_subdev *sd, | ||
295 | struct v4l2_mbus_framefmt *mf) | ||
296 | { | ||
297 | u8 val = adv7170_read(sd, 0x7); | ||
298 | int ret; | ||
299 | |||
300 | switch (mf->code) { | ||
301 | case V4L2_MBUS_FMT_UYVY8_2X8: | ||
302 | val &= ~0x40; | ||
303 | break; | ||
304 | |||
305 | case V4L2_MBUS_FMT_UYVY8_1X16: | ||
306 | val |= 0x40; | ||
307 | break; | ||
308 | |||
309 | default: | ||
310 | v4l2_dbg(1, debug, sd, | ||
311 | "illegal v4l2_mbus_framefmt code: %d\n", mf->code); | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | |||
315 | ret = adv7170_write(sd, 0x7, val); | ||
316 | |||
317 | return ret; | ||
318 | } | ||
319 | |||
261 | static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) | 320 | static int adv7170_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) |
262 | { | 321 | { |
263 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 322 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
@@ -274,6 +333,9 @@ static const struct v4l2_subdev_core_ops adv7170_core_ops = { | |||
274 | static const struct v4l2_subdev_video_ops adv7170_video_ops = { | 333 | static const struct v4l2_subdev_video_ops adv7170_video_ops = { |
275 | .s_std_output = adv7170_s_std_output, | 334 | .s_std_output = adv7170_s_std_output, |
276 | .s_routing = adv7170_s_routing, | 335 | .s_routing = adv7170_s_routing, |
336 | .s_mbus_fmt = adv7170_s_fmt, | ||
337 | .g_mbus_fmt = adv7170_g_fmt, | ||
338 | .enum_mbus_fmt = adv7170_enum_fmt, | ||
277 | }; | 339 | }; |
278 | 340 | ||
279 | static const struct v4l2_subdev_ops adv7170_ops = { | 341 | static const struct v4l2_subdev_ops adv7170_ops = { |
diff --git a/drivers/media/video/as3645a.c b/drivers/media/video/as3645a.c new file mode 100644 index 000000000000..ec859a580651 --- /dev/null +++ b/drivers/media/video/as3645a.c | |||
@@ -0,0 +1,904 @@ | |||
1 | /* | ||
2 | * drivers/media/video/as3645a.c - AS3645A and LM3555 flash controllers driver | ||
3 | * | ||
4 | * Copyright (C) 2008-2011 Nokia Corporation | ||
5 | * Copyright (c) 2011, Intel Corporation. | ||
6 | * | ||
7 | * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * 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., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | * TODO: | ||
24 | * - Check hardware FSTROBE control when sensor driver add support for this | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | #include <linux/delay.h> | ||
29 | #include <linux/i2c.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/mutex.h> | ||
32 | |||
33 | #include <media/as3645a.h> | ||
34 | #include <media/v4l2-ctrls.h> | ||
35 | #include <media/v4l2-device.h> | ||
36 | |||
37 | #define AS_TIMER_MS_TO_CODE(t) (((t) - 100) / 50) | ||
38 | #define AS_TIMER_CODE_TO_MS(c) (50 * (c) + 100) | ||
39 | |||
40 | /* Register definitions */ | ||
41 | |||
42 | /* Read-only Design info register: Reset state: xxxx 0001 */ | ||
43 | #define AS_DESIGN_INFO_REG 0x00 | ||
44 | #define AS_DESIGN_INFO_FACTORY(x) (((x) >> 4)) | ||
45 | #define AS_DESIGN_INFO_MODEL(x) ((x) & 0x0f) | ||
46 | |||
47 | /* Read-only Version control register: Reset state: 0000 0000 | ||
48 | * for first engineering samples | ||
49 | */ | ||
50 | #define AS_VERSION_CONTROL_REG 0x01 | ||
51 | #define AS_VERSION_CONTROL_RFU(x) (((x) >> 4)) | ||
52 | #define AS_VERSION_CONTROL_VERSION(x) ((x) & 0x0f) | ||
53 | |||
54 | /* Read / Write (Indicator and timer register): Reset state: 0000 1111 */ | ||
55 | #define AS_INDICATOR_AND_TIMER_REG 0x02 | ||
56 | #define AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT 0 | ||
57 | #define AS_INDICATOR_AND_TIMER_VREF_SHIFT 4 | ||
58 | #define AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT 6 | ||
59 | |||
60 | /* Read / Write (Current set register): Reset state: 0110 1001 */ | ||
61 | #define AS_CURRENT_SET_REG 0x03 | ||
62 | #define AS_CURRENT_ASSIST_LIGHT_SHIFT 0 | ||
63 | #define AS_CURRENT_LED_DET_ON (1 << 3) | ||
64 | #define AS_CURRENT_FLASH_CURRENT_SHIFT 4 | ||
65 | |||
66 | /* Read / Write (Control register): Reset state: 1011 0100 */ | ||
67 | #define AS_CONTROL_REG 0x04 | ||
68 | #define AS_CONTROL_MODE_SETTING_SHIFT 0 | ||
69 | #define AS_CONTROL_STROBE_ON (1 << 2) | ||
70 | #define AS_CONTROL_OUT_ON (1 << 3) | ||
71 | #define AS_CONTROL_EXT_TORCH_ON (1 << 4) | ||
72 | #define AS_CONTROL_STROBE_TYPE_EDGE (0 << 5) | ||
73 | #define AS_CONTROL_STROBE_TYPE_LEVEL (1 << 5) | ||
74 | #define AS_CONTROL_COIL_PEAK_SHIFT 6 | ||
75 | |||
76 | /* Read only (D3 is read / write) (Fault and info): Reset state: 0000 x000 */ | ||
77 | #define AS_FAULT_INFO_REG 0x05 | ||
78 | #define AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT (1 << 1) | ||
79 | #define AS_FAULT_INFO_INDICATOR_LED (1 << 2) | ||
80 | #define AS_FAULT_INFO_LED_AMOUNT (1 << 3) | ||
81 | #define AS_FAULT_INFO_TIMEOUT (1 << 4) | ||
82 | #define AS_FAULT_INFO_OVER_TEMPERATURE (1 << 5) | ||
83 | #define AS_FAULT_INFO_SHORT_CIRCUIT (1 << 6) | ||
84 | #define AS_FAULT_INFO_OVER_VOLTAGE (1 << 7) | ||
85 | |||
86 | /* Boost register */ | ||
87 | #define AS_BOOST_REG 0x0d | ||
88 | #define AS_BOOST_CURRENT_DISABLE (0 << 0) | ||
89 | #define AS_BOOST_CURRENT_ENABLE (1 << 0) | ||
90 | |||
91 | /* Password register is used to unlock boost register writing */ | ||
92 | #define AS_PASSWORD_REG 0x0f | ||
93 | #define AS_PASSWORD_UNLOCK_VALUE 0x55 | ||
94 | |||
95 | enum as_mode { | ||
96 | AS_MODE_EXT_TORCH = 0 << AS_CONTROL_MODE_SETTING_SHIFT, | ||
97 | AS_MODE_INDICATOR = 1 << AS_CONTROL_MODE_SETTING_SHIFT, | ||
98 | AS_MODE_ASSIST = 2 << AS_CONTROL_MODE_SETTING_SHIFT, | ||
99 | AS_MODE_FLASH = 3 << AS_CONTROL_MODE_SETTING_SHIFT, | ||
100 | }; | ||
101 | |||
102 | /* | ||
103 | * struct as3645a | ||
104 | * | ||
105 | * @subdev: V4L2 subdev | ||
106 | * @pdata: Flash platform data | ||
107 | * @power_lock: Protects power_count | ||
108 | * @power_count: Power reference count | ||
109 | * @led_mode: V4L2 flash LED mode | ||
110 | * @timeout: Flash timeout in microseconds | ||
111 | * @flash_current: Flash current (0=200mA ... 15=500mA). Maximum | ||
112 | * values are 400mA for two LEDs and 500mA for one LED. | ||
113 | * @assist_current: Torch/Assist light current (0=20mA, 1=40mA ... 7=160mA) | ||
114 | * @indicator_current: Indicator LED current (0=0mA, 1=2.5mA ... 4=10mA) | ||
115 | * @strobe_source: Flash strobe source (software or external) | ||
116 | */ | ||
117 | struct as3645a { | ||
118 | struct v4l2_subdev subdev; | ||
119 | const struct as3645a_platform_data *pdata; | ||
120 | |||
121 | struct mutex power_lock; | ||
122 | int power_count; | ||
123 | |||
124 | /* Controls */ | ||
125 | struct v4l2_ctrl_handler ctrls; | ||
126 | |||
127 | enum v4l2_flash_led_mode led_mode; | ||
128 | unsigned int timeout; | ||
129 | u8 flash_current; | ||
130 | u8 assist_current; | ||
131 | u8 indicator_current; | ||
132 | enum v4l2_flash_strobe_source strobe_source; | ||
133 | }; | ||
134 | |||
135 | #define to_as3645a(sd) container_of(sd, struct as3645a, subdev) | ||
136 | |||
137 | /* Return negative errno else zero on success */ | ||
138 | static int as3645a_write(struct as3645a *flash, u8 addr, u8 val) | ||
139 | { | ||
140 | struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev); | ||
141 | int rval; | ||
142 | |||
143 | rval = i2c_smbus_write_byte_data(client, addr, val); | ||
144 | |||
145 | dev_dbg(&client->dev, "Write Addr:%02X Val:%02X %s\n", addr, val, | ||
146 | rval < 0 ? "fail" : "ok"); | ||
147 | |||
148 | return rval; | ||
149 | } | ||
150 | |||
151 | /* Return negative errno else a data byte received from the device. */ | ||
152 | static int as3645a_read(struct as3645a *flash, u8 addr) | ||
153 | { | ||
154 | struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev); | ||
155 | int rval; | ||
156 | |||
157 | rval = i2c_smbus_read_byte_data(client, addr); | ||
158 | |||
159 | dev_dbg(&client->dev, "Read Addr:%02X Val:%02X %s\n", addr, rval, | ||
160 | rval < 0 ? "fail" : "ok"); | ||
161 | |||
162 | return rval; | ||
163 | } | ||
164 | |||
165 | /* ----------------------------------------------------------------------------- | ||
166 | * Hardware configuration and trigger | ||
167 | */ | ||
168 | |||
169 | /* | ||
170 | * as3645a_set_config - Set flash configuration registers | ||
171 | * @flash: The flash | ||
172 | * | ||
173 | * Configure the hardware with flash, assist and indicator currents, as well as | ||
174 | * flash timeout. | ||
175 | * | ||
176 | * Return 0 on success, or a negative error code if an I2C communication error | ||
177 | * occurred. | ||
178 | */ | ||
179 | static int as3645a_set_config(struct as3645a *flash) | ||
180 | { | ||
181 | int ret; | ||
182 | u8 val; | ||
183 | |||
184 | val = (flash->flash_current << AS_CURRENT_FLASH_CURRENT_SHIFT) | ||
185 | | (flash->assist_current << AS_CURRENT_ASSIST_LIGHT_SHIFT) | ||
186 | | AS_CURRENT_LED_DET_ON; | ||
187 | |||
188 | ret = as3645a_write(flash, AS_CURRENT_SET_REG, val); | ||
189 | if (ret < 0) | ||
190 | return ret; | ||
191 | |||
192 | val = AS_TIMER_MS_TO_CODE(flash->timeout / 1000) | ||
193 | << AS_INDICATOR_AND_TIMER_TIMEOUT_SHIFT; | ||
194 | |||
195 | val |= (flash->pdata->vref << AS_INDICATOR_AND_TIMER_VREF_SHIFT) | ||
196 | | ((flash->indicator_current ? flash->indicator_current - 1 : 0) | ||
197 | << AS_INDICATOR_AND_TIMER_INDICATOR_SHIFT); | ||
198 | |||
199 | return as3645a_write(flash, AS_INDICATOR_AND_TIMER_REG, val); | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * as3645a_set_control - Set flash control register | ||
204 | * @flash: The flash | ||
205 | * @mode: Desired output mode | ||
206 | * @on: Desired output state | ||
207 | * | ||
208 | * Configure the hardware with output mode and state. | ||
209 | * | ||
210 | * Return 0 on success, or a negative error code if an I2C communication error | ||
211 | * occurred. | ||
212 | */ | ||
213 | static int | ||
214 | as3645a_set_control(struct as3645a *flash, enum as_mode mode, bool on) | ||
215 | { | ||
216 | u8 reg; | ||
217 | |||
218 | /* Configure output parameters and operation mode. */ | ||
219 | reg = (flash->pdata->peak << AS_CONTROL_COIL_PEAK_SHIFT) | ||
220 | | (on ? AS_CONTROL_OUT_ON : 0) | ||
221 | | mode; | ||
222 | |||
223 | if (flash->led_mode == V4L2_FLASH_LED_MODE_FLASH && | ||
224 | flash->strobe_source == V4L2_FLASH_STROBE_SOURCE_EXTERNAL) { | ||
225 | reg |= AS_CONTROL_STROBE_TYPE_LEVEL | ||
226 | | AS_CONTROL_STROBE_ON; | ||
227 | } | ||
228 | |||
229 | return as3645a_write(flash, AS_CONTROL_REG, reg); | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | * as3645a_set_output - Configure output and operation mode | ||
234 | * @flash: Flash controller | ||
235 | * @strobe: Strobe the flash (only valid in flash mode) | ||
236 | * | ||
237 | * Turn the LEDs output on/off and set the operation mode based on the current | ||
238 | * parameters. | ||
239 | * | ||
240 | * The AS3645A can't control the indicator LED independently of the flash/torch | ||
241 | * LED. If the flash controller is in V4L2_FLASH_LED_MODE_NONE mode, set the | ||
242 | * chip to indicator mode. Otherwise set it to assist light (torch) or flash | ||
243 | * mode. | ||
244 | * | ||
245 | * In indicator and assist modes, turn the output on/off based on the indicator | ||
246 | * and torch currents. In software strobe flash mode, turn the output on/off | ||
247 | * based on the strobe parameter. | ||
248 | */ | ||
249 | static int as3645a_set_output(struct as3645a *flash, bool strobe) | ||
250 | { | ||
251 | enum as_mode mode; | ||
252 | bool on; | ||
253 | |||
254 | switch (flash->led_mode) { | ||
255 | case V4L2_FLASH_LED_MODE_NONE: | ||
256 | on = flash->indicator_current != 0; | ||
257 | mode = AS_MODE_INDICATOR; | ||
258 | break; | ||
259 | case V4L2_FLASH_LED_MODE_TORCH: | ||
260 | on = true; | ||
261 | mode = AS_MODE_ASSIST; | ||
262 | break; | ||
263 | case V4L2_FLASH_LED_MODE_FLASH: | ||
264 | on = strobe; | ||
265 | mode = AS_MODE_FLASH; | ||
266 | break; | ||
267 | default: | ||
268 | BUG(); | ||
269 | } | ||
270 | |||
271 | /* Configure output parameters and operation mode. */ | ||
272 | return as3645a_set_control(flash, mode, on); | ||
273 | } | ||
274 | |||
275 | /* ----------------------------------------------------------------------------- | ||
276 | * V4L2 controls | ||
277 | */ | ||
278 | |||
279 | static int as3645a_is_active(struct as3645a *flash) | ||
280 | { | ||
281 | int ret; | ||
282 | |||
283 | ret = as3645a_read(flash, AS_CONTROL_REG); | ||
284 | return ret < 0 ? ret : !!(ret & AS_CONTROL_OUT_ON); | ||
285 | } | ||
286 | |||
287 | static int as3645a_read_fault(struct as3645a *flash) | ||
288 | { | ||
289 | struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev); | ||
290 | int rval; | ||
291 | |||
292 | /* NOTE: reading register clear fault status */ | ||
293 | rval = as3645a_read(flash, AS_FAULT_INFO_REG); | ||
294 | if (rval < 0) | ||
295 | return rval; | ||
296 | |||
297 | if (rval & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT) | ||
298 | dev_dbg(&client->dev, "Inductor Peak limit fault\n"); | ||
299 | |||
300 | if (rval & AS_FAULT_INFO_INDICATOR_LED) | ||
301 | dev_dbg(&client->dev, "Indicator LED fault: " | ||
302 | "Short circuit or open loop\n"); | ||
303 | |||
304 | dev_dbg(&client->dev, "%u connected LEDs\n", | ||
305 | rval & AS_FAULT_INFO_LED_AMOUNT ? 2 : 1); | ||
306 | |||
307 | if (rval & AS_FAULT_INFO_TIMEOUT) | ||
308 | dev_dbg(&client->dev, "Timeout fault\n"); | ||
309 | |||
310 | if (rval & AS_FAULT_INFO_OVER_TEMPERATURE) | ||
311 | dev_dbg(&client->dev, "Over temperature fault\n"); | ||
312 | |||
313 | if (rval & AS_FAULT_INFO_SHORT_CIRCUIT) | ||
314 | dev_dbg(&client->dev, "Short circuit fault\n"); | ||
315 | |||
316 | if (rval & AS_FAULT_INFO_OVER_VOLTAGE) | ||
317 | dev_dbg(&client->dev, "Over voltage fault: " | ||
318 | "Indicates missing capacitor or open connection\n"); | ||
319 | |||
320 | return rval; | ||
321 | } | ||
322 | |||
323 | static int as3645a_get_ctrl(struct v4l2_ctrl *ctrl) | ||
324 | { | ||
325 | struct as3645a *flash = | ||
326 | container_of(ctrl->handler, struct as3645a, ctrls); | ||
327 | struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev); | ||
328 | int value; | ||
329 | |||
330 | switch (ctrl->id) { | ||
331 | case V4L2_CID_FLASH_FAULT: | ||
332 | value = as3645a_read_fault(flash); | ||
333 | if (value < 0) | ||
334 | return value; | ||
335 | |||
336 | ctrl->cur.val = 0; | ||
337 | if (value & AS_FAULT_INFO_SHORT_CIRCUIT) | ||
338 | ctrl->cur.val |= V4L2_FLASH_FAULT_SHORT_CIRCUIT; | ||
339 | if (value & AS_FAULT_INFO_OVER_TEMPERATURE) | ||
340 | ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_TEMPERATURE; | ||
341 | if (value & AS_FAULT_INFO_TIMEOUT) | ||
342 | ctrl->cur.val |= V4L2_FLASH_FAULT_TIMEOUT; | ||
343 | if (value & AS_FAULT_INFO_OVER_VOLTAGE) | ||
344 | ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_VOLTAGE; | ||
345 | if (value & AS_FAULT_INFO_INDUCTOR_PEAK_LIMIT) | ||
346 | ctrl->cur.val |= V4L2_FLASH_FAULT_OVER_CURRENT; | ||
347 | if (value & AS_FAULT_INFO_INDICATOR_LED) | ||
348 | ctrl->cur.val |= V4L2_FLASH_FAULT_INDICATOR; | ||
349 | break; | ||
350 | |||
351 | case V4L2_CID_FLASH_STROBE_STATUS: | ||
352 | if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) { | ||
353 | ctrl->cur.val = 0; | ||
354 | break; | ||
355 | } | ||
356 | |||
357 | value = as3645a_is_active(flash); | ||
358 | if (value < 0) | ||
359 | return value; | ||
360 | |||
361 | ctrl->cur.val = value; | ||
362 | break; | ||
363 | } | ||
364 | |||
365 | dev_dbg(&client->dev, "G_CTRL %08x:%d\n", ctrl->id, ctrl->cur.val); | ||
366 | |||
367 | return 0; | ||
368 | } | ||
369 | |||
370 | static int as3645a_set_ctrl(struct v4l2_ctrl *ctrl) | ||
371 | { | ||
372 | struct as3645a *flash = | ||
373 | container_of(ctrl->handler, struct as3645a, ctrls); | ||
374 | struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev); | ||
375 | int ret; | ||
376 | |||
377 | dev_dbg(&client->dev, "S_CTRL %08x:%d\n", ctrl->id, ctrl->val); | ||
378 | |||
379 | /* If a control that doesn't apply to the current mode is modified, | ||
380 | * we store the value and return immediately. The setting will be | ||
381 | * applied when the LED mode is changed. Otherwise we apply the setting | ||
382 | * immediately. | ||
383 | */ | ||
384 | |||
385 | switch (ctrl->id) { | ||
386 | case V4L2_CID_FLASH_LED_MODE: | ||
387 | if (flash->indicator_current) | ||
388 | return -EBUSY; | ||
389 | |||
390 | ret = as3645a_set_config(flash); | ||
391 | if (ret < 0) | ||
392 | return ret; | ||
393 | |||
394 | flash->led_mode = ctrl->val; | ||
395 | return as3645a_set_output(flash, false); | ||
396 | |||
397 | case V4L2_CID_FLASH_STROBE_SOURCE: | ||
398 | flash->strobe_source = ctrl->val; | ||
399 | |||
400 | /* Applies to flash mode only. */ | ||
401 | if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) | ||
402 | break; | ||
403 | |||
404 | return as3645a_set_output(flash, false); | ||
405 | |||
406 | case V4L2_CID_FLASH_STROBE: | ||
407 | if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) | ||
408 | return -EBUSY; | ||
409 | |||
410 | return as3645a_set_output(flash, true); | ||
411 | |||
412 | case V4L2_CID_FLASH_STROBE_STOP: | ||
413 | if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) | ||
414 | return -EBUSY; | ||
415 | |||
416 | return as3645a_set_output(flash, false); | ||
417 | |||
418 | case V4L2_CID_FLASH_TIMEOUT: | ||
419 | flash->timeout = ctrl->val; | ||
420 | |||
421 | /* Applies to flash mode only. */ | ||
422 | if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) | ||
423 | break; | ||
424 | |||
425 | return as3645a_set_config(flash); | ||
426 | |||
427 | case V4L2_CID_FLASH_INTENSITY: | ||
428 | flash->flash_current = (ctrl->val - AS3645A_FLASH_INTENSITY_MIN) | ||
429 | / AS3645A_FLASH_INTENSITY_STEP; | ||
430 | |||
431 | /* Applies to flash mode only. */ | ||
432 | if (flash->led_mode != V4L2_FLASH_LED_MODE_FLASH) | ||
433 | break; | ||
434 | |||
435 | return as3645a_set_config(flash); | ||
436 | |||
437 | case V4L2_CID_FLASH_TORCH_INTENSITY: | ||
438 | flash->assist_current = | ||
439 | (ctrl->val - AS3645A_TORCH_INTENSITY_MIN) | ||
440 | / AS3645A_TORCH_INTENSITY_STEP; | ||
441 | |||
442 | /* Applies to torch mode only. */ | ||
443 | if (flash->led_mode != V4L2_FLASH_LED_MODE_TORCH) | ||
444 | break; | ||
445 | |||
446 | return as3645a_set_config(flash); | ||
447 | |||
448 | case V4L2_CID_FLASH_INDICATOR_INTENSITY: | ||
449 | if (flash->led_mode != V4L2_FLASH_LED_MODE_NONE) | ||
450 | return -EBUSY; | ||
451 | |||
452 | flash->indicator_current = | ||
453 | (ctrl->val - AS3645A_INDICATOR_INTENSITY_MIN) | ||
454 | / AS3645A_INDICATOR_INTENSITY_STEP; | ||
455 | |||
456 | ret = as3645a_set_config(flash); | ||
457 | if (ret < 0) | ||
458 | return ret; | ||
459 | |||
460 | if ((ctrl->val == 0) == (ctrl->cur.val == 0)) | ||
461 | break; | ||
462 | |||
463 | return as3645a_set_output(flash, false); | ||
464 | } | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static const struct v4l2_ctrl_ops as3645a_ctrl_ops = { | ||
470 | .g_volatile_ctrl = as3645a_get_ctrl, | ||
471 | .s_ctrl = as3645a_set_ctrl, | ||
472 | }; | ||
473 | |||
474 | /* ----------------------------------------------------------------------------- | ||
475 | * V4L2 subdev core operations | ||
476 | */ | ||
477 | |||
478 | /* Put device into know state. */ | ||
479 | static int as3645a_setup(struct as3645a *flash) | ||
480 | { | ||
481 | struct i2c_client *client = v4l2_get_subdevdata(&flash->subdev); | ||
482 | int ret; | ||
483 | |||
484 | /* clear errors */ | ||
485 | ret = as3645a_read(flash, AS_FAULT_INFO_REG); | ||
486 | if (ret < 0) | ||
487 | return ret; | ||
488 | |||
489 | dev_dbg(&client->dev, "Fault info: %02x\n", ret); | ||
490 | |||
491 | ret = as3645a_set_config(flash); | ||
492 | if (ret < 0) | ||
493 | return ret; | ||
494 | |||
495 | ret = as3645a_set_output(flash, false); | ||
496 | if (ret < 0) | ||
497 | return ret; | ||
498 | |||
499 | /* read status */ | ||
500 | ret = as3645a_read_fault(flash); | ||
501 | if (ret < 0) | ||
502 | return ret; | ||
503 | |||
504 | dev_dbg(&client->dev, "AS_INDICATOR_AND_TIMER_REG: %02x\n", | ||
505 | as3645a_read(flash, AS_INDICATOR_AND_TIMER_REG)); | ||
506 | dev_dbg(&client->dev, "AS_CURRENT_SET_REG: %02x\n", | ||
507 | as3645a_read(flash, AS_CURRENT_SET_REG)); | ||
508 | dev_dbg(&client->dev, "AS_CONTROL_REG: %02x\n", | ||
509 | as3645a_read(flash, AS_CONTROL_REG)); | ||
510 | |||
511 | return ret & ~AS_FAULT_INFO_LED_AMOUNT ? -EIO : 0; | ||
512 | } | ||
513 | |||
514 | static int __as3645a_set_power(struct as3645a *flash, int on) | ||
515 | { | ||
516 | int ret; | ||
517 | |||
518 | if (!on) | ||
519 | as3645a_set_control(flash, AS_MODE_EXT_TORCH, false); | ||
520 | |||
521 | if (flash->pdata->set_power) { | ||
522 | ret = flash->pdata->set_power(&flash->subdev, on); | ||
523 | if (ret < 0) | ||
524 | return ret; | ||
525 | } | ||
526 | |||
527 | if (!on) | ||
528 | return 0; | ||
529 | |||
530 | ret = as3645a_setup(flash); | ||
531 | if (ret < 0) { | ||
532 | if (flash->pdata->set_power) | ||
533 | flash->pdata->set_power(&flash->subdev, 0); | ||
534 | } | ||
535 | |||
536 | return ret; | ||
537 | } | ||
538 | |||
539 | static int as3645a_set_power(struct v4l2_subdev *sd, int on) | ||
540 | { | ||
541 | struct as3645a *flash = to_as3645a(sd); | ||
542 | int ret = 0; | ||
543 | |||
544 | mutex_lock(&flash->power_lock); | ||
545 | |||
546 | if (flash->power_count == !on) { | ||
547 | ret = __as3645a_set_power(flash, !!on); | ||
548 | if (ret < 0) | ||
549 | goto done; | ||
550 | } | ||
551 | |||
552 | flash->power_count += on ? 1 : -1; | ||
553 | WARN_ON(flash->power_count < 0); | ||
554 | |||
555 | done: | ||
556 | mutex_unlock(&flash->power_lock); | ||
557 | return ret; | ||
558 | } | ||
559 | |||
560 | static int as3645a_registered(struct v4l2_subdev *sd) | ||
561 | { | ||
562 | struct as3645a *flash = to_as3645a(sd); | ||
563 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
564 | int rval, man, model, rfu, version; | ||
565 | const char *vendor; | ||
566 | |||
567 | /* Power up the flash driver and read manufacturer ID, model ID, RFU | ||
568 | * and version. | ||
569 | */ | ||
570 | rval = as3645a_set_power(&flash->subdev, 1); | ||
571 | if (rval < 0) | ||
572 | return rval; | ||
573 | |||
574 | rval = as3645a_read(flash, AS_DESIGN_INFO_REG); | ||
575 | if (rval < 0) | ||
576 | goto power_off; | ||
577 | |||
578 | man = AS_DESIGN_INFO_FACTORY(rval); | ||
579 | model = AS_DESIGN_INFO_MODEL(rval); | ||
580 | |||
581 | rval = as3645a_read(flash, AS_VERSION_CONTROL_REG); | ||
582 | if (rval < 0) | ||
583 | goto power_off; | ||
584 | |||
585 | rfu = AS_VERSION_CONTROL_RFU(rval); | ||
586 | version = AS_VERSION_CONTROL_VERSION(rval); | ||
587 | |||
588 | /* Verify the chip model and version. */ | ||
589 | if (model != 0x01 || rfu != 0x00) { | ||
590 | dev_err(&client->dev, "AS3645A not detected " | ||
591 | "(model %d rfu %d)\n", model, rfu); | ||
592 | rval = -ENODEV; | ||
593 | goto power_off; | ||
594 | } | ||
595 | |||
596 | switch (man) { | ||
597 | case 1: | ||
598 | vendor = "AMS, Austria Micro Systems"; | ||
599 | break; | ||
600 | case 2: | ||
601 | vendor = "ADI, Analog Devices Inc."; | ||
602 | break; | ||
603 | case 3: | ||
604 | vendor = "NSC, National Semiconductor"; | ||
605 | break; | ||
606 | case 4: | ||
607 | vendor = "NXP"; | ||
608 | break; | ||
609 | case 5: | ||
610 | vendor = "TI, Texas Instrument"; | ||
611 | break; | ||
612 | default: | ||
613 | vendor = "Unknown"; | ||
614 | } | ||
615 | |||
616 | dev_info(&client->dev, "Chip vendor: %s (%d) Version: %d\n", vendor, | ||
617 | man, version); | ||
618 | |||
619 | rval = as3645a_write(flash, AS_PASSWORD_REG, AS_PASSWORD_UNLOCK_VALUE); | ||
620 | if (rval < 0) | ||
621 | goto power_off; | ||
622 | |||
623 | rval = as3645a_write(flash, AS_BOOST_REG, AS_BOOST_CURRENT_DISABLE); | ||
624 | if (rval < 0) | ||
625 | goto power_off; | ||
626 | |||
627 | /* Setup default values. This makes sure that the chip is in a known | ||
628 | * state, in case the power rail can't be controlled. | ||
629 | */ | ||
630 | rval = as3645a_setup(flash); | ||
631 | |||
632 | power_off: | ||
633 | as3645a_set_power(&flash->subdev, 0); | ||
634 | |||
635 | return rval; | ||
636 | } | ||
637 | |||
638 | static int as3645a_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) | ||
639 | { | ||
640 | return as3645a_set_power(sd, 1); | ||
641 | } | ||
642 | |||
643 | static int as3645a_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) | ||
644 | { | ||
645 | return as3645a_set_power(sd, 0); | ||
646 | } | ||
647 | |||
648 | static const struct v4l2_subdev_core_ops as3645a_core_ops = { | ||
649 | .s_power = as3645a_set_power, | ||
650 | }; | ||
651 | |||
652 | static const struct v4l2_subdev_ops as3645a_ops = { | ||
653 | .core = &as3645a_core_ops, | ||
654 | }; | ||
655 | |||
656 | static const struct v4l2_subdev_internal_ops as3645a_internal_ops = { | ||
657 | .registered = as3645a_registered, | ||
658 | .open = as3645a_open, | ||
659 | .close = as3645a_close, | ||
660 | }; | ||
661 | |||
662 | /* ----------------------------------------------------------------------------- | ||
663 | * I2C driver | ||
664 | */ | ||
665 | #ifdef CONFIG_PM | ||
666 | |||
667 | static int as3645a_suspend(struct device *dev) | ||
668 | { | ||
669 | struct i2c_client *client = to_i2c_client(dev); | ||
670 | struct v4l2_subdev *subdev = i2c_get_clientdata(client); | ||
671 | struct as3645a *flash = to_as3645a(subdev); | ||
672 | int rval; | ||
673 | |||
674 | if (flash->power_count == 0) | ||
675 | return 0; | ||
676 | |||
677 | rval = __as3645a_set_power(flash, 0); | ||
678 | |||
679 | dev_dbg(&client->dev, "Suspend %s\n", rval < 0 ? "failed" : "ok"); | ||
680 | |||
681 | return rval; | ||
682 | } | ||
683 | |||
684 | static int as3645a_resume(struct device *dev) | ||
685 | { | ||
686 | struct i2c_client *client = to_i2c_client(dev); | ||
687 | struct v4l2_subdev *subdev = i2c_get_clientdata(client); | ||
688 | struct as3645a *flash = to_as3645a(subdev); | ||
689 | int rval; | ||
690 | |||
691 | if (flash->power_count == 0) | ||
692 | return 0; | ||
693 | |||
694 | rval = __as3645a_set_power(flash, 1); | ||
695 | |||
696 | dev_dbg(&client->dev, "Resume %s\n", rval < 0 ? "fail" : "ok"); | ||
697 | |||
698 | return rval; | ||
699 | } | ||
700 | |||
701 | #else | ||
702 | |||
703 | #define as3645a_suspend NULL | ||
704 | #define as3645a_resume NULL | ||
705 | |||
706 | #endif /* CONFIG_PM */ | ||
707 | |||
708 | /* | ||
709 | * as3645a_init_controls - Create controls | ||
710 | * @flash: The flash | ||
711 | * | ||
712 | * The number of LEDs reported in platform data is used to compute default | ||
713 | * limits. Parameters passed through platform data can override those limits. | ||
714 | */ | ||
715 | static int as3645a_init_controls(struct as3645a *flash) | ||
716 | { | ||
717 | const struct as3645a_platform_data *pdata = flash->pdata; | ||
718 | struct v4l2_ctrl *ctrl; | ||
719 | int maximum; | ||
720 | |||
721 | v4l2_ctrl_handler_init(&flash->ctrls, 10); | ||
722 | |||
723 | /* V4L2_CID_FLASH_LED_MODE */ | ||
724 | v4l2_ctrl_new_std_menu(&flash->ctrls, &as3645a_ctrl_ops, | ||
725 | V4L2_CID_FLASH_LED_MODE, 2, ~7, | ||
726 | V4L2_FLASH_LED_MODE_NONE); | ||
727 | |||
728 | /* V4L2_CID_FLASH_STROBE_SOURCE */ | ||
729 | v4l2_ctrl_new_std_menu(&flash->ctrls, &as3645a_ctrl_ops, | ||
730 | V4L2_CID_FLASH_STROBE_SOURCE, | ||
731 | pdata->ext_strobe ? 1 : 0, | ||
732 | pdata->ext_strobe ? ~3 : ~1, | ||
733 | V4L2_FLASH_STROBE_SOURCE_SOFTWARE); | ||
734 | |||
735 | flash->strobe_source = V4L2_FLASH_STROBE_SOURCE_SOFTWARE; | ||
736 | |||
737 | /* V4L2_CID_FLASH_STROBE */ | ||
738 | v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops, | ||
739 | V4L2_CID_FLASH_STROBE, 0, 0, 0, 0); | ||
740 | |||
741 | /* V4L2_CID_FLASH_STROBE_STOP */ | ||
742 | v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops, | ||
743 | V4L2_CID_FLASH_STROBE_STOP, 0, 0, 0, 0); | ||
744 | |||
745 | /* V4L2_CID_FLASH_STROBE_STATUS */ | ||
746 | ctrl = v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops, | ||
747 | V4L2_CID_FLASH_STROBE_STATUS, 0, 1, 1, 1); | ||
748 | if (ctrl != NULL) | ||
749 | ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; | ||
750 | |||
751 | /* V4L2_CID_FLASH_TIMEOUT */ | ||
752 | maximum = pdata->timeout_max; | ||
753 | |||
754 | v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops, | ||
755 | V4L2_CID_FLASH_TIMEOUT, AS3645A_FLASH_TIMEOUT_MIN, | ||
756 | maximum, AS3645A_FLASH_TIMEOUT_STEP, maximum); | ||
757 | |||
758 | flash->timeout = maximum; | ||
759 | |||
760 | /* V4L2_CID_FLASH_INTENSITY */ | ||
761 | maximum = pdata->flash_max_current; | ||
762 | |||
763 | v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops, | ||
764 | V4L2_CID_FLASH_INTENSITY, AS3645A_FLASH_INTENSITY_MIN, | ||
765 | maximum, AS3645A_FLASH_INTENSITY_STEP, maximum); | ||
766 | |||
767 | flash->flash_current = (maximum - AS3645A_FLASH_INTENSITY_MIN) | ||
768 | / AS3645A_FLASH_INTENSITY_STEP; | ||
769 | |||
770 | /* V4L2_CID_FLASH_TORCH_INTENSITY */ | ||
771 | maximum = pdata->torch_max_current; | ||
772 | |||
773 | v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops, | ||
774 | V4L2_CID_FLASH_TORCH_INTENSITY, | ||
775 | AS3645A_TORCH_INTENSITY_MIN, maximum, | ||
776 | AS3645A_TORCH_INTENSITY_STEP, | ||
777 | AS3645A_TORCH_INTENSITY_MIN); | ||
778 | |||
779 | flash->assist_current = 0; | ||
780 | |||
781 | /* V4L2_CID_FLASH_INDICATOR_INTENSITY */ | ||
782 | v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops, | ||
783 | V4L2_CID_FLASH_INDICATOR_INTENSITY, | ||
784 | AS3645A_INDICATOR_INTENSITY_MIN, | ||
785 | AS3645A_INDICATOR_INTENSITY_MAX, | ||
786 | AS3645A_INDICATOR_INTENSITY_STEP, | ||
787 | AS3645A_INDICATOR_INTENSITY_MIN); | ||
788 | |||
789 | flash->indicator_current = 0; | ||
790 | |||
791 | /* V4L2_CID_FLASH_FAULT */ | ||
792 | ctrl = v4l2_ctrl_new_std(&flash->ctrls, &as3645a_ctrl_ops, | ||
793 | V4L2_CID_FLASH_FAULT, 0, | ||
794 | V4L2_FLASH_FAULT_OVER_VOLTAGE | | ||
795 | V4L2_FLASH_FAULT_TIMEOUT | | ||
796 | V4L2_FLASH_FAULT_OVER_TEMPERATURE | | ||
797 | V4L2_FLASH_FAULT_SHORT_CIRCUIT, 0, 0); | ||
798 | if (ctrl != NULL) | ||
799 | ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; | ||
800 | |||
801 | flash->subdev.ctrl_handler = &flash->ctrls; | ||
802 | |||
803 | return flash->ctrls.error; | ||
804 | } | ||
805 | |||
806 | static int as3645a_probe(struct i2c_client *client, | ||
807 | const struct i2c_device_id *devid) | ||
808 | { | ||
809 | struct as3645a *flash; | ||
810 | int ret; | ||
811 | |||
812 | if (client->dev.platform_data == NULL) | ||
813 | return -ENODEV; | ||
814 | |||
815 | flash = kzalloc(sizeof(*flash), GFP_KERNEL); | ||
816 | if (flash == NULL) | ||
817 | return -ENOMEM; | ||
818 | |||
819 | flash->pdata = client->dev.platform_data; | ||
820 | |||
821 | v4l2_i2c_subdev_init(&flash->subdev, client, &as3645a_ops); | ||
822 | flash->subdev.internal_ops = &as3645a_internal_ops; | ||
823 | flash->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
824 | |||
825 | ret = as3645a_init_controls(flash); | ||
826 | if (ret < 0) | ||
827 | goto done; | ||
828 | |||
829 | ret = media_entity_init(&flash->subdev.entity, 0, NULL, 0); | ||
830 | if (ret < 0) | ||
831 | goto done; | ||
832 | |||
833 | flash->subdev.entity.type = MEDIA_ENT_T_V4L2_SUBDEV_FLASH; | ||
834 | |||
835 | mutex_init(&flash->power_lock); | ||
836 | |||
837 | flash->led_mode = V4L2_FLASH_LED_MODE_NONE; | ||
838 | |||
839 | done: | ||
840 | if (ret < 0) { | ||
841 | v4l2_ctrl_handler_free(&flash->ctrls); | ||
842 | kfree(flash); | ||
843 | } | ||
844 | |||
845 | return ret; | ||
846 | } | ||
847 | |||
848 | static int __exit as3645a_remove(struct i2c_client *client) | ||
849 | { | ||
850 | struct v4l2_subdev *subdev = i2c_get_clientdata(client); | ||
851 | struct as3645a *flash = to_as3645a(subdev); | ||
852 | |||
853 | v4l2_device_unregister_subdev(subdev); | ||
854 | v4l2_ctrl_handler_free(&flash->ctrls); | ||
855 | media_entity_cleanup(&flash->subdev.entity); | ||
856 | mutex_destroy(&flash->power_lock); | ||
857 | kfree(flash); | ||
858 | |||
859 | return 0; | ||
860 | } | ||
861 | |||
862 | static const struct i2c_device_id as3645a_id_table[] = { | ||
863 | { AS3645A_NAME, 0 }, | ||
864 | { }, | ||
865 | }; | ||
866 | MODULE_DEVICE_TABLE(i2c, as3645a_id_table); | ||
867 | |||
868 | static const struct dev_pm_ops as3645a_pm_ops = { | ||
869 | .suspend = as3645a_suspend, | ||
870 | .resume = as3645a_resume, | ||
871 | }; | ||
872 | |||
873 | static struct i2c_driver as3645a_i2c_driver = { | ||
874 | .driver = { | ||
875 | .name = AS3645A_NAME, | ||
876 | .pm = &as3645a_pm_ops, | ||
877 | }, | ||
878 | .probe = as3645a_probe, | ||
879 | .remove = __exit_p(as3645a_remove), | ||
880 | .id_table = as3645a_id_table, | ||
881 | }; | ||
882 | |||
883 | static int __init as3645a_init(void) | ||
884 | { | ||
885 | int rval; | ||
886 | |||
887 | rval = i2c_add_driver(&as3645a_i2c_driver); | ||
888 | if (rval) | ||
889 | pr_err("%s: Failed to register the driver\n", AS3645A_NAME); | ||
890 | |||
891 | return rval; | ||
892 | } | ||
893 | |||
894 | static void __exit as3645a_exit(void) | ||
895 | { | ||
896 | i2c_del_driver(&as3645a_i2c_driver); | ||
897 | } | ||
898 | |||
899 | module_init(as3645a_init); | ||
900 | module_exit(as3645a_exit); | ||
901 | |||
902 | MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); | ||
903 | MODULE_DESCRIPTION("LED flash driver for AS3645A, LM3555 and their clones"); | ||
904 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/atmel-isi.c b/drivers/media/video/atmel-isi.c index 8c775c59e120..9fe4519176a4 100644 --- a/drivers/media/video/atmel-isi.c +++ b/drivers/media/video/atmel-isi.c | |||
@@ -90,7 +90,10 @@ struct atmel_isi { | |||
90 | struct isi_dma_desc dma_desc[MAX_BUFFER_NUM]; | 90 | struct isi_dma_desc dma_desc[MAX_BUFFER_NUM]; |
91 | 91 | ||
92 | struct completion complete; | 92 | struct completion complete; |
93 | /* ISI peripherial clock */ | ||
93 | struct clk *pclk; | 94 | struct clk *pclk; |
95 | /* ISI_MCK, feed to camera sensor to generate pixel clock */ | ||
96 | struct clk *mck; | ||
94 | unsigned int irq; | 97 | unsigned int irq; |
95 | 98 | ||
96 | struct isi_platform_data *pdata; | 99 | struct isi_platform_data *pdata; |
@@ -766,6 +769,12 @@ static int isi_camera_add_device(struct soc_camera_device *icd) | |||
766 | if (ret) | 769 | if (ret) |
767 | return ret; | 770 | return ret; |
768 | 771 | ||
772 | ret = clk_enable(isi->mck); | ||
773 | if (ret) { | ||
774 | clk_disable(isi->pclk); | ||
775 | return ret; | ||
776 | } | ||
777 | |||
769 | isi->icd = icd; | 778 | isi->icd = icd; |
770 | dev_dbg(icd->parent, "Atmel ISI Camera driver attached to camera %d\n", | 779 | dev_dbg(icd->parent, "Atmel ISI Camera driver attached to camera %d\n", |
771 | icd->devnum); | 780 | icd->devnum); |
@@ -779,6 +788,7 @@ static void isi_camera_remove_device(struct soc_camera_device *icd) | |||
779 | 788 | ||
780 | BUG_ON(icd != isi->icd); | 789 | BUG_ON(icd != isi->icd); |
781 | 790 | ||
791 | clk_disable(isi->mck); | ||
782 | clk_disable(isi->pclk); | 792 | clk_disable(isi->pclk); |
783 | isi->icd = NULL; | 793 | isi->icd = NULL; |
784 | 794 | ||
@@ -803,7 +813,7 @@ static int isi_camera_querycap(struct soc_camera_host *ici, | |||
803 | return 0; | 813 | return 0; |
804 | } | 814 | } |
805 | 815 | ||
806 | static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt) | 816 | static int isi_camera_set_bus_param(struct soc_camera_device *icd) |
807 | { | 817 | { |
808 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 818 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
809 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 819 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
@@ -874,7 +884,7 @@ static int isi_camera_set_bus_param(struct soc_camera_device *icd, u32 pixfmt) | |||
874 | 884 | ||
875 | if (isi->pdata->has_emb_sync) | 885 | if (isi->pdata->has_emb_sync) |
876 | cfg1 |= ISI_CFG1_EMB_SYNC; | 886 | cfg1 |= ISI_CFG1_EMB_SYNC; |
877 | if (isi->pdata->isi_full_mode) | 887 | if (isi->pdata->full_mode) |
878 | cfg1 |= ISI_CFG1_FULL_MODE; | 888 | cfg1 |= ISI_CFG1_FULL_MODE; |
879 | 889 | ||
880 | isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS); | 890 | isi_writel(isi, ISI_CTRL, ISI_CTRL_DIS); |
@@ -912,6 +922,7 @@ static int __devexit atmel_isi_remove(struct platform_device *pdev) | |||
912 | isi->fb_descriptors_phys); | 922 | isi->fb_descriptors_phys); |
913 | 923 | ||
914 | iounmap(isi->regs); | 924 | iounmap(isi->regs); |
925 | clk_put(isi->mck); | ||
915 | clk_put(isi->pclk); | 926 | clk_put(isi->pclk); |
916 | kfree(isi); | 927 | kfree(isi); |
917 | 928 | ||
@@ -930,7 +941,7 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev) | |||
930 | struct isi_platform_data *pdata; | 941 | struct isi_platform_data *pdata; |
931 | 942 | ||
932 | pdata = dev->platform_data; | 943 | pdata = dev->platform_data; |
933 | if (!pdata || !pdata->data_width_flags) { | 944 | if (!pdata || !pdata->data_width_flags || !pdata->mck_hz) { |
934 | dev_err(&pdev->dev, | 945 | dev_err(&pdev->dev, |
935 | "No config available for Atmel ISI\n"); | 946 | "No config available for Atmel ISI\n"); |
936 | return -EINVAL; | 947 | return -EINVAL; |
@@ -959,6 +970,19 @@ static int __devinit atmel_isi_probe(struct platform_device *pdev) | |||
959 | INIT_LIST_HEAD(&isi->video_buffer_list); | 970 | INIT_LIST_HEAD(&isi->video_buffer_list); |
960 | INIT_LIST_HEAD(&isi->dma_desc_head); | 971 | INIT_LIST_HEAD(&isi->dma_desc_head); |
961 | 972 | ||
973 | /* Get ISI_MCK, provided by programmable clock or external clock */ | ||
974 | isi->mck = clk_get(dev, "isi_mck"); | ||
975 | if (IS_ERR(isi->mck)) { | ||
976 | dev_err(dev, "Failed to get isi_mck\n"); | ||
977 | ret = PTR_ERR(isi->mck); | ||
978 | goto err_clk_get; | ||
979 | } | ||
980 | |||
981 | /* Set ISI_MCK's frequency, it should be faster than pixel clock */ | ||
982 | ret = clk_set_rate(isi->mck, pdata->mck_hz); | ||
983 | if (ret < 0) | ||
984 | goto err_set_mck_rate; | ||
985 | |||
962 | isi->p_fb_descriptors = dma_alloc_coherent(&pdev->dev, | 986 | isi->p_fb_descriptors = dma_alloc_coherent(&pdev->dev, |
963 | sizeof(struct fbd) * MAX_BUFFER_NUM, | 987 | sizeof(struct fbd) * MAX_BUFFER_NUM, |
964 | &isi->fb_descriptors_phys, | 988 | &isi->fb_descriptors_phys, |
@@ -1034,9 +1058,12 @@ err_alloc_ctx: | |||
1034 | isi->p_fb_descriptors, | 1058 | isi->p_fb_descriptors, |
1035 | isi->fb_descriptors_phys); | 1059 | isi->fb_descriptors_phys); |
1036 | err_alloc_descriptors: | 1060 | err_alloc_descriptors: |
1061 | err_set_mck_rate: | ||
1062 | clk_put(isi->mck); | ||
1063 | err_clk_get: | ||
1037 | kfree(isi); | 1064 | kfree(isi); |
1038 | err_alloc_isi: | 1065 | err_alloc_isi: |
1039 | clk_put(isi->pclk); | 1066 | clk_put(pclk); |
1040 | 1067 | ||
1041 | return ret; | 1068 | return ret; |
1042 | } | 1069 | } |
diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig index 0c3a5ba0e857..81ba9d9d1b52 100644 --- a/drivers/media/video/au0828/Kconfig +++ b/drivers/media/video/au0828/Kconfig | |||
@@ -2,6 +2,7 @@ | |||
2 | config VIDEO_AU0828 | 2 | config VIDEO_AU0828 |
3 | tristate "Auvitek AU0828 support" | 3 | tristate "Auvitek AU0828 support" |
4 | depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2 | 4 | depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2 |
5 | depends on DVB_CAPTURE_DRIVERS | ||
5 | select I2C_ALGOBIT | 6 | select I2C_ALGOBIT |
6 | select VIDEO_TVEEPROM | 7 | select VIDEO_TVEEPROM |
7 | select VIDEOBUF_VMALLOC | 8 | select VIDEOBUF_VMALLOC |
diff --git a/drivers/media/video/au0828/au0828-i2c.c b/drivers/media/video/au0828/au0828-i2c.c index cbdb65c34f21..05c299fa5d79 100644 --- a/drivers/media/video/au0828/au0828-i2c.c +++ b/drivers/media/video/au0828/au0828-i2c.c | |||
@@ -348,7 +348,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) | |||
348 | } | 348 | } |
349 | } | 349 | } |
350 | 350 | ||
351 | /* init + register i2c algo-bit adapter */ | 351 | /* init + register i2c adapter */ |
352 | int au0828_i2c_register(struct au0828_dev *dev) | 352 | int au0828_i2c_register(struct au0828_dev *dev) |
353 | { | 353 | { |
354 | dprintk(1, "%s()\n", __func__); | 354 | dprintk(1, "%s()\n", __func__); |
diff --git a/drivers/media/video/bt8xx/bt848.h b/drivers/media/video/bt8xx/bt848.h index 0bcd95303bb0..c37e6acffded 100644 --- a/drivers/media/video/bt8xx/bt848.h +++ b/drivers/media/video/bt8xx/bt848.h | |||
@@ -30,6 +30,10 @@ | |||
30 | #ifndef PCI_DEVICE_ID_BT849 | 30 | #ifndef PCI_DEVICE_ID_BT849 |
31 | #define PCI_DEVICE_ID_BT849 0x351 | 31 | #define PCI_DEVICE_ID_BT849 0x351 |
32 | #endif | 32 | #endif |
33 | #ifndef PCI_DEVICE_ID_FUSION879 | ||
34 | #define PCI_DEVICE_ID_FUSION879 0x36c | ||
35 | #endif | ||
36 | |||
33 | #ifndef PCI_DEVICE_ID_BT878 | 37 | #ifndef PCI_DEVICE_ID_BT878 |
34 | #define PCI_DEVICE_ID_BT878 0x36e | 38 | #define PCI_DEVICE_ID_BT878 0x36e |
35 | #endif | 39 | #endif |
@@ -37,7 +41,6 @@ | |||
37 | #define PCI_DEVICE_ID_BT879 0x36f | 41 | #define PCI_DEVICE_ID_BT879 0x36f |
38 | #endif | 42 | #endif |
39 | 43 | ||
40 | |||
41 | /* Brooktree 848 registers */ | 44 | /* Brooktree 848 registers */ |
42 | 45 | ||
43 | #define BT848_DSTATUS 0x000 | 46 | #define BT848_DSTATUS 0x000 |
diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 5939021d8eba..ff2933ab705f 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c | |||
@@ -80,6 +80,8 @@ static void phytec_muxsel(struct bttv *btv, unsigned int input); | |||
80 | static void gv800s_muxsel(struct bttv *btv, unsigned int input); | 80 | static void gv800s_muxsel(struct bttv *btv, unsigned int input); |
81 | static void gv800s_init(struct bttv *btv); | 81 | static void gv800s_init(struct bttv *btv); |
82 | 82 | ||
83 | static void td3116_muxsel(struct bttv *btv, unsigned int input); | ||
84 | |||
83 | static int terratec_active_radio_upgrade(struct bttv *btv); | 85 | static int terratec_active_radio_upgrade(struct bttv *btv); |
84 | static int tea5757_read(struct bttv *btv); | 86 | static int tea5757_read(struct bttv *btv); |
85 | static int tea5757_write(struct bttv *btv, int value); | 87 | static int tea5757_write(struct bttv *btv, int value); |
@@ -284,7 +286,8 @@ static struct CARD { | |||
284 | { 0x10b42636, BTTV_BOARD_HAUPPAUGE878, "STB ???" }, | 286 | { 0x10b42636, BTTV_BOARD_HAUPPAUGE878, "STB ???" }, |
285 | { 0x217d6606, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, | 287 | { 0x217d6606, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, |
286 | { 0xfff6f6ff, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, | 288 | { 0xfff6f6ff, BTTV_BOARD_WINFAST2000, "Leadtek WinFast TV 2000" }, |
287 | { 0x03116000, BTTV_BOARD_SENSORAY311, "Sensoray 311" }, | 289 | { 0x03116000, BTTV_BOARD_SENSORAY311_611, "Sensoray 311" }, |
290 | { 0x06116000, BTTV_BOARD_SENSORAY311_611, "Sensoray 611" }, | ||
288 | { 0x00790e11, BTTV_BOARD_WINDVR, "Canopus WinDVR PCI" }, | 291 | { 0x00790e11, BTTV_BOARD_WINDVR, "Canopus WinDVR PCI" }, |
289 | { 0xa0fca1a0, BTTV_BOARD_ZOLTRIX, "Face to Face Tvmax" }, | 292 | { 0xa0fca1a0, BTTV_BOARD_ZOLTRIX, "Face to Face Tvmax" }, |
290 | { 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" }, | 293 | { 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" }, |
@@ -341,6 +344,7 @@ static struct CARD { | |||
341 | { 0x15401835, BTTV_BOARD_PV183, "Provideo PV183-6" }, | 344 | { 0x15401835, BTTV_BOARD_PV183, "Provideo PV183-6" }, |
342 | { 0x15401836, BTTV_BOARD_PV183, "Provideo PV183-7" }, | 345 | { 0x15401836, BTTV_BOARD_PV183, "Provideo PV183-7" }, |
343 | { 0x15401837, BTTV_BOARD_PV183, "Provideo PV183-8" }, | 346 | { 0x15401837, BTTV_BOARD_PV183, "Provideo PV183-8" }, |
347 | { 0x3116f200, BTTV_BOARD_TVT_TD3116, "Tongwei Video Technology TD-3116" }, | ||
344 | 348 | ||
345 | { 0, -1, NULL } | 349 | { 0, -1, NULL } |
346 | }; | 350 | }; |
@@ -1526,10 +1530,10 @@ struct tvcard bttv_tvcards[] = { | |||
1526 | GPIO20,22,23: R30,R29,R28 | 1530 | GPIO20,22,23: R30,R29,R28 |
1527 | */ | 1531 | */ |
1528 | }, | 1532 | }, |
1529 | [BTTV_BOARD_SENSORAY311] = { | 1533 | [BTTV_BOARD_SENSORAY311_611] = { |
1530 | /* Clay Kunz <ckunz@mail.arc.nasa.gov> */ | 1534 | /* Clay Kunz <ckunz@mail.arc.nasa.gov> */ |
1531 | /* you must jumper JP5 for the card to work */ | 1535 | /* you must jumper JP5 for the 311 card (PC/104+) to work */ |
1532 | .name = "Sensoray 311", | 1536 | .name = "Sensoray 311/611", |
1533 | .video_inputs = 5, | 1537 | .video_inputs = 5, |
1534 | /* .audio_inputs= 0, */ | 1538 | /* .audio_inputs= 0, */ |
1535 | .svhs = 4, | 1539 | .svhs = 4, |
@@ -2879,6 +2883,16 @@ struct tvcard bttv_tvcards[] = { | |||
2879 | .tuner_type = TUNER_ABSENT, | 2883 | .tuner_type = TUNER_ABSENT, |
2880 | .tuner_addr = ADDR_UNSET, | 2884 | .tuner_addr = ADDR_UNSET, |
2881 | }, | 2885 | }, |
2886 | [BTTV_BOARD_TVT_TD3116] = { | ||
2887 | .name = "Tongwei Video Technology TD-3116", | ||
2888 | .video_inputs = 16, | ||
2889 | .gpiomask = 0xc00ff, | ||
2890 | .muxsel = MUXSEL(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2), | ||
2891 | .muxsel_hook = td3116_muxsel, | ||
2892 | .svhs = NO_SVHS, | ||
2893 | .pll = PLL_28, | ||
2894 | .tuner_type = TUNER_ABSENT, | ||
2895 | }, | ||
2882 | }; | 2896 | }; |
2883 | 2897 | ||
2884 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); | 2898 | static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); |
@@ -3228,6 +3242,42 @@ static void geovision_muxsel(struct bttv *btv, unsigned int input) | |||
3228 | gpio_bits(0xf, inmux); | 3242 | gpio_bits(0xf, inmux); |
3229 | } | 3243 | } |
3230 | 3244 | ||
3245 | /* | ||
3246 | * The TD3116 has 2 74HC4051 muxes wired to the MUX0 input of a bt878. | ||
3247 | * The first 74HC4051 has the lower 8 inputs, the second one the higher 8. | ||
3248 | * The muxes are controlled via a 74HC373 latch which is connected to | ||
3249 | * GPIOs 0-7. GPIO 18 is connected to the LE signal of the latch. | ||
3250 | * Q0 of the latch is connected to the Enable (~E) input of the first | ||
3251 | * 74HC4051. Q1 - Q3 are connected to S0 - S2 of the same 74HC4051. | ||
3252 | * Q4 - Q7 are connected to the second 74HC4051 in the same way. | ||
3253 | */ | ||
3254 | |||
3255 | static void td3116_latch_value(struct bttv *btv, u32 value) | ||
3256 | { | ||
3257 | gpio_bits((1<<18) | 0xff, value); | ||
3258 | gpio_bits((1<<18) | 0xff, (1<<18) | value); | ||
3259 | udelay(1); | ||
3260 | gpio_bits((1<<18) | 0xff, value); | ||
3261 | } | ||
3262 | |||
3263 | static void td3116_muxsel(struct bttv *btv, unsigned int input) | ||
3264 | { | ||
3265 | u32 value; | ||
3266 | u32 highbit; | ||
3267 | |||
3268 | highbit = (input & 0x8) >> 3 ; | ||
3269 | |||
3270 | /* Disable outputs and set value in the mux */ | ||
3271 | value = 0x11; /* Disable outputs */ | ||
3272 | value |= ((input & 0x7) << 1) << (4 * highbit); | ||
3273 | td3116_latch_value(btv, value); | ||
3274 | |||
3275 | /* Enable the correct output */ | ||
3276 | value &= ~0x11; | ||
3277 | value |= ((highbit ^ 0x1) << 4) | highbit; | ||
3278 | td3116_latch_value(btv, value); | ||
3279 | } | ||
3280 | |||
3231 | /* ----------------------------------------------------------------------- */ | 3281 | /* ----------------------------------------------------------------------- */ |
3232 | 3282 | ||
3233 | static void bttv_reset_audio(struct bttv *btv) | 3283 | static void bttv_reset_audio(struct bttv *btv) |
diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c index 3dd06607aec2..76c301f05095 100644 --- a/drivers/media/video/bt8xx/bttv-driver.c +++ b/drivers/media/video/bt8xx/bttv-driver.c | |||
@@ -4572,6 +4572,7 @@ static struct pci_device_id bttv_pci_tbl[] = { | |||
4572 | {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0}, | 4572 | {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT849), 0}, |
4573 | {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0}, | 4573 | {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT878), 0}, |
4574 | {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0}, | 4574 | {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_BT879), 0}, |
4575 | {PCI_VDEVICE(BROOKTREE, PCI_DEVICE_ID_FUSION879), 0}, | ||
4575 | {0,} | 4576 | {0,} |
4576 | }; | 4577 | }; |
4577 | 4578 | ||
diff --git a/drivers/media/video/bt8xx/bttv-i2c.c b/drivers/media/video/bt8xx/bttv-i2c.c index e3952af7e56e..580c8e682392 100644 --- a/drivers/media/video/bt8xx/bttv-i2c.c +++ b/drivers/media/video/bt8xx/bttv-i2c.c | |||
@@ -346,7 +346,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) | |||
346 | } | 346 | } |
347 | } | 347 | } |
348 | 348 | ||
349 | /* init + register i2c algo-bit adapter */ | 349 | /* init + register i2c adapter */ |
350 | int __devinit init_bttv_i2c(struct bttv *btv) | 350 | int __devinit init_bttv_i2c(struct bttv *btv) |
351 | { | 351 | { |
352 | strlcpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE); | 352 | strlcpy(btv->i2c_client.name, "bttv internal", I2C_NAME_SIZE); |
diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index c6333595c6b9..c5171619ac79 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h | |||
@@ -96,7 +96,7 @@ | |||
96 | #define BTTV_BOARD_PV_BT878P_PLUS 0x46 | 96 | #define BTTV_BOARD_PV_BT878P_PLUS 0x46 |
97 | #define BTTV_BOARD_FLYVIDEO98EZ 0x47 | 97 | #define BTTV_BOARD_FLYVIDEO98EZ 0x47 |
98 | #define BTTV_BOARD_PV_BT878P_9B 0x48 | 98 | #define BTTV_BOARD_PV_BT878P_9B 0x48 |
99 | #define BTTV_BOARD_SENSORAY311 0x49 | 99 | #define BTTV_BOARD_SENSORAY311_611 0x49 |
100 | #define BTTV_BOARD_RV605 0x4a | 100 | #define BTTV_BOARD_RV605 0x4a |
101 | #define BTTV_BOARD_POWERCLR_MTV878 0x4b | 101 | #define BTTV_BOARD_POWERCLR_MTV878 0x4b |
102 | #define BTTV_BOARD_WINDVR 0x4c | 102 | #define BTTV_BOARD_WINDVR 0x4c |
@@ -183,6 +183,7 @@ | |||
183 | #define BTTV_BOARD_GEOVISION_GV800S 0x9d | 183 | #define BTTV_BOARD_GEOVISION_GV800S 0x9d |
184 | #define BTTV_BOARD_GEOVISION_GV800S_SL 0x9e | 184 | #define BTTV_BOARD_GEOVISION_GV800S_SL 0x9e |
185 | #define BTTV_BOARD_PV183 0x9f | 185 | #define BTTV_BOARD_PV183 0x9f |
186 | #define BTTV_BOARD_TVT_TD3116 0xa0 | ||
186 | 187 | ||
187 | 188 | ||
188 | /* more card-specific defines */ | 189 | /* more card-specific defines */ |
diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 040aaa87579d..51609d5c88ce 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c | |||
@@ -232,7 +232,7 @@ static struct i2c_algo_bit_data cx18_i2c_algo_template = { | |||
232 | .timeout = CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */ | 232 | .timeout = CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */ |
233 | }; | 233 | }; |
234 | 234 | ||
235 | /* init + register i2c algo-bit adapter */ | 235 | /* init + register i2c adapter */ |
236 | int init_cx18_i2c(struct cx18 *cx) | 236 | int init_cx18_i2c(struct cx18 *cx) |
237 | { | 237 | { |
238 | int i, err; | 238 | int i, err; |
diff --git a/drivers/media/video/cx18/cx18-i2c.h b/drivers/media/video/cx18/cx18-i2c.h index bdfd1921e300..1180fdc8d983 100644 --- a/drivers/media/video/cx18/cx18-i2c.h +++ b/drivers/media/video/cx18/cx18-i2c.h | |||
@@ -24,6 +24,6 @@ | |||
24 | int cx18_i2c_register(struct cx18 *cx, unsigned idx); | 24 | int cx18_i2c_register(struct cx18 *cx, unsigned idx); |
25 | struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw); | 25 | struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw); |
26 | 26 | ||
27 | /* init + register i2c algo-bit adapter */ | 27 | /* init + register i2c adapter */ |
28 | int init_cx18_i2c(struct cx18 *cx); | 28 | int init_cx18_i2c(struct cx18 *cx); |
29 | void exit_cx18_i2c(struct cx18 *cx); | 29 | void exit_cx18_i2c(struct cx18 *cx); |
diff --git a/drivers/media/video/cx231xx/Kconfig b/drivers/media/video/cx231xx/Kconfig index ae85a7a7bd73..446f692aabb7 100644 --- a/drivers/media/video/cx231xx/Kconfig +++ b/drivers/media/video/cx231xx/Kconfig | |||
@@ -40,10 +40,10 @@ config VIDEO_CX231XX_ALSA | |||
40 | 40 | ||
41 | config VIDEO_CX231XX_DVB | 41 | config VIDEO_CX231XX_DVB |
42 | tristate "DVB/ATSC Support for Cx231xx based TV cards" | 42 | tristate "DVB/ATSC Support for Cx231xx based TV cards" |
43 | depends on VIDEO_CX231XX && DVB_CORE | 43 | depends on VIDEO_CX231XX && DVB_CORE && DVB_CAPTURE_DRIVERS |
44 | select VIDEOBUF_DVB | 44 | select VIDEOBUF_DVB |
45 | select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMISE | 45 | select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE |
46 | select MEDIA_TUNER_NXP18271 if !DVB_FE_CUSTOMISE | 46 | select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE |
47 | select DVB_MB86A20S if !DVB_FE_CUSTOMISE | 47 | select DVB_MB86A20S if !DVB_FE_CUSTOMISE |
48 | 48 | ||
49 | ---help--- | 49 | ---help--- |
diff --git a/drivers/media/video/cx231xx/cx231xx-audio.c b/drivers/media/video/cx231xx/cx231xx-audio.c index 30d13c15739a..a2c2b7d343ec 100644 --- a/drivers/media/video/cx231xx/cx231xx-audio.c +++ b/drivers/media/video/cx231xx/cx231xx-audio.c | |||
@@ -111,6 +111,9 @@ static void cx231xx_audio_isocirq(struct urb *urb) | |||
111 | struct snd_pcm_substream *substream; | 111 | struct snd_pcm_substream *substream; |
112 | struct snd_pcm_runtime *runtime; | 112 | struct snd_pcm_runtime *runtime; |
113 | 113 | ||
114 | if (dev->state & DEV_DISCONNECTED) | ||
115 | return; | ||
116 | |||
114 | switch (urb->status) { | 117 | switch (urb->status) { |
115 | case 0: /* success */ | 118 | case 0: /* success */ |
116 | case -ETIMEDOUT: /* NAK */ | 119 | case -ETIMEDOUT: /* NAK */ |
@@ -196,6 +199,9 @@ static void cx231xx_audio_bulkirq(struct urb *urb) | |||
196 | struct snd_pcm_substream *substream; | 199 | struct snd_pcm_substream *substream; |
197 | struct snd_pcm_runtime *runtime; | 200 | struct snd_pcm_runtime *runtime; |
198 | 201 | ||
202 | if (dev->state & DEV_DISCONNECTED) | ||
203 | return; | ||
204 | |||
199 | switch (urb->status) { | 205 | switch (urb->status) { |
200 | case 0: /* success */ | 206 | case 0: /* success */ |
201 | case -ETIMEDOUT: /* NAK */ | 207 | case -ETIMEDOUT: /* NAK */ |
@@ -273,6 +279,9 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) | |||
273 | 279 | ||
274 | cx231xx_info("%s: Starting ISO AUDIO transfers\n", __func__); | 280 | cx231xx_info("%s: Starting ISO AUDIO transfers\n", __func__); |
275 | 281 | ||
282 | if (dev->state & DEV_DISCONNECTED) | ||
283 | return -ENODEV; | ||
284 | |||
276 | sb_size = CX231XX_ISO_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; | 285 | sb_size = CX231XX_ISO_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; |
277 | 286 | ||
278 | for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { | 287 | for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { |
@@ -298,7 +307,7 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) | |||
298 | urb->context = dev; | 307 | urb->context = dev; |
299 | urb->pipe = usb_rcvisocpipe(dev->udev, | 308 | urb->pipe = usb_rcvisocpipe(dev->udev, |
300 | dev->adev.end_point_addr); | 309 | dev->adev.end_point_addr); |
301 | urb->transfer_flags = URB_ISO_ASAP; | 310 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; |
302 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; | 311 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; |
303 | urb->interval = 1; | 312 | urb->interval = 1; |
304 | urb->complete = cx231xx_audio_isocirq; | 313 | urb->complete = cx231xx_audio_isocirq; |
@@ -331,6 +340,9 @@ static int cx231xx_init_audio_bulk(struct cx231xx *dev) | |||
331 | 340 | ||
332 | cx231xx_info("%s: Starting BULK AUDIO transfers\n", __func__); | 341 | cx231xx_info("%s: Starting BULK AUDIO transfers\n", __func__); |
333 | 342 | ||
343 | if (dev->state & DEV_DISCONNECTED) | ||
344 | return -ENODEV; | ||
345 | |||
334 | sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; | 346 | sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; |
335 | 347 | ||
336 | for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { | 348 | for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { |
@@ -356,7 +368,7 @@ static int cx231xx_init_audio_bulk(struct cx231xx *dev) | |||
356 | urb->context = dev; | 368 | urb->context = dev; |
357 | urb->pipe = usb_rcvbulkpipe(dev->udev, | 369 | urb->pipe = usb_rcvbulkpipe(dev->udev, |
358 | dev->adev.end_point_addr); | 370 | dev->adev.end_point_addr); |
359 | urb->transfer_flags = 0; | 371 | urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; |
360 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; | 372 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; |
361 | urb->complete = cx231xx_audio_bulkirq; | 373 | urb->complete = cx231xx_audio_bulkirq; |
362 | urb->transfer_buffer_length = sb_size; | 374 | urb->transfer_buffer_length = sb_size; |
@@ -432,6 +444,11 @@ static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream) | |||
432 | return -ENODEV; | 444 | return -ENODEV; |
433 | } | 445 | } |
434 | 446 | ||
447 | if (dev->state & DEV_DISCONNECTED) { | ||
448 | cx231xx_errdev("Can't open. the device was removed.\n"); | ||
449 | return -ENODEV; | ||
450 | } | ||
451 | |||
435 | /* Sets volume, mute, etc */ | 452 | /* Sets volume, mute, etc */ |
436 | dev->mute = 0; | 453 | dev->mute = 0; |
437 | 454 | ||
@@ -571,6 +588,9 @@ static int snd_cx231xx_capture_trigger(struct snd_pcm_substream *substream, | |||
571 | struct cx231xx *dev = snd_pcm_substream_chip(substream); | 588 | struct cx231xx *dev = snd_pcm_substream_chip(substream); |
572 | int retval; | 589 | int retval; |
573 | 590 | ||
591 | if (dev->state & DEV_DISCONNECTED) | ||
592 | return -ENODEV; | ||
593 | |||
574 | spin_lock(&dev->adev.slock); | 594 | spin_lock(&dev->adev.slock); |
575 | switch (cmd) { | 595 | switch (cmd) { |
576 | case SNDRV_PCM_TRIGGER_START: | 596 | case SNDRV_PCM_TRIGGER_START: |
diff --git a/drivers/media/video/cx231xx/cx231xx-cards.c b/drivers/media/video/cx231xx/cx231xx-cards.c index 60b021e79864..919ed77b32f2 100644 --- a/drivers/media/video/cx231xx/cx231xx-cards.c +++ b/drivers/media/video/cx231xx/cx231xx-cards.c | |||
@@ -843,25 +843,34 @@ void cx231xx_release_resources(struct cx231xx *dev) | |||
843 | 843 | ||
844 | cx231xx_remove_from_devlist(dev); | 844 | cx231xx_remove_from_devlist(dev); |
845 | 845 | ||
846 | cx231xx_ir_exit(dev); | ||
847 | |||
846 | /* Release I2C buses */ | 848 | /* Release I2C buses */ |
847 | cx231xx_dev_uninit(dev); | 849 | cx231xx_dev_uninit(dev); |
848 | 850 | ||
849 | cx231xx_ir_exit(dev); | 851 | /* delete v4l2 device */ |
852 | v4l2_device_unregister(&dev->v4l2_dev); | ||
850 | 853 | ||
851 | usb_put_dev(dev->udev); | 854 | usb_put_dev(dev->udev); |
852 | 855 | ||
853 | /* Mark device as unused */ | 856 | /* Mark device as unused */ |
854 | cx231xx_devused &= ~(1 << dev->devno); | 857 | clear_bit(dev->devno, &cx231xx_devused); |
858 | |||
859 | kfree(dev->video_mode.alt_max_pkt_size); | ||
860 | kfree(dev->vbi_mode.alt_max_pkt_size); | ||
861 | kfree(dev->sliced_cc_mode.alt_max_pkt_size); | ||
862 | kfree(dev->ts1_mode.alt_max_pkt_size); | ||
863 | kfree(dev); | ||
864 | dev = NULL; | ||
855 | } | 865 | } |
856 | 866 | ||
857 | /* | 867 | /* |
858 | * cx231xx_init_dev() | 868 | * cx231xx_init_dev() |
859 | * allocates and inits the device structs, registers i2c bus and v4l device | 869 | * allocates and inits the device structs, registers i2c bus and v4l device |
860 | */ | 870 | */ |
861 | static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, | 871 | static int cx231xx_init_dev(struct cx231xx *dev, struct usb_device *udev, |
862 | int minor) | 872 | int minor) |
863 | { | 873 | { |
864 | struct cx231xx *dev = *devhandle; | ||
865 | int retval = -ENOMEM; | 874 | int retval = -ENOMEM; |
866 | int errCode; | 875 | int errCode; |
867 | unsigned int maxh, maxw; | 876 | unsigned int maxh, maxw; |
@@ -1016,7 +1025,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1016 | int i, isoc_pipe = 0; | 1025 | int i, isoc_pipe = 0; |
1017 | char *speed; | 1026 | char *speed; |
1018 | char descr[255] = ""; | 1027 | char descr[255] = ""; |
1019 | struct usb_interface *lif = NULL; | ||
1020 | struct usb_interface_assoc_descriptor *assoc_desc; | 1028 | struct usb_interface_assoc_descriptor *assoc_desc; |
1021 | 1029 | ||
1022 | udev = usb_get_dev(interface_to_usbdev(interface)); | 1030 | udev = usb_get_dev(interface_to_usbdev(interface)); |
@@ -1030,21 +1038,21 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1030 | return -ENODEV; | 1038 | return -ENODEV; |
1031 | 1039 | ||
1032 | /* Check to see next free device and mark as used */ | 1040 | /* Check to see next free device and mark as used */ |
1033 | nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS); | 1041 | do { |
1034 | cx231xx_devused |= 1 << nr; | 1042 | nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS); |
1035 | 1043 | if (nr >= CX231XX_MAXBOARDS) { | |
1036 | if (nr >= CX231XX_MAXBOARDS) { | 1044 | /* No free device slots */ |
1037 | cx231xx_err(DRIVER_NAME | 1045 | cx231xx_err(DRIVER_NAME ": Supports only %i devices.\n", |
1038 | ": Supports only %i cx231xx boards.\n", CX231XX_MAXBOARDS); | 1046 | CX231XX_MAXBOARDS); |
1039 | cx231xx_devused &= ~(1 << nr); | 1047 | return -ENOMEM; |
1040 | return -ENOMEM; | 1048 | } |
1041 | } | 1049 | } while (test_and_set_bit(nr, &cx231xx_devused)); |
1042 | 1050 | ||
1043 | /* allocate memory for our device state and initialize it */ | 1051 | /* allocate memory for our device state and initialize it */ |
1044 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | 1052 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); |
1045 | if (dev == NULL) { | 1053 | if (dev == NULL) { |
1046 | cx231xx_err(DRIVER_NAME ": out of memory!\n"); | 1054 | cx231xx_err(DRIVER_NAME ": out of memory!\n"); |
1047 | cx231xx_devused &= ~(1 << nr); | 1055 | clear_bit(dev->devno, &cx231xx_devused); |
1048 | return -ENOMEM; | 1056 | return -ENOMEM; |
1049 | } | 1057 | } |
1050 | 1058 | ||
@@ -1071,9 +1079,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1071 | 1079 | ||
1072 | /* init CIR module TBD */ | 1080 | /* init CIR module TBD */ |
1073 | 1081 | ||
1074 | /* store the current interface */ | ||
1075 | lif = interface; | ||
1076 | |||
1077 | /*mode_tv: digital=1 or analog=0*/ | 1082 | /*mode_tv: digital=1 or analog=0*/ |
1078 | dev->mode_tv = 0; | 1083 | dev->mode_tv = 0; |
1079 | 1084 | ||
@@ -1113,9 +1118,6 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1113 | le16_to_cpu(udev->descriptor.idProduct), | 1118 | le16_to_cpu(udev->descriptor.idProduct), |
1114 | dev->max_iad_interface_count); | 1119 | dev->max_iad_interface_count); |
1115 | 1120 | ||
1116 | /* store the interface 0 back */ | ||
1117 | lif = udev->actconfig->interface[0]; | ||
1118 | |||
1119 | /* increment interface count */ | 1121 | /* increment interface count */ |
1120 | dev->interface_count++; | 1122 | dev->interface_count++; |
1121 | 1123 | ||
@@ -1126,7 +1128,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1126 | if (assoc_desc->bFirstInterface != ifnum) { | 1128 | if (assoc_desc->bFirstInterface != ifnum) { |
1127 | cx231xx_err(DRIVER_NAME ": Not found " | 1129 | cx231xx_err(DRIVER_NAME ": Not found " |
1128 | "matching IAD interface\n"); | 1130 | "matching IAD interface\n"); |
1129 | cx231xx_devused &= ~(1 << nr); | 1131 | clear_bit(dev->devno, &cx231xx_devused); |
1130 | kfree(dev); | 1132 | kfree(dev); |
1131 | dev = NULL; | 1133 | dev = NULL; |
1132 | return -ENODEV; | 1134 | return -ENODEV; |
@@ -1135,7 +1137,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1135 | cx231xx_info("registering interface %d\n", ifnum); | 1137 | cx231xx_info("registering interface %d\n", ifnum); |
1136 | 1138 | ||
1137 | /* save our data pointer in this interface device */ | 1139 | /* save our data pointer in this interface device */ |
1138 | usb_set_intfdata(lif, dev); | 1140 | usb_set_intfdata(interface, dev); |
1139 | 1141 | ||
1140 | /* | 1142 | /* |
1141 | * AV device initialization - only done at the last interface | 1143 | * AV device initialization - only done at the last interface |
@@ -1145,19 +1147,19 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1145 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); | 1147 | retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev); |
1146 | if (retval) { | 1148 | if (retval) { |
1147 | cx231xx_errdev("v4l2_device_register failed\n"); | 1149 | cx231xx_errdev("v4l2_device_register failed\n"); |
1148 | cx231xx_devused &= ~(1 << nr); | 1150 | clear_bit(dev->devno, &cx231xx_devused); |
1149 | kfree(dev); | 1151 | kfree(dev); |
1150 | dev = NULL; | 1152 | dev = NULL; |
1151 | return -EIO; | 1153 | return -EIO; |
1152 | } | 1154 | } |
1153 | /* allocate device struct */ | 1155 | /* allocate device struct */ |
1154 | retval = cx231xx_init_dev(&dev, udev, nr); | 1156 | retval = cx231xx_init_dev(dev, udev, nr); |
1155 | if (retval) { | 1157 | if (retval) { |
1156 | cx231xx_devused &= ~(1 << dev->devno); | 1158 | clear_bit(dev->devno, &cx231xx_devused); |
1157 | v4l2_device_unregister(&dev->v4l2_dev); | 1159 | v4l2_device_unregister(&dev->v4l2_dev); |
1158 | kfree(dev); | 1160 | kfree(dev); |
1159 | dev = NULL; | 1161 | dev = NULL; |
1160 | usb_set_intfdata(lif, NULL); | 1162 | usb_set_intfdata(interface, NULL); |
1161 | 1163 | ||
1162 | return retval; | 1164 | return retval; |
1163 | } | 1165 | } |
@@ -1178,7 +1180,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1178 | 1180 | ||
1179 | if (dev->video_mode.alt_max_pkt_size == NULL) { | 1181 | if (dev->video_mode.alt_max_pkt_size == NULL) { |
1180 | cx231xx_errdev("out of memory!\n"); | 1182 | cx231xx_errdev("out of memory!\n"); |
1181 | cx231xx_devused &= ~(1 << nr); | 1183 | clear_bit(dev->devno, &cx231xx_devused); |
1182 | v4l2_device_unregister(&dev->v4l2_dev); | 1184 | v4l2_device_unregister(&dev->v4l2_dev); |
1183 | kfree(dev); | 1185 | kfree(dev); |
1184 | dev = NULL; | 1186 | dev = NULL; |
@@ -1212,7 +1214,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1212 | 1214 | ||
1213 | if (dev->vbi_mode.alt_max_pkt_size == NULL) { | 1215 | if (dev->vbi_mode.alt_max_pkt_size == NULL) { |
1214 | cx231xx_errdev("out of memory!\n"); | 1216 | cx231xx_errdev("out of memory!\n"); |
1215 | cx231xx_devused &= ~(1 << nr); | 1217 | clear_bit(dev->devno, &cx231xx_devused); |
1216 | v4l2_device_unregister(&dev->v4l2_dev); | 1218 | v4l2_device_unregister(&dev->v4l2_dev); |
1217 | kfree(dev); | 1219 | kfree(dev); |
1218 | dev = NULL; | 1220 | dev = NULL; |
@@ -1247,7 +1249,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1247 | 1249 | ||
1248 | if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { | 1250 | if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) { |
1249 | cx231xx_errdev("out of memory!\n"); | 1251 | cx231xx_errdev("out of memory!\n"); |
1250 | cx231xx_devused &= ~(1 << nr); | 1252 | clear_bit(dev->devno, &cx231xx_devused); |
1251 | v4l2_device_unregister(&dev->v4l2_dev); | 1253 | v4l2_device_unregister(&dev->v4l2_dev); |
1252 | kfree(dev); | 1254 | kfree(dev); |
1253 | dev = NULL; | 1255 | dev = NULL; |
@@ -1283,7 +1285,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, | |||
1283 | 1285 | ||
1284 | if (dev->ts1_mode.alt_max_pkt_size == NULL) { | 1286 | if (dev->ts1_mode.alt_max_pkt_size == NULL) { |
1285 | cx231xx_errdev("out of memory!\n"); | 1287 | cx231xx_errdev("out of memory!\n"); |
1286 | cx231xx_devused &= ~(1 << nr); | 1288 | clear_bit(dev->devno, &cx231xx_devused); |
1287 | v4l2_device_unregister(&dev->v4l2_dev); | 1289 | v4l2_device_unregister(&dev->v4l2_dev); |
1288 | kfree(dev); | 1290 | kfree(dev); |
1289 | dev = NULL; | 1291 | dev = NULL; |
@@ -1334,10 +1336,9 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) | |||
1334 | if (!dev->udev) | 1336 | if (!dev->udev) |
1335 | return; | 1337 | return; |
1336 | 1338 | ||
1337 | flush_request_modules(dev); | 1339 | dev->state |= DEV_DISCONNECTED; |
1338 | 1340 | ||
1339 | /* delete v4l2 device */ | 1341 | flush_request_modules(dev); |
1340 | v4l2_device_unregister(&dev->v4l2_dev); | ||
1341 | 1342 | ||
1342 | /* wait until all current v4l2 io is finished then deallocate | 1343 | /* wait until all current v4l2 io is finished then deallocate |
1343 | resources */ | 1344 | resources */ |
@@ -1351,31 +1352,24 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) | |||
1351 | "deallocation are deferred on close.\n", | 1352 | "deallocation are deferred on close.\n", |
1352 | video_device_node_name(dev->vdev)); | 1353 | video_device_node_name(dev->vdev)); |
1353 | 1354 | ||
1354 | dev->state |= DEV_MISCONFIGURED; | 1355 | /* Even having users, it is safe to remove the RC i2c driver */ |
1356 | cx231xx_ir_exit(dev); | ||
1357 | |||
1355 | if (dev->USE_ISO) | 1358 | if (dev->USE_ISO) |
1356 | cx231xx_uninit_isoc(dev); | 1359 | cx231xx_uninit_isoc(dev); |
1357 | else | 1360 | else |
1358 | cx231xx_uninit_bulk(dev); | 1361 | cx231xx_uninit_bulk(dev); |
1359 | dev->state |= DEV_DISCONNECTED; | ||
1360 | wake_up_interruptible(&dev->wait_frame); | 1362 | wake_up_interruptible(&dev->wait_frame); |
1361 | wake_up_interruptible(&dev->wait_stream); | 1363 | wake_up_interruptible(&dev->wait_stream); |
1362 | } else { | 1364 | } else { |
1363 | dev->state |= DEV_DISCONNECTED; | ||
1364 | cx231xx_release_resources(dev); | ||
1365 | } | 1365 | } |
1366 | 1366 | ||
1367 | cx231xx_close_extension(dev); | 1367 | cx231xx_close_extension(dev); |
1368 | 1368 | ||
1369 | mutex_unlock(&dev->lock); | 1369 | mutex_unlock(&dev->lock); |
1370 | 1370 | ||
1371 | if (!dev->users) { | 1371 | if (!dev->users) |
1372 | kfree(dev->video_mode.alt_max_pkt_size); | 1372 | cx231xx_release_resources(dev); |
1373 | kfree(dev->vbi_mode.alt_max_pkt_size); | ||
1374 | kfree(dev->sliced_cc_mode.alt_max_pkt_size); | ||
1375 | kfree(dev->ts1_mode.alt_max_pkt_size); | ||
1376 | kfree(dev); | ||
1377 | dev = NULL; | ||
1378 | } | ||
1379 | } | 1373 | } |
1380 | 1374 | ||
1381 | static struct usb_driver cx231xx_usb_driver = { | 1375 | static struct usb_driver cx231xx_usb_driver = { |
diff --git a/drivers/media/video/cx231xx/cx231xx-core.c b/drivers/media/video/cx231xx/cx231xx-core.c index d4457f9488ee..08dd930f882a 100644 --- a/drivers/media/video/cx231xx/cx231xx-core.c +++ b/drivers/media/video/cx231xx/cx231xx-core.c | |||
@@ -166,6 +166,9 @@ int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, | |||
166 | u8 _i2c_nostop = 0; | 166 | u8 _i2c_nostop = 0; |
167 | u8 _i2c_reserve = 0; | 167 | u8 _i2c_reserve = 0; |
168 | 168 | ||
169 | if (dev->state & DEV_DISCONNECTED) | ||
170 | return -ENODEV; | ||
171 | |||
169 | /* Get the I2C period, nostop and reserve parameters */ | 172 | /* Get the I2C period, nostop and reserve parameters */ |
170 | _i2c_period = i2c_bus->i2c_period; | 173 | _i2c_period = i2c_bus->i2c_period; |
171 | _i2c_nostop = i2c_bus->i2c_nostop; | 174 | _i2c_nostop = i2c_bus->i2c_nostop; |
@@ -1071,7 +1074,7 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, | |||
1071 | sb_size, cx231xx_isoc_irq_callback, dma_q, 1); | 1074 | sb_size, cx231xx_isoc_irq_callback, dma_q, 1); |
1072 | 1075 | ||
1073 | urb->number_of_packets = max_packets; | 1076 | urb->number_of_packets = max_packets; |
1074 | urb->transfer_flags = URB_ISO_ASAP; | 1077 | urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; |
1075 | 1078 | ||
1076 | k = 0; | 1079 | k = 0; |
1077 | for (j = 0; j < max_packets; j++) { | 1080 | for (j = 0; j < max_packets; j++) { |
@@ -1182,7 +1185,7 @@ int cx231xx_init_bulk(struct cx231xx *dev, int max_packets, | |||
1182 | return -ENOMEM; | 1185 | return -ENOMEM; |
1183 | } | 1186 | } |
1184 | dev->video_mode.bulk_ctl.urb[i] = urb; | 1187 | dev->video_mode.bulk_ctl.urb[i] = urb; |
1185 | urb->transfer_flags = 0; | 1188 | urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; |
1186 | 1189 | ||
1187 | dev->video_mode.bulk_ctl.transfer_buffer[i] = | 1190 | dev->video_mode.bulk_ctl.transfer_buffer[i] = |
1188 | usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL, | 1191 | usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL, |
diff --git a/drivers/media/video/cx231xx/cx231xx-dvb.c b/drivers/media/video/cx231xx/cx231xx-dvb.c index da9a4a0aab79..7c4e360ba9bc 100644 --- a/drivers/media/video/cx231xx/cx231xx-dvb.c +++ b/drivers/media/video/cx231xx/cx231xx-dvb.c | |||
@@ -196,7 +196,7 @@ static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb) | |||
196 | if (!dev) | 196 | if (!dev) |
197 | return 0; | 197 | return 0; |
198 | 198 | ||
199 | if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) | 199 | if (dev->state & DEV_DISCONNECTED) |
200 | return 0; | 200 | return 0; |
201 | 201 | ||
202 | if (urb->status < 0) { | 202 | if (urb->status < 0) { |
@@ -228,7 +228,7 @@ static inline int dvb_bulk_copy(struct cx231xx *dev, struct urb *urb) | |||
228 | if (!dev) | 228 | if (!dev) |
229 | return 0; | 229 | return 0; |
230 | 230 | ||
231 | if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) | 231 | if (dev->state & DEV_DISCONNECTED) |
232 | return 0; | 232 | return 0; |
233 | 233 | ||
234 | if (urb->status < 0) { | 234 | if (urb->status < 0) { |
diff --git a/drivers/media/video/cx231xx/cx231xx-input.c b/drivers/media/video/cx231xx/cx231xx-input.c index 45e14cac4622..96176e9db5a2 100644 --- a/drivers/media/video/cx231xx/cx231xx-input.c +++ b/drivers/media/video/cx231xx/cx231xx-input.c | |||
@@ -27,12 +27,16 @@ | |||
27 | static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key, | 27 | static int get_key_isdbt(struct IR_i2c *ir, u32 *ir_key, |
28 | u32 *ir_raw) | 28 | u32 *ir_raw) |
29 | { | 29 | { |
30 | int rc; | ||
30 | u8 cmd, scancode; | 31 | u8 cmd, scancode; |
31 | 32 | ||
32 | dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__); | 33 | dev_dbg(&ir->rc->input_dev->dev, "%s\n", __func__); |
33 | 34 | ||
34 | /* poll IR chip */ | 35 | /* poll IR chip */ |
35 | if (1 != i2c_master_recv(ir->c, &cmd, 1)) | 36 | rc = i2c_master_recv(ir->c, &cmd, 1); |
37 | if (rc < 0) | ||
38 | return rc; | ||
39 | if (rc != 1) | ||
36 | return -EIO; | 40 | return -EIO; |
37 | 41 | ||
38 | /* it seems that 0xFE indicates that a button is still hold | 42 | /* it seems that 0xFE indicates that a button is still hold |
@@ -102,11 +106,14 @@ int cx231xx_ir_init(struct cx231xx *dev) | |||
102 | ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master; | 106 | ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master; |
103 | dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n", | 107 | dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n", |
104 | ir_i2c_bus, info.addr); | 108 | ir_i2c_bus, info.addr); |
105 | i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info); | 109 | dev->ir_i2c_client = i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info); |
106 | 110 | ||
107 | return 0; | 111 | return 0; |
108 | } | 112 | } |
109 | 113 | ||
110 | void cx231xx_ir_exit(struct cx231xx *dev) | 114 | void cx231xx_ir_exit(struct cx231xx *dev) |
111 | { | 115 | { |
116 | if (dev->ir_i2c_client) | ||
117 | i2c_unregister_device(dev->ir_i2c_client); | ||
118 | dev->ir_i2c_client = NULL; | ||
112 | } | 119 | } |
diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c index 1c7a4daafecf..8cdee5f78f13 100644 --- a/drivers/media/video/cx231xx/cx231xx-vbi.c +++ b/drivers/media/video/cx231xx/cx231xx-vbi.c | |||
@@ -93,7 +93,7 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb) | |||
93 | if (!dev) | 93 | if (!dev) |
94 | return 0; | 94 | return 0; |
95 | 95 | ||
96 | if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) | 96 | if (dev->state & DEV_DISCONNECTED) |
97 | return 0; | 97 | return 0; |
98 | 98 | ||
99 | if (urb->status < 0) { | 99 | if (urb->status < 0) { |
@@ -452,7 +452,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, | |||
452 | return -ENOMEM; | 452 | return -ENOMEM; |
453 | } | 453 | } |
454 | dev->vbi_mode.bulk_ctl.urb[i] = urb; | 454 | dev->vbi_mode.bulk_ctl.urb[i] = urb; |
455 | urb->transfer_flags = 0; | 455 | urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; |
456 | 456 | ||
457 | dev->vbi_mode.bulk_ctl.transfer_buffer[i] = | 457 | dev->vbi_mode.bulk_ctl.transfer_buffer[i] = |
458 | kzalloc(sb_size, GFP_KERNEL); | 458 | kzalloc(sb_size, GFP_KERNEL); |
diff --git a/drivers/media/video/cx231xx/cx231xx-video.c b/drivers/media/video/cx231xx/cx231xx-video.c index 6e81f970dc7d..829a41b0c9ef 100644 --- a/drivers/media/video/cx231xx/cx231xx-video.c +++ b/drivers/media/video/cx231xx/cx231xx-video.c | |||
@@ -337,7 +337,7 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) | |||
337 | if (!dev) | 337 | if (!dev) |
338 | return 0; | 338 | return 0; |
339 | 339 | ||
340 | if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) | 340 | if (dev->state & DEV_DISCONNECTED) |
341 | return 0; | 341 | return 0; |
342 | 342 | ||
343 | if (urb->status < 0) { | 343 | if (urb->status < 0) { |
@@ -440,7 +440,7 @@ static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb) | |||
440 | if (!dev) | 440 | if (!dev) |
441 | return 0; | 441 | return 0; |
442 | 442 | ||
443 | if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED)) | 443 | if (dev->state & DEV_DISCONNECTED) |
444 | return 0; | 444 | return 0; |
445 | 445 | ||
446 | if (urb->status < 0) { | 446 | if (urb->status < 0) { |
@@ -1000,12 +1000,6 @@ static int check_dev(struct cx231xx *dev) | |||
1000 | cx231xx_errdev("v4l2 ioctl: device not present\n"); | 1000 | cx231xx_errdev("v4l2 ioctl: device not present\n"); |
1001 | return -ENODEV; | 1001 | return -ENODEV; |
1002 | } | 1002 | } |
1003 | |||
1004 | if (dev->state & DEV_MISCONFIGURED) { | ||
1005 | cx231xx_errdev("v4l2 ioctl: device is misconfigured; " | ||
1006 | "close and open it again\n"); | ||
1007 | return -EIO; | ||
1008 | } | ||
1009 | return 0; | 1003 | return 0; |
1010 | } | 1004 | } |
1011 | 1005 | ||
@@ -2347,7 +2341,8 @@ static int cx231xx_v4l2_close(struct file *filp) | |||
2347 | return 0; | 2341 | return 0; |
2348 | } | 2342 | } |
2349 | 2343 | ||
2350 | if (dev->users == 1) { | 2344 | dev->users--; |
2345 | if (!dev->users) { | ||
2351 | videobuf_stop(&fh->vb_vidq); | 2346 | videobuf_stop(&fh->vb_vidq); |
2352 | videobuf_mmap_free(&fh->vb_vidq); | 2347 | videobuf_mmap_free(&fh->vb_vidq); |
2353 | 2348 | ||
@@ -2374,7 +2369,6 @@ static int cx231xx_v4l2_close(struct file *filp) | |||
2374 | cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); | 2369 | cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0); |
2375 | } | 2370 | } |
2376 | kfree(fh); | 2371 | kfree(fh); |
2377 | dev->users--; | ||
2378 | wake_up_interruptible_nr(&dev->open, 1); | 2372 | wake_up_interruptible_nr(&dev->open, 1); |
2379 | return 0; | 2373 | return 0; |
2380 | } | 2374 | } |
diff --git a/drivers/media/video/cx231xx/cx231xx.h b/drivers/media/video/cx231xx/cx231xx.h index 2000bc64c497..e17447554a0d 100644 --- a/drivers/media/video/cx231xx/cx231xx.h +++ b/drivers/media/video/cx231xx/cx231xx.h | |||
@@ -377,7 +377,6 @@ struct cx231xx_board { | |||
377 | enum cx231xx_dev_state { | 377 | enum cx231xx_dev_state { |
378 | DEV_INITIALIZED = 0x01, | 378 | DEV_INITIALIZED = 0x01, |
379 | DEV_DISCONNECTED = 0x02, | 379 | DEV_DISCONNECTED = 0x02, |
380 | DEV_MISCONFIGURED = 0x04, | ||
381 | }; | 380 | }; |
382 | 381 | ||
383 | enum AFE_MODE { | 382 | enum AFE_MODE { |
@@ -621,6 +620,7 @@ struct cx231xx { | |||
621 | 620 | ||
622 | /* For I2C IR support */ | 621 | /* For I2C IR support */ |
623 | struct IR_i2c_init_data init_data; | 622 | struct IR_i2c_init_data init_data; |
623 | struct i2c_client *ir_i2c_client; | ||
624 | 624 | ||
625 | unsigned int stream_on:1; /* Locks streams */ | 625 | unsigned int stream_on:1; /* Locks streams */ |
626 | unsigned int vbi_stream_on:1; /* Locks streams for VBI */ | 626 | unsigned int vbi_stream_on:1; /* Locks streams for VBI */ |
diff --git a/drivers/media/video/cx23885/cx23885-417.c b/drivers/media/video/cx23885/cx23885-417.c index 67c4a59bd882..f5c79e53e5a1 100644 --- a/drivers/media/video/cx23885/cx23885-417.c +++ b/drivers/media/video/cx23885/cx23885-417.c | |||
@@ -900,6 +900,7 @@ static int cx23885_load_firmware(struct cx23885_dev *dev) | |||
900 | int i, retval = 0; | 900 | int i, retval = 0; |
901 | u32 value = 0; | 901 | u32 value = 0; |
902 | u32 gpio_output = 0; | 902 | u32 gpio_output = 0; |
903 | u32 gpio_value; | ||
903 | u32 checksum = 0; | 904 | u32 checksum = 0; |
904 | u32 *dataptr; | 905 | u32 *dataptr; |
905 | 906 | ||
@@ -907,7 +908,7 @@ static int cx23885_load_firmware(struct cx23885_dev *dev) | |||
907 | 908 | ||
908 | /* Save GPIO settings before reset of APU */ | 909 | /* Save GPIO settings before reset of APU */ |
909 | retval |= mc417_memory_read(dev, 0x9020, &gpio_output); | 910 | retval |= mc417_memory_read(dev, 0x9020, &gpio_output); |
910 | retval |= mc417_memory_read(dev, 0x900C, &value); | 911 | retval |= mc417_memory_read(dev, 0x900C, &gpio_value); |
911 | 912 | ||
912 | retval = mc417_register_write(dev, | 913 | retval = mc417_register_write(dev, |
913 | IVTV_REG_VPU, 0xFFFFFFED); | 914 | IVTV_REG_VPU, 0xFFFFFFED); |
@@ -991,11 +992,18 @@ static int cx23885_load_firmware(struct cx23885_dev *dev) | |||
991 | 992 | ||
992 | /* F/W power up disturbs the GPIOs, restore state */ | 993 | /* F/W power up disturbs the GPIOs, restore state */ |
993 | retval |= mc417_register_write(dev, 0x9020, gpio_output); | 994 | retval |= mc417_register_write(dev, 0x9020, gpio_output); |
994 | retval |= mc417_register_write(dev, 0x900C, value); | 995 | retval |= mc417_register_write(dev, 0x900C, gpio_value); |
995 | 996 | ||
996 | retval |= mc417_register_read(dev, IVTV_REG_VPU, &value); | 997 | retval |= mc417_register_read(dev, IVTV_REG_VPU, &value); |
997 | retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8); | 998 | retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8); |
998 | 999 | ||
1000 | /* Hardcoded GPIO's here */ | ||
1001 | retval |= mc417_register_write(dev, 0x9020, 0x4000); | ||
1002 | retval |= mc417_register_write(dev, 0x900C, 0x4000); | ||
1003 | |||
1004 | mc417_register_read(dev, 0x9020, &gpio_output); | ||
1005 | mc417_register_read(dev, 0x900C, &gpio_value); | ||
1006 | |||
999 | if (retval < 0) | 1007 | if (retval < 0) |
1000 | printk(KERN_ERR "%s: Error with mc417_register_write\n", | 1008 | printk(KERN_ERR "%s: Error with mc417_register_write\n", |
1001 | __func__); | 1009 | __func__); |
@@ -1015,6 +1023,12 @@ static void cx23885_codec_settings(struct cx23885_dev *dev) | |||
1015 | { | 1023 | { |
1016 | dprintk(1, "%s()\n", __func__); | 1024 | dprintk(1, "%s()\n", __func__); |
1017 | 1025 | ||
1026 | /* Dynamically change the height based on video standard */ | ||
1027 | if (dev->encodernorm.id & V4L2_STD_525_60) | ||
1028 | dev->ts1.height = 480; | ||
1029 | else | ||
1030 | dev->ts1.height = 576; | ||
1031 | |||
1018 | /* assign frame size */ | 1032 | /* assign frame size */ |
1019 | cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, | 1033 | cx23885_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0, |
1020 | dev->ts1.height, dev->ts1.width); | 1034 | dev->ts1.height, dev->ts1.width); |
@@ -1030,7 +1044,7 @@ static void cx23885_codec_settings(struct cx23885_dev *dev) | |||
1030 | cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1); | 1044 | cx23885_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1); |
1031 | } | 1045 | } |
1032 | 1046 | ||
1033 | static int cx23885_initialize_codec(struct cx23885_dev *dev) | 1047 | static int cx23885_initialize_codec(struct cx23885_dev *dev, int startencoder) |
1034 | { | 1048 | { |
1035 | int version; | 1049 | int version; |
1036 | int retval; | 1050 | int retval; |
@@ -1112,9 +1126,11 @@ static int cx23885_initialize_codec(struct cx23885_dev *dev) | |||
1112 | mc417_memory_write(dev, 2120, 0x00000080); | 1126 | mc417_memory_write(dev, 2120, 0x00000080); |
1113 | 1127 | ||
1114 | /* start capturing to the host interface */ | 1128 | /* start capturing to the host interface */ |
1115 | cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, | 1129 | if (startencoder) { |
1116 | CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE); | 1130 | cx23885_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0, |
1117 | msleep(10); | 1131 | CX23885_MPEG_CAPTURE, CX23885_RAW_BITS_NONE); |
1132 | msleep(10); | ||
1133 | } | ||
1118 | 1134 | ||
1119 | return 0; | 1135 | return 0; |
1120 | } | 1136 | } |
@@ -1196,6 +1212,16 @@ static int cx23885_querymenu(struct cx23885_dev *dev, | |||
1196 | cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id)); | 1212 | cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id)); |
1197 | } | 1213 | } |
1198 | 1214 | ||
1215 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) | ||
1216 | { | ||
1217 | struct cx23885_fh *fh = file->private_data; | ||
1218 | struct cx23885_dev *dev = fh->dev; | ||
1219 | |||
1220 | call_all(dev, core, g_std, id); | ||
1221 | |||
1222 | return 0; | ||
1223 | } | ||
1224 | |||
1199 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) | 1225 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) |
1200 | { | 1226 | { |
1201 | struct cx23885_fh *fh = file->private_data; | 1227 | struct cx23885_fh *fh = file->private_data; |
@@ -1208,55 +1234,31 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id) | |||
1208 | if (i == ARRAY_SIZE(cx23885_tvnorms)) | 1234 | if (i == ARRAY_SIZE(cx23885_tvnorms)) |
1209 | return -EINVAL; | 1235 | return -EINVAL; |
1210 | dev->encodernorm = cx23885_tvnorms[i]; | 1236 | dev->encodernorm = cx23885_tvnorms[i]; |
1237 | |||
1238 | /* Have the drier core notify the subdevices */ | ||
1239 | mutex_lock(&dev->lock); | ||
1240 | cx23885_set_tvnorm(dev, *id); | ||
1241 | mutex_unlock(&dev->lock); | ||
1242 | |||
1211 | return 0; | 1243 | return 0; |
1212 | } | 1244 | } |
1213 | 1245 | ||
1214 | static int vidioc_enum_input(struct file *file, void *priv, | 1246 | static int vidioc_enum_input(struct file *file, void *priv, |
1215 | struct v4l2_input *i) | 1247 | struct v4l2_input *i) |
1216 | { | 1248 | { |
1217 | struct cx23885_fh *fh = file->private_data; | 1249 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; |
1218 | struct cx23885_dev *dev = fh->dev; | 1250 | dprintk(1, "%s()\n", __func__); |
1219 | struct cx23885_input *input; | 1251 | return cx23885_enum_input(dev, i); |
1220 | int n; | ||
1221 | |||
1222 | if (i->index >= 4) | ||
1223 | return -EINVAL; | ||
1224 | |||
1225 | input = &cx23885_boards[dev->board].input[i->index]; | ||
1226 | |||
1227 | if (input->type == 0) | ||
1228 | return -EINVAL; | ||
1229 | |||
1230 | /* FIXME | ||
1231 | * strcpy(i->name, input->name); */ | ||
1232 | strcpy(i->name, "unset"); | ||
1233 | |||
1234 | if (input->type == CX23885_VMUX_TELEVISION || | ||
1235 | input->type == CX23885_VMUX_CABLE) | ||
1236 | i->type = V4L2_INPUT_TYPE_TUNER; | ||
1237 | else | ||
1238 | i->type = V4L2_INPUT_TYPE_CAMERA; | ||
1239 | |||
1240 | for (n = 0; n < ARRAY_SIZE(cx23885_tvnorms); n++) | ||
1241 | i->std |= cx23885_tvnorms[n].id; | ||
1242 | return 0; | ||
1243 | } | 1252 | } |
1244 | 1253 | ||
1245 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | 1254 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) |
1246 | { | 1255 | { |
1247 | struct cx23885_fh *fh = file->private_data; | 1256 | return cx23885_get_input(file, priv, i); |
1248 | struct cx23885_dev *dev = fh->dev; | ||
1249 | |||
1250 | *i = dev->input; | ||
1251 | return 0; | ||
1252 | } | 1257 | } |
1253 | 1258 | ||
1254 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | 1259 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) |
1255 | { | 1260 | { |
1256 | if (i >= 4) | 1261 | return cx23885_set_input(file, priv, i); |
1257 | return -EINVAL; | ||
1258 | |||
1259 | return 0; | ||
1260 | } | 1262 | } |
1261 | 1263 | ||
1262 | static int vidioc_g_tuner(struct file *file, void *priv, | 1264 | static int vidioc_g_tuner(struct file *file, void *priv, |
@@ -1309,43 +1311,25 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
1309 | } | 1311 | } |
1310 | 1312 | ||
1311 | static int vidioc_s_frequency(struct file *file, void *priv, | 1313 | static int vidioc_s_frequency(struct file *file, void *priv, |
1312 | struct v4l2_frequency *f) | 1314 | struct v4l2_frequency *f) |
1313 | { | 1315 | { |
1314 | struct cx23885_fh *fh = file->private_data; | 1316 | return cx23885_set_frequency(file, priv, f); |
1315 | struct cx23885_dev *dev = fh->dev; | 1317 | } |
1316 | |||
1317 | cx23885_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0, | ||
1318 | CX23885_END_NOW, CX23885_MPEG_CAPTURE, | ||
1319 | CX23885_RAW_BITS_NONE); | ||
1320 | |||
1321 | dprintk(1, "VIDIOC_S_FREQUENCY: dev type %d, f\n", | ||
1322 | dev->tuner_type); | ||
1323 | dprintk(1, "VIDIOC_S_FREQUENCY: f tuner %d, f type %d\n", | ||
1324 | f->tuner, f->type); | ||
1325 | if (UNSET == dev->tuner_type) | ||
1326 | return -EINVAL; | ||
1327 | if (f->tuner != 0) | ||
1328 | return -EINVAL; | ||
1329 | if (f->type != V4L2_TUNER_ANALOG_TV) | ||
1330 | return -EINVAL; | ||
1331 | dev->freq = f->frequency; | ||
1332 | |||
1333 | call_all(dev, tuner, s_frequency, f); | ||
1334 | 1318 | ||
1335 | cx23885_initialize_codec(dev); | 1319 | static int vidioc_g_ctrl(struct file *file, void *priv, |
1320 | struct v4l2_control *ctl) | ||
1321 | { | ||
1322 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; | ||
1336 | 1323 | ||
1337 | return 0; | 1324 | return cx23885_get_control(dev, ctl); |
1338 | } | 1325 | } |
1339 | 1326 | ||
1340 | static int vidioc_s_ctrl(struct file *file, void *priv, | 1327 | static int vidioc_s_ctrl(struct file *file, void *priv, |
1341 | struct v4l2_control *ctl) | 1328 | struct v4l2_control *ctl) |
1342 | { | 1329 | { |
1343 | struct cx23885_fh *fh = file->private_data; | 1330 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; |
1344 | struct cx23885_dev *dev = fh->dev; | ||
1345 | 1331 | ||
1346 | /* Update the A/V core */ | 1332 | return cx23885_set_control(dev, ctl); |
1347 | call_all(dev, core, s_ctrl, ctl); | ||
1348 | return 0; | ||
1349 | } | 1333 | } |
1350 | 1334 | ||
1351 | static int vidioc_querycap(struct file *file, void *priv, | 1335 | static int vidioc_querycap(struct file *file, void *priv, |
@@ -1636,7 +1620,7 @@ static ssize_t mpeg_read(struct file *file, char __user *data, | |||
1636 | /* Start mpeg encoder on first read. */ | 1620 | /* Start mpeg encoder on first read. */ |
1637 | if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { | 1621 | if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) { |
1638 | if (atomic_inc_return(&dev->v4l_reader_count) == 1) { | 1622 | if (atomic_inc_return(&dev->v4l_reader_count) == 1) { |
1639 | if (cx23885_initialize_codec(dev) < 0) | 1623 | if (cx23885_initialize_codec(dev, 1) < 0) |
1640 | return -EINVAL; | 1624 | return -EINVAL; |
1641 | } | 1625 | } |
1642 | } | 1626 | } |
@@ -1677,6 +1661,8 @@ static struct v4l2_file_operations mpeg_fops = { | |||
1677 | }; | 1661 | }; |
1678 | 1662 | ||
1679 | static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { | 1663 | static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { |
1664 | .vidioc_querystd = vidioc_g_std, | ||
1665 | .vidioc_g_std = vidioc_g_std, | ||
1680 | .vidioc_s_std = vidioc_s_std, | 1666 | .vidioc_s_std = vidioc_s_std, |
1681 | .vidioc_enum_input = vidioc_enum_input, | 1667 | .vidioc_enum_input = vidioc_enum_input, |
1682 | .vidioc_g_input = vidioc_g_input, | 1668 | .vidioc_g_input = vidioc_g_input, |
@@ -1686,6 +1672,7 @@ static const struct v4l2_ioctl_ops mpeg_ioctl_ops = { | |||
1686 | .vidioc_g_frequency = vidioc_g_frequency, | 1672 | .vidioc_g_frequency = vidioc_g_frequency, |
1687 | .vidioc_s_frequency = vidioc_s_frequency, | 1673 | .vidioc_s_frequency = vidioc_s_frequency, |
1688 | .vidioc_s_ctrl = vidioc_s_ctrl, | 1674 | .vidioc_s_ctrl = vidioc_s_ctrl, |
1675 | .vidioc_g_ctrl = vidioc_g_ctrl, | ||
1689 | .vidioc_querycap = vidioc_querycap, | 1676 | .vidioc_querycap = vidioc_querycap, |
1690 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, | 1677 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap, |
1691 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, | 1678 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap, |
@@ -1746,8 +1733,8 @@ static struct video_device *cx23885_video_dev_alloc( | |||
1746 | if (NULL == vfd) | 1733 | if (NULL == vfd) |
1747 | return NULL; | 1734 | return NULL; |
1748 | *vfd = *template; | 1735 | *vfd = *template; |
1749 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, | 1736 | snprintf(vfd->name, sizeof(vfd->name), "%s (%s)", |
1750 | type, cx23885_boards[tsport->dev->board].name); | 1737 | cx23885_boards[tsport->dev->board].name, type); |
1751 | vfd->parent = &pci->dev; | 1738 | vfd->parent = &pci->dev; |
1752 | vfd->release = video_device_release; | 1739 | vfd->release = video_device_release; |
1753 | return vfd; | 1740 | return vfd; |
@@ -1791,5 +1778,11 @@ int cx23885_417_register(struct cx23885_dev *dev) | |||
1791 | printk(KERN_INFO "%s: registered device %s [mpeg]\n", | 1778 | printk(KERN_INFO "%s: registered device %s [mpeg]\n", |
1792 | dev->name, video_device_node_name(dev->v4l_device)); | 1779 | dev->name, video_device_node_name(dev->v4l_device)); |
1793 | 1780 | ||
1781 | /* ST: Configure the encoder paramaters, but don't begin | ||
1782 | * encoding, this resolves an issue where the first time the | ||
1783 | * encoder is started video can be choppy. | ||
1784 | */ | ||
1785 | cx23885_initialize_codec(dev, 0); | ||
1786 | |||
1794 | return 0; | 1787 | return 0; |
1795 | } | 1788 | } |
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index c3cf08945e4c..3c01be999e35 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c | |||
@@ -335,8 +335,33 @@ struct cx23885_board cx23885_boards[] = { | |||
335 | }, | 335 | }, |
336 | [CX23885_BOARD_HAUPPAUGE_HVR1850] = { | 336 | [CX23885_BOARD_HAUPPAUGE_HVR1850] = { |
337 | .name = "Hauppauge WinTV-HVR1850", | 337 | .name = "Hauppauge WinTV-HVR1850", |
338 | .porta = CX23885_ANALOG_VIDEO, | ||
338 | .portb = CX23885_MPEG_ENCODER, | 339 | .portb = CX23885_MPEG_ENCODER, |
339 | .portc = CX23885_MPEG_DVB, | 340 | .portc = CX23885_MPEG_DVB, |
341 | .tuner_type = TUNER_ABSENT, | ||
342 | .tuner_addr = 0x42, /* 0x84 >> 1 */ | ||
343 | .force_bff = 1, | ||
344 | .input = {{ | ||
345 | .type = CX23885_VMUX_TELEVISION, | ||
346 | .vmux = CX25840_VIN7_CH3 | | ||
347 | CX25840_VIN5_CH2 | | ||
348 | CX25840_VIN2_CH1 | | ||
349 | CX25840_DIF_ON, | ||
350 | .amux = CX25840_AUDIO8, | ||
351 | }, { | ||
352 | .type = CX23885_VMUX_COMPOSITE1, | ||
353 | .vmux = CX25840_VIN7_CH3 | | ||
354 | CX25840_VIN4_CH2 | | ||
355 | CX25840_VIN6_CH1, | ||
356 | .amux = CX25840_AUDIO7, | ||
357 | }, { | ||
358 | .type = CX23885_VMUX_SVIDEO, | ||
359 | .vmux = CX25840_VIN7_CH3 | | ||
360 | CX25840_VIN4_CH2 | | ||
361 | CX25840_VIN8_CH1 | | ||
362 | CX25840_SVIDEO_ON, | ||
363 | .amux = CX25840_AUDIO7, | ||
364 | } }, | ||
340 | }, | 365 | }, |
341 | [CX23885_BOARD_COMPRO_VIDEOMATE_E800] = { | 366 | [CX23885_BOARD_COMPRO_VIDEOMATE_E800] = { |
342 | .name = "Compro VideoMate E800", | 367 | .name = "Compro VideoMate E800", |
@@ -438,6 +463,41 @@ struct cx23885_board cx23885_boards[] = { | |||
438 | .gpio0 = 0, | 463 | .gpio0 = 0, |
439 | } }, | 464 | } }, |
440 | }, | 465 | }, |
466 | [CX23885_BOARD_MYGICA_X8507] = { | ||
467 | .name = "Mygica X8507", | ||
468 | .tuner_type = TUNER_XC5000, | ||
469 | .tuner_addr = 0x61, | ||
470 | .tuner_bus = 1, | ||
471 | .porta = CX23885_ANALOG_VIDEO, | ||
472 | .input = { | ||
473 | { | ||
474 | .type = CX23885_VMUX_TELEVISION, | ||
475 | .vmux = CX25840_COMPOSITE2, | ||
476 | .amux = CX25840_AUDIO8, | ||
477 | }, | ||
478 | { | ||
479 | .type = CX23885_VMUX_COMPOSITE1, | ||
480 | .vmux = CX25840_COMPOSITE8, | ||
481 | }, | ||
482 | { | ||
483 | .type = CX23885_VMUX_SVIDEO, | ||
484 | .vmux = CX25840_SVIDEO_LUMA3 | | ||
485 | CX25840_SVIDEO_CHROMA4, | ||
486 | }, | ||
487 | { | ||
488 | .type = CX23885_VMUX_COMPONENT, | ||
489 | .vmux = CX25840_COMPONENT_ON | | ||
490 | CX25840_VIN1_CH1 | | ||
491 | CX25840_VIN6_CH2 | | ||
492 | CX25840_VIN7_CH3, | ||
493 | }, | ||
494 | }, | ||
495 | }, | ||
496 | [CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL] = { | ||
497 | .name = "TerraTec Cinergy T PCIe Dual", | ||
498 | .portb = CX23885_MPEG_DVB, | ||
499 | .portc = CX23885_MPEG_DVB, | ||
500 | } | ||
441 | }; | 501 | }; |
442 | const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); | 502 | const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); |
443 | 503 | ||
@@ -637,6 +697,14 @@ struct cx23885_subid cx23885_subids[] = { | |||
637 | .subvendor = 0x1b55, | 697 | .subvendor = 0x1b55, |
638 | .subdevice = 0xe2e4, | 698 | .subdevice = 0xe2e4, |
639 | .card = CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF, | 699 | .card = CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF, |
700 | }, { | ||
701 | .subvendor = 0x14f1, | ||
702 | .subdevice = 0x8502, | ||
703 | .card = CX23885_BOARD_MYGICA_X8507, | ||
704 | }, { | ||
705 | .subvendor = 0x153b, | ||
706 | .subdevice = 0x117e, | ||
707 | .card = CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL, | ||
640 | }, | 708 | }, |
641 | }; | 709 | }; |
642 | const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); | 710 | const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); |
@@ -1068,6 +1136,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) | |||
1068 | break; | 1136 | break; |
1069 | case CX23885_BOARD_MYGICA_X8506: | 1137 | case CX23885_BOARD_MYGICA_X8506: |
1070 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: | 1138 | case CX23885_BOARD_MAGICPRO_PROHDTVE2: |
1139 | case CX23885_BOARD_MYGICA_X8507: | ||
1071 | /* GPIO-0 (0)Analog / (1)Digital TV */ | 1140 | /* GPIO-0 (0)Analog / (1)Digital TV */ |
1072 | /* GPIO-1 reset XC5000 */ | 1141 | /* GPIO-1 reset XC5000 */ |
1073 | /* GPIO-2 reset LGS8GL5 / LGS8G75 */ | 1142 | /* GPIO-2 reset LGS8GL5 / LGS8G75 */ |
@@ -1367,6 +1436,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
1367 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | 1436 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ |
1368 | ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | 1437 | ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; |
1369 | break; | 1438 | break; |
1439 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
1370 | case CX23885_BOARD_HAUPPAUGE_HVR1800: | 1440 | case CX23885_BOARD_HAUPPAUGE_HVR1800: |
1371 | /* Defaults for VID B - Analog encoder */ | 1441 | /* Defaults for VID B - Analog encoder */ |
1372 | /* DREQ_POL, SMODE, PUNC_CLK, MCLK_POL Serial bus + punc clk */ | 1442 | /* DREQ_POL, SMODE, PUNC_CLK, MCLK_POL Serial bus + punc clk */ |
@@ -1377,6 +1447,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
1377 | /* APB_TSVALERR_POL (active low)*/ | 1447 | /* APB_TSVALERR_POL (active low)*/ |
1378 | ts1->vld_misc_val = 0x2000; | 1448 | ts1->vld_misc_val = 0x2000; |
1379 | ts1->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4 | 0xc); | 1449 | ts1->hw_sop_ctrl_val = (0x47 << 16 | 188 << 4 | 0xc); |
1450 | cx_write(0x130184, 0xc); | ||
1380 | 1451 | ||
1381 | /* Defaults for VID C */ | 1452 | /* Defaults for VID C */ |
1382 | ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ | 1453 | ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ |
@@ -1396,6 +1467,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
1396 | break; | 1467 | break; |
1397 | case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: | 1468 | case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: |
1398 | case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: | 1469 | case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: |
1470 | case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: | ||
1399 | ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ | 1471 | ts1->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ |
1400 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ | 1472 | ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ |
1401 | ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; | 1473 | ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; |
@@ -1431,7 +1503,6 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
1431 | case CX23885_BOARD_HAUPPAUGE_HVR1275: | 1503 | case CX23885_BOARD_HAUPPAUGE_HVR1275: |
1432 | case CX23885_BOARD_HAUPPAUGE_HVR1255: | 1504 | case CX23885_BOARD_HAUPPAUGE_HVR1255: |
1433 | case CX23885_BOARD_HAUPPAUGE_HVR1210: | 1505 | case CX23885_BOARD_HAUPPAUGE_HVR1210: |
1434 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | ||
1435 | case CX23885_BOARD_COMPRO_VIDEOMATE_E800: | 1506 | case CX23885_BOARD_COMPRO_VIDEOMATE_E800: |
1436 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | 1507 | case CX23885_BOARD_HAUPPAUGE_HVR1290: |
1437 | case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: | 1508 | case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: |
@@ -1468,6 +1539,8 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
1468 | case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: | 1539 | case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID: |
1469 | case CX23885_BOARD_HAUPPAUGE_HVR1500: | 1540 | case CX23885_BOARD_HAUPPAUGE_HVR1500: |
1470 | case CX23885_BOARD_MPX885: | 1541 | case CX23885_BOARD_MPX885: |
1542 | case CX23885_BOARD_MYGICA_X8507: | ||
1543 | case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: | ||
1471 | dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, | 1544 | dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, |
1472 | &dev->i2c_bus[2].i2c_adap, | 1545 | &dev->i2c_bus[2].i2c_adap, |
1473 | "cx25840", 0x88 >> 1, NULL); | 1546 | "cx25840", 0x88 >> 1, NULL); |
diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 40e68b22015e..6ad227029a0f 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c | |||
@@ -206,12 +206,12 @@ static struct sram_channel cx23887_sram_channels[] = { | |||
206 | .cnt2_reg = DMA1_CNT2, | 206 | .cnt2_reg = DMA1_CNT2, |
207 | }, | 207 | }, |
208 | [SRAM_CH02] = { | 208 | [SRAM_CH02] = { |
209 | .name = "ch2", | 209 | .name = "VID A (VBI)", |
210 | .cmds_start = 0x0, | 210 | .cmds_start = 0x10050, |
211 | .ctrl_start = 0x0, | 211 | .ctrl_start = 0x105F0, |
212 | .cdt = 0x0, | 212 | .cdt = 0x10810, |
213 | .fifo_start = 0x0, | 213 | .fifo_start = 0x3000, |
214 | .fifo_size = 0x0, | 214 | .fifo_size = 0x1000, |
215 | .ptr1_reg = DMA2_PTR1, | 215 | .ptr1_reg = DMA2_PTR1, |
216 | .ptr2_reg = DMA2_PTR2, | 216 | .ptr2_reg = DMA2_PTR2, |
217 | .cnt1_reg = DMA2_CNT1, | 217 | .cnt1_reg = DMA2_CNT1, |
@@ -266,12 +266,12 @@ static struct sram_channel cx23887_sram_channels[] = { | |||
266 | .cnt2_reg = DMA5_CNT2, | 266 | .cnt2_reg = DMA5_CNT2, |
267 | }, | 267 | }, |
268 | [SRAM_CH07] = { | 268 | [SRAM_CH07] = { |
269 | .name = "ch7", | 269 | .name = "TV Audio", |
270 | .cmds_start = 0x0, | 270 | .cmds_start = 0x10190, |
271 | .ctrl_start = 0x0, | 271 | .ctrl_start = 0x106B0, |
272 | .cdt = 0x0, | 272 | .cdt = 0x10930, |
273 | .fifo_start = 0x0, | 273 | .fifo_start = 0x7000, |
274 | .fifo_size = 0x0, | 274 | .fifo_size = 0x1000, |
275 | .ptr1_reg = DMA6_PTR1, | 275 | .ptr1_reg = DMA6_PTR1, |
276 | .ptr2_reg = DMA6_PTR2, | 276 | .ptr2_reg = DMA6_PTR2, |
277 | .cnt1_reg = DMA6_CNT1, | 277 | .cnt1_reg = DMA6_CNT1, |
diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index bcb45be44bb2..af8a225763d3 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c | |||
@@ -61,6 +61,8 @@ | |||
61 | #include "cx23885-f300.h" | 61 | #include "cx23885-f300.h" |
62 | #include "altera-ci.h" | 62 | #include "altera-ci.h" |
63 | #include "stv0367.h" | 63 | #include "stv0367.h" |
64 | #include "drxk.h" | ||
65 | #include "mt2063.h" | ||
64 | 66 | ||
65 | static unsigned int debug; | 67 | static unsigned int debug; |
66 | 68 | ||
@@ -111,6 +113,8 @@ static void dvb_buf_release(struct videobuf_queue *q, | |||
111 | cx23885_free_buffer(q, (struct cx23885_buffer *)vb); | 113 | cx23885_free_buffer(q, (struct cx23885_buffer *)vb); |
112 | } | 114 | } |
113 | 115 | ||
116 | static int cx23885_dvb_set_frontend(struct dvb_frontend *fe); | ||
117 | |||
114 | static void cx23885_dvb_gate_ctrl(struct cx23885_tsport *port, int open) | 118 | static void cx23885_dvb_gate_ctrl(struct cx23885_tsport *port, int open) |
115 | { | 119 | { |
116 | struct videobuf_dvb_frontends *f; | 120 | struct videobuf_dvb_frontends *f; |
@@ -125,6 +129,12 @@ static void cx23885_dvb_gate_ctrl(struct cx23885_tsport *port, int open) | |||
125 | 129 | ||
126 | if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) | 130 | if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl) |
127 | fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open); | 131 | fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open); |
132 | |||
133 | /* | ||
134 | * FIXME: Improve this path to avoid calling the | ||
135 | * cx23885_dvb_set_frontend() every time it passes here. | ||
136 | */ | ||
137 | cx23885_dvb_set_frontend(fe->dvb.frontend); | ||
128 | } | 138 | } |
129 | 139 | ||
130 | static struct videobuf_queue_ops dvb_qops = { | 140 | static struct videobuf_queue_ops dvb_qops = { |
@@ -479,15 +489,15 @@ static struct xc5000_config mygica_x8506_xc5000_config = { | |||
479 | .if_khz = 5380, | 489 | .if_khz = 5380, |
480 | }; | 490 | }; |
481 | 491 | ||
482 | static int cx23885_dvb_set_frontend(struct dvb_frontend *fe, | 492 | static int cx23885_dvb_set_frontend(struct dvb_frontend *fe) |
483 | struct dvb_frontend_parameters *param) | ||
484 | { | 493 | { |
494 | struct dtv_frontend_properties *p = &fe->dtv_property_cache; | ||
485 | struct cx23885_tsport *port = fe->dvb->priv; | 495 | struct cx23885_tsport *port = fe->dvb->priv; |
486 | struct cx23885_dev *dev = port->dev; | 496 | struct cx23885_dev *dev = port->dev; |
487 | 497 | ||
488 | switch (dev->board) { | 498 | switch (dev->board) { |
489 | case CX23885_BOARD_HAUPPAUGE_HVR1275: | 499 | case CX23885_BOARD_HAUPPAUGE_HVR1275: |
490 | switch (param->u.vsb.modulation) { | 500 | switch (p->modulation) { |
491 | case VSB_8: | 501 | case VSB_8: |
492 | cx23885_gpio_clear(dev, GPIO_5); | 502 | cx23885_gpio_clear(dev, GPIO_5); |
493 | break; | 503 | break; |
@@ -507,31 +517,6 @@ static int cx23885_dvb_set_frontend(struct dvb_frontend *fe, | |||
507 | return 0; | 517 | return 0; |
508 | } | 518 | } |
509 | 519 | ||
510 | static int cx23885_dvb_fe_ioctl_override(struct dvb_frontend *fe, | ||
511 | unsigned int cmd, void *parg, | ||
512 | unsigned int stage) | ||
513 | { | ||
514 | int err = 0; | ||
515 | |||
516 | switch (stage) { | ||
517 | case DVB_FE_IOCTL_PRE: | ||
518 | |||
519 | switch (cmd) { | ||
520 | case FE_SET_FRONTEND: | ||
521 | err = cx23885_dvb_set_frontend(fe, | ||
522 | (struct dvb_frontend_parameters *) parg); | ||
523 | break; | ||
524 | } | ||
525 | break; | ||
526 | |||
527 | case DVB_FE_IOCTL_POST: | ||
528 | /* no post-ioctl handling required */ | ||
529 | break; | ||
530 | } | ||
531 | return err; | ||
532 | }; | ||
533 | |||
534 | |||
535 | static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = { | 520 | static struct lgs8gxx_config magicpro_prohdtve2_lgs8g75_config = { |
536 | .prod = LGS8GXX_PROD_LGS8G75, | 521 | .prod = LGS8GXX_PROD_LGS8G75, |
537 | .demod_address = 0x19, | 522 | .demod_address = 0x19, |
@@ -617,6 +602,24 @@ static struct xc5000_config netup_xc5000_config[] = { | |||
617 | }, | 602 | }, |
618 | }; | 603 | }; |
619 | 604 | ||
605 | static struct drxk_config terratec_drxk_config[] = { | ||
606 | { | ||
607 | .adr = 0x29, | ||
608 | .no_i2c_bridge = 1, | ||
609 | }, { | ||
610 | .adr = 0x2a, | ||
611 | .no_i2c_bridge = 1, | ||
612 | }, | ||
613 | }; | ||
614 | |||
615 | static struct mt2063_config terratec_mt2063_config[] = { | ||
616 | { | ||
617 | .tuner_address = 0x60, | ||
618 | }, { | ||
619 | .tuner_address = 0x67, | ||
620 | }, | ||
621 | }; | ||
622 | |||
620 | int netup_altera_fpga_rw(void *device, int flag, int data, int read) | 623 | int netup_altera_fpga_rw(void *device, int flag, int data, int read) |
621 | { | 624 | { |
622 | struct cx23885_dev *dev = (struct cx23885_dev *)device; | 625 | struct cx23885_dev *dev = (struct cx23885_dev *)device; |
@@ -1043,6 +1046,20 @@ static int dvb_register(struct cx23885_tsport *port) | |||
1043 | } | 1046 | } |
1044 | break; | 1047 | break; |
1045 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | 1048 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
1049 | i2c_bus = &dev->i2c_bus[0]; | ||
1050 | fe0->dvb.frontend = dvb_attach(s5h1411_attach, | ||
1051 | &hcw_s5h1411_config, | ||
1052 | &i2c_bus->i2c_adap); | ||
1053 | if (fe0->dvb.frontend != NULL) | ||
1054 | dvb_attach(tda18271_attach, fe0->dvb.frontend, | ||
1055 | 0x60, &dev->i2c_bus[0].i2c_adap, | ||
1056 | &hauppauge_tda18271_config); | ||
1057 | |||
1058 | tda18271_attach(&dev->ts1.analog_fe, | ||
1059 | 0x60, &dev->i2c_bus[1].i2c_adap, | ||
1060 | &hauppauge_tda18271_config); | ||
1061 | |||
1062 | break; | ||
1046 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | 1063 | case CX23885_BOARD_HAUPPAUGE_HVR1290: |
1047 | i2c_bus = &dev->i2c_bus[0]; | 1064 | i2c_bus = &dev->i2c_bus[0]; |
1048 | fe0->dvb.frontend = dvb_attach(s5h1411_attach, | 1065 | fe0->dvb.frontend = dvb_attach(s5h1411_attach, |
@@ -1118,6 +1135,39 @@ static int dvb_register(struct cx23885_tsport *port) | |||
1118 | goto frontend_detach; | 1135 | goto frontend_detach; |
1119 | } | 1136 | } |
1120 | break; | 1137 | break; |
1138 | case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: | ||
1139 | i2c_bus = &dev->i2c_bus[0]; | ||
1140 | i2c_bus2 = &dev->i2c_bus[1]; | ||
1141 | |||
1142 | switch (port->nr) { | ||
1143 | /* port b */ | ||
1144 | case 1: | ||
1145 | fe0->dvb.frontend = dvb_attach(drxk_attach, | ||
1146 | &terratec_drxk_config[0], | ||
1147 | &i2c_bus->i2c_adap); | ||
1148 | if (fe0->dvb.frontend != NULL) { | ||
1149 | if (!dvb_attach(mt2063_attach, | ||
1150 | fe0->dvb.frontend, | ||
1151 | &terratec_mt2063_config[0], | ||
1152 | &i2c_bus2->i2c_adap)) | ||
1153 | goto frontend_detach; | ||
1154 | } | ||
1155 | break; | ||
1156 | /* port c */ | ||
1157 | case 2: | ||
1158 | fe0->dvb.frontend = dvb_attach(drxk_attach, | ||
1159 | &terratec_drxk_config[1], | ||
1160 | &i2c_bus->i2c_adap); | ||
1161 | if (fe0->dvb.frontend != NULL) { | ||
1162 | if (!dvb_attach(mt2063_attach, | ||
1163 | fe0->dvb.frontend, | ||
1164 | &terratec_mt2063_config[1], | ||
1165 | &i2c_bus2->i2c_adap)) | ||
1166 | goto frontend_detach; | ||
1167 | } | ||
1168 | break; | ||
1169 | } | ||
1170 | break; | ||
1121 | default: | 1171 | default: |
1122 | printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " | 1172 | printk(KERN_INFO "%s: The frontend of your DVB/ATSC card " |
1123 | " isn't supported yet\n", | 1173 | " isn't supported yet\n", |
@@ -1151,7 +1201,7 @@ static int dvb_register(struct cx23885_tsport *port) | |||
1151 | /* register everything */ | 1201 | /* register everything */ |
1152 | ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, | 1202 | ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, |
1153 | &dev->pci->dev, adapter_nr, mfe_shared, | 1203 | &dev->pci->dev, adapter_nr, mfe_shared, |
1154 | cx23885_dvb_fe_ioctl_override); | 1204 | NULL); |
1155 | if (ret) | 1205 | if (ret) |
1156 | goto frontend_detach; | 1206 | goto frontend_detach; |
1157 | 1207 | ||
diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 0ff7a9e98f3e..be1e21d8295c 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c | |||
@@ -309,7 +309,7 @@ static void do_i2c_scan(char *name, struct i2c_client *c) | |||
309 | } | 309 | } |
310 | } | 310 | } |
311 | 311 | ||
312 | /* init + register i2c algo-bit adapter */ | 312 | /* init + register i2c adapter */ |
313 | int cx23885_i2c_register(struct cx23885_i2c *bus) | 313 | int cx23885_i2c_register(struct cx23885_i2c *bus) |
314 | { | 314 | { |
315 | struct cx23885_dev *dev = bus->dev; | 315 | struct cx23885_dev *dev = bus->dev; |
diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index e730b9263016..4bbf9bb97bde 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c | |||
@@ -253,9 +253,9 @@ static struct cx23885_ctrl cx23885_ctls[] = { | |||
253 | .id = V4L2_CID_AUDIO_VOLUME, | 253 | .id = V4L2_CID_AUDIO_VOLUME, |
254 | .name = "Volume", | 254 | .name = "Volume", |
255 | .minimum = 0, | 255 | .minimum = 0, |
256 | .maximum = 0x3f, | 256 | .maximum = 65535, |
257 | .step = 1, | 257 | .step = 65535 / 100, |
258 | .default_value = 0x3f, | 258 | .default_value = 65535, |
259 | .type = V4L2_CTRL_TYPE_INTEGER, | 259 | .type = V4L2_CTRL_TYPE_INTEGER, |
260 | }, | 260 | }, |
261 | .reg = PATH1_VOL_CTL, | 261 | .reg = PATH1_VOL_CTL, |
@@ -316,7 +316,7 @@ void cx23885_video_wakeup(struct cx23885_dev *dev, | |||
316 | __func__, bc); | 316 | __func__, bc); |
317 | } | 317 | } |
318 | 318 | ||
319 | static int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) | 319 | int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm) |
320 | { | 320 | { |
321 | dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", | 321 | dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", |
322 | __func__, | 322 | __func__, |
@@ -344,8 +344,8 @@ static struct video_device *cx23885_vdev_init(struct cx23885_dev *dev, | |||
344 | *vfd = *template; | 344 | *vfd = *template; |
345 | vfd->v4l2_dev = &dev->v4l2_dev; | 345 | vfd->v4l2_dev = &dev->v4l2_dev; |
346 | vfd->release = video_device_release; | 346 | vfd->release = video_device_release; |
347 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", | 347 | snprintf(vfd->name, sizeof(vfd->name), "%s (%s)", |
348 | dev->name, type, cx23885_boards[dev->board].name); | 348 | cx23885_boards[dev->board].name, type); |
349 | video_set_drvdata(vfd, dev); | 349 | video_set_drvdata(vfd, dev); |
350 | return vfd; | 350 | return vfd; |
351 | } | 351 | } |
@@ -492,7 +492,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) | |||
492 | dev->input = input; | 492 | dev->input = input; |
493 | 493 | ||
494 | if (dev->board == CX23885_BOARD_MYGICA_X8506 || | 494 | if (dev->board == CX23885_BOARD_MYGICA_X8506 || |
495 | dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2) { | 495 | dev->board == CX23885_BOARD_MAGICPRO_PROHDTVE2 || |
496 | dev->board == CX23885_BOARD_MYGICA_X8507) { | ||
496 | /* Select Analog TV */ | 497 | /* Select Analog TV */ |
497 | if (INPUT(input)->type == CX23885_VMUX_TELEVISION) | 498 | if (INPUT(input)->type == CX23885_VMUX_TELEVISION) |
498 | cx23885_gpio_clear(dev, GPIO_0); | 499 | cx23885_gpio_clear(dev, GPIO_0); |
@@ -503,7 +504,8 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input) | |||
503 | INPUT(input)->vmux, 0, 0); | 504 | INPUT(input)->vmux, 0, 0); |
504 | 505 | ||
505 | if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) || | 506 | if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) || |
506 | (dev->board == CX23885_BOARD_MPX885)) { | 507 | (dev->board == CX23885_BOARD_MPX885) || |
508 | (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850)) { | ||
507 | /* Configure audio routing */ | 509 | /* Configure audio routing */ |
508 | v4l2_subdev_call(dev->sd_cx25840, audio, s_routing, | 510 | v4l2_subdev_call(dev->sd_cx25840, audio, s_routing, |
509 | INPUT(input)->amux, 0, 0); | 511 | INPUT(input)->amux, 0, 0); |
@@ -649,6 +651,7 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
649 | int rc, init_buffer = 0; | 651 | int rc, init_buffer = 0; |
650 | u32 line0_offset, line1_offset; | 652 | u32 line0_offset, line1_offset; |
651 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); | 653 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); |
654 | int field_tff; | ||
652 | 655 | ||
653 | BUG_ON(NULL == fh->fmt); | 656 | BUG_ON(NULL == fh->fmt); |
654 | if (fh->width < 48 || fh->width > norm_maxw(dev->tvnorm) || | 657 | if (fh->width < 48 || fh->width > norm_maxw(dev->tvnorm) || |
@@ -690,15 +693,25 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
690 | buf->bpl, 0, buf->vb.height); | 693 | buf->bpl, 0, buf->vb.height); |
691 | break; | 694 | break; |
692 | case V4L2_FIELD_INTERLACED: | 695 | case V4L2_FIELD_INTERLACED: |
693 | if (dev->tvnorm & V4L2_STD_NTSC) { | 696 | if (dev->tvnorm & V4L2_STD_NTSC) |
697 | /* NTSC or */ | ||
698 | field_tff = 1; | ||
699 | else | ||
700 | field_tff = 0; | ||
701 | |||
702 | if (cx23885_boards[dev->board].force_bff) | ||
703 | /* PAL / SECAM OR 888 in NTSC MODE */ | ||
704 | field_tff = 0; | ||
705 | |||
706 | if (field_tff) { | ||
694 | /* cx25840 transmits NTSC bottom field first */ | 707 | /* cx25840 transmits NTSC bottom field first */ |
695 | dprintk(1, "%s() Creating NTSC risc\n", | 708 | dprintk(1, "%s() Creating TFF/NTSC risc\n", |
696 | __func__); | 709 | __func__); |
697 | line0_offset = buf->bpl; | 710 | line0_offset = buf->bpl; |
698 | line1_offset = 0; | 711 | line1_offset = 0; |
699 | } else { | 712 | } else { |
700 | /* All other formats are top field first */ | 713 | /* All other formats are top field first */ |
701 | dprintk(1, "%s() Creating PAL/SECAM risc\n", | 714 | dprintk(1, "%s() Creating BFF/PAL/SECAM risc\n", |
702 | __func__); | 715 | __func__); |
703 | line0_offset = 0; | 716 | line0_offset = 0; |
704 | line1_offset = buf->bpl; | 717 | line1_offset = buf->bpl; |
@@ -981,6 +994,8 @@ static int video_release(struct file *file) | |||
981 | } | 994 | } |
982 | 995 | ||
983 | videobuf_mmap_free(&fh->vidq); | 996 | videobuf_mmap_free(&fh->vidq); |
997 | videobuf_mmap_free(&fh->vbiq); | ||
998 | |||
984 | file->private_data = NULL; | 999 | file->private_data = NULL; |
985 | kfree(fh); | 1000 | kfree(fh); |
986 | 1001 | ||
@@ -1002,7 +1017,7 @@ static int video_mmap(struct file *file, struct vm_area_struct *vma) | |||
1002 | /* ------------------------------------------------------------------ */ | 1017 | /* ------------------------------------------------------------------ */ |
1003 | /* VIDEO CTRL IOCTLS */ | 1018 | /* VIDEO CTRL IOCTLS */ |
1004 | 1019 | ||
1005 | static int cx23885_get_control(struct cx23885_dev *dev, | 1020 | int cx23885_get_control(struct cx23885_dev *dev, |
1006 | struct v4l2_control *ctl) | 1021 | struct v4l2_control *ctl) |
1007 | { | 1022 | { |
1008 | dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__); | 1023 | dprintk(1, "%s() calling cx25840(VIDIOC_G_CTRL)\n", __func__); |
@@ -1010,7 +1025,7 @@ static int cx23885_get_control(struct cx23885_dev *dev, | |||
1010 | return 0; | 1025 | return 0; |
1011 | } | 1026 | } |
1012 | 1027 | ||
1013 | static int cx23885_set_control(struct cx23885_dev *dev, | 1028 | int cx23885_set_control(struct cx23885_dev *dev, |
1014 | struct v4l2_control *ctl) | 1029 | struct v4l2_control *ctl) |
1015 | { | 1030 | { |
1016 | dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)\n", __func__); | 1031 | dprintk(1, "%s() calling cx25840(VIDIOC_S_CTRL)\n", __func__); |
@@ -1229,6 +1244,16 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | |||
1229 | return 0; | 1244 | return 0; |
1230 | } | 1245 | } |
1231 | 1246 | ||
1247 | static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id) | ||
1248 | { | ||
1249 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; | ||
1250 | dprintk(1, "%s()\n", __func__); | ||
1251 | |||
1252 | call_all(dev, core, g_std, id); | ||
1253 | |||
1254 | return 0; | ||
1255 | } | ||
1256 | |||
1232 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) | 1257 | static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) |
1233 | { | 1258 | { |
1234 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; | 1259 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; |
@@ -1241,7 +1266,7 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *tvnorms) | |||
1241 | return 0; | 1266 | return 0; |
1242 | } | 1267 | } |
1243 | 1268 | ||
1244 | static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) | 1269 | int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) |
1245 | { | 1270 | { |
1246 | static const char *iname[] = { | 1271 | static const char *iname[] = { |
1247 | [CX23885_VMUX_COMPOSITE1] = "Composite1", | 1272 | [CX23885_VMUX_COMPOSITE1] = "Composite1", |
@@ -1278,6 +1303,15 @@ static int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i) | |||
1278 | if (INPUT(n)->type != CX23885_VMUX_TELEVISION) | 1303 | if (INPUT(n)->type != CX23885_VMUX_TELEVISION) |
1279 | i->audioset = 0x3; | 1304 | i->audioset = 0x3; |
1280 | 1305 | ||
1306 | if (dev->input == n) { | ||
1307 | /* enum'd input matches our configured input. | ||
1308 | * Ask the video decoder to process the call | ||
1309 | * and give it an oppertunity to update the | ||
1310 | * status field. | ||
1311 | */ | ||
1312 | call_all(dev, video, g_input_status, &i->status); | ||
1313 | } | ||
1314 | |||
1281 | return 0; | 1315 | return 0; |
1282 | } | 1316 | } |
1283 | 1317 | ||
@@ -1289,7 +1323,7 @@ static int vidioc_enum_input(struct file *file, void *priv, | |||
1289 | return cx23885_enum_input(dev, i); | 1323 | return cx23885_enum_input(dev, i); |
1290 | } | 1324 | } |
1291 | 1325 | ||
1292 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | 1326 | int cx23885_get_input(struct file *file, void *priv, unsigned int *i) |
1293 | { | 1327 | { |
1294 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; | 1328 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; |
1295 | 1329 | ||
@@ -1298,7 +1332,12 @@ static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) | |||
1298 | return 0; | 1332 | return 0; |
1299 | } | 1333 | } |
1300 | 1334 | ||
1301 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | 1335 | static int vidioc_g_input(struct file *file, void *priv, unsigned int *i) |
1336 | { | ||
1337 | return cx23885_get_input(file, priv, i); | ||
1338 | } | ||
1339 | |||
1340 | int cx23885_set_input(struct file *file, void *priv, unsigned int i) | ||
1302 | { | 1341 | { |
1303 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; | 1342 | struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev; |
1304 | 1343 | ||
@@ -1322,6 +1361,11 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | |||
1322 | return 0; | 1361 | return 0; |
1323 | } | 1362 | } |
1324 | 1363 | ||
1364 | static int vidioc_s_input(struct file *file, void *priv, unsigned int i) | ||
1365 | { | ||
1366 | return cx23885_set_input(file, priv, i); | ||
1367 | } | ||
1368 | |||
1325 | static int vidioc_log_status(struct file *file, void *priv) | 1369 | static int vidioc_log_status(struct file *file, void *priv) |
1326 | { | 1370 | { |
1327 | struct cx23885_fh *fh = priv; | 1371 | struct cx23885_fh *fh = priv; |
@@ -1329,11 +1373,11 @@ static int vidioc_log_status(struct file *file, void *priv) | |||
1329 | 1373 | ||
1330 | printk(KERN_INFO | 1374 | printk(KERN_INFO |
1331 | "%s/0: ============ START LOG STATUS ============\n", | 1375 | "%s/0: ============ START LOG STATUS ============\n", |
1332 | dev->name); | 1376 | dev->name); |
1333 | call_all(dev, core, log_status); | 1377 | call_all(dev, core, log_status); |
1334 | printk(KERN_INFO | 1378 | printk(KERN_INFO |
1335 | "%s/0: ============= END LOG STATUS =============\n", | 1379 | "%s/0: ============= END LOG STATUS =============\n", |
1336 | dev->name); | 1380 | dev->name); |
1337 | return 0; | 1381 | return 0; |
1338 | } | 1382 | } |
1339 | 1383 | ||
@@ -1471,6 +1515,8 @@ static int vidioc_g_frequency(struct file *file, void *priv, | |||
1471 | 1515 | ||
1472 | static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) | 1516 | static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) |
1473 | { | 1517 | { |
1518 | struct v4l2_control ctrl; | ||
1519 | |||
1474 | if (unlikely(UNSET == dev->tuner_type)) | 1520 | if (unlikely(UNSET == dev->tuner_type)) |
1475 | return -EINVAL; | 1521 | return -EINVAL; |
1476 | if (unlikely(f->tuner != 0)) | 1522 | if (unlikely(f->tuner != 0)) |
@@ -1479,29 +1525,102 @@ static int cx23885_set_freq(struct cx23885_dev *dev, struct v4l2_frequency *f) | |||
1479 | mutex_lock(&dev->lock); | 1525 | mutex_lock(&dev->lock); |
1480 | dev->freq = f->frequency; | 1526 | dev->freq = f->frequency; |
1481 | 1527 | ||
1528 | /* I need to mute audio here */ | ||
1529 | ctrl.id = V4L2_CID_AUDIO_MUTE; | ||
1530 | ctrl.value = 1; | ||
1531 | cx23885_set_control(dev, &ctrl); | ||
1532 | |||
1482 | call_all(dev, tuner, s_frequency, f); | 1533 | call_all(dev, tuner, s_frequency, f); |
1483 | 1534 | ||
1484 | /* When changing channels it is required to reset TVAUDIO */ | 1535 | /* When changing channels it is required to reset TVAUDIO */ |
1485 | msleep(10); | 1536 | msleep(100); |
1537 | |||
1538 | /* I need to unmute audio here */ | ||
1539 | ctrl.value = 0; | ||
1540 | cx23885_set_control(dev, &ctrl); | ||
1486 | 1541 | ||
1487 | mutex_unlock(&dev->lock); | 1542 | mutex_unlock(&dev->lock); |
1488 | 1543 | ||
1489 | return 0; | 1544 | return 0; |
1490 | } | 1545 | } |
1491 | 1546 | ||
1492 | static int vidioc_s_frequency(struct file *file, void *priv, | 1547 | static int cx23885_set_freq_via_ops(struct cx23885_dev *dev, |
1493 | struct v4l2_frequency *f) | 1548 | struct v4l2_frequency *f) |
1549 | { | ||
1550 | struct v4l2_control ctrl; | ||
1551 | struct videobuf_dvb_frontend *vfe; | ||
1552 | struct dvb_frontend *fe; | ||
1553 | int err = 0; | ||
1554 | |||
1555 | struct analog_parameters params = { | ||
1556 | .mode = V4L2_TUNER_ANALOG_TV, | ||
1557 | .audmode = V4L2_TUNER_MODE_STEREO, | ||
1558 | .std = dev->tvnorm, | ||
1559 | .frequency = f->frequency | ||
1560 | }; | ||
1561 | |||
1562 | mutex_lock(&dev->lock); | ||
1563 | dev->freq = f->frequency; | ||
1564 | |||
1565 | /* I need to mute audio here */ | ||
1566 | ctrl.id = V4L2_CID_AUDIO_MUTE; | ||
1567 | ctrl.value = 1; | ||
1568 | cx23885_set_control(dev, &ctrl); | ||
1569 | |||
1570 | /* If HVR1850 */ | ||
1571 | dprintk(1, "%s() frequency=%d tuner=%d std=0x%llx\n", __func__, | ||
1572 | params.frequency, f->tuner, params.std); | ||
1573 | |||
1574 | vfe = videobuf_dvb_get_frontend(&dev->ts2.frontends, 1); | ||
1575 | if (!vfe) | ||
1576 | err = -EINVAL; | ||
1577 | |||
1578 | fe = vfe->dvb.frontend; | ||
1579 | |||
1580 | if (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) | ||
1581 | fe = &dev->ts1.analog_fe; | ||
1582 | |||
1583 | if (fe && fe->ops.tuner_ops.set_analog_params) { | ||
1584 | call_all(dev, core, s_std, dev->tvnorm); | ||
1585 | fe->ops.tuner_ops.set_analog_params(fe, ¶ms); | ||
1586 | } | ||
1587 | else | ||
1588 | printk(KERN_ERR "%s() No analog tuner, aborting\n", __func__); | ||
1589 | |||
1590 | /* When changing channels it is required to reset TVAUDIO */ | ||
1591 | msleep(100); | ||
1592 | |||
1593 | /* I need to unmute audio here */ | ||
1594 | ctrl.value = 0; | ||
1595 | cx23885_set_control(dev, &ctrl); | ||
1596 | |||
1597 | mutex_unlock(&dev->lock); | ||
1598 | |||
1599 | return 0; | ||
1600 | } | ||
1601 | |||
1602 | int cx23885_set_frequency(struct file *file, void *priv, | ||
1603 | struct v4l2_frequency *f) | ||
1494 | { | 1604 | { |
1495 | struct cx23885_fh *fh = priv; | 1605 | struct cx23885_fh *fh = priv; |
1496 | struct cx23885_dev *dev = fh->dev; | 1606 | struct cx23885_dev *dev = fh->dev; |
1607 | int ret; | ||
1497 | 1608 | ||
1498 | if (unlikely(0 == fh->radio && f->type != V4L2_TUNER_ANALOG_TV)) | 1609 | switch (dev->board) { |
1499 | return -EINVAL; | 1610 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
1500 | if (unlikely(1 == fh->radio && f->type != V4L2_TUNER_RADIO)) | 1611 | ret = cx23885_set_freq_via_ops(dev, f); |
1501 | return -EINVAL; | 1612 | break; |
1613 | default: | ||
1614 | ret = cx23885_set_freq(dev, f); | ||
1615 | } | ||
1502 | 1616 | ||
1503 | return | 1617 | return ret; |
1504 | cx23885_set_freq(dev, f); | 1618 | } |
1619 | |||
1620 | static int vidioc_s_frequency(struct file *file, void *priv, | ||
1621 | struct v4l2_frequency *f) | ||
1622 | { | ||
1623 | return cx23885_set_frequency(file, priv, f); | ||
1505 | } | 1624 | } |
1506 | 1625 | ||
1507 | /* ----------------------------------------------------------- */ | 1626 | /* ----------------------------------------------------------- */ |
@@ -1613,6 +1732,8 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { | |||
1613 | .vidioc_qbuf = vidioc_qbuf, | 1732 | .vidioc_qbuf = vidioc_qbuf, |
1614 | .vidioc_dqbuf = vidioc_dqbuf, | 1733 | .vidioc_dqbuf = vidioc_dqbuf, |
1615 | .vidioc_s_std = vidioc_s_std, | 1734 | .vidioc_s_std = vidioc_s_std, |
1735 | .vidioc_g_std = vidioc_g_std, | ||
1736 | .vidioc_querystd = vidioc_g_std, | ||
1616 | .vidioc_enum_input = vidioc_enum_input, | 1737 | .vidioc_enum_input = vidioc_enum_input, |
1617 | .vidioc_g_input = vidioc_g_input, | 1738 | .vidioc_g_input = vidioc_g_input, |
1618 | .vidioc_s_input = vidioc_s_input, | 1739 | .vidioc_s_input = vidioc_s_input, |
diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index b49036fe3ffd..f020f0568df4 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h | |||
@@ -87,6 +87,8 @@ | |||
87 | #define CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF 30 | 87 | #define CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF 30 |
88 | #define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000 31 | 88 | #define CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000 31 |
89 | #define CX23885_BOARD_MPX885 32 | 89 | #define CX23885_BOARD_MPX885 32 |
90 | #define CX23885_BOARD_MYGICA_X8507 33 | ||
91 | #define CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL 34 | ||
90 | 92 | ||
91 | #define GPIO_0 0x00000001 | 93 | #define GPIO_0 0x00000001 |
92 | #define GPIO_1 0x00000002 | 94 | #define GPIO_1 0x00000002 |
@@ -226,6 +228,8 @@ struct cx23885_board { | |||
226 | u32 clk_freq; | 228 | u32 clk_freq; |
227 | struct cx23885_input input[MAX_CX23885_INPUT]; | 229 | struct cx23885_input input[MAX_CX23885_INPUT]; |
228 | int ci_type; /* for NetUP */ | 230 | int ci_type; /* for NetUP */ |
231 | /* Force bottom field first during DMA (888 workaround) */ | ||
232 | u32 force_bff; | ||
229 | }; | 233 | }; |
230 | 234 | ||
231 | struct cx23885_subid { | 235 | struct cx23885_subid { |
@@ -310,6 +314,9 @@ struct cx23885_tsport { | |||
310 | u32 num_frontends; | 314 | u32 num_frontends; |
311 | void (*gate_ctrl)(struct cx23885_tsport *port, int open); | 315 | void (*gate_ctrl)(struct cx23885_tsport *port, int open); |
312 | void *port_priv; | 316 | void *port_priv; |
317 | |||
318 | /* Workaround for a temp dvb_frontend that the tuner can attached to */ | ||
319 | struct dvb_frontend analog_fe; | ||
313 | }; | 320 | }; |
314 | 321 | ||
315 | struct cx23885_kernel_ir { | 322 | struct cx23885_kernel_ir { |
@@ -574,6 +581,13 @@ extern void cx23885_video_unregister(struct cx23885_dev *dev); | |||
574 | extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status); | 581 | extern int cx23885_video_irq(struct cx23885_dev *dev, u32 status); |
575 | extern void cx23885_video_wakeup(struct cx23885_dev *dev, | 582 | extern void cx23885_video_wakeup(struct cx23885_dev *dev, |
576 | struct cx23885_dmaqueue *q, u32 count); | 583 | struct cx23885_dmaqueue *q, u32 count); |
584 | int cx23885_enum_input(struct cx23885_dev *dev, struct v4l2_input *i); | ||
585 | int cx23885_set_input(struct file *file, void *priv, unsigned int i); | ||
586 | int cx23885_get_input(struct file *file, void *priv, unsigned int *i); | ||
587 | int cx23885_set_frequency(struct file *file, void *priv, struct v4l2_frequency *f); | ||
588 | int cx23885_set_control(struct cx23885_dev *dev, struct v4l2_control *ctl); | ||
589 | int cx23885_get_control(struct cx23885_dev *dev, struct v4l2_control *ctl); | ||
590 | int cx23885_set_tvnorm(struct cx23885_dev *dev, v4l2_std_id norm); | ||
577 | 591 | ||
578 | /* ----------------------------------------------------------- */ | 592 | /* ----------------------------------------------------------- */ |
579 | /* cx23885-vbi.c */ | 593 | /* cx23885-vbi.c */ |
diff --git a/drivers/media/video/cx25821/cx25821-alsa.c b/drivers/media/video/cx25821/cx25821-alsa.c index 58be4f3bb3cb..03cfac476b03 100644 --- a/drivers/media/video/cx25821/cx25821-alsa.c +++ b/drivers/media/video/cx25821/cx25821-alsa.c | |||
@@ -176,8 +176,7 @@ static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip) | |||
176 | 176 | ||
177 | /* Set the input mode to 16-bit */ | 177 | /* Set the input mode to 16-bit */ |
178 | tmp = cx_read(AUD_A_CFG); | 178 | tmp = cx_read(AUD_A_CFG); |
179 | cx_write(AUD_A_CFG, | 179 | cx_write(AUD_A_CFG, tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE | |
180 | tmp | FLD_AUD_DST_PK_MODE | FLD_AUD_DST_ENABLE | | ||
181 | FLD_AUD_CLK_ENABLE); | 180 | FLD_AUD_CLK_ENABLE); |
182 | 181 | ||
183 | /* | 182 | /* |
@@ -188,9 +187,8 @@ static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip) | |||
188 | */ | 187 | */ |
189 | 188 | ||
190 | /* Enables corresponding bits at AUD_INT_STAT */ | 189 | /* Enables corresponding bits at AUD_INT_STAT */ |
191 | cx_write(AUD_A_INT_MSK, | 190 | cx_write(AUD_A_INT_MSK, FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | |
192 | FLD_AUD_DST_RISCI1 | FLD_AUD_DST_OF | FLD_AUD_DST_SYNC | | 191 | FLD_AUD_DST_SYNC | FLD_AUD_DST_OPC_ERR); |
193 | FLD_AUD_DST_OPC_ERR); | ||
194 | 192 | ||
195 | /* Clean any pending interrupt bits already set */ | 193 | /* Clean any pending interrupt bits already set */ |
196 | cx_write(AUD_A_INT_STAT, ~0); | 194 | cx_write(AUD_A_INT_STAT, ~0); |
@@ -200,8 +198,8 @@ static int _cx25821_start_audio_dma(struct cx25821_audio_dev *chip) | |||
200 | 198 | ||
201 | /* Turn on audio downstream fifo and risc enable 0x101 */ | 199 | /* Turn on audio downstream fifo and risc enable 0x101 */ |
202 | tmp = cx_read(AUD_INT_DMA_CTL); | 200 | tmp = cx_read(AUD_INT_DMA_CTL); |
203 | cx_set(AUD_INT_DMA_CTL, | 201 | cx_set(AUD_INT_DMA_CTL, tmp | |
204 | tmp | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN)); | 202 | (FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN)); |
205 | 203 | ||
206 | mdelay(100); | 204 | mdelay(100); |
207 | return 0; | 205 | return 0; |
@@ -220,9 +218,8 @@ static int _cx25821_stop_audio_dma(struct cx25821_audio_dev *chip) | |||
220 | 218 | ||
221 | /* disable irqs */ | 219 | /* disable irqs */ |
222 | cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT); | 220 | cx_clear(PCI_INT_MSK, PCI_MSK_AUD_INT); |
223 | cx_clear(AUD_A_INT_MSK, | 221 | cx_clear(AUD_A_INT_MSK, AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | |
224 | AUD_INT_OPC_ERR | AUD_INT_DN_SYNC | AUD_INT_DN_RISCI2 | | 222 | AUD_INT_DN_RISCI2 | AUD_INT_DN_RISCI1); |
225 | AUD_INT_DN_RISCI1); | ||
226 | 223 | ||
227 | return 0; | 224 | return 0; |
228 | } | 225 | } |
@@ -234,15 +231,15 @@ static int _cx25821_stop_audio_dma(struct cx25821_audio_dev *chip) | |||
234 | */ | 231 | */ |
235 | static char *cx25821_aud_irqs[32] = { | 232 | static char *cx25821_aud_irqs[32] = { |
236 | "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */ | 233 | "dn_risci1", "up_risci1", "rds_dn_risc1", /* 0-2 */ |
237 | NULL, /* reserved */ | 234 | NULL, /* reserved */ |
238 | "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */ | 235 | "dn_risci2", "up_risci2", "rds_dn_risc2", /* 4-6 */ |
239 | NULL, /* reserved */ | 236 | NULL, /* reserved */ |
240 | "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */ | 237 | "dnf_of", "upf_uf", "rds_dnf_uf", /* 8-10 */ |
241 | NULL, /* reserved */ | 238 | NULL, /* reserved */ |
242 | "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */ | 239 | "dn_sync", "up_sync", "rds_dn_sync", /* 12-14 */ |
243 | NULL, /* reserved */ | 240 | NULL, /* reserved */ |
244 | "opc_err", "par_err", "rip_err", /* 16-18 */ | 241 | "opc_err", "par_err", "rip_err", /* 16-18 */ |
245 | "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */ | 242 | "pci_abort", "ber_irq", "mchg_irq" /* 19-21 */ |
246 | }; | 243 | }; |
247 | 244 | ||
248 | /* | 245 | /* |
@@ -258,10 +255,8 @@ static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status, | |||
258 | 255 | ||
259 | cx_write(AUD_A_INT_STAT, status); | 256 | cx_write(AUD_A_INT_STAT, status); |
260 | if (debug > 1 || (status & mask & ~0xff)) | 257 | if (debug > 1 || (status & mask & ~0xff)) |
261 | cx25821_print_irqbits(dev->name, "irq aud", | 258 | cx25821_print_irqbits(dev->name, "irq aud", cx25821_aud_irqs, |
262 | cx25821_aud_irqs, | 259 | ARRAY_SIZE(cx25821_aud_irqs), status, mask); |
263 | ARRAY_SIZE(cx25821_aud_irqs), status, | ||
264 | mask); | ||
265 | 260 | ||
266 | /* risc op code error */ | 261 | /* risc op code error */ |
267 | if (status & AUD_INT_OPC_ERR) { | 262 | if (status & AUD_INT_OPC_ERR) { |
@@ -270,8 +265,7 @@ static void cx25821_aud_irq(struct cx25821_audio_dev *chip, u32 status, | |||
270 | cx_clear(AUD_INT_DMA_CTL, | 265 | cx_clear(AUD_INT_DMA_CTL, |
271 | FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN); | 266 | FLD_AUD_DST_A_RISC_EN | FLD_AUD_DST_A_FIFO_EN); |
272 | cx25821_sram_channel_dump_audio(dev, | 267 | cx25821_sram_channel_dump_audio(dev, |
273 | &cx25821_sram_channels | 268 | &cx25821_sram_channels[AUDIO_SRAM_CHANNEL]); |
274 | [AUDIO_SRAM_CHANNEL]); | ||
275 | } | 269 | } |
276 | if (status & AUD_INT_DN_SYNC) { | 270 | if (status & AUD_INT_DN_SYNC) { |
277 | pr_warn("WARNING %s: Downstream sync error!\n", dev->name); | 271 | pr_warn("WARNING %s: Downstream sync error!\n", dev->name); |
@@ -317,8 +311,9 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id) | |||
317 | cx25821_aud_irq(chip, audint_status, | 311 | cx25821_aud_irq(chip, audint_status, |
318 | audint_mask); | 312 | audint_mask); |
319 | break; | 313 | break; |
320 | } else | 314 | } else { |
321 | goto out; | 315 | goto out; |
316 | } | ||
322 | } | 317 | } |
323 | 318 | ||
324 | handled = 1; | 319 | handled = 1; |
@@ -361,9 +356,8 @@ static int dsp_buffer_free(struct cx25821_audio_dev *chip) | |||
361 | */ | 356 | */ |
362 | #define DEFAULT_FIFO_SIZE 384 | 357 | #define DEFAULT_FIFO_SIZE 384 |
363 | static struct snd_pcm_hardware snd_cx25821_digital_hw = { | 358 | static struct snd_pcm_hardware snd_cx25821_digital_hw = { |
364 | .info = SNDRV_PCM_INFO_MMAP | | 359 | .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | |
365 | SNDRV_PCM_INFO_INTERLEAVED | | 360 | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID, |
366 | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID, | ||
367 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 361 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
368 | 362 | ||
369 | .rates = SNDRV_PCM_RATE_48000, | 363 | .rates = SNDRV_PCM_RATE_48000, |
@@ -396,8 +390,8 @@ static int snd_cx25821_pcm_open(struct snd_pcm_substream *substream) | |||
396 | return -ENODEV; | 390 | return -ENODEV; |
397 | } | 391 | } |
398 | 392 | ||
399 | err = | 393 | err = snd_pcm_hw_constraint_pow2(runtime, 0, |
400 | snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIODS); | 394 | SNDRV_PCM_HW_PARAM_PERIODS); |
401 | if (err < 0) | 395 | if (err < 0) |
402 | goto _error; | 396 | goto _error; |
403 | 397 | ||
@@ -468,8 +462,7 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, | |||
468 | dma = &buf->dma; | 462 | dma = &buf->dma; |
469 | videobuf_dma_init(dma); | 463 | videobuf_dma_init(dma); |
470 | ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, | 464 | ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE, |
471 | (PAGE_ALIGN(chip->dma_size) >> | 465 | (PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT)); |
472 | PAGE_SHIFT)); | ||
473 | if (ret < 0) | 466 | if (ret < 0) |
474 | goto error; | 467 | goto error; |
475 | 468 | ||
@@ -477,10 +470,8 @@ static int snd_cx25821_hw_params(struct snd_pcm_substream *substream, | |||
477 | if (ret < 0) | 470 | if (ret < 0) |
478 | goto error; | 471 | goto error; |
479 | 472 | ||
480 | ret = | 473 | ret = cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist, |
481 | cx25821_risc_databuffer_audio(chip->pci, &buf->risc, dma->sglist, | 474 | chip->period_size, chip->num_periods, 1); |
482 | chip->period_size, chip->num_periods, | ||
483 | 1); | ||
484 | if (ret < 0) { | 475 | if (ret < 0) { |
485 | pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n"); | 476 | pr_info("DEBUG: ERROR after cx25821_risc_databuffer_audio()\n"); |
486 | goto error; | 477 | goto error; |
@@ -686,7 +677,7 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) | |||
686 | } | 677 | } |
687 | 678 | ||
688 | err = snd_card_create(index[devno], id[devno], THIS_MODULE, | 679 | err = snd_card_create(index[devno], id[devno], THIS_MODULE, |
689 | sizeof(struct cx25821_audio_dev), &card); | 680 | sizeof(struct cx25821_audio_dev), &card); |
690 | if (err < 0) { | 681 | if (err < 0) { |
691 | pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n", | 682 | pr_info("DEBUG ERROR: cannot create snd_card_new in %s\n", |
692 | __func__); | 683 | __func__); |
@@ -711,8 +702,8 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) | |||
711 | IRQF_SHARED, chip->dev->name, chip); | 702 | IRQF_SHARED, chip->dev->name, chip); |
712 | 703 | ||
713 | if (err < 0) { | 704 | if (err < 0) { |
714 | pr_err("ERROR %s: can't get IRQ %d for ALSA\n", | 705 | pr_err("ERROR %s: can't get IRQ %d for ALSA\n", chip->dev->name, |
715 | chip->dev->name, dev->pci->irq); | 706 | dev->pci->irq); |
716 | goto error; | 707 | goto error; |
717 | } | 708 | } |
718 | 709 | ||
@@ -730,8 +721,8 @@ static int cx25821_audio_initdev(struct cx25821_dev *dev) | |||
730 | chip->iobase, chip->irq); | 721 | chip->iobase, chip->irq); |
731 | strcpy(card->mixername, "CX25821"); | 722 | strcpy(card->mixername, "CX25821"); |
732 | 723 | ||
733 | pr_info("%s/%i: ALSA support for cx25821 boards\n", | 724 | pr_info("%s/%i: ALSA support for cx25821 boards\n", card->driver, |
734 | card->driver, devno); | 725 | devno); |
735 | 726 | ||
736 | err = snd_card_register(card); | 727 | err = snd_card_register(card); |
737 | if (err < 0) { | 728 | if (err < 0) { |
diff --git a/drivers/media/video/cx25821/cx25821-audio-upstream.c b/drivers/media/video/cx25821/cx25821-audio-upstream.c index c20d6dece154..20c7ca3351a8 100644 --- a/drivers/media/video/cx25821/cx25821-audio-upstream.c +++ b/drivers/media/video/cx25821/cx25821-audio-upstream.c | |||
@@ -107,7 +107,7 @@ static __le32 *cx25821_risc_field_upstream_audio(struct cx25821_dev *dev, | |||
107 | { | 107 | { |
108 | unsigned int line; | 108 | unsigned int line; |
109 | struct sram_channel *sram_ch = | 109 | struct sram_channel *sram_ch = |
110 | dev->channels[dev->_audio_upstream_channel].sram_channels; | 110 | dev->channels[dev->_audio_upstream_channel].sram_channels; |
111 | int offset = 0; | 111 | int offset = 0; |
112 | 112 | ||
113 | /* scan lines */ | 113 | /* scan lines */ |
@@ -175,10 +175,8 @@ int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev, | |||
175 | } | 175 | } |
176 | 176 | ||
177 | rp = cx25821_risc_field_upstream_audio(dev, rp, | 177 | rp = cx25821_risc_field_upstream_audio(dev, rp, |
178 | dev-> | 178 | dev->_audiodata_buf_phys_addr + databuf_offset, |
179 | _audiodata_buf_phys_addr | 179 | bpl, fifo_enable); |
180 | + databuf_offset, bpl, | ||
181 | fifo_enable); | ||
182 | 180 | ||
183 | if (USE_RISC_NOOP_AUDIO) { | 181 | if (USE_RISC_NOOP_AUDIO) { |
184 | for (i = 0; i < NUM_NO_OPS; i++) | 182 | for (i = 0; i < NUM_NO_OPS; i++) |
@@ -193,7 +191,7 @@ int cx25821_risc_buffer_upstream_audio(struct cx25821_dev *dev, | |||
193 | 191 | ||
194 | /* Recalculate virtual address based on frame index */ | 192 | /* Recalculate virtual address based on frame index */ |
195 | rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 + | 193 | rp = dev->_risc_virt_addr + RISC_SYNC_INSTRUCTION_SIZE / 4 + |
196 | (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4); | 194 | (AUDIO_RISC_DMA_BUF_SIZE * (frame + 1) / 4); |
197 | } | 195 | } |
198 | 196 | ||
199 | return 0; | 197 | return 0; |
@@ -218,7 +216,7 @@ void cx25821_free_memory_audio(struct cx25821_dev *dev) | |||
218 | void cx25821_stop_upstream_audio(struct cx25821_dev *dev) | 216 | void cx25821_stop_upstream_audio(struct cx25821_dev *dev) |
219 | { | 217 | { |
220 | struct sram_channel *sram_ch = | 218 | struct sram_channel *sram_ch = |
221 | dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels; | 219 | dev->channels[AUDIO_UPSTREAM_SRAM_CHANNEL_B].sram_channels; |
222 | u32 tmp = 0; | 220 | u32 tmp = 0; |
223 | 221 | ||
224 | if (!dev->_audio_is_running) { | 222 | if (!dev->_audio_is_running) { |
@@ -286,14 +284,14 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, | |||
286 | } else { | 284 | } else { |
287 | if (!(myfile->f_op)) { | 285 | if (!(myfile->f_op)) { |
288 | pr_err("%s(): File has no file operations registered!\n", | 286 | pr_err("%s(): File has no file operations registered!\n", |
289 | __func__); | 287 | __func__); |
290 | filp_close(myfile, NULL); | 288 | filp_close(myfile, NULL); |
291 | return -EIO; | 289 | return -EIO; |
292 | } | 290 | } |
293 | 291 | ||
294 | if (!myfile->f_op->read) { | 292 | if (!myfile->f_op->read) { |
295 | pr_err("%s(): File has no READ operations registered!\n", | 293 | pr_err("%s(): File has no READ operations registered!\n", |
296 | __func__); | 294 | __func__); |
297 | filp_close(myfile, NULL); | 295 | filp_close(myfile, NULL); |
298 | return -EIO; | 296 | return -EIO; |
299 | } | 297 | } |
@@ -305,14 +303,14 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, | |||
305 | for (i = 0; i < dev->_audio_lines_count; i++) { | 303 | for (i = 0; i < dev->_audio_lines_count; i++) { |
306 | pos = file_offset; | 304 | pos = file_offset; |
307 | 305 | ||
308 | vfs_read_retval = | 306 | vfs_read_retval = vfs_read(myfile, mybuf, line_size, |
309 | vfs_read(myfile, mybuf, line_size, &pos); | 307 | &pos); |
310 | 308 | ||
311 | if (vfs_read_retval > 0 && vfs_read_retval == line_size | 309 | if (vfs_read_retval > 0 && vfs_read_retval == line_size |
312 | && dev->_audiodata_buf_virt_addr != NULL) { | 310 | && dev->_audiodata_buf_virt_addr != NULL) { |
313 | memcpy((void *)(dev->_audiodata_buf_virt_addr + | 311 | memcpy((void *)(dev->_audiodata_buf_virt_addr + |
314 | frame_offset / 4), mybuf, | 312 | frame_offset / 4), mybuf, |
315 | vfs_read_retval); | 313 | vfs_read_retval); |
316 | } | 314 | } |
317 | 315 | ||
318 | file_offset += vfs_read_retval; | 316 | file_offset += vfs_read_retval; |
@@ -328,8 +326,8 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, | |||
328 | if (i > 0) | 326 | if (i > 0) |
329 | dev->_audioframe_count++; | 327 | dev->_audioframe_count++; |
330 | 328 | ||
331 | dev->_audiofile_status = | 329 | dev->_audiofile_status = (vfs_read_retval == line_size) ? |
332 | (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | 330 | IN_PROGRESS : END_OF_FILE; |
333 | 331 | ||
334 | set_fs(old_fs); | 332 | set_fs(old_fs); |
335 | filp_close(myfile, NULL); | 333 | filp_close(myfile, NULL); |
@@ -340,12 +338,12 @@ int cx25821_get_audio_data(struct cx25821_dev *dev, | |||
340 | 338 | ||
341 | static void cx25821_audioups_handler(struct work_struct *work) | 339 | static void cx25821_audioups_handler(struct work_struct *work) |
342 | { | 340 | { |
343 | struct cx25821_dev *dev = | 341 | struct cx25821_dev *dev = container_of(work, struct cx25821_dev, |
344 | container_of(work, struct cx25821_dev, _audio_work_entry); | 342 | _audio_work_entry); |
345 | 343 | ||
346 | if (!dev) { | 344 | if (!dev) { |
347 | pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", | 345 | pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", |
348 | __func__); | 346 | __func__); |
349 | return; | 347 | return; |
350 | } | 348 | } |
351 | 349 | ||
@@ -370,19 +368,19 @@ int cx25821_openfile_audio(struct cx25821_dev *dev, | |||
370 | if (IS_ERR(myfile)) { | 368 | if (IS_ERR(myfile)) { |
371 | const int open_errno = -PTR_ERR(myfile); | 369 | const int open_errno = -PTR_ERR(myfile); |
372 | pr_err("%s(): ERROR opening file(%s) with errno = %d!\n", | 370 | pr_err("%s(): ERROR opening file(%s) with errno = %d!\n", |
373 | __func__, dev->_audiofilename, open_errno); | 371 | __func__, dev->_audiofilename, open_errno); |
374 | return PTR_ERR(myfile); | 372 | return PTR_ERR(myfile); |
375 | } else { | 373 | } else { |
376 | if (!(myfile->f_op)) { | 374 | if (!(myfile->f_op)) { |
377 | pr_err("%s(): File has no file operations registered!\n", | 375 | pr_err("%s(): File has no file operations registered!\n", |
378 | __func__); | 376 | __func__); |
379 | filp_close(myfile, NULL); | 377 | filp_close(myfile, NULL); |
380 | return -EIO; | 378 | return -EIO; |
381 | } | 379 | } |
382 | 380 | ||
383 | if (!myfile->f_op->read) { | 381 | if (!myfile->f_op->read) { |
384 | pr_err("%s(): File has no READ operations registered!\n", | 382 | pr_err("%s(): File has no READ operations registered!\n", |
385 | __func__); | 383 | __func__); |
386 | filp_close(myfile, NULL); | 384 | filp_close(myfile, NULL); |
387 | return -EIO; | 385 | return -EIO; |
388 | } | 386 | } |
@@ -395,12 +393,12 @@ int cx25821_openfile_audio(struct cx25821_dev *dev, | |||
395 | for (i = 0; i < dev->_audio_lines_count; i++) { | 393 | for (i = 0; i < dev->_audio_lines_count; i++) { |
396 | pos = offset; | 394 | pos = offset; |
397 | 395 | ||
398 | vfs_read_retval = | 396 | vfs_read_retval = vfs_read(myfile, mybuf, |
399 | vfs_read(myfile, mybuf, line_size, &pos); | 397 | line_size, &pos); |
400 | 398 | ||
401 | if (vfs_read_retval > 0 | 399 | if (vfs_read_retval > 0 && |
402 | && vfs_read_retval == line_size | 400 | vfs_read_retval == line_size && |
403 | && dev->_audiodata_buf_virt_addr != NULL) { | 401 | dev->_audiodata_buf_virt_addr != NULL) { |
404 | memcpy((void *)(dev-> | 402 | memcpy((void *)(dev-> |
405 | _audiodata_buf_virt_addr | 403 | _audiodata_buf_virt_addr |
406 | + offset / 4), mybuf, | 404 | + offset / 4), mybuf, |
@@ -423,8 +421,8 @@ int cx25821_openfile_audio(struct cx25821_dev *dev, | |||
423 | break; | 421 | break; |
424 | } | 422 | } |
425 | 423 | ||
426 | dev->_audiofile_status = | 424 | dev->_audiofile_status = (vfs_read_retval == line_size) ? |
427 | (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | 425 | IN_PROGRESS : END_OF_FILE; |
428 | 426 | ||
429 | set_fs(old_fs); | 427 | set_fs(old_fs); |
430 | myfile->f_pos = 0; | 428 | myfile->f_pos = 0; |
@@ -444,9 +442,8 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, | |||
444 | 442 | ||
445 | cx25821_free_memory_audio(dev); | 443 | cx25821_free_memory_audio(dev); |
446 | 444 | ||
447 | dev->_risc_virt_addr = | 445 | dev->_risc_virt_addr = pci_alloc_consistent(dev->pci, |
448 | pci_alloc_consistent(dev->pci, dev->audio_upstream_riscbuf_size, | 446 | dev->audio_upstream_riscbuf_size, &dma_addr); |
449 | &dma_addr); | ||
450 | dev->_risc_virt_start_addr = dev->_risc_virt_addr; | 447 | dev->_risc_virt_start_addr = dev->_risc_virt_addr; |
451 | dev->_risc_phys_start_addr = dma_addr; | 448 | dev->_risc_phys_start_addr = dma_addr; |
452 | dev->_risc_phys_addr = dma_addr; | 449 | dev->_risc_phys_addr = dma_addr; |
@@ -454,22 +451,21 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, | |||
454 | 451 | ||
455 | if (!dev->_risc_virt_addr) { | 452 | if (!dev->_risc_virt_addr) { |
456 | printk(KERN_DEBUG | 453 | printk(KERN_DEBUG |
457 | pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n")); | 454 | pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for RISC program! Returning\n")); |
458 | return -ENOMEM; | 455 | return -ENOMEM; |
459 | } | 456 | } |
460 | /* Clear out memory at address */ | 457 | /* Clear out memory at address */ |
461 | memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size); | 458 | memset(dev->_risc_virt_addr, 0, dev->_audiorisc_size); |
462 | 459 | ||
463 | /* For Audio Data buffer allocation */ | 460 | /* For Audio Data buffer allocation */ |
464 | dev->_audiodata_buf_virt_addr = | 461 | dev->_audiodata_buf_virt_addr = pci_alloc_consistent(dev->pci, |
465 | pci_alloc_consistent(dev->pci, dev->audio_upstream_databuf_size, | 462 | dev->audio_upstream_databuf_size, &data_dma_addr); |
466 | &data_dma_addr); | ||
467 | dev->_audiodata_buf_phys_addr = data_dma_addr; | 463 | dev->_audiodata_buf_phys_addr = data_dma_addr; |
468 | dev->_audiodata_buf_size = dev->audio_upstream_databuf_size; | 464 | dev->_audiodata_buf_size = dev->audio_upstream_databuf_size; |
469 | 465 | ||
470 | if (!dev->_audiodata_buf_virt_addr) { | 466 | if (!dev->_audiodata_buf_virt_addr) { |
471 | printk(KERN_DEBUG | 467 | printk(KERN_DEBUG |
472 | pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n")); | 468 | pr_fmt("ERROR: pci_alloc_consistent() FAILED to allocate memory for data buffer! Returning\n")); |
473 | return -ENOMEM; | 469 | return -ENOMEM; |
474 | } | 470 | } |
475 | /* Clear out memory at address */ | 471 | /* Clear out memory at address */ |
@@ -480,12 +476,11 @@ static int cx25821_audio_upstream_buffer_prepare(struct cx25821_dev *dev, | |||
480 | return ret; | 476 | return ret; |
481 | 477 | ||
482 | /* Creating RISC programs */ | 478 | /* Creating RISC programs */ |
483 | ret = | 479 | ret = cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl, |
484 | cx25821_risc_buffer_upstream_audio(dev, dev->pci, bpl, | 480 | dev->_audio_lines_count); |
485 | dev->_audio_lines_count); | ||
486 | if (ret < 0) { | 481 | if (ret < 0) { |
487 | printk(KERN_DEBUG | 482 | printk(KERN_DEBUG |
488 | pr_fmt("ERROR creating audio upstream RISC programs!\n")); | 483 | pr_fmt("ERROR creating audio upstream RISC programs!\n")); |
489 | goto error; | 484 | goto error; |
490 | } | 485 | } |
491 | 486 | ||
@@ -533,9 +528,9 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, | |||
533 | 528 | ||
534 | if (dev->_risc_virt_start_addr != NULL) { | 529 | if (dev->_risc_virt_start_addr != NULL) { |
535 | risc_phys_jump_addr = | 530 | risc_phys_jump_addr = |
536 | dev->_risc_phys_start_addr + | 531 | dev->_risc_phys_start_addr + |
537 | RISC_SYNC_INSTRUCTION_SIZE + | 532 | RISC_SYNC_INSTRUCTION_SIZE + |
538 | AUDIO_RISC_DMA_BUF_SIZE; | 533 | AUDIO_RISC_DMA_BUF_SIZE; |
539 | 534 | ||
540 | rp = cx25821_risc_field_upstream_audio(dev, | 535 | rp = cx25821_risc_field_upstream_audio(dev, |
541 | dev->_risc_virt_start_addr + 1, | 536 | dev->_risc_virt_start_addr + 1, |
@@ -632,7 +627,7 @@ static void cx25821_wait_fifo_enable(struct cx25821_dev *dev, | |||
632 | /* 10 millisecond timeout */ | 627 | /* 10 millisecond timeout */ |
633 | if (count++ > 1000) { | 628 | if (count++ > 1000) { |
634 | pr_err("ERROR: %s() fifo is NOT turned on. Timeout!\n", | 629 | pr_err("ERROR: %s() fifo is NOT turned on. Timeout!\n", |
635 | __func__); | 630 | __func__); |
636 | return; | 631 | return; |
637 | } | 632 | } |
638 | 633 | ||
@@ -661,9 +656,9 @@ int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, | |||
661 | 656 | ||
662 | /* Set the input mode to 16-bit */ | 657 | /* Set the input mode to 16-bit */ |
663 | tmp = cx_read(sram_ch->aud_cfg); | 658 | tmp = cx_read(sram_ch->aud_cfg); |
664 | tmp |= | 659 | tmp |= FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE | |
665 | FLD_AUD_SRC_ENABLE | FLD_AUD_DST_PK_MODE | FLD_AUD_CLK_ENABLE | | 660 | FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | |
666 | FLD_AUD_MASTER_MODE | FLD_AUD_CLK_SELECT_PLL_D | FLD_AUD_SONY_MODE; | 661 | FLD_AUD_SONY_MODE; |
667 | cx_write(sram_ch->aud_cfg, tmp); | 662 | cx_write(sram_ch->aud_cfg, tmp); |
668 | 663 | ||
669 | /* Read and write back the interrupt status register to clear it */ | 664 | /* Read and write back the interrupt status register to clear it */ |
@@ -678,12 +673,11 @@ int cx25821_start_audio_dma_upstream(struct cx25821_dev *dev, | |||
678 | tmp = cx_read(sram_ch->int_msk); | 673 | tmp = cx_read(sram_ch->int_msk); |
679 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); | 674 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); |
680 | 675 | ||
681 | err = | 676 | err = request_irq(dev->pci->irq, cx25821_upstream_irq_audio, |
682 | request_irq(dev->pci->irq, cx25821_upstream_irq_audio, | ||
683 | IRQF_SHARED, dev->name, dev); | 677 | IRQF_SHARED, dev->name, dev); |
684 | if (err < 0) { | 678 | if (err < 0) { |
685 | pr_err("%s: can't get upstream IRQ %d\n", | 679 | pr_err("%s: can't get upstream IRQ %d\n", dev->name, |
686 | dev->name, dev->pci->irq); | 680 | dev->pci->irq); |
687 | goto fail_irq; | 681 | goto fail_irq; |
688 | } | 682 | } |
689 | 683 | ||
@@ -726,7 +720,7 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) | |||
726 | 720 | ||
727 | if (!dev->_irq_audio_queues) { | 721 | if (!dev->_irq_audio_queues) { |
728 | printk(KERN_DEBUG | 722 | printk(KERN_DEBUG |
729 | pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n")); | 723 | pr_fmt("ERROR: create_singlethread_workqueue() for Audio FAILED!\n")); |
730 | return -ENOMEM; | 724 | return -ENOMEM; |
731 | } | 725 | } |
732 | 726 | ||
@@ -739,33 +733,30 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) | |||
739 | 733 | ||
740 | if (dev->input_audiofilename) { | 734 | if (dev->input_audiofilename) { |
741 | str_length = strlen(dev->input_audiofilename); | 735 | str_length = strlen(dev->input_audiofilename); |
742 | dev->_audiofilename = kmalloc(str_length + 1, GFP_KERNEL); | 736 | dev->_audiofilename = kmemdup(dev->input_audiofilename, |
737 | str_length + 1, GFP_KERNEL); | ||
743 | 738 | ||
744 | if (!dev->_audiofilename) | 739 | if (!dev->_audiofilename) |
745 | goto error; | 740 | goto error; |
746 | 741 | ||
747 | memcpy(dev->_audiofilename, dev->input_audiofilename, | ||
748 | str_length + 1); | ||
749 | |||
750 | /* Default if filename is empty string */ | 742 | /* Default if filename is empty string */ |
751 | if (strcmp(dev->input_audiofilename, "") == 0) | 743 | if (strcmp(dev->input_audiofilename, "") == 0) |
752 | dev->_audiofilename = "/root/audioGOOD.wav"; | 744 | dev->_audiofilename = "/root/audioGOOD.wav"; |
753 | } else { | 745 | } else { |
754 | str_length = strlen(_defaultAudioName); | 746 | str_length = strlen(_defaultAudioName); |
755 | dev->_audiofilename = kmalloc(str_length + 1, GFP_KERNEL); | 747 | dev->_audiofilename = kmemdup(_defaultAudioName, |
748 | str_length + 1, GFP_KERNEL); | ||
756 | 749 | ||
757 | if (!dev->_audiofilename) | 750 | if (!dev->_audiofilename) |
758 | goto error; | 751 | goto error; |
759 | |||
760 | memcpy(dev->_audiofilename, _defaultAudioName, str_length + 1); | ||
761 | } | 752 | } |
762 | 753 | ||
763 | retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch, | 754 | retval = cx25821_sram_channel_setup_upstream_audio(dev, sram_ch, |
764 | _line_size, 0); | 755 | _line_size, 0); |
765 | 756 | ||
766 | dev->audio_upstream_riscbuf_size = | 757 | dev->audio_upstream_riscbuf_size = |
767 | AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS + | 758 | AUDIO_RISC_DMA_BUF_SIZE * NUM_AUDIO_PROGS + |
768 | RISC_SYNC_INSTRUCTION_SIZE; | 759 | RISC_SYNC_INSTRUCTION_SIZE; |
769 | dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS; | 760 | dev->audio_upstream_databuf_size = AUDIO_DATA_BUF_SZ * NUM_AUDIO_PROGS; |
770 | 761 | ||
771 | /* Allocating buffers and prepare RISC program */ | 762 | /* Allocating buffers and prepare RISC program */ |
@@ -773,7 +764,7 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) | |||
773 | _line_size); | 764 | _line_size); |
774 | if (retval < 0) { | 765 | if (retval < 0) { |
775 | pr_err("%s: Failed to set up Audio upstream buffers!\n", | 766 | pr_err("%s: Failed to set up Audio upstream buffers!\n", |
776 | dev->name); | 767 | dev->name); |
777 | goto error; | 768 | goto error; |
778 | } | 769 | } |
779 | /* Start RISC engine */ | 770 | /* Start RISC engine */ |
diff --git a/drivers/media/video/cx25821/cx25821-audio.h b/drivers/media/video/cx25821/cx25821-audio.h index 8eb55b7b88cb..1fc2d24f5110 100644 --- a/drivers/media/video/cx25821/cx25821-audio.h +++ b/drivers/media/video/cx25821/cx25821-audio.h | |||
@@ -23,39 +23,40 @@ | |||
23 | #ifndef __CX25821_AUDIO_H__ | 23 | #ifndef __CX25821_AUDIO_H__ |
24 | #define __CX25821_AUDIO_H__ | 24 | #define __CX25821_AUDIO_H__ |
25 | 25 | ||
26 | #define USE_RISC_NOOP 1 | 26 | #define USE_RISC_NOOP 1 |
27 | #define LINES_PER_BUFFER 15 | 27 | #define LINES_PER_BUFFER 15 |
28 | #define AUDIO_LINE_SIZE 128 | 28 | #define AUDIO_LINE_SIZE 128 |
29 | 29 | ||
30 | /* Number of buffer programs to use at once. */ | 30 | /* Number of buffer programs to use at once. */ |
31 | #define NUMBER_OF_PROGRAMS 8 | 31 | #define NUMBER_OF_PROGRAMS 8 |
32 | 32 | ||
33 | /* | 33 | /* |
34 | * Max size of the RISC program for a buffer. - worst case is 2 writes per line | 34 | * Max size of the RISC program for a buffer. - worst case is 2 writes per line |
35 | * Space is also added for the 4 no-op instructions added on the end. | 35 | * Space is also added for the 4 no-op instructions added on the end. |
36 | */ | 36 | */ |
37 | #ifndef USE_RISC_NOOP | 37 | #ifndef USE_RISC_NOOP |
38 | #define MAX_BUFFER_PROGRAM_SIZE \ | 38 | #define MAX_BUFFER_PROGRAM_SIZE \ |
39 | (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \ | 39 | (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \ |
40 | RISC_WRITECR_INSTRUCTION_SIZE * 4) | 40 | RISC_WRITECR_INSTRUCTION_SIZE * 4) |
41 | #endif | 41 | #endif |
42 | 42 | ||
43 | /* MAE 12 July 2005 Try to use NOOP RISC instruction instead */ | 43 | /* MAE 12 July 2005 Try to use NOOP RISC instruction instead */ |
44 | #ifdef USE_RISC_NOOP | 44 | #ifdef USE_RISC_NOOP |
45 | #define MAX_BUFFER_PROGRAM_SIZE \ | 45 | #define MAX_BUFFER_PROGRAM_SIZE \ |
46 | (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \ | 46 | (2 * LINES_PER_BUFFER * RISC_WRITE_INSTRUCTION_SIZE + \ |
47 | RISC_NOOP_INSTRUCTION_SIZE * 4) | 47 | RISC_NOOP_INSTRUCTION_SIZE * 4) |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | /* Sizes of various instructions in bytes. Used when adding instructions. */ | 50 | /* Sizes of various instructions in bytes. Used when adding instructions. */ |
51 | #define RISC_WRITE_INSTRUCTION_SIZE 12 | 51 | #define RISC_WRITE_INSTRUCTION_SIZE 12 |
52 | #define RISC_JUMP_INSTRUCTION_SIZE 12 | 52 | #define RISC_JUMP_INSTRUCTION_SIZE 12 |
53 | #define RISC_SKIP_INSTRUCTION_SIZE 4 | 53 | #define RISC_SKIP_INSTRUCTION_SIZE 4 |
54 | #define RISC_SYNC_INSTRUCTION_SIZE 4 | 54 | #define RISC_SYNC_INSTRUCTION_SIZE 4 |
55 | #define RISC_WRITECR_INSTRUCTION_SIZE 16 | 55 | #define RISC_WRITECR_INSTRUCTION_SIZE 16 |
56 | #define RISC_NOOP_INSTRUCTION_SIZE 4 | 56 | #define RISC_NOOP_INSTRUCTION_SIZE 4 |
57 | 57 | ||
58 | #define MAX_AUDIO_DMA_BUFFER_SIZE \ | 58 | #define MAX_AUDIO_DMA_BUFFER_SIZE \ |
59 | (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + RISC_SYNC_INSTRUCTION_SIZE) | 59 | (MAX_BUFFER_PROGRAM_SIZE * NUMBER_OF_PROGRAMS + \ |
60 | RISC_SYNC_INSTRUCTION_SIZE) | ||
60 | 61 | ||
61 | #endif | 62 | #endif |
diff --git a/drivers/media/video/cx25821/cx25821-cards.c b/drivers/media/video/cx25821/cx25821-cards.c index 6ace60313b49..99988c988095 100644 --- a/drivers/media/video/cx25821/cx25821-cards.c +++ b/drivers/media/video/cx25821/cx25821-cards.c | |||
@@ -67,6 +67,6 @@ void cx25821_card_setup(struct cx25821_dev *dev) | |||
67 | if (dev->i2c_bus[0].i2c_rc == 0) { | 67 | if (dev->i2c_bus[0].i2c_rc == 0) { |
68 | dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; | 68 | dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; |
69 | tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, | 69 | tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, |
70 | sizeof(eeprom)); | 70 | sizeof(eeprom)); |
71 | } | 71 | } |
72 | } | 72 | } |
diff --git a/drivers/media/video/cx25821/cx25821-core.c b/drivers/media/video/cx25821/cx25821-core.c index a7fa38f9594e..f617474f9073 100644 --- a/drivers/media/video/cx25821/cx25821-core.c +++ b/drivers/media/video/cx25821/cx25821-core.c | |||
@@ -804,8 +804,8 @@ void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select, | |||
804 | u32 format) | 804 | u32 format) |
805 | { | 805 | { |
806 | if (channel_select <= 7 && channel_select >= 0) { | 806 | if (channel_select <= 7 && channel_select >= 0) { |
807 | cx_write(dev->channels[channel_select]. | 807 | cx_write(dev->channels[channel_select].sram_channels->pix_frmt, |
808 | sram_channels->pix_frmt, format); | 808 | format); |
809 | dev->channels[channel_select].pixel_formats = format; | 809 | dev->channels[channel_select].pixel_formats = format; |
810 | } | 810 | } |
811 | } | 811 | } |
@@ -855,21 +855,19 @@ static void cx25821_initialize(struct cx25821_dev *dev) | |||
855 | } | 855 | } |
856 | 856 | ||
857 | cx25821_sram_channel_setup_audio(dev, | 857 | cx25821_sram_channel_setup_audio(dev, |
858 | dev->channels[SRAM_CH08].sram_channels, | 858 | dev->channels[SRAM_CH08].sram_channels, 128, 0); |
859 | 128, 0); | ||
860 | 859 | ||
861 | cx25821_gpio_init(dev); | 860 | cx25821_gpio_init(dev); |
862 | } | 861 | } |
863 | 862 | ||
864 | static int cx25821_get_resources(struct cx25821_dev *dev) | 863 | static int cx25821_get_resources(struct cx25821_dev *dev) |
865 | { | 864 | { |
866 | if (request_mem_region | 865 | if (request_mem_region(pci_resource_start(dev->pci, 0), |
867 | (pci_resource_start(dev->pci, 0), pci_resource_len(dev->pci, 0), | 866 | pci_resource_len(dev->pci, 0), dev->name)) |
868 | dev->name)) | ||
869 | return 0; | 867 | return 0; |
870 | 868 | ||
871 | pr_err("%s: can't get MMIO memory @ 0x%llx\n", | 869 | pr_err("%s: can't get MMIO memory @ 0x%llx\n", |
872 | dev->name, (unsigned long long)pci_resource_start(dev->pci, 0)); | 870 | dev->name, (unsigned long long)pci_resource_start(dev->pci, 0)); |
873 | 871 | ||
874 | return -EBUSY; | 872 | return -EBUSY; |
875 | } | 873 | } |
@@ -972,8 +970,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) | |||
972 | dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0)); | 970 | dev->lmmio = ioremap(dev->base_io_addr, pci_resource_len(dev->pci, 0)); |
973 | 971 | ||
974 | if (!dev->lmmio) { | 972 | if (!dev->lmmio) { |
975 | CX25821_ERR | 973 | CX25821_ERR("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n"); |
976 | ("ioremap failed, maybe increasing __VMALLOC_RESERVE in page.h\n"); | ||
977 | cx25821_iounmap(dev); | 974 | cx25821_iounmap(dev); |
978 | return -ENOMEM; | 975 | return -ENOMEM; |
979 | } | 976 | } |
@@ -994,7 +991,7 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) | |||
994 | * cx25821_i2c_register(&dev->i2c_bus[2]); */ | 991 | * cx25821_i2c_register(&dev->i2c_bus[2]); */ |
995 | 992 | ||
996 | CX25821_INFO("i2c register! bus->i2c_rc = %d\n", | 993 | CX25821_INFO("i2c register! bus->i2c_rc = %d\n", |
997 | dev->i2c_bus[0].i2c_rc); | 994 | dev->i2c_bus[0].i2c_rc); |
998 | 995 | ||
999 | cx25821_card_setup(dev); | 996 | cx25821_card_setup(dev); |
1000 | 997 | ||
@@ -1004,9 +1001,8 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) | |||
1004 | cx25821_video_register(dev); | 1001 | cx25821_video_register(dev); |
1005 | 1002 | ||
1006 | /* register IOCTL device */ | 1003 | /* register IOCTL device */ |
1007 | dev->ioctl_dev = | 1004 | dev->ioctl_dev = cx25821_vdev_init(dev, dev->pci, |
1008 | cx25821_vdev_init(dev, dev->pci, &cx25821_videoioctl_template, | 1005 | &cx25821_videoioctl_template, "video"); |
1009 | "video"); | ||
1010 | 1006 | ||
1011 | if (video_register_device | 1007 | if (video_register_device |
1012 | (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) { | 1008 | (dev->ioctl_dev, VFL_TYPE_GRABBER, VIDEO_IOCTL_CH) < 0) { |
@@ -1103,16 +1099,15 @@ static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist, | |||
1103 | } | 1099 | } |
1104 | if (bpl <= sg_dma_len(sg) - offset) { | 1100 | if (bpl <= sg_dma_len(sg) - offset) { |
1105 | /* fits into current chunk */ | 1101 | /* fits into current chunk */ |
1106 | *(rp++) = | 1102 | *(rp++) = cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL | |
1107 | cpu_to_le32(RISC_WRITE | RISC_SOL | RISC_EOL | bpl); | 1103 | bpl); |
1108 | *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); | 1104 | *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); |
1109 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | 1105 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ |
1110 | offset += bpl; | 1106 | offset += bpl; |
1111 | } else { | 1107 | } else { |
1112 | /* scanline needs to be split */ | 1108 | /* scanline needs to be split */ |
1113 | todo = bpl; | 1109 | todo = bpl; |
1114 | *(rp++) = | 1110 | *(rp++) = cpu_to_le32(RISC_WRITE | RISC_SOL | |
1115 | cpu_to_le32(RISC_WRITE | RISC_SOL | | ||
1116 | (sg_dma_len(sg) - offset)); | 1111 | (sg_dma_len(sg) - offset)); |
1117 | *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); | 1112 | *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); |
1118 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | 1113 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ |
@@ -1120,8 +1115,8 @@ static __le32 *cx25821_risc_field(__le32 * rp, struct scatterlist *sglist, | |||
1120 | offset = 0; | 1115 | offset = 0; |
1121 | sg++; | 1116 | sg++; |
1122 | while (todo > sg_dma_len(sg)) { | 1117 | while (todo > sg_dma_len(sg)) { |
1123 | *(rp++) = | 1118 | *(rp++) = cpu_to_le32(RISC_WRITE | |
1124 | cpu_to_le32(RISC_WRITE | sg_dma_len(sg)); | 1119 | sg_dma_len(sg)); |
1125 | *(rp++) = cpu_to_le32(sg_dma_address(sg)); | 1120 | *(rp++) = cpu_to_le32(sg_dma_address(sg)); |
1126 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | 1121 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ |
1127 | todo -= sg_dma_len(sg); | 1122 | todo -= sg_dma_len(sg); |
@@ -1160,8 +1155,8 @@ int cx25821_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, | |||
1160 | can cause next bpl to start close to a page border. First DMA | 1155 | can cause next bpl to start close to a page border. First DMA |
1161 | region may be smaller than PAGE_SIZE */ | 1156 | region may be smaller than PAGE_SIZE */ |
1162 | /* write and jump need and extra dword */ | 1157 | /* write and jump need and extra dword */ |
1163 | instructions = | 1158 | instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + |
1164 | fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); | 1159 | lines); |
1165 | instructions += 2; | 1160 | instructions += 2; |
1166 | rc = btcx_riscmem_alloc(pci, risc, instructions * 12); | 1161 | rc = btcx_riscmem_alloc(pci, risc, instructions * 12); |
1167 | 1162 | ||
@@ -1215,8 +1210,8 @@ static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist, | |||
1215 | 1210 | ||
1216 | if (bpl <= sg_dma_len(sg) - offset) { | 1211 | if (bpl <= sg_dma_len(sg) - offset) { |
1217 | /* fits into current chunk */ | 1212 | /* fits into current chunk */ |
1218 | *(rp++) = | 1213 | *(rp++) = cpu_to_le32(RISC_WRITE | sol | RISC_EOL | |
1219 | cpu_to_le32(RISC_WRITE | sol | RISC_EOL | bpl); | 1214 | bpl); |
1220 | *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); | 1215 | *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); |
1221 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | 1216 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ |
1222 | offset += bpl; | 1217 | offset += bpl; |
@@ -1224,7 +1219,7 @@ static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist, | |||
1224 | /* scanline needs to be split */ | 1219 | /* scanline needs to be split */ |
1225 | todo = bpl; | 1220 | todo = bpl; |
1226 | *(rp++) = cpu_to_le32(RISC_WRITE | sol | | 1221 | *(rp++) = cpu_to_le32(RISC_WRITE | sol | |
1227 | (sg_dma_len(sg) - offset)); | 1222 | (sg_dma_len(sg) - offset)); |
1228 | *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); | 1223 | *(rp++) = cpu_to_le32(sg_dma_address(sg) + offset); |
1229 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | 1224 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ |
1230 | todo -= (sg_dma_len(sg) - offset); | 1225 | todo -= (sg_dma_len(sg) - offset); |
@@ -1232,7 +1227,7 @@ static __le32 *cx25821_risc_field_audio(__le32 * rp, struct scatterlist *sglist, | |||
1232 | sg++; | 1227 | sg++; |
1233 | while (todo > sg_dma_len(sg)) { | 1228 | while (todo > sg_dma_len(sg)) { |
1234 | *(rp++) = cpu_to_le32(RISC_WRITE | | 1229 | *(rp++) = cpu_to_le32(RISC_WRITE | |
1235 | sg_dma_len(sg)); | 1230 | sg_dma_len(sg)); |
1236 | *(rp++) = cpu_to_le32(sg_dma_address(sg)); | 1231 | *(rp++) = cpu_to_le32(sg_dma_address(sg)); |
1237 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | 1232 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ |
1238 | todo -= sg_dma_len(sg); | 1233 | todo -= sg_dma_len(sg); |
@@ -1339,8 +1334,8 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id) | |||
1339 | sram_channels->int_stat); | 1334 | sram_channels->int_stat); |
1340 | 1335 | ||
1341 | if (vid_status) | 1336 | if (vid_status) |
1342 | handled += | 1337 | handled += cx25821_video_irq(dev, i, |
1343 | cx25821_video_irq(dev, i, vid_status); | 1338 | vid_status); |
1344 | 1339 | ||
1345 | cx_write(PCI_INT_STAT, mask[i]); | 1340 | cx_write(PCI_INT_STAT, mask[i]); |
1346 | } | 1341 | } |
@@ -1427,9 +1422,8 @@ static int __devinit cx25821_initdev(struct pci_dev *pci_dev, | |||
1427 | goto fail_irq; | 1422 | goto fail_irq; |
1428 | } | 1423 | } |
1429 | 1424 | ||
1430 | err = | 1425 | err = request_irq(pci_dev->irq, cx25821_irq, |
1431 | request_irq(pci_dev->irq, cx25821_irq, IRQF_SHARED, | 1426 | IRQF_SHARED, dev->name, dev); |
1432 | dev->name, dev); | ||
1433 | 1427 | ||
1434 | if (err < 0) { | 1428 | if (err < 0) { |
1435 | pr_err("%s: can't get IRQ %d\n", dev->name, pci_dev->irq); | 1429 | pr_err("%s: can't get IRQ %d\n", dev->name, pci_dev->irq); |
@@ -1512,6 +1506,5 @@ static void __exit cx25821_fini(void) | |||
1512 | pci_unregister_driver(&cx25821_pci_driver); | 1506 | pci_unregister_driver(&cx25821_pci_driver); |
1513 | } | 1507 | } |
1514 | 1508 | ||
1515 | |||
1516 | module_init(cx25821_init); | 1509 | module_init(cx25821_init); |
1517 | module_exit(cx25821_fini); | 1510 | module_exit(cx25821_fini); |
diff --git a/drivers/media/video/cx25821/cx25821-i2c.c b/drivers/media/video/cx25821/cx25821-i2c.c index 4d3d0ce40785..12d7300fa1e9 100644 --- a/drivers/media/video/cx25821/cx25821-i2c.c +++ b/drivers/media/video/cx25821/cx25821-i2c.c | |||
@@ -252,8 +252,8 @@ static int i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) | |||
252 | } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && | 252 | } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && |
253 | msgs[i].addr == msgs[i + 1].addr) { | 253 | msgs[i].addr == msgs[i + 1].addr) { |
254 | /* write then read from same address */ | 254 | /* write then read from same address */ |
255 | retval = | 255 | retval = i2c_sendbytes(i2c_adap, &msgs[i], |
256 | i2c_sendbytes(i2c_adap, &msgs[i], msgs[i + 1].len); | 256 | msgs[i + 1].len); |
257 | 257 | ||
258 | if (retval < 0) | 258 | if (retval < 0) |
259 | goto err; | 259 | goto err; |
@@ -276,10 +276,8 @@ err: | |||
276 | 276 | ||
277 | static u32 cx25821_functionality(struct i2c_adapter *adap) | 277 | static u32 cx25821_functionality(struct i2c_adapter *adap) |
278 | { | 278 | { |
279 | return I2C_FUNC_SMBUS_EMUL | | 279 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C | I2C_FUNC_SMBUS_WORD_DATA | |
280 | I2C_FUNC_I2C | | 280 | I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA; |
281 | I2C_FUNC_SMBUS_WORD_DATA | | ||
282 | I2C_FUNC_SMBUS_READ_WORD_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA; | ||
283 | } | 281 | } |
284 | 282 | ||
285 | static struct i2c_algorithm cx25821_i2c_algo_template = { | 283 | static struct i2c_algorithm cx25821_i2c_algo_template = { |
@@ -300,7 +298,7 @@ static struct i2c_client cx25821_i2c_client_template = { | |||
300 | .name = "cx25821 internal", | 298 | .name = "cx25821 internal", |
301 | }; | 299 | }; |
302 | 300 | ||
303 | /* init + register i2c algo-bit adapter */ | 301 | /* init + register i2c adapter */ |
304 | int cx25821_i2c_register(struct cx25821_i2c *bus) | 302 | int cx25821_i2c_register(struct cx25821_i2c *bus) |
305 | { | 303 | { |
306 | struct cx25821_dev *dev = bus->dev; | 304 | struct cx25821_dev *dev = bus->dev; |
diff --git a/drivers/media/video/cx25821/cx25821-medusa-defines.h b/drivers/media/video/cx25821/cx25821-medusa-defines.h index 60d197f57556..7a9e6470ba22 100644 --- a/drivers/media/video/cx25821/cx25821-medusa-defines.h +++ b/drivers/media/video/cx25821/cx25821-medusa-defines.h | |||
@@ -23,7 +23,7 @@ | |||
23 | #ifndef _MEDUSA_DEF_H_ | 23 | #ifndef _MEDUSA_DEF_H_ |
24 | #define _MEDUSA_DEF_H_ | 24 | #define _MEDUSA_DEF_H_ |
25 | 25 | ||
26 | /* Video deocder that we supported */ | 26 | /* Video decoder that we supported */ |
27 | #define VDEC_A 0 | 27 | #define VDEC_A 0 |
28 | #define VDEC_B 1 | 28 | #define VDEC_B 1 |
29 | #define VDEC_C 2 | 29 | #define VDEC_C 2 |
@@ -34,9 +34,9 @@ | |||
34 | #define VDEC_H 7 | 34 | #define VDEC_H 7 |
35 | 35 | ||
36 | /* end of display sequence */ | 36 | /* end of display sequence */ |
37 | #define END_OF_SEQ 0xF; | 37 | #define END_OF_SEQ 0xF; |
38 | 38 | ||
39 | /* registry string size */ | 39 | /* registry string size */ |
40 | #define MAX_REGISTRY_SZ 40; | 40 | #define MAX_REGISTRY_SZ 40; |
41 | 41 | ||
42 | #endif | 42 | #endif |
diff --git a/drivers/media/video/cx25821/cx25821-medusa-reg.h b/drivers/media/video/cx25821/cx25821-medusa-reg.h index 1c1c228352d1..c98ac946b277 100644 --- a/drivers/media/video/cx25821/cx25821-medusa-reg.h +++ b/drivers/media/video/cx25821/cx25821-medusa-reg.h | |||
@@ -28,22 +28,22 @@ | |||
28 | #define HOST_REGISTER2 0x0001 | 28 | #define HOST_REGISTER2 0x0001 |
29 | 29 | ||
30 | /* Chip Configuration Registers */ | 30 | /* Chip Configuration Registers */ |
31 | #define CHIP_CTRL 0x0100 | 31 | #define CHIP_CTRL 0x0100 |
32 | #define AFE_AB_CTRL 0x0104 | 32 | #define AFE_AB_CTRL 0x0104 |
33 | #define AFE_CD_CTRL 0x0108 | 33 | #define AFE_CD_CTRL 0x0108 |
34 | #define AFE_EF_CTRL 0x010C | 34 | #define AFE_EF_CTRL 0x010C |
35 | #define AFE_GH_CTRL 0x0110 | 35 | #define AFE_GH_CTRL 0x0110 |
36 | #define DENC_AB_CTRL 0x0114 | 36 | #define DENC_AB_CTRL 0x0114 |
37 | #define BYP_AB_CTRL 0x0118 | 37 | #define BYP_AB_CTRL 0x0118 |
38 | #define MON_A_CTRL 0x011C | 38 | #define MON_A_CTRL 0x011C |
39 | #define DISP_SEQ_A 0x0120 | 39 | #define DISP_SEQ_A 0x0120 |
40 | #define DISP_SEQ_B 0x0124 | 40 | #define DISP_SEQ_B 0x0124 |
41 | #define DISP_AB_CNT 0x0128 | 41 | #define DISP_AB_CNT 0x0128 |
42 | #define DISP_CD_CNT 0x012C | 42 | #define DISP_CD_CNT 0x012C |
43 | #define DISP_EF_CNT 0x0130 | 43 | #define DISP_EF_CNT 0x0130 |
44 | #define DISP_GH_CNT 0x0134 | 44 | #define DISP_GH_CNT 0x0134 |
45 | #define DISP_IJ_CNT 0x0138 | 45 | #define DISP_IJ_CNT 0x0138 |
46 | #define PIN_OE_CTRL 0x013C | 46 | #define PIN_OE_CTRL 0x013C |
47 | #define PIN_SPD_CTRL 0x0140 | 47 | #define PIN_SPD_CTRL 0x0140 |
48 | #define PIN_SPD_CTRL2 0x0144 | 48 | #define PIN_SPD_CTRL2 0x0144 |
49 | #define IRQ_STAT_CTRL 0x0148 | 49 | #define IRQ_STAT_CTRL 0x0148 |
@@ -51,8 +51,8 @@ | |||
51 | #define POWER_CTRL_CD 0x0150 | 51 | #define POWER_CTRL_CD 0x0150 |
52 | #define POWER_CTRL_EF 0x0154 | 52 | #define POWER_CTRL_EF 0x0154 |
53 | #define POWER_CTRL_GH 0x0158 | 53 | #define POWER_CTRL_GH 0x0158 |
54 | #define TUNE_CTRL 0x015C | 54 | #define TUNE_CTRL 0x015C |
55 | #define BIAS_CTRL 0x0160 | 55 | #define BIAS_CTRL 0x0160 |
56 | #define AFE_AB_DIAG_CTRL 0x0164 | 56 | #define AFE_AB_DIAG_CTRL 0x0164 |
57 | #define AFE_CD_DIAG_CTRL 0x0168 | 57 | #define AFE_CD_DIAG_CTRL 0x0168 |
58 | #define AFE_EF_DIAG_CTRL 0x016C | 58 | #define AFE_EF_DIAG_CTRL 0x016C |
@@ -61,17 +61,17 @@ | |||
61 | #define PLL_CD_DIAG_CTRL 0x0178 | 61 | #define PLL_CD_DIAG_CTRL 0x0178 |
62 | #define PLL_EF_DIAG_CTRL 0x017C | 62 | #define PLL_EF_DIAG_CTRL 0x017C |
63 | #define PLL_GH_DIAG_CTRL 0x0180 | 63 | #define PLL_GH_DIAG_CTRL 0x0180 |
64 | #define TEST_CTRL 0x0184 | 64 | #define TEST_CTRL 0x0184 |
65 | #define BIST_STAT 0x0188 | 65 | #define BIST_STAT 0x0188 |
66 | #define BIST_STAT2 0x018C | 66 | #define BIST_STAT2 0x018C |
67 | #define BIST_VID_PLL_AB_STAT 0x0190 | 67 | #define BIST_VID_PLL_AB_STAT 0x0190 |
68 | #define BIST_VID_PLL_CD_STAT 0x0194 | 68 | #define BIST_VID_PLL_CD_STAT 0x0194 |
69 | #define BIST_VID_PLL_EF_STAT 0x0198 | 69 | #define BIST_VID_PLL_EF_STAT 0x0198 |
70 | #define BIST_VID_PLL_GH_STAT 0x019C | 70 | #define BIST_VID_PLL_GH_STAT 0x019C |
71 | #define DLL_DIAG_CTRL 0x01A0 | 71 | #define DLL_DIAG_CTRL 0x01A0 |
72 | #define DEV_CH_ID_CTRL 0x01A4 | 72 | #define DEV_CH_ID_CTRL 0x01A4 |
73 | #define ABIST_CTRL_STATUS 0x01A8 | 73 | #define ABIST_CTRL_STATUS 0x01A8 |
74 | #define ABIST_FREQ 0x01AC | 74 | #define ABIST_FREQ 0x01AC |
75 | #define ABIST_GOERT_SHIFT 0x01B0 | 75 | #define ABIST_GOERT_SHIFT 0x01B0 |
76 | #define ABIST_COEF12 0x01B4 | 76 | #define ABIST_COEF12 0x01B4 |
77 | #define ABIST_COEF34 0x01B8 | 77 | #define ABIST_COEF34 0x01B8 |
@@ -92,357 +92,357 @@ | |||
92 | #define ABIST_CLAMP_E 0x01F4 | 92 | #define ABIST_CLAMP_E 0x01F4 |
93 | #define ABIST_CLAMP_F 0x01F8 | 93 | #define ABIST_CLAMP_F 0x01F8 |
94 | 94 | ||
95 | /* Digital Video Encoder A Registers */ | 95 | /* Digital Video Encoder A Registers */ |
96 | #define DENC_A_REG_1 0x0200 | 96 | #define DENC_A_REG_1 0x0200 |
97 | #define DENC_A_REG_2 0x0204 | 97 | #define DENC_A_REG_2 0x0204 |
98 | #define DENC_A_REG_3 0x0208 | 98 | #define DENC_A_REG_3 0x0208 |
99 | #define DENC_A_REG_4 0x020C | 99 | #define DENC_A_REG_4 0x020C |
100 | #define DENC_A_REG_5 0x0210 | 100 | #define DENC_A_REG_5 0x0210 |
101 | #define DENC_A_REG_6 0x0214 | 101 | #define DENC_A_REG_6 0x0214 |
102 | #define DENC_A_REG_7 0x0218 | 102 | #define DENC_A_REG_7 0x0218 |
103 | #define DENC_A_REG_8 0x021C | 103 | #define DENC_A_REG_8 0x021C |
104 | 104 | ||
105 | /* Digital Video Encoder B Registers */ | 105 | /* Digital Video Encoder B Registers */ |
106 | #define DENC_B_REG_1 0x0300 | 106 | #define DENC_B_REG_1 0x0300 |
107 | #define DENC_B_REG_2 0x0304 | 107 | #define DENC_B_REG_2 0x0304 |
108 | #define DENC_B_REG_3 0x0308 | 108 | #define DENC_B_REG_3 0x0308 |
109 | #define DENC_B_REG_4 0x030C | 109 | #define DENC_B_REG_4 0x030C |
110 | #define DENC_B_REG_5 0x0310 | 110 | #define DENC_B_REG_5 0x0310 |
111 | #define DENC_B_REG_6 0x0314 | 111 | #define DENC_B_REG_6 0x0314 |
112 | #define DENC_B_REG_7 0x0318 | 112 | #define DENC_B_REG_7 0x0318 |
113 | #define DENC_B_REG_8 0x031C | 113 | #define DENC_B_REG_8 0x031C |
114 | 114 | ||
115 | /* Video Decoder A Registers */ | 115 | /* Video Decoder A Registers */ |
116 | #define MODE_CTRL 0x1000 | 116 | #define MODE_CTRL 0x1000 |
117 | #define OUT_CTRL1 0x1004 | 117 | #define OUT_CTRL1 0x1004 |
118 | #define OUT_CTRL_NS 0x1008 | 118 | #define OUT_CTRL_NS 0x1008 |
119 | #define GEN_STAT 0x100C | 119 | #define GEN_STAT 0x100C |
120 | #define INT_STAT_MASK 0x1010 | 120 | #define INT_STAT_MASK 0x1010 |
121 | #define LUMA_CTRL 0x1014 | 121 | #define LUMA_CTRL 0x1014 |
122 | #define CHROMA_CTRL 0x1018 | 122 | #define CHROMA_CTRL 0x1018 |
123 | #define CRUSH_CTRL 0x101C | 123 | #define CRUSH_CTRL 0x101C |
124 | #define HORIZ_TIM_CTRL 0x1020 | 124 | #define HORIZ_TIM_CTRL 0x1020 |
125 | #define VERT_TIM_CTRL 0x1024 | 125 | #define VERT_TIM_CTRL 0x1024 |
126 | #define MISC_TIM_CTRL 0x1028 | 126 | #define MISC_TIM_CTRL 0x1028 |
127 | #define FIELD_COUNT 0x102C | 127 | #define FIELD_COUNT 0x102C |
128 | #define HSCALE_CTRL 0x1030 | 128 | #define HSCALE_CTRL 0x1030 |
129 | #define VSCALE_CTRL 0x1034 | 129 | #define VSCALE_CTRL 0x1034 |
130 | #define MAN_VGA_CTRL 0x1038 | 130 | #define MAN_VGA_CTRL 0x1038 |
131 | #define MAN_AGC_CTRL 0x103C | 131 | #define MAN_AGC_CTRL 0x103C |
132 | #define DFE_CTRL1 0x1040 | 132 | #define DFE_CTRL1 0x1040 |
133 | #define DFE_CTRL2 0x1044 | 133 | #define DFE_CTRL2 0x1044 |
134 | #define DFE_CTRL3 0x1048 | 134 | #define DFE_CTRL3 0x1048 |
135 | #define PLL_CTRL 0x104C | 135 | #define PLL_CTRL 0x104C |
136 | #define PLL_CTRL_FAST 0x1050 | 136 | #define PLL_CTRL_FAST 0x1050 |
137 | #define HTL_CTRL 0x1054 | 137 | #define HTL_CTRL 0x1054 |
138 | #define SRC_CFG 0x1058 | 138 | #define SRC_CFG 0x1058 |
139 | #define SC_STEP_SIZE 0x105C | 139 | #define SC_STEP_SIZE 0x105C |
140 | #define SC_CONVERGE_CTRL 0x1060 | 140 | #define SC_CONVERGE_CTRL 0x1060 |
141 | #define SC_LOOP_CTRL 0x1064 | 141 | #define SC_LOOP_CTRL 0x1064 |
142 | #define COMB_2D_HFS_CFG 0x1068 | 142 | #define COMB_2D_HFS_CFG 0x1068 |
143 | #define COMB_2D_HFD_CFG 0x106C | 143 | #define COMB_2D_HFD_CFG 0x106C |
144 | #define COMB_2D_LF_CFG 0x1070 | 144 | #define COMB_2D_LF_CFG 0x1070 |
145 | #define COMB_2D_BLEND 0x1074 | 145 | #define COMB_2D_BLEND 0x1074 |
146 | #define COMB_MISC_CTRL 0x1078 | 146 | #define COMB_MISC_CTRL 0x1078 |
147 | #define COMB_FLAT_THRESH_CTRL 0x107C | 147 | #define COMB_FLAT_THRESH_CTRL 0x107C |
148 | #define COMB_TEST 0x1080 | 148 | #define COMB_TEST 0x1080 |
149 | #define BP_MISC_CTRL 0x1084 | 149 | #define BP_MISC_CTRL 0x1084 |
150 | #define VCR_DET_CTRL 0x1088 | 150 | #define VCR_DET_CTRL 0x1088 |
151 | #define NOISE_DET_CTRL 0x108C | 151 | #define NOISE_DET_CTRL 0x108C |
152 | #define COMB_FLAT_NOISE_CTRL 0x1090 | 152 | #define COMB_FLAT_NOISE_CTRL 0x1090 |
153 | #define VERSION 0x11F8 | 153 | #define VERSION 0x11F8 |
154 | #define SOFT_RST_CTRL 0x11FC | 154 | #define SOFT_RST_CTRL 0x11FC |
155 | 155 | ||
156 | /* Video Decoder B Registers */ | 156 | /* Video Decoder B Registers */ |
157 | #define VDEC_B_MODE_CTRL 0x1200 | 157 | #define VDEC_B_MODE_CTRL 0x1200 |
158 | #define VDEC_B_OUT_CTRL1 0x1204 | 158 | #define VDEC_B_OUT_CTRL1 0x1204 |
159 | #define VDEC_B_OUT_CTRL_NS 0x1208 | 159 | #define VDEC_B_OUT_CTRL_NS 0x1208 |
160 | #define VDEC_B_GEN_STAT 0x120C | 160 | #define VDEC_B_GEN_STAT 0x120C |
161 | #define VDEC_B_INT_STAT_MASK 0x1210 | 161 | #define VDEC_B_INT_STAT_MASK 0x1210 |
162 | #define VDEC_B_LUMA_CTRL 0x1214 | 162 | #define VDEC_B_LUMA_CTRL 0x1214 |
163 | #define VDEC_B_CHROMA_CTRL 0x1218 | 163 | #define VDEC_B_CHROMA_CTRL 0x1218 |
164 | #define VDEC_B_CRUSH_CTRL 0x121C | 164 | #define VDEC_B_CRUSH_CTRL 0x121C |
165 | #define VDEC_B_HORIZ_TIM_CTRL 0x1220 | 165 | #define VDEC_B_HORIZ_TIM_CTRL 0x1220 |
166 | #define VDEC_B_VERT_TIM_CTRL 0x1224 | 166 | #define VDEC_B_VERT_TIM_CTRL 0x1224 |
167 | #define VDEC_B_MISC_TIM_CTRL 0x1228 | 167 | #define VDEC_B_MISC_TIM_CTRL 0x1228 |
168 | #define VDEC_B_FIELD_COUNT 0x122C | 168 | #define VDEC_B_FIELD_COUNT 0x122C |
169 | #define VDEC_B_HSCALE_CTRL 0x1230 | 169 | #define VDEC_B_HSCALE_CTRL 0x1230 |
170 | #define VDEC_B_VSCALE_CTRL 0x1234 | 170 | #define VDEC_B_VSCALE_CTRL 0x1234 |
171 | #define VDEC_B_MAN_VGA_CTRL 0x1238 | 171 | #define VDEC_B_MAN_VGA_CTRL 0x1238 |
172 | #define VDEC_B_MAN_AGC_CTRL 0x123C | 172 | #define VDEC_B_MAN_AGC_CTRL 0x123C |
173 | #define VDEC_B_DFE_CTRL1 0x1240 | 173 | #define VDEC_B_DFE_CTRL1 0x1240 |
174 | #define VDEC_B_DFE_CTRL2 0x1244 | 174 | #define VDEC_B_DFE_CTRL2 0x1244 |
175 | #define VDEC_B_DFE_CTRL3 0x1248 | 175 | #define VDEC_B_DFE_CTRL3 0x1248 |
176 | #define VDEC_B_PLL_CTRL 0x124C | 176 | #define VDEC_B_PLL_CTRL 0x124C |
177 | #define VDEC_B_PLL_CTRL_FAST 0x1250 | 177 | #define VDEC_B_PLL_CTRL_FAST 0x1250 |
178 | #define VDEC_B_HTL_CTRL 0x1254 | 178 | #define VDEC_B_HTL_CTRL 0x1254 |
179 | #define VDEC_B_SRC_CFG 0x1258 | 179 | #define VDEC_B_SRC_CFG 0x1258 |
180 | #define VDEC_B_SC_STEP_SIZE 0x125C | 180 | #define VDEC_B_SC_STEP_SIZE 0x125C |
181 | #define VDEC_B_SC_CONVERGE_CTRL 0x1260 | 181 | #define VDEC_B_SC_CONVERGE_CTRL 0x1260 |
182 | #define VDEC_B_SC_LOOP_CTRL 0x1264 | 182 | #define VDEC_B_SC_LOOP_CTRL 0x1264 |
183 | #define VDEC_B_COMB_2D_HFS_CFG 0x1268 | 183 | #define VDEC_B_COMB_2D_HFS_CFG 0x1268 |
184 | #define VDEC_B_COMB_2D_HFD_CFG 0x126C | 184 | #define VDEC_B_COMB_2D_HFD_CFG 0x126C |
185 | #define VDEC_B_COMB_2D_LF_CFG 0x1270 | 185 | #define VDEC_B_COMB_2D_LF_CFG 0x1270 |
186 | #define VDEC_B_COMB_2D_BLEND 0x1274 | 186 | #define VDEC_B_COMB_2D_BLEND 0x1274 |
187 | #define VDEC_B_COMB_MISC_CTRL 0x1278 | 187 | #define VDEC_B_COMB_MISC_CTRL 0x1278 |
188 | #define VDEC_B_COMB_FLAT_THRESH_CTRL 0x127C | 188 | #define VDEC_B_COMB_FLAT_THRESH_CTRL 0x127C |
189 | #define VDEC_B_COMB_TEST 0x1280 | 189 | #define VDEC_B_COMB_TEST 0x1280 |
190 | #define VDEC_B_BP_MISC_CTRL 0x1284 | 190 | #define VDEC_B_BP_MISC_CTRL 0x1284 |
191 | #define VDEC_B_VCR_DET_CTRL 0x1288 | 191 | #define VDEC_B_VCR_DET_CTRL 0x1288 |
192 | #define VDEC_B_NOISE_DET_CTRL 0x128C | 192 | #define VDEC_B_NOISE_DET_CTRL 0x128C |
193 | #define VDEC_B_COMB_FLAT_NOISE_CTRL 0x1290 | 193 | #define VDEC_B_COMB_FLAT_NOISE_CTRL 0x1290 |
194 | #define VDEC_B_VERSION 0x13F8 | 194 | #define VDEC_B_VERSION 0x13F8 |
195 | #define VDEC_B_SOFT_RST_CTRL 0x13FC | 195 | #define VDEC_B_SOFT_RST_CTRL 0x13FC |
196 | 196 | ||
197 | /* Video Decoder C Registers */ | 197 | /* Video Decoder C Registers */ |
198 | #define VDEC_C_MODE_CTRL 0x1400 | 198 | #define VDEC_C_MODE_CTRL 0x1400 |
199 | #define VDEC_C_OUT_CTRL1 0x1404 | 199 | #define VDEC_C_OUT_CTRL1 0x1404 |
200 | #define VDEC_C_OUT_CTRL_NS 0x1408 | 200 | #define VDEC_C_OUT_CTRL_NS 0x1408 |
201 | #define VDEC_C_GEN_STAT 0x140C | 201 | #define VDEC_C_GEN_STAT 0x140C |
202 | #define VDEC_C_INT_STAT_MASK 0x1410 | 202 | #define VDEC_C_INT_STAT_MASK 0x1410 |
203 | #define VDEC_C_LUMA_CTRL 0x1414 | 203 | #define VDEC_C_LUMA_CTRL 0x1414 |
204 | #define VDEC_C_CHROMA_CTRL 0x1418 | 204 | #define VDEC_C_CHROMA_CTRL 0x1418 |
205 | #define VDEC_C_CRUSH_CTRL 0x141C | 205 | #define VDEC_C_CRUSH_CTRL 0x141C |
206 | #define VDEC_C_HORIZ_TIM_CTRL 0x1420 | 206 | #define VDEC_C_HORIZ_TIM_CTRL 0x1420 |
207 | #define VDEC_C_VERT_TIM_CTRL 0x1424 | 207 | #define VDEC_C_VERT_TIM_CTRL 0x1424 |
208 | #define VDEC_C_MISC_TIM_CTRL 0x1428 | 208 | #define VDEC_C_MISC_TIM_CTRL 0x1428 |
209 | #define VDEC_C_FIELD_COUNT 0x142C | 209 | #define VDEC_C_FIELD_COUNT 0x142C |
210 | #define VDEC_C_HSCALE_CTRL 0x1430 | 210 | #define VDEC_C_HSCALE_CTRL 0x1430 |
211 | #define VDEC_C_VSCALE_CTRL 0x1434 | 211 | #define VDEC_C_VSCALE_CTRL 0x1434 |
212 | #define VDEC_C_MAN_VGA_CTRL 0x1438 | 212 | #define VDEC_C_MAN_VGA_CTRL 0x1438 |
213 | #define VDEC_C_MAN_AGC_CTRL 0x143C | 213 | #define VDEC_C_MAN_AGC_CTRL 0x143C |
214 | #define VDEC_C_DFE_CTRL1 0x1440 | 214 | #define VDEC_C_DFE_CTRL1 0x1440 |
215 | #define VDEC_C_DFE_CTRL2 0x1444 | 215 | #define VDEC_C_DFE_CTRL2 0x1444 |
216 | #define VDEC_C_DFE_CTRL3 0x1448 | 216 | #define VDEC_C_DFE_CTRL3 0x1448 |
217 | #define VDEC_C_PLL_CTRL 0x144C | 217 | #define VDEC_C_PLL_CTRL 0x144C |
218 | #define VDEC_C_PLL_CTRL_FAST 0x1450 | 218 | #define VDEC_C_PLL_CTRL_FAST 0x1450 |
219 | #define VDEC_C_HTL_CTRL 0x1454 | 219 | #define VDEC_C_HTL_CTRL 0x1454 |
220 | #define VDEC_C_SRC_CFG 0x1458 | 220 | #define VDEC_C_SRC_CFG 0x1458 |
221 | #define VDEC_C_SC_STEP_SIZE 0x145C | 221 | #define VDEC_C_SC_STEP_SIZE 0x145C |
222 | #define VDEC_C_SC_CONVERGE_CTRL 0x1460 | 222 | #define VDEC_C_SC_CONVERGE_CTRL 0x1460 |
223 | #define VDEC_C_SC_LOOP_CTRL 0x1464 | 223 | #define VDEC_C_SC_LOOP_CTRL 0x1464 |
224 | #define VDEC_C_COMB_2D_HFS_CFG 0x1468 | 224 | #define VDEC_C_COMB_2D_HFS_CFG 0x1468 |
225 | #define VDEC_C_COMB_2D_HFD_CFG 0x146C | 225 | #define VDEC_C_COMB_2D_HFD_CFG 0x146C |
226 | #define VDEC_C_COMB_2D_LF_CFG 0x1470 | 226 | #define VDEC_C_COMB_2D_LF_CFG 0x1470 |
227 | #define VDEC_C_COMB_2D_BLEND 0x1474 | 227 | #define VDEC_C_COMB_2D_BLEND 0x1474 |
228 | #define VDEC_C_COMB_MISC_CTRL 0x1478 | 228 | #define VDEC_C_COMB_MISC_CTRL 0x1478 |
229 | #define VDEC_C_COMB_FLAT_THRESH_CTRL 0x147C | 229 | #define VDEC_C_COMB_FLAT_THRESH_CTRL 0x147C |
230 | #define VDEC_C_COMB_TEST 0x1480 | 230 | #define VDEC_C_COMB_TEST 0x1480 |
231 | #define VDEC_C_BP_MISC_CTRL 0x1484 | 231 | #define VDEC_C_BP_MISC_CTRL 0x1484 |
232 | #define VDEC_C_VCR_DET_CTRL 0x1488 | 232 | #define VDEC_C_VCR_DET_CTRL 0x1488 |
233 | #define VDEC_C_NOISE_DET_CTRL 0x148C | 233 | #define VDEC_C_NOISE_DET_CTRL 0x148C |
234 | #define VDEC_C_COMB_FLAT_NOISE_CTRL 0x1490 | 234 | #define VDEC_C_COMB_FLAT_NOISE_CTRL 0x1490 |
235 | #define VDEC_C_VERSION 0x15F8 | 235 | #define VDEC_C_VERSION 0x15F8 |
236 | #define VDEC_C_SOFT_RST_CTRL 0x15FC | 236 | #define VDEC_C_SOFT_RST_CTRL 0x15FC |
237 | 237 | ||
238 | /* Video Decoder D Registers */ | 238 | /* Video Decoder D Registers */ |
239 | #define VDEC_D_MODE_CTRL 0x1600 | 239 | #define VDEC_D_MODE_CTRL 0x1600 |
240 | #define VDEC_D_OUT_CTRL1 0x1604 | 240 | #define VDEC_D_OUT_CTRL1 0x1604 |
241 | #define VDEC_D_OUT_CTRL_NS 0x1608 | 241 | #define VDEC_D_OUT_CTRL_NS 0x1608 |
242 | #define VDEC_D_GEN_STAT 0x160C | 242 | #define VDEC_D_GEN_STAT 0x160C |
243 | #define VDEC_D_INT_STAT_MASK 0x1610 | 243 | #define VDEC_D_INT_STAT_MASK 0x1610 |
244 | #define VDEC_D_LUMA_CTRL 0x1614 | 244 | #define VDEC_D_LUMA_CTRL 0x1614 |
245 | #define VDEC_D_CHROMA_CTRL 0x1618 | 245 | #define VDEC_D_CHROMA_CTRL 0x1618 |
246 | #define VDEC_D_CRUSH_CTRL 0x161C | 246 | #define VDEC_D_CRUSH_CTRL 0x161C |
247 | #define VDEC_D_HORIZ_TIM_CTRL 0x1620 | 247 | #define VDEC_D_HORIZ_TIM_CTRL 0x1620 |
248 | #define VDEC_D_VERT_TIM_CTRL 0x1624 | 248 | #define VDEC_D_VERT_TIM_CTRL 0x1624 |
249 | #define VDEC_D_MISC_TIM_CTRL 0x1628 | 249 | #define VDEC_D_MISC_TIM_CTRL 0x1628 |
250 | #define VDEC_D_FIELD_COUNT 0x162C | 250 | #define VDEC_D_FIELD_COUNT 0x162C |
251 | #define VDEC_D_HSCALE_CTRL 0x1630 | 251 | #define VDEC_D_HSCALE_CTRL 0x1630 |
252 | #define VDEC_D_VSCALE_CTRL 0x1634 | 252 | #define VDEC_D_VSCALE_CTRL 0x1634 |
253 | #define VDEC_D_MAN_VGA_CTRL 0x1638 | 253 | #define VDEC_D_MAN_VGA_CTRL 0x1638 |
254 | #define VDEC_D_MAN_AGC_CTRL 0x163C | 254 | #define VDEC_D_MAN_AGC_CTRL 0x163C |
255 | #define VDEC_D_DFE_CTRL1 0x1640 | 255 | #define VDEC_D_DFE_CTRL1 0x1640 |
256 | #define VDEC_D_DFE_CTRL2 0x1644 | 256 | #define VDEC_D_DFE_CTRL2 0x1644 |
257 | #define VDEC_D_DFE_CTRL3 0x1648 | 257 | #define VDEC_D_DFE_CTRL3 0x1648 |
258 | #define VDEC_D_PLL_CTRL 0x164C | 258 | #define VDEC_D_PLL_CTRL 0x164C |
259 | #define VDEC_D_PLL_CTRL_FAST 0x1650 | 259 | #define VDEC_D_PLL_CTRL_FAST 0x1650 |
260 | #define VDEC_D_HTL_CTRL 0x1654 | 260 | #define VDEC_D_HTL_CTRL 0x1654 |
261 | #define VDEC_D_SRC_CFG 0x1658 | 261 | #define VDEC_D_SRC_CFG 0x1658 |
262 | #define VDEC_D_SC_STEP_SIZE 0x165C | 262 | #define VDEC_D_SC_STEP_SIZE 0x165C |
263 | #define VDEC_D_SC_CONVERGE_CTRL 0x1660 | 263 | #define VDEC_D_SC_CONVERGE_CTRL 0x1660 |
264 | #define VDEC_D_SC_LOOP_CTRL 0x1664 | 264 | #define VDEC_D_SC_LOOP_CTRL 0x1664 |
265 | #define VDEC_D_COMB_2D_HFS_CFG 0x1668 | 265 | #define VDEC_D_COMB_2D_HFS_CFG 0x1668 |
266 | #define VDEC_D_COMB_2D_HFD_CFG 0x166C | 266 | #define VDEC_D_COMB_2D_HFD_CFG 0x166C |
267 | #define VDEC_D_COMB_2D_LF_CFG 0x1670 | 267 | #define VDEC_D_COMB_2D_LF_CFG 0x1670 |
268 | #define VDEC_D_COMB_2D_BLEND 0x1674 | 268 | #define VDEC_D_COMB_2D_BLEND 0x1674 |
269 | #define VDEC_D_COMB_MISC_CTRL 0x1678 | 269 | #define VDEC_D_COMB_MISC_CTRL 0x1678 |
270 | #define VDEC_D_COMB_FLAT_THRESH_CTRL 0x167C | 270 | #define VDEC_D_COMB_FLAT_THRESH_CTRL 0x167C |
271 | #define VDEC_D_COMB_TEST 0x1680 | 271 | #define VDEC_D_COMB_TEST 0x1680 |
272 | #define VDEC_D_BP_MISC_CTRL 0x1684 | 272 | #define VDEC_D_BP_MISC_CTRL 0x1684 |
273 | #define VDEC_D_VCR_DET_CTRL 0x1688 | 273 | #define VDEC_D_VCR_DET_CTRL 0x1688 |
274 | #define VDEC_D_NOISE_DET_CTRL 0x168C | 274 | #define VDEC_D_NOISE_DET_CTRL 0x168C |
275 | #define VDEC_D_COMB_FLAT_NOISE_CTRL 0x1690 | 275 | #define VDEC_D_COMB_FLAT_NOISE_CTRL 0x1690 |
276 | #define VDEC_D_VERSION 0x17F8 | 276 | #define VDEC_D_VERSION 0x17F8 |
277 | #define VDEC_D_SOFT_RST_CTRL 0x17FC | 277 | #define VDEC_D_SOFT_RST_CTRL 0x17FC |
278 | 278 | ||
279 | /* Video Decoder E Registers */ | 279 | /* Video Decoder E Registers */ |
280 | #define VDEC_E_MODE_CTRL 0x1800 | 280 | #define VDEC_E_MODE_CTRL 0x1800 |
281 | #define VDEC_E_OUT_CTRL1 0x1804 | 281 | #define VDEC_E_OUT_CTRL1 0x1804 |
282 | #define VDEC_E_OUT_CTRL_NS 0x1808 | 282 | #define VDEC_E_OUT_CTRL_NS 0x1808 |
283 | #define VDEC_E_GEN_STAT 0x180C | 283 | #define VDEC_E_GEN_STAT 0x180C |
284 | #define VDEC_E_INT_STAT_MASK 0x1810 | 284 | #define VDEC_E_INT_STAT_MASK 0x1810 |
285 | #define VDEC_E_LUMA_CTRL 0x1814 | 285 | #define VDEC_E_LUMA_CTRL 0x1814 |
286 | #define VDEC_E_CHROMA_CTRL 0x1818 | 286 | #define VDEC_E_CHROMA_CTRL 0x1818 |
287 | #define VDEC_E_CRUSH_CTRL 0x181C | 287 | #define VDEC_E_CRUSH_CTRL 0x181C |
288 | #define VDEC_E_HORIZ_TIM_CTRL 0x1820 | 288 | #define VDEC_E_HORIZ_TIM_CTRL 0x1820 |
289 | #define VDEC_E_VERT_TIM_CTRL 0x1824 | 289 | #define VDEC_E_VERT_TIM_CTRL 0x1824 |
290 | #define VDEC_E_MISC_TIM_CTRL 0x1828 | 290 | #define VDEC_E_MISC_TIM_CTRL 0x1828 |
291 | #define VDEC_E_FIELD_COUNT 0x182C | 291 | #define VDEC_E_FIELD_COUNT 0x182C |
292 | #define VDEC_E_HSCALE_CTRL 0x1830 | 292 | #define VDEC_E_HSCALE_CTRL 0x1830 |
293 | #define VDEC_E_VSCALE_CTRL 0x1834 | 293 | #define VDEC_E_VSCALE_CTRL 0x1834 |
294 | #define VDEC_E_MAN_VGA_CTRL 0x1838 | 294 | #define VDEC_E_MAN_VGA_CTRL 0x1838 |
295 | #define VDEC_E_MAN_AGC_CTRL 0x183C | 295 | #define VDEC_E_MAN_AGC_CTRL 0x183C |
296 | #define VDEC_E_DFE_CTRL1 0x1840 | 296 | #define VDEC_E_DFE_CTRL1 0x1840 |
297 | #define VDEC_E_DFE_CTRL2 0x1844 | 297 | #define VDEC_E_DFE_CTRL2 0x1844 |
298 | #define VDEC_E_DFE_CTRL3 0x1848 | 298 | #define VDEC_E_DFE_CTRL3 0x1848 |
299 | #define VDEC_E_PLL_CTRL 0x184C | 299 | #define VDEC_E_PLL_CTRL 0x184C |
300 | #define VDEC_E_PLL_CTRL_FAST 0x1850 | 300 | #define VDEC_E_PLL_CTRL_FAST 0x1850 |
301 | #define VDEC_E_HTL_CTRL 0x1854 | 301 | #define VDEC_E_HTL_CTRL 0x1854 |
302 | #define VDEC_E_SRC_CFG 0x1858 | 302 | #define VDEC_E_SRC_CFG 0x1858 |
303 | #define VDEC_E_SC_STEP_SIZE 0x185C | 303 | #define VDEC_E_SC_STEP_SIZE 0x185C |
304 | #define VDEC_E_SC_CONVERGE_CTRL 0x1860 | 304 | #define VDEC_E_SC_CONVERGE_CTRL 0x1860 |
305 | #define VDEC_E_SC_LOOP_CTRL 0x1864 | 305 | #define VDEC_E_SC_LOOP_CTRL 0x1864 |
306 | #define VDEC_E_COMB_2D_HFS_CFG 0x1868 | 306 | #define VDEC_E_COMB_2D_HFS_CFG 0x1868 |
307 | #define VDEC_E_COMB_2D_HFD_CFG 0x186C | 307 | #define VDEC_E_COMB_2D_HFD_CFG 0x186C |
308 | #define VDEC_E_COMB_2D_LF_CFG 0x1870 | 308 | #define VDEC_E_COMB_2D_LF_CFG 0x1870 |
309 | #define VDEC_E_COMB_2D_BLEND 0x1874 | 309 | #define VDEC_E_COMB_2D_BLEND 0x1874 |
310 | #define VDEC_E_COMB_MISC_CTRL 0x1878 | 310 | #define VDEC_E_COMB_MISC_CTRL 0x1878 |
311 | #define VDEC_E_COMB_FLAT_THRESH_CTRL 0x187C | 311 | #define VDEC_E_COMB_FLAT_THRESH_CTRL 0x187C |
312 | #define VDEC_E_COMB_TEST 0x1880 | 312 | #define VDEC_E_COMB_TEST 0x1880 |
313 | #define VDEC_E_BP_MISC_CTRL 0x1884 | 313 | #define VDEC_E_BP_MISC_CTRL 0x1884 |
314 | #define VDEC_E_VCR_DET_CTRL 0x1888 | 314 | #define VDEC_E_VCR_DET_CTRL 0x1888 |
315 | #define VDEC_E_NOISE_DET_CTRL 0x188C | 315 | #define VDEC_E_NOISE_DET_CTRL 0x188C |
316 | #define VDEC_E_COMB_FLAT_NOISE_CTRL 0x1890 | 316 | #define VDEC_E_COMB_FLAT_NOISE_CTRL 0x1890 |
317 | #define VDEC_E_VERSION 0x19F8 | 317 | #define VDEC_E_VERSION 0x19F8 |
318 | #define VDEC_E_SOFT_RST_CTRL 0x19FC | 318 | #define VDEC_E_SOFT_RST_CTRL 0x19FC |
319 | 319 | ||
320 | /* Video Decoder F Registers */ | 320 | /* Video Decoder F Registers */ |
321 | #define VDEC_F_MODE_CTRL 0x1A00 | 321 | #define VDEC_F_MODE_CTRL 0x1A00 |
322 | #define VDEC_F_OUT_CTRL1 0x1A04 | 322 | #define VDEC_F_OUT_CTRL1 0x1A04 |
323 | #define VDEC_F_OUT_CTRL_NS 0x1A08 | 323 | #define VDEC_F_OUT_CTRL_NS 0x1A08 |
324 | #define VDEC_F_GEN_STAT 0x1A0C | 324 | #define VDEC_F_GEN_STAT 0x1A0C |
325 | #define VDEC_F_INT_STAT_MASK 0x1A10 | 325 | #define VDEC_F_INT_STAT_MASK 0x1A10 |
326 | #define VDEC_F_LUMA_CTRL 0x1A14 | 326 | #define VDEC_F_LUMA_CTRL 0x1A14 |
327 | #define VDEC_F_CHROMA_CTRL 0x1A18 | 327 | #define VDEC_F_CHROMA_CTRL 0x1A18 |
328 | #define VDEC_F_CRUSH_CTRL 0x1A1C | 328 | #define VDEC_F_CRUSH_CTRL 0x1A1C |
329 | #define VDEC_F_HORIZ_TIM_CTRL 0x1A20 | 329 | #define VDEC_F_HORIZ_TIM_CTRL 0x1A20 |
330 | #define VDEC_F_VERT_TIM_CTRL 0x1A24 | 330 | #define VDEC_F_VERT_TIM_CTRL 0x1A24 |
331 | #define VDEC_F_MISC_TIM_CTRL 0x1A28 | 331 | #define VDEC_F_MISC_TIM_CTRL 0x1A28 |
332 | #define VDEC_F_FIELD_COUNT 0x1A2C | 332 | #define VDEC_F_FIELD_COUNT 0x1A2C |
333 | #define VDEC_F_HSCALE_CTRL 0x1A30 | 333 | #define VDEC_F_HSCALE_CTRL 0x1A30 |
334 | #define VDEC_F_VSCALE_CTRL 0x1A34 | 334 | #define VDEC_F_VSCALE_CTRL 0x1A34 |
335 | #define VDEC_F_MAN_VGA_CTRL 0x1A38 | 335 | #define VDEC_F_MAN_VGA_CTRL 0x1A38 |
336 | #define VDEC_F_MAN_AGC_CTRL 0x1A3C | 336 | #define VDEC_F_MAN_AGC_CTRL 0x1A3C |
337 | #define VDEC_F_DFE_CTRL1 0x1A40 | 337 | #define VDEC_F_DFE_CTRL1 0x1A40 |
338 | #define VDEC_F_DFE_CTRL2 0x1A44 | 338 | #define VDEC_F_DFE_CTRL2 0x1A44 |
339 | #define VDEC_F_DFE_CTRL3 0x1A48 | 339 | #define VDEC_F_DFE_CTRL3 0x1A48 |
340 | #define VDEC_F_PLL_CTRL 0x1A4C | 340 | #define VDEC_F_PLL_CTRL 0x1A4C |
341 | #define VDEC_F_PLL_CTRL_FAST 0x1A50 | 341 | #define VDEC_F_PLL_CTRL_FAST 0x1A50 |
342 | #define VDEC_F_HTL_CTRL 0x1A54 | 342 | #define VDEC_F_HTL_CTRL 0x1A54 |
343 | #define VDEC_F_SRC_CFG 0x1A58 | 343 | #define VDEC_F_SRC_CFG 0x1A58 |
344 | #define VDEC_F_SC_STEP_SIZE 0x1A5C | 344 | #define VDEC_F_SC_STEP_SIZE 0x1A5C |
345 | #define VDEC_F_SC_CONVERGE_CTRL 0x1A60 | 345 | #define VDEC_F_SC_CONVERGE_CTRL 0x1A60 |
346 | #define VDEC_F_SC_LOOP_CTRL 0x1A64 | 346 | #define VDEC_F_SC_LOOP_CTRL 0x1A64 |
347 | #define VDEC_F_COMB_2D_HFS_CFG 0x1A68 | 347 | #define VDEC_F_COMB_2D_HFS_CFG 0x1A68 |
348 | #define VDEC_F_COMB_2D_HFD_CFG 0x1A6C | 348 | #define VDEC_F_COMB_2D_HFD_CFG 0x1A6C |
349 | #define VDEC_F_COMB_2D_LF_CFG 0x1A70 | 349 | #define VDEC_F_COMB_2D_LF_CFG 0x1A70 |
350 | #define VDEC_F_COMB_2D_BLEND 0x1A74 | 350 | #define VDEC_F_COMB_2D_BLEND 0x1A74 |
351 | #define VDEC_F_COMB_MISC_CTRL 0x1A78 | 351 | #define VDEC_F_COMB_MISC_CTRL 0x1A78 |
352 | #define VDEC_F_COMB_FLAT_THRESH_CTRL 0x1A7C | 352 | #define VDEC_F_COMB_FLAT_THRESH_CTRL 0x1A7C |
353 | #define VDEC_F_COMB_TEST 0x1A80 | 353 | #define VDEC_F_COMB_TEST 0x1A80 |
354 | #define VDEC_F_BP_MISC_CTRL 0x1A84 | 354 | #define VDEC_F_BP_MISC_CTRL 0x1A84 |
355 | #define VDEC_F_VCR_DET_CTRL 0x1A88 | 355 | #define VDEC_F_VCR_DET_CTRL 0x1A88 |
356 | #define VDEC_F_NOISE_DET_CTRL 0x1A8C | 356 | #define VDEC_F_NOISE_DET_CTRL 0x1A8C |
357 | #define VDEC_F_COMB_FLAT_NOISE_CTRL 0x1A90 | 357 | #define VDEC_F_COMB_FLAT_NOISE_CTRL 0x1A90 |
358 | #define VDEC_F_VERSION 0x1BF8 | 358 | #define VDEC_F_VERSION 0x1BF8 |
359 | #define VDEC_F_SOFT_RST_CTRL 0x1BFC | 359 | #define VDEC_F_SOFT_RST_CTRL 0x1BFC |
360 | 360 | ||
361 | /* Video Decoder G Registers */ | 361 | /* Video Decoder G Registers */ |
362 | #define VDEC_G_MODE_CTRL 0x1C00 | 362 | #define VDEC_G_MODE_CTRL 0x1C00 |
363 | #define VDEC_G_OUT_CTRL1 0x1C04 | 363 | #define VDEC_G_OUT_CTRL1 0x1C04 |
364 | #define VDEC_G_OUT_CTRL_NS 0x1C08 | 364 | #define VDEC_G_OUT_CTRL_NS 0x1C08 |
365 | #define VDEC_G_GEN_STAT 0x1C0C | 365 | #define VDEC_G_GEN_STAT 0x1C0C |
366 | #define VDEC_G_INT_STAT_MASK 0x1C10 | 366 | #define VDEC_G_INT_STAT_MASK 0x1C10 |
367 | #define VDEC_G_LUMA_CTRL 0x1C14 | 367 | #define VDEC_G_LUMA_CTRL 0x1C14 |
368 | #define VDEC_G_CHROMA_CTRL 0x1C18 | 368 | #define VDEC_G_CHROMA_CTRL 0x1C18 |
369 | #define VDEC_G_CRUSH_CTRL 0x1C1C | 369 | #define VDEC_G_CRUSH_CTRL 0x1C1C |
370 | #define VDEC_G_HORIZ_TIM_CTRL 0x1C20 | 370 | #define VDEC_G_HORIZ_TIM_CTRL 0x1C20 |
371 | #define VDEC_G_VERT_TIM_CTRL 0x1C24 | 371 | #define VDEC_G_VERT_TIM_CTRL 0x1C24 |
372 | #define VDEC_G_MISC_TIM_CTRL 0x1C28 | 372 | #define VDEC_G_MISC_TIM_CTRL 0x1C28 |
373 | #define VDEC_G_FIELD_COUNT 0x1C2C | 373 | #define VDEC_G_FIELD_COUNT 0x1C2C |
374 | #define VDEC_G_HSCALE_CTRL 0x1C30 | 374 | #define VDEC_G_HSCALE_CTRL 0x1C30 |
375 | #define VDEC_G_VSCALE_CTRL 0x1C34 | 375 | #define VDEC_G_VSCALE_CTRL 0x1C34 |
376 | #define VDEC_G_MAN_VGA_CTRL 0x1C38 | 376 | #define VDEC_G_MAN_VGA_CTRL 0x1C38 |
377 | #define VDEC_G_MAN_AGC_CTRL 0x1C3C | 377 | #define VDEC_G_MAN_AGC_CTRL 0x1C3C |
378 | #define VDEC_G_DFE_CTRL1 0x1C40 | 378 | #define VDEC_G_DFE_CTRL1 0x1C40 |
379 | #define VDEC_G_DFE_CTRL2 0x1C44 | 379 | #define VDEC_G_DFE_CTRL2 0x1C44 |
380 | #define VDEC_G_DFE_CTRL3 0x1C48 | 380 | #define VDEC_G_DFE_CTRL3 0x1C48 |
381 | #define VDEC_G_PLL_CTRL 0x1C4C | 381 | #define VDEC_G_PLL_CTRL 0x1C4C |
382 | #define VDEC_G_PLL_CTRL_FAST 0x1C50 | 382 | #define VDEC_G_PLL_CTRL_FAST 0x1C50 |
383 | #define VDEC_G_HTL_CTRL 0x1C54 | 383 | #define VDEC_G_HTL_CTRL 0x1C54 |
384 | #define VDEC_G_SRC_CFG 0x1C58 | 384 | #define VDEC_G_SRC_CFG 0x1C58 |
385 | #define VDEC_G_SC_STEP_SIZE 0x1C5C | 385 | #define VDEC_G_SC_STEP_SIZE 0x1C5C |
386 | #define VDEC_G_SC_CONVERGE_CTRL 0x1C60 | 386 | #define VDEC_G_SC_CONVERGE_CTRL 0x1C60 |
387 | #define VDEC_G_SC_LOOP_CTRL 0x1C64 | 387 | #define VDEC_G_SC_LOOP_CTRL 0x1C64 |
388 | #define VDEC_G_COMB_2D_HFS_CFG 0x1C68 | 388 | #define VDEC_G_COMB_2D_HFS_CFG 0x1C68 |
389 | #define VDEC_G_COMB_2D_HFD_CFG 0x1C6C | 389 | #define VDEC_G_COMB_2D_HFD_CFG 0x1C6C |
390 | #define VDEC_G_COMB_2D_LF_CFG 0x1C70 | 390 | #define VDEC_G_COMB_2D_LF_CFG 0x1C70 |
391 | #define VDEC_G_COMB_2D_BLEND 0x1C74 | 391 | #define VDEC_G_COMB_2D_BLEND 0x1C74 |
392 | #define VDEC_G_COMB_MISC_CTRL 0x1C78 | 392 | #define VDEC_G_COMB_MISC_CTRL 0x1C78 |
393 | #define VDEC_G_COMB_FLAT_THRESH_CTRL 0x1C7C | 393 | #define VDEC_G_COMB_FLAT_THRESH_CTRL 0x1C7C |
394 | #define VDEC_G_COMB_TEST 0x1C80 | 394 | #define VDEC_G_COMB_TEST 0x1C80 |
395 | #define VDEC_G_BP_MISC_CTRL 0x1C84 | 395 | #define VDEC_G_BP_MISC_CTRL 0x1C84 |
396 | #define VDEC_G_VCR_DET_CTRL 0x1C88 | 396 | #define VDEC_G_VCR_DET_CTRL 0x1C88 |
397 | #define VDEC_G_NOISE_DET_CTRL 0x1C8C | 397 | #define VDEC_G_NOISE_DET_CTRL 0x1C8C |
398 | #define VDEC_G_COMB_FLAT_NOISE_CTRL 0x1C90 | 398 | #define VDEC_G_COMB_FLAT_NOISE_CTRL 0x1C90 |
399 | #define VDEC_G_VERSION 0x1DF8 | 399 | #define VDEC_G_VERSION 0x1DF8 |
400 | #define VDEC_G_SOFT_RST_CTRL 0x1DFC | 400 | #define VDEC_G_SOFT_RST_CTRL 0x1DFC |
401 | 401 | ||
402 | /* Video Decoder H Registers */ | 402 | /* Video Decoder H Registers */ |
403 | #define VDEC_H_MODE_CTRL 0x1E00 | 403 | #define VDEC_H_MODE_CTRL 0x1E00 |
404 | #define VDEC_H_OUT_CTRL1 0x1E04 | 404 | #define VDEC_H_OUT_CTRL1 0x1E04 |
405 | #define VDEC_H_OUT_CTRL_NS 0x1E08 | 405 | #define VDEC_H_OUT_CTRL_NS 0x1E08 |
406 | #define VDEC_H_GEN_STAT 0x1E0C | 406 | #define VDEC_H_GEN_STAT 0x1E0C |
407 | #define VDEC_H_INT_STAT_MASK 0x1E1E | 407 | #define VDEC_H_INT_STAT_MASK 0x1E1E |
408 | #define VDEC_H_LUMA_CTRL 0x1E14 | 408 | #define VDEC_H_LUMA_CTRL 0x1E14 |
409 | #define VDEC_H_CHROMA_CTRL 0x1E18 | 409 | #define VDEC_H_CHROMA_CTRL 0x1E18 |
410 | #define VDEC_H_CRUSH_CTRL 0x1E1C | 410 | #define VDEC_H_CRUSH_CTRL 0x1E1C |
411 | #define VDEC_H_HORIZ_TIM_CTRL 0x1E20 | 411 | #define VDEC_H_HORIZ_TIM_CTRL 0x1E20 |
412 | #define VDEC_H_VERT_TIM_CTRL 0x1E24 | 412 | #define VDEC_H_VERT_TIM_CTRL 0x1E24 |
413 | #define VDEC_H_MISC_TIM_CTRL 0x1E28 | 413 | #define VDEC_H_MISC_TIM_CTRL 0x1E28 |
414 | #define VDEC_H_FIELD_COUNT 0x1E2C | 414 | #define VDEC_H_FIELD_COUNT 0x1E2C |
415 | #define VDEC_H_HSCALE_CTRL 0x1E30 | 415 | #define VDEC_H_HSCALE_CTRL 0x1E30 |
416 | #define VDEC_H_VSCALE_CTRL 0x1E34 | 416 | #define VDEC_H_VSCALE_CTRL 0x1E34 |
417 | #define VDEC_H_MAN_VGA_CTRL 0x1E38 | 417 | #define VDEC_H_MAN_VGA_CTRL 0x1E38 |
418 | #define VDEC_H_MAN_AGC_CTRL 0x1E3C | 418 | #define VDEC_H_MAN_AGC_CTRL 0x1E3C |
419 | #define VDEC_H_DFE_CTRL1 0x1E40 | 419 | #define VDEC_H_DFE_CTRL1 0x1E40 |
420 | #define VDEC_H_DFE_CTRL2 0x1E44 | 420 | #define VDEC_H_DFE_CTRL2 0x1E44 |
421 | #define VDEC_H_DFE_CTRL3 0x1E48 | 421 | #define VDEC_H_DFE_CTRL3 0x1E48 |
422 | #define VDEC_H_PLL_CTRL 0x1E4C | 422 | #define VDEC_H_PLL_CTRL 0x1E4C |
423 | #define VDEC_H_PLL_CTRL_FAST 0x1E50 | 423 | #define VDEC_H_PLL_CTRL_FAST 0x1E50 |
424 | #define VDEC_H_HTL_CTRL 0x1E54 | 424 | #define VDEC_H_HTL_CTRL 0x1E54 |
425 | #define VDEC_H_SRC_CFG 0x1E58 | 425 | #define VDEC_H_SRC_CFG 0x1E58 |
426 | #define VDEC_H_SC_STEP_SIZE 0x1E5C | 426 | #define VDEC_H_SC_STEP_SIZE 0x1E5C |
427 | #define VDEC_H_SC_CONVERGE_CTRL 0x1E60 | 427 | #define VDEC_H_SC_CONVERGE_CTRL 0x1E60 |
428 | #define VDEC_H_SC_LOOP_CTRL 0x1E64 | 428 | #define VDEC_H_SC_LOOP_CTRL 0x1E64 |
429 | #define VDEC_H_COMB_2D_HFS_CFG 0x1E68 | 429 | #define VDEC_H_COMB_2D_HFS_CFG 0x1E68 |
430 | #define VDEC_H_COMB_2D_HFD_CFG 0x1E6C | 430 | #define VDEC_H_COMB_2D_HFD_CFG 0x1E6C |
431 | #define VDEC_H_COMB_2D_LF_CFG 0x1E70 | 431 | #define VDEC_H_COMB_2D_LF_CFG 0x1E70 |
432 | #define VDEC_H_COMB_2D_BLEND 0x1E74 | 432 | #define VDEC_H_COMB_2D_BLEND 0x1E74 |
433 | #define VDEC_H_COMB_MISC_CTRL 0x1E78 | 433 | #define VDEC_H_COMB_MISC_CTRL 0x1E78 |
434 | #define VDEC_H_COMB_FLAT_THRESH_CTRL 0x1E7C | 434 | #define VDEC_H_COMB_FLAT_THRESH_CTRL 0x1E7C |
435 | #define VDEC_H_COMB_TEST 0x1E80 | 435 | #define VDEC_H_COMB_TEST 0x1E80 |
436 | #define VDEC_H_BP_MISC_CTRL 0x1E84 | 436 | #define VDEC_H_BP_MISC_CTRL 0x1E84 |
437 | #define VDEC_H_VCR_DET_CTRL 0x1E88 | 437 | #define VDEC_H_VCR_DET_CTRL 0x1E88 |
438 | #define VDEC_H_NOISE_DET_CTRL 0x1E8C | 438 | #define VDEC_H_NOISE_DET_CTRL 0x1E8C |
439 | #define VDEC_H_COMB_FLAT_NOISE_CTRL 0x1E90 | 439 | #define VDEC_H_COMB_FLAT_NOISE_CTRL 0x1E90 |
440 | #define VDEC_H_VERSION 0x1FF8 | 440 | #define VDEC_H_VERSION 0x1FF8 |
441 | #define VDEC_H_SOFT_RST_CTRL 0x1FFC | 441 | #define VDEC_H_SOFT_RST_CTRL 0x1FFC |
442 | 442 | ||
443 | /*****************************************************************************/ | 443 | /*****************************************************************************/ |
444 | /* LUMA_CTRL register fields */ | 444 | /* LUMA_CTRL register fields */ |
445 | #define VDEC_A_BRITE_CTRL 0x1014 | 445 | #define VDEC_A_BRITE_CTRL 0x1014 |
446 | #define VDEC_A_CNTRST_CTRL 0x1015 | 446 | #define VDEC_A_CNTRST_CTRL 0x1015 |
447 | #define VDEC_A_PEAK_SEL 0x1016 | 447 | #define VDEC_A_PEAK_SEL 0x1016 |
448 | 448 | ||
diff --git a/drivers/media/video/cx25821/cx25821-medusa-video.c b/drivers/media/video/cx25821/cx25821-medusa-video.c index fc780d0908dc..298a68d98c2f 100644 --- a/drivers/media/video/cx25821/cx25821-medusa-video.c +++ b/drivers/media/video/cx25821/cx25821-medusa-video.c | |||
@@ -99,82 +99,67 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) | |||
99 | 99 | ||
100 | for (i = 0; i < MAX_DECODERS; i++) { | 100 | for (i = 0; i < MAX_DECODERS; i++) { |
101 | /* set video format NTSC-M */ | 101 | /* set video format NTSC-M */ |
102 | value = | 102 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
103 | cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | 103 | MODE_CTRL + (0x200 * i), &tmp); |
104 | &tmp); | ||
105 | value &= 0xFFFFFFF0; | 104 | value &= 0xFFFFFFF0; |
106 | /* enable the fast locking mode bit[16] */ | 105 | /* enable the fast locking mode bit[16] */ |
107 | value |= 0x10001; | 106 | value |= 0x10001; |
108 | ret_val = | 107 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
109 | cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | 108 | MODE_CTRL + (0x200 * i), value); |
110 | value); | ||
111 | 109 | ||
112 | /* resolution NTSC 720x480 */ | 110 | /* resolution NTSC 720x480 */ |
113 | value = | 111 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
114 | cx25821_i2c_read(&dev->i2c_bus[0], | 112 | HORIZ_TIM_CTRL + (0x200 * i), &tmp); |
115 | HORIZ_TIM_CTRL + (0x200 * i), &tmp); | ||
116 | value &= 0x00C00C00; | 113 | value &= 0x00C00C00; |
117 | value |= 0x612D0074; | 114 | value |= 0x612D0074; |
118 | ret_val = | 115 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
119 | cx25821_i2c_write(&dev->i2c_bus[0], | 116 | HORIZ_TIM_CTRL + (0x200 * i), value); |
120 | HORIZ_TIM_CTRL + (0x200 * i), value); | ||
121 | 117 | ||
122 | value = | 118 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
123 | cx25821_i2c_read(&dev->i2c_bus[0], | 119 | VERT_TIM_CTRL + (0x200 * i), &tmp); |
124 | VERT_TIM_CTRL + (0x200 * i), &tmp); | ||
125 | value &= 0x00C00C00; | 120 | value &= 0x00C00C00; |
126 | value |= 0x1C1E001A; /* vblank_cnt + 2 to get camera ID */ | 121 | value |= 0x1C1E001A; /* vblank_cnt + 2 to get camera ID */ |
127 | ret_val = | 122 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
128 | cx25821_i2c_write(&dev->i2c_bus[0], | 123 | VERT_TIM_CTRL + (0x200 * i), value); |
129 | VERT_TIM_CTRL + (0x200 * i), value); | ||
130 | 124 | ||
131 | /* chroma subcarrier step size */ | 125 | /* chroma subcarrier step size */ |
132 | ret_val = | 126 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
133 | cx25821_i2c_write(&dev->i2c_bus[0], | 127 | SC_STEP_SIZE + (0x200 * i), 0x43E00000); |
134 | SC_STEP_SIZE + (0x200 * i), 0x43E00000); | ||
135 | 128 | ||
136 | /* enable VIP optional active */ | 129 | /* enable VIP optional active */ |
137 | value = | 130 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
138 | cx25821_i2c_read(&dev->i2c_bus[0], | 131 | OUT_CTRL_NS + (0x200 * i), &tmp); |
139 | OUT_CTRL_NS + (0x200 * i), &tmp); | ||
140 | value &= 0xFFFBFFFF; | 132 | value &= 0xFFFBFFFF; |
141 | value |= 0x00040000; | 133 | value |= 0x00040000; |
142 | ret_val = | 134 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
143 | cx25821_i2c_write(&dev->i2c_bus[0], | 135 | OUT_CTRL_NS + (0x200 * i), value); |
144 | OUT_CTRL_NS + (0x200 * i), value); | ||
145 | 136 | ||
146 | /* enable VIP optional active (VIP_OPT_AL) for direct output. */ | 137 | /* enable VIP optional active (VIP_OPT_AL) for direct output. */ |
147 | value = | 138 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
148 | cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | 139 | OUT_CTRL1 + (0x200 * i), &tmp); |
149 | &tmp); | ||
150 | value &= 0xFFFBFFFF; | 140 | value &= 0xFFFBFFFF; |
151 | value |= 0x00040000; | 141 | value |= 0x00040000; |
152 | ret_val = | 142 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
153 | cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | 143 | OUT_CTRL1 + (0x200 * i), value); |
154 | value); | ||
155 | 144 | ||
156 | /* | 145 | /* |
157 | * clear VPRES_VERT_EN bit, fixes the chroma run away problem | 146 | * clear VPRES_VERT_EN bit, fixes the chroma run away problem |
158 | * when the input switching rate < 16 fields | 147 | * when the input switching rate < 16 fields |
159 | */ | 148 | */ |
160 | value = | 149 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
161 | cx25821_i2c_read(&dev->i2c_bus[0], | 150 | MISC_TIM_CTRL + (0x200 * i), &tmp); |
162 | MISC_TIM_CTRL + (0x200 * i), &tmp); | ||
163 | /* disable special play detection */ | 151 | /* disable special play detection */ |
164 | value = setBitAtPos(value, 14); | 152 | value = setBitAtPos(value, 14); |
165 | value = clearBitAtPos(value, 15); | 153 | value = clearBitAtPos(value, 15); |
166 | ret_val = | 154 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
167 | cx25821_i2c_write(&dev->i2c_bus[0], | 155 | MISC_TIM_CTRL + (0x200 * i), value); |
168 | MISC_TIM_CTRL + (0x200 * i), value); | ||
169 | 156 | ||
170 | /* set vbi_gate_en to 0 */ | 157 | /* set vbi_gate_en to 0 */ |
171 | value = | 158 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
172 | cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | 159 | DFE_CTRL1 + (0x200 * i), &tmp); |
173 | &tmp); | ||
174 | value = clearBitAtPos(value, 29); | 160 | value = clearBitAtPos(value, 29); |
175 | ret_val = | 161 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
176 | cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | 162 | DFE_CTRL1 + (0x200 * i), value); |
177 | value); | ||
178 | 163 | ||
179 | /* Enable the generation of blue field output if no video */ | 164 | /* Enable the generation of blue field output if no video */ |
180 | medusa_enable_bluefield_output(dev, i, 1); | 165 | medusa_enable_bluefield_output(dev, i, 1); |
@@ -182,61 +167,49 @@ static int medusa_initialize_ntsc(struct cx25821_dev *dev) | |||
182 | 167 | ||
183 | for (i = 0; i < MAX_ENCODERS; i++) { | 168 | for (i = 0; i < MAX_ENCODERS; i++) { |
184 | /* NTSC hclock */ | 169 | /* NTSC hclock */ |
185 | value = | 170 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
186 | cx25821_i2c_read(&dev->i2c_bus[0], | 171 | DENC_A_REG_1 + (0x100 * i), &tmp); |
187 | DENC_A_REG_1 + (0x100 * i), &tmp); | ||
188 | value &= 0xF000FC00; | 172 | value &= 0xF000FC00; |
189 | value |= 0x06B402D0; | 173 | value |= 0x06B402D0; |
190 | ret_val = | 174 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
191 | cx25821_i2c_write(&dev->i2c_bus[0], | 175 | DENC_A_REG_1 + (0x100 * i), value); |
192 | DENC_A_REG_1 + (0x100 * i), value); | ||
193 | 176 | ||
194 | /* burst begin and burst end */ | 177 | /* burst begin and burst end */ |
195 | value = | 178 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
196 | cx25821_i2c_read(&dev->i2c_bus[0], | 179 | DENC_A_REG_2 + (0x100 * i), &tmp); |
197 | DENC_A_REG_2 + (0x100 * i), &tmp); | ||
198 | value &= 0xFF000000; | 180 | value &= 0xFF000000; |
199 | value |= 0x007E9054; | 181 | value |= 0x007E9054; |
200 | ret_val = | 182 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
201 | cx25821_i2c_write(&dev->i2c_bus[0], | 183 | DENC_A_REG_2 + (0x100 * i), value); |
202 | DENC_A_REG_2 + (0x100 * i), value); | ||
203 | 184 | ||
204 | value = | 185 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
205 | cx25821_i2c_read(&dev->i2c_bus[0], | 186 | DENC_A_REG_3 + (0x100 * i), &tmp); |
206 | DENC_A_REG_3 + (0x100 * i), &tmp); | ||
207 | value &= 0xFC00FE00; | 187 | value &= 0xFC00FE00; |
208 | value |= 0x00EC00F0; | 188 | value |= 0x00EC00F0; |
209 | ret_val = | 189 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
210 | cx25821_i2c_write(&dev->i2c_bus[0], | 190 | DENC_A_REG_3 + (0x100 * i), value); |
211 | DENC_A_REG_3 + (0x100 * i), value); | ||
212 | 191 | ||
213 | /* set NTSC vblank, no phase alternation, 7.5 IRE pedestal */ | 192 | /* set NTSC vblank, no phase alternation, 7.5 IRE pedestal */ |
214 | value = | 193 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
215 | cx25821_i2c_read(&dev->i2c_bus[0], | 194 | DENC_A_REG_4 + (0x100 * i), &tmp); |
216 | DENC_A_REG_4 + (0x100 * i), &tmp); | ||
217 | value &= 0x00FCFFFF; | 195 | value &= 0x00FCFFFF; |
218 | value |= 0x13020000; | 196 | value |= 0x13020000; |
219 | ret_val = | 197 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
220 | cx25821_i2c_write(&dev->i2c_bus[0], | 198 | DENC_A_REG_4 + (0x100 * i), value); |
221 | DENC_A_REG_4 + (0x100 * i), value); | ||
222 | 199 | ||
223 | value = | 200 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
224 | cx25821_i2c_read(&dev->i2c_bus[0], | 201 | DENC_A_REG_5 + (0x100 * i), &tmp); |
225 | DENC_A_REG_5 + (0x100 * i), &tmp); | ||
226 | value &= 0xFFFF0000; | 202 | value &= 0xFFFF0000; |
227 | value |= 0x0000E575; | 203 | value |= 0x0000E575; |
228 | ret_val = | 204 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
229 | cx25821_i2c_write(&dev->i2c_bus[0], | 205 | DENC_A_REG_5 + (0x100 * i), value); |
230 | DENC_A_REG_5 + (0x100 * i), value); | ||
231 | 206 | ||
232 | ret_val = | 207 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
233 | cx25821_i2c_write(&dev->i2c_bus[0], | 208 | DENC_A_REG_6 + (0x100 * i), 0x009A89C1); |
234 | DENC_A_REG_6 + (0x100 * i), 0x009A89C1); | ||
235 | 209 | ||
236 | /* Subcarrier Increment */ | 210 | /* Subcarrier Increment */ |
237 | ret_val = | 211 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
238 | cx25821_i2c_write(&dev->i2c_bus[0], | 212 | DENC_A_REG_7 + (0x100 * i), 0x21F07C1F); |
239 | DENC_A_REG_7 + (0x100 * i), 0x21F07C1F); | ||
240 | } | 213 | } |
241 | 214 | ||
242 | /* set picture resolutions */ | 215 | /* set picture resolutions */ |
@@ -261,34 +234,27 @@ static int medusa_PALCombInit(struct cx25821_dev *dev, int dec) | |||
261 | u32 value = 0, tmp = 0; | 234 | u32 value = 0, tmp = 0; |
262 | 235 | ||
263 | /* Setup for 2D threshold */ | 236 | /* Setup for 2D threshold */ |
264 | ret_val = | 237 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
265 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG + (0x200 * dec), | 238 | COMB_2D_HFS_CFG + (0x200 * dec), 0x20002861); |
266 | 0x20002861); | 239 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
267 | ret_val = | 240 | COMB_2D_HFD_CFG + (0x200 * dec), 0x20002861); |
268 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG + (0x200 * dec), | 241 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
269 | 0x20002861); | 242 | COMB_2D_LF_CFG + (0x200 * dec), 0x200A1023); |
270 | ret_val = | ||
271 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG + (0x200 * dec), | ||
272 | 0x200A1023); | ||
273 | 243 | ||
274 | /* Setup flat chroma and luma thresholds */ | 244 | /* Setup flat chroma and luma thresholds */ |
275 | value = | 245 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
276 | cx25821_i2c_read(&dev->i2c_bus[0], | 246 | COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp); |
277 | COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp); | ||
278 | value &= 0x06230000; | 247 | value &= 0x06230000; |
279 | ret_val = | 248 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
280 | cx25821_i2c_write(&dev->i2c_bus[0], | 249 | COMB_FLAT_THRESH_CTRL + (0x200 * dec), value); |
281 | COMB_FLAT_THRESH_CTRL + (0x200 * dec), value); | ||
282 | 250 | ||
283 | /* set comb 2D blend */ | 251 | /* set comb 2D blend */ |
284 | ret_val = | 252 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
285 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND + (0x200 * dec), | 253 | COMB_2D_BLEND + (0x200 * dec), 0x210F0F0F); |
286 | 0x210F0F0F); | ||
287 | 254 | ||
288 | /* COMB MISC CONTROL */ | 255 | /* COMB MISC CONTROL */ |
289 | ret_val = | 256 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
290 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL + (0x200 * dec), | 257 | COMB_MISC_CTRL + (0x200 * dec), 0x41120A7F); |
291 | 0x41120A7F); | ||
292 | 258 | ||
293 | return ret_val; | 259 | return ret_val; |
294 | } | 260 | } |
@@ -304,83 +270,68 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) | |||
304 | 270 | ||
305 | for (i = 0; i < MAX_DECODERS; i++) { | 271 | for (i = 0; i < MAX_DECODERS; i++) { |
306 | /* set video format PAL-BDGHI */ | 272 | /* set video format PAL-BDGHI */ |
307 | value = | 273 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
308 | cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | 274 | MODE_CTRL + (0x200 * i), &tmp); |
309 | &tmp); | ||
310 | value &= 0xFFFFFFF0; | 275 | value &= 0xFFFFFFF0; |
311 | /* enable the fast locking mode bit[16] */ | 276 | /* enable the fast locking mode bit[16] */ |
312 | value |= 0x10004; | 277 | value |= 0x10004; |
313 | ret_val = | 278 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
314 | cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | 279 | MODE_CTRL + (0x200 * i), value); |
315 | value); | ||
316 | 280 | ||
317 | /* resolution PAL 720x576 */ | 281 | /* resolution PAL 720x576 */ |
318 | value = | 282 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
319 | cx25821_i2c_read(&dev->i2c_bus[0], | 283 | HORIZ_TIM_CTRL + (0x200 * i), &tmp); |
320 | HORIZ_TIM_CTRL + (0x200 * i), &tmp); | ||
321 | value &= 0x00C00C00; | 284 | value &= 0x00C00C00; |
322 | value |= 0x632D007D; | 285 | value |= 0x632D007D; |
323 | ret_val = | 286 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
324 | cx25821_i2c_write(&dev->i2c_bus[0], | 287 | HORIZ_TIM_CTRL + (0x200 * i), value); |
325 | HORIZ_TIM_CTRL + (0x200 * i), value); | ||
326 | 288 | ||
327 | /* vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 */ | 289 | /* vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 */ |
328 | value = | 290 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
329 | cx25821_i2c_read(&dev->i2c_bus[0], | 291 | VERT_TIM_CTRL + (0x200 * i), &tmp); |
330 | VERT_TIM_CTRL + (0x200 * i), &tmp); | ||
331 | value &= 0x00C00C00; | 292 | value &= 0x00C00C00; |
332 | value |= 0x28240026; /* vblank_cnt + 2 to get camera ID */ | 293 | value |= 0x28240026; /* vblank_cnt + 2 to get camera ID */ |
333 | ret_val = | 294 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
334 | cx25821_i2c_write(&dev->i2c_bus[0], | 295 | VERT_TIM_CTRL + (0x200 * i), value); |
335 | VERT_TIM_CTRL + (0x200 * i), value); | ||
336 | 296 | ||
337 | /* chroma subcarrier step size */ | 297 | /* chroma subcarrier step size */ |
338 | ret_val = | 298 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
339 | cx25821_i2c_write(&dev->i2c_bus[0], | 299 | SC_STEP_SIZE + (0x200 * i), 0x5411E2D0); |
340 | SC_STEP_SIZE + (0x200 * i), 0x5411E2D0); | ||
341 | 300 | ||
342 | /* enable VIP optional active */ | 301 | /* enable VIP optional active */ |
343 | value = | 302 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
344 | cx25821_i2c_read(&dev->i2c_bus[0], | 303 | OUT_CTRL_NS + (0x200 * i), &tmp); |
345 | OUT_CTRL_NS + (0x200 * i), &tmp); | ||
346 | value &= 0xFFFBFFFF; | 304 | value &= 0xFFFBFFFF; |
347 | value |= 0x00040000; | 305 | value |= 0x00040000; |
348 | ret_val = | 306 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
349 | cx25821_i2c_write(&dev->i2c_bus[0], | 307 | OUT_CTRL_NS + (0x200 * i), value); |
350 | OUT_CTRL_NS + (0x200 * i), value); | ||
351 | 308 | ||
352 | /* enable VIP optional active (VIP_OPT_AL) for direct output. */ | 309 | /* enable VIP optional active (VIP_OPT_AL) for direct output. */ |
353 | value = | 310 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
354 | cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | 311 | OUT_CTRL1 + (0x200 * i), &tmp); |
355 | &tmp); | ||
356 | value &= 0xFFFBFFFF; | 312 | value &= 0xFFFBFFFF; |
357 | value |= 0x00040000; | 313 | value |= 0x00040000; |
358 | ret_val = | 314 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
359 | cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | 315 | OUT_CTRL1 + (0x200 * i), value); |
360 | value); | ||
361 | 316 | ||
362 | /* | 317 | /* |
363 | * clear VPRES_VERT_EN bit, fixes the chroma run away problem | 318 | * clear VPRES_VERT_EN bit, fixes the chroma run away problem |
364 | * when the input switching rate < 16 fields | 319 | * when the input switching rate < 16 fields |
365 | */ | 320 | */ |
366 | value = | 321 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
367 | cx25821_i2c_read(&dev->i2c_bus[0], | 322 | MISC_TIM_CTRL + (0x200 * i), &tmp); |
368 | MISC_TIM_CTRL + (0x200 * i), &tmp); | ||
369 | /* disable special play detection */ | 323 | /* disable special play detection */ |
370 | value = setBitAtPos(value, 14); | 324 | value = setBitAtPos(value, 14); |
371 | value = clearBitAtPos(value, 15); | 325 | value = clearBitAtPos(value, 15); |
372 | ret_val = | 326 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
373 | cx25821_i2c_write(&dev->i2c_bus[0], | 327 | MISC_TIM_CTRL + (0x200 * i), value); |
374 | MISC_TIM_CTRL + (0x200 * i), value); | ||
375 | 328 | ||
376 | /* set vbi_gate_en to 0 */ | 329 | /* set vbi_gate_en to 0 */ |
377 | value = | 330 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
378 | cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | 331 | DFE_CTRL1 + (0x200 * i), &tmp); |
379 | &tmp); | ||
380 | value = clearBitAtPos(value, 29); | 332 | value = clearBitAtPos(value, 29); |
381 | ret_val = | 333 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
382 | cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | 334 | DFE_CTRL1 + (0x200 * i), value); |
383 | value); | ||
384 | 335 | ||
385 | medusa_PALCombInit(dev, i); | 336 | medusa_PALCombInit(dev, i); |
386 | 337 | ||
@@ -390,62 +341,50 @@ static int medusa_initialize_pal(struct cx25821_dev *dev) | |||
390 | 341 | ||
391 | for (i = 0; i < MAX_ENCODERS; i++) { | 342 | for (i = 0; i < MAX_ENCODERS; i++) { |
392 | /* PAL hclock */ | 343 | /* PAL hclock */ |
393 | value = | 344 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
394 | cx25821_i2c_read(&dev->i2c_bus[0], | 345 | DENC_A_REG_1 + (0x100 * i), &tmp); |
395 | DENC_A_REG_1 + (0x100 * i), &tmp); | ||
396 | value &= 0xF000FC00; | 346 | value &= 0xF000FC00; |
397 | value |= 0x06C002D0; | 347 | value |= 0x06C002D0; |
398 | ret_val = | 348 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
399 | cx25821_i2c_write(&dev->i2c_bus[0], | 349 | DENC_A_REG_1 + (0x100 * i), value); |
400 | DENC_A_REG_1 + (0x100 * i), value); | ||
401 | 350 | ||
402 | /* burst begin and burst end */ | 351 | /* burst begin and burst end */ |
403 | value = | 352 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
404 | cx25821_i2c_read(&dev->i2c_bus[0], | 353 | DENC_A_REG_2 + (0x100 * i), &tmp); |
405 | DENC_A_REG_2 + (0x100 * i), &tmp); | ||
406 | value &= 0xFF000000; | 354 | value &= 0xFF000000; |
407 | value |= 0x007E9754; | 355 | value |= 0x007E9754; |
408 | ret_val = | 356 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
409 | cx25821_i2c_write(&dev->i2c_bus[0], | 357 | DENC_A_REG_2 + (0x100 * i), value); |
410 | DENC_A_REG_2 + (0x100 * i), value); | ||
411 | 358 | ||
412 | /* hblank and vactive */ | 359 | /* hblank and vactive */ |
413 | value = | 360 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
414 | cx25821_i2c_read(&dev->i2c_bus[0], | 361 | DENC_A_REG_3 + (0x100 * i), &tmp); |
415 | DENC_A_REG_3 + (0x100 * i), &tmp); | ||
416 | value &= 0xFC00FE00; | 362 | value &= 0xFC00FE00; |
417 | value |= 0x00FC0120; | 363 | value |= 0x00FC0120; |
418 | ret_val = | 364 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
419 | cx25821_i2c_write(&dev->i2c_bus[0], | 365 | DENC_A_REG_3 + (0x100 * i), value); |
420 | DENC_A_REG_3 + (0x100 * i), value); | ||
421 | 366 | ||
422 | /* set PAL vblank, phase alternation, 0 IRE pedestal */ | 367 | /* set PAL vblank, phase alternation, 0 IRE pedestal */ |
423 | value = | 368 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
424 | cx25821_i2c_read(&dev->i2c_bus[0], | 369 | DENC_A_REG_4 + (0x100 * i), &tmp); |
425 | DENC_A_REG_4 + (0x100 * i), &tmp); | ||
426 | value &= 0x00FCFFFF; | 370 | value &= 0x00FCFFFF; |
427 | value |= 0x14010000; | 371 | value |= 0x14010000; |
428 | ret_val = | 372 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
429 | cx25821_i2c_write(&dev->i2c_bus[0], | 373 | DENC_A_REG_4 + (0x100 * i), value); |
430 | DENC_A_REG_4 + (0x100 * i), value); | ||
431 | 374 | ||
432 | value = | 375 | value = cx25821_i2c_read(&dev->i2c_bus[0], |
433 | cx25821_i2c_read(&dev->i2c_bus[0], | 376 | DENC_A_REG_5 + (0x100 * i), &tmp); |
434 | DENC_A_REG_5 + (0x100 * i), &tmp); | ||
435 | value &= 0xFFFF0000; | 377 | value &= 0xFFFF0000; |
436 | value |= 0x0000F078; | 378 | value |= 0x0000F078; |
437 | ret_val = | 379 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
438 | cx25821_i2c_write(&dev->i2c_bus[0], | 380 | DENC_A_REG_5 + (0x100 * i), value); |
439 | DENC_A_REG_5 + (0x100 * i), value); | ||
440 | 381 | ||
441 | ret_val = | 382 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
442 | cx25821_i2c_write(&dev->i2c_bus[0], | 383 | DENC_A_REG_6 + (0x100 * i), 0x00A493CF); |
443 | DENC_A_REG_6 + (0x100 * i), 0x00A493CF); | ||
444 | 384 | ||
445 | /* Subcarrier Increment */ | 385 | /* Subcarrier Increment */ |
446 | ret_val = | 386 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
447 | cx25821_i2c_write(&dev->i2c_bus[0], | 387 | DENC_A_REG_7 + (0x100 * i), 0x2A098ACB); |
448 | DENC_A_REG_7 + (0x100 * i), 0x2A098ACB); | ||
449 | } | 388 | } |
450 | 389 | ||
451 | /* set picture resolutions */ | 390 | /* set picture resolutions */ |
@@ -499,7 +438,7 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width, | |||
499 | 438 | ||
500 | mutex_lock(&dev->lock); | 439 | mutex_lock(&dev->lock); |
501 | 440 | ||
502 | /* validate the width - cannot be negative */ | 441 | /* validate the width */ |
503 | if (width > MAX_WIDTH) { | 442 | if (width > MAX_WIDTH) { |
504 | pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n", | 443 | pr_info("%s(): width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n", |
505 | __func__, width, MAX_WIDTH); | 444 | __func__, width, MAX_WIDTH); |
@@ -543,12 +482,10 @@ void medusa_set_resolution(struct cx25821_dev *dev, int width, | |||
543 | 482 | ||
544 | for (; decoder < decoder_count; decoder++) { | 483 | for (; decoder < decoder_count; decoder++) { |
545 | /* write scaling values for each decoder */ | 484 | /* write scaling values for each decoder */ |
546 | ret_val = | 485 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
547 | cx25821_i2c_write(&dev->i2c_bus[0], | 486 | HSCALE_CTRL + (0x200 * decoder), hscale); |
548 | HSCALE_CTRL + (0x200 * decoder), hscale); | 487 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], |
549 | ret_val = | 488 | VSCALE_CTRL + (0x200 * decoder), vscale); |
550 | cx25821_i2c_write(&dev->i2c_bus[0], | ||
551 | VSCALE_CTRL + (0x200 * decoder), vscale); | ||
552 | } | 489 | } |
553 | 490 | ||
554 | mutex_unlock(&dev->lock); | 491 | mutex_unlock(&dev->lock); |
@@ -606,8 +543,8 @@ static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, | |||
606 | } | 543 | } |
607 | 544 | ||
608 | /* Map to Medusa register setting */ | 545 | /* Map to Medusa register setting */ |
609 | static int mapM(int srcMin, | 546 | static int mapM(int srcMin, int srcMax, int srcVal, int dstMin, int dstMax, |
610 | int srcMax, int srcVal, int dstMin, int dstMax, int *dstVal) | 547 | int *dstVal) |
611 | { | 548 | { |
612 | int numerator; | 549 | int numerator; |
613 | int denominator; | 550 | int denominator; |
@@ -654,23 +591,19 @@ int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder) | |||
654 | u32 val = 0, tmp = 0; | 591 | u32 val = 0, tmp = 0; |
655 | 592 | ||
656 | mutex_lock(&dev->lock); | 593 | mutex_lock(&dev->lock); |
657 | if ((brightness > VIDEO_PROCAMP_MAX) | 594 | if ((brightness > VIDEO_PROCAMP_MAX) || |
658 | || (brightness < VIDEO_PROCAMP_MIN)) { | 595 | (brightness < VIDEO_PROCAMP_MIN)) { |
659 | mutex_unlock(&dev->lock); | 596 | mutex_unlock(&dev->lock); |
660 | return -1; | 597 | return -1; |
661 | } | 598 | } |
662 | ret_val = | 599 | ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness, |
663 | mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness, | 600 | SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); |
664 | SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); | ||
665 | value = convert_to_twos(value, 8); | 601 | value = convert_to_twos(value, 8); |
666 | val = | 602 | val = cx25821_i2c_read(&dev->i2c_bus[0], |
667 | cx25821_i2c_read(&dev->i2c_bus[0], | 603 | VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp); |
668 | VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp); | ||
669 | val &= 0xFFFFFF00; | 604 | val &= 0xFFFFFF00; |
670 | ret_val |= | 605 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], |
671 | cx25821_i2c_write(&dev->i2c_bus[0], | 606 | VDEC_A_BRITE_CTRL + (0x200 * decoder), val | value); |
672 | VDEC_A_BRITE_CTRL + (0x200 * decoder), | ||
673 | val | value); | ||
674 | mutex_unlock(&dev->lock); | 607 | mutex_unlock(&dev->lock); |
675 | return ret_val; | 608 | return ret_val; |
676 | } | 609 | } |
@@ -688,17 +621,13 @@ int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder) | |||
688 | return -1; | 621 | return -1; |
689 | } | 622 | } |
690 | 623 | ||
691 | ret_val = | 624 | ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast, |
692 | mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast, | 625 | UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); |
693 | UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); | 626 | val = cx25821_i2c_read(&dev->i2c_bus[0], |
694 | val = | 627 | VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp); |
695 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
696 | VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp); | ||
697 | val &= 0xFFFFFF00; | 628 | val &= 0xFFFFFF00; |
698 | ret_val |= | 629 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], |
699 | cx25821_i2c_write(&dev->i2c_bus[0], | 630 | VDEC_A_CNTRST_CTRL + (0x200 * decoder), val | value); |
700 | VDEC_A_CNTRST_CTRL + (0x200 * decoder), | ||
701 | val | value); | ||
702 | 631 | ||
703 | mutex_unlock(&dev->lock); | 632 | mutex_unlock(&dev->lock); |
704 | return ret_val; | 633 | return ret_val; |
@@ -717,19 +646,16 @@ int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder) | |||
717 | return -1; | 646 | return -1; |
718 | } | 647 | } |
719 | 648 | ||
720 | ret_val = | 649 | ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, |
721 | mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN, | 650 | SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); |
722 | SIGNED_BYTE_MAX, &value); | ||
723 | 651 | ||
724 | value = convert_to_twos(value, 8); | 652 | value = convert_to_twos(value, 8); |
725 | val = | 653 | val = cx25821_i2c_read(&dev->i2c_bus[0], |
726 | cx25821_i2c_read(&dev->i2c_bus[0], | 654 | VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp); |
727 | VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp); | ||
728 | val &= 0xFFFFFF00; | 655 | val &= 0xFFFFFF00; |
729 | 656 | ||
730 | ret_val |= | 657 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], |
731 | cx25821_i2c_write(&dev->i2c_bus[0], | 658 | VDEC_A_HUE_CTRL + (0x200 * decoder), val | value); |
732 | VDEC_A_HUE_CTRL + (0x200 * decoder), val | value); | ||
733 | 659 | ||
734 | mutex_unlock(&dev->lock); | 660 | mutex_unlock(&dev->lock); |
735 | return ret_val; | 661 | return ret_val; |
@@ -743,33 +669,26 @@ int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) | |||
743 | 669 | ||
744 | mutex_lock(&dev->lock); | 670 | mutex_lock(&dev->lock); |
745 | 671 | ||
746 | if ((saturation > VIDEO_PROCAMP_MAX) | 672 | if ((saturation > VIDEO_PROCAMP_MAX) || |
747 | || (saturation < VIDEO_PROCAMP_MIN)) { | 673 | (saturation < VIDEO_PROCAMP_MIN)) { |
748 | mutex_unlock(&dev->lock); | 674 | mutex_unlock(&dev->lock); |
749 | return -1; | 675 | return -1; |
750 | } | 676 | } |
751 | 677 | ||
752 | ret_val = | 678 | ret_val = mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation, |
753 | mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation, | 679 | UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); |
754 | UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); | ||
755 | 680 | ||
756 | val = | 681 | val = cx25821_i2c_read(&dev->i2c_bus[0], |
757 | cx25821_i2c_read(&dev->i2c_bus[0], | 682 | VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp); |
758 | VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp); | ||
759 | val &= 0xFFFFFF00; | 683 | val &= 0xFFFFFF00; |
760 | ret_val |= | 684 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], |
761 | cx25821_i2c_write(&dev->i2c_bus[0], | 685 | VDEC_A_USAT_CTRL + (0x200 * decoder), val | value); |
762 | VDEC_A_USAT_CTRL + (0x200 * decoder), | 686 | |
763 | val | value); | 687 | val = cx25821_i2c_read(&dev->i2c_bus[0], |
764 | 688 | VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp); | |
765 | val = | ||
766 | cx25821_i2c_read(&dev->i2c_bus[0], | ||
767 | VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp); | ||
768 | val &= 0xFFFFFF00; | 689 | val &= 0xFFFFFF00; |
769 | ret_val |= | 690 | ret_val |= cx25821_i2c_write(&dev->i2c_bus[0], |
770 | cx25821_i2c_write(&dev->i2c_bus[0], | 691 | VDEC_A_VSAT_CTRL + (0x200 * decoder), val | value); |
771 | VDEC_A_VSAT_CTRL + (0x200 * decoder), | ||
772 | val | value); | ||
773 | 692 | ||
774 | mutex_unlock(&dev->lock); | 693 | mutex_unlock(&dev->lock); |
775 | return ret_val; | 694 | return ret_val; |
@@ -830,9 +749,8 @@ int medusa_video_init(struct cx25821_dev *dev) | |||
830 | /* select AFE clock to output mode */ | 749 | /* select AFE clock to output mode */ |
831 | value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); | 750 | value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); |
832 | value &= 0x83FFFFFF; | 751 | value &= 0x83FFFFFF; |
833 | ret_val = | 752 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, |
834 | cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, | 753 | value | 0x10000000); |
835 | value | 0x10000000); | ||
836 | 754 | ||
837 | if (ret_val < 0) | 755 | if (ret_val < 0) |
838 | goto error; | 756 | goto error; |
diff --git a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c index 2a724ddfa53f..5a157cf4a95e 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c +++ b/drivers/media/video/cx25821/cx25821-video-upstream-ch2.c | |||
@@ -65,9 +65,8 @@ static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev, | |||
65 | *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2 + offset); | 65 | *(rp++) = cpu_to_le32(dev->_data_buf_phys_addr_ch2 + offset); |
66 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | 66 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ |
67 | 67 | ||
68 | if ((lines <= NTSC_FIELD_HEIGHT) | 68 | if ((lines <= NTSC_FIELD_HEIGHT) || |
69 | || (line < (NTSC_FIELD_HEIGHT - 1)) | 69 | (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) { |
70 | || !(dev->_isNTSC_ch2)) { | ||
71 | offset += dist_betwn_starts; | 70 | offset += dist_betwn_starts; |
72 | } | 71 | } |
73 | } | 72 | } |
@@ -85,7 +84,7 @@ static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev, | |||
85 | { | 84 | { |
86 | unsigned int line, i; | 85 | unsigned int line, i; |
87 | struct sram_channel *sram_ch = | 86 | struct sram_channel *sram_ch = |
88 | dev->channels[dev->_channel2_upstream_select].sram_channels; | 87 | dev->channels[dev->_channel2_upstream_select].sram_channels; |
89 | int dist_betwn_starts = bpl * 2; | 88 | int dist_betwn_starts = bpl * 2; |
90 | 89 | ||
91 | /* sync instruction */ | 90 | /* sync instruction */ |
@@ -103,9 +102,8 @@ static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev, | |||
103 | *(rp++) = cpu_to_le32(databuf_phys_addr + offset); | 102 | *(rp++) = cpu_to_le32(databuf_phys_addr + offset); |
104 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ | 103 | *(rp++) = cpu_to_le32(0); /* bits 63-32 */ |
105 | 104 | ||
106 | if ((lines <= NTSC_FIELD_HEIGHT) | 105 | if ((lines <= NTSC_FIELD_HEIGHT) || |
107 | || (line < (NTSC_FIELD_HEIGHT - 1)) | 106 | (line < (NTSC_FIELD_HEIGHT - 1)) || !(dev->_isNTSC_ch2)) { |
108 | || !(dev->_isNTSC_ch2)) { | ||
109 | offset += dist_betwn_starts; | 107 | offset += dist_betwn_starts; |
110 | } | 108 | } |
111 | 109 | ||
@@ -173,7 +171,7 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev, | |||
173 | 171 | ||
174 | fifo_enable = FIFO_DISABLE; | 172 | fifo_enable = FIFO_DISABLE; |
175 | 173 | ||
176 | /* Even field */ | 174 | /* Even field */ |
177 | rp = cx25821_risc_field_upstream_ch2(dev, rp, | 175 | rp = cx25821_risc_field_upstream_ch2(dev, rp, |
178 | dev->_data_buf_phys_addr_ch2 + databuf_offset, | 176 | dev->_data_buf_phys_addr_ch2 + databuf_offset, |
179 | bottom_offset, 0x200, bpl, singlefield_lines, | 177 | bottom_offset, 0x200, bpl, singlefield_lines, |
@@ -189,9 +187,9 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev, | |||
189 | } | 187 | } |
190 | 188 | ||
191 | /* | 189 | /* |
192 | Loop to 2ndFrameRISC or to Start of | 190 | * Loop to 2ndFrameRISC or to Start of |
193 | Risc program & generate IRQ | 191 | * Risc program & generate IRQ |
194 | */ | 192 | */ |
195 | *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); | 193 | *(rp++) = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | risc_flag); |
196 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); | 194 | *(rp++) = cpu_to_le32(risc_phys_jump_addr); |
197 | *(rp++) = cpu_to_le32(0); | 195 | *(rp++) = cpu_to_le32(0); |
@@ -203,7 +201,7 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev, | |||
203 | void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) | 201 | void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) |
204 | { | 202 | { |
205 | struct sram_channel *sram_ch = | 203 | struct sram_channel *sram_ch = |
206 | dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels; | 204 | dev->channels[VID_UPSTREAM_SRAM_CHANNEL_J].sram_channels; |
207 | u32 tmp = 0; | 205 | u32 tmp = 0; |
208 | 206 | ||
209 | if (!dev->_is_running_ch2) { | 207 | if (!dev->_is_running_ch2) { |
@@ -262,9 +260,8 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
262 | struct file *myfile; | 260 | struct file *myfile; |
263 | int frame_index_temp = dev->_frame_index_ch2; | 261 | int frame_index_temp = dev->_frame_index_ch2; |
264 | int i = 0; | 262 | int i = 0; |
265 | int line_size = | 263 | int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? |
266 | (dev->_pixel_format_ch2 == | 264 | Y411_LINE_SZ : Y422_LINE_SZ; |
267 | PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; | ||
268 | int frame_size = 0; | 265 | int frame_size = 0; |
269 | int frame_offset = 0; | 266 | int frame_offset = 0; |
270 | ssize_t vfs_read_retval = 0; | 267 | ssize_t vfs_read_retval = 0; |
@@ -277,14 +274,11 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
277 | return 0; | 274 | return 0; |
278 | 275 | ||
279 | if (dev->_isNTSC_ch2) { | 276 | if (dev->_isNTSC_ch2) { |
280 | frame_size = | 277 | frame_size = (line_size == Y411_LINE_SZ) ? |
281 | (line_size == | 278 | FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; |
282 | Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : | ||
283 | FRAME_SIZE_NTSC_Y422; | ||
284 | } else { | 279 | } else { |
285 | frame_size = | 280 | frame_size = (line_size == Y411_LINE_SZ) ? |
286 | (line_size == | 281 | FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; |
287 | Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; | ||
288 | } | 282 | } |
289 | 283 | ||
290 | frame_offset = (frame_index_temp > 0) ? frame_size : 0; | 284 | frame_offset = (frame_index_temp > 0) ? frame_size : 0; |
@@ -318,14 +312,14 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
318 | for (i = 0; i < dev->_lines_count_ch2; i++) { | 312 | for (i = 0; i < dev->_lines_count_ch2; i++) { |
319 | pos = file_offset; | 313 | pos = file_offset; |
320 | 314 | ||
321 | vfs_read_retval = | 315 | vfs_read_retval = vfs_read(myfile, mybuf, line_size, |
322 | vfs_read(myfile, mybuf, line_size, &pos); | 316 | &pos); |
323 | 317 | ||
324 | if (vfs_read_retval > 0 && vfs_read_retval == line_size | 318 | if (vfs_read_retval > 0 && vfs_read_retval == line_size |
325 | && dev->_data_buf_virt_addr_ch2 != NULL) { | 319 | && dev->_data_buf_virt_addr_ch2 != NULL) { |
326 | memcpy((void *)(dev->_data_buf_virt_addr_ch2 + | 320 | memcpy((void *)(dev->_data_buf_virt_addr_ch2 + |
327 | frame_offset / 4), mybuf, | 321 | frame_offset / 4), mybuf, |
328 | vfs_read_retval); | 322 | vfs_read_retval); |
329 | } | 323 | } |
330 | 324 | ||
331 | file_offset += vfs_read_retval; | 325 | file_offset += vfs_read_retval; |
@@ -341,8 +335,8 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
341 | if (i > 0) | 335 | if (i > 0) |
342 | dev->_frame_count_ch2++; | 336 | dev->_frame_count_ch2++; |
343 | 337 | ||
344 | dev->_file_status_ch2 = | 338 | dev->_file_status_ch2 = (vfs_read_retval == line_size) ? |
345 | (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | 339 | IN_PROGRESS : END_OF_FILE; |
346 | 340 | ||
347 | set_fs(old_fs); | 341 | set_fs(old_fs); |
348 | filp_close(myfile, NULL); | 342 | filp_close(myfile, NULL); |
@@ -353,8 +347,8 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
353 | 347 | ||
354 | static void cx25821_vidups_handler_ch2(struct work_struct *work) | 348 | static void cx25821_vidups_handler_ch2(struct work_struct *work) |
355 | { | 349 | { |
356 | struct cx25821_dev *dev = | 350 | struct cx25821_dev *dev = container_of(work, struct cx25821_dev, |
357 | container_of(work, struct cx25821_dev, _irq_work_entry_ch2); | 351 | _irq_work_entry_ch2); |
358 | 352 | ||
359 | if (!dev) { | 353 | if (!dev) { |
360 | pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", | 354 | pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", |
@@ -362,18 +356,16 @@ static void cx25821_vidups_handler_ch2(struct work_struct *work) | |||
362 | return; | 356 | return; |
363 | } | 357 | } |
364 | 358 | ||
365 | cx25821_get_frame_ch2(dev, | 359 | cx25821_get_frame_ch2(dev, dev->channels[dev-> |
366 | dev->channels[dev-> | 360 | _channel2_upstream_select].sram_channels); |
367 | _channel2_upstream_select].sram_channels); | ||
368 | } | 361 | } |
369 | 362 | ||
370 | int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) | 363 | int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) |
371 | { | 364 | { |
372 | struct file *myfile; | 365 | struct file *myfile; |
373 | int i = 0, j = 0; | 366 | int i = 0, j = 0; |
374 | int line_size = | 367 | int line_size = (dev->_pixel_format_ch2 == PIXEL_FRMT_411) ? |
375 | (dev->_pixel_format_ch2 == | 368 | Y411_LINE_SZ : Y422_LINE_SZ; |
376 | PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; | ||
377 | ssize_t vfs_read_retval = 0; | 369 | ssize_t vfs_read_retval = 0; |
378 | char mybuf[line_size]; | 370 | char mybuf[line_size]; |
379 | loff_t pos; | 371 | loff_t pos; |
@@ -410,16 +402,16 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
410 | for (i = 0; i < dev->_lines_count_ch2; i++) { | 402 | for (i = 0; i < dev->_lines_count_ch2; i++) { |
411 | pos = offset; | 403 | pos = offset; |
412 | 404 | ||
413 | vfs_read_retval = | 405 | vfs_read_retval = vfs_read(myfile, mybuf, |
414 | vfs_read(myfile, mybuf, line_size, &pos); | 406 | line_size, &pos); |
415 | 407 | ||
416 | if (vfs_read_retval > 0 | 408 | if (vfs_read_retval > 0 && |
417 | && vfs_read_retval == line_size | 409 | vfs_read_retval == line_size && |
418 | && dev->_data_buf_virt_addr_ch2 != NULL) { | 410 | dev->_data_buf_virt_addr_ch2 != NULL) { |
419 | memcpy((void *)(dev-> | 411 | memcpy((void *)(dev-> |
420 | _data_buf_virt_addr_ch2 | 412 | _data_buf_virt_addr_ch2 |
421 | + offset / 4), mybuf, | 413 | + offset / 4), mybuf, |
422 | vfs_read_retval); | 414 | vfs_read_retval); |
423 | } | 415 | } |
424 | 416 | ||
425 | offset += vfs_read_retval; | 417 | offset += vfs_read_retval; |
@@ -438,8 +430,8 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
438 | break; | 430 | break; |
439 | } | 431 | } |
440 | 432 | ||
441 | dev->_file_status_ch2 = | 433 | dev->_file_status_ch2 = (vfs_read_retval == line_size) ? |
442 | (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | 434 | IN_PROGRESS : END_OF_FILE; |
443 | 435 | ||
444 | set_fs(old_fs); | 436 | set_fs(old_fs); |
445 | myfile->f_pos = 0; | 437 | myfile->f_pos = 0; |
@@ -463,9 +455,8 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, | |||
463 | dev->_dma_phys_addr_ch2); | 455 | dev->_dma_phys_addr_ch2); |
464 | } | 456 | } |
465 | 457 | ||
466 | dev->_dma_virt_addr_ch2 = | 458 | dev->_dma_virt_addr_ch2 = pci_alloc_consistent(dev->pci, |
467 | pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size_ch2, | 459 | dev->upstream_riscbuf_size_ch2, &dma_addr); |
468 | &dma_addr); | ||
469 | dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2; | 460 | dev->_dma_virt_start_addr_ch2 = dev->_dma_virt_addr_ch2; |
470 | dev->_dma_phys_start_addr_ch2 = dma_addr; | 461 | dev->_dma_phys_start_addr_ch2 = dma_addr; |
471 | dev->_dma_phys_addr_ch2 = dma_addr; | 462 | dev->_dma_phys_addr_ch2 = dma_addr; |
@@ -485,9 +476,8 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, | |||
485 | dev->_data_buf_phys_addr_ch2); | 476 | dev->_data_buf_phys_addr_ch2); |
486 | } | 477 | } |
487 | /* For Video Data buffer allocation */ | 478 | /* For Video Data buffer allocation */ |
488 | dev->_data_buf_virt_addr_ch2 = | 479 | dev->_data_buf_virt_addr_ch2 = pci_alloc_consistent(dev->pci, |
489 | pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2, | 480 | dev->upstream_databuf_size_ch2, &data_dma_addr); |
490 | &data_dma_addr); | ||
491 | dev->_data_buf_phys_addr_ch2 = data_dma_addr; | 481 | dev->_data_buf_phys_addr_ch2 = data_dma_addr; |
492 | dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2; | 482 | dev->_data_buf_size_ch2 = dev->upstream_databuf_size_ch2; |
493 | 483 | ||
@@ -563,8 +553,8 @@ int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, | |||
563 | else | 553 | else |
564 | line_size_in_bytes = Y422_LINE_SZ; | 554 | line_size_in_bytes = Y422_LINE_SZ; |
565 | risc_phys_jump_addr = | 555 | risc_phys_jump_addr = |
566 | dev->_dma_phys_start_addr_ch2 + | 556 | dev->_dma_phys_start_addr_ch2 + |
567 | odd_risc_prog_size; | 557 | odd_risc_prog_size; |
568 | 558 | ||
569 | rp = cx25821_update_riscprogram_ch2(dev, | 559 | rp = cx25821_update_riscprogram_ch2(dev, |
570 | dev->_dma_virt_start_addr_ch2, | 560 | dev->_dma_virt_start_addr_ch2, |
@@ -612,11 +602,9 @@ static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id) | |||
612 | vid_status = cx_read(sram_ch->int_stat); | 602 | vid_status = cx_read(sram_ch->int_stat); |
613 | 603 | ||
614 | /* Only deal with our interrupt */ | 604 | /* Only deal with our interrupt */ |
615 | if (vid_status) { | 605 | if (vid_status) |
616 | handled = | 606 | handled = cx25821_video_upstream_irq_ch2(dev, channel_num, |
617 | cx25821_video_upstream_irq_ch2(dev, channel_num, | 607 | vid_status); |
618 | vid_status); | ||
619 | } | ||
620 | 608 | ||
621 | if (handled < 0) | 609 | if (handled < 0) |
622 | cx25821_stop_upstream_video_ch2(dev); | 610 | cx25821_stop_upstream_video_ch2(dev); |
@@ -691,8 +679,7 @@ int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, | |||
691 | tmp = cx_read(sram_ch->int_msk); | 679 | tmp = cx_read(sram_ch->int_msk); |
692 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); | 680 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); |
693 | 681 | ||
694 | err = | 682 | err = request_irq(dev->pci->irq, cx25821_upstream_irq_ch2, |
695 | request_irq(dev->pci->irq, cx25821_upstream_irq_ch2, | ||
696 | IRQF_SHARED, dev->name, dev); | 683 | IRQF_SHARED, dev->name, dev); |
697 | if (err < 0) { | 684 | if (err < 0) { |
698 | pr_err("%s: can't get upstream IRQ %d\n", | 685 | pr_err("%s: can't get upstream IRQ %d\n", |
@@ -752,45 +739,38 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, | |||
752 | dev->_file_status_ch2 = RESET_STATUS; | 739 | dev->_file_status_ch2 = RESET_STATUS; |
753 | dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576; | 740 | dev->_lines_count_ch2 = dev->_isNTSC_ch2 ? 480 : 576; |
754 | dev->_pixel_format_ch2 = pixel_format; | 741 | dev->_pixel_format_ch2 = pixel_format; |
755 | dev->_line_size_ch2 = | 742 | dev->_line_size_ch2 = (dev->_pixel_format_ch2 == PIXEL_FRMT_422) ? |
756 | (dev->_pixel_format_ch2 == | 743 | (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; |
757 | PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; | ||
758 | data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; | 744 | data_frame_size = dev->_isNTSC_ch2 ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; |
759 | risc_buffer_size = | 745 | risc_buffer_size = dev->_isNTSC_ch2 ? |
760 | dev->_isNTSC_ch2 ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; | 746 | NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; |
761 | 747 | ||
762 | if (dev->input_filename_ch2) { | 748 | if (dev->input_filename_ch2) { |
763 | str_length = strlen(dev->input_filename_ch2); | 749 | str_length = strlen(dev->input_filename_ch2); |
764 | dev->_filename_ch2 = kmalloc(str_length + 1, GFP_KERNEL); | 750 | dev->_filename_ch2 = kmemdup(dev->input_filename_ch2, |
751 | str_length + 1, GFP_KERNEL); | ||
765 | 752 | ||
766 | if (!dev->_filename_ch2) | 753 | if (!dev->_filename_ch2) |
767 | goto error; | 754 | goto error; |
768 | |||
769 | memcpy(dev->_filename_ch2, dev->input_filename_ch2, | ||
770 | str_length + 1); | ||
771 | } else { | 755 | } else { |
772 | str_length = strlen(dev->_defaultname_ch2); | 756 | str_length = strlen(dev->_defaultname_ch2); |
773 | dev->_filename_ch2 = kmalloc(str_length + 1, GFP_KERNEL); | 757 | dev->_filename_ch2 = kmemdup(dev->_defaultname_ch2, |
758 | str_length + 1, GFP_KERNEL); | ||
774 | 759 | ||
775 | if (!dev->_filename_ch2) | 760 | if (!dev->_filename_ch2) |
776 | goto error; | 761 | goto error; |
777 | |||
778 | memcpy(dev->_filename_ch2, dev->_defaultname_ch2, | ||
779 | str_length + 1); | ||
780 | } | 762 | } |
781 | 763 | ||
782 | /* Default if filename is empty string */ | 764 | /* Default if filename is empty string */ |
783 | if (strcmp(dev->input_filename_ch2, "") == 0) { | 765 | if (strcmp(dev->input_filename_ch2, "") == 0) { |
784 | if (dev->_isNTSC_ch2) { | 766 | if (dev->_isNTSC_ch2) { |
785 | dev->_filename_ch2 = | 767 | dev->_filename_ch2 = (dev->_pixel_format_ch2 == |
786 | (dev->_pixel_format_ch2 == | 768 | PIXEL_FRMT_411) ? "/root/vid411.yuv" : |
787 | PIXEL_FRMT_411) ? "/root/vid411.yuv" : | 769 | "/root/vidtest.yuv"; |
788 | "/root/vidtest.yuv"; | ||
789 | } else { | 770 | } else { |
790 | dev->_filename_ch2 = | 771 | dev->_filename_ch2 = (dev->_pixel_format_ch2 == |
791 | (dev->_pixel_format_ch2 == | 772 | PIXEL_FRMT_411) ? "/root/pal411.yuv" : |
792 | PIXEL_FRMT_411) ? "/root/pal411.yuv" : | 773 | "/root/pal422.yuv"; |
793 | "/root/pal422.yuv"; | ||
794 | } | 774 | } |
795 | } | 775 | } |
796 | 776 | ||
diff --git a/drivers/media/video/cx25821/cx25821-video-upstream.c b/drivers/media/video/cx25821/cx25821-video-upstream.c index c0b80068f468..21e7d657f049 100644 --- a/drivers/media/video/cx25821/cx25821-video-upstream.c +++ b/drivers/media/video/cx25821/cx25821-video-upstream.c | |||
@@ -136,7 +136,7 @@ static __le32 *cx25821_risc_field_upstream(struct cx25821_dev *dev, __le32 * rp, | |||
136 | { | 136 | { |
137 | unsigned int line, i; | 137 | unsigned int line, i; |
138 | struct sram_channel *sram_ch = | 138 | struct sram_channel *sram_ch = |
139 | dev->channels[dev->_channel_upstream_select].sram_channels; | 139 | dev->channels[dev->_channel_upstream_select].sram_channels; |
140 | int dist_betwn_starts = bpl * 2; | 140 | int dist_betwn_starts = bpl * 2; |
141 | 141 | ||
142 | /* sync instruction */ | 142 | /* sync instruction */ |
@@ -194,15 +194,12 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, | |||
194 | if (dev->_isNTSC) { | 194 | if (dev->_isNTSC) { |
195 | odd_num_lines = singlefield_lines + 1; | 195 | odd_num_lines = singlefield_lines + 1; |
196 | risc_program_size = FRAME1_VID_PROG_SIZE; | 196 | risc_program_size = FRAME1_VID_PROG_SIZE; |
197 | frame_size = | 197 | frame_size = (bpl == Y411_LINE_SZ) ? |
198 | (bpl == | 198 | FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; |
199 | Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : | ||
200 | FRAME_SIZE_NTSC_Y422; | ||
201 | } else { | 199 | } else { |
202 | risc_program_size = PAL_VID_PROG_SIZE; | 200 | risc_program_size = PAL_VID_PROG_SIZE; |
203 | frame_size = | 201 | frame_size = (bpl == Y411_LINE_SZ) ? |
204 | (bpl == | 202 | FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; |
205 | Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; | ||
206 | } | 203 | } |
207 | 204 | ||
208 | /* Virtual address of Risc buffer program */ | 205 | /* Virtual address of Risc buffer program */ |
@@ -214,13 +211,9 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, | |||
214 | if (UNSET != top_offset) { | 211 | if (UNSET != top_offset) { |
215 | fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; | 212 | fifo_enable = (frame == 0) ? FIFO_ENABLE : FIFO_DISABLE; |
216 | rp = cx25821_risc_field_upstream(dev, rp, | 213 | rp = cx25821_risc_field_upstream(dev, rp, |
217 | dev-> | 214 | dev->_data_buf_phys_addr + |
218 | _data_buf_phys_addr + | 215 | databuf_offset, top_offset, 0, bpl, |
219 | databuf_offset, | 216 | odd_num_lines, fifo_enable, ODD_FIELD); |
220 | top_offset, 0, bpl, | ||
221 | odd_num_lines, | ||
222 | fifo_enable, | ||
223 | ODD_FIELD); | ||
224 | } | 217 | } |
225 | 218 | ||
226 | fifo_enable = FIFO_DISABLE; | 219 | fifo_enable = FIFO_DISABLE; |
@@ -234,8 +227,8 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, | |||
234 | 227 | ||
235 | if (frame == 0) { | 228 | if (frame == 0) { |
236 | risc_flag = RISC_CNT_RESET; | 229 | risc_flag = RISC_CNT_RESET; |
237 | risc_phys_jump_addr = | 230 | risc_phys_jump_addr = dev->_dma_phys_start_addr + |
238 | dev->_dma_phys_start_addr + risc_program_size; | 231 | risc_program_size; |
239 | } else { | 232 | } else { |
240 | risc_phys_jump_addr = dev->_dma_phys_start_addr; | 233 | risc_phys_jump_addr = dev->_dma_phys_start_addr; |
241 | risc_flag = RISC_CNT_INC; | 234 | risc_flag = RISC_CNT_INC; |
@@ -255,7 +248,7 @@ int cx25821_risc_buffer_upstream(struct cx25821_dev *dev, | |||
255 | void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) | 248 | void cx25821_stop_upstream_video_ch1(struct cx25821_dev *dev) |
256 | { | 249 | { |
257 | struct sram_channel *sram_ch = | 250 | struct sram_channel *sram_ch = |
258 | dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels; | 251 | dev->channels[VID_UPSTREAM_SRAM_CHANNEL_I].sram_channels; |
259 | u32 tmp = 0; | 252 | u32 tmp = 0; |
260 | 253 | ||
261 | if (!dev->_is_running) { | 254 | if (!dev->_is_running) { |
@@ -312,9 +305,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
312 | struct file *myfile; | 305 | struct file *myfile; |
313 | int frame_index_temp = dev->_frame_index; | 306 | int frame_index_temp = dev->_frame_index; |
314 | int i = 0; | 307 | int i = 0; |
315 | int line_size = | 308 | int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ? |
316 | (dev->_pixel_format == | 309 | Y411_LINE_SZ : Y422_LINE_SZ; |
317 | PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; | ||
318 | int frame_size = 0; | 310 | int frame_size = 0; |
319 | int frame_offset = 0; | 311 | int frame_offset = 0; |
320 | ssize_t vfs_read_retval = 0; | 312 | ssize_t vfs_read_retval = 0; |
@@ -326,16 +318,12 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
326 | if (dev->_file_status == END_OF_FILE) | 318 | if (dev->_file_status == END_OF_FILE) |
327 | return 0; | 319 | return 0; |
328 | 320 | ||
329 | if (dev->_isNTSC) { | 321 | if (dev->_isNTSC) |
330 | frame_size = | 322 | frame_size = (line_size == Y411_LINE_SZ) ? |
331 | (line_size == | 323 | FRAME_SIZE_NTSC_Y411 : FRAME_SIZE_NTSC_Y422; |
332 | Y411_LINE_SZ) ? FRAME_SIZE_NTSC_Y411 : | 324 | else |
333 | FRAME_SIZE_NTSC_Y422; | 325 | frame_size = (line_size == Y411_LINE_SZ) ? |
334 | } else { | 326 | FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; |
335 | frame_size = | ||
336 | (line_size == | ||
337 | Y411_LINE_SZ) ? FRAME_SIZE_PAL_Y411 : FRAME_SIZE_PAL_Y422; | ||
338 | } | ||
339 | 327 | ||
340 | frame_offset = (frame_index_temp > 0) ? frame_size : 0; | 328 | frame_offset = (frame_index_temp > 0) ? frame_size : 0; |
341 | file_offset = dev->_frame_count * frame_size; | 329 | file_offset = dev->_frame_count * frame_size; |
@@ -369,8 +357,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
369 | for (i = 0; i < dev->_lines_count; i++) { | 357 | for (i = 0; i < dev->_lines_count; i++) { |
370 | pos = file_offset; | 358 | pos = file_offset; |
371 | 359 | ||
372 | vfs_read_retval = | 360 | vfs_read_retval = vfs_read(myfile, mybuf, line_size, |
373 | vfs_read(myfile, mybuf, line_size, &pos); | 361 | &pos); |
374 | 362 | ||
375 | if (vfs_read_retval > 0 && vfs_read_retval == line_size | 363 | if (vfs_read_retval > 0 && vfs_read_retval == line_size |
376 | && dev->_data_buf_virt_addr != NULL) { | 364 | && dev->_data_buf_virt_addr != NULL) { |
@@ -392,8 +380,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
392 | if (i > 0) | 380 | if (i > 0) |
393 | dev->_frame_count++; | 381 | dev->_frame_count++; |
394 | 382 | ||
395 | dev->_file_status = | 383 | dev->_file_status = (vfs_read_retval == line_size) ? |
396 | (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | 384 | IN_PROGRESS : END_OF_FILE; |
397 | 385 | ||
398 | set_fs(old_fs); | 386 | set_fs(old_fs); |
399 | filp_close(myfile, NULL); | 387 | filp_close(myfile, NULL); |
@@ -404,8 +392,8 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
404 | 392 | ||
405 | static void cx25821_vidups_handler(struct work_struct *work) | 393 | static void cx25821_vidups_handler(struct work_struct *work) |
406 | { | 394 | { |
407 | struct cx25821_dev *dev = | 395 | struct cx25821_dev *dev = container_of(work, struct cx25821_dev, |
408 | container_of(work, struct cx25821_dev, _irq_work_entry); | 396 | _irq_work_entry); |
409 | 397 | ||
410 | if (!dev) { | 398 | if (!dev) { |
411 | pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", | 399 | pr_err("ERROR %s(): since container_of(work_struct) FAILED!\n", |
@@ -413,18 +401,16 @@ static void cx25821_vidups_handler(struct work_struct *work) | |||
413 | return; | 401 | return; |
414 | } | 402 | } |
415 | 403 | ||
416 | cx25821_get_frame(dev, | 404 | cx25821_get_frame(dev, dev->channels[dev->_channel_upstream_select]. |
417 | dev->channels[dev->_channel_upstream_select]. | 405 | sram_channels); |
418 | sram_channels); | ||
419 | } | 406 | } |
420 | 407 | ||
421 | int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) | 408 | int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) |
422 | { | 409 | { |
423 | struct file *myfile; | 410 | struct file *myfile; |
424 | int i = 0, j = 0; | 411 | int i = 0, j = 0; |
425 | int line_size = | 412 | int line_size = (dev->_pixel_format == PIXEL_FRMT_411) ? |
426 | (dev->_pixel_format == | 413 | Y411_LINE_SZ : Y422_LINE_SZ; |
427 | PIXEL_FRMT_411) ? Y411_LINE_SZ : Y422_LINE_SZ; | ||
428 | ssize_t vfs_read_retval = 0; | 414 | ssize_t vfs_read_retval = 0; |
429 | char mybuf[line_size]; | 415 | char mybuf[line_size]; |
430 | loff_t pos; | 416 | loff_t pos; |
@@ -461,8 +447,8 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
461 | for (i = 0; i < dev->_lines_count; i++) { | 447 | for (i = 0; i < dev->_lines_count; i++) { |
462 | pos = offset; | 448 | pos = offset; |
463 | 449 | ||
464 | vfs_read_retval = | 450 | vfs_read_retval = vfs_read(myfile, mybuf, |
465 | vfs_read(myfile, mybuf, line_size, &pos); | 451 | line_size, &pos); |
466 | 452 | ||
467 | if (vfs_read_retval > 0 | 453 | if (vfs_read_retval > 0 |
468 | && vfs_read_retval == line_size | 454 | && vfs_read_retval == line_size |
@@ -489,8 +475,8 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) | |||
489 | break; | 475 | break; |
490 | } | 476 | } |
491 | 477 | ||
492 | dev->_file_status = | 478 | dev->_file_status = (vfs_read_retval == line_size) ? |
493 | (vfs_read_retval == line_size) ? IN_PROGRESS : END_OF_FILE; | 479 | IN_PROGRESS : END_OF_FILE; |
494 | 480 | ||
495 | set_fs(old_fs); | 481 | set_fs(old_fs); |
496 | myfile->f_pos = 0; | 482 | myfile->f_pos = 0; |
@@ -507,14 +493,12 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, | |||
507 | dma_addr_t dma_addr; | 493 | dma_addr_t dma_addr; |
508 | dma_addr_t data_dma_addr; | 494 | dma_addr_t data_dma_addr; |
509 | 495 | ||
510 | if (dev->_dma_virt_addr != NULL) { | 496 | if (dev->_dma_virt_addr != NULL) |
511 | pci_free_consistent(dev->pci, dev->upstream_riscbuf_size, | 497 | pci_free_consistent(dev->pci, dev->upstream_riscbuf_size, |
512 | dev->_dma_virt_addr, dev->_dma_phys_addr); | 498 | dev->_dma_virt_addr, dev->_dma_phys_addr); |
513 | } | ||
514 | 499 | ||
515 | dev->_dma_virt_addr = | 500 | dev->_dma_virt_addr = pci_alloc_consistent(dev->pci, |
516 | pci_alloc_consistent(dev->pci, dev->upstream_riscbuf_size, | 501 | dev->upstream_riscbuf_size, &dma_addr); |
517 | &dma_addr); | ||
518 | dev->_dma_virt_start_addr = dev->_dma_virt_addr; | 502 | dev->_dma_virt_start_addr = dev->_dma_virt_addr; |
519 | dev->_dma_phys_start_addr = dma_addr; | 503 | dev->_dma_phys_start_addr = dma_addr; |
520 | dev->_dma_phys_addr = dma_addr; | 504 | dev->_dma_phys_addr = dma_addr; |
@@ -528,15 +512,13 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, | |||
528 | /* Clear memory at address */ | 512 | /* Clear memory at address */ |
529 | memset(dev->_dma_virt_addr, 0, dev->_risc_size); | 513 | memset(dev->_dma_virt_addr, 0, dev->_risc_size); |
530 | 514 | ||
531 | if (dev->_data_buf_virt_addr != NULL) { | 515 | if (dev->_data_buf_virt_addr != NULL) |
532 | pci_free_consistent(dev->pci, dev->upstream_databuf_size, | 516 | pci_free_consistent(dev->pci, dev->upstream_databuf_size, |
533 | dev->_data_buf_virt_addr, | 517 | dev->_data_buf_virt_addr, |
534 | dev->_data_buf_phys_addr); | 518 | dev->_data_buf_phys_addr); |
535 | } | ||
536 | /* For Video Data buffer allocation */ | 519 | /* For Video Data buffer allocation */ |
537 | dev->_data_buf_virt_addr = | 520 | dev->_data_buf_virt_addr = pci_alloc_consistent(dev->pci, |
538 | pci_alloc_consistent(dev->pci, dev->upstream_databuf_size, | 521 | dev->upstream_databuf_size, &data_dma_addr); |
539 | &data_dma_addr); | ||
540 | dev->_data_buf_phys_addr = data_dma_addr; | 522 | dev->_data_buf_phys_addr = data_dma_addr; |
541 | dev->_data_buf_size = dev->upstream_databuf_size; | 523 | dev->_data_buf_size = dev->upstream_databuf_size; |
542 | 524 | ||
@@ -553,9 +535,8 @@ int cx25821_upstream_buffer_prepare(struct cx25821_dev *dev, | |||
553 | return ret; | 535 | return ret; |
554 | 536 | ||
555 | /* Create RISC programs */ | 537 | /* Create RISC programs */ |
556 | ret = | 538 | ret = cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl, |
557 | cx25821_risc_buffer_upstream(dev, dev->pci, 0, bpl, | 539 | dev->_lines_count); |
558 | dev->_lines_count); | ||
559 | if (ret < 0) { | 540 | if (ret < 0) { |
560 | pr_info("Failed creating Video Upstream Risc programs!\n"); | 541 | pr_info("Failed creating Video Upstream Risc programs!\n"); |
561 | goto error; | 542 | goto error; |
@@ -672,10 +653,9 @@ static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) | |||
672 | vid_status = cx_read(sram_ch->int_stat); | 653 | vid_status = cx_read(sram_ch->int_stat); |
673 | 654 | ||
674 | /* Only deal with our interrupt */ | 655 | /* Only deal with our interrupt */ |
675 | if (vid_status) { | 656 | if (vid_status) |
676 | handled = | 657 | handled = cx25821_video_upstream_irq(dev, channel_num, |
677 | cx25821_video_upstream_irq(dev, channel_num, vid_status); | 658 | vid_status); |
678 | } | ||
679 | 659 | ||
680 | if (handled < 0) | 660 | if (handled < 0) |
681 | cx25821_stop_upstream_video_ch1(dev); | 661 | cx25821_stop_upstream_video_ch1(dev); |
@@ -747,8 +727,7 @@ int cx25821_start_video_dma_upstream(struct cx25821_dev *dev, | |||
747 | tmp = cx_read(sram_ch->int_msk); | 727 | tmp = cx_read(sram_ch->int_msk); |
748 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); | 728 | cx_write(sram_ch->int_msk, tmp |= _intr_msk); |
749 | 729 | ||
750 | err = | 730 | err = request_irq(dev->pci->irq, cx25821_upstream_irq, |
751 | request_irq(dev->pci->irq, cx25821_upstream_irq, | ||
752 | IRQF_SHARED, dev->name, dev); | 731 | IRQF_SHARED, dev->name, dev); |
753 | if (err < 0) { | 732 | if (err < 0) { |
754 | pr_err("%s: can't get upstream IRQ %d\n", | 733 | pr_err("%s: can't get upstream IRQ %d\n", |
@@ -807,43 +786,38 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, | |||
807 | dev->_file_status = RESET_STATUS; | 786 | dev->_file_status = RESET_STATUS; |
808 | dev->_lines_count = dev->_isNTSC ? 480 : 576; | 787 | dev->_lines_count = dev->_isNTSC ? 480 : 576; |
809 | dev->_pixel_format = pixel_format; | 788 | dev->_pixel_format = pixel_format; |
810 | dev->_line_size = | 789 | dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ? |
811 | (dev->_pixel_format == | 790 | (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; |
812 | PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; | ||
813 | data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; | 791 | data_frame_size = dev->_isNTSC ? NTSC_DATA_BUF_SZ : PAL_DATA_BUF_SZ; |
814 | risc_buffer_size = | 792 | risc_buffer_size = dev->_isNTSC ? |
815 | dev->_isNTSC ? NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; | 793 | NTSC_RISC_BUF_SIZE : PAL_RISC_BUF_SIZE; |
816 | 794 | ||
817 | if (dev->input_filename) { | 795 | if (dev->input_filename) { |
818 | str_length = strlen(dev->input_filename); | 796 | str_length = strlen(dev->input_filename); |
819 | dev->_filename = kmalloc(str_length + 1, GFP_KERNEL); | 797 | dev->_filename = kmemdup(dev->input_filename, str_length + 1, |
798 | GFP_KERNEL); | ||
820 | 799 | ||
821 | if (!dev->_filename) | 800 | if (!dev->_filename) |
822 | goto error; | 801 | goto error; |
823 | |||
824 | memcpy(dev->_filename, dev->input_filename, str_length + 1); | ||
825 | } else { | 802 | } else { |
826 | str_length = strlen(dev->_defaultname); | 803 | str_length = strlen(dev->_defaultname); |
827 | dev->_filename = kmalloc(str_length + 1, GFP_KERNEL); | 804 | dev->_filename = kmemdup(dev->_defaultname, str_length + 1, |
805 | GFP_KERNEL); | ||
828 | 806 | ||
829 | if (!dev->_filename) | 807 | if (!dev->_filename) |
830 | goto error; | 808 | goto error; |
831 | |||
832 | memcpy(dev->_filename, dev->_defaultname, str_length + 1); | ||
833 | } | 809 | } |
834 | 810 | ||
835 | /* Default if filename is empty string */ | 811 | /* Default if filename is empty string */ |
836 | if (strcmp(dev->input_filename, "") == 0) { | 812 | if (strcmp(dev->input_filename, "") == 0) { |
837 | if (dev->_isNTSC) { | 813 | if (dev->_isNTSC) { |
838 | dev->_filename = | 814 | dev->_filename = |
839 | (dev->_pixel_format == | 815 | (dev->_pixel_format == PIXEL_FRMT_411) ? |
840 | PIXEL_FRMT_411) ? "/root/vid411.yuv" : | 816 | "/root/vid411.yuv" : "/root/vidtest.yuv"; |
841 | "/root/vidtest.yuv"; | ||
842 | } else { | 817 | } else { |
843 | dev->_filename = | 818 | dev->_filename = |
844 | (dev->_pixel_format == | 819 | (dev->_pixel_format == PIXEL_FRMT_411) ? |
845 | PIXEL_FRMT_411) ? "/root/pal411.yuv" : | 820 | "/root/pal411.yuv" : "/root/pal422.yuv"; |
846 | "/root/pal422.yuv"; | ||
847 | } | 821 | } |
848 | } | 822 | } |
849 | 823 | ||
@@ -852,13 +826,11 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, | |||
852 | dev->_file_status = RESET_STATUS; | 826 | dev->_file_status = RESET_STATUS; |
853 | dev->_lines_count = dev->_isNTSC ? 480 : 576; | 827 | dev->_lines_count = dev->_isNTSC ? 480 : 576; |
854 | dev->_pixel_format = pixel_format; | 828 | dev->_pixel_format = pixel_format; |
855 | dev->_line_size = | 829 | dev->_line_size = (dev->_pixel_format == PIXEL_FRMT_422) ? |
856 | (dev->_pixel_format == | 830 | (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; |
857 | PIXEL_FRMT_422) ? (WIDTH_D1 * 2) : (WIDTH_D1 * 3) / 2; | ||
858 | 831 | ||
859 | retval = | 832 | retval = cx25821_sram_channel_setup_upstream(dev, sram_ch, |
860 | cx25821_sram_channel_setup_upstream(dev, sram_ch, dev->_line_size, | 833 | dev->_line_size, 0); |
861 | 0); | ||
862 | 834 | ||
863 | /* setup fifo + format */ | 835 | /* setup fifo + format */ |
864 | cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format); | 836 | cx25821_set_pixelengine(dev, sram_ch, dev->_pixel_format); |
diff --git a/drivers/media/video/cx25821/cx25821-video.c b/drivers/media/video/cx25821/cx25821-video.c index 4d6907cda75b..ffd8bc79c02e 100644 --- a/drivers/media/video/cx25821/cx25821-video.c +++ b/drivers/media/video/cx25821/cx25821-video.c | |||
@@ -118,12 +118,12 @@ void cx25821_dump_video_queue(struct cx25821_dev *dev, | |||
118 | 118 | ||
119 | if (!list_empty(&q->active)) { | 119 | if (!list_empty(&q->active)) { |
120 | list_for_each(item, &q->active) | 120 | list_for_each(item, &q->active) |
121 | buf = list_entry(item, struct cx25821_buffer, vb.queue); | 121 | buf = list_entry(item, struct cx25821_buffer, vb.queue); |
122 | } | 122 | } |
123 | 123 | ||
124 | if (!list_empty(&q->queued)) { | 124 | if (!list_empty(&q->queued)) { |
125 | list_for_each(item, &q->queued) | 125 | list_for_each(item, &q->queued) |
126 | buf = list_entry(item, struct cx25821_buffer, vb.queue); | 126 | buf = list_entry(item, struct cx25821_buffer, vb.queue); |
127 | } | 127 | } |
128 | 128 | ||
129 | } | 129 | } |
@@ -140,8 +140,8 @@ void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, | |||
140 | break; | 140 | break; |
141 | } | 141 | } |
142 | 142 | ||
143 | buf = | 143 | buf = list_entry(q->active.next, struct cx25821_buffer, |
144 | list_entry(q->active.next, struct cx25821_buffer, vb.queue); | 144 | vb.queue); |
145 | 145 | ||
146 | /* count comes from the hw and it is 16bit wide -- | 146 | /* count comes from the hw and it is 16bit wide -- |
147 | * this trick handles wrap-arounds correctly for | 147 | * this trick handles wrap-arounds correctly for |
@@ -318,8 +318,8 @@ int cx25821_restart_video_queue(struct cx25821_dev *dev, | |||
318 | struct list_head *item; | 318 | struct list_head *item; |
319 | 319 | ||
320 | if (!list_empty(&q->active)) { | 320 | if (!list_empty(&q->active)) { |
321 | buf = | 321 | buf = list_entry(q->active.next, struct cx25821_buffer, |
322 | list_entry(q->active.next, struct cx25821_buffer, vb.queue); | 322 | vb.queue); |
323 | 323 | ||
324 | cx25821_start_video_dma(dev, q, buf, channel); | 324 | cx25821_start_video_dma(dev, q, buf, channel); |
325 | 325 | ||
@@ -337,8 +337,8 @@ int cx25821_restart_video_queue(struct cx25821_dev *dev, | |||
337 | if (list_empty(&q->queued)) | 337 | if (list_empty(&q->queued)) |
338 | return 0; | 338 | return 0; |
339 | 339 | ||
340 | buf = | 340 | buf = list_entry(q->queued.next, struct cx25821_buffer, |
341 | list_entry(q->queued.next, struct cx25821_buffer, vb.queue); | 341 | vb.queue); |
342 | 342 | ||
343 | if (NULL == prev) { | 343 | if (NULL == prev) { |
344 | list_move_tail(&buf->vb.queue, &q->active); | 344 | list_move_tail(&buf->vb.queue, &q->active); |
@@ -375,8 +375,8 @@ void cx25821_vid_timeout(unsigned long data) | |||
375 | 375 | ||
376 | spin_lock_irqsave(&dev->slock, flags); | 376 | spin_lock_irqsave(&dev->slock, flags); |
377 | while (!list_empty(&q->active)) { | 377 | while (!list_empty(&q->active)) { |
378 | buf = | 378 | buf = list_entry(q->active.next, struct cx25821_buffer, |
379 | list_entry(q->active.next, struct cx25821_buffer, vb.queue); | 379 | vb.queue); |
380 | list_del(&buf->vb.queue); | 380 | list_del(&buf->vb.queue); |
381 | 381 | ||
382 | buf->vb.state = VIDEOBUF_ERROR; | 382 | buf->vb.state = VIDEOBUF_ERROR; |
@@ -484,8 +484,7 @@ int cx25821_video_register(struct cx25821_dev *dev) | |||
484 | cx25821_init_controls(dev, i); | 484 | cx25821_init_controls(dev, i); |
485 | 485 | ||
486 | cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper, | 486 | cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper, |
487 | dev->channels[i].sram_channels->dma_ctl, | 487 | dev->channels[i].sram_channels->dma_ctl, 0x11, 0); |
488 | 0x11, 0); | ||
489 | 488 | ||
490 | dev->channels[i].sram_channels = &cx25821_sram_channels[i]; | 489 | dev->channels[i].sram_channels = &cx25821_sram_channels[i]; |
491 | dev->channels[i].video_dev = NULL; | 490 | dev->channels[i].video_dev = NULL; |
@@ -499,15 +498,14 @@ int cx25821_video_register(struct cx25821_dev *dev) | |||
499 | dev->channels[i].timeout_data.dev = dev; | 498 | dev->channels[i].timeout_data.dev = dev; |
500 | dev->channels[i].timeout_data.channel = | 499 | dev->channels[i].timeout_data.channel = |
501 | &cx25821_sram_channels[i]; | 500 | &cx25821_sram_channels[i]; |
502 | dev->channels[i].vidq.timeout.function = | 501 | dev->channels[i].vidq.timeout.function = cx25821_vid_timeout; |
503 | cx25821_vid_timeout; | ||
504 | dev->channels[i].vidq.timeout.data = | 502 | dev->channels[i].vidq.timeout.data = |
505 | (unsigned long)&dev->channels[i].timeout_data; | 503 | (unsigned long)&dev->channels[i].timeout_data; |
506 | init_timer(&dev->channels[i].vidq.timeout); | 504 | init_timer(&dev->channels[i].vidq.timeout); |
507 | 505 | ||
508 | /* register v4l devices */ | 506 | /* register v4l devices */ |
509 | dev->channels[i].video_dev = cx25821_vdev_init(dev, | 507 | dev->channels[i].video_dev = cx25821_vdev_init(dev, dev->pci, |
510 | dev->pci, &cx25821_video_device, "video"); | 508 | &cx25821_video_device, "video"); |
511 | 509 | ||
512 | err = video_register_device(dev->channels[i].video_dev, | 510 | err = video_register_device(dev->channels[i].video_dev, |
513 | VFL_TYPE_GRABBER, video_nr[dev->nr]); | 511 | VFL_TYPE_GRABBER, video_nr[dev->nr]); |
@@ -528,7 +526,6 @@ int cx25821_video_register(struct cx25821_dev *dev) | |||
528 | #endif | 526 | #endif |
529 | mutex_unlock(&dev->lock); | 527 | mutex_unlock(&dev->lock); |
530 | 528 | ||
531 | |||
532 | return 0; | 529 | return 0; |
533 | 530 | ||
534 | fail_unreg: | 531 | fail_unreg: |
@@ -558,7 +555,7 @@ int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
558 | struct cx25821_fh *fh = q->priv_data; | 555 | struct cx25821_fh *fh = q->priv_data; |
559 | struct cx25821_dev *dev = fh->dev; | 556 | struct cx25821_dev *dev = fh->dev; |
560 | struct cx25821_buffer *buf = | 557 | struct cx25821_buffer *buf = |
561 | container_of(vb, struct cx25821_buffer, vb); | 558 | container_of(vb, struct cx25821_buffer, vb); |
562 | int rc, init_buffer = 0; | 559 | int rc, init_buffer = 0; |
563 | u32 line0_offset, line1_offset; | 560 | u32 line0_offset, line1_offset; |
564 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); | 561 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); |
@@ -617,14 +614,13 @@ int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | |||
617 | if (channel_opened >= 0 && channel_opened <= 7) { | 614 | if (channel_opened >= 0 && channel_opened <= 7) { |
618 | if (dev->channels[channel_opened] | 615 | if (dev->channels[channel_opened] |
619 | .use_cif_resolution) { | 616 | .use_cif_resolution) { |
620 | if (dev->tvnorm & V4L2_STD_PAL_BG | 617 | if (dev->tvnorm & V4L2_STD_PAL_BG || |
621 | || dev->tvnorm & V4L2_STD_PAL_DK) | 618 | dev->tvnorm & V4L2_STD_PAL_DK) |
622 | bpl_local = 352 << 1; | 619 | bpl_local = 352 << 1; |
623 | else | 620 | else |
624 | bpl_local = | 621 | bpl_local = dev->channels[ |
625 | dev->channels[channel_opened]. | 622 | channel_opened]. |
626 | cif_width << | 623 | cif_width << 1; |
627 | 1; | ||
628 | } | 624 | } |
629 | } | 625 | } |
630 | } | 626 | } |
@@ -685,7 +681,7 @@ void cx25821_buffer_release(struct videobuf_queue *q, | |||
685 | struct videobuf_buffer *vb) | 681 | struct videobuf_buffer *vb) |
686 | { | 682 | { |
687 | struct cx25821_buffer *buf = | 683 | struct cx25821_buffer *buf = |
688 | container_of(vb, struct cx25821_buffer, vb); | 684 | container_of(vb, struct cx25821_buffer, vb); |
689 | 685 | ||
690 | cx25821_free_buffer(q, buf); | 686 | cx25821_free_buffer(q, buf); |
691 | } | 687 | } |
@@ -723,7 +719,7 @@ int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma) | |||
723 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | 719 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) |
724 | { | 720 | { |
725 | struct cx25821_buffer *buf = | 721 | struct cx25821_buffer *buf = |
726 | container_of(vb, struct cx25821_buffer, vb); | 722 | container_of(vb, struct cx25821_buffer, vb); |
727 | struct cx25821_buffer *prev; | 723 | struct cx25821_buffer *prev; |
728 | struct cx25821_fh *fh = vq->priv_data; | 724 | struct cx25821_fh *fh = vq->priv_data; |
729 | struct cx25821_dev *dev = fh->dev; | 725 | struct cx25821_dev *dev = fh->dev; |
@@ -814,7 +810,7 @@ static int video_open(struct file *file) | |||
814 | 810 | ||
815 | for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) { | 811 | for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) { |
816 | if (h->channels[i].video_dev && | 812 | if (h->channels[i].video_dev && |
817 | h->channels[i].video_dev->minor == minor) { | 813 | h->channels[i].video_dev->minor == minor) { |
818 | dev = h; | 814 | dev = h; |
819 | ch_id = i; | 815 | ch_id = i; |
820 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 816 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
@@ -848,11 +844,10 @@ static int video_open(struct file *file) | |||
848 | 844 | ||
849 | v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio); | 845 | v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio); |
850 | 846 | ||
851 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, | 847 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, &dev->pci->dev, |
852 | &dev->pci->dev, &dev->slock, | 848 | &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
853 | V4L2_BUF_TYPE_VIDEO_CAPTURE, | 849 | V4L2_FIELD_INTERLACED, sizeof(struct cx25821_buffer), |
854 | V4L2_FIELD_INTERLACED, | 850 | fh, NULL); |
855 | sizeof(struct cx25821_buffer), fh, NULL); | ||
856 | 851 | ||
857 | dprintk(1, "post videobuf_queue_init()\n"); | 852 | dprintk(1, "post videobuf_queue_init()\n"); |
858 | mutex_unlock(&cx25821_devlist_mutex); | 853 | mutex_unlock(&cx25821_devlist_mutex); |
@@ -1168,8 +1163,8 @@ int cx25821_vidioc_querycap(struct file *file, void *priv, | |||
1168 | strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); | 1163 | strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); |
1169 | sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); | 1164 | sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); |
1170 | cap->version = CX25821_VERSION_CODE; | 1165 | cap->version = CX25821_VERSION_CODE; |
1171 | cap->capabilities = | 1166 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | |
1172 | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING; | 1167 | V4L2_CAP_STREAMING; |
1173 | if (UNSET != dev->tuner_type) | 1168 | if (UNSET != dev->tuner_type) |
1174 | cap->capabilities |= V4L2_CAP_TUNER; | 1169 | cap->capabilities |= V4L2_CAP_TUNER; |
1175 | return 0; | 1170 | return 0; |
@@ -1454,38 +1449,38 @@ static const struct v4l2_queryctrl no_ctl = { | |||
1454 | static struct v4l2_queryctrl cx25821_ctls[] = { | 1449 | static struct v4l2_queryctrl cx25821_ctls[] = { |
1455 | /* --- video --- */ | 1450 | /* --- video --- */ |
1456 | { | 1451 | { |
1457 | .id = V4L2_CID_BRIGHTNESS, | 1452 | .id = V4L2_CID_BRIGHTNESS, |
1458 | .name = "Brightness", | 1453 | .name = "Brightness", |
1459 | .minimum = 0, | 1454 | .minimum = 0, |
1460 | .maximum = 10000, | 1455 | .maximum = 10000, |
1461 | .step = 1, | 1456 | .step = 1, |
1462 | .default_value = 6200, | 1457 | .default_value = 6200, |
1463 | .type = V4L2_CTRL_TYPE_INTEGER, | 1458 | .type = V4L2_CTRL_TYPE_INTEGER, |
1464 | }, { | 1459 | }, { |
1465 | .id = V4L2_CID_CONTRAST, | 1460 | .id = V4L2_CID_CONTRAST, |
1466 | .name = "Contrast", | 1461 | .name = "Contrast", |
1467 | .minimum = 0, | 1462 | .minimum = 0, |
1468 | .maximum = 10000, | 1463 | .maximum = 10000, |
1469 | .step = 1, | 1464 | .step = 1, |
1470 | .default_value = 5000, | 1465 | .default_value = 5000, |
1471 | .type = V4L2_CTRL_TYPE_INTEGER, | 1466 | .type = V4L2_CTRL_TYPE_INTEGER, |
1472 | }, { | 1467 | }, { |
1473 | .id = V4L2_CID_SATURATION, | 1468 | .id = V4L2_CID_SATURATION, |
1474 | .name = "Saturation", | 1469 | .name = "Saturation", |
1475 | .minimum = 0, | 1470 | .minimum = 0, |
1476 | .maximum = 10000, | 1471 | .maximum = 10000, |
1477 | .step = 1, | 1472 | .step = 1, |
1478 | .default_value = 5000, | 1473 | .default_value = 5000, |
1479 | .type = V4L2_CTRL_TYPE_INTEGER, | 1474 | .type = V4L2_CTRL_TYPE_INTEGER, |
1480 | }, { | 1475 | }, { |
1481 | .id = V4L2_CID_HUE, | 1476 | .id = V4L2_CID_HUE, |
1482 | .name = "Hue", | 1477 | .name = "Hue", |
1483 | .minimum = 0, | 1478 | .minimum = 0, |
1484 | .maximum = 10000, | 1479 | .maximum = 10000, |
1485 | .step = 1, | 1480 | .step = 1, |
1486 | .default_value = 5000, | 1481 | .default_value = 5000, |
1487 | .type = V4L2_CTRL_TYPE_INTEGER, | 1482 | .type = V4L2_CTRL_TYPE_INTEGER, |
1488 | } | 1483 | } |
1489 | }; | 1484 | }; |
1490 | static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls); | 1485 | static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls); |
1491 | 1486 | ||
@@ -1623,7 +1618,8 @@ int cx25821_vidioc_cropcap(struct file *file, void *priv, | |||
1623 | 1618 | ||
1624 | if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1619 | if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1625 | return -EINVAL; | 1620 | return -EINVAL; |
1626 | cropcap->bounds.top = cropcap->bounds.left = 0; | 1621 | cropcap->bounds.top = 0; |
1622 | cropcap->bounds.left = 0; | ||
1627 | cropcap->bounds.width = 720; | 1623 | cropcap->bounds.width = 720; |
1628 | cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480; | 1624 | cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480; |
1629 | cropcap->pixelaspect.numerator = | 1625 | cropcap->pixelaspect.numerator = |
@@ -1829,8 +1825,11 @@ static long video_ioctl_set(struct file *file, unsigned int cmd, | |||
1829 | struct downstream_user_struct *data_from_user; | 1825 | struct downstream_user_struct *data_from_user; |
1830 | int command; | 1826 | int command; |
1831 | int width = 720; | 1827 | int width = 720; |
1832 | int selected_channel = 0, pix_format = 0, i = 0; | 1828 | int selected_channel = 0; |
1833 | int cif_enable = 0, cif_width = 0; | 1829 | int pix_format = 0; |
1830 | int i = 0; | ||
1831 | int cif_enable = 0; | ||
1832 | int cif_width = 0; | ||
1834 | u32 value = 0; | 1833 | u32 value = 0; |
1835 | 1834 | ||
1836 | data_from_user = (struct downstream_user_struct *)arg; | 1835 | data_from_user = (struct downstream_user_struct *)arg; |
@@ -1895,8 +1894,8 @@ static long video_ioctl_set(struct file *file, unsigned int cmd, | |||
1895 | } | 1894 | } |
1896 | 1895 | ||
1897 | if (selected_channel <= 7 && selected_channel >= 0) { | 1896 | if (selected_channel <= 7 && selected_channel >= 0) { |
1898 | dev->channels[selected_channel]. | 1897 | dev->channels[selected_channel].use_cif_resolution = |
1899 | use_cif_resolution = cif_enable; | 1898 | cif_enable; |
1900 | dev->channels[selected_channel].cif_width = width; | 1899 | dev->channels[selected_channel].cif_width = width; |
1901 | } else { | 1900 | } else { |
1902 | for (i = 0; i < VID_CHANNEL_NUM; i++) { | 1901 | for (i = 0; i < VID_CHANNEL_NUM; i++) { |
@@ -1932,9 +1931,9 @@ static long video_ioctl_set(struct file *file, unsigned int cmd, | |||
1932 | static long cx25821_video_ioctl(struct file *file, | 1931 | static long cx25821_video_ioctl(struct file *file, |
1933 | unsigned int cmd, unsigned long arg) | 1932 | unsigned int cmd, unsigned long arg) |
1934 | { | 1933 | { |
1935 | int ret = 0; | 1934 | int ret = 0; |
1936 | 1935 | ||
1937 | struct cx25821_fh *fh = file->private_data; | 1936 | struct cx25821_fh *fh = file->private_data; |
1938 | 1937 | ||
1939 | /* check to see if it's the video upstream */ | 1938 | /* check to see if it's the video upstream */ |
1940 | if (fh->channel_id == SRAM_CH09) { | 1939 | if (fh->channel_id == SRAM_CH09) { |
diff --git a/drivers/media/video/cx25821/cx25821.h b/drivers/media/video/cx25821/cx25821.h index 2d2d00932823..b9aa801b00a7 100644 --- a/drivers/media/video/cx25821/cx25821.h +++ b/drivers/media/video/cx25821/cx25821.h | |||
@@ -67,7 +67,7 @@ | |||
67 | #define MAX_CAMERAS 16 | 67 | #define MAX_CAMERAS 16 |
68 | 68 | ||
69 | /* Max number of inputs by card */ | 69 | /* Max number of inputs by card */ |
70 | #define MAX_CX25821_INPUT 8 | 70 | #define MAX_CX25821_INPUT 8 |
71 | #define INPUT(nr) (&cx25821_boards[dev->board].input[nr]) | 71 | #define INPUT(nr) (&cx25821_boards[dev->board].input[nr]) |
72 | #define RESOURCE_VIDEO0 1 | 72 | #define RESOURCE_VIDEO0 1 |
73 | #define RESOURCE_VIDEO1 2 | 73 | #define RESOURCE_VIDEO1 2 |
@@ -85,7 +85,7 @@ | |||
85 | 85 | ||
86 | #define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */ | 86 | #define BUFFER_TIMEOUT (HZ) /* 0.5 seconds */ |
87 | 87 | ||
88 | #define UNKNOWN_BOARD 0 | 88 | #define UNKNOWN_BOARD 0 |
89 | #define CX25821_BOARD 1 | 89 | #define CX25821_BOARD 1 |
90 | 90 | ||
91 | /* Currently supported by the driver */ | 91 | /* Currently supported by the driver */ |
diff --git a/drivers/media/video/cx25840/cx25840-audio.c b/drivers/media/video/cx25840/cx25840-audio.c index 005f11093642..34b96c7cfd62 100644 --- a/drivers/media/video/cx25840/cx25840-audio.c +++ b/drivers/media/video/cx25840/cx25840-audio.c | |||
@@ -480,7 +480,6 @@ void cx25840_audio_set_path(struct i2c_client *client) | |||
480 | 480 | ||
481 | static void set_volume(struct i2c_client *client, int volume) | 481 | static void set_volume(struct i2c_client *client, int volume) |
482 | { | 482 | { |
483 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | ||
484 | int vol; | 483 | int vol; |
485 | 484 | ||
486 | /* Convert the volume to msp3400 values (0-127) */ | 485 | /* Convert the volume to msp3400 values (0-127) */ |
@@ -496,14 +495,7 @@ static void set_volume(struct i2c_client *client, int volume) | |||
496 | } | 495 | } |
497 | 496 | ||
498 | /* PATH1_VOLUME */ | 497 | /* PATH1_VOLUME */ |
499 | if (is_cx2388x(state)) { | 498 | cx25840_write(client, 0x8d4, 228 - (vol * 2)); |
500 | /* for cx23885 volume doesn't work, | ||
501 | * the calculation always results in | ||
502 | * e4 regardless. | ||
503 | */ | ||
504 | cx25840_write(client, 0x8d4, volume); | ||
505 | } else | ||
506 | cx25840_write(client, 0x8d4, 228 - (vol * 2)); | ||
507 | } | 499 | } |
508 | 500 | ||
509 | static void set_balance(struct i2c_client *client, int balance) | 501 | static void set_balance(struct i2c_client *client, int balance) |
diff --git a/drivers/media/video/cx25840/cx25840-core.c b/drivers/media/video/cx25840/cx25840-core.c index cd9976408ab3..05247d4c340a 100644 --- a/drivers/media/video/cx25840/cx25840-core.c +++ b/drivers/media/video/cx25840/cx25840-core.c | |||
@@ -18,6 +18,9 @@ | |||
18 | * CX2388[578] IRQ handling, IO Pin mux configuration and other small fixes are | 18 | * CX2388[578] IRQ handling, IO Pin mux configuration and other small fixes are |
19 | * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net> | 19 | * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net> |
20 | * | 20 | * |
21 | * CX23888 DIF support for the HVR1850 | ||
22 | * Copyright (C) 2011 Steven Toth <stoth@kernellabs.com> | ||
23 | * | ||
21 | * This program is free software; you can redistribute it and/or | 24 | * This program is free software; you can redistribute it and/or |
22 | * modify it under the terms of the GNU General Public License | 25 | * modify it under the terms of the GNU General Public License |
23 | * as published by the Free Software Foundation; either version 2 | 26 | * as published by the Free Software Foundation; either version 2 |
@@ -40,6 +43,7 @@ | |||
40 | #include <linux/videodev2.h> | 43 | #include <linux/videodev2.h> |
41 | #include <linux/i2c.h> | 44 | #include <linux/i2c.h> |
42 | #include <linux/delay.h> | 45 | #include <linux/delay.h> |
46 | #include <linux/math64.h> | ||
43 | #include <media/v4l2-common.h> | 47 | #include <media/v4l2-common.h> |
44 | #include <media/v4l2-chip-ident.h> | 48 | #include <media/v4l2-chip-ident.h> |
45 | #include <media/cx25840.h> | 49 | #include <media/cx25840.h> |
@@ -80,6 +84,7 @@ MODULE_PARM_DESC(debug, "Debugging messages [0=Off (default) 1=On]"); | |||
80 | 84 | ||
81 | 85 | ||
82 | /* ----------------------------------------------------------------------- */ | 86 | /* ----------------------------------------------------------------------- */ |
87 | static void cx23885_std_setup(struct i2c_client *client); | ||
83 | 88 | ||
84 | int cx25840_write(struct i2c_client *client, u16 addr, u8 value) | 89 | int cx25840_write(struct i2c_client *client, u16 addr, u8 value) |
85 | { | 90 | { |
@@ -498,8 +503,13 @@ static void cx23885_initialize(struct i2c_client *client) | |||
498 | * 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz | 503 | * 50.0 MHz * (0xb + 0xe8ba26/0x2000000)/4 = 5 * 28.636363 MHz |
499 | * 572.73 MHz before post divide | 504 | * 572.73 MHz before post divide |
500 | */ | 505 | */ |
501 | cx25840_write4(client, 0x11c, 0x00e8ba26); | 506 | /* HVR1850 or 50MHz xtal */ |
502 | cx25840_write4(client, 0x118, 0x0000040b); | 507 | cx25840_write(client, 0x2, 0x71); |
508 | cx25840_write4(client, 0x11c, 0x01d1744c); | ||
509 | cx25840_write4(client, 0x118, 0x00000416); | ||
510 | cx25840_write4(client, 0x404, 0x0010253e); | ||
511 | cx25840_write4(client, 0x42c, 0x42600000); | ||
512 | cx25840_write4(client, 0x44c, 0x161f1000); | ||
503 | break; | 513 | break; |
504 | case V4L2_IDENT_CX23887_AV: | 514 | case V4L2_IDENT_CX23887_AV: |
505 | /* | 515 | /* |
@@ -533,8 +543,18 @@ static void cx23885_initialize(struct i2c_client *client) | |||
533 | * 28.636363 MHz * (0xf + 0x02be2c9/0x2000000)/4 = 8 * 13.5 MHz | 543 | * 28.636363 MHz * (0xf + 0x02be2c9/0x2000000)/4 = 8 * 13.5 MHz |
534 | * 432.0 MHz before post divide | 544 | * 432.0 MHz before post divide |
535 | */ | 545 | */ |
536 | cx25840_write4(client, 0x10c, 0x002be2c9); | 546 | |
537 | cx25840_write4(client, 0x108, 0x0000040f); | 547 | /* HVR1850 */ |
548 | switch (state->id) { | ||
549 | case V4L2_IDENT_CX23888_AV: | ||
550 | /* 888/HVR1250 specific */ | ||
551 | cx25840_write4(client, 0x10c, 0x13333333); | ||
552 | cx25840_write4(client, 0x108, 0x00000515); | ||
553 | break; | ||
554 | default: | ||
555 | cx25840_write4(client, 0x10c, 0x002be2c9); | ||
556 | cx25840_write4(client, 0x108, 0x0000040f); | ||
557 | } | ||
538 | 558 | ||
539 | /* Luma */ | 559 | /* Luma */ |
540 | cx25840_write4(client, 0x414, 0x00107d12); | 560 | cx25840_write4(client, 0x414, 0x00107d12); |
@@ -556,8 +576,9 @@ static void cx23885_initialize(struct i2c_client *client) | |||
556 | * 368.64 MHz before post divide | 576 | * 368.64 MHz before post divide |
557 | * 122.88 MHz / 0xa = 12.288 MHz | 577 | * 122.88 MHz / 0xa = 12.288 MHz |
558 | */ | 578 | */ |
559 | cx25840_write4(client, 0x114, 0x00bedfa4); | 579 | /* HVR1850 or 50MHz xtal */ |
560 | cx25840_write4(client, 0x110, 0x000a0307); | 580 | cx25840_write4(client, 0x114, 0x017dbf48); |
581 | cx25840_write4(client, 0x110, 0x000a030e); | ||
561 | break; | 582 | break; |
562 | case V4L2_IDENT_CX23887_AV: | 583 | case V4L2_IDENT_CX23887_AV: |
563 | /* | 584 | /* |
@@ -617,7 +638,10 @@ static void cx23885_initialize(struct i2c_client *client) | |||
617 | finish_wait(&state->fw_wait, &wait); | 638 | finish_wait(&state->fw_wait, &wait); |
618 | destroy_workqueue(q); | 639 | destroy_workqueue(q); |
619 | 640 | ||
620 | cx25840_std_setup(client); | 641 | /* Call the cx23885 specific std setup func, we no longer rely on |
642 | * the generic cx24840 func. | ||
643 | */ | ||
644 | cx23885_std_setup(client); | ||
621 | 645 | ||
622 | /* (re)set input */ | 646 | /* (re)set input */ |
623 | set_input(client, state->vid_input, state->aud_input); | 647 | set_input(client, state->vid_input, state->aud_input); |
@@ -631,6 +655,37 @@ static void cx23885_initialize(struct i2c_client *client) | |||
631 | /* Disable and clear audio interrupts - we don't use them */ | 655 | /* Disable and clear audio interrupts - we don't use them */ |
632 | cx25840_write(client, CX25840_AUD_INT_CTRL_REG, 0xff); | 656 | cx25840_write(client, CX25840_AUD_INT_CTRL_REG, 0xff); |
633 | cx25840_write(client, CX25840_AUD_INT_STAT_REG, 0xff); | 657 | cx25840_write(client, CX25840_AUD_INT_STAT_REG, 0xff); |
658 | |||
659 | /* CC raw enable */ | ||
660 | /* - VIP 1.1 control codes - 10bit, blue field enable. | ||
661 | * - enable raw data during vertical blanking. | ||
662 | * - enable ancillary Data insertion for 656 or VIP. | ||
663 | */ | ||
664 | cx25840_write4(client, 0x404, 0x0010253e); | ||
665 | |||
666 | /* CC on - Undocumented Register */ | ||
667 | cx25840_write(client, 0x42f, 0x66); | ||
668 | |||
669 | /* HVR-1250 / HVR1850 DIF related */ | ||
670 | /* Power everything up */ | ||
671 | cx25840_write4(client, 0x130, 0x0); | ||
672 | |||
673 | /* Undocumented */ | ||
674 | cx25840_write4(client, 0x478, 0x6628021F); | ||
675 | |||
676 | /* AFE_CLK_OUT_CTRL - Select the clock output source as output */ | ||
677 | cx25840_write4(client, 0x144, 0x5); | ||
678 | |||
679 | /* I2C_OUT_CTL - I2S output configuration as | ||
680 | * Master, Sony, Left justified, left sample on WS=1 | ||
681 | */ | ||
682 | cx25840_write4(client, 0x918, 0x1a0); | ||
683 | |||
684 | /* AFE_DIAG_CTRL1 */ | ||
685 | cx25840_write4(client, 0x134, 0x000a1800); | ||
686 | |||
687 | /* AFE_DIAG_CTRL3 - Inverted Polarity for Audio and Video */ | ||
688 | cx25840_write4(client, 0x13c, 0x00310000); | ||
634 | } | 689 | } |
635 | 690 | ||
636 | /* ----------------------------------------------------------------------- */ | 691 | /* ----------------------------------------------------------------------- */ |
@@ -945,9 +1000,14 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
945 | vid_input <= CX25840_COMPOSITE8); | 1000 | vid_input <= CX25840_COMPOSITE8); |
946 | u8 is_component = (vid_input & CX25840_COMPONENT_ON) == | 1001 | u8 is_component = (vid_input & CX25840_COMPONENT_ON) == |
947 | CX25840_COMPONENT_ON; | 1002 | CX25840_COMPONENT_ON; |
1003 | u8 is_dif = (vid_input & CX25840_DIF_ON) == | ||
1004 | CX25840_DIF_ON; | ||
1005 | u8 is_svideo = (vid_input & CX25840_SVIDEO_ON) == | ||
1006 | CX25840_SVIDEO_ON; | ||
948 | int luma = vid_input & 0xf0; | 1007 | int luma = vid_input & 0xf0; |
949 | int chroma = vid_input & 0xf00; | 1008 | int chroma = vid_input & 0xf00; |
950 | u8 reg; | 1009 | u8 reg; |
1010 | u32 val; | ||
951 | 1011 | ||
952 | v4l_dbg(1, cx25840_debug, client, | 1012 | v4l_dbg(1, cx25840_debug, client, |
953 | "decoder set video input %d, audio input %d\n", | 1013 | "decoder set video input %d, audio input %d\n", |
@@ -1012,6 +1072,66 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
1012 | else | 1072 | else |
1013 | cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02); | 1073 | cx25840_and_or(client, 0x401, ~0x6, is_composite ? 0 : 0x02); |
1014 | 1074 | ||
1075 | if (is_cx2388x(state)) { | ||
1076 | |||
1077 | /* Enable or disable the DIF for tuner use */ | ||
1078 | if (is_dif) { | ||
1079 | cx25840_and_or(client, 0x102, ~0x80, 0x80); | ||
1080 | |||
1081 | /* Set of defaults for NTSC and PAL */ | ||
1082 | cx25840_write4(client, 0x31c, 0xc2262600); | ||
1083 | cx25840_write4(client, 0x320, 0xc2262600); | ||
1084 | |||
1085 | /* 18271 IF - Nobody else yet uses a different | ||
1086 | * tuner with the DIF, so these are reasonable | ||
1087 | * assumptions (HVR1250 and HVR1850 specific). | ||
1088 | */ | ||
1089 | cx25840_write4(client, 0x318, 0xda262600); | ||
1090 | cx25840_write4(client, 0x33c, 0x2a24c800); | ||
1091 | cx25840_write4(client, 0x104, 0x0704dd00); | ||
1092 | } else { | ||
1093 | cx25840_write4(client, 0x300, 0x015c28f5); | ||
1094 | |||
1095 | cx25840_and_or(client, 0x102, ~0x80, 0); | ||
1096 | cx25840_write4(client, 0x340, 0xdf7df83); | ||
1097 | cx25840_write4(client, 0x104, 0x0704dd80); | ||
1098 | cx25840_write4(client, 0x314, 0x22400600); | ||
1099 | cx25840_write4(client, 0x318, 0x40002600); | ||
1100 | cx25840_write4(client, 0x324, 0x40002600); | ||
1101 | cx25840_write4(client, 0x32c, 0x0250e620); | ||
1102 | cx25840_write4(client, 0x39c, 0x01FF0B00); | ||
1103 | |||
1104 | cx25840_write4(client, 0x410, 0xffff0dbf); | ||
1105 | cx25840_write4(client, 0x414, 0x00137d03); | ||
1106 | cx25840_write4(client, 0x418, 0x01008080); | ||
1107 | cx25840_write4(client, 0x41c, 0x00000000); | ||
1108 | cx25840_write4(client, 0x420, 0x001c3e0f); | ||
1109 | cx25840_write4(client, 0x42c, 0x42600000); | ||
1110 | cx25840_write4(client, 0x430, 0x0000039b); | ||
1111 | cx25840_write4(client, 0x438, 0x00000000); | ||
1112 | |||
1113 | cx25840_write4(client, 0x440, 0xF8E3E824); | ||
1114 | cx25840_write4(client, 0x444, 0x401040dc); | ||
1115 | cx25840_write4(client, 0x448, 0xcd3f02a0); | ||
1116 | cx25840_write4(client, 0x44c, 0x161f1000); | ||
1117 | cx25840_write4(client, 0x450, 0x00000802); | ||
1118 | |||
1119 | cx25840_write4(client, 0x91c, 0x01000000); | ||
1120 | cx25840_write4(client, 0x8e0, 0x03063870); | ||
1121 | cx25840_write4(client, 0x8d4, 0x7FFF0024); | ||
1122 | cx25840_write4(client, 0x8d0, 0x00063073); | ||
1123 | |||
1124 | cx25840_write4(client, 0x8c8, 0x00010000); | ||
1125 | cx25840_write4(client, 0x8cc, 0x00080023); | ||
1126 | |||
1127 | /* DIF BYPASS */ | ||
1128 | cx25840_write4(client, 0x33c, 0x2a04c800); | ||
1129 | } | ||
1130 | |||
1131 | /* Reset the DIF */ | ||
1132 | cx25840_write4(client, 0x398, 0); | ||
1133 | } | ||
1134 | |||
1015 | if (!is_cx2388x(state) && !is_cx231xx(state)) { | 1135 | if (!is_cx2388x(state) && !is_cx231xx(state)) { |
1016 | /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ | 1136 | /* Set CH_SEL_ADC2 to 1 if input comes from CH3 */ |
1017 | cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); | 1137 | cx25840_and_or(client, 0x102, ~0x2, (reg & 0x80) == 0 ? 2 : 0); |
@@ -1036,6 +1156,33 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
1036 | cx25840_and_or(client, 0x102, ~0x2, 0); | 1156 | cx25840_and_or(client, 0x102, ~0x2, 0); |
1037 | } | 1157 | } |
1038 | } | 1158 | } |
1159 | |||
1160 | /* cx23885 / SVIDEO */ | ||
1161 | if (is_cx2388x(state) && is_svideo) { | ||
1162 | #define AFE_CTRL (0x104) | ||
1163 | #define MODE_CTRL (0x400) | ||
1164 | cx25840_and_or(client, 0x102, ~0x2, 0x2); | ||
1165 | |||
1166 | val = cx25840_read4(client, MODE_CTRL); | ||
1167 | val &= 0xFFFFF9FF; | ||
1168 | |||
1169 | /* YC */ | ||
1170 | val |= 0x00000200; | ||
1171 | val &= ~0x2000; | ||
1172 | cx25840_write4(client, MODE_CTRL, val); | ||
1173 | |||
1174 | val = cx25840_read4(client, AFE_CTRL); | ||
1175 | |||
1176 | /* Chroma in select */ | ||
1177 | val |= 0x00001000; | ||
1178 | val &= 0xfffffe7f; | ||
1179 | /* Clear VGA_SEL_CH2 and VGA_SEL_CH3 (bits 7 and 8). | ||
1180 | * This sets them to use video rather than audio. | ||
1181 | * Only one of the two will be in use. | ||
1182 | */ | ||
1183 | cx25840_write4(client, AFE_CTRL, val); | ||
1184 | } else | ||
1185 | cx25840_and_or(client, 0x102, ~0x2, 0); | ||
1039 | } | 1186 | } |
1040 | 1187 | ||
1041 | state->vid_input = vid_input; | 1188 | state->vid_input = vid_input; |
@@ -1086,6 +1233,23 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp | |||
1086 | cx25840_write4(client, 0x8d0, 0x1f063870); | 1233 | cx25840_write4(client, 0x8d0, 0x1f063870); |
1087 | } | 1234 | } |
1088 | 1235 | ||
1236 | if (is_cx2388x(state)) { | ||
1237 | /* HVR1850 */ | ||
1238 | /* AUD_IO_CTRL - I2S Input, Parallel1*/ | ||
1239 | /* - Channel 1 src - Parallel1 (Merlin out) */ | ||
1240 | /* - Channel 2 src - Parallel2 (Merlin out) */ | ||
1241 | /* - Channel 3 src - Parallel3 (Merlin AC97 out) */ | ||
1242 | /* - I2S source and dir - Merlin, output */ | ||
1243 | cx25840_write4(client, 0x124, 0x100); | ||
1244 | |||
1245 | if (!is_dif) { | ||
1246 | /* Stop microcontroller if we don't need it | ||
1247 | * to avoid audio popping on svideo/composite use. | ||
1248 | */ | ||
1249 | cx25840_and_or(client, 0x803, ~0x10, 0x00); | ||
1250 | } | ||
1251 | } | ||
1252 | |||
1089 | return 0; | 1253 | return 0; |
1090 | } | 1254 | } |
1091 | 1255 | ||
@@ -1134,7 +1298,10 @@ static int set_v4lstd(struct i2c_client *client) | |||
1134 | } | 1298 | } |
1135 | cx25840_and_or(client, 0x400, ~0xf, fmt); | 1299 | cx25840_and_or(client, 0x400, ~0xf, fmt); |
1136 | cx25840_and_or(client, 0x403, ~0x3, pal_m); | 1300 | cx25840_and_or(client, 0x403, ~0x3, pal_m); |
1137 | cx25840_std_setup(client); | 1301 | if (is_cx2388x(state)) |
1302 | cx23885_std_setup(client); | ||
1303 | else | ||
1304 | cx25840_std_setup(client); | ||
1138 | if (!is_cx2583x(state)) | 1305 | if (!is_cx2583x(state)) |
1139 | input_change(client); | 1306 | input_change(client); |
1140 | return 0; | 1307 | return 0; |
@@ -1539,6 +1706,56 @@ static int cx25840_s_stream(struct v4l2_subdev *sd, int enable) | |||
1539 | return 0; | 1706 | return 0; |
1540 | } | 1707 | } |
1541 | 1708 | ||
1709 | /* Query the current detected video format */ | ||
1710 | static int cx25840_g_std(struct v4l2_subdev *sd, v4l2_std_id *std) | ||
1711 | { | ||
1712 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1713 | |||
1714 | v4l2_std_id stds[] = { | ||
1715 | /* 0000 */ V4L2_STD_UNKNOWN, | ||
1716 | |||
1717 | /* 0001 */ V4L2_STD_NTSC_M, | ||
1718 | /* 0010 */ V4L2_STD_NTSC_M_JP, | ||
1719 | /* 0011 */ V4L2_STD_NTSC_443, | ||
1720 | /* 0100 */ V4L2_STD_PAL, | ||
1721 | /* 0101 */ V4L2_STD_PAL_M, | ||
1722 | /* 0110 */ V4L2_STD_PAL_N, | ||
1723 | /* 0111 */ V4L2_STD_PAL_Nc, | ||
1724 | /* 1000 */ V4L2_STD_PAL_60, | ||
1725 | |||
1726 | /* 1001 */ V4L2_STD_UNKNOWN, | ||
1727 | /* 1010 */ V4L2_STD_UNKNOWN, | ||
1728 | /* 1001 */ V4L2_STD_UNKNOWN, | ||
1729 | /* 1010 */ V4L2_STD_UNKNOWN, | ||
1730 | /* 1011 */ V4L2_STD_UNKNOWN, | ||
1731 | /* 1110 */ V4L2_STD_UNKNOWN, | ||
1732 | /* 1111 */ V4L2_STD_UNKNOWN | ||
1733 | }; | ||
1734 | |||
1735 | u32 fmt = (cx25840_read4(client, 0x40c) >> 8) & 0xf; | ||
1736 | *std = stds[ fmt ]; | ||
1737 | |||
1738 | v4l_dbg(1, cx25840_debug, client, "g_std fmt = %x, v4l2_std_id = 0x%x\n", | ||
1739 | fmt, (unsigned int)stds[ fmt ]); | ||
1740 | |||
1741 | return 0; | ||
1742 | } | ||
1743 | |||
1744 | static int cx25840_g_input_status(struct v4l2_subdev *sd, u32 *status) | ||
1745 | { | ||
1746 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
1747 | |||
1748 | /* A limited function that checks for signal status and returns | ||
1749 | * the state. | ||
1750 | */ | ||
1751 | |||
1752 | /* Check for status of Horizontal lock (SRC lock isn't reliable) */ | ||
1753 | if ((cx25840_read4(client, 0x40c) & 0x00010000) == 0) | ||
1754 | *status |= V4L2_IN_ST_NO_SIGNAL; | ||
1755 | |||
1756 | return 0; | ||
1757 | } | ||
1758 | |||
1542 | static int cx25840_s_std(struct v4l2_subdev *sd, v4l2_std_id std) | 1759 | static int cx25840_s_std(struct v4l2_subdev *sd, v4l2_std_id std) |
1543 | { | 1760 | { |
1544 | struct cx25840_state *state = to_state(sd); | 1761 | struct cx25840_state *state = to_state(sd); |
@@ -1565,6 +1782,9 @@ static int cx25840_s_video_routing(struct v4l2_subdev *sd, | |||
1565 | struct cx25840_state *state = to_state(sd); | 1782 | struct cx25840_state *state = to_state(sd); |
1566 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1783 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1567 | 1784 | ||
1785 | if (is_cx2388x(state)) | ||
1786 | cx23885_std_setup(client); | ||
1787 | |||
1568 | return set_input(client, input, state->aud_input); | 1788 | return set_input(client, input, state->aud_input); |
1569 | } | 1789 | } |
1570 | 1790 | ||
@@ -1574,6 +1794,8 @@ static int cx25840_s_audio_routing(struct v4l2_subdev *sd, | |||
1574 | struct cx25840_state *state = to_state(sd); | 1794 | struct cx25840_state *state = to_state(sd); |
1575 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 1795 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
1576 | 1796 | ||
1797 | if (is_cx2388x(state)) | ||
1798 | cx23885_std_setup(client); | ||
1577 | return set_input(client, state->vid_input, input); | 1799 | return set_input(client, state->vid_input, input); |
1578 | } | 1800 | } |
1579 | 1801 | ||
@@ -1786,6 +2008,3007 @@ static int cx25840_irq_handler(struct v4l2_subdev *sd, u32 status, | |||
1786 | 2008 | ||
1787 | /* ----------------------------------------------------------------------- */ | 2009 | /* ----------------------------------------------------------------------- */ |
1788 | 2010 | ||
2011 | #define DIF_PLL_FREQ_WORD (0x300) | ||
2012 | #define DIF_BPF_COEFF01 (0x348) | ||
2013 | #define DIF_BPF_COEFF23 (0x34c) | ||
2014 | #define DIF_BPF_COEFF45 (0x350) | ||
2015 | #define DIF_BPF_COEFF67 (0x354) | ||
2016 | #define DIF_BPF_COEFF89 (0x358) | ||
2017 | #define DIF_BPF_COEFF1011 (0x35c) | ||
2018 | #define DIF_BPF_COEFF1213 (0x360) | ||
2019 | #define DIF_BPF_COEFF1415 (0x364) | ||
2020 | #define DIF_BPF_COEFF1617 (0x368) | ||
2021 | #define DIF_BPF_COEFF1819 (0x36c) | ||
2022 | #define DIF_BPF_COEFF2021 (0x370) | ||
2023 | #define DIF_BPF_COEFF2223 (0x374) | ||
2024 | #define DIF_BPF_COEFF2425 (0x378) | ||
2025 | #define DIF_BPF_COEFF2627 (0x37c) | ||
2026 | #define DIF_BPF_COEFF2829 (0x380) | ||
2027 | #define DIF_BPF_COEFF3031 (0x384) | ||
2028 | #define DIF_BPF_COEFF3233 (0x388) | ||
2029 | #define DIF_BPF_COEFF3435 (0x38c) | ||
2030 | #define DIF_BPF_COEFF36 (0x390) | ||
2031 | |||
2032 | void cx23885_dif_setup(struct i2c_client *client, u32 ifHz) | ||
2033 | { | ||
2034 | u64 pll_freq; | ||
2035 | u32 pll_freq_word; | ||
2036 | |||
2037 | v4l_dbg(1, cx25840_debug, client, "%s(%d)\n", __func__, ifHz); | ||
2038 | |||
2039 | /* Assuming TV */ | ||
2040 | /* Calculate the PLL frequency word based on the adjusted ifHz */ | ||
2041 | pll_freq = div_u64((u64)ifHz * 268435456, 50000000); | ||
2042 | pll_freq_word = (u32)pll_freq; | ||
2043 | |||
2044 | cx25840_write4(client, DIF_PLL_FREQ_WORD, pll_freq_word); | ||
2045 | |||
2046 | /* Round down to the nearest 100KHz */ | ||
2047 | ifHz = (ifHz / 100000) * 100000; | ||
2048 | |||
2049 | if (ifHz < 3000000) | ||
2050 | ifHz = 3000000; | ||
2051 | |||
2052 | if (ifHz > 16000000) | ||
2053 | ifHz = 16000000; | ||
2054 | |||
2055 | v4l_dbg(1, cx25840_debug, client, "%s(%d) again\n", __func__, ifHz); | ||
2056 | |||
2057 | switch (ifHz) { | ||
2058 | case 3000000: | ||
2059 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
2060 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00080012); | ||
2061 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0024); | ||
2062 | cx25840_write4(client, DIF_BPF_COEFF67, 0x001bfff8); | ||
2063 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffb4ff50); | ||
2064 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed8fe68); | ||
2065 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe24fe34); | ||
2066 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfebaffc7); | ||
2067 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d031f); | ||
2068 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x04f0065d); | ||
2069 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x07010688); | ||
2070 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x04c901d6); | ||
2071 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe00f9d3); | ||
2072 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f342); | ||
2073 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf235f337); | ||
2074 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf64efb22); | ||
2075 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0105070f); | ||
2076 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0c460fce); | ||
2077 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2078 | break; | ||
2079 | |||
2080 | case 3100000: | ||
2081 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001); | ||
2082 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00070012); | ||
2083 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00220032); | ||
2084 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00370026); | ||
2085 | cx25840_write4(client, DIF_BPF_COEFF89, 0xfff0ff91); | ||
2086 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff0efe7c); | ||
2087 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01fdcc); | ||
2088 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe0afedb); | ||
2089 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440224); | ||
2090 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0434060c); | ||
2091 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0738074e); | ||
2092 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x06090361); | ||
2093 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xff99fb39); | ||
2094 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef3b6); | ||
2095 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21af2a5); | ||
2096 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf573fa33); | ||
2097 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0034067d); | ||
2098 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0bfb0fb9); | ||
2099 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2100 | break; | ||
2101 | |||
2102 | case 3200000: | ||
2103 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000000); | ||
2104 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0004000e); | ||
2105 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00200038); | ||
2106 | cx25840_write4(client, DIF_BPF_COEFF67, 0x004c004f); | ||
2107 | cx25840_write4(client, DIF_BPF_COEFF89, 0x002fffdf); | ||
2108 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff5cfeb6); | ||
2109 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0dfd92); | ||
2110 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd7ffe03); | ||
2111 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36010a); | ||
2112 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x03410575); | ||
2113 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x072607d2); | ||
2114 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x071804d5); | ||
2115 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0134fcb7); | ||
2116 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff451); | ||
2117 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf223f22e); | ||
2118 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4a7f94b); | ||
2119 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xff6405e8); | ||
2120 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0bae0fa4); | ||
2121 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2122 | break; | ||
2123 | |||
2124 | case 3300000: | ||
2125 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff); | ||
2126 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00000008); | ||
2127 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001a0036); | ||
2128 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0056006d); | ||
2129 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00670030); | ||
2130 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffbdff10); | ||
2131 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe46fd8d); | ||
2132 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd25fd4f); | ||
2133 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35ffe0); | ||
2134 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0224049f); | ||
2135 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c9080e); | ||
2136 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x07ef0627); | ||
2137 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c9fe45); | ||
2138 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f513); | ||
2139 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf250f1d2); | ||
2140 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3ecf869); | ||
2141 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe930552); | ||
2142 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0b5f0f8f); | ||
2143 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2144 | break; | ||
2145 | |||
2146 | case 3400000: | ||
2147 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe); | ||
2148 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd0001); | ||
2149 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000f002c); | ||
2150 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0054007d); | ||
2151 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0093007c); | ||
2152 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0024ff82); | ||
2153 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea6fdbb); | ||
2154 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd03fcca); | ||
2155 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51feb9); | ||
2156 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x00eb0392); | ||
2157 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06270802); | ||
2158 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08880750); | ||
2159 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x044dffdb); | ||
2160 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf5f8); | ||
2161 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a0f193); | ||
2162 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf342f78f); | ||
2163 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc404b9); | ||
2164 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0b0e0f78); | ||
2165 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2166 | break; | ||
2167 | |||
2168 | case 3500000: | ||
2169 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd); | ||
2170 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff9); | ||
2171 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0002001b); | ||
2172 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0046007d); | ||
2173 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00ad00ba); | ||
2174 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00870000); | ||
2175 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff26fe1a); | ||
2176 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd1bfc7e); | ||
2177 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fda4); | ||
2178 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xffa5025c); | ||
2179 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x054507ad); | ||
2180 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08dd0847); | ||
2181 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b80172); | ||
2182 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef6ff); | ||
2183 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf313f170); | ||
2184 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2abf6bd); | ||
2185 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6041f); | ||
2186 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0abc0f61); | ||
2187 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2188 | break; | ||
2189 | |||
2190 | case 3600000: | ||
2191 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd); | ||
2192 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff3); | ||
2193 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff50006); | ||
2194 | cx25840_write4(client, DIF_BPF_COEFF67, 0x002f006c); | ||
2195 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00b200e3); | ||
2196 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00dc007e); | ||
2197 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffb9fea0); | ||
2198 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd6bfc71); | ||
2199 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fcb1); | ||
2200 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe65010b); | ||
2201 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x042d0713); | ||
2202 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08ec0906); | ||
2203 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x07020302); | ||
2204 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff823); | ||
2205 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3a7f16a); | ||
2206 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf228f5f5); | ||
2207 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfc2a0384); | ||
2208 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0a670f4a); | ||
2209 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2210 | break; | ||
2211 | |||
2212 | case 3700000: | ||
2213 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
2214 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7ffef); | ||
2215 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe9fff1); | ||
2216 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0010004d); | ||
2217 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00a100f2); | ||
2218 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x011a00f0); | ||
2219 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0053ff44); | ||
2220 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdedfca2); | ||
2221 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fbef); | ||
2222 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd39ffae); | ||
2223 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x02ea0638); | ||
2224 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08b50987); | ||
2225 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x08230483); | ||
2226 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f960); | ||
2227 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf45bf180); | ||
2228 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1b8f537); | ||
2229 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfb6102e7); | ||
2230 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x0a110f32); | ||
2231 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2232 | break; | ||
2233 | |||
2234 | case 3800000: | ||
2235 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
2236 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9ffee); | ||
2237 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffdd); | ||
2238 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfff00024); | ||
2239 | cx25840_write4(client, DIF_BPF_COEFF89, 0x007c00e5); | ||
2240 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013a014a); | ||
2241 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00e6fff8); | ||
2242 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe98fd0f); | ||
2243 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fb67); | ||
2244 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc32fe54); | ||
2245 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x01880525); | ||
2246 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x083909c7); | ||
2247 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x091505ee); | ||
2248 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7fab3); | ||
2249 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf52df1b4); | ||
2250 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf15df484); | ||
2251 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfa9b0249); | ||
2252 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x09ba0f19); | ||
2253 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2254 | break; | ||
2255 | |||
2256 | case 3900000: | ||
2257 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000000); | ||
2258 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbfff0); | ||
2259 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffcf); | ||
2260 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1fff6); | ||
2261 | cx25840_write4(client, DIF_BPF_COEFF89, 0x004800be); | ||
2262 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x01390184); | ||
2263 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x016300ac); | ||
2264 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff5efdb1); | ||
2265 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fb23); | ||
2266 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb5cfd0d); | ||
2267 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x001703e4); | ||
2268 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x077b09c4); | ||
2269 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x09d2073c); | ||
2270 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251fc18); | ||
2271 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf61cf203); | ||
2272 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf118f3dc); | ||
2273 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf9d801aa); | ||
2274 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x09600eff); | ||
2275 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2276 | break; | ||
2277 | |||
2278 | case 4000000: | ||
2279 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001); | ||
2280 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffefff4); | ||
2281 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffc8); | ||
2282 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffca); | ||
2283 | cx25840_write4(client, DIF_BPF_COEFF89, 0x000b0082); | ||
2284 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x01170198); | ||
2285 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01c10152); | ||
2286 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0030fe7b); | ||
2287 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fb24); | ||
2288 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfac3fbe9); | ||
2289 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfea5027f); | ||
2290 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0683097f); | ||
2291 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a560867); | ||
2292 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2fd89); | ||
2293 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf723f26f); | ||
2294 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0e8f341); | ||
2295 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf919010a); | ||
2296 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x09060ee5); | ||
2297 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2298 | break; | ||
2299 | |||
2300 | case 4100000: | ||
2301 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002); | ||
2302 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0002fffb); | ||
2303 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe8ffca); | ||
2304 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffa4); | ||
2305 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffcd0036); | ||
2306 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d70184); | ||
2307 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f601dc); | ||
2308 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x00ffff60); | ||
2309 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb6d); | ||
2310 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa6efaf5); | ||
2311 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd410103); | ||
2312 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x055708f9); | ||
2313 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a9e0969); | ||
2314 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543ff02); | ||
2315 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf842f2f5); | ||
2316 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0cef2b2); | ||
2317 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf85e006b); | ||
2318 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x08aa0ecb); | ||
2319 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2320 | break; | ||
2321 | |||
2322 | case 4200000: | ||
2323 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003); | ||
2324 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00050003); | ||
2325 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff3ffd3); | ||
2326 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaff8b); | ||
2327 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff95ffe5); | ||
2328 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0080014a); | ||
2329 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fe023f); | ||
2330 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01ba0050); | ||
2331 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fbf8); | ||
2332 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa62fa3b); | ||
2333 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbf9ff7e); | ||
2334 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x04010836); | ||
2335 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aa90a3d); | ||
2336 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f007f); | ||
2337 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf975f395); | ||
2338 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0cbf231); | ||
2339 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf7a9ffcb); | ||
2340 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x084c0eaf); | ||
2341 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2342 | break; | ||
2343 | |||
2344 | case 4300000: | ||
2345 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003); | ||
2346 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000a); | ||
2347 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0000ffe4); | ||
2348 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ff81); | ||
2349 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff6aff96); | ||
2350 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x001c00f0); | ||
2351 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01d70271); | ||
2352 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0254013b); | ||
2353 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fcbd); | ||
2354 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa9ff9c5); | ||
2355 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfadbfdfe); | ||
2356 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x028c073b); | ||
2357 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a750adf); | ||
2358 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e101fa); | ||
2359 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfab8f44e); | ||
2360 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0ddf1be); | ||
2361 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf6f9ff2b); | ||
2362 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x07ed0e94); | ||
2363 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2364 | break; | ||
2365 | |||
2366 | case 4400000: | ||
2367 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
2368 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0009000f); | ||
2369 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000efff8); | ||
2370 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ff87); | ||
2371 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff52ff54); | ||
2372 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffb5007e); | ||
2373 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01860270); | ||
2374 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c00210); | ||
2375 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fdb2); | ||
2376 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb22f997); | ||
2377 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9f2fc90); | ||
2378 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0102060f); | ||
2379 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a050b4c); | ||
2380 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902036e); | ||
2381 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfc0af51e); | ||
2382 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf106f15a); | ||
2383 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf64efe8b); | ||
2384 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x078d0e77); | ||
2385 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2386 | break; | ||
2387 | |||
2388 | case 4500000: | ||
2389 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
2390 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00080012); | ||
2391 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0019000e); | ||
2392 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff9e); | ||
2393 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff4fff25); | ||
2394 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff560000); | ||
2395 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0112023b); | ||
2396 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f702c0); | ||
2397 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfec8); | ||
2398 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbe5f9b3); | ||
2399 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf947fb41); | ||
2400 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xff7004b9); | ||
2401 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x095a0b81); | ||
2402 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a0004d8); | ||
2403 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfd65f603); | ||
2404 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf144f104); | ||
2405 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf5aafdec); | ||
2406 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x072b0e5a); | ||
2407 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2408 | break; | ||
2409 | |||
2410 | case 4600000: | ||
2411 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001); | ||
2412 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00060012); | ||
2413 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00200022); | ||
2414 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ffc1); | ||
2415 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff61ff10); | ||
2416 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff09ff82); | ||
2417 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x008601d7); | ||
2418 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f50340); | ||
2419 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fff0); | ||
2420 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcddfa19); | ||
2421 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8e2fa1e); | ||
2422 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfde30343); | ||
2423 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x08790b7f); | ||
2424 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50631); | ||
2425 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfec7f6fc); | ||
2426 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf198f0bd); | ||
2427 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf50dfd4e); | ||
2428 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x06c90e3d); | ||
2429 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2430 | break; | ||
2431 | |||
2432 | case 4700000: | ||
2433 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff); | ||
2434 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0003000f); | ||
2435 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00220030); | ||
2436 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ffed); | ||
2437 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff87ff15); | ||
2438 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed6ff10); | ||
2439 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffed014c); | ||
2440 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b90386); | ||
2441 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110119); | ||
2442 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfdfefac4); | ||
2443 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8c6f92f); | ||
2444 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc6701b7); | ||
2445 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x07670b44); | ||
2446 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0776); | ||
2447 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x002df807); | ||
2448 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf200f086); | ||
2449 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf477fcb1); | ||
2450 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x06650e1e); | ||
2451 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2452 | break; | ||
2453 | |||
2454 | case 4800000: | ||
2455 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe); | ||
2456 | cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0009); | ||
2457 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0038); | ||
2458 | cx25840_write4(client, DIF_BPF_COEFF67, 0x003f001b); | ||
2459 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffbcff36); | ||
2460 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec2feb6); | ||
2461 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff5600a5); | ||
2462 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0248038d); | ||
2463 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00232); | ||
2464 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xff39fbab); | ||
2465 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8f4f87f); | ||
2466 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb060020); | ||
2467 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x062a0ad2); | ||
2468 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf908a3); | ||
2469 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0192f922); | ||
2470 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf27df05e); | ||
2471 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf3e8fc14); | ||
2472 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x06000e00); | ||
2473 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2474 | break; | ||
2475 | |||
2476 | case 4900000: | ||
2477 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd); | ||
2478 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc0002); | ||
2479 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00160037); | ||
2480 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00510046); | ||
2481 | cx25840_write4(client, DIF_BPF_COEFF89, 0xfff9ff6d); | ||
2482 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed0fe7c); | ||
2483 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfecefff0); | ||
2484 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01aa0356); | ||
2485 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413032b); | ||
2486 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x007ffcc5); | ||
2487 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf96cf812); | ||
2488 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9cefe87); | ||
2489 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x04c90a2c); | ||
2490 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c4309b4); | ||
2491 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x02f3fa4a); | ||
2492 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf30ef046); | ||
2493 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf361fb7a); | ||
2494 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x059b0de0); | ||
2495 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2496 | break; | ||
2497 | |||
2498 | case 5000000: | ||
2499 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd); | ||
2500 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffa); | ||
2501 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000a002d); | ||
2502 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00570067); | ||
2503 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0037ffb5); | ||
2504 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfefffe68); | ||
2505 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe62ff3d); | ||
2506 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x00ec02e3); | ||
2507 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x043503f6); | ||
2508 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x01befe05); | ||
2509 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa27f7ee); | ||
2510 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8c6fcf8); | ||
2511 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x034c0954); | ||
2512 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5c0aa4); | ||
2513 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x044cfb7e); | ||
2514 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3b1f03f); | ||
2515 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf2e2fae1); | ||
2516 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x05340dc0); | ||
2517 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2518 | break; | ||
2519 | |||
2520 | case 5100000: | ||
2521 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
2522 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff4); | ||
2523 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfffd001e); | ||
2524 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0051007b); | ||
2525 | cx25840_write4(client, DIF_BPF_COEFF89, 0x006e0006); | ||
2526 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff48fe7c); | ||
2527 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe1bfe9a); | ||
2528 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x001d023e); | ||
2529 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130488); | ||
2530 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x02e6ff5b); | ||
2531 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb1ef812); | ||
2532 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7f7fb7f); | ||
2533 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x01bc084e); | ||
2534 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c430b72); | ||
2535 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x059afcba); | ||
2536 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf467f046); | ||
2537 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf26cfa4a); | ||
2538 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x04cd0da0); | ||
2539 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2540 | break; | ||
2541 | |||
2542 | case 5200000: | ||
2543 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
2544 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8ffef); | ||
2545 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff00009); | ||
2546 | cx25840_write4(client, DIF_BPF_COEFF67, 0x003f007f); | ||
2547 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00980056); | ||
2548 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffa5feb6); | ||
2549 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe00fe15); | ||
2550 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff4b0170); | ||
2551 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b004d7); | ||
2552 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x03e800b9); | ||
2553 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc48f87f); | ||
2554 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf768fa23); | ||
2555 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0022071f); | ||
2556 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf90c1b); | ||
2557 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x06dafdfd); | ||
2558 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf52df05e); | ||
2559 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf1fef9b5); | ||
2560 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x04640d7f); | ||
2561 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2562 | break; | ||
2563 | |||
2564 | case 5300000: | ||
2565 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff); | ||
2566 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9ffee); | ||
2567 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe6fff3); | ||
2568 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00250072); | ||
2569 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00af009c); | ||
2570 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x000cff10); | ||
2571 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe13fdb8); | ||
2572 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe870089); | ||
2573 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x031104e1); | ||
2574 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x04b8020f); | ||
2575 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd98f92f); | ||
2576 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf71df8f0); | ||
2577 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe8805ce); | ||
2578 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0c9c); | ||
2579 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0808ff44); | ||
2580 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf603f086); | ||
2581 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf19af922); | ||
2582 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x03fb0d5e); | ||
2583 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2584 | break; | ||
2585 | |||
2586 | case 5400000: | ||
2587 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001); | ||
2588 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcffef); | ||
2589 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffe0); | ||
2590 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00050056); | ||
2591 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00b000d1); | ||
2592 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0071ff82); | ||
2593 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe53fd8c); | ||
2594 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfddfff99); | ||
2595 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104a3); | ||
2596 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x054a034d); | ||
2597 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xff01fa1e); | ||
2598 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf717f7ed); | ||
2599 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfcf50461); | ||
2600 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50cf4); | ||
2601 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0921008d); | ||
2602 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf6e7f0bd); | ||
2603 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf13ff891); | ||
2604 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x03920d3b); | ||
2605 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2606 | break; | ||
2607 | |||
2608 | case 5500000: | ||
2609 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002); | ||
2610 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffffff3); | ||
2611 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffd1); | ||
2612 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5002f); | ||
2613 | cx25840_write4(client, DIF_BPF_COEFF89, 0x009c00ed); | ||
2614 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00cb0000); | ||
2615 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfebafd94); | ||
2616 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd61feb0); | ||
2617 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d0422); | ||
2618 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x05970464); | ||
2619 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0074fb41); | ||
2620 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf759f721); | ||
2621 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfb7502de); | ||
2622 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000d21); | ||
2623 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a2201d4); | ||
2624 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf7d9f104); | ||
2625 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0edf804); | ||
2626 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x03280d19); | ||
2627 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2628 | break; | ||
2629 | |||
2630 | case 5600000: | ||
2631 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003); | ||
2632 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0003fffa); | ||
2633 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe3ffc9); | ||
2634 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc90002); | ||
2635 | cx25840_write4(client, DIF_BPF_COEFF89, 0x007500ef); | ||
2636 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x010e007e); | ||
2637 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff3dfdcf); | ||
2638 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd16fddd); | ||
2639 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440365); | ||
2640 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x059b0548); | ||
2641 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x01e3fc90); | ||
2642 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7dff691); | ||
2643 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa0f014d); | ||
2644 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x09020d23); | ||
2645 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b0a0318); | ||
2646 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf8d7f15a); | ||
2647 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0a5f779); | ||
2648 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x02bd0cf6); | ||
2649 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2650 | break; | ||
2651 | |||
2652 | case 5700000: | ||
2653 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010003); | ||
2654 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00060001); | ||
2655 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffecffc9); | ||
2656 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ffd4); | ||
2657 | cx25840_write4(client, DIF_BPF_COEFF89, 0x004000d5); | ||
2658 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013600f0); | ||
2659 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffd3fe39); | ||
2660 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd04fd31); | ||
2661 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff360277); | ||
2662 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x055605ef); | ||
2663 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x033efdfe); | ||
2664 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8a5f642); | ||
2665 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf8cbffb6); | ||
2666 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e10cfb); | ||
2667 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0bd50456); | ||
2668 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf9dff1be); | ||
2669 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf067f6f2); | ||
2670 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x02520cd2); | ||
2671 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2672 | break; | ||
2673 | |||
2674 | case 5800000: | ||
2675 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
2676 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00080009); | ||
2677 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff8ffd2); | ||
2678 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaffac); | ||
2679 | cx25840_write4(client, DIF_BPF_COEFF89, 0x000200a3); | ||
2680 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013c014a); | ||
2681 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x006dfec9); | ||
2682 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd2bfcb7); | ||
2683 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe350165); | ||
2684 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x04cb0651); | ||
2685 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0477ff7e); | ||
2686 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9a5f635); | ||
2687 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7b1fe20); | ||
2688 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0ca8); | ||
2689 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c81058b); | ||
2690 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfaf0f231); | ||
2691 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf033f66d); | ||
2692 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x01e60cae); | ||
2693 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2694 | break; | ||
2695 | |||
2696 | case 5900000: | ||
2697 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
2698 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0009000e); | ||
2699 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0005ffe1); | ||
2700 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffacff90); | ||
2701 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffc5005f); | ||
2702 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x01210184); | ||
2703 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00fcff72); | ||
2704 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd8afc77); | ||
2705 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51003f); | ||
2706 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x04020669); | ||
2707 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x05830103); | ||
2708 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfad7f66b); | ||
2709 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6c8fc93); | ||
2710 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430c2b); | ||
2711 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d0d06b5); | ||
2712 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfc08f2b2); | ||
2713 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf00af5ec); | ||
2714 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x017b0c89); | ||
2715 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2716 | break; | ||
2717 | |||
2718 | case 6000000: | ||
2719 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001); | ||
2720 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00070012); | ||
2721 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0012fff5); | ||
2722 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaff82); | ||
2723 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff8e000f); | ||
2724 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e80198); | ||
2725 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01750028); | ||
2726 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe18fc75); | ||
2727 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99ff15); | ||
2728 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x03050636); | ||
2729 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0656027f); | ||
2730 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc32f6e2); | ||
2731 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf614fb17); | ||
2732 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20b87); | ||
2733 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d7707d2); | ||
2734 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfd26f341); | ||
2735 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xefeaf56f); | ||
2736 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x010f0c64); | ||
2737 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2738 | break; | ||
2739 | |||
2740 | case 6100000: | ||
2741 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000); | ||
2742 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00050012); | ||
2743 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001c000b); | ||
2744 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1ff84); | ||
2745 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff66ffbe); | ||
2746 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00960184); | ||
2747 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01cd00da); | ||
2748 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfeccfcb2); | ||
2749 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fdf9); | ||
2750 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x01e005bc); | ||
2751 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06e703e4); | ||
2752 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfdabf798); | ||
2753 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf599f9b3); | ||
2754 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x02510abd); | ||
2755 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dbf08df); | ||
2756 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfe48f3dc); | ||
2757 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xefd5f4f6); | ||
2758 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x00a20c3e); | ||
2759 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2760 | break; | ||
2761 | |||
2762 | case 6200000: | ||
2763 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe); | ||
2764 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0002000f); | ||
2765 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0021001f); | ||
2766 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0ff97); | ||
2767 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff50ff74); | ||
2768 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0034014a); | ||
2769 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fa0179); | ||
2770 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff97fd2a); | ||
2771 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fcfa); | ||
2772 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x00a304fe); | ||
2773 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x07310525); | ||
2774 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xff37f886); | ||
2775 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55cf86e); | ||
2776 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c709d0); | ||
2777 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de209db); | ||
2778 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xff6df484); | ||
2779 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xefcbf481); | ||
2780 | cx25840_write4(client, DIF_BPF_COEFF3435, 0x00360c18); | ||
2781 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2782 | break; | ||
2783 | |||
2784 | case 6300000: | ||
2785 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd); | ||
2786 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffe000a); | ||
2787 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0021002f); | ||
2788 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0010ffb8); | ||
2789 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff50ff3b); | ||
2790 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffcc00f0); | ||
2791 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fa01fa); | ||
2792 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0069fdd4); | ||
2793 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fc26); | ||
2794 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xff5d0407); | ||
2795 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x07310638); | ||
2796 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x00c9f9a8); | ||
2797 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55cf74e); | ||
2798 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xff3908c3); | ||
2799 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de20ac3); | ||
2800 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0093f537); | ||
2801 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xefcbf410); | ||
2802 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xffca0bf2); | ||
2803 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2804 | break; | ||
2805 | |||
2806 | case 6400000: | ||
2807 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffd); | ||
2808 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffb0003); | ||
2809 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001c0037); | ||
2810 | cx25840_write4(client, DIF_BPF_COEFF67, 0x002fffe2); | ||
2811 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff66ff17); | ||
2812 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff6a007e); | ||
2813 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01cd0251); | ||
2814 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0134fea5); | ||
2815 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fb8b); | ||
2816 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe2002e0); | ||
2817 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06e70713); | ||
2818 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0255faf5); | ||
2819 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf599f658); | ||
2820 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaf0799); | ||
2821 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dbf0b96); | ||
2822 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x01b8f5f5); | ||
2823 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xefd5f3a3); | ||
2824 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xff5e0bca); | ||
2825 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2826 | break; | ||
2827 | |||
2828 | case 6500000: | ||
2829 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
2830 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffb); | ||
2831 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00120037); | ||
2832 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00460010); | ||
2833 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff8eff0f); | ||
2834 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff180000); | ||
2835 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01750276); | ||
2836 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01e8ff8d); | ||
2837 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fb31); | ||
2838 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcfb0198); | ||
2839 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x065607ad); | ||
2840 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x03cefc64); | ||
2841 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf614f592); | ||
2842 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2e0656); | ||
2843 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d770c52); | ||
2844 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x02daf6bd); | ||
2845 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xefeaf33b); | ||
2846 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfef10ba3); | ||
2847 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2848 | break; | ||
2849 | |||
2850 | case 6600000: | ||
2851 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
2852 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7fff5); | ||
2853 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0005002f); | ||
2854 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0054003c); | ||
2855 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffc5ff22); | ||
2856 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedfff82); | ||
2857 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00fc0267); | ||
2858 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0276007e); | ||
2859 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb1c); | ||
2860 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbfe003e); | ||
2861 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x05830802); | ||
2862 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0529fdec); | ||
2863 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6c8f4fe); | ||
2864 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabd04ff); | ||
2865 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d0d0cf6); | ||
2866 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x03f8f78f); | ||
2867 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf00af2d7); | ||
2868 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfe850b7b); | ||
2869 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2870 | break; | ||
2871 | |||
2872 | case 6700000: | ||
2873 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff); | ||
2874 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff0); | ||
2875 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff80020); | ||
2876 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00560060); | ||
2877 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0002ff4e); | ||
2878 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec4ff10); | ||
2879 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x006d0225); | ||
2880 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02d50166); | ||
2881 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb4e); | ||
2882 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb35fee1); | ||
2883 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0477080e); | ||
2884 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x065bff82); | ||
2885 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7b1f4a0); | ||
2886 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf9610397); | ||
2887 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c810d80); | ||
2888 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0510f869); | ||
2889 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf033f278); | ||
2890 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfe1a0b52); | ||
2891 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2892 | break; | ||
2893 | |||
2894 | case 6800000: | ||
2895 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000); | ||
2896 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffaffee); | ||
2897 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffec000c); | ||
2898 | cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0078); | ||
2899 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0040ff8e); | ||
2900 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecafeb6); | ||
2901 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffd301b6); | ||
2902 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fc0235); | ||
2903 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fbc5); | ||
2904 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaaafd90); | ||
2905 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x033e07d2); | ||
2906 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x075b011b); | ||
2907 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf8cbf47a); | ||
2908 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81f0224); | ||
2909 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0bd50def); | ||
2910 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0621f94b); | ||
2911 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf067f21e); | ||
2912 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfdae0b29); | ||
2913 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2914 | break; | ||
2915 | |||
2916 | case 6900000: | ||
2917 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001); | ||
2918 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffdffef); | ||
2919 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe3fff6); | ||
2920 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0037007f); | ||
2921 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0075ffdc); | ||
2922 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef2fe7c); | ||
2923 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff3d0122); | ||
2924 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02ea02dd); | ||
2925 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fc79); | ||
2926 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa65fc5d); | ||
2927 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x01e3074e); | ||
2928 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x082102ad); | ||
2929 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa0ff48c); | ||
2930 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fe00a9); | ||
2931 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b0a0e43); | ||
2932 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0729fa33); | ||
2933 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0a5f1c9); | ||
2934 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfd430b00); | ||
2935 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2936 | break; | ||
2937 | |||
2938 | case 7000000: | ||
2939 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002); | ||
2940 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0001fff3); | ||
2941 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffe2); | ||
2942 | cx25840_write4(client, DIF_BPF_COEFF67, 0x001b0076); | ||
2943 | cx25840_write4(client, DIF_BPF_COEFF89, 0x009c002d); | ||
2944 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff35fe68); | ||
2945 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfeba0076); | ||
2946 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x029f0352); | ||
2947 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfd60); | ||
2948 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa69fb53); | ||
2949 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x00740688); | ||
2950 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08a7042d); | ||
2951 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfb75f4d6); | ||
2952 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600ff2d); | ||
2953 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a220e7a); | ||
2954 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0827fb22); | ||
2955 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf0edf17a); | ||
2956 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfcd80ad6); | ||
2957 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2958 | break; | ||
2959 | |||
2960 | case 7100000: | ||
2961 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
2962 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0004fff9); | ||
2963 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffd2); | ||
2964 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfffb005e); | ||
2965 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00b0007a); | ||
2966 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff8ffe7c); | ||
2967 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe53ffc1); | ||
2968 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0221038c); | ||
2969 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fe6e); | ||
2970 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfab6fa80); | ||
2971 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xff010587); | ||
2972 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08e90590); | ||
2973 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfcf5f556); | ||
2974 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bfdb3); | ||
2975 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x09210e95); | ||
2976 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0919fc15); | ||
2977 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf13ff12f); | ||
2978 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfc6e0aab); | ||
2979 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
2980 | break; | ||
2981 | |||
2982 | case 7200000: | ||
2983 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
2984 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00070000); | ||
2985 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe6ffc9); | ||
2986 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffdb0039); | ||
2987 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00af00b8); | ||
2988 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfff4feb6); | ||
2989 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe13ff10); | ||
2990 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01790388); | ||
2991 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311ff92); | ||
2992 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb48f9ed); | ||
2993 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd980453); | ||
2994 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08e306cd); | ||
2995 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe88f60a); | ||
2996 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482fc40); | ||
2997 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x08080e93); | ||
2998 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x09fdfd0c); | ||
2999 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf19af0ea); | ||
3000 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfc050a81); | ||
3001 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3002 | break; | ||
3003 | |||
3004 | case 7300000: | ||
3005 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
3006 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00080008); | ||
3007 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff0ffc9); | ||
3008 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1000d); | ||
3009 | cx25840_write4(client, DIF_BPF_COEFF89, 0x009800e2); | ||
3010 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x005bff10); | ||
3011 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe00fe74); | ||
3012 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x00b50345); | ||
3013 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b000bc); | ||
3014 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc18f9a1); | ||
3015 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc4802f9); | ||
3016 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x089807dc); | ||
3017 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0022f6f0); | ||
3018 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407fada); | ||
3019 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x06da0e74); | ||
3020 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ad3fe06); | ||
3021 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf1fef0ab); | ||
3022 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfb9c0a55); | ||
3023 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3024 | break; | ||
3025 | |||
3026 | case 7400000: | ||
3027 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000001); | ||
3028 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000e); | ||
3029 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfffdffd0); | ||
3030 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffafffdf); | ||
3031 | cx25840_write4(client, DIF_BPF_COEFF89, 0x006e00f2); | ||
3032 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00b8ff82); | ||
3033 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe1bfdf8); | ||
3034 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xffe302c8); | ||
3035 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x041301dc); | ||
3036 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd1af99e); | ||
3037 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb1e0183); | ||
3038 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x080908b5); | ||
3039 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x01bcf801); | ||
3040 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdf985); | ||
3041 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x059a0e38); | ||
3042 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b99ff03); | ||
3043 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf26cf071); | ||
3044 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfb330a2a); | ||
3045 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3046 | break; | ||
3047 | |||
3048 | case 7500000: | ||
3049 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000); | ||
3050 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00070011); | ||
3051 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000affdf); | ||
3052 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffa9ffb5); | ||
3053 | cx25840_write4(client, DIF_BPF_COEFF89, 0x003700e6); | ||
3054 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x01010000); | ||
3055 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe62fda8); | ||
3056 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff140219); | ||
3057 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x043502e1); | ||
3058 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe42f9e6); | ||
3059 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa270000); | ||
3060 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x073a0953); | ||
3061 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x034cf939); | ||
3062 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3a4f845); | ||
3063 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x044c0de1); | ||
3064 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c4f0000); | ||
3065 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf2e2f03c); | ||
3066 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfacc09fe); | ||
3067 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3068 | break; | ||
3069 | |||
3070 | case 7600000: | ||
3071 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff); | ||
3072 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00040012); | ||
3073 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0016fff3); | ||
3074 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffafff95); | ||
3075 | cx25840_write4(client, DIF_BPF_COEFF89, 0xfff900c0); | ||
3076 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0130007e); | ||
3077 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfecefd89); | ||
3078 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe560146); | ||
3079 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x041303bc); | ||
3080 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xff81fa76); | ||
3081 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf96cfe7d); | ||
3082 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x063209b1); | ||
3083 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x04c9fa93); | ||
3084 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdf71e); | ||
3085 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x02f30d6e); | ||
3086 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cf200fd); | ||
3087 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf361f00e); | ||
3088 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfa6509d1); | ||
3089 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3090 | break; | ||
3091 | |||
3092 | case 7700000: | ||
3093 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe); | ||
3094 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00010010); | ||
3095 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001e0008); | ||
3096 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1ff84); | ||
3097 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffbc0084); | ||
3098 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013e00f0); | ||
3099 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff56fd9f); | ||
3100 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdb8005c); | ||
3101 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00460); | ||
3102 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x00c7fb45); | ||
3103 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8f4fd07); | ||
3104 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x04fa09ce); | ||
3105 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x062afc07); | ||
3106 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407f614); | ||
3107 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x01920ce0); | ||
3108 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d8301fa); | ||
3109 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf3e8efe5); | ||
3110 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xfa0009a4); | ||
3111 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3112 | break; | ||
3113 | |||
3114 | case 7800000: | ||
3115 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
3116 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd000b); | ||
3117 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0022001d); | ||
3118 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffdbff82); | ||
3119 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff870039); | ||
3120 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x012a014a); | ||
3121 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffedfde7); | ||
3122 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd47ff6b); | ||
3123 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x031104c6); | ||
3124 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0202fc4c); | ||
3125 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8c6fbad); | ||
3126 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x039909a7); | ||
3127 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0767fd8e); | ||
3128 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482f52b); | ||
3129 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x002d0c39); | ||
3130 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e0002f4); | ||
3131 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf477efc2); | ||
3132 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf99b0977); | ||
3133 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3134 | break; | ||
3135 | |||
3136 | case 7900000: | ||
3137 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
3138 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa0004); | ||
3139 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0020002d); | ||
3140 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfffbff91); | ||
3141 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff61ffe8); | ||
3142 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f70184); | ||
3143 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0086fe5c); | ||
3144 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd0bfe85); | ||
3145 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104e5); | ||
3146 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0323fd7d); | ||
3147 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8e2fa79); | ||
3148 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x021d093f); | ||
3149 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0879ff22); | ||
3150 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bf465); | ||
3151 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfec70b79); | ||
3152 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e6803eb); | ||
3153 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf50defa5); | ||
3154 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf937094a); | ||
3155 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3156 | break; | ||
3157 | |||
3158 | case 8000000: | ||
3159 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
3160 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fffd); | ||
3161 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00190036); | ||
3162 | cx25840_write4(client, DIF_BPF_COEFF67, 0x001bffaf); | ||
3163 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff4fff99); | ||
3164 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00aa0198); | ||
3165 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0112fef3); | ||
3166 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd09fdb9); | ||
3167 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d04be); | ||
3168 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x041bfecc); | ||
3169 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf947f978); | ||
3170 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x00900897); | ||
3171 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x095a00b9); | ||
3172 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f3c5); | ||
3173 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfd650aa3); | ||
3174 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ebc04de); | ||
3175 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf5aaef8e); | ||
3176 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf8d5091c); | ||
3177 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3178 | break; | ||
3179 | |||
3180 | case 8100000: | ||
3181 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000ffff); | ||
3182 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff7fff6); | ||
3183 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000e0038); | ||
3184 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0037ffd7); | ||
3185 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff52ff56); | ||
3186 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x004b0184); | ||
3187 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0186ffa1); | ||
3188 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd40fd16); | ||
3189 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440452); | ||
3190 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x04de0029); | ||
3191 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9f2f8b2); | ||
3192 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfefe07b5); | ||
3193 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a05024d); | ||
3194 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef34d); | ||
3195 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfc0a09b8); | ||
3196 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0efa05cd); | ||
3197 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf64eef7d); | ||
3198 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf87308ed); | ||
3199 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3200 | break; | ||
3201 | |||
3202 | case 8200000: | ||
3203 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000); | ||
3204 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff0); | ||
3205 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00000031); | ||
3206 | cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0005); | ||
3207 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff6aff27); | ||
3208 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffe4014a); | ||
3209 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01d70057); | ||
3210 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdacfca6); | ||
3211 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3603a7); | ||
3212 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x05610184); | ||
3213 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfadbf82e); | ||
3214 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd74069f); | ||
3215 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a7503d6); | ||
3216 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff2ff); | ||
3217 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfab808b9); | ||
3218 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f2306b5); | ||
3219 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf6f9ef72); | ||
3220 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf81308bf); | ||
3221 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3222 | break; | ||
3223 | |||
3224 | case 8300000: | ||
3225 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001); | ||
3226 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbffee); | ||
3227 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff30022); | ||
3228 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00560032); | ||
3229 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff95ff10); | ||
3230 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff8000f0); | ||
3231 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01fe0106); | ||
3232 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe46fc71); | ||
3233 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3502c7); | ||
3234 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x059e02ce); | ||
3235 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbf9f7f2); | ||
3236 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfbff055b); | ||
3237 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aa9054c); | ||
3238 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f2db); | ||
3239 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf97507aa); | ||
3240 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f350797); | ||
3241 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf7a9ef6d); | ||
3242 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf7b40890); | ||
3243 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3244 | break; | ||
3245 | |||
3246 | case 8400000: | ||
3247 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002); | ||
3248 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffeffee); | ||
3249 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe8000f); | ||
3250 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00540058); | ||
3251 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffcdff14); | ||
3252 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff29007e); | ||
3253 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f6019e); | ||
3254 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff01fc7c); | ||
3255 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd5101bf); | ||
3256 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x059203f6); | ||
3257 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfd41f7fe); | ||
3258 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfaa903f3); | ||
3259 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a9e06a9); | ||
3260 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf2e2); | ||
3261 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf842068b); | ||
3262 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f320871); | ||
3263 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf85eef6e); | ||
3264 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf7560860); | ||
3265 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3266 | break; | ||
3267 | |||
3268 | case 8500000: | ||
3269 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
3270 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0002fff2); | ||
3271 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1fff9); | ||
3272 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00460073); | ||
3273 | cx25840_write4(client, DIF_BPF_COEFF89, 0x000bff34); | ||
3274 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfee90000); | ||
3275 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01c10215); | ||
3276 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xffd0fcc5); | ||
3277 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99009d); | ||
3278 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x053d04f1); | ||
3279 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfea5f853); | ||
3280 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf97d0270); | ||
3281 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a5607e4); | ||
3282 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef314); | ||
3283 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf723055f); | ||
3284 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0f180943); | ||
3285 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf919ef75); | ||
3286 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf6fa0830); | ||
3287 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3288 | break; | ||
3289 | |||
3290 | case 8600000: | ||
3291 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
3292 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0005fff8); | ||
3293 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffe4); | ||
3294 | cx25840_write4(client, DIF_BPF_COEFF67, 0x002f007f); | ||
3295 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0048ff6b); | ||
3296 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec7ff82); | ||
3297 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0163025f); | ||
3298 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x00a2fd47); | ||
3299 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17ff73); | ||
3300 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x04a405b2); | ||
3301 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0017f8ed); | ||
3302 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf88500dc); | ||
3303 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x09d208f9); | ||
3304 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff370); | ||
3305 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf61c0429); | ||
3306 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ee80a0b); | ||
3307 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xf9d8ef82); | ||
3308 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf6a00800); | ||
3309 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3310 | break; | ||
3311 | |||
3312 | case 8700000: | ||
3313 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
3314 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0007ffff); | ||
3315 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe1ffd4); | ||
3316 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0010007a); | ||
3317 | cx25840_write4(client, DIF_BPF_COEFF89, 0x007cffb2); | ||
3318 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec6ff10); | ||
3319 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00e60277); | ||
3320 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0168fdf9); | ||
3321 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fe50); | ||
3322 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x03ce0631); | ||
3323 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0188f9c8); | ||
3324 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7c7ff43); | ||
3325 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x091509e3); | ||
3326 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f3f6); | ||
3327 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf52d02ea); | ||
3328 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0ea30ac9); | ||
3329 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfa9bef95); | ||
3330 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf64607d0); | ||
3331 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3332 | break; | ||
3333 | |||
3334 | case 8800000: | ||
3335 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
3336 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00090007); | ||
3337 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe9ffca); | ||
3338 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfff00065); | ||
3339 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00a10003); | ||
3340 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfee6feb6); | ||
3341 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0053025b); | ||
3342 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0213fed0); | ||
3343 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3fd46); | ||
3344 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x02c70668); | ||
3345 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x02eafadb); | ||
3346 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf74bfdae); | ||
3347 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x08230a9c); | ||
3348 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7f4a3); | ||
3349 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf45b01a6); | ||
3350 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0e480b7c); | ||
3351 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfb61efae); | ||
3352 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf5ef079f); | ||
3353 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3354 | break; | ||
3355 | |||
3356 | case 8900000: | ||
3357 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000); | ||
3358 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000d); | ||
3359 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff5ffc8); | ||
3360 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffd10043); | ||
3361 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00b20053); | ||
3362 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff24fe7c); | ||
3363 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffb9020c); | ||
3364 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0295ffbb); | ||
3365 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fc64); | ||
3366 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x019b0654); | ||
3367 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x042dfc1c); | ||
3368 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf714fc2a); | ||
3369 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x07020b21); | ||
3370 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251f575); | ||
3371 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3a7005e); | ||
3372 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0dd80c24); | ||
3373 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfc2aefcd); | ||
3374 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf599076e); | ||
3375 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3376 | break; | ||
3377 | |||
3378 | case 9000000: | ||
3379 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff); | ||
3380 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00060011); | ||
3381 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0002ffcf); | ||
3382 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffba0018); | ||
3383 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00ad009a); | ||
3384 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff79fe68); | ||
3385 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff260192); | ||
3386 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02e500ab); | ||
3387 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fbb6); | ||
3388 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x005b05f7); | ||
3389 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0545fd81); | ||
3390 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf723fabf); | ||
3391 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b80b70); | ||
3392 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2f669); | ||
3393 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf313ff15); | ||
3394 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d550cbf); | ||
3395 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6eff2); | ||
3396 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf544073d); | ||
3397 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3398 | break; | ||
3399 | |||
3400 | case 9100000: | ||
3401 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe); | ||
3402 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00030012); | ||
3403 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000fffdd); | ||
3404 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffea); | ||
3405 | cx25840_write4(client, DIF_BPF_COEFF89, 0x009300cf); | ||
3406 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffdcfe7c); | ||
3407 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea600f7); | ||
3408 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fd0190); | ||
3409 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fb46); | ||
3410 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xff150554); | ||
3411 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0627fefd); | ||
3412 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf778f978); | ||
3413 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x044d0b87); | ||
3414 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543f77d); | ||
3415 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a0fdcf); | ||
3416 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cbe0d4e); | ||
3417 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc4f01d); | ||
3418 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4f2070b); | ||
3419 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3420 | break; | ||
3421 | |||
3422 | case 9200000: | ||
3423 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
3424 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00000010); | ||
3425 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001afff0); | ||
3426 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffaaffbf); | ||
3427 | cx25840_write4(client, DIF_BPF_COEFF89, 0x006700ed); | ||
3428 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0043feb6); | ||
3429 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe460047); | ||
3430 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02db0258); | ||
3431 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb1b); | ||
3432 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfddc0473); | ||
3433 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c90082); | ||
3434 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf811f85e); | ||
3435 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c90b66); | ||
3436 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x069ff8ad); | ||
3437 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf250fc8d); | ||
3438 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c140dcf); | ||
3439 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe93f04d); | ||
3440 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4a106d9); | ||
3441 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3442 | break; | ||
3443 | |||
3444 | case 9300000: | ||
3445 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
3446 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc000c); | ||
3447 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00200006); | ||
3448 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ff9c); | ||
3449 | cx25840_write4(client, DIF_BPF_COEFF89, 0x002f00ef); | ||
3450 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00a4ff10); | ||
3451 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0dff92); | ||
3452 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x028102f7); | ||
3453 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb37); | ||
3454 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcbf035e); | ||
3455 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x07260202); | ||
3456 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8e8f778); | ||
3457 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x01340b0d); | ||
3458 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1f9f4); | ||
3459 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf223fb51); | ||
3460 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b590e42); | ||
3461 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xff64f083); | ||
3462 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf45206a7); | ||
3463 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3464 | break; | ||
3465 | |||
3466 | case 9400000: | ||
3467 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
3468 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff90005); | ||
3469 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0022001a); | ||
3470 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ff86); | ||
3471 | cx25840_write4(client, DIF_BPF_COEFF89, 0xfff000d7); | ||
3472 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f2ff82); | ||
3473 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01fee5); | ||
3474 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01f60362); | ||
3475 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb99); | ||
3476 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbcc0222); | ||
3477 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x07380370); | ||
3478 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9f7f6cc); | ||
3479 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xff990a7e); | ||
3480 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902fb50); | ||
3481 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21afa1f); | ||
3482 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0a8d0ea6); | ||
3483 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0034f0bf); | ||
3484 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4050675); | ||
3485 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3486 | break; | ||
3487 | |||
3488 | case 9500000: | ||
3489 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
3490 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fffe); | ||
3491 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001e002b); | ||
3492 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff81); | ||
3493 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffb400a5); | ||
3494 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x01280000); | ||
3495 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe24fe50); | ||
3496 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01460390); | ||
3497 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfc3a); | ||
3498 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb1000ce); | ||
3499 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x070104bf); | ||
3500 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb37f65f); | ||
3501 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe0009bc); | ||
3502 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a00fcbb); | ||
3503 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf235f8f8); | ||
3504 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x09b20efc); | ||
3505 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0105f101); | ||
3506 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf3ba0642); | ||
3507 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3508 | break; | ||
3509 | |||
3510 | case 9600000: | ||
3511 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff); | ||
3512 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff7); | ||
3513 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00150036); | ||
3514 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ff8c); | ||
3515 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff810061); | ||
3516 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013d007e); | ||
3517 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe71fddf); | ||
3518 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x007c0380); | ||
3519 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fd13); | ||
3520 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa94ff70); | ||
3521 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x068005e2); | ||
3522 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc9bf633); | ||
3523 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfc7308ca); | ||
3524 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad5fe30); | ||
3525 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf274f7e0); | ||
3526 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x08c90f43); | ||
3527 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x01d4f147); | ||
3528 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf371060f); | ||
3529 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3530 | break; | ||
3531 | |||
3532 | case 9700000: | ||
3533 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001); | ||
3534 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fff1); | ||
3535 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00090038); | ||
3536 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ffa7); | ||
3537 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff5e0012); | ||
3538 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013200f0); | ||
3539 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfee3fd9b); | ||
3540 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xffaa0331); | ||
3541 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fe15); | ||
3542 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa60fe18); | ||
3543 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x05bd06d1); | ||
3544 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe1bf64a); | ||
3545 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfafa07ae); | ||
3546 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7effab); | ||
3547 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2d5f6d7); | ||
3548 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x07d30f7a); | ||
3549 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x02a3f194); | ||
3550 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf32905dc); | ||
3551 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3552 | break; | ||
3553 | |||
3554 | case 9800000: | ||
3555 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002); | ||
3556 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcffee); | ||
3557 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfffb0032); | ||
3558 | cx25840_write4(client, DIF_BPF_COEFF67, 0x003fffcd); | ||
3559 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff4effc1); | ||
3560 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0106014a); | ||
3561 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff6efd8a); | ||
3562 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfedd02aa); | ||
3563 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0ff34); | ||
3564 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa74fcd7); | ||
3565 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x04bf0781); | ||
3566 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xffaaf6a3); | ||
3567 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf99e066b); | ||
3568 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf90128); | ||
3569 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf359f5e1); | ||
3570 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x06d20fa2); | ||
3571 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0370f1e5); | ||
3572 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2e405a8); | ||
3573 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3574 | break; | ||
3575 | |||
3576 | case 9900000: | ||
3577 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
3578 | cx25840_write4(client, DIF_BPF_COEFF23, 0xffffffee); | ||
3579 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffef0024); | ||
3580 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0051fffa); | ||
3581 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff54ff77); | ||
3582 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00be0184); | ||
3583 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0006fdad); | ||
3584 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe2701f3); | ||
3585 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413005e); | ||
3586 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfad1fbba); | ||
3587 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x039007ee); | ||
3588 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x013bf73d); | ||
3589 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf868050a); | ||
3590 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c4302a1); | ||
3591 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3fdf4fe); | ||
3592 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x05c70fba); | ||
3593 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x043bf23c); | ||
3594 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2a10575); | ||
3595 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3596 | break; | ||
3597 | |||
3598 | case 10000000: | ||
3599 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
3600 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0003fff1); | ||
3601 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe50011); | ||
3602 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00570027); | ||
3603 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff70ff3c); | ||
3604 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00620198); | ||
3605 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x009efe01); | ||
3606 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd95011a); | ||
3607 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x04350183); | ||
3608 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb71fad0); | ||
3609 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x023c0812); | ||
3610 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x02c3f811); | ||
3611 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf75e0390); | ||
3612 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5c0411); | ||
3613 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf4c1f432); | ||
3614 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x04b30fc1); | ||
3615 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0503f297); | ||
3616 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2610541); | ||
3617 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3618 | break; | ||
3619 | |||
3620 | case 10100000: | ||
3621 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
3622 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0006fff7); | ||
3623 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdffffc); | ||
3624 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00510050); | ||
3625 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff9dff18); | ||
3626 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfffc0184); | ||
3627 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0128fe80); | ||
3628 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd32002e); | ||
3629 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130292); | ||
3630 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc4dfa21); | ||
3631 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x00d107ee); | ||
3632 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0435f91c); | ||
3633 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6850205); | ||
3634 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c430573); | ||
3635 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf5a1f37d); | ||
3636 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x03990fba); | ||
3637 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x05c7f2f8); | ||
3638 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf222050d); | ||
3639 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3640 | break; | ||
3641 | |||
3642 | case 10200000: | ||
3643 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
3644 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffe); | ||
3645 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdfffe7); | ||
3646 | cx25840_write4(client, DIF_BPF_COEFF67, 0x003f006e); | ||
3647 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffd6ff0f); | ||
3648 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff96014a); | ||
3649 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0197ff1f); | ||
3650 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd05ff3e); | ||
3651 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0037c); | ||
3652 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd59f9b7); | ||
3653 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xff5d0781); | ||
3654 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0585fa56); | ||
3655 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5e4006f); | ||
3656 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf906c4); | ||
3657 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf69df2e0); | ||
3658 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x02790fa2); | ||
3659 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0688f35d); | ||
3660 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1e604d8); | ||
3661 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3662 | break; | ||
3663 | |||
3664 | case 10300000: | ||
3665 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001); | ||
3666 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00090005); | ||
3667 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe4ffd6); | ||
3668 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0025007e); | ||
3669 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0014ff20); | ||
3670 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff3c00f0); | ||
3671 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e1ffd0); | ||
3672 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd12fe5c); | ||
3673 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110433); | ||
3674 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe88f996); | ||
3675 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfdf106d1); | ||
3676 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x06aafbb7); | ||
3677 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf57efed8); | ||
3678 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e07ff); | ||
3679 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf7b0f25e); | ||
3680 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x01560f7a); | ||
3681 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0745f3c7); | ||
3682 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1ac04a4); | ||
3683 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3684 | break; | ||
3685 | |||
3686 | case 10400000: | ||
3687 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff); | ||
3688 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008000c); | ||
3689 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffedffcb); | ||
3690 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0005007d); | ||
3691 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0050ff4c); | ||
3692 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef6007e); | ||
3693 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01ff0086); | ||
3694 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd58fd97); | ||
3695 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x024104ad); | ||
3696 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xffcaf9c0); | ||
3697 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc9905e2); | ||
3698 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x079afd35); | ||
3699 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf555fd46); | ||
3700 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad50920); | ||
3701 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf8d9f1f6); | ||
3702 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x00310f43); | ||
3703 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x07fdf435); | ||
3704 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf174046f); | ||
3705 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3706 | break; | ||
3707 | |||
3708 | case 10500000: | ||
3709 | cx25840_write4(client, DIF_BPF_COEFF01, 0xfffffffe); | ||
3710 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00050011); | ||
3711 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfffaffc8); | ||
3712 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5006b); | ||
3713 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0082ff8c); | ||
3714 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecc0000); | ||
3715 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f00130); | ||
3716 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdd2fcfc); | ||
3717 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d04e3); | ||
3718 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x010efa32); | ||
3719 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb6404bf); | ||
3720 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x084efec5); | ||
3721 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf569fbc2); | ||
3722 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000a23); | ||
3723 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfa15f1ab); | ||
3724 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xff0b0efc); | ||
3725 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x08b0f4a7); | ||
3726 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf13f043a); | ||
3727 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3728 | break; | ||
3729 | |||
3730 | case 10600000: | ||
3731 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
3732 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00020012); | ||
3733 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0007ffcd); | ||
3734 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9004c); | ||
3735 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00a4ffd9); | ||
3736 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec3ff82); | ||
3737 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01b401c1); | ||
3738 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe76fc97); | ||
3739 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x004404d2); | ||
3740 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0245fae8); | ||
3741 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa5f0370); | ||
3742 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08c1005f); | ||
3743 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5bcfa52); | ||
3744 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x09020b04); | ||
3745 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfb60f17b); | ||
3746 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfde70ea6); | ||
3747 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x095df51e); | ||
3748 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf10c0405); | ||
3749 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3750 | break; | ||
3751 | |||
3752 | case 10700000: | ||
3753 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
3754 | cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0011); | ||
3755 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0014ffdb); | ||
3756 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffb40023); | ||
3757 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00b2002a); | ||
3758 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedbff10); | ||
3759 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0150022d); | ||
3760 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff38fc6f); | ||
3761 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36047b); | ||
3762 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x035efbda); | ||
3763 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9940202); | ||
3764 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08ee01f5); | ||
3765 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf649f8fe); | ||
3766 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e10bc2); | ||
3767 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfcb6f169); | ||
3768 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfcc60e42); | ||
3769 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0a04f599); | ||
3770 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0db03d0); | ||
3771 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3772 | break; | ||
3773 | |||
3774 | case 10800000: | ||
3775 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
3776 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffb000d); | ||
3777 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001dffed); | ||
3778 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffaafff5); | ||
3779 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00aa0077); | ||
3780 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff13feb6); | ||
3781 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00ce026b); | ||
3782 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x000afc85); | ||
3783 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3503e3); | ||
3784 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x044cfcfb); | ||
3785 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf90c0082); | ||
3786 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08d5037f); | ||
3787 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf710f7cc); | ||
3788 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0c59); | ||
3789 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfe16f173); | ||
3790 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfbaa0dcf); | ||
3791 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0aa5f617); | ||
3792 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0ad039b); | ||
3793 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3794 | break; | ||
3795 | |||
3796 | case 10900000: | ||
3797 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
3798 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff90006); | ||
3799 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00210003); | ||
3800 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffacffc8); | ||
3801 | cx25840_write4(client, DIF_BPF_COEFF89, 0x008e00b6); | ||
3802 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff63fe7c); | ||
3803 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x003a0275); | ||
3804 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x00dafcda); | ||
3805 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd510313); | ||
3806 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0501fe40); | ||
3807 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8cbfefd); | ||
3808 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x087604f0); | ||
3809 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf80af6c2); | ||
3810 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430cc8); | ||
3811 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xff7af19a); | ||
3812 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfa940d4e); | ||
3813 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0b3ff699); | ||
3814 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0810365); | ||
3815 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3816 | break; | ||
3817 | |||
3818 | case 11000000: | ||
3819 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff); | ||
3820 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8ffff); | ||
3821 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00210018); | ||
3822 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffa3); | ||
3823 | cx25840_write4(client, DIF_BPF_COEFF89, 0x006000e1); | ||
3824 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffc4fe68); | ||
3825 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffa0024b); | ||
3826 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x019afd66); | ||
3827 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc990216); | ||
3828 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0575ff99); | ||
3829 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8d4fd81); | ||
3830 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x07d40640); | ||
3831 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf932f5e6); | ||
3832 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20d0d); | ||
3833 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x00dff1de); | ||
3834 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf9860cbf); | ||
3835 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0bd1f71e); | ||
3836 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf058032f); | ||
3837 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3838 | break; | ||
3839 | |||
3840 | case 11100000: | ||
3841 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000); | ||
3842 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff8); | ||
3843 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001b0029); | ||
3844 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffd1ff8a); | ||
3845 | cx25840_write4(client, DIF_BPF_COEFF89, 0x002600f2); | ||
3846 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x002cfe7c); | ||
3847 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff0f01f0); | ||
3848 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x023bfe20); | ||
3849 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc1700fa); | ||
3850 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x05a200f7); | ||
3851 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf927fc1c); | ||
3852 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x06f40765); | ||
3853 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa82f53b); | ||
3854 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x02510d27); | ||
3855 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0243f23d); | ||
3856 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf8810c24); | ||
3857 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0c5cf7a7); | ||
3858 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf03102fa); | ||
3859 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3860 | break; | ||
3861 | |||
3862 | case 11200000: | ||
3863 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010002); | ||
3864 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff2); | ||
3865 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00110035); | ||
3866 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0ff81); | ||
3867 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffe700e7); | ||
3868 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x008ffeb6); | ||
3869 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe94016d); | ||
3870 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b0fefb); | ||
3871 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3ffd1); | ||
3872 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x05850249); | ||
3873 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9c1fadb); | ||
3874 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x05de0858); | ||
3875 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfbf2f4c4); | ||
3876 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c70d17); | ||
3877 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x03a0f2b8); | ||
3878 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf7870b7c); | ||
3879 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0cdff833); | ||
3880 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf00d02c4); | ||
3881 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3882 | break; | ||
3883 | |||
3884 | case 11300000: | ||
3885 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
3886 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffdffee); | ||
3887 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00040038); | ||
3888 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0010ff88); | ||
3889 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffac00c2); | ||
3890 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e2ff10); | ||
3891 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe3900cb); | ||
3892 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f1ffe9); | ||
3893 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3feaa); | ||
3894 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x05210381); | ||
3895 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa9cf9c8); | ||
3896 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x04990912); | ||
3897 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfd7af484); | ||
3898 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xff390cdb); | ||
3899 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x04f4f34d); | ||
3900 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf69a0ac9); | ||
3901 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0d5af8c1); | ||
3902 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xefec028e); | ||
3903 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3904 | break; | ||
3905 | |||
3906 | case 11400000: | ||
3907 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
3908 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0000ffee); | ||
3909 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff60033); | ||
3910 | cx25840_write4(client, DIF_BPF_COEFF67, 0x002fff9f); | ||
3911 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff7b0087); | ||
3912 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x011eff82); | ||
3913 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe080018); | ||
3914 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f900d8); | ||
3915 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17fd96); | ||
3916 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x04790490); | ||
3917 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbadf8ed); | ||
3918 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x032f098e); | ||
3919 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xff10f47d); | ||
3920 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaf0c75); | ||
3921 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x063cf3fc); | ||
3922 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf5ba0a0b); | ||
3923 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0dccf952); | ||
3924 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xefcd0258); | ||
3925 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3926 | break; | ||
3927 | |||
3928 | case 11500000: | ||
3929 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
3930 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0004fff1); | ||
3931 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffea0026); | ||
3932 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0046ffc3); | ||
3933 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff5a003c); | ||
3934 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013b0000); | ||
3935 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe04ff63); | ||
3936 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c801b8); | ||
3937 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fca6); | ||
3938 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0397056a); | ||
3939 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfcecf853); | ||
3940 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x01ad09c9); | ||
3941 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x00acf4ad); | ||
3942 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2e0be7); | ||
3943 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0773f4c2); | ||
3944 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4e90943); | ||
3945 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e35f9e6); | ||
3946 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xefb10221); | ||
3947 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3948 | break; | ||
3949 | |||
3950 | case 11600000: | ||
3951 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
3952 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0007fff6); | ||
3953 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe20014); | ||
3954 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0054ffee); | ||
3955 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff4effeb); | ||
3956 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0137007e); | ||
3957 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2efebb); | ||
3958 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0260027a); | ||
3959 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fbe6); | ||
3960 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x02870605); | ||
3961 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfe4af7fe); | ||
3962 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x001d09c1); | ||
3963 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0243f515); | ||
3964 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabd0b32); | ||
3965 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0897f59e); | ||
3966 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4280871); | ||
3967 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e95fa7c); | ||
3968 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef9701eb); | ||
3969 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3970 | break; | ||
3971 | |||
3972 | case 11700000: | ||
3973 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001); | ||
3974 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffd); | ||
3975 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdeffff); | ||
3976 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0056001d); | ||
3977 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff57ff9c); | ||
3978 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x011300f0); | ||
3979 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe82fe2e); | ||
3980 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01ca0310); | ||
3981 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fb62); | ||
3982 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0155065a); | ||
3983 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xffbaf7f2); | ||
3984 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe8c0977); | ||
3985 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x03cef5b2); | ||
3986 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf9610a58); | ||
3987 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x09a5f68f); | ||
3988 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf3790797); | ||
3989 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0eebfb14); | ||
3990 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef8001b5); | ||
3991 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
3992 | break; | ||
3993 | |||
3994 | case 11800000: | ||
3995 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000); | ||
3996 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00080004); | ||
3997 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe0ffe9); | ||
3998 | cx25840_write4(client, DIF_BPF_COEFF67, 0x004c0047); | ||
3999 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff75ff58); | ||
4000 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d1014a); | ||
4001 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfef9fdc8); | ||
4002 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0111036f); | ||
4003 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb21); | ||
4004 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x00120665); | ||
4005 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x012df82e); | ||
4006 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd0708ec); | ||
4007 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0542f682); | ||
4008 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81f095c); | ||
4009 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a9af792); | ||
4010 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2db06b5); | ||
4011 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f38fbad); | ||
4012 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef6c017e); | ||
4013 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4014 | break; | ||
4015 | |||
4016 | case 11900000: | ||
4017 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff); | ||
4018 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0007000b); | ||
4019 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe7ffd8); | ||
4020 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00370068); | ||
4021 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffa4ff28); | ||
4022 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00790184); | ||
4023 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff87fd91); | ||
4024 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x00430392); | ||
4025 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb26); | ||
4026 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfece0626); | ||
4027 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0294f8b2); | ||
4028 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb990825); | ||
4029 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0698f77f); | ||
4030 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fe0842); | ||
4031 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b73f8a7); | ||
4032 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf25105cd); | ||
4033 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f7bfc48); | ||
4034 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef5a0148); | ||
4035 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4036 | break; | ||
4037 | |||
4038 | case 12000000: | ||
4039 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
4040 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00050010); | ||
4041 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff2ffcc); | ||
4042 | cx25840_write4(client, DIF_BPF_COEFF67, 0x001b007b); | ||
4043 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffdfff10); | ||
4044 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00140198); | ||
4045 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0020fd8e); | ||
4046 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff710375); | ||
4047 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfb73); | ||
4048 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd9a059f); | ||
4049 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x03e0f978); | ||
4050 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfa4e0726); | ||
4051 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x07c8f8a7); | ||
4052 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600070c); | ||
4053 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c2ff9c9); | ||
4054 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1db04de); | ||
4055 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fb4fce5); | ||
4056 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef4b0111); | ||
4057 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4058 | break; | ||
4059 | |||
4060 | case 12100000: | ||
4061 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
4062 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00010012); | ||
4063 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffffffc8); | ||
4064 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfffb007e); | ||
4065 | cx25840_write4(client, DIF_BPF_COEFF89, 0x001dff14); | ||
4066 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffad0184); | ||
4067 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00b7fdbe); | ||
4068 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfea9031b); | ||
4069 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fc01); | ||
4070 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc8504d6); | ||
4071 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0504fa79); | ||
4072 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf93005f6); | ||
4073 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x08caf9f2); | ||
4074 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52b05c0); | ||
4075 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0ccbfaf9); | ||
4076 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf17903eb); | ||
4077 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fe3fd83); | ||
4078 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3f00db); | ||
4079 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4080 | break; | ||
4081 | |||
4082 | case 12200000: | ||
4083 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
4084 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffe0011); | ||
4085 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000cffcc); | ||
4086 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffdb0071); | ||
4087 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0058ff32); | ||
4088 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff4f014a); | ||
4089 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x013cfe1f); | ||
4090 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdfb028a); | ||
4091 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fcc9); | ||
4092 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb9d03d6); | ||
4093 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x05f4fbad); | ||
4094 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf848049d); | ||
4095 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0999fb5b); | ||
4096 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf4820461); | ||
4097 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d46fc32); | ||
4098 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf12d02f4); | ||
4099 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x1007fe21); | ||
4100 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3600a4); | ||
4101 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4102 | break; | ||
4103 | |||
4104 | case 12300000: | ||
4105 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
4106 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa000e); | ||
4107 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0017ffd9); | ||
4108 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc10055); | ||
4109 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0088ff68); | ||
4110 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff0400f0); | ||
4111 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01a6fea7); | ||
4112 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd7501cc); | ||
4113 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0fdc0); | ||
4114 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaef02a8); | ||
4115 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06a7fd07); | ||
4116 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf79d0326); | ||
4117 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a31fcda); | ||
4118 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf40702f3); | ||
4119 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d9ffd72); | ||
4120 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0f601fa); | ||
4121 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x1021fec0); | ||
4122 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2f006d); | ||
4123 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4124 | break; | ||
4125 | |||
4126 | case 12400000: | ||
4127 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff); | ||
4128 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80007); | ||
4129 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001fffeb); | ||
4130 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffaf002d); | ||
4131 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00a8ffb0); | ||
4132 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed3007e); | ||
4133 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e9ff4c); | ||
4134 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd2000ee); | ||
4135 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413fed8); | ||
4136 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa82015c); | ||
4137 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0715fe7d); | ||
4138 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7340198); | ||
4139 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a8dfe69); | ||
4140 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bd017c); | ||
4141 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dd5feb8); | ||
4142 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0d500fd); | ||
4143 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x1031ff60); | ||
4144 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2b0037); | ||
4145 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4146 | break; | ||
4147 | |||
4148 | case 12500000: | ||
4149 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000); | ||
4150 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff70000); | ||
4151 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00220000); | ||
4152 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffa90000); | ||
4153 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00b30000); | ||
4154 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec20000); | ||
4155 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x02000000); | ||
4156 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd030000); | ||
4157 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x04350000); | ||
4158 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa5e0000); | ||
4159 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x073b0000); | ||
4160 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7110000); | ||
4161 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0aac0000); | ||
4162 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3a40000); | ||
4163 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0de70000); | ||
4164 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0c90000); | ||
4165 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x10360000); | ||
4166 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef290000); | ||
4167 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4168 | break; | ||
4169 | |||
4170 | case 12600000: | ||
4171 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001); | ||
4172 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff8fff9); | ||
4173 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001f0015); | ||
4174 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffafffd3); | ||
4175 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00a80050); | ||
4176 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfed3ff82); | ||
4177 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e900b4); | ||
4178 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd20ff12); | ||
4179 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x04130128); | ||
4180 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa82fea4); | ||
4181 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x07150183); | ||
4182 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf734fe68); | ||
4183 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a8d0197); | ||
4184 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf3bdfe84); | ||
4185 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0dd50148); | ||
4186 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0d5ff03); | ||
4187 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x103100a0); | ||
4188 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2bffc9); | ||
4189 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4190 | break; | ||
4191 | |||
4192 | case 12700000: | ||
4193 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
4194 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffafff2); | ||
4195 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00170027); | ||
4196 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc1ffab); | ||
4197 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00880098); | ||
4198 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff04ff10); | ||
4199 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01a60159); | ||
4200 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd75fe34); | ||
4201 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b00240); | ||
4202 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfaeffd58); | ||
4203 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06a702f9); | ||
4204 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf79dfcda); | ||
4205 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0a310326); | ||
4206 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf407fd0d); | ||
4207 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d9f028e); | ||
4208 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf0f6fe06); | ||
4209 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x10210140); | ||
4210 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef2fff93); | ||
4211 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4212 | break; | ||
4213 | |||
4214 | case 12800000: | ||
4215 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
4216 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffeffef); | ||
4217 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000c0034); | ||
4218 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffdbff8f); | ||
4219 | cx25840_write4(client, DIF_BPF_COEFF89, 0x005800ce); | ||
4220 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff4ffeb6); | ||
4221 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x013c01e1); | ||
4222 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdfbfd76); | ||
4223 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03110337); | ||
4224 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb9dfc2a); | ||
4225 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x05f40453); | ||
4226 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf848fb63); | ||
4227 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x099904a5); | ||
4228 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf482fb9f); | ||
4229 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0d4603ce); | ||
4230 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf12dfd0c); | ||
4231 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x100701df); | ||
4232 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef36ff5c); | ||
4233 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4234 | break; | ||
4235 | |||
4236 | case 12900000: | ||
4237 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
4238 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0001ffee); | ||
4239 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffff0038); | ||
4240 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfffbff82); | ||
4241 | cx25840_write4(client, DIF_BPF_COEFF89, 0x001d00ec); | ||
4242 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffadfe7c); | ||
4243 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00b70242); | ||
4244 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfea9fce5); | ||
4245 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x024103ff); | ||
4246 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc85fb2a); | ||
4247 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x05040587); | ||
4248 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf930fa0a); | ||
4249 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x08ca060e); | ||
4250 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf52bfa40); | ||
4251 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0ccb0507); | ||
4252 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf179fc15); | ||
4253 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fe3027d); | ||
4254 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef3fff25); | ||
4255 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4256 | break; | ||
4257 | |||
4258 | case 13000000: | ||
4259 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
4260 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0005fff0); | ||
4261 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff20034); | ||
4262 | cx25840_write4(client, DIF_BPF_COEFF67, 0x001bff85); | ||
4263 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffdf00f0); | ||
4264 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0014fe68); | ||
4265 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00200272); | ||
4266 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff71fc8b); | ||
4267 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d048d); | ||
4268 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd9afa61); | ||
4269 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x03e00688); | ||
4270 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfa4ef8da); | ||
4271 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x07c80759); | ||
4272 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf600f8f4); | ||
4273 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0c2f0637); | ||
4274 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf1dbfb22); | ||
4275 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0fb4031b); | ||
4276 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef4bfeef); | ||
4277 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4278 | break; | ||
4279 | |||
4280 | case 13100000: | ||
4281 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001); | ||
4282 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0007fff5); | ||
4283 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe70028); | ||
4284 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0037ff98); | ||
4285 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffa400d8); | ||
4286 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0079fe7c); | ||
4287 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff87026f); | ||
4288 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0043fc6e); | ||
4289 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x004404da); | ||
4290 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfecef9da); | ||
4291 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0294074e); | ||
4292 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb99f7db); | ||
4293 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x06980881); | ||
4294 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf6fef7be); | ||
4295 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0b730759); | ||
4296 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf251fa33); | ||
4297 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f7b03b8); | ||
4298 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef5afeb8); | ||
4299 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4300 | break; | ||
4301 | |||
4302 | case 13200000: | ||
4303 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0000); | ||
4304 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fffc); | ||
4305 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe00017); | ||
4306 | cx25840_write4(client, DIF_BPF_COEFF67, 0x004cffb9); | ||
4307 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff7500a8); | ||
4308 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00d1feb6); | ||
4309 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfef90238); | ||
4310 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0111fc91); | ||
4311 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3604df); | ||
4312 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0012f99b); | ||
4313 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x012d07d2); | ||
4314 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfd07f714); | ||
4315 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0542097e); | ||
4316 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf81ff6a4); | ||
4317 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x0a9a086e); | ||
4318 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf2dbf94b); | ||
4319 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0f380453); | ||
4320 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef6cfe82); | ||
4321 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4322 | break; | ||
4323 | |||
4324 | case 13300000: | ||
4325 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff); | ||
4326 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00080003); | ||
4327 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffde0001); | ||
4328 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0056ffe3); | ||
4329 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff570064); | ||
4330 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0113ff10); | ||
4331 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe8201d2); | ||
4332 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01cafcf0); | ||
4333 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35049e); | ||
4334 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0155f9a6); | ||
4335 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xffba080e); | ||
4336 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe8cf689); | ||
4337 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x03ce0a4e); | ||
4338 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xf961f5a8); | ||
4339 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x09a50971); | ||
4340 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf379f869); | ||
4341 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0eeb04ec); | ||
4342 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef80fe4b); | ||
4343 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4344 | break; | ||
4345 | |||
4346 | case 13400000: | ||
4347 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
4348 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0007000a); | ||
4349 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe2ffec); | ||
4350 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00540012); | ||
4351 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff4e0015); | ||
4352 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0137ff82); | ||
4353 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2e0145); | ||
4354 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0260fd86); | ||
4355 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51041a); | ||
4356 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0287f9fb); | ||
4357 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfe4a0802); | ||
4358 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x001df63f); | ||
4359 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x02430aeb); | ||
4360 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfabdf4ce); | ||
4361 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x08970a62); | ||
4362 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf428f78f); | ||
4363 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e950584); | ||
4364 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xef97fe15); | ||
4365 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4366 | break; | ||
4367 | |||
4368 | case 13500000: | ||
4369 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
4370 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0004000f); | ||
4371 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffeaffda); | ||
4372 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0046003d); | ||
4373 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff5affc4); | ||
4374 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013b0000); | ||
4375 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe04009d); | ||
4376 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02c8fe48); | ||
4377 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99035a); | ||
4378 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0397fa96); | ||
4379 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfcec07ad); | ||
4380 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x01adf637); | ||
4381 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x00ac0b53); | ||
4382 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfc2ef419); | ||
4383 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x07730b3e); | ||
4384 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf4e9f6bd); | ||
4385 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0e35061a); | ||
4386 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xefb1fddf); | ||
4387 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4388 | break; | ||
4389 | |||
4390 | case 13600000: | ||
4391 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
4392 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00000012); | ||
4393 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfff6ffcd); | ||
4394 | cx25840_write4(client, DIF_BPF_COEFF67, 0x002f0061); | ||
4395 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff7bff79); | ||
4396 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x011e007e); | ||
4397 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe08ffe8); | ||
4398 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f9ff28); | ||
4399 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17026a); | ||
4400 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0479fb70); | ||
4401 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfbad0713); | ||
4402 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x032ff672); | ||
4403 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xff100b83); | ||
4404 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xfdaff38b); | ||
4405 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x063c0c04); | ||
4406 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf5baf5f5); | ||
4407 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0dcc06ae); | ||
4408 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xefcdfda8); | ||
4409 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4410 | break; | ||
4411 | |||
4412 | case 13700000: | ||
4413 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
4414 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffd0012); | ||
4415 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0004ffc8); | ||
4416 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00100078); | ||
4417 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffacff3e); | ||
4418 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00e200f0); | ||
4419 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe39ff35); | ||
4420 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02f10017); | ||
4421 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd30156); | ||
4422 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0521fc7f); | ||
4423 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa9c0638); | ||
4424 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0499f6ee); | ||
4425 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfd7a0b7c); | ||
4426 | cx25840_write4(client, DIF_BPF_COEFF2627, 0xff39f325); | ||
4427 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x04f40cb3); | ||
4428 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf69af537); | ||
4429 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0d5a073f); | ||
4430 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xefecfd72); | ||
4431 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4432 | break; | ||
4433 | |||
4434 | case 13800000: | ||
4435 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0001fffe); | ||
4436 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffa000e); | ||
4437 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0011ffcb); | ||
4438 | cx25840_write4(client, DIF_BPF_COEFF67, 0xfff0007f); | ||
4439 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffe7ff19); | ||
4440 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x008f014a); | ||
4441 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe94fe93); | ||
4442 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02b00105); | ||
4443 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfbd3002f); | ||
4444 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x0585fdb7); | ||
4445 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf9c10525); | ||
4446 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x05def7a8); | ||
4447 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfbf20b3c); | ||
4448 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x00c7f2e9); | ||
4449 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x03a00d48); | ||
4450 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf787f484); | ||
4451 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0cdf07cd); | ||
4452 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf00dfd3c); | ||
4453 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4454 | break; | ||
4455 | |||
4456 | case 13900000: | ||
4457 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010000); | ||
4458 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80008); | ||
4459 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001bffd7); | ||
4460 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffd10076); | ||
4461 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0026ff0e); | ||
4462 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x002c0184); | ||
4463 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff0ffe10); | ||
4464 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x023b01e0); | ||
4465 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc17ff06); | ||
4466 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x05a2ff09); | ||
4467 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf92703e4); | ||
4468 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x06f4f89b); | ||
4469 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfa820ac5); | ||
4470 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0251f2d9); | ||
4471 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x02430dc3); | ||
4472 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf881f3dc); | ||
4473 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0c5c0859); | ||
4474 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf031fd06); | ||
4475 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4476 | break; | ||
4477 | |||
4478 | case 14000000: | ||
4479 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001); | ||
4480 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80001); | ||
4481 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0021ffe8); | ||
4482 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffba005d); | ||
4483 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0060ff1f); | ||
4484 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffc40198); | ||
4485 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xffa0fdb5); | ||
4486 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x019a029a); | ||
4487 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99fdea); | ||
4488 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x05750067); | ||
4489 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8d4027f); | ||
4490 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x07d4f9c0); | ||
4491 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf9320a1a); | ||
4492 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d2f2f3); | ||
4493 | cx25840_write4(client, DIF_BPF_COEFF2829, 0x00df0e22); | ||
4494 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xf986f341); | ||
4495 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0bd108e2); | ||
4496 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf058fcd1); | ||
4497 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4498 | break; | ||
4499 | |||
4500 | case 14100000: | ||
4501 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
4502 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffa); | ||
4503 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0021fffd); | ||
4504 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffac0038); | ||
4505 | cx25840_write4(client, DIF_BPF_COEFF89, 0x008eff4a); | ||
4506 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff630184); | ||
4507 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x003afd8b); | ||
4508 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x00da0326); | ||
4509 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd51fced); | ||
4510 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x050101c0); | ||
4511 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf8cb0103); | ||
4512 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x0876fb10); | ||
4513 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf80a093e); | ||
4514 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0543f338); | ||
4515 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xff7a0e66); | ||
4516 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfa94f2b2); | ||
4517 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0b3f0967); | ||
4518 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf081fc9b); | ||
4519 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4520 | break; | ||
4521 | |||
4522 | case 14200000: | ||
4523 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
4524 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffbfff3); | ||
4525 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001d0013); | ||
4526 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffaa000b); | ||
4527 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00aaff89); | ||
4528 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff13014a); | ||
4529 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00cefd95); | ||
4530 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x000a037b); | ||
4531 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe35fc1d); | ||
4532 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x044c0305); | ||
4533 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf90cff7e); | ||
4534 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08d5fc81); | ||
4535 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf7100834); | ||
4536 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x069ff3a7); | ||
4537 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfe160e8d); | ||
4538 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfbaaf231); | ||
4539 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0aa509e9); | ||
4540 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0adfc65); | ||
4541 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4542 | break; | ||
4543 | |||
4544 | case 14300000: | ||
4545 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
4546 | cx25840_write4(client, DIF_BPF_COEFF23, 0xffffffef); | ||
4547 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00140025); | ||
4548 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffb4ffdd); | ||
4549 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00b2ffd6); | ||
4550 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfedb00f0); | ||
4551 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x0150fdd3); | ||
4552 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xff380391); | ||
4553 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff36fb85); | ||
4554 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x035e0426); | ||
4555 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xf994fdfe); | ||
4556 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08eefe0b); | ||
4557 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf6490702); | ||
4558 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1f43e); | ||
4559 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfcb60e97); | ||
4560 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfcc6f1be); | ||
4561 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x0a040a67); | ||
4562 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf0dbfc30); | ||
4563 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4564 | break; | ||
4565 | |||
4566 | case 14400000: | ||
4567 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
4568 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0002ffee); | ||
4569 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00070033); | ||
4570 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9ffb4); | ||
4571 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00a40027); | ||
4572 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfec3007e); | ||
4573 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01b4fe3f); | ||
4574 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe760369); | ||
4575 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0044fb2e); | ||
4576 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x02450518); | ||
4577 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfa5ffc90); | ||
4578 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x08c1ffa1); | ||
4579 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5bc05ae); | ||
4580 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0902f4fc); | ||
4581 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfb600e85); | ||
4582 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xfde7f15a); | ||
4583 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x095d0ae2); | ||
4584 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf10cfbfb); | ||
4585 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4586 | break; | ||
4587 | |||
4588 | case 14500000: | ||
4589 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0002); | ||
4590 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0005ffef); | ||
4591 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfffa0038); | ||
4592 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5ff95); | ||
4593 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00820074); | ||
4594 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfecc0000); | ||
4595 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01f0fed0); | ||
4596 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfdd20304); | ||
4597 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014dfb1d); | ||
4598 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x010e05ce); | ||
4599 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfb64fb41); | ||
4600 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x084e013b); | ||
4601 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf569043e); | ||
4602 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a00f5dd); | ||
4603 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xfa150e55); | ||
4604 | cx25840_write4(client, DIF_BPF_COEFF3031, 0xff0bf104); | ||
4605 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x08b00b59); | ||
4606 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf13ffbc6); | ||
4607 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4608 | break; | ||
4609 | |||
4610 | case 14600000: | ||
4611 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001); | ||
4612 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0008fff4); | ||
4613 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffed0035); | ||
4614 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0005ff83); | ||
4615 | cx25840_write4(client, DIF_BPF_COEFF89, 0x005000b4); | ||
4616 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfef6ff82); | ||
4617 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01ffff7a); | ||
4618 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd580269); | ||
4619 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0241fb53); | ||
4620 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xffca0640); | ||
4621 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfc99fa1e); | ||
4622 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x079a02cb); | ||
4623 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf55502ba); | ||
4624 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad5f6e0); | ||
4625 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf8d90e0a); | ||
4626 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0031f0bd); | ||
4627 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x07fd0bcb); | ||
4628 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf174fb91); | ||
4629 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4630 | break; | ||
4631 | |||
4632 | case 14700000: | ||
4633 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffffffff); | ||
4634 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0009fffb); | ||
4635 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe4002a); | ||
4636 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0025ff82); | ||
4637 | cx25840_write4(client, DIF_BPF_COEFF89, 0x001400e0); | ||
4638 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff3cff10); | ||
4639 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01e10030); | ||
4640 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd1201a4); | ||
4641 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0311fbcd); | ||
4642 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfe88066a); | ||
4643 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xfdf1f92f); | ||
4644 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x06aa0449); | ||
4645 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf57e0128); | ||
4646 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7ef801); | ||
4647 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf7b00da2); | ||
4648 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0156f086); | ||
4649 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x07450c39); | ||
4650 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1acfb5c); | ||
4651 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4652 | break; | ||
4653 | |||
4654 | case 14800000: | ||
4655 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffe); | ||
4656 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00080002); | ||
4657 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdf0019); | ||
4658 | cx25840_write4(client, DIF_BPF_COEFF67, 0x003fff92); | ||
4659 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffd600f1); | ||
4660 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff96feb6); | ||
4661 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x019700e1); | ||
4662 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd0500c2); | ||
4663 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b0fc84); | ||
4664 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfd590649); | ||
4665 | cx25840_write4(client, DIF_BPF_COEFF2021, 0xff5df87f); | ||
4666 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x058505aa); | ||
4667 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf5e4ff91); | ||
4668 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf9f93c); | ||
4669 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf69d0d20); | ||
4670 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0279f05e); | ||
4671 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x06880ca3); | ||
4672 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf1e6fb28); | ||
4673 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4674 | break; | ||
4675 | |||
4676 | case 14900000: | ||
4677 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
4678 | cx25840_write4(client, DIF_BPF_COEFF23, 0x00060009); | ||
4679 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffdf0004); | ||
4680 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0051ffb0); | ||
4681 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff9d00e8); | ||
4682 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xfffcfe7c); | ||
4683 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x01280180); | ||
4684 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd32ffd2); | ||
4685 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413fd6e); | ||
4686 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfc4d05df); | ||
4687 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x00d1f812); | ||
4688 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x043506e4); | ||
4689 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf685fdfb); | ||
4690 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c43fa8d); | ||
4691 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf5a10c83); | ||
4692 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0399f046); | ||
4693 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x05c70d08); | ||
4694 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf222faf3); | ||
4695 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4696 | break; | ||
4697 | |||
4698 | case 15000000: | ||
4699 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
4700 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0003000f); | ||
4701 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffe5ffef); | ||
4702 | cx25840_write4(client, DIF_BPF_COEFF67, 0x0057ffd9); | ||
4703 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff7000c4); | ||
4704 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0062fe68); | ||
4705 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x009e01ff); | ||
4706 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfd95fee6); | ||
4707 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0435fe7d); | ||
4708 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb710530); | ||
4709 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x023cf7ee); | ||
4710 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x02c307ef); | ||
4711 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf75efc70); | ||
4712 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c5cfbef); | ||
4713 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf4c10bce); | ||
4714 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x04b3f03f); | ||
4715 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x05030d69); | ||
4716 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf261fabf); | ||
4717 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4718 | break; | ||
4719 | |||
4720 | case 15100000: | ||
4721 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0000fffd); | ||
4722 | cx25840_write4(client, DIF_BPF_COEFF23, 0xffff0012); | ||
4723 | cx25840_write4(client, DIF_BPF_COEFF45, 0xffefffdc); | ||
4724 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00510006); | ||
4725 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff540089); | ||
4726 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00befe7c); | ||
4727 | cx25840_write4(client, DIF_BPF_COEFF1213, 0x00060253); | ||
4728 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfe27fe0d); | ||
4729 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x0413ffa2); | ||
4730 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfad10446); | ||
4731 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0390f812); | ||
4732 | cx25840_write4(client, DIF_BPF_COEFF2223, 0x013b08c3); | ||
4733 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf868faf6); | ||
4734 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0c43fd5f); | ||
4735 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3fd0b02); | ||
4736 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x05c7f046); | ||
4737 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x043b0dc4); | ||
4738 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2a1fa8b); | ||
4739 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4740 | break; | ||
4741 | |||
4742 | case 15200000: | ||
4743 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0001fffe); | ||
4744 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffc0012); | ||
4745 | cx25840_write4(client, DIF_BPF_COEFF45, 0xfffbffce); | ||
4746 | cx25840_write4(client, DIF_BPF_COEFF67, 0x003f0033); | ||
4747 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff4e003f); | ||
4748 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0106feb6); | ||
4749 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff6e0276); | ||
4750 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xfeddfd56); | ||
4751 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x03b000cc); | ||
4752 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa740329); | ||
4753 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x04bff87f); | ||
4754 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xffaa095d); | ||
4755 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xf99ef995); | ||
4756 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0bf9fed8); | ||
4757 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf3590a1f); | ||
4758 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x06d2f05e); | ||
4759 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x03700e1b); | ||
4760 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf2e4fa58); | ||
4761 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4762 | break; | ||
4763 | |||
4764 | case 15300000: | ||
4765 | cx25840_write4(client, DIF_BPF_COEFF01, 0x0001ffff); | ||
4766 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9000f); | ||
4767 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0009ffc8); | ||
4768 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00250059); | ||
4769 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff5effee); | ||
4770 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0132ff10); | ||
4771 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfee30265); | ||
4772 | cx25840_write4(client, DIF_BPF_COEFF1415, 0xffaafccf); | ||
4773 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x031101eb); | ||
4774 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa6001e8); | ||
4775 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x05bdf92f); | ||
4776 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfe1b09b6); | ||
4777 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfafaf852); | ||
4778 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0b7e0055); | ||
4779 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2d50929); | ||
4780 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x07d3f086); | ||
4781 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x02a30e6c); | ||
4782 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf329fa24); | ||
4783 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4784 | break; | ||
4785 | |||
4786 | case 15400000: | ||
4787 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00010001); | ||
4788 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80009); | ||
4789 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0015ffca); | ||
4790 | cx25840_write4(client, DIF_BPF_COEFF67, 0x00050074); | ||
4791 | cx25840_write4(client, DIF_BPF_COEFF89, 0xff81ff9f); | ||
4792 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x013dff82); | ||
4793 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe710221); | ||
4794 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x007cfc80); | ||
4795 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x024102ed); | ||
4796 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfa940090); | ||
4797 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0680fa1e); | ||
4798 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfc9b09cd); | ||
4799 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfc73f736); | ||
4800 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0ad501d0); | ||
4801 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2740820); | ||
4802 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x08c9f0bd); | ||
4803 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x01d40eb9); | ||
4804 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf371f9f1); | ||
4805 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4806 | break; | ||
4807 | |||
4808 | case 15500000: | ||
4809 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000002); | ||
4810 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff80002); | ||
4811 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001effd5); | ||
4812 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffe5007f); | ||
4813 | cx25840_write4(client, DIF_BPF_COEFF89, 0xffb4ff5b); | ||
4814 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x01280000); | ||
4815 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe2401b0); | ||
4816 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0146fc70); | ||
4817 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x014d03c6); | ||
4818 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfb10ff32); | ||
4819 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0701fb41); | ||
4820 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xfb3709a1); | ||
4821 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xfe00f644); | ||
4822 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x0a000345); | ||
4823 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2350708); | ||
4824 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x09b2f104); | ||
4825 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x01050eff); | ||
4826 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf3baf9be); | ||
4827 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4828 | break; | ||
4829 | |||
4830 | case 15600000: | ||
4831 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
4832 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfff9fffb); | ||
4833 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0022ffe6); | ||
4834 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffc9007a); | ||
4835 | cx25840_write4(client, DIF_BPF_COEFF89, 0xfff0ff29); | ||
4836 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00f2007e); | ||
4837 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe01011b); | ||
4838 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x01f6fc9e); | ||
4839 | cx25840_write4(client, DIF_BPF_COEFF1617, 0x00440467); | ||
4840 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfbccfdde); | ||
4841 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0738fc90); | ||
4842 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf9f70934); | ||
4843 | cx25840_write4(client, DIF_BPF_COEFF2425, 0xff99f582); | ||
4844 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x090204b0); | ||
4845 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf21a05e1); | ||
4846 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0a8df15a); | ||
4847 | cx25840_write4(client, DIF_BPF_COEFF3233, 0x00340f41); | ||
4848 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf405f98b); | ||
4849 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4850 | break; | ||
4851 | |||
4852 | case 15700000: | ||
4853 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
4854 | cx25840_write4(client, DIF_BPF_COEFF23, 0xfffcfff4); | ||
4855 | cx25840_write4(client, DIF_BPF_COEFF45, 0x0020fffa); | ||
4856 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffb40064); | ||
4857 | cx25840_write4(client, DIF_BPF_COEFF89, 0x002fff11); | ||
4858 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x00a400f0); | ||
4859 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe0d006e); | ||
4860 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x0281fd09); | ||
4861 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xff3604c9); | ||
4862 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfcbffca2); | ||
4863 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0726fdfe); | ||
4864 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf8e80888); | ||
4865 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x0134f4f3); | ||
4866 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x07e1060c); | ||
4867 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf22304af); | ||
4868 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0b59f1be); | ||
4869 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xff640f7d); | ||
4870 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf452f959); | ||
4871 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4872 | break; | ||
4873 | |||
4874 | case 15800000: | ||
4875 | cx25840_write4(client, DIF_BPF_COEFF01, 0x00000003); | ||
4876 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0000fff0); | ||
4877 | cx25840_write4(client, DIF_BPF_COEFF45, 0x001a0010); | ||
4878 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffaa0041); | ||
4879 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0067ff13); | ||
4880 | cx25840_write4(client, DIF_BPF_COEFF1011, 0x0043014a); | ||
4881 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfe46ffb9); | ||
4882 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02dbfda8); | ||
4883 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfe3504e5); | ||
4884 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xfddcfb8d); | ||
4885 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06c9ff7e); | ||
4886 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf81107a2); | ||
4887 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x02c9f49a); | ||
4888 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x069f0753); | ||
4889 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2500373); | ||
4890 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0c14f231); | ||
4891 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfe930fb3); | ||
4892 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4a1f927); | ||
4893 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4894 | break; | ||
4895 | |||
4896 | case 15900000: | ||
4897 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0002); | ||
4898 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0003ffee); | ||
4899 | cx25840_write4(client, DIF_BPF_COEFF45, 0x000f0023); | ||
4900 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffac0016); | ||
4901 | cx25840_write4(client, DIF_BPF_COEFF89, 0x0093ff31); | ||
4902 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xffdc0184); | ||
4903 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xfea6ff09); | ||
4904 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02fdfe70); | ||
4905 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfd5104ba); | ||
4906 | cx25840_write4(client, DIF_BPF_COEFF1819, 0xff15faac); | ||
4907 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x06270103); | ||
4908 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7780688); | ||
4909 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x044df479); | ||
4910 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x05430883); | ||
4911 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf2a00231); | ||
4912 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0cbef2b2); | ||
4913 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfdc40fe3); | ||
4914 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf4f2f8f5); | ||
4915 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4916 | break; | ||
4917 | |||
4918 | case 16000000: | ||
4919 | cx25840_write4(client, DIF_BPF_COEFF01, 0xffff0001); | ||
4920 | cx25840_write4(client, DIF_BPF_COEFF23, 0x0006ffef); | ||
4921 | cx25840_write4(client, DIF_BPF_COEFF45, 0x00020031); | ||
4922 | cx25840_write4(client, DIF_BPF_COEFF67, 0xffbaffe8); | ||
4923 | cx25840_write4(client, DIF_BPF_COEFF89, 0x00adff66); | ||
4924 | cx25840_write4(client, DIF_BPF_COEFF1011, 0xff790198); | ||
4925 | cx25840_write4(client, DIF_BPF_COEFF1213, 0xff26fe6e); | ||
4926 | cx25840_write4(client, DIF_BPF_COEFF1415, 0x02e5ff55); | ||
4927 | cx25840_write4(client, DIF_BPF_COEFF1617, 0xfc99044a); | ||
4928 | cx25840_write4(client, DIF_BPF_COEFF1819, 0x005bfa09); | ||
4929 | cx25840_write4(client, DIF_BPF_COEFF2021, 0x0545027f); | ||
4930 | cx25840_write4(client, DIF_BPF_COEFF2223, 0xf7230541); | ||
4931 | cx25840_write4(client, DIF_BPF_COEFF2425, 0x05b8f490); | ||
4932 | cx25840_write4(client, DIF_BPF_COEFF2627, 0x03d20997); | ||
4933 | cx25840_write4(client, DIF_BPF_COEFF2829, 0xf31300eb); | ||
4934 | cx25840_write4(client, DIF_BPF_COEFF3031, 0x0d55f341); | ||
4935 | cx25840_write4(client, DIF_BPF_COEFF3233, 0xfcf6100e); | ||
4936 | cx25840_write4(client, DIF_BPF_COEFF3435, 0xf544f8c3); | ||
4937 | cx25840_write4(client, DIF_BPF_COEFF36, 0x110d0000); | ||
4938 | break; | ||
4939 | } | ||
4940 | } | ||
4941 | |||
4942 | static void cx23885_std_setup(struct i2c_client *client) | ||
4943 | { | ||
4944 | struct cx25840_state *state = to_state(i2c_get_clientdata(client)); | ||
4945 | v4l2_std_id std = state->std; | ||
4946 | u32 ifHz; | ||
4947 | |||
4948 | cx25840_write4(client, 0x478, 0x6628021F); | ||
4949 | cx25840_write4(client, 0x400, 0x0); | ||
4950 | cx25840_write4(client, 0x4b4, 0x20524030); | ||
4951 | cx25840_write4(client, 0x47c, 0x010a8263); | ||
4952 | |||
4953 | if (std & V4L2_STD_NTSC) { | ||
4954 | v4l_dbg(1, cx25840_debug, client, "%s() Selecting NTSC", | ||
4955 | __func__); | ||
4956 | |||
4957 | /* Horiz / vert timing */ | ||
4958 | cx25840_write4(client, 0x428, 0x1e1e601a); | ||
4959 | cx25840_write4(client, 0x424, 0x5b2d007a); | ||
4960 | |||
4961 | /* DIF NTSC */ | ||
4962 | cx25840_write4(client, 0x304, 0x6503bc0c); | ||
4963 | cx25840_write4(client, 0x308, 0xbd038c85); | ||
4964 | cx25840_write4(client, 0x30c, 0x1db4640a); | ||
4965 | cx25840_write4(client, 0x310, 0x00008800); | ||
4966 | cx25840_write4(client, 0x314, 0x44400400); | ||
4967 | cx25840_write4(client, 0x32c, 0x0c800800); | ||
4968 | cx25840_write4(client, 0x330, 0x27000100); | ||
4969 | cx25840_write4(client, 0x334, 0x1f296e1f); | ||
4970 | cx25840_write4(client, 0x338, 0x009f50c1); | ||
4971 | cx25840_write4(client, 0x340, 0x1befbf06); | ||
4972 | cx25840_write4(client, 0x344, 0x000035e8); | ||
4973 | |||
4974 | /* DIF I/F */ | ||
4975 | ifHz = 5400000; | ||
4976 | |||
4977 | } else { | ||
4978 | v4l_dbg(1, cx25840_debug, client, "%s() Selecting PAL-BG", | ||
4979 | __func__); | ||
4980 | |||
4981 | /* Horiz / vert timing */ | ||
4982 | cx25840_write4(client, 0x428, 0x28244024); | ||
4983 | cx25840_write4(client, 0x424, 0x5d2d0084); | ||
4984 | |||
4985 | /* DIF */ | ||
4986 | cx25840_write4(client, 0x304, 0x6503bc0c); | ||
4987 | cx25840_write4(client, 0x308, 0xbd038c85); | ||
4988 | cx25840_write4(client, 0x30c, 0x1db4640a); | ||
4989 | cx25840_write4(client, 0x310, 0x00008800); | ||
4990 | cx25840_write4(client, 0x314, 0x44400600); | ||
4991 | cx25840_write4(client, 0x32c, 0x0c800800); | ||
4992 | cx25840_write4(client, 0x330, 0x27000100); | ||
4993 | cx25840_write4(client, 0x334, 0x213530ec); | ||
4994 | cx25840_write4(client, 0x338, 0x00a65ba8); | ||
4995 | cx25840_write4(client, 0x340, 0x1befbf06); | ||
4996 | cx25840_write4(client, 0x344, 0x000035e8); | ||
4997 | |||
4998 | /* DIF I/F */ | ||
4999 | ifHz = 6000000; | ||
5000 | } | ||
5001 | |||
5002 | cx23885_dif_setup(client, ifHz); | ||
5003 | |||
5004 | /* Explicitly ensure the inputs are reconfigured after | ||
5005 | * a standard change. | ||
5006 | */ | ||
5007 | set_input(client, state->vid_input, state->aud_input); | ||
5008 | } | ||
5009 | |||
5010 | /* ----------------------------------------------------------------------- */ | ||
5011 | |||
1789 | static const struct v4l2_ctrl_ops cx25840_ctrl_ops = { | 5012 | static const struct v4l2_ctrl_ops cx25840_ctrl_ops = { |
1790 | .s_ctrl = cx25840_s_ctrl, | 5013 | .s_ctrl = cx25840_s_ctrl, |
1791 | }; | 5014 | }; |
@@ -1801,6 +5024,7 @@ static const struct v4l2_subdev_core_ops cx25840_core_ops = { | |||
1801 | .queryctrl = v4l2_subdev_queryctrl, | 5024 | .queryctrl = v4l2_subdev_queryctrl, |
1802 | .querymenu = v4l2_subdev_querymenu, | 5025 | .querymenu = v4l2_subdev_querymenu, |
1803 | .s_std = cx25840_s_std, | 5026 | .s_std = cx25840_s_std, |
5027 | .g_std = cx25840_g_std, | ||
1804 | .reset = cx25840_reset, | 5028 | .reset = cx25840_reset, |
1805 | .load_fw = cx25840_load_fw, | 5029 | .load_fw = cx25840_load_fw, |
1806 | .s_io_pin_config = common_s_io_pin_config, | 5030 | .s_io_pin_config = common_s_io_pin_config, |
@@ -1828,6 +5052,7 @@ static const struct v4l2_subdev_video_ops cx25840_video_ops = { | |||
1828 | .s_routing = cx25840_s_video_routing, | 5052 | .s_routing = cx25840_s_video_routing, |
1829 | .s_mbus_fmt = cx25840_s_mbus_fmt, | 5053 | .s_mbus_fmt = cx25840_s_mbus_fmt, |
1830 | .s_stream = cx25840_s_stream, | 5054 | .s_stream = cx25840_s_stream, |
5055 | .g_input_status = cx25840_g_input_status, | ||
1831 | }; | 5056 | }; |
1832 | 5057 | ||
1833 | static const struct v4l2_subdev_vbi_ops cx25840_vbi_ops = { | 5058 | static const struct v4l2_subdev_vbi_ops cx25840_vbi_ops = { |
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 5c42abdf422f..3598dc087b08 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig | |||
@@ -70,11 +70,6 @@ config VIDEO_CX88_DVB | |||
70 | To compile this driver as a module, choose M here: the | 70 | To compile this driver as a module, choose M here: the |
71 | module will be called cx88-dvb. | 71 | module will be called cx88-dvb. |
72 | 72 | ||
73 | config VIDEO_CX88_MPEG | ||
74 | tristate | ||
75 | depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD | ||
76 | default y | ||
77 | |||
78 | config VIDEO_CX88_VP3054 | 73 | config VIDEO_CX88_VP3054 |
79 | tristate "VP-3054 Secondary I2C Bus Support" | 74 | tristate "VP-3054 Secondary I2C Bus Support" |
80 | default m | 75 | default m |
@@ -84,3 +79,8 @@ config VIDEO_CX88_VP3054 | |||
84 | Conexant 2388x chip and the MT352 demodulator, | 79 | Conexant 2388x chip and the MT352 demodulator, |
85 | which also require support for the VP-3054 | 80 | which also require support for the VP-3054 |
86 | Secondary I2C bus, such at DNTV Live! DVB-T Pro. | 81 | Secondary I2C bus, such at DNTV Live! DVB-T Pro. |
82 | |||
83 | config VIDEO_CX88_MPEG | ||
84 | tristate | ||
85 | depends on VIDEO_CX88_DVB || VIDEO_CX88_BLACKBIRD | ||
86 | default y | ||
diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 0d719faafd8a..62c7ad050f9b 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c | |||
@@ -1306,7 +1306,7 @@ static const struct cx88_board cx88_boards[] = { | |||
1306 | }, | 1306 | }, |
1307 | [CX88_BOARD_WINFAST_DTV2000H_J] = { | 1307 | [CX88_BOARD_WINFAST_DTV2000H_J] = { |
1308 | .name = "WinFast DTV2000 H rev. J", | 1308 | .name = "WinFast DTV2000 H rev. J", |
1309 | .tuner_type = TUNER_PHILIPS_FMD1216ME_MK3, | 1309 | .tuner_type = TUNER_PHILIPS_FMD1216MEX_MK3, |
1310 | .radio_type = UNSET, | 1310 | .radio_type = UNSET, |
1311 | .tuner_addr = ADDR_UNSET, | 1311 | .tuner_addr = ADDR_UNSET, |
1312 | .radio_addr = ADDR_UNSET, | 1312 | .radio_addr = ADDR_UNSET, |
@@ -1643,6 +1643,78 @@ static const struct cx88_board cx88_boards[] = { | |||
1643 | .gpio3 = 0x0000, | 1643 | .gpio3 = 0x0000, |
1644 | }, | 1644 | }, |
1645 | }, | 1645 | }, |
1646 | [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36] = { | ||
1647 | .name = "Leadtek TV2000 XP Global (SC4100)", | ||
1648 | .tuner_type = TUNER_XC4000, | ||
1649 | .tuner_addr = 0x61, | ||
1650 | .radio_type = UNSET, | ||
1651 | .radio_addr = ADDR_UNSET, | ||
1652 | .input = { { | ||
1653 | .type = CX88_VMUX_TELEVISION, | ||
1654 | .vmux = 0, | ||
1655 | .gpio0 = 0x0400, /* pin 2 = 0 */ | ||
1656 | .gpio1 = 0x0000, | ||
1657 | .gpio2 = 0x0C04, /* pin 18 = 1, pin 19 = 0 */ | ||
1658 | .gpio3 = 0x0000, | ||
1659 | }, { | ||
1660 | .type = CX88_VMUX_COMPOSITE1, | ||
1661 | .vmux = 1, | ||
1662 | .gpio0 = 0x0400, /* pin 2 = 0 */ | ||
1663 | .gpio1 = 0x0000, | ||
1664 | .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */ | ||
1665 | .gpio3 = 0x0000, | ||
1666 | }, { | ||
1667 | .type = CX88_VMUX_SVIDEO, | ||
1668 | .vmux = 2, | ||
1669 | .gpio0 = 0x0400, /* pin 2 = 0 */ | ||
1670 | .gpio1 = 0x0000, | ||
1671 | .gpio2 = 0x0C0C, /* pin 18 = 1, pin 19 = 1 */ | ||
1672 | .gpio3 = 0x0000, | ||
1673 | } }, | ||
1674 | .radio = { | ||
1675 | .type = CX88_RADIO, | ||
1676 | .gpio0 = 0x0400, /* pin 2 = 0 */ | ||
1677 | .gpio1 = 0x0000, | ||
1678 | .gpio2 = 0x0C00, /* pin 18 = 0, pin 19 = 0 */ | ||
1679 | .gpio3 = 0x0000, | ||
1680 | }, | ||
1681 | }, | ||
1682 | [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43] = { | ||
1683 | .name = "Leadtek TV2000 XP Global (XC4100)", | ||
1684 | .tuner_type = TUNER_XC4000, | ||
1685 | .tuner_addr = 0x61, | ||
1686 | .radio_type = UNSET, | ||
1687 | .radio_addr = ADDR_UNSET, | ||
1688 | .input = { { | ||
1689 | .type = CX88_VMUX_TELEVISION, | ||
1690 | .vmux = 0, | ||
1691 | .gpio0 = 0x0400, /* pin 2 = 0 */ | ||
1692 | .gpio1 = 0x6040, /* pin 14 = 1, pin 13 = 0 */ | ||
1693 | .gpio2 = 0x0000, | ||
1694 | .gpio3 = 0x0000, | ||
1695 | }, { | ||
1696 | .type = CX88_VMUX_COMPOSITE1, | ||
1697 | .vmux = 1, | ||
1698 | .gpio0 = 0x0400, /* pin 2 = 0 */ | ||
1699 | .gpio1 = 0x6060, /* pin 14 = 1, pin 13 = 1 */ | ||
1700 | .gpio2 = 0x0000, | ||
1701 | .gpio3 = 0x0000, | ||
1702 | }, { | ||
1703 | .type = CX88_VMUX_SVIDEO, | ||
1704 | .vmux = 2, | ||
1705 | .gpio0 = 0x0400, /* pin 2 = 0 */ | ||
1706 | .gpio1 = 0x6060, /* pin 14 = 1, pin 13 = 1 */ | ||
1707 | .gpio2 = 0x0000, | ||
1708 | .gpio3 = 0x0000, | ||
1709 | } }, | ||
1710 | .radio = { | ||
1711 | .type = CX88_RADIO, | ||
1712 | .gpio0 = 0x0400, /* pin 2 = 0 */ | ||
1713 | .gpio1 = 0x6000, /* pin 14 = 1, pin 13 = 0 */ | ||
1714 | .gpio2 = 0x0000, | ||
1715 | .gpio3 = 0x0000, | ||
1716 | }, | ||
1717 | }, | ||
1646 | [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { | 1718 | [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { |
1647 | .name = "PowerColor RA330", /* Long names may confuse LIRC. */ | 1719 | .name = "PowerColor RA330", /* Long names may confuse LIRC. */ |
1648 | .tuner_type = TUNER_XC2028, | 1720 | .tuner_type = TUNER_XC2028, |
@@ -2719,6 +2791,21 @@ static const struct cx88_subid cx88_subids[] = { | |||
2719 | .subdevice = 0x6618, | 2791 | .subdevice = 0x6618, |
2720 | .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, | 2792 | .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, |
2721 | }, { | 2793 | }, { |
2794 | /* TV2000 XP Global [107d:6618] */ | ||
2795 | .subvendor = 0x107d, | ||
2796 | .subdevice = 0x6619, | ||
2797 | .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, | ||
2798 | }, { | ||
2799 | /* WinFast TV2000 XP Global with XC4000 tuner */ | ||
2800 | .subvendor = 0x107d, | ||
2801 | .subdevice = 0x6f36, | ||
2802 | .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36, | ||
2803 | }, { | ||
2804 | /* WinFast TV2000 XP Global with XC4000 tuner and different GPIOs */ | ||
2805 | .subvendor = 0x107d, | ||
2806 | .subdevice = 0x6f43, | ||
2807 | .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43, | ||
2808 | }, { | ||
2722 | .subvendor = 0xb034, | 2809 | .subvendor = 0xb034, |
2723 | .subdevice = 0x3034, | 2810 | .subdevice = 0x3034, |
2724 | .card = CX88_BOARD_PROF_7301, | 2811 | .card = CX88_BOARD_PROF_7301, |
@@ -3075,6 +3162,8 @@ static int cx88_xc4000_tuner_callback(struct cx88_core *core, | |||
3075 | switch (core->boardnr) { | 3162 | switch (core->boardnr) { |
3076 | case CX88_BOARD_WINFAST_DTV1800H_XC4000: | 3163 | case CX88_BOARD_WINFAST_DTV1800H_XC4000: |
3077 | case CX88_BOARD_WINFAST_DTV2000H_PLUS: | 3164 | case CX88_BOARD_WINFAST_DTV2000H_PLUS: |
3165 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36: | ||
3166 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43: | ||
3078 | return cx88_xc4000_winfast2000h_plus_callback(core, | 3167 | return cx88_xc4000_winfast2000h_plus_callback(core, |
3079 | command, arg); | 3168 | command, arg); |
3080 | } | 3169 | } |
@@ -3232,6 +3321,7 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) | |||
3232 | cx_set(MO_GP0_IO, 0x00001010); | 3321 | cx_set(MO_GP0_IO, 0x00001010); |
3233 | break; | 3322 | break; |
3234 | 3323 | ||
3324 | case CX88_BOARD_WINFAST_DTV2000H_J: | ||
3235 | case CX88_BOARD_HAUPPAUGE_HVR3000: | 3325 | case CX88_BOARD_HAUPPAUGE_HVR3000: |
3236 | case CX88_BOARD_HAUPPAUGE_HVR4000: | 3326 | case CX88_BOARD_HAUPPAUGE_HVR4000: |
3237 | /* Init GPIO */ | 3327 | /* Init GPIO */ |
@@ -3250,6 +3340,8 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) | |||
3250 | 3340 | ||
3251 | case CX88_BOARD_WINFAST_DTV1800H_XC4000: | 3341 | case CX88_BOARD_WINFAST_DTV1800H_XC4000: |
3252 | case CX88_BOARD_WINFAST_DTV2000H_PLUS: | 3342 | case CX88_BOARD_WINFAST_DTV2000H_PLUS: |
3343 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36: | ||
3344 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43: | ||
3253 | cx88_xc4000_winfast2000h_plus_callback(core, | 3345 | cx88_xc4000_winfast2000h_plus_callback(core, |
3254 | XC4000_TUNER_RESET, 0); | 3346 | XC4000_TUNER_RESET, 0); |
3255 | break; | 3347 | break; |
diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index cf3d33ab541b..003937cd72f5 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c | |||
@@ -815,9 +815,9 @@ static const u8 samsung_smt_7020_inittab[] = { | |||
815 | }; | 815 | }; |
816 | 816 | ||
817 | 817 | ||
818 | static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe, | 818 | static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe) |
819 | struct dvb_frontend_parameters *params) | ||
820 | { | 819 | { |
820 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
821 | struct cx8802_dev *dev = fe->dvb->priv; | 821 | struct cx8802_dev *dev = fe->dvb->priv; |
822 | u8 buf[4]; | 822 | u8 buf[4]; |
823 | u32 div; | 823 | u32 div; |
@@ -827,14 +827,14 @@ static int samsung_smt_7020_tuner_set_params(struct dvb_frontend *fe, | |||
827 | .buf = buf, | 827 | .buf = buf, |
828 | .len = sizeof(buf) }; | 828 | .len = sizeof(buf) }; |
829 | 829 | ||
830 | div = params->frequency / 125; | 830 | div = c->frequency / 125; |
831 | 831 | ||
832 | buf[0] = (div >> 8) & 0x7f; | 832 | buf[0] = (div >> 8) & 0x7f; |
833 | buf[1] = div & 0xff; | 833 | buf[1] = div & 0xff; |
834 | buf[2] = 0x84; /* 0xC4 */ | 834 | buf[2] = 0x84; /* 0xC4 */ |
835 | buf[3] = 0x00; | 835 | buf[3] = 0x00; |
836 | 836 | ||
837 | if (params->frequency < 1500000) | 837 | if (c->frequency < 1500000) |
838 | buf[3] |= 0x10; | 838 | buf[3] |= 0x10; |
839 | 839 | ||
840 | if (fe->ops.i2c_gate_ctrl) | 840 | if (fe->ops.i2c_gate_ctrl) |
@@ -954,6 +954,7 @@ static int dvb_register(struct cx8802_dev *dev) | |||
954 | struct cx88_core *core = dev->core; | 954 | struct cx88_core *core = dev->core; |
955 | struct videobuf_dvb_frontend *fe0, *fe1 = NULL; | 955 | struct videobuf_dvb_frontend *fe0, *fe1 = NULL; |
956 | int mfe_shared = 0; /* bus not shared by default */ | 956 | int mfe_shared = 0; /* bus not shared by default */ |
957 | int res = -EINVAL; | ||
957 | 958 | ||
958 | if (0 != core->i2c_rc) { | 959 | if (0 != core->i2c_rc) { |
959 | printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name); | 960 | printk(KERN_ERR "%s/2: no i2c-bus available, cannot attach dvb drivers\n", core->name); |
@@ -999,7 +1000,6 @@ static int dvb_register(struct cx8802_dev *dev) | |||
999 | } | 1000 | } |
1000 | break; | 1001 | break; |
1001 | case CX88_BOARD_WINFAST_DTV2000H: | 1002 | case CX88_BOARD_WINFAST_DTV2000H: |
1002 | case CX88_BOARD_WINFAST_DTV2000H_J: | ||
1003 | case CX88_BOARD_HAUPPAUGE_HVR1100: | 1003 | case CX88_BOARD_HAUPPAUGE_HVR1100: |
1004 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: | 1004 | case CX88_BOARD_HAUPPAUGE_HVR1100LP: |
1005 | case CX88_BOARD_HAUPPAUGE_HVR1300: | 1005 | case CX88_BOARD_HAUPPAUGE_HVR1300: |
@@ -1013,6 +1013,17 @@ static int dvb_register(struct cx8802_dev *dev) | |||
1013 | goto frontend_detach; | 1013 | goto frontend_detach; |
1014 | } | 1014 | } |
1015 | break; | 1015 | break; |
1016 | case CX88_BOARD_WINFAST_DTV2000H_J: | ||
1017 | fe0->dvb.frontend = dvb_attach(cx22702_attach, | ||
1018 | &hauppauge_hvr_config, | ||
1019 | &core->i2c_adap); | ||
1020 | if (fe0->dvb.frontend != NULL) { | ||
1021 | if (!dvb_attach(simple_tuner_attach, fe0->dvb.frontend, | ||
1022 | &core->i2c_adap, 0x61, | ||
1023 | TUNER_PHILIPS_FMD1216MEX_MK3)) | ||
1024 | goto frontend_detach; | ||
1025 | } | ||
1026 | break; | ||
1016 | case CX88_BOARD_HAUPPAUGE_HVR3000: | 1027 | case CX88_BOARD_HAUPPAUGE_HVR3000: |
1017 | /* MFE frontend 1 */ | 1028 | /* MFE frontend 1 */ |
1018 | mfe_shared = 1; | 1029 | mfe_shared = 1; |
@@ -1566,13 +1577,16 @@ static int dvb_register(struct cx8802_dev *dev) | |||
1566 | call_all(core, core, s_power, 0); | 1577 | call_all(core, core, s_power, 0); |
1567 | 1578 | ||
1568 | /* register everything */ | 1579 | /* register everything */ |
1569 | return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, | 1580 | res = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev, |
1570 | &dev->pci->dev, adapter_nr, mfe_shared, NULL); | 1581 | &dev->pci->dev, adapter_nr, mfe_shared, NULL); |
1582 | if (res) | ||
1583 | goto frontend_detach; | ||
1584 | return res; | ||
1571 | 1585 | ||
1572 | frontend_detach: | 1586 | frontend_detach: |
1573 | core->gate_ctrl = NULL; | 1587 | core->gate_ctrl = NULL; |
1574 | videobuf_dvb_dealloc_frontends(&dev->frontends); | 1588 | videobuf_dvb_dealloc_frontends(&dev->frontends); |
1575 | return -EINVAL; | 1589 | return res; |
1576 | } | 1590 | } |
1577 | 1591 | ||
1578 | /* ----------------------------------------------------------- */ | 1592 | /* ----------------------------------------------------------- */ |
diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index a1fe0abb6e43..de0f1af74e41 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c | |||
@@ -132,7 +132,7 @@ static void do_i2c_scan(const char *name, struct i2c_client *c) | |||
132 | } | 132 | } |
133 | } | 133 | } |
134 | 134 | ||
135 | /* init + register i2c algo-bit adapter */ | 135 | /* init + register i2c adapter */ |
136 | int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) | 136 | int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) |
137 | { | 137 | { |
138 | /* Prevents usage of invalid delay values */ | 138 | /* Prevents usage of invalid delay values */ |
diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index e614201b5ed3..ebf448c48ca3 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c | |||
@@ -103,6 +103,8 @@ static void cx88_ir_handle_key(struct cx88_IR *ir) | |||
103 | case CX88_BOARD_WINFAST_DTV1800H_XC4000: | 103 | case CX88_BOARD_WINFAST_DTV1800H_XC4000: |
104 | case CX88_BOARD_WINFAST_DTV2000H_PLUS: | 104 | case CX88_BOARD_WINFAST_DTV2000H_PLUS: |
105 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: | 105 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: |
106 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36: | ||
107 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43: | ||
106 | gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900); | 108 | gpio = (gpio & 0x6ff) | ((cx_read(MO_GP1_IO) << 8) & 0x900); |
107 | auxgpio = gpio; | 109 | auxgpio = gpio; |
108 | break; | 110 | break; |
@@ -302,6 +304,8 @@ int cx88_ir_init(struct cx88_core *core, struct pci_dev *pci) | |||
302 | case CX88_BOARD_WINFAST2000XP_EXPERT: | 304 | case CX88_BOARD_WINFAST2000XP_EXPERT: |
303 | case CX88_BOARD_WINFAST_DTV1000: | 305 | case CX88_BOARD_WINFAST_DTV1000: |
304 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: | 306 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: |
307 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36: | ||
308 | case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43: | ||
305 | ir_codes = RC_MAP_WINFAST; | 309 | ir_codes = RC_MAP_WINFAST; |
306 | ir->gpio_addr = MO_GP0_IO; | 310 | ir->gpio_addr = MO_GP0_IO; |
307 | ir->mask_keycode = 0x8f8; | 311 | ir->mask_keycode = 0x8f8; |
diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index fa8d307e1a3d..c9659def2a78 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h | |||
@@ -244,6 +244,8 @@ extern const struct sram_channel const cx88_sram_channels[]; | |||
244 | #define CX88_BOARD_TEVII_S464 86 | 244 | #define CX88_BOARD_TEVII_S464 86 |
245 | #define CX88_BOARD_WINFAST_DTV2000H_PLUS 87 | 245 | #define CX88_BOARD_WINFAST_DTV2000H_PLUS 87 |
246 | #define CX88_BOARD_WINFAST_DTV1800H_XC4000 88 | 246 | #define CX88_BOARD_WINFAST_DTV1800H_XC4000 88 |
247 | #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36 89 | ||
248 | #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43 90 | ||
247 | 249 | ||
248 | enum cx88_itype { | 250 | enum cx88_itype { |
249 | CX88_VMUX_COMPOSITE1 = 1, | 251 | CX88_VMUX_COMPOSITE1 = 1, |
diff --git a/drivers/media/video/davinci/dm355_ccdc.c b/drivers/media/video/davinci/dm355_ccdc.c index bd443ee76fff..f83baf3a52b0 100644 --- a/drivers/media/video/davinci/dm355_ccdc.c +++ b/drivers/media/video/davinci/dm355_ccdc.c | |||
@@ -1069,15 +1069,4 @@ static struct platform_driver dm355_ccdc_driver = { | |||
1069 | .probe = dm355_ccdc_probe, | 1069 | .probe = dm355_ccdc_probe, |
1070 | }; | 1070 | }; |
1071 | 1071 | ||
1072 | static int __init dm355_ccdc_init(void) | 1072 | module_platform_driver(dm355_ccdc_driver); |
1073 | { | ||
1074 | return platform_driver_register(&dm355_ccdc_driver); | ||
1075 | } | ||
1076 | |||
1077 | static void __exit dm355_ccdc_exit(void) | ||
1078 | { | ||
1079 | platform_driver_unregister(&dm355_ccdc_driver); | ||
1080 | } | ||
1081 | |||
1082 | module_init(dm355_ccdc_init); | ||
1083 | module_exit(dm355_ccdc_exit); | ||
diff --git a/drivers/media/video/davinci/dm644x_ccdc.c b/drivers/media/video/davinci/dm644x_ccdc.c index 8051c2956478..9303fe553b07 100644 --- a/drivers/media/video/davinci/dm644x_ccdc.c +++ b/drivers/media/video/davinci/dm644x_ccdc.c | |||
@@ -1078,15 +1078,4 @@ static struct platform_driver dm644x_ccdc_driver = { | |||
1078 | .probe = dm644x_ccdc_probe, | 1078 | .probe = dm644x_ccdc_probe, |
1079 | }; | 1079 | }; |
1080 | 1080 | ||
1081 | static int __init dm644x_ccdc_init(void) | 1081 | module_platform_driver(dm644x_ccdc_driver); |
1082 | { | ||
1083 | return platform_driver_register(&dm644x_ccdc_driver); | ||
1084 | } | ||
1085 | |||
1086 | static void __exit dm644x_ccdc_exit(void) | ||
1087 | { | ||
1088 | platform_driver_unregister(&dm644x_ccdc_driver); | ||
1089 | } | ||
1090 | |||
1091 | module_init(dm644x_ccdc_init); | ||
1092 | module_exit(dm644x_ccdc_exit); | ||
diff --git a/drivers/media/video/davinci/isif.c b/drivers/media/video/davinci/isif.c index 29c29c668596..1e63852374be 100644 --- a/drivers/media/video/davinci/isif.c +++ b/drivers/media/video/davinci/isif.c | |||
@@ -1156,17 +1156,6 @@ static struct platform_driver isif_driver = { | |||
1156 | .probe = isif_probe, | 1156 | .probe = isif_probe, |
1157 | }; | 1157 | }; |
1158 | 1158 | ||
1159 | static int __init isif_init(void) | 1159 | module_platform_driver(isif_driver); |
1160 | { | ||
1161 | return platform_driver_register(&isif_driver); | ||
1162 | } | ||
1163 | |||
1164 | static void isif_exit(void) | ||
1165 | { | ||
1166 | platform_driver_unregister(&isif_driver); | ||
1167 | } | ||
1168 | |||
1169 | module_init(isif_init); | ||
1170 | module_exit(isif_exit); | ||
1171 | 1160 | ||
1172 | MODULE_LICENSE("GPL"); | 1161 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/video/davinci/vpbe.c b/drivers/media/video/davinci/vpbe.c index d773d30de221..c4a82a1a8a97 100644 --- a/drivers/media/video/davinci/vpbe.c +++ b/drivers/media/video/davinci/vpbe.c | |||
@@ -141,11 +141,12 @@ static int vpbe_enum_outputs(struct vpbe_device *vpbe_dev, | |||
141 | return 0; | 141 | return 0; |
142 | } | 142 | } |
143 | 143 | ||
144 | static int vpbe_get_mode_info(struct vpbe_device *vpbe_dev, char *mode) | 144 | static int vpbe_get_mode_info(struct vpbe_device *vpbe_dev, char *mode, |
145 | int output_index) | ||
145 | { | 146 | { |
146 | struct vpbe_config *cfg = vpbe_dev->cfg; | 147 | struct vpbe_config *cfg = vpbe_dev->cfg; |
147 | struct vpbe_enc_mode_info var; | 148 | struct vpbe_enc_mode_info var; |
148 | int curr_output = vpbe_dev->current_out_index; | 149 | int curr_output = output_index; |
149 | int i; | 150 | int i; |
150 | 151 | ||
151 | if (NULL == mode) | 152 | if (NULL == mode) |
@@ -245,6 +246,8 @@ static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index) | |||
245 | struct encoder_config_info *curr_enc_info = | 246 | struct encoder_config_info *curr_enc_info = |
246 | vpbe_current_encoder_info(vpbe_dev); | 247 | vpbe_current_encoder_info(vpbe_dev); |
247 | struct vpbe_config *cfg = vpbe_dev->cfg; | 248 | struct vpbe_config *cfg = vpbe_dev->cfg; |
249 | struct venc_platform_data *venc_device = vpbe_dev->venc_device; | ||
250 | enum v4l2_mbus_pixelcode if_params; | ||
248 | int enc_out_index; | 251 | int enc_out_index; |
249 | int sd_index; | 252 | int sd_index; |
250 | int ret = 0; | 253 | int ret = 0; |
@@ -274,6 +277,8 @@ static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index) | |||
274 | goto out; | 277 | goto out; |
275 | } | 278 | } |
276 | 279 | ||
280 | if_params = cfg->outputs[index].if_params; | ||
281 | venc_device->setup_if_config(if_params); | ||
277 | if (ret) | 282 | if (ret) |
278 | goto out; | 283 | goto out; |
279 | } | 284 | } |
@@ -293,7 +298,7 @@ static int vpbe_set_output(struct vpbe_device *vpbe_dev, int index) | |||
293 | * encoder. | 298 | * encoder. |
294 | */ | 299 | */ |
295 | ret = vpbe_get_mode_info(vpbe_dev, | 300 | ret = vpbe_get_mode_info(vpbe_dev, |
296 | cfg->outputs[index].default_mode); | 301 | cfg->outputs[index].default_mode, index); |
297 | if (!ret) { | 302 | if (!ret) { |
298 | struct osd_state *osd_device = vpbe_dev->osd_device; | 303 | struct osd_state *osd_device = vpbe_dev->osd_device; |
299 | 304 | ||
@@ -367,6 +372,11 @@ static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev, | |||
367 | 372 | ||
368 | ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video, | 373 | ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video, |
369 | s_dv_preset, dv_preset); | 374 | s_dv_preset, dv_preset); |
375 | if (!ret && (vpbe_dev->amp != NULL)) { | ||
376 | /* Call amplifier subdevice */ | ||
377 | ret = v4l2_subdev_call(vpbe_dev->amp, video, | ||
378 | s_dv_preset, dv_preset); | ||
379 | } | ||
370 | /* set the lcd controller output for the given mode */ | 380 | /* set the lcd controller output for the given mode */ |
371 | if (!ret) { | 381 | if (!ret) { |
372 | struct osd_state *osd_device = vpbe_dev->osd_device; | 382 | struct osd_state *osd_device = vpbe_dev->osd_device; |
@@ -566,6 +576,8 @@ static int platform_device_get(struct device *dev, void *data) | |||
566 | 576 | ||
567 | if (strcmp("vpbe-osd", pdev->name) == 0) | 577 | if (strcmp("vpbe-osd", pdev->name) == 0) |
568 | vpbe_dev->osd_device = platform_get_drvdata(pdev); | 578 | vpbe_dev->osd_device = platform_get_drvdata(pdev); |
579 | if (strcmp("vpbe-venc", pdev->name) == 0) | ||
580 | vpbe_dev->venc_device = dev_get_platdata(&pdev->dev); | ||
569 | 581 | ||
570 | return 0; | 582 | return 0; |
571 | } | 583 | } |
@@ -584,6 +596,7 @@ static int platform_device_get(struct device *dev, void *data) | |||
584 | static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) | 596 | static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) |
585 | { | 597 | { |
586 | struct encoder_config_info *enc_info; | 598 | struct encoder_config_info *enc_info; |
599 | struct amp_config_info *amp_info; | ||
587 | struct v4l2_subdev **enc_subdev; | 600 | struct v4l2_subdev **enc_subdev; |
588 | struct osd_state *osd_device; | 601 | struct osd_state *osd_device; |
589 | struct i2c_adapter *i2c_adap; | 602 | struct i2c_adapter *i2c_adap; |
@@ -704,6 +717,32 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) | |||
704 | v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders" | 717 | v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c encoders" |
705 | " currently not supported"); | 718 | " currently not supported"); |
706 | } | 719 | } |
720 | /* Add amplifier subdevice for dm365 */ | ||
721 | if ((strcmp(vpbe_dev->cfg->module_name, "dm365-vpbe-display") == 0) && | ||
722 | vpbe_dev->cfg->amp != NULL) { | ||
723 | amp_info = vpbe_dev->cfg->amp; | ||
724 | if (amp_info->is_i2c) { | ||
725 | vpbe_dev->amp = v4l2_i2c_new_subdev_board( | ||
726 | &vpbe_dev->v4l2_dev, i2c_adap, | ||
727 | &_info->board_info, NULL); | ||
728 | if (!vpbe_dev->amp) { | ||
729 | v4l2_err(&vpbe_dev->v4l2_dev, | ||
730 | "amplifier %s failed to register", | ||
731 | amp_info->module_name); | ||
732 | ret = -ENODEV; | ||
733 | goto vpbe_fail_amp_register; | ||
734 | } | ||
735 | v4l2_info(&vpbe_dev->v4l2_dev, | ||
736 | "v4l2 sub device %s registered\n", | ||
737 | amp_info->module_name); | ||
738 | } else { | ||
739 | vpbe_dev->amp = NULL; | ||
740 | v4l2_warn(&vpbe_dev->v4l2_dev, "non-i2c amplifiers" | ||
741 | " currently not supported"); | ||
742 | } | ||
743 | } else { | ||
744 | vpbe_dev->amp = NULL; | ||
745 | } | ||
707 | 746 | ||
708 | /* set the current encoder and output to that of venc by default */ | 747 | /* set the current encoder and output to that of venc by default */ |
709 | vpbe_dev->current_sd_index = 0; | 748 | vpbe_dev->current_sd_index = 0; |
@@ -731,6 +770,8 @@ static int vpbe_initialize(struct device *dev, struct vpbe_device *vpbe_dev) | |||
731 | /* TBD handling of bootargs for default output and mode */ | 770 | /* TBD handling of bootargs for default output and mode */ |
732 | return 0; | 771 | return 0; |
733 | 772 | ||
773 | vpbe_fail_amp_register: | ||
774 | kfree(vpbe_dev->amp); | ||
734 | vpbe_fail_sd_register: | 775 | vpbe_fail_sd_register: |
735 | kfree(vpbe_dev->encoders); | 776 | kfree(vpbe_dev->encoders); |
736 | vpbe_fail_v4l2_device: | 777 | vpbe_fail_v4l2_device: |
@@ -757,6 +798,7 @@ static void vpbe_deinitialize(struct device *dev, struct vpbe_device *vpbe_dev) | |||
757 | if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) | 798 | if (strcmp(vpbe_dev->cfg->module_name, "dm644x-vpbe-display") != 0) |
758 | clk_put(vpbe_dev->dac_clk); | 799 | clk_put(vpbe_dev->dac_clk); |
759 | 800 | ||
801 | kfree(vpbe_dev->amp); | ||
760 | kfree(vpbe_dev->encoders); | 802 | kfree(vpbe_dev->encoders); |
761 | vpbe_dev->initialized = 0; | 803 | vpbe_dev->initialized = 0; |
762 | /* disable vpss clocks */ | 804 | /* disable vpss clocks */ |
@@ -811,8 +853,10 @@ static __devinit int vpbe_probe(struct platform_device *pdev) | |||
811 | 853 | ||
812 | if (cfg->outputs->num_modes > 0) | 854 | if (cfg->outputs->num_modes > 0) |
813 | vpbe_dev->current_timings = vpbe_dev->cfg->outputs[0].modes[0]; | 855 | vpbe_dev->current_timings = vpbe_dev->cfg->outputs[0].modes[0]; |
814 | else | 856 | else { |
857 | kfree(vpbe_dev); | ||
815 | return -ENODEV; | 858 | return -ENODEV; |
859 | } | ||
816 | 860 | ||
817 | /* set the driver data in platform device */ | 861 | /* set the driver data in platform device */ |
818 | platform_set_drvdata(pdev, vpbe_dev); | 862 | platform_set_drvdata(pdev, vpbe_dev); |
@@ -839,26 +883,4 @@ static struct platform_driver vpbe_driver = { | |||
839 | .remove = vpbe_remove, | 883 | .remove = vpbe_remove, |
840 | }; | 884 | }; |
841 | 885 | ||
842 | /** | 886 | module_platform_driver(vpbe_driver); |
843 | * vpbe_init: initialize the vpbe driver | ||
844 | * | ||
845 | * This function registers device and driver to the kernel | ||
846 | */ | ||
847 | static __init int vpbe_init(void) | ||
848 | { | ||
849 | return platform_driver_register(&vpbe_driver); | ||
850 | } | ||
851 | |||
852 | /** | ||
853 | * vpbe_cleanup : cleanup function for vpbe driver | ||
854 | * | ||
855 | * This will un-registers the device and driver to the kernel | ||
856 | */ | ||
857 | static void vpbe_cleanup(void) | ||
858 | { | ||
859 | platform_driver_unregister(&vpbe_driver); | ||
860 | } | ||
861 | |||
862 | /* Function for module initialization and cleanup */ | ||
863 | module_init(vpbe_init); | ||
864 | module_exit(vpbe_cleanup); | ||
diff --git a/drivers/media/video/davinci/vpbe_display.c b/drivers/media/video/davinci/vpbe_display.c index 8588a86d9b45..1f3b1c729252 100644 --- a/drivers/media/video/davinci/vpbe_display.c +++ b/drivers/media/video/davinci/vpbe_display.c | |||
@@ -1746,15 +1746,16 @@ static __devinit int vpbe_display_probe(struct platform_device *pdev) | |||
1746 | for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) { | 1746 | for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) { |
1747 | if (register_device(disp_dev->dev[i], disp_dev, pdev)) { | 1747 | if (register_device(disp_dev->dev[i], disp_dev, pdev)) { |
1748 | err = -ENODEV; | 1748 | err = -ENODEV; |
1749 | goto probe_out; | 1749 | goto probe_out_irq; |
1750 | } | 1750 | } |
1751 | } | 1751 | } |
1752 | 1752 | ||
1753 | printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n"); | 1753 | printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n"); |
1754 | return 0; | 1754 | return 0; |
1755 | 1755 | ||
1756 | probe_out: | 1756 | probe_out_irq: |
1757 | free_irq(res->start, disp_dev); | 1757 | free_irq(res->start, disp_dev); |
1758 | probe_out: | ||
1758 | for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) { | 1759 | for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) { |
1759 | /* Get the pointer to the layer object */ | 1760 | /* Get the pointer to the layer object */ |
1760 | vpbe_display_layer = disp_dev->dev[k]; | 1761 | vpbe_display_layer = disp_dev->dev[k]; |
@@ -1816,43 +1817,7 @@ static struct platform_driver vpbe_display_driver = { | |||
1816 | .remove = __devexit_p(vpbe_display_remove), | 1817 | .remove = __devexit_p(vpbe_display_remove), |
1817 | }; | 1818 | }; |
1818 | 1819 | ||
1819 | /* | 1820 | module_platform_driver(vpbe_display_driver); |
1820 | * vpbe_display_init() | ||
1821 | * This function registers device and driver to the kernel, requests irq | ||
1822 | * handler and allocates memory for layer objects | ||
1823 | */ | ||
1824 | static __devinit int vpbe_display_init(void) | ||
1825 | { | ||
1826 | int err; | ||
1827 | |||
1828 | printk(KERN_DEBUG "vpbe_display_init\n"); | ||
1829 | |||
1830 | /* Register driver to the kernel */ | ||
1831 | err = platform_driver_register(&vpbe_display_driver); | ||
1832 | if (0 != err) | ||
1833 | return err; | ||
1834 | |||
1835 | printk(KERN_DEBUG "vpbe_display_init:" | ||
1836 | "VPBE V4L2 Display Driver V1.0 loaded\n"); | ||
1837 | return 0; | ||
1838 | } | ||
1839 | |||
1840 | /* | ||
1841 | * vpbe_display_cleanup() | ||
1842 | * This function un-registers device and driver to the kernel, frees requested | ||
1843 | * irq handler and de-allocates memory allocated for layer objects. | ||
1844 | */ | ||
1845 | static void vpbe_display_cleanup(void) | ||
1846 | { | ||
1847 | printk(KERN_DEBUG "vpbe_display_cleanup\n"); | ||
1848 | |||
1849 | /* platform driver unregister */ | ||
1850 | platform_driver_unregister(&vpbe_display_driver); | ||
1851 | } | ||
1852 | |||
1853 | /* Function for module initialization and cleanup */ | ||
1854 | module_init(vpbe_display_init); | ||
1855 | module_exit(vpbe_display_cleanup); | ||
1856 | 1821 | ||
1857 | MODULE_DESCRIPTION("TI DM644x/DM355/DM365 VPBE Display controller"); | 1822 | MODULE_DESCRIPTION("TI DM644x/DM355/DM365 VPBE Display controller"); |
1858 | MODULE_LICENSE("GPL"); | 1823 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/video/davinci/vpbe_osd.c b/drivers/media/video/davinci/vpbe_osd.c index ceccf4302518..d6488b79ae3b 100644 --- a/drivers/media/video/davinci/vpbe_osd.c +++ b/drivers/media/video/davinci/vpbe_osd.c | |||
@@ -248,11 +248,29 @@ static void _osd_set_rec601_attenuation(struct osd_state *sd, | |||
248 | osd_modify(sd, OSD_OSDWIN0MD_ATN0E, | 248 | osd_modify(sd, OSD_OSDWIN0MD_ATN0E, |
249 | enable ? OSD_OSDWIN0MD_ATN0E : 0, | 249 | enable ? OSD_OSDWIN0MD_ATN0E : 0, |
250 | OSD_OSDWIN0MD); | 250 | OSD_OSDWIN0MD); |
251 | if (sd->vpbe_type == VPBE_VERSION_1) | ||
252 | osd_modify(sd, OSD_OSDWIN0MD_ATN0E, | ||
253 | enable ? OSD_OSDWIN0MD_ATN0E : 0, | ||
254 | OSD_OSDWIN0MD); | ||
255 | else if ((sd->vpbe_type == VPBE_VERSION_3) || | ||
256 | (sd->vpbe_type == VPBE_VERSION_2)) | ||
257 | osd_modify(sd, OSD_EXTMODE_ATNOSD0EN, | ||
258 | enable ? OSD_EXTMODE_ATNOSD0EN : 0, | ||
259 | OSD_EXTMODE); | ||
251 | break; | 260 | break; |
252 | case OSDWIN_OSD1: | 261 | case OSDWIN_OSD1: |
253 | osd_modify(sd, OSD_OSDWIN1MD_ATN1E, | 262 | osd_modify(sd, OSD_OSDWIN1MD_ATN1E, |
254 | enable ? OSD_OSDWIN1MD_ATN1E : 0, | 263 | enable ? OSD_OSDWIN1MD_ATN1E : 0, |
255 | OSD_OSDWIN1MD); | 264 | OSD_OSDWIN1MD); |
265 | if (sd->vpbe_type == VPBE_VERSION_1) | ||
266 | osd_modify(sd, OSD_OSDWIN1MD_ATN1E, | ||
267 | enable ? OSD_OSDWIN1MD_ATN1E : 0, | ||
268 | OSD_OSDWIN1MD); | ||
269 | else if ((sd->vpbe_type == VPBE_VERSION_3) || | ||
270 | (sd->vpbe_type == VPBE_VERSION_2)) | ||
271 | osd_modify(sd, OSD_EXTMODE_ATNOSD1EN, | ||
272 | enable ? OSD_EXTMODE_ATNOSD1EN : 0, | ||
273 | OSD_EXTMODE); | ||
256 | break; | 274 | break; |
257 | } | 275 | } |
258 | } | 276 | } |
@@ -273,15 +291,71 @@ static void _osd_set_blending_factor(struct osd_state *sd, | |||
273 | } | 291 | } |
274 | } | 292 | } |
275 | 293 | ||
294 | static void _osd_enable_rgb888_pixblend(struct osd_state *sd, | ||
295 | enum osd_win_layer osdwin) | ||
296 | { | ||
297 | |||
298 | osd_modify(sd, OSD_MISCCTL_BLDSEL, 0, OSD_MISCCTL); | ||
299 | switch (osdwin) { | ||
300 | case OSDWIN_OSD0: | ||
301 | osd_modify(sd, OSD_EXTMODE_OSD0BLDCHR, | ||
302 | OSD_EXTMODE_OSD0BLDCHR, OSD_EXTMODE); | ||
303 | break; | ||
304 | case OSDWIN_OSD1: | ||
305 | osd_modify(sd, OSD_EXTMODE_OSD1BLDCHR, | ||
306 | OSD_EXTMODE_OSD1BLDCHR, OSD_EXTMODE); | ||
307 | break; | ||
308 | } | ||
309 | } | ||
310 | |||
276 | static void _osd_enable_color_key(struct osd_state *sd, | 311 | static void _osd_enable_color_key(struct osd_state *sd, |
277 | enum osd_win_layer osdwin, | 312 | enum osd_win_layer osdwin, |
278 | unsigned colorkey, | 313 | unsigned colorkey, |
279 | enum osd_pix_format pixfmt) | 314 | enum osd_pix_format pixfmt) |
280 | { | 315 | { |
281 | switch (pixfmt) { | 316 | switch (pixfmt) { |
317 | case PIXFMT_1BPP: | ||
318 | case PIXFMT_2BPP: | ||
319 | case PIXFMT_4BPP: | ||
320 | case PIXFMT_8BPP: | ||
321 | if (sd->vpbe_type == VPBE_VERSION_3) { | ||
322 | switch (osdwin) { | ||
323 | case OSDWIN_OSD0: | ||
324 | osd_modify(sd, OSD_TRANSPBMPIDX_BMP0, | ||
325 | colorkey << | ||
326 | OSD_TRANSPBMPIDX_BMP0_SHIFT, | ||
327 | OSD_TRANSPBMPIDX); | ||
328 | break; | ||
329 | case OSDWIN_OSD1: | ||
330 | osd_modify(sd, OSD_TRANSPBMPIDX_BMP1, | ||
331 | colorkey << | ||
332 | OSD_TRANSPBMPIDX_BMP1_SHIFT, | ||
333 | OSD_TRANSPBMPIDX); | ||
334 | break; | ||
335 | } | ||
336 | } | ||
337 | break; | ||
282 | case PIXFMT_RGB565: | 338 | case PIXFMT_RGB565: |
283 | osd_write(sd, colorkey & OSD_TRANSPVAL_RGBTRANS, | 339 | if (sd->vpbe_type == VPBE_VERSION_1) |
284 | OSD_TRANSPVAL); | 340 | osd_write(sd, colorkey & OSD_TRANSPVAL_RGBTRANS, |
341 | OSD_TRANSPVAL); | ||
342 | else if (sd->vpbe_type == VPBE_VERSION_3) | ||
343 | osd_write(sd, colorkey & OSD_TRANSPVALL_RGBL, | ||
344 | OSD_TRANSPVALL); | ||
345 | break; | ||
346 | case PIXFMT_YCbCrI: | ||
347 | case PIXFMT_YCrCbI: | ||
348 | if (sd->vpbe_type == VPBE_VERSION_3) | ||
349 | osd_modify(sd, OSD_TRANSPVALU_Y, colorkey, | ||
350 | OSD_TRANSPVALU); | ||
351 | break; | ||
352 | case PIXFMT_RGB888: | ||
353 | if (sd->vpbe_type == VPBE_VERSION_3) { | ||
354 | osd_write(sd, colorkey & OSD_TRANSPVALL_RGBL, | ||
355 | OSD_TRANSPVALL); | ||
356 | osd_modify(sd, OSD_TRANSPVALU_RGBU, colorkey >> 16, | ||
357 | OSD_TRANSPVALU); | ||
358 | } | ||
285 | break; | 359 | break; |
286 | default: | 360 | default: |
287 | break; | 361 | break; |
@@ -470,23 +544,188 @@ static int osd_enable_layer(struct osd_state *sd, enum osd_layer layer, | |||
470 | return 0; | 544 | return 0; |
471 | } | 545 | } |
472 | 546 | ||
547 | #define OSD_SRC_ADDR_HIGH4 0x7800000 | ||
548 | #define OSD_SRC_ADDR_HIGH7 0x7F0000 | ||
549 | #define OSD_SRCADD_OFSET_SFT 23 | ||
550 | #define OSD_SRCADD_ADD_SFT 16 | ||
551 | #define OSD_WINADL_MASK 0xFFFF | ||
552 | #define OSD_WINOFST_MASK 0x1000 | ||
553 | #define VPBE_REG_BASE 0x80000000 | ||
554 | |||
473 | static void _osd_start_layer(struct osd_state *sd, enum osd_layer layer, | 555 | static void _osd_start_layer(struct osd_state *sd, enum osd_layer layer, |
474 | unsigned long fb_base_phys, | 556 | unsigned long fb_base_phys, |
475 | unsigned long cbcr_ofst) | 557 | unsigned long cbcr_ofst) |
476 | { | 558 | { |
477 | switch (layer) { | 559 | |
478 | case WIN_OSD0: | 560 | if (sd->vpbe_type == VPBE_VERSION_1) { |
479 | osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN0ADR); | 561 | switch (layer) { |
480 | break; | 562 | case WIN_OSD0: |
481 | case WIN_VID0: | 563 | osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN0ADR); |
482 | osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR); | 564 | break; |
483 | break; | 565 | case WIN_VID0: |
484 | case WIN_OSD1: | 566 | osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN0ADR); |
485 | osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN1ADR); | 567 | break; |
486 | break; | 568 | case WIN_OSD1: |
487 | case WIN_VID1: | 569 | osd_write(sd, fb_base_phys & ~0x1F, OSD_OSDWIN1ADR); |
488 | osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN1ADR); | 570 | break; |
489 | break; | 571 | case WIN_VID1: |
572 | osd_write(sd, fb_base_phys & ~0x1F, OSD_VIDWIN1ADR); | ||
573 | break; | ||
574 | } | ||
575 | } else if (sd->vpbe_type == VPBE_VERSION_3) { | ||
576 | unsigned long fb_offset_32 = | ||
577 | (fb_base_phys - VPBE_REG_BASE) >> 5; | ||
578 | |||
579 | switch (layer) { | ||
580 | case WIN_OSD0: | ||
581 | osd_modify(sd, OSD_OSDWINADH_O0AH, | ||
582 | fb_offset_32 >> (OSD_SRCADD_ADD_SFT - | ||
583 | OSD_OSDWINADH_O0AH_SHIFT), | ||
584 | OSD_OSDWINADH); | ||
585 | osd_write(sd, fb_offset_32 & OSD_OSDWIN0ADL_O0AL, | ||
586 | OSD_OSDWIN0ADL); | ||
587 | break; | ||
588 | case WIN_VID0: | ||
589 | osd_modify(sd, OSD_VIDWINADH_V0AH, | ||
590 | fb_offset_32 >> (OSD_SRCADD_ADD_SFT - | ||
591 | OSD_VIDWINADH_V0AH_SHIFT), | ||
592 | OSD_VIDWINADH); | ||
593 | osd_write(sd, fb_offset_32 & OSD_VIDWIN0ADL_V0AL, | ||
594 | OSD_VIDWIN0ADL); | ||
595 | break; | ||
596 | case WIN_OSD1: | ||
597 | osd_modify(sd, OSD_OSDWINADH_O1AH, | ||
598 | fb_offset_32 >> (OSD_SRCADD_ADD_SFT - | ||
599 | OSD_OSDWINADH_O1AH_SHIFT), | ||
600 | OSD_OSDWINADH); | ||
601 | osd_write(sd, fb_offset_32 & OSD_OSDWIN1ADL_O1AL, | ||
602 | OSD_OSDWIN1ADL); | ||
603 | break; | ||
604 | case WIN_VID1: | ||
605 | osd_modify(sd, OSD_VIDWINADH_V1AH, | ||
606 | fb_offset_32 >> (OSD_SRCADD_ADD_SFT - | ||
607 | OSD_VIDWINADH_V1AH_SHIFT), | ||
608 | OSD_VIDWINADH); | ||
609 | osd_write(sd, fb_offset_32 & OSD_VIDWIN1ADL_V1AL, | ||
610 | OSD_VIDWIN1ADL); | ||
611 | break; | ||
612 | } | ||
613 | } else if (sd->vpbe_type == VPBE_VERSION_2) { | ||
614 | struct osd_window_state *win = &sd->win[layer]; | ||
615 | unsigned long fb_offset_32, cbcr_offset_32; | ||
616 | |||
617 | fb_offset_32 = fb_base_phys - VPBE_REG_BASE; | ||
618 | if (cbcr_ofst) | ||
619 | cbcr_offset_32 = cbcr_ofst; | ||
620 | else | ||
621 | cbcr_offset_32 = win->lconfig.line_length * | ||
622 | win->lconfig.ysize; | ||
623 | cbcr_offset_32 += fb_offset_32; | ||
624 | fb_offset_32 = fb_offset_32 >> 5; | ||
625 | cbcr_offset_32 = cbcr_offset_32 >> 5; | ||
626 | /* | ||
627 | * DM365: start address is 27-bit long address b26 - b23 are | ||
628 | * in offset register b12 - b9, and * bit 26 has to be '1' | ||
629 | */ | ||
630 | if (win->lconfig.pixfmt == PIXFMT_NV12) { | ||
631 | switch (layer) { | ||
632 | case WIN_VID0: | ||
633 | case WIN_VID1: | ||
634 | /* Y is in VID0 */ | ||
635 | osd_modify(sd, OSD_VIDWIN0OFST_V0AH, | ||
636 | ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >> | ||
637 | (OSD_SRCADD_OFSET_SFT - | ||
638 | OSD_WINOFST_AH_SHIFT)) | | ||
639 | OSD_WINOFST_MASK, OSD_VIDWIN0OFST); | ||
640 | osd_modify(sd, OSD_VIDWINADH_V0AH, | ||
641 | (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >> | ||
642 | (OSD_SRCADD_ADD_SFT - | ||
643 | OSD_VIDWINADH_V0AH_SHIFT), | ||
644 | OSD_VIDWINADH); | ||
645 | osd_write(sd, fb_offset_32 & OSD_WINADL_MASK, | ||
646 | OSD_VIDWIN0ADL); | ||
647 | /* CbCr is in VID1 */ | ||
648 | osd_modify(sd, OSD_VIDWIN1OFST_V1AH, | ||
649 | ((cbcr_offset_32 & | ||
650 | OSD_SRC_ADDR_HIGH4) >> | ||
651 | (OSD_SRCADD_OFSET_SFT - | ||
652 | OSD_WINOFST_AH_SHIFT)) | | ||
653 | OSD_WINOFST_MASK, OSD_VIDWIN1OFST); | ||
654 | osd_modify(sd, OSD_VIDWINADH_V1AH, | ||
655 | (cbcr_offset_32 & | ||
656 | OSD_SRC_ADDR_HIGH7) >> | ||
657 | (OSD_SRCADD_ADD_SFT - | ||
658 | OSD_VIDWINADH_V1AH_SHIFT), | ||
659 | OSD_VIDWINADH); | ||
660 | osd_write(sd, cbcr_offset_32 & OSD_WINADL_MASK, | ||
661 | OSD_VIDWIN1ADL); | ||
662 | break; | ||
663 | default: | ||
664 | break; | ||
665 | } | ||
666 | } | ||
667 | |||
668 | switch (layer) { | ||
669 | case WIN_OSD0: | ||
670 | osd_modify(sd, OSD_OSDWIN0OFST_O0AH, | ||
671 | ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >> | ||
672 | (OSD_SRCADD_OFSET_SFT - | ||
673 | OSD_WINOFST_AH_SHIFT)) | OSD_WINOFST_MASK, | ||
674 | OSD_OSDWIN0OFST); | ||
675 | osd_modify(sd, OSD_OSDWINADH_O0AH, | ||
676 | (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >> | ||
677 | (OSD_SRCADD_ADD_SFT - | ||
678 | OSD_OSDWINADH_O0AH_SHIFT), OSD_OSDWINADH); | ||
679 | osd_write(sd, fb_offset_32 & OSD_WINADL_MASK, | ||
680 | OSD_OSDWIN0ADL); | ||
681 | break; | ||
682 | case WIN_VID0: | ||
683 | if (win->lconfig.pixfmt != PIXFMT_NV12) { | ||
684 | osd_modify(sd, OSD_VIDWIN0OFST_V0AH, | ||
685 | ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >> | ||
686 | (OSD_SRCADD_OFSET_SFT - | ||
687 | OSD_WINOFST_AH_SHIFT)) | | ||
688 | OSD_WINOFST_MASK, OSD_VIDWIN0OFST); | ||
689 | osd_modify(sd, OSD_VIDWINADH_V0AH, | ||
690 | (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >> | ||
691 | (OSD_SRCADD_ADD_SFT - | ||
692 | OSD_VIDWINADH_V0AH_SHIFT), | ||
693 | OSD_VIDWINADH); | ||
694 | osd_write(sd, fb_offset_32 & OSD_WINADL_MASK, | ||
695 | OSD_VIDWIN0ADL); | ||
696 | } | ||
697 | break; | ||
698 | case WIN_OSD1: | ||
699 | osd_modify(sd, OSD_OSDWIN1OFST_O1AH, | ||
700 | ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >> | ||
701 | (OSD_SRCADD_OFSET_SFT - | ||
702 | OSD_WINOFST_AH_SHIFT)) | OSD_WINOFST_MASK, | ||
703 | OSD_OSDWIN1OFST); | ||
704 | osd_modify(sd, OSD_OSDWINADH_O1AH, | ||
705 | (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >> | ||
706 | (OSD_SRCADD_ADD_SFT - | ||
707 | OSD_OSDWINADH_O1AH_SHIFT), | ||
708 | OSD_OSDWINADH); | ||
709 | osd_write(sd, fb_offset_32 & OSD_WINADL_MASK, | ||
710 | OSD_OSDWIN1ADL); | ||
711 | break; | ||
712 | case WIN_VID1: | ||
713 | if (win->lconfig.pixfmt != PIXFMT_NV12) { | ||
714 | osd_modify(sd, OSD_VIDWIN1OFST_V1AH, | ||
715 | ((fb_offset_32 & OSD_SRC_ADDR_HIGH4) >> | ||
716 | (OSD_SRCADD_OFSET_SFT - | ||
717 | OSD_WINOFST_AH_SHIFT)) | | ||
718 | OSD_WINOFST_MASK, OSD_VIDWIN1OFST); | ||
719 | osd_modify(sd, OSD_VIDWINADH_V1AH, | ||
720 | (fb_offset_32 & OSD_SRC_ADDR_HIGH7) >> | ||
721 | (OSD_SRCADD_ADD_SFT - | ||
722 | OSD_VIDWINADH_V1AH_SHIFT), | ||
723 | OSD_VIDWINADH); | ||
724 | osd_write(sd, fb_offset_32 & OSD_WINADL_MASK, | ||
725 | OSD_VIDWIN1ADL); | ||
726 | } | ||
727 | break; | ||
728 | } | ||
490 | } | 729 | } |
491 | } | 730 | } |
492 | 731 | ||
@@ -545,7 +784,7 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer, | |||
545 | { | 784 | { |
546 | struct osd_state *osd = sd; | 785 | struct osd_state *osd = sd; |
547 | struct osd_window_state *win = &osd->win[layer]; | 786 | struct osd_window_state *win = &osd->win[layer]; |
548 | int bad_config; | 787 | int bad_config = 0; |
549 | 788 | ||
550 | /* verify that the pixel format is compatible with the layer */ | 789 | /* verify that the pixel format is compatible with the layer */ |
551 | switch (lconfig->pixfmt) { | 790 | switch (lconfig->pixfmt) { |
@@ -554,17 +793,25 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer, | |||
554 | case PIXFMT_4BPP: | 793 | case PIXFMT_4BPP: |
555 | case PIXFMT_8BPP: | 794 | case PIXFMT_8BPP: |
556 | case PIXFMT_RGB565: | 795 | case PIXFMT_RGB565: |
557 | bad_config = !is_osd_win(layer); | 796 | if (osd->vpbe_type == VPBE_VERSION_1) |
797 | bad_config = !is_vid_win(layer); | ||
558 | break; | 798 | break; |
559 | case PIXFMT_YCbCrI: | 799 | case PIXFMT_YCbCrI: |
560 | case PIXFMT_YCrCbI: | 800 | case PIXFMT_YCrCbI: |
561 | bad_config = !is_vid_win(layer); | 801 | bad_config = !is_vid_win(layer); |
562 | break; | 802 | break; |
563 | case PIXFMT_RGB888: | 803 | case PIXFMT_RGB888: |
564 | bad_config = !is_vid_win(layer); | 804 | if (osd->vpbe_type == VPBE_VERSION_1) |
805 | bad_config = !is_vid_win(layer); | ||
806 | else if ((osd->vpbe_type == VPBE_VERSION_3) || | ||
807 | (osd->vpbe_type == VPBE_VERSION_2)) | ||
808 | bad_config = !is_osd_win(layer); | ||
565 | break; | 809 | break; |
566 | case PIXFMT_NV12: | 810 | case PIXFMT_NV12: |
567 | bad_config = 1; | 811 | if (osd->vpbe_type != VPBE_VERSION_2) |
812 | bad_config = 1; | ||
813 | else | ||
814 | bad_config = is_osd_win(layer); | ||
568 | break; | 815 | break; |
569 | case PIXFMT_OSD_ATTR: | 816 | case PIXFMT_OSD_ATTR: |
570 | bad_config = (layer != WIN_OSD1); | 817 | bad_config = (layer != WIN_OSD1); |
@@ -584,7 +831,8 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer, | |||
584 | 831 | ||
585 | /* DM6446: */ | 832 | /* DM6446: */ |
586 | /* only one OSD window at a time can use RGB pixel formats */ | 833 | /* only one OSD window at a time can use RGB pixel formats */ |
587 | if (is_osd_win(layer) && is_rgb_pixfmt(lconfig->pixfmt)) { | 834 | if ((osd->vpbe_type == VPBE_VERSION_1) && |
835 | is_osd_win(layer) && is_rgb_pixfmt(lconfig->pixfmt)) { | ||
588 | enum osd_pix_format pixfmt; | 836 | enum osd_pix_format pixfmt; |
589 | if (layer == WIN_OSD0) | 837 | if (layer == WIN_OSD0) |
590 | pixfmt = osd->win[WIN_OSD1].lconfig.pixfmt; | 838 | pixfmt = osd->win[WIN_OSD1].lconfig.pixfmt; |
@@ -602,7 +850,8 @@ static int try_layer_config(struct osd_state *sd, enum osd_layer layer, | |||
602 | } | 850 | } |
603 | 851 | ||
604 | /* DM6446: only one video window at a time can use RGB888 */ | 852 | /* DM6446: only one video window at a time can use RGB888 */ |
605 | if (is_vid_win(layer) && lconfig->pixfmt == PIXFMT_RGB888) { | 853 | if ((osd->vpbe_type == VPBE_VERSION_1) && is_vid_win(layer) && |
854 | lconfig->pixfmt == PIXFMT_RGB888) { | ||
606 | enum osd_pix_format pixfmt; | 855 | enum osd_pix_format pixfmt; |
607 | 856 | ||
608 | if (layer == WIN_VID0) | 857 | if (layer == WIN_VID0) |
@@ -652,7 +901,8 @@ static void _osd_disable_vid_rgb888(struct osd_state *sd) | |||
652 | * The caller must ensure that neither video window is currently | 901 | * The caller must ensure that neither video window is currently |
653 | * configured for RGB888 pixel format. | 902 | * configured for RGB888 pixel format. |
654 | */ | 903 | */ |
655 | osd_clear(sd, OSD_MISCCTL_RGBEN, OSD_MISCCTL); | 904 | if (sd->vpbe_type == VPBE_VERSION_1) |
905 | osd_clear(sd, OSD_MISCCTL_RGBEN, OSD_MISCCTL); | ||
656 | } | 906 | } |
657 | 907 | ||
658 | static void _osd_enable_vid_rgb888(struct osd_state *sd, | 908 | static void _osd_enable_vid_rgb888(struct osd_state *sd, |
@@ -665,13 +915,14 @@ static void _osd_enable_vid_rgb888(struct osd_state *sd, | |||
665 | * currently configured for RGB888 pixel format, as this routine will | 915 | * currently configured for RGB888 pixel format, as this routine will |
666 | * disable RGB888 pixel format for the other window. | 916 | * disable RGB888 pixel format for the other window. |
667 | */ | 917 | */ |
668 | if (layer == WIN_VID0) { | 918 | if (sd->vpbe_type == VPBE_VERSION_1) { |
669 | osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN, | 919 | if (layer == WIN_VID0) |
670 | OSD_MISCCTL_RGBEN, OSD_MISCCTL); | 920 | osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN, |
671 | } else if (layer == WIN_VID1) { | 921 | OSD_MISCCTL_RGBEN, OSD_MISCCTL); |
672 | osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN, | 922 | else if (layer == WIN_VID1) |
673 | OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN, | 923 | osd_modify(sd, OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN, |
674 | OSD_MISCCTL); | 924 | OSD_MISCCTL_RGBEN | OSD_MISCCTL_RGBWIN, |
925 | OSD_MISCCTL); | ||
675 | } | 926 | } |
676 | } | 927 | } |
677 | 928 | ||
@@ -697,9 +948,30 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer, | |||
697 | 948 | ||
698 | switch (layer) { | 949 | switch (layer) { |
699 | case WIN_OSD0: | 950 | case WIN_OSD0: |
700 | winmd_mask |= OSD_OSDWIN0MD_RGB0E; | 951 | if (sd->vpbe_type == VPBE_VERSION_1) { |
701 | if (lconfig->pixfmt == PIXFMT_RGB565) | 952 | winmd_mask |= OSD_OSDWIN0MD_RGB0E; |
702 | winmd |= OSD_OSDWIN0MD_RGB0E; | 953 | if (lconfig->pixfmt == PIXFMT_RGB565) |
954 | winmd |= OSD_OSDWIN0MD_RGB0E; | ||
955 | } else if ((sd->vpbe_type == VPBE_VERSION_3) || | ||
956 | (sd->vpbe_type == VPBE_VERSION_2)) { | ||
957 | winmd_mask |= OSD_OSDWIN0MD_BMP0MD; | ||
958 | switch (lconfig->pixfmt) { | ||
959 | case PIXFMT_RGB565: | ||
960 | winmd |= (1 << | ||
961 | OSD_OSDWIN0MD_BMP0MD_SHIFT); | ||
962 | break; | ||
963 | case PIXFMT_RGB888: | ||
964 | winmd |= (2 << OSD_OSDWIN0MD_BMP0MD_SHIFT); | ||
965 | _osd_enable_rgb888_pixblend(sd, OSDWIN_OSD0); | ||
966 | break; | ||
967 | case PIXFMT_YCbCrI: | ||
968 | case PIXFMT_YCrCbI: | ||
969 | winmd |= (3 << OSD_OSDWIN0MD_BMP0MD_SHIFT); | ||
970 | break; | ||
971 | default: | ||
972 | break; | ||
973 | } | ||
974 | } | ||
703 | 975 | ||
704 | winmd_mask |= OSD_OSDWIN0MD_BMW0 | OSD_OSDWIN0MD_OFF0; | 976 | winmd_mask |= OSD_OSDWIN0MD_BMW0 | OSD_OSDWIN0MD_OFF0; |
705 | 977 | ||
@@ -749,12 +1021,59 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer, | |||
749 | * For YUV420P format the register contents are | 1021 | * For YUV420P format the register contents are |
750 | * duplicated in both VID registers | 1022 | * duplicated in both VID registers |
751 | */ | 1023 | */ |
1024 | if ((sd->vpbe_type == VPBE_VERSION_2) && | ||
1025 | (lconfig->pixfmt == PIXFMT_NV12)) { | ||
1026 | /* other window also */ | ||
1027 | if (lconfig->interlaced) { | ||
1028 | winmd_mask |= OSD_VIDWINMD_VFF1; | ||
1029 | winmd |= OSD_VIDWINMD_VFF1; | ||
1030 | osd_modify(sd, winmd_mask, winmd, | ||
1031 | OSD_VIDWINMD); | ||
1032 | } | ||
1033 | |||
1034 | osd_modify(sd, OSD_MISCCTL_S420D, | ||
1035 | OSD_MISCCTL_S420D, OSD_MISCCTL); | ||
1036 | osd_write(sd, lconfig->line_length >> 5, | ||
1037 | OSD_VIDWIN1OFST); | ||
1038 | osd_write(sd, lconfig->xpos, OSD_VIDWIN1XP); | ||
1039 | osd_write(sd, lconfig->xsize, OSD_VIDWIN1XL); | ||
1040 | /* | ||
1041 | * if NV21 pixfmt and line length not 32B | ||
1042 | * aligned (e.g. NTSC), Need to set window | ||
1043 | * X pixel size to be 32B aligned as well | ||
1044 | */ | ||
1045 | if (lconfig->xsize % 32) { | ||
1046 | osd_write(sd, | ||
1047 | ((lconfig->xsize + 31) & ~31), | ||
1048 | OSD_VIDWIN1XL); | ||
1049 | osd_write(sd, | ||
1050 | ((lconfig->xsize + 31) & ~31), | ||
1051 | OSD_VIDWIN0XL); | ||
1052 | } | ||
1053 | } else if ((sd->vpbe_type == VPBE_VERSION_2) && | ||
1054 | (lconfig->pixfmt != PIXFMT_NV12)) { | ||
1055 | osd_modify(sd, OSD_MISCCTL_S420D, ~OSD_MISCCTL_S420D, | ||
1056 | OSD_MISCCTL); | ||
1057 | } | ||
1058 | |||
752 | if (lconfig->interlaced) { | 1059 | if (lconfig->interlaced) { |
753 | osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN0YP); | 1060 | osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN0YP); |
754 | osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN0YL); | 1061 | osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN0YL); |
1062 | if ((sd->vpbe_type == VPBE_VERSION_2) && | ||
1063 | lconfig->pixfmt == PIXFMT_NV12) { | ||
1064 | osd_write(sd, lconfig->ypos >> 1, | ||
1065 | OSD_VIDWIN1YP); | ||
1066 | osd_write(sd, lconfig->ysize >> 1, | ||
1067 | OSD_VIDWIN1YL); | ||
1068 | } | ||
755 | } else { | 1069 | } else { |
756 | osd_write(sd, lconfig->ypos, OSD_VIDWIN0YP); | 1070 | osd_write(sd, lconfig->ypos, OSD_VIDWIN0YP); |
757 | osd_write(sd, lconfig->ysize, OSD_VIDWIN0YL); | 1071 | osd_write(sd, lconfig->ysize, OSD_VIDWIN0YL); |
1072 | if ((sd->vpbe_type == VPBE_VERSION_2) && | ||
1073 | lconfig->pixfmt == PIXFMT_NV12) { | ||
1074 | osd_write(sd, lconfig->ypos, OSD_VIDWIN1YP); | ||
1075 | osd_write(sd, lconfig->ysize, OSD_VIDWIN1YL); | ||
1076 | } | ||
758 | } | 1077 | } |
759 | break; | 1078 | break; |
760 | case WIN_OSD1: | 1079 | case WIN_OSD1: |
@@ -764,14 +1083,43 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer, | |||
764 | * attribute mode to a normal mode. | 1083 | * attribute mode to a normal mode. |
765 | */ | 1084 | */ |
766 | if (lconfig->pixfmt == PIXFMT_OSD_ATTR) { | 1085 | if (lconfig->pixfmt == PIXFMT_OSD_ATTR) { |
767 | winmd_mask |= | 1086 | if (sd->vpbe_type == VPBE_VERSION_1) { |
768 | OSD_OSDWIN1MD_ATN1E | OSD_OSDWIN1MD_RGB1E | | 1087 | winmd_mask |= OSD_OSDWIN1MD_ATN1E | |
769 | OSD_OSDWIN1MD_CLUTS1 | | 1088 | OSD_OSDWIN1MD_RGB1E | OSD_OSDWIN1MD_CLUTS1 | |
770 | OSD_OSDWIN1MD_BLND1 | OSD_OSDWIN1MD_TE1; | 1089 | OSD_OSDWIN1MD_BLND1 | OSD_OSDWIN1MD_TE1; |
1090 | } else { | ||
1091 | winmd_mask |= OSD_OSDWIN1MD_BMP1MD | | ||
1092 | OSD_OSDWIN1MD_CLUTS1 | OSD_OSDWIN1MD_BLND1 | | ||
1093 | OSD_OSDWIN1MD_TE1; | ||
1094 | } | ||
771 | } else { | 1095 | } else { |
772 | winmd_mask |= OSD_OSDWIN1MD_RGB1E; | 1096 | if (sd->vpbe_type == VPBE_VERSION_1) { |
773 | if (lconfig->pixfmt == PIXFMT_RGB565) | 1097 | winmd_mask |= OSD_OSDWIN1MD_RGB1E; |
774 | winmd |= OSD_OSDWIN1MD_RGB1E; | 1098 | if (lconfig->pixfmt == PIXFMT_RGB565) |
1099 | winmd |= OSD_OSDWIN1MD_RGB1E; | ||
1100 | } else if ((sd->vpbe_type == VPBE_VERSION_3) | ||
1101 | || (sd->vpbe_type == VPBE_VERSION_2)) { | ||
1102 | winmd_mask |= OSD_OSDWIN1MD_BMP1MD; | ||
1103 | switch (lconfig->pixfmt) { | ||
1104 | case PIXFMT_RGB565: | ||
1105 | winmd |= | ||
1106 | (1 << OSD_OSDWIN1MD_BMP1MD_SHIFT); | ||
1107 | break; | ||
1108 | case PIXFMT_RGB888: | ||
1109 | winmd |= | ||
1110 | (2 << OSD_OSDWIN1MD_BMP1MD_SHIFT); | ||
1111 | _osd_enable_rgb888_pixblend(sd, | ||
1112 | OSDWIN_OSD1); | ||
1113 | break; | ||
1114 | case PIXFMT_YCbCrI: | ||
1115 | case PIXFMT_YCrCbI: | ||
1116 | winmd |= | ||
1117 | (3 << OSD_OSDWIN1MD_BMP1MD_SHIFT); | ||
1118 | break; | ||
1119 | default: | ||
1120 | break; | ||
1121 | } | ||
1122 | } | ||
775 | 1123 | ||
776 | winmd_mask |= OSD_OSDWIN1MD_BMW1; | 1124 | winmd_mask |= OSD_OSDWIN1MD_BMW1; |
777 | switch (lconfig->pixfmt) { | 1125 | switch (lconfig->pixfmt) { |
@@ -822,15 +1170,45 @@ static void _osd_set_layer_config(struct osd_state *sd, enum osd_layer layer, | |||
822 | * For YUV420P format the register contents are | 1170 | * For YUV420P format the register contents are |
823 | * duplicated in both VID registers | 1171 | * duplicated in both VID registers |
824 | */ | 1172 | */ |
825 | osd_modify(sd, OSD_MISCCTL_S420D, ~OSD_MISCCTL_S420D, | 1173 | if (sd->vpbe_type == VPBE_VERSION_2) { |
826 | OSD_MISCCTL); | 1174 | if (lconfig->pixfmt == PIXFMT_NV12) { |
1175 | /* other window also */ | ||
1176 | if (lconfig->interlaced) { | ||
1177 | winmd_mask |= OSD_VIDWINMD_VFF0; | ||
1178 | winmd |= OSD_VIDWINMD_VFF0; | ||
1179 | osd_modify(sd, winmd_mask, winmd, | ||
1180 | OSD_VIDWINMD); | ||
1181 | } | ||
1182 | osd_modify(sd, OSD_MISCCTL_S420D, | ||
1183 | OSD_MISCCTL_S420D, OSD_MISCCTL); | ||
1184 | osd_write(sd, lconfig->line_length >> 5, | ||
1185 | OSD_VIDWIN0OFST); | ||
1186 | osd_write(sd, lconfig->xpos, OSD_VIDWIN0XP); | ||
1187 | osd_write(sd, lconfig->xsize, OSD_VIDWIN0XL); | ||
1188 | } else { | ||
1189 | osd_modify(sd, OSD_MISCCTL_S420D, | ||
1190 | ~OSD_MISCCTL_S420D, OSD_MISCCTL); | ||
1191 | } | ||
1192 | } | ||
827 | 1193 | ||
828 | if (lconfig->interlaced) { | 1194 | if (lconfig->interlaced) { |
829 | osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN1YP); | 1195 | osd_write(sd, lconfig->ypos >> 1, OSD_VIDWIN1YP); |
830 | osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN1YL); | 1196 | osd_write(sd, lconfig->ysize >> 1, OSD_VIDWIN1YL); |
1197 | if ((sd->vpbe_type == VPBE_VERSION_2) && | ||
1198 | lconfig->pixfmt == PIXFMT_NV12) { | ||
1199 | osd_write(sd, lconfig->ypos >> 1, | ||
1200 | OSD_VIDWIN0YP); | ||
1201 | osd_write(sd, lconfig->ysize >> 1, | ||
1202 | OSD_VIDWIN0YL); | ||
1203 | } | ||
831 | } else { | 1204 | } else { |
832 | osd_write(sd, lconfig->ypos, OSD_VIDWIN1YP); | 1205 | osd_write(sd, lconfig->ypos, OSD_VIDWIN1YP); |
833 | osd_write(sd, lconfig->ysize, OSD_VIDWIN1YL); | 1206 | osd_write(sd, lconfig->ysize, OSD_VIDWIN1YL); |
1207 | if ((sd->vpbe_type == VPBE_VERSION_2) && | ||
1208 | lconfig->pixfmt == PIXFMT_NV12) { | ||
1209 | osd_write(sd, lconfig->ypos, OSD_VIDWIN0YP); | ||
1210 | osd_write(sd, lconfig->ysize, OSD_VIDWIN0YL); | ||
1211 | } | ||
834 | } | 1212 | } |
835 | break; | 1213 | break; |
836 | } | 1214 | } |
@@ -1089,6 +1467,11 @@ static void _osd_init(struct osd_state *sd) | |||
1089 | osd_write(sd, 0, OSD_OSDWIN1MD); | 1467 | osd_write(sd, 0, OSD_OSDWIN1MD); |
1090 | osd_write(sd, 0, OSD_RECTCUR); | 1468 | osd_write(sd, 0, OSD_RECTCUR); |
1091 | osd_write(sd, 0, OSD_MISCCTL); | 1469 | osd_write(sd, 0, OSD_MISCCTL); |
1470 | if (sd->vpbe_type == VPBE_VERSION_3) { | ||
1471 | osd_write(sd, 0, OSD_VBNDRY); | ||
1472 | osd_write(sd, 0, OSD_EXTMODE); | ||
1473 | osd_write(sd, OSD_MISCCTL_DMANG, OSD_MISCCTL); | ||
1474 | } | ||
1092 | } | 1475 | } |
1093 | 1476 | ||
1094 | static void osd_set_left_margin(struct osd_state *sd, u32 val) | 1477 | static void osd_set_left_margin(struct osd_state *sd, u32 val) |
@@ -1110,6 +1493,14 @@ static int osd_initialize(struct osd_state *osd) | |||
1110 | /* set default Cb/Cr order */ | 1493 | /* set default Cb/Cr order */ |
1111 | osd->yc_pixfmt = PIXFMT_YCbCrI; | 1494 | osd->yc_pixfmt = PIXFMT_YCbCrI; |
1112 | 1495 | ||
1496 | if (osd->vpbe_type == VPBE_VERSION_3) { | ||
1497 | /* | ||
1498 | * ROM CLUT1 on the DM355 is similar (identical?) to ROM CLUT0 | ||
1499 | * on the DM6446, so make ROM_CLUT1 the default on the DM355. | ||
1500 | */ | ||
1501 | osd->rom_clut = ROM_CLUT1; | ||
1502 | } | ||
1503 | |||
1113 | _osd_set_field_inversion(osd, osd->field_inversion); | 1504 | _osd_set_field_inversion(osd, osd->field_inversion); |
1114 | _osd_set_rom_clut(osd, osd->rom_clut); | 1505 | _osd_set_rom_clut(osd, osd->rom_clut); |
1115 | 1506 | ||
@@ -1208,23 +1599,7 @@ static struct platform_driver osd_driver = { | |||
1208 | }, | 1599 | }, |
1209 | }; | 1600 | }; |
1210 | 1601 | ||
1211 | static int osd_init(void) | 1602 | module_platform_driver(osd_driver); |
1212 | { | ||
1213 | if (platform_driver_register(&osd_driver)) { | ||
1214 | printk(KERN_ERR "Unable to register davinci osd driver\n"); | ||
1215 | return -ENODEV; | ||
1216 | } | ||
1217 | |||
1218 | return 0; | ||
1219 | } | ||
1220 | |||
1221 | static void osd_exit(void) | ||
1222 | { | ||
1223 | platform_driver_unregister(&osd_driver); | ||
1224 | } | ||
1225 | |||
1226 | module_init(osd_init); | ||
1227 | module_exit(osd_exit); | ||
1228 | 1603 | ||
1229 | MODULE_LICENSE("GPL"); | 1604 | MODULE_LICENSE("GPL"); |
1230 | MODULE_DESCRIPTION("DaVinci OSD Manager Driver"); | 1605 | MODULE_DESCRIPTION("DaVinci OSD Manager Driver"); |
diff --git a/drivers/media/video/davinci/vpbe_venc.c b/drivers/media/video/davinci/vpbe_venc.c index 03a3e5c65ee7..00e80f59d5d5 100644 --- a/drivers/media/video/davinci/vpbe_venc.c +++ b/drivers/media/video/davinci/vpbe_venc.c | |||
@@ -99,6 +99,8 @@ static inline u32 vdaccfg_write(struct v4l2_subdev *sd, u32 val) | |||
99 | return val; | 99 | return val; |
100 | } | 100 | } |
101 | 101 | ||
102 | #define VDAC_COMPONENT 0x543 | ||
103 | #define VDAC_S_VIDEO 0x210 | ||
102 | /* This function sets the dac of the VPBE for various outputs | 104 | /* This function sets the dac of the VPBE for various outputs |
103 | */ | 105 | */ |
104 | static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index) | 106 | static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index) |
@@ -109,11 +111,12 @@ static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index) | |||
109 | venc_write(sd, VENC_DACSEL, 0); | 111 | venc_write(sd, VENC_DACSEL, 0); |
110 | break; | 112 | break; |
111 | case 1: | 113 | case 1: |
112 | v4l2_dbg(debug, 1, sd, "Setting output to S-Video\n"); | 114 | v4l2_dbg(debug, 1, sd, "Setting output to Component\n"); |
113 | venc_write(sd, VENC_DACSEL, 0x210); | 115 | venc_write(sd, VENC_DACSEL, VDAC_COMPONENT); |
114 | break; | 116 | break; |
115 | case 2: | 117 | case 2: |
116 | venc_write(sd, VENC_DACSEL, 0x543); | 118 | v4l2_dbg(debug, 1, sd, "Setting output to S-video\n"); |
119 | venc_write(sd, VENC_DACSEL, VDAC_S_VIDEO); | ||
117 | break; | 120 | break; |
118 | default: | 121 | default: |
119 | return -EINVAL; | 122 | return -EINVAL; |
@@ -124,6 +127,8 @@ static int venc_set_dac(struct v4l2_subdev *sd, u32 out_index) | |||
124 | 127 | ||
125 | static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable) | 128 | static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable) |
126 | { | 129 | { |
130 | struct venc_state *venc = to_state(sd); | ||
131 | struct venc_platform_data *pdata = venc->pdata; | ||
127 | v4l2_dbg(debug, 2, sd, "venc_enabledigitaloutput\n"); | 132 | v4l2_dbg(debug, 2, sd, "venc_enabledigitaloutput\n"); |
128 | 133 | ||
129 | if (benable) { | 134 | if (benable) { |
@@ -155,7 +160,8 @@ static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable) | |||
155 | 160 | ||
156 | /* Disable LCD output control (accepting default polarity) */ | 161 | /* Disable LCD output control (accepting default polarity) */ |
157 | venc_write(sd, VENC_LCDOUT, 0); | 162 | venc_write(sd, VENC_LCDOUT, 0); |
158 | venc_write(sd, VENC_CMPNT, 0x100); | 163 | if (pdata->venc_type != VPBE_VERSION_3) |
164 | venc_write(sd, VENC_CMPNT, 0x100); | ||
159 | venc_write(sd, VENC_HSPLS, 0); | 165 | venc_write(sd, VENC_HSPLS, 0); |
160 | venc_write(sd, VENC_HINT, 0); | 166 | venc_write(sd, VENC_HINT, 0); |
161 | venc_write(sd, VENC_HSTART, 0); | 167 | venc_write(sd, VENC_HSTART, 0); |
@@ -178,11 +184,14 @@ static void venc_enabledigitaloutput(struct v4l2_subdev *sd, int benable) | |||
178 | } | 184 | } |
179 | } | 185 | } |
180 | 186 | ||
187 | #define VDAC_CONFIG_SD_V3 0x0E21A6B6 | ||
188 | #define VDAC_CONFIG_SD_V2 0x081141CF | ||
181 | /* | 189 | /* |
182 | * setting NTSC mode | 190 | * setting NTSC mode |
183 | */ | 191 | */ |
184 | static int venc_set_ntsc(struct v4l2_subdev *sd) | 192 | static int venc_set_ntsc(struct v4l2_subdev *sd) |
185 | { | 193 | { |
194 | u32 val; | ||
186 | struct venc_state *venc = to_state(sd); | 195 | struct venc_state *venc = to_state(sd); |
187 | struct venc_platform_data *pdata = venc->pdata; | 196 | struct venc_platform_data *pdata = venc->pdata; |
188 | 197 | ||
@@ -195,12 +204,22 @@ static int venc_set_ntsc(struct v4l2_subdev *sd) | |||
195 | 204 | ||
196 | venc_enabledigitaloutput(sd, 0); | 205 | venc_enabledigitaloutput(sd, 0); |
197 | 206 | ||
198 | /* to set VENC CLK DIV to 1 - final clock is 54 MHz */ | 207 | if (pdata->venc_type == VPBE_VERSION_3) { |
199 | venc_modify(sd, VENC_VIDCTL, 0, 1 << 1); | 208 | venc_write(sd, VENC_CLKCTL, 0x01); |
200 | /* Set REC656 Mode */ | 209 | venc_write(sd, VENC_VIDCTL, 0); |
201 | venc_write(sd, VENC_YCCCTL, 0x1); | 210 | val = vdaccfg_write(sd, VDAC_CONFIG_SD_V3); |
202 | venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAFRQ); | 211 | } else if (pdata->venc_type == VPBE_VERSION_2) { |
203 | venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAUPS); | 212 | venc_write(sd, VENC_CLKCTL, 0x01); |
213 | venc_write(sd, VENC_VIDCTL, 0); | ||
214 | vdaccfg_write(sd, VDAC_CONFIG_SD_V2); | ||
215 | } else { | ||
216 | /* to set VENC CLK DIV to 1 - final clock is 54 MHz */ | ||
217 | venc_modify(sd, VENC_VIDCTL, 0, 1 << 1); | ||
218 | /* Set REC656 Mode */ | ||
219 | venc_write(sd, VENC_YCCCTL, 0x1); | ||
220 | venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAFRQ); | ||
221 | venc_modify(sd, VENC_VDPRO, 0, VENC_VDPRO_DAUPS); | ||
222 | } | ||
204 | 223 | ||
205 | venc_write(sd, VENC_VMOD, 0); | 224 | venc_write(sd, VENC_VMOD, 0); |
206 | venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT), | 225 | venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT), |
@@ -220,6 +239,7 @@ static int venc_set_ntsc(struct v4l2_subdev *sd) | |||
220 | static int venc_set_pal(struct v4l2_subdev *sd) | 239 | static int venc_set_pal(struct v4l2_subdev *sd) |
221 | { | 240 | { |
222 | struct venc_state *venc = to_state(sd); | 241 | struct venc_state *venc = to_state(sd); |
242 | struct venc_platform_data *pdata = venc->pdata; | ||
223 | 243 | ||
224 | v4l2_dbg(debug, 2, sd, "venc_set_pal\n"); | 244 | v4l2_dbg(debug, 2, sd, "venc_set_pal\n"); |
225 | 245 | ||
@@ -230,10 +250,20 @@ static int venc_set_pal(struct v4l2_subdev *sd) | |||
230 | 250 | ||
231 | venc_enabledigitaloutput(sd, 0); | 251 | venc_enabledigitaloutput(sd, 0); |
232 | 252 | ||
233 | /* to set VENC CLK DIV to 1 - final clock is 54 MHz */ | 253 | if (pdata->venc_type == VPBE_VERSION_3) { |
234 | venc_modify(sd, VENC_VIDCTL, 0, 1 << 1); | 254 | venc_write(sd, VENC_CLKCTL, 0x1); |
235 | /* Set REC656 Mode */ | 255 | venc_write(sd, VENC_VIDCTL, 0); |
236 | venc_write(sd, VENC_YCCCTL, 0x1); | 256 | vdaccfg_write(sd, VDAC_CONFIG_SD_V3); |
257 | } else if (pdata->venc_type == VPBE_VERSION_2) { | ||
258 | venc_write(sd, VENC_CLKCTL, 0x1); | ||
259 | venc_write(sd, VENC_VIDCTL, 0); | ||
260 | vdaccfg_write(sd, VDAC_CONFIG_SD_V2); | ||
261 | } else { | ||
262 | /* to set VENC CLK DIV to 1 - final clock is 54 MHz */ | ||
263 | venc_modify(sd, VENC_VIDCTL, 0, 1 << 1); | ||
264 | /* Set REC656 Mode */ | ||
265 | venc_write(sd, VENC_YCCCTL, 0x1); | ||
266 | } | ||
237 | 267 | ||
238 | venc_modify(sd, VENC_SYNCCTL, 1 << VENC_SYNCCTL_OVD_SHIFT, | 268 | venc_modify(sd, VENC_SYNCCTL, 1 << VENC_SYNCCTL_OVD_SHIFT, |
239 | VENC_SYNCCTL_OVD); | 269 | VENC_SYNCCTL_OVD); |
@@ -252,6 +282,7 @@ static int venc_set_pal(struct v4l2_subdev *sd) | |||
252 | return 0; | 282 | return 0; |
253 | } | 283 | } |
254 | 284 | ||
285 | #define VDAC_CONFIG_HD_V2 0x081141EF | ||
255 | /* | 286 | /* |
256 | * venc_set_480p59_94 | 287 | * venc_set_480p59_94 |
257 | * | 288 | * |
@@ -263,6 +294,9 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd) | |||
263 | struct venc_platform_data *pdata = venc->pdata; | 294 | struct venc_platform_data *pdata = venc->pdata; |
264 | 295 | ||
265 | v4l2_dbg(debug, 2, sd, "venc_set_480p59_94\n"); | 296 | v4l2_dbg(debug, 2, sd, "venc_set_480p59_94\n"); |
297 | if ((pdata->venc_type != VPBE_VERSION_1) && | ||
298 | (pdata->venc_type != VPBE_VERSION_2)) | ||
299 | return -EINVAL; | ||
266 | 300 | ||
267 | /* Setup clock at VPSS & VENC for SD */ | 301 | /* Setup clock at VPSS & VENC for SD */ |
268 | if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_480P59_94) < 0) | 302 | if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_480P59_94) < 0) |
@@ -270,12 +304,18 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd) | |||
270 | 304 | ||
271 | venc_enabledigitaloutput(sd, 0); | 305 | venc_enabledigitaloutput(sd, 0); |
272 | 306 | ||
307 | if (pdata->venc_type == VPBE_VERSION_2) | ||
308 | vdaccfg_write(sd, VDAC_CONFIG_HD_V2); | ||
273 | venc_write(sd, VENC_OSDCLK0, 0); | 309 | venc_write(sd, VENC_OSDCLK0, 0); |
274 | venc_write(sd, VENC_OSDCLK1, 1); | 310 | venc_write(sd, VENC_OSDCLK1, 1); |
275 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ, | 311 | |
276 | VENC_VDPRO_DAFRQ); | 312 | if (pdata->venc_type == VPBE_VERSION_1) { |
277 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS, | 313 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ, |
278 | VENC_VDPRO_DAUPS); | 314 | VENC_VDPRO_DAFRQ); |
315 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS, | ||
316 | VENC_VDPRO_DAUPS); | ||
317 | } | ||
318 | |||
279 | venc_write(sd, VENC_VMOD, 0); | 319 | venc_write(sd, VENC_VMOD, 0); |
280 | venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT), | 320 | venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT), |
281 | VENC_VMOD_VIE); | 321 | VENC_VMOD_VIE); |
@@ -302,19 +342,27 @@ static int venc_set_576p50(struct v4l2_subdev *sd) | |||
302 | 342 | ||
303 | v4l2_dbg(debug, 2, sd, "venc_set_576p50\n"); | 343 | v4l2_dbg(debug, 2, sd, "venc_set_576p50\n"); |
304 | 344 | ||
345 | if ((pdata->venc_type != VPBE_VERSION_1) && | ||
346 | (pdata->venc_type != VPBE_VERSION_2)) | ||
347 | return -EINVAL; | ||
305 | /* Setup clock at VPSS & VENC for SD */ | 348 | /* Setup clock at VPSS & VENC for SD */ |
306 | if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_576P50) < 0) | 349 | if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_576P50) < 0) |
307 | return -EINVAL; | 350 | return -EINVAL; |
308 | 351 | ||
309 | venc_enabledigitaloutput(sd, 0); | 352 | venc_enabledigitaloutput(sd, 0); |
310 | 353 | ||
354 | if (pdata->venc_type == VPBE_VERSION_2) | ||
355 | vdaccfg_write(sd, VDAC_CONFIG_HD_V2); | ||
356 | |||
311 | venc_write(sd, VENC_OSDCLK0, 0); | 357 | venc_write(sd, VENC_OSDCLK0, 0); |
312 | venc_write(sd, VENC_OSDCLK1, 1); | 358 | venc_write(sd, VENC_OSDCLK1, 1); |
313 | 359 | ||
314 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ, | 360 | if (pdata->venc_type == VPBE_VERSION_1) { |
315 | VENC_VDPRO_DAFRQ); | 361 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAFRQ, |
316 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS, | 362 | VENC_VDPRO_DAFRQ); |
317 | VENC_VDPRO_DAUPS); | 363 | venc_modify(sd, VENC_VDPRO, VENC_VDPRO_DAUPS, |
364 | VENC_VDPRO_DAUPS); | ||
365 | } | ||
318 | 366 | ||
319 | venc_write(sd, VENC_VMOD, 0); | 367 | venc_write(sd, VENC_VMOD, 0); |
320 | venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT), | 368 | venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT), |
@@ -330,6 +378,63 @@ static int venc_set_576p50(struct v4l2_subdev *sd) | |||
330 | return 0; | 378 | return 0; |
331 | } | 379 | } |
332 | 380 | ||
381 | /* | ||
382 | * venc_set_720p60_internal - Setup 720p60 in venc for dm365 only | ||
383 | */ | ||
384 | static int venc_set_720p60_internal(struct v4l2_subdev *sd) | ||
385 | { | ||
386 | struct venc_state *venc = to_state(sd); | ||
387 | struct venc_platform_data *pdata = venc->pdata; | ||
388 | |||
389 | if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_720P60) < 0) | ||
390 | return -EINVAL; | ||
391 | |||
392 | venc_enabledigitaloutput(sd, 0); | ||
393 | |||
394 | venc_write(sd, VENC_OSDCLK0, 0); | ||
395 | venc_write(sd, VENC_OSDCLK1, 1); | ||
396 | |||
397 | venc_write(sd, VENC_VMOD, 0); | ||
398 | /* DM365 component HD mode */ | ||
399 | venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT), | ||
400 | VENC_VMOD_VIE); | ||
401 | venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD); | ||
402 | venc_modify(sd, VENC_VMOD, (HDTV_720P << VENC_VMOD_TVTYP_SHIFT), | ||
403 | VENC_VMOD_TVTYP); | ||
404 | venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC); | ||
405 | venc_write(sd, VENC_XHINTVL, 0); | ||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | /* | ||
410 | * venc_set_1080i30_internal - Setup 1080i30 in venc for dm365 only | ||
411 | */ | ||
412 | static int venc_set_1080i30_internal(struct v4l2_subdev *sd) | ||
413 | { | ||
414 | struct venc_state *venc = to_state(sd); | ||
415 | struct venc_platform_data *pdata = venc->pdata; | ||
416 | |||
417 | if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_1080P30) < 0) | ||
418 | return -EINVAL; | ||
419 | |||
420 | venc_enabledigitaloutput(sd, 0); | ||
421 | |||
422 | venc_write(sd, VENC_OSDCLK0, 0); | ||
423 | venc_write(sd, VENC_OSDCLK1, 1); | ||
424 | |||
425 | |||
426 | venc_write(sd, VENC_VMOD, 0); | ||
427 | /* DM365 component HD mode */ | ||
428 | venc_modify(sd, VENC_VMOD, (1 << VENC_VMOD_VIE_SHIFT), | ||
429 | VENC_VMOD_VIE); | ||
430 | venc_modify(sd, VENC_VMOD, VENC_VMOD_HDMD, VENC_VMOD_HDMD); | ||
431 | venc_modify(sd, VENC_VMOD, (HDTV_1080I << VENC_VMOD_TVTYP_SHIFT), | ||
432 | VENC_VMOD_TVTYP); | ||
433 | venc_modify(sd, VENC_VMOD, VENC_VMOD_VENC, VENC_VMOD_VENC); | ||
434 | venc_write(sd, VENC_XHINTVL, 0); | ||
435 | return 0; | ||
436 | } | ||
437 | |||
333 | static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm) | 438 | static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm) |
334 | { | 439 | { |
335 | v4l2_dbg(debug, 1, sd, "venc_s_std_output\n"); | 440 | v4l2_dbg(debug, 1, sd, "venc_s_std_output\n"); |
@@ -345,13 +450,30 @@ static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm) | |||
345 | static int venc_s_dv_preset(struct v4l2_subdev *sd, | 450 | static int venc_s_dv_preset(struct v4l2_subdev *sd, |
346 | struct v4l2_dv_preset *dv_preset) | 451 | struct v4l2_dv_preset *dv_preset) |
347 | { | 452 | { |
453 | struct venc_state *venc = to_state(sd); | ||
454 | int ret; | ||
455 | |||
348 | v4l2_dbg(debug, 1, sd, "venc_s_dv_preset\n"); | 456 | v4l2_dbg(debug, 1, sd, "venc_s_dv_preset\n"); |
349 | 457 | ||
350 | if (dv_preset->preset == V4L2_DV_576P50) | 458 | if (dv_preset->preset == V4L2_DV_576P50) |
351 | return venc_set_576p50(sd); | 459 | return venc_set_576p50(sd); |
352 | else if (dv_preset->preset == V4L2_DV_480P59_94) | 460 | else if (dv_preset->preset == V4L2_DV_480P59_94) |
353 | return venc_set_480p59_94(sd); | 461 | return venc_set_480p59_94(sd); |
354 | 462 | else if ((dv_preset->preset == V4L2_DV_720P60) && | |
463 | (venc->pdata->venc_type == VPBE_VERSION_2)) { | ||
464 | /* TBD setup internal 720p mode here */ | ||
465 | ret = venc_set_720p60_internal(sd); | ||
466 | /* for DM365 VPBE, there is DAC inside */ | ||
467 | vdaccfg_write(sd, VDAC_CONFIG_HD_V2); | ||
468 | return ret; | ||
469 | } else if ((dv_preset->preset == V4L2_DV_1080I30) && | ||
470 | (venc->pdata->venc_type == VPBE_VERSION_2)) { | ||
471 | /* TBD setup internal 1080i mode here */ | ||
472 | ret = venc_set_1080i30_internal(sd); | ||
473 | /* for DM365 VPBE, there is DAC inside */ | ||
474 | vdaccfg_write(sd, VDAC_CONFIG_HD_V2); | ||
475 | return ret; | ||
476 | } | ||
355 | return -EINVAL; | 477 | return -EINVAL; |
356 | } | 478 | } |
357 | 479 | ||
@@ -508,11 +630,41 @@ static int venc_probe(struct platform_device *pdev) | |||
508 | goto release_venc_mem_region; | 630 | goto release_venc_mem_region; |
509 | } | 631 | } |
510 | 632 | ||
633 | if (venc->pdata->venc_type != VPBE_VERSION_1) { | ||
634 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
635 | if (!res) { | ||
636 | dev_err(venc->pdev, | ||
637 | "Unable to get VDAC_CONFIG address map\n"); | ||
638 | ret = -ENODEV; | ||
639 | goto unmap_venc_io; | ||
640 | } | ||
641 | |||
642 | if (!request_mem_region(res->start, | ||
643 | resource_size(res), "venc")) { | ||
644 | dev_err(venc->pdev, | ||
645 | "Unable to reserve VDAC_CONFIG MMIO region\n"); | ||
646 | ret = -ENODEV; | ||
647 | goto unmap_venc_io; | ||
648 | } | ||
649 | |||
650 | venc->vdaccfg_reg = ioremap_nocache(res->start, | ||
651 | resource_size(res)); | ||
652 | if (!venc->vdaccfg_reg) { | ||
653 | dev_err(venc->pdev, | ||
654 | "Unable to map VDAC_CONFIG IO space\n"); | ||
655 | ret = -ENODEV; | ||
656 | goto release_vdaccfg_mem_region; | ||
657 | } | ||
658 | } | ||
511 | spin_lock_init(&venc->lock); | 659 | spin_lock_init(&venc->lock); |
512 | platform_set_drvdata(pdev, venc); | 660 | platform_set_drvdata(pdev, venc); |
513 | dev_notice(venc->pdev, "VENC sub device probe success\n"); | 661 | dev_notice(venc->pdev, "VENC sub device probe success\n"); |
514 | return 0; | 662 | return 0; |
515 | 663 | ||
664 | release_vdaccfg_mem_region: | ||
665 | release_mem_region(res->start, resource_size(res)); | ||
666 | unmap_venc_io: | ||
667 | iounmap(venc->venc_base); | ||
516 | release_venc_mem_region: | 668 | release_venc_mem_region: |
517 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 669 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
518 | release_mem_region(res->start, resource_size(res)); | 670 | release_mem_region(res->start, resource_size(res)); |
@@ -529,6 +681,11 @@ static int venc_remove(struct platform_device *pdev) | |||
529 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 681 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
530 | iounmap((void *)venc->venc_base); | 682 | iounmap((void *)venc->venc_base); |
531 | release_mem_region(res->start, resource_size(res)); | 683 | release_mem_region(res->start, resource_size(res)); |
684 | if (venc->pdata->venc_type != VPBE_VERSION_1) { | ||
685 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
686 | iounmap((void *)venc->vdaccfg_reg); | ||
687 | release_mem_region(res->start, resource_size(res)); | ||
688 | } | ||
532 | kfree(venc); | 689 | kfree(venc); |
533 | 690 | ||
534 | return 0; | 691 | return 0; |
@@ -543,23 +700,7 @@ static struct platform_driver venc_driver = { | |||
543 | }, | 700 | }, |
544 | }; | 701 | }; |
545 | 702 | ||
546 | static int venc_init(void) | 703 | module_platform_driver(venc_driver); |
547 | { | ||
548 | if (platform_driver_register(&venc_driver)) { | ||
549 | printk(KERN_ERR "Unable to register venc driver\n"); | ||
550 | return -ENODEV; | ||
551 | } | ||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | static void venc_exit(void) | ||
556 | { | ||
557 | platform_driver_unregister(&venc_driver); | ||
558 | return; | ||
559 | } | ||
560 | |||
561 | module_init(venc_init); | ||
562 | module_exit(venc_exit); | ||
563 | 704 | ||
564 | MODULE_LICENSE("GPL"); | 705 | MODULE_LICENSE("GPL"); |
565 | MODULE_DESCRIPTION("VPBE VENC Driver"); | 706 | MODULE_DESCRIPTION("VPBE VENC Driver"); |
diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 5b38fc93ff28..20cf271a774b 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c | |||
@@ -2076,20 +2076,4 @@ static struct platform_driver vpfe_driver = { | |||
2076 | .remove = __devexit_p(vpfe_remove), | 2076 | .remove = __devexit_p(vpfe_remove), |
2077 | }; | 2077 | }; |
2078 | 2078 | ||
2079 | static __init int vpfe_init(void) | 2079 | module_platform_driver(vpfe_driver); |
2080 | { | ||
2081 | printk(KERN_NOTICE "vpfe_init\n"); | ||
2082 | /* Register driver to the kernel */ | ||
2083 | return platform_driver_register(&vpfe_driver); | ||
2084 | } | ||
2085 | |||
2086 | /* | ||
2087 | * vpfe_cleanup : This function un-registers device driver | ||
2088 | */ | ||
2089 | static void vpfe_cleanup(void) | ||
2090 | { | ||
2091 | platform_driver_unregister(&vpfe_driver); | ||
2092 | } | ||
2093 | |||
2094 | module_init(vpfe_init); | ||
2095 | module_exit(vpfe_cleanup); | ||
diff --git a/drivers/media/video/davinci/vpif_capture.c b/drivers/media/video/davinci/vpif_capture.c index 49e4deb50043..6504e40a31dd 100644 --- a/drivers/media/video/davinci/vpif_capture.c +++ b/drivers/media/video/davinci/vpif_capture.c | |||
@@ -2177,6 +2177,12 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
2177 | return err; | 2177 | return err; |
2178 | } | 2178 | } |
2179 | 2179 | ||
2180 | err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev); | ||
2181 | if (err) { | ||
2182 | v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n"); | ||
2183 | return err; | ||
2184 | } | ||
2185 | |||
2180 | k = 0; | 2186 | k = 0; |
2181 | while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) { | 2187 | while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) { |
2182 | for (i = res->start; i <= res->end; i++) { | 2188 | for (i = res->start; i <= res->end; i++) { |
@@ -2246,12 +2252,6 @@ static __init int vpif_probe(struct platform_device *pdev) | |||
2246 | goto probe_out; | 2252 | goto probe_out; |
2247 | } | 2253 | } |
2248 | 2254 | ||
2249 | err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev); | ||
2250 | if (err) { | ||
2251 | v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n"); | ||
2252 | goto probe_subdev_out; | ||
2253 | } | ||
2254 | |||
2255 | for (i = 0; i < subdev_count; i++) { | 2255 | for (i = 0; i < subdev_count; i++) { |
2256 | subdevdata = &config->subdev_info[i]; | 2256 | subdevdata = &config->subdev_info[i]; |
2257 | vpif_obj.sd[i] = | 2257 | vpif_obj.sd[i] = |
@@ -2281,7 +2281,6 @@ probe_subdev_out: | |||
2281 | 2281 | ||
2282 | j = VPIF_CAPTURE_MAX_DEVICES; | 2282 | j = VPIF_CAPTURE_MAX_DEVICES; |
2283 | probe_out: | 2283 | probe_out: |
2284 | v4l2_device_unregister(&vpif_obj.v4l2_dev); | ||
2285 | for (k = 0; k < j; k++) { | 2284 | for (k = 0; k < j; k++) { |
2286 | /* Get the pointer to the channel object */ | 2285 | /* Get the pointer to the channel object */ |
2287 | ch = vpif_obj.dev[k]; | 2286 | ch = vpif_obj.dev[k]; |
@@ -2303,6 +2302,7 @@ vpif_int_err: | |||
2303 | if (res) | 2302 | if (res) |
2304 | i = res->end; | 2303 | i = res->end; |
2305 | } | 2304 | } |
2305 | v4l2_device_unregister(&vpif_obj.v4l2_dev); | ||
2306 | return err; | 2306 | return err; |
2307 | } | 2307 | } |
2308 | 2308 | ||
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index cff0768afbf5..e2a7b77c39c7 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c | |||
@@ -193,7 +193,7 @@ static int em28xx_init_audio_isoc(struct em28xx *dev) | |||
193 | 193 | ||
194 | urb->dev = dev->udev; | 194 | urb->dev = dev->udev; |
195 | urb->context = dev; | 195 | urb->context = dev; |
196 | urb->pipe = usb_rcvisocpipe(dev->udev, 0x83); | 196 | urb->pipe = usb_rcvisocpipe(dev->udev, EM28XX_EP_AUDIO); |
197 | urb->transfer_flags = URB_ISO_ASAP; | 197 | urb->transfer_flags = URB_ISO_ASAP; |
198 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; | 198 | urb->transfer_buffer = dev->adev.transfer_buffer[i]; |
199 | urb->interval = 1; | 199 | urb->interval = 1; |
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 93807dcf944e..4561cd89938d 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c | |||
@@ -336,6 +336,23 @@ static struct em28xx_reg_seq pctv_460e[] = { | |||
336 | { -1, -1, -1, -1}, | 336 | { -1, -1, -1, -1}, |
337 | }; | 337 | }; |
338 | 338 | ||
339 | #if 0 | ||
340 | static struct em28xx_reg_seq hauppauge_930c_gpio[] = { | ||
341 | {EM2874_R80_GPIO, 0x6f, 0xff, 10}, | ||
342 | {EM2874_R80_GPIO, 0x4f, 0xff, 10}, /* xc5000 reset */ | ||
343 | {EM2874_R80_GPIO, 0x6f, 0xff, 10}, | ||
344 | {EM2874_R80_GPIO, 0x4f, 0xff, 10}, | ||
345 | { -1, -1, -1, -1}, | ||
346 | }; | ||
347 | |||
348 | static struct em28xx_reg_seq hauppauge_930c_digital[] = { | ||
349 | {EM2874_R80_GPIO, 0xf6, 0xff, 10}, | ||
350 | {EM2874_R80_GPIO, 0xe6, 0xff, 100}, | ||
351 | {EM2874_R80_GPIO, 0xa6, 0xff, 10}, | ||
352 | { -1, -1, -1, -1}, | ||
353 | }; | ||
354 | #endif | ||
355 | |||
339 | /* | 356 | /* |
340 | * Board definitions | 357 | * Board definitions |
341 | */ | 358 | */ |
@@ -839,6 +856,10 @@ struct em28xx_board em28xx_boards[] = { | |||
839 | [EM2870_BOARD_KWORLD_355U] = { | 856 | [EM2870_BOARD_KWORLD_355U] = { |
840 | .name = "Kworld 355 U DVB-T", | 857 | .name = "Kworld 355 U DVB-T", |
841 | .valid = EM28XX_BOARD_NOT_VALIDATED, | 858 | .valid = EM28XX_BOARD_NOT_VALIDATED, |
859 | .tuner_type = TUNER_ABSENT, | ||
860 | .tuner_gpio = default_tuner_gpio, | ||
861 | .has_dvb = 1, | ||
862 | .dvb_gpio = default_digital, | ||
842 | }, | 863 | }, |
843 | [EM2870_BOARD_PINNACLE_PCTV_DVB] = { | 864 | [EM2870_BOARD_PINNACLE_PCTV_DVB] = { |
844 | .name = "Pinnacle PCTV DVB-T", | 865 | .name = "Pinnacle PCTV DVB-T", |
@@ -887,6 +908,37 @@ struct em28xx_board em28xx_boards[] = { | |||
887 | .tuner_addr = 0x41, | 908 | .tuner_addr = 0x41, |
888 | .dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */ | 909 | .dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */ |
889 | .tuner_gpio = terratec_h5_gpio, | 910 | .tuner_gpio = terratec_h5_gpio, |
911 | #else | ||
912 | .tuner_type = TUNER_ABSENT, | ||
913 | #endif | ||
914 | .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | | ||
915 | EM28XX_I2C_CLK_WAIT_ENABLE | | ||
916 | EM28XX_I2C_FREQ_400_KHZ, | ||
917 | }, | ||
918 | [EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C] = { | ||
919 | .name = "Hauppauge WinTV HVR 930C", | ||
920 | .has_dvb = 1, | ||
921 | #if 0 /* FIXME: Add analog support */ | ||
922 | .tuner_type = TUNER_XC5000, | ||
923 | .tuner_addr = 0x41, | ||
924 | .dvb_gpio = hauppauge_930c_digital, | ||
925 | .tuner_gpio = hauppauge_930c_gpio, | ||
926 | #else | ||
927 | .tuner_type = TUNER_ABSENT, | ||
928 | #endif | ||
929 | .ir_codes = RC_MAP_HAUPPAUGE, | ||
930 | .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | | ||
931 | EM28XX_I2C_CLK_WAIT_ENABLE | | ||
932 | EM28XX_I2C_FREQ_400_KHZ, | ||
933 | }, | ||
934 | [EM2884_BOARD_CINERGY_HTC_STICK] = { | ||
935 | .name = "Terratec Cinergy HTC Stick", | ||
936 | .has_dvb = 1, | ||
937 | #if 0 | ||
938 | .tuner_type = TUNER_PHILIPS_TDA8290, | ||
939 | .tuner_addr = 0x41, | ||
940 | .dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */ | ||
941 | .tuner_gpio = terratec_h5_gpio, | ||
890 | #endif | 942 | #endif |
891 | .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | | 943 | .i2c_speed = EM2874_I2C_SECONDARY_BUS_SELECT | |
892 | EM28XX_I2C_CLK_WAIT_ENABLE | | 944 | EM28XX_I2C_CLK_WAIT_ENABLE | |
@@ -1127,7 +1179,7 @@ struct em28xx_board em28xx_boards[] = { | |||
1127 | .name = "Terratec Cinergy 200 USB", | 1179 | .name = "Terratec Cinergy 200 USB", |
1128 | .is_em2800 = 1, | 1180 | .is_em2800 = 1, |
1129 | .has_ir_i2c = 1, | 1181 | .has_ir_i2c = 1, |
1130 | .tuner_type = TUNER_LG_PAL_NEW_TAPC, | 1182 | .tuner_type = TUNER_LG_TALN, |
1131 | .tda9887_conf = TDA9887_PRESENT, | 1183 | .tda9887_conf = TDA9887_PRESENT, |
1132 | .decoder = EM28XX_SAA711X, | 1184 | .decoder = EM28XX_SAA711X, |
1133 | .input = { { | 1185 | .input = { { |
@@ -1218,7 +1270,7 @@ struct em28xx_board em28xx_boards[] = { | |||
1218 | }, | 1270 | }, |
1219 | [EM2820_BOARD_PINNACLE_DVC_90] = { | 1271 | [EM2820_BOARD_PINNACLE_DVC_90] = { |
1220 | .name = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker " | 1272 | .name = "Pinnacle Dazzle DVC 90/100/101/107 / Kaiser Baas Video to DVD maker " |
1221 | "/ Kworld DVD Maker 2", | 1273 | "/ Kworld DVD Maker 2 / Plextor ConvertX PX-AV100U", |
1222 | .tuner_type = TUNER_ABSENT, /* capture only board */ | 1274 | .tuner_type = TUNER_ABSENT, /* capture only board */ |
1223 | .decoder = EM28XX_SAA711X, | 1275 | .decoder = EM28XX_SAA711X, |
1224 | .input = { { | 1276 | .input = { { |
@@ -1840,6 +1892,22 @@ struct em28xx_board em28xx_boards[] = { | |||
1840 | .has_dvb = 1, | 1892 | .has_dvb = 1, |
1841 | .ir_codes = RC_MAP_PINNACLE_PCTV_HD, | 1893 | .ir_codes = RC_MAP_PINNACLE_PCTV_HD, |
1842 | }, | 1894 | }, |
1895 | /* eb1a:5006 Honestech VIDBOX NW03 | ||
1896 | * Empia EM2860, Philips SAA7113, Empia EMP202, No Tuner */ | ||
1897 | [EM2860_BOARD_HT_VIDBOX_NW03] = { | ||
1898 | .name = "Honestech Vidbox NW03", | ||
1899 | .tuner_type = TUNER_ABSENT, | ||
1900 | .decoder = EM28XX_SAA711X, | ||
1901 | .input = { { | ||
1902 | .type = EM28XX_VMUX_COMPOSITE1, | ||
1903 | .vmux = SAA7115_COMPOSITE0, | ||
1904 | .amux = EM28XX_AMUX_LINE_IN, | ||
1905 | }, { | ||
1906 | .type = EM28XX_VMUX_SVIDEO, | ||
1907 | .vmux = SAA7115_SVIDEO3, /* S-VIDEO needs confirming */ | ||
1908 | .amux = EM28XX_AMUX_LINE_IN, | ||
1909 | } }, | ||
1910 | }, | ||
1843 | }; | 1911 | }; |
1844 | const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); | 1912 | const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); |
1845 | 1913 | ||
@@ -1899,6 +1967,8 @@ struct usb_device_id em28xx_id_table[] = { | |||
1899 | .driver_info = EM2800_BOARD_GRABBEEX_USB2800 }, | 1967 | .driver_info = EM2800_BOARD_GRABBEEX_USB2800 }, |
1900 | { USB_DEVICE(0xeb1a, 0xe357), | 1968 | { USB_DEVICE(0xeb1a, 0xe357), |
1901 | .driver_info = EM2870_BOARD_KWORLD_355U }, | 1969 | .driver_info = EM2870_BOARD_KWORLD_355U }, |
1970 | { USB_DEVICE(0xeb1a, 0xe359), | ||
1971 | .driver_info = EM2870_BOARD_KWORLD_355U }, | ||
1902 | { USB_DEVICE(0x1b80, 0xe302), | 1972 | { USB_DEVICE(0x1b80, 0xe302), |
1903 | .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kaiser Baas Video to DVD maker */ | 1973 | .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, /* Kaiser Baas Video to DVD maker */ |
1904 | { USB_DEVICE(0x1b80, 0xe304), | 1974 | { USB_DEVICE(0x1b80, 0xe304), |
@@ -1914,17 +1984,23 @@ struct usb_device_id em28xx_id_table[] = { | |||
1914 | { USB_DEVICE(0x0ccd, 0x0042), | 1984 | { USB_DEVICE(0x0ccd, 0x0042), |
1915 | .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, | 1985 | .driver_info = EM2882_BOARD_TERRATEC_HYBRID_XS }, |
1916 | { USB_DEVICE(0x0ccd, 0x0043), | 1986 | { USB_DEVICE(0x0ccd, 0x0043), |
1987 | .driver_info = EM2870_BOARD_TERRATEC_XS }, | ||
1988 | { USB_DEVICE(0x0ccd, 0x008e), /* Cinergy HTC USB XS Rev. 1 */ | ||
1989 | .driver_info = EM2884_BOARD_TERRATEC_H5 }, | ||
1990 | { USB_DEVICE(0x0ccd, 0x00ac), /* Cinergy HTC USB XS Rev. 2 */ | ||
1991 | .driver_info = EM2884_BOARD_TERRATEC_H5 }, | ||
1992 | { USB_DEVICE(0x0ccd, 0x10a2), /* H5 Rev. 1 */ | ||
1917 | .driver_info = EM2884_BOARD_TERRATEC_H5 }, | 1993 | .driver_info = EM2884_BOARD_TERRATEC_H5 }, |
1918 | { USB_DEVICE(0x0ccd, 0x10a2), /* Rev. 1 */ | 1994 | { USB_DEVICE(0x0ccd, 0x10ad), /* H5 Rev. 2 */ |
1919 | .driver_info = EM2884_BOARD_TERRATEC_H5 }, | 1995 | .driver_info = EM2884_BOARD_TERRATEC_H5 }, |
1920 | { USB_DEVICE(0x0ccd, 0x10ad), /* Rev. 2 */ | ||
1921 | .driver_info = EM2880_BOARD_TERRATEC_PRODIGY_XS }, | ||
1922 | { USB_DEVICE(0x0ccd, 0x0084), | 1996 | { USB_DEVICE(0x0ccd, 0x0084), |
1923 | .driver_info = EM2860_BOARD_TERRATEC_AV350 }, | 1997 | .driver_info = EM2860_BOARD_TERRATEC_AV350 }, |
1924 | { USB_DEVICE(0x0ccd, 0x0096), | 1998 | { USB_DEVICE(0x0ccd, 0x0096), |
1925 | .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, | 1999 | .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, |
1926 | { USB_DEVICE(0x0ccd, 0x10AF), | 2000 | { USB_DEVICE(0x0ccd, 0x10AF), |
1927 | .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, | 2001 | .driver_info = EM2860_BOARD_TERRATEC_GRABBY }, |
2002 | { USB_DEVICE(0x0ccd, 0x00b2), | ||
2003 | .driver_info = EM2884_BOARD_CINERGY_HTC_STICK }, | ||
1928 | { USB_DEVICE(0x0fd9, 0x0033), | 2004 | { USB_DEVICE(0x0fd9, 0x0033), |
1929 | .driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE}, | 2005 | .driver_info = EM2860_BOARD_ELGATO_VIDEO_CAPTURE}, |
1930 | { USB_DEVICE(0x185b, 0x2870), | 2006 | { USB_DEVICE(0x185b, 0x2870), |
@@ -1963,6 +2039,8 @@ struct usb_device_id em28xx_id_table[] = { | |||
1963 | .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO }, | 2039 | .driver_info = EM2880_BOARD_PINNACLE_PCTV_HD_PRO }, |
1964 | { USB_DEVICE(0x0413, 0x6023), | 2040 | { USB_DEVICE(0x0413, 0x6023), |
1965 | .driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII }, | 2041 | .driver_info = EM2800_BOARD_LEADTEK_WINFAST_USBII }, |
2042 | { USB_DEVICE(0x093b, 0xa003), | ||
2043 | .driver_info = EM2820_BOARD_PINNACLE_DVC_90 }, | ||
1966 | { USB_DEVICE(0x093b, 0xa005), | 2044 | { USB_DEVICE(0x093b, 0xa005), |
1967 | .driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U }, | 2045 | .driver_info = EM2861_BOARD_PLEXTOR_PX_TV100U }, |
1968 | { USB_DEVICE(0x04bb, 0x0515), | 2046 | { USB_DEVICE(0x04bb, 0x0515), |
@@ -1975,6 +2053,12 @@ struct usb_device_id em28xx_id_table[] = { | |||
1975 | .driver_info = EM28174_BOARD_PCTV_290E }, | 2053 | .driver_info = EM28174_BOARD_PCTV_290E }, |
1976 | { USB_DEVICE(0x2013, 0x024c), | 2054 | { USB_DEVICE(0x2013, 0x024c), |
1977 | .driver_info = EM28174_BOARD_PCTV_460E }, | 2055 | .driver_info = EM28174_BOARD_PCTV_460E }, |
2056 | { USB_DEVICE(0x2040, 0x1605), | ||
2057 | .driver_info = EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C }, | ||
2058 | { USB_DEVICE(0xeb1a, 0x5006), | ||
2059 | .driver_info = EM2860_BOARD_HT_VIDBOX_NW03 }, | ||
2060 | { USB_DEVICE(0x1b80, 0xe309), /* Sveon STV40 */ | ||
2061 | .driver_info = EM2860_BOARD_EASYCAP }, | ||
1978 | { }, | 2062 | { }, |
1979 | }; | 2063 | }; |
1980 | MODULE_DEVICE_TABLE(usb, em28xx_id_table); | 2064 | MODULE_DEVICE_TABLE(usb, em28xx_id_table); |
@@ -2028,10 +2112,10 @@ int em28xx_tuner_callback(void *ptr, int component, int command, int arg) | |||
2028 | int rc = 0; | 2112 | int rc = 0; |
2029 | struct em28xx *dev = ptr; | 2113 | struct em28xx *dev = ptr; |
2030 | 2114 | ||
2031 | if (dev->tuner_type != TUNER_XC2028) | 2115 | if (dev->tuner_type != TUNER_XC2028 && dev->tuner_type != TUNER_XC5000) |
2032 | return 0; | 2116 | return 0; |
2033 | 2117 | ||
2034 | if (command != XC2028_TUNER_RESET) | 2118 | if (command != XC2028_TUNER_RESET && command != XC5000_TUNER_RESET) |
2035 | return 0; | 2119 | return 0; |
2036 | 2120 | ||
2037 | rc = em28xx_gpio_set(dev, dev->board.tuner_gpio); | 2121 | rc = em28xx_gpio_set(dev, dev->board.tuner_gpio); |
@@ -2203,7 +2287,8 @@ void em28xx_pre_card_setup(struct em28xx *dev) | |||
2203 | /* Set the initial XCLK and I2C clock values based on the board | 2287 | /* Set the initial XCLK and I2C clock values based on the board |
2204 | definition */ | 2288 | definition */ |
2205 | em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f); | 2289 | em28xx_write_reg(dev, EM28XX_R0F_XCLK, dev->board.xclk & 0x7f); |
2206 | em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); | 2290 | if (!dev->board.is_em2800) |
2291 | em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); | ||
2207 | msleep(50); | 2292 | msleep(50); |
2208 | 2293 | ||
2209 | /* request some modules */ | 2294 | /* request some modules */ |
@@ -2832,11 +2917,10 @@ void em28xx_release_resources(struct em28xx *dev) | |||
2832 | * em28xx_init_dev() | 2917 | * em28xx_init_dev() |
2833 | * allocates and inits the device structs, registers i2c bus and v4l device | 2918 | * allocates and inits the device structs, registers i2c bus and v4l device |
2834 | */ | 2919 | */ |
2835 | static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | 2920 | static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev, |
2836 | struct usb_interface *interface, | 2921 | struct usb_interface *interface, |
2837 | int minor) | 2922 | int minor) |
2838 | { | 2923 | { |
2839 | struct em28xx *dev = *devhandle; | ||
2840 | int retval; | 2924 | int retval; |
2841 | 2925 | ||
2842 | dev->udev = udev; | 2926 | dev->udev = udev; |
@@ -2931,7 +3015,7 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, | |||
2931 | 3015 | ||
2932 | if (!dev->board.is_em2800) { | 3016 | if (!dev->board.is_em2800) { |
2933 | /* Resets I2C speed */ | 3017 | /* Resets I2C speed */ |
2934 | em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); | 3018 | retval = em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, dev->board.i2c_speed); |
2935 | if (retval < 0) { | 3019 | if (retval < 0) { |
2936 | em28xx_errdev("%s: em28xx_write_reg failed!" | 3020 | em28xx_errdev("%s: em28xx_write_reg failed!" |
2937 | " retval [%d]\n", | 3021 | " retval [%d]\n", |
@@ -3031,12 +3115,11 @@ unregister_dev: | |||
3031 | static int em28xx_usb_probe(struct usb_interface *interface, | 3115 | static int em28xx_usb_probe(struct usb_interface *interface, |
3032 | const struct usb_device_id *id) | 3116 | const struct usb_device_id *id) |
3033 | { | 3117 | { |
3034 | const struct usb_endpoint_descriptor *endpoint; | ||
3035 | struct usb_device *udev; | 3118 | struct usb_device *udev; |
3036 | struct em28xx *dev = NULL; | 3119 | struct em28xx *dev = NULL; |
3037 | int retval; | 3120 | int retval; |
3038 | bool is_audio_only = false, has_audio = false; | 3121 | bool has_audio = false, has_video = false, has_dvb = false; |
3039 | int i, nr, isoc_pipe; | 3122 | int i, nr; |
3040 | const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; | 3123 | const int ifnum = interface->altsetting[0].desc.bInterfaceNumber; |
3041 | char *speed; | 3124 | char *speed; |
3042 | char descr[255] = ""; | 3125 | char descr[255] = ""; |
@@ -3068,54 +3151,65 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3068 | goto err; | 3151 | goto err; |
3069 | } | 3152 | } |
3070 | 3153 | ||
3154 | /* allocate memory for our device state and initialize it */ | ||
3155 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
3156 | if (dev == NULL) { | ||
3157 | em28xx_err(DRIVER_NAME ": out of memory!\n"); | ||
3158 | retval = -ENOMEM; | ||
3159 | goto err; | ||
3160 | } | ||
3161 | |||
3162 | /* compute alternate max packet sizes */ | ||
3163 | dev->alt_max_pkt_size = kmalloc(sizeof(dev->alt_max_pkt_size[0]) * | ||
3164 | interface->num_altsetting, GFP_KERNEL); | ||
3165 | if (dev->alt_max_pkt_size == NULL) { | ||
3166 | em28xx_errdev("out of memory!\n"); | ||
3167 | kfree(dev); | ||
3168 | retval = -ENOMEM; | ||
3169 | goto err; | ||
3170 | } | ||
3171 | |||
3071 | /* Get endpoints */ | 3172 | /* Get endpoints */ |
3072 | for (i = 0; i < interface->num_altsetting; i++) { | 3173 | for (i = 0; i < interface->num_altsetting; i++) { |
3073 | int ep; | 3174 | int ep; |
3074 | 3175 | ||
3075 | for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) { | 3176 | for (ep = 0; ep < interface->altsetting[i].desc.bNumEndpoints; ep++) { |
3076 | struct usb_host_endpoint *e; | 3177 | const struct usb_endpoint_descriptor *e; |
3077 | e = &interface->altsetting[i].endpoint[ep]; | 3178 | int sizedescr, size; |
3078 | 3179 | ||
3079 | if (e->desc.bEndpointAddress == 0x83) | 3180 | e = &interface->altsetting[i].endpoint[ep].desc; |
3080 | has_audio = true; | 3181 | |
3182 | sizedescr = le16_to_cpu(e->wMaxPacketSize); | ||
3183 | size = sizedescr & 0x7ff; | ||
3184 | |||
3185 | if (udev->speed == USB_SPEED_HIGH) | ||
3186 | size = size * hb_mult(sizedescr); | ||
3187 | |||
3188 | if (usb_endpoint_xfer_isoc(e) && | ||
3189 | usb_endpoint_dir_in(e)) { | ||
3190 | switch (e->bEndpointAddress) { | ||
3191 | case EM28XX_EP_AUDIO: | ||
3192 | has_audio = true; | ||
3193 | break; | ||
3194 | case EM28XX_EP_ANALOG: | ||
3195 | has_video = true; | ||
3196 | dev->alt_max_pkt_size[i] = size; | ||
3197 | break; | ||
3198 | case EM28XX_EP_DIGITAL: | ||
3199 | has_dvb = true; | ||
3200 | if (size > dev->dvb_max_pkt_size) { | ||
3201 | dev->dvb_max_pkt_size = size; | ||
3202 | dev->dvb_alt = i; | ||
3203 | } | ||
3204 | break; | ||
3205 | } | ||
3206 | } | ||
3081 | } | 3207 | } |
3082 | } | 3208 | } |
3083 | 3209 | ||
3084 | endpoint = &interface->cur_altsetting->endpoint[0].desc; | 3210 | if (!(has_audio || has_video || has_dvb)) { |
3085 | 3211 | retval = -ENODEV; | |
3086 | /* check if the device has the iso in endpoint at the correct place */ | 3212 | goto err_free; |
3087 | if (usb_endpoint_xfer_isoc(endpoint) | ||
3088 | && | ||
3089 | (interface->altsetting[1].endpoint[0].desc.wMaxPacketSize == 940)) { | ||
3090 | /* It's a newer em2874/em2875 device */ | ||
3091 | isoc_pipe = 0; | ||
3092 | } else { | ||
3093 | int check_interface = 1; | ||
3094 | isoc_pipe = 1; | ||
3095 | endpoint = &interface->cur_altsetting->endpoint[1].desc; | ||
3096 | if (!usb_endpoint_xfer_isoc(endpoint)) | ||
3097 | check_interface = 0; | ||
3098 | |||
3099 | if (usb_endpoint_dir_out(endpoint)) | ||
3100 | check_interface = 0; | ||
3101 | |||
3102 | if (!check_interface) { | ||
3103 | if (has_audio) { | ||
3104 | is_audio_only = true; | ||
3105 | } else { | ||
3106 | em28xx_err(DRIVER_NAME " video device (%04x:%04x): " | ||
3107 | "interface %i, class %i found.\n", | ||
3108 | le16_to_cpu(udev->descriptor.idVendor), | ||
3109 | le16_to_cpu(udev->descriptor.idProduct), | ||
3110 | ifnum, | ||
3111 | interface->altsetting[0].desc.bInterfaceClass); | ||
3112 | em28xx_err(DRIVER_NAME " This is an anciliary " | ||
3113 | "interface not used by the driver\n"); | ||
3114 | |||
3115 | retval = -ENODEV; | ||
3116 | goto err; | ||
3117 | } | ||
3118 | } | ||
3119 | } | 3213 | } |
3120 | 3214 | ||
3121 | switch (udev->speed) { | 3215 | switch (udev->speed) { |
@@ -3141,6 +3235,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3141 | strlcat(descr, " ", sizeof(descr)); | 3235 | strlcat(descr, " ", sizeof(descr)); |
3142 | strlcat(descr, udev->product, sizeof(descr)); | 3236 | strlcat(descr, udev->product, sizeof(descr)); |
3143 | } | 3237 | } |
3238 | |||
3144 | if (*descr) | 3239 | if (*descr) |
3145 | strlcat(descr, " ", sizeof(descr)); | 3240 | strlcat(descr, " ", sizeof(descr)); |
3146 | 3241 | ||
@@ -3157,6 +3252,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3157 | printk(KERN_INFO DRIVER_NAME | 3252 | printk(KERN_INFO DRIVER_NAME |
3158 | ": Audio Vendor Class interface %i found\n", | 3253 | ": Audio Vendor Class interface %i found\n", |
3159 | ifnum); | 3254 | ifnum); |
3255 | if (has_video) | ||
3256 | printk(KERN_INFO DRIVER_NAME | ||
3257 | ": Video interface %i found\n", | ||
3258 | ifnum); | ||
3259 | if (has_dvb) | ||
3260 | printk(KERN_INFO DRIVER_NAME | ||
3261 | ": DVB interface %i found\n", | ||
3262 | ifnum); | ||
3160 | 3263 | ||
3161 | /* | 3264 | /* |
3162 | * Make sure we have 480 Mbps of bandwidth, otherwise things like | 3265 | * Make sure we have 480 Mbps of bandwidth, otherwise things like |
@@ -3168,22 +3271,14 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3168 | printk(DRIVER_NAME ": Device must be connected to a high-speed" | 3271 | printk(DRIVER_NAME ": Device must be connected to a high-speed" |
3169 | " USB 2.0 port.\n"); | 3272 | " USB 2.0 port.\n"); |
3170 | retval = -ENODEV; | 3273 | retval = -ENODEV; |
3171 | goto err; | 3274 | goto err_free; |
3172 | } | ||
3173 | |||
3174 | /* allocate memory for our device state and initialize it */ | ||
3175 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
3176 | if (dev == NULL) { | ||
3177 | em28xx_err(DRIVER_NAME ": out of memory!\n"); | ||
3178 | retval = -ENOMEM; | ||
3179 | goto err; | ||
3180 | } | 3275 | } |
3181 | 3276 | ||
3182 | snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr); | 3277 | snprintf(dev->name, sizeof(dev->name), "em28xx #%d", nr); |
3183 | dev->devno = nr; | 3278 | dev->devno = nr; |
3184 | dev->model = id->driver_info; | 3279 | dev->model = id->driver_info; |
3185 | dev->alt = -1; | 3280 | dev->alt = -1; |
3186 | dev->is_audio_only = is_audio_only; | 3281 | dev->is_audio_only = has_audio && !(has_video || has_dvb); |
3187 | dev->has_alsa_audio = has_audio; | 3282 | dev->has_alsa_audio = has_audio; |
3188 | dev->audio_ifnum = ifnum; | 3283 | dev->audio_ifnum = ifnum; |
3189 | 3284 | ||
@@ -3196,26 +3291,7 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3196 | } | 3291 | } |
3197 | } | 3292 | } |
3198 | 3293 | ||
3199 | /* compute alternate max packet sizes */ | ||
3200 | dev->num_alt = interface->num_altsetting; | 3294 | dev->num_alt = interface->num_altsetting; |
3201 | dev->alt_max_pkt_size = kmalloc(32 * dev->num_alt, GFP_KERNEL); | ||
3202 | |||
3203 | if (dev->alt_max_pkt_size == NULL) { | ||
3204 | em28xx_errdev("out of memory!\n"); | ||
3205 | kfree(dev); | ||
3206 | retval = -ENOMEM; | ||
3207 | goto err; | ||
3208 | } | ||
3209 | |||
3210 | for (i = 0; i < dev->num_alt ; i++) { | ||
3211 | u16 tmp = le16_to_cpu(interface->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize); | ||
3212 | unsigned int size = tmp & 0x7ff; | ||
3213 | |||
3214 | if (udev->speed == USB_SPEED_HIGH) | ||
3215 | size = size * hb_mult(tmp); | ||
3216 | |||
3217 | dev->alt_max_pkt_size[i] = size; | ||
3218 | } | ||
3219 | 3295 | ||
3220 | if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) | 3296 | if ((card[nr] >= 0) && (card[nr] < em28xx_bcount)) |
3221 | dev->model = card[nr]; | 3297 | dev->model = card[nr]; |
@@ -3226,12 +3302,9 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3226 | /* allocate device struct */ | 3302 | /* allocate device struct */ |
3227 | mutex_init(&dev->lock); | 3303 | mutex_init(&dev->lock); |
3228 | mutex_lock(&dev->lock); | 3304 | mutex_lock(&dev->lock); |
3229 | retval = em28xx_init_dev(&dev, udev, interface, nr); | 3305 | retval = em28xx_init_dev(dev, udev, interface, nr); |
3230 | if (retval) { | 3306 | if (retval) { |
3231 | mutex_unlock(&dev->lock); | 3307 | goto unlock_and_free; |
3232 | kfree(dev->alt_max_pkt_size); | ||
3233 | kfree(dev); | ||
3234 | goto err; | ||
3235 | } | 3308 | } |
3236 | 3309 | ||
3237 | request_modules(dev); | 3310 | request_modules(dev); |
@@ -3250,6 +3323,13 @@ static int em28xx_usb_probe(struct usb_interface *interface, | |||
3250 | 3323 | ||
3251 | return 0; | 3324 | return 0; |
3252 | 3325 | ||
3326 | unlock_and_free: | ||
3327 | mutex_unlock(&dev->lock); | ||
3328 | |||
3329 | err_free: | ||
3330 | kfree(dev->alt_max_pkt_size); | ||
3331 | kfree(dev); | ||
3332 | |||
3253 | err: | 3333 | err: |
3254 | clear_bit(nr, &em28xx_devused); | 3334 | clear_bit(nr, &em28xx_devused); |
3255 | 3335 | ||
diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 804a4ab47ac6..0aacc96f9a23 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c | |||
@@ -568,7 +568,7 @@ int em28xx_audio_setup(struct em28xx *dev) | |||
568 | em28xx_warn("AC97 features = 0x%04x\n", feat); | 568 | em28xx_warn("AC97 features = 0x%04x\n", feat); |
569 | 569 | ||
570 | /* Try to identify what audio processor we have */ | 570 | /* Try to identify what audio processor we have */ |
571 | if ((vid == 0xffffffff) && (feat == 0x6a90)) | 571 | if (((vid == 0xffffffff) || (vid == 0x83847650)) && (feat == 0x6a90)) |
572 | dev->audio_mode.ac97 = EM28XX_AC97_EM202; | 572 | dev->audio_mode.ac97 = EM28XX_AC97_EM202; |
573 | else if ((vid >> 8) == 0x838476) | 573 | else if ((vid >> 8) == 0x838476) |
574 | dev->audio_mode.ac97 = EM28XX_AC97_SIGMATEL; | 574 | dev->audio_mode.ac97 = EM28XX_AC97_SIGMATEL; |
@@ -1070,7 +1070,8 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, | |||
1070 | should also be using 'desc.bInterval' | 1070 | should also be using 'desc.bInterval' |
1071 | */ | 1071 | */ |
1072 | pipe = usb_rcvisocpipe(dev->udev, | 1072 | pipe = usb_rcvisocpipe(dev->udev, |
1073 | dev->mode == EM28XX_ANALOG_MODE ? 0x82 : 0x84); | 1073 | dev->mode == EM28XX_ANALOG_MODE ? |
1074 | EM28XX_EP_ANALOG : EM28XX_EP_DIGITAL); | ||
1074 | 1075 | ||
1075 | usb_fill_int_urb(urb, dev->udev, pipe, | 1076 | usb_fill_int_urb(urb, dev->udev, pipe, |
1076 | dev->isoc_ctl.transfer_buffer[i], sb_size, | 1077 | dev->isoc_ctl.transfer_buffer[i], sb_size, |
@@ -1108,62 +1109,6 @@ int em28xx_init_isoc(struct em28xx *dev, int max_packets, | |||
1108 | } | 1109 | } |
1109 | EXPORT_SYMBOL_GPL(em28xx_init_isoc); | 1110 | EXPORT_SYMBOL_GPL(em28xx_init_isoc); |
1110 | 1111 | ||
1111 | /* Determine the packet size for the DVB stream for the given device | ||
1112 | (underlying value programmed into the eeprom) */ | ||
1113 | int em28xx_isoc_dvb_max_packetsize(struct em28xx *dev) | ||
1114 | { | ||
1115 | unsigned int chip_cfg2; | ||
1116 | unsigned int packet_size; | ||
1117 | |||
1118 | switch (dev->chip_id) { | ||
1119 | case CHIP_ID_EM2710: | ||
1120 | case CHIP_ID_EM2750: | ||
1121 | case CHIP_ID_EM2800: | ||
1122 | case CHIP_ID_EM2820: | ||
1123 | case CHIP_ID_EM2840: | ||
1124 | case CHIP_ID_EM2860: | ||
1125 | /* No DVB support */ | ||
1126 | return -EINVAL; | ||
1127 | case CHIP_ID_EM2870: | ||
1128 | case CHIP_ID_EM2883: | ||
1129 | /* TS max packet size stored in bits 1-0 of R01 */ | ||
1130 | chip_cfg2 = em28xx_read_reg(dev, EM28XX_R01_CHIPCFG2); | ||
1131 | switch (chip_cfg2 & EM28XX_CHIPCFG2_TS_PACKETSIZE_MASK) { | ||
1132 | case EM28XX_CHIPCFG2_TS_PACKETSIZE_188: | ||
1133 | packet_size = 188; | ||
1134 | break; | ||
1135 | case EM28XX_CHIPCFG2_TS_PACKETSIZE_376: | ||
1136 | packet_size = 376; | ||
1137 | break; | ||
1138 | case EM28XX_CHIPCFG2_TS_PACKETSIZE_564: | ||
1139 | packet_size = 564; | ||
1140 | break; | ||
1141 | case EM28XX_CHIPCFG2_TS_PACKETSIZE_752: | ||
1142 | packet_size = 752; | ||
1143 | break; | ||
1144 | } | ||
1145 | break; | ||
1146 | case CHIP_ID_EM2874: | ||
1147 | /* | ||
1148 | * FIXME: for now assumes 564 like it was before, but the | ||
1149 | * em2874 code should be added to return the proper value | ||
1150 | */ | ||
1151 | packet_size = 564; | ||
1152 | break; | ||
1153 | case CHIP_ID_EM2884: | ||
1154 | case CHIP_ID_EM28174: | ||
1155 | default: | ||
1156 | /* | ||
1157 | * FIXME: same as em2874. 564 was enough for 22 Mbit DVB-T | ||
1158 | * but not enough for 44 Mbit DVB-C. | ||
1159 | */ | ||
1160 | packet_size = 752; | ||
1161 | } | ||
1162 | |||
1163 | return packet_size; | ||
1164 | } | ||
1165 | EXPORT_SYMBOL_GPL(em28xx_isoc_dvb_max_packetsize); | ||
1166 | |||
1167 | /* | 1112 | /* |
1168 | * em28xx_wake_i2c() | 1113 | * em28xx_wake_i2c() |
1169 | * configure i2c attached devices | 1114 | * configure i2c attached devices |
diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index cef7a2d409cb..9449423098e0 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include "drxk.h" | 44 | #include "drxk.h" |
45 | #include "tda10071.h" | 45 | #include "tda10071.h" |
46 | #include "a8293.h" | 46 | #include "a8293.h" |
47 | #include "qt1010.h" | ||
47 | 48 | ||
48 | MODULE_DESCRIPTION("driver for em28xx based DVB cards"); | 49 | MODULE_DESCRIPTION("driver for em28xx based DVB cards"); |
49 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); | 50 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@infradead.org>"); |
@@ -163,12 +164,12 @@ static int em28xx_start_streaming(struct em28xx_dvb *dvb) | |||
163 | struct em28xx *dev = dvb->adapter.priv; | 164 | struct em28xx *dev = dvb->adapter.priv; |
164 | int max_dvb_packet_size; | 165 | int max_dvb_packet_size; |
165 | 166 | ||
166 | usb_set_interface(dev->udev, 0, 1); | 167 | usb_set_interface(dev->udev, 0, dev->dvb_alt); |
167 | rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); | 168 | rc = em28xx_set_mode(dev, EM28XX_DIGITAL_MODE); |
168 | if (rc < 0) | 169 | if (rc < 0) |
169 | return rc; | 170 | return rc; |
170 | 171 | ||
171 | max_dvb_packet_size = em28xx_isoc_dvb_max_packetsize(dev); | 172 | max_dvb_packet_size = dev->dvb_max_pkt_size; |
172 | if (max_dvb_packet_size < 0) | 173 | if (max_dvb_packet_size < 0) |
173 | return max_dvb_packet_size; | 174 | return max_dvb_packet_size; |
174 | dprintk(1, "Using %d buffers each with %d bytes\n", | 175 | dprintk(1, "Using %d buffers each with %d bytes\n", |
@@ -302,10 +303,12 @@ static struct zl10353_config em28xx_zl10353_xc3028_no_i2c_gate = { | |||
302 | }; | 303 | }; |
303 | 304 | ||
304 | static struct drxd_config em28xx_drxd = { | 305 | static struct drxd_config em28xx_drxd = { |
305 | .index = 0, .demod_address = 0x70, .demod_revision = 0xa2, | 306 | .demod_address = 0x70, |
306 | .demoda_address = 0x00, .pll_address = 0x00, | 307 | .demod_revision = 0xa2, |
307 | .pll_type = DRXD_PLL_NONE, .clock = 12000, .insert_rs_byte = 1, | 308 | .pll_type = DRXD_PLL_NONE, |
308 | .pll_set = NULL, .osc_deviation = NULL, .IF = 42800000, | 309 | .clock = 12000, |
310 | .insert_rs_byte = 1, | ||
311 | .IF = 42800000, | ||
309 | .disable_i2c_gate_ctrl = 1, | 312 | .disable_i2c_gate_ctrl = 1, |
310 | }; | 313 | }; |
311 | 314 | ||
@@ -316,6 +319,14 @@ struct drxk_config terratec_h5_drxk = { | |||
316 | .microcode_name = "dvb-usb-terratec-h5-drxk.fw", | 319 | .microcode_name = "dvb-usb-terratec-h5-drxk.fw", |
317 | }; | 320 | }; |
318 | 321 | ||
322 | struct drxk_config hauppauge_930c_drxk = { | ||
323 | .adr = 0x29, | ||
324 | .single_master = 1, | ||
325 | .no_i2c_bridge = 1, | ||
326 | .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw", | ||
327 | .chunk_size = 56, | ||
328 | }; | ||
329 | |||
319 | static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) | 330 | static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) |
320 | { | 331 | { |
321 | struct em28xx_dvb *dvb = fe->sec_priv; | 332 | struct em28xx_dvb *dvb = fe->sec_priv; |
@@ -334,6 +345,73 @@ static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable) | |||
334 | return status; | 345 | return status; |
335 | } | 346 | } |
336 | 347 | ||
348 | static void hauppauge_hvr930c_init(struct em28xx *dev) | ||
349 | { | ||
350 | int i; | ||
351 | |||
352 | struct em28xx_reg_seq hauppauge_hvr930c_init[] = { | ||
353 | {EM2874_R80_GPIO, 0xff, 0xff, 0x65}, | ||
354 | {EM2874_R80_GPIO, 0xfb, 0xff, 0x32}, | ||
355 | {EM2874_R80_GPIO, 0xff, 0xff, 0xb8}, | ||
356 | { -1, -1, -1, -1}, | ||
357 | }; | ||
358 | struct em28xx_reg_seq hauppauge_hvr930c_end[] = { | ||
359 | {EM2874_R80_GPIO, 0xef, 0xff, 0x01}, | ||
360 | {EM2874_R80_GPIO, 0xaf, 0xff, 0x65}, | ||
361 | {EM2874_R80_GPIO, 0xef, 0xff, 0x76}, | ||
362 | {EM2874_R80_GPIO, 0xef, 0xff, 0x01}, | ||
363 | {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b}, | ||
364 | {EM2874_R80_GPIO, 0xef, 0xff, 0x40}, | ||
365 | |||
366 | {EM2874_R80_GPIO, 0xcf, 0xff, 0x65}, | ||
367 | {EM2874_R80_GPIO, 0xef, 0xff, 0x65}, | ||
368 | {EM2874_R80_GPIO, 0xcf, 0xff, 0x0b}, | ||
369 | {EM2874_R80_GPIO, 0xef, 0xff, 0x65}, | ||
370 | |||
371 | { -1, -1, -1, -1}, | ||
372 | }; | ||
373 | |||
374 | struct { | ||
375 | unsigned char r[4]; | ||
376 | int len; | ||
377 | } regs[] = { | ||
378 | {{ 0x06, 0x02, 0x00, 0x31 }, 4}, | ||
379 | {{ 0x01, 0x02 }, 2}, | ||
380 | {{ 0x01, 0x02, 0x00, 0xc6 }, 4}, | ||
381 | {{ 0x01, 0x00 }, 2}, | ||
382 | {{ 0x01, 0x00, 0xff, 0xaf }, 4}, | ||
383 | {{ 0x01, 0x00, 0x03, 0xa0 }, 4}, | ||
384 | {{ 0x01, 0x00 }, 2}, | ||
385 | {{ 0x01, 0x00, 0x73, 0xaf }, 4}, | ||
386 | {{ 0x04, 0x00 }, 2}, | ||
387 | {{ 0x00, 0x04 }, 2}, | ||
388 | {{ 0x00, 0x04, 0x00, 0x0a }, 4}, | ||
389 | {{ 0x04, 0x14 }, 2}, | ||
390 | {{ 0x04, 0x14, 0x00, 0x00 }, 4}, | ||
391 | }; | ||
392 | |||
393 | em28xx_gpio_set(dev, hauppauge_hvr930c_init); | ||
394 | em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x40); | ||
395 | msleep(10); | ||
396 | em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); | ||
397 | msleep(10); | ||
398 | |||
399 | dev->i2c_client.addr = 0x82 >> 1; | ||
400 | |||
401 | for (i = 0; i < ARRAY_SIZE(regs); i++) | ||
402 | i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len); | ||
403 | em28xx_gpio_set(dev, hauppauge_hvr930c_end); | ||
404 | |||
405 | msleep(100); | ||
406 | |||
407 | em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x44); | ||
408 | msleep(30); | ||
409 | |||
410 | em28xx_write_reg(dev, EM28XX_R06_I2C_CLK, 0x45); | ||
411 | msleep(10); | ||
412 | |||
413 | } | ||
414 | |||
337 | static void terratec_h5_init(struct em28xx *dev) | 415 | static void terratec_h5_init(struct em28xx *dev) |
338 | { | 416 | { |
339 | int i; | 417 | int i; |
@@ -425,13 +503,6 @@ static struct tda10023_config em28xx_tda10023_config = { | |||
425 | static struct cxd2820r_config em28xx_cxd2820r_config = { | 503 | static struct cxd2820r_config em28xx_cxd2820r_config = { |
426 | .i2c_address = (0xd8 >> 1), | 504 | .i2c_address = (0xd8 >> 1), |
427 | .ts_mode = CXD2820R_TS_SERIAL, | 505 | .ts_mode = CXD2820R_TS_SERIAL, |
428 | .if_dvbt_6 = 3300, | ||
429 | .if_dvbt_7 = 3500, | ||
430 | .if_dvbt_8 = 4000, | ||
431 | .if_dvbt2_6 = 3300, | ||
432 | .if_dvbt2_7 = 3500, | ||
433 | .if_dvbt2_8 = 4000, | ||
434 | .if_dvbc = 5000, | ||
435 | 506 | ||
436 | /* enable LNA for DVB-T2 and DVB-C */ | 507 | /* enable LNA for DVB-T2 and DVB-C */ |
437 | .gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, | 508 | .gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L, |
@@ -456,6 +527,17 @@ static const struct a8293_config em28xx_a8293_config = { | |||
456 | .i2c_addr = 0x08, /* (0x10 >> 1) */ | 527 | .i2c_addr = 0x08, /* (0x10 >> 1) */ |
457 | }; | 528 | }; |
458 | 529 | ||
530 | static struct zl10353_config em28xx_zl10353_no_i2c_gate_dev = { | ||
531 | .demod_address = (0x1e >> 1), | ||
532 | .disable_i2c_gate_ctrl = 1, | ||
533 | .no_tuner = 1, | ||
534 | .parallel_ts = 1, | ||
535 | }; | ||
536 | static struct qt1010_config em28xx_qt1010_config = { | ||
537 | .i2c_address = 0x62 | ||
538 | |||
539 | }; | ||
540 | |||
459 | /* ------------------------------------------------------------------ */ | 541 | /* ------------------------------------------------------------------ */ |
460 | 542 | ||
461 | static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev) | 543 | static int em28xx_attach_xc3028(u8 addr, struct em28xx *dev) |
@@ -708,6 +790,14 @@ static int em28xx_dvb_init(struct em28xx *dev) | |||
708 | goto out_free; | 790 | goto out_free; |
709 | } | 791 | } |
710 | break; | 792 | break; |
793 | case EM2870_BOARD_KWORLD_355U: | ||
794 | dvb->fe[0] = dvb_attach(zl10353_attach, | ||
795 | &em28xx_zl10353_no_i2c_gate_dev, | ||
796 | &dev->i2c_adap); | ||
797 | if (dvb->fe[0] != NULL) | ||
798 | dvb_attach(qt1010_attach, dvb->fe[0], | ||
799 | &dev->i2c_adap, &em28xx_qt1010_config); | ||
800 | break; | ||
711 | case EM2883_BOARD_KWORLD_HYBRID_330U: | 801 | case EM2883_BOARD_KWORLD_HYBRID_330U: |
712 | case EM2882_BOARD_EVGA_INDTUBE: | 802 | case EM2882_BOARD_EVGA_INDTUBE: |
713 | dvb->fe[0] = dvb_attach(s5h1409_attach, | 803 | dvb->fe[0] = dvb_attach(s5h1409_attach, |
@@ -761,50 +851,72 @@ static int em28xx_dvb_init(struct em28xx *dev) | |||
761 | &dev->i2c_adap, &kworld_a340_config); | 851 | &dev->i2c_adap, &kworld_a340_config); |
762 | break; | 852 | break; |
763 | case EM28174_BOARD_PCTV_290E: | 853 | case EM28174_BOARD_PCTV_290E: |
764 | /* MFE | ||
765 | * FE 0 = DVB-T/T2 + FE 1 = DVB-C, both sharing same tuner. */ | ||
766 | /* FE 0 */ | ||
767 | dvb->fe[0] = dvb_attach(cxd2820r_attach, | 854 | dvb->fe[0] = dvb_attach(cxd2820r_attach, |
768 | &em28xx_cxd2820r_config, &dev->i2c_adap, NULL); | 855 | &em28xx_cxd2820r_config, |
856 | &dev->i2c_adap, | ||
857 | NULL); | ||
769 | if (dvb->fe[0]) { | 858 | if (dvb->fe[0]) { |
770 | /* FE 0 attach tuner */ | 859 | /* FE 0 attach tuner */ |
771 | if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60, | 860 | if (!dvb_attach(tda18271_attach, |
772 | &dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) { | 861 | dvb->fe[0], |
862 | 0x60, | ||
863 | &dev->i2c_adap, | ||
864 | &em28xx_cxd2820r_tda18271_config)) { | ||
865 | |||
773 | dvb_frontend_detach(dvb->fe[0]); | 866 | dvb_frontend_detach(dvb->fe[0]); |
774 | result = -EINVAL; | 867 | result = -EINVAL; |
775 | goto out_free; | 868 | goto out_free; |
776 | } | 869 | } |
777 | /* FE 1. This dvb_attach() cannot fail. */ | 870 | } |
778 | dvb->fe[1] = dvb_attach(cxd2820r_attach, NULL, NULL, | 871 | break; |
779 | dvb->fe[0]); | 872 | case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C: |
780 | dvb->fe[1]->id = 1; | 873 | { |
781 | /* FE 1 attach tuner */ | 874 | struct xc5000_config cfg; |
782 | if (!dvb_attach(tda18271_attach, dvb->fe[1], 0x60, | 875 | hauppauge_hvr930c_init(dev); |
783 | &dev->i2c_adap, &em28xx_cxd2820r_tda18271_config)) { | 876 | |
784 | dvb_frontend_detach(dvb->fe[1]); | 877 | dvb->fe[0] = dvb_attach(drxk_attach, |
785 | /* leave FE 0 still active */ | 878 | &hauppauge_930c_drxk, &dev->i2c_adap); |
786 | } | 879 | if (!dvb->fe[0]) { |
880 | result = -EINVAL; | ||
881 | goto out_free; | ||
882 | } | ||
883 | /* FIXME: do we need a pll semaphore? */ | ||
884 | dvb->fe[0]->sec_priv = dvb; | ||
885 | sema_init(&dvb->pll_mutex, 1); | ||
886 | dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; | ||
887 | dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; | ||
787 | 888 | ||
788 | mfe_shared = 1; | 889 | /* Attach xc5000 */ |
890 | memset(&cfg, 0, sizeof(cfg)); | ||
891 | cfg.i2c_address = 0x61; | ||
892 | cfg.if_khz = 4000; | ||
893 | |||
894 | if (dvb->fe[0]->ops.i2c_gate_ctrl) | ||
895 | dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 1); | ||
896 | if (!dvb_attach(xc5000_attach, dvb->fe[0], &dev->i2c_adap, | ||
897 | &cfg)) { | ||
898 | result = -EINVAL; | ||
899 | goto out_free; | ||
789 | } | 900 | } |
901 | if (dvb->fe[0]->ops.i2c_gate_ctrl) | ||
902 | dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); | ||
903 | |||
790 | break; | 904 | break; |
905 | } | ||
791 | case EM2884_BOARD_TERRATEC_H5: | 906 | case EM2884_BOARD_TERRATEC_H5: |
907 | case EM2884_BOARD_CINERGY_HTC_STICK: | ||
792 | terratec_h5_init(dev); | 908 | terratec_h5_init(dev); |
793 | 909 | ||
794 | dvb->dont_attach_fe1 = 1; | 910 | dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap); |
795 | |||
796 | dvb->fe[0] = dvb_attach(drxk_attach, &terratec_h5_drxk, &dev->i2c_adap, &dvb->fe[1]); | ||
797 | if (!dvb->fe[0]) { | 911 | if (!dvb->fe[0]) { |
798 | result = -EINVAL; | 912 | result = -EINVAL; |
799 | goto out_free; | 913 | goto out_free; |
800 | } | 914 | } |
801 | |||
802 | /* FIXME: do we need a pll semaphore? */ | 915 | /* FIXME: do we need a pll semaphore? */ |
803 | dvb->fe[0]->sec_priv = dvb; | 916 | dvb->fe[0]->sec_priv = dvb; |
804 | sema_init(&dvb->pll_mutex, 1); | 917 | sema_init(&dvb->pll_mutex, 1); |
805 | dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; | 918 | dvb->gate_ctrl = dvb->fe[0]->ops.i2c_gate_ctrl; |
806 | dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; | 919 | dvb->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl; |
807 | dvb->fe[1]->id = 1; | ||
808 | 920 | ||
809 | /* Attach tda18271 to DVB-C frontend */ | 921 | /* Attach tda18271 to DVB-C frontend */ |
810 | if (dvb->fe[0]->ops.i2c_gate_ctrl) | 922 | if (dvb->fe[0]->ops.i2c_gate_ctrl) |
@@ -816,12 +928,6 @@ static int em28xx_dvb_init(struct em28xx *dev) | |||
816 | if (dvb->fe[0]->ops.i2c_gate_ctrl) | 928 | if (dvb->fe[0]->ops.i2c_gate_ctrl) |
817 | dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); | 929 | dvb->fe[0]->ops.i2c_gate_ctrl(dvb->fe[0], 0); |
818 | 930 | ||
819 | /* Hack - needed by drxk/tda18271c2dd */ | ||
820 | dvb->fe[1]->tuner_priv = dvb->fe[0]->tuner_priv; | ||
821 | memcpy(&dvb->fe[1]->ops.tuner_ops, | ||
822 | &dvb->fe[0]->ops.tuner_ops, | ||
823 | sizeof(dvb->fe[0]->ops.tuner_ops)); | ||
824 | |||
825 | break; | 931 | break; |
826 | case EM28174_BOARD_PCTV_460E: | 932 | case EM28174_BOARD_PCTV_460E: |
827 | /* attach demod */ | 933 | /* attach demod */ |
@@ -845,6 +951,8 @@ static int em28xx_dvb_init(struct em28xx *dev) | |||
845 | } | 951 | } |
846 | /* define general-purpose callback pointer */ | 952 | /* define general-purpose callback pointer */ |
847 | dvb->fe[0]->callback = em28xx_tuner_callback; | 953 | dvb->fe[0]->callback = em28xx_tuner_callback; |
954 | if (dvb->fe[1]) | ||
955 | dvb->fe[1]->callback = em28xx_tuner_callback; | ||
848 | 956 | ||
849 | /* register everything */ | 957 | /* register everything */ |
850 | result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); | 958 | result = em28xx_register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev); |
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index 679da4804281..2630b265b0e8 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c | |||
@@ -306,7 +306,8 @@ static void em28xx_ir_handle_key(struct em28xx_IR *ir) | |||
306 | poll_result.rc_data[0], | 306 | poll_result.rc_data[0], |
307 | poll_result.toggle_bit); | 307 | poll_result.toggle_bit); |
308 | 308 | ||
309 | if (ir->dev->chip_id == CHIP_ID_EM2874) | 309 | if (ir->dev->chip_id == CHIP_ID_EM2874 || |
310 | ir->dev->chip_id == CHIP_ID_EM2884) | ||
310 | /* The em2874 clears the readcount field every time the | 311 | /* The em2874 clears the readcount field every time the |
311 | register is read. The em2860/2880 datasheet says that it | 312 | register is read. The em2860/2880 datasheet says that it |
312 | is supposed to clear the readcount, but it doesn't. So with | 313 | is supposed to clear the readcount, but it doesn't. So with |
@@ -371,13 +372,15 @@ int em28xx_ir_change_protocol(struct rc_dev *rc_dev, u64 rc_type) | |||
371 | case CHIP_ID_EM2883: | 372 | case CHIP_ID_EM2883: |
372 | ir->get_key = default_polling_getkey; | 373 | ir->get_key = default_polling_getkey; |
373 | break; | 374 | break; |
375 | case CHIP_ID_EM2884: | ||
374 | case CHIP_ID_EM2874: | 376 | case CHIP_ID_EM2874: |
375 | case CHIP_ID_EM28174: | 377 | case CHIP_ID_EM28174: |
376 | ir->get_key = em2874_polling_getkey; | 378 | ir->get_key = em2874_polling_getkey; |
377 | em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1); | 379 | em28xx_write_regs(dev, EM2874_R50_IR_CONFIG, &ir_config, 1); |
378 | break; | 380 | break; |
379 | default: | 381 | default: |
380 | printk("Unrecognized em28xx chip id: IR not supported\n"); | 382 | printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n", |
383 | dev->chip_id); | ||
381 | rc = -EINVAL; | 384 | rc = -EINVAL; |
382 | } | 385 | } |
383 | 386 | ||
diff --git a/drivers/media/video/em28xx/em28xx-reg.h b/drivers/media/video/em28xx/em28xx-reg.h index 66f792361b97..2f6268505726 100644 --- a/drivers/media/video/em28xx/em28xx-reg.h +++ b/drivers/media/video/em28xx/em28xx-reg.h | |||
@@ -12,6 +12,11 @@ | |||
12 | #define EM_GPO_2 (1 << 2) | 12 | #define EM_GPO_2 (1 << 2) |
13 | #define EM_GPO_3 (1 << 3) | 13 | #define EM_GPO_3 (1 << 3) |
14 | 14 | ||
15 | /* em28xx endpoints */ | ||
16 | #define EM28XX_EP_ANALOG 0x82 | ||
17 | #define EM28XX_EP_AUDIO 0x83 | ||
18 | #define EM28XX_EP_DIGITAL 0x84 | ||
19 | |||
15 | /* em2800 registers */ | 20 | /* em2800 registers */ |
16 | #define EM2800_R08_AUDIOSRC 0x08 | 21 | #define EM2800_R08_AUDIOSRC 0x08 |
17 | 22 | ||
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 9b4557a2f6d0..613300b51a9e 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -1070,6 +1070,10 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv, | |||
1070 | /* the em2800 can only scale down to 50% */ | 1070 | /* the em2800 can only scale down to 50% */ |
1071 | height = height > (3 * maxh / 4) ? maxh : maxh / 2; | 1071 | height = height > (3 * maxh / 4) ? maxh : maxh / 2; |
1072 | width = width > (3 * maxw / 4) ? maxw : maxw / 2; | 1072 | width = width > (3 * maxw / 4) ? maxw : maxw / 2; |
1073 | /* MaxPacketSize for em2800 is too small to capture at full resolution | ||
1074 | * use half of maxw as the scaler can only scale to 50% */ | ||
1075 | if (width == maxw && height == maxh) | ||
1076 | width /= 2; | ||
1073 | } else { | 1077 | } else { |
1074 | /* width must even because of the YUYV format | 1078 | /* width must even because of the YUYV format |
1075 | height must be even because of interlacing */ | 1079 | height must be even because of interlacing */ |
@@ -2503,6 +2507,7 @@ int em28xx_register_analog_devices(struct em28xx *dev) | |||
2503 | { | 2507 | { |
2504 | u8 val; | 2508 | u8 val; |
2505 | int ret; | 2509 | int ret; |
2510 | unsigned int maxw; | ||
2506 | 2511 | ||
2507 | printk(KERN_INFO "%s: v4l2 driver version %s\n", | 2512 | printk(KERN_INFO "%s: v4l2 driver version %s\n", |
2508 | dev->name, EM28XX_VERSION); | 2513 | dev->name, EM28XX_VERSION); |
@@ -2515,8 +2520,15 @@ int em28xx_register_analog_devices(struct em28xx *dev) | |||
2515 | 2520 | ||
2516 | /* Analog specific initialization */ | 2521 | /* Analog specific initialization */ |
2517 | dev->format = &format[0]; | 2522 | dev->format = &format[0]; |
2523 | |||
2524 | maxw = norm_maxw(dev); | ||
2525 | /* MaxPacketSize for em2800 is too small to capture at full resolution | ||
2526 | * use half of maxw as the scaler can only scale to 50% */ | ||
2527 | if (dev->board.is_em2800) | ||
2528 | maxw /= 2; | ||
2529 | |||
2518 | em28xx_set_video_format(dev, format[0].fourcc, | 2530 | em28xx_set_video_format(dev, format[0].fourcc, |
2519 | norm_maxw(dev), norm_maxh(dev)); | 2531 | maxw, norm_maxh(dev)); |
2520 | 2532 | ||
2521 | video_mux(dev, dev->ctl_input); | 2533 | video_mux(dev, dev->ctl_input); |
2522 | 2534 | ||
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index 2a2cb7ed0014..22e252bcc41e 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <media/videobuf-dvb.h> | 38 | #include <media/videobuf-dvb.h> |
39 | #endif | 39 | #endif |
40 | #include "tuner-xc2028.h" | 40 | #include "tuner-xc2028.h" |
41 | #include "xc5000.h" | ||
41 | #include "em28xx-reg.h" | 42 | #include "em28xx-reg.h" |
42 | 43 | ||
43 | /* Boards supported by driver */ | 44 | /* Boards supported by driver */ |
@@ -121,6 +122,9 @@ | |||
121 | #define EM28174_BOARD_PCTV_290E 78 | 122 | #define EM28174_BOARD_PCTV_290E 78 |
122 | #define EM2884_BOARD_TERRATEC_H5 79 | 123 | #define EM2884_BOARD_TERRATEC_H5 79 |
123 | #define EM28174_BOARD_PCTV_460E 80 | 124 | #define EM28174_BOARD_PCTV_460E 80 |
125 | #define EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C 81 | ||
126 | #define EM2884_BOARD_CINERGY_HTC_STICK 82 | ||
127 | #define EM2860_BOARD_HT_VIDBOX_NW03 83 | ||
124 | 128 | ||
125 | /* Limits minimum and default number of buffers */ | 129 | /* Limits minimum and default number of buffers */ |
126 | #define EM28XX_MIN_BUF 4 | 130 | #define EM28XX_MIN_BUF 4 |
@@ -594,6 +598,8 @@ struct em28xx { | |||
594 | int max_pkt_size; /* max packet size of isoc transaction */ | 598 | int max_pkt_size; /* max packet size of isoc transaction */ |
595 | int num_alt; /* Number of alternative settings */ | 599 | int num_alt; /* Number of alternative settings */ |
596 | unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ | 600 | unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ |
601 | int dvb_alt; /* alternate for DVB */ | ||
602 | unsigned int dvb_max_pkt_size; /* wMaxPacketSize for DVB */ | ||
597 | struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ | 603 | struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */ |
598 | char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc | 604 | char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc |
599 | transfer */ | 605 | transfer */ |
@@ -825,7 +831,7 @@ static inline unsigned int norm_maxw(struct em28xx *dev) | |||
825 | if (dev->board.is_webcam) | 831 | if (dev->board.is_webcam) |
826 | return dev->sensor_xres; | 832 | return dev->sensor_xres; |
827 | 833 | ||
828 | if (dev->board.max_range_640_480 || dev->board.is_em2800) | 834 | if (dev->board.max_range_640_480) |
829 | return 640; | 835 | return 640; |
830 | 836 | ||
831 | return 720; | 837 | return 720; |
diff --git a/drivers/media/video/fsl-viu.c b/drivers/media/video/fsl-viu.c index 27cb197d0bd6..27e3e0c0b219 100644 --- a/drivers/media/video/fsl-viu.c +++ b/drivers/media/video/fsl-viu.c | |||
@@ -1661,18 +1661,7 @@ static struct platform_driver viu_of_platform_driver = { | |||
1661 | }, | 1661 | }, |
1662 | }; | 1662 | }; |
1663 | 1663 | ||
1664 | static int __init viu_init(void) | 1664 | module_platform_driver(viu_of_platform_driver); |
1665 | { | ||
1666 | return platform_driver_register(&viu_of_platform_driver); | ||
1667 | } | ||
1668 | |||
1669 | static void __exit viu_exit(void) | ||
1670 | { | ||
1671 | platform_driver_unregister(&viu_of_platform_driver); | ||
1672 | } | ||
1673 | |||
1674 | module_init(viu_init); | ||
1675 | module_exit(viu_exit); | ||
1676 | 1665 | ||
1677 | MODULE_DESCRIPTION("Freescale Video-In(VIU)"); | 1666 | MODULE_DESCRIPTION("Freescale Video-In(VIU)"); |
1678 | MODULE_AUTHOR("Hongjun Chen"); | 1667 | MODULE_AUTHOR("Hongjun Chen"); |
diff --git a/drivers/media/video/gspca/Kconfig b/drivers/media/video/gspca/Kconfig index 103af3fe5aa0..dfe268bfa4f8 100644 --- a/drivers/media/video/gspca/Kconfig +++ b/drivers/media/video/gspca/Kconfig | |||
@@ -77,6 +77,16 @@ config USB_GSPCA_JEILINJ | |||
77 | To compile this driver as a module, choose M here: the | 77 | To compile this driver as a module, choose M here: the |
78 | module will be called gspca_jeilinj. | 78 | module will be called gspca_jeilinj. |
79 | 79 | ||
80 | config USB_GSPCA_JL2005BCD | ||
81 | tristate "JL2005B/C/D USB V4L2 driver" | ||
82 | depends on VIDEO_V4L2 && USB_GSPCA | ||
83 | help | ||
84 | Say Y here if you want support for cameras based the | ||
85 | JL2005B, JL2005C, or JL2005D chip. | ||
86 | |||
87 | To compile this driver as a module, choose M here: the | ||
88 | module will be called gspca_jl2005bcd. | ||
89 | |||
80 | config USB_GSPCA_KINECT | 90 | config USB_GSPCA_KINECT |
81 | tristate "Kinect sensor device USB Camera Driver" | 91 | tristate "Kinect sensor device USB Camera Driver" |
82 | depends on VIDEO_V4L2 && USB_GSPCA | 92 | depends on VIDEO_V4L2 && USB_GSPCA |
diff --git a/drivers/media/video/gspca/Makefile b/drivers/media/video/gspca/Makefile index f345f494d0f3..79ebe46e1ad7 100644 --- a/drivers/media/video/gspca/Makefile +++ b/drivers/media/video/gspca/Makefile | |||
@@ -5,6 +5,7 @@ obj-$(CONFIG_USB_GSPCA_CPIA1) += gspca_cpia1.o | |||
5 | obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o | 5 | obj-$(CONFIG_USB_GSPCA_ETOMS) += gspca_etoms.o |
6 | obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o | 6 | obj-$(CONFIG_USB_GSPCA_FINEPIX) += gspca_finepix.o |
7 | obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o | 7 | obj-$(CONFIG_USB_GSPCA_JEILINJ) += gspca_jeilinj.o |
8 | obj-$(CONFIG_USB_GSPCA_JL2005BCD) += gspca_jl2005bcd.o | ||
8 | obj-$(CONFIG_USB_GSPCA_KINECT) += gspca_kinect.o | 9 | obj-$(CONFIG_USB_GSPCA_KINECT) += gspca_kinect.o |
9 | obj-$(CONFIG_USB_GSPCA_KONICA) += gspca_konica.o | 10 | obj-$(CONFIG_USB_GSPCA_KONICA) += gspca_konica.o |
10 | obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o | 11 | obj-$(CONFIG_USB_GSPCA_MARS) += gspca_mars.o |
@@ -49,6 +50,7 @@ gspca_cpia1-objs := cpia1.o | |||
49 | gspca_etoms-objs := etoms.o | 50 | gspca_etoms-objs := etoms.o |
50 | gspca_finepix-objs := finepix.o | 51 | gspca_finepix-objs := finepix.o |
51 | gspca_jeilinj-objs := jeilinj.o | 52 | gspca_jeilinj-objs := jeilinj.o |
53 | gspca_jl2005bcd-objs := jl2005bcd.o | ||
52 | gspca_kinect-objs := kinect.o | 54 | gspca_kinect-objs := kinect.o |
53 | gspca_konica-objs := konica.o | 55 | gspca_konica-objs := konica.o |
54 | gspca_mars-objs := mars.o | 56 | gspca_mars-objs := mars.o |
diff --git a/drivers/media/video/gspca/benq.c b/drivers/media/video/gspca/benq.c index 636627b57dc9..9769f17915c0 100644 --- a/drivers/media/video/gspca/benq.c +++ b/drivers/media/video/gspca/benq.c | |||
@@ -76,7 +76,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
76 | gspca_dev->cam.cam_mode = vga_mode; | 76 | gspca_dev->cam.cam_mode = vga_mode; |
77 | gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); | 77 | gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); |
78 | gspca_dev->cam.no_urb_create = 1; | 78 | gspca_dev->cam.no_urb_create = 1; |
79 | gspca_dev->cam.reverse_alts = 1; | ||
80 | return 0; | 79 | return 0; |
81 | } | 80 | } |
82 | 81 | ||
@@ -135,13 +134,17 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
135 | 134 | ||
136 | static void sd_stopN(struct gspca_dev *gspca_dev) | 135 | static void sd_stopN(struct gspca_dev *gspca_dev) |
137 | { | 136 | { |
137 | struct usb_interface *intf; | ||
138 | |||
138 | reg_w(gspca_dev, 0x003c, 0x0003); | 139 | reg_w(gspca_dev, 0x003c, 0x0003); |
139 | reg_w(gspca_dev, 0x003c, 0x0004); | 140 | reg_w(gspca_dev, 0x003c, 0x0004); |
140 | reg_w(gspca_dev, 0x003c, 0x0005); | 141 | reg_w(gspca_dev, 0x003c, 0x0005); |
141 | reg_w(gspca_dev, 0x003c, 0x0006); | 142 | reg_w(gspca_dev, 0x003c, 0x0006); |
142 | reg_w(gspca_dev, 0x003c, 0x0007); | 143 | reg_w(gspca_dev, 0x003c, 0x0007); |
144 | |||
145 | intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); | ||
143 | usb_set_interface(gspca_dev->dev, gspca_dev->iface, | 146 | usb_set_interface(gspca_dev->dev, gspca_dev->iface, |
144 | gspca_dev->nbalt - 1); | 147 | intf->num_altsetting - 1); |
145 | } | 148 | } |
146 | 149 | ||
147 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 150 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
diff --git a/drivers/media/video/gspca/gl860/gl860.c b/drivers/media/video/gspca/gl860/gl860.c index a8f54c20e585..c84e26006fc3 100644 --- a/drivers/media/video/gspca/gl860/gl860.c +++ b/drivers/media/video/gspca/gl860/gl860.c | |||
@@ -337,7 +337,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
337 | return -1; | 337 | return -1; |
338 | 338 | ||
339 | cam = &gspca_dev->cam; | 339 | cam = &gspca_dev->cam; |
340 | gspca_dev->nbalt = 4; | ||
341 | 340 | ||
342 | switch (sd->sensor) { | 341 | switch (sd->sensor) { |
343 | case ID_MI1320: | 342 | case ID_MI1320: |
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 2ca10dfec91f..ca5a2b139d0b 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -633,23 +633,32 @@ static u32 which_bandwidth(struct gspca_dev *gspca_dev) | |||
633 | u32 bandwidth; | 633 | u32 bandwidth; |
634 | int i; | 634 | int i; |
635 | 635 | ||
636 | /* get the (max) image size */ | ||
636 | i = gspca_dev->curr_mode; | 637 | i = gspca_dev->curr_mode; |
637 | bandwidth = gspca_dev->cam.cam_mode[i].sizeimage; | 638 | bandwidth = gspca_dev->cam.cam_mode[i].sizeimage; |
638 | 639 | ||
639 | /* if the image is compressed, estimate the mean image size */ | 640 | /* if the image is compressed, estimate its mean size */ |
640 | if (bandwidth < gspca_dev->cam.cam_mode[i].width * | 641 | if (!gspca_dev->cam.needs_full_bandwidth && |
642 | bandwidth < gspca_dev->cam.cam_mode[i].width * | ||
641 | gspca_dev->cam.cam_mode[i].height) | 643 | gspca_dev->cam.cam_mode[i].height) |
642 | bandwidth /= 3; | 644 | bandwidth = bandwidth * 3 / 8; /* 0.375 */ |
643 | 645 | ||
644 | /* estimate the frame rate */ | 646 | /* estimate the frame rate */ |
645 | if (gspca_dev->sd_desc->get_streamparm) { | 647 | if (gspca_dev->sd_desc->get_streamparm) { |
646 | struct v4l2_streamparm parm; | 648 | struct v4l2_streamparm parm; |
647 | 649 | ||
648 | parm.parm.capture.timeperframe.denominator = 15; | ||
649 | gspca_dev->sd_desc->get_streamparm(gspca_dev, &parm); | 650 | gspca_dev->sd_desc->get_streamparm(gspca_dev, &parm); |
650 | bandwidth *= parm.parm.capture.timeperframe.denominator; | 651 | bandwidth *= parm.parm.capture.timeperframe.denominator; |
652 | bandwidth /= parm.parm.capture.timeperframe.numerator; | ||
651 | } else { | 653 | } else { |
652 | bandwidth *= 15; /* 15 fps */ | 654 | |
655 | /* don't hope more than 15 fps with USB 1.1 and | ||
656 | * image resolution >= 640x480 */ | ||
657 | if (gspca_dev->width >= 640 | ||
658 | && gspca_dev->dev->speed == USB_SPEED_FULL) | ||
659 | bandwidth *= 15; /* 15 fps */ | ||
660 | else | ||
661 | bandwidth *= 30; /* 30 fps */ | ||
653 | } | 662 | } |
654 | 663 | ||
655 | PDEBUG(D_STREAM, "min bandwidth: %d", bandwidth); | 664 | PDEBUG(D_STREAM, "min bandwidth: %d", bandwidth); |
@@ -667,9 +676,8 @@ struct ep_tb_s { | |||
667 | * build the table of the endpoints | 676 | * build the table of the endpoints |
668 | * and compute the minimum bandwidth for the image transfer | 677 | * and compute the minimum bandwidth for the image transfer |
669 | */ | 678 | */ |
670 | static int build_ep_tb(struct gspca_dev *gspca_dev, | 679 | static int build_isoc_ep_tb(struct gspca_dev *gspca_dev, |
671 | struct usb_interface *intf, | 680 | struct usb_interface *intf, |
672 | int xfer, | ||
673 | struct ep_tb_s *ep_tb) | 681 | struct ep_tb_s *ep_tb) |
674 | { | 682 | { |
675 | struct usb_host_endpoint *ep; | 683 | struct usb_host_endpoint *ep; |
@@ -687,17 +695,21 @@ static int build_ep_tb(struct gspca_dev *gspca_dev, | |||
687 | ep_tb->bandwidth = 2000 * 2000 * 120; | 695 | ep_tb->bandwidth = 2000 * 2000 * 120; |
688 | found = 0; | 696 | found = 0; |
689 | for (j = 0; j < nbalt; j++) { | 697 | for (j = 0; j < nbalt; j++) { |
690 | ep = alt_xfer(&intf->altsetting[j], xfer); | 698 | ep = alt_xfer(&intf->altsetting[j], |
699 | USB_ENDPOINT_XFER_ISOC); | ||
691 | if (ep == NULL) | 700 | if (ep == NULL) |
692 | continue; | 701 | continue; |
702 | if (ep->desc.bInterval == 0) { | ||
703 | pr_err("alt %d iso endp with 0 interval\n", j); | ||
704 | continue; | ||
705 | } | ||
693 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); | 706 | psize = le16_to_cpu(ep->desc.wMaxPacketSize); |
694 | if (!gspca_dev->cam.bulk) /* isoc */ | 707 | psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3)); |
695 | psize = (psize & 0x07ff) * | 708 | bandwidth = psize * 1000; |
696 | (1 + ((psize >> 11) & 3)); | ||
697 | bandwidth = psize * ep->desc.bInterval * 1000; | ||
698 | if (gspca_dev->dev->speed == USB_SPEED_HIGH | 709 | if (gspca_dev->dev->speed == USB_SPEED_HIGH |
699 | || gspca_dev->dev->speed == USB_SPEED_SUPER) | 710 | || gspca_dev->dev->speed == USB_SPEED_SUPER) |
700 | bandwidth *= 8; | 711 | bandwidth *= 8; |
712 | bandwidth /= 1 << (ep->desc.bInterval - 1); | ||
701 | if (bandwidth <= last_bw) | 713 | if (bandwidth <= last_bw) |
702 | continue; | 714 | continue; |
703 | if (bandwidth < ep_tb->bandwidth) { | 715 | if (bandwidth < ep_tb->bandwidth) { |
@@ -715,6 +727,23 @@ static int build_ep_tb(struct gspca_dev *gspca_dev, | |||
715 | ep_tb++; | 727 | ep_tb++; |
716 | } | 728 | } |
717 | 729 | ||
730 | /* | ||
731 | * If the camera: | ||
732 | * has a usb audio class interface (a built in usb mic); and | ||
733 | * is a usb 1 full speed device; and | ||
734 | * uses the max full speed iso bandwidth; and | ||
735 | * and has more than 1 alt setting | ||
736 | * then skip the highest alt setting to spare bandwidth for the mic | ||
737 | */ | ||
738 | if (gspca_dev->audio && | ||
739 | gspca_dev->dev->speed == USB_SPEED_FULL && | ||
740 | last_bw >= 1000000 && | ||
741 | i > 1) { | ||
742 | PDEBUG(D_STREAM, "dev has usb audio, skipping highest alt"); | ||
743 | i--; | ||
744 | ep_tb--; | ||
745 | } | ||
746 | |||
718 | /* get the requested bandwidth and start at the highest atlsetting */ | 747 | /* get the requested bandwidth and start at the highest atlsetting */ |
719 | bandwidth = which_bandwidth(gspca_dev); | 748 | bandwidth = which_bandwidth(gspca_dev); |
720 | ep_tb--; | 749 | ep_tb--; |
@@ -790,10 +819,7 @@ static int create_urbs(struct gspca_dev *gspca_dev, | |||
790 | ep->desc.bEndpointAddress); | 819 | ep->desc.bEndpointAddress); |
791 | urb->transfer_flags = URB_ISO_ASAP | 820 | urb->transfer_flags = URB_ISO_ASAP |
792 | | URB_NO_TRANSFER_DMA_MAP; | 821 | | URB_NO_TRANSFER_DMA_MAP; |
793 | if (gspca_dev->dev->speed == USB_SPEED_LOW) | 822 | urb->interval = 1 << (ep->desc.bInterval - 1); |
794 | urb->interval = ep->desc.bInterval; | ||
795 | else | ||
796 | urb->interval = 1 << (ep->desc.bInterval - 1); | ||
797 | urb->complete = isoc_irq; | 823 | urb->complete = isoc_irq; |
798 | urb->number_of_packets = npkt; | 824 | urb->number_of_packets = npkt; |
799 | for (i = 0; i < npkt; i++) { | 825 | for (i = 0; i < npkt; i++) { |
@@ -848,7 +874,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
848 | xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK | 874 | xfer = gspca_dev->cam.bulk ? USB_ENDPOINT_XFER_BULK |
849 | : USB_ENDPOINT_XFER_ISOC; | 875 | : USB_ENDPOINT_XFER_ISOC; |
850 | 876 | ||
851 | /* if the subdriver forced an altsetting, get the endpoint */ | 877 | /* if bulk or the subdriver forced an altsetting, get the endpoint */ |
852 | if (gspca_dev->alt != 0) { | 878 | if (gspca_dev->alt != 0) { |
853 | gspca_dev->alt--; /* (previous version compatibility) */ | 879 | gspca_dev->alt--; /* (previous version compatibility) */ |
854 | ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer); | 880 | ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer); |
@@ -863,7 +889,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
863 | 889 | ||
864 | /* else, compute the minimum bandwidth | 890 | /* else, compute the minimum bandwidth |
865 | * and build the endpoint table */ | 891 | * and build the endpoint table */ |
866 | alt_idx = build_ep_tb(gspca_dev, intf, xfer, ep_tb); | 892 | alt_idx = build_isoc_ep_tb(gspca_dev, intf, ep_tb); |
867 | if (alt_idx <= 0) { | 893 | if (alt_idx <= 0) { |
868 | pr_err("no transfer endpoint found\n"); | 894 | pr_err("no transfer endpoint found\n"); |
869 | ret = -EIO; | 895 | ret = -EIO; |
@@ -880,7 +906,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev) | |||
880 | for (;;) { | 906 | for (;;) { |
881 | if (alt != gspca_dev->alt) { | 907 | if (alt != gspca_dev->alt) { |
882 | alt = gspca_dev->alt; | 908 | alt = gspca_dev->alt; |
883 | if (gspca_dev->nbalt > 1) { | 909 | if (intf->num_altsetting > 1) { |
884 | ret = usb_set_interface(gspca_dev->dev, | 910 | ret = usb_set_interface(gspca_dev->dev, |
885 | gspca_dev->iface, | 911 | gspca_dev->iface, |
886 | alt); | 912 | alt); |
@@ -2300,15 +2326,14 @@ int gspca_dev_probe2(struct usb_interface *intf, | |||
2300 | } | 2326 | } |
2301 | gspca_dev->dev = dev; | 2327 | gspca_dev->dev = dev; |
2302 | gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber; | 2328 | gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber; |
2303 | gspca_dev->nbalt = intf->num_altsetting; | ||
2304 | 2329 | ||
2305 | /* check if any audio device */ | 2330 | /* check if any audio device */ |
2306 | if (dev->config->desc.bNumInterfaces != 1) { | 2331 | if (dev->actconfig->desc.bNumInterfaces != 1) { |
2307 | int i; | 2332 | int i; |
2308 | struct usb_interface *intf2; | 2333 | struct usb_interface *intf2; |
2309 | 2334 | ||
2310 | for (i = 0; i < dev->config->desc.bNumInterfaces; i++) { | 2335 | for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { |
2311 | intf2 = dev->config->interface[i]; | 2336 | intf2 = dev->actconfig->interface[i]; |
2312 | if (intf2 != NULL | 2337 | if (intf2 != NULL |
2313 | && intf2->altsetting != NULL | 2338 | && intf2->altsetting != NULL |
2314 | && intf2->altsetting->desc.bInterfaceClass == | 2339 | && intf2->altsetting->desc.bInterfaceClass == |
@@ -2389,7 +2414,7 @@ int gspca_dev_probe(struct usb_interface *intf, | |||
2389 | } | 2414 | } |
2390 | 2415 | ||
2391 | /* the USB video interface must be the first one */ | 2416 | /* the USB video interface must be the first one */ |
2392 | if (dev->config->desc.bNumInterfaces != 1 | 2417 | if (dev->actconfig->desc.bNumInterfaces != 1 |
2393 | && intf->cur_altsetting->desc.bInterfaceNumber != 0) | 2418 | && intf->cur_altsetting->desc.bInterfaceNumber != 0) |
2394 | return -ENODEV; | 2419 | return -ENODEV; |
2395 | 2420 | ||
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h index e444f16e1497..589009f4496f 100644 --- a/drivers/media/video/gspca/gspca.h +++ b/drivers/media/video/gspca/gspca.h | |||
@@ -69,7 +69,9 @@ struct cam { | |||
69 | u8 bulk; /* image transfer by 0:isoc / 1:bulk */ | 69 | u8 bulk; /* image transfer by 0:isoc / 1:bulk */ |
70 | u8 npkt; /* number of packets in an ISOC message | 70 | u8 npkt; /* number of packets in an ISOC message |
71 | * 0 is the default value: 32 packets */ | 71 | * 0 is the default value: 32 packets */ |
72 | u8 reverse_alts; /* Alt settings are in high to low order */ | 72 | u8 needs_full_bandwidth;/* Set this flag to notify the bandwidth calc. |
73 | * code that the cam fills all image buffers to | ||
74 | * the max, even when using compression. */ | ||
73 | }; | 75 | }; |
74 | 76 | ||
75 | struct gspca_dev; | 77 | struct gspca_dev; |
@@ -208,7 +210,6 @@ struct gspca_dev { | |||
208 | char memory; /* memory type (V4L2_MEMORY_xxx) */ | 210 | char memory; /* memory type (V4L2_MEMORY_xxx) */ |
209 | __u8 iface; /* USB interface number */ | 211 | __u8 iface; /* USB interface number */ |
210 | __u8 alt; /* USB alternate setting */ | 212 | __u8 alt; /* USB alternate setting */ |
211 | __u8 nbalt; /* number of USB alternate settings */ | ||
212 | u8 audio; /* presence of audio device */ | 213 | u8 audio; /* presence of audio device */ |
213 | }; | 214 | }; |
214 | 215 | ||
diff --git a/drivers/media/video/gspca/jl2005bcd.c b/drivers/media/video/gspca/jl2005bcd.c new file mode 100644 index 000000000000..53f58ef367cf --- /dev/null +++ b/drivers/media/video/gspca/jl2005bcd.c | |||
@@ -0,0 +1,554 @@ | |||
1 | /* | ||
2 | * Jeilin JL2005B/C/D library | ||
3 | * | ||
4 | * Copyright (C) 2011 Theodore Kilgore <kilgota@auburn.edu> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #define MODULE_NAME "jl2005bcd" | ||
22 | |||
23 | #include <linux/workqueue.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include "gspca.h" | ||
26 | |||
27 | |||
28 | MODULE_AUTHOR("Theodore Kilgore <kilgota@auburn.edu>"); | ||
29 | MODULE_DESCRIPTION("JL2005B/C/D USB Camera Driver"); | ||
30 | MODULE_LICENSE("GPL"); | ||
31 | |||
32 | /* Default timeouts, in ms */ | ||
33 | #define JL2005C_CMD_TIMEOUT 500 | ||
34 | #define JL2005C_DATA_TIMEOUT 1000 | ||
35 | |||
36 | /* Maximum transfer size to use. */ | ||
37 | #define JL2005C_MAX_TRANSFER 0x200 | ||
38 | #define FRAME_HEADER_LEN 16 | ||
39 | |||
40 | |||
41 | /* specific webcam descriptor */ | ||
42 | struct sd { | ||
43 | struct gspca_dev gspca_dev; /* !! must be the first item */ | ||
44 | unsigned char firmware_id[6]; | ||
45 | const struct v4l2_pix_format *cap_mode; | ||
46 | /* Driver stuff */ | ||
47 | struct work_struct work_struct; | ||
48 | struct workqueue_struct *work_thread; | ||
49 | u8 frame_brightness; | ||
50 | int block_size; /* block size of camera */ | ||
51 | int vga; /* 1 if vga cam, 0 if cif cam */ | ||
52 | }; | ||
53 | |||
54 | |||
55 | /* Camera has two resolution settings. What they are depends on model. */ | ||
56 | static const struct v4l2_pix_format cif_mode[] = { | ||
57 | {176, 144, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, | ||
58 | .bytesperline = 176, | ||
59 | .sizeimage = 176 * 144, | ||
60 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
61 | .priv = 0}, | ||
62 | {352, 288, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, | ||
63 | .bytesperline = 352, | ||
64 | .sizeimage = 352 * 288, | ||
65 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
66 | .priv = 0}, | ||
67 | }; | ||
68 | |||
69 | static const struct v4l2_pix_format vga_mode[] = { | ||
70 | {320, 240, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, | ||
71 | .bytesperline = 320, | ||
72 | .sizeimage = 320 * 240, | ||
73 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
74 | .priv = 0}, | ||
75 | {640, 480, V4L2_PIX_FMT_JL2005BCD, V4L2_FIELD_NONE, | ||
76 | .bytesperline = 640, | ||
77 | .sizeimage = 640 * 480, | ||
78 | .colorspace = V4L2_COLORSPACE_SRGB, | ||
79 | .priv = 0}, | ||
80 | }; | ||
81 | |||
82 | /* | ||
83 | * cam uses endpoint 0x03 to send commands, 0x84 for read commands, | ||
84 | * and 0x82 for bulk data transfer. | ||
85 | */ | ||
86 | |||
87 | /* All commands are two bytes only */ | ||
88 | static int jl2005c_write2(struct gspca_dev *gspca_dev, unsigned char *command) | ||
89 | { | ||
90 | int retval; | ||
91 | |||
92 | memcpy(gspca_dev->usb_buf, command, 2); | ||
93 | retval = usb_bulk_msg(gspca_dev->dev, | ||
94 | usb_sndbulkpipe(gspca_dev->dev, 3), | ||
95 | gspca_dev->usb_buf, 2, NULL, 500); | ||
96 | if (retval < 0) | ||
97 | pr_err("command write [%02x] error %d\n", | ||
98 | gspca_dev->usb_buf[0], retval); | ||
99 | return retval; | ||
100 | } | ||
101 | |||
102 | /* Response to a command is one byte in usb_buf[0], only if requested. */ | ||
103 | static int jl2005c_read1(struct gspca_dev *gspca_dev) | ||
104 | { | ||
105 | int retval; | ||
106 | |||
107 | retval = usb_bulk_msg(gspca_dev->dev, | ||
108 | usb_rcvbulkpipe(gspca_dev->dev, 0x84), | ||
109 | gspca_dev->usb_buf, 1, NULL, 500); | ||
110 | if (retval < 0) | ||
111 | pr_err("read command [0x%02x] error %d\n", | ||
112 | gspca_dev->usb_buf[0], retval); | ||
113 | return retval; | ||
114 | } | ||
115 | |||
116 | /* Response appears in gspca_dev->usb_buf[0] */ | ||
117 | static int jl2005c_read_reg(struct gspca_dev *gspca_dev, unsigned char reg) | ||
118 | { | ||
119 | int retval; | ||
120 | |||
121 | static u8 instruction[2] = {0x95, 0x00}; | ||
122 | /* put register to read in byte 1 */ | ||
123 | instruction[1] = reg; | ||
124 | /* Send the read request */ | ||
125 | retval = jl2005c_write2(gspca_dev, instruction); | ||
126 | if (retval < 0) | ||
127 | return retval; | ||
128 | retval = jl2005c_read1(gspca_dev); | ||
129 | |||
130 | return retval; | ||
131 | } | ||
132 | |||
133 | static int jl2005c_start_new_frame(struct gspca_dev *gspca_dev) | ||
134 | { | ||
135 | int i; | ||
136 | int retval; | ||
137 | int frame_brightness = 0; | ||
138 | |||
139 | static u8 instruction[2] = {0x7f, 0x01}; | ||
140 | |||
141 | retval = jl2005c_write2(gspca_dev, instruction); | ||
142 | if (retval < 0) | ||
143 | return retval; | ||
144 | |||
145 | i = 0; | ||
146 | while (i < 20 && !frame_brightness) { | ||
147 | /* If we tried 20 times, give up. */ | ||
148 | retval = jl2005c_read_reg(gspca_dev, 0x7e); | ||
149 | if (retval < 0) | ||
150 | return retval; | ||
151 | frame_brightness = gspca_dev->usb_buf[0]; | ||
152 | retval = jl2005c_read_reg(gspca_dev, 0x7d); | ||
153 | if (retval < 0) | ||
154 | return retval; | ||
155 | i++; | ||
156 | } | ||
157 | PDEBUG(D_FRAM, "frame_brightness is 0x%02x", gspca_dev->usb_buf[0]); | ||
158 | return retval; | ||
159 | } | ||
160 | |||
161 | static int jl2005c_write_reg(struct gspca_dev *gspca_dev, unsigned char reg, | ||
162 | unsigned char value) | ||
163 | { | ||
164 | int retval; | ||
165 | u8 instruction[2]; | ||
166 | |||
167 | instruction[0] = reg; | ||
168 | instruction[1] = value; | ||
169 | |||
170 | retval = jl2005c_write2(gspca_dev, instruction); | ||
171 | if (retval < 0) | ||
172 | return retval; | ||
173 | |||
174 | return retval; | ||
175 | } | ||
176 | |||
177 | static int jl2005c_get_firmware_id(struct gspca_dev *gspca_dev) | ||
178 | { | ||
179 | struct sd *sd = (struct sd *)gspca_dev; | ||
180 | int i = 0; | ||
181 | int retval = -1; | ||
182 | unsigned char regs_to_read[] = {0x57, 0x02, 0x03, 0x5d, 0x5e, 0x5f}; | ||
183 | |||
184 | PDEBUG(D_PROBE, "Running jl2005c_get_firmware_id"); | ||
185 | /* Read the first ID byte once for warmup */ | ||
186 | retval = jl2005c_read_reg(gspca_dev, regs_to_read[0]); | ||
187 | PDEBUG(D_PROBE, "response is %02x", gspca_dev->usb_buf[0]); | ||
188 | if (retval < 0) | ||
189 | return retval; | ||
190 | /* Now actually get the ID string */ | ||
191 | for (i = 0; i < 6; i++) { | ||
192 | retval = jl2005c_read_reg(gspca_dev, regs_to_read[i]); | ||
193 | if (retval < 0) | ||
194 | return retval; | ||
195 | sd->firmware_id[i] = gspca_dev->usb_buf[0]; | ||
196 | } | ||
197 | PDEBUG(D_PROBE, "firmware ID is %02x%02x%02x%02x%02x%02x", | ||
198 | sd->firmware_id[0], | ||
199 | sd->firmware_id[1], | ||
200 | sd->firmware_id[2], | ||
201 | sd->firmware_id[3], | ||
202 | sd->firmware_id[4], | ||
203 | sd->firmware_id[5]); | ||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | static int jl2005c_stream_start_vga_lg | ||
208 | (struct gspca_dev *gspca_dev) | ||
209 | { | ||
210 | int i; | ||
211 | int retval = -1; | ||
212 | static u8 instruction[][2] = { | ||
213 | {0x05, 0x00}, | ||
214 | {0x7c, 0x00}, | ||
215 | {0x7d, 0x18}, | ||
216 | {0x02, 0x00}, | ||
217 | {0x01, 0x00}, | ||
218 | {0x04, 0x52}, | ||
219 | }; | ||
220 | |||
221 | for (i = 0; i < ARRAY_SIZE(instruction); i++) { | ||
222 | msleep(60); | ||
223 | retval = jl2005c_write2(gspca_dev, instruction[i]); | ||
224 | if (retval < 0) | ||
225 | return retval; | ||
226 | } | ||
227 | msleep(60); | ||
228 | return retval; | ||
229 | } | ||
230 | |||
231 | static int jl2005c_stream_start_vga_small(struct gspca_dev *gspca_dev) | ||
232 | { | ||
233 | int i; | ||
234 | int retval = -1; | ||
235 | static u8 instruction[][2] = { | ||
236 | {0x06, 0x00}, | ||
237 | {0x7c, 0x00}, | ||
238 | {0x7d, 0x1a}, | ||
239 | {0x02, 0x00}, | ||
240 | {0x01, 0x00}, | ||
241 | {0x04, 0x52}, | ||
242 | }; | ||
243 | |||
244 | for (i = 0; i < ARRAY_SIZE(instruction); i++) { | ||
245 | msleep(60); | ||
246 | retval = jl2005c_write2(gspca_dev, instruction[i]); | ||
247 | if (retval < 0) | ||
248 | return retval; | ||
249 | } | ||
250 | msleep(60); | ||
251 | return retval; | ||
252 | } | ||
253 | |||
254 | static int jl2005c_stream_start_cif_lg(struct gspca_dev *gspca_dev) | ||
255 | { | ||
256 | int i; | ||
257 | int retval = -1; | ||
258 | static u8 instruction[][2] = { | ||
259 | {0x05, 0x00}, | ||
260 | {0x7c, 0x00}, | ||
261 | {0x7d, 0x30}, | ||
262 | {0x02, 0x00}, | ||
263 | {0x01, 0x00}, | ||
264 | {0x04, 0x42}, | ||
265 | }; | ||
266 | |||
267 | for (i = 0; i < ARRAY_SIZE(instruction); i++) { | ||
268 | msleep(60); | ||
269 | retval = jl2005c_write2(gspca_dev, instruction[i]); | ||
270 | if (retval < 0) | ||
271 | return retval; | ||
272 | } | ||
273 | msleep(60); | ||
274 | return retval; | ||
275 | } | ||
276 | |||
277 | static int jl2005c_stream_start_cif_small(struct gspca_dev *gspca_dev) | ||
278 | { | ||
279 | int i; | ||
280 | int retval = -1; | ||
281 | static u8 instruction[][2] = { | ||
282 | {0x06, 0x00}, | ||
283 | {0x7c, 0x00}, | ||
284 | {0x7d, 0x32}, | ||
285 | {0x02, 0x00}, | ||
286 | {0x01, 0x00}, | ||
287 | {0x04, 0x42}, | ||
288 | }; | ||
289 | |||
290 | for (i = 0; i < ARRAY_SIZE(instruction); i++) { | ||
291 | msleep(60); | ||
292 | retval = jl2005c_write2(gspca_dev, instruction[i]); | ||
293 | if (retval < 0) | ||
294 | return retval; | ||
295 | } | ||
296 | msleep(60); | ||
297 | return retval; | ||
298 | } | ||
299 | |||
300 | |||
301 | static int jl2005c_stop(struct gspca_dev *gspca_dev) | ||
302 | { | ||
303 | int retval; | ||
304 | |||
305 | retval = jl2005c_write_reg(gspca_dev, 0x07, 0x00); | ||
306 | return retval; | ||
307 | } | ||
308 | |||
309 | /* This function is called as a workqueue function and runs whenever the camera | ||
310 | * is streaming data. Because it is a workqueue function it is allowed to sleep | ||
311 | * so we can use synchronous USB calls. To avoid possible collisions with other | ||
312 | * threads attempting to use the camera's USB interface the gspca usb_lock is | ||
313 | * used when performing the one USB control operation inside the workqueue, | ||
314 | * which tells the camera to close the stream. In practice the only thing | ||
315 | * which needs to be protected against is the usb_set_interface call that | ||
316 | * gspca makes during stream_off. Otherwise the camera doesn't provide any | ||
317 | * controls that the user could try to change. | ||
318 | */ | ||
319 | static void jl2005c_dostream(struct work_struct *work) | ||
320 | { | ||
321 | struct sd *dev = container_of(work, struct sd, work_struct); | ||
322 | struct gspca_dev *gspca_dev = &dev->gspca_dev; | ||
323 | int bytes_left = 0; /* bytes remaining in current frame. */ | ||
324 | int data_len; /* size to use for the next read. */ | ||
325 | int header_read = 0; | ||
326 | unsigned char header_sig[2] = {0x4a, 0x4c}; | ||
327 | int act_len; | ||
328 | int packet_type; | ||
329 | int ret; | ||
330 | u8 *buffer; | ||
331 | |||
332 | buffer = kmalloc(JL2005C_MAX_TRANSFER, GFP_KERNEL | GFP_DMA); | ||
333 | if (!buffer) { | ||
334 | pr_err("Couldn't allocate USB buffer\n"); | ||
335 | goto quit_stream; | ||
336 | } | ||
337 | |||
338 | while (gspca_dev->present && gspca_dev->streaming) { | ||
339 | /* Check if this is a new frame. If so, start the frame first */ | ||
340 | if (!header_read) { | ||
341 | mutex_lock(&gspca_dev->usb_lock); | ||
342 | ret = jl2005c_start_new_frame(gspca_dev); | ||
343 | mutex_unlock(&gspca_dev->usb_lock); | ||
344 | if (ret < 0) | ||
345 | goto quit_stream; | ||
346 | ret = usb_bulk_msg(gspca_dev->dev, | ||
347 | usb_rcvbulkpipe(gspca_dev->dev, 0x82), | ||
348 | buffer, JL2005C_MAX_TRANSFER, &act_len, | ||
349 | JL2005C_DATA_TIMEOUT); | ||
350 | PDEBUG(D_PACK, | ||
351 | "Got %d bytes out of %d for header", | ||
352 | act_len, JL2005C_MAX_TRANSFER); | ||
353 | if (ret < 0 || act_len < JL2005C_MAX_TRANSFER) | ||
354 | goto quit_stream; | ||
355 | /* Check whether we actually got the first blodk */ | ||
356 | if (memcmp(header_sig, buffer, 2) != 0) { | ||
357 | pr_err("First block is not the first block\n"); | ||
358 | goto quit_stream; | ||
359 | } | ||
360 | /* total size to fetch is byte 7, times blocksize | ||
361 | * of which we already got act_len */ | ||
362 | bytes_left = buffer[0x07] * dev->block_size - act_len; | ||
363 | PDEBUG(D_PACK, "bytes_left = 0x%x", bytes_left); | ||
364 | /* We keep the header. It has other information, too.*/ | ||
365 | packet_type = FIRST_PACKET; | ||
366 | gspca_frame_add(gspca_dev, packet_type, | ||
367 | buffer, act_len); | ||
368 | header_read = 1; | ||
369 | } | ||
370 | while (bytes_left > 0 && gspca_dev->present) { | ||
371 | data_len = bytes_left > JL2005C_MAX_TRANSFER ? | ||
372 | JL2005C_MAX_TRANSFER : bytes_left; | ||
373 | ret = usb_bulk_msg(gspca_dev->dev, | ||
374 | usb_rcvbulkpipe(gspca_dev->dev, 0x82), | ||
375 | buffer, data_len, &act_len, | ||
376 | JL2005C_DATA_TIMEOUT); | ||
377 | if (ret < 0 || act_len < data_len) | ||
378 | goto quit_stream; | ||
379 | PDEBUG(D_PACK, | ||
380 | "Got %d bytes out of %d for frame", | ||
381 | data_len, bytes_left); | ||
382 | bytes_left -= data_len; | ||
383 | if (bytes_left == 0) { | ||
384 | packet_type = LAST_PACKET; | ||
385 | header_read = 0; | ||
386 | } else | ||
387 | packet_type = INTER_PACKET; | ||
388 | gspca_frame_add(gspca_dev, packet_type, | ||
389 | buffer, data_len); | ||
390 | } | ||
391 | } | ||
392 | quit_stream: | ||
393 | if (gspca_dev->present) { | ||
394 | mutex_lock(&gspca_dev->usb_lock); | ||
395 | jl2005c_stop(gspca_dev); | ||
396 | mutex_unlock(&gspca_dev->usb_lock); | ||
397 | } | ||
398 | kfree(buffer); | ||
399 | } | ||
400 | |||
401 | |||
402 | |||
403 | |||
404 | /* This function is called at probe time */ | ||
405 | static int sd_config(struct gspca_dev *gspca_dev, | ||
406 | const struct usb_device_id *id) | ||
407 | { | ||
408 | struct cam *cam; | ||
409 | struct sd *sd = (struct sd *) gspca_dev; | ||
410 | |||
411 | cam = &gspca_dev->cam; | ||
412 | /* We don't use the buffer gspca allocates so make it small. */ | ||
413 | cam->bulk_size = 64; | ||
414 | cam->bulk = 1; | ||
415 | /* For the rest, the camera needs to be detected */ | ||
416 | jl2005c_get_firmware_id(gspca_dev); | ||
417 | /* Here are some known firmware IDs | ||
418 | * First some JL2005B cameras | ||
419 | * {0x41, 0x07, 0x04, 0x2c, 0xe8, 0xf2} Sakar KidzCam | ||
420 | * {0x45, 0x02, 0x08, 0xb9, 0x00, 0xd2} No-name JL2005B | ||
421 | * JL2005C cameras | ||
422 | * {0x01, 0x0c, 0x16, 0x10, 0xf8, 0xc8} Argus DC-1512 | ||
423 | * {0x12, 0x04, 0x03, 0xc0, 0x00, 0xd8} ICarly | ||
424 | * {0x86, 0x08, 0x05, 0x02, 0x00, 0xd4} Jazz | ||
425 | * | ||
426 | * Based upon this scanty evidence, we can detect a CIF camera by | ||
427 | * testing byte 0 for 0x4x. | ||
428 | */ | ||
429 | if ((sd->firmware_id[0] & 0xf0) == 0x40) { | ||
430 | cam->cam_mode = cif_mode; | ||
431 | cam->nmodes = ARRAY_SIZE(cif_mode); | ||
432 | sd->block_size = 0x80; | ||
433 | } else { | ||
434 | cam->cam_mode = vga_mode; | ||
435 | cam->nmodes = ARRAY_SIZE(vga_mode); | ||
436 | sd->block_size = 0x200; | ||
437 | } | ||
438 | |||
439 | INIT_WORK(&sd->work_struct, jl2005c_dostream); | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | /* this function is called at probe and resume time */ | ||
445 | static int sd_init(struct gspca_dev *gspca_dev) | ||
446 | { | ||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | static int sd_start(struct gspca_dev *gspca_dev) | ||
451 | { | ||
452 | |||
453 | struct sd *sd = (struct sd *) gspca_dev; | ||
454 | sd->cap_mode = gspca_dev->cam.cam_mode; | ||
455 | |||
456 | switch (gspca_dev->width) { | ||
457 | case 640: | ||
458 | PDEBUG(D_STREAM, "Start streaming at vga resolution"); | ||
459 | jl2005c_stream_start_vga_lg(gspca_dev); | ||
460 | break; | ||
461 | case 320: | ||
462 | PDEBUG(D_STREAM, "Start streaming at qvga resolution"); | ||
463 | jl2005c_stream_start_vga_small(gspca_dev); | ||
464 | break; | ||
465 | case 352: | ||
466 | PDEBUG(D_STREAM, "Start streaming at cif resolution"); | ||
467 | jl2005c_stream_start_cif_lg(gspca_dev); | ||
468 | break; | ||
469 | case 176: | ||
470 | PDEBUG(D_STREAM, "Start streaming at qcif resolution"); | ||
471 | jl2005c_stream_start_cif_small(gspca_dev); | ||
472 | break; | ||
473 | default: | ||
474 | pr_err("Unknown resolution specified\n"); | ||
475 | return -1; | ||
476 | } | ||
477 | |||
478 | /* Start the workqueue function to do the streaming */ | ||
479 | sd->work_thread = create_singlethread_workqueue(MODULE_NAME); | ||
480 | queue_work(sd->work_thread, &sd->work_struct); | ||
481 | |||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | /* called on streamoff with alt==0 and on disconnect */ | ||
486 | /* the usb_lock is held at entry - restore on exit */ | ||
487 | static void sd_stop0(struct gspca_dev *gspca_dev) | ||
488 | { | ||
489 | struct sd *dev = (struct sd *) gspca_dev; | ||
490 | |||
491 | /* wait for the work queue to terminate */ | ||
492 | mutex_unlock(&gspca_dev->usb_lock); | ||
493 | /* This waits for sq905c_dostream to finish */ | ||
494 | destroy_workqueue(dev->work_thread); | ||
495 | dev->work_thread = NULL; | ||
496 | mutex_lock(&gspca_dev->usb_lock); | ||
497 | } | ||
498 | |||
499 | |||
500 | |||
501 | /* sub-driver description */ | ||
502 | static const struct sd_desc sd_desc = { | ||
503 | .name = MODULE_NAME, | ||
504 | /* .ctrls = none have been detected */ | ||
505 | /* .nctrls = ARRAY_SIZE(sd_ctrls), */ | ||
506 | .config = sd_config, | ||
507 | .init = sd_init, | ||
508 | .start = sd_start, | ||
509 | .stop0 = sd_stop0, | ||
510 | }; | ||
511 | |||
512 | /* -- module initialisation -- */ | ||
513 | static const __devinitdata struct usb_device_id device_table[] = { | ||
514 | {USB_DEVICE(0x0979, 0x0227)}, | ||
515 | {} | ||
516 | }; | ||
517 | MODULE_DEVICE_TABLE(usb, device_table); | ||
518 | |||
519 | /* -- device connect -- */ | ||
520 | static int sd_probe(struct usb_interface *intf, | ||
521 | const struct usb_device_id *id) | ||
522 | { | ||
523 | return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd), | ||
524 | THIS_MODULE); | ||
525 | } | ||
526 | |||
527 | static struct usb_driver sd_driver = { | ||
528 | .name = MODULE_NAME, | ||
529 | .id_table = device_table, | ||
530 | .probe = sd_probe, | ||
531 | .disconnect = gspca_disconnect, | ||
532 | #ifdef CONFIG_PM | ||
533 | .suspend = gspca_suspend, | ||
534 | .resume = gspca_resume, | ||
535 | #endif | ||
536 | }; | ||
537 | |||
538 | /* -- module insert / remove -- */ | ||
539 | static int __init sd_mod_init(void) | ||
540 | { | ||
541 | int ret; | ||
542 | |||
543 | ret = usb_register(&sd_driver); | ||
544 | if (ret < 0) | ||
545 | return ret; | ||
546 | return 0; | ||
547 | } | ||
548 | static void __exit sd_mod_exit(void) | ||
549 | { | ||
550 | usb_deregister(&sd_driver); | ||
551 | } | ||
552 | |||
553 | module_init(sd_mod_init); | ||
554 | module_exit(sd_mod_exit); | ||
diff --git a/drivers/media/video/gspca/konica.c b/drivers/media/video/gspca/konica.c index b1da7f4096c8..f0c0d74dfe92 100644 --- a/drivers/media/video/gspca/konica.c +++ b/drivers/media/video/gspca/konica.c | |||
@@ -247,9 +247,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
247 | gspca_dev->cam.cam_mode = vga_mode; | 247 | gspca_dev->cam.cam_mode = vga_mode; |
248 | gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); | 248 | gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode); |
249 | gspca_dev->cam.no_urb_create = 1; | 249 | gspca_dev->cam.no_urb_create = 1; |
250 | /* The highest alt setting has an isoc packetsize of 0, so we | ||
251 | don't want to use it */ | ||
252 | gspca_dev->nbalt--; | ||
253 | 250 | ||
254 | sd->brightness = BRIGHTNESS_DEFAULT; | 251 | sd->brightness = BRIGHTNESS_DEFAULT; |
255 | sd->contrast = CONTRAST_DEFAULT; | 252 | sd->contrast = CONTRAST_DEFAULT; |
diff --git a/drivers/media/video/gspca/mars.c b/drivers/media/video/gspca/mars.c index 5c2ea05c46b4..b0231465afae 100644 --- a/drivers/media/video/gspca/mars.c +++ b/drivers/media/video/gspca/mars.c | |||
@@ -263,7 +263,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
263 | cam->nmodes = ARRAY_SIZE(vga_mode); | 263 | cam->nmodes = ARRAY_SIZE(vga_mode); |
264 | cam->ctrls = sd->ctrls; | 264 | cam->ctrls = sd->ctrls; |
265 | sd->quality = QUALITY_DEF; | 265 | sd->quality = QUALITY_DEF; |
266 | gspca_dev->nbalt = 9; /* use the altsetting 08 */ | ||
267 | return 0; | 266 | return 0; |
268 | } | 267 | } |
269 | 268 | ||
diff --git a/drivers/media/video/gspca/nw80x.c b/drivers/media/video/gspca/nw80x.c index d4bec9321771..7167cac7359c 100644 --- a/drivers/media/video/gspca/nw80x.c +++ b/drivers/media/video/gspca/nw80x.c | |||
@@ -1763,8 +1763,8 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1763 | if ((unsigned) webcam >= NWEBCAMS) | 1763 | if ((unsigned) webcam >= NWEBCAMS) |
1764 | webcam = 0; | 1764 | webcam = 0; |
1765 | sd->webcam = webcam; | 1765 | sd->webcam = webcam; |
1766 | gspca_dev->cam.reverse_alts = 1; | ||
1767 | gspca_dev->cam.ctrls = sd->ctrls; | 1766 | gspca_dev->cam.ctrls = sd->ctrls; |
1767 | gspca_dev->cam.needs_full_bandwidth = 1; | ||
1768 | sd->ag_cnt = -1; | 1768 | sd->ag_cnt = -1; |
1769 | 1769 | ||
1770 | /* | 1770 | /* |
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c index 08b8ce1dee18..739e8a2a2d30 100644 --- a/drivers/media/video/gspca/ov519.c +++ b/drivers/media/video/gspca/ov519.c | |||
@@ -3348,7 +3348,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
3348 | case BRIDGE_W9968CF: | 3348 | case BRIDGE_W9968CF: |
3349 | cam->cam_mode = w9968cf_vga_mode; | 3349 | cam->cam_mode = w9968cf_vga_mode; |
3350 | cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); | 3350 | cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); |
3351 | cam->reverse_alts = 1; | ||
3352 | break; | 3351 | break; |
3353 | } | 3352 | } |
3354 | 3353 | ||
@@ -3684,8 +3683,8 @@ static void ov511_mode_init_regs(struct sd *sd) | |||
3684 | /* Check if we have enough bandwidth to disable compression */ | 3683 | /* Check if we have enough bandwidth to disable compression */ |
3685 | fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1; | 3684 | fps = (interlaced ? 60 : 30) / (sd->clockdiv + 1) + 1; |
3686 | needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2; | 3685 | needed = fps * sd->gspca_dev.width * sd->gspca_dev.height * 3 / 2; |
3687 | /* 1400 is a conservative estimate of the max nr of isoc packets/sec */ | 3686 | /* 1000 isoc packets/sec */ |
3688 | if (needed > 1400 * packet_size) { | 3687 | if (needed > 1000 * packet_size) { |
3689 | /* Enable Y and UV quantization and compression */ | 3688 | /* Enable Y and UV quantization and compression */ |
3690 | reg_w(sd, R511_COMP_EN, 0x07); | 3689 | reg_w(sd, R511_COMP_EN, 0x07); |
3691 | reg_w(sd, R511_COMP_LUT_EN, 0x03); | 3690 | reg_w(sd, R511_COMP_LUT_EN, 0x03); |
diff --git a/drivers/media/video/gspca/ov534_9.c b/drivers/media/video/gspca/ov534_9.c index f30060d50633..fbfa02affa13 100644 --- a/drivers/media/video/gspca/ov534_9.c +++ b/drivers/media/video/gspca/ov534_9.c | |||
@@ -71,6 +71,7 @@ struct sd { | |||
71 | enum sensors { | 71 | enum sensors { |
72 | SENSOR_OV965x, /* ov9657 */ | 72 | SENSOR_OV965x, /* ov9657 */ |
73 | SENSOR_OV971x, /* ov9712 */ | 73 | SENSOR_OV971x, /* ov9712 */ |
74 | SENSOR_OV562x, /* ov5621 */ | ||
74 | NSENSORS | 75 | NSENSORS |
75 | }; | 76 | }; |
76 | 77 | ||
@@ -207,6 +208,14 @@ static const struct v4l2_pix_format ov971x_mode[] = { | |||
207 | } | 208 | } |
208 | }; | 209 | }; |
209 | 210 | ||
211 | static const struct v4l2_pix_format ov562x_mode[] = { | ||
212 | {2592, 1680, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE, | ||
213 | .bytesperline = 2592, | ||
214 | .sizeimage = 2592 * 1680, | ||
215 | .colorspace = V4L2_COLORSPACE_SRGB | ||
216 | } | ||
217 | }; | ||
218 | |||
210 | static const u8 bridge_init[][2] = { | 219 | static const u8 bridge_init[][2] = { |
211 | {0x88, 0xf8}, | 220 | {0x88, 0xf8}, |
212 | {0x89, 0xff}, | 221 | {0x89, 0xff}, |
@@ -830,6 +839,124 @@ static const u8 ov965x_start_2_sxga[][2] = { | |||
830 | {0xa3, 0x41}, /* bd60 */ | 839 | {0xa3, 0x41}, /* bd60 */ |
831 | }; | 840 | }; |
832 | 841 | ||
842 | static const u8 ov562x_init[][2] = { | ||
843 | {0x88, 0x20}, | ||
844 | {0x89, 0x0a}, | ||
845 | {0x8a, 0x90}, | ||
846 | {0x8b, 0x06}, | ||
847 | {0x8c, 0x01}, | ||
848 | {0x8d, 0x10}, | ||
849 | {0x1c, 0x00}, | ||
850 | {0x1d, 0x48}, | ||
851 | {0x1d, 0x00}, | ||
852 | {0x1d, 0xff}, | ||
853 | {0x1c, 0x0a}, | ||
854 | {0x1d, 0x2e}, | ||
855 | {0x1d, 0x1e}, | ||
856 | }; | ||
857 | |||
858 | static const u8 ov562x_init_2[][2] = { | ||
859 | {0x12, 0x80}, | ||
860 | {0x11, 0x41}, | ||
861 | {0x13, 0x00}, | ||
862 | {0x10, 0x1e}, | ||
863 | {0x3b, 0x07}, | ||
864 | {0x5b, 0x40}, | ||
865 | {0x39, 0x07}, | ||
866 | {0x53, 0x02}, | ||
867 | {0x54, 0x60}, | ||
868 | {0x04, 0x20}, | ||
869 | {0x27, 0x04}, | ||
870 | {0x3d, 0x40}, | ||
871 | {0x36, 0x00}, | ||
872 | {0xc5, 0x04}, | ||
873 | {0x4e, 0x00}, | ||
874 | {0x4f, 0x93}, | ||
875 | {0x50, 0x7b}, | ||
876 | {0xca, 0x0c}, | ||
877 | {0xcb, 0x0f}, | ||
878 | {0x39, 0x07}, | ||
879 | {0x4a, 0x10}, | ||
880 | {0x3e, 0x0a}, | ||
881 | {0x3d, 0x00}, | ||
882 | {0x0c, 0x38}, | ||
883 | {0x38, 0x90}, | ||
884 | {0x46, 0x30}, | ||
885 | {0x4f, 0x93}, | ||
886 | {0x50, 0x7b}, | ||
887 | {0xab, 0x00}, | ||
888 | {0xca, 0x0c}, | ||
889 | {0xcb, 0x0f}, | ||
890 | {0x37, 0x02}, | ||
891 | {0x44, 0x48}, | ||
892 | {0x8d, 0x44}, | ||
893 | {0x2a, 0x00}, | ||
894 | {0x2b, 0x00}, | ||
895 | {0x32, 0x00}, | ||
896 | {0x38, 0x90}, | ||
897 | {0x53, 0x02}, | ||
898 | {0x54, 0x60}, | ||
899 | {0x12, 0x00}, | ||
900 | {0x17, 0x12}, | ||
901 | {0x18, 0xb4}, | ||
902 | {0x19, 0x0c}, | ||
903 | {0x1a, 0xf4}, | ||
904 | {0x03, 0x4a}, | ||
905 | {0x89, 0x20}, | ||
906 | {0x83, 0x80}, | ||
907 | {0xb7, 0x9d}, | ||
908 | {0xb6, 0x11}, | ||
909 | {0xb5, 0x55}, | ||
910 | {0xb4, 0x00}, | ||
911 | {0xa9, 0xf0}, | ||
912 | {0xa8, 0x0a}, | ||
913 | {0xb8, 0xf0}, | ||
914 | {0xb9, 0xf0}, | ||
915 | {0xba, 0xf0}, | ||
916 | {0x81, 0x07}, | ||
917 | {0x63, 0x44}, | ||
918 | {0x13, 0xc7}, | ||
919 | {0x14, 0x60}, | ||
920 | {0x33, 0x75}, | ||
921 | {0x2c, 0x00}, | ||
922 | {0x09, 0x00}, | ||
923 | {0x35, 0x30}, | ||
924 | {0x27, 0x04}, | ||
925 | {0x3c, 0x07}, | ||
926 | {0x3a, 0x0a}, | ||
927 | {0x3b, 0x07}, | ||
928 | {0x01, 0x40}, | ||
929 | {0x02, 0x40}, | ||
930 | {0x16, 0x40}, | ||
931 | {0x52, 0xb0}, | ||
932 | {0x51, 0x83}, | ||
933 | {0x21, 0xbb}, | ||
934 | {0x22, 0x10}, | ||
935 | {0x23, 0x03}, | ||
936 | {0x35, 0x38}, | ||
937 | {0x20, 0x90}, | ||
938 | {0x28, 0x30}, | ||
939 | {0x73, 0xe1}, | ||
940 | {0x6c, 0x00}, | ||
941 | {0x6d, 0x80}, | ||
942 | {0x6e, 0x00}, | ||
943 | {0x70, 0x04}, | ||
944 | {0x71, 0x00}, | ||
945 | {0x8d, 0x04}, | ||
946 | {0x64, 0x00}, | ||
947 | {0x65, 0x00}, | ||
948 | {0x66, 0x00}, | ||
949 | {0x67, 0x00}, | ||
950 | {0x68, 0x00}, | ||
951 | {0x69, 0x00}, | ||
952 | {0x6a, 0x00}, | ||
953 | {0x6b, 0x00}, | ||
954 | {0x71, 0x94}, | ||
955 | {0x74, 0x20}, | ||
956 | {0x80, 0x09}, | ||
957 | {0x85, 0xc0}, | ||
958 | }; | ||
959 | |||
833 | static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val) | 960 | static void reg_w_i(struct gspca_dev *gspca_dev, u16 reg, u8 val) |
834 | { | 961 | { |
835 | struct usb_device *udev = gspca_dev->dev; | 962 | struct usb_device *udev = gspca_dev->dev; |
@@ -1210,6 +1337,17 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
1210 | reg_w(gspca_dev, 0x56, 0x1f); | 1337 | reg_w(gspca_dev, 0x56, 0x1f); |
1211 | else | 1338 | else |
1212 | reg_w(gspca_dev, 0x56, 0x17); | 1339 | reg_w(gspca_dev, 0x56, 0x17); |
1340 | } else if ((sensor_id & 0xfff0) == 0x5620) { | ||
1341 | sd->sensor = SENSOR_OV562x; | ||
1342 | |||
1343 | gspca_dev->cam.cam_mode = ov562x_mode; | ||
1344 | gspca_dev->cam.nmodes = ARRAY_SIZE(ov562x_mode); | ||
1345 | |||
1346 | reg_w_array(gspca_dev, ov562x_init, | ||
1347 | ARRAY_SIZE(ov562x_init)); | ||
1348 | sccb_w_array(gspca_dev, ov562x_init_2, | ||
1349 | ARRAY_SIZE(ov562x_init_2)); | ||
1350 | reg_w(gspca_dev, 0xe0, 0x00); | ||
1213 | } else { | 1351 | } else { |
1214 | err("Unknown sensor %04x", sensor_id); | 1352 | err("Unknown sensor %04x", sensor_id); |
1215 | return -EINVAL; | 1353 | return -EINVAL; |
@@ -1222,7 +1360,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
1222 | { | 1360 | { |
1223 | struct sd *sd = (struct sd *) gspca_dev; | 1361 | struct sd *sd = (struct sd *) gspca_dev; |
1224 | 1362 | ||
1225 | if (sd->sensor == SENSOR_OV971x) | 1363 | if (sd->sensor == SENSOR_OV971x || sd->sensor == SENSOR_OV562x) |
1226 | return gspca_dev->usb_err; | 1364 | return gspca_dev->usb_err; |
1227 | switch (gspca_dev->curr_mode) { | 1365 | switch (gspca_dev->curr_mode) { |
1228 | case QVGA_MODE: /* 320x240 */ | 1366 | case QVGA_MODE: /* 320x240 */ |
@@ -1409,6 +1547,7 @@ static const struct sd_desc sd_desc = { | |||
1409 | static const struct usb_device_id device_table[] = { | 1547 | static const struct usb_device_id device_table[] = { |
1410 | {USB_DEVICE(0x05a9, 0x8065)}, | 1548 | {USB_DEVICE(0x05a9, 0x8065)}, |
1411 | {USB_DEVICE(0x06f8, 0x3003)}, | 1549 | {USB_DEVICE(0x06f8, 0x3003)}, |
1550 | {USB_DEVICE(0x05a9, 0x1550)}, | ||
1412 | {} | 1551 | {} |
1413 | }; | 1552 | }; |
1414 | 1553 | ||
diff --git a/drivers/media/video/gspca/pac207.c b/drivers/media/video/gspca/pac207.c index ece8b1e82a13..3844c49f269c 100644 --- a/drivers/media/video/gspca/pac207.c +++ b/drivers/media/video/gspca/pac207.c | |||
@@ -41,14 +41,14 @@ MODULE_LICENSE("GPL"); | |||
41 | #define PAC207_BRIGHTNESS_DEFAULT 46 | 41 | #define PAC207_BRIGHTNESS_DEFAULT 46 |
42 | 42 | ||
43 | #define PAC207_EXPOSURE_MIN 3 | 43 | #define PAC207_EXPOSURE_MIN 3 |
44 | #define PAC207_EXPOSURE_MAX 26 | 44 | #define PAC207_EXPOSURE_MAX 90 /* 1 sec expo time / 1 fps */ |
45 | #define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 */ | 45 | #define PAC207_EXPOSURE_DEFAULT 5 /* power on default: 3 */ |
46 | #define PAC207_EXPOSURE_KNEE 8 /* 4 = 30 fps, 11 = 8, 15 = 6 */ | 46 | #define PAC207_EXPOSURE_KNEE 9 /* fps: 90 / exposure -> 9: 10 fps */ |
47 | 47 | ||
48 | #define PAC207_GAIN_MIN 0 | 48 | #define PAC207_GAIN_MIN 0 |
49 | #define PAC207_GAIN_MAX 31 | 49 | #define PAC207_GAIN_MAX 31 |
50 | #define PAC207_GAIN_DEFAULT 9 /* power on default: 9 */ | 50 | #define PAC207_GAIN_DEFAULT 7 /* power on default: 9 */ |
51 | #define PAC207_GAIN_KNEE 31 | 51 | #define PAC207_GAIN_KNEE 15 |
52 | 52 | ||
53 | #define PAC207_AUTOGAIN_DEADZONE 30 | 53 | #define PAC207_AUTOGAIN_DEADZONE 30 |
54 | 54 | ||
@@ -332,7 +332,7 @@ static void pac207_do_auto_gain(struct gspca_dev *gspca_dev) | |||
332 | if (sd->autogain_ignore_frames > 0) | 332 | if (sd->autogain_ignore_frames > 0) |
333 | sd->autogain_ignore_frames--; | 333 | sd->autogain_ignore_frames--; |
334 | else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, | 334 | else if (gspca_auto_gain_n_exposure(gspca_dev, avg_lum, |
335 | 100, PAC207_AUTOGAIN_DEADZONE, | 335 | 90, PAC207_AUTOGAIN_DEADZONE, |
336 | PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE)) | 336 | PAC207_GAIN_KNEE, PAC207_EXPOSURE_KNEE)) |
337 | sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; | 337 | sd->autogain_ignore_frames = PAC_AUTOGAIN_IGNORE_FRAMES; |
338 | } | 338 | } |
diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 2811195258c4..9db2b34d172c 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c | |||
@@ -1197,6 +1197,7 @@ static const struct usb_device_id device_table[] = { | |||
1197 | {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP}, | 1197 | {USB_DEVICE(0x093a, 0x2629), .driver_info = FL_VFLIP}, |
1198 | {USB_DEVICE(0x093a, 0x262a)}, | 1198 | {USB_DEVICE(0x093a, 0x262a)}, |
1199 | {USB_DEVICE(0x093a, 0x262c)}, | 1199 | {USB_DEVICE(0x093a, 0x262c)}, |
1200 | {USB_DEVICE(0x145f, 0x013c)}, | ||
1200 | {} | 1201 | {} |
1201 | }; | 1202 | }; |
1202 | MODULE_DEVICE_TABLE(usb, device_table); | 1203 | MODULE_DEVICE_TABLE(usb, device_table); |
diff --git a/drivers/media/video/gspca/se401.c b/drivers/media/video/gspca/se401.c index 1494e1829d36..bb70092c2229 100644 --- a/drivers/media/video/gspca/se401.c +++ b/drivers/media/video/gspca/se401.c | |||
@@ -376,7 +376,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
376 | cam->bulk_size = BULK_SIZE; | 376 | cam->bulk_size = BULK_SIZE; |
377 | cam->bulk_nurbs = 4; | 377 | cam->bulk_nurbs = 4; |
378 | cam->ctrls = sd->ctrls; | 378 | cam->ctrls = sd->ctrls; |
379 | gspca_dev->nbalt = 1; /* Ignore the bogus isoc alt settings */ | ||
380 | sd->resetlevel = 0x2d; /* Set initial resetlevel */ | 379 | sd->resetlevel = 0x2d; /* Set initial resetlevel */ |
381 | 380 | ||
382 | /* See if the camera supports brightness */ | 381 | /* See if the camera supports brightness */ |
@@ -395,6 +394,14 @@ static int sd_init(struct gspca_dev *gspca_dev) | |||
395 | return 0; | 394 | return 0; |
396 | } | 395 | } |
397 | 396 | ||
397 | /* function called at start time before URB creation */ | ||
398 | static int sd_isoc_init(struct gspca_dev *gspca_dev) | ||
399 | { | ||
400 | gspca_dev->alt = 1; /* Ignore the bogus isoc alt settings */ | ||
401 | |||
402 | return gspca_dev->usb_err; | ||
403 | } | ||
404 | |||
398 | /* -- start the camera -- */ | 405 | /* -- start the camera -- */ |
399 | static int sd_start(struct gspca_dev *gspca_dev) | 406 | static int sd_start(struct gspca_dev *gspca_dev) |
400 | { | 407 | { |
@@ -714,6 +721,7 @@ static const struct sd_desc sd_desc = { | |||
714 | .nctrls = ARRAY_SIZE(sd_ctrls), | 721 | .nctrls = ARRAY_SIZE(sd_ctrls), |
715 | .config = sd_config, | 722 | .config = sd_config, |
716 | .init = sd_init, | 723 | .init = sd_init, |
724 | .isoc_init = sd_isoc_init, | ||
717 | .start = sd_start, | 725 | .start = sd_start, |
718 | .stopN = sd_stopN, | 726 | .stopN = sd_stopN, |
719 | .dq_callback = sd_dq_callback, | 727 | .dq_callback = sd_dq_callback, |
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 33cabc342dcf..9e198b45c3c8 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c | |||
@@ -2048,6 +2048,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
2048 | struct cam *cam; | 2048 | struct cam *cam; |
2049 | 2049 | ||
2050 | cam = &gspca_dev->cam; | 2050 | cam = &gspca_dev->cam; |
2051 | cam->needs_full_bandwidth = 1; | ||
2051 | 2052 | ||
2052 | sd->sensor = (id->driver_info >> 8) & 0xff; | 2053 | sd->sensor = (id->driver_info >> 8) & 0xff; |
2053 | sd->i2c_addr = id->driver_info & 0xff; | 2054 | sd->i2c_addr = id->driver_info & 0xff; |
@@ -2233,6 +2234,42 @@ static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode) | |||
2233 | } | 2234 | } |
2234 | } | 2235 | } |
2235 | 2236 | ||
2237 | static int sd_isoc_init(struct gspca_dev *gspca_dev) | ||
2238 | { | ||
2239 | struct usb_interface *intf; | ||
2240 | u32 flags = gspca_dev->cam.cam_mode[(int)gspca_dev->curr_mode].priv; | ||
2241 | |||
2242 | /* | ||
2243 | * When using the SN9C20X_I420 fmt the sn9c20x needs more bandwidth | ||
2244 | * than our regular bandwidth calculations reserve, so we force the | ||
2245 | * use of a specific altsetting when using the SN9C20X_I420 fmt. | ||
2246 | */ | ||
2247 | if (!(flags & (MODE_RAW | MODE_JPEG))) { | ||
2248 | intf = usb_ifnum_to_if(gspca_dev->dev, gspca_dev->iface); | ||
2249 | |||
2250 | if (intf->num_altsetting != 9) { | ||
2251 | pr_warn("sn9c20x camera with unknown number of alt " | ||
2252 | "settings (%d), please report!\n", | ||
2253 | intf->num_altsetting); | ||
2254 | gspca_dev->alt = intf->num_altsetting; | ||
2255 | return 0; | ||
2256 | } | ||
2257 | |||
2258 | switch (gspca_dev->width) { | ||
2259 | case 160: /* 160x120 */ | ||
2260 | gspca_dev->alt = 2; | ||
2261 | break; | ||
2262 | case 320: /* 320x240 */ | ||
2263 | gspca_dev->alt = 6; | ||
2264 | break; | ||
2265 | default: /* >= 640x480 */ | ||
2266 | gspca_dev->alt = 9; | ||
2267 | } | ||
2268 | } | ||
2269 | |||
2270 | return 0; | ||
2271 | } | ||
2272 | |||
2236 | #define HW_WIN(mode, hstart, vstart) \ | 2273 | #define HW_WIN(mode, hstart, vstart) \ |
2237 | ((const u8 []){hstart, 0, vstart, 0, \ | 2274 | ((const u8 []){hstart, 0, vstart, 0, \ |
2238 | (mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \ | 2275 | (mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \ |
@@ -2473,6 +2510,7 @@ static const struct sd_desc sd_desc = { | |||
2473 | .nctrls = ARRAY_SIZE(sd_ctrls), | 2510 | .nctrls = ARRAY_SIZE(sd_ctrls), |
2474 | .config = sd_config, | 2511 | .config = sd_config, |
2475 | .init = sd_init, | 2512 | .init = sd_init, |
2513 | .isoc_init = sd_isoc_init, | ||
2476 | .start = sd_start, | 2514 | .start = sd_start, |
2477 | .stopN = sd_stopN, | 2515 | .stopN = sd_stopN, |
2478 | .pkt_scan = sd_pkt_scan, | 2516 | .pkt_scan = sd_pkt_scan, |
diff --git a/drivers/media/video/gspca/sonixb.c b/drivers/media/video/gspca/sonixb.c index ddb392dc4f2d..6a1148d7fe92 100644 --- a/drivers/media/video/gspca/sonixb.c +++ b/drivers/media/video/gspca/sonixb.c | |||
@@ -1079,20 +1079,23 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1079 | } | 1079 | } |
1080 | cam->npkt = 36; /* 36 packets per ISOC message */ | 1080 | cam->npkt = 36; /* 36 packets per ISOC message */ |
1081 | 1081 | ||
1082 | if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) { | ||
1083 | sd->ctrls[EXPOSURE].min = COARSE_EXPOSURE_MIN; | ||
1084 | sd->ctrls[EXPOSURE].max = COARSE_EXPOSURE_MAX; | ||
1085 | sd->ctrls[EXPOSURE].def = COARSE_EXPOSURE_DEF; | ||
1086 | } | ||
1087 | |||
1088 | return 0; | 1082 | return 0; |
1089 | } | 1083 | } |
1090 | 1084 | ||
1091 | /* this function is called at probe and resume time */ | 1085 | /* this function is called at probe and resume time */ |
1092 | static int sd_init(struct gspca_dev *gspca_dev) | 1086 | static int sd_init(struct gspca_dev *gspca_dev) |
1093 | { | 1087 | { |
1088 | struct sd *sd = (struct sd *) gspca_dev; | ||
1094 | const __u8 stop = 0x09; /* Disable stream turn of LED */ | 1089 | const __u8 stop = 0x09; /* Disable stream turn of LED */ |
1095 | 1090 | ||
1091 | if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) { | ||
1092 | sd->ctrls[EXPOSURE].min = COARSE_EXPOSURE_MIN; | ||
1093 | sd->ctrls[EXPOSURE].max = COARSE_EXPOSURE_MAX; | ||
1094 | sd->ctrls[EXPOSURE].def = COARSE_EXPOSURE_DEF; | ||
1095 | if (sd->ctrls[EXPOSURE].val > COARSE_EXPOSURE_MAX) | ||
1096 | sd->ctrls[EXPOSURE].val = COARSE_EXPOSURE_DEF; | ||
1097 | } | ||
1098 | |||
1096 | reg_w(gspca_dev, 0x01, &stop, 1); | 1099 | reg_w(gspca_dev, 0x01, &stop, 1); |
1097 | 1100 | ||
1098 | return 0; | 1101 | return 0; |
diff --git a/drivers/media/video/gspca/sonixj.c b/drivers/media/video/gspca/sonixj.c index afa3186b8038..0c9e6ddabd2c 100644 --- a/drivers/media/video/gspca/sonixj.c +++ b/drivers/media/video/gspca/sonixj.c | |||
@@ -1235,7 +1235,7 @@ static const u8 po2030n_sensor_param1[][8] = { | |||
1235 | {DELAY, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */ | 1235 | {DELAY, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* delay 8ms */ |
1236 | {0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10}, | 1236 | {0xa1, 0x6e, 0x1b, 0xf4, 0x00, 0x00, 0x00, 0x10}, |
1237 | {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, | 1237 | {0xa1, 0x6e, 0x15, 0x04, 0x00, 0x00, 0x00, 0x10}, |
1238 | {0xd1, 0x6e, 0x16, 0x50, 0x40, 0x49, 0x40, 0x10}, | 1238 | {0xd1, 0x6e, 0x16, 0x40, 0x40, 0x40, 0x40, 0x10}, /* RGBG gains */ |
1239 | /*param2*/ | 1239 | /*param2*/ |
1240 | {0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10}, | 1240 | {0xa1, 0x6e, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x10}, |
1241 | {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10}, | 1241 | {0xa1, 0x6e, 0x04, 0x03, 0x00, 0x00, 0x00, 0x10}, |
@@ -1779,10 +1779,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
1779 | sd->ag_cnt = -1; | 1779 | sd->ag_cnt = -1; |
1780 | sd->quality = QUALITY_DEF; | 1780 | sd->quality = QUALITY_DEF; |
1781 | 1781 | ||
1782 | /* if USB 1.1, let some bandwidth for the audio device */ | ||
1783 | if (gspca_dev->audio && gspca_dev->dev->speed < USB_SPEED_HIGH) | ||
1784 | gspca_dev->nbalt--; | ||
1785 | |||
1786 | INIT_WORK(&sd->work, qual_upd); | 1782 | INIT_WORK(&sd->work, qual_upd); |
1787 | 1783 | ||
1788 | return 0; | 1784 | return 0; |
@@ -2063,6 +2059,16 @@ static void setredblue(struct gspca_dev *gspca_dev) | |||
2063 | { | 2059 | { |
2064 | struct sd *sd = (struct sd *) gspca_dev; | 2060 | struct sd *sd = (struct sd *) gspca_dev; |
2065 | 2061 | ||
2062 | if (sd->sensor == SENSOR_PO2030N) { | ||
2063 | u8 rg1b[] = /* red green1 blue (no g2) */ | ||
2064 | {0xc1, 0x6e, 0x16, 0x00, 0x40, 0x00, 0x00, 0x10}; | ||
2065 | |||
2066 | /* 0x40 = normal value = gain x 1 */ | ||
2067 | rg1b[3] = sd->ctrls[RED].val * 2; | ||
2068 | rg1b[5] = sd->ctrls[BLUE].val * 2; | ||
2069 | i2c_w8(gspca_dev, rg1b); | ||
2070 | return; | ||
2071 | } | ||
2066 | reg_w1(gspca_dev, 0x05, sd->ctrls[RED].val); | 2072 | reg_w1(gspca_dev, 0x05, sd->ctrls[RED].val); |
2067 | /* reg_w1(gspca_dev, 0x07, 32); */ | 2073 | /* reg_w1(gspca_dev, 0x07, 32); */ |
2068 | reg_w1(gspca_dev, 0x06, sd->ctrls[BLUE].val); | 2074 | reg_w1(gspca_dev, 0x06, sd->ctrls[BLUE].val); |
@@ -2397,7 +2403,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
2397 | reg_w1(gspca_dev, 0x17, reg17); | 2403 | reg_w1(gspca_dev, 0x17, reg17); |
2398 | reg01 &= ~S_PWR_DN; /* sensor power on */ | 2404 | reg01 &= ~S_PWR_DN; /* sensor power on */ |
2399 | reg_w1(gspca_dev, 0x01, reg01); | 2405 | reg_w1(gspca_dev, 0x01, reg01); |
2400 | reg01 &= ~SYS_SEL_48M; | 2406 | reg01 &= ~SCL_SEL_OD; /* remove open-drain mode */ |
2401 | reg_w1(gspca_dev, 0x01, reg01); | 2407 | reg_w1(gspca_dev, 0x01, reg01); |
2402 | 2408 | ||
2403 | switch (sd->sensor) { | 2409 | switch (sd->sensor) { |
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index 259a0c73c664..4a5f209ce719 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c | |||
@@ -451,7 +451,7 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
451 | } | 451 | } |
452 | 452 | ||
453 | cam = &gspca_dev->cam; | 453 | cam = &gspca_dev->cam; |
454 | gspca_dev->nbalt = 7 + 1; /* choose alternate 7 first */ | 454 | cam->needs_full_bandwidth = 1; |
455 | 455 | ||
456 | sd->chip_revision = id->driver_info; | 456 | sd->chip_revision = id->driver_info; |
457 | if (sd->chip_revision == Rev012A) { | 457 | if (sd->chip_revision == Rev012A) { |
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index 6f878f6c6e99..91d99b4cc57b 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c | |||
@@ -304,7 +304,7 @@ static int stv06xx_isoc_init(struct gspca_dev *gspca_dev) | |||
304 | struct sd *sd = (struct sd *) gspca_dev; | 304 | struct sd *sd = (struct sd *) gspca_dev; |
305 | 305 | ||
306 | /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ | 306 | /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ |
307 | alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; | 307 | alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; |
308 | alt->endpoint[0].desc.wMaxPacketSize = | 308 | alt->endpoint[0].desc.wMaxPacketSize = |
309 | cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]); | 309 | cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]); |
310 | 310 | ||
@@ -317,7 +317,7 @@ static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev) | |||
317 | struct usb_host_interface *alt; | 317 | struct usb_host_interface *alt; |
318 | struct sd *sd = (struct sd *) gspca_dev; | 318 | struct sd *sd = (struct sd *) gspca_dev; |
319 | 319 | ||
320 | alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; | 320 | alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; |
321 | packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); | 321 | packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); |
322 | min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode]; | 322 | min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode]; |
323 | if (packet_size <= min_packet_size) | 323 | if (packet_size <= min_packet_size) |
diff --git a/drivers/media/video/gspca/t613.c b/drivers/media/video/gspca/t613.c index ea44deb66af4..9b9f85a8e60e 100644 --- a/drivers/media/video/gspca/t613.c +++ b/drivers/media/video/gspca/t613.c | |||
@@ -30,6 +30,7 @@ | |||
30 | 30 | ||
31 | #define MODULE_NAME "t613" | 31 | #define MODULE_NAME "t613" |
32 | 32 | ||
33 | #include <linux/input.h> | ||
33 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
34 | #include "gspca.h" | 35 | #include "gspca.h" |
35 | 36 | ||
@@ -57,6 +58,7 @@ struct sd { | |||
57 | u8 effect; | 58 | u8 effect; |
58 | 59 | ||
59 | u8 sensor; | 60 | u8 sensor; |
61 | u8 button_pressed; | ||
60 | }; | 62 | }; |
61 | enum sensors { | 63 | enum sensors { |
62 | SENSOR_OM6802, | 64 | SENSOR_OM6802, |
@@ -1095,15 +1097,35 @@ static void sd_stopN(struct gspca_dev *gspca_dev) | |||
1095 | msleep(20); | 1097 | msleep(20); |
1096 | reg_w(gspca_dev, 0x0309); | 1098 | reg_w(gspca_dev, 0x0309); |
1097 | } | 1099 | } |
1100 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | ||
1101 | /* If the last button state is pressed, release it now! */ | ||
1102 | if (sd->button_pressed) { | ||
1103 | input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0); | ||
1104 | input_sync(gspca_dev->input_dev); | ||
1105 | sd->button_pressed = 0; | ||
1106 | } | ||
1107 | #endif | ||
1098 | } | 1108 | } |
1099 | 1109 | ||
1100 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, | 1110 | static void sd_pkt_scan(struct gspca_dev *gspca_dev, |
1101 | u8 *data, /* isoc packet */ | 1111 | u8 *data, /* isoc packet */ |
1102 | int len) /* iso packet length */ | 1112 | int len) /* iso packet length */ |
1103 | { | 1113 | { |
1114 | struct sd *sd = (struct sd *) gspca_dev; | ||
1104 | int pkt_type; | 1115 | int pkt_type; |
1105 | 1116 | ||
1106 | if (data[0] == 0x5a) { | 1117 | if (data[0] == 0x5a) { |
1118 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | ||
1119 | if (len > 20) { | ||
1120 | u8 state = (data[20] & 0x80) ? 1 : 0; | ||
1121 | if (sd->button_pressed != state) { | ||
1122 | input_report_key(gspca_dev->input_dev, | ||
1123 | KEY_CAMERA, state); | ||
1124 | input_sync(gspca_dev->input_dev); | ||
1125 | sd->button_pressed = state; | ||
1126 | } | ||
1127 | } | ||
1128 | #endif | ||
1107 | /* Control Packet, after this came the header again, | 1129 | /* Control Packet, after this came the header again, |
1108 | * but extra bytes came in the packet before this, | 1130 | * but extra bytes came in the packet before this, |
1109 | * sometimes an EOF arrives, sometimes not... */ | 1131 | * sometimes an EOF arrives, sometimes not... */ |
@@ -1410,6 +1432,9 @@ static const struct sd_desc sd_desc = { | |||
1410 | .stopN = sd_stopN, | 1432 | .stopN = sd_stopN, |
1411 | .pkt_scan = sd_pkt_scan, | 1433 | .pkt_scan = sd_pkt_scan, |
1412 | .querymenu = sd_querymenu, | 1434 | .querymenu = sd_querymenu, |
1435 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | ||
1436 | .other_input = 1, | ||
1437 | #endif | ||
1413 | }; | 1438 | }; |
1414 | 1439 | ||
1415 | /* -- module initialisation -- */ | 1440 | /* -- module initialisation -- */ |
diff --git a/drivers/media/video/gspca/topro.c b/drivers/media/video/gspca/topro.c index b2695b1dc603..444d3c5b9079 100644 --- a/drivers/media/video/gspca/topro.c +++ b/drivers/media/video/gspca/topro.c | |||
@@ -3946,7 +3946,7 @@ static int get_fr_idx(struct gspca_dev *gspca_dev) | |||
3946 | /* 640x480 * 30 fps does not work */ | 3946 | /* 640x480 * 30 fps does not work */ |
3947 | if (i == 6 /* if 30 fps */ | 3947 | if (i == 6 /* if 30 fps */ |
3948 | && gspca_dev->width == 640) | 3948 | && gspca_dev->width == 640) |
3949 | i = 0x86; /* 15 fps */ | 3949 | i = 0x05; /* 15 fps */ |
3950 | } else { | 3950 | } else { |
3951 | for (i = 0; i < ARRAY_SIZE(rates_6810) - 1; i++) { | 3951 | for (i = 0; i < ARRAY_SIZE(rates_6810) - 1; i++) { |
3952 | if (sd->framerate >= rates_6810[i]) | 3952 | if (sd->framerate >= rates_6810[i]) |
diff --git a/drivers/media/video/gspca/vicam.c b/drivers/media/video/gspca/vicam.c index d12ea1518ace..911152e169d6 100644 --- a/drivers/media/video/gspca/vicam.c +++ b/drivers/media/video/gspca/vicam.c | |||
@@ -324,7 +324,8 @@ static void sd_stop0(struct gspca_dev *gspca_dev) | |||
324 | dev->work_thread = NULL; | 324 | dev->work_thread = NULL; |
325 | mutex_lock(&gspca_dev->usb_lock); | 325 | mutex_lock(&gspca_dev->usb_lock); |
326 | 326 | ||
327 | vicam_set_camera_power(gspca_dev, 0); | 327 | if (gspca_dev->present) |
328 | vicam_set_camera_power(gspca_dev, 0); | ||
328 | } | 329 | } |
329 | 330 | ||
330 | /* Table of supported USB devices */ | 331 | /* Table of supported USB devices */ |
diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c index fbb6ed25ec31..ecada178bceb 100644 --- a/drivers/media/video/gspca/xirlink_cit.c +++ b/drivers/media/video/gspca/xirlink_cit.c | |||
@@ -995,14 +995,12 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
995 | case CIT_MODEL0: | 995 | case CIT_MODEL0: |
996 | cam->cam_mode = model0_mode; | 996 | cam->cam_mode = model0_mode; |
997 | cam->nmodes = ARRAY_SIZE(model0_mode); | 997 | cam->nmodes = ARRAY_SIZE(model0_mode); |
998 | cam->reverse_alts = 1; | ||
999 | gspca_dev->ctrl_dis = ~((1 << SD_CONTRAST) | (1 << SD_HFLIP)); | 998 | gspca_dev->ctrl_dis = ~((1 << SD_CONTRAST) | (1 << SD_HFLIP)); |
1000 | sd->sof_len = 4; | 999 | sd->sof_len = 4; |
1001 | break; | 1000 | break; |
1002 | case CIT_MODEL1: | 1001 | case CIT_MODEL1: |
1003 | cam->cam_mode = cif_yuv_mode; | 1002 | cam->cam_mode = cif_yuv_mode; |
1004 | cam->nmodes = ARRAY_SIZE(cif_yuv_mode); | 1003 | cam->nmodes = ARRAY_SIZE(cif_yuv_mode); |
1005 | cam->reverse_alts = 1; | ||
1006 | gspca_dev->ctrl_dis = (1 << SD_HUE) | (1 << SD_HFLIP); | 1004 | gspca_dev->ctrl_dis = (1 << SD_HUE) | (1 << SD_HFLIP); |
1007 | sd->sof_len = 4; | 1005 | sd->sof_len = 4; |
1008 | break; | 1006 | break; |
@@ -2791,7 +2789,7 @@ static int sd_isoc_init(struct gspca_dev *gspca_dev) | |||
2791 | } | 2789 | } |
2792 | 2790 | ||
2793 | /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ | 2791 | /* Start isoc bandwidth "negotiation" at max isoc bandwidth */ |
2794 | alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; | 2792 | alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; |
2795 | alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size); | 2793 | alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size); |
2796 | 2794 | ||
2797 | return 0; | 2795 | return 0; |
@@ -2814,7 +2812,7 @@ static int sd_isoc_nego(struct gspca_dev *gspca_dev) | |||
2814 | break; | 2812 | break; |
2815 | } | 2813 | } |
2816 | 2814 | ||
2817 | alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1]; | 2815 | alt = &gspca_dev->dev->actconfig->intf_cache[0]->altsetting[1]; |
2818 | packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); | 2816 | packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize); |
2819 | if (packet_size <= min_packet_size) | 2817 | if (packet_size <= min_packet_size) |
2820 | return -EIO; | 2818 | return -EIO; |
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c index 0202fead6b97..b9e15bb0328b 100644 --- a/drivers/media/video/gspca/zc3xx.c +++ b/drivers/media/video/gspca/zc3xx.c | |||
@@ -5381,12 +5381,12 @@ static const struct usb_action tas5130c_NoFlikerScale[] = { | |||
5381 | {} | 5381 | {} |
5382 | }; | 5382 | }; |
5383 | 5383 | ||
5384 | static const struct usb_action gc0303_InitialScale[] = { | 5384 | /* from usbvm305.inf 0ac8:305b 07/06/15 (3 - tas5130c) */ |
5385 | static const struct usb_action gc0303_Initial[] = { | ||
5385 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ | 5386 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ |
5386 | {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ | 5387 | {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ |
5387 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ | 5388 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ |
5388 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, /* 00,02,00,cc, | 5389 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, |
5389 | * 0<->10 */ | ||
5390 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */ | 5390 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */ |
5391 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */ | 5391 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */ |
5392 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */ | 5392 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */ |
@@ -5405,29 +5405,22 @@ static const struct usb_action gc0303_InitialScale[] = { | |||
5405 | * 6<->8 */ | 5405 | * 6<->8 */ |
5406 | {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */ | 5406 | {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */ |
5407 | {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */ | 5407 | {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */ |
5408 | {0xaa, 0x1b, 0x0024}, /* 00,1b,24,aa, */ | ||
5409 | {0xdd, 0x00, 0x0080}, /* 00,00,80,dd, */ | ||
5410 | {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa, */ | ||
5411 | {0xaa, 0x13, 0x0002}, /* 00,13,02,aa, */ | ||
5412 | {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */ | ||
5413 | /*?? {0xaa, 0x01, 0x0000}, */ | ||
5414 | {0xaa, 0x01, 0x0000}, | 5408 | {0xaa, 0x01, 0x0000}, |
5415 | {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */ | 5409 | {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */ |
5416 | {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */ | 5410 | {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */ |
5411 | {0xaa, 0x1b, 0x0000}, | ||
5417 | {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */ | 5412 | {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */ |
5418 | {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */ | 5413 | {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */ |
5419 | {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */ | 5414 | {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */ |
5420 | {0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */ | 5415 | {0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */ |
5421 | {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa, */ | 5416 | {0xaa, 0x0a, 0x0002}, |
5422 | {0xaa, 0x0b, 0x00a0}, /* 00,0b,a0,aa, */ | 5417 | {0xaa, 0x0b, 0x0000}, |
5423 | {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa, */ | 5418 | {0xaa, 0x0c, 0x0002}, |
5424 | {0xaa, 0x0d, 0x00a0}, /* 00,0d,a0,aa, */ | 5419 | {0xaa, 0x0d, 0x0000}, |
5425 | {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa, */ | 5420 | {0xaa, 0x0e, 0x0002}, |
5426 | {0xaa, 0x0f, 0x00a0}, /* 00,0f,a0,aa, */ | 5421 | {0xaa, 0x0f, 0x0000}, |
5427 | {0xaa, 0x10, 0x0000}, /* 00,10,00,aa, */ | 5422 | {0xaa, 0x10, 0x0002}, |
5428 | {0xaa, 0x11, 0x00a0}, /* 00,11,a0,aa, */ | 5423 | {0xaa, 0x11, 0x0000}, |
5429 | /*?? {0xa0, 0x00, 0x0039}, | ||
5430 | {0xa1, 0x01, 0x0037}, */ | ||
5431 | {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */ | 5424 | {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */ |
5432 | {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa, (e6 -> e8) */ | 5425 | {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa, (e6 -> e8) */ |
5433 | {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */ | 5426 | {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */ |
@@ -5442,17 +5435,18 @@ static const struct usb_action gc0303_InitialScale[] = { | |||
5442 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */ | 5435 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */ |
5443 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */ | 5436 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */ |
5444 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */ | 5437 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */ |
5445 | {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc, */ | 5438 | {0xa0, 0x58, ZC3XX_R1A8_DIGITALGAIN}, |
5446 | {0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */ | 5439 | {0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */ |
5447 | {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */ | 5440 | {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */ |
5441 | {0xaa, 0x1b, 0x0000}, | ||
5448 | {} | 5442 | {} |
5449 | }; | 5443 | }; |
5450 | 5444 | ||
5451 | static const struct usb_action gc0303_Initial[] = { | 5445 | static const struct usb_action gc0303_InitialScale[] = { |
5452 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ | 5446 | {0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL}, /* 00,00,01,cc, */ |
5453 | {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ | 5447 | {0xa0, 0x02, ZC3XX_R008_CLOCKSETTING}, /* 00,08,02,cc, */ |
5454 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ | 5448 | {0xa0, 0x01, ZC3XX_R010_CMOSSENSORSELECT}, /* 00,10,01,cc, */ |
5455 | {0xa0, 0x00, ZC3XX_R002_CLOCKSELECT}, /* 00,02,10,cc, */ | 5449 | {0xa0, 0x10, ZC3XX_R002_CLOCKSELECT}, |
5456 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */ | 5450 | {0xa0, 0x02, ZC3XX_R003_FRAMEWIDTHHIGH}, /* 00,03,02,cc, */ |
5457 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */ | 5451 | {0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW}, /* 00,04,80,cc, */ |
5458 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */ | 5452 | {0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH}, /* 00,05,01,cc, */ |
@@ -5471,34 +5465,26 @@ static const struct usb_action gc0303_Initial[] = { | |||
5471 | * 8<->6 */ | 5465 | * 8<->6 */ |
5472 | {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */ | 5466 | {0xa0, 0x10, ZC3XX_R087_EXPTIMEMID}, /* 00,87,10,cc, */ |
5473 | {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */ | 5467 | {0xa0, 0x98, ZC3XX_R08B_I2CDEVICEADDR}, /* 00,8b,98,cc, */ |
5474 | {0xaa, 0x1b, 0x0024}, /* 00,1b,24,aa, */ | ||
5475 | {0xdd, 0x00, 0x0080}, /* 00,00,80,dd, */ | ||
5476 | {0xaa, 0x1b, 0x0000}, /* 00,1b,00,aa, */ | ||
5477 | {0xaa, 0x13, 0x0002}, /* 00,13,02,aa, */ | ||
5478 | {0xaa, 0x15, 0x0004}, /* 00,15,04,aa */ | ||
5479 | /*?? {0xaa, 0x01, 0x0000}, */ | ||
5480 | {0xaa, 0x01, 0x0000}, | 5468 | {0xaa, 0x01, 0x0000}, |
5481 | {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */ | 5469 | {0xaa, 0x1a, 0x0000}, /* 00,1a,00,aa, */ |
5482 | {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */ | 5470 | {0xaa, 0x1c, 0x0017}, /* 00,1c,17,aa, */ |
5471 | {0xaa, 0x1b, 0x0000}, | ||
5483 | {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */ | 5472 | {0xa0, 0x82, ZC3XX_R086_EXPTIMEHIGH}, /* 00,86,82,cc, */ |
5484 | {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */ | 5473 | {0xa0, 0x83, ZC3XX_R087_EXPTIMEMID}, /* 00,87,83,cc, */ |
5485 | {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */ | 5474 | {0xa0, 0x84, ZC3XX_R088_EXPTIMELOW}, /* 00,88,84,cc, */ |
5486 | {0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */ | 5475 | {0xaa, 0x05, 0x0010}, /* 00,05,10,aa, */ |
5487 | {0xaa, 0x0a, 0x0000}, /* 00,0a,00,aa, */ | 5476 | {0xaa, 0x0a, 0x0001}, |
5488 | {0xaa, 0x0b, 0x00a0}, /* 00,0b,a0,aa, */ | 5477 | {0xaa, 0x0b, 0x0000}, |
5489 | {0xaa, 0x0c, 0x0000}, /* 00,0c,00,aa, */ | 5478 | {0xaa, 0x0c, 0x0001}, |
5490 | {0xaa, 0x0d, 0x00a0}, /* 00,0d,a0,aa, */ | 5479 | {0xaa, 0x0d, 0x0000}, |
5491 | {0xaa, 0x0e, 0x0000}, /* 00,0e,00,aa, */ | 5480 | {0xaa, 0x0e, 0x0001}, |
5492 | {0xaa, 0x0f, 0x00a0}, /* 00,0f,a0,aa, */ | 5481 | {0xaa, 0x0f, 0x0000}, |
5493 | {0xaa, 0x10, 0x0000}, /* 00,10,00,aa, */ | 5482 | {0xaa, 0x10, 0x0001}, |
5494 | {0xaa, 0x11, 0x00a0}, /* 00,11,a0,aa, */ | 5483 | {0xaa, 0x11, 0x0000}, |
5495 | /*?? {0xa0, 0x00, 0x0039}, | ||
5496 | {0xa1, 0x01, 0x0037}, */ | ||
5497 | {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */ | 5484 | {0xaa, 0x16, 0x0001}, /* 00,16,01,aa, */ |
5498 | {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa (e6 -> e8) */ | 5485 | {0xaa, 0x17, 0x00e8}, /* 00,17,e6,aa (e6 -> e8) */ |
5499 | {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */ | 5486 | {0xaa, 0x18, 0x0002}, /* 00,18,02,aa, */ |
5500 | {0xaa, 0x19, 0x0088}, /* 00,19,88,aa, */ | 5487 | {0xaa, 0x19, 0x0088}, /* 00,19,88,aa, */ |
5501 | {0xaa, 0x20, 0x0020}, /* 00,20,20,aa, */ | ||
5502 | {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc, */ | 5488 | {0xa0, 0xb7, ZC3XX_R101_SENSORCORRECTION}, /* 01,01,b7,cc, */ |
5503 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc, */ | 5489 | {0xa0, 0x05, ZC3XX_R012_VIDEOCONTROLFUNC}, /* 00,12,05,cc, */ |
5504 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc, */ | 5490 | {0xa0, 0x0d, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0d,cc, */ |
@@ -5508,36 +5494,37 @@ static const struct usb_action gc0303_Initial[] = { | |||
5508 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */ | 5494 | {0xa0, 0x13, ZC3XX_R1CB_SHARPNESS05}, /* 01,cb,13,cc, */ |
5509 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */ | 5495 | {0xa0, 0x08, ZC3XX_R250_DEADPIXELSMODE}, /* 02,50,08,cc, */ |
5510 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */ | 5496 | {0xa0, 0x08, ZC3XX_R301_EEPROMACCESS}, /* 03,01,08,cc, */ |
5511 | {0xa0, 0x60, ZC3XX_R1A8_DIGITALGAIN}, /* 01,a8,60,cc, */ | 5497 | {0xa0, 0x58, ZC3XX_R1A8_DIGITALGAIN}, |
5512 | {0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */ | 5498 | {0xa0, 0x61, ZC3XX_R116_RGAIN}, /* 01,16,61,cc, */ |
5513 | {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */ | 5499 | {0xa0, 0x65, ZC3XX_R118_BGAIN}, /* 01,18,65,cc */ |
5500 | {0xaa, 0x1b, 0x0000}, | ||
5514 | {} | 5501 | {} |
5515 | }; | 5502 | }; |
5516 | static const struct usb_action gc0303_50HZScale[] = { | 5503 | static const struct usb_action gc0303_50HZ[] = { |
5517 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5504 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5518 | {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ | 5505 | {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ |
5519 | {0xaa, 0x84, 0x00aa}, /* 00,84,aa,aa */ | 5506 | {0xaa, 0x84, 0x0063}, |
5520 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */ | 5507 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */ |
5521 | {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0d,cc, */ | 5508 | {0xa0, 0x06, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0d,cc, */ |
5522 | {0xa0, 0xa8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc, */ | 5509 | {0xa0, 0xa8, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,50,cc, */ |
5523 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */ | 5510 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */ |
5524 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */ | 5511 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */ |
5525 | {0xa0, 0x8e, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc, */ | 5512 | {0xa0, 0x47, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,47,cc, */ |
5526 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */ | 5513 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */ |
5527 | {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */ | 5514 | {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */ |
5528 | {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */ | 5515 | {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */ |
5529 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */ | 5516 | {0xa0, 0x48, ZC3XX_R1AA_DIGITALGAINSTEP}, |
5530 | {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */ | 5517 | {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */ |
5531 | {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */ | 5518 | {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */ |
5532 | {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */ | 5519 | {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */ |
5533 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */ | 5520 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */ |
5534 | {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */ | 5521 | {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */ |
5535 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */ | 5522 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */ |
5536 | {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */ | 5523 | {0xa0, 0x7f, ZC3XX_R18D_YTARGET}, |
5537 | {} | 5524 | {} |
5538 | }; | 5525 | }; |
5539 | 5526 | ||
5540 | static const struct usb_action gc0303_50HZ[] = { | 5527 | static const struct usb_action gc0303_50HZScale[] = { |
5541 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5528 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5542 | {0xaa, 0x83, 0x0003}, /* 00,83,03,aa */ | 5529 | {0xaa, 0x83, 0x0003}, /* 00,83,03,aa */ |
5543 | {0xaa, 0x84, 0x0054}, /* 00,84,54,aa */ | 5530 | {0xaa, 0x84, 0x0054}, /* 00,84,54,aa */ |
@@ -5550,21 +5537,21 @@ static const struct usb_action gc0303_50HZ[] = { | |||
5550 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */ | 5537 | {0xa0, 0x0e, ZC3XX_R18C_AEFREEZE}, /* 01,8c,0e,cc, */ |
5551 | {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */ | 5538 | {0xa0, 0x15, ZC3XX_R18F_AEUNFREEZE}, /* 01,8f,15,cc, */ |
5552 | {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */ | 5539 | {0xa0, 0x10, ZC3XX_R1A9_DIGITALLIMITDIFF}, /* 01,a9,10,cc, */ |
5553 | {0xa0, 0x24, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */ | 5540 | {0xa0, 0x48, ZC3XX_R1AA_DIGITALGAINSTEP}, /* 01,aa,24,cc, */ |
5554 | {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */ | 5541 | {0xa0, 0x62, ZC3XX_R01D_HSYNC_0}, /* 00,1d,62,cc, */ |
5555 | {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */ | 5542 | {0xa0, 0x90, ZC3XX_R01E_HSYNC_1}, /* 00,1e,90,cc, */ |
5556 | {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */ | 5543 | {0xa0, 0xc8, ZC3XX_R01F_HSYNC_2}, /* 00,1f,c8,cc, */ |
5557 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */ | 5544 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */ |
5558 | {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */ | 5545 | {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */ |
5559 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */ | 5546 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */ |
5560 | {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */ | 5547 | {0xa0, 0x7f, ZC3XX_R18D_YTARGET}, |
5561 | {} | 5548 | {} |
5562 | }; | 5549 | }; |
5563 | 5550 | ||
5564 | static const struct usb_action gc0303_60HZScale[] = { | 5551 | static const struct usb_action gc0303_60HZ[] = { |
5565 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5552 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5566 | {0xaa, 0x83, 0x0001}, /* 00,83,01,aa */ | 5553 | {0xaa, 0x83, 0x0000}, |
5567 | {0xaa, 0x84, 0x0062}, /* 00,84,62,aa */ | 5554 | {0xaa, 0x84, 0x003b}, |
5568 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */ | 5555 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */ |
5569 | {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,05,cc, */ | 5556 | {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,05,cc, */ |
5570 | {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,88,cc, */ | 5557 | {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,88,cc, */ |
@@ -5581,14 +5568,14 @@ static const struct usb_action gc0303_60HZScale[] = { | |||
5581 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */ | 5568 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,20,ff,cc, */ |
5582 | {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */ | 5569 | {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,1d,58,cc, */ |
5583 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */ | 5570 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */ |
5584 | {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,8d,78,cc */ | 5571 | {0xa0, 0x80, ZC3XX_R18D_YTARGET}, |
5585 | {} | 5572 | {} |
5586 | }; | 5573 | }; |
5587 | 5574 | ||
5588 | static const struct usb_action gc0303_60HZ[] = { | 5575 | static const struct usb_action gc0303_60HZScale[] = { |
5589 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5576 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5590 | {0xaa, 0x83, 0x0002}, /* 00,83,02,aa */ | 5577 | {0xaa, 0x83, 0x0000}, |
5591 | {0xaa, 0x84, 0x00c4}, /* 00,84,c4,aa */ | 5578 | {0xaa, 0x84, 0x0076}, |
5592 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */ | 5579 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */ |
5593 | {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,1,0b,cc, */ | 5580 | {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,1,0b,cc, */ |
5594 | {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,2,10,cc, */ | 5581 | {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,2,10,cc, */ |
@@ -5605,18 +5592,18 @@ static const struct usb_action gc0303_60HZ[] = { | |||
5605 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,0,ff,cc, */ | 5592 | {0xa0, 0xff, ZC3XX_R020_HSYNC_3}, /* 00,0,ff,cc, */ |
5606 | {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,d,58,cc, */ | 5593 | {0xa0, 0x58, ZC3XX_R11D_GLOBALGAIN}, /* 01,d,58,cc, */ |
5607 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */ | 5594 | {0xa0, 0x42, ZC3XX_R180_AUTOCORRECTENABLE}, /* 01,80,42,cc, */ |
5608 | {0xa0, 0x78, ZC3XX_R18D_YTARGET}, /* 01,d,78,cc */ | 5595 | {0xa0, 0x80, ZC3XX_R18D_YTARGET}, |
5609 | {} | 5596 | {} |
5610 | }; | 5597 | }; |
5611 | 5598 | ||
5612 | static const struct usb_action gc0303_NoFlikerScale[] = { | 5599 | static const struct usb_action gc0303_NoFliker[] = { |
5613 | {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ | 5600 | {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ |
5614 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5601 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5615 | {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ | 5602 | {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ |
5616 | {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */ | 5603 | {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */ |
5617 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,0,00,cc, */ | 5604 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,0,00,cc, */ |
5618 | {0xa0, 0x05, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,05,cc, */ | 5605 | {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID}, |
5619 | {0xa0, 0x88, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,88,cc, */ | 5606 | {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW}, |
5620 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */ | 5607 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */ |
5621 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */ | 5608 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */ |
5622 | {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */ | 5609 | {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */ |
@@ -5631,14 +5618,14 @@ static const struct usb_action gc0303_NoFlikerScale[] = { | |||
5631 | {} | 5618 | {} |
5632 | }; | 5619 | }; |
5633 | 5620 | ||
5634 | static const struct usb_action gc0303_NoFliker[] = { | 5621 | static const struct usb_action gc0303_NoFlikerScale[] = { |
5635 | {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ | 5622 | {0xa0, 0x0c, ZC3XX_R100_OPERATIONMODE}, /* 01,00,0c,cc, */ |
5636 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ | 5623 | {0xaa, 0x82, 0x0000}, /* 00,82,00,aa */ |
5637 | {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ | 5624 | {0xaa, 0x83, 0x0000}, /* 00,83,00,aa */ |
5638 | {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */ | 5625 | {0xaa, 0x84, 0x0020}, /* 00,84,20,aa */ |
5639 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */ | 5626 | {0xa0, 0x00, ZC3XX_R190_EXPOSURELIMITHIGH}, /* 01,90,00,cc, */ |
5640 | {0xa0, 0x0b, ZC3XX_R191_EXPOSURELIMITMID}, /* 01,91,0b,cc, */ | 5627 | {0xa0, 0x00, ZC3XX_R191_EXPOSURELIMITMID}, |
5641 | {0xa0, 0x10, ZC3XX_R192_EXPOSURELIMITLOW}, /* 01,92,10,cc, */ | 5628 | {0xa0, 0x48, ZC3XX_R192_EXPOSURELIMITLOW}, |
5642 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */ | 5629 | {0xa0, 0x00, ZC3XX_R195_ANTIFLICKERHIGH}, /* 01,95,00,cc, */ |
5643 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */ | 5630 | {0xa0, 0x00, ZC3XX_R196_ANTIFLICKERMID}, /* 01,96,00,cc, */ |
5644 | {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */ | 5631 | {0xa0, 0x10, ZC3XX_R197_ANTIFLICKERLOW}, /* 01,97,10,cc, */ |
@@ -5809,7 +5796,7 @@ static void setmatrix(struct gspca_dev *gspca_dev) | |||
5809 | static const u8 tas5130c_matrix[9] = | 5796 | static const u8 tas5130c_matrix[9] = |
5810 | {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68}; | 5797 | {0x68, 0xec, 0xec, 0xec, 0x68, 0xec, 0xec, 0xec, 0x68}; |
5811 | static const u8 gc0303_matrix[9] = | 5798 | static const u8 gc0303_matrix[9] = |
5812 | {0x7b, 0xea, 0xea, 0xea, 0x7b, 0xea, 0xea, 0xea, 0x7b}; | 5799 | {0x6c, 0xea, 0xea, 0xea, 0x6c, 0xea, 0xea, 0xea, 0x6c}; |
5813 | static const u8 *matrix_tb[SENSOR_MAX] = { | 5800 | static const u8 *matrix_tb[SENSOR_MAX] = { |
5814 | [SENSOR_ADCM2700] = adcm2700_matrix, | 5801 | [SENSOR_ADCM2700] = adcm2700_matrix, |
5815 | [SENSOR_CS2102] = ov7620_matrix, | 5802 | [SENSOR_CS2102] = ov7620_matrix, |
@@ -6426,10 +6413,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
6426 | gspca_dev->cam.ctrls = sd->ctrls; | 6413 | gspca_dev->cam.ctrls = sd->ctrls; |
6427 | sd->quality = QUALITY_DEF; | 6414 | sd->quality = QUALITY_DEF; |
6428 | 6415 | ||
6429 | /* if USB 1.1, let some bandwidth for the audio device */ | ||
6430 | if (gspca_dev->audio && gspca_dev->dev->speed < USB_SPEED_HIGH) | ||
6431 | gspca_dev->nbalt--; | ||
6432 | |||
6433 | return 0; | 6416 | return 0; |
6434 | } | 6417 | } |
6435 | 6418 | ||
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 3ab875d036e1..a7c41d32f414 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -244,7 +244,7 @@ static int get_key_avermedia_cardbus(struct IR_i2c *ir, | |||
244 | 244 | ||
245 | /* ----------------------------------------------------------------------- */ | 245 | /* ----------------------------------------------------------------------- */ |
246 | 246 | ||
247 | static void ir_key_poll(struct IR_i2c *ir) | 247 | static int ir_key_poll(struct IR_i2c *ir) |
248 | { | 248 | { |
249 | static u32 ir_key, ir_raw; | 249 | static u32 ir_key, ir_raw; |
250 | int rc; | 250 | int rc; |
@@ -253,20 +253,28 @@ static void ir_key_poll(struct IR_i2c *ir) | |||
253 | rc = ir->get_key(ir, &ir_key, &ir_raw); | 253 | rc = ir->get_key(ir, &ir_key, &ir_raw); |
254 | if (rc < 0) { | 254 | if (rc < 0) { |
255 | dprintk(2,"error\n"); | 255 | dprintk(2,"error\n"); |
256 | return; | 256 | return rc; |
257 | } | 257 | } |
258 | 258 | ||
259 | if (rc) { | 259 | if (rc) { |
260 | dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key); | 260 | dprintk(1, "%s: keycode = 0x%04x\n", __func__, ir_key); |
261 | rc_keydown(ir->rc, ir_key, 0); | 261 | rc_keydown(ir->rc, ir_key, 0); |
262 | } | 262 | } |
263 | return 0; | ||
263 | } | 264 | } |
264 | 265 | ||
265 | static void ir_work(struct work_struct *work) | 266 | static void ir_work(struct work_struct *work) |
266 | { | 267 | { |
268 | int rc; | ||
267 | struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work); | 269 | struct IR_i2c *ir = container_of(work, struct IR_i2c, work.work); |
268 | 270 | ||
269 | ir_key_poll(ir); | 271 | rc = ir_key_poll(ir); |
272 | if (rc == -ENODEV) { | ||
273 | rc_unregister_device(ir->rc); | ||
274 | ir->rc = NULL; | ||
275 | return; | ||
276 | } | ||
277 | |||
270 | schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling_interval)); | 278 | schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling_interval)); |
271 | } | 279 | } |
272 | 280 | ||
@@ -446,7 +454,8 @@ static int ir_remove(struct i2c_client *client) | |||
446 | cancel_delayed_work_sync(&ir->work); | 454 | cancel_delayed_work_sync(&ir->work); |
447 | 455 | ||
448 | /* unregister device */ | 456 | /* unregister device */ |
449 | rc_unregister_device(ir->rc); | 457 | if (ir->rc) |
458 | rc_unregister_device(ir->rc); | ||
450 | 459 | ||
451 | /* free memory */ | 460 | /* free memory */ |
452 | kfree(ir); | 461 | kfree(ir); |
@@ -489,11 +498,3 @@ static void __exit ir_fini(void) | |||
489 | 498 | ||
490 | module_init(ir_init); | 499 | module_init(ir_init); |
491 | module_exit(ir_fini); | 500 | module_exit(ir_fini); |
492 | |||
493 | /* | ||
494 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
495 | * --------------------------------------------------------------------------- | ||
496 | * Local variables: | ||
497 | * c-basic-offset: 8 | ||
498 | * End: | ||
499 | */ | ||
diff --git a/drivers/media/video/ivtv/ivtv-i2c.h b/drivers/media/video/ivtv/ivtv-i2c.h index 9332920ca4ff..7b9ec1cfeb80 100644 --- a/drivers/media/video/ivtv/ivtv-i2c.h +++ b/drivers/media/video/ivtv/ivtv-i2c.h | |||
@@ -25,7 +25,7 @@ struct i2c_client *ivtv_i2c_new_ir_legacy(struct ivtv *itv); | |||
25 | int ivtv_i2c_register(struct ivtv *itv, unsigned idx); | 25 | int ivtv_i2c_register(struct ivtv *itv, unsigned idx); |
26 | struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw); | 26 | struct v4l2_subdev *ivtv_find_hw(struct ivtv *itv, u32 hw); |
27 | 27 | ||
28 | /* init + register i2c algo-bit adapter */ | 28 | /* init + register i2c adapter */ |
29 | int init_ivtv_i2c(struct ivtv *itv); | 29 | int init_ivtv_i2c(struct ivtv *itv); |
30 | void exit_ivtv_i2c(struct ivtv *itv); | 30 | void exit_ivtv_i2c(struct ivtv *itv); |
31 | 31 | ||
diff --git a/drivers/media/video/m5mols/m5mols.h b/drivers/media/video/m5mols/m5mols.h index 82c8817bd32d..4b021e1ee5f2 100644 --- a/drivers/media/video/m5mols/m5mols.h +++ b/drivers/media/video/m5mols/m5mols.h | |||
@@ -163,7 +163,6 @@ struct m5mols_version { | |||
163 | * @ffmt: current fmt according to resolution type | 163 | * @ffmt: current fmt according to resolution type |
164 | * @res_type: current resolution type | 164 | * @res_type: current resolution type |
165 | * @irq_waitq: waitqueue for the capture | 165 | * @irq_waitq: waitqueue for the capture |
166 | * @work_irq: workqueue for the IRQ | ||
167 | * @flags: state variable for the interrupt handler | 166 | * @flags: state variable for the interrupt handler |
168 | * @handle: control handler | 167 | * @handle: control handler |
169 | * @autoexposure: Auto Exposure control | 168 | * @autoexposure: Auto Exposure control |
@@ -175,14 +174,12 @@ struct m5mols_version { | |||
175 | * @ver: information of the version | 174 | * @ver: information of the version |
176 | * @cap: the capture mode attributes | 175 | * @cap: the capture mode attributes |
177 | * @power: current sensor's power status | 176 | * @power: current sensor's power status |
178 | * @ctrl_sync: true means all controls of the sensor are initialized | 177 | * @isp_ready: 1 when the ISP controller has completed booting |
179 | * @int_capture: true means the capture interrupt is issued once | 178 | * @ctrl_sync: 1 when the control handler state is restored in H/W |
180 | * @lock_ae: true means the Auto Exposure is locked | 179 | * @lock_ae: true means the Auto Exposure is locked |
181 | * @lock_awb: true means the Aut WhiteBalance is locked | 180 | * @lock_awb: true means the Aut WhiteBalance is locked |
182 | * @resolution: register value for current resolution | 181 | * @resolution: register value for current resolution |
183 | * @interrupt: register value for current interrupt status | ||
184 | * @mode: register value for current operation mode | 182 | * @mode: register value for current operation mode |
185 | * @mode_save: register value for current operation mode for saving | ||
186 | * @set_power: optional power callback to the board code | 183 | * @set_power: optional power callback to the board code |
187 | */ | 184 | */ |
188 | struct m5mols_info { | 185 | struct m5mols_info { |
@@ -191,16 +188,16 @@ struct m5mols_info { | |||
191 | struct media_pad pad; | 188 | struct media_pad pad; |
192 | struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX]; | 189 | struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX]; |
193 | int res_type; | 190 | int res_type; |
191 | |||
194 | wait_queue_head_t irq_waitq; | 192 | wait_queue_head_t irq_waitq; |
195 | struct work_struct work_irq; | 193 | atomic_t irq_done; |
196 | unsigned long flags; | ||
197 | 194 | ||
198 | struct v4l2_ctrl_handler handle; | 195 | struct v4l2_ctrl_handler handle; |
196 | |||
199 | /* Autoexposure/exposure control cluster */ | 197 | /* Autoexposure/exposure control cluster */ |
200 | struct { | 198 | struct v4l2_ctrl *autoexposure; |
201 | struct v4l2_ctrl *autoexposure; | 199 | struct v4l2_ctrl *exposure; |
202 | struct v4l2_ctrl *exposure; | 200 | |
203 | }; | ||
204 | struct v4l2_ctrl *autowb; | 201 | struct v4l2_ctrl *autowb; |
205 | struct v4l2_ctrl *colorfx; | 202 | struct v4l2_ctrl *colorfx; |
206 | struct v4l2_ctrl *saturation; | 203 | struct v4l2_ctrl *saturation; |
@@ -208,21 +205,19 @@ struct m5mols_info { | |||
208 | 205 | ||
209 | struct m5mols_version ver; | 206 | struct m5mols_version ver; |
210 | struct m5mols_capture cap; | 207 | struct m5mols_capture cap; |
211 | bool power; | 208 | |
212 | bool ctrl_sync; | 209 | unsigned int isp_ready:1; |
210 | unsigned int power:1; | ||
211 | unsigned int ctrl_sync:1; | ||
212 | |||
213 | bool lock_ae; | 213 | bool lock_ae; |
214 | bool lock_awb; | 214 | bool lock_awb; |
215 | u8 resolution; | 215 | u8 resolution; |
216 | u8 interrupt; | ||
217 | u8 mode; | 216 | u8 mode; |
218 | u8 mode_save; | 217 | |
219 | int (*set_power)(struct device *dev, int on); | 218 | int (*set_power)(struct device *dev, int on); |
220 | }; | 219 | }; |
221 | 220 | ||
222 | #define ST_CAPT_IRQ 0 | ||
223 | |||
224 | #define is_powered(__info) (__info->power) | ||
225 | #define is_ctrl_synced(__info) (__info->ctrl_sync) | ||
226 | #define is_available_af(__info) (__info->ver.af) | 221 | #define is_available_af(__info) (__info->ver.af) |
227 | #define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code) | 222 | #define is_code(__code, __type) (__code == m5mols_default_ffmt[__type].code) |
228 | #define is_manufacturer(__info, __manufacturer) \ | 223 | #define is_manufacturer(__info, __manufacturer) \ |
@@ -257,7 +252,15 @@ int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val); | |||
257 | int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val); | 252 | int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val); |
258 | int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val); | 253 | int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val); |
259 | int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val); | 254 | int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val); |
260 | int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 value); | 255 | |
256 | int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask, | ||
257 | int timeout); | ||
258 | |||
259 | /* Mask value for busy waiting until M-5MOLS I2C interface is initialized */ | ||
260 | #define M5MOLS_I2C_RDY_WAIT_FL (1 << 16) | ||
261 | /* ISP state transition timeout, in ms */ | ||
262 | #define M5MOLS_MODE_CHANGE_TIMEOUT 200 | ||
263 | #define M5MOLS_BUSY_WAIT_DEF_TIMEOUT 250 | ||
261 | 264 | ||
262 | /* | 265 | /* |
263 | * Mode operation of the M-5MOLS | 266 | * Mode operation of the M-5MOLS |
@@ -282,7 +285,8 @@ int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 value); | |||
282 | int m5mols_mode(struct m5mols_info *info, u8 mode); | 285 | int m5mols_mode(struct m5mols_info *info, u8 mode); |
283 | 286 | ||
284 | int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg); | 287 | int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg); |
285 | int m5mols_sync_controls(struct m5mols_info *info); | 288 | int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 condition, u32 timeout); |
289 | int m5mols_restore_controls(struct m5mols_info *info); | ||
286 | int m5mols_start_capture(struct m5mols_info *info); | 290 | int m5mols_start_capture(struct m5mols_info *info); |
287 | int m5mols_do_scenemode(struct m5mols_info *info, u8 mode); | 291 | int m5mols_do_scenemode(struct m5mols_info *info, u8 mode); |
288 | int m5mols_lock_3a(struct m5mols_info *info, bool lock); | 292 | int m5mols_lock_3a(struct m5mols_info *info, bool lock); |
diff --git a/drivers/media/video/m5mols/m5mols_capture.c b/drivers/media/video/m5mols/m5mols_capture.c index 3248ac805711..ba25e8e2ba4c 100644 --- a/drivers/media/video/m5mols/m5mols_capture.c +++ b/drivers/media/video/m5mols/m5mols_capture.c | |||
@@ -1,3 +1,4 @@ | |||
1 | |||
1 | /* | 2 | /* |
2 | * The Capture code for Fujitsu M-5MOLS ISP | 3 | * The Capture code for Fujitsu M-5MOLS ISP |
3 | * | 4 | * |
@@ -25,26 +26,11 @@ | |||
25 | #include <media/v4l2-device.h> | 26 | #include <media/v4l2-device.h> |
26 | #include <media/v4l2-subdev.h> | 27 | #include <media/v4l2-subdev.h> |
27 | #include <media/m5mols.h> | 28 | #include <media/m5mols.h> |
29 | #include <media/s5p_fimc.h> | ||
28 | 30 | ||
29 | #include "m5mols.h" | 31 | #include "m5mols.h" |
30 | #include "m5mols_reg.h" | 32 | #include "m5mols_reg.h" |
31 | 33 | ||
32 | static int m5mols_capture_error_handler(struct m5mols_info *info, | ||
33 | int timeout) | ||
34 | { | ||
35 | int ret; | ||
36 | |||
37 | /* Disable all interrupts and clear relevant interrupt staus bits */ | ||
38 | ret = m5mols_write(&info->sd, SYSTEM_INT_ENABLE, | ||
39 | info->interrupt & ~(REG_INT_CAPTURE)); | ||
40 | if (ret) | ||
41 | return ret; | ||
42 | |||
43 | if (timeout == 0) | ||
44 | return -ETIMEDOUT; | ||
45 | |||
46 | return 0; | ||
47 | } | ||
48 | /** | 34 | /** |
49 | * m5mols_read_rational - I2C read of a rational number | 35 | * m5mols_read_rational - I2C read of a rational number |
50 | * | 36 | * |
@@ -121,69 +107,54 @@ int m5mols_start_capture(struct m5mols_info *info) | |||
121 | { | 107 | { |
122 | struct v4l2_subdev *sd = &info->sd; | 108 | struct v4l2_subdev *sd = &info->sd; |
123 | u8 resolution = info->resolution; | 109 | u8 resolution = info->resolution; |
124 | int timeout; | ||
125 | int ret; | 110 | int ret; |
126 | 111 | ||
127 | /* | 112 | /* |
128 | * Preparing capture. Setting control & interrupt before entering | 113 | * Synchronize the controls, set the capture frame resolution and color |
129 | * capture mode | 114 | * format. The frame capture is initiated during switching from Monitor |
130 | * | 115 | * to Capture mode. |
131 | * 1) change to MONITOR mode for operating control & interrupt | ||
132 | * 2) set controls (considering v4l2_control value & lock 3A) | ||
133 | * 3) set interrupt | ||
134 | * 4) change to CAPTURE mode | ||
135 | */ | 116 | */ |
136 | ret = m5mols_mode(info, REG_MONITOR); | 117 | ret = m5mols_mode(info, REG_MONITOR); |
137 | if (!ret) | 118 | if (!ret) |
138 | ret = m5mols_sync_controls(info); | 119 | ret = m5mols_restore_controls(info); |
139 | if (!ret) | 120 | if (!ret) |
140 | ret = m5mols_lock_3a(info, true); | 121 | ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG); |
122 | if (!ret) | ||
123 | ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution); | ||
141 | if (!ret) | 124 | if (!ret) |
142 | ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE); | 125 | ret = m5mols_lock_3a(info, true); |
143 | if (!ret) | 126 | if (!ret) |
144 | ret = m5mols_mode(info, REG_CAPTURE); | 127 | ret = m5mols_mode(info, REG_CAPTURE); |
145 | if (!ret) { | 128 | if (!ret) |
146 | /* Wait for capture interrupt, after changing capture mode */ | 129 | /* Wait until a frame is captured to ISP internal memory */ |
147 | timeout = wait_event_interruptible_timeout(info->irq_waitq, | 130 | ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000); |
148 | test_bit(ST_CAPT_IRQ, &info->flags), | ||
149 | msecs_to_jiffies(2000)); | ||
150 | if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) | ||
151 | ret = m5mols_capture_error_handler(info, timeout); | ||
152 | } | ||
153 | if (!ret) | 131 | if (!ret) |
154 | ret = m5mols_lock_3a(info, false); | 132 | ret = m5mols_lock_3a(info, false); |
155 | if (ret) | 133 | if (ret) |
156 | return ret; | 134 | return ret; |
135 | |||
157 | /* | 136 | /* |
158 | * Starting capture. Setting capture frame count and resolution and | 137 | * Initiate the captured data transfer to a MIPI-CSI receiver. |
159 | * the format(available format: JPEG, Bayer RAW, YUV). | ||
160 | * | ||
161 | * 1) select single or multi(enable to 25), format, size | ||
162 | * 2) set interrupt | ||
163 | * 3) start capture(for main image, now) | ||
164 | * 4) get information | ||
165 | * 5) notify file size to v4l2 device(e.g, to s5p-fimc v4l2 device) | ||
166 | */ | 138 | */ |
167 | ret = m5mols_write(sd, CAPC_SEL_FRAME, 1); | 139 | ret = m5mols_write(sd, CAPC_SEL_FRAME, 1); |
168 | if (!ret) | 140 | if (!ret) |
169 | ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG); | ||
170 | if (!ret) | ||
171 | ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution); | ||
172 | if (!ret) | ||
173 | ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE); | ||
174 | if (!ret) | ||
175 | ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN); | 141 | ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN); |
176 | if (!ret) { | 142 | if (!ret) { |
143 | bool captured = false; | ||
144 | unsigned int size; | ||
145 | |||
177 | /* Wait for the capture completion interrupt */ | 146 | /* Wait for the capture completion interrupt */ |
178 | timeout = wait_event_interruptible_timeout(info->irq_waitq, | 147 | ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000); |
179 | test_bit(ST_CAPT_IRQ, &info->flags), | 148 | if (!ret) { |
180 | msecs_to_jiffies(2000)); | 149 | captured = true; |
181 | if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) { | ||
182 | ret = m5mols_capture_info(info); | 150 | ret = m5mols_capture_info(info); |
183 | if (!ret) | ||
184 | v4l2_subdev_notify(sd, 0, &info->cap.total); | ||
185 | } | 151 | } |
152 | size = captured ? info->cap.main : 0; | ||
153 | v4l2_dbg(1, m5mols_debug, sd, "%s: size: %d, thumb.: %d B\n", | ||
154 | __func__, size, info->cap.thumb); | ||
155 | |||
156 | v4l2_subdev_notify(sd, S5P_FIMC_TX_END_NOTIFY, &size); | ||
186 | } | 157 | } |
187 | 158 | ||
188 | return m5mols_capture_error_handler(info, timeout); | 159 | return ret; |
189 | } | 160 | } |
diff --git a/drivers/media/video/m5mols/m5mols_core.c b/drivers/media/video/m5mols/m5mols_core.c index e0f09e531800..93d768db9f33 100644 --- a/drivers/media/video/m5mols/m5mols_core.c +++ b/drivers/media/video/m5mols/m5mols_core.c | |||
@@ -135,10 +135,13 @@ static u32 m5mols_swap_byte(u8 *data, u8 length) | |||
135 | * @reg: combination of size, category and command for the I2C packet | 135 | * @reg: combination of size, category and command for the I2C packet |
136 | * @size: desired size of I2C packet | 136 | * @size: desired size of I2C packet |
137 | * @val: read value | 137 | * @val: read value |
138 | * | ||
139 | * Returns 0 on success, or else negative errno. | ||
138 | */ | 140 | */ |
139 | static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val) | 141 | static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val) |
140 | { | 142 | { |
141 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 143 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
144 | struct m5mols_info *info = to_m5mols(sd); | ||
142 | u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1]; | 145 | u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1]; |
143 | u8 category = I2C_CATEGORY(reg); | 146 | u8 category = I2C_CATEGORY(reg); |
144 | u8 cmd = I2C_COMMAND(reg); | 147 | u8 cmd = I2C_COMMAND(reg); |
@@ -168,15 +171,17 @@ static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val) | |||
168 | usleep_range(200, 200); | 171 | usleep_range(200, 200); |
169 | 172 | ||
170 | ret = i2c_transfer(client->adapter, msg, 2); | 173 | ret = i2c_transfer(client->adapter, msg, 2); |
171 | if (ret < 0) { | 174 | |
172 | v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n", | 175 | if (ret == 2) { |
173 | size, category, cmd, ret); | 176 | *val = m5mols_swap_byte(&rbuf[1], size); |
174 | return ret; | 177 | return 0; |
175 | } | 178 | } |
176 | 179 | ||
177 | *val = m5mols_swap_byte(&rbuf[1], size); | 180 | if (info->isp_ready) |
181 | v4l2_err(sd, "read failed: size:%d cat:%02x cmd:%02x. %d\n", | ||
182 | size, category, cmd, ret); | ||
178 | 183 | ||
179 | return 0; | 184 | return ret < 0 ? ret : -EIO; |
180 | } | 185 | } |
181 | 186 | ||
182 | int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val) | 187 | int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val) |
@@ -229,10 +234,13 @@ int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val) | |||
229 | * m5mols_write - I2C command write function | 234 | * m5mols_write - I2C command write function |
230 | * @reg: combination of size, category and command for the I2C packet | 235 | * @reg: combination of size, category and command for the I2C packet |
231 | * @val: value to write | 236 | * @val: value to write |
237 | * | ||
238 | * Returns 0 on success, or else negative errno. | ||
232 | */ | 239 | */ |
233 | int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val) | 240 | int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val) |
234 | { | 241 | { |
235 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 242 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
243 | struct m5mols_info *info = to_m5mols(sd); | ||
236 | u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4]; | 244 | u8 wbuf[M5MOLS_I2C_MAX_SIZE + 4]; |
237 | u8 category = I2C_CATEGORY(reg); | 245 | u8 category = I2C_CATEGORY(reg); |
238 | u8 cmd = I2C_COMMAND(reg); | 246 | u8 cmd = I2C_COMMAND(reg); |
@@ -263,28 +271,45 @@ int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val) | |||
263 | usleep_range(200, 200); | 271 | usleep_range(200, 200); |
264 | 272 | ||
265 | ret = i2c_transfer(client->adapter, msg, 1); | 273 | ret = i2c_transfer(client->adapter, msg, 1); |
266 | if (ret < 0) { | 274 | if (ret == 1) |
267 | v4l2_err(sd, "write failed: size:%d cat:%02x cmd:%02x. %d\n", | 275 | return 0; |
268 | size, category, cmd, ret); | ||
269 | return ret; | ||
270 | } | ||
271 | 276 | ||
272 | return 0; | 277 | if (info->isp_ready) |
278 | v4l2_err(sd, "write failed: cat:%02x cmd:%02x ret:%d\n", | ||
279 | category, cmd, ret); | ||
280 | |||
281 | return ret < 0 ? ret : -EIO; | ||
273 | } | 282 | } |
274 | 283 | ||
275 | int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 mask) | 284 | /** |
285 | * m5mols_busy_wait - Busy waiting with I2C register polling | ||
286 | * @reg: the I2C_REG() address of an 8-bit status register to check | ||
287 | * @value: expected status register value | ||
288 | * @mask: bit mask for the read status register value | ||
289 | * @timeout: timeout in miliseconds, or -1 for default timeout | ||
290 | * | ||
291 | * The @reg register value is ORed with @mask before comparing with @value. | ||
292 | * | ||
293 | * Return: 0 if the requested condition became true within less than | ||
294 | * @timeout ms, or else negative errno. | ||
295 | */ | ||
296 | int m5mols_busy_wait(struct v4l2_subdev *sd, u32 reg, u32 value, u32 mask, | ||
297 | int timeout) | ||
276 | { | 298 | { |
277 | u8 busy; | 299 | int ms = timeout < 0 ? M5MOLS_BUSY_WAIT_DEF_TIMEOUT : timeout; |
278 | int i; | 300 | unsigned long end = jiffies + msecs_to_jiffies(ms); |
279 | int ret; | 301 | u8 status; |
280 | 302 | ||
281 | for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) { | 303 | do { |
282 | ret = m5mols_read_u8(sd, I2C_REG(category, cmd, 1), &busy); | 304 | int ret = m5mols_read_u8(sd, reg, &status); |
283 | if (ret < 0) | 305 | |
306 | if (ret < 0 && !(mask & M5MOLS_I2C_RDY_WAIT_FL)) | ||
284 | return ret; | 307 | return ret; |
285 | if ((busy & mask) == mask) | 308 | if (!ret && (status & mask & 0xff) == (value & 0xff)) |
286 | return 0; | 309 | return 0; |
287 | } | 310 | usleep_range(100, 250); |
311 | } while (ms > 0 && time_is_after_jiffies(end)); | ||
312 | |||
288 | return -EBUSY; | 313 | return -EBUSY; |
289 | } | 314 | } |
290 | 315 | ||
@@ -307,6 +332,20 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg) | |||
307 | return ret; | 332 | return ret; |
308 | } | 333 | } |
309 | 334 | ||
335 | int m5mols_wait_interrupt(struct v4l2_subdev *sd, u8 irq_mask, u32 timeout) | ||
336 | { | ||
337 | struct m5mols_info *info = to_m5mols(sd); | ||
338 | |||
339 | int ret = wait_event_interruptible_timeout(info->irq_waitq, | ||
340 | atomic_add_unless(&info->irq_done, -1, 0), | ||
341 | msecs_to_jiffies(timeout)); | ||
342 | if (ret <= 0) | ||
343 | return ret ? ret : -ETIMEDOUT; | ||
344 | |||
345 | return m5mols_busy_wait(sd, SYSTEM_INT_FACTOR, irq_mask, | ||
346 | M5MOLS_I2C_RDY_WAIT_FL | irq_mask, -1); | ||
347 | } | ||
348 | |||
310 | /** | 349 | /** |
311 | * m5mols_reg_mode - Write the mode and check busy status | 350 | * m5mols_reg_mode - Write the mode and check busy status |
312 | * | 351 | * |
@@ -316,8 +355,10 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg) | |||
316 | static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode) | 355 | static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode) |
317 | { | 356 | { |
318 | int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode); | 357 | int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode); |
319 | 358 | if (ret < 0) | |
320 | return ret ? ret : m5mols_busy(sd, CAT_SYSTEM, CAT0_SYSMODE, mode); | 359 | return ret; |
360 | return m5mols_busy_wait(sd, SYSTEM_SYSMODE, mode, 0xff, | ||
361 | M5MOLS_MODE_CHANGE_TIMEOUT); | ||
321 | } | 362 | } |
322 | 363 | ||
323 | /** | 364 | /** |
@@ -338,13 +379,13 @@ int m5mols_mode(struct m5mols_info *info, u8 mode) | |||
338 | return ret; | 379 | return ret; |
339 | 380 | ||
340 | ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, ®); | 381 | ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, ®); |
341 | if ((!ret && reg == mode) || ret) | 382 | if (ret || reg == mode) |
342 | return ret; | 383 | return ret; |
343 | 384 | ||
344 | switch (reg) { | 385 | switch (reg) { |
345 | case REG_PARAMETER: | 386 | case REG_PARAMETER: |
346 | ret = m5mols_reg_mode(sd, REG_MONITOR); | 387 | ret = m5mols_reg_mode(sd, REG_MONITOR); |
347 | if (!ret && mode == REG_MONITOR) | 388 | if (mode == REG_MONITOR) |
348 | break; | 389 | break; |
349 | if (!ret) | 390 | if (!ret) |
350 | ret = m5mols_reg_mode(sd, REG_CAPTURE); | 391 | ret = m5mols_reg_mode(sd, REG_CAPTURE); |
@@ -361,7 +402,7 @@ int m5mols_mode(struct m5mols_info *info, u8 mode) | |||
361 | 402 | ||
362 | case REG_CAPTURE: | 403 | case REG_CAPTURE: |
363 | ret = m5mols_reg_mode(sd, REG_MONITOR); | 404 | ret = m5mols_reg_mode(sd, REG_MONITOR); |
364 | if (!ret && mode == REG_MONITOR) | 405 | if (mode == REG_MONITOR) |
365 | break; | 406 | break; |
366 | if (!ret) | 407 | if (!ret) |
367 | ret = m5mols_reg_mode(sd, REG_PARAMETER); | 408 | ret = m5mols_reg_mode(sd, REG_PARAMETER); |
@@ -570,26 +611,25 @@ static struct v4l2_subdev_pad_ops m5mols_pad_ops = { | |||
570 | }; | 611 | }; |
571 | 612 | ||
572 | /** | 613 | /** |
573 | * m5mols_sync_controls - Apply default scene mode and the current controls | 614 | * m5mols_restore_controls - Apply current control values to the registers |
574 | * | 615 | * |
575 | * This is used only streaming for syncing between v4l2_ctrl framework and | 616 | * m5mols_do_scenemode() handles all parameters for which there is yet no |
576 | * m5mols's controls. First, do the scenemode to the sensor, then call | 617 | * individual control. It should be replaced at some point by setting each |
577 | * v4l2_ctrl_handler_setup. It can be same between some commands and | 618 | * control individually, in required register set up order. |
578 | * the scenemode's in the default v4l2_ctrls. But, such commands of control | ||
579 | * should be prior to the scenemode's one. | ||
580 | */ | 619 | */ |
581 | int m5mols_sync_controls(struct m5mols_info *info) | 620 | int m5mols_restore_controls(struct m5mols_info *info) |
582 | { | 621 | { |
583 | int ret = -EINVAL; | 622 | int ret; |
584 | 623 | ||
585 | if (!is_ctrl_synced(info)) { | 624 | if (info->ctrl_sync) |
586 | ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL); | 625 | return 0; |
587 | if (ret) | ||
588 | return ret; | ||
589 | 626 | ||
590 | v4l2_ctrl_handler_setup(&info->handle); | 627 | ret = m5mols_do_scenemode(info, REG_SCENE_NORMAL); |
591 | info->ctrl_sync = true; | 628 | if (ret) |
592 | } | 629 | return ret; |
630 | |||
631 | ret = v4l2_ctrl_handler_setup(&info->handle); | ||
632 | info->ctrl_sync = !ret; | ||
593 | 633 | ||
594 | return ret; | 634 | return ret; |
595 | } | 635 | } |
@@ -613,7 +653,7 @@ static int m5mols_start_monitor(struct m5mols_info *info) | |||
613 | if (!ret) | 653 | if (!ret) |
614 | ret = m5mols_mode(info, REG_MONITOR); | 654 | ret = m5mols_mode(info, REG_MONITOR); |
615 | if (!ret) | 655 | if (!ret) |
616 | ret = m5mols_sync_controls(info); | 656 | ret = m5mols_restore_controls(info); |
617 | 657 | ||
618 | return ret; | 658 | return ret; |
619 | } | 659 | } |
@@ -645,17 +685,25 @@ static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl) | |||
645 | { | 685 | { |
646 | struct v4l2_subdev *sd = to_sd(ctrl); | 686 | struct v4l2_subdev *sd = to_sd(ctrl); |
647 | struct m5mols_info *info = to_m5mols(sd); | 687 | struct m5mols_info *info = to_m5mols(sd); |
688 | int ispstate = info->mode; | ||
648 | int ret; | 689 | int ret; |
649 | 690 | ||
650 | info->mode_save = info->mode; | 691 | /* |
692 | * If needed, defer restoring the controls until | ||
693 | * the device is fully initialized. | ||
694 | */ | ||
695 | if (!info->isp_ready) { | ||
696 | info->ctrl_sync = 0; | ||
697 | return 0; | ||
698 | } | ||
651 | 699 | ||
652 | ret = m5mols_mode(info, REG_PARAMETER); | 700 | ret = m5mols_mode(info, REG_PARAMETER); |
653 | if (!ret) | 701 | if (ret < 0) |
654 | ret = m5mols_set_ctrl(ctrl); | 702 | return ret; |
655 | if (!ret) | 703 | ret = m5mols_set_ctrl(ctrl); |
656 | ret = m5mols_mode(info, info->mode_save); | 704 | if (ret < 0) |
657 | 705 | return ret; | |
658 | return ret; | 706 | return m5mols_mode(info, ispstate); |
659 | } | 707 | } |
660 | 708 | ||
661 | static const struct v4l2_ctrl_ops m5mols_ctrl_ops = { | 709 | static const struct v4l2_ctrl_ops m5mols_ctrl_ops = { |
@@ -669,10 +717,10 @@ static int m5mols_sensor_power(struct m5mols_info *info, bool enable) | |||
669 | const struct m5mols_platform_data *pdata = info->pdata; | 717 | const struct m5mols_platform_data *pdata = info->pdata; |
670 | int ret; | 718 | int ret; |
671 | 719 | ||
672 | if (enable) { | 720 | if (info->power == enable) |
673 | if (is_powered(info)) | 721 | return 0; |
674 | return 0; | ||
675 | 722 | ||
723 | if (enable) { | ||
676 | if (info->set_power) { | 724 | if (info->set_power) { |
677 | ret = info->set_power(&client->dev, 1); | 725 | ret = info->set_power(&client->dev, 1); |
678 | if (ret) | 726 | if (ret) |
@@ -686,15 +734,11 @@ static int m5mols_sensor_power(struct m5mols_info *info, bool enable) | |||
686 | } | 734 | } |
687 | 735 | ||
688 | gpio_set_value(pdata->gpio_reset, !pdata->reset_polarity); | 736 | gpio_set_value(pdata->gpio_reset, !pdata->reset_polarity); |
689 | usleep_range(1000, 1000); | 737 | info->power = 1; |
690 | info->power = true; | ||
691 | 738 | ||
692 | return ret; | 739 | return ret; |
693 | } | 740 | } |
694 | 741 | ||
695 | if (!is_powered(info)) | ||
696 | return 0; | ||
697 | |||
698 | ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies); | 742 | ret = regulator_bulk_disable(ARRAY_SIZE(supplies), supplies); |
699 | if (ret) | 743 | if (ret) |
700 | return ret; | 744 | return ret; |
@@ -703,8 +747,9 @@ static int m5mols_sensor_power(struct m5mols_info *info, bool enable) | |||
703 | info->set_power(&client->dev, 0); | 747 | info->set_power(&client->dev, 0); |
704 | 748 | ||
705 | gpio_set_value(pdata->gpio_reset, pdata->reset_polarity); | 749 | gpio_set_value(pdata->gpio_reset, pdata->reset_polarity); |
706 | usleep_range(1000, 1000); | 750 | |
707 | info->power = false; | 751 | info->isp_ready = 0; |
752 | info->power = 0; | ||
708 | 753 | ||
709 | return ret; | 754 | return ret; |
710 | } | 755 | } |
@@ -717,21 +762,29 @@ int __attribute__ ((weak)) m5mols_update_fw(struct v4l2_subdev *sd, | |||
717 | } | 762 | } |
718 | 763 | ||
719 | /** | 764 | /** |
720 | * m5mols_sensor_armboot - Booting M-5MOLS internal ARM core. | 765 | * m5mols_fw_start - M-5MOLS internal ARM controller initialization |
721 | * | 766 | * |
722 | * Booting internal ARM core makes the M-5MOLS is ready for getting commands | 767 | * Execute the M-5MOLS internal ARM controller initialization sequence. |
723 | * with I2C. It's the first thing to be done after it powered up. It must wait | 768 | * This function should be called after the supply voltage has been |
724 | * at least 520ms recommended by M-5MOLS datasheet, after executing arm booting. | 769 | * applied and before any requests to the device are made. |
725 | */ | 770 | */ |
726 | static int m5mols_sensor_armboot(struct v4l2_subdev *sd) | 771 | static int m5mols_fw_start(struct v4l2_subdev *sd) |
727 | { | 772 | { |
773 | struct m5mols_info *info = to_m5mols(sd); | ||
728 | int ret; | 774 | int ret; |
729 | 775 | ||
730 | ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT); | 776 | atomic_set(&info->irq_done, 0); |
777 | /* Wait until I2C slave is initialized in Flash Writer mode */ | ||
778 | ret = m5mols_busy_wait(sd, FLASH_CAM_START, REG_IN_FLASH_MODE, | ||
779 | M5MOLS_I2C_RDY_WAIT_FL | 0xff, -1); | ||
780 | if (!ret) | ||
781 | ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT); | ||
782 | if (!ret) | ||
783 | ret = m5mols_wait_interrupt(sd, REG_INT_MODE, 2000); | ||
731 | if (ret < 0) | 784 | if (ret < 0) |
732 | return ret; | 785 | return ret; |
733 | 786 | ||
734 | msleep(520); | 787 | info->isp_ready = 1; |
735 | 788 | ||
736 | ret = m5mols_get_version(sd); | 789 | ret = m5mols_get_version(sd); |
737 | if (!ret) | 790 | if (!ret) |
@@ -743,7 +796,8 @@ static int m5mols_sensor_armboot(struct v4l2_subdev *sd) | |||
743 | 796 | ||
744 | ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI); | 797 | ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI); |
745 | if (!ret) | 798 | if (!ret) |
746 | ret = m5mols_enable_interrupt(sd, REG_INT_AF); | 799 | ret = m5mols_enable_interrupt(sd, |
800 | REG_INT_AF | REG_INT_CAPTURE); | ||
747 | 801 | ||
748 | return ret; | 802 | return ret; |
749 | } | 803 | } |
@@ -780,7 +834,7 @@ static int m5mols_init_controls(struct m5mols_info *info) | |||
780 | 4, (1 << V4L2_COLORFX_BW), V4L2_COLORFX_NONE); | 834 | 4, (1 << V4L2_COLORFX_BW), V4L2_COLORFX_NONE); |
781 | info->autoexposure = v4l2_ctrl_new_std_menu(&info->handle, | 835 | info->autoexposure = v4l2_ctrl_new_std_menu(&info->handle, |
782 | &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, | 836 | &m5mols_ctrl_ops, V4L2_CID_EXPOSURE_AUTO, |
783 | 1, 0, V4L2_EXPOSURE_MANUAL); | 837 | 1, 0, V4L2_EXPOSURE_AUTO); |
784 | 838 | ||
785 | sd->ctrl_handler = &info->handle; | 839 | sd->ctrl_handler = &info->handle; |
786 | if (info->handle.error) { | 840 | if (info->handle.error) { |
@@ -809,16 +863,7 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on) | |||
809 | if (on) { | 863 | if (on) { |
810 | ret = m5mols_sensor_power(info, true); | 864 | ret = m5mols_sensor_power(info, true); |
811 | if (!ret) | 865 | if (!ret) |
812 | ret = m5mols_sensor_armboot(sd); | 866 | ret = m5mols_fw_start(sd); |
813 | if (!ret) | ||
814 | ret = m5mols_init_controls(info); | ||
815 | if (ret) | ||
816 | return ret; | ||
817 | |||
818 | info->ffmt[M5MOLS_RESTYPE_MONITOR] = | ||
819 | m5mols_default_ffmt[M5MOLS_RESTYPE_MONITOR]; | ||
820 | info->ffmt[M5MOLS_RESTYPE_CAPTURE] = | ||
821 | m5mols_default_ffmt[M5MOLS_RESTYPE_CAPTURE]; | ||
822 | return ret; | 867 | return ret; |
823 | } | 868 | } |
824 | 869 | ||
@@ -829,17 +874,14 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on) | |||
829 | if (!ret) | 874 | if (!ret) |
830 | ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF); | 875 | ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF); |
831 | if (!ret) | 876 | if (!ret) |
832 | ret = m5mols_busy(sd, CAT_SYSTEM, CAT0_STATUS, | 877 | ret = m5mols_busy_wait(sd, SYSTEM_STATUS, REG_AF_IDLE, |
833 | REG_AF_IDLE); | 878 | 0xff, -1); |
834 | if (!ret) | 879 | if (ret < 0) |
835 | v4l2_info(sd, "Success soft-landing lens\n"); | 880 | v4l2_warn(sd, "Soft landing lens failed\n"); |
836 | } | 881 | } |
837 | 882 | ||
838 | ret = m5mols_sensor_power(info, false); | 883 | ret = m5mols_sensor_power(info, false); |
839 | if (!ret) { | 884 | info->ctrl_sync = 0; |
840 | v4l2_ctrl_handler_free(&info->handle); | ||
841 | info->ctrl_sync = false; | ||
842 | } | ||
843 | 885 | ||
844 | return ret; | 886 | return ret; |
845 | } | 887 | } |
@@ -865,52 +907,33 @@ static const struct v4l2_subdev_core_ops m5mols_core_ops = { | |||
865 | .log_status = m5mols_log_status, | 907 | .log_status = m5mols_log_status, |
866 | }; | 908 | }; |
867 | 909 | ||
910 | /* | ||
911 | * V4L2 subdev internal operations | ||
912 | */ | ||
913 | static int m5mols_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) | ||
914 | { | ||
915 | struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0); | ||
916 | |||
917 | *format = m5mols_default_ffmt[0]; | ||
918 | return 0; | ||
919 | } | ||
920 | |||
921 | static const struct v4l2_subdev_internal_ops m5mols_subdev_internal_ops = { | ||
922 | .open = m5mols_open, | ||
923 | }; | ||
924 | |||
868 | static const struct v4l2_subdev_ops m5mols_ops = { | 925 | static const struct v4l2_subdev_ops m5mols_ops = { |
869 | .core = &m5mols_core_ops, | 926 | .core = &m5mols_core_ops, |
870 | .pad = &m5mols_pad_ops, | 927 | .pad = &m5mols_pad_ops, |
871 | .video = &m5mols_video_ops, | 928 | .video = &m5mols_video_ops, |
872 | }; | 929 | }; |
873 | 930 | ||
874 | static void m5mols_irq_work(struct work_struct *work) | ||
875 | { | ||
876 | struct m5mols_info *info = | ||
877 | container_of(work, struct m5mols_info, work_irq); | ||
878 | struct v4l2_subdev *sd = &info->sd; | ||
879 | u8 reg; | ||
880 | int ret; | ||
881 | |||
882 | if (!is_powered(info) || | ||
883 | m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &info->interrupt)) | ||
884 | return; | ||
885 | |||
886 | switch (info->interrupt & REG_INT_MASK) { | ||
887 | case REG_INT_AF: | ||
888 | if (!is_available_af(info)) | ||
889 | break; | ||
890 | ret = m5mols_read_u8(sd, AF_STATUS, ®); | ||
891 | v4l2_dbg(2, m5mols_debug, sd, "AF %s\n", | ||
892 | reg == REG_AF_FAIL ? "Failed" : | ||
893 | reg == REG_AF_SUCCESS ? "Success" : | ||
894 | reg == REG_AF_IDLE ? "Idle" : "Busy"); | ||
895 | break; | ||
896 | case REG_INT_CAPTURE: | ||
897 | if (!test_and_set_bit(ST_CAPT_IRQ, &info->flags)) | ||
898 | wake_up_interruptible(&info->irq_waitq); | ||
899 | |||
900 | v4l2_dbg(2, m5mols_debug, sd, "CAPTURE\n"); | ||
901 | break; | ||
902 | default: | ||
903 | v4l2_dbg(2, m5mols_debug, sd, "Undefined: %02x\n", reg); | ||
904 | break; | ||
905 | }; | ||
906 | } | ||
907 | |||
908 | static irqreturn_t m5mols_irq_handler(int irq, void *data) | 931 | static irqreturn_t m5mols_irq_handler(int irq, void *data) |
909 | { | 932 | { |
910 | struct v4l2_subdev *sd = data; | 933 | struct m5mols_info *info = to_m5mols(data); |
911 | struct m5mols_info *info = to_m5mols(sd); | ||
912 | 934 | ||
913 | schedule_work(&info->work_irq); | 935 | atomic_set(&info->irq_done, 1); |
936 | wake_up_interruptible(&info->irq_waitq); | ||
914 | 937 | ||
915 | return IRQ_HANDLED; | 938 | return IRQ_HANDLED; |
916 | } | 939 | } |
@@ -961,7 +984,9 @@ static int __devinit m5mols_probe(struct i2c_client *client, | |||
961 | sd = &info->sd; | 984 | sd = &info->sd; |
962 | strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); | 985 | strlcpy(sd->name, MODULE_NAME, sizeof(sd->name)); |
963 | v4l2_i2c_subdev_init(sd, client, &m5mols_ops); | 986 | v4l2_i2c_subdev_init(sd, client, &m5mols_ops); |
987 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
964 | 988 | ||
989 | sd->internal_ops = &m5mols_subdev_internal_ops; | ||
965 | info->pad.flags = MEDIA_PAD_FL_SOURCE; | 990 | info->pad.flags = MEDIA_PAD_FL_SOURCE; |
966 | ret = media_entity_init(&sd->entity, 1, &info->pad, 0); | 991 | ret = media_entity_init(&sd->entity, 1, &info->pad, 0); |
967 | if (ret < 0) | 992 | if (ret < 0) |
@@ -969,7 +994,6 @@ static int __devinit m5mols_probe(struct i2c_client *client, | |||
969 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; | 994 | sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR; |
970 | 995 | ||
971 | init_waitqueue_head(&info->irq_waitq); | 996 | init_waitqueue_head(&info->irq_waitq); |
972 | INIT_WORK(&info->work_irq, m5mols_irq_work); | ||
973 | ret = request_irq(client->irq, m5mols_irq_handler, | 997 | ret = request_irq(client->irq, m5mols_irq_handler, |
974 | IRQF_TRIGGER_RISING, MODULE_NAME, sd); | 998 | IRQF_TRIGGER_RISING, MODULE_NAME, sd); |
975 | if (ret) { | 999 | if (ret) { |
@@ -977,7 +1001,20 @@ static int __devinit m5mols_probe(struct i2c_client *client, | |||
977 | goto out_me; | 1001 | goto out_me; |
978 | } | 1002 | } |
979 | info->res_type = M5MOLS_RESTYPE_MONITOR; | 1003 | info->res_type = M5MOLS_RESTYPE_MONITOR; |
980 | return 0; | 1004 | info->ffmt[0] = m5mols_default_ffmt[0]; |
1005 | info->ffmt[1] = m5mols_default_ffmt[1]; | ||
1006 | |||
1007 | ret = m5mols_sensor_power(info, true); | ||
1008 | if (ret) | ||
1009 | goto out_me; | ||
1010 | |||
1011 | ret = m5mols_fw_start(sd); | ||
1012 | if (!ret) | ||
1013 | ret = m5mols_init_controls(info); | ||
1014 | |||
1015 | m5mols_sensor_power(info, false); | ||
1016 | if (!ret) | ||
1017 | return 0; | ||
981 | out_me: | 1018 | out_me: |
982 | media_entity_cleanup(&sd->entity); | 1019 | media_entity_cleanup(&sd->entity); |
983 | out_reg: | 1020 | out_reg: |
@@ -995,6 +1032,7 @@ static int __devexit m5mols_remove(struct i2c_client *client) | |||
995 | struct m5mols_info *info = to_m5mols(sd); | 1032 | struct m5mols_info *info = to_m5mols(sd); |
996 | 1033 | ||
997 | v4l2_device_unregister_subdev(sd); | 1034 | v4l2_device_unregister_subdev(sd); |
1035 | v4l2_ctrl_handler_free(sd->ctrl_handler); | ||
998 | free_irq(client->irq, sd); | 1036 | free_irq(client->irq, sd); |
999 | 1037 | ||
1000 | regulator_bulk_free(ARRAY_SIZE(supplies), supplies); | 1038 | regulator_bulk_free(ARRAY_SIZE(supplies), supplies); |
diff --git a/drivers/media/video/m5mols/m5mols_reg.h b/drivers/media/video/m5mols/m5mols_reg.h index c755bd6edfe9..ae4aced0f9b2 100644 --- a/drivers/media/video/m5mols/m5mols_reg.h +++ b/drivers/media/video/m5mols/m5mols_reg.h | |||
@@ -55,39 +55,31 @@ | |||
55 | * There is many registers between customer version address and awb one. For | 55 | * There is many registers between customer version address and awb one. For |
56 | * more specific contents, see definition if file m5mols.h. | 56 | * more specific contents, see definition if file m5mols.h. |
57 | */ | 57 | */ |
58 | #define CAT0_VER_CUSTOMER 0x00 /* customer version */ | 58 | #define SYSTEM_VER_CUSTOMER I2C_REG(CAT_SYSTEM, 0x00, 1) |
59 | #define CAT0_VER_PROJECT 0x01 /* project version */ | 59 | #define SYSTEM_VER_PROJECT I2C_REG(CAT_SYSTEM, 0x01, 1) |
60 | #define CAT0_VER_FIRMWARE 0x02 /* Firmware version */ | 60 | #define SYSTEM_VER_FIRMWARE I2C_REG(CAT_SYSTEM, 0x02, 2) |
61 | #define CAT0_VER_HARDWARE 0x04 /* Hardware version */ | 61 | #define SYSTEM_VER_HARDWARE I2C_REG(CAT_SYSTEM, 0x04, 2) |
62 | #define CAT0_VER_PARAMETER 0x06 /* Parameter version */ | 62 | #define SYSTEM_VER_PARAMETER I2C_REG(CAT_SYSTEM, 0x06, 2) |
63 | #define CAT0_VER_AWB 0x08 /* Auto WB version */ | 63 | #define SYSTEM_VER_AWB I2C_REG(CAT_SYSTEM, 0x08, 2) |
64 | #define CAT0_VER_STRING 0x0a /* string including M-5MOLS */ | 64 | |
65 | #define CAT0_SYSMODE 0x0b /* SYSTEM mode register */ | 65 | #define SYSTEM_SYSMODE I2C_REG(CAT_SYSTEM, 0x0b, 1) |
66 | #define CAT0_STATUS 0x0c /* SYSTEM mode status register */ | ||
67 | #define CAT0_INT_FACTOR 0x10 /* interrupt pending register */ | ||
68 | #define CAT0_INT_ENABLE 0x11 /* interrupt enable register */ | ||
69 | |||
70 | #define SYSTEM_VER_CUSTOMER I2C_REG(CAT_SYSTEM, CAT0_VER_CUSTOMER, 1) | ||
71 | #define SYSTEM_VER_PROJECT I2C_REG(CAT_SYSTEM, CAT0_VER_PROJECT, 1) | ||
72 | #define SYSTEM_VER_FIRMWARE I2C_REG(CAT_SYSTEM, CAT0_VER_FIRMWARE, 2) | ||
73 | #define SYSTEM_VER_HARDWARE I2C_REG(CAT_SYSTEM, CAT0_VER_HARDWARE, 2) | ||
74 | #define SYSTEM_VER_PARAMETER I2C_REG(CAT_SYSTEM, CAT0_VER_PARAMETER, 2) | ||
75 | #define SYSTEM_VER_AWB I2C_REG(CAT_SYSTEM, CAT0_VER_AWB, 2) | ||
76 | |||
77 | #define SYSTEM_SYSMODE I2C_REG(CAT_SYSTEM, CAT0_SYSMODE, 1) | ||
78 | #define REG_SYSINIT 0x00 /* SYSTEM mode */ | 66 | #define REG_SYSINIT 0x00 /* SYSTEM mode */ |
79 | #define REG_PARAMETER 0x01 /* PARAMETER mode */ | 67 | #define REG_PARAMETER 0x01 /* PARAMETER mode */ |
80 | #define REG_MONITOR 0x02 /* MONITOR mode */ | 68 | #define REG_MONITOR 0x02 /* MONITOR mode */ |
81 | #define REG_CAPTURE 0x03 /* CAPTURE mode */ | 69 | #define REG_CAPTURE 0x03 /* CAPTURE mode */ |
82 | 70 | ||
83 | #define SYSTEM_CMD(__cmd) I2C_REG(CAT_SYSTEM, cmd, 1) | 71 | #define SYSTEM_CMD(__cmd) I2C_REG(CAT_SYSTEM, cmd, 1) |
84 | #define SYSTEM_VER_STRING I2C_REG(CAT_SYSTEM, CAT0_VER_STRING, 1) | 72 | #define SYSTEM_VER_STRING I2C_REG(CAT_SYSTEM, 0x0a, 1) |
85 | #define REG_SAMSUNG_ELECTRO "SE" /* Samsung Electro-Mechanics */ | 73 | #define REG_SAMSUNG_ELECTRO "SE" /* Samsung Electro-Mechanics */ |
86 | #define REG_SAMSUNG_OPTICS "OP" /* Samsung Fiber-Optics */ | 74 | #define REG_SAMSUNG_OPTICS "OP" /* Samsung Fiber-Optics */ |
87 | #define REG_SAMSUNG_TECHWIN "TB" /* Samsung Techwin */ | 75 | #define REG_SAMSUNG_TECHWIN "TB" /* Samsung Techwin */ |
76 | /* SYSTEM mode status */ | ||
77 | #define SYSTEM_STATUS I2C_REG(CAT_SYSTEM, 0x0c, 1) | ||
88 | 78 | ||
89 | #define SYSTEM_INT_FACTOR I2C_REG(CAT_SYSTEM, CAT0_INT_FACTOR, 1) | 79 | /* Interrupt pending register */ |
90 | #define SYSTEM_INT_ENABLE I2C_REG(CAT_SYSTEM, CAT0_INT_ENABLE, 1) | 80 | #define SYSTEM_INT_FACTOR I2C_REG(CAT_SYSTEM, 0x10, 1) |
81 | /* interrupt enable register */ | ||
82 | #define SYSTEM_INT_ENABLE I2C_REG(CAT_SYSTEM, 0x11, 1) | ||
91 | #define REG_INT_MODE (1 << 0) | 83 | #define REG_INT_MODE (1 << 0) |
92 | #define REG_INT_AF (1 << 1) | 84 | #define REG_INT_AF (1 << 1) |
93 | #define REG_INT_ZOOM (1 << 2) | 85 | #define REG_INT_ZOOM (1 << 2) |
@@ -105,20 +97,20 @@ | |||
105 | * can handle with preview(MONITOR) resolution size/frame per second/interface | 97 | * can handle with preview(MONITOR) resolution size/frame per second/interface |
106 | * between the sensor and the Application Processor/even the image effect. | 98 | * between the sensor and the Application Processor/even the image effect. |
107 | */ | 99 | */ |
108 | #define CAT1_DATA_INTERFACE 0x00 /* interface between sensor and AP */ | ||
109 | #define CAT1_MONITOR_SIZE 0x01 /* resolution at the MONITOR mode */ | ||
110 | #define CAT1_MONITOR_FPS 0x02 /* frame per second at this mode */ | ||
111 | #define CAT1_EFFECT 0x0b /* image effects */ | ||
112 | 100 | ||
113 | #define PARM_MON_SIZE I2C_REG(CAT_PARAM, CAT1_MONITOR_SIZE, 1) | 101 | /* Resolution in the MONITOR mode */ |
102 | #define PARM_MON_SIZE I2C_REG(CAT_PARAM, 0x01, 1) | ||
114 | 103 | ||
115 | #define PARM_MON_FPS I2C_REG(CAT_PARAM, CAT1_MONITOR_FPS, 1) | 104 | /* Frame rate */ |
105 | #define PARM_MON_FPS I2C_REG(CAT_PARAM, 0x02, 1) | ||
116 | #define REG_FPS_30 0x02 | 106 | #define REG_FPS_30 0x02 |
117 | 107 | ||
118 | #define PARM_INTERFACE I2C_REG(CAT_PARAM, CAT1_DATA_INTERFACE, 1) | 108 | /* Video bus between the sensor and a host processor */ |
109 | #define PARM_INTERFACE I2C_REG(CAT_PARAM, 0x00, 1) | ||
119 | #define REG_INTERFACE_MIPI 0x02 | 110 | #define REG_INTERFACE_MIPI 0x02 |
120 | 111 | ||
121 | #define PARM_EFFECT I2C_REG(CAT_PARAM, CAT1_EFFECT, 1) | 112 | /* Image effects */ |
113 | #define PARM_EFFECT I2C_REG(CAT_PARAM, 0x0b, 1) | ||
122 | #define REG_EFFECT_OFF 0x00 | 114 | #define REG_EFFECT_OFF 0x00 |
123 | #define REG_EFFECT_NEGA 0x01 | 115 | #define REG_EFFECT_NEGA 0x01 |
124 | #define REG_EFFECT_EMBOSS 0x06 | 116 | #define REG_EFFECT_EMBOSS 0x06 |
@@ -135,39 +127,37 @@ | |||
135 | * another options like zoom/color effect(different with effect in PARAMETER | 127 | * another options like zoom/color effect(different with effect in PARAMETER |
136 | * mode)/anti hand shaking algorithm. | 128 | * mode)/anti hand shaking algorithm. |
137 | */ | 129 | */ |
138 | #define CAT2_ZOOM 0x01 /* set the zoom position & execute */ | 130 | |
139 | #define CAT2_ZOOM_STEP 0x03 /* set the zoom step */ | 131 | /* Target digital zoom position */ |
140 | #define CAT2_CFIXB 0x09 /* CB value for color effect */ | 132 | #define MON_ZOOM I2C_REG(CAT_MONITOR, 0x01, 1) |
141 | #define CAT2_CFIXR 0x0a /* CR value for color effect */ | 133 | |
142 | #define CAT2_COLOR_EFFECT 0x0b /* set on/off of color effect */ | 134 | /* CR value for color effect */ |
143 | #define CAT2_CHROMA_LVL 0x0f /* set chroma level */ | 135 | #define MON_CFIXR I2C_REG(CAT_MONITOR, 0x0a, 1) |
144 | #define CAT2_CHROMA_EN 0x10 /* set on/off of choroma */ | 136 | /* CB value for color effect */ |
145 | #define CAT2_EDGE_LVL 0x11 /* set sharpness level */ | 137 | #define MON_CFIXB I2C_REG(CAT_MONITOR, 0x09, 1) |
146 | #define CAT2_EDGE_EN 0x12 /* set on/off sharpness */ | ||
147 | #define CAT2_TONE_CTL 0x25 /* set tone color(contrast) */ | ||
148 | |||
149 | #define MON_ZOOM I2C_REG(CAT_MONITOR, CAT2_ZOOM, 1) | ||
150 | |||
151 | #define MON_CFIXR I2C_REG(CAT_MONITOR, CAT2_CFIXR, 1) | ||
152 | #define MON_CFIXB I2C_REG(CAT_MONITOR, CAT2_CFIXB, 1) | ||
153 | #define REG_CFIXB_SEPIA 0xd8 | 138 | #define REG_CFIXB_SEPIA 0xd8 |
154 | #define REG_CFIXR_SEPIA 0x18 | 139 | #define REG_CFIXR_SEPIA 0x18 |
155 | 140 | ||
156 | #define MON_EFFECT I2C_REG(CAT_MONITOR, CAT2_COLOR_EFFECT, 1) | 141 | #define MON_EFFECT I2C_REG(CAT_MONITOR, 0x0b, 1) |
157 | #define REG_COLOR_EFFECT_OFF 0x00 | 142 | #define REG_COLOR_EFFECT_OFF 0x00 |
158 | #define REG_COLOR_EFFECT_ON 0x01 | 143 | #define REG_COLOR_EFFECT_ON 0x01 |
159 | 144 | ||
160 | #define MON_CHROMA_EN I2C_REG(CAT_MONITOR, CAT2_CHROMA_EN, 1) | 145 | /* Chroma enable */ |
161 | #define MON_CHROMA_LVL I2C_REG(CAT_MONITOR, CAT2_CHROMA_LVL, 1) | 146 | #define MON_CHROMA_EN I2C_REG(CAT_MONITOR, 0x10, 1) |
147 | /* Chroma level */ | ||
148 | #define MON_CHROMA_LVL I2C_REG(CAT_MONITOR, 0x0f, 1) | ||
162 | #define REG_CHROMA_OFF 0x00 | 149 | #define REG_CHROMA_OFF 0x00 |
163 | #define REG_CHROMA_ON 0x01 | 150 | #define REG_CHROMA_ON 0x01 |
164 | 151 | ||
165 | #define MON_EDGE_EN I2C_REG(CAT_MONITOR, CAT2_EDGE_EN, 1) | 152 | /* Sharpness on/off */ |
166 | #define MON_EDGE_LVL I2C_REG(CAT_MONITOR, CAT2_EDGE_LVL, 1) | 153 | #define MON_EDGE_EN I2C_REG(CAT_MONITOR, 0x12, 1) |
154 | /* Sharpness level */ | ||
155 | #define MON_EDGE_LVL I2C_REG(CAT_MONITOR, 0x11, 1) | ||
167 | #define REG_EDGE_OFF 0x00 | 156 | #define REG_EDGE_OFF 0x00 |
168 | #define REG_EDGE_ON 0x01 | 157 | #define REG_EDGE_ON 0x01 |
169 | 158 | ||
170 | #define MON_TONE_CTL I2C_REG(CAT_MONITOR, CAT2_TONE_CTL, 1) | 159 | /* Set color tone (contrast) */ |
160 | #define MON_TONE_CTL I2C_REG(CAT_MONITOR, 0x25, 1) | ||
171 | 161 | ||
172 | /* | 162 | /* |
173 | * Category 3 - Auto Exposure | 163 | * Category 3 - Auto Exposure |
@@ -179,27 +169,20 @@ | |||
179 | * different. So, this category also provide getting the max/min values. And, | 169 | * different. So, this category also provide getting the max/min values. And, |
180 | * each MONITOR and CAPTURE mode has each gain/shutter/max exposure values. | 170 | * each MONITOR and CAPTURE mode has each gain/shutter/max exposure values. |
181 | */ | 171 | */ |
182 | #define CAT3_AE_LOCK 0x00 /* locking Auto exposure */ | 172 | |
183 | #define CAT3_AE_MODE 0x01 /* set AE mode, mode means range */ | 173 | /* Auto Exposure locking */ |
184 | #define CAT3_ISO 0x05 /* set ISO */ | 174 | #define AE_LOCK I2C_REG(CAT_AE, 0x00, 1) |
185 | #define CAT3_EV_PRESET_MONITOR 0x0a /* EV(scenemode) preset for MONITOR */ | ||
186 | #define CAT3_EV_PRESET_CAPTURE 0x0b /* EV(scenemode) preset for CAPTURE */ | ||
187 | #define CAT3_MANUAL_GAIN_MON 0x12 /* meteoring value for the MONITOR */ | ||
188 | #define CAT3_MAX_GAIN_MON 0x1a /* max gain value for the MONITOR */ | ||
189 | #define CAT3_MANUAL_GAIN_CAP 0x26 /* meteoring value for the CAPTURE */ | ||
190 | #define CAT3_AE_INDEX 0x38 /* AE index */ | ||
191 | |||
192 | #define AE_LOCK I2C_REG(CAT_AE, CAT3_AE_LOCK, 1) | ||
193 | #define REG_AE_UNLOCK 0x00 | 175 | #define REG_AE_UNLOCK 0x00 |
194 | #define REG_AE_LOCK 0x01 | 176 | #define REG_AE_LOCK 0x01 |
195 | 177 | ||
196 | #define AE_MODE I2C_REG(CAT_AE, CAT3_AE_MODE, 1) | 178 | /* Auto Exposure algorithm mode */ |
179 | #define AE_MODE I2C_REG(CAT_AE, 0x01, 1) | ||
197 | #define REG_AE_OFF 0x00 /* AE off */ | 180 | #define REG_AE_OFF 0x00 /* AE off */ |
198 | #define REG_AE_ALL 0x01 /* calc AE in all block integral */ | 181 | #define REG_AE_ALL 0x01 /* calc AE in all block integral */ |
199 | #define REG_AE_CENTER 0x03 /* calc AE in center weighted */ | 182 | #define REG_AE_CENTER 0x03 /* calc AE in center weighted */ |
200 | #define REG_AE_SPOT 0x06 /* calc AE in specific spot */ | 183 | #define REG_AE_SPOT 0x06 /* calc AE in specific spot */ |
201 | 184 | ||
202 | #define AE_ISO I2C_REG(CAT_AE, CAT3_ISO, 1) | 185 | #define AE_ISO I2C_REG(CAT_AE, 0x05, 1) |
203 | #define REG_ISO_AUTO 0x00 | 186 | #define REG_ISO_AUTO 0x00 |
204 | #define REG_ISO_50 0x01 | 187 | #define REG_ISO_50 0x01 |
205 | #define REG_ISO_100 0x02 | 188 | #define REG_ISO_100 0x02 |
@@ -207,8 +190,10 @@ | |||
207 | #define REG_ISO_400 0x04 | 190 | #define REG_ISO_400 0x04 |
208 | #define REG_ISO_800 0x05 | 191 | #define REG_ISO_800 0x05 |
209 | 192 | ||
210 | #define AE_EV_PRESET_MONITOR I2C_REG(CAT_AE, CAT3_EV_PRESET_MONITOR, 1) | 193 | /* EV (scenemode) preset for MONITOR */ |
211 | #define AE_EV_PRESET_CAPTURE I2C_REG(CAT_AE, CAT3_EV_PRESET_CAPTURE, 1) | 194 | #define AE_EV_PRESET_MONITOR I2C_REG(CAT_AE, 0x0a, 1) |
195 | /* EV (scenemode) preset for CAPTURE */ | ||
196 | #define AE_EV_PRESET_CAPTURE I2C_REG(CAT_AE, 0x0b, 1) | ||
212 | #define REG_SCENE_NORMAL 0x00 | 197 | #define REG_SCENE_NORMAL 0x00 |
213 | #define REG_SCENE_PORTRAIT 0x01 | 198 | #define REG_SCENE_PORTRAIT 0x01 |
214 | #define REG_SCENE_LANDSCAPE 0x02 | 199 | #define REG_SCENE_LANDSCAPE 0x02 |
@@ -224,11 +209,14 @@ | |||
224 | #define REG_SCENE_TEXT 0x0c | 209 | #define REG_SCENE_TEXT 0x0c |
225 | #define REG_SCENE_CANDLE 0x0d | 210 | #define REG_SCENE_CANDLE 0x0d |
226 | 211 | ||
227 | #define AE_MAN_GAIN_MON I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_MON, 2) | 212 | /* Manual gain in MONITOR mode */ |
228 | #define AE_MAX_GAIN_MON I2C_REG(CAT_AE, CAT3_MAX_GAIN_MON, 2) | 213 | #define AE_MAN_GAIN_MON I2C_REG(CAT_AE, 0x12, 2) |
229 | #define AE_MAN_GAIN_CAP I2C_REG(CAT_AE, CAT3_MANUAL_GAIN_CAP, 2) | 214 | /* Maximum gain in MONITOR mode */ |
215 | #define AE_MAX_GAIN_MON I2C_REG(CAT_AE, 0x1a, 2) | ||
216 | /* Manual gain in CAPTURE mode */ | ||
217 | #define AE_MAN_GAIN_CAP I2C_REG(CAT_AE, 0x26, 2) | ||
230 | 218 | ||
231 | #define AE_INDEX I2C_REG(CAT_AE, CAT3_AE_INDEX, 1) | 219 | #define AE_INDEX I2C_REG(CAT_AE, 0x38, 1) |
232 | #define REG_AE_INDEX_20_NEG 0x00 | 220 | #define REG_AE_INDEX_20_NEG 0x00 |
233 | #define REG_AE_INDEX_15_NEG 0x01 | 221 | #define REG_AE_INDEX_15_NEG 0x01 |
234 | #define REG_AE_INDEX_10_NEG 0x02 | 222 | #define REG_AE_INDEX_10_NEG 0x02 |
@@ -241,22 +229,19 @@ | |||
241 | 229 | ||
242 | /* | 230 | /* |
243 | * Category 6 - White Balance | 231 | * Category 6 - White Balance |
244 | * | ||
245 | * This category provide AWB locking/mode/preset/speed/gain bias, etc. | ||
246 | */ | 232 | */ |
247 | #define CAT6_AWB_LOCK 0x00 /* locking Auto Whitebalance */ | ||
248 | #define CAT6_AWB_MODE 0x02 /* set Auto or Manual */ | ||
249 | #define CAT6_AWB_MANUAL 0x03 /* set Manual(preset) value */ | ||
250 | 233 | ||
251 | #define AWB_LOCK I2C_REG(CAT_WB, CAT6_AWB_LOCK, 1) | 234 | /* Auto Whitebalance locking */ |
235 | #define AWB_LOCK I2C_REG(CAT_WB, 0x00, 1) | ||
252 | #define REG_AWB_UNLOCK 0x00 | 236 | #define REG_AWB_UNLOCK 0x00 |
253 | #define REG_AWB_LOCK 0x01 | 237 | #define REG_AWB_LOCK 0x01 |
254 | 238 | ||
255 | #define AWB_MODE I2C_REG(CAT_WB, CAT6_AWB_MODE, 1) | 239 | #define AWB_MODE I2C_REG(CAT_WB, 0x02, 1) |
256 | #define REG_AWB_AUTO 0x01 /* AWB off */ | 240 | #define REG_AWB_AUTO 0x01 /* AWB off */ |
257 | #define REG_AWB_PRESET 0x02 /* AWB preset */ | 241 | #define REG_AWB_PRESET 0x02 /* AWB preset */ |
258 | 242 | ||
259 | #define AWB_MANUAL I2C_REG(CAT_WB, CAT6_AWB_MANUAL, 1) | 243 | /* Manual WB (preset) */ |
244 | #define AWB_MANUAL I2C_REG(CAT_WB, 0x03, 1) | ||
260 | #define REG_AWB_INCANDESCENT 0x01 | 245 | #define REG_AWB_INCANDESCENT 0x01 |
261 | #define REG_AWB_FLUORESCENT_1 0x02 | 246 | #define REG_AWB_FLUORESCENT_1 0x02 |
262 | #define REG_AWB_FLUORESCENT_2 0x03 | 247 | #define REG_AWB_FLUORESCENT_2 0x03 |
@@ -269,42 +254,25 @@ | |||
269 | /* | 254 | /* |
270 | * Category 7 - EXIF information | 255 | * Category 7 - EXIF information |
271 | */ | 256 | */ |
272 | #define CAT7_INFO_EXPTIME_NU 0x00 | 257 | #define EXIF_INFO_EXPTIME_NU I2C_REG(CAT_EXIF, 0x00, 4) |
273 | #define CAT7_INFO_EXPTIME_DE 0x04 | 258 | #define EXIF_INFO_EXPTIME_DE I2C_REG(CAT_EXIF, 0x04, 4) |
274 | #define CAT7_INFO_TV_NU 0x08 | 259 | #define EXIF_INFO_TV_NU I2C_REG(CAT_EXIF, 0x08, 4) |
275 | #define CAT7_INFO_TV_DE 0x0c | 260 | #define EXIF_INFO_TV_DE I2C_REG(CAT_EXIF, 0x0c, 4) |
276 | #define CAT7_INFO_AV_NU 0x10 | 261 | #define EXIF_INFO_AV_NU I2C_REG(CAT_EXIF, 0x10, 4) |
277 | #define CAT7_INFO_AV_DE 0x14 | 262 | #define EXIF_INFO_AV_DE I2C_REG(CAT_EXIF, 0x14, 4) |
278 | #define CAT7_INFO_BV_NU 0x18 | 263 | #define EXIF_INFO_BV_NU I2C_REG(CAT_EXIF, 0x18, 4) |
279 | #define CAT7_INFO_BV_DE 0x1c | 264 | #define EXIF_INFO_BV_DE I2C_REG(CAT_EXIF, 0x1c, 4) |
280 | #define CAT7_INFO_EBV_NU 0x20 | 265 | #define EXIF_INFO_EBV_NU I2C_REG(CAT_EXIF, 0x20, 4) |
281 | #define CAT7_INFO_EBV_DE 0x24 | 266 | #define EXIF_INFO_EBV_DE I2C_REG(CAT_EXIF, 0x24, 4) |
282 | #define CAT7_INFO_ISO 0x28 | 267 | #define EXIF_INFO_ISO I2C_REG(CAT_EXIF, 0x28, 2) |
283 | #define CAT7_INFO_FLASH 0x2a | 268 | #define EXIF_INFO_FLASH I2C_REG(CAT_EXIF, 0x2a, 2) |
284 | #define CAT7_INFO_SDR 0x2c | 269 | #define EXIF_INFO_SDR I2C_REG(CAT_EXIF, 0x2c, 2) |
285 | #define CAT7_INFO_QVAL 0x2e | 270 | #define EXIF_INFO_QVAL I2C_REG(CAT_EXIF, 0x2e, 2) |
286 | |||
287 | #define EXIF_INFO_EXPTIME_NU I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_NU, 4) | ||
288 | #define EXIF_INFO_EXPTIME_DE I2C_REG(CAT_EXIF, CAT7_INFO_EXPTIME_DE, 4) | ||
289 | #define EXIF_INFO_TV_NU I2C_REG(CAT_EXIF, CAT7_INFO_TV_NU, 4) | ||
290 | #define EXIF_INFO_TV_DE I2C_REG(CAT_EXIF, CAT7_INFO_TV_DE, 4) | ||
291 | #define EXIF_INFO_AV_NU I2C_REG(CAT_EXIF, CAT7_INFO_AV_NU, 4) | ||
292 | #define EXIF_INFO_AV_DE I2C_REG(CAT_EXIF, CAT7_INFO_AV_DE, 4) | ||
293 | #define EXIF_INFO_BV_NU I2C_REG(CAT_EXIF, CAT7_INFO_BV_NU, 4) | ||
294 | #define EXIF_INFO_BV_DE I2C_REG(CAT_EXIF, CAT7_INFO_BV_DE, 4) | ||
295 | #define EXIF_INFO_EBV_NU I2C_REG(CAT_EXIF, CAT7_INFO_EBV_NU, 4) | ||
296 | #define EXIF_INFO_EBV_DE I2C_REG(CAT_EXIF, CAT7_INFO_EBV_DE, 4) | ||
297 | #define EXIF_INFO_ISO I2C_REG(CAT_EXIF, CAT7_INFO_ISO, 2) | ||
298 | #define EXIF_INFO_FLASH I2C_REG(CAT_EXIF, CAT7_INFO_FLASH, 2) | ||
299 | #define EXIF_INFO_SDR I2C_REG(CAT_EXIF, CAT7_INFO_SDR, 2) | ||
300 | #define EXIF_INFO_QVAL I2C_REG(CAT_EXIF, CAT7_INFO_QVAL, 2) | ||
301 | 271 | ||
302 | /* | 272 | /* |
303 | * Category 9 - Face Detection | 273 | * Category 9 - Face Detection |
304 | */ | 274 | */ |
305 | #define CAT9_FD_CTL 0x00 | 275 | #define FD_CTL I2C_REG(CAT_FD, 0x00, 1) |
306 | |||
307 | #define FD_CTL I2C_REG(CAT_FD, CAT9_FD_CTL, 1) | ||
308 | #define BIT_FD_EN 0 | 276 | #define BIT_FD_EN 0 |
309 | #define BIT_FD_DRAW_FACE_FRAME 4 | 277 | #define BIT_FD_DRAW_FACE_FRAME 4 |
310 | #define BIT_FD_DRAW_SMILE_LVL 6 | 278 | #define BIT_FD_DRAW_SMILE_LVL 6 |
@@ -314,62 +282,50 @@ | |||
314 | /* | 282 | /* |
315 | * Category A - Lens Parameter | 283 | * Category A - Lens Parameter |
316 | */ | 284 | */ |
317 | #define CATA_AF_MODE 0x01 | 285 | #define AF_MODE I2C_REG(CAT_LENS, 0x01, 1) |
318 | #define CATA_AF_EXECUTE 0x02 | ||
319 | #define CATA_AF_STATUS 0x03 | ||
320 | #define CATA_AF_VERSION 0x0a | ||
321 | |||
322 | #define AF_MODE I2C_REG(CAT_LENS, CATA_AF_MODE, 1) | ||
323 | #define REG_AF_NORMAL 0x00 /* Normal AF, one time */ | 286 | #define REG_AF_NORMAL 0x00 /* Normal AF, one time */ |
324 | #define REG_AF_MACRO 0x01 /* Macro AF, one time */ | 287 | #define REG_AF_MACRO 0x01 /* Macro AF, one time */ |
325 | #define REG_AF_POWEROFF 0x07 | 288 | #define REG_AF_POWEROFF 0x07 |
326 | 289 | ||
327 | #define AF_EXECUTE I2C_REG(CAT_LENS, CATA_AF_EXECUTE, 1) | 290 | #define AF_EXECUTE I2C_REG(CAT_LENS, 0x02, 1) |
328 | #define REG_AF_STOP 0x00 | 291 | #define REG_AF_STOP 0x00 |
329 | #define REG_AF_EXE_AUTO 0x01 | 292 | #define REG_AF_EXE_AUTO 0x01 |
330 | #define REG_AF_EXE_CAF 0x02 | 293 | #define REG_AF_EXE_CAF 0x02 |
331 | 294 | ||
332 | #define AF_STATUS I2C_REG(CAT_LENS, CATA_AF_STATUS, 1) | 295 | #define AF_STATUS I2C_REG(CAT_LENS, 0x03, 1) |
333 | #define REG_AF_FAIL 0x00 | 296 | #define REG_AF_FAIL 0x00 |
334 | #define REG_AF_SUCCESS 0x02 | 297 | #define REG_AF_SUCCESS 0x02 |
335 | #define REG_AF_IDLE 0x04 | 298 | #define REG_AF_IDLE 0x04 |
336 | #define REG_AF_BUSY 0x05 | 299 | #define REG_AF_BUSY 0x05 |
337 | 300 | ||
338 | #define AF_VERSION I2C_REG(CAT_LENS, CATA_AF_VERSION, 1) | 301 | #define AF_VERSION I2C_REG(CAT_LENS, 0x0a, 1) |
339 | 302 | ||
340 | /* | 303 | /* |
341 | * Category B - CAPTURE Parameter | 304 | * Category B - CAPTURE Parameter |
342 | */ | 305 | */ |
343 | #define CATB_YUVOUT_MAIN 0x00 | 306 | #define CAPP_YUVOUT_MAIN I2C_REG(CAT_CAPT_PARM, 0x00, 1) |
344 | #define CATB_MAIN_IMAGE_SIZE 0x01 | ||
345 | #define CATB_MCC_MODE 0x1d | ||
346 | #define CATB_WDR_EN 0x2c | ||
347 | #define CATB_LIGHT_CTRL 0x40 | ||
348 | #define CATB_FLASH_CTRL 0x41 | ||
349 | |||
350 | #define CAPP_YUVOUT_MAIN I2C_REG(CAT_CAPT_PARM, CATB_YUVOUT_MAIN, 1) | ||
351 | #define REG_YUV422 0x00 | 307 | #define REG_YUV422 0x00 |
352 | #define REG_BAYER10 0x05 | 308 | #define REG_BAYER10 0x05 |
353 | #define REG_BAYER8 0x06 | 309 | #define REG_BAYER8 0x06 |
354 | #define REG_JPEG 0x10 | 310 | #define REG_JPEG 0x10 |
355 | 311 | ||
356 | #define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, CATB_MAIN_IMAGE_SIZE, 1) | 312 | #define CAPP_MAIN_IMAGE_SIZE I2C_REG(CAT_CAPT_PARM, 0x01, 1) |
357 | 313 | ||
358 | #define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, CATB_MCC_MODE, 1) | 314 | #define CAPP_MCC_MODE I2C_REG(CAT_CAPT_PARM, 0x1d, 1) |
359 | #define REG_MCC_OFF 0x00 | 315 | #define REG_MCC_OFF 0x00 |
360 | #define REG_MCC_NORMAL 0x01 | 316 | #define REG_MCC_NORMAL 0x01 |
361 | 317 | ||
362 | #define CAPP_WDR_EN I2C_REG(CAT_CAPT_PARM, CATB_WDR_EN, 1) | 318 | #define CAPP_WDR_EN I2C_REG(CAT_CAPT_PARM, 0x2c, 1) |
363 | #define REG_WDR_OFF 0x00 | 319 | #define REG_WDR_OFF 0x00 |
364 | #define REG_WDR_ON 0x01 | 320 | #define REG_WDR_ON 0x01 |
365 | #define REG_WDR_AUTO 0x02 | 321 | #define REG_WDR_AUTO 0x02 |
366 | 322 | ||
367 | #define CAPP_LIGHT_CTRL I2C_REG(CAT_CAPT_PARM, CATB_LIGHT_CTRL, 1) | 323 | #define CAPP_LIGHT_CTRL I2C_REG(CAT_CAPT_PARM, 0x40, 1) |
368 | #define REG_LIGHT_OFF 0x00 | 324 | #define REG_LIGHT_OFF 0x00 |
369 | #define REG_LIGHT_ON 0x01 | 325 | #define REG_LIGHT_ON 0x01 |
370 | #define REG_LIGHT_AUTO 0x02 | 326 | #define REG_LIGHT_AUTO 0x02 |
371 | 327 | ||
372 | #define CAPP_FLASH_CTRL I2C_REG(CAT_CAPT_PARM, CATB_FLASH_CTRL, 1) | 328 | #define CAPP_FLASH_CTRL I2C_REG(CAT_CAPT_PARM, 0x41, 1) |
373 | #define REG_FLASH_OFF 0x00 | 329 | #define REG_FLASH_OFF 0x00 |
374 | #define REG_FLASH_ON 0x01 | 330 | #define REG_FLASH_ON 0x01 |
375 | #define REG_FLASH_AUTO 0x02 | 331 | #define REG_FLASH_AUTO 0x02 |
@@ -377,34 +333,29 @@ | |||
377 | /* | 333 | /* |
378 | * Category C - CAPTURE Control | 334 | * Category C - CAPTURE Control |
379 | */ | 335 | */ |
380 | #define CATC_CAP_MODE 0x00 | 336 | #define CAPC_MODE I2C_REG(CAT_CAPT_CTRL, 0x00, 1) |
381 | #define CATC_CAP_SEL_FRAME 0x06 /* It determines Single or Multi */ | ||
382 | #define CATC_CAP_START 0x09 | ||
383 | #define CATC_CAP_IMAGE_SIZE 0x0d | ||
384 | #define CATC_CAP_THUMB_SIZE 0x11 | ||
385 | |||
386 | #define CAPC_MODE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_MODE, 1) | ||
387 | #define REG_CAP_NONE 0x00 | 337 | #define REG_CAP_NONE 0x00 |
388 | #define REG_CAP_ANTI_SHAKE 0x02 | 338 | #define REG_CAP_ANTI_SHAKE 0x02 |
389 | 339 | ||
390 | #define CAPC_SEL_FRAME I2C_REG(CAT_CAPT_CTRL, CATC_CAP_SEL_FRAME, 1) | 340 | /* Select single- or multi-shot capture */ |
341 | #define CAPC_SEL_FRAME I2C_REG(CAT_CAPT_CTRL, 0x06, 1) | ||
391 | 342 | ||
392 | #define CAPC_START I2C_REG(CAT_CAPT_CTRL, CATC_CAP_START, 1) | 343 | #define CAPC_START I2C_REG(CAT_CAPT_CTRL, 0x09, 1) |
393 | #define REG_CAP_START_MAIN 0x01 | 344 | #define REG_CAP_START_MAIN 0x01 |
394 | #define REG_CAP_START_THUMB 0x03 | 345 | #define REG_CAP_START_THUMB 0x03 |
395 | 346 | ||
396 | #define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 4) | 347 | #define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, 0x0d, 4) |
397 | #define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 4) | 348 | #define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, 0x11, 4) |
398 | 349 | ||
399 | /* | 350 | /* |
400 | * Category F - Flash | 351 | * Category F - Flash |
401 | * | 352 | * |
402 | * This mode provides functions about internal flash stuff and system startup. | 353 | * This mode provides functions about internal flash stuff and system startup. |
403 | */ | 354 | */ |
404 | #define CATF_CAM_START 0x12 /* It starts internal ARM core booting | ||
405 | * after power-up */ | ||
406 | 355 | ||
407 | #define FLASH_CAM_START I2C_REG(CAT_FLASH, CATF_CAM_START, 1) | 356 | /* Starts internal ARM core booting after power-up */ |
408 | #define REG_START_ARM_BOOT 0x01 | 357 | #define FLASH_CAM_START I2C_REG(CAT_FLASH, 0x12, 1) |
358 | #define REG_START_ARM_BOOT 0x01 /* write value */ | ||
359 | #define REG_IN_FLASH_MODE 0x00 /* read value */ | ||
409 | 360 | ||
410 | #endif /* M5MOLS_REG_H */ | 361 | #endif /* M5MOLS_REG_H */ |
diff --git a/drivers/media/video/marvell-ccic/mcam-core.c b/drivers/media/video/marvell-ccic/mcam-core.c index 2c8fc0f6d690..37d20e73908a 100644 --- a/drivers/media/video/marvell-ccic/mcam-core.c +++ b/drivers/media/video/marvell-ccic/mcam-core.c | |||
@@ -522,6 +522,15 @@ static void mcam_sg_next_buffer(struct mcam_camera *cam) | |||
522 | */ | 522 | */ |
523 | static void mcam_ctlr_dma_sg(struct mcam_camera *cam) | 523 | static void mcam_ctlr_dma_sg(struct mcam_camera *cam) |
524 | { | 524 | { |
525 | /* | ||
526 | * The list-empty condition can hit us at resume time | ||
527 | * if the buffer list was empty when the system was suspended. | ||
528 | */ | ||
529 | if (list_empty(&cam->buffers)) { | ||
530 | set_bit(CF_SG_RESTART, &cam->flags); | ||
531 | return; | ||
532 | } | ||
533 | |||
525 | mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_3WORD); | 534 | mcam_reg_clear_bit(cam, REG_CTRL1, C1_DESC_3WORD); |
526 | mcam_sg_next_buffer(cam); | 535 | mcam_sg_next_buffer(cam); |
527 | mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); | 536 | mcam_reg_set_bit(cam, REG_CTRL1, C1_DESC_ENA); |
@@ -566,6 +575,7 @@ static void mcam_dma_sg_done(struct mcam_camera *cam, int frame) | |||
566 | } else { | 575 | } else { |
567 | set_bit(CF_SG_RESTART, &cam->flags); | 576 | set_bit(CF_SG_RESTART, &cam->flags); |
568 | singles++; | 577 | singles++; |
578 | cam->vb_bufs[0] = NULL; | ||
569 | } | 579 | } |
570 | /* | 580 | /* |
571 | * Now we can give the completed frame back to user space. | 581 | * Now we can give the completed frame back to user space. |
@@ -661,10 +671,10 @@ static int mcam_ctlr_configure(struct mcam_camera *cam) | |||
661 | unsigned long flags; | 671 | unsigned long flags; |
662 | 672 | ||
663 | spin_lock_irqsave(&cam->dev_lock, flags); | 673 | spin_lock_irqsave(&cam->dev_lock, flags); |
674 | clear_bit(CF_SG_RESTART, &cam->flags); | ||
664 | cam->dma_setup(cam); | 675 | cam->dma_setup(cam); |
665 | mcam_ctlr_image(cam); | 676 | mcam_ctlr_image(cam); |
666 | mcam_set_config_needed(cam, 0); | 677 | mcam_set_config_needed(cam, 0); |
667 | clear_bit(CF_SG_RESTART, &cam->flags); | ||
668 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 678 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
669 | return 0; | 679 | return 0; |
670 | } | 680 | } |
@@ -873,7 +883,8 @@ static int mcam_read_setup(struct mcam_camera *cam) | |||
873 | mcam_reset_buffers(cam); | 883 | mcam_reset_buffers(cam); |
874 | mcam_ctlr_irq_enable(cam); | 884 | mcam_ctlr_irq_enable(cam); |
875 | cam->state = S_STREAMING; | 885 | cam->state = S_STREAMING; |
876 | mcam_ctlr_start(cam); | 886 | if (!test_bit(CF_SG_RESTART, &cam->flags)) |
887 | mcam_ctlr_start(cam); | ||
877 | spin_unlock_irqrestore(&cam->dev_lock, flags); | 888 | spin_unlock_irqrestore(&cam->dev_lock, flags); |
878 | return 0; | 889 | return 0; |
879 | } | 890 | } |
@@ -1818,11 +1829,15 @@ void mccic_shutdown(struct mcam_camera *cam) | |||
1818 | 1829 | ||
1819 | void mccic_suspend(struct mcam_camera *cam) | 1830 | void mccic_suspend(struct mcam_camera *cam) |
1820 | { | 1831 | { |
1821 | enum mcam_state cstate = cam->state; | 1832 | mutex_lock(&cam->s_mutex); |
1833 | if (cam->users > 0) { | ||
1834 | enum mcam_state cstate = cam->state; | ||
1822 | 1835 | ||
1823 | mcam_ctlr_stop_dma(cam); | 1836 | mcam_ctlr_stop_dma(cam); |
1824 | mcam_ctlr_power_down(cam); | 1837 | mcam_ctlr_power_down(cam); |
1825 | cam->state = cstate; | 1838 | cam->state = cstate; |
1839 | } | ||
1840 | mutex_unlock(&cam->s_mutex); | ||
1826 | } | 1841 | } |
1827 | 1842 | ||
1828 | int mccic_resume(struct mcam_camera *cam) | 1843 | int mccic_resume(struct mcam_camera *cam) |
@@ -1839,8 +1854,15 @@ int mccic_resume(struct mcam_camera *cam) | |||
1839 | mutex_unlock(&cam->s_mutex); | 1854 | mutex_unlock(&cam->s_mutex); |
1840 | 1855 | ||
1841 | set_bit(CF_CONFIG_NEEDED, &cam->flags); | 1856 | set_bit(CF_CONFIG_NEEDED, &cam->flags); |
1842 | if (cam->state == S_STREAMING) | 1857 | if (cam->state == S_STREAMING) { |
1858 | /* | ||
1859 | * If there was a buffer in the DMA engine at suspend | ||
1860 | * time, put it back on the queue or we'll forget about it. | ||
1861 | */ | ||
1862 | if (cam->buffer_mode == B_DMA_sg && cam->vb_bufs[0]) | ||
1863 | list_add(&cam->vb_bufs[0]->queue, &cam->buffers); | ||
1843 | ret = mcam_read_setup(cam); | 1864 | ret = mcam_read_setup(cam); |
1865 | } | ||
1844 | return ret; | 1866 | return ret; |
1845 | } | 1867 | } |
1846 | #endif /* CONFIG_PM */ | 1868 | #endif /* CONFIG_PM */ |
diff --git a/drivers/media/video/marvell-ccic/mmp-driver.c b/drivers/media/video/marvell-ccic/mmp-driver.c index fb0b124b35f3..0d64e2d7474a 100644 --- a/drivers/media/video/marvell-ccic/mmp-driver.c +++ b/drivers/media/video/marvell-ccic/mmp-driver.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/io.h> | 26 | #include <linux/io.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
29 | #include <linux/pm.h> | ||
29 | 30 | ||
30 | #include "mcam-core.h" | 31 | #include "mcam-core.h" |
31 | 32 | ||
@@ -310,10 +311,44 @@ static int mmpcam_platform_remove(struct platform_device *pdev) | |||
310 | return mmpcam_remove(cam); | 311 | return mmpcam_remove(cam); |
311 | } | 312 | } |
312 | 313 | ||
314 | /* | ||
315 | * Suspend/resume support. | ||
316 | */ | ||
317 | #ifdef CONFIG_PM | ||
318 | |||
319 | static int mmpcam_suspend(struct platform_device *pdev, pm_message_t state) | ||
320 | { | ||
321 | struct mmp_camera *cam = mmpcam_find_device(pdev); | ||
322 | |||
323 | if (state.event != PM_EVENT_SUSPEND) | ||
324 | return 0; | ||
325 | mccic_suspend(&cam->mcam); | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static int mmpcam_resume(struct platform_device *pdev) | ||
330 | { | ||
331 | struct mmp_camera *cam = mmpcam_find_device(pdev); | ||
332 | |||
333 | /* | ||
334 | * Power up unconditionally just in case the core tries to | ||
335 | * touch a register even if nothing was active before; trust | ||
336 | * me, it's better this way. | ||
337 | */ | ||
338 | mmpcam_power_up(&cam->mcam); | ||
339 | return mccic_resume(&cam->mcam); | ||
340 | } | ||
341 | |||
342 | #endif | ||
343 | |||
313 | 344 | ||
314 | static struct platform_driver mmpcam_driver = { | 345 | static struct platform_driver mmpcam_driver = { |
315 | .probe = mmpcam_probe, | 346 | .probe = mmpcam_probe, |
316 | .remove = mmpcam_platform_remove, | 347 | .remove = mmpcam_platform_remove, |
348 | #ifdef CONFIG_PM | ||
349 | .suspend = mmpcam_suspend, | ||
350 | .resume = mmpcam_resume, | ||
351 | #endif | ||
317 | .driver = { | 352 | .driver = { |
318 | .name = "mmp-camera", | 353 | .name = "mmp-camera", |
319 | .owner = THIS_MODULE | 354 | .owner = THIS_MODULE |
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index e2b1029b16cd..097c9d3d04a8 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c | |||
@@ -109,14 +109,13 @@ static struct mt9m001 *to_mt9m001(const struct i2c_client *client) | |||
109 | 109 | ||
110 | static int reg_read(struct i2c_client *client, const u8 reg) | 110 | static int reg_read(struct i2c_client *client, const u8 reg) |
111 | { | 111 | { |
112 | s32 data = i2c_smbus_read_word_data(client, reg); | 112 | return i2c_smbus_read_word_swapped(client, reg); |
113 | return data < 0 ? data : swab16(data); | ||
114 | } | 113 | } |
115 | 114 | ||
116 | static int reg_write(struct i2c_client *client, const u8 reg, | 115 | static int reg_write(struct i2c_client *client, const u8 reg, |
117 | const u16 data) | 116 | const u16 data) |
118 | { | 117 | { |
119 | return i2c_smbus_write_word_data(client, reg, swab16(data)); | 118 | return i2c_smbus_write_word_swapped(client, reg, data); |
120 | } | 119 | } |
121 | 120 | ||
122 | static int reg_set(struct i2c_client *client, const u8 reg, | 121 | static int reg_set(struct i2c_client *client, const u8 reg, |
diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index 398f96ffd35e..bee65bff46e8 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c | |||
@@ -139,25 +139,52 @@ | |||
139 | #define MT9M111_MAX_HEIGHT 1024 | 139 | #define MT9M111_MAX_HEIGHT 1024 |
140 | #define MT9M111_MAX_WIDTH 1280 | 140 | #define MT9M111_MAX_WIDTH 1280 |
141 | 141 | ||
142 | struct mt9m111_context { | ||
143 | u16 read_mode; | ||
144 | u16 blanking_h; | ||
145 | u16 blanking_v; | ||
146 | u16 reducer_xzoom; | ||
147 | u16 reducer_yzoom; | ||
148 | u16 reducer_xsize; | ||
149 | u16 reducer_ysize; | ||
150 | u16 output_fmt_ctrl2; | ||
151 | u16 control; | ||
152 | }; | ||
153 | |||
154 | static struct mt9m111_context context_a = { | ||
155 | .read_mode = MT9M111_READ_MODE_A, | ||
156 | .blanking_h = MT9M111_HORIZONTAL_BLANKING_A, | ||
157 | .blanking_v = MT9M111_VERTICAL_BLANKING_A, | ||
158 | .reducer_xzoom = MT9M111_REDUCER_XZOOM_A, | ||
159 | .reducer_yzoom = MT9M111_REDUCER_YZOOM_A, | ||
160 | .reducer_xsize = MT9M111_REDUCER_XSIZE_A, | ||
161 | .reducer_ysize = MT9M111_REDUCER_YSIZE_A, | ||
162 | .output_fmt_ctrl2 = MT9M111_OUTPUT_FORMAT_CTRL2_A, | ||
163 | .control = MT9M111_CTXT_CTRL_RESTART, | ||
164 | }; | ||
165 | |||
166 | static struct mt9m111_context context_b = { | ||
167 | .read_mode = MT9M111_READ_MODE_B, | ||
168 | .blanking_h = MT9M111_HORIZONTAL_BLANKING_B, | ||
169 | .blanking_v = MT9M111_VERTICAL_BLANKING_B, | ||
170 | .reducer_xzoom = MT9M111_REDUCER_XZOOM_B, | ||
171 | .reducer_yzoom = MT9M111_REDUCER_YZOOM_B, | ||
172 | .reducer_xsize = MT9M111_REDUCER_XSIZE_B, | ||
173 | .reducer_ysize = MT9M111_REDUCER_YSIZE_B, | ||
174 | .output_fmt_ctrl2 = MT9M111_OUTPUT_FORMAT_CTRL2_B, | ||
175 | .control = MT9M111_CTXT_CTRL_RESTART | | ||
176 | MT9M111_CTXT_CTRL_DEFECTCOR_B | MT9M111_CTXT_CTRL_RESIZE_B | | ||
177 | MT9M111_CTXT_CTRL_CTRL2_B | MT9M111_CTXT_CTRL_GAMMA_B | | ||
178 | MT9M111_CTXT_CTRL_READ_MODE_B | MT9M111_CTXT_CTRL_VBLANK_SEL_B | | ||
179 | MT9M111_CTXT_CTRL_HBLANK_SEL_B, | ||
180 | }; | ||
181 | |||
142 | /* MT9M111 has only one fixed colorspace per pixelcode */ | 182 | /* MT9M111 has only one fixed colorspace per pixelcode */ |
143 | struct mt9m111_datafmt { | 183 | struct mt9m111_datafmt { |
144 | enum v4l2_mbus_pixelcode code; | 184 | enum v4l2_mbus_pixelcode code; |
145 | enum v4l2_colorspace colorspace; | 185 | enum v4l2_colorspace colorspace; |
146 | }; | 186 | }; |
147 | 187 | ||
148 | /* Find a data format by a pixel code in an array */ | ||
149 | static const struct mt9m111_datafmt *mt9m111_find_datafmt( | ||
150 | enum v4l2_mbus_pixelcode code, const struct mt9m111_datafmt *fmt, | ||
151 | int n) | ||
152 | { | ||
153 | int i; | ||
154 | for (i = 0; i < n; i++) | ||
155 | if (fmt[i].code == code) | ||
156 | return fmt + i; | ||
157 | |||
158 | return NULL; | ||
159 | } | ||
160 | |||
161 | static const struct mt9m111_datafmt mt9m111_colour_fmts[] = { | 188 | static const struct mt9m111_datafmt mt9m111_colour_fmts[] = { |
162 | {V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG}, | 189 | {V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG}, |
163 | {V4L2_MBUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG}, | 190 | {V4L2_MBUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG}, |
@@ -173,27 +200,35 @@ static const struct mt9m111_datafmt mt9m111_colour_fmts[] = { | |||
173 | {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, | 200 | {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB}, |
174 | }; | 201 | }; |
175 | 202 | ||
176 | enum mt9m111_context { | ||
177 | HIGHPOWER = 0, | ||
178 | LOWPOWER, | ||
179 | }; | ||
180 | |||
181 | struct mt9m111 { | 203 | struct mt9m111 { |
182 | struct v4l2_subdev subdev; | 204 | struct v4l2_subdev subdev; |
183 | struct v4l2_ctrl_handler hdl; | 205 | struct v4l2_ctrl_handler hdl; |
184 | struct v4l2_ctrl *gain; | 206 | struct v4l2_ctrl *gain; |
185 | int model; /* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code | 207 | int model; /* V4L2_IDENT_MT9M111 or V4L2_IDENT_MT9M112 code |
186 | * from v4l2-chip-ident.h */ | 208 | * from v4l2-chip-ident.h */ |
187 | enum mt9m111_context context; | 209 | struct mt9m111_context *ctx; |
188 | struct v4l2_rect rect; | 210 | struct v4l2_rect rect; /* cropping rectangle */ |
211 | int width; /* output */ | ||
212 | int height; /* sizes */ | ||
189 | struct mutex power_lock; /* lock to protect power_count */ | 213 | struct mutex power_lock; /* lock to protect power_count */ |
190 | int power_count; | 214 | int power_count; |
191 | const struct mt9m111_datafmt *fmt; | 215 | const struct mt9m111_datafmt *fmt; |
192 | int lastpage; /* PageMap cache value */ | 216 | int lastpage; /* PageMap cache value */ |
193 | unsigned char datawidth; | 217 | unsigned char datawidth; |
194 | unsigned int powered:1; | ||
195 | }; | 218 | }; |
196 | 219 | ||
220 | /* Find a data format by a pixel code */ | ||
221 | static const struct mt9m111_datafmt *mt9m111_find_datafmt(struct mt9m111 *mt9m111, | ||
222 | enum v4l2_mbus_pixelcode code) | ||
223 | { | ||
224 | int i; | ||
225 | for (i = 0; i < ARRAY_SIZE(mt9m111_colour_fmts); i++) | ||
226 | if (mt9m111_colour_fmts[i].code == code) | ||
227 | return mt9m111_colour_fmts + i; | ||
228 | |||
229 | return mt9m111->fmt; | ||
230 | } | ||
231 | |||
197 | static struct mt9m111 *to_mt9m111(const struct i2c_client *client) | 232 | static struct mt9m111 *to_mt9m111(const struct i2c_client *client) |
198 | { | 233 | { |
199 | return container_of(i2c_get_clientdata(client), struct mt9m111, subdev); | 234 | return container_of(i2c_get_clientdata(client), struct mt9m111, subdev); |
@@ -211,7 +246,7 @@ static int reg_page_map_set(struct i2c_client *client, const u16 reg) | |||
211 | if (page > 2) | 246 | if (page > 2) |
212 | return -EINVAL; | 247 | return -EINVAL; |
213 | 248 | ||
214 | ret = i2c_smbus_write_word_data(client, MT9M111_PAGE_MAP, swab16(page)); | 249 | ret = i2c_smbus_write_word_swapped(client, MT9M111_PAGE_MAP, page); |
215 | if (!ret) | 250 | if (!ret) |
216 | mt9m111->lastpage = page; | 251 | mt9m111->lastpage = page; |
217 | return ret; | 252 | return ret; |
@@ -223,7 +258,7 @@ static int mt9m111_reg_read(struct i2c_client *client, const u16 reg) | |||
223 | 258 | ||
224 | ret = reg_page_map_set(client, reg); | 259 | ret = reg_page_map_set(client, reg); |
225 | if (!ret) | 260 | if (!ret) |
226 | ret = swab16(i2c_smbus_read_word_data(client, reg & 0xff)); | 261 | ret = i2c_smbus_read_word_swapped(client, reg & 0xff); |
227 | 262 | ||
228 | dev_dbg(&client->dev, "read reg.%03x -> %04x\n", reg, ret); | 263 | dev_dbg(&client->dev, "read reg.%03x -> %04x\n", reg, ret); |
229 | return ret; | 264 | return ret; |
@@ -236,8 +271,7 @@ static int mt9m111_reg_write(struct i2c_client *client, const u16 reg, | |||
236 | 271 | ||
237 | ret = reg_page_map_set(client, reg); | 272 | ret = reg_page_map_set(client, reg); |
238 | if (!ret) | 273 | if (!ret) |
239 | ret = i2c_smbus_write_word_data(client, reg & 0xff, | 274 | ret = i2c_smbus_write_word_swapped(client, reg & 0xff, data); |
240 | swab16(data)); | ||
241 | dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); | 275 | dev_dbg(&client->dev, "write reg.%03x = %04x -> %d\n", reg, data, ret); |
242 | return ret; | 276 | return ret; |
243 | } | 277 | } |
@@ -276,76 +310,63 @@ static int mt9m111_reg_mask(struct i2c_client *client, const u16 reg, | |||
276 | } | 310 | } |
277 | 311 | ||
278 | static int mt9m111_set_context(struct mt9m111 *mt9m111, | 312 | static int mt9m111_set_context(struct mt9m111 *mt9m111, |
279 | enum mt9m111_context ctxt) | 313 | struct mt9m111_context *ctx) |
280 | { | 314 | { |
281 | struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); | 315 | struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); |
282 | int valB = MT9M111_CTXT_CTRL_RESTART | MT9M111_CTXT_CTRL_DEFECTCOR_B | 316 | return reg_write(CONTEXT_CONTROL, ctx->control); |
283 | | MT9M111_CTXT_CTRL_RESIZE_B | MT9M111_CTXT_CTRL_CTRL2_B | ||
284 | | MT9M111_CTXT_CTRL_GAMMA_B | MT9M111_CTXT_CTRL_READ_MODE_B | ||
285 | | MT9M111_CTXT_CTRL_VBLANK_SEL_B | ||
286 | | MT9M111_CTXT_CTRL_HBLANK_SEL_B; | ||
287 | int valA = MT9M111_CTXT_CTRL_RESTART; | ||
288 | |||
289 | if (ctxt == HIGHPOWER) | ||
290 | return reg_write(CONTEXT_CONTROL, valB); | ||
291 | else | ||
292 | return reg_write(CONTEXT_CONTROL, valA); | ||
293 | } | 317 | } |
294 | 318 | ||
295 | static int mt9m111_setup_rect(struct mt9m111 *mt9m111, | 319 | static int mt9m111_setup_rect_ctx(struct mt9m111 *mt9m111, |
296 | struct v4l2_rect *rect) | 320 | struct mt9m111_context *ctx, struct v4l2_rect *rect, |
321 | unsigned int width, unsigned int height) | ||
297 | { | 322 | { |
298 | struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); | 323 | struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); |
299 | int ret, is_raw_format; | 324 | int ret = mt9m111_reg_write(client, ctx->reducer_xzoom, rect->width); |
300 | int width = rect->width; | 325 | if (!ret) |
301 | int height = rect->height; | 326 | ret = mt9m111_reg_write(client, ctx->reducer_yzoom, rect->height); |
327 | if (!ret) | ||
328 | ret = mt9m111_reg_write(client, ctx->reducer_xsize, width); | ||
329 | if (!ret) | ||
330 | ret = mt9m111_reg_write(client, ctx->reducer_ysize, height); | ||
331 | return ret; | ||
332 | } | ||
302 | 333 | ||
303 | if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 || | 334 | static int mt9m111_setup_geometry(struct mt9m111 *mt9m111, struct v4l2_rect *rect, |
304 | mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) | 335 | int width, int height, enum v4l2_mbus_pixelcode code) |
305 | is_raw_format = 1; | 336 | { |
306 | else | 337 | struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); |
307 | is_raw_format = 0; | 338 | int ret; |
308 | 339 | ||
309 | ret = reg_write(COLUMN_START, rect->left); | 340 | ret = reg_write(COLUMN_START, rect->left); |
310 | if (!ret) | 341 | if (!ret) |
311 | ret = reg_write(ROW_START, rect->top); | 342 | ret = reg_write(ROW_START, rect->top); |
312 | 343 | ||
313 | if (is_raw_format) { | 344 | if (!ret) |
314 | if (!ret) | 345 | ret = reg_write(WINDOW_WIDTH, rect->width); |
315 | ret = reg_write(WINDOW_WIDTH, width); | 346 | if (!ret) |
316 | if (!ret) | 347 | ret = reg_write(WINDOW_HEIGHT, rect->height); |
317 | ret = reg_write(WINDOW_HEIGHT, height); | 348 | |
318 | } else { | 349 | if (code != V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) { |
319 | if (!ret) | 350 | /* IFP in use, down-scaling possible */ |
320 | ret = reg_write(REDUCER_XZOOM_B, MT9M111_MAX_WIDTH); | ||
321 | if (!ret) | ||
322 | ret = reg_write(REDUCER_YZOOM_B, MT9M111_MAX_HEIGHT); | ||
323 | if (!ret) | ||
324 | ret = reg_write(REDUCER_XSIZE_B, width); | ||
325 | if (!ret) | ||
326 | ret = reg_write(REDUCER_YSIZE_B, height); | ||
327 | if (!ret) | ||
328 | ret = reg_write(REDUCER_XZOOM_A, MT9M111_MAX_WIDTH); | ||
329 | if (!ret) | ||
330 | ret = reg_write(REDUCER_YZOOM_A, MT9M111_MAX_HEIGHT); | ||
331 | if (!ret) | 351 | if (!ret) |
332 | ret = reg_write(REDUCER_XSIZE_A, width); | 352 | ret = mt9m111_setup_rect_ctx(mt9m111, &context_b, |
353 | rect, width, height); | ||
333 | if (!ret) | 354 | if (!ret) |
334 | ret = reg_write(REDUCER_YSIZE_A, height); | 355 | ret = mt9m111_setup_rect_ctx(mt9m111, &context_a, |
356 | rect, width, height); | ||
335 | } | 357 | } |
336 | 358 | ||
359 | dev_dbg(&client->dev, "%s(%x): %ux%u@%u:%u -> %ux%u = %d\n", | ||
360 | __func__, code, rect->width, rect->height, rect->left, rect->top, | ||
361 | width, height, ret); | ||
362 | |||
337 | return ret; | 363 | return ret; |
338 | } | 364 | } |
339 | 365 | ||
340 | static int mt9m111_enable(struct mt9m111 *mt9m111) | 366 | static int mt9m111_enable(struct mt9m111 *mt9m111) |
341 | { | 367 | { |
342 | struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); | 368 | struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); |
343 | int ret; | 369 | return reg_write(RESET, MT9M111_RESET_CHIP_ENABLE); |
344 | |||
345 | ret = reg_set(RESET, MT9M111_RESET_CHIP_ENABLE); | ||
346 | if (!ret) | ||
347 | mt9m111->powered = 1; | ||
348 | return ret; | ||
349 | } | 370 | } |
350 | 371 | ||
351 | static int mt9m111_reset(struct mt9m111 *mt9m111) | 372 | static int mt9m111_reset(struct mt9m111 *mt9m111) |
@@ -363,43 +384,41 @@ static int mt9m111_reset(struct mt9m111 *mt9m111) | |||
363 | return ret; | 384 | return ret; |
364 | } | 385 | } |
365 | 386 | ||
366 | static int mt9m111_make_rect(struct mt9m111 *mt9m111, | 387 | static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) |
367 | struct v4l2_rect *rect) | ||
368 | { | 388 | { |
389 | struct v4l2_rect rect = a->c; | ||
390 | struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); | ||
391 | int width, height; | ||
392 | int ret; | ||
393 | |||
394 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
395 | return -EINVAL; | ||
396 | |||
369 | if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 || | 397 | if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 || |
370 | mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) { | 398 | mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) { |
371 | /* Bayer format - even size lengths */ | 399 | /* Bayer format - even size lengths */ |
372 | rect->width = ALIGN(rect->width, 2); | 400 | rect.width = ALIGN(rect.width, 2); |
373 | rect->height = ALIGN(rect->height, 2); | 401 | rect.height = ALIGN(rect.height, 2); |
374 | /* Let the user play with the starting pixel */ | 402 | /* Let the user play with the starting pixel */ |
375 | } | 403 | } |
376 | 404 | ||
377 | /* FIXME: the datasheet doesn't specify minimum sizes */ | 405 | /* FIXME: the datasheet doesn't specify minimum sizes */ |
378 | soc_camera_limit_side(&rect->left, &rect->width, | 406 | soc_camera_limit_side(&rect.left, &rect.width, |
379 | MT9M111_MIN_DARK_COLS, 2, MT9M111_MAX_WIDTH); | 407 | MT9M111_MIN_DARK_COLS, 2, MT9M111_MAX_WIDTH); |
380 | 408 | ||
381 | soc_camera_limit_side(&rect->top, &rect->height, | 409 | soc_camera_limit_side(&rect.top, &rect.height, |
382 | MT9M111_MIN_DARK_ROWS, 2, MT9M111_MAX_HEIGHT); | 410 | MT9M111_MIN_DARK_ROWS, 2, MT9M111_MAX_HEIGHT); |
383 | 411 | ||
384 | return mt9m111_setup_rect(mt9m111, rect); | 412 | width = min(mt9m111->width, rect.width); |
385 | } | 413 | height = min(mt9m111->height, rect.height); |
386 | |||
387 | static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a) | ||
388 | { | ||
389 | struct v4l2_rect rect = a->c; | ||
390 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
391 | struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); | ||
392 | int ret; | ||
393 | |||
394 | dev_dbg(&client->dev, "%s left=%d, top=%d, width=%d, height=%d\n", | ||
395 | __func__, rect.left, rect.top, rect.width, rect.height); | ||
396 | 414 | ||
397 | if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 415 | ret = mt9m111_setup_geometry(mt9m111, &rect, width, height, mt9m111->fmt->code); |
398 | return -EINVAL; | 416 | if (!ret) { |
399 | |||
400 | ret = mt9m111_make_rect(mt9m111, &rect); | ||
401 | if (!ret) | ||
402 | mt9m111->rect = rect; | 417 | mt9m111->rect = rect; |
418 | mt9m111->width = width; | ||
419 | mt9m111->height = height; | ||
420 | } | ||
421 | |||
403 | return ret; | 422 | return ret; |
404 | } | 423 | } |
405 | 424 | ||
@@ -434,8 +453,8 @@ static int mt9m111_g_fmt(struct v4l2_subdev *sd, | |||
434 | { | 453 | { |
435 | struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); | 454 | struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); |
436 | 455 | ||
437 | mf->width = mt9m111->rect.width; | 456 | mf->width = mt9m111->width; |
438 | mf->height = mt9m111->rect.height; | 457 | mf->height = mt9m111->height; |
439 | mf->code = mt9m111->fmt->code; | 458 | mf->code = mt9m111->fmt->code; |
440 | mf->colorspace = mt9m111->fmt->colorspace; | 459 | mf->colorspace = mt9m111->fmt->colorspace; |
441 | mf->field = V4L2_FIELD_NONE; | 460 | mf->field = V4L2_FIELD_NONE; |
@@ -504,46 +523,11 @@ static int mt9m111_set_pixfmt(struct mt9m111 *mt9m111, | |||
504 | return -EINVAL; | 523 | return -EINVAL; |
505 | } | 524 | } |
506 | 525 | ||
507 | ret = reg_mask(OUTPUT_FORMAT_CTRL2_A, data_outfmt2, | 526 | ret = mt9m111_reg_mask(client, context_a.output_fmt_ctrl2, |
508 | mask_outfmt2); | 527 | data_outfmt2, mask_outfmt2); |
509 | if (!ret) | 528 | if (!ret) |
510 | ret = reg_mask(OUTPUT_FORMAT_CTRL2_B, data_outfmt2, | 529 | ret = mt9m111_reg_mask(client, context_b.output_fmt_ctrl2, |
511 | mask_outfmt2); | 530 | data_outfmt2, mask_outfmt2); |
512 | |||
513 | return ret; | ||
514 | } | ||
515 | |||
516 | static int mt9m111_s_fmt(struct v4l2_subdev *sd, | ||
517 | struct v4l2_mbus_framefmt *mf) | ||
518 | { | ||
519 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
520 | const struct mt9m111_datafmt *fmt; | ||
521 | struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); | ||
522 | struct v4l2_rect rect = { | ||
523 | .left = mt9m111->rect.left, | ||
524 | .top = mt9m111->rect.top, | ||
525 | .width = mf->width, | ||
526 | .height = mf->height, | ||
527 | }; | ||
528 | int ret; | ||
529 | |||
530 | fmt = mt9m111_find_datafmt(mf->code, mt9m111_colour_fmts, | ||
531 | ARRAY_SIZE(mt9m111_colour_fmts)); | ||
532 | if (!fmt) | ||
533 | return -EINVAL; | ||
534 | |||
535 | dev_dbg(&client->dev, | ||
536 | "%s code=%x left=%d, top=%d, width=%d, height=%d\n", __func__, | ||
537 | mf->code, rect.left, rect.top, rect.width, rect.height); | ||
538 | |||
539 | ret = mt9m111_make_rect(mt9m111, &rect); | ||
540 | if (!ret) | ||
541 | ret = mt9m111_set_pixfmt(mt9m111, mf->code); | ||
542 | if (!ret) { | ||
543 | mt9m111->rect = rect; | ||
544 | mt9m111->fmt = fmt; | ||
545 | mf->colorspace = fmt->colorspace; | ||
546 | } | ||
547 | 531 | ||
548 | return ret; | 532 | return ret; |
549 | } | 533 | } |
@@ -551,42 +535,71 @@ static int mt9m111_s_fmt(struct v4l2_subdev *sd, | |||
551 | static int mt9m111_try_fmt(struct v4l2_subdev *sd, | 535 | static int mt9m111_try_fmt(struct v4l2_subdev *sd, |
552 | struct v4l2_mbus_framefmt *mf) | 536 | struct v4l2_mbus_framefmt *mf) |
553 | { | 537 | { |
538 | struct i2c_client *client = v4l2_get_subdevdata(sd); | ||
554 | struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); | 539 | struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); |
555 | const struct mt9m111_datafmt *fmt; | 540 | const struct mt9m111_datafmt *fmt; |
556 | bool bayer = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 || | 541 | struct v4l2_rect *rect = &mt9m111->rect; |
557 | mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE; | 542 | bool bayer; |
558 | 543 | ||
559 | fmt = mt9m111_find_datafmt(mf->code, mt9m111_colour_fmts, | 544 | fmt = mt9m111_find_datafmt(mt9m111, mf->code); |
560 | ARRAY_SIZE(mt9m111_colour_fmts)); | 545 | |
561 | if (!fmt) { | 546 | bayer = fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 || |
562 | fmt = mt9m111->fmt; | 547 | fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE; |
563 | mf->code = fmt->code; | ||
564 | } | ||
565 | 548 | ||
566 | /* | 549 | /* |
567 | * With Bayer format enforce even side lengths, but let the user play | 550 | * With Bayer format enforce even side lengths, but let the user play |
568 | * with the starting pixel | 551 | * with the starting pixel |
569 | */ | 552 | */ |
553 | if (bayer) { | ||
554 | rect->width = ALIGN(rect->width, 2); | ||
555 | rect->height = ALIGN(rect->height, 2); | ||
556 | } | ||
570 | 557 | ||
571 | if (mf->height > MT9M111_MAX_HEIGHT) | 558 | if (fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) { |
572 | mf->height = MT9M111_MAX_HEIGHT; | 559 | /* IFP bypass mode, no scaling */ |
573 | else if (mf->height < 2) | 560 | mf->width = rect->width; |
574 | mf->height = 2; | 561 | mf->height = rect->height; |
575 | else if (bayer) | 562 | } else { |
576 | mf->height = ALIGN(mf->height, 2); | 563 | /* No upscaling */ |
564 | if (mf->width > rect->width) | ||
565 | mf->width = rect->width; | ||
566 | if (mf->height > rect->height) | ||
567 | mf->height = rect->height; | ||
568 | } | ||
577 | 569 | ||
578 | if (mf->width > MT9M111_MAX_WIDTH) | 570 | dev_dbg(&client->dev, "%s(): %ux%u, code=%x\n", __func__, |
579 | mf->width = MT9M111_MAX_WIDTH; | 571 | mf->width, mf->height, fmt->code); |
580 | else if (mf->width < 2) | ||
581 | mf->width = 2; | ||
582 | else if (bayer) | ||
583 | mf->width = ALIGN(mf->width, 2); | ||
584 | 572 | ||
573 | mf->code = fmt->code; | ||
585 | mf->colorspace = fmt->colorspace; | 574 | mf->colorspace = fmt->colorspace; |
586 | 575 | ||
587 | return 0; | 576 | return 0; |
588 | } | 577 | } |
589 | 578 | ||
579 | static int mt9m111_s_fmt(struct v4l2_subdev *sd, | ||
580 | struct v4l2_mbus_framefmt *mf) | ||
581 | { | ||
582 | const struct mt9m111_datafmt *fmt; | ||
583 | struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev); | ||
584 | struct v4l2_rect *rect = &mt9m111->rect; | ||
585 | int ret; | ||
586 | |||
587 | mt9m111_try_fmt(sd, mf); | ||
588 | fmt = mt9m111_find_datafmt(mt9m111, mf->code); | ||
589 | /* try_fmt() guarantees fmt != NULL && fmt->code == mf->code */ | ||
590 | |||
591 | ret = mt9m111_setup_geometry(mt9m111, rect, mf->width, mf->height, mf->code); | ||
592 | if (!ret) | ||
593 | ret = mt9m111_set_pixfmt(mt9m111, mf->code); | ||
594 | if (!ret) { | ||
595 | mt9m111->width = mf->width; | ||
596 | mt9m111->height = mf->height; | ||
597 | mt9m111->fmt = fmt; | ||
598 | } | ||
599 | |||
600 | return ret; | ||
601 | } | ||
602 | |||
590 | static int mt9m111_g_chip_ident(struct v4l2_subdev *sd, | 603 | static int mt9m111_g_chip_ident(struct v4l2_subdev *sd, |
591 | struct v4l2_dbg_chip_ident *id) | 604 | struct v4l2_dbg_chip_ident *id) |
592 | { | 605 | { |
@@ -650,17 +663,10 @@ static int mt9m111_set_flip(struct mt9m111 *mt9m111, int flip, int mask) | |||
650 | struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); | 663 | struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); |
651 | int ret; | 664 | int ret; |
652 | 665 | ||
653 | if (mt9m111->context == HIGHPOWER) { | 666 | if (flip) |
654 | if (flip) | 667 | ret = mt9m111_reg_set(client, mt9m111->ctx->read_mode, mask); |
655 | ret = reg_set(READ_MODE_B, mask); | 668 | else |
656 | else | 669 | ret = mt9m111_reg_clear(client, mt9m111->ctx->read_mode, mask); |
657 | ret = reg_clear(READ_MODE_B, mask); | ||
658 | } else { | ||
659 | if (flip) | ||
660 | ret = reg_set(READ_MODE_A, mask); | ||
661 | else | ||
662 | ret = reg_clear(READ_MODE_A, mask); | ||
663 | } | ||
664 | 670 | ||
665 | return ret; | 671 | return ret; |
666 | } | 672 | } |
@@ -738,30 +744,39 @@ static int mt9m111_s_ctrl(struct v4l2_ctrl *ctrl) | |||
738 | 744 | ||
739 | static int mt9m111_suspend(struct mt9m111 *mt9m111) | 745 | static int mt9m111_suspend(struct mt9m111 *mt9m111) |
740 | { | 746 | { |
747 | struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); | ||
748 | int ret; | ||
749 | |||
741 | v4l2_ctrl_s_ctrl(mt9m111->gain, mt9m111_get_global_gain(mt9m111)); | 750 | v4l2_ctrl_s_ctrl(mt9m111->gain, mt9m111_get_global_gain(mt9m111)); |
742 | 751 | ||
743 | return 0; | 752 | ret = reg_set(RESET, MT9M111_RESET_RESET_MODE); |
753 | if (!ret) | ||
754 | ret = reg_set(RESET, MT9M111_RESET_RESET_SOC | | ||
755 | MT9M111_RESET_OUTPUT_DISABLE | | ||
756 | MT9M111_RESET_ANALOG_STANDBY); | ||
757 | if (!ret) | ||
758 | ret = reg_clear(RESET, MT9M111_RESET_CHIP_ENABLE); | ||
759 | |||
760 | return ret; | ||
744 | } | 761 | } |
745 | 762 | ||
746 | static void mt9m111_restore_state(struct mt9m111 *mt9m111) | 763 | static void mt9m111_restore_state(struct mt9m111 *mt9m111) |
747 | { | 764 | { |
748 | mt9m111_set_context(mt9m111, mt9m111->context); | 765 | mt9m111_set_context(mt9m111, mt9m111->ctx); |
749 | mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code); | 766 | mt9m111_set_pixfmt(mt9m111, mt9m111->fmt->code); |
750 | mt9m111_setup_rect(mt9m111, &mt9m111->rect); | 767 | mt9m111_setup_geometry(mt9m111, &mt9m111->rect, |
768 | mt9m111->width, mt9m111->height, mt9m111->fmt->code); | ||
751 | v4l2_ctrl_handler_setup(&mt9m111->hdl); | 769 | v4l2_ctrl_handler_setup(&mt9m111->hdl); |
752 | } | 770 | } |
753 | 771 | ||
754 | static int mt9m111_resume(struct mt9m111 *mt9m111) | 772 | static int mt9m111_resume(struct mt9m111 *mt9m111) |
755 | { | 773 | { |
756 | int ret = 0; | 774 | int ret = mt9m111_enable(mt9m111); |
775 | if (!ret) | ||
776 | ret = mt9m111_reset(mt9m111); | ||
777 | if (!ret) | ||
778 | mt9m111_restore_state(mt9m111); | ||
757 | 779 | ||
758 | if (mt9m111->powered) { | ||
759 | ret = mt9m111_enable(mt9m111); | ||
760 | if (!ret) | ||
761 | ret = mt9m111_reset(mt9m111); | ||
762 | if (!ret) | ||
763 | mt9m111_restore_state(mt9m111); | ||
764 | } | ||
765 | return ret; | 780 | return ret; |
766 | } | 781 | } |
767 | 782 | ||
@@ -770,12 +785,13 @@ static int mt9m111_init(struct mt9m111 *mt9m111) | |||
770 | struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); | 785 | struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev); |
771 | int ret; | 786 | int ret; |
772 | 787 | ||
773 | mt9m111->context = HIGHPOWER; | 788 | /* Default HIGHPOWER context */ |
789 | mt9m111->ctx = &context_b; | ||
774 | ret = mt9m111_enable(mt9m111); | 790 | ret = mt9m111_enable(mt9m111); |
775 | if (!ret) | 791 | if (!ret) |
776 | ret = mt9m111_reset(mt9m111); | 792 | ret = mt9m111_reset(mt9m111); |
777 | if (!ret) | 793 | if (!ret) |
778 | ret = mt9m111_set_context(mt9m111, mt9m111->context); | 794 | ret = mt9m111_set_context(mt9m111, mt9m111->ctx); |
779 | if (ret) | 795 | if (ret) |
780 | dev_err(&client->dev, "mt9m111 init failed: %d\n", ret); | 796 | dev_err(&client->dev, "mt9m111 init failed: %d\n", ret); |
781 | return ret; | 797 | return ret; |
diff --git a/drivers/media/video/mt9p031.c b/drivers/media/video/mt9p031.c index 73c068993f05..93c3ec7426e8 100644 --- a/drivers/media/video/mt9p031.c +++ b/drivers/media/video/mt9p031.c | |||
@@ -132,13 +132,12 @@ static struct mt9p031 *to_mt9p031(struct v4l2_subdev *sd) | |||
132 | 132 | ||
133 | static int mt9p031_read(struct i2c_client *client, u8 reg) | 133 | static int mt9p031_read(struct i2c_client *client, u8 reg) |
134 | { | 134 | { |
135 | s32 data = i2c_smbus_read_word_data(client, reg); | 135 | return i2c_smbus_read_word_swapped(client, reg); |
136 | return data < 0 ? data : be16_to_cpu(data); | ||
137 | } | 136 | } |
138 | 137 | ||
139 | static int mt9p031_write(struct i2c_client *client, u8 reg, u16 data) | 138 | static int mt9p031_write(struct i2c_client *client, u8 reg, u16 data) |
140 | { | 139 | { |
141 | return i2c_smbus_write_word_data(client, reg, cpu_to_be16(data)); | 140 | return i2c_smbus_write_word_swapped(client, reg, data); |
142 | } | 141 | } |
143 | 142 | ||
144 | static int mt9p031_set_output_control(struct mt9p031 *mt9p031, u16 clear, | 143 | static int mt9p031_set_output_control(struct mt9p031 *mt9p031, u16 clear, |
diff --git a/drivers/media/video/mt9t001.c b/drivers/media/video/mt9t001.c index 08074b8a2736..cd81d04a529e 100644 --- a/drivers/media/video/mt9t001.c +++ b/drivers/media/video/mt9t001.c | |||
@@ -133,13 +133,12 @@ static inline struct mt9t001 *to_mt9t001(struct v4l2_subdev *sd) | |||
133 | 133 | ||
134 | static int mt9t001_read(struct i2c_client *client, u8 reg) | 134 | static int mt9t001_read(struct i2c_client *client, u8 reg) |
135 | { | 135 | { |
136 | s32 data = i2c_smbus_read_word_data(client, reg); | 136 | return i2c_smbus_read_word_swapped(client, reg); |
137 | return data < 0 ? data : be16_to_cpu(data); | ||
138 | } | 137 | } |
139 | 138 | ||
140 | static int mt9t001_write(struct i2c_client *client, u8 reg, u16 data) | 139 | static int mt9t001_write(struct i2c_client *client, u8 reg, u16 data) |
141 | { | 140 | { |
142 | return i2c_smbus_write_word_data(client, reg, cpu_to_be16(data)); | 141 | return i2c_smbus_write_word_swapped(client, reg, data); |
143 | } | 142 | } |
144 | 143 | ||
145 | static int mt9t001_set_output_control(struct mt9t001 *mt9t001, u16 clear, | 144 | static int mt9t001_set_output_control(struct mt9t001 *mt9t001, u16 clear, |
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 0e78477452ff..84add1aef139 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c | |||
@@ -90,14 +90,13 @@ static struct mt9t031 *to_mt9t031(const struct i2c_client *client) | |||
90 | 90 | ||
91 | static int reg_read(struct i2c_client *client, const u8 reg) | 91 | static int reg_read(struct i2c_client *client, const u8 reg) |
92 | { | 92 | { |
93 | s32 data = i2c_smbus_read_word_data(client, reg); | 93 | return i2c_smbus_read_word_swapped(client, reg); |
94 | return data < 0 ? data : swab16(data); | ||
95 | } | 94 | } |
96 | 95 | ||
97 | static int reg_write(struct i2c_client *client, const u8 reg, | 96 | static int reg_write(struct i2c_client *client, const u8 reg, |
98 | const u16 data) | 97 | const u16 data) |
99 | { | 98 | { |
100 | return i2c_smbus_write_word_data(client, reg, swab16(data)); | 99 | return i2c_smbus_write_word_swapped(client, reg, data); |
101 | } | 100 | } |
102 | 101 | ||
103 | static int reg_set(struct i2c_client *client, const u8 reg, | 102 | static int reg_set(struct i2c_client *client, const u8 reg, |
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 690ee0d42eeb..944940758fa3 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c | |||
@@ -130,14 +130,13 @@ static struct mt9v022 *to_mt9v022(const struct i2c_client *client) | |||
130 | 130 | ||
131 | static int reg_read(struct i2c_client *client, const u8 reg) | 131 | static int reg_read(struct i2c_client *client, const u8 reg) |
132 | { | 132 | { |
133 | s32 data = i2c_smbus_read_word_data(client, reg); | 133 | return i2c_smbus_read_word_swapped(client, reg); |
134 | return data < 0 ? data : swab16(data); | ||
135 | } | 134 | } |
136 | 135 | ||
137 | static int reg_write(struct i2c_client *client, const u8 reg, | 136 | static int reg_write(struct i2c_client *client, const u8 reg, |
138 | const u16 data) | 137 | const u16 data) |
139 | { | 138 | { |
140 | return i2c_smbus_write_word_data(client, reg, swab16(data)); | 139 | return i2c_smbus_write_word_swapped(client, reg, data); |
141 | } | 140 | } |
142 | 141 | ||
143 | static int reg_set(struct i2c_client *client, const u8 reg, | 142 | static int reg_set(struct i2c_client *client, const u8 reg, |
diff --git a/drivers/media/video/mt9v032.c b/drivers/media/video/mt9v032.c index f080c162123f..d90b982cc218 100644 --- a/drivers/media/video/mt9v032.c +++ b/drivers/media/video/mt9v032.c | |||
@@ -139,10 +139,10 @@ static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd) | |||
139 | 139 | ||
140 | static int mt9v032_read(struct i2c_client *client, const u8 reg) | 140 | static int mt9v032_read(struct i2c_client *client, const u8 reg) |
141 | { | 141 | { |
142 | s32 data = i2c_smbus_read_word_data(client, reg); | 142 | s32 data = i2c_smbus_read_word_swapped(client, reg); |
143 | dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__, | 143 | dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__, |
144 | swab16(data), reg); | 144 | data, reg); |
145 | return data < 0 ? data : swab16(data); | 145 | return data; |
146 | } | 146 | } |
147 | 147 | ||
148 | static int mt9v032_write(struct i2c_client *client, const u8 reg, | 148 | static int mt9v032_write(struct i2c_client *client, const u8 reg, |
@@ -150,7 +150,7 @@ static int mt9v032_write(struct i2c_client *client, const u8 reg, | |||
150 | { | 150 | { |
151 | dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__, | 151 | dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__, |
152 | data, reg); | 152 | data, reg); |
153 | return i2c_smbus_write_word_data(client, reg, swab16(data)); | 153 | return i2c_smbus_write_word_swapped(client, reg, data); |
154 | } | 154 | } |
155 | 155 | ||
156 | static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set) | 156 | static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set) |
diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index 18e94c7d2be8..055d11ddb038 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c | |||
@@ -487,7 +487,7 @@ static int mx1_camera_set_crop(struct soc_camera_device *icd, | |||
487 | return v4l2_subdev_call(sd, video, s_crop, a); | 487 | return v4l2_subdev_call(sd, video, s_crop, a); |
488 | } | 488 | } |
489 | 489 | ||
490 | static int mx1_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | 490 | static int mx1_camera_set_bus_param(struct soc_camera_device *icd) |
491 | { | 491 | { |
492 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 492 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
493 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 493 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
diff --git a/drivers/media/video/mx2_camera.c b/drivers/media/video/mx2_camera.c index a803d9ea8fd6..04aab0c538aa 100644 --- a/drivers/media/video/mx2_camera.c +++ b/drivers/media/video/mx2_camera.c | |||
@@ -210,6 +210,22 @@ | |||
210 | 210 | ||
211 | #define MAX_VIDEO_MEM 16 | 211 | #define MAX_VIDEO_MEM 16 |
212 | 212 | ||
213 | struct mx2_prp_cfg { | ||
214 | int channel; | ||
215 | u32 in_fmt; | ||
216 | u32 out_fmt; | ||
217 | u32 src_pixel; | ||
218 | u32 ch1_pixel; | ||
219 | u32 irq_flags; | ||
220 | }; | ||
221 | |||
222 | /* prp configuration for a client-host fmt pair */ | ||
223 | struct mx2_fmt_cfg { | ||
224 | enum v4l2_mbus_pixelcode in_fmt; | ||
225 | u32 out_fmt; | ||
226 | struct mx2_prp_cfg cfg; | ||
227 | }; | ||
228 | |||
213 | struct mx2_camera_dev { | 229 | struct mx2_camera_dev { |
214 | struct device *dev; | 230 | struct device *dev; |
215 | struct soc_camera_host soc_host; | 231 | struct soc_camera_host soc_host; |
@@ -241,6 +257,8 @@ struct mx2_camera_dev { | |||
241 | void *discard_buffer; | 257 | void *discard_buffer; |
242 | dma_addr_t discard_buffer_dma; | 258 | dma_addr_t discard_buffer_dma; |
243 | size_t discard_size; | 259 | size_t discard_size; |
260 | struct mx2_fmt_cfg *emma_prp; | ||
261 | u32 frame_count; | ||
244 | }; | 262 | }; |
245 | 263 | ||
246 | /* buffer for one video frame */ | 264 | /* buffer for one video frame */ |
@@ -253,6 +271,59 @@ struct mx2_buffer { | |||
253 | int bufnum; | 271 | int bufnum; |
254 | }; | 272 | }; |
255 | 273 | ||
274 | static struct mx2_fmt_cfg mx27_emma_prp_table[] = { | ||
275 | /* | ||
276 | * This is a generic configuration which is valid for most | ||
277 | * prp input-output format combinations. | ||
278 | * We set the incomming and outgoing pixelformat to a | ||
279 | * 16 Bit wide format and adjust the bytesperline | ||
280 | * accordingly. With this configuration the inputdata | ||
281 | * will not be changed by the emma and could be any type | ||
282 | * of 16 Bit Pixelformat. | ||
283 | */ | ||
284 | { | ||
285 | .in_fmt = 0, | ||
286 | .out_fmt = 0, | ||
287 | .cfg = { | ||
288 | .channel = 1, | ||
289 | .in_fmt = PRP_CNTL_DATA_IN_RGB16, | ||
290 | .out_fmt = PRP_CNTL_CH1_OUT_RGB16, | ||
291 | .src_pixel = 0x2ca00565, /* RGB565 */ | ||
292 | .ch1_pixel = 0x2ca00565, /* RGB565 */ | ||
293 | .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH1WERR | | ||
294 | PRP_INTR_CH1FC | PRP_INTR_LBOVF, | ||
295 | } | ||
296 | }, | ||
297 | { | ||
298 | .in_fmt = V4L2_MBUS_FMT_YUYV8_2X8, | ||
299 | .out_fmt = V4L2_PIX_FMT_YUV420, | ||
300 | .cfg = { | ||
301 | .channel = 2, | ||
302 | .in_fmt = PRP_CNTL_DATA_IN_YUV422, | ||
303 | .out_fmt = PRP_CNTL_CH2_OUT_YUV420, | ||
304 | .src_pixel = 0x22000888, /* YUV422 (YUYV) */ | ||
305 | .irq_flags = PRP_INTR_RDERR | PRP_INTR_CH2WERR | | ||
306 | PRP_INTR_CH2FC | PRP_INTR_LBOVF | | ||
307 | PRP_INTR_CH2OVF, | ||
308 | } | ||
309 | }, | ||
310 | }; | ||
311 | |||
312 | static struct mx2_fmt_cfg *mx27_emma_prp_get_format( | ||
313 | enum v4l2_mbus_pixelcode in_fmt, | ||
314 | u32 out_fmt) | ||
315 | { | ||
316 | int i; | ||
317 | |||
318 | for (i = 1; i < ARRAY_SIZE(mx27_emma_prp_table); i++) | ||
319 | if ((mx27_emma_prp_table[i].in_fmt == in_fmt) && | ||
320 | (mx27_emma_prp_table[i].out_fmt == out_fmt)) { | ||
321 | return &mx27_emma_prp_table[i]; | ||
322 | } | ||
323 | /* If no match return the most generic configuration */ | ||
324 | return &mx27_emma_prp_table[0]; | ||
325 | }; | ||
326 | |||
256 | static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) | 327 | static void mx2_camera_deactivate(struct mx2_camera_dev *pcdev) |
257 | { | 328 | { |
258 | unsigned long flags; | 329 | unsigned long flags; |
@@ -301,6 +372,7 @@ static int mx2_camera_add_device(struct soc_camera_device *icd) | |||
301 | writel(pcdev->csicr1, pcdev->base_csi + CSICR1); | 372 | writel(pcdev->csicr1, pcdev->base_csi + CSICR1); |
302 | 373 | ||
303 | pcdev->icd = icd; | 374 | pcdev->icd = icd; |
375 | pcdev->frame_count = 0; | ||
304 | 376 | ||
305 | dev_info(icd->parent, "Camera driver attached to camera %d\n", | 377 | dev_info(icd->parent, "Camera driver attached to camera %d\n", |
306 | icd->devnum); | 378 | icd->devnum); |
@@ -719,55 +791,77 @@ static void mx27_camera_emma_buf_init(struct soc_camera_device *icd, | |||
719 | struct soc_camera_host *ici = | 791 | struct soc_camera_host *ici = |
720 | to_soc_camera_host(icd->parent); | 792 | to_soc_camera_host(icd->parent); |
721 | struct mx2_camera_dev *pcdev = ici->priv; | 793 | struct mx2_camera_dev *pcdev = ici->priv; |
794 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; | ||
795 | u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width; | ||
796 | |||
797 | if (prp->cfg.channel == 1) { | ||
798 | writel(pcdev->discard_buffer_dma, | ||
799 | pcdev->base_emma + PRP_DEST_RGB1_PTR); | ||
800 | writel(pcdev->discard_buffer_dma, | ||
801 | pcdev->base_emma + PRP_DEST_RGB2_PTR); | ||
802 | |||
803 | writel(PRP_CNTL_CH1EN | | ||
804 | PRP_CNTL_CSIEN | | ||
805 | prp->cfg.in_fmt | | ||
806 | prp->cfg.out_fmt | | ||
807 | PRP_CNTL_CH1_LEN | | ||
808 | PRP_CNTL_CH1BYP | | ||
809 | PRP_CNTL_CH1_TSKIP(0) | | ||
810 | PRP_CNTL_IN_TSKIP(0), | ||
811 | pcdev->base_emma + PRP_CNTL); | ||
812 | |||
813 | writel((icd->user_width << 16) | icd->user_height, | ||
814 | pcdev->base_emma + PRP_SRC_FRAME_SIZE); | ||
815 | writel((icd->user_width << 16) | icd->user_height, | ||
816 | pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); | ||
817 | writel(bytesperline, | ||
818 | pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); | ||
819 | writel(prp->cfg.src_pixel, | ||
820 | pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); | ||
821 | writel(prp->cfg.ch1_pixel, | ||
822 | pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); | ||
823 | } else { /* channel 2 */ | ||
824 | writel(pcdev->discard_buffer_dma, | ||
825 | pcdev->base_emma + PRP_DEST_Y_PTR); | ||
826 | writel(pcdev->discard_buffer_dma, | ||
827 | pcdev->base_emma + PRP_SOURCE_Y_PTR); | ||
828 | |||
829 | if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) { | ||
830 | writel(pcdev->discard_buffer_dma + imgsize, | ||
831 | pcdev->base_emma + PRP_DEST_CB_PTR); | ||
832 | writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4), | ||
833 | pcdev->base_emma + PRP_DEST_CR_PTR); | ||
834 | writel(pcdev->discard_buffer_dma + imgsize, | ||
835 | pcdev->base_emma + PRP_SOURCE_CB_PTR); | ||
836 | writel(pcdev->discard_buffer_dma + ((5 * imgsize) / 4), | ||
837 | pcdev->base_emma + PRP_SOURCE_CR_PTR); | ||
838 | } | ||
722 | 839 | ||
723 | writel(pcdev->discard_buffer_dma, | 840 | writel(PRP_CNTL_CH2EN | |
724 | pcdev->base_emma + PRP_DEST_RGB1_PTR); | ||
725 | writel(pcdev->discard_buffer_dma, | ||
726 | pcdev->base_emma + PRP_DEST_RGB2_PTR); | ||
727 | |||
728 | /* | ||
729 | * We only use the EMMA engine to get rid of the broken | ||
730 | * DMA Engine. No color space consversion at the moment. | ||
731 | * We set the incomming and outgoing pixelformat to an | ||
732 | * 16 Bit wide format and adjust the bytesperline | ||
733 | * accordingly. With this configuration the inputdata | ||
734 | * will not be changed by the emma and could be any type | ||
735 | * of 16 Bit Pixelformat. | ||
736 | */ | ||
737 | writel(PRP_CNTL_CH1EN | | ||
738 | PRP_CNTL_CSIEN | | 841 | PRP_CNTL_CSIEN | |
739 | PRP_CNTL_DATA_IN_RGB16 | | 842 | prp->cfg.in_fmt | |
740 | PRP_CNTL_CH1_OUT_RGB16 | | 843 | prp->cfg.out_fmt | |
741 | PRP_CNTL_CH1_LEN | | 844 | PRP_CNTL_CH2_LEN | |
742 | PRP_CNTL_CH1BYP | | 845 | PRP_CNTL_CH2_TSKIP(0) | |
743 | PRP_CNTL_CH1_TSKIP(0) | | ||
744 | PRP_CNTL_IN_TSKIP(0), | 846 | PRP_CNTL_IN_TSKIP(0), |
745 | pcdev->base_emma + PRP_CNTL); | 847 | pcdev->base_emma + PRP_CNTL); |
746 | 848 | ||
747 | writel(((bytesperline >> 1) << 16) | icd->user_height, | 849 | writel((icd->user_width << 16) | icd->user_height, |
748 | pcdev->base_emma + PRP_SRC_FRAME_SIZE); | 850 | pcdev->base_emma + PRP_SRC_FRAME_SIZE); |
749 | writel(((bytesperline >> 1) << 16) | icd->user_height, | 851 | |
750 | pcdev->base_emma + PRP_CH1_OUT_IMAGE_SIZE); | 852 | writel((icd->user_width << 16) | icd->user_height, |
751 | writel(bytesperline, | 853 | pcdev->base_emma + PRP_CH2_OUT_IMAGE_SIZE); |
752 | pcdev->base_emma + PRP_DEST_CH1_LINE_STRIDE); | 854 | |
753 | writel(0x2ca00565, /* RGB565 */ | 855 | writel(prp->cfg.src_pixel, |
754 | pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); | 856 | pcdev->base_emma + PRP_SRC_PIXEL_FORMAT_CNTL); |
755 | writel(0x2ca00565, /* RGB565 */ | 857 | |
756 | pcdev->base_emma + PRP_CH1_PIXEL_FORMAT_CNTL); | 858 | } |
757 | 859 | ||
758 | /* Enable interrupts */ | 860 | /* Enable interrupts */ |
759 | writel(PRP_INTR_RDERR | | 861 | writel(prp->cfg.irq_flags, pcdev->base_emma + PRP_INTR_CNTL); |
760 | PRP_INTR_CH1WERR | | ||
761 | PRP_INTR_CH2WERR | | ||
762 | PRP_INTR_CH1FC | | ||
763 | PRP_INTR_CH2FC | | ||
764 | PRP_INTR_LBOVF | | ||
765 | PRP_INTR_CH2OVF, | ||
766 | pcdev->base_emma + PRP_INTR_CNTL); | ||
767 | } | 862 | } |
768 | 863 | ||
769 | static int mx2_camera_set_bus_param(struct soc_camera_device *icd, | 864 | static int mx2_camera_set_bus_param(struct soc_camera_device *icd) |
770 | __u32 pixfmt) | ||
771 | { | 865 | { |
772 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 866 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
773 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 867 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
@@ -911,9 +1005,58 @@ static int mx2_camera_set_crop(struct soc_camera_device *icd, | |||
911 | return ret; | 1005 | return ret; |
912 | } | 1006 | } |
913 | 1007 | ||
1008 | static int mx2_camera_get_formats(struct soc_camera_device *icd, | ||
1009 | unsigned int idx, | ||
1010 | struct soc_camera_format_xlate *xlate) | ||
1011 | { | ||
1012 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | ||
1013 | const struct soc_mbus_pixelfmt *fmt; | ||
1014 | struct device *dev = icd->parent; | ||
1015 | enum v4l2_mbus_pixelcode code; | ||
1016 | int ret, formats = 0; | ||
1017 | |||
1018 | ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code); | ||
1019 | if (ret < 0) | ||
1020 | /* no more formats */ | ||
1021 | return 0; | ||
1022 | |||
1023 | fmt = soc_mbus_get_fmtdesc(code); | ||
1024 | if (!fmt) { | ||
1025 | dev_err(dev, "Invalid format code #%u: %d\n", idx, code); | ||
1026 | return 0; | ||
1027 | } | ||
1028 | |||
1029 | if (code == V4L2_MBUS_FMT_YUYV8_2X8) { | ||
1030 | formats++; | ||
1031 | if (xlate) { | ||
1032 | /* | ||
1033 | * CH2 can output YUV420 which is a standard format in | ||
1034 | * soc_mediabus.c | ||
1035 | */ | ||
1036 | xlate->host_fmt = | ||
1037 | soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_1_5X8); | ||
1038 | xlate->code = code; | ||
1039 | dev_dbg(dev, "Providing host format %s for sensor code %d\n", | ||
1040 | xlate->host_fmt->name, code); | ||
1041 | xlate++; | ||
1042 | } | ||
1043 | } | ||
1044 | |||
1045 | /* Generic pass-trough */ | ||
1046 | formats++; | ||
1047 | if (xlate) { | ||
1048 | xlate->host_fmt = fmt; | ||
1049 | xlate->code = code; | ||
1050 | xlate++; | ||
1051 | } | ||
1052 | return formats; | ||
1053 | } | ||
1054 | |||
914 | static int mx2_camera_set_fmt(struct soc_camera_device *icd, | 1055 | static int mx2_camera_set_fmt(struct soc_camera_device *icd, |
915 | struct v4l2_format *f) | 1056 | struct v4l2_format *f) |
916 | { | 1057 | { |
1058 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | ||
1059 | struct mx2_camera_dev *pcdev = ici->priv; | ||
917 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1060 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
918 | const struct soc_camera_format_xlate *xlate; | 1061 | const struct soc_camera_format_xlate *xlate; |
919 | struct v4l2_pix_format *pix = &f->fmt.pix; | 1062 | struct v4l2_pix_format *pix = &f->fmt.pix; |
@@ -946,6 +1089,10 @@ static int mx2_camera_set_fmt(struct soc_camera_device *icd, | |||
946 | pix->colorspace = mf.colorspace; | 1089 | pix->colorspace = mf.colorspace; |
947 | icd->current_fmt = xlate; | 1090 | icd->current_fmt = xlate; |
948 | 1091 | ||
1092 | if (mx27_camera_emma(pcdev)) | ||
1093 | pcdev->emma_prp = mx27_emma_prp_get_format(xlate->code, | ||
1094 | xlate->host_fmt->fourcc); | ||
1095 | |||
949 | return 0; | 1096 | return 0; |
950 | } | 1097 | } |
951 | 1098 | ||
@@ -1011,7 +1158,12 @@ static int mx2_camera_try_fmt(struct soc_camera_device *icd, | |||
1011 | 1158 | ||
1012 | if (mf.field == V4L2_FIELD_ANY) | 1159 | if (mf.field == V4L2_FIELD_ANY) |
1013 | mf.field = V4L2_FIELD_NONE; | 1160 | mf.field = V4L2_FIELD_NONE; |
1014 | if (mf.field != V4L2_FIELD_NONE) { | 1161 | /* |
1162 | * Driver supports interlaced images provided they have | ||
1163 | * both fields so that they can be processed as if they | ||
1164 | * were progressive. | ||
1165 | */ | ||
1166 | if (mf.field != V4L2_FIELD_NONE && !V4L2_FIELD_HAS_BOTH(mf.field)) { | ||
1015 | dev_err(icd->parent, "Field type %d unsupported.\n", | 1167 | dev_err(icd->parent, "Field type %d unsupported.\n", |
1016 | mf.field); | 1168 | mf.field); |
1017 | return -EINVAL; | 1169 | return -EINVAL; |
@@ -1173,6 +1325,7 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = { | |||
1173 | .remove = mx2_camera_remove_device, | 1325 | .remove = mx2_camera_remove_device, |
1174 | .set_fmt = mx2_camera_set_fmt, | 1326 | .set_fmt = mx2_camera_set_fmt, |
1175 | .set_crop = mx2_camera_set_crop, | 1327 | .set_crop = mx2_camera_set_crop, |
1328 | .get_formats = mx2_camera_get_formats, | ||
1176 | .try_fmt = mx2_camera_try_fmt, | 1329 | .try_fmt = mx2_camera_try_fmt, |
1177 | .init_videobuf = mx2_camera_init_videobuf, | 1330 | .init_videobuf = mx2_camera_init_videobuf, |
1178 | .reqbufs = mx2_camera_reqbufs, | 1331 | .reqbufs = mx2_camera_reqbufs, |
@@ -1184,6 +1337,8 @@ static struct soc_camera_host_ops mx2_soc_camera_host_ops = { | |||
1184 | static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, | 1337 | static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, |
1185 | int bufnum, int state) | 1338 | int bufnum, int state) |
1186 | { | 1339 | { |
1340 | u32 imgsize = pcdev->icd->user_height * pcdev->icd->user_width; | ||
1341 | struct mx2_fmt_cfg *prp = pcdev->emma_prp; | ||
1187 | struct mx2_buffer *buf; | 1342 | struct mx2_buffer *buf; |
1188 | struct videobuf_buffer *vb; | 1343 | struct videobuf_buffer *vb; |
1189 | unsigned long phys; | 1344 | unsigned long phys; |
@@ -1197,12 +1352,22 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, | |||
1197 | vb = &buf->vb; | 1352 | vb = &buf->vb; |
1198 | #ifdef DEBUG | 1353 | #ifdef DEBUG |
1199 | phys = videobuf_to_dma_contig(vb); | 1354 | phys = videobuf_to_dma_contig(vb); |
1200 | if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum) | 1355 | if (prp->cfg.channel == 1) { |
1201 | != phys) { | 1356 | if (readl(pcdev->base_emma + PRP_DEST_RGB1_PTR + |
1202 | dev_err(pcdev->dev, "%p != %p\n", phys, | 1357 | 4 * bufnum) != phys) { |
1203 | readl(pcdev->base_emma + | 1358 | dev_err(pcdev->dev, "%p != %p\n", phys, |
1204 | PRP_DEST_RGB1_PTR + | 1359 | readl(pcdev->base_emma + |
1205 | 4 * bufnum)); | 1360 | PRP_DEST_RGB1_PTR + |
1361 | 4 * bufnum)); | ||
1362 | } | ||
1363 | } else { | ||
1364 | if (readl(pcdev->base_emma + PRP_DEST_Y_PTR - | ||
1365 | 0x14 * bufnum) != phys) { | ||
1366 | dev_err(pcdev->dev, "%p != %p\n", phys, | ||
1367 | readl(pcdev->base_emma + | ||
1368 | PRP_DEST_Y_PTR - | ||
1369 | 0x14 * bufnum)); | ||
1370 | } | ||
1206 | } | 1371 | } |
1207 | #endif | 1372 | #endif |
1208 | dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, | 1373 | dev_dbg(pcdev->dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__, vb, |
@@ -1211,14 +1376,29 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, | |||
1211 | list_del(&vb->queue); | 1376 | list_del(&vb->queue); |
1212 | vb->state = state; | 1377 | vb->state = state; |
1213 | do_gettimeofday(&vb->ts); | 1378 | do_gettimeofday(&vb->ts); |
1214 | vb->field_count++; | 1379 | vb->field_count = pcdev->frame_count * 2; |
1380 | pcdev->frame_count++; | ||
1215 | 1381 | ||
1216 | wake_up(&vb->done); | 1382 | wake_up(&vb->done); |
1217 | } | 1383 | } |
1218 | 1384 | ||
1219 | if (list_empty(&pcdev->capture)) { | 1385 | if (list_empty(&pcdev->capture)) { |
1220 | writel(pcdev->discard_buffer_dma, pcdev->base_emma + | 1386 | if (prp->cfg.channel == 1) { |
1221 | PRP_DEST_RGB1_PTR + 4 * bufnum); | 1387 | writel(pcdev->discard_buffer_dma, pcdev->base_emma + |
1388 | PRP_DEST_RGB1_PTR + 4 * bufnum); | ||
1389 | } else { | ||
1390 | writel(pcdev->discard_buffer_dma, pcdev->base_emma + | ||
1391 | PRP_DEST_Y_PTR - | ||
1392 | 0x14 * bufnum); | ||
1393 | if (prp->out_fmt == V4L2_PIX_FMT_YUV420) { | ||
1394 | writel(pcdev->discard_buffer_dma + imgsize, | ||
1395 | pcdev->base_emma + PRP_DEST_CB_PTR - | ||
1396 | 0x14 * bufnum); | ||
1397 | writel(pcdev->discard_buffer_dma + | ||
1398 | ((5 * imgsize) / 4), pcdev->base_emma + | ||
1399 | PRP_DEST_CR_PTR - 0x14 * bufnum); | ||
1400 | } | ||
1401 | } | ||
1222 | return; | 1402 | return; |
1223 | } | 1403 | } |
1224 | 1404 | ||
@@ -1233,7 +1413,18 @@ static void mx27_camera_frame_done_emma(struct mx2_camera_dev *pcdev, | |||
1233 | vb->state = VIDEOBUF_ACTIVE; | 1413 | vb->state = VIDEOBUF_ACTIVE; |
1234 | 1414 | ||
1235 | phys = videobuf_to_dma_contig(vb); | 1415 | phys = videobuf_to_dma_contig(vb); |
1236 | writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum); | 1416 | if (prp->cfg.channel == 1) { |
1417 | writel(phys, pcdev->base_emma + PRP_DEST_RGB1_PTR + 4 * bufnum); | ||
1418 | } else { | ||
1419 | writel(phys, pcdev->base_emma + | ||
1420 | PRP_DEST_Y_PTR - 0x14 * bufnum); | ||
1421 | if (prp->cfg.out_fmt == PRP_CNTL_CH2_OUT_YUV420) { | ||
1422 | writel(phys + imgsize, pcdev->base_emma + | ||
1423 | PRP_DEST_CB_PTR - 0x14 * bufnum); | ||
1424 | writel(phys + ((5 * imgsize) / 4), pcdev->base_emma + | ||
1425 | PRP_DEST_CR_PTR - 0x14 * bufnum); | ||
1426 | } | ||
1427 | } | ||
1237 | } | 1428 | } |
1238 | 1429 | ||
1239 | static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) | 1430 | static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) |
@@ -1253,10 +1444,12 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) | |||
1253 | * the next one. | 1444 | * the next one. |
1254 | */ | 1445 | */ |
1255 | cntl = readl(pcdev->base_emma + PRP_CNTL); | 1446 | cntl = readl(pcdev->base_emma + PRP_CNTL); |
1256 | writel(cntl & ~PRP_CNTL_CH1EN, pcdev->base_emma + PRP_CNTL); | 1447 | writel(cntl & ~(PRP_CNTL_CH1EN | PRP_CNTL_CH2EN), |
1448 | pcdev->base_emma + PRP_CNTL); | ||
1257 | writel(cntl, pcdev->base_emma + PRP_CNTL); | 1449 | writel(cntl, pcdev->base_emma + PRP_CNTL); |
1258 | } | 1450 | } |
1259 | if ((status & (3 << 5)) == (3 << 5) | 1451 | if ((((status & (3 << 5)) == (3 << 5)) || |
1452 | ((status & (3 << 3)) == (3 << 3))) | ||
1260 | && !list_empty(&pcdev->active_bufs)) { | 1453 | && !list_empty(&pcdev->active_bufs)) { |
1261 | /* | 1454 | /* |
1262 | * Both buffers have triggered, process the one we're expecting | 1455 | * Both buffers have triggered, process the one we're expecting |
@@ -1267,9 +1460,9 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data) | |||
1267 | mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE); | 1460 | mx27_camera_frame_done_emma(pcdev, buf->bufnum, VIDEOBUF_DONE); |
1268 | status &= ~(1 << (6 - buf->bufnum)); /* mark processed */ | 1461 | status &= ~(1 << (6 - buf->bufnum)); /* mark processed */ |
1269 | } | 1462 | } |
1270 | if (status & (1 << 6)) | 1463 | if ((status & (1 << 6)) || (status & (1 << 4))) |
1271 | mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE); | 1464 | mx27_camera_frame_done_emma(pcdev, 0, VIDEOBUF_DONE); |
1272 | if (status & (1 << 5)) | 1465 | if ((status & (1 << 5)) || (status & (1 << 3))) |
1273 | mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE); | 1466 | mx27_camera_frame_done_emma(pcdev, 1, VIDEOBUF_DONE); |
1274 | 1467 | ||
1275 | writel(status, pcdev->base_emma + PRP_INTRSTATUS); | 1468 | writel(status, pcdev->base_emma + PRP_INTRSTATUS); |
diff --git a/drivers/media/video/mx3_camera.c b/drivers/media/video/mx3_camera.c index f96f92f00f92..0cb461dd396a 100644 --- a/drivers/media/video/mx3_camera.c +++ b/drivers/media/video/mx3_camera.c | |||
@@ -982,12 +982,13 @@ static int mx3_camera_querycap(struct soc_camera_host *ici, | |||
982 | return 0; | 982 | return 0; |
983 | } | 983 | } |
984 | 984 | ||
985 | static int mx3_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | 985 | static int mx3_camera_set_bus_param(struct soc_camera_device *icd) |
986 | { | 986 | { |
987 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 987 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
988 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 988 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
989 | struct mx3_camera_dev *mx3_cam = ici->priv; | 989 | struct mx3_camera_dev *mx3_cam = ici->priv; |
990 | struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; | 990 | struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; |
991 | u32 pixfmt = icd->current_fmt->host_fmt->fourcc; | ||
991 | unsigned long bus_flags, common_flags; | 992 | unsigned long bus_flags, common_flags; |
992 | u32 dw, sens_conf; | 993 | u32 dw, sens_conf; |
993 | const struct soc_mbus_pixelfmt *fmt; | 994 | const struct soc_mbus_pixelfmt *fmt; |
@@ -1285,19 +1286,7 @@ static struct platform_driver mx3_camera_driver = { | |||
1285 | .remove = __devexit_p(mx3_camera_remove), | 1286 | .remove = __devexit_p(mx3_camera_remove), |
1286 | }; | 1287 | }; |
1287 | 1288 | ||
1288 | 1289 | module_platform_driver(mx3_camera_driver); | |
1289 | static int __init mx3_camera_init(void) | ||
1290 | { | ||
1291 | return platform_driver_register(&mx3_camera_driver); | ||
1292 | } | ||
1293 | |||
1294 | static void __exit mx3_camera_exit(void) | ||
1295 | { | ||
1296 | platform_driver_unregister(&mx3_camera_driver); | ||
1297 | } | ||
1298 | |||
1299 | module_init(mx3_camera_init); | ||
1300 | module_exit(mx3_camera_exit); | ||
1301 | 1290 | ||
1302 | MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver"); | 1291 | MODULE_DESCRIPTION("i.MX3x SoC Camera Host driver"); |
1303 | MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>"); | 1292 | MODULE_AUTHOR("Guennadi Liakhovetski <lg@denx.de>"); |
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index a378c2ce1273..a277f95091ef 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c | |||
@@ -524,10 +524,50 @@ static int omapvid_apply_changes(struct omap_vout_device *vout) | |||
524 | return 0; | 524 | return 0; |
525 | } | 525 | } |
526 | 526 | ||
527 | static int omapvid_handle_interlace_display(struct omap_vout_device *vout, | ||
528 | unsigned int irqstatus, struct timeval timevalue) | ||
529 | { | ||
530 | u32 fid; | ||
531 | |||
532 | if (vout->first_int) { | ||
533 | vout->first_int = 0; | ||
534 | goto err; | ||
535 | } | ||
536 | |||
537 | if (irqstatus & DISPC_IRQ_EVSYNC_ODD) | ||
538 | fid = 1; | ||
539 | else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) | ||
540 | fid = 0; | ||
541 | else | ||
542 | goto err; | ||
543 | |||
544 | vout->field_id ^= 1; | ||
545 | if (fid != vout->field_id) { | ||
546 | if (fid == 0) | ||
547 | vout->field_id = fid; | ||
548 | } else if (0 == fid) { | ||
549 | if (vout->cur_frm == vout->next_frm) | ||
550 | goto err; | ||
551 | |||
552 | vout->cur_frm->ts = timevalue; | ||
553 | vout->cur_frm->state = VIDEOBUF_DONE; | ||
554 | wake_up_interruptible(&vout->cur_frm->done); | ||
555 | vout->cur_frm = vout->next_frm; | ||
556 | } else { | ||
557 | if (list_empty(&vout->dma_queue) || | ||
558 | (vout->cur_frm != vout->next_frm)) | ||
559 | goto err; | ||
560 | } | ||
561 | |||
562 | return vout->field_id; | ||
563 | err: | ||
564 | return 0; | ||
565 | } | ||
566 | |||
527 | static void omap_vout_isr(void *arg, unsigned int irqstatus) | 567 | static void omap_vout_isr(void *arg, unsigned int irqstatus) |
528 | { | 568 | { |
529 | int ret; | 569 | int ret, fid, mgr_id; |
530 | u32 addr, fid; | 570 | u32 addr, irq; |
531 | struct omap_overlay *ovl; | 571 | struct omap_overlay *ovl; |
532 | struct timeval timevalue; | 572 | struct timeval timevalue; |
533 | struct omapvideo_info *ovid; | 573 | struct omapvideo_info *ovid; |
@@ -543,112 +583,73 @@ static void omap_vout_isr(void *arg, unsigned int irqstatus) | |||
543 | if (!ovl->manager || !ovl->manager->device) | 583 | if (!ovl->manager || !ovl->manager->device) |
544 | return; | 584 | return; |
545 | 585 | ||
586 | mgr_id = ovl->manager->id; | ||
546 | cur_display = ovl->manager->device; | 587 | cur_display = ovl->manager->device; |
547 | 588 | ||
548 | spin_lock(&vout->vbq_lock); | 589 | spin_lock(&vout->vbq_lock); |
549 | do_gettimeofday(&timevalue); | 590 | do_gettimeofday(&timevalue); |
550 | 591 | ||
551 | if (cur_display->type != OMAP_DISPLAY_TYPE_VENC) { | 592 | switch (cur_display->type) { |
552 | switch (cur_display->type) { | 593 | case OMAP_DISPLAY_TYPE_DSI: |
553 | case OMAP_DISPLAY_TYPE_DPI: | 594 | case OMAP_DISPLAY_TYPE_DPI: |
554 | if (!(irqstatus & (DISPC_IRQ_VSYNC | DISPC_IRQ_VSYNC2))) | 595 | if (mgr_id == OMAP_DSS_CHANNEL_LCD) |
555 | goto vout_isr_err; | 596 | irq = DISPC_IRQ_VSYNC; |
556 | break; | 597 | else if (mgr_id == OMAP_DSS_CHANNEL_LCD2) |
557 | case OMAP_DISPLAY_TYPE_HDMI: | 598 | irq = DISPC_IRQ_VSYNC2; |
558 | if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN)) | 599 | else |
559 | goto vout_isr_err; | ||
560 | break; | ||
561 | default: | ||
562 | goto vout_isr_err; | ||
563 | } | ||
564 | if (!vout->first_int && (vout->cur_frm != vout->next_frm)) { | ||
565 | vout->cur_frm->ts = timevalue; | ||
566 | vout->cur_frm->state = VIDEOBUF_DONE; | ||
567 | wake_up_interruptible(&vout->cur_frm->done); | ||
568 | vout->cur_frm = vout->next_frm; | ||
569 | } | ||
570 | vout->first_int = 0; | ||
571 | if (list_empty(&vout->dma_queue)) | ||
572 | goto vout_isr_err; | 600 | goto vout_isr_err; |
573 | 601 | ||
574 | vout->next_frm = list_entry(vout->dma_queue.next, | 602 | if (!(irqstatus & irq)) |
575 | struct videobuf_buffer, queue); | 603 | goto vout_isr_err; |
576 | list_del(&vout->next_frm->queue); | 604 | break; |
577 | 605 | case OMAP_DISPLAY_TYPE_VENC: | |
578 | vout->next_frm->state = VIDEOBUF_ACTIVE; | 606 | fid = omapvid_handle_interlace_display(vout, irqstatus, |
607 | timevalue); | ||
608 | if (!fid) | ||
609 | goto vout_isr_err; | ||
610 | break; | ||
611 | case OMAP_DISPLAY_TYPE_HDMI: | ||
612 | if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN)) | ||
613 | goto vout_isr_err; | ||
614 | break; | ||
615 | default: | ||
616 | goto vout_isr_err; | ||
617 | } | ||
579 | 618 | ||
580 | addr = (unsigned long) vout->queued_buf_addr[vout->next_frm->i] | 619 | if (!vout->first_int && (vout->cur_frm != vout->next_frm)) { |
581 | + vout->cropped_offset; | 620 | vout->cur_frm->ts = timevalue; |
621 | vout->cur_frm->state = VIDEOBUF_DONE; | ||
622 | wake_up_interruptible(&vout->cur_frm->done); | ||
623 | vout->cur_frm = vout->next_frm; | ||
624 | } | ||
582 | 625 | ||
583 | /* First save the configuration in ovelray structure */ | 626 | vout->first_int = 0; |
584 | ret = omapvid_init(vout, addr); | 627 | if (list_empty(&vout->dma_queue)) |
585 | if (ret) | 628 | goto vout_isr_err; |
586 | printk(KERN_ERR VOUT_NAME | ||
587 | "failed to set overlay info\n"); | ||
588 | /* Enable the pipeline and set the Go bit */ | ||
589 | ret = omapvid_apply_changes(vout); | ||
590 | if (ret) | ||
591 | printk(KERN_ERR VOUT_NAME "failed to change mode\n"); | ||
592 | } else { | ||
593 | 629 | ||
594 | if (vout->first_int) { | 630 | vout->next_frm = list_entry(vout->dma_queue.next, |
595 | vout->first_int = 0; | 631 | struct videobuf_buffer, queue); |
596 | goto vout_isr_err; | 632 | list_del(&vout->next_frm->queue); |
597 | } | ||
598 | if (irqstatus & DISPC_IRQ_EVSYNC_ODD) | ||
599 | fid = 1; | ||
600 | else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) | ||
601 | fid = 0; | ||
602 | else | ||
603 | goto vout_isr_err; | ||
604 | 633 | ||
605 | vout->field_id ^= 1; | 634 | vout->next_frm->state = VIDEOBUF_ACTIVE; |
606 | if (fid != vout->field_id) { | ||
607 | if (0 == fid) | ||
608 | vout->field_id = fid; | ||
609 | 635 | ||
610 | goto vout_isr_err; | 636 | addr = (unsigned long) vout->queued_buf_addr[vout->next_frm->i] |
611 | } | 637 | + vout->cropped_offset; |
612 | if (0 == fid) { | ||
613 | if (vout->cur_frm == vout->next_frm) | ||
614 | goto vout_isr_err; | ||
615 | |||
616 | vout->cur_frm->ts = timevalue; | ||
617 | vout->cur_frm->state = VIDEOBUF_DONE; | ||
618 | wake_up_interruptible(&vout->cur_frm->done); | ||
619 | vout->cur_frm = vout->next_frm; | ||
620 | } else if (1 == fid) { | ||
621 | if (list_empty(&vout->dma_queue) || | ||
622 | (vout->cur_frm != vout->next_frm)) | ||
623 | goto vout_isr_err; | ||
624 | |||
625 | vout->next_frm = list_entry(vout->dma_queue.next, | ||
626 | struct videobuf_buffer, queue); | ||
627 | list_del(&vout->next_frm->queue); | ||
628 | |||
629 | vout->next_frm->state = VIDEOBUF_ACTIVE; | ||
630 | addr = (unsigned long) | ||
631 | vout->queued_buf_addr[vout->next_frm->i] + | ||
632 | vout->cropped_offset; | ||
633 | /* First save the configuration in ovelray structure */ | ||
634 | ret = omapvid_init(vout, addr); | ||
635 | if (ret) | ||
636 | printk(KERN_ERR VOUT_NAME | ||
637 | "failed to set overlay info\n"); | ||
638 | /* Enable the pipeline and set the Go bit */ | ||
639 | ret = omapvid_apply_changes(vout); | ||
640 | if (ret) | ||
641 | printk(KERN_ERR VOUT_NAME | ||
642 | "failed to change mode\n"); | ||
643 | } | ||
644 | 638 | ||
645 | } | 639 | /* First save the configuration in ovelray structure */ |
640 | ret = omapvid_init(vout, addr); | ||
641 | if (ret) | ||
642 | printk(KERN_ERR VOUT_NAME | ||
643 | "failed to set overlay info\n"); | ||
644 | /* Enable the pipeline and set the Go bit */ | ||
645 | ret = omapvid_apply_changes(vout); | ||
646 | if (ret) | ||
647 | printk(KERN_ERR VOUT_NAME "failed to change mode\n"); | ||
646 | 648 | ||
647 | vout_isr_err: | 649 | vout_isr_err: |
648 | spin_unlock(&vout->vbq_lock); | 650 | spin_unlock(&vout->vbq_lock); |
649 | } | 651 | } |
650 | 652 | ||
651 | |||
652 | /* Video buffer call backs */ | 653 | /* Video buffer call backs */ |
653 | 654 | ||
654 | /* | 655 | /* |
@@ -664,10 +665,14 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, | |||
664 | u32 phy_addr = 0, virt_addr = 0; | 665 | u32 phy_addr = 0, virt_addr = 0; |
665 | struct omap_vout_device *vout = q->priv_data; | 666 | struct omap_vout_device *vout = q->priv_data; |
666 | struct omapvideo_info *ovid = &vout->vid_info; | 667 | struct omapvideo_info *ovid = &vout->vid_info; |
668 | int vid_max_buf_size; | ||
667 | 669 | ||
668 | if (!vout) | 670 | if (!vout) |
669 | return -EINVAL; | 671 | return -EINVAL; |
670 | 672 | ||
673 | vid_max_buf_size = vout->vid == OMAP_VIDEO1 ? video1_bufsize : | ||
674 | video2_bufsize; | ||
675 | |||
671 | if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type) | 676 | if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type) |
672 | return -EINVAL; | 677 | return -EINVAL; |
673 | 678 | ||
@@ -690,7 +695,7 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count, | |||
690 | video1_numbuffers : video2_numbuffers; | 695 | video1_numbuffers : video2_numbuffers; |
691 | 696 | ||
692 | /* Check the size of the buffer */ | 697 | /* Check the size of the buffer */ |
693 | if (*size > vout->buffer_size) { | 698 | if (*size > vid_max_buf_size) { |
694 | v4l2_err(&vout->vid_dev->v4l2_dev, | 699 | v4l2_err(&vout->vid_dev->v4l2_dev, |
695 | "buffer allocation mismatch [%u] [%u]\n", | 700 | "buffer allocation mismatch [%u] [%u]\n", |
696 | *size, vout->buffer_size); | 701 | *size, vout->buffer_size); |
diff --git a/drivers/media/video/omap/omap_voutdef.h b/drivers/media/video/omap/omap_voutdef.h index d793501cafcc..27a95d23b913 100644 --- a/drivers/media/video/omap/omap_voutdef.h +++ b/drivers/media/video/omap/omap_voutdef.h | |||
@@ -25,7 +25,7 @@ | |||
25 | #define MAC_VRFB_CTXS 4 | 25 | #define MAC_VRFB_CTXS 4 |
26 | #define MAX_VOUT_DEV 2 | 26 | #define MAX_VOUT_DEV 2 |
27 | #define MAX_OVLS 3 | 27 | #define MAX_OVLS 3 |
28 | #define MAX_DISPLAYS 3 | 28 | #define MAX_DISPLAYS 10 |
29 | #define MAX_MANAGERS 3 | 29 | #define MAX_MANAGERS 3 |
30 | 30 | ||
31 | #define QQVGA_WIDTH 160 | 31 | #define QQVGA_WIDTH 160 |
diff --git a/drivers/media/video/omap1_camera.c b/drivers/media/video/omap1_camera.c index 6a6cf388bae4..c20f5ecd6790 100644 --- a/drivers/media/video/omap1_camera.c +++ b/drivers/media/video/omap1_camera.c | |||
@@ -1436,13 +1436,13 @@ static int omap1_cam_querycap(struct soc_camera_host *ici, | |||
1436 | return 0; | 1436 | return 0; |
1437 | } | 1437 | } |
1438 | 1438 | ||
1439 | static int omap1_cam_set_bus_param(struct soc_camera_device *icd, | 1439 | static int omap1_cam_set_bus_param(struct soc_camera_device *icd) |
1440 | __u32 pixfmt) | ||
1441 | { | 1440 | { |
1442 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1441 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1443 | struct device *dev = icd->parent; | 1442 | struct device *dev = icd->parent; |
1444 | struct soc_camera_host *ici = to_soc_camera_host(dev); | 1443 | struct soc_camera_host *ici = to_soc_camera_host(dev); |
1445 | struct omap1_cam_dev *pcdev = ici->priv; | 1444 | struct omap1_cam_dev *pcdev = ici->priv; |
1445 | u32 pixfmt = icd->current_fmt->host_fmt->fourcc; | ||
1446 | const struct soc_camera_format_xlate *xlate; | 1446 | const struct soc_camera_format_xlate *xlate; |
1447 | const struct soc_mbus_pixelfmt *fmt; | 1447 | const struct soc_mbus_pixelfmt *fmt; |
1448 | struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; | 1448 | struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; |
@@ -1713,17 +1713,7 @@ static struct platform_driver omap1_cam_driver = { | |||
1713 | .remove = __exit_p(omap1_cam_remove), | 1713 | .remove = __exit_p(omap1_cam_remove), |
1714 | }; | 1714 | }; |
1715 | 1715 | ||
1716 | static int __init omap1_cam_init(void) | 1716 | module_platform_driver(omap1_cam_driver); |
1717 | { | ||
1718 | return platform_driver_register(&omap1_cam_driver); | ||
1719 | } | ||
1720 | module_init(omap1_cam_init); | ||
1721 | |||
1722 | static void __exit omap1_cam_exit(void) | ||
1723 | { | ||
1724 | platform_driver_unregister(&omap1_cam_driver); | ||
1725 | } | ||
1726 | module_exit(omap1_cam_exit); | ||
1727 | 1717 | ||
1728 | module_param(sg_mode, bool, 0644); | 1718 | module_param(sg_mode, bool, 0644); |
1729 | MODULE_PARM_DESC(sg_mode, "videobuf mode, 0: dma-contig (default), 1: dma-sg"); | 1719 | MODULE_PARM_DESC(sg_mode, "videobuf mode, 0: dma-contig (default), 1: dma-sg"); |
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index 45522e603185..7d3864144368 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c | |||
@@ -1868,21 +1868,7 @@ static struct platform_driver omap24xxcam_driver = { | |||
1868 | }, | 1868 | }, |
1869 | }; | 1869 | }; |
1870 | 1870 | ||
1871 | /* | 1871 | module_platform_driver(omap24xxcam_driver); |
1872 | * | ||
1873 | * Module initialisation and deinitialisation | ||
1874 | * | ||
1875 | */ | ||
1876 | |||
1877 | static int __init omap24xxcam_init(void) | ||
1878 | { | ||
1879 | return platform_driver_register(&omap24xxcam_driver); | ||
1880 | } | ||
1881 | |||
1882 | static void __exit omap24xxcam_cleanup(void) | ||
1883 | { | ||
1884 | platform_driver_unregister(&omap24xxcam_driver); | ||
1885 | } | ||
1886 | 1872 | ||
1887 | MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>"); | 1873 | MODULE_AUTHOR("Sakari Ailus <sakari.ailus@nokia.com>"); |
1888 | MODULE_DESCRIPTION("OMAP24xx Video for Linux camera driver"); | 1874 | MODULE_DESCRIPTION("OMAP24xx Video for Linux camera driver"); |
@@ -1894,6 +1880,3 @@ MODULE_PARM_DESC(video_nr, | |||
1894 | module_param(capture_mem, int, 0); | 1880 | module_param(capture_mem, int, 0); |
1895 | MODULE_PARM_DESC(capture_mem, "Maximum amount of memory for capture " | 1881 | MODULE_PARM_DESC(capture_mem, "Maximum amount of memory for capture " |
1896 | "buffers (default 4800kiB)"); | 1882 | "buffers (default 4800kiB)"); |
1897 | |||
1898 | module_init(omap24xxcam_init); | ||
1899 | module_exit(omap24xxcam_cleanup); | ||
diff --git a/drivers/media/video/omap3isp/isp.c b/drivers/media/video/omap3isp/isp.c index d4c48ef227fb..12d5f923e1d0 100644 --- a/drivers/media/video/omap3isp/isp.c +++ b/drivers/media/video/omap3isp/isp.c | |||
@@ -403,6 +403,7 @@ static inline void isp_isr_dbg(struct isp_device *isp, u32 irqstatus) | |||
403 | static void isp_isr_sbl(struct isp_device *isp) | 403 | static void isp_isr_sbl(struct isp_device *isp) |
404 | { | 404 | { |
405 | struct device *dev = isp->dev; | 405 | struct device *dev = isp->dev; |
406 | struct isp_pipeline *pipe; | ||
406 | u32 sbl_pcr; | 407 | u32 sbl_pcr; |
407 | 408 | ||
408 | /* | 409 | /* |
@@ -416,27 +417,38 @@ static void isp_isr_sbl(struct isp_device *isp) | |||
416 | if (sbl_pcr) | 417 | if (sbl_pcr) |
417 | dev_dbg(dev, "SBL overflow (PCR = 0x%08x)\n", sbl_pcr); | 418 | dev_dbg(dev, "SBL overflow (PCR = 0x%08x)\n", sbl_pcr); |
418 | 419 | ||
419 | if (sbl_pcr & (ISPSBL_PCR_CCDC_WBL_OVF | ISPSBL_PCR_CSIA_WBL_OVF | 420 | if (sbl_pcr & ISPSBL_PCR_CSIB_WBL_OVF) { |
420 | | ISPSBL_PCR_CSIB_WBL_OVF)) { | 421 | pipe = to_isp_pipeline(&isp->isp_ccp2.subdev.entity); |
421 | isp->isp_ccdc.error = 1; | 422 | if (pipe != NULL) |
422 | if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW) | 423 | pipe->error = true; |
423 | isp->isp_prev.error = 1; | 424 | } |
424 | if (isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER) | 425 | |
425 | isp->isp_res.error = 1; | 426 | if (sbl_pcr & ISPSBL_PCR_CSIA_WBL_OVF) { |
427 | pipe = to_isp_pipeline(&isp->isp_csi2a.subdev.entity); | ||
428 | if (pipe != NULL) | ||
429 | pipe->error = true; | ||
430 | } | ||
431 | |||
432 | if (sbl_pcr & ISPSBL_PCR_CCDC_WBL_OVF) { | ||
433 | pipe = to_isp_pipeline(&isp->isp_ccdc.subdev.entity); | ||
434 | if (pipe != NULL) | ||
435 | pipe->error = true; | ||
426 | } | 436 | } |
427 | 437 | ||
428 | if (sbl_pcr & ISPSBL_PCR_PRV_WBL_OVF) { | 438 | if (sbl_pcr & ISPSBL_PCR_PRV_WBL_OVF) { |
429 | isp->isp_prev.error = 1; | 439 | pipe = to_isp_pipeline(&isp->isp_prev.subdev.entity); |
430 | if (isp->isp_res.input == RESIZER_INPUT_VP && | 440 | if (pipe != NULL) |
431 | !(isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER)) | 441 | pipe->error = true; |
432 | isp->isp_res.error = 1; | ||
433 | } | 442 | } |
434 | 443 | ||
435 | if (sbl_pcr & (ISPSBL_PCR_RSZ1_WBL_OVF | 444 | if (sbl_pcr & (ISPSBL_PCR_RSZ1_WBL_OVF |
436 | | ISPSBL_PCR_RSZ2_WBL_OVF | 445 | | ISPSBL_PCR_RSZ2_WBL_OVF |
437 | | ISPSBL_PCR_RSZ3_WBL_OVF | 446 | | ISPSBL_PCR_RSZ3_WBL_OVF |
438 | | ISPSBL_PCR_RSZ4_WBL_OVF)) | 447 | | ISPSBL_PCR_RSZ4_WBL_OVF)) { |
439 | isp->isp_res.error = 1; | 448 | pipe = to_isp_pipeline(&isp->isp_res.subdev.entity); |
449 | if (pipe != NULL) | ||
450 | pipe->error = true; | ||
451 | } | ||
440 | 452 | ||
441 | if (sbl_pcr & ISPSBL_PCR_H3A_AF_WBL_OVF) | 453 | if (sbl_pcr & ISPSBL_PCR_H3A_AF_WBL_OVF) |
442 | omap3isp_stat_sbl_overflow(&isp->isp_af); | 454 | omap3isp_stat_sbl_overflow(&isp->isp_af); |
@@ -464,24 +476,17 @@ static irqreturn_t isp_isr(int irq, void *_isp) | |||
464 | IRQ0STATUS_HS_VS_IRQ; | 476 | IRQ0STATUS_HS_VS_IRQ; |
465 | struct isp_device *isp = _isp; | 477 | struct isp_device *isp = _isp; |
466 | u32 irqstatus; | 478 | u32 irqstatus; |
467 | int ret; | ||
468 | 479 | ||
469 | irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS); | 480 | irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS); |
470 | isp_reg_writel(isp, irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS); | 481 | isp_reg_writel(isp, irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS); |
471 | 482 | ||
472 | isp_isr_sbl(isp); | 483 | isp_isr_sbl(isp); |
473 | 484 | ||
474 | if (irqstatus & IRQ0STATUS_CSIA_IRQ) { | 485 | if (irqstatus & IRQ0STATUS_CSIA_IRQ) |
475 | ret = omap3isp_csi2_isr(&isp->isp_csi2a); | 486 | omap3isp_csi2_isr(&isp->isp_csi2a); |
476 | if (ret) | ||
477 | isp->isp_ccdc.error = 1; | ||
478 | } | ||
479 | 487 | ||
480 | if (irqstatus & IRQ0STATUS_CSIB_IRQ) { | 488 | if (irqstatus & IRQ0STATUS_CSIB_IRQ) |
481 | ret = omap3isp_ccp2_isr(&isp->isp_ccp2); | 489 | omap3isp_ccp2_isr(&isp->isp_ccp2); |
482 | if (ret) | ||
483 | isp->isp_ccdc.error = 1; | ||
484 | } | ||
485 | 490 | ||
486 | if (irqstatus & IRQ0STATUS_CCDC_VD0_IRQ) { | 491 | if (irqstatus & IRQ0STATUS_CCDC_VD0_IRQ) { |
487 | if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW) | 492 | if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW) |
@@ -2222,24 +2227,7 @@ static struct platform_driver omap3isp_driver = { | |||
2222 | }, | 2227 | }, |
2223 | }; | 2228 | }; |
2224 | 2229 | ||
2225 | /* | 2230 | module_platform_driver(omap3isp_driver); |
2226 | * isp_init - ISP module initialization. | ||
2227 | */ | ||
2228 | static int __init isp_init(void) | ||
2229 | { | ||
2230 | return platform_driver_register(&omap3isp_driver); | ||
2231 | } | ||
2232 | |||
2233 | /* | ||
2234 | * isp_cleanup - ISP module cleanup. | ||
2235 | */ | ||
2236 | static void __exit isp_cleanup(void) | ||
2237 | { | ||
2238 | platform_driver_unregister(&omap3isp_driver); | ||
2239 | } | ||
2240 | |||
2241 | module_init(isp_init); | ||
2242 | module_exit(isp_cleanup); | ||
2243 | 2231 | ||
2244 | MODULE_AUTHOR("Nokia Corporation"); | 2232 | MODULE_AUTHOR("Nokia Corporation"); |
2245 | MODULE_DESCRIPTION("TI OMAP3 ISP driver"); | 2233 | MODULE_DESCRIPTION("TI OMAP3 ISP driver"); |
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c index d341ba12593f..a74a79701d34 100644 --- a/drivers/media/video/omap3isp/ispccdc.c +++ b/drivers/media/video/omap3isp/ispccdc.c | |||
@@ -1406,9 +1406,8 @@ static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event) | |||
1406 | 1406 | ||
1407 | static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc) | 1407 | static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc) |
1408 | { | 1408 | { |
1409 | struct isp_pipeline *pipe = | 1409 | struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity); |
1410 | to_isp_pipeline(&ccdc->video_out.video.entity); | 1410 | struct video_device *vdev = &ccdc->subdev.devnode; |
1411 | struct video_device *vdev = ccdc->subdev.devnode; | ||
1412 | struct v4l2_event event; | 1411 | struct v4l2_event event; |
1413 | 1412 | ||
1414 | memset(&event, 0, sizeof(event)); | 1413 | memset(&event, 0, sizeof(event)); |
@@ -1428,8 +1427,11 @@ static void ccdc_lsc_isr(struct isp_ccdc_device *ccdc, u32 events) | |||
1428 | unsigned long flags; | 1427 | unsigned long flags; |
1429 | 1428 | ||
1430 | if (events & IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ) { | 1429 | if (events & IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ) { |
1430 | struct isp_pipeline *pipe = | ||
1431 | to_isp_pipeline(&ccdc->subdev.entity); | ||
1432 | |||
1431 | ccdc_lsc_error_handler(ccdc); | 1433 | ccdc_lsc_error_handler(ccdc); |
1432 | ccdc->error = 1; | 1434 | pipe->error = true; |
1433 | dev_dbg(to_device(ccdc), "lsc prefetch error\n"); | 1435 | dev_dbg(to_device(ccdc), "lsc prefetch error\n"); |
1434 | } | 1436 | } |
1435 | 1437 | ||
@@ -1504,7 +1506,7 @@ static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc) | |||
1504 | goto done; | 1506 | goto done; |
1505 | } | 1507 | } |
1506 | 1508 | ||
1507 | buffer = omap3isp_video_buffer_next(&ccdc->video_out, ccdc->error); | 1509 | buffer = omap3isp_video_buffer_next(&ccdc->video_out); |
1508 | if (buffer != NULL) { | 1510 | if (buffer != NULL) { |
1509 | ccdc_set_outaddr(ccdc, buffer->isp_addr); | 1511 | ccdc_set_outaddr(ccdc, buffer->isp_addr); |
1510 | restart = 1; | 1512 | restart = 1; |
@@ -1518,7 +1520,6 @@ static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc) | |||
1518 | ISP_PIPELINE_STREAM_SINGLESHOT); | 1520 | ISP_PIPELINE_STREAM_SINGLESHOT); |
1519 | 1521 | ||
1520 | done: | 1522 | done: |
1521 | ccdc->error = 0; | ||
1522 | return restart; | 1523 | return restart; |
1523 | } | 1524 | } |
1524 | 1525 | ||
@@ -1744,7 +1745,6 @@ static int ccdc_set_stream(struct v4l2_subdev *sd, int enable) | |||
1744 | */ | 1745 | */ |
1745 | ccdc_config_vp(ccdc); | 1746 | ccdc_config_vp(ccdc); |
1746 | ccdc_enable_vp(ccdc, 1); | 1747 | ccdc_enable_vp(ccdc, 1); |
1747 | ccdc->error = 0; | ||
1748 | ccdc_print_status(ccdc); | 1748 | ccdc_print_status(ccdc); |
1749 | } | 1749 | } |
1750 | 1750 | ||
diff --git a/drivers/media/video/omap3isp/ispccdc.h b/drivers/media/video/omap3isp/ispccdc.h index 483a19cac1ad..6d0264bab75b 100644 --- a/drivers/media/video/omap3isp/ispccdc.h +++ b/drivers/media/video/omap3isp/ispccdc.h | |||
@@ -150,7 +150,6 @@ struct ispccdc_lsc { | |||
150 | * @input: Active input | 150 | * @input: Active input |
151 | * @output: Active outputs | 151 | * @output: Active outputs |
152 | * @video_out: Output video node | 152 | * @video_out: Output video node |
153 | * @error: A hardware error occurred during capture | ||
154 | * @alaw: A-law compression enabled (1) or disabled (0) | 153 | * @alaw: A-law compression enabled (1) or disabled (0) |
155 | * @lpf: Low pass filter enabled (1) or disabled (0) | 154 | * @lpf: Low pass filter enabled (1) or disabled (0) |
156 | * @obclamp: Optical-black clamp enabled (1) or disabled (0) | 155 | * @obclamp: Optical-black clamp enabled (1) or disabled (0) |
@@ -178,7 +177,6 @@ struct isp_ccdc_device { | |||
178 | enum ccdc_input_entity input; | 177 | enum ccdc_input_entity input; |
179 | unsigned int output; | 178 | unsigned int output; |
180 | struct isp_video video_out; | 179 | struct isp_video video_out; |
181 | unsigned int error; | ||
182 | 180 | ||
183 | unsigned int alaw:1, | 181 | unsigned int alaw:1, |
184 | lpf:1, | 182 | lpf:1, |
diff --git a/drivers/media/video/omap3isp/ispccp2.c b/drivers/media/video/omap3isp/ispccp2.c index 904ca8c8b17f..70ddbf35b223 100644 --- a/drivers/media/video/omap3isp/ispccp2.c +++ b/drivers/media/video/omap3isp/ispccp2.c | |||
@@ -556,7 +556,7 @@ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2) | |||
556 | struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity); | 556 | struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity); |
557 | struct isp_buffer *buffer; | 557 | struct isp_buffer *buffer; |
558 | 558 | ||
559 | buffer = omap3isp_video_buffer_next(&ccp2->video_in, ccp2->error); | 559 | buffer = omap3isp_video_buffer_next(&ccp2->video_in); |
560 | if (buffer != NULL) | 560 | if (buffer != NULL) |
561 | ccp2_set_inaddr(ccp2, buffer->isp_addr); | 561 | ccp2_set_inaddr(ccp2, buffer->isp_addr); |
562 | 562 | ||
@@ -567,8 +567,6 @@ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2) | |||
567 | omap3isp_pipeline_set_stream(pipe, | 567 | omap3isp_pipeline_set_stream(pipe, |
568 | ISP_PIPELINE_STREAM_SINGLESHOT); | 568 | ISP_PIPELINE_STREAM_SINGLESHOT); |
569 | } | 569 | } |
570 | |||
571 | ccp2->error = 0; | ||
572 | } | 570 | } |
573 | 571 | ||
574 | /* | 572 | /* |
@@ -576,13 +574,11 @@ static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2) | |||
576 | * @ccp2: Pointer to ISP CCP2 device | 574 | * @ccp2: Pointer to ISP CCP2 device |
577 | * | 575 | * |
578 | * This will handle the CCP2 interrupts | 576 | * This will handle the CCP2 interrupts |
579 | * | ||
580 | * Returns -EIO in case of error, or 0 on success. | ||
581 | */ | 577 | */ |
582 | int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2) | 578 | void omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2) |
583 | { | 579 | { |
580 | struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity); | ||
584 | struct isp_device *isp = to_isp_device(ccp2); | 581 | struct isp_device *isp = to_isp_device(ccp2); |
585 | int ret = 0; | ||
586 | static const u32 ISPCCP2_LC01_ERROR = | 582 | static const u32 ISPCCP2_LC01_ERROR = |
587 | ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ | | 583 | ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ | |
588 | ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ | | 584 | ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ | |
@@ -604,19 +600,18 @@ int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2) | |||
604 | ISPCCP2_LCM_IRQSTATUS); | 600 | ISPCCP2_LCM_IRQSTATUS); |
605 | /* Errors */ | 601 | /* Errors */ |
606 | if (lcx_irqstatus & ISPCCP2_LC01_ERROR) { | 602 | if (lcx_irqstatus & ISPCCP2_LC01_ERROR) { |
607 | ccp2->error = 1; | 603 | pipe->error = true; |
608 | dev_dbg(isp->dev, "CCP2 err:%x\n", lcx_irqstatus); | 604 | dev_dbg(isp->dev, "CCP2 err:%x\n", lcx_irqstatus); |
609 | return -EIO; | 605 | return; |
610 | } | 606 | } |
611 | 607 | ||
612 | if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ) { | 608 | if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ) { |
613 | ccp2->error = 1; | 609 | pipe->error = true; |
614 | dev_dbg(isp->dev, "CCP2 OCP err:%x\n", lcm_irqstatus); | 610 | dev_dbg(isp->dev, "CCP2 OCP err:%x\n", lcm_irqstatus); |
615 | ret = -EIO; | ||
616 | } | 611 | } |
617 | 612 | ||
618 | if (omap3isp_module_sync_is_stopping(&ccp2->wait, &ccp2->stopping)) | 613 | if (omap3isp_module_sync_is_stopping(&ccp2->wait, &ccp2->stopping)) |
619 | return 0; | 614 | return; |
620 | 615 | ||
621 | /* Frame number propagation */ | 616 | /* Frame number propagation */ |
622 | if (lcx_irqstatus & ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ) { | 617 | if (lcx_irqstatus & ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ) { |
@@ -629,8 +624,6 @@ int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2) | |||
629 | /* Handle queued buffers on frame end interrupts */ | 624 | /* Handle queued buffers on frame end interrupts */ |
630 | if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_EOF_IRQ) | 625 | if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_EOF_IRQ) |
631 | ccp2_isr_buffer(ccp2); | 626 | ccp2_isr_buffer(ccp2); |
632 | |||
633 | return ret; | ||
634 | } | 627 | } |
635 | 628 | ||
636 | /* ----------------------------------------------------------------------------- | 629 | /* ----------------------------------------------------------------------------- |
@@ -867,7 +860,6 @@ static int ccp2_s_stream(struct v4l2_subdev *sd, int enable) | |||
867 | if (enable == ISP_PIPELINE_STREAM_STOPPED) | 860 | if (enable == ISP_PIPELINE_STREAM_STOPPED) |
868 | return 0; | 861 | return 0; |
869 | atomic_set(&ccp2->stopping, 0); | 862 | atomic_set(&ccp2->stopping, 0); |
870 | ccp2->error = 0; | ||
871 | } | 863 | } |
872 | 864 | ||
873 | switch (enable) { | 865 | switch (enable) { |
diff --git a/drivers/media/video/omap3isp/ispccp2.h b/drivers/media/video/omap3isp/ispccp2.h index 6674e9de2cd7..76d65f4576ef 100644 --- a/drivers/media/video/omap3isp/ispccp2.h +++ b/drivers/media/video/omap3isp/ispccp2.h | |||
@@ -82,7 +82,6 @@ struct isp_ccp2_device { | |||
82 | struct isp_video video_in; | 82 | struct isp_video video_in; |
83 | struct isp_csiphy *phy; | 83 | struct isp_csiphy *phy; |
84 | struct regulator *vdds_csib; | 84 | struct regulator *vdds_csib; |
85 | unsigned int error; | ||
86 | enum isp_pipeline_stream_state state; | 85 | enum isp_pipeline_stream_state state; |
87 | wait_queue_head_t wait; | 86 | wait_queue_head_t wait; |
88 | atomic_t stopping; | 87 | atomic_t stopping; |
@@ -94,6 +93,6 @@ void omap3isp_ccp2_cleanup(struct isp_device *isp); | |||
94 | int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2, | 93 | int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2, |
95 | struct v4l2_device *vdev); | 94 | struct v4l2_device *vdev); |
96 | void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2); | 95 | void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2); |
97 | int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2); | 96 | void omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2); |
98 | 97 | ||
99 | #endif /* OMAP3_ISP_CCP2_H */ | 98 | #endif /* OMAP3_ISP_CCP2_H */ |
diff --git a/drivers/media/video/omap3isp/ispcsi2.c b/drivers/media/video/omap3isp/ispcsi2.c index 0c5f1cb9d99d..fcb5168996a7 100644 --- a/drivers/media/video/omap3isp/ispcsi2.c +++ b/drivers/media/video/omap3isp/ispcsi2.c | |||
@@ -667,7 +667,7 @@ static void csi2_isr_buffer(struct isp_csi2_device *csi2) | |||
667 | 667 | ||
668 | csi2_ctx_enable(isp, csi2, 0, 0); | 668 | csi2_ctx_enable(isp, csi2, 0, 0); |
669 | 669 | ||
670 | buffer = omap3isp_video_buffer_next(&csi2->video_out, 0); | 670 | buffer = omap3isp_video_buffer_next(&csi2->video_out); |
671 | 671 | ||
672 | /* | 672 | /* |
673 | * Let video queue operation restart engine if there is an underrun | 673 | * Let video queue operation restart engine if there is an underrun |
@@ -727,17 +727,15 @@ static void csi2_isr_ctx(struct isp_csi2_device *csi2, | |||
727 | 727 | ||
728 | /* | 728 | /* |
729 | * omap3isp_csi2_isr - CSI2 interrupt handling. | 729 | * omap3isp_csi2_isr - CSI2 interrupt handling. |
730 | * | ||
731 | * Return -EIO on Transmission error | ||
732 | */ | 730 | */ |
733 | int omap3isp_csi2_isr(struct isp_csi2_device *csi2) | 731 | void omap3isp_csi2_isr(struct isp_csi2_device *csi2) |
734 | { | 732 | { |
733 | struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity); | ||
735 | u32 csi2_irqstatus, cpxio1_irqstatus; | 734 | u32 csi2_irqstatus, cpxio1_irqstatus; |
736 | struct isp_device *isp = csi2->isp; | 735 | struct isp_device *isp = csi2->isp; |
737 | int retval = 0; | ||
738 | 736 | ||
739 | if (!csi2->available) | 737 | if (!csi2->available) |
740 | return -ENODEV; | 738 | return; |
741 | 739 | ||
742 | csi2_irqstatus = isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQSTATUS); | 740 | csi2_irqstatus = isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQSTATUS); |
743 | isp_reg_writel(isp, csi2_irqstatus, csi2->regs1, ISPCSI2_IRQSTATUS); | 741 | isp_reg_writel(isp, csi2_irqstatus, csi2->regs1, ISPCSI2_IRQSTATUS); |
@@ -750,7 +748,7 @@ int omap3isp_csi2_isr(struct isp_csi2_device *csi2) | |||
750 | csi2->regs1, ISPCSI2_PHY_IRQSTATUS); | 748 | csi2->regs1, ISPCSI2_PHY_IRQSTATUS); |
751 | dev_dbg(isp->dev, "CSI2: ComplexIO Error IRQ " | 749 | dev_dbg(isp->dev, "CSI2: ComplexIO Error IRQ " |
752 | "%x\n", cpxio1_irqstatus); | 750 | "%x\n", cpxio1_irqstatus); |
753 | retval = -EIO; | 751 | pipe->error = true; |
754 | } | 752 | } |
755 | 753 | ||
756 | if (csi2_irqstatus & (ISPCSI2_IRQSTATUS_OCP_ERR_IRQ | | 754 | if (csi2_irqstatus & (ISPCSI2_IRQSTATUS_OCP_ERR_IRQ | |
@@ -775,11 +773,11 @@ int omap3isp_csi2_isr(struct isp_csi2_device *csi2) | |||
775 | ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ) ? 1 : 0, | 773 | ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ) ? 1 : 0, |
776 | (csi2_irqstatus & | 774 | (csi2_irqstatus & |
777 | ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ) ? 1 : 0); | 775 | ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ) ? 1 : 0); |
778 | retval = -EIO; | 776 | pipe->error = true; |
779 | } | 777 | } |
780 | 778 | ||
781 | if (omap3isp_module_sync_is_stopping(&csi2->wait, &csi2->stopping)) | 779 | if (omap3isp_module_sync_is_stopping(&csi2->wait, &csi2->stopping)) |
782 | return 0; | 780 | return; |
783 | 781 | ||
784 | /* Successful cases */ | 782 | /* Successful cases */ |
785 | if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0)) | 783 | if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0)) |
@@ -787,8 +785,6 @@ int omap3isp_csi2_isr(struct isp_csi2_device *csi2) | |||
787 | 785 | ||
788 | if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ) | 786 | if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ) |
789 | dev_dbg(isp->dev, "CSI2: ECC correction done\n"); | 787 | dev_dbg(isp->dev, "CSI2: ECC correction done\n"); |
790 | |||
791 | return retval; | ||
792 | } | 788 | } |
793 | 789 | ||
794 | /* ----------------------------------------------------------------------------- | 790 | /* ----------------------------------------------------------------------------- |
diff --git a/drivers/media/video/omap3isp/ispcsi2.h b/drivers/media/video/omap3isp/ispcsi2.h index 456fb7fb8a0f..885ad79a7678 100644 --- a/drivers/media/video/omap3isp/ispcsi2.h +++ b/drivers/media/video/omap3isp/ispcsi2.h | |||
@@ -156,7 +156,7 @@ struct isp_csi2_device { | |||
156 | atomic_t stopping; | 156 | atomic_t stopping; |
157 | }; | 157 | }; |
158 | 158 | ||
159 | int omap3isp_csi2_isr(struct isp_csi2_device *csi2); | 159 | void omap3isp_csi2_isr(struct isp_csi2_device *csi2); |
160 | int omap3isp_csi2_reset(struct isp_csi2_device *csi2); | 160 | int omap3isp_csi2_reset(struct isp_csi2_device *csi2); |
161 | int omap3isp_csi2_init(struct isp_device *isp); | 161 | int omap3isp_csi2_init(struct isp_device *isp); |
162 | void omap3isp_csi2_cleanup(struct isp_device *isp); | 162 | void omap3isp_csi2_cleanup(struct isp_device *isp); |
diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c index ccb876fe023f..6d0fb2c8c26d 100644 --- a/drivers/media/video/omap3isp/isppreview.c +++ b/drivers/media/video/omap3isp/isppreview.c | |||
@@ -116,11 +116,11 @@ static struct omap3isp_prev_csc flr_prev_csc = { | |||
116 | #define PREV_MIN_IN_HEIGHT 8 | 116 | #define PREV_MIN_IN_HEIGHT 8 |
117 | #define PREV_MAX_IN_HEIGHT 16384 | 117 | #define PREV_MAX_IN_HEIGHT 16384 |
118 | 118 | ||
119 | #define PREV_MIN_OUT_WIDTH 0 | 119 | #define PREV_MIN_OUT_WIDTH 0 |
120 | #define PREV_MIN_OUT_HEIGHT 0 | 120 | #define PREV_MIN_OUT_HEIGHT 0 |
121 | #define PREV_MAX_OUT_WIDTH 1280 | 121 | #define PREV_MAX_OUT_WIDTH_REV_1 1280 |
122 | #define PREV_MAX_OUT_WIDTH_ES2 3300 | 122 | #define PREV_MAX_OUT_WIDTH_REV_2 3300 |
123 | #define PREV_MAX_OUT_WIDTH_3630 4096 | 123 | #define PREV_MAX_OUT_WIDTH_REV_15 4096 |
124 | 124 | ||
125 | /* | 125 | /* |
126 | * Coeficient Tables for the submodules in Preview. | 126 | * Coeficient Tables for the submodules in Preview. |
@@ -1306,14 +1306,14 @@ static unsigned int preview_max_out_width(struct isp_prev_device *prev) | |||
1306 | 1306 | ||
1307 | switch (isp->revision) { | 1307 | switch (isp->revision) { |
1308 | case ISP_REVISION_1_0: | 1308 | case ISP_REVISION_1_0: |
1309 | return PREV_MAX_OUT_WIDTH; | 1309 | return PREV_MAX_OUT_WIDTH_REV_1; |
1310 | 1310 | ||
1311 | case ISP_REVISION_2_0: | 1311 | case ISP_REVISION_2_0: |
1312 | default: | 1312 | default: |
1313 | return PREV_MAX_OUT_WIDTH_ES2; | 1313 | return PREV_MAX_OUT_WIDTH_REV_2; |
1314 | 1314 | ||
1315 | case ISP_REVISION_15_0: | 1315 | case ISP_REVISION_15_0: |
1316 | return PREV_MAX_OUT_WIDTH_3630; | 1316 | return PREV_MAX_OUT_WIDTH_REV_15; |
1317 | } | 1317 | } |
1318 | } | 1318 | } |
1319 | 1319 | ||
@@ -1404,16 +1404,14 @@ static void preview_isr_buffer(struct isp_prev_device *prev) | |||
1404 | int restart = 0; | 1404 | int restart = 0; |
1405 | 1405 | ||
1406 | if (prev->input == PREVIEW_INPUT_MEMORY) { | 1406 | if (prev->input == PREVIEW_INPUT_MEMORY) { |
1407 | buffer = omap3isp_video_buffer_next(&prev->video_in, | 1407 | buffer = omap3isp_video_buffer_next(&prev->video_in); |
1408 | prev->error); | ||
1409 | if (buffer != NULL) | 1408 | if (buffer != NULL) |
1410 | preview_set_inaddr(prev, buffer->isp_addr); | 1409 | preview_set_inaddr(prev, buffer->isp_addr); |
1411 | pipe->state |= ISP_PIPELINE_IDLE_INPUT; | 1410 | pipe->state |= ISP_PIPELINE_IDLE_INPUT; |
1412 | } | 1411 | } |
1413 | 1412 | ||
1414 | if (prev->output & PREVIEW_OUTPUT_MEMORY) { | 1413 | if (prev->output & PREVIEW_OUTPUT_MEMORY) { |
1415 | buffer = omap3isp_video_buffer_next(&prev->video_out, | 1414 | buffer = omap3isp_video_buffer_next(&prev->video_out); |
1416 | prev->error); | ||
1417 | if (buffer != NULL) { | 1415 | if (buffer != NULL) { |
1418 | preview_set_outaddr(prev, buffer->isp_addr); | 1416 | preview_set_outaddr(prev, buffer->isp_addr); |
1419 | restart = 1; | 1417 | restart = 1; |
@@ -1440,8 +1438,6 @@ static void preview_isr_buffer(struct isp_prev_device *prev) | |||
1440 | default: | 1438 | default: |
1441 | return; | 1439 | return; |
1442 | } | 1440 | } |
1443 | |||
1444 | prev->error = 0; | ||
1445 | } | 1441 | } |
1446 | 1442 | ||
1447 | /* | 1443 | /* |
@@ -1565,7 +1561,6 @@ static int preview_set_stream(struct v4l2_subdev *sd, int enable) | |||
1565 | omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW); | 1561 | omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW); |
1566 | preview_configure(prev); | 1562 | preview_configure(prev); |
1567 | atomic_set(&prev->stopping, 0); | 1563 | atomic_set(&prev->stopping, 0); |
1568 | prev->error = 0; | ||
1569 | preview_print_status(prev); | 1564 | preview_print_status(prev); |
1570 | } | 1565 | } |
1571 | 1566 | ||
diff --git a/drivers/media/video/omap3isp/isppreview.h b/drivers/media/video/omap3isp/isppreview.h index f54e775c2df4..09686607973c 100644 --- a/drivers/media/video/omap3isp/isppreview.h +++ b/drivers/media/video/omap3isp/isppreview.h | |||
@@ -157,7 +157,6 @@ struct isptables_update { | |||
157 | * @output: Bitmask of the active output | 157 | * @output: Bitmask of the active output |
158 | * @video_in: Input video entity | 158 | * @video_in: Input video entity |
159 | * @video_out: Output video entity | 159 | * @video_out: Output video entity |
160 | * @error: A hardware error occurred during capture | ||
161 | * @params: Module configuration data | 160 | * @params: Module configuration data |
162 | * @shadow_update: If set, update the hardware configured in the next interrupt | 161 | * @shadow_update: If set, update the hardware configured in the next interrupt |
163 | * @underrun: Whether the preview entity has queued buffers on the output | 162 | * @underrun: Whether the preview entity has queued buffers on the output |
@@ -179,7 +178,6 @@ struct isp_prev_device { | |||
179 | unsigned int output; | 178 | unsigned int output; |
180 | struct isp_video video_in; | 179 | struct isp_video video_in; |
181 | struct isp_video video_out; | 180 | struct isp_video video_out; |
182 | unsigned int error; | ||
183 | 181 | ||
184 | struct prev_params params; | 182 | struct prev_params params; |
185 | unsigned int shadow_update:1; | 183 | unsigned int shadow_update:1; |
diff --git a/drivers/media/video/omap3isp/ispresizer.c b/drivers/media/video/omap3isp/ispresizer.c index 50e593bfcfaf..6958a9e3dc22 100644 --- a/drivers/media/video/omap3isp/ispresizer.c +++ b/drivers/media/video/omap3isp/ispresizer.c | |||
@@ -1038,7 +1038,7 @@ static void resizer_isr_buffer(struct isp_res_device *res) | |||
1038 | /* Complete the output buffer and, if reading from memory, the input | 1038 | /* Complete the output buffer and, if reading from memory, the input |
1039 | * buffer. | 1039 | * buffer. |
1040 | */ | 1040 | */ |
1041 | buffer = omap3isp_video_buffer_next(&res->video_out, res->error); | 1041 | buffer = omap3isp_video_buffer_next(&res->video_out); |
1042 | if (buffer != NULL) { | 1042 | if (buffer != NULL) { |
1043 | resizer_set_outaddr(res, buffer->isp_addr); | 1043 | resizer_set_outaddr(res, buffer->isp_addr); |
1044 | restart = 1; | 1044 | restart = 1; |
@@ -1047,7 +1047,7 @@ static void resizer_isr_buffer(struct isp_res_device *res) | |||
1047 | pipe->state |= ISP_PIPELINE_IDLE_OUTPUT; | 1047 | pipe->state |= ISP_PIPELINE_IDLE_OUTPUT; |
1048 | 1048 | ||
1049 | if (res->input == RESIZER_INPUT_MEMORY) { | 1049 | if (res->input == RESIZER_INPUT_MEMORY) { |
1050 | buffer = omap3isp_video_buffer_next(&res->video_in, 0); | 1050 | buffer = omap3isp_video_buffer_next(&res->video_in); |
1051 | if (buffer != NULL) | 1051 | if (buffer != NULL) |
1052 | resizer_set_inaddr(res, buffer->isp_addr); | 1052 | resizer_set_inaddr(res, buffer->isp_addr); |
1053 | pipe->state |= ISP_PIPELINE_IDLE_INPUT; | 1053 | pipe->state |= ISP_PIPELINE_IDLE_INPUT; |
@@ -1064,8 +1064,6 @@ static void resizer_isr_buffer(struct isp_res_device *res) | |||
1064 | if (restart) | 1064 | if (restart) |
1065 | resizer_enable_oneshot(res); | 1065 | resizer_enable_oneshot(res); |
1066 | } | 1066 | } |
1067 | |||
1068 | res->error = 0; | ||
1069 | } | 1067 | } |
1070 | 1068 | ||
1071 | /* | 1069 | /* |
@@ -1154,7 +1152,6 @@ static int resizer_set_stream(struct v4l2_subdev *sd, int enable) | |||
1154 | 1152 | ||
1155 | omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_RESIZER); | 1153 | omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_RESIZER); |
1156 | resizer_configure(res); | 1154 | resizer_configure(res); |
1157 | res->error = 0; | ||
1158 | resizer_print_status(res); | 1155 | resizer_print_status(res); |
1159 | } | 1156 | } |
1160 | 1157 | ||
diff --git a/drivers/media/video/omap3isp/ispresizer.h b/drivers/media/video/omap3isp/ispresizer.h index 76abc2e42126..70c1c0e1bbdf 100644 --- a/drivers/media/video/omap3isp/ispresizer.h +++ b/drivers/media/video/omap3isp/ispresizer.h | |||
@@ -107,7 +107,6 @@ struct isp_res_device { | |||
107 | enum resizer_input_entity input; | 107 | enum resizer_input_entity input; |
108 | struct isp_video video_in; | 108 | struct isp_video video_in; |
109 | struct isp_video video_out; | 109 | struct isp_video video_out; |
110 | unsigned int error; | ||
111 | 110 | ||
112 | u32 addr_base; /* stored source buffer address in memory mode */ | 111 | u32 addr_base; /* stored source buffer address in memory mode */ |
113 | u32 crop_offset; /* additional offset for crop in memory mode */ | 112 | u32 crop_offset; /* additional offset for crop in memory mode */ |
diff --git a/drivers/media/video/omap3isp/ispvideo.c b/drivers/media/video/omap3isp/ispvideo.c index bd3aebafafa0..b02070057724 100644 --- a/drivers/media/video/omap3isp/ispvideo.c +++ b/drivers/media/video/omap3isp/ispvideo.c | |||
@@ -211,14 +211,14 @@ static void isp_video_pix_to_mbus(const struct v4l2_pix_format *pix, | |||
211 | mbus->width = pix->width; | 211 | mbus->width = pix->width; |
212 | mbus->height = pix->height; | 212 | mbus->height = pix->height; |
213 | 213 | ||
214 | for (i = 0; i < ARRAY_SIZE(formats); ++i) { | 214 | /* Skip the last format in the loop so that it will be selected if no |
215 | * match is found. | ||
216 | */ | ||
217 | for (i = 0; i < ARRAY_SIZE(formats) - 1; ++i) { | ||
215 | if (formats[i].pixelformat == pix->pixelformat) | 218 | if (formats[i].pixelformat == pix->pixelformat) |
216 | break; | 219 | break; |
217 | } | 220 | } |
218 | 221 | ||
219 | if (WARN_ON(i == ARRAY_SIZE(formats))) | ||
220 | return; | ||
221 | |||
222 | mbus->code = formats[i].code; | 222 | mbus->code = formats[i].code; |
223 | mbus->colorspace = pix->colorspace; | 223 | mbus->colorspace = pix->colorspace; |
224 | mbus->field = pix->field; | 224 | mbus->field = pix->field; |
@@ -581,21 +581,20 @@ static const struct isp_video_queue_operations isp_video_queue_ops = { | |||
581 | /* | 581 | /* |
582 | * omap3isp_video_buffer_next - Complete the current buffer and return the next | 582 | * omap3isp_video_buffer_next - Complete the current buffer and return the next |
583 | * @video: ISP video object | 583 | * @video: ISP video object |
584 | * @error: Whether an error occurred during capture | ||
585 | * | 584 | * |
586 | * Remove the current video buffer from the DMA queue and fill its timestamp, | 585 | * Remove the current video buffer from the DMA queue and fill its timestamp, |
587 | * field count and state fields before waking up its completion handler. | 586 | * field count and state fields before waking up its completion handler. |
588 | * | 587 | * |
589 | * The buffer state is set to VIDEOBUF_DONE if no error occurred (@error is 0) | 588 | * For capture video nodes the buffer state is set to ISP_BUF_STATE_DONE if no |
590 | * or VIDEOBUF_ERROR otherwise (@error is non-zero). | 589 | * error has been flagged in the pipeline, or to ISP_BUF_STATE_ERROR otherwise. |
590 | * For video output nodes the buffer state is always set to ISP_BUF_STATE_DONE. | ||
591 | * | 591 | * |
592 | * The DMA queue is expected to contain at least one buffer. | 592 | * The DMA queue is expected to contain at least one buffer. |
593 | * | 593 | * |
594 | * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is | 594 | * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is |
595 | * empty. | 595 | * empty. |
596 | */ | 596 | */ |
597 | struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video, | 597 | struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video) |
598 | unsigned int error) | ||
599 | { | 598 | { |
600 | struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity); | 599 | struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity); |
601 | struct isp_video_queue *queue = video->queue; | 600 | struct isp_video_queue *queue = video->queue; |
@@ -630,7 +629,13 @@ struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video, | |||
630 | else | 629 | else |
631 | buf->vbuf.sequence = atomic_read(&pipe->frame_number); | 630 | buf->vbuf.sequence = atomic_read(&pipe->frame_number); |
632 | 631 | ||
633 | buf->state = error ? ISP_BUF_STATE_ERROR : ISP_BUF_STATE_DONE; | 632 | /* Report pipeline errors to userspace on the capture device side. */ |
633 | if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->error) { | ||
634 | buf->state = ISP_BUF_STATE_ERROR; | ||
635 | pipe->error = false; | ||
636 | } else { | ||
637 | buf->state = ISP_BUF_STATE_DONE; | ||
638 | } | ||
634 | 639 | ||
635 | wake_up(&buf->wait); | 640 | wake_up(&buf->wait); |
636 | 641 | ||
@@ -1016,6 +1021,8 @@ isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type) | |||
1016 | if (ret < 0) | 1021 | if (ret < 0) |
1017 | goto error; | 1022 | goto error; |
1018 | 1023 | ||
1024 | pipe->error = false; | ||
1025 | |||
1019 | spin_lock_irqsave(&pipe->lock, flags); | 1026 | spin_lock_irqsave(&pipe->lock, flags); |
1020 | pipe->state &= ~ISP_PIPELINE_STREAM; | 1027 | pipe->state &= ~ISP_PIPELINE_STREAM; |
1021 | pipe->state |= state; | 1028 | pipe->state |= state; |
diff --git a/drivers/media/video/omap3isp/ispvideo.h b/drivers/media/video/omap3isp/ispvideo.h index 08cbfa144e6e..d91bdb919be0 100644 --- a/drivers/media/video/omap3isp/ispvideo.h +++ b/drivers/media/video/omap3isp/ispvideo.h | |||
@@ -85,6 +85,10 @@ enum isp_pipeline_state { | |||
85 | ISP_PIPELINE_STREAM = 64, | 85 | ISP_PIPELINE_STREAM = 64, |
86 | }; | 86 | }; |
87 | 87 | ||
88 | /* | ||
89 | * struct isp_pipeline - An ISP hardware pipeline | ||
90 | * @error: A hardware error occurred during capture | ||
91 | */ | ||
88 | struct isp_pipeline { | 92 | struct isp_pipeline { |
89 | struct media_pipeline pipe; | 93 | struct media_pipeline pipe; |
90 | spinlock_t lock; /* Pipeline state and queue flags */ | 94 | spinlock_t lock; /* Pipeline state and queue flags */ |
@@ -96,6 +100,7 @@ struct isp_pipeline { | |||
96 | unsigned int max_rate; | 100 | unsigned int max_rate; |
97 | atomic_t frame_number; | 101 | atomic_t frame_number; |
98 | bool do_propagation; /* of frame number */ | 102 | bool do_propagation; /* of frame number */ |
103 | bool error; | ||
99 | struct v4l2_fract max_timeperframe; | 104 | struct v4l2_fract max_timeperframe; |
100 | }; | 105 | }; |
101 | 106 | ||
@@ -194,8 +199,7 @@ void omap3isp_video_cleanup(struct isp_video *video); | |||
194 | int omap3isp_video_register(struct isp_video *video, | 199 | int omap3isp_video_register(struct isp_video *video, |
195 | struct v4l2_device *vdev); | 200 | struct v4l2_device *vdev); |
196 | void omap3isp_video_unregister(struct isp_video *video); | 201 | void omap3isp_video_unregister(struct isp_video *video); |
197 | struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video, | 202 | struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video); |
198 | unsigned int error); | ||
199 | void omap3isp_video_resume(struct isp_video *video, int continuous); | 203 | void omap3isp_video_resume(struct isp_video *video, int continuous); |
200 | struct media_pad *omap3isp_video_remote_pad(struct isp_video *video); | 204 | struct media_pad *omap3isp_video_remote_pad(struct isp_video *video); |
201 | 205 | ||
diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c index 122b45760f0d..ebc2c7e39233 100644 --- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c | |||
@@ -2546,8 +2546,9 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf, | |||
2546 | } | 2546 | } |
2547 | 2547 | ||
2548 | /* Define and configure additional controls from cx2341x module. */ | 2548 | /* Define and configure additional controls from cx2341x module. */ |
2549 | hdw->mpeg_ctrl_info = kzalloc( | 2549 | hdw->mpeg_ctrl_info = kcalloc(MPEGDEF_COUNT, |
2550 | sizeof(*(hdw->mpeg_ctrl_info)) * MPEGDEF_COUNT, GFP_KERNEL); | 2550 | sizeof(*(hdw->mpeg_ctrl_info)), |
2551 | GFP_KERNEL); | ||
2551 | if (!hdw->mpeg_ctrl_info) goto fail; | 2552 | if (!hdw->mpeg_ctrl_info) goto fail; |
2552 | for (idx = 0; idx < MPEGDEF_COUNT; idx++) { | 2553 | for (idx = 0; idx < MPEGDEF_COUNT; idx++) { |
2553 | cptr = hdw->controls + idx + CTRLDEF_COUNT; | 2554 | cptr = hdw->controls + idx + CTRLDEF_COUNT; |
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index 3977addf3ba8..905d41d90c6a 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c | |||
@@ -102,8 +102,6 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] = | |||
102 | #include "pwc-nala.h" | 102 | #include "pwc-nala.h" |
103 | }; | 103 | }; |
104 | 104 | ||
105 | static void pwc_set_image_buffer_size(struct pwc_device *pdev); | ||
106 | |||
107 | /****************************************************************************/ | 105 | /****************************************************************************/ |
108 | 106 | ||
109 | static int _send_control_msg(struct pwc_device *pdev, | 107 | static int _send_control_msg(struct pwc_device *pdev, |
@@ -113,10 +111,9 @@ static int _send_control_msg(struct pwc_device *pdev, | |||
113 | void *kbuf = NULL; | 111 | void *kbuf = NULL; |
114 | 112 | ||
115 | if (buflen) { | 113 | if (buflen) { |
116 | kbuf = kmalloc(buflen, GFP_KERNEL); /* not allowed on stack */ | 114 | kbuf = kmemdup(buf, buflen, GFP_KERNEL); /* not allowed on stack */ |
117 | if (kbuf == NULL) | 115 | if (kbuf == NULL) |
118 | return -ENOMEM; | 116 | return -ENOMEM; |
119 | memcpy(kbuf, buf, buflen); | ||
120 | } | 117 | } |
121 | 118 | ||
122 | rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), | 119 | rc = usb_control_msg(pdev->udev, usb_sndctrlpipe(pdev->udev, 0), |
@@ -171,7 +168,8 @@ int send_control_msg(struct pwc_device *pdev, | |||
171 | request, value, pdev->vcinterface, buf, buflen); | 168 | request, value, pdev->vcinterface, buf, buflen); |
172 | } | 169 | } |
173 | 170 | ||
174 | static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) | 171 | static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames, |
172 | int *compression) | ||
175 | { | 173 | { |
176 | unsigned char buf[3]; | 174 | unsigned char buf[3]; |
177 | int ret, fps; | 175 | int ret, fps; |
@@ -221,10 +219,10 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) | |||
221 | 219 | ||
222 | /* Set various parameters */ | 220 | /* Set various parameters */ |
223 | pdev->vframes = frames; | 221 | pdev->vframes = frames; |
224 | pdev->vsize = size; | ||
225 | pdev->valternate = pEntry->alternate; | 222 | pdev->valternate = pEntry->alternate; |
226 | pdev->image = pwc_image_sizes[size]; | 223 | pdev->width = pwc_image_sizes[size][0]; |
227 | pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2; | 224 | pdev->height = pwc_image_sizes[size][1]; |
225 | pdev->frame_size = (pdev->width * pdev->height * 3) / 2; | ||
228 | if (pEntry->compressed) { | 226 | if (pEntry->compressed) { |
229 | if (pdev->release < 5) { /* 4 fold compression */ | 227 | if (pdev->release < 5) { /* 4 fold compression */ |
230 | pdev->vbandlength = 528; | 228 | pdev->vbandlength = 528; |
@@ -237,38 +235,40 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) | |||
237 | } | 235 | } |
238 | else | 236 | else |
239 | pdev->vbandlength = 0; | 237 | pdev->vbandlength = 0; |
238 | |||
239 | /* Let pwc-if.c:isoc_init know we don't support higher compression */ | ||
240 | *compression = 3; | ||
241 | |||
240 | return 0; | 242 | return 0; |
241 | } | 243 | } |
242 | 244 | ||
243 | 245 | ||
244 | static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) | 246 | static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, |
247 | int *compression) | ||
245 | { | 248 | { |
246 | unsigned char buf[13]; | 249 | unsigned char buf[13]; |
247 | const struct Timon_table_entry *pChoose; | 250 | const struct Timon_table_entry *pChoose; |
248 | int ret, fps; | 251 | int ret, fps; |
249 | 252 | ||
250 | if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3) | 253 | if (size >= PSZ_MAX || frames < 5 || frames > 30 || |
254 | *compression < 0 || *compression > 3) | ||
251 | return -EINVAL; | 255 | return -EINVAL; |
252 | if (size == PSZ_VGA && frames > 15) | 256 | if (size == PSZ_VGA && frames > 15) |
253 | return -EINVAL; | 257 | return -EINVAL; |
254 | fps = (frames / 5) - 1; | 258 | fps = (frames / 5) - 1; |
255 | 259 | ||
256 | /* Find a supported framerate with progressively higher compression ratios | 260 | /* Find a supported framerate with progressively higher compression */ |
257 | if the preferred ratio is not available. | ||
258 | */ | ||
259 | pChoose = NULL; | 261 | pChoose = NULL; |
260 | while (compression <= 3) { | 262 | while (*compression <= 3) { |
261 | pChoose = &Timon_table[size][fps][compression]; | 263 | pChoose = &Timon_table[size][fps][*compression]; |
262 | if (pChoose->alternate != 0) | 264 | if (pChoose->alternate != 0) |
263 | break; | 265 | break; |
264 | compression++; | 266 | (*compression)++; |
265 | } | 267 | } |
266 | if (pChoose == NULL || pChoose->alternate == 0) | 268 | if (pChoose == NULL || pChoose->alternate == 0) |
267 | return -ENOENT; /* Not supported. */ | 269 | return -ENOENT; /* Not supported. */ |
268 | 270 | ||
269 | memcpy(buf, pChoose->mode, 13); | 271 | memcpy(buf, pChoose->mode, 13); |
270 | if (snapshot) | ||
271 | buf[0] |= 0x80; | ||
272 | ret = send_video_command(pdev, pdev->vendpoint, buf, 13); | 272 | ret = send_video_command(pdev, pdev->vendpoint, buf, 13); |
273 | if (ret < 0) | 273 | if (ret < 0) |
274 | return ret; | 274 | return ret; |
@@ -284,55 +284,38 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, i | |||
284 | 284 | ||
285 | /* Set various parameters */ | 285 | /* Set various parameters */ |
286 | pdev->vframes = frames; | 286 | pdev->vframes = frames; |
287 | pdev->vsize = size; | ||
288 | pdev->vsnapshot = snapshot; | ||
289 | pdev->valternate = pChoose->alternate; | 287 | pdev->valternate = pChoose->alternate; |
290 | pdev->image = pwc_image_sizes[size]; | 288 | pdev->width = pwc_image_sizes[size][0]; |
289 | pdev->height = pwc_image_sizes[size][1]; | ||
291 | pdev->vbandlength = pChoose->bandlength; | 290 | pdev->vbandlength = pChoose->bandlength; |
292 | if (pChoose->bandlength > 0) | 291 | if (pChoose->bandlength > 0) |
293 | pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4; | 292 | pdev->frame_size = (pChoose->bandlength * pdev->height) / 4; |
294 | else | 293 | else |
295 | pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; | 294 | pdev->frame_size = (pdev->width * pdev->height * 12) / 8; |
296 | return 0; | 295 | return 0; |
297 | } | 296 | } |
298 | 297 | ||
299 | 298 | ||
300 | static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, int compression, int snapshot) | 299 | static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, |
300 | int *compression) | ||
301 | { | 301 | { |
302 | const struct Kiara_table_entry *pChoose = NULL; | 302 | const struct Kiara_table_entry *pChoose = NULL; |
303 | int fps, ret; | 303 | int fps, ret; |
304 | unsigned char buf[12]; | 304 | unsigned char buf[12]; |
305 | struct Kiara_table_entry RawEntry = {6, 773, 1272, {0xAD, 0xF4, 0x10, 0x27, 0xB6, 0x24, 0x96, 0x02, 0x30, 0x05, 0x03, 0x80}}; | ||
306 | 305 | ||
307 | if (size >= PSZ_MAX || frames < 5 || frames > 30 || compression < 0 || compression > 3) | 306 | if (size >= PSZ_MAX || frames < 5 || frames > 30 || |
307 | *compression < 0 || *compression > 3) | ||
308 | return -EINVAL; | 308 | return -EINVAL; |
309 | if (size == PSZ_VGA && frames > 15) | 309 | if (size == PSZ_VGA && frames > 15) |
310 | return -EINVAL; | 310 | return -EINVAL; |
311 | fps = (frames / 5) - 1; | 311 | fps = (frames / 5) - 1; |
312 | 312 | ||
313 | /* special case: VGA @ 5 fps and snapshot is raw bayer mode */ | 313 | /* Find a supported framerate with progressively higher compression */ |
314 | if (size == PSZ_VGA && frames == 5 && snapshot && pdev->pixfmt != V4L2_PIX_FMT_YUV420) | 314 | while (*compression <= 3) { |
315 | { | 315 | pChoose = &Kiara_table[size][fps][*compression]; |
316 | /* Only available in case the raw palette is selected or | 316 | if (pChoose->alternate != 0) |
317 | we have the decompressor available. This mode is | 317 | break; |
318 | only available in compressed form | 318 | (*compression)++; |
319 | */ | ||
320 | PWC_DEBUG_SIZE("Choosing VGA/5 BAYER mode.\n"); | ||
321 | pChoose = &RawEntry; | ||
322 | } | ||
323 | else | ||
324 | { | ||
325 | /* Find a supported framerate with progressively higher compression ratios | ||
326 | if the preferred ratio is not available. | ||
327 | Skip this step when using RAW modes. | ||
328 | */ | ||
329 | snapshot = 0; | ||
330 | while (compression <= 3) { | ||
331 | pChoose = &Kiara_table[size][fps][compression]; | ||
332 | if (pChoose->alternate != 0) | ||
333 | break; | ||
334 | compression++; | ||
335 | } | ||
336 | } | 319 | } |
337 | if (pChoose == NULL || pChoose->alternate == 0) | 320 | if (pChoose == NULL || pChoose->alternate == 0) |
338 | return -ENOENT; /* Not supported. */ | 321 | return -ENOENT; /* Not supported. */ |
@@ -341,8 +324,6 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, i | |||
341 | 324 | ||
342 | /* usb_control_msg won't take staticly allocated arrays as argument?? */ | 325 | /* usb_control_msg won't take staticly allocated arrays as argument?? */ |
343 | memcpy(buf, pChoose->mode, 12); | 326 | memcpy(buf, pChoose->mode, 12); |
344 | if (snapshot) | ||
345 | buf[0] |= 0x80; | ||
346 | 327 | ||
347 | /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */ | 328 | /* Firmware bug: video endpoint is 5, but commands are sent to endpoint 4 */ |
348 | ret = send_video_command(pdev, 4 /* pdev->vendpoint */, buf, 12); | 329 | ret = send_video_command(pdev, 4 /* pdev->vendpoint */, buf, 12); |
@@ -359,61 +340,43 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, i | |||
359 | memcpy(pdev->cmd_buf, buf, 12); | 340 | memcpy(pdev->cmd_buf, buf, 12); |
360 | /* All set and go */ | 341 | /* All set and go */ |
361 | pdev->vframes = frames; | 342 | pdev->vframes = frames; |
362 | pdev->vsize = size; | ||
363 | pdev->vsnapshot = snapshot; | ||
364 | pdev->valternate = pChoose->alternate; | 343 | pdev->valternate = pChoose->alternate; |
365 | pdev->image = pwc_image_sizes[size]; | 344 | pdev->width = pwc_image_sizes[size][0]; |
345 | pdev->height = pwc_image_sizes[size][1]; | ||
366 | pdev->vbandlength = pChoose->bandlength; | 346 | pdev->vbandlength = pChoose->bandlength; |
367 | if (pdev->vbandlength > 0) | 347 | if (pdev->vbandlength > 0) |
368 | pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4; | 348 | pdev->frame_size = (pdev->vbandlength * pdev->height) / 4; |
369 | else | 349 | else |
370 | pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; | 350 | pdev->frame_size = (pdev->width * pdev->height * 12) / 8; |
371 | PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vsnapshot=%d, vbandlength=%d\n", | 351 | PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n", |
372 | pdev->frame_size,pdev->vframes,pdev->vsize,pdev->vsnapshot,pdev->vbandlength); | 352 | pdev->frame_size, pdev->vframes, size, pdev->vbandlength); |
373 | return 0; | 353 | return 0; |
374 | } | 354 | } |
375 | 355 | ||
376 | 356 | int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, | |
377 | 357 | int frames, int *compression) | |
378 | /** | ||
379 | @pdev: device structure | ||
380 | @width: viewport width | ||
381 | @height: viewport height | ||
382 | @frame: framerate, in fps | ||
383 | @compression: preferred compression ratio | ||
384 | @snapshot: snapshot mode or streaming | ||
385 | */ | ||
386 | int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot) | ||
387 | { | 358 | { |
388 | int ret, size; | 359 | int ret, size; |
389 | 360 | ||
390 | PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt); | 361 | PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt); |
391 | size = pwc_decode_size(pdev, width, height); | 362 | size = pwc_get_size(pdev, width, height); |
392 | if (size < 0) { | ||
393 | PWC_DEBUG_MODULE("Could not find suitable size.\n"); | ||
394 | return -ERANGE; | ||
395 | } | ||
396 | PWC_TRACE("decode_size = %d.\n", size); | 363 | PWC_TRACE("decode_size = %d.\n", size); |
397 | 364 | ||
398 | if (DEVICE_USE_CODEC1(pdev->type)) { | 365 | if (DEVICE_USE_CODEC1(pdev->type)) { |
399 | ret = set_video_mode_Nala(pdev, size, frames); | 366 | ret = set_video_mode_Nala(pdev, size, frames, compression); |
400 | 367 | ||
401 | } else if (DEVICE_USE_CODEC3(pdev->type)) { | 368 | } else if (DEVICE_USE_CODEC3(pdev->type)) { |
402 | ret = set_video_mode_Kiara(pdev, size, frames, compression, snapshot); | 369 | ret = set_video_mode_Kiara(pdev, size, frames, compression); |
403 | 370 | ||
404 | } else { | 371 | } else { |
405 | ret = set_video_mode_Timon(pdev, size, frames, compression, snapshot); | 372 | ret = set_video_mode_Timon(pdev, size, frames, compression); |
406 | } | 373 | } |
407 | if (ret < 0) { | 374 | if (ret < 0) { |
408 | PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); | 375 | PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); |
409 | return ret; | 376 | return ret; |
410 | } | 377 | } |
411 | pdev->view.x = width; | ||
412 | pdev->view.y = height; | ||
413 | pdev->vcompression = compression; | ||
414 | pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; | 378 | pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; |
415 | pwc_set_image_buffer_size(pdev); | 379 | PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height); |
416 | PWC_DEBUG_SIZE("Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y); | ||
417 | return 0; | 380 | return 0; |
418 | } | 381 | } |
419 | 382 | ||
@@ -470,34 +433,6 @@ unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned i | |||
470 | return ret; | 433 | return ret; |
471 | } | 434 | } |
472 | 435 | ||
473 | static void pwc_set_image_buffer_size(struct pwc_device *pdev) | ||
474 | { | ||
475 | int factor = 0; | ||
476 | |||
477 | /* for V4L2_PIX_FMT_YUV420 */ | ||
478 | switch (pdev->pixfmt) { | ||
479 | case V4L2_PIX_FMT_YUV420: | ||
480 | factor = 6; | ||
481 | break; | ||
482 | case V4L2_PIX_FMT_PWC1: | ||
483 | case V4L2_PIX_FMT_PWC2: | ||
484 | factor = 6; /* can be uncompressed YUV420P */ | ||
485 | break; | ||
486 | } | ||
487 | |||
488 | /* Set sizes in bytes */ | ||
489 | pdev->image.size = pdev->image.x * pdev->image.y * factor / 4; | ||
490 | pdev->view.size = pdev->view.x * pdev->view.y * factor / 4; | ||
491 | |||
492 | /* Align offset, or you'll get some very weird results in | ||
493 | YUV420 mode... x must be multiple of 4 (to get the Y's in | ||
494 | place), and y even (or you'll mixup U & V). This is less of a | ||
495 | problem for YUV420P. | ||
496 | */ | ||
497 | pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC; | ||
498 | pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE; | ||
499 | } | ||
500 | |||
501 | int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) | 436 | int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) |
502 | { | 437 | { |
503 | int ret; | 438 | int ret; |
@@ -598,54 +533,6 @@ void pwc_camera_power(struct pwc_device *pdev, int power) | |||
598 | power ? "on" : "off", r); | 533 | power ? "on" : "off", r); |
599 | } | 534 | } |
600 | 535 | ||
601 | static int pwc_set_wb_speed(struct pwc_device *pdev, int speed) | ||
602 | { | ||
603 | unsigned char buf; | ||
604 | |||
605 | /* useful range is 0x01..0x20 */ | ||
606 | buf = speed / 0x7f0; | ||
607 | return send_control_msg(pdev, | ||
608 | SET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf)); | ||
609 | } | ||
610 | |||
611 | static int pwc_get_wb_speed(struct pwc_device *pdev, int *value) | ||
612 | { | ||
613 | unsigned char buf; | ||
614 | int ret; | ||
615 | |||
616 | ret = recv_control_msg(pdev, | ||
617 | GET_CHROM_CTL, AWB_CONTROL_SPEED_FORMATTER, &buf, sizeof(buf)); | ||
618 | if (ret < 0) | ||
619 | return ret; | ||
620 | *value = buf * 0x7f0; | ||
621 | return 0; | ||
622 | } | ||
623 | |||
624 | |||
625 | static int pwc_set_wb_delay(struct pwc_device *pdev, int delay) | ||
626 | { | ||
627 | unsigned char buf; | ||
628 | |||
629 | /* useful range is 0x01..0x3F */ | ||
630 | buf = (delay >> 10); | ||
631 | return send_control_msg(pdev, | ||
632 | SET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf)); | ||
633 | } | ||
634 | |||
635 | static int pwc_get_wb_delay(struct pwc_device *pdev, int *value) | ||
636 | { | ||
637 | unsigned char buf; | ||
638 | int ret; | ||
639 | |||
640 | ret = recv_control_msg(pdev, | ||
641 | GET_CHROM_CTL, AWB_CONTROL_DELAY_FORMATTER, &buf, sizeof(buf)); | ||
642 | if (ret < 0) | ||
643 | return ret; | ||
644 | *value = buf << 10; | ||
645 | return 0; | ||
646 | } | ||
647 | |||
648 | |||
649 | int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) | 536 | int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) |
650 | { | 537 | { |
651 | unsigned char buf[2]; | 538 | unsigned char buf[2]; |
@@ -675,108 +562,6 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) | |||
675 | return r; | 562 | return r; |
676 | } | 563 | } |
677 | 564 | ||
678 | static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) | ||
679 | { | ||
680 | unsigned char buf[2]; | ||
681 | int ret; | ||
682 | |||
683 | if (pdev->type < 730) { | ||
684 | *on_value = -1; | ||
685 | *off_value = -1; | ||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | ret = recv_control_msg(pdev, | ||
690 | GET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf)); | ||
691 | if (ret < 0) | ||
692 | return ret; | ||
693 | *on_value = buf[0] * 100; | ||
694 | *off_value = buf[1] * 100; | ||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | static int _pwc_mpt_reset(struct pwc_device *pdev, int flags) | ||
699 | { | ||
700 | unsigned char buf; | ||
701 | |||
702 | buf = flags & 0x03; // only lower two bits are currently used | ||
703 | return send_control_msg(pdev, | ||
704 | SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, &buf, sizeof(buf)); | ||
705 | } | ||
706 | |||
707 | int pwc_mpt_reset(struct pwc_device *pdev, int flags) | ||
708 | { | ||
709 | int ret; | ||
710 | ret = _pwc_mpt_reset(pdev, flags); | ||
711 | if (ret >= 0) { | ||
712 | pdev->pan_angle = 0; | ||
713 | pdev->tilt_angle = 0; | ||
714 | } | ||
715 | return ret; | ||
716 | } | ||
717 | |||
718 | static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) | ||
719 | { | ||
720 | unsigned char buf[4]; | ||
721 | |||
722 | /* set new relative angle; angles are expressed in degrees * 100, | ||
723 | but cam as .5 degree resolution, hence divide by 200. Also | ||
724 | the angle must be multiplied by 64 before it's send to | ||
725 | the cam (??) | ||
726 | */ | ||
727 | pan = 64 * pan / 100; | ||
728 | tilt = -64 * tilt / 100; /* positive tilt is down, which is not what the user would expect */ | ||
729 | buf[0] = pan & 0xFF; | ||
730 | buf[1] = (pan >> 8) & 0xFF; | ||
731 | buf[2] = tilt & 0xFF; | ||
732 | buf[3] = (tilt >> 8) & 0xFF; | ||
733 | return send_control_msg(pdev, | ||
734 | SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, &buf, sizeof(buf)); | ||
735 | } | ||
736 | |||
737 | int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt) | ||
738 | { | ||
739 | int ret; | ||
740 | |||
741 | /* check absolute ranges */ | ||
742 | if (pan < pdev->angle_range.pan_min || | ||
743 | pan > pdev->angle_range.pan_max || | ||
744 | tilt < pdev->angle_range.tilt_min || | ||
745 | tilt > pdev->angle_range.tilt_max) | ||
746 | return -ERANGE; | ||
747 | |||
748 | /* go to relative range, check again */ | ||
749 | pan -= pdev->pan_angle; | ||
750 | tilt -= pdev->tilt_angle; | ||
751 | /* angles are specified in degrees * 100, thus the limit = 36000 */ | ||
752 | if (pan < -36000 || pan > 36000 || tilt < -36000 || tilt > 36000) | ||
753 | return -ERANGE; | ||
754 | |||
755 | ret = _pwc_mpt_set_angle(pdev, pan, tilt); | ||
756 | if (ret >= 0) { | ||
757 | pdev->pan_angle += pan; | ||
758 | pdev->tilt_angle += tilt; | ||
759 | } | ||
760 | if (ret == -EPIPE) /* stall -> out of range */ | ||
761 | ret = -ERANGE; | ||
762 | return ret; | ||
763 | } | ||
764 | |||
765 | static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status) | ||
766 | { | ||
767 | int ret; | ||
768 | unsigned char buf[5]; | ||
769 | |||
770 | ret = recv_control_msg(pdev, | ||
771 | GET_MPT_CTL, PT_STATUS_FORMATTER, &buf, sizeof(buf)); | ||
772 | if (ret < 0) | ||
773 | return ret; | ||
774 | status->status = buf[0] & 0x7; // 3 bits are used for reporting | ||
775 | status->time_pan = (buf[1] << 8) + buf[2]; | ||
776 | status->time_tilt = (buf[3] << 8) + buf[4]; | ||
777 | return 0; | ||
778 | } | ||
779 | |||
780 | #ifdef CONFIG_USB_PWC_DEBUG | 565 | #ifdef CONFIG_USB_PWC_DEBUG |
781 | int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) | 566 | int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) |
782 | { | 567 | { |
@@ -801,420 +586,3 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) | |||
801 | return 0; | 586 | return 0; |
802 | } | 587 | } |
803 | #endif | 588 | #endif |
804 | |||
805 | /* End of Add-Ons */ | ||
806 | /* ************************************************* */ | ||
807 | |||
808 | /* Linux 2.5.something and 2.6 pass direct pointers to arguments of | ||
809 | ioctl() calls. With 2.4, you have to do tedious copy_from_user() | ||
810 | and copy_to_user() calls. With these macros we circumvent this, | ||
811 | and let me maintain only one source file. The functionality is | ||
812 | exactly the same otherwise. | ||
813 | */ | ||
814 | |||
815 | /* define local variable for arg */ | ||
816 | #define ARG_DEF(ARG_type, ARG_name)\ | ||
817 | ARG_type *ARG_name = arg; | ||
818 | /* copy arg to local variable */ | ||
819 | #define ARG_IN(ARG_name) /* nothing */ | ||
820 | /* argument itself (referenced) */ | ||
821 | #define ARGR(ARG_name) (*ARG_name) | ||
822 | /* argument address */ | ||
823 | #define ARGA(ARG_name) ARG_name | ||
824 | /* copy local variable to arg */ | ||
825 | #define ARG_OUT(ARG_name) /* nothing */ | ||
826 | |||
827 | /* | ||
828 | * Our ctrls use native values, but the old custom pwc ioctl interface expects | ||
829 | * values from 0 - 65535, define 2 helper functions to scale things. */ | ||
830 | static int pwc_ioctl_g_ctrl(struct v4l2_ctrl *ctrl) | ||
831 | { | ||
832 | return v4l2_ctrl_g_ctrl(ctrl) * 65535 / ctrl->maximum; | ||
833 | } | ||
834 | |||
835 | static int pwc_ioctl_s_ctrl(struct v4l2_ctrl *ctrl, int val) | ||
836 | { | ||
837 | return v4l2_ctrl_s_ctrl(ctrl, val * ctrl->maximum / 65535); | ||
838 | } | ||
839 | |||
840 | long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) | ||
841 | { | ||
842 | long ret = 0; | ||
843 | |||
844 | switch(cmd) { | ||
845 | case VIDIOCPWCRUSER: | ||
846 | ret = pwc_button_ctrl(pdev, RESTORE_USER_DEFAULTS_FORMATTER); | ||
847 | break; | ||
848 | |||
849 | case VIDIOCPWCSUSER: | ||
850 | ret = pwc_button_ctrl(pdev, SAVE_USER_DEFAULTS_FORMATTER); | ||
851 | break; | ||
852 | |||
853 | case VIDIOCPWCFACTORY: | ||
854 | ret = pwc_button_ctrl(pdev, RESTORE_FACTORY_DEFAULTS_FORMATTER); | ||
855 | break; | ||
856 | |||
857 | case VIDIOCPWCSCQUAL: | ||
858 | { | ||
859 | ARG_DEF(int, qual) | ||
860 | |||
861 | if (vb2_is_streaming(&pdev->vb_queue)) { | ||
862 | ret = -EBUSY; | ||
863 | break; | ||
864 | } | ||
865 | |||
866 | ARG_IN(qual) | ||
867 | if (ARGR(qual) < 0 || ARGR(qual) > 3) | ||
868 | ret = -EINVAL; | ||
869 | else | ||
870 | ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot); | ||
871 | break; | ||
872 | } | ||
873 | |||
874 | case VIDIOCPWCGCQUAL: | ||
875 | { | ||
876 | ARG_DEF(int, qual) | ||
877 | |||
878 | ARGR(qual) = pdev->vcompression; | ||
879 | ARG_OUT(qual) | ||
880 | break; | ||
881 | } | ||
882 | |||
883 | case VIDIOCPWCPROBE: | ||
884 | { | ||
885 | ARG_DEF(struct pwc_probe, probe) | ||
886 | |||
887 | strcpy(ARGR(probe).name, pdev->vdev.name); | ||
888 | ARGR(probe).type = pdev->type; | ||
889 | ARG_OUT(probe) | ||
890 | break; | ||
891 | } | ||
892 | |||
893 | case VIDIOCPWCGSERIAL: | ||
894 | { | ||
895 | ARG_DEF(struct pwc_serial, serial) | ||
896 | |||
897 | strcpy(ARGR(serial).serial, pdev->serial); | ||
898 | ARG_OUT(serial) | ||
899 | break; | ||
900 | } | ||
901 | |||
902 | case VIDIOCPWCSAGC: | ||
903 | { | ||
904 | ARG_DEF(int, agc) | ||
905 | ARG_IN(agc) | ||
906 | ret = v4l2_ctrl_s_ctrl(pdev->autogain, ARGR(agc) < 0); | ||
907 | if (ret == 0 && ARGR(agc) >= 0) | ||
908 | ret = pwc_ioctl_s_ctrl(pdev->gain, ARGR(agc)); | ||
909 | break; | ||
910 | } | ||
911 | |||
912 | case VIDIOCPWCGAGC: | ||
913 | { | ||
914 | ARG_DEF(int, agc) | ||
915 | if (v4l2_ctrl_g_ctrl(pdev->autogain)) | ||
916 | ARGR(agc) = -1; | ||
917 | else | ||
918 | ARGR(agc) = pwc_ioctl_g_ctrl(pdev->gain); | ||
919 | ARG_OUT(agc) | ||
920 | break; | ||
921 | } | ||
922 | |||
923 | case VIDIOCPWCSSHUTTER: | ||
924 | { | ||
925 | ARG_DEF(int, shutter) | ||
926 | ARG_IN(shutter) | ||
927 | ret = v4l2_ctrl_s_ctrl(pdev->exposure_auto, | ||
928 | /* Menu idx 0 = auto, idx 1 = manual */ | ||
929 | ARGR(shutter) >= 0); | ||
930 | if (ret == 0 && ARGR(shutter) >= 0) | ||
931 | ret = pwc_ioctl_s_ctrl(pdev->exposure, ARGR(shutter)); | ||
932 | break; | ||
933 | } | ||
934 | |||
935 | case VIDIOCPWCSAWB: | ||
936 | { | ||
937 | ARG_DEF(struct pwc_whitebalance, wb) | ||
938 | ARG_IN(wb) | ||
939 | ret = v4l2_ctrl_s_ctrl(pdev->auto_white_balance, | ||
940 | ARGR(wb).mode); | ||
941 | if (ret == 0 && ARGR(wb).mode == PWC_WB_MANUAL) | ||
942 | ret = pwc_ioctl_s_ctrl(pdev->red_balance, | ||
943 | ARGR(wb).manual_red); | ||
944 | if (ret == 0 && ARGR(wb).mode == PWC_WB_MANUAL) | ||
945 | ret = pwc_ioctl_s_ctrl(pdev->blue_balance, | ||
946 | ARGR(wb).manual_blue); | ||
947 | break; | ||
948 | } | ||
949 | |||
950 | case VIDIOCPWCGAWB: | ||
951 | { | ||
952 | ARG_DEF(struct pwc_whitebalance, wb) | ||
953 | ARGR(wb).mode = v4l2_ctrl_g_ctrl(pdev->auto_white_balance); | ||
954 | ARGR(wb).manual_red = ARGR(wb).read_red = | ||
955 | pwc_ioctl_g_ctrl(pdev->red_balance); | ||
956 | ARGR(wb).manual_blue = ARGR(wb).read_blue = | ||
957 | pwc_ioctl_g_ctrl(pdev->blue_balance); | ||
958 | ARG_OUT(wb) | ||
959 | break; | ||
960 | } | ||
961 | |||
962 | case VIDIOCPWCSAWBSPEED: | ||
963 | { | ||
964 | ARG_DEF(struct pwc_wb_speed, wbs) | ||
965 | |||
966 | if (ARGR(wbs).control_speed > 0) { | ||
967 | ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed); | ||
968 | } | ||
969 | if (ARGR(wbs).control_delay > 0) { | ||
970 | ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay); | ||
971 | } | ||
972 | break; | ||
973 | } | ||
974 | |||
975 | case VIDIOCPWCGAWBSPEED: | ||
976 | { | ||
977 | ARG_DEF(struct pwc_wb_speed, wbs) | ||
978 | |||
979 | ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed); | ||
980 | if (ret < 0) | ||
981 | break; | ||
982 | ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay); | ||
983 | if (ret < 0) | ||
984 | break; | ||
985 | ARG_OUT(wbs) | ||
986 | break; | ||
987 | } | ||
988 | |||
989 | case VIDIOCPWCSLED: | ||
990 | { | ||
991 | ARG_DEF(struct pwc_leds, leds) | ||
992 | |||
993 | ARG_IN(leds) | ||
994 | ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off); | ||
995 | break; | ||
996 | } | ||
997 | |||
998 | |||
999 | case VIDIOCPWCGLED: | ||
1000 | { | ||
1001 | ARG_DEF(struct pwc_leds, leds) | ||
1002 | |||
1003 | ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off); | ||
1004 | ARG_OUT(leds) | ||
1005 | break; | ||
1006 | } | ||
1007 | |||
1008 | case VIDIOCPWCSCONTOUR: | ||
1009 | { | ||
1010 | ARG_DEF(int, contour) | ||
1011 | ARG_IN(contour) | ||
1012 | ret = v4l2_ctrl_s_ctrl(pdev->autocontour, ARGR(contour) < 0); | ||
1013 | if (ret == 0 && ARGR(contour) >= 0) | ||
1014 | ret = pwc_ioctl_s_ctrl(pdev->contour, ARGR(contour)); | ||
1015 | break; | ||
1016 | } | ||
1017 | |||
1018 | case VIDIOCPWCGCONTOUR: | ||
1019 | { | ||
1020 | ARG_DEF(int, contour) | ||
1021 | if (v4l2_ctrl_g_ctrl(pdev->autocontour)) | ||
1022 | ARGR(contour) = -1; | ||
1023 | else | ||
1024 | ARGR(contour) = pwc_ioctl_g_ctrl(pdev->contour); | ||
1025 | ARG_OUT(contour) | ||
1026 | break; | ||
1027 | } | ||
1028 | |||
1029 | case VIDIOCPWCSBACKLIGHT: | ||
1030 | { | ||
1031 | ARG_DEF(int, backlight) | ||
1032 | ARG_IN(backlight) | ||
1033 | ret = v4l2_ctrl_s_ctrl(pdev->backlight, ARGR(backlight)); | ||
1034 | break; | ||
1035 | } | ||
1036 | |||
1037 | case VIDIOCPWCGBACKLIGHT: | ||
1038 | { | ||
1039 | ARG_DEF(int, backlight) | ||
1040 | ARGR(backlight) = v4l2_ctrl_g_ctrl(pdev->backlight); | ||
1041 | ARG_OUT(backlight) | ||
1042 | break; | ||
1043 | } | ||
1044 | |||
1045 | case VIDIOCPWCSFLICKER: | ||
1046 | { | ||
1047 | ARG_DEF(int, flicker) | ||
1048 | ARG_IN(flicker) | ||
1049 | ret = v4l2_ctrl_s_ctrl(pdev->flicker, ARGR(flicker)); | ||
1050 | break; | ||
1051 | } | ||
1052 | |||
1053 | case VIDIOCPWCGFLICKER: | ||
1054 | { | ||
1055 | ARG_DEF(int, flicker) | ||
1056 | ARGR(flicker) = v4l2_ctrl_g_ctrl(pdev->flicker); | ||
1057 | ARG_OUT(flicker) | ||
1058 | break; | ||
1059 | } | ||
1060 | |||
1061 | case VIDIOCPWCSDYNNOISE: | ||
1062 | { | ||
1063 | ARG_DEF(int, dynnoise) | ||
1064 | ARG_IN(dynnoise) | ||
1065 | ret = v4l2_ctrl_s_ctrl(pdev->noise_reduction, ARGR(dynnoise)); | ||
1066 | break; | ||
1067 | } | ||
1068 | |||
1069 | case VIDIOCPWCGDYNNOISE: | ||
1070 | { | ||
1071 | ARG_DEF(int, dynnoise) | ||
1072 | ARGR(dynnoise) = v4l2_ctrl_g_ctrl(pdev->noise_reduction); | ||
1073 | ARG_OUT(dynnoise); | ||
1074 | break; | ||
1075 | } | ||
1076 | |||
1077 | case VIDIOCPWCGREALSIZE: | ||
1078 | { | ||
1079 | ARG_DEF(struct pwc_imagesize, size) | ||
1080 | |||
1081 | ARGR(size).width = pdev->image.x; | ||
1082 | ARGR(size).height = pdev->image.y; | ||
1083 | ARG_OUT(size) | ||
1084 | break; | ||
1085 | } | ||
1086 | |||
1087 | case VIDIOCPWCMPTRESET: | ||
1088 | { | ||
1089 | if (pdev->features & FEATURE_MOTOR_PANTILT) | ||
1090 | { | ||
1091 | ARG_DEF(int, flags) | ||
1092 | |||
1093 | ARG_IN(flags) | ||
1094 | ret = pwc_mpt_reset(pdev, ARGR(flags)); | ||
1095 | } | ||
1096 | else | ||
1097 | { | ||
1098 | ret = -ENXIO; | ||
1099 | } | ||
1100 | break; | ||
1101 | } | ||
1102 | |||
1103 | case VIDIOCPWCMPTGRANGE: | ||
1104 | { | ||
1105 | if (pdev->features & FEATURE_MOTOR_PANTILT) | ||
1106 | { | ||
1107 | ARG_DEF(struct pwc_mpt_range, range) | ||
1108 | |||
1109 | ARGR(range) = pdev->angle_range; | ||
1110 | ARG_OUT(range) | ||
1111 | } | ||
1112 | else | ||
1113 | { | ||
1114 | ret = -ENXIO; | ||
1115 | } | ||
1116 | break; | ||
1117 | } | ||
1118 | |||
1119 | case VIDIOCPWCMPTSANGLE: | ||
1120 | { | ||
1121 | int new_pan, new_tilt; | ||
1122 | |||
1123 | if (pdev->features & FEATURE_MOTOR_PANTILT) | ||
1124 | { | ||
1125 | ARG_DEF(struct pwc_mpt_angles, angles) | ||
1126 | |||
1127 | ARG_IN(angles) | ||
1128 | /* The camera can only set relative angles, so | ||
1129 | do some calculations when getting an absolute angle . | ||
1130 | */ | ||
1131 | if (ARGR(angles).absolute) | ||
1132 | { | ||
1133 | new_pan = ARGR(angles).pan; | ||
1134 | new_tilt = ARGR(angles).tilt; | ||
1135 | } | ||
1136 | else | ||
1137 | { | ||
1138 | new_pan = pdev->pan_angle + ARGR(angles).pan; | ||
1139 | new_tilt = pdev->tilt_angle + ARGR(angles).tilt; | ||
1140 | } | ||
1141 | ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt); | ||
1142 | } | ||
1143 | else | ||
1144 | { | ||
1145 | ret = -ENXIO; | ||
1146 | } | ||
1147 | break; | ||
1148 | } | ||
1149 | |||
1150 | case VIDIOCPWCMPTGANGLE: | ||
1151 | { | ||
1152 | |||
1153 | if (pdev->features & FEATURE_MOTOR_PANTILT) | ||
1154 | { | ||
1155 | ARG_DEF(struct pwc_mpt_angles, angles) | ||
1156 | |||
1157 | ARGR(angles).absolute = 1; | ||
1158 | ARGR(angles).pan = pdev->pan_angle; | ||
1159 | ARGR(angles).tilt = pdev->tilt_angle; | ||
1160 | ARG_OUT(angles) | ||
1161 | } | ||
1162 | else | ||
1163 | { | ||
1164 | ret = -ENXIO; | ||
1165 | } | ||
1166 | break; | ||
1167 | } | ||
1168 | |||
1169 | case VIDIOCPWCMPTSTATUS: | ||
1170 | { | ||
1171 | if (pdev->features & FEATURE_MOTOR_PANTILT) | ||
1172 | { | ||
1173 | ARG_DEF(struct pwc_mpt_status, status) | ||
1174 | |||
1175 | ret = pwc_mpt_get_status(pdev, ARGA(status)); | ||
1176 | ARG_OUT(status) | ||
1177 | } | ||
1178 | else | ||
1179 | { | ||
1180 | ret = -ENXIO; | ||
1181 | } | ||
1182 | break; | ||
1183 | } | ||
1184 | |||
1185 | case VIDIOCPWCGVIDCMD: | ||
1186 | { | ||
1187 | ARG_DEF(struct pwc_video_command, vcmd); | ||
1188 | |||
1189 | ARGR(vcmd).type = pdev->type; | ||
1190 | ARGR(vcmd).release = pdev->release; | ||
1191 | ARGR(vcmd).command_len = pdev->cmd_len; | ||
1192 | memcpy(&ARGR(vcmd).command_buf, pdev->cmd_buf, pdev->cmd_len); | ||
1193 | ARGR(vcmd).bandlength = pdev->vbandlength; | ||
1194 | ARGR(vcmd).frame_size = pdev->frame_size; | ||
1195 | ARG_OUT(vcmd) | ||
1196 | break; | ||
1197 | } | ||
1198 | /* | ||
1199 | case VIDIOCPWCGVIDTABLE: | ||
1200 | { | ||
1201 | ARG_DEF(struct pwc_table_init_buffer, table); | ||
1202 | ARGR(table).len = pdev->cmd_len; | ||
1203 | memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size); | ||
1204 | ARG_OUT(table) | ||
1205 | break; | ||
1206 | } | ||
1207 | */ | ||
1208 | |||
1209 | default: | ||
1210 | ret = -ENOIOCTLCMD; | ||
1211 | break; | ||
1212 | } | ||
1213 | |||
1214 | if (ret > 0) | ||
1215 | return 0; | ||
1216 | return ret; | ||
1217 | } | ||
1218 | |||
1219 | |||
1220 | /* vim: set cinoptions= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ | ||
diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/video/pwc/pwc-dec23.c index 06a4e877ba40..2c6709112b2f 100644 --- a/drivers/media/video/pwc/pwc-dec23.c +++ b/drivers/media/video/pwc/pwc-dec23.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include "pwc-timon.h" | 27 | #include "pwc-timon.h" |
28 | #include "pwc-kiara.h" | 28 | #include "pwc-kiara.h" |
29 | #include "pwc-dec23.h" | 29 | #include "pwc-dec23.h" |
30 | #include <media/pwc-ioctl.h> | ||
31 | 30 | ||
32 | #include <linux/string.h> | 31 | #include <linux/string.h> |
33 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
@@ -51,13 +50,6 @@ | |||
51 | # define USE_LOOKUP_TABLE_TO_CLAMP 1 | 50 | # define USE_LOOKUP_TABLE_TO_CLAMP 1 |
52 | #endif | 51 | #endif |
53 | 52 | ||
54 | /* | ||
55 | * ENABLE_BAYER_DECODER | ||
56 | * 0: bayer decoder is not build (save some space) | ||
57 | * 1: bayer decoder is build and can be used | ||
58 | */ | ||
59 | #define ENABLE_BAYER_DECODER 0 | ||
60 | |||
61 | static void build_subblock_pattern(struct pwc_dec23_private *pdec) | 53 | static void build_subblock_pattern(struct pwc_dec23_private *pdec) |
62 | { | 54 | { |
63 | static const unsigned int initial_values[12] = { | 55 | static const unsigned int initial_values[12] = { |
@@ -315,6 +307,8 @@ int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd) | |||
315 | } | 307 | } |
316 | pdec = pwc->decompress_data; | 308 | pdec = pwc->decompress_data; |
317 | 309 | ||
310 | mutex_init(&pdec->lock); | ||
311 | |||
318 | if (DEVICE_USE_CODEC3(type)) { | 312 | if (DEVICE_USE_CODEC3(type)) { |
319 | flags = cmd[2] & 0x18; | 313 | flags = cmd[2] & 0x18; |
320 | if (flags == 8) | 314 | if (flags == 8) |
@@ -467,123 +461,6 @@ static void copy_image_block_CrCb(const int *src, unsigned char *dst, unsigned i | |||
467 | #endif | 461 | #endif |
468 | } | 462 | } |
469 | 463 | ||
470 | #if ENABLE_BAYER_DECODER | ||
471 | /* | ||
472 | * Format: 8x2 pixels | ||
473 | * . G . G . G . G . G . G . G | ||
474 | * . . . . . . . . . . . . . . | ||
475 | * . G . G . G . G . G . G . G | ||
476 | * . . . . . . . . . . . . . . | ||
477 | * or | ||
478 | * . . . . . . . . . . . . . . | ||
479 | * G . G . G . G . G . G . G . | ||
480 | * . . . . . . . . . . . . . . | ||
481 | * G . G . G . G . G . G . G . | ||
482 | */ | ||
483 | static void copy_image_block_Green(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) | ||
484 | { | ||
485 | #if UNROLL_LOOP_FOR_COPY | ||
486 | /* Unroll all loops */ | ||
487 | const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; | ||
488 | unsigned char *d = dst; | ||
489 | const int *c = src; | ||
490 | |||
491 | d[0] = cm[c[0] >> scalebits]; | ||
492 | d[2] = cm[c[1] >> scalebits]; | ||
493 | d[4] = cm[c[2] >> scalebits]; | ||
494 | d[6] = cm[c[3] >> scalebits]; | ||
495 | d[8] = cm[c[4] >> scalebits]; | ||
496 | d[10] = cm[c[5] >> scalebits]; | ||
497 | d[12] = cm[c[6] >> scalebits]; | ||
498 | d[14] = cm[c[7] >> scalebits]; | ||
499 | |||
500 | d = dst + bytes_per_line; | ||
501 | d[0] = cm[c[8] >> scalebits]; | ||
502 | d[2] = cm[c[9] >> scalebits]; | ||
503 | d[4] = cm[c[10] >> scalebits]; | ||
504 | d[6] = cm[c[11] >> scalebits]; | ||
505 | d[8] = cm[c[12] >> scalebits]; | ||
506 | d[10] = cm[c[13] >> scalebits]; | ||
507 | d[12] = cm[c[14] >> scalebits]; | ||
508 | d[14] = cm[c[15] >> scalebits]; | ||
509 | #else | ||
510 | int i; | ||
511 | unsigned char *d; | ||
512 | const int *c = src; | ||
513 | |||
514 | d = dst; | ||
515 | for (i = 0; i < 8; i++, c++) | ||
516 | d[i*2] = CLAMP((*c) >> scalebits); | ||
517 | |||
518 | d = dst + bytes_per_line; | ||
519 | for (i = 0; i < 8; i++, c++) | ||
520 | d[i*2] = CLAMP((*c) >> scalebits); | ||
521 | #endif | ||
522 | } | ||
523 | #endif | ||
524 | |||
525 | #if ENABLE_BAYER_DECODER | ||
526 | /* | ||
527 | * Format: 4x4 pixels | ||
528 | * R . R . R . R | ||
529 | * . B . B . B . | ||
530 | * R . R . R . R | ||
531 | * . B . B . B . | ||
532 | */ | ||
533 | static void copy_image_block_RedBlue(const int *src, unsigned char *dst, unsigned int bytes_per_line, unsigned int scalebits) | ||
534 | { | ||
535 | #if UNROLL_LOOP_FOR_COPY | ||
536 | /* Unroll all loops */ | ||
537 | const unsigned char *cm = pwc_crop_table+MAX_OUTER_CROP_VALUE; | ||
538 | unsigned char *d = dst; | ||
539 | const int *c = src; | ||
540 | |||
541 | d[0] = cm[c[0] >> scalebits]; | ||
542 | d[2] = cm[c[1] >> scalebits]; | ||
543 | d[4] = cm[c[2] >> scalebits]; | ||
544 | d[6] = cm[c[3] >> scalebits]; | ||
545 | |||
546 | d = dst + bytes_per_line; | ||
547 | d[1] = cm[c[4] >> scalebits]; | ||
548 | d[3] = cm[c[5] >> scalebits]; | ||
549 | d[5] = cm[c[6] >> scalebits]; | ||
550 | d[7] = cm[c[7] >> scalebits]; | ||
551 | |||
552 | d = dst + bytes_per_line*2; | ||
553 | d[0] = cm[c[8] >> scalebits]; | ||
554 | d[2] = cm[c[9] >> scalebits]; | ||
555 | d[4] = cm[c[10] >> scalebits]; | ||
556 | d[6] = cm[c[11] >> scalebits]; | ||
557 | |||
558 | d = dst + bytes_per_line*3; | ||
559 | d[1] = cm[c[12] >> scalebits]; | ||
560 | d[3] = cm[c[13] >> scalebits]; | ||
561 | d[5] = cm[c[14] >> scalebits]; | ||
562 | d[7] = cm[c[15] >> scalebits]; | ||
563 | #else | ||
564 | int i; | ||
565 | unsigned char *d; | ||
566 | const int *c = src; | ||
567 | |||
568 | d = dst; | ||
569 | for (i = 0; i < 4; i++, c++) | ||
570 | d[i*2] = CLAMP((*c) >> scalebits); | ||
571 | |||
572 | d = dst + bytes_per_line; | ||
573 | for (i = 0; i < 4; i++, c++) | ||
574 | d[i*2+1] = CLAMP((*c) >> scalebits); | ||
575 | |||
576 | d = dst + bytes_per_line*2; | ||
577 | for (i = 0; i < 4; i++, c++) | ||
578 | d[i*2] = CLAMP((*c) >> scalebits); | ||
579 | |||
580 | d = dst + bytes_per_line*3; | ||
581 | for (i = 0; i < 4; i++, c++) | ||
582 | d[i*2+1] = CLAMP((*c) >> scalebits); | ||
583 | #endif | ||
584 | } | ||
585 | #endif | ||
586 | |||
587 | /* | 464 | /* |
588 | * To manage the stream, we keep bits in a 32 bits register. | 465 | * To manage the stream, we keep bits in a 32 bits register. |
589 | * fill_nbits(n): fill the reservoir with at least n bits | 466 | * fill_nbits(n): fill the reservoir with at least n bits |
@@ -775,146 +652,45 @@ static void DecompressBand23(struct pwc_dec23_private *pdec, | |||
775 | 652 | ||
776 | } | 653 | } |
777 | 654 | ||
778 | #if ENABLE_BAYER_DECODER | ||
779 | /* | ||
780 | * Size need to be a multiple of 8 in width | ||
781 | * | ||
782 | * Return a block of four line encoded like this: | ||
783 | * | ||
784 | * G R G R G R G R G R G R G R G R | ||
785 | * B G B G B G B G B G B G B G B G | ||
786 | * G R G R G R G R G R G R G R G R | ||
787 | * B G B G B G B G B G B G B G B G | ||
788 | * | ||
789 | */ | ||
790 | static void DecompressBandBayer(struct pwc_dec23_private *pdec, | ||
791 | const unsigned char *rawyuv, | ||
792 | unsigned char *rgbbayer, | ||
793 | unsigned int compressed_image_width, | ||
794 | unsigned int real_image_width) | ||
795 | { | ||
796 | int compression_index, nblocks; | ||
797 | const unsigned char *ptable0004; | ||
798 | const unsigned char *ptable8004; | ||
799 | unsigned char *dest; | ||
800 | |||
801 | pdec->reservoir = 0; | ||
802 | pdec->nbits_in_reservoir = 0; | ||
803 | pdec->stream = rawyuv + 1; /* The first byte of the stream is skipped */ | ||
804 | |||
805 | get_nbits(pdec, 4, compression_index); | ||
806 | |||
807 | /* pass 1: uncompress RB component */ | ||
808 | nblocks = compressed_image_width / 4; | ||
809 | |||
810 | ptable0004 = pdec->table_0004_pass1[compression_index]; | ||
811 | ptable8004 = pdec->table_8004_pass1[compression_index]; | ||
812 | dest = rgbbayer; | ||
813 | |||
814 | /* Each block decode a square of 4x4 */ | ||
815 | while (nblocks) { | ||
816 | decode_block(pdec, ptable0004, ptable8004); | ||
817 | copy_image_block_RedBlue(pdec->temp_colors, rgbbayer, real_image_width, pdec->scalebits); | ||
818 | dest += 8; | ||
819 | nblocks--; | ||
820 | } | ||
821 | |||
822 | /* pass 2: uncompress G component */ | ||
823 | nblocks = compressed_image_width / 8; | ||
824 | |||
825 | ptable0004 = pdec->table_0004_pass2[compression_index]; | ||
826 | ptable8004 = pdec->table_8004_pass2[compression_index]; | ||
827 | |||
828 | /* Each block decode a square of 4x4 */ | ||
829 | while (nblocks) { | ||
830 | decode_block(pdec, ptable0004, ptable8004); | ||
831 | copy_image_block_Green(pdec->temp_colors, rgbbayer+1, real_image_width, pdec->scalebits); | ||
832 | |||
833 | decode_block(pdec, ptable0004, ptable8004); | ||
834 | copy_image_block_Green(pdec->temp_colors, rgbbayer+real_image_width, real_image_width, pdec->scalebits); | ||
835 | |||
836 | rgbbayer += 16; | ||
837 | nblocks -= 2; | ||
838 | } | ||
839 | } | ||
840 | #endif | ||
841 | |||
842 | |||
843 | /** | 655 | /** |
844 | * | 656 | * |
845 | * Uncompress a pwc23 buffer. | 657 | * Uncompress a pwc23 buffer. |
846 | * | 658 | * |
847 | * pwc.view: size of the image wanted | ||
848 | * pwc.image: size of the image returned by the camera | ||
849 | * pwc.offset: (x,y) to displayer image in the view | ||
850 | * | ||
851 | * src: raw data | 659 | * src: raw data |
852 | * dst: image output | 660 | * dst: image output |
853 | * flags: PWCX_FLAG_PLANAR or PWCX_FLAG_BAYER | ||
854 | */ | 661 | */ |
855 | void pwc_dec23_decompress(const struct pwc_device *pwc, | 662 | void pwc_dec23_decompress(const struct pwc_device *pwc, |
856 | const void *src, | 663 | const void *src, |
857 | void *dst, | 664 | void *dst) |
858 | int flags) | ||
859 | { | 665 | { |
860 | int bandlines_left, stride, bytes_per_block; | 666 | int bandlines_left, bytes_per_block; |
861 | 667 | struct pwc_dec23_private *pdec = pwc->decompress_data; | |
862 | bandlines_left = pwc->image.y / 4; | 668 | |
863 | bytes_per_block = pwc->view.x * 4; | 669 | /* YUV420P image format */ |
864 | 670 | unsigned char *pout_planar_y; | |
865 | if (flags & PWCX_FLAG_BAYER) { | 671 | unsigned char *pout_planar_u; |
866 | #if ENABLE_BAYER_DECODER | 672 | unsigned char *pout_planar_v; |
867 | /* RGB Bayer format */ | 673 | unsigned int plane_size; |
868 | unsigned char *rgbout; | 674 | |
869 | 675 | mutex_lock(&pdec->lock); | |
870 | stride = pwc->view.x * pwc->offset.y; | 676 | |
871 | rgbout = dst + stride + pwc->offset.x; | 677 | bandlines_left = pwc->height / 4; |
872 | 678 | bytes_per_block = pwc->width * 4; | |
873 | 679 | plane_size = pwc->height * pwc->width; | |
874 | while (bandlines_left--) { | 680 | |
875 | 681 | pout_planar_y = dst; | |
876 | DecompressBandBayer(pwc->decompress_data, | 682 | pout_planar_u = dst + plane_size; |
877 | src, | 683 | pout_planar_v = dst + plane_size + plane_size / 4; |
878 | rgbout, | 684 | |
879 | pwc->image.x, pwc->view.x); | 685 | while (bandlines_left--) { |
880 | 686 | DecompressBand23(pwc->decompress_data, | |
881 | src += pwc->vbandlength; | 687 | src, |
882 | rgbout += bytes_per_block; | 688 | pout_planar_y, pout_planar_u, pout_planar_v, |
883 | 689 | pwc->width, pwc->width); | |
884 | } | 690 | src += pwc->vbandlength; |
885 | #else | 691 | pout_planar_y += bytes_per_block; |
886 | memset(dst, 0, pwc->view.x * pwc->view.y); | 692 | pout_planar_u += pwc->width; |
887 | #endif | 693 | pout_planar_v += pwc->width; |
888 | |||
889 | } else { | ||
890 | /* YUV420P image format */ | ||
891 | unsigned char *pout_planar_y; | ||
892 | unsigned char *pout_planar_u; | ||
893 | unsigned char *pout_planar_v; | ||
894 | unsigned int plane_size; | ||
895 | |||
896 | plane_size = pwc->view.x * pwc->view.y; | ||
897 | |||
898 | /* offset in Y plane */ | ||
899 | stride = pwc->view.x * pwc->offset.y; | ||
900 | pout_planar_y = dst + stride + pwc->offset.x; | ||
901 | |||
902 | /* offsets in U/V planes */ | ||
903 | stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2; | ||
904 | pout_planar_u = dst + plane_size + stride; | ||
905 | pout_planar_v = dst + plane_size + plane_size / 4 + stride; | ||
906 | |||
907 | while (bandlines_left--) { | ||
908 | |||
909 | DecompressBand23(pwc->decompress_data, | ||
910 | src, | ||
911 | pout_planar_y, pout_planar_u, pout_planar_v, | ||
912 | pwc->image.x, pwc->view.x); | ||
913 | src += pwc->vbandlength; | ||
914 | pout_planar_y += bytes_per_block; | ||
915 | pout_planar_u += pwc->view.x; | ||
916 | pout_planar_v += pwc->view.x; | ||
917 | |||
918 | } | ||
919 | } | 694 | } |
695 | mutex_unlock(&pdec->lock); | ||
920 | } | 696 | } |
diff --git a/drivers/media/video/pwc/pwc-dec23.h b/drivers/media/video/pwc/pwc-dec23.h index a0ac4f3dff81..d64a3c281af6 100644 --- a/drivers/media/video/pwc/pwc-dec23.h +++ b/drivers/media/video/pwc/pwc-dec23.h | |||
@@ -29,6 +29,8 @@ | |||
29 | 29 | ||
30 | struct pwc_dec23_private | 30 | struct pwc_dec23_private |
31 | { | 31 | { |
32 | struct mutex lock; | ||
33 | |||
32 | unsigned int scalebits; | 34 | unsigned int scalebits; |
33 | unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */ | 35 | unsigned int nbitsmask, nbits; /* Number of bits of a color in the compressed stream */ |
34 | 36 | ||
@@ -52,6 +54,5 @@ struct pwc_dec23_private | |||
52 | int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd); | 54 | int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd); |
53 | void pwc_dec23_decompress(const struct pwc_device *pwc, | 55 | void pwc_dec23_decompress(const struct pwc_device *pwc, |
54 | const void *src, | 56 | const void *src, |
55 | void *dst, | 57 | void *dst); |
56 | int flags); | ||
57 | #endif | 58 | #endif |
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 01ff643e682d..943d37ad0d33 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
@@ -134,7 +134,6 @@ static int default_fps = 10; | |||
134 | #endif | 134 | #endif |
135 | static int power_save = -1; | 135 | static int power_save = -1; |
136 | static int led_on = 100, led_off; /* defaults to LED that is on while in use */ | 136 | static int led_on = 100, led_off; /* defaults to LED that is on while in use */ |
137 | static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */ | ||
138 | static struct { | 137 | static struct { |
139 | int type; | 138 | int type; |
140 | char serial_number[30]; | 139 | char serial_number[30]; |
@@ -144,17 +143,15 @@ static struct { | |||
144 | 143 | ||
145 | /***/ | 144 | /***/ |
146 | 145 | ||
147 | static int pwc_video_open(struct file *file); | ||
148 | static int pwc_video_close(struct file *file); | 146 | static int pwc_video_close(struct file *file); |
149 | static ssize_t pwc_video_read(struct file *file, char __user *buf, | 147 | static ssize_t pwc_video_read(struct file *file, char __user *buf, |
150 | size_t count, loff_t *ppos); | 148 | size_t count, loff_t *ppos); |
151 | static unsigned int pwc_video_poll(struct file *file, poll_table *wait); | 149 | static unsigned int pwc_video_poll(struct file *file, poll_table *wait); |
152 | static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma); | 150 | static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma); |
153 | static void pwc_video_release(struct video_device *vfd); | ||
154 | 151 | ||
155 | static const struct v4l2_file_operations pwc_fops = { | 152 | static const struct v4l2_file_operations pwc_fops = { |
156 | .owner = THIS_MODULE, | 153 | .owner = THIS_MODULE, |
157 | .open = pwc_video_open, | 154 | .open = v4l2_fh_open, |
158 | .release = pwc_video_close, | 155 | .release = pwc_video_close, |
159 | .read = pwc_video_read, | 156 | .read = pwc_video_read, |
160 | .poll = pwc_video_poll, | 157 | .poll = pwc_video_poll, |
@@ -163,7 +160,7 @@ static const struct v4l2_file_operations pwc_fops = { | |||
163 | }; | 160 | }; |
164 | static struct video_device pwc_template = { | 161 | static struct video_device pwc_template = { |
165 | .name = "Philips Webcam", /* Filled in later */ | 162 | .name = "Philips Webcam", /* Filled in later */ |
166 | .release = pwc_video_release, | 163 | .release = video_device_release_empty, |
167 | .fops = &pwc_fops, | 164 | .fops = &pwc_fops, |
168 | .ioctl_ops = &pwc_ioctl_ops, | 165 | .ioctl_ops = &pwc_ioctl_ops, |
169 | }; | 166 | }; |
@@ -191,7 +188,6 @@ static void pwc_snapshot_button(struct pwc_device *pdev, int down) | |||
191 | { | 188 | { |
192 | if (down) { | 189 | if (down) { |
193 | PWC_TRACE("Snapshot button pressed.\n"); | 190 | PWC_TRACE("Snapshot button pressed.\n"); |
194 | pdev->snapshot_button_status = 1; | ||
195 | } else { | 191 | } else { |
196 | PWC_TRACE("Snapshot button released.\n"); | 192 | PWC_TRACE("Snapshot button released.\n"); |
197 | } | 193 | } |
@@ -375,6 +371,7 @@ static int pwc_isoc_init(struct pwc_device *pdev) | |||
375 | int i, j, ret; | 371 | int i, j, ret; |
376 | struct usb_interface *intf; | 372 | struct usb_interface *intf; |
377 | struct usb_host_interface *idesc = NULL; | 373 | struct usb_host_interface *idesc = NULL; |
374 | int compression = 0; /* 0..3 = uncompressed..high */ | ||
378 | 375 | ||
379 | if (pdev->iso_init) | 376 | if (pdev->iso_init) |
380 | return 0; | 377 | return 0; |
@@ -386,6 +383,12 @@ static int pwc_isoc_init(struct pwc_device *pdev) | |||
386 | pdev->visoc_errors = 0; | 383 | pdev->visoc_errors = 0; |
387 | udev = pdev->udev; | 384 | udev = pdev->udev; |
388 | 385 | ||
386 | retry: | ||
387 | /* We first try with low compression and then retry with a higher | ||
388 | compression setting if there is not enough bandwidth. */ | ||
389 | ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, | ||
390 | pdev->vframes, &compression); | ||
391 | |||
389 | /* Get the current alternate interface, adjust packet size */ | 392 | /* Get the current alternate interface, adjust packet size */ |
390 | intf = usb_ifnum_to_if(udev, 0); | 393 | intf = usb_ifnum_to_if(udev, 0); |
391 | if (intf) | 394 | if (intf) |
@@ -408,9 +411,12 @@ static int pwc_isoc_init(struct pwc_device *pdev) | |||
408 | } | 411 | } |
409 | 412 | ||
410 | /* Set alternate interface */ | 413 | /* Set alternate interface */ |
411 | ret = 0; | ||
412 | PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate); | 414 | PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate); |
413 | ret = usb_set_interface(pdev->udev, 0, pdev->valternate); | 415 | ret = usb_set_interface(pdev->udev, 0, pdev->valternate); |
416 | if (ret == -ENOSPC && compression < 3) { | ||
417 | compression++; | ||
418 | goto retry; | ||
419 | } | ||
414 | if (ret < 0) | 420 | if (ret < 0) |
415 | return ret; | 421 | return ret; |
416 | 422 | ||
@@ -454,6 +460,12 @@ static int pwc_isoc_init(struct pwc_device *pdev) | |||
454 | /* link */ | 460 | /* link */ |
455 | for (i = 0; i < MAX_ISO_BUFS; i++) { | 461 | for (i = 0; i < MAX_ISO_BUFS; i++) { |
456 | ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL); | 462 | ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL); |
463 | if (ret == -ENOSPC && compression < 3) { | ||
464 | compression++; | ||
465 | pdev->iso_init = 1; | ||
466 | pwc_isoc_cleanup(pdev); | ||
467 | goto retry; | ||
468 | } | ||
457 | if (ret) { | 469 | if (ret) { |
458 | PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret); | 470 | PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret); |
459 | pdev->iso_init = 1; | 471 | pdev->iso_init = 1; |
@@ -517,12 +529,11 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev) | |||
517 | PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n"); | 529 | PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n"); |
518 | } | 530 | } |
519 | 531 | ||
520 | /* | ||
521 | * Release all queued buffers, no need to take queued_bufs_lock, since all | ||
522 | * iso urbs have been killed when we're called so pwc_isoc_handler won't run. | ||
523 | */ | ||
524 | static void pwc_cleanup_queued_bufs(struct pwc_device *pdev) | 532 | static void pwc_cleanup_queued_bufs(struct pwc_device *pdev) |
525 | { | 533 | { |
534 | unsigned long flags = 0; | ||
535 | |||
536 | spin_lock_irqsave(&pdev->queued_bufs_lock, flags); | ||
526 | while (!list_empty(&pdev->queued_bufs)) { | 537 | while (!list_empty(&pdev->queued_bufs)) { |
527 | struct pwc_frame_buf *buf; | 538 | struct pwc_frame_buf *buf; |
528 | 539 | ||
@@ -531,84 +542,7 @@ static void pwc_cleanup_queued_bufs(struct pwc_device *pdev) | |||
531 | list_del(&buf->list); | 542 | list_del(&buf->list); |
532 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | 543 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); |
533 | } | 544 | } |
534 | } | 545 | spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags); |
535 | |||
536 | /********* | ||
537 | * sysfs | ||
538 | *********/ | ||
539 | static struct pwc_device *cd_to_pwc(struct device *cd) | ||
540 | { | ||
541 | struct video_device *vdev = to_video_device(cd); | ||
542 | return video_get_drvdata(vdev); | ||
543 | } | ||
544 | |||
545 | static ssize_t show_pan_tilt(struct device *class_dev, | ||
546 | struct device_attribute *attr, char *buf) | ||
547 | { | ||
548 | struct pwc_device *pdev = cd_to_pwc(class_dev); | ||
549 | return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle); | ||
550 | } | ||
551 | |||
552 | static ssize_t store_pan_tilt(struct device *class_dev, | ||
553 | struct device_attribute *attr, | ||
554 | const char *buf, size_t count) | ||
555 | { | ||
556 | struct pwc_device *pdev = cd_to_pwc(class_dev); | ||
557 | int pan, tilt; | ||
558 | int ret = -EINVAL; | ||
559 | |||
560 | if (strncmp(buf, "reset", 5) == 0) | ||
561 | ret = pwc_mpt_reset(pdev, 0x3); | ||
562 | |||
563 | else if (sscanf(buf, "%d %d", &pan, &tilt) > 0) | ||
564 | ret = pwc_mpt_set_angle(pdev, pan, tilt); | ||
565 | |||
566 | if (ret < 0) | ||
567 | return ret; | ||
568 | return strlen(buf); | ||
569 | } | ||
570 | static DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt, | ||
571 | store_pan_tilt); | ||
572 | |||
573 | static ssize_t show_snapshot_button_status(struct device *class_dev, | ||
574 | struct device_attribute *attr, char *buf) | ||
575 | { | ||
576 | struct pwc_device *pdev = cd_to_pwc(class_dev); | ||
577 | int status = pdev->snapshot_button_status; | ||
578 | pdev->snapshot_button_status = 0; | ||
579 | return sprintf(buf, "%d\n", status); | ||
580 | } | ||
581 | |||
582 | static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status, | ||
583 | NULL); | ||
584 | |||
585 | static int pwc_create_sysfs_files(struct pwc_device *pdev) | ||
586 | { | ||
587 | int rc; | ||
588 | |||
589 | rc = device_create_file(&pdev->vdev.dev, &dev_attr_button); | ||
590 | if (rc) | ||
591 | goto err; | ||
592 | if (pdev->features & FEATURE_MOTOR_PANTILT) { | ||
593 | rc = device_create_file(&pdev->vdev.dev, &dev_attr_pan_tilt); | ||
594 | if (rc) | ||
595 | goto err_button; | ||
596 | } | ||
597 | |||
598 | return 0; | ||
599 | |||
600 | err_button: | ||
601 | device_remove_file(&pdev->vdev.dev, &dev_attr_button); | ||
602 | err: | ||
603 | PWC_ERROR("Could not create sysfs files.\n"); | ||
604 | return rc; | ||
605 | } | ||
606 | |||
607 | static void pwc_remove_sysfs_files(struct pwc_device *pdev) | ||
608 | { | ||
609 | if (pdev->features & FEATURE_MOTOR_PANTILT) | ||
610 | device_remove_file(&pdev->vdev.dev, &dev_attr_pan_tilt); | ||
611 | device_remove_file(&pdev->vdev.dev, &dev_attr_button); | ||
612 | } | 546 | } |
613 | 547 | ||
614 | #ifdef CONFIG_USB_PWC_DEBUG | 548 | #ifdef CONFIG_USB_PWC_DEBUG |
@@ -644,25 +578,25 @@ static const char *pwc_sensor_type_to_string(unsigned int sensor_type) | |||
644 | /***************************************************************************/ | 578 | /***************************************************************************/ |
645 | /* Video4Linux functions */ | 579 | /* Video4Linux functions */ |
646 | 580 | ||
647 | static int pwc_video_open(struct file *file) | 581 | int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file) |
648 | { | 582 | { |
649 | struct video_device *vdev = video_devdata(file); | 583 | int r = 0; |
650 | struct pwc_device *pdev; | ||
651 | |||
652 | PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev); | ||
653 | 584 | ||
654 | pdev = video_get_drvdata(vdev); | 585 | mutex_lock(&pdev->capt_file_lock); |
655 | if (!pdev->udev) | 586 | if (pdev->capt_file != NULL && |
656 | return -ENODEV; | 587 | pdev->capt_file != file) { |
657 | 588 | r = -EBUSY; | |
658 | file->private_data = vdev; | 589 | goto leave; |
659 | PWC_DEBUG_OPEN("<< video_open() returns 0.\n"); | 590 | } |
660 | return 0; | 591 | pdev->capt_file = file; |
592 | leave: | ||
593 | mutex_unlock(&pdev->capt_file_lock); | ||
594 | return r; | ||
661 | } | 595 | } |
662 | 596 | ||
663 | static void pwc_video_release(struct video_device *vfd) | 597 | static void pwc_video_release(struct v4l2_device *v) |
664 | { | 598 | { |
665 | struct pwc_device *pdev = container_of(vfd, struct pwc_device, vdev); | 599 | struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev); |
666 | int hint; | 600 | int hint; |
667 | 601 | ||
668 | /* search device_hint[] table if we occupy a slot, by any chance */ | 602 | /* search device_hint[] table if we occupy a slot, by any chance */ |
@@ -685,44 +619,33 @@ static void pwc_video_release(struct video_device *vfd) | |||
685 | 619 | ||
686 | static int pwc_video_close(struct file *file) | 620 | static int pwc_video_close(struct file *file) |
687 | { | 621 | { |
688 | struct video_device *vdev = file->private_data; | 622 | struct pwc_device *pdev = video_drvdata(file); |
689 | struct pwc_device *pdev; | ||
690 | |||
691 | PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); | ||
692 | 623 | ||
693 | pdev = video_get_drvdata(vdev); | ||
694 | if (pdev->capt_file == file) { | 624 | if (pdev->capt_file == file) { |
695 | vb2_queue_release(&pdev->vb_queue); | 625 | vb2_queue_release(&pdev->vb_queue); |
696 | pdev->capt_file = NULL; | 626 | pdev->capt_file = NULL; |
697 | } | 627 | } |
698 | 628 | return v4l2_fh_release(file); | |
699 | PWC_DEBUG_OPEN("<< video_close()\n"); | ||
700 | return 0; | ||
701 | } | 629 | } |
702 | 630 | ||
703 | static ssize_t pwc_video_read(struct file *file, char __user *buf, | 631 | static ssize_t pwc_video_read(struct file *file, char __user *buf, |
704 | size_t count, loff_t *ppos) | 632 | size_t count, loff_t *ppos) |
705 | { | 633 | { |
706 | struct video_device *vdev = file->private_data; | 634 | struct pwc_device *pdev = video_drvdata(file); |
707 | struct pwc_device *pdev = video_get_drvdata(vdev); | ||
708 | 635 | ||
709 | if (!pdev->udev) | 636 | if (!pdev->udev) |
710 | return -ENODEV; | 637 | return -ENODEV; |
711 | 638 | ||
712 | if (pdev->capt_file != NULL && | 639 | if (pwc_test_n_set_capt_file(pdev, file)) |
713 | pdev->capt_file != file) | ||
714 | return -EBUSY; | 640 | return -EBUSY; |
715 | 641 | ||
716 | pdev->capt_file = file; | ||
717 | |||
718 | return vb2_read(&pdev->vb_queue, buf, count, ppos, | 642 | return vb2_read(&pdev->vb_queue, buf, count, ppos, |
719 | file->f_flags & O_NONBLOCK); | 643 | file->f_flags & O_NONBLOCK); |
720 | } | 644 | } |
721 | 645 | ||
722 | static unsigned int pwc_video_poll(struct file *file, poll_table *wait) | 646 | static unsigned int pwc_video_poll(struct file *file, poll_table *wait) |
723 | { | 647 | { |
724 | struct video_device *vdev = file->private_data; | 648 | struct pwc_device *pdev = video_drvdata(file); |
725 | struct pwc_device *pdev = video_get_drvdata(vdev); | ||
726 | 649 | ||
727 | if (!pdev->udev) | 650 | if (!pdev->udev) |
728 | return POLL_ERR; | 651 | return POLL_ERR; |
@@ -732,8 +655,7 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait) | |||
732 | 655 | ||
733 | static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) | 656 | static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma) |
734 | { | 657 | { |
735 | struct video_device *vdev = file->private_data; | 658 | struct pwc_device *pdev = video_drvdata(file); |
736 | struct pwc_device *pdev = video_get_drvdata(vdev); | ||
737 | 659 | ||
738 | if (pdev->capt_file != file) | 660 | if (pdev->capt_file != file) |
739 | return -EBUSY; | 661 | return -EBUSY; |
@@ -749,6 +671,7 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, | |||
749 | unsigned int sizes[], void *alloc_ctxs[]) | 671 | unsigned int sizes[], void *alloc_ctxs[]) |
750 | { | 672 | { |
751 | struct pwc_device *pdev = vb2_get_drv_priv(vq); | 673 | struct pwc_device *pdev = vb2_get_drv_priv(vq); |
674 | int size; | ||
752 | 675 | ||
753 | if (*nbuffers < MIN_FRAMES) | 676 | if (*nbuffers < MIN_FRAMES) |
754 | *nbuffers = MIN_FRAMES; | 677 | *nbuffers = MIN_FRAMES; |
@@ -757,7 +680,9 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, | |||
757 | 680 | ||
758 | *nplanes = 1; | 681 | *nplanes = 1; |
759 | 682 | ||
760 | sizes[0] = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2); | 683 | size = pwc_get_size(pdev, MAX_WIDTH, MAX_HEIGHT); |
684 | sizes[0] = PAGE_ALIGN(pwc_image_sizes[size][0] * | ||
685 | pwc_image_sizes[size][1] * 3 / 2); | ||
761 | 686 | ||
762 | return 0; | 687 | return 0; |
763 | } | 688 | } |
@@ -812,56 +737,59 @@ static void buffer_queue(struct vb2_buffer *vb) | |||
812 | unsigned long flags = 0; | 737 | unsigned long flags = 0; |
813 | 738 | ||
814 | spin_lock_irqsave(&pdev->queued_bufs_lock, flags); | 739 | spin_lock_irqsave(&pdev->queued_bufs_lock, flags); |
815 | list_add_tail(&buf->list, &pdev->queued_bufs); | 740 | /* Check the device has not disconnected between prep and queuing */ |
741 | if (pdev->udev) | ||
742 | list_add_tail(&buf->list, &pdev->queued_bufs); | ||
743 | else | ||
744 | vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR); | ||
816 | spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags); | 745 | spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags); |
817 | } | 746 | } |
818 | 747 | ||
819 | static int start_streaming(struct vb2_queue *vq, unsigned int count) | 748 | static int start_streaming(struct vb2_queue *vq, unsigned int count) |
820 | { | 749 | { |
821 | struct pwc_device *pdev = vb2_get_drv_priv(vq); | 750 | struct pwc_device *pdev = vb2_get_drv_priv(vq); |
751 | int r; | ||
822 | 752 | ||
823 | if (!pdev->udev) | 753 | mutex_lock(&pdev->udevlock); |
824 | return -ENODEV; | 754 | if (!pdev->udev) { |
755 | r = -ENODEV; | ||
756 | goto leave; | ||
757 | } | ||
825 | 758 | ||
826 | /* Turn on camera and set LEDS on */ | 759 | /* Turn on camera and set LEDS on */ |
827 | pwc_camera_power(pdev, 1); | 760 | pwc_camera_power(pdev, 1); |
828 | if (pdev->power_save) { | ||
829 | /* Restore video mode */ | ||
830 | pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, | ||
831 | pdev->vframes, pdev->vcompression, | ||
832 | pdev->vsnapshot); | ||
833 | } | ||
834 | pwc_set_leds(pdev, led_on, led_off); | 761 | pwc_set_leds(pdev, led_on, led_off); |
835 | 762 | ||
836 | return pwc_isoc_init(pdev); | 763 | r = pwc_isoc_init(pdev); |
764 | if (r) { | ||
765 | /* If we failed turn camera and LEDS back off */ | ||
766 | pwc_set_leds(pdev, 0, 0); | ||
767 | pwc_camera_power(pdev, 0); | ||
768 | /* And cleanup any queued bufs!! */ | ||
769 | pwc_cleanup_queued_bufs(pdev); | ||
770 | } | ||
771 | leave: | ||
772 | mutex_unlock(&pdev->udevlock); | ||
773 | return r; | ||
837 | } | 774 | } |
838 | 775 | ||
839 | static int stop_streaming(struct vb2_queue *vq) | 776 | static int stop_streaming(struct vb2_queue *vq) |
840 | { | 777 | { |
841 | struct pwc_device *pdev = vb2_get_drv_priv(vq); | 778 | struct pwc_device *pdev = vb2_get_drv_priv(vq); |
842 | 779 | ||
780 | mutex_lock(&pdev->udevlock); | ||
843 | if (pdev->udev) { | 781 | if (pdev->udev) { |
844 | pwc_set_leds(pdev, 0, 0); | 782 | pwc_set_leds(pdev, 0, 0); |
845 | pwc_camera_power(pdev, 0); | 783 | pwc_camera_power(pdev, 0); |
846 | pwc_isoc_cleanup(pdev); | 784 | pwc_isoc_cleanup(pdev); |
847 | } | 785 | } |
786 | mutex_unlock(&pdev->udevlock); | ||
787 | |||
848 | pwc_cleanup_queued_bufs(pdev); | 788 | pwc_cleanup_queued_bufs(pdev); |
849 | 789 | ||
850 | return 0; | 790 | return 0; |
851 | } | 791 | } |
852 | 792 | ||
853 | static void pwc_lock(struct vb2_queue *vq) | ||
854 | { | ||
855 | struct pwc_device *pdev = vb2_get_drv_priv(vq); | ||
856 | mutex_lock(&pdev->modlock); | ||
857 | } | ||
858 | |||
859 | static void pwc_unlock(struct vb2_queue *vq) | ||
860 | { | ||
861 | struct pwc_device *pdev = vb2_get_drv_priv(vq); | ||
862 | mutex_unlock(&pdev->modlock); | ||
863 | } | ||
864 | |||
865 | static struct vb2_ops pwc_vb_queue_ops = { | 793 | static struct vb2_ops pwc_vb_queue_ops = { |
866 | .queue_setup = queue_setup, | 794 | .queue_setup = queue_setup, |
867 | .buf_init = buffer_init, | 795 | .buf_init = buffer_init, |
@@ -871,8 +799,6 @@ static struct vb2_ops pwc_vb_queue_ops = { | |||
871 | .buf_queue = buffer_queue, | 799 | .buf_queue = buffer_queue, |
872 | .start_streaming = start_streaming, | 800 | .start_streaming = start_streaming, |
873 | .stop_streaming = stop_streaming, | 801 | .stop_streaming = stop_streaming, |
874 | .wait_prepare = pwc_unlock, | ||
875 | .wait_finish = pwc_lock, | ||
876 | }; | 802 | }; |
877 | 803 | ||
878 | /***************************************************************************/ | 804 | /***************************************************************************/ |
@@ -889,6 +815,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
889 | int vendor_id, product_id, type_id; | 815 | int vendor_id, product_id, type_id; |
890 | int hint, rc; | 816 | int hint, rc; |
891 | int features = 0; | 817 | int features = 0; |
818 | int compression = 0; | ||
892 | int video_nr = -1; /* default: use next available device */ | 819 | int video_nr = -1; /* default: use next available device */ |
893 | int my_power_save = power_save; | 820 | int my_power_save = power_save; |
894 | char serial_number[30], *name; | 821 | char serial_number[30], *name; |
@@ -1150,27 +1077,15 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1150 | } | 1077 | } |
1151 | pdev->type = type_id; | 1078 | pdev->type = type_id; |
1152 | pdev->vframes = default_fps; | 1079 | pdev->vframes = default_fps; |
1153 | strcpy(pdev->serial, serial_number); | ||
1154 | pdev->features = features; | 1080 | pdev->features = features; |
1155 | if (vendor_id == 0x046D && product_id == 0x08B5) { | ||
1156 | /* Logitech QuickCam Orbit | ||
1157 | The ranges have been determined experimentally; they may differ from cam to cam. | ||
1158 | Also, the exact ranges left-right and up-down are different for my cam | ||
1159 | */ | ||
1160 | pdev->angle_range.pan_min = -7000; | ||
1161 | pdev->angle_range.pan_max = 7000; | ||
1162 | pdev->angle_range.tilt_min = -3000; | ||
1163 | pdev->angle_range.tilt_max = 2500; | ||
1164 | } | ||
1165 | pwc_construct(pdev); /* set min/max sizes correct */ | 1081 | pwc_construct(pdev); /* set min/max sizes correct */ |
1166 | 1082 | ||
1167 | mutex_init(&pdev->modlock); | 1083 | mutex_init(&pdev->capt_file_lock); |
1168 | mutex_init(&pdev->udevlock); | 1084 | mutex_init(&pdev->udevlock); |
1169 | spin_lock_init(&pdev->queued_bufs_lock); | 1085 | spin_lock_init(&pdev->queued_bufs_lock); |
1170 | INIT_LIST_HEAD(&pdev->queued_bufs); | 1086 | INIT_LIST_HEAD(&pdev->queued_bufs); |
1171 | 1087 | ||
1172 | pdev->udev = udev; | 1088 | pdev->udev = udev; |
1173 | pdev->vcompression = pwc_preferred_compression; | ||
1174 | pdev->power_save = my_power_save; | 1089 | pdev->power_save = my_power_save; |
1175 | 1090 | ||
1176 | /* Init videobuf2 queue structure */ | 1091 | /* Init videobuf2 queue structure */ |
@@ -1185,9 +1100,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1185 | 1100 | ||
1186 | /* Init video_device structure */ | 1101 | /* Init video_device structure */ |
1187 | memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template)); | 1102 | memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template)); |
1188 | pdev->vdev.parent = &intf->dev; | ||
1189 | pdev->vdev.lock = &pdev->modlock; | ||
1190 | strcpy(pdev->vdev.name, name); | 1103 | strcpy(pdev->vdev.name, name); |
1104 | set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags); | ||
1191 | video_set_drvdata(&pdev->vdev, pdev); | 1105 | video_set_drvdata(&pdev->vdev, pdev); |
1192 | 1106 | ||
1193 | pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); | 1107 | pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); |
@@ -1211,9 +1125,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1211 | if (hint < MAX_DEV_HINTS) | 1125 | if (hint < MAX_DEV_HINTS) |
1212 | device_hint[hint].pdev = pdev; | 1126 | device_hint[hint].pdev = pdev; |
1213 | 1127 | ||
1214 | PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev); | ||
1215 | usb_set_intfdata(intf, pdev); | ||
1216 | |||
1217 | #ifdef CONFIG_USB_PWC_DEBUG | 1128 | #ifdef CONFIG_USB_PWC_DEBUG |
1218 | /* Query sensor type */ | 1129 | /* Query sensor type */ |
1219 | if (pwc_get_cmos_sensor(pdev, &rc) >= 0) { | 1130 | if (pwc_get_cmos_sensor(pdev, &rc) >= 0) { |
@@ -1227,8 +1138,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1227 | pwc_set_leds(pdev, 0, 0); | 1138 | pwc_set_leds(pdev, 0, 0); |
1228 | 1139 | ||
1229 | /* Setup intial videomode */ | 1140 | /* Setup intial videomode */ |
1230 | rc = pwc_set_video_mode(pdev, pdev->view_max.x, pdev->view_max.y, | 1141 | rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, pdev->vframes, |
1231 | pdev->vframes, pdev->vcompression, 0); | 1142 | &compression); |
1232 | if (rc) | 1143 | if (rc) |
1233 | goto err_free_mem; | 1144 | goto err_free_mem; |
1234 | 1145 | ||
@@ -1239,20 +1150,25 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1239 | goto err_free_mem; | 1150 | goto err_free_mem; |
1240 | } | 1151 | } |
1241 | 1152 | ||
1242 | pdev->vdev.ctrl_handler = &pdev->ctrl_handler; | ||
1243 | |||
1244 | /* And powerdown the camera until streaming starts */ | 1153 | /* And powerdown the camera until streaming starts */ |
1245 | pwc_camera_power(pdev, 0); | 1154 | pwc_camera_power(pdev, 0); |
1246 | 1155 | ||
1156 | /* Register the v4l2_device structure */ | ||
1157 | pdev->v4l2_dev.release = pwc_video_release; | ||
1158 | rc = v4l2_device_register(&intf->dev, &pdev->v4l2_dev); | ||
1159 | if (rc) { | ||
1160 | PWC_ERROR("Failed to register v4l2-device (%d).\n", rc); | ||
1161 | goto err_free_controls; | ||
1162 | } | ||
1163 | |||
1164 | pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler; | ||
1165 | pdev->vdev.v4l2_dev = &pdev->v4l2_dev; | ||
1166 | |||
1247 | rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr); | 1167 | rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr); |
1248 | if (rc < 0) { | 1168 | if (rc < 0) { |
1249 | PWC_ERROR("Failed to register as video device (%d).\n", rc); | 1169 | PWC_ERROR("Failed to register as video device (%d).\n", rc); |
1250 | goto err_free_controls; | 1170 | goto err_unregister_v4l2_dev; |
1251 | } | 1171 | } |
1252 | rc = pwc_create_sysfs_files(pdev); | ||
1253 | if (rc) | ||
1254 | goto err_video_unreg; | ||
1255 | |||
1256 | PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev)); | 1172 | PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev)); |
1257 | 1173 | ||
1258 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | 1174 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV |
@@ -1261,7 +1177,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1261 | if (!pdev->button_dev) { | 1177 | if (!pdev->button_dev) { |
1262 | PWC_ERROR("Err, insufficient memory for webcam snapshot button device."); | 1178 | PWC_ERROR("Err, insufficient memory for webcam snapshot button device."); |
1263 | rc = -ENOMEM; | 1179 | rc = -ENOMEM; |
1264 | pwc_remove_sysfs_files(pdev); | ||
1265 | goto err_video_unreg; | 1180 | goto err_video_unreg; |
1266 | } | 1181 | } |
1267 | 1182 | ||
@@ -1279,7 +1194,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1279 | if (rc) { | 1194 | if (rc) { |
1280 | input_free_device(pdev->button_dev); | 1195 | input_free_device(pdev->button_dev); |
1281 | pdev->button_dev = NULL; | 1196 | pdev->button_dev = NULL; |
1282 | pwc_remove_sysfs_files(pdev); | ||
1283 | goto err_video_unreg; | 1197 | goto err_video_unreg; |
1284 | } | 1198 | } |
1285 | #endif | 1199 | #endif |
@@ -1287,13 +1201,14 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1287 | return 0; | 1201 | return 0; |
1288 | 1202 | ||
1289 | err_video_unreg: | 1203 | err_video_unreg: |
1290 | if (hint < MAX_DEV_HINTS) | ||
1291 | device_hint[hint].pdev = NULL; | ||
1292 | video_unregister_device(&pdev->vdev); | 1204 | video_unregister_device(&pdev->vdev); |
1205 | err_unregister_v4l2_dev: | ||
1206 | v4l2_device_unregister(&pdev->v4l2_dev); | ||
1293 | err_free_controls: | 1207 | err_free_controls: |
1294 | v4l2_ctrl_handler_free(&pdev->ctrl_handler); | 1208 | v4l2_ctrl_handler_free(&pdev->ctrl_handler); |
1295 | err_free_mem: | 1209 | err_free_mem: |
1296 | usb_set_intfdata(intf, NULL); | 1210 | if (hint < MAX_DEV_HINTS) |
1211 | device_hint[hint].pdev = NULL; | ||
1297 | kfree(pdev); | 1212 | kfree(pdev); |
1298 | return rc; | 1213 | return rc; |
1299 | } | 1214 | } |
@@ -1301,27 +1216,26 @@ err_free_mem: | |||
1301 | /* The user yanked out the cable... */ | 1216 | /* The user yanked out the cable... */ |
1302 | static void usb_pwc_disconnect(struct usb_interface *intf) | 1217 | static void usb_pwc_disconnect(struct usb_interface *intf) |
1303 | { | 1218 | { |
1304 | struct pwc_device *pdev = usb_get_intfdata(intf); | 1219 | struct v4l2_device *v = usb_get_intfdata(intf); |
1220 | struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev); | ||
1305 | 1221 | ||
1306 | mutex_lock(&pdev->udevlock); | 1222 | mutex_lock(&pdev->udevlock); |
1307 | mutex_lock(&pdev->modlock); | ||
1308 | |||
1309 | usb_set_intfdata(intf, NULL); | ||
1310 | /* No need to keep the urbs around after disconnection */ | 1223 | /* No need to keep the urbs around after disconnection */ |
1311 | pwc_isoc_cleanup(pdev); | 1224 | pwc_isoc_cleanup(pdev); |
1312 | pwc_cleanup_queued_bufs(pdev); | ||
1313 | pdev->udev = NULL; | 1225 | pdev->udev = NULL; |
1314 | |||
1315 | mutex_unlock(&pdev->modlock); | ||
1316 | mutex_unlock(&pdev->udevlock); | 1226 | mutex_unlock(&pdev->udevlock); |
1317 | 1227 | ||
1318 | pwc_remove_sysfs_files(pdev); | 1228 | pwc_cleanup_queued_bufs(pdev); |
1229 | |||
1319 | video_unregister_device(&pdev->vdev); | 1230 | video_unregister_device(&pdev->vdev); |
1231 | v4l2_device_unregister(&pdev->v4l2_dev); | ||
1320 | 1232 | ||
1321 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | 1233 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV |
1322 | if (pdev->button_dev) | 1234 | if (pdev->button_dev) |
1323 | input_unregister_device(pdev->button_dev); | 1235 | input_unregister_device(pdev->button_dev); |
1324 | #endif | 1236 | #endif |
1237 | |||
1238 | v4l2_device_put(&pdev->v4l2_dev); | ||
1325 | } | 1239 | } |
1326 | 1240 | ||
1327 | 1241 | ||
@@ -1330,7 +1244,6 @@ static void usb_pwc_disconnect(struct usb_interface *intf) | |||
1330 | */ | 1244 | */ |
1331 | 1245 | ||
1332 | static int fps; | 1246 | static int fps; |
1333 | static int compression = -1; | ||
1334 | static int leds[2] = { -1, -1 }; | 1247 | static int leds[2] = { -1, -1 }; |
1335 | static unsigned int leds_nargs; | 1248 | static unsigned int leds_nargs; |
1336 | static char *dev_hint[MAX_DEV_HINTS]; | 1249 | static char *dev_hint[MAX_DEV_HINTS]; |
@@ -1341,7 +1254,6 @@ module_param(fps, int, 0444); | |||
1341 | module_param_named(trace, pwc_trace, int, 0644); | 1254 | module_param_named(trace, pwc_trace, int, 0644); |
1342 | #endif | 1255 | #endif |
1343 | module_param(power_save, int, 0644); | 1256 | module_param(power_save, int, 0644); |
1344 | module_param(compression, int, 0444); | ||
1345 | module_param_array(leds, int, &leds_nargs, 0444); | 1257 | module_param_array(leds, int, &leds_nargs, 0444); |
1346 | module_param_array(dev_hint, charp, &dev_hint_nargs, 0444); | 1258 | module_param_array(dev_hint, charp, &dev_hint_nargs, 0444); |
1347 | 1259 | ||
@@ -1350,7 +1262,6 @@ MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful rang | |||
1350 | MODULE_PARM_DESC(trace, "For debugging purposes"); | 1262 | MODULE_PARM_DESC(trace, "For debugging purposes"); |
1351 | #endif | 1263 | #endif |
1352 | MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off"); | 1264 | MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off"); |
1353 | MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)"); | ||
1354 | MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); | 1265 | MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); |
1355 | MODULE_PARM_DESC(dev_hint, "Device node hints"); | 1266 | MODULE_PARM_DESC(dev_hint, "Device node hints"); |
1356 | 1267 | ||
@@ -1384,14 +1295,6 @@ static int __init usb_pwc_init(void) | |||
1384 | PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps); | 1295 | PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps); |
1385 | } | 1296 | } |
1386 | 1297 | ||
1387 | if (compression >= 0) { | ||
1388 | if (compression > 3) { | ||
1389 | PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n"); | ||
1390 | return -EINVAL; | ||
1391 | } | ||
1392 | pwc_preferred_compression = compression; | ||
1393 | PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression); | ||
1394 | } | ||
1395 | if (leds[0] >= 0) | 1298 | if (leds[0] >= 0) |
1396 | led_on = leds[0]; | 1299 | led_on = leds[0]; |
1397 | if (leds[1] >= 0) | 1300 | if (leds[1] >= 0) |
diff --git a/drivers/media/video/pwc/pwc-kiara.h b/drivers/media/video/pwc/pwc-kiara.h index 047dad8c15f7..8e02b7ac2139 100644 --- a/drivers/media/video/pwc/pwc-kiara.h +++ b/drivers/media/video/pwc/pwc-kiara.h | |||
@@ -27,7 +27,7 @@ | |||
27 | #ifndef PWC_KIARA_H | 27 | #ifndef PWC_KIARA_H |
28 | #define PWC_KIARA_H | 28 | #define PWC_KIARA_H |
29 | 29 | ||
30 | #include <media/pwc-ioctl.h> | 30 | #include "pwc.h" |
31 | 31 | ||
32 | #define PWC_FPS_MAX_KIARA 6 | 32 | #define PWC_FPS_MAX_KIARA 6 |
33 | 33 | ||
diff --git a/drivers/media/video/pwc/pwc-misc.c b/drivers/media/video/pwc/pwc-misc.c index 0b031336eab8..23a55b5814fc 100644 --- a/drivers/media/video/pwc/pwc-misc.c +++ b/drivers/media/video/pwc/pwc-misc.c | |||
@@ -27,67 +27,47 @@ | |||
27 | 27 | ||
28 | #include "pwc.h" | 28 | #include "pwc.h" |
29 | 29 | ||
30 | const struct pwc_coord pwc_image_sizes[PSZ_MAX] = | 30 | const int pwc_image_sizes[PSZ_MAX][2] = |
31 | { | 31 | { |
32 | { 128, 96, 0 }, /* sqcif */ | 32 | { 128, 96 }, /* sqcif */ |
33 | { 160, 120, 0 }, /* qsif */ | 33 | { 160, 120 }, /* qsif */ |
34 | { 176, 144, 0 }, /* qcif */ | 34 | { 176, 144 }, /* qcif */ |
35 | { 320, 240, 0 }, /* sif */ | 35 | { 320, 240 }, /* sif */ |
36 | { 352, 288, 0 }, /* cif */ | 36 | { 352, 288 }, /* cif */ |
37 | { 640, 480, 0 }, /* vga */ | 37 | { 640, 480 }, /* vga */ |
38 | }; | 38 | }; |
39 | 39 | ||
40 | /* x,y -> PSZ_ */ | 40 | /* x,y -> PSZ_ */ |
41 | int pwc_decode_size(struct pwc_device *pdev, int width, int height) | 41 | int pwc_get_size(struct pwc_device *pdev, int width, int height) |
42 | { | 42 | { |
43 | int i, find; | 43 | int i; |
44 | |||
45 | /* Make sure we don't go beyond our max size. | ||
46 | NB: we have different limits for RAW and normal modes. In case | ||
47 | you don't have the decompressor loaded or use RAW mode, | ||
48 | the maximum viewable size is smaller. | ||
49 | */ | ||
50 | if (pdev->pixfmt != V4L2_PIX_FMT_YUV420) | ||
51 | { | ||
52 | if (width > pdev->abs_max.x || height > pdev->abs_max.y) | ||
53 | { | ||
54 | PWC_DEBUG_SIZE("VIDEO_PALETTE_RAW: going beyond abs_max.\n"); | ||
55 | return -1; | ||
56 | } | ||
57 | } | ||
58 | else | ||
59 | { | ||
60 | if (width > pdev->view_max.x || height > pdev->view_max.y) | ||
61 | { | ||
62 | PWC_DEBUG_SIZE("VIDEO_PALETTE_not RAW: going beyond view_max.\n"); | ||
63 | return -1; | ||
64 | } | ||
65 | } | ||
66 | 44 | ||
67 | /* Find the largest size supported by the camera that fits into the | 45 | /* Find the largest size supported by the camera that fits into the |
68 | requested size. | 46 | requested size. */ |
69 | */ | 47 | for (i = PSZ_MAX - 1; i >= 0; i--) { |
70 | find = -1; | 48 | if (!(pdev->image_mask & (1 << i))) |
49 | continue; | ||
50 | |||
51 | if (pwc_image_sizes[i][0] <= width && | ||
52 | pwc_image_sizes[i][1] <= height) | ||
53 | return i; | ||
54 | } | ||
55 | |||
56 | /* No mode found, return the smallest mode we have */ | ||
71 | for (i = 0; i < PSZ_MAX; i++) { | 57 | for (i = 0; i < PSZ_MAX; i++) { |
72 | if (pdev->image_mask & (1 << i)) { | 58 | if (pdev->image_mask & (1 << i)) |
73 | if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height) | 59 | return i; |
74 | find = i; | ||
75 | } | ||
76 | } | 60 | } |
77 | return find; | 61 | |
62 | /* Never reached there always is atleast one supported mode */ | ||
63 | return 0; | ||
78 | } | 64 | } |
79 | 65 | ||
80 | /* initialize variables depending on type and decompressor*/ | 66 | /* initialize variables depending on type and decompressor */ |
81 | void pwc_construct(struct pwc_device *pdev) | 67 | void pwc_construct(struct pwc_device *pdev) |
82 | { | 68 | { |
83 | if (DEVICE_USE_CODEC1(pdev->type)) { | 69 | if (DEVICE_USE_CODEC1(pdev->type)) { |
84 | 70 | ||
85 | pdev->view_min.x = 128; | ||
86 | pdev->view_min.y = 96; | ||
87 | pdev->view_max.x = 352; | ||
88 | pdev->view_max.y = 288; | ||
89 | pdev->abs_max.x = 352; | ||
90 | pdev->abs_max.y = 288; | ||
91 | pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF; | 71 | pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF; |
92 | pdev->vcinterface = 2; | 72 | pdev->vcinterface = 2; |
93 | pdev->vendpoint = 4; | 73 | pdev->vendpoint = 4; |
@@ -96,13 +76,7 @@ void pwc_construct(struct pwc_device *pdev) | |||
96 | 76 | ||
97 | } else if (DEVICE_USE_CODEC3(pdev->type)) { | 77 | } else if (DEVICE_USE_CODEC3(pdev->type)) { |
98 | 78 | ||
99 | pdev->view_min.x = 160; | ||
100 | pdev->view_min.y = 120; | ||
101 | pdev->view_max.x = 640; | ||
102 | pdev->view_max.y = 480; | ||
103 | pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA; | 79 | pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA; |
104 | pdev->abs_max.x = 640; | ||
105 | pdev->abs_max.y = 480; | ||
106 | pdev->vcinterface = 3; | 80 | pdev->vcinterface = 3; |
107 | pdev->vendpoint = 5; | 81 | pdev->vendpoint = 5; |
108 | pdev->frame_header_size = TOUCAM_HEADER_SIZE; | 82 | pdev->frame_header_size = TOUCAM_HEADER_SIZE; |
@@ -110,20 +84,11 @@ void pwc_construct(struct pwc_device *pdev) | |||
110 | 84 | ||
111 | } else /* if (DEVICE_USE_CODEC2(pdev->type)) */ { | 85 | } else /* if (DEVICE_USE_CODEC2(pdev->type)) */ { |
112 | 86 | ||
113 | pdev->view_min.x = 128; | ||
114 | pdev->view_min.y = 96; | ||
115 | /* Anthill bug #38: PWC always reports max size, even without PWCX */ | ||
116 | pdev->view_max.x = 640; | ||
117 | pdev->view_max.y = 480; | ||
118 | pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA; | 87 | pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA; |
119 | pdev->abs_max.x = 640; | ||
120 | pdev->abs_max.y = 480; | ||
121 | pdev->vcinterface = 3; | 88 | pdev->vcinterface = 3; |
122 | pdev->vendpoint = 4; | 89 | pdev->vendpoint = 4; |
123 | pdev->frame_header_size = 0; | 90 | pdev->frame_header_size = 0; |
124 | pdev->frame_trailer_size = 0; | 91 | pdev->frame_trailer_size = 0; |
125 | } | 92 | } |
126 | pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */ | 93 | pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */ |
127 | pdev->view_min.size = pdev->view_min.x * pdev->view_min.y; | ||
128 | pdev->view_max.size = pdev->view_max.x * pdev->view_max.y; | ||
129 | } | 94 | } |
diff --git a/drivers/media/video/pwc/pwc-timon.h b/drivers/media/video/pwc/pwc-timon.h index a6e22224c95f..270c5b9010f6 100644 --- a/drivers/media/video/pwc/pwc-timon.h +++ b/drivers/media/video/pwc/pwc-timon.h | |||
@@ -42,7 +42,7 @@ | |||
42 | #ifndef PWC_TIMON_H | 42 | #ifndef PWC_TIMON_H |
43 | #define PWC_TIMON_H | 43 | #define PWC_TIMON_H |
44 | 44 | ||
45 | #include <media/pwc-ioctl.h> | 45 | #include "pwc.h" |
46 | 46 | ||
47 | #define PWC_FPS_MAX_TIMON 6 | 47 | #define PWC_FPS_MAX_TIMON 6 |
48 | 48 | ||
diff --git a/drivers/media/video/pwc/pwc-uncompress.c b/drivers/media/video/pwc/pwc-uncompress.c index 51265092bd31..b65903fbcf0d 100644 --- a/drivers/media/video/pwc/pwc-uncompress.c +++ b/drivers/media/video/pwc/pwc-uncompress.c | |||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) | 36 | int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) |
37 | { | 37 | { |
38 | int n, line, col, stride; | 38 | int n, line, col; |
39 | void *yuv, *image; | 39 | void *yuv, *image; |
40 | u16 *src; | 40 | u16 *src; |
41 | u16 *dsty, *dstu, *dstv; | 41 | u16 *dsty, *dstu, *dstv; |
@@ -60,35 +60,23 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) | |||
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | vb2_set_plane_payload(&fbuf->vb, 0, pdev->view.size); | 63 | vb2_set_plane_payload(&fbuf->vb, 0, |
64 | pdev->width * pdev->height * 3 / 2); | ||
64 | 65 | ||
65 | if (pdev->vbandlength == 0) { | 66 | if (pdev->vbandlength == 0) { |
66 | /* Uncompressed mode. | 67 | /* Uncompressed mode. |
67 | * We copy the data into the output buffer, using the viewport | ||
68 | * size (which may be larger than the image size). | ||
69 | * Unfortunately we have to do a bit of byte stuffing to get | ||
70 | * the desired output format/size. | ||
71 | * | 68 | * |
72 | * We do some byte shuffling here to go from the | 69 | * We do some byte shuffling here to go from the |
73 | * native format to YUV420P. | 70 | * native format to YUV420P. |
74 | */ | 71 | */ |
75 | src = (u16 *)yuv; | 72 | src = (u16 *)yuv; |
76 | n = pdev->view.x * pdev->view.y; | 73 | n = pdev->width * pdev->height; |
74 | dsty = (u16 *)(image); | ||
75 | dstu = (u16 *)(image + n); | ||
76 | dstv = (u16 *)(image + n + n / 4); | ||
77 | 77 | ||
78 | /* offset in Y plane */ | 78 | for (line = 0; line < pdev->height; line++) { |
79 | stride = pdev->view.x * pdev->offset.y + pdev->offset.x; | 79 | for (col = 0; col < pdev->width; col += 4) { |
80 | dsty = (u16 *)(image + stride); | ||
81 | |||
82 | /* offsets in U/V planes */ | ||
83 | stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2; | ||
84 | dstu = (u16 *)(image + n + stride); | ||
85 | dstv = (u16 *)(image + n + n / 4 + stride); | ||
86 | |||
87 | /* increment after each line */ | ||
88 | stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */ | ||
89 | |||
90 | for (line = 0; line < pdev->image.y; line++) { | ||
91 | for (col = 0; col < pdev->image.x; col += 4) { | ||
92 | *dsty++ = *src++; | 80 | *dsty++ = *src++; |
93 | *dsty++ = *src++; | 81 | *dsty++ = *src++; |
94 | if (line & 1) | 82 | if (line & 1) |
@@ -96,11 +84,6 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) | |||
96 | else | 84 | else |
97 | *dstu++ = *src++; | 85 | *dstu++ = *src++; |
98 | } | 86 | } |
99 | dsty += stride; | ||
100 | if (line & 1) | ||
101 | dstv += (stride >> 1); | ||
102 | else | ||
103 | dstu += (stride >> 1); | ||
104 | } | 87 | } |
105 | 88 | ||
106 | return 0; | 89 | return 0; |
@@ -111,12 +94,6 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) | |||
111 | * the decompressor routines will write the data in planar format | 94 | * the decompressor routines will write the data in planar format |
112 | * immediately. | 95 | * immediately. |
113 | */ | 96 | */ |
114 | if (pdev->vsize == PSZ_VGA && pdev->vframes == 5 && pdev->vsnapshot) { | ||
115 | PWC_ERROR("Mode Bayer is not supported for now\n"); | ||
116 | /* flags |= PWCX_FLAG_BAYER; */ | ||
117 | return -ENXIO; /* No such device or address: missing decompressor */ | ||
118 | } | ||
119 | |||
120 | if (DEVICE_USE_CODEC1(pdev->type)) { | 97 | if (DEVICE_USE_CODEC1(pdev->type)) { |
121 | 98 | ||
122 | /* TODO & FIXME */ | 99 | /* TODO & FIXME */ |
@@ -124,10 +101,7 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) | |||
124 | return -ENXIO; /* No such device or address: missing decompressor */ | 101 | return -ENXIO; /* No such device or address: missing decompressor */ |
125 | 102 | ||
126 | } else { | 103 | } else { |
127 | pwc_dec23_decompress(pdev, yuv, image, PWCX_FLAG_PLANAR); | 104 | pwc_dec23_decompress(pdev, yuv, image); |
128 | } | 105 | } |
129 | return 0; | 106 | return 0; |
130 | } | 107 | } |
131 | |||
132 | |||
133 | /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ | ||
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index a10ff6b64acf..80e25842e84a 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c | |||
@@ -49,6 +49,7 @@ static const struct v4l2_ctrl_ops pwc_ctrl_ops = { | |||
49 | 49 | ||
50 | enum { awb_indoor, awb_outdoor, awb_fl, awb_manual, awb_auto }; | 50 | enum { awb_indoor, awb_outdoor, awb_fl, awb_manual, awb_auto }; |
51 | enum { custom_autocontour, custom_contour, custom_noise_reduction, | 51 | enum { custom_autocontour, custom_contour, custom_noise_reduction, |
52 | custom_awb_speed, custom_awb_delay, | ||
52 | custom_save_user, custom_restore_user, custom_restore_factory }; | 53 | custom_save_user, custom_restore_user, custom_restore_factory }; |
53 | 54 | ||
54 | const char * const pwc_auto_whitebal_qmenu[] = { | 55 | const char * const pwc_auto_whitebal_qmenu[] = { |
@@ -138,6 +139,26 @@ static const struct v4l2_ctrl_config pwc_restore_factory_cfg = { | |||
138 | .name = "Restore Factory Settings", | 139 | .name = "Restore Factory Settings", |
139 | }; | 140 | }; |
140 | 141 | ||
142 | static const struct v4l2_ctrl_config pwc_awb_speed_cfg = { | ||
143 | .ops = &pwc_ctrl_ops, | ||
144 | .id = PWC_CID_CUSTOM(awb_speed), | ||
145 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
146 | .name = "Auto White Balance Speed", | ||
147 | .min = 1, | ||
148 | .max = 32, | ||
149 | .step = 1, | ||
150 | }; | ||
151 | |||
152 | static const struct v4l2_ctrl_config pwc_awb_delay_cfg = { | ||
153 | .ops = &pwc_ctrl_ops, | ||
154 | .id = PWC_CID_CUSTOM(awb_delay), | ||
155 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
156 | .name = "Auto White Balance Delay", | ||
157 | .min = 0, | ||
158 | .max = 63, | ||
159 | .step = 1, | ||
160 | }; | ||
161 | |||
141 | int pwc_init_controls(struct pwc_device *pdev) | 162 | int pwc_init_controls(struct pwc_device *pdev) |
142 | { | 163 | { |
143 | struct v4l2_ctrl_handler *hdl; | 164 | struct v4l2_ctrl_handler *hdl; |
@@ -338,6 +359,23 @@ int pwc_init_controls(struct pwc_device *pdev) | |||
338 | if (pdev->restore_factory) | 359 | if (pdev->restore_factory) |
339 | pdev->restore_factory->flags |= V4L2_CTRL_FLAG_UPDATE; | 360 | pdev->restore_factory->flags |= V4L2_CTRL_FLAG_UPDATE; |
340 | 361 | ||
362 | /* Auto White Balance speed & delay */ | ||
363 | r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, | ||
364 | AWB_CONTROL_SPEED_FORMATTER, &def); | ||
365 | if (r || def < 1 || def > 32) | ||
366 | def = 1; | ||
367 | cfg = pwc_awb_speed_cfg; | ||
368 | cfg.def = def; | ||
369 | pdev->awb_speed = v4l2_ctrl_new_custom(hdl, &cfg, NULL); | ||
370 | |||
371 | r = pwc_get_u8_ctrl(pdev, GET_CHROM_CTL, | ||
372 | AWB_CONTROL_DELAY_FORMATTER, &def); | ||
373 | if (r || def > 63) | ||
374 | def = 0; | ||
375 | cfg = pwc_awb_delay_cfg; | ||
376 | cfg.def = def; | ||
377 | pdev->awb_delay = v4l2_ctrl_new_custom(hdl, &cfg, NULL); | ||
378 | |||
341 | if (!(pdev->features & FEATURE_MOTOR_PANTILT)) | 379 | if (!(pdev->features & FEATURE_MOTOR_PANTILT)) |
342 | return hdl->error; | 380 | return hdl->error; |
343 | 381 | ||
@@ -357,25 +395,16 @@ int pwc_init_controls(struct pwc_device *pdev) | |||
357 | return hdl->error; | 395 | return hdl->error; |
358 | } | 396 | } |
359 | 397 | ||
360 | static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f) | 398 | static void pwc_vidioc_fill_fmt(struct v4l2_format *f, |
399 | int width, int height, u32 pixfmt) | ||
361 | { | 400 | { |
362 | memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); | 401 | memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); |
363 | f->fmt.pix.width = pdev->view.x; | 402 | f->fmt.pix.width = width; |
364 | f->fmt.pix.height = pdev->view.y; | 403 | f->fmt.pix.height = height; |
365 | f->fmt.pix.field = V4L2_FIELD_NONE; | 404 | f->fmt.pix.field = V4L2_FIELD_NONE; |
366 | if (pdev->pixfmt == V4L2_PIX_FMT_YUV420) { | 405 | f->fmt.pix.pixelformat = pixfmt; |
367 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; | 406 | f->fmt.pix.bytesperline = f->fmt.pix.width; |
368 | f->fmt.pix.bytesperline = (f->fmt.pix.width * 3)/2; | 407 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.width * 3 / 2; |
369 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
370 | } else { | ||
371 | /* vbandlength contains 4 lines ... */ | ||
372 | f->fmt.pix.bytesperline = pdev->vbandlength/4; | ||
373 | f->fmt.pix.sizeimage = pdev->frame_size + sizeof(struct pwc_raw_frame); | ||
374 | if (DEVICE_USE_CODEC1(pdev->type)) | ||
375 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_PWC1; | ||
376 | else | ||
377 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_PWC2; | ||
378 | } | ||
379 | PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() " | 408 | PWC_DEBUG_IOCTL("pwc_vidioc_fill_fmt() " |
380 | "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n", | 409 | "width=%d, height=%d, bytesperline=%d, sizeimage=%d, pixelformat=%c%c%c%c\n", |
381 | f->fmt.pix.width, | 410 | f->fmt.pix.width, |
@@ -391,6 +420,8 @@ static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_forma | |||
391 | /* ioctl(VIDIOC_TRY_FMT) */ | 420 | /* ioctl(VIDIOC_TRY_FMT) */ |
392 | static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f) | 421 | static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f) |
393 | { | 422 | { |
423 | int size; | ||
424 | |||
394 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 425 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
395 | PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); | 426 | PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); |
396 | return -EINVAL; | 427 | return -EINVAL; |
@@ -417,15 +448,11 @@ static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f) | |||
417 | 448 | ||
418 | } | 449 | } |
419 | 450 | ||
420 | if (f->fmt.pix.width > pdev->view_max.x) | 451 | size = pwc_get_size(pdev, f->fmt.pix.width, f->fmt.pix.height); |
421 | f->fmt.pix.width = pdev->view_max.x; | 452 | pwc_vidioc_fill_fmt(f, |
422 | else if (f->fmt.pix.width < pdev->view_min.x) | 453 | pwc_image_sizes[size][0], |
423 | f->fmt.pix.width = pdev->view_min.x; | 454 | pwc_image_sizes[size][1], |
424 | 455 | f->fmt.pix.pixelformat); | |
425 | if (f->fmt.pix.height > pdev->view_max.y) | ||
426 | f->fmt.pix.height = pdev->view_max.y; | ||
427 | else if (f->fmt.pix.height < pdev->view_min.y) | ||
428 | f->fmt.pix.height = pdev->view_min.y; | ||
429 | 456 | ||
430 | return 0; | 457 | return 0; |
431 | } | 458 | } |
@@ -435,68 +462,50 @@ static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f) | |||
435 | static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) | 462 | static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) |
436 | { | 463 | { |
437 | struct pwc_device *pdev = video_drvdata(file); | 464 | struct pwc_device *pdev = video_drvdata(file); |
438 | int ret, fps, snapshot, compression, pixelformat; | 465 | int ret, pixelformat, compression = 0; |
439 | |||
440 | if (!pdev->udev) | ||
441 | return -ENODEV; | ||
442 | 466 | ||
443 | if (pdev->capt_file != NULL && | 467 | if (pwc_test_n_set_capt_file(pdev, file)) |
444 | pdev->capt_file != file) | ||
445 | return -EBUSY; | 468 | return -EBUSY; |
446 | 469 | ||
447 | pdev->capt_file = file; | ||
448 | |||
449 | ret = pwc_vidioc_try_fmt(pdev, f); | 470 | ret = pwc_vidioc_try_fmt(pdev, f); |
450 | if (ret<0) | 471 | if (ret < 0) |
451 | return ret; | 472 | return ret; |
452 | 473 | ||
453 | pixelformat = f->fmt.pix.pixelformat; | 474 | pixelformat = f->fmt.pix.pixelformat; |
454 | compression = pdev->vcompression; | ||
455 | snapshot = 0; | ||
456 | fps = pdev->vframes; | ||
457 | if (f->fmt.pix.priv) { | ||
458 | compression = (f->fmt.pix.priv & PWC_QLT_MASK) >> PWC_QLT_SHIFT; | ||
459 | snapshot = !!(f->fmt.pix.priv & PWC_FPS_SNAPSHOT); | ||
460 | fps = (f->fmt.pix.priv & PWC_FPS_FRMASK) >> PWC_FPS_SHIFT; | ||
461 | if (fps == 0) | ||
462 | fps = pdev->vframes; | ||
463 | } | ||
464 | 475 | ||
465 | if (pixelformat != V4L2_PIX_FMT_YUV420 && | 476 | mutex_lock(&pdev->udevlock); |
466 | pixelformat != V4L2_PIX_FMT_PWC1 && | 477 | if (!pdev->udev) { |
467 | pixelformat != V4L2_PIX_FMT_PWC2) | 478 | ret = -ENODEV; |
468 | return -EINVAL; | 479 | goto leave; |
480 | } | ||
469 | 481 | ||
470 | if (vb2_is_streaming(&pdev->vb_queue)) | 482 | if (pdev->iso_init) { |
471 | return -EBUSY; | 483 | ret = -EBUSY; |
484 | goto leave; | ||
485 | } | ||
472 | 486 | ||
473 | PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d " | 487 | PWC_DEBUG_IOCTL("Trying to set format to: width=%d height=%d fps=%d " |
474 | "compression=%d snapshot=%d format=%c%c%c%c\n", | 488 | "format=%c%c%c%c\n", |
475 | f->fmt.pix.width, f->fmt.pix.height, fps, | 489 | f->fmt.pix.width, f->fmt.pix.height, pdev->vframes, |
476 | compression, snapshot, | ||
477 | (pixelformat)&255, | 490 | (pixelformat)&255, |
478 | (pixelformat>>8)&255, | 491 | (pixelformat>>8)&255, |
479 | (pixelformat>>16)&255, | 492 | (pixelformat>>16)&255, |
480 | (pixelformat>>24)&255); | 493 | (pixelformat>>24)&255); |
481 | 494 | ||
482 | ret = pwc_set_video_mode(pdev, | 495 | ret = pwc_set_video_mode(pdev, f->fmt.pix.width, f->fmt.pix.height, |
483 | f->fmt.pix.width, | 496 | pdev->vframes, &compression); |
484 | f->fmt.pix.height, | ||
485 | fps, | ||
486 | compression, | ||
487 | snapshot); | ||
488 | 497 | ||
489 | PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret); | 498 | PWC_DEBUG_IOCTL("pwc_set_video_mode(), return=%d\n", ret); |
490 | 499 | ||
491 | if (ret) | 500 | if (ret == 0) { |
492 | return ret; | 501 | pdev->pixfmt = pixelformat; |
493 | 502 | pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, | |
494 | pdev->pixfmt = pixelformat; | 503 | pdev->pixfmt); |
495 | 504 | } | |
496 | pwc_vidioc_fill_fmt(pdev, f); | ||
497 | |||
498 | return 0; | ||
499 | 505 | ||
506 | leave: | ||
507 | mutex_unlock(&pdev->udevlock); | ||
508 | return ret; | ||
500 | } | 509 | } |
501 | 510 | ||
502 | static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) | 511 | static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) |
@@ -536,30 +545,14 @@ static int pwc_s_input(struct file *file, void *fh, unsigned int i) | |||
536 | return i ? -EINVAL : 0; | 545 | return i ? -EINVAL : 0; |
537 | } | 546 | } |
538 | 547 | ||
539 | static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | 548 | static int pwc_g_volatile_ctrl_unlocked(struct v4l2_ctrl *ctrl) |
540 | { | 549 | { |
541 | struct pwc_device *pdev = | 550 | struct pwc_device *pdev = |
542 | container_of(ctrl->handler, struct pwc_device, ctrl_handler); | 551 | container_of(ctrl->handler, struct pwc_device, ctrl_handler); |
543 | int ret = 0; | 552 | int ret = 0; |
544 | 553 | ||
545 | /* | 554 | if (!pdev->udev) |
546 | * Sometimes it can take quite long for the pwc to complete usb control | 555 | return -ENODEV; |
547 | * transfers, so release the modlock to give streaming by another | ||
548 | * process / thread the chance to continue with a dqbuf. | ||
549 | */ | ||
550 | mutex_unlock(&pdev->modlock); | ||
551 | |||
552 | /* | ||
553 | * Take the udev-lock to protect against the disconnect handler | ||
554 | * completing and setting dev->udev to NULL underneath us. Other code | ||
555 | * does not need to do this since it is protected by the modlock. | ||
556 | */ | ||
557 | mutex_lock(&pdev->udevlock); | ||
558 | |||
559 | if (!pdev->udev) { | ||
560 | ret = -ENODEV; | ||
561 | goto leave; | ||
562 | } | ||
563 | 556 | ||
564 | switch (ctrl->id) { | 557 | switch (ctrl->id) { |
565 | case V4L2_CID_AUTO_WHITE_BALANCE: | 558 | case V4L2_CID_AUTO_WHITE_BALANCE: |
@@ -624,9 +617,18 @@ static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | |||
624 | if (ret) | 617 | if (ret) |
625 | PWC_ERROR("g_ctrl %s error %d\n", ctrl->name, ret); | 618 | PWC_ERROR("g_ctrl %s error %d\n", ctrl->name, ret); |
626 | 619 | ||
627 | leave: | 620 | return ret; |
621 | } | ||
622 | |||
623 | static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | ||
624 | { | ||
625 | struct pwc_device *pdev = | ||
626 | container_of(ctrl->handler, struct pwc_device, ctrl_handler); | ||
627 | int ret; | ||
628 | |||
629 | mutex_lock(&pdev->udevlock); | ||
630 | ret = pwc_g_volatile_ctrl_unlocked(ctrl); | ||
628 | mutex_unlock(&pdev->udevlock); | 631 | mutex_unlock(&pdev->udevlock); |
629 | mutex_lock(&pdev->modlock); | ||
630 | return ret; | 632 | return ret; |
631 | } | 633 | } |
632 | 634 | ||
@@ -643,6 +645,15 @@ static int pwc_set_awb(struct pwc_device *pdev) | |||
643 | 645 | ||
644 | if (pdev->auto_white_balance->val != awb_manual) | 646 | if (pdev->auto_white_balance->val != awb_manual) |
645 | pdev->color_bal_valid = false; /* Force cache update */ | 647 | pdev->color_bal_valid = false; /* Force cache update */ |
648 | |||
649 | /* | ||
650 | * If this is a preset, update our red / blue balance values | ||
651 | * so that events get generated for the new preset values | ||
652 | */ | ||
653 | if (pdev->auto_white_balance->val == awb_indoor || | ||
654 | pdev->auto_white_balance->val == awb_outdoor || | ||
655 | pdev->auto_white_balance->val == awb_fl) | ||
656 | pwc_g_volatile_ctrl_unlocked(pdev->auto_white_balance); | ||
646 | } | 657 | } |
647 | if (pdev->auto_white_balance->val != awb_manual) | 658 | if (pdev->auto_white_balance->val != awb_manual) |
648 | return 0; | 659 | return 0; |
@@ -806,8 +817,6 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl) | |||
806 | container_of(ctrl->handler, struct pwc_device, ctrl_handler); | 817 | container_of(ctrl->handler, struct pwc_device, ctrl_handler); |
807 | int ret = 0; | 818 | int ret = 0; |
808 | 819 | ||
809 | /* See the comments on locking in pwc_g_volatile_ctrl */ | ||
810 | mutex_unlock(&pdev->modlock); | ||
811 | mutex_lock(&pdev->udevlock); | 820 | mutex_lock(&pdev->udevlock); |
812 | 821 | ||
813 | if (!pdev->udev) { | 822 | if (!pdev->udev) { |
@@ -891,6 +900,16 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl) | |||
891 | ret = pwc_button_ctrl(pdev, | 900 | ret = pwc_button_ctrl(pdev, |
892 | RESTORE_FACTORY_DEFAULTS_FORMATTER); | 901 | RESTORE_FACTORY_DEFAULTS_FORMATTER); |
893 | break; | 902 | break; |
903 | case PWC_CID_CUSTOM(awb_speed): | ||
904 | ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL, | ||
905 | AWB_CONTROL_SPEED_FORMATTER, | ||
906 | ctrl->val); | ||
907 | break; | ||
908 | case PWC_CID_CUSTOM(awb_delay): | ||
909 | ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL, | ||
910 | AWB_CONTROL_DELAY_FORMATTER, | ||
911 | ctrl->val); | ||
912 | break; | ||
894 | case V4L2_CID_PAN_RELATIVE: | 913 | case V4L2_CID_PAN_RELATIVE: |
895 | ret = pwc_set_motor(pdev); | 914 | ret = pwc_set_motor(pdev); |
896 | break; | 915 | break; |
@@ -903,7 +922,6 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl) | |||
903 | 922 | ||
904 | leave: | 923 | leave: |
905 | mutex_unlock(&pdev->udevlock); | 924 | mutex_unlock(&pdev->udevlock); |
906 | mutex_lock(&pdev->modlock); | ||
907 | return ret; | 925 | return ret; |
908 | } | 926 | } |
909 | 927 | ||
@@ -933,9 +951,14 @@ static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) | |||
933 | { | 951 | { |
934 | struct pwc_device *pdev = video_drvdata(file); | 952 | struct pwc_device *pdev = video_drvdata(file); |
935 | 953 | ||
954 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
955 | return -EINVAL; | ||
956 | |||
957 | mutex_lock(&pdev->udevlock); /* To avoid race with s_fmt */ | ||
936 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n", | 958 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n", |
937 | pdev->image.x, pdev->image.y); | 959 | pdev->width, pdev->height); |
938 | pwc_vidioc_fill_fmt(pdev, f); | 960 | pwc_vidioc_fill_fmt(f, pdev->width, pdev->height, pdev->pixfmt); |
961 | mutex_unlock(&pdev->udevlock); | ||
939 | return 0; | 962 | return 0; |
940 | } | 963 | } |
941 | 964 | ||
@@ -951,12 +974,9 @@ static int pwc_reqbufs(struct file *file, void *fh, | |||
951 | { | 974 | { |
952 | struct pwc_device *pdev = video_drvdata(file); | 975 | struct pwc_device *pdev = video_drvdata(file); |
953 | 976 | ||
954 | if (pdev->capt_file != NULL && | 977 | if (pwc_test_n_set_capt_file(pdev, file)) |
955 | pdev->capt_file != file) | ||
956 | return -EBUSY; | 978 | return -EBUSY; |
957 | 979 | ||
958 | pdev->capt_file = file; | ||
959 | |||
960 | return vb2_reqbufs(&pdev->vb_queue, rb); | 980 | return vb2_reqbufs(&pdev->vb_queue, rb); |
961 | } | 981 | } |
962 | 982 | ||
@@ -1025,25 +1045,21 @@ static int pwc_enum_framesizes(struct file *file, void *fh, | |||
1025 | struct pwc_device *pdev = video_drvdata(file); | 1045 | struct pwc_device *pdev = video_drvdata(file); |
1026 | unsigned int i = 0, index = fsize->index; | 1046 | unsigned int i = 0, index = fsize->index; |
1027 | 1047 | ||
1028 | if (fsize->pixel_format == V4L2_PIX_FMT_YUV420) { | 1048 | if (fsize->pixel_format == V4L2_PIX_FMT_YUV420 || |
1049 | (fsize->pixel_format == V4L2_PIX_FMT_PWC1 && | ||
1050 | DEVICE_USE_CODEC1(pdev->type)) || | ||
1051 | (fsize->pixel_format == V4L2_PIX_FMT_PWC2 && | ||
1052 | DEVICE_USE_CODEC23(pdev->type))) { | ||
1029 | for (i = 0; i < PSZ_MAX; i++) { | 1053 | for (i = 0; i < PSZ_MAX; i++) { |
1030 | if (pdev->image_mask & (1UL << i)) { | 1054 | if (!(pdev->image_mask & (1UL << i))) |
1031 | if (!index--) { | 1055 | continue; |
1032 | fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; | 1056 | if (!index--) { |
1033 | fsize->discrete.width = pwc_image_sizes[i].x; | 1057 | fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; |
1034 | fsize->discrete.height = pwc_image_sizes[i].y; | 1058 | fsize->discrete.width = pwc_image_sizes[i][0]; |
1035 | return 0; | 1059 | fsize->discrete.height = pwc_image_sizes[i][1]; |
1036 | } | 1060 | return 0; |
1037 | } | 1061 | } |
1038 | } | 1062 | } |
1039 | } else if (fsize->index == 0 && | ||
1040 | ((fsize->pixel_format == V4L2_PIX_FMT_PWC1 && DEVICE_USE_CODEC1(pdev->type)) || | ||
1041 | (fsize->pixel_format == V4L2_PIX_FMT_PWC2 && DEVICE_USE_CODEC23(pdev->type)))) { | ||
1042 | |||
1043 | fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; | ||
1044 | fsize->discrete.width = pdev->abs_max.x; | ||
1045 | fsize->discrete.height = pdev->abs_max.y; | ||
1046 | return 0; | ||
1047 | } | 1063 | } |
1048 | return -EINVAL; | 1064 | return -EINVAL; |
1049 | } | 1065 | } |
@@ -1056,8 +1072,8 @@ static int pwc_enum_frameintervals(struct file *file, void *fh, | |||
1056 | unsigned int i; | 1072 | unsigned int i; |
1057 | 1073 | ||
1058 | for (i = 0; i < PSZ_MAX; i++) { | 1074 | for (i = 0; i < PSZ_MAX; i++) { |
1059 | if (pwc_image_sizes[i].x == fival->width && | 1075 | if (pwc_image_sizes[i][0] == fival->width && |
1060 | pwc_image_sizes[i].y == fival->height) { | 1076 | pwc_image_sizes[i][1] == fival->height) { |
1061 | size = i; | 1077 | size = i; |
1062 | break; | 1078 | break; |
1063 | } | 1079 | } |
@@ -1086,14 +1102,6 @@ static int pwc_log_status(struct file *file, void *priv) | |||
1086 | return 0; | 1102 | return 0; |
1087 | } | 1103 | } |
1088 | 1104 | ||
1089 | static long pwc_default(struct file *file, void *fh, bool valid_prio, | ||
1090 | int cmd, void *arg) | ||
1091 | { | ||
1092 | struct pwc_device *pdev = video_drvdata(file); | ||
1093 | |||
1094 | return pwc_ioctl(pdev, cmd, arg); | ||
1095 | } | ||
1096 | |||
1097 | const struct v4l2_ioctl_ops pwc_ioctl_ops = { | 1105 | const struct v4l2_ioctl_ops pwc_ioctl_ops = { |
1098 | .vidioc_querycap = pwc_querycap, | 1106 | .vidioc_querycap = pwc_querycap, |
1099 | .vidioc_enum_input = pwc_enum_input, | 1107 | .vidioc_enum_input = pwc_enum_input, |
@@ -1112,8 +1120,4 @@ const struct v4l2_ioctl_ops pwc_ioctl_ops = { | |||
1112 | .vidioc_log_status = pwc_log_status, | 1120 | .vidioc_log_status = pwc_log_status, |
1113 | .vidioc_enum_framesizes = pwc_enum_framesizes, | 1121 | .vidioc_enum_framesizes = pwc_enum_framesizes, |
1114 | .vidioc_enum_frameintervals = pwc_enum_frameintervals, | 1122 | .vidioc_enum_frameintervals = pwc_enum_frameintervals, |
1115 | .vidioc_default = pwc_default, | ||
1116 | }; | 1123 | }; |
1117 | |||
1118 | |||
1119 | /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ | ||
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index 0e4e2d7b7872..47c518fef179 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h | |||
@@ -35,15 +35,16 @@ | |||
35 | #include <asm/errno.h> | 35 | #include <asm/errno.h> |
36 | #include <linux/videodev2.h> | 36 | #include <linux/videodev2.h> |
37 | #include <media/v4l2-common.h> | 37 | #include <media/v4l2-common.h> |
38 | #include <media/v4l2-device.h> | ||
38 | #include <media/v4l2-ioctl.h> | 39 | #include <media/v4l2-ioctl.h> |
39 | #include <media/v4l2-ctrls.h> | 40 | #include <media/v4l2-ctrls.h> |
41 | #include <media/v4l2-fh.h> | ||
42 | #include <media/v4l2-event.h> | ||
40 | #include <media/videobuf2-vmalloc.h> | 43 | #include <media/videobuf2-vmalloc.h> |
41 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | 44 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV |
42 | #include <linux/input.h> | 45 | #include <linux/input.h> |
43 | #endif | 46 | #endif |
44 | 47 | ||
45 | #include <media/pwc-ioctl.h> | ||
46 | |||
47 | /* Version block */ | 48 | /* Version block */ |
48 | #define PWC_VERSION "10.0.15" | 49 | #define PWC_VERSION "10.0.15" |
49 | #define PWC_NAME "pwc" | 50 | #define PWC_NAME "pwc" |
@@ -106,6 +107,9 @@ | |||
106 | #define FEATURE_CODEC1 0x0002 | 107 | #define FEATURE_CODEC1 0x0002 |
107 | #define FEATURE_CODEC2 0x0004 | 108 | #define FEATURE_CODEC2 0x0004 |
108 | 109 | ||
110 | #define MAX_WIDTH 640 | ||
111 | #define MAX_HEIGHT 480 | ||
112 | |||
109 | /* Ignore errors in the first N frames, to allow for startup delays */ | 113 | /* Ignore errors in the first N frames, to allow for startup delays */ |
110 | #define FRAME_LOWMARK 5 | 114 | #define FRAME_LOWMARK 5 |
111 | 115 | ||
@@ -186,6 +190,24 @@ | |||
186 | #define PT_RESET_CONTROL_FORMATTER 0x02 | 190 | #define PT_RESET_CONTROL_FORMATTER 0x02 |
187 | #define PT_STATUS_FORMATTER 0x03 | 191 | #define PT_STATUS_FORMATTER 0x03 |
188 | 192 | ||
193 | /* Enumeration of image sizes */ | ||
194 | #define PSZ_SQCIF 0x00 | ||
195 | #define PSZ_QSIF 0x01 | ||
196 | #define PSZ_QCIF 0x02 | ||
197 | #define PSZ_SIF 0x03 | ||
198 | #define PSZ_CIF 0x04 | ||
199 | #define PSZ_VGA 0x05 | ||
200 | #define PSZ_MAX 6 | ||
201 | |||
202 | struct pwc_raw_frame { | ||
203 | __le16 type; /* type of the webcam */ | ||
204 | __le16 vbandlength; /* Size of 4 lines compressed (used by the | ||
205 | decompressor) */ | ||
206 | __u8 cmd[4]; /* the four byte of the command (in case of | ||
207 | nala, only the first 3 bytes is filled) */ | ||
208 | __u8 rawframe[0]; /* frame_size = H / 4 * vbandlength */ | ||
209 | } __packed; | ||
210 | |||
189 | /* intermediate buffers with raw data from the USB cam */ | 211 | /* intermediate buffers with raw data from the USB cam */ |
190 | struct pwc_frame_buf | 212 | struct pwc_frame_buf |
191 | { | 213 | { |
@@ -198,33 +220,30 @@ struct pwc_frame_buf | |||
198 | struct pwc_device | 220 | struct pwc_device |
199 | { | 221 | { |
200 | struct video_device vdev; | 222 | struct video_device vdev; |
201 | struct mutex modlock; | 223 | struct v4l2_device v4l2_dev; |
202 | 224 | ||
203 | /* Pointer to our usb_device, may be NULL after unplug */ | 225 | /* Pointer to our usb_device, may be NULL after unplug */ |
204 | struct usb_device *udev; | 226 | struct usb_device *udev; |
205 | /* Protects the setting of udev to NULL by our disconnect handler */ | ||
206 | struct mutex udevlock; | 227 | struct mutex udevlock; |
207 | 228 | ||
208 | /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */ | 229 | /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */ |
209 | int type; | 230 | int type; |
210 | int release; /* release number */ | 231 | int release; /* release number */ |
211 | int features; /* feature bits */ | 232 | int features; /* feature bits */ |
212 | char serial[30]; /* serial number (string) */ | ||
213 | 233 | ||
214 | /*** Video data ***/ | 234 | /*** Video data ***/ |
215 | struct file *capt_file; /* file doing video capture */ | 235 | struct file *capt_file; /* file doing video capture */ |
236 | struct mutex capt_file_lock; | ||
216 | int vendpoint; /* video isoc endpoint */ | 237 | int vendpoint; /* video isoc endpoint */ |
217 | int vcinterface; /* video control interface */ | 238 | int vcinterface; /* video control interface */ |
218 | int valternate; /* alternate interface needed */ | 239 | int valternate; /* alternate interface needed */ |
219 | int vframes, vsize; /* frames-per-second & size (see PSZ_*) */ | 240 | int vframes; /* frames-per-second */ |
220 | int pixfmt; /* pixelformat: V4L2_PIX_FMT_YUV420 or _PWCX */ | 241 | int pixfmt; /* pixelformat: V4L2_PIX_FMT_YUV420 or _PWCX */ |
221 | int vframe_count; /* received frames */ | 242 | int vframe_count; /* received frames */ |
222 | int vmax_packet_size; /* USB maxpacket size */ | 243 | int vmax_packet_size; /* USB maxpacket size */ |
223 | int vlast_packet_size; /* for frame synchronisation */ | 244 | int vlast_packet_size; /* for frame synchronisation */ |
224 | int visoc_errors; /* number of contiguous ISOC errors */ | 245 | int visoc_errors; /* number of contiguous ISOC errors */ |
225 | int vcompression; /* desired compression factor */ | ||
226 | int vbandlength; /* compressed band length; 0 is uncompressed */ | 246 | int vbandlength; /* compressed band length; 0 is uncompressed */ |
227 | char vsnapshot; /* snapshot mode */ | ||
228 | char vsync; /* used by isoc handler */ | 247 | char vsync; /* used by isoc handler */ |
229 | char vmirror; /* for ToUCaM series */ | 248 | char vmirror; /* for ToUCaM series */ |
230 | char power_save; /* Do powersaving for this cam */ | 249 | char power_save; /* Do powersaving for this cam */ |
@@ -262,21 +281,8 @@ struct pwc_device | |||
262 | * a gray or black border. view_min <= image <= view <= view_max; | 281 | * a gray or black border. view_min <= image <= view <= view_max; |
263 | */ | 282 | */ |
264 | int image_mask; /* supported sizes */ | 283 | int image_mask; /* supported sizes */ |
265 | struct pwc_coord view_min, view_max; /* minimum and maximum view */ | 284 | int width, height; /* current resolution */ |
266 | struct pwc_coord abs_max; /* maximum supported size */ | ||
267 | struct pwc_coord image, view; /* image and viewport size */ | ||
268 | struct pwc_coord offset; /* offset of the viewport */ | ||
269 | |||
270 | /*** motorized pan/tilt feature */ | ||
271 | struct pwc_mpt_range angle_range; | ||
272 | int pan_angle; /* in degrees * 100 */ | ||
273 | int tilt_angle; /* absolute angle; 0,0 is home */ | ||
274 | 285 | ||
275 | /* | ||
276 | * Set to 1 when the user push the button, reset to 0 | ||
277 | * when this value is read from sysfs. | ||
278 | */ | ||
279 | int snapshot_button_status; | ||
280 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | 286 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV |
281 | struct input_dev *button_dev; /* webcam snapshot button input */ | 287 | struct input_dev *button_dev; /* webcam snapshot button input */ |
282 | char button_phys[64]; | 288 | char button_phys[64]; |
@@ -328,6 +334,8 @@ struct pwc_device | |||
328 | struct v4l2_ctrl *save_user; | 334 | struct v4l2_ctrl *save_user; |
329 | struct v4l2_ctrl *restore_user; | 335 | struct v4l2_ctrl *restore_user; |
330 | struct v4l2_ctrl *restore_factory; | 336 | struct v4l2_ctrl *restore_factory; |
337 | struct v4l2_ctrl *awb_speed; | ||
338 | struct v4l2_ctrl *awb_delay; | ||
331 | struct { | 339 | struct { |
332 | /* motor control cluster */ | 340 | /* motor control cluster */ |
333 | struct v4l2_ctrl *motor_pan; | 341 | struct v4l2_ctrl *motor_pan; |
@@ -344,19 +352,20 @@ struct pwc_device | |||
344 | extern int pwc_trace; | 352 | extern int pwc_trace; |
345 | #endif | 353 | #endif |
346 | 354 | ||
355 | int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file); | ||
356 | |||
347 | /** Functions in pwc-misc.c */ | 357 | /** Functions in pwc-misc.c */ |
348 | /* sizes in pixels */ | 358 | /* sizes in pixels */ |
349 | extern const struct pwc_coord pwc_image_sizes[PSZ_MAX]; | 359 | extern const int pwc_image_sizes[PSZ_MAX][2]; |
350 | 360 | ||
351 | int pwc_decode_size(struct pwc_device *pdev, int width, int height); | 361 | int pwc_get_size(struct pwc_device *pdev, int width, int height); |
352 | void pwc_construct(struct pwc_device *pdev); | 362 | void pwc_construct(struct pwc_device *pdev); |
353 | 363 | ||
354 | /** Functions in pwc-ctrl.c */ | 364 | /** Functions in pwc-ctrl.c */ |
355 | /* Request a certain video mode. Returns < 0 if not possible */ | 365 | /* Request a certain video mode. Returns < 0 if not possible */ |
356 | extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frames, int compression, int snapshot); | 366 | extern int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, |
367 | int frames, int *compression); | ||
357 | extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size); | 368 | extern unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned int size); |
358 | extern int pwc_mpt_reset(struct pwc_device *pdev, int flags); | ||
359 | extern int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt); | ||
360 | extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value); | 369 | extern int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value); |
361 | extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor); | 370 | extern int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor); |
362 | extern int send_control_msg(struct pwc_device *pdev, | 371 | extern int send_control_msg(struct pwc_device *pdev, |
@@ -375,9 +384,6 @@ int pwc_init_controls(struct pwc_device *pdev); | |||
375 | /* Power down or up the camera; not supported by all models */ | 384 | /* Power down or up the camera; not supported by all models */ |
376 | extern void pwc_camera_power(struct pwc_device *pdev, int power); | 385 | extern void pwc_camera_power(struct pwc_device *pdev, int power); |
377 | 386 | ||
378 | /* Private ioctl()s; see pwc-ioctl.h */ | ||
379 | extern long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg); | ||
380 | |||
381 | extern const struct v4l2_ioctl_ops pwc_ioctl_ops; | 387 | extern const struct v4l2_ioctl_ops pwc_ioctl_ops; |
382 | 388 | ||
383 | /** pwc-uncompress.c */ | 389 | /** pwc-uncompress.c */ |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 79fb22c89ae9..0bd7da26d018 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
@@ -1133,12 +1133,13 @@ static void pxa_camera_setup_cicr(struct soc_camera_device *icd, | |||
1133 | __raw_writel(cicr0, pcdev->base + CICR0); | 1133 | __raw_writel(cicr0, pcdev->base + CICR0); |
1134 | } | 1134 | } |
1135 | 1135 | ||
1136 | static int pxa_camera_set_bus_param(struct soc_camera_device *icd, __u32 pixfmt) | 1136 | static int pxa_camera_set_bus_param(struct soc_camera_device *icd) |
1137 | { | 1137 | { |
1138 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); | 1138 | struct v4l2_subdev *sd = soc_camera_to_subdev(icd); |
1139 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 1139 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
1140 | struct pxa_camera_dev *pcdev = ici->priv; | 1140 | struct pxa_camera_dev *pcdev = ici->priv; |
1141 | struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; | 1141 | struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; |
1142 | u32 pixfmt = icd->current_fmt->host_fmt->fourcc; | ||
1142 | unsigned long bus_flags, common_flags; | 1143 | unsigned long bus_flags, common_flags; |
1143 | int ret; | 1144 | int ret; |
1144 | struct pxa_cam *cam = icd->host_priv; | 1145 | struct pxa_cam *cam = icd->host_priv; |
@@ -1851,19 +1852,7 @@ static struct platform_driver pxa_camera_driver = { | |||
1851 | .remove = __devexit_p(pxa_camera_remove), | 1852 | .remove = __devexit_p(pxa_camera_remove), |
1852 | }; | 1853 | }; |
1853 | 1854 | ||
1854 | 1855 | module_platform_driver(pxa_camera_driver); | |
1855 | static int __init pxa_camera_init(void) | ||
1856 | { | ||
1857 | return platform_driver_register(&pxa_camera_driver); | ||
1858 | } | ||
1859 | |||
1860 | static void __exit pxa_camera_exit(void) | ||
1861 | { | ||
1862 | platform_driver_unregister(&pxa_camera_driver); | ||
1863 | } | ||
1864 | |||
1865 | module_init(pxa_camera_init); | ||
1866 | module_exit(pxa_camera_exit); | ||
1867 | 1856 | ||
1868 | MODULE_DESCRIPTION("PXA27x SoC Camera Host driver"); | 1857 | MODULE_DESCRIPTION("PXA27x SoC Camera Host driver"); |
1869 | MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); | 1858 | MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); |
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c index 2cc3b9166724..510cfab477ff 100644 --- a/drivers/media/video/s5p-fimc/fimc-capture.c +++ b/drivers/media/video/s5p-fimc/fimc-capture.c | |||
@@ -63,6 +63,8 @@ static int fimc_init_capture(struct fimc_dev *fimc) | |||
63 | fimc_hw_set_effect(ctx, false); | 63 | fimc_hw_set_effect(ctx, false); |
64 | fimc_hw_set_output_path(ctx); | 64 | fimc_hw_set_output_path(ctx); |
65 | fimc_hw_set_out_dma(ctx); | 65 | fimc_hw_set_out_dma(ctx); |
66 | if (fimc->variant->has_alpha) | ||
67 | fimc_hw_set_rgb_alpha(ctx); | ||
66 | clear_bit(ST_CAPT_APPLY_CFG, &fimc->state); | 68 | clear_bit(ST_CAPT_APPLY_CFG, &fimc->state); |
67 | } | 69 | } |
68 | spin_unlock_irqrestore(&fimc->slock, flags); | 70 | spin_unlock_irqrestore(&fimc->slock, flags); |
@@ -154,6 +156,8 @@ int fimc_capture_config_update(struct fimc_ctx *ctx) | |||
154 | fimc_hw_set_rotation(ctx); | 156 | fimc_hw_set_rotation(ctx); |
155 | fimc_prepare_dma_offset(ctx, &ctx->d_frame); | 157 | fimc_prepare_dma_offset(ctx, &ctx->d_frame); |
156 | fimc_hw_set_out_dma(ctx); | 158 | fimc_hw_set_out_dma(ctx); |
159 | if (fimc->variant->has_alpha) | ||
160 | fimc_hw_set_rgb_alpha(ctx); | ||
157 | clear_bit(ST_CAPT_APPLY_CFG, &fimc->state); | 161 | clear_bit(ST_CAPT_APPLY_CFG, &fimc->state); |
158 | } | 162 | } |
159 | spin_unlock(&ctx->slock); | 163 | spin_unlock(&ctx->slock); |
@@ -812,6 +816,10 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f) | |||
812 | FIMC_SD_PAD_SOURCE); | 816 | FIMC_SD_PAD_SOURCE); |
813 | if (!ff->fmt) | 817 | if (!ff->fmt) |
814 | return -EINVAL; | 818 | return -EINVAL; |
819 | |||
820 | /* Update RGB Alpha control state and value range */ | ||
821 | fimc_alpha_ctrl_update(ctx); | ||
822 | |||
815 | /* Try to match format at the host and the sensor */ | 823 | /* Try to match format at the host and the sensor */ |
816 | if (!fimc->vid_cap.user_subdev_api) { | 824 | if (!fimc->vid_cap.user_subdev_api) { |
817 | mf->code = ff->fmt->mbus_code; | 825 | mf->code = ff->fmt->mbus_code; |
@@ -1235,6 +1243,9 @@ static int fimc_subdev_set_fmt(struct v4l2_subdev *sd, | |||
1235 | *mf = fmt->format; | 1243 | *mf = fmt->format; |
1236 | return 0; | 1244 | return 0; |
1237 | } | 1245 | } |
1246 | /* Update RGB Alpha control state and value range */ | ||
1247 | fimc_alpha_ctrl_update(ctx); | ||
1248 | |||
1238 | fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ffmt->color)); | 1249 | fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ffmt->color)); |
1239 | 1250 | ||
1240 | ff = fmt->pad == FIMC_SD_PAD_SINK ? | 1251 | ff = fmt->pad == FIMC_SD_PAD_SINK ? |
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index 07c6254faee3..f5cbb8a4c540 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c | |||
@@ -52,13 +52,29 @@ static struct fimc_fmt fimc_formats[] = { | |||
52 | .colplanes = 1, | 52 | .colplanes = 1, |
53 | .flags = FMT_FLAGS_M2M, | 53 | .flags = FMT_FLAGS_M2M, |
54 | }, { | 54 | }, { |
55 | .name = "XRGB-8-8-8-8, 32 bpp", | 55 | .name = "ARGB8888, 32 bpp", |
56 | .fourcc = V4L2_PIX_FMT_RGB32, | 56 | .fourcc = V4L2_PIX_FMT_RGB32, |
57 | .depth = { 32 }, | 57 | .depth = { 32 }, |
58 | .color = S5P_FIMC_RGB888, | 58 | .color = S5P_FIMC_RGB888, |
59 | .memplanes = 1, | 59 | .memplanes = 1, |
60 | .colplanes = 1, | 60 | .colplanes = 1, |
61 | .flags = FMT_FLAGS_M2M, | 61 | .flags = FMT_FLAGS_M2M | FMT_HAS_ALPHA, |
62 | }, { | ||
63 | .name = "ARGB1555", | ||
64 | .fourcc = V4L2_PIX_FMT_RGB555, | ||
65 | .depth = { 16 }, | ||
66 | .color = S5P_FIMC_RGB555, | ||
67 | .memplanes = 1, | ||
68 | .colplanes = 1, | ||
69 | .flags = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA, | ||
70 | }, { | ||
71 | .name = "ARGB4444", | ||
72 | .fourcc = V4L2_PIX_FMT_RGB444, | ||
73 | .depth = { 16 }, | ||
74 | .color = S5P_FIMC_RGB444, | ||
75 | .memplanes = 1, | ||
76 | .colplanes = 1, | ||
77 | .flags = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA, | ||
62 | }, { | 78 | }, { |
63 | .name = "YUV 4:2:2 packed, YCbYCr", | 79 | .name = "YUV 4:2:2 packed, YCbYCr", |
64 | .fourcc = V4L2_PIX_FMT_YUYV, | 80 | .fourcc = V4L2_PIX_FMT_YUYV, |
@@ -171,6 +187,14 @@ static struct fimc_fmt fimc_formats[] = { | |||
171 | }, | 187 | }, |
172 | }; | 188 | }; |
173 | 189 | ||
190 | static unsigned int get_m2m_fmt_flags(unsigned int stream_type) | ||
191 | { | ||
192 | if (stream_type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) | ||
193 | return FMT_FLAGS_M2M_IN; | ||
194 | else | ||
195 | return FMT_FLAGS_M2M_OUT; | ||
196 | } | ||
197 | |||
174 | int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh, | 198 | int fimc_check_scaler_ratio(struct fimc_ctx *ctx, int sw, int sh, |
175 | int dw, int dh, int rotation) | 199 | int dw, int dh, int rotation) |
176 | { | 200 | { |
@@ -652,8 +676,11 @@ static void fimc_dma_run(void *priv) | |||
652 | if (ctx->state & (FIMC_DST_ADDR | FIMC_PARAMS)) | 676 | if (ctx->state & (FIMC_DST_ADDR | FIMC_PARAMS)) |
653 | fimc_hw_set_output_addr(fimc, &ctx->d_frame.paddr, -1); | 677 | fimc_hw_set_output_addr(fimc, &ctx->d_frame.paddr, -1); |
654 | 678 | ||
655 | if (ctx->state & FIMC_PARAMS) | 679 | if (ctx->state & FIMC_PARAMS) { |
656 | fimc_hw_set_out_dma(ctx); | 680 | fimc_hw_set_out_dma(ctx); |
681 | if (fimc->variant->has_alpha) | ||
682 | fimc_hw_set_rgb_alpha(ctx); | ||
683 | } | ||
657 | 684 | ||
658 | fimc_activate_capture(ctx); | 685 | fimc_activate_capture(ctx); |
659 | 686 | ||
@@ -750,12 +777,11 @@ static struct vb2_ops fimc_qops = { | |||
750 | #define ctrl_to_ctx(__ctrl) \ | 777 | #define ctrl_to_ctx(__ctrl) \ |
751 | container_of((__ctrl)->handler, struct fimc_ctx, ctrl_handler) | 778 | container_of((__ctrl)->handler, struct fimc_ctx, ctrl_handler) |
752 | 779 | ||
753 | static int fimc_s_ctrl(struct v4l2_ctrl *ctrl) | 780 | static int __fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_ctrl *ctrl) |
754 | { | 781 | { |
755 | struct fimc_ctx *ctx = ctrl_to_ctx(ctrl); | ||
756 | struct fimc_dev *fimc = ctx->fimc_dev; | 782 | struct fimc_dev *fimc = ctx->fimc_dev; |
757 | struct samsung_fimc_variant *variant = fimc->variant; | 783 | struct samsung_fimc_variant *variant = fimc->variant; |
758 | unsigned long flags; | 784 | unsigned int flags = FIMC_DST_FMT | FIMC_SRC_FMT; |
759 | int ret = 0; | 785 | int ret = 0; |
760 | 786 | ||
761 | if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) | 787 | if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE) |
@@ -763,52 +789,63 @@ static int fimc_s_ctrl(struct v4l2_ctrl *ctrl) | |||
763 | 789 | ||
764 | switch (ctrl->id) { | 790 | switch (ctrl->id) { |
765 | case V4L2_CID_HFLIP: | 791 | case V4L2_CID_HFLIP: |
766 | spin_lock_irqsave(&ctx->slock, flags); | ||
767 | ctx->hflip = ctrl->val; | 792 | ctx->hflip = ctrl->val; |
768 | break; | 793 | break; |
769 | 794 | ||
770 | case V4L2_CID_VFLIP: | 795 | case V4L2_CID_VFLIP: |
771 | spin_lock_irqsave(&ctx->slock, flags); | ||
772 | ctx->vflip = ctrl->val; | 796 | ctx->vflip = ctrl->val; |
773 | break; | 797 | break; |
774 | 798 | ||
775 | case V4L2_CID_ROTATE: | 799 | case V4L2_CID_ROTATE: |
776 | if (fimc_capture_pending(fimc) || | 800 | if (fimc_capture_pending(fimc) || |
777 | fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) { | 801 | (ctx->state & flags) == flags) { |
778 | ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, | 802 | ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width, |
779 | ctx->s_frame.height, ctx->d_frame.width, | 803 | ctx->s_frame.height, ctx->d_frame.width, |
780 | ctx->d_frame.height, ctrl->val); | 804 | ctx->d_frame.height, ctrl->val); |
781 | } | 805 | if (ret) |
782 | if (ret) { | 806 | return -EINVAL; |
783 | v4l2_err(fimc->m2m.vfd, "Out of scaler range\n"); | ||
784 | return -EINVAL; | ||
785 | } | 807 | } |
786 | if ((ctrl->val == 90 || ctrl->val == 270) && | 808 | if ((ctrl->val == 90 || ctrl->val == 270) && |
787 | !variant->has_out_rot) | 809 | !variant->has_out_rot) |
788 | return -EINVAL; | 810 | return -EINVAL; |
789 | spin_lock_irqsave(&ctx->slock, flags); | 811 | |
790 | ctx->rotation = ctrl->val; | 812 | ctx->rotation = ctrl->val; |
791 | break; | 813 | break; |
792 | 814 | ||
793 | default: | 815 | case V4L2_CID_ALPHA_COMPONENT: |
794 | v4l2_err(fimc->v4l2_dev, "Invalid control: 0x%X\n", ctrl->id); | 816 | ctx->d_frame.alpha = ctrl->val; |
795 | return -EINVAL; | 817 | break; |
796 | } | 818 | } |
797 | ctx->state |= FIMC_PARAMS; | 819 | ctx->state |= FIMC_PARAMS; |
798 | set_bit(ST_CAPT_APPLY_CFG, &fimc->state); | 820 | set_bit(ST_CAPT_APPLY_CFG, &fimc->state); |
799 | spin_unlock_irqrestore(&ctx->slock, flags); | ||
800 | return 0; | 821 | return 0; |
801 | } | 822 | } |
802 | 823 | ||
824 | static int fimc_s_ctrl(struct v4l2_ctrl *ctrl) | ||
825 | { | ||
826 | struct fimc_ctx *ctx = ctrl_to_ctx(ctrl); | ||
827 | unsigned long flags; | ||
828 | int ret; | ||
829 | |||
830 | spin_lock_irqsave(&ctx->slock, flags); | ||
831 | ret = __fimc_s_ctrl(ctx, ctrl); | ||
832 | spin_unlock_irqrestore(&ctx->slock, flags); | ||
833 | |||
834 | return ret; | ||
835 | } | ||
836 | |||
803 | static const struct v4l2_ctrl_ops fimc_ctrl_ops = { | 837 | static const struct v4l2_ctrl_ops fimc_ctrl_ops = { |
804 | .s_ctrl = fimc_s_ctrl, | 838 | .s_ctrl = fimc_s_ctrl, |
805 | }; | 839 | }; |
806 | 840 | ||
807 | int fimc_ctrls_create(struct fimc_ctx *ctx) | 841 | int fimc_ctrls_create(struct fimc_ctx *ctx) |
808 | { | 842 | { |
843 | struct samsung_fimc_variant *variant = ctx->fimc_dev->variant; | ||
844 | unsigned int max_alpha = fimc_get_alpha_mask(ctx->d_frame.fmt); | ||
845 | |||
809 | if (ctx->ctrls_rdy) | 846 | if (ctx->ctrls_rdy) |
810 | return 0; | 847 | return 0; |
811 | v4l2_ctrl_handler_init(&ctx->ctrl_handler, 3); | 848 | v4l2_ctrl_handler_init(&ctx->ctrl_handler, 4); |
812 | 849 | ||
813 | ctx->ctrl_rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops, | 850 | ctx->ctrl_rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops, |
814 | V4L2_CID_HFLIP, 0, 1, 1, 0); | 851 | V4L2_CID_HFLIP, 0, 1, 1, 0); |
@@ -816,6 +853,13 @@ int fimc_ctrls_create(struct fimc_ctx *ctx) | |||
816 | V4L2_CID_VFLIP, 0, 1, 1, 0); | 853 | V4L2_CID_VFLIP, 0, 1, 1, 0); |
817 | ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops, | 854 | ctx->ctrl_vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler, &fimc_ctrl_ops, |
818 | V4L2_CID_ROTATE, 0, 270, 90, 0); | 855 | V4L2_CID_ROTATE, 0, 270, 90, 0); |
856 | if (variant->has_alpha) | ||
857 | ctx->ctrl_alpha = v4l2_ctrl_new_std(&ctx->ctrl_handler, | ||
858 | &fimc_ctrl_ops, V4L2_CID_ALPHA_COMPONENT, | ||
859 | 0, max_alpha, 1, 0); | ||
860 | else | ||
861 | ctx->ctrl_alpha = NULL; | ||
862 | |||
819 | ctx->ctrls_rdy = ctx->ctrl_handler.error == 0; | 863 | ctx->ctrls_rdy = ctx->ctrl_handler.error == 0; |
820 | 864 | ||
821 | return ctx->ctrl_handler.error; | 865 | return ctx->ctrl_handler.error; |
@@ -826,11 +870,14 @@ void fimc_ctrls_delete(struct fimc_ctx *ctx) | |||
826 | if (ctx->ctrls_rdy) { | 870 | if (ctx->ctrls_rdy) { |
827 | v4l2_ctrl_handler_free(&ctx->ctrl_handler); | 871 | v4l2_ctrl_handler_free(&ctx->ctrl_handler); |
828 | ctx->ctrls_rdy = false; | 872 | ctx->ctrls_rdy = false; |
873 | ctx->ctrl_alpha = NULL; | ||
829 | } | 874 | } |
830 | } | 875 | } |
831 | 876 | ||
832 | void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active) | 877 | void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active) |
833 | { | 878 | { |
879 | unsigned int has_alpha = ctx->d_frame.fmt->flags & FMT_HAS_ALPHA; | ||
880 | |||
834 | if (!ctx->ctrls_rdy) | 881 | if (!ctx->ctrls_rdy) |
835 | return; | 882 | return; |
836 | 883 | ||
@@ -838,6 +885,8 @@ void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active) | |||
838 | v4l2_ctrl_activate(ctx->ctrl_rotate, active); | 885 | v4l2_ctrl_activate(ctx->ctrl_rotate, active); |
839 | v4l2_ctrl_activate(ctx->ctrl_hflip, active); | 886 | v4l2_ctrl_activate(ctx->ctrl_hflip, active); |
840 | v4l2_ctrl_activate(ctx->ctrl_vflip, active); | 887 | v4l2_ctrl_activate(ctx->ctrl_vflip, active); |
888 | if (ctx->ctrl_alpha) | ||
889 | v4l2_ctrl_activate(ctx->ctrl_alpha, active && has_alpha); | ||
841 | 890 | ||
842 | if (active) { | 891 | if (active) { |
843 | ctx->rotation = ctx->ctrl_rotate->val; | 892 | ctx->rotation = ctx->ctrl_rotate->val; |
@@ -851,6 +900,24 @@ void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active) | |||
851 | mutex_unlock(&ctx->ctrl_handler.lock); | 900 | mutex_unlock(&ctx->ctrl_handler.lock); |
852 | } | 901 | } |
853 | 902 | ||
903 | /* Update maximum value of the alpha color control */ | ||
904 | void fimc_alpha_ctrl_update(struct fimc_ctx *ctx) | ||
905 | { | ||
906 | struct fimc_dev *fimc = ctx->fimc_dev; | ||
907 | struct v4l2_ctrl *ctrl = ctx->ctrl_alpha; | ||
908 | |||
909 | if (ctrl == NULL || !fimc->variant->has_alpha) | ||
910 | return; | ||
911 | |||
912 | v4l2_ctrl_lock(ctrl); | ||
913 | ctrl->maximum = fimc_get_alpha_mask(ctx->d_frame.fmt); | ||
914 | |||
915 | if (ctrl->cur.val > ctrl->maximum) | ||
916 | ctrl->cur.val = ctrl->maximum; | ||
917 | |||
918 | v4l2_ctrl_unlock(ctrl); | ||
919 | } | ||
920 | |||
854 | /* | 921 | /* |
855 | * V4L2 ioctl handlers | 922 | * V4L2 ioctl handlers |
856 | */ | 923 | */ |
@@ -874,7 +941,8 @@ static int fimc_m2m_enum_fmt_mplane(struct file *file, void *priv, | |||
874 | { | 941 | { |
875 | struct fimc_fmt *fmt; | 942 | struct fimc_fmt *fmt; |
876 | 943 | ||
877 | fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_M2M, f->index); | 944 | fmt = fimc_find_format(NULL, NULL, get_m2m_fmt_flags(f->type), |
945 | f->index); | ||
878 | if (!fmt) | 946 | if (!fmt) |
879 | return -EINVAL; | 947 | return -EINVAL; |
880 | 948 | ||
@@ -938,6 +1006,7 @@ void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height, | |||
938 | pix->colorspace = V4L2_COLORSPACE_JPEG; | 1006 | pix->colorspace = V4L2_COLORSPACE_JPEG; |
939 | pix->field = V4L2_FIELD_NONE; | 1007 | pix->field = V4L2_FIELD_NONE; |
940 | pix->num_planes = fmt->memplanes; | 1008 | pix->num_planes = fmt->memplanes; |
1009 | pix->pixelformat = fmt->fourcc; | ||
941 | pix->height = height; | 1010 | pix->height = height; |
942 | pix->width = width; | 1011 | pix->width = width; |
943 | 1012 | ||
@@ -1017,7 +1086,8 @@ static int fimc_try_fmt_mplane(struct fimc_ctx *ctx, struct v4l2_format *f) | |||
1017 | 1086 | ||
1018 | dbg("w: %d, h: %d", pix->width, pix->height); | 1087 | dbg("w: %d, h: %d", pix->width, pix->height); |
1019 | 1088 | ||
1020 | fmt = fimc_find_format(&pix->pixelformat, NULL, FMT_FLAGS_M2M, 0); | 1089 | fmt = fimc_find_format(&pix->pixelformat, NULL, |
1090 | get_m2m_fmt_flags(f->type), 0); | ||
1021 | if (WARN(fmt == NULL, "Pixel format lookup failed")) | 1091 | if (WARN(fmt == NULL, "Pixel format lookup failed")) |
1022 | return -EINVAL; | 1092 | return -EINVAL; |
1023 | 1093 | ||
@@ -1087,10 +1157,13 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh, | |||
1087 | 1157 | ||
1088 | pix = &f->fmt.pix_mp; | 1158 | pix = &f->fmt.pix_mp; |
1089 | frame->fmt = fimc_find_format(&pix->pixelformat, NULL, | 1159 | frame->fmt = fimc_find_format(&pix->pixelformat, NULL, |
1090 | FMT_FLAGS_M2M, 0); | 1160 | get_m2m_fmt_flags(f->type), 0); |
1091 | if (!frame->fmt) | 1161 | if (!frame->fmt) |
1092 | return -EINVAL; | 1162 | return -EINVAL; |
1093 | 1163 | ||
1164 | /* Update RGB Alpha control state and value range */ | ||
1165 | fimc_alpha_ctrl_update(ctx); | ||
1166 | |||
1094 | for (i = 0; i < frame->fmt->colplanes; i++) { | 1167 | for (i = 0; i < frame->fmt->colplanes; i++) { |
1095 | frame->payload[i] = | 1168 | frame->payload[i] = |
1096 | (pix->width * pix->height * frame->fmt->depth[i]) / 8; | 1169 | (pix->width * pix->height * frame->fmt->depth[i]) / 8; |
@@ -1374,6 +1447,12 @@ static int fimc_m2m_open(struct file *file) | |||
1374 | if (!ctx) | 1447 | if (!ctx) |
1375 | return -ENOMEM; | 1448 | return -ENOMEM; |
1376 | v4l2_fh_init(&ctx->fh, fimc->m2m.vfd); | 1449 | v4l2_fh_init(&ctx->fh, fimc->m2m.vfd); |
1450 | ctx->fimc_dev = fimc; | ||
1451 | |||
1452 | /* Default color format */ | ||
1453 | ctx->s_frame.fmt = &fimc_formats[0]; | ||
1454 | ctx->d_frame.fmt = &fimc_formats[0]; | ||
1455 | |||
1377 | ret = fimc_ctrls_create(ctx); | 1456 | ret = fimc_ctrls_create(ctx); |
1378 | if (ret) | 1457 | if (ret) |
1379 | goto error_fh; | 1458 | goto error_fh; |
@@ -1383,10 +1462,6 @@ static int fimc_m2m_open(struct file *file) | |||
1383 | file->private_data = &ctx->fh; | 1462 | file->private_data = &ctx->fh; |
1384 | v4l2_fh_add(&ctx->fh); | 1463 | v4l2_fh_add(&ctx->fh); |
1385 | 1464 | ||
1386 | ctx->fimc_dev = fimc; | ||
1387 | /* Default color format */ | ||
1388 | ctx->s_frame.fmt = &fimc_formats[0]; | ||
1389 | ctx->d_frame.fmt = &fimc_formats[0]; | ||
1390 | /* Setup the device context for memory-to-memory mode */ | 1465 | /* Setup the device context for memory-to-memory mode */ |
1391 | ctx->state = FIMC_CTX_M2M; | 1466 | ctx->state = FIMC_CTX_M2M; |
1392 | ctx->flags = 0; | 1467 | ctx->flags = 0; |
@@ -1709,9 +1784,8 @@ static int fimc_runtime_resume(struct device *dev) | |||
1709 | /* Resume the capture or mem-to-mem device */ | 1784 | /* Resume the capture or mem-to-mem device */ |
1710 | if (fimc_capture_busy(fimc)) | 1785 | if (fimc_capture_busy(fimc)) |
1711 | return fimc_capture_resume(fimc); | 1786 | return fimc_capture_resume(fimc); |
1712 | else if (fimc_m2m_pending(fimc)) | 1787 | |
1713 | return fimc_m2m_resume(fimc); | 1788 | return fimc_m2m_resume(fimc); |
1714 | return 0; | ||
1715 | } | 1789 | } |
1716 | 1790 | ||
1717 | static int fimc_runtime_suspend(struct device *dev) | 1791 | static int fimc_runtime_suspend(struct device *dev) |
@@ -1893,6 +1967,7 @@ static struct samsung_fimc_variant fimc0_variant_exynos4 = { | |||
1893 | .has_cam_if = 1, | 1967 | .has_cam_if = 1, |
1894 | .has_cistatus2 = 1, | 1968 | .has_cistatus2 = 1, |
1895 | .has_mainscaler_ext = 1, | 1969 | .has_mainscaler_ext = 1, |
1970 | .has_alpha = 1, | ||
1896 | .min_inp_pixsize = 16, | 1971 | .min_inp_pixsize = 16, |
1897 | .min_out_pixsize = 16, | 1972 | .min_out_pixsize = 16, |
1898 | .hor_offs_align = 2, | 1973 | .hor_offs_align = 2, |
@@ -1906,6 +1981,7 @@ static struct samsung_fimc_variant fimc3_variant_exynos4 = { | |||
1906 | .has_cam_if = 1, | 1981 | .has_cam_if = 1, |
1907 | .has_cistatus2 = 1, | 1982 | .has_cistatus2 = 1, |
1908 | .has_mainscaler_ext = 1, | 1983 | .has_mainscaler_ext = 1, |
1984 | .has_alpha = 1, | ||
1909 | .min_inp_pixsize = 16, | 1985 | .min_inp_pixsize = 16, |
1910 | .min_out_pixsize = 16, | 1986 | .min_out_pixsize = 16, |
1911 | .hor_offs_align = 2, | 1987 | .hor_offs_align = 2, |
diff --git a/drivers/media/video/s5p-fimc/fimc-core.h b/drivers/media/video/s5p-fimc/fimc-core.h index c7f01c47b20f..4e20560c73d4 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.h +++ b/drivers/media/video/s5p-fimc/fimc-core.h | |||
@@ -85,7 +85,9 @@ enum fimc_datapath { | |||
85 | }; | 85 | }; |
86 | 86 | ||
87 | enum fimc_color_fmt { | 87 | enum fimc_color_fmt { |
88 | S5P_FIMC_RGB565 = 0x10, | 88 | S5P_FIMC_RGB444 = 0x10, |
89 | S5P_FIMC_RGB555, | ||
90 | S5P_FIMC_RGB565, | ||
89 | S5P_FIMC_RGB666, | 91 | S5P_FIMC_RGB666, |
90 | S5P_FIMC_RGB888, | 92 | S5P_FIMC_RGB888, |
91 | S5P_FIMC_RGB30_LOCAL, | 93 | S5P_FIMC_RGB30_LOCAL, |
@@ -160,8 +162,11 @@ struct fimc_fmt { | |||
160 | u16 colplanes; | 162 | u16 colplanes; |
161 | u8 depth[VIDEO_MAX_PLANES]; | 163 | u8 depth[VIDEO_MAX_PLANES]; |
162 | u16 flags; | 164 | u16 flags; |
163 | #define FMT_FLAGS_CAM (1 << 0) | 165 | #define FMT_FLAGS_CAM (1 << 0) |
164 | #define FMT_FLAGS_M2M (1 << 1) | 166 | #define FMT_FLAGS_M2M_IN (1 << 1) |
167 | #define FMT_FLAGS_M2M_OUT (1 << 2) | ||
168 | #define FMT_FLAGS_M2M (1 << 1 | 1 << 2) | ||
169 | #define FMT_HAS_ALPHA (1 << 3) | ||
165 | }; | 170 | }; |
166 | 171 | ||
167 | /** | 172 | /** |
@@ -283,6 +288,7 @@ struct fimc_frame { | |||
283 | struct fimc_addr paddr; | 288 | struct fimc_addr paddr; |
284 | struct fimc_dma_offset dma_offset; | 289 | struct fimc_dma_offset dma_offset; |
285 | struct fimc_fmt *fmt; | 290 | struct fimc_fmt *fmt; |
291 | u8 alpha; | ||
286 | }; | 292 | }; |
287 | 293 | ||
288 | /** | 294 | /** |
@@ -387,6 +393,7 @@ struct samsung_fimc_variant { | |||
387 | unsigned int has_cistatus2:1; | 393 | unsigned int has_cistatus2:1; |
388 | unsigned int has_mainscaler_ext:1; | 394 | unsigned int has_mainscaler_ext:1; |
389 | unsigned int has_cam_if:1; | 395 | unsigned int has_cam_if:1; |
396 | unsigned int has_alpha:1; | ||
390 | struct fimc_pix_limit *pix_limit; | 397 | struct fimc_pix_limit *pix_limit; |
391 | u16 min_inp_pixsize; | 398 | u16 min_inp_pixsize; |
392 | u16 min_out_pixsize; | 399 | u16 min_out_pixsize; |
@@ -482,7 +489,8 @@ struct fimc_dev { | |||
482 | * @ctrl_handler: v4l2 controls handler | 489 | * @ctrl_handler: v4l2 controls handler |
483 | * @ctrl_rotate image rotation control | 490 | * @ctrl_rotate image rotation control |
484 | * @ctrl_hflip horizontal flip control | 491 | * @ctrl_hflip horizontal flip control |
485 | * @ctrl_vflip vartical flip control | 492 | * @ctrl_vflip vertical flip control |
493 | * @ctrl_alpha RGB alpha control | ||
486 | * @ctrls_rdy: true if the control handler is initialized | 494 | * @ctrls_rdy: true if the control handler is initialized |
487 | */ | 495 | */ |
488 | struct fimc_ctx { | 496 | struct fimc_ctx { |
@@ -509,6 +517,7 @@ struct fimc_ctx { | |||
509 | struct v4l2_ctrl *ctrl_rotate; | 517 | struct v4l2_ctrl *ctrl_rotate; |
510 | struct v4l2_ctrl *ctrl_hflip; | 518 | struct v4l2_ctrl *ctrl_hflip; |
511 | struct v4l2_ctrl *ctrl_vflip; | 519 | struct v4l2_ctrl *ctrl_vflip; |
520 | struct v4l2_ctrl *ctrl_alpha; | ||
512 | bool ctrls_rdy; | 521 | bool ctrls_rdy; |
513 | }; | 522 | }; |
514 | 523 | ||
@@ -578,6 +587,17 @@ static inline int tiled_fmt(struct fimc_fmt *fmt) | |||
578 | return fmt->fourcc == V4L2_PIX_FMT_NV12MT; | 587 | return fmt->fourcc == V4L2_PIX_FMT_NV12MT; |
579 | } | 588 | } |
580 | 589 | ||
590 | /* Return the alpha component bit mask */ | ||
591 | static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt) | ||
592 | { | ||
593 | switch (fmt->color) { | ||
594 | case S5P_FIMC_RGB444: return 0x0f; | ||
595 | case S5P_FIMC_RGB555: return 0x01; | ||
596 | case S5P_FIMC_RGB888: return 0xff; | ||
597 | default: return 0; | ||
598 | }; | ||
599 | } | ||
600 | |||
581 | static inline void fimc_hw_clear_irq(struct fimc_dev *dev) | 601 | static inline void fimc_hw_clear_irq(struct fimc_dev *dev) |
582 | { | 602 | { |
583 | u32 cfg = readl(dev->regs + S5P_CIGCTRL); | 603 | u32 cfg = readl(dev->regs + S5P_CIGCTRL); |
@@ -674,6 +694,7 @@ void fimc_hw_set_prescaler(struct fimc_ctx *ctx); | |||
674 | void fimc_hw_set_mainscaler(struct fimc_ctx *ctx); | 694 | void fimc_hw_set_mainscaler(struct fimc_ctx *ctx); |
675 | void fimc_hw_en_capture(struct fimc_ctx *ctx); | 695 | void fimc_hw_en_capture(struct fimc_ctx *ctx); |
676 | void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active); | 696 | void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active); |
697 | void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx); | ||
677 | void fimc_hw_set_in_dma(struct fimc_ctx *ctx); | 698 | void fimc_hw_set_in_dma(struct fimc_ctx *ctx); |
678 | void fimc_hw_set_input_path(struct fimc_ctx *ctx); | 699 | void fimc_hw_set_input_path(struct fimc_ctx *ctx); |
679 | void fimc_hw_set_output_path(struct fimc_ctx *ctx); | 700 | void fimc_hw_set_output_path(struct fimc_ctx *ctx); |
@@ -695,6 +716,7 @@ int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv, | |||
695 | int fimc_ctrls_create(struct fimc_ctx *ctx); | 716 | int fimc_ctrls_create(struct fimc_ctx *ctx); |
696 | void fimc_ctrls_delete(struct fimc_ctx *ctx); | 717 | void fimc_ctrls_delete(struct fimc_ctx *ctx); |
697 | void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active); | 718 | void fimc_ctrls_activate(struct fimc_ctx *ctx, bool active); |
719 | void fimc_alpha_ctrl_update(struct fimc_ctx *ctx); | ||
698 | int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f); | 720 | int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f); |
699 | void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height, | 721 | void fimc_adjust_mplane_format(struct fimc_fmt *fmt, u32 width, u32 height, |
700 | struct v4l2_pix_format_mplane *pix); | 722 | struct v4l2_pix_format_mplane *pix); |
diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c index 44f5c2d1920b..15466d0529c1 100644 --- a/drivers/media/video/s5p-fimc/fimc-reg.c +++ b/drivers/media/video/s5p-fimc/fimc-reg.c | |||
@@ -117,7 +117,7 @@ void fimc_hw_set_target_format(struct fimc_ctx *ctx) | |||
117 | S5P_CITRGFMT_VSIZE_MASK); | 117 | S5P_CITRGFMT_VSIZE_MASK); |
118 | 118 | ||
119 | switch (frame->fmt->color) { | 119 | switch (frame->fmt->color) { |
120 | case S5P_FIMC_RGB565...S5P_FIMC_RGB888: | 120 | case S5P_FIMC_RGB444...S5P_FIMC_RGB888: |
121 | cfg |= S5P_CITRGFMT_RGB; | 121 | cfg |= S5P_CITRGFMT_RGB; |
122 | break; | 122 | break; |
123 | case S5P_FIMC_YCBCR420: | 123 | case S5P_FIMC_YCBCR420: |
@@ -175,6 +175,7 @@ void fimc_hw_set_out_dma(struct fimc_ctx *ctx) | |||
175 | struct fimc_dev *dev = ctx->fimc_dev; | 175 | struct fimc_dev *dev = ctx->fimc_dev; |
176 | struct fimc_frame *frame = &ctx->d_frame; | 176 | struct fimc_frame *frame = &ctx->d_frame; |
177 | struct fimc_dma_offset *offset = &frame->dma_offset; | 177 | struct fimc_dma_offset *offset = &frame->dma_offset; |
178 | struct fimc_fmt *fmt = frame->fmt; | ||
178 | 179 | ||
179 | /* Set the input dma offsets. */ | 180 | /* Set the input dma offsets. */ |
180 | cfg = 0; | 181 | cfg = 0; |
@@ -198,15 +199,22 @@ void fimc_hw_set_out_dma(struct fimc_ctx *ctx) | |||
198 | cfg = readl(dev->regs + S5P_CIOCTRL); | 199 | cfg = readl(dev->regs + S5P_CIOCTRL); |
199 | 200 | ||
200 | cfg &= ~(S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK | | 201 | cfg &= ~(S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK | |
201 | S5P_CIOCTRL_YCBCR_PLANE_MASK); | 202 | S5P_CIOCTRL_YCBCR_PLANE_MASK | S5P_CIOCTRL_RGB16FMT_MASK); |
202 | 203 | ||
203 | if (frame->fmt->colplanes == 1) | 204 | if (fmt->colplanes == 1) |
204 | cfg |= ctx->out_order_1p; | 205 | cfg |= ctx->out_order_1p; |
205 | else if (frame->fmt->colplanes == 2) | 206 | else if (fmt->colplanes == 2) |
206 | cfg |= ctx->out_order_2p | S5P_CIOCTRL_YCBCR_2PLANE; | 207 | cfg |= ctx->out_order_2p | S5P_CIOCTRL_YCBCR_2PLANE; |
207 | else if (frame->fmt->colplanes == 3) | 208 | else if (fmt->colplanes == 3) |
208 | cfg |= S5P_CIOCTRL_YCBCR_3PLANE; | 209 | cfg |= S5P_CIOCTRL_YCBCR_3PLANE; |
209 | 210 | ||
211 | if (fmt->color == S5P_FIMC_RGB565) | ||
212 | cfg |= S5P_CIOCTRL_RGB565; | ||
213 | else if (fmt->color == S5P_FIMC_RGB555) | ||
214 | cfg |= S5P_CIOCTRL_ARGB1555; | ||
215 | else if (fmt->color == S5P_FIMC_RGB444) | ||
216 | cfg |= S5P_CIOCTRL_ARGB4444; | ||
217 | |||
210 | writel(cfg, dev->regs + S5P_CIOCTRL); | 218 | writel(cfg, dev->regs + S5P_CIOCTRL); |
211 | } | 219 | } |
212 | 220 | ||
@@ -278,22 +286,28 @@ static void fimc_hw_set_scaler(struct fimc_ctx *ctx) | |||
278 | if (sc->copy_mode) | 286 | if (sc->copy_mode) |
279 | cfg |= S5P_CISCCTRL_ONE2ONE; | 287 | cfg |= S5P_CISCCTRL_ONE2ONE; |
280 | 288 | ||
281 | |||
282 | if (ctx->in_path == FIMC_DMA) { | 289 | if (ctx->in_path == FIMC_DMA) { |
283 | if (src_frame->fmt->color == S5P_FIMC_RGB565) | 290 | switch (src_frame->fmt->color) { |
291 | case S5P_FIMC_RGB565: | ||
284 | cfg |= S5P_CISCCTRL_INRGB_FMT_RGB565; | 292 | cfg |= S5P_CISCCTRL_INRGB_FMT_RGB565; |
285 | else if (src_frame->fmt->color == S5P_FIMC_RGB666) | 293 | break; |
294 | case S5P_FIMC_RGB666: | ||
286 | cfg |= S5P_CISCCTRL_INRGB_FMT_RGB666; | 295 | cfg |= S5P_CISCCTRL_INRGB_FMT_RGB666; |
287 | else if (src_frame->fmt->color == S5P_FIMC_RGB888) | 296 | break; |
297 | case S5P_FIMC_RGB888: | ||
288 | cfg |= S5P_CISCCTRL_INRGB_FMT_RGB888; | 298 | cfg |= S5P_CISCCTRL_INRGB_FMT_RGB888; |
299 | break; | ||
300 | } | ||
289 | } | 301 | } |
290 | 302 | ||
291 | if (ctx->out_path == FIMC_DMA) { | 303 | if (ctx->out_path == FIMC_DMA) { |
292 | if (dst_frame->fmt->color == S5P_FIMC_RGB565) | 304 | u32 color = dst_frame->fmt->color; |
305 | |||
306 | if (color >= S5P_FIMC_RGB444 && color <= S5P_FIMC_RGB565) | ||
293 | cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB565; | 307 | cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB565; |
294 | else if (dst_frame->fmt->color == S5P_FIMC_RGB666) | 308 | else if (color == S5P_FIMC_RGB666) |
295 | cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB666; | 309 | cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB666; |
296 | else if (dst_frame->fmt->color == S5P_FIMC_RGB888) | 310 | else if (color == S5P_FIMC_RGB888) |
297 | cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888; | 311 | cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888; |
298 | } else { | 312 | } else { |
299 | cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888; | 313 | cfg |= S5P_CISCCTRL_OUTRGB_FMT_RGB888; |
@@ -379,6 +393,21 @@ void fimc_hw_set_effect(struct fimc_ctx *ctx, bool active) | |||
379 | writel(cfg, dev->regs + S5P_CIIMGEFF); | 393 | writel(cfg, dev->regs + S5P_CIIMGEFF); |
380 | } | 394 | } |
381 | 395 | ||
396 | void fimc_hw_set_rgb_alpha(struct fimc_ctx *ctx) | ||
397 | { | ||
398 | struct fimc_dev *dev = ctx->fimc_dev; | ||
399 | struct fimc_frame *frame = &ctx->d_frame; | ||
400 | u32 cfg; | ||
401 | |||
402 | if (!(frame->fmt->flags & FMT_HAS_ALPHA)) | ||
403 | return; | ||
404 | |||
405 | cfg = readl(dev->regs + S5P_CIOCTRL); | ||
406 | cfg &= ~S5P_CIOCTRL_ALPHA_OUT_MASK; | ||
407 | cfg |= (frame->alpha << 4); | ||
408 | writel(cfg, dev->regs + S5P_CIOCTRL); | ||
409 | } | ||
410 | |||
382 | static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx) | 411 | static void fimc_hw_set_in_dma_size(struct fimc_ctx *ctx) |
383 | { | 412 | { |
384 | struct fimc_dev *dev = ctx->fimc_dev; | 413 | struct fimc_dev *dev = ctx->fimc_dev; |
diff --git a/drivers/media/video/s5p-fimc/mipi-csis.c b/drivers/media/video/s5p-fimc/mipi-csis.c index 59d79bc2f58a..130335cf62fd 100644 --- a/drivers/media/video/s5p-fimc/mipi-csis.c +++ b/drivers/media/video/s5p-fimc/mipi-csis.c | |||
@@ -427,6 +427,23 @@ static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, | |||
427 | return 0; | 427 | return 0; |
428 | } | 428 | } |
429 | 429 | ||
430 | static int s5pcsis_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) | ||
431 | { | ||
432 | struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0); | ||
433 | |||
434 | format->colorspace = V4L2_COLORSPACE_JPEG; | ||
435 | format->code = s5pcsis_formats[0].code; | ||
436 | format->width = S5PCSIS_DEF_PIX_WIDTH; | ||
437 | format->height = S5PCSIS_DEF_PIX_HEIGHT; | ||
438 | format->field = V4L2_FIELD_NONE; | ||
439 | |||
440 | return 0; | ||
441 | } | ||
442 | |||
443 | static const struct v4l2_subdev_internal_ops s5pcsis_sd_internal_ops = { | ||
444 | .open = s5pcsis_open, | ||
445 | }; | ||
446 | |||
430 | static struct v4l2_subdev_core_ops s5pcsis_core_ops = { | 447 | static struct v4l2_subdev_core_ops s5pcsis_core_ops = { |
431 | .s_power = s5pcsis_s_power, | 448 | .s_power = s5pcsis_s_power, |
432 | }; | 449 | }; |
@@ -544,8 +561,13 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev) | |||
544 | v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops); | 561 | v4l2_subdev_init(&state->sd, &s5pcsis_subdev_ops); |
545 | state->sd.owner = THIS_MODULE; | 562 | state->sd.owner = THIS_MODULE; |
546 | strlcpy(state->sd.name, dev_name(&pdev->dev), sizeof(state->sd.name)); | 563 | strlcpy(state->sd.name, dev_name(&pdev->dev), sizeof(state->sd.name)); |
564 | state->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | ||
547 | state->csis_fmt = &s5pcsis_formats[0]; | 565 | state->csis_fmt = &s5pcsis_formats[0]; |
548 | 566 | ||
567 | state->format.code = s5pcsis_formats[0].code; | ||
568 | state->format.width = S5PCSIS_DEF_PIX_WIDTH; | ||
569 | state->format.height = S5PCSIS_DEF_PIX_HEIGHT; | ||
570 | |||
549 | state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK; | 571 | state->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK; |
550 | state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; | 572 | state->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE; |
551 | ret = media_entity_init(&state->sd.entity, | 573 | ret = media_entity_init(&state->sd.entity, |
diff --git a/drivers/media/video/s5p-fimc/mipi-csis.h b/drivers/media/video/s5p-fimc/mipi-csis.h index f5691336dd5c..2709286396e1 100644 --- a/drivers/media/video/s5p-fimc/mipi-csis.h +++ b/drivers/media/video/s5p-fimc/mipi-csis.h | |||
@@ -19,4 +19,7 @@ | |||
19 | #define CSIS_PAD_SOURCE 1 | 19 | #define CSIS_PAD_SOURCE 1 |
20 | #define CSIS_PADS_NUM 2 | 20 | #define CSIS_PADS_NUM 2 |
21 | 21 | ||
22 | #define S5PCSIS_DEF_PIX_WIDTH 640 | ||
23 | #define S5PCSIS_DEF_PIX_HEIGHT 480 | ||
24 | |||
22 | #endif | 25 | #endif |
diff --git a/drivers/media/video/s5p-fimc/regs-fimc.h b/drivers/media/video/s5p-fimc/regs-fimc.h index c8e3b94bd91d..c7a5bc51d571 100644 --- a/drivers/media/video/s5p-fimc/regs-fimc.h +++ b/drivers/media/video/s5p-fimc/regs-fimc.h | |||
@@ -107,6 +107,11 @@ | |||
107 | #define S5P_CIOCTRL_YCBCR_3PLANE (0 << 3) | 107 | #define S5P_CIOCTRL_YCBCR_3PLANE (0 << 3) |
108 | #define S5P_CIOCTRL_YCBCR_2PLANE (1 << 3) | 108 | #define S5P_CIOCTRL_YCBCR_2PLANE (1 << 3) |
109 | #define S5P_CIOCTRL_YCBCR_PLANE_MASK (1 << 3) | 109 | #define S5P_CIOCTRL_YCBCR_PLANE_MASK (1 << 3) |
110 | #define S5P_CIOCTRL_ALPHA_OUT_MASK (0xff << 4) | ||
111 | #define S5P_CIOCTRL_RGB16FMT_MASK (3 << 16) | ||
112 | #define S5P_CIOCTRL_RGB565 (0 << 16) | ||
113 | #define S5P_CIOCTRL_ARGB1555 (1 << 16) | ||
114 | #define S5P_CIOCTRL_ARGB4444 (2 << 16) | ||
110 | #define S5P_CIOCTRL_ORDER2P_SHIFT (24) | 115 | #define S5P_CIOCTRL_ORDER2P_SHIFT (24) |
111 | #define S5P_CIOCTRL_ORDER2P_MASK (3 << 24) | 116 | #define S5P_CIOCTRL_ORDER2P_MASK (3 << 24) |
112 | #define S5P_CIOCTRL_ORDER422_2P_LSB_CRCB (0 << 24) | 117 | #define S5P_CIOCTRL_ORDER422_2P_LSB_CRCB (0 << 24) |
diff --git a/drivers/media/video/s5p-g2d/Makefile b/drivers/media/video/s5p-g2d/Makefile new file mode 100644 index 000000000000..2c48c416a804 --- /dev/null +++ b/drivers/media/video/s5p-g2d/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | s5p-g2d-objs := g2d.o g2d-hw.o | ||
2 | |||
3 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D) += s5p-g2d.o | ||
diff --git a/drivers/media/video/s5p-g2d/g2d-hw.c b/drivers/media/video/s5p-g2d/g2d-hw.c new file mode 100644 index 000000000000..39937cf03c88 --- /dev/null +++ b/drivers/media/video/s5p-g2d/g2d-hw.c | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * Samsung S5P G2D - 2D Graphics Accelerator Driver | ||
3 | * | ||
4 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
5 | * Kamil Debski, <k.debski@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the | ||
10 | * License, or (at your option) any later version | ||
11 | */ | ||
12 | |||
13 | #include <linux/io.h> | ||
14 | |||
15 | #include "g2d.h" | ||
16 | #include "g2d-regs.h" | ||
17 | |||
18 | #define w(x, a) writel((x), d->regs + (a)) | ||
19 | #define r(a) readl(d->regs + (a)) | ||
20 | |||
21 | /* g2d_reset clears all g2d registers */ | ||
22 | void g2d_reset(struct g2d_dev *d) | ||
23 | { | ||
24 | w(1, SOFT_RESET_REG); | ||
25 | } | ||
26 | |||
27 | void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f) | ||
28 | { | ||
29 | u32 n; | ||
30 | |||
31 | w(f->stride & 0xFFFF, SRC_STRIDE_REG); | ||
32 | |||
33 | n = f->o_height & 0xFFF; | ||
34 | n <<= 16; | ||
35 | n |= f->o_width & 0xFFF; | ||
36 | w(n, SRC_LEFT_TOP_REG); | ||
37 | |||
38 | n = f->bottom & 0xFFF; | ||
39 | n <<= 16; | ||
40 | n |= f->right & 0xFFF; | ||
41 | w(n, SRC_RIGHT_BOTTOM_REG); | ||
42 | |||
43 | w(f->fmt->hw, SRC_COLOR_MODE_REG); | ||
44 | } | ||
45 | |||
46 | void g2d_set_src_addr(struct g2d_dev *d, dma_addr_t a) | ||
47 | { | ||
48 | w(a, SRC_BASE_ADDR_REG); | ||
49 | } | ||
50 | |||
51 | void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f) | ||
52 | { | ||
53 | u32 n; | ||
54 | |||
55 | w(f->stride & 0xFFFF, DST_STRIDE_REG); | ||
56 | |||
57 | n = f->o_height & 0xFFF; | ||
58 | n <<= 16; | ||
59 | n |= f->o_width & 0xFFF; | ||
60 | w(n, DST_LEFT_TOP_REG); | ||
61 | |||
62 | n = f->bottom & 0xFFF; | ||
63 | n <<= 16; | ||
64 | n |= f->right & 0xFFF; | ||
65 | w(n, DST_RIGHT_BOTTOM_REG); | ||
66 | |||
67 | w(f->fmt->hw, DST_COLOR_MODE_REG); | ||
68 | } | ||
69 | |||
70 | void g2d_set_dst_addr(struct g2d_dev *d, dma_addr_t a) | ||
71 | { | ||
72 | w(a, DST_BASE_ADDR_REG); | ||
73 | } | ||
74 | |||
75 | void g2d_set_rop4(struct g2d_dev *d, u32 r) | ||
76 | { | ||
77 | w(r, ROP4_REG); | ||
78 | } | ||
79 | |||
80 | u32 g2d_cmd_stretch(u32 e) | ||
81 | { | ||
82 | e &= 1; | ||
83 | return e << 4; | ||
84 | } | ||
85 | |||
86 | void g2d_set_cmd(struct g2d_dev *d, u32 c) | ||
87 | { | ||
88 | w(c, BITBLT_COMMAND_REG); | ||
89 | } | ||
90 | |||
91 | void g2d_start(struct g2d_dev *d) | ||
92 | { | ||
93 | /* Clear cache */ | ||
94 | w(0x7, CACHECTL_REG); | ||
95 | /* Enable interrupt */ | ||
96 | w(1, INTEN_REG); | ||
97 | /* Start G2D engine */ | ||
98 | w(1, BITBLT_START_REG); | ||
99 | } | ||
100 | |||
101 | void g2d_clear_int(struct g2d_dev *d) | ||
102 | { | ||
103 | w(1, INTC_PEND_REG); | ||
104 | } | ||
diff --git a/drivers/media/video/s5p-g2d/g2d-regs.h b/drivers/media/video/s5p-g2d/g2d-regs.h new file mode 100644 index 000000000000..02e1cf50da4e --- /dev/null +++ b/drivers/media/video/s5p-g2d/g2d-regs.h | |||
@@ -0,0 +1,115 @@ | |||
1 | /* | ||
2 | * Samsung S5P G2D - 2D Graphics Accelerator Driver | ||
3 | * | ||
4 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
5 | * Kamil Debski, <k.debski@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the | ||
10 | * License, or (at your option) any later version | ||
11 | */ | ||
12 | |||
13 | /* General Registers */ | ||
14 | #define SOFT_RESET_REG 0x0000 /* Software reset reg */ | ||
15 | #define INTEN_REG 0x0004 /* Interrupt Enable reg */ | ||
16 | #define INTC_PEND_REG 0x000C /* Interrupt Control Pending reg */ | ||
17 | #define FIFO_STAT_REG 0x0010 /* Command FIFO Status reg */ | ||
18 | #define AXI_ID_MODE_REG 0x0014 /* AXI Read ID Mode reg */ | ||
19 | #define CACHECTL_REG 0x0018 /* Cache & Buffer clear reg */ | ||
20 | #define AXI_MODE_REG 0x001C /* AXI Mode reg */ | ||
21 | |||
22 | /* Command Registers */ | ||
23 | #define BITBLT_START_REG 0x0100 /* BitBLT Start reg */ | ||
24 | #define BITBLT_COMMAND_REG 0x0104 /* Command reg for BitBLT */ | ||
25 | |||
26 | /* Parameter Setting Registers (Rotate & Direction) */ | ||
27 | #define ROTATE_REG 0x0200 /* Rotation reg */ | ||
28 | #define SRC_MSK_DIRECT_REG 0x0204 /* Src and Mask Direction reg */ | ||
29 | #define DST_PAT_DIRECT_REG 0x0208 /* Dest and Pattern Direction reg */ | ||
30 | |||
31 | /* Parameter Setting Registers (Src) */ | ||
32 | #define SRC_SELECT_REG 0x0300 /* Src Image Selection reg */ | ||
33 | #define SRC_BASE_ADDR_REG 0x0304 /* Src Image Base Address reg */ | ||
34 | #define SRC_STRIDE_REG 0x0308 /* Src Stride reg */ | ||
35 | #define SRC_COLOR_MODE_REG 0x030C /* Src Image Color Mode reg */ | ||
36 | #define SRC_LEFT_TOP_REG 0x0310 /* Src Left Top Coordinate reg */ | ||
37 | #define SRC_RIGHT_BOTTOM_REG 0x0314 /* Src Right Bottom Coordinate reg */ | ||
38 | |||
39 | /* Parameter Setting Registers (Dest) */ | ||
40 | #define DST_SELECT_REG 0x0400 /* Dest Image Selection reg */ | ||
41 | #define DST_BASE_ADDR_REG 0x0404 /* Dest Image Base Address reg */ | ||
42 | #define DST_STRIDE_REG 0x0408 /* Dest Stride reg */ | ||
43 | #define DST_COLOR_MODE_REG 0x040C /* Dest Image Color Mode reg */ | ||
44 | #define DST_LEFT_TOP_REG 0x0410 /* Dest Left Top Coordinate reg */ | ||
45 | #define DST_RIGHT_BOTTOM_REG 0x0414 /* Dest Right Bottom Coordinate reg */ | ||
46 | |||
47 | /* Parameter Setting Registers (Pattern) */ | ||
48 | #define PAT_BASE_ADDR_REG 0x0500 /* Pattern Image Base Address reg */ | ||
49 | #define PAT_SIZE_REG 0x0504 /* Pattern Image Size reg */ | ||
50 | #define PAT_COLOR_MODE_REG 0x0508 /* Pattern Image Color Mode reg */ | ||
51 | #define PAT_OFFSET_REG 0x050C /* Pattern Left Top Coordinate reg */ | ||
52 | #define PAT_STRIDE_REG 0x0510 /* Pattern Stride reg */ | ||
53 | |||
54 | /* Parameter Setting Registers (Mask) */ | ||
55 | #define MASK_BASE_ADDR_REG 0x0520 /* Mask Base Address reg */ | ||
56 | #define MASK_STRIDE_REG 0x0524 /* Mask Stride reg */ | ||
57 | |||
58 | /* Parameter Setting Registers (Clipping Window) */ | ||
59 | #define CW_LT_REG 0x0600 /* LeftTop coordinates of Clip Window */ | ||
60 | #define CW_RB_REG 0x0604 /* RightBottom coordinates of Clip | ||
61 | Window */ | ||
62 | |||
63 | /* Parameter Setting Registers (ROP & Alpha Setting) */ | ||
64 | #define THIRD_OPERAND_REG 0x0610 /* Third Operand Selection reg */ | ||
65 | #define ROP4_REG 0x0614 /* Raster Operation reg */ | ||
66 | #define ALPHA_REG 0x0618 /* Alpha value, Fading offset value */ | ||
67 | |||
68 | /* Parameter Setting Registers (Color) */ | ||
69 | #define FG_COLOR_REG 0x0700 /* Foreground Color reg */ | ||
70 | #define BG_COLOR_REG 0x0704 /* Background Color reg */ | ||
71 | #define BS_COLOR_REG 0x0708 /* Blue Screen Color reg */ | ||
72 | |||
73 | /* Parameter Setting Registers (Color Key) */ | ||
74 | #define SRC_COLORKEY_CTRL_REG 0x0710 /* Src Colorkey control reg */ | ||
75 | #define SRC_COLORKEY_DR_MIN_REG 0x0714 /* Src Colorkey Decision Reference | ||
76 | Min reg */ | ||
77 | #define SRC_COLORKEY_DR_MAX_REG 0x0718 /* Src Colorkey Decision Reference | ||
78 | Max reg */ | ||
79 | #define DST_COLORKEY_CTRL_REG 0x071C /* Dest Colorkey control reg */ | ||
80 | #define DST_COLORKEY_DR_MIN_REG 0x0720 /* Dest Colorkey Decision Reference | ||
81 | Min reg */ | ||
82 | #define DST_COLORKEY_DR_MAX_REG 0x0724 /* Dest Colorkey Decision Reference | ||
83 | Max reg */ | ||
84 | |||
85 | /* Color mode values */ | ||
86 | |||
87 | #define ORDER_XRGB 0 | ||
88 | #define ORDER_RGBX 1 | ||
89 | #define ORDER_XBGR 2 | ||
90 | #define ORDER_BGRX 3 | ||
91 | |||
92 | #define MODE_XRGB_8888 0 | ||
93 | #define MODE_ARGB_8888 1 | ||
94 | #define MODE_RGB_565 2 | ||
95 | #define MODE_XRGB_1555 3 | ||
96 | #define MODE_ARGB_1555 4 | ||
97 | #define MODE_XRGB_4444 5 | ||
98 | #define MODE_ARGB_4444 6 | ||
99 | #define MODE_PACKED_RGB_888 7 | ||
100 | |||
101 | #define COLOR_MODE(o, m) (((o) << 4) | (m)) | ||
102 | |||
103 | /* ROP4 operation values */ | ||
104 | #define ROP4_COPY 0xCCCC | ||
105 | #define ROP4_INVERT 0x3333 | ||
106 | |||
107 | /* Hardware limits */ | ||
108 | #define MAX_WIDTH 8000 | ||
109 | #define MAX_HEIGHT 8000 | ||
110 | |||
111 | #define G2D_TIMEOUT 500 | ||
112 | |||
113 | #define DEFAULT_WIDTH 100 | ||
114 | #define DEFAULT_HEIGHT 100 | ||
115 | |||
diff --git a/drivers/media/video/s5p-g2d/g2d.c b/drivers/media/video/s5p-g2d/g2d.c new file mode 100644 index 000000000000..c40b0dde1883 --- /dev/null +++ b/drivers/media/video/s5p-g2d/g2d.c | |||
@@ -0,0 +1,810 @@ | |||
1 | /* | ||
2 | * Samsung S5P G2D - 2D Graphics Accelerator Driver | ||
3 | * | ||
4 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
5 | * Kamil Debski, <k.debski@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the | ||
10 | * License, or (at your option) any later version | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/fs.h> | ||
15 | #include <linux/version.h> | ||
16 | #include <linux/timer.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | |||
22 | #include <linux/platform_device.h> | ||
23 | #include <media/v4l2-mem2mem.h> | ||
24 | #include <media/v4l2-device.h> | ||
25 | #include <media/v4l2-ioctl.h> | ||
26 | #include <media/videobuf2-core.h> | ||
27 | #include <media/videobuf2-dma-contig.h> | ||
28 | |||
29 | #include "g2d.h" | ||
30 | #include "g2d-regs.h" | ||
31 | |||
32 | #define fh2ctx(__fh) container_of(__fh, struct g2d_ctx, fh) | ||
33 | |||
34 | static struct g2d_fmt formats[] = { | ||
35 | { | ||
36 | .name = "XRGB_8888", | ||
37 | .fourcc = V4L2_PIX_FMT_RGB32, | ||
38 | .depth = 32, | ||
39 | .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_8888), | ||
40 | }, | ||
41 | { | ||
42 | .name = "RGB_565", | ||
43 | .fourcc = V4L2_PIX_FMT_RGB565X, | ||
44 | .depth = 16, | ||
45 | .hw = COLOR_MODE(ORDER_XRGB, MODE_RGB_565), | ||
46 | }, | ||
47 | { | ||
48 | .name = "XRGB_1555", | ||
49 | .fourcc = V4L2_PIX_FMT_RGB555X, | ||
50 | .depth = 16, | ||
51 | .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_1555), | ||
52 | }, | ||
53 | { | ||
54 | .name = "XRGB_4444", | ||
55 | .fourcc = V4L2_PIX_FMT_RGB444, | ||
56 | .depth = 16, | ||
57 | .hw = COLOR_MODE(ORDER_XRGB, MODE_XRGB_4444), | ||
58 | }, | ||
59 | { | ||
60 | .name = "PACKED_RGB_888", | ||
61 | .fourcc = V4L2_PIX_FMT_RGB24, | ||
62 | .depth = 24, | ||
63 | .hw = COLOR_MODE(ORDER_XRGB, MODE_PACKED_RGB_888), | ||
64 | }, | ||
65 | }; | ||
66 | #define NUM_FORMATS ARRAY_SIZE(formats) | ||
67 | |||
68 | struct g2d_frame def_frame = { | ||
69 | .width = DEFAULT_WIDTH, | ||
70 | .height = DEFAULT_HEIGHT, | ||
71 | .c_width = DEFAULT_WIDTH, | ||
72 | .c_height = DEFAULT_HEIGHT, | ||
73 | .o_width = 0, | ||
74 | .o_height = 0, | ||
75 | .fmt = &formats[0], | ||
76 | .right = DEFAULT_WIDTH, | ||
77 | .bottom = DEFAULT_HEIGHT, | ||
78 | }; | ||
79 | |||
80 | struct g2d_fmt *find_fmt(struct v4l2_format *f) | ||
81 | { | ||
82 | unsigned int i; | ||
83 | for (i = 0; i < NUM_FORMATS; i++) { | ||
84 | if (formats[i].fourcc == f->fmt.pix.pixelformat) | ||
85 | return &formats[i]; | ||
86 | } | ||
87 | return NULL; | ||
88 | } | ||
89 | |||
90 | |||
91 | static struct g2d_frame *get_frame(struct g2d_ctx *ctx, | ||
92 | enum v4l2_buf_type type) | ||
93 | { | ||
94 | switch (type) { | ||
95 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
96 | return &ctx->in; | ||
97 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | ||
98 | return &ctx->out; | ||
99 | default: | ||
100 | return ERR_PTR(-EINVAL); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | static int g2d_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, | ||
105 | unsigned int *nbuffers, unsigned int *nplanes, | ||
106 | unsigned int sizes[], void *alloc_ctxs[]) | ||
107 | { | ||
108 | struct g2d_ctx *ctx = vb2_get_drv_priv(vq); | ||
109 | struct g2d_frame *f = get_frame(ctx, vq->type); | ||
110 | |||
111 | if (IS_ERR(f)) | ||
112 | return PTR_ERR(f); | ||
113 | |||
114 | sizes[0] = f->size; | ||
115 | *nplanes = 1; | ||
116 | alloc_ctxs[0] = ctx->dev->alloc_ctx; | ||
117 | |||
118 | if (*nbuffers == 0) | ||
119 | *nbuffers = 1; | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static int g2d_buf_prepare(struct vb2_buffer *vb) | ||
125 | { | ||
126 | struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||
127 | struct g2d_frame *f = get_frame(ctx, vb->vb2_queue->type); | ||
128 | |||
129 | if (IS_ERR(f)) | ||
130 | return PTR_ERR(f); | ||
131 | vb2_set_plane_payload(vb, 0, f->size); | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static void g2d_buf_queue(struct vb2_buffer *vb) | ||
136 | { | ||
137 | struct g2d_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||
138 | v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); | ||
139 | } | ||
140 | |||
141 | |||
142 | static struct vb2_ops g2d_qops = { | ||
143 | .queue_setup = g2d_queue_setup, | ||
144 | .buf_prepare = g2d_buf_prepare, | ||
145 | .buf_queue = g2d_buf_queue, | ||
146 | }; | ||
147 | |||
148 | static int queue_init(void *priv, struct vb2_queue *src_vq, | ||
149 | struct vb2_queue *dst_vq) | ||
150 | { | ||
151 | struct g2d_ctx *ctx = priv; | ||
152 | int ret; | ||
153 | |||
154 | memset(src_vq, 0, sizeof(*src_vq)); | ||
155 | src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
156 | src_vq->io_modes = VB2_MMAP | VB2_USERPTR; | ||
157 | src_vq->drv_priv = ctx; | ||
158 | src_vq->ops = &g2d_qops; | ||
159 | src_vq->mem_ops = &vb2_dma_contig_memops; | ||
160 | src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); | ||
161 | |||
162 | ret = vb2_queue_init(src_vq); | ||
163 | if (ret) | ||
164 | return ret; | ||
165 | |||
166 | memset(dst_vq, 0, sizeof(*dst_vq)); | ||
167 | dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
168 | dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; | ||
169 | dst_vq->drv_priv = ctx; | ||
170 | dst_vq->ops = &g2d_qops; | ||
171 | dst_vq->mem_ops = &vb2_dma_contig_memops; | ||
172 | dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); | ||
173 | |||
174 | return vb2_queue_init(dst_vq); | ||
175 | } | ||
176 | |||
177 | static int g2d_s_ctrl(struct v4l2_ctrl *ctrl) | ||
178 | { | ||
179 | struct g2d_ctx *ctx = container_of(ctrl->handler, struct g2d_ctx, | ||
180 | ctrl_handler); | ||
181 | switch (ctrl->id) { | ||
182 | case V4L2_CID_COLORFX: | ||
183 | if (ctrl->val == V4L2_COLORFX_NEGATIVE) | ||
184 | ctx->rop = ROP4_INVERT; | ||
185 | else | ||
186 | ctx->rop = ROP4_COPY; | ||
187 | default: | ||
188 | v4l2_err(&ctx->dev->v4l2_dev, "unknown control\n"); | ||
189 | return -EINVAL; | ||
190 | } | ||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static const struct v4l2_ctrl_ops g2d_ctrl_ops = { | ||
195 | .s_ctrl = g2d_s_ctrl, | ||
196 | }; | ||
197 | |||
198 | int g2d_setup_ctrls(struct g2d_ctx *ctx) | ||
199 | { | ||
200 | struct g2d_dev *dev = ctx->dev; | ||
201 | |||
202 | v4l2_ctrl_handler_init(&ctx->ctrl_handler, 1); | ||
203 | if (ctx->ctrl_handler.error) { | ||
204 | v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n"); | ||
205 | return ctx->ctrl_handler.error; | ||
206 | } | ||
207 | |||
208 | v4l2_ctrl_new_std_menu( | ||
209 | &ctx->ctrl_handler, | ||
210 | &g2d_ctrl_ops, | ||
211 | V4L2_CID_COLORFX, | ||
212 | V4L2_COLORFX_NEGATIVE, | ||
213 | ~((1 << V4L2_COLORFX_NONE) | (1 << V4L2_COLORFX_NEGATIVE)), | ||
214 | V4L2_COLORFX_NONE); | ||
215 | |||
216 | if (ctx->ctrl_handler.error) { | ||
217 | v4l2_err(&dev->v4l2_dev, "v4l2_ctrl_handler_init failed\n"); | ||
218 | return ctx->ctrl_handler.error; | ||
219 | } | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static int g2d_open(struct file *file) | ||
225 | { | ||
226 | struct g2d_dev *dev = video_drvdata(file); | ||
227 | struct g2d_ctx *ctx = NULL; | ||
228 | int ret = 0; | ||
229 | |||
230 | ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); | ||
231 | if (!ctx) | ||
232 | return -ENOMEM; | ||
233 | ctx->dev = dev; | ||
234 | /* Set default formats */ | ||
235 | ctx->in = def_frame; | ||
236 | ctx->out = def_frame; | ||
237 | |||
238 | ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init); | ||
239 | if (IS_ERR(ctx->m2m_ctx)) { | ||
240 | ret = PTR_ERR(ctx->m2m_ctx); | ||
241 | kfree(ctx); | ||
242 | return ret; | ||
243 | } | ||
244 | v4l2_fh_init(&ctx->fh, video_devdata(file)); | ||
245 | file->private_data = &ctx->fh; | ||
246 | v4l2_fh_add(&ctx->fh); | ||
247 | |||
248 | g2d_setup_ctrls(ctx); | ||
249 | |||
250 | /* Write the default values to the ctx struct */ | ||
251 | v4l2_ctrl_handler_setup(&ctx->ctrl_handler); | ||
252 | |||
253 | ctx->fh.ctrl_handler = &ctx->ctrl_handler; | ||
254 | |||
255 | v4l2_info(&dev->v4l2_dev, "instance opened\n"); | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int g2d_release(struct file *file) | ||
260 | { | ||
261 | struct g2d_dev *dev = video_drvdata(file); | ||
262 | struct g2d_ctx *ctx = fh2ctx(file->private_data); | ||
263 | |||
264 | v4l2_ctrl_handler_free(&ctx->ctrl_handler); | ||
265 | v4l2_fh_del(&ctx->fh); | ||
266 | v4l2_fh_exit(&ctx->fh); | ||
267 | kfree(ctx); | ||
268 | v4l2_info(&dev->v4l2_dev, "instance closed\n"); | ||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | |||
273 | static int vidioc_querycap(struct file *file, void *priv, | ||
274 | struct v4l2_capability *cap) | ||
275 | { | ||
276 | strncpy(cap->driver, G2D_NAME, sizeof(cap->driver) - 1); | ||
277 | strncpy(cap->card, G2D_NAME, sizeof(cap->card) - 1); | ||
278 | cap->bus_info[0] = 0; | ||
279 | cap->version = KERNEL_VERSION(1, 0, 0); | ||
280 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT | ||
281 | | V4L2_CAP_STREAMING; | ||
282 | return 0; | ||
283 | } | ||
284 | |||
285 | static int vidioc_enum_fmt(struct file *file, void *prv, struct v4l2_fmtdesc *f) | ||
286 | { | ||
287 | struct g2d_fmt *fmt; | ||
288 | if (f->index >= NUM_FORMATS) | ||
289 | return -EINVAL; | ||
290 | fmt = &formats[f->index]; | ||
291 | f->pixelformat = fmt->fourcc; | ||
292 | strncpy(f->description, fmt->name, sizeof(f->description) - 1); | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static int vidioc_g_fmt(struct file *file, void *prv, struct v4l2_format *f) | ||
297 | { | ||
298 | struct g2d_ctx *ctx = prv; | ||
299 | struct vb2_queue *vq; | ||
300 | struct g2d_frame *frm; | ||
301 | |||
302 | vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); | ||
303 | if (!vq) | ||
304 | return -EINVAL; | ||
305 | frm = get_frame(ctx, f->type); | ||
306 | if (IS_ERR(frm)) | ||
307 | return PTR_ERR(frm); | ||
308 | |||
309 | f->fmt.pix.width = frm->width; | ||
310 | f->fmt.pix.height = frm->height; | ||
311 | f->fmt.pix.field = V4L2_FIELD_NONE; | ||
312 | f->fmt.pix.pixelformat = frm->fmt->fourcc; | ||
313 | f->fmt.pix.bytesperline = (frm->width * frm->fmt->depth) >> 3; | ||
314 | f->fmt.pix.sizeimage = frm->size; | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static int vidioc_try_fmt(struct file *file, void *prv, struct v4l2_format *f) | ||
319 | { | ||
320 | struct g2d_fmt *fmt; | ||
321 | enum v4l2_field *field; | ||
322 | |||
323 | fmt = find_fmt(f); | ||
324 | if (!fmt) | ||
325 | return -EINVAL; | ||
326 | |||
327 | field = &f->fmt.pix.field; | ||
328 | if (*field == V4L2_FIELD_ANY) | ||
329 | *field = V4L2_FIELD_NONE; | ||
330 | else if (*field != V4L2_FIELD_NONE) | ||
331 | return -EINVAL; | ||
332 | |||
333 | if (f->fmt.pix.width > MAX_WIDTH) | ||
334 | f->fmt.pix.width = MAX_WIDTH; | ||
335 | if (f->fmt.pix.height > MAX_HEIGHT) | ||
336 | f->fmt.pix.height = MAX_HEIGHT; | ||
337 | |||
338 | if (f->fmt.pix.width < 1) | ||
339 | f->fmt.pix.width = 1; | ||
340 | if (f->fmt.pix.height < 1) | ||
341 | f->fmt.pix.height = 1; | ||
342 | |||
343 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; | ||
344 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | ||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f) | ||
349 | { | ||
350 | struct g2d_ctx *ctx = prv; | ||
351 | struct g2d_dev *dev = ctx->dev; | ||
352 | struct vb2_queue *vq; | ||
353 | struct g2d_frame *frm; | ||
354 | struct g2d_fmt *fmt; | ||
355 | int ret = 0; | ||
356 | |||
357 | /* Adjust all values accordingly to the hardware capabilities | ||
358 | * and chosen format. */ | ||
359 | ret = vidioc_try_fmt(file, prv, f); | ||
360 | if (ret) | ||
361 | return ret; | ||
362 | vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type); | ||
363 | if (vb2_is_busy(vq)) { | ||
364 | v4l2_err(&dev->v4l2_dev, "queue (%d) bust\n", f->type); | ||
365 | return -EBUSY; | ||
366 | } | ||
367 | frm = get_frame(ctx, f->type); | ||
368 | if (IS_ERR(frm)) | ||
369 | return PTR_ERR(frm); | ||
370 | fmt = find_fmt(f); | ||
371 | if (!fmt) | ||
372 | return -EINVAL; | ||
373 | frm->width = f->fmt.pix.width; | ||
374 | frm->height = f->fmt.pix.height; | ||
375 | frm->size = f->fmt.pix.sizeimage; | ||
376 | /* Reset crop settings */ | ||
377 | frm->o_width = 0; | ||
378 | frm->o_height = 0; | ||
379 | frm->c_width = frm->width; | ||
380 | frm->c_height = frm->height; | ||
381 | frm->right = frm->width; | ||
382 | frm->bottom = frm->height; | ||
383 | frm->fmt = fmt; | ||
384 | frm->stride = f->fmt.pix.bytesperline; | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | static unsigned int g2d_poll(struct file *file, struct poll_table_struct *wait) | ||
389 | { | ||
390 | struct g2d_ctx *ctx = fh2ctx(file->private_data); | ||
391 | return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); | ||
392 | } | ||
393 | |||
394 | static int g2d_mmap(struct file *file, struct vm_area_struct *vma) | ||
395 | { | ||
396 | struct g2d_ctx *ctx = fh2ctx(file->private_data); | ||
397 | return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); | ||
398 | } | ||
399 | |||
400 | static int vidioc_reqbufs(struct file *file, void *priv, | ||
401 | struct v4l2_requestbuffers *reqbufs) | ||
402 | { | ||
403 | struct g2d_ctx *ctx = priv; | ||
404 | return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); | ||
405 | } | ||
406 | |||
407 | static int vidioc_querybuf(struct file *file, void *priv, | ||
408 | struct v4l2_buffer *buf) | ||
409 | { | ||
410 | struct g2d_ctx *ctx = priv; | ||
411 | return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); | ||
412 | } | ||
413 | |||
414 | static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
415 | { | ||
416 | struct g2d_ctx *ctx = priv; | ||
417 | return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); | ||
418 | } | ||
419 | |||
420 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
421 | { | ||
422 | struct g2d_ctx *ctx = priv; | ||
423 | return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); | ||
424 | } | ||
425 | |||
426 | |||
427 | static int vidioc_streamon(struct file *file, void *priv, | ||
428 | enum v4l2_buf_type type) | ||
429 | { | ||
430 | struct g2d_ctx *ctx = priv; | ||
431 | return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); | ||
432 | } | ||
433 | |||
434 | static int vidioc_streamoff(struct file *file, void *priv, | ||
435 | enum v4l2_buf_type type) | ||
436 | { | ||
437 | struct g2d_ctx *ctx = priv; | ||
438 | return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); | ||
439 | } | ||
440 | |||
441 | static int vidioc_cropcap(struct file *file, void *priv, | ||
442 | struct v4l2_cropcap *cr) | ||
443 | { | ||
444 | struct g2d_ctx *ctx = priv; | ||
445 | struct g2d_frame *f; | ||
446 | |||
447 | f = get_frame(ctx, cr->type); | ||
448 | if (IS_ERR(f)) | ||
449 | return PTR_ERR(f); | ||
450 | |||
451 | cr->bounds.left = 0; | ||
452 | cr->bounds.top = 0; | ||
453 | cr->bounds.width = f->width; | ||
454 | cr->bounds.height = f->height; | ||
455 | cr->defrect = cr->bounds; | ||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | static int vidioc_g_crop(struct file *file, void *prv, struct v4l2_crop *cr) | ||
460 | { | ||
461 | struct g2d_ctx *ctx = prv; | ||
462 | struct g2d_frame *f; | ||
463 | |||
464 | f = get_frame(ctx, cr->type); | ||
465 | if (IS_ERR(f)) | ||
466 | return PTR_ERR(f); | ||
467 | |||
468 | cr->c.left = f->o_height; | ||
469 | cr->c.top = f->o_width; | ||
470 | cr->c.width = f->c_width; | ||
471 | cr->c.height = f->c_height; | ||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | static int vidioc_try_crop(struct file *file, void *prv, struct v4l2_crop *cr) | ||
476 | { | ||
477 | struct g2d_ctx *ctx = prv; | ||
478 | struct g2d_dev *dev = ctx->dev; | ||
479 | struct g2d_frame *f; | ||
480 | |||
481 | f = get_frame(ctx, cr->type); | ||
482 | if (IS_ERR(f)) | ||
483 | return PTR_ERR(f); | ||
484 | |||
485 | if (cr->c.top < 0 || cr->c.left < 0) { | ||
486 | v4l2_err(&dev->v4l2_dev, | ||
487 | "doesn't support negative values for top & left\n"); | ||
488 | return -EINVAL; | ||
489 | } | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | static int vidioc_s_crop(struct file *file, void *prv, struct v4l2_crop *cr) | ||
495 | { | ||
496 | struct g2d_ctx *ctx = prv; | ||
497 | struct g2d_frame *f; | ||
498 | int ret; | ||
499 | |||
500 | ret = vidioc_try_crop(file, prv, cr); | ||
501 | if (ret) | ||
502 | return ret; | ||
503 | f = get_frame(ctx, cr->type); | ||
504 | if (IS_ERR(f)) | ||
505 | return PTR_ERR(f); | ||
506 | |||
507 | f->c_width = cr->c.width; | ||
508 | f->c_height = cr->c.height; | ||
509 | f->o_width = cr->c.left; | ||
510 | f->o_height = cr->c.top; | ||
511 | f->bottom = f->o_height + f->c_height; | ||
512 | f->right = f->o_width + f->c_width; | ||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | static void g2d_lock(void *prv) | ||
517 | { | ||
518 | struct g2d_ctx *ctx = prv; | ||
519 | struct g2d_dev *dev = ctx->dev; | ||
520 | mutex_lock(&dev->mutex); | ||
521 | } | ||
522 | |||
523 | static void g2d_unlock(void *prv) | ||
524 | { | ||
525 | struct g2d_ctx *ctx = prv; | ||
526 | struct g2d_dev *dev = ctx->dev; | ||
527 | mutex_unlock(&dev->mutex); | ||
528 | } | ||
529 | |||
530 | static void job_abort(void *prv) | ||
531 | { | ||
532 | struct g2d_ctx *ctx = prv; | ||
533 | struct g2d_dev *dev = ctx->dev; | ||
534 | int ret; | ||
535 | |||
536 | if (dev->curr == 0) /* No job currently running */ | ||
537 | return; | ||
538 | |||
539 | ret = wait_event_timeout(dev->irq_queue, | ||
540 | dev->curr == 0, | ||
541 | msecs_to_jiffies(G2D_TIMEOUT)); | ||
542 | } | ||
543 | |||
544 | static void device_run(void *prv) | ||
545 | { | ||
546 | struct g2d_ctx *ctx = prv; | ||
547 | struct g2d_dev *dev = ctx->dev; | ||
548 | struct vb2_buffer *src, *dst; | ||
549 | u32 cmd = 0; | ||
550 | |||
551 | dev->curr = ctx; | ||
552 | |||
553 | src = v4l2_m2m_next_src_buf(ctx->m2m_ctx); | ||
554 | dst = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | ||
555 | |||
556 | clk_enable(dev->gate); | ||
557 | g2d_reset(dev); | ||
558 | |||
559 | g2d_set_src_size(dev, &ctx->in); | ||
560 | g2d_set_src_addr(dev, vb2_dma_contig_plane_dma_addr(src, 0)); | ||
561 | |||
562 | g2d_set_dst_size(dev, &ctx->out); | ||
563 | g2d_set_dst_addr(dev, vb2_dma_contig_plane_dma_addr(dst, 0)); | ||
564 | |||
565 | g2d_set_rop4(dev, ctx->rop); | ||
566 | if (ctx->in.c_width != ctx->out.c_width || | ||
567 | ctx->in.c_height != ctx->out.c_height) | ||
568 | cmd |= g2d_cmd_stretch(1); | ||
569 | g2d_set_cmd(dev, cmd); | ||
570 | g2d_start(dev); | ||
571 | } | ||
572 | |||
573 | static irqreturn_t g2d_isr(int irq, void *prv) | ||
574 | { | ||
575 | struct g2d_dev *dev = prv; | ||
576 | struct g2d_ctx *ctx = dev->curr; | ||
577 | struct vb2_buffer *src, *dst; | ||
578 | |||
579 | g2d_clear_int(dev); | ||
580 | clk_disable(dev->gate); | ||
581 | |||
582 | BUG_ON(ctx == 0); | ||
583 | |||
584 | src = v4l2_m2m_src_buf_remove(ctx->m2m_ctx); | ||
585 | dst = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx); | ||
586 | |||
587 | BUG_ON(src == 0); | ||
588 | BUG_ON(dst == 0); | ||
589 | |||
590 | v4l2_m2m_buf_done(src, VB2_BUF_STATE_DONE); | ||
591 | v4l2_m2m_buf_done(dst, VB2_BUF_STATE_DONE); | ||
592 | v4l2_m2m_job_finish(dev->m2m_dev, ctx->m2m_ctx); | ||
593 | |||
594 | dev->curr = 0; | ||
595 | wake_up(&dev->irq_queue); | ||
596 | return IRQ_HANDLED; | ||
597 | } | ||
598 | |||
599 | static const struct v4l2_file_operations g2d_fops = { | ||
600 | .owner = THIS_MODULE, | ||
601 | .open = g2d_open, | ||
602 | .release = g2d_release, | ||
603 | .poll = g2d_poll, | ||
604 | .unlocked_ioctl = video_ioctl2, | ||
605 | .mmap = g2d_mmap, | ||
606 | }; | ||
607 | |||
608 | static const struct v4l2_ioctl_ops g2d_ioctl_ops = { | ||
609 | .vidioc_querycap = vidioc_querycap, | ||
610 | |||
611 | .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt, | ||
612 | .vidioc_g_fmt_vid_cap = vidioc_g_fmt, | ||
613 | .vidioc_try_fmt_vid_cap = vidioc_try_fmt, | ||
614 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt, | ||
615 | |||
616 | .vidioc_enum_fmt_vid_out = vidioc_enum_fmt, | ||
617 | .vidioc_g_fmt_vid_out = vidioc_g_fmt, | ||
618 | .vidioc_try_fmt_vid_out = vidioc_try_fmt, | ||
619 | .vidioc_s_fmt_vid_out = vidioc_s_fmt, | ||
620 | |||
621 | .vidioc_reqbufs = vidioc_reqbufs, | ||
622 | .vidioc_querybuf = vidioc_querybuf, | ||
623 | |||
624 | .vidioc_qbuf = vidioc_qbuf, | ||
625 | .vidioc_dqbuf = vidioc_dqbuf, | ||
626 | |||
627 | .vidioc_streamon = vidioc_streamon, | ||
628 | .vidioc_streamoff = vidioc_streamoff, | ||
629 | |||
630 | .vidioc_g_crop = vidioc_g_crop, | ||
631 | .vidioc_s_crop = vidioc_s_crop, | ||
632 | .vidioc_cropcap = vidioc_cropcap, | ||
633 | }; | ||
634 | |||
635 | static struct video_device g2d_videodev = { | ||
636 | .name = G2D_NAME, | ||
637 | .fops = &g2d_fops, | ||
638 | .ioctl_ops = &g2d_ioctl_ops, | ||
639 | .minor = -1, | ||
640 | .release = video_device_release, | ||
641 | }; | ||
642 | |||
643 | static struct v4l2_m2m_ops g2d_m2m_ops = { | ||
644 | .device_run = device_run, | ||
645 | .job_abort = job_abort, | ||
646 | .lock = g2d_lock, | ||
647 | .unlock = g2d_unlock, | ||
648 | }; | ||
649 | |||
650 | static int g2d_probe(struct platform_device *pdev) | ||
651 | { | ||
652 | struct g2d_dev *dev; | ||
653 | struct video_device *vfd; | ||
654 | struct resource *res; | ||
655 | int ret = 0; | ||
656 | |||
657 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
658 | if (!dev) | ||
659 | return -ENOMEM; | ||
660 | spin_lock_init(&dev->irqlock); | ||
661 | mutex_init(&dev->mutex); | ||
662 | atomic_set(&dev->num_inst, 0); | ||
663 | init_waitqueue_head(&dev->irq_queue); | ||
664 | |||
665 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
666 | if (!res) { | ||
667 | dev_err(&pdev->dev, "failed to find registers\n"); | ||
668 | ret = -ENOENT; | ||
669 | goto free_dev; | ||
670 | } | ||
671 | |||
672 | dev->res_regs = request_mem_region(res->start, resource_size(res), | ||
673 | dev_name(&pdev->dev)); | ||
674 | |||
675 | if (!dev->res_regs) { | ||
676 | dev_err(&pdev->dev, "failed to obtain register region\n"); | ||
677 | ret = -ENOENT; | ||
678 | goto free_dev; | ||
679 | } | ||
680 | |||
681 | dev->regs = ioremap(res->start, resource_size(res)); | ||
682 | if (!dev->regs) { | ||
683 | dev_err(&pdev->dev, "failed to map registers\n"); | ||
684 | ret = -ENOENT; | ||
685 | goto rel_res_regs; | ||
686 | } | ||
687 | |||
688 | dev->clk = clk_get(&pdev->dev, "sclk_fimg2d"); | ||
689 | if (IS_ERR_OR_NULL(dev->clk)) { | ||
690 | dev_err(&pdev->dev, "failed to get g2d clock\n"); | ||
691 | ret = -ENXIO; | ||
692 | goto unmap_regs; | ||
693 | } | ||
694 | |||
695 | dev->gate = clk_get(&pdev->dev, "fimg2d"); | ||
696 | if (IS_ERR_OR_NULL(dev->gate)) { | ||
697 | dev_err(&pdev->dev, "failed to get g2d clock gate\n"); | ||
698 | ret = -ENXIO; | ||
699 | goto put_clk; | ||
700 | } | ||
701 | |||
702 | res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||
703 | if (!res) { | ||
704 | dev_err(&pdev->dev, "failed to find IRQ\n"); | ||
705 | ret = -ENXIO; | ||
706 | goto put_clk_gate; | ||
707 | } | ||
708 | |||
709 | dev->irq = res->start; | ||
710 | |||
711 | ret = request_irq(dev->irq, g2d_isr, 0, pdev->name, dev); | ||
712 | if (ret) { | ||
713 | dev_err(&pdev->dev, "failed to install IRQ\n"); | ||
714 | goto put_clk_gate; | ||
715 | } | ||
716 | |||
717 | dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | ||
718 | if (IS_ERR(dev->alloc_ctx)) { | ||
719 | ret = PTR_ERR(dev->alloc_ctx); | ||
720 | goto rel_irq; | ||
721 | } | ||
722 | |||
723 | ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); | ||
724 | if (ret) | ||
725 | goto alloc_ctx_cleanup; | ||
726 | vfd = video_device_alloc(); | ||
727 | if (!vfd) { | ||
728 | v4l2_err(&dev->v4l2_dev, "Failed to allocate video device\n"); | ||
729 | ret = -ENOMEM; | ||
730 | goto unreg_v4l2_dev; | ||
731 | } | ||
732 | *vfd = g2d_videodev; | ||
733 | vfd->lock = &dev->mutex; | ||
734 | ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0); | ||
735 | if (ret) { | ||
736 | v4l2_err(&dev->v4l2_dev, "Failed to register video device\n"); | ||
737 | goto rel_vdev; | ||
738 | } | ||
739 | video_set_drvdata(vfd, dev); | ||
740 | snprintf(vfd->name, sizeof(vfd->name), "%s", g2d_videodev.name); | ||
741 | dev->vfd = vfd; | ||
742 | v4l2_info(&dev->v4l2_dev, "device registered as /dev/video%d\n", | ||
743 | vfd->num); | ||
744 | platform_set_drvdata(pdev, dev); | ||
745 | dev->m2m_dev = v4l2_m2m_init(&g2d_m2m_ops); | ||
746 | if (IS_ERR(dev->m2m_dev)) { | ||
747 | v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n"); | ||
748 | ret = PTR_ERR(dev->m2m_dev); | ||
749 | goto unreg_video_dev; | ||
750 | } | ||
751 | |||
752 | def_frame.stride = (def_frame.width * def_frame.fmt->depth) >> 3; | ||
753 | |||
754 | return 0; | ||
755 | |||
756 | unreg_video_dev: | ||
757 | video_unregister_device(dev->vfd); | ||
758 | rel_vdev: | ||
759 | video_device_release(vfd); | ||
760 | unreg_v4l2_dev: | ||
761 | v4l2_device_unregister(&dev->v4l2_dev); | ||
762 | alloc_ctx_cleanup: | ||
763 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); | ||
764 | rel_irq: | ||
765 | free_irq(dev->irq, dev); | ||
766 | put_clk_gate: | ||
767 | clk_put(dev->gate); | ||
768 | put_clk: | ||
769 | clk_put(dev->clk); | ||
770 | unmap_regs: | ||
771 | iounmap(dev->regs); | ||
772 | rel_res_regs: | ||
773 | release_resource(dev->res_regs); | ||
774 | free_dev: | ||
775 | kfree(dev); | ||
776 | return ret; | ||
777 | } | ||
778 | |||
779 | static int g2d_remove(struct platform_device *pdev) | ||
780 | { | ||
781 | struct g2d_dev *dev = (struct g2d_dev *)platform_get_drvdata(pdev); | ||
782 | |||
783 | v4l2_info(&dev->v4l2_dev, "Removing " G2D_NAME); | ||
784 | v4l2_m2m_release(dev->m2m_dev); | ||
785 | video_unregister_device(dev->vfd); | ||
786 | v4l2_device_unregister(&dev->v4l2_dev); | ||
787 | vb2_dma_contig_cleanup_ctx(dev->alloc_ctx); | ||
788 | free_irq(dev->irq, dev); | ||
789 | clk_put(dev->gate); | ||
790 | clk_put(dev->clk); | ||
791 | iounmap(dev->regs); | ||
792 | release_resource(dev->res_regs); | ||
793 | kfree(dev); | ||
794 | return 0; | ||
795 | } | ||
796 | |||
797 | static struct platform_driver g2d_pdrv = { | ||
798 | .probe = g2d_probe, | ||
799 | .remove = g2d_remove, | ||
800 | .driver = { | ||
801 | .name = G2D_NAME, | ||
802 | .owner = THIS_MODULE, | ||
803 | }, | ||
804 | }; | ||
805 | |||
806 | module_platform_driver(g2d_pdrv); | ||
807 | |||
808 | MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>"); | ||
809 | MODULE_DESCRIPTION("S5P G2D 2d graphics accelerator driver"); | ||
810 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/video/s5p-g2d/g2d.h b/drivers/media/video/s5p-g2d/g2d.h new file mode 100644 index 000000000000..5eae90107bf8 --- /dev/null +++ b/drivers/media/video/s5p-g2d/g2d.h | |||
@@ -0,0 +1,83 @@ | |||
1 | /* | ||
2 | * Samsung S5P G2D - 2D Graphics Accelerator Driver | ||
3 | * | ||
4 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
5 | * Kamil Debski, <k.debski@samsung.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the | ||
10 | * License, or (at your option) any later version | ||
11 | */ | ||
12 | |||
13 | #include <media/v4l2-device.h> | ||
14 | #include <media/v4l2-ctrls.h> | ||
15 | |||
16 | #define G2D_NAME "s5p-g2d" | ||
17 | |||
18 | struct g2d_dev { | ||
19 | struct v4l2_device v4l2_dev; | ||
20 | struct v4l2_m2m_dev *m2m_dev; | ||
21 | struct video_device *vfd; | ||
22 | struct mutex mutex; | ||
23 | spinlock_t irqlock; | ||
24 | atomic_t num_inst; | ||
25 | struct vb2_alloc_ctx *alloc_ctx; | ||
26 | struct resource *res_regs; | ||
27 | void __iomem *regs; | ||
28 | struct clk *clk; | ||
29 | struct clk *gate; | ||
30 | struct g2d_ctx *curr; | ||
31 | int irq; | ||
32 | wait_queue_head_t irq_queue; | ||
33 | }; | ||
34 | |||
35 | struct g2d_frame { | ||
36 | /* Original dimensions */ | ||
37 | u32 width; | ||
38 | u32 height; | ||
39 | /* Crop size */ | ||
40 | u32 c_width; | ||
41 | u32 c_height; | ||
42 | /* Offset */ | ||
43 | u32 o_width; | ||
44 | u32 o_height; | ||
45 | /* Image format */ | ||
46 | struct g2d_fmt *fmt; | ||
47 | /* Variables that can calculated once and reused */ | ||
48 | u32 stride; | ||
49 | u32 bottom; | ||
50 | u32 right; | ||
51 | u32 size; | ||
52 | }; | ||
53 | |||
54 | struct g2d_ctx { | ||
55 | struct v4l2_fh fh; | ||
56 | struct g2d_dev *dev; | ||
57 | struct v4l2_m2m_ctx *m2m_ctx; | ||
58 | struct g2d_frame in; | ||
59 | struct g2d_frame out; | ||
60 | struct v4l2_ctrl_handler ctrl_handler; | ||
61 | u32 rop; | ||
62 | }; | ||
63 | |||
64 | struct g2d_fmt { | ||
65 | char *name; | ||
66 | u32 fourcc; | ||
67 | int depth; | ||
68 | u32 hw; | ||
69 | }; | ||
70 | |||
71 | |||
72 | void g2d_reset(struct g2d_dev *d); | ||
73 | void g2d_set_src_size(struct g2d_dev *d, struct g2d_frame *f); | ||
74 | void g2d_set_src_addr(struct g2d_dev *d, dma_addr_t a); | ||
75 | void g2d_set_dst_size(struct g2d_dev *d, struct g2d_frame *f); | ||
76 | void g2d_set_dst_addr(struct g2d_dev *d, dma_addr_t a); | ||
77 | void g2d_start(struct g2d_dev *d); | ||
78 | void g2d_clear_int(struct g2d_dev *d); | ||
79 | void g2d_set_rop4(struct g2d_dev *d, u32 r); | ||
80 | u32 g2d_cmd_stretch(u32 e); | ||
81 | void g2d_set_cmd(struct g2d_dev *d, u32 c); | ||
82 | |||
83 | |||
diff --git a/drivers/media/video/s5p-jpeg/Makefile b/drivers/media/video/s5p-jpeg/Makefile new file mode 100644 index 000000000000..ddc2900d88a2 --- /dev/null +++ b/drivers/media/video/s5p-jpeg/Makefile | |||
@@ -0,0 +1,2 @@ | |||
1 | s5p-jpeg-objs := jpeg-core.o | ||
2 | obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG) := s5p-jpeg.o | ||
diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.c b/drivers/media/video/s5p-jpeg/jpeg-core.c new file mode 100644 index 000000000000..f841a3e9845c --- /dev/null +++ b/drivers/media/video/s5p-jpeg/jpeg-core.c | |||
@@ -0,0 +1,1481 @@ | |||
1 | /* linux/drivers/media/video/s5p-jpeg/jpeg-core.c | ||
2 | * | ||
3 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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 version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/gfp.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/pm_runtime.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | #include <linux/string.h> | ||
25 | #include <media/v4l2-mem2mem.h> | ||
26 | #include <media/v4l2-ioctl.h> | ||
27 | #include <media/videobuf2-core.h> | ||
28 | #include <media/videobuf2-dma-contig.h> | ||
29 | |||
30 | #include "jpeg-core.h" | ||
31 | #include "jpeg-hw.h" | ||
32 | |||
33 | static struct s5p_jpeg_fmt formats_enc[] = { | ||
34 | { | ||
35 | .name = "YUV 4:2:0 planar, YCbCr", | ||
36 | .fourcc = V4L2_PIX_FMT_YUV420, | ||
37 | .depth = 12, | ||
38 | .colplanes = 3, | ||
39 | .types = MEM2MEM_CAPTURE, | ||
40 | }, | ||
41 | { | ||
42 | .name = "YUV 4:2:2 packed, YCbYCr", | ||
43 | .fourcc = V4L2_PIX_FMT_YUYV, | ||
44 | .depth = 16, | ||
45 | .colplanes = 1, | ||
46 | .types = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT, | ||
47 | }, | ||
48 | { | ||
49 | .name = "RGB565", | ||
50 | .fourcc = V4L2_PIX_FMT_RGB565, | ||
51 | .depth = 16, | ||
52 | .colplanes = 1, | ||
53 | .types = MEM2MEM_OUTPUT, | ||
54 | }, | ||
55 | }; | ||
56 | #define NUM_FORMATS_ENC ARRAY_SIZE(formats_enc) | ||
57 | |||
58 | static struct s5p_jpeg_fmt formats_dec[] = { | ||
59 | { | ||
60 | .name = "YUV 4:2:0 planar, YCbCr", | ||
61 | .fourcc = V4L2_PIX_FMT_YUV420, | ||
62 | .depth = 12, | ||
63 | .colplanes = 3, | ||
64 | .h_align = 4, | ||
65 | .v_align = 4, | ||
66 | .types = MEM2MEM_CAPTURE, | ||
67 | }, | ||
68 | { | ||
69 | .name = "YUV 4:2:2 packed, YCbYCr", | ||
70 | .fourcc = V4L2_PIX_FMT_YUYV, | ||
71 | .depth = 16, | ||
72 | .colplanes = 1, | ||
73 | .h_align = 4, | ||
74 | .v_align = 3, | ||
75 | .types = MEM2MEM_CAPTURE, | ||
76 | }, | ||
77 | { | ||
78 | .name = "JPEG JFIF", | ||
79 | .fourcc = V4L2_PIX_FMT_JPEG, | ||
80 | .colplanes = 1, | ||
81 | .types = MEM2MEM_OUTPUT, | ||
82 | }, | ||
83 | }; | ||
84 | #define NUM_FORMATS_DEC ARRAY_SIZE(formats_dec) | ||
85 | |||
86 | static const unsigned char qtbl_luminance[4][64] = { | ||
87 | {/* level 1 - high quality */ | ||
88 | 8, 6, 6, 8, 12, 14, 16, 17, | ||
89 | 6, 6, 6, 8, 10, 13, 12, 15, | ||
90 | 6, 6, 7, 8, 13, 14, 18, 24, | ||
91 | 8, 8, 8, 14, 13, 19, 24, 35, | ||
92 | 12, 10, 13, 13, 20, 26, 34, 39, | ||
93 | 14, 13, 14, 19, 26, 34, 39, 39, | ||
94 | 16, 12, 18, 24, 34, 39, 39, 39, | ||
95 | 17, 15, 24, 35, 39, 39, 39, 39 | ||
96 | }, | ||
97 | {/* level 2 */ | ||
98 | 12, 8, 8, 12, 17, 21, 24, 23, | ||
99 | 8, 9, 9, 11, 15, 19, 18, 23, | ||
100 | 8, 9, 10, 12, 19, 20, 27, 36, | ||
101 | 12, 11, 12, 21, 20, 28, 36, 53, | ||
102 | 17, 15, 19, 20, 30, 39, 51, 59, | ||
103 | 21, 19, 20, 28, 39, 51, 59, 59, | ||
104 | 24, 18, 27, 36, 51, 59, 59, 59, | ||
105 | 23, 23, 36, 53, 59, 59, 59, 59 | ||
106 | }, | ||
107 | {/* level 3 */ | ||
108 | 16, 11, 11, 16, 23, 27, 31, 30, | ||
109 | 11, 12, 12, 15, 20, 23, 23, 30, | ||
110 | 11, 12, 13, 16, 23, 26, 35, 47, | ||
111 | 16, 15, 16, 23, 26, 37, 47, 64, | ||
112 | 23, 20, 23, 26, 39, 51, 64, 64, | ||
113 | 27, 23, 26, 37, 51, 64, 64, 64, | ||
114 | 31, 23, 35, 47, 64, 64, 64, 64, | ||
115 | 30, 30, 47, 64, 64, 64, 64, 64 | ||
116 | }, | ||
117 | {/*level 4 - low quality */ | ||
118 | 20, 16, 25, 39, 50, 46, 62, 68, | ||
119 | 16, 18, 23, 38, 38, 53, 65, 68, | ||
120 | 25, 23, 31, 38, 53, 65, 68, 68, | ||
121 | 39, 38, 38, 53, 65, 68, 68, 68, | ||
122 | 50, 38, 53, 65, 68, 68, 68, 68, | ||
123 | 46, 53, 65, 68, 68, 68, 68, 68, | ||
124 | 62, 65, 68, 68, 68, 68, 68, 68, | ||
125 | 68, 68, 68, 68, 68, 68, 68, 68 | ||
126 | } | ||
127 | }; | ||
128 | |||
129 | static const unsigned char qtbl_chrominance[4][64] = { | ||
130 | {/* level 1 - high quality */ | ||
131 | 9, 8, 9, 11, 14, 17, 19, 24, | ||
132 | 8, 10, 9, 11, 14, 13, 17, 22, | ||
133 | 9, 9, 13, 14, 13, 15, 23, 26, | ||
134 | 11, 11, 14, 14, 15, 20, 26, 33, | ||
135 | 14, 14, 13, 15, 20, 24, 33, 39, | ||
136 | 17, 13, 15, 20, 24, 32, 39, 39, | ||
137 | 19, 17, 23, 26, 33, 39, 39, 39, | ||
138 | 24, 22, 26, 33, 39, 39, 39, 39 | ||
139 | }, | ||
140 | {/* level 2 */ | ||
141 | 13, 11, 13, 16, 20, 20, 29, 37, | ||
142 | 11, 14, 14, 14, 16, 20, 26, 32, | ||
143 | 13, 14, 15, 17, 20, 23, 35, 40, | ||
144 | 16, 14, 17, 21, 23, 30, 40, 50, | ||
145 | 20, 16, 20, 23, 30, 37, 50, 59, | ||
146 | 20, 20, 23, 30, 37, 48, 59, 59, | ||
147 | 29, 26, 35, 40, 50, 59, 59, 59, | ||
148 | 37, 32, 40, 50, 59, 59, 59, 59 | ||
149 | }, | ||
150 | {/* level 3 */ | ||
151 | 17, 15, 17, 21, 20, 26, 38, 48, | ||
152 | 15, 19, 18, 17, 20, 26, 35, 43, | ||
153 | 17, 18, 20, 22, 26, 30, 46, 53, | ||
154 | 21, 17, 22, 28, 30, 39, 53, 64, | ||
155 | 20, 20, 26, 30, 39, 48, 64, 64, | ||
156 | 26, 26, 30, 39, 48, 63, 64, 64, | ||
157 | 38, 35, 46, 53, 64, 64, 64, 64, | ||
158 | 48, 43, 53, 64, 64, 64, 64, 64 | ||
159 | }, | ||
160 | {/*level 4 - low quality */ | ||
161 | 21, 25, 32, 38, 54, 68, 68, 68, | ||
162 | 25, 28, 24, 38, 54, 68, 68, 68, | ||
163 | 32, 24, 32, 43, 66, 68, 68, 68, | ||
164 | 38, 38, 43, 53, 68, 68, 68, 68, | ||
165 | 54, 54, 66, 68, 68, 68, 68, 68, | ||
166 | 68, 68, 68, 68, 68, 68, 68, 68, | ||
167 | 68, 68, 68, 68, 68, 68, 68, 68, | ||
168 | 68, 68, 68, 68, 68, 68, 68, 68 | ||
169 | } | ||
170 | }; | ||
171 | |||
172 | static const unsigned char hdctbl0[16] = { | ||
173 | 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 | ||
174 | }; | ||
175 | |||
176 | static const unsigned char hdctblg0[12] = { | ||
177 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb | ||
178 | }; | ||
179 | static const unsigned char hactbl0[16] = { | ||
180 | 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d | ||
181 | }; | ||
182 | static const unsigned char hactblg0[162] = { | ||
183 | 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, | ||
184 | 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, | ||
185 | 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, | ||
186 | 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, | ||
187 | 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, | ||
188 | 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, | ||
189 | 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, | ||
190 | 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, | ||
191 | 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, | ||
192 | 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, | ||
193 | 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, | ||
194 | 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, | ||
195 | 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, | ||
196 | 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, | ||
197 | 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, | ||
198 | 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, | ||
199 | 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, | ||
200 | 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, | ||
201 | 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, | ||
202 | 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, | ||
203 | 0xf9, 0xfa | ||
204 | }; | ||
205 | |||
206 | static inline void jpeg_set_qtbl(void __iomem *regs, const unsigned char *qtbl, | ||
207 | unsigned long tab, int len) | ||
208 | { | ||
209 | int i; | ||
210 | |||
211 | for (i = 0; i < len; i++) | ||
212 | writel((unsigned int)qtbl[i], regs + tab + (i * 0x04)); | ||
213 | } | ||
214 | |||
215 | static inline void jpeg_set_qtbl_lum(void __iomem *regs, int quality) | ||
216 | { | ||
217 | /* this driver fills quantisation table 0 with data for luma */ | ||
218 | jpeg_set_qtbl(regs, qtbl_luminance[quality], S5P_JPG_QTBL_CONTENT(0), | ||
219 | ARRAY_SIZE(qtbl_luminance[quality])); | ||
220 | } | ||
221 | |||
222 | static inline void jpeg_set_qtbl_chr(void __iomem *regs, int quality) | ||
223 | { | ||
224 | /* this driver fills quantisation table 1 with data for chroma */ | ||
225 | jpeg_set_qtbl(regs, qtbl_chrominance[quality], S5P_JPG_QTBL_CONTENT(1), | ||
226 | ARRAY_SIZE(qtbl_chrominance[quality])); | ||
227 | } | ||
228 | |||
229 | static inline void jpeg_set_htbl(void __iomem *regs, const unsigned char *htbl, | ||
230 | unsigned long tab, int len) | ||
231 | { | ||
232 | int i; | ||
233 | |||
234 | for (i = 0; i < len; i++) | ||
235 | writel((unsigned int)htbl[i], regs + tab + (i * 0x04)); | ||
236 | } | ||
237 | |||
238 | static inline void jpeg_set_hdctbl(void __iomem *regs) | ||
239 | { | ||
240 | /* this driver fills table 0 for this component */ | ||
241 | jpeg_set_htbl(regs, hdctbl0, S5P_JPG_HDCTBL(0), ARRAY_SIZE(hdctbl0)); | ||
242 | } | ||
243 | |||
244 | static inline void jpeg_set_hdctblg(void __iomem *regs) | ||
245 | { | ||
246 | /* this driver fills table 0 for this component */ | ||
247 | jpeg_set_htbl(regs, hdctblg0, S5P_JPG_HDCTBLG(0), ARRAY_SIZE(hdctblg0)); | ||
248 | } | ||
249 | |||
250 | static inline void jpeg_set_hactbl(void __iomem *regs) | ||
251 | { | ||
252 | /* this driver fills table 0 for this component */ | ||
253 | jpeg_set_htbl(regs, hactbl0, S5P_JPG_HACTBL(0), ARRAY_SIZE(hactbl0)); | ||
254 | } | ||
255 | |||
256 | static inline void jpeg_set_hactblg(void __iomem *regs) | ||
257 | { | ||
258 | /* this driver fills table 0 for this component */ | ||
259 | jpeg_set_htbl(regs, hactblg0, S5P_JPG_HACTBLG(0), ARRAY_SIZE(hactblg0)); | ||
260 | } | ||
261 | |||
262 | /* | ||
263 | * ============================================================================ | ||
264 | * Device file operations | ||
265 | * ============================================================================ | ||
266 | */ | ||
267 | |||
268 | static int queue_init(void *priv, struct vb2_queue *src_vq, | ||
269 | struct vb2_queue *dst_vq); | ||
270 | static struct s5p_jpeg_fmt *s5p_jpeg_find_format(unsigned int mode, | ||
271 | __u32 pixelformat); | ||
272 | |||
273 | static int s5p_jpeg_open(struct file *file) | ||
274 | { | ||
275 | struct s5p_jpeg *jpeg = video_drvdata(file); | ||
276 | struct video_device *vfd = video_devdata(file); | ||
277 | struct s5p_jpeg_ctx *ctx; | ||
278 | struct s5p_jpeg_fmt *out_fmt; | ||
279 | |||
280 | ctx = kzalloc(sizeof *ctx, GFP_KERNEL); | ||
281 | if (!ctx) | ||
282 | return -ENOMEM; | ||
283 | |||
284 | file->private_data = ctx; | ||
285 | ctx->jpeg = jpeg; | ||
286 | if (vfd == jpeg->vfd_encoder) { | ||
287 | ctx->mode = S5P_JPEG_ENCODE; | ||
288 | out_fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_RGB565); | ||
289 | } else { | ||
290 | ctx->mode = S5P_JPEG_DECODE; | ||
291 | out_fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_JPEG); | ||
292 | } | ||
293 | |||
294 | ctx->m2m_ctx = v4l2_m2m_ctx_init(jpeg->m2m_dev, ctx, queue_init); | ||
295 | if (IS_ERR(ctx->m2m_ctx)) { | ||
296 | int err = PTR_ERR(ctx->m2m_ctx); | ||
297 | kfree(ctx); | ||
298 | return err; | ||
299 | } | ||
300 | |||
301 | ctx->out_q.fmt = out_fmt; | ||
302 | ctx->cap_q.fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_YUYV); | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static int s5p_jpeg_release(struct file *file) | ||
308 | { | ||
309 | struct s5p_jpeg_ctx *ctx = file->private_data; | ||
310 | |||
311 | v4l2_m2m_ctx_release(ctx->m2m_ctx); | ||
312 | kfree(ctx); | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static unsigned int s5p_jpeg_poll(struct file *file, | ||
318 | struct poll_table_struct *wait) | ||
319 | { | ||
320 | struct s5p_jpeg_ctx *ctx = file->private_data; | ||
321 | |||
322 | return v4l2_m2m_poll(file, ctx->m2m_ctx, wait); | ||
323 | } | ||
324 | |||
325 | static int s5p_jpeg_mmap(struct file *file, struct vm_area_struct *vma) | ||
326 | { | ||
327 | struct s5p_jpeg_ctx *ctx = file->private_data; | ||
328 | |||
329 | return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma); | ||
330 | } | ||
331 | |||
332 | static const struct v4l2_file_operations s5p_jpeg_fops = { | ||
333 | .owner = THIS_MODULE, | ||
334 | .open = s5p_jpeg_open, | ||
335 | .release = s5p_jpeg_release, | ||
336 | .poll = s5p_jpeg_poll, | ||
337 | .unlocked_ioctl = video_ioctl2, | ||
338 | .mmap = s5p_jpeg_mmap, | ||
339 | }; | ||
340 | |||
341 | /* | ||
342 | * ============================================================================ | ||
343 | * video ioctl operations | ||
344 | * ============================================================================ | ||
345 | */ | ||
346 | |||
347 | static int get_byte(struct s5p_jpeg_buffer *buf) | ||
348 | { | ||
349 | if (buf->curr >= buf->size) | ||
350 | return -1; | ||
351 | |||
352 | return ((unsigned char *)buf->data)[buf->curr++]; | ||
353 | } | ||
354 | |||
355 | static int get_word_be(struct s5p_jpeg_buffer *buf, unsigned int *word) | ||
356 | { | ||
357 | unsigned int temp; | ||
358 | int byte; | ||
359 | |||
360 | byte = get_byte(buf); | ||
361 | if (byte == -1) | ||
362 | return -1; | ||
363 | temp = byte << 8; | ||
364 | byte = get_byte(buf); | ||
365 | if (byte == -1) | ||
366 | return -1; | ||
367 | *word = (unsigned int)byte | temp; | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static void skip(struct s5p_jpeg_buffer *buf, long len) | ||
372 | { | ||
373 | if (len <= 0) | ||
374 | return; | ||
375 | |||
376 | while (len--) | ||
377 | get_byte(buf); | ||
378 | } | ||
379 | |||
380 | static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result, | ||
381 | unsigned long buffer, unsigned long size) | ||
382 | { | ||
383 | int c, components, notfound; | ||
384 | unsigned int height, width, word; | ||
385 | long length; | ||
386 | struct s5p_jpeg_buffer jpeg_buffer; | ||
387 | |||
388 | jpeg_buffer.size = size; | ||
389 | jpeg_buffer.data = buffer; | ||
390 | jpeg_buffer.curr = 0; | ||
391 | |||
392 | notfound = 1; | ||
393 | while (notfound) { | ||
394 | c = get_byte(&jpeg_buffer); | ||
395 | if (c == -1) | ||
396 | break; | ||
397 | if (c != 0xff) | ||
398 | continue; | ||
399 | do | ||
400 | c = get_byte(&jpeg_buffer); | ||
401 | while (c == 0xff); | ||
402 | if (c == -1) | ||
403 | break; | ||
404 | if (c == 0) | ||
405 | continue; | ||
406 | length = 0; | ||
407 | switch (c) { | ||
408 | /* SOF0: baseline JPEG */ | ||
409 | case SOF0: | ||
410 | if (get_word_be(&jpeg_buffer, &word)) | ||
411 | break; | ||
412 | if (get_byte(&jpeg_buffer) == -1) | ||
413 | break; | ||
414 | if (get_word_be(&jpeg_buffer, &height)) | ||
415 | break; | ||
416 | if (get_word_be(&jpeg_buffer, &width)) | ||
417 | break; | ||
418 | components = get_byte(&jpeg_buffer); | ||
419 | if (components == -1) | ||
420 | break; | ||
421 | notfound = 0; | ||
422 | |||
423 | skip(&jpeg_buffer, components * 3); | ||
424 | break; | ||
425 | |||
426 | /* skip payload-less markers */ | ||
427 | case RST ... RST + 7: | ||
428 | case SOI: | ||
429 | case EOI: | ||
430 | case TEM: | ||
431 | break; | ||
432 | |||
433 | /* skip uninteresting payload markers */ | ||
434 | default: | ||
435 | if (get_word_be(&jpeg_buffer, &word)) | ||
436 | break; | ||
437 | length = (long)word - 2; | ||
438 | skip(&jpeg_buffer, length); | ||
439 | break; | ||
440 | } | ||
441 | } | ||
442 | result->w = width; | ||
443 | result->h = height; | ||
444 | result->size = components; | ||
445 | return !notfound; | ||
446 | } | ||
447 | |||
448 | static int s5p_jpeg_querycap(struct file *file, void *priv, | ||
449 | struct v4l2_capability *cap) | ||
450 | { | ||
451 | struct s5p_jpeg_ctx *ctx = priv; | ||
452 | |||
453 | if (ctx->mode == S5P_JPEG_ENCODE) { | ||
454 | strlcpy(cap->driver, S5P_JPEG_M2M_NAME " encoder", | ||
455 | sizeof(cap->driver)); | ||
456 | strlcpy(cap->card, S5P_JPEG_M2M_NAME " encoder", | ||
457 | sizeof(cap->card)); | ||
458 | } else { | ||
459 | strlcpy(cap->driver, S5P_JPEG_M2M_NAME " decoder", | ||
460 | sizeof(cap->driver)); | ||
461 | strlcpy(cap->card, S5P_JPEG_M2M_NAME " decoder", | ||
462 | sizeof(cap->card)); | ||
463 | } | ||
464 | cap->bus_info[0] = 0; | ||
465 | cap->capabilities = V4L2_CAP_STREAMING | | ||
466 | V4L2_CAP_VIDEO_CAPTURE | | ||
467 | V4L2_CAP_VIDEO_OUTPUT; | ||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int enum_fmt(struct s5p_jpeg_fmt *formats, int n, | ||
472 | struct v4l2_fmtdesc *f, u32 type) | ||
473 | { | ||
474 | int i, num = 0; | ||
475 | |||
476 | for (i = 0; i < n; ++i) { | ||
477 | if (formats[i].types & type) { | ||
478 | /* index-th format of type type found ? */ | ||
479 | if (num == f->index) | ||
480 | break; | ||
481 | /* Correct type but haven't reached our index yet, | ||
482 | * just increment per-type index */ | ||
483 | ++num; | ||
484 | } | ||
485 | } | ||
486 | |||
487 | /* Format not found */ | ||
488 | if (i >= n) | ||
489 | return -EINVAL; | ||
490 | |||
491 | strlcpy(f->description, formats[i].name, sizeof(f->description)); | ||
492 | f->pixelformat = formats[i].fourcc; | ||
493 | |||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | static int s5p_jpeg_enum_fmt_vid_cap(struct file *file, void *priv, | ||
498 | struct v4l2_fmtdesc *f) | ||
499 | { | ||
500 | struct s5p_jpeg_ctx *ctx; | ||
501 | |||
502 | ctx = priv; | ||
503 | |||
504 | if (ctx->mode == S5P_JPEG_ENCODE) | ||
505 | return enum_fmt(formats_enc, NUM_FORMATS_ENC, f, | ||
506 | MEM2MEM_CAPTURE); | ||
507 | |||
508 | return enum_fmt(formats_dec, NUM_FORMATS_DEC, f, MEM2MEM_CAPTURE); | ||
509 | } | ||
510 | |||
511 | static int s5p_jpeg_enum_fmt_vid_out(struct file *file, void *priv, | ||
512 | struct v4l2_fmtdesc *f) | ||
513 | { | ||
514 | struct s5p_jpeg_ctx *ctx; | ||
515 | |||
516 | ctx = priv; | ||
517 | |||
518 | if (ctx->mode == S5P_JPEG_ENCODE) | ||
519 | return enum_fmt(formats_enc, NUM_FORMATS_ENC, f, | ||
520 | MEM2MEM_OUTPUT); | ||
521 | |||
522 | return enum_fmt(formats_dec, NUM_FORMATS_DEC, f, MEM2MEM_OUTPUT); | ||
523 | } | ||
524 | |||
525 | static struct s5p_jpeg_q_data *get_q_data(struct s5p_jpeg_ctx *ctx, | ||
526 | enum v4l2_buf_type type) | ||
527 | { | ||
528 | if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT) | ||
529 | return &ctx->out_q; | ||
530 | if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
531 | return &ctx->cap_q; | ||
532 | |||
533 | return NULL; | ||
534 | } | ||
535 | |||
536 | static int s5p_jpeg_g_fmt(struct file *file, void *priv, struct v4l2_format *f) | ||
537 | { | ||
538 | struct vb2_queue *vq; | ||
539 | struct s5p_jpeg_q_data *q_data = NULL; | ||
540 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
541 | struct s5p_jpeg_ctx *ct = priv; | ||
542 | |||
543 | vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type); | ||
544 | if (!vq) | ||
545 | return -EINVAL; | ||
546 | |||
547 | if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && | ||
548 | ct->mode == S5P_JPEG_DECODE && !ct->hdr_parsed) | ||
549 | return -EINVAL; | ||
550 | q_data = get_q_data(ct, f->type); | ||
551 | BUG_ON(q_data == NULL); | ||
552 | |||
553 | pix->width = q_data->w; | ||
554 | pix->height = q_data->h; | ||
555 | pix->field = V4L2_FIELD_NONE; | ||
556 | pix->pixelformat = q_data->fmt->fourcc; | ||
557 | pix->bytesperline = 0; | ||
558 | if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) { | ||
559 | u32 bpl = q_data->w; | ||
560 | if (q_data->fmt->colplanes == 1) | ||
561 | bpl = (bpl * q_data->fmt->depth) >> 3; | ||
562 | pix->bytesperline = bpl; | ||
563 | } | ||
564 | pix->sizeimage = q_data->size; | ||
565 | |||
566 | return 0; | ||
567 | } | ||
568 | |||
569 | static struct s5p_jpeg_fmt *s5p_jpeg_find_format(unsigned int mode, | ||
570 | u32 pixelformat) | ||
571 | { | ||
572 | unsigned int k; | ||
573 | struct s5p_jpeg_fmt *formats; | ||
574 | int n; | ||
575 | |||
576 | if (mode == S5P_JPEG_ENCODE) { | ||
577 | formats = formats_enc; | ||
578 | n = NUM_FORMATS_ENC; | ||
579 | } else { | ||
580 | formats = formats_dec; | ||
581 | n = NUM_FORMATS_DEC; | ||
582 | } | ||
583 | |||
584 | for (k = 0; k < n; k++) { | ||
585 | struct s5p_jpeg_fmt *fmt = &formats[k]; | ||
586 | if (fmt->fourcc == pixelformat) | ||
587 | return fmt; | ||
588 | } | ||
589 | |||
590 | return NULL; | ||
591 | |||
592 | } | ||
593 | |||
594 | static void jpeg_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, | ||
595 | unsigned int walign, | ||
596 | u32 *h, unsigned int hmin, unsigned int hmax, | ||
597 | unsigned int halign) | ||
598 | { | ||
599 | int width, height, w_step, h_step; | ||
600 | |||
601 | width = *w; | ||
602 | height = *h; | ||
603 | |||
604 | w_step = 1 << walign; | ||
605 | h_step = 1 << halign; | ||
606 | v4l_bound_align_image(w, wmin, wmax, walign, h, hmin, hmax, halign, 0); | ||
607 | |||
608 | if (*w < width && (*w + w_step) < wmax) | ||
609 | *w += w_step; | ||
610 | if (*h < height && (*h + h_step) < hmax) | ||
611 | *h += h_step; | ||
612 | |||
613 | } | ||
614 | |||
615 | static int vidioc_try_fmt(struct v4l2_format *f, struct s5p_jpeg_fmt *fmt, | ||
616 | struct s5p_jpeg_ctx *ctx, int q_type) | ||
617 | { | ||
618 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
619 | |||
620 | if (pix->field == V4L2_FIELD_ANY) | ||
621 | pix->field = V4L2_FIELD_NONE; | ||
622 | else if (pix->field != V4L2_FIELD_NONE) | ||
623 | return -EINVAL; | ||
624 | |||
625 | /* V4L2 specification suggests the driver corrects the format struct | ||
626 | * if any of the dimensions is unsupported */ | ||
627 | if (q_type == MEM2MEM_OUTPUT) | ||
628 | jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH, | ||
629 | S5P_JPEG_MAX_WIDTH, 0, | ||
630 | &pix->height, S5P_JPEG_MIN_HEIGHT, | ||
631 | S5P_JPEG_MAX_HEIGHT, 0); | ||
632 | else | ||
633 | jpeg_bound_align_image(&pix->width, S5P_JPEG_MIN_WIDTH, | ||
634 | S5P_JPEG_MAX_WIDTH, fmt->h_align, | ||
635 | &pix->height, S5P_JPEG_MIN_HEIGHT, | ||
636 | S5P_JPEG_MAX_HEIGHT, fmt->v_align); | ||
637 | |||
638 | if (fmt->fourcc == V4L2_PIX_FMT_JPEG) { | ||
639 | if (pix->sizeimage <= 0) | ||
640 | pix->sizeimage = PAGE_SIZE; | ||
641 | pix->bytesperline = 0; | ||
642 | } else { | ||
643 | u32 bpl = pix->bytesperline; | ||
644 | |||
645 | if (fmt->colplanes > 1 && bpl < pix->width) | ||
646 | bpl = pix->width; /* planar */ | ||
647 | |||
648 | if (fmt->colplanes == 1 && /* packed */ | ||
649 | (bpl << 3) * fmt->depth < pix->width) | ||
650 | bpl = (pix->width * fmt->depth) >> 3; | ||
651 | |||
652 | pix->bytesperline = bpl; | ||
653 | pix->sizeimage = (pix->width * pix->height * fmt->depth) >> 3; | ||
654 | } | ||
655 | |||
656 | return 0; | ||
657 | } | ||
658 | |||
659 | static int s5p_jpeg_try_fmt_vid_cap(struct file *file, void *priv, | ||
660 | struct v4l2_format *f) | ||
661 | { | ||
662 | struct s5p_jpeg_fmt *fmt; | ||
663 | struct s5p_jpeg_ctx *ctx = priv; | ||
664 | |||
665 | fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat); | ||
666 | if (!fmt || !(fmt->types & MEM2MEM_CAPTURE)) { | ||
667 | v4l2_err(&ctx->jpeg->v4l2_dev, | ||
668 | "Fourcc format (0x%08x) invalid.\n", | ||
669 | f->fmt.pix.pixelformat); | ||
670 | return -EINVAL; | ||
671 | } | ||
672 | |||
673 | return vidioc_try_fmt(f, fmt, ctx, MEM2MEM_CAPTURE); | ||
674 | } | ||
675 | |||
676 | static int s5p_jpeg_try_fmt_vid_out(struct file *file, void *priv, | ||
677 | struct v4l2_format *f) | ||
678 | { | ||
679 | struct s5p_jpeg_fmt *fmt; | ||
680 | struct s5p_jpeg_ctx *ctx = priv; | ||
681 | |||
682 | fmt = s5p_jpeg_find_format(ctx->mode, f->fmt.pix.pixelformat); | ||
683 | if (!fmt || !(fmt->types & MEM2MEM_OUTPUT)) { | ||
684 | v4l2_err(&ctx->jpeg->v4l2_dev, | ||
685 | "Fourcc format (0x%08x) invalid.\n", | ||
686 | f->fmt.pix.pixelformat); | ||
687 | return -EINVAL; | ||
688 | } | ||
689 | |||
690 | return vidioc_try_fmt(f, fmt, ctx, MEM2MEM_OUTPUT); | ||
691 | } | ||
692 | |||
693 | static int s5p_jpeg_s_fmt(struct s5p_jpeg_ctx *ct, struct v4l2_format *f) | ||
694 | { | ||
695 | struct vb2_queue *vq; | ||
696 | struct s5p_jpeg_q_data *q_data = NULL; | ||
697 | struct v4l2_pix_format *pix = &f->fmt.pix; | ||
698 | |||
699 | vq = v4l2_m2m_get_vq(ct->m2m_ctx, f->type); | ||
700 | if (!vq) | ||
701 | return -EINVAL; | ||
702 | |||
703 | q_data = get_q_data(ct, f->type); | ||
704 | BUG_ON(q_data == NULL); | ||
705 | |||
706 | if (vb2_is_busy(vq)) { | ||
707 | v4l2_err(&ct->jpeg->v4l2_dev, "%s queue busy\n", __func__); | ||
708 | return -EBUSY; | ||
709 | } | ||
710 | |||
711 | q_data->fmt = s5p_jpeg_find_format(ct->mode, pix->pixelformat); | ||
712 | q_data->w = pix->width; | ||
713 | q_data->h = pix->height; | ||
714 | if (q_data->fmt->fourcc != V4L2_PIX_FMT_JPEG) | ||
715 | q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3; | ||
716 | else | ||
717 | q_data->size = pix->sizeimage; | ||
718 | |||
719 | return 0; | ||
720 | } | ||
721 | |||
722 | static int s5p_jpeg_s_fmt_vid_cap(struct file *file, void *priv, | ||
723 | struct v4l2_format *f) | ||
724 | { | ||
725 | int ret; | ||
726 | |||
727 | ret = s5p_jpeg_try_fmt_vid_cap(file, priv, f); | ||
728 | if (ret) | ||
729 | return ret; | ||
730 | |||
731 | return s5p_jpeg_s_fmt(priv, f); | ||
732 | } | ||
733 | |||
734 | static int s5p_jpeg_s_fmt_vid_out(struct file *file, void *priv, | ||
735 | struct v4l2_format *f) | ||
736 | { | ||
737 | int ret; | ||
738 | |||
739 | ret = s5p_jpeg_try_fmt_vid_out(file, priv, f); | ||
740 | if (ret) | ||
741 | return ret; | ||
742 | |||
743 | return s5p_jpeg_s_fmt(priv, f); | ||
744 | } | ||
745 | |||
746 | static int s5p_jpeg_reqbufs(struct file *file, void *priv, | ||
747 | struct v4l2_requestbuffers *reqbufs) | ||
748 | { | ||
749 | struct s5p_jpeg_ctx *ctx = priv; | ||
750 | |||
751 | return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs); | ||
752 | } | ||
753 | |||
754 | static int s5p_jpeg_querybuf(struct file *file, void *priv, | ||
755 | struct v4l2_buffer *buf) | ||
756 | { | ||
757 | struct s5p_jpeg_ctx *ctx = priv; | ||
758 | |||
759 | return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf); | ||
760 | } | ||
761 | |||
762 | static int s5p_jpeg_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf) | ||
763 | { | ||
764 | struct s5p_jpeg_ctx *ctx = priv; | ||
765 | |||
766 | return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf); | ||
767 | } | ||
768 | |||
769 | static int s5p_jpeg_dqbuf(struct file *file, void *priv, | ||
770 | struct v4l2_buffer *buf) | ||
771 | { | ||
772 | struct s5p_jpeg_ctx *ctx = priv; | ||
773 | |||
774 | return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf); | ||
775 | } | ||
776 | |||
777 | static int s5p_jpeg_streamon(struct file *file, void *priv, | ||
778 | enum v4l2_buf_type type) | ||
779 | { | ||
780 | struct s5p_jpeg_ctx *ctx = priv; | ||
781 | |||
782 | return v4l2_m2m_streamon(file, ctx->m2m_ctx, type); | ||
783 | } | ||
784 | |||
785 | static int s5p_jpeg_streamoff(struct file *file, void *priv, | ||
786 | enum v4l2_buf_type type) | ||
787 | { | ||
788 | struct s5p_jpeg_ctx *ctx = priv; | ||
789 | |||
790 | return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type); | ||
791 | } | ||
792 | |||
793 | int s5p_jpeg_g_selection(struct file *file, void *priv, | ||
794 | struct v4l2_selection *s) | ||
795 | { | ||
796 | struct s5p_jpeg_ctx *ctx = priv; | ||
797 | |||
798 | if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && | ||
799 | s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
800 | return -EINVAL; | ||
801 | |||
802 | /* For JPEG blob active == default == bounds */ | ||
803 | switch (s->target) { | ||
804 | case V4L2_SEL_TGT_CROP_ACTIVE: | ||
805 | case V4L2_SEL_TGT_CROP_BOUNDS: | ||
806 | case V4L2_SEL_TGT_CROP_DEFAULT: | ||
807 | case V4L2_SEL_TGT_COMPOSE_ACTIVE: | ||
808 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: | ||
809 | s->r.width = ctx->out_q.w; | ||
810 | s->r.height = ctx->out_q.h; | ||
811 | break; | ||
812 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: | ||
813 | case V4L2_SEL_TGT_COMPOSE_PADDED: | ||
814 | s->r.width = ctx->cap_q.w; | ||
815 | s->r.height = ctx->cap_q.h; | ||
816 | break; | ||
817 | default: | ||
818 | return -EINVAL; | ||
819 | } | ||
820 | s->r.left = 0; | ||
821 | s->r.top = 0; | ||
822 | return 0; | ||
823 | } | ||
824 | |||
825 | static int s5p_jpeg_g_jpegcomp(struct file *file, void *priv, | ||
826 | struct v4l2_jpegcompression *compr) | ||
827 | { | ||
828 | struct s5p_jpeg_ctx *ctx = priv; | ||
829 | |||
830 | if (ctx->mode == S5P_JPEG_DECODE) | ||
831 | return -ENOTTY; | ||
832 | |||
833 | memset(compr, 0, sizeof(*compr)); | ||
834 | compr->quality = ctx->compr_quality; | ||
835 | |||
836 | return 0; | ||
837 | } | ||
838 | |||
839 | static int s5p_jpeg_s_jpegcomp(struct file *file, void *priv, | ||
840 | struct v4l2_jpegcompression *compr) | ||
841 | { | ||
842 | struct s5p_jpeg_ctx *ctx = priv; | ||
843 | |||
844 | if (ctx->mode == S5P_JPEG_DECODE) | ||
845 | return -ENOTTY; | ||
846 | |||
847 | compr->quality = clamp(compr->quality, S5P_JPEG_COMPR_QUAL_BEST, | ||
848 | S5P_JPEG_COMPR_QUAL_WORST); | ||
849 | |||
850 | ctx->compr_quality = S5P_JPEG_COMPR_QUAL_WORST - compr->quality; | ||
851 | |||
852 | return 0; | ||
853 | } | ||
854 | |||
855 | static const struct v4l2_ioctl_ops s5p_jpeg_ioctl_ops = { | ||
856 | .vidioc_querycap = s5p_jpeg_querycap, | ||
857 | |||
858 | .vidioc_enum_fmt_vid_cap = s5p_jpeg_enum_fmt_vid_cap, | ||
859 | .vidioc_enum_fmt_vid_out = s5p_jpeg_enum_fmt_vid_out, | ||
860 | |||
861 | .vidioc_g_fmt_vid_cap = s5p_jpeg_g_fmt, | ||
862 | .vidioc_g_fmt_vid_out = s5p_jpeg_g_fmt, | ||
863 | |||
864 | .vidioc_try_fmt_vid_cap = s5p_jpeg_try_fmt_vid_cap, | ||
865 | .vidioc_try_fmt_vid_out = s5p_jpeg_try_fmt_vid_out, | ||
866 | |||
867 | .vidioc_s_fmt_vid_cap = s5p_jpeg_s_fmt_vid_cap, | ||
868 | .vidioc_s_fmt_vid_out = s5p_jpeg_s_fmt_vid_out, | ||
869 | |||
870 | .vidioc_reqbufs = s5p_jpeg_reqbufs, | ||
871 | .vidioc_querybuf = s5p_jpeg_querybuf, | ||
872 | |||
873 | .vidioc_qbuf = s5p_jpeg_qbuf, | ||
874 | .vidioc_dqbuf = s5p_jpeg_dqbuf, | ||
875 | |||
876 | .vidioc_streamon = s5p_jpeg_streamon, | ||
877 | .vidioc_streamoff = s5p_jpeg_streamoff, | ||
878 | |||
879 | .vidioc_g_selection = s5p_jpeg_g_selection, | ||
880 | |||
881 | .vidioc_g_jpegcomp = s5p_jpeg_g_jpegcomp, | ||
882 | .vidioc_s_jpegcomp = s5p_jpeg_s_jpegcomp, | ||
883 | }; | ||
884 | |||
885 | /* | ||
886 | * ============================================================================ | ||
887 | * mem2mem callbacks | ||
888 | * ============================================================================ | ||
889 | */ | ||
890 | |||
891 | static void s5p_jpeg_device_run(void *priv) | ||
892 | { | ||
893 | struct s5p_jpeg_ctx *ctx = priv; | ||
894 | struct s5p_jpeg *jpeg = ctx->jpeg; | ||
895 | struct vb2_buffer *src_buf, *dst_buf; | ||
896 | unsigned long src_addr, dst_addr; | ||
897 | |||
898 | src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx); | ||
899 | dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx); | ||
900 | src_addr = vb2_dma_contig_plane_dma_addr(src_buf, 0); | ||
901 | dst_addr = vb2_dma_contig_plane_dma_addr(dst_buf, 0); | ||
902 | |||
903 | jpeg_reset(jpeg->regs); | ||
904 | jpeg_poweron(jpeg->regs); | ||
905 | jpeg_proc_mode(jpeg->regs, ctx->mode); | ||
906 | if (ctx->mode == S5P_JPEG_ENCODE) { | ||
907 | if (ctx->out_q.fmt->fourcc == V4L2_PIX_FMT_RGB565) | ||
908 | jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_565); | ||
909 | else | ||
910 | jpeg_input_raw_mode(jpeg->regs, S5P_JPEG_RAW_IN_422); | ||
911 | if (ctx->cap_q.fmt->fourcc == V4L2_PIX_FMT_YUYV) | ||
912 | jpeg_subsampling_mode(jpeg->regs, | ||
913 | S5P_JPEG_SUBSAMPLING_422); | ||
914 | else | ||
915 | jpeg_subsampling_mode(jpeg->regs, | ||
916 | S5P_JPEG_SUBSAMPLING_420); | ||
917 | jpeg_dri(jpeg->regs, 0); | ||
918 | jpeg_x(jpeg->regs, ctx->out_q.w); | ||
919 | jpeg_y(jpeg->regs, ctx->out_q.h); | ||
920 | jpeg_imgadr(jpeg->regs, src_addr); | ||
921 | jpeg_jpgadr(jpeg->regs, dst_addr); | ||
922 | |||
923 | /* ultimately comes from sizeimage from userspace */ | ||
924 | jpeg_enc_stream_int(jpeg->regs, ctx->cap_q.size); | ||
925 | |||
926 | /* JPEG RGB to YCbCr conversion matrix */ | ||
927 | jpeg_coef(jpeg->regs, 1, 1, S5P_JPEG_COEF11); | ||
928 | jpeg_coef(jpeg->regs, 1, 2, S5P_JPEG_COEF12); | ||
929 | jpeg_coef(jpeg->regs, 1, 3, S5P_JPEG_COEF13); | ||
930 | jpeg_coef(jpeg->regs, 2, 1, S5P_JPEG_COEF21); | ||
931 | jpeg_coef(jpeg->regs, 2, 2, S5P_JPEG_COEF22); | ||
932 | jpeg_coef(jpeg->regs, 2, 3, S5P_JPEG_COEF23); | ||
933 | jpeg_coef(jpeg->regs, 3, 1, S5P_JPEG_COEF31); | ||
934 | jpeg_coef(jpeg->regs, 3, 2, S5P_JPEG_COEF32); | ||
935 | jpeg_coef(jpeg->regs, 3, 3, S5P_JPEG_COEF33); | ||
936 | |||
937 | /* | ||
938 | * JPEG IP allows storing 4 quantization tables | ||
939 | * We fill table 0 for luma and table 1 for chroma | ||
940 | */ | ||
941 | jpeg_set_qtbl_lum(jpeg->regs, ctx->compr_quality); | ||
942 | jpeg_set_qtbl_chr(jpeg->regs, ctx->compr_quality); | ||
943 | /* use table 0 for Y */ | ||
944 | jpeg_qtbl(jpeg->regs, 1, 0); | ||
945 | /* use table 1 for Cb and Cr*/ | ||
946 | jpeg_qtbl(jpeg->regs, 2, 1); | ||
947 | jpeg_qtbl(jpeg->regs, 3, 1); | ||
948 | |||
949 | /* Y, Cb, Cr use Huffman table 0 */ | ||
950 | jpeg_htbl_ac(jpeg->regs, 1); | ||
951 | jpeg_htbl_dc(jpeg->regs, 1); | ||
952 | jpeg_htbl_ac(jpeg->regs, 2); | ||
953 | jpeg_htbl_dc(jpeg->regs, 2); | ||
954 | jpeg_htbl_ac(jpeg->regs, 3); | ||
955 | jpeg_htbl_dc(jpeg->regs, 3); | ||
956 | } else { | ||
957 | jpeg_rst_int_enable(jpeg->regs, true); | ||
958 | jpeg_data_num_int_enable(jpeg->regs, true); | ||
959 | jpeg_final_mcu_num_int_enable(jpeg->regs, true); | ||
960 | jpeg_outform_raw(jpeg->regs, S5P_JPEG_RAW_OUT_422); | ||
961 | jpeg_jpgadr(jpeg->regs, src_addr); | ||
962 | jpeg_imgadr(jpeg->regs, dst_addr); | ||
963 | } | ||
964 | jpeg_start(jpeg->regs); | ||
965 | } | ||
966 | |||
967 | static int s5p_jpeg_job_ready(void *priv) | ||
968 | { | ||
969 | struct s5p_jpeg_ctx *ctx = priv; | ||
970 | |||
971 | if (ctx->mode == S5P_JPEG_DECODE) | ||
972 | return ctx->hdr_parsed; | ||
973 | return 1; | ||
974 | } | ||
975 | |||
976 | static void s5p_jpeg_job_abort(void *priv) | ||
977 | { | ||
978 | } | ||
979 | |||
980 | static struct v4l2_m2m_ops s5p_jpeg_m2m_ops = { | ||
981 | .device_run = s5p_jpeg_device_run, | ||
982 | .job_ready = s5p_jpeg_job_ready, | ||
983 | .job_abort = s5p_jpeg_job_abort, | ||
984 | }; | ||
985 | |||
986 | /* | ||
987 | * ============================================================================ | ||
988 | * Queue operations | ||
989 | * ============================================================================ | ||
990 | */ | ||
991 | |||
992 | static int s5p_jpeg_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers, | ||
993 | unsigned int *nplanes, unsigned int sizes[], | ||
994 | void *alloc_ctxs[]) | ||
995 | { | ||
996 | struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq); | ||
997 | struct s5p_jpeg_q_data *q_data = NULL; | ||
998 | unsigned int size, count = *nbuffers; | ||
999 | |||
1000 | q_data = get_q_data(ctx, vq->type); | ||
1001 | BUG_ON(q_data == NULL); | ||
1002 | |||
1003 | size = q_data->size; | ||
1004 | |||
1005 | /* | ||
1006 | * header is parsed during decoding and parsed information stored | ||
1007 | * in the context so we do not allow another buffer to overwrite it | ||
1008 | */ | ||
1009 | if (ctx->mode == S5P_JPEG_DECODE) | ||
1010 | count = 1; | ||
1011 | |||
1012 | *nbuffers = count; | ||
1013 | *nplanes = 1; | ||
1014 | sizes[0] = size; | ||
1015 | alloc_ctxs[0] = ctx->jpeg->alloc_ctx; | ||
1016 | |||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
1020 | static int s5p_jpeg_buf_prepare(struct vb2_buffer *vb) | ||
1021 | { | ||
1022 | struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||
1023 | struct s5p_jpeg_q_data *q_data = NULL; | ||
1024 | |||
1025 | q_data = get_q_data(ctx, vb->vb2_queue->type); | ||
1026 | BUG_ON(q_data == NULL); | ||
1027 | |||
1028 | if (vb2_plane_size(vb, 0) < q_data->size) { | ||
1029 | pr_err("%s data will not fit into plane (%lu < %lu)\n", | ||
1030 | __func__, vb2_plane_size(vb, 0), | ||
1031 | (long)q_data->size); | ||
1032 | return -EINVAL; | ||
1033 | } | ||
1034 | |||
1035 | vb2_set_plane_payload(vb, 0, q_data->size); | ||
1036 | |||
1037 | return 0; | ||
1038 | } | ||
1039 | |||
1040 | static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) | ||
1041 | { | ||
1042 | struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue); | ||
1043 | |||
1044 | if (ctx->mode == S5P_JPEG_DECODE && | ||
1045 | vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { | ||
1046 | struct s5p_jpeg_q_data tmp, *q_data; | ||
1047 | ctx->hdr_parsed = s5p_jpeg_parse_hdr(&tmp, | ||
1048 | (unsigned long)vb2_plane_vaddr(vb, 0), | ||
1049 | min((unsigned long)ctx->out_q.size, | ||
1050 | vb2_get_plane_payload(vb, 0))); | ||
1051 | if (!ctx->hdr_parsed) { | ||
1052 | vb2_buffer_done(vb, VB2_BUF_STATE_ERROR); | ||
1053 | return; | ||
1054 | } | ||
1055 | |||
1056 | q_data = &ctx->out_q; | ||
1057 | q_data->w = tmp.w; | ||
1058 | q_data->h = tmp.h; | ||
1059 | |||
1060 | q_data = &ctx->cap_q; | ||
1061 | q_data->w = tmp.w; | ||
1062 | q_data->h = tmp.h; | ||
1063 | |||
1064 | jpeg_bound_align_image(&q_data->w, S5P_JPEG_MIN_WIDTH, | ||
1065 | S5P_JPEG_MAX_WIDTH, q_data->fmt->h_align, | ||
1066 | &q_data->h, S5P_JPEG_MIN_HEIGHT, | ||
1067 | S5P_JPEG_MAX_HEIGHT, q_data->fmt->v_align | ||
1068 | ); | ||
1069 | q_data->size = q_data->w * q_data->h * q_data->fmt->depth >> 3; | ||
1070 | } | ||
1071 | if (ctx->m2m_ctx) | ||
1072 | v4l2_m2m_buf_queue(ctx->m2m_ctx, vb); | ||
1073 | } | ||
1074 | |||
1075 | static void s5p_jpeg_wait_prepare(struct vb2_queue *vq) | ||
1076 | { | ||
1077 | struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq); | ||
1078 | |||
1079 | mutex_unlock(&ctx->jpeg->lock); | ||
1080 | } | ||
1081 | |||
1082 | static void s5p_jpeg_wait_finish(struct vb2_queue *vq) | ||
1083 | { | ||
1084 | struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(vq); | ||
1085 | |||
1086 | mutex_lock(&ctx->jpeg->lock); | ||
1087 | } | ||
1088 | |||
1089 | static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count) | ||
1090 | { | ||
1091 | struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q); | ||
1092 | int ret; | ||
1093 | |||
1094 | ret = pm_runtime_get_sync(ctx->jpeg->dev); | ||
1095 | |||
1096 | return ret > 0 ? 0 : ret; | ||
1097 | } | ||
1098 | |||
1099 | static int s5p_jpeg_stop_streaming(struct vb2_queue *q) | ||
1100 | { | ||
1101 | struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q); | ||
1102 | |||
1103 | pm_runtime_put(ctx->jpeg->dev); | ||
1104 | |||
1105 | return 0; | ||
1106 | } | ||
1107 | |||
1108 | static struct vb2_ops s5p_jpeg_qops = { | ||
1109 | .queue_setup = s5p_jpeg_queue_setup, | ||
1110 | .buf_prepare = s5p_jpeg_buf_prepare, | ||
1111 | .buf_queue = s5p_jpeg_buf_queue, | ||
1112 | .wait_prepare = s5p_jpeg_wait_prepare, | ||
1113 | .wait_finish = s5p_jpeg_wait_finish, | ||
1114 | .start_streaming = s5p_jpeg_start_streaming, | ||
1115 | .stop_streaming = s5p_jpeg_stop_streaming, | ||
1116 | }; | ||
1117 | |||
1118 | static int queue_init(void *priv, struct vb2_queue *src_vq, | ||
1119 | struct vb2_queue *dst_vq) | ||
1120 | { | ||
1121 | struct s5p_jpeg_ctx *ctx = priv; | ||
1122 | int ret; | ||
1123 | |||
1124 | memset(src_vq, 0, sizeof(*src_vq)); | ||
1125 | src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; | ||
1126 | src_vq->io_modes = VB2_MMAP | VB2_USERPTR; | ||
1127 | src_vq->drv_priv = ctx; | ||
1128 | src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); | ||
1129 | src_vq->ops = &s5p_jpeg_qops; | ||
1130 | src_vq->mem_ops = &vb2_dma_contig_memops; | ||
1131 | |||
1132 | ret = vb2_queue_init(src_vq); | ||
1133 | if (ret) | ||
1134 | return ret; | ||
1135 | |||
1136 | memset(dst_vq, 0, sizeof(*dst_vq)); | ||
1137 | dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||
1138 | dst_vq->io_modes = VB2_MMAP | VB2_USERPTR; | ||
1139 | dst_vq->drv_priv = ctx; | ||
1140 | dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer); | ||
1141 | dst_vq->ops = &s5p_jpeg_qops; | ||
1142 | dst_vq->mem_ops = &vb2_dma_contig_memops; | ||
1143 | |||
1144 | return vb2_queue_init(dst_vq); | ||
1145 | } | ||
1146 | |||
1147 | /* | ||
1148 | * ============================================================================ | ||
1149 | * ISR | ||
1150 | * ============================================================================ | ||
1151 | */ | ||
1152 | |||
1153 | static irqreturn_t s5p_jpeg_irq(int irq, void *dev_id) | ||
1154 | { | ||
1155 | struct s5p_jpeg *jpeg = dev_id; | ||
1156 | struct s5p_jpeg_ctx *curr_ctx; | ||
1157 | struct vb2_buffer *src_buf, *dst_buf; | ||
1158 | unsigned long payload_size = 0; | ||
1159 | enum vb2_buffer_state state = VB2_BUF_STATE_DONE; | ||
1160 | bool enc_jpeg_too_large = false; | ||
1161 | bool timer_elapsed = false; | ||
1162 | bool op_completed = false; | ||
1163 | |||
1164 | curr_ctx = v4l2_m2m_get_curr_priv(jpeg->m2m_dev); | ||
1165 | |||
1166 | src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx); | ||
1167 | dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx); | ||
1168 | |||
1169 | if (curr_ctx->mode == S5P_JPEG_ENCODE) | ||
1170 | enc_jpeg_too_large = jpeg_enc_stream_stat(jpeg->regs); | ||
1171 | timer_elapsed = jpeg_timer_stat(jpeg->regs); | ||
1172 | op_completed = jpeg_result_stat_ok(jpeg->regs); | ||
1173 | if (curr_ctx->mode == S5P_JPEG_DECODE) | ||
1174 | op_completed = op_completed && jpeg_stream_stat_ok(jpeg->regs); | ||
1175 | |||
1176 | if (enc_jpeg_too_large) { | ||
1177 | state = VB2_BUF_STATE_ERROR; | ||
1178 | jpeg_clear_enc_stream_stat(jpeg->regs); | ||
1179 | } else if (timer_elapsed) { | ||
1180 | state = VB2_BUF_STATE_ERROR; | ||
1181 | jpeg_clear_timer_stat(jpeg->regs); | ||
1182 | } else if (!op_completed) { | ||
1183 | state = VB2_BUF_STATE_ERROR; | ||
1184 | } else { | ||
1185 | payload_size = jpeg_compressed_size(jpeg->regs); | ||
1186 | } | ||
1187 | |||
1188 | v4l2_m2m_buf_done(src_buf, state); | ||
1189 | if (curr_ctx->mode == S5P_JPEG_ENCODE) | ||
1190 | vb2_set_plane_payload(dst_buf, 0, payload_size); | ||
1191 | v4l2_m2m_buf_done(dst_buf, state); | ||
1192 | v4l2_m2m_job_finish(jpeg->m2m_dev, curr_ctx->m2m_ctx); | ||
1193 | |||
1194 | jpeg_clear_int(jpeg->regs); | ||
1195 | |||
1196 | return IRQ_HANDLED; | ||
1197 | } | ||
1198 | |||
1199 | /* | ||
1200 | * ============================================================================ | ||
1201 | * Driver basic infrastructure | ||
1202 | * ============================================================================ | ||
1203 | */ | ||
1204 | |||
1205 | static int s5p_jpeg_probe(struct platform_device *pdev) | ||
1206 | { | ||
1207 | struct s5p_jpeg *jpeg; | ||
1208 | struct resource *res; | ||
1209 | int ret; | ||
1210 | |||
1211 | /* JPEG IP abstraction struct */ | ||
1212 | jpeg = kzalloc(sizeof(struct s5p_jpeg), GFP_KERNEL); | ||
1213 | if (!jpeg) | ||
1214 | return -ENOMEM; | ||
1215 | |||
1216 | mutex_init(&jpeg->lock); | ||
1217 | jpeg->dev = &pdev->dev; | ||
1218 | |||
1219 | /* memory-mapped registers */ | ||
1220 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1221 | if (!res) { | ||
1222 | dev_err(&pdev->dev, "cannot find IO resource\n"); | ||
1223 | ret = -ENOENT; | ||
1224 | goto jpeg_alloc_rollback; | ||
1225 | } | ||
1226 | |||
1227 | jpeg->ioarea = request_mem_region(res->start, resource_size(res), | ||
1228 | pdev->name); | ||
1229 | if (!jpeg->ioarea) { | ||
1230 | dev_err(&pdev->dev, "cannot request IO\n"); | ||
1231 | ret = -ENXIO; | ||
1232 | goto jpeg_alloc_rollback; | ||
1233 | } | ||
1234 | |||
1235 | jpeg->regs = ioremap(res->start, resource_size(res)); | ||
1236 | if (!jpeg->regs) { | ||
1237 | dev_err(&pdev->dev, "cannot map IO\n"); | ||
1238 | ret = -ENXIO; | ||
1239 | goto mem_region_rollback; | ||
1240 | } | ||
1241 | |||
1242 | dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", | ||
1243 | jpeg->regs, jpeg->ioarea, res); | ||
1244 | |||
1245 | /* interrupt service routine registration */ | ||
1246 | jpeg->irq = ret = platform_get_irq(pdev, 0); | ||
1247 | if (ret < 0) { | ||
1248 | dev_err(&pdev->dev, "cannot find IRQ\n"); | ||
1249 | goto ioremap_rollback; | ||
1250 | } | ||
1251 | |||
1252 | ret = request_irq(jpeg->irq, s5p_jpeg_irq, 0, | ||
1253 | dev_name(&pdev->dev), jpeg); | ||
1254 | |||
1255 | if (ret) { | ||
1256 | dev_err(&pdev->dev, "cannot claim IRQ %d\n", jpeg->irq); | ||
1257 | goto ioremap_rollback; | ||
1258 | } | ||
1259 | |||
1260 | /* clocks */ | ||
1261 | jpeg->clk = clk_get(&pdev->dev, "jpeg"); | ||
1262 | if (IS_ERR(jpeg->clk)) { | ||
1263 | dev_err(&pdev->dev, "cannot get clock\n"); | ||
1264 | ret = PTR_ERR(jpeg->clk); | ||
1265 | goto request_irq_rollback; | ||
1266 | } | ||
1267 | dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk); | ||
1268 | clk_enable(jpeg->clk); | ||
1269 | |||
1270 | /* v4l2 device */ | ||
1271 | ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev); | ||
1272 | if (ret) { | ||
1273 | dev_err(&pdev->dev, "Failed to register v4l2 device\n"); | ||
1274 | goto clk_get_rollback; | ||
1275 | } | ||
1276 | |||
1277 | /* mem2mem device */ | ||
1278 | jpeg->m2m_dev = v4l2_m2m_init(&s5p_jpeg_m2m_ops); | ||
1279 | if (IS_ERR(jpeg->m2m_dev)) { | ||
1280 | v4l2_err(&jpeg->v4l2_dev, "Failed to init mem2mem device\n"); | ||
1281 | ret = PTR_ERR(jpeg->m2m_dev); | ||
1282 | goto device_register_rollback; | ||
1283 | } | ||
1284 | |||
1285 | jpeg->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev); | ||
1286 | if (IS_ERR(jpeg->alloc_ctx)) { | ||
1287 | v4l2_err(&jpeg->v4l2_dev, "Failed to init memory allocator\n"); | ||
1288 | ret = PTR_ERR(jpeg->alloc_ctx); | ||
1289 | goto m2m_init_rollback; | ||
1290 | } | ||
1291 | |||
1292 | /* JPEG encoder /dev/videoX node */ | ||
1293 | jpeg->vfd_encoder = video_device_alloc(); | ||
1294 | if (!jpeg->vfd_encoder) { | ||
1295 | v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n"); | ||
1296 | ret = -ENOMEM; | ||
1297 | goto vb2_allocator_rollback; | ||
1298 | } | ||
1299 | strlcpy(jpeg->vfd_encoder->name, S5P_JPEG_M2M_NAME, | ||
1300 | sizeof(jpeg->vfd_encoder->name)); | ||
1301 | jpeg->vfd_encoder->fops = &s5p_jpeg_fops; | ||
1302 | jpeg->vfd_encoder->ioctl_ops = &s5p_jpeg_ioctl_ops; | ||
1303 | jpeg->vfd_encoder->minor = -1; | ||
1304 | jpeg->vfd_encoder->release = video_device_release; | ||
1305 | jpeg->vfd_encoder->lock = &jpeg->lock; | ||
1306 | jpeg->vfd_encoder->v4l2_dev = &jpeg->v4l2_dev; | ||
1307 | |||
1308 | ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_GRABBER, -1); | ||
1309 | if (ret) { | ||
1310 | v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n"); | ||
1311 | goto enc_vdev_alloc_rollback; | ||
1312 | } | ||
1313 | |||
1314 | video_set_drvdata(jpeg->vfd_encoder, jpeg); | ||
1315 | v4l2_info(&jpeg->v4l2_dev, | ||
1316 | "encoder device registered as /dev/video%d\n", | ||
1317 | jpeg->vfd_encoder->num); | ||
1318 | |||
1319 | /* JPEG decoder /dev/videoX node */ | ||
1320 | jpeg->vfd_decoder = video_device_alloc(); | ||
1321 | if (!jpeg->vfd_decoder) { | ||
1322 | v4l2_err(&jpeg->v4l2_dev, "Failed to allocate video device\n"); | ||
1323 | ret = -ENOMEM; | ||
1324 | goto enc_vdev_register_rollback; | ||
1325 | } | ||
1326 | strlcpy(jpeg->vfd_decoder->name, S5P_JPEG_M2M_NAME, | ||
1327 | sizeof(jpeg->vfd_decoder->name)); | ||
1328 | jpeg->vfd_decoder->fops = &s5p_jpeg_fops; | ||
1329 | jpeg->vfd_decoder->ioctl_ops = &s5p_jpeg_ioctl_ops; | ||
1330 | jpeg->vfd_decoder->minor = -1; | ||
1331 | jpeg->vfd_decoder->release = video_device_release; | ||
1332 | jpeg->vfd_decoder->lock = &jpeg->lock; | ||
1333 | jpeg->vfd_decoder->v4l2_dev = &jpeg->v4l2_dev; | ||
1334 | |||
1335 | ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1); | ||
1336 | if (ret) { | ||
1337 | v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n"); | ||
1338 | goto dec_vdev_alloc_rollback; | ||
1339 | } | ||
1340 | |||
1341 | video_set_drvdata(jpeg->vfd_decoder, jpeg); | ||
1342 | v4l2_info(&jpeg->v4l2_dev, | ||
1343 | "decoder device registered as /dev/video%d\n", | ||
1344 | jpeg->vfd_decoder->num); | ||
1345 | |||
1346 | /* final statements & power management */ | ||
1347 | platform_set_drvdata(pdev, jpeg); | ||
1348 | |||
1349 | pm_runtime_enable(&pdev->dev); | ||
1350 | |||
1351 | v4l2_info(&jpeg->v4l2_dev, "Samsung S5P JPEG codec\n"); | ||
1352 | |||
1353 | return 0; | ||
1354 | |||
1355 | dec_vdev_alloc_rollback: | ||
1356 | video_device_release(jpeg->vfd_decoder); | ||
1357 | |||
1358 | enc_vdev_register_rollback: | ||
1359 | video_unregister_device(jpeg->vfd_encoder); | ||
1360 | |||
1361 | enc_vdev_alloc_rollback: | ||
1362 | video_device_release(jpeg->vfd_encoder); | ||
1363 | |||
1364 | vb2_allocator_rollback: | ||
1365 | vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx); | ||
1366 | |||
1367 | m2m_init_rollback: | ||
1368 | v4l2_m2m_release(jpeg->m2m_dev); | ||
1369 | |||
1370 | device_register_rollback: | ||
1371 | v4l2_device_unregister(&jpeg->v4l2_dev); | ||
1372 | |||
1373 | clk_get_rollback: | ||
1374 | clk_disable(jpeg->clk); | ||
1375 | clk_put(jpeg->clk); | ||
1376 | |||
1377 | request_irq_rollback: | ||
1378 | free_irq(jpeg->irq, jpeg); | ||
1379 | |||
1380 | ioremap_rollback: | ||
1381 | iounmap(jpeg->regs); | ||
1382 | |||
1383 | mem_region_rollback: | ||
1384 | release_resource(jpeg->ioarea); | ||
1385 | release_mem_region(jpeg->ioarea->start, resource_size(jpeg->ioarea)); | ||
1386 | |||
1387 | jpeg_alloc_rollback: | ||
1388 | kfree(jpeg); | ||
1389 | return ret; | ||
1390 | } | ||
1391 | |||
1392 | static int s5p_jpeg_remove(struct platform_device *pdev) | ||
1393 | { | ||
1394 | struct s5p_jpeg *jpeg = platform_get_drvdata(pdev); | ||
1395 | |||
1396 | pm_runtime_disable(jpeg->dev); | ||
1397 | |||
1398 | video_unregister_device(jpeg->vfd_decoder); | ||
1399 | video_device_release(jpeg->vfd_decoder); | ||
1400 | video_unregister_device(jpeg->vfd_encoder); | ||
1401 | video_device_release(jpeg->vfd_encoder); | ||
1402 | vb2_dma_contig_cleanup_ctx(jpeg->alloc_ctx); | ||
1403 | v4l2_m2m_release(jpeg->m2m_dev); | ||
1404 | v4l2_device_unregister(&jpeg->v4l2_dev); | ||
1405 | |||
1406 | clk_disable(jpeg->clk); | ||
1407 | clk_put(jpeg->clk); | ||
1408 | |||
1409 | free_irq(jpeg->irq, jpeg); | ||
1410 | |||
1411 | iounmap(jpeg->regs); | ||
1412 | |||
1413 | release_resource(jpeg->ioarea); | ||
1414 | release_mem_region(jpeg->ioarea->start, resource_size(jpeg->ioarea)); | ||
1415 | kfree(jpeg); | ||
1416 | |||
1417 | return 0; | ||
1418 | } | ||
1419 | |||
1420 | static int s5p_jpeg_runtime_suspend(struct device *dev) | ||
1421 | { | ||
1422 | return 0; | ||
1423 | } | ||
1424 | |||
1425 | static int s5p_jpeg_runtime_resume(struct device *dev) | ||
1426 | { | ||
1427 | struct s5p_jpeg *jpeg = dev_get_drvdata(dev); | ||
1428 | /* | ||
1429 | * JPEG IP allows storing two Huffman tables for each component | ||
1430 | * We fill table 0 for each component | ||
1431 | */ | ||
1432 | jpeg_set_hdctbl(jpeg->regs); | ||
1433 | jpeg_set_hdctblg(jpeg->regs); | ||
1434 | jpeg_set_hactbl(jpeg->regs); | ||
1435 | jpeg_set_hactblg(jpeg->regs); | ||
1436 | return 0; | ||
1437 | } | ||
1438 | |||
1439 | static const struct dev_pm_ops s5p_jpeg_pm_ops = { | ||
1440 | .runtime_suspend = s5p_jpeg_runtime_suspend, | ||
1441 | .runtime_resume = s5p_jpeg_runtime_resume, | ||
1442 | }; | ||
1443 | |||
1444 | static struct platform_driver s5p_jpeg_driver = { | ||
1445 | .probe = s5p_jpeg_probe, | ||
1446 | .remove = s5p_jpeg_remove, | ||
1447 | .driver = { | ||
1448 | .owner = THIS_MODULE, | ||
1449 | .name = S5P_JPEG_M2M_NAME, | ||
1450 | .pm = &s5p_jpeg_pm_ops, | ||
1451 | }, | ||
1452 | }; | ||
1453 | |||
1454 | static int __init | ||
1455 | s5p_jpeg_register(void) | ||
1456 | { | ||
1457 | int ret; | ||
1458 | |||
1459 | pr_info("S5P JPEG V4L2 Driver, (c) 2011 Samsung Electronics\n"); | ||
1460 | |||
1461 | ret = platform_driver_register(&s5p_jpeg_driver); | ||
1462 | |||
1463 | if (ret) | ||
1464 | pr_err("%s: failed to register jpeg driver\n", __func__); | ||
1465 | |||
1466 | return ret; | ||
1467 | } | ||
1468 | |||
1469 | static void __exit | ||
1470 | s5p_jpeg_unregister(void) | ||
1471 | { | ||
1472 | platform_driver_unregister(&s5p_jpeg_driver); | ||
1473 | } | ||
1474 | |||
1475 | module_init(s5p_jpeg_register); | ||
1476 | module_exit(s5p_jpeg_unregister); | ||
1477 | |||
1478 | MODULE_AUTHOR("Andrzej Pietrasiewicz <andrzej.p@samsung.com>"); | ||
1479 | MODULE_DESCRIPTION("Samsung JPEG codec driver"); | ||
1480 | MODULE_LICENSE("GPL"); | ||
1481 | |||
diff --git a/drivers/media/video/s5p-jpeg/jpeg-core.h b/drivers/media/video/s5p-jpeg/jpeg-core.h new file mode 100644 index 000000000000..facad6114f5e --- /dev/null +++ b/drivers/media/video/s5p-jpeg/jpeg-core.h | |||
@@ -0,0 +1,143 @@ | |||
1 | /* linux/drivers/media/video/s5p-jpeg/jpeg-core.h | ||
2 | * | ||
3 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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 version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef JPEG_CORE_H_ | ||
14 | #define JPEG_CORE_H_ | ||
15 | |||
16 | #include <media/v4l2-device.h> | ||
17 | |||
18 | #define S5P_JPEG_M2M_NAME "s5p-jpeg" | ||
19 | |||
20 | /* JPEG compression quality setting */ | ||
21 | #define S5P_JPEG_COMPR_QUAL_BEST 0 | ||
22 | #define S5P_JPEG_COMPR_QUAL_WORST 3 | ||
23 | |||
24 | /* JPEG RGB to YCbCr conversion matrix coefficients */ | ||
25 | #define S5P_JPEG_COEF11 0x4d | ||
26 | #define S5P_JPEG_COEF12 0x97 | ||
27 | #define S5P_JPEG_COEF13 0x1e | ||
28 | #define S5P_JPEG_COEF21 0x2c | ||
29 | #define S5P_JPEG_COEF22 0x57 | ||
30 | #define S5P_JPEG_COEF23 0x83 | ||
31 | #define S5P_JPEG_COEF31 0x83 | ||
32 | #define S5P_JPEG_COEF32 0x6e | ||
33 | #define S5P_JPEG_COEF33 0x13 | ||
34 | |||
35 | /* a selection of JPEG markers */ | ||
36 | #define TEM 0x01 | ||
37 | #define SOF0 0xc0 | ||
38 | #define RST 0xd0 | ||
39 | #define SOI 0xd8 | ||
40 | #define EOI 0xd9 | ||
41 | #define DHP 0xde | ||
42 | |||
43 | /* Flags that indicate a format can be used for capture/output */ | ||
44 | #define MEM2MEM_CAPTURE (1 << 0) | ||
45 | #define MEM2MEM_OUTPUT (1 << 1) | ||
46 | |||
47 | /** | ||
48 | * struct s5p_jpeg - JPEG IP abstraction | ||
49 | * @lock: the mutex protecting this structure | ||
50 | * @v4l2_dev: v4l2 device for mem2mem mode | ||
51 | * @vfd_encoder: video device node for encoder mem2mem mode | ||
52 | * @vfd_decoder: video device node for decoder mem2mem mode | ||
53 | * @m2m_dev: v4l2 mem2mem device data | ||
54 | * @ioarea: JPEG IP memory region | ||
55 | * @regs: JPEG IP registers mapping | ||
56 | * @irq: JPEG IP irq | ||
57 | * @clk: JPEG IP clock | ||
58 | * @dev: JPEG IP struct device | ||
59 | * @alloc_ctx: videobuf2 memory allocator's context | ||
60 | */ | ||
61 | struct s5p_jpeg { | ||
62 | struct mutex lock; | ||
63 | |||
64 | struct v4l2_device v4l2_dev; | ||
65 | struct video_device *vfd_encoder; | ||
66 | struct video_device *vfd_decoder; | ||
67 | struct v4l2_m2m_dev *m2m_dev; | ||
68 | |||
69 | struct resource *ioarea; | ||
70 | void __iomem *regs; | ||
71 | unsigned int irq; | ||
72 | struct clk *clk; | ||
73 | struct device *dev; | ||
74 | void *alloc_ctx; | ||
75 | }; | ||
76 | |||
77 | /** | ||
78 | * struct jpeg_fmt - driver's internal color format data | ||
79 | * @name: format descritpion | ||
80 | * @fourcc: the fourcc code, 0 if not applicable | ||
81 | * @depth: number of bits per pixel | ||
82 | * @colplanes: number of color planes (1 for packed formats) | ||
83 | * @h_align: horizontal alignment order (align to 2^h_align) | ||
84 | * @v_align: vertical alignment order (align to 2^v_align) | ||
85 | * @types: types of queue this format is applicable to | ||
86 | */ | ||
87 | struct s5p_jpeg_fmt { | ||
88 | char *name; | ||
89 | u32 fourcc; | ||
90 | int depth; | ||
91 | int colplanes; | ||
92 | int h_align; | ||
93 | int v_align; | ||
94 | u32 types; | ||
95 | }; | ||
96 | |||
97 | /** | ||
98 | * s5p_jpeg_q_data - parameters of one queue | ||
99 | * @fmt: driver-specific format of this queue | ||
100 | * @w: image width | ||
101 | * @h: image height | ||
102 | * @size: image buffer size in bytes | ||
103 | */ | ||
104 | struct s5p_jpeg_q_data { | ||
105 | struct s5p_jpeg_fmt *fmt; | ||
106 | u32 w; | ||
107 | u32 h; | ||
108 | u32 size; | ||
109 | }; | ||
110 | |||
111 | /** | ||
112 | * s5p_jpeg_ctx - the device context data | ||
113 | * @jpeg: JPEG IP device for this context | ||
114 | * @mode: compression (encode) operation or decompression (decode) | ||
115 | * @compr_quality: destination image quality in compression (encode) mode | ||
116 | * @m2m_ctx: mem2mem device context | ||
117 | * @out_q: source (output) queue information | ||
118 | * @cap_fmt: destination (capture) queue queue information | ||
119 | * @hdr_parsed: set if header has been parsed during decompression | ||
120 | */ | ||
121 | struct s5p_jpeg_ctx { | ||
122 | struct s5p_jpeg *jpeg; | ||
123 | unsigned int mode; | ||
124 | unsigned int compr_quality; | ||
125 | struct v4l2_m2m_ctx *m2m_ctx; | ||
126 | struct s5p_jpeg_q_data out_q; | ||
127 | struct s5p_jpeg_q_data cap_q; | ||
128 | bool hdr_parsed; | ||
129 | }; | ||
130 | |||
131 | /** | ||
132 | * s5p_jpeg_buffer - description of memory containing input JPEG data | ||
133 | * @size: buffer size | ||
134 | * @curr: current position in the buffer | ||
135 | * @data: pointer to the data | ||
136 | */ | ||
137 | struct s5p_jpeg_buffer { | ||
138 | unsigned long size; | ||
139 | unsigned long curr; | ||
140 | unsigned long data; | ||
141 | }; | ||
142 | |||
143 | #endif /* JPEG_CORE_H */ | ||
diff --git a/drivers/media/video/s5p-jpeg/jpeg-hw.h b/drivers/media/video/s5p-jpeg/jpeg-hw.h new file mode 100644 index 000000000000..e10c744e9f23 --- /dev/null +++ b/drivers/media/video/s5p-jpeg/jpeg-hw.h | |||
@@ -0,0 +1,353 @@ | |||
1 | /* linux/drivers/media/video/s5p-jpeg/jpeg-hw.h | ||
2 | * | ||
3 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
4 | * http://www.samsung.com | ||
5 | * | ||
6 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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 version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | #ifndef JPEG_HW_H_ | ||
13 | #define JPEG_HW_H_ | ||
14 | |||
15 | #include <linux/io.h> | ||
16 | |||
17 | #include "jpeg-hw.h" | ||
18 | #include "jpeg-regs.h" | ||
19 | |||
20 | #define S5P_JPEG_MIN_WIDTH 32 | ||
21 | #define S5P_JPEG_MIN_HEIGHT 32 | ||
22 | #define S5P_JPEG_MAX_WIDTH 8192 | ||
23 | #define S5P_JPEG_MAX_HEIGHT 8192 | ||
24 | #define S5P_JPEG_ENCODE 0 | ||
25 | #define S5P_JPEG_DECODE 1 | ||
26 | #define S5P_JPEG_RAW_IN_565 0 | ||
27 | #define S5P_JPEG_RAW_IN_422 1 | ||
28 | #define S5P_JPEG_SUBSAMPLING_422 0 | ||
29 | #define S5P_JPEG_SUBSAMPLING_420 1 | ||
30 | #define S5P_JPEG_RAW_OUT_422 0 | ||
31 | #define S5P_JPEG_RAW_OUT_420 1 | ||
32 | |||
33 | static inline void jpeg_reset(void __iomem *regs) | ||
34 | { | ||
35 | unsigned long reg; | ||
36 | |||
37 | writel(1, regs + S5P_JPG_SW_RESET); | ||
38 | reg = readl(regs + S5P_JPG_SW_RESET); | ||
39 | /* no other way but polling for when JPEG IP becomes operational */ | ||
40 | while (reg != 0) { | ||
41 | cpu_relax(); | ||
42 | reg = readl(regs + S5P_JPG_SW_RESET); | ||
43 | } | ||
44 | } | ||
45 | |||
46 | static inline void jpeg_poweron(void __iomem *regs) | ||
47 | { | ||
48 | writel(S5P_POWER_ON, regs + S5P_JPGCLKCON); | ||
49 | } | ||
50 | |||
51 | static inline void jpeg_input_raw_mode(void __iomem *regs, unsigned long mode) | ||
52 | { | ||
53 | unsigned long reg, m; | ||
54 | |||
55 | m = S5P_MOD_SEL_565; | ||
56 | if (mode == S5P_JPEG_RAW_IN_565) | ||
57 | m = S5P_MOD_SEL_565; | ||
58 | else if (mode == S5P_JPEG_RAW_IN_422) | ||
59 | m = S5P_MOD_SEL_422; | ||
60 | |||
61 | reg = readl(regs + S5P_JPGCMOD); | ||
62 | reg &= ~S5P_MOD_SEL_MASK; | ||
63 | reg |= m; | ||
64 | writel(reg, regs + S5P_JPGCMOD); | ||
65 | } | ||
66 | |||
67 | static inline void jpeg_input_raw_y16(void __iomem *regs, bool y16) | ||
68 | { | ||
69 | unsigned long reg; | ||
70 | |||
71 | reg = readl(regs + S5P_JPGCMOD); | ||
72 | if (y16) | ||
73 | reg |= S5P_MODE_Y16; | ||
74 | else | ||
75 | reg &= ~S5P_MODE_Y16_MASK; | ||
76 | writel(reg, regs + S5P_JPGCMOD); | ||
77 | } | ||
78 | |||
79 | static inline void jpeg_proc_mode(void __iomem *regs, unsigned long mode) | ||
80 | { | ||
81 | unsigned long reg, m; | ||
82 | |||
83 | m = S5P_PROC_MODE_DECOMPR; | ||
84 | if (mode == S5P_JPEG_ENCODE) | ||
85 | m = S5P_PROC_MODE_COMPR; | ||
86 | else | ||
87 | m = S5P_PROC_MODE_DECOMPR; | ||
88 | reg = readl(regs + S5P_JPGMOD); | ||
89 | reg &= ~S5P_PROC_MODE_MASK; | ||
90 | reg |= m; | ||
91 | writel(reg, regs + S5P_JPGMOD); | ||
92 | } | ||
93 | |||
94 | static inline void jpeg_subsampling_mode(void __iomem *regs, unsigned long mode) | ||
95 | { | ||
96 | unsigned long reg, m; | ||
97 | |||
98 | m = S5P_SUBSAMPLING_MODE_422; | ||
99 | if (mode == S5P_JPEG_SUBSAMPLING_422) | ||
100 | m = S5P_SUBSAMPLING_MODE_422; | ||
101 | else if (mode == S5P_JPEG_SUBSAMPLING_420) | ||
102 | m = S5P_SUBSAMPLING_MODE_420; | ||
103 | reg = readl(regs + S5P_JPGMOD); | ||
104 | reg &= ~S5P_SUBSAMPLING_MODE_MASK; | ||
105 | reg |= m; | ||
106 | writel(reg, regs + S5P_JPGMOD); | ||
107 | } | ||
108 | |||
109 | static inline void jpeg_dri(void __iomem *regs, unsigned int dri) | ||
110 | { | ||
111 | unsigned long reg; | ||
112 | |||
113 | reg = readl(regs + S5P_JPGDRI_U); | ||
114 | reg &= ~0xff; | ||
115 | reg |= (dri >> 8) & 0xff; | ||
116 | writel(reg, regs + S5P_JPGDRI_U); | ||
117 | |||
118 | reg = readl(regs + S5P_JPGDRI_L); | ||
119 | reg &= ~0xff; | ||
120 | reg |= dri & 0xff; | ||
121 | writel(reg, regs + S5P_JPGDRI_L); | ||
122 | } | ||
123 | |||
124 | static inline void jpeg_qtbl(void __iomem *regs, unsigned int t, unsigned int n) | ||
125 | { | ||
126 | unsigned long reg; | ||
127 | |||
128 | reg = readl(regs + S5P_JPG_QTBL); | ||
129 | reg &= ~S5P_QT_NUMt_MASK(t); | ||
130 | reg |= (n << S5P_QT_NUMt_SHIFT(t)) & S5P_QT_NUMt_MASK(t); | ||
131 | writel(reg, regs + S5P_JPG_QTBL); | ||
132 | } | ||
133 | |||
134 | static inline void jpeg_htbl_ac(void __iomem *regs, unsigned int t) | ||
135 | { | ||
136 | unsigned long reg; | ||
137 | |||
138 | reg = readl(regs + S5P_JPG_HTBL); | ||
139 | reg &= ~S5P_HT_NUMt_AC_MASK(t); | ||
140 | /* this driver uses table 0 for all color components */ | ||
141 | reg |= (0 << S5P_HT_NUMt_AC_SHIFT(t)) & S5P_HT_NUMt_AC_MASK(t); | ||
142 | writel(reg, regs + S5P_JPG_HTBL); | ||
143 | } | ||
144 | |||
145 | static inline void jpeg_htbl_dc(void __iomem *regs, unsigned int t) | ||
146 | { | ||
147 | unsigned long reg; | ||
148 | |||
149 | reg = readl(regs + S5P_JPG_HTBL); | ||
150 | reg &= ~S5P_HT_NUMt_DC_MASK(t); | ||
151 | /* this driver uses table 0 for all color components */ | ||
152 | reg |= (0 << S5P_HT_NUMt_DC_SHIFT(t)) & S5P_HT_NUMt_DC_MASK(t); | ||
153 | writel(reg, regs + S5P_JPG_HTBL); | ||
154 | } | ||
155 | |||
156 | static inline void jpeg_y(void __iomem *regs, unsigned int y) | ||
157 | { | ||
158 | unsigned long reg; | ||
159 | |||
160 | reg = readl(regs + S5P_JPGY_U); | ||
161 | reg &= ~0xff; | ||
162 | reg |= (y >> 8) & 0xff; | ||
163 | writel(reg, regs + S5P_JPGY_U); | ||
164 | |||
165 | reg = readl(regs + S5P_JPGY_L); | ||
166 | reg &= ~0xff; | ||
167 | reg |= y & 0xff; | ||
168 | writel(reg, regs + S5P_JPGY_L); | ||
169 | } | ||
170 | |||
171 | static inline void jpeg_x(void __iomem *regs, unsigned int x) | ||
172 | { | ||
173 | unsigned long reg; | ||
174 | |||
175 | reg = readl(regs + S5P_JPGX_U); | ||
176 | reg &= ~0xff; | ||
177 | reg |= (x >> 8) & 0xff; | ||
178 | writel(reg, regs + S5P_JPGX_U); | ||
179 | |||
180 | reg = readl(regs + S5P_JPGX_L); | ||
181 | reg &= ~0xff; | ||
182 | reg |= x & 0xff; | ||
183 | writel(reg, regs + S5P_JPGX_L); | ||
184 | } | ||
185 | |||
186 | static inline void jpeg_rst_int_enable(void __iomem *regs, bool enable) | ||
187 | { | ||
188 | unsigned long reg; | ||
189 | |||
190 | reg = readl(regs + S5P_JPGINTSE); | ||
191 | reg &= ~S5P_RSTm_INT_EN_MASK; | ||
192 | if (enable) | ||
193 | reg |= S5P_RSTm_INT_EN; | ||
194 | writel(reg, regs + S5P_JPGINTSE); | ||
195 | } | ||
196 | |||
197 | static inline void jpeg_data_num_int_enable(void __iomem *regs, bool enable) | ||
198 | { | ||
199 | unsigned long reg; | ||
200 | |||
201 | reg = readl(regs + S5P_JPGINTSE); | ||
202 | reg &= ~S5P_DATA_NUM_INT_EN_MASK; | ||
203 | if (enable) | ||
204 | reg |= S5P_DATA_NUM_INT_EN; | ||
205 | writel(reg, regs + S5P_JPGINTSE); | ||
206 | } | ||
207 | |||
208 | static inline void jpeg_final_mcu_num_int_enable(void __iomem *regs, bool enbl) | ||
209 | { | ||
210 | unsigned long reg; | ||
211 | |||
212 | reg = readl(regs + S5P_JPGINTSE); | ||
213 | reg &= ~S5P_FINAL_MCU_NUM_INT_EN_MASK; | ||
214 | if (enbl) | ||
215 | reg |= S5P_FINAL_MCU_NUM_INT_EN; | ||
216 | writel(reg, regs + S5P_JPGINTSE); | ||
217 | } | ||
218 | |||
219 | static inline void jpeg_timer_enable(void __iomem *regs, unsigned long val) | ||
220 | { | ||
221 | unsigned long reg; | ||
222 | |||
223 | reg = readl(regs + S5P_JPG_TIMER_SE); | ||
224 | reg |= S5P_TIMER_INT_EN; | ||
225 | reg &= ~S5P_TIMER_INIT_MASK; | ||
226 | reg |= val & S5P_TIMER_INIT_MASK; | ||
227 | writel(reg, regs + S5P_JPG_TIMER_SE); | ||
228 | } | ||
229 | |||
230 | static inline void jpeg_timer_disable(void __iomem *regs) | ||
231 | { | ||
232 | unsigned long reg; | ||
233 | |||
234 | reg = readl(regs + S5P_JPG_TIMER_SE); | ||
235 | reg &= ~S5P_TIMER_INT_EN_MASK; | ||
236 | writel(reg, regs + S5P_JPG_TIMER_SE); | ||
237 | } | ||
238 | |||
239 | static inline int jpeg_timer_stat(void __iomem *regs) | ||
240 | { | ||
241 | return (int)((readl(regs + S5P_JPG_TIMER_ST) & S5P_TIMER_INT_STAT_MASK) | ||
242 | >> S5P_TIMER_INT_STAT_SHIFT); | ||
243 | } | ||
244 | |||
245 | static inline void jpeg_clear_timer_stat(void __iomem *regs) | ||
246 | { | ||
247 | unsigned long reg; | ||
248 | |||
249 | reg = readl(regs + S5P_JPG_TIMER_SE); | ||
250 | reg &= ~S5P_TIMER_INT_STAT_MASK; | ||
251 | writel(reg, regs + S5P_JPG_TIMER_SE); | ||
252 | } | ||
253 | |||
254 | static inline void jpeg_enc_stream_int(void __iomem *regs, unsigned long size) | ||
255 | { | ||
256 | unsigned long reg; | ||
257 | |||
258 | reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE); | ||
259 | reg &= ~S5P_ENC_STREAM_BOUND_MASK; | ||
260 | reg |= S5P_ENC_STREAM_INT_EN; | ||
261 | reg |= size & S5P_ENC_STREAM_BOUND_MASK; | ||
262 | writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE); | ||
263 | } | ||
264 | |||
265 | static inline int jpeg_enc_stream_stat(void __iomem *regs) | ||
266 | { | ||
267 | return (int)(readl(regs + S5P_JPG_ENC_STREAM_INTST) & | ||
268 | S5P_ENC_STREAM_INT_STAT_MASK); | ||
269 | } | ||
270 | |||
271 | static inline void jpeg_clear_enc_stream_stat(void __iomem *regs) | ||
272 | { | ||
273 | unsigned long reg; | ||
274 | |||
275 | reg = readl(regs + S5P_JPG_ENC_STREAM_INTSE); | ||
276 | reg &= ~S5P_ENC_STREAM_INT_MASK; | ||
277 | writel(reg, regs + S5P_JPG_ENC_STREAM_INTSE); | ||
278 | } | ||
279 | |||
280 | static inline void jpeg_outform_raw(void __iomem *regs, unsigned long format) | ||
281 | { | ||
282 | unsigned long reg, f; | ||
283 | |||
284 | f = S5P_DEC_OUT_FORMAT_422; | ||
285 | if (format == S5P_JPEG_RAW_OUT_422) | ||
286 | f = S5P_DEC_OUT_FORMAT_422; | ||
287 | else if (format == S5P_JPEG_RAW_OUT_420) | ||
288 | f = S5P_DEC_OUT_FORMAT_420; | ||
289 | reg = readl(regs + S5P_JPG_OUTFORM); | ||
290 | reg &= ~S5P_DEC_OUT_FORMAT_MASK; | ||
291 | reg |= f; | ||
292 | writel(reg, regs + S5P_JPG_OUTFORM); | ||
293 | } | ||
294 | |||
295 | static inline void jpeg_jpgadr(void __iomem *regs, unsigned long addr) | ||
296 | { | ||
297 | writel(addr, regs + S5P_JPG_JPGADR); | ||
298 | } | ||
299 | |||
300 | static inline void jpeg_imgadr(void __iomem *regs, unsigned long addr) | ||
301 | { | ||
302 | writel(addr, regs + S5P_JPG_IMGADR); | ||
303 | } | ||
304 | |||
305 | static inline void jpeg_coef(void __iomem *regs, unsigned int i, | ||
306 | unsigned int j, unsigned int coef) | ||
307 | { | ||
308 | unsigned long reg; | ||
309 | |||
310 | reg = readl(regs + S5P_JPG_COEF(i)); | ||
311 | reg &= ~S5P_COEFn_MASK(j); | ||
312 | reg |= (coef << S5P_COEFn_SHIFT(j)) & S5P_COEFn_MASK(j); | ||
313 | writel(reg, regs + S5P_JPG_COEF(i)); | ||
314 | } | ||
315 | |||
316 | static inline void jpeg_start(void __iomem *regs) | ||
317 | { | ||
318 | writel(1, regs + S5P_JSTART); | ||
319 | } | ||
320 | |||
321 | static inline int jpeg_result_stat_ok(void __iomem *regs) | ||
322 | { | ||
323 | return (int)((readl(regs + S5P_JPGINTST) & S5P_RESULT_STAT_MASK) | ||
324 | >> S5P_RESULT_STAT_SHIFT); | ||
325 | } | ||
326 | |||
327 | static inline int jpeg_stream_stat_ok(void __iomem *regs) | ||
328 | { | ||
329 | return !(int)((readl(regs + S5P_JPGINTST) & S5P_STREAM_STAT_MASK) | ||
330 | >> S5P_STREAM_STAT_SHIFT); | ||
331 | } | ||
332 | |||
333 | static inline void jpeg_clear_int(void __iomem *regs) | ||
334 | { | ||
335 | unsigned long reg; | ||
336 | |||
337 | reg = readl(regs + S5P_JPGINTST); | ||
338 | writel(S5P_INT_RELEASE, regs + S5P_JPGCOM); | ||
339 | reg = readl(regs + S5P_JPGOPR); | ||
340 | } | ||
341 | |||
342 | static inline unsigned int jpeg_compressed_size(void __iomem *regs) | ||
343 | { | ||
344 | unsigned long jpeg_size = 0; | ||
345 | |||
346 | jpeg_size |= (readl(regs + S5P_JPGCNT_U) & 0xff) << 16; | ||
347 | jpeg_size |= (readl(regs + S5P_JPGCNT_M) & 0xff) << 8; | ||
348 | jpeg_size |= (readl(regs + S5P_JPGCNT_L) & 0xff); | ||
349 | |||
350 | return (unsigned int)jpeg_size; | ||
351 | } | ||
352 | |||
353 | #endif /* JPEG_HW_H_ */ | ||
diff --git a/drivers/media/video/s5p-jpeg/jpeg-regs.h b/drivers/media/video/s5p-jpeg/jpeg-regs.h new file mode 100644 index 000000000000..91f4dd5f86dd --- /dev/null +++ b/drivers/media/video/s5p-jpeg/jpeg-regs.h | |||
@@ -0,0 +1,170 @@ | |||
1 | /* linux/drivers/media/video/s5p-jpeg/jpeg-regs.h | ||
2 | * | ||
3 | * Register definition file for Samsung JPEG codec driver | ||
4 | * | ||
5 | * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||
6 | * http://www.samsung.com | ||
7 | * | ||
8 | * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> | ||
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 version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #ifndef JPEG_REGS_H_ | ||
16 | #define JPEG_REGS_H_ | ||
17 | |||
18 | /* JPEG mode register */ | ||
19 | #define S5P_JPGMOD 0x00 | ||
20 | #define S5P_PROC_MODE_MASK (0x1 << 3) | ||
21 | #define S5P_PROC_MODE_DECOMPR (0x1 << 3) | ||
22 | #define S5P_PROC_MODE_COMPR (0x0 << 3) | ||
23 | #define S5P_SUBSAMPLING_MODE_MASK 0x7 | ||
24 | #define S5P_SUBSAMPLING_MODE_444 (0x0 << 0) | ||
25 | #define S5P_SUBSAMPLING_MODE_422 (0x1 << 0) | ||
26 | #define S5P_SUBSAMPLING_MODE_420 (0x2 << 0) | ||
27 | #define S5P_SUBSAMPLING_MODE_GRAY (0x3 << 0) | ||
28 | |||
29 | /* JPEG operation status register */ | ||
30 | #define S5P_JPGOPR 0x04 | ||
31 | |||
32 | /* Quantization tables*/ | ||
33 | #define S5P_JPG_QTBL 0x08 | ||
34 | #define S5P_QT_NUMt_SHIFT(t) (((t) - 1) << 1) | ||
35 | #define S5P_QT_NUMt_MASK(t) (0x3 << S5P_QT_NUMt_SHIFT(t)) | ||
36 | |||
37 | /* Huffman tables */ | ||
38 | #define S5P_JPG_HTBL 0x0c | ||
39 | #define S5P_HT_NUMt_AC_SHIFT(t) (((t) << 1) - 1) | ||
40 | #define S5P_HT_NUMt_AC_MASK(t) (0x1 << S5P_HT_NUMt_AC_SHIFT(t)) | ||
41 | |||
42 | #define S5P_HT_NUMt_DC_SHIFT(t) (((t) - 1) << 1) | ||
43 | #define S5P_HT_NUMt_DC_MASK(t) (0x1 << S5P_HT_NUMt_DC_SHIFT(t)) | ||
44 | |||
45 | /* JPEG restart interval register upper byte */ | ||
46 | #define S5P_JPGDRI_U 0x10 | ||
47 | |||
48 | /* JPEG restart interval register lower byte */ | ||
49 | #define S5P_JPGDRI_L 0x14 | ||
50 | |||
51 | /* JPEG vertical resolution register upper byte */ | ||
52 | #define S5P_JPGY_U 0x18 | ||
53 | |||
54 | /* JPEG vertical resolution register lower byte */ | ||
55 | #define S5P_JPGY_L 0x1c | ||
56 | |||
57 | /* JPEG horizontal resolution register upper byte */ | ||
58 | #define S5P_JPGX_U 0x20 | ||
59 | |||
60 | /* JPEG horizontal resolution register lower byte */ | ||
61 | #define S5P_JPGX_L 0x24 | ||
62 | |||
63 | /* JPEG byte count register upper byte */ | ||
64 | #define S5P_JPGCNT_U 0x28 | ||
65 | |||
66 | /* JPEG byte count register middle byte */ | ||
67 | #define S5P_JPGCNT_M 0x2c | ||
68 | |||
69 | /* JPEG byte count register lower byte */ | ||
70 | #define S5P_JPGCNT_L 0x30 | ||
71 | |||
72 | /* JPEG interrupt setting register */ | ||
73 | #define S5P_JPGINTSE 0x34 | ||
74 | #define S5P_RSTm_INT_EN_MASK (0x1 << 7) | ||
75 | #define S5P_RSTm_INT_EN (0x1 << 7) | ||
76 | #define S5P_DATA_NUM_INT_EN_MASK (0x1 << 6) | ||
77 | #define S5P_DATA_NUM_INT_EN (0x1 << 6) | ||
78 | #define S5P_FINAL_MCU_NUM_INT_EN_MASK (0x1 << 5) | ||
79 | #define S5P_FINAL_MCU_NUM_INT_EN (0x1 << 5) | ||
80 | |||
81 | /* JPEG interrupt status register */ | ||
82 | #define S5P_JPGINTST 0x38 | ||
83 | #define S5P_RESULT_STAT_SHIFT 6 | ||
84 | #define S5P_RESULT_STAT_MASK (0x1 << S5P_RESULT_STAT_SHIFT) | ||
85 | #define S5P_STREAM_STAT_SHIFT 5 | ||
86 | #define S5P_STREAM_STAT_MASK (0x1 << S5P_STREAM_STAT_SHIFT) | ||
87 | |||
88 | /* JPEG command register */ | ||
89 | #define S5P_JPGCOM 0x4c | ||
90 | #define S5P_INT_RELEASE (0x1 << 2) | ||
91 | |||
92 | /* Raw image data r/w address register */ | ||
93 | #define S5P_JPG_IMGADR 0x50 | ||
94 | |||
95 | /* JPEG file r/w address register */ | ||
96 | #define S5P_JPG_JPGADR 0x58 | ||
97 | |||
98 | /* Coefficient for RGB-to-YCbCr converter register */ | ||
99 | #define S5P_JPG_COEF(n) (0x5c + (((n) - 1) << 2)) | ||
100 | #define S5P_COEFn_SHIFT(j) ((3 - (j)) << 3) | ||
101 | #define S5P_COEFn_MASK(j) (0xff << S5P_COEFn_SHIFT(j)) | ||
102 | |||
103 | /* JPEG color mode register */ | ||
104 | #define S5P_JPGCMOD 0x68 | ||
105 | #define S5P_MOD_SEL_MASK (0x7 << 5) | ||
106 | #define S5P_MOD_SEL_422 (0x1 << 5) | ||
107 | #define S5P_MOD_SEL_565 (0x2 << 5) | ||
108 | #define S5P_MODE_Y16_MASK (0x1 << 1) | ||
109 | #define S5P_MODE_Y16 (0x1 << 1) | ||
110 | |||
111 | /* JPEG clock control register */ | ||
112 | #define S5P_JPGCLKCON 0x6c | ||
113 | #define S5P_CLK_DOWN_READY (0x1 << 1) | ||
114 | #define S5P_POWER_ON (0x1 << 0) | ||
115 | |||
116 | /* JPEG start register */ | ||
117 | #define S5P_JSTART 0x70 | ||
118 | |||
119 | /* JPEG SW reset register */ | ||
120 | #define S5P_JPG_SW_RESET 0x78 | ||
121 | |||
122 | /* JPEG timer setting register */ | ||
123 | #define S5P_JPG_TIMER_SE 0x7c | ||
124 | #define S5P_TIMER_INT_EN_MASK (0x1 << 31) | ||
125 | #define S5P_TIMER_INT_EN (0x1 << 31) | ||
126 | #define S5P_TIMER_INIT_MASK 0x7fffffff | ||
127 | |||
128 | /* JPEG timer status register */ | ||
129 | #define S5P_JPG_TIMER_ST 0x80 | ||
130 | #define S5P_TIMER_INT_STAT_SHIFT 31 | ||
131 | #define S5P_TIMER_INT_STAT_MASK (0x1 << S5P_TIMER_INT_STAT_SHIFT) | ||
132 | #define S5P_TIMER_CNT_SHIFT 0 | ||
133 | #define S5P_TIMER_CNT_MASK 0x7fffffff | ||
134 | |||
135 | /* JPEG decompression output format register */ | ||
136 | #define S5P_JPG_OUTFORM 0x88 | ||
137 | #define S5P_DEC_OUT_FORMAT_MASK (0x1 << 0) | ||
138 | #define S5P_DEC_OUT_FORMAT_422 (0x0 << 0) | ||
139 | #define S5P_DEC_OUT_FORMAT_420 (0x1 << 0) | ||
140 | |||
141 | /* JPEG version register */ | ||
142 | #define S5P_JPG_VERSION 0x8c | ||
143 | |||
144 | /* JPEG compressed stream size interrupt setting register */ | ||
145 | #define S5P_JPG_ENC_STREAM_INTSE 0x98 | ||
146 | #define S5P_ENC_STREAM_INT_MASK (0x1 << 24) | ||
147 | #define S5P_ENC_STREAM_INT_EN (0x1 << 24) | ||
148 | #define S5P_ENC_STREAM_BOUND_MASK 0xffffff | ||
149 | |||
150 | /* JPEG compressed stream size interrupt status register */ | ||
151 | #define S5P_JPG_ENC_STREAM_INTST 0x9c | ||
152 | #define S5P_ENC_STREAM_INT_STAT_MASK 0x1 | ||
153 | |||
154 | /* JPEG quantizer table register */ | ||
155 | #define S5P_JPG_QTBL_CONTENT(n) (0x400 + (n) * 0x100) | ||
156 | |||
157 | /* JPEG DC Huffman table register */ | ||
158 | #define S5P_JPG_HDCTBL(n) (0x800 + (n) * 0x400) | ||
159 | |||
160 | /* JPEG DC Huffman table register */ | ||
161 | #define S5P_JPG_HDCTBLG(n) (0x840 + (n) * 0x400) | ||
162 | |||
163 | /* JPEG AC Huffman table register */ | ||
164 | #define S5P_JPG_HACTBL(n) (0x880 + (n) * 0x400) | ||
165 | |||
166 | /* JPEG AC Huffman table register */ | ||
167 | #define S5P_JPG_HACTBLG(n) (0x8c0 + (n) * 0x400) | ||
168 | |||
169 | #endif /* JPEG_REGS_H_ */ | ||
170 | |||
diff --git a/drivers/media/video/s5p-mfc/s5p_mfc.c b/drivers/media/video/s5p-mfc/s5p_mfc.c index 8be8b54eb749..e43e128baf5f 100644 --- a/drivers/media/video/s5p-mfc/s5p_mfc.c +++ b/drivers/media/video/s5p-mfc/s5p_mfc.c | |||
@@ -1245,27 +1245,7 @@ static struct platform_driver s5p_mfc_driver = { | |||
1245 | }, | 1245 | }, |
1246 | }; | 1246 | }; |
1247 | 1247 | ||
1248 | static char banner[] __initdata = | 1248 | module_platform_driver(s5p_mfc_driver); |
1249 | "S5P MFC V4L2 Driver, (C) 2011 Samsung Electronics\n"; | ||
1250 | |||
1251 | static int __init s5p_mfc_init(void) | ||
1252 | { | ||
1253 | int ret; | ||
1254 | |||
1255 | pr_info("%s", banner); | ||
1256 | ret = platform_driver_register(&s5p_mfc_driver); | ||
1257 | if (ret) | ||
1258 | pr_err("Platform device registration failed.\n"); | ||
1259 | return ret; | ||
1260 | } | ||
1261 | |||
1262 | static void __exit s5p_mfc_exit(void) | ||
1263 | { | ||
1264 | platform_driver_unregister(&s5p_mfc_driver); | ||
1265 | } | ||
1266 | |||
1267 | module_init(s5p_mfc_init); | ||
1268 | module_exit(s5p_mfc_exit); | ||
1269 | 1249 | ||
1270 | MODULE_LICENSE("GPL"); | 1250 | MODULE_LICENSE("GPL"); |
1271 | MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>"); | 1251 | MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>"); |
diff --git a/drivers/media/video/s5p-tv/hdmi_drv.c b/drivers/media/video/s5p-tv/hdmi_drv.c index 0279e6e89feb..8b41a0410ab1 100644 --- a/drivers/media/video/s5p-tv/hdmi_drv.c +++ b/drivers/media/video/s5p-tv/hdmi_drv.c | |||
@@ -838,8 +838,8 @@ static int hdmi_resources_init(struct hdmi_device *hdev) | |||
838 | dev_err(dev, "failed to get clock 'hdmiphy'\n"); | 838 | dev_err(dev, "failed to get clock 'hdmiphy'\n"); |
839 | goto fail; | 839 | goto fail; |
840 | } | 840 | } |
841 | res->regul_bulk = kzalloc(ARRAY_SIZE(supply) * | 841 | res->regul_bulk = kcalloc(ARRAY_SIZE(supply), |
842 | sizeof res->regul_bulk[0], GFP_KERNEL); | 842 | sizeof(res->regul_bulk[0]), GFP_KERNEL); |
843 | if (!res->regul_bulk) { | 843 | if (!res->regul_bulk) { |
844 | dev_err(dev, "failed to get memory for regulators\n"); | 844 | dev_err(dev, "failed to get memory for regulators\n"); |
845 | goto fail; | 845 | goto fail; |
@@ -1016,28 +1016,4 @@ static struct platform_driver hdmi_driver __refdata = { | |||
1016 | } | 1016 | } |
1017 | }; | 1017 | }; |
1018 | 1018 | ||
1019 | /* D R I V E R I N I T I A L I Z A T I O N */ | 1019 | module_platform_driver(hdmi_driver); |
1020 | |||
1021 | static int __init hdmi_init(void) | ||
1022 | { | ||
1023 | int ret; | ||
1024 | static const char banner[] __initdata = KERN_INFO \ | ||
1025 | "Samsung HDMI output driver, " | ||
1026 | "(c) 2010-2011 Samsung Electronics Co., Ltd.\n"; | ||
1027 | printk(banner); | ||
1028 | |||
1029 | ret = platform_driver_register(&hdmi_driver); | ||
1030 | if (ret) | ||
1031 | printk(KERN_ERR "HDMI platform driver register failed\n"); | ||
1032 | |||
1033 | return ret; | ||
1034 | } | ||
1035 | module_init(hdmi_init); | ||
1036 | |||
1037 | static void __exit hdmi_exit(void) | ||
1038 | { | ||
1039 | platform_driver_unregister(&hdmi_driver); | ||
1040 | } | ||
1041 | module_exit(hdmi_exit); | ||
1042 | |||
1043 | |||
diff --git a/drivers/media/video/s5p-tv/mixer.h b/drivers/media/video/s5p-tv/mixer.h index 51ad59b30358..1597078c4a50 100644 --- a/drivers/media/video/s5p-tv/mixer.h +++ b/drivers/media/video/s5p-tv/mixer.h | |||
@@ -86,6 +86,17 @@ struct mxr_crop { | |||
86 | unsigned int field; | 86 | unsigned int field; |
87 | }; | 87 | }; |
88 | 88 | ||
89 | /** stages of geometry operations */ | ||
90 | enum mxr_geometry_stage { | ||
91 | MXR_GEOMETRY_SINK, | ||
92 | MXR_GEOMETRY_COMPOSE, | ||
93 | MXR_GEOMETRY_CROP, | ||
94 | MXR_GEOMETRY_SOURCE, | ||
95 | }; | ||
96 | |||
97 | /* flag indicating that offset should be 0 */ | ||
98 | #define MXR_NO_OFFSET 0x80000000 | ||
99 | |||
89 | /** description of transformation from source to destination image */ | 100 | /** description of transformation from source to destination image */ |
90 | struct mxr_geometry { | 101 | struct mxr_geometry { |
91 | /** cropping for source image */ | 102 | /** cropping for source image */ |
@@ -133,7 +144,8 @@ struct mxr_layer_ops { | |||
133 | /** streaming stop/start */ | 144 | /** streaming stop/start */ |
134 | void (*stream_set)(struct mxr_layer *, int); | 145 | void (*stream_set)(struct mxr_layer *, int); |
135 | /** adjusting geometry */ | 146 | /** adjusting geometry */ |
136 | void (*fix_geometry)(struct mxr_layer *); | 147 | void (*fix_geometry)(struct mxr_layer *, |
148 | enum mxr_geometry_stage, unsigned long); | ||
137 | }; | 149 | }; |
138 | 150 | ||
139 | /** layer instance, a single window and content displayed on output */ | 151 | /** layer instance, a single window and content displayed on output */ |
diff --git a/drivers/media/video/s5p-tv/mixer_grp_layer.c b/drivers/media/video/s5p-tv/mixer_grp_layer.c index de8270c2b6e7..b93a21f5aa13 100644 --- a/drivers/media/video/s5p-tv/mixer_grp_layer.c +++ b/drivers/media/video/s5p-tv/mixer_grp_layer.c | |||
@@ -101,47 +101,132 @@ static void mxr_graph_format_set(struct mxr_layer *layer) | |||
101 | layer->fmt, &layer->geo); | 101 | layer->fmt, &layer->geo); |
102 | } | 102 | } |
103 | 103 | ||
104 | static void mxr_graph_fix_geometry(struct mxr_layer *layer) | 104 | static inline unsigned int closest(unsigned int x, unsigned int a, |
105 | unsigned int b, unsigned long flags) | ||
106 | { | ||
107 | unsigned int mid = (a + b) / 2; | ||
108 | |||
109 | /* choosing closest value with constraints according to table: | ||
110 | * -------------+-----+-----+-----+-------+ | ||
111 | * flags | 0 | LE | GE | LE|GE | | ||
112 | * -------------+-----+-----+-----+-------+ | ||
113 | * x <= a | a | a | a | a | | ||
114 | * a < x <= mid | a | a | b | a | | ||
115 | * mid < x < b | b | a | b | b | | ||
116 | * b <= x | b | b | b | b | | ||
117 | * -------------+-----+-----+-----+-------+ | ||
118 | */ | ||
119 | |||
120 | /* remove all non-constraint flags */ | ||
121 | flags &= V4L2_SEL_FLAG_LE | V4L2_SEL_FLAG_GE; | ||
122 | |||
123 | if (x <= a) | ||
124 | return a; | ||
125 | if (x >= b) | ||
126 | return b; | ||
127 | if (flags == V4L2_SEL_FLAG_LE) | ||
128 | return a; | ||
129 | if (flags == V4L2_SEL_FLAG_GE) | ||
130 | return b; | ||
131 | if (x <= mid) | ||
132 | return a; | ||
133 | return b; | ||
134 | } | ||
135 | |||
136 | static inline unsigned int do_center(unsigned int center, | ||
137 | unsigned int size, unsigned int upper, unsigned int flags) | ||
138 | { | ||
139 | unsigned int lower; | ||
140 | |||
141 | if (flags & MXR_NO_OFFSET) | ||
142 | return 0; | ||
143 | |||
144 | lower = center - min(center, size / 2); | ||
145 | return min(lower, upper - size); | ||
146 | } | ||
147 | |||
148 | static void mxr_graph_fix_geometry(struct mxr_layer *layer, | ||
149 | enum mxr_geometry_stage stage, unsigned long flags) | ||
105 | { | 150 | { |
106 | struct mxr_geometry *geo = &layer->geo; | 151 | struct mxr_geometry *geo = &layer->geo; |
152 | struct mxr_crop *src = &geo->src; | ||
153 | struct mxr_crop *dst = &geo->dst; | ||
154 | unsigned int x_center, y_center; | ||
107 | 155 | ||
108 | /* limit to boundary size */ | 156 | switch (stage) { |
109 | geo->src.full_width = clamp_val(geo->src.full_width, 1, 32767); | ||
110 | geo->src.full_height = clamp_val(geo->src.full_height, 1, 2047); | ||
111 | geo->src.width = clamp_val(geo->src.width, 1, geo->src.full_width); | ||
112 | geo->src.width = min(geo->src.width, 2047U); | ||
113 | /* not possible to crop of Y axis */ | ||
114 | geo->src.y_offset = min(geo->src.y_offset, geo->src.full_height - 1); | ||
115 | geo->src.height = geo->src.full_height - geo->src.y_offset; | ||
116 | /* limitting offset */ | ||
117 | geo->src.x_offset = min(geo->src.x_offset, | ||
118 | geo->src.full_width - geo->src.width); | ||
119 | |||
120 | /* setting position in output */ | ||
121 | geo->dst.width = min(geo->dst.width, geo->dst.full_width); | ||
122 | geo->dst.height = min(geo->dst.height, geo->dst.full_height); | ||
123 | |||
124 | /* Mixer supports only 1x and 2x scaling */ | ||
125 | if (geo->dst.width >= 2 * geo->src.width) { | ||
126 | geo->x_ratio = 1; | ||
127 | geo->dst.width = 2 * geo->src.width; | ||
128 | } else { | ||
129 | geo->x_ratio = 0; | ||
130 | geo->dst.width = geo->src.width; | ||
131 | } | ||
132 | 157 | ||
133 | if (geo->dst.height >= 2 * geo->src.height) { | 158 | case MXR_GEOMETRY_SINK: /* nothing to be fixed here */ |
134 | geo->y_ratio = 1; | 159 | flags = 0; |
135 | geo->dst.height = 2 * geo->src.height; | 160 | /* fall through */ |
136 | } else { | 161 | |
137 | geo->y_ratio = 0; | 162 | case MXR_GEOMETRY_COMPOSE: |
138 | geo->dst.height = geo->src.height; | 163 | /* remember center of the area */ |
139 | } | 164 | x_center = dst->x_offset + dst->width / 2; |
165 | y_center = dst->y_offset + dst->height / 2; | ||
166 | /* round up/down to 2 multiple depending on flags */ | ||
167 | if (flags & V4L2_SEL_FLAG_LE) { | ||
168 | dst->width = round_down(dst->width, 2); | ||
169 | dst->height = round_down(dst->height, 2); | ||
170 | } else { | ||
171 | dst->width = round_up(dst->width, 2); | ||
172 | dst->height = round_up(dst->height, 2); | ||
173 | } | ||
174 | /* assure that compose rect is inside display area */ | ||
175 | dst->width = min(dst->width, dst->full_width); | ||
176 | dst->height = min(dst->height, dst->full_height); | ||
177 | |||
178 | /* ensure that compose is reachable using 2x scaling */ | ||
179 | dst->width = min(dst->width, 2 * src->full_width); | ||
180 | dst->height = min(dst->height, 2 * src->full_height); | ||
181 | |||
182 | /* setup offsets */ | ||
183 | dst->x_offset = do_center(x_center, dst->width, | ||
184 | dst->full_width, flags); | ||
185 | dst->y_offset = do_center(y_center, dst->height, | ||
186 | dst->full_height, flags); | ||
187 | flags = 0; | ||
188 | /* fall through */ | ||
140 | 189 | ||
141 | geo->dst.x_offset = min(geo->dst.x_offset, | 190 | case MXR_GEOMETRY_CROP: |
142 | geo->dst.full_width - geo->dst.width); | 191 | /* remember center of the area */ |
143 | geo->dst.y_offset = min(geo->dst.y_offset, | 192 | x_center = src->x_offset + src->width / 2; |
144 | geo->dst.full_height - geo->dst.height); | 193 | y_center = src->y_offset + src->height / 2; |
194 | /* ensure that cropping area lies inside the buffer */ | ||
195 | if (src->full_width < dst->width) | ||
196 | src->width = dst->width / 2; | ||
197 | else | ||
198 | src->width = closest(src->width, dst->width / 2, | ||
199 | dst->width, flags); | ||
200 | |||
201 | if (src->width == dst->width) | ||
202 | geo->x_ratio = 0; | ||
203 | else | ||
204 | geo->x_ratio = 1; | ||
205 | |||
206 | if (src->full_height < dst->height) | ||
207 | src->height = dst->height / 2; | ||
208 | else | ||
209 | src->height = closest(src->height, dst->height / 2, | ||
210 | dst->height, flags); | ||
211 | |||
212 | if (src->height == dst->height) | ||
213 | geo->y_ratio = 0; | ||
214 | else | ||
215 | geo->y_ratio = 1; | ||
216 | |||
217 | /* setup offsets */ | ||
218 | src->x_offset = do_center(x_center, src->width, | ||
219 | src->full_width, flags); | ||
220 | src->y_offset = do_center(y_center, src->height, | ||
221 | src->full_height, flags); | ||
222 | flags = 0; | ||
223 | /* fall through */ | ||
224 | case MXR_GEOMETRY_SOURCE: | ||
225 | src->full_width = clamp_val(src->full_width, | ||
226 | src->width + src->x_offset, 32767); | ||
227 | src->full_height = clamp_val(src->full_height, | ||
228 | src->height + src->y_offset, 2047); | ||
229 | }; | ||
145 | } | 230 | } |
146 | 231 | ||
147 | /* PUBLIC API */ | 232 | /* PUBLIC API */ |
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c index b47d0c06ecf5..7884baeff76a 100644 --- a/drivers/media/video/s5p-tv/mixer_video.c +++ b/drivers/media/video/s5p-tv/mixer_video.c | |||
@@ -170,18 +170,22 @@ static int mxr_querycap(struct file *file, void *priv, | |||
170 | return 0; | 170 | return 0; |
171 | } | 171 | } |
172 | 172 | ||
173 | /* Geometry handling */ | 173 | static void mxr_geometry_dump(struct mxr_device *mdev, struct mxr_geometry *geo) |
174 | static void mxr_layer_geo_fix(struct mxr_layer *layer) | ||
175 | { | 174 | { |
176 | struct mxr_device *mdev = layer->mdev; | 175 | mxr_dbg(mdev, "src.full_size = (%u, %u)\n", |
177 | struct v4l2_mbus_framefmt mbus_fmt; | 176 | geo->src.full_width, geo->src.full_height); |
178 | 177 | mxr_dbg(mdev, "src.size = (%u, %u)\n", | |
179 | /* TODO: add some dirty flag to avoid unnecessary adjustments */ | 178 | geo->src.width, geo->src.height); |
180 | mxr_get_mbus_fmt(mdev, &mbus_fmt); | 179 | mxr_dbg(mdev, "src.offset = (%u, %u)\n", |
181 | layer->geo.dst.full_width = mbus_fmt.width; | 180 | geo->src.x_offset, geo->src.y_offset); |
182 | layer->geo.dst.full_height = mbus_fmt.height; | 181 | mxr_dbg(mdev, "dst.full_size = (%u, %u)\n", |
183 | layer->geo.dst.field = mbus_fmt.field; | 182 | geo->dst.full_width, geo->dst.full_height); |
184 | layer->ops.fix_geometry(layer); | 183 | mxr_dbg(mdev, "dst.size = (%u, %u)\n", |
184 | geo->dst.width, geo->dst.height); | ||
185 | mxr_dbg(mdev, "dst.offset = (%u, %u)\n", | ||
186 | geo->dst.x_offset, geo->dst.y_offset); | ||
187 | mxr_dbg(mdev, "ratio = (%u, %u)\n", | ||
188 | geo->x_ratio, geo->y_ratio); | ||
185 | } | 189 | } |
186 | 190 | ||
187 | static void mxr_layer_default_geo(struct mxr_layer *layer) | 191 | static void mxr_layer_default_geo(struct mxr_layer *layer) |
@@ -204,27 +208,29 @@ static void mxr_layer_default_geo(struct mxr_layer *layer) | |||
204 | layer->geo.src.width = layer->geo.src.full_width; | 208 | layer->geo.src.width = layer->geo.src.full_width; |
205 | layer->geo.src.height = layer->geo.src.full_height; | 209 | layer->geo.src.height = layer->geo.src.full_height; |
206 | 210 | ||
207 | layer->ops.fix_geometry(layer); | 211 | mxr_geometry_dump(mdev, &layer->geo); |
212 | layer->ops.fix_geometry(layer, MXR_GEOMETRY_SINK, 0); | ||
213 | mxr_geometry_dump(mdev, &layer->geo); | ||
208 | } | 214 | } |
209 | 215 | ||
210 | static void mxr_geometry_dump(struct mxr_device *mdev, struct mxr_geometry *geo) | 216 | static void mxr_layer_update_output(struct mxr_layer *layer) |
211 | { | 217 | { |
212 | mxr_dbg(mdev, "src.full_size = (%u, %u)\n", | 218 | struct mxr_device *mdev = layer->mdev; |
213 | geo->src.full_width, geo->src.full_height); | 219 | struct v4l2_mbus_framefmt mbus_fmt; |
214 | mxr_dbg(mdev, "src.size = (%u, %u)\n", | 220 | |
215 | geo->src.width, geo->src.height); | 221 | mxr_get_mbus_fmt(mdev, &mbus_fmt); |
216 | mxr_dbg(mdev, "src.offset = (%u, %u)\n", | 222 | /* checking if update is needed */ |
217 | geo->src.x_offset, geo->src.y_offset); | 223 | if (layer->geo.dst.full_width == mbus_fmt.width && |
218 | mxr_dbg(mdev, "dst.full_size = (%u, %u)\n", | 224 | layer->geo.dst.full_height == mbus_fmt.width) |
219 | geo->dst.full_width, geo->dst.full_height); | 225 | return; |
220 | mxr_dbg(mdev, "dst.size = (%u, %u)\n", | ||
221 | geo->dst.width, geo->dst.height); | ||
222 | mxr_dbg(mdev, "dst.offset = (%u, %u)\n", | ||
223 | geo->dst.x_offset, geo->dst.y_offset); | ||
224 | mxr_dbg(mdev, "ratio = (%u, %u)\n", | ||
225 | geo->x_ratio, geo->y_ratio); | ||
226 | } | ||
227 | 226 | ||
227 | layer->geo.dst.full_width = mbus_fmt.width; | ||
228 | layer->geo.dst.full_height = mbus_fmt.height; | ||
229 | layer->geo.dst.field = mbus_fmt.field; | ||
230 | layer->ops.fix_geometry(layer, MXR_GEOMETRY_SINK, 0); | ||
231 | |||
232 | mxr_geometry_dump(mdev, &layer->geo); | ||
233 | } | ||
228 | 234 | ||
229 | static const struct mxr_format *find_format_by_fourcc( | 235 | static const struct mxr_format *find_format_by_fourcc( |
230 | struct mxr_layer *layer, unsigned long fourcc); | 236 | struct mxr_layer *layer, unsigned long fourcc); |
@@ -249,37 +255,6 @@ static int mxr_enum_fmt(struct file *file, void *priv, | |||
249 | return 0; | 255 | return 0; |
250 | } | 256 | } |
251 | 257 | ||
252 | static int mxr_s_fmt(struct file *file, void *priv, | ||
253 | struct v4l2_format *f) | ||
254 | { | ||
255 | struct mxr_layer *layer = video_drvdata(file); | ||
256 | const struct mxr_format *fmt; | ||
257 | struct v4l2_pix_format_mplane *pix; | ||
258 | struct mxr_device *mdev = layer->mdev; | ||
259 | struct mxr_geometry *geo = &layer->geo; | ||
260 | |||
261 | mxr_dbg(mdev, "%s:%d\n", __func__, __LINE__); | ||
262 | |||
263 | pix = &f->fmt.pix_mp; | ||
264 | fmt = find_format_by_fourcc(layer, pix->pixelformat); | ||
265 | if (fmt == NULL) { | ||
266 | mxr_warn(mdev, "not recognized fourcc: %08x\n", | ||
267 | pix->pixelformat); | ||
268 | return -EINVAL; | ||
269 | } | ||
270 | layer->fmt = fmt; | ||
271 | geo->src.full_width = pix->width; | ||
272 | geo->src.width = pix->width; | ||
273 | geo->src.full_height = pix->height; | ||
274 | geo->src.height = pix->height; | ||
275 | /* assure consistency of geometry */ | ||
276 | mxr_layer_geo_fix(layer); | ||
277 | mxr_dbg(mdev, "width=%u height=%u span=%u\n", | ||
278 | geo->src.width, geo->src.height, geo->src.full_width); | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static unsigned int divup(unsigned int divident, unsigned int divisor) | 258 | static unsigned int divup(unsigned int divident, unsigned int divisor) |
284 | { | 259 | { |
285 | return (divident + divisor - 1) / divisor; | 260 | return (divident + divisor - 1) / divisor; |
@@ -299,6 +274,10 @@ static void mxr_mplane_fill(struct v4l2_plane_pix_format *planes, | |||
299 | { | 274 | { |
300 | int i; | 275 | int i; |
301 | 276 | ||
277 | /* checking if nothing to fill */ | ||
278 | if (!planes) | ||
279 | return; | ||
280 | |||
302 | memset(planes, 0, sizeof(*planes) * fmt->num_subframes); | 281 | memset(planes, 0, sizeof(*planes) * fmt->num_subframes); |
303 | for (i = 0; i < fmt->num_planes; ++i) { | 282 | for (i = 0; i < fmt->num_planes; ++i) { |
304 | struct v4l2_plane_pix_format *plane = planes | 283 | struct v4l2_plane_pix_format *plane = planes |
@@ -332,73 +311,194 @@ static int mxr_g_fmt(struct file *file, void *priv, | |||
332 | return 0; | 311 | return 0; |
333 | } | 312 | } |
334 | 313 | ||
335 | static inline struct mxr_crop *choose_crop_by_type(struct mxr_geometry *geo, | 314 | static int mxr_s_fmt(struct file *file, void *priv, |
336 | enum v4l2_buf_type type) | 315 | struct v4l2_format *f) |
337 | { | ||
338 | switch (type) { | ||
339 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
340 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: | ||
341 | return &geo->dst; | ||
342 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
343 | return &geo->src; | ||
344 | default: | ||
345 | return NULL; | ||
346 | } | ||
347 | } | ||
348 | |||
349 | static int mxr_g_crop(struct file *file, void *fh, struct v4l2_crop *a) | ||
350 | { | 316 | { |
351 | struct mxr_layer *layer = video_drvdata(file); | 317 | struct mxr_layer *layer = video_drvdata(file); |
352 | struct mxr_crop *crop; | 318 | const struct mxr_format *fmt; |
319 | struct v4l2_pix_format_mplane *pix; | ||
320 | struct mxr_device *mdev = layer->mdev; | ||
321 | struct mxr_geometry *geo = &layer->geo; | ||
353 | 322 | ||
354 | mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); | 323 | mxr_dbg(mdev, "%s:%d\n", __func__, __LINE__); |
355 | crop = choose_crop_by_type(&layer->geo, a->type); | 324 | |
356 | if (crop == NULL) | 325 | pix = &f->fmt.pix_mp; |
326 | fmt = find_format_by_fourcc(layer, pix->pixelformat); | ||
327 | if (fmt == NULL) { | ||
328 | mxr_warn(mdev, "not recognized fourcc: %08x\n", | ||
329 | pix->pixelformat); | ||
357 | return -EINVAL; | 330 | return -EINVAL; |
358 | mxr_layer_geo_fix(layer); | 331 | } |
359 | a->c.left = crop->x_offset; | 332 | layer->fmt = fmt; |
360 | a->c.top = crop->y_offset; | 333 | /* set source size to highest accepted value */ |
361 | a->c.width = crop->width; | 334 | geo->src.full_width = max(geo->dst.full_width, pix->width); |
362 | a->c.height = crop->height; | 335 | geo->src.full_height = max(geo->dst.full_height, pix->height); |
336 | layer->ops.fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0); | ||
337 | mxr_geometry_dump(mdev, &layer->geo); | ||
338 | /* set cropping to total visible screen */ | ||
339 | geo->src.width = pix->width; | ||
340 | geo->src.height = pix->height; | ||
341 | geo->src.x_offset = 0; | ||
342 | geo->src.y_offset = 0; | ||
343 | /* assure consistency of geometry */ | ||
344 | layer->ops.fix_geometry(layer, MXR_GEOMETRY_CROP, MXR_NO_OFFSET); | ||
345 | mxr_geometry_dump(mdev, &layer->geo); | ||
346 | /* set full size to lowest possible value */ | ||
347 | geo->src.full_width = 0; | ||
348 | geo->src.full_height = 0; | ||
349 | layer->ops.fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0); | ||
350 | mxr_geometry_dump(mdev, &layer->geo); | ||
351 | |||
352 | /* returning results */ | ||
353 | mxr_g_fmt(file, priv, f); | ||
354 | |||
363 | return 0; | 355 | return 0; |
364 | } | 356 | } |
365 | 357 | ||
366 | static int mxr_s_crop(struct file *file, void *fh, struct v4l2_crop *a) | 358 | static int mxr_g_selection(struct file *file, void *fh, |
359 | struct v4l2_selection *s) | ||
367 | { | 360 | { |
368 | struct mxr_layer *layer = video_drvdata(file); | 361 | struct mxr_layer *layer = video_drvdata(file); |
369 | struct mxr_crop *crop; | 362 | struct mxr_geometry *geo = &layer->geo; |
370 | 363 | ||
371 | mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); | 364 | mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); |
372 | crop = choose_crop_by_type(&layer->geo, a->type); | 365 | |
373 | if (crop == NULL) | 366 | if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && |
367 | s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) | ||
368 | return -EINVAL; | ||
369 | |||
370 | switch (s->target) { | ||
371 | case V4L2_SEL_TGT_CROP_ACTIVE: | ||
372 | s->r.left = geo->src.x_offset; | ||
373 | s->r.top = geo->src.y_offset; | ||
374 | s->r.width = geo->src.width; | ||
375 | s->r.height = geo->src.height; | ||
376 | break; | ||
377 | case V4L2_SEL_TGT_CROP_DEFAULT: | ||
378 | case V4L2_SEL_TGT_CROP_BOUNDS: | ||
379 | s->r.left = 0; | ||
380 | s->r.top = 0; | ||
381 | s->r.width = geo->src.full_width; | ||
382 | s->r.height = geo->src.full_height; | ||
383 | break; | ||
384 | case V4L2_SEL_TGT_COMPOSE_ACTIVE: | ||
385 | case V4L2_SEL_TGT_COMPOSE_PADDED: | ||
386 | s->r.left = geo->dst.x_offset; | ||
387 | s->r.top = geo->dst.y_offset; | ||
388 | s->r.width = geo->dst.width; | ||
389 | s->r.height = geo->dst.height; | ||
390 | break; | ||
391 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: | ||
392 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: | ||
393 | s->r.left = 0; | ||
394 | s->r.top = 0; | ||
395 | s->r.width = geo->dst.full_width; | ||
396 | s->r.height = geo->dst.full_height; | ||
397 | break; | ||
398 | default: | ||
374 | return -EINVAL; | 399 | return -EINVAL; |
375 | crop->x_offset = a->c.left; | 400 | } |
376 | crop->y_offset = a->c.top; | 401 | |
377 | crop->width = a->c.width; | ||
378 | crop->height = a->c.height; | ||
379 | mxr_layer_geo_fix(layer); | ||
380 | return 0; | 402 | return 0; |
381 | } | 403 | } |
382 | 404 | ||
383 | static int mxr_cropcap(struct file *file, void *fh, struct v4l2_cropcap *a) | 405 | /* returns 1 if rectangle 'a' is inside 'b' */ |
406 | static int mxr_is_rect_inside(struct v4l2_rect *a, struct v4l2_rect *b) | ||
407 | { | ||
408 | if (a->left < b->left) | ||
409 | return 0; | ||
410 | if (a->top < b->top) | ||
411 | return 0; | ||
412 | if (a->left + a->width > b->left + b->width) | ||
413 | return 0; | ||
414 | if (a->top + a->height > b->top + b->height) | ||
415 | return 0; | ||
416 | return 1; | ||
417 | } | ||
418 | |||
419 | static int mxr_s_selection(struct file *file, void *fh, | ||
420 | struct v4l2_selection *s) | ||
384 | { | 421 | { |
385 | struct mxr_layer *layer = video_drvdata(file); | 422 | struct mxr_layer *layer = video_drvdata(file); |
386 | struct mxr_crop *crop; | 423 | struct mxr_geometry *geo = &layer->geo; |
424 | struct mxr_crop *target = NULL; | ||
425 | enum mxr_geometry_stage stage; | ||
426 | struct mxr_geometry tmp; | ||
427 | struct v4l2_rect res; | ||
387 | 428 | ||
388 | mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); | 429 | memset(&res, 0, sizeof res); |
389 | crop = choose_crop_by_type(&layer->geo, a->type); | 430 | |
390 | if (crop == NULL) | 431 | mxr_dbg(layer->mdev, "%s: rect: %dx%d@%d,%d\n", __func__, |
432 | s->r.width, s->r.height, s->r.left, s->r.top); | ||
433 | |||
434 | if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && | ||
435 | s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) | ||
391 | return -EINVAL; | 436 | return -EINVAL; |
392 | mxr_layer_geo_fix(layer); | 437 | |
393 | a->bounds.left = 0; | 438 | switch (s->target) { |
394 | a->bounds.top = 0; | 439 | /* ignore read-only targets */ |
395 | a->bounds.width = crop->full_width; | 440 | case V4L2_SEL_TGT_CROP_DEFAULT: |
396 | a->bounds.top = crop->full_height; | 441 | case V4L2_SEL_TGT_CROP_BOUNDS: |
397 | a->defrect = a->bounds; | 442 | res.width = geo->src.full_width; |
398 | /* setting pixel aspect to 1/1 */ | 443 | res.height = geo->src.full_height; |
399 | a->pixelaspect.numerator = 1; | 444 | break; |
400 | a->pixelaspect.denominator = 1; | 445 | |
446 | /* ignore read-only targets */ | ||
447 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: | ||
448 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: | ||
449 | res.width = geo->dst.full_width; | ||
450 | res.height = geo->dst.full_height; | ||
451 | break; | ||
452 | |||
453 | case V4L2_SEL_TGT_CROP_ACTIVE: | ||
454 | target = &geo->src; | ||
455 | stage = MXR_GEOMETRY_CROP; | ||
456 | break; | ||
457 | case V4L2_SEL_TGT_COMPOSE_ACTIVE: | ||
458 | case V4L2_SEL_TGT_COMPOSE_PADDED: | ||
459 | target = &geo->dst; | ||
460 | stage = MXR_GEOMETRY_COMPOSE; | ||
461 | break; | ||
462 | default: | ||
463 | return -EINVAL; | ||
464 | } | ||
465 | /* apply change and update geometry if needed */ | ||
466 | if (target) { | ||
467 | /* backup current geometry if setup fails */ | ||
468 | memcpy(&tmp, geo, sizeof tmp); | ||
469 | |||
470 | /* apply requested selection */ | ||
471 | target->x_offset = s->r.left; | ||
472 | target->y_offset = s->r.top; | ||
473 | target->width = s->r.width; | ||
474 | target->height = s->r.height; | ||
475 | |||
476 | layer->ops.fix_geometry(layer, stage, s->flags); | ||
477 | |||
478 | /* retrieve update selection rectangle */ | ||
479 | res.left = target->x_offset; | ||
480 | res.top = target->y_offset; | ||
481 | res.width = target->width; | ||
482 | res.height = target->height; | ||
483 | |||
484 | mxr_geometry_dump(layer->mdev, &layer->geo); | ||
485 | } | ||
486 | |||
487 | /* checking if the rectangle satisfies constraints */ | ||
488 | if ((s->flags & V4L2_SEL_FLAG_LE) && !mxr_is_rect_inside(&res, &s->r)) | ||
489 | goto fail; | ||
490 | if ((s->flags & V4L2_SEL_FLAG_GE) && !mxr_is_rect_inside(&s->r, &res)) | ||
491 | goto fail; | ||
492 | |||
493 | /* return result rectangle */ | ||
494 | s->r = res; | ||
495 | |||
401 | return 0; | 496 | return 0; |
497 | fail: | ||
498 | /* restore old geometry, which is not touched if target is NULL */ | ||
499 | if (target) | ||
500 | memcpy(geo, &tmp, sizeof tmp); | ||
501 | return -ERANGE; | ||
402 | } | 502 | } |
403 | 503 | ||
404 | static int mxr_enum_dv_presets(struct file *file, void *fh, | 504 | static int mxr_enum_dv_presets(struct file *file, void *fh, |
@@ -438,6 +538,8 @@ static int mxr_s_dv_preset(struct file *file, void *fh, | |||
438 | 538 | ||
439 | mutex_unlock(&mdev->mutex); | 539 | mutex_unlock(&mdev->mutex); |
440 | 540 | ||
541 | mxr_layer_update_output(layer); | ||
542 | |||
441 | /* any failure should return EINVAL according to V4L2 doc */ | 543 | /* any failure should return EINVAL according to V4L2 doc */ |
442 | return ret ? -EINVAL : 0; | 544 | return ret ? -EINVAL : 0; |
443 | } | 545 | } |
@@ -478,6 +580,8 @@ static int mxr_s_std(struct file *file, void *fh, v4l2_std_id *norm) | |||
478 | 580 | ||
479 | mutex_unlock(&mdev->mutex); | 581 | mutex_unlock(&mdev->mutex); |
480 | 582 | ||
583 | mxr_layer_update_output(layer); | ||
584 | |||
481 | return ret ? -EINVAL : 0; | 585 | return ret ? -EINVAL : 0; |
482 | } | 586 | } |
483 | 587 | ||
@@ -526,25 +630,27 @@ static int mxr_s_output(struct file *file, void *fh, unsigned int i) | |||
526 | struct video_device *vfd = video_devdata(file); | 630 | struct video_device *vfd = video_devdata(file); |
527 | struct mxr_layer *layer = video_drvdata(file); | 631 | struct mxr_layer *layer = video_drvdata(file); |
528 | struct mxr_device *mdev = layer->mdev; | 632 | struct mxr_device *mdev = layer->mdev; |
529 | int ret = 0; | ||
530 | 633 | ||
531 | if (i >= mdev->output_cnt || mdev->output[i] == NULL) | 634 | if (i >= mdev->output_cnt || mdev->output[i] == NULL) |
532 | return -EINVAL; | 635 | return -EINVAL; |
533 | 636 | ||
534 | mutex_lock(&mdev->mutex); | 637 | mutex_lock(&mdev->mutex); |
535 | if (mdev->n_output > 0) { | 638 | if (mdev->n_output > 0) { |
536 | ret = -EBUSY; | 639 | mutex_unlock(&mdev->mutex); |
537 | goto done; | 640 | return -EBUSY; |
538 | } | 641 | } |
539 | mdev->current_output = i; | 642 | mdev->current_output = i; |
540 | vfd->tvnorms = 0; | 643 | vfd->tvnorms = 0; |
541 | v4l2_subdev_call(to_outsd(mdev), video, g_tvnorms_output, | 644 | v4l2_subdev_call(to_outsd(mdev), video, g_tvnorms_output, |
542 | &vfd->tvnorms); | 645 | &vfd->tvnorms); |
646 | mutex_unlock(&mdev->mutex); | ||
647 | |||
648 | /* update layers geometry */ | ||
649 | mxr_layer_update_output(layer); | ||
650 | |||
543 | mxr_dbg(mdev, "tvnorms = %08llx\n", vfd->tvnorms); | 651 | mxr_dbg(mdev, "tvnorms = %08llx\n", vfd->tvnorms); |
544 | 652 | ||
545 | done: | 653 | return 0; |
546 | mutex_unlock(&mdev->mutex); | ||
547 | return ret; | ||
548 | } | 654 | } |
549 | 655 | ||
550 | static int mxr_g_output(struct file *file, void *fh, unsigned int *p) | 656 | static int mxr_g_output(struct file *file, void *fh, unsigned int *p) |
@@ -633,10 +739,9 @@ static const struct v4l2_ioctl_ops mxr_ioctl_ops = { | |||
633 | .vidioc_enum_output = mxr_enum_output, | 739 | .vidioc_enum_output = mxr_enum_output, |
634 | .vidioc_s_output = mxr_s_output, | 740 | .vidioc_s_output = mxr_s_output, |
635 | .vidioc_g_output = mxr_g_output, | 741 | .vidioc_g_output = mxr_g_output, |
636 | /* Crop ioctls */ | 742 | /* selection ioctls */ |
637 | .vidioc_g_crop = mxr_g_crop, | 743 | .vidioc_g_selection = mxr_g_selection, |
638 | .vidioc_s_crop = mxr_s_crop, | 744 | .vidioc_s_selection = mxr_s_selection, |
639 | .vidioc_cropcap = mxr_cropcap, | ||
640 | }; | 745 | }; |
641 | 746 | ||
642 | static int mxr_video_open(struct file *file) | 747 | static int mxr_video_open(struct file *file) |
@@ -805,10 +910,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) | |||
805 | /* block any changes in output configuration */ | 910 | /* block any changes in output configuration */ |
806 | mxr_output_get(mdev); | 911 | mxr_output_get(mdev); |
807 | 912 | ||
808 | /* update layers geometry */ | 913 | mxr_layer_update_output(layer); |
809 | mxr_layer_geo_fix(layer); | ||
810 | mxr_geometry_dump(mdev, &layer->geo); | ||
811 | |||
812 | layer->ops.format_set(layer); | 914 | layer->ops.format_set(layer); |
813 | /* enabling layer in hardware */ | 915 | /* enabling layer in hardware */ |
814 | spin_lock_irqsave(&layer->enq_slock, flags); | 916 | spin_lock_irqsave(&layer->enq_slock, flags); |
diff --git a/drivers/media/video/s5p-tv/mixer_vp_layer.c b/drivers/media/video/s5p-tv/mixer_vp_layer.c index f3bb2e34cb51..3d13a636877b 100644 --- a/drivers/media/video/s5p-tv/mixer_vp_layer.c +++ b/drivers/media/video/s5p-tv/mixer_vp_layer.c | |||
@@ -127,47 +127,77 @@ static void mxr_vp_format_set(struct mxr_layer *layer) | |||
127 | mxr_reg_vp_format(layer->mdev, layer->fmt, &layer->geo); | 127 | mxr_reg_vp_format(layer->mdev, layer->fmt, &layer->geo); |
128 | } | 128 | } |
129 | 129 | ||
130 | static void mxr_vp_fix_geometry(struct mxr_layer *layer) | 130 | static inline unsigned int do_center(unsigned int center, |
131 | unsigned int size, unsigned int upper, unsigned int flags) | ||
131 | { | 132 | { |
132 | struct mxr_geometry *geo = &layer->geo; | 133 | unsigned int lower; |
134 | |||
135 | if (flags & MXR_NO_OFFSET) | ||
136 | return 0; | ||
137 | |||
138 | lower = center - min(center, size / 2); | ||
139 | return min(lower, upper - size); | ||
140 | } | ||
133 | 141 | ||
134 | /* align horizontal size to 8 pixels */ | 142 | static void mxr_vp_fix_geometry(struct mxr_layer *layer, |
135 | geo->src.full_width = ALIGN(geo->src.full_width, 8); | 143 | enum mxr_geometry_stage stage, unsigned long flags) |
136 | /* limit to boundary size */ | 144 | { |
137 | geo->src.full_width = clamp_val(geo->src.full_width, 8, 8192); | 145 | struct mxr_geometry *geo = &layer->geo; |
138 | geo->src.full_height = clamp_val(geo->src.full_height, 1, 8192); | 146 | struct mxr_crop *src = &geo->src; |
139 | geo->src.width = clamp_val(geo->src.width, 32, geo->src.full_width); | 147 | struct mxr_crop *dst = &geo->dst; |
140 | geo->src.width = min(geo->src.width, 2047U); | 148 | unsigned long x_center, y_center; |
141 | geo->src.height = clamp_val(geo->src.height, 4, geo->src.full_height); | 149 | |
142 | geo->src.height = min(geo->src.height, 2047U); | 150 | switch (stage) { |
143 | 151 | ||
144 | /* setting size of output window */ | 152 | case MXR_GEOMETRY_SINK: /* nothing to be fixed here */ |
145 | geo->dst.width = clamp_val(geo->dst.width, 8, geo->dst.full_width); | 153 | case MXR_GEOMETRY_COMPOSE: |
146 | geo->dst.height = clamp_val(geo->dst.height, 1, geo->dst.full_height); | 154 | /* remember center of the area */ |
147 | 155 | x_center = dst->x_offset + dst->width / 2; | |
148 | /* ensure that scaling is in range 1/4x to 16x */ | 156 | y_center = dst->y_offset + dst->height / 2; |
149 | if (geo->src.width >= 4 * geo->dst.width) | 157 | |
150 | geo->src.width = 4 * geo->dst.width; | 158 | /* ensure that compose is reachable using 16x scaling */ |
151 | if (geo->dst.width >= 16 * geo->src.width) | 159 | dst->width = clamp(dst->width, 8U, 16 * src->full_width); |
152 | geo->dst.width = 16 * geo->src.width; | 160 | dst->height = clamp(dst->height, 1U, 16 * src->full_height); |
153 | if (geo->src.height >= 4 * geo->dst.height) | 161 | |
154 | geo->src.height = 4 * geo->dst.height; | 162 | /* setup offsets */ |
155 | if (geo->dst.height >= 16 * geo->src.height) | 163 | dst->x_offset = do_center(x_center, dst->width, |
156 | geo->dst.height = 16 * geo->src.height; | 164 | dst->full_width, flags); |
157 | 165 | dst->y_offset = do_center(y_center, dst->height, | |
158 | /* setting scaling ratio */ | 166 | dst->full_height, flags); |
159 | geo->x_ratio = (geo->src.width << 16) / geo->dst.width; | 167 | flags = 0; /* remove possible MXR_NO_OFFSET flag */ |
160 | geo->y_ratio = (geo->src.height << 16) / geo->dst.height; | 168 | /* fall through */ |
161 | 169 | case MXR_GEOMETRY_CROP: | |
162 | /* adjust offsets */ | 170 | /* remember center of the area */ |
163 | geo->src.x_offset = min(geo->src.x_offset, | 171 | x_center = src->x_offset + src->width / 2; |
164 | geo->src.full_width - geo->src.width); | 172 | y_center = src->y_offset + src->height / 2; |
165 | geo->src.y_offset = min(geo->src.y_offset, | 173 | |
166 | geo->src.full_height - geo->src.height); | 174 | /* ensure scaling is between 0.25x .. 16x */ |
167 | geo->dst.x_offset = min(geo->dst.x_offset, | 175 | src->width = clamp(src->width, round_up(dst->width / 16, 4), |
168 | geo->dst.full_width - geo->dst.width); | 176 | dst->width * 4); |
169 | geo->dst.y_offset = min(geo->dst.y_offset, | 177 | src->height = clamp(src->height, round_up(dst->height / 16, 4), |
170 | geo->dst.full_height - geo->dst.height); | 178 | dst->height * 4); |
179 | |||
180 | /* hardware limits */ | ||
181 | src->width = clamp(src->width, 32U, 2047U); | ||
182 | src->height = clamp(src->height, 4U, 2047U); | ||
183 | |||
184 | /* setup offsets */ | ||
185 | src->x_offset = do_center(x_center, src->width, | ||
186 | src->full_width, flags); | ||
187 | src->y_offset = do_center(y_center, src->height, | ||
188 | src->full_height, flags); | ||
189 | |||
190 | /* setting scaling ratio */ | ||
191 | geo->x_ratio = (src->width << 16) / dst->width; | ||
192 | geo->y_ratio = (src->height << 16) / dst->height; | ||
193 | /* fall through */ | ||
194 | |||
195 | case MXR_GEOMETRY_SOURCE: | ||
196 | src->full_width = clamp(src->full_width, | ||
197 | ALIGN(src->width + src->x_offset, 8), 8192U); | ||
198 | src->full_height = clamp(src->full_height, | ||
199 | src->height + src->y_offset, 8192U); | ||
200 | }; | ||
171 | } | 201 | } |
172 | 202 | ||
173 | /* PUBLIC API */ | 203 | /* PUBLIC API */ |
diff --git a/drivers/media/video/s5p-tv/sdo_drv.c b/drivers/media/video/s5p-tv/sdo_drv.c index 8cec67ef48c9..059e7749ce95 100644 --- a/drivers/media/video/s5p-tv/sdo_drv.c +++ b/drivers/media/video/s5p-tv/sdo_drv.c | |||
@@ -457,24 +457,4 @@ static struct platform_driver sdo_driver __refdata = { | |||
457 | } | 457 | } |
458 | }; | 458 | }; |
459 | 459 | ||
460 | static int __init sdo_init(void) | 460 | module_platform_driver(sdo_driver); |
461 | { | ||
462 | int ret; | ||
463 | static const char banner[] __initdata = KERN_INFO \ | ||
464 | "Samsung Standard Definition Output (SDO) driver, " | ||
465 | "(c) 2010-2011 Samsung Electronics Co., Ltd.\n"; | ||
466 | printk(banner); | ||
467 | |||
468 | ret = platform_driver_register(&sdo_driver); | ||
469 | if (ret) | ||
470 | printk(KERN_ERR "SDO platform driver register failed\n"); | ||
471 | |||
472 | return ret; | ||
473 | } | ||
474 | module_init(sdo_init); | ||
475 | |||
476 | static void __exit sdo_exit(void) | ||
477 | { | ||
478 | platform_driver_unregister(&sdo_driver); | ||
479 | } | ||
480 | module_exit(sdo_exit); | ||
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 0f9fb99adeb4..065d0f6be4a0 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -5691,6 +5691,27 @@ struct saa7134_board saa7134_boards[] = { | |||
5691 | .amux = LINE1, | 5691 | .amux = LINE1, |
5692 | }, | 5692 | }, |
5693 | }, | 5693 | }, |
5694 | [SAA7134_BOARD_SENSORAY811_911] = { | ||
5695 | .name = "Sensoray 811/911", | ||
5696 | .audio_clock = 0x00200000, | ||
5697 | .tuner_type = TUNER_ABSENT, | ||
5698 | .radio_type = UNSET, | ||
5699 | .tuner_addr = ADDR_UNSET, | ||
5700 | .radio_addr = ADDR_UNSET, | ||
5701 | .inputs = {{ | ||
5702 | .name = name_comp1, | ||
5703 | .vmux = 0, | ||
5704 | .amux = LINE1, | ||
5705 | }, { | ||
5706 | .name = name_comp3, | ||
5707 | .vmux = 2, | ||
5708 | .amux = LINE1, | ||
5709 | }, { | ||
5710 | .name = name_svideo, | ||
5711 | .vmux = 8, | ||
5712 | .amux = LINE1, | ||
5713 | } }, | ||
5714 | }, | ||
5694 | 5715 | ||
5695 | }; | 5716 | }; |
5696 | 5717 | ||
@@ -6914,6 +6935,18 @@ struct pci_device_id saa7134_pci_tbl[] = { | |||
6914 | .subdevice = 0xd136, | 6935 | .subdevice = 0xd136, |
6915 | .driver_data = SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2, | 6936 | .driver_data = SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2, |
6916 | }, { | 6937 | }, { |
6938 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
6939 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
6940 | .subvendor = 0x6000, | ||
6941 | .subdevice = 0x0811, | ||
6942 | .driver_data = SAA7134_BOARD_SENSORAY811_911, | ||
6943 | }, { | ||
6944 | .vendor = PCI_VENDOR_ID_PHILIPS, | ||
6945 | .device = PCI_DEVICE_ID_PHILIPS_SAA7133, | ||
6946 | .subvendor = 0x6000, | ||
6947 | .subdevice = 0x0911, | ||
6948 | .driver_data = SAA7134_BOARD_SENSORAY811_911, | ||
6949 | }, { | ||
6917 | /* --- boards without eeprom + subsystem ID --- */ | 6950 | /* --- boards without eeprom + subsystem ID --- */ |
6918 | .vendor = PCI_VENDOR_ID_PHILIPS, | 6951 | .vendor = PCI_VENDOR_ID_PHILIPS, |
6919 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, | 6952 | .device = PCI_DEVICE_ID_PHILIPS_SAA7134, |
diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index ca65cda3e101..5fbb4e49495c 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c | |||
@@ -1263,7 +1263,6 @@ static int saa7134_resume(struct pci_dev *pci_dev) | |||
1263 | saa7134_tvaudio_setmute(dev); | 1263 | saa7134_tvaudio_setmute(dev); |
1264 | saa7134_tvaudio_setvolume(dev, dev->ctl_volume); | 1264 | saa7134_tvaudio_setvolume(dev, dev->ctl_volume); |
1265 | saa7134_tvaudio_init(dev); | 1265 | saa7134_tvaudio_init(dev); |
1266 | saa7134_tvaudio_do_scan(dev); | ||
1267 | saa7134_enable_i2s(dev); | 1266 | saa7134_enable_i2s(dev); |
1268 | saa7134_hw_enable2(dev); | 1267 | saa7134_hw_enable2(dev); |
1269 | 1268 | ||
diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 1e4ef1669887..089fa0fb5c94 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c | |||
@@ -183,9 +183,9 @@ static int mt352_avermedia_xc3028_init(struct dvb_frontend *fe) | |||
183 | return 0; | 183 | return 0; |
184 | } | 184 | } |
185 | 185 | ||
186 | static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe, | 186 | static int mt352_pinnacle_tuner_set_params(struct dvb_frontend *fe) |
187 | struct dvb_frontend_parameters* params) | ||
188 | { | 187 | { |
188 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
189 | u8 off[] = { 0x00, 0xf1}; | 189 | u8 off[] = { 0x00, 0xf1}; |
190 | u8 on[] = { 0x00, 0x71}; | 190 | u8 on[] = { 0x00, 0x71}; |
191 | struct i2c_msg msg = {.addr=0x43, .flags=0, .buf=off, .len = sizeof(off)}; | 191 | struct i2c_msg msg = {.addr=0x43, .flags=0, .buf=off, .len = sizeof(off)}; |
@@ -196,7 +196,7 @@ static int mt352_pinnacle_tuner_set_params(struct dvb_frontend* fe, | |||
196 | /* set frequency (mt2050) */ | 196 | /* set frequency (mt2050) */ |
197 | f.tuner = 0; | 197 | f.tuner = 0; |
198 | f.type = V4L2_TUNER_DIGITAL_TV; | 198 | f.type = V4L2_TUNER_DIGITAL_TV; |
199 | f.frequency = params->frequency / 1000 * 16 / 1000; | 199 | f.frequency = c->frequency / 1000 * 16 / 1000; |
200 | if (fe->ops.i2c_gate_ctrl) | 200 | if (fe->ops.i2c_gate_ctrl) |
201 | fe->ops.i2c_gate_ctrl(fe, 1); | 201 | fe->ops.i2c_gate_ctrl(fe, 1); |
202 | i2c_transfer(&dev->i2c_adap, &msg, 1); | 202 | i2c_transfer(&dev->i2c_adap, &msg, 1); |
@@ -287,8 +287,9 @@ static int philips_tda1004x_request_firmware(struct dvb_frontend *fe, | |||
287 | * these tuners are tu1216, td1316(a) | 287 | * these tuners are tu1216, td1316(a) |
288 | */ | 288 | */ |
289 | 289 | ||
290 | static int philips_tda6651_pll_set(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 290 | static int philips_tda6651_pll_set(struct dvb_frontend *fe) |
291 | { | 291 | { |
292 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
292 | struct saa7134_dev *dev = fe->dvb->priv; | 293 | struct saa7134_dev *dev = fe->dvb->priv; |
293 | struct tda1004x_state *state = fe->demodulator_priv; | 294 | struct tda1004x_state *state = fe->demodulator_priv; |
294 | u8 addr = state->config->tuner_address; | 295 | u8 addr = state->config->tuner_address; |
@@ -299,7 +300,7 @@ static int philips_tda6651_pll_set(struct dvb_frontend *fe, struct dvb_frontend_ | |||
299 | u8 band, cp, filter; | 300 | u8 band, cp, filter; |
300 | 301 | ||
301 | /* determine charge pump */ | 302 | /* determine charge pump */ |
302 | tuner_frequency = params->frequency + 36166000; | 303 | tuner_frequency = c->frequency + 36166000; |
303 | if (tuner_frequency < 87000000) | 304 | if (tuner_frequency < 87000000) |
304 | return -EINVAL; | 305 | return -EINVAL; |
305 | else if (tuner_frequency < 130000000) | 306 | else if (tuner_frequency < 130000000) |
@@ -324,28 +325,28 @@ static int philips_tda6651_pll_set(struct dvb_frontend *fe, struct dvb_frontend_ | |||
324 | return -EINVAL; | 325 | return -EINVAL; |
325 | 326 | ||
326 | /* determine band */ | 327 | /* determine band */ |
327 | if (params->frequency < 49000000) | 328 | if (c->frequency < 49000000) |
328 | return -EINVAL; | 329 | return -EINVAL; |
329 | else if (params->frequency < 161000000) | 330 | else if (c->frequency < 161000000) |
330 | band = 1; | 331 | band = 1; |
331 | else if (params->frequency < 444000000) | 332 | else if (c->frequency < 444000000) |
332 | band = 2; | 333 | band = 2; |
333 | else if (params->frequency < 861000000) | 334 | else if (c->frequency < 861000000) |
334 | band = 4; | 335 | band = 4; |
335 | else | 336 | else |
336 | return -EINVAL; | 337 | return -EINVAL; |
337 | 338 | ||
338 | /* setup PLL filter */ | 339 | /* setup PLL filter */ |
339 | switch (params->u.ofdm.bandwidth) { | 340 | switch (c->bandwidth_hz) { |
340 | case BANDWIDTH_6_MHZ: | 341 | case 6000000: |
341 | filter = 0; | 342 | filter = 0; |
342 | break; | 343 | break; |
343 | 344 | ||
344 | case BANDWIDTH_7_MHZ: | 345 | case 7000000: |
345 | filter = 0; | 346 | filter = 0; |
346 | break; | 347 | break; |
347 | 348 | ||
348 | case BANDWIDTH_8_MHZ: | 349 | case 8000000: |
349 | filter = 1; | 350 | filter = 1; |
350 | break; | 351 | break; |
351 | 352 | ||
@@ -356,7 +357,7 @@ static int philips_tda6651_pll_set(struct dvb_frontend *fe, struct dvb_frontend_ | |||
356 | /* calculate divisor | 357 | /* calculate divisor |
357 | * ((36166000+((1000000/6)/2)) + Finput)/(1000000/6) | 358 | * ((36166000+((1000000/6)/2)) + Finput)/(1000000/6) |
358 | */ | 359 | */ |
359 | tuner_frequency = (((params->frequency / 1000) * 6) + 217496) / 1000; | 360 | tuner_frequency = (((c->frequency / 1000) * 6) + 217496) / 1000; |
360 | 361 | ||
361 | /* setup tuner buffer */ | 362 | /* setup tuner buffer */ |
362 | tuner_buf[0] = (tuner_frequency >> 8) & 0x7f; | 363 | tuner_buf[0] = (tuner_frequency >> 8) & 0x7f; |
@@ -436,9 +437,9 @@ static int philips_td1316_tuner_init(struct dvb_frontend *fe) | |||
436 | return 0; | 437 | return 0; |
437 | } | 438 | } |
438 | 439 | ||
439 | static int philips_td1316_tuner_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) | 440 | static int philips_td1316_tuner_set_params(struct dvb_frontend *fe) |
440 | { | 441 | { |
441 | return philips_tda6651_pll_set(fe, params); | 442 | return philips_tda6651_pll_set(fe); |
442 | } | 443 | } |
443 | 444 | ||
444 | static int philips_td1316_tuner_sleep(struct dvb_frontend *fe) | 445 | static int philips_td1316_tuner_sleep(struct dvb_frontend *fe) |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index d4ee24bf6928..22ecd7297d2d 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -235,22 +235,25 @@ static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | |||
235 | 235 | ||
236 | static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | 236 | static int get_key_hvr1110(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) |
237 | { | 237 | { |
238 | unsigned char buf[5], cod4, code3, code4; | 238 | unsigned char buf[5]; |
239 | 239 | ||
240 | /* poll IR chip */ | 240 | /* poll IR chip */ |
241 | if (5 != i2c_master_recv(ir->c, buf, 5)) | 241 | if (5 != i2c_master_recv(ir->c, buf, 5)) |
242 | return -EIO; | 242 | return -EIO; |
243 | 243 | ||
244 | cod4 = buf[4]; | 244 | /* Check if some key were pressed */ |
245 | code4 = (cod4 >> 2); | 245 | if (!(buf[0] & 0x80)) |
246 | code3 = buf[3]; | ||
247 | if (code3 == 0) | ||
248 | /* no key pressed */ | ||
249 | return 0; | 246 | return 0; |
250 | 247 | ||
251 | /* return key */ | 248 | /* |
252 | *ir_key = code4; | 249 | * buf[3] & 0x80 is always high. |
253 | *ir_raw = code4; | 250 | * buf[3] & 0x40 is a parity bit. A repeat event is marked |
251 | * by preserving it into two separate readings | ||
252 | * buf[4] bits 0 and 1, and buf[1] and buf[2] are always | ||
253 | * zero. | ||
254 | */ | ||
255 | *ir_key = 0x1fff & ((buf[3] << 8) | (buf[4] >> 2)); | ||
256 | *ir_raw = *ir_key; | ||
254 | return 1; | 257 | return 1; |
255 | } | 258 | } |
256 | 259 | ||
@@ -752,7 +755,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) | |||
752 | polling = 50; /* ms */ | 755 | polling = 50; /* ms */ |
753 | break; | 756 | break; |
754 | case SAA7134_BOARD_VIDEOMATE_M1F: | 757 | case SAA7134_BOARD_VIDEOMATE_M1F: |
755 | ir_codes = RC_MAP_VIDEOMATE_M1F; | 758 | ir_codes = RC_MAP_VIDEOMATE_K100; |
756 | mask_keycode = 0x0ff00; | 759 | mask_keycode = 0x0ff00; |
757 | mask_keyup = 0x040000; | 760 | mask_keyup = 0x040000; |
758 | break; | 761 | break; |
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index 57e646bb48b3..b7a99bee2f98 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c | |||
@@ -332,6 +332,13 @@ static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan) | |||
332 | { | 332 | { |
333 | __s32 left,right,value; | 333 | __s32 left,right,value; |
334 | 334 | ||
335 | if (!(dev->tvnorm->id & scan->std)) { | ||
336 | value = 0; | ||
337 | dprintk("skipping %d.%03d MHz [%4s]\n", | ||
338 | scan->carr / 1000, scan->carr % 1000, scan->name); | ||
339 | return 0; | ||
340 | } | ||
341 | |||
335 | if (audio_debug > 1) { | 342 | if (audio_debug > 1) { |
336 | int i; | 343 | int i; |
337 | dprintk("debug %d:",scan->carr); | 344 | dprintk("debug %d:",scan->carr); |
@@ -348,30 +355,25 @@ static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan) | |||
348 | } | 355 | } |
349 | printk("\n"); | 356 | printk("\n"); |
350 | } | 357 | } |
351 | if (dev->tvnorm->id & scan->std) { | 358 | |
352 | tvaudio_setcarrier(dev,scan->carr-90,scan->carr-90); | 359 | tvaudio_setcarrier(dev,scan->carr-90,scan->carr-90); |
353 | saa_readl(SAA7134_LEVEL_READOUT1 >> 2); | 360 | saa_readl(SAA7134_LEVEL_READOUT1 >> 2); |
354 | if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY)) | 361 | if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY)) |
355 | return -1; | 362 | return -1; |
356 | left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2); | 363 | left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2); |
357 | 364 | ||
358 | tvaudio_setcarrier(dev,scan->carr+90,scan->carr+90); | 365 | tvaudio_setcarrier(dev,scan->carr+90,scan->carr+90); |
359 | saa_readl(SAA7134_LEVEL_READOUT1 >> 2); | 366 | saa_readl(SAA7134_LEVEL_READOUT1 >> 2); |
360 | if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY)) | 367 | if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY)) |
361 | return -1; | 368 | return -1; |
362 | right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2); | 369 | right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2); |
363 | 370 | ||
364 | left >>= 16; | 371 | left >>= 16; |
365 | right >>= 16; | 372 | right >>= 16; |
366 | value = left > right ? left - right : right - left; | 373 | value = left > right ? left - right : right - left; |
367 | dprintk("scanning %d.%03d MHz [%4s] => dc is %5d [%d/%d]\n", | 374 | dprintk("scanning %d.%03d MHz [%4s] => dc is %5d [%d/%d]\n", |
368 | scan->carr / 1000, scan->carr % 1000, | 375 | scan->carr / 1000, scan->carr % 1000, |
369 | scan->name, value, left, right); | 376 | scan->name, value, left, right); |
370 | } else { | ||
371 | value = 0; | ||
372 | dprintk("skipping %d.%03d MHz [%4s]\n", | ||
373 | scan->carr / 1000, scan->carr % 1000, scan->name); | ||
374 | } | ||
375 | return value; | 377 | return value; |
376 | } | 378 | } |
377 | 379 | ||
@@ -546,6 +548,7 @@ static int tvaudio_thread(void *data) | |||
546 | dev->tvnorm->name, carrier/1000, carrier%1000, | 548 | dev->tvnorm->name, carrier/1000, carrier%1000, |
547 | max1, max2); | 549 | max1, max2); |
548 | dev->last_carrier = carrier; | 550 | dev->last_carrier = carrier; |
551 | dev->automute = 0; | ||
549 | 552 | ||
550 | } else if (0 != dev->last_carrier) { | 553 | } else if (0 != dev->last_carrier) { |
551 | /* no carrier -- try last detected one as fallback */ | 554 | /* no carrier -- try last detected one as fallback */ |
@@ -553,6 +556,7 @@ static int tvaudio_thread(void *data) | |||
553 | dprintk("audio carrier scan failed, " | 556 | dprintk("audio carrier scan failed, " |
554 | "using %d.%03d MHz [last detected]\n", | 557 | "using %d.%03d MHz [last detected]\n", |
555 | carrier/1000, carrier%1000); | 558 | carrier/1000, carrier%1000); |
559 | dev->automute = 1; | ||
556 | 560 | ||
557 | } else { | 561 | } else { |
558 | /* no carrier + no fallback -- use default */ | 562 | /* no carrier + no fallback -- use default */ |
@@ -560,9 +564,9 @@ static int tvaudio_thread(void *data) | |||
560 | dprintk("audio carrier scan failed, " | 564 | dprintk("audio carrier scan failed, " |
561 | "using %d.%03d MHz [default]\n", | 565 | "using %d.%03d MHz [default]\n", |
562 | carrier/1000, carrier%1000); | 566 | carrier/1000, carrier%1000); |
567 | dev->automute = 1; | ||
563 | } | 568 | } |
564 | tvaudio_setcarrier(dev,carrier,carrier); | 569 | tvaudio_setcarrier(dev,carrier,carrier); |
565 | dev->automute = 0; | ||
566 | saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x00); | 570 | saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x00); |
567 | saa7134_tvaudio_setmute(dev); | 571 | saa7134_tvaudio_setmute(dev); |
568 | /* find the exact tv audio norm */ | 572 | /* find the exact tv audio norm */ |
@@ -601,7 +605,7 @@ static int tvaudio_thread(void *data) | |||
601 | if (kthread_should_stop()) | 605 | if (kthread_should_stop()) |
602 | break; | 606 | break; |
603 | if (UNSET == dev->thread.mode) { | 607 | if (UNSET == dev->thread.mode) { |
604 | rx = tvaudio_getstereo(dev,&tvaudio[i]); | 608 | rx = tvaudio_getstereo(dev, &tvaudio[audio]); |
605 | mode = saa7134_tvaudio_rx2mode(rx); | 609 | mode = saa7134_tvaudio_rx2mode(rx); |
606 | } else { | 610 | } else { |
607 | mode = dev->thread.mode; | 611 | mode = dev->thread.mode; |
@@ -1020,6 +1024,7 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev) | |||
1020 | } | 1024 | } |
1021 | 1025 | ||
1022 | dev->thread.thread = NULL; | 1026 | dev->thread.thread = NULL; |
1027 | dev->thread.scan1 = dev->thread.scan2 = 0; | ||
1023 | if (my_thread) { | 1028 | if (my_thread) { |
1024 | saa7134_tvaudio_init(dev); | 1029 | saa7134_tvaudio_init(dev); |
1025 | /* start tvaudio thread */ | 1030 | /* start tvaudio thread */ |
@@ -1029,13 +1034,19 @@ int saa7134_tvaudio_init2(struct saa7134_dev *dev) | |||
1029 | dev->name); | 1034 | dev->name); |
1030 | /* XXX: missing error handling here */ | 1035 | /* XXX: missing error handling here */ |
1031 | } | 1036 | } |
1032 | saa7134_tvaudio_do_scan(dev); | ||
1033 | } | 1037 | } |
1034 | 1038 | ||
1035 | saa7134_enable_i2s(dev); | 1039 | saa7134_enable_i2s(dev); |
1036 | return 0; | 1040 | return 0; |
1037 | } | 1041 | } |
1038 | 1042 | ||
1043 | int saa7134_tvaudio_close(struct saa7134_dev *dev) | ||
1044 | { | ||
1045 | dev->automute = 1; | ||
1046 | /* anything else to undo? */ | ||
1047 | return 0; | ||
1048 | } | ||
1049 | |||
1039 | int saa7134_tvaudio_fini(struct saa7134_dev *dev) | 1050 | int saa7134_tvaudio_fini(struct saa7134_dev *dev) |
1040 | { | 1051 | { |
1041 | /* shutdown tvaudio thread */ | 1052 | /* shutdown tvaudio thread */ |
diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 9cf7914f6f90..417034eb6ad2 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c | |||
@@ -1462,6 +1462,8 @@ static int video_release(struct file *file) | |||
1462 | struct saa6588_command cmd; | 1462 | struct saa6588_command cmd; |
1463 | unsigned long flags; | 1463 | unsigned long flags; |
1464 | 1464 | ||
1465 | saa7134_tvaudio_close(dev); | ||
1466 | |||
1465 | /* turn off overlay */ | 1467 | /* turn off overlay */ |
1466 | if (res_check(fh, RESOURCE_OVERLAY)) { | 1468 | if (res_check(fh, RESOURCE_OVERLAY)) { |
1467 | spin_lock_irqsave(&dev->slock,flags); | 1469 | spin_lock_irqsave(&dev->slock,flags); |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 9b550687213a..42fba4f93c72 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -330,6 +330,7 @@ struct saa7134_card_ir { | |||
330 | #define SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2 185 | 330 | #define SAA7134_BOARD_MAGICPRO_PROHDTV_PRO2 185 |
331 | #define SAA7134_BOARD_BEHOLD_501 186 | 331 | #define SAA7134_BOARD_BEHOLD_501 186 |
332 | #define SAA7134_BOARD_BEHOLD_503FM 187 | 332 | #define SAA7134_BOARD_BEHOLD_503FM 187 |
333 | #define SAA7134_BOARD_SENSORAY811_911 188 | ||
333 | 334 | ||
334 | #define SAA7134_MAXBOARDS 32 | 335 | #define SAA7134_MAXBOARDS 32 |
335 | #define SAA7134_INPUT_MAX 8 | 336 | #define SAA7134_INPUT_MAX 8 |
@@ -817,6 +818,7 @@ void saa7134_tvaudio_init(struct saa7134_dev *dev); | |||
817 | int saa7134_tvaudio_init2(struct saa7134_dev *dev); | 818 | int saa7134_tvaudio_init2(struct saa7134_dev *dev); |
818 | int saa7134_tvaudio_fini(struct saa7134_dev *dev); | 819 | int saa7134_tvaudio_fini(struct saa7134_dev *dev); |
819 | int saa7134_tvaudio_do_scan(struct saa7134_dev *dev); | 820 | int saa7134_tvaudio_do_scan(struct saa7134_dev *dev); |
821 | int saa7134_tvaudio_close(struct saa7134_dev *dev); | ||
820 | 822 | ||
821 | int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value); | 823 | int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value); |
822 | 824 | ||
diff --git a/drivers/media/video/saa7164/saa7164-bus.c b/drivers/media/video/saa7164/saa7164-bus.c index 466e1b02f91f..a7f58a998752 100644 --- a/drivers/media/video/saa7164/saa7164-bus.c +++ b/drivers/media/video/saa7164/saa7164-bus.c | |||
@@ -149,7 +149,7 @@ int saa7164_bus_set(struct saa7164_dev *dev, struct tmComResInfo* msg, | |||
149 | saa7164_bus_verify(dev); | 149 | saa7164_bus_verify(dev); |
150 | 150 | ||
151 | msg->size = cpu_to_le16(msg->size); | 151 | msg->size = cpu_to_le16(msg->size); |
152 | msg->command = cpu_to_le16(msg->command); | 152 | msg->command = cpu_to_le32(msg->command); |
153 | msg->controlselector = cpu_to_le16(msg->controlselector); | 153 | msg->controlselector = cpu_to_le16(msg->controlselector); |
154 | 154 | ||
155 | if (msg->size > dev->bus.m_wMaxReqSize) { | 155 | if (msg->size > dev->bus.m_wMaxReqSize) { |
@@ -464,7 +464,7 @@ int saa7164_bus_get(struct saa7164_dev *dev, struct tmComResInfo* msg, | |||
464 | 464 | ||
465 | peekout: | 465 | peekout: |
466 | msg->size = le16_to_cpu(msg->size); | 466 | msg->size = le16_to_cpu(msg->size); |
467 | msg->command = le16_to_cpu(msg->command); | 467 | msg->command = le32_to_cpu(msg->command); |
468 | msg->controlselector = le16_to_cpu(msg->controlselector); | 468 | msg->controlselector = le16_to_cpu(msg->controlselector); |
469 | ret = SAA_OK; | 469 | ret = SAA_OK; |
470 | out: | 470 | out: |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index c51decfcae19..f854d85a387c 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
@@ -786,8 +786,7 @@ static struct v4l2_subdev *find_bus_subdev(struct sh_mobile_ceu_dev *pcdev, | |||
786 | V4L2_MBUS_DATA_ACTIVE_HIGH) | 786 | V4L2_MBUS_DATA_ACTIVE_HIGH) |
787 | 787 | ||
788 | /* Capture is not running, no interrupts, no locking needed */ | 788 | /* Capture is not running, no interrupts, no locking needed */ |
789 | static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, | 789 | static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd) |
790 | __u32 pixfmt) | ||
791 | { | 790 | { |
792 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); | 791 | struct soc_camera_host *ici = to_soc_camera_host(icd->parent); |
793 | struct sh_mobile_ceu_dev *pcdev = ici->priv; | 792 | struct sh_mobile_ceu_dev *pcdev = ici->priv; |
@@ -925,11 +924,6 @@ static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd, | |||
925 | ceu_write(pcdev, CDOCR, value); | 924 | ceu_write(pcdev, CDOCR, value); |
926 | ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */ | 925 | ceu_write(pcdev, CFWCR, 0); /* keep "datafetch firewall" disabled */ |
927 | 926 | ||
928 | dev_dbg(icd->parent, "S_FMT successful for %c%c%c%c %ux%u\n", | ||
929 | pixfmt & 0xff, (pixfmt >> 8) & 0xff, | ||
930 | (pixfmt >> 16) & 0xff, (pixfmt >> 24) & 0xff, | ||
931 | icd->user_width, icd->user_height); | ||
932 | |||
933 | capture_restore(pcdev, capsr); | 927 | capture_restore(pcdev, capsr); |
934 | 928 | ||
935 | /* not in bundle mode: skip CBDSR, CDAYR2, CDACR2, CDBYR2, CDBCR2 */ | 929 | /* not in bundle mode: skip CBDSR, CDAYR2, CDACR2, CDBYR2, CDBCR2 */ |
@@ -1966,8 +1960,7 @@ static int sh_mobile_ceu_set_livecrop(struct soc_camera_device *icd, | |||
1966 | if (!ret) { | 1960 | if (!ret) { |
1967 | icd->user_width = out_width & ~3; | 1961 | icd->user_width = out_width & ~3; |
1968 | icd->user_height = out_height & ~3; | 1962 | icd->user_height = out_height & ~3; |
1969 | ret = sh_mobile_ceu_set_bus_param(icd, | 1963 | ret = sh_mobile_ceu_set_bus_param(icd); |
1970 | icd->current_fmt->host_fmt->fourcc); | ||
1971 | } | 1964 | } |
1972 | } | 1965 | } |
1973 | 1966 | ||
diff --git a/drivers/media/video/sh_mobile_csi2.c b/drivers/media/video/sh_mobile_csi2.c index 8a652b53ff7e..05286500b4d4 100644 --- a/drivers/media/video/sh_mobile_csi2.c +++ b/drivers/media/video/sh_mobile_csi2.c | |||
@@ -390,18 +390,7 @@ static struct platform_driver __refdata sh_csi2_pdrv = { | |||
390 | }, | 390 | }, |
391 | }; | 391 | }; |
392 | 392 | ||
393 | static int __init sh_csi2_init(void) | 393 | module_platform_driver(sh_csi2_pdrv); |
394 | { | ||
395 | return platform_driver_register(&sh_csi2_pdrv); | ||
396 | } | ||
397 | |||
398 | static void __exit sh_csi2_exit(void) | ||
399 | { | ||
400 | platform_driver_unregister(&sh_csi2_pdrv); | ||
401 | } | ||
402 | |||
403 | module_init(sh_csi2_init); | ||
404 | module_exit(sh_csi2_exit); | ||
405 | 394 | ||
406 | MODULE_DESCRIPTION("SH-Mobile MIPI CSI-2 driver"); | 395 | MODULE_DESCRIPTION("SH-Mobile MIPI CSI-2 driver"); |
407 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | 396 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); |
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index 62e4312515cb..b82710745ba8 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -487,7 +487,7 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd, | |||
487 | icd->user_width, icd->user_height); | 487 | icd->user_width, icd->user_height); |
488 | 488 | ||
489 | /* set physical bus parameters */ | 489 | /* set physical bus parameters */ |
490 | return ici->ops->set_bus_param(icd, pix->pixelformat); | 490 | return ici->ops->set_bus_param(icd); |
491 | } | 491 | } |
492 | 492 | ||
493 | static int soc_camera_open(struct file *file) | 493 | static int soc_camera_open(struct file *file) |
@@ -600,9 +600,9 @@ static int soc_camera_close(struct file *file) | |||
600 | pm_runtime_suspend(&icd->vdev->dev); | 600 | pm_runtime_suspend(&icd->vdev->dev); |
601 | pm_runtime_disable(&icd->vdev->dev); | 601 | pm_runtime_disable(&icd->vdev->dev); |
602 | 602 | ||
603 | ici->ops->remove(icd); | ||
604 | if (ici->ops->init_videobuf2) | 603 | if (ici->ops->init_videobuf2) |
605 | vb2_queue_release(&icd->vb2_vidq); | 604 | vb2_queue_release(&icd->vb2_vidq); |
605 | ici->ops->remove(icd); | ||
606 | 606 | ||
607 | soc_camera_power_off(icd, icl); | 607 | soc_camera_power_off(icd, icl); |
608 | } | 608 | } |
diff --git a/drivers/media/video/soc_camera_platform.c b/drivers/media/video/soc_camera_platform.c index 4402a8a74f7a..f59ccade07c8 100644 --- a/drivers/media/video/soc_camera_platform.c +++ b/drivers/media/video/soc_camera_platform.c | |||
@@ -189,18 +189,7 @@ static struct platform_driver soc_camera_platform_driver = { | |||
189 | .remove = soc_camera_platform_remove, | 189 | .remove = soc_camera_platform_remove, |
190 | }; | 190 | }; |
191 | 191 | ||
192 | static int __init soc_camera_platform_module_init(void) | 192 | module_platform_driver(soc_camera_platform_driver); |
193 | { | ||
194 | return platform_driver_register(&soc_camera_platform_driver); | ||
195 | } | ||
196 | |||
197 | static void __exit soc_camera_platform_module_exit(void) | ||
198 | { | ||
199 | platform_driver_unregister(&soc_camera_platform_driver); | ||
200 | } | ||
201 | |||
202 | module_init(soc_camera_platform_module_init); | ||
203 | module_exit(soc_camera_platform_module_exit); | ||
204 | 193 | ||
205 | MODULE_DESCRIPTION("SoC Camera Platform driver"); | 194 | MODULE_DESCRIPTION("SoC Camera Platform driver"); |
206 | MODULE_AUTHOR("Magnus Damm"); | 195 | MODULE_AUTHOR("Magnus Damm"); |
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index 3c61aec517ac..d427f8436c70 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c | |||
@@ -377,8 +377,8 @@ static int stk_prepare_iso(struct stk_camera *dev) | |||
377 | if (dev->isobufs) | 377 | if (dev->isobufs) |
378 | STK_ERROR("isobufs already allocated. Bad\n"); | 378 | STK_ERROR("isobufs already allocated. Bad\n"); |
379 | else | 379 | else |
380 | dev->isobufs = kzalloc(MAX_ISO_BUFS * sizeof(*dev->isobufs), | 380 | dev->isobufs = kcalloc(MAX_ISO_BUFS, sizeof(*dev->isobufs), |
381 | GFP_KERNEL); | 381 | GFP_KERNEL); |
382 | if (dev->isobufs == NULL) { | 382 | if (dev->isobufs == NULL) { |
383 | STK_ERROR("Unable to allocate iso buffers\n"); | 383 | STK_ERROR("Unable to allocate iso buffers\n"); |
384 | return -ENOMEM; | 384 | return -ENOMEM; |
diff --git a/drivers/media/video/timblogiw.c b/drivers/media/video/timblogiw.c index a0895bf07487..0a2d75f04066 100644 --- a/drivers/media/video/timblogiw.c +++ b/drivers/media/video/timblogiw.c | |||
@@ -872,20 +872,7 @@ static struct platform_driver timblogiw_platform_driver = { | |||
872 | .remove = __devexit_p(timblogiw_remove), | 872 | .remove = __devexit_p(timblogiw_remove), |
873 | }; | 873 | }; |
874 | 874 | ||
875 | /* Module functions */ | 875 | module_platform_driver(timblogiw_platform_driver); |
876 | |||
877 | static int __init timblogiw_init(void) | ||
878 | { | ||
879 | return platform_driver_register(&timblogiw_platform_driver); | ||
880 | } | ||
881 | |||
882 | static void __exit timblogiw_exit(void) | ||
883 | { | ||
884 | platform_driver_unregister(&timblogiw_platform_driver); | ||
885 | } | ||
886 | |||
887 | module_init(timblogiw_init); | ||
888 | module_exit(timblogiw_exit); | ||
889 | 876 | ||
890 | MODULE_DESCRIPTION(TIMBLOGIWIN_NAME); | 877 | MODULE_DESCRIPTION(TIMBLOGIWIN_NAME); |
891 | MODULE_AUTHOR("Pelagicore AB <info@pelagicore.com>"); | 878 | MODULE_AUTHOR("Pelagicore AB <info@pelagicore.com>"); |
diff --git a/drivers/media/video/tlg2300/pd-common.h b/drivers/media/video/tlg2300/pd-common.h index 56564e6aaac2..5dd73b7857d1 100644 --- a/drivers/media/video/tlg2300/pd-common.h +++ b/drivers/media/video/tlg2300/pd-common.h | |||
@@ -140,7 +140,7 @@ struct pd_dvb_adapter { | |||
140 | u8 reserved[3]; | 140 | u8 reserved[3]; |
141 | 141 | ||
142 | /* data for power resume*/ | 142 | /* data for power resume*/ |
143 | struct dvb_frontend_parameters fe_param; | 143 | struct dtv_frontend_properties fe_param; |
144 | 144 | ||
145 | /* for channel scanning */ | 145 | /* for channel scanning */ |
146 | int prev_freq; | 146 | int prev_freq; |
diff --git a/drivers/media/video/tlg2300/pd-dvb.c b/drivers/media/video/tlg2300/pd-dvb.c index d0da11ae19df..30fcb117e898 100644 --- a/drivers/media/video/tlg2300/pd-dvb.c +++ b/drivers/media/video/tlg2300/pd-dvb.c | |||
@@ -12,9 +12,9 @@ | |||
12 | static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb); | 12 | static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb); |
13 | 13 | ||
14 | static int dvb_bandwidth[][2] = { | 14 | static int dvb_bandwidth[][2] = { |
15 | { TLG_BW_8, BANDWIDTH_8_MHZ }, | 15 | { TLG_BW_8, 8000000 }, |
16 | { TLG_BW_7, BANDWIDTH_7_MHZ }, | 16 | { TLG_BW_7, 7000000 }, |
17 | { TLG_BW_6, BANDWIDTH_6_MHZ } | 17 | { TLG_BW_6, 6000000 } |
18 | }; | 18 | }; |
19 | static int dvb_bandwidth_length = ARRAY_SIZE(dvb_bandwidth); | 19 | static int dvb_bandwidth_length = ARRAY_SIZE(dvb_bandwidth); |
20 | 20 | ||
@@ -146,9 +146,9 @@ static int fw_delay_overflow(struct pd_dvb_adapter *adapter) | |||
146 | return msec > 800 ? true : false; | 146 | return msec > 800 ? true : false; |
147 | } | 147 | } |
148 | 148 | ||
149 | static int poseidon_set_fe(struct dvb_frontend *fe, | 149 | static int poseidon_set_fe(struct dvb_frontend *fe) |
150 | struct dvb_frontend_parameters *fep) | ||
151 | { | 150 | { |
151 | struct dtv_frontend_properties *fep = &fe->dtv_property_cache; | ||
152 | s32 ret = 0, cmd_status = 0; | 152 | s32 ret = 0, cmd_status = 0; |
153 | s32 i, bandwidth = -1; | 153 | s32 i, bandwidth = -1; |
154 | struct poseidon *pd = fe->demodulator_priv; | 154 | struct poseidon *pd = fe->demodulator_priv; |
@@ -159,7 +159,7 @@ static int poseidon_set_fe(struct dvb_frontend *fe, | |||
159 | 159 | ||
160 | mutex_lock(&pd->lock); | 160 | mutex_lock(&pd->lock); |
161 | for (i = 0; i < dvb_bandwidth_length; i++) | 161 | for (i = 0; i < dvb_bandwidth_length; i++) |
162 | if (fep->u.ofdm.bandwidth == dvb_bandwidth[i][1]) | 162 | if (fep->bandwidth_hz == dvb_bandwidth[i][1]) |
163 | bandwidth = dvb_bandwidth[i][0]; | 163 | bandwidth = dvb_bandwidth[i][0]; |
164 | 164 | ||
165 | if (check_scan_ok(fep->frequency, bandwidth, pd_dvb)) { | 165 | if (check_scan_ok(fep->frequency, bandwidth, pd_dvb)) { |
@@ -210,7 +210,7 @@ static int pm_dvb_resume(struct poseidon *pd) | |||
210 | 210 | ||
211 | poseidon_check_mode_dvbt(pd); | 211 | poseidon_check_mode_dvbt(pd); |
212 | msleep(300); | 212 | msleep(300); |
213 | poseidon_set_fe(&pd_dvb->dvb_fe, &pd_dvb->fe_param); | 213 | poseidon_set_fe(&pd_dvb->dvb_fe); |
214 | 214 | ||
215 | dvb_start_streaming(pd_dvb); | 215 | dvb_start_streaming(pd_dvb); |
216 | return 0; | 216 | return 0; |
@@ -227,13 +227,13 @@ static s32 poseidon_fe_init(struct dvb_frontend *fe) | |||
227 | pd->pm_resume = pm_dvb_resume; | 227 | pd->pm_resume = pm_dvb_resume; |
228 | #endif | 228 | #endif |
229 | memset(&pd_dvb->fe_param, 0, | 229 | memset(&pd_dvb->fe_param, 0, |
230 | sizeof(struct dvb_frontend_parameters)); | 230 | sizeof(struct dtv_frontend_properties)); |
231 | return 0; | 231 | return 0; |
232 | } | 232 | } |
233 | 233 | ||
234 | static int poseidon_get_fe(struct dvb_frontend *fe, | 234 | static int poseidon_get_fe(struct dvb_frontend *fe) |
235 | struct dvb_frontend_parameters *fep) | ||
236 | { | 235 | { |
236 | struct dtv_frontend_properties *fep = &fe->dtv_property_cache; | ||
237 | struct poseidon *pd = fe->demodulator_priv; | 237 | struct poseidon *pd = fe->demodulator_priv; |
238 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; | 238 | struct pd_dvb_adapter *pd_dvb = &pd->dvb_data; |
239 | 239 | ||
@@ -332,9 +332,9 @@ static int poseidon_read_unc_blocks(struct dvb_frontend *fe, u32 *unc) | |||
332 | } | 332 | } |
333 | 333 | ||
334 | static struct dvb_frontend_ops poseidon_frontend_ops = { | 334 | static struct dvb_frontend_ops poseidon_frontend_ops = { |
335 | .delsys = { SYS_DVBT }, | ||
335 | .info = { | 336 | .info = { |
336 | .name = "Poseidon DVB-T", | 337 | .name = "Poseidon DVB-T", |
337 | .type = FE_OFDM, | ||
338 | .frequency_min = 174000000, | 338 | .frequency_min = 174000000, |
339 | .frequency_max = 862000000, | 339 | .frequency_max = 862000000, |
340 | .frequency_stepsize = 62500,/* FIXME */ | 340 | .frequency_stepsize = 62500,/* FIXME */ |
diff --git a/drivers/media/video/tm6000/Kconfig b/drivers/media/video/tm6000/Kconfig index 114eec8a630a..a43b77abd931 100644 --- a/drivers/media/video/tm6000/Kconfig +++ b/drivers/media/video/tm6000/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config VIDEO_TM6000 | 1 | config VIDEO_TM6000 |
2 | tristate "TV Master TM5600/6000/6010 driver" | 2 | tristate "TV Master TM5600/6000/6010 driver" |
3 | depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB && EXPERIMENTAL | 3 | depends on VIDEO_DEV && I2C && INPUT && RC_CORE && USB |
4 | select VIDEO_TUNER | 4 | select VIDEO_TUNER |
5 | select MEDIA_TUNER_XC2028 | 5 | select MEDIA_TUNER_XC2028 |
6 | select MEDIA_TUNER_XC5000 | 6 | select MEDIA_TUNER_XC5000 |
@@ -16,7 +16,7 @@ config VIDEO_TM6000 | |||
16 | 16 | ||
17 | config VIDEO_TM6000_ALSA | 17 | config VIDEO_TM6000_ALSA |
18 | tristate "TV Master TM5600/6000/6010 audio support" | 18 | tristate "TV Master TM5600/6000/6010 audio support" |
19 | depends on VIDEO_TM6000 && SND && EXPERIMENTAL | 19 | depends on VIDEO_TM6000 && SND |
20 | select SND_PCM | 20 | select SND_PCM |
21 | ---help--- | 21 | ---help--- |
22 | This is a video4linux driver for direct (DMA) audio for | 22 | This is a video4linux driver for direct (DMA) audio for |
@@ -27,7 +27,7 @@ config VIDEO_TM6000_ALSA | |||
27 | 27 | ||
28 | config VIDEO_TM6000_DVB | 28 | config VIDEO_TM6000_DVB |
29 | tristate "DVB Support for tm6000 based TV cards" | 29 | tristate "DVB Support for tm6000 based TV cards" |
30 | depends on VIDEO_TM6000 && DVB_CORE && USB && EXPERIMENTAL | 30 | depends on VIDEO_TM6000 && DVB_CORE && USB |
31 | select DVB_ZL10353 | 31 | select DVB_ZL10353 |
32 | ---help--- | 32 | ---help--- |
33 | This adds support for DVB cards based on the tm5600/tm6000 chip. | 33 | This adds support for DVB cards based on the tm5600/tm6000 chip. |
diff --git a/drivers/media/video/tm6000/tm6000-alsa.c b/drivers/media/video/tm6000/tm6000-alsa.c index bb2047c10358..bd07ec707956 100644 --- a/drivers/media/video/tm6000/tm6000-alsa.c +++ b/drivers/media/video/tm6000/tm6000-alsa.c | |||
@@ -146,20 +146,21 @@ static int dsp_buffer_alloc(struct snd_pcm_substream *substream, int size) | |||
146 | #define DEFAULT_FIFO_SIZE 4096 | 146 | #define DEFAULT_FIFO_SIZE 4096 |
147 | 147 | ||
148 | static struct snd_pcm_hardware snd_tm6000_digital_hw = { | 148 | static struct snd_pcm_hardware snd_tm6000_digital_hw = { |
149 | .info = SNDRV_PCM_INFO_MMAP | | 149 | .info = SNDRV_PCM_INFO_BATCH | |
150 | SNDRV_PCM_INFO_MMAP | | ||
150 | SNDRV_PCM_INFO_INTERLEAVED | | 151 | SNDRV_PCM_INFO_INTERLEAVED | |
151 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 152 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
152 | SNDRV_PCM_INFO_MMAP_VALID, | 153 | SNDRV_PCM_INFO_MMAP_VALID, |
153 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 154 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
154 | 155 | ||
155 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | 156 | .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_KNOT, |
156 | .rate_min = 48000, | 157 | .rate_min = 48000, |
157 | .rate_max = 48000, | 158 | .rate_max = 48000, |
158 | .channels_min = 2, | 159 | .channels_min = 2, |
159 | .channels_max = 2, | 160 | .channels_max = 2, |
160 | .period_bytes_min = 64, | 161 | .period_bytes_min = 64, |
161 | .period_bytes_max = 12544, | 162 | .period_bytes_max = 12544, |
162 | .periods_min = 1, | 163 | .periods_min = 2, |
163 | .periods_max = 98, | 164 | .periods_max = 98, |
164 | .buffer_bytes_max = 62720 * 8, | 165 | .buffer_bytes_max = 62720 * 8, |
165 | }; | 166 | }; |
@@ -181,6 +182,7 @@ static int snd_tm6000_pcm_open(struct snd_pcm_substream *substream) | |||
181 | chip->substream = substream; | 182 | chip->substream = substream; |
182 | 183 | ||
183 | runtime->hw = snd_tm6000_digital_hw; | 184 | runtime->hw = snd_tm6000_digital_hw; |
185 | snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
184 | 186 | ||
185 | return 0; | 187 | return 0; |
186 | _error: | 188 | _error: |
@@ -347,9 +349,13 @@ static int snd_tm6000_card_trigger(struct snd_pcm_substream *substream, int cmd) | |||
347 | int err = 0; | 349 | int err = 0; |
348 | 350 | ||
349 | switch (cmd) { | 351 | switch (cmd) { |
352 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: /* fall through */ | ||
353 | case SNDRV_PCM_TRIGGER_RESUME: /* fall through */ | ||
350 | case SNDRV_PCM_TRIGGER_START: | 354 | case SNDRV_PCM_TRIGGER_START: |
351 | atomic_set(&core->stream_started, 1); | 355 | atomic_set(&core->stream_started, 1); |
352 | break; | 356 | break; |
357 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: /* fall through */ | ||
358 | case SNDRV_PCM_TRIGGER_SUSPEND: /* fall through */ | ||
353 | case SNDRV_PCM_TRIGGER_STOP: | 359 | case SNDRV_PCM_TRIGGER_STOP: |
354 | atomic_set(&core->stream_started, 0); | 360 | atomic_set(&core->stream_started, 0); |
355 | break; | 361 | break; |
@@ -371,6 +377,14 @@ static snd_pcm_uframes_t snd_tm6000_pointer(struct snd_pcm_substream *substream) | |||
371 | return chip->buf_pos; | 377 | return chip->buf_pos; |
372 | } | 378 | } |
373 | 379 | ||
380 | static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs, | ||
381 | unsigned long offset) | ||
382 | { | ||
383 | void *pageptr = subs->runtime->dma_area + offset; | ||
384 | |||
385 | return vmalloc_to_page(pageptr); | ||
386 | } | ||
387 | |||
374 | /* | 388 | /* |
375 | * operators | 389 | * operators |
376 | */ | 390 | */ |
@@ -383,6 +397,7 @@ static struct snd_pcm_ops snd_tm6000_pcm_ops = { | |||
383 | .prepare = snd_tm6000_prepare, | 397 | .prepare = snd_tm6000_prepare, |
384 | .trigger = snd_tm6000_card_trigger, | 398 | .trigger = snd_tm6000_card_trigger, |
385 | .pointer = snd_tm6000_pointer, | 399 | .pointer = snd_tm6000_pointer, |
400 | .page = snd_pcm_get_vmalloc_page, | ||
386 | }; | 401 | }; |
387 | 402 | ||
388 | /* | 403 | /* |
diff --git a/drivers/media/video/tm6000/tm6000-cards.c b/drivers/media/video/tm6000/tm6000-cards.c index ff939bc0e0b9..034659b13174 100644 --- a/drivers/media/video/tm6000/tm6000-cards.c +++ b/drivers/media/video/tm6000/tm6000-cards.c | |||
@@ -351,6 +351,7 @@ static struct tm6000_board tm6000_boards[] = { | |||
351 | .tuner_addr = 0xc2 >> 1, | 351 | .tuner_addr = 0xc2 >> 1, |
352 | .demod_addr = 0x1e >> 1, | 352 | .demod_addr = 0x1e >> 1, |
353 | .type = TM6010, | 353 | .type = TM6010, |
354 | .ir_codes = RC_MAP_HAUPPAUGE, | ||
354 | .caps = { | 355 | .caps = { |
355 | .has_tuner = 1, | 356 | .has_tuner = 1, |
356 | .has_dvb = 1, | 357 | .has_dvb = 1, |
@@ -639,6 +640,7 @@ static struct usb_device_id tm6000_id_table[] = { | |||
639 | { USB_DEVICE(0x6000, 0xdec3), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER_LITE }, | 640 | { USB_DEVICE(0x6000, 0xdec3), .driver_info = TM6010_BOARD_BEHOLD_VOYAGER_LITE }, |
640 | { } | 641 | { } |
641 | }; | 642 | }; |
643 | MODULE_DEVICE_TABLE(usb, tm6000_id_table); | ||
642 | 644 | ||
643 | /* Control power led for show some activity */ | 645 | /* Control power led for show some activity */ |
644 | void tm6000_flash_led(struct tm6000_core *dev, u8 state) | 646 | void tm6000_flash_led(struct tm6000_core *dev, u8 state) |
@@ -941,6 +943,7 @@ static void tm6000_config_tuner(struct tm6000_core *dev) | |||
941 | case TM6010_BOARD_HAUPPAUGE_900H: | 943 | case TM6010_BOARD_HAUPPAUGE_900H: |
942 | case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: | 944 | case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: |
943 | case TM6010_BOARD_TWINHAN_TU501: | 945 | case TM6010_BOARD_TWINHAN_TU501: |
946 | ctl.max_len = 80; | ||
944 | ctl.fname = "xc3028L-v36.fw"; | 947 | ctl.fname = "xc3028L-v36.fw"; |
945 | break; | 948 | break; |
946 | default: | 949 | default: |
@@ -1002,6 +1005,7 @@ static int fill_board_specific_data(struct tm6000_core *dev) | |||
1002 | /* setup per-model quirks */ | 1005 | /* setup per-model quirks */ |
1003 | switch (dev->model) { | 1006 | switch (dev->model) { |
1004 | case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: | 1007 | case TM6010_BOARD_TERRATEC_CINERGY_HYBRID_XE: |
1008 | case TM6010_BOARD_HAUPPAUGE_900H: | ||
1005 | dev->quirks |= TM6000_QUIRK_NO_USB_DELAY; | 1009 | dev->quirks |= TM6000_QUIRK_NO_USB_DELAY; |
1006 | break; | 1010 | break; |
1007 | 1011 | ||
@@ -1050,6 +1054,33 @@ static void use_alternative_detection_method(struct tm6000_core *dev) | |||
1050 | tm6000_boards[model].name, model); | 1054 | tm6000_boards[model].name, model); |
1051 | } | 1055 | } |
1052 | 1056 | ||
1057 | #if defined(CONFIG_MODULES) && defined(MODULE) | ||
1058 | static void request_module_async(struct work_struct *work) | ||
1059 | { | ||
1060 | struct tm6000_core *dev = container_of(work, struct tm6000_core, | ||
1061 | request_module_wk); | ||
1062 | |||
1063 | request_module("tm6000-alsa"); | ||
1064 | |||
1065 | if (dev->caps.has_dvb) | ||
1066 | request_module("tm6000-dvb"); | ||
1067 | } | ||
1068 | |||
1069 | static void request_modules(struct tm6000_core *dev) | ||
1070 | { | ||
1071 | INIT_WORK(&dev->request_module_wk, request_module_async); | ||
1072 | schedule_work(&dev->request_module_wk); | ||
1073 | } | ||
1074 | |||
1075 | static void flush_request_modules(struct tm6000_core *dev) | ||
1076 | { | ||
1077 | flush_work_sync(&dev->request_module_wk); | ||
1078 | } | ||
1079 | #else | ||
1080 | #define request_modules(dev) | ||
1081 | #define flush_request_modules(dev) | ||
1082 | #endif /* CONFIG_MODULES */ | ||
1083 | |||
1053 | static int tm6000_init_dev(struct tm6000_core *dev) | 1084 | static int tm6000_init_dev(struct tm6000_core *dev) |
1054 | { | 1085 | { |
1055 | struct v4l2_frequency f; | 1086 | struct v4l2_frequency f; |
@@ -1112,6 +1143,8 @@ static int tm6000_init_dev(struct tm6000_core *dev) | |||
1112 | 1143 | ||
1113 | tm6000_ir_init(dev); | 1144 | tm6000_ir_init(dev); |
1114 | 1145 | ||
1146 | request_modules(dev); | ||
1147 | |||
1115 | mutex_unlock(&dev->lock); | 1148 | mutex_unlock(&dev->lock); |
1116 | return 0; | 1149 | return 0; |
1117 | 1150 | ||
@@ -1324,6 +1357,8 @@ static void tm6000_usb_disconnect(struct usb_interface *interface) | |||
1324 | 1357 | ||
1325 | printk(KERN_INFO "tm6000: disconnecting %s\n", dev->name); | 1358 | printk(KERN_INFO "tm6000: disconnecting %s\n", dev->name); |
1326 | 1359 | ||
1360 | flush_request_modules(dev); | ||
1361 | |||
1327 | tm6000_ir_fini(dev); | 1362 | tm6000_ir_fini(dev); |
1328 | 1363 | ||
1329 | if (dev->gpio.power_led) { | 1364 | if (dev->gpio.power_led) { |
diff --git a/drivers/media/video/tm6000/tm6000-core.c b/drivers/media/video/tm6000/tm6000-core.c index 9783616a0da2..22cc0116deb6 100644 --- a/drivers/media/video/tm6000/tm6000-core.c +++ b/drivers/media/video/tm6000/tm6000-core.c | |||
@@ -38,6 +38,7 @@ int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req, | |||
38 | int ret, i; | 38 | int ret, i; |
39 | unsigned int pipe; | 39 | unsigned int pipe; |
40 | u8 *data = NULL; | 40 | u8 *data = NULL; |
41 | int delay = 5000; | ||
41 | 42 | ||
42 | mutex_lock(&dev->usb_lock); | 43 | mutex_lock(&dev->usb_lock); |
43 | 44 | ||
@@ -88,7 +89,20 @@ int tm6000_read_write_usb(struct tm6000_core *dev, u8 req_type, u8 req, | |||
88 | } | 89 | } |
89 | 90 | ||
90 | kfree(data); | 91 | kfree(data); |
91 | msleep(5); | 92 | |
93 | if (dev->quirks & TM6000_QUIRK_NO_USB_DELAY) | ||
94 | delay = 0; | ||
95 | |||
96 | if (req == REQ_16_SET_GET_I2C_WR1_RDN && !(req_type & USB_DIR_IN)) { | ||
97 | unsigned int tsleep; | ||
98 | /* Calculate delay time, 14000us for 64 bytes */ | ||
99 | tsleep = (len * 200) + 200; | ||
100 | if (tsleep < delay) | ||
101 | tsleep = delay; | ||
102 | usleep_range(tsleep, tsleep + 1000); | ||
103 | } | ||
104 | else if (delay) | ||
105 | usleep_range(delay, delay + 1000); | ||
92 | 106 | ||
93 | mutex_unlock(&dev->usb_lock); | 107 | mutex_unlock(&dev->usb_lock); |
94 | return ret; | 108 | return ret; |
@@ -125,14 +139,14 @@ int tm6000_set_reg_mask(struct tm6000_core *dev, u8 req, u16 value, | |||
125 | u8 new_index; | 139 | u8 new_index; |
126 | 140 | ||
127 | rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req, | 141 | rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR, req, |
128 | value, index, buf, 1); | 142 | value, 0, buf, 1); |
129 | 143 | ||
130 | if (rc < 0) | 144 | if (rc < 0) |
131 | return rc; | 145 | return rc; |
132 | 146 | ||
133 | new_index = (buf[0] & ~mask) | (index & mask); | 147 | new_index = (buf[0] & ~mask) | (index & mask); |
134 | 148 | ||
135 | if (new_index == index) | 149 | if (new_index == buf[0]) |
136 | return 0; | 150 | return 0; |
137 | 151 | ||
138 | return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR, | 152 | return tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR, |
@@ -536,16 +550,16 @@ static struct reg_init tm6010_init_tab[] = { | |||
536 | 550 | ||
537 | { TM6010_REQ05_R18_IMASK7, 0x00 }, | 551 | { TM6010_REQ05_R18_IMASK7, 0x00 }, |
538 | 552 | ||
539 | { TM6010_REQ07_RD8_IR_LEADER1, 0xaa }, | 553 | { TM6010_REQ07_RDC_IR_LEADER1, 0xaa }, |
540 | { TM6010_REQ07_RD8_IR_LEADER0, 0x30 }, | 554 | { TM6010_REQ07_RDD_IR_LEADER0, 0x30 }, |
541 | { TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20 }, | 555 | { TM6010_REQ07_RDE_IR_PULSE_CNT1, 0x20 }, |
542 | { TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0 }, | 556 | { TM6010_REQ07_RDF_IR_PULSE_CNT0, 0xd0 }, |
543 | { REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 }, | 557 | { REQ_04_EN_DISABLE_MCU_INT, 0x02, 0x00 }, |
544 | { TM6010_REQ07_RD8_IR, 0x2f }, | 558 | { TM6010_REQ07_RD8_IR, 0x0f }, |
545 | 559 | ||
546 | /* set remote wakeup key:any key wakeup */ | 560 | /* set remote wakeup key:any key wakeup */ |
547 | { TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe }, | 561 | { TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe }, |
548 | { TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff }, | 562 | { TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff }, |
549 | }; | 563 | }; |
550 | 564 | ||
551 | int tm6000_init(struct tm6000_core *dev) | 565 | int tm6000_init(struct tm6000_core *dev) |
@@ -599,55 +613,6 @@ int tm6000_init(struct tm6000_core *dev) | |||
599 | return rc; | 613 | return rc; |
600 | } | 614 | } |
601 | 615 | ||
602 | int tm6000_reset(struct tm6000_core *dev) | ||
603 | { | ||
604 | int pipe; | ||
605 | int err; | ||
606 | |||
607 | msleep(500); | ||
608 | |||
609 | err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 0); | ||
610 | if (err < 0) { | ||
611 | tm6000_err("failed to select interface %d, alt. setting 0\n", | ||
612 | dev->isoc_in.bInterfaceNumber); | ||
613 | return err; | ||
614 | } | ||
615 | |||
616 | err = usb_reset_configuration(dev->udev); | ||
617 | if (err < 0) { | ||
618 | tm6000_err("failed to reset configuration\n"); | ||
619 | return err; | ||
620 | } | ||
621 | |||
622 | if ((dev->quirks & TM6000_QUIRK_NO_USB_DELAY) == 0) | ||
623 | msleep(5); | ||
624 | |||
625 | /* | ||
626 | * Not all devices have int_in defined | ||
627 | */ | ||
628 | if (!dev->int_in.endp) | ||
629 | return 0; | ||
630 | |||
631 | err = usb_set_interface(dev->udev, dev->isoc_in.bInterfaceNumber, 2); | ||
632 | if (err < 0) { | ||
633 | tm6000_err("failed to select interface %d, alt. setting 2\n", | ||
634 | dev->isoc_in.bInterfaceNumber); | ||
635 | return err; | ||
636 | } | ||
637 | |||
638 | msleep(5); | ||
639 | |||
640 | pipe = usb_rcvintpipe(dev->udev, | ||
641 | dev->int_in.endp->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); | ||
642 | |||
643 | err = usb_clear_halt(dev->udev, pipe); | ||
644 | if (err < 0) { | ||
645 | tm6000_err("usb_clear_halt failed: %d\n", err); | ||
646 | return err; | ||
647 | } | ||
648 | |||
649 | return 0; | ||
650 | } | ||
651 | 616 | ||
652 | int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate) | 617 | int tm6000_set_audio_bitrate(struct tm6000_core *dev, int bitrate) |
653 | { | 618 | { |
@@ -696,11 +661,13 @@ int tm6000_set_audio_rinput(struct tm6000_core *dev) | |||
696 | if (dev->dev_type == TM6010) { | 661 | if (dev->dev_type == TM6010) { |
697 | /* Audio crossbar setting, default SIF1 */ | 662 | /* Audio crossbar setting, default SIF1 */ |
698 | u8 areg_f0; | 663 | u8 areg_f0; |
664 | u8 areg_07 = 0x10; | ||
699 | 665 | ||
700 | switch (dev->rinput.amux) { | 666 | switch (dev->rinput.amux) { |
701 | case TM6000_AMUX_SIF1: | 667 | case TM6000_AMUX_SIF1: |
702 | case TM6000_AMUX_SIF2: | 668 | case TM6000_AMUX_SIF2: |
703 | areg_f0 = 0x03; | 669 | areg_f0 = 0x03; |
670 | areg_07 = 0x30; | ||
704 | break; | 671 | break; |
705 | case TM6000_AMUX_ADC1: | 672 | case TM6000_AMUX_ADC1: |
706 | areg_f0 = 0x00; | 673 | areg_f0 = 0x00; |
@@ -720,6 +687,9 @@ int tm6000_set_audio_rinput(struct tm6000_core *dev) | |||
720 | /* Set audio input crossbar */ | 687 | /* Set audio input crossbar */ |
721 | tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, | 688 | tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, |
722 | areg_f0, 0x0f); | 689 | areg_f0, 0x0f); |
690 | /* Mux overflow workaround */ | ||
691 | tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, | ||
692 | areg_07, 0xf0); | ||
723 | } else { | 693 | } else { |
724 | u8 areg_eb; | 694 | u8 areg_eb; |
725 | /* Audio setting, default LINE1 */ | 695 | /* Audio setting, default LINE1 */ |
diff --git a/drivers/media/video/tm6000/tm6000-dvb.c b/drivers/media/video/tm6000/tm6000-dvb.c index 5e6c129a4beb..e1f3f66e1e63 100644 --- a/drivers/media/video/tm6000/tm6000-dvb.c +++ b/drivers/media/video/tm6000/tm6000-dvb.c | |||
@@ -89,9 +89,19 @@ static void tm6000_urb_received(struct urb *urb) | |||
89 | int ret; | 89 | int ret; |
90 | struct tm6000_core *dev = urb->context; | 90 | struct tm6000_core *dev = urb->context; |
91 | 91 | ||
92 | if (urb->status != 0) | 92 | switch (urb->status) { |
93 | case 0: | ||
94 | case -ETIMEDOUT: | ||
95 | break; | ||
96 | case -ENOENT: | ||
97 | case -ECONNRESET: | ||
98 | case -ESHUTDOWN: | ||
99 | return; | ||
100 | default: | ||
93 | print_err_status(dev, 0, urb->status); | 101 | print_err_status(dev, 0, urb->status); |
94 | else if (urb->actual_length > 0) | 102 | } |
103 | |||
104 | if (urb->actual_length > 0) | ||
95 | dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer, | 105 | dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer, |
96 | urb->actual_length); | 106 | urb->actual_length); |
97 | 107 | ||
@@ -151,7 +161,7 @@ static int tm6000_start_stream(struct tm6000_core *dev) | |||
151 | printk(KERN_ERR "tm6000: pipe resetted\n"); | 161 | printk(KERN_ERR "tm6000: pipe resetted\n"); |
152 | 162 | ||
153 | /* mutex_lock(&tm6000_driver.open_close_mutex); */ | 163 | /* mutex_lock(&tm6000_driver.open_close_mutex); */ |
154 | ret = usb_submit_urb(dvb->bulk_urb, GFP_KERNEL); | 164 | ret = usb_submit_urb(dvb->bulk_urb, GFP_ATOMIC); |
155 | 165 | ||
156 | /* mutex_unlock(&tm6000_driver.open_close_mutex); */ | 166 | /* mutex_unlock(&tm6000_driver.open_close_mutex); */ |
157 | if (ret) { | 167 | if (ret) { |
@@ -396,6 +406,11 @@ static int dvb_init(struct tm6000_core *dev) | |||
396 | if (!dev->caps.has_dvb) | 406 | if (!dev->caps.has_dvb) |
397 | return 0; | 407 | return 0; |
398 | 408 | ||
409 | if (dev->udev->speed == USB_SPEED_FULL) { | ||
410 | printk(KERN_INFO "This USB2.0 device cannot be run on a USB1.1 port. (it lacks a hardware PID filter)\n"); | ||
411 | return 0; | ||
412 | } | ||
413 | |||
399 | dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL); | 414 | dvb = kzalloc(sizeof(struct tm6000_dvb), GFP_KERNEL); |
400 | if (!dvb) { | 415 | if (!dvb) { |
401 | printk(KERN_INFO "Cannot allocate memory\n"); | 416 | printk(KERN_INFO "Cannot allocate memory\n"); |
diff --git a/drivers/media/video/tm6000/tm6000-i2c.c b/drivers/media/video/tm6000/tm6000-i2c.c index 0290bbf00c3e..c7e23e3dd75e 100644 --- a/drivers/media/video/tm6000/tm6000-i2c.c +++ b/drivers/media/video/tm6000/tm6000-i2c.c | |||
@@ -46,11 +46,10 @@ static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr, | |||
46 | __u8 reg, char *buf, int len) | 46 | __u8 reg, char *buf, int len) |
47 | { | 47 | { |
48 | int rc; | 48 | int rc; |
49 | unsigned int tsleep; | ||
50 | unsigned int i2c_packet_limit = 16; | 49 | unsigned int i2c_packet_limit = 16; |
51 | 50 | ||
52 | if (dev->dev_type == TM6010) | 51 | if (dev->dev_type == TM6010) |
53 | i2c_packet_limit = 64; | 52 | i2c_packet_limit = 80; |
54 | 53 | ||
55 | if (!buf) | 54 | if (!buf) |
56 | return -1; | 55 | return -1; |
@@ -71,10 +70,6 @@ static int tm6000_i2c_send_regs(struct tm6000_core *dev, unsigned char addr, | |||
71 | return rc; | 70 | return rc; |
72 | } | 71 | } |
73 | 72 | ||
74 | /* Calculate delay time, 14000us for 64 bytes */ | ||
75 | tsleep = ((len * 200) + 200 + 1000) / 1000; | ||
76 | msleep(tsleep); | ||
77 | |||
78 | /* release mutex */ | 73 | /* release mutex */ |
79 | return rc; | 74 | return rc; |
80 | } | 75 | } |
@@ -145,7 +140,6 @@ static int tm6000_i2c_recv_regs16(struct tm6000_core *dev, unsigned char addr, | |||
145 | return rc; | 140 | return rc; |
146 | } | 141 | } |
147 | 142 | ||
148 | msleep(1400 / 1000); | ||
149 | rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | | 143 | rc = tm6000_read_write_usb(dev, USB_DIR_IN | USB_TYPE_VENDOR | |
150 | USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ, | 144 | USB_RECIP_DEVICE, REQ_35_AFTEK_TUNER_READ, |
151 | reg, 0, buf, len); | 145 | reg, 0, buf, len); |
diff --git a/drivers/media/video/tm6000/tm6000-input.c b/drivers/media/video/tm6000/tm6000-input.c index 405d12729d05..7844607dd45a 100644 --- a/drivers/media/video/tm6000/tm6000-input.c +++ b/drivers/media/video/tm6000/tm6000-input.c | |||
@@ -31,22 +31,25 @@ | |||
31 | 31 | ||
32 | static unsigned int ir_debug; | 32 | static unsigned int ir_debug; |
33 | module_param(ir_debug, int, 0644); | 33 | module_param(ir_debug, int, 0644); |
34 | MODULE_PARM_DESC(ir_debug, "enable debug message [IR]"); | 34 | MODULE_PARM_DESC(ir_debug, "debug message level"); |
35 | 35 | ||
36 | static unsigned int enable_ir = 1; | 36 | static unsigned int enable_ir = 1; |
37 | module_param(enable_ir, int, 0644); | 37 | module_param(enable_ir, int, 0644); |
38 | MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)"); | 38 | MODULE_PARM_DESC(enable_ir, "enable ir (default is enable)"); |
39 | 39 | ||
40 | /* number of 50ms for ON-OFF-ON power led */ | 40 | static unsigned int ir_clock_mhz = 12; |
41 | /* show IR activity */ | 41 | module_param(ir_clock_mhz, int, 0644); |
42 | #define PWLED_OFF 2 | 42 | MODULE_PARM_DESC(enable_ir, "ir clock, in MHz"); |
43 | |||
44 | #define URB_SUBMIT_DELAY 100 /* ms - Delay to submit an URB request on retrial and init */ | ||
45 | #define URB_INT_LED_DELAY 100 /* ms - Delay to turn led on again on int mode */ | ||
43 | 46 | ||
44 | #undef dprintk | 47 | #undef dprintk |
45 | 48 | ||
46 | #define dprintk(fmt, arg...) \ | 49 | #define dprintk(level, fmt, arg...) do {\ |
47 | if (ir_debug) { \ | 50 | if (ir_debug >= level) \ |
48 | printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ | 51 | printk(KERN_DEBUG "%s/ir: " fmt, ir->name , ## arg); \ |
49 | } | 52 | } while (0) |
50 | 53 | ||
51 | struct tm6000_ir_poll_result { | 54 | struct tm6000_ir_poll_result { |
52 | u16 rc_data; | 55 | u16 rc_data; |
@@ -62,20 +65,15 @@ struct tm6000_IR { | |||
62 | int polling; | 65 | int polling; |
63 | struct delayed_work work; | 66 | struct delayed_work work; |
64 | u8 wait:1; | 67 | u8 wait:1; |
65 | u8 key:1; | 68 | u8 pwled:2; |
66 | u8 pwled:1; | 69 | u8 submit_urb:1; |
67 | u8 pwledcnt; | ||
68 | u16 key_addr; | 70 | u16 key_addr; |
69 | struct urb *int_urb; | 71 | struct urb *int_urb; |
70 | u8 *urb_data; | ||
71 | |||
72 | int (*get_key) (struct tm6000_IR *, struct tm6000_ir_poll_result *); | ||
73 | 72 | ||
74 | /* IR device properties */ | 73 | /* IR device properties */ |
75 | u64 rc_type; | 74 | u64 rc_type; |
76 | }; | 75 | }; |
77 | 76 | ||
78 | |||
79 | void tm6000_ir_wait(struct tm6000_core *dev, u8 state) | 77 | void tm6000_ir_wait(struct tm6000_core *dev, u8 state) |
80 | { | 78 | { |
81 | struct tm6000_IR *ir = dev->ir; | 79 | struct tm6000_IR *ir = dev->ir; |
@@ -83,62 +81,84 @@ void tm6000_ir_wait(struct tm6000_core *dev, u8 state) | |||
83 | if (!dev->ir) | 81 | if (!dev->ir) |
84 | return; | 82 | return; |
85 | 83 | ||
84 | dprintk(2, "%s: %i\n",__func__, ir->wait); | ||
85 | |||
86 | if (state) | 86 | if (state) |
87 | ir->wait = 1; | 87 | ir->wait = 1; |
88 | else | 88 | else |
89 | ir->wait = 0; | 89 | ir->wait = 0; |
90 | } | 90 | } |
91 | 91 | ||
92 | |||
93 | static int tm6000_ir_config(struct tm6000_IR *ir) | 92 | static int tm6000_ir_config(struct tm6000_IR *ir) |
94 | { | 93 | { |
95 | struct tm6000_core *dev = ir->dev; | 94 | struct tm6000_core *dev = ir->dev; |
96 | u8 buf[10]; | 95 | u32 pulse = 0, leader = 0; |
97 | int rc; | 96 | |
97 | dprintk(2, "%s\n",__func__); | ||
98 | |||
99 | /* | ||
100 | * The IR decoder supports RC-5 or NEC, with a configurable timing. | ||
101 | * The timing configuration there is not that accurate, as it uses | ||
102 | * approximate values. The NEC spec mentions a 562.5 unit period, | ||
103 | * and RC-5 uses a 888.8 period. | ||
104 | * Currently, driver assumes a clock provided by a 12 MHz XTAL, but | ||
105 | * a modprobe parameter can adjust it. | ||
106 | * Adjustments are required for other timings. | ||
107 | * It seems that the 900ms timing for NEC is used to detect a RC-5 | ||
108 | * IR, in order to discard such decoding | ||
109 | */ | ||
98 | 110 | ||
99 | switch (ir->rc_type) { | 111 | switch (ir->rc_type) { |
100 | case RC_TYPE_NEC: | 112 | case RC_TYPE_NEC: |
101 | /* Setup IR decoder for NEC standard 12MHz system clock */ | 113 | leader = 900; /* ms */ |
102 | /* IR_LEADER_CNT = 0.9ms */ | 114 | pulse = 700; /* ms - the actual value would be 562 */ |
103 | tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER1, 0xaa); | ||
104 | tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_LEADER0, 0x30); | ||
105 | /* IR_PULSE_CNT = 0.7ms */ | ||
106 | tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT1, 0x20); | ||
107 | tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_PULSE_CNT0, 0xd0); | ||
108 | /* Remote WAKEUP = enable */ | ||
109 | tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe); | ||
110 | /* IR_WKUP_SEL = Low byte in decoded IR data */ | ||
111 | tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_SEL, 0xff); | ||
112 | /* IR_WKU_ADD code */ | ||
113 | tm6000_set_reg(dev, TM6010_REQ07_RD8_IR_WAKEUP_ADD, 0xff); | ||
114 | tm6000_flash_led(dev, 0); | ||
115 | msleep(100); | ||
116 | tm6000_flash_led(dev, 1); | ||
117 | break; | 115 | break; |
118 | default: | 116 | default: |
119 | /* hack */ | 117 | case RC_TYPE_RC5: |
120 | buf[0] = 0xff; | 118 | leader = 900; /* ms - from the NEC decoding */ |
121 | buf[1] = 0xff; | 119 | pulse = 1780; /* ms - The actual value would be 1776 */ |
122 | buf[2] = 0xf2; | ||
123 | buf[3] = 0x2b; | ||
124 | buf[4] = 0x20; | ||
125 | buf[5] = 0x35; | ||
126 | buf[6] = 0x60; | ||
127 | buf[7] = 0x04; | ||
128 | buf[8] = 0xc0; | ||
129 | buf[9] = 0x08; | ||
130 | |||
131 | rc = tm6000_read_write_usb(dev, USB_DIR_OUT | USB_TYPE_VENDOR | | ||
132 | USB_RECIP_DEVICE, REQ_00_SET_IR_VALUE, 0, 0, buf, 0x0a); | ||
133 | msleep(100); | ||
134 | |||
135 | if (rc < 0) { | ||
136 | printk(KERN_INFO "IR configuration failed"); | ||
137 | return rc; | ||
138 | } | ||
139 | break; | 120 | break; |
140 | } | 121 | } |
141 | 122 | ||
123 | pulse = ir_clock_mhz * pulse; | ||
124 | leader = ir_clock_mhz * leader; | ||
125 | if (ir->rc_type == RC_TYPE_NEC) | ||
126 | leader = leader | 0x8000; | ||
127 | |||
128 | dprintk(2, "%s: %s, %d MHz, leader = 0x%04x, pulse = 0x%06x \n", | ||
129 | __func__, | ||
130 | (ir->rc_type == RC_TYPE_NEC) ? "NEC" : "RC-5", | ||
131 | ir_clock_mhz, leader, pulse); | ||
132 | |||
133 | /* Remote WAKEUP = enable, normal mode, from IR decoder output */ | ||
134 | tm6000_set_reg(dev, TM6010_REQ07_RE5_REMOTE_WAKEUP, 0xfe); | ||
135 | |||
136 | /* Enable IR reception on non-busrt mode */ | ||
137 | tm6000_set_reg(dev, TM6010_REQ07_RD8_IR, 0x2f); | ||
138 | |||
139 | /* IR_WKUP_SEL = Low byte in decoded IR data */ | ||
140 | tm6000_set_reg(dev, TM6010_REQ07_RDA_IR_WAKEUP_SEL, 0xff); | ||
141 | /* IR_WKU_ADD code */ | ||
142 | tm6000_set_reg(dev, TM6010_REQ07_RDB_IR_WAKEUP_ADD, 0xff); | ||
143 | |||
144 | tm6000_set_reg(dev, TM6010_REQ07_RDC_IR_LEADER1, leader >> 8); | ||
145 | tm6000_set_reg(dev, TM6010_REQ07_RDD_IR_LEADER0, leader); | ||
146 | |||
147 | tm6000_set_reg(dev, TM6010_REQ07_RDE_IR_PULSE_CNT1, pulse >> 8); | ||
148 | tm6000_set_reg(dev, TM6010_REQ07_RDF_IR_PULSE_CNT0, pulse); | ||
149 | |||
150 | if (!ir->polling) | ||
151 | tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); | ||
152 | else | ||
153 | tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1); | ||
154 | msleep(10); | ||
155 | |||
156 | /* Shows that IR is working via the LED */ | ||
157 | tm6000_flash_led(dev, 0); | ||
158 | msleep(100); | ||
159 | tm6000_flash_led(dev, 1); | ||
160 | ir->pwled = 1; | ||
161 | |||
142 | return 0; | 162 | return 0; |
143 | } | 163 | } |
144 | 164 | ||
@@ -146,132 +166,124 @@ static void tm6000_ir_urb_received(struct urb *urb) | |||
146 | { | 166 | { |
147 | struct tm6000_core *dev = urb->context; | 167 | struct tm6000_core *dev = urb->context; |
148 | struct tm6000_IR *ir = dev->ir; | 168 | struct tm6000_IR *ir = dev->ir; |
169 | struct tm6000_ir_poll_result poll_result; | ||
170 | char *buf; | ||
149 | int rc; | 171 | int rc; |
150 | 172 | ||
151 | if (urb->status != 0) | 173 | dprintk(2, "%s\n",__func__); |
152 | printk(KERN_INFO "not ready\n"); | 174 | if (urb->status < 0 || urb->actual_length <= 0) { |
153 | else if (urb->actual_length > 0) { | 175 | printk(KERN_INFO "tm6000: IR URB failure: status: %i, length %i\n", |
154 | memcpy(ir->urb_data, urb->transfer_buffer, urb->actual_length); | 176 | urb->status, urb->actual_length); |
177 | ir->submit_urb = 1; | ||
178 | schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY)); | ||
179 | return; | ||
180 | } | ||
181 | buf = urb->transfer_buffer; | ||
155 | 182 | ||
156 | dprintk("data %02x %02x %02x %02x\n", ir->urb_data[0], | 183 | if (ir_debug) |
157 | ir->urb_data[1], ir->urb_data[2], ir->urb_data[3]); | 184 | print_hex_dump(KERN_DEBUG, "tm6000: IR data: ", |
185 | DUMP_PREFIX_OFFSET,16, 1, | ||
186 | buf, urb->actual_length, false); | ||
158 | 187 | ||
159 | ir->key = 1; | 188 | poll_result.rc_data = buf[0]; |
160 | } | 189 | if (urb->actual_length > 1) |
190 | poll_result.rc_data |= buf[1] << 8; | ||
191 | |||
192 | dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data); | ||
193 | rc_keydown(ir->rc, poll_result.rc_data, 0); | ||
161 | 194 | ||
162 | rc = usb_submit_urb(urb, GFP_ATOMIC); | 195 | rc = usb_submit_urb(urb, GFP_ATOMIC); |
196 | /* | ||
197 | * Flash the led. We can't do it here, as it is running on IRQ context. | ||
198 | * So, use the scheduler to do it, in a few ms. | ||
199 | */ | ||
200 | ir->pwled = 2; | ||
201 | schedule_delayed_work(&ir->work, msecs_to_jiffies(10)); | ||
163 | } | 202 | } |
164 | 203 | ||
165 | static int default_polling_getkey(struct tm6000_IR *ir, | 204 | static void tm6000_ir_handle_key(struct work_struct *work) |
166 | struct tm6000_ir_poll_result *poll_result) | ||
167 | { | 205 | { |
206 | struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work); | ||
168 | struct tm6000_core *dev = ir->dev; | 207 | struct tm6000_core *dev = ir->dev; |
208 | struct tm6000_ir_poll_result poll_result; | ||
169 | int rc; | 209 | int rc; |
170 | u8 buf[2]; | 210 | u8 buf[2]; |
171 | 211 | ||
172 | if (ir->wait && !&dev->int_in) | 212 | if (ir->wait) |
173 | return 0; | 213 | return; |
174 | |||
175 | if (&dev->int_in) { | ||
176 | switch (ir->rc_type) { | ||
177 | case RC_TYPE_RC5: | ||
178 | poll_result->rc_data = ir->urb_data[0]; | ||
179 | break; | ||
180 | case RC_TYPE_NEC: | ||
181 | if (ir->urb_data[1] == ((ir->key_addr >> 8) & 0xff)) { | ||
182 | poll_result->rc_data = ir->urb_data[0] | ||
183 | | ir->urb_data[1] << 8; | ||
184 | } | ||
185 | break; | ||
186 | default: | ||
187 | poll_result->rc_data = ir->urb_data[0] | ||
188 | | ir->urb_data[1] << 8; | ||
189 | break; | ||
190 | } | ||
191 | } else { | ||
192 | tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); | ||
193 | msleep(10); | ||
194 | tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 1); | ||
195 | msleep(10); | ||
196 | |||
197 | if (ir->rc_type == RC_TYPE_RC5) { | ||
198 | rc = tm6000_read_write_usb(dev, USB_DIR_IN | | ||
199 | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
200 | REQ_02_GET_IR_CODE, 0, 0, buf, 1); | ||
201 | |||
202 | msleep(10); | ||
203 | |||
204 | dprintk("read data=%02x\n", buf[0]); | ||
205 | if (rc < 0) | ||
206 | return rc; | ||
207 | 214 | ||
208 | poll_result->rc_data = buf[0]; | 215 | dprintk(3, "%s\n",__func__); |
209 | } else { | ||
210 | rc = tm6000_read_write_usb(dev, USB_DIR_IN | | ||
211 | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
212 | REQ_02_GET_IR_CODE, 0, 0, buf, 2); | ||
213 | 216 | ||
214 | msleep(10); | 217 | rc = tm6000_read_write_usb(dev, USB_DIR_IN | |
218 | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
219 | REQ_02_GET_IR_CODE, 0, 0, buf, 2); | ||
220 | if (rc < 0) | ||
221 | return; | ||
215 | 222 | ||
216 | dprintk("read data=%04x\n", buf[0] | buf[1] << 8); | 223 | if (rc > 1) |
217 | if (rc < 0) | 224 | poll_result.rc_data = buf[0] | buf[1] << 8; |
218 | return rc; | 225 | else |
226 | poll_result.rc_data = buf[0]; | ||
219 | 227 | ||
220 | poll_result->rc_data = buf[0] | buf[1] << 8; | 228 | /* Check if something was read */ |
229 | if ((poll_result.rc_data & 0xff) == 0xff) { | ||
230 | if (!ir->pwled) { | ||
231 | tm6000_flash_led(dev, 1); | ||
232 | ir->pwled = 1; | ||
221 | } | 233 | } |
222 | if ((poll_result->rc_data & 0x00ff) != 0xff) | 234 | return; |
223 | ir->key = 1; | ||
224 | } | 235 | } |
225 | return 0; | 236 | |
237 | dprintk(1, "%s, scancode: 0x%04x\n",__func__, poll_result.rc_data); | ||
238 | rc_keydown(ir->rc, poll_result.rc_data, 0); | ||
239 | tm6000_flash_led(dev, 0); | ||
240 | ir->pwled = 0; | ||
241 | |||
242 | /* Re-schedule polling */ | ||
243 | schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); | ||
226 | } | 244 | } |
227 | 245 | ||
228 | static void tm6000_ir_handle_key(struct tm6000_IR *ir) | 246 | static void tm6000_ir_int_work(struct work_struct *work) |
229 | { | 247 | { |
248 | struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work); | ||
230 | struct tm6000_core *dev = ir->dev; | 249 | struct tm6000_core *dev = ir->dev; |
231 | int result; | 250 | int rc; |
232 | struct tm6000_ir_poll_result poll_result; | ||
233 | 251 | ||
234 | /* read the registers containing the IR status */ | 252 | dprintk(3, "%s, submit_urb = %d, pwled = %d\n",__func__, ir->submit_urb, |
235 | result = ir->get_key(ir, &poll_result); | 253 | ir->pwled); |
236 | if (result < 0) { | ||
237 | printk(KERN_INFO "ir->get_key() failed %d\n", result); | ||
238 | return; | ||
239 | } | ||
240 | 254 | ||
241 | dprintk("ir->get_key result data=%04x\n", poll_result.rc_data); | 255 | if (ir->submit_urb) { |
256 | dprintk(3, "Resubmit urb\n"); | ||
257 | tm6000_set_reg(dev, REQ_04_EN_DISABLE_MCU_INT, 2, 0); | ||
242 | 258 | ||
243 | if (ir->pwled) { | 259 | rc = usb_submit_urb(ir->int_urb, GFP_ATOMIC); |
244 | if (ir->pwledcnt >= PWLED_OFF) { | 260 | if (rc < 0) { |
245 | ir->pwled = 0; | 261 | printk(KERN_ERR "tm6000: Can't submit an IR interrupt. Error %i\n", |
246 | ir->pwledcnt = 0; | 262 | rc); |
247 | tm6000_flash_led(dev, 1); | 263 | /* Retry in 100 ms */ |
248 | } else | 264 | schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY)); |
249 | ir->pwledcnt += 1; | 265 | return; |
266 | } | ||
267 | ir->submit_urb = 0; | ||
250 | } | 268 | } |
251 | 269 | ||
252 | if (ir->key) { | 270 | /* Led is enabled only if USB submit doesn't fail */ |
253 | rc_keydown(ir->rc, poll_result.rc_data, 0); | 271 | if (ir->pwled == 2) { |
254 | ir->key = 0; | ||
255 | ir->pwled = 1; | ||
256 | ir->pwledcnt = 0; | ||
257 | tm6000_flash_led(dev, 0); | 272 | tm6000_flash_led(dev, 0); |
273 | ir->pwled = 0; | ||
274 | schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_INT_LED_DELAY)); | ||
275 | } else if (!ir->pwled) { | ||
276 | tm6000_flash_led(dev, 1); | ||
277 | ir->pwled = 1; | ||
258 | } | 278 | } |
259 | return; | ||
260 | } | ||
261 | |||
262 | static void tm6000_ir_work(struct work_struct *work) | ||
263 | { | ||
264 | struct tm6000_IR *ir = container_of(work, struct tm6000_IR, work.work); | ||
265 | |||
266 | tm6000_ir_handle_key(ir); | ||
267 | schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling)); | ||
268 | } | 279 | } |
269 | 280 | ||
270 | static int tm6000_ir_start(struct rc_dev *rc) | 281 | static int tm6000_ir_start(struct rc_dev *rc) |
271 | { | 282 | { |
272 | struct tm6000_IR *ir = rc->priv; | 283 | struct tm6000_IR *ir = rc->priv; |
273 | 284 | ||
274 | INIT_DELAYED_WORK(&ir->work, tm6000_ir_work); | 285 | dprintk(2, "%s\n",__func__); |
286 | |||
275 | schedule_delayed_work(&ir->work, 0); | 287 | schedule_delayed_work(&ir->work, 0); |
276 | 288 | ||
277 | return 0; | 289 | return 0; |
@@ -281,6 +293,8 @@ static void tm6000_ir_stop(struct rc_dev *rc) | |||
281 | { | 293 | { |
282 | struct tm6000_IR *ir = rc->priv; | 294 | struct tm6000_IR *ir = rc->priv; |
283 | 295 | ||
296 | dprintk(2, "%s\n",__func__); | ||
297 | |||
284 | cancel_delayed_work_sync(&ir->work); | 298 | cancel_delayed_work_sync(&ir->work); |
285 | } | 299 | } |
286 | 300 | ||
@@ -291,10 +305,11 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type) | |||
291 | if (!ir) | 305 | if (!ir) |
292 | return 0; | 306 | return 0; |
293 | 307 | ||
308 | dprintk(2, "%s\n",__func__); | ||
309 | |||
294 | if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC)) | 310 | if ((rc->rc_map.scan) && (rc_type == RC_TYPE_NEC)) |
295 | ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff); | 311 | ir->key_addr = ((rc->rc_map.scan[0].scancode >> 8) & 0xffff); |
296 | 312 | ||
297 | ir->get_key = default_polling_getkey; | ||
298 | ir->rc_type = rc_type; | 313 | ir->rc_type = rc_type; |
299 | 314 | ||
300 | tm6000_ir_config(ir); | 315 | tm6000_ir_config(ir); |
@@ -302,17 +317,19 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type) | |||
302 | return 0; | 317 | return 0; |
303 | } | 318 | } |
304 | 319 | ||
305 | int tm6000_ir_int_start(struct tm6000_core *dev) | 320 | static int __tm6000_ir_int_start(struct rc_dev *rc) |
306 | { | 321 | { |
307 | struct tm6000_IR *ir = dev->ir; | 322 | struct tm6000_IR *ir = rc->priv; |
323 | struct tm6000_core *dev = ir->dev; | ||
308 | int pipe, size; | 324 | int pipe, size; |
309 | int err = -ENOMEM; | 325 | int err = -ENOMEM; |
310 | 326 | ||
311 | |||
312 | if (!ir) | 327 | if (!ir) |
313 | return -ENODEV; | 328 | return -ENODEV; |
314 | 329 | ||
315 | ir->int_urb = usb_alloc_urb(0, GFP_KERNEL); | 330 | dprintk(2, "%s\n",__func__); |
331 | |||
332 | ir->int_urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
316 | if (!ir->int_urb) | 333 | if (!ir->int_urb) |
317 | return -ENOMEM; | 334 | return -ENOMEM; |
318 | 335 | ||
@@ -321,42 +338,59 @@ int tm6000_ir_int_start(struct tm6000_core *dev) | |||
321 | & USB_ENDPOINT_NUMBER_MASK); | 338 | & USB_ENDPOINT_NUMBER_MASK); |
322 | 339 | ||
323 | size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); | 340 | size = usb_maxpacket(dev->udev, pipe, usb_pipeout(pipe)); |
324 | dprintk("IR max size: %d\n", size); | 341 | dprintk(1, "IR max size: %d\n", size); |
325 | 342 | ||
326 | ir->int_urb->transfer_buffer = kzalloc(size, GFP_KERNEL); | 343 | ir->int_urb->transfer_buffer = kzalloc(size, GFP_ATOMIC); |
327 | if (ir->int_urb->transfer_buffer == NULL) { | 344 | if (ir->int_urb->transfer_buffer == NULL) { |
328 | usb_free_urb(ir->int_urb); | 345 | usb_free_urb(ir->int_urb); |
329 | return err; | 346 | return err; |
330 | } | 347 | } |
331 | dprintk("int interval: %d\n", dev->int_in.endp->desc.bInterval); | 348 | dprintk(1, "int interval: %d\n", dev->int_in.endp->desc.bInterval); |
349 | |||
332 | usb_fill_int_urb(ir->int_urb, dev->udev, pipe, | 350 | usb_fill_int_urb(ir->int_urb, dev->udev, pipe, |
333 | ir->int_urb->transfer_buffer, size, | 351 | ir->int_urb->transfer_buffer, size, |
334 | tm6000_ir_urb_received, dev, | 352 | tm6000_ir_urb_received, dev, |
335 | dev->int_in.endp->desc.bInterval); | 353 | dev->int_in.endp->desc.bInterval); |
336 | err = usb_submit_urb(ir->int_urb, GFP_KERNEL); | 354 | |
337 | if (err) { | 355 | ir->submit_urb = 1; |
338 | kfree(ir->int_urb->transfer_buffer); | 356 | schedule_delayed_work(&ir->work, msecs_to_jiffies(URB_SUBMIT_DELAY)); |
339 | usb_free_urb(ir->int_urb); | ||
340 | return err; | ||
341 | } | ||
342 | ir->urb_data = kzalloc(size, GFP_KERNEL); | ||
343 | 357 | ||
344 | return 0; | 358 | return 0; |
345 | } | 359 | } |
346 | 360 | ||
347 | void tm6000_ir_int_stop(struct tm6000_core *dev) | 361 | static void __tm6000_ir_int_stop(struct rc_dev *rc) |
348 | { | 362 | { |
349 | struct tm6000_IR *ir = dev->ir; | 363 | struct tm6000_IR *ir = rc->priv; |
350 | 364 | ||
351 | if (!ir) | 365 | if (!ir || !ir->int_urb) |
352 | return; | 366 | return; |
353 | 367 | ||
368 | dprintk(2, "%s\n",__func__); | ||
369 | |||
354 | usb_kill_urb(ir->int_urb); | 370 | usb_kill_urb(ir->int_urb); |
355 | kfree(ir->int_urb->transfer_buffer); | 371 | kfree(ir->int_urb->transfer_buffer); |
356 | usb_free_urb(ir->int_urb); | 372 | usb_free_urb(ir->int_urb); |
357 | ir->int_urb = NULL; | 373 | ir->int_urb = NULL; |
358 | kfree(ir->urb_data); | 374 | } |
359 | ir->urb_data = NULL; | 375 | |
376 | int tm6000_ir_int_start(struct tm6000_core *dev) | ||
377 | { | ||
378 | struct tm6000_IR *ir = dev->ir; | ||
379 | |||
380 | if (!ir) | ||
381 | return 0; | ||
382 | |||
383 | return __tm6000_ir_int_start(ir->rc); | ||
384 | } | ||
385 | |||
386 | void tm6000_ir_int_stop(struct tm6000_core *dev) | ||
387 | { | ||
388 | struct tm6000_IR *ir = dev->ir; | ||
389 | |||
390 | if (!ir || !ir->rc) | ||
391 | return; | ||
392 | |||
393 | __tm6000_ir_int_stop(ir->rc); | ||
360 | } | 394 | } |
361 | 395 | ||
362 | int tm6000_ir_init(struct tm6000_core *dev) | 396 | int tm6000_ir_init(struct tm6000_core *dev) |
@@ -374,29 +408,36 @@ int tm6000_ir_init(struct tm6000_core *dev) | |||
374 | if (!dev->ir_codes) | 408 | if (!dev->ir_codes) |
375 | return 0; | 409 | return 0; |
376 | 410 | ||
377 | ir = kzalloc(sizeof(*ir), GFP_KERNEL); | 411 | ir = kzalloc(sizeof(*ir), GFP_ATOMIC); |
378 | rc = rc_allocate_device(); | 412 | rc = rc_allocate_device(); |
379 | if (!ir || !rc) | 413 | if (!ir || !rc) |
380 | goto out; | 414 | goto out; |
381 | 415 | ||
416 | dprintk(2, "%s\n", __func__); | ||
417 | |||
382 | /* record handles to ourself */ | 418 | /* record handles to ourself */ |
383 | ir->dev = dev; | 419 | ir->dev = dev; |
384 | dev->ir = ir; | 420 | dev->ir = ir; |
385 | ir->rc = rc; | 421 | ir->rc = rc; |
386 | 422 | ||
387 | /* input einrichten */ | 423 | /* input setup */ |
388 | rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC; | 424 | rc->allowed_protos = RC_TYPE_RC5 | RC_TYPE_NEC; |
425 | /* Neded, in order to support NEC remotes with 24 or 32 bits */ | ||
426 | rc->scanmask = 0xffff; | ||
389 | rc->priv = ir; | 427 | rc->priv = ir; |
390 | rc->change_protocol = tm6000_ir_change_protocol; | 428 | rc->change_protocol = tm6000_ir_change_protocol; |
391 | rc->open = tm6000_ir_start; | 429 | if (dev->int_in.endp) { |
392 | rc->close = tm6000_ir_stop; | 430 | rc->open = __tm6000_ir_int_start; |
431 | rc->close = __tm6000_ir_int_stop; | ||
432 | INIT_DELAYED_WORK(&ir->work, tm6000_ir_int_work); | ||
433 | } else { | ||
434 | rc->open = tm6000_ir_start; | ||
435 | rc->close = tm6000_ir_stop; | ||
436 | ir->polling = 50; | ||
437 | INIT_DELAYED_WORK(&ir->work, tm6000_ir_handle_key); | ||
438 | } | ||
393 | rc->driver_type = RC_DRIVER_SCANCODE; | 439 | rc->driver_type = RC_DRIVER_SCANCODE; |
394 | 440 | ||
395 | ir->polling = 50; | ||
396 | ir->pwled = 0; | ||
397 | ir->pwledcnt = 0; | ||
398 | |||
399 | |||
400 | snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)", | 441 | snprintf(ir->name, sizeof(ir->name), "tm5600/60x0 IR (%s)", |
401 | dev->name); | 442 | dev->name); |
402 | 443 | ||
@@ -415,15 +456,6 @@ int tm6000_ir_init(struct tm6000_core *dev) | |||
415 | rc->driver_name = "tm6000"; | 456 | rc->driver_name = "tm6000"; |
416 | rc->dev.parent = &dev->udev->dev; | 457 | rc->dev.parent = &dev->udev->dev; |
417 | 458 | ||
418 | if (&dev->int_in) { | ||
419 | dprintk("IR over int\n"); | ||
420 | |||
421 | err = tm6000_ir_int_start(dev); | ||
422 | |||
423 | if (err) | ||
424 | goto out; | ||
425 | } | ||
426 | |||
427 | /* ir register */ | 459 | /* ir register */ |
428 | err = rc_register_device(rc); | 460 | err = rc_register_device(rc); |
429 | if (err) | 461 | if (err) |
@@ -447,10 +479,19 @@ int tm6000_ir_fini(struct tm6000_core *dev) | |||
447 | if (!ir) | 479 | if (!ir) |
448 | return 0; | 480 | return 0; |
449 | 481 | ||
482 | dprintk(2, "%s\n",__func__); | ||
483 | |||
450 | rc_unregister_device(ir->rc); | 484 | rc_unregister_device(ir->rc); |
451 | 485 | ||
452 | if (ir->int_urb) | 486 | if (!ir->polling) |
453 | tm6000_ir_int_stop(dev); | 487 | __tm6000_ir_int_stop(ir->rc); |
488 | |||
489 | tm6000_ir_stop(ir->rc); | ||
490 | |||
491 | /* Turn off the led */ | ||
492 | tm6000_flash_led(dev, 0); | ||
493 | ir->pwled = 0; | ||
494 | |||
454 | 495 | ||
455 | kfree(ir); | 496 | kfree(ir); |
456 | dev->ir = NULL; | 497 | dev->ir = NULL; |
diff --git a/drivers/media/video/tm6000/tm6000-regs.h b/drivers/media/video/tm6000/tm6000-regs.h index 7f491b6de933..a38c251ed57b 100644 --- a/drivers/media/video/tm6000/tm6000-regs.h +++ b/drivers/media/video/tm6000/tm6000-regs.h | |||
@@ -284,19 +284,19 @@ enum { | |||
284 | /* ONLY for TM6010 */ | 284 | /* ONLY for TM6010 */ |
285 | #define TM6010_REQ07_RD8_IR 0x07, 0xd8 | 285 | #define TM6010_REQ07_RD8_IR 0x07, 0xd8 |
286 | /* ONLY for TM6010 */ | 286 | /* ONLY for TM6010 */ |
287 | #define TM6010_REQ07_RD8_IR_BSIZE 0x07, 0xd9 | 287 | #define TM6010_REQ07_RD9_IR_BSIZE 0x07, 0xd9 |
288 | /* ONLY for TM6010 */ | 288 | /* ONLY for TM6010 */ |
289 | #define TM6010_REQ07_RD8_IR_WAKEUP_SEL 0x07, 0xda | 289 | #define TM6010_REQ07_RDA_IR_WAKEUP_SEL 0x07, 0xda |
290 | /* ONLY for TM6010 */ | 290 | /* ONLY for TM6010 */ |
291 | #define TM6010_REQ07_RD8_IR_WAKEUP_ADD 0x07, 0xdb | 291 | #define TM6010_REQ07_RDB_IR_WAKEUP_ADD 0x07, 0xdb |
292 | /* ONLY for TM6010 */ | 292 | /* ONLY for TM6010 */ |
293 | #define TM6010_REQ07_RD8_IR_LEADER1 0x07, 0xdc | 293 | #define TM6010_REQ07_RDC_IR_LEADER1 0x07, 0xdc |
294 | /* ONLY for TM6010 */ | 294 | /* ONLY for TM6010 */ |
295 | #define TM6010_REQ07_RD8_IR_LEADER0 0x07, 0xdd | 295 | #define TM6010_REQ07_RDD_IR_LEADER0 0x07, 0xdd |
296 | /* ONLY for TM6010 */ | 296 | /* ONLY for TM6010 */ |
297 | #define TM6010_REQ07_RD8_IR_PULSE_CNT1 0x07, 0xde | 297 | #define TM6010_REQ07_RDE_IR_PULSE_CNT1 0x07, 0xde |
298 | /* ONLY for TM6010 */ | 298 | /* ONLY for TM6010 */ |
299 | #define TM6010_REQ07_RD8_IR_PULSE_CNT0 0x07, 0xdf | 299 | #define TM6010_REQ07_RDF_IR_PULSE_CNT0 0x07, 0xdf |
300 | /* ONLY for TM6010 */ | 300 | /* ONLY for TM6010 */ |
301 | #define TM6010_REQ07_RE0_DVIDEO_SOURCE 0x07, 0xe0 | 301 | #define TM6010_REQ07_RE0_DVIDEO_SOURCE 0x07, 0xe0 |
302 | /* ONLY for TM6010 */ | 302 | /* ONLY for TM6010 */ |
diff --git a/drivers/media/video/tm6000/tm6000-stds.c b/drivers/media/video/tm6000/tm6000-stds.c index 9a4145dc3d87..9dc0831d813f 100644 --- a/drivers/media/video/tm6000/tm6000-stds.c +++ b/drivers/media/video/tm6000/tm6000-stds.c | |||
@@ -361,82 +361,51 @@ static int tm6000_set_audio_std(struct tm6000_core *dev) | |||
361 | return 0; | 361 | return 0; |
362 | } | 362 | } |
363 | 363 | ||
364 | switch (tm6010_a_mode) { | 364 | /* |
365 | * STD/MN shouldn't be affected by tm6010_a_mode, as there's just one | ||
366 | * audio standard for each V4L2_STD type. | ||
367 | */ | ||
368 | if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_KR) { | ||
369 | areg_05 |= 0x04; | ||
370 | } else if ((dev->norm & V4L2_STD_NTSC) == V4L2_STD_NTSC_M_JP) { | ||
371 | areg_05 |= 0x43; | ||
372 | } else if (dev->norm & V4L2_STD_MN) { | ||
373 | areg_05 |= 0x22; | ||
374 | } else switch (tm6010_a_mode) { | ||
365 | /* auto */ | 375 | /* auto */ |
366 | case 0: | 376 | case 0: |
367 | switch (dev->norm) { | 377 | if ((dev->norm & V4L2_STD_SECAM) == V4L2_STD_SECAM_L) |
368 | case V4L2_STD_NTSC_M_KR: | ||
369 | areg_05 |= 0x00; | 378 | areg_05 |= 0x00; |
370 | break; | 379 | else /* Other PAL/SECAM standards */ |
371 | case V4L2_STD_NTSC_M_JP: | ||
372 | areg_05 |= 0x40; | ||
373 | break; | ||
374 | case V4L2_STD_NTSC_M: | ||
375 | case V4L2_STD_PAL_M: | ||
376 | case V4L2_STD_PAL_N: | ||
377 | areg_05 |= 0x20; | ||
378 | break; | ||
379 | case V4L2_STD_PAL_Nc: | ||
380 | areg_05 |= 0x60; | ||
381 | break; | ||
382 | case V4L2_STD_SECAM_L: | ||
383 | areg_05 |= 0x00; | ||
384 | break; | ||
385 | case V4L2_STD_DK: | ||
386 | areg_05 |= 0x10; | 380 | areg_05 |= 0x10; |
387 | break; | ||
388 | } | ||
389 | break; | 381 | break; |
390 | /* A2 */ | 382 | /* A2 */ |
391 | case 1: | 383 | case 1: |
392 | switch (dev->norm) { | 384 | if (dev->norm & V4L2_STD_DK) |
393 | case V4L2_STD_B: | ||
394 | case V4L2_STD_GH: | ||
395 | areg_05 = 0x05; | ||
396 | break; | ||
397 | case V4L2_STD_DK: | ||
398 | areg_05 = 0x09; | 385 | areg_05 = 0x09; |
399 | break; | 386 | else |
400 | } | 387 | areg_05 = 0x05; |
401 | break; | 388 | break; |
402 | /* NICAM */ | 389 | /* NICAM */ |
403 | case 2: | 390 | case 2: |
404 | switch (dev->norm) { | 391 | if (dev->norm & V4L2_STD_DK) { |
405 | case V4L2_STD_B: | ||
406 | case V4L2_STD_GH: | ||
407 | areg_05 = 0x07; | ||
408 | break; | ||
409 | case V4L2_STD_DK: | ||
410 | areg_05 = 0x06; | 392 | areg_05 = 0x06; |
411 | break; | 393 | } else if (dev->norm & V4L2_STD_PAL_I) { |
412 | case V4L2_STD_PAL_I: | ||
413 | areg_05 = 0x08; | 394 | areg_05 = 0x08; |
414 | break; | 395 | } else if (dev->norm & V4L2_STD_SECAM_L) { |
415 | case V4L2_STD_SECAM_L: | ||
416 | areg_05 = 0x0a; | 396 | areg_05 = 0x0a; |
417 | areg_02 = 0x02; | 397 | areg_02 = 0x02; |
418 | break; | 398 | } else { |
399 | areg_05 = 0x07; | ||
419 | } | 400 | } |
420 | nicam_flag = 1; | 401 | nicam_flag = 1; |
421 | break; | 402 | break; |
422 | /* other */ | 403 | /* other */ |
423 | case 3: | 404 | case 3: |
424 | switch (dev->norm) { | 405 | if (dev->norm & V4L2_STD_DK) { |
425 | /* DK3_A2 */ | ||
426 | case V4L2_STD_DK: | ||
427 | areg_05 = 0x0b; | 406 | areg_05 = 0x0b; |
428 | break; | 407 | } else { |
429 | /* Korea */ | ||
430 | case V4L2_STD_NTSC_M_KR: | ||
431 | areg_05 = 0x04; | ||
432 | break; | ||
433 | /* EIAJ */ | ||
434 | case V4L2_STD_NTSC_M_JP: | ||
435 | areg_05 = 0x03; | ||
436 | break; | ||
437 | default: | ||
438 | areg_05 = 0x02; | 408 | areg_05 = 0x02; |
439 | break; | ||
440 | } | 409 | } |
441 | break; | 410 | break; |
442 | } | 411 | } |
@@ -557,10 +526,16 @@ int tm6000_set_standard(struct tm6000_core *dev) | |||
557 | case TM6000_AMUX_ADC1: | 526 | case TM6000_AMUX_ADC1: |
558 | tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, | 527 | tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, |
559 | 0x00, 0x0f); | 528 | 0x00, 0x0f); |
529 | /* Mux overflow workaround */ | ||
530 | tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, | ||
531 | 0x10, 0xf0); | ||
560 | break; | 532 | break; |
561 | case TM6000_AMUX_ADC2: | 533 | case TM6000_AMUX_ADC2: |
562 | tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, | 534 | tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, |
563 | 0x08, 0x0f); | 535 | 0x08, 0x0f); |
536 | /* Mux overflow workaround */ | ||
537 | tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, | ||
538 | 0x10, 0xf0); | ||
564 | break; | 539 | break; |
565 | case TM6000_AMUX_SIF1: | 540 | case TM6000_AMUX_SIF1: |
566 | reg_08_e2 |= 0x02; | 541 | reg_08_e2 |= 0x02; |
@@ -570,6 +545,9 @@ int tm6000_set_standard(struct tm6000_core *dev) | |||
570 | tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3); | 545 | tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf3); |
571 | tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, | 546 | tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, |
572 | 0x02, 0x0f); | 547 | 0x02, 0x0f); |
548 | /* Mux overflow workaround */ | ||
549 | tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, | ||
550 | 0x30, 0xf0); | ||
573 | break; | 551 | break; |
574 | case TM6000_AMUX_SIF2: | 552 | case TM6000_AMUX_SIF2: |
575 | reg_08_e2 |= 0x02; | 553 | reg_08_e2 |= 0x02; |
@@ -579,6 +557,9 @@ int tm6000_set_standard(struct tm6000_core *dev) | |||
579 | tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf7); | 557 | tm6000_set_reg(dev, TM6010_REQ08_RE4_ADC_IN2_SEL, 0xf7); |
580 | tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, | 558 | tm6000_set_reg_mask(dev, TM6010_REQ08_RF0_DAUDIO_INPUT_CONFIG, |
581 | 0x02, 0x0f); | 559 | 0x02, 0x0f); |
560 | /* Mux overflow workaround */ | ||
561 | tm6000_set_reg_mask(dev, TM6010_REQ07_R07_OUTPUT_CONTROL, | ||
562 | 0x30, 0xf0); | ||
582 | break; | 563 | break; |
583 | default: | 564 | default: |
584 | break; | 565 | break; |
diff --git a/drivers/media/video/tm6000/tm6000-video.c b/drivers/media/video/tm6000/tm6000-video.c index 1e5ace0b5d10..bc13db736e24 100644 --- a/drivers/media/video/tm6000/tm6000-video.c +++ b/drivers/media/video/tm6000/tm6000-video.c | |||
@@ -1605,16 +1605,25 @@ static int tm6000_release(struct file *file) | |||
1605 | res_free(dev, fh); | 1605 | res_free(dev, fh); |
1606 | 1606 | ||
1607 | if (!dev->users) { | 1607 | if (!dev->users) { |
1608 | int err; | ||
1609 | |||
1610 | tm6000_uninit_isoc(dev); | 1608 | tm6000_uninit_isoc(dev); |
1611 | 1609 | ||
1610 | /* Stop interrupt USB pipe */ | ||
1611 | tm6000_ir_int_stop(dev); | ||
1612 | |||
1613 | usb_reset_configuration(dev->udev); | ||
1614 | |||
1615 | if (dev->int_in.endp) | ||
1616 | usb_set_interface(dev->udev, | ||
1617 | dev->isoc_in.bInterfaceNumber, 2); | ||
1618 | else | ||
1619 | usb_set_interface(dev->udev, | ||
1620 | dev->isoc_in.bInterfaceNumber, 0); | ||
1621 | |||
1622 | /* Start interrupt USB pipe */ | ||
1623 | tm6000_ir_int_start(dev); | ||
1624 | |||
1612 | if (!fh->radio) | 1625 | if (!fh->radio) |
1613 | videobuf_mmap_free(&fh->vb_vidq); | 1626 | videobuf_mmap_free(&fh->vb_vidq); |
1614 | |||
1615 | err = tm6000_reset(dev); | ||
1616 | if (err < 0) | ||
1617 | dev_err(&vdev->dev, "reset failed: %d\n", err); | ||
1618 | } | 1627 | } |
1619 | 1628 | ||
1620 | kfree(fh); | 1629 | kfree(fh); |
diff --git a/drivers/media/video/tm6000/tm6000.h b/drivers/media/video/tm6000/tm6000.h index 2777e514eff2..27ba659cfa85 100644 --- a/drivers/media/video/tm6000/tm6000.h +++ b/drivers/media/video/tm6000/tm6000.h | |||
@@ -188,6 +188,9 @@ struct tm6000_core { | |||
188 | /* Device Capabilities*/ | 188 | /* Device Capabilities*/ |
189 | struct tm6000_capabilities caps; | 189 | struct tm6000_capabilities caps; |
190 | 190 | ||
191 | /* Used to load alsa/dvb */ | ||
192 | struct work_struct request_module_wk; | ||
193 | |||
191 | /* Tuner configuration */ | 194 | /* Tuner configuration */ |
192 | int tuner_type; /* type of the tuner */ | 195 | int tuner_type; /* type of the tuner */ |
193 | int tuner_addr; /* tuner address */ | 196 | int tuner_addr; /* tuner address */ |
diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 11cc980b0cd5..4059ea178c2d 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c | |||
@@ -326,6 +326,7 @@ static void set_type(struct i2c_client *c, unsigned int type, | |||
326 | t->mode_mask = T_RADIO; | 326 | t->mode_mask = T_RADIO; |
327 | break; | 327 | break; |
328 | case TUNER_PHILIPS_FMD1216ME_MK3: | 328 | case TUNER_PHILIPS_FMD1216ME_MK3: |
329 | case TUNER_PHILIPS_FMD1216MEX_MK3: | ||
329 | buffer[0] = 0x0b; | 330 | buffer[0] = 0x0b; |
330 | buffer[1] = 0xdc; | 331 | buffer[1] = 0xdc; |
331 | buffer[2] = 0x9c; | 332 | buffer[2] = 0x9c; |
diff --git a/drivers/media/video/tvp5150.c b/drivers/media/video/tvp5150.c index 6abaa16ae136..6be9910a6e24 100644 --- a/drivers/media/video/tvp5150.c +++ b/drivers/media/video/tvp5150.c | |||
@@ -703,21 +703,21 @@ static int tvp5150_set_std(struct v4l2_subdev *sd, v4l2_std_id std) | |||
703 | /* First tests should be against specific std */ | 703 | /* First tests should be against specific std */ |
704 | 704 | ||
705 | if (std == V4L2_STD_ALL) { | 705 | if (std == V4L2_STD_ALL) { |
706 | fmt = 0; /* Autodetect mode */ | 706 | fmt = VIDEO_STD_AUTO_SWITCH_BIT; /* Autodetect mode */ |
707 | } else if (std & V4L2_STD_NTSC_443) { | 707 | } else if (std & V4L2_STD_NTSC_443) { |
708 | fmt = 0xa; | 708 | fmt = VIDEO_STD_NTSC_4_43_BIT; |
709 | } else if (std & V4L2_STD_PAL_M) { | 709 | } else if (std & V4L2_STD_PAL_M) { |
710 | fmt = 0x6; | 710 | fmt = VIDEO_STD_PAL_M_BIT; |
711 | } else if (std & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { | 711 | } else if (std & (V4L2_STD_PAL_N | V4L2_STD_PAL_Nc)) { |
712 | fmt = 0x8; | 712 | fmt = VIDEO_STD_PAL_COMBINATION_N_BIT; |
713 | } else { | 713 | } else { |
714 | /* Then, test against generic ones */ | 714 | /* Then, test against generic ones */ |
715 | if (std & V4L2_STD_NTSC) | 715 | if (std & V4L2_STD_NTSC) |
716 | fmt = 0x2; | 716 | fmt = VIDEO_STD_NTSC_MJ_BIT; |
717 | else if (std & V4L2_STD_PAL) | 717 | else if (std & V4L2_STD_PAL) |
718 | fmt = 0x4; | 718 | fmt = VIDEO_STD_PAL_BDGHIN_BIT; |
719 | else if (std & V4L2_STD_SECAM) | 719 | else if (std & V4L2_STD_SECAM) |
720 | fmt = 0xc; | 720 | fmt = VIDEO_STD_SECAM_BIT; |
721 | } | 721 | } |
722 | 722 | ||
723 | v4l2_dbg(1, debug, sd, "Set video std register to %d.\n", fmt); | 723 | v4l2_dbg(1, debug, sd, "Set video std register to %d.\n", fmt); |
@@ -779,6 +779,70 @@ static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl) | |||
779 | return -EINVAL; | 779 | return -EINVAL; |
780 | } | 780 | } |
781 | 781 | ||
782 | static v4l2_std_id tvp5150_read_std(struct v4l2_subdev *sd) | ||
783 | { | ||
784 | int val = tvp5150_read(sd, TVP5150_STATUS_REG_5); | ||
785 | |||
786 | switch (val & 0x0F) { | ||
787 | case 0x01: | ||
788 | return V4L2_STD_NTSC; | ||
789 | case 0x03: | ||
790 | return V4L2_STD_PAL; | ||
791 | case 0x05: | ||
792 | return V4L2_STD_PAL_M; | ||
793 | case 0x07: | ||
794 | return V4L2_STD_PAL_N | V4L2_STD_PAL_Nc; | ||
795 | case 0x09: | ||
796 | return V4L2_STD_NTSC_443; | ||
797 | case 0xb: | ||
798 | return V4L2_STD_SECAM; | ||
799 | default: | ||
800 | return V4L2_STD_UNKNOWN; | ||
801 | } | ||
802 | } | ||
803 | |||
804 | static int tvp5150_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index, | ||
805 | enum v4l2_mbus_pixelcode *code) | ||
806 | { | ||
807 | if (index) | ||
808 | return -EINVAL; | ||
809 | |||
810 | *code = V4L2_MBUS_FMT_YUYV8_2X8; | ||
811 | return 0; | ||
812 | } | ||
813 | |||
814 | static int tvp5150_mbus_fmt(struct v4l2_subdev *sd, | ||
815 | struct v4l2_mbus_framefmt *f) | ||
816 | { | ||
817 | struct tvp5150 *decoder = to_tvp5150(sd); | ||
818 | v4l2_std_id std; | ||
819 | |||
820 | if (f == NULL) | ||
821 | return -EINVAL; | ||
822 | |||
823 | tvp5150_reset(sd, 0); | ||
824 | |||
825 | /* Calculate height and width based on current standard */ | ||
826 | if (decoder->norm == V4L2_STD_ALL) | ||
827 | std = tvp5150_read_std(sd); | ||
828 | else | ||
829 | std = decoder->norm; | ||
830 | |||
831 | f->width = 720; | ||
832 | if (std & V4L2_STD_525_60) | ||
833 | f->height = 480; | ||
834 | else | ||
835 | f->height = 576; | ||
836 | |||
837 | f->code = V4L2_MBUS_FMT_YUYV8_2X8; | ||
838 | f->field = V4L2_FIELD_SEQ_TB; | ||
839 | f->colorspace = V4L2_COLORSPACE_SMPTE170M; | ||
840 | |||
841 | v4l2_dbg(1, debug, sd, "width = %d, height = %d\n", f->width, | ||
842 | f->height); | ||
843 | return 0; | ||
844 | } | ||
845 | |||
782 | /**************************************************************************** | 846 | /**************************************************************************** |
783 | I2C Command | 847 | I2C Command |
784 | ****************************************************************************/ | 848 | ****************************************************************************/ |
@@ -931,6 +995,9 @@ static const struct v4l2_subdev_tuner_ops tvp5150_tuner_ops = { | |||
931 | 995 | ||
932 | static const struct v4l2_subdev_video_ops tvp5150_video_ops = { | 996 | static const struct v4l2_subdev_video_ops tvp5150_video_ops = { |
933 | .s_routing = tvp5150_s_routing, | 997 | .s_routing = tvp5150_s_routing, |
998 | .enum_mbus_fmt = tvp5150_enum_mbus_fmt, | ||
999 | .s_mbus_fmt = tvp5150_mbus_fmt, | ||
1000 | .try_mbus_fmt = tvp5150_mbus_fmt, | ||
934 | }; | 1001 | }; |
935 | 1002 | ||
936 | static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { | 1003 | static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = { |
diff --git a/drivers/media/video/usbvision/usbvision-i2c.c b/drivers/media/video/usbvision/usbvision-i2c.c index d7f97513b289..89fec029e924 100644 --- a/drivers/media/video/usbvision/usbvision-i2c.c +++ b/drivers/media/video/usbvision/usbvision-i2c.c | |||
@@ -110,42 +110,20 @@ static inline int usb_find_address(struct i2c_adapter *i2c_adap, | |||
110 | 110 | ||
111 | unsigned char addr; | 111 | unsigned char addr; |
112 | int ret; | 112 | int ret; |
113 | if ((flags & I2C_M_TEN)) { | ||
114 | /* a ten bit address */ | ||
115 | addr = 0xf0 | ((msg->addr >> 7) & 0x03); | ||
116 | /* try extended address code... */ | ||
117 | ret = try_write_address(i2c_adap, addr, retries); | ||
118 | if (ret != 1) { | ||
119 | dev_err(&i2c_adap->dev, | ||
120 | "died at extended address code, while writing\n"); | ||
121 | return -EREMOTEIO; | ||
122 | } | ||
123 | add[0] = addr; | ||
124 | if (flags & I2C_M_RD) { | ||
125 | /* okay, now switch into reading mode */ | ||
126 | addr |= 0x01; | ||
127 | ret = try_read_address(i2c_adap, addr, retries); | ||
128 | if (ret != 1) { | ||
129 | dev_err(&i2c_adap->dev, | ||
130 | "died at extended address code, while reading\n"); | ||
131 | return -EREMOTEIO; | ||
132 | } | ||
133 | } | ||
134 | 113 | ||
135 | } else { /* normal 7bit address */ | 114 | addr = (msg->addr << 1); |
136 | addr = (msg->addr << 1); | 115 | if (flags & I2C_M_RD) |
137 | if (flags & I2C_M_RD) | 116 | addr |= 1; |
138 | addr |= 1; | ||
139 | 117 | ||
140 | add[0] = addr; | 118 | add[0] = addr; |
141 | if (flags & I2C_M_RD) | 119 | if (flags & I2C_M_RD) |
142 | ret = try_read_address(i2c_adap, addr, retries); | 120 | ret = try_read_address(i2c_adap, addr, retries); |
143 | else | 121 | else |
144 | ret = try_write_address(i2c_adap, addr, retries); | 122 | ret = try_write_address(i2c_adap, addr, retries); |
123 | |||
124 | if (ret != 1) | ||
125 | return -EREMOTEIO; | ||
145 | 126 | ||
146 | if (ret != 1) | ||
147 | return -EREMOTEIO; | ||
148 | } | ||
149 | return 0; | 127 | return 0; |
150 | } | 128 | } |
151 | 129 | ||
@@ -184,7 +162,7 @@ usbvision_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msgs[], int num) | |||
184 | 162 | ||
185 | static u32 functionality(struct i2c_adapter *adap) | 163 | static u32 functionality(struct i2c_adapter *adap) |
186 | { | 164 | { |
187 | return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; | 165 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; |
188 | } | 166 | } |
189 | 167 | ||
190 | /* -----exported algorithm data: ------------------------------------- */ | 168 | /* -----exported algorithm data: ------------------------------------- */ |
diff --git a/drivers/media/video/uvc/Kconfig b/drivers/media/video/uvc/Kconfig index 2956a7637219..6c197da531b2 100644 --- a/drivers/media/video/uvc/Kconfig +++ b/drivers/media/video/uvc/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | config USB_VIDEO_CLASS | 1 | config USB_VIDEO_CLASS |
2 | tristate "USB Video Class (UVC)" | 2 | tristate "USB Video Class (UVC)" |
3 | select VIDEOBUF2_VMALLOC | ||
3 | ---help--- | 4 | ---help--- |
4 | Support for the USB Video Class (UVC). Currently only video | 5 | Support for the USB Video Class (UVC). Currently only video |
5 | input devices, such as webcams, are supported. | 6 | input devices, such as webcams, are supported. |
diff --git a/drivers/media/video/uvc/Makefile b/drivers/media/video/uvc/Makefile index 2071ca8a2f03..c26d12fdb8f4 100644 --- a/drivers/media/video/uvc/Makefile +++ b/drivers/media/video/uvc/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \ | 1 | uvcvideo-objs := uvc_driver.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_ctrl.o \ |
2 | uvc_status.o uvc_isight.o | 2 | uvc_status.o uvc_isight.o uvc_debugfs.o |
3 | ifeq ($(CONFIG_MEDIA_CONTROLLER),y) | 3 | ifeq ($(CONFIG_MEDIA_CONTROLLER),y) |
4 | uvcvideo-objs += uvc_entity.o | 4 | uvcvideo-objs += uvc_entity.o |
5 | endif | 5 | endif |
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 254d32688843..0efd3b10b353 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
@@ -878,8 +878,21 @@ static int uvc_ctrl_populate_cache(struct uvc_video_chain *chain, | |||
878 | chain->dev->intfnum, ctrl->info.selector, | 878 | chain->dev->intfnum, ctrl->info.selector, |
879 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), | 879 | uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), |
880 | ctrl->info.size); | 880 | ctrl->info.size); |
881 | if (ret < 0) | 881 | if (ret < 0) { |
882 | return ret; | 882 | if (UVC_ENTITY_TYPE(ctrl->entity) != |
883 | UVC_VC_EXTENSION_UNIT) | ||
884 | return ret; | ||
885 | |||
886 | /* GET_RES is mandatory for XU controls, but some | ||
887 | * cameras still choke on it. Ignore errors and set the | ||
888 | * resolution value to zero. | ||
889 | */ | ||
890 | uvc_warn_once(chain->dev, UVC_WARN_XU_GET_RES, | ||
891 | "UVC non compliance - GET_RES failed on " | ||
892 | "an XU control. Enabling workaround.\n"); | ||
893 | memset(uvc_ctrl_data(ctrl, UVC_CTRL_DATA_RES), 0, | ||
894 | ctrl->info.size); | ||
895 | } | ||
883 | } | 896 | } |
884 | 897 | ||
885 | ctrl->cached = 1; | 898 | ctrl->cached = 1; |
@@ -1861,7 +1874,7 @@ int uvc_ctrl_init_device(struct uvc_device *dev) | |||
1861 | if (ncontrols == 0) | 1874 | if (ncontrols == 0) |
1862 | continue; | 1875 | continue; |
1863 | 1876 | ||
1864 | entity->controls = kzalloc(ncontrols * sizeof(*ctrl), | 1877 | entity->controls = kcalloc(ncontrols, sizeof(*ctrl), |
1865 | GFP_KERNEL); | 1878 | GFP_KERNEL); |
1866 | if (entity->controls == NULL) | 1879 | if (entity->controls == NULL) |
1867 | return -ENOMEM; | 1880 | return -ENOMEM; |
diff --git a/drivers/media/video/uvc/uvc_debugfs.c b/drivers/media/video/uvc/uvc_debugfs.c new file mode 100644 index 000000000000..14561a5abb79 --- /dev/null +++ b/drivers/media/video/uvc/uvc_debugfs.c | |||
@@ -0,0 +1,136 @@ | |||
1 | /* | ||
2 | * uvc_debugfs.c -- USB Video Class driver - Debugging support | ||
3 | * | ||
4 | * Copyright (C) 2011 | ||
5 | * Laurent Pinchart (laurent.pinchart@ideasonboard.com) | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/debugfs.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/usb.h> | ||
18 | |||
19 | #include "uvcvideo.h" | ||
20 | |||
21 | /* ----------------------------------------------------------------------------- | ||
22 | * Statistics | ||
23 | */ | ||
24 | |||
25 | #define UVC_DEBUGFS_BUF_SIZE 1024 | ||
26 | |||
27 | struct uvc_debugfs_buffer { | ||
28 | size_t count; | ||
29 | char data[UVC_DEBUGFS_BUF_SIZE]; | ||
30 | }; | ||
31 | |||
32 | static int uvc_debugfs_stats_open(struct inode *inode, struct file *file) | ||
33 | { | ||
34 | struct uvc_streaming *stream = inode->i_private; | ||
35 | struct uvc_debugfs_buffer *buf; | ||
36 | |||
37 | buf = kmalloc(sizeof(*buf), GFP_KERNEL); | ||
38 | if (buf == NULL) | ||
39 | return -ENOMEM; | ||
40 | |||
41 | buf->count = uvc_video_stats_dump(stream, buf->data, sizeof(buf->data)); | ||
42 | |||
43 | file->private_data = buf; | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | static ssize_t uvc_debugfs_stats_read(struct file *file, char __user *user_buf, | ||
48 | size_t nbytes, loff_t *ppos) | ||
49 | { | ||
50 | struct uvc_debugfs_buffer *buf = file->private_data; | ||
51 | |||
52 | return simple_read_from_buffer(user_buf, nbytes, ppos, buf->data, | ||
53 | buf->count); | ||
54 | } | ||
55 | |||
56 | static int uvc_debugfs_stats_release(struct inode *inode, struct file *file) | ||
57 | { | ||
58 | kfree(file->private_data); | ||
59 | file->private_data = NULL; | ||
60 | |||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static const struct file_operations uvc_debugfs_stats_fops = { | ||
65 | .owner = THIS_MODULE, | ||
66 | .open = uvc_debugfs_stats_open, | ||
67 | .llseek = no_llseek, | ||
68 | .read = uvc_debugfs_stats_read, | ||
69 | .release = uvc_debugfs_stats_release, | ||
70 | }; | ||
71 | |||
72 | /* ----------------------------------------------------------------------------- | ||
73 | * Global and stream initialization/cleanup | ||
74 | */ | ||
75 | |||
76 | static struct dentry *uvc_debugfs_root_dir; | ||
77 | |||
78 | int uvc_debugfs_init_stream(struct uvc_streaming *stream) | ||
79 | { | ||
80 | struct usb_device *udev = stream->dev->udev; | ||
81 | struct dentry *dent; | ||
82 | char dir_name[32]; | ||
83 | |||
84 | if (uvc_debugfs_root_dir == NULL) | ||
85 | return -ENODEV; | ||
86 | |||
87 | sprintf(dir_name, "%u-%u", udev->bus->busnum, udev->devnum); | ||
88 | |||
89 | dent = debugfs_create_dir(dir_name, uvc_debugfs_root_dir); | ||
90 | if (IS_ERR_OR_NULL(dent)) { | ||
91 | uvc_printk(KERN_INFO, "Unable to create debugfs %s " | ||
92 | "directory.\n", dir_name); | ||
93 | return -ENODEV; | ||
94 | } | ||
95 | |||
96 | stream->debugfs_dir = dent; | ||
97 | |||
98 | dent = debugfs_create_file("stats", 0444, stream->debugfs_dir, | ||
99 | stream, &uvc_debugfs_stats_fops); | ||
100 | if (IS_ERR_OR_NULL(dent)) { | ||
101 | uvc_printk(KERN_INFO, "Unable to create debugfs stats file.\n"); | ||
102 | uvc_debugfs_cleanup_stream(stream); | ||
103 | return -ENODEV; | ||
104 | } | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream) | ||
110 | { | ||
111 | if (stream->debugfs_dir == NULL) | ||
112 | return; | ||
113 | |||
114 | debugfs_remove_recursive(stream->debugfs_dir); | ||
115 | stream->debugfs_dir = NULL; | ||
116 | } | ||
117 | |||
118 | int uvc_debugfs_init(void) | ||
119 | { | ||
120 | struct dentry *dir; | ||
121 | |||
122 | dir = debugfs_create_dir("uvcvideo", usb_debug_root); | ||
123 | if (IS_ERR_OR_NULL(dir)) { | ||
124 | uvc_printk(KERN_INFO, "Unable to create debugfs directory\n"); | ||
125 | return -ENODATA; | ||
126 | } | ||
127 | |||
128 | uvc_debugfs_root_dir = dir; | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | void uvc_debugfs_cleanup(void) | ||
133 | { | ||
134 | if (uvc_debugfs_root_dir != NULL) | ||
135 | debugfs_remove_recursive(uvc_debugfs_root_dir); | ||
136 | } | ||
diff --git a/drivers/media/video/uvc/uvc_driver.c b/drivers/media/video/uvc/uvc_driver.c index 656d4c9e3b9f..a240d43d15d1 100644 --- a/drivers/media/video/uvc/uvc_driver.c +++ b/drivers/media/video/uvc/uvc_driver.c | |||
@@ -1675,6 +1675,8 @@ static void uvc_unregister_video(struct uvc_device *dev) | |||
1675 | 1675 | ||
1676 | video_unregister_device(stream->vdev); | 1676 | video_unregister_device(stream->vdev); |
1677 | stream->vdev = NULL; | 1677 | stream->vdev = NULL; |
1678 | |||
1679 | uvc_debugfs_cleanup_stream(stream); | ||
1678 | } | 1680 | } |
1679 | 1681 | ||
1680 | /* Decrement the stream count and call uvc_delete explicitly if there | 1682 | /* Decrement the stream count and call uvc_delete explicitly if there |
@@ -1700,6 +1702,8 @@ static int uvc_register_video(struct uvc_device *dev, | |||
1700 | return ret; | 1702 | return ret; |
1701 | } | 1703 | } |
1702 | 1704 | ||
1705 | uvc_debugfs_init_stream(stream); | ||
1706 | |||
1703 | /* Register the device with V4L. */ | 1707 | /* Register the device with V4L. */ |
1704 | vdev = video_device_alloc(); | 1708 | vdev = video_device_alloc(); |
1705 | if (vdev == NULL) { | 1709 | if (vdev == NULL) { |
@@ -2033,6 +2037,15 @@ MODULE_PARM_DESC(timeout, "Streaming control requests timeout"); | |||
2033 | * though they are compliant. | 2037 | * though they are compliant. |
2034 | */ | 2038 | */ |
2035 | static struct usb_device_id uvc_ids[] = { | 2039 | static struct usb_device_id uvc_ids[] = { |
2040 | /* LogiLink Wireless Webcam */ | ||
2041 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | ||
2042 | | USB_DEVICE_ID_MATCH_INT_INFO, | ||
2043 | .idVendor = 0x0416, | ||
2044 | .idProduct = 0xa91a, | ||
2045 | .bInterfaceClass = USB_CLASS_VIDEO, | ||
2046 | .bInterfaceSubClass = 1, | ||
2047 | .bInterfaceProtocol = 0, | ||
2048 | .driver_info = UVC_QUIRK_PROBE_MINMAX }, | ||
2036 | /* Genius eFace 2025 */ | 2049 | /* Genius eFace 2025 */ |
2037 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | 2050 | { .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
2038 | | USB_DEVICE_ID_MATCH_INT_INFO, | 2051 | | USB_DEVICE_ID_MATCH_INT_INFO, |
@@ -2396,17 +2409,24 @@ struct uvc_driver uvc_driver = { | |||
2396 | 2409 | ||
2397 | static int __init uvc_init(void) | 2410 | static int __init uvc_init(void) |
2398 | { | 2411 | { |
2399 | int result; | 2412 | int ret; |
2413 | |||
2414 | uvc_debugfs_init(); | ||
2400 | 2415 | ||
2401 | result = usb_register(&uvc_driver.driver); | 2416 | ret = usb_register(&uvc_driver.driver); |
2402 | if (result == 0) | 2417 | if (ret < 0) { |
2403 | printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n"); | 2418 | uvc_debugfs_cleanup(); |
2404 | return result; | 2419 | return ret; |
2420 | } | ||
2421 | |||
2422 | printk(KERN_INFO DRIVER_DESC " (" DRIVER_VERSION ")\n"); | ||
2423 | return 0; | ||
2405 | } | 2424 | } |
2406 | 2425 | ||
2407 | static void __exit uvc_cleanup(void) | 2426 | static void __exit uvc_cleanup(void) |
2408 | { | 2427 | { |
2409 | usb_deregister(&uvc_driver.driver); | 2428 | usb_deregister(&uvc_driver.driver); |
2429 | uvc_debugfs_cleanup(); | ||
2410 | } | 2430 | } |
2411 | 2431 | ||
2412 | module_init(uvc_init); | 2432 | module_init(uvc_init); |
diff --git a/drivers/media/video/uvc/uvc_isight.c b/drivers/media/video/uvc/uvc_isight.c index 74bbe8f18f3e..8510e7259e76 100644 --- a/drivers/media/video/uvc/uvc_isight.c +++ b/drivers/media/video/uvc/uvc_isight.c | |||
@@ -74,7 +74,7 @@ static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf, | |||
74 | * Empty buffers (bytesused == 0) don't trigger end of frame detection | 74 | * Empty buffers (bytesused == 0) don't trigger end of frame detection |
75 | * as it doesn't make sense to return an empty buffer. | 75 | * as it doesn't make sense to return an empty buffer. |
76 | */ | 76 | */ |
77 | if (is_header && buf->buf.bytesused != 0) { | 77 | if (is_header && buf->bytesused != 0) { |
78 | buf->state = UVC_BUF_STATE_DONE; | 78 | buf->state = UVC_BUF_STATE_DONE; |
79 | return -EAGAIN; | 79 | return -EAGAIN; |
80 | } | 80 | } |
@@ -83,13 +83,13 @@ static int isight_decode(struct uvc_video_queue *queue, struct uvc_buffer *buf, | |||
83 | * contain no data. | 83 | * contain no data. |
84 | */ | 84 | */ |
85 | if (!is_header) { | 85 | if (!is_header) { |
86 | maxlen = buf->buf.length - buf->buf.bytesused; | 86 | maxlen = buf->length - buf->bytesused; |
87 | mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused; | 87 | mem = buf->mem + buf->bytesused; |
88 | nbytes = min(len, maxlen); | 88 | nbytes = min(len, maxlen); |
89 | memcpy(mem, data, nbytes); | 89 | memcpy(mem, data, nbytes); |
90 | buf->buf.bytesused += nbytes; | 90 | buf->bytesused += nbytes; |
91 | 91 | ||
92 | if (len > maxlen || buf->buf.bytesused == buf->buf.length) { | 92 | if (len > maxlen || buf->bytesused == buf->length) { |
93 | uvc_trace(UVC_TRACE_FRAME, "Frame complete " | 93 | uvc_trace(UVC_TRACE_FRAME, "Frame complete " |
94 | "(overflow).\n"); | 94 | "(overflow).\n"); |
95 | buf->state = UVC_BUF_STATE_DONE; | 95 | buf->state = UVC_BUF_STATE_DONE; |
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 677691c44500..518f77d3a4d8 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * | 11 | * |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/atomic.h> | ||
14 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
15 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
16 | #include <linux/list.h> | 17 | #include <linux/list.h> |
@@ -19,7 +20,7 @@ | |||
19 | #include <linux/videodev2.h> | 20 | #include <linux/videodev2.h> |
20 | #include <linux/vmalloc.h> | 21 | #include <linux/vmalloc.h> |
21 | #include <linux/wait.h> | 22 | #include <linux/wait.h> |
22 | #include <linux/atomic.h> | 23 | #include <media/videobuf2-vmalloc.h> |
23 | 24 | ||
24 | #include "uvcvideo.h" | 25 | #include "uvcvideo.h" |
25 | 26 | ||
@@ -29,467 +30,211 @@ | |||
29 | * Video queues is initialized by uvc_queue_init(). The function performs | 30 | * Video queues is initialized by uvc_queue_init(). The function performs |
30 | * basic initialization of the uvc_video_queue struct and never fails. | 31 | * basic initialization of the uvc_video_queue struct and never fails. |
31 | * | 32 | * |
32 | * Video buffer allocation and freeing are performed by uvc_alloc_buffers and | 33 | * Video buffers are managed by videobuf2. The driver uses a mutex to protect |
33 | * uvc_free_buffers respectively. The former acquires the video queue lock, | 34 | * the videobuf2 queue operations by serializing calls to videobuf2 and a |
34 | * while the later must be called with the lock held (so that allocation can | 35 | * spinlock to protect the IRQ queue that holds the buffers to be processed by |
35 | * free previously allocated buffers). Trying to free buffers that are mapped | 36 | * the driver. |
36 | * to user space will return -EBUSY. | ||
37 | * | ||
38 | * Video buffers are managed using two queues. However, unlike most USB video | ||
39 | * drivers that use an in queue and an out queue, we use a main queue to hold | ||
40 | * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to | ||
41 | * hold empty buffers. This design (copied from video-buf) minimizes locking | ||
42 | * in interrupt, as only one queue is shared between interrupt and user | ||
43 | * contexts. | ||
44 | * | ||
45 | * Use cases | ||
46 | * --------- | ||
47 | * | ||
48 | * Unless stated otherwise, all operations that modify the irq buffers queue | ||
49 | * are protected by the irq spinlock. | ||
50 | * | ||
51 | * 1. The user queues the buffers, starts streaming and dequeues a buffer. | ||
52 | * | ||
53 | * The buffers are added to the main and irq queues. Both operations are | ||
54 | * protected by the queue lock, and the later is protected by the irq | ||
55 | * spinlock as well. | ||
56 | * | ||
57 | * The completion handler fetches a buffer from the irq queue and fills it | ||
58 | * with video data. If no buffer is available (irq queue empty), the handler | ||
59 | * returns immediately. | ||
60 | * | ||
61 | * When the buffer is full, the completion handler removes it from the irq | ||
62 | * queue, marks it as done (UVC_BUF_STATE_DONE) and wakes its wait queue. | ||
63 | * At that point, any process waiting on the buffer will be woken up. If a | ||
64 | * process tries to dequeue a buffer after it has been marked done, the | ||
65 | * dequeing will succeed immediately. | ||
66 | * | ||
67 | * 2. Buffers are queued, user is waiting on a buffer and the device gets | ||
68 | * disconnected. | ||
69 | * | ||
70 | * When the device is disconnected, the kernel calls the completion handler | ||
71 | * with an appropriate status code. The handler marks all buffers in the | ||
72 | * irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so | ||
73 | * that any process waiting on a buffer gets woken up. | ||
74 | * | ||
75 | * Waking up up the first buffer on the irq list is not enough, as the | ||
76 | * process waiting on the buffer might restart the dequeue operation | ||
77 | * immediately. | ||
78 | * | ||
79 | */ | 37 | */ |
80 | 38 | ||
81 | void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, | 39 | /* ----------------------------------------------------------------------------- |
82 | int drop_corrupted) | 40 | * videobuf2 queue operations |
83 | { | ||
84 | mutex_init(&queue->mutex); | ||
85 | spin_lock_init(&queue->irqlock); | ||
86 | INIT_LIST_HEAD(&queue->mainqueue); | ||
87 | INIT_LIST_HEAD(&queue->irqqueue); | ||
88 | queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0; | ||
89 | queue->type = type; | ||
90 | } | ||
91 | |||
92 | /* | ||
93 | * Free the video buffers. | ||
94 | * | ||
95 | * This function must be called with the queue lock held. | ||
96 | */ | 41 | */ |
97 | static int __uvc_free_buffers(struct uvc_video_queue *queue) | 42 | |
43 | static int uvc_queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, | ||
44 | unsigned int *nbuffers, unsigned int *nplanes, | ||
45 | unsigned int sizes[], void *alloc_ctxs[]) | ||
98 | { | 46 | { |
99 | unsigned int i; | 47 | struct uvc_video_queue *queue = vb2_get_drv_priv(vq); |
48 | struct uvc_streaming *stream = | ||
49 | container_of(queue, struct uvc_streaming, queue); | ||
100 | 50 | ||
101 | for (i = 0; i < queue->count; ++i) { | 51 | if (*nbuffers > UVC_MAX_VIDEO_BUFFERS) |
102 | if (queue->buffer[i].vma_use_count != 0) | 52 | *nbuffers = UVC_MAX_VIDEO_BUFFERS; |
103 | return -EBUSY; | ||
104 | } | ||
105 | 53 | ||
106 | if (queue->count) { | 54 | *nplanes = 1; |
107 | uvc_queue_cancel(queue, 0); | 55 | |
108 | INIT_LIST_HEAD(&queue->mainqueue); | 56 | sizes[0] = stream->ctrl.dwMaxVideoFrameSize; |
109 | vfree(queue->mem); | ||
110 | queue->count = 0; | ||
111 | } | ||
112 | 57 | ||
113 | return 0; | 58 | return 0; |
114 | } | 59 | } |
115 | 60 | ||
116 | int uvc_free_buffers(struct uvc_video_queue *queue) | 61 | static int uvc_buffer_prepare(struct vb2_buffer *vb) |
117 | { | 62 | { |
118 | int ret; | 63 | struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); |
64 | struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf); | ||
119 | 65 | ||
120 | mutex_lock(&queue->mutex); | 66 | if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_OUTPUT && |
121 | ret = __uvc_free_buffers(queue); | 67 | vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) { |
122 | mutex_unlock(&queue->mutex); | 68 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n"); |
69 | return -EINVAL; | ||
70 | } | ||
123 | 71 | ||
124 | return ret; | 72 | if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED)) |
125 | } | 73 | return -ENODEV; |
126 | 74 | ||
127 | /* | 75 | buf->state = UVC_BUF_STATE_QUEUED; |
128 | * Allocate the video buffers. | 76 | buf->error = 0; |
129 | * | 77 | buf->mem = vb2_plane_vaddr(vb, 0); |
130 | * Pages are reserved to make sure they will not be swapped, as they will be | 78 | buf->length = vb2_plane_size(vb, 0); |
131 | * filled in the URB completion handler. | 79 | if (vb->v4l2_buf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE) |
132 | * | 80 | buf->bytesused = 0; |
133 | * Buffers will be individually mapped, so they must all be page aligned. | 81 | else |
134 | */ | 82 | buf->bytesused = vb2_get_plane_payload(vb, 0); |
135 | int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, | ||
136 | unsigned int buflength) | ||
137 | { | ||
138 | unsigned int bufsize = PAGE_ALIGN(buflength); | ||
139 | unsigned int i; | ||
140 | void *mem = NULL; | ||
141 | int ret; | ||
142 | 83 | ||
143 | if (nbuffers > UVC_MAX_VIDEO_BUFFERS) | 84 | return 0; |
144 | nbuffers = UVC_MAX_VIDEO_BUFFERS; | 85 | } |
145 | 86 | ||
146 | mutex_lock(&queue->mutex); | 87 | static void uvc_buffer_queue(struct vb2_buffer *vb) |
88 | { | ||
89 | struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); | ||
90 | struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf); | ||
91 | unsigned long flags; | ||
147 | 92 | ||
148 | if ((ret = __uvc_free_buffers(queue)) < 0) | 93 | spin_lock_irqsave(&queue->irqlock, flags); |
149 | goto done; | 94 | if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) { |
95 | list_add_tail(&buf->queue, &queue->irqqueue); | ||
96 | } else { | ||
97 | /* If the device is disconnected return the buffer to userspace | ||
98 | * directly. The next QBUF call will fail with -ENODEV. | ||
99 | */ | ||
100 | buf->state = UVC_BUF_STATE_ERROR; | ||
101 | vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR); | ||
102 | } | ||
150 | 103 | ||
151 | /* Bail out if no buffers should be allocated. */ | 104 | spin_unlock_irqrestore(&queue->irqlock, flags); |
152 | if (nbuffers == 0) | 105 | } |
153 | goto done; | ||
154 | 106 | ||
155 | /* Decrement the number of buffers until allocation succeeds. */ | 107 | static int uvc_buffer_finish(struct vb2_buffer *vb) |
156 | for (; nbuffers > 0; --nbuffers) { | 108 | { |
157 | mem = vmalloc_32(nbuffers * bufsize); | 109 | struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue); |
158 | if (mem != NULL) | 110 | struct uvc_streaming *stream = |
159 | break; | 111 | container_of(queue, struct uvc_streaming, queue); |
160 | } | 112 | struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf); |
161 | 113 | ||
162 | if (mem == NULL) { | 114 | uvc_video_clock_update(stream, &vb->v4l2_buf, buf); |
163 | ret = -ENOMEM; | 115 | return 0; |
164 | goto done; | 116 | } |
165 | } | ||
166 | 117 | ||
167 | for (i = 0; i < nbuffers; ++i) { | 118 | static struct vb2_ops uvc_queue_qops = { |
168 | memset(&queue->buffer[i], 0, sizeof queue->buffer[i]); | 119 | .queue_setup = uvc_queue_setup, |
169 | queue->buffer[i].buf.index = i; | 120 | .buf_prepare = uvc_buffer_prepare, |
170 | queue->buffer[i].buf.m.offset = i * bufsize; | 121 | .buf_queue = uvc_buffer_queue, |
171 | queue->buffer[i].buf.length = buflength; | 122 | .buf_finish = uvc_buffer_finish, |
172 | queue->buffer[i].buf.type = queue->type; | 123 | }; |
173 | queue->buffer[i].buf.field = V4L2_FIELD_NONE; | ||
174 | queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP; | ||
175 | queue->buffer[i].buf.flags = 0; | ||
176 | init_waitqueue_head(&queue->buffer[i].wait); | ||
177 | } | ||
178 | 124 | ||
179 | queue->mem = mem; | 125 | void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, |
180 | queue->count = nbuffers; | 126 | int drop_corrupted) |
181 | queue->buf_size = bufsize; | 127 | { |
182 | ret = nbuffers; | 128 | queue->queue.type = type; |
129 | queue->queue.io_modes = VB2_MMAP; | ||
130 | queue->queue.drv_priv = queue; | ||
131 | queue->queue.buf_struct_size = sizeof(struct uvc_buffer); | ||
132 | queue->queue.ops = &uvc_queue_qops; | ||
133 | queue->queue.mem_ops = &vb2_vmalloc_memops; | ||
134 | vb2_queue_init(&queue->queue); | ||
183 | 135 | ||
184 | done: | 136 | mutex_init(&queue->mutex); |
185 | mutex_unlock(&queue->mutex); | 137 | spin_lock_init(&queue->irqlock); |
186 | return ret; | 138 | INIT_LIST_HEAD(&queue->irqqueue); |
139 | queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0; | ||
187 | } | 140 | } |
188 | 141 | ||
189 | /* | 142 | /* ----------------------------------------------------------------------------- |
190 | * Check if buffers have been allocated. | 143 | * V4L2 queue operations |
191 | */ | 144 | */ |
192 | int uvc_queue_allocated(struct uvc_video_queue *queue) | 145 | |
146 | int uvc_alloc_buffers(struct uvc_video_queue *queue, | ||
147 | struct v4l2_requestbuffers *rb) | ||
193 | { | 148 | { |
194 | int allocated; | 149 | int ret; |
195 | 150 | ||
196 | mutex_lock(&queue->mutex); | 151 | mutex_lock(&queue->mutex); |
197 | allocated = queue->count != 0; | 152 | ret = vb2_reqbufs(&queue->queue, rb); |
198 | mutex_unlock(&queue->mutex); | 153 | mutex_unlock(&queue->mutex); |
199 | 154 | ||
200 | return allocated; | 155 | return ret ? ret : rb->count; |
201 | } | 156 | } |
202 | 157 | ||
203 | static void __uvc_query_buffer(struct uvc_buffer *buf, | 158 | void uvc_free_buffers(struct uvc_video_queue *queue) |
204 | struct v4l2_buffer *v4l2_buf) | ||
205 | { | 159 | { |
206 | memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf); | 160 | mutex_lock(&queue->mutex); |
207 | 161 | vb2_queue_release(&queue->queue); | |
208 | if (buf->vma_use_count) | 162 | mutex_unlock(&queue->mutex); |
209 | v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED; | ||
210 | |||
211 | switch (buf->state) { | ||
212 | case UVC_BUF_STATE_ERROR: | ||
213 | case UVC_BUF_STATE_DONE: | ||
214 | v4l2_buf->flags |= V4L2_BUF_FLAG_DONE; | ||
215 | break; | ||
216 | case UVC_BUF_STATE_QUEUED: | ||
217 | case UVC_BUF_STATE_ACTIVE: | ||
218 | case UVC_BUF_STATE_READY: | ||
219 | v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED; | ||
220 | break; | ||
221 | case UVC_BUF_STATE_IDLE: | ||
222 | default: | ||
223 | break; | ||
224 | } | ||
225 | } | 163 | } |
226 | 164 | ||
227 | int uvc_query_buffer(struct uvc_video_queue *queue, | 165 | int uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) |
228 | struct v4l2_buffer *v4l2_buf) | ||
229 | { | 166 | { |
230 | int ret = 0; | 167 | int ret; |
231 | 168 | ||
232 | mutex_lock(&queue->mutex); | 169 | mutex_lock(&queue->mutex); |
233 | if (v4l2_buf->index >= queue->count) { | 170 | ret = vb2_querybuf(&queue->queue, buf); |
234 | ret = -EINVAL; | ||
235 | goto done; | ||
236 | } | ||
237 | |||
238 | __uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf); | ||
239 | |||
240 | done: | ||
241 | mutex_unlock(&queue->mutex); | 171 | mutex_unlock(&queue->mutex); |
172 | |||
242 | return ret; | 173 | return ret; |
243 | } | 174 | } |
244 | 175 | ||
245 | /* | 176 | int uvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf) |
246 | * Queue a video buffer. Attempting to queue a buffer that has already been | ||
247 | * queued will return -EINVAL. | ||
248 | */ | ||
249 | int uvc_queue_buffer(struct uvc_video_queue *queue, | ||
250 | struct v4l2_buffer *v4l2_buf) | ||
251 | { | 177 | { |
252 | struct uvc_buffer *buf; | 178 | int ret; |
253 | unsigned long flags; | ||
254 | int ret = 0; | ||
255 | |||
256 | uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index); | ||
257 | |||
258 | if (v4l2_buf->type != queue->type || | ||
259 | v4l2_buf->memory != V4L2_MEMORY_MMAP) { | ||
260 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " | ||
261 | "and/or memory (%u).\n", v4l2_buf->type, | ||
262 | v4l2_buf->memory); | ||
263 | return -EINVAL; | ||
264 | } | ||
265 | 179 | ||
266 | mutex_lock(&queue->mutex); | 180 | mutex_lock(&queue->mutex); |
267 | if (v4l2_buf->index >= queue->count) { | 181 | ret = vb2_qbuf(&queue->queue, buf); |
268 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n"); | ||
269 | ret = -EINVAL; | ||
270 | goto done; | ||
271 | } | ||
272 | |||
273 | buf = &queue->buffer[v4l2_buf->index]; | ||
274 | if (buf->state != UVC_BUF_STATE_IDLE) { | ||
275 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state " | ||
276 | "(%u).\n", buf->state); | ||
277 | ret = -EINVAL; | ||
278 | goto done; | ||
279 | } | ||
280 | |||
281 | if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT && | ||
282 | v4l2_buf->bytesused > buf->buf.length) { | ||
283 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n"); | ||
284 | ret = -EINVAL; | ||
285 | goto done; | ||
286 | } | ||
287 | |||
288 | spin_lock_irqsave(&queue->irqlock, flags); | ||
289 | if (queue->flags & UVC_QUEUE_DISCONNECTED) { | ||
290 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
291 | ret = -ENODEV; | ||
292 | goto done; | ||
293 | } | ||
294 | buf->state = UVC_BUF_STATE_QUEUED; | ||
295 | if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
296 | buf->buf.bytesused = 0; | ||
297 | else | ||
298 | buf->buf.bytesused = v4l2_buf->bytesused; | ||
299 | |||
300 | list_add_tail(&buf->stream, &queue->mainqueue); | ||
301 | list_add_tail(&buf->queue, &queue->irqqueue); | ||
302 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
303 | |||
304 | done: | ||
305 | mutex_unlock(&queue->mutex); | 182 | mutex_unlock(&queue->mutex); |
306 | return ret; | ||
307 | } | ||
308 | 183 | ||
309 | static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking) | 184 | return ret; |
310 | { | ||
311 | if (nonblocking) { | ||
312 | return (buf->state != UVC_BUF_STATE_QUEUED && | ||
313 | buf->state != UVC_BUF_STATE_ACTIVE && | ||
314 | buf->state != UVC_BUF_STATE_READY) | ||
315 | ? 0 : -EAGAIN; | ||
316 | } | ||
317 | |||
318 | return wait_event_interruptible(buf->wait, | ||
319 | buf->state != UVC_BUF_STATE_QUEUED && | ||
320 | buf->state != UVC_BUF_STATE_ACTIVE && | ||
321 | buf->state != UVC_BUF_STATE_READY); | ||
322 | } | 185 | } |
323 | 186 | ||
324 | /* | 187 | int uvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf, |
325 | * Dequeue a video buffer. If nonblocking is false, block until a buffer is | 188 | int nonblocking) |
326 | * available. | ||
327 | */ | ||
328 | int uvc_dequeue_buffer(struct uvc_video_queue *queue, | ||
329 | struct v4l2_buffer *v4l2_buf, int nonblocking) | ||
330 | { | 189 | { |
331 | struct uvc_buffer *buf; | 190 | int ret; |
332 | int ret = 0; | ||
333 | |||
334 | if (v4l2_buf->type != queue->type || | ||
335 | v4l2_buf->memory != V4L2_MEMORY_MMAP) { | ||
336 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) " | ||
337 | "and/or memory (%u).\n", v4l2_buf->type, | ||
338 | v4l2_buf->memory); | ||
339 | return -EINVAL; | ||
340 | } | ||
341 | 191 | ||
342 | mutex_lock(&queue->mutex); | 192 | mutex_lock(&queue->mutex); |
343 | if (list_empty(&queue->mainqueue)) { | 193 | ret = vb2_dqbuf(&queue->queue, buf, nonblocking); |
344 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n"); | ||
345 | ret = -EINVAL; | ||
346 | goto done; | ||
347 | } | ||
348 | |||
349 | buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream); | ||
350 | if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0) | ||
351 | goto done; | ||
352 | |||
353 | uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n", | ||
354 | buf->buf.index, buf->state, buf->buf.bytesused); | ||
355 | |||
356 | switch (buf->state) { | ||
357 | case UVC_BUF_STATE_ERROR: | ||
358 | uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data " | ||
359 | "(transmission error).\n"); | ||
360 | ret = -EIO; | ||
361 | case UVC_BUF_STATE_DONE: | ||
362 | buf->state = UVC_BUF_STATE_IDLE; | ||
363 | break; | ||
364 | |||
365 | case UVC_BUF_STATE_IDLE: | ||
366 | case UVC_BUF_STATE_QUEUED: | ||
367 | case UVC_BUF_STATE_ACTIVE: | ||
368 | case UVC_BUF_STATE_READY: | ||
369 | default: | ||
370 | uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u " | ||
371 | "(driver bug?).\n", buf->state); | ||
372 | ret = -EINVAL; | ||
373 | goto done; | ||
374 | } | ||
375 | |||
376 | list_del(&buf->stream); | ||
377 | __uvc_query_buffer(buf, v4l2_buf); | ||
378 | |||
379 | done: | ||
380 | mutex_unlock(&queue->mutex); | 194 | mutex_unlock(&queue->mutex); |
381 | return ret; | ||
382 | } | ||
383 | 195 | ||
384 | /* | 196 | return ret; |
385 | * VMA operations. | ||
386 | */ | ||
387 | static void uvc_vm_open(struct vm_area_struct *vma) | ||
388 | { | ||
389 | struct uvc_buffer *buffer = vma->vm_private_data; | ||
390 | buffer->vma_use_count++; | ||
391 | } | ||
392 | |||
393 | static void uvc_vm_close(struct vm_area_struct *vma) | ||
394 | { | ||
395 | struct uvc_buffer *buffer = vma->vm_private_data; | ||
396 | buffer->vma_use_count--; | ||
397 | } | 197 | } |
398 | 198 | ||
399 | static const struct vm_operations_struct uvc_vm_ops = { | ||
400 | .open = uvc_vm_open, | ||
401 | .close = uvc_vm_close, | ||
402 | }; | ||
403 | |||
404 | /* | ||
405 | * Memory-map a video buffer. | ||
406 | * | ||
407 | * This function implements video buffers memory mapping and is intended to be | ||
408 | * used by the device mmap handler. | ||
409 | */ | ||
410 | int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) | 199 | int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) |
411 | { | 200 | { |
412 | struct uvc_buffer *uninitialized_var(buffer); | 201 | int ret; |
413 | struct page *page; | ||
414 | unsigned long addr, start, size; | ||
415 | unsigned int i; | ||
416 | int ret = 0; | ||
417 | |||
418 | start = vma->vm_start; | ||
419 | size = vma->vm_end - vma->vm_start; | ||
420 | 202 | ||
421 | mutex_lock(&queue->mutex); | 203 | mutex_lock(&queue->mutex); |
204 | ret = vb2_mmap(&queue->queue, vma); | ||
205 | mutex_unlock(&queue->mutex); | ||
422 | 206 | ||
423 | for (i = 0; i < queue->count; ++i) { | 207 | return ret; |
424 | buffer = &queue->buffer[i]; | 208 | } |
425 | if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff) | ||
426 | break; | ||
427 | } | ||
428 | |||
429 | if (i == queue->count || PAGE_ALIGN(size) != queue->buf_size) { | ||
430 | ret = -EINVAL; | ||
431 | goto done; | ||
432 | } | ||
433 | |||
434 | /* | ||
435 | * VM_IO marks the area as being an mmaped region for I/O to a | ||
436 | * device. It also prevents the region from being core dumped. | ||
437 | */ | ||
438 | vma->vm_flags |= VM_IO; | ||
439 | |||
440 | addr = (unsigned long)queue->mem + buffer->buf.m.offset; | ||
441 | #ifdef CONFIG_MMU | ||
442 | while (size > 0) { | ||
443 | page = vmalloc_to_page((void *)addr); | ||
444 | if ((ret = vm_insert_page(vma, start, page)) < 0) | ||
445 | goto done; | ||
446 | |||
447 | start += PAGE_SIZE; | ||
448 | addr += PAGE_SIZE; | ||
449 | size -= PAGE_SIZE; | ||
450 | } | ||
451 | #endif | ||
452 | 209 | ||
453 | vma->vm_ops = &uvc_vm_ops; | 210 | unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, |
454 | vma->vm_private_data = buffer; | 211 | poll_table *wait) |
455 | uvc_vm_open(vma); | 212 | { |
213 | unsigned int ret; | ||
456 | 214 | ||
457 | done: | 215 | mutex_lock(&queue->mutex); |
216 | ret = vb2_poll(&queue->queue, file, wait); | ||
458 | mutex_unlock(&queue->mutex); | 217 | mutex_unlock(&queue->mutex); |
218 | |||
459 | return ret; | 219 | return ret; |
460 | } | 220 | } |
461 | 221 | ||
462 | /* | 222 | /* ----------------------------------------------------------------------------- |
463 | * Poll the video queue. | ||
464 | * | 223 | * |
465 | * This function implements video queue polling and is intended to be used by | ||
466 | * the device poll handler. | ||
467 | */ | 224 | */ |
468 | unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, | 225 | |
469 | poll_table *wait) | 226 | /* |
227 | * Check if buffers have been allocated. | ||
228 | */ | ||
229 | int uvc_queue_allocated(struct uvc_video_queue *queue) | ||
470 | { | 230 | { |
471 | struct uvc_buffer *buf; | 231 | int allocated; |
472 | unsigned int mask = 0; | ||
473 | 232 | ||
474 | mutex_lock(&queue->mutex); | 233 | mutex_lock(&queue->mutex); |
475 | if (list_empty(&queue->mainqueue)) { | 234 | allocated = vb2_is_busy(&queue->queue); |
476 | mask |= POLLERR; | ||
477 | goto done; | ||
478 | } | ||
479 | buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream); | ||
480 | |||
481 | poll_wait(file, &buf->wait, wait); | ||
482 | if (buf->state == UVC_BUF_STATE_DONE || | ||
483 | buf->state == UVC_BUF_STATE_ERROR) { | ||
484 | if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
485 | mask |= POLLIN | POLLRDNORM; | ||
486 | else | ||
487 | mask |= POLLOUT | POLLWRNORM; | ||
488 | } | ||
489 | |||
490 | done: | ||
491 | mutex_unlock(&queue->mutex); | 235 | mutex_unlock(&queue->mutex); |
492 | return mask; | 236 | |
237 | return allocated; | ||
493 | } | 238 | } |
494 | 239 | ||
495 | #ifndef CONFIG_MMU | 240 | #ifndef CONFIG_MMU |
@@ -515,7 +260,7 @@ unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, | |||
515 | ret = -EINVAL; | 260 | ret = -EINVAL; |
516 | goto done; | 261 | goto done; |
517 | } | 262 | } |
518 | ret = (unsigned long)queue->mem + buffer->buf.m.offset; | 263 | ret = (unsigned long)buf->mem; |
519 | done: | 264 | done: |
520 | mutex_unlock(&queue->mutex); | 265 | mutex_unlock(&queue->mutex); |
521 | return ret; | 266 | return ret; |
@@ -540,27 +285,24 @@ done: | |||
540 | */ | 285 | */ |
541 | int uvc_queue_enable(struct uvc_video_queue *queue, int enable) | 286 | int uvc_queue_enable(struct uvc_video_queue *queue, int enable) |
542 | { | 287 | { |
543 | unsigned int i; | 288 | unsigned long flags; |
544 | int ret = 0; | 289 | int ret; |
545 | 290 | ||
546 | mutex_lock(&queue->mutex); | 291 | mutex_lock(&queue->mutex); |
547 | if (enable) { | 292 | if (enable) { |
548 | if (uvc_queue_streaming(queue)) { | 293 | ret = vb2_streamon(&queue->queue, queue->queue.type); |
549 | ret = -EBUSY; | 294 | if (ret < 0) |
550 | goto done; | 295 | goto done; |
551 | } | 296 | |
552 | queue->flags |= UVC_QUEUE_STREAMING; | ||
553 | queue->buf_used = 0; | 297 | queue->buf_used = 0; |
554 | } else { | 298 | } else { |
555 | uvc_queue_cancel(queue, 0); | 299 | ret = vb2_streamoff(&queue->queue, queue->queue.type); |
556 | INIT_LIST_HEAD(&queue->mainqueue); | 300 | if (ret < 0) |
557 | 301 | goto done; | |
558 | for (i = 0; i < queue->count; ++i) { | ||
559 | queue->buffer[i].error = 0; | ||
560 | queue->buffer[i].state = UVC_BUF_STATE_IDLE; | ||
561 | } | ||
562 | 302 | ||
563 | queue->flags &= ~UVC_QUEUE_STREAMING; | 303 | spin_lock_irqsave(&queue->irqlock, flags); |
304 | INIT_LIST_HEAD(&queue->irqqueue); | ||
305 | spin_unlock_irqrestore(&queue->irqlock, flags); | ||
564 | } | 306 | } |
565 | 307 | ||
566 | done: | 308 | done: |
@@ -591,12 +333,12 @@ void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) | |||
591 | queue); | 333 | queue); |
592 | list_del(&buf->queue); | 334 | list_del(&buf->queue); |
593 | buf->state = UVC_BUF_STATE_ERROR; | 335 | buf->state = UVC_BUF_STATE_ERROR; |
594 | wake_up(&buf->wait); | 336 | vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR); |
595 | } | 337 | } |
596 | /* This must be protected by the irqlock spinlock to avoid race | 338 | /* This must be protected by the irqlock spinlock to avoid race |
597 | * conditions between uvc_queue_buffer and the disconnection event that | 339 | * conditions between uvc_buffer_queue and the disconnection event that |
598 | * could result in an interruptible wait in uvc_dequeue_buffer. Do not | 340 | * could result in an interruptible wait in uvc_dequeue_buffer. Do not |
599 | * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED | 341 | * blindly replace this logic by checking for the UVC_QUEUE_DISCONNECTED |
600 | * state outside the queue code. | 342 | * state outside the queue code. |
601 | */ | 343 | */ |
602 | if (disconnect) | 344 | if (disconnect) |
@@ -613,14 +355,12 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, | |||
613 | if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) { | 355 | if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) { |
614 | buf->error = 0; | 356 | buf->error = 0; |
615 | buf->state = UVC_BUF_STATE_QUEUED; | 357 | buf->state = UVC_BUF_STATE_QUEUED; |
616 | buf->buf.bytesused = 0; | 358 | vb2_set_plane_payload(&buf->buf, 0, 0); |
617 | return buf; | 359 | return buf; |
618 | } | 360 | } |
619 | 361 | ||
620 | spin_lock_irqsave(&queue->irqlock, flags); | 362 | spin_lock_irqsave(&queue->irqlock, flags); |
621 | list_del(&buf->queue); | 363 | list_del(&buf->queue); |
622 | buf->error = 0; | ||
623 | buf->state = UVC_BUF_STATE_DONE; | ||
624 | if (!list_empty(&queue->irqqueue)) | 364 | if (!list_empty(&queue->irqqueue)) |
625 | nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, | 365 | nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, |
626 | queue); | 366 | queue); |
@@ -628,7 +368,9 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, | |||
628 | nextbuf = NULL; | 368 | nextbuf = NULL; |
629 | spin_unlock_irqrestore(&queue->irqlock, flags); | 369 | spin_unlock_irqrestore(&queue->irqlock, flags); |
630 | 370 | ||
631 | wake_up(&buf->wait); | 371 | buf->state = buf->error ? VB2_BUF_STATE_ERROR : UVC_BUF_STATE_DONE; |
372 | vb2_set_plane_payload(&buf->buf, 0, buf->bytesused); | ||
373 | vb2_buffer_done(&buf->buf, VB2_BUF_STATE_DONE); | ||
374 | |||
632 | return nextbuf; | 375 | return nextbuf; |
633 | } | 376 | } |
634 | |||
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index dadf11f704dc..2ae4f880ea05 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c | |||
@@ -58,6 +58,15 @@ static int uvc_ioctl_ctrl_map(struct uvc_video_chain *chain, | |||
58 | break; | 58 | break; |
59 | 59 | ||
60 | case V4L2_CTRL_TYPE_MENU: | 60 | case V4L2_CTRL_TYPE_MENU: |
61 | /* Prevent excessive memory consumption, as well as integer | ||
62 | * overflows. | ||
63 | */ | ||
64 | if (xmap->menu_count == 0 || | ||
65 | xmap->menu_count > UVC_MAX_CONTROL_MENU_ENTRIES) { | ||
66 | ret = -EINVAL; | ||
67 | goto done; | ||
68 | } | ||
69 | |||
61 | size = xmap->menu_count * sizeof(*map->menu_info); | 70 | size = xmap->menu_count * sizeof(*map->menu_info); |
62 | map->menu_info = kmalloc(size, GFP_KERNEL); | 71 | map->menu_info = kmalloc(size, GFP_KERNEL); |
63 | if (map->menu_info == NULL) { | 72 | if (map->menu_info == NULL) { |
@@ -513,10 +522,7 @@ static int uvc_v4l2_release(struct file *file) | |||
513 | /* Only free resources if this is a privileged handle. */ | 522 | /* Only free resources if this is a privileged handle. */ |
514 | if (uvc_has_privileges(handle)) { | 523 | if (uvc_has_privileges(handle)) { |
515 | uvc_video_enable(stream, 0); | 524 | uvc_video_enable(stream, 0); |
516 | 525 | uvc_free_buffers(&stream->queue); | |
517 | if (uvc_free_buffers(&stream->queue) < 0) | ||
518 | uvc_printk(KERN_ERR, "uvc_v4l2_release: Unable to " | ||
519 | "free buffers.\n"); | ||
520 | } | 526 | } |
521 | 527 | ||
522 | /* Release the file handle. */ | 528 | /* Release the file handle. */ |
@@ -914,19 +920,11 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
914 | 920 | ||
915 | /* Buffers & streaming */ | 921 | /* Buffers & streaming */ |
916 | case VIDIOC_REQBUFS: | 922 | case VIDIOC_REQBUFS: |
917 | { | ||
918 | struct v4l2_requestbuffers *rb = arg; | ||
919 | |||
920 | if (rb->type != stream->type || | ||
921 | rb->memory != V4L2_MEMORY_MMAP) | ||
922 | return -EINVAL; | ||
923 | |||
924 | if ((ret = uvc_acquire_privileges(handle)) < 0) | 923 | if ((ret = uvc_acquire_privileges(handle)) < 0) |
925 | return ret; | 924 | return ret; |
926 | 925 | ||
927 | mutex_lock(&stream->mutex); | 926 | mutex_lock(&stream->mutex); |
928 | ret = uvc_alloc_buffers(&stream->queue, rb->count, | 927 | ret = uvc_alloc_buffers(&stream->queue, arg); |
929 | stream->ctrl.dwMaxVideoFrameSize); | ||
930 | mutex_unlock(&stream->mutex); | 928 | mutex_unlock(&stream->mutex); |
931 | if (ret < 0) | 929 | if (ret < 0) |
932 | return ret; | 930 | return ret; |
@@ -934,18 +932,13 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
934 | if (ret == 0) | 932 | if (ret == 0) |
935 | uvc_dismiss_privileges(handle); | 933 | uvc_dismiss_privileges(handle); |
936 | 934 | ||
937 | rb->count = ret; | ||
938 | ret = 0; | 935 | ret = 0; |
939 | break; | 936 | break; |
940 | } | ||
941 | 937 | ||
942 | case VIDIOC_QUERYBUF: | 938 | case VIDIOC_QUERYBUF: |
943 | { | 939 | { |
944 | struct v4l2_buffer *buf = arg; | 940 | struct v4l2_buffer *buf = arg; |
945 | 941 | ||
946 | if (buf->type != stream->type) | ||
947 | return -EINVAL; | ||
948 | |||
949 | if (!uvc_has_privileges(handle)) | 942 | if (!uvc_has_privileges(handle)) |
950 | return -EBUSY; | 943 | return -EBUSY; |
951 | 944 | ||
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index b015e8e5e8b0..c7e69b8f81c9 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -351,25 +351,553 @@ done: | |||
351 | return ret; | 351 | return ret; |
352 | } | 352 | } |
353 | 353 | ||
354 | int uvc_commit_video(struct uvc_streaming *stream, | 354 | static int uvc_commit_video(struct uvc_streaming *stream, |
355 | struct uvc_streaming_control *probe) | 355 | struct uvc_streaming_control *probe) |
356 | { | 356 | { |
357 | return uvc_set_video_ctrl(stream, probe, 0); | 357 | return uvc_set_video_ctrl(stream, probe, 0); |
358 | } | 358 | } |
359 | 359 | ||
360 | /* ----------------------------------------------------------------------------- | ||
361 | * Clocks and timestamps | ||
362 | */ | ||
363 | |||
364 | static void | ||
365 | uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf, | ||
366 | const __u8 *data, int len) | ||
367 | { | ||
368 | struct uvc_clock_sample *sample; | ||
369 | unsigned int header_size; | ||
370 | bool has_pts = false; | ||
371 | bool has_scr = false; | ||
372 | unsigned long flags; | ||
373 | struct timespec ts; | ||
374 | u16 host_sof; | ||
375 | u16 dev_sof; | ||
376 | |||
377 | switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) { | ||
378 | case UVC_STREAM_PTS | UVC_STREAM_SCR: | ||
379 | header_size = 12; | ||
380 | has_pts = true; | ||
381 | has_scr = true; | ||
382 | break; | ||
383 | case UVC_STREAM_PTS: | ||
384 | header_size = 6; | ||
385 | has_pts = true; | ||
386 | break; | ||
387 | case UVC_STREAM_SCR: | ||
388 | header_size = 8; | ||
389 | has_scr = true; | ||
390 | break; | ||
391 | default: | ||
392 | header_size = 2; | ||
393 | break; | ||
394 | } | ||
395 | |||
396 | /* Check for invalid headers. */ | ||
397 | if (len < header_size) | ||
398 | return; | ||
399 | |||
400 | /* Extract the timestamps: | ||
401 | * | ||
402 | * - store the frame PTS in the buffer structure | ||
403 | * - if the SCR field is present, retrieve the host SOF counter and | ||
404 | * kernel timestamps and store them with the SCR STC and SOF fields | ||
405 | * in the ring buffer | ||
406 | */ | ||
407 | if (has_pts && buf != NULL) | ||
408 | buf->pts = get_unaligned_le32(&data[2]); | ||
409 | |||
410 | if (!has_scr) | ||
411 | return; | ||
412 | |||
413 | /* To limit the amount of data, drop SCRs with an SOF identical to the | ||
414 | * previous one. | ||
415 | */ | ||
416 | dev_sof = get_unaligned_le16(&data[header_size - 2]); | ||
417 | if (dev_sof == stream->clock.last_sof) | ||
418 | return; | ||
419 | |||
420 | stream->clock.last_sof = dev_sof; | ||
421 | |||
422 | host_sof = usb_get_current_frame_number(stream->dev->udev); | ||
423 | ktime_get_ts(&ts); | ||
424 | |||
425 | /* The UVC specification allows device implementations that can't obtain | ||
426 | * the USB frame number to keep their own frame counters as long as they | ||
427 | * match the size and frequency of the frame number associated with USB | ||
428 | * SOF tokens. The SOF values sent by such devices differ from the USB | ||
429 | * SOF tokens by a fixed offset that needs to be estimated and accounted | ||
430 | * for to make timestamp recovery as accurate as possible. | ||
431 | * | ||
432 | * The offset is estimated the first time a device SOF value is received | ||
433 | * as the difference between the host and device SOF values. As the two | ||
434 | * SOF values can differ slightly due to transmission delays, consider | ||
435 | * that the offset is null if the difference is not higher than 10 ms | ||
436 | * (negative differences can not happen and are thus considered as an | ||
437 | * offset). The video commit control wDelay field should be used to | ||
438 | * compute a dynamic threshold instead of using a fixed 10 ms value, but | ||
439 | * devices don't report reliable wDelay values. | ||
440 | * | ||
441 | * See uvc_video_clock_host_sof() for an explanation regarding why only | ||
442 | * the 8 LSBs of the delta are kept. | ||
443 | */ | ||
444 | if (stream->clock.sof_offset == (u16)-1) { | ||
445 | u16 delta_sof = (host_sof - dev_sof) & 255; | ||
446 | if (delta_sof >= 10) | ||
447 | stream->clock.sof_offset = delta_sof; | ||
448 | else | ||
449 | stream->clock.sof_offset = 0; | ||
450 | } | ||
451 | |||
452 | dev_sof = (dev_sof + stream->clock.sof_offset) & 2047; | ||
453 | |||
454 | spin_lock_irqsave(&stream->clock.lock, flags); | ||
455 | |||
456 | sample = &stream->clock.samples[stream->clock.head]; | ||
457 | sample->dev_stc = get_unaligned_le32(&data[header_size - 6]); | ||
458 | sample->dev_sof = dev_sof; | ||
459 | sample->host_sof = host_sof; | ||
460 | sample->host_ts = ts; | ||
461 | |||
462 | /* Update the sliding window head and count. */ | ||
463 | stream->clock.head = (stream->clock.head + 1) % stream->clock.size; | ||
464 | |||
465 | if (stream->clock.count < stream->clock.size) | ||
466 | stream->clock.count++; | ||
467 | |||
468 | spin_unlock_irqrestore(&stream->clock.lock, flags); | ||
469 | } | ||
470 | |||
471 | static int uvc_video_clock_init(struct uvc_streaming *stream) | ||
472 | { | ||
473 | struct uvc_clock *clock = &stream->clock; | ||
474 | |||
475 | spin_lock_init(&clock->lock); | ||
476 | clock->head = 0; | ||
477 | clock->count = 0; | ||
478 | clock->size = 32; | ||
479 | clock->last_sof = -1; | ||
480 | clock->sof_offset = -1; | ||
481 | |||
482 | clock->samples = kmalloc(clock->size * sizeof(*clock->samples), | ||
483 | GFP_KERNEL); | ||
484 | if (clock->samples == NULL) | ||
485 | return -ENOMEM; | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static void uvc_video_clock_cleanup(struct uvc_streaming *stream) | ||
491 | { | ||
492 | kfree(stream->clock.samples); | ||
493 | stream->clock.samples = NULL; | ||
494 | } | ||
495 | |||
496 | /* | ||
497 | * uvc_video_clock_host_sof - Return the host SOF value for a clock sample | ||
498 | * | ||
499 | * Host SOF counters reported by usb_get_current_frame_number() usually don't | ||
500 | * cover the whole 11-bits SOF range (0-2047) but are limited to the HCI frame | ||
501 | * schedule window. They can be limited to 8, 9 or 10 bits depending on the host | ||
502 | * controller and its configuration. | ||
503 | * | ||
504 | * We thus need to recover the SOF value corresponding to the host frame number. | ||
505 | * As the device and host frame numbers are sampled in a short interval, the | ||
506 | * difference between their values should be equal to a small delta plus an | ||
507 | * integer multiple of 256 caused by the host frame number limited precision. | ||
508 | * | ||
509 | * To obtain the recovered host SOF value, compute the small delta by masking | ||
510 | * the high bits of the host frame counter and device SOF difference and add it | ||
511 | * to the device SOF value. | ||
512 | */ | ||
513 | static u16 uvc_video_clock_host_sof(const struct uvc_clock_sample *sample) | ||
514 | { | ||
515 | /* The delta value can be negative. */ | ||
516 | s8 delta_sof; | ||
517 | |||
518 | delta_sof = (sample->host_sof - sample->dev_sof) & 255; | ||
519 | |||
520 | return (sample->dev_sof + delta_sof) & 2047; | ||
521 | } | ||
522 | |||
523 | /* | ||
524 | * uvc_video_clock_update - Update the buffer timestamp | ||
525 | * | ||
526 | * This function converts the buffer PTS timestamp to the host clock domain by | ||
527 | * going through the USB SOF clock domain and stores the result in the V4L2 | ||
528 | * buffer timestamp field. | ||
529 | * | ||
530 | * The relationship between the device clock and the host clock isn't known. | ||
531 | * However, the device and the host share the common USB SOF clock which can be | ||
532 | * used to recover that relationship. | ||
533 | * | ||
534 | * The relationship between the device clock and the USB SOF clock is considered | ||
535 | * to be linear over the clock samples sliding window and is given by | ||
536 | * | ||
537 | * SOF = m * PTS + p | ||
538 | * | ||
539 | * Several methods to compute the slope (m) and intercept (p) can be used. As | ||
540 | * the clock drift should be small compared to the sliding window size, we | ||
541 | * assume that the line that goes through the points at both ends of the window | ||
542 | * is a good approximation. Naming those points P1 and P2, we get | ||
543 | * | ||
544 | * SOF = (SOF2 - SOF1) / (STC2 - STC1) * PTS | ||
545 | * + (SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1) | ||
546 | * | ||
547 | * or | ||
548 | * | ||
549 | * SOF = ((SOF2 - SOF1) * PTS + SOF1 * STC2 - SOF2 * STC1) / (STC2 - STC1) (1) | ||
550 | * | ||
551 | * to avoid loosing precision in the division. Similarly, the host timestamp is | ||
552 | * computed with | ||
553 | * | ||
554 | * TS = ((TS2 - TS1) * PTS + TS1 * SOF2 - TS2 * SOF1) / (SOF2 - SOF1) (2) | ||
555 | * | ||
556 | * SOF values are coded on 11 bits by USB. We extend their precision with 16 | ||
557 | * decimal bits, leading to a 11.16 coding. | ||
558 | * | ||
559 | * TODO: To avoid surprises with device clock values, PTS/STC timestamps should | ||
560 | * be normalized using the nominal device clock frequency reported through the | ||
561 | * UVC descriptors. | ||
562 | * | ||
563 | * Both the PTS/STC and SOF counters roll over, after a fixed but device | ||
564 | * specific amount of time for PTS/STC and after 2048ms for SOF. As long as the | ||
565 | * sliding window size is smaller than the rollover period, differences computed | ||
566 | * on unsigned integers will produce the correct result. However, the p term in | ||
567 | * the linear relations will be miscomputed. | ||
568 | * | ||
569 | * To fix the issue, we subtract a constant from the PTS and STC values to bring | ||
570 | * PTS to half the 32 bit STC range. The sliding window STC values then fit into | ||
571 | * the 32 bit range without any rollover. | ||
572 | * | ||
573 | * Similarly, we add 2048 to the device SOF values to make sure that the SOF | ||
574 | * computed by (1) will never be smaller than 0. This offset is then compensated | ||
575 | * by adding 2048 to the SOF values used in (2). However, this doesn't prevent | ||
576 | * rollovers between (1) and (2): the SOF value computed by (1) can be slightly | ||
577 | * lower than 4096, and the host SOF counters can have rolled over to 2048. This | ||
578 | * case is handled by subtracting 2048 from the SOF value if it exceeds the host | ||
579 | * SOF value at the end of the sliding window. | ||
580 | * | ||
581 | * Finally we subtract a constant from the host timestamps to bring the first | ||
582 | * timestamp of the sliding window to 1s. | ||
583 | */ | ||
584 | void uvc_video_clock_update(struct uvc_streaming *stream, | ||
585 | struct v4l2_buffer *v4l2_buf, | ||
586 | struct uvc_buffer *buf) | ||
587 | { | ||
588 | struct uvc_clock *clock = &stream->clock; | ||
589 | struct uvc_clock_sample *first; | ||
590 | struct uvc_clock_sample *last; | ||
591 | unsigned long flags; | ||
592 | struct timespec ts; | ||
593 | u32 delta_stc; | ||
594 | u32 y1, y2; | ||
595 | u32 x1, x2; | ||
596 | u32 mean; | ||
597 | u32 sof; | ||
598 | u32 div; | ||
599 | u32 rem; | ||
600 | u64 y; | ||
601 | |||
602 | spin_lock_irqsave(&clock->lock, flags); | ||
603 | |||
604 | if (clock->count < clock->size) | ||
605 | goto done; | ||
606 | |||
607 | first = &clock->samples[clock->head]; | ||
608 | last = &clock->samples[(clock->head - 1) % clock->size]; | ||
609 | |||
610 | /* First step, PTS to SOF conversion. */ | ||
611 | delta_stc = buf->pts - (1UL << 31); | ||
612 | x1 = first->dev_stc - delta_stc; | ||
613 | x2 = last->dev_stc - delta_stc; | ||
614 | y1 = (first->dev_sof + 2048) << 16; | ||
615 | y2 = (last->dev_sof + 2048) << 16; | ||
616 | |||
617 | if (y2 < y1) | ||
618 | y2 += 2048 << 16; | ||
619 | |||
620 | y = (u64)(y2 - y1) * (1ULL << 31) + (u64)y1 * (u64)x2 | ||
621 | - (u64)y2 * (u64)x1; | ||
622 | y = div_u64(y, x2 - x1); | ||
623 | |||
624 | sof = y; | ||
625 | |||
626 | uvc_trace(UVC_TRACE_CLOCK, "%s: PTS %u y %llu.%06llu SOF %u.%06llu " | ||
627 | "(x1 %u x2 %u y1 %u y2 %u SOF offset %u)\n", | ||
628 | stream->dev->name, buf->pts, | ||
629 | y >> 16, div_u64((y & 0xffff) * 1000000, 65536), | ||
630 | sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536), | ||
631 | x1, x2, y1, y2, clock->sof_offset); | ||
632 | |||
633 | /* Second step, SOF to host clock conversion. */ | ||
634 | ts = timespec_sub(last->host_ts, first->host_ts); | ||
635 | x1 = (uvc_video_clock_host_sof(first) + 2048) << 16; | ||
636 | x2 = (uvc_video_clock_host_sof(last) + 2048) << 16; | ||
637 | y1 = NSEC_PER_SEC; | ||
638 | y2 = (ts.tv_sec + 1) * NSEC_PER_SEC + ts.tv_nsec; | ||
639 | |||
640 | if (x2 < x1) | ||
641 | x2 += 2048 << 16; | ||
642 | |||
643 | /* Interpolated and host SOF timestamps can wrap around at slightly | ||
644 | * different times. Handle this by adding or removing 2048 to or from | ||
645 | * the computed SOF value to keep it close to the SOF samples mean | ||
646 | * value. | ||
647 | */ | ||
648 | mean = (x1 + x2) / 2; | ||
649 | if (mean - (1024 << 16) > sof) | ||
650 | sof += 2048 << 16; | ||
651 | else if (sof > mean + (1024 << 16)) | ||
652 | sof -= 2048 << 16; | ||
653 | |||
654 | y = (u64)(y2 - y1) * (u64)sof + (u64)y1 * (u64)x2 | ||
655 | - (u64)y2 * (u64)x1; | ||
656 | y = div_u64(y, x2 - x1); | ||
657 | |||
658 | div = div_u64_rem(y, NSEC_PER_SEC, &rem); | ||
659 | ts.tv_sec = first->host_ts.tv_sec - 1 + div; | ||
660 | ts.tv_nsec = first->host_ts.tv_nsec + rem; | ||
661 | if (ts.tv_nsec >= NSEC_PER_SEC) { | ||
662 | ts.tv_sec++; | ||
663 | ts.tv_nsec -= NSEC_PER_SEC; | ||
664 | } | ||
665 | |||
666 | uvc_trace(UVC_TRACE_CLOCK, "%s: SOF %u.%06llu y %llu ts %lu.%06lu " | ||
667 | "buf ts %lu.%06lu (x1 %u/%u/%u x2 %u/%u/%u y1 %u y2 %u)\n", | ||
668 | stream->dev->name, | ||
669 | sof >> 16, div_u64(((u64)sof & 0xffff) * 1000000LLU, 65536), | ||
670 | y, ts.tv_sec, ts.tv_nsec / NSEC_PER_USEC, | ||
671 | v4l2_buf->timestamp.tv_sec, v4l2_buf->timestamp.tv_usec, | ||
672 | x1, first->host_sof, first->dev_sof, | ||
673 | x2, last->host_sof, last->dev_sof, y1, y2); | ||
674 | |||
675 | /* Update the V4L2 buffer. */ | ||
676 | v4l2_buf->timestamp.tv_sec = ts.tv_sec; | ||
677 | v4l2_buf->timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC; | ||
678 | |||
679 | done: | ||
680 | spin_unlock_irqrestore(&stream->clock.lock, flags); | ||
681 | } | ||
682 | |||
360 | /* ------------------------------------------------------------------------ | 683 | /* ------------------------------------------------------------------------ |
361 | * Video codecs | 684 | * Stream statistics |
362 | */ | 685 | */ |
363 | 686 | ||
364 | /* Values for bmHeaderInfo (Video and Still Image Payload Headers, 2.4.3.3) */ | 687 | static void uvc_video_stats_decode(struct uvc_streaming *stream, |
365 | #define UVC_STREAM_EOH (1 << 7) | 688 | const __u8 *data, int len) |
366 | #define UVC_STREAM_ERR (1 << 6) | 689 | { |
367 | #define UVC_STREAM_STI (1 << 5) | 690 | unsigned int header_size; |
368 | #define UVC_STREAM_RES (1 << 4) | 691 | bool has_pts = false; |
369 | #define UVC_STREAM_SCR (1 << 3) | 692 | bool has_scr = false; |
370 | #define UVC_STREAM_PTS (1 << 2) | 693 | u16 uninitialized_var(scr_sof); |
371 | #define UVC_STREAM_EOF (1 << 1) | 694 | u32 uninitialized_var(scr_stc); |
372 | #define UVC_STREAM_FID (1 << 0) | 695 | u32 uninitialized_var(pts); |
696 | |||
697 | if (stream->stats.stream.nb_frames == 0 && | ||
698 | stream->stats.frame.nb_packets == 0) | ||
699 | ktime_get_ts(&stream->stats.stream.start_ts); | ||
700 | |||
701 | switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) { | ||
702 | case UVC_STREAM_PTS | UVC_STREAM_SCR: | ||
703 | header_size = 12; | ||
704 | has_pts = true; | ||
705 | has_scr = true; | ||
706 | break; | ||
707 | case UVC_STREAM_PTS: | ||
708 | header_size = 6; | ||
709 | has_pts = true; | ||
710 | break; | ||
711 | case UVC_STREAM_SCR: | ||
712 | header_size = 8; | ||
713 | has_scr = true; | ||
714 | break; | ||
715 | default: | ||
716 | header_size = 2; | ||
717 | break; | ||
718 | } | ||
719 | |||
720 | /* Check for invalid headers. */ | ||
721 | if (len < header_size || data[0] < header_size) { | ||
722 | stream->stats.frame.nb_invalid++; | ||
723 | return; | ||
724 | } | ||
725 | |||
726 | /* Extract the timestamps. */ | ||
727 | if (has_pts) | ||
728 | pts = get_unaligned_le32(&data[2]); | ||
729 | |||
730 | if (has_scr) { | ||
731 | scr_stc = get_unaligned_le32(&data[header_size - 6]); | ||
732 | scr_sof = get_unaligned_le16(&data[header_size - 2]); | ||
733 | } | ||
734 | |||
735 | /* Is PTS constant through the whole frame ? */ | ||
736 | if (has_pts && stream->stats.frame.nb_pts) { | ||
737 | if (stream->stats.frame.pts != pts) { | ||
738 | stream->stats.frame.nb_pts_diffs++; | ||
739 | stream->stats.frame.last_pts_diff = | ||
740 | stream->stats.frame.nb_packets; | ||
741 | } | ||
742 | } | ||
743 | |||
744 | if (has_pts) { | ||
745 | stream->stats.frame.nb_pts++; | ||
746 | stream->stats.frame.pts = pts; | ||
747 | } | ||
748 | |||
749 | /* Do all frames have a PTS in their first non-empty packet, or before | ||
750 | * their first empty packet ? | ||
751 | */ | ||
752 | if (stream->stats.frame.size == 0) { | ||
753 | if (len > header_size) | ||
754 | stream->stats.frame.has_initial_pts = has_pts; | ||
755 | if (len == header_size && has_pts) | ||
756 | stream->stats.frame.has_early_pts = true; | ||
757 | } | ||
758 | |||
759 | /* Do the SCR.STC and SCR.SOF fields vary through the frame ? */ | ||
760 | if (has_scr && stream->stats.frame.nb_scr) { | ||
761 | if (stream->stats.frame.scr_stc != scr_stc) | ||
762 | stream->stats.frame.nb_scr_diffs++; | ||
763 | } | ||
764 | |||
765 | if (has_scr) { | ||
766 | /* Expand the SOF counter to 32 bits and store its value. */ | ||
767 | if (stream->stats.stream.nb_frames > 0 || | ||
768 | stream->stats.frame.nb_scr > 0) | ||
769 | stream->stats.stream.scr_sof_count += | ||
770 | (scr_sof - stream->stats.stream.scr_sof) % 2048; | ||
771 | stream->stats.stream.scr_sof = scr_sof; | ||
772 | |||
773 | stream->stats.frame.nb_scr++; | ||
774 | stream->stats.frame.scr_stc = scr_stc; | ||
775 | stream->stats.frame.scr_sof = scr_sof; | ||
776 | |||
777 | if (scr_sof < stream->stats.stream.min_sof) | ||
778 | stream->stats.stream.min_sof = scr_sof; | ||
779 | if (scr_sof > stream->stats.stream.max_sof) | ||
780 | stream->stats.stream.max_sof = scr_sof; | ||
781 | } | ||
782 | |||
783 | /* Record the first non-empty packet number. */ | ||
784 | if (stream->stats.frame.size == 0 && len > header_size) | ||
785 | stream->stats.frame.first_data = stream->stats.frame.nb_packets; | ||
786 | |||
787 | /* Update the frame size. */ | ||
788 | stream->stats.frame.size += len - header_size; | ||
789 | |||
790 | /* Update the packets counters. */ | ||
791 | stream->stats.frame.nb_packets++; | ||
792 | if (len > header_size) | ||
793 | stream->stats.frame.nb_empty++; | ||
794 | |||
795 | if (data[1] & UVC_STREAM_ERR) | ||
796 | stream->stats.frame.nb_errors++; | ||
797 | } | ||
798 | |||
799 | static void uvc_video_stats_update(struct uvc_streaming *stream) | ||
800 | { | ||
801 | struct uvc_stats_frame *frame = &stream->stats.frame; | ||
802 | |||
803 | uvc_trace(UVC_TRACE_STATS, "frame %u stats: %u/%u/%u packets, " | ||
804 | "%u/%u/%u pts (%searly %sinitial), %u/%u scr, " | ||
805 | "last pts/stc/sof %u/%u/%u\n", | ||
806 | stream->sequence, frame->first_data, | ||
807 | frame->nb_packets - frame->nb_empty, frame->nb_packets, | ||
808 | frame->nb_pts_diffs, frame->last_pts_diff, frame->nb_pts, | ||
809 | frame->has_early_pts ? "" : "!", | ||
810 | frame->has_initial_pts ? "" : "!", | ||
811 | frame->nb_scr_diffs, frame->nb_scr, | ||
812 | frame->pts, frame->scr_stc, frame->scr_sof); | ||
813 | |||
814 | stream->stats.stream.nb_frames++; | ||
815 | stream->stats.stream.nb_packets += stream->stats.frame.nb_packets; | ||
816 | stream->stats.stream.nb_empty += stream->stats.frame.nb_empty; | ||
817 | stream->stats.stream.nb_errors += stream->stats.frame.nb_errors; | ||
818 | stream->stats.stream.nb_invalid += stream->stats.frame.nb_invalid; | ||
819 | |||
820 | if (frame->has_early_pts) | ||
821 | stream->stats.stream.nb_pts_early++; | ||
822 | if (frame->has_initial_pts) | ||
823 | stream->stats.stream.nb_pts_initial++; | ||
824 | if (frame->last_pts_diff <= frame->first_data) | ||
825 | stream->stats.stream.nb_pts_constant++; | ||
826 | if (frame->nb_scr >= frame->nb_packets - frame->nb_empty) | ||
827 | stream->stats.stream.nb_scr_count_ok++; | ||
828 | if (frame->nb_scr_diffs + 1 == frame->nb_scr) | ||
829 | stream->stats.stream.nb_scr_diffs_ok++; | ||
830 | |||
831 | memset(&stream->stats.frame, 0, sizeof(stream->stats.frame)); | ||
832 | } | ||
833 | |||
834 | size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf, | ||
835 | size_t size) | ||
836 | { | ||
837 | unsigned int scr_sof_freq; | ||
838 | unsigned int duration; | ||
839 | struct timespec ts; | ||
840 | size_t count = 0; | ||
841 | |||
842 | ts.tv_sec = stream->stats.stream.stop_ts.tv_sec | ||
843 | - stream->stats.stream.start_ts.tv_sec; | ||
844 | ts.tv_nsec = stream->stats.stream.stop_ts.tv_nsec | ||
845 | - stream->stats.stream.start_ts.tv_nsec; | ||
846 | if (ts.tv_nsec < 0) { | ||
847 | ts.tv_sec--; | ||
848 | ts.tv_nsec += 1000000000; | ||
849 | } | ||
850 | |||
851 | /* Compute the SCR.SOF frequency estimate. At the nominal 1kHz SOF | ||
852 | * frequency this will not overflow before more than 1h. | ||
853 | */ | ||
854 | duration = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; | ||
855 | if (duration != 0) | ||
856 | scr_sof_freq = stream->stats.stream.scr_sof_count * 1000 | ||
857 | / duration; | ||
858 | else | ||
859 | scr_sof_freq = 0; | ||
860 | |||
861 | count += scnprintf(buf + count, size - count, | ||
862 | "frames: %u\npackets: %u\nempty: %u\n" | ||
863 | "errors: %u\ninvalid: %u\n", | ||
864 | stream->stats.stream.nb_frames, | ||
865 | stream->stats.stream.nb_packets, | ||
866 | stream->stats.stream.nb_empty, | ||
867 | stream->stats.stream.nb_errors, | ||
868 | stream->stats.stream.nb_invalid); | ||
869 | count += scnprintf(buf + count, size - count, | ||
870 | "pts: %u early, %u initial, %u ok\n", | ||
871 | stream->stats.stream.nb_pts_early, | ||
872 | stream->stats.stream.nb_pts_initial, | ||
873 | stream->stats.stream.nb_pts_constant); | ||
874 | count += scnprintf(buf + count, size - count, | ||
875 | "scr: %u count ok, %u diff ok\n", | ||
876 | stream->stats.stream.nb_scr_count_ok, | ||
877 | stream->stats.stream.nb_scr_diffs_ok); | ||
878 | count += scnprintf(buf + count, size - count, | ||
879 | "sof: %u <= sof <= %u, freq %u.%03u kHz\n", | ||
880 | stream->stats.stream.min_sof, | ||
881 | stream->stats.stream.max_sof, | ||
882 | scr_sof_freq / 1000, scr_sof_freq % 1000); | ||
883 | |||
884 | return count; | ||
885 | } | ||
886 | |||
887 | static void uvc_video_stats_start(struct uvc_streaming *stream) | ||
888 | { | ||
889 | memset(&stream->stats, 0, sizeof(stream->stats)); | ||
890 | stream->stats.stream.min_sof = 2048; | ||
891 | } | ||
892 | |||
893 | static void uvc_video_stats_stop(struct uvc_streaming *stream) | ||
894 | { | ||
895 | ktime_get_ts(&stream->stats.stream.stop_ts); | ||
896 | } | ||
897 | |||
898 | /* ------------------------------------------------------------------------ | ||
899 | * Video codecs | ||
900 | */ | ||
373 | 901 | ||
374 | /* Video payload decoding is handled by uvc_video_decode_start(), | 902 | /* Video payload decoding is handled by uvc_video_decode_start(), |
375 | * uvc_video_decode_data() and uvc_video_decode_end(). | 903 | * uvc_video_decode_data() and uvc_video_decode_end(). |
@@ -416,14 +944,9 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, | |||
416 | * - bHeaderLength value must be at least 2 bytes (see above) | 944 | * - bHeaderLength value must be at least 2 bytes (see above) |
417 | * - bHeaderLength value can't be larger than the packet size. | 945 | * - bHeaderLength value can't be larger than the packet size. |
418 | */ | 946 | */ |
419 | if (len < 2 || data[0] < 2 || data[0] > len) | 947 | if (len < 2 || data[0] < 2 || data[0] > len) { |
948 | stream->stats.frame.nb_invalid++; | ||
420 | return -EINVAL; | 949 | return -EINVAL; |
421 | |||
422 | /* Skip payloads marked with the error bit ("error frames"). */ | ||
423 | if (data[1] & UVC_STREAM_ERR) { | ||
424 | uvc_trace(UVC_TRACE_FRAME, "Dropping payload (error bit " | ||
425 | "set).\n"); | ||
426 | return -ENODATA; | ||
427 | } | 950 | } |
428 | 951 | ||
429 | fid = data[1] & UVC_STREAM_FID; | 952 | fid = data[1] & UVC_STREAM_FID; |
@@ -431,8 +954,14 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, | |||
431 | /* Increase the sequence number regardless of any buffer states, so | 954 | /* Increase the sequence number regardless of any buffer states, so |
432 | * that discontinuous sequence numbers always indicate lost frames. | 955 | * that discontinuous sequence numbers always indicate lost frames. |
433 | */ | 956 | */ |
434 | if (stream->last_fid != fid) | 957 | if (stream->last_fid != fid) { |
435 | stream->sequence++; | 958 | stream->sequence++; |
959 | if (stream->sequence) | ||
960 | uvc_video_stats_update(stream); | ||
961 | } | ||
962 | |||
963 | uvc_video_clock_decode(stream, buf, data, len); | ||
964 | uvc_video_stats_decode(stream, data, len); | ||
436 | 965 | ||
437 | /* Store the payload FID bit and return immediately when the buffer is | 966 | /* Store the payload FID bit and return immediately when the buffer is |
438 | * NULL. | 967 | * NULL. |
@@ -442,6 +971,13 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, | |||
442 | return -ENODATA; | 971 | return -ENODATA; |
443 | } | 972 | } |
444 | 973 | ||
974 | /* Mark the buffer as bad if the error bit is set. */ | ||
975 | if (data[1] & UVC_STREAM_ERR) { | ||
976 | uvc_trace(UVC_TRACE_FRAME, "Marking buffer as bad (error bit " | ||
977 | "set).\n"); | ||
978 | buf->error = 1; | ||
979 | } | ||
980 | |||
445 | /* Synchronize to the input stream by waiting for the FID bit to be | 981 | /* Synchronize to the input stream by waiting for the FID bit to be |
446 | * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE. | 982 | * toggled when the the buffer state is not UVC_BUF_STATE_ACTIVE. |
447 | * stream->last_fid is initialized to -1, so the first isochronous | 983 | * stream->last_fid is initialized to -1, so the first isochronous |
@@ -467,9 +1003,10 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, | |||
467 | else | 1003 | else |
468 | ktime_get_real_ts(&ts); | 1004 | ktime_get_real_ts(&ts); |
469 | 1005 | ||
470 | buf->buf.sequence = stream->sequence; | 1006 | buf->buf.v4l2_buf.sequence = stream->sequence; |
471 | buf->buf.timestamp.tv_sec = ts.tv_sec; | 1007 | buf->buf.v4l2_buf.timestamp.tv_sec = ts.tv_sec; |
472 | buf->buf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC; | 1008 | buf->buf.v4l2_buf.timestamp.tv_usec = |
1009 | ts.tv_nsec / NSEC_PER_USEC; | ||
473 | 1010 | ||
474 | /* TODO: Handle PTS and SCR. */ | 1011 | /* TODO: Handle PTS and SCR. */ |
475 | buf->state = UVC_BUF_STATE_ACTIVE; | 1012 | buf->state = UVC_BUF_STATE_ACTIVE; |
@@ -490,7 +1027,7 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, | |||
490 | * avoids detecting end of frame conditions at FID toggling if the | 1027 | * avoids detecting end of frame conditions at FID toggling if the |
491 | * previous payload had the EOF bit set. | 1028 | * previous payload had the EOF bit set. |
492 | */ | 1029 | */ |
493 | if (fid != stream->last_fid && buf->buf.bytesused != 0) { | 1030 | if (fid != stream->last_fid && buf->bytesused != 0) { |
494 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit " | 1031 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (FID bit " |
495 | "toggled).\n"); | 1032 | "toggled).\n"); |
496 | buf->state = UVC_BUF_STATE_READY; | 1033 | buf->state = UVC_BUF_STATE_READY; |
@@ -505,7 +1042,6 @@ static int uvc_video_decode_start(struct uvc_streaming *stream, | |||
505 | static void uvc_video_decode_data(struct uvc_streaming *stream, | 1042 | static void uvc_video_decode_data(struct uvc_streaming *stream, |
506 | struct uvc_buffer *buf, const __u8 *data, int len) | 1043 | struct uvc_buffer *buf, const __u8 *data, int len) |
507 | { | 1044 | { |
508 | struct uvc_video_queue *queue = &stream->queue; | ||
509 | unsigned int maxlen, nbytes; | 1045 | unsigned int maxlen, nbytes; |
510 | void *mem; | 1046 | void *mem; |
511 | 1047 | ||
@@ -513,11 +1049,11 @@ static void uvc_video_decode_data(struct uvc_streaming *stream, | |||
513 | return; | 1049 | return; |
514 | 1050 | ||
515 | /* Copy the video data to the buffer. */ | 1051 | /* Copy the video data to the buffer. */ |
516 | maxlen = buf->buf.length - buf->buf.bytesused; | 1052 | maxlen = buf->length - buf->bytesused; |
517 | mem = queue->mem + buf->buf.m.offset + buf->buf.bytesused; | 1053 | mem = buf->mem + buf->bytesused; |
518 | nbytes = min((unsigned int)len, maxlen); | 1054 | nbytes = min((unsigned int)len, maxlen); |
519 | memcpy(mem, data, nbytes); | 1055 | memcpy(mem, data, nbytes); |
520 | buf->buf.bytesused += nbytes; | 1056 | buf->bytesused += nbytes; |
521 | 1057 | ||
522 | /* Complete the current frame if the buffer size was exceeded. */ | 1058 | /* Complete the current frame if the buffer size was exceeded. */ |
523 | if (len > maxlen) { | 1059 | if (len > maxlen) { |
@@ -530,7 +1066,7 @@ static void uvc_video_decode_end(struct uvc_streaming *stream, | |||
530 | struct uvc_buffer *buf, const __u8 *data, int len) | 1066 | struct uvc_buffer *buf, const __u8 *data, int len) |
531 | { | 1067 | { |
532 | /* Mark the buffer as done if the EOF marker is set. */ | 1068 | /* Mark the buffer as done if the EOF marker is set. */ |
533 | if (data[1] & UVC_STREAM_EOF && buf->buf.bytesused != 0) { | 1069 | if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) { |
534 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); | 1070 | uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); |
535 | if (data[0] == len) | 1071 | if (data[0] == len) |
536 | uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n"); | 1072 | uvc_trace(UVC_TRACE_FRAME, "EOF in empty payload.\n"); |
@@ -568,8 +1104,8 @@ static int uvc_video_encode_data(struct uvc_streaming *stream, | |||
568 | void *mem; | 1104 | void *mem; |
569 | 1105 | ||
570 | /* Copy video data to the URB buffer. */ | 1106 | /* Copy video data to the URB buffer. */ |
571 | mem = queue->mem + buf->buf.m.offset + queue->buf_used; | 1107 | mem = buf->mem + queue->buf_used; |
572 | nbytes = min((unsigned int)len, buf->buf.bytesused - queue->buf_used); | 1108 | nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used); |
573 | nbytes = min(stream->bulk.max_payload_size - stream->bulk.payload_size, | 1109 | nbytes = min(stream->bulk.max_payload_size - stream->bulk.payload_size, |
574 | nbytes); | 1110 | nbytes); |
575 | memcpy(data, mem, nbytes); | 1111 | memcpy(data, mem, nbytes); |
@@ -624,7 +1160,7 @@ static void uvc_video_decode_isoc(struct urb *urb, struct uvc_streaming *stream, | |||
624 | urb->iso_frame_desc[i].actual_length); | 1160 | urb->iso_frame_desc[i].actual_length); |
625 | 1161 | ||
626 | if (buf->state == UVC_BUF_STATE_READY) { | 1162 | if (buf->state == UVC_BUF_STATE_READY) { |
627 | if (buf->buf.length != buf->buf.bytesused && | 1163 | if (buf->length != buf->bytesused && |
628 | !(stream->cur_format->flags & | 1164 | !(stream->cur_format->flags & |
629 | UVC_FMT_FLAG_COMPRESSED)) | 1165 | UVC_FMT_FLAG_COMPRESSED)) |
630 | buf->error = 1; | 1166 | buf->error = 1; |
@@ -724,12 +1260,12 @@ static void uvc_video_encode_bulk(struct urb *urb, struct uvc_streaming *stream, | |||
724 | stream->bulk.payload_size += ret; | 1260 | stream->bulk.payload_size += ret; |
725 | len -= ret; | 1261 | len -= ret; |
726 | 1262 | ||
727 | if (buf->buf.bytesused == stream->queue.buf_used || | 1263 | if (buf->bytesused == stream->queue.buf_used || |
728 | stream->bulk.payload_size == stream->bulk.max_payload_size) { | 1264 | stream->bulk.payload_size == stream->bulk.max_payload_size) { |
729 | if (buf->buf.bytesused == stream->queue.buf_used) { | 1265 | if (buf->bytesused == stream->queue.buf_used) { |
730 | stream->queue.buf_used = 0; | 1266 | stream->queue.buf_used = 0; |
731 | buf->state = UVC_BUF_STATE_READY; | 1267 | buf->state = UVC_BUF_STATE_READY; |
732 | buf->buf.sequence = ++stream->sequence; | 1268 | buf->buf.v4l2_buf.sequence = ++stream->sequence; |
733 | uvc_queue_next_buffer(&stream->queue, buf); | 1269 | uvc_queue_next_buffer(&stream->queue, buf); |
734 | stream->last_fid ^= UVC_STREAM_FID; | 1270 | stream->last_fid ^= UVC_STREAM_FID; |
735 | } | 1271 | } |
@@ -870,6 +1406,8 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) | |||
870 | struct urb *urb; | 1406 | struct urb *urb; |
871 | unsigned int i; | 1407 | unsigned int i; |
872 | 1408 | ||
1409 | uvc_video_stats_stop(stream); | ||
1410 | |||
873 | for (i = 0; i < UVC_URBS; ++i) { | 1411 | for (i = 0; i < UVC_URBS; ++i) { |
874 | urb = stream->urb[i]; | 1412 | urb = stream->urb[i]; |
875 | if (urb == NULL) | 1413 | if (urb == NULL) |
@@ -882,6 +1420,8 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers) | |||
882 | 1420 | ||
883 | if (free_buffers) | 1421 | if (free_buffers) |
884 | uvc_free_urb_buffers(stream); | 1422 | uvc_free_urb_buffers(stream); |
1423 | |||
1424 | uvc_video_clock_cleanup(stream); | ||
885 | } | 1425 | } |
886 | 1426 | ||
887 | /* | 1427 | /* |
@@ -1009,6 +1549,12 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags) | |||
1009 | stream->bulk.skip_payload = 0; | 1549 | stream->bulk.skip_payload = 0; |
1010 | stream->bulk.payload_size = 0; | 1550 | stream->bulk.payload_size = 0; |
1011 | 1551 | ||
1552 | uvc_video_stats_start(stream); | ||
1553 | |||
1554 | ret = uvc_video_clock_init(stream); | ||
1555 | if (ret < 0) | ||
1556 | return ret; | ||
1557 | |||
1012 | if (intf->num_altsetting > 1) { | 1558 | if (intf->num_altsetting > 1) { |
1013 | struct usb_host_endpoint *best_ep = NULL; | 1559 | struct usb_host_endpoint *best_ep = NULL; |
1014 | unsigned int best_psize = 3 * 1024; | 1560 | unsigned int best_psize = 3 * 1024; |
@@ -1283,6 +1829,11 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable) | |||
1283 | return ret; | 1829 | return ret; |
1284 | } | 1830 | } |
1285 | 1831 | ||
1286 | return uvc_init_video(stream, GFP_KERNEL); | 1832 | ret = uvc_init_video(stream, GFP_KERNEL); |
1287 | } | 1833 | if (ret < 0) { |
1834 | usb_set_interface(stream->dev->udev, stream->intfnum, 0); | ||
1835 | uvc_queue_enable(&stream->queue, 0); | ||
1836 | } | ||
1288 | 1837 | ||
1838 | return ret; | ||
1839 | } | ||
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 4c1392ebcd4b..67f88d85bb16 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/videodev2.h> | 13 | #include <linux/videodev2.h> |
14 | #include <media/media-device.h> | 14 | #include <media/media-device.h> |
15 | #include <media/v4l2-device.h> | 15 | #include <media/v4l2-device.h> |
16 | #include <media/videobuf2-core.h> | ||
16 | 17 | ||
17 | /* -------------------------------------------------------------------------- | 18 | /* -------------------------------------------------------------------------- |
18 | * UVC constants | 19 | * UVC constants |
@@ -113,6 +114,7 @@ | |||
113 | 114 | ||
114 | /* Maximum allowed number of control mappings per device */ | 115 | /* Maximum allowed number of control mappings per device */ |
115 | #define UVC_MAX_CONTROL_MAPPINGS 1024 | 116 | #define UVC_MAX_CONTROL_MAPPINGS 1024 |
117 | #define UVC_MAX_CONTROL_MENU_ENTRIES 32 | ||
116 | 118 | ||
117 | /* Devices quirks */ | 119 | /* Devices quirks */ |
118 | #define UVC_QUIRK_STATUS_INTERVAL 0x00000001 | 120 | #define UVC_QUIRK_STATUS_INTERVAL 0x00000001 |
@@ -319,35 +321,30 @@ enum uvc_buffer_state { | |||
319 | }; | 321 | }; |
320 | 322 | ||
321 | struct uvc_buffer { | 323 | struct uvc_buffer { |
322 | unsigned long vma_use_count; | 324 | struct vb2_buffer buf; |
323 | struct list_head stream; | ||
324 | |||
325 | /* Touched by interrupt handler. */ | ||
326 | struct v4l2_buffer buf; | ||
327 | struct list_head queue; | 325 | struct list_head queue; |
328 | wait_queue_head_t wait; | 326 | |
329 | enum uvc_buffer_state state; | 327 | enum uvc_buffer_state state; |
330 | unsigned int error; | 328 | unsigned int error; |
329 | |||
330 | void *mem; | ||
331 | unsigned int length; | ||
332 | unsigned int bytesused; | ||
333 | |||
334 | u32 pts; | ||
331 | }; | 335 | }; |
332 | 336 | ||
333 | #define UVC_QUEUE_STREAMING (1 << 0) | 337 | #define UVC_QUEUE_DISCONNECTED (1 << 0) |
334 | #define UVC_QUEUE_DISCONNECTED (1 << 1) | 338 | #define UVC_QUEUE_DROP_CORRUPTED (1 << 1) |
335 | #define UVC_QUEUE_DROP_CORRUPTED (1 << 2) | ||
336 | 339 | ||
337 | struct uvc_video_queue { | 340 | struct uvc_video_queue { |
338 | enum v4l2_buf_type type; | 341 | struct vb2_queue queue; |
342 | struct mutex mutex; /* Protects queue */ | ||
339 | 343 | ||
340 | void *mem; | ||
341 | unsigned int flags; | 344 | unsigned int flags; |
342 | |||
343 | unsigned int count; | ||
344 | unsigned int buf_size; | ||
345 | unsigned int buf_used; | 345 | unsigned int buf_used; |
346 | struct uvc_buffer buffer[UVC_MAX_VIDEO_BUFFERS]; | ||
347 | struct mutex mutex; /* protects buffers and mainqueue */ | ||
348 | spinlock_t irqlock; /* protects irqqueue */ | ||
349 | 346 | ||
350 | struct list_head mainqueue; | 347 | spinlock_t irqlock; /* Protects irqqueue */ |
351 | struct list_head irqqueue; | 348 | struct list_head irqqueue; |
352 | }; | 349 | }; |
353 | 350 | ||
@@ -362,6 +359,51 @@ struct uvc_video_chain { | |||
362 | struct mutex ctrl_mutex; /* Protects ctrl.info */ | 359 | struct mutex ctrl_mutex; /* Protects ctrl.info */ |
363 | }; | 360 | }; |
364 | 361 | ||
362 | struct uvc_stats_frame { | ||
363 | unsigned int size; /* Number of bytes captured */ | ||
364 | unsigned int first_data; /* Index of the first non-empty packet */ | ||
365 | |||
366 | unsigned int nb_packets; /* Number of packets */ | ||
367 | unsigned int nb_empty; /* Number of empty packets */ | ||
368 | unsigned int nb_invalid; /* Number of packets with an invalid header */ | ||
369 | unsigned int nb_errors; /* Number of packets with the error bit set */ | ||
370 | |||
371 | unsigned int nb_pts; /* Number of packets with a PTS timestamp */ | ||
372 | unsigned int nb_pts_diffs; /* Number of PTS differences inside a frame */ | ||
373 | unsigned int last_pts_diff; /* Index of the last PTS difference */ | ||
374 | bool has_initial_pts; /* Whether the first non-empty packet has a PTS */ | ||
375 | bool has_early_pts; /* Whether a PTS is present before the first non-empty packet */ | ||
376 | u32 pts; /* PTS of the last packet */ | ||
377 | |||
378 | unsigned int nb_scr; /* Number of packets with a SCR timestamp */ | ||
379 | unsigned int nb_scr_diffs; /* Number of SCR.STC differences inside a frame */ | ||
380 | u16 scr_sof; /* SCR.SOF of the last packet */ | ||
381 | u32 scr_stc; /* SCR.STC of the last packet */ | ||
382 | }; | ||
383 | |||
384 | struct uvc_stats_stream { | ||
385 | struct timespec start_ts; /* Stream start timestamp */ | ||
386 | struct timespec stop_ts; /* Stream stop timestamp */ | ||
387 | |||
388 | unsigned int nb_frames; /* Number of frames */ | ||
389 | |||
390 | unsigned int nb_packets; /* Number of packets */ | ||
391 | unsigned int nb_empty; /* Number of empty packets */ | ||
392 | unsigned int nb_invalid; /* Number of packets with an invalid header */ | ||
393 | unsigned int nb_errors; /* Number of packets with the error bit set */ | ||
394 | |||
395 | unsigned int nb_pts_constant; /* Number of frames with constant PTS */ | ||
396 | unsigned int nb_pts_early; /* Number of frames with early PTS */ | ||
397 | unsigned int nb_pts_initial; /* Number of frames with initial PTS */ | ||
398 | |||
399 | unsigned int nb_scr_count_ok; /* Number of frames with at least one SCR per non empty packet */ | ||
400 | unsigned int nb_scr_diffs_ok; /* Number of frames with varying SCR.STC */ | ||
401 | unsigned int scr_sof_count; /* STC.SOF counter accumulated since stream start */ | ||
402 | unsigned int scr_sof; /* STC.SOF of the last packet */ | ||
403 | unsigned int min_sof; /* Minimum STC.SOF value */ | ||
404 | unsigned int max_sof; /* Maximum STC.SOF value */ | ||
405 | }; | ||
406 | |||
365 | struct uvc_streaming { | 407 | struct uvc_streaming { |
366 | struct list_head list; | 408 | struct list_head list; |
367 | struct uvc_device *dev; | 409 | struct uvc_device *dev; |
@@ -387,6 +429,7 @@ struct uvc_streaming { | |||
387 | */ | 429 | */ |
388 | struct mutex mutex; | 430 | struct mutex mutex; |
389 | 431 | ||
432 | /* Buffers queue. */ | ||
390 | unsigned int frozen : 1; | 433 | unsigned int frozen : 1; |
391 | struct uvc_video_queue queue; | 434 | struct uvc_video_queue queue; |
392 | void (*decode) (struct urb *urb, struct uvc_streaming *video, | 435 | void (*decode) (struct urb *urb, struct uvc_streaming *video, |
@@ -408,6 +451,32 @@ struct uvc_streaming { | |||
408 | 451 | ||
409 | __u32 sequence; | 452 | __u32 sequence; |
410 | __u8 last_fid; | 453 | __u8 last_fid; |
454 | |||
455 | /* debugfs */ | ||
456 | struct dentry *debugfs_dir; | ||
457 | struct { | ||
458 | struct uvc_stats_frame frame; | ||
459 | struct uvc_stats_stream stream; | ||
460 | } stats; | ||
461 | |||
462 | /* Timestamps support. */ | ||
463 | struct uvc_clock { | ||
464 | struct uvc_clock_sample { | ||
465 | u32 dev_stc; | ||
466 | u16 dev_sof; | ||
467 | struct timespec host_ts; | ||
468 | u16 host_sof; | ||
469 | } *samples; | ||
470 | |||
471 | unsigned int head; | ||
472 | unsigned int count; | ||
473 | unsigned int size; | ||
474 | |||
475 | u16 last_sof; | ||
476 | u16 sof_offset; | ||
477 | |||
478 | spinlock_t lock; | ||
479 | } clock; | ||
411 | }; | 480 | }; |
412 | 481 | ||
413 | enum uvc_device_state { | 482 | enum uvc_device_state { |
@@ -479,9 +548,12 @@ struct uvc_driver { | |||
479 | #define UVC_TRACE_SUSPEND (1 << 8) | 548 | #define UVC_TRACE_SUSPEND (1 << 8) |
480 | #define UVC_TRACE_STATUS (1 << 9) | 549 | #define UVC_TRACE_STATUS (1 << 9) |
481 | #define UVC_TRACE_VIDEO (1 << 10) | 550 | #define UVC_TRACE_VIDEO (1 << 10) |
551 | #define UVC_TRACE_STATS (1 << 11) | ||
552 | #define UVC_TRACE_CLOCK (1 << 12) | ||
482 | 553 | ||
483 | #define UVC_WARN_MINMAX 0 | 554 | #define UVC_WARN_MINMAX 0 |
484 | #define UVC_WARN_PROBE_DEF 1 | 555 | #define UVC_WARN_PROBE_DEF 1 |
556 | #define UVC_WARN_XU_GET_RES 2 | ||
485 | 557 | ||
486 | extern unsigned int uvc_clock_param; | 558 | extern unsigned int uvc_clock_param; |
487 | extern unsigned int uvc_no_drop_param; | 559 | extern unsigned int uvc_no_drop_param; |
@@ -516,8 +588,8 @@ extern struct uvc_entity *uvc_entity_by_id(struct uvc_device *dev, int id); | |||
516 | extern void uvc_queue_init(struct uvc_video_queue *queue, | 588 | extern void uvc_queue_init(struct uvc_video_queue *queue, |
517 | enum v4l2_buf_type type, int drop_corrupted); | 589 | enum v4l2_buf_type type, int drop_corrupted); |
518 | extern int uvc_alloc_buffers(struct uvc_video_queue *queue, | 590 | extern int uvc_alloc_buffers(struct uvc_video_queue *queue, |
519 | unsigned int nbuffers, unsigned int buflength); | 591 | struct v4l2_requestbuffers *rb); |
520 | extern int uvc_free_buffers(struct uvc_video_queue *queue); | 592 | extern void uvc_free_buffers(struct uvc_video_queue *queue); |
521 | extern int uvc_query_buffer(struct uvc_video_queue *queue, | 593 | extern int uvc_query_buffer(struct uvc_video_queue *queue, |
522 | struct v4l2_buffer *v4l2_buf); | 594 | struct v4l2_buffer *v4l2_buf); |
523 | extern int uvc_queue_buffer(struct uvc_video_queue *queue, | 595 | extern int uvc_queue_buffer(struct uvc_video_queue *queue, |
@@ -539,7 +611,7 @@ extern unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, | |||
539 | extern int uvc_queue_allocated(struct uvc_video_queue *queue); | 611 | extern int uvc_queue_allocated(struct uvc_video_queue *queue); |
540 | static inline int uvc_queue_streaming(struct uvc_video_queue *queue) | 612 | static inline int uvc_queue_streaming(struct uvc_video_queue *queue) |
541 | { | 613 | { |
542 | return queue->flags & UVC_QUEUE_STREAMING; | 614 | return vb2_is_streaming(&queue->queue); |
543 | } | 615 | } |
544 | 616 | ||
545 | /* V4L2 interface */ | 617 | /* V4L2 interface */ |
@@ -556,10 +628,11 @@ extern int uvc_video_resume(struct uvc_streaming *stream, int reset); | |||
556 | extern int uvc_video_enable(struct uvc_streaming *stream, int enable); | 628 | extern int uvc_video_enable(struct uvc_streaming *stream, int enable); |
557 | extern int uvc_probe_video(struct uvc_streaming *stream, | 629 | extern int uvc_probe_video(struct uvc_streaming *stream, |
558 | struct uvc_streaming_control *probe); | 630 | struct uvc_streaming_control *probe); |
559 | extern int uvc_commit_video(struct uvc_streaming *stream, | ||
560 | struct uvc_streaming_control *ctrl); | ||
561 | extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, | 631 | extern int uvc_query_ctrl(struct uvc_device *dev, __u8 query, __u8 unit, |
562 | __u8 intfnum, __u8 cs, void *data, __u16 size); | 632 | __u8 intfnum, __u8 cs, void *data, __u16 size); |
633 | void uvc_video_clock_update(struct uvc_streaming *stream, | ||
634 | struct v4l2_buffer *v4l2_buf, | ||
635 | struct uvc_buffer *buf); | ||
563 | 636 | ||
564 | /* Status */ | 637 | /* Status */ |
565 | extern int uvc_status_init(struct uvc_device *dev); | 638 | extern int uvc_status_init(struct uvc_device *dev); |
@@ -612,4 +685,13 @@ extern struct usb_host_endpoint *uvc_find_endpoint( | |||
612 | void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream, | 685 | void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream, |
613 | struct uvc_buffer *buf); | 686 | struct uvc_buffer *buf); |
614 | 687 | ||
688 | /* debugfs and statistics */ | ||
689 | int uvc_debugfs_init(void); | ||
690 | void uvc_debugfs_cleanup(void); | ||
691 | int uvc_debugfs_init_stream(struct uvc_streaming *stream); | ||
692 | void uvc_debugfs_cleanup_stream(struct uvc_streaming *stream); | ||
693 | |||
694 | size_t uvc_video_stats_dump(struct uvc_streaming *stream, char *buf, | ||
695 | size_t size); | ||
696 | |||
615 | #endif | 697 | #endif |
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c index c68531b88279..af4419e6c658 100644 --- a/drivers/media/video/v4l2-compat-ioctl32.c +++ b/drivers/media/video/v4l2-compat-ioctl32.c | |||
@@ -985,6 +985,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) | |||
985 | case VIDIOC_CROPCAP: | 985 | case VIDIOC_CROPCAP: |
986 | case VIDIOC_G_CROP: | 986 | case VIDIOC_G_CROP: |
987 | case VIDIOC_S_CROP: | 987 | case VIDIOC_S_CROP: |
988 | case VIDIOC_G_SELECTION: | ||
989 | case VIDIOC_S_SELECTION: | ||
988 | case VIDIOC_G_JPEGCOMP: | 990 | case VIDIOC_G_JPEGCOMP: |
989 | case VIDIOC_S_JPEGCOMP: | 991 | case VIDIOC_S_JPEGCOMP: |
990 | case VIDIOC_QUERYSTD: | 992 | case VIDIOC_QUERYSTD: |
diff --git a/drivers/media/video/v4l2-ctrls.c b/drivers/media/video/v4l2-ctrls.c index 0f415dade05a..da1f4c2d2d4b 100644 --- a/drivers/media/video/v4l2-ctrls.c +++ b/drivers/media/video/v4l2-ctrls.c | |||
@@ -467,6 +467,7 @@ const char *v4l2_ctrl_get_name(u32 id) | |||
467 | case V4L2_CID_ILLUMINATORS_2: return "Illuminator 2"; | 467 | case V4L2_CID_ILLUMINATORS_2: return "Illuminator 2"; |
468 | case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: return "Minimum Number of Capture Buffers"; | 468 | case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE: return "Minimum Number of Capture Buffers"; |
469 | case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: return "Minimum Number of Output Buffers"; | 469 | case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT: return "Minimum Number of Output Buffers"; |
470 | case V4L2_CID_ALPHA_COMPONENT: return "Alpha Component"; | ||
470 | 471 | ||
471 | /* MPEG controls */ | 472 | /* MPEG controls */ |
472 | /* Keep the order of the 'case's the same as in videodev2.h! */ | 473 | /* Keep the order of the 'case's the same as in videodev2.h! */ |
@@ -1108,8 +1109,8 @@ int v4l2_ctrl_handler_init(struct v4l2_ctrl_handler *hdl, | |||
1108 | INIT_LIST_HEAD(&hdl->ctrls); | 1109 | INIT_LIST_HEAD(&hdl->ctrls); |
1109 | INIT_LIST_HEAD(&hdl->ctrl_refs); | 1110 | INIT_LIST_HEAD(&hdl->ctrl_refs); |
1110 | hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8; | 1111 | hdl->nr_of_buckets = 1 + nr_of_controls_hint / 8; |
1111 | hdl->buckets = kzalloc(sizeof(hdl->buckets[0]) * hdl->nr_of_buckets, | 1112 | hdl->buckets = kcalloc(hdl->nr_of_buckets, sizeof(hdl->buckets[0]), |
1112 | GFP_KERNEL); | 1113 | GFP_KERNEL); |
1113 | hdl->error = hdl->buckets ? 0 : -ENOMEM; | 1114 | hdl->error = hdl->buckets ? 0 : -ENOMEM; |
1114 | return hdl->error; | 1115 | return hdl->error; |
1115 | } | 1116 | } |
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index a5c9ed128b97..96e9615663e9 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c | |||
@@ -146,10 +146,9 @@ static void v4l2_device_release(struct device *cd) | |||
146 | struct v4l2_device *v4l2_dev = vdev->v4l2_dev; | 146 | struct v4l2_device *v4l2_dev = vdev->v4l2_dev; |
147 | 147 | ||
148 | mutex_lock(&videodev_lock); | 148 | mutex_lock(&videodev_lock); |
149 | if (video_device[vdev->minor] != vdev) { | 149 | if (WARN_ON(video_device[vdev->minor] != vdev)) { |
150 | mutex_unlock(&videodev_lock); | ||
151 | /* should not happen */ | 150 | /* should not happen */ |
152 | WARN_ON(1); | 151 | mutex_unlock(&videodev_lock); |
153 | return; | 152 | return; |
154 | } | 153 | } |
155 | 154 | ||
@@ -168,7 +167,7 @@ static void v4l2_device_release(struct device *cd) | |||
168 | mutex_unlock(&videodev_lock); | 167 | mutex_unlock(&videodev_lock); |
169 | 168 | ||
170 | #if defined(CONFIG_MEDIA_CONTROLLER) | 169 | #if defined(CONFIG_MEDIA_CONTROLLER) |
171 | if (vdev->v4l2_dev && vdev->v4l2_dev->mdev && | 170 | if (v4l2_dev && v4l2_dev->mdev && |
172 | vdev->vfl_type != VFL_TYPE_SUBDEV) | 171 | vdev->vfl_type != VFL_TYPE_SUBDEV) |
173 | media_device_unregister_entity(&vdev->entity); | 172 | media_device_unregister_entity(&vdev->entity); |
174 | #endif | 173 | #endif |
@@ -556,8 +555,7 @@ int __video_register_device(struct video_device *vdev, int type, int nr, | |||
556 | vdev->minor = -1; | 555 | vdev->minor = -1; |
557 | 556 | ||
558 | /* the release callback MUST be present */ | 557 | /* the release callback MUST be present */ |
559 | WARN_ON(!vdev->release); | 558 | if (WARN_ON(!vdev->release)) |
560 | if (!vdev->release) | ||
561 | return -EINVAL; | 559 | return -EINVAL; |
562 | 560 | ||
563 | /* v4l2_fh support */ | 561 | /* v4l2_fh support */ |
@@ -703,8 +701,8 @@ int __video_register_device(struct video_device *vdev, int type, int nr, | |||
703 | vdev->vfl_type != VFL_TYPE_SUBDEV) { | 701 | vdev->vfl_type != VFL_TYPE_SUBDEV) { |
704 | vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L; | 702 | vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L; |
705 | vdev->entity.name = vdev->name; | 703 | vdev->entity.name = vdev->name; |
706 | vdev->entity.v4l.major = VIDEO_MAJOR; | 704 | vdev->entity.info.v4l.major = VIDEO_MAJOR; |
707 | vdev->entity.v4l.minor = vdev->minor; | 705 | vdev->entity.info.v4l.minor = vdev->minor; |
708 | ret = media_device_register_entity(vdev->v4l2_dev->mdev, | 706 | ret = media_device_register_entity(vdev->v4l2_dev->mdev, |
709 | &vdev->entity); | 707 | &vdev->entity); |
710 | if (ret < 0) | 708 | if (ret < 0) |
diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index 0edd618b9ddf..1f203b85a637 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c | |||
@@ -234,8 +234,8 @@ int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev) | |||
234 | goto clean_up; | 234 | goto clean_up; |
235 | } | 235 | } |
236 | #if defined(CONFIG_MEDIA_CONTROLLER) | 236 | #if defined(CONFIG_MEDIA_CONTROLLER) |
237 | sd->entity.v4l.major = VIDEO_MAJOR; | 237 | sd->entity.info.v4l.major = VIDEO_MAJOR; |
238 | sd->entity.v4l.minor = vdev->minor; | 238 | sd->entity.info.v4l.minor = vdev->minor; |
239 | #endif | 239 | #endif |
240 | sd->devnode = vdev; | 240 | sd->devnode = vdev; |
241 | } | 241 | } |
diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c index e1da8fc9dd2f..77feeb67e2db 100644 --- a/drivers/media/video/v4l2-ioctl.c +++ b/drivers/media/video/v4l2-ioctl.c | |||
@@ -238,6 +238,8 @@ static const char *v4l2_ioctls[] = { | |||
238 | [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP", | 238 | [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP", |
239 | [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP", | 239 | [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP", |
240 | [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP", | 240 | [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP", |
241 | [_IOC_NR(VIDIOC_G_SELECTION)] = "VIDIOC_G_SELECTION", | ||
242 | [_IOC_NR(VIDIOC_S_SELECTION)] = "VIDIOC_S_SELECTION", | ||
241 | [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP", | 243 | [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP", |
242 | [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP", | 244 | [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP", |
243 | [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD", | 245 | [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD", |
@@ -1547,11 +1549,32 @@ static long __video_do_ioctl(struct file *file, | |||
1547 | { | 1549 | { |
1548 | struct v4l2_crop *p = arg; | 1550 | struct v4l2_crop *p = arg; |
1549 | 1551 | ||
1550 | if (!ops->vidioc_g_crop) | 1552 | if (!ops->vidioc_g_crop && !ops->vidioc_g_selection) |
1551 | break; | 1553 | break; |
1552 | 1554 | ||
1553 | dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); | 1555 | dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); |
1554 | ret = ops->vidioc_g_crop(file, fh, p); | 1556 | |
1557 | if (ops->vidioc_g_crop) { | ||
1558 | ret = ops->vidioc_g_crop(file, fh, p); | ||
1559 | } else { | ||
1560 | /* simulate capture crop using selection api */ | ||
1561 | struct v4l2_selection s = { | ||
1562 | .type = p->type, | ||
1563 | }; | ||
1564 | |||
1565 | /* crop means compose for output devices */ | ||
1566 | if (V4L2_TYPE_IS_OUTPUT(p->type)) | ||
1567 | s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; | ||
1568 | else | ||
1569 | s.target = V4L2_SEL_TGT_CROP_ACTIVE; | ||
1570 | |||
1571 | ret = ops->vidioc_g_selection(file, fh, &s); | ||
1572 | |||
1573 | /* copying results to old structure on success */ | ||
1574 | if (!ret) | ||
1575 | p->c = s.r; | ||
1576 | } | ||
1577 | |||
1555 | if (!ret) | 1578 | if (!ret) |
1556 | dbgrect(vfd, "", &p->c); | 1579 | dbgrect(vfd, "", &p->c); |
1557 | break; | 1580 | break; |
@@ -1560,15 +1583,65 @@ static long __video_do_ioctl(struct file *file, | |||
1560 | { | 1583 | { |
1561 | struct v4l2_crop *p = arg; | 1584 | struct v4l2_crop *p = arg; |
1562 | 1585 | ||
1563 | if (!ops->vidioc_s_crop) | 1586 | if (!ops->vidioc_s_crop && !ops->vidioc_s_selection) |
1564 | break; | 1587 | break; |
1588 | |||
1565 | if (ret_prio) { | 1589 | if (ret_prio) { |
1566 | ret = ret_prio; | 1590 | ret = ret_prio; |
1567 | break; | 1591 | break; |
1568 | } | 1592 | } |
1569 | dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); | 1593 | dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); |
1570 | dbgrect(vfd, "", &p->c); | 1594 | dbgrect(vfd, "", &p->c); |
1571 | ret = ops->vidioc_s_crop(file, fh, p); | 1595 | |
1596 | if (ops->vidioc_s_crop) { | ||
1597 | ret = ops->vidioc_s_crop(file, fh, p); | ||
1598 | } else { | ||
1599 | /* simulate capture crop using selection api */ | ||
1600 | struct v4l2_selection s = { | ||
1601 | .type = p->type, | ||
1602 | .r = p->c, | ||
1603 | }; | ||
1604 | |||
1605 | /* crop means compose for output devices */ | ||
1606 | if (V4L2_TYPE_IS_OUTPUT(p->type)) | ||
1607 | s.target = V4L2_SEL_TGT_COMPOSE_ACTIVE; | ||
1608 | else | ||
1609 | s.target = V4L2_SEL_TGT_CROP_ACTIVE; | ||
1610 | |||
1611 | ret = ops->vidioc_s_selection(file, fh, &s); | ||
1612 | } | ||
1613 | break; | ||
1614 | } | ||
1615 | case VIDIOC_G_SELECTION: | ||
1616 | { | ||
1617 | struct v4l2_selection *p = arg; | ||
1618 | |||
1619 | if (!ops->vidioc_g_selection) | ||
1620 | break; | ||
1621 | |||
1622 | dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); | ||
1623 | |||
1624 | ret = ops->vidioc_g_selection(file, fh, p); | ||
1625 | if (!ret) | ||
1626 | dbgrect(vfd, "", &p->r); | ||
1627 | break; | ||
1628 | } | ||
1629 | case VIDIOC_S_SELECTION: | ||
1630 | { | ||
1631 | struct v4l2_selection *p = arg; | ||
1632 | |||
1633 | if (!ops->vidioc_s_selection) | ||
1634 | break; | ||
1635 | |||
1636 | if (ret_prio) { | ||
1637 | ret = ret_prio; | ||
1638 | break; | ||
1639 | } | ||
1640 | |||
1641 | dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); | ||
1642 | dbgrect(vfd, "", &p->r); | ||
1643 | |||
1644 | ret = ops->vidioc_s_selection(file, fh, p); | ||
1572 | break; | 1645 | break; |
1573 | } | 1646 | } |
1574 | case VIDIOC_CROPCAP: | 1647 | case VIDIOC_CROPCAP: |
@@ -1576,11 +1649,42 @@ static long __video_do_ioctl(struct file *file, | |||
1576 | struct v4l2_cropcap *p = arg; | 1649 | struct v4l2_cropcap *p = arg; |
1577 | 1650 | ||
1578 | /*FIXME: Should also show v4l2_fract pixelaspect */ | 1651 | /*FIXME: Should also show v4l2_fract pixelaspect */ |
1579 | if (!ops->vidioc_cropcap) | 1652 | if (!ops->vidioc_cropcap && !ops->vidioc_g_selection) |
1580 | break; | 1653 | break; |
1581 | 1654 | ||
1582 | dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); | 1655 | dbgarg(cmd, "type=%s\n", prt_names(p->type, v4l2_type_names)); |
1583 | ret = ops->vidioc_cropcap(file, fh, p); | 1656 | if (ops->vidioc_cropcap) { |
1657 | ret = ops->vidioc_cropcap(file, fh, p); | ||
1658 | } else { | ||
1659 | struct v4l2_selection s = { .type = p->type }; | ||
1660 | |||
1661 | /* obtaining bounds */ | ||
1662 | if (V4L2_TYPE_IS_OUTPUT(p->type)) | ||
1663 | s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS; | ||
1664 | else | ||
1665 | s.target = V4L2_SEL_TGT_CROP_BOUNDS; | ||
1666 | |||
1667 | ret = ops->vidioc_g_selection(file, fh, &s); | ||
1668 | if (ret) | ||
1669 | break; | ||
1670 | p->bounds = s.r; | ||
1671 | |||
1672 | /* obtaining defrect */ | ||
1673 | if (V4L2_TYPE_IS_OUTPUT(p->type)) | ||
1674 | s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT; | ||
1675 | else | ||
1676 | s.target = V4L2_SEL_TGT_CROP_DEFAULT; | ||
1677 | |||
1678 | ret = ops->vidioc_g_selection(file, fh, &s); | ||
1679 | if (ret) | ||
1680 | break; | ||
1681 | p->defrect = s.r; | ||
1682 | |||
1683 | /* setting trivial pixelaspect */ | ||
1684 | p->pixelaspect.numerator = 1; | ||
1685 | p->pixelaspect.denominator = 1; | ||
1686 | } | ||
1687 | |||
1584 | if (!ret) { | 1688 | if (!ret) { |
1585 | dbgrect(vfd, "bounds ", &p->bounds); | 1689 | dbgrect(vfd, "bounds ", &p->bounds); |
1586 | dbgrect(vfd, "defrect ", &p->defrect); | 1690 | dbgrect(vfd, "defrect ", &p->defrect); |
@@ -2226,6 +2330,10 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size, | |||
2226 | struct v4l2_ext_controls *ctrls = parg; | 2330 | struct v4l2_ext_controls *ctrls = parg; |
2227 | 2331 | ||
2228 | if (ctrls->count != 0) { | 2332 | if (ctrls->count != 0) { |
2333 | if (ctrls->count > V4L2_CID_MAX_CTRLS) { | ||
2334 | ret = -EINVAL; | ||
2335 | break; | ||
2336 | } | ||
2229 | *user_ptr = (void __user *)ctrls->controls; | 2337 | *user_ptr = (void __user *)ctrls->controls; |
2230 | *kernel_ptr = (void *)&ctrls->controls; | 2338 | *kernel_ptr = (void *)&ctrls->controls; |
2231 | *array_size = sizeof(struct v4l2_ext_control) | 2339 | *array_size = sizeof(struct v4l2_ext_control) |
diff --git a/drivers/media/video/v4l2-subdev.c b/drivers/media/video/v4l2-subdev.c index 65ade5f03c2e..41d118ee2de6 100644 --- a/drivers/media/video/v4l2-subdev.c +++ b/drivers/media/video/v4l2-subdev.c | |||
@@ -193,6 +193,10 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
193 | return v4l2_subdev_call(sd, core, s_register, p); | 193 | return v4l2_subdev_call(sd, core, s_register, p); |
194 | } | 194 | } |
195 | #endif | 195 | #endif |
196 | |||
197 | case VIDIOC_LOG_STATUS: | ||
198 | return v4l2_subdev_call(sd, core, log_status); | ||
199 | |||
196 | #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) | 200 | #if defined(CONFIG_VIDEO_V4L2_SUBDEV_API) |
197 | case VIDIOC_SUBDEV_G_FMT: { | 201 | case VIDIOC_SUBDEV_G_FMT: { |
198 | struct v4l2_subdev_format *format = arg; | 202 | struct v4l2_subdev_format *format = arg; |
diff --git a/drivers/media/video/via-camera.c b/drivers/media/video/via-camera.c index bfae41ba53c3..20f7237b8242 100644 --- a/drivers/media/video/via-camera.c +++ b/drivers/media/video/via-camera.c | |||
@@ -156,14 +156,10 @@ static struct via_format { | |||
156 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, | 156 | .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8, |
157 | .bpp = 2, | 157 | .bpp = 2, |
158 | }, | 158 | }, |
159 | { | ||
160 | .desc = "RGB 565", | ||
161 | .pixelformat = V4L2_PIX_FMT_RGB565, | ||
162 | .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE, | ||
163 | .bpp = 2, | ||
164 | }, | ||
165 | /* RGB444 and Bayer should be doable, but have never been | 159 | /* RGB444 and Bayer should be doable, but have never been |
166 | tested with this driver. */ | 160 | tested with this driver. RGB565 seems to work at the default |
161 | resolution, but results in color corruption when being scaled by | ||
162 | viacam_set_scaled(), and is disabled as a result. */ | ||
167 | }; | 163 | }; |
168 | #define N_VIA_FMTS ARRAY_SIZE(via_formats) | 164 | #define N_VIA_FMTS ARRAY_SIZE(via_formats) |
169 | 165 | ||
@@ -1504,14 +1500,4 @@ static struct platform_driver viacam_driver = { | |||
1504 | .remove = viacam_remove, | 1500 | .remove = viacam_remove, |
1505 | }; | 1501 | }; |
1506 | 1502 | ||
1507 | static int viacam_init(void) | 1503 | module_platform_driver(viacam_driver); |
1508 | { | ||
1509 | return platform_driver_register(&viacam_driver); | ||
1510 | } | ||
1511 | module_init(viacam_init); | ||
1512 | |||
1513 | static void viacam_exit(void) | ||
1514 | { | ||
1515 | platform_driver_unregister(&viacam_driver); | ||
1516 | } | ||
1517 | module_exit(viacam_exit); | ||
diff --git a/drivers/media/video/videobuf-dvb.c b/drivers/media/video/videobuf-dvb.c index 3de7c7e4402d..59cb54aa2946 100644 --- a/drivers/media/video/videobuf-dvb.c +++ b/drivers/media/video/videobuf-dvb.c | |||
@@ -226,9 +226,10 @@ static int videobuf_dvb_register_frontend(struct dvb_adapter *adapter, | |||
226 | } | 226 | } |
227 | 227 | ||
228 | /* register network adapter */ | 228 | /* register network adapter */ |
229 | dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx); | 229 | result = dvb_net_init(adapter, &dvb->net, &dvb->demux.dmx); |
230 | if (dvb->net.dvbdev == NULL) { | 230 | if (result < 0) { |
231 | result = -ENOMEM; | 231 | printk(KERN_WARNING "%s: dvb_net_init failed (errno = %d)\n", |
232 | dvb->name, result); | ||
232 | goto fail_fe_conn; | 233 | goto fail_fe_conn; |
233 | } | 234 | } |
234 | return 0; | 235 | return 0; |
diff --git a/drivers/media/video/videobuf2-core.c b/drivers/media/video/videobuf2-core.c index 95a3f5e82aef..2e8f1df775b6 100644 --- a/drivers/media/video/videobuf2-core.c +++ b/drivers/media/video/videobuf2-core.c | |||
@@ -30,7 +30,7 @@ module_param(debug, int, 0644); | |||
30 | printk(KERN_DEBUG "vb2: " fmt, ## arg); \ | 30 | printk(KERN_DEBUG "vb2: " fmt, ## arg); \ |
31 | } while (0) | 31 | } while (0) |
32 | 32 | ||
33 | #define call_memop(q, plane, op, args...) \ | 33 | #define call_memop(q, op, args...) \ |
34 | (((q)->mem_ops->op) ? \ | 34 | (((q)->mem_ops->op) ? \ |
35 | ((q)->mem_ops->op(args)) : 0) | 35 | ((q)->mem_ops->op(args)) : 0) |
36 | 36 | ||
@@ -52,7 +52,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) | |||
52 | 52 | ||
53 | /* Allocate memory for all planes in this buffer */ | 53 | /* Allocate memory for all planes in this buffer */ |
54 | for (plane = 0; plane < vb->num_planes; ++plane) { | 54 | for (plane = 0; plane < vb->num_planes; ++plane) { |
55 | mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane], | 55 | mem_priv = call_memop(q, alloc, q->alloc_ctx[plane], |
56 | q->plane_sizes[plane]); | 56 | q->plane_sizes[plane]); |
57 | if (IS_ERR_OR_NULL(mem_priv)) | 57 | if (IS_ERR_OR_NULL(mem_priv)) |
58 | goto free; | 58 | goto free; |
@@ -65,8 +65,10 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb) | |||
65 | return 0; | 65 | return 0; |
66 | free: | 66 | free: |
67 | /* Free already allocated memory if one of the allocations failed */ | 67 | /* Free already allocated memory if one of the allocations failed */ |
68 | for (; plane > 0; --plane) | 68 | for (; plane > 0; --plane) { |
69 | call_memop(q, plane, put, vb->planes[plane - 1].mem_priv); | 69 | call_memop(q, put, vb->planes[plane - 1].mem_priv); |
70 | vb->planes[plane - 1].mem_priv = NULL; | ||
71 | } | ||
70 | 72 | ||
71 | return -ENOMEM; | 73 | return -ENOMEM; |
72 | } | 74 | } |
@@ -80,10 +82,10 @@ static void __vb2_buf_mem_free(struct vb2_buffer *vb) | |||
80 | unsigned int plane; | 82 | unsigned int plane; |
81 | 83 | ||
82 | for (plane = 0; plane < vb->num_planes; ++plane) { | 84 | for (plane = 0; plane < vb->num_planes; ++plane) { |
83 | call_memop(q, plane, put, vb->planes[plane].mem_priv); | 85 | call_memop(q, put, vb->planes[plane].mem_priv); |
84 | vb->planes[plane].mem_priv = NULL; | 86 | vb->planes[plane].mem_priv = NULL; |
85 | dprintk(3, "Freed plane %d of buffer %d\n", | 87 | dprintk(3, "Freed plane %d of buffer %d\n", plane, |
86 | plane, vb->v4l2_buf.index); | 88 | vb->v4l2_buf.index); |
87 | } | 89 | } |
88 | } | 90 | } |
89 | 91 | ||
@@ -97,12 +99,9 @@ static void __vb2_buf_userptr_put(struct vb2_buffer *vb) | |||
97 | unsigned int plane; | 99 | unsigned int plane; |
98 | 100 | ||
99 | for (plane = 0; plane < vb->num_planes; ++plane) { | 101 | for (plane = 0; plane < vb->num_planes; ++plane) { |
100 | void *mem_priv = vb->planes[plane].mem_priv; | 102 | if (vb->planes[plane].mem_priv) |
101 | 103 | call_memop(q, put_userptr, vb->planes[plane].mem_priv); | |
102 | if (mem_priv) { | 104 | vb->planes[plane].mem_priv = NULL; |
103 | call_memop(q, plane, put_userptr, mem_priv); | ||
104 | vb->planes[plane].mem_priv = NULL; | ||
105 | } | ||
106 | } | 105 | } |
107 | } | 106 | } |
108 | 107 | ||
@@ -305,7 +304,7 @@ static bool __buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb) | |||
305 | * case anyway. If num_users() returns more than 1, | 304 | * case anyway. If num_users() returns more than 1, |
306 | * we are not the only user of the plane's memory. | 305 | * we are not the only user of the plane's memory. |
307 | */ | 306 | */ |
308 | if (mem_priv && call_memop(q, plane, num_users, mem_priv) > 1) | 307 | if (mem_priv && call_memop(q, num_users, mem_priv) > 1) |
309 | return true; | 308 | return true; |
310 | } | 309 | } |
311 | return false; | 310 | return false; |
@@ -731,10 +730,10 @@ void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no) | |||
731 | { | 730 | { |
732 | struct vb2_queue *q = vb->vb2_queue; | 731 | struct vb2_queue *q = vb->vb2_queue; |
733 | 732 | ||
734 | if (plane_no > vb->num_planes) | 733 | if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv) |
735 | return NULL; | 734 | return NULL; |
736 | 735 | ||
737 | return call_memop(q, plane_no, vaddr, vb->planes[plane_no].mem_priv); | 736 | return call_memop(q, vaddr, vb->planes[plane_no].mem_priv); |
738 | 737 | ||
739 | } | 738 | } |
740 | EXPORT_SYMBOL_GPL(vb2_plane_vaddr); | 739 | EXPORT_SYMBOL_GPL(vb2_plane_vaddr); |
@@ -754,10 +753,10 @@ void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no) | |||
754 | { | 753 | { |
755 | struct vb2_queue *q = vb->vb2_queue; | 754 | struct vb2_queue *q = vb->vb2_queue; |
756 | 755 | ||
757 | if (plane_no > vb->num_planes) | 756 | if (plane_no > vb->num_planes || !vb->planes[plane_no].mem_priv) |
758 | return NULL; | 757 | return NULL; |
759 | 758 | ||
760 | return call_memop(q, plane_no, cookie, vb->planes[plane_no].mem_priv); | 759 | return call_memop(q, cookie, vb->planes[plane_no].mem_priv); |
761 | } | 760 | } |
762 | EXPORT_SYMBOL_GPL(vb2_plane_cookie); | 761 | EXPORT_SYMBOL_GPL(vb2_plane_cookie); |
763 | 762 | ||
@@ -883,7 +882,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
883 | 882 | ||
884 | for (plane = 0; plane < vb->num_planes; ++plane) { | 883 | for (plane = 0; plane < vb->num_planes; ++plane) { |
885 | /* Skip the plane if already verified */ | 884 | /* Skip the plane if already verified */ |
886 | if (vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr | 885 | if (vb->v4l2_planes[plane].m.userptr && |
886 | vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr | ||
887 | && vb->v4l2_planes[plane].length == planes[plane].length) | 887 | && vb->v4l2_planes[plane].length == planes[plane].length) |
888 | continue; | 888 | continue; |
889 | 889 | ||
@@ -898,27 +898,23 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b) | |||
898 | 898 | ||
899 | /* Release previously acquired memory if present */ | 899 | /* Release previously acquired memory if present */ |
900 | if (vb->planes[plane].mem_priv) | 900 | if (vb->planes[plane].mem_priv) |
901 | call_memop(q, plane, put_userptr, | 901 | call_memop(q, put_userptr, vb->planes[plane].mem_priv); |
902 | vb->planes[plane].mem_priv); | ||
903 | 902 | ||
904 | vb->planes[plane].mem_priv = NULL; | 903 | vb->planes[plane].mem_priv = NULL; |
905 | vb->v4l2_planes[plane].m.userptr = 0; | 904 | vb->v4l2_planes[plane].m.userptr = 0; |
906 | vb->v4l2_planes[plane].length = 0; | 905 | vb->v4l2_planes[plane].length = 0; |
907 | 906 | ||
908 | /* Acquire each plane's memory */ | 907 | /* Acquire each plane's memory */ |
909 | if (q->mem_ops->get_userptr) { | 908 | mem_priv = call_memop(q, get_userptr, q->alloc_ctx[plane], |
910 | mem_priv = q->mem_ops->get_userptr(q->alloc_ctx[plane], | 909 | planes[plane].m.userptr, |
911 | planes[plane].m.userptr, | 910 | planes[plane].length, write); |
912 | planes[plane].length, | 911 | if (IS_ERR_OR_NULL(mem_priv)) { |
913 | write); | 912 | dprintk(1, "qbuf: failed acquiring userspace " |
914 | if (IS_ERR(mem_priv)) { | ||
915 | dprintk(1, "qbuf: failed acquiring userspace " | ||
916 | "memory for plane %d\n", plane); | 913 | "memory for plane %d\n", plane); |
917 | ret = PTR_ERR(mem_priv); | 914 | ret = mem_priv ? PTR_ERR(mem_priv) : -EINVAL; |
918 | goto err; | 915 | goto err; |
919 | } | ||
920 | vb->planes[plane].mem_priv = mem_priv; | ||
921 | } | 916 | } |
917 | vb->planes[plane].mem_priv = mem_priv; | ||
922 | } | 918 | } |
923 | 919 | ||
924 | /* | 920 | /* |
@@ -943,8 +939,7 @@ err: | |||
943 | /* In case of errors, release planes that were already acquired */ | 939 | /* In case of errors, release planes that were already acquired */ |
944 | for (plane = 0; plane < vb->num_planes; ++plane) { | 940 | for (plane = 0; plane < vb->num_planes; ++plane) { |
945 | if (vb->planes[plane].mem_priv) | 941 | if (vb->planes[plane].mem_priv) |
946 | call_memop(q, plane, put_userptr, | 942 | call_memop(q, put_userptr, vb->planes[plane].mem_priv); |
947 | vb->planes[plane].mem_priv); | ||
948 | vb->planes[plane].mem_priv = NULL; | 943 | vb->planes[plane].mem_priv = NULL; |
949 | vb->v4l2_planes[plane].m.userptr = 0; | 944 | vb->v4l2_planes[plane].m.userptr = 0; |
950 | vb->v4l2_planes[plane].length = 0; | 945 | vb->v4l2_planes[plane].length = 0; |
@@ -1081,46 +1076,76 @@ EXPORT_SYMBOL_GPL(vb2_prepare_buf); | |||
1081 | */ | 1076 | */ |
1082 | int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | 1077 | int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) |
1083 | { | 1078 | { |
1079 | struct rw_semaphore *mmap_sem = NULL; | ||
1084 | struct vb2_buffer *vb; | 1080 | struct vb2_buffer *vb; |
1085 | int ret; | 1081 | int ret = 0; |
1082 | |||
1083 | /* | ||
1084 | * In case of user pointer buffers vb2 allocator needs to get direct | ||
1085 | * access to userspace pages. This requires getting read access on | ||
1086 | * mmap semaphore in the current process structure. The same | ||
1087 | * semaphore is taken before calling mmap operation, while both mmap | ||
1088 | * and qbuf are called by the driver or v4l2 core with driver's lock | ||
1089 | * held. To avoid a AB-BA deadlock (mmap_sem then driver's lock in | ||
1090 | * mmap and driver's lock then mmap_sem in qbuf) the videobuf2 core | ||
1091 | * release driver's lock, takes mmap_sem and then takes again driver's | ||
1092 | * lock. | ||
1093 | * | ||
1094 | * To avoid race with other vb2 calls, which might be called after | ||
1095 | * releasing driver's lock, this operation is performed at the | ||
1096 | * beggining of qbuf processing. This way the queue status is | ||
1097 | * consistent after getting driver's lock back. | ||
1098 | */ | ||
1099 | if (q->memory == V4L2_MEMORY_USERPTR) { | ||
1100 | mmap_sem = ¤t->mm->mmap_sem; | ||
1101 | call_qop(q, wait_prepare, q); | ||
1102 | down_read(mmap_sem); | ||
1103 | call_qop(q, wait_finish, q); | ||
1104 | } | ||
1086 | 1105 | ||
1087 | if (q->fileio) { | 1106 | if (q->fileio) { |
1088 | dprintk(1, "qbuf: file io in progress\n"); | 1107 | dprintk(1, "qbuf: file io in progress\n"); |
1089 | return -EBUSY; | 1108 | ret = -EBUSY; |
1109 | goto unlock; | ||
1090 | } | 1110 | } |
1091 | 1111 | ||
1092 | if (b->type != q->type) { | 1112 | if (b->type != q->type) { |
1093 | dprintk(1, "qbuf: invalid buffer type\n"); | 1113 | dprintk(1, "qbuf: invalid buffer type\n"); |
1094 | return -EINVAL; | 1114 | ret = -EINVAL; |
1115 | goto unlock; | ||
1095 | } | 1116 | } |
1096 | 1117 | ||
1097 | if (b->index >= q->num_buffers) { | 1118 | if (b->index >= q->num_buffers) { |
1098 | dprintk(1, "qbuf: buffer index out of range\n"); | 1119 | dprintk(1, "qbuf: buffer index out of range\n"); |
1099 | return -EINVAL; | 1120 | ret = -EINVAL; |
1121 | goto unlock; | ||
1100 | } | 1122 | } |
1101 | 1123 | ||
1102 | vb = q->bufs[b->index]; | 1124 | vb = q->bufs[b->index]; |
1103 | if (NULL == vb) { | 1125 | if (NULL == vb) { |
1104 | /* Should never happen */ | 1126 | /* Should never happen */ |
1105 | dprintk(1, "qbuf: buffer is NULL\n"); | 1127 | dprintk(1, "qbuf: buffer is NULL\n"); |
1106 | return -EINVAL; | 1128 | ret = -EINVAL; |
1129 | goto unlock; | ||
1107 | } | 1130 | } |
1108 | 1131 | ||
1109 | if (b->memory != q->memory) { | 1132 | if (b->memory != q->memory) { |
1110 | dprintk(1, "qbuf: invalid memory type\n"); | 1133 | dprintk(1, "qbuf: invalid memory type\n"); |
1111 | return -EINVAL; | 1134 | ret = -EINVAL; |
1135 | goto unlock; | ||
1112 | } | 1136 | } |
1113 | 1137 | ||
1114 | switch (vb->state) { | 1138 | switch (vb->state) { |
1115 | case VB2_BUF_STATE_DEQUEUED: | 1139 | case VB2_BUF_STATE_DEQUEUED: |
1116 | ret = __buf_prepare(vb, b); | 1140 | ret = __buf_prepare(vb, b); |
1117 | if (ret) | 1141 | if (ret) |
1118 | return ret; | 1142 | goto unlock; |
1119 | case VB2_BUF_STATE_PREPARED: | 1143 | case VB2_BUF_STATE_PREPARED: |
1120 | break; | 1144 | break; |
1121 | default: | 1145 | default: |
1122 | dprintk(1, "qbuf: buffer already in use\n"); | 1146 | dprintk(1, "qbuf: buffer already in use\n"); |
1123 | return -EINVAL; | 1147 | ret = -EINVAL; |
1148 | goto unlock; | ||
1124 | } | 1149 | } |
1125 | 1150 | ||
1126 | /* | 1151 | /* |
@@ -1141,7 +1166,10 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b) | |||
1141 | __fill_v4l2_buffer(vb, b); | 1166 | __fill_v4l2_buffer(vb, b); |
1142 | 1167 | ||
1143 | dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index); | 1168 | dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index); |
1144 | return 0; | 1169 | unlock: |
1170 | if (mmap_sem) | ||
1171 | up_read(mmap_sem); | ||
1172 | return ret; | ||
1145 | } | 1173 | } |
1146 | EXPORT_SYMBOL_GPL(vb2_qbuf); | 1174 | EXPORT_SYMBOL_GPL(vb2_qbuf); |
1147 | 1175 | ||
@@ -1521,7 +1549,6 @@ static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off, | |||
1521 | int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma) | 1549 | int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma) |
1522 | { | 1550 | { |
1523 | unsigned long off = vma->vm_pgoff << PAGE_SHIFT; | 1551 | unsigned long off = vma->vm_pgoff << PAGE_SHIFT; |
1524 | struct vb2_plane *vb_plane; | ||
1525 | struct vb2_buffer *vb; | 1552 | struct vb2_buffer *vb; |
1526 | unsigned int buffer, plane; | 1553 | unsigned int buffer, plane; |
1527 | int ret; | 1554 | int ret; |
@@ -1558,9 +1585,8 @@ int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma) | |||
1558 | return ret; | 1585 | return ret; |
1559 | 1586 | ||
1560 | vb = q->bufs[buffer]; | 1587 | vb = q->bufs[buffer]; |
1561 | vb_plane = &vb->planes[plane]; | ||
1562 | 1588 | ||
1563 | ret = q->mem_ops->mmap(vb_plane->mem_priv, vma); | 1589 | ret = call_memop(q, mmap, vb->planes[plane].mem_priv, vma); |
1564 | if (ret) | 1590 | if (ret) |
1565 | return ret; | 1591 | return ret; |
1566 | 1592 | ||
diff --git a/drivers/media/video/videobuf2-dma-sg.c b/drivers/media/video/videobuf2-dma-sg.c index 3bad8b105fea..25c3b360e1ad 100644 --- a/drivers/media/video/videobuf2-dma-sg.c +++ b/drivers/media/video/videobuf2-dma-sg.c | |||
@@ -140,7 +140,6 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr, | |||
140 | if (!buf->pages) | 140 | if (!buf->pages) |
141 | goto userptr_fail_pages_array_alloc; | 141 | goto userptr_fail_pages_array_alloc; |
142 | 142 | ||
143 | down_read(¤t->mm->mmap_sem); | ||
144 | num_pages_from_user = get_user_pages(current, current->mm, | 143 | num_pages_from_user = get_user_pages(current, current->mm, |
145 | vaddr & PAGE_MASK, | 144 | vaddr & PAGE_MASK, |
146 | buf->sg_desc.num_pages, | 145 | buf->sg_desc.num_pages, |
@@ -148,7 +147,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr, | |||
148 | 1, /* force */ | 147 | 1, /* force */ |
149 | buf->pages, | 148 | buf->pages, |
150 | NULL); | 149 | NULL); |
151 | up_read(¤t->mm->mmap_sem); | 150 | |
152 | if (num_pages_from_user != buf->sg_desc.num_pages) | 151 | if (num_pages_from_user != buf->sg_desc.num_pages) |
153 | goto userptr_fail_get_user_pages; | 152 | goto userptr_fail_get_user_pages; |
154 | 153 | ||
diff --git a/drivers/media/video/videobuf2-memops.c b/drivers/media/video/videobuf2-memops.c index 71a7a78c3fc0..c41cb60245d6 100644 --- a/drivers/media/video/videobuf2-memops.c +++ b/drivers/media/video/videobuf2-memops.c | |||
@@ -100,29 +100,26 @@ int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size, | |||
100 | unsigned long offset, start, end; | 100 | unsigned long offset, start, end; |
101 | unsigned long this_pfn, prev_pfn; | 101 | unsigned long this_pfn, prev_pfn; |
102 | dma_addr_t pa = 0; | 102 | dma_addr_t pa = 0; |
103 | int ret = -EFAULT; | ||
104 | 103 | ||
105 | start = vaddr; | 104 | start = vaddr; |
106 | offset = start & ~PAGE_MASK; | 105 | offset = start & ~PAGE_MASK; |
107 | end = start + size; | 106 | end = start + size; |
108 | 107 | ||
109 | down_read(&mm->mmap_sem); | ||
110 | vma = find_vma(mm, start); | 108 | vma = find_vma(mm, start); |
111 | 109 | ||
112 | if (vma == NULL || vma->vm_end < end) | 110 | if (vma == NULL || vma->vm_end < end) |
113 | goto done; | 111 | return -EFAULT; |
114 | 112 | ||
115 | for (prev_pfn = 0; start < end; start += PAGE_SIZE) { | 113 | for (prev_pfn = 0; start < end; start += PAGE_SIZE) { |
116 | ret = follow_pfn(vma, start, &this_pfn); | 114 | int ret = follow_pfn(vma, start, &this_pfn); |
117 | if (ret) | 115 | if (ret) |
118 | goto done; | 116 | return ret; |
119 | 117 | ||
120 | if (prev_pfn == 0) | 118 | if (prev_pfn == 0) |
121 | pa = this_pfn << PAGE_SHIFT; | 119 | pa = this_pfn << PAGE_SHIFT; |
122 | else if (this_pfn != prev_pfn + 1) { | 120 | else if (this_pfn != prev_pfn + 1) |
123 | ret = -EFAULT; | 121 | return -EFAULT; |
124 | goto done; | 122 | |
125 | } | ||
126 | prev_pfn = this_pfn; | 123 | prev_pfn = this_pfn; |
127 | } | 124 | } |
128 | 125 | ||
@@ -130,16 +127,11 @@ int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size, | |||
130 | * Memory is contigous, lock vma and return to the caller | 127 | * Memory is contigous, lock vma and return to the caller |
131 | */ | 128 | */ |
132 | *res_vma = vb2_get_vma(vma); | 129 | *res_vma = vb2_get_vma(vma); |
133 | if (*res_vma == NULL) { | 130 | if (*res_vma == NULL) |
134 | ret = -ENOMEM; | 131 | return -ENOMEM; |
135 | goto done; | ||
136 | } | ||
137 | *res_pa = pa + offset; | ||
138 | ret = 0; | ||
139 | 132 | ||
140 | done: | 133 | *res_pa = pa + offset; |
141 | up_read(&mm->mmap_sem); | 134 | return 0; |
142 | return ret; | ||
143 | } | 135 | } |
144 | EXPORT_SYMBOL_GPL(vb2_get_contig_userptr); | 136 | EXPORT_SYMBOL_GPL(vb2_get_contig_userptr); |
145 | 137 | ||
diff --git a/drivers/media/video/videobuf2-vmalloc.c b/drivers/media/video/videobuf2-vmalloc.c index a3a884234059..4e789a178f8a 100644 --- a/drivers/media/video/videobuf2-vmalloc.c +++ b/drivers/media/video/videobuf2-vmalloc.c | |||
@@ -12,6 +12,7 @@ | |||
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/mm.h> | 14 | #include <linux/mm.h> |
15 | #include <linux/sched.h> | ||
15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
16 | #include <linux/vmalloc.h> | 17 | #include <linux/vmalloc.h> |
17 | 18 | ||
@@ -20,7 +21,10 @@ | |||
20 | 21 | ||
21 | struct vb2_vmalloc_buf { | 22 | struct vb2_vmalloc_buf { |
22 | void *vaddr; | 23 | void *vaddr; |
24 | struct page **pages; | ||
25 | int write; | ||
23 | unsigned long size; | 26 | unsigned long size; |
27 | unsigned int n_pages; | ||
24 | atomic_t refcount; | 28 | atomic_t refcount; |
25 | struct vb2_vmarea_handler handler; | 29 | struct vb2_vmarea_handler handler; |
26 | }; | 30 | }; |
@@ -31,7 +35,7 @@ static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size) | |||
31 | { | 35 | { |
32 | struct vb2_vmalloc_buf *buf; | 36 | struct vb2_vmalloc_buf *buf; |
33 | 37 | ||
34 | buf = kzalloc(sizeof *buf, GFP_KERNEL); | 38 | buf = kzalloc(sizeof(*buf), GFP_KERNEL); |
35 | if (!buf) | 39 | if (!buf) |
36 | return NULL; | 40 | return NULL; |
37 | 41 | ||
@@ -42,15 +46,12 @@ static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size) | |||
42 | buf->handler.arg = buf; | 46 | buf->handler.arg = buf; |
43 | 47 | ||
44 | if (!buf->vaddr) { | 48 | if (!buf->vaddr) { |
45 | printk(KERN_ERR "vmalloc of size %ld failed\n", buf->size); | 49 | pr_debug("vmalloc of size %ld failed\n", buf->size); |
46 | kfree(buf); | 50 | kfree(buf); |
47 | return NULL; | 51 | return NULL; |
48 | } | 52 | } |
49 | 53 | ||
50 | atomic_inc(&buf->refcount); | 54 | atomic_inc(&buf->refcount); |
51 | printk(KERN_DEBUG "Allocated vmalloc buffer of size %ld at vaddr=%p\n", | ||
52 | buf->size, buf->vaddr); | ||
53 | |||
54 | return buf; | 55 | return buf; |
55 | } | 56 | } |
56 | 57 | ||
@@ -59,21 +60,84 @@ static void vb2_vmalloc_put(void *buf_priv) | |||
59 | struct vb2_vmalloc_buf *buf = buf_priv; | 60 | struct vb2_vmalloc_buf *buf = buf_priv; |
60 | 61 | ||
61 | if (atomic_dec_and_test(&buf->refcount)) { | 62 | if (atomic_dec_and_test(&buf->refcount)) { |
62 | printk(KERN_DEBUG "%s: Freeing vmalloc mem at vaddr=%p\n", | ||
63 | __func__, buf->vaddr); | ||
64 | vfree(buf->vaddr); | 63 | vfree(buf->vaddr); |
65 | kfree(buf); | 64 | kfree(buf); |
66 | } | 65 | } |
67 | } | 66 | } |
68 | 67 | ||
69 | static void *vb2_vmalloc_vaddr(void *buf_priv) | 68 | static void *vb2_vmalloc_get_userptr(void *alloc_ctx, unsigned long vaddr, |
69 | unsigned long size, int write) | ||
70 | { | ||
71 | struct vb2_vmalloc_buf *buf; | ||
72 | unsigned long first, last; | ||
73 | int n_pages, offset; | ||
74 | |||
75 | buf = kzalloc(sizeof(*buf), GFP_KERNEL); | ||
76 | if (!buf) | ||
77 | return NULL; | ||
78 | |||
79 | buf->write = write; | ||
80 | offset = vaddr & ~PAGE_MASK; | ||
81 | buf->size = size; | ||
82 | |||
83 | first = vaddr >> PAGE_SHIFT; | ||
84 | last = (vaddr + size - 1) >> PAGE_SHIFT; | ||
85 | buf->n_pages = last - first + 1; | ||
86 | buf->pages = kzalloc(buf->n_pages * sizeof(struct page *), GFP_KERNEL); | ||
87 | if (!buf->pages) | ||
88 | goto fail_pages_array_alloc; | ||
89 | |||
90 | /* current->mm->mmap_sem is taken by videobuf2 core */ | ||
91 | n_pages = get_user_pages(current, current->mm, vaddr & PAGE_MASK, | ||
92 | buf->n_pages, write, 1, /* force */ | ||
93 | buf->pages, NULL); | ||
94 | if (n_pages != buf->n_pages) | ||
95 | goto fail_get_user_pages; | ||
96 | |||
97 | buf->vaddr = vm_map_ram(buf->pages, buf->n_pages, -1, PAGE_KERNEL); | ||
98 | if (!buf->vaddr) | ||
99 | goto fail_get_user_pages; | ||
100 | |||
101 | buf->vaddr += offset; | ||
102 | return buf; | ||
103 | |||
104 | fail_get_user_pages: | ||
105 | pr_debug("get_user_pages requested/got: %d/%d]\n", n_pages, | ||
106 | buf->n_pages); | ||
107 | while (--n_pages >= 0) | ||
108 | put_page(buf->pages[n_pages]); | ||
109 | kfree(buf->pages); | ||
110 | |||
111 | fail_pages_array_alloc: | ||
112 | kfree(buf); | ||
113 | |||
114 | return NULL; | ||
115 | } | ||
116 | |||
117 | static void vb2_vmalloc_put_userptr(void *buf_priv) | ||
70 | { | 118 | { |
71 | struct vb2_vmalloc_buf *buf = buf_priv; | 119 | struct vb2_vmalloc_buf *buf = buf_priv; |
120 | unsigned long vaddr = (unsigned long)buf->vaddr & PAGE_MASK; | ||
121 | unsigned int i; | ||
122 | |||
123 | if (vaddr) | ||
124 | vm_unmap_ram((void *)vaddr, buf->n_pages); | ||
125 | for (i = 0; i < buf->n_pages; ++i) { | ||
126 | if (buf->write) | ||
127 | set_page_dirty_lock(buf->pages[i]); | ||
128 | put_page(buf->pages[i]); | ||
129 | } | ||
130 | kfree(buf->pages); | ||
131 | kfree(buf); | ||
132 | } | ||
72 | 133 | ||
73 | BUG_ON(!buf); | 134 | static void *vb2_vmalloc_vaddr(void *buf_priv) |
135 | { | ||
136 | struct vb2_vmalloc_buf *buf = buf_priv; | ||
74 | 137 | ||
75 | if (!buf->vaddr) { | 138 | if (!buf->vaddr) { |
76 | printk(KERN_ERR "Address of an unallocated plane requested\n"); | 139 | pr_err("Address of an unallocated plane requested " |
140 | "or cannot map user pointer\n"); | ||
77 | return NULL; | 141 | return NULL; |
78 | } | 142 | } |
79 | 143 | ||
@@ -92,13 +156,13 @@ static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma) | |||
92 | int ret; | 156 | int ret; |
93 | 157 | ||
94 | if (!buf) { | 158 | if (!buf) { |
95 | printk(KERN_ERR "No memory to map\n"); | 159 | pr_err("No memory to map\n"); |
96 | return -EINVAL; | 160 | return -EINVAL; |
97 | } | 161 | } |
98 | 162 | ||
99 | ret = remap_vmalloc_range(vma, buf->vaddr, 0); | 163 | ret = remap_vmalloc_range(vma, buf->vaddr, 0); |
100 | if (ret) { | 164 | if (ret) { |
101 | printk(KERN_ERR "Remapping vmalloc memory, error: %d\n", ret); | 165 | pr_err("Remapping vmalloc memory, error: %d\n", ret); |
102 | return ret; | 166 | return ret; |
103 | } | 167 | } |
104 | 168 | ||
@@ -121,6 +185,8 @@ static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma) | |||
121 | const struct vb2_mem_ops vb2_vmalloc_memops = { | 185 | const struct vb2_mem_ops vb2_vmalloc_memops = { |
122 | .alloc = vb2_vmalloc_alloc, | 186 | .alloc = vb2_vmalloc_alloc, |
123 | .put = vb2_vmalloc_put, | 187 | .put = vb2_vmalloc_put, |
188 | .get_userptr = vb2_vmalloc_get_userptr, | ||
189 | .put_userptr = vb2_vmalloc_put_userptr, | ||
124 | .vaddr = vb2_vmalloc_vaddr, | 190 | .vaddr = vb2_vmalloc_vaddr, |
125 | .mmap = vb2_vmalloc_mmap, | 191 | .mmap = vb2_vmalloc_mmap, |
126 | .num_users = vb2_vmalloc_num_users, | 192 | .num_users = vb2_vmalloc_num_users, |
diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index 52a0a3736c82..4d7391ec8001 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c | |||
@@ -708,7 +708,7 @@ static int vino_allocate_buffer(struct vino_framebuffer *fb, | |||
708 | size, count); | 708 | size, count); |
709 | 709 | ||
710 | /* allocate memory for table with virtual (page) addresses */ | 710 | /* allocate memory for table with virtual (page) addresses */ |
711 | fb->desc_table.virtual = (unsigned long *) | 711 | fb->desc_table.virtual = |
712 | kmalloc(count * sizeof(unsigned long), GFP_KERNEL); | 712 | kmalloc(count * sizeof(unsigned long), GFP_KERNEL); |
713 | if (!fb->desc_table.virtual) | 713 | if (!fb->desc_table.virtual) |
714 | return -ENOMEM; | 714 | return -ENOMEM; |