1/* 2 * Card-specific functions for the Siano SMS1xxx USB dongle 3 * 4 * Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation; 9 * 10 * Software distributed under the License is distributed on an "AS IS" 11 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. 12 * 13 * See the GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 */ 19 20#include "sms-cards.h" 21#include "smsir.h" 22 23static int sms_dbg; 24module_param_named(cards_dbg, sms_dbg, int, 0644); 25MODULE_PARM_DESC(cards_dbg, "set debug level (info=1, adv=2 (or-able))"); 26 27static struct sms_board sms_boards[] = { 28 [SMS_BOARD_UNKNOWN] = { 29 .name = "Unknown board", 30 }, 31 [SMS1XXX_BOARD_SIANO_STELLAR] = { 32 .name = "Siano Stellar Digital Receiver", 33 .type = SMS_STELLAR, 34 }, 35 [SMS1XXX_BOARD_SIANO_NOVA_A] = { 36 .name = "Siano Nova A Digital Receiver", 37 .type = SMS_NOVA_A0, 38 }, 39 [SMS1XXX_BOARD_SIANO_NOVA_B] = { 40 .name = "Siano Nova B Digital Receiver", 41 .type = SMS_NOVA_B0, 42 }, 43 [SMS1XXX_BOARD_SIANO_VEGA] = { 44 .name = "Siano Vega Digital Receiver", 45 .type = SMS_VEGA, 46 }, 47 [SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT] = { 48 .name = "Hauppauge Catamount", 49 .type = SMS_STELLAR, 50 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw", 51 }, 52 [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A] = { 53 .name = "Hauppauge Okemo-A", 54 .type = SMS_NOVA_A0, 55 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw", 56 }, 57 [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B] = { 58 .name = "Hauppauge Okemo-B", 59 .type = SMS_NOVA_B0, 60 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw", 61 }, 62 [SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = { 63 .name = "Hauppauge WinTV MiniStick", 64 .type = SMS_NOVA_B0, 65 .fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw", 66 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", 67 .rc_codes = RC_MAP_RC5_HAUPPAUGE_NEW, 68 .board_cfg.leds_power = 26, 69 .board_cfg.led0 = 27, 70 .board_cfg.led1 = 28, 71 .board_cfg.ir = 9, 72 .led_power = 26, 73 .led_lo = 27, 74 .led_hi = 28, 75 }, 76 [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD] = { 77 .name = "Hauppauge WinTV MiniCard", 78 .type = SMS_NOVA_B0, 79 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", 80 .lna_ctrl = 29, 81 .board_cfg.foreign_lna0_ctrl = 29, 82 .rf_switch = 17, 83 .board_cfg.rf_switch_uhf = 17, 84 }, 85 [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = { 86 .name = "Hauppauge WinTV MiniCard", 87 .type = SMS_NOVA_B0, 88 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", 89 .lna_ctrl = -1, 90 }, 91 [SMS1XXX_BOARD_SIANO_NICE] = { 92 /* 11 */ 93 .name = "Siano Nice Digital Receiver", 94 .type = SMS_NOVA_B0, 95 }, 96 [SMS1XXX_BOARD_SIANO_VENICE] = { 97 /* 12 */ 98 .name = "Siano Venice Digital Receiver", 99 .type = SMS_VEGA, 100 }, 101}; 102 103struct sms_board *sms_get_board(unsigned id) 104{ 105 BUG_ON(id >= ARRAY_SIZE(sms_boards)); 106 107 return &sms_boards[id]; 108} 109EXPORT_SYMBOL_GPL(sms_get_board); 110static inline void sms_gpio_assign_11xx_default_led_config( 111 struct smscore_gpio_config *pGpioConfig) { 112 pGpioConfig->Direction = SMS_GPIO_DIRECTION_OUTPUT; 113 pGpioConfig->InputCharacteristics = 114 SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL; 115 pGpioConfig->OutputDriving = SMS_GPIO_OUTPUT_DRIVING_4mA; 116 pGpioConfig->OutputSlewRate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS; 117 pGpioConfig->PullUpDown = SMS_GPIO_PULL_UP_DOWN_NONE; 118} 119 120int sms_board_event(struct smscore_device_t *coredev, 121 enum SMS_BOARD_EVENTS gevent) { 122 struct smscore_gpio_config MyGpioConfig; 123 124 sms_gpio_assign_11xx_default_led_config(&MyGpioConfig); 125 126 switch (gevent) { 127 case BOARD_EVENT_POWER_INIT: /* including hotplug */ 128 break; /* BOARD_EVENT_BIND */ 129 130 case BOARD_EVENT_POWER_SUSPEND: 131 break; /* BOARD_EVENT_POWER_SUSPEND */ 132 133 case BOARD_EVENT_POWER_RESUME: 134 break; /* BOARD_EVENT_POWER_RESUME */ 135 136 case BOARD_EVENT_BIND: 137 break; /* BOARD_EVENT_BIND */ 138 139 case BOARD_EVENT_SCAN_PROG: 140 break; /* BOARD_EVENT_SCAN_PROG */ 141 case BOARD_EVENT_SCAN_COMP: 142 break; /* BOARD_EVENT_SCAN_COMP */ 143 case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL: 144 break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */ 145 case BOARD_EVENT_FE_LOCK: 146 break; /* BOARD_EVENT_FE_LOCK */ 147 case BOARD_EVENT_FE_UNLOCK: 148 break; /* BOARD_EVENT_FE_UNLOCK */ 149 case BOARD_EVENT_DEMOD_LOCK: 150 break; /* BOARD_EVENT_DEMOD_LOCK */ 151 case BOARD_EVENT_DEMOD_UNLOCK: 152 break; /* BOARD_EVENT_DEMOD_UNLOCK */ 153 case BOARD_EVENT_RECEPTION_MAX_4: 154 break; /* BOARD_EVENT_RECEPTION_MAX_4 */ 155 case BOARD_EVENT_RECEPTION_3: 156 break; /* BOARD_EVENT_RECEPTION_3 */ 157 case BOARD_EVENT_RECEPTION_2: 158 break; /* BOARD_EVENT_RECEPTION_2 */ 159 case BOARD_EVENT_RECEPTION_1: 160 break; /* BOARD_EVENT_RECEPTION_1 */ 161 case BOARD_EVENT_RECEPTION_LOST_0: 162 break; /* BOARD_EVENT_RECEPTION_LOST_0 */ 163 case BOARD_EVENT_MULTIPLEX_OK: 164 break; /* BOARD_EVENT_MULTIPLEX_OK */ 165 case BOARD_EVENT_MULTIPLEX_ERRORS: 166 break; /* BOARD_EVENT_MULTIPLEX_ERRORS */ 167 168 default: 169 sms_err("Unknown SMS board event"); 170 break; 171 } 172 return 0; 173} 174EXPORT_SYMBOL_GPL(sms_board_event); 175 176static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable) 177{ 178 int lvl, ret; 179 u32 gpio; 180 struct smscore_config_gpio gpioconfig = { 181 .direction = SMS_GPIO_DIRECTION_OUTPUT, 182 .pullupdown = SMS_GPIO_PULLUPDOWN_NONE, 183 .inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL, 184 .outputslewrate = SMS_GPIO_OUTPUTSLEWRATE_FAST, 185 .outputdriving = SMS_GPIO_OUTPUTDRIVING_4mA, 186 }; 187 188 if (pin == 0) 189 return -EINVAL; 190 191 if (pin < 0) { 192 /* inverted gpio */ 193 gpio = pin * -1; 194 lvl = enable ? 0 : 1; 195 } else { 196 gpio = pin; 197 lvl = enable ? 1 : 0; 198 } 199 200 ret = smscore_configure_gpio(coredev, gpio, &gpioconfig); 201 if (ret < 0) 202 return ret; 203 204 return smscore_set_gpio(coredev, gpio, lvl); 205} 206 207int sms_board_setup(struct smscore_device_t *coredev) 208{ 209 int board_id = smscore_get_board_id(coredev); 210 struct sms_board *board = sms_get_board(board_id); 211 212 switch (board_id) { 213 case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: 214 /* turn off all LEDs */ 215 sms_set_gpio(coredev, board->led_power, 0); 216 sms_set_gpio(coredev, board->led_hi, 0); 217 sms_set_gpio(coredev, board->led_lo, 0); 218 break; 219 case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: 220 case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: 221 /* turn off LNA */ 222 sms_set_gpio(coredev, board->lna_ctrl, 0); 223 break; 224 } 225 return 0; 226} 227EXPORT_SYMBOL_GPL(sms_board_setup); 228 229int sms_board_power(struct smscore_device_t *coredev, int onoff) 230{ 231 int board_id = smscore_get_board_id(coredev); 232 struct sms_board *board = sms_get_board(board_id); 233 234 switch (board_id) { 235 case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: 236 /* power LED */ 237 sms_set_gpio(coredev, 238 board->led_power, onoff ? 1 : 0); 239 break; 240 case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: 241 case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: 242 /* LNA */ 243 if (!onoff) 244 sms_set_gpio(coredev, board->lna_ctrl, 0); 245 break; 246 } 247 return 0; 248} 249EXPORT_SYMBOL_GPL(sms_board_power); 250 251int sms_board_led_feedback(struct smscore_device_t *coredev, int led) 252{ 253 int board_id = smscore_get_board_id(coredev); 254 struct sms_board *board = sms_get_board(board_id); 255 256 /* dont touch GPIO if LEDs are already set */ 257 if (smscore_led_state(coredev, -1) == led) 258 return 0; 259 260 switch (board_id) { 261 case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: 262 sms_set_gpio(coredev, 263 board->led_lo, (led & SMS_LED_LO) ? 1 : 0); 264 sms_set_gpio(coredev, 265 board->led_hi, (led & SMS_LED_HI) ? 1 : 0); 266 267 smscore_led_state(coredev, led); 268 break; 269 } 270 return 0; 271} 272EXPORT_SYMBOL_GPL(sms_board_led_feedback); 273 274int sms_board_lna_control(struct smscore_device_t *coredev, int onoff) 275{ 276 int board_id = smscore_get_board_id(coredev); 277 struct sms_board *board = sms_get_board(board_id); 278 279 sms_debug("%s: LNA %s", __func__, onoff ? "enabled" : "disabled"); 280 281 switch (board_id) { 282 case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: 283 case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: 284 sms_set_gpio(coredev, 285 board->rf_switch, onoff ? 1 : 0); 286 return sms_set_gpio(coredev, 287 board->lna_ctrl, onoff ? 1 : 0); 288 } 289 return -EINVAL; 290} 291EXPORT_SYMBOL_GPL(sms_board_lna_control); 292 293int sms_board_load_modules(int id) 294{ 295 switch (id) { 296 case SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT: 297 case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A: 298 case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B: 299 case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: 300 case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: 301 case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: 302 request_module("smsdvb"); 303 break; 304 default: 305 /* do nothing */ 306 break; 307 } 308 return 0; 309} 310EXPORT_SYMBOL_GPL(sms_board_load_modules); 311