V4L/DVB (8123): Add support for em2860 based PointNix Intra-Oral Camera
em28xx-cards.c em28xx-input.c em28xx-video.c em28xx.h - Add support for the PointNix Intra-Oral Camera, which required addition of a construct for reading the "snapshot" button (provided on the em2860 and em2880 chips, but this is the first case where I have seen it actually used in a product). The button is wired to pin 56 on the em2880. http://www.pointnix.com/ENG/dental/product_02.asp Thanks to Roberto Mantovani <rmantovani@libero.it> for testing the changes Signed-off-by: Devin Heitmueller <devin.heitmueller@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
Родитель
305519c924
Коммит
a9fc52bcbe
|
@ -17,3 +17,4 @@
|
|||
16 -> Hauppauge WinTV HVR 950 (em2880) [2040:6513,2040:6517,2040:651b,2040:651f]
|
||||
17 -> Pinnacle PCTV HD Pro Stick (em2880) [2304:0227]
|
||||
18 -> Hauppauge WinTV HVR 900 (R2) (em2880) [2040:6502]
|
||||
19 -> PointNix Intra-Oral Camera (em2860)
|
||||
|
|
|
@ -426,6 +426,19 @@ struct em28xx_board em28xx_boards[] = {
|
|||
.amux = EM28XX_AMUX_LINE_IN,
|
||||
} },
|
||||
},
|
||||
[EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA] = {
|
||||
.name = "PointNix Intra-Oral Camera",
|
||||
.has_snapshot_button = 1,
|
||||
.vchannels = 1,
|
||||
.tda9887_conf = TDA9887_PRESENT,
|
||||
.tuner_type = TUNER_ABSENT,
|
||||
.decoder = EM28XX_SAA7113,
|
||||
.input = { {
|
||||
.type = EM28XX_VMUX_SVIDEO,
|
||||
.vmux = SAA7115_SVIDEO3,
|
||||
.amux = 0,
|
||||
} },
|
||||
},
|
||||
};
|
||||
const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
|
||||
|
||||
|
@ -522,6 +535,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash [] = {
|
|||
static struct em28xx_hash_table em28xx_i2c_hash[] = {
|
||||
{0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC},
|
||||
{0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC},
|
||||
{0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT},
|
||||
};
|
||||
|
||||
int em28xx_tuner_callback(void *ptr, int command, int arg)
|
||||
|
@ -554,6 +568,7 @@ static void em28xx_set_model(struct em28xx *dev)
|
|||
dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
|
||||
dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
|
||||
dev->has_dvb = em28xx_boards[dev->model].has_dvb;
|
||||
dev->has_snapshot_button = em28xx_boards[dev->model].has_snapshot_button;
|
||||
}
|
||||
|
||||
/* Since em28xx_pre_card_setup() requires a proper dev->model,
|
||||
|
@ -841,6 +856,9 @@ void em28xx_card_setup(struct em28xx *dev)
|
|||
em28xx_set_model(dev);
|
||||
}
|
||||
|
||||
if (dev->has_snapshot_button)
|
||||
em28xx_register_snapshot_button(dev);
|
||||
|
||||
/* Allow override tuner type by a module parameter */
|
||||
if (tuner >= 0)
|
||||
dev->tuner_type = tuner;
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
|
||||
#include "em28xx.h"
|
||||
|
||||
#define EM28XX_SNAPSHOT_KEY KEY_CAMERA
|
||||
#define EM28XX_SBUTTON_QUERY_INTERVAL 500
|
||||
#define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20
|
||||
|
||||
static unsigned int ir_debug;
|
||||
module_param(ir_debug, int, 0644);
|
||||
MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]");
|
||||
|
@ -124,6 +128,89 @@ int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void em28xx_query_sbutton(struct work_struct *work)
|
||||
{
|
||||
/* Poll the register and see if the button is depressed */
|
||||
struct em28xx *dev =
|
||||
container_of(work, struct em28xx, sbutton_query_work.work);
|
||||
int ret;
|
||||
|
||||
ret = em28xx_read_reg(dev, EM28XX_R0C_USBSUSP);
|
||||
|
||||
if (ret & EM28XX_R0C_USBSUSP_SNAPSHOT) {
|
||||
u8 cleared;
|
||||
/* Button is depressed, clear the register */
|
||||
cleared = ((u8) ret) & ~EM28XX_R0C_USBSUSP_SNAPSHOT;
|
||||
em28xx_write_regs(dev, EM28XX_R0C_USBSUSP, &cleared, 1);
|
||||
|
||||
/* Not emulate the keypress */
|
||||
input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY,
|
||||
1);
|
||||
/* Now unpress the key */
|
||||
input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY,
|
||||
0);
|
||||
}
|
||||
|
||||
/* Schedule next poll */
|
||||
schedule_delayed_work(&dev->sbutton_query_work,
|
||||
msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL));
|
||||
}
|
||||
|
||||
void em28xx_register_snapshot_button(struct em28xx *dev)
|
||||
{
|
||||
struct input_dev *input_dev;
|
||||
int err;
|
||||
|
||||
em28xx_info("Registering snapshot button...\n");
|
||||
input_dev = input_allocate_device();
|
||||
if (!input_dev) {
|
||||
em28xx_errdev("input_allocate_device failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
usb_make_path(dev->udev, dev->snapshot_button_path,
|
||||
sizeof(dev->snapshot_button_path));
|
||||
strlcat(dev->snapshot_button_path, "/sbutton",
|
||||
sizeof(dev->snapshot_button_path));
|
||||
INIT_DELAYED_WORK(&dev->sbutton_query_work, em28xx_query_sbutton);
|
||||
|
||||
input_dev->name = "em28xx snapshot button";
|
||||
input_dev->phys = dev->snapshot_button_path;
|
||||
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
|
||||
set_bit(EM28XX_SNAPSHOT_KEY, input_dev->keybit);
|
||||
input_dev->keycodesize = 0;
|
||||
input_dev->keycodemax = 0;
|
||||
input_dev->id.bustype = BUS_USB;
|
||||
input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
|
||||
input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
|
||||
input_dev->id.version = 1;
|
||||
input_dev->dev.parent = &dev->udev->dev;
|
||||
|
||||
err = input_register_device(input_dev);
|
||||
if (err) {
|
||||
em28xx_errdev("input_register_device failed\n");
|
||||
input_free_device(input_dev);
|
||||
return;
|
||||
}
|
||||
|
||||
dev->sbutton_input_dev = input_dev;
|
||||
schedule_delayed_work(&dev->sbutton_query_work,
|
||||
msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL));
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
void em28xx_deregister_snapshot_button(struct em28xx *dev)
|
||||
{
|
||||
if (dev->sbutton_input_dev != NULL) {
|
||||
em28xx_info("Deregistering snapshot button\n");
|
||||
cancel_rearming_delayed_work(&dev->sbutton_query_work);
|
||||
input_unregister_device(dev->sbutton_input_dev);
|
||||
dev->sbutton_input_dev = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Local variables:
|
||||
* c-basic-offset: 8
|
||||
|
|
|
@ -1590,6 +1590,8 @@ static void em28xx_release_resources(struct em28xx *dev)
|
|||
dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN,
|
||||
dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN);
|
||||
list_del(&dev->devlist);
|
||||
if (dev->sbutton_input_dev)
|
||||
em28xx_deregister_snapshot_button(dev);
|
||||
if (dev->radio_dev) {
|
||||
if (-1 != dev->radio_dev->minor)
|
||||
video_unregister_device(dev->radio_dev);
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16
|
||||
#define EM2880_BOARD_PINNACLE_PCTV_HD_PRO 17
|
||||
#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 18
|
||||
#define EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA 19
|
||||
|
||||
/* Limits minimum and default number of buffers */
|
||||
#define EM28XX_MIN_BUF 4
|
||||
|
@ -249,6 +250,7 @@ struct em28xx_board {
|
|||
unsigned int has_12mhz_i2s:1;
|
||||
unsigned int max_range_640_480:1;
|
||||
unsigned int has_dvb:1;
|
||||
unsigned int has_snapshot_button:1;
|
||||
|
||||
enum em28xx_decoder decoder;
|
||||
|
||||
|
@ -328,6 +330,7 @@ struct em28xx {
|
|||
unsigned int has_12mhz_i2s:1;
|
||||
unsigned int max_range_640_480:1;
|
||||
unsigned int has_dvb:1;
|
||||
unsigned int has_snapshot_button:1;
|
||||
|
||||
/* Some older em28xx chips needs a waiting time after writing */
|
||||
unsigned int wait_after_write;
|
||||
|
@ -418,6 +421,11 @@ struct em28xx {
|
|||
/* Caches GPO and GPIO registers */
|
||||
unsigned char reg_gpo, reg_gpio;
|
||||
|
||||
/* Snapshot button */
|
||||
char snapshot_button_path[30]; /* path of the input dev */
|
||||
struct input_dev *sbutton_input_dev;
|
||||
struct delayed_work sbutton_query_work;
|
||||
|
||||
struct em28xx_dvb *dvb;
|
||||
};
|
||||
|
||||
|
@ -483,6 +491,8 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
|
|||
int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
|
||||
int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
|
||||
u32 *ir_raw);
|
||||
void em28xx_register_snapshot_button(struct em28xx *dev);
|
||||
void em28xx_deregister_snapshot_button(struct em28xx *dev);
|
||||
|
||||
/* printk macros */
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче