diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-07 01:22:01 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-09-12 11:20:17 -0400 |
commit | 7aedd5ec87686c557d48584d69ad880c11a0984d (patch) | |
tree | 4b700249f4c94e76fdf86c7f45bc287631d721d7 /drivers | |
parent | 78f2e672b37ae8935ec0b97cedbc2d877ffa0c5f (diff) |
V4L/DVB (12701): saa7134: ir-kbd-i2c init data needs a persistent object
ir-kbd-i2c's ir_probe() function can be called much later (i.e. at
ir-kbd-i2c module load), than the lifetime of a struct IR_i2c_init_data
allocated off of the stack in cx18_i2c_new_ir() at registration time.
Make sure we pass a pointer to a persistent IR_i2c_init_data object at
i2c registration time.
Thanks to Brian Rogers, Dustin Mitchell, Andy Walls and Jean Delvare to
rise this question.
Before this patch, if ir-kbd-i2c were probed after SAA7134, trash data
were used.
Compile tested only, but the patch is identical to em28xx one. So, it
should work properly.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/saa7134/saa7134-input.c | 60 | ||||
-rw-r--r-- | drivers/media/video/saa7134/saa7134.h | 4 |
2 files changed, 33 insertions, 31 deletions
diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 9070e5fabb4e..e1e83c7b966e 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c | |||
@@ -691,8 +691,6 @@ void saa7134_input_fini(struct saa7134_dev *dev) | |||
691 | 691 | ||
692 | void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | 692 | void saa7134_probe_i2c_ir(struct saa7134_dev *dev) |
693 | { | 693 | { |
694 | struct i2c_board_info info; | ||
695 | struct IR_i2c_init_data init_data; | ||
696 | const unsigned short addr_list[] = { | 694 | const unsigned short addr_list[] = { |
697 | 0x7a, 0x47, 0x71, 0x2d, | 695 | 0x7a, 0x47, 0x71, 0x2d, |
698 | I2C_CLIENT_END | 696 | I2C_CLIENT_END |
@@ -712,34 +710,34 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
712 | return; | 710 | return; |
713 | } | 711 | } |
714 | 712 | ||
715 | memset(&info, 0, sizeof(struct i2c_board_info)); | 713 | memset(&dev->info, 0, sizeof(dev->info)); |
716 | memset(&init_data, 0, sizeof(struct IR_i2c_init_data)); | 714 | memset(&dev->init_data, 0, sizeof(dev->init_data)); |
717 | strlcpy(info.type, "ir_video", I2C_NAME_SIZE); | 715 | strlcpy(dev->info.type, "ir_video", I2C_NAME_SIZE); |
718 | 716 | ||
719 | switch (dev->board) { | 717 | switch (dev->board) { |
720 | case SAA7134_BOARD_PINNACLE_PCTV_110i: | 718 | case SAA7134_BOARD_PINNACLE_PCTV_110i: |
721 | case SAA7134_BOARD_PINNACLE_PCTV_310i: | 719 | case SAA7134_BOARD_PINNACLE_PCTV_310i: |
722 | init_data.name = "Pinnacle PCTV"; | 720 | dev->init_data.name = "Pinnacle PCTV"; |
723 | if (pinnacle_remote == 0) { | 721 | if (pinnacle_remote == 0) { |
724 | init_data.get_key = get_key_pinnacle_color; | 722 | dev->init_data.get_key = get_key_pinnacle_color; |
725 | init_data.ir_codes = &ir_codes_pinnacle_color_table; | 723 | dev->init_data.ir_codes = &ir_codes_pinnacle_color_table; |
726 | info.addr = 0x47; | 724 | dev->info.addr = 0x47; |
727 | } else { | 725 | } else { |
728 | init_data.get_key = get_key_pinnacle_grey; | 726 | dev->init_data.get_key = get_key_pinnacle_grey; |
729 | init_data.ir_codes = &ir_codes_pinnacle_grey_table; | 727 | dev->init_data.ir_codes = &ir_codes_pinnacle_grey_table; |
730 | info.addr = 0x47; | 728 | dev->info.addr = 0x47; |
731 | } | 729 | } |
732 | break; | 730 | break; |
733 | case SAA7134_BOARD_UPMOST_PURPLE_TV: | 731 | case SAA7134_BOARD_UPMOST_PURPLE_TV: |
734 | init_data.name = "Purple TV"; | 732 | dev->init_data.name = "Purple TV"; |
735 | init_data.get_key = get_key_purpletv; | 733 | dev->init_data.get_key = get_key_purpletv; |
736 | init_data.ir_codes = &ir_codes_purpletv_table; | 734 | dev->init_data.ir_codes = &ir_codes_purpletv_table; |
737 | break; | 735 | break; |
738 | case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: | 736 | case SAA7134_BOARD_MSI_TVATANYWHERE_PLUS: |
739 | init_data.name = "MSI TV@nywhere Plus"; | 737 | dev->init_data.name = "MSI TV@nywhere Plus"; |
740 | init_data.get_key = get_key_msi_tvanywhere_plus; | 738 | dev->init_data.get_key = get_key_msi_tvanywhere_plus; |
741 | init_data.ir_codes = &ir_codes_msi_tvanywhere_plus_table; | 739 | dev->init_data.ir_codes = &ir_codes_msi_tvanywhere_plus_table; |
742 | info.addr = 0x30; | 740 | dev->info.addr = 0x30; |
743 | /* MSI TV@nywhere Plus controller doesn't seem to | 741 | /* MSI TV@nywhere Plus controller doesn't seem to |
744 | respond to probes unless we read something from | 742 | respond to probes unless we read something from |
745 | an existing device. Weird... | 743 | an existing device. Weird... |
@@ -750,9 +748,9 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
750 | (1 == rc) ? "yes" : "no"); | 748 | (1 == rc) ? "yes" : "no"); |
751 | break; | 749 | break; |
752 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: | 750 | case SAA7134_BOARD_HAUPPAUGE_HVR1110: |
753 | init_data.name = "HVR 1110"; | 751 | dev->init_data.name = "HVR 1110"; |
754 | init_data.get_key = get_key_hvr1110; | 752 | dev->init_data.get_key = get_key_hvr1110; |
755 | init_data.ir_codes = &ir_codes_hauppauge_new_table; | 753 | dev->init_data.ir_codes = &ir_codes_hauppauge_new_table; |
756 | break; | 754 | break; |
757 | case SAA7134_BOARD_BEHOLD_607FM_MK3: | 755 | case SAA7134_BOARD_BEHOLD_607FM_MK3: |
758 | case SAA7134_BOARD_BEHOLD_607FM_MK5: | 756 | case SAA7134_BOARD_BEHOLD_607FM_MK5: |
@@ -767,26 +765,26 @@ void saa7134_probe_i2c_ir(struct saa7134_dev *dev) | |||
767 | case SAA7134_BOARD_BEHOLD_M6_EXTRA: | 765 | case SAA7134_BOARD_BEHOLD_M6_EXTRA: |
768 | case SAA7134_BOARD_BEHOLD_H6: | 766 | case SAA7134_BOARD_BEHOLD_H6: |
769 | case SAA7134_BOARD_BEHOLD_X7: | 767 | case SAA7134_BOARD_BEHOLD_X7: |
770 | init_data.name = "BeholdTV"; | 768 | dev->init_data.name = "BeholdTV"; |
771 | init_data.get_key = get_key_beholdm6xx; | 769 | dev->init_data.get_key = get_key_beholdm6xx; |
772 | init_data.ir_codes = &ir_codes_behold_table; | 770 | dev->init_data.ir_codes = &ir_codes_behold_table; |
773 | break; | 771 | break; |
774 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: | 772 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_501: |
775 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: | 773 | case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: |
776 | info.addr = 0x40; | 774 | dev->info.addr = 0x40; |
777 | break; | 775 | break; |
778 | } | 776 | } |
779 | 777 | ||
780 | if (init_data.name) | 778 | if (dev->init_data.name) |
781 | info.platform_data = &init_data; | 779 | dev->info.platform_data = &dev->init_data; |
782 | /* No need to probe if address is known */ | 780 | /* No need to probe if address is known */ |
783 | if (info.addr) { | 781 | if (dev->info.addr) { |
784 | i2c_new_device(&dev->i2c_adap, &info); | 782 | i2c_new_device(&dev->i2c_adap, &dev->info); |
785 | return; | 783 | return; |
786 | } | 784 | } |
787 | 785 | ||
788 | /* Address not known, fallback to probing */ | 786 | /* Address not known, fallback to probing */ |
789 | i2c_new_probed_device(&dev->i2c_adap, &info, addr_list); | 787 | i2c_new_probed_device(&dev->i2c_adap, &dev->info, addr_list); |
790 | } | 788 | } |
791 | 789 | ||
792 | static int saa7134_rc5_irq(struct saa7134_dev *dev) | 790 | static int saa7134_rc5_irq(struct saa7134_dev *dev) |
diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index ac74903a5bd4..d18bb9643856 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h | |||
@@ -589,6 +589,10 @@ struct saa7134_dev { | |||
589 | int nosignal; | 589 | int nosignal; |
590 | unsigned int insuspend; | 590 | unsigned int insuspend; |
591 | 591 | ||
592 | /* I2C keyboard data */ | ||
593 | struct i2c_board_info info; | ||
594 | struct IR_i2c_init_data init_data; | ||
595 | |||
592 | /* SAA7134_MPEG_* */ | 596 | /* SAA7134_MPEG_* */ |
593 | struct saa7134_ts ts; | 597 | struct saa7134_ts ts; |
594 | struct saa7134_dmaqueue ts_q; | 598 | struct saa7134_dmaqueue ts_q; |