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", |
9504ccac US |
67 | .board_cfg.leds_power = 26, |
68 | .board_cfg.led0 = 27, | |
69 | .board_cfg.led1 = 28, | |
250fa674 MK |
70 | .led_power = 26, |
71 | .led_lo = 27, | |
72 | .led_hi = 28, | |
44f71c3f | 73 | }, |
3f7d99f6 MK |
74 | [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD] = { |
75 | .name = "Hauppauge WinTV MiniCard", | |
76 | .type = SMS_NOVA_B0, | |
77 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", | |
250fa674 | 78 | .lna_ctrl = 29, |
9504ccac | 79 | .board_cfg.foreign_lna0_ctrl = 29, |
d54093af | 80 | .rf_switch = 17, |
9504ccac | 81 | .board_cfg.rf_switch_uhf = 17, |
250fa674 MK |
82 | }, |
83 | [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = { | |
84 | .name = "Hauppauge WinTV MiniCard", | |
85 | .type = SMS_NOVA_B0, | |
86 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", | |
f4c82548 | 87 | .lna_ctrl = -1, |
3f7d99f6 | 88 | }, |
d0b66180 US |
89 | [SMS1XXX_BOARD_SIANO_NICE] = { |
90 | /* 11 */ | |
91 | .name = "Siano Nice Digital Receiver", | |
92 | .type = SMS_NOVA_B0, | |
93 | }, | |
94 | [SMS1XXX_BOARD_SIANO_VENICE] = { | |
95 | /* 12 */ | |
96 | .name = "Siano Venice Digital Receiver", | |
97 | .type = SMS_VEGA, | |
98 | }, | |
1c11d546 MK |
99 | }; |
100 | ||
3a054627 | 101 | struct sms_board *sms_get_board(unsigned id) |
1c11d546 MK |
102 | { |
103 | BUG_ON(id >= ARRAY_SIZE(sms_boards)); | |
104 | ||
105 | return &sms_boards[id]; | |
106 | } | |
a0beec8f | 107 | EXPORT_SYMBOL_GPL(sms_get_board); |
5b8db897 US |
108 | static inline void sms_gpio_assign_11xx_default_led_config( |
109 | struct smscore_gpio_config *pGpioConfig) { | |
110 | pGpioConfig->Direction = SMS_GPIO_DIRECTION_OUTPUT; | |
111 | pGpioConfig->InputCharacteristics = | |
112 | SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL; | |
113 | pGpioConfig->OutputDriving = SMS_GPIO_OUTPUT_DRIVING_4mA; | |
114 | pGpioConfig->OutputSlewRate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS; | |
115 | pGpioConfig->PullUpDown = SMS_GPIO_PULL_UP_DOWN_NONE; | |
116 | } | |
117 | ||
118 | int sms_board_event(struct smscore_device_t *coredev, | |
119 | enum SMS_BOARD_EVENTS gevent) { | |
5b8db897 US |
120 | struct smscore_gpio_config MyGpioConfig; |
121 | ||
122 | sms_gpio_assign_11xx_default_led_config(&MyGpioConfig); | |
123 | ||
124 | switch (gevent) { | |
125 | case BOARD_EVENT_POWER_INIT: /* including hotplug */ | |
5b8db897 US |
126 | break; /* BOARD_EVENT_BIND */ |
127 | ||
128 | case BOARD_EVENT_POWER_SUSPEND: | |
5b8db897 US |
129 | break; /* BOARD_EVENT_POWER_SUSPEND */ |
130 | ||
131 | case BOARD_EVENT_POWER_RESUME: | |
5b8db897 US |
132 | break; /* BOARD_EVENT_POWER_RESUME */ |
133 | ||
134 | case BOARD_EVENT_BIND: | |
5b8db897 US |
135 | break; /* BOARD_EVENT_BIND */ |
136 | ||
137 | case BOARD_EVENT_SCAN_PROG: | |
138 | break; /* BOARD_EVENT_SCAN_PROG */ | |
139 | case BOARD_EVENT_SCAN_COMP: | |
140 | break; /* BOARD_EVENT_SCAN_COMP */ | |
141 | case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL: | |
142 | break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */ | |
143 | case BOARD_EVENT_FE_LOCK: | |
5b8db897 US |
144 | break; /* BOARD_EVENT_FE_LOCK */ |
145 | case BOARD_EVENT_FE_UNLOCK: | |
5b8db897 US |
146 | break; /* BOARD_EVENT_FE_UNLOCK */ |
147 | case BOARD_EVENT_DEMOD_LOCK: | |
148 | break; /* BOARD_EVENT_DEMOD_LOCK */ | |
149 | case BOARD_EVENT_DEMOD_UNLOCK: | |
150 | break; /* BOARD_EVENT_DEMOD_UNLOCK */ | |
151 | case BOARD_EVENT_RECEPTION_MAX_4: | |
152 | break; /* BOARD_EVENT_RECEPTION_MAX_4 */ | |
153 | case BOARD_EVENT_RECEPTION_3: | |
154 | break; /* BOARD_EVENT_RECEPTION_3 */ | |
155 | case BOARD_EVENT_RECEPTION_2: | |
156 | break; /* BOARD_EVENT_RECEPTION_2 */ | |
157 | case BOARD_EVENT_RECEPTION_1: | |
158 | break; /* BOARD_EVENT_RECEPTION_1 */ | |
159 | case BOARD_EVENT_RECEPTION_LOST_0: | |
160 | break; /* BOARD_EVENT_RECEPTION_LOST_0 */ | |
161 | case BOARD_EVENT_MULTIPLEX_OK: | |
5b8db897 US |
162 | break; /* BOARD_EVENT_MULTIPLEX_OK */ |
163 | case BOARD_EVENT_MULTIPLEX_ERRORS: | |
5b8db897 US |
164 | break; /* BOARD_EVENT_MULTIPLEX_ERRORS */ |
165 | ||
166 | default: | |
167 | sms_err("Unknown SMS board event"); | |
168 | break; | |
169 | } | |
170 | return 0; | |
171 | } | |
172 | EXPORT_SYMBOL_GPL(sms_board_event); | |
1c11d546 | 173 | |
dd72f31b | 174 | static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable) |
250fa674 | 175 | { |
dd72f31b MK |
176 | int lvl, ret; |
177 | u32 gpio; | |
7c4ca79f | 178 | struct smscore_config_gpio gpioconfig = { |
250fa674 MK |
179 | .direction = SMS_GPIO_DIRECTION_OUTPUT, |
180 | .pullupdown = SMS_GPIO_PULLUPDOWN_NONE, | |
181 | .inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL, | |
182 | .outputslewrate = SMS_GPIO_OUTPUTSLEWRATE_FAST, | |
183 | .outputdriving = SMS_GPIO_OUTPUTDRIVING_4mA, | |
184 | }; | |
185 | ||
186 | if (pin == 0) | |
187 | return -EINVAL; | |
188 | ||
dd72f31b MK |
189 | if (pin < 0) { |
190 | /* inverted gpio */ | |
191 | gpio = pin * -1; | |
192 | lvl = enable ? 0 : 1; | |
193 | } else { | |
194 | gpio = pin; | |
195 | lvl = enable ? 1 : 0; | |
196 | } | |
250fa674 | 197 | |
dd72f31b | 198 | ret = smscore_configure_gpio(coredev, gpio, &gpioconfig); |
250fa674 MK |
199 | if (ret < 0) |
200 | return ret; | |
201 | ||
dd72f31b | 202 | return smscore_set_gpio(coredev, gpio, lvl); |
250fa674 MK |
203 | } |
204 | ||
205 | int sms_board_setup(struct smscore_device_t *coredev) | |
206 | { | |
207 | int board_id = smscore_get_board_id(coredev); | |
208 | struct sms_board *board = sms_get_board(board_id); | |
209 | ||
210 | switch (board_id) { | |
211 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | |
212 | /* turn off all LEDs */ | |
213 | sms_set_gpio(coredev, board->led_power, 0); | |
214 | sms_set_gpio(coredev, board->led_hi, 0); | |
215 | sms_set_gpio(coredev, board->led_lo, 0); | |
216 | break; | |
dff65740 MK |
217 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: |
218 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | |
219 | /* turn off LNA */ | |
220 | sms_set_gpio(coredev, board->lna_ctrl, 0); | |
221 | break; | |
250fa674 MK |
222 | } |
223 | return 0; | |
224 | } | |
a0beec8f | 225 | EXPORT_SYMBOL_GPL(sms_board_setup); |
7a6fbed6 MK |
226 | |
227 | int sms_board_power(struct smscore_device_t *coredev, int onoff) | |
228 | { | |
229 | int board_id = smscore_get_board_id(coredev); | |
230 | struct sms_board *board = sms_get_board(board_id); | |
231 | ||
232 | switch (board_id) { | |
233 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | |
234 | /* power LED */ | |
235 | sms_set_gpio(coredev, | |
236 | board->led_power, onoff ? 1 : 0); | |
237 | break; | |
dff65740 MK |
238 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: |
239 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | |
240 | /* LNA */ | |
d54093af MK |
241 | if (!onoff) |
242 | sms_set_gpio(coredev, board->lna_ctrl, 0); | |
dff65740 | 243 | break; |
7a6fbed6 MK |
244 | } |
245 | return 0; | |
246 | } | |
a0beec8f | 247 | EXPORT_SYMBOL_GPL(sms_board_power); |
7b29e10d MK |
248 | |
249 | int sms_board_led_feedback(struct smscore_device_t *coredev, int led) | |
250 | { | |
251 | int board_id = smscore_get_board_id(coredev); | |
252 | struct sms_board *board = sms_get_board(board_id); | |
253 | ||
254 | /* dont touch GPIO if LEDs are already set */ | |
255 | if (smscore_led_state(coredev, -1) == led) | |
256 | return 0; | |
257 | ||
258 | switch (board_id) { | |
259 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | |
260 | sms_set_gpio(coredev, | |
261 | board->led_lo, (led & SMS_LED_LO) ? 1 : 0); | |
262 | sms_set_gpio(coredev, | |
263 | board->led_hi, (led & SMS_LED_HI) ? 1 : 0); | |
264 | ||
265 | smscore_led_state(coredev, led); | |
266 | break; | |
267 | } | |
268 | return 0; | |
269 | } | |
a0beec8f | 270 | EXPORT_SYMBOL_GPL(sms_board_led_feedback); |
d54093af MK |
271 | |
272 | int sms_board_lna_control(struct smscore_device_t *coredev, int onoff) | |
273 | { | |
274 | int board_id = smscore_get_board_id(coredev); | |
275 | struct sms_board *board = sms_get_board(board_id); | |
276 | ||
277 | sms_debug("%s: LNA %s", __func__, onoff ? "enabled" : "disabled"); | |
278 | ||
279 | switch (board_id) { | |
280 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | |
281 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | |
282 | sms_set_gpio(coredev, | |
283 | board->rf_switch, onoff ? 1 : 0); | |
284 | return sms_set_gpio(coredev, | |
285 | board->lna_ctrl, onoff ? 1 : 0); | |
286 | } | |
287 | return -EINVAL; | |
288 | } | |
a0beec8f | 289 | EXPORT_SYMBOL_GPL(sms_board_lna_control); |
05860f2d MK |
290 | |
291 | int sms_board_load_modules(int id) | |
292 | { | |
293 | switch (id) { | |
294 | case SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT: | |
295 | case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A: | |
296 | case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B: | |
297 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | |
7dee9d1c ÉP |
298 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: |
299 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | |
05860f2d MK |
300 | request_module("smsdvb"); |
301 | break; | |
302 | default: | |
303 | /* do nothing */ | |
304 | break; | |
305 | } | |
306 | return 0; | |
307 | } | |
a0beec8f | 308 | EXPORT_SYMBOL_GPL(sms_board_load_modules); |