aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx
diff options
context:
space:
mode:
authorDevin Heitmueller <devin.heitmueller@gmail.com>2008-06-28 07:57:06 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-07-20 06:12:48 -0400
commita9fc52bcbeb5245b58d23c558f3e3e8f18bebbc3 (patch)
treebd0f1f54ed1ee0f3994a38ecebe6dc5fb00c4bc5 /drivers/media/video/em28xx
parent305519c924d8f2f2f85c390c6d456dc41dbe0284 (diff)
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>
Diffstat (limited to 'drivers/media/video/em28xx')
-rw-r--r--drivers/media/video/em28xx/em28xx-cards.c18
-rw-r--r--drivers/media/video/em28xx/em28xx-input.c87
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c2
-rw-r--r--drivers/media/video/em28xx/em28xx.h10
4 files changed, 117 insertions, 0 deletions
diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c
index 938c51e1c86d..05f0d5a15058 100644
--- a/drivers/media/video/em28xx/em28xx-cards.c
+++ b/drivers/media/video/em28xx/em28xx-cards.c
@@ -426,6 +426,19 @@ struct em28xx_board em28xx_boards[] = {
426 .amux = EM28XX_AMUX_LINE_IN, 426 .amux = EM28XX_AMUX_LINE_IN,
427 } }, 427 } },
428 }, 428 },
429 [EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA] = {
430 .name = "PointNix Intra-Oral Camera",
431 .has_snapshot_button = 1,
432 .vchannels = 1,
433 .tda9887_conf = TDA9887_PRESENT,
434 .tuner_type = TUNER_ABSENT,
435 .decoder = EM28XX_SAA7113,
436 .input = { {
437 .type = EM28XX_VMUX_SVIDEO,
438 .vmux = SAA7115_SVIDEO3,
439 .amux = 0,
440 } },
441 },
429}; 442};
430const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards); 443const unsigned int em28xx_bcount = ARRAY_SIZE(em28xx_boards);
431 444
@@ -522,6 +535,7 @@ static struct em28xx_hash_table em28xx_eeprom_hash [] = {
522static struct em28xx_hash_table em28xx_i2c_hash[] = { 535static struct em28xx_hash_table em28xx_i2c_hash[] = {
523 {0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC}, 536 {0xb06a32c3, EM2800_BOARD_TERRATEC_CINERGY_200, TUNER_LG_PAL_NEW_TAPC},
524 {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC}, 537 {0xf51200e3, EM2800_BOARD_VGEAR_POCKETTV, TUNER_LG_PAL_NEW_TAPC},
538 {0x1ba50080, EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA, TUNER_ABSENT},
525}; 539};
526 540
527int em28xx_tuner_callback(void *ptr, int command, int arg) 541int em28xx_tuner_callback(void *ptr, int command, int arg)
@@ -554,6 +568,7 @@ static void em28xx_set_model(struct em28xx *dev)
554 dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s; 568 dev->has_12mhz_i2s = em28xx_boards[dev->model].has_12mhz_i2s;
555 dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480; 569 dev->max_range_640_480 = em28xx_boards[dev->model].max_range_640_480;
556 dev->has_dvb = em28xx_boards[dev->model].has_dvb; 570 dev->has_dvb = em28xx_boards[dev->model].has_dvb;
571 dev->has_snapshot_button = em28xx_boards[dev->model].has_snapshot_button;
557} 572}
558 573
559/* Since em28xx_pre_card_setup() requires a proper dev->model, 574/* Since em28xx_pre_card_setup() requires a proper dev->model,
@@ -841,6 +856,9 @@ void em28xx_card_setup(struct em28xx *dev)
841 em28xx_set_model(dev); 856 em28xx_set_model(dev);
842 } 857 }
843 858
859 if (dev->has_snapshot_button)
860 em28xx_register_snapshot_button(dev);
861
844 /* Allow override tuner type by a module parameter */ 862 /* Allow override tuner type by a module parameter */
845 if (tuner >= 0) 863 if (tuner >= 0)
846 dev->tuner_type = tuner; 864 dev->tuner_type = tuner;
diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c
index bb5807159b8d..eab3d9511af3 100644
--- a/drivers/media/video/em28xx/em28xx-input.c
+++ b/drivers/media/video/em28xx/em28xx-input.c
@@ -30,6 +30,10 @@
30 30
31#include "em28xx.h" 31#include "em28xx.h"
32 32
33#define EM28XX_SNAPSHOT_KEY KEY_CAMERA
34#define EM28XX_SBUTTON_QUERY_INTERVAL 500
35#define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20
36
33static unsigned int ir_debug; 37static unsigned int ir_debug;
34module_param(ir_debug, int, 0644); 38module_param(ir_debug, int, 0644);
35MODULE_PARM_DESC(ir_debug, "enable debug messages [IR]"); 39MODULE_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,
124 return 1; 128 return 1;
125} 129}
126 130
131static void em28xx_query_sbutton(struct work_struct *work)
132{
133 /* Poll the register and see if the button is depressed */
134 struct em28xx *dev =
135 container_of(work, struct em28xx, sbutton_query_work.work);
136 int ret;
137
138 ret = em28xx_read_reg(dev, EM28XX_R0C_USBSUSP);
139
140 if (ret & EM28XX_R0C_USBSUSP_SNAPSHOT) {
141 u8 cleared;
142 /* Button is depressed, clear the register */
143 cleared = ((u8) ret) & ~EM28XX_R0C_USBSUSP_SNAPSHOT;
144 em28xx_write_regs(dev, EM28XX_R0C_USBSUSP, &cleared, 1);
145
146 /* Not emulate the keypress */
147 input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY,
148 1);
149 /* Now unpress the key */
150 input_report_key(dev->sbutton_input_dev, EM28XX_SNAPSHOT_KEY,
151 0);
152 }
153
154 /* Schedule next poll */
155 schedule_delayed_work(&dev->sbutton_query_work,
156 msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL));
157}
158
159void em28xx_register_snapshot_button(struct em28xx *dev)
160{
161 struct input_dev *input_dev;
162 int err;
163
164 em28xx_info("Registering snapshot button...\n");
165 input_dev = input_allocate_device();
166 if (!input_dev) {
167 em28xx_errdev("input_allocate_device failed\n");
168 return;
169 }
170
171 usb_make_path(dev->udev, dev->snapshot_button_path,
172 sizeof(dev->snapshot_button_path));
173 strlcat(dev->snapshot_button_path, "/sbutton",
174 sizeof(dev->snapshot_button_path));
175 INIT_DELAYED_WORK(&dev->sbutton_query_work, em28xx_query_sbutton);
176
177 input_dev->name = "em28xx snapshot button";
178 input_dev->phys = dev->snapshot_button_path;
179 input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
180 set_bit(EM28XX_SNAPSHOT_KEY, input_dev->keybit);
181 input_dev->keycodesize = 0;
182 input_dev->keycodemax = 0;
183 input_dev->id.bustype = BUS_USB;
184 input_dev->id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor);
185 input_dev->id.product = le16_to_cpu(dev->udev->descriptor.idProduct);
186 input_dev->id.version = 1;
187 input_dev->dev.parent = &dev->udev->dev;
188
189 err = input_register_device(input_dev);
190 if (err) {
191 em28xx_errdev("input_register_device failed\n");
192 input_free_device(input_dev);
193 return;
194 }
195
196 dev->sbutton_input_dev = input_dev;
197 schedule_delayed_work(&dev->sbutton_query_work,
198 msecs_to_jiffies(EM28XX_SBUTTON_QUERY_INTERVAL));
199 return;
200
201}
202
203void em28xx_deregister_snapshot_button(struct em28xx *dev)
204{
205 if (dev->sbutton_input_dev != NULL) {
206 em28xx_info("Deregistering snapshot button\n");
207 cancel_rearming_delayed_work(&dev->sbutton_query_work);
208 input_unregister_device(dev->sbutton_input_dev);
209 dev->sbutton_input_dev = NULL;
210 }
211 return;
212}
213
127/* ---------------------------------------------------------------------- 214/* ----------------------------------------------------------------------
128 * Local variables: 215 * Local variables:
129 * c-basic-offset: 8 216 * c-basic-offset: 8
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index 1c3e8b6291ea..2d9f14d2a00b 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -1590,6 +1590,8 @@ static void em28xx_release_resources(struct em28xx *dev)
1590 dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN, 1590 dev->vdev->minor-MINOR_VFL_TYPE_GRABBER_MIN,
1591 dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN); 1591 dev->vbi_dev->minor-MINOR_VFL_TYPE_VBI_MIN);
1592 list_del(&dev->devlist); 1592 list_del(&dev->devlist);
1593 if (dev->sbutton_input_dev)
1594 em28xx_deregister_snapshot_button(dev);
1593 if (dev->radio_dev) { 1595 if (dev->radio_dev) {
1594 if (-1 != dev->radio_dev->minor) 1596 if (-1 != dev->radio_dev->minor)
1595 video_unregister_device(dev->radio_dev); 1597 video_unregister_device(dev->radio_dev);
diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h
index cff618b2d13c..89842c5d64a1 100644
--- a/drivers/media/video/em28xx/em28xx.h
+++ b/drivers/media/video/em28xx/em28xx.h
@@ -57,6 +57,7 @@
57#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16 57#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16
58#define EM2880_BOARD_PINNACLE_PCTV_HD_PRO 17 58#define EM2880_BOARD_PINNACLE_PCTV_HD_PRO 17
59#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 18 59#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 18
60#define EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA 19
60 61
61/* Limits minimum and default number of buffers */ 62/* Limits minimum and default number of buffers */
62#define EM28XX_MIN_BUF 4 63#define EM28XX_MIN_BUF 4
@@ -249,6 +250,7 @@ struct em28xx_board {
249 unsigned int has_12mhz_i2s:1; 250 unsigned int has_12mhz_i2s:1;
250 unsigned int max_range_640_480:1; 251 unsigned int max_range_640_480:1;
251 unsigned int has_dvb:1; 252 unsigned int has_dvb:1;
253 unsigned int has_snapshot_button:1;
252 254
253 enum em28xx_decoder decoder; 255 enum em28xx_decoder decoder;
254 256
@@ -328,6 +330,7 @@ struct em28xx {
328 unsigned int has_12mhz_i2s:1; 330 unsigned int has_12mhz_i2s:1;
329 unsigned int max_range_640_480:1; 331 unsigned int max_range_640_480:1;
330 unsigned int has_dvb:1; 332 unsigned int has_dvb:1;
333 unsigned int has_snapshot_button:1;
331 334
332 /* Some older em28xx chips needs a waiting time after writing */ 335 /* Some older em28xx chips needs a waiting time after writing */
333 unsigned int wait_after_write; 336 unsigned int wait_after_write;
@@ -418,6 +421,11 @@ struct em28xx {
418 /* Caches GPO and GPIO registers */ 421 /* Caches GPO and GPIO registers */
419 unsigned char reg_gpo, reg_gpio; 422 unsigned char reg_gpo, reg_gpio;
420 423
424 /* Snapshot button */
425 char snapshot_button_path[30]; /* path of the input dev */
426 struct input_dev *sbutton_input_dev;
427 struct delayed_work sbutton_query_work;
428
421 struct em28xx_dvb *dvb; 429 struct em28xx_dvb *dvb;
422}; 430};
423 431
@@ -483,6 +491,8 @@ int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
483int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw); 491int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
484int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key, 492int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
485 u32 *ir_raw); 493 u32 *ir_raw);
494void em28xx_register_snapshot_button(struct em28xx *dev);
495void em28xx_deregister_snapshot_button(struct em28xx *dev);
486 496
487/* printk macros */ 497/* printk macros */
488 498