diff options
Diffstat (limited to 'drivers/media/video/cx23885')
-rw-r--r-- | drivers/media/video/cx23885/Kconfig | 2 | ||||
-rw-r--r-- | drivers/media/video/cx23885/Makefile | 5 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-av.c | 35 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-av.h | 27 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-cards.c | 154 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-core.c | 135 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-dvb.c | 2 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-i2c.c | 42 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-input.c | 363 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-ir.c | 26 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-reg.h | 1 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-vbi.c | 2 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885-video.c | 23 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23885.h | 21 | ||||
-rw-r--r-- | drivers/media/video/cx23885/cx23888-ir.c | 142 |
15 files changed, 645 insertions, 335 deletions
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index bcdda9a9aa9..e1367b35647 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -5,7 +5,7 @@ config VIDEO_CX23885 select VIDEO_BTCX select VIDEO_TUNER select VIDEO_TVEEPROM - select VIDEO_IR + depends on IR_CORE select VIDEOBUF_DVB select VIDEOBUF_DMA_SG select VIDEO_CX25840 diff --git a/drivers/media/video/cx23885/Makefile b/drivers/media/video/cx23885/Makefile index 5787ae24363..e2ee95f660d 100644 --- a/drivers/media/video/cx23885/Makefile +++ b/drivers/media/video/cx23885/Makefile @@ -1,7 +1,8 @@ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.o \ - cx23885-ioctl.o cx23885-ir.o cx23885-input.o cx23888-ir.o \ - netup-init.o cimax2.o netup-eeprom.o cx23885-f300.o + cx23885-ioctl.o cx23885-ir.o cx23885-av.o cx23885-input.o \ + cx23888-ir.o netup-init.o cimax2.o netup-eeprom.o \ + cx23885-f300.o obj-$(CONFIG_VIDEO_CX23885) += cx23885.o diff --git a/drivers/media/video/cx23885/cx23885-av.c b/drivers/media/video/cx23885/cx23885-av.c new file mode 100644 index 00000000000..134ebddd860 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-av.c @@ -0,0 +1,35 @@ +/* + * Driver for the Conexant CX23885/7/8 PCIe bridge + * + * AV device support routines - non-input, non-vl42_subdev routines + * + * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include "cx23885.h" + +void cx23885_av_work_handler(struct work_struct *work) +{ + struct cx23885_dev *dev = + container_of(work, struct cx23885_dev, cx25840_work); + bool handled; + + v4l2_subdev_call(dev->sd_cx25840, core, interrupt_service_routine, + PCI_MSK_AV_CORE, &handled); + cx23885_irq_enable(dev, PCI_MSK_AV_CORE); +} diff --git a/drivers/media/video/cx23885/cx23885-av.h b/drivers/media/video/cx23885/cx23885-av.h new file mode 100644 index 00000000000..d2915c3e53a --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-av.h @@ -0,0 +1,27 @@ +/* + * Driver for the Conexant CX23885/7/8 PCIe bridge + * + * AV device support routines - non-input, non-vl42_subdev routines + * + * Copyright (C) 2010 Andy Walls <awalls@md.metrocast.net> + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef _CX23885_AV_H_ +#define _CX23885_AV_H_ +void cx23885_av_work_handler(struct work_struct *work); +#endif diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index d639186f645..e76ce8709af 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -30,6 +30,16 @@ #include "netup-init.h" #include "cx23888-ir.h" +static unsigned int enable_885_ir; +module_param(enable_885_ir, int, 0644); +MODULE_PARM_DESC(enable_885_ir, + "Enable integrated IR controller for supported\n" + "\t\t CX2388[57] boards that are wired for it:\n" + "\t\t\tHVR-1250 (reported safe)\n" + "\t\t\tTeVii S470 (reported unsafe)\n" + "\t\t This can cause an interrupt storm with some cards.\n" + "\t\t Default: 0 [Disabled]"); + /* ------------------------------------------------------------------ */ /* board config info */ @@ -408,10 +418,18 @@ struct cx23885_subid cx23885_subids[] = { .card = CX23885_BOARD_HAUPPAUGE_HVR1275, }, { .subvendor = 0x0070, + .subdevice = 0x221d, + .card = CX23885_BOARD_HAUPPAUGE_HVR1275, + }, { + .subvendor = 0x0070, .subdevice = 0x2251, .card = CX23885_BOARD_HAUPPAUGE_HVR1255, }, { .subvendor = 0x0070, + .subdevice = 0x2259, + .card = CX23885_BOARD_HAUPPAUGE_HVR1255, + }, { + .subvendor = 0x0070, .subdevice = 0x2291, .card = CX23885_BOARD_HAUPPAUGE_HVR1210, }, { @@ -419,6 +437,38 @@ struct cx23885_subid cx23885_subids[] = { .subdevice = 0x2295, .card = CX23885_BOARD_HAUPPAUGE_HVR1210, }, { + .subvendor = 0x0070, + .subdevice = 0x2299, + .card = CX23885_BOARD_HAUPPAUGE_HVR1210, + }, { + .subvendor = 0x0070, + .subdevice = 0x229d, + .card = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */ + }, { + .subvendor = 0x0070, + .subdevice = 0x22f0, + .card = CX23885_BOARD_HAUPPAUGE_HVR1210, + }, { + .subvendor = 0x0070, + .subdevice = 0x22f1, + .card = CX23885_BOARD_HAUPPAUGE_HVR1255, + }, { + .subvendor = 0x0070, + .subdevice = 0x22f2, + .card = CX23885_BOARD_HAUPPAUGE_HVR1275, + }, { + .subvendor = 0x0070, + .subdevice = 0x22f3, + .card = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */ + }, { + .subvendor = 0x0070, + .subdevice = 0x22f4, + .card = CX23885_BOARD_HAUPPAUGE_HVR1210, + }, { + .subvendor = 0x0070, + .subdevice = 0x22f5, + .card = CX23885_BOARD_HAUPPAUGE_HVR1210, /* HVR1215 */ + }, { .subvendor = 0x14f1, .subdevice = 0x8651, .card = CX23885_BOARD_MYGICA_X8506, @@ -586,6 +636,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) case 79101: /* WinTV-HVR1250 (PCIe, Retail, IR, half height, ATSC and Basic analog */ + case 79501: + /* WinTV-HVR1250 (PCIe, No IR, half height, + ATSC [at least] and Basic analog) */ case 79561: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */ @@ -919,9 +972,37 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) int cx23885_ir_init(struct cx23885_dev *dev) { + static struct v4l2_subdev_io_pin_config ir_rxtx_pin_cfg[] = { + { + .flags = V4L2_SUBDEV_IO_PIN_INPUT, + .pin = CX23885_PIN_IR_RX_GPIO19, + .function = CX23885_PAD_IR_RX, + .value = 0, + .strength = CX25840_PIN_DRIVE_MEDIUM, + }, { + .flags = V4L2_SUBDEV_IO_PIN_OUTPUT, + .pin = CX23885_PIN_IR_TX_GPIO20, + .function = CX23885_PAD_IR_TX, + .value = 0, + .strength = CX25840_PIN_DRIVE_MEDIUM, + } + }; + const size_t ir_rxtx_pin_cfg_count = ARRAY_SIZE(ir_rxtx_pin_cfg); + + static struct v4l2_subdev_io_pin_config ir_rx_pin_cfg[] = { + { + .flags = V4L2_SUBDEV_IO_PIN_INPUT, + .pin = CX23885_PIN_IR_RX_GPIO19, + .function = CX23885_PAD_IR_RX, + .value = 0, + .strength = CX25840_PIN_DRIVE_MEDIUM, + } + }; + const size_t ir_rx_pin_cfg_count = ARRAY_SIZE(ir_rx_pin_cfg); + + struct v4l2_subdev_ir_parameters params; int ret = 0; switch (dev->board) { - case CX23885_BOARD_HAUPPAUGE_HVR1250: case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: case CX23885_BOARD_HAUPPAUGE_HVR1800: @@ -939,7 +1020,41 @@ int cx23885_ir_init(struct cx23885_dev *dev) if (ret) break; dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR); - dev->pci_irqmask |= PCI_MSK_IR; + v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config, + ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg); + /* + * For these boards we need to invert the Tx output via the + * IR controller to have the LED off while idle + */ + v4l2_subdev_call(dev->sd_ir, ir, tx_g_parameters, ¶ms); + params.enable = false; + params.shutdown = false; + params.invert_level = true; + v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, ¶ms); + params.shutdown = true; + v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, ¶ms); + break; + case CX23885_BOARD_TEVII_S470: + if (!enable_885_ir) + break; + dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE); + if (dev->sd_ir == NULL) { + ret = -ENODEV; + break; + } + v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config, + ir_rx_pin_cfg_count, ir_rx_pin_cfg); + break; + case CX23885_BOARD_HAUPPAUGE_HVR1250: + if (!enable_885_ir) + break; + dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE); + if (dev->sd_ir == NULL) { + ret = -ENODEV; + break; + } + v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config, + ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg); break; case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: request_module("ir-kbd-i2c"); @@ -954,11 +1069,16 @@ void cx23885_ir_fini(struct cx23885_dev *dev) switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1290: - dev->pci_irqmask &= ~PCI_MSK_IR; - cx_clear(PCI_INT_MSK, PCI_MSK_IR); + cx23885_irq_remove(dev, PCI_MSK_IR); cx23888_ir_remove(dev); dev->sd_ir = NULL; break; + case CX23885_BOARD_TEVII_S470: + case CX23885_BOARD_HAUPPAUGE_HVR1250: + cx23885_irq_remove(dev, PCI_MSK_AV_CORE); + /* sd_ir is a duplicate pointer to the AV Core, just clear it */ + dev->sd_ir = NULL; + break; } } @@ -967,8 +1087,13 @@ void cx23885_ir_pci_int_enable(struct cx23885_dev *dev) switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1290: - if (dev->sd_ir && (dev->pci_irqmask & PCI_MSK_IR)) - cx_set(PCI_INT_MSK, PCI_MSK_IR); + if (dev->sd_ir) + cx23885_irq_add_enable(dev, PCI_MSK_IR); + break; + case CX23885_BOARD_TEVII_S470: + case CX23885_BOARD_HAUPPAUGE_HVR1250: + if (dev->sd_ir) + cx23885_irq_add_enable(dev, PCI_MSK_AV_CORE); break; } } @@ -988,6 +1113,13 @@ void cx23885_card_setup(struct cx23885_dev *dev) switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1250: + if (dev->i2c_bus[0].i2c_rc == 0) { + if (eeprom[0x80] != 0x84) + hauppauge_eeprom(dev, eeprom+0xc0); + else + hauppauge_eeprom(dev, eeprom+0x80); + } + break; case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: case CX23885_BOARD_HAUPPAUGE_HVR1400: @@ -1096,6 +1228,11 @@ void cx23885_card_setup(struct cx23885_dev *dev) * loaded, ensure this happens. */ switch (dev->board) { + case CX23885_BOARD_TEVII_S470: + case CX23885_BOARD_HAUPPAUGE_HVR1250: + /* Currently only enabled for the integrated IR controller */ + if (!enable_885_ir) + break; case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1800lp: case CX23885_BOARD_HAUPPAUGE_HVR1700: @@ -1111,7 +1248,10 @@ void cx23885_card_setup(struct cx23885_dev *dev) dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_bus[2].i2c_adap, "cx25840", "cx25840", 0x88 >> 1, NULL); - v4l2_subdev_call(dev->sd_cx25840, core, load_fw); + if (dev->sd_cx25840) { + dev->sd_cx25840->grp_id = CX23885_HW_AV_CORE; + v4l2_subdev_call(dev->sd_cx25840, core, load_fw); + } break; } diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c index 0dde57e96d3..f6b62e7398a 100644 --- a/drivers/media/video/cx23885/cx23885-core.c +++ b/drivers/media/video/cx23885/cx23885-core.c @@ -34,6 +34,7 @@ #include "cimax2.h" #include "cx23888-ir.h" #include "cx23885-ir.h" +#include "cx23885-av.h" #include "cx23885-input.h" MODULE_DESCRIPTION("Driver for cx23885 based TV cards"); @@ -299,6 +300,83 @@ static struct sram_channel cx23887_sram_channels[] = { }, }; +void cx23885_irq_add(struct cx23885_dev *dev, u32 mask) +{ + unsigned long flags; + spin_lock_irqsave(&dev->pci_irqmask_lock, flags); + + dev->pci_irqmask |= mask; + + spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags); +} + +void cx23885_irq_add_enable(struct cx23885_dev *dev, u32 mask) +{ + unsigned long flags; + spin_lock_irqsave(&dev->pci_irqmask_lock, flags); + + dev->pci_irqmask |= mask; + cx_set(PCI_INT_MSK, mask); + + spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags); +} + +void cx23885_irq_enable(struct cx23885_dev *dev, u32 mask) +{ + u32 v; + unsigned long flags; + spin_lock_irqsave(&dev->pci_irqmask_lock, flags); + + v = mask & dev->pci_irqmask; + if (v) + cx_set(PCI_INT_MSK, v); + + spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags); +} + +static inline void cx23885_irq_enable_all(struct cx23885_dev *dev) +{ + cx23885_irq_enable(dev, 0xffffffff); +} + +void cx23885_irq_disable(struct cx23885_dev *dev, u32 mask) +{ + unsigned long flags; + spin_lock_irqsave(&dev->pci_irqmask_lock, flags); + + cx_clear(PCI_INT_MSK, mask); + + spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags); +} + +static inline void cx23885_irq_disable_all(struct cx23885_dev *dev) +{ + cx23885_irq_disable(dev, 0xffffffff); +} + +void cx23885_irq_remove(struct cx23885_dev *dev, u32 mask) +{ + unsigned long flags; + spin_lock_irqsave(&dev->pci_irqmask_lock, flags); + + dev->pci_irqmask &= ~mask; + cx_clear(PCI_INT_MSK, mask); + + spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags); +} + +static u32 cx23885_irq_get_mask(struct cx23885_dev *dev) +{ + u32 v; + unsigned long flags; + spin_lock_irqsave(&dev->pci_irqmask_lock, flags); + + v = cx_read(PCI_INT_MSK); + + spin_unlock_irqrestore(&dev->pci_irqmask_lock, flags); + return v; +} + static int cx23885_risc_decode(u32 risc) { static char *instr[16] = { @@ -548,7 +626,7 @@ static void cx23885_shutdown(struct cx23885_dev *dev) cx_write(UART_CTL, 0); /* Disable Interrupts */ - cx_write(PCI_INT_MSK, 0); + cx23885_irq_disable_all(dev); cx_write(VID_A_INT_MSK, 0); cx_write(VID_B_INT_MSK, 0); cx_write(VID_C_INT_MSK, 0); @@ -774,6 +852,8 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) { int i; + spin_lock_init(&dev->pci_irqmask_lock); + mutex_init(&dev->lock); mutex_init(&dev->gpio_lock); @@ -820,9 +900,9 @@ static int cx23885_dev_setup(struct cx23885_dev *dev) dev->pci_bus = dev->pci->bus->number; dev->pci_slot = PCI_SLOT(dev->pci->devfn); - dev->pci_irqmask = 0x001f00; + cx23885_irq_add(dev, 0x001f00); if (cx23885_boards[dev->board].cimax > 0) - dev->pci_irqmask |= 0x01800000; /* for CiMaxes */ + cx23885_irq_add(dev, 0x01800000); /* for CiMaxes */ /* External Master 1 Bus */ dev->i2c_bus[0].nr = 0; @@ -1142,7 +1222,7 @@ void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf) BUG_ON(in_interrupt()); videobuf_waiton(&buf->vb, 0, 0); - videobuf_dma_unmap(q, dma); + videobuf_dma_unmap(q->dev, dma); videobuf_dma_free(dma); btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); buf->vb.state = VIDEOBUF_NEEDS_INIT; @@ -1156,7 +1236,7 @@ static void cx23885_tsport_reg_dump(struct cx23885_tsport *port) dprintk(1, "%s() DEV_CNTRL2 0x%08X\n", __func__, cx_read(DEV_CNTRL2)); dprintk(1, "%s() PCI_INT_MSK 0x%08X\n", __func__, - cx_read(PCI_INT_MSK)); + cx23885_irq_get_mask(dev)); dprintk(1, "%s() AUD_INT_INT_MSK 0x%08X\n", __func__, cx_read(AUDIO_INT_INT_MSK)); dprintk(1, "%s() AUD_INT_DMA_CTL 0x%08X\n", __func__, @@ -1292,7 +1372,8 @@ static int cx23885_start_dma(struct cx23885_tsport *port, dprintk(1, "%s() enabling TS int's and DMA\n", __func__); cx_set(port->reg_ts_int_msk, port->ts_int_msk_val); cx_set(port->reg_dma_ctl, port->dma_ctl_val); - cx_set(PCI_INT_MSK, dev->pci_irqmask | port->pci_irqmask); + cx23885_irq_add(dev, port->pci_irqmask); + cx23885_irq_enable_all(dev); break; default: BUG(); @@ -1650,10 +1731,10 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) u32 ts1_status, ts1_mask; u32 ts2_status, ts2_mask; int vida_count = 0, ts1_count = 0, ts2_count = 0, handled = 0; - bool ir_handled = false; + bool subdev_handled; pci_status = cx_read(PCI_INT_STAT); - pci_mask = cx_read(PCI_INT_MSK); + pci_mask = cx23885_irq_get_mask(dev); vida_status = cx_read(VID_A_INT_STAT); vida_mask = cx_read(VID_A_INT_MSK); ts1_status = cx_read(VID_B_INT_STAT); @@ -1681,7 +1762,7 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) PCI_MSK_VID_C | PCI_MSK_VID_B | PCI_MSK_VID_A | PCI_MSK_AUD_INT | PCI_MSK_AUD_EXT | PCI_MSK_GPIO0 | PCI_MSK_GPIO1 | - PCI_MSK_IR)) { + PCI_MSK_AV_CORE | PCI_MSK_IR)) { if (pci_status & PCI_MSK_RISC_RD) dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n", @@ -1731,6 +1812,10 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n", PCI_MSK_GPIO1); + if (pci_status & PCI_MSK_AV_CORE) + dprintk(7, " (PCI_MSK_AV_CORE 0x%08x)\n", + PCI_MSK_AV_CORE); + if (pci_status & PCI_MSK_IR) dprintk(7, " (PCI_MSK_IR 0x%08x)\n", PCI_MSK_IR); @@ -1765,12 +1850,22 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id) handled += cx23885_video_irq(dev, vida_status); if (pci_status & PCI_MSK_IR) { - v4l2_subdev_call(dev->sd_ir, ir, interrupt_service_routine, - pci_status, &ir_handled); - if (ir_handled) + subdev_handled = false; + v4l2_subdev_call(dev->sd_ir, core, interrupt_service_routine, + pci_status, &subdev_handled); + if (subdev_handled) handled++; } + if ((pci_status & pci_mask) & PCI_MSK_AV_CORE) { + cx23885_irq_disable(dev, PCI_MSK_AV_CORE); + if (!schedule_work(&dev->cx25840_work)) + printk(KERN_ERR "%s: failed to set up deferred work for" + " AV Core/IR interrupt. Interrupt is disabled" + " and won't be re-enabled\n", dev->name); + handled++; + } + if (handled) cx_write(PCI_INT_STAT, pci_status); out: @@ -1788,11 +1883,11 @@ static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd, dev = to_cx23885(sd->v4l2_dev); switch (notification) { - case V4L2_SUBDEV_IR_RX_NOTIFY: /* Called in an IRQ context */ + case V4L2_SUBDEV_IR_RX_NOTIFY: /* Possibly called in an IRQ context */ if (sd == dev->sd_ir) cx23885_ir_rx_v4l2_dev_notify(sd, *(u32 *)arg); break; - case V4L2_SUBDEV_IR_TX_NOTIFY: /* Called in an IRQ context */ + case V4L2_SUBDEV_IR_TX_NOTIFY: /* Possibly called in an IRQ context */ if (sd == dev->sd_ir) cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg); break; @@ -1801,6 +1896,7 @@ static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd, static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev) { + INIT_WORK(&dev->cx25840_work, cx23885_av_work_handler); INIT_WORK(&dev->ir_rx_work, cx23885_ir_rx_work_handler); INIT_WORK(&dev->ir_tx_work, cx23885_ir_tx_work_handler); dev->v4l2_dev.notify = cx23885_v4l2_dev_notify; @@ -1953,8 +2049,12 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, goto fail_irq; } - err = request_irq(pci_dev->irq, cx23885_irq, - IRQF_SHARED | IRQF_DISABLED, dev->name, dev); + if (!pci_enable_msi(pci_dev)) + err = request_irq(pci_dev->irq, cx23885_irq, + IRQF_DISABLED, dev->name, dev); + else + err = request_irq(pci_dev->irq, cx23885_irq, + IRQF_SHARED | IRQF_DISABLED, dev->name, dev); if (err < 0) { printk(KERN_ERR "%s: can't get IRQ %d\n", dev->name, pci_dev->irq); @@ -1963,7 +2063,7 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev, switch (dev->board) { case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: - cx_set(PCI_INT_MSK, 0x01800000); /* for NetUP */ + cx23885_irq_add_enable(dev, 0x01800000); /* for NetUP */ break; } @@ -2000,6 +2100,7 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev) /* unregister stuff */ free_irq(pci_dev->irq, dev); + pci_disable_msi(pci_dev); cx23885_dev_unregister(dev); v4l2_device_unregister(v4l2_dev); diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 0a199d774d9..3d70af28388 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -991,7 +991,7 @@ static int dvb_register(struct cx23885_tsport *port) ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port, &dev->pci->dev, adapter_nr, 0, cx23885_dvb_fe_ioctl_override); - if (!ret) + if (ret) return ret; /* init CI & MAC */ diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index d4746e06451..ed3d8f55029 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -99,7 +99,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, if (!i2c_wait_done(i2c_adap)) return -EIO; if (!i2c_slave_did_ack(i2c_adap)) - return -EIO; + return -ENXIO; dprintk(1, "%s() returns 0\n", __func__); return 0; @@ -120,11 +120,12 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, cx_write(bus->reg_wdata, wdata); cx_write(bus->reg_ctrl, ctrl); - retval = i2c_wait_done(i2c_adap); - if (retval < 0) - goto err; - if (retval == 0) + if (!i2c_wait_done(i2c_adap)) goto eio; + if (!i2c_slave_did_ack(i2c_adap)) { + retval = -ENXIO; + goto err; + } if (i2c_debug) { printk(" <W %02x %02x", msg->addr << 1, msg->buf[0]); if (!(ctrl & I2C_NOSTOP)) @@ -145,10 +146,7 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap, cx_write(bus->reg_wdata, wdata); cx_write(bus->reg_ctrl, ctrl); - retval = i2c_wait_done(i2c_adap); - if (retval < 0) - goto err; - if (retval == 0) + if (!i2c_wait_done(i2c_adap)) goto eio; if (i2c_debug) { dprintk(1, " %02x", msg->buf[cnt]); @@ -185,7 +183,7 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, if (!i2c_wait_done(i2c_adap)) return -EIO; if (!i2c_slave_did_ack(i2c_adap)) - return -EIO; + return -ENXIO; dprintk(1, "%s() returns 0\n", __func__); @@ -209,11 +207,12 @@ static int i2c_readbytes(struct i2c_adapter *i2c_adap, cx_write(bus->reg_addr, msg->addr << 25); cx_write(bus->reg_ctrl, ctrl); - retval = i2c_wait_done(i2c_adap); - if (retval < 0) - goto err; - if (retval == 0) + if (!i2c_wait_done(i2c_adap)) goto eio; + if (cnt == 0 && !i2c_slave_did_ack(i2c_adap)) { + retval = -ENXIO; + goto err; + } msg->buf[cnt] = cx_read(bus->reg_rdata) & 0xff; if (i2c_debug) { dprintk(1, " %02x", msg->buf[cnt]); @@ -365,17 +364,10 @@ int cx23885_i2c_register(struct cx23885_i2c *bus) memset(&info, 0, sizeof(struct i2c_board_info)); strlcpy(info.type, "ir_video", I2C_NAME_SIZE); - /* - * We can't call i2c_new_probed_device() because it uses - * quick writes for probing and the IR receiver device only - * replies to reads. - */ - if (i2c_smbus_xfer(&bus->i2c_adap, addr_list[0], 0, - I2C_SMBUS_READ, 0, I2C_SMBUS_QUICK, - NULL) >= 0) { - info.addr = addr_list[0]; - i2c_new_device(&bus->i2c_adap, &info); - } + /* Use quick read command for probe, some IR chips don't + * support writes */ + i2c_new_probed_device(&bus->i2c_adap, &info, addr_list, + i2c_probe_func_quick_read); } return bus->i2c_rc; diff --git a/drivers/media/video/cx23885/cx23885-input.c b/drivers/media/video/cx23885/cx23885-input.c index 5de6ba98f7a..bb61870b8d6 100644 --- a/drivers/media/video/cx23885/cx23885-input.c +++ b/drivers/media/video/cx23885/cx23885-input.c @@ -37,161 +37,41 @@ #include <linux/input.h> #include <linux/slab.h> -#include <media/ir-common.h> +#include <media/ir-core.h> #include <media/v4l2-subdev.h> #include "cx23885.h" -#define RC5_BITS 14 -#define RC5_HALF_BITS (2*RC5_BITS) -#define RC5_HALF_BITS_MASK ((1 << RC5_HALF_BITS) - 1) - -#define RC5_START_BITS_NORMAL 0x3 /* Command range 0 - 63 */ -#define RC5_START_BITS_EXTENDED 0x2 /* Command range 64 - 127 */ - -#define RC5_EXTENDED_COMMAND_OFFSET 64 - #define MODULE_NAME "cx23885" -static inline unsigned int rc5_command(u32 rc5_baseband) -{ - return RC5_INSTR(rc5_baseband) + - ((RC5_START(rc5_baseband) == RC5_START_BITS_EXTENDED) - ? RC5_EXTENDED_COMMAND_OFFSET : 0); -} - -static void cx23885_input_process_raw_rc5(struct cx23885_dev *dev) -{ - struct card_ir *ir_input = dev->ir_input; - unsigned int code, command; - u32 rc5; - - /* Ignore codes that are too short to be valid RC-5 */ - if (ir_input->last_bit < (RC5_HALF_BITS - 1)) - return; - - /* The library has the manchester coding backwards; XOR to adapt. */ - code = (ir_input->code & RC5_HALF_BITS_MASK) ^ RC5_HALF_BITS_MASK; - rc5 = ir_rc5_decode(code); - - switch (RC5_START(rc5)) { - case RC5_START_BITS_NORMAL: - break; - case RC5_START_BITS_EXTENDED: - /* Don't allow if the remote only emits standard commands */ - if (ir_input->start == RC5_START_BITS_NORMAL) - return; - break; - default: - return; - } - - if (ir_input->addr != RC5_ADDR(rc5)) - return; - - /* Don't generate a keypress for RC-5 auto-repeated keypresses */ - command = rc5_command(rc5); - if (RC5_TOGGLE(rc5) != RC5_TOGGLE(ir_input->last_rc5) || - command != rc5_command(ir_input->last_rc5) || - /* Catch T == 0, CMD == 0 (e.g. '0') as first keypress after init */ - RC5_START(ir_input->last_rc5) == 0) { - /* This keypress is differnet: not an auto repeat */ - ir_input_nokey(ir_input->dev, &ir_input->ir); - ir_input_keydown(ir_input->dev, &ir_input->ir, command); - } - ir_input->last_rc5 = rc5; - - /* Schedule when we should do the key up event: ir_input_nokey() */ - mod_timer(&ir_input->timer_keyup, - jiffies + msecs_to_jiffies(ir_input->rc5_key_timeout)); -} - -static void cx23885_input_next_pulse_width_rc5(struct cx23885_dev *dev, - u32 ns_pulse) -{ - const int rc5_quarterbit_ns = 444444; /* 32 cycles/36 kHz/2 = 444 us */ - struct card_ir *ir_input = dev->ir_input; - int i, level, quarterbits, halfbits; - - if (!ir_input->active) { - ir_input->active = 1; - /* assume an initial space that we may not detect or measure */ - ir_input->code = 0; - ir_input->last_bit = 0; - } - - if (ns_pulse == V4L2_SUBDEV_IR_PULSE_RX_SEQ_END) { - ir_input->last_bit++; /* Account for the final space */ - ir_input->active = 0; - cx23885_input_process_raw_rc5(dev); - return; - } - - level = (ns_pulse & V4L2_SUBDEV_IR_PULSE_LEVEL_MASK) ? 1 : 0; - - /* Skip any leading space to sync to the start bit */ - if (ir_input->last_bit == 0 && level == 0) - return; - - /* - * With valid RC-5 we can get up to two consecutive half-bits in a - * single pulse measurment. Experiments have shown that the duration - * of a half-bit can vary. Make sure we always end up with an even - * number of quarter bits at the same level (mark or space). - */ - ns_pulse &= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; - quarterbits = ns_pulse / rc5_quarterbit_ns; - if (quarterbits & 1) - quarterbits++; - halfbits = quarterbits / 2; - - for (i = 0; i < halfbits; i++) { - ir_input->last_bit++; - ir_input->code |= (level << ir_input->last_bit); - - if (ir_input->last_bit >= RC5_HALF_BITS-1) { - ir_input->active = 0; - cx23885_input_process_raw_rc5(dev); - /* - * If level is 1, a leading mark is invalid for RC5. - * If level is 0, we scan past extra intial space. - * Either way we don't want to reactivate collecting - * marks or spaces here with any left over half-bits. - */ - break; - } - } -} - -static void cx23885_input_process_pulse_widths_rc5(struct cx23885_dev *dev, - bool add_eom) +static void cx23885_input_process_measurements(struct cx23885_dev *dev, + bool overrun) { - struct card_ir *ir_input = dev->ir_input; - struct ir_input_state *ir_input_state = &ir_input->ir; + struct cx23885_kernel_ir *kernel_ir = dev->kernel_ir; - u32 ns_pulse[RC5_HALF_BITS+1]; - ssize_t num = 0; + ssize_t num; int count, i; + bool handle = false; + struct ir_raw_event ir_core_event[64]; do { - v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ns_pulse, - sizeof(ns_pulse), &num); + num = 0; + v4l2_subdev_call(dev->sd_ir, ir, rx_read, (u8 *) ir_core_event, + sizeof(ir_core_event), &num); - count = num / sizeof(u32); + count = num / sizeof(struct ir_raw_event); - /* Append an end of Rx seq, if the caller requested */ - if (add_eom && count < ARRAY_SIZE(ns_pulse)) { - ns_pulse[count] = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END; - count++; + for (i = 0; i < count; i++) { + ir_raw_event_store(kernel_ir->inp_dev, + &ir_core_event[i]); + handle = true; } - - /* Just drain the Rx FIFO, if we're called, but not RC-5 */ - if (ir_input_state->ir_type != IR_TYPE_RC5) - continue; - - for (i = 0; i < count; i++) - cx23885_input_next_pulse_width_rc5(dev, ns_pulse[i]); } while (num != 0); + + if (overrun) + ir_raw_event_reset(kernel_ir->inp_dev); + else if (handle) + ir_raw_event_handle(kernel_ir->inp_dev); } void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) @@ -205,8 +85,10 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1290: + case CX23885_BOARD_TEVII_S470: + case CX23885_BOARD_HAUPPAUGE_HVR1250: /* - * The only board we handle right now. However other boards + * The only boards we handle right now. However other boards * using the CX2388x integrated IR controller should be similar */ break; @@ -230,7 +112,7 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) } if (data_available) - cx23885_input_process_pulse_widths_rc5(dev, overrun); + cx23885_input_process_measurements(dev, overrun); if (overrun) { /* If there was a FIFO overrun, clear & restart the device */ @@ -241,38 +123,20 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events) } } -static void cx23885_input_ir_start(struct cx23885_dev *dev) +static int cx23885_input_ir_start(struct cx23885_dev *dev) { - struct card_ir *ir_input = dev->ir_input; - struct ir_input_state *ir_input_state = &ir_input->ir; struct v4l2_subdev_ir_parameters params; if (dev->sd_ir == NULL) - return; + return -ENODEV; atomic_set(&dev->ir_input_stopping, 0); - /* keyup timer set up, if needed */ - switch (dev->board) { - case CX23885_BOARD_HAUPPAUGE_HVR1850: - case CX23885_BOARD_HAUPPAUGE_HVR1290: - setup_timer(&ir_input->timer_keyup, - ir_rc5_timer_keyup, /* Not actually RC-5 specific */ - (unsigned long) ir_input); - if (ir_input_state->ir_type == IR_TYPE_RC5) { - /* - * RC-5 repeats a held key every - * 64 bits * (2 * 32/36000) sec/bit = 113.778 ms - */ - ir_input->rc5_key_timeout = 115; - } - break; - } - v4l2_subdev_call(dev->sd_ir, ir, rx_g_parameters, ¶ms); switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1290: + case CX23885_BOARD_HAUPPAUGE_HVR1250: /* * The IR controller on this board only returns pulse widths. * Any other mode setting will fail to set up the device. @@ -295,15 +159,56 @@ static void cx23885_input_ir_start(struct cx23885_dev *dev) * mark is received as low logic level; * falling edges are detected as rising edges; etc. */ - params.invert = true; + params.invert_level = true; + break; + case CX23885_BOARD_TEVII_S470: + /* + * The IR controller on this board only returns pulse widths. + * Any other mode setting will fail to set up the device. + */ + params.mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; + params.enable = true; + params.interrupt_enable = true; + params.shutdown = false; + + /* Setup for a standard NEC protocol */ + params.carrier_freq = 37917; /* Hz, 455 kHz/12 for NEC */ + params.carrier_range_lower = 33000; /* Hz */ + params.carrier_range_upper = 43000; /* Hz */ + params.duty_cycle = 33; /* percent, 33 percent for NEC */ + + /* + * NEC max pulse width: (64/3)/(455 kHz/12) * 16 nec_units + * (64/3)/(455 kHz/12) * 16 nec_units * 1.375 = 12378022 ns + */ + params.max_pulse_width = 12378022; /* ns */ + + /* + * NEC noise filter min width: (64/3)/(455 kHz/12) * 1 nec_unit + * (64/3)/(455 kHz/12) * 1 nec_units * 0.625 = 351648 ns + */ + params.noise_filter_min_width = 351648; /* ns */ + + params.modulation = false; + params.invert_level = true; break; } v4l2_subdev_call(dev->sd_ir, ir, rx_s_parameters, ¶ms); + return 0; +} + +static int cx23885_input_ir_open(void *priv) +{ + struct cx23885_kernel_ir *kernel_ir = priv; + + if (kernel_ir->cx == NULL) + return -ENODEV; + + return cx23885_input_ir_start(kernel_ir->cx); } static void cx23885_input_ir_stop(struct cx23885_dev *dev) { - struct card_ir *ir_input = dev->ir_input; struct v4l2_subdev_ir_parameters params; if (dev->sd_ir == NULL) @@ -327,21 +232,26 @@ static void cx23885_input_ir_stop(struct cx23885_dev *dev) } flush_scheduled_work(); +} - switch (dev->board) { - case CX23885_BOARD_HAUPPAUGE_HVR1850: - case CX23885_BOARD_HAUPPAUGE_HVR1290: - del_timer_sync(&ir_input->timer_keyup); - break; - } +static void cx23885_input_ir_close(void *priv) +{ + struct cx23885_kernel_ir *kernel_ir = priv; + + if (kernel_ir->cx != NULL) + cx23885_input_ir_stop(kernel_ir->cx); } int cx23885_input_init(struct cx23885_dev *dev) { - struct card_ir *ir; - struct input_dev *input_dev; - char *ir_codes = NULL; - int ir_type, ir_addr, ir_start; + struct cx23885_kernel_ir *kernel_ir; + struct input_dev *inp_dev; + struct ir_dev_props *props; + + char *rc_map; + enum rc_driver_type driver_type; + unsigned long allowed_protos; + int ret; /* @@ -354,53 +264,67 @@ int cx23885_input_init(struct cx23885_dev *dev) switch (dev->board) { case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1290: - /* Parameters for the grey Hauppauge remote for the HVR-1850 */ - ir_codes = RC_MAP_HAUPPAUGE_NEW; - ir_type = IR_TYPE_RC5; - ir_addr = 0x1e; /* RC-5 system bits emitted by the remote */ - ir_start = RC5_START_BITS_NORMAL; /* A basic RC-5 remote */ + case CX23885_BOARD_HAUPPAUGE_HVR1250: + /* Integrated CX2388[58] IR controller */ + driver_type = RC_DRIVER_IR_RAW; + allowed_protos = IR_TYPE_ALL; + /* The grey Hauppauge RC-5 remote */ + rc_map = RC_MAP_RC5_HAUPPAUGE_NEW; break; - } - if (ir_codes == NULL) + case CX23885_BOARD_TEVII_S470: + /* Integrated CX23885 IR controller */ + driver_type = RC_DRIVER_IR_RAW; + allowed_protos = IR_TYPE_ALL; + /* A guess at the remote */ + rc_map = RC_MAP_TEVII_NEC; + break; + default: return -ENODEV; - - ir = kzalloc(sizeof(*ir), GFP_KERNEL); - input_dev = input_allocate_device(); - if (!ir || !input_dev) { - ret = -ENOMEM; - goto err_out_free; } - ir->dev = input_dev; - ir->addr = ir_addr; - ir->start = ir_start; + /* cx23885 board instance kernel IR state */ + kernel_ir = kzalloc(sizeof(struct cx23885_kernel_ir), GFP_KERNEL); + if (kernel_ir == NULL) + return -ENOMEM; - /* init input device */ - snprintf(ir->name, sizeof(ir->name), "cx23885 IR (%s)", - cx23885_boards[dev->board].name); - snprintf(ir->phys, sizeof(ir->phys), "pci-%s/ir0", pci_name(dev->pci)); + kernel_ir->cx = dev; + kernel_ir->name = kasprintf(GFP_KERNEL, "cx23885 IR (%s)", + cx23885_boards[dev->board].name); + kernel_ir->phys = kasprintf(GFP_KERNEL, "pci-%s/ir0", + pci_name(dev->pci)); - ret = ir_input_init(input_dev, &ir->ir, ir_type); - if (ret < 0) + /* input device */ + inp_dev = input_allocate_device(); + if (inp_dev == NULL) { + ret = -ENOMEM; goto err_out_free; + } - input_dev->name = ir->name; - input_dev->phys = ir->phys; - input_dev->id.bustype = BUS_PCI; - input_dev->id.version = 1; + kernel_ir->inp_dev = inp_dev; + inp_dev->name = kernel_ir->name; + inp_dev->phys = kernel_ir->phys; + inp_dev->id.bustype = BUS_PCI; + inp_dev->id.version = 1; if (dev->pci->subsystem_vendor) { - input_dev->id.vendor = dev->pci->subsystem_vendor; - input_dev->id.product = dev->pci->subsystem_device; + inp_dev->id.vendor = dev->pci->subsystem_vendor; + inp_dev->id.product = dev->pci->subsystem_device; } else { - input_dev->id.vendor = dev->pci->vendor; - input_dev->id.product = dev->pci->device; + inp_dev->id.vendor = dev->pci->vendor; + inp_dev->id.product = dev->pci->device; } - input_dev->dev.parent = &dev->pci->dev; - - dev->ir_input = ir; - cx23885_input_ir_start(dev); - - ret = ir_input_register(ir->dev, ir_codes, NULL, MODULE_NAME); + inp_dev->dev.parent = &dev->pci->dev; + + /* kernel ir device properties */ + props = &kernel_ir->props; + props->driver_type = driver_type; + props->allowed_protos = allowed_protos; + props->priv = kernel_ir; + props->open = cx23885_input_ir_open; + props->close = cx23885_input_ir_close; + + /* Go */ + dev->kernel_ir = kernel_ir; + ret = ir_input_register(inp_dev, rc_map, props, MODULE_NAME); if (ret) goto err_out_stop; @@ -408,9 +332,12 @@ int cx23885_input_init(struct cx23885_dev *dev) err_out_stop: cx23885_input_ir_stop(dev); - dev->ir_input = NULL; + dev->kernel_ir = NULL; + /* TODO: double check clean-up of kernel_ir->inp_dev */ err_out_free: - kfree(ir); + kfree(kernel_ir->phys); + kfree(kernel_ir->name); + kfree(kernel_ir); return ret; } @@ -419,9 +346,11 @@ void cx23885_input_fini(struct cx23885_dev *dev) /* Always stop the IR hardware from generating interrupts */ cx23885_input_ir_stop(dev); - if (dev->ir_input == NULL) + if (dev->kernel_ir == NULL) return; - ir_input_unregister(dev->ir_input->dev); - kfree(dev->ir_input); - dev->ir_input = NULL; + ir_input_unregister(dev->kernel_ir->inp_dev); + kfree(dev->kernel_ir->phys); + kfree(dev->kernel_ir->name); + kfree(dev->kernel_ir); + dev->kernel_ir = NULL; } diff --git a/drivers/media/video/cx23885/cx23885-ir.c b/drivers/media/video/cx23885/cx23885-ir.c index 9a677eb080a..7125247dd25 100644 --- a/drivers/media/video/cx23885/cx23885-ir.c +++ b/drivers/media/video/cx23885/cx23885-ir.c @@ -53,7 +53,7 @@ void cx23885_ir_rx_work_handler(struct work_struct *work) if (events == 0) return; - if (dev->ir_input) + if (dev->kernel_ir) cx23885_input_rx_work_handler(dev, events); } @@ -72,7 +72,7 @@ void cx23885_ir_tx_work_handler(struct work_struct *work) } -/* Called in an IRQ context */ +/* Possibly called in an IRQ context */ void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events) { struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev); @@ -86,10 +86,18 @@ void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events) set_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications); if (events & V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN) set_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications); - schedule_work(&dev->ir_rx_work); + + /* + * For the integrated AV core, we are already in a workqueue context. + * For the CX23888 integrated IR, we are in an interrupt context. + */ + if (sd == dev->sd_cx25840) + cx23885_ir_rx_work_handler(&dev->ir_rx_work); + else + schedule_work(&dev->ir_rx_work); } -/* Called in an IRQ context */ +/* Possibly called in an IRQ context */ void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events) { struct cx23885_dev *dev = to_cx23885(sd->v4l2_dev); @@ -97,5 +105,13 @@ void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events) if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ) set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications); - schedule_work(&dev->ir_tx_work); + + /* + * For the integrated AV core, we are already in a workqueue context. + * For the CX23888 integrated IR, we are in an interrupt context. + */ + if (sd == dev->sd_cx25840) + cx23885_ir_tx_work_handler(&dev->ir_tx_work); + else + schedule_work(&dev->ir_tx_work); } diff --git a/drivers/media/video/cx23885/cx23885-reg.h b/drivers/media/video/cx23885/cx23885-reg.h index c0bc9a06895..a28772db11f 100644 --- a/drivers/media/video/cx23885/cx23885-reg.h +++ b/drivers/media/video/cx23885/cx23885-reg.h @@ -213,6 +213,7 @@ Channel manager Data Structure entry = 20 DWORD #define DEV_CNTRL2 0x00040000 #define PCI_MSK_IR (1 << 28) +#define PCI_MSK_AV_CORE (1 << 27) #define PCI_MSK_GPIO1 (1 << 24) #define PCI_MSK_GPIO0 (1 << 23) #define PCI_MSK_APB_DMA (1 << 12) diff --git a/drivers/media/video/cx23885/cx23885-vbi.c b/drivers/media/video/cx23885/cx23885-vbi.c index 708a8c766d1..c0b60382ad1 100644 --- a/drivers/media/video/cx23885/cx23885-vbi.c +++ b/drivers/media/video/cx23885/cx23885-vbi.c @@ -74,7 +74,7 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev, q->count = 1; /* enable irqs */ - cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | 0x01); + cx23885_irq_add_enable(dev, 0x01); cx_set(VID_A_INT_MSK, 0x000022); /* start dma */ diff --git a/drivers/media/video/cx23885/cx23885-video.c b/drivers/media/video/cx23885/cx23885-video.c index 4e44dcda387..da66e5f8d91 100644 --- a/drivers/media/video/cx23885/cx23885-video.c +++ b/drivers/media/video/cx23885/cx23885-video.c @@ -441,7 +441,7 @@ static int cx23885_start_video_dma(struct cx23885_dev *dev, q->count = 1; /* enable irq */ - cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | 0x01); + cx23885_irq_add_enable(dev, 0x01); cx_set(VID_A_INT_MSK, 0x000011); /* start dma */ @@ -1205,6 +1205,21 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) return 0; } +static int vidioc_log_status(struct file *file, void *priv) +{ + struct cx23885_fh *fh = priv; + struct cx23885_dev *dev = fh->dev; + + printk(KERN_INFO + "%s/0: ============ START LOG STATUS ============\n", + dev->name); + call_all(dev, core, log_status); + printk(KERN_INFO + "%s/0: ============= END LOG STATUS =============\n", + dev->name); + return 0; +} + static int vidioc_queryctrl(struct file *file, void *priv, struct v4l2_queryctrl *qctrl) { @@ -1410,6 +1425,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = { .vidioc_enum_input = vidioc_enum_input, .vidioc_g_input = vidioc_g_input, .vidioc_s_input = vidioc_s_input, + .vidioc_log_status = vidioc_log_status, .vidioc_queryctrl = vidioc_queryctrl, .vidioc_g_ctrl = vidioc_g_ctrl, .vidioc_s_ctrl = vidioc_s_ctrl, @@ -1449,7 +1465,7 @@ static const struct v4l2_file_operations radio_fops = { void cx23885_video_unregister(struct cx23885_dev *dev) { dprintk(1, "%s()\n", __func__); - cx_clear(PCI_INT_MSK, 1); + cx23885_irq_remove(dev, 0x01); if (dev->video_dev) { if (video_is_registered(dev->video_dev)) @@ -1486,7 +1502,8 @@ int cx23885_video_register(struct cx23885_dev *dev) VID_A_DMA_CTL, 0x11, 0x00); /* Don't enable VBI yet */ - cx_set(PCI_INT_MSK, 1); + + cx23885_irq_add_enable(dev, 0x01); if (TUNER_ABSENT != dev->tuner_type) { struct v4l2_subdev *sd = NULL; diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 8d6a55e54ee..ed94b17dd8a 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -30,6 +30,7 @@ #include <media/tveeprom.h> #include <media/videobuf-dma-sg.h> #include <media/videobuf-dvb.h> +#include <media/ir-core.h> #include "btcx-risc.h" #include "cx23885-reg.h" @@ -304,6 +305,15 @@ struct cx23885_tsport { void *port_priv; }; +struct cx23885_kernel_ir { + struct cx23885_dev *cx; + char *name; + char *phys; + + struct input_dev *inp_dev; + struct ir_dev_props props; +}; + struct cx23885_dev { atomic_t refcount; struct v4l2_device v4l2_dev; @@ -315,6 +325,7 @@ struct cx23885_dev { u32 __iomem *lmmio; u8 __iomem *bmmio; int pci_irqmask; + spinlock_t pci_irqmask_lock; /* protects mask reg too */ int hwrevision; /* This valud is board specific and is used to configure the @@ -355,6 +366,7 @@ struct cx23885_dev { unsigned char radio_addr; unsigned int has_radio; struct v4l2_subdev *sd_cx25840; + struct work_struct cx25840_work; /* Infrared */ struct v4l2_subdev *sd_ir; @@ -363,7 +375,7 @@ struct cx23885_dev { struct work_struct ir_tx_work; unsigned long ir_tx_notifications; - struct card_ir *ir_input; + struct cx23885_kernel_ir *kernel_ir; atomic_t ir_input_stopping; /* V4l */ @@ -393,7 +405,8 @@ static inline struct cx23885_dev *to_cx23885(struct v4l2_device *v4l2_dev) #define call_all(dev, o, f, args...) \ v4l2_device_call_all(&dev->v4l2_dev, 0, o, f, ##args) -#define CX23885_HW_888_IR (1 << 0) +#define CX23885_HW_888_IR (1 << 0) +#define CX23885_HW_AV_CORE (1 << 1) #define call_hw(dev, grpid, o, f, args...) \ v4l2_device_call_all(&dev->v4l2_dev, grpid, o, f, ##args) @@ -474,6 +487,10 @@ extern u32 cx23885_gpio_get(struct cx23885_dev *dev, u32 mask); extern void cx23885_gpio_enable(struct cx23885_dev *dev, u32 mask, int asoutput); +extern void cx23885_irq_add_enable(struct cx23885_dev *dev, u32 mask); +extern void cx23885_irq_enable(struct cx23885_dev *dev, u32 mask); +extern void cx23885_irq_disable(struct cx23885_dev *dev, u32 mask); +extern void cx23885_irq_remove(struct cx23885_dev *dev, u32 mask); /* ----------------------------------------------------------- */ /* cx23885-cards.c */ diff --git a/drivers/media/video/cx23885/cx23888-ir.c b/drivers/media/video/cx23885/cx23888-ir.c index f63d378257a..2502a0a6709 100644 --- a/drivers/media/video/cx23885/cx23888-ir.c +++ b/drivers/media/video/cx23885/cx23888-ir.c @@ -26,6 +26,7 @@ #include <media/v4l2-device.h> #include <media/v4l2-chip-ident.h> +#include <media/ir-core.h> #include "cx23885.h" @@ -60,6 +61,8 @@ MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]"); #define CNTRL_CPL 0x00001000 #define CNTRL_LBM 0x00002000 #define CNTRL_R 0x00004000 +/* CX23888 specific control flag */ +#define CNTRL_IVO 0x00008000 #define CX23888_IR_TXCLK_REG 0x170004 #define TXCLK_TCD 0x0000FFFF @@ -111,8 +114,18 @@ MODULE_PARM_DESC(ir_888_debug, "enable debug messages [CX23888 IR controller]"); #define CX23888_VIDCLK_FREQ 108000000 /* 108 MHz, BT.656 */ #define CX23888_IR_REFCLK_FREQ (CX23888_VIDCLK_FREQ / 2) -#define CX23888_IR_RX_KFIFO_SIZE (512 * sizeof(u32)) -#define CX23888_IR_TX_KFIFO_SIZE (512 * sizeof(u32)) +/* + * We use this union internally for convenience, but callers to tx_write + * and rx_read will be expecting records of type struct ir_raw_event. + * Always ensure the size of this union is dictated by struct ir_raw_event. + */ +union cx23888_ir_fifo_rec { + u32 hw_fifo_data; + struct ir_raw_event ir_core_data; +}; + +#define CX23888_IR_RX_KFIFO_SIZE (256 * sizeof(union cx23888_ir_fifo_rec)) +#define CX23888_IR_TX_KFIFO_SIZE (256 * sizeof(union cx23888_ir_fifo_rec)) struct cx23888_ir_state { struct v4l2_subdev sd; @@ -423,6 +436,13 @@ static inline void control_tx_polarity_invert(struct cx23885_dev *dev, invert ? CNTRL_CPL : 0); } +static inline void control_tx_level_invert(struct cx23885_dev *dev, + bool invert) +{ + cx23888_ir_and_or4(dev, CX23888_IR_CNTRL_REG, ~CNTRL_IVO, + invert ? CNTRL_IVO : 0); +} + /* * IR Rx & Tx Clock Register helpers */ @@ -449,8 +469,8 @@ static u32 txclk_tx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns, { u64 pulse_clocks; - if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) - ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; + if (ns > IR_MAX_DURATION) + ns = IR_MAX_DURATION; pulse_clocks = ns_to_pulse_clocks(ns); *divider = pulse_clocks_to_clock_divider(pulse_clocks); cx23888_ir_write4(dev, CX23888_IR_TXCLK_REG, *divider); @@ -462,8 +482,8 @@ static u32 rxclk_rx_s_max_pulse_width(struct cx23885_dev *dev, u32 ns, { u64 pulse_clocks; - if (ns > V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) - ns = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS; + if (ns > IR_MAX_DURATION) + ns = IR_MAX_DURATION; pulse_clocks = ns_to_pulse_clocks(ns); *divider = pulse_clocks_to_clock_divider(pulse_clocks); cx23888_ir_write4(dev, CX23888_IR_RXCLK_REG, *divider); @@ -526,8 +546,8 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, u32 irqen = cx23888_ir_read4(dev, CX23888_IR_IRQEN_REG); u32 stats = cx23888_ir_read4(dev, CX23888_IR_STATS_REG); - u32 rx_data[FIFO_RX_DEPTH]; - int i, j, k; + union cx23888_ir_fifo_rec rx_data[FIFO_RX_DEPTH]; + unsigned int i, j, k; u32 events, v; int tsr, rsr, rto, ror, tse, rse, rte, roe, kror; @@ -588,11 +608,12 @@ static int cx23888_ir_irq_handler(struct v4l2_subdev *sd, u32 status, for (j = 0; (v & FIFO_RX_NDV) && j < FIFO_RX_DEPTH; j++) { v = cx23888_ir_read4(dev, CX23888_IR_FIFO_REG); - rx_data[i++] = v & ~FIFO_RX_NDV; + rx_data[i].hw_fifo_data = v & ~FIFO_RX_NDV; + i++; } if (i == 0) break; - j = i * sizeof(u32); + j = i * sizeof(union cx23888_ir_fifo_rec); k = kfifo_in_locked(&state->rx_kfifo, (unsigned char *) rx_data, j, &state->rx_kfifo_lock); @@ -651,10 +672,11 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count, u16 divider = (u16) atomic_read(&state->rxclk_divider); unsigned int i, n; - u32 *p; - u32 u, v; + union cx23888_ir_fifo_rec *p; + unsigned u, v; - n = count / sizeof(u32) * sizeof(u32); + n = count / sizeof(union cx23888_ir_fifo_rec) + * sizeof(union cx23888_ir_fifo_rec); if (n == 0) { *num = 0; return 0; @@ -662,26 +684,28 @@ static int cx23888_ir_rx_read(struct v4l2_subdev *sd, u8 *buf, size_t count, n = kfifo_out_locked(&state->rx_kfifo, buf, n, &state->rx_kfifo_lock); - n /= sizeof(u32); - *num = n * sizeof(u32); + n /= sizeof(union cx23888_ir_fifo_rec); + *num = n * sizeof(union cx23888_ir_fifo_rec); + + for (p = (union cx23888_ir_fifo_rec *) buf, i = 0; i < n; p++, i++) { - for (p = (u32 *) buf, i = 0; i < n; p++, i++) { - if ((*p & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) { - *p = V4L2_SUBDEV_IR_PULSE_RX_SEQ_END; + if ((p->hw_fifo_data & FIFO_RXTX_RTO) == FIFO_RXTX_RTO) { + /* Assume RTO was because of no IR light input */ + u = 0; v4l2_dbg(2, ir_888_debug, sd, "rx read: end of rx\n"); - continue; + } else { + u = (p->hw_fifo_data & FIFO_RXTX_LVL) ? 1 : 0; + if (invert) + u = u ? 0 : 1; } - u = (*p & FIFO_RXTX_LVL) ? V4L2_SUBDEV_IR_PULSE_LEVEL_MASK : 0; - if (invert) - u = u ? 0 : V4L2_SUBDEV_IR_PULSE_LEVEL_MASK; + v = (unsigned) pulse_width_count_to_ns( + (u16) (p->hw_fifo_data & FIFO_RXTX), divider); + if (v > IR_MAX_DURATION) + v = IR_MAX_DURATION; - v = (u32) pulse_width_count_to_ns((u16) (*p & FIFO_RXTX), - divider); - if (v >= V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS) - v = V4L2_SUBDEV_IR_PULSE_MAX_WIDTH_NS - 1; - - *p = u | v; + p->ir_core_data.pulse = u; + p->ir_core_data.duration = v; v4l2_dbg(2, ir_888_debug, sd, "rx read: %10u ns %s\n", v, u ? "mark" : "space"); @@ -740,7 +764,8 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd, o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; - o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32); + o->bytes_per_data_element = p->bytes_per_data_element + = sizeof(union cx23888_ir_fifo_rec); /* Before we tweak the hardware, we have to disable the receiver */ irqenable_rx(dev, 0); @@ -762,12 +787,15 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd, &p->carrier_range_upper); o->carrier_range_lower = p->carrier_range_lower; o->carrier_range_upper = p->carrier_range_upper; + + p->max_pulse_width = + (u32) pulse_width_count_to_ns(FIFO_RXTX, rxclk_divider); } else { p->max_pulse_width = rxclk_rx_s_max_pulse_width(dev, p->max_pulse_width, &rxclk_divider); - o->max_pulse_width = p->max_pulse_width; } + o->max_pulse_width = p->max_pulse_width; atomic_set(&state->rxclk_divider, rxclk_divider); p->noise_filter_min_width = @@ -782,8 +810,8 @@ static int cx23888_ir_rx_s_parameters(struct v4l2_subdev *sd, control_rx_s_edge_detection(dev, CNTRL_EDG_BOTH); - o->invert = p->invert; - atomic_set(&state->rx_invert, p->invert); + o->invert_level = p->invert_level; + atomic_set(&state->rx_invert, p->invert_level); o->interrupt_enable = p->interrupt_enable; o->enable = p->enable; @@ -864,7 +892,8 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd, o->mode = p->mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH; - o->bytes_per_data_element = p->bytes_per_data_element = sizeof(u32); + o->bytes_per_data_element = p->bytes_per_data_element + = sizeof(union cx23888_ir_fifo_rec); /* Before we tweak the hardware, we have to disable the transmitter */ irqenable_tx(dev, 0); @@ -880,12 +909,15 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd, p->duty_cycle = cduty_tx_s_duty_cycle(dev, p->duty_cycle); o->duty_cycle = p->duty_cycle; + + p->max_pulse_width = + (u32) pulse_width_count_to_ns(FIFO_RXTX, txclk_divider); } else { p->max_pulse_width = txclk_tx_s_max_pulse_width(dev, p->max_pulse_width, &txclk_divider); - o->max_pulse_width = p->max_pulse_width; } + o->max_pulse_width = p->max_pulse_width; atomic_set(&state->txclk_divider, txclk_divider); p->resolution = clock_divider_to_resolution(txclk_divider); @@ -894,8 +926,11 @@ static int cx23888_ir_tx_s_parameters(struct v4l2_subdev *sd, /* FIXME - make this dependent on resolution for better performance */ control_tx_irq_watermark(dev, TX_FIFO_HALF_EMPTY); - control_tx_polarity_invert(dev, p->invert); - o->invert = p->invert; + control_tx_polarity_invert(dev, p->invert_carrier_sense); + o->invert_carrier_sense = p->invert_carrier_sense; + + control_tx_level_invert(dev, p->invert_level); + o->invert_level = p->invert_level; o->interrupt_enable = p->interrupt_enable; o->enable = p->enable; @@ -988,12 +1023,10 @@ static int cx23888_ir_log_status(struct v4l2_subdev *sd) "-%1d/+%1d, %u to %u Hz\n", i, j, clock_divider_to_freq(rxclk, 16 + j), clock_divider_to_freq(rxclk, 16 - i)); - } else { - v4l2_info(sd, "\tMax measurable pulse width: %u us, " - "%llu ns\n", - pulse_width_count_to_us(FIFO_RXTX, rxclk), - pulse_width_count_to_ns(FIFO_RXTX, rxclk)); } + v4l2_info(sd, "\tMax measurable pulse width: %u us, %llu ns\n", + pulse_width_count_to_us(FIFO_RXTX, rxclk), + pulse_width_count_to_ns(FIFO_RXTX, rxclk)); v4l2_info(sd, "\tLow pass filter: %s\n", filtr ? "enabled" : "disabled"); if (filtr) @@ -1025,19 +1058,20 @@ static int cx23888_ir_log_status(struct v4l2_subdev *sd) cntrl & CNTRL_TFE ? "enabled" : "disabled"); v4l2_info(sd, "\tFIFO interrupt watermark: %s\n", cntrl & CNTRL_TIC ? "not empty" : "half full or less"); - v4l2_info(sd, "\tSignal polarity: %s\n", - cntrl & CNTRL_CPL ? "0:mark 1:space" : "0:space 1:mark"); + v4l2_info(sd, "\tOutput pin level inversion %s\n", + cntrl & CNTRL_IVO ? "yes" : "no"); + v4l2_info(sd, "\tCarrier polarity: %s\n", + cntrl & CNTRL_CPL ? "space:burst mark:noburst" + : "space:noburst mark:burst"); if (cntrl & CNTRL_MOD) { v4l2_info(sd, "\tCarrier (16 clocks): %u Hz\n", clock_divider_to_carrier_freq(txclk)); v4l2_info(sd, "\tCarrier duty cycle: %2u/16\n", cduty + 1); - } else { - v4l2_info(sd, "\tMax pulse width: %u us, " - "%llu ns\n", - pulse_width_count_to_us(FIFO_RXTX, txclk), - pulse_width_count_to_ns(FIFO_RXTX, txclk)); } + v4l2_info(sd, "\tMax pulse width: %u us, %llu ns\n", + pulse_width_count_to_us(FIFO_RXTX, txclk), + pulse_width_count_to_ns(FIFO_RXTX, txclk)); v4l2_info(sd, "\tBusy: %s\n", stats & STATS_TBY ? "yes" : "no"); v4l2_info(sd, "\tFIFO service requested: %s\n", @@ -1111,11 +1145,10 @@ static const struct v4l2_subdev_core_ops cx23888_ir_core_ops = { .g_register = cx23888_ir_g_register, .s_register = cx23888_ir_s_register, #endif + .interrupt_service_routine = cx23888_ir_irq_handler, }; static const struct v4l2_subdev_ir_ops cx23888_ir_ir_ops = { - .interrupt_service_routine = cx23888_ir_irq_handler, - .rx_read = cx23888_ir_rx_read, .rx_g_parameters = cx23888_ir_rx_g_parameters, .rx_s_parameters = cx23888_ir_rx_s_parameters, @@ -1131,7 +1164,7 @@ static const struct v4l2_subdev_ops cx23888_ir_controller_ops = { }; static const struct v4l2_subdev_ir_parameters default_rx_params = { - .bytes_per_data_element = sizeof(u32), + .bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec), .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, .enable = false, @@ -1146,11 +1179,11 @@ static const struct v4l2_subdev_ir_parameters default_rx_params = { .noise_filter_min_width = 333333, /* ns */ .carrier_range_lower = 35000, .carrier_range_upper = 37000, - .invert = false, + .invert_level = false, }; static const struct v4l2_subdev_ir_parameters default_tx_params = { - .bytes_per_data_element = sizeof(u32), + .bytes_per_data_element = sizeof(union cx23888_ir_fifo_rec), .mode = V4L2_SUBDEV_IR_MODE_PULSE_WIDTH, .enable = false, @@ -1160,7 +1193,8 @@ static const struct v4l2_subdev_ir_parameters default_tx_params = { .modulation = true, .carrier_freq = 36000, /* 36 kHz - RC-5 carrier */ .duty_cycle = 25, /* 25 % - RC-5 carrier */ - .invert = false, + .invert_level = false, + .invert_carrier_sense = false, }; int cx23888_ir_probe(struct cx23885_dev *dev) |