diff options
Diffstat (limited to 'drivers/media/video/cx23885/cx23885-cards.c')
-rw-r--r-- | drivers/media/video/cx23885/cx23885-cards.c | 114 |
1 files changed, 107 insertions, 7 deletions
diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 2014daedee8b..e76ce8709afd 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c | |||
@@ -30,6 +30,16 @@ | |||
30 | #include "netup-init.h" | 30 | #include "netup-init.h" |
31 | #include "cx23888-ir.h" | 31 | #include "cx23888-ir.h" |
32 | 32 | ||
33 | static unsigned int enable_885_ir; | ||
34 | module_param(enable_885_ir, int, 0644); | ||
35 | MODULE_PARM_DESC(enable_885_ir, | ||
36 | "Enable integrated IR controller for supported\n" | ||
37 | "\t\t CX2388[57] boards that are wired for it:\n" | ||
38 | "\t\t\tHVR-1250 (reported safe)\n" | ||
39 | "\t\t\tTeVii S470 (reported unsafe)\n" | ||
40 | "\t\t This can cause an interrupt storm with some cards.\n" | ||
41 | "\t\t Default: 0 [Disabled]"); | ||
42 | |||
33 | /* ------------------------------------------------------------------ */ | 43 | /* ------------------------------------------------------------------ */ |
34 | /* board config info */ | 44 | /* board config info */ |
35 | 45 | ||
@@ -626,6 +636,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) | |||
626 | case 79101: | 636 | case 79101: |
627 | /* WinTV-HVR1250 (PCIe, Retail, IR, half height, | 637 | /* WinTV-HVR1250 (PCIe, Retail, IR, half height, |
628 | ATSC and Basic analog */ | 638 | ATSC and Basic analog */ |
639 | case 79501: | ||
640 | /* WinTV-HVR1250 (PCIe, No IR, half height, | ||
641 | ATSC [at least] and Basic analog) */ | ||
629 | case 79561: | 642 | case 79561: |
630 | /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, | 643 | /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, |
631 | ATSC and Basic analog */ | 644 | ATSC and Basic analog */ |
@@ -959,9 +972,37 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) | |||
959 | 972 | ||
960 | int cx23885_ir_init(struct cx23885_dev *dev) | 973 | int cx23885_ir_init(struct cx23885_dev *dev) |
961 | { | 974 | { |
975 | static struct v4l2_subdev_io_pin_config ir_rxtx_pin_cfg[] = { | ||
976 | { | ||
977 | .flags = V4L2_SUBDEV_IO_PIN_INPUT, | ||
978 | .pin = CX23885_PIN_IR_RX_GPIO19, | ||
979 | .function = CX23885_PAD_IR_RX, | ||
980 | .value = 0, | ||
981 | .strength = CX25840_PIN_DRIVE_MEDIUM, | ||
982 | }, { | ||
983 | .flags = V4L2_SUBDEV_IO_PIN_OUTPUT, | ||
984 | .pin = CX23885_PIN_IR_TX_GPIO20, | ||
985 | .function = CX23885_PAD_IR_TX, | ||
986 | .value = 0, | ||
987 | .strength = CX25840_PIN_DRIVE_MEDIUM, | ||
988 | } | ||
989 | }; | ||
990 | const size_t ir_rxtx_pin_cfg_count = ARRAY_SIZE(ir_rxtx_pin_cfg); | ||
991 | |||
992 | static struct v4l2_subdev_io_pin_config ir_rx_pin_cfg[] = { | ||
993 | { | ||
994 | .flags = V4L2_SUBDEV_IO_PIN_INPUT, | ||
995 | .pin = CX23885_PIN_IR_RX_GPIO19, | ||
996 | .function = CX23885_PAD_IR_RX, | ||
997 | .value = 0, | ||
998 | .strength = CX25840_PIN_DRIVE_MEDIUM, | ||
999 | } | ||
1000 | }; | ||
1001 | const size_t ir_rx_pin_cfg_count = ARRAY_SIZE(ir_rx_pin_cfg); | ||
1002 | |||
1003 | struct v4l2_subdev_ir_parameters params; | ||
962 | int ret = 0; | 1004 | int ret = 0; |
963 | switch (dev->board) { | 1005 | switch (dev->board) { |
964 | case CX23885_BOARD_HAUPPAUGE_HVR1250: | ||
965 | case CX23885_BOARD_HAUPPAUGE_HVR1500: | 1006 | case CX23885_BOARD_HAUPPAUGE_HVR1500: |
966 | case CX23885_BOARD_HAUPPAUGE_HVR1500Q: | 1007 | case CX23885_BOARD_HAUPPAUGE_HVR1500Q: |
967 | case CX23885_BOARD_HAUPPAUGE_HVR1800: | 1008 | case CX23885_BOARD_HAUPPAUGE_HVR1800: |
@@ -979,7 +1020,41 @@ int cx23885_ir_init(struct cx23885_dev *dev) | |||
979 | if (ret) | 1020 | if (ret) |
980 | break; | 1021 | break; |
981 | dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR); | 1022 | dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_888_IR); |
982 | dev->pci_irqmask |= PCI_MSK_IR; | 1023 | v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config, |
1024 | ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg); | ||
1025 | /* | ||
1026 | * For these boards we need to invert the Tx output via the | ||
1027 | * IR controller to have the LED off while idle | ||
1028 | */ | ||
1029 | v4l2_subdev_call(dev->sd_ir, ir, tx_g_parameters, ¶ms); | ||
1030 | params.enable = false; | ||
1031 | params.shutdown = false; | ||
1032 | params.invert_level = true; | ||
1033 | v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, ¶ms); | ||
1034 | params.shutdown = true; | ||
1035 | v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, ¶ms); | ||
1036 | break; | ||
1037 | case CX23885_BOARD_TEVII_S470: | ||
1038 | if (!enable_885_ir) | ||
1039 | break; | ||
1040 | dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE); | ||
1041 | if (dev->sd_ir == NULL) { | ||
1042 | ret = -ENODEV; | ||
1043 | break; | ||
1044 | } | ||
1045 | v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config, | ||
1046 | ir_rx_pin_cfg_count, ir_rx_pin_cfg); | ||
1047 | break; | ||
1048 | case CX23885_BOARD_HAUPPAUGE_HVR1250: | ||
1049 | if (!enable_885_ir) | ||
1050 | break; | ||
1051 | dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE); | ||
1052 | if (dev->sd_ir == NULL) { | ||
1053 | ret = -ENODEV; | ||
1054 | break; | ||
1055 | } | ||
1056 | v4l2_subdev_call(dev->sd_cx25840, core, s_io_pin_config, | ||
1057 | ir_rxtx_pin_cfg_count, ir_rxtx_pin_cfg); | ||
983 | break; | 1058 | break; |
984 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: | 1059 | case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: |
985 | request_module("ir-kbd-i2c"); | 1060 | request_module("ir-kbd-i2c"); |
@@ -994,11 +1069,16 @@ void cx23885_ir_fini(struct cx23885_dev *dev) | |||
994 | switch (dev->board) { | 1069 | switch (dev->board) { |
995 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | 1070 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
996 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | 1071 | case CX23885_BOARD_HAUPPAUGE_HVR1290: |
997 | dev->pci_irqmask &= ~PCI_MSK_IR; | 1072 | cx23885_irq_remove(dev, PCI_MSK_IR); |
998 | cx_clear(PCI_INT_MSK, PCI_MSK_IR); | ||
999 | cx23888_ir_remove(dev); | 1073 | cx23888_ir_remove(dev); |
1000 | dev->sd_ir = NULL; | 1074 | dev->sd_ir = NULL; |
1001 | break; | 1075 | break; |
1076 | case CX23885_BOARD_TEVII_S470: | ||
1077 | case CX23885_BOARD_HAUPPAUGE_HVR1250: | ||
1078 | cx23885_irq_remove(dev, PCI_MSK_AV_CORE); | ||
1079 | /* sd_ir is a duplicate pointer to the AV Core, just clear it */ | ||
1080 | dev->sd_ir = NULL; | ||
1081 | break; | ||
1002 | } | 1082 | } |
1003 | } | 1083 | } |
1004 | 1084 | ||
@@ -1007,8 +1087,13 @@ void cx23885_ir_pci_int_enable(struct cx23885_dev *dev) | |||
1007 | switch (dev->board) { | 1087 | switch (dev->board) { |
1008 | case CX23885_BOARD_HAUPPAUGE_HVR1850: | 1088 | case CX23885_BOARD_HAUPPAUGE_HVR1850: |
1009 | case CX23885_BOARD_HAUPPAUGE_HVR1290: | 1089 | case CX23885_BOARD_HAUPPAUGE_HVR1290: |
1010 | if (dev->sd_ir && (dev->pci_irqmask & PCI_MSK_IR)) | 1090 | if (dev->sd_ir) |
1011 | cx_set(PCI_INT_MSK, PCI_MSK_IR); | 1091 | cx23885_irq_add_enable(dev, PCI_MSK_IR); |
1092 | break; | ||
1093 | case CX23885_BOARD_TEVII_S470: | ||
1094 | case CX23885_BOARD_HAUPPAUGE_HVR1250: | ||
1095 | if (dev->sd_ir) | ||
1096 | cx23885_irq_add_enable(dev, PCI_MSK_AV_CORE); | ||
1012 | break; | 1097 | break; |
1013 | } | 1098 | } |
1014 | } | 1099 | } |
@@ -1028,6 +1113,13 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
1028 | 1113 | ||
1029 | switch (dev->board) { | 1114 | switch (dev->board) { |
1030 | case CX23885_BOARD_HAUPPAUGE_HVR1250: | 1115 | case CX23885_BOARD_HAUPPAUGE_HVR1250: |
1116 | if (dev->i2c_bus[0].i2c_rc == 0) { | ||
1117 | if (eeprom[0x80] != 0x84) | ||
1118 | hauppauge_eeprom(dev, eeprom+0xc0); | ||
1119 | else | ||
1120 | hauppauge_eeprom(dev, eeprom+0x80); | ||
1121 | } | ||
1122 | break; | ||
1031 | case CX23885_BOARD_HAUPPAUGE_HVR1500: | 1123 | case CX23885_BOARD_HAUPPAUGE_HVR1500: |
1032 | case CX23885_BOARD_HAUPPAUGE_HVR1500Q: | 1124 | case CX23885_BOARD_HAUPPAUGE_HVR1500Q: |
1033 | case CX23885_BOARD_HAUPPAUGE_HVR1400: | 1125 | case CX23885_BOARD_HAUPPAUGE_HVR1400: |
@@ -1136,6 +1228,11 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
1136 | * loaded, ensure this happens. | 1228 | * loaded, ensure this happens. |
1137 | */ | 1229 | */ |
1138 | switch (dev->board) { | 1230 | switch (dev->board) { |
1231 | case CX23885_BOARD_TEVII_S470: | ||
1232 | case CX23885_BOARD_HAUPPAUGE_HVR1250: | ||
1233 | /* Currently only enabled for the integrated IR controller */ | ||
1234 | if (!enable_885_ir) | ||
1235 | break; | ||
1139 | case CX23885_BOARD_HAUPPAUGE_HVR1800: | 1236 | case CX23885_BOARD_HAUPPAUGE_HVR1800: |
1140 | case CX23885_BOARD_HAUPPAUGE_HVR1800lp: | 1237 | case CX23885_BOARD_HAUPPAUGE_HVR1800lp: |
1141 | case CX23885_BOARD_HAUPPAUGE_HVR1700: | 1238 | case CX23885_BOARD_HAUPPAUGE_HVR1700: |
@@ -1151,7 +1248,10 @@ void cx23885_card_setup(struct cx23885_dev *dev) | |||
1151 | dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, | 1248 | dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev, |
1152 | &dev->i2c_bus[2].i2c_adap, | 1249 | &dev->i2c_bus[2].i2c_adap, |
1153 | "cx25840", "cx25840", 0x88 >> 1, NULL); | 1250 | "cx25840", "cx25840", 0x88 >> 1, NULL); |
1154 | v4l2_subdev_call(dev->sd_cx25840, core, load_fw); | 1251 | if (dev->sd_cx25840) { |
1252 | dev->sd_cx25840->grp_id = CX23885_HW_AV_CORE; | ||
1253 | v4l2_subdev_call(dev->sd_cx25840, core, load_fw); | ||
1254 | } | ||
1155 | break; | 1255 | break; |
1156 | } | 1256 | } |
1157 | 1257 | ||