Commit 7ae0dea9 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6

* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (94 commits)
  V4L/DVB: tvp7002: fix write to H-PLL Feedback Divider LSB register
  V4L/DVB: dvb: siano: free spinlock before schedule()
  V4L/DVB: media: video: pvrusb2: remove custom hex_to_bin()
  V4L/DVB: drivers: usbvideo: remove custom implementation of hex_to_bin()
  V4L/DVB: Report supported QAM modes on bt8xx
  V4L/DVB: media: ir-keytable: null dereference in debug code
  V4L/DVB: ivtv: convert to the new control framework
  V4L/DVB: ivtv: convert gpio subdev to new control framework
  V4L/DVB: wm8739: convert to the new control framework
  V4L/DVB: cs53l32a: convert to new control framework
  V4L/DVB: wm8775: convert to the new control framework
  V4L/DVB: cx2341x: convert to the control framework
  V4L/DVB: cx25840: convert to the new control framework
  V4L/DVB: cx25840/ivtv: replace ugly priv control with s_config
  V4L/DVB: saa717x: convert to the new control framework
  V4L/DVB: msp3400: convert to the new control framework
  V4L/DVB: saa7115: convert to the new control framework
  V4L/DVB: v4l2: hook up the new control framework into the core framework
  V4L/DVB: Documentation: add v4l2-controls.txt documenting the new controls API
  V4L/DVB: v4l2-ctrls: Whitespace cleanups
  ...
parents 6c74700f 560afa7d
...@@ -229,6 +229,22 @@ on working with the default settings initially.</para> ...@@ -229,6 +229,22 @@ on working with the default settings initially.</para>
and LIRC_SETUP_END. Drivers can also choose to ignore these ioctls.</para> and LIRC_SETUP_END. Drivers can also choose to ignore these ioctls.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term>LIRC_SET_WIDEBAND_RECEIVER</term>
<listitem>
<para>Some receivers are equipped with special wide band receiver which is intended
to be used to learn output of existing remote.
Calling that ioctl with (1) will enable it, and with (0) disable it.
This might be useful of receivers that have otherwise narrow band receiver
that prevents them to be used with some remotes.
Wide band receiver might also be more precise
On the other hand its disadvantage it usually reduced range of reception.
Note: wide band receiver might be implictly enabled if you enable
carrier reports. In that case it will be disabled as soon as you disable
carrier reports. Trying to disable wide band receiver while carrier
reports are active will do nothing.</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</section> </section>
......
...@@ -240,6 +240,45 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para> ...@@ -240,6 +240,45 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
<entry>r<subscript>1</subscript></entry> <entry>r<subscript>1</subscript></entry>
<entry>r<subscript>0</subscript></entry> <entry>r<subscript>0</subscript></entry>
</row> </row>
<row id="V4L2-PIX-FMT-BGR666">
<entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
<entry>'BGRH'</entry>
<entry></entry>
<entry>b<subscript>5</subscript></entry>
<entry>b<subscript>4</subscript></entry>
<entry>b<subscript>3</subscript></entry>
<entry>b<subscript>2</subscript></entry>
<entry>b<subscript>1</subscript></entry>
<entry>b<subscript>0</subscript></entry>
<entry>g<subscript>5</subscript></entry>
<entry>g<subscript>4</subscript></entry>
<entry></entry>
<entry>g<subscript>3</subscript></entry>
<entry>g<subscript>2</subscript></entry>
<entry>g<subscript>1</subscript></entry>
<entry>g<subscript>0</subscript></entry>
<entry>r<subscript>5</subscript></entry>
<entry>r<subscript>4</subscript></entry>
<entry>r<subscript>3</subscript></entry>
<entry>r<subscript>2</subscript></entry>
<entry></entry>
<entry>r<subscript>1</subscript></entry>
<entry>r<subscript>0</subscript></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
</row>
<row id="V4L2-PIX-FMT-BGR24"> <row id="V4L2-PIX-FMT-BGR24">
<entry><constant>V4L2_PIX_FMT_BGR24</constant></entry> <entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
<entry>'BGR3'</entry> <entry>'BGR3'</entry>
...@@ -700,6 +739,45 @@ defined in error. Drivers may interpret them as in <xref ...@@ -700,6 +739,45 @@ defined in error. Drivers may interpret them as in <xref
<entry>b<subscript>1</subscript></entry> <entry>b<subscript>1</subscript></entry>
<entry>b<subscript>0</subscript></entry> <entry>b<subscript>0</subscript></entry>
</row> </row>
<row id="V4L2-PIX-FMT-BGR666">
<entry><constant>V4L2_PIX_FMT_BGR666</constant></entry>
<entry>'BGRH'</entry>
<entry></entry>
<entry>b<subscript>5</subscript></entry>
<entry>b<subscript>4</subscript></entry>
<entry>b<subscript>3</subscript></entry>
<entry>b<subscript>2</subscript></entry>
<entry>b<subscript>1</subscript></entry>
<entry>b<subscript>0</subscript></entry>
<entry>g<subscript>5</subscript></entry>
<entry>g<subscript>4</subscript></entry>
<entry></entry>
<entry>g<subscript>3</subscript></entry>
<entry>g<subscript>2</subscript></entry>
<entry>g<subscript>1</subscript></entry>
<entry>g<subscript>0</subscript></entry>
<entry>r<subscript>5</subscript></entry>
<entry>r<subscript>4</subscript></entry>
<entry>r<subscript>3</subscript></entry>
<entry>r<subscript>2</subscript></entry>
<entry></entry>
<entry>r<subscript>1</subscript></entry>
<entry>r<subscript>0</subscript></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
<entry></entry>
</row>
<row><!-- id="V4L2-PIX-FMT-BGR24" --> <row><!-- id="V4L2-PIX-FMT-BGR24" -->
<entry><constant>V4L2_PIX_FMT_BGR24</constant></entry> <entry><constant>V4L2_PIX_FMT_BGR24</constant></entry>
<entry>'BGR3'</entry> <entry>'BGR3'</entry>
......
This diff is collapsed.
...@@ -2203,6 +2203,12 @@ F: drivers/misc/cb710/ ...@@ -2203,6 +2203,12 @@ F: drivers/misc/cb710/
F: drivers/mmc/host/cb710-mmc.* F: drivers/mmc/host/cb710-mmc.*
F: include/linux/cb710.h F: include/linux/cb710.h
ENE KB2426 (ENE0100/ENE020XX) INFRARED RECEIVER
M: Maxim Levitsky <maximlevitsky@gmail.com>
S: Maintained
F: drivers/media/IR/ene_ir.c
F: drivers/media/IR/ene_ir.h
EPSON 1355 FRAMEBUFFER DRIVER EPSON 1355 FRAMEBUFFER DRIVER
M: Christopher Hoover <ch@murgatroid.com> M: Christopher Hoover <ch@murgatroid.com>
M: Christopher Hoover <ch@hpl.hp.com> M: Christopher Hoover <ch@hpl.hp.com>
......
config IR_CORE menuconfig IR_CORE
tristate tristate "Infrared remote controller adapters"
depends on INPUT depends on INPUT
default INPUT default INPUT
if IR_CORE
config VIDEO_IR config VIDEO_IR
tristate tristate
depends on IR_CORE depends on IR_CORE
...@@ -16,7 +18,7 @@ config LIRC ...@@ -16,7 +18,7 @@ config LIRC
Enable this option to build the Linux Infrared Remote Enable this option to build the Linux Infrared Remote
Control (LIRC) core device interface driver. The LIRC Control (LIRC) core device interface driver. The LIRC
interface passes raw IR to and from userspace, where the interface passes raw IR to and from userspace, where the
LIRC daemon handles protocol decoding for IR reception ann LIRC daemon handles protocol decoding for IR reception and
encoding for IR transmitting (aka "blasting"). encoding for IR transmitting (aka "blasting").
source "drivers/media/IR/keymaps/Kconfig" source "drivers/media/IR/keymaps/Kconfig"
...@@ -103,3 +105,31 @@ config IR_MCEUSB ...@@ -103,3 +105,31 @@ config IR_MCEUSB
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called mceusb. module will be called mceusb.
config IR_ENE
tristate "ENE eHome Receiver/Transciever (pnp id: ENE0100/ENE02xxx)"
depends on PNP
depends on IR_CORE
---help---
Say Y here to enable support for integrated infrared receiver
/transciever made by ENE.
You can see if you have it by looking at lspnp output.
Output should include ENE0100 ENE0200 or something similiar.
To compile this driver as a module, choose M here: the
module will be called ene_ir.
config IR_STREAMZAP
tristate "Streamzap PC Remote IR Receiver"
depends on USB_ARCH_HAS_HCD
depends on IR_CORE
select USB
---help---
Say Y here if you want to use a Streamzap PC Remote
Infrared Receiver.
To compile this driver as a module, choose M here: the
module will be called streamzap.
endif #IR_CORE
...@@ -16,3 +16,5 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o ...@@ -16,3 +16,5 @@ obj-$(CONFIG_IR_LIRC_CODEC) += ir-lirc-codec.o
# stand-alone IR receivers/transmitters # stand-alone IR receivers/transmitters
obj-$(CONFIG_IR_IMON) += imon.o obj-$(CONFIG_IR_IMON) += imon.o
obj-$(CONFIG_IR_MCEUSB) += mceusb.o obj-$(CONFIG_IR_MCEUSB) += mceusb.o
obj-$(CONFIG_IR_ENE) += ene_ir.o
obj-$(CONFIG_IR_STREAMZAP) += streamzap.o
/*
* driver for ENE KB3926 B/C/D CIR (also known as ENE0XXX)
*
* Copyright (C) 2010 Maxim Levitsky <maximlevitsky@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#include <linux/spinlock.h>
/* hardware address */
#define ENE_STATUS 0 /* hardware status - unused */
#define ENE_ADDR_HI 1 /* hi byte of register address */
#define ENE_ADDR_LO 2 /* low byte of register address */
#define ENE_IO 3 /* read/write window */
#define ENE_MAX_IO 4
/* 8 bytes of samples, divided in 2 halfs*/
#define ENE_SAMPLE_BUFFER 0xF8F0 /* regular sample buffer */
#define ENE_SAMPLE_SPC_MASK 0x80 /* sample is space */
#define ENE_SAMPLE_VALUE_MASK 0x7F
#define ENE_SAMPLE_OVERFLOW 0x7F
#define ENE_SAMPLES_SIZE 4
/* fan input sample buffer */
#define ENE_SAMPLE_BUFFER_FAN 0xF8FB /* this buffer holds high byte of */
/* each sample of normal buffer */
#define ENE_FAN_SMPL_PULS_MSK 0x8000 /* this bit of combined sample */
/* if set, says that sample is pulse */
#define ENE_FAN_VALUE_MASK 0x0FFF /* mask for valid bits of the value */
/* first firmware register */
#define ENE_FW1 0xF8F8
#define ENE_FW1_ENABLE 0x01 /* enable fw processing */
#define ENE_FW1_TXIRQ 0x02 /* TX interrupt pending */
#define ENE_FW1_WAKE 0x40 /* enable wake from S3 */
#define ENE_FW1_IRQ 0x80 /* enable interrupt */
/* second firmware register */
#define ENE_FW2 0xF8F9
#define ENE_FW2_BUF_HIGH 0x01 /* which half of the buffer to read */
#define ENE_FW2_IRQ_CLR 0x04 /* clear this on IRQ */
#define ENE_FW2_GP40_AS_LEARN 0x08 /* normal input is used as */
/* learning input */
#define ENE_FW2_FAN_AS_NRML_IN 0x40 /* fan is used as normal input */
#define ENE_FW2_LEARNING 0x80 /* hardware supports learning and TX */
/* transmitter ports */
#define ENE_TX_PORT2 0xFC01 /* this enables one or both */
#define ENE_TX_PORT2_EN 0x20 /* TX ports */
#define ENE_TX_PORT1 0xFC08
#define ENE_TX_PORT1_EN 0x02
/* IRQ registers block (for revision B) */
#define ENEB_IRQ 0xFD09 /* IRQ number */
#define ENEB_IRQ_UNK1 0xFD17 /* unknown setting = 1 */
#define ENEB_IRQ_STATUS 0xFD80 /* irq status */
#define ENEB_IRQ_STATUS_IR 0x20 /* IR irq */
/* fan as input settings - only if learning capable */
#define ENE_FAN_AS_IN1 0xFE30 /* fan init reg 1 */
#define ENE_FAN_AS_IN1_EN 0xCD
#define ENE_FAN_AS_IN2 0xFE31 /* fan init reg 2 */
#define ENE_FAN_AS_IN2_EN 0x03
#define ENE_SAMPLE_PERIOD_FAN 61 /* fan input has fixed sample period */
/* IRQ registers block (for revision C,D) */
#define ENEC_IRQ 0xFE9B /* new irq settings register */
#define ENEC_IRQ_MASK 0x0F /* irq number mask */
#define ENEC_IRQ_UNK_EN 0x10 /* always enabled */
#define ENEC_IRQ_STATUS 0x20 /* irq status and ACK */
/* CIR block settings */
#define ENE_CIR_CONF1 0xFEC0
#define ENE_CIR_CONF1_TX_CLEAR 0x01 /* clear that on revC */
/* while transmitting */
#define ENE_CIR_CONF1_RX_ON 0x07 /* normal receiver enabled */
#define ENE_CIR_CONF1_LEARN1 0x08 /* enabled on learning mode */
#define ENE_CIR_CONF1_TX_ON 0x30 /* enabled on transmit */
#define ENE_CIR_CONF1_TX_CARR 0x80 /* send TX carrier or not */
#define ENE_CIR_CONF2 0xFEC1 /* unknown setting = 0 */
#define ENE_CIR_CONF2_LEARN2 0x10 /* set on enable learning */
#define ENE_CIR_CONF2_GPIO40DIS 0x20 /* disable input via gpio40 */
#define ENE_CIR_SAMPLE_PERIOD 0xFEC8 /* sample period in us */
#define ENE_CIR_SAMPLE_OVERFLOW 0x80 /* interrupt on overflows if set */
/* Two byte tx buffer */
#define ENE_TX_INPUT1 0xFEC9
#define ENE_TX_INPUT2 0xFECA
#define ENE_TX_PULSE_MASK 0x80 /* Transmitted sample is pulse */
#define ENE_TX_SMLP_MASK 0x7F
#define ENE_TX_SMPL_PERIOD 50 /* transmit sample period - fixed */
/* Unknown TX setting - TX sample period ??? */
#define ENE_TX_UNK1 0xFECB /* set to 0x63 */
/* Current received carrier period */
#define ENE_RX_CARRIER 0xFECC /* RX period (500 ns) */
#define ENE_RX_CARRIER_VALID 0x80 /* Register content valid */
/* TX period (1/carrier) */
#define ENE_TX_PERIOD 0xFECE /* TX period (500 ns) */
#define ENE_TX_PERIOD_UNKBIT 0x80 /* This bit set on transmit*/
#define ENE_TX_PERIOD_PULSE 0xFECF /* TX pulse period (500 ns)*/
/* Hardware versions */
#define ENE_HW_VERSION 0xFF00 /* hardware revision */
#define ENE_PLLFRH 0xFF16
#define ENE_PLLFRL 0xFF17
#define ENE_HW_UNK 0xFF1D
#define ENE_HW_UNK_CLR 0x04
#define ENE_HW_VER_MAJOR 0xFF1E /* chip version */
#define ENE_HW_VER_MINOR 0xFF1F
#define ENE_HW_VER_OLD 0xFD00
/* Normal/Learning carrier ranges - only valid if we have learning input*/
/* TODO: test */
#define ENE_NORMAL_RX_LOW 34
#define ENE_NORMAL_RX_HI 38
/* Tx carrier range */
/* Hardware might be able to do more, but this range is enough for
all purposes */
#define ENE_TX_PERIOD_MAX 32 /* corresponds to 29.4 kHz */
#define ENE_TX_PERIOD_MIN 16 /* corrsponds to 62.5 kHz */
/* Minimal and maximal gaps */
/* Normal case:
Minimal gap is 0x7F * sample period
Maximum gap depends on hardware.
For KB3926B, it is unlimited, for newer models its around
250000, after which HW stops sending samples, and that is
not possible to change */
/* Fan case:
Both minimal and maximal gaps are same, and equal to 0xFFF * 0x61
And there is nothing to change this setting
*/
#define ENE_MAXGAP 250000
#define ENE_MINGAP (127 * sample_period)
/******************************************************************************/
#define ENE_DRIVER_NAME "ene_ir"
#define ENE_IRQ_RX 1
#define ENE_IRQ_TX 2
#define ENE_HW_B 1 /* 3926B */
#define ENE_HW_C 2 /* 3926C */
#define ENE_HW_D 3 /* 3926D */
#define ene_printk(level, text, ...) \
printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__)
#define ene_dbg(text, ...) \
if (debug) \
printk(KERN_DEBUG \
ENE_DRIVER_NAME ": " text "\n" , ## __VA_ARGS__)
#define ene_dbg_verbose(text, ...) \
if (debug > 1) \
printk(KERN_DEBUG \
ENE_DRIVER_NAME ": " text "\n" , ## __VA_ARGS__)
struct ene_device {
struct pnp_dev *pnp_dev;
struct input_dev *idev;
struct ir_dev_props *props;
int in_use;
/* hw IO settings */
unsigned long hw_io;
int irq;
spinlock_t hw_lock;
/* HW features */
int hw_revision; /* hardware revision */
bool hw_learning_and_tx_capable; /* learning capable */
bool hw_gpio40_learning; /* gpio40 is learning */
bool hw_fan_as_normal_input; /* fan input is used as */
/* regular input */
/* HW state*/
int rx_pointer; /* hw pointer to rx buffer */
bool rx_fan_input_inuse; /* is fan input in use for rx*/
int tx_reg; /* current reg used for TX */
u8 saved_conf1; /* saved FEC0 reg */
/* TX sample handling */
unsigned int tx_sample; /* current sample for TX */
bool tx_sample_pulse; /* current sample is pulse */
/* TX buffer */
int *tx_buffer; /* input samples buffer*/
int tx_pos; /* position in that bufer */
int tx_len; /* current len of tx buffer */
int tx_done; /* done transmitting */
/* one more sample pending*/
struct completion tx_complete; /* TX completion */
struct timer_list tx_sim_timer;
/* TX settings */
int tx_period;
int tx_duty_cycle;
int transmitter_mask;
/* RX settings */
bool learning_enabled; /* learning input enabled */
bool carrier_detect_enabled; /* carrier detect enabled */
int rx_period_adjust;
};
...@@ -87,7 +87,6 @@ static ssize_t lcd_write(struct file *file, const char *buf, ...@@ -87,7 +87,6 @@ static ssize_t lcd_write(struct file *file, const char *buf,
struct imon_context { struct imon_context {
struct device *dev; struct device *dev;
struct ir_dev_props *props; struct ir_dev_props *props;
struct ir_input_dev *ir;
/* Newer devices have two interfaces */ /* Newer devices have two interfaces */
struct usb_device *usbdev_intf0; struct usb_device *usbdev_intf0;
struct usb_device *usbdev_intf1; struct usb_device *usbdev_intf1;
...@@ -1656,7 +1655,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx) ...@@ -1656,7 +1655,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
{ {
struct input_dev *idev; struct input_dev *idev;
struct ir_dev_props *props; struct ir_dev_props *props;
struct ir_input_dev *ir;
int ret, i; int ret, i;
idev = input_allocate_device(); idev = input_allocate_device();
...@@ -1671,12 +1669,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx) ...@@ -1671,12 +1669,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
goto props_alloc_failed; goto props_alloc_failed;
} }
ir = kzalloc(sizeof(struct ir_input_dev), GFP_KERNEL);
if (!ir) {
dev_err(ictx->dev, "remote ir input dev allocation failed\n");
goto ir_dev_alloc_failed;
}
snprintf(ictx->name_idev, sizeof(ictx->name_idev), snprintf(ictx->name_idev, sizeof(ictx->name_idev),
"iMON Remote (%04x:%04x)", ictx->vendor, ictx->product); "iMON Remote (%04x:%04x)", ictx->vendor, ictx->product);
idev->name = ictx->name_idev; idev->name = ictx->name_idev;
...@@ -1706,14 +1698,9 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx) ...@@ -1706,14 +1698,9 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
props->change_protocol = imon_ir_change_protocol; props->change_protocol = imon_ir_change_protocol;
ictx->props = props; ictx->props = props;
ictx->ir = ir;
memcpy(&ir->dev, ictx->dev, sizeof(struct device));
usb_to_input_id(ictx->usbdev_intf0, &idev->id); usb_to_input_id(ictx->usbdev_intf0, &idev->id);
idev->dev.parent = ictx->dev; idev->dev.parent = ictx->dev;
input_set_drvdata(idev, ir);
ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME); ret = ir_input_register(idev, RC_MAP_IMON_PAD, props, MOD_NAME);
if (ret < 0) { if (ret < 0) {
dev_err(ictx->dev, "remote input dev register failed\n"); dev_err(ictx->dev, "remote input dev register failed\n");
...@@ -1723,8 +1710,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx) ...@@ -1723,8 +1710,6 @@ static struct input_dev *imon_init_idev(struct imon_context *ictx)
return idev; return idev;
idev_register_failed: idev_register_failed:
kfree(ir);
ir_dev_alloc_failed:
kfree(props); kfree(props);
props_alloc_failed: props_alloc_failed:
input_free_device(idev); input_free_device(idev);
...@@ -1944,7 +1929,6 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf) ...@@ -1944,7 +1929,6 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
urb_submit_failed: urb_submit_failed:
ir_input_unregister(ictx->idev); ir_input_unregister(ictx->idev);
input_free_device(ictx->idev);
idev_setup_failed: idev_setup_failed:
find_endpoint_failed: find_endpoint_failed:
mutex_unlock(&ictx->lock); mutex_unlock(&ictx->lock);
...@@ -2014,10 +1998,8 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf, ...@@ -2014,10 +1998,8 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf,
return ictx; return ictx;
urb_submit_failed: urb_submit_failed:
if (ictx->touch) { if (ictx->touch)
input_unregister_device(ictx->touch); input_unregister_device(ictx->touch);
input_free_device(ictx->touch);
}
touch_setup_failed: touch_setup_failed:
find_endpoint_failed: find_endpoint_failed:
mutex_unlock(&ictx->lock); mutex_unlock(&ictx->lock);
......
...@@ -32,7 +32,7 @@ struct ir_raw_handler { ...@@ -32,7 +32,7 @@ struct ir_raw_handler {
struct ir_raw_event_ctrl { struct ir_raw_event_ctrl {
struct list_head list; /* to keep track of raw clients */ struct list_head list; /* to keep track of raw clients */
struct work_struct rx_work; /* for the rx decoding workqueue */ struct task_struct *thread;
struct kfifo kfifo; /* fifo for the pulse/space durations */ struct kfifo kfifo; /* fifo for the pulse/space durations */
ktime_t last_event; /* when last event occurred */ ktime_t last_event; /* when last event occurred */
enum raw_event_type last_type; /* last event type */ enum raw_event_type last_type; /* last event type */
...@@ -41,10 +41,13 @@ struct ir_raw_event_ctrl { ...@@ -41,10 +41,13 @@ struct ir_raw_event_ctrl {
/* raw decoder state follows */ /* raw decoder state follows */
struct ir_raw_event prev_ev; struct ir_raw_event prev_ev;
struct ir_raw_event this_ev;
struct nec_dec { struct nec_dec {
int state; int state;
unsigned count; unsigned count;
u32 bits; u32 bits;
bool is_nec_x;
bool necx_repeat;
} nec; } nec;
struct rc5_dec { struct rc5_dec {
int state; int state;
...@@ -76,7 +79,7 @@ struct ir_raw_event_ctrl { ...@@ -76,7 +79,7 @@ struct ir_raw_event_ctrl {
struct lirc_codec { struct lirc_codec {
struct ir_input_dev *ir_dev; struct ir_input_dev *ir_dev;
struct lirc_driver *drv; struct lirc_driver *drv;
int lircdata; int carrier_low;
} lirc; } lirc;
}; };
...@@ -104,10 +107,9 @@ static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration) ...@@ -104,10 +107,9 @@ static inline void decrease_duration(struct ir_raw_event *ev, unsigned duration)
ev->duration -= duration; ev->duration -= duration;
} }
#define TO_US(duration) (((duration) + 500) / 1000) #define TO_US(duration) DIV_ROUND_CLOSEST((duration), 1000)
#define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space") #define TO_STR(is_pulse) ((is_pulse) ? "pulse" : "space")
#define IS_RESET(ev) (ev.duration == 0) #define IS_RESET(ev) (ev.duration == 0)
/* /*
* Routines from ir-sysfs.c - Meant to be called only internally inside * Routines from ir-sysfs.c - Meant to be called only internally inside
* ir-core * ir-core
...@@ -126,7 +128,8 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler); ...@@ -126,7 +128,8 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler);
void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler); void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler);
void ir_raw_init(void); void ir_raw_init(void);
int ir_rcmap_init(void);
void ir_rcmap_cleanup(void);
/* /*
* Decoder initialization code * Decoder initialization code
* *
......
...@@ -32,6 +32,7 @@ enum jvc_state { ...@@ -32,6 +32,7 @@ enum jvc_state {
STATE_BIT_SPACE, STATE_BIT_SPACE,
STATE_TRAILER_PULSE, STATE_TRAILER_PULSE,
STATE_TRAILER_SPACE, STATE_TRAILER_SPACE,
STATE_CHECK_REPEAT,
}; };
/** /**
...@@ -60,6 +61,7 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) ...@@ -60,6 +61,7 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n", IR_dprintk(2, "JVC decode started at state %d (%uus %s)\n",
data->state, TO_US(ev.duration), TO_STR(ev.pulse)); data->state, TO_US(ev.duration), TO_STR(ev.pulse));
again:
switch (data->state) { switch (data->state) {
case STATE_INACTIVE: case STATE_INACTIVE:
...@@ -149,8 +151,18 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev) ...@@ -149,8 +151,18 @@ static int ir_jvc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
} }
data->count = 0; data->count = 0;
data->state = STATE_BIT_PULSE; data->state = STATE_CHECK_REPEAT;
return 0; return 0;
case STATE_CHECK_REPEAT:
if (!ev.pulse)
break;
if (eq_margin(ev.duration, JVC_HEADER_PULSE, JVC_UNIT / 2))
data->state = STATE_INACTIVE;
else
data->state = STATE_BIT_PULSE;
goto again;
} }
out: out:
......
...@@ -339,6 +339,8 @@ void ir_repeat(struct input_dev *dev) ...@@ -339,6 +339,8 @@ void ir_repeat(struct input_dev *dev)
spin_lock_irqsave(&ir->keylock, flags); spin_lock_irqsave(&ir->keylock, flags);
input_event(dev, EV_MSC, MSC_SCAN, ir->last_scancode);
if (!ir->keypressed) if (!ir->keypressed)
goto out; goto out;
...@@ -370,6 +372,8 @@ void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) ...@@ -370,6 +372,8 @@ void ir_keydown(struct input_dev *dev, int scancode, u8 toggle)
spin_lock_irqsave(&ir->keylock, flags); spin_lock_irqsave(&ir->keylock, flags);
input_event(dev, EV_MSC, MSC_SCAN, scancode);
/* Repeat event? */ /* Repeat event? */
if (ir->keypressed && if (ir->keypressed &&
ir->last_scancode == scancode && ir->last_scancode == scancode &&
...@@ -383,9 +387,11 @@ void ir_keydown(struct input_dev *dev, int scancode, u8 toggle) ...@@ -383,9 +387,11 @@ void ir_keydown(struct input_dev *dev, int scancode, u8 toggle)
ir->last_toggle = toggle; ir->last_toggle = toggle;
ir->last_keycode = keycode; ir->last_keycode = keycode;
if (keycode == KEY_RESERVED) if (keycode == KEY_RESERVED)
goto out; goto out;
/* Register a keypress */ /* Register a keypress */
ir->keypressed = true; ir->keypressed = true;
IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n", IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n",
...@@ -428,7 +434,7 @@ static void ir_close(struct input_dev *input_dev) ...@@ -428,7 +434,7 @@ static void ir_close(struct input_dev *input_dev)
*/ */
int __ir_input_register(struct input_dev *input_dev, int __ir_input_register(struct input_dev *input_dev,
const struct ir_scancode_table *rc_tab, const struct ir_scancode_table *rc_tab,
const struct ir_dev_props *props, struct ir_dev_props *props,
const char *driver_name) const char *driver_name)
{ {
struct ir_input_dev *ir_dev; struct ir_input_dev *ir_dev;
...@@ -480,6 +486,8 @@ int __ir_input_register(struct input_dev *input_dev, ...@@ -480,6 +486,8 @@ int __ir_input_register(struct input_dev *input_dev,
set_bit(EV_KEY, input_dev->evbit); set_bit(EV_KEY, input_dev->evbit);
set_bit(EV_REP, input_dev->evbit); set_bit(EV_REP, input_dev->evbit);
set_bit(EV_MSC, input_dev->evbit);
set_bit(MSC_SCAN, input_dev->mscbit);
if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) { if (ir_setkeytable(input_dev, &ir_dev->rc_tab, rc_tab)) {
rc = -ENOMEM; rc = -ENOMEM;
...@@ -499,7 +507,8 @@ int __ir_input_register(struct input_dev *input_dev, ...@@ -499,7 +507,8 @@ int __ir_input_register(struct input_dev *input_dev,
IR_dprintk(1, "Registered input device on %s for %s remote%s.\n", IR_dprintk(1, "Registered input device on %s for %s remote%s.\n",
driver_name, rc_tab->name, driver_name, rc_tab->name,
ir_dev->props->driver_type == RC_DRIVER_IR_RAW ? " in raw mode" : ""); (ir_dev->props && ir_dev->props->driver_type == RC_DRIVER_IR_RAW) ?
" in raw mode" : "");
return 0; return 0;
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
{ {
struct ir_input_dev *ir_dev = input_get_drvdata(input_dev); struct ir_input_dev *ir_dev = input_get_drvdata(input_dev);
int sample;
if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC)) if (!(ir_dev->raw->enabled_protocols & IR_TYPE_LIRC))
return 0; return 0;
...@@ -39,18 +40,20 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev) ...@@ -39,18 +40,20 @@ static int ir_lirc_decode(struct input_dev *input_dev, struct ir_raw_event ev)
if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf) if (!ir_dev->raw->lirc.drv || !ir_dev->raw->lirc.drv->rbuf)
return -EINVAL; return -EINVAL;
if (IS_RESET(ev))
return 0;
IR_dprintk(2, "LIRC data transfer started (%uus %s)\n", IR_dprintk(2, "LIRC data transfer started (%uus %s)\n",
TO_US(ev.duration), TO_STR(ev.pulse)); TO_US(ev.duration), TO_STR(ev.pulse));
ir_dev->raw->lirc.lircdata += ev.duration / 1000; sample = ev.duration / 1000;
if (ev.pulse) if (ev.pulse)
ir_dev->raw->lirc.lircdata |= PULSE_BIT; sample |= PULSE_BIT;
lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf, lirc_buffer_write(ir_dev->raw->lirc.drv->rbuf,
(unsigned char *) &ir_dev->raw->lirc.lircdata); (unsigned char *) &sample);
wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll); wake_up(&ir_dev->raw->lirc.drv->rbuf->wait_poll);
ir_dev->raw->lirc.lircdata = 0;
return 0; return 0;
} }
...@@ -92,13 +95,14 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf, ...@@ -92,13 +95,14 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char *buf,
return ret; return ret;
} }
static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) static long ir_lirc_ioctl(struct file *filep, unsigned int cmd,
unsigned long __user arg)
{ {
struct lirc_codec *lirc; struct lirc_codec *lirc;
struct ir_input_dev *ir_dev; struct ir_input_dev *ir_dev;
int ret = 0; int ret = 0;
void *drv_data; void *drv_data;
unsigned long val; unsigned long val = 0;
lirc = lirc_get_pdata(filep); lirc = lirc_get_pdata(filep);
if (!lirc) if (!lirc)
...@@ -110,47 +114,106 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long ar ...@@ -110,47 +114,106 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, unsigned long ar
drv_data = ir_dev->props->priv; drv_data = ir_dev->props->priv;
switch (cmd) { if (_IOC_DIR(cmd) & _IOC_WRITE) {
case LIRC_SET_TRANSMITTER_MASK:
ret = get_user(val, (unsigned long *)arg); ret = get_user(val, (unsigned long *)arg);
if (ret) if (ret)
return ret; return ret;
}
switch (cmd) {
if (ir_dev->props && ir_dev->props->s_tx_mask) /* legacy support */
case LIRC_GET_SEND_MODE:
val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK;
break;
case LIRC_SET_SEND_MODE:
if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK))
return -EINVAL;
break;
/* TX settings */
case LIRC_SET_TRANSMITTER_MASK:
if (ir_dev->props->s_tx_mask)
ret = ir_dev->props->s_tx_mask(drv_data, (u32)val); ret = ir_dev->props->s_tx_mask(drv_data, (u32)val);
else else
return -EINVAL; return -EINVAL;
break; break;
case LIRC_SET_SEND_CARRIER: case LIRC_SET_SEND_CARRIER:
ret = get_user(val, (unsigned long *)arg); if (ir_dev->props->s_tx_carrier)
if (ret)
return ret;
if (ir_dev->props && ir_dev->props->s_tx_carrier)
ir_dev->props->s_tx_carrier(drv_data, (u32)val); ir_dev->props->s_tx_carrier(drv_data, (u32)val);
else else
return -EINVAL; return -EINVAL;
break; break;
case LIRC_GET_SEND_MODE: case LIRC_SET_SEND_DUTY_CYCLE:
val = LIRC_CAN_SEND_PULSE & LIRC_CAN_SEND_MASK; if (!ir_dev->props->s_tx_duty_cycle)
ret = put_user(val, (unsigned long *)arg); return -ENOSYS;
if (val <= 0 || val >= 100)
return -EINVAL;
ir_dev->props->s_tx_duty_cycle(ir_dev->props->priv, val);
break; break;
case LIRC_SET_SEND_MODE: /* RX settings */
ret = get_user(val, (unsigned long *)arg); case LIRC_SET_REC_CARRIER:
if (ret) if (ir_dev->props->s_rx_carrier_range)
return ret; ret = ir_dev->props->s_rx_carrier_range(
ir_dev->props->priv,
ir_dev->raw->lirc.carrier_low, val);
else
return -ENOSYS;
if (val != (LIRC_MODE_PULSE & LIRC_CAN_SEND_MASK)) if (!ret)
ir_dev->raw->lirc.carrier_low = 0;
break;
case LIRC_SET_REC_CARRIER_RANGE:
if (val >= 0)
ir_dev->raw->lirc.carrier_low = val;
break;
case LIRC_GET_REC_RESOLUTION:
val = ir_dev->props->rx_resolution;
break;
case LIRC_SET_WIDEBAND_RECEIVER:
if (ir_dev->props->s_learning_mode)
return ir_dev->props->s_learning_mode(
ir_dev->props->priv, !!val);
else
return -ENOSYS;
/* Generic timeout support */
case LIRC_GET_MIN_TIMEOUT:
if (!ir_dev->props->max_timeout)
return -ENOSYS;
val = ir_dev->props->min_timeout / 1000;
break;
case LIRC_GET_MAX_TIMEOUT:
if (!ir_dev->props->max_timeout)
return -ENOSYS;
val = ir_dev->props->max_timeout / 1000;
break;
case LIRC_SET_REC_TIMEOUT:
if (val < ir_dev->props->min_timeout ||
val > ir_dev->props->max_timeout)
return -EINVAL; return -EINVAL;
ir_dev->props->timeout = val * 1000;
break; break;
default: default:
return lirc_dev_fop_ioctl(filep, cmd, arg); return lirc_dev_fop_ioctl(filep, cmd, arg);
} }
if (_IOC_DIR(cmd) & _IOC_READ)
ret = put_user(val, (unsigned long *)arg);
return ret; return ret;
} }
...@@ -196,13 +259,28 @@ static int ir_lirc_register(struct input_dev *input_dev) ...@@ -196,13 +259,28 @@ static int ir_lirc_register(struct input_dev *input_dev)
features = LIRC_CAN_REC_MODE2; features = LIRC_CAN_REC_MODE2;
if (ir_dev->props->tx_ir) { if (ir_dev->props->tx_ir) {
features |= LIRC_CAN_SEND_PULSE; features |= LIRC_CAN_SEND_PULSE;
if (ir_dev->props->s_tx_mask) if (ir_dev->props->s_tx_mask)
features |= LIRC_CAN_SET_TRANSMITTER_MASK; features |= LIRC_CAN_SET_TRANSMITTER_MASK;
if (ir_dev->props->s_tx_carrier) if (ir_dev->props->s_tx_carrier)
features |= LIRC_CAN_SET_SEND_CARRIER; features |= LIRC_CAN_SET_SEND_CARRIER;
if (ir_dev->props->s_tx_duty_cycle)
features |= LIRC_CAN_SET_REC_DUTY_CYCLE;
} }
if (ir_dev->props->s_rx_carrier_range)
features |= LIRC_CAN_SET_REC_CARRIER |
LIRC_CAN_SET_REC_CARRIER_RANGE;
if (ir_dev->props->s_learning_mode)
features |= LIRC_CAN_USE_WIDEBAND_RECEIVER;
if (ir_dev->props->max_timeout)
features |= LIRC_CAN_SET_REC_TIMEOUT;
snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)", snprintf(drv->name, sizeof(drv->name), "ir-lirc-codec (%s)",
ir_dev->driver_name); ir_dev->driver_name);
drv->minor = -1; drv->minor = -1;
...@@ -224,8 +302,6 @@ static int ir_lirc_register(struct input_dev *input_dev) ...@@ -224,8 +302,6 @@ static int ir_lirc_register(struct input_dev *input_dev)
ir_dev->raw->lirc.drv = drv; ir_dev->raw->lirc.drv = drv;
ir_dev->raw->lirc.ir_dev = ir_dev; ir_dev->raw->lirc.ir_dev = ir_dev;
ir_dev->raw->lirc.lircdata = PULSE_MASK;
return 0; return 0;
lirc_register_failed: lirc_register_failed:
......
...@@ -20,12 +20,13 @@ ...@@ -20,12 +20,13 @@
#define NEC_HEADER_PULSE (16 * NEC_UNIT) #define NEC_HEADER_PULSE (16 * NEC_UNIT)
#define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */ #define NECX_HEADER_PULSE (8 * NEC_UNIT) /* Less common NEC variant */
#define NEC_HEADER_SPACE (8 * NEC_UNIT) #define NEC_HEADER_SPACE (8 * NEC_UNIT)
#define NEC_REPEAT_SPACE (8 * NEC_UNIT) #define NEC_REPEAT_SPACE (4 * NEC_UNIT)
#define NEC_BIT_PULSE (1 * NEC_UNIT) #define NEC_BIT_PULSE (1 * NEC_UNIT)
#define NEC_BIT_0_SPACE (1 * NEC_UNIT) #define NEC_BIT_0_SPACE (1 * NEC_UNIT)
#define NEC_BIT_1_SPACE (3 * NEC_UNIT) #define NEC_BIT_1_SPACE (3 * NEC_UNIT)
#define NEC_TRAILER_PULSE (1 * NEC_UNIT) #define NEC_TRAILER_PULSE (1 * NEC_UNIT)
#define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */ #define NEC_TRAILER_SPACE (10 * NEC_UNIT) /* even longer in reality */
#define NECX_REPEAT_BITS 1
enum nec_state { enum nec_state {
STATE_INACTIVE, STATE_INACTIVE,
...@@ -67,8 +68,12 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) ...@@ -67,8 +68,12 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
if (!ev.pulse) if (!ev.pulse)
break; break;
if (!eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2) && if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2)) {
!eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2)) data->is_nec_x = false;
data->necx_repeat = false;
} else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
data->is_nec_x = true;
else
break; break;
data->count = 0; data->count = 0;
...@@ -105,6 +110,17 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) ...@@ -105,6 +110,17 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
if (ev.pulse) if (ev.pulse)
break; break;
if (data->necx_repeat && data->count == NECX_REPEAT_BITS &&
geq_margin(ev.duration,
NEC_TRAILER_SPACE, NEC_UNIT / 2)) {
IR_dprintk(1, "Repeat last key\n");
ir_repeat(input_dev);
data->state = STATE_INACTIVE;
return 0;
} else if (data->count > NECX_REPEAT_BITS)
data->necx_repeat = false;
data->bits <<= 1; data->bits <<= 1;
if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2)) if (eq_margin(ev.duration, NEC_BIT_1_SPACE, NEC_UNIT / 2))
data->bits |= 1; data->bits |= 1;
...@@ -159,6 +175,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev) ...@@ -159,6 +175,9 @@ static int ir_nec_decode(struct input_dev *input_dev, struct ir_raw_event ev)
IR_dprintk(1, "NEC scancode 0x%04x\n", scancode); IR_dprintk(1, "NEC scancode 0x%04x\n", scancode);
} }
if (data->is_nec_x)
data->necx_repeat = true;
ir_keydown(input_dev, scancode, 0); ir_keydown(input_dev, scancode, 0);
data->state = STATE_INACTIVE; data->state = STATE_INACTIVE;
return 0; return 0;
......
...@@ -12,9 +12,10 @@ ...@@ -12,9 +12,10 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <linux/workqueue.h> #include <linux/kthread.h>
#include <linux/spinlock.h> #include <linux/mutex.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/freezer.h>
#include "ir-core-priv.h" #include "ir-core-priv.h"
/* Define the max number of pulse/space transitions to buffer */ /* Define the max number of pulse/space transitions to buffer */
...@@ -24,7 +25,7 @@ ...@@ -24,7 +25,7 @@
static LIST_HEAD(ir_raw_client_list); static LIST_HEAD(ir_raw_client_list);
/* Used to handle IR raw handler extensions */ /* Used to handle IR raw handler extensions */
static DEFINE_SPINLOCK(ir_raw_handler_lock); static DEFINE_MUTEX(ir_raw_handler_lock);
static LIST_HEAD(ir_raw_handler_list); static LIST_HEAD(ir_raw_handler_list);
static u64 available_protocols; static u64 available_protocols;
...@@ -33,20 +34,30 @@ static u64 available_protocols; ...@@ -33,20 +34,30 @@ static u64 available_protocols;
static struct work_struct wq_load; static struct work_struct wq_load;
#endif #endif
static void ir_raw_event_work(struct work_struct *work) static int ir_raw_event_thread(void *data)
{ {
struct ir_raw_event ev; struct ir_raw_event ev;
struct ir_raw_handler *handler; struct ir_raw_handler *handler;
struct ir_raw_event_ctrl *raw = struct ir_raw_event_ctrl *raw = (struct ir_raw_event_ctrl *)data;
container_of(work, struct ir_raw_event_ctrl, rx_work);
while (!kthread_should_stop()) {
while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) { try_to_freeze();
spin_lock(&ir_raw_handler_lock);
list_for_each_entry(handler, &ir_raw_handler_list, list) mutex_lock(&ir_raw_handler_lock);
handler->decode(raw->input_dev, ev);
spin_unlock(&ir_raw_handler_lock); while (kfifo_out(&raw->kfifo, &ev, sizeof(ev)) == sizeof(ev)) {
raw->prev_ev = ev; list_for_each_entry(handler, &ir_raw_handler_list, list)
handler->decode(raw->input_dev, ev);
raw->prev_ev = ev;
}
mutex_unlock(&ir_raw_handler_lock);
set_current_state(TASK_INTERRUPTIBLE);
schedule();
} }
return 0;
} }
/** /**
...@@ -66,6 +77,9 @@ int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev) ...@@ -66,6 +77,9 @@ int ir_raw_event_store(struct input_dev *input_dev, struct ir_raw_event *ev)
if (!ir->raw) if (!ir->raw)
return -EINVAL; return -EINVAL;
IR_dprintk(2, "sample: (05%dus %s)\n",
TO_US(ev->duration), TO_STR(ev->pulse));
if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev)) if (kfifo_in(&ir->raw->kfifo, ev, sizeof(*ev)) != sizeof(*ev))
return -ENOMEM; return -ENOMEM;
...@@ -125,6 +139,90 @@ int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type typ ...@@ -125,6 +139,90 @@ int ir_raw_event_store_edge(struct input_dev *input_dev, enum raw_event_type typ
} }
EXPORT_SYMBOL_GPL(ir_raw_event_store_edge); EXPORT_SYMBOL_GPL(ir_raw_event_store_edge);
/**
* ir_raw_event_store_with_filter() - pass next pulse/space to decoders with some processing
* @input_dev: the struct input_dev device descriptor
* @type: the type of the event that has occurred
*
* This routine (which may be called from an interrupt context) works
* in similiar manner to ir_raw_event_store_edge.
* This routine is intended for devices with limited internal buffer
* It automerges samples of same type, and handles timeouts
*/
int ir_raw_event_store_with_filter(struct input_dev *input_dev,
struct ir_raw_event *ev)
{
struct ir_input_dev *ir = input_get_drvdata(input_dev);
struct ir_raw_event_ctrl *raw = ir->raw;
if (!raw || !ir->props)
return -EINVAL;
/* Ignore spaces in idle mode */
if (ir->idle && !ev->pulse)
return 0;
else if (ir->idle)
ir_raw_event_set_idle(input_dev, 0);
if (!raw->this_ev.duration) {
raw->this_ev = *ev;
} else if (ev->pulse == raw->this_ev.pulse) {
raw->this_ev.duration += ev->duration;
} else {
ir_raw_event_store(input_dev, &raw->this_ev);
raw->this_ev = *ev;
}
/* Enter idle mode if nessesary */
if (!ev->pulse && ir->props->timeout &&
raw->this_ev.duration >= ir->props->timeout)
ir_raw_event_set_idle(input_dev, 1);
return 0;
}
EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
void ir_raw_event_set_idle(struct input_dev *input_dev, int idle)
{
struct ir_input_dev *ir = input_get_drvdata(input_dev);
struct ir_raw_event_ctrl *raw = ir->raw;
ktime_t now;
u64 delta;
if (!ir->props)
return;
if (!ir->raw)
goto out;
if (idle) {
IR_dprintk(2, "enter idle mode\n");
raw->last_event = ktime_get();
} else {
IR_dprintk(2, "exit idle mode\n");
now = ktime_get();
delta = ktime_to_ns(ktime_sub(now, ir->raw->last_event));
WARN_ON(raw->this_ev.pulse);
raw->this_ev.duration =
min(raw->this_ev.duration + delta,
(u64)IR_MAX_DURATION);
ir_raw_event_store(input_dev, &raw->this_ev);
if (raw->this_ev.duration == IR_MAX_DURATION)
ir_raw_event_reset(input_dev);
raw->this_ev.duration = 0;
}
out:
if (ir->props->s_idle)
ir->props->s_idle(ir->props->priv, idle);
ir->idle = idle;
}
EXPORT_SYMBOL_GPL(ir_raw_event_set_idle);
/** /**
* ir_raw_event_handle() - schedules the decoding of stored ir data * ir_raw_event_handle() - schedules the decoding of stored ir data
* @input_dev: the struct input_dev device descriptor * @input_dev: the struct input_dev device descriptor
...@@ -138,7 +236,7 @@ void ir_raw_event_handle(struct input_dev *input_dev) ...@@ -138,7 +236,7 @@ void ir_raw_event_handle(struct input_dev *input_dev)
if (!ir->raw) if (!ir->raw)
return; return;
schedule_work(&ir->raw->rx_work); wake_up_process(ir->raw->thread);
} }
EXPORT_SYMBOL_GPL(ir_raw_event_handle); EXPORT_SYMBOL_GPL(ir_raw_event_handle);
...@@ -147,9 +245,9 @@ u64 ...@@ -147,9 +245,9 @@ u64
ir_raw_get_allowed_protocols() ir_raw_get_allowed_protocols()
{ {
u64 protocols; u64 protocols;
spin_lock(&ir_raw_handler_lock); mutex_lock(&ir_raw_handler_lock);
protocols = available_protocols; protocols = available_protocols;
spin_unlock(&ir_raw_handler_lock); mutex_unlock(&ir_raw_handler_lock);
return protocols; return protocols;
} }
...@@ -167,7 +265,7 @@ int ir_raw_event_register(struct input_dev *input_dev) ...@@ -167,7 +265,7 @@ int ir_raw_event_register(struct input_dev *input_dev)
return -ENOMEM; return -ENOMEM;
ir->raw->input_dev = input_dev; ir->raw->input_dev = input_dev;
INIT_WORK(&ir->raw->rx_work, ir_raw_event_work);
ir->raw->enabled_protocols = ~0; ir->raw->enabled_protocols = ~0;
rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE, rc = kfifo_alloc(&ir->raw->kfifo, sizeof(s64) * MAX_IR_EVENT_SIZE,
GFP_KERNEL); GFP_KERNEL);
...@@ -177,12 +275,21 @@ int ir_raw_event_register(struct input_dev *input_dev) ...@@ -177,12 +275,21 @@ int ir_raw_event_register(struct input_dev *input_dev)
return rc; return rc;
} }
spin_lock(&ir_raw_handler_lock); ir->raw->thread = kthread_run(ir_raw_event_thread, ir->raw,
"rc%u", (unsigned int)ir->devno);
if (IS_ERR(ir->raw->thread)) {
kfree(ir->raw);
ir->raw = NULL;
return PTR_ERR(ir->raw->thread);
}
mutex_lock(&ir_raw_handler_lock);
list_add_tail(&ir->raw->list, &ir_raw_client_list); list_add_tail(&ir->raw->list, &ir_raw_client_list);
list_for_each_entry(handler, &ir_raw_handler_list, list) list_for_each_entry(handler, &ir_raw_handler_list, list)
if (handler->raw_register) if (handler->raw_register)
handler->raw_register(ir->raw->input_dev); handler->raw_register(ir->raw->input_dev);
spin_unlock(&ir_raw_handler_lock); mutex_unlock(&ir_raw_handler_lock);
return 0; return 0;
} }
...@@ -195,14 +302,14 @@ void ir_raw_event_unregister(struct input_dev *input_dev) ...@@ -195,14 +302,14 @@ void ir_raw_event_unregister(struct input_dev *input_dev)
if (!ir->raw) if (!ir->raw)
return; return;
cancel_work_sync(&ir->raw->rx_work); kthread_stop(ir->raw->thread);
spin_lock(&ir_raw_handler_lock); mutex_lock(&ir_raw_handler_lock);
list_del(&ir->raw->list); list_del(&ir->raw->list);
list_for_each_entry(handler, &ir_raw_handler_list, list) list_for_each_entry(handler, &ir_raw_handler_list, list)
if (handler->raw_unregister) if (handler->raw_unregister)
handler->raw_unregister(ir->raw->input_dev); handler->raw_unregister(ir->raw->input_dev);
spin_unlock(&ir_raw_handler_lock); mutex_unlock(&ir_raw_handler_lock);
kfifo_free(&ir->raw->kfifo); kfifo_free(&ir->raw->kfifo);
kfree(ir->raw); kfree(ir->raw);
...@@ -217,13 +324,13 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler) ...@@ -217,13 +324,13 @@ int ir_raw_handler_register(struct ir_raw_handler *ir_raw_handler)
{ {
struct ir_raw_event_ctrl *raw; struct ir_raw_event_ctrl *raw;
spin_lock(&ir_raw_handler_lock); mutex_lock(&ir_raw_handler_lock);
list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list); list_add_tail(&ir_raw_handler->list, &ir_raw_handler_list);
if (ir_raw_handler->raw_register) if (ir_raw_handler->raw_register)
list_for_each_entry(raw, &ir_raw_client_list, list) list_for_each_entry(raw, &ir_raw_client_list, list)
ir_raw_handler->raw_register(raw->input_dev); ir_raw_handler->raw_register(raw->input_dev);
available_protocols |= ir_raw_handler->protocols; available_protocols |= ir_raw_handler->protocols;
spin_unlock(&ir_raw_handler_lock); mutex_unlock(&ir_raw_handler_lock);
return 0; return 0;
} }
...@@ -233,13 +340,13 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler) ...@@ -233,13 +340,13 @@ void ir_raw_handler_unregister(struct ir_raw_handler *ir_raw_handler)
{ {
struct ir_raw_event_ctrl *raw; struct ir_raw_event_ctrl *raw;
spin_lock(&ir_raw_handler_lock); mutex_lock(&ir_raw_handler_lock);
list_del(&ir_raw_handler->list); list_del(&ir_raw_handler->list);
if (ir_raw_handler->raw_unregister) if (ir_raw_handler->raw_unregister)
list_for_each_entry(raw, &ir_raw_client_list, list) list_for_each_entry(raw, &ir_raw_client_list, list)
ir_raw_handler->raw_unregister(raw->input_dev); ir_raw_handler->raw_unregister(raw->input_dev);
available_protocols &= ~ir_raw_handler->protocols; available_protocols &= ~ir_raw_handler->protocols;
spin_unlock(&ir_raw_handler_lock); mutex_unlock(&ir_raw_handler_lock);
} }
EXPORT_SYMBOL(ir_raw_handler_unregister); EXPORT_SYMBOL(ir_raw_handler_unregister);
......
...@@ -325,6 +325,7 @@ static int __init ir_core_init(void) ...@@ -325,6 +325,7 @@ static int __init ir_core_init(void)
/* Initialize/load the decoders/keymap code that will be used */ /* Initialize/load the decoders/keymap code that will be used */
ir_raw_init(); ir_raw_init();
ir_rcmap_init();
return 0; return 0;
} }
...@@ -332,6 +333,7 @@ static int __init ir_core_init(void) ...@@ -332,6 +333,7 @@ static int __init ir_core_init(void)
static void __exit ir_core_exit(void) static void __exit ir_core_exit(void)
{ {
class_unregister(&ir_input_class); class_unregister(&ir_input_class);
ir_rcmap_cleanup();
} }
module_init(ir_core_init); module_init(ir_core_init);
......
...@@ -19,7 +19,6 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ ...@@ -19,7 +19,6 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
rc-dm1105-nec.o \ rc-dm1105-nec.o \
rc-dntv-live-dvb-t.o \ rc-dntv-live-dvb-t.o \
rc-dntv-live-dvbt-pro.o \ rc-dntv-live-dvbt-pro.o \
rc-empty.o \
rc-em-terratec.o \ rc-em-terratec.o \
rc-encore-enltv2.o \ rc-encore-enltv2.o \
rc-encore-enltv.o \ rc-encore-enltv.o \
...@@ -59,6 +58,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \ ...@@ -59,6 +58,7 @@ obj-$(CONFIG_RC_MAP) += rc-adstech-dvb-t-pci.o \
rc-purpletv.o \ rc-purpletv.o \
rc-pv951.o \ rc-pv951.o \
rc-rc5-hauppauge-new.o \ rc-rc5-hauppauge-new.o \
rc-rc5-streamzap.o \
rc-rc5-tv.o \ rc-rc5-tv.o \
rc-rc6-mce.o \ rc-rc6-mce.o \
rc-real-audio-220-32-keys.o \ rc-real-audio-220-32-keys.o \
......
/* empty.h - Keytable for empty Remote Controller
*
* keymap imported from ir-keymaps.c
*
* Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
/* empty keytable, can be used as placeholder for not-yet created keytables */
static struct ir_scancode empty[] = {
{ 0x2a, KEY_COFFEE },
};
static struct rc_keymap empty_map = {
.map = {
.scan = empty,
.size = ARRAY_SIZE(empty),
.ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_EMPTY,
}
};
static int __init init_rc_map_empty(void)
{
return ir_register_map(&empty_map);
}
static void __exit exit_rc_map_empty(void)
{
ir_unregister_map(&empty_map);
}
module_init(init_rc_map_empty)
module_exit(exit_rc_map_empty)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
/* rc-rc5-streamzap.c - Keytable for Streamzap PC Remote, for use
* with the Streamzap PC Remote IR Receiver.
*
* Copyright (c) 2010 by Jarod Wilson <jarod@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <media/rc-map.h>
static struct ir_scancode rc5_streamzap[] = {
/*
* FIXME: The Streamzap remote isn't actually true RC-5, it has an extra
* bit in it, which presently throws the in-kernel RC-5 decoder for a loop.
* We either have to enhance the decoder to support it, add a new decoder,
* or just rely on lirc userspace decoding.
*/
{ 0x00, KEY_NUMERIC_0 },
{ 0x01, KEY_NUMERIC_1 },
{ 0x02, KEY_NUMERIC_2 },
{ 0x03, KEY_NUMERIC_3 },
{ 0x04, KEY_NUMERIC_4 },
{ 0x05, KEY_NUMERIC_5 },
{ 0x06, KEY_NUMERIC_6 },
{ 0x07, KEY_NUMERIC_7 },
{ 0x08, KEY_NUMERIC_8 },
{ 0x0a, KEY_POWER },
{ 0x0b, KEY_MUTE },
{ 0x0c, KEY_CHANNELUP },
{ 0x0d, KEY_VOLUMEUP },
{ 0x0e, KEY_CHANNELDOWN },
{ 0x0f, KEY_VOLUMEDOWN },
{ 0x10, KEY_UP },
{ 0x11, KEY_LEFT },
{ 0x12, KEY_OK },
{ 0x13, KEY_RIGHT },
{ 0x14, KEY_DOWN },
{ 0x15, KEY_MENU },
{ 0x16, KEY_EXIT },
{ 0x17, KEY_PLAY },
{ 0x18, KEY_PAUSE },
{ 0x19, KEY_STOP },
{ 0x1a, KEY_BACK },
{ 0x1b, KEY_FORWARD },
{ 0x1c, KEY_RECORD },
{ 0x1d, KEY_REWIND },
{ 0x1e, KEY_FASTFORWARD },
{ 0x20, KEY_RED },
{ 0x21, KEY_GREEN },
{ 0x22, KEY_YELLOW },
{ 0x23, KEY_BLUE },
};
static struct rc_keymap rc5_streamzap_map = {
.map = {
.scan = rc5_streamzap,
.size = ARRAY_SIZE(rc5_streamzap),
.ir_type = IR_TYPE_RC5,
.name = RC_MAP_RC5_STREAMZAP,
}
};
static int __init init_rc_map_rc5_streamzap(void)
{
return ir_register_map(&rc5_streamzap_map);
}
static void __exit exit_rc_map_rc5_streamzap(void)
{
ir_unregister_map(&rc5_streamzap_map);
}
module_init(init_rc_map_rc5_streamzap)
module_exit(exit_rc_map_rc5_streamzap)
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jarod Wilson <jarod@redhat.com>");
...@@ -74,6 +74,8 @@ static struct ir_scancode rc6_mce[] = { ...@@ -74,6 +74,8 @@ static struct ir_scancode rc6_mce[] = {
{ 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */ { 0x800f045a, KEY_SUBTITLE }, /* Caption/Teletext */
{ 0x800f044d, KEY_TITLE }, { 0x800f044d, KEY_TITLE },
{ 0x800f044e, KEY_PRINT }, /* Print - HP OEM version of remote */
{ 0x800f040c, KEY_POWER }, { 0x800f040c, KEY_POWER },
{ 0x800f040d, KEY_PROG1 }, /* Windows MCE button */ { 0x800f040d, KEY_PROG1 }, /* Windows MCE button */
......
...@@ -228,7 +228,6 @@ static struct usb_device_id std_tx_mask_list[] = { ...@@ -228,7 +228,6 @@ static struct usb_device_id std_tx_mask_list[] = {
/* data structure for each usb transceiver */ /* data structure for each usb transceiver */
struct mceusb_dev { struct mceusb_dev {
/* ir-core bits */ /* ir-core bits */
struct ir_input_dev *irdev;
struct ir_dev_props *props; struct ir_dev_props *props;
struct ir_raw_event rawir; struct ir_raw_event rawir;
...@@ -428,7 +427,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf, ...@@ -428,7 +427,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
} }
} }
static void usb_async_callback(struct urb *urb, struct pt_regs *regs) static void mce_async_callback(struct urb *urb, struct pt_regs *regs)
{ {
struct mceusb_dev *ir; struct mceusb_dev *ir;
int len; int len;
...@@ -477,7 +476,7 @@ static void mce_request_packet(struct mceusb_dev *ir, ...@@ -477,7 +476,7 @@ static void mce_request_packet(struct mceusb_dev *ir,
/* outbound data */ /* outbound data */
usb_fill_int_urb(async_urb, ir->usbdev, usb_fill_int_urb(async_urb, ir->usbdev,
usb_sndintpipe(ir->usbdev, ep->bEndpointAddress), usb_sndintpipe(ir->usbdev, ep->bEndpointAddress),
async_buf, size, (usb_complete_t) usb_async_callback, async_buf, size, (usb_complete_t)mce_async_callback,
ir, ep->bInterval); ir, ep->bInterval);
memcpy(async_buf, data, size); memcpy(async_buf, data, size);
...@@ -739,7 +738,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs) ...@@ -739,7 +738,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
if (ir->send_flags == RECV_FLAG_IN_PROGRESS) { if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
ir->send_flags = SEND_FLAG_COMPLETE; ir->send_flags = SEND_FLAG_COMPLETE;
dev_dbg(&ir->irdev->dev, "setup answer received %d bytes\n", dev_dbg(ir->dev, "setup answer received %d bytes\n",
buf_len); buf_len);
} }
...@@ -861,7 +860,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir) ...@@ -861,7 +860,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
{ {
struct input_dev *idev; struct input_dev *idev;
struct ir_dev_props *props; struct ir_dev_props *props;
struct ir_input_dev *irdev;
struct device *dev = ir->dev; struct device *dev = ir->dev;
int ret = -ENODEV; int ret = -ENODEV;
...@@ -878,12 +876,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir) ...@@ -878,12 +876,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
goto props_alloc_failed; goto props_alloc_failed;
} }
irdev = kzalloc(sizeof(struct ir_input_dev), GFP_KERNEL);
if (!irdev) {
dev_err(dev, "remote ir input dev allocation failed\n");
goto ir_dev_alloc_failed;
}
snprintf(ir->name, sizeof(ir->name), "Media Center Ed. eHome " snprintf(ir->name, sizeof(ir->name), "Media Center Ed. eHome "
"Infrared Remote Transceiver (%04x:%04x)", "Infrared Remote Transceiver (%04x:%04x)",
le16_to_cpu(ir->usbdev->descriptor.idVendor), le16_to_cpu(ir->usbdev->descriptor.idVendor),
...@@ -902,9 +894,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir) ...@@ -902,9 +894,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
props->tx_ir = mceusb_tx_ir; props->tx_ir = mceusb_tx_ir;
ir->props = props; ir->props = props;
ir->irdev = irdev;
input_set_drvdata(idev, irdev);
ret = ir_input_register(idev, RC_MAP_RC6_MCE, props, DRIVER_NAME); ret = ir_input_register(idev, RC_MAP_RC6_MCE, props, DRIVER_NAME);
if (ret < 0) { if (ret < 0) {
...@@ -915,8 +904,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir) ...@@ -915,8 +904,6 @@ static struct input_dev *mceusb_init_input_dev(struct mceusb_dev *ir)
return idev; return idev;
irdev_failed: irdev_failed:
kfree(irdev);
ir_dev_alloc_failed:
kfree(props); kfree(props);
props_alloc_failed: props_alloc_failed:
input_free_device(idev); input_free_device(idev);
...@@ -932,7 +919,6 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, ...@@ -932,7 +919,6 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
struct usb_endpoint_descriptor *ep = NULL; struct usb_endpoint_descriptor *ep = NULL;
struct usb_endpoint_descriptor *ep_in = NULL; struct usb_endpoint_descriptor *ep_in = NULL;
struct usb_endpoint_descriptor *ep_out = NULL; struct usb_endpoint_descriptor *ep_out = NULL;
struct usb_host_config *config;
struct mceusb_dev *ir = NULL; struct mceusb_dev *ir = NULL;
int pipe, maxp, i; int pipe, maxp, i;
char buf[63], name[128] = ""; char buf[63], name[128] = "";
...@@ -942,7 +928,6 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf, ...@@ -942,7 +928,6 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
dev_dbg(&intf->dev, ": %s called\n", __func__); dev_dbg(&intf->dev, ": %s called\n", __func__);
config = dev->actconfig;
idesc = intf->cur_altsetting; idesc = intf->cur_altsetting;
is_gen3 = usb_match_id(intf, gen3_list) ? 1 : 0; is_gen3 = usb_match_id(intf, gen3_list) ? 1 : 0;
......
...@@ -82,3 +82,26 @@ void ir_unregister_map(struct rc_keymap *map) ...@@ -82,3 +82,26 @@ void ir_unregister_map(struct rc_keymap *map)
} }
EXPORT_SYMBOL_GPL(ir_unregister_map); EXPORT_SYMBOL_GPL(ir_unregister_map);
static struct ir_scancode empty[] = {
{ 0x2a, KEY_COFFEE },
};
static struct rc_keymap empty_map = {
.map = {
.scan = empty,
.size = ARRAY_SIZE(empty),
.ir_type = IR_TYPE_UNKNOWN, /* Legacy IR type */
.name = RC_MAP_EMPTY,
}
};
int ir_rcmap_init(void)
{
return ir_register_map(&empty_map);
}
void ir_rcmap_cleanup(void)
{
ir_unregister_map(&empty_map);
}
...@@ -34,7 +34,7 @@ config MEDIA_TUNER ...@@ -34,7 +34,7 @@ config MEDIA_TUNER
menuconfig MEDIA_TUNER_CUSTOMISE menuconfig MEDIA_TUNER_CUSTOMISE
bool "Customize analog and hybrid tuner modules to build" bool "Customize analog and hybrid tuner modules to build"
depends on MEDIA_TUNER depends on MEDIA_TUNER
default n default y if EMBEDDED
help help
This allows the user to deselect tuner drivers unnecessary This allows the user to deselect tuner drivers unnecessary
for their hardware from the build. Use this option with care for their hardware from the build. Use this option with care
......
...@@ -1763,7 +1763,15 @@ static struct dvb_frontend_ops dst_dvbt_ops = { ...@@ -1763,7 +1763,15 @@ static struct dvb_frontend_ops dst_dvbt_ops = {
.frequency_min = 137000000, .frequency_min = 137000000,
.frequency_max = 858000000, .frequency_max = 858000000,
.frequency_stepsize = 166667, .frequency_stepsize = 166667,
.caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO .caps = FE_CAN_FEC_AUTO |
FE_CAN_QAM_AUTO |
FE_CAN_QAM_16 |
FE_CAN_QAM_32 |
FE_CAN_QAM_64 |
FE_CAN_QAM_128 |
FE_CAN_QAM_256 |
FE_CAN_TRANSMISSION_MODE_AUTO |
FE_CAN_GUARD_INTERVAL_AUTO
}, },
.release = dst_release, .release = dst_release,
......
config DVB_FE_CUSTOMISE config DVB_FE_CUSTOMISE
bool "Customise the frontend modules to build" bool "Customise the frontend modules to build"
depends on DVB_CORE depends on DVB_CORE
default N default y if EMBEDDED
help help
This allows the user to select/deselect frontend drivers for their This allows the user to select/deselect frontend drivers for their
hardware from the build. hardware from the build.
......
...@@ -1113,9 +1113,11 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) ...@@ -1113,9 +1113,11 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev)
*/ */
prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE); prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE);
if (list_empty(&coredev->buffers)) {
if (list_empty(&coredev->buffers)) spin_unlock_irqrestore(&coredev->bufferslock, flags);
schedule(); schedule();
spin_lock_irqsave(&coredev->bufferslock, flags);
}
finish_wait(&coredev->buffer_mng_waitq, &wait); finish_wait(&coredev->buffer_mng_waitq, &wait);
......
...@@ -83,7 +83,7 @@ config VIDEO_FIXED_MINOR_RANGES ...@@ -83,7 +83,7 @@ config VIDEO_FIXED_MINOR_RANGES
config VIDEO_HELPER_CHIPS_AUTO config VIDEO_HELPER_CHIPS_AUTO
bool "Autoselect pertinent encoders/decoders and other helper chips" bool "Autoselect pertinent encoders/decoders and other helper chips"
default y default y if !EMBEDDED
---help--- ---help---
Most video cards may require additional modules to encode or Most video cards may require additional modules to encode or
decode audio/video standards. This option will autoselect decode audio/video standards. This option will autoselect
...@@ -792,10 +792,11 @@ config SOC_CAMERA_MT9M001 ...@@ -792,10 +792,11 @@ config SOC_CAMERA_MT9M001
and colour models. and colour models.
config SOC_CAMERA_MT9M111 config SOC_CAMERA_MT9M111
tristate "mt9m111 and mt9m112 support" tristate "mt9m111, mt9m112 and mt9m131 support"
depends on SOC_CAMERA && I2C depends on SOC_CAMERA && I2C
help help
This driver supports MT9M111 and MT9M112 cameras from Micron This driver supports MT9M111, MT9M112 and MT9M131 cameras from
Micron/Aptina
config SOC_CAMERA_MT9T031 config SOC_CAMERA_MT9T031
tristate "mt9t031 support" tristate "mt9t031 support"
...@@ -1016,4 +1017,13 @@ config VIDEO_MEM2MEM_TESTDEV ...@@ -1016,4 +1017,13 @@ config VIDEO_MEM2MEM_TESTDEV
This is a virtual test device for the memory-to-memory driver This is a virtual test device for the memory-to-memory driver
framework. framework.
config VIDEO_SAMSUNG_S5P_FIMC
tristate "Samsung S5P FIMC (video postprocessor) driver"
depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
select VIDEOBUF_DMA_CONTIG
select V4L2_MEM2MEM_DEV
help
This is a v4l2 driver for the S5P camera interface
(video postprocessor)
endif # V4L_MEM2MEM_DRIVERS endif # V4L_MEM2MEM_DRIVERS
...@@ -11,7 +11,7 @@ stkwebcam-objs := stk-webcam.o stk-sensor.o ...@@ -11,7 +11,7 @@ stkwebcam-objs := stk-webcam.o stk-sensor.o
omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o omap2cam-objs := omap24xxcam.o omap24xxcam-dma.o
videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \ videodev-objs := v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
v4l2-event.o v4l2-event.o v4l2-ctrls.o
# V4L2 core modules # V4L2 core modules
...@@ -163,6 +163,7 @@ obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o ...@@ -163,6 +163,7 @@ obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o
obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2) += sh_mobile_csi2.o
obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) += s5p-fimc/
obj-$(CONFIG_ARCH_DAVINCI) += davinci/ obj-$(CONFIG_ARCH_DAVINCI) += davinci/
......
...@@ -26,10 +26,10 @@ ...@@ -26,10 +26,10 @@
#include <linux/ioctl.h> #include <linux/ioctl.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h> #include <media/v4l2-chip-ident.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-i2c-drv.h> #include <media/v4l2-i2c-drv.h>
MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC"); MODULE_DESCRIPTION("i2c device driver for cs53l32a Audio ADC");
...@@ -43,6 +43,21 @@ module_param(debug, bool, 0644); ...@@ -43,6 +43,21 @@ module_param(debug, bool, 0644);
MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On"); MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On");
struct cs53l32a_state {
struct v4l2_subdev sd;
struct v4l2_ctrl_handler hdl;
};
static inline struct cs53l32a_state *to_state(struct v4l2_subdev *sd)
{
return container_of(sd, struct cs53l32a_state, sd);
}
static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
{
return &container_of(ctrl->handler, struct cs53l32a_state, hdl)->sd;
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int cs53l32a_write(struct v4l2_subdev *sd, u8 reg, u8 value) static int cs53l32a_write(struct v4l2_subdev *sd, u8 reg, u8 value)
...@@ -74,31 +89,20 @@ static int cs53l32a_s_routing(struct v4l2_subdev *sd, ...@@ -74,31 +89,20 @@ static int cs53l32a_s_routing(struct v4l2_subdev *sd,
return 0; return 0;
} }
static int cs53l32a_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) static int cs53l32a_s_ctrl(struct v4l2_ctrl *ctrl)
{ {
if (ctrl->id == V4L2_CID_AUDIO_MUTE) { struct v4l2_subdev *sd = to_sd(ctrl);
ctrl->value = (cs53l32a_read(sd, 0x03) & 0xc0) != 0;
return 0;
}
if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
return -EINVAL;
ctrl->value = (s8)cs53l32a_read(sd, 0x04);
return 0;
}
static int cs53l32a_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) switch (ctrl->id) {
{ case V4L2_CID_AUDIO_MUTE:
if (ctrl->id == V4L2_CID_AUDIO_MUTE) { cs53l32a_write(sd, 0x03, ctrl->val ? 0xf0 : 0x30);
cs53l32a_write(sd, 0x03, ctrl->value ? 0xf0 : 0x30); return 0;
case V4L2_CID_AUDIO_VOLUME:
cs53l32a_write(sd, 0x04, (u8)ctrl->val);
cs53l32a_write(sd, 0x05, (u8)ctrl->val);
return 0; return 0;
} }
if (ctrl->id != V4L2_CID_AUDIO_VOLUME) return -EINVAL;
return -EINVAL;
if (ctrl->value > 12 || ctrl->value < -96)
return -EINVAL;
cs53l32a_write(sd, 0x04, (u8) ctrl->value);
cs53l32a_write(sd, 0x05, (u8) ctrl->value);
return 0;
} }
static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip) static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
...@@ -111,23 +115,30 @@ static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_id ...@@ -111,23 +115,30 @@ static int cs53l32a_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_id
static int cs53l32a_log_status(struct v4l2_subdev *sd) static int cs53l32a_log_status(struct v4l2_subdev *sd)
{ {
struct cs53l32a_state *state = to_state(sd);
u8 v = cs53l32a_read(sd, 0x01); u8 v = cs53l32a_read(sd, 0x01);
u8 m = cs53l32a_read(sd, 0x03);
s8 vol = cs53l32a_read(sd, 0x04);
v4l2_info(sd, "Input: %d%s\n", (v >> 4) & 3, v4l2_info(sd, "Input: %d\n", (v >> 4) & 3);
(m & 0xC0) ? " (muted)" : ""); v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
v4l2_info(sd, "Volume: %d dB\n", vol);
return 0; return 0;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static const struct v4l2_ctrl_ops cs53l32a_ctrl_ops = {
.s_ctrl = cs53l32a_s_ctrl,
};
static const struct v4l2_subdev_core_ops cs53l32a_core_ops = { static const struct v4l2_subdev_core_ops cs53l32a_core_ops = {
.log_status = cs53l32a_log_status, .log_status = cs53l32a_log_status,
.g_chip_ident = cs53l32a_g_chip_ident, .g_chip_ident = cs53l32a_g_chip_ident,
.g_ctrl = cs53l32a_g_ctrl, .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
.s_ctrl = cs53l32a_s_ctrl, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
.g_ctrl = v4l2_subdev_g_ctrl,
.s_ctrl = v4l2_subdev_s_ctrl,
.queryctrl = v4l2_subdev_queryctrl,
.querymenu = v4l2_subdev_querymenu,
}; };
static const struct v4l2_subdev_audio_ops cs53l32a_audio_ops = { static const struct v4l2_subdev_audio_ops cs53l32a_audio_ops = {
...@@ -151,6 +162,7 @@ static const struct v4l2_subdev_ops cs53l32a_ops = { ...@@ -151,6 +162,7 @@ static const struct v4l2_subdev_ops cs53l32a_ops = {
static int cs53l32a_probe(struct i2c_client *client, static int cs53l32a_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct cs53l32a_state *state;
struct v4l2_subdev *sd; struct v4l2_subdev *sd;
int i; int i;
...@@ -164,9 +176,10 @@ static int cs53l32a_probe(struct i2c_client *client, ...@@ -164,9 +176,10 @@ static int cs53l32a_probe(struct i2c_client *client,
v4l_info(client, "chip found @ 0x%x (%s)\n", v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name); client->addr << 1, client->adapter->name);
sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL); state = kzalloc(sizeof(struct cs53l32a_state), GFP_KERNEL);
if (sd == NULL) if (state == NULL)
return -ENOMEM; return -ENOMEM;
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &cs53l32a_ops); v4l2_i2c_subdev_init(sd, client, &cs53l32a_ops);
for (i = 1; i <= 7; i++) { for (i = 1; i <= 7; i++) {
...@@ -175,15 +188,29 @@ static int cs53l32a_probe(struct i2c_client *client, ...@@ -175,15 +188,29 @@ static int cs53l32a_probe(struct i2c_client *client,
v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v); v4l2_dbg(1, debug, sd, "Read Reg %d %02x\n", i, v);
} }
v4l2_ctrl_handler_init(&state->hdl, 2);
v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
V4L2_CID_AUDIO_VOLUME, -96, 12, 1, 0);
v4l2_ctrl_new_std(&state->hdl, &cs53l32a_ctrl_ops,
V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
sd->ctrl_handler = &state->hdl;
if (state->hdl.error) {
int err = state->hdl.error;
v4l2_ctrl_handler_free(&state->hdl);
kfree(state);
return err;
}
/* Set cs53l32a internal register for Adaptec 2010/2410 setup */ /* Set cs53l32a internal register for Adaptec 2010/2410 setup */
cs53l32a_write(sd, 0x01, (u8) 0x21); cs53l32a_write(sd, 0x01, 0x21);
cs53l32a_write(sd, 0x02, (u8) 0x29); cs53l32a_write(sd, 0x02, 0x29);
cs53l32a_write(sd, 0x03, (u8) 0x30); cs53l32a_write(sd, 0x03, 0x30);
cs53l32a_write(sd, 0x04, (u8) 0x00); cs53l32a_write(sd, 0x04, 0x00);
cs53l32a_write(sd, 0x05, (u8) 0x00); cs53l32a_write(sd, 0x05, 0x00);
cs53l32a_write(sd, 0x06, (u8) 0x00); cs53l32a_write(sd, 0x06, 0x00);
cs53l32a_write(sd, 0x07, (u8) 0x00); cs53l32a_write(sd, 0x07, 0x00);
/* Display results, should be 0x21,0x29,0x30,0x00,0x00,0x00,0x00 */ /* Display results, should be 0x21,0x29,0x30,0x00,0x00,0x00,0x00 */
...@@ -198,9 +225,11 @@ static int cs53l32a_probe(struct i2c_client *client, ...@@ -198,9 +225,11 @@ static int cs53l32a_probe(struct i2c_client *client,
static int cs53l32a_remove(struct i2c_client *client) static int cs53l32a_remove(struct i2c_client *client)
{ {
struct v4l2_subdev *sd = i2c_get_clientdata(client); struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct cs53l32a_state *state = to_state(sd);
v4l2_device_unregister_subdev(sd); v4l2_device_unregister_subdev(sd);
kfree(sd); v4l2_ctrl_handler_free(&state->hdl);
kfree(state);
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -5,7 +5,7 @@ config VIDEO_CX23885 ...@@ -5,7 +5,7 @@ config VIDEO_CX23885
select VIDEO_BTCX select VIDEO_BTCX
select VIDEO_TUNER select VIDEO_TUNER
select VIDEO_TVEEPROM select VIDEO_TVEEPROM
select VIDEO_IR select IR_CORE
select VIDEOBUF_DVB select VIDEOBUF_DVB
select VIDEOBUF_DMA_SG select VIDEOBUF_DMA_SG
select VIDEO_CX25840 select VIDEO_CX25840
......
cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \ cx23885-objs := cx23885-cards.o cx23885-video.o cx23885-vbi.o \
cx23885-core.o cx23885-i2c.o cx23885-dvb.o cx23885-417.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 \ cx23885-ioctl.o cx23885-ir.o cx23885-av.o cx23885-input.o \
netup-init.o cimax2.o netup-eeprom.o cx23885-f300.o cx23888-ir.o netup-init.o cimax2.o netup-eeprom.o \
cx23885-f300.o
obj-$(CONFIG_VIDEO_CX23885) += cx23885.o obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
......
/*
* 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);
}
/*
* 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
...@@ -30,6 +30,16 @@ ...@@ -30,6 +30,16 @@
#include "netup-init.h" #include "netup-init.h"
#include "cx23888-ir.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 */ /* board config info */
...@@ -626,6 +636,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) ...@@ -626,6 +636,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
case 79101: case 79101:
/* WinTV-HVR1250 (PCIe, Retail, IR, half height, /* WinTV-HVR1250 (PCIe, Retail, IR, half height,
ATSC and Basic analog */ ATSC and Basic analog */
case 79501:
/* WinTV-HVR1250 (PCIe, No IR, half height,
ATSC [at least] and Basic analog) */
case 79561: case 79561:
/* WinTV-HVR1250 (PCIe, OEM, No IR, half height, /* WinTV-HVR1250 (PCIe, OEM, No IR, half height,
ATSC and Basic analog */ ATSC and Basic analog */
...@@ -959,9 +972,37 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) ...@@ -959,9 +972,37 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
int cx23885_ir_init(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; int ret = 0;
switch (dev->board) { switch (dev->board) {
case CX23885_BOARD_HAUPPAUGE_HVR1250:
case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500:
case CX23885_BOARD_HAUPPAUGE_HVR1500Q: case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1800:
...@@ -979,7 +1020,41 @@ int cx23885_ir_init(struct cx23885_dev *dev) ...@@ -979,7 +1020,41 @@ int cx23885_ir_init(struct cx23885_dev *dev)
if (ret) if (ret)
break; break;
dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR); 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, &params);
params.enable = false;
params.shutdown = false;
params.invert_level = true;
v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, &params);
params.shutdown = true;
v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, &params);
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; break;
case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP:
request_module("ir-kbd-i2c"); request_module("ir-kbd-i2c");
...@@ -994,11 +1069,16 @@ void cx23885_ir_fini(struct cx23885_dev *dev) ...@@ -994,11 +1069,16 @@ void cx23885_ir_fini(struct cx23885_dev *dev)
switch (dev->board) { switch (dev->board) {
case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1850:
case CX23885_BOARD_HAUPPAUGE_HVR1290: case CX23885_BOARD_HAUPPAUGE_HVR1290:
dev->pci_irqmask &= ~PCI_MSK_IR; cx23885_irq_remove(dev, PCI_MSK_IR);
cx_clear(PCI_INT_MSK, PCI_MSK_IR);
cx23888_ir_remove(dev); cx23888_ir_remove(dev);
dev->sd_ir = NULL; dev->sd_ir = NULL;
break; 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;
} }
} }
...@@ -1007,8 +1087,13 @@ void cx23885_ir_pci_int_enable(struct cx23885_dev *dev) ...@@ -1007,8 +1087,13 @@ void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
switch (dev->board) { switch (dev->board) {
case CX23885_BOARD_HAUPPAUGE_HVR1850: case CX23885_BOARD_HAUPPAUGE_HVR1850:
case CX23885_BOARD_HAUPPAUGE_HVR1290: case CX23885_BOARD_HAUPPAUGE_HVR1290:
if (dev->sd_ir && (dev->pci_irqmask & PCI_MSK_IR)) if (dev->sd_ir)
cx_set(PCI_INT_MSK, PCI_MSK_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; break;
} }
} }
...@@ -1028,6 +1113,13 @@ void cx23885_card_setup(struct cx23885_dev *dev) ...@@ -1028,6 +1113,13 @@ void cx23885_card_setup(struct cx23885_dev *dev)
switch (dev->board) { switch (dev->board) {
case CX23885_BOARD_HAUPPAUGE_HVR1250: 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_HVR1500:
case CX23885_BOARD_HAUPPAUGE_HVR1500Q: case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
case CX23885_BOARD_HAUPPAUGE_HVR1400: case CX23885_BOARD_HAUPPAUGE_HVR1400:
...@@ -1136,6 +1228,11 @@ void cx23885_card_setup(struct cx23885_dev *dev) ...@@ -1136,6 +1228,11 @@ void cx23885_card_setup(struct cx23885_dev *dev)
* loaded, ensure this happens. * loaded, ensure this happens.
*/ */
switch (dev->board) { 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_HVR1800:
case CX23885_BOARD_HAUPPAUGE_HVR1800lp: case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
case CX23885_BOARD_HAUPPAUGE_HVR1700: case CX23885_BOARD_HAUPPAUGE_HVR1700:
...@@ -1151,7 +1248,10 @@ void cx23885_card_setup(struct cx23885_dev *dev) ...@@ -1151,7 +1248,10 @@ void cx23885_card_setup(struct cx23885_dev *dev)
dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
&dev->i2c_bus[2].i2c_adap, &dev->i2c_bus[2].i2c_adap,
"cx25840", "cx25840", 0x88 >> 1, NULL); "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; break;
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -213,6 +213,7 @@ Channel manager Data Structure entry = 20 DWORD ...@@ -213,6 +213,7 @@ Channel manager Data Structure entry = 20 DWORD
#define DEV_CNTRL2 0x00040000 #define DEV_CNTRL2 0x00040000
#define PCI_MSK_IR (1 << 28) #define PCI_MSK_IR (1 << 28)
#define PCI_MSK_AV_CORE (1 << 27)
#define PCI_MSK_GPIO1 (1 << 24) #define PCI_MSK_GPIO1 (1 << 24)
#define PCI_MSK_GPIO0 (1 << 23) #define PCI_MSK_GPIO0 (1 << 23)
#define PCI_MSK_APB_DMA (1 << 12) #define PCI_MSK_APB_DMA (1 << 12)
......
...@@ -74,7 +74,7 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev, ...@@ -74,7 +74,7 @@ static int cx23885_start_vbi_dma(struct cx23885_dev *dev,
q->count = 1; q->count = 1;
/* enable irqs */ /* 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); cx_set(VID_A_INT_MSK, 0x000022);
/* start dma */ /* start dma */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC) := s5p-fimc.o
s5p-fimc-y := fimc-core.o fimc-reg.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment