Commit | Line | Data |
---|---|---|
1c11d546 MK |
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 | |
09a29b77 | 7 | * it under the terms of the GNU General Public License version 2 as |
1c11d546 MK |
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" | |
90f944a3 | 21 | #include "smsir.h" |
1c11d546 | 22 | |
0d02efe4 MK |
23 | static int sms_dbg; |
24 | module_param_named(cards_dbg, sms_dbg, int, 0644); | |
25 | MODULE_PARM_DESC(cards_dbg, "set debug level (info=1, adv=2 (or-able))"); | |
26 | ||
1c11d546 MK |
27 | static struct sms_board sms_boards[] = { |
28 | [SMS_BOARD_UNKNOWN] = { | |
29 | .name = "Unknown board", | |
30 | }, | |
1c11d546 | 31 | [SMS1XXX_BOARD_SIANO_STELLAR] = { |
cf1cfe1b | 32 | .name = "Siano Stellar Digital Receiver", |
1c11d546 MK |
33 | .type = SMS_STELLAR, |
34 | }, | |
35 | [SMS1XXX_BOARD_SIANO_NOVA_A] = { | |
cf1cfe1b | 36 | .name = "Siano Nova A Digital Receiver", |
1c11d546 MK |
37 | .type = SMS_NOVA_A0, |
38 | }, | |
39 | [SMS1XXX_BOARD_SIANO_NOVA_B] = { | |
cf1cfe1b | 40 | .name = "Siano Nova B Digital Receiver", |
1c11d546 MK |
41 | .type = SMS_NOVA_B0, |
42 | }, | |
43 | [SMS1XXX_BOARD_SIANO_VEGA] = { | |
cf1cfe1b | 44 | .name = "Siano Vega Digital Receiver", |
1c11d546 MK |
45 | .type = SMS_VEGA, |
46 | }, | |
44f71c3f MK |
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] = { | |
7a9b5fc5 | 63 | .name = "Hauppauge WinTV MiniStick", |
44f71c3f | 64 | .type = SMS_NOVA_B0, |
dcb0c533 | 65 | .fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw", |
7a8f4ccf | 66 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", |
15195d3a | 67 | .rc_codes = RC_MAP_HAUPPAUGE, |
9504ccac US |
68 | .board_cfg.leds_power = 26, |
69 | .board_cfg.led0 = 27, | |
70 | .board_cfg.led1 = 28, | |
20d64443 | 71 | .board_cfg.ir = 9, |
250fa674 MK |
72 | .led_power = 26, |
73 | .led_lo = 27, | |
74 | .led_hi = 28, | |
44f71c3f | 75 | }, |
3f7d99f6 MK |
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", | |
250fa674 | 80 | .lna_ctrl = 29, |
9504ccac | 81 | .board_cfg.foreign_lna0_ctrl = 29, |
d54093af | 82 | .rf_switch = 17, |
9504ccac | 83 | .board_cfg.rf_switch_uhf = 17, |
250fa674 MK |
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", | |
f4c82548 | 89 | .lna_ctrl = -1, |
3f7d99f6 | 90 | }, |
d0b66180 US |
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 | }, | |
1c11d546 MK |
101 | }; |
102 | ||
3a054627 | 103 | struct sms_board *sms_get_board(unsigned id) |
1c11d546 MK |
104 | { |
105 | BUG_ON(id >= ARRAY_SIZE(sms_boards)); | |
106 | ||
107 | return &sms_boards[id]; | |
108 | } | |
a0beec8f | 109 | EXPORT_SYMBOL_GPL(sms_get_board); |
5b8db897 US |
110 | static 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 | ||
120 | int sms_board_event(struct smscore_device_t *coredev, | |
121 | enum SMS_BOARD_EVENTS gevent) { | |
5b8db897 US |
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 */ | |
5b8db897 US |
128 | break; /* BOARD_EVENT_BIND */ |
129 | ||
130 | case BOARD_EVENT_POWER_SUSPEND: | |
5b8db897 US |
131 | break; /* BOARD_EVENT_POWER_SUSPEND */ |
132 | ||
133 | case BOARD_EVENT_POWER_RESUME: | |
5b8db897 US |
134 | break; /* BOARD_EVENT_POWER_RESUME */ |
135 | ||
136 | case BOARD_EVENT_BIND: | |
5b8db897 US |
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: | |
5b8db897 US |
146 | break; /* BOARD_EVENT_FE_LOCK */ |
147 | case BOARD_EVENT_FE_UNLOCK: | |
5b8db897 US |
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: | |
5b8db897 US |
164 | break; /* BOARD_EVENT_MULTIPLEX_OK */ |
165 | case BOARD_EVENT_MULTIPLEX_ERRORS: | |
5b8db897 US |
166 | break; /* BOARD_EVENT_MULTIPLEX_ERRORS */ |
167 | ||
168 | default: | |
169 | sms_err("Unknown SMS board event"); | |
170 | break; | |
171 | } | |
172 | return 0; | |
173 | } | |
174 | EXPORT_SYMBOL_GPL(sms_board_event); | |
1c11d546 | 175 | |
dd72f31b | 176 | static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable) |
250fa674 | 177 | { |
dd72f31b MK |
178 | int lvl, ret; |
179 | u32 gpio; | |
7c4ca79f | 180 | struct smscore_config_gpio gpioconfig = { |
250fa674 MK |
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 | ||
dd72f31b MK |
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 | } | |
250fa674 | 199 | |
dd72f31b | 200 | ret = smscore_configure_gpio(coredev, gpio, &gpioconfig); |
250fa674 MK |
201 | if (ret < 0) |
202 | return ret; | |
203 | ||
dd72f31b | 204 | return smscore_set_gpio(coredev, gpio, lvl); |
250fa674 MK |
205 | } |
206 | ||
207 | int 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; | |
dff65740 MK |
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; | |
250fa674 MK |
224 | } |
225 | return 0; | |
226 | } | |
a0beec8f | 227 | EXPORT_SYMBOL_GPL(sms_board_setup); |
7a6fbed6 MK |
228 | |
229 | int 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; | |
dff65740 MK |
240 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: |
241 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | |
242 | /* LNA */ | |
d54093af MK |
243 | if (!onoff) |
244 | sms_set_gpio(coredev, board->lna_ctrl, 0); | |
dff65740 | 245 | break; |
7a6fbed6 MK |
246 | } |
247 | return 0; | |
248 | } | |
a0beec8f | 249 | EXPORT_SYMBOL_GPL(sms_board_power); |
7b29e10d MK |
250 | |
251 | int 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 | } | |
a0beec8f | 272 | EXPORT_SYMBOL_GPL(sms_board_led_feedback); |
d54093af MK |
273 | |
274 | int 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 | } | |
a0beec8f | 291 | EXPORT_SYMBOL_GPL(sms_board_lna_control); |
05860f2d MK |
292 | |
293 | int 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: | |
7dee9d1c ÉP |
300 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: |
301 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | |
05860f2d MK |
302 | request_module("smsdvb"); |
303 | break; | |
304 | default: | |
305 | /* do nothing */ | |
306 | break; | |
307 | } | |
308 | return 0; | |
309 | } | |
a0beec8f | 310 | EXPORT_SYMBOL_GPL(sms_board_load_modules); |