mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-18 09:44:18 +08:00
V4L/DVB (13098): cx23885: Add integrated IR subdevice interrupt and notification handling
Add integrated IR subdevice interrupt and notification handling. This is in preparation of input keypress handling changes for the cx23885 module. Signed-off-by: Andy Walls <awalls@radix.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
1a0b9d89c6
commit
f59ad611ac
@ -1,6 +1,6 @@
|
||||
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 cx23888-ir.o \
|
||||
cx23885-ioctl.o cx23885-ir.o cx23888-ir.o \
|
||||
netup-init.o cimax2.o netup-eeprom.o
|
||||
|
||||
obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
|
||||
|
@ -821,6 +821,7 @@ 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;
|
||||
break;
|
||||
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
|
||||
request_module("ir-kbd-i2c");
|
||||
@ -830,6 +831,28 @@ int cx23885_ir_init(struct cx23885_dev *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void cx23885_ir_fini(struct cx23885_dev *dev)
|
||||
{
|
||||
switch (dev->board) {
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1850:
|
||||
dev->pci_irqmask &= ~PCI_MSK_IR;
|
||||
cx_clear(PCI_INT_MSK, PCI_MSK_IR);
|
||||
cx23888_ir_remove(dev);
|
||||
dev->sd_ir = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
|
||||
{
|
||||
switch (dev->board) {
|
||||
case CX23885_BOARD_HAUPPAUGE_HVR1850:
|
||||
if (dev->sd_ir && (dev->pci_irqmask & PCI_MSK_IR))
|
||||
cx_set(PCI_INT_MSK, PCI_MSK_IR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void cx23885_card_setup(struct cx23885_dev *dev)
|
||||
{
|
||||
struct cx23885_tsport *ts1 = &dev->ts1;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "cx23885.h"
|
||||
#include "cimax2.h"
|
||||
#include "cx23888-ir.h"
|
||||
#include "cx23885-ir.h"
|
||||
|
||||
MODULE_DESCRIPTION("Driver for cx23885 based TV cards");
|
||||
MODULE_AUTHOR("Steven Toth <stoth@linuxtv.org>");
|
||||
@ -1655,6 +1656,7 @@ 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;
|
||||
|
||||
pci_status = cx_read(PCI_INT_STAT);
|
||||
pci_mask = cx_read(PCI_INT_MSK);
|
||||
@ -1680,18 +1682,12 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
|
||||
dprintk(7, "ts2_status: 0x%08x ts2_mask: 0x%08x count: 0x%x\n",
|
||||
ts2_status, ts2_mask, ts2_count);
|
||||
|
||||
if ((pci_status & PCI_MSK_RISC_RD) ||
|
||||
(pci_status & PCI_MSK_RISC_WR) ||
|
||||
(pci_status & PCI_MSK_AL_RD) ||
|
||||
(pci_status & PCI_MSK_AL_WR) ||
|
||||
(pci_status & PCI_MSK_APB_DMA) ||
|
||||
(pci_status & PCI_MSK_VID_C) ||
|
||||
(pci_status & PCI_MSK_VID_B) ||
|
||||
(pci_status & PCI_MSK_VID_A) ||
|
||||
(pci_status & PCI_MSK_AUD_INT) ||
|
||||
(pci_status & PCI_MSK_AUD_EXT) ||
|
||||
(pci_status & PCI_MSK_GPIO0) ||
|
||||
(pci_status & PCI_MSK_GPIO1)) {
|
||||
if (pci_status & (PCI_MSK_RISC_RD | PCI_MSK_RISC_WR |
|
||||
PCI_MSK_AL_RD | PCI_MSK_AL_WR | PCI_MSK_APB_DMA |
|
||||
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)) {
|
||||
|
||||
if (pci_status & PCI_MSK_RISC_RD)
|
||||
dprintk(7, " (PCI_MSK_RISC_RD 0x%08x)\n",
|
||||
@ -1740,6 +1736,10 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
|
||||
if (pci_status & PCI_MSK_GPIO1)
|
||||
dprintk(7, " (PCI_MSK_GPIO1 0x%08x)\n",
|
||||
PCI_MSK_GPIO1);
|
||||
|
||||
if (pci_status & PCI_MSK_IR)
|
||||
dprintk(7, " (PCI_MSK_IR 0x%08x)\n",
|
||||
PCI_MSK_IR);
|
||||
}
|
||||
|
||||
if (cx23885_boards[dev->board].cimax > 0 &&
|
||||
@ -1770,12 +1770,48 @@ static irqreturn_t cx23885_irq(int irq, void *dev_id)
|
||||
if (vida_status)
|
||||
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)
|
||||
handled++;
|
||||
}
|
||||
|
||||
if (handled)
|
||||
cx_write(PCI_INT_STAT, pci_status);
|
||||
out:
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
||||
static void cx23885_v4l2_dev_notify(struct v4l2_subdev *sd,
|
||||
unsigned int notification, void *arg)
|
||||
{
|
||||
struct cx23885_dev *dev;
|
||||
|
||||
if (sd == NULL)
|
||||
return;
|
||||
|
||||
dev = to_cx23885(sd->v4l2_dev);
|
||||
|
||||
switch (notification) {
|
||||
case V4L2_SUBDEV_IR_RX_NOTIFY: /* 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 */
|
||||
if (sd == dev->sd_ir)
|
||||
cx23885_ir_tx_v4l2_dev_notify(sd, *(u32 *)arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void cx23885_v4l2_dev_notify_init(struct cx23885_dev *dev)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static inline int encoder_on_portb(struct cx23885_dev *dev)
|
||||
{
|
||||
return cx23885_boards[dev->board].portb == CX23885_MPEG_ENCODER;
|
||||
@ -1872,6 +1908,9 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
|
||||
if (err < 0)
|
||||
goto fail_free;
|
||||
|
||||
/* Prepare to handle notifications from subdevices */
|
||||
cx23885_v4l2_dev_notify_init(dev);
|
||||
|
||||
/* pci init */
|
||||
dev->pci = pci_dev;
|
||||
if (pci_enable_device(pci_dev)) {
|
||||
@ -1914,6 +1953,13 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The CX2388[58] IR controller can start firing interrupts when
|
||||
* enabled, so these have to take place after the cx23885_irq() handler
|
||||
* is hooked up by the call to request_irq() above.
|
||||
*/
|
||||
cx23885_ir_pci_int_enable(dev);
|
||||
|
||||
return 0;
|
||||
|
||||
fail_irq:
|
||||
@ -1930,9 +1976,9 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev)
|
||||
struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
|
||||
struct cx23885_dev *dev = to_cx23885(v4l2_dev);
|
||||
|
||||
cx23885_shutdown(dev);
|
||||
cx23885_ir_fini(dev);
|
||||
|
||||
cx23888_ir_remove(dev);
|
||||
cx23885_shutdown(dev);
|
||||
|
||||
pci_disable_device(pci_dev);
|
||||
|
||||
|
97
drivers/media/video/cx23885/cx23885-ir.c
Normal file
97
drivers/media/video/cx23885/cx23885-ir.c
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Driver for the Conexant CX23885/7/8 PCIe bridge
|
||||
*
|
||||
* Infrared device support routines - non-input, non-vl42_subdev routines
|
||||
*
|
||||
* Copyright (C) 2009 Andy Walls <awalls@radix.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 <media/v4l2-device.h>
|
||||
|
||||
#include "cx23885.h"
|
||||
|
||||
#define CX23885_IR_RX_FIFO_SERVICE_REQ 0
|
||||
#define CX23885_IR_RX_END_OF_RX_DETECTED 1
|
||||
#define CX23885_IR_RX_HW_FIFO_OVERRUN 2
|
||||
#define CX23885_IR_RX_SW_FIFO_OVERRUN 3
|
||||
|
||||
#define CX23885_IR_TX_FIFO_SERVICE_REQ 0
|
||||
|
||||
|
||||
void cx23885_ir_rx_work_handler(struct work_struct *work)
|
||||
{
|
||||
struct cx23885_dev *dev =
|
||||
container_of(work, struct cx23885_dev, ir_rx_work);
|
||||
u32 events = 0;
|
||||
unsigned long *notifications = &dev->ir_rx_notifications;
|
||||
|
||||
if (test_and_clear_bit(CX23885_IR_RX_SW_FIFO_OVERRUN, notifications))
|
||||
events |= V4L2_SUBDEV_IR_RX_SW_FIFO_OVERRUN;
|
||||
if (test_and_clear_bit(CX23885_IR_RX_HW_FIFO_OVERRUN, notifications))
|
||||
events |= V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN;
|
||||
if (test_and_clear_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications))
|
||||
events |= V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED;
|
||||
if (test_and_clear_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications))
|
||||
events |= V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ;
|
||||
|
||||
if (events == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
void cx23885_ir_tx_work_handler(struct work_struct *work)
|
||||
{
|
||||
struct cx23885_dev *dev =
|
||||
container_of(work, struct cx23885_dev, ir_tx_work);
|
||||
u32 events = 0;
|
||||
unsigned long *notifications = &dev->ir_tx_notifications;
|
||||
|
||||
if (test_and_clear_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications))
|
||||
events |= V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ;
|
||||
|
||||
if (events == 0)
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/* 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);
|
||||
unsigned long *notifications = &dev->ir_rx_notifications;
|
||||
|
||||
if (events & V4L2_SUBDEV_IR_RX_FIFO_SERVICE_REQ)
|
||||
set_bit(CX23885_IR_RX_FIFO_SERVICE_REQ, notifications);
|
||||
if (events & V4L2_SUBDEV_IR_RX_END_OF_RX_DETECTED)
|
||||
set_bit(CX23885_IR_RX_END_OF_RX_DETECTED, notifications);
|
||||
if (events & V4L2_SUBDEV_IR_RX_HW_FIFO_OVERRUN)
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
unsigned long *notifications = &dev->ir_tx_notifications;
|
||||
|
||||
if (events & V4L2_SUBDEV_IR_TX_FIFO_SERVICE_REQ)
|
||||
set_bit(CX23885_IR_TX_FIFO_SERVICE_REQ, notifications);
|
||||
schedule_work(&dev->ir_tx_work);
|
||||
}
|
31
drivers/media/video/cx23885/cx23885-ir.h
Normal file
31
drivers/media/video/cx23885/cx23885-ir.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Driver for the Conexant CX23885/7/8 PCIe bridge
|
||||
*
|
||||
* Infrared device support routines - non-input, non-vl42_subdev routines
|
||||
*
|
||||
* Copyright (C) 2009 Andy Walls <awalls@radix.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_IR_H_
|
||||
#define _CX23885_IR_H_
|
||||
void cx23885_ir_rx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events);
|
||||
void cx23885_ir_tx_v4l2_dev_notify(struct v4l2_subdev *sd, u32 events);
|
||||
|
||||
void cx23885_ir_rx_work_handler(struct work_struct *work);
|
||||
void cx23885_ir_tx_work_handler(struct work_struct *work);
|
||||
#endif
|
@ -212,8 +212,9 @@ Channel manager Data Structure entry = 20 DWORD
|
||||
|
||||
#define DEV_CNTRL2 0x00040000
|
||||
|
||||
#define PCI_MSK_GPIO1 (1 << 24)
|
||||
#define PCI_MSK_GPIO0 (1 << 23)
|
||||
#define PCI_MSK_IR (1 << 28)
|
||||
#define PCI_MSK_GPIO1 (1 << 24)
|
||||
#define PCI_MSK_GPIO0 (1 << 23)
|
||||
#define PCI_MSK_APB_DMA (1 << 12)
|
||||
#define PCI_MSK_AL_WR (1 << 11)
|
||||
#define PCI_MSK_AL_RD (1 << 10)
|
||||
|
@ -355,7 +355,13 @@ struct cx23885_dev {
|
||||
unsigned char radio_addr;
|
||||
unsigned int has_radio;
|
||||
struct v4l2_subdev *sd_cx25840;
|
||||
struct v4l2_subdev *sd_ir;
|
||||
|
||||
/* Infrared */
|
||||
struct v4l2_subdev *sd_ir;
|
||||
struct work_struct ir_rx_work;
|
||||
unsigned long ir_rx_notifications;
|
||||
struct work_struct ir_tx_work;
|
||||
unsigned long ir_tx_notifications;
|
||||
|
||||
/* V4l */
|
||||
u32 freq;
|
||||
@ -479,6 +485,8 @@ extern int cx23885_tuner_callback(void *priv, int component,
|
||||
int command, int arg);
|
||||
extern void cx23885_card_list(struct cx23885_dev *dev);
|
||||
extern int cx23885_ir_init(struct cx23885_dev *dev);
|
||||
extern void cx23885_ir_pci_int_enable(struct cx23885_dev *dev);
|
||||
extern void cx23885_ir_fini(struct cx23885_dev *dev);
|
||||
extern void cx23885_gpio_setup(struct cx23885_dev *dev);
|
||||
extern void cx23885_card_setup(struct cx23885_dev *dev);
|
||||
extern void cx23885_card_setup_pre_i2c(struct cx23885_dev *dev);
|
||||
|
Loading…
Reference in New Issue
Block a user