V4L/DVB (11883): Siano: cards - add two additional (USB) devices
[linux-2.6] / drivers / media / dvb / siano / sms-cards.c
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
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
27 static 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_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
66                 .board_cfg.leds_power = 26,
67                 .board_cfg.led0 = 27,
68                 .board_cfg.led1 = 28,
69                 .led_power = 26,
70                 .led_lo    = 27,
71                 .led_hi    = 28,
72         },
73         [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD] = {
74                 .name   = "Hauppauge WinTV MiniCard",
75                 .type   = SMS_NOVA_B0,
76                 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
77                 .lna_ctrl  = 29,
78                 .board_cfg.foreign_lna0_ctrl = 29,
79                 .rf_switch = 17,
80                 .board_cfg.rf_switch_uhf = 17,
81         },
82         [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = {
83                 .name   = "Hauppauge WinTV MiniCard",
84                 .type   = SMS_NOVA_B0,
85                 .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw",
86                 .lna_ctrl  = -1,
87         },
88         [SMS1XXX_BOARD_SIANO_NICE] = {
89         /* 11 */
90                 .name = "Siano Nice Digital Receiver",
91                 .type = SMS_NOVA_B0,
92         },
93         [SMS1XXX_BOARD_SIANO_VENICE] = {
94         /* 12 */
95                 .name = "Siano Venice Digital Receiver",
96                 .type = SMS_VEGA,
97         },
98 };
99
100 struct sms_board *sms_get_board(int id)
101 {
102         BUG_ON(id >= ARRAY_SIZE(sms_boards));
103
104         return &sms_boards[id];
105 }
106 EXPORT_SYMBOL_GPL(sms_get_board);
107
108 static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable)
109 {
110         int lvl, ret;
111         u32 gpio;
112         struct smscore_gpio_config gpioconfig = {
113                 .direction            = SMS_GPIO_DIRECTION_OUTPUT,
114                 .pullupdown           = SMS_GPIO_PULLUPDOWN_NONE,
115                 .inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL,
116                 .outputslewrate       = SMS_GPIO_OUTPUTSLEWRATE_FAST,
117                 .outputdriving        = SMS_GPIO_OUTPUTDRIVING_4mA,
118         };
119
120         if (pin == 0)
121                 return -EINVAL;
122
123         if (pin < 0) {
124                 /* inverted gpio */
125                 gpio = pin * -1;
126                 lvl = enable ? 0 : 1;
127         } else {
128                 gpio = pin;
129                 lvl = enable ? 1 : 0;
130         }
131
132         ret = smscore_configure_gpio(coredev, gpio, &gpioconfig);
133         if (ret < 0)
134                 return ret;
135
136         return smscore_set_gpio(coredev, gpio, lvl);
137 }
138
139 int sms_board_setup(struct smscore_device_t *coredev)
140 {
141         int board_id = smscore_get_board_id(coredev);
142         struct sms_board *board = sms_get_board(board_id);
143
144         switch (board_id) {
145         case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
146                 /* turn off all LEDs */
147                 sms_set_gpio(coredev, board->led_power, 0);
148                 sms_set_gpio(coredev, board->led_hi, 0);
149                 sms_set_gpio(coredev, board->led_lo, 0);
150                 break;
151         case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
152         case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
153                 /* turn off LNA */
154                 sms_set_gpio(coredev, board->lna_ctrl, 0);
155                 break;
156         }
157         return 0;
158 }
159 EXPORT_SYMBOL_GPL(sms_board_setup);
160
161 int sms_board_power(struct smscore_device_t *coredev, int onoff)
162 {
163         int board_id = smscore_get_board_id(coredev);
164         struct sms_board *board = sms_get_board(board_id);
165
166         switch (board_id) {
167         case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
168                 /* power LED */
169                 sms_set_gpio(coredev,
170                              board->led_power, onoff ? 1 : 0);
171                 break;
172         case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
173         case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
174                 /* LNA */
175                 if (!onoff)
176                         sms_set_gpio(coredev, board->lna_ctrl, 0);
177                 break;
178         }
179         return 0;
180 }
181 EXPORT_SYMBOL_GPL(sms_board_power);
182
183 int sms_board_led_feedback(struct smscore_device_t *coredev, int led)
184 {
185         int board_id = smscore_get_board_id(coredev);
186         struct sms_board *board = sms_get_board(board_id);
187
188         /* dont touch GPIO if LEDs are already set */
189         if (smscore_led_state(coredev, -1) == led)
190                 return 0;
191
192         switch (board_id) {
193         case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
194                 sms_set_gpio(coredev,
195                              board->led_lo, (led & SMS_LED_LO) ? 1 : 0);
196                 sms_set_gpio(coredev,
197                              board->led_hi, (led & SMS_LED_HI) ? 1 : 0);
198
199                 smscore_led_state(coredev, led);
200                 break;
201         }
202         return 0;
203 }
204 EXPORT_SYMBOL_GPL(sms_board_led_feedback);
205
206 int sms_board_lna_control(struct smscore_device_t *coredev, int onoff)
207 {
208         int board_id = smscore_get_board_id(coredev);
209         struct sms_board *board = sms_get_board(board_id);
210
211         sms_debug("%s: LNA %s", __func__, onoff ? "enabled" : "disabled");
212
213         switch (board_id) {
214         case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2:
215         case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD:
216                 sms_set_gpio(coredev,
217                              board->rf_switch, onoff ? 1 : 0);
218                 return sms_set_gpio(coredev,
219                                     board->lna_ctrl, onoff ? 1 : 0);
220         }
221         return -EINVAL;
222 }
223 EXPORT_SYMBOL_GPL(sms_board_lna_control);
224
225 int sms_board_load_modules(int id)
226 {
227         switch (id) {
228         case SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT:
229         case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A:
230         case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B:
231         case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM:
232                 request_module("smsdvb");
233                 break;
234         default:
235                 /* do nothing */
236                 break;
237         }
238         return 0;
239 }
240 EXPORT_SYMBOL_GPL(sms_board_load_modules);