From: Arne Fitzenreiter Date: Sat, 31 Aug 2013 13:08:03 +0000 (+0200) Subject: kernel: update to 3.10.10. X-Git-Url: http://git.ipfire.org/?p=people%2Fteissler%2Fipfire-2.x.git;a=commitdiff_plain;h=e2b79cd11e413ab74126a2475f7de46a331da865 kernel: update to 3.10.10. enabled all DVB Devices and add some patches. --- diff --git a/config/kernel/kernel.config.i586-ipfire b/config/kernel/kernel.config.i586-ipfire index 131b8dfe8..711879065 100644 --- a/config/kernel/kernel.config.i586-ipfire +++ b/config/kernel/kernel.config.i586-ipfire @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 3.10.9 Kernel Configuration +# Linux/x86 3.10.10 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -375,6 +375,7 @@ CONFIG_X86_GENERIC=y CONFIG_X86_INTERNODE_CACHE_SHIFT=6 CONFIG_X86_L1_CACHE_SHIFT=6 # CONFIG_X86_PPRO_FENCE is not set +CONFIG_X86_F00F_BUG=y CONFIG_X86_ALIGNMENT_16=y CONFIG_X86_INTEL_USERCOPY=y CONFIG_X86_TSC=y @@ -478,6 +479,7 @@ CONFIG_X86_SMAP=y CONFIG_EFI=y CONFIG_EFI_STUB=y CONFIG_SECCOMP=y +CONFIG_CC_STACKPROTECTOR=y # CONFIG_HZ_100 is not set # CONFIG_HZ_250 is not set CONFIG_HZ_300=y @@ -616,12 +618,10 @@ CONFIG_PCI=y # CONFIG_PCI_GOBIOS is not set # CONFIG_PCI_GOMMCONFIG is not set # CONFIG_PCI_GODIRECT is not set -# CONFIG_PCI_GOOLPC is not set CONFIG_PCI_GOANY=y CONFIG_PCI_BIOS=y CONFIG_PCI_DIRECT=y CONFIG_PCI_MMCONFIG=y -CONFIG_PCI_OLPC=y CONFIG_PCI_DOMAINS=y # CONFIG_PCI_CNB20LE_QUIRK is not set CONFIG_PCIEPORTBUS=y @@ -648,19 +648,22 @@ CONFIG_PCI_IOV=y CONFIG_PCI_IOAPIC=y CONFIG_PCI_LABEL=y CONFIG_ISA_DMA_API=y -# CONFIG_ISA is not set -# CONFIG_SCx200 is not set -CONFIG_OLPC=y -CONFIG_OLPC_XO1_PM=y -CONFIG_OLPC_XO1_RTC=y -CONFIG_OLPC_XO1_SCI=y -CONFIG_OLPC_XO15_SCI=y -# CONFIG_ALIX is not set -# CONFIG_NET5501 is not set -# CONFIG_GEOS is not set +CONFIG_ISA=y +CONFIG_EISA=y +# CONFIG_EISA_VLB_PRIMING is not set +CONFIG_EISA_PCI_EISA=y +CONFIG_EISA_VIRTUAL_ROOT=y +CONFIG_EISA_NAMES=y +CONFIG_SCx200=m +CONFIG_SCx200HR_TIMER=m +# CONFIG_OLPC is not set +CONFIG_ALIX=y +CONFIG_NET5501=y +CONFIG_GEOS=y CONFIG_AMD_NB=y CONFIG_PCCARD=m -# CONFIG_PCMCIA is not set +CONFIG_PCMCIA=m +CONFIG_PCMCIA_LOAD_CIS=y CONFIG_CARDBUS=y # @@ -672,6 +675,12 @@ CONFIG_YENTA_RICOH=y CONFIG_YENTA_TI=y CONFIG_YENTA_ENE_TUNE=y CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_I82365=m +CONFIG_TCIC=m +CONFIG_PCMCIA_PROBE=y +CONFIG_PCCARD_NONSTATIC=y CONFIG_HOTPLUG_PCI=y # CONFIG_HOTPLUG_PCI_COMPAQ is not set # CONFIG_HOTPLUG_PCI_IBM is not set @@ -1217,6 +1226,10 @@ CONFIG_BT_HCIUART_3WIRE=y CONFIG_BT_HCIBCM203X=m CONFIG_BT_HCIBPA10X=m CONFIG_BT_HCIBFUSB=m +# CONFIG_BT_HCIDTL1 is not set +# CONFIG_BT_HCIBT3C is not set +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m CONFIG_BT_HCIVHCI=m CONFIG_BT_MRVL=m CONFIG_BT_MRVL_SDIO=m @@ -1298,29 +1311,14 @@ CONFIG_DMA_SHARED_BUFFER=y CONFIG_CONNECTOR=y CONFIG_PROC_EVENTS=y # CONFIG_MTD is not set -CONFIG_OF=y - -# -# Device Tree and Open Firmware support -# -CONFIG_PROC_DEVICETREE=y -# CONFIG_OF_SELFTEST is not set -CONFIG_OF_PROMTREE=y -CONFIG_OF_ADDRESS=y -CONFIG_OF_IRQ=y -CONFIG_OF_DEVICE=y -CONFIG_OF_I2C=m -CONFIG_OF_NET=y -CONFIG_OF_MDIO=y -CONFIG_OF_PCI=y -CONFIG_OF_PCI_IRQ=y CONFIG_PARPORT=m CONFIG_PARPORT_PC=m CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_FIFO=y +CONFIG_PARPORT_PC_SUPERIO=y +CONFIG_PARPORT_PC_PCMCIA=m # CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_AX88796=m CONFIG_PARPORT_1284=y CONFIG_PARPORT_NOT_PC=y CONFIG_PNP=y @@ -1329,6 +1327,9 @@ CONFIG_PNP=y # # Protocols # +CONFIG_ISAPNP=y +CONFIG_PNPBIOS=y +# CONFIG_PNPBIOS_PROC_FS is not set CONFIG_PNPACPI=y CONFIG_BLK_DEV=y CONFIG_BLK_DEV_FD=m @@ -1475,7 +1476,11 @@ CONFIG_BLK_DEV_3W_XXXX_RAID=m CONFIG_SCSI_HPSA=m CONFIG_SCSI_3W_9XXX=m CONFIG_SCSI_3W_SAS=m +CONFIG_SCSI_7000FASST=m CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AHA152X=m +CONFIG_SCSI_AHA1542=m +CONFIG_SCSI_AHA1740=m CONFIG_SCSI_AACRAID=m CONFIG_SCSI_AIC7XXX=m CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 @@ -1495,9 +1500,10 @@ CONFIG_SCSI_AIC94XX=m CONFIG_SCSI_MVSAS=m # CONFIG_SCSI_MVSAS_DEBUG is not set CONFIG_SCSI_MVSAS_TASKLET=y -# CONFIG_SCSI_MVUMI is not set +CONFIG_SCSI_MVUMI=m CONFIG_SCSI_DPT_I2O=m CONFIG_SCSI_ADVANSYS=m +CONFIG_SCSI_IN2000=m CONFIG_SCSI_ARCMSR=m CONFIG_MEGARAID_NEWGEN=y CONFIG_MEGARAID_MM=m @@ -1522,6 +1528,7 @@ CONFIG_LIBFCOE=m CONFIG_FCOE=m CONFIG_FCOE_FNIC=m CONFIG_SCSI_DMX3191D=m +CONFIG_SCSI_DTC3280=m CONFIG_SCSI_EATA=m CONFIG_SCSI_EATA_TAGGED_QUEUE=y # CONFIG_SCSI_EATA_LINKED_COMMANDS is not set @@ -1529,6 +1536,9 @@ CONFIG_SCSI_EATA_MAX_TAGS=16 CONFIG_SCSI_FUTURE_DOMAIN=m CONFIG_SCSI_GDTH=m CONFIG_SCSI_ISCI=m +CONFIG_SCSI_GENERIC_NCR5380=m +CONFIG_SCSI_GENERIC_NCR5380_MMIO=m +# CONFIG_SCSI_GENERIC_NCR53C400 is not set CONFIG_SCSI_IPS=m CONFIG_SCSI_INITIO=m CONFIG_SCSI_INIA100=m @@ -1536,6 +1546,7 @@ CONFIG_SCSI_PPA=m CONFIG_SCSI_IMM=m # CONFIG_SCSI_IZIP_EPP16 is not set # CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_NCR53C406A=m CONFIG_SCSI_STEX=m CONFIG_SCSI_SYM53C8XX_2=m CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 @@ -1545,14 +1556,24 @@ CONFIG_SCSI_SYM53C8XX_MMIO=y CONFIG_SCSI_IPR=m CONFIG_SCSI_IPR_TRACE=y CONFIG_SCSI_IPR_DUMP=y +CONFIG_SCSI_PAS16=m +CONFIG_SCSI_QLOGIC_FAS=m CONFIG_SCSI_QLOGIC_1280=m CONFIG_SCSI_QLA_FC=m CONFIG_SCSI_QLA_ISCSI=m CONFIG_SCSI_LPFC=m # CONFIG_SCSI_LPFC_DEBUG_FS is not set +CONFIG_SCSI_SIM710=m +CONFIG_SCSI_SYM53C416=m CONFIG_SCSI_DC395x=m CONFIG_SCSI_DC390T=m -# CONFIG_SCSI_NSP32 is not set +CONFIG_SCSI_T128=m +CONFIG_SCSI_U14_34F=m +# CONFIG_SCSI_U14_34F_TAGGED_QUEUE is not set +# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set +CONFIG_SCSI_U14_34F_MAX_TAGS=8 +CONFIG_SCSI_ULTRASTOR=m +CONFIG_SCSI_NSP32=m # CONFIG_SCSI_DEBUG is not set CONFIG_SCSI_PMCRAID=m CONFIG_SCSI_PM8001=m @@ -1560,6 +1581,12 @@ CONFIG_SCSI_PM8001=m CONFIG_SCSI_BFA_FC=m CONFIG_SCSI_VIRTIO=m CONFIG_SCSI_CHELSIO_FCOE=m +CONFIG_SCSI_LOWLEVEL_PCMCIA=y +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m CONFIG_SCSI_DH=y CONFIG_SCSI_DH_RDAC=m CONFIG_SCSI_DH_HP_SW=m @@ -1573,7 +1600,7 @@ CONFIG_ATA=y # CONFIG_ATA_NONSTANDARD is not set CONFIG_ATA_VERBOSE_ERROR=y CONFIG_ATA_ACPI=y -# CONFIG_SATA_ZPODD is not set +CONFIG_SATA_ZPODD=y CONFIG_SATA_PMP=y # @@ -1641,9 +1668,9 @@ CONFIG_PATA_OLDPIIX=m CONFIG_PATA_OPTIDMA=m CONFIG_PATA_PDC2027X=m CONFIG_PATA_PDC_OLD=m -# CONFIG_PATA_RADISYS is not set +CONFIG_PATA_RADISYS=m CONFIG_PATA_RDC=m -# CONFIG_PATA_SC1200 is not set +CONFIG_PATA_SC1200=m CONFIG_PATA_SCH=m CONFIG_PATA_SERVERWORKS=m CONFIG_PATA_SIL680=m @@ -1657,18 +1684,22 @@ CONFIG_PATA_WINBOND=m # PIO-only SFF controllers # CONFIG_PATA_CMD640_PCI=m +CONFIG_PATA_ISAPNP=m CONFIG_PATA_MPIIX=m CONFIG_PATA_NS87410=m CONFIG_PATA_OPTI=m -# CONFIG_PATA_PLATFORM is not set +CONFIG_PATA_PCMCIA=m +CONFIG_PATA_PLATFORM=m +CONFIG_PATA_QDI=m CONFIG_PATA_RZ1000=m +CONFIG_PATA_WINBOND_VLB=m # # Generic fallback / legacy drivers # CONFIG_PATA_ACPI=m CONFIG_ATA_GENERIC=m -# CONFIG_PATA_LEGACY is not set +CONFIG_PATA_LEGACY=m CONFIG_MD=y CONFIG_BLK_DEV_MD=y CONFIG_MD_AUTODETECT=y @@ -1769,7 +1800,8 @@ CONFIG_ATM_ENI=m # CONFIG_ATM_ENI_DEBUG is not set # CONFIG_ATM_ENI_TUNE_BURST is not set CONFIG_ATM_FIRESTREAM=m -# CONFIG_ATM_ZATM is not set +CONFIG_ATM_ZATM=m +# CONFIG_ATM_ZATM_DEBUG is not set CONFIG_ATM_NICSTAR=m # CONFIG_ATM_NICSTAR_USE_SUNI is not set # CONFIG_ATM_NICSTAR_USE_IDT77105 is not set @@ -1777,10 +1809,16 @@ CONFIG_ATM_IDT77252=m # CONFIG_ATM_IDT77252_DEBUG is not set # CONFIG_ATM_IDT77252_RCV_ALL is not set CONFIG_ATM_IDT77252_USE_SUNI=y -# CONFIG_ATM_AMBASSADOR is not set -# CONFIG_ATM_HORIZON is not set -# CONFIG_ATM_IA is not set -# CONFIG_ATM_FORE200E is not set +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_IA=m +# CONFIG_ATM_IA_DEBUG is not set +CONFIG_ATM_FORE200E=m +# CONFIG_ATM_FORE200E_USE_TASKLET is not set +CONFIG_ATM_FORE200E_TX_RETRY=16 +CONFIG_ATM_FORE200E_DEBUG=0 CONFIG_ATM_HE=m # CONFIG_ATM_HE_USE_SUNI is not set CONFIG_ATM_SOLOS=m @@ -1802,6 +1840,10 @@ CONFIG_NET_DSA_MV88E6123_61_65=y CONFIG_ETHERNET=y CONFIG_MDIO=m CONFIG_NET_VENDOR_3COM=y +CONFIG_EL3=m +CONFIG_3C515=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_3C589=m CONFIG_VORTEX=m CONFIG_TYPHOON=m CONFIG_NET_VENDOR_ADAPTEC=y @@ -1811,7 +1853,10 @@ CONFIG_ACENIC=m # CONFIG_ACENIC_OMIT_TIGON_I is not set CONFIG_NET_VENDOR_AMD=y CONFIG_AMD8111_ETH=m +CONFIG_LANCE=m CONFIG_PCNET32=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_NI65=m CONFIG_NET_VENDOR_ATHEROS=y CONFIG_ATL2=m CONFIG_ATL1=m @@ -1840,6 +1885,9 @@ CONFIG_CHELSIO_T1_1G=y CONFIG_CHELSIO_T3=m CONFIG_CHELSIO_T4=m CONFIG_CHELSIO_T4VF=m +CONFIG_NET_VENDOR_CIRRUS=y +CONFIG_CS89x0=m +# CONFIG_CS89x0_PLATFORM is not set CONFIG_NET_VENDOR_CISCO=y CONFIG_ENIC=m CONFIG_DNET=m @@ -1867,6 +1915,8 @@ CONFIG_NET_VENDOR_EXAR=y CONFIG_S2IO=m CONFIG_VXGE=m # CONFIG_VXGE_DEBUG_TRACE_ALL is not set +CONFIG_NET_VENDOR_FUJITSU=y +CONFIG_PCMCIA_FMVJ18X=m CONFIG_NET_VENDOR_HP=y CONFIG_HP100=m CONFIG_NET_VENDOR_INTEL=y @@ -1897,8 +1947,8 @@ CONFIG_MLX4_EN=m CONFIG_MLX4_CORE=m CONFIG_MLX4_DEBUG=y CONFIG_NET_VENDOR_MICREL=y -# CONFIG_KS8842 is not set -# CONFIG_KS8851_MLL is not set +CONFIG_KS8842=m +CONFIG_KS8851_MLL=m CONFIG_KSZ884X_PCI=m CONFIG_NET_VENDOR_MYRI=y CONFIG_MYRI10GE=m @@ -1908,7 +1958,12 @@ CONFIG_NET_VENDOR_NATSEMI=y CONFIG_NATSEMI=m CONFIG_NS83820=m CONFIG_NET_VENDOR_8390=y +CONFIG_PCMCIA_AXNET=m +CONFIG_NE2000=m CONFIG_NE2K_PCI=m +CONFIG_PCMCIA_PCNET=m +CONFIG_ULTRA=m +CONFIG_WD80x3=m CONFIG_NET_VENDOR_NVIDIA=y CONFIG_FORCEDETH=m CONFIG_NET_VENDOR_OKI=y @@ -1942,6 +1997,8 @@ CONFIG_SFC=m CONFIG_SFC_MCDI_MON=y CONFIG_SFC_SRIOV=y CONFIG_NET_VENDOR_SMSC=y +CONFIG_SMC9194=m +CONFIG_PCMCIA_SMC91C92=m CONFIG_EPIC100=m CONFIG_SMSC9420=m CONFIG_NET_VENDOR_STMICRO=y @@ -1969,6 +2026,8 @@ CONFIG_WIZNET_W5300=m # CONFIG_WIZNET_BUS_DIRECT is not set # CONFIG_WIZNET_BUS_INDIRECT is not set CONFIG_WIZNET_BUS_ANY=y +CONFIG_NET_VENDOR_XIRCOM=y +CONFIG_PCMCIA_XIRC2PS=m # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_NET_SB1000 is not set @@ -1997,9 +2056,6 @@ CONFIG_MICREL_PHY=m CONFIG_FIXED_PHY=y CONFIG_MDIO_BITBANG=m # CONFIG_MDIO_GPIO is not set -CONFIG_MDIO_BUS_MUX=m -CONFIG_MDIO_BUS_MUX_GPIO=m -CONFIG_MDIO_BUS_MUX_MMIOREG=m # CONFIG_PLIP is not set CONFIG_PPP=m CONFIG_PPP_BSDCOMP=m @@ -2056,13 +2112,17 @@ CONFIG_USB_IPHETH=m CONFIG_USB_SIERRA_NET=m CONFIG_USB_VL600=m CONFIG_WLAN=y +# CONFIG_PCMCIA_RAYCS is not set CONFIG_LIBERTAS_THINFIRM=m # CONFIG_LIBERTAS_THINFIRM_DEBUG is not set CONFIG_LIBERTAS_THINFIRM_USB=m CONFIG_AIRO=m CONFIG_ATMEL=m CONFIG_PCI_ATMEL=m +CONFIG_PCMCIA_ATMEL=m CONFIG_AT76C50X_USB=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_WL3501=m # CONFIG_PRISM54 is not set CONFIG_USB_ZD1201=m CONFIG_USB_NET_RNDIS_WLAN=m @@ -2101,6 +2161,7 @@ CONFIG_B43=m CONFIG_B43_SSB=y CONFIG_B43_PCI_AUTOSELECT=y CONFIG_B43_PCICORE_AUTOSELECT=y +# CONFIG_B43_PCMCIA is not set CONFIG_B43_SDIO=y CONFIG_B43_PIO=y CONFIG_B43_PHY_N=y @@ -2119,12 +2180,18 @@ CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y # CONFIG_B43LEGACY_DMA_MODE is not set # CONFIG_B43LEGACY_PIO_MODE is not set -# CONFIG_BRCMFMAC is not set +CONFIG_BRCMUTIL=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_SDIO=y +# CONFIG_BRCMFMAC_USB is not set +# CONFIG_BRCM_TRACING is not set +# CONFIG_BRCMDBG is not set CONFIG_HOSTAP=m CONFIG_HOSTAP_FIRMWARE=y CONFIG_HOSTAP_FIRMWARE_NVRAM=y CONFIG_HOSTAP_PLX=m CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m CONFIG_IPW2100=m CONFIG_IPW2100_MONITOR=y # CONFIG_IPW2100_DEBUG is not set @@ -2136,7 +2203,17 @@ CONFIG_IPW2200_QOS=y # CONFIG_IPW2200_DEBUG is not set CONFIG_LIBIPW=m # CONFIG_LIBIPW_DEBUG is not set -# CONFIG_IWLWIFI is not set +CONFIG_IWLWIFI=m +CONFIG_IWLDVM=m +CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y + +# +# Debugging Options +# +# CONFIG_IWLWIFI_DEBUG is not set +# CONFIG_IWLWIFI_DEVICE_TRACING is not set +CONFIG_IWLWIFI_P2P=y CONFIG_IWLEGACY=m CONFIG_IWL4965=m CONFIG_IWL3945=m @@ -2147,6 +2224,7 @@ CONFIG_IWL3945=m # CONFIG_IWLEGACY_DEBUG is not set CONFIG_LIBERTAS=m CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_CS=m CONFIG_LIBERTAS_SDIO=m # CONFIG_LIBERTAS_DEBUG is not set CONFIG_LIBERTAS_MESH=y @@ -2156,6 +2234,8 @@ CONFIG_HERMES_CACHE_FW_ON_INIT=y CONFIG_PLX_HERMES=m CONFIG_TMD_HERMES=m CONFIG_NORTEL_HERMES=m +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m CONFIG_ORINOCO_USB=m CONFIG_P54_COMMON=m CONFIG_P54_USB=m @@ -2208,7 +2288,7 @@ CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m -# CONFIG_MWIFIEX_PCIE is not set +CONFIG_MWIFIEX_PCIE=m CONFIG_MWIFIEX_USB=m # @@ -2255,17 +2335,27 @@ CONFIG_HISAX_MAX_CARDS=8 # # HiSax supported cards # +# CONFIG_HISAX_16_0 is not set CONFIG_HISAX_16_3=y CONFIG_HISAX_TELESPCI=y CONFIG_HISAX_S0BOX=y +# CONFIG_HISAX_AVM_A1 is not set CONFIG_HISAX_FRITZPCI=y CONFIG_HISAX_AVM_A1_PCMCIA=y CONFIG_HISAX_ELSA=y +# CONFIG_HISAX_IX1MICROR2 is not set CONFIG_HISAX_DIEHLDIVA=y +# CONFIG_HISAX_ASUSCOM is not set +# CONFIG_HISAX_TELEINT is not set +# CONFIG_HISAX_HFCS is not set CONFIG_HISAX_SEDLBAUER=y +# CONFIG_HISAX_SPORTSTER is not set +# CONFIG_HISAX_MIC is not set CONFIG_HISAX_NETJET=y CONFIG_HISAX_NETJET_U=y CONFIG_HISAX_NICCY=y +# CONFIG_HISAX_ISURF is not set +# CONFIG_HISAX_HSTSAPHIR is not set CONFIG_HISAX_BKM_A4T=y CONFIG_HISAX_SCT_QUADRO=y CONFIG_HISAX_GAZEL=y @@ -2278,6 +2368,10 @@ CONFIG_HISAX_ENTERNOW_PCI=y # # HiSax PCMCIA card service modules # +# CONFIG_HISAX_SEDLBAUER_CS is not set +# CONFIG_HISAX_ELSA_CS is not set +# CONFIG_HISAX_AVM_A1_CS is not set +# CONFIG_HISAX_TELES_CS is not set # # HiSax sub driver modules @@ -2290,6 +2384,10 @@ CONFIG_HISAX_FRITZ_PCIPNP=m # # Active cards # +# CONFIG_ISDN_DRV_ICN is not set +# CONFIG_ISDN_DRV_PCBIT is not set +# CONFIG_ISDN_DRV_SC is not set +# CONFIG_ISDN_DRV_ACT2000 is not set CONFIG_ISDN_CAPI=m CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y CONFIG_CAPI_TRACE=y @@ -2301,8 +2399,11 @@ CONFIG_ISDN_CAPI_CAPIDRV=m # CAPI hardware drivers # CONFIG_CAPI_AVM=y +# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set CONFIG_ISDN_DRV_AVMB1_B1PCI=m CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set +# CONFIG_ISDN_DRV_AVMB1_B1PCMCIA is not set CONFIG_ISDN_DRV_AVMB1_T1PCI=m CONFIG_ISDN_DRV_AVMB1_C4=m CONFIG_CAPI_EICON=y @@ -2375,11 +2476,13 @@ CONFIG_MOUSE_PS2_TRACKPOINT=y CONFIG_MOUSE_PS2_ELANTECH=y CONFIG_MOUSE_PS2_SENTELIC=y CONFIG_MOUSE_PS2_TOUCHKIT=y -CONFIG_MOUSE_PS2_OLPC=y CONFIG_MOUSE_SERIAL=m CONFIG_MOUSE_APPLETOUCH=m CONFIG_MOUSE_BCM5974=m CONFIG_MOUSE_CYAPA=m +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set CONFIG_MOUSE_VSXXXAA=m # CONFIG_MOUSE_GPIO is not set CONFIG_MOUSE_SYNAPTICS_I2C=m @@ -2407,7 +2510,6 @@ CONFIG_INPUT_CM109=m CONFIG_INPUT_RETU_PWRBUTTON=m CONFIG_INPUT_UINPUT=m # CONFIG_INPUT_PCF8574 is not set -CONFIG_INPUT_PWM_BEEPER=m CONFIG_INPUT_GPIO_ROTARY_ENCODER=m # CONFIG_INPUT_ADXL34X is not set # CONFIG_INPUT_IMS_PCU is not set @@ -2427,7 +2529,6 @@ CONFIG_SERIO_RAW=m CONFIG_SERIO_ALTERA_PS2=m # CONFIG_SERIO_PS2MULT is not set CONFIG_SERIO_ARC_PS2=m -CONFIG_SERIO_APBPS2=m # CONFIG_GAMEPORT is not set # @@ -2469,14 +2570,20 @@ CONFIG_SERIAL_8250_CONSOLE=y CONFIG_FIX_EARLYCON_MEM=y CONFIG_SERIAL_8250_DMA=y CONFIG_SERIAL_8250_PCI=y +# CONFIG_SERIAL_8250_CS is not set CONFIG_SERIAL_8250_NR_UARTS=4 CONFIG_SERIAL_8250_RUNTIME_UARTS=4 CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y +# CONFIG_SERIAL_8250_FOURPORT is not set +# CONFIG_SERIAL_8250_ACCENT is not set +# CONFIG_SERIAL_8250_BOCA is not set +# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set +# CONFIG_SERIAL_8250_HUB6 is not set CONFIG_SERIAL_8250_SHARE_IRQ=y # CONFIG_SERIAL_8250_DETECT_IRQ is not set CONFIG_SERIAL_8250_RSA=y -# CONFIG_SERIAL_8250_DW is not set +CONFIG_SERIAL_8250_DW=m # # Non-8250 serial port support @@ -2485,13 +2592,11 @@ CONFIG_SERIAL_8250_RSA=y CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_SERIAL_JSM=m -CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SERIAL_SCCNXP=m # CONFIG_SERIAL_TIMBERDALE is not set # CONFIG_SERIAL_ALTERA_JTAGUART is not set # CONFIG_SERIAL_ALTERA_UART is not set # CONFIG_SERIAL_PCH_UART is not set -# CONFIG_SERIAL_XILINX_PS_UART is not set CONFIG_SERIAL_ARC=m CONFIG_SERIAL_ARC_NR_PORTS=1 CONFIG_SERIAL_RP2=m @@ -2518,10 +2623,20 @@ CONFIG_HW_RANDOM_VIA=m CONFIG_HW_RANDOM_VIRTIO=m CONFIG_HW_RANDOM_EXYNOS=m CONFIG_NVRAM=y +# CONFIG_DTLK is not set CONFIG_R3964=m # CONFIG_APPLICOM is not set CONFIG_SONYPI=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_IPWIRELESS is not set CONFIG_MWAVE=m +# CONFIG_SCx200_GPIO is not set CONFIG_PC8736x_GPIO=m CONFIG_NSC_GPIO=m CONFIG_RAW_DRIVER=y @@ -2583,8 +2698,7 @@ CONFIG_I2C_DESIGNWARE_PLATFORM=m # CONFIG_I2C_INTEL_MID is not set # CONFIG_I2C_OCORES is not set CONFIG_I2C_PCA_PLATFORM=m -CONFIG_I2C_PXA=m -CONFIG_I2C_PXA_PCI=y +# CONFIG_I2C_PXA_PCI is not set CONFIG_I2C_SIMTEC=m # CONFIG_I2C_XILINX is not set @@ -2601,6 +2715,7 @@ CONFIG_I2C_VIPERBOARD=m # # Other I2C/SMBus bus drivers # +# CONFIG_I2C_PCA_ISA is not set CONFIG_SCx200_ACB=m CONFIG_I2C_STUB=m # CONFIG_I2C_DEBUG_CORE is not set @@ -2650,7 +2765,6 @@ CONFIG_PTP_1588_CLOCK_PCH=m CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y CONFIG_GPIO_DEVRES=y CONFIG_GPIOLIB=y -CONFIG_OF_GPIO=y CONFIG_GPIO_ACPI=y # CONFIG_DEBUG_GPIO is not set CONFIG_GPIO_SYSFS=y @@ -2665,7 +2779,6 @@ CONFIG_GPIO_SCH=m CONFIG_GPIO_ICH=m # CONFIG_GPIO_VX855 is not set # CONFIG_GPIO_LYNXPOINT is not set -# CONFIG_GPIO_GRGPIO is not set # # I2C GPIO expanders: @@ -2675,17 +2788,15 @@ CONFIG_GPIO_ICH=m # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set # CONFIG_GPIO_ADP5588 is not set -CONFIG_GPIO_ADNP=m # # PCI GPIO expanders: # -CONFIG_GPIO_CS5535=y +# CONFIG_GPIO_CS5535 is not set # CONFIG_GPIO_AMD8111 is not set # CONFIG_GPIO_LANGWELL is not set # CONFIG_GPIO_PCH is not set # CONFIG_GPIO_ML_IOH is not set -# CONFIG_GPIO_SODAVILLE is not set # CONFIG_GPIO_RDC321X is not set # @@ -2743,7 +2854,6 @@ CONFIG_GENERIC_ADC_BATTERY=m # CONFIG_BATTERY_DS2780 is not set # CONFIG_BATTERY_DS2781 is not set # CONFIG_BATTERY_DS2782 is not set -CONFIG_BATTERY_OLPC=y # CONFIG_BATTERY_SBS is not set # CONFIG_BATTERY_BQ27x00 is not set # CONFIG_BATTERY_MAX17040 is not set @@ -2755,7 +2865,6 @@ CONFIG_BATTERY_OLPC=y # CONFIG_CHARGER_SMB347 is not set # CONFIG_BATTERY_GOLDFISH is not set CONFIG_POWER_RESET=y -CONFIG_POWER_RESET_GPIO=y CONFIG_POWER_AVS=y CONFIG_HWMON=y CONFIG_HWMON_VID=m @@ -2935,6 +3044,7 @@ CONFIG_IT87_WDT=m CONFIG_HP_WATCHDOG=m CONFIG_HPWDT_NMI_DECODING=y # CONFIG_SC1200_WDT is not set +# CONFIG_SCx200_WDT is not set # CONFIG_PC87413_WDT is not set CONFIG_NV_TCO=m # CONFIG_60XX_WDT is not set @@ -2952,6 +3062,13 @@ CONFIG_W83977F_WDT=m CONFIG_MACHZ_WDT=m # CONFIG_SBC_EPX_C3_WATCHDOG is not set +# +# ISA-based Watchdog Cards +# +# CONFIG_PCWATCHDOG is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_WDT is not set + # # PCI-based Watchdog Cards # @@ -2973,10 +3090,11 @@ CONFIG_SSB_BLOCKIO=y CONFIG_SSB_PCIHOST_POSSIBLE=y CONFIG_SSB_PCIHOST=y CONFIG_SSB_B43_PCI_BRIDGE=y +CONFIG_SSB_PCMCIAHOST_POSSIBLE=y +CONFIG_SSB_PCMCIAHOST=y CONFIG_SSB_SDIOHOST_POSSIBLE=y CONFIG_SSB_SDIOHOST=y -# CONFIG_SSB_SILENT is not set -# CONFIG_SSB_DEBUG is not set +CONFIG_SSB_SILENT=y CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y CONFIG_SSB_DRIVER_PCICORE=y CONFIG_SSB_DRIVER_GPIO=y @@ -2990,7 +3108,7 @@ CONFIG_BCMA_POSSIBLE=y # # Multifunction device drivers # -CONFIG_MFD_CORE=y +CONFIG_MFD_CORE=m CONFIG_MFD_CS5535=m # CONFIG_MFD_CROS_EC is not set # CONFIG_MFD_MC13XXX_I2C is not set @@ -3060,7 +3178,7 @@ CONFIG_DVB_DYNAMIC_MINORS=y # Media drivers # CONFIG_RC_CORE=y -# CONFIG_RC_MAP is not set +CONFIG_RC_MAP=m CONFIG_RC_DECODERS=y CONFIG_LIRC=m CONFIG_IR_LIRC_CODEC=m @@ -3073,7 +3191,7 @@ CONFIG_IR_RC5_SZ_DECODER=m CONFIG_IR_SANYO_DECODER=m CONFIG_IR_MCE_KBD_DECODER=m CONFIG_RC_DEVICES=y -# CONFIG_RC_ATI_REMOTE is not set +CONFIG_RC_ATI_REMOTE=m CONFIG_IR_ENE=m CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m @@ -3135,7 +3253,7 @@ CONFIG_USB_GSPCA_STK014=m CONFIG_USB_GSPCA_STV0680=m CONFIG_USB_GSPCA_SUNPLUS=m CONFIG_USB_GSPCA_T613=m -# CONFIG_USB_GSPCA_TOPRO is not set +CONFIG_USB_GSPCA_TOPRO=m CONFIG_USB_GSPCA_TV8532=m CONFIG_USB_GSPCA_VC032X=m CONFIG_USB_GSPCA_VICAM=m @@ -3148,16 +3266,20 @@ CONFIG_VIDEO_CPIA2=m CONFIG_USB_ZR364XX=m CONFIG_USB_STKWEBCAM=m CONFIG_USB_S2255=m -# CONFIG_USB_SN9C102 is not set +CONFIG_USB_SN9C102=m # # Analog TV USB devices # -# CONFIG_VIDEO_PVRUSB2 is not set -# CONFIG_VIDEO_HDPVR is not set -# CONFIG_VIDEO_TLG2300 is not set -# CONFIG_VIDEO_USBVISION is not set -# CONFIG_VIDEO_STK1160 is not set +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_TLG2300=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_STK1160=m +CONFIG_VIDEO_STK1160_AC97=y # # Analog/digital TV USB devices @@ -3195,7 +3317,7 @@ CONFIG_DVB_USB_DTT200U=m CONFIG_DVB_USB_OPERA1=m CONFIG_DVB_USB_AF9005=m CONFIG_DVB_USB_AF9005_REMOTE=m -# CONFIG_DVB_USB_PCTV452E is not set +CONFIG_DVB_USB_PCTV452E=m CONFIG_DVB_USB_DW2102=m CONFIG_DVB_USB_CINERGY_T2=m CONFIG_DVB_USB_DTV5100=m @@ -3211,10 +3333,11 @@ CONFIG_DVB_USB_AZ6007=m CONFIG_DVB_USB_CE6230=m CONFIG_DVB_USB_EC168=m CONFIG_DVB_USB_GL861=m -# CONFIG_DVB_USB_IT913X is not set +CONFIG_DVB_USB_IT913X=m CONFIG_DVB_USB_LME2510=m -# CONFIG_DVB_USB_MXL111SF is not set +CONFIG_DVB_USB_MXL111SF=m CONFIG_DVB_USB_RTL28XXU=m +CONFIG_DVB_USB_DVBSKY=m CONFIG_DVB_TTUSB_BUDGET=m CONFIG_DVB_TTUSB_DEC=m CONFIG_SMS_USB_DRV=m @@ -3238,11 +3361,20 @@ CONFIG_VIDEO_MEYE=m # # Media capture/analog TV support # -# CONFIG_VIDEO_IVTV is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_HEXIUM_GEMINI is not set -# CONFIG_VIDEO_HEXIUM_ORION is not set -# CONFIG_VIDEO_MXB is not set +CONFIG_VIDEO_IVTV=m +CONFIG_VIDEO_IVTV_ALSA=m +CONFIG_VIDEO_FB_IVTV=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_ZR36060=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_MXB=m # # Media capture/analog/hybrid TV support @@ -3286,7 +3418,7 @@ CONFIG_MANTIS_CORE=m CONFIG_DVB_MANTIS=m CONFIG_DVB_HOPPER=m CONFIG_DVB_NGENE=m -# CONFIG_DVB_DDBRIDGE is not set +CONFIG_DVB_DDBRIDGE=m CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_VIDEO_CAFE_CCIC=m CONFIG_VIDEO_TIMBERDALE=m @@ -3338,9 +3470,15 @@ CONFIG_VIDEO_IR_I2C=m # CONFIG_VIDEO_TVAUDIO=m CONFIG_VIDEO_TDA7432=m +CONFIG_VIDEO_TDA9840=m +CONFIG_VIDEO_TEA6415C=m +CONFIG_VIDEO_TEA6420=m CONFIG_VIDEO_MSP3400=m CONFIG_VIDEO_CS5345=m +CONFIG_VIDEO_CS53L32A=m CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_VP27SMPX=m # # RDS decoders @@ -3351,17 +3489,28 @@ CONFIG_VIDEO_SAA6588=m # Video decoders # CONFIG_VIDEO_ADV7180=m +CONFIG_VIDEO_BT819=m +CONFIG_VIDEO_BT856=m +CONFIG_VIDEO_BT866=m +CONFIG_VIDEO_KS0127=m +CONFIG_VIDEO_SAA7110=m CONFIG_VIDEO_SAA711X=m CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_VPX3220=m # # Video and audio decoders # +CONFIG_VIDEO_SAA717X=m CONFIG_VIDEO_CX25840=m # # Video encoders # +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_SAA7185=m +CONFIG_VIDEO_ADV7170=m +CONFIG_VIDEO_ADV7175=m # # Camera sensor devices @@ -3376,10 +3525,13 @@ CONFIG_VIDEO_MT9V011=m # # Video improvement chips # +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m # # Miscelaneous helper chips # +CONFIG_VIDEO_M52790=m # # Sensors used on soc_camera driver @@ -3469,6 +3621,8 @@ CONFIG_DVB_TUNER_CX24113=m CONFIG_DVB_TDA826X=m CONFIG_DVB_TUA6100=m CONFIG_DVB_CX24116=m +CONFIG_DVB_M88DS3103=m +CONFIG_DVB_M88DC2800=m CONFIG_DVB_SI21XX=m CONFIG_DVB_TS2020=m CONFIG_DVB_DS3000=m @@ -3517,6 +3671,7 @@ CONFIG_DVB_OR51132=m CONFIG_DVB_BCM3510=m CONFIG_DVB_LGDT330X=m CONFIG_DVB_LGDT3305=m +CONFIG_DVB_LG2160=m CONFIG_DVB_S5H1409=m CONFIG_DVB_AU8522=m CONFIG_DVB_AU8522_DTV=m @@ -3541,6 +3696,7 @@ CONFIG_DVB_TUNER_DIB0090=m # SEC control devices for DVB-S # CONFIG_DVB_LNBP21=m +CONFIG_DVB_LNBP22=m CONFIG_DVB_ISL6405=m CONFIG_DVB_ISL6421=m CONFIG_DVB_ISL6423=m @@ -3549,6 +3705,7 @@ CONFIG_DVB_LGS8GXX=m CONFIG_DVB_ATBM8830=m CONFIG_DVB_TDA665x=m CONFIG_DVB_IX2505V=m +CONFIG_DVB_IT913X_FE=m CONFIG_DVB_M88RS2000=m CONFIG_DVB_AF9033=m @@ -3687,7 +3844,6 @@ CONFIG_LCD_PLATFORM=m CONFIG_BACKLIGHT_CLASS_DEVICE=y # CONFIG_BACKLIGHT_GENERIC is not set # CONFIG_BACKLIGHT_LM3533 is not set -CONFIG_BACKLIGHT_PWM=m CONFIG_BACKLIGHT_APPLE=m # CONFIG_BACKLIGHT_SAHARA is not set # CONFIG_BACKLIGHT_ADP8860 is not set @@ -3695,13 +3851,13 @@ CONFIG_BACKLIGHT_APPLE=m # CONFIG_BACKLIGHT_LM3630 is not set # CONFIG_BACKLIGHT_LM3639 is not set # CONFIG_BACKLIGHT_LP855X is not set -# CONFIG_BACKLIGHT_OT200 is not set # # Console display driver support # CONFIG_VGA_CONSOLE=y # CONFIG_VGACON_SOFT_SCROLLBACK is not set +# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=m CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y @@ -3713,7 +3869,6 @@ CONFIG_LOGO=y # CONFIG_LOGO_LINUX_MONO is not set # CONFIG_LOGO_LINUX_VGA16 is not set CONFIG_LOGO_LINUX_CLUT224=y -# CONFIG_FB_SSD1307 is not set CONFIG_SOUND=m CONFIG_SOUND_OSS_CORE=y CONFIG_SOUND_OSS_CORE_PRECLAIM=y @@ -3744,11 +3899,12 @@ CONFIG_SND_KCTL_JACK=y CONFIG_SND_DMA_SGBUF=y CONFIG_SND_RAWMIDI_SEQ=m CONFIG_SND_OPL3_LIB_SEQ=m -# CONFIG_SND_OPL4_LIB_SEQ is not set -# CONFIG_SND_SBAWE_SEQ is not set +CONFIG_SND_OPL4_LIB_SEQ=m +CONFIG_SND_SBAWE_SEQ=m CONFIG_SND_EMU10K1_SEQ=m CONFIG_SND_MPU401_UART=m CONFIG_SND_OPL3_LIB=m +CONFIG_SND_OPL4_LIB=m CONFIG_SND_VX_LIB=m CONFIG_SND_AC97_CODEC=m CONFIG_SND_DRIVERS=y @@ -3763,8 +3919,44 @@ CONFIG_SND_MPU401=m CONFIG_SND_PORTMAN2X4=m CONFIG_SND_AC97_POWER_SAVE=y CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 +CONFIG_SND_WSS_LIB=m CONFIG_SND_SB_COMMON=m +CONFIG_SND_SB8_DSP=m CONFIG_SND_SB16_DSP=m +CONFIG_SND_ISA=y +CONFIG_SND_ADLIB=m +CONFIG_SND_AD1816A=m +CONFIG_SND_AD1848=m +CONFIG_SND_ALS100=m +CONFIG_SND_AZT1605=m +CONFIG_SND_AZT2316=m +CONFIG_SND_AZT2320=m +CONFIG_SND_CMI8328=m +CONFIG_SND_CMI8330=m +CONFIG_SND_CS4231=m +CONFIG_SND_CS4236=m +CONFIG_SND_ES1688=m +CONFIG_SND_ES18XX=m +CONFIG_SND_SC6000=m +CONFIG_SND_GUSCLASSIC=m +CONFIG_SND_GUSEXTREME=m +CONFIG_SND_GUSMAX=m +CONFIG_SND_INTERWAVE=m +CONFIG_SND_INTERWAVE_STB=m +CONFIG_SND_JAZZ16=m +CONFIG_SND_OPL3SA2=m +CONFIG_SND_OPTI92X_AD1848=m +CONFIG_SND_OPTI92X_CS4231=m +CONFIG_SND_OPTI93X=m +CONFIG_SND_MIRO=m +CONFIG_SND_SB8=m +CONFIG_SND_SB16=m +CONFIG_SND_SBAWE=m +CONFIG_SND_SB16_CSP=y +CONFIG_SND_SSCAPE=m +CONFIG_SND_WAVEFRONT=m +CONFIG_SND_MSND_PINNACLE=m +CONFIG_SND_MSND_CLASSIC=m CONFIG_SND_TEA575X=m CONFIG_SND_PCI=y CONFIG_SND_AD1889=m @@ -3876,6 +4068,9 @@ CONFIG_SND_FIREWIRE_LIB=m CONFIG_SND_FIREWIRE_SPEAKERS=m # CONFIG_SND_ISIGHT is not set # CONFIG_SND_SCS1X is not set +CONFIG_SND_PCMCIA=y +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set # CONFIG_SND_SOC is not set # CONFIG_SOUND_PRIME is not set CONFIG_AC97_BUS=m @@ -4017,6 +4212,7 @@ CONFIG_USB_UHCI_HCD=y # CONFIG_USB_U132_HCD is not set CONFIG_USB_SL811_HCD=m CONFIG_USB_SL811_HCD_ISO=y +# CONFIG_USB_SL811_CS is not set # CONFIG_USB_R8A66597_HCD is not set CONFIG_USB_WHCI_HCD=m CONFIG_USB_HWA_HCD=m @@ -4192,6 +4388,7 @@ CONFIG_MMC_SDHCI_PXAV3=m CONFIG_MMC_SDHCI_PXAV2=m CONFIG_MMC_WBSD=m CONFIG_MMC_TIFM_SD=m +# CONFIG_MMC_SDRICOH_CS is not set CONFIG_MMC_CB710=m CONFIG_MMC_VIA_SDMMC=m CONFIG_MMC_VUB300=m @@ -4232,7 +4429,6 @@ CONFIG_LEDS_LP5562=m CONFIG_LEDS_CLEVO_MAIL=m # CONFIG_LEDS_PCA955X is not set CONFIG_LEDS_PCA9633=m -CONFIG_LEDS_PWM=m # CONFIG_LEDS_BD2802 is not set CONFIG_LEDS_INTEL_SS4200=m CONFIG_LEDS_LT3593=m @@ -4251,7 +4447,7 @@ CONFIG_LEDS_TRIGGER_TIMER=m CONFIG_LEDS_TRIGGER_ONESHOT=m CONFIG_LEDS_TRIGGER_HEARTBEAT=m CONFIG_LEDS_TRIGGER_BACKLIGHT=m -# CONFIG_LEDS_TRIGGER_CPU is not set +CONFIG_LEDS_TRIGGER_CPU=y CONFIG_LEDS_TRIGGER_GPIO=m CONFIG_LEDS_TRIGGER_DEFAULT_ON=m @@ -4260,6 +4456,7 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=m # CONFIG_LEDS_TRIGGER_TRANSIENT=m CONFIG_LEDS_TRIGGER_CAMERA=m +CONFIG_LEDS_TRIGGER_NETDEV=m # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set CONFIG_EDAC=y @@ -4349,7 +4546,6 @@ CONFIG_RTC_DRV_DS2404=m # # on-CPU RTC drivers # -CONFIG_RTC_DRV_SNVS=m # # HID Sensor RTC drivers @@ -4369,7 +4565,6 @@ CONFIG_TIMB_DMA=m CONFIG_PCH_DMA=m CONFIG_DMA_ENGINE=y CONFIG_DMA_ACPI=y -CONFIG_DMA_OF=y # # DMA Clients @@ -4411,7 +4606,6 @@ CONFIG_ET131X=m # CONFIG_PRISM2_USB is not set # CONFIG_ECHO is not set # CONFIG_COMEDI is not set -# CONFIG_FB_OLPC_DCON is not set # CONFIG_ASUS_OLED is not set # CONFIG_PANEL is not set # CONFIG_R8187SE is not set @@ -4501,6 +4695,8 @@ CONFIG_RTLLIB_CRYPTO_WEP=m # CONFIG_IIO_SYSFS_TRIGGER is not set # CONFIG_IIO_SIMPLE_DUMMY is not set # CONFIG_ZSMALLOC is not set +# CONFIG_WLAGS49_H2 is not set +# CONFIG_WLAGS49_H25 is not set # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -4575,7 +4771,6 @@ CONFIG_TOSHIBA_BT_RFKILL=m CONFIG_ACPI_CMPC=m CONFIG_INTEL_IPS=m # CONFIG_IBM_RTL is not set -CONFIG_XO1_RFKILL=m # CONFIG_XO15_EBOOK is not set CONFIG_SAMSUNG_LAPTOP=m CONFIG_MXM_WMI=m @@ -4591,7 +4786,6 @@ CONFIG_COMMON_CLK=y # Common Clock Framework # # CONFIG_COMMON_CLK_DEBUG is not set -# CONFIG_COMMON_CLK_SI5351 is not set # # Hardware Spinlock drivers @@ -4603,7 +4797,6 @@ CONFIG_CLKBLD_I8253=y CONFIG_MAILBOX=y CONFIG_IOMMU_API=y CONFIG_IOMMU_SUPPORT=y -CONFIG_OF_IOMMU=y CONFIG_DMAR_TABLE=y CONFIG_INTEL_IOMMU=y # CONFIG_INTEL_IOMMU_DEFAULT_ON is not set @@ -4636,7 +4829,6 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # # Analog to digital converters # -# CONFIG_EXYNOS_ADC is not set # CONFIG_MAX1363 is not set # CONFIG_TI_ADC081C is not set # CONFIG_VIPERBOARD_ADC is not set @@ -4701,8 +4893,7 @@ CONFIG_HID_SENSOR_IIO_TRIGGER=m # CONFIG_HID_SENSOR_MAGNETOMETER_3D is not set # CONFIG_IIO_ST_MAGN_3AXIS is not set # CONFIG_VME_BUS is not set -CONFIG_PWM=y -CONFIG_IRQCHIP=y +# CONFIG_PWM is not set # CONFIG_IPACK_BUS is not set # CONFIG_RESET_CONTROLLER is not set @@ -4995,6 +5186,9 @@ CONFIG_HAVE_DEBUG_KMEMLEAK=y # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set # CONFIG_DEBUG_ATOMIC_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set CONFIG_STACKTRACE=y @@ -5157,9 +5351,8 @@ CONFIG_PAX_EMUTRAMP=y CONFIG_PAX_MPROTECT=y # CONFIG_PAX_MPROTECT_COMPAT is not set CONFIG_PAX_ELFRELOCS=y -CONFIG_PAX_KERNEXEC=y +# CONFIG_PAX_KERNEXEC is not set CONFIG_PAX_KERNEXEC_PLUGIN_METHOD="" -CONFIG_PAX_KERNEXEC_MODULE_TEXT=4 # # Address Space Layout Randomization @@ -5174,9 +5367,8 @@ CONFIG_PAX_RANDMMAP=y # CONFIG_PAX_MEMORY_STACKLEAK=y CONFIG_PAX_MEMORY_STRUCTLEAK=y -CONFIG_PAX_MEMORY_UDEREF=y +# CONFIG_PAX_MEMORY_UDEREF is not set CONFIG_PAX_REFCOUNT=y -CONFIG_PAX_CONSTIFY_PLUGIN=y CONFIG_PAX_USERCOPY=y # CONFIG_PAX_USERCOPY_DEBUG is not set # CONFIG_PAX_SIZE_OVERFLOW is not set @@ -5215,7 +5407,7 @@ CONFIG_GRKERNSEC_FIFO=y # CONFIG_GRKERNSEC_ROFS is not set CONFIG_GRKERNSEC_DEVICE_SIDECHANNEL=y CONFIG_GRKERNSEC_CHROOT=y -CONFIG_GRKERNSEC_CHROOT_MOUNT=y +# CONFIG_GRKERNSEC_CHROOT_MOUNT is not set CONFIG_GRKERNSEC_CHROOT_DOUBLE=y CONFIG_GRKERNSEC_CHROOT_PIVOT=y CONFIG_GRKERNSEC_CHROOT_CHDIR=y @@ -5263,6 +5455,11 @@ CONFIG_GRKERNSEC_BLACKHOLE=y CONFIG_GRKERNSEC_NO_SIMULT_CONNECT=y # CONFIG_GRKERNSEC_SOCKET is not set +# +# Physical Protections +# +# CONFIG_GRKERNSEC_DENYUSB is not set + # # Sysctl Support # @@ -5422,7 +5619,8 @@ CONFIG_CRYPTO_DEV_PADLOCK=m CONFIG_CRYPTO_DEV_PADLOCK_AES=m CONFIG_CRYPTO_DEV_PADLOCK_SHA=m CONFIG_CRYPTO_DEV_GEODE=m -# CONFIG_CRYPTO_DEV_HIFN_795X is not set +CONFIG_CRYPTO_DEV_HIFN_795X=m +CONFIG_CRYPTO_DEV_HIFN_795X_RNG=y CONFIG_ASYMMETRIC_KEY_TYPE=m CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=m CONFIG_PUBLIC_KEY_ALGO_RSA=m diff --git a/config/kernel/kernel.config.i586-ipfire-pae b/config/kernel/kernel.config.i586-ipfire-pae index 18bd29eae..4c32511e8 100644 --- a/config/kernel/kernel.config.i586-ipfire-pae +++ b/config/kernel/kernel.config.i586-ipfire-pae @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/x86 3.10.9 Kernel Configuration +# Linux/x86 3.10.10 Kernel Configuration # # CONFIG_64BIT is not set CONFIG_X86_32=y @@ -662,14 +662,20 @@ CONFIG_PCI_IOV=y CONFIG_PCI_IOAPIC=y CONFIG_PCI_LABEL=y CONFIG_ISA_DMA_API=y -# CONFIG_ISA is not set +CONFIG_ISA=y +CONFIG_EISA=y +# CONFIG_EISA_VLB_PRIMING is not set +CONFIG_EISA_PCI_EISA=y +CONFIG_EISA_VIRTUAL_ROOT=y +CONFIG_EISA_NAMES=y # CONFIG_SCx200 is not set # CONFIG_ALIX is not set # CONFIG_NET5501 is not set # CONFIG_GEOS is not set CONFIG_AMD_NB=y CONFIG_PCCARD=m -# CONFIG_PCMCIA is not set +CONFIG_PCMCIA=m +CONFIG_PCMCIA_LOAD_CIS=y CONFIG_CARDBUS=y # @@ -681,6 +687,12 @@ CONFIG_YENTA_RICOH=y CONFIG_YENTA_TI=y CONFIG_YENTA_ENE_TUNE=y CONFIG_YENTA_TOSHIBA=y +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_I82365=m +CONFIG_TCIC=m +CONFIG_PCMCIA_PROBE=y +CONFIG_PCCARD_NONSTATIC=y CONFIG_HOTPLUG_PCI=y # CONFIG_HOTPLUG_PCI_COMPAQ is not set # CONFIG_HOTPLUG_PCI_IBM is not set @@ -1226,6 +1238,10 @@ CONFIG_BT_HCIUART_3WIRE=y CONFIG_BT_HCIBCM203X=m CONFIG_BT_HCIBPA10X=m CONFIG_BT_HCIBFUSB=m +# CONFIG_BT_HCIDTL1 is not set +# CONFIG_BT_HCIBT3C is not set +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIBTUART=m CONFIG_BT_HCIVHCI=m CONFIG_BT_MRVL=m CONFIG_BT_MRVL_SDIO=m @@ -1309,10 +1325,11 @@ CONFIG_PROC_EVENTS=y CONFIG_PARPORT=m CONFIG_PARPORT_PC=m CONFIG_PARPORT_SERIAL=m -# CONFIG_PARPORT_PC_FIFO is not set -# CONFIG_PARPORT_PC_SUPERIO is not set +CONFIG_PARPORT_PC_FIFO=y +CONFIG_PARPORT_PC_SUPERIO=y +CONFIG_PARPORT_PC_PCMCIA=m # CONFIG_PARPORT_GSC is not set -# CONFIG_PARPORT_AX88796 is not set +CONFIG_PARPORT_AX88796=m CONFIG_PARPORT_1284=y CONFIG_PARPORT_NOT_PC=y CONFIG_PNP=y @@ -1321,6 +1338,9 @@ CONFIG_PNP=y # # Protocols # +CONFIG_ISAPNP=y +CONFIG_PNPBIOS=y +# CONFIG_PNPBIOS_PROC_FS is not set CONFIG_PNPACPI=y CONFIG_BLK_DEV=y CONFIG_BLK_DEV_FD=m @@ -1469,7 +1489,11 @@ CONFIG_BLK_DEV_3W_XXXX_RAID=m CONFIG_SCSI_HPSA=m CONFIG_SCSI_3W_9XXX=m CONFIG_SCSI_3W_SAS=m +CONFIG_SCSI_7000FASST=m CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AHA152X=m +CONFIG_SCSI_AHA1542=m +CONFIG_SCSI_AHA1740=m CONFIG_SCSI_AACRAID=m CONFIG_SCSI_AIC7XXX=m CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 @@ -1489,9 +1513,10 @@ CONFIG_SCSI_AIC94XX=m CONFIG_SCSI_MVSAS=m # CONFIG_SCSI_MVSAS_DEBUG is not set CONFIG_SCSI_MVSAS_TASKLET=y -# CONFIG_SCSI_MVUMI is not set +CONFIG_SCSI_MVUMI=m CONFIG_SCSI_DPT_I2O=m CONFIG_SCSI_ADVANSYS=m +CONFIG_SCSI_IN2000=m CONFIG_SCSI_ARCMSR=m CONFIG_MEGARAID_NEWGEN=y CONFIG_MEGARAID_MM=m @@ -1516,6 +1541,7 @@ CONFIG_LIBFCOE=m CONFIG_FCOE=m CONFIG_FCOE_FNIC=m CONFIG_SCSI_DMX3191D=m +CONFIG_SCSI_DTC3280=m CONFIG_SCSI_EATA=m CONFIG_SCSI_EATA_TAGGED_QUEUE=y # CONFIG_SCSI_EATA_LINKED_COMMANDS is not set @@ -1523,6 +1549,9 @@ CONFIG_SCSI_EATA_MAX_TAGS=16 CONFIG_SCSI_FUTURE_DOMAIN=m CONFIG_SCSI_GDTH=m CONFIG_SCSI_ISCI=m +CONFIG_SCSI_GENERIC_NCR5380=m +CONFIG_SCSI_GENERIC_NCR5380_MMIO=m +# CONFIG_SCSI_GENERIC_NCR53C400 is not set CONFIG_SCSI_IPS=m CONFIG_SCSI_INITIO=m CONFIG_SCSI_INIA100=m @@ -1530,6 +1559,7 @@ CONFIG_SCSI_PPA=m CONFIG_SCSI_IMM=m # CONFIG_SCSI_IZIP_EPP16 is not set # CONFIG_SCSI_IZIP_SLOW_CTR is not set +CONFIG_SCSI_NCR53C406A=m CONFIG_SCSI_STEX=m CONFIG_SCSI_SYM53C8XX_2=m CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 @@ -1539,14 +1569,24 @@ CONFIG_SCSI_SYM53C8XX_MMIO=y CONFIG_SCSI_IPR=m CONFIG_SCSI_IPR_TRACE=y CONFIG_SCSI_IPR_DUMP=y +CONFIG_SCSI_PAS16=m +CONFIG_SCSI_QLOGIC_FAS=m CONFIG_SCSI_QLOGIC_1280=m CONFIG_SCSI_QLA_FC=m CONFIG_SCSI_QLA_ISCSI=m CONFIG_SCSI_LPFC=m # CONFIG_SCSI_LPFC_DEBUG_FS is not set +CONFIG_SCSI_SIM710=m +CONFIG_SCSI_SYM53C416=m CONFIG_SCSI_DC395x=m CONFIG_SCSI_DC390T=m -# CONFIG_SCSI_NSP32 is not set +CONFIG_SCSI_T128=m +CONFIG_SCSI_U14_34F=m +# CONFIG_SCSI_U14_34F_TAGGED_QUEUE is not set +# CONFIG_SCSI_U14_34F_LINKED_COMMANDS is not set +CONFIG_SCSI_U14_34F_MAX_TAGS=8 +CONFIG_SCSI_ULTRASTOR=m +CONFIG_SCSI_NSP32=m # CONFIG_SCSI_DEBUG is not set CONFIG_SCSI_PMCRAID=m CONFIG_SCSI_PM8001=m @@ -1554,6 +1594,12 @@ CONFIG_SCSI_PM8001=m CONFIG_SCSI_BFA_FC=m CONFIG_SCSI_VIRTIO=m CONFIG_SCSI_CHELSIO_FCOE=m +CONFIG_SCSI_LOWLEVEL_PCMCIA=y +CONFIG_PCMCIA_AHA152X=m +CONFIG_PCMCIA_FDOMAIN=m +CONFIG_PCMCIA_NINJA_SCSI=m +CONFIG_PCMCIA_QLOGIC=m +CONFIG_PCMCIA_SYM53C500=m CONFIG_SCSI_DH=y CONFIG_SCSI_DH_RDAC=m CONFIG_SCSI_DH_HP_SW=m @@ -1567,7 +1613,7 @@ CONFIG_ATA=y # CONFIG_ATA_NONSTANDARD is not set CONFIG_ATA_VERBOSE_ERROR=y CONFIG_ATA_ACPI=y -# CONFIG_SATA_ZPODD is not set +CONFIG_SATA_ZPODD=y CONFIG_SATA_PMP=y # @@ -1635,9 +1681,9 @@ CONFIG_PATA_OLDPIIX=m CONFIG_PATA_OPTIDMA=m CONFIG_PATA_PDC2027X=m CONFIG_PATA_PDC_OLD=m -# CONFIG_PATA_RADISYS is not set +CONFIG_PATA_RADISYS=m CONFIG_PATA_RDC=m -# CONFIG_PATA_SC1200 is not set +CONFIG_PATA_SC1200=m CONFIG_PATA_SCH=m CONFIG_PATA_SERVERWORKS=m CONFIG_PATA_SIL680=m @@ -1651,18 +1697,22 @@ CONFIG_PATA_WINBOND=m # PIO-only SFF controllers # CONFIG_PATA_CMD640_PCI=m +CONFIG_PATA_ISAPNP=m CONFIG_PATA_MPIIX=m CONFIG_PATA_NS87410=m CONFIG_PATA_OPTI=m -# CONFIG_PATA_PLATFORM is not set +CONFIG_PATA_PCMCIA=m +CONFIG_PATA_PLATFORM=m +CONFIG_PATA_QDI=m CONFIG_PATA_RZ1000=m +CONFIG_PATA_WINBOND_VLB=m # # Generic fallback / legacy drivers # CONFIG_PATA_ACPI=m CONFIG_ATA_GENERIC=m -# CONFIG_PATA_LEGACY is not set +CONFIG_PATA_LEGACY=m CONFIG_MD=y CONFIG_BLK_DEV_MD=y CONFIG_MD_AUTODETECT=y @@ -1764,7 +1814,8 @@ CONFIG_ATM_ENI=m # CONFIG_ATM_ENI_DEBUG is not set # CONFIG_ATM_ENI_TUNE_BURST is not set CONFIG_ATM_FIRESTREAM=m -# CONFIG_ATM_ZATM is not set +CONFIG_ATM_ZATM=m +# CONFIG_ATM_ZATM_DEBUG is not set CONFIG_ATM_NICSTAR=m # CONFIG_ATM_NICSTAR_USE_SUNI is not set # CONFIG_ATM_NICSTAR_USE_IDT77105 is not set @@ -1772,10 +1823,16 @@ CONFIG_ATM_IDT77252=m # CONFIG_ATM_IDT77252_DEBUG is not set # CONFIG_ATM_IDT77252_RCV_ALL is not set CONFIG_ATM_IDT77252_USE_SUNI=y -# CONFIG_ATM_AMBASSADOR is not set -# CONFIG_ATM_HORIZON is not set -# CONFIG_ATM_IA is not set -# CONFIG_ATM_FORE200E is not set +CONFIG_ATM_AMBASSADOR=m +# CONFIG_ATM_AMBASSADOR_DEBUG is not set +CONFIG_ATM_HORIZON=m +# CONFIG_ATM_HORIZON_DEBUG is not set +CONFIG_ATM_IA=m +# CONFIG_ATM_IA_DEBUG is not set +CONFIG_ATM_FORE200E=m +# CONFIG_ATM_FORE200E_USE_TASKLET is not set +CONFIG_ATM_FORE200E_TX_RETRY=16 +CONFIG_ATM_FORE200E_DEBUG=0 CONFIG_ATM_HE=m # CONFIG_ATM_HE_USE_SUNI is not set CONFIG_ATM_SOLOS=m @@ -1797,6 +1854,10 @@ CONFIG_NET_DSA_MV88E6123_61_65=y CONFIG_ETHERNET=y CONFIG_MDIO=m CONFIG_NET_VENDOR_3COM=y +CONFIG_EL3=m +CONFIG_3C515=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_3C589=m CONFIG_VORTEX=m CONFIG_TYPHOON=m CONFIG_NET_VENDOR_ADAPTEC=y @@ -1806,7 +1867,10 @@ CONFIG_ACENIC=m # CONFIG_ACENIC_OMIT_TIGON_I is not set CONFIG_NET_VENDOR_AMD=y CONFIG_AMD8111_ETH=m +CONFIG_LANCE=m CONFIG_PCNET32=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_NI65=m CONFIG_NET_VENDOR_ATHEROS=y CONFIG_ATL2=m CONFIG_ATL1=m @@ -1835,6 +1899,9 @@ CONFIG_CHELSIO_T1_1G=y CONFIG_CHELSIO_T3=m CONFIG_CHELSIO_T4=m CONFIG_CHELSIO_T4VF=m +CONFIG_NET_VENDOR_CIRRUS=y +CONFIG_CS89x0=m +# CONFIG_CS89x0_PLATFORM is not set CONFIG_NET_VENDOR_CISCO=y CONFIG_ENIC=m CONFIG_DNET=m @@ -1862,6 +1929,8 @@ CONFIG_NET_VENDOR_EXAR=y CONFIG_S2IO=m CONFIG_VXGE=m # CONFIG_VXGE_DEBUG_TRACE_ALL is not set +CONFIG_NET_VENDOR_FUJITSU=y +CONFIG_PCMCIA_FMVJ18X=m CONFIG_NET_VENDOR_HP=y CONFIG_HP100=m CONFIG_NET_VENDOR_INTEL=y @@ -1892,8 +1961,8 @@ CONFIG_MLX4_EN=m CONFIG_MLX4_CORE=m CONFIG_MLX4_DEBUG=y CONFIG_NET_VENDOR_MICREL=y -# CONFIG_KS8842 is not set -# CONFIG_KS8851_MLL is not set +CONFIG_KS8842=m +CONFIG_KS8851_MLL=m CONFIG_KSZ884X_PCI=m CONFIG_NET_VENDOR_MYRI=y CONFIG_MYRI10GE=m @@ -1903,7 +1972,12 @@ CONFIG_NET_VENDOR_NATSEMI=y CONFIG_NATSEMI=m CONFIG_NS83820=m CONFIG_NET_VENDOR_8390=y +CONFIG_PCMCIA_AXNET=m +CONFIG_NE2000=m CONFIG_NE2K_PCI=m +CONFIG_PCMCIA_PCNET=m +CONFIG_ULTRA=m +CONFIG_WD80x3=m CONFIG_NET_VENDOR_NVIDIA=y CONFIG_FORCEDETH=m CONFIG_NET_VENDOR_OKI=y @@ -1937,6 +2011,8 @@ CONFIG_SFC=m CONFIG_SFC_MCDI_MON=y CONFIG_SFC_SRIOV=y CONFIG_NET_VENDOR_SMSC=y +CONFIG_SMC9194=m +CONFIG_PCMCIA_SMC91C92=m CONFIG_EPIC100=m CONFIG_SMSC9420=m CONFIG_NET_VENDOR_STMICRO=y @@ -1964,6 +2040,8 @@ CONFIG_WIZNET_W5300=m # CONFIG_WIZNET_BUS_DIRECT is not set # CONFIG_WIZNET_BUS_INDIRECT is not set CONFIG_WIZNET_BUS_ANY=y +CONFIG_NET_VENDOR_XIRCOM=y +CONFIG_PCMCIA_XIRC2PS=m # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_NET_SB1000 is not set @@ -2048,13 +2126,17 @@ CONFIG_USB_IPHETH=m CONFIG_USB_SIERRA_NET=m CONFIG_USB_VL600=m CONFIG_WLAN=y +# CONFIG_PCMCIA_RAYCS is not set CONFIG_LIBERTAS_THINFIRM=m # CONFIG_LIBERTAS_THINFIRM_DEBUG is not set CONFIG_LIBERTAS_THINFIRM_USB=m CONFIG_AIRO=m CONFIG_ATMEL=m CONFIG_PCI_ATMEL=m +CONFIG_PCMCIA_ATMEL=m CONFIG_AT76C50X_USB=m +CONFIG_AIRO_CS=m +CONFIG_PCMCIA_WL3501=m # CONFIG_PRISM54 is not set CONFIG_USB_ZD1201=m CONFIG_USB_NET_RNDIS_WLAN=m @@ -2093,6 +2175,7 @@ CONFIG_B43=m CONFIG_B43_SSB=y CONFIG_B43_PCI_AUTOSELECT=y CONFIG_B43_PCICORE_AUTOSELECT=y +# CONFIG_B43_PCMCIA is not set CONFIG_B43_SDIO=y CONFIG_B43_PIO=y CONFIG_B43_PHY_N=y @@ -2111,12 +2194,18 @@ CONFIG_B43LEGACY_PIO=y CONFIG_B43LEGACY_DMA_AND_PIO_MODE=y # CONFIG_B43LEGACY_DMA_MODE is not set # CONFIG_B43LEGACY_PIO_MODE is not set -# CONFIG_BRCMFMAC is not set +CONFIG_BRCMUTIL=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_SDIO=y +# CONFIG_BRCMFMAC_USB is not set +# CONFIG_BRCM_TRACING is not set +# CONFIG_BRCMDBG is not set CONFIG_HOSTAP=m CONFIG_HOSTAP_FIRMWARE=y CONFIG_HOSTAP_FIRMWARE_NVRAM=y CONFIG_HOSTAP_PLX=m CONFIG_HOSTAP_PCI=m +CONFIG_HOSTAP_CS=m CONFIG_IPW2100=m CONFIG_IPW2100_MONITOR=y # CONFIG_IPW2100_DEBUG is not set @@ -2128,7 +2217,17 @@ CONFIG_IPW2200_QOS=y # CONFIG_IPW2200_DEBUG is not set CONFIG_LIBIPW=m # CONFIG_LIBIPW_DEBUG is not set -# CONFIG_IWLWIFI is not set +CONFIG_IWLWIFI=m +CONFIG_IWLDVM=m +CONFIG_IWLMVM=m +CONFIG_IWLWIFI_OPMODE_MODULAR=y + +# +# Debugging Options +# +# CONFIG_IWLWIFI_DEBUG is not set +# CONFIG_IWLWIFI_DEVICE_TRACING is not set +CONFIG_IWLWIFI_P2P=y CONFIG_IWLEGACY=m CONFIG_IWL4965=m CONFIG_IWL3945=m @@ -2139,6 +2238,7 @@ CONFIG_IWL3945=m # CONFIG_IWLEGACY_DEBUG is not set CONFIG_LIBERTAS=m CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_CS=m CONFIG_LIBERTAS_SDIO=m # CONFIG_LIBERTAS_DEBUG is not set CONFIG_LIBERTAS_MESH=y @@ -2148,6 +2248,8 @@ CONFIG_HERMES_CACHE_FW_ON_INIT=y CONFIG_PLX_HERMES=m CONFIG_TMD_HERMES=m CONFIG_NORTEL_HERMES=m +CONFIG_PCMCIA_HERMES=m +CONFIG_PCMCIA_SPECTRUM=m CONFIG_ORINOCO_USB=m CONFIG_P54_COMMON=m CONFIG_P54_USB=m @@ -2200,7 +2302,7 @@ CONFIG_ZD1211RW=m # CONFIG_ZD1211RW_DEBUG is not set CONFIG_MWIFIEX=m CONFIG_MWIFIEX_SDIO=m -# CONFIG_MWIFIEX_PCIE is not set +CONFIG_MWIFIEX_PCIE=m CONFIG_MWIFIEX_USB=m # @@ -2249,17 +2351,27 @@ CONFIG_HISAX_MAX_CARDS=8 # # HiSax supported cards # +# CONFIG_HISAX_16_0 is not set CONFIG_HISAX_16_3=y CONFIG_HISAX_TELESPCI=y CONFIG_HISAX_S0BOX=y +# CONFIG_HISAX_AVM_A1 is not set CONFIG_HISAX_FRITZPCI=y CONFIG_HISAX_AVM_A1_PCMCIA=y CONFIG_HISAX_ELSA=y +# CONFIG_HISAX_IX1MICROR2 is not set CONFIG_HISAX_DIEHLDIVA=y +# CONFIG_HISAX_ASUSCOM is not set +# CONFIG_HISAX_TELEINT is not set +# CONFIG_HISAX_HFCS is not set CONFIG_HISAX_SEDLBAUER=y +# CONFIG_HISAX_SPORTSTER is not set +# CONFIG_HISAX_MIC is not set CONFIG_HISAX_NETJET=y CONFIG_HISAX_NETJET_U=y CONFIG_HISAX_NICCY=y +# CONFIG_HISAX_ISURF is not set +# CONFIG_HISAX_HSTSAPHIR is not set CONFIG_HISAX_BKM_A4T=y CONFIG_HISAX_SCT_QUADRO=y CONFIG_HISAX_GAZEL=y @@ -2272,6 +2384,10 @@ CONFIG_HISAX_ENTERNOW_PCI=y # # HiSax PCMCIA card service modules # +# CONFIG_HISAX_SEDLBAUER_CS is not set +# CONFIG_HISAX_ELSA_CS is not set +# CONFIG_HISAX_AVM_A1_CS is not set +# CONFIG_HISAX_TELES_CS is not set # # HiSax sub driver modules @@ -2284,6 +2400,10 @@ CONFIG_HISAX_FRITZ_PCIPNP=m # # Active cards # +# CONFIG_ISDN_DRV_ICN is not set +# CONFIG_ISDN_DRV_PCBIT is not set +# CONFIG_ISDN_DRV_SC is not set +# CONFIG_ISDN_DRV_ACT2000 is not set CONFIG_ISDN_CAPI=m CONFIG_ISDN_DRV_AVMB1_VERBOSE_REASON=y CONFIG_CAPI_TRACE=y @@ -2295,8 +2415,11 @@ CONFIG_ISDN_CAPI_CAPIDRV=m # CAPI hardware drivers # CONFIG_CAPI_AVM=y +# CONFIG_ISDN_DRV_AVMB1_B1ISA is not set CONFIG_ISDN_DRV_AVMB1_B1PCI=m CONFIG_ISDN_DRV_AVMB1_B1PCIV4=y +# CONFIG_ISDN_DRV_AVMB1_T1ISA is not set +# CONFIG_ISDN_DRV_AVMB1_B1PCMCIA is not set CONFIG_ISDN_DRV_AVMB1_T1PCI=m CONFIG_ISDN_DRV_AVMB1_C4=m CONFIG_CAPI_EICON=y @@ -2373,6 +2496,9 @@ CONFIG_MOUSE_SERIAL=m CONFIG_MOUSE_APPLETOUCH=m CONFIG_MOUSE_BCM5974=m CONFIG_MOUSE_CYAPA=m +# CONFIG_MOUSE_INPORT is not set +# CONFIG_MOUSE_LOGIBM is not set +# CONFIG_MOUSE_PC110PAD is not set CONFIG_MOUSE_VSXXXAA=m # CONFIG_MOUSE_GPIO is not set CONFIG_MOUSE_SYNAPTICS_I2C=m @@ -2461,10 +2587,16 @@ CONFIG_SERIAL_8250_CONSOLE=y CONFIG_FIX_EARLYCON_MEM=y CONFIG_SERIAL_8250_DMA=y CONFIG_SERIAL_8250_PCI=y +# CONFIG_SERIAL_8250_CS is not set CONFIG_SERIAL_8250_NR_UARTS=4 CONFIG_SERIAL_8250_RUNTIME_UARTS=4 CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y +# CONFIG_SERIAL_8250_FOURPORT is not set +# CONFIG_SERIAL_8250_ACCENT is not set +# CONFIG_SERIAL_8250_BOCA is not set +# CONFIG_SERIAL_8250_EXAR_ST16C554 is not set +# CONFIG_SERIAL_8250_HUB6 is not set CONFIG_SERIAL_8250_SHARE_IRQ=y # CONFIG_SERIAL_8250_DETECT_IRQ is not set CONFIG_SERIAL_8250_RSA=y @@ -2511,9 +2643,18 @@ CONFIG_HW_RANDOM_VIA=m CONFIG_HW_RANDOM_VIRTIO=m CONFIG_HW_RANDOM_EXYNOS=m CONFIG_NVRAM=y +# CONFIG_DTLK is not set CONFIG_R3964=m # CONFIG_APPLICOM is not set CONFIG_SONYPI=m + +# +# PCMCIA character devices +# +# CONFIG_SYNCLINK_CS is not set +# CONFIG_CARDMAN_4000 is not set +# CONFIG_CARDMAN_4040 is not set +# CONFIG_IPWIRELESS is not set CONFIG_MWAVE=m CONFIG_PC8736x_GPIO=m CONFIG_NSC_GPIO=m @@ -2593,6 +2734,7 @@ CONFIG_I2C_VIPERBOARD=m # # Other I2C/SMBus bus drivers # +# CONFIG_I2C_PCA_ISA is not set CONFIG_SCx200_ACB=m CONFIG_I2C_STUB=m # CONFIG_I2C_DEBUG_CORE is not set @@ -2939,6 +3081,13 @@ CONFIG_MACHZ_WDT=m # CONFIG_SBC_EPX_C3_WATCHDOG is not set CONFIG_XEN_WDT=m +# +# ISA-based Watchdog Cards +# +# CONFIG_PCWATCHDOG is not set +# CONFIG_MIXCOMWD is not set +# CONFIG_WDT is not set + # # PCI-based Watchdog Cards # @@ -2960,10 +3109,11 @@ CONFIG_SSB_BLOCKIO=y CONFIG_SSB_PCIHOST_POSSIBLE=y CONFIG_SSB_PCIHOST=y CONFIG_SSB_B43_PCI_BRIDGE=y +CONFIG_SSB_PCMCIAHOST_POSSIBLE=y +CONFIG_SSB_PCMCIAHOST=y CONFIG_SSB_SDIOHOST_POSSIBLE=y CONFIG_SSB_SDIOHOST=y -# CONFIG_SSB_SILENT is not set -# CONFIG_SSB_DEBUG is not set +CONFIG_SSB_SILENT=y CONFIG_SSB_DRIVER_PCICORE_POSSIBLE=y CONFIG_SSB_DRIVER_PCICORE=y CONFIG_SSB_DRIVER_GPIO=y @@ -3047,7 +3197,7 @@ CONFIG_DVB_DYNAMIC_MINORS=y # Media drivers # CONFIG_RC_CORE=y -# CONFIG_RC_MAP is not set +CONFIG_RC_MAP=m CONFIG_RC_DECODERS=y CONFIG_LIRC=m CONFIG_IR_LIRC_CODEC=m @@ -3060,7 +3210,7 @@ CONFIG_IR_RC5_SZ_DECODER=m CONFIG_IR_SANYO_DECODER=m CONFIG_IR_MCE_KBD_DECODER=m CONFIG_RC_DEVICES=y -# CONFIG_RC_ATI_REMOTE is not set +CONFIG_RC_ATI_REMOTE=m CONFIG_IR_ENE=m CONFIG_IR_IMON=m CONFIG_IR_MCEUSB=m @@ -3122,7 +3272,7 @@ CONFIG_USB_GSPCA_STK014=m CONFIG_USB_GSPCA_STV0680=m CONFIG_USB_GSPCA_SUNPLUS=m CONFIG_USB_GSPCA_T613=m -# CONFIG_USB_GSPCA_TOPRO is not set +CONFIG_USB_GSPCA_TOPRO=m CONFIG_USB_GSPCA_TV8532=m CONFIG_USB_GSPCA_VC032X=m CONFIG_USB_GSPCA_VICAM=m @@ -3135,16 +3285,20 @@ CONFIG_VIDEO_CPIA2=m CONFIG_USB_ZR364XX=m CONFIG_USB_STKWEBCAM=m CONFIG_USB_S2255=m -# CONFIG_USB_SN9C102 is not set +CONFIG_USB_SN9C102=m # # Analog TV USB devices # -# CONFIG_VIDEO_PVRUSB2 is not set -# CONFIG_VIDEO_HDPVR is not set -# CONFIG_VIDEO_TLG2300 is not set -# CONFIG_VIDEO_USBVISION is not set -# CONFIG_VIDEO_STK1160 is not set +CONFIG_VIDEO_PVRUSB2=m +CONFIG_VIDEO_PVRUSB2_SYSFS=y +CONFIG_VIDEO_PVRUSB2_DVB=y +# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set +CONFIG_VIDEO_HDPVR=m +CONFIG_VIDEO_TLG2300=m +CONFIG_VIDEO_USBVISION=m +CONFIG_VIDEO_STK1160=m +CONFIG_VIDEO_STK1160_AC97=y # # Analog/digital TV USB devices @@ -3182,7 +3336,7 @@ CONFIG_DVB_USB_DTT200U=m CONFIG_DVB_USB_OPERA1=m CONFIG_DVB_USB_AF9005=m CONFIG_DVB_USB_AF9005_REMOTE=m -# CONFIG_DVB_USB_PCTV452E is not set +CONFIG_DVB_USB_PCTV452E=m CONFIG_DVB_USB_DW2102=m CONFIG_DVB_USB_CINERGY_T2=m CONFIG_DVB_USB_DTV5100=m @@ -3198,10 +3352,11 @@ CONFIG_DVB_USB_AZ6007=m CONFIG_DVB_USB_CE6230=m CONFIG_DVB_USB_EC168=m CONFIG_DVB_USB_GL861=m -# CONFIG_DVB_USB_IT913X is not set +CONFIG_DVB_USB_IT913X=m CONFIG_DVB_USB_LME2510=m -# CONFIG_DVB_USB_MXL111SF is not set +CONFIG_DVB_USB_MXL111SF=m CONFIG_DVB_USB_RTL28XXU=m +CONFIG_DVB_USB_DVBSKY=m CONFIG_DVB_TTUSB_BUDGET=m CONFIG_DVB_TTUSB_DEC=m CONFIG_SMS_USB_DRV=m @@ -3225,11 +3380,20 @@ CONFIG_VIDEO_MEYE=m # # Media capture/analog TV support # -# CONFIG_VIDEO_IVTV is not set -# CONFIG_VIDEO_ZORAN is not set -# CONFIG_VIDEO_HEXIUM_GEMINI is not set -# CONFIG_VIDEO_HEXIUM_ORION is not set -# CONFIG_VIDEO_MXB is not set +CONFIG_VIDEO_IVTV=m +CONFIG_VIDEO_IVTV_ALSA=m +CONFIG_VIDEO_FB_IVTV=m +CONFIG_VIDEO_ZORAN=m +CONFIG_VIDEO_ZORAN_DC30=m +CONFIG_VIDEO_ZORAN_ZR36060=m +CONFIG_VIDEO_ZORAN_BUZ=m +CONFIG_VIDEO_ZORAN_DC10=m +CONFIG_VIDEO_ZORAN_LML33=m +CONFIG_VIDEO_ZORAN_LML33R10=m +CONFIG_VIDEO_ZORAN_AVS6EYES=m +CONFIG_VIDEO_HEXIUM_GEMINI=m +CONFIG_VIDEO_HEXIUM_ORION=m +CONFIG_VIDEO_MXB=m # # Media capture/analog/hybrid TV support @@ -3273,7 +3437,7 @@ CONFIG_MANTIS_CORE=m CONFIG_DVB_MANTIS=m CONFIG_DVB_HOPPER=m CONFIG_DVB_NGENE=m -# CONFIG_DVB_DDBRIDGE is not set +CONFIG_DVB_DDBRIDGE=m CONFIG_V4L_PLATFORM_DRIVERS=y CONFIG_VIDEO_CAFE_CCIC=m CONFIG_VIDEO_TIMBERDALE=m @@ -3325,9 +3489,15 @@ CONFIG_VIDEO_IR_I2C=m # CONFIG_VIDEO_TVAUDIO=m CONFIG_VIDEO_TDA7432=m +CONFIG_VIDEO_TDA9840=m +CONFIG_VIDEO_TEA6415C=m +CONFIG_VIDEO_TEA6420=m CONFIG_VIDEO_MSP3400=m CONFIG_VIDEO_CS5345=m +CONFIG_VIDEO_CS53L32A=m CONFIG_VIDEO_WM8775=m +CONFIG_VIDEO_WM8739=m +CONFIG_VIDEO_VP27SMPX=m # # RDS decoders @@ -3338,17 +3508,28 @@ CONFIG_VIDEO_SAA6588=m # Video decoders # CONFIG_VIDEO_ADV7180=m +CONFIG_VIDEO_BT819=m +CONFIG_VIDEO_BT856=m +CONFIG_VIDEO_BT866=m +CONFIG_VIDEO_KS0127=m +CONFIG_VIDEO_SAA7110=m CONFIG_VIDEO_SAA711X=m CONFIG_VIDEO_TVP5150=m +CONFIG_VIDEO_VPX3220=m # # Video and audio decoders # +CONFIG_VIDEO_SAA717X=m CONFIG_VIDEO_CX25840=m # # Video encoders # +CONFIG_VIDEO_SAA7127=m +CONFIG_VIDEO_SAA7185=m +CONFIG_VIDEO_ADV7170=m +CONFIG_VIDEO_ADV7175=m # # Camera sensor devices @@ -3363,10 +3544,13 @@ CONFIG_VIDEO_MT9V011=m # # Video improvement chips # +CONFIG_VIDEO_UPD64031A=m +CONFIG_VIDEO_UPD64083=m # # Miscelaneous helper chips # +CONFIG_VIDEO_M52790=m # # Sensors used on soc_camera driver @@ -3456,6 +3640,8 @@ CONFIG_DVB_TUNER_CX24113=m CONFIG_DVB_TDA826X=m CONFIG_DVB_TUA6100=m CONFIG_DVB_CX24116=m +CONFIG_DVB_M88DS3103=m +CONFIG_DVB_M88DC2800=m CONFIG_DVB_SI21XX=m CONFIG_DVB_TS2020=m CONFIG_DVB_DS3000=m @@ -3504,6 +3690,7 @@ CONFIG_DVB_OR51132=m CONFIG_DVB_BCM3510=m CONFIG_DVB_LGDT330X=m CONFIG_DVB_LGDT3305=m +CONFIG_DVB_LG2160=m CONFIG_DVB_S5H1409=m CONFIG_DVB_AU8522=m CONFIG_DVB_AU8522_DTV=m @@ -3528,6 +3715,7 @@ CONFIG_DVB_TUNER_DIB0090=m # SEC control devices for DVB-S # CONFIG_DVB_LNBP21=m +CONFIG_DVB_LNBP22=m CONFIG_DVB_ISL6405=m CONFIG_DVB_ISL6421=m CONFIG_DVB_ISL6423=m @@ -3536,6 +3724,7 @@ CONFIG_DVB_LGS8GXX=m CONFIG_DVB_ATBM8830=m CONFIG_DVB_TDA665x=m CONFIG_DVB_IX2505V=m +CONFIG_DVB_IT913X_FE=m CONFIG_DVB_M88RS2000=m CONFIG_DVB_AF9033=m @@ -3688,6 +3877,7 @@ CONFIG_BACKLIGHT_APPLE=m # CONFIG_VGA_CONSOLE=y # CONFIG_VGACON_SOFT_SCROLLBACK is not set +# CONFIG_MDA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=m CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y @@ -3729,11 +3919,12 @@ CONFIG_SND_KCTL_JACK=y CONFIG_SND_DMA_SGBUF=y CONFIG_SND_RAWMIDI_SEQ=m CONFIG_SND_OPL3_LIB_SEQ=m -# CONFIG_SND_OPL4_LIB_SEQ is not set -# CONFIG_SND_SBAWE_SEQ is not set +CONFIG_SND_OPL4_LIB_SEQ=m +CONFIG_SND_SBAWE_SEQ=m CONFIG_SND_EMU10K1_SEQ=m CONFIG_SND_MPU401_UART=m CONFIG_SND_OPL3_LIB=m +CONFIG_SND_OPL4_LIB=m CONFIG_SND_VX_LIB=m CONFIG_SND_AC97_CODEC=m CONFIG_SND_DRIVERS=y @@ -3748,8 +3939,44 @@ CONFIG_SND_MPU401=m CONFIG_SND_PORTMAN2X4=m CONFIG_SND_AC97_POWER_SAVE=y CONFIG_SND_AC97_POWER_SAVE_DEFAULT=0 +CONFIG_SND_WSS_LIB=m CONFIG_SND_SB_COMMON=m +CONFIG_SND_SB8_DSP=m CONFIG_SND_SB16_DSP=m +CONFIG_SND_ISA=y +CONFIG_SND_ADLIB=m +CONFIG_SND_AD1816A=m +CONFIG_SND_AD1848=m +CONFIG_SND_ALS100=m +CONFIG_SND_AZT1605=m +CONFIG_SND_AZT2316=m +CONFIG_SND_AZT2320=m +CONFIG_SND_CMI8328=m +CONFIG_SND_CMI8330=m +CONFIG_SND_CS4231=m +CONFIG_SND_CS4236=m +CONFIG_SND_ES1688=m +CONFIG_SND_ES18XX=m +CONFIG_SND_SC6000=m +CONFIG_SND_GUSCLASSIC=m +CONFIG_SND_GUSEXTREME=m +CONFIG_SND_GUSMAX=m +CONFIG_SND_INTERWAVE=m +CONFIG_SND_INTERWAVE_STB=m +CONFIG_SND_JAZZ16=m +CONFIG_SND_OPL3SA2=m +CONFIG_SND_OPTI92X_AD1848=m +CONFIG_SND_OPTI92X_CS4231=m +CONFIG_SND_OPTI93X=m +CONFIG_SND_MIRO=m +CONFIG_SND_SB8=m +CONFIG_SND_SB16=m +CONFIG_SND_SBAWE=m +CONFIG_SND_SB16_CSP=y +CONFIG_SND_SSCAPE=m +CONFIG_SND_WAVEFRONT=m +CONFIG_SND_MSND_PINNACLE=m +CONFIG_SND_MSND_CLASSIC=m CONFIG_SND_TEA575X=m CONFIG_SND_PCI=y CONFIG_SND_AD1889=m @@ -3861,6 +4088,9 @@ CONFIG_SND_FIREWIRE_LIB=m CONFIG_SND_FIREWIRE_SPEAKERS=m # CONFIG_SND_ISIGHT is not set # CONFIG_SND_SCS1X is not set +CONFIG_SND_PCMCIA=y +# CONFIG_SND_VXPOCKET is not set +# CONFIG_SND_PDAUDIOCF is not set # CONFIG_SND_SOC is not set # CONFIG_SOUND_PRIME is not set CONFIG_AC97_BUS=m @@ -4002,6 +4232,7 @@ CONFIG_USB_UHCI_HCD=y # CONFIG_USB_U132_HCD is not set CONFIG_USB_SL811_HCD=m CONFIG_USB_SL811_HCD_ISO=y +# CONFIG_USB_SL811_CS is not set # CONFIG_USB_R8A66597_HCD is not set CONFIG_USB_WHCI_HCD=m CONFIG_USB_HWA_HCD=m @@ -4177,6 +4408,7 @@ CONFIG_MMC_SDHCI_PXAV3=m CONFIG_MMC_SDHCI_PXAV2=m CONFIG_MMC_WBSD=m CONFIG_MMC_TIFM_SD=m +# CONFIG_MMC_SDRICOH_CS is not set CONFIG_MMC_CB710=m CONFIG_MMC_VIA_SDMMC=m CONFIG_MMC_VUB300=m @@ -4235,7 +4467,7 @@ CONFIG_LEDS_TRIGGER_TIMER=m CONFIG_LEDS_TRIGGER_ONESHOT=m CONFIG_LEDS_TRIGGER_HEARTBEAT=m CONFIG_LEDS_TRIGGER_BACKLIGHT=m -# CONFIG_LEDS_TRIGGER_CPU is not set +CONFIG_LEDS_TRIGGER_CPU=y CONFIG_LEDS_TRIGGER_GPIO=m CONFIG_LEDS_TRIGGER_DEFAULT_ON=m @@ -4244,6 +4476,7 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=m # CONFIG_LEDS_TRIGGER_TRANSIENT=m CONFIG_LEDS_TRIGGER_CAMERA=m +CONFIG_LEDS_TRIGGER_NETDEV=m # CONFIG_ACCESSIBILITY is not set # CONFIG_INFINIBAND is not set CONFIG_EDAC=y @@ -4503,6 +4736,8 @@ CONFIG_RTLLIB_CRYPTO_WEP=m # CONFIG_IIO_SYSFS_TRIGGER is not set # CONFIG_IIO_SIMPLE_DUMMY is not set # CONFIG_ZSMALLOC is not set +# CONFIG_WLAGS49_H2 is not set +# CONFIG_WLAGS49_H25 is not set # CONFIG_FB_SM7XX is not set # CONFIG_CRYSTALHD is not set # CONFIG_FB_XGI is not set @@ -5211,7 +5446,7 @@ CONFIG_GRKERNSEC_FIFO=y # CONFIG_GRKERNSEC_ROFS is not set CONFIG_GRKERNSEC_DEVICE_SIDECHANNEL=y CONFIG_GRKERNSEC_CHROOT=y -CONFIG_GRKERNSEC_CHROOT_MOUNT=y +# CONFIG_GRKERNSEC_CHROOT_MOUNT is not set CONFIG_GRKERNSEC_CHROOT_DOUBLE=y CONFIG_GRKERNSEC_CHROOT_PIVOT=y CONFIG_GRKERNSEC_CHROOT_CHDIR=y @@ -5259,6 +5494,11 @@ CONFIG_GRKERNSEC_BLACKHOLE=y CONFIG_GRKERNSEC_NO_SIMULT_CONNECT=y # CONFIG_GRKERNSEC_SOCKET is not set +# +# Physical Protections +# +# CONFIG_GRKERNSEC_DENYUSB is not set + # # Sysctl Support # diff --git a/lfs/linux b/lfs/linux index 2ca7696cc..567d01131 100644 --- a/lfs/linux +++ b/lfs/linux @@ -24,7 +24,7 @@ include Config -VER = 3.10.9 +VER = 3.10.10 RPI_PATCHES = linux-3.2.27-ada8b44 @@ -71,7 +71,7 @@ objects =$(DL_FILE) \ $(DL_FILE) = $(URL_IPFIRE)/$(DL_FILE) rpi-patches-$(RPI_PATCHES).patch.xz = $(URL_IPFIRE)/rpi-patches-$(RPI_PATCHES).patch.xz -$(DL_FILE)_MD5 = 28d1e1117c30fdd861f70ac0f9b677aa +$(DL_FILE)_MD5 = 647f76225dd6bc112369ba573ba3de18 rpi-patches-$(RPI_PATCHES).patch.xz_MD5 = 966687ff27e450e04ff50e0da829dc00 @@ -119,7 +119,7 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) # Grsecurity-patches ifneq "$(KCFG)" "-headers" - cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grsecurity-2.9.1-3.10.9-201308202015.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/grsecurity-2.9.1-3.10.10-201308292131.patch cd $(DIR_APP) && rm localversion-grsec cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.7-disable-compat_vdso.patch endif @@ -130,8 +130,12 @@ endif # Remove ACPI Blacklist message cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-2.6-silence-acpi-blacklist.patch + # DVB Patches + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.9-dvbsky-wot2.patch + cd $(DIR_APP) && patch -Np2 < $(DIR_SRC)/src/patches/v4l-dvb_fix_tua6034_pll.patch + # Add LED trigger -# cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.2.33-ledtrig-netdev-1.patch + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.10.9-ledtrig-netdev-1.patch # Fix uevent PHYSDEVDRIVER cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux-3.2.33_ipg-fix-driver-name.patch diff --git a/src/patches/grsecurity-2.9.1-3.10.9-201308202015.patch b/src/patches/grsecurity-2.9.1-3.10.10-201308292131.patch similarity index 98% rename from src/patches/grsecurity-2.9.1-3.10.9-201308202015.patch rename to src/patches/grsecurity-2.9.1-3.10.10-201308292131.patch index 24d81a08c..ec95bfd86 100644 --- a/src/patches/grsecurity-2.9.1-3.10.9-201308202015.patch +++ b/src/patches/grsecurity-2.9.1-3.10.10-201308292131.patch @@ -281,7 +281,7 @@ index 2fe6e76..889ee23 100644 pcd. [PARIDE] diff --git a/Makefile b/Makefile -index 4b31d62..ac99d49 100644 +index b119684..13ac256 100644 --- a/Makefile +++ b/Makefile @@ -241,8 +241,9 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ @@ -1968,7 +1968,7 @@ index 86b8fe3..e25f975 100644 #define L_PTE_DIRTY_HIGH (1 << (55 - 32)) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h -index 9bcd262..fba731c 100644 +index 9bcd262..1ff999b 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -30,6 +30,9 @@ @@ -1991,20 +1991,18 @@ index 9bcd262..fba731c 100644 extern void __pte_error(const char *file, int line, pte_t); extern void __pmd_error(const char *file, int line, pmd_t); extern void __pgd_error(const char *file, int line, pgd_t); -@@ -53,6 +59,50 @@ extern void __pgd_error(const char *file, int line, pgd_t); +@@ -53,6 +59,48 @@ extern void __pgd_error(const char *file, int line, pgd_t); #define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd) #define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd) +#define __HAVE_ARCH_PAX_OPEN_KERNEL +#define __HAVE_ARCH_PAX_CLOSE_KERNEL + -+#ifdef CONFIG_PAX_KERNEXEC ++#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) +#include +#include +#include -+#endif + -+#if defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) +static inline int test_domain(int domain, int domaintype) +{ + return ((current_thread_info()->cpu_domain) & domain_val(domain, 3)) == domain_val(domain, domaintype); @@ -2042,7 +2040,7 @@ index 9bcd262..fba731c 100644 /* * This is the lowest virtual address we can permit any user space * mapping to be mapped at. This is particularly important for -@@ -72,8 +122,8 @@ extern void __pgd_error(const char *file, int line, pgd_t); +@@ -72,8 +120,8 @@ extern void __pgd_error(const char *file, int line, pgd_t); /* * The pgprot_* and protection_map entries will be fixed up in runtime * to include the cachable and bufferable bits based on memory policy, @@ -2053,7 +2051,7 @@ index 9bcd262..fba731c 100644 */ #define _L_PTE_DEFAULT L_PTE_PRESENT | L_PTE_YOUNG -@@ -257,7 +307,7 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; } +@@ -257,7 +305,7 @@ static inline pte_t pte_mkspecial(pte_t pte) { return pte; } static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) { const pteval_t mask = L_PTE_XN | L_PTE_RDONLY | L_PTE_USER | @@ -3634,7 +3632,7 @@ index cad3ca86..1d79e0f 100644 extern void ux500_cpu_die(unsigned int cpu); diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig -index 2950082..d0f0782 100644 +index 08c9fe9..191320c 100644 --- a/arch/arm/mm/Kconfig +++ b/arch/arm/mm/Kconfig @@ -436,7 +436,7 @@ config CPU_32v5 @@ -3662,8 +3660,8 @@ index 2950082..d0f0782 100644 help Warning: disabling this option may break user programs. -@@ -790,7 +792,7 @@ config KUSER_HELPERS - run on ARMv4 through to ARMv7 without modification. +@@ -792,7 +794,7 @@ config KUSER_HELPERS + See Documentation/arm/kernel_user_helpers.txt for details. However, the fixed address nature of these helpers can be used - by ROP (return orientated programming) authors when creating @@ -3737,7 +3735,7 @@ index 6f4585b..7b6f52b 100644 goto fault; \ } while (0) diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c -index 5dbf13f..ee1ec24 100644 +index 5dbf13f..a2d1876 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c @@ -25,6 +25,7 @@ @@ -3840,7 +3838,7 @@ index 5dbf13f..ee1ec24 100644 printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n", inf->name, fsr, addr); -@@ -569,15 +631,67 @@ hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs * +@@ -569,15 +631,68 @@ hook_ifault_code(int nr, int (*fn)(unsigned long, unsigned int, struct pt_regs * ifsr_info[nr].name = name; } @@ -3852,18 +3850,19 @@ index 5dbf13f..ee1ec24 100644 { const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr); struct siginfo info; - ++ unsigned long pc = instruction_pointer(regs); ++ + if (user_mode(regs)) { + unsigned long sigpage = current->mm->context.sigpage; + -+ if (sigpage <= addr && addr < sigpage + 7*4) { -+ if (addr < sigpage + 3*4) ++ if (sigpage <= pc && pc < sigpage + 7*4) { ++ if (pc < sigpage + 3*4) + sys_sigreturn(regs); + else + sys_rt_sigreturn(regs); + return; + } -+ if (addr == 0xffff0fe0UL) { ++ if (pc == 0xffff0fe0UL) { + /* + * PaX: __kuser_get_tls emulation + */ @@ -3878,11 +3877,11 @@ index 5dbf13f..ee1ec24 100644 + if (current->signal->curr_ip) + printk(KERN_ERR "PAX: From %pI4: %s:%d, uid/euid: %u/%u, attempted to execute %s memory at %08lx\n", ¤t->signal->curr_ip, current->comm, task_pid_nr(current), + from_kuid_munged(&init_user_ns, current_uid()), from_kuid_munged(&init_user_ns, current_euid()), -+ addr >= TASK_SIZE ? "non-executable kernel" : "userland", addr); ++ pc >= TASK_SIZE ? "non-executable kernel" : "userland", pc); + else + printk(KERN_ERR "PAX: %s:%d, uid/euid: %u/%u, attempted to execute %s memory at %08lx\n", current->comm, task_pid_nr(current), + from_kuid_munged(&init_user_ns, current_uid()), from_kuid_munged(&init_user_ns, current_euid()), -+ addr >= TASK_SIZE ? "non-executable kernel" : "userland", addr); ++ pc >= TASK_SIZE ? "non-executable kernel" : "userland", pc); + goto die; + } +#endif @@ -3891,7 +3890,7 @@ index 5dbf13f..ee1ec24 100644 + if (fsr_fs(ifsr) == FAULT_CODE_DEBUG) { + unsigned int bkpt; + -+ if (!probe_kernel_address((unsigned int *)addr, bkpt) && bkpt == 0xe12f1073) { ++ if (!probe_kernel_address((unsigned int *)pc, bkpt) && cpu_to_le32(bkpt) == 0xe12f1073) { + current->thread.error_code = ifsr; + current->thread.trap_no = 0; + pax_report_refcount_overflow(regs); @@ -3900,7 +3899,7 @@ index 5dbf13f..ee1ec24 100644 + } + } +#endif -+ + if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs)) return; @@ -5347,10 +5346,10 @@ index 4efe96a..60e8699 100644 #define SMP_CACHE_BYTES L1_CACHE_BYTES diff --git a/arch/mips/include/asm/atomic.h b/arch/mips/include/asm/atomic.h -index 08b6079..eb272cf 100644 +index 08b6079..e94e6da 100644 --- a/arch/mips/include/asm/atomic.h +++ b/arch/mips/include/asm/atomic.h -@@ -21,6 +21,10 @@ +@@ -21,15 +21,39 @@ #include #include @@ -5360,24 +5359,887 @@ index 08b6079..eb272cf 100644 + #define ATOMIC_INIT(i) { (i) } ++#ifdef CONFIG_64BIT ++#define _ASM_EXTABLE(from, to) \ ++" .section __ex_table,\"a\"\n" \ ++" .dword " #from ", " #to"\n" \ ++" .previous\n" ++#else ++#define _ASM_EXTABLE(from, to) \ ++" .section __ex_table,\"a\"\n" \ ++" .word " #from ", " #to"\n" \ ++" .previous\n" ++#endif ++ /* -@@ -759,6 +763,16 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) + * atomic_read - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. */ - #define atomic64_add_negative(i, v) (atomic64_add_return(i, (v)) < 0) +-#define atomic_read(v) (*(volatile int *)&(v)->counter) ++static inline int atomic_read(const atomic_t *v) ++{ ++ return (*(volatile const int *) &v->counter); ++} ++ ++static inline int atomic_read_unchecked(const atomic_unchecked_t *v) ++{ ++ return (*(volatile const int *) &v->counter); ++} -+#define atomic64_read_unchecked(v) atomic64_read(v) -+#define atomic64_set_unchecked(v, i) atomic64_set((v), (i)) -+#define atomic64_add_unchecked(a, v) atomic64_add((a), (v)) -+#define atomic64_add_return_unchecked(a, v) atomic64_add_return((a), (v)) -+#define atomic64_sub_unchecked(a, v) atomic64_sub((a), (v)) -+#define atomic64_inc_unchecked(v) atomic64_inc(v) -+#define atomic64_inc_return_unchecked(v) atomic64_inc_return(v) -+#define atomic64_dec_unchecked(v) atomic64_dec(v) -+#define atomic64_cmpxchg_unchecked(v, o, n) atomic64_cmpxchg((v), (o), (n)) + /* + * atomic_set - set atomic variable +@@ -38,7 +62,15 @@ + * + * Atomically sets the value of @v to @i. + */ +-#define atomic_set(v, i) ((v)->counter = (i)) ++static inline void atomic_set(atomic_t *v, int i) ++{ ++ v->counter = i; ++} + - #endif /* CONFIG_64BIT */ ++static inline void atomic_set_unchecked(atomic_unchecked_t *v, int i) ++{ ++ v->counter = i; ++} + + /* + * atomic_add - add integer to atomic variable +@@ -47,7 +79,67 @@ + * + * Atomically adds @i to @v. + */ +-static __inline__ void atomic_add(int i, atomic_t * v) ++static __inline__ void atomic_add(int i, atomic_t *v) ++{ ++ int temp; ++ ++ if (kernel_uses_llsc && R10000_LLSC_WAR) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: ll %0, %1 # atomic_add \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "2: add %0, %2 \n" ++#else ++ " addu %0, %2 \n" ++#endif ++ " sc %0, %1 \n" ++ " beqzl %0, 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "3: \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ " .set mips0 \n" ++ : "=&r" (temp), "+m" (v->counter) ++ : "Ir" (i)); ++ } else if (kernel_uses_llsc) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: ll %0, %1 # atomic_add \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "2: add %0, %2 \n" ++#else ++ " addu %0, %2 \n" ++#endif ++ " sc %0, %1 \n" ++ " beqz %0, 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "3: \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ " .set mips0 \n" ++ : "=&r" (temp), "+m" (v->counter) ++ : "Ir" (i)); ++ } else { ++ unsigned long flags; ++ ++ raw_local_irq_save(flags); ++ __asm__ __volatile__( ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "1: add %0, %1 \n" ++ "2: \n" ++ _ASM_EXTABLE(1b, 2b) ++#else ++ " addu %0, %1 \n" ++#endif ++ : "+r" (v->counter) : "Ir" (i)); ++ raw_local_irq_restore(flags); ++ } ++} ++ ++static __inline__ void atomic_add_unchecked(int i, atomic_unchecked_t *v) + { + if (kernel_uses_llsc && R10000_LLSC_WAR) { + int temp; +@@ -90,7 +182,67 @@ static __inline__ void atomic_add(int i, atomic_t * v) + * + * Atomically subtracts @i from @v. + */ +-static __inline__ void atomic_sub(int i, atomic_t * v) ++static __inline__ void atomic_sub(int i, atomic_t *v) ++{ ++ int temp; ++ ++ if (kernel_uses_llsc && R10000_LLSC_WAR) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: ll %0, %1 # atomic64_sub \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "2: sub %0, %2 \n" ++#else ++ " subu %0, %2 \n" ++#endif ++ " sc %0, %1 \n" ++ " beqzl %0, 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "3: \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ " .set mips0 \n" ++ : "=&r" (temp), "+m" (v->counter) ++ : "Ir" (i)); ++ } else if (kernel_uses_llsc) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: ll %0, %1 # atomic64_sub \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "2: sub %0, %2 \n" ++#else ++ " subu %0, %2 \n" ++#endif ++ " sc %0, %1 \n" ++ " beqz %0, 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "3: \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ " .set mips0 \n" ++ : "=&r" (temp), "+m" (v->counter) ++ : "Ir" (i)); ++ } else { ++ unsigned long flags; ++ ++ raw_local_irq_save(flags); ++ __asm__ __volatile__( ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "1: sub %0, %1 \n" ++ "2: \n" ++ _ASM_EXTABLE(1b, 2b) ++#else ++ " subu %0, %1 \n" ++#endif ++ : "+r" (v->counter) : "Ir" (i)); ++ raw_local_irq_restore(flags); ++ } ++} ++ ++static __inline__ void atomic_sub_unchecked(long i, atomic_unchecked_t *v) + { + if (kernel_uses_llsc && R10000_LLSC_WAR) { + int temp; +@@ -129,7 +281,93 @@ static __inline__ void atomic_sub(int i, atomic_t * v) + /* + * Same as above, but return the result value + */ +-static __inline__ int atomic_add_return(int i, atomic_t * v) ++static __inline__ int atomic_add_return(int i, atomic_t *v) ++{ ++ int result; ++ int temp; ++ ++ smp_mb__before_llsc(); ++ ++ if (kernel_uses_llsc && R10000_LLSC_WAR) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: ll %1, %2 # atomic_add_return \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "2: add %0, %1, %3 \n" ++#else ++ " addu %0, %1, %3 \n" ++#endif ++ " sc %0, %2 \n" ++ " beqzl %0, 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ " b 4f \n" ++ " .set noreorder \n" ++ "3: b 5f \n" ++ " move %0, %1 \n" ++ " .set reorder \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ "4: addu %0, %1, %3 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "5: \n" ++#endif ++ " .set mips0 \n" ++ : "=&r" (result), "=&r" (temp), "+m" (v->counter) ++ : "Ir" (i)); ++ } else if (kernel_uses_llsc) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: ll %1, %2 # atomic_add_return \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "2: add %0, %1, %3 \n" ++#else ++ " addu %0, %1, %3 \n" ++#endif ++ " sc %0, %2 \n" ++ " bnez %0, 4f \n" ++ " b 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ " .set noreorder \n" ++ "3: b 5f \n" ++ " move %0, %1 \n" ++ " .set reorder \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ "4: addu %0, %1, %3 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "5: \n" ++#endif ++ " .set mips0 \n" ++ : "=&r" (result), "=&r" (temp), "+m" (v->counter) ++ : "Ir" (i)); ++ } else { ++ unsigned long flags; ++ ++ raw_local_irq_save(flags); ++ __asm__ __volatile__( ++ " lw %0, %1 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "1: add %0, %2 \n" ++#else ++ " addu %0, %2 \n" ++#endif ++ " sw %0, %1 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Note: Dest reg is not modified on overflow */ ++ "2: \n" ++ _ASM_EXTABLE(1b, 2b) ++#endif ++ : "=&r" (result), "+m" (v->counter) : "Ir" (i)); ++ raw_local_irq_restore(flags); ++ } ++ ++ smp_llsc_mb(); ++ ++ return result; ++} ++ ++static __inline__ int atomic_add_return_unchecked(int i, atomic_unchecked_t *v) + { + int result; + +@@ -178,7 +416,93 @@ static __inline__ int atomic_add_return(int i, atomic_t * v) + return result; + } + +-static __inline__ int atomic_sub_return(int i, atomic_t * v) ++static __inline__ int atomic_sub_return(int i, atomic_t *v) ++{ ++ int result; ++ int temp; ++ ++ smp_mb__before_llsc(); ++ ++ if (kernel_uses_llsc && R10000_LLSC_WAR) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: ll %1, %2 # atomic_sub_return \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "2: sub %0, %1, %3 \n" ++#else ++ " subu %0, %1, %3 \n" ++#endif ++ " sc %0, %2 \n" ++ " beqzl %0, 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ " b 4f \n" ++ " .set noreorder \n" ++ "3: b 5f \n" ++ " move %0, %1 \n" ++ " .set reorder \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ "4: subu %0, %1, %3 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "5: \n" ++#endif ++ " .set mips0 \n" ++ : "=&r" (result), "=&r" (temp), "=m" (v->counter) ++ : "Ir" (i), "m" (v->counter) ++ : "memory"); ++ } else if (kernel_uses_llsc) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: ll %1, %2 # atomic_sub_return \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "2: sub %0, %1, %3 \n" ++#else ++ " subu %0, %1, %3 \n" ++#endif ++ " sc %0, %2 \n" ++ " bnez %0, 4f \n" ++ " b 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ " .set noreorder \n" ++ "3: b 5f \n" ++ " move %0, %1 \n" ++ " .set reorder \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ "4: subu %0, %1, %3 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "5: \n" ++#endif ++ " .set mips0 \n" ++ : "=&r" (result), "=&r" (temp), "+m" (v->counter) ++ : "Ir" (i)); ++ } else { ++ unsigned long flags; ++ ++ raw_local_irq_save(flags); ++ __asm__ __volatile__( ++ " lw %0, %1 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "1: sub %0, %2 \n" ++#else ++ " subu %0, %2 \n" ++#endif ++ " sw %0, %1 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Note: Dest reg is not modified on overflow */ ++ "2: \n" ++ _ASM_EXTABLE(1b, 2b) ++#endif ++ : "=&r" (result), "+m" (v->counter) : "Ir" (i)); ++ raw_local_irq_restore(flags); ++ } ++ ++ smp_llsc_mb(); ++ ++ return result; ++} ++static __inline__ int atomic_sub_return_unchecked(int i, atomic_unchecked_t *v) + { + int result; + +@@ -238,7 +562,7 @@ static __inline__ int atomic_sub_return(int i, atomic_t * v) + * Atomically test @v and subtract @i if @v is greater or equal than @i. + * The function returns the old value of @v minus @i. + */ +-static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) ++static __inline__ int atomic_sub_if_positive(int i, atomic_t *v) + { + int result; + +@@ -295,8 +619,26 @@ static __inline__ int atomic_sub_if_positive(int i, atomic_t * v) + return result; + } + +-#define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n))) +-#define atomic_xchg(v, new) (xchg(&((v)->counter), (new))) ++static inline int atomic_cmpxchg(atomic_t *v, int old, int new) ++{ ++ return cmpxchg(&v->counter, old, new); ++} ++ ++static inline int atomic_cmpxchg_unchecked(atomic_unchecked_t *v, int old, ++ int new) ++{ ++ return cmpxchg(&(v->counter), old, new); ++} ++ ++static inline int atomic_xchg(atomic_t *v, int new) ++{ ++ return xchg(&v->counter, new); ++} ++ ++static inline int atomic_xchg_unchecked(atomic_unchecked_t *v, int new) ++{ ++ return xchg(&(v->counter), new); ++} + + /** + * __atomic_add_unless - add unless the number is a given value +@@ -324,6 +666,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) + + #define atomic_dec_return(v) atomic_sub_return(1, (v)) + #define atomic_inc_return(v) atomic_add_return(1, (v)) ++#define atomic_inc_return_unchecked(v) atomic_add_return_unchecked(1, (v)) + + /* + * atomic_sub_and_test - subtract value from variable and test result +@@ -345,6 +688,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) + * other cases. + */ + #define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) ++#define atomic_inc_and_test_unchecked(v) (atomic_add_return_unchecked(1, (v)) == 0) + + /* + * atomic_dec_and_test - decrement by 1 and test +@@ -369,6 +713,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) + * Atomically increments @v by 1. + */ + #define atomic_inc(v) atomic_add(1, (v)) ++#define atomic_inc_unchecked(v) atomic_add_unchecked(1, (v)) + + /* + * atomic_dec - decrement and test +@@ -377,6 +722,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) + * Atomically decrements @v by 1. + */ + #define atomic_dec(v) atomic_sub(1, (v)) ++#define atomic_dec_unchecked(v) atomic_sub_return_unchecked(1, (v)) + + /* + * atomic_add_negative - add and test if negative +@@ -398,14 +744,30 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) + * @v: pointer of type atomic64_t + * + */ +-#define atomic64_read(v) (*(volatile long *)&(v)->counter) ++static inline long atomic64_read(const atomic64_t *v) ++{ ++ return (*(volatile const long *) &v->counter); ++} ++ ++static inline long atomic64_read_unchecked(const atomic64_unchecked_t *v) ++{ ++ return (*(volatile const long *) &v->counter); ++} + + /* + * atomic64_set - set atomic variable + * @v: pointer of type atomic64_t + * @i: required value + */ +-#define atomic64_set(v, i) ((v)->counter = (i)) ++static inline void atomic64_set(atomic64_t *v, long i) ++{ ++ v->counter = i; ++} ++ ++static inline void atomic64_set_unchecked(atomic64_unchecked_t *v, long i) ++{ ++ v->counter = i; ++} + + /* + * atomic64_add - add integer to atomic variable +@@ -414,7 +776,66 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) + * + * Atomically adds @i to @v. + */ +-static __inline__ void atomic64_add(long i, atomic64_t * v) ++static __inline__ void atomic64_add(long i, atomic64_t *v) ++{ ++ long temp; ++ ++ if (kernel_uses_llsc && R10000_LLSC_WAR) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: lld %0, %1 # atomic64_add \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "2: dadd %0, %2 \n" ++#else ++ " daddu %0, %2 \n" ++#endif ++ " scd %0, %1 \n" ++ " beqzl %0, 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "3: \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ " .set mips0 \n" ++ : "=&r" (temp), "+m" (v->counter) ++ : "Ir" (i)); ++ } else if (kernel_uses_llsc) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: lld %0, %1 # atomic64_add \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "2: dadd %0, %2 \n" ++#else ++ " daddu %0, %2 \n" ++#endif ++ " scd %0, %1 \n" ++ " beqz %0, 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "3: \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ " .set mips0 \n" ++ : "=&r" (temp), "+m" (v->counter) ++ : "Ir" (i)); ++ } else { ++ unsigned long flags; ++ ++ raw_local_irq_save(flags); ++ __asm__ __volatile__( ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "1: dadd %0, %1 \n" ++ "2: \n" ++ _ASM_EXTABLE(1b, 2b) ++#else ++ " daddu %0, %1 \n" ++#endif ++ : "+r" (v->counter) : "Ir" (i)); ++ raw_local_irq_restore(flags); ++ } ++} ++static __inline__ void atomic64_add_unchecked(long i, atomic64_unchecked_t *v) + { + if (kernel_uses_llsc && R10000_LLSC_WAR) { + long temp; +@@ -457,7 +878,67 @@ static __inline__ void atomic64_add(long i, atomic64_t * v) + * + * Atomically subtracts @i from @v. + */ +-static __inline__ void atomic64_sub(long i, atomic64_t * v) ++static __inline__ void atomic64_sub(long i, atomic64_t *v) ++{ ++ long temp; ++ ++ if (kernel_uses_llsc && R10000_LLSC_WAR) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: lld %0, %1 # atomic64_sub \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "2: dsub %0, %2 \n" ++#else ++ " dsubu %0, %2 \n" ++#endif ++ " scd %0, %1 \n" ++ " beqzl %0, 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "3: \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ " .set mips0 \n" ++ : "=&r" (temp), "+m" (v->counter) ++ : "Ir" (i)); ++ } else if (kernel_uses_llsc) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: lld %0, %1 # atomic64_sub \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "2: dsub %0, %2 \n" ++#else ++ " dsubu %0, %2 \n" ++#endif ++ " scd %0, %1 \n" ++ " beqz %0, 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "3: \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ " .set mips0 \n" ++ : "=&r" (temp), "+m" (v->counter) ++ : "Ir" (i)); ++ } else { ++ unsigned long flags; ++ ++ raw_local_irq_save(flags); ++ __asm__ __volatile__( ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "1: dsub %0, %1 \n" ++ "2: \n" ++ _ASM_EXTABLE(1b, 2b) ++#else ++ " dsubu %0, %1 \n" ++#endif ++ : "+r" (v->counter) : "Ir" (i)); ++ raw_local_irq_restore(flags); ++ } ++} ++ ++static __inline__ void atomic64_sub_unchecked(long i, atomic64_unchecked_t *v) + { + if (kernel_uses_llsc && R10000_LLSC_WAR) { + long temp; +@@ -496,7 +977,93 @@ static __inline__ void atomic64_sub(long i, atomic64_t * v) + /* + * Same as above, but return the result value + */ +-static __inline__ long atomic64_add_return(long i, atomic64_t * v) ++static __inline__ long atomic64_add_return(long i, atomic64_t *v) ++{ ++ long result; ++ long temp; ++ ++ smp_mb__before_llsc(); ++ ++ if (kernel_uses_llsc && R10000_LLSC_WAR) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: lld %1, %2 # atomic64_add_return \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "2: dadd %0, %1, %3 \n" ++#else ++ " daddu %0, %1, %3 \n" ++#endif ++ " scd %0, %2 \n" ++ " beqzl %0, 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ " b 4f \n" ++ " .set noreorder \n" ++ "3: b 5f \n" ++ " move %0, %1 \n" ++ " .set reorder \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ "4: daddu %0, %1, %3 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "5: \n" ++#endif ++ " .set mips0 \n" ++ : "=&r" (result), "=&r" (temp), "+m" (v->counter) ++ : "Ir" (i)); ++ } else if (kernel_uses_llsc) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: lld %1, %2 # atomic64_add_return \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "2: dadd %0, %1, %3 \n" ++#else ++ " daddu %0, %1, %3 \n" ++#endif ++ " scd %0, %2 \n" ++ " bnez %0, 4f \n" ++ " b 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ " .set noreorder \n" ++ "3: b 5f \n" ++ " move %0, %1 \n" ++ " .set reorder \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ "4: daddu %0, %1, %3 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "5: \n" ++#endif ++ " .set mips0 \n" ++ : "=&r" (result), "=&r" (temp), "=m" (v->counter) ++ : "Ir" (i), "m" (v->counter) ++ : "memory"); ++ } else { ++ unsigned long flags; ++ ++ raw_local_irq_save(flags); ++ __asm__ __volatile__( ++ " ld %0, %1 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "1: dadd %0, %2 \n" ++#else ++ " daddu %0, %2 \n" ++#endif ++ " sd %0, %1 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Note: Dest reg is not modified on overflow */ ++ "2: \n" ++ _ASM_EXTABLE(1b, 2b) ++#endif ++ : "=&r" (result), "+m" (v->counter) : "Ir" (i)); ++ raw_local_irq_restore(flags); ++ } ++ ++ smp_llsc_mb(); ++ ++ return result; ++} ++static __inline__ long atomic64_add_return_unchecked(long i, atomic64_unchecked_t *v) + { + long result; + +@@ -546,7 +1113,97 @@ static __inline__ long atomic64_add_return(long i, atomic64_t * v) + return result; + } + +-static __inline__ long atomic64_sub_return(long i, atomic64_t * v) ++static __inline__ long atomic64_sub_return(long i, atomic64_t *v) ++{ ++ long result; ++ long temp; ++ ++ smp_mb__before_llsc(); ++ ++ if (kernel_uses_llsc && R10000_LLSC_WAR) { ++ long temp; ++ ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: lld %1, %2 # atomic64_sub_return \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "2: dsub %0, %1, %3 \n" ++#else ++ " dsubu %0, %1, %3 \n" ++#endif ++ " scd %0, %2 \n" ++ " beqzl %0, 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ " b 4f \n" ++ " .set noreorder \n" ++ "3: b 5f \n" ++ " move %0, %1 \n" ++ " .set reorder \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ "4: dsubu %0, %1, %3 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "5: \n" ++#endif ++ " .set mips0 \n" ++ : "=&r" (result), "=&r" (temp), "=m" (v->counter) ++ : "Ir" (i), "m" (v->counter) ++ : "memory"); ++ } else if (kernel_uses_llsc) { ++ __asm__ __volatile__( ++ " .set mips3 \n" ++ "1: lld %1, %2 # atomic64_sub_return \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "2: dsub %0, %1, %3 \n" ++#else ++ " dsubu %0, %1, %3 \n" ++#endif ++ " scd %0, %2 \n" ++ " bnez %0, 4f \n" ++ " b 1b \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ " .set noreorder \n" ++ "3: b 5f \n" ++ " move %0, %1 \n" ++ " .set reorder \n" ++ _ASM_EXTABLE(2b, 3b) ++#endif ++ "4: dsubu %0, %1, %3 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ "5: \n" ++#endif ++ " .set mips0 \n" ++ : "=&r" (result), "=&r" (temp), "=m" (v->counter) ++ : "Ir" (i), "m" (v->counter) ++ : "memory"); ++ } else { ++ unsigned long flags; ++ ++ raw_local_irq_save(flags); ++ __asm__ __volatile__( ++ " ld %0, %1 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Exception on overflow. */ ++ "1: dsub %0, %2 \n" ++#else ++ " dsubu %0, %2 \n" ++#endif ++ " sd %0, %1 \n" ++#ifdef CONFIG_PAX_REFCOUNT ++ /* Note: Dest reg is not modified on overflow */ ++ "2: \n" ++ _ASM_EXTABLE(1b, 2b) ++#endif ++ : "=&r" (result), "+m" (v->counter) : "Ir" (i)); ++ raw_local_irq_restore(flags); ++ } ++ ++ smp_llsc_mb(); ++ ++ return result; ++} ++ ++static __inline__ long atomic64_sub_return_unchecked(long i, atomic64_unchecked_t *v) + { + long result; + +@@ -605,7 +1262,7 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v) + * Atomically test @v and subtract @i if @v is greater or equal than @i. + * The function returns the old value of @v minus @i. + */ +-static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) ++static __inline__ long atomic64_sub_if_positive(long i, atomic64_t *v) + { + long result; + +@@ -662,9 +1319,26 @@ static __inline__ long atomic64_sub_if_positive(long i, atomic64_t * v) + return result; + } + +-#define atomic64_cmpxchg(v, o, n) \ +- ((__typeof__((v)->counter))cmpxchg(&((v)->counter), (o), (n))) +-#define atomic64_xchg(v, new) (xchg(&((v)->counter), (new))) ++static inline long atomic64_cmpxchg(atomic64_t *v, long old, long new) ++{ ++ return cmpxchg(&v->counter, old, new); ++} ++ ++static inline long atomic64_cmpxchg_unchecked(atomic64_unchecked_t *v, long old, ++ long new) ++{ ++ return cmpxchg(&(v->counter), old, new); ++} ++ ++static inline long atomic64_xchg(atomic64_t *v, long new) ++{ ++ return xchg(&v->counter, new); ++} ++ ++static inline long atomic64_xchg_unchecked(atomic64_unchecked_t *v, long new) ++{ ++ return xchg(&(v->counter), new); ++} + + /** + * atomic64_add_unless - add unless the number is a given value +@@ -694,6 +1368,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) + + #define atomic64_dec_return(v) atomic64_sub_return(1, (v)) + #define atomic64_inc_return(v) atomic64_add_return(1, (v)) ++#define atomic64_inc_return_unchecked(v) atomic64_add_return_unchecked(1, (v)) + + /* + * atomic64_sub_and_test - subtract value from variable and test result +@@ -715,6 +1390,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) + * other cases. + */ + #define atomic64_inc_and_test(v) (atomic64_inc_return(v) == 0) ++#define atomic64_inc_and_test_unchecked(v) atomic64_add_return_unchecked(1, (v)) == 0) + + /* + * atomic64_dec_and_test - decrement by 1 and test +@@ -739,6 +1415,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) + * Atomically increments @v by 1. + */ + #define atomic64_inc(v) atomic64_add(1, (v)) ++#define atomic64_inc_unchecked(v) atomic64_add_unchecked(1, (v)) + + /* + * atomic64_dec - decrement and test +@@ -747,6 +1424,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) + * Atomically decrements @v by 1. + */ + #define atomic64_dec(v) atomic64_sub(1, (v)) ++#define atomic64_dec_unchecked(v) atomic64_sub_unchecked(1, (v)) /* + * atomic64_add_negative - add and test if negative diff --git a/arch/mips/include/asm/cache.h b/arch/mips/include/asm/cache.h index b4db69f..8f3b093 100644 --- a/arch/mips/include/asm/cache.h @@ -5721,6 +6583,29 @@ index 74f485d..47d2c38 100644 LONG_L t0, TI_FLAGS($28) # syscall tracing enabled? and t0, t1, t0 bnez t0, trace_a_syscall +diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c +index a75ae40..0d0f56a 100644 +--- a/arch/mips/kernel/traps.c ++++ b/arch/mips/kernel/traps.c +@@ -675,7 +675,17 @@ asmlinkage void do_ov(struct pt_regs *regs) + { + siginfo_t info; + +- die_if_kernel("Integer overflow", regs); ++ if (unlikely(!user_mode(regs))) { ++ ++#ifdef CONFIG_PAX_REFCOUNT ++ if (fixup_exception(regs)) { ++ pax_report_refcount_overflow(regs); ++ return; ++ } ++#endif ++ ++ die("Integer overflow", regs); ++ } + + info.si_code = FPE_INTOVF; + info.si_signo = SIGFPE; diff --git a/arch/mips/mm/fault.c b/arch/mips/mm/fault.c index 0fead53..eeb00a6 100644 --- a/arch/mips/mm/fault.c @@ -16806,15 +17691,17 @@ index a1df6e8..e002940 100644 #endif #endif /* _ASM_X86_THREAD_INFO_H */ diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h -index 50a7fc0..7c437a7 100644 +index 50a7fc0..45844c0 100644 --- a/arch/x86/include/asm/tlbflush.h +++ b/arch/x86/include/asm/tlbflush.h -@@ -17,18 +17,40 @@ +@@ -17,18 +17,44 @@ static inline void __native_flush_tlb(void) { + if (static_cpu_has(X86_FEATURE_INVPCID)) { + unsigned long descriptor[2]; ++ ++ descriptor[0] = PCID_KERNEL; + asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_ALL_MONGLOBAL) : "memory"); + return; + } @@ -16838,15 +17725,17 @@ index 50a7fc0..7c437a7 100644 - unsigned long cr4; + if (static_cpu_has(X86_FEATURE_INVPCID)) { + unsigned long descriptor[2]; -+ asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_ALL_GLOBAL) : "memory"); -+ } else { -+ unsigned long cr4; - cr4 = native_read_cr4(); - /* clear PGE */ - native_write_cr4(cr4 & ~X86_CR4_PGE); - /* write old PGE again and flush TLBs */ - native_write_cr4(cr4); ++ descriptor[0] = PCID_KERNEL; ++ asm volatile(__ASM_INVPCID : : "d"(&descriptor), "a"(INVPCID_ALL_GLOBAL) : "memory"); ++ } else { ++ unsigned long cr4; ++ + cr4 = native_read_cr4(); + /* clear PGE */ + native_write_cr4(cr4 & ~X86_CR4_PGE); @@ -16856,7 +17745,7 @@ index 50a7fc0..7c437a7 100644 } static inline void __native_flush_tlb_global(void) -@@ -49,6 +71,42 @@ static inline void __native_flush_tlb_global(void) +@@ -49,6 +75,42 @@ static inline void __native_flush_tlb_global(void) static inline void __native_flush_tlb_single(unsigned long addr) { @@ -17350,7 +18239,7 @@ index 7f760a9..04b1c65 100644 } diff --git a/arch/x86/include/asm/uaccess_64.h b/arch/x86/include/asm/uaccess_64.h -index 142810c..1f2a0a7 100644 +index 142810c..1dbe82f 100644 --- a/arch/x86/include/asm/uaccess_64.h +++ b/arch/x86/include/asm/uaccess_64.h @@ -10,6 +10,9 @@ @@ -17669,8 +18558,9 @@ index 142810c..1f2a0a7 100644 } } - static __must_check __always_inline int +-static __must_check __always_inline int -__copy_from_user_inatomic(void *dst, const void __user *src, unsigned size) ++static __must_check __always_inline unsigned long +__copy_from_user_inatomic(void *dst, const void __user *src, unsigned long size) { - return copy_user_generic(dst, (__force const void *)src, size); @@ -24734,7 +25624,7 @@ index 0000000..5877189 + return arch_get_unmapped_area(filp, addr0, len, pgoff, flags); +} diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c -index 48f8375..ace2781 100644 +index 30277e2..5664a29 100644 --- a/arch/x86/kernel/sys_x86_64.c +++ b/arch/x86/kernel/sys_x86_64.c @@ -81,8 +81,8 @@ out: @@ -24752,8 +25642,8 @@ index 48f8375..ace2781 100644 *begin = new_begin; } } else { -- *begin = mmap_legacy_base(); -+ *begin = mm->mmap_base; +- *begin = current->mm->mmap_legacy_base; ++ *begin = mm->mmap_legacy_base; *end = TASK_SIZE; } } @@ -30568,7 +31458,7 @@ index d87dd6d..bf3fa66 100644 pte = kmemcheck_pte_lookup(address); diff --git a/arch/x86/mm/mmap.c b/arch/x86/mm/mmap.c -index c1af323..4758dad 100644 +index 5c1ae28..45f4ac9 100644 --- a/arch/x86/mm/mmap.c +++ b/arch/x86/mm/mmap.c @@ -52,7 +52,7 @@ static unsigned int stack_maxrandom_size(void) @@ -30608,8 +31498,8 @@ index c1af323..4758dad 100644 * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64 * does, but not when emulating X86_32 */ --unsigned long mmap_legacy_base(void) -+unsigned long mmap_legacy_base(struct mm_struct *mm) +-static unsigned long mmap_legacy_base(void) ++static unsigned long mmap_legacy_base(struct mm_struct *mm) { - if (mmap_is_ia32()) + if (mmap_is_ia32()) { @@ -30626,32 +31516,24 @@ index c1af323..4758dad 100644 return TASK_UNMAPPED_BASE + mmap_rnd(); } -@@ -113,11 +126,23 @@ unsigned long mmap_legacy_base(void) +@@ -112,8 +125,15 @@ static unsigned long mmap_legacy_base(void) + */ void arch_pick_mmap_layout(struct mm_struct *mm) { - if (mmap_is_legacy()) { -- mm->mmap_base = mmap_legacy_base(); -+ mm->mmap_base = mmap_legacy_base(mm); +- mm->mmap_legacy_base = mmap_legacy_base(); +- mm->mmap_base = mmap_base(); ++ mm->mmap_legacy_base = mmap_legacy_base(mm); ++ mm->mmap_base = mmap_base(mm); + +#ifdef CONFIG_PAX_RANDMMAP -+ if (mm->pax_flags & MF_PAX_RANDMMAP) -+ mm->mmap_base += mm->delta_mmap; -+#endif -+ - mm->get_unmapped_area = arch_get_unmapped_area; - mm->unmap_area = arch_unmap_area; - } else { -- mm->mmap_base = mmap_base(); -+ mm->mmap_base = mmap_base(mm); -+ -+#ifdef CONFIG_PAX_RANDMMAP -+ if (mm->pax_flags & MF_PAX_RANDMMAP) -+ mm->mmap_base -= mm->delta_mmap + mm->delta_stack; ++ if (mm->pax_flags & MF_PAX_RANDMMAP) { ++ mm->mmap_legacy_base += mm->delta_mmap; ++ mm->mmap_base -= mm->delta_mmap + mm->delta_stack; ++ } +#endif -+ - mm->get_unmapped_area = arch_get_unmapped_area_topdown; - mm->unmap_area = arch_unmap_area_topdown; - } + + if (mmap_is_legacy()) { + mm->mmap_base = mm->mmap_legacy_base; diff --git a/arch/x86/mm/mmio-mod.c b/arch/x86/mm/mmio-mod.c index dc0b727..f612039 100644 --- a/arch/x86/mm/mmio-mod.c @@ -33284,7 +34166,7 @@ index fdc3ba2..3daee39 100644 .alloc_pud = xen_alloc_pmd_init, .release_pud = xen_release_pmd_init, diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c -index d99cae8..18401e1 100644 +index a1e58e1..9392ad8 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -240,11 +240,6 @@ static void __init xen_smp_prepare_boot_cpu(void) @@ -38535,10 +39417,112 @@ index 8c04943..4370ed9 100644 err = drm_debugfs_create_files(dc->debugfs_files, ARRAY_SIZE(debugfs_files), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c -index 402f486..f862d7e 100644 +index 402f486..5340852 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c -@@ -2275,7 +2275,7 @@ EXPORT_SYMBOL_GPL(hid_ignore); +@@ -63,6 +63,8 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type, + struct hid_report_enum *report_enum = device->report_enum + type; + struct hid_report *report; + ++ if (id >= HID_MAX_IDS) ++ return NULL; + if (report_enum->report_id_hash[id]) + return report_enum->report_id_hash[id]; + +@@ -404,8 +406,10 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) + + case HID_GLOBAL_ITEM_TAG_REPORT_ID: + parser->global.report_id = item_udata(item); +- if (parser->global.report_id == 0) { +- hid_err(parser->device, "report_id 0 is invalid\n"); ++ if (parser->global.report_id == 0 || ++ parser->global.report_id >= HID_MAX_IDS) { ++ hid_err(parser->device, "report_id %u is invalid\n", ++ parser->global.report_id); + return -1; + } + return 0; +@@ -575,7 +579,7 @@ static void hid_close_report(struct hid_device *device) + for (i = 0; i < HID_REPORT_TYPES; i++) { + struct hid_report_enum *report_enum = device->report_enum + i; + +- for (j = 0; j < 256; j++) { ++ for (j = 0; j < HID_MAX_IDS; j++) { + struct hid_report *report = report_enum->report_id_hash[j]; + if (report) + hid_free_report(report); +@@ -755,6 +759,56 @@ int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size) + } + EXPORT_SYMBOL_GPL(hid_parse_report); + ++static const char * const hid_report_names[] = { ++ "HID_INPUT_REPORT", ++ "HID_OUTPUT_REPORT", ++ "HID_FEATURE_REPORT", ++}; ++/** ++ * hid_validate_report - validate existing device report ++ * ++ * @device: hid device ++ * @type: which report type to examine ++ * @id: which report ID to examine (0 for first) ++ * @fields: expected number of fields ++ * @report_counts: expected number of values per field ++ * ++ * Validate the report details after parsing. ++ */ ++struct hid_report *hid_validate_report(struct hid_device *hid, ++ unsigned int type, unsigned int id, ++ unsigned int fields, ++ unsigned int report_counts) ++{ ++ struct hid_report *report; ++ unsigned int i; ++ ++ if (type > HID_FEATURE_REPORT) { ++ hid_err(hid, "invalid HID report %u\n", type); ++ return NULL; ++ } ++ ++ report = hid->report_enum[type].report_id_hash[id]; ++ if (!report) { ++ hid_err(hid, "missing %s %u\n", hid_report_names[type], id); ++ return NULL; ++ } ++ if (report->maxfield < fields) { ++ hid_err(hid, "not enough fields in %s %u\n", ++ hid_report_names[type], id); ++ return NULL; ++ } ++ for (i = 0; i < fields; i++) { ++ if (report->field[i]->report_count < report_counts) { ++ hid_err(hid, "not enough values in %s %u fields\n", ++ hid_report_names[type], id); ++ return NULL; ++ } ++ } ++ return report; ++} ++EXPORT_SYMBOL_GPL(hid_validate_report); ++ + /** + * hid_open_report - open a driver-specific device report + * +@@ -1152,7 +1206,12 @@ EXPORT_SYMBOL_GPL(hid_output_report); + + int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) + { +- unsigned size = field->report_size; ++ unsigned size; ++ ++ if (!field) ++ return -1; ++ ++ size = field->report_size; + + hid_dump_input(field->report->device, field->usage + offset, value); + +@@ -2275,7 +2334,7 @@ EXPORT_SYMBOL_GPL(hid_ignore); int hid_add_device(struct hid_device *hdev) { @@ -38547,7 +39531,7 @@ index 402f486..f862d7e 100644 int ret; if (WARN_ON(hdev->status & HID_STAT_ADDED)) -@@ -2309,7 +2309,7 @@ int hid_add_device(struct hid_device *hdev) +@@ -2309,7 +2368,7 @@ int hid_add_device(struct hid_device *hdev) /* XXX hack, any other cleaner solution after the driver core * is converted to allow more than 20 bytes as the device name? */ dev_set_name(&hdev->dev, "%04X:%04X:%04X.%04X", hdev->bus, @@ -38556,6 +39540,349 @@ index 402f486..f862d7e 100644 hid_debug_register(hdev, dev_name(&hdev->dev)); ret = device_add(&hdev->dev); +diff --git a/drivers/hid/hid-lenovo-tpkbd.c b/drivers/hid/hid-lenovo-tpkbd.c +index 07837f5..b697ada 100644 +--- a/drivers/hid/hid-lenovo-tpkbd.c ++++ b/drivers/hid/hid-lenovo-tpkbd.c +@@ -341,6 +341,11 @@ static int tpkbd_probe_tp(struct hid_device *hdev) + char *name_mute, *name_micmute; + int ret; + ++ /* Validate required reports. */ ++ if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, 4, 4, 1) || ++ !hid_validate_report(hdev, HID_OUTPUT_REPORT, 3, 1, 2)) ++ return -ENODEV; ++ + if (sysfs_create_group(&hdev->dev.kobj, + &tpkbd_attr_group_pointer)) { + hid_warn(hdev, "Could not create sysfs group\n"); +diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c +index b3cd150..9805197 100644 +--- a/drivers/hid/hid-lg2ff.c ++++ b/drivers/hid/hid-lg2ff.c +@@ -64,26 +64,13 @@ int lg2ff_init(struct hid_device *hid) + struct hid_report *report; + struct hid_input *hidinput = list_entry(hid->inputs.next, + struct hid_input, list); +- struct list_head *report_list = +- &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; + int error; + +- if (list_empty(report_list)) { +- hid_err(hid, "no output report found\n"); ++ /* Check that the report looks ok */ ++ report = hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 7); ++ if (!report) + return -ENODEV; +- } +- +- report = list_entry(report_list->next, struct hid_report, list); +- +- if (report->maxfield < 1) { +- hid_err(hid, "output report is empty\n"); +- return -ENODEV; +- } +- if (report->field[0]->report_count < 7) { +- hid_err(hid, "not enough values in the field\n"); +- return -ENODEV; +- } + + lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL); + if (!lg2ff) +diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c +index e52f181..53ac79b 100644 +--- a/drivers/hid/hid-lg3ff.c ++++ b/drivers/hid/hid-lg3ff.c +@@ -66,10 +66,11 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data, + int x, y; + + /* +- * Maxusage should always be 63 (maximum fields) +- * likely a better way to ensure this data is clean ++ * Available values in the field should always be 63, but we only use up to ++ * 35. Instead, clear the entire area, however big it is. + */ +- memset(report->field[0]->value, 0, sizeof(__s32)*report->field[0]->maxusage); ++ memset(report->field[0]->value, 0, ++ sizeof(__s32) * report->field[0]->report_count); + + switch (effect->type) { + case FF_CONSTANT: +@@ -129,32 +130,14 @@ static const signed short ff3_joystick_ac[] = { + int lg3ff_init(struct hid_device *hid) + { + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; +- struct hid_report *report; +- struct hid_field *field; + const signed short *ff_bits = ff3_joystick_ac; + int error; + int i; + +- /* Find the report to use */ +- if (list_empty(report_list)) { +- hid_err(hid, "No output report found\n"); +- return -1; +- } +- + /* Check that the report looks ok */ +- report = list_entry(report_list->next, struct hid_report, list); +- if (!report) { +- hid_err(hid, "NULL output report\n"); +- return -1; +- } +- +- field = report->field[0]; +- if (!field) { +- hid_err(hid, "NULL field\n"); +- return -1; +- } ++ if (!hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 35)) ++ return -ENODEV; + + /* Assume single fixed device G940 */ + for (i = 0; ff_bits[i] >= 0; i++) +diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c +index 0ddae2a..8b89f0f 100644 +--- a/drivers/hid/hid-lg4ff.c ++++ b/drivers/hid/hid-lg4ff.c +@@ -484,34 +484,16 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde + int lg4ff_init(struct hid_device *hid) + { + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; +- struct hid_report *report; +- struct hid_field *field; + struct lg4ff_device_entry *entry; + struct lg_drv_data *drv_data; + struct usb_device_descriptor *udesc; + int error, i, j; + __u16 bcdDevice, rev_maj, rev_min; + +- /* Find the report to use */ +- if (list_empty(report_list)) { +- hid_err(hid, "No output report found\n"); +- return -1; +- } +- + /* Check that the report looks ok */ +- report = list_entry(report_list->next, struct hid_report, list); +- if (!report) { +- hid_err(hid, "NULL output report\n"); ++ if (!hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 7)) + return -1; +- } +- +- field = report->field[0]; +- if (!field) { +- hid_err(hid, "NULL field\n"); +- return -1; +- } + + /* Check what wheel has been connected */ + for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { +diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c +index d7ea8c8..a84fb40 100644 +--- a/drivers/hid/hid-lgff.c ++++ b/drivers/hid/hid-lgff.c +@@ -128,27 +128,14 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude) + int lgff_init(struct hid_device* hid) + { + struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); +- struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; +- struct hid_report *report; +- struct hid_field *field; + const signed short *ff_bits = ff_joystick; + int error; + int i; + +- /* Find the report to use */ +- if (list_empty(report_list)) { +- hid_err(hid, "No output report found\n"); +- return -1; +- } +- + /* Check that the report looks ok */ +- report = list_entry(report_list->next, struct hid_report, list); +- field = report->field[0]; +- if (!field) { +- hid_err(hid, "NULL field\n"); +- return -1; +- } ++ if (!hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 1, 7)) ++ return -ENODEV; + + for (i = 0; i < ARRAY_SIZE(devices); i++) { + if (dev->id.vendor == devices[i].idVendor && +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 5207591a..6c9197f 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -421,7 +421,7 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, + struct hid_report *report; + struct hid_report_enum *output_report_enum; + u8 *data = (u8 *)(&dj_report->device_index); +- int i; ++ unsigned int i, length; + + output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; + report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; +@@ -431,7 +431,9 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, + return -ENODEV; + } + +- for (i = 0; i < report->field[0]->report_count; i++) ++ length = min_t(size_t, sizeof(*dj_report) - 1, ++ report->field[0]->report_count); ++ for (i = 0; i < length; i++) + report->field[0]->value[i] = data[i]; + + hid_hw_request(hdev, report, HID_REQ_SET_REPORT); +@@ -738,6 +740,12 @@ static int logi_dj_probe(struct hid_device *hdev, + goto hid_parse_fail; + } + ++ if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT, ++ 1, 3)) { ++ retval = -ENODEV; ++ goto hid_parse_fail; ++ } ++ + /* Starts the usb device and connects to upper interfaces hiddev and + * hidraw */ + retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT); +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index d39a5ce..4892dfc 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -330,9 +330,18 @@ static void mt_feature_mapping(struct hid_device *hdev, + break; + } + } ++ /* Ignore if value index is out of bounds. */ ++ if (td->inputmode_index < 0 || ++ td->inputmode_index >= field->report_count) { ++ dev_err(&hdev->dev, "HID_DG_INPUTMODE out of range\n"); ++ td->inputmode = -1; ++ } + + break; + case HID_DG_CONTACTMAX: ++ /* Ignore if value count is out of bounds. */ ++ if (field->report_count < 1) ++ break; + td->maxcontact_report_id = field->report->id; + td->maxcontacts = field->value[0]; + if (!td->maxcontacts && +@@ -743,15 +752,21 @@ static void mt_touch_report(struct hid_device *hid, struct hid_report *report) + unsigned count; + int r, n; + ++ if (report->maxfield == 0) ++ return; ++ + /* + * Includes multi-packet support where subsequent + * packets are sent with zero contactcount. + */ +- if (td->cc_index >= 0) { +- struct hid_field *field = report->field[td->cc_index]; +- int value = field->value[td->cc_value_index]; +- if (value) +- td->num_expected = value; ++ if (td->cc_index >= 0 && td->cc_index < report->maxfield) { ++ field = report->field[td->cc_index]; ++ if (td->cc_value_index >= 0 && ++ td->cc_value_index < field->report_count) { ++ int value = field->value[td->cc_value_index]; ++ if (value) ++ td->num_expected = value; ++ } + } + + for (r = 0; r < report->maxfield; r++) { +diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c +index ef95102..5482156 100644 +--- a/drivers/hid/hid-ntrig.c ++++ b/drivers/hid/hid-ntrig.c +@@ -115,7 +115,8 @@ static inline int ntrig_get_mode(struct hid_device *hdev) + struct hid_report *report = hdev->report_enum[HID_FEATURE_REPORT]. + report_id_hash[0x0d]; + +- if (!report) ++ if (!report || report->maxfield < 1 || ++ report->field[0]->report_count < 1) + return -EINVAL; + + hid_hw_request(hdev, report, HID_REQ_GET_REPORT); +diff --git a/drivers/hid/hid-picolcd_core.c b/drivers/hid/hid-picolcd_core.c +index b48092d..72bba1e 100644 +--- a/drivers/hid/hid-picolcd_core.c ++++ b/drivers/hid/hid-picolcd_core.c +@@ -290,7 +290,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev, + buf += 10; + cnt -= 10; + } +- if (!report) ++ if (!report || report->maxfield < 1) + return -EINVAL; + + while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r')) +diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c +index d29112f..2dcd7d9 100644 +--- a/drivers/hid/hid-pl.c ++++ b/drivers/hid/hid-pl.c +@@ -132,8 +132,14 @@ static int plff_init(struct hid_device *hid) + strong = &report->field[0]->value[2]; + weak = &report->field[0]->value[3]; + debug("detected single-field device"); +- } else if (report->maxfield >= 4 && report->field[0]->maxusage == 1 && +- report->field[0]->usage[0].hid == (HID_UP_LED | 0x43)) { ++ } else if (report->field[0]->maxusage == 1 && ++ report->field[0]->usage[0].hid == ++ (HID_UP_LED | 0x43) && ++ report->maxfield >= 4 && ++ report->field[0]->report_count >= 1 && ++ report->field[1]->report_count >= 1 && ++ report->field[2]->report_count >= 1 && ++ report->field[3]->report_count >= 1) { + report->field[0]->value[0] = 0x00; + report->field[1]->value[0] = 0x00; + strong = &report->field[2]->value[0]; +diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c +index ca749810..aa34755 100644 +--- a/drivers/hid/hid-sensor-hub.c ++++ b/drivers/hid/hid-sensor-hub.c +@@ -221,7 +221,8 @@ int sensor_hub_get_feature(struct hid_sensor_hub_device *hsdev, u32 report_id, + + mutex_lock(&data->mutex); + report = sensor_hub_report(report_id, hsdev->hdev, HID_FEATURE_REPORT); +- if (!report || (field_index >= report->maxfield)) { ++ if (!report || (field_index >= report->maxfield) || ++ report->field[field_index]->report_count < 1) { + ret = -EINVAL; + goto done_proc; + } +diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c +index d164911..ef42e86 100644 +--- a/drivers/hid/hid-steelseries.c ++++ b/drivers/hid/hid-steelseries.c +@@ -249,6 +249,11 @@ static int steelseries_srws1_probe(struct hid_device *hdev, + goto err_free; + } + ++ if (!hid_validate_report(hdev, HID_OUTPUT_REPORT, 0, 1, 16)) { ++ ret = -ENODEV; ++ goto err_free; ++ } ++ + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); + if (ret) { + hid_err(hdev, "hw start failed\n"); diff --git a/drivers/hid/hid-wiimote-debug.c b/drivers/hid/hid-wiimote-debug.c index 90124ff..3761764 100644 --- a/drivers/hid/hid-wiimote-debug.c @@ -38569,6 +39896,66 @@ index 90124ff..3761764 100644 return -EFAULT; *off += size; +diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c +index 6ec28a3..b124991 100644 +--- a/drivers/hid/hid-zpff.c ++++ b/drivers/hid/hid-zpff.c +@@ -68,22 +68,12 @@ static int zpff_init(struct hid_device *hid) + struct hid_report *report; + struct hid_input *hidinput = list_entry(hid->inputs.next, + struct hid_input, list); +- struct list_head *report_list = +- &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; + int error; + +- if (list_empty(report_list)) { +- hid_err(hid, "no output report found\n"); ++ report = hid_validate_report(hid, HID_OUTPUT_REPORT, 0, 4, 1); ++ if (!report) + return -ENODEV; +- } +- +- report = list_entry(report_list->next, struct hid_report, list); +- +- if (report->maxfield < 4) { +- hid_err(hid, "not enough fields in report\n"); +- return -ENODEV; +- } + + zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); + if (!zpff) +diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c +index fc307e0..2b255e8 100644 +--- a/drivers/hid/uhid.c ++++ b/drivers/hid/uhid.c +@@ -47,7 +47,7 @@ struct uhid_device { + struct mutex report_lock; + wait_queue_head_t report_wait; + atomic_t report_done; +- atomic_t report_id; ++ atomic_unchecked_t report_id; + struct uhid_event report_buf; + }; + +@@ -187,7 +187,7 @@ static int uhid_hid_get_raw(struct hid_device *hid, unsigned char rnum, + + spin_lock_irqsave(&uhid->qlock, flags); + ev->type = UHID_FEATURE; +- ev->u.feature.id = atomic_inc_return(&uhid->report_id); ++ ev->u.feature.id = atomic_inc_return_unchecked(&uhid->report_id); + ev->u.feature.rnum = rnum; + ev->u.feature.rtype = report_type; + +@@ -471,7 +471,7 @@ static int uhid_dev_feature_answer(struct uhid_device *uhid, + spin_lock_irqsave(&uhid->qlock, flags); + + /* id for old report; drop it silently */ +- if (atomic_read(&uhid->report_id) != ev->u.feature_answer.id) ++ if (atomic_read_unchecked(&uhid->report_id) != ev->u.feature_answer.id) + goto unlock; + if (atomic_read(&uhid->report_done)) + goto unlock; diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 0b122f8..b1d8160 100644 --- a/drivers/hv/channel.c @@ -39908,6 +41295,19 @@ index 600c79b..3752bab 100644 tty_port_tty_set(&cs->port, NULL); mutex_unlock(&cs->mutex); +diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c +index d0a41cb..f0cdb8c 100644 +--- a/drivers/isdn/gigaset/usb-gigaset.c ++++ b/drivers/isdn/gigaset/usb-gigaset.c +@@ -547,7 +547,7 @@ static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) + gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf); + memcpy(cs->hw.usb->bchars, buf, 6); + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41, +- 0, 0, &buf, 6, 2000); ++ 0, 0, buf, 6, 2000); + } + + static void gigaset_freebcshw(struct bc_state *bcs) diff --git a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c index 4d9b195..455075c 100644 --- a/drivers/isdn/hardware/avm/b1.c @@ -39930,6 +41330,19 @@ index 4d9b195..455075c 100644 return -EFAULT; } else { memcpy(buf, dp, left); +diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c +index 9bb12ba..d4262f7 100644 +--- a/drivers/isdn/i4l/isdn_common.c ++++ b/drivers/isdn/i4l/isdn_common.c +@@ -1651,6 +1651,8 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) + } else + return -EINVAL; + case IIOCDBGVAR: ++ if (!capable(CAP_SYS_RAWIO)) ++ return -EPERM; + if (arg) { + if (copy_to_user(argp, &dev, sizeof(ulong))) + return -EFAULT; diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 3c5f249..5fac4d0 100644 --- a/drivers/isdn/i4l/isdn_tty.c @@ -42959,7 +44372,7 @@ index d532948..e0d8bb1 100644 memset(buf, 0, sizeof(buf)); buf_size = min(count, sizeof(buf) - 1); diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c -index 50ba0a4..29424e7 100644 +index aeb70e1..d7b5bb5 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c @@ -1329,7 +1329,7 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file, @@ -46639,6 +48052,29 @@ index d53547d..6a22d02 100644 if (atomic_read(&urb->reject)) wake_up(&usb_kill_urb_queue); usb_put_urb(urb); +diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c +index da2905a..834a569 100644 +--- a/drivers/usb/core/hub.c ++++ b/drivers/usb/core/hub.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -4424,6 +4425,10 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, + goto done; + return; + } ++ ++ if (gr_handle_new_usb()) ++ goto done; ++ + if (hub_is_superspeed(hub->hdev)) + unit_load = 150; + else diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 444d30e..f15c850 100644 --- a/drivers/usb/core/message.c @@ -46678,6 +48114,19 @@ index b10da72..43aa0b2 100644 INIT_LIST_HEAD(&dev->ep0.urb_list); dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE; +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index f77083f..f3e2e34 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -550,8 +550,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, + if (!usb_endpoint_xfer_isoc(desc)) + return 0; + +- memset(&trb_link, 0, sizeof(trb_link)); +- + /* Link TRB for ISOC. The HWO bit is never reset */ + trb_st_hw = &dep->trb_pool[0]; + diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 5e29dde..eca992f 100644 --- a/drivers/usb/early/ehci-dbgp.c @@ -51538,10 +52987,10 @@ index d50bbe5..af3b649 100644 goto err; } diff --git a/fs/bio.c b/fs/bio.c -index 94bbc04..6fe78a4 100644 +index c5eae72..599e3cf 100644 --- a/fs/bio.c +++ b/fs/bio.c -@@ -1096,7 +1096,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, +@@ -1106,7 +1106,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, /* * Overflow, abort */ @@ -51550,7 +52999,7 @@ index 94bbc04..6fe78a4 100644 return ERR_PTR(-EINVAL); nr_pages += end - start; -@@ -1230,7 +1230,7 @@ static struct bio *__bio_map_user_iov(struct request_queue *q, +@@ -1240,7 +1240,7 @@ static struct bio *__bio_map_user_iov(struct request_queue *q, /* * Overflow, abort */ @@ -51559,7 +53008,7 @@ index 94bbc04..6fe78a4 100644 return ERR_PTR(-EINVAL); nr_pages += end - start; -@@ -1492,7 +1492,7 @@ static void bio_copy_kern_endio(struct bio *bio, int err) +@@ -1502,7 +1502,7 @@ static void bio_copy_kern_endio(struct bio *bio, int err) const int read = bio_data_dir(bio) == READ; struct bio_map_data *bmd = bio->bi_private; int i; @@ -56152,7 +57601,7 @@ index 9ed9361..2b72db1 100644 out: return len; diff --git a/fs/namespace.c b/fs/namespace.c -index 7b1ca9b..6faeccf 100644 +index a45ba4f..e7dc489 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1265,6 +1265,9 @@ static int do_umount(struct mount *mnt, int flags) @@ -56560,9 +58009,18 @@ index aa411c3..c260a84 100644 "inode 0x%lx or driver bug.", vdir->i_ino); goto err_out; diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c -index c5670b8..01a3656 100644 +index c5670b8..2b43d9b 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c +@@ -1282,7 +1282,7 @@ static inline size_t ntfs_copy_from_user(struct page **pages, + char *addr; + size_t total = 0; + unsigned len; +- int left; ++ unsigned left; + + do { + len = PAGE_CACHE_SIZE - ofs; @@ -2241,6 +2241,6 @@ const struct inode_operations ntfs_file_inode_ops = { #endif /* NTFS_RW */ }; @@ -59456,10 +60914,10 @@ index ca9ecaa..60100c7 100644 kfree(s); diff --git a/grsecurity/Kconfig b/grsecurity/Kconfig new file mode 100644 -index 0000000..712a85d +index 0000000..76e84b9 --- /dev/null +++ b/grsecurity/Kconfig -@@ -0,0 +1,1043 @@ +@@ -0,0 +1,1063 @@ +# +# grecurity configuration +# @@ -60431,6 +61889,26 @@ index 0000000..712a85d + option with name "socket_server_gid" is created. + +endmenu ++ ++menu "Physical Protections" ++depends on GRKERNSEC ++ ++config GRKERNSEC_DENYUSB ++ bool "Deny new USB connections after toggle" ++ default y if GRKERNSEC_CONFIG_AUTO ++ help ++ If you say Y here, a new sysctl option with name "deny_new_usb" ++ will be created. Setting its value to 1 will prevent any new ++ USB devices from being recognized by the OS. Any attempted USB ++ device insertion will be logged. This option is intended to be ++ used against custom USB devices designed to exploit vulnerabilities ++ in various USB device drivers. ++ ++ For greatest effectiveness, this sysctl should be set after any ++ relevant init scripts. Once set, it cannot be unset. ++ ++endmenu ++ +menu "Sysctl Support" +depends on GRKERNSEC && SYSCTL + @@ -60505,10 +61983,10 @@ index 0000000..712a85d +endmenu diff --git a/grsecurity/Makefile b/grsecurity/Makefile new file mode 100644 -index 0000000..36845aa +index 0000000..b0b77d5 --- /dev/null +++ b/grsecurity/Makefile -@@ -0,0 +1,42 @@ +@@ -0,0 +1,43 @@ +# grsecurity's ACL system was originally written in 2001 by Michael Dalton +# during 2001-2009 it has been completely redesigned by Brad Spengler +# into an RBAC system @@ -60521,7 +61999,8 @@ index 0000000..36845aa + +obj-y = grsec_chdir.o grsec_chroot.o grsec_exec.o grsec_fifo.o grsec_fork.o \ + grsec_mount.o grsec_sig.o grsec_sysctl.o \ -+ grsec_time.o grsec_tpe.o grsec_link.o grsec_pax.o grsec_ptrace.o ++ grsec_time.o grsec_tpe.o grsec_link.o grsec_pax.o grsec_ptrace.o \ ++ grsec_usb.o + +obj-$(CONFIG_GRKERNSEC) += grsec_init.o grsum.o gracl.o gracl_segv.o \ + gracl_cap.o gracl_alloc.o gracl_shm.o grsec_mem.o gracl_fs.o \ @@ -67806,10 +69285,10 @@ index 0000000..8ca18bf +} diff --git a/grsecurity/grsec_init.c b/grsecurity/grsec_init.c new file mode 100644 -index 0000000..ab2d875 +index 0000000..836f38f --- /dev/null +++ b/grsecurity/grsec_init.c -@@ -0,0 +1,279 @@ +@@ -0,0 +1,280 @@ +#include +#include +#include @@ -67838,6 +69317,7 @@ index 0000000..ab2d875 +int grsec_enable_chdir; +int grsec_enable_mount; +int grsec_enable_rofs; ++int grsec_deny_new_usb; +int grsec_enable_chroot_findtask; +int grsec_enable_chroot_mount; +int grsec_enable_chroot_shmat; @@ -69205,10 +70685,10 @@ index 0000000..4030d57 +} diff --git a/grsecurity/grsec_sysctl.c b/grsecurity/grsec_sysctl.c new file mode 100644 -index 0000000..7624d1c +index 0000000..301c665 --- /dev/null +++ b/grsecurity/grsec_sysctl.c -@@ -0,0 +1,460 @@ +@@ -0,0 +1,471 @@ +#include +#include +#include @@ -69666,6 +71146,17 @@ index 0000000..7624d1c + .extra2 = &one, + }, +#endif ++#ifdef CONFIG_GRKERNSEC_DENYUSB ++ { ++ .procname = "deny_new_usb", ++ .data = &grsec_deny_new_usb, ++ .maxlen = sizeof(int), ++ .mode = 0600, ++ .proc_handler = &proc_dointvec_minmax, ++ .extra1 = &one, ++ .extra2 = &one, ++ }, ++#endif + { } +}; +#endif @@ -69770,6 +71261,27 @@ index 0000000..ee57dcf +#endif + return 1; +} +diff --git a/grsecurity/grsec_usb.c b/grsecurity/grsec_usb.c +new file mode 100644 +index 0000000..ae02d8e +--- /dev/null ++++ b/grsecurity/grsec_usb.c +@@ -0,0 +1,15 @@ ++#include ++#include ++#include ++ ++int gr_handle_new_usb(void) ++{ ++#ifdef CONFIG_GRKERNSEC_DENYUSB ++ if (grsec_deny_new_usb) { ++ printk(KERN_ALERT "grsec: denied insert of new USB device\n"); ++ return 1; ++ } ++#endif ++ return 0; ++} ++EXPORT_SYMBOL_GPL(gr_handle_new_usb); diff --git a/grsecurity/grsum.c b/grsecurity/grsum.c new file mode 100644 index 0000000..9f7b1ac @@ -72156,10 +73668,10 @@ index 0000000..be66033 +#endif diff --git a/include/linux/grinternal.h b/include/linux/grinternal.h new file mode 100644 -index 0000000..fd8598b +index 0000000..e337683 --- /dev/null +++ b/include/linux/grinternal.h -@@ -0,0 +1,228 @@ +@@ -0,0 +1,229 @@ +#ifndef __GRINTERNAL_H +#define __GRINTERNAL_H + @@ -72208,6 +73720,7 @@ index 0000000..fd8598b +extern int grsec_enable_forkfail; +extern int grsec_enable_time; +extern int grsec_enable_rofs; ++extern int grsec_deny_new_usb; +extern int grsec_enable_chroot_shmat; +extern int grsec_enable_chroot_mount; +extern int grsec_enable_chroot_double; @@ -72509,10 +74022,10 @@ index 0000000..a4396b5 +#define GR_BRUTE_SUID_MSG "bruteforce prevention initiated due to crash of %.950s against uid %u, banning suid/sgid execs for %u minutes. Please investigate the crash report for " diff --git a/include/linux/grsecurity.h b/include/linux/grsecurity.h new file mode 100644 -index 0000000..3676b0b +index 0000000..d6f5a21 --- /dev/null +++ b/include/linux/grsecurity.h -@@ -0,0 +1,242 @@ +@@ -0,0 +1,244 @@ +#ifndef GR_SECURITY_H +#define GR_SECURITY_H +#include @@ -72534,6 +74047,8 @@ index 0000000..3676b0b +#error "CONFIG_PAX enabled, but no PaX options are enabled." +#endif + ++int gr_handle_new_usb(void); ++ +void gr_handle_brute_attach(unsigned long mm_flags); +void gr_handle_brute_check(void); +void gr_handle_kernel_exploit(void); @@ -72780,6 +74295,35 @@ index 0000000..e7ffaaf + const int protocol); + +#endif +diff --git a/include/linux/hid.h b/include/linux/hid.h +index 0c48991..76e41d8 100644 +--- a/include/linux/hid.h ++++ b/include/linux/hid.h +@@ -393,10 +393,12 @@ struct hid_report { + struct hid_device *device; /* associated device */ + }; + ++#define HID_MAX_IDS 256 ++ + struct hid_report_enum { + unsigned numbered; + struct list_head report_list; +- struct hid_report *report_id_hash[256]; ++ struct hid_report *report_id_hash[HID_MAX_IDS]; + }; + + #define HID_REPORT_TYPES 3 +@@ -747,6 +749,10 @@ void hid_output_report(struct hid_report *report, __u8 *data); + struct hid_device *hid_allocate_device(void); + struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); + int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); ++struct hid_report *hid_validate_report(struct hid_device *hid, ++ unsigned int type, unsigned int id, ++ unsigned int fields, ++ unsigned int report_counts); + int hid_open_report(struct hid_device *device); + int hid_check_keys_pressed(struct hid_device *hid); + int hid_connect(struct hid_device *hid, unsigned int connect_mask); diff --git a/include/linux/highmem.h b/include/linux/highmem.h index 7fb31da..08b5114 100644 --- a/include/linux/highmem.h @@ -73541,7 +75085,7 @@ index e0c8528..bcf0c29 100644 #endif /* __KERNEL__ */ #endif /* _LINUX_MM_H */ diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h -index ace9a5f..81bdb59 100644 +index 4a189ba..04101d6 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -289,6 +289,8 @@ struct vm_area_struct { @@ -73553,7 +75097,7 @@ index ace9a5f..81bdb59 100644 }; struct core_thread { -@@ -437,6 +439,24 @@ struct mm_struct { +@@ -438,6 +440,24 @@ struct mm_struct { int first_nid; #endif struct uprobes_state uprobes_state; @@ -74489,7 +76033,7 @@ index 6dacb93..6174423 100644 static inline void anon_vma_merge(struct vm_area_struct *vma, struct vm_area_struct *next) diff --git a/include/linux/sched.h b/include/linux/sched.h -index 3aeb14b..73816a6 100644 +index 178a8d9..918ea01 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -62,6 +62,7 @@ struct bio_list; @@ -74509,11 +76053,10 @@ index 3aeb14b..73816a6 100644 extern signed long schedule_timeout_interruptible(signed long timeout); extern signed long schedule_timeout_killable(signed long timeout); extern signed long schedule_timeout_uninterruptible(signed long timeout); -@@ -314,7 +315,19 @@ struct nsproxy; +@@ -314,6 +315,18 @@ struct nsproxy; struct user_namespace; #ifdef CONFIG_MMU --extern unsigned long mmap_legacy_base(void); + +#ifdef CONFIG_GRKERNSEC_RAND_THREADSTACK +extern unsigned long gr_rand_threadstack_offset(const struct mm_struct *mm, const struct file *filp, unsigned long flags); @@ -74526,11 +76069,10 @@ index 3aeb14b..73816a6 100644 + +extern bool check_heap_stack_gap(const struct vm_area_struct *vma, unsigned long addr, unsigned long len, unsigned long offset); +extern unsigned long skip_heap_stack_gap(const struct vm_area_struct *vma, unsigned long len, unsigned long offset); -+extern unsigned long mmap_legacy_base(struct mm_struct *mm); extern void arch_pick_mmap_layout(struct mm_struct *mm); extern unsigned long arch_get_unmapped_area(struct file *, unsigned long, unsigned long, -@@ -592,6 +605,17 @@ struct signal_struct { +@@ -591,6 +604,17 @@ struct signal_struct { #ifdef CONFIG_TASKSTATS struct taskstats *stats; #endif @@ -74548,7 +76090,7 @@ index 3aeb14b..73816a6 100644 #ifdef CONFIG_AUDIT unsigned audit_tty; unsigned audit_tty_log_passwd; -@@ -672,6 +696,14 @@ struct user_struct { +@@ -671,6 +695,14 @@ struct user_struct { struct key *session_keyring; /* UID's default session keyring */ #endif @@ -74563,7 +76105,7 @@ index 3aeb14b..73816a6 100644 /* Hash table maintenance information */ struct hlist_node uidhash_node; kuid_t uid; -@@ -1159,8 +1191,8 @@ struct task_struct { +@@ -1158,8 +1190,8 @@ struct task_struct { struct list_head thread_group; struct completion *vfork_done; /* for vfork() */ @@ -74574,7 +76116,7 @@ index 3aeb14b..73816a6 100644 cputime_t utime, stime, utimescaled, stimescaled; cputime_t gtime; -@@ -1185,11 +1217,6 @@ struct task_struct { +@@ -1184,11 +1216,6 @@ struct task_struct { struct task_cputime cputime_expires; struct list_head cpu_timers[3]; @@ -74586,7 +76128,7 @@ index 3aeb14b..73816a6 100644 char comm[TASK_COMM_LEN]; /* executable name excluding path - access with [gs]et_task_comm (which lock it with task_lock()) -@@ -1206,6 +1233,10 @@ struct task_struct { +@@ -1205,6 +1232,10 @@ struct task_struct { #endif /* CPU-specific state of this task */ struct thread_struct thread; @@ -74597,7 +76139,7 @@ index 3aeb14b..73816a6 100644 /* filesystem information */ struct fs_struct *fs; /* open file information */ -@@ -1279,6 +1310,10 @@ struct task_struct { +@@ -1278,6 +1309,10 @@ struct task_struct { gfp_t lockdep_reclaim_gfp; #endif @@ -74608,7 +76150,7 @@ index 3aeb14b..73816a6 100644 /* journalling filesystem info */ void *journal_info; -@@ -1317,6 +1352,10 @@ struct task_struct { +@@ -1316,6 +1351,10 @@ struct task_struct { /* cg_list protected by css_set_lock and tsk->alloc_lock */ struct list_head cg_list; #endif @@ -74619,7 +76161,7 @@ index 3aeb14b..73816a6 100644 #ifdef CONFIG_FUTEX struct robust_list_head __user *robust_list; #ifdef CONFIG_COMPAT -@@ -1417,8 +1456,76 @@ struct task_struct { +@@ -1416,8 +1455,76 @@ struct task_struct { unsigned int sequential_io; unsigned int sequential_io_avg; #endif @@ -74696,7 +76238,7 @@ index 3aeb14b..73816a6 100644 /* Future-safe accessor for struct task_struct's cpus_allowed. */ #define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed) -@@ -1477,7 +1584,7 @@ struct pid_namespace; +@@ -1476,7 +1583,7 @@ struct pid_namespace; pid_t __task_pid_nr_ns(struct task_struct *task, enum pid_type type, struct pid_namespace *ns); @@ -74705,7 +76247,7 @@ index 3aeb14b..73816a6 100644 { return tsk->pid; } -@@ -1920,7 +2027,9 @@ void yield(void); +@@ -1919,7 +2026,9 @@ void yield(void); extern struct exec_domain default_exec_domain; union thread_union { @@ -74715,7 +76257,7 @@ index 3aeb14b..73816a6 100644 unsigned long stack[THREAD_SIZE/sizeof(long)]; }; -@@ -1953,6 +2062,7 @@ extern struct pid_namespace init_pid_ns; +@@ -1952,6 +2061,7 @@ extern struct pid_namespace init_pid_ns; */ extern struct task_struct *find_task_by_vpid(pid_t nr); @@ -74723,7 +76265,7 @@ index 3aeb14b..73816a6 100644 extern struct task_struct *find_task_by_pid_ns(pid_t nr, struct pid_namespace *ns); -@@ -2119,7 +2229,7 @@ extern void __cleanup_sighand(struct sighand_struct *); +@@ -2118,7 +2228,7 @@ extern void __cleanup_sighand(struct sighand_struct *); extern void exit_itimers(struct signal_struct *); extern void flush_itimer_signals(void); @@ -74732,7 +76274,7 @@ index 3aeb14b..73816a6 100644 extern int allow_signal(int); extern int disallow_signal(int); -@@ -2310,9 +2420,9 @@ static inline unsigned long *end_of_stack(struct task_struct *p) +@@ -2309,9 +2419,9 @@ static inline unsigned long *end_of_stack(struct task_struct *p) #endif @@ -78484,7 +80026,7 @@ index e76e495..cbfe63a 100644 /* diff --git a/kernel/events/internal.h b/kernel/events/internal.h -index ca65997..cc8cee4 100644 +index ca65997..60df03d 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -81,10 +81,10 @@ static inline unsigned long perf_data_size(struct ring_buffer *rb) @@ -78492,11 +80034,12 @@ index ca65997..cc8cee4 100644 } -#define DEFINE_OUTPUT_COPY(func_name, memcpy_func) \ +-static inline unsigned int \ +#define DEFINE_OUTPUT_COPY(func_name, memcpy_func, user) \ - static inline unsigned int \ ++static inline unsigned long \ func_name(struct perf_output_handle *handle, \ - const void *buf, unsigned int len) \ -+ const void user *buf, unsigned int len) \ ++ const void user *buf, unsigned long len) \ { \ unsigned long size, written; \ \ @@ -78521,6 +80064,19 @@ index ca65997..cc8cee4 100644 /* Callchain handling */ extern struct perf_callchain_entry * +diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c +index f356974..cb8c570 100644 +--- a/kernel/events/uprobes.c ++++ b/kernel/events/uprobes.c +@@ -1556,7 +1556,7 @@ static int is_trap_at_addr(struct mm_struct *mm, unsigned long vaddr) + { + struct page *page; + uprobe_opcode_t opcode; +- int result; ++ long result; + + pagefault_disable(); + result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr, diff --git a/kernel/exit.c b/kernel/exit.c index 7bb73f9..d7978ed 100644 --- a/kernel/exit.c @@ -78906,7 +80462,7 @@ index ffbc090..08ceeee 100644 else new_fs = fs; diff --git a/kernel/futex.c b/kernel/futex.c -index 49dacfb..5c6b450 100644 +index 49dacfb..2ac4526 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -54,6 +54,7 @@ @@ -78929,6 +80485,15 @@ index 49dacfb..5c6b450 100644 /* * The futex address must be "naturally" aligned. */ +@@ -440,7 +446,7 @@ static int cmpxchg_futex_value_locked(u32 *curval, u32 __user *uaddr, + + static int get_futex_value_locked(u32 *dest, u32 __user *from) + { +- int ret; ++ unsigned long ret; + + pagefault_disable(); + ret = __copy_from_user_inatomic(dest, from, sizeof(u32)); @@ -2733,6 +2739,7 @@ static int __init futex_init(void) { u32 curval; @@ -82923,10 +84488,10 @@ index b8b8560..75b1a09 100644 ret = -EIO; bt->dropped_file = debugfs_create_file("dropped", 0444, dir, bt, diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c -index 6c508ff..ee55a13 100644 +index f23449d..b8cc3a1 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c -@@ -1915,12 +1915,17 @@ ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec) +@@ -1925,12 +1925,17 @@ ftrace_code_disable(struct module *mod, struct dyn_ftrace *rec) if (unlikely(ftrace_disabled)) return 0; @@ -82946,7 +84511,7 @@ index 6c508ff..ee55a13 100644 } /* -@@ -3931,8 +3936,10 @@ static int ftrace_process_locs(struct module *mod, +@@ -3994,8 +3999,10 @@ static int ftrace_process_locs(struct module *mod, if (!count) return 0; @@ -82957,7 +84522,7 @@ index 6c508ff..ee55a13 100644 start_pg = ftrace_allocate_pages(count); if (!start_pg) -@@ -4655,8 +4662,6 @@ ftrace_enable_sysctl(struct ctl_table *table, int write, +@@ -4718,8 +4725,6 @@ ftrace_enable_sysctl(struct ctl_table *table, int write, #ifdef CONFIG_FUNCTION_GRAPH_TRACER static int ftrace_graph_active; @@ -82966,7 +84531,7 @@ index 6c508ff..ee55a13 100644 int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace) { return 0; -@@ -4800,6 +4805,10 @@ ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state, +@@ -4863,6 +4868,10 @@ ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state, return NOTIFY_DONE; } @@ -82977,7 +84542,7 @@ index 6c508ff..ee55a13 100644 int register_ftrace_graph(trace_func_graph_ret_t retfunc, trace_func_graph_ent_t entryfunc) { -@@ -4813,7 +4822,6 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc, +@@ -4876,7 +4885,6 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc, goto out; } @@ -83264,10 +84829,10 @@ index e444ff8..438b8f4 100644 *data_page = bpage; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c -index 06a5bce..53ad6e7 100644 +index 0582a01..310bed1 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c -@@ -3347,7 +3347,7 @@ int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set) +@@ -3327,7 +3327,7 @@ int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set) return 0; } @@ -83290,10 +84855,10 @@ index 51b4448..7be601f 100644 /* * Normal trace_printk() and friends allocates special buffers diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c -index 6953263..2004e16 100644 +index 3d18aad..d1be0eb 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c -@@ -1748,10 +1748,6 @@ static LIST_HEAD(ftrace_module_file_list); +@@ -1794,10 +1794,6 @@ static LIST_HEAD(ftrace_module_file_list); struct ftrace_module_file_ops { struct list_head list; struct module *mod; @@ -83304,7 +84869,7 @@ index 6953263..2004e16 100644 }; static struct ftrace_module_file_ops * -@@ -1792,17 +1788,12 @@ trace_create_file_ops(struct module *mod) +@@ -1838,17 +1834,12 @@ trace_create_file_ops(struct module *mod) file_ops->mod = mod; @@ -83328,7 +84893,7 @@ index 6953263..2004e16 100644 list_add(&file_ops->list, &ftrace_module_file_list); -@@ -1895,8 +1886,8 @@ __trace_add_new_mod_event(struct ftrace_event_call *call, +@@ -1941,8 +1932,8 @@ __trace_add_new_mod_event(struct ftrace_event_call *call, struct ftrace_module_file_ops *file_ops) { return __trace_add_new_event(call, tr, @@ -84210,7 +85775,7 @@ index 5025174..9d67dcd 100644 bdi_destroy(bdi); return err; diff --git a/mm/filemap.c b/mm/filemap.c -index 7905fe7..e60faa8 100644 +index 7905fe7..f59502b 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1766,7 +1766,7 @@ int generic_file_mmap(struct file * file, struct vm_area_struct * vma) @@ -84222,6 +85787,42 @@ index 7905fe7..e60faa8 100644 file_accessed(file); vma->vm_ops = &generic_file_vm_ops; return 0; +@@ -1948,7 +1948,7 @@ static size_t __iovec_copy_from_user_inatomic(char *vaddr, + + while (bytes) { + char __user *buf = iov->iov_base + base; +- int copy = min(bytes, iov->iov_len - base); ++ size_t copy = min(bytes, iov->iov_len - base); + + base = 0; + left = __copy_from_user_inatomic(vaddr, buf, copy); +@@ -1977,7 +1977,7 @@ size_t iov_iter_copy_from_user_atomic(struct page *page, + BUG_ON(!in_atomic()); + kaddr = kmap_atomic(page); + if (likely(i->nr_segs == 1)) { +- int left; ++ size_t left; + char __user *buf = i->iov->iov_base + i->iov_offset; + left = __copy_from_user_inatomic(kaddr + offset, buf, bytes); + copied = bytes - left; +@@ -2005,7 +2005,7 @@ size_t iov_iter_copy_from_user(struct page *page, + + kaddr = kmap(page); + if (likely(i->nr_segs == 1)) { +- int left; ++ size_t left; + char __user *buf = i->iov->iov_base + i->iov_offset; + left = __copy_from_user(kaddr + offset, buf, bytes); + copied = bytes - left; +@@ -2035,7 +2035,7 @@ void iov_iter_advance(struct iov_iter *i, size_t bytes) + * zero-length segments (without overruning the iovec). + */ + while (bytes || unlikely(i->count && !iov->iov_len)) { +- int copy; ++ size_t copy; + + copy = min(bytes, iov->iov_len - base); + BUG_ON(!i->count || i->count < copy); @@ -2106,6 +2106,7 @@ inline int generic_write_checks(struct file *file, loff_t *pos, size_t *count, i *pos = i_size_read(inode); @@ -90212,9 +91813,18 @@ index a08bd2b..c59bd7c 100644 if (extfilt) filter_mask = nla_get_u32(extfilt); diff --git a/net/core/scm.c b/net/core/scm.c -index 03795d0..eaf7368 100644 +index 03795d0..98d6bdb 100644 --- a/net/core/scm.c +++ b/net/core/scm.c +@@ -54,7 +54,7 @@ static __inline__ int scm_check_creds(struct ucred *creds) + return -EINVAL; + + if ((creds->pid == task_tgid_vnr(current) || +- ns_capable(current->nsproxy->pid_ns->user_ns, CAP_SYS_ADMIN)) && ++ ns_capable(task_active_pid_ns(current)->user_ns, CAP_SYS_ADMIN)) && + ((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) || + uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) && + ((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) || @@ -210,7 +210,7 @@ EXPORT_SYMBOL(__scm_send); int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data) { @@ -90526,6 +92136,19 @@ index a55eecc..dd8428c 100644 return -EFAULT; *lenp = len; +diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c +index 55e1fd5..fd602b8 100644 +--- a/net/ieee802154/6lowpan.c ++++ b/net/ieee802154/6lowpan.c +@@ -459,7 +459,7 @@ static int lowpan_header_create(struct sk_buff *skb, + hc06_ptr += 3; + } else { + /* compress nothing */ +- memcpy(hc06_ptr, &hdr, 4); ++ memcpy(hc06_ptr, hdr, 4); + /* replace the top byte with new ECN | DSCP format */ + *hc06_ptr = tmp; + hc06_ptr += 4; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index d01be2a..8976537 100644 --- a/net/ipv4/af_inet.c @@ -91688,7 +93311,7 @@ index 9a459be..086b866 100644 return -ENOMEM; } diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c -index fb8c94c..fb18024 100644 +index fb8c94c..80a31d8 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -621,7 +621,7 @@ static int inet6_netconf_dump_devconf(struct sk_buff *skb, @@ -91700,7 +93323,24 @@ index fb8c94c..fb18024 100644 net->dev_base_seq; hlist_for_each_entry_rcu(dev, head, index_hlist) { if (idx < s_idx) -@@ -2380,7 +2380,7 @@ int addrconf_set_dstaddr(struct net *net, void __user *arg) +@@ -1124,12 +1124,10 @@ retry: + if (ifp->flags & IFA_F_OPTIMISTIC) + addr_flags |= IFA_F_OPTIMISTIC; + +- ift = !max_addresses || +- ipv6_count_addresses(idev) < max_addresses ? +- ipv6_add_addr(idev, &addr, tmp_plen, +- ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, +- addr_flags) : NULL; +- if (IS_ERR_OR_NULL(ift)) { ++ ift = ipv6_add_addr(idev, &addr, tmp_plen, ++ ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, ++ addr_flags); ++ if (IS_ERR(ift)) { + in6_ifa_put(ifp); + in6_dev_put(idev); + pr_info("%s: retry temporary address regeneration\n", __func__); +@@ -2380,7 +2378,7 @@ int addrconf_set_dstaddr(struct net *net, void __user *arg) p.iph.ihl = 5; p.iph.protocol = IPPROTO_IPV6; p.iph.ttl = 64; @@ -91709,7 +93349,7 @@ index fb8c94c..fb18024 100644 if (ops->ndo_do_ioctl) { mm_segment_t oldfs = get_fs(); -@@ -4002,7 +4002,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, +@@ -4002,7 +4000,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb, s_ip_idx = ip_idx = cb->args[2]; rcu_read_lock(); @@ -91718,7 +93358,7 @@ index fb8c94c..fb18024 100644 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { idx = 0; head = &net->dev_index_head[h]; -@@ -4587,7 +4587,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) +@@ -4587,7 +4585,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) dst_free(&ifp->rt->dst); break; } @@ -91727,7 +93367,7 @@ index fb8c94c..fb18024 100644 } static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) -@@ -4607,7 +4607,7 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, +@@ -4607,7 +4605,7 @@ int addrconf_sysctl_forward(ctl_table *ctl, int write, int *valp = ctl->data; int val = *valp; loff_t pos = *ppos; @@ -91736,7 +93376,7 @@ index fb8c94c..fb18024 100644 int ret; /* -@@ -4689,7 +4689,7 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write, +@@ -4689,7 +4687,7 @@ int addrconf_sysctl_disable(ctl_table *ctl, int write, int *valp = ctl->data; int val = *valp; loff_t pos = *ppos; @@ -91938,9 +93578,18 @@ index dffdc1a..ccc6678 100644 return -ENOMEM; } diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c -index eedff8c..6e13a47 100644 +index eedff8c..7d7e24a 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c +@@ -108,7 +108,7 @@ found: + */ + static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb) + { +- struct icmp6hdr *_hdr; ++ struct icmp6hdr _hdr; + const struct icmp6hdr *hdr; + + hdr = skb_header_pointer(skb, skb_transport_offset(skb), @@ -378,7 +378,7 @@ static inline int rawv6_rcv_skb(struct sock *sk, struct sk_buff *skb) { if ((raw6_sk(sk)->checksum || rcu_access_pointer(sk->sk_filter)) && @@ -92939,9 +94588,18 @@ index 0ab9636..cea3c6a 100644 { if (users > 0) diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c -index a99b6c3..3841268 100644 +index a99b6c3..cb372f9 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c +@@ -428,7 +428,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, + const char *msg; + u_int8_t state; + +- dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); ++ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); + BUG_ON(dh == NULL); + + state = dccp_state_table[CT_DCCP_ROLE_CLIENT][dh->dccph_type][CT_DCCP_NONE]; @@ -457,7 +457,7 @@ static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, out_invalid: if (LOG_INVALID(net, IPPROTO_DCCP)) @@ -92951,6 +94609,24 @@ index a99b6c3..3841268 100644 return false; } +@@ -486,7 +486,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, + u_int8_t type, old_state, new_state; + enum ct_dccp_roles role; + +- dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); ++ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); + BUG_ON(dh == NULL); + type = dh->dccph_type; + +@@ -577,7 +577,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl, + unsigned int cscov; + const char *msg; + +- dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &dh); ++ dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); + if (dh == NULL) { + msg = "nf_ct_dccp: short packet "; + goto out_invalid; @@ -614,7 +614,7 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl, out_invalid: @@ -95557,7 +97233,7 @@ index f5eb43d..1814de8 100644 shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff)); shstrtab_sec = shdr + r2(&ehdr->e_shstrndx); diff --git a/security/Kconfig b/security/Kconfig -index e9c6ac7..3e3f362 100644 +index e9c6ac7..c5d45c8 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -4,6 +4,959 @@ @@ -96396,7 +98072,7 @@ index e9c6ac7..3e3f362 100644 +config PAX_REFCOUNT + bool "Prevent various kernel object reference counter overflows" + default y if GRKERNSEC_CONFIG_AUTO -+ depends on GRKERNSEC && ((ARM && (CPU_V6 || CPU_V6K || CPU_V7)) || SPARC64 || X86) ++ depends on GRKERNSEC && ((ARM && (CPU_V6 || CPU_V6K || CPU_V7)) || MIPS || SPARC64 || X86) + help + By saying Y here the kernel will detect and prevent overflowing + various (but not all) kinds of object reference counters. Such @@ -99033,10 +100709,10 @@ index 0000000..568b360 +} diff --git a/tools/gcc/kernexec_plugin.c b/tools/gcc/kernexec_plugin.c new file mode 100644 -index 0000000..0408e06 +index 0000000..257529f --- /dev/null +++ b/tools/gcc/kernexec_plugin.c -@@ -0,0 +1,465 @@ +@@ -0,0 +1,471 @@ +/* + * Copyright 2011-2013 by the PaX Team + * Licensed under the GPL v2 @@ -99088,7 +100764,7 @@ index 0000000..0408e06 +int plugin_is_GPL_compatible; + +static struct plugin_info kernexec_plugin_info = { -+ .version = "201302112000", ++ .version = "201308230150", + .help = "method=[bts|or]\tinstrumentation method\n" +}; + @@ -99239,7 +100915,7 @@ index 0000000..0408e06 +static void kernexec_instrument_fptr_bts(gimple_stmt_iterator *gsi) +{ + gimple assign_intptr, assign_new_fptr, call_stmt; -+ tree intptr, old_fptr, new_fptr, kernexec_mask; ++ tree intptr, orptr, old_fptr, new_fptr, kernexec_mask; + + call_stmt = gsi_stmt(*gsi); + old_fptr = gimple_call_fn(call_stmt); @@ -99248,16 +100924,20 @@ index 0000000..0408e06 + intptr = create_tmp_var(long_unsigned_type_node, "kernexec_bts"); +#if BUILDING_GCC_VERSION <= 4007 + add_referenced_var(intptr); -+ mark_sym_for_renaming(intptr); +#endif ++ intptr = make_ssa_name(intptr, NULL); + assign_intptr = gimple_build_assign(intptr, fold_convert(long_unsigned_type_node, old_fptr)); ++ SSA_NAME_DEF_STMT(intptr) = assign_intptr; + gsi_insert_before(gsi, assign_intptr, GSI_SAME_STMT); + update_stmt(assign_intptr); + + // apply logical or to temporary unsigned long and bitmask + kernexec_mask = build_int_cstu(long_long_unsigned_type_node, 0x8000000000000000LL); +// kernexec_mask = build_int_cstu(long_long_unsigned_type_node, 0xffffffff80000000LL); -+ assign_intptr = gimple_build_assign(intptr, fold_build2(BIT_IOR_EXPR, long_long_unsigned_type_node, intptr, kernexec_mask)); ++ orptr = fold_build2(BIT_IOR_EXPR, long_long_unsigned_type_node, intptr, kernexec_mask); ++ intptr = make_ssa_name(SSA_NAME_VAR(intptr), NULL); ++ assign_intptr = gimple_build_assign(intptr, orptr); ++ SSA_NAME_DEF_STMT(intptr) = assign_intptr; + gsi_insert_before(gsi, assign_intptr, GSI_SAME_STMT); + update_stmt(assign_intptr); + @@ -99265,9 +100945,10 @@ index 0000000..0408e06 + new_fptr = create_tmp_var(TREE_TYPE(old_fptr), "kernexec_fptr"); +#if BUILDING_GCC_VERSION <= 4007 + add_referenced_var(new_fptr); -+ mark_sym_for_renaming(new_fptr); +#endif ++ new_fptr = make_ssa_name(new_fptr, NULL); + assign_new_fptr = gimple_build_assign(new_fptr, fold_convert(TREE_TYPE(old_fptr), intptr)); ++ SSA_NAME_DEF_STMT(new_fptr) = assign_new_fptr; + gsi_insert_before(gsi, assign_new_fptr, GSI_SAME_STMT); + update_stmt(assign_new_fptr); + @@ -99295,8 +100976,8 @@ index 0000000..0408e06 + new_fptr = create_tmp_var(TREE_TYPE(old_fptr), "kernexec_or"); +#if BUILDING_GCC_VERSION <= 4007 + add_referenced_var(new_fptr); -+ mark_sym_for_renaming(new_fptr); +#endif ++ new_fptr = make_ssa_name(new_fptr, NULL); + + // build asm volatile("orq %%r10, %0\n\t" : "=r"(new_fptr) : "0"(old_fptr)); + input = build_tree_list(NULL_TREE, build_string(2, "0")); @@ -99311,6 +100992,7 @@ index 0000000..0408e06 + vec_safe_push(outputs, output); +#endif + asm_or_stmt = gimple_build_asm_vec("orq %%r10, %0\n\t", inputs, outputs, NULL, NULL); ++ SSA_NAME_DEF_STMT(new_fptr) = asm_or_stmt; + gimple_asm_set_volatile(asm_or_stmt, true); + gsi_insert_before(gsi, asm_or_stmt, GSI_SAME_STMT); + update_stmt(asm_or_stmt); @@ -99504,10 +101186,10 @@ index 0000000..0408e06 +} diff --git a/tools/gcc/latent_entropy_plugin.c b/tools/gcc/latent_entropy_plugin.c new file mode 100644 -index 0000000..b5395ba +index 0000000..2ef6fd9 --- /dev/null +++ b/tools/gcc/latent_entropy_plugin.c -@@ -0,0 +1,327 @@ +@@ -0,0 +1,321 @@ +/* + * Copyright 2012-2013 by the PaX Team + * Licensed under the GPL v2 @@ -99559,7 +101241,7 @@ index 0000000..b5395ba +static tree latent_entropy_decl; + +static struct plugin_info latent_entropy_plugin_info = { -+ .version = "201303102320", ++ .version = "201308230230", + .help = NULL +}; + @@ -99668,13 +101350,10 @@ index 0000000..b5395ba + op = get_op(&rhs); + addxorrol = fold_build2_loc(UNKNOWN_LOCATION, op, unsigned_intDI_type_node, local_entropy, rhs); + assign = gimple_build_assign(local_entropy, addxorrol); -+#if BUILDING_GCC_VERSION <= 4007 -+ find_referenced_vars_in(assign); -+#endif -+//debug_bb(bb); + gsi = gsi_after_labels(bb); + gsi_insert_before(&gsi, assign, GSI_NEW_STMT); + update_stmt(assign); ++//debug_bb(bb); +} + +static void perturb_latent_entropy(basic_block bb, tree rhs) @@ -99687,13 +101366,14 @@ index 0000000..b5395ba + temp = create_tmp_var(unsigned_intDI_type_node, "temp_latent_entropy"); +#if BUILDING_GCC_VERSION <= 4007 + add_referenced_var(temp); -+ mark_sym_for_renaming(temp); +#endif + + // 2. read... ++ temp = make_ssa_name(temp, NULL); + assign = gimple_build_assign(temp, latent_entropy_decl); ++ SSA_NAME_DEF_STMT(temp) = assign; +#if BUILDING_GCC_VERSION <= 4007 -+ find_referenced_vars_in(assign); ++ add_referenced_var(latent_entropy_decl); +#endif + gsi = gsi_after_labels(bb); + gsi_insert_after(&gsi, assign, GSI_NEW_STMT); @@ -99701,18 +101381,14 @@ index 0000000..b5395ba + + // 3. ...modify... + addxorrol = fold_build2_loc(UNKNOWN_LOCATION, get_op(NULL), unsigned_intDI_type_node, temp, rhs); ++ temp = make_ssa_name(SSA_NAME_VAR(temp), NULL); + assign = gimple_build_assign(temp, addxorrol); -+#if BUILDING_GCC_VERSION <= 4007 -+ find_referenced_vars_in(assign); -+#endif ++ SSA_NAME_DEF_STMT(temp) = assign; + gsi_insert_after(&gsi, assign, GSI_NEW_STMT); + update_stmt(assign); + + // 4. ...write latent_entropy + assign = gimple_build_assign(latent_entropy_decl, temp); -+#if BUILDING_GCC_VERSION <= 4007 -+ find_referenced_vars_in(assign); -+#endif + gsi_insert_after(&gsi, assign, GSI_NEW_STMT); + update_stmt(assign); +} @@ -99763,21 +101439,21 @@ index 0000000..b5395ba + + assign = gimple_build_assign(local_entropy, build_int_cstu(unsigned_intDI_type_node, get_random_const())); +// gimple_set_location(assign, loc); -+#if BUILDING_GCC_VERSION <= 4007 -+ find_referenced_vars_in(assign); -+#endif + gsi_insert_after(&gsi, assign, GSI_NEW_STMT); + update_stmt(assign); ++//debug_bb(bb); + bb = bb->next_bb; + + // 3. instrument each BB with an operation on the local entropy variable + while (bb != EXIT_BLOCK_PTR) { + perturb_local_entropy(bb, local_entropy); ++//debug_bb(bb); + bb = bb->next_bb; + }; + + // 4. mix local entropy into the global entropy variable + perturb_latent_entropy(EXIT_BLOCK_PTR->prev_bb, local_entropy); ++//debug_bb(EXIT_BLOCK_PTR->prev_bb); + return 0; +} + @@ -106193,10 +107869,10 @@ index 0000000..b04803b +alloc_dr_65495 alloc_dr 2 65495 NULL diff --git a/tools/gcc/size_overflow_plugin.c b/tools/gcc/size_overflow_plugin.c new file mode 100644 -index 0000000..9db0d0e +index 0000000..03d0c84 --- /dev/null +++ b/tools/gcc/size_overflow_plugin.c -@@ -0,0 +1,2114 @@ +@@ -0,0 +1,2113 @@ +/* + * Copyright 2011, 2012, 2013 by Emese Revfy + * Licensed under the GPL v2, or (at your option) v3 @@ -106286,7 +107962,7 @@ index 0000000..9db0d0e +static void print_missing_msg(tree func, unsigned int argnum); + +static struct plugin_info size_overflow_plugin_info = { -+ .version = "20130410beta", ++ .version = "20130822beta", + .help = "no-size-overflow\tturn off size overflow checking\n", +}; + @@ -106666,7 +108342,6 @@ index 0000000..9db0d0e + +#if BUILDING_GCC_VERSION <= 4007 + add_referenced_var(new_var); -+ mark_sym_for_renaming(new_var); +#endif + return new_var; +} diff --git a/src/patches/linux-3.10.9-ledtrig-netdev-1.patch b/src/patches/linux-3.10.9-ledtrig-netdev-1.patch new file mode 100644 index 000000000..8ad1ebd9d --- /dev/null +++ b/src/patches/linux-3.10.9-ledtrig-netdev-1.patch @@ -0,0 +1,478 @@ +diff -Naur linux-3.10.9.org/drivers/leds/trigger/Kconfig linux-3.10.9/drivers/leds/trigger/Kconfig +--- linux-3.10.9.org/drivers/leds/trigger/Kconfig 2013-08-21 00:40:47.000000000 +0200 ++++ linux-3.10.9/drivers/leds/trigger/Kconfig 2013-08-30 20:43:19.064025933 +0200 +@@ -108,4 +108,11 @@ + This enables direct flash/torch on/off by the driver, kernel space. + If unsure, say Y. + ++config LEDS_TRIGGER_NETDEV ++ tristate "LED Netdev Trigger" ++ depends on LEDS_TRIGGERS ++ help ++ This allows LEDs to be controlled by network device activity. ++ If unsure, say Y. ++ + endif # LEDS_TRIGGERS +diff -Naur linux-3.10.9.org/drivers/leds/trigger/ledtrig-netdev.c linux-3.10.9/drivers/leds/trigger/ledtrig-netdev.c +--- linux-3.10.9.org/drivers/leds/trigger/ledtrig-netdev.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-3.10.9/drivers/leds/trigger/ledtrig-netdev.c 2013-08-30 20:44:17.857339974 +0200 +@@ -0,0 +1,451 @@ ++/* ++ * LED Kernel Netdev Trigger ++ * ++ * Toggles the LED to reflect the link and traffic state of a named net device ++ * ++ * Copyright 2007 Oliver Jowett ++ * ++ * Derived from ledtrig-timer.c which is: ++ * Copyright 2005-2006 Openedhand Ltd. ++ * Author: Richard Purdie ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++#include ++#endif ++ ++#include "../leds.h" ++ ++/* ++ * Configurable sysfs attributes: ++ * ++ * device_name - network device name to monitor ++ * ++ * interval - duration of LED blink, in milliseconds ++ * ++ * mode - either "none" (LED is off) or a space separated list of one or more of: ++ * link: LED's normal state reflects whether the link is up (has carrier) or not ++ * tx: LED blinks on transmitted data ++ * rx: LED blinks on receive data ++ * ++ * Some suggestions: ++ * ++ * Simple link status LED: ++ * $ echo netdev >someled/trigger ++ * $ echo eth0 >someled/device_name ++ * $ echo link >someled/mode ++ * ++ * Ethernet-style link/activity LED: ++ * $ echo netdev >someled/trigger ++ * $ echo eth0 >someled/device_name ++ * $ echo "link tx rx" >someled/mode ++ * ++ * Modem-style tx/rx LEDs: ++ * $ echo netdev >led1/trigger ++ * $ echo ppp0 >led1/device_name ++ * $ echo tx >led1/mode ++ * $ echo netdev >led2/trigger ++ * $ echo ppp0 >led2/device_name ++ * $ echo rx >led2/mode ++ * ++ */ ++ ++#define MODE_LINK 1 ++#define MODE_TX 2 ++#define MODE_RX 4 ++ ++struct led_netdev_data { ++ rwlock_t lock; ++ ++ struct timer_list timer; ++ struct notifier_block notifier; ++ ++ struct led_classdev *led_cdev; ++ struct net_device *net_dev; ++ ++ char device_name[IFNAMSIZ]; ++ unsigned interval; ++ unsigned mode; ++ unsigned link_up; ++ unsigned last_activity; ++}; ++ ++static void set_baseline_state(struct led_netdev_data *trigger_data) ++{ ++ if ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up) ++ led_set_brightness(trigger_data->led_cdev, LED_FULL); ++ else ++ led_set_brightness(trigger_data->led_cdev, LED_OFF); ++ ++ if ((trigger_data->mode & (MODE_TX | MODE_RX)) != 0 && trigger_data->link_up) ++ mod_timer(&trigger_data->timer, jiffies + trigger_data->interval); ++ else ++ del_timer(&trigger_data->timer); ++} ++ ++static ssize_t led_device_name_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct led_classdev *led_cdev = dev_get_drvdata(dev); ++ struct led_netdev_data *trigger_data = led_cdev->trigger_data; ++ ++ read_lock(&trigger_data->lock); ++ sprintf(buf, "%s\n", trigger_data->device_name); ++ read_unlock(&trigger_data->lock); ++ ++ return strlen(buf) + 1; ++} ++ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21) ++extern struct net init_net; ++#endif ++ ++static ssize_t led_device_name_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct led_classdev *led_cdev = dev_get_drvdata(dev); ++ struct led_netdev_data *trigger_data = led_cdev->trigger_data; ++ ++ if (size < 0 || size >= IFNAMSIZ) ++ return -EINVAL; ++ ++ write_lock(&trigger_data->lock); ++ ++ strcpy(trigger_data->device_name, buf); ++ if (size > 0 && trigger_data->device_name[size-1] == '\n') ++ trigger_data->device_name[size-1] = 0; ++ ++ if (trigger_data->device_name[0] != 0) { ++ /* check for existing device to update from */ ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) ++ trigger_data->net_dev = dev_get_by_name(&init_net, trigger_data->device_name); ++#else ++ trigger_data->net_dev = dev_get_by_name(trigger_data->device_name); ++#endif ++ if (trigger_data->net_dev != NULL) ++ trigger_data->link_up = (dev_get_flags(trigger_data->net_dev) & IFF_LOWER_UP) != 0; ++ set_baseline_state(trigger_data); /* updates LEDs, may start timers */ ++ } ++ ++ write_unlock(&trigger_data->lock); ++ return size; ++} ++ ++static DEVICE_ATTR(device_name, 0644, led_device_name_show, led_device_name_store); ++ ++static ssize_t led_mode_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct led_classdev *led_cdev = dev_get_drvdata(dev); ++ struct led_netdev_data *trigger_data = led_cdev->trigger_data; ++ ++ read_lock(&trigger_data->lock); ++ ++ if (trigger_data->mode == 0) { ++ strcpy(buf, "none\n"); ++ } else { ++ if (trigger_data->mode & MODE_LINK) ++ strcat(buf, "link "); ++ if (trigger_data->mode & MODE_TX) ++ strcat(buf, "tx "); ++ if (trigger_data->mode & MODE_RX) ++ strcat(buf, "rx "); ++ strcat(buf, "\n"); ++ } ++ ++ read_unlock(&trigger_data->lock); ++ ++ return strlen(buf)+1; ++} ++ ++static ssize_t led_mode_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct led_classdev *led_cdev = dev_get_drvdata(dev); ++ struct led_netdev_data *trigger_data = led_cdev->trigger_data; ++ char copybuf[1024]; ++ int new_mode = -1; ++ char *p, *token; ++ ++ /* take a copy since we don't want to trash the inbound buffer when using strsep */ ++ strncpy(copybuf, buf, sizeof(copybuf)); ++ copybuf[1023] = 0; ++ p = copybuf; ++ ++ while ((token = strsep(&p, " \t\n")) != NULL) { ++ if (!*token) ++ continue; ++ ++ if (new_mode == -1) ++ new_mode = 0; ++ ++ if (!strcmp(token, "none")) ++ new_mode = 0; ++ else if (!strcmp(token, "tx")) ++ new_mode |= MODE_TX; ++ else if (!strcmp(token, "rx")) ++ new_mode |= MODE_RX; ++ else if (!strcmp(token, "link")) ++ new_mode |= MODE_LINK; ++ else ++ return -EINVAL; ++ } ++ ++ if (new_mode == -1) ++ return -EINVAL; ++ ++ write_lock(&trigger_data->lock); ++ trigger_data->mode = new_mode; ++ set_baseline_state(trigger_data); ++ write_unlock(&trigger_data->lock); ++ ++ return size; ++} ++ ++static DEVICE_ATTR(mode, 0644, led_mode_show, led_mode_store); ++ ++static ssize_t led_interval_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct led_classdev *led_cdev = dev_get_drvdata(dev); ++ struct led_netdev_data *trigger_data = led_cdev->trigger_data; ++ ++ read_lock(&trigger_data->lock); ++ sprintf(buf, "%u\n", jiffies_to_msecs(trigger_data->interval)); ++ read_unlock(&trigger_data->lock); ++ ++ return strlen(buf) + 1; ++} ++ ++static ssize_t led_interval_store(struct device *dev, ++ struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct led_classdev *led_cdev = dev_get_drvdata(dev); ++ struct led_netdev_data *trigger_data = led_cdev->trigger_data; ++ int ret = -EINVAL; ++ char *after; ++ unsigned long value = simple_strtoul(buf, &after, 10); ++ size_t count = after - buf; ++ ++ if (*after && isspace(*after)) ++ count++; ++ ++ /* impose some basic bounds on the timer interval */ ++ if (count == size && value >= 5 && value <= 10000) { ++ write_lock(&trigger_data->lock); ++ trigger_data->interval = msecs_to_jiffies(value); ++ set_baseline_state(trigger_data); // resets timer ++ write_unlock(&trigger_data->lock); ++ ret = count; ++ } ++ ++ return ret; ++} ++ ++static DEVICE_ATTR(interval, 0644, led_interval_show, led_interval_store); ++ ++static int netdev_trig_notify(struct notifier_block *nb, ++ unsigned long evt, ++ void *dv) ++{ ++ struct net_device *dev = dv; ++ struct led_netdev_data *trigger_data = container_of(nb, struct led_netdev_data, notifier); ++ ++ if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER) ++ return NOTIFY_DONE; ++ ++ write_lock(&trigger_data->lock); ++ ++ if (strcmp(dev->name, trigger_data->device_name)) ++ goto done; ++ ++ if (evt == NETDEV_REGISTER) { ++ if (trigger_data->net_dev != NULL) ++ dev_put(trigger_data->net_dev); ++ dev_hold(dev); ++ trigger_data->net_dev = dev; ++ trigger_data->link_up = 0; ++ goto done; ++ } ++ ++ if (evt == NETDEV_UNREGISTER && trigger_data->net_dev != NULL) { ++ dev_put(trigger_data->net_dev); ++ trigger_data->net_dev = NULL; ++ goto done; ++ } ++ ++ /* UP / DOWN / CHANGE */ ++ ++ trigger_data->link_up = (evt != NETDEV_DOWN && netif_carrier_ok(dev)); ++ set_baseline_state(trigger_data); ++ ++done: ++ write_unlock(&trigger_data->lock); ++ return NOTIFY_DONE; ++} ++ ++/* here's the real work! */ ++static void netdev_trig_timer(unsigned long arg) ++{ ++ struct led_netdev_data *trigger_data = (struct led_netdev_data *)arg; ++ struct rtnl_link_stats64 *dev_stats; ++ unsigned new_activity; ++ struct rtnl_link_stats64 temp; ++ ++ write_lock(&trigger_data->lock); ++ ++ if (!trigger_data->link_up || !trigger_data->net_dev || (trigger_data->mode & (MODE_TX | MODE_RX)) == 0) { ++ /* we don't need to do timer work, just reflect link state. */ ++ led_set_brightness(trigger_data->led_cdev, ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up) ? LED_FULL : LED_OFF); ++ goto no_restart; ++ } ++ ++ dev_stats = dev_get_stats(trigger_data->net_dev, &temp); ++ new_activity = ++ ((trigger_data->mode & MODE_TX) ? dev_stats->tx_packets : 0) + ++ ((trigger_data->mode & MODE_RX) ? dev_stats->rx_packets : 0); ++ ++ if (trigger_data->mode & MODE_LINK) { ++ /* base state is ON (link present) */ ++ /* if there's no link, we don't get this far and the LED is off */ ++ ++ /* OFF -> ON always */ ++ /* ON -> OFF on activity */ ++ if (trigger_data->led_cdev->brightness == LED_OFF) { ++ led_set_brightness(trigger_data->led_cdev, LED_FULL); ++ } else if (trigger_data->last_activity != new_activity) { ++ led_set_brightness(trigger_data->led_cdev, LED_OFF); ++ } ++ } else { ++ /* base state is OFF */ ++ /* ON -> OFF always */ ++ /* OFF -> ON on activity */ ++ if (trigger_data->led_cdev->brightness == LED_FULL) { ++ led_set_brightness(trigger_data->led_cdev, LED_OFF); ++ } else if (trigger_data->last_activity != new_activity) { ++ led_set_brightness(trigger_data->led_cdev, LED_FULL); ++ } ++ } ++ ++ trigger_data->last_activity = new_activity; ++ mod_timer(&trigger_data->timer, jiffies + trigger_data->interval); ++ ++no_restart: ++ write_unlock(&trigger_data->lock); ++} ++ ++static void netdev_trig_activate(struct led_classdev *led_cdev) ++{ ++ struct led_netdev_data *trigger_data; ++ int rc; ++ ++ trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); ++ if (!trigger_data) ++ return; ++ ++ rwlock_init(&trigger_data->lock); ++ ++ trigger_data->notifier.notifier_call = netdev_trig_notify; ++ trigger_data->notifier.priority = 10; ++ ++ setup_timer(&trigger_data->timer, netdev_trig_timer, (unsigned long) trigger_data); ++ ++ trigger_data->led_cdev = led_cdev; ++ trigger_data->net_dev = NULL; ++ trigger_data->device_name[0] = 0; ++ ++ trigger_data->mode = 0; ++ trigger_data->interval = msecs_to_jiffies(50); ++ trigger_data->link_up = 0; ++ trigger_data->last_activity = 0; ++ ++ led_cdev->trigger_data = trigger_data; ++ ++ rc = device_create_file(led_cdev->dev, &dev_attr_device_name); ++ if (rc) ++ goto err_out; ++ rc = device_create_file(led_cdev->dev, &dev_attr_mode); ++ if (rc) ++ goto err_out_device_name; ++ rc = device_create_file(led_cdev->dev, &dev_attr_interval); ++ if (rc) ++ goto err_out_mode; ++ ++ register_netdevice_notifier(&trigger_data->notifier); ++ return; ++ ++err_out_mode: ++ device_remove_file(led_cdev->dev, &dev_attr_mode); ++err_out_device_name: ++ device_remove_file(led_cdev->dev, &dev_attr_device_name); ++err_out: ++ led_cdev->trigger_data = NULL; ++ kfree(trigger_data); ++} ++ ++static void netdev_trig_deactivate(struct led_classdev *led_cdev) ++{ ++ struct led_netdev_data *trigger_data = led_cdev->trigger_data; ++ ++ if (trigger_data) { ++ unregister_netdevice_notifier(&trigger_data->notifier); ++ ++ device_remove_file(led_cdev->dev, &dev_attr_device_name); ++ device_remove_file(led_cdev->dev, &dev_attr_mode); ++ device_remove_file(led_cdev->dev, &dev_attr_interval); ++ ++ write_lock(&trigger_data->lock); ++ ++ if (trigger_data->net_dev) { ++ dev_put(trigger_data->net_dev); ++ trigger_data->net_dev = NULL; ++ } ++ ++ write_unlock(&trigger_data->lock); ++ ++ del_timer_sync(&trigger_data->timer); ++ ++ kfree(trigger_data); ++ } ++} ++ ++static struct led_trigger netdev_led_trigger = { ++ .name = "netdev", ++ .activate = netdev_trig_activate, ++ .deactivate = netdev_trig_deactivate, ++}; ++ ++static int __init netdev_trig_init(void) ++{ ++ return led_trigger_register(&netdev_led_trigger); ++} ++ ++static void __exit netdev_trig_exit(void) ++{ ++ led_trigger_unregister(&netdev_led_trigger); ++} ++ ++module_init(netdev_trig_init); ++module_exit(netdev_trig_exit); ++ ++MODULE_AUTHOR("Oliver Jowett "); ++MODULE_DESCRIPTION("Netdev LED trigger"); ++MODULE_LICENSE("GPL"); +diff -Naur linux-3.10.9.org/drivers/leds/trigger/Makefile linux-3.10.9/drivers/leds/trigger/Makefile +--- linux-3.10.9.org/drivers/leds/trigger/Makefile 2013-08-21 00:40:47.000000000 +0200 ++++ linux-3.10.9/drivers/leds/trigger/Makefile 2013-08-30 20:43:56.414009853 +0200 +@@ -8,3 +8,4 @@ + obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o + obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT) += ledtrig-transient.o + obj-$(CONFIG_LEDS_TRIGGER_CAMERA) += ledtrig-camera.o ++obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o diff --git a/src/patches/linux-3.9-dvbsky-wot2.patch b/src/patches/linux-3.9-dvbsky-wot2.patch new file mode 100644 index 000000000..e084c8cc6 --- /dev/null +++ b/src/patches/linux-3.9-dvbsky-wot2.patch @@ -0,0 +1,6161 @@ +diff -urN a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig +--- a/drivers/media/dvb-frontends/Kconfig 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/dvb-frontends/Kconfig 2013-05-03 17:03:57.000000000 +0800 +@@ -200,6 +200,20 @@ + help + A DVB-S/S2 tuner module. Say Y when you want to support this frontend. + ++config DVB_M88DS3103 ++ tristate "Montage M88DS3103 based" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ A DVB-S/S2 tuner module. Say Y when you want to support this frontend. ++ ++config DVB_M88DC2800 ++ tristate "Montage M88DC2800 based" ++ depends on DVB_CORE && I2C ++ default m if !MEDIA_SUBDRV_AUTOSELECT ++ help ++ A DVB-C tuner module. Say Y when you want to support this frontend. ++ + config DVB_SI21XX + tristate "Silicon Labs SI21XX based" + depends on DVB_CORE && I2C +diff -urN a/drivers/media/dvb-frontends/m88dc2800.c b/drivers/media/dvb-frontends/m88dc2800.c +--- a/drivers/media/dvb-frontends/m88dc2800.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/media/dvb-frontends/m88dc2800.c 2013-01-26 16:03:21.000000000 +0800 +@@ -0,0 +1,2124 @@ ++/* ++ M88DC2800/M88TC2800 - DVB-C demodulator and tuner from Montage ++ ++ Copyright (C) 2012 Max nibble ++ Copyright (C) 2011 Montage Technology / www.montage-tech.com ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "dvb_frontend.h" ++#include "m88dc2800.h" ++ ++struct m88dc2800_state { ++ struct i2c_adapter *i2c; ++ const struct m88dc2800_config *config; ++ struct dvb_frontend frontend; ++ u32 freq; ++ u32 ber; ++ u32 sym; ++ u16 qam; ++ u8 inverted; ++ u32 xtal; ++ /* tuner state */ ++ u8 tuner_init_OK; /* Tuner initialize status */ ++ u8 tuner_dev_addr; /* Tuner device address */ ++ u32 tuner_freq; /* RF frequency to be set, unit: KHz */ ++ u16 tuner_qam; /* Reserved */ ++ u16 tuner_mode; ++ u8 tuner_bandwidth; /* Bandwidth of the channel, unit: MHz, 6/7/8 */ ++ u8 tuner_loopthrough; /* Tuner loop through switch, 0/1 */ ++ u32 tuner_crystal; /* Tuner crystal frequency, unit: KHz */ ++ u32 tuner_dac; /* Tuner DAC frequency, unit: KHz */ ++ u16 tuner_mtt; /* Tuner chip version, D1: 0x0d, E0: 0x0e, E1: 0x8e */ ++ u16 tuner_custom_cfg; ++ u32 tuner_version; /* Tuner driver version number */ ++ u32 tuner_time; ++}; ++ ++static int debug; ++module_param(debug, int, 0644); ++MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); ++ ++#define dprintk(args...) \ ++ do { \ ++ if (debug) \ ++ printk(KERN_INFO "m88dc2800: " args); \ ++ } while (0) ++ ++ ++static int m88dc2800_i2c_write(struct m88dc2800_state *state, u8 addr, ++ u8 * p_data, u8 len) ++{ ++ struct i2c_msg msg = { .flags = 0 }; ++ ++ msg.addr = addr; ++ msg.buf = p_data; ++ msg.len = len; ++ ++ return i2c_transfer(state->i2c, &msg, 1); ++} ++ ++static int m88dc2800_i2c_read(struct m88dc2800_state *state, u8 addr, ++ u8 * p_data, u8 len) ++{ ++ struct i2c_msg msg = { .flags = I2C_M_RD }; ++ ++ msg.addr = addr; ++ msg.buf = p_data; ++ msg.len = len; ++ ++ return i2c_transfer(state->i2c, &msg, 1); ++} ++ ++/*demod register operations.*/ ++static int WriteReg(struct m88dc2800_state *state, u8 reg, u8 data) ++{ ++ u8 buf[] = { reg, data }; ++ u8 addr = state->config->demod_address; ++ int err; ++ ++ dprintk("%s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data); ++ ++ err = m88dc2800_i2c_write(state, addr, buf, 2); ++ ++ if (err != 1) { ++ printk(KERN_ERR ++ "%s: writereg error(err == %i, reg == 0x%02x," ++ " value == 0x%02x)\n", __func__, err, reg, data); ++ return -EIO; ++ } ++ return 0; ++} ++ ++static int ReadReg(struct m88dc2800_state *state, u8 reg) ++{ ++ int ret; ++ u8 b0[] = { reg }; ++ u8 b1[] = { 0 }; ++ u8 addr = state->config->demod_address; ++ ++ ret = m88dc2800_i2c_write(state, addr, b0, 1); ++ ++ if (ret != 1) { ++ printk(KERN_ERR "%s: reg=0x%x (error=%d)\n", ++ __func__, reg, ret); ++ return -EIO; ++ } ++ ++ ret = m88dc2800_i2c_read(state, addr, b1, 1); ++ ++ dprintk("%s: read reg 0x%02x, value 0x%02x\n", __func__, reg, b1[0]); ++ return b1[0]; ++} ++ ++static int _mt_fe_tn_set_reg(struct m88dc2800_state *state, u8 reg, ++ u8 data) ++{ ++ int ret; ++ u8 buf[2]; ++ u8 addr = state->tuner_dev_addr; ++ ++ buf[1] = ReadReg(state, 0x86); ++ buf[1] |= 0x80; ++ ret = WriteReg(state, 0x86, buf[1]); ++ ++ buf[0] = reg; ++ buf[1] = data; ++ ++ ret = m88dc2800_i2c_write(state, addr, buf, 2); ++ if (ret != 1) ++ return -EIO; ++ return 0; ++} ++ ++static int _mt_fe_tn_get_reg(struct m88dc2800_state *state, u8 reg, ++ u8 * p_data) ++{ ++ int ret; ++ u8 buf[2]; ++ u8 addr = state->tuner_dev_addr; ++ ++ buf[1] = ReadReg(state, 0x86); ++ buf[1] |= 0x80; ++ ret = WriteReg(state, 0x86, buf[1]); ++ ++ buf[0] = reg; ++ ret = m88dc2800_i2c_write(state, addr, buf, 1); ++ ++ msleep(1); ++ ++ buf[1] = ReadReg(state, 0x86); ++ buf[1] |= 0x80; ++ ret = WriteReg(state, 0x86, buf[1]); ++ ++ return m88dc2800_i2c_read(state, addr, p_data, 1); ++} ++ ++/* Tuner operation functions.*/ ++static int _mt_fe_tn_set_RF_front_tc2800(struct m88dc2800_state *state) ++{ ++ u32 freq_KHz = state->tuner_freq; ++ u8 a, b, c; ++ if (state->tuner_mtt == 0xD1) { /* D1 */ ++ if (freq_KHz <= 123000) { ++ if (freq_KHz <= 56000) { ++ a = 0x00; b = 0x00; c = 0x00; ++ } else if (freq_KHz <= 64000) { ++ a = 0x10; b = 0x01; c = 0x08; ++ } else if (freq_KHz <= 72000) { ++ a = 0x20; b = 0x02; c = 0x10; ++ } else if (freq_KHz <= 80000) { ++ a = 0x30; b = 0x03; c = 0x18; ++ } else if (freq_KHz <= 88000) { ++ a = 0x40; b = 0x04; c = 0x20; ++ } else if (freq_KHz <= 96000) { ++ a = 0x50; b = 0x05; c = 0x28; ++ } else if (freq_KHz <= 104000) { ++ a = 0x60; b = 0x06; c = 0x30; ++ } else { ++ a = 0x70; b = 0x07; c = 0x38; ++ } ++ _mt_fe_tn_set_reg(state, 0x58, 0x9b); ++ _mt_fe_tn_set_reg(state, 0x59, a); ++ _mt_fe_tn_set_reg(state, 0x5d, b); ++ _mt_fe_tn_set_reg(state, 0x5e, c); ++ _mt_fe_tn_set_reg(state, 0x5a, 0x75); ++ _mt_fe_tn_set_reg(state, 0x73, 0x0c); ++ } else { /* if (freq_KHz > 112000) */ ++ _mt_fe_tn_set_reg(state, 0x58, 0x7b); ++ if (freq_KHz <= 304000) { ++ if (freq_KHz <= 136000) { ++ _mt_fe_tn_set_reg(state, 0x5e, 0x40); ++ } else if (freq_KHz <= 160000) { ++ _mt_fe_tn_set_reg(state, 0x5e, 0x48); ++ } else if (freq_KHz <= 184000) { ++ _mt_fe_tn_set_reg(state, 0x5e, 0x50); ++ } else if (freq_KHz <= 208000) { ++ _mt_fe_tn_set_reg(state, 0x5e, 0x58); ++ } else if (freq_KHz <= 232000) { ++ _mt_fe_tn_set_reg(state, 0x5e, 0x60); ++ } else if (freq_KHz <= 256000) { ++ _mt_fe_tn_set_reg(state, 0x5e, 0x68); ++ } else if (freq_KHz <= 280000) { ++ _mt_fe_tn_set_reg(state, 0x5e, 0x70); ++ } else { /* if (freq_KHz <= 304000) */ ++ _mt_fe_tn_set_reg(state, 0x5e, 0x78); ++ } ++ if (freq_KHz <= 171000) { ++ _mt_fe_tn_set_reg(state, 0x73, 0x08); ++ } else if (freq_KHz <= 211000) { ++ _mt_fe_tn_set_reg(state, 0x73, 0x0a); ++ } else { ++ _mt_fe_tn_set_reg(state, 0x73, 0x0e); ++ } ++ } else { /* if (freq_KHz > 304000) */ ++ _mt_fe_tn_set_reg(state, 0x5e, 0x88); ++ if (freq_KHz <= 400000) { ++ _mt_fe_tn_set_reg(state, 0x73, 0x0c); ++ } else if (freq_KHz <= 450000) { ++ _mt_fe_tn_set_reg(state, 0x73, 0x09); ++ } else if (freq_KHz <= 550000) { ++ _mt_fe_tn_set_reg(state, 0x73, 0x0e); ++ } else if (freq_KHz <= 650000) { ++ _mt_fe_tn_set_reg(state, 0x73, 0x0d); ++ } else { /*if (freq_KHz > 650000) */ ++ _mt_fe_tn_set_reg(state, 0x73, 0x0e); ++ } ++ } ++ } ++ if (freq_KHz > 800000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x24); ++ else if (freq_KHz > 700000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x34); ++ else if (freq_KHz > 500000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x44); ++ else if (freq_KHz > 300000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x43); ++ else if (freq_KHz > 220000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ else if (freq_KHz > 110000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x14); ++ else ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ if (freq_KHz > 600000) ++ _mt_fe_tn_set_reg(state, 0x6a, 0x53); ++ else if (freq_KHz > 500000) ++ _mt_fe_tn_set_reg(state, 0x6a, 0x57); ++ else ++ _mt_fe_tn_set_reg(state, 0x6a, 0x59); ++ if (freq_KHz < 200000) { ++ _mt_fe_tn_set_reg(state, 0x20, 0x5d); ++ } else if (freq_KHz < 500000) { ++ _mt_fe_tn_set_reg(state, 0x20, 0x7d); ++ } else { ++ _mt_fe_tn_set_reg(state, 0x20, 0xfd); ++ } /* end of 0xD1 */ ++ } else if (state->tuner_mtt == 0xE1) { /* E1 */ ++ if (freq_KHz <= 112000) { /* 123MHz */ ++ if (freq_KHz <= 56000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x01); ++ } else if (freq_KHz <= 64000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x09); ++ } else if (freq_KHz <= 72000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x11); ++ } else if (freq_KHz <= 80000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x19); ++ } else if (freq_KHz <= 88000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x21); ++ } else if (freq_KHz <= 96000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x29); ++ } else if (freq_KHz <= 104000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x31); ++ } else { /* if (freq_KHz <= 112000) */ ++ _mt_fe_tn_set_reg(state, 0x5c, 0x39); ++ } ++ _mt_fe_tn_set_reg(state, 0x5b, 0x30); ++ } else { /* if (freq_KHz > 112000) */ ++ if (freq_KHz <= 304000) { ++ if (freq_KHz <= 136000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x41); ++ } else if (freq_KHz <= 160000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x49); ++ } else if (freq_KHz <= 184000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x51); ++ } else if (freq_KHz <= 208000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x59); ++ } else if (freq_KHz <= 232000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x61); ++ } else if (freq_KHz <= 256000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x69); ++ } else if (freq_KHz <= 280000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x71); ++ } else { /* if (freq_KHz <= 304000) */ ++ _mt_fe_tn_set_reg(state, 0x5c, 0x79); ++ } ++ if (freq_KHz <= 150000) { ++ _mt_fe_tn_set_reg(state, 0x5b, 0x28); ++ } else if (freq_KHz <= 256000) { ++ _mt_fe_tn_set_reg(state, 0x5b, 0x29); ++ } else { ++ _mt_fe_tn_set_reg(state, 0x5b, 0x2a); ++ } ++ } else { /* if (freq_KHz > 304000) */ ++ if (freq_KHz <= 400000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x89); ++ } else if (freq_KHz <= 450000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x91); ++ } else if (freq_KHz <= 650000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0x98); ++ } else if (freq_KHz <= 850000) { ++ _mt_fe_tn_set_reg(state, 0x5c, 0xa0); ++ } else { ++ _mt_fe_tn_set_reg(state, 0x5c, 0xa8); ++ } ++ _mt_fe_tn_set_reg(state, 0x5b, 0x08); ++ } ++ } ++ } /* end of 0xE1 */ ++ return 0; ++} ++ ++static int _mt_fe_tn_cali_PLL_tc2800(struct m88dc2800_state *state, ++ u32 freq_KHz, ++ u32 cali_freq_thres_div2, ++ u32 cali_freq_thres_div3r, ++ u32 cali_freq_thres_div3) ++{ ++ s32 N, F, MUL; ++ u8 buf, tmp, tmp2; ++ s32 M; ++ const s32 crystal_KHz = state->tuner_crystal; ++ if (state->tuner_mtt == 0xD1) { ++ M = state->tuner_crystal / 4000; ++ if (freq_KHz > cali_freq_thres_div2) { ++ MUL = 4; ++ tmp = 2; ++ } else if (freq_KHz > 300000) { ++ MUL = 8; ++ tmp = 3; ++ } else if (freq_KHz > (cali_freq_thres_div2 / 2)) { ++ MUL = 8; ++ tmp = 4; ++ } else if (freq_KHz > (cali_freq_thres_div2 / 4)) { ++ MUL = 16; ++ tmp = 5; ++ } else if (freq_KHz > (cali_freq_thres_div2 / 8)) { ++ MUL = 32; ++ tmp = 6; ++ } else if (freq_KHz > (cali_freq_thres_div2 / 16)) { ++ MUL = 64; ++ tmp = 7; ++ } else { /* invalid */ ++ MUL = 0; ++ tmp = 0; ++ return 1; ++ } ++ } else if (state->tuner_mtt == 0xE1) { ++ M = state->tuner_crystal / 1000; ++ _mt_fe_tn_set_reg(state, 0x30, 0xff); ++ _mt_fe_tn_set_reg(state, 0x32, 0xe0); ++ _mt_fe_tn_set_reg(state, 0x33, 0x86); ++ _mt_fe_tn_set_reg(state, 0x37, 0x70); ++ _mt_fe_tn_set_reg(state, 0x38, 0x20); ++ _mt_fe_tn_set_reg(state, 0x39, 0x18); ++ _mt_fe_tn_set_reg(state, 0x89, 0x83); ++ if (freq_KHz > cali_freq_thres_div2) { ++ M = M / 4; ++ MUL = 4; ++ tmp = 2; ++ tmp2 = M + 16; /* 48 */ ++ } else if (freq_KHz > cali_freq_thres_div3r) { ++ M = M / 3; ++ MUL = 6; ++ tmp = 2; ++ tmp2 = M + 32; /* 32 */ ++ } else if (freq_KHz > cali_freq_thres_div3) { ++ M = M / 3; ++ MUL = 6; ++ tmp = 2; ++ tmp2 = M; /* 16 */ ++ } else if (freq_KHz > 304000) { ++ M = M / 4; ++ MUL = 8; ++ tmp = 3; ++ tmp2 = M + 16; /* 48 */ ++ } else if (freq_KHz > (cali_freq_thres_div2 / 2)) { ++ M = M / 4; ++ MUL = 8; ++ tmp = 4; ++ tmp2 = M + 16; /* 48 */ ++ } else if (freq_KHz > (cali_freq_thres_div3r / 2)) { ++ M = M / 3; ++ MUL = 12; ++ tmp = 4; ++ tmp2 = M + 32; /* 32 */ ++ } else if (freq_KHz > (cali_freq_thres_div3 / 2)) { ++ M = M / 3; ++ MUL = 12; ++ tmp = 4; ++ tmp2 = M; /* 16 */ ++ } else if (freq_KHz > (cali_freq_thres_div2 / 4)) { ++ M = M / 4; ++ MUL = 16; ++ tmp = 5; ++ tmp2 = M + 16; /* 48 */ ++ } else if (freq_KHz > (cali_freq_thres_div3r / 4)) { ++ M = M / 3; ++ MUL = 24; ++ tmp = 5; ++ tmp2 = M + 32; /* 32 */ ++ } else if (freq_KHz > (cali_freq_thres_div3 / 4)) { ++ M = M / 3; ++ MUL = 24; ++ tmp = 5; ++ tmp2 = M; /* 16 */ ++ } else if (freq_KHz > (cali_freq_thres_div2 / 8)) { ++ M = M / 4; ++ MUL = 32; ++ tmp = 6; ++ tmp2 = M + 16; /* 48 */ ++ } else if (freq_KHz > (cali_freq_thres_div3r / 8)) { ++ M = M / 3; ++ MUL = 48; ++ tmp = 6; ++ tmp2 = M + 32; /* 32 */ ++ } else if (freq_KHz > (cali_freq_thres_div3 / 8)) { ++ M = M / 3; ++ MUL = 48; ++ tmp = 6; ++ tmp2 = M; /* 16 */ ++ } else if (freq_KHz > (cali_freq_thres_div2 / 16)) { ++ M = M / 4; ++ MUL = 64; ++ tmp = 7; ++ tmp2 = M + 16; /* 48 */ ++ } else if (freq_KHz > (cali_freq_thres_div3r / 16)) { ++ M = M / 3; ++ MUL = 96; ++ tmp = 7; ++ tmp2 = M + 32; /* 32 */ ++ } else if (freq_KHz > (cali_freq_thres_div3 / 16)) { ++ M = M / 3; ++ MUL = 96; ++ tmp = 7; ++ tmp2 = M; /* 16 */ ++ } else { /* invalid */ ++ M = M / 4; ++ MUL = 0; ++ tmp = 0; ++ tmp2 = 48; ++ return 1; ++ } ++ if (freq_KHz == 291000) { ++ M = state->tuner_crystal / 1000 / 3; ++ MUL = 12; ++ tmp = 4; ++ tmp2 = M + 32; /* 32 */ ++ } ++ /* ++ if (freq_KHz == 578000) { ++ M = state->tuner_crystal / 1000 / 4; ++ MUL = 4; ++ tmp = 2; ++ tmp2 = M + 16; // 48 ++ } ++ */ ++ if (freq_KHz == 690000) { ++ M = state->tuner_crystal / 1000 / 3; ++ MUL = 4; ++ tmp = 2; ++ tmp2 = M + 16; /* 48 */ ++ } ++ _mt_fe_tn_get_reg(state, 0x33, &buf); ++ buf &= 0xc0; ++ buf += tmp2; ++ _mt_fe_tn_set_reg(state, 0x33, buf); ++ } else { ++ return 1; ++ } ++ _mt_fe_tn_get_reg(state, 0x39, &buf); ++ buf &= 0xf8; ++ buf += tmp; ++ _mt_fe_tn_set_reg(state, 0x39, buf); ++ N = (freq_KHz * MUL * M / crystal_KHz) / 2 * 2 - 256; ++ buf = (N >> 8) & 0xcf; ++ if (state->tuner_mtt == 0xE1) { ++ buf |= 0x30; ++ } ++ _mt_fe_tn_set_reg(state, 0x34, buf); ++ buf = N & 0xff; ++ _mt_fe_tn_set_reg(state, 0x35, buf); ++ F = ((freq_KHz * MUL * M / (crystal_KHz / 1000) / 2) - ++ (freq_KHz * MUL * M / crystal_KHz / 2 * 1000)) * 64 / 1000; ++ buf = F & 0xff; ++ _mt_fe_tn_set_reg(state, 0x36, buf); ++ if (F == 0) { ++ if (state->tuner_mtt == 0xD1) { ++ _mt_fe_tn_set_reg(state, 0x3d, 0xca); ++ } else if (state->tuner_mtt == 0xE1) { ++ _mt_fe_tn_set_reg(state, 0x3d, 0xfe); ++ } else { ++ return 1; ++ } ++ _mt_fe_tn_set_reg(state, 0x3e, 0x9c); ++ _mt_fe_tn_set_reg(state, 0x3f, 0x34); ++ } ++ if (F > 0) { ++ if (state->tuner_mtt == 0xD1) { ++ if ((F == 32) || (F == 16) || (F == 48)) { ++ _mt_fe_tn_set_reg(state, 0x3e, 0xa4); ++ _mt_fe_tn_set_reg(state, 0x3d, 0x4a); ++ _mt_fe_tn_set_reg(state, 0x3f, 0x36); ++ } else { ++ _mt_fe_tn_set_reg(state, 0x3e, 0xa4); ++ _mt_fe_tn_set_reg(state, 0x3d, 0x4a); ++ _mt_fe_tn_set_reg(state, 0x3f, 0x36); ++ } ++ } else if (state->tuner_mtt == 0xE1) { ++ _mt_fe_tn_set_reg(state, 0x3e, 0xa4); ++ _mt_fe_tn_set_reg(state, 0x3d, 0x7e); ++ _mt_fe_tn_set_reg(state, 0x3f, 0x36); ++ _mt_fe_tn_set_reg(state, 0x89, 0x84); ++ _mt_fe_tn_get_reg(state, 0x39, &buf); ++ buf = buf & 0x1f; ++ _mt_fe_tn_set_reg(state, 0x39, buf); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = buf | 0x02; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ } else { ++ return 1; ++ } ++ } ++ _mt_fe_tn_set_reg(state, 0x41, 0x00); ++ if (state->tuner_mtt == 0xD1) { ++ msleep(5); ++ } else if (state->tuner_mtt == 0xE1) { ++ msleep(2); ++ } else { ++ return 1; ++ } ++ _mt_fe_tn_set_reg(state, 0x41, 0x02); ++ _mt_fe_tn_set_reg(state, 0x30, 0x7f); ++ _mt_fe_tn_set_reg(state, 0x30, 0xff); ++ _mt_fe_tn_set_reg(state, 0x31, 0x80); ++ _mt_fe_tn_set_reg(state, 0x31, 0x00); ++ ++ return 0; ++} ++ ++static int _mt_fe_tn_set_PLL_freq_tc2800(struct m88dc2800_state *state) ++{ ++ u8 buf, buf1; ++ u32 freq_thres_div2_KHz, freq_thres_div3r_KHz, ++ freq_thres_div3_KHz; ++ const u32 freq_KHz = state->tuner_freq; ++ if (state->tuner_mtt == 0xD1) { ++ _mt_fe_tn_set_reg(state, 0x32, 0xe1); ++ _mt_fe_tn_set_reg(state, 0x33, 0xa6); ++ _mt_fe_tn_set_reg(state, 0x37, 0x7f); ++ _mt_fe_tn_set_reg(state, 0x38, 0x20); ++ _mt_fe_tn_set_reg(state, 0x39, 0x18); ++ _mt_fe_tn_set_reg(state, 0x40, 0x40); ++ freq_thres_div2_KHz = 520000; ++ _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, ++ freq_thres_div2_KHz, 0, 0); ++ msleep(5); ++ _mt_fe_tn_get_reg(state, 0x3a, &buf); ++ buf1 = buf; ++ buf = buf & 0x03; ++ buf1 = buf1 & 0x01; ++ if ((buf1 == 0) || (buf == 3)) { ++ freq_thres_div2_KHz = 420000; ++ _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, ++ freq_thres_div2_KHz, 0, ++ 0); ++ msleep(5); ++ _mt_fe_tn_get_reg(state, 0x3a, &buf); ++ buf = buf & 0x07; ++ if (buf == 5) { ++ freq_thres_div2_KHz = 520000; ++ _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, ++ freq_thres_div2_KHz, ++ 0, 0); ++ msleep(5); ++ } ++ } ++ _mt_fe_tn_get_reg(state, 0x38, &buf); ++ _mt_fe_tn_set_reg(state, 0x38, buf); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = buf | 0x10; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ _mt_fe_tn_set_reg(state, 0x30, 0x7f); ++ _mt_fe_tn_set_reg(state, 0x30, 0xff); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = buf & 0xdf; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ _mt_fe_tn_set_reg(state, 0x40, 0x0); ++ _mt_fe_tn_set_reg(state, 0x30, 0x7f); ++ _mt_fe_tn_set_reg(state, 0x30, 0xff); ++ _mt_fe_tn_set_reg(state, 0x31, 0x80); ++ _mt_fe_tn_set_reg(state, 0x31, 0x00); ++ msleep(5); ++ _mt_fe_tn_get_reg(state, 0x39, &buf); ++ buf = buf >> 5; ++ if (buf < 5) { ++ _mt_fe_tn_get_reg(state, 0x39, &buf); ++ buf = buf | 0xa0; ++ buf = buf & 0xbf; ++ _mt_fe_tn_set_reg(state, 0x39, buf); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = buf | 0x02; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ } ++ _mt_fe_tn_get_reg(state, 0x37, &buf); ++ if (buf > 0x70) { ++ buf = 0x7f; ++ _mt_fe_tn_set_reg(state, 0x40, 0x40); ++ } ++ _mt_fe_tn_set_reg(state, 0x37, buf); ++ _mt_fe_tn_get_reg(state, 0x38, &buf); ++ if (buf < 0x0f) { ++ buf = (buf & 0x0f) << 2; ++ buf = buf + 0x0f; ++ _mt_fe_tn_set_reg(state, 0x37, buf); ++ } else if (buf < 0x1f) { ++ buf = buf + 0x0f; ++ _mt_fe_tn_set_reg(state, 0x37, buf); ++ } ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = (buf | 0x20) & 0xef; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ _mt_fe_tn_set_reg(state, 0x41, 0x00); ++ msleep(5); ++ _mt_fe_tn_set_reg(state, 0x41, 0x02); ++ } else if (state->tuner_mtt == 0xE1) { ++ freq_thres_div2_KHz = 580000; ++ freq_thres_div3r_KHz = 500000; ++ freq_thres_div3_KHz = 440000; ++ _mt_fe_tn_cali_PLL_tc2800(state, freq_KHz, ++ freq_thres_div2_KHz, ++ freq_thres_div3r_KHz, ++ freq_thres_div3_KHz); ++ msleep(3); ++ _mt_fe_tn_get_reg(state, 0x38, &buf); ++ _mt_fe_tn_set_reg(state, 0x38, buf); ++ _mt_fe_tn_set_reg(state, 0x30, 0x7f); ++ _mt_fe_tn_set_reg(state, 0x30, 0xff); ++ _mt_fe_tn_set_reg(state, 0x31, 0x80); ++ _mt_fe_tn_set_reg(state, 0x31, 0x00); ++ msleep(3); ++ _mt_fe_tn_get_reg(state, 0x38, &buf); ++ _mt_fe_tn_set_reg(state, 0x38, buf); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = buf | 0x10; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ _mt_fe_tn_set_reg(state, 0x30, 0x7f); ++ _mt_fe_tn_set_reg(state, 0x30, 0xff); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = buf & 0xdf; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ _mt_fe_tn_set_reg(state, 0x31, 0x80); ++ _mt_fe_tn_set_reg(state, 0x31, 0x00); ++ msleep(3); ++ _mt_fe_tn_get_reg(state, 0x37, &buf); ++ _mt_fe_tn_set_reg(state, 0x37, buf); ++ /* ++ if ((freq_KHz == 802000) || (freq_KHz == 826000)) { ++ _mt_fe_tn_set_reg(state, 0x37, 0x5e); ++ } ++ */ ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = (buf & 0xef) | 0x30; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ _mt_fe_tn_set_reg(state, 0x41, 0x00); ++ msleep(2); ++ _mt_fe_tn_set_reg(state, 0x41, 0x02); ++ } else { ++ return 1; ++ } ++ return 0; ++} ++ ++static int _mt_fe_tn_set_BB_tc2800(struct m88dc2800_state *state) ++{ ++ return 0; ++} ++ ++ static int _mt_fe_tn_set_appendix_tc2800(struct m88dc2800_state *state) ++ ++{ ++ u8 buf; ++ const u32 freq_KHz = state->tuner_freq; ++ if (state->tuner_mtt == 0xD1) { ++ if ((freq_KHz == 123000) || (freq_KHz == 147000) || ++ (freq_KHz == 171000) || (freq_KHz == 195000)) { ++ _mt_fe_tn_set_reg(state, 0x20, 0x1b); ++ } ++ if ((freq_KHz == 371000) || (freq_KHz == 419000) || ++ (freq_KHz == 610000) || (freq_KHz == 730000) || ++ (freq_KHz == 754000) || (freq_KHz == 826000)) { ++ _mt_fe_tn_get_reg(state, 0x0d, &buf); ++ _mt_fe_tn_set_reg(state, 0x0d, (u8) (buf + 1)); ++ } ++ if ((freq_KHz == 522000) || (freq_KHz == 578000) || ++ (freq_KHz == 634000) || (freq_KHz == 690000) || ++ (freq_KHz == 834000)) { ++ _mt_fe_tn_get_reg(state, 0x0d, &buf); ++ _mt_fe_tn_set_reg(state, 0x0d, (u8) (buf - 1)); ++ } ++ } else if (state->tuner_mtt == 0xE1) { ++ _mt_fe_tn_set_reg(state, 0x20, 0xfc); ++ if (freq_KHz == 123000 || freq_KHz == 147000 || ++ freq_KHz == 171000 || freq_KHz == 195000 || ++ freq_KHz == 219000 || freq_KHz == 267000 || ++ freq_KHz == 291000 || freq_KHz == 339000 || ++ freq_KHz == 387000 || freq_KHz == 435000 || ++ freq_KHz == 482000 || freq_KHz == 530000 || ++ freq_KHz == 722000 || ++ (state->tuner_custom_cfg == 1 && freq_KHz == 315000)) { ++ _mt_fe_tn_set_reg(state, 0x20, 0x5c); ++ } ++ } ++ return 0; ++} ++ ++ static int _mt_fe_tn_set_DAC_tc2800(struct m88dc2800_state *state) ++{ ++ u8 buf, tempnumber; ++ s32 N; ++ s32 f1f2number, f1, f2, delta1, Totalnum1; ++ s32 cntT, cntin, NCOI, z0, z1, z2, tmp; ++ u32 fc, fadc, fsd, f2d; ++ u32 FreqTrue108_Hz; ++ s32 M = state->tuner_crystal / 4000; ++ /* const u8 bandwidth = state->tuner_bandwidth; */ ++ const u16 DAC_fre = 108; ++ const u32 crystal_KHz = state->tuner_crystal; ++ const u32 DACFreq_KHz = state->tuner_dac; ++ const u32 freq_KHz = state->tuner_freq; ++ ++ if (state->tuner_mtt == 0xE1) { ++ _mt_fe_tn_get_reg(state, 0x33, &buf); ++ M = buf & 0x0f; ++ if (M == 0) ++ M = 6; ++ } ++ _mt_fe_tn_get_reg(state, 0x34, &buf); ++ N = buf & 0x07; ++ _mt_fe_tn_get_reg(state, 0x35, &buf); ++ N = (N << 8) + buf; ++ buf = ((N + 256) * crystal_KHz / M / DAC_fre + 500) / 1000; ++ if (state->tuner_mtt == 0xE1) { ++ _mt_fe_tn_set_appendix_tc2800(state); ++ if (freq_KHz == 187000 || freq_KHz == 195000 || ++ freq_KHz == 131000 || freq_KHz == 211000 || ++ freq_KHz == 219000 || freq_KHz == 227000 || ++ freq_KHz == 267000 || freq_KHz == 299000 || ++ freq_KHz == 347000 || freq_KHz == 363000 || ++ freq_KHz == 395000 || freq_KHz == 403000 || ++ freq_KHz == 435000 || freq_KHz == 482000 || ++ freq_KHz == 474000 || freq_KHz == 490000 || ++ freq_KHz == 610000 || freq_KHz == 642000 || ++ freq_KHz == 666000 || freq_KHz == 722000 || ++ freq_KHz == 754000 || ++ ((freq_KHz == 379000 || freq_KHz == 467000 || ++ freq_KHz == 762000) && state->tuner_custom_cfg != 1)) { ++ buf = buf + 1; ++ } ++ if (freq_KHz == 123000 || freq_KHz == 139000 || ++ freq_KHz == 147000 || freq_KHz == 171000 || ++ freq_KHz == 179000 || freq_KHz == 203000 || ++ freq_KHz == 235000 || freq_KHz == 251000 || ++ freq_KHz == 259000 || freq_KHz == 283000 || ++ freq_KHz == 331000 || freq_KHz == 363000 || ++ freq_KHz == 371000 || freq_KHz == 387000 || ++ freq_KHz == 411000 || freq_KHz == 427000 || ++ freq_KHz == 443000 || freq_KHz == 451000 || ++ freq_KHz == 459000 || freq_KHz == 506000 || ++ freq_KHz == 514000 || freq_KHz == 538000 || ++ freq_KHz == 546000 || freq_KHz == 554000 || ++ freq_KHz == 562000 || freq_KHz == 570000 || ++ freq_KHz == 578000 || freq_KHz == 602000 || ++ freq_KHz == 626000 || freq_KHz == 658000 || ++ freq_KHz == 690000 || freq_KHz == 714000 || ++ freq_KHz == 746000 || freq_KHz == 522000 || ++ freq_KHz == 826000 || freq_KHz == 155000 || ++ freq_KHz == 530000 || ++ ((freq_KHz == 275000 || freq_KHz == 355000) && ++ state->tuner_custom_cfg != 1) || ++ ((freq_KHz == 467000 || freq_KHz == 762000 || ++ freq_KHz == 778000 || freq_KHz == 818000) && ++ state->tuner_custom_cfg == 1)) { ++ buf = buf - 1; ++ } ++ } ++ _mt_fe_tn_set_reg(state, 0x0e, buf); ++ _mt_fe_tn_set_reg(state, 0x0d, buf); ++ f1f2number = ++ (((DACFreq_KHz * M * buf) / crystal_KHz) << 16) / (N + 256) + ++ (((DACFreq_KHz * M * buf) % crystal_KHz) << 16) / ((N + 256) * ++ crystal_KHz); ++ _mt_fe_tn_set_reg(state, 0xf1, (f1f2number & 0xff00) >> 8); ++ _mt_fe_tn_set_reg(state, 0xf2, f1f2number & 0x00ff); ++ FreqTrue108_Hz = ++ (N + 256) * crystal_KHz / (M * buf) * 1000 + ++ (((N + 256) * crystal_KHz) % (M * buf)) * 1000 / (M * buf); ++ f1 = 4096; ++ fc = FreqTrue108_Hz; ++ fadc = fc / 4; ++ fsd = 27000000; ++ f2d = state->tuner_bandwidth * 1000 / 2 - 150; ++ f2 = (fsd / 250) * f2d / ((fc + 500) / 1000); ++ delta1 = ((f1 - f2) << 15) / f2; ++ Totalnum1 = ((f1 - f2) << 15) - delta1 * f2; ++ cntT = f2; ++ cntin = Totalnum1; ++ NCOI = delta1; ++ z0 = cntin; ++ z1 = cntT; ++ z2 = NCOI; ++ tempnumber = (z0 & 0xff00) >> 8; ++ _mt_fe_tn_set_reg(state, 0xc9, (u8) (tempnumber & 0x0f)); ++ tempnumber = (z0 & 0xff); ++ _mt_fe_tn_set_reg(state, 0xca, tempnumber); ++ tempnumber = (z1 & 0xff00) >> 8; ++ _mt_fe_tn_set_reg(state, 0xcb, tempnumber); ++ tempnumber = (z1 & 0xff); ++ _mt_fe_tn_set_reg(state, 0xcc, tempnumber); ++ tempnumber = (z2 & 0xff00) >> 8; ++ _mt_fe_tn_set_reg(state, 0xcd, tempnumber); ++ tempnumber = (z2 & 0xff); ++ _mt_fe_tn_set_reg(state, 0xce, tempnumber); ++ tmp = f1; ++ f1 = f2; ++ f2 = tmp / 2; ++ delta1 = ((f1 - f2) << 15) / f2; ++ Totalnum1 = ((f1 - f2) << 15) - delta1 * f2; ++ NCOI = (f1 << 15) / f2 - (1 << 15); ++ cntT = f2; ++ cntin = Totalnum1; ++ z0 = cntin; ++ z1 = cntT; ++ z2 = NCOI; ++ tempnumber = (z0 & 0xff00) >> 8; ++ _mt_fe_tn_set_reg(state, 0xd9, (u8) (tempnumber & 0x0f)); ++ tempnumber = (z0 & 0xff); ++ _mt_fe_tn_set_reg(state, 0xda, tempnumber); ++ tempnumber = (z1 & 0xff00) >> 8; ++ _mt_fe_tn_set_reg(state, 0xdb, tempnumber); ++ tempnumber = (z1 & 0xff); ++ _mt_fe_tn_set_reg(state, 0xdc, tempnumber); ++ tempnumber = (z2 & 0xff00) >> 8; ++ _mt_fe_tn_set_reg(state, 0xdd, tempnumber); ++ tempnumber = (z2 & 0xff); ++ _mt_fe_tn_set_reg(state, 0xde, tempnumber); ++ ++ return 0; ++} ++ ++static int _mt_fe_tn_preset_tc2800(struct m88dc2800_state *state) ++{ ++ if (state->tuner_mtt == 0xD1) { ++ _mt_fe_tn_set_reg(state, 0x19, 0x4a); ++ _mt_fe_tn_set_reg(state, 0x1b, 0x4b); ++ _mt_fe_tn_set_reg(state, 0x04, 0x04); ++ _mt_fe_tn_set_reg(state, 0x17, 0x0d); ++ _mt_fe_tn_set_reg(state, 0x62, 0x6c); ++ _mt_fe_tn_set_reg(state, 0x63, 0xf4); ++ _mt_fe_tn_set_reg(state, 0x1f, 0x0e); ++ _mt_fe_tn_set_reg(state, 0x6b, 0xf4); ++ _mt_fe_tn_set_reg(state, 0x14, 0x01); ++ _mt_fe_tn_set_reg(state, 0x5a, 0x75); ++ _mt_fe_tn_set_reg(state, 0x66, 0x74); ++ _mt_fe_tn_set_reg(state, 0x72, 0xe0); ++ _mt_fe_tn_set_reg(state, 0x70, 0x07); ++ _mt_fe_tn_set_reg(state, 0x15, 0x7b); ++ _mt_fe_tn_set_reg(state, 0x55, 0x71); ++ _mt_fe_tn_set_reg(state, 0x75, 0x55); ++ _mt_fe_tn_set_reg(state, 0x76, 0xac); ++ _mt_fe_tn_set_reg(state, 0x77, 0x6c); ++ _mt_fe_tn_set_reg(state, 0x78, 0x8b); ++ _mt_fe_tn_set_reg(state, 0x79, 0x42); ++ _mt_fe_tn_set_reg(state, 0x7a, 0xd2); ++ _mt_fe_tn_set_reg(state, 0x81, 0x01); ++ _mt_fe_tn_set_reg(state, 0x82, 0x00); ++ _mt_fe_tn_set_reg(state, 0x82, 0x02); ++ _mt_fe_tn_set_reg(state, 0x82, 0x04); ++ _mt_fe_tn_set_reg(state, 0x82, 0x06); ++ _mt_fe_tn_set_reg(state, 0x82, 0x08); ++ _mt_fe_tn_set_reg(state, 0x82, 0x09); ++ _mt_fe_tn_set_reg(state, 0x82, 0x29); ++ _mt_fe_tn_set_reg(state, 0x82, 0x49); ++ _mt_fe_tn_set_reg(state, 0x82, 0x58); ++ _mt_fe_tn_set_reg(state, 0x82, 0x59); ++ _mt_fe_tn_set_reg(state, 0x82, 0x98); ++ _mt_fe_tn_set_reg(state, 0x82, 0x99); ++ _mt_fe_tn_set_reg(state, 0x10, 0x05); ++ _mt_fe_tn_set_reg(state, 0x10, 0x0d); ++ _mt_fe_tn_set_reg(state, 0x11, 0x95); ++ _mt_fe_tn_set_reg(state, 0x11, 0x9d); ++ if (state->tuner_loopthrough != 0) { ++ _mt_fe_tn_set_reg(state, 0x67, 0x25); ++ } else { ++ _mt_fe_tn_set_reg(state, 0x67, 0x05); ++ } ++ } else if (state->tuner_mtt == 0xE1) { ++ _mt_fe_tn_set_reg(state, 0x1b, 0x47); ++ if (state->tuner_mode == 0) { /* DVB-C */ ++ _mt_fe_tn_set_reg(state, 0x66, 0x74); ++ _mt_fe_tn_set_reg(state, 0x62, 0x2c); ++ _mt_fe_tn_set_reg(state, 0x63, 0x54); ++ _mt_fe_tn_set_reg(state, 0x68, 0x0b); ++ _mt_fe_tn_set_reg(state, 0x14, 0x00); ++ } else { /* CTTB */ ++ _mt_fe_tn_set_reg(state, 0x66, 0x74); ++ _mt_fe_tn_set_reg(state, 0x62, 0x0c); ++ _mt_fe_tn_set_reg(state, 0x63, 0x54); ++ _mt_fe_tn_set_reg(state, 0x68, 0x0b); ++ _mt_fe_tn_set_reg(state, 0x14, 0x05); ++ } ++ _mt_fe_tn_set_reg(state, 0x6f, 0x00); ++ _mt_fe_tn_set_reg(state, 0x84, 0x04); ++ _mt_fe_tn_set_reg(state, 0x5e, 0xbe); ++ _mt_fe_tn_set_reg(state, 0x87, 0x07); ++ _mt_fe_tn_set_reg(state, 0x8a, 0x1f); ++ _mt_fe_tn_set_reg(state, 0x8b, 0x1f); ++ _mt_fe_tn_set_reg(state, 0x88, 0x30); ++ _mt_fe_tn_set_reg(state, 0x58, 0x34); ++ _mt_fe_tn_set_reg(state, 0x61, 0x8c); ++ _mt_fe_tn_set_reg(state, 0x6a, 0x42); ++ } ++ return 0; ++} ++ ++static int mt_fe_tn_wakeup_tc2800(struct m88dc2800_state *state) ++{ ++ _mt_fe_tn_set_reg(state, 0x16, 0xb1); ++ _mt_fe_tn_set_reg(state, 0x09, 0x7d); ++ return 0; ++} ++ ++ static int mt_fe_tn_sleep_tc2800(struct m88dc2800_state *state) ++{ ++ _mt_fe_tn_set_reg(state, 0x16, 0xb0); ++ _mt_fe_tn_set_reg(state, 0x09, 0x6d); ++ return 0; ++} ++ ++ static int mt_fe_tn_init_tc2800(struct m88dc2800_state *state) ++{ ++ if (state->tuner_init_OK != 1) { ++ state->tuner_dev_addr = 0x61; /* TUNER_I2C_ADDR_TC2800 */ ++ state->tuner_freq = 650000; ++ state->tuner_qam = 0; ++ state->tuner_mode = 0; // 0: DVB-C, 1: CTTB ++ state->tuner_bandwidth = 8; ++ state->tuner_loopthrough = 0; ++ state->tuner_crystal = 24000; ++ state->tuner_dac = 7200; ++ state->tuner_mtt = 0x00; ++ state->tuner_custom_cfg = 0; ++ state->tuner_version = 30022; /* Driver version number */ ++ state->tuner_time = 12092611; ++ state->tuner_init_OK = 1; ++ } ++ _mt_fe_tn_set_reg(state, 0x2b, 0x46); ++ _mt_fe_tn_set_reg(state, 0x2c, 0x75); ++ if (state->tuner_mtt == 0x00) { ++ u8 tmp = 0; ++ _mt_fe_tn_get_reg(state, 0x01, &tmp); ++ printk(KERN_INFO "m88dc2800: tuner id = 0x%02x ", tmp); ++ switch (tmp) { ++ case 0x0d: ++ state->tuner_mtt = 0xD1; ++ break; ++ case 0x8e: ++ default: ++ state->tuner_mtt = 0xE1; ++ break; ++ } ++ } ++ return 0; ++} ++ ++ static int mt_fe_tn_set_freq_tc2800(struct m88dc2800_state *state, ++ u32 freq_KHz) ++{ ++ u8 buf; ++ u8 buf1; ++ ++ mt_fe_tn_init_tc2800(state); ++ state->tuner_freq = freq_KHz; ++ _mt_fe_tn_set_reg(state, 0x21, freq_KHz > 500000 ? 0xb9 : 0x99); ++ mt_fe_tn_wakeup_tc2800(state); ++ _mt_fe_tn_set_reg(state, 0x05, 0x7f); ++ _mt_fe_tn_set_reg(state, 0x06, 0xf8); ++ _mt_fe_tn_set_RF_front_tc2800(state); ++ _mt_fe_tn_set_PLL_freq_tc2800(state); ++ _mt_fe_tn_set_DAC_tc2800(state); ++ _mt_fe_tn_set_BB_tc2800(state); ++ _mt_fe_tn_preset_tc2800(state); ++ _mt_fe_tn_set_reg(state, 0x05, 0x00); ++ _mt_fe_tn_set_reg(state, 0x06, 0x00); ++ if (state->tuner_mtt == 0xD1) { ++ _mt_fe_tn_set_reg(state, 0x00, 0x01); ++ _mt_fe_tn_set_reg(state, 0x00, 0x00); ++ msleep(5); ++ _mt_fe_tn_set_reg(state, 0x41, 0x00); ++ msleep(5); ++ _mt_fe_tn_set_reg(state, 0x41, 0x02); ++ ++ _mt_fe_tn_get_reg(state, 0x69, &buf1); ++ buf1 = buf1 & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x61, &buf); ++ buf = buf & 0x0f; ++ if (buf == 0x0c) ++ _mt_fe_tn_set_reg(state, 0x6a, 0x59); ++ if (buf1 > 0x02) { ++ if (freq_KHz > 600000) ++ _mt_fe_tn_set_reg(state, 0x66, 0x44); ++ else if (freq_KHz > 500000) ++ _mt_fe_tn_set_reg(state, 0x66, 0x64); ++ else ++ _mt_fe_tn_set_reg(state, 0x66, 0x74); ++ } ++ if (buf1 < 0x03) { ++ if (freq_KHz > 800000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x64); ++ else if (freq_KHz > 600000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ else if (freq_KHz > 500000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ else if (freq_KHz > 300000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x43); ++ else if (freq_KHz > 220000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ else if (freq_KHz > 110000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x14); ++ else ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ msleep(5); ++ } else if (buf < 0x0c) { ++ if (freq_KHz > 800000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x14); ++ else if (freq_KHz > 600000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x14); ++ else if (freq_KHz > 500000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x34); ++ else if (freq_KHz > 300000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x43); ++ else if (freq_KHz > 220000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ else if (freq_KHz > 110000) ++ _mt_fe_tn_set_reg(state, 0x87, 0x14); ++ else ++ _mt_fe_tn_set_reg(state, 0x87, 0x54); ++ msleep(5); ++ } ++ } else if ((state->tuner_mtt == 0xE1)) { ++ _mt_fe_tn_set_reg(state, 0x00, 0x01); ++ _mt_fe_tn_set_reg(state, 0x00, 0x00); ++ msleep(20); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = (buf & 0xef) | 0x28; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ msleep(50); ++ _mt_fe_tn_get_reg(state, 0x38, &buf); ++ _mt_fe_tn_set_reg(state, 0x38, buf); ++ _mt_fe_tn_get_reg(state, 0x32, &buf); ++ buf = (buf & 0xf7) | 0x10; ++ _mt_fe_tn_set_reg(state, 0x32, buf); ++ msleep(10); ++ _mt_fe_tn_get_reg(state, 0x69, &buf); ++ buf = buf & 0x03; ++ _mt_fe_tn_set_reg(state, 0x2a, buf); ++ if (buf > 0) { ++ msleep(20); ++ _mt_fe_tn_get_reg(state, 0x84, &buf); ++ buf = buf & 0x1f; ++ _mt_fe_tn_set_reg(state, 0x68, 0x0a); ++ _mt_fe_tn_get_reg(state, 0x88, &buf1); ++ buf1 = buf1 & 0x1f; ++ if (buf <= buf1) ++ _mt_fe_tn_set_reg(state, 0x66, 0x44); ++ else ++ _mt_fe_tn_set_reg(state, 0x66, 0x74); ++ } else { ++ if (freq_KHz <= 600000) ++ _mt_fe_tn_set_reg(state, 0x68, 0x0c); ++ else ++ _mt_fe_tn_set_reg(state, 0x68, 0x0e); ++ _mt_fe_tn_set_reg(state, 0x30, 0xfb); ++ _mt_fe_tn_set_reg(state, 0x30, 0xff); ++ _mt_fe_tn_set_reg(state, 0x31, 0x04); ++ _mt_fe_tn_set_reg(state, 0x31, 0x00); ++ } ++ if (state->tuner_loopthrough != 0) { ++ _mt_fe_tn_get_reg(state, 0x28, &buf); ++ if (buf == 0) { ++ _mt_fe_tn_set_reg(state, 0x28, 0xff); ++ _mt_fe_tn_get_reg(state, 0x61, &buf); ++ buf = buf & 0x0f; ++ if (buf > 9) ++ _mt_fe_tn_set_reg(state, 0x67, 0x74); ++ else if (buf > 6) ++ _mt_fe_tn_set_reg(state, 0x67, 0x64); ++ else if (buf > 3) ++ _mt_fe_tn_set_reg(state, 0x67, 0x54); ++ else ++ _mt_fe_tn_set_reg(state, 0x67, 0x44); ++ } ++ } else { ++ _mt_fe_tn_set_reg(state, 0x67, 0x34); ++ } ++ } else { ++ return 1; ++ } ++ return 0; ++} ++ ++ ++/* ++static int mt_fe_tn_set_BB_filter_band_tc2800(struct m88dc2800_state *state, ++ u8 bandwidth) ++{ ++ u8 buf, tmp; ++ ++ _mt_fe_tn_get_reg(state, 0x53, &tmp); ++ ++ if (bandwidth == 6) ++ buf = 0x01 << 1; ++ else if (bandwidth == 7) ++ buf = 0x02 << 1; ++ else if (bandwidth == 8) ++ buf = 0x04 << 1; ++ else ++ buf = 0x04 << 1; ++ ++ tmp &= 0xf1; ++ tmp |= buf; ++ _mt_fe_tn_set_reg(state, 0x53, tmp); ++ state->tuner_bandwidth = bandwidth; ++ return 0; ++} ++*/ ++ ++static s32 mt_fe_tn_get_signal_strength_tc2800(struct m88dc2800_state ++ *state) ++{ ++ s32 level = -107; ++ s32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; ++ s32 val1, val2, val; ++ s32 result2, result3, result4, result5, result6; ++ s32 append; ++ u8 tmp; ++ s32 freq_KHz = (s32) state->tuner_freq; ++ if (state->tuner_mtt == 0xD1) { ++ _mt_fe_tn_get_reg(state, 0x61, &tmp); ++ tmp1 = tmp & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x69, &tmp); ++ tmp2 = tmp & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x73, &tmp); ++ tmp3 = tmp & 0x07; ++ _mt_fe_tn_get_reg(state, 0x7c, &tmp); ++ tmp4 = (tmp >> 4) & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x7b, &tmp); ++ tmp5 = tmp & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x7f, &tmp); ++ tmp6 = (tmp >> 5) & 0x01; ++ if (tmp1 > 6) { ++ val1 = 0; ++ if (freq_KHz <= 200000) { ++ val2 = (tmp1 - 6) * 267; ++ } else if (freq_KHz <= 600000) { ++ val2 = (tmp1 - 6) * 280; ++ } else { ++ val2 = (tmp1 - 6) * 290; ++ } ++ val = val1 + val2; ++ } else { ++ if (tmp1 == 0) { ++ val1 = -550; ++ } else { ++ val1 = 0; ++ } ++ if ((tmp1 < 4) && (freq_KHz >= 506000)) { ++ val1 = -850; ++ } ++ val2 = 0; ++ val = val1 + val2; ++ } ++ if (freq_KHz <= 95000) { ++ result2 = tmp2 * 289; ++ } else if (freq_KHz <= 155000) { ++ result2 = tmp2 * 278; ++ } else if (freq_KHz <= 245000) { ++ result2 = tmp2 * 267; ++ } else if (freq_KHz <= 305000) { ++ result2 = tmp2 * 256; ++ } else if (freq_KHz <= 335000) { ++ result2 = tmp2 * 244; ++ } else if (freq_KHz <= 425000) { ++ result2 = tmp2 * 233; ++ } else if (freq_KHz <= 575000) { ++ result2 = tmp2 * 222; ++ } else if (freq_KHz <= 665000) { ++ result2 = tmp2 * 211; ++ } else { ++ result2 = tmp2 * 200; ++ } ++ result3 = (6 - tmp3) * 100; ++ result4 = 300 * tmp4; ++ result5 = 50 * tmp5; ++ result6 = 300 * tmp6; ++ if (freq_KHz < 105000) { ++ append = -450; ++ } else if (freq_KHz <= 227000) { ++ append = -4 * (freq_KHz / 1000 - 100) + 150; ++ } else if (freq_KHz <= 305000) { ++ append = -4 * (freq_KHz / 1000 - 100); ++ } else if (freq_KHz <= 419000) { ++ append = 500 - 40 * (freq_KHz / 1000 - 300) / 17 + 130; ++ } else if (freq_KHz <= 640000) { ++ append = 500 - 40 * (freq_KHz / 1000 - 300) / 17; ++ } else { ++ append = -500; ++ } ++ level = append - (val + result2 + result3 + result4 + ++ result5 + result6); ++ level /= 100; ++ } else if (state->tuner_mtt == 0xE1) { ++ _mt_fe_tn_get_reg(state, 0x61, &tmp); ++ tmp1 = tmp & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x84, &tmp); ++ tmp2 = tmp & 0x1f; ++ _mt_fe_tn_get_reg(state, 0x69, &tmp); ++ tmp3 = tmp & 0x03; ++ _mt_fe_tn_get_reg(state, 0x73, &tmp); ++ tmp4 = tmp & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x7c, &tmp); ++ tmp5 = (tmp >> 4) & 0x0f; ++ _mt_fe_tn_get_reg(state, 0x7b, &tmp); ++ tmp6 = tmp & 0x0f; ++ if (freq_KHz < 151000) { ++ result2 = (1150 - freq_KHz / 100) * 163 / 33 + 4230; ++ result3 = (1150 - freq_KHz / 100) * 115 / 33 + 1850; ++ result4 = -3676 * (freq_KHz / 1000) / 100 + 6115; ++ } else if (freq_KHz < 257000) { ++ result2 = (1540 - freq_KHz / 100) * 11 / 4 + 3870; ++ result3 = (1540 - freq_KHz / 100) * 205 / 96 + 2100; ++ result4 = -21 * freq_KHz / 1000 + 5084; ++ } else if (freq_KHz < 305000) { ++ result2 = (2620 - freq_KHz / 100) * 5 / 3 + 2770; ++ result3 = (2620 - freq_KHz / 100) * 10 / 7 + 1700; ++ result4 = 650; ++ } else if (freq_KHz < 449000) { ++ result2 = (307 - freq_KHz / 1000) * 82 / 27 + 11270; ++ result3 = (3100 - freq_KHz / 100) * 5 / 3 + 10000; ++ result4 = 134 * freq_KHz / 10000 + 11875; ++ } else { ++ result2 = (307 - freq_KHz / 1000) * 82 / 27 + 11270; ++ result3 = 8400; ++ result4 = 5300; ++ } ++ if (tmp1 > 6) { ++ val1 = result2; ++ val2 = 2900; ++ val = 500; ++ } else if (tmp1 > 0) { ++ val1 = result3; ++ val2 = 2700; ++ val = 500; ++ } else { ++ val1 = result4; ++ val2 = 2700; ++ val = 400; ++ } ++ level = val1 - (val2 * tmp1 + 500 * tmp2 + 3000 * tmp3 - ++ 500 * tmp4 + 3000 * tmp5 + val * tmp6) - 1000; ++ level /= 1000; ++ } ++ return level; ++} ++ ++ ++/* m88dc2800 operation functions */ ++u8 M88DC2000GetLock(struct m88dc2800_state * state) ++{ ++ u8 u8ret = 0; ++ if (ReadReg(state, 0x80) < 0x06) { ++ if ((ReadReg(state, 0xdf) & 0x80) == 0x80 ++ &&(ReadReg(state, 0x91) & 0x23) == 0x03 ++ &&(ReadReg(state, 0x43) & 0x08) == 0x08) ++ u8ret = 1; ++ else ++ u8ret = 0; ++ } else { ++ if ((ReadReg(state, 0x85) & 0x08) == 0x08) ++ u8ret = 1; ++ else ++ u8ret = 0; ++ } ++ dprintk("%s, lock=%d\n", __func__, u8ret); ++ return u8ret; ++} ++ ++static int M88DC2000SetTsType(struct m88dc2800_state *state, u8 type) ++{ ++ u8 regC2H; ++ ++ if (type == 3) { ++ WriteReg(state, 0x84, 0x6A); ++ WriteReg(state, 0xC0, 0x43); ++ WriteReg(state, 0xE2, 0x06); ++ regC2H = ReadReg(state, 0xC2); ++ regC2H &= 0xC0; ++ regC2H |= 0x1B; ++ WriteReg(state, 0xC2, regC2H); ++ WriteReg(state, 0xC1, 0x60); /* common interface */ ++ } else if (type == 1) { ++ WriteReg(state, 0x84, 0x6A); ++ WriteReg(state, 0xC0, 0x47); /* serial format */ ++ WriteReg(state, 0xE2, 0x02); ++ regC2H = ReadReg(state, 0xC2); ++ regC2H &= 0xC7; ++ WriteReg(state, 0xC2, regC2H); ++ WriteReg(state, 0xC1, 0x00); ++ } else { ++ WriteReg(state, 0x84, 0x6C); ++ WriteReg(state, 0xC0, 0x43); /* parallel format */ ++ WriteReg(state, 0xE2, 0x06); ++ regC2H = ReadReg(state, 0xC2); ++ regC2H &= 0xC7; ++ WriteReg(state, 0xC2, regC2H); ++ WriteReg(state, 0xC1, 0x00); ++ } ++ return 0; ++} ++ ++static int M88DC2000RegInitial_TC2800(struct m88dc2800_state *state) ++{ ++ u8 RegE3H, RegE4H; ++ ++ WriteReg(state, 0x00, 0x48); ++ WriteReg(state, 0x01, 0x09); ++ WriteReg(state, 0xFB, 0x0A); ++ WriteReg(state, 0xFC, 0x0B); ++ WriteReg(state, 0x02, 0x0B); ++ WriteReg(state, 0x03, 0x18); ++ WriteReg(state, 0x05, 0x0D); ++ WriteReg(state, 0x36, 0x80); ++ WriteReg(state, 0x43, 0x40); ++ WriteReg(state, 0x55, 0x7A); ++ WriteReg(state, 0x56, 0xD9); ++ WriteReg(state, 0x57, 0xDF); ++ WriteReg(state, 0x58, 0x39); ++ WriteReg(state, 0x5A, 0x00); ++ WriteReg(state, 0x5C, 0x71); ++ WriteReg(state, 0x5D, 0x23); ++ WriteReg(state, 0x86, 0x40); ++ WriteReg(state, 0xF9, 0x08); ++ WriteReg(state, 0x61, 0x40); ++ WriteReg(state, 0x62, 0x0A); ++ WriteReg(state, 0x90, 0x06); ++ WriteReg(state, 0xDE, 0x00); ++ WriteReg(state, 0xA0, 0x03); ++ WriteReg(state, 0xDF, 0x81); ++ WriteReg(state, 0xFA, 0x40); ++ WriteReg(state, 0x37, 0x10); ++ WriteReg(state, 0xF0, 0x40); ++ WriteReg(state, 0xF2, 0x9C); ++ WriteReg(state, 0xF3, 0x40); ++ RegE3H = ReadReg(state, 0xE3); ++ RegE4H = ReadReg(state, 0xE4); ++ if (((RegE3H & 0xC0) == 0x00) && ((RegE4H & 0xC0) == 0x00)) { ++ WriteReg(state, 0x30, 0xFF); ++ WriteReg(state, 0x31, 0x00); ++ WriteReg(state, 0x32, 0x00); ++ WriteReg(state, 0x33, 0x00); ++ WriteReg(state, 0x35, 0x32); ++ WriteReg(state, 0x40, 0x00); ++ WriteReg(state, 0x41, 0x10); ++ WriteReg(state, 0xF1, 0x02); ++ WriteReg(state, 0xF4, 0x04); ++ WriteReg(state, 0xF5, 0x00); ++ WriteReg(state, 0x42, 0x14); ++ WriteReg(state, 0xE1, 0x25); ++ } else if (((RegE3H & 0xC0) == 0x80) && ((RegE4H & 0xC0) == 0x40)) { ++ WriteReg(state, 0x30, 0xFF); ++ WriteReg(state, 0x31, 0x00); ++ WriteReg(state, 0x32, 0x00); ++ WriteReg(state, 0x33, 0x00); ++ WriteReg(state, 0x35, 0x32); ++ WriteReg(state, 0x39, 0x00); ++ WriteReg(state, 0x3A, 0x00); ++ WriteReg(state, 0x40, 0x00); ++ WriteReg(state, 0x41, 0x10); ++ WriteReg(state, 0xF1, 0x00); ++ WriteReg(state, 0xF4, 0x00); ++ WriteReg(state, 0xF5, 0x40); ++ WriteReg(state, 0x42, 0x14); ++ WriteReg(state, 0xE1, 0x25); ++ } else if ((RegE3H == 0x80 || RegE3H == 0x81) ++ && (RegE4H == 0x80 || RegE4H == 0x81)) { ++ WriteReg(state, 0x30, 0xFF); ++ WriteReg(state, 0x31, 0x00); ++ WriteReg(state, 0x32, 0x00); ++ WriteReg(state, 0x33, 0x00); ++ WriteReg(state, 0x35, 0x32); ++ WriteReg(state, 0x39, 0x00); ++ WriteReg(state, 0x3A, 0x00); ++ WriteReg(state, 0xF1, 0x00); ++ WriteReg(state, 0xF4, 0x00); ++ WriteReg(state, 0xF5, 0x40); ++ WriteReg(state, 0x42, 0x24); ++ WriteReg(state, 0xE1, 0x25); ++ WriteReg(state, 0x92, 0x7F); ++ WriteReg(state, 0x93, 0x91); ++ WriteReg(state, 0x95, 0x00); ++ WriteReg(state, 0x2B, 0x33); ++ WriteReg(state, 0x2A, 0x2A); ++ WriteReg(state, 0x2E, 0x80); ++ WriteReg(state, 0x25, 0x25); ++ WriteReg(state, 0x2D, 0xFF); ++ WriteReg(state, 0x26, 0xFF); ++ WriteReg(state, 0x27, 0x00); ++ WriteReg(state, 0x24, 0x25); ++ WriteReg(state, 0xA4, 0xFF); ++ WriteReg(state, 0xA3, 0x0D); ++ } else { ++ WriteReg(state, 0x30, 0xFF); ++ WriteReg(state, 0x31, 0x00); ++ WriteReg(state, 0x32, 0x00); ++ WriteReg(state, 0x33, 0x00); ++ WriteReg(state, 0x35, 0x32); ++ WriteReg(state, 0x39, 0x00); ++ WriteReg(state, 0x3A, 0x00); ++ WriteReg(state, 0xF1, 0x00); ++ WriteReg(state, 0xF4, 0x00); ++ WriteReg(state, 0xF5, 0x40); ++ WriteReg(state, 0x42, 0x24); ++ WriteReg(state, 0xE1, 0x27); ++ WriteReg(state, 0x92, 0x7F); ++ WriteReg(state, 0x93, 0x91); ++ WriteReg(state, 0x95, 0x00); ++ WriteReg(state, 0x2B, 0x33); ++ WriteReg(state, 0x2A, 0x2A); ++ WriteReg(state, 0x2E, 0x80); ++ WriteReg(state, 0x25, 0x25); ++ WriteReg(state, 0x2D, 0xFF); ++ WriteReg(state, 0x26, 0xFF); ++ WriteReg(state, 0x27, 0x00); ++ WriteReg(state, 0x24, 0x25); ++ WriteReg(state, 0xA4, 0xFF); ++ WriteReg(state, 0xA3, 0x10); ++ } ++ WriteReg(state, 0xF6, 0x4E); ++ WriteReg(state, 0xF7, 0x20); ++ WriteReg(state, 0x89, 0x02); ++ WriteReg(state, 0x14, 0x08); ++ WriteReg(state, 0x6F, 0x0D); ++ WriteReg(state, 0x10, 0xFF); ++ WriteReg(state, 0x11, 0x00); ++ WriteReg(state, 0x12, 0x30); ++ WriteReg(state, 0x13, 0x23); ++ WriteReg(state, 0x60, 0x00); ++ WriteReg(state, 0x69, 0x00); ++ WriteReg(state, 0x6A, 0x03); ++ WriteReg(state, 0xE0, 0x75); ++ WriteReg(state, 0x8D, 0x29); ++ WriteReg(state, 0x4E, 0xD8); ++ WriteReg(state, 0x88, 0x80); ++ WriteReg(state, 0x52, 0x79); ++ WriteReg(state, 0x53, 0x03); ++ WriteReg(state, 0x59, 0x30); ++ WriteReg(state, 0x5E, 0x02); ++ WriteReg(state, 0x5F, 0x0F); ++ WriteReg(state, 0x71, 0x03); ++ WriteReg(state, 0x72, 0x12); ++ WriteReg(state, 0x73, 0x12); ++ ++ return 0; ++} ++ ++static int M88DC2000AutoTSClock_P(struct m88dc2800_state *state, u32 sym, ++ u16 qam) ++{ ++ u32 dataRate; ++ u8 clk_div, value; ++ printk(KERN_INFO ++ "m88dc2800: M88DC2000AutoTSClock_P, symrate=%d qam=%d\n", ++ sym, qam); ++ switch (qam) { ++ case 16: ++ dataRate = 4; ++ break; ++ case 32: ++ dataRate = 5; ++ break; ++ case 128: ++ dataRate = 7; ++ break; ++ case 256: ++ dataRate = 8; ++ break; ++ case 64: ++ default: ++ dataRate = 6; ++ break; ++ } ++ dataRate *= sym * 105; ++ dataRate /= 800; ++ if (dataRate <= 4115) ++ clk_div = 0x05; ++ else if (dataRate <= 4800) ++ clk_div = 0x04; ++ else if (dataRate <= 5760) ++ clk_div = 0x03; ++ else if (dataRate <= 7200) ++ clk_div = 0x02; ++ else if (dataRate <= 9600) ++ clk_div = 0x01; ++ else ++ clk_div = 0x00; ++ value = ReadReg(state, 0xC2); ++ value &= 0xc0; ++ value |= clk_div; ++ WriteReg(state, 0xC2, value); ++ return 0; ++} ++ ++static int M88DC2000AutoTSClock_C(struct m88dc2800_state *state, u32 sym, ++ u16 qam) ++{ ++ u32 dataRate; ++ u8 clk_div, value; ++ printk(KERN_INFO ++ "m88dc2800: M88DC2000AutoTSClock_C, symrate=%d qam=%d\n", ++ sym, qam); ++ switch (qam) { ++ case 16: ++ dataRate = 4; ++ break; ++ case 32: ++ dataRate = 5; ++ break; ++ case 128: ++ dataRate = 7; ++ break; ++ case 256: ++ dataRate = 8; ++ break; ++ case 64: ++ default: ++ dataRate = 6; ++ break; ++ } ++ dataRate *= sym * 105; ++ dataRate /= 800; ++ if (dataRate <= 4115) ++ clk_div = 0x3F; ++ else if (dataRate <= 4800) ++ clk_div = 0x36; ++ else if (dataRate <= 5760) ++ clk_div = 0x2D; ++ else if (dataRate <= 7200) ++ clk_div = 0x24; ++ else if (dataRate <= 9600) ++ clk_div = 0x1B; ++ else ++ clk_div = 0x12; ++ value = ReadReg(state, 0xC2); ++ value &= 0xc0; ++ value |= clk_div; ++ WriteReg(state, 0xC2, value); ++ return 0; ++} ++ ++static int M88DC2000SetTxMode(struct m88dc2800_state *state, u8 inverted, ++ u8 j83) ++{ ++ u8 value = 0; ++ if (inverted) ++ value |= 0x08; /* spectrum inverted */ ++ if (j83) ++ value |= 0x01; /* J83C */ ++ WriteReg(state, 0x83, value); ++ return 0; ++} ++ ++static int M88DC2000SoftReset(struct m88dc2800_state *state) ++{ ++ WriteReg(state, 0x80, 0x01); ++ WriteReg(state, 0x82, 0x00); ++ msleep(1); ++ WriteReg(state, 0x80, 0x00); ++ return 0; ++} ++ ++static int M88DC2000SetSym(struct m88dc2800_state *state, u32 sym, u32 xtal) ++{ ++ u8 value; ++ u8 reg6FH, reg12H; ++ u64 fValue; ++ u32 dwValue; ++ ++ printk(KERN_INFO "%s, sym=%d, xtal=%d\n", __func__, sym, xtal); ++ fValue = 4294967296 * (sym + 10); ++ do_div(fValue, xtal); ++ ++ /* fValue = 4294967296 * (sym + 10) / xtal; */ ++ dwValue = (u32) fValue; ++ printk(KERN_INFO "%s, fvalue1=%x\n", __func__, dwValue); ++ WriteReg(state, 0x58, (u8) ((dwValue >> 24) & 0xff)); ++ WriteReg(state, 0x57, (u8) ((dwValue >> 16) & 0xff)); ++ WriteReg(state, 0x56, (u8) ((dwValue >> 8) & 0xff)); ++ WriteReg(state, 0x55, (u8) ((dwValue >> 0) & 0xff)); ++ ++ /* fValue = 2048 * xtal / sym; */ ++ fValue = 2048 * xtal; ++ do_div(fValue, sym); ++ dwValue = (u32) fValue; ++ printk(KERN_INFO "%s, fvalue2=%x\n", __func__, dwValue); ++ WriteReg(state, 0x5D, (u8) ((dwValue >> 8) & 0xff)); ++ WriteReg(state, 0x5C, (u8) ((dwValue >> 0) & 0xff)); ++ value = ReadReg(state, 0x5A); ++ if (((dwValue >> 16) & 0x0001) == 0) ++ value &= 0x7F; ++ else ++ value |= 0x80; ++ WriteReg(state, 0x5A, value); ++ value = ReadReg(state, 0x89); ++ if (sym <= 1800) ++ value |= 0x01; ++ else ++ value &= 0xFE; ++ WriteReg(state, 0x89, value); ++ if (sym >= 6700) { ++ reg6FH = 0x0D; ++ reg12H = 0x30; ++ } else if (sym >= 4000) { ++ fValue = 22 * 4096 / sym; ++ reg6FH = (u8) fValue; ++ reg12H = 0x30; ++ } else if (sym >= 2000) { ++ fValue = 14 * 4096 / sym; ++ reg6FH = (u8) fValue; ++ reg12H = 0x20; ++ } else { ++ fValue = 7 * 4096 / sym; ++ reg6FH = (u8) fValue; ++ reg12H = 0x10; ++ } ++ WriteReg(state, 0x6F, reg6FH); ++ WriteReg(state, 0x12, reg12H); ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) ++ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { ++ if (sym < 3000) { ++ WriteReg(state, 0x6C, 0x16); ++ WriteReg(state, 0x6D, 0x10); ++ WriteReg(state, 0x6E, 0x18); ++ } else { ++ WriteReg(state, 0x6C, 0x14); ++ WriteReg(state, 0x6D, 0x0E); ++ WriteReg(state, 0x6E, 0x36); ++ } ++ } else { ++ WriteReg(state, 0x6C, 0x16); ++ WriteReg(state, 0x6D, 0x10); ++ WriteReg(state, 0x6E, 0x18); ++ } ++ return 0; ++} ++ ++static int M88DC2000SetQAM(struct m88dc2800_state *state, u16 qam) ++{ ++ u8 reg00H, reg4AH, regC2H, reg44H, reg4CH, reg4DH, reg74H, value; ++ u8 reg8BH, reg8EH; ++ printk(KERN_INFO "%s, qam=%d\n", __func__, qam); ++ regC2H = ReadReg(state, 0xC2); ++ regC2H &= 0xF8; ++ switch (qam) { ++ case 16: /* 16 QAM */ ++ reg00H = 0x08; ++ reg4AH = 0x0F; ++ regC2H |= 0x02; ++ reg44H = 0xAA; ++ reg4CH = 0x0C; ++ reg4DH = 0xF7; ++ reg74H = 0x0E; ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) ++ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { ++ reg8BH = 0x5A; ++ reg8EH = 0xBD; ++ } else { ++ reg8BH = 0x5B; ++ reg8EH = 0x9D; ++ } ++ WriteReg(state, 0x6E, 0x18); ++ break; ++ case 32: /* 32 QAM */ ++ reg00H = 0x18; ++ reg4AH = 0xFB; ++ regC2H |= 0x02; ++ reg44H = 0xAA; ++ reg4CH = 0x0C; ++ reg4DH = 0xF7; ++ reg74H = 0x0E; ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) ++ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { ++ reg8BH = 0x5A; ++ reg8EH = 0xBD; ++ } else { ++ reg8BH = 0x5B; ++ reg8EH = 0x9D; ++ } ++ WriteReg(state, 0x6E, 0x18); ++ break; ++ case 64: /* 64 QAM */ ++ reg00H = 0x48; ++ reg4AH = 0xCD; ++ regC2H |= 0x02; ++ reg44H = 0xAA; ++ reg4CH = 0x0C; ++ reg4DH = 0xF7; ++ reg74H = 0x0E; ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) ++ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { ++ reg8BH = 0x5A; ++ reg8EH = 0xBD; ++ } else { ++ reg8BH = 0x5B; ++ reg8EH = 0x9D; ++ } ++ break; ++ case 128: /* 128 QAM */ ++ reg00H = 0x28; ++ reg4AH = 0xFF; ++ regC2H |= 0x02; ++ reg44H = 0xA9; ++ reg4CH = 0x08; ++ reg4DH = 0xF5; ++ reg74H = 0x0E; ++ reg8BH = 0x5B; ++ reg8EH = 0x9D; ++ break; ++ case 256: /* 256 QAM */ ++ reg00H = 0x38; ++ reg4AH = 0xCD; ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) ++ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { ++ regC2H |= 0x02; ++ } else { ++ regC2H |= 0x01; ++ } ++ reg44H = 0xA9; ++ reg4CH = 0x08; ++ reg4DH = 0xF5; ++ reg74H = 0x0E; ++ reg8BH = 0x5B; ++ reg8EH = 0x9D; ++ break; ++ default: /* 64 QAM */ ++ reg00H = 0x48; ++ reg4AH = 0xCD; ++ regC2H |= 0x02; ++ reg44H = 0xAA; ++ reg4CH = 0x0C; ++ reg4DH = 0xF7; ++ reg74H = 0x0E; ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) ++ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) { ++ reg8BH = 0x5A; ++ reg8EH = 0xBD; ++ } else { ++ reg8BH = 0x5B; ++ reg8EH = 0x9D; ++ } ++ break; ++ } ++ WriteReg(state, 0x00, reg00H); ++ value = ReadReg(state, 0x88); ++ value |= 0x08; ++ WriteReg(state, 0x88, value); ++ WriteReg(state, 0x4B, 0xFF); ++ WriteReg(state, 0x4A, reg4AH); ++ value &= 0xF7; ++ WriteReg(state, 0x88, value); ++ WriteReg(state, 0xC2, regC2H); ++ WriteReg(state, 0x44, reg44H); ++ WriteReg(state, 0x4C, reg4CH); ++ WriteReg(state, 0x4D, reg4DH); ++ WriteReg(state, 0x74, reg74H); ++ WriteReg(state, 0x8B, reg8BH); ++ WriteReg(state, 0x8E, reg8EH); ++ return 0; ++} ++ ++static int M88DC2000WriteTuner_TC2800(struct m88dc2800_state *state, ++ u32 freq_KHz) ++{ ++ printk(KERN_INFO "%s, freq=%d KHz\n", __func__, freq_KHz); ++ return mt_fe_tn_set_freq_tc2800(state, freq_KHz); ++} ++ ++static int m88dc2800_init(struct dvb_frontend *fe) ++{ ++ dprintk("%s()\n", __func__); ++ return 0; ++} ++ ++static int m88dc2800_set_parameters(struct dvb_frontend *fe) ++{ ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ u8 is_annex_c, is_update; ++ u16 temp_qam; ++ s32 waiting_time; ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ ++ is_annex_c = c->delivery_system == SYS_DVBC_ANNEX_C ? 1 : 0; ++ ++ switch (c->modulation) { ++ case QAM_16: ++ temp_qam = 16; ++ break; ++ case QAM_32: ++ temp_qam = 32; ++ break; ++ case QAM_128: ++ temp_qam = 128; ++ break; ++ case QAM_256: ++ temp_qam = 256; ++ break; ++ default: /* QAM_64 */ ++ temp_qam = 64; ++ break; ++ } ++ ++ state->inverted = c->inversion == INVERSION_ON ? 1 : 0; ++ ++ printk(KERN_INFO ++ "m88dc2800: state, freq=%d qam=%d sym=%d inverted=%d xtal=%d\n", ++ state->freq, state->qam, state->sym, state->inverted, ++ state->xtal); ++ printk(KERN_INFO ++ "m88dc2800: set frequency to %d qam=%d symrate=%d annex-c=%d\n", ++ c->frequency, temp_qam, c->symbol_rate, is_annex_c); ++ ++ is_update = 0; ++ WriteReg(state, 0x80, 0x01); ++ if (c->frequency != state->freq) { ++ M88DC2000WriteTuner_TC2800(state, c->frequency / 1000); ++ state->freq = c->frequency; ++ } ++ if (c->symbol_rate != state->sym) { ++ M88DC2000SetSym(state, c->symbol_rate / 1000, state->xtal); ++ state->sym = c->symbol_rate; ++ is_update = 1; ++ } ++ if (temp_qam != state->qam) { ++ M88DC2000SetQAM(state, temp_qam); ++ state->qam = temp_qam; ++ is_update = 1; ++ } ++ ++ if (is_update != 0) { ++ if (state->config->ts_mode == 3) ++ M88DC2000AutoTSClock_C(state, state->sym / 1000, ++ temp_qam); ++ else ++ M88DC2000AutoTSClock_P(state, state->sym / 1000, ++ temp_qam); ++ } ++ ++ M88DC2000SetTxMode(state, state->inverted, is_annex_c); ++ M88DC2000SoftReset(state); ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) ++ && ((ReadReg(state, 0xE4) & 0x80) == 0x80)) ++ waiting_time = 800; ++ else ++ waiting_time = 500; ++ while (waiting_time > 0) { ++ msleep(50); ++ waiting_time -= 50; ++ if (M88DC2000GetLock(state)) ++ return 0; ++ } ++ ++ state->inverted = (state->inverted != 0) ? 0 : 1; ++ M88DC2000SetTxMode(state, state->inverted, is_annex_c); ++ M88DC2000SoftReset(state); ++ if (((ReadReg(state, 0xE3) & 0x80) == 0x80) && ++ ((ReadReg(state, 0xE4) & 0x80) == 0x80)) ++ waiting_time = 800; ++ else ++ waiting_time = 500; ++ while (waiting_time > 0) { ++ msleep(50); ++ waiting_time -= 50; ++ if (M88DC2000GetLock(state)) ++ return 0; ++ } ++ return 0; ++} ++ ++static int m88dc2800_read_status(struct dvb_frontend *fe, ++ fe_status_t * status) ++{ ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ *status = 0; ++ ++ if (M88DC2000GetLock(state)) { ++ *status = FE_HAS_SIGNAL | FE_HAS_CARRIER ++ |FE_HAS_SYNC | FE_HAS_VITERBI | FE_HAS_LOCK; ++ } ++ return 0; ++} ++ ++static int m88dc2800_read_ber(struct dvb_frontend *fe, u32 * ber) ++{ ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ u16 tmp; ++ ++ if (M88DC2000GetLock(state) == 0) { ++ state->ber = 0; ++ } else if ((ReadReg(state, 0xA0) & 0x80) != 0x80) { ++ tmp = ReadReg(state, 0xA2) << 8; ++ tmp += ReadReg(state, 0xA1); ++ state->ber = tmp; ++ WriteReg(state, 0xA0, 0x05); ++ WriteReg(state, 0xA0, 0x85); ++ } ++ *ber = state->ber; ++ return 0; ++} ++ ++static int m88dc2800_read_signal_strength(struct dvb_frontend *fe, ++ u16 * strength) ++{ ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ s16 tuner_strength; ++ ++ tuner_strength = mt_fe_tn_get_signal_strength_tc2800(state); ++ *strength = tuner_strength < -107 ? 0 : tuner_strength + 107; ++ ++ return 0; ++} ++ ++static int m88dc2800_read_snr(struct dvb_frontend *fe, u16 * snr) ++{ ++ static const u32 mes_log[] = { ++ 0, 3010, 4771, 6021, 6990, 7781, 8451, 9031, 9542, 10000, ++ 10414, 10792, 11139, 11461, 11761, 12041, 12304, 12553, 12788, ++ 13010, 13222, 13424, 13617, 13802, 13979, 14150, 14314, 14472, ++ 14624, 14771, 14914, 15052, 15185, 15315, 15441, 15563, 15682, ++ 15798, 15911, 16021, 16128, 16232, 16335, 16435, 16532, 16628, ++ 16721, 16812, 16902, 16990, 17076, 17160, 17243, 17324, 17404, ++ 17482, 17559, 17634, 17709, 17782, 17853, 17924, 17993, 18062, ++ 18129, 18195, 18261, 18325, 18388, 18451, 18513, 18573, 18633, ++ 18692, 18751, 18808, 18865, 18921, 18976, 19031 ++ }; ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ u8 i; ++ u32 _snr, mse; ++ ++ if ((ReadReg(state, 0x91) & 0x23) != 0x03) { ++ *snr = 0; ++ return 0; ++ } ++ mse = 0; ++ for (i = 0; i < 30; i++) { ++ mse += (ReadReg(state, 0x08) << 8) + ReadReg(state, 0x07); ++ } ++ mse /= 30; ++ if (mse > 80) ++ mse = 80; ++ switch (state->qam) { ++ case 16: ++ _snr = 34080; ++ break; /* 16QAM */ ++ case 32: ++ _snr = 37600; ++ break; /* 32QAM */ ++ case 64: ++ _snr = 40310; ++ break; /* 64QAM */ ++ case 128: ++ _snr = 43720; ++ break; /* 128QAM */ ++ case 256: ++ _snr = 46390; ++ break; /* 256QAM */ ++ default: ++ _snr = 40310; ++ break; ++ } ++ _snr -= mes_log[mse - 1]; /* C - 10*log10(MSE) */ ++ _snr /= 1000; ++ if (_snr > 0xff) ++ _snr = 0xff; ++ *snr = _snr; ++ return 0; ++} ++ ++static int m88dc2800_read_ucblocks(struct dvb_frontend *fe, u32 * ucblocks) ++{ ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ u8 u8Value; ++ ++ u8Value = ReadReg(state, 0xdf); ++ u8Value |= 0x02; /* Hold */ ++ WriteReg(state, 0xdf, u8Value); ++ ++ *ucblocks = ReadReg(state, 0xd5); ++ *ucblocks = (*ucblocks << 8) | ReadReg(state, 0xd4); ++ ++ u8Value &= 0xfe; /* Clear */ ++ WriteReg(state, 0xdf, u8Value); ++ u8Value &= 0xfc; /* Update */ ++ u8Value |= 0x01; ++ WriteReg(state, 0xdf, u8Value); ++ ++ return 0; ++} ++ ++static int m88dc2800_sleep(struct dvb_frontend *fe) ++{ ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ ++ mt_fe_tn_sleep_tc2800(state); ++ state->freq = 0; ++ ++ return 0; ++} ++ ++static void m88dc2800_release(struct dvb_frontend *fe) ++{ ++ struct m88dc2800_state *state = fe->demodulator_priv; ++ kfree(state); ++} ++ ++static struct dvb_frontend_ops m88dc2800_ops; ++ ++struct dvb_frontend *m88dc2800_attach(const struct m88dc2800_config ++ *config, struct i2c_adapter *i2c) ++{ ++ struct m88dc2800_state *state = NULL; ++ ++ /* allocate memory for the internal state */ ++ state = kzalloc(sizeof(struct m88dc2800_state), GFP_KERNEL); ++ if (state == NULL) ++ goto error; ++ ++ /* setup the state */ ++ state->config = config; ++ state->i2c = i2c; ++ state->xtal = 28800; ++ ++ WriteReg(state, 0x80, 0x01); ++ M88DC2000RegInitial_TC2800(state); ++ M88DC2000SetTsType(state, state->config->ts_mode); ++ mt_fe_tn_init_tc2800(state); ++ ++ /* create dvb_frontend */ ++ memcpy(&state->frontend.ops, &m88dc2800_ops, ++ sizeof(struct dvb_frontend_ops)); ++ state->frontend.demodulator_priv = state; ++ return &state->frontend; ++ ++ error: ++ kfree(state); ++ return NULL; ++} ++ ++EXPORT_SYMBOL(m88dc2800_attach); ++ ++static struct dvb_frontend_ops m88dc2800_ops = { ++ .delsys = {SYS_DVBC_ANNEX_A, SYS_DVBC_ANNEX_C}, ++ .info = { ++ .name = "Montage M88DC2800 DVB-C", ++ .frequency_stepsize = 62500, ++ .frequency_min = 48000000, ++ .frequency_max = 870000000, ++ .symbol_rate_min = 870000, ++ .symbol_rate_max = 9000000, ++ .caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | ++ FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_FEC_AUTO ++ }, ++ .release = m88dc2800_release, ++ .init = m88dc2800_init, ++ .sleep = m88dc2800_sleep, ++ .set_frontend = m88dc2800_set_parameters, ++ .read_status = m88dc2800_read_status, ++ .read_ber = m88dc2800_read_ber, ++ .read_signal_strength = m88dc2800_read_signal_strength, ++ .read_snr = m88dc2800_read_snr, ++ .read_ucblocks = m88dc2800_read_ucblocks, ++}; ++ ++MODULE_DESCRIPTION("Montage DVB-C demodulator driver"); ++MODULE_AUTHOR("Max Nibble "); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION("1.00"); +diff -urN a/drivers/media/dvb-frontends/m88dc2800.h b/drivers/media/dvb-frontends/m88dc2800.h +--- a/drivers/media/dvb-frontends/m88dc2800.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/media/dvb-frontends/m88dc2800.h 2013-01-26 14:57:32.000000000 +0800 +@@ -0,0 +1,43 @@ ++/* ++ M88DC2800/M88TC2800 - DVB-C demodulator and tuner from Montage ++ ++ Copyright (C) 2012 Max Nibble ++ Copyright (C) 2011 Montage Technology - www.montage-tech.com ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#ifndef M88DC2800_H ++#define M88DC2800_H ++ ++#include ++ ++struct m88dc2800_config { ++ u8 demod_address; ++ u8 ts_mode; ++}; ++ ++#if defined(CONFIG_DVB_M88DC2800) || (defined(CONFIG_DVB_M88DC2800_MODULE) && defined(MODULE)) ++extern struct dvb_frontend* m88dc2800_attach(const struct m88dc2800_config* config, ++ struct i2c_adapter* i2c); ++#else ++static inline struct dvb_frontend* m88dc2800_attach(const struct m88dc2800_config* config, ++ struct i2c_adapter* i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif /* CONFIG_DVB_M88DC2800 */ ++#endif /* M88DC2800_H */ +diff -urN a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c +--- a/drivers/media/dvb-frontends/m88ds3103.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/media/dvb-frontends/m88ds3103.c 2013-01-30 12:33:47.000000000 +0800 +@@ -0,0 +1,1710 @@ ++/* ++ Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver ++ ++ Copyright (C) 2011 Max nibble ++ Copyright (C) 2010 Montage Technology ++ Copyright (C) 2009 Konstantin Dimitrov. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "dvb_frontend.h" ++#include "m88ds3103.h" ++#include "m88ds3103_priv.h" ++ ++static int debug; ++module_param(debug, int, 0644); ++MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); ++ ++#define dprintk(args...) \ ++ do { \ ++ if (debug) \ ++ printk(KERN_INFO "m88ds3103: " args); \ ++ } while (0) ++ ++/*demod register operations.*/ ++static int m88ds3103_writereg(struct m88ds3103_state *state, int reg, int data) ++{ ++ u8 buf[] = { reg, data }; ++ struct i2c_msg msg = { .addr = state->config->demod_address, ++ .flags = 0, .buf = buf, .len = 2 }; ++ int err; ++ ++ if (debug > 1) ++ printk("m88ds3103: %s: write reg 0x%02x, value 0x%02x\n", ++ __func__, reg, data); ++ ++ err = i2c_transfer(state->i2c, &msg, 1); ++ if (err != 1) { ++ printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x," ++ " value == 0x%02x)\n", __func__, err, reg, data); ++ return -EREMOTEIO; ++ } ++ return 0; ++} ++ ++static int m88ds3103_readreg(struct m88ds3103_state *state, u8 reg) ++{ ++ int ret; ++ u8 b0[] = { reg }; ++ u8 b1[] = { 0 }; ++ struct i2c_msg msg[] = { ++ { .addr = state->config->demod_address, .flags = 0, ++ .buf = b0, .len = 1 }, ++ { .addr = state->config->demod_address, .flags = I2C_M_RD, ++ .buf = b1, .len = 1 } ++ }; ++ ret = i2c_transfer(state->i2c, msg, 2); ++ ++ if (ret != 2) { ++ printk(KERN_ERR "%s: reg=0x%x (error=%d)\n", ++ __func__, reg, ret); ++ return ret; ++ } ++ ++ if (debug > 1) ++ printk(KERN_INFO "m88ds3103: read reg 0x%02x, value 0x%02x\n", ++ reg, b1[0]); ++ ++ return b1[0]; ++} ++ ++/*tuner register operations.*/ ++static int m88ds3103_tuner_writereg(struct m88ds3103_state *state, int reg, int data) ++{ ++ u8 buf[] = { reg, data }; ++ struct i2c_msg msg = { .addr = 0x60, ++ .flags = 0, .buf = buf, .len = 2 }; ++ int err; ++ ++ m88ds3103_writereg(state, 0x03, 0x11); ++ err = i2c_transfer(state->i2c, &msg, 1); ++ ++ if (err != 1) { ++ printk("%s: writereg error(err == %i, reg == 0x%02x," ++ " value == 0x%02x)\n", __func__, err, reg, data); ++ return -EREMOTEIO; ++ } ++ ++ return 0; ++} ++ ++static int m88ds3103_tuner_readreg(struct m88ds3103_state *state, u8 reg) ++{ ++ int ret; ++ u8 b0[] = { reg }; ++ u8 b1[] = { 0 }; ++ struct i2c_msg msg[] = { ++ { .addr = 0x60, .flags = 0, ++ .buf = b0, .len = 1 }, ++ { .addr = 0x60, .flags = I2C_M_RD, ++ .buf = b1, .len = 1 } ++ }; ++ ++ m88ds3103_writereg(state, 0x03, 0x11); ++ ret = i2c_transfer(state->i2c, msg, 2); ++ ++ if (ret != 2) { ++ printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret); ++ return ret; ++ } ++ ++ return b1[0]; ++} ++ ++/* Bulk demod I2C write, for firmware download. */ ++static int m88ds3103_writeregN(struct m88ds3103_state *state, int reg, ++ const u8 *data, u16 len) ++{ ++ int ret = -EREMOTEIO; ++ struct i2c_msg msg; ++ u8 *buf; ++ ++ buf = kmalloc(len + 1, GFP_KERNEL); ++ if (buf == NULL) { ++ printk("Unable to kmalloc\n"); ++ ret = -ENOMEM; ++ goto error; ++ } ++ ++ *(buf) = reg; ++ memcpy(buf + 1, data, len); ++ ++ msg.addr = state->config->demod_address; ++ msg.flags = 0; ++ msg.buf = buf; ++ msg.len = len + 1; ++ ++ if (debug > 1) ++ printk(KERN_INFO "m88ds3103: %s: write regN 0x%02x, len = %d\n", ++ __func__, reg, len); ++ ++ ret = i2c_transfer(state->i2c, &msg, 1); ++ if (ret != 1) { ++ printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x\n", ++ __func__, ret, reg); ++ ret = -EREMOTEIO; ++ } ++ ++error: ++ kfree(buf); ++ ++ return ret; ++} ++ ++static int m88ds3103_load_firmware(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ const struct firmware *fw; ++ int i, ret = 0; ++ ++ dprintk("%s()\n", __func__); ++ ++ if (state->skip_fw_load) ++ return 0; ++ /* Load firmware */ ++ /* request the firmware, this will block until someone uploads it */ ++ if(state->demod_id == DS3000_ID){ ++ printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__, ++ DS3000_DEFAULT_FIRMWARE); ++ ret = request_firmware(&fw, DS3000_DEFAULT_FIRMWARE, ++ state->i2c->dev.parent); ++ }else if(state->demod_id == DS3103_ID){ ++ printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__, ++ DS3103_DEFAULT_FIRMWARE); ++ ret = request_firmware(&fw, DS3103_DEFAULT_FIRMWARE, ++ state->i2c->dev.parent); ++ } ++ ++ printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__); ++ if (ret) { ++ printk(KERN_ERR "%s: No firmware uploaded (timeout or file not " ++ "found?)\n", __func__); ++ return ret; ++ } ++ ++ /* Make sure we don't recurse back through here during loading */ ++ state->skip_fw_load = 1; ++ ++ dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n", ++ fw->size, ++ fw->data[0], ++ fw->data[1], ++ fw->data[fw->size - 2], ++ fw->data[fw->size - 1]); ++ ++ /* stop internal mcu. */ ++ m88ds3103_writereg(state, 0xb2, 0x01); ++ /* split firmware to download.*/ ++ for(i = 0; i < FW_DOWN_LOOP; i++){ ++ ret = m88ds3103_writeregN(state, 0xb0, &(fw->data[FW_DOWN_SIZE*i]), FW_DOWN_SIZE); ++ if(ret != 1) break; ++ } ++ /* start internal mcu. */ ++ if(ret == 1) ++ m88ds3103_writereg(state, 0xb2, 0x00); ++ ++ release_firmware(fw); ++ ++ dprintk("%s: Firmware upload %s\n", __func__, ++ ret == 1 ? "complete" : "failed"); ++ ++ if(ret == 1) ret = 0; ++ ++ /* Ensure firmware is always loaded if required */ ++ state->skip_fw_load = 0; ++ ++ return ret; ++} ++ ++ ++static int m88ds3103_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 data; ++ ++ dprintk("%s(%d)\n", __func__, voltage); ++ ++ dprintk("m88ds3103:pin_ctrl = (%02x)\n", state->config->pin_ctrl); ++ ++ if(state->config->set_voltage) ++ state->config->set_voltage(fe, voltage); ++ ++ data = m88ds3103_readreg(state, 0xa2); ++ ++ if(state->config->pin_ctrl & 0x80){ /*If control pin is assigned.*/ ++ data &= ~0x03; /* bit0 V/H, bit1 off/on */ ++ if(state->config->pin_ctrl & 0x02) ++ data |= 0x02; ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_18: ++ if((state->config->pin_ctrl & 0x01) == 0) ++ data |= 0x01; ++ break; ++ case SEC_VOLTAGE_13: ++ if(state->config->pin_ctrl & 0x01) ++ data |= 0x01; ++ break; ++ case SEC_VOLTAGE_OFF: ++ if(state->config->pin_ctrl & 0x02) ++ data &= ~0x02; ++ else ++ data |= 0x02; ++ break; ++ } ++ } ++ ++ m88ds3103_writereg(state, 0xa2, data); ++ ++ return 0; ++} ++ ++static int m88ds3103_read_status(struct dvb_frontend *fe, fe_status_t* status) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ int lock = 0; ++ ++ *status = 0; ++ ++ switch (state->delivery_system){ ++ case SYS_DVBS: ++ lock = m88ds3103_readreg(state, 0xd1); ++ dprintk("%s: SYS_DVBS status=%x.\n", __func__, lock); ++ ++ if ((lock & 0x07) == 0x07){ ++ /*if((m88ds3103_readreg(state, 0x0d) & 0x07) == 0x07)*/ ++ *status = FE_HAS_SIGNAL | FE_HAS_CARRIER ++ | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; ++ ++ } ++ break; ++ case SYS_DVBS2: ++ lock = m88ds3103_readreg(state, 0x0d); ++ dprintk("%s: SYS_DVBS2 status=%x.\n", __func__, lock); ++ ++ if ((lock & 0x8f) == 0x8f) ++ *status = FE_HAS_SIGNAL | FE_HAS_CARRIER ++ | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; ++ ++ break; ++ default: ++ break; ++ } ++ ++ return 0; ++} ++ ++static int m88ds3103_read_ber(struct dvb_frontend *fe, u32* ber) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 tmp1, tmp2, tmp3; ++ u32 ldpc_frame_cnt, pre_err_packags, code_rate_fac = 0; ++ ++ dprintk("%s()\n", __func__); ++ ++ switch (state->delivery_system) { ++ case SYS_DVBS: ++ m88ds3103_writereg(state, 0xf9, 0x04); ++ tmp3 = m88ds3103_readreg(state, 0xf8); ++ if ((tmp3&0x10) == 0){ ++ tmp1 = m88ds3103_readreg(state, 0xf7); ++ tmp2 = m88ds3103_readreg(state, 0xf6); ++ tmp3 |= 0x10; ++ m88ds3103_writereg(state, 0xf8, tmp3); ++ state->preBer = (tmp1<<8) | tmp2; ++ } ++ break; ++ case SYS_DVBS2: ++ tmp1 = m88ds3103_readreg(state, 0x7e) & 0x0f; ++ switch(tmp1){ ++ case 0: code_rate_fac = 16008 - 80; break; ++ case 1: code_rate_fac = 21408 - 80; break; ++ case 2: code_rate_fac = 25728 - 80; break; ++ case 3: code_rate_fac = 32208 - 80; break; ++ case 4: code_rate_fac = 38688 - 80; break; ++ case 5: code_rate_fac = 43040 - 80; break; ++ case 6: code_rate_fac = 48408 - 80; break; ++ case 7: code_rate_fac = 51648 - 80; break; ++ case 8: code_rate_fac = 53840 - 80; break; ++ case 9: code_rate_fac = 57472 - 80; break; ++ case 10: code_rate_fac = 58192 - 80; break; ++ } ++ ++ tmp1 = m88ds3103_readreg(state, 0xd7) & 0xff; ++ tmp2 = m88ds3103_readreg(state, 0xd6) & 0xff; ++ tmp3 = m88ds3103_readreg(state, 0xd5) & 0xff; ++ ldpc_frame_cnt = (tmp1 << 16) | (tmp2 << 8) | tmp3; ++ ++ tmp1 = m88ds3103_readreg(state, 0xf8) & 0xff; ++ tmp2 = m88ds3103_readreg(state, 0xf7) & 0xff; ++ pre_err_packags = tmp1<<8 | tmp2; ++ ++ if (ldpc_frame_cnt > 1000){ ++ m88ds3103_writereg(state, 0xd1, 0x01); ++ m88ds3103_writereg(state, 0xf9, 0x01); ++ m88ds3103_writereg(state, 0xf9, 0x00); ++ m88ds3103_writereg(state, 0xd1, 0x00); ++ state->preBer = pre_err_packags; ++ } ++ break; ++ default: ++ break; ++ } ++ *ber = state->preBer; ++ ++ return 0; ++} ++ ++static int m88ds3103_read_signal_strength(struct dvb_frontend *fe, ++ u16 *signal_strength) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u16 gain; ++ u8 gain1, gain2, gain3 = 0; ++ ++ dprintk("%s()\n", __func__); ++ ++ gain1 = m88ds3103_tuner_readreg(state, 0x3d) & 0x1f; ++ dprintk("%s: gain1 = 0x%02x \n", __func__, gain1); ++ ++ if (gain1 > 15) gain1 = 15; ++ gain2 = m88ds3103_tuner_readreg(state, 0x21) & 0x1f; ++ dprintk("%s: gain2 = 0x%02x \n", __func__, gain2); ++ ++ if(state->tuner_id == TS2022_ID){ ++ gain3 = (m88ds3103_tuner_readreg(state, 0x66)>>3) & 0x07; ++ dprintk("%s: gain3 = 0x%02x \n", __func__, gain3); ++ ++ if (gain2 > 16) gain2 = 16; ++ if (gain2 < 2) gain2 = 2; ++ if (gain3 > 6) gain3 = 6; ++ }else{ ++ if (gain2 > 13) gain2 = 13; ++ gain3 = 0; ++ } ++ ++ gain = gain1*23 + gain2*35 + gain3*29; ++ *signal_strength = 60000 - gain*55; ++ ++ return 0; ++} ++ ++ ++static int m88ds3103_read_snr(struct dvb_frontend *fe, u16 *p_snr) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 val, npow1, npow2, spow1, cnt; ++ u16 tmp, snr; ++ u32 npow, spow, snr_total; ++ static const u16 mes_log10[] ={ ++ 0, 3010, 4771, 6021, 6990, 7781, 8451, 9031, 9542, 10000, ++ 10414, 10792, 11139, 11461, 11761, 12041, 12304, 12553, 12788, 13010, ++ 13222, 13424, 13617, 13802, 13979, 14150, 14314, 14472, 14624, 14771, ++ 14914, 15052, 15185, 15315, 15441, 15563, 15682, 15798, 15911, 16021, ++ 16128, 16232, 16335, 16435, 16532, 16628, 16721, 16812, 16902, 16990, ++ 17076, 17160, 17243, 17324, 17404, 17482, 17559, 17634, 17709, 17782, ++ 17853, 17924, 17993, 18062, 18129, 18195, 18261, 18325, 18388, 18451, ++ 18513, 18573, 18633, 18692, 18751, 18808, 18865, 18921, 18976, 19031 ++ }; ++ static const u16 mes_loge[] ={ ++ 0, 6931, 10986, 13863, 16094, 17918, 19459, 20794, 21972, 23026, ++ 23979, 24849, 25649, 26391, 27081, 27726, 28332, 28904, 29444, 29957, ++ 30445, 30910, 31355, 31781, 32189, 32581, 32958, 33322, 33673, 34012, ++ 34340, 34657, ++ }; ++ ++ dprintk("%s()\n", __func__); ++ ++ snr = 0; ++ ++ switch (state->delivery_system){ ++ case SYS_DVBS: ++ cnt = 10; snr_total = 0; ++ while(cnt > 0){ ++ val = m88ds3103_readreg(state, 0xff); ++ snr_total += val; ++ cnt--; ++ } ++ tmp = (u16)(snr_total/80); ++ if(tmp > 0){ ++ if (tmp > 32) tmp = 32; ++ snr = (mes_loge[tmp - 1] * 100) / 45; ++ }else{ ++ snr = 0; ++ } ++ break; ++ case SYS_DVBS2: ++ cnt = 10; npow = 0; spow = 0; ++ while(cnt >0){ ++ npow1 = m88ds3103_readreg(state, 0x8c) & 0xff; ++ npow2 = m88ds3103_readreg(state, 0x8d) & 0xff; ++ npow += (((npow1 & 0x3f) + (u16)(npow2 << 6)) >> 2); ++ ++ spow1 = m88ds3103_readreg(state, 0x8e) & 0xff; ++ spow += ((spow1 * spow1) >> 1); ++ cnt--; ++ } ++ npow /= 10; spow /= 10; ++ if(spow == 0){ ++ snr = 0; ++ }else if(npow == 0){ ++ snr = 19; ++ }else{ ++ if(spow > npow){ ++ tmp = (u16)(spow / npow); ++ if (tmp > 80) tmp = 80; ++ snr = mes_log10[tmp - 1]*3; ++ }else{ ++ tmp = (u16)(npow / spow); ++ if (tmp > 80) tmp = 80; ++ snr = -(mes_log10[tmp - 1] / 1000); ++ } ++ } ++ break; ++ default: ++ break; ++ } ++ *p_snr = snr; ++ ++ return 0; ++} ++ ++ ++static int m88ds3103_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 tmp1, tmp2, tmp3, data; ++ ++ dprintk("%s()\n", __func__); ++ ++ switch (state->delivery_system) { ++ case SYS_DVBS: ++ data = m88ds3103_readreg(state, 0xf8); ++ data |= 0x40; ++ m88ds3103_writereg(state, 0xf8, data); ++ tmp1 = m88ds3103_readreg(state, 0xf5); ++ tmp2 = m88ds3103_readreg(state, 0xf4); ++ *ucblocks = (tmp1 <<8) | tmp2; ++ data &= ~0x20; ++ m88ds3103_writereg(state, 0xf8, data); ++ data |= 0x20; ++ m88ds3103_writereg(state, 0xf8, data); ++ data &= ~0x40; ++ m88ds3103_writereg(state, 0xf8, data); ++ break; ++ case SYS_DVBS2: ++ tmp1 = m88ds3103_readreg(state, 0xda); ++ tmp2 = m88ds3103_readreg(state, 0xd9); ++ tmp3 = m88ds3103_readreg(state, 0xd8); ++ *ucblocks = (tmp1 <<16)|(tmp2 <<8)|tmp3; ++ data = m88ds3103_readreg(state, 0xd1); ++ data |= 0x01; ++ m88ds3103_writereg(state, 0xd1, data); ++ data &= ~0x01; ++ m88ds3103_writereg(state, 0xd1, data); ++ break; ++ default: ++ break; ++ } ++ return 0; ++} ++ ++static int m88ds3103_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 data_a1, data_a2; ++ ++ dprintk("%s(%d)\n", __func__, tone); ++ if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) { ++ printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone); ++ return -EINVAL; ++ } ++ ++ data_a1 = m88ds3103_readreg(state, 0xa1); ++ data_a2 = m88ds3103_readreg(state, 0xa2); ++ if(state->demod_id == DS3103_ID) ++ data_a2 &= 0xdf; /* Normal mode */ ++ switch (tone) { ++ case SEC_TONE_ON: ++ dprintk("%s: SEC_TONE_ON\n", __func__); ++ data_a1 |= 0x04; ++ data_a1 &= ~0x03; ++ data_a1 &= ~0x40; ++ data_a2 &= ~0xc0; ++ break; ++ case SEC_TONE_OFF: ++ dprintk("%s: SEC_TONE_OFF\n", __func__); ++ data_a2 &= ~0xc0; ++ data_a2 |= 0x80; ++ break; ++ } ++ m88ds3103_writereg(state, 0xa2, data_a2); ++ m88ds3103_writereg(state, 0xa1, data_a1); ++ return 0; ++} ++ ++static int m88ds3103_send_diseqc_msg(struct dvb_frontend *fe, ++ struct dvb_diseqc_master_cmd *d) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ int i, ret = 0; ++ u8 tmp, time_out; ++ ++ /* Dump DiSEqC message */ ++ if (debug) { ++ printk(KERN_INFO "m88ds3103: %s(", __func__); ++ for (i = 0 ; i < d->msg_len ;) { ++ printk(KERN_INFO "0x%02x", d->msg[i]); ++ if (++i < d->msg_len) ++ printk(KERN_INFO ", "); ++ } ++ } ++ ++ tmp = m88ds3103_readreg(state, 0xa2); ++ tmp &= ~0xc0; ++ if(state->demod_id == DS3103_ID) ++ tmp &= ~0x20; ++ m88ds3103_writereg(state, 0xa2, tmp); ++ ++ for (i = 0; i < d->msg_len; i ++) ++ m88ds3103_writereg(state, (0xa3+i), d->msg[i]); ++ ++ tmp = m88ds3103_readreg(state, 0xa1); ++ tmp &= ~0x38; ++ tmp &= ~0x40; ++ tmp |= ((d->msg_len-1) << 3) | 0x07; ++ tmp &= ~0x80; ++ m88ds3103_writereg(state, 0xa1, tmp); ++ /* 1.5 * 9 * 8 = 108ms */ ++ time_out = 150; ++ while (time_out > 0){ ++ msleep(10); ++ time_out -= 10; ++ tmp = m88ds3103_readreg(state, 0xa1); ++ if ((tmp & 0x40) == 0) ++ break; ++ } ++ if (time_out == 0){ ++ tmp = m88ds3103_readreg(state, 0xa1); ++ tmp &= ~0x80; ++ tmp |= 0x40; ++ m88ds3103_writereg(state, 0xa1, tmp); ++ ret = 1; ++ } ++ tmp = m88ds3103_readreg(state, 0xa2); ++ tmp &= ~0xc0; ++ tmp |= 0x80; ++ m88ds3103_writereg(state, 0xa2, tmp); ++ return ret; ++} ++ ++ ++static int m88ds3103_diseqc_send_burst(struct dvb_frontend *fe, ++ fe_sec_mini_cmd_t burst) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 val, time_out; ++ ++ dprintk("%s()\n", __func__); ++ ++ val = m88ds3103_readreg(state, 0xa2); ++ val &= ~0xc0; ++ if(state->demod_id == DS3103_ID) ++ val &= 0xdf; /* Normal mode */ ++ m88ds3103_writereg(state, 0xa2, val); ++ /* DiSEqC burst */ ++ if (burst == SEC_MINI_B) ++ m88ds3103_writereg(state, 0xa1, 0x01); ++ else ++ m88ds3103_writereg(state, 0xa1, 0x02); ++ ++ msleep(13); ++ ++ time_out = 5; ++ do{ ++ val = m88ds3103_readreg(state, 0xa1); ++ if ((val & 0x40) == 0) ++ break; ++ msleep(1); ++ time_out --; ++ } while (time_out > 0); ++ ++ val = m88ds3103_readreg(state, 0xa2); ++ val &= ~0xc0; ++ val |= 0x80; ++ m88ds3103_writereg(state, 0xa2, val); ++ ++ return 0; ++} ++ ++static void m88ds3103_release(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ ++ dprintk("%s\n", __func__); ++ kfree(state); ++} ++ ++static int m88ds3103_check_id(struct m88ds3103_state *state) ++{ ++ int val_00, val_01; ++ ++ /*check demod id*/ ++ val_01 = m88ds3103_readreg(state, 0x01); ++ printk(KERN_INFO "DS3000 chip version: %x attached.\n", val_01); ++ ++ if(val_01 == 0xD0) ++ state->demod_id = DS3103_ID; ++ else if(val_01 == 0xC0) ++ state->demod_id = DS3000_ID; ++ else ++ state->demod_id = UNKNOW_ID; ++ ++ /*check tuner id*/ ++ val_00 = m88ds3103_tuner_readreg(state, 0x00); ++ printk(KERN_INFO "TS202x chip version[1]: %x attached.\n", val_00); ++ val_00 &= 0x03; ++ if(val_00 == 0) ++ { ++ m88ds3103_tuner_writereg(state, 0x00, 0x01); ++ msleep(3); ++ } ++ m88ds3103_tuner_writereg(state, 0x00, 0x03); ++ msleep(5); ++ ++ val_00 = m88ds3103_tuner_readreg(state, 0x00); ++ printk(KERN_INFO "TS202x chip version[2]: %x attached.\n", val_00); ++ val_00 &= 0xff; ++ if((val_00 == 0x01) || (val_00 == 0x41) || (val_00 == 0x81)) ++ state->tuner_id = TS2020_ID; ++ else if(((val_00 & 0xc0)== 0xc0) || (val_00 == 0x83)) ++ state->tuner_id = TS2022_ID; ++ else ++ state->tuner_id = UNKNOW_ID; ++ ++ return state->demod_id; ++} ++ ++static struct dvb_frontend_ops m88ds3103_ops; ++static int m88ds3103_initilaze(struct dvb_frontend *fe); ++ ++struct dvb_frontend *m88ds3103_attach(const struct m88ds3103_config *config, ++ struct i2c_adapter *i2c) ++{ ++ struct m88ds3103_state *state = NULL; ++ ++ dprintk("%s\n", __func__); ++ ++ /* allocate memory for the internal state */ ++ state = kzalloc(sizeof(struct m88ds3103_state), GFP_KERNEL); ++ if (state == NULL) { ++ printk(KERN_ERR "Unable to kmalloc\n"); ++ goto error2; ++ } ++ ++ state->config = config; ++ state->i2c = i2c; ++ state->preBer = 0xffff; ++ state->delivery_system = SYS_DVBS; /*Default to DVB-S.*/ ++ ++ /* check demod id */ ++ if(m88ds3103_check_id(state) == UNKNOW_ID){ ++ printk(KERN_ERR "Unable to find Montage chip\n"); ++ goto error3; ++ } ++ ++ memcpy(&state->frontend.ops, &m88ds3103_ops, ++ sizeof(struct dvb_frontend_ops)); ++ state->frontend.demodulator_priv = state; ++ ++ m88ds3103_initilaze(&state->frontend); ++ ++ return &state->frontend; ++ ++error3: ++ kfree(state); ++error2: ++ return NULL; ++} ++EXPORT_SYMBOL(m88ds3103_attach); ++ ++static int m88ds3103_set_carrier_offset(struct dvb_frontend *fe, ++ s32 carrier_offset_khz) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ s32 tmp; ++ ++ tmp = carrier_offset_khz; ++ tmp *= 65536; ++ ++ tmp = (2*tmp + MT_FE_MCLK_KHZ) / (2*MT_FE_MCLK_KHZ); ++ ++ if (tmp < 0) ++ tmp += 65536; ++ ++ m88ds3103_writereg(state, 0x5f, tmp >> 8); ++ m88ds3103_writereg(state, 0x5e, tmp & 0xff); ++ ++ return 0; ++} ++ ++static int m88ds3103_set_symrate(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ u16 value; ++ ++ value = (((c->symbol_rate / 1000) << 15) + (MT_FE_MCLK_KHZ / 4)) / (MT_FE_MCLK_KHZ / 2); ++ m88ds3103_writereg(state, 0x61, value & 0x00ff); ++ m88ds3103_writereg(state, 0x62, (value & 0xff00) >> 8); ++ ++ return 0; ++} ++ ++static int m88ds3103_set_CCI(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 tmp; ++ ++ tmp = m88ds3103_readreg(state, 0x56); ++ tmp &= ~0x01; ++ m88ds3103_writereg(state, 0x56, tmp); ++ ++ tmp = m88ds3103_readreg(state, 0x76); ++ tmp &= ~0x80; ++ m88ds3103_writereg(state, 0x76, tmp); ++ ++ return 0; ++} ++ ++static int m88ds3103_init_reg(struct m88ds3103_state *state, const u8 *p_reg_tab, u32 size) ++{ ++ u32 i; ++ ++ for(i = 0; i < size; i+=2) ++ m88ds3103_writereg(state, p_reg_tab[i], p_reg_tab[i+1]); ++ ++ return 0; ++} ++ ++static int m88ds3103_get_locked_sym_rate(struct m88ds3103_state *state, u32 *sym_rate_KSs) ++{ ++ u16 tmp; ++ u32 sym_rate_tmp; ++ u8 val_0x6d, val_0x6e; ++ ++ val_0x6d = m88ds3103_readreg(state, 0x6d); ++ val_0x6e = m88ds3103_readreg(state, 0x6e); ++ ++ tmp = (u16)((val_0x6e<<8) | val_0x6d); ++ ++ sym_rate_tmp = (u32)(tmp * MT_FE_MCLK_KHZ); ++ sym_rate_tmp = (u32)(sym_rate_tmp / (1<<16)); ++ *sym_rate_KSs = sym_rate_tmp; ++ ++ return 0; ++} ++ ++static int m88ds3103_get_channel_info(struct m88ds3103_state *state, u8 *p_mode, u8 *p_coderate) ++{ ++ u8 tmp, val_0x7E; ++ ++ if(state->delivery_system == SYS_DVBS2){ ++ val_0x7E = m88ds3103_readreg(state, 0x7e); ++ tmp = (u8)((val_0x7E&0xC0) >> 6); ++ *p_mode = tmp; ++ tmp = (u8)(val_0x7E & 0x0f); ++ *p_coderate = tmp; ++ } else { ++ *p_mode = 0; ++ tmp = m88ds3103_readreg(state, 0xe6); ++ tmp = (u8)(tmp >> 5); ++ *p_coderate = tmp; ++ } ++ ++ return 0; ++} ++ ++static int m88ds3103_set_clock_ratio(struct m88ds3103_state *state) ++{ ++ u8 val, mod_fac, tmp1, tmp2; ++ u32 input_datarate, locked_sym_rate_KSs; ++ u32 MClk_KHz = 96000; ++ u8 mod_mode, code_rate, divid_ratio = 0; ++ ++ locked_sym_rate_KSs = 0; ++ m88ds3103_get_locked_sym_rate(state, &locked_sym_rate_KSs); ++ if(locked_sym_rate_KSs == 0) ++ return 0; ++ ++ m88ds3103_get_channel_info(state, &mod_mode, &code_rate); ++ ++ if (state->delivery_system == SYS_DVBS2) ++ { ++ switch(mod_mode) { ++ case 1: mod_fac = 3; break; ++ case 2: mod_fac = 4; break; ++ case 3: mod_fac = 5; break; ++ default: mod_fac = 2; break; ++ } ++ ++ switch(code_rate) { ++ case 0: input_datarate = locked_sym_rate_KSs*mod_fac/8/4; break; ++ case 1: input_datarate = locked_sym_rate_KSs*mod_fac/8/3; break; ++ case 2: input_datarate = locked_sym_rate_KSs*mod_fac*2/8/5; break; ++ case 3: input_datarate = locked_sym_rate_KSs*mod_fac/8/2; break; ++ case 4: input_datarate = locked_sym_rate_KSs*mod_fac*3/8/5; break; ++ case 5: input_datarate = locked_sym_rate_KSs*mod_fac*2/8/3; break; ++ case 6: input_datarate = locked_sym_rate_KSs*mod_fac*3/8/4; break; ++ case 7: input_datarate = locked_sym_rate_KSs*mod_fac*4/8/5; break; ++ case 8: input_datarate = locked_sym_rate_KSs*mod_fac*5/8/6; break; ++ case 9: input_datarate = locked_sym_rate_KSs*mod_fac*8/8/9; break; ++ case 10: input_datarate = locked_sym_rate_KSs*mod_fac*9/8/10; break; ++ default: input_datarate = locked_sym_rate_KSs*mod_fac*2/8/3; break; ++ } ++ ++ if(state->demod_id == DS3000_ID) ++ input_datarate = input_datarate * 115 / 100; ++ ++ if(input_datarate < 4800) {tmp1 = 15;tmp2 = 15;} //4.8MHz TS clock ++ else if(input_datarate < 4966) {tmp1 = 14;tmp2 = 15;} //4.966MHz TS clock ++ else if(input_datarate < 5143) {tmp1 = 14;tmp2 = 14;} //5.143MHz TS clock ++ else if(input_datarate < 5333) {tmp1 = 13;tmp2 = 14;} //5.333MHz TS clock ++ else if(input_datarate < 5538) {tmp1 = 13;tmp2 = 13;} //5.538MHz TS clock ++ else if(input_datarate < 5760) {tmp1 = 12;tmp2 = 13;} //5.76MHz TS clock allan 0809 ++ else if(input_datarate < 6000) {tmp1 = 12;tmp2 = 12;} //6MHz TS clock ++ else if(input_datarate < 6260) {tmp1 = 11;tmp2 = 12;} //6.26MHz TS clock ++ else if(input_datarate < 6545) {tmp1 = 11;tmp2 = 11;} //6.545MHz TS clock ++ else if(input_datarate < 6857) {tmp1 = 10;tmp2 = 11;} //6.857MHz TS clock ++ else if(input_datarate < 7200) {tmp1 = 10;tmp2 = 10;} //7.2MHz TS clock ++ else if(input_datarate < 7578) {tmp1 = 9;tmp2 = 10;} //7.578MHz TS clock ++ else if(input_datarate < 8000) {tmp1 = 9;tmp2 = 9;} //8MHz TS clock ++ else if(input_datarate < 8470) {tmp1 = 8;tmp2 = 9;} //8.47MHz TS clock ++ else if(input_datarate < 9000) {tmp1 = 8;tmp2 = 8;} //9MHz TS clock ++ else if(input_datarate < 9600) {tmp1 = 7;tmp2 = 8;} //9.6MHz TS clock ++ else if(input_datarate < 10285) {tmp1 = 7;tmp2 = 7;} //10.285MHz TS clock ++ else if(input_datarate < 12000) {tmp1 = 6;tmp2 = 6;} //12MHz TS clock ++ else if(input_datarate < 14400) {tmp1 = 5;tmp2 = 5;} //14.4MHz TS clock ++ else if(input_datarate < 18000) {tmp1 = 4;tmp2 = 4;} //18MHz TS clock ++ else {tmp1 = 3;tmp2 = 3;} //24MHz TS clock ++ ++ if(state->demod_id == DS3000_ID) { ++ val = (u8)((tmp1<<4) + tmp2); ++ m88ds3103_writereg(state, 0xfe, val); ++ } else { ++ tmp1 = m88ds3103_readreg(state, 0x22); ++ tmp2 = m88ds3103_readreg(state, 0x24); ++ ++ tmp1 >>= 6; ++ tmp1 &= 0x03; ++ tmp2 >>= 6; ++ tmp2 &= 0x03; ++ ++ if((tmp1 == 0x00) && (tmp2 == 0x01)) ++ MClk_KHz = 144000; ++ else if((tmp1 == 0x00) && (tmp2 == 0x03)) ++ MClk_KHz = 72000; ++ else if((tmp1 == 0x01) && (tmp2 == 0x01)) ++ MClk_KHz = 115200; ++ else if((tmp1 == 0x02) && (tmp2 == 0x01)) ++ MClk_KHz = 96000; ++ else if((tmp1 == 0x03) && (tmp2 == 0x00)) ++ MClk_KHz = 192000; ++ else ++ return 0; ++ ++ if(input_datarate < 5200) /*Max. 2011-12-23 11:55*/ ++ input_datarate = 5200; ++ ++ if(input_datarate != 0) ++ divid_ratio = (u8)(MClk_KHz / input_datarate); ++ else ++ divid_ratio = 0xFF; ++ ++ if(divid_ratio > 128) ++ divid_ratio = 128; ++ ++ if(divid_ratio < 2) ++ divid_ratio = 2; ++ ++ tmp1 = (u8)(divid_ratio / 2); ++ tmp2 = (u8)(divid_ratio / 2); ++ ++ if((divid_ratio % 2) != 0) ++ tmp2 += 1; ++ ++ tmp1 -= 1; ++ tmp2 -= 1; ++ ++ tmp1 &= 0x3f; ++ tmp2 &= 0x3f; ++ ++ val = m88ds3103_readreg(state, 0xfe); ++ val &= 0xF0; ++ val |= (tmp2 >> 2) & 0x0f; ++ m88ds3103_writereg(state, 0xfe, val); ++ ++ val = (u8)((tmp2 & 0x03) << 6); ++ val |= tmp1; ++ m88ds3103_writereg(state, 0xea, val); ++ } ++ } else { ++ mod_fac = 2; ++ ++ switch(code_rate) { ++ case 4: input_datarate = locked_sym_rate_KSs*mod_fac/2/8; break; ++ case 3: input_datarate = locked_sym_rate_KSs*mod_fac*2/3/8; break; ++ case 2: input_datarate = locked_sym_rate_KSs*mod_fac*3/4/8; break; ++ case 1: input_datarate = locked_sym_rate_KSs*mod_fac*5/6/8; break; ++ case 0: input_datarate = locked_sym_rate_KSs*mod_fac*7/8/8; break; ++ default: input_datarate = locked_sym_rate_KSs*mod_fac*3/4/8; break; ++ } ++ ++ if(state->demod_id == DS3000_ID) ++ input_datarate = input_datarate * 115 / 100; ++ ++ if(input_datarate < 6857) {tmp1 = 7;tmp2 = 7;} //6.857MHz TS clock ++ else if(input_datarate < 7384) {tmp1 = 6;tmp2 = 7;} //7.384MHz TS clock ++ else if(input_datarate < 8000) {tmp1 = 6;tmp2 = 6;} //8MHz TS clock ++ else if(input_datarate < 8727) {tmp1 = 5;tmp2 = 6;} //8.727MHz TS clock ++ else if(input_datarate < 9600) {tmp1 = 5;tmp2 = 5;} //9.6MHz TS clock ++ else if(input_datarate < 10666) {tmp1 = 4;tmp2 = 5;} //10.666MHz TS clock ++ else if(input_datarate < 12000) {tmp1 = 4;tmp2 = 4;} //12MHz TS clock ++ else if(input_datarate < 13714) {tmp1 = 3;tmp2 = 4;} //13.714MHz TS clock ++ else if(input_datarate < 16000) {tmp1 = 3;tmp2 = 3;} //16MHz TS clock ++ else if(input_datarate < 19200) {tmp1 = 2;tmp2 = 3;} //19.2MHz TS clock ++ else {tmp1 = 2;tmp2 = 2;} //24MHz TS clock ++ ++ if(state->demod_id == DS3000_ID) { ++ val = m88ds3103_readreg(state, 0xfe); ++ val &= 0xc0; ++ val |= ((u8)((tmp1<<3) + tmp2)); ++ m88ds3103_writereg(state, 0xfe, val); ++ } else { ++ if(input_datarate < 5200) /*Max. 2011-12-23 11:55*/ ++ input_datarate = 5200; ++ ++ if(input_datarate != 0) ++ divid_ratio = (u8)(MClk_KHz / input_datarate); ++ else ++ divid_ratio = 0xFF; ++ ++ if(divid_ratio > 128) ++ divid_ratio = 128; ++ ++ if(divid_ratio < 2) ++ divid_ratio = 2; ++ ++ tmp1 = (u8)(divid_ratio / 2); ++ tmp2 = (u8)(divid_ratio / 2); ++ ++ if((divid_ratio % 2) != 0) ++ tmp2 += 1; ++ ++ tmp1 -= 1; ++ tmp2 -= 1; ++ ++ tmp1 &= 0x3f; ++ tmp2 &= 0x3f; ++ ++ val = m88ds3103_readreg(state, 0xfe); ++ val &= 0xF0; ++ val |= (tmp2 >> 2) & 0x0f; ++ m88ds3103_writereg(state, 0xfe, val); ++ ++ val = (u8)((tmp2 & 0x03) << 6); ++ val |= tmp1; ++ m88ds3103_writereg(state, 0xea, val); ++ } ++ } ++ return 0; ++} ++ ++static int m88ds3103_demod_connect(struct dvb_frontend *fe, s32 carrier_offset_khz) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ u16 value; ++ u8 val1,val2,data; ++ ++ dprintk("connect delivery system = %d\n", state->delivery_system); ++ ++ /* ds3000 global reset */ ++ m88ds3103_writereg(state, 0x07, 0x80); ++ m88ds3103_writereg(state, 0x07, 0x00); ++ /* ds3000 build-in uC reset */ ++ m88ds3103_writereg(state, 0xb2, 0x01); ++ /* ds3000 software reset */ ++ m88ds3103_writereg(state, 0x00, 0x01); ++ ++ switch (state->delivery_system) { ++ case SYS_DVBS: ++ /* initialise the demod in DVB-S mode */ ++ if(state->demod_id == DS3000_ID){ ++ m88ds3103_init_reg(state, ds3000_dvbs_init_tab, sizeof(ds3000_dvbs_init_tab)); ++ ++ value = m88ds3103_readreg(state, 0xfe); ++ value &= 0xc0; ++ value |= 0x1b; ++ m88ds3103_writereg(state, 0xfe, value); ++ ++ if(state->config->ci_mode) ++ val1 = 0x80; ++ else if(state->config->ts_mode) ++ val1 = 0x60; ++ else ++ val1 = 0x20; ++ m88ds3103_writereg(state, 0xfd, val1); ++ ++ }else if(state->demod_id == DS3103_ID){ ++ m88ds3103_init_reg(state, ds3103_dvbs_init_tab, sizeof(ds3103_dvbs_init_tab)); ++ ++ /* set ts clock */ ++ if(state->config->ci_mode == 2){ ++ val1 = 6; val2 = 6; ++ }else if(state->config->ts_mode == 0) { ++ val1 = 3; val2 = 3; ++ }else{ ++ val1 = 0; val2 = 0; ++ } ++ val1 -= 1; val2 -= 1; ++ val1 &= 0x3f; val2 &= 0x3f; ++ data = m88ds3103_readreg(state, 0xfe); ++ data &= 0xf0; ++ data |= (val2 >> 2) & 0x0f; ++ m88ds3103_writereg(state, 0xfe, data); ++ data = (val2 & 0x03) << 6; ++ data |= val1; ++ m88ds3103_writereg(state, 0xea, data); ++ ++ m88ds3103_writereg(state, 0x4d, 0xfd & m88ds3103_readreg(state, 0x4d)); ++ m88ds3103_writereg(state, 0x30, 0xef & m88ds3103_readreg(state, 0x30)); ++ ++ /* set master clock */ ++ val1 = m88ds3103_readreg(state, 0x22); ++ val2 = m88ds3103_readreg(state, 0x24); ++ ++ val1 &= 0x3f; ++ val2 &= 0x3f; ++ val1 |= 0x80; ++ val2 |= 0x40; ++ ++ m88ds3103_writereg(state, 0x22, val1); ++ m88ds3103_writereg(state, 0x24, val2); ++ ++ if(state->config->ci_mode) ++ val1 = 0x03; ++ else if(state->config->ts_mode) ++ val1 = 0x06; ++ else ++ val1 = 0x42; ++ m88ds3103_writereg(state, 0xfd, val1); ++ } ++ break; ++ case SYS_DVBS2: ++ /* initialise the demod in DVB-S2 mode */ ++ if(state->demod_id == DS3000_ID){ ++ m88ds3103_init_reg(state, ds3000_dvbs2_init_tab, sizeof(ds3000_dvbs2_init_tab)); ++ ++ if (c->symbol_rate >= 30000000) ++ m88ds3103_writereg(state, 0xfe, 0x54); ++ else ++ m88ds3103_writereg(state, 0xfe, 0x98); ++ ++ }else if(state->demod_id == DS3103_ID){ ++ m88ds3103_init_reg(state, ds3103_dvbs2_init_tab, sizeof(ds3103_dvbs2_init_tab)); ++ ++ /* set ts clock */ ++ if(state->config->ci_mode == 2){ ++ val1 = 6; val2 = 6; ++ }else if(state->config->ts_mode == 0){ ++ val1 = 5; val2 = 4; ++ }else{ ++ val1 = 0; val2 = 0; ++ } ++ val1 -= 1; val2 -= 1; ++ val1 &= 0x3f; val2 &= 0x3f; ++ data = m88ds3103_readreg(state, 0xfe); ++ data &= 0xf0; ++ data |= (val2 >> 2) & 0x0f; ++ m88ds3103_writereg(state, 0xfe, data); ++ data = (val2 & 0x03) << 6; ++ data |= val1; ++ m88ds3103_writereg(state, 0xea, data); ++ ++ m88ds3103_writereg(state, 0x4d, 0xfd & m88ds3103_readreg(state, 0x4d)); ++ m88ds3103_writereg(state, 0x30, 0xef & m88ds3103_readreg(state, 0x30)); ++ ++ /* set master clock */ ++ val1 = m88ds3103_readreg(state, 0x22); ++ val2 = m88ds3103_readreg(state, 0x24); ++ ++ val1 &= 0x3f; ++ val2 &= 0x3f; ++ if((state->config->ci_mode == 2) || (state->config->ts_mode == 1)){ ++ val1 |= 0x80; ++ val2 |= 0x40; ++ }else{ ++ if (c->symbol_rate >= 28000000){ ++ val1 |= 0xc0; ++ }else if (c->symbol_rate >= 18000000){ ++ val2 |= 0x40; ++ }else{ ++ val1 |= 0x80; ++ val2 |= 0x40; ++ } ++ } ++ m88ds3103_writereg(state, 0x22, val1); ++ m88ds3103_writereg(state, 0x24, val2); ++ } ++ ++ if(state->config->ci_mode) ++ val1 = 0x03; ++ else if(state->config->ts_mode) ++ val1 = 0x06; ++ else ++ val1 = 0x42; ++ m88ds3103_writereg(state, 0xfd, val1); ++ ++ break; ++ default: ++ return 1; ++ } ++ /* disable 27MHz clock output */ ++ m88ds3103_writereg(state, 0x29, 0x80); ++ /* enable ac coupling */ ++ m88ds3103_writereg(state, 0x25, 0x8a); ++ ++ if ((c->symbol_rate / 1000) <= 3000){ ++ m88ds3103_writereg(state, 0xc3, 0x08); /* 8 * 32 * 100 / 64 = 400*/ ++ m88ds3103_writereg(state, 0xc8, 0x20); ++ m88ds3103_writereg(state, 0xc4, 0x08); /* 8 * 0 * 100 / 128 = 0*/ ++ m88ds3103_writereg(state, 0xc7, 0x00); ++ }else if((c->symbol_rate / 1000) <= 10000){ ++ m88ds3103_writereg(state, 0xc3, 0x08); /* 8 * 16 * 100 / 64 = 200*/ ++ m88ds3103_writereg(state, 0xc8, 0x10); ++ m88ds3103_writereg(state, 0xc4, 0x08); /* 8 * 0 * 100 / 128 = 0*/ ++ m88ds3103_writereg(state, 0xc7, 0x00); ++ }else{ ++ m88ds3103_writereg(state, 0xc3, 0x08); /* 8 * 6 * 100 / 64 = 75*/ ++ m88ds3103_writereg(state, 0xc8, 0x06); ++ m88ds3103_writereg(state, 0xc4, 0x08); /* 8 * 0 * 100 / 128 = 0*/ ++ m88ds3103_writereg(state, 0xc7, 0x00); ++ } ++ ++ m88ds3103_set_symrate(fe); ++ ++ m88ds3103_set_CCI(fe); ++ ++ m88ds3103_set_carrier_offset(fe, carrier_offset_khz); ++ ++ /* ds3000 out of software reset */ ++ m88ds3103_writereg(state, 0x00, 0x00); ++ /* start ds3000 build-in uC */ ++ m88ds3103_writereg(state, 0xb2, 0x00); ++ ++ return 0; ++} ++ ++static int m88ds3103_set_frontend(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ struct dtv_frontend_properties *c = &fe->dtv_property_cache; ++ ++ int i; ++ fe_status_t status; ++ u8 lpf_mxdiv, mlpf_max, mlpf_min, nlpf, div4, capCode, changePLL; ++ s32 offset_khz, lpf_offset_KHz; ++ u16 value, ndiv, lpf_coeff; ++ u32 f3db, gdiv28, realFreq; ++ u8 RFgain; ++ ++ dprintk("%s() ", __func__); ++ dprintk("c frequency = %d\n", c->frequency); ++ dprintk("symbol rate = %d\n", c->symbol_rate); ++ dprintk("delivery system = %d\n", c->delivery_system); ++ ++ realFreq = c->frequency; ++ lpf_offset_KHz = 0; ++ if(c->symbol_rate < 5000000){ ++ lpf_offset_KHz = FREQ_OFFSET_AT_SMALL_SYM_RATE_KHz; ++ realFreq += FREQ_OFFSET_AT_SMALL_SYM_RATE_KHz; ++ } ++ ++ if (state->config->set_ts_params) ++ state->config->set_ts_params(fe, 0); ++ ++ div4 = 0; ++ RFgain = 0; ++ if(state->tuner_id == TS2022_ID){ ++ m88ds3103_tuner_writereg(state, 0x10, 0x0a); ++ m88ds3103_tuner_writereg(state, 0x11, 0x40); ++ if (realFreq < 1103000) { ++ m88ds3103_tuner_writereg(state, 0x10, 0x1b); ++ div4 = 1; ++ ndiv = (realFreq * (6 + 8) * 4)/MT_FE_CRYSTAL_KHZ; ++ }else { ++ ndiv = (realFreq * (6 + 8) * 2)/MT_FE_CRYSTAL_KHZ; ++ } ++ ndiv = ndiv + ndiv%2; ++ if(ndiv < 4095) ++ ndiv = ndiv - 1024; ++ else if (ndiv < 6143) ++ ndiv = ndiv + 1024; ++ else ++ ndiv = ndiv + 3072; ++ ++ m88ds3103_tuner_writereg(state, 0x01, (ndiv & 0x3f00) >> 8); ++ }else{ ++ m88ds3103_tuner_writereg(state, 0x10, 0x00); ++ if (realFreq < 1146000){ ++ m88ds3103_tuner_writereg(state, 0x10, 0x11); ++ div4 = 1; ++ ndiv = (realFreq * (6 + 8) * 4) / MT_FE_CRYSTAL_KHZ; ++ }else{ ++ m88ds3103_tuner_writereg(state, 0x10, 0x01); ++ ndiv = (realFreq * (6 + 8) * 2) / MT_FE_CRYSTAL_KHZ; ++ } ++ ndiv = ndiv + ndiv%2; ++ ndiv = ndiv - 1024; ++ m88ds3103_tuner_writereg(state, 0x01, (ndiv>>8)&0x0f); ++ } ++ /* set pll */ ++ m88ds3103_tuner_writereg(state, 0x02, ndiv & 0x00ff); ++ m88ds3103_tuner_writereg(state, 0x03, 0x06); ++ m88ds3103_tuner_writereg(state, 0x51, 0x0f); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x10); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ ++ if(state->tuner_id == TS2022_ID){ ++ if(( realFreq >= 1650000 ) && (realFreq <= 1850000)){ ++ msleep(5); ++ value = m88ds3103_tuner_readreg(state, 0x14); ++ value &= 0x7f; ++ if(value < 64){ ++ m88ds3103_tuner_writereg(state, 0x10, 0x82); ++ m88ds3103_tuner_writereg(state, 0x11, 0x6f); ++ ++ m88ds3103_tuner_writereg(state, 0x51, 0x0f); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x10); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ } ++ } ++ msleep(5); ++ value = m88ds3103_tuner_readreg(state, 0x14); ++ value &= 0x1f; ++ ++ if(value > 19){ ++ value = m88ds3103_tuner_readreg(state, 0x10); ++ value &= 0x1d; ++ m88ds3103_tuner_writereg(state, 0x10, value); ++ } ++ }else{ ++ msleep(5); ++ value = m88ds3103_tuner_readreg(state, 0x66); ++ changePLL = (((value & 0x80) >> 7) != div4); ++ ++ if(changePLL){ ++ m88ds3103_tuner_writereg(state, 0x10, 0x11); ++ div4 = 1; ++ ndiv = (realFreq * (6 + 8) * 4)/MT_FE_CRYSTAL_KHZ; ++ ndiv = ndiv + ndiv%2; ++ ndiv = ndiv - 1024; ++ ++ m88ds3103_tuner_writereg(state, 0x01, (ndiv>>8) & 0x0f); ++ m88ds3103_tuner_writereg(state, 0x02, ndiv & 0xff); ++ ++ m88ds3103_tuner_writereg(state, 0x51, 0x0f); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x10); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ } ++ } ++ /*set the RF gain*/ ++ if(state->tuner_id == TS2020_ID) ++ m88ds3103_tuner_writereg(state, 0x60, 0x79); ++ ++ m88ds3103_tuner_writereg(state, 0x51, 0x17); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x08); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ msleep(5); ++ ++ if(state->tuner_id == TS2020_ID){ ++ RFgain = m88ds3103_tuner_readreg(state, 0x3d); ++ RFgain &= 0x0f; ++ if(RFgain < 15){ ++ if(RFgain < 4) ++ RFgain = 0; ++ else ++ RFgain = RFgain -3; ++ value = ((RFgain << 3) | 0x01) & 0x79; ++ m88ds3103_tuner_writereg(state, 0x60, value); ++ m88ds3103_tuner_writereg(state, 0x51, 0x17); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x08); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ } ++ } ++ ++ /* set the LPF */ ++ if(state->tuner_id == TS2022_ID){ ++ m88ds3103_tuner_writereg(state, 0x25, 0x00); ++ m88ds3103_tuner_writereg(state, 0x27, 0x70); ++ m88ds3103_tuner_writereg(state, 0x41, 0x09); ++ m88ds3103_tuner_writereg(state, 0x08, 0x0b); ++ } ++ ++ f3db = ((c->symbol_rate / 1000) *135) / 200 + 2000; ++ f3db += lpf_offset_KHz; ++ if (f3db < 7000) ++ f3db = 7000; ++ if (f3db > 40000) ++ f3db = 40000; ++ ++ gdiv28 = (MT_FE_CRYSTAL_KHZ / 1000 * 1694 + 500) / 1000; ++ m88ds3103_tuner_writereg(state, 0x04, gdiv28 & 0xff); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1b); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x04); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ msleep(5); ++ ++ value = m88ds3103_tuner_readreg(state, 0x26); ++ capCode = value & 0x3f; ++ if(state->tuner_id == TS2022_ID){ ++ m88ds3103_tuner_writereg(state, 0x41, 0x0d); ++ ++ m88ds3103_tuner_writereg(state, 0x51, 0x1b); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x04); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ ++ msleep(2); ++ ++ value = m88ds3103_tuner_readreg(state, 0x26); ++ value &= 0x3f; ++ value = (capCode + value) / 2; ++ } ++ else ++ value = capCode; ++ ++ gdiv28 = gdiv28 * 207 / (value * 2 + 151); ++ mlpf_max = gdiv28 * 135 / 100; ++ mlpf_min = gdiv28 * 78 / 100; ++ if (mlpf_max > 63) ++ mlpf_max = 63; ++ ++ if(state->tuner_id == TS2022_ID) ++ lpf_coeff = 3200; ++ else ++ lpf_coeff = 2766; ++ ++ nlpf = (f3db * gdiv28 * 2 / lpf_coeff / (MT_FE_CRYSTAL_KHZ / 1000) + 1) / 2 ; ++ if (nlpf > 23) nlpf = 23; ++ if (nlpf < 1) nlpf = 1; ++ ++ lpf_mxdiv = (nlpf * (MT_FE_CRYSTAL_KHZ / 1000) * lpf_coeff * 2 / f3db + 1) / 2; ++ ++ if (lpf_mxdiv < mlpf_min){ ++ nlpf++; ++ lpf_mxdiv = (nlpf * (MT_FE_CRYSTAL_KHZ / 1000) * lpf_coeff * 2 / f3db + 1) / 2; ++ } ++ ++ if (lpf_mxdiv > mlpf_max) ++ lpf_mxdiv = mlpf_max; ++ ++ m88ds3103_tuner_writereg(state, 0x04, lpf_mxdiv); ++ m88ds3103_tuner_writereg(state, 0x06, nlpf); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1b); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x04); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ msleep(5); ++ ++ if(state->tuner_id == TS2022_ID){ ++ msleep(2); ++ value = m88ds3103_tuner_readreg(state, 0x26); ++ capCode = value & 0x3f; ++ ++ m88ds3103_tuner_writereg(state, 0x41, 0x09); ++ ++ m88ds3103_tuner_writereg(state, 0x51, 0x1b); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x04); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ ++ msleep(2); ++ value = m88ds3103_tuner_readreg(state, 0x26); ++ value &= 0x3f; ++ value = (capCode + value) / 2; ++ ++ value = value | 0x80; ++ m88ds3103_tuner_writereg(state, 0x25, value); ++ m88ds3103_tuner_writereg(state, 0x27, 0x30); ++ ++ m88ds3103_tuner_writereg(state, 0x08, 0x09); ++ } ++ ++ /* Set the BB gain */ ++ m88ds3103_tuner_writereg(state, 0x51, 0x1e); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x01); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ if(state->tuner_id == TS2020_ID){ ++ if(RFgain == 15){ ++ msleep(40); ++ value = m88ds3103_tuner_readreg(state, 0x21); ++ value &= 0x0f; ++ if(value < 3){ ++ m88ds3103_tuner_writereg(state, 0x60, 0x61); ++ m88ds3103_tuner_writereg(state, 0x51, 0x17); ++ m88ds3103_tuner_writereg(state, 0x51, 0x1f); ++ m88ds3103_tuner_writereg(state, 0x50, 0x08); ++ m88ds3103_tuner_writereg(state, 0x50, 0x00); ++ } ++ } ++ } ++ msleep(60); ++ ++ offset_khz = (ndiv - ndiv % 2 + 1024) * MT_FE_CRYSTAL_KHZ ++ / (6 + 8) / (div4 + 1) / 2 - realFreq; ++ ++ m88ds3103_demod_connect(fe, offset_khz+lpf_offset_KHz); ++ ++ for (i = 0; i < 30 ; i++) { ++ m88ds3103_read_status(fe, &status); ++ if (status & FE_HAS_LOCK){ ++ break; ++ } ++ msleep(20); ++ } ++ ++ if((status & FE_HAS_LOCK) == 0){ ++ state->delivery_system = (state->delivery_system == SYS_DVBS) ? SYS_DVBS2 : SYS_DVBS; ++ m88ds3103_demod_connect(fe, offset_khz); ++ ++ for (i = 0; i < 30 ; i++) { ++ m88ds3103_read_status(fe, &status); ++ if (status & FE_HAS_LOCK){ ++ break; ++ } ++ msleep(20); ++ } ++ } ++ ++ if (status & FE_HAS_LOCK){ ++ if(state->config->ci_mode == 2) ++ m88ds3103_set_clock_ratio(state); ++ if(state->config->start_ctrl){ ++ if(state->first_lock == 0){ ++ state->config->start_ctrl(fe); ++ state->first_lock = 1; ++ } ++ } ++ } ++ ++ return 0; ++} ++ ++static int m88ds3103_tune(struct dvb_frontend *fe, ++ bool re_tune, ++ unsigned int mode_flags, ++ unsigned int *delay, ++ fe_status_t *status) ++{ ++ *delay = HZ / 5; ++ ++ dprintk("%s() ", __func__); ++ dprintk("re_tune = %d\n", re_tune); ++ ++ if (re_tune) { ++ int ret = m88ds3103_set_frontend(fe); ++ if (ret) ++ return ret; ++ } ++ ++ return m88ds3103_read_status(fe, status); ++} ++ ++static enum dvbfe_algo m88ds3103_get_algo(struct dvb_frontend *fe) ++{ ++ return DVBFE_ALGO_HW; ++} ++ ++ /* ++ * Power config will reset and load initial firmware if required ++ */ ++static int m88ds3103_initilaze(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ int ret; ++ ++ dprintk("%s()\n", __func__); ++ /* hard reset */ ++ m88ds3103_writereg(state, 0x07, 0x80); ++ m88ds3103_writereg(state, 0x07, 0x00); ++ msleep(1); ++ ++ m88ds3103_writereg(state, 0x08, 0x01 | m88ds3103_readreg(state, 0x08)); ++ msleep(1); ++ ++ if(state->tuner_id == TS2020_ID){ ++ /* TS2020 init */ ++ m88ds3103_tuner_writereg(state, 0x42, 0x73); ++ msleep(2); ++ m88ds3103_tuner_writereg(state, 0x05, 0x01); ++ m88ds3103_tuner_writereg(state, 0x62, 0xb5); ++ m88ds3103_tuner_writereg(state, 0x07, 0x02); ++ m88ds3103_tuner_writereg(state, 0x08, 0x01); ++ } ++ else if(state->tuner_id == TS2022_ID){ ++ /* TS2022 init */ ++ m88ds3103_tuner_writereg(state, 0x62, 0x6c); ++ msleep(2); ++ m88ds3103_tuner_writereg(state, 0x42, 0x6c); ++ msleep(2); ++ m88ds3103_tuner_writereg(state, 0x7d, 0x9d); ++ m88ds3103_tuner_writereg(state, 0x7c, 0x9a); ++ m88ds3103_tuner_writereg(state, 0x7a, 0x76); ++ ++ m88ds3103_tuner_writereg(state, 0x3b, 0x01); ++ m88ds3103_tuner_writereg(state, 0x63, 0x88); ++ ++ m88ds3103_tuner_writereg(state, 0x61, 0x85); ++ m88ds3103_tuner_writereg(state, 0x22, 0x30); ++ m88ds3103_tuner_writereg(state, 0x30, 0x40); ++ m88ds3103_tuner_writereg(state, 0x20, 0x23); ++ m88ds3103_tuner_writereg(state, 0x24, 0x02); ++ m88ds3103_tuner_writereg(state, 0x12, 0xa0); ++ } ++ ++ if(state->demod_id == DS3103_ID){ ++ m88ds3103_writereg(state, 0x07, 0xe0); ++ m88ds3103_writereg(state, 0x07, 0x00); ++ msleep(1); ++ } ++ m88ds3103_writereg(state, 0xb2, 0x01); ++ ++ /* Load the firmware if required */ ++ ret = m88ds3103_load_firmware(fe); ++ if (ret != 0){ ++ printk(KERN_ERR "%s: Unable initialize firmware\n", __func__); ++ return ret; ++ } ++ if(state->demod_id == DS3103_ID){ ++ m88ds3103_writereg(state, 0x4d, 0xfd & m88ds3103_readreg(state, 0x4d)); ++ m88ds3103_writereg(state, 0x30, 0xef & m88ds3103_readreg(state, 0x30)); ++ } ++ ++ return 0; ++} ++ ++/* ++ * Initialise or wake up device ++ */ ++static int m88ds3103_initfe(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ u8 val; ++ ++ dprintk("%s()\n", __func__); ++ ++ /* 1st step to wake up demod */ ++ m88ds3103_writereg(state, 0x08, 0x01 | m88ds3103_readreg(state, 0x08)); ++ m88ds3103_writereg(state, 0x04, 0xfe & m88ds3103_readreg(state, 0x04)); ++ m88ds3103_writereg(state, 0x23, 0xef & m88ds3103_readreg(state, 0x23)); ++ ++ /* 2nd step to wake up tuner */ ++ val = m88ds3103_tuner_readreg(state, 0x00) & 0xff; ++ if((val & 0x01) == 0){ ++ m88ds3103_tuner_writereg(state, 0x00, 0x01); ++ msleep(50); ++ } ++ m88ds3103_tuner_writereg(state, 0x00, 0x03); ++ msleep(50); ++ ++ return 0; ++} ++ ++/* Put device to sleep */ ++static int m88ds3103_sleep(struct dvb_frontend *fe) ++{ ++ struct m88ds3103_state *state = fe->demodulator_priv; ++ ++ dprintk("%s()\n", __func__); ++ ++ /* 1st step to sleep tuner */ ++ m88ds3103_tuner_writereg(state, 0x00, 0x00); ++ ++ /* 2nd step to sleep demod */ ++ m88ds3103_writereg(state, 0x08, 0xfe & m88ds3103_readreg(state, 0x08)); ++ m88ds3103_writereg(state, 0x04, 0x01 | m88ds3103_readreg(state, 0x04)); ++ m88ds3103_writereg(state, 0x23, 0x10 | m88ds3103_readreg(state, 0x23)); ++ ++ ++ return 0; ++} ++ ++static struct dvb_frontend_ops m88ds3103_ops = { ++ .delsys = { SYS_DVBS, SYS_DVBS2}, ++ .info = { ++ .name = "Montage DS3103/TS2022", ++ .type = FE_QPSK, ++ .frequency_min = 950000, ++ .frequency_max = 2150000, ++ .frequency_stepsize = 1011, /* kHz for QPSK frontends */ ++ .frequency_tolerance = 5000, ++ .symbol_rate_min = 1000000, ++ .symbol_rate_max = 45000000, ++ .caps = FE_CAN_INVERSION_AUTO | ++ FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | ++ FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | ++ FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | ++ FE_CAN_2G_MODULATION | ++ FE_CAN_QPSK | FE_CAN_RECOVER ++ }, ++ ++ .release = m88ds3103_release, ++ ++ .init = m88ds3103_initfe, ++ .sleep = m88ds3103_sleep, ++ .read_status = m88ds3103_read_status, ++ .read_ber = m88ds3103_read_ber, ++ .read_signal_strength = m88ds3103_read_signal_strength, ++ .read_snr = m88ds3103_read_snr, ++ .read_ucblocks = m88ds3103_read_ucblocks, ++ .set_tone = m88ds3103_set_tone, ++ .set_voltage = m88ds3103_set_voltage, ++ .diseqc_send_master_cmd = m88ds3103_send_diseqc_msg, ++ .diseqc_send_burst = m88ds3103_diseqc_send_burst, ++ .get_frontend_algo = m88ds3103_get_algo, ++ .tune = m88ds3103_tune, ++ .set_frontend = m88ds3103_set_frontend, ++}; ++ ++MODULE_DESCRIPTION("DVB Frontend module for Montage DS3103/TS2022 hardware"); ++MODULE_AUTHOR("Max nibble"); ++MODULE_LICENSE("GPL"); +diff -urN a/drivers/media/dvb-frontends/m88ds3103.h b/drivers/media/dvb-frontends/m88ds3103.h +--- a/drivers/media/dvb-frontends/m88ds3103.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/media/dvb-frontends/m88ds3103.h 2013-01-30 12:33:51.000000000 +0800 +@@ -0,0 +1,53 @@ ++/* ++ Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef M88DS3103_H ++#define M88DS3103_H ++ ++#include ++ ++struct m88ds3103_config { ++ /* the demodulator's i2c address */ ++ u8 demod_address; ++ u8 ci_mode; ++ u8 pin_ctrl; ++ u8 ts_mode; /* 0: Parallel, 1: Serial */ ++ ++ /* Set device param to start dma */ ++ int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured); ++ /* Start to transfer data */ ++ int (*start_ctrl)(struct dvb_frontend *fe); ++ /* Set LNB voltage */ ++ int (*set_voltage)(struct dvb_frontend* fe, fe_sec_voltage_t voltage); ++}; ++ ++#if defined(CONFIG_DVB_M88DS3103) || \ ++ (defined(CONFIG_DVB_M88DS3103_MODULE) && defined(MODULE)) ++extern struct dvb_frontend *m88ds3103_attach( ++ const struct m88ds3103_config *config, ++ struct i2c_adapter *i2c); ++#else ++static inline struct dvb_frontend *m88ds3103_attach( ++ const struct m88ds3103_config *config, ++ struct i2c_adapter *i2c) ++{ ++ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); ++ return NULL; ++} ++#endif /* CONFIG_DVB_M88DS3103 */ ++#endif /* M88DS3103_H */ +diff -urN a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h +--- a/drivers/media/dvb-frontends/m88ds3103_priv.h 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/media/dvb-frontends/m88ds3103_priv.h 2013-01-30 12:33:56.000000000 +0800 +@@ -0,0 +1,403 @@ ++/* ++ Montage Technology M88DS3103/M88TS2022 - DVBS/S2 Satellite demod/tuner driver ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#ifndef M88DS3103_PRIV_H ++#define M88DS3103_PRIV_H ++ ++#define FW_DOWN_SIZE 32 ++#define FW_DOWN_LOOP (8192/FW_DOWN_SIZE) ++#define DS3103_DEFAULT_FIRMWARE "dvb-fe-ds3103.fw" ++#define DS3000_DEFAULT_FIRMWARE "dvb-fe-ds300x.fw" ++#define MT_FE_MCLK_KHZ 96000 /* in kHz */ ++#define MT_FE_CRYSTAL_KHZ 27000 /* in kHz */ ++#define FREQ_OFFSET_AT_SMALL_SYM_RATE_KHz 3000 ++#define DS3000_ID 0x3000 ++#define DS3103_ID 0x3103 ++#define TS2020_ID 0x2020 ++#define TS2022_ID 0x2022 ++#define UNKNOW_ID 0x0000 ++ ++struct m88ds3103_state { ++ struct i2c_adapter *i2c; ++ const struct m88ds3103_config *config; ++ ++ struct dvb_frontend frontend; ++ ++ u32 preBer; ++ u8 skip_fw_load; ++ u8 first_lock; /* The first time of signal lock */ ++ u16 demod_id; /* demod chip type */ ++ u16 tuner_id; /* tuner chip type */ ++ fe_delivery_system_t delivery_system; ++}; ++ ++/* For M88DS3103 demod dvbs mode.*/ ++static u8 ds3103_dvbs_init_tab[] = { ++ 0x23, 0x07, ++ 0x08, 0x03, ++ 0x0c, 0x02, ++ 0x21, 0x54, ++ 0x25, 0x82, ++ 0x27, 0x31, ++ 0x30, 0x08, ++ 0x31, 0x40, ++ 0x32, 0x32, ++ 0x33, 0x35, ++ 0x35, 0xff, ++ 0x3a, 0x00, ++ 0x37, 0x10, ++ 0x38, 0x10, ++ 0x39, 0x02, ++ 0x42, 0x60, ++ 0x4a, 0x80, ++ 0x4b, 0x04, ++ 0x4d, 0x91, ++ 0x5d, 0xc8, ++ 0x50, 0x36, ++ 0x51, 0x36, ++ 0x52, 0x36, ++ 0x53, 0x36, ++ 0x63, 0x0f, ++ 0x64, 0x30, ++ 0x65, 0x40, ++ 0x68, 0x26, ++ 0x69, 0x4c, ++ 0x70, 0x20, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x40, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x60, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x80, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0xa0, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x1f, ++ 0x76, 0x38, ++ 0x77, 0xa6, ++ 0x78, 0x0c, ++ 0x79, 0x80, ++ 0x7f, 0x14, ++ 0x7c, 0x00, ++ 0xae, 0x82, ++ 0x80, 0x64, ++ 0x81, 0x66, ++ 0x82, 0x44, ++ 0x85, 0x04, ++ 0xcd, 0xf4, ++ 0x90, 0x33, ++ 0xa0, 0x44, ++ 0xc0, 0x08, ++ 0xc3, 0x10, ++ 0xc4, 0x08, ++ 0xc5, 0xf0, ++ 0xc6, 0xff, ++ 0xc7, 0x00, ++ 0xc8, 0x1a, ++ 0xc9, 0x80, ++ 0xe0, 0xf8, ++ 0xe6, 0x8b, ++ 0xd0, 0x40, ++ 0xf8, 0x20, ++ 0xfa, 0x0f, ++ 0x00, 0x00, ++ 0xbd, 0x01, ++ 0xb8, 0x00, ++}; ++/* For M88DS3103 demod dvbs2 mode.*/ ++static u8 ds3103_dvbs2_init_tab[] = { ++ 0x23, 0x07, ++ 0x08, 0x07, ++ 0x0c, 0x02, ++ 0x21, 0x54, ++ 0x25, 0x82, ++ 0x27, 0x31, ++ 0x30, 0x08, ++ 0x32, 0x32, ++ 0x33, 0x35, ++ 0x35, 0xff, ++ 0x3a, 0x00, ++ 0x37, 0x10, ++ 0x38, 0x10, ++ 0x39, 0x02, ++ 0x42, 0x60, ++ 0x4a, 0x80, ++ 0x4b, 0x04, ++ 0x4d, 0x91, ++ 0x5d, 0xc8, ++ 0x50, 0x36, ++ 0x51, 0x36, ++ 0x52, 0x36, ++ 0x53, 0x36, ++ 0x63, 0x0f, ++ 0x64, 0x10, ++ 0x65, 0x20, ++ 0x68, 0x46, ++ 0x69, 0xcd, ++ 0x70, 0x20, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x40, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x60, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x80, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0xa0, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x1f, ++ 0x76, 0x38, ++ 0x77, 0xa6, ++ 0x78, 0x0c, ++ 0x79, 0x80, ++ 0x7f, 0x14, ++ 0x85, 0x08, ++ 0xcd, 0xf4, ++ 0x90, 0x33, ++ 0x86, 0x00, ++ 0x87, 0x0f, ++ 0x89, 0x00, ++ 0x8b, 0x44, ++ 0x8c, 0x66, ++ 0x9d, 0xc1, ++ 0x8a, 0x10, ++ 0xad, 0x40, ++ 0xa0, 0x44, ++ 0xc0, 0x08, ++ 0xc1, 0x10, ++ 0xc2, 0x08, ++ 0xc3, 0x10, ++ 0xc4, 0x08, ++ 0xc5, 0xf0, ++ 0xc6, 0xff, ++ 0xc7, 0x00, ++ 0xc8, 0x1a, ++ 0xc9, 0x80, ++ 0xca, 0x23, ++ 0xcb, 0x24, ++ 0xcc, 0xf4, ++ 0xce, 0x74, ++ 0x00, 0x00, ++ 0xbd, 0x01, ++ 0xb8, 0x00, ++}; ++ ++/* For M88DS3000 demod dvbs mode.*/ ++static u8 ds3000_dvbs_init_tab[] = { ++ 0x23, 0x05, ++ 0x08, 0x03, ++ 0x0c, 0x02, ++ 0x21, 0x54, ++ 0x25, 0x82, ++ 0x27, 0x31, ++ 0x30, 0x08, ++ 0x31, 0x40, ++ 0x32, 0x32, ++ 0x33, 0x35, ++ 0x35, 0xff, ++ 0x3a, 0x00, ++ 0x37, 0x10, ++ 0x38, 0x10, ++ 0x39, 0x02, ++ 0x42, 0x60, ++ 0x4a, 0x40, ++ 0x4b, 0x04, ++ 0x4d, 0x91, ++ 0x5d, 0xc8, ++ 0x50, 0x77, ++ 0x51, 0x77, ++ 0x52, 0x36, ++ 0x53, 0x36, ++ 0x56, 0x01, ++ 0x63, 0x47, ++ 0x64, 0x30, ++ 0x65, 0x40, ++ 0x68, 0x26, ++ 0x69, 0x4c, ++ 0x70, 0x20, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x40, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x60, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x80, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0xa0, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x1f, ++ 0x76, 0x00, ++ 0x77, 0xd1, ++ 0x78, 0x0c, ++ 0x79, 0x80, ++ 0x7f, 0x04, ++ 0x7c, 0x00, ++ 0x80, 0x86, ++ 0x81, 0xa6, ++ 0x85, 0x04, ++ 0xcd, 0xf4, ++ 0x90, 0x33, ++ 0xa0, 0x44, ++ 0xc0, 0x18, ++ 0xc3, 0x10, ++ 0xc4, 0x08, ++ 0xc5, 0x80, ++ 0xc6, 0x80, ++ 0xc7, 0x0a, ++ 0xc8, 0x1a, ++ 0xc9, 0x80, ++ 0xfe, 0xb6, ++ 0xe0, 0xf8, ++ 0xe6, 0x8b, ++ 0xd0, 0x40, ++ 0xf8, 0x20, ++ 0xfa, 0x0f, ++ 0xad, 0x20, ++ 0xae, 0x07, ++ 0xb8, 0x00, ++}; ++ ++/* For M88DS3000 demod dvbs2 mode.*/ ++static u8 ds3000_dvbs2_init_tab[] = { ++ 0x23, 0x0f, ++ 0x08, 0x07, ++ 0x0c, 0x02, ++ 0x21, 0x54, ++ 0x25, 0x82, ++ 0x27, 0x31, ++ 0x30, 0x08, ++ 0x31, 0x32, ++ 0x32, 0x32, ++ 0x33, 0x35, ++ 0x35, 0xff, ++ 0x3a, 0x00, ++ 0x37, 0x10, ++ 0x38, 0x10, ++ 0x39, 0x02, ++ 0x42, 0x60, ++ 0x4a, 0x80, ++ 0x4b, 0x04, ++ 0x4d, 0x91, ++ 0x5d, 0x88, ++ 0x50, 0x36, ++ 0x51, 0x36, ++ 0x52, 0x36, ++ 0x53, 0x36, ++ 0x63, 0x60, ++ 0x64, 0x10, ++ 0x65, 0x10, ++ 0x68, 0x04, ++ 0x69, 0x29, ++ 0x70, 0x20, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x40, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x60, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x80, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0xa0, ++ 0x71, 0x70, ++ 0x72, 0x04, ++ 0x73, 0x00, ++ 0x70, 0x1f, ++ 0xa0, 0x44, ++ 0xc0, 0x08, ++ 0xc1, 0x10, ++ 0xc2, 0x08, ++ 0xc3, 0x10, ++ 0xc4, 0x08, ++ 0xc5, 0xf0, ++ 0xc6, 0xf0, ++ 0xc7, 0x0a, ++ 0xc8, 0x1a, ++ 0xc9, 0x80, ++ 0xca, 0x23, ++ 0xcb, 0x24, ++ 0xce, 0x74, ++ 0x56, 0x01, ++ 0x90, 0x03, ++ 0x76, 0x80, ++ 0x77, 0x42, ++ 0x78, 0x0a, ++ 0x79, 0x80, ++ 0xad, 0x40, ++ 0xae, 0x07, ++ 0x7f, 0xd4, ++ 0x7c, 0x00, ++ 0x80, 0xa8, ++ 0x81, 0xda, ++ 0x7c, 0x01, ++ 0x80, 0xda, ++ 0x81, 0xec, ++ 0x7c, 0x02, ++ 0x80, 0xca, ++ 0x81, 0xeb, ++ 0x7c, 0x03, ++ 0x80, 0xba, ++ 0x81, 0xdb, ++ 0x85, 0x08, ++ 0x86, 0x00, ++ 0x87, 0x02, ++ 0x89, 0x80, ++ 0x8b, 0x44, ++ 0x8c, 0xaa, ++ 0x8a, 0x10, ++ 0xba, 0x00, ++ 0xf5, 0x04, ++ 0xd2, 0x32, ++ 0xb8, 0x00, ++}; ++ ++#endif /* M88DS3103_PRIV_H */ +diff -urN a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile +--- a/drivers/media/dvb-frontends/Makefile 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/dvb-frontends/Makefile 2013-05-03 17:04:31.000000000 +0800 +@@ -103,4 +103,5 @@ + obj-$(CONFIG_DVB_RTL2832) += rtl2832.o + obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o + obj-$(CONFIG_DVB_AF9033) += af9033.o +- ++obj-$(CONFIG_DVB_M88DS3103) += m88ds3103.o ++obj-$(CONFIG_DVB_M88DC2800) += m88dc2800.o +diff -urN a/drivers/media/pci/cx23885/cimax2.c b/drivers/media/pci/cx23885/cimax2.c +--- a/drivers/media/pci/cx23885/cimax2.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/cimax2.c 2013-03-31 22:03:29.000000000 +0800 +@@ -415,7 +415,7 @@ + return state->status; + } + +-int netup_ci_init(struct cx23885_tsport *port) ++int netup_ci_init(struct cx23885_tsport *port, bool isDVBSky) + { + struct netup_ci_state *state; + u8 cimax_init[34] = { +@@ -464,6 +464,11 @@ + goto err; + } + ++ if(isDVBSky) { ++ cimax_init[32] = 0x22; ++ cimax_init[33] = 0x00; ++ } ++ + port->port_priv = state; + + switch (port->nr) { +@@ -537,3 +542,19 @@ + dvb_ca_en50221_release(&state->ca); + kfree(state); + } ++ ++/* CI irq handler for DVBSky board*/ ++int dvbsky_ci_slot_status(struct cx23885_dev *dev) ++{ ++ struct cx23885_tsport *port = NULL; ++ struct netup_ci_state *state = NULL; ++ ++ ci_dbg_print("%s:\n", __func__); ++ ++ port = &dev->ts1; ++ state = port->port_priv; ++ schedule_work(&state->work); ++ ci_dbg_print("%s: Wakeup CI0\n", __func__); ++ ++ return 1; ++} +diff -urN a/drivers/media/pci/cx23885/cimax2.h b/drivers/media/pci/cx23885/cimax2.h +--- a/drivers/media/pci/cx23885/cimax2.h 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/cimax2.h 2013-01-30 12:34:37.000000000 +0800 +@@ -41,7 +41,9 @@ + extern int netup_ci_slot_status(struct cx23885_dev *dev, u32 pci_status); + extern int netup_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, + int slot, int open); +-extern int netup_ci_init(struct cx23885_tsport *port); ++extern int netup_ci_init(struct cx23885_tsport *port, bool isDVBSky); + extern void netup_ci_exit(struct cx23885_tsport *port); + ++extern int dvbsky_ci_slot_status(struct cx23885_dev *dev); ++ + #endif +diff -urN a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c +--- a/drivers/media/pci/cx23885/cx23885-cards.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/cx23885-cards.c 2013-05-03 17:34:46.000000000 +0800 +@@ -569,6 +569,34 @@ + .name = "TeVii S471", + .portb = CX23885_MPEG_DVB, + }, ++ [CX23885_BOARD_BST_PS8512] = { ++ .name = "Bestunar PS8512", ++ .portb = CX23885_MPEG_DVB, ++ }, ++ [CX23885_BOARD_DVBSKY_S950] = { ++ .name = "DVBSKY S950", ++ .portb = CX23885_MPEG_DVB, ++ }, ++ [CX23885_BOARD_DVBSKY_S952] = { ++ .name = "DVBSKY S952", ++ .portb = CX23885_MPEG_DVB, ++ .portc = CX23885_MPEG_DVB, ++ }, ++ [CX23885_BOARD_DVBSKY_S950_CI] = { ++ .ci_type = 3, ++ .name = "DVBSKY S950CI DVB-S2 CI", ++ .portb = CX23885_MPEG_DVB, ++ }, ++ [CX23885_BOARD_DVBSKY_C2800E_CI] = { ++ .ci_type = 3, ++ .name = "DVBSKY C2800E DVB-C CI", ++ .portb = CX23885_MPEG_DVB, ++ }, ++ [CX23885_BOARD_DVBSKY_T9580] = { ++ .name = "DVBSKY T9580", ++ .portb = CX23885_MPEG_DVB, ++ .portc = CX23885_MPEG_DVB, ++ }, + [CX23885_BOARD_PROF_8000] = { + .name = "Prof Revolution DVB-S2 8000", + .portb = CX23885_MPEG_DVB, +@@ -605,7 +633,7 @@ + CX25840_NONE1_CH3, + .amux = CX25840_AUDIO6, + } }, +- } ++ } + }; + const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); + +@@ -818,6 +846,30 @@ + .subdevice = 0x9022, + .card = CX23885_BOARD_TEVII_S471, + }, { ++ .subvendor = 0x14f1, ++ .subdevice = 0x8512, ++ .card = CX23885_BOARD_BST_PS8512, ++ }, { ++ .subvendor = 0x4254, ++ .subdevice = 0x0950, ++ .card = CX23885_BOARD_DVBSKY_S950, ++ }, { ++ .subvendor = 0x4254, ++ .subdevice = 0x0952, ++ .card = CX23885_BOARD_DVBSKY_S952, ++ }, { ++ .subvendor = 0x4254, ++ .subdevice = 0x950C, ++ .card = CX23885_BOARD_DVBSKY_S950_CI, ++ }, { ++ .subvendor = 0x4254, ++ .subdevice = 0x2800, ++ .card = CX23885_BOARD_DVBSKY_C2800E_CI, ++ }, { ++ .subvendor = 0x4254, ++ .subdevice = 0x9580, ++ .card = CX23885_BOARD_DVBSKY_T9580, ++ }, { + .subvendor = 0x8000, + .subdevice = 0x3034, + .card = CX23885_BOARD_PROF_8000, +@@ -1224,7 +1276,7 @@ + cx_set(GP0_IO, 0x00040004); + break; + case CX23885_BOARD_TBS_6920: +- case CX23885_BOARD_PROF_8000: ++ case CX23885_BOARD_PROF_8000: + cx_write(MC417_CTL, 0x00000036); + cx_write(MC417_OEN, 0x00001000); + cx_set(MC417_RWD, 0x00000002); +@@ -1394,9 +1446,84 @@ + cx_set(GP0_IO, 0x00040004); + mdelay(60); + break; ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_BST_PS8512: ++ cx23885_gpio_enable(dev, GPIO_2, 1); ++ cx23885_gpio_clear(dev, GPIO_2); ++ msleep(100); ++ cx23885_gpio_set(dev, GPIO_2); ++ break; ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_T9580: ++ cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */ ++ ++ cx23885_gpio_enable(dev, GPIO_2, 1); ++ cx23885_gpio_enable(dev, GPIO_11, 1); ++ ++ cx23885_gpio_clear(dev, GPIO_2); ++ cx23885_gpio_clear(dev, GPIO_11); ++ msleep(100); ++ cx23885_gpio_set(dev, GPIO_2); ++ cx23885_gpio_set(dev, GPIO_11); ++ break; ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ /* GPIO-0 INTA from CiMax, input ++ GPIO-1 reset CiMax, output, high active ++ GPIO-2 reset demod, output, low active ++ GPIO-3 to GPIO-10 data/addr for CAM ++ GPIO-11 ~CS0 to CiMax1 ++ GPIO-12 ~CS1 to CiMax2 ++ GPIO-13 ADL0 load LSB addr ++ GPIO-14 ADL1 load MSB addr ++ GPIO-15 ~RDY from CiMax ++ GPIO-17 ~RD to CiMax ++ GPIO-18 ~WR to CiMax ++ */ ++ cx_set(GP0_IO, 0x00060002); /* GPIO 1/2 as output */ ++ cx_clear(GP0_IO, 0x00010004); /*GPIO 0 as input*/ ++ mdelay(100);/* reset delay */ ++ cx_set(GP0_IO, 0x00060004); /* GPIO as out, reset high */ ++ cx_clear(GP0_IO, 0x00010002); ++ cx_write(MC417_CTL, 0x00000037);/* enable GPIO3-18 pins */ ++ /* GPIO-15 IN as ~ACK, rest as OUT */ ++ cx_write(MC417_OEN, 0x00001000); ++ /* ~RD, ~WR high; ADL0, ADL1 low; ~CS0, ~CS1 high */ ++ cx_write(MC417_RWD, 0x0000c300); ++ /* enable irq */ ++ cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/ ++ break; + } + } + ++static int cx23885_ir_patch(struct i2c_adapter *i2c, u8 reg, u8 mask) ++{ ++ struct i2c_msg msgs[2]; ++ u8 tx_buf[2], rx_buf[1]; ++ /* Write register address */ ++ tx_buf[0] = reg; ++ msgs[0].addr = 0x4c; ++ msgs[0].flags = 0; ++ msgs[0].len = 1; ++ msgs[0].buf = (char *) tx_buf; ++ /* Read data from register */ ++ msgs[1].addr = 0x4c; ++ msgs[1].flags = I2C_M_RD; ++ msgs[1].len = 1; ++ msgs[1].buf = (char *) rx_buf; ++ ++ i2c_transfer(i2c, msgs, 2); ++ ++ tx_buf[0] = reg; ++ tx_buf[1] = rx_buf[0] | mask; ++ msgs[0].addr = 0x4c; ++ msgs[0].flags = 0; ++ msgs[0].len = 2; ++ msgs[0].buf = (char *) tx_buf; ++ ++ return i2c_transfer(i2c, msgs, 1); ++} ++ + int cx23885_ir_init(struct cx23885_dev *dev) + { + static struct v4l2_subdev_io_pin_config ir_rxtx_pin_cfg[] = { +@@ -1482,6 +1609,23 @@ + v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config, + ir_rx_pin_cfg_count, ir_rx_pin_cfg); + break; ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ case CX23885_BOARD_DVBSKY_T9580: ++ dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE); ++ if (dev->sd_ir == NULL) { ++ ret = -ENODEV; ++ break; ++ } ++ v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config, ++ ir_rx_pin_cfg_count, ir_rx_pin_cfg); ++ ++ cx23885_ir_patch(&(dev->i2c_bus[2].i2c_adap),0x1f,0x80); ++ cx23885_ir_patch(&(dev->i2c_bus[2].i2c_adap),0x23,0x80); ++ break; + case CX23885_BOARD_HAUPPAUGE_HVR1250: + if (!enable_885_ir) + break; +@@ -1511,9 +1655,15 @@ + cx23888_ir_remove(dev); + dev->sd_ir = NULL; + break; ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ case CX23885_BOARD_DVBSKY_T9580: + case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: + case CX23885_BOARD_TEVII_S470: +- case CX23885_BOARD_HAUPPAUGE_HVR1250: ++ case CX23885_BOARD_HAUPPAUGE_HVR1250: + case CX23885_BOARD_MYGICA_X8507: + cx23885_irq_remove(dev, PCI_MSK_AV_CORE); + /* sd_ir is a duplicate pointer to the AV Core, just clear it */ +@@ -1556,6 +1706,12 @@ + if (dev->sd_ir) + cx23885_irq_add_enable(dev, PCI_MSK_IR); + break; ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ case CX23885_BOARD_DVBSKY_T9580: + case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: + case CX23885_BOARD_TEVII_S470: + case CX23885_BOARD_HAUPPAUGE_HVR1250: +@@ -1657,6 +1813,10 @@ + ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + break; ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: + case CX23885_BOARD_TEVII_S470: + case CX23885_BOARD_TEVII_S471: + case CX23885_BOARD_DVBWORLD_2005: +@@ -1694,6 +1854,22 @@ + ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ + ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; + break; ++ case CX23885_BOARD_DVBSKY_S952: ++ ts1->gen_ctrl_val = 0x5; /* Parallel */ ++ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ++ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; ++ ts2->gen_ctrl_val = 0xe; /* Serial bus + punctured clock */ ++ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ++ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; ++ break; ++ case CX23885_BOARD_DVBSKY_T9580: ++ ts1->gen_ctrl_val = 0x5; /* Parallel */ ++ ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ++ ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; ++ ts2->gen_ctrl_val = 0x8; /* Serial bus */ ++ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ ++ ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO; ++ break; + case CX23885_BOARD_HAUPPAUGE_HVR1250: + case CX23885_BOARD_HAUPPAUGE_HVR1500: + case CX23885_BOARD_HAUPPAUGE_HVR1500Q: +@@ -1749,6 +1925,12 @@ + case CX23885_BOARD_MPX885: + case CX23885_BOARD_MYGICA_X8507: + case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ case CX23885_BOARD_DVBSKY_T9580: + case CX23885_BOARD_AVERMEDIA_HC81R: + dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, + &dev->i2c_bus[2].i2c_adap, +diff -urN a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c +--- a/drivers/media/pci/cx23885/cx23885-core.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/cx23885-core.c 2013-05-03 17:36:31.000000000 +0800 +@@ -1909,6 +1909,10 @@ + (pci_status & PCI_MSK_GPIO0)) + handled += altera_ci_irq(dev); + ++ if (cx23885_boards[dev->board].ci_type == 3 && ++ (pci_status & PCI_MSK_GPIO0)) ++ handled += dvbsky_ci_slot_status(dev); ++ + if (ts1_status) { + if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) + handled += cx23885_irq_ts(ts1, ts1_status); +@@ -2144,6 +2148,8 @@ + cx23885_irq_add_enable(dev, PCI_MSK_GPIO1 | PCI_MSK_GPIO0); + break; + case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: + cx23885_irq_add_enable(dev, PCI_MSK_GPIO0); + break; + } +diff -urN a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c +--- a/drivers/media/pci/cx23885/cx23885-dvb.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/cx23885-dvb.c 2013-05-03 17:38:34.000000000 +0800 +@@ -51,6 +51,8 @@ + #include "stv6110.h" + #include "lnbh24.h" + #include "cx24116.h" ++#include "m88ds3103.h" ++#include "m88dc2800.h" + #include "cimax2.h" + #include "lgs8gxx.h" + #include "netup-eeprom.h" +@@ -64,8 +66,8 @@ + #include "stv0367.h" + #include "drxk.h" + #include "mt2063.h" +-#include "stv090x.h" +-#include "stb6100.h" ++#include "stv090x.h" ++#include "stb6100.h" + #include "stb6100_cfg.h" + #include "tda10071.h" + #include "a8293.h" +@@ -500,42 +502,130 @@ + .if_khz = 5380, + }; + +-static struct stv090x_config prof_8000_stv090x_config = { +- .device = STV0903, +- .demod_mode = STV090x_SINGLE, +- .clk_mode = STV090x_CLK_EXT, +- .xtal = 27000000, +- .address = 0x6A, +- .ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, +- .repeater_level = STV090x_RPTLEVEL_64, +- .adc1_range = STV090x_ADC_2Vpp, +- .diseqc_envelope_mode = false, +- +- .tuner_get_frequency = stb6100_get_frequency, +- .tuner_set_frequency = stb6100_set_frequency, +- .tuner_set_bandwidth = stb6100_set_bandwidth, +- .tuner_get_bandwidth = stb6100_get_bandwidth, +-}; + +-static struct stb6100_config prof_8000_stb6100_config = { +- .tuner_address = 0x60, +- .refclock = 27000000, +-}; +- +-static int p8000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++/* bst control */ ++int bst_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) + { + struct cx23885_tsport *port = fe->dvb->priv; + struct cx23885_dev *dev = port->dev; ++ ++ cx23885_gpio_enable(dev, GPIO_1, 1); ++ cx23885_gpio_enable(dev, GPIO_0, 1); ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ cx23885_gpio_set(dev, GPIO_1); ++ cx23885_gpio_clear(dev, GPIO_0); ++ break; ++ case SEC_VOLTAGE_18: ++ cx23885_gpio_set(dev, GPIO_1); ++ cx23885_gpio_set(dev, GPIO_0); ++ break; ++ case SEC_VOLTAGE_OFF: ++ cx23885_gpio_clear(dev, GPIO_1); ++ cx23885_gpio_clear(dev, GPIO_0); ++ break; ++ } ++ return 0; ++} + +- if (voltage == SEC_VOLTAGE_18) +- cx_write(MC417_RWD, 0x00001e00); +- else if (voltage == SEC_VOLTAGE_13) +- cx_write(MC417_RWD, 0x00001a00); +- else +- cx_write(MC417_RWD, 0x00001800); ++int dvbsky_set_voltage_sec(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct cx23885_tsport *port = fe->dvb->priv; ++ struct cx23885_dev *dev = port->dev; ++ ++ cx23885_gpio_enable(dev, GPIO_12, 1); ++ cx23885_gpio_enable(dev, GPIO_13, 1); ++ ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ cx23885_gpio_set(dev, GPIO_13); ++ cx23885_gpio_clear(dev, GPIO_12); ++ break; ++ case SEC_VOLTAGE_18: ++ cx23885_gpio_set(dev, GPIO_13); ++ cx23885_gpio_set(dev, GPIO_12); ++ break; ++ case SEC_VOLTAGE_OFF: ++ cx23885_gpio_clear(dev, GPIO_13); ++ cx23885_gpio_clear(dev, GPIO_12); ++ break; ++ } + return 0; + } + ++/* bestunar single dvb-s2 */ ++static struct m88ds3103_config bst_ds3103_config = { ++ .demod_address = 0x68, ++ .ci_mode = 0, ++ .pin_ctrl = 0x82, ++ .ts_mode = 0, ++ .set_voltage = bst_set_voltage, ++}; ++/* DVBSKY dual dvb-s2 */ ++static struct m88ds3103_config dvbsky_ds3103_config_pri = { ++ .demod_address = 0x68, ++ .ci_mode = 0, ++ .pin_ctrl = 0x82, ++ .ts_mode = 0, ++ .set_voltage = bst_set_voltage, ++}; ++static struct m88ds3103_config dvbsky_ds3103_config_sec = { ++ .demod_address = 0x68, ++ .ci_mode = 0, ++ .pin_ctrl = 0x82, ++ .ts_mode = 1, ++ .set_voltage = dvbsky_set_voltage_sec, ++}; ++ ++static struct m88ds3103_config dvbsky_ds3103_ci_config = { ++ .demod_address = 0x68, ++ .ci_mode = 2, ++ .pin_ctrl = 0x82, ++ .ts_mode = 0, ++}; ++ ++static struct m88dc2800_config dvbsky_dc2800_config = { ++ .demod_address = 0x1c, ++ .ts_mode = 3, ++}; ++ ++static struct stv090x_config prof_8000_stv090x_config = { ++ .device = STV0903, ++ .demod_mode = STV090x_SINGLE, ++ .clk_mode = STV090x_CLK_EXT, ++ .xtal = 27000000, ++ .address = 0x6A, ++ .ts1_mode = STV090x_TSMODE_PARALLEL_PUNCTURED, ++ .repeater_level = STV090x_RPTLEVEL_64, ++ .adc1_range = STV090x_ADC_2Vpp, ++ .diseqc_envelope_mode = false, ++ ++ .tuner_get_frequency = stb6100_get_frequency, ++ .tuner_set_frequency = stb6100_set_frequency, ++ .tuner_set_bandwidth = stb6100_set_bandwidth, ++ .tuner_get_bandwidth = stb6100_get_bandwidth, ++}; ++ ++static struct stb6100_config prof_8000_stb6100_config = { ++ .tuner_address = 0x60, ++ .refclock = 27000000, ++}; ++ ++static int p8000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct cx23885_tsport *port = fe->dvb->priv; ++ struct cx23885_dev *dev = port->dev; ++ ++ if (voltage == SEC_VOLTAGE_18) ++ cx_write(MC417_RWD, 0x00001e00); ++ else if (voltage == SEC_VOLTAGE_13) ++ cx_write(MC417_RWD, 0x00001a00); ++ else ++ cx_write(MC417_RWD, 0x00001800); ++ return 0; ++} ++ + static int cx23885_dvb_set_frontend(struct dvb_frontend *fe) + { + struct dtv_frontend_properties *p = &fe->dtv_property_cache; +@@ -1250,23 +1340,79 @@ + &tevii_ds3000_config, + &i2c_bus->i2c_adap); + break; +- case CX23885_BOARD_PROF_8000: +- i2c_bus = &dev->i2c_bus[0]; ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ i2c_bus = &dev->i2c_bus[1]; ++ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, ++ &bst_ds3103_config, ++ &i2c_bus->i2c_adap); ++ break; ++ ++ case CX23885_BOARD_DVBSKY_S952: ++ switch (port->nr) { ++ /* port B */ ++ case 1: ++ i2c_bus = &dev->i2c_bus[1]; ++ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, ++ &dvbsky_ds3103_config_pri, ++ &i2c_bus->i2c_adap); ++ break; ++ /* port C */ ++ case 2: ++ i2c_bus = &dev->i2c_bus[0]; ++ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, ++ &dvbsky_ds3103_config_sec, ++ &i2c_bus->i2c_adap); ++ break; ++ } ++ break; + +- fe0->dvb.frontend = dvb_attach(stv090x_attach, +- &prof_8000_stv090x_config, +- &i2c_bus->i2c_adap, +- STV090x_DEMODULATOR_0); +- if (fe0->dvb.frontend != NULL) { +- if (!dvb_attach(stb6100_attach, +- fe0->dvb.frontend, +- &prof_8000_stb6100_config, +- &i2c_bus->i2c_adap)) +- goto frontend_detach; ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ i2c_bus = &dev->i2c_bus[1]; ++ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, ++ &dvbsky_ds3103_ci_config, ++ &i2c_bus->i2c_adap); ++ break; ++ ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ i2c_bus = &dev->i2c_bus[1]; ++ fe0->dvb.frontend = dvb_attach(m88dc2800_attach, ++ &dvbsky_dc2800_config, ++ &i2c_bus->i2c_adap); ++ break; + +- fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage; ++ case CX23885_BOARD_DVBSKY_T9580: ++ switch (port->nr) { ++ /* port B */ ++ case 1: ++ i2c_bus = &dev->i2c_bus[1]; ++ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, ++ &dvbsky_ds3103_config_pri, ++ &i2c_bus->i2c_adap); ++ break; ++ /* port C */ ++ case 2: ++ break; + } + break; ++ ++ case CX23885_BOARD_PROF_8000: ++ i2c_bus = &dev->i2c_bus[0]; ++ ++ fe0->dvb.frontend = dvb_attach(stv090x_attach, ++ &prof_8000_stv090x_config, ++ &i2c_bus->i2c_adap, ++ STV090x_DEMODULATOR_0); ++ if (fe0->dvb.frontend != NULL) { ++ if (!dvb_attach(stb6100_attach, ++ fe0->dvb.frontend, ++ &prof_8000_stb6100_config, ++ &i2c_bus->i2c_adap)) ++ goto frontend_detach; ++ ++ fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage; ++ } ++ break; + case CX23885_BOARD_HAUPPAUGE_HVR4400: + i2c_bus = &dev->i2c_bus[0]; + fe0->dvb.frontend = dvb_attach(tda10071_attach, +@@ -1325,7 +1471,7 @@ + printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n", + port->nr, port->frontends.adapter.proposed_mac); + +- netup_ci_init(port); ++ netup_ci_init(port, false); + break; + } + case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: { +@@ -1352,6 +1498,41 @@ + memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6); + break; + } ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_T9580:{ ++ u8 eeprom[256]; /* 24C02 i2c eeprom */ ++ ++ if(port->nr > 2) ++ break; ++ ++ dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; ++ tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); ++ printk(KERN_INFO "DVBSKY PCIe MAC= %pM\n", eeprom + 0xc0+(port->nr-1)*8); ++ memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 + ++ (port->nr-1)*8, 6); ++ break; ++ } ++ case CX23885_BOARD_DVBSKY_S950_CI: { ++ u8 eeprom[256]; /* 24C02 i2c eeprom */ ++ ++ if(port->nr > 2) ++ break; ++ ++ dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1; ++ tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom)); ++ printk(KERN_INFO "DVBSKY PCIe MAC= %pM\n", eeprom + 0xc0+(port->nr-1)*8); ++ memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 + ++ (port->nr-1)*8, 6); ++ ++ netup_ci_init(port, true); ++ break; ++ } ++ case CX23885_BOARD_DVBSKY_C2800E_CI: { ++ netup_ci_init(port, true); ++ break; ++ } + } + + return ret; +@@ -1434,6 +1615,8 @@ + + switch (port->dev->board) { + case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: + netup_ci_exit(port); + break; + case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: +diff -urN a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h +--- a/drivers/media/pci/cx23885/cx23885.h 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/cx23885.h 2013-05-03 17:14:20.000000000 +0800 +@@ -94,6 +94,14 @@ + #define CX23885_BOARD_HAUPPAUGE_HVR4400 38 + #define CX23885_BOARD_AVERMEDIA_HC81R 39 + ++#define CX23885_BOARD_BASE_INDEX 40 ++#define CX23885_BOARD_BST_PS8512 (CX23885_BOARD_BASE_INDEX) ++#define CX23885_BOARD_DVBSKY_S952 (CX23885_BOARD_BASE_INDEX+1) ++#define CX23885_BOARD_DVBSKY_S950 (CX23885_BOARD_BASE_INDEX+2) ++#define CX23885_BOARD_DVBSKY_S950_CI (CX23885_BOARD_BASE_INDEX+3) ++#define CX23885_BOARD_DVBSKY_C2800E_CI (CX23885_BOARD_BASE_INDEX+4) ++#define CX23885_BOARD_DVBSKY_T9580 (CX23885_BOARD_BASE_INDEX+5) ++ + #define GPIO_0 0x00000001 + #define GPIO_1 0x00000002 + #define GPIO_2 0x00000004 +@@ -231,7 +239,7 @@ + */ + u32 clk_freq; + struct cx23885_input input[MAX_CX23885_INPUT]; +- int ci_type; /* for NetUP */ ++ int ci_type; /* 1 and 2 for NetUP, 3 for DVBSky. */ + /* Force bottom field first during DMA (888 workaround) */ + u32 force_bff; + }; +diff -urN a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c +--- a/drivers/media/pci/cx23885/cx23885-input.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/cx23885-input.c 2013-05-03 17:42:09.000000000 +0800 +@@ -89,6 +89,12 @@ + case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL: + case CX23885_BOARD_TEVII_S470: + case CX23885_BOARD_HAUPPAUGE_HVR1250: ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ case CX23885_BOARD_DVBSKY_T9580: + case CX23885_BOARD_MYGICA_X8507: + /* + * The only boards we handle right now. However other boards +@@ -141,6 +147,12 @@ + case CX23885_BOARD_HAUPPAUGE_HVR1850: + case CX23885_BOARD_HAUPPAUGE_HVR1290: + case CX23885_BOARD_HAUPPAUGE_HVR1250: ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ case CX23885_BOARD_DVBSKY_T9580: + case CX23885_BOARD_MYGICA_X8507: + /* + * The IR controller on this board only returns pulse widths. +@@ -291,6 +303,18 @@ + /* A guess at the remote */ + rc_map = RC_MAP_TEVII_NEC; + break; ++ case CX23885_BOARD_BST_PS8512: ++ case CX23885_BOARD_DVBSKY_S950: ++ case CX23885_BOARD_DVBSKY_S952: ++ case CX23885_BOARD_DVBSKY_S950_CI: ++ case CX23885_BOARD_DVBSKY_C2800E_CI: ++ case CX23885_BOARD_DVBSKY_T9580: ++ /* Integrated CX2388[58] IR controller */ ++ driver_type = RC_DRIVER_IR_RAW; ++ allowed_protos = RC_BIT_ALL; ++ /* A guess at the remote */ ++ rc_map = RC_MAP_DVBSKY; ++ break; + case CX23885_BOARD_MYGICA_X8507: + /* Integrated CX23885 IR controller */ + driver_type = RC_DRIVER_IR_RAW; +diff -urN a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig +--- a/drivers/media/pci/cx23885/Kconfig 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx23885/Kconfig 2013-05-03 17:43:05.000000000 +0800 +@@ -23,6 +23,8 @@ + select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT + select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_M88DC2800 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT + select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT + select DVB_TS2020 if MEDIA_SUBDRV_AUTOSELECT +diff -urN a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c +--- a/drivers/media/pci/cx88/cx88-cards.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx88/cx88-cards.c 2013-05-03 17:06:55.000000000 +0800 +@@ -2309,6 +2309,18 @@ + } }, + .mpeg = CX88_MPEG_DVB, + }, ++ [CX88_BOARD_BST_PS8312] = { ++ .name = "Bestunar PS8312 DVB-S/S2", ++ .tuner_type = UNSET, ++ .radio_type = UNSET, ++ .tuner_addr = ADDR_UNSET, ++ .radio_addr = ADDR_UNSET, ++ .input = { { ++ .type = CX88_VMUX_DVB, ++ .vmux = 0, ++ } }, ++ .mpeg = CX88_MPEG_DVB, ++ }, + }; + + /* ------------------------------------------------------------------ */ +@@ -2813,6 +2825,10 @@ + .subvendor = 0x1822, + .subdevice = 0x0023, + .card = CX88_BOARD_TWINHAN_VP1027_DVBS, ++ }, { ++ .subvendor = 0x14f1, ++ .subdevice = 0x8312, ++ .card = CX88_BOARD_BST_PS8312, + }, + }; + +@@ -3547,6 +3563,12 @@ + cx_write(MO_SRST_IO, 1); + msleep(100); + break; ++ case CX88_BOARD_BST_PS8312: ++ cx_write(MO_GP1_IO, 0x808000); ++ msleep(100); ++ cx_write(MO_GP1_IO, 0x808080); ++ msleep(100); ++ break; + } /*end switch() */ + + +diff -urN a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c +--- a/drivers/media/pci/cx88/cx88-dvb.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx88/cx88-dvb.c 2013-05-03 17:09:09.000000000 +0800 +@@ -54,6 +54,7 @@ + #include "stv0288.h" + #include "stb6000.h" + #include "cx24116.h" ++#include "m88ds3103.h" + #include "stv0900.h" + #include "stb6100.h" + #include "stb6100_proc.h" +@@ -459,6 +460,56 @@ + return core->prev_set_voltage(fe, voltage); + return 0; + } ++/*CX88_BOARD_BST_PS8312*/ ++static int bst_dvbs_set_voltage(struct dvb_frontend *fe, ++ fe_sec_voltage_t voltage) ++{ ++ struct cx8802_dev *dev= fe->dvb->priv; ++ struct cx88_core *core = dev->core; ++ ++ cx_write(MO_GP1_IO, 0x111111); ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ cx_write(MO_GP1_IO, 0x020200); ++ break; ++ case SEC_VOLTAGE_18: ++ cx_write(MO_GP1_IO, 0x020202); ++ break; ++ case SEC_VOLTAGE_OFF: ++ cx_write(MO_GP1_IO, 0x111100); ++ break; ++ } ++ ++ if (core->prev_set_voltage) ++ return core->prev_set_voltage(fe, voltage); ++ return 0; ++} ++ ++static int bst_dvbs_set_voltage_v2(struct dvb_frontend *fe, ++ fe_sec_voltage_t voltage) ++{ ++ struct cx8802_dev *dev= fe->dvb->priv; ++ struct cx88_core *core = dev->core; ++ ++ cx_write(MO_GP1_IO, 0x111101); ++ switch (voltage) { ++ case SEC_VOLTAGE_13: ++ cx_write(MO_GP1_IO, 0x020200); ++ break; ++ case SEC_VOLTAGE_18: ++ ++ cx_write(MO_GP1_IO, 0x020202); ++ break; ++ case SEC_VOLTAGE_OFF: ++ ++ cx_write(MO_GP1_IO, 0x111110); ++ break; ++ } ++ ++ if (core->prev_set_voltage) ++ return core->prev_set_voltage(fe, voltage); ++ return 0; ++} + + static int vp1027_set_voltage(struct dvb_frontend *fe, + fe_sec_voltage_t voltage) +@@ -706,6 +757,11 @@ + .clk_out_div = 1, + }; + ++static struct m88ds3103_config dvbsky_ds3103_config = { ++ .demod_address = 0x68, ++ .set_ts_params = ds3000_set_ts_param, ++}; ++ + static const struct stv0900_config prof_7301_stv0900_config = { + .demod_address = 0x6a, + /* demod_mode = 0,*/ +@@ -1477,6 +1533,35 @@ + &tevii_ts2020_config, &core->i2c_adap); + fe0->dvb.frontend->ops.set_voltage = + tevii_dvbs_set_voltage; ++ } ++ break; ++ case CX88_BOARD_BST_PS8312: ++ fe0->dvb.frontend = dvb_attach(m88ds3103_attach, ++ &dvbsky_ds3103_config, ++ &core->i2c_adap); ++ if (fe0->dvb.frontend != NULL){ ++ int ret; ++ u8 b0[] = { 0x60 }; ++ u8 b1[2] = { 0 }; ++ struct i2c_msg msg[] = { ++ { ++ .addr = 0x50, ++ .flags = 0, ++ .buf = b0, ++ .len = 1 ++ }, { ++ .addr = 0x50, ++ .flags = I2C_M_RD, ++ .buf = b1, ++ .len = 2 ++ } ++ }; ++ ret = i2c_transfer(&core->i2c_adap, msg, 2); ++ printk("PS8312: config = %02x, %02x", b1[0],b1[1]); ++ if(b1[0] == 0xaa) ++ fe0->dvb.frontend->ops.set_voltage = bst_dvbs_set_voltage_v2; ++ else ++ fe0->dvb.frontend->ops.set_voltage = bst_dvbs_set_voltage; + } + break; + case CX88_BOARD_OMICOM_SS4_PCI: +diff -urN a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h +--- a/drivers/media/pci/cx88/cx88.h 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx88/cx88.h 2013-05-03 17:05:57.000000000 +0800 +@@ -238,6 +238,7 @@ + #define CX88_BOARD_WINFAST_DTV1800H_XC4000 88 + #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F36 89 + #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL_6F43 90 ++#define CX88_BOARD_BST_PS8312 91 + + enum cx88_itype { + CX88_VMUX_COMPOSITE1 = 1, +diff -urN a/drivers/media/pci/cx88/cx88-input.c b/drivers/media/pci/cx88/cx88-input.c +--- a/drivers/media/pci/cx88/cx88-input.c 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx88/cx88-input.c 2013-01-26 14:52:03.000000000 +0800 +@@ -419,6 +419,10 @@ + rc_type = RC_BIT_NEC; + ir->sampling = 0xff00; /* address */ + break; ++ case CX88_BOARD_BST_PS8312: ++ ir_codes = RC_MAP_DVBSKY; ++ ir->sampling = 0xff00; /* address */ ++ break; + } + + if (!ir_codes) { +diff -urN a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig +--- a/drivers/media/pci/cx88/Kconfig 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/pci/cx88/Kconfig 2013-05-03 17:10:41.000000000 +0800 +@@ -57,6 +57,7 @@ + select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT + select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT + select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT ++ select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT + select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT +diff -urN a/drivers/media/rc/keymaps/Makefile b/drivers/media/rc/keymaps/Makefile +--- a/drivers/media/rc/keymaps/Makefile 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/rc/keymaps/Makefile 2013-05-03 17:43:41.000000000 +0800 +@@ -27,6 +27,7 @@ + rc-dm1105-nec.o \ + rc-dntv-live-dvb-t.o \ + rc-dntv-live-dvbt-pro.o \ ++ rc-dvbsky.o \ + rc-em-terratec.o \ + rc-encore-enltv2.o \ + rc-encore-enltv.o \ +diff -urN a/drivers/media/rc/keymaps/rc-dvbsky.c b/drivers/media/rc/keymaps/rc-dvbsky.c +--- a/drivers/media/rc/keymaps/rc-dvbsky.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/media/rc/keymaps/rc-dvbsky.c 2013-01-26 14:52:49.000000000 +0800 +@@ -0,0 +1,78 @@ ++/* rc-dvbsky.c - Keytable for Dvbsky Remote Controllers ++ * ++ * keymap imported from ir-keymaps.c ++ * ++ * ++ * Copyright (c) 2010-2012 by Nibble Max ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++#include ++/* ++ * This table contains the complete RC5 code, instead of just the data part ++ */ ++ ++static struct rc_map_table rc5_dvbsky[] = { ++ { 0x0000, KEY_0 }, ++ { 0x0001, KEY_1 }, ++ { 0x0002, KEY_2 }, ++ { 0x0003, KEY_3 }, ++ { 0x0004, KEY_4 }, ++ { 0x0005, KEY_5 }, ++ { 0x0006, KEY_6 }, ++ { 0x0007, KEY_7 }, ++ { 0x0008, KEY_8 }, ++ { 0x0009, KEY_9 }, ++ { 0x000a, KEY_MUTE }, ++ { 0x000d, KEY_OK }, ++ { 0x000b, KEY_STOP }, ++ { 0x000c, KEY_EXIT }, ++ { 0x000e, KEY_CAMERA }, /*Snap shot*/ ++ { 0x000f, KEY_SUBTITLE }, /*PIP*/ ++ { 0x0010, KEY_VOLUMEUP }, ++ { 0x0011, KEY_VOLUMEDOWN }, ++ { 0x0012, KEY_FAVORITES }, ++ { 0x0013, KEY_LIST }, /*Info*/ ++ { 0x0016, KEY_PAUSE }, ++ { 0x0017, KEY_PLAY }, ++ { 0x001f, KEY_RECORD }, ++ { 0x0020, KEY_CHANNELDOWN }, ++ { 0x0021, KEY_CHANNELUP }, ++ { 0x0025, KEY_POWER2 }, ++ { 0x0026, KEY_REWIND }, ++ { 0x0027, KEY_FASTFORWARD }, ++ { 0x0029, KEY_LAST }, ++ { 0x002b, KEY_MENU }, ++ { 0x002c, KEY_EPG }, ++ { 0x002d, KEY_ZOOM }, ++}; ++ ++static struct rc_map_list rc5_dvbsky_map = { ++ .map = { ++ .scan = rc5_dvbsky, ++ .size = ARRAY_SIZE(rc5_dvbsky), ++ .rc_type = RC_TYPE_RC5, ++ .name = RC_MAP_DVBSKY, ++ } ++}; ++ ++static int __init init_rc_map_rc5_dvbsky(void) ++{ ++ return rc_map_register(&rc5_dvbsky_map); ++} ++ ++static void __exit exit_rc_map_rc5_dvbsky(void) ++{ ++ rc_map_unregister(&rc5_dvbsky_map); ++} ++ ++module_init(init_rc_map_rc5_dvbsky) ++module_exit(exit_rc_map_rc5_dvbsky) ++ ++MODULE_LICENSE("GPL"); ++MODULE_AUTHOR("Nibble Max "); +diff -urN a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c +--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c 1970-01-01 08:00:00.000000000 +0800 ++++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c 2013-05-03 17:47:38.000000000 +0800 +@@ -0,0 +1,665 @@ ++/* ++ * Driver for DVBSky USB2.0 receiver ++ * ++ * Copyright (C) 2013 Max nibble ++ * ++ * CIMax code is copied and modified from: ++ * CIMax2(R) SP2 driver in conjunction with NetUp Dual DVB-S2 CI card ++ * Copyright (C) 2009 NetUP Inc. ++ * Copyright (C) 2009 Igor M. Liplianin ++ * Copyright (C) 2009 Abylay Ospan ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ */ ++ ++#include "dvb_ca_en50221.h" ++#include "dvb_usb.h" ++#include "m88ds3103.h" ++ ++static int dvbsky_debug; ++module_param(dvbsky_debug, int, 0644); ++MODULE_PARM_DESC(dvbsky_debug, "Activates dvbsky usb debugging (default:0)"); ++ ++#define DVBSKY_CI_CTL 0x04 ++#define DVBSKY_CI_RD 1 ++ ++#define dprintk(args...) \ ++ do { \ ++ if (dvbsky_debug) \ ++ printk(KERN_INFO "dvbsky_usb: " args); \ ++ } while (0) ++ ++DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); ++ ++struct dvbsky_state { ++ struct mutex stream_mutex; ++ u8 has_ci; ++ u8 ci_attached; ++ struct dvb_ca_en50221 ci; ++ unsigned long next_status_checked_time; ++ u8 ci_i2c_addr; ++ u8 current_ci_flag; ++ int ci_status; ++}; ++ ++static int dvbsky_stream_ctrl(struct dvb_usb_device *d, u8 onoff) ++{ ++ struct dvbsky_state *state = d_to_priv(d); ++ int ret; ++ u8 obuf_pre[3] = { 0x37, 0, 0 }; ++ u8 obuf_post[3] = { 0x36, 3, 0 }; ++ dprintk("%s() -off \n", __func__); ++ mutex_lock(&state->stream_mutex); ++ ret = dvb_usbv2_generic_write(d, obuf_pre, 3); ++ if (!ret && onoff) { ++ msleep(10); ++ ret = dvb_usbv2_generic_write(d, obuf_post, 3); ++ dprintk("%s() -on \n", __func__); ++ } ++ mutex_unlock(&state->stream_mutex); ++ return ret; ++} ++ ++/* CI opertaions */ ++static int dvbsky_ci_read_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg, ++ u8 *buf, int len) ++{ ++ int ret; ++ struct i2c_msg msg[] = { ++ { ++ .addr = addr, ++ .flags = 0, ++ .buf = ®, ++ .len = 1 ++ }, { ++ .addr = addr, ++ .flags = I2C_M_RD, ++ .buf = buf, ++ .len = len ++ } ++ }; ++ ++ ret = i2c_transfer(i2c_adap, msg, 2); ++ ++ if (ret != 2) { ++ dprintk("%s: error, Reg = 0x%02x, Status = %d\n", __func__, reg, ret); ++ return -1; ++ } ++ return 0; ++} ++ ++static int dvbsky_ci_write_i2c(struct i2c_adapter *i2c_adap, u8 addr, u8 reg, ++ u8 *buf, int len) ++{ ++ int ret; ++ u8 buffer[len + 1]; ++ ++ struct i2c_msg msg = { ++ .addr = addr, ++ .flags = 0, ++ .buf = &buffer[0], ++ .len = len + 1 ++ }; ++ ++ buffer[0] = reg; ++ memcpy(&buffer[1], buf, len); ++ ++ ret = i2c_transfer(i2c_adap, &msg, 1); ++ ++ if (ret != 1) { ++ dprintk("%s: error, Reg=[0x%02x], Status=%d\n", __func__, reg, ret); ++ return -1; ++ } ++ return 0; ++} ++ ++static int dvbsky_ci_op_cam(struct dvb_ca_en50221 *ci, int slot, ++ u8 flag, u8 read, int addr, u8 data) ++{ ++ struct dvb_usb_device *d = ci->data; ++ struct dvbsky_state *state = d_to_priv(d); ++ u8 store; ++ int ret; ++ u8 command[4], respond[2], command_size, respond_size; ++ ++ /*dprintk("%s()\n", __func__);*/ ++ if (0 != slot) ++ return -EINVAL; ++ ++ if (state->current_ci_flag != flag) { ++ ret = dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &store, 1); ++ if (ret != 0) ++ return ret; ++ ++ store &= ~0x0c; ++ store |= flag; ++ ++ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &store, 1); ++ if (ret != 0) ++ return ret; ++ } ++ state->current_ci_flag = flag; ++ ++ command[1] = (u8)((addr >> 8) & 0xff); /*high part of address*/ ++ command[2] = (u8)(addr & 0xff); /*low part of address*/ ++ if (read) { ++ command[0] = 0x71; ++ command_size = 3; ++ respond_size = 2; ++ } else { ++ command[0] = 0x70; ++ command[3] = data; ++ command_size = 4; ++ respond_size = 1; ++ } ++ ret = dvb_usbv2_generic_rw(d, command, command_size, respond, respond_size); ++ ++ return (read) ? respond[1] : 0; ++} ++ ++static int dvbsky_ci_read_attribute_mem(struct dvb_ca_en50221 *ci, ++ int slot, int addr) ++{ ++ return dvbsky_ci_op_cam(ci, slot, 0, DVBSKY_CI_RD, addr, 0); ++} ++ ++static int dvbsky_ci_write_attribute_mem(struct dvb_ca_en50221 *ci, ++ int slot, int addr, u8 data) ++{ ++ return dvbsky_ci_op_cam(ci, slot, 0, 0, addr, data); ++} ++ ++static int dvbsky_ci_read_cam_ctl(struct dvb_ca_en50221 *ci, int slot, u8 addr) ++{ ++ return dvbsky_ci_op_cam(ci, slot, DVBSKY_CI_CTL, DVBSKY_CI_RD, addr, 0); ++} ++ ++static int dvbsky_ci_write_cam_ctl(struct dvb_ca_en50221 *ci, int slot, ++ u8 addr, u8 data) ++{ ++ return dvbsky_ci_op_cam(ci, slot, DVBSKY_CI_CTL, 0, addr, data); ++} ++ ++static int dvbsky_ci_slot_reset(struct dvb_ca_en50221 *ci, int slot) ++{ ++ struct dvb_usb_device *d = ci->data; ++ struct dvbsky_state *state = d_to_priv(d); ++ u8 buf = 0x80; ++ int ret; ++ dprintk("%s() slot=%d\n", __func__, slot); ++ ++ if (0 != slot) ++ return -EINVAL; ++ ++ udelay(500); ++ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &buf, 1); ++ ++ if (ret != 0) ++ return ret; ++ ++ udelay(500); ++ ++ buf = 0x00; ++ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &buf, 1); ++ msleep(1000); ++ dprintk("%s() slot=%d complete\n", __func__, slot); ++ return 0; ++ ++} ++ ++static int dvbsky_ci_slot_shutdown(struct dvb_ca_en50221 *ci, int slot) ++{ ++ /* not implemented */ ++ dprintk("%s()\n", __func__); ++ return 0; ++} ++ ++static int dvbsky_ci_slot_ts_enable(struct dvb_ca_en50221 *ci, int slot) ++{ ++ struct dvb_usb_device *d = ci->data; ++ struct dvbsky_state *state = d_to_priv(d); ++ u8 buf; ++ int ret; ++ ++ dprintk("%s()\n", __func__); ++ if (0 != slot) ++ return -EINVAL; ++ ++ dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &buf, 1); ++ buf |= 0x60; ++ ++ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &buf, 1); ++ return ret; ++} ++ ++static int dvbsky_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot, ++ int open) ++{ ++ struct dvb_usb_device *d = ci->data; ++ struct dvbsky_state *state = d_to_priv(d); ++ int ret = 0; ++ u8 buf = 0; ++ /*dprintk("%s()\n", __func__);*/ ++ ++ /* CAM module INSERT/REMOVE processing. slow operation because of i2c ++ * transfers */ ++ if (time_after(jiffies, state->next_status_checked_time)) { ++ ret = dvbsky_ci_read_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &buf, 1); ++ ++ /*dprintk("%s() status=%x\n", __func__, buf);*/ ++ ++ state->next_status_checked_time = jiffies ++ + msecs_to_jiffies(1000); ++ ++ if (ret != 0) ++ return 0; ++ ++ if (buf & 1) { ++ state->ci_status = DVB_CA_EN50221_POLL_CAM_PRESENT | ++ DVB_CA_EN50221_POLL_CAM_READY; ++ } ++ else ++ state->ci_status = 0; ++ } ++ /*dprintk("%s() ret=%x\n", __func__, state->ci_status);*/ ++ return state->ci_status; ++} ++ ++static int dvbsky_ci_init(struct dvb_usb_device *d) ++{ ++ struct dvbsky_state *state = d_to_priv(d); ++ int ret; ++ u8 cimax_init[34] = { ++ 0x00, /* module A control*/ ++ 0x00, /* auto select mask high A */ ++ 0x00, /* auto select mask low A */ ++ 0x00, /* auto select pattern high A */ ++ 0x00, /* auto select pattern low A */ ++ 0x44, /* memory access time A */ ++ 0x00, /* invert input A */ ++ 0x00, /* RFU */ ++ 0x00, /* RFU */ ++ 0x00, /* module B control*/ ++ 0x00, /* auto select mask high B */ ++ 0x00, /* auto select mask low B */ ++ 0x00, /* auto select pattern high B */ ++ 0x00, /* auto select pattern low B */ ++ 0x44, /* memory access time B */ ++ 0x00, /* invert input B */ ++ 0x00, /* RFU */ ++ 0x00, /* RFU */ ++ 0x00, /* auto select mask high Ext */ ++ 0x00, /* auto select mask low Ext */ ++ 0x00, /* auto select pattern high Ext */ ++ 0x00, /* auto select pattern low Ext */ ++ 0x00, /* RFU */ ++ 0x02, /* destination - module A */ ++ 0x01, /* power on (use it like store place) */ ++ 0x00, /* RFU */ ++ 0x00, /* int status read only */ ++ 0x00, /* Max: Disable the interrupt in USB solution.*/ ++ 0x05, /* EXTINT=active-high, INT=push-pull */ ++ 0x00, /* USCG1 */ ++ 0x04, /* ack active low */ ++ 0x00, /* LOCK = 0 */ ++ 0x22, /* serial mode, rising in, rising out, MSB first*/ ++ 0x00 /* synchronization */ ++ }; ++ dprintk("%s()\n", __func__); ++ state->current_ci_flag = 0xff; ++ state->ci_status = 0; ++ state->next_status_checked_time = jiffies + msecs_to_jiffies(1000); ++ state->ci_i2c_addr = 0x40; ++ ++ state->ci.owner = THIS_MODULE; ++ state->ci.read_attribute_mem = dvbsky_ci_read_attribute_mem; ++ state->ci.write_attribute_mem = dvbsky_ci_write_attribute_mem; ++ state->ci.read_cam_control = dvbsky_ci_read_cam_ctl; ++ state->ci.write_cam_control = dvbsky_ci_write_cam_ctl; ++ state->ci.slot_reset = dvbsky_ci_slot_reset; ++ state->ci.slot_shutdown = dvbsky_ci_slot_shutdown; ++ state->ci.slot_ts_enable = dvbsky_ci_slot_ts_enable; ++ state->ci.poll_slot_status = dvbsky_ci_poll_slot_status; ++ state->ci.data = d; ++ ++ ret = dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0, &cimax_init[0], 34); ++ /* lock registers */ ++ ret |= dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0x1f, &cimax_init[0x18], 1); ++ /* power on slots */ ++ ret |= dvbsky_ci_write_i2c(&d->i2c_adap, state->ci_i2c_addr, ++ 0x18, &cimax_init[0x18], 1); ++ if (0 != ret) ++ return ret; ++ ++ ret = dvb_ca_en50221_init(&d->adapter[0].dvb_adap, &state->ci, 0, 1); ++ if (ret) ++ return ret; ++ state->ci_attached = 1; ++ dprintk("%s() complete.\n", __func__); ++ return 0; ++} ++ ++static void dvbsky_ci_release(struct dvb_usb_device *d) ++{ ++ struct dvbsky_state *state = d_to_priv(d); ++ ++ /* detach CI */ ++ if (state->ci_attached) ++ dvb_ca_en50221_release(&state->ci); ++ ++ return; ++} ++ ++static int dvbsky_streaming_ctrl(struct dvb_frontend *fe, int onoff) ++{ ++ struct dvb_usb_device *d = fe_to_d(fe); ++ /*dprintk("%s() %d\n", __func__, onoff);*/ ++ return dvbsky_stream_ctrl(d, (onoff == 0) ? 0 : 1); ++} ++ ++/* GPIO */ ++static int dvbsky_gpio_ctrl(struct dvb_usb_device *d, u8 gport, u8 value) ++{ ++ u8 obuf[64], ibuf[64]; ++ obuf[0] = 0x0e; ++ obuf[1] = gport; ++ obuf[2] = value; ++ return dvb_usbv2_generic_rw(d, obuf, 3, ibuf, 1); ++} ++ ++/* I2C */ ++static int dvbsky_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], ++ int num) ++{ ++ struct dvb_usb_device *d = i2c_get_adapdata(adap); ++ int ret = 0; ++ u8 ibuf[64], obuf[64]; ++ ++ if (mutex_lock_interruptible(&d->i2c_mutex) < 0) ++ return -EAGAIN; ++ ++ if (num > 2) { ++ printk(KERN_ERR "dvbsky_usb: too many i2c messages[%d] than 2.", num); ++ ret = -EOPNOTSUPP; ++ goto i2c_error; ++ } ++ ++ if(num == 1) { ++ if (msg[0].len > 60) { ++ printk(KERN_ERR "dvbsky_usb: too many i2c bytes[%d] than 60.", msg[0].len); ++ ret = -EOPNOTSUPP; ++ goto i2c_error; ++ } ++ if (msg[0].flags & I2C_M_RD) { ++ /* single read */ ++ obuf[0] = 0x09; ++ obuf[1] = 0; ++ obuf[2] = msg[0].len; ++ obuf[3] = msg[0].addr; ++ ret = dvb_usbv2_generic_rw(d, obuf, 4, ibuf, msg[0].len + 1); ++ /*dprintk("%s(): read status = %d\n", __func__, ibuf[0]);*/ ++ if (!ret) ++ memcpy(msg[0].buf, &ibuf[1], msg[0].len); ++ } else { ++ /* write */ ++ obuf[0] = 0x08; ++ obuf[1] = msg[0].addr; ++ obuf[2] = msg[0].len; ++ memcpy(&obuf[3], msg[0].buf, msg[0].len); ++ ret = dvb_usbv2_generic_rw(d, obuf, msg[0].len + 3, ibuf, 1); ++ /*dprintk("%s(): write status = %d\n", __func__, ibuf[0]);*/ ++ } ++ } else { ++ if ((msg[0].len > 60) || (msg[1].len > 60)) { ++ printk(KERN_ERR "dvbsky_usb: too many i2c bytes[w-%d][r-%d] than 60.", msg[0].len, msg[1].len); ++ ret = -EOPNOTSUPP; ++ goto i2c_error; ++ } ++ /* write then read */ ++ obuf[0] = 0x09; ++ obuf[1] = msg[0].len; ++ obuf[2] = msg[1].len; ++ obuf[3] = msg[0].addr; ++ memcpy(&obuf[4], msg[0].buf, msg[0].len); ++ ret = dvb_usbv2_generic_rw(d, obuf, msg[0].len + 4, ibuf, msg[1].len + 1); ++ /*dprintk("%s(): write then read status = %d\n", __func__, ibuf[0]);*/ ++ if (!ret) ++ memcpy(msg[1].buf, &ibuf[1], msg[1].len); ++ } ++i2c_error: ++ mutex_unlock(&d->i2c_mutex); ++ return (ret) ? ret : num; ++} ++ ++static u32 dvbsky_i2c_func(struct i2c_adapter *adapter) ++{ ++ return I2C_FUNC_I2C; ++} ++ ++static struct i2c_algorithm dvbsky_i2c_algo = { ++ .master_xfer = dvbsky_i2c_xfer, ++ .functionality = dvbsky_i2c_func, ++}; ++ ++#if IS_ENABLED(CONFIG_RC_CORE) ++static int dvbsky_rc_query(struct dvb_usb_device *d) ++{ ++ u32 code = 0xffff; ++ u8 obuf[2], ibuf[2], toggle; ++ int ret; ++ obuf[0] = 0x10; ++ ret = dvb_usbv2_generic_rw(d, obuf, 1, ibuf, 2); ++ if(ret == 0) ++ code = (ibuf[0] << 8) | ibuf[1]; ++ ++ if (code != 0xffff) { ++ dprintk("rc code: %x", code); ++ toggle = (code & 0x800) ? 1 : 0; ++ code &= 0x3f; ++ rc_keydown(d->rc_dev, code, toggle); ++ } ++ return 0; ++} ++ ++static int dvbsky_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc) ++{ ++ rc->allowed_protos = RC_BIT_RC5; ++ rc->query = dvbsky_rc_query; ++ rc->interval = 300; ++ return 0; ++} ++#else ++ #define dvbsky_get_rc_config NULL ++#endif ++ ++static int dvbsky_sync_ctrl(struct dvb_frontend *fe) ++{ ++ struct dvb_usb_device *d = fe_to_d(fe); ++ return dvbsky_stream_ctrl(d, 1); ++} ++ ++static int dvbsky_usb_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ++{ ++ struct dvb_usb_device *d = fe_to_d(fe); ++ u8 value; ++ ++ if (voltage == SEC_VOLTAGE_OFF) ++ value = 0; ++ else ++ value = 1; ++ return dvbsky_gpio_ctrl(d, 0x80, value); ++} ++ ++static int dvbsky_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6]) ++{ ++ struct dvb_usb_device *d = adap_to_d(adap); ++ u8 obuf[] = { 0x1e, 0x00 }; ++ u8 ibuf[6] = { 0 }; ++ struct i2c_msg msg[] = { ++ { ++ .addr = 0x51, ++ .flags = 0, ++ .buf = obuf, ++ .len = 2, ++ }, { ++ .addr = 0x51, ++ .flags = I2C_M_RD, ++ .buf = ibuf, ++ .len = 6, ++ ++ } ++ }; ++ ++ if (i2c_transfer(&d->i2c_adap, msg, 2) == 2) ++ memcpy(mac, ibuf, 6); ++ ++ printk(KERN_INFO "dvbsky_usb MAC address=%pM\n", mac); ++ ++ return 0; ++} ++ ++static struct m88ds3103_config dvbsky_usb_ds3103_config = { ++ .demod_address = 0x68, ++ .ci_mode = 1, ++ .pin_ctrl = 0x83, ++ .ts_mode = 0, ++ .start_ctrl = dvbsky_sync_ctrl, ++ .set_voltage = dvbsky_usb_set_voltage, ++}; ++ ++static int dvbsky_s960_attach(struct dvb_usb_adapter *adap) ++{ ++ struct dvbsky_state *state = adap_to_priv(adap); ++ struct dvb_usb_device *d = adap_to_d(adap); ++ int ret = 0; ++ ++ dprintk("%s()\n", __func__); ++ ++ dvbsky_gpio_ctrl(d, 0x04, 1); ++ ++ dvbsky_gpio_ctrl(d, 0x83, 0); ++ msleep(50); ++ dvbsky_gpio_ctrl(d, 0x83, 1); ++ msleep(20); ++ ++ adap->fe[0] = dvb_attach(m88ds3103_attach, ++ &dvbsky_usb_ds3103_config, ++ &d->i2c_adap); ++ if (!adap->fe[0]) { ++ printk(KERN_ERR "dvbsky_s960_attach fail."); ++ ret = -ENODEV; ++ } ++ ++ state->has_ci = 0; ++ ++ return ret; ++} ++ ++static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name) ++{ ++ return WARM; ++} ++ ++static int dvbsky_init(struct dvb_usb_device *d) ++{ ++ struct dvbsky_state *state = d_to_priv(d); ++ int ret; ++ ++ /* use default interface */ ++ ret = usb_set_interface(d->udev, 0, 0); ++ if (ret) ++ return ret; ++ ++ mutex_init(&state->stream_mutex); ++ ++ /* attach CI */ ++ if (state->has_ci) { ++ dvbsky_gpio_ctrl(d, 0xc0, 1); ++ msleep(100); ++ dvbsky_gpio_ctrl(d, 0xc0, 0); ++ msleep(50); ++ state->ci_attached = 0; ++ ret = dvbsky_ci_init(d); ++ if (ret) ++ return ret; ++ } ++ return 0; ++} ++ ++static void dvbsky_exit(struct dvb_usb_device *d) ++{ ++ return dvbsky_ci_release(d); ++} ++ ++/* DVB USB Driver stuff */ ++static struct dvb_usb_device_properties dvbsky_s960_props = { ++ .driver_name = KBUILD_MODNAME, ++ .owner = THIS_MODULE, ++ .adapter_nr = adapter_nr, ++ .size_of_priv = sizeof(struct dvbsky_state), ++ ++ .generic_bulk_ctrl_endpoint = 0x01, ++ .generic_bulk_ctrl_endpoint_response = 0x81, ++ ++ .i2c_algo = &dvbsky_i2c_algo, ++ .frontend_attach = dvbsky_s960_attach, ++ .init = dvbsky_init, ++ .get_rc_config = dvbsky_get_rc_config, ++ .streaming_ctrl = dvbsky_streaming_ctrl, ++ .identify_state = dvbsky_identify_state, ++ .exit = dvbsky_exit, ++ .read_mac_address = dvbsky_read_mac_addr, ++ ++ .num_adapters = 1, ++ .adapter = { ++ { ++ .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096), ++ } ++ } ++}; ++ ++static const struct usb_device_id dvbsky_id_table[] = { ++ { DVB_USB_DEVICE(0x0572, 0x6831, ++ &dvbsky_s960_props, "DVBSky S960/S860", RC_MAP_DVBSKY) }, ++ { } ++}; ++MODULE_DEVICE_TABLE(usb, dvbsky_id_table); ++ ++static struct usb_driver dvbsky_usb_driver = { ++ .name = KBUILD_MODNAME, ++ .id_table = dvbsky_id_table, ++ .probe = dvb_usbv2_probe, ++ .disconnect = dvb_usbv2_disconnect, ++ .suspend = dvb_usbv2_suspend, ++ .resume = dvb_usbv2_resume, ++ .reset_resume = dvb_usbv2_reset_resume, ++ .no_dynamic_id = 1, ++ .soft_unbind = 1, ++}; ++ ++module_usb_driver(dvbsky_usb_driver); ++ ++MODULE_AUTHOR("Max nibble "); ++MODULE_DESCRIPTION("Driver for DVBSky USB2.0"); ++MODULE_LICENSE("GPL"); +diff -urN a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig +--- a/drivers/media/usb/dvb-usb-v2/Kconfig 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/usb/dvb-usb-v2/Kconfig 2013-05-03 17:45:35.000000000 +0800 +@@ -149,3 +149,10 @@ + help + Say Y here to support the Realtek RTL28xxU DVB USB receiver. + ++config DVB_USB_DVBSKY ++ tristate "DVBSky USB2.0 support" ++ depends on DVB_USB_V2 ++ select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT ++ help ++ Say Y here to support the USB receivers from DVBSky. ++ +diff -urN a/drivers/media/usb/dvb-usb-v2/Makefile b/drivers/media/usb/dvb-usb-v2/Makefile +--- a/drivers/media/usb/dvb-usb-v2/Makefile 2013-04-29 08:36:01.000000000 +0800 ++++ b/drivers/media/usb/dvb-usb-v2/Makefile 2013-02-17 12:03:00.000000000 +0800 +@@ -43,6 +43,9 @@ + dvb-usb-rtl28xxu-objs := rtl28xxu.o + obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o + ++dvb-usb-dvbsky-objs := dvbsky.o ++obj-$(CONFIG_DVB_USB_DVBSKY) += dvb-usb-dvbsky.o ++ + ccflags-y += -I$(srctree)/drivers/media/dvb-core + ccflags-y += -I$(srctree)/drivers/media/dvb-frontends + ccflags-y += -I$(srctree)/drivers/media/tuners +diff -urN a/include/media/rc-map.h b/include/media/rc-map.h +--- a/include/media/rc-map.h 2013-04-29 08:36:01.000000000 +0800 ++++ b/include/media/rc-map.h 2013-05-03 17:02:46.000000000 +0800 +@@ -118,6 +118,7 @@ + #define RC_MAP_DM1105_NEC "rc-dm1105-nec" + #define RC_MAP_DNTV_LIVE_DVBT_PRO "rc-dntv-live-dvbt-pro" + #define RC_MAP_DNTV_LIVE_DVB_T "rc-dntv-live-dvb-t" ++#define RC_MAP_DVBSKY "rc-dvbsky" + #define RC_MAP_EMPTY "rc-empty" + #define RC_MAP_EM_TERRATEC "rc-em-terratec" + #define RC_MAP_ENCORE_ENLTV2 "rc-encore-enltv2"