diff options
author | Brian Rogers <brian_rogers@comcast.net> | 2008-10-13 07:37:06 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2008-10-13 07:57:34 -0400 |
commit | ba340b40a5f65261731583f67d7ec8cafbf5cfaa (patch) | |
tree | b62243ecb18ccf1d38b60e5919e8ab7eeaa7d6f4 /drivers/media | |
parent | fa405d7094489828014315a34f0c21fba30be38c (diff) |
V4L/DVB (9168): Add support for MSI TV@nywhere Plus remote
The IR controller has a couple quirks. It won't respond until some other
device on the bus is probed. To work around that, probe 0x50 first.
Then, since it won't respond to a zero-byte read, probe with a one-byte
read.
Signed-off-by: Brian Rogers <brian_rogers@comcast.net>
[mchehab.redhat.com: Fix merge conflicts and remove an unused var]
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/common/ir-keymaps.c | 92 | ||||
-rw-r--r-- | drivers/media/video/ir-kbd-i2c.c | 42 | ||||
-rw-r--r-- | drivers/media/video/saa7134/saa7134-cards.c | 1 | ||||
-rw-r--r-- | drivers/media/video/saa7134/saa7134-i2c.c | 1 | ||||
-rw-r--r-- | drivers/media/video/saa7134/saa7134-input.c | 52 |
5 files changed, 185 insertions, 3 deletions
diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index b7ed88c59b54..4952aeb5dd80 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c | |||
@@ -517,7 +517,8 @@ EXPORT_SYMBOL_GPL(ir_codes_adstech_dvb_t_pci); | |||
517 | 517 | ||
518 | /* ---------------------------------------------------------------------- */ | 518 | /* ---------------------------------------------------------------------- */ |
519 | 519 | ||
520 | /* MSI TV@nywhere remote */ | 520 | /* MSI TV@nywhere MASTER remote */ |
521 | |||
521 | IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { | 522 | IR_KEYTAB_TYPE ir_codes_msi_tvanywhere[IR_KEYTAB_SIZE] = { |
522 | /* Keys 0 to 9 */ | 523 | /* Keys 0 to 9 */ |
523 | [ 0x00 ] = KEY_0, | 524 | [ 0x00 ] = KEY_0, |
@@ -551,6 +552,95 @@ EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere); | |||
551 | 552 | ||
552 | /* ---------------------------------------------------------------------- */ | 553 | /* ---------------------------------------------------------------------- */ |
553 | 554 | ||
555 | /* | ||
556 | Keycodes for remote on the MSI TV@nywhere Plus. The controller IC on the card | ||
557 | is marked "KS003". The controller is I2C at address 0x30, but does not seem | ||
558 | to respond to probes until a read is performed from a valid device. | ||
559 | I don't know why... | ||
560 | |||
561 | Note: This remote may be of similar or identical design to the | ||
562 | Pixelview remote (?). The raw codes and duplicate button codes | ||
563 | appear to be the same. | ||
564 | |||
565 | Henry Wong <henry@stuffedcow.net> | ||
566 | Some changes to formatting and keycodes by Mark Schultz <n9xmj@yahoo.com> | ||
567 | |||
568 | */ | ||
569 | |||
570 | IR_KEYTAB_TYPE ir_codes_msi_tvanywhere_plus[IR_KEYTAB_SIZE] = { | ||
571 | |||
572 | /* ---- Remote Button Layout ---- | ||
573 | |||
574 | POWER SOURCE SCAN MUTE | ||
575 | TV/FM 1 2 3 | ||
576 | |> 4 5 6 | ||
577 | <| 7 8 9 | ||
578 | ^^UP 0 + RECALL | ||
579 | vvDN RECORD STOP PLAY | ||
580 | |||
581 | MINIMIZE ZOOM | ||
582 | |||
583 | CH+ | ||
584 | VOL- VOL+ | ||
585 | CH- | ||
586 | |||
587 | SNAPSHOT MTS | ||
588 | |||
589 | << FUNC >> RESET | ||
590 | */ | ||
591 | |||
592 | [0x01] = KEY_KP1, /* 1 */ | ||
593 | [0x0b] = KEY_KP2, /* 2 */ | ||
594 | [0x1b] = KEY_KP3, /* 3 */ | ||
595 | [0x05] = KEY_KP4, /* 4 */ | ||
596 | [0x09] = KEY_KP5, /* 5 */ | ||
597 | [0x15] = KEY_KP6, /* 6 */ | ||
598 | [0x06] = KEY_KP7, /* 7 */ | ||
599 | [0x0a] = KEY_KP8, /* 8 */ | ||
600 | [0x12] = KEY_KP9, /* 9 */ | ||
601 | [0x02] = KEY_KP0, /* 0 */ | ||
602 | [0x10] = KEY_KPPLUS, /* + */ | ||
603 | [0x13] = KEY_AGAIN, /* Recall */ | ||
604 | |||
605 | [0x1e] = KEY_POWER, /* Power */ | ||
606 | [0x07] = KEY_TUNER, /* Source */ | ||
607 | [0x1c] = KEY_SEARCH, /* Scan */ | ||
608 | [0x18] = KEY_MUTE, /* Mute */ | ||
609 | |||
610 | [0x03] = KEY_RADIO, /* TV/FM */ | ||
611 | /* The next four keys are duplicates that appear to send the | ||
612 | same IR code as Ch+, Ch-, >>, and << . The raw code assigned | ||
613 | to them is the actual code + 0x20 - they will never be | ||
614 | detected as such unless some way is discovered to distinguish | ||
615 | these buttons from those that have the same code. */ | ||
616 | [0x3f] = KEY_RIGHT, /* |> and Ch+ */ | ||
617 | [0x37] = KEY_LEFT, /* <| and Ch- */ | ||
618 | [0x2c] = KEY_UP, /* ^^Up and >> */ | ||
619 | [0x24] = KEY_DOWN, /* vvDn and << */ | ||
620 | |||
621 | [0x00] = KEY_RECORD, /* Record */ | ||
622 | [0x08] = KEY_STOP, /* Stop */ | ||
623 | [0x11] = KEY_PLAY, /* Play */ | ||
624 | |||
625 | [0x0f] = KEY_CLOSE, /* Minimize */ | ||
626 | [0x19] = KEY_ZOOM, /* Zoom */ | ||
627 | [0x1a] = KEY_SHUFFLE, /* Snapshot */ | ||
628 | [0x0d] = KEY_LANGUAGE, /* MTS */ | ||
629 | |||
630 | [0x14] = KEY_VOLUMEDOWN, /* Vol- */ | ||
631 | [0x16] = KEY_VOLUMEUP, /* Vol+ */ | ||
632 | [0x17] = KEY_CHANNELDOWN, /* Ch- */ | ||
633 | [0x1f] = KEY_CHANNELUP, /* Ch+ */ | ||
634 | |||
635 | [0x04] = KEY_REWIND, /* << */ | ||
636 | [0x0e] = KEY_MENU, /* Function */ | ||
637 | [0x0c] = KEY_FASTFORWARD, /* >> */ | ||
638 | [0x1d] = KEY_RESTART, /* Reset */ | ||
639 | }; | ||
640 | EXPORT_SYMBOL_GPL(ir_codes_msi_tvanywhere_plus); | ||
641 | |||
642 | /* ---------------------------------------------------------------------- */ | ||
643 | |||
554 | /* Cinergy 1400 DVB-T */ | 644 | /* Cinergy 1400 DVB-T */ |
555 | IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { | 645 | IR_KEYTAB_TYPE ir_codes_cinergy_1400[IR_KEYTAB_SIZE] = { |
556 | [ 0x01 ] = KEY_POWER, | 646 | [ 0x01 ] = KEY_POWER, |
diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index 703195a5ad4e..efe849981ab7 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c | |||
@@ -12,6 +12,10 @@ | |||
12 | * Markus Rechberger <mrechberger@gmail.com> | 12 | * Markus Rechberger <mrechberger@gmail.com> |
13 | * modified for DViCO Fusion HDTV 5 RT GOLD by | 13 | * modified for DViCO Fusion HDTV 5 RT GOLD by |
14 | * Chaogui Zhang <czhang1974@gmail.com> | 14 | * Chaogui Zhang <czhang1974@gmail.com> |
15 | * modified for MSI TV@nywhere Plus by | ||
16 | * Henry Wong <henry@stuffedcow.net> | ||
17 | * Mark Schultz <n9xmj@yahoo.com> | ||
18 | * Brian Rogers <brian_rogers@comcast.net> | ||
15 | * | 19 | * |
16 | * This program is free software; you can redistribute it and/or modify | 20 | * This program is free software; you can redistribute it and/or modify |
17 | * it under the terms of the GNU General Public License as published by | 21 | * it under the terms of the GNU General Public License as published by |
@@ -242,9 +246,15 @@ static void ir_timer(unsigned long data) | |||
242 | static void ir_work(struct work_struct *work) | 246 | static void ir_work(struct work_struct *work) |
243 | { | 247 | { |
244 | struct IR_i2c *ir = container_of(work, struct IR_i2c, work); | 248 | struct IR_i2c *ir = container_of(work, struct IR_i2c, work); |
249 | int polling_interval = 100; | ||
250 | |||
251 | /* MSI TV@nywhere Plus requires more frequent polling | ||
252 | otherwise it will miss some keypresses */ | ||
253 | if (ir->c.adapter->id == I2C_HW_SAA7134 && ir->c.addr == 0x30) | ||
254 | polling_interval = 50; | ||
245 | 255 | ||
246 | ir_key_poll(ir); | 256 | ir_key_poll(ir); |
247 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(100)); | 257 | mod_timer(&ir->timer, jiffies + msecs_to_jiffies(polling_interval)); |
248 | } | 258 | } |
249 | 259 | ||
250 | /* ----------------------------------------------------------------------- */ | 260 | /* ----------------------------------------------------------------------- */ |
@@ -483,9 +493,37 @@ static int ir_probe(struct i2c_adapter *adap) | |||
483 | (1 == rc) ? "yes" : "no"); | 493 | (1 == rc) ? "yes" : "no"); |
484 | if (1 == rc) { | 494 | if (1 == rc) { |
485 | ir_attach(adap, probe[i], 0, 0); | 495 | ir_attach(adap, probe[i], 0, 0); |
486 | break; | 496 | return 0; |
487 | } | 497 | } |
488 | } | 498 | } |
499 | |||
500 | /* Special case for MSI TV@nywhere Plus remote */ | ||
501 | if (adap->id == I2C_HW_SAA7134) { | ||
502 | u8 temp; | ||
503 | |||
504 | /* MSI TV@nywhere Plus controller doesn't seem to | ||
505 | respond to probes unless we read something from | ||
506 | an existing device. Weird... */ | ||
507 | |||
508 | msg.addr = 0x50; | ||
509 | rc = i2c_transfer(adap, &msg, 1); | ||
510 | dprintk(1, "probe 0x%02x @ %s: %s\n", | ||
511 | msg.addr, adap->name, | ||
512 | (1 == rc) ? "yes" : "no"); | ||
513 | |||
514 | /* Now do the probe. The controller does not respond | ||
515 | to 0-byte reads, so we use a 1-byte read instead. */ | ||
516 | msg.addr = 0x30; | ||
517 | msg.len = 1; | ||
518 | msg.buf = &temp; | ||
519 | rc = i2c_transfer(adap, &msg, 1); | ||
520 | dprintk(1, "probe 0x%02x @ %s: %s\n", | ||
521 | msg.addr, adap->name, | ||
522 | (1 == rc) ? "yes" : "no"); | ||
523 | if (1 == rc) | ||
524 | ir_attach(adap, msg.addr, 0, 0); | ||
525 | } | ||
526 | |||
489 | return 0; | 527 | return 0; |
490 | } | 528 | } |
491 | 529 | ||
diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index c9392c4e92fd..ddc5402c5fb0 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c | |||
@@ -5969,6 +5969,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) | |||
5969 | case SAA7134_BOARD_PINNACLE_PCTV_110i: | 5969 | case SAA7134_BOARD_PINNACLE_PCTV_110i: |
5970 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | 5970 | case SAA7134_BOARD_PINNACLE_PCTV_310i: |
5971 | case SAA7134_BOARD_UPMOST_PURPLE_TV: | 5971 | case SAA7134_BOARD_UPMOST_PURPLE_TV: |
5972 | case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: | ||
5972 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | 5973 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: |
5973 | case SAA7134_BOARD_BEHOLD_607_9FM: | 5974 | case SAA7134_BOARD_BEHOLD_607_9FM: |
5974 | case SAA7134_BOARD_BEHOLD_M6: | 5975 | case SAA7134_BOARD_BEHOLD_M6: |
diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index b02965c52476..20c1b33caf7b 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c | |||
@@ -337,6 +337,7 @@ static int attach_inform(struct i2c_client *client) | |||
337 | case 0x47: | 337 | case 0x47: |
338 | case 0x71: | 338 | case 0x71: |
339 | case 0x2d: | 339 | case 0x2d: |
340 | case 0x30: | ||
340 | { | 341 | { |
341 | struct IR_i2c *ir = i2c_get_clientdata(client); | 342 | struct IR_i2c *ir = i2c_get_clientdata(client); |
342 | d1printk("%s i2c IR detected (%s).\n", | 343 | d1printk("%s i2c IR detected (%s).\n", |
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 72a1c67a8c39..c53fd5f9f6b5 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -118,6 +118,53 @@ static int build_key(struct saa7134_dev *dev) | |||
118 | 118 | ||
119 | /* --------------------- Chip specific I2C key builders ----------------- */ | 119 | /* --------------------- Chip specific I2C key builders ----------------- */ |
120 | 120 | ||
121 | static int get_key_msi_tvanywhere_plus(struct IR_i2c *ir, u32 *ir_key, | ||
122 | u32 *ir_raw) | ||
123 | { | ||
124 | unsigned char b; | ||
125 | int gpio; | ||
126 | |||
127 | /* <dev> is needed to access GPIO. Used by the saa_readl macro. */ | ||
128 | struct saa7134_dev *dev = ir->c.adapter->algo_data; | ||
129 | if (dev == NULL) { | ||
130 | dprintk("get_key_msi_tvanywhere_plus: " | ||
131 | "gir->c.adapter->algo_data is NULL!\n"); | ||
132 | return -EIO; | ||
133 | } | ||
134 | |||
135 | /* rising SAA7134_GPIO_GPRESCAN reads the status */ | ||
136 | |||
137 | saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
138 | saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN); | ||
139 | |||
140 | gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); | ||
141 | |||
142 | /* GPIO&0x40 is pulsed low when a button is pressed. Don't do | ||
143 | I2C receive if gpio&0x40 is not low. */ | ||
144 | |||
145 | if (gpio & 0x40) | ||
146 | return 0; /* No button press */ | ||
147 | |||
148 | /* GPIO says there is a button press. Get it. */ | ||
149 | |||
150 | if (1 != i2c_master_recv(&ir->c, &b, 1)) { | ||
151 | i2cdprintk("read error\n"); | ||
152 | return -EIO; | ||
153 | } | ||
154 | |||
155 | /* No button press */ | ||
156 | |||
157 | if (b == 0xff) | ||
158 | return 0; | ||
159 | |||
160 | /* Button pressed */ | ||
161 | |||
162 | dprintk("get_key_msi_tvanywhere_plus: Key = 0x%02X\n", b); | ||
163 | *ir_key = b; | ||
164 | *ir_raw = b; | ||
165 | return 1; | ||
166 | } | ||
167 | |||
121 | static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) | 168 | static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) |
122 | { | 169 | { |
123 | unsigned char b; | 170 | unsigned char b; |
@@ -641,6 +688,11 @@ void saa7134_set_i2c_ir(struct saa7134_dev *dev, struct IR_i2c *ir) | |||
641 | ir->get_key = get_key_purpletv; | 688 | ir->get_key = get_key_purpletv; |
642 | ir->ir_codes = ir_codes_purpletv; | 689 | ir->ir_codes = ir_codes_purpletv; |
643 | break; | 690 | break; |
691 | case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: | ||
692 | snprintf(ir->c.name, sizeof(ir->c.name), "MSI TV@nywhere Plus"); | ||
693 | ir->get_key = get_key_msi_tvanywhere_plus; | ||
694 | ir->ir_codes = ir_codes_msi_tvanywhere_plus; | ||
695 | break; | ||
644 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | 696 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: |
645 | snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110"); | 697 | snprintf(ir->c.name, sizeof(ir->c.name), "HVR 1110"); |
646 | ir->get_key = get_key_hvr1110; | 698 | ir->get_key = get_key_hvr1110; |