From ea9d209432f87b75b70648bc403c9ed5245b85c7 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Fri, 8 Oct 2010 21:08:08 +0200 Subject: [PATCH] linux: wrong patch included with last commit, add the right one Signed-off-by: Stephan Raue --- .../linux-2.6.36-add_nuvoton_cir-0.1.diff | 1680 ---------- .../linux-2.6.36-add_nuvoton_cir-0.2.diff | 2692 +++++++++++------ 2 files changed, 1711 insertions(+), 2661 deletions(-) delete mode 100644 packages/linux/patches/linux-2.6.36-add_nuvoton_cir-0.1.diff diff --git a/packages/linux/patches/linux-2.6.36-add_nuvoton_cir-0.1.diff b/packages/linux/patches/linux-2.6.36-add_nuvoton_cir-0.1.diff deleted file mode 100644 index 9a099f80f5..0000000000 --- a/packages/linux/patches/linux-2.6.36-add_nuvoton_cir-0.1.diff +++ /dev/null @@ -1,1680 +0,0 @@ -diff -Naur linux-2.6.36-rc7/drivers/media/IR/Kconfig linux-2.6.36-rc7.patch/drivers/media/IR/Kconfig ---- linux-2.6.36-rc7/drivers/media/IR/Kconfig 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/media/IR/Kconfig 2010-10-07 22:45:58.161335701 +0200 -@@ -113,6 +113,17 @@ - To compile this driver as a module, choose M here: the - module will be called mceusb. - -+config IR_NUVOTON -+ tristate "Nuvoton eHome Infrared Transceiver" -+ depends on USB_ARCH_HAS_HCD -+ depends on IR_CORE -+ select USB -+ ---help--- -+ Say Y here if you want to use a Novoton eHome Infrared Transceiver. -+ -+ To compile this driver as a module, choose M here: the -+ module will be called nuvoton. -+ - config IR_ENE - tristate "ENE eHome Receiver/Transciever (pnp id: ENE0100/ENE02xxx)" - depends on PNP -diff -Naur linux-2.6.36-rc7/drivers/media/IR/Makefile linux-2.6.36-rc7.patch/drivers/media/IR/Makefile ---- linux-2.6.36-rc7/drivers/media/IR/Makefile 2010-10-06 22:39:52.000000000 +0200 -+++ linux-2.6.36-rc7.patch/drivers/media/IR/Makefile 2010-10-07 22:47:02.346138444 +0200 -@@ -16,5 +16,6 @@ - # stand-alone IR receivers/transmitters - obj-$(CONFIG_IR_IMON) += imon.o - obj-$(CONFIG_IR_MCEUSB) += mceusb.o -+obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o - obj-$(CONFIG_IR_ENE) += ene_ir.o - obj-$(CONFIG_IR_STREAMZAP) += streamzap.o -diff -Naur linux-2.6.36-rc7/drivers/media/IR/nuvoton-cir.c linux-2.6.36-rc7.patch/drivers/media/IR/nuvoton-cir.c ---- linux-2.6.36-rc7/drivers/media/IR/nuvoton-cir.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36-rc7.patch/drivers/media/IR/nuvoton-cir.c 2010-10-07 22:43:52.000000000 +0200 -@@ -0,0 +1,1210 @@ -+/* -+ * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR -+ * -+ * Copyright (C) 2010 Jarod Wilson -+ * Copyright (C) 2009 Nuvoton PS Team -+ * -+ * Special thanks to Nuvoton for providing hardware, spec sheets and -+ * sample code upon which portions of this driver are based. Indirect -+ * thanks also to Maxim Levitsky, whose ene_ir driver this driver is -+ * modeled after. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ * USA -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "nuvoton-cir.h" -+ -+static char *chip_id = "w836x7hg"; -+ -+/* write val to config reg */ -+static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg) -+{ -+ outb(reg, nvt->cr_efir); -+ outb(val, nvt->cr_efdr); -+} -+ -+/* read val from config reg */ -+static inline u8 nvt_cr_read(struct nvt_dev *nvt, u8 reg) -+{ -+ outb(reg, nvt->cr_efir); -+ return inb(nvt->cr_efdr); -+} -+ -+/* update config register bit without changing other bits */ -+static inline void nvt_set_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg) -+{ -+ u8 tmp = nvt_cr_read(nvt, reg) | val; -+ nvt_cr_write(nvt, tmp, reg); -+} -+ -+/* clear config register bit without changing other bits */ -+static inline void nvt_clear_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg) -+{ -+ u8 tmp = nvt_cr_read(nvt, reg) & ~val; -+ nvt_cr_write(nvt, tmp, reg); -+} -+ -+/* enter extended function mode */ -+static inline void nvt_efm_enable(struct nvt_dev *nvt) -+{ -+ /* Enabling Extended Function Mode explicitly requires writing 2x */ -+ outb(EFER_EFM_ENABLE, nvt->cr_efir); -+ outb(EFER_EFM_ENABLE, nvt->cr_efir); -+} -+ -+/* exit extended function mode */ -+static inline void nvt_efm_disable(struct nvt_dev *nvt) -+{ -+ outb(EFER_EFM_DISABLE, nvt->cr_efir); -+} -+ -+/* -+ * When you want to address a specific logical device, write its logical -+ * device number to CR_LOGICAL_DEV_SEL, then enable/disable by writing -+ * 0x1/0x0 respectively to CR_LOGICAL_DEV_EN. -+ */ -+static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev) -+{ -+ outb(CR_LOGICAL_DEV_SEL, nvt->cr_efir); -+ outb(ldev, nvt->cr_efdr); -+} -+ -+/* write val to cir config register */ -+static inline void nvt_cir_reg_write(struct nvt_dev *nvt, u8 val, u8 offset) -+{ -+ outb(val, nvt->cir_addr + offset); -+} -+ -+/* read val from cir config register */ -+static u8 nvt_cir_reg_read(struct nvt_dev *nvt, u8 offset) -+{ -+ u8 val; -+ -+ val = inb(nvt->cir_addr + offset); -+ -+ return val; -+} -+ -+/* write val to cir wake register */ -+static inline void nvt_cir_wake_reg_write(struct nvt_dev *nvt, -+ u8 val, u8 offset) -+{ -+ outb(val, nvt->cir_wake_addr + offset); -+} -+ -+/* read val from cir wake config register */ -+static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset) -+{ -+ u8 val; -+ -+ val = inb(nvt->cir_wake_addr + offset); -+ -+ return val; -+} -+ -+/* dump current cir register contents */ -+static void cir_dump_regs(struct nvt_dev *nvt) -+{ -+ nvt_efm_enable(nvt); -+ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); -+ -+ printk("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME); -+ printk(" * CR CIR ACTIVE : 0x%x\n", -+ nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); -+ printk(" * CR CIR BASE ADDR: 0x%x\n", -+ (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | -+ nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO)); -+ printk(" * CR CIR IRQ NUM: 0x%x\n", -+ nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); -+ -+ nvt_efm_disable(nvt); -+ -+ printk("%s: Dump CIR registers:\n", NVT_DRIVER_NAME); -+ printk(" * IRCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON)); -+ printk(" * IRSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS)); -+ printk(" * IREN: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN)); -+ printk(" * RXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT)); -+ printk(" * CP: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CP)); -+ printk(" * CC: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CC)); -+ printk(" * SLCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH)); -+ printk(" * SLCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL)); -+ printk(" * FIFOCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON)); -+ printk(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS)); -+ printk(" * SRXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO)); -+ printk(" * TXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT)); -+ printk(" * STXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO)); -+ printk(" * FCCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH)); -+ printk(" * FCCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL)); -+ printk(" * IRFSM: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM)); -+} -+ -+/* dump current cir wake register contents */ -+static void cir_wake_dump_regs(struct nvt_dev *nvt) -+{ -+ u8 i, fifo_len; -+ -+ nvt_efm_enable(nvt); -+ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); -+ -+ printk("%s: Dump CIR WAKE logical device registers:\n", -+ NVT_DRIVER_NAME); -+ printk(" * CR CIR WAKE ACTIVE : 0x%x\n", -+ nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); -+ printk(" * CR CIR WAKE BASE ADDR: 0x%x\n", -+ (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | -+ nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO)); -+ printk(" * CR CIR WAKE IRQ NUM: 0x%x\n", -+ nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); -+ -+ nvt_efm_disable(nvt); -+ -+ printk("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME); -+ printk(" * IRCON: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON)); -+ printk(" * IRSTS: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS)); -+ printk(" * IREN: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN)); -+ printk(" * FIFO CMP DEEP: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP)); -+ printk(" * FIFO CMP TOL: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL)); -+ printk(" * FIFO COUNT: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT)); -+ printk(" * SLCH: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH)); -+ printk(" * SLCL: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL)); -+ printk(" * FIFOCON: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON)); -+ printk(" * SRXFSTS: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS)); -+ printk(" * SAMPLE RX FIFO: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO)); -+ printk(" * WR FIFO DATA: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA)); -+ printk(" * RD FIFO ONLY: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); -+ printk(" * RD FIFO ONLY IDX: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)); -+ printk(" * FIFO IGNORE: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE)); -+ printk(" * IRFSM: 0x%x\n", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM)); -+ -+ fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT); -+ printk("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len); -+ printk("* Contents = "); -+ for (i = 0; i < fifo_len; i++) -+ printk("%02x ", -+ nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); -+ printk("\n"); -+} -+ -+/* detect hardware features */ -+static int nvt_hw_detect(struct nvt_dev *nvt) -+{ -+ u8 chip_major, chip_minor; -+ int ret = 0; -+ -+ nvt_efm_enable(nvt); -+ -+ /* Check if we're wired for the alternate EFER setup */ -+ chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); -+ if (chip_major == 0xff) { -+ nvt->cr_efir = CR_EFIR2; -+ nvt->cr_efdr = CR_EFDR2; -+ nvt_efm_enable(nvt); -+ chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); -+ } -+ -+ chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); -+ nvt_dbg("%s: chip id: 0x%02x 0x%02x", chip_id, chip_major, chip_minor); -+ -+ if (chip_major != CHIP_ID_HIGH && -+ (chip_minor != CHIP_ID_LOW || chip_minor != CHIP_ID_LOW2)) -+ ret = -ENODEV; -+ -+ nvt_efm_disable(nvt); -+ -+ return ret; -+} -+ -+static void nvt_cir_ldev_init(struct nvt_dev *nvt) -+{ -+ u8 val; -+ -+ /* output pin selection (Pin95=CIRRX, Pin96=CIRTX1, WB enabled */ -+ val = nvt_cr_read(nvt, CR_OUTPUT_PIN_SEL); -+ val &= OUTPUT_PIN_SEL_MASK; -+ val |= (OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB); -+ nvt_cr_write(nvt, val, CR_OUTPUT_PIN_SEL); -+ -+ /* Select CIR logical device and enable */ -+ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); -+ nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); -+ -+ nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI); -+ nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO); -+ -+ nvt_cr_write(nvt, nvt->cir_irq, CR_CIR_IRQ_RSRC); -+ -+ nvt_dbg("CIR initialized, base io port address: 0x%lx, irq: %d", -+ nvt->cir_addr, nvt->cir_irq); -+} -+ -+static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt) -+{ -+ /* Select ACPI logical device, enable it and CIR Wake */ -+ nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); -+ nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); -+ -+ /* Enable CIR Wake via PSOUT# (Pin60) */ -+ nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE); -+ -+ /* enable cir interrupt of mouse/keyboard IRQ event */ -+ nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS); -+ -+ /* enable pme interrupt of cir wakeup event */ -+ nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2); -+ -+ /* Select CIR Wake logical device and enable */ -+ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); -+ nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); -+ -+ nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI); -+ nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO); -+ -+ nvt_cr_write(nvt, nvt->cir_wake_irq, CR_CIR_IRQ_RSRC); -+ -+ nvt_dbg("CIR Wake initialized, base io port address: 0x%lx, irq: %d", -+ nvt->cir_wake_addr, nvt->cir_wake_irq); -+} -+ -+/* clear out the hardware's cir rx fifo */ -+static void nvt_clear_cir_fifo(struct nvt_dev *nvt) -+{ -+ u8 val; -+ -+ val = nvt_cir_reg_read(nvt, CIR_FIFOCON); -+ nvt_cir_reg_write(nvt, val | CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON); -+} -+ -+/* clear out the hardware's cir wake rx fifo */ -+static void nvt_clear_cir_wake_fifo(struct nvt_dev *nvt) -+{ -+ u8 val; -+ -+ val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON); -+ nvt_cir_wake_reg_write(nvt, val | CIR_WAKE_FIFOCON_RXFIFOCLR, -+ CIR_WAKE_FIFOCON); -+} -+ -+/* clear out the hardware's cir tx fifo */ -+static void nvt_clear_tx_fifo(struct nvt_dev *nvt) -+{ -+ u8 val; -+ -+ val = nvt_cir_reg_read(nvt, CIR_FIFOCON); -+ nvt_cir_reg_write(nvt, val | CIR_FIFOCON_TXFIFOCLR, CIR_FIFOCON); -+} -+ -+static void nvt_cir_regs_init(struct nvt_dev *nvt) -+{ -+ /* FIXME: document what's going on */ -+ nvt_cir_reg_write(nvt, CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, -+ CIR_IRCON); -+ nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); -+ nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_SLCH); -+ nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_SLCL); -+ nvt_cir_reg_write(nvt, -+ CIR_FIFOCON_TXFIFOCLR | CIR_FIFOCON_TX_TRIGGER_LEV | -+ CIR_FIFOCON_RXFIFOCLR | CIR_FIFOCON_RX_TRIGGER_LEV, -+ CIR_FIFOCON); -+ nvt_cir_reg_write(nvt, CIR_IRCON_RECV | CIR_IRCON_RXINV | -+ CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); -+ nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | CIR_IRCON_RXINV | -+ CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); -+ nvt_clear_cir_fifo(nvt); -+ nvt_clear_tx_fifo(nvt); -+ nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); -+ /* Enable interrupts */ -+ nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); -+} -+ -+static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) -+{ -+ /* FIXME: remove magic numbers, document what's going on */ -+ nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); -+ nvt_cir_wake_reg_write(nvt, 0x41, CIR_WAKE_FIFO_CMP_DEEP); -+ nvt_cir_wake_reg_write(nvt, 0x05, CIR_WAKE_FIFO_CMP_TOL); -+ nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_WAKE_SLCH); -+ nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_WAKE_SLCL); -+ nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_FIFOCON); -+ nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_FIFOCON); -+ nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | -+ CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | -+ CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, -+ CIR_WAKE_IRCON); -+ nvt_clear_cir_wake_fifo(nvt); -+ nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); -+} -+ -+static void nvt_enable_wake(struct nvt_dev *nvt) -+{ -+ nvt_efm_enable(nvt); -+ -+ nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); -+ nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE); -+ nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS); -+ nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2); -+ -+ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); -+ nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); -+ -+ nvt_efm_disable(nvt); -+ -+ nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | -+ CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | -+ CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, CIR_WAKE_IRCON); -+ nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); -+ nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); -+} -+ -+static void nvt_disable_wake(struct nvt_dev *nvt) -+{ -+ nvt_efm_enable(nvt); -+ -+ nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); -+ nvt_clear_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE); -+ nvt_clear_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS); -+ nvt_clear_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2); -+ -+ nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRCON); -+ nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); -+ nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); -+ -+ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); -+ nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); -+ -+ nvt_efm_disable(nvt); -+} -+ -+/* rx carrier detect only works in learning mode, must be called w/nvt_lock */ -+static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt) -+{ -+ u32 count, carrier, duration = 0; -+ int i; -+ -+ count = nvt_cir_reg_read(nvt, CIR_FCCL) | -+ nvt_cir_reg_read(nvt, CIR_FCCH) << 8; -+ -+ for (i = 0; i < nvt->pkts; i++) { -+ if (nvt->buf[i] & BUF_PULSE_BIT) -+ duration += nvt->buf[i] & BUF_LEN_MASK; -+ } -+ -+ duration *= SAMPLE_PERIOD; -+ -+ if (!count || !duration) { -+ nvt_pr(KERN_NOTICE, "Unable to determine carrier! (c:%u, d:%u)", -+ count, duration); -+ return 0; -+ } -+ -+ carrier = (count * 1000000) / duration; -+ -+ if ((carrier > MAX_CARRIER) || (carrier < MIN_CARRIER)) -+ nvt_dbg("WTF? Carrier frequency out of range!"); -+ -+ nvt_dbg("Carrier frequency: %u (count %u, duration %u)", -+ carrier, count, duration); -+ -+ return carrier; -+} -+ -+/* -+ * set carrier frequency -+ * -+ * set carrier on 2 registers: CP & CC -+ * always set CP as 0x81 -+ * set CC by SPEC, CC = 3MHz/carrier - 1 -+ */ -+static int nvt_set_tx_carrier(void *data, u32 carrier) -+{ -+ struct nvt_dev *nvt = data; -+ u16 val; -+ -+ nvt_cir_reg_write(nvt, 1, CIR_CP); -+ val = 3000000 / (carrier) - 1; -+ nvt_cir_reg_write(nvt, val & 0xff, CIR_CC); -+ -+ nvt_dbg("cp: 0x%x cc: 0x%x\n", -+ nvt_cir_reg_read(nvt, CIR_CP), nvt_cir_reg_read(nvt, CIR_CC)); -+ -+ return 0; -+} -+ -+/* -+ * nvt_tx_ir -+ * -+ * 1) clean TX fifo first (handled by AP) -+ * 2) copy data from user space -+ * 3) disable RX interrupts, enable TX interrupts: TTR & TFU -+ * 4) send 9 packets to TX FIFO to open TTR -+ * in interrupt_handler: -+ * 5) send all data out -+ * go back to write(): -+ * 6) disable TX interrupts, re-enable RX interupts -+ * -+ * The key problem of this function is user space data may larger than -+ * driver's data buf length. So nvt_tx_ir() will only copy TX_BUF_LEN data to -+ * buf, and keep current copied data buf num in cur_buf_num. But driver's buf -+ * number may larger than TXFCONT (0xff). So in interrupt_handler, it has to -+ * set TXFCONT as 0xff, until buf_count less than 0xff. -+ */ -+static int nvt_tx_ir(void *priv, int *txbuf, u32 n) -+{ -+ struct nvt_dev *nvt = priv; -+ unsigned long flags; -+ size_t cur_count; -+ unsigned int i; -+ u8 iren; -+ int ret; -+ -+ spin_lock_irqsave(&nvt->tx.lock, flags); -+ -+ if (n >= TX_BUF_LEN) { -+ nvt->tx.buf_count = cur_count = TX_BUF_LEN; -+ ret = TX_BUF_LEN; -+ } else { -+ nvt->tx.buf_count = cur_count = n; -+ ret = n; -+ } -+ -+ memcpy(nvt->tx.buf, txbuf, nvt->tx.buf_count); -+ -+ nvt->tx.cur_buf_num = 0; -+ -+ /* save currently enabled interrupts */ -+ iren = nvt_cir_reg_read(nvt, CIR_IREN); -+ -+ /* now disable all interrupts, save TFU & TTR */ -+ nvt_cir_reg_write(nvt, CIR_IREN_TFU | CIR_IREN_TTR, CIR_IREN); -+ -+ nvt->tx.tx_state = ST_TX_REPLY; -+ -+ nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV_8 | -+ CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON); -+ -+ /* trigger TTR interrupt by writing out ones, (yes, it's ugly) */ -+ for (i = 0; i < 9; i++) -+ nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO); -+ -+ spin_unlock_irqrestore(&nvt->tx.lock, flags); -+ -+ wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST); -+ -+ spin_lock_irqsave(&nvt->tx.lock, flags); -+ nvt->tx.tx_state = ST_TX_NONE; -+ spin_unlock_irqrestore(&nvt->tx.lock, flags); -+ -+ /* restore enabled interrupts to prior state */ -+ nvt_cir_reg_write(nvt, iren, CIR_IREN); -+ -+ return ret; -+} -+ -+/* dump contents of the last rx buffer we got from the hw rx fifo */ -+static void nvt_dump_rx_buf(struct nvt_dev *nvt) -+{ -+ int i; -+ -+ printk("%s (len %d): ", __func__, nvt->pkts); -+ for (i = 0; (i < nvt->pkts) && (i < RX_BUF_LEN); i++) -+ printk("0x%02x ", nvt->buf[i]); -+ printk("\n"); -+} -+ -+/* -+ * Process raw data in rx driver buffer, store it in raw IR event kfifo, -+ * trigger decode when appropriate. -+ * -+ * We get IR data samples one byte at a time. If the msb is set, its a pulse, -+ * otherwise its a space. The lower 7 bits are the count of SAMPLE_PERIOD -+ * (default 50us) intervals for that pulse/space. A discrete signal is -+ * followed by a series of 0x7f packets, then either 0x7 or 0x80 -+ * to signal more IR coming (repeats) or end of IR, respectively. We store -+ * sample data in the raw event kfifo until we see 0x7 (except f) -+ * or 0x80, at which time, we trigger a decode operation. -+ */ -+static void nvt_process_rx_ir_data(struct nvt_dev *nvt) -+{ -+ struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; -+ unsigned int count; -+ u32 carrier; -+ u8 sample; -+ int i; -+ -+ nvt_dbg_verbose("%s firing", __func__); -+ -+ if (debug) -+ nvt_dump_rx_buf(nvt); -+ -+ if (nvt->carrier_detect_enabled) -+ carrier = nvt_rx_carrier_detect(nvt); -+ -+ count = nvt->pkts; -+ nvt_dbg_verbose("Processing buffer of len %d", count); -+ -+ for (i = 0; i < count; i++) { -+ nvt->pkts--; -+ sample = nvt->buf[i]; -+ -+ rawir.pulse = ((sample & BUF_PULSE_BIT) != 0); -+ rawir.duration = (sample & BUF_LEN_MASK) -+ * SAMPLE_PERIOD * 1000; -+ -+ if ((sample & BUF_LEN_MASK) == BUF_LEN_MASK) { -+ if (nvt->rawir.pulse == rawir.pulse) -+ nvt->rawir.duration += rawir.duration; -+ else { -+ nvt->rawir.duration = rawir.duration; -+ nvt->rawir.pulse = rawir.pulse; -+ } -+ continue; -+ } -+ -+ rawir.duration += nvt->rawir.duration; -+ nvt->rawir.duration = 0; -+ nvt->rawir.pulse = rawir.pulse; -+ -+ if (sample == BUF_PULSE_BIT) -+ rawir.pulse = false; -+ -+ if (rawir.duration) { -+ nvt_dbg("Storing %s with duration %d", -+ rawir.pulse ? "pulse" : "space", -+ rawir.duration); -+ -+ ir_raw_event_store(nvt->rdev, &rawir); -+ } -+ -+ /* -+ * BUF_PULSE_BIT indicates end of IR data, BUF_REPEAT_BYTE -+ * indicates end of IR signal, but new data incoming. In both -+ * cases, it means we're ready to call ir_raw_event_handle -+ */ -+ if (sample == BUF_PULSE_BIT || ((sample != BUF_LEN_MASK) && -+ (sample & BUF_REPEAT_MASK) == BUF_REPEAT_BYTE)) -+ ir_raw_event_handle(nvt->rdev); -+ } -+ -+ if (nvt->pkts) { -+ nvt_dbg("Odd, pkts should be 0 now... (its %u)", nvt->pkts); -+ nvt->pkts = 0; -+ } -+ -+ nvt_dbg_verbose("%s done", __func__); -+} -+ -+/* copy data from hardware rx fifo into driver buffer */ -+static void nvt_get_rx_ir_data(struct nvt_dev *nvt) -+{ -+ unsigned long flags; -+ u8 fifocount, val; -+ unsigned int b_idx; -+ int i; -+ -+ /* Get count of how many bytes to read from RX FIFO */ -+ fifocount = nvt_cir_reg_read(nvt, CIR_RXFCONT); -+ /* if we get 0xff, probably means the logical dev is disabled */ -+ if (fifocount == 0xff) -+ return; -+ /* this would suggest a fifo overrun, not good... */ -+ else if (fifocount > RX_BUF_LEN) { -+ nvt_pr(KERN_WARNING, "fifocount %d over fifo len (%d)!", -+ fifocount, RX_BUF_LEN); -+ return; -+ } -+ -+ nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount); -+ -+ spin_lock_irqsave(&nvt->nvt_lock, flags); -+ -+ b_idx = nvt->pkts; -+ -+ /* This should never happen, but lets check anyway... */ -+ if (b_idx + fifocount > RX_BUF_LEN) { -+ nvt_process_rx_ir_data(nvt); -+ b_idx = 0; -+ } -+ -+ /* Read fifocount bytes from CIR Sample RX FIFO register */ -+ for (i = 0; i < fifocount; i++) { -+ val = nvt_cir_reg_read(nvt, CIR_SRXFIFO); -+ nvt->buf[b_idx + i] = val; -+ } -+ -+ nvt->pkts += fifocount; -+ nvt_dbg("%s: pkts now %d", __func__, nvt->pkts); -+ -+ nvt_process_rx_ir_data(nvt); -+ -+ spin_unlock_irqrestore(&nvt->nvt_lock, flags); -+} -+ -+static void nvt_cir_log_irqs(u8 status, u8 iren) -+{ -+ nvt_pr(KERN_INFO, "IRQ 0x%02x (IREN 0x%02x) :%s%s%s%s%s%s%s%s%s", -+ status, iren, -+ status & CIR_IRSTS_RDR ? " RDR" : "", -+ status & CIR_IRSTS_RTR ? " RTR" : "", -+ status & CIR_IRSTS_PE ? " PE" : "", -+ status & CIR_IRSTS_RFO ? " RFO" : "", -+ status & CIR_IRSTS_TE ? " TE" : "", -+ status & CIR_IRSTS_TTR ? " TTR" : "", -+ status & CIR_IRSTS_TFU ? " TFU" : "", -+ status & CIR_IRSTS_GH ? " GH" : "", -+ status & ~(CIR_IRSTS_RDR | CIR_IRSTS_RTR | CIR_IRSTS_PE | -+ CIR_IRSTS_RFO | CIR_IRSTS_TE | CIR_IRSTS_TTR | -+ CIR_IRSTS_TFU | CIR_IRSTS_GH) ? " ?" : ""); -+} -+ -+static bool nvt_cir_tx_inactive(struct nvt_dev *nvt) -+{ -+ unsigned long flags; -+ bool tx_inactive; -+ u8 tx_state; -+ -+ spin_lock_irqsave(&nvt->tx.lock, flags); -+ tx_state = nvt->tx.tx_state; -+ spin_unlock_irqrestore(&nvt->tx.lock, flags); -+ -+ tx_inactive = (tx_state == ST_TX_NONE); -+ -+ return tx_inactive; -+} -+ -+/* interrupt service routine for incoming and outgoing CIR data */ -+static irqreturn_t nvt_cir_isr(int irq, void *data) -+{ -+ struct nvt_dev *nvt = data; -+ u8 status, iren, cur_state; -+ unsigned long flags; -+ -+ nvt_dbg_verbose("%s firing", __func__); -+ -+ nvt_efm_enable(nvt); -+ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); -+ nvt_efm_disable(nvt); -+ -+ /* -+ * Get IR Status register contents. Write 1 to ack/clear -+ * -+ * bit: reg name - description -+ * 7: CIR_IRSTS_RDR - RX Data Ready -+ * 6: CIR_IRSTS_RTR - RX FIFO Trigger Level Reach -+ * 5: CIR_IRSTS_PE - Packet End -+ * 4: CIR_IRSTS_RFO - RX FIFO Overrun (RDR will also be set) -+ * 3: CIR_IRSTS_TE - TX FIFO Empty -+ * 2: CIR_IRSTS_TTR - TX FIFO Trigger Level Reach -+ * 1: CIR_IRSTS_TFU - TX FIFO Underrun -+ * 0: CIR_IRSTS_GH - Min Length Detected -+ */ -+ status = nvt_cir_reg_read(nvt, CIR_IRSTS); -+ if (!status) { -+ nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__); -+ nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); -+ return IRQ_RETVAL(IRQ_NONE); -+ } -+ -+ /* ack/clear all irq flags we've got */ -+ nvt_cir_reg_write(nvt, status, CIR_IRSTS); -+ nvt_cir_reg_write(nvt, 0, CIR_IRSTS); -+ -+ /* Interrupt may be shared with CIR Wake, bail if CIR not enabled */ -+ iren = nvt_cir_reg_read(nvt, CIR_IREN); -+ if (!iren) { -+ nvt_dbg_verbose("%s exiting, CIR not enabled", __func__); -+ return IRQ_RETVAL(IRQ_NONE); -+ } -+ -+ if (debug) -+ nvt_cir_log_irqs(status, iren); -+ -+ if (status & CIR_IRSTS_RTR) { -+ /* FIXME: add code for study/learn mode */ -+ /* We only do rx if not tx'ing */ -+ if (nvt_cir_tx_inactive(nvt)) -+ nvt_get_rx_ir_data(nvt); -+ } -+ -+ if (status & CIR_IRSTS_PE) { -+ if (nvt_cir_tx_inactive(nvt)) -+ nvt_get_rx_ir_data(nvt); -+ -+ spin_lock_irqsave(&nvt->nvt_lock, flags); -+ -+ cur_state = nvt->study_state; -+ -+ spin_unlock_irqrestore(&nvt->nvt_lock, flags); -+ -+ if (cur_state == ST_STUDY_NONE) -+ nvt_clear_cir_fifo(nvt); -+ } -+ -+ if (status & CIR_IRSTS_TE) -+ nvt_clear_tx_fifo(nvt); -+ -+ if (status & CIR_IRSTS_TTR) { -+ unsigned int pos, count; -+ u8 tmp; -+ -+ spin_lock_irqsave(&nvt->tx.lock, flags); -+ -+ pos = nvt->tx.cur_buf_num; -+ count = nvt->tx.buf_count; -+ -+ /* Write data into the hardware tx fifo while pos < count */ -+ if (pos < count) { -+ nvt_cir_reg_write(nvt, nvt->tx.buf[pos], CIR_STXFIFO); -+ nvt->tx.cur_buf_num++; -+ /* Disable TX FIFO Trigger Level Reach (TTR) interrupt */ -+ } else { -+ tmp = nvt_cir_reg_read(nvt, CIR_IREN); -+ nvt_cir_reg_write(nvt, tmp & ~CIR_IREN_TTR, CIR_IREN); -+ } -+ -+ spin_unlock_irqrestore(&nvt->tx.lock, flags); -+ -+ } -+ -+ /* FIXME: what (else) should we do if we hit an underrun? */ -+ if (status & CIR_IRSTS_TFU) { -+ spin_lock_irqsave(&nvt->tx.lock, flags); -+ if (nvt->tx.tx_state == ST_TX_REPLY) { -+ nvt->tx.tx_state = ST_TX_REQUEST; -+ wake_up(&nvt->tx.queue); -+ } -+ spin_unlock_irqrestore(&nvt->tx.lock, flags); -+ } -+ -+ nvt_dbg_verbose("%s done", __func__); -+ return IRQ_RETVAL(IRQ_HANDLED); -+} -+ -+/* Interrupt service routine for CIR Wake */ -+static irqreturn_t nvt_cir_wake_isr(int irq, void *data) -+{ -+ u8 status, iren, val; -+ struct nvt_dev *nvt = data; -+ unsigned long flags; -+ -+ nvt_dbg_wake("%s firing", __func__); -+ -+ status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS); -+ if (!status) -+ return IRQ_RETVAL(IRQ_NONE); -+ -+ if (status & CIR_WAKE_IRSTS_IR_PENDING) -+ nvt_clear_cir_wake_fifo(nvt); -+ -+ nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS); -+ nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS); -+ -+ /* Interrupt may be shared with CIR, bail if Wake not enabled */ -+ iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); -+ if (!iren) { -+ nvt_dbg_wake("%s exiting, wake not enabled", __func__); -+ return IRQ_RETVAL(IRQ_HANDLED); -+ } -+ -+ if ((status & CIR_WAKE_IRSTS_PE) && -+ (nvt->wake_state == ST_WAKE_START)) { -+ while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) { -+ val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY); -+ nvt_dbg("setting wake up key: 0x%x", val); -+ } -+ -+ nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); -+ spin_lock_irqsave(&nvt->nvt_lock, flags); -+ nvt->wake_state = ST_WAKE_FINISH; -+ spin_unlock_irqrestore(&nvt->nvt_lock, flags); -+ } -+ -+ nvt_dbg_wake("%s done", __func__); -+ return IRQ_RETVAL(IRQ_HANDLED); -+} -+ -+static void nvt_enable_cir(struct nvt_dev *nvt) -+{ -+ /* set function enable flags */ -+ nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | -+ CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, -+ CIR_IRCON); -+ -+ nvt_efm_enable(nvt); -+ -+ /* enable the CIR logical device */ -+ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); -+ nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); -+ -+ nvt_efm_disable(nvt); -+ -+ /* clear all pending interrupts */ -+ nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); -+ -+ /* enable interrupts */ -+ nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); -+} -+ -+static void nvt_disable_cir(struct nvt_dev *nvt) -+{ -+ /* clear all pending interrupts */ -+ nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); -+ -+ /* clear all function enable flags */ -+ nvt_cir_reg_write(nvt, 0, CIR_IRCON); -+ -+ /* flush cir fifos */ -+ nvt_clear_cir_fifo(nvt); -+ nvt_clear_tx_fifo(nvt); -+ -+ nvt_efm_enable(nvt); -+ -+ /* disable the CIR logical device */ -+ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); -+ nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); -+ -+ nvt_efm_disable(nvt); -+ -+ /* disable CIR interrupts */ -+ nvt_cir_reg_write(nvt, 0, CIR_IREN); -+} -+ -+static int nvt_open(void *data) -+{ -+ struct nvt_dev *nvt = (struct nvt_dev *)data; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&nvt->nvt_lock, flags); -+ nvt->in_use = true; -+ /* FIXME: enable/disable worth the effort? */ -+ nvt_enable_cir(nvt); -+ spin_unlock_irqrestore(&nvt->nvt_lock, flags); -+ -+ return 0; -+} -+ -+static void nvt_close(void *data) -+{ -+ struct nvt_dev *nvt = (struct nvt_dev *)data; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&nvt->nvt_lock, flags); -+ nvt->in_use = false; -+ /* FIXME: enable/disable worth the effort? */ -+ nvt_disable_cir(nvt); -+ spin_unlock_irqrestore(&nvt->nvt_lock, flags); -+} -+ -+/* Allocate memory, probe hardware, and initialize everything */ -+static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) -+{ -+ struct nvt_dev *nvt = NULL; -+ struct input_dev *rdev = NULL; -+ struct ir_dev_props *props = NULL; -+ int ret = -ENOMEM; -+ -+ nvt = kzalloc(sizeof(struct nvt_dev), GFP_KERNEL); -+ if (!nvt) -+ return ret; -+ -+ props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); -+ if (!props) -+ goto failure; -+ -+ /* input device for IR remote (and tx) */ -+ rdev = input_allocate_device(); -+ if (!rdev) -+ goto failure; -+ -+ ret = -ENODEV; -+ /* validate pnp resources */ -+ if (!pnp_port_valid(pdev, 0) || -+ pnp_port_len(pdev, 0) < CIR_IOREG_LENGTH) { -+ dev_err(&pdev->dev, "IR PNP Port not valid!\n"); -+ goto failure; -+ } -+ -+ if (!pnp_irq_valid(pdev, 0)) { -+ dev_err(&pdev->dev, "PNP IRQ not valid!\n"); -+ goto failure; -+ } -+ -+ if (!pnp_port_valid(pdev, 1) || -+ pnp_port_len(pdev, 1) < CIR_IOREG_LENGTH) { -+ dev_err(&pdev->dev, "Wake PNP Port not valid!\n"); -+ goto failure; -+ } -+ -+ nvt->cir_addr = pnp_port_start(pdev, 0); -+ nvt->cir_irq = pnp_irq(pdev, 0); -+ -+ nvt->cir_wake_addr = pnp_port_start(pdev, 1); -+ /* irq is always shared between cir and cir wake */ -+ nvt->cir_wake_irq = nvt->cir_irq; -+ -+ nvt->cr_efir = CR_EFIR; -+ nvt->cr_efdr = CR_EFDR; -+ -+ spin_lock_init(&nvt->nvt_lock); -+ spin_lock_init(&nvt->tx.lock); -+ -+ ret = -EBUSY; -+ /* now claim resources */ -+ if (!request_region(nvt->cir_addr, -+ CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) -+ goto failure; -+ -+ if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED, -+ NVT_DRIVER_NAME, (void *)nvt)) -+ goto failure; -+ -+ if (!request_region(nvt->cir_wake_addr, -+ CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) -+ goto failure; -+ -+ if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED, -+ NVT_DRIVER_NAME, (void *)nvt)) -+ goto failure; -+ -+ pnp_set_drvdata(pdev, nvt); -+ nvt->pdev = pdev; -+ -+ init_waitqueue_head(&nvt->tx.queue); -+ -+ ret = nvt_hw_detect(nvt); -+ if (ret) -+ goto failure; -+ -+ /* Initialize CIR & CIR Wake Logical Devices */ -+ nvt_efm_enable(nvt); -+ nvt_cir_ldev_init(nvt); -+ nvt_cir_wake_ldev_init(nvt); -+ nvt_efm_disable(nvt); -+ -+ /* Initialize CIR & CIR Wake Config Registers */ -+ nvt_cir_regs_init(nvt); -+ nvt_cir_wake_regs_init(nvt); -+ -+ /* Set up ir-core props */ -+ props->priv = nvt; -+ props->driver_type = RC_DRIVER_IR_RAW; -+ props->allowed_protos = IR_TYPE_ALL; -+ props->open = nvt_open; -+ props->close = nvt_close; -+#if 0 -+ props->min_timeout = XYZ; -+ props->max_timeout = XYZ; -+ props->timeout = XYZ; -+ /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ -+ props->rx_resolution = XYZ; -+ -+ /* tx bits */ -+ props->tx_resolution = XYZ; -+#endif -+ props->tx_ir = nvt_tx_ir; -+ props->s_tx_carrier = nvt_set_tx_carrier; -+ -+ rdev->name = "Nuvoton w836x7hg Infrared Remote Transceiver"; -+ -+ nvt->props = props; -+ nvt->rdev = rdev; -+ -+ device_set_wakeup_capable(&pdev->dev, 1); -+ device_set_wakeup_enable(&pdev->dev, 1); -+ -+ ret = ir_input_register(rdev, RC_MAP_RC6_MCE, props, NVT_DRIVER_NAME); -+ if (ret) -+ goto failure; -+ -+ nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n"); -+ if (debug) { -+ cir_dump_regs(nvt); -+ cir_wake_dump_regs(nvt); -+ } -+ -+ return 0; -+ -+failure: -+ if (nvt->cir_irq) -+ free_irq(nvt->cir_irq, nvt); -+ if (nvt->cir_addr) -+ release_region(nvt->cir_addr, CIR_IOREG_LENGTH); -+ -+ if (nvt->cir_wake_irq) -+ free_irq(nvt->cir_wake_irq, nvt); -+ if (nvt->cir_wake_addr) -+ release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); -+ -+ input_free_device(rdev); -+ kfree(props); -+ kfree(nvt); -+ -+ return ret; -+} -+ -+static void __devexit nvt_remove(struct pnp_dev *pdev) -+{ -+ struct nvt_dev *nvt = pnp_get_drvdata(pdev); -+ unsigned long flags; -+ -+ spin_lock_irqsave(&nvt->nvt_lock, flags); -+ /* disable CIR */ -+ nvt_cir_reg_write(nvt, 0, CIR_IREN); -+ nvt_disable_cir(nvt); -+ /* enable CIR Wake (for IR power-on) */ -+ nvt_enable_wake(nvt); -+ spin_unlock_irqrestore(&nvt->nvt_lock, flags); -+ -+ /* free resources */ -+ free_irq(nvt->cir_irq, nvt); -+ free_irq(nvt->cir_wake_irq, nvt); -+ release_region(nvt->cir_addr, CIR_IOREG_LENGTH); -+ release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); -+ -+ ir_input_unregister(nvt->rdev); -+ -+ kfree(nvt->props); -+ kfree(nvt); -+} -+ -+static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) -+{ -+ struct nvt_dev *nvt = pnp_get_drvdata(pdev); -+ unsigned long flags; -+ -+ nvt_dbg("%s called", __func__); -+ -+ /* zero out misc state tracking */ -+ spin_lock_irqsave(&nvt->nvt_lock, flags); -+ nvt->study_state = ST_STUDY_NONE; -+ nvt->wake_state = ST_WAKE_NONE; -+ spin_unlock_irqrestore(&nvt->nvt_lock, flags); -+ -+ spin_lock_irqsave(&nvt->tx.lock, flags); -+ nvt->tx.tx_state = ST_TX_NONE; -+ spin_unlock_irqrestore(&nvt->tx.lock, flags); -+ -+ /* disable all CIR interrupts */ -+ nvt_cir_reg_write(nvt, 0, CIR_IREN); -+ -+ nvt_efm_enable(nvt); -+ -+ /* disable cir logical dev */ -+ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); -+ nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); -+ -+ nvt_efm_disable(nvt); -+ -+ /* make sure wake is enabled */ -+ nvt_enable_wake(nvt); -+ -+ return 0; -+} -+ -+static int nvt_resume(struct pnp_dev *pdev) -+{ -+ int ret = 0; -+ struct nvt_dev *nvt = pnp_get_drvdata(pdev); -+ -+ nvt_dbg("%s called", __func__); -+ -+ /* open interrupt */ -+ nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); -+ -+ /* Enable CIR logical device */ -+ nvt_efm_enable(nvt); -+ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); -+ nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); -+ -+ nvt_efm_disable(nvt); -+ -+ nvt_cir_regs_init(nvt); -+ nvt_cir_wake_regs_init(nvt); -+ -+ return ret; -+} -+ -+static void nvt_shutdown(struct pnp_dev *pdev) -+{ -+ struct nvt_dev *nvt = pnp_get_drvdata(pdev); -+ nvt_enable_wake(nvt); -+} -+ -+static const struct pnp_device_id nvt_ids[] = { -+ { "WEC0530", 0 }, /* CIR */ -+ { "NTN0530", 0 }, /* CIR for new chip's pnp id*/ -+ { "", 0 }, -+}; -+ -+static struct pnp_driver nvt_driver = { -+ .name = NVT_DRIVER_NAME, -+ .id_table = nvt_ids, -+ .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, -+ .probe = nvt_probe, -+ .remove = __devexit_p(nvt_remove), -+#ifdef CONFIG_PM -+ .suspend = nvt_suspend, -+ .resume = nvt_resume, -+#endif -+ .shutdown = nvt_shutdown, -+}; -+ -+int nvt_init(void) -+{ -+ return pnp_register_driver(&nvt_driver); -+} -+ -+void nvt_exit(void) -+{ -+ pnp_unregister_driver(&nvt_driver); -+} -+ -+module_param(debug, int, S_IRUGO | S_IWUSR); -+MODULE_PARM_DESC(debug, "Enable debugging output"); -+ -+MODULE_DEVICE_TABLE(pnp, nvt_ids); -+MODULE_DESCRIPTION("driver for Nuvoton W83667HG-A & W83677HG-I CIR"); -+ -+MODULE_AUTHOR("Jarod Wilson "); -+MODULE_LICENSE("GPL"); -+ -+module_init(nvt_init); -+module_exit(nvt_exit); -diff -Naur linux-2.6.36-rc7/drivers/media/IR/nuvoton-cir.h linux-2.6.36-rc7.patch/drivers/media/IR/nuvoton-cir.h ---- linux-2.6.36-rc7/drivers/media/IR/nuvoton-cir.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.36-rc7.patch/drivers/media/IR/nuvoton-cir.h 2010-10-07 22:44:04.000000000 +0200 -@@ -0,0 +1,431 @@ -+/* -+ * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR -+ * -+ * Copyright (C) 2010 Jarod Wilson -+ * Copyright (C) 2009 Nuvoton PS Team -+ * -+ * Special thanks to Nuvoton for providing hardware, spec sheets and -+ * sample code upon which portions of this driver are based. Indirect -+ * thanks also to Maxim Levitsky, whose ene_ir driver this driver is -+ * modeled after. -+ * -+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -+ * USA -+ */ -+ -+#include -+#include -+ -+/* platform driver name to register */ -+#define NVT_DRIVER_NAME "nuvoton-cir" -+ -+/* debugging module parameter */ -+static int debug; -+ -+ -+#define nvt_pr(level, text, ...) \ -+ printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__) -+ -+#define nvt_dbg(text, ...) \ -+ if (debug) \ -+ printk(KERN_DEBUG \ -+ KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) -+ -+#define nvt_dbg_verbose(text, ...) \ -+ if (debug > 1) \ -+ printk(KERN_DEBUG \ -+ KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) -+ -+#define nvt_dbg_wake(text, ...) \ -+ if (debug > 2) \ -+ printk(KERN_DEBUG \ -+ KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) -+ -+ -+/* -+ * Original lirc driver said min value of 76, and recommended value of 256 -+ * for the buffer length, but then used 2048. Never mind that the size of the -+ * RX FIFO is 32 bytes... So I'm using 32 for RX and 256 for TX atm, but I'm -+ * not sure if maybe that TX value is off by a factor of 8 (bits vs. bytes), -+ * and I don't have TX-capable hardware to test/debug on... -+ */ -+#define TX_BUF_LEN 256 -+#define RX_BUF_LEN 32 -+ -+struct nvt_dev { -+ struct pnp_dev *pdev; -+ struct input_dev *rdev; -+ struct ir_dev_props *props; -+ struct ir_raw_event rawir; -+ -+ spinlock_t nvt_lock; -+ bool in_use; -+ -+ /* for decode */ -+ u8 buf[RX_BUF_LEN]; -+ unsigned int pkts; -+ u8 rem; -+ u8 cmd; -+ -+ struct { -+ spinlock_t lock; -+ u8 buf[TX_BUF_LEN]; -+ unsigned int buf_count; -+ unsigned int cur_buf_num; -+ wait_queue_head_t queue; -+ u8 tx_state; -+ } tx; -+ -+ /* EFER Config register index/data pair */ -+ u8 cr_efir; -+ u8 cr_efdr; -+ -+ /* hardware I/O settings */ -+ unsigned long cir_addr; -+ unsigned long cir_wake_addr; -+ int cir_irq; -+ int cir_wake_irq; -+ -+ /* hardware features */ -+ bool hw_learning_capable; -+ bool hw_tx_capable; -+ -+ /* rx settings */ -+ bool learning_enabled; /* FIXME: not yet utilized */ -+ bool carrier_detect_enabled; -+ -+ /* track cir wake state */ -+ u8 wake_state; -+ /* for study */ -+ u8 study_state; -+ /* carrier period = 1 / frequency */ -+ u32 carrier; -+}; -+ -+/* study states */ -+#define ST_STUDY_NONE 0x0 -+#define ST_STUDY_START 0x1 -+#define ST_STUDY_CARRIER 0x2 -+#define ST_STUDY_ALL_RECV 0x4 -+ -+/* wake states */ -+#define ST_WAKE_NONE 0x0 -+#define ST_WAKE_START 0x1 -+#define ST_WAKE_FINISH 0x2 -+ -+/* receive states */ -+#define ST_RX_WAIT_7F 0x1 -+#define ST_RX_WAIT_HEAD 0x2 -+#define ST_RX_WAIT_SILENT_END 0x4 -+ -+/* send states */ -+#define ST_TX_NONE 0x0 -+#define ST_TX_REQUEST 0x2 -+#define ST_TX_REPLY 0x4 -+ -+/* buffer packet constants */ -+#define BUF_PULSE_BIT 0x80 -+#define BUF_LEN_MASK 0x7f -+#define BUF_REPEAT_BYTE 0x70 -+#define BUF_REPEAT_MASK 0xf0 -+ -+#if 0 -+/* keycode table for EN_US layout MCE IR keyboard */ -+/* FIXME: this should be handled by a stand-alone keyboard/mouse decoder that both -+ * this driver and the mceusb driver (and really, any raw ir receiver) can use */ -+unsigned int mce_kbd_keycode[256] = { -+ 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, -+ 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, -+ 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, -+ 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, -+ 65, 66, 67, 68, 87, 88, 99, 70, 119, 110, 102, 104, 111, 107, 109, 106, -+ 105, 108, 103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, -+ 72, 73, 82, 83, 86, 127, 116, 117, 183, 184, 185, 186, 187, 188, 189, 190, -+ 191, 192, 193, 194, 134, 138, 130, 132, 128, 129, 131, 137, 133, 135, 136, 113, -+ 115, 114, 0, 0, 0, 121, 0, 89, 93, 124, 92, 94, 95, 0, 0, 0, -+ 122, 123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -+ 29, 42, 56, 125, 97, 54, 100, 126, 164, 166, 165, 163, 161, 115, 114, 113, -+ 150, 158, 159, 128, 136, 177, 178, 176, 142, 152, 173, 140 -+}; -+#endif -+ -+/* CIR settings */ -+ -+/* total length of CIR and CIR WAKE */ -+#define CIR_IOREG_LENGTH 0x0f -+ -+/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */ -+#define CIR_RX_LIMIT_COUNT 0x7d0 -+ -+/* CIR Regs */ -+#define CIR_IRCON 0x00 -+#define CIR_IRSTS 0x01 -+#define CIR_IREN 0x02 -+#define CIR_RXFCONT 0x03 -+#define CIR_CP 0x04 -+#define CIR_CC 0x05 -+#define CIR_SLCH 0x06 -+#define CIR_SLCL 0x07 -+#define CIR_FIFOCON 0x08 -+#define CIR_IRFIFOSTS 0x09 -+#define CIR_SRXFIFO 0x0a -+#define CIR_TXFCONT 0x0b -+#define CIR_STXFIFO 0x0c -+#define CIR_FCCH 0x0d -+#define CIR_FCCL 0x0e -+#define CIR_IRFSM 0x0f -+ -+/* CIR IRCON settings */ -+#define CIR_IRCON_RECV 0x80 -+#define CIR_IRCON_WIREN 0x40 -+#define CIR_IRCON_TXEN 0x20 -+#define CIR_IRCON_RXEN 0x10 -+#define CIR_IRCON_WRXINV 0x08 -+#define CIR_IRCON_RXINV 0x04 -+ -+#define CIR_IRCON_SAMPLE_PERIOD_SEL_1 0x00 -+#define CIR_IRCON_SAMPLE_PERIOD_SEL_25 0x01 -+#define CIR_IRCON_SAMPLE_PERIOD_SEL_50 0x02 -+#define CIR_IRCON_SAMPLE_PERIOD_SEL_100 0x03 -+ -+/* FIXME/jarod: make this a runtime option */ -+/* select sample period as 50us */ -+#define CIR_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50 -+ -+/* CIR IRSTS settings */ -+#define CIR_IRSTS_RDR 0x80 -+#define CIR_IRSTS_RTR 0x40 -+#define CIR_IRSTS_PE 0x20 -+#define CIR_IRSTS_RFO 0x10 -+#define CIR_IRSTS_TE 0x08 -+#define CIR_IRSTS_TTR 0x04 -+#define CIR_IRSTS_TFU 0x02 -+#define CIR_IRSTS_GH 0x01 -+ -+/* CIR IREN settings */ -+#define CIR_IREN_RDR 0x80 -+#define CIR_IREN_RTR 0x40 -+#define CIR_IREN_PE 0x20 -+#define CIR_IREN_RFO 0x10 -+#define CIR_IREN_TE 0x08 -+#define CIR_IREN_TTR 0x04 -+#define CIR_IREN_TFU 0x02 -+#define CIR_IREN_GH 0x01 -+ -+/* CIR FIFOCON settings */ -+#define CIR_FIFOCON_TXFIFOCLR 0x80 -+ -+#define CIR_FIFOCON_TX_TRIGGER_LEV_31 0x00 -+#define CIR_FIFOCON_TX_TRIGGER_LEV_24 0x10 -+#define CIR_FIFOCON_TX_TRIGGER_LEV_16 0x20 -+#define CIR_FIFOCON_TX_TRIGGER_LEV_8 0x30 -+ -+/* FIXME/jarod: make this a runtime option */ -+/* select TX trigger level as 16 */ -+#define CIR_FIFOCON_TX_TRIGGER_LEV CIR_FIFOCON_TX_TRIGGER_LEV_16 -+ -+#define CIR_FIFOCON_RXFIFOCLR 0x08 -+ -+#define CIR_FIFOCON_RX_TRIGGER_LEV_1 0x00 -+#define CIR_FIFOCON_RX_TRIGGER_LEV_8 0x01 -+#define CIR_FIFOCON_RX_TRIGGER_LEV_16 0x02 -+#define CIR_FIFOCON_RX_TRIGGER_LEV_24 0x03 -+ -+/* FIXME/jarod: make this a runtime option */ -+/* select RX trigger level as 24 */ -+#define CIR_FIFOCON_RX_TRIGGER_LEV CIR_FIFOCON_RX_TRIGGER_LEV_24 -+ -+/* CIR IRFIFOSTS settings */ -+#define CIR_IRFIFOSTS_IR_PENDING 0x80 -+#define CIR_IRFIFOSTS_RX_GS 0x40 -+#define CIR_IRFIFOSTS_RX_FTA 0x20 -+#define CIR_IRFIFOSTS_RX_EMPTY 0x10 -+#define CIR_IRFIFOSTS_RX_FULL 0x08 -+#define CIR_IRFIFOSTS_TX_FTA 0x04 -+#define CIR_IRFIFOSTS_TX_EMPTY 0x02 -+#define CIR_IRFIFOSTS_TX_FULL 0x01 -+ -+ -+/* CIR WAKE UP Regs */ -+#define CIR_WAKE_IRCON 0x00 -+#define CIR_WAKE_IRSTS 0x01 -+#define CIR_WAKE_IREN 0x02 -+#define CIR_WAKE_FIFO_CMP_DEEP 0x03 -+#define CIR_WAKE_FIFO_CMP_TOL 0x04 -+#define CIR_WAKE_FIFO_COUNT 0x05 -+#define CIR_WAKE_SLCH 0x06 -+#define CIR_WAKE_SLCL 0x07 -+#define CIR_WAKE_FIFOCON 0x08 -+#define CIR_WAKE_SRXFSTS 0x09 -+#define CIR_WAKE_SAMPLE_RX_FIFO 0x0a -+#define CIR_WAKE_WR_FIFO_DATA 0x0b -+#define CIR_WAKE_RD_FIFO_ONLY 0x0c -+#define CIR_WAKE_RD_FIFO_ONLY_IDX 0x0d -+#define CIR_WAKE_FIFO_IGNORE 0x0e -+#define CIR_WAKE_IRFSM 0x0f -+ -+/* CIR WAKE UP IRCON settings */ -+#define CIR_WAKE_IRCON_DEC_RST 0x80 -+#define CIR_WAKE_IRCON_MODE1 0x40 -+#define CIR_WAKE_IRCON_MODE0 0x20 -+#define CIR_WAKE_IRCON_RXEN 0x10 -+#define CIR_WAKE_IRCON_R 0x08 -+#define CIR_WAKE_IRCON_RXINV 0x04 -+ -+/* FIXME/jarod: make this a runtime option */ -+/* select a same sample period like cir register */ -+#define CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50 -+ -+/* CIR WAKE IRSTS Bits */ -+#define CIR_WAKE_IRSTS_RDR 0x80 -+#define CIR_WAKE_IRSTS_RTR 0x40 -+#define CIR_WAKE_IRSTS_PE 0x20 -+#define CIR_WAKE_IRSTS_RFO 0x10 -+#define CIR_WAKE_IRSTS_GH 0x08 -+#define CIR_WAKE_IRSTS_IR_PENDING 0x01 -+ -+/* CIR WAKE UP IREN Bits */ -+#define CIR_WAKE_IREN_RDR 0x80 -+#define CIR_WAKE_IREN_RTR 0x40 -+#define CIR_WAKE_IREN_PE 0x20 -+#define CIR_WAKE_IREN_RFO 0x10 -+#define CIR_WAKE_IREN_TE 0x08 -+#define CIR_WAKE_IREN_TTR 0x04 -+#define CIR_WAKE_IREN_TFU 0x02 -+#define CIR_WAKE_IREN_GH 0x01 -+ -+/* CIR WAKE FIFOCON settings */ -+#define CIR_WAKE_FIFOCON_RXFIFOCLR 0x08 -+ -+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67 0x00 -+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_66 0x01 -+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_65 0x02 -+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_64 0x03 -+ -+/* FIXME/jarod: make this a runtime option */ -+/* select WAKE UP RX trigger level as 67 */ -+#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67 -+ -+/* CIR WAKE SRXFSTS settings */ -+#define CIR_WAKE_IRFIFOSTS_RX_GS 0x80 -+#define CIR_WAKE_IRFIFOSTS_RX_FTA 0x40 -+#define CIR_WAKE_IRFIFOSTS_RX_EMPTY 0x20 -+#define CIR_WAKE_IRFIFOSTS_RX_FULL 0x10 -+ -+/* CIR Wake FIFO buffer is 67 bytes long */ -+#define CIR_WAKE_FIFO_LEN 67 -+ -+ -+/* -+ * Extended Function Enable Registers: -+ * Extended Function Index Register -+ * Extended Function Data Register -+ */ -+#define CR_EFIR 0x2e -+#define CR_EFDR 0x2f -+ -+/* Possible alternate EFER values, depends on how the chip is wired */ -+#define CR_EFIR2 0x4e -+#define CR_EFDR2 0x4f -+ -+/* Extended Function Mode enable/disable magic values */ -+#define EFER_EFM_ENABLE 0x87 -+#define EFER_EFM_DISABLE 0xaa -+ -+/* Chip IDs found in CR_CHIP_ID_{HI,LO} */ -+#define CHIP_ID_HIGH 0xb4 -+#define CHIP_ID_LOW 0x72 -+#define CHIP_ID_LOW2 0x73 -+ -+/* Config regs we need to care about */ -+#define CR_SOFTWARE_RESET 0x02 -+#define CR_LOGICAL_DEV_SEL 0x07 -+#define CR_CHIP_ID_HI 0x20 -+#define CR_CHIP_ID_LO 0x21 -+#define CR_DEV_POWER_DOWN 0x22 /* bit 2 is CIR power, default power on */ -+#define CR_OUTPUT_PIN_SEL 0x27 -+#define CR_LOGICAL_DEV_EN 0x30 /* valid for all logical devices */ -+/* next three regs valid for both the CIR and CIR_WAKE logical devices */ -+#define CR_CIR_BASE_ADDR_HI 0x60 -+#define CR_CIR_BASE_ADDR_LO 0x61 -+#define CR_CIR_IRQ_RSRC 0x70 -+/* next three regs valid only for ACPI logical dev */ -+#define CR_ACPI_CIR_WAKE 0xe0 -+#define CR_ACPI_IRQ_EVENTS 0xf6 -+#define CR_ACPI_IRQ_EVENTS2 0xf7 -+ -+/* Logical devices that we need to care about */ -+#define LOGICAL_DEV_LPT 0x01 -+#define LOGICAL_DEV_CIR 0x06 -+#define LOGICAL_DEV_ACPI 0x0a -+#define LOGICAL_DEV_CIR_WAKE 0x0e -+ -+#define LOGICAL_DEV_DISABLE 0x00 -+#define LOGICAL_DEV_ENABLE 0x01 -+ -+#define CIR_WAKE_ENABLE_BIT 0x08 -+#define CIR_INTR_MOUSE_IRQ_BIT 0x80 -+#define PME_INTR_CIR_PASS_BIT 0x08 -+ -+#define OUTPUT_PIN_SEL_MASK 0xbc -+#define OUTPUT_ENABLE_CIR 0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */ -+#define OUTPUT_ENABLE_CIRWB 0x40 /* enable wide-band sensor */ -+ -+/* MCE CIR signal length, related on sample period */ -+ -+/* MCE CIR controller signal length: about 43ms -+ * 43ms / 50us (sample period) * 0.85 (inaccuracy) -+ */ -+#define CONTROLLER_BUF_LEN_MIN 830 -+ -+/* MCE CIR keyboard signal length: about 26ms -+ * 26ms / 50us (sample period) * 0.85 (inaccuracy) -+ */ -+#define KEYBOARD_BUF_LEN_MAX 650 -+#define KEYBOARD_BUF_LEN_MIN 610 -+ -+/* MCE CIR mouse signal length: about 24ms -+ * 24ms / 50us (sample period) * 0.85 (inaccuracy) -+ */ -+#define MOUSE_BUF_LEN_MIN 565 -+ -+#define CIR_SAMPLE_PERIOD 50 -+#define CIR_SAMPLE_LOW_INACCURACY 0.85 -+ -+/* MAX silence time that driver will sent to lirc */ -+#define MAX_SILENCE_TIME 60000 -+ -+/* FIXME/jarod: should be runtime selectable */ -+/* this value copy from lirc_mod_mce */ -+#if CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_100 -+#define SAMPLE_PERIOD 100 -+ -+#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_50 -+#define SAMPLE_PERIOD 50 -+ -+#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_25 -+#define SAMPLE_PERIOD 25 -+ -+#else -+#define SAMPLE_PERIOD 1 -+#endif -+ -+/* as VISTA MCE definition, valid carrier value */ -+#define MAX_CARRIER 60000 -+#define MIN_CARRIER 30000 diff --git a/packages/linux/patches/linux-2.6.36-add_nuvoton_cir-0.2.diff b/packages/linux/patches/linux-2.6.36-add_nuvoton_cir-0.2.diff index 56dd752890..c6d1509dd0 100644 --- a/packages/linux/patches/linux-2.6.36-add_nuvoton_cir-0.2.diff +++ b/packages/linux/patches/linux-2.6.36-add_nuvoton_cir-0.2.diff @@ -1,994 +1,1724 @@ -From b9a1211dff08aa73fc26db66980ec0710a6c7134 Mon Sep 17 00:00:00 2001 -From: Ruslan Pisarev -Date: Mon, 27 Sep 2010 10:01:36 -0300 -Subject: [PATCH] V4L/DVB: Staging: cx25821: fix braces and space coding style issues +From 04515eb583b1651cb95bc7c34a00696fc91c4fa8 Mon Sep 17 00:00:00 2001 +From: Jarod Wilson +Date: Thu, 7 Oct 2010 16:50:34 -0400 +Subject: [PATCH 1/1] IR: add driver for Nuvoton w836x7hg integrated CIR -Errors found by the checkpatch.pl tool. +This is a new ir-core pnp driver for the Nuvoton w836x7hg integrated CIR +function. The chip is found on at least the ASRock ION 330HT boxes and +apparently, on a number of Intel DP55-series motherboards: -[mchehab@redhat.com: merged a series of CodingStyle cleanup patches for cx25851. They're all from the same author, and patches the same driver] -Signed-off-by: Ruslan Pisarev -Cc: Palash Bandyopadhyay -Signed-off-by: Mauro Carvalho Chehab +http://www.asrock.com/nettop/overview.asp?Model=ION%20330HT +http://downloadcenter.intel.com/Detail_Desc.aspx?agr=Y&DwnldID=17685&lang=eng + +This driver was made possible by a hardware donation from Nuvoton, along +with sample code (in the form of an lirc driver) and datasheet, so huge +thanks to them for supporting this effort. Note that this driver +constitutes a massive rewrite, porting from the lirc interfaces to the +ir-core interfaces, and restructuring the driver to look more like Maxim +Levitsky's ene_ir driver (as well as generally making it look more like +kernel code). + +There's some work left to be done on this driver, to fully support the +range of functionality possible, but receive and IR power-on/wake are +both functional (may require setting wake key under another OS atm). The +hardware I've got (one of the ASRock boxes) only supports RX, so TX is +completely untested as of yet. Certain RX parameters, like sample +resolution and RX IRQ sample length trigger level could possibly stand +to be made tweakable via modparams or sysfs nodes, but the current +values work well enough for me w/an MCE RC6A remote. + +The original lirc driver carried support for the Windows MCE IR +keyboard/mouse device, which I plan to add back generically, in a way +that should be usable by any raw IR receiver (or at least by this driver +and the mceusb driver). + +Suspend and resume have also been tested, the power button on my remote +can be used to wake the machine, and CIR functionality resumes just +fine. Module unload/reload has also been tested, though not extensively +or repetitively. Also tested to work with the lirc bridge plugin for +userspace decoding. + +Signed-off-by: Jarod Wilson --- - drivers/staging/cx25821/cx25821-audio-upstream.c | 13 +- - drivers/staging/cx25821/cx25821-audio.h | 10 +- - drivers/staging/cx25821/cx25821-core.c | 62 +++++----- - drivers/staging/cx25821/cx25821-i2c.c | 2 +- - drivers/staging/cx25821/cx25821-medusa-reg.h | 10 +- - drivers/staging/cx25821/cx25821-medusa-video.c | 8 +- - drivers/staging/cx25821/cx25821-reg.h | 4 +- - .../staging/cx25821/cx25821-video-upstream-ch2.c | 135 +++++++++----------- - .../staging/cx25821/cx25821-video-upstream-ch2.h | 14 +- - drivers/staging/cx25821/cx25821-video-upstream.c | 28 ++-- - drivers/staging/cx25821/cx25821-video-upstream.h | 10 +- - drivers/staging/cx25821/cx25821.h | 51 ++++---- - 12 files changed, 168 insertions(+), 179 deletions(-) + drivers/media/IR/Kconfig | 13 + + drivers/media/IR/Makefile | 1 + + drivers/media/IR/nuvoton-cir.c | 1216 ++++++++++++++++++++++++++++++++++++++++ + drivers/media/IR/nuvoton-cir.h | 408 ++++++++++++++ + 4 files changed, 1638 insertions(+), 0 deletions(-) + create mode 100644 drivers/media/IR/nuvoton-cir.c + create mode 100644 drivers/media/IR/nuvoton-cir.h -diff --git a/drivers/staging/cx25821/cx25821-audio-upstream.c b/drivers/staging/cx25821/cx25821-audio-upstream.c -index cdff49f..6f32006 100644 ---- a/drivers/staging/cx25821/cx25821-audio-upstream.c -+++ b/drivers/staging/cx25821/cx25821-audio-upstream.c -@@ -40,8 +40,8 @@ MODULE_AUTHOR("Hiep Huynh "); - MODULE_LICENSE("GPL"); +diff --git a/drivers/media/IR/Kconfig b/drivers/media/IR/Kconfig +index 152000d..364514a 100644 +--- a/drivers/media/IR/Kconfig ++++ b/drivers/media/IR/Kconfig +@@ -113,6 +113,19 @@ config IR_IMON + To compile this driver as a module, choose M here: the + module will be called imon. - static int _intr_msk = -- FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF | FLD_AUD_SRC_SYNC | -- FLD_AUD_SRC_OPC_ERR; -+ FLD_AUD_SRC_RISCI1 | FLD_AUD_SRC_OF | FLD_AUD_SRC_SYNC | -+ FLD_AUD_SRC_OPC_ERR; - - int cx25821_sram_channel_setup_upstream_audio(struct cx25821_dev *dev, - struct sram_channel *ch, -@@ -506,7 +506,7 @@ int cx25821_audio_upstream_irq(struct cx25821_dev *dev, int chan_num, - { - int i = 0; - u32 int_msk_tmp; -- struct sram_channel *channel = dev->channels[chan_num].sram_channels; -+ struct sram_channel *channel = dev->channels[chan_num].sram_channels; - dma_addr_t risc_phys_jump_addr; - __le32 *rp; - -@@ -608,7 +608,7 @@ static irqreturn_t cx25821_upstream_irq_audio(int irq, void *dev_id) - if (!dev) - return -1; - -- sram_ch = dev->channels[dev->_audio_upstream_channel_select]. -+ sram_ch = dev->channels[dev->_audio_upstream_channel_select]. - sram_channels; - - msk_stat = cx_read(sram_ch->int_mstat); -@@ -733,7 +733,7 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) - } - - dev->_audio_upstream_channel_select = channel_select; -- sram_ch = dev->channels[channel_select].sram_channels; -+ sram_ch = dev->channels[channel_select].sram_channels; - - /* Work queue */ - INIT_WORK(&dev->_audio_work_entry, cx25821_audioups_handler); -@@ -764,9 +764,8 @@ int cx25821_audio_upstream_init(struct cx25821_dev *dev, int channel_select) - str_length + 1); - - /* Default if filename is empty string */ -- if (strcmp(dev->input_audiofilename, "") == 0) { -+ if (strcmp(dev->input_audiofilename, "") == 0) - dev->_audiofilename = "/root/audioGOOD.wav"; -- } - } else { - str_length = strlen(_defaultAudioName); - dev->_audiofilename = kmalloc(str_length + 1, GFP_KERNEL); -diff --git a/drivers/staging/cx25821/cx25821-audio.h b/drivers/staging/cx25821/cx25821-audio.h -index 434b2a3..a702a0d 100644 ---- a/drivers/staging/cx25821/cx25821-audio.h -+++ b/drivers/staging/cx25821/cx25821-audio.h -@@ -31,18 +31,18 @@ - #define NUMBER_OF_PROGRAMS 8 - - /* -- Max size of the RISC program for a buffer. - worst case is 2 writes per line -- Space is also added for the 4 no-op instructions added on the end. --*/ -+ * Max size of the RISC program for a buffer. - worst case is 2 writes per line -+ * Space is also added for the 4 no-op instructions added on the end. ++config IR_NUVOTON ++ tristate "Nuvoton w836x7hg Consumer Infrared Transceiver" ++ depends on PNP ++ depends on IR_CORE ++ ---help--- ++ Say Y here to enable support for integrated infrared receiver ++ /transciever made by Nuvoton (formerly Winbond). This chip is ++ found in the ASRock ION 330HT, as well as assorted Intel ++ DP55-series motherboards (and of course, possibly others). ++ ++ To compile this driver as a module, choose M here: the ++ module will be called nuvoton-cir. ++ + config IR_MCEUSB + tristate "Windows Media Center Ed. eHome Infrared Transceiver" + depends on USB_ARCH_HAS_HCD +diff --git a/drivers/media/IR/Makefile b/drivers/media/IR/Makefile +index 953c6c4..f9574ad 100644 +--- a/drivers/media/IR/Makefile ++++ b/drivers/media/IR/Makefile +@@ -17,5 +17,6 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o + # stand-alone IR receivers/transmitters + obj-$(CONFIG_IR_IMON) += imon.o + obj-$(CONFIG_IR_MCEUSB) += mceusb.o ++obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o + obj-$(CONFIG_IR_ENE) += ene_ir.o + obj-$(CONFIG_IR_STREAMZAP) += streamzap.o +diff --git a/drivers/media/IR/nuvoton-cir.c b/drivers/media/IR/nuvoton-cir.c +new file mode 100644 +index 0000000..1ce9359 +--- /dev/null ++++ b/drivers/media/IR/nuvoton-cir.c +@@ -0,0 +1,1216 @@ ++/* ++ * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR ++ * ++ * Copyright (C) 2010 Jarod Wilson ++ * Copyright (C) 2009 Nuvoton PS Team ++ * ++ * Special thanks to Nuvoton for providing hardware, spec sheets and ++ * sample code upon which portions of this driver are based. Indirect ++ * thanks also to Maxim Levitsky, whose ene_ir driver this driver is ++ * modeled after. ++ * ++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ * USA + */ - #ifndef USE_RISC_NOOP - #define MAX_BUFFER_PROGRAM_SIZE \ -- (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE*4) -+ (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE*4) - #endif - - /* MAE 12 July 2005 Try to use NOOP RISC instruction instead */ - #ifdef USE_RISC_NOOP - #define MAX_BUFFER_PROGRAM_SIZE \ -- (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_NOOP_INSTRUCTION_SIZE*4) -+ (2*LINES_PER_BUFFER*RISC_WRITE_INSTRUCTION_SIZE + RISC_NOOP_INSTRUCTION_SIZE*4) - #endif - - /* Sizes of various instructions in bytes. Used when adding instructions. */ -diff --git a/drivers/staging/cx25821/cx25821-core.c b/drivers/staging/cx25821/cx25821-core.c -index 03391f4..ca1eece 100644 ---- a/drivers/staging/cx25821/cx25821-core.c -+++ b/drivers/staging/cx25821/cx25821-core.c -@@ -42,7 +42,7 @@ static unsigned int card[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; - module_param_array(card, int, NULL, 0444); - MODULE_PARM_DESC(card, "card type"); - --static unsigned int cx25821_devcount = 0; -+static unsigned int cx25821_devcount; - - static DEFINE_MUTEX(devlist); - LIST_HEAD(cx25821_devlist); -@@ -781,14 +781,14 @@ static void cx25821_shutdown(struct cx25821_dev *dev) - - /* Disable Video A/B activity */ - for (i = 0; i < VID_CHANNEL_NUM; i++) { -- cx_write(dev->channels[i].sram_channels->dma_ctl, 0); -- cx_write(dev->channels[i].sram_channels->int_msk, 0); -+ cx_write(dev->channels[i].sram_channels->dma_ctl, 0); -+ cx_write(dev->channels[i].sram_channels->int_msk, 0); - } - -- for (i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; -- i++) { -- cx_write(dev->channels[i].sram_channels->dma_ctl, 0); -- cx_write(dev->channels[i].sram_channels->int_msk, 0); -+ for (i = VID_UPSTREAM_SRAM_CHANNEL_I; -+ i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) { -+ cx_write(dev->channels[i].sram_channels->dma_ctl, 0); -+ cx_write(dev->channels[i].sram_channels->int_msk, 0); - } - - /* Disable Audio activity */ -@@ -806,9 +806,9 @@ void cx25821_set_pixel_format(struct cx25821_dev *dev, int channel_select, - u32 format) - { - if (channel_select <= 7 && channel_select >= 0) { -- cx_write(dev->channels[channel_select]. -- sram_channels->pix_frmt, format); -- dev->channels[channel_select].pixel_formats = format; -+ cx_write(dev->channels[channel_select]. -+ sram_channels->pix_frmt, format); -+ dev->channels[channel_select].pixel_formats = format; - } - } - -@@ -829,7 +829,7 @@ static void cx25821_initialize(struct cx25821_dev *dev) - cx_write(PCI_INT_STAT, 0xffffffff); - - for (i = 0; i < VID_CHANNEL_NUM; i++) -- cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff); -+ cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff); - - cx_write(AUD_A_INT_STAT, 0xffffffff); - cx_write(AUD_B_INT_STAT, 0xffffffff); -@@ -843,22 +843,22 @@ static void cx25821_initialize(struct cx25821_dev *dev) - mdelay(100); - - for (i = 0; i < VID_CHANNEL_NUM; i++) { -- cx25821_set_vip_mode(dev, dev->channels[i].sram_channels); -- cx25821_sram_channel_setup(dev, dev->channels[i].sram_channels, -- 1440, 0); -- dev->channels[i].pixel_formats = PIXEL_FRMT_422; -- dev->channels[i].use_cif_resolution = FALSE; -+ cx25821_set_vip_mode(dev, dev->channels[i].sram_channels); -+ cx25821_sram_channel_setup(dev, dev->channels[i].sram_channels, -+ 1440, 0); -+ dev->channels[i].pixel_formats = PIXEL_FRMT_422; -+ dev->channels[i].use_cif_resolution = FALSE; - } - - /* Probably only affect Downstream */ -- for (i = VID_UPSTREAM_SRAM_CHANNEL_I; i <= VID_UPSTREAM_SRAM_CHANNEL_J; -- i++) { -- cx25821_set_vip_mode(dev, dev->channels[i].sram_channels); -+ for (i = VID_UPSTREAM_SRAM_CHANNEL_I; -+ i <= VID_UPSTREAM_SRAM_CHANNEL_J; i++) { -+ cx25821_set_vip_mode(dev, dev->channels[i].sram_channels); - } - -- cx25821_sram_channel_setup_audio(dev, -- dev->channels[SRAM_CH08].sram_channels, -- 128, 0); -+ cx25821_sram_channel_setup_audio(dev, -+ dev->channels[SRAM_CH08].sram_channels, -+ 128, 0); - - cx25821_gpio_init(dev); - } -@@ -931,8 +931,8 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) - - /* Apply a sensible clock frequency for the PCIe bridge */ - dev->clk_freq = 28000000; -- for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) -- dev->channels[i].sram_channels = &cx25821_sram_channels[i]; -+ for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) -+ dev->channels[i].sram_channels = &cx25821_sram_channels[i]; - - if (dev->nr > 1) - CX25821_INFO("dev->nr > 1!"); -@@ -1003,11 +1003,11 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) - - cx25821_card_setup(dev); - -- if (medusa_video_init(dev) < 0) -- CX25821_ERR("%s() Failed to initialize medusa!\n" -- , __func__); -+ if (medusa_video_init(dev) < 0) -+ CX25821_ERR("%s() Failed to initialize medusa!\n" -+ , __func__); - -- cx25821_video_register(dev); -+ cx25821_video_register(dev); - - /* register IOCTL device */ - dev->ioctl_dev = -@@ -1342,12 +1342,12 @@ static irqreturn_t cx25821_irq(int irq, void *dev_id) - - for (i = 0; i < VID_CHANNEL_NUM; i++) { - if (pci_status & mask[i]) { -- vid_status = cx_read(dev->channels[i]. -- sram_channels->int_stat); -+ vid_status = cx_read(dev->channels[i]. -+ sram_channels->int_stat); - - if (vid_status) - handled += -- cx25821_video_irq(dev, i, vid_status); -+ cx25821_video_irq(dev, i, vid_status); - - cx_write(PCI_INT_STAT, mask[i]); - } -diff --git a/drivers/staging/cx25821/cx25821-i2c.c b/drivers/staging/cx25821/cx25821-i2c.c -index e43572e..2b14bcc 100644 ---- a/drivers/staging/cx25821/cx25821-i2c.c -+++ b/drivers/staging/cx25821/cx25821-i2c.c -@@ -283,7 +283,7 @@ static struct i2c_algorithm cx25821_i2c_algo_template = { - .master_xfer = i2c_xfer, - .functionality = cx25821_functionality, - #ifdef NEED_ALGO_CONTROL -- .algo_control = dummy_algo_control, -+ .algo_control = dummy_algo_control, - #endif - }; - -diff --git a/drivers/staging/cx25821/cx25821-medusa-reg.h b/drivers/staging/cx25821/cx25821-medusa-reg.h -index f7f33b3..1c1c228 100644 ---- a/drivers/staging/cx25821/cx25821-medusa-reg.h -+++ b/drivers/staging/cx25821/cx25821-medusa-reg.h -@@ -443,13 +443,13 @@ - /*****************************************************************************/ - /* LUMA_CTRL register fields */ - #define VDEC_A_BRITE_CTRL 0x1014 --#define VDEC_A_CNTRST_CTRL 0x1015 --#define VDEC_A_PEAK_SEL 0x1016 -+#define VDEC_A_CNTRST_CTRL 0x1015 -+#define VDEC_A_PEAK_SEL 0x1016 - - /*****************************************************************************/ - /* CHROMA_CTRL register fields */ --#define VDEC_A_USAT_CTRL 0x1018 --#define VDEC_A_VSAT_CTRL 0x1019 --#define VDEC_A_HUE_CTRL 0x101A -+#define VDEC_A_USAT_CTRL 0x1018 -+#define VDEC_A_VSAT_CTRL 0x1019 -+#define VDEC_A_HUE_CTRL 0x101A - - #endif -diff --git a/drivers/staging/cx25821/cx25821-medusa-video.c b/drivers/staging/cx25821/cx25821-medusa-video.c -index ef9f2b8..1e11e0c 100644 ---- a/drivers/staging/cx25821/cx25821-medusa-video.c -+++ b/drivers/staging/cx25821/cx25821-medusa-video.c -@@ -778,9 +778,9 @@ int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) - - int medusa_video_init(struct cx25821_dev *dev) - { -- u32 value = 0, tmp = 0; -- int ret_val = 0; -- int i = 0; -+ u32 value = 0, tmp = 0; -+ int ret_val = 0; -+ int i = 0; - - mutex_lock(&dev->lock); - -@@ -829,7 +829,7 @@ int medusa_video_init(struct cx25821_dev *dev) - /* select AFE clock to output mode */ - value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); - value &= 0x83FFFFFF; -- ret_val = -+ ret_val = - cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, - value | 0x10000000); - -diff --git a/drivers/staging/cx25821/cx25821-reg.h b/drivers/staging/cx25821/cx25821-reg.h -index cfe0f32..a3fc25a 100644 ---- a/drivers/staging/cx25821/cx25821-reg.h -+++ b/drivers/staging/cx25821/cx25821-reg.h -@@ -163,8 +163,8 @@ - #define FLD_VID_DST_RISC2 0x00000010 - #define FLD_VID_SRC_RISC1 0x00000002 - #define FLD_VID_DST_RISC1 0x00000001 --#define FLD_VID_SRC_ERRORS FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF --#define FLD_VID_DST_ERRORS FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF -+#define FLD_VID_SRC_ERRORS (FLD_VID_SRC_OPC_ERR | FLD_VID_SRC_SYNC | FLD_VID_SRC_UF) -+#define FLD_VID_DST_ERRORS (FLD_VID_DST_OPC_ERR | FLD_VID_DST_SYNC | FLD_VID_DST_OF) - - /* ***************************************************************************** */ - #define AUD_A_INT_MSK 0x0400C0 /* Audio Int interrupt mask */ -diff --git a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c -index d12dbb5..405e2db 100644 ---- a/drivers/staging/cx25821/cx25821-video-upstream-ch2.c -+++ b/drivers/staging/cx25821/cx25821-video-upstream-ch2.c -@@ -32,17 +32,17 @@ - #include - #include - #include --#include -+#include - - MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); - MODULE_AUTHOR("Hiep Huynh "); - MODULE_LICENSE("GPL"); - - static int _intr_msk = -- FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; -+ FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; - - static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev, -- __le32 * rp, unsigned int offset, -+ __le32 *rp, unsigned int offset, - unsigned int bpl, u32 sync_line, - unsigned int lines, - int fifo_enable, int field_type) -@@ -53,9 +53,8 @@ static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev, - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); - - if (USE_RISC_NOOP_VIDEO) { -- for (i = 0; i < NUM_NO_OPS; i++) { -+ for (i = 0; i < NUM_NO_OPS; i++) - *(rp++) = cpu_to_le32(RISC_NOOP); -- } - } - - /* scan lines */ -@@ -75,7 +74,7 @@ static __le32 *cx25821_update_riscprogram_ch2(struct cx25821_dev *dev, - } - - static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev, -- __le32 * rp, -+ __le32 *rp, - dma_addr_t databuf_phys_addr, - unsigned int offset, - u32 sync_line, unsigned int bpl, -@@ -88,14 +87,12 @@ static __le32 *cx25821_risc_field_upstream_ch2(struct cx25821_dev *dev, - int dist_betwn_starts = bpl * 2; - - /* sync instruction */ -- if (sync_line != NO_SYNC_LINE) { -+ if (sync_line != NO_SYNC_LINE) - *(rp++) = cpu_to_le32(RISC_RESYNC | sync_line); -- } - - if (USE_RISC_NOOP_VIDEO) { -- for (i = 0; i < NUM_NO_OPS; i++) { -+ for (i = 0; i < NUM_NO_OPS; i++) - *(rp++) = cpu_to_le32(RISC_NOOP); -- } - } - - /* scan lines */ -@@ -133,7 +130,7 @@ int cx25821_risc_buffer_upstream_ch2(struct cx25821_dev *dev, - { - __le32 *rp; - int fifo_enable = 0; -- int singlefield_lines = lines >> 1; /*get line count for single field */ -+ int singlefield_lines = lines >> 1; /*get line count for single field */ - int odd_num_lines = singlefield_lines; - int frame = 0; - int frame_size = 0; -@@ -218,15 +215,15 @@ void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) - ("cx25821: No video file is currently running so return!\n"); - return; - } -- /* Disable RISC interrupts */ -+ /* Disable RISC interrupts */ - tmp = cx_read(sram_ch->int_msk); - cx_write(sram_ch->int_msk, tmp & ~_intr_msk); - -- /* Turn OFF risc and fifo */ -+ /* Turn OFF risc and fifo */ - tmp = cx_read(sram_ch->dma_ctl); - cx_write(sram_ch->dma_ctl, tmp & ~(FLD_VID_FIFO_EN | FLD_VID_RISC_EN)); - -- /* Clear data buffer memory */ -+ /* Clear data buffer memory */ - if (dev->_data_buf_virt_addr_ch2) - memset(dev->_data_buf_virt_addr_ch2, 0, - dev->_data_buf_size_ch2); -@@ -250,9 +247,8 @@ void cx25821_stop_upstream_video_ch2(struct cx25821_dev *dev) - - void cx25821_free_mem_upstream_ch2(struct cx25821_dev *dev) - { -- if (dev->_is_running_ch2) { -+ if (dev->_is_running_ch2) - cx25821_stop_upstream_video_ch2(dev); -- } - - if (dev->_dma_virt_addr_ch2) { - pci_free_consistent(dev->pci, dev->_risc_size_ch2, -@@ -303,11 +299,10 @@ int cx25821_get_frame_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) - file_offset = dev->_frame_count_ch2 * frame_size; - - myfile = filp_open(dev->_filename_ch2, O_RDONLY | O_LARGEFILE, 0); -- - if (IS_ERR(myfile)) { - const int open_errno = -PTR_ERR(myfile); -- printk("%s(): ERROR opening file(%s) with errno = %d! \n", -- __func__, dev->_filename_ch2, open_errno); -+ printk("%s(): ERROR opening file(%s) with errno = %d!\n", -+ __func__, dev->_filename_ch2, open_errno); - return PTR_ERR(myfile); - } else { - if (!(myfile->f_op)) { -@@ -371,8 +366,8 @@ static void cx25821_vidups_handler_ch2(struct work_struct *work) - container_of(work, struct cx25821_dev, _irq_work_entry_ch2); - - if (!dev) { -- printk("ERROR %s(): since container_of(work_struct) FAILED! \n", -- __func__); -+ printk("ERROR %s(): since container_of(work_struct) FAILED!\n", -+ __func__); - return; - } - -@@ -398,8 +393,8 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) - - if (IS_ERR(myfile)) { - const int open_errno = -PTR_ERR(myfile); -- printk("%s(): ERROR opening file(%s) with errno = %d! \n", -- __func__, dev->_filename_ch2, open_errno); -+ printk("%s(): ERROR opening file(%s) with errno = %d!\n", -+ __func__, dev->_filename_ch2, open_errno); - return PTR_ERR(myfile); - } else { - if (!(myfile->f_op)) { -@@ -450,9 +445,8 @@ int cx25821_openfile_ch2(struct cx25821_dev *dev, struct sram_channel *sram_ch) - if (i > 0) - dev->_frame_count_ch2++; - -- if (vfs_read_retval < line_size) { -+ if (vfs_read_retval < line_size) - break; -- } - } - - dev->_file_status_ch2 = -@@ -494,7 +488,7 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, - return -ENOMEM; - } - -- /* Iniitize at this address until n bytes to 0 */ -+ /* Iniitize at this address until n bytes to 0 */ - memset(dev->_dma_virt_addr_ch2, 0, dev->_risc_size_ch2); - - if (dev->_data_buf_virt_addr_ch2 != NULL) { -@@ -502,7 +496,7 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, - dev->_data_buf_virt_addr_ch2, - dev->_data_buf_phys_addr_ch2); - } -- /* For Video Data buffer allocation */ -+ /* For Video Data buffer allocation */ - dev->_data_buf_virt_addr_ch2 = - pci_alloc_consistent(dev->pci, dev->upstream_databuf_size_ch2, - &data_dma_addr); -@@ -515,26 +509,26 @@ static int cx25821_upstream_buffer_prepare_ch2(struct cx25821_dev *dev, - return -ENOMEM; - } - -- /* Initialize at this address until n bytes to 0 */ -+ /* Initialize at this address until n bytes to 0 */ - memset(dev->_data_buf_virt_addr_ch2, 0, dev->_data_buf_size_ch2); - - ret = cx25821_openfile_ch2(dev, sram_ch); - if (ret < 0) - return ret; - -- /* Creating RISC programs */ -+ /* Creating RISC programs */ - ret = - cx25821_risc_buffer_upstream_ch2(dev, dev->pci, 0, bpl, - dev->_lines_count_ch2); - if (ret < 0) { - printk(KERN_INFO -- "cx25821: Failed creating Video Upstream Risc programs! \n"); -+ "cx25821: Failed creating Video Upstream Risc programs!\n"); - goto error; - } - - return 0; - -- error: -+ error: - return ret; - } - -@@ -542,7 +536,7 @@ int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, - u32 status) - { - u32 int_msk_tmp; -- struct sram_channel *channel = dev->channels[chan_num].sram_channels; -+ struct sram_channel *channel = dev->channels[chan_num].sram_channels; - int singlefield_lines = NTSC_FIELD_HEIGHT; - int line_size_in_bytes = Y422_LINE_SZ; - int odd_risc_prog_size = 0; -@@ -550,13 +544,13 @@ int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, - __le32 *rp; - - if (status & FLD_VID_SRC_RISC1) { -- /* We should only process one program per call */ -+ /* We should only process one program per call */ - u32 prog_cnt = cx_read(channel->gpcnt); - -- /* -- Since we've identified our IRQ, clear our bits from the -- interrupt mask and interrupt status registers -- */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "nuvoton-cir.h" ++ ++static char *chip_id = "w836x7hg"; ++ ++/* write val to config reg */ ++static inline void nvt_cr_write(struct nvt_dev *nvt, u8 val, u8 reg) ++{ ++ outb(reg, nvt->cr_efir); ++ outb(val, nvt->cr_efdr); ++} ++ ++/* read val from config reg */ ++static inline u8 nvt_cr_read(struct nvt_dev *nvt, u8 reg) ++{ ++ outb(reg, nvt->cr_efir); ++ return inb(nvt->cr_efdr); ++} ++ ++/* update config register bit without changing other bits */ ++static inline void nvt_set_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg) ++{ ++ u8 tmp = nvt_cr_read(nvt, reg) | val; ++ nvt_cr_write(nvt, tmp, reg); ++} ++ ++/* clear config register bit without changing other bits */ ++static inline void nvt_clear_reg_bit(struct nvt_dev *nvt, u8 val, u8 reg) ++{ ++ u8 tmp = nvt_cr_read(nvt, reg) & ~val; ++ nvt_cr_write(nvt, tmp, reg); ++} ++ ++/* enter extended function mode */ ++static inline void nvt_efm_enable(struct nvt_dev *nvt) ++{ ++ /* Enabling Extended Function Mode explicitly requires writing 2x */ ++ outb(EFER_EFM_ENABLE, nvt->cr_efir); ++ outb(EFER_EFM_ENABLE, nvt->cr_efir); ++} ++ ++/* exit extended function mode */ ++static inline void nvt_efm_disable(struct nvt_dev *nvt) ++{ ++ outb(EFER_EFM_DISABLE, nvt->cr_efir); ++} ++ ++/* ++ * When you want to address a specific logical device, write its logical ++ * device number to CR_LOGICAL_DEV_SEL, then enable/disable by writing ++ * 0x1/0x0 respectively to CR_LOGICAL_DEV_EN. ++ */ ++static inline void nvt_select_logical_dev(struct nvt_dev *nvt, u8 ldev) ++{ ++ outb(CR_LOGICAL_DEV_SEL, nvt->cr_efir); ++ outb(ldev, nvt->cr_efdr); ++} ++ ++/* write val to cir config register */ ++static inline void nvt_cir_reg_write(struct nvt_dev *nvt, u8 val, u8 offset) ++{ ++ outb(val, nvt->cir_addr + offset); ++} ++ ++/* read val from cir config register */ ++static u8 nvt_cir_reg_read(struct nvt_dev *nvt, u8 offset) ++{ ++ u8 val; ++ ++ val = inb(nvt->cir_addr + offset); ++ ++ return val; ++} ++ ++/* write val to cir wake register */ ++static inline void nvt_cir_wake_reg_write(struct nvt_dev *nvt, ++ u8 val, u8 offset) ++{ ++ outb(val, nvt->cir_wake_addr + offset); ++} ++ ++/* read val from cir wake config register */ ++static u8 nvt_cir_wake_reg_read(struct nvt_dev *nvt, u8 offset) ++{ ++ u8 val; ++ ++ val = inb(nvt->cir_wake_addr + offset); ++ ++ return val; ++} ++ ++/* dump current cir register contents */ ++static void cir_dump_regs(struct nvt_dev *nvt) ++{ ++ nvt_efm_enable(nvt); ++ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); ++ ++ printk("%s: Dump CIR logical device registers:\n", NVT_DRIVER_NAME); ++ printk(" * CR CIR ACTIVE : 0x%x\n", ++ nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); ++ printk(" * CR CIR BASE ADDR: 0x%x\n", ++ (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | ++ nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO)); ++ printk(" * CR CIR IRQ NUM: 0x%x\n", ++ nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); ++ ++ nvt_efm_disable(nvt); ++ ++ printk("%s: Dump CIR registers:\n", NVT_DRIVER_NAME); ++ printk(" * IRCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRCON)); ++ printk(" * IRSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRSTS)); ++ printk(" * IREN: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IREN)); ++ printk(" * RXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_RXFCONT)); ++ printk(" * CP: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CP)); ++ printk(" * CC: 0x%x\n", nvt_cir_reg_read(nvt, CIR_CC)); ++ printk(" * SLCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCH)); ++ printk(" * SLCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SLCL)); ++ printk(" * FIFOCON: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FIFOCON)); ++ printk(" * IRFIFOSTS: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFIFOSTS)); ++ printk(" * SRXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_SRXFIFO)); ++ printk(" * TXFCONT: 0x%x\n", nvt_cir_reg_read(nvt, CIR_TXFCONT)); ++ printk(" * STXFIFO: 0x%x\n", nvt_cir_reg_read(nvt, CIR_STXFIFO)); ++ printk(" * FCCH: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCH)); ++ printk(" * FCCL: 0x%x\n", nvt_cir_reg_read(nvt, CIR_FCCL)); ++ printk(" * IRFSM: 0x%x\n", nvt_cir_reg_read(nvt, CIR_IRFSM)); ++} ++ ++/* dump current cir wake register contents */ ++static void cir_wake_dump_regs(struct nvt_dev *nvt) ++{ ++ u8 i, fifo_len; ++ ++ nvt_efm_enable(nvt); ++ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); ++ ++ printk("%s: Dump CIR WAKE logical device registers:\n", ++ NVT_DRIVER_NAME); ++ printk(" * CR CIR WAKE ACTIVE : 0x%x\n", ++ nvt_cr_read(nvt, CR_LOGICAL_DEV_EN)); ++ printk(" * CR CIR WAKE BASE ADDR: 0x%x\n", ++ (nvt_cr_read(nvt, CR_CIR_BASE_ADDR_HI) << 8) | ++ nvt_cr_read(nvt, CR_CIR_BASE_ADDR_LO)); ++ printk(" * CR CIR WAKE IRQ NUM: 0x%x\n", ++ nvt_cr_read(nvt, CR_CIR_IRQ_RSRC)); ++ ++ nvt_efm_disable(nvt); ++ ++ printk("%s: Dump CIR WAKE registers\n", NVT_DRIVER_NAME); ++ printk(" * IRCON: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRCON)); ++ printk(" * IRSTS: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS)); ++ printk(" * IREN: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN)); ++ printk(" * FIFO CMP DEEP: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_DEEP)); ++ printk(" * FIFO CMP TOL: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_CMP_TOL)); ++ printk(" * FIFO COUNT: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT)); ++ printk(" * SLCH: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCH)); ++ printk(" * SLCL: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_SLCL)); ++ printk(" * FIFOCON: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON)); ++ printk(" * SRXFSTS: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_SRXFSTS)); ++ printk(" * SAMPLE RX FIFO: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_SAMPLE_RX_FIFO)); ++ printk(" * WR FIFO DATA: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_WR_FIFO_DATA)); ++ printk(" * RD FIFO ONLY: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); ++ printk(" * RD FIFO ONLY IDX: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)); ++ printk(" * FIFO IGNORE: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_IGNORE)); ++ printk(" * IRFSM: 0x%x\n", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRFSM)); ++ ++ fifo_len = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFO_COUNT); ++ printk("%s: Dump CIR WAKE FIFO (len %d)\n", NVT_DRIVER_NAME, fifo_len); ++ printk("* Contents = "); ++ for (i = 0; i < fifo_len; i++) ++ printk("%02x ", ++ nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY)); ++ printk("\n"); ++} ++ ++/* detect hardware features */ ++static int nvt_hw_detect(struct nvt_dev *nvt) ++{ ++ unsigned long flags; ++ u8 chip_major, chip_minor; ++ int ret = 0; ++ ++ nvt_efm_enable(nvt); ++ ++ /* Check if we're wired for the alternate EFER setup */ ++ chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); ++ if (chip_major == 0xff) { ++ nvt->cr_efir = CR_EFIR2; ++ nvt->cr_efdr = CR_EFDR2; ++ nvt_efm_enable(nvt); ++ chip_major = nvt_cr_read(nvt, CR_CHIP_ID_HI); ++ } ++ ++ chip_minor = nvt_cr_read(nvt, CR_CHIP_ID_LO); ++ nvt_dbg("%s: chip id: 0x%02x 0x%02x", chip_id, chip_major, chip_minor); ++ ++ if (chip_major != CHIP_ID_HIGH && ++ (chip_minor != CHIP_ID_LOW || chip_minor != CHIP_ID_LOW2)) ++ ret = -ENODEV; ++ ++ nvt_efm_disable(nvt); ++ ++ spin_lock_irqsave(&nvt->nvt_lock, flags); ++ nvt->chip_major = chip_major; ++ nvt->chip_minor = chip_minor; ++ spin_unlock_irqrestore(&nvt->nvt_lock, flags); ++ ++ return ret; ++} ++ ++static void nvt_cir_ldev_init(struct nvt_dev *nvt) ++{ ++ u8 val; ++ ++ /* output pin selection (Pin95=CIRRX, Pin96=CIRTX1, WB enabled */ ++ val = nvt_cr_read(nvt, CR_OUTPUT_PIN_SEL); ++ val &= OUTPUT_PIN_SEL_MASK; ++ val |= (OUTPUT_ENABLE_CIR | OUTPUT_ENABLE_CIRWB); ++ nvt_cr_write(nvt, val, CR_OUTPUT_PIN_SEL); ++ ++ /* Select CIR logical device and enable */ ++ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); ++ nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); ++ ++ nvt_cr_write(nvt, nvt->cir_addr >> 8, CR_CIR_BASE_ADDR_HI); ++ nvt_cr_write(nvt, nvt->cir_addr & 0xff, CR_CIR_BASE_ADDR_LO); ++ ++ nvt_cr_write(nvt, nvt->cir_irq, CR_CIR_IRQ_RSRC); ++ ++ nvt_dbg("CIR initialized, base io port address: 0x%lx, irq: %d", ++ nvt->cir_addr, nvt->cir_irq); ++} ++ ++static void nvt_cir_wake_ldev_init(struct nvt_dev *nvt) ++{ ++ /* Select ACPI logical device, enable it and CIR Wake */ ++ nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); ++ nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); ++ ++ /* Enable CIR Wake via PSOUT# (Pin60) */ ++ nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE); ++ ++ /* enable cir interrupt of mouse/keyboard IRQ event */ ++ nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS); ++ ++ /* enable pme interrupt of cir wakeup event */ ++ nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2); ++ ++ /* Select CIR Wake logical device and enable */ ++ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); ++ nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); ++ ++ nvt_cr_write(nvt, nvt->cir_wake_addr >> 8, CR_CIR_BASE_ADDR_HI); ++ nvt_cr_write(nvt, nvt->cir_wake_addr & 0xff, CR_CIR_BASE_ADDR_LO); ++ ++ nvt_cr_write(nvt, nvt->cir_wake_irq, CR_CIR_IRQ_RSRC); ++ ++ nvt_dbg("CIR Wake initialized, base io port address: 0x%lx, irq: %d", ++ nvt->cir_wake_addr, nvt->cir_wake_irq); ++} ++ ++/* clear out the hardware's cir rx fifo */ ++static void nvt_clear_cir_fifo(struct nvt_dev *nvt) ++{ ++ u8 val; ++ ++ val = nvt_cir_reg_read(nvt, CIR_FIFOCON); ++ nvt_cir_reg_write(nvt, val | CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON); ++} ++ ++/* clear out the hardware's cir wake rx fifo */ ++static void nvt_clear_cir_wake_fifo(struct nvt_dev *nvt) ++{ ++ u8 val; ++ ++ val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_FIFOCON); ++ nvt_cir_wake_reg_write(nvt, val | CIR_WAKE_FIFOCON_RXFIFOCLR, ++ CIR_WAKE_FIFOCON); ++} ++ ++/* clear out the hardware's cir tx fifo */ ++static void nvt_clear_tx_fifo(struct nvt_dev *nvt) ++{ ++ u8 val; ++ ++ val = nvt_cir_reg_read(nvt, CIR_FIFOCON); ++ nvt_cir_reg_write(nvt, val | CIR_FIFOCON_TXFIFOCLR, CIR_FIFOCON); ++} ++ ++static void nvt_cir_regs_init(struct nvt_dev *nvt) ++{ ++ /* set sample limit count (PE interrupt raised when reached) */ ++ nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_SLCH); ++ nvt_cir_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_SLCL); ++ ++ /* set fifo irq trigger levels */ ++ nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV | ++ CIR_FIFOCON_RX_TRIGGER_LEV, CIR_FIFOCON); ++ ++ /* ++ * Enable TX and RX, specify carrier on = low, off = high, and set ++ * sample period (currently 50us) ++ */ ++ nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | CIR_IRCON_RXINV | ++ CIR_IRCON_SAMPLE_PERIOD_SEL, CIR_IRCON); ++ ++ /* clear hardware rx and tx fifos */ ++ nvt_clear_cir_fifo(nvt); ++ nvt_clear_tx_fifo(nvt); ++ ++ /* clear any and all stray interrupts */ ++ nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); ++ ++ /* and finally, enable RX Trigger Level Read and Packet End interrupts */ ++ nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); ++} ++ ++static void nvt_cir_wake_regs_init(struct nvt_dev *nvt) ++{ ++ /* set number of bytes needed for wake key comparison (default 67) */ ++ nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFO_LEN, CIR_WAKE_FIFO_CMP_DEEP); ++ ++ /* set tolerance/variance allowed per byte during wake compare */ ++ nvt_cir_wake_reg_write(nvt, CIR_WAKE_CMP_TOLERANCE, ++ CIR_WAKE_FIFO_CMP_TOL); ++ ++ /* set sample limit count (PE interrupt raised when reached) */ ++ nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT >> 8, CIR_WAKE_SLCH); ++ nvt_cir_wake_reg_write(nvt, CIR_RX_LIMIT_COUNT & 0xff, CIR_WAKE_SLCL); ++ ++ /* set cir wake fifo rx trigger level (currently 67) */ ++ nvt_cir_wake_reg_write(nvt, CIR_WAKE_FIFOCON_RX_TRIGGER_LEV, ++ CIR_WAKE_FIFOCON); ++ ++ /* ++ * Enable TX and RX, specific carrier on = low, off = high, and set ++ * sample period (currently 50us) ++ */ ++ nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | ++ CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | ++ CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, ++ CIR_WAKE_IRCON); ++ ++ /* clear cir wake rx fifo */ ++ nvt_clear_cir_wake_fifo(nvt); ++ ++ /* clear any and all stray interrupts */ ++ nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); ++} ++ ++static void nvt_enable_wake(struct nvt_dev *nvt) ++{ ++ nvt_efm_enable(nvt); ++ ++ nvt_select_logical_dev(nvt, LOGICAL_DEV_ACPI); ++ nvt_set_reg_bit(nvt, CIR_WAKE_ENABLE_BIT, CR_ACPI_CIR_WAKE); ++ nvt_set_reg_bit(nvt, CIR_INTR_MOUSE_IRQ_BIT, CR_ACPI_IRQ_EVENTS); ++ nvt_set_reg_bit(nvt, PME_INTR_CIR_PASS_BIT, CR_ACPI_IRQ_EVENTS2); ++ ++ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR_WAKE); ++ nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); ++ ++ nvt_efm_disable(nvt); ++ ++ nvt_cir_wake_reg_write(nvt, CIR_WAKE_IRCON_MODE0 | CIR_WAKE_IRCON_RXEN | ++ CIR_WAKE_IRCON_R | CIR_WAKE_IRCON_RXINV | ++ CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL, CIR_WAKE_IRCON); ++ nvt_cir_wake_reg_write(nvt, 0xff, CIR_WAKE_IRSTS); ++ nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); ++} ++ ++/* rx carrier detect only works in learning mode, must be called w/nvt_lock */ ++static u32 nvt_rx_carrier_detect(struct nvt_dev *nvt) ++{ ++ u32 count, carrier, duration = 0; ++ int i; ++ ++ count = nvt_cir_reg_read(nvt, CIR_FCCL) | ++ nvt_cir_reg_read(nvt, CIR_FCCH) << 8; ++ ++ for (i = 0; i < nvt->pkts; i++) { ++ if (nvt->buf[i] & BUF_PULSE_BIT) ++ duration += nvt->buf[i] & BUF_LEN_MASK; ++ } ++ ++ duration *= SAMPLE_PERIOD; ++ ++ if (!count || !duration) { ++ nvt_pr(KERN_NOTICE, "Unable to determine carrier! (c:%u, d:%u)", ++ count, duration); ++ return 0; ++ } ++ ++ carrier = (count * 1000000) / duration; ++ ++ if ((carrier > MAX_CARRIER) || (carrier < MIN_CARRIER)) ++ nvt_dbg("WTF? Carrier frequency out of range!"); ++ ++ nvt_dbg("Carrier frequency: %u (count %u, duration %u)", ++ carrier, count, duration); ++ ++ return carrier; ++} ++ ++/* ++ * set carrier frequency ++ * ++ * set carrier on 2 registers: CP & CC ++ * always set CP as 0x81 ++ * set CC by SPEC, CC = 3MHz/carrier - 1 ++ */ ++static int nvt_set_tx_carrier(void *data, u32 carrier) ++{ ++ struct nvt_dev *nvt = data; ++ u16 val; ++ ++ nvt_cir_reg_write(nvt, 1, CIR_CP); ++ val = 3000000 / (carrier) - 1; ++ nvt_cir_reg_write(nvt, val & 0xff, CIR_CC); ++ ++ nvt_dbg("cp: 0x%x cc: 0x%x\n", ++ nvt_cir_reg_read(nvt, CIR_CP), nvt_cir_reg_read(nvt, CIR_CC)); ++ ++ return 0; ++} ++ ++/* ++ * nvt_tx_ir ++ * ++ * 1) clean TX fifo first (handled by AP) ++ * 2) copy data from user space ++ * 3) disable RX interrupts, enable TX interrupts: TTR & TFU ++ * 4) send 9 packets to TX FIFO to open TTR ++ * in interrupt_handler: ++ * 5) send all data out ++ * go back to write(): ++ * 6) disable TX interrupts, re-enable RX interupts ++ * ++ * The key problem of this function is user space data may larger than ++ * driver's data buf length. So nvt_tx_ir() will only copy TX_BUF_LEN data to ++ * buf, and keep current copied data buf num in cur_buf_num. But driver's buf ++ * number may larger than TXFCONT (0xff). So in interrupt_handler, it has to ++ * set TXFCONT as 0xff, until buf_count less than 0xff. ++ */ ++static int nvt_tx_ir(void *priv, int *txbuf, u32 n) ++{ ++ struct nvt_dev *nvt = priv; ++ unsigned long flags; ++ size_t cur_count; ++ unsigned int i; ++ u8 iren; ++ int ret; ++ ++ spin_lock_irqsave(&nvt->tx.lock, flags); ++ ++ if (n >= TX_BUF_LEN) { ++ nvt->tx.buf_count = cur_count = TX_BUF_LEN; ++ ret = TX_BUF_LEN; ++ } else { ++ nvt->tx.buf_count = cur_count = n; ++ ret = n; ++ } ++ ++ memcpy(nvt->tx.buf, txbuf, nvt->tx.buf_count); ++ ++ nvt->tx.cur_buf_num = 0; ++ ++ /* save currently enabled interrupts */ ++ iren = nvt_cir_reg_read(nvt, CIR_IREN); ++ ++ /* now disable all interrupts, save TFU & TTR */ ++ nvt_cir_reg_write(nvt, CIR_IREN_TFU | CIR_IREN_TTR, CIR_IREN); ++ ++ nvt->tx.tx_state = ST_TX_REPLY; ++ ++ nvt_cir_reg_write(nvt, CIR_FIFOCON_TX_TRIGGER_LEV_8 | ++ CIR_FIFOCON_RXFIFOCLR, CIR_FIFOCON); ++ ++ /* trigger TTR interrupt by writing out ones, (yes, it's ugly) */ ++ for (i = 0; i < 9; i++) ++ nvt_cir_reg_write(nvt, 0x01, CIR_STXFIFO); ++ ++ spin_unlock_irqrestore(&nvt->tx.lock, flags); ++ ++ wait_event(nvt->tx.queue, nvt->tx.tx_state == ST_TX_REQUEST); ++ ++ spin_lock_irqsave(&nvt->tx.lock, flags); ++ nvt->tx.tx_state = ST_TX_NONE; ++ spin_unlock_irqrestore(&nvt->tx.lock, flags); ++ ++ /* restore enabled interrupts to prior state */ ++ nvt_cir_reg_write(nvt, iren, CIR_IREN); ++ ++ return ret; ++} ++ ++/* dump contents of the last rx buffer we got from the hw rx fifo */ ++static void nvt_dump_rx_buf(struct nvt_dev *nvt) ++{ ++ int i; ++ ++ printk("%s (len %d): ", __func__, nvt->pkts); ++ for (i = 0; (i < nvt->pkts) && (i < RX_BUF_LEN); i++) ++ printk("0x%02x ", nvt->buf[i]); ++ printk("\n"); ++} ++ ++/* ++ * Process raw data in rx driver buffer, store it in raw IR event kfifo, ++ * trigger decode when appropriate. ++ * ++ * We get IR data samples one byte at a time. If the msb is set, its a pulse, ++ * otherwise its a space. The lower 7 bits are the count of SAMPLE_PERIOD ++ * (default 50us) intervals for that pulse/space. A discrete signal is ++ * followed by a series of 0x7f packets, then either 0x7 or 0x80 ++ * to signal more IR coming (repeats) or end of IR, respectively. We store ++ * sample data in the raw event kfifo until we see 0x7 (except f) ++ * or 0x80, at which time, we trigger a decode operation. ++ */ ++static void nvt_process_rx_ir_data(struct nvt_dev *nvt) ++{ ++ struct ir_raw_event rawir = { .pulse = false, .duration = 0 }; ++ unsigned int count; ++ u32 carrier; ++ u8 sample; ++ int i; ++ ++ nvt_dbg_verbose("%s firing", __func__); ++ ++ if (debug) ++ nvt_dump_rx_buf(nvt); ++ ++ if (nvt->carrier_detect_enabled) ++ carrier = nvt_rx_carrier_detect(nvt); ++ ++ count = nvt->pkts; ++ nvt_dbg_verbose("Processing buffer of len %d", count); ++ ++ for (i = 0; i < count; i++) { ++ nvt->pkts--; ++ sample = nvt->buf[i]; ++ ++ rawir.pulse = ((sample & BUF_PULSE_BIT) != 0); ++ rawir.duration = (sample & BUF_LEN_MASK) ++ * SAMPLE_PERIOD * 1000; ++ ++ if ((sample & BUF_LEN_MASK) == BUF_LEN_MASK) { ++ if (nvt->rawir.pulse == rawir.pulse) ++ nvt->rawir.duration += rawir.duration; ++ else { ++ nvt->rawir.duration = rawir.duration; ++ nvt->rawir.pulse = rawir.pulse; ++ } ++ continue; ++ } ++ ++ rawir.duration += nvt->rawir.duration; ++ nvt->rawir.duration = 0; ++ nvt->rawir.pulse = rawir.pulse; ++ ++ if (sample == BUF_PULSE_BIT) ++ rawir.pulse = false; ++ ++ if (rawir.duration) { ++ nvt_dbg("Storing %s with duration %d", ++ rawir.pulse ? "pulse" : "space", ++ rawir.duration); ++ ++ ir_raw_event_store(nvt->rdev, &rawir); ++ } ++ + /* -+ * Since we've identified our IRQ, clear our bits from the -+ * interrupt mask and interrupt status registers ++ * BUF_PULSE_BIT indicates end of IR data, BUF_REPEAT_BYTE ++ * indicates end of IR signal, but new data incoming. In both ++ * cases, it means we're ready to call ir_raw_event_handle + */ - int_msk_tmp = cx_read(channel->int_msk); - cx_write(channel->int_msk, int_msk_tmp & ~_intr_msk); - cx_write(channel->int_stat, _intr_msk); -@@ -612,7 +606,7 @@ int cx25821_video_upstream_irq_ch2(struct cx25821_dev *dev, int chan_num, - dev->_frame_count_ch2); - return -1; - } -- /* ElSE, set the interrupt mask register, re-enable irq. */ -+ /* ElSE, set the interrupt mask register, re-enable irq. */ - int_msk_tmp = cx_read(channel->int_msk); - cx_write(channel->int_msk, int_msk_tmp |= _intr_msk); - -@@ -631,24 +625,22 @@ static irqreturn_t cx25821_upstream_irq_ch2(int irq, void *dev_id) - return -1; - - channel_num = VID_UPSTREAM_SRAM_CHANNEL_J; -- -- sram_ch = dev->channels[channel_num].sram_channels; -+ sram_ch = dev->channels[channel_num].sram_channels; - - msk_stat = cx_read(sram_ch->int_mstat); - vid_status = cx_read(sram_ch->int_stat); - -- /* Only deal with our interrupt */ -+ /* Only deal with our interrupt */ - if (vid_status) { - handled = - cx25821_video_upstream_irq_ch2(dev, channel_num, - vid_status); - } - -- if (handled < 0) { -+ if (handled < 0) - cx25821_stop_upstream_video_ch2(dev); -- } else { -+ else - handled += handled; -- } - - return IRQ_RETVAL(handled); - } -@@ -667,22 +659,21 @@ static void cx25821_set_pixelengine_ch2(struct cx25821_dev *dev, - value |= dev->_isNTSC_ch2 ? 0 : 0x10; - cx_write(ch->vid_fmt_ctl, value); - -- /* -- set number of active pixels in each line. Default is 720 -- pixels in both NTSC and PAL format -- */ ++ if (sample == BUF_PULSE_BIT || ((sample != BUF_LEN_MASK) && ++ (sample & BUF_REPEAT_MASK) == BUF_REPEAT_BYTE)) ++ ir_raw_event_handle(nvt->rdev); ++ } ++ ++ if (nvt->pkts) { ++ nvt_dbg("Odd, pkts should be 0 now... (its %u)", nvt->pkts); ++ nvt->pkts = 0; ++ } ++ ++ nvt_dbg_verbose("%s done", __func__); ++} ++ ++/* copy data from hardware rx fifo into driver buffer */ ++static void nvt_get_rx_ir_data(struct nvt_dev *nvt) ++{ ++ unsigned long flags; ++ u8 fifocount, val; ++ unsigned int b_idx; ++ int i; ++ ++ /* Get count of how many bytes to read from RX FIFO */ ++ fifocount = nvt_cir_reg_read(nvt, CIR_RXFCONT); ++ /* if we get 0xff, probably means the logical dev is disabled */ ++ if (fifocount == 0xff) ++ return; ++ /* this would suggest a fifo overrun, not good... */ ++ else if (fifocount > RX_BUF_LEN) { ++ nvt_pr(KERN_WARNING, "fifocount %d over fifo len (%d)!", ++ fifocount, RX_BUF_LEN); ++ return; ++ } ++ ++ nvt_dbg("attempting to fetch %u bytes from hw rx fifo", fifocount); ++ ++ spin_lock_irqsave(&nvt->nvt_lock, flags); ++ ++ b_idx = nvt->pkts; ++ ++ /* This should never happen, but lets check anyway... */ ++ if (b_idx + fifocount > RX_BUF_LEN) { ++ nvt_process_rx_ir_data(nvt); ++ b_idx = 0; ++ } ++ ++ /* Read fifocount bytes from CIR Sample RX FIFO register */ ++ for (i = 0; i < fifocount; i++) { ++ val = nvt_cir_reg_read(nvt, CIR_SRXFIFO); ++ nvt->buf[b_idx + i] = val; ++ } ++ ++ nvt->pkts += fifocount; ++ nvt_dbg("%s: pkts now %d", __func__, nvt->pkts); ++ ++ nvt_process_rx_ir_data(nvt); ++ ++ spin_unlock_irqrestore(&nvt->nvt_lock, flags); ++} ++ ++static void nvt_cir_log_irqs(u8 status, u8 iren) ++{ ++ nvt_pr(KERN_INFO, "IRQ 0x%02x (IREN 0x%02x) :%s%s%s%s%s%s%s%s%s", ++ status, iren, ++ status & CIR_IRSTS_RDR ? " RDR" : "", ++ status & CIR_IRSTS_RTR ? " RTR" : "", ++ status & CIR_IRSTS_PE ? " PE" : "", ++ status & CIR_IRSTS_RFO ? " RFO" : "", ++ status & CIR_IRSTS_TE ? " TE" : "", ++ status & CIR_IRSTS_TTR ? " TTR" : "", ++ status & CIR_IRSTS_TFU ? " TFU" : "", ++ status & CIR_IRSTS_GH ? " GH" : "", ++ status & ~(CIR_IRSTS_RDR | CIR_IRSTS_RTR | CIR_IRSTS_PE | ++ CIR_IRSTS_RFO | CIR_IRSTS_TE | CIR_IRSTS_TTR | ++ CIR_IRSTS_TFU | CIR_IRSTS_GH) ? " ?" : ""); ++} ++ ++static bool nvt_cir_tx_inactive(struct nvt_dev *nvt) ++{ ++ unsigned long flags; ++ bool tx_inactive; ++ u8 tx_state; ++ ++ spin_lock_irqsave(&nvt->tx.lock, flags); ++ tx_state = nvt->tx.tx_state; ++ spin_unlock_irqrestore(&nvt->tx.lock, flags); ++ ++ tx_inactive = (tx_state == ST_TX_NONE); ++ ++ return tx_inactive; ++} ++ ++/* interrupt service routine for incoming and outgoing CIR data */ ++static irqreturn_t nvt_cir_isr(int irq, void *data) ++{ ++ struct nvt_dev *nvt = data; ++ u8 status, iren, cur_state; ++ unsigned long flags; ++ ++ nvt_dbg_verbose("%s firing", __func__); ++ ++ nvt_efm_enable(nvt); ++ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); ++ nvt_efm_disable(nvt); ++ + /* -+ * set number of active pixels in each line. Default is 720 -+ * pixels in both NTSC and PAL format ++ * Get IR Status register contents. Write 1 to ack/clear ++ * ++ * bit: reg name - description ++ * 7: CIR_IRSTS_RDR - RX Data Ready ++ * 6: CIR_IRSTS_RTR - RX FIFO Trigger Level Reach ++ * 5: CIR_IRSTS_PE - Packet End ++ * 4: CIR_IRSTS_RFO - RX FIFO Overrun (RDR will also be set) ++ * 3: CIR_IRSTS_TE - TX FIFO Empty ++ * 2: CIR_IRSTS_TTR - TX FIFO Trigger Level Reach ++ * 1: CIR_IRSTS_TFU - TX FIFO Underrun ++ * 0: CIR_IRSTS_GH - Min Length Detected + */ - cx_write(ch->vid_active_ctl1, width); - - num_lines = (height / 2) & 0x3FF; - odd_num_lines = num_lines; - -- if (dev->_isNTSC_ch2) { -+ if (dev->_isNTSC_ch2) - odd_num_lines += 1; -- } - - value = (num_lines << 16) | odd_num_lines; - -- /* set number of active lines in field 0 (top) and field 1 (bottom) */ -+ /* set number of active lines in field 0 (top) and field 1 (bottom) */ - cx_write(ch->vid_active_ctl2, value); - - cx_write(ch->vid_cdt_size, VID_CDT_SIZE >> 3); -@@ -694,27 +685,27 @@ int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, - u32 tmp = 0; - int err = 0; - -- /* -- 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface -- for channel A-C -- */ -+ /* -+ * 656/VIP SRC Upstream Channel I & J and 7 - Host Bus Interface -+ * for channel A-C -+ */ - tmp = cx_read(VID_CH_MODE_SEL); - cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); - -- /* -- Set the physical start address of the RISC program in the initial -- program counter(IPC) member of the cmds. -- */ -+ /* -+ * Set the physical start address of the RISC program in the initial -+ * program counter(IPC) member of the cmds. -+ */ - cx_write(sram_ch->cmds_start + 0, dev->_dma_phys_addr_ch2); -- cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ -+ cx_write(sram_ch->cmds_start + 4, 0); /* Risc IPC High 64 bits 63-32 */ - - /* reset counter */ - cx_write(sram_ch->gpcnt_ctl, 3); - -- /* Clear our bits from the interrupt status register. */ -+ /* Clear our bits from the interrupt status register. */ - cx_write(sram_ch->int_stat, _intr_msk); - -- /* Set the interrupt mask register, enable irq. */ -+ /* Set the interrupt mask register, enable irq. */ - cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << sram_ch->irq_bit)); - tmp = cx_read(sram_ch->int_msk); - cx_write(sram_ch->int_msk, tmp |= _intr_msk); -@@ -727,7 +718,7 @@ int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, - dev->pci->irq); - goto fail_irq; - } -- /* Start the DMA engine */ -+ /* Start the DMA engine */ - tmp = cx_read(sram_ch->dma_ctl); - cx_set(sram_ch->dma_ctl, tmp | FLD_VID_RISC_EN); - -@@ -736,7 +727,7 @@ int cx25821_start_video_dma_upstream_ch2(struct cx25821_dev *dev, - - return 0; - -- fail_irq: -+ fail_irq: - cx25821_dev_unregister(dev); - return err; - } -@@ -758,7 +749,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, - } - - dev->_channel2_upstream_select = channel_select; -- sram_ch = dev->channels[channel_select].sram_channels; -+ sram_ch = dev->channels[channel_select].sram_channels; - - INIT_WORK(&dev->_irq_work_entry_ch2, cx25821_vidups_handler_ch2); - dev->_irq_queues_ch2 = -@@ -769,10 +760,10 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, - ("cx25821: create_singlethread_workqueue() for Video FAILED!\n"); - return -ENOMEM; - } -- /* -- 656/VIP SRC Upstream Channel I & J and 7 - -- Host Bus Interface for channel A-C -- */ -+ /* -+ * 656/VIP SRC Upstream Channel I & J and 7 - -+ * Host Bus Interface for channel A-C -+ */ - tmp = cx_read(VID_CH_MODE_SEL); - cx_write(VID_CH_MODE_SEL, tmp | 0x1B0001FF); - -@@ -808,7 +799,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, - str_length + 1); - } - -- /* Default if filename is empty string */ -+ /* Default if filename is empty string */ - if (strcmp(dev->input_filename_ch2, "") == 0) { - if (dev->_isNTSC_ch2) { - dev->_filename_ch2 = -@@ -833,7 +824,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, - dev->upstream_riscbuf_size_ch2 = risc_buffer_size * 2; - dev->upstream_databuf_size_ch2 = data_frame_size * 2; - -- /* Allocating buffers and prepare RISC program */ -+ /* Allocating buffers and prepare RISC program */ - retval = - cx25821_upstream_buffer_prepare_ch2(dev, sram_ch, - dev->_line_size_ch2); -@@ -848,7 +839,7 @@ int cx25821_vidupstream_init_ch2(struct cx25821_dev *dev, int channel_select, - - return 0; - -- error: -+ error: - cx25821_dev_unregister(dev); - - return err; -diff --git a/drivers/staging/cx25821/cx25821-video-upstream-ch2.h b/drivers/staging/cx25821/cx25821-video-upstream-ch2.h -index 6234063..029e830 100644 ---- a/drivers/staging/cx25821/cx25821-video-upstream-ch2.h -+++ b/drivers/staging/cx25821/cx25821-video-upstream-ch2.h -@@ -88,14 +88,14 @@ - #endif - - #ifndef USE_RISC_NOOP_VIDEO --#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) --#define PAL_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE) ) -+#define PAL_US_VID_PROG_SIZE ((PAL_FIELD_HEIGHT + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE) -+#define PAL_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + PAL_US_VID_PROG_SIZE)) - #define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ -- RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) --#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) --#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) -+ RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) -+#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE) -+#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE) - #define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) --#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) ) -+#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) - #define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ -- RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) -+ RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) - #endif -diff --git a/drivers/staging/cx25821/cx25821-video-upstream.c b/drivers/staging/cx25821/cx25821-video-upstream.c -index 756a820..16bf74d 100644 ---- a/drivers/staging/cx25821/cx25821-video-upstream.c -+++ b/drivers/staging/cx25821/cx25821-video-upstream.c -@@ -39,7 +39,7 @@ MODULE_AUTHOR("Hiep Huynh "); - MODULE_LICENSE("GPL"); - - static int _intr_msk = -- FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; -+ FLD_VID_SRC_RISC1 | FLD_VID_SRC_UF | FLD_VID_SRC_SYNC | FLD_VID_SRC_OPC_ERR; - - int cx25821_sram_channel_setup_upstream(struct cx25821_dev *dev, - struct sram_channel *ch, -@@ -346,13 +346,13 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) - - if (IS_ERR(myfile)) { - const int open_errno = -PTR_ERR(myfile); -- printk(KERN_ERR -+ printk(KERN_ERR - "%s(): ERROR opening file(%s) with errno = %d!\n", - __func__, dev->_filename, open_errno); - return PTR_ERR(myfile); - } else { - if (!(myfile->f_op)) { -- printk(KERN_ERR -+ printk(KERN_ERR - "%s: File has no file operations registered!", - __func__); - filp_close(myfile, NULL); -@@ -360,7 +360,7 @@ int cx25821_get_frame(struct cx25821_dev *dev, struct sram_channel *sram_ch) - } - - if (!myfile->f_op->read) { -- printk(KERN_ERR -+ printk(KERN_ERR - "%s: File has no READ operations registered!", - __func__); - filp_close(myfile, NULL); -@@ -415,7 +415,7 @@ static void cx25821_vidups_handler(struct work_struct *work) - container_of(work, struct cx25821_dev, _irq_work_entry); - - if (!dev) { -- printk(KERN_ERR -+ printk(KERN_ERR - "ERROR %s(): since container_of(work_struct) FAILED!\n", - __func__); - return; -@@ -448,7 +448,7 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) - return PTR_ERR(myfile); - } else { - if (!(myfile->f_op)) { -- printk(KERN_ERR -+ printk(KERN_ERR - "%s: File has no file operations registered!", - __func__); - filp_close(myfile, NULL); -@@ -456,7 +456,7 @@ int cx25821_openfile(struct cx25821_dev *dev, struct sram_channel *sram_ch) - } - - if (!myfile->f_op->read) { -- printk(KERN_ERR -+ printk(KERN_ERR - "%s: File has no READ operations registered! \ - Returning.", - __func__); -@@ -589,7 +589,7 @@ int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, - u32 status) - { - u32 int_msk_tmp; -- struct sram_channel *channel = dev->channels[chan_num].sram_channels; -+ struct sram_channel *channel = dev->channels[chan_num].sram_channels; - int singlefield_lines = NTSC_FIELD_HEIGHT; - int line_size_in_bytes = Y422_LINE_SZ; - int odd_risc_prog_size = 0; -@@ -657,12 +657,12 @@ int cx25821_video_upstream_irq(struct cx25821_dev *dev, int chan_num, - Interrupt!\n", __func__); - - if (status & FLD_VID_SRC_SYNC) -- printk(KERN_ERR "%s: Video Received Sync Error \ -- Interrupt!\n", __func__); -+ printk(KERN_ERR "%s: Video Received Sync Error \ -+ Interrupt!\n", __func__); - - if (status & FLD_VID_SRC_OPC_ERR) -- printk(KERN_ERR "%s: Video Received OpCode Error \ -- Interrupt!\n", __func__); -+ printk(KERN_ERR "%s: Video Received OpCode Error \ -+ Interrupt!\n", __func__); - } - - if (dev->_file_status == END_OF_FILE) { -@@ -690,7 +690,7 @@ static irqreturn_t cx25821_upstream_irq(int irq, void *dev_id) - - channel_num = VID_UPSTREAM_SRAM_CHANNEL_I; - -- sram_ch = dev->channels[channel_num].sram_channels; -+ sram_ch = dev->channels[channel_num].sram_channels; - - msk_stat = cx_read(sram_ch->int_mstat); - vid_status = cx_read(sram_ch->int_stat); -@@ -811,7 +811,7 @@ int cx25821_vidupstream_init_ch1(struct cx25821_dev *dev, int channel_select, - } - - dev->_channel_upstream_select = channel_select; -- sram_ch = dev->channels[channel_select].sram_channels; -+ sram_ch = dev->channels[channel_select].sram_channels; - - INIT_WORK(&dev->_irq_work_entry, cx25821_vidups_handler); - dev->_irq_queues = create_singlethread_workqueue("cx25821_workqueue"); -diff --git a/drivers/staging/cx25821/cx25821-video-upstream.h b/drivers/staging/cx25821/cx25821-video-upstream.h -index 10dee5c..f0b3ac0 100644 ---- a/drivers/staging/cx25821/cx25821-video-upstream.h -+++ b/drivers/staging/cx25821/cx25821-video-upstream.h -@@ -97,13 +97,13 @@ - #define PAL_RISC_BUF_SIZE (2 * PAL_US_VID_PROG_SIZE) - - #define PAL_VID_PROG_SIZE ((PAL_FIELD_HEIGHT*2) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ -- RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) -+ RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) - --#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) --#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE ) -+#define ODD_FLD_PAL_PROG_SIZE ((PAL_FIELD_HEIGHT) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE) -+#define ODD_FLD_NTSC_PROG_SIZE ((NTSC_ODD_FLD_LINES) * 3 * DWORD_SIZE + RISC_SYNC_INSTRUCTION_SIZE + RISC_WRITECR_INSTRUCTION_SIZE) - - #define NTSC_US_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + 1) * 3 * DWORD_SIZE + RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) --#define NTSC_RISC_BUF_SIZE ( 2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE) ) -+#define NTSC_RISC_BUF_SIZE (2 * (RISC_SYNC_INSTRUCTION_SIZE + NTSC_US_VID_PROG_SIZE)) - #define FRAME1_VID_PROG_SIZE ((NTSC_ODD_FLD_LINES + NTSC_FIELD_HEIGHT) * 3 * DWORD_SIZE + 2*RISC_SYNC_INSTRUCTION_SIZE + \ -- RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE ) -+ RISC_WRITECR_INSTRUCTION_SIZE + JUMP_INSTRUCTION_SIZE) - #endif -diff --git a/drivers/staging/cx25821/cx25821.h b/drivers/staging/cx25821/cx25821.h -index 1b628f6..c940001 100644 ---- a/drivers/staging/cx25821/cx25821.h -+++ b/drivers/staging/cx25821/cx25821.h -@@ -91,10 +91,10 @@ - - /* Currently supported by the driver */ - #define CX25821_NORMS (\ -- V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR | \ -- V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \ -- V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_H | \ -- V4L2_STD_PAL_Nc ) -+ V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_M_KR | \ -+ V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \ -+ V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_H | \ -+ V4L2_STD_PAL_Nc) - - #define CX25821_BOARD_CONEXANT_ATHENA10 1 - #define MAX_VID_CHANNEL_NUM 12 -@@ -139,7 +139,7 @@ struct cx25821_fh { - /* video capture */ - struct cx25821_fmt *fmt; - unsigned int width, height; -- int channel_id; -+ int channel_id; - - /* vbi capture */ - struct videobuf_queue vidq; -@@ -238,26 +238,25 @@ struct cx25821_data { - }; - - struct cx25821_channel { -- struct v4l2_prio_state prio; -+ struct v4l2_prio_state prio; - -- int ctl_bright; -- int ctl_contrast; -- int ctl_hue; -- int ctl_saturation; -+ int ctl_bright; -+ int ctl_contrast; -+ int ctl_hue; -+ int ctl_saturation; -+ struct cx25821_data timeout_data; - -- struct cx25821_data timeout_data; -+ struct video_device *video_dev; -+ struct cx25821_dmaqueue vidq; - -- struct video_device *video_dev; -- struct cx25821_dmaqueue vidq; -+ struct sram_channel *sram_channels; - -- struct sram_channel *sram_channels; -- -- struct mutex lock; -- int resources; -+ struct mutex lock; -+ int resources; - -- int pixel_formats; -- int use_cif_resolution; -- int cif_width; -+ int pixel_formats; -+ int use_cif_resolution; -+ int cif_width; - }; - - struct cx25821_dev { -@@ -283,7 +282,7 @@ struct cx25821_dev { - int nr; - struct mutex lock; - -- struct cx25821_channel channels[MAX_VID_CHANNEL_NUM]; -+ struct cx25821_channel channels[MAX_VID_CHANNEL_NUM]; - - /* board details */ - unsigned int board; -@@ -311,7 +310,7 @@ struct cx25821_dev { - int _audio_lines_count; - int _audioframe_count; - int _audio_upstream_channel_select; -- int _last_index_irq; /* The last interrupt index processed. */ -+ int _last_index_irq; /* The last interrupt index processed. */ - - __le32 *_risc_audio_jmp_addr; - __le32 *_risc_virt_start_addr; -@@ -443,7 +442,7 @@ static inline struct cx25821_dev *get_cx25821(struct v4l2_device *v4l2_dev) - } - - #define cx25821_call_all(dev, o, f, args...) \ -- v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) -+ v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) - - extern struct list_head cx25821_devlist; - extern struct cx25821_board cx25821_boards[]; -@@ -491,7 +490,7 @@ struct sram_channel { - u32 fld_aud_fifo_en; - u32 fld_aud_risc_en; - -- /* For Upstream Video */ -+ /* For Upstream Video */ - u32 vid_fmt_ctl; - u32 vid_active_ctl1; - u32 vid_active_ctl2; -@@ -511,8 +510,8 @@ extern struct sram_channel cx25821_sram_channels[]; - #define cx_write(reg, value) writel((value), dev->lmmio + ((reg)>>2)) - - #define cx_andor(reg, mask, value) \ -- writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\ -- ((value) & (mask)), dev->lmmio+((reg)>>2)) -+ writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\ -+ ((value) & (mask)), dev->lmmio+((reg)>>2)) - - #define cx_set(reg, bit) cx_andor((reg), (bit), (bit)) - #define cx_clear(reg, bit) cx_andor((reg), (bit), 0) ++ status = nvt_cir_reg_read(nvt, CIR_IRSTS); ++ if (!status) { ++ nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__); ++ nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); ++ return IRQ_RETVAL(IRQ_NONE); ++ } ++ ++ /* ack/clear all irq flags we've got */ ++ nvt_cir_reg_write(nvt, status, CIR_IRSTS); ++ nvt_cir_reg_write(nvt, 0, CIR_IRSTS); ++ ++ /* Interrupt may be shared with CIR Wake, bail if CIR not enabled */ ++ iren = nvt_cir_reg_read(nvt, CIR_IREN); ++ if (!iren) { ++ nvt_dbg_verbose("%s exiting, CIR not enabled", __func__); ++ return IRQ_RETVAL(IRQ_NONE); ++ } ++ ++ if (debug) ++ nvt_cir_log_irqs(status, iren); ++ ++ if (status & CIR_IRSTS_RTR) { ++ /* FIXME: add code for study/learn mode */ ++ /* We only do rx if not tx'ing */ ++ if (nvt_cir_tx_inactive(nvt)) ++ nvt_get_rx_ir_data(nvt); ++ } ++ ++ if (status & CIR_IRSTS_PE) { ++ if (nvt_cir_tx_inactive(nvt)) ++ nvt_get_rx_ir_data(nvt); ++ ++ spin_lock_irqsave(&nvt->nvt_lock, flags); ++ ++ cur_state = nvt->study_state; ++ ++ spin_unlock_irqrestore(&nvt->nvt_lock, flags); ++ ++ if (cur_state == ST_STUDY_NONE) ++ nvt_clear_cir_fifo(nvt); ++ } ++ ++ if (status & CIR_IRSTS_TE) ++ nvt_clear_tx_fifo(nvt); ++ ++ if (status & CIR_IRSTS_TTR) { ++ unsigned int pos, count; ++ u8 tmp; ++ ++ spin_lock_irqsave(&nvt->tx.lock, flags); ++ ++ pos = nvt->tx.cur_buf_num; ++ count = nvt->tx.buf_count; ++ ++ /* Write data into the hardware tx fifo while pos < count */ ++ if (pos < count) { ++ nvt_cir_reg_write(nvt, nvt->tx.buf[pos], CIR_STXFIFO); ++ nvt->tx.cur_buf_num++; ++ /* Disable TX FIFO Trigger Level Reach (TTR) interrupt */ ++ } else { ++ tmp = nvt_cir_reg_read(nvt, CIR_IREN); ++ nvt_cir_reg_write(nvt, tmp & ~CIR_IREN_TTR, CIR_IREN); ++ } ++ ++ spin_unlock_irqrestore(&nvt->tx.lock, flags); ++ ++ } ++ ++ if (status & CIR_IRSTS_TFU) { ++ spin_lock_irqsave(&nvt->tx.lock, flags); ++ if (nvt->tx.tx_state == ST_TX_REPLY) { ++ nvt->tx.tx_state = ST_TX_REQUEST; ++ wake_up(&nvt->tx.queue); ++ } ++ spin_unlock_irqrestore(&nvt->tx.lock, flags); ++ } ++ ++ nvt_dbg_verbose("%s done", __func__); ++ return IRQ_RETVAL(IRQ_HANDLED); ++} ++ ++/* Interrupt service routine for CIR Wake */ ++static irqreturn_t nvt_cir_wake_isr(int irq, void *data) ++{ ++ u8 status, iren, val; ++ struct nvt_dev *nvt = data; ++ unsigned long flags; ++ ++ nvt_dbg_wake("%s firing", __func__); ++ ++ status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS); ++ if (!status) ++ return IRQ_RETVAL(IRQ_NONE); ++ ++ if (status & CIR_WAKE_IRSTS_IR_PENDING) ++ nvt_clear_cir_wake_fifo(nvt); ++ ++ nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS); ++ nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS); ++ ++ /* Interrupt may be shared with CIR, bail if Wake not enabled */ ++ iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); ++ if (!iren) { ++ nvt_dbg_wake("%s exiting, wake not enabled", __func__); ++ return IRQ_RETVAL(IRQ_HANDLED); ++ } ++ ++ if ((status & CIR_WAKE_IRSTS_PE) && ++ (nvt->wake_state == ST_WAKE_START)) { ++ while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) { ++ val = nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY); ++ nvt_dbg("setting wake up key: 0x%x", val); ++ } ++ ++ nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IREN); ++ spin_lock_irqsave(&nvt->nvt_lock, flags); ++ nvt->wake_state = ST_WAKE_FINISH; ++ spin_unlock_irqrestore(&nvt->nvt_lock, flags); ++ } ++ ++ nvt_dbg_wake("%s done", __func__); ++ return IRQ_RETVAL(IRQ_HANDLED); ++} ++ ++static void nvt_enable_cir(struct nvt_dev *nvt) ++{ ++ /* set function enable flags */ ++ nvt_cir_reg_write(nvt, CIR_IRCON_TXEN | CIR_IRCON_RXEN | ++ CIR_IRCON_RXINV | CIR_IRCON_SAMPLE_PERIOD_SEL, ++ CIR_IRCON); ++ ++ nvt_efm_enable(nvt); ++ ++ /* enable the CIR logical device */ ++ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); ++ nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); ++ ++ nvt_efm_disable(nvt); ++ ++ /* clear all pending interrupts */ ++ nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); ++ ++ /* enable interrupts */ ++ nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); ++} ++ ++static void nvt_disable_cir(struct nvt_dev *nvt) ++{ ++ /* disable CIR interrupts */ ++ nvt_cir_reg_write(nvt, 0, CIR_IREN); ++ ++ /* clear any and all pending interrupts */ ++ nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); ++ ++ /* clear all function enable flags */ ++ nvt_cir_reg_write(nvt, 0, CIR_IRCON); ++ ++ /* clear hardware rx and tx fifos */ ++ nvt_clear_cir_fifo(nvt); ++ nvt_clear_tx_fifo(nvt); ++ ++ nvt_efm_enable(nvt); ++ ++ /* disable the CIR logical device */ ++ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); ++ nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); ++ ++ nvt_efm_disable(nvt); ++} ++ ++static int nvt_open(void *data) ++{ ++ struct nvt_dev *nvt = (struct nvt_dev *)data; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&nvt->nvt_lock, flags); ++ nvt->in_use = true; ++ nvt_enable_cir(nvt); ++ spin_unlock_irqrestore(&nvt->nvt_lock, flags); ++ ++ return 0; ++} ++ ++static void nvt_close(void *data) ++{ ++ struct nvt_dev *nvt = (struct nvt_dev *)data; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&nvt->nvt_lock, flags); ++ nvt->in_use = false; ++ nvt_disable_cir(nvt); ++ spin_unlock_irqrestore(&nvt->nvt_lock, flags); ++} ++ ++/* Allocate memory, probe hardware, and initialize everything */ ++static int nvt_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) ++{ ++ struct nvt_dev *nvt = NULL; ++ struct input_dev *rdev = NULL; ++ struct ir_dev_props *props = NULL; ++ int ret = -ENOMEM; ++ ++ nvt = kzalloc(sizeof(struct nvt_dev), GFP_KERNEL); ++ if (!nvt) ++ return ret; ++ ++ props = kzalloc(sizeof(struct ir_dev_props), GFP_KERNEL); ++ if (!props) ++ goto failure; ++ ++ /* input device for IR remote (and tx) */ ++ rdev = input_allocate_device(); ++ if (!rdev) ++ goto failure; ++ ++ ret = -ENODEV; ++ /* validate pnp resources */ ++ if (!pnp_port_valid(pdev, 0) || ++ pnp_port_len(pdev, 0) < CIR_IOREG_LENGTH) { ++ dev_err(&pdev->dev, "IR PNP Port not valid!\n"); ++ goto failure; ++ } ++ ++ if (!pnp_irq_valid(pdev, 0)) { ++ dev_err(&pdev->dev, "PNP IRQ not valid!\n"); ++ goto failure; ++ } ++ ++ if (!pnp_port_valid(pdev, 1) || ++ pnp_port_len(pdev, 1) < CIR_IOREG_LENGTH) { ++ dev_err(&pdev->dev, "Wake PNP Port not valid!\n"); ++ goto failure; ++ } ++ ++ nvt->cir_addr = pnp_port_start(pdev, 0); ++ nvt->cir_irq = pnp_irq(pdev, 0); ++ ++ nvt->cir_wake_addr = pnp_port_start(pdev, 1); ++ /* irq is always shared between cir and cir wake */ ++ nvt->cir_wake_irq = nvt->cir_irq; ++ ++ nvt->cr_efir = CR_EFIR; ++ nvt->cr_efdr = CR_EFDR; ++ ++ spin_lock_init(&nvt->nvt_lock); ++ spin_lock_init(&nvt->tx.lock); ++ ++ ret = -EBUSY; ++ /* now claim resources */ ++ if (!request_region(nvt->cir_addr, ++ CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) ++ goto failure; ++ ++ if (request_irq(nvt->cir_irq, nvt_cir_isr, IRQF_SHARED, ++ NVT_DRIVER_NAME, (void *)nvt)) ++ goto failure; ++ ++ if (!request_region(nvt->cir_wake_addr, ++ CIR_IOREG_LENGTH, NVT_DRIVER_NAME)) ++ goto failure; ++ ++ if (request_irq(nvt->cir_wake_irq, nvt_cir_wake_isr, IRQF_SHARED, ++ NVT_DRIVER_NAME, (void *)nvt)) ++ goto failure; ++ ++ pnp_set_drvdata(pdev, nvt); ++ nvt->pdev = pdev; ++ ++ init_waitqueue_head(&nvt->tx.queue); ++ ++ ret = nvt_hw_detect(nvt); ++ if (ret) ++ goto failure; ++ ++ /* Initialize CIR & CIR Wake Logical Devices */ ++ nvt_efm_enable(nvt); ++ nvt_cir_ldev_init(nvt); ++ nvt_cir_wake_ldev_init(nvt); ++ nvt_efm_disable(nvt); ++ ++ /* Initialize CIR & CIR Wake Config Registers */ ++ nvt_cir_regs_init(nvt); ++ nvt_cir_wake_regs_init(nvt); ++ ++ /* Set up ir-core props */ ++ props->priv = nvt; ++ props->driver_type = RC_DRIVER_IR_RAW; ++ props->allowed_protos = IR_TYPE_ALL; ++ props->open = nvt_open; ++ props->close = nvt_close; ++#if 0 ++ props->min_timeout = XYZ; ++ props->max_timeout = XYZ; ++ props->timeout = XYZ; ++ /* rx resolution is hardwired to 50us atm, 1, 25, 100 also possible */ ++ props->rx_resolution = XYZ; ++ ++ /* tx bits */ ++ props->tx_resolution = XYZ; ++#endif ++ props->tx_ir = nvt_tx_ir; ++ props->s_tx_carrier = nvt_set_tx_carrier; ++ ++ rdev->name = "Nuvoton w836x7hg Infrared Remote Transceiver"; ++ rdev->id.bustype = BUS_HOST; ++ rdev->id.vendor = PCI_VENDOR_ID_WINBOND2; ++ rdev->id.product = nvt->chip_major; ++ rdev->id.version = nvt->chip_minor; ++ ++ nvt->props = props; ++ nvt->rdev = rdev; ++ ++ device_set_wakeup_capable(&pdev->dev, 1); ++ device_set_wakeup_enable(&pdev->dev, 1); ++ ++ ret = ir_input_register(rdev, RC_MAP_RC6_MCE, props, NVT_DRIVER_NAME); ++ if (ret) ++ goto failure; ++ ++ nvt_pr(KERN_NOTICE, "driver has been successfully loaded\n"); ++ if (debug) { ++ cir_dump_regs(nvt); ++ cir_wake_dump_regs(nvt); ++ } ++ ++ return 0; ++ ++failure: ++ if (nvt->cir_irq) ++ free_irq(nvt->cir_irq, nvt); ++ if (nvt->cir_addr) ++ release_region(nvt->cir_addr, CIR_IOREG_LENGTH); ++ ++ if (nvt->cir_wake_irq) ++ free_irq(nvt->cir_wake_irq, nvt); ++ if (nvt->cir_wake_addr) ++ release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); ++ ++ input_free_device(rdev); ++ kfree(props); ++ kfree(nvt); ++ ++ return ret; ++} ++ ++static void __devexit nvt_remove(struct pnp_dev *pdev) ++{ ++ struct nvt_dev *nvt = pnp_get_drvdata(pdev); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&nvt->nvt_lock, flags); ++ /* disable CIR */ ++ nvt_cir_reg_write(nvt, 0, CIR_IREN); ++ nvt_disable_cir(nvt); ++ /* enable CIR Wake (for IR power-on) */ ++ nvt_enable_wake(nvt); ++ spin_unlock_irqrestore(&nvt->nvt_lock, flags); ++ ++ /* free resources */ ++ free_irq(nvt->cir_irq, nvt); ++ free_irq(nvt->cir_wake_irq, nvt); ++ release_region(nvt->cir_addr, CIR_IOREG_LENGTH); ++ release_region(nvt->cir_wake_addr, CIR_IOREG_LENGTH); ++ ++ ir_input_unregister(nvt->rdev); ++ ++ kfree(nvt->props); ++ kfree(nvt); ++} ++ ++static int nvt_suspend(struct pnp_dev *pdev, pm_message_t state) ++{ ++ struct nvt_dev *nvt = pnp_get_drvdata(pdev); ++ unsigned long flags; ++ ++ nvt_dbg("%s called", __func__); ++ ++ /* zero out misc state tracking */ ++ spin_lock_irqsave(&nvt->nvt_lock, flags); ++ nvt->study_state = ST_STUDY_NONE; ++ nvt->wake_state = ST_WAKE_NONE; ++ spin_unlock_irqrestore(&nvt->nvt_lock, flags); ++ ++ spin_lock_irqsave(&nvt->tx.lock, flags); ++ nvt->tx.tx_state = ST_TX_NONE; ++ spin_unlock_irqrestore(&nvt->tx.lock, flags); ++ ++ /* disable all CIR interrupts */ ++ nvt_cir_reg_write(nvt, 0, CIR_IREN); ++ ++ nvt_efm_enable(nvt); ++ ++ /* disable cir logical dev */ ++ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); ++ nvt_cr_write(nvt, LOGICAL_DEV_DISABLE, CR_LOGICAL_DEV_EN); ++ ++ nvt_efm_disable(nvt); ++ ++ /* make sure wake is enabled */ ++ nvt_enable_wake(nvt); ++ ++ return 0; ++} ++ ++static int nvt_resume(struct pnp_dev *pdev) ++{ ++ int ret = 0; ++ struct nvt_dev *nvt = pnp_get_drvdata(pdev); ++ ++ nvt_dbg("%s called", __func__); ++ ++ /* open interrupt */ ++ nvt_cir_reg_write(nvt, CIR_IREN_RTR | CIR_IREN_PE, CIR_IREN); ++ ++ /* Enable CIR logical device */ ++ nvt_efm_enable(nvt); ++ nvt_select_logical_dev(nvt, LOGICAL_DEV_CIR); ++ nvt_cr_write(nvt, LOGICAL_DEV_ENABLE, CR_LOGICAL_DEV_EN); ++ ++ nvt_efm_disable(nvt); ++ ++ nvt_cir_regs_init(nvt); ++ nvt_cir_wake_regs_init(nvt); ++ ++ return ret; ++} ++ ++static void nvt_shutdown(struct pnp_dev *pdev) ++{ ++ struct nvt_dev *nvt = pnp_get_drvdata(pdev); ++ nvt_enable_wake(nvt); ++} ++ ++static const struct pnp_device_id nvt_ids[] = { ++ { "WEC0530", 0 }, /* CIR */ ++ { "NTN0530", 0 }, /* CIR for new chip's pnp id*/ ++ { "", 0 }, ++}; ++ ++static struct pnp_driver nvt_driver = { ++ .name = NVT_DRIVER_NAME, ++ .id_table = nvt_ids, ++ .flags = PNP_DRIVER_RES_DO_NOT_CHANGE, ++ .probe = nvt_probe, ++ .remove = __devexit_p(nvt_remove), ++ .suspend = nvt_suspend, ++ .resume = nvt_resume, ++ .shutdown = nvt_shutdown, ++}; ++ ++int nvt_init(void) ++{ ++ return pnp_register_driver(&nvt_driver); ++} ++ ++void nvt_exit(void) ++{ ++ pnp_unregister_driver(&nvt_driver); ++} ++ ++module_param(debug, int, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(debug, "Enable debugging output"); ++ ++MODULE_DEVICE_TABLE(pnp, nvt_ids); ++MODULE_DESCRIPTION("Nuvoton W83667HG-A & W83677HG-I CIR driver"); ++ ++MODULE_AUTHOR("Jarod Wilson "); ++MODULE_LICENSE("GPL"); ++ ++module_init(nvt_init); ++module_exit(nvt_exit); +diff --git a/drivers/media/IR/nuvoton-cir.h b/drivers/media/IR/nuvoton-cir.h +new file mode 100644 +index 0000000..12bfe89 +--- /dev/null ++++ b/drivers/media/IR/nuvoton-cir.h +@@ -0,0 +1,408 @@ ++/* ++ * Driver for Nuvoton Technology Corporation w83667hg/w83677hg-i CIR ++ * ++ * Copyright (C) 2010 Jarod Wilson ++ * Copyright (C) 2009 Nuvoton PS Team ++ * ++ * Special thanks to Nuvoton for providing hardware, spec sheets and ++ * sample code upon which portions of this driver are based. Indirect ++ * thanks also to Maxim Levitsky, whose ene_ir driver this driver is ++ * modeled after. ++ * ++ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 ++ * USA ++ */ ++ ++#include ++#include ++ ++/* platform driver name to register */ ++#define NVT_DRIVER_NAME "nuvoton-cir" ++ ++/* debugging module parameter */ ++static int debug; ++ ++ ++#define nvt_pr(level, text, ...) \ ++ printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__) ++ ++#define nvt_dbg(text, ...) \ ++ if (debug) \ ++ printk(KERN_DEBUG \ ++ KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) ++ ++#define nvt_dbg_verbose(text, ...) \ ++ if (debug > 1) \ ++ printk(KERN_DEBUG \ ++ KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) ++ ++#define nvt_dbg_wake(text, ...) \ ++ if (debug > 2) \ ++ printk(KERN_DEBUG \ ++ KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__) ++ ++ ++/* ++ * Original lirc driver said min value of 76, and recommended value of 256 ++ * for the buffer length, but then used 2048. Never mind that the size of the ++ * RX FIFO is 32 bytes... So I'm using 32 for RX and 256 for TX atm, but I'm ++ * not sure if maybe that TX value is off by a factor of 8 (bits vs. bytes), ++ * and I don't have TX-capable hardware to test/debug on... ++ */ ++#define TX_BUF_LEN 256 ++#define RX_BUF_LEN 32 ++ ++struct nvt_dev { ++ struct pnp_dev *pdev; ++ struct input_dev *rdev; ++ struct ir_dev_props *props; ++ struct ir_raw_event rawir; ++ ++ spinlock_t nvt_lock; ++ bool in_use; ++ ++ /* for rx */ ++ u8 buf[RX_BUF_LEN]; ++ unsigned int pkts; ++ ++ struct { ++ spinlock_t lock; ++ u8 buf[TX_BUF_LEN]; ++ unsigned int buf_count; ++ unsigned int cur_buf_num; ++ wait_queue_head_t queue; ++ u8 tx_state; ++ } tx; ++ ++ /* EFER Config register index/data pair */ ++ u8 cr_efir; ++ u8 cr_efdr; ++ ++ /* hardware I/O settings */ ++ unsigned long cir_addr; ++ unsigned long cir_wake_addr; ++ int cir_irq; ++ int cir_wake_irq; ++ ++ /* hardware id */ ++ u8 chip_major; ++ u8 chip_minor; ++ ++ /* hardware features */ ++ bool hw_learning_capable; ++ bool hw_tx_capable; ++ ++ /* rx settings */ ++ bool learning_enabled; ++ bool carrier_detect_enabled; ++ ++ /* track cir wake state */ ++ u8 wake_state; ++ /* for study */ ++ u8 study_state; ++ /* carrier period = 1 / frequency */ ++ u32 carrier; ++}; ++ ++/* study states */ ++#define ST_STUDY_NONE 0x0 ++#define ST_STUDY_START 0x1 ++#define ST_STUDY_CARRIER 0x2 ++#define ST_STUDY_ALL_RECV 0x4 ++ ++/* wake states */ ++#define ST_WAKE_NONE 0x0 ++#define ST_WAKE_START 0x1 ++#define ST_WAKE_FINISH 0x2 ++ ++/* receive states */ ++#define ST_RX_WAIT_7F 0x1 ++#define ST_RX_WAIT_HEAD 0x2 ++#define ST_RX_WAIT_SILENT_END 0x4 ++ ++/* send states */ ++#define ST_TX_NONE 0x0 ++#define ST_TX_REQUEST 0x2 ++#define ST_TX_REPLY 0x4 ++ ++/* buffer packet constants */ ++#define BUF_PULSE_BIT 0x80 ++#define BUF_LEN_MASK 0x7f ++#define BUF_REPEAT_BYTE 0x70 ++#define BUF_REPEAT_MASK 0xf0 ++ ++/* CIR settings */ ++ ++/* total length of CIR and CIR WAKE */ ++#define CIR_IOREG_LENGTH 0x0f ++ ++/* RX limit length, 8 high bits for SLCH, 8 low bits for SLCL (0x7d0 = 2000) */ ++#define CIR_RX_LIMIT_COUNT 0x7d0 ++ ++/* CIR Regs */ ++#define CIR_IRCON 0x00 ++#define CIR_IRSTS 0x01 ++#define CIR_IREN 0x02 ++#define CIR_RXFCONT 0x03 ++#define CIR_CP 0x04 ++#define CIR_CC 0x05 ++#define CIR_SLCH 0x06 ++#define CIR_SLCL 0x07 ++#define CIR_FIFOCON 0x08 ++#define CIR_IRFIFOSTS 0x09 ++#define CIR_SRXFIFO 0x0a ++#define CIR_TXFCONT 0x0b ++#define CIR_STXFIFO 0x0c ++#define CIR_FCCH 0x0d ++#define CIR_FCCL 0x0e ++#define CIR_IRFSM 0x0f ++ ++/* CIR IRCON settings */ ++#define CIR_IRCON_RECV 0x80 ++#define CIR_IRCON_WIREN 0x40 ++#define CIR_IRCON_TXEN 0x20 ++#define CIR_IRCON_RXEN 0x10 ++#define CIR_IRCON_WRXINV 0x08 ++#define CIR_IRCON_RXINV 0x04 ++ ++#define CIR_IRCON_SAMPLE_PERIOD_SEL_1 0x00 ++#define CIR_IRCON_SAMPLE_PERIOD_SEL_25 0x01 ++#define CIR_IRCON_SAMPLE_PERIOD_SEL_50 0x02 ++#define CIR_IRCON_SAMPLE_PERIOD_SEL_100 0x03 ++ ++/* FIXME: make this a runtime option */ ++/* select sample period as 50us */ ++#define CIR_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50 ++ ++/* CIR IRSTS settings */ ++#define CIR_IRSTS_RDR 0x80 ++#define CIR_IRSTS_RTR 0x40 ++#define CIR_IRSTS_PE 0x20 ++#define CIR_IRSTS_RFO 0x10 ++#define CIR_IRSTS_TE 0x08 ++#define CIR_IRSTS_TTR 0x04 ++#define CIR_IRSTS_TFU 0x02 ++#define CIR_IRSTS_GH 0x01 ++ ++/* CIR IREN settings */ ++#define CIR_IREN_RDR 0x80 ++#define CIR_IREN_RTR 0x40 ++#define CIR_IREN_PE 0x20 ++#define CIR_IREN_RFO 0x10 ++#define CIR_IREN_TE 0x08 ++#define CIR_IREN_TTR 0x04 ++#define CIR_IREN_TFU 0x02 ++#define CIR_IREN_GH 0x01 ++ ++/* CIR FIFOCON settings */ ++#define CIR_FIFOCON_TXFIFOCLR 0x80 ++ ++#define CIR_FIFOCON_TX_TRIGGER_LEV_31 0x00 ++#define CIR_FIFOCON_TX_TRIGGER_LEV_24 0x10 ++#define CIR_FIFOCON_TX_TRIGGER_LEV_16 0x20 ++#define CIR_FIFOCON_TX_TRIGGER_LEV_8 0x30 ++ ++/* FIXME: make this a runtime option */ ++/* select TX trigger level as 16 */ ++#define CIR_FIFOCON_TX_TRIGGER_LEV CIR_FIFOCON_TX_TRIGGER_LEV_16 ++ ++#define CIR_FIFOCON_RXFIFOCLR 0x08 ++ ++#define CIR_FIFOCON_RX_TRIGGER_LEV_1 0x00 ++#define CIR_FIFOCON_RX_TRIGGER_LEV_8 0x01 ++#define CIR_FIFOCON_RX_TRIGGER_LEV_16 0x02 ++#define CIR_FIFOCON_RX_TRIGGER_LEV_24 0x03 ++ ++/* FIXME: make this a runtime option */ ++/* select RX trigger level as 24 */ ++#define CIR_FIFOCON_RX_TRIGGER_LEV CIR_FIFOCON_RX_TRIGGER_LEV_24 ++ ++/* CIR IRFIFOSTS settings */ ++#define CIR_IRFIFOSTS_IR_PENDING 0x80 ++#define CIR_IRFIFOSTS_RX_GS 0x40 ++#define CIR_IRFIFOSTS_RX_FTA 0x20 ++#define CIR_IRFIFOSTS_RX_EMPTY 0x10 ++#define CIR_IRFIFOSTS_RX_FULL 0x08 ++#define CIR_IRFIFOSTS_TX_FTA 0x04 ++#define CIR_IRFIFOSTS_TX_EMPTY 0x02 ++#define CIR_IRFIFOSTS_TX_FULL 0x01 ++ ++ ++/* CIR WAKE UP Regs */ ++#define CIR_WAKE_IRCON 0x00 ++#define CIR_WAKE_IRSTS 0x01 ++#define CIR_WAKE_IREN 0x02 ++#define CIR_WAKE_FIFO_CMP_DEEP 0x03 ++#define CIR_WAKE_FIFO_CMP_TOL 0x04 ++#define CIR_WAKE_FIFO_COUNT 0x05 ++#define CIR_WAKE_SLCH 0x06 ++#define CIR_WAKE_SLCL 0x07 ++#define CIR_WAKE_FIFOCON 0x08 ++#define CIR_WAKE_SRXFSTS 0x09 ++#define CIR_WAKE_SAMPLE_RX_FIFO 0x0a ++#define CIR_WAKE_WR_FIFO_DATA 0x0b ++#define CIR_WAKE_RD_FIFO_ONLY 0x0c ++#define CIR_WAKE_RD_FIFO_ONLY_IDX 0x0d ++#define CIR_WAKE_FIFO_IGNORE 0x0e ++#define CIR_WAKE_IRFSM 0x0f ++ ++/* CIR WAKE UP IRCON settings */ ++#define CIR_WAKE_IRCON_DEC_RST 0x80 ++#define CIR_WAKE_IRCON_MODE1 0x40 ++#define CIR_WAKE_IRCON_MODE0 0x20 ++#define CIR_WAKE_IRCON_RXEN 0x10 ++#define CIR_WAKE_IRCON_R 0x08 ++#define CIR_WAKE_IRCON_RXINV 0x04 ++ ++/* FIXME/jarod: make this a runtime option */ ++/* select a same sample period like cir register */ ++#define CIR_WAKE_IRCON_SAMPLE_PERIOD_SEL CIR_IRCON_SAMPLE_PERIOD_SEL_50 ++ ++/* CIR WAKE IRSTS Bits */ ++#define CIR_WAKE_IRSTS_RDR 0x80 ++#define CIR_WAKE_IRSTS_RTR 0x40 ++#define CIR_WAKE_IRSTS_PE 0x20 ++#define CIR_WAKE_IRSTS_RFO 0x10 ++#define CIR_WAKE_IRSTS_GH 0x08 ++#define CIR_WAKE_IRSTS_IR_PENDING 0x01 ++ ++/* CIR WAKE UP IREN Bits */ ++#define CIR_WAKE_IREN_RDR 0x80 ++#define CIR_WAKE_IREN_RTR 0x40 ++#define CIR_WAKE_IREN_PE 0x20 ++#define CIR_WAKE_IREN_RFO 0x10 ++#define CIR_WAKE_IREN_TE 0x08 ++#define CIR_WAKE_IREN_TTR 0x04 ++#define CIR_WAKE_IREN_TFU 0x02 ++#define CIR_WAKE_IREN_GH 0x01 ++ ++/* CIR WAKE FIFOCON settings */ ++#define CIR_WAKE_FIFOCON_RXFIFOCLR 0x08 ++ ++#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67 0x00 ++#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_66 0x01 ++#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_65 0x02 ++#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_64 0x03 ++ ++/* FIXME: make this a runtime option */ ++/* select WAKE UP RX trigger level as 67 */ ++#define CIR_WAKE_FIFOCON_RX_TRIGGER_LEV CIR_WAKE_FIFOCON_RX_TRIGGER_LEV_67 ++ ++/* CIR WAKE SRXFSTS settings */ ++#define CIR_WAKE_IRFIFOSTS_RX_GS 0x80 ++#define CIR_WAKE_IRFIFOSTS_RX_FTA 0x40 ++#define CIR_WAKE_IRFIFOSTS_RX_EMPTY 0x20 ++#define CIR_WAKE_IRFIFOSTS_RX_FULL 0x10 ++ ++/* CIR Wake FIFO buffer is 67 bytes long */ ++#define CIR_WAKE_FIFO_LEN 67 ++/* CIR Wake byte comparison tolerance */ ++#define CIR_WAKE_CMP_TOLERANCE 5 ++ ++/* ++ * Extended Function Enable Registers: ++ * Extended Function Index Register ++ * Extended Function Data Register ++ */ ++#define CR_EFIR 0x2e ++#define CR_EFDR 0x2f ++ ++/* Possible alternate EFER values, depends on how the chip is wired */ ++#define CR_EFIR2 0x4e ++#define CR_EFDR2 0x4f ++ ++/* Extended Function Mode enable/disable magic values */ ++#define EFER_EFM_ENABLE 0x87 ++#define EFER_EFM_DISABLE 0xaa ++ ++/* Chip IDs found in CR_CHIP_ID_{HI,LO} */ ++#define CHIP_ID_HIGH 0xb4 ++#define CHIP_ID_LOW 0x72 ++#define CHIP_ID_LOW2 0x73 ++ ++/* Config regs we need to care about */ ++#define CR_SOFTWARE_RESET 0x02 ++#define CR_LOGICAL_DEV_SEL 0x07 ++#define CR_CHIP_ID_HI 0x20 ++#define CR_CHIP_ID_LO 0x21 ++#define CR_DEV_POWER_DOWN 0x22 /* bit 2 is CIR power, default power on */ ++#define CR_OUTPUT_PIN_SEL 0x27 ++#define CR_LOGICAL_DEV_EN 0x30 /* valid for all logical devices */ ++/* next three regs valid for both the CIR and CIR_WAKE logical devices */ ++#define CR_CIR_BASE_ADDR_HI 0x60 ++#define CR_CIR_BASE_ADDR_LO 0x61 ++#define CR_CIR_IRQ_RSRC 0x70 ++/* next three regs valid only for ACPI logical dev */ ++#define CR_ACPI_CIR_WAKE 0xe0 ++#define CR_ACPI_IRQ_EVENTS 0xf6 ++#define CR_ACPI_IRQ_EVENTS2 0xf7 ++ ++/* Logical devices that we need to care about */ ++#define LOGICAL_DEV_LPT 0x01 ++#define LOGICAL_DEV_CIR 0x06 ++#define LOGICAL_DEV_ACPI 0x0a ++#define LOGICAL_DEV_CIR_WAKE 0x0e ++ ++#define LOGICAL_DEV_DISABLE 0x00 ++#define LOGICAL_DEV_ENABLE 0x01 ++ ++#define CIR_WAKE_ENABLE_BIT 0x08 ++#define CIR_INTR_MOUSE_IRQ_BIT 0x80 ++#define PME_INTR_CIR_PASS_BIT 0x08 ++ ++#define OUTPUT_PIN_SEL_MASK 0xbc ++#define OUTPUT_ENABLE_CIR 0x01 /* Pin95=CIRRX, Pin96=CIRTX1 */ ++#define OUTPUT_ENABLE_CIRWB 0x40 /* enable wide-band sensor */ ++ ++/* MCE CIR signal length, related on sample period */ ++ ++/* MCE CIR controller signal length: about 43ms ++ * 43ms / 50us (sample period) * 0.85 (inaccuracy) ++ */ ++#define CONTROLLER_BUF_LEN_MIN 830 ++ ++/* MCE CIR keyboard signal length: about 26ms ++ * 26ms / 50us (sample period) * 0.85 (inaccuracy) ++ */ ++#define KEYBOARD_BUF_LEN_MAX 650 ++#define KEYBOARD_BUF_LEN_MIN 610 ++ ++/* MCE CIR mouse signal length: about 24ms ++ * 24ms / 50us (sample period) * 0.85 (inaccuracy) ++ */ ++#define MOUSE_BUF_LEN_MIN 565 ++ ++#define CIR_SAMPLE_PERIOD 50 ++#define CIR_SAMPLE_LOW_INACCURACY 0.85 ++ ++/* MAX silence time that driver will sent to lirc */ ++#define MAX_SILENCE_TIME 60000 ++ ++#if CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_100 ++#define SAMPLE_PERIOD 100 ++ ++#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_50 ++#define SAMPLE_PERIOD 50 ++ ++#elif CIR_IRCON_SAMPLE_PERIOD_SEL == CIR_IRCON_SAMPLE_PERIOD_SEL_25 ++#define SAMPLE_PERIOD 25 ++ ++#else ++#define SAMPLE_PERIOD 1 ++#endif ++ ++/* as VISTA MCE definition, valid carrier value */ ++#define MAX_CARRIER 60000 ++#define MIN_CARRIER 30000 -- 1.7.3.1