diff options
Diffstat (limited to 'drivers/media/dvb/siano')
-rw-r--r-- | drivers/media/dvb/siano/Makefile | 2 | ||||
-rw-r--r-- | drivers/media/dvb/siano/sms-cards.c | 188 | ||||
-rw-r--r-- | drivers/media/dvb/siano/sms-cards.h | 64 | ||||
-rw-r--r-- | drivers/media/dvb/siano/smscoreapi.c | 468 | ||||
-rw-r--r-- | drivers/media/dvb/siano/smscoreapi.h | 488 | ||||
-rw-r--r-- | drivers/media/dvb/siano/smsdvb.c | 372 | ||||
-rw-r--r-- | drivers/media/dvb/siano/smsendian.c | 102 | ||||
-rw-r--r-- | drivers/media/dvb/siano/smsendian.h | 32 | ||||
-rw-r--r-- | drivers/media/dvb/siano/smsir.c | 301 | ||||
-rw-r--r-- | drivers/media/dvb/siano/smsir.h | 93 | ||||
-rw-r--r-- | drivers/media/dvb/siano/smssdio.c | 357 | ||||
-rw-r--r-- | drivers/media/dvb/siano/smsusb.c | 75 |
12 files changed, 2172 insertions, 370 deletions
diff --git a/drivers/media/dvb/siano/Makefile b/drivers/media/dvb/siano/Makefile index bcf93f4828b2..c6644d909433 100644 --- a/drivers/media/dvb/siano/Makefile +++ b/drivers/media/dvb/siano/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | sms1xxx-objs := smscoreapi.o sms-cards.o | 1 | sms1xxx-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o |
2 | 2 | ||
3 | obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o | 3 | obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o |
4 | obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o | 4 | obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o |
diff --git a/drivers/media/dvb/siano/sms-cards.c b/drivers/media/dvb/siano/sms-cards.c index 63e4d0ec6583..d8b15d583bde 100644 --- a/drivers/media/dvb/siano/sms-cards.c +++ b/drivers/media/dvb/siano/sms-cards.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include "sms-cards.h" | 20 | #include "sms-cards.h" |
21 | #include "smsir.h" | ||
21 | 22 | ||
22 | static int sms_dbg; | 23 | static int sms_dbg; |
23 | module_param_named(cards_dbg, sms_dbg, int, 0644); | 24 | module_param_named(cards_dbg, sms_dbg, int, 0644); |
@@ -30,17 +31,14 @@ static struct sms_board sms_boards[] = { | |||
30 | [SMS1XXX_BOARD_SIANO_STELLAR] = { | 31 | [SMS1XXX_BOARD_SIANO_STELLAR] = { |
31 | .name = "Siano Stellar Digital Receiver", | 32 | .name = "Siano Stellar Digital Receiver", |
32 | .type = SMS_STELLAR, | 33 | .type = SMS_STELLAR, |
33 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw", | ||
34 | }, | 34 | }, |
35 | [SMS1XXX_BOARD_SIANO_NOVA_A] = { | 35 | [SMS1XXX_BOARD_SIANO_NOVA_A] = { |
36 | .name = "Siano Nova A Digital Receiver", | 36 | .name = "Siano Nova A Digital Receiver", |
37 | .type = SMS_NOVA_A0, | 37 | .type = SMS_NOVA_A0, |
38 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw", | ||
39 | }, | 38 | }, |
40 | [SMS1XXX_BOARD_SIANO_NOVA_B] = { | 39 | [SMS1XXX_BOARD_SIANO_NOVA_B] = { |
41 | .name = "Siano Nova B Digital Receiver", | 40 | .name = "Siano Nova B Digital Receiver", |
42 | .type = SMS_NOVA_B0, | 41 | .type = SMS_NOVA_B0, |
43 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw", | ||
44 | }, | 42 | }, |
45 | [SMS1XXX_BOARD_SIANO_VEGA] = { | 43 | [SMS1XXX_BOARD_SIANO_VEGA] = { |
46 | .name = "Siano Vega Digital Receiver", | 44 | .name = "Siano Vega Digital Receiver", |
@@ -65,6 +63,9 @@ static struct sms_board sms_boards[] = { | |||
65 | .name = "Hauppauge WinTV MiniStick", | 63 | .name = "Hauppauge WinTV MiniStick", |
66 | .type = SMS_NOVA_B0, | 64 | .type = SMS_NOVA_B0, |
67 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", | 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, | ||
68 | .led_power = 26, | 69 | .led_power = 26, |
69 | .led_lo = 27, | 70 | .led_lo = 27, |
70 | .led_hi = 28, | 71 | .led_hi = 28, |
@@ -74,7 +75,9 @@ static struct sms_board sms_boards[] = { | |||
74 | .type = SMS_NOVA_B0, | 75 | .type = SMS_NOVA_B0, |
75 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", | 76 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", |
76 | .lna_ctrl = 29, | 77 | .lna_ctrl = 29, |
78 | .board_cfg.foreign_lna0_ctrl = 29, | ||
77 | .rf_switch = 17, | 79 | .rf_switch = 17, |
80 | .board_cfg.rf_switch_uhf = 17, | ||
78 | }, | 81 | }, |
79 | [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = { | 82 | [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = { |
80 | .name = "Hauppauge WinTV MiniCard", | 83 | .name = "Hauppauge WinTV MiniCard", |
@@ -82,6 +85,16 @@ static struct sms_board sms_boards[] = { | |||
82 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", | 85 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", |
83 | .lna_ctrl = -1, | 86 | .lna_ctrl = -1, |
84 | }, | 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 | }, | ||
85 | }; | 98 | }; |
86 | 99 | ||
87 | struct sms_board *sms_get_board(int id) | 100 | struct sms_board *sms_get_board(int id) |
@@ -91,12 +104,179 @@ struct sms_board *sms_get_board(int id) | |||
91 | return &sms_boards[id]; | 104 | return &sms_boards[id]; |
92 | } | 105 | } |
93 | EXPORT_SYMBOL_GPL(sms_get_board); | 106 | EXPORT_SYMBOL_GPL(sms_get_board); |
107 | static inline void sms_gpio_assign_11xx_default_led_config( | ||
108 | struct smscore_gpio_config *pGpioConfig) { | ||
109 | pGpioConfig->Direction = SMS_GPIO_DIRECTION_OUTPUT; | ||
110 | pGpioConfig->InputCharacteristics = | ||
111 | SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL; | ||
112 | pGpioConfig->OutputDriving = SMS_GPIO_OUTPUT_DRIVING_4mA; | ||
113 | pGpioConfig->OutputSlewRate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS; | ||
114 | pGpioConfig->PullUpDown = SMS_GPIO_PULL_UP_DOWN_NONE; | ||
115 | } | ||
116 | |||
117 | int sms_board_event(struct smscore_device_t *coredev, | ||
118 | enum SMS_BOARD_EVENTS gevent) { | ||
119 | int board_id = smscore_get_board_id(coredev); | ||
120 | struct sms_board *board = sms_get_board(board_id); | ||
121 | struct smscore_gpio_config MyGpioConfig; | ||
122 | |||
123 | sms_gpio_assign_11xx_default_led_config(&MyGpioConfig); | ||
124 | |||
125 | switch (gevent) { | ||
126 | case BOARD_EVENT_POWER_INIT: /* including hotplug */ | ||
127 | switch (board_id) { | ||
128 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
129 | /* set I/O and turn off all LEDs */ | ||
130 | smscore_gpio_configure(coredev, | ||
131 | board->board_cfg.leds_power, | ||
132 | &MyGpioConfig); | ||
133 | smscore_gpio_set_level(coredev, | ||
134 | board->board_cfg.leds_power, 0); | ||
135 | smscore_gpio_configure(coredev, board->board_cfg.led0, | ||
136 | &MyGpioConfig); | ||
137 | smscore_gpio_set_level(coredev, | ||
138 | board->board_cfg.led0, 0); | ||
139 | smscore_gpio_configure(coredev, board->board_cfg.led1, | ||
140 | &MyGpioConfig); | ||
141 | smscore_gpio_set_level(coredev, | ||
142 | board->board_cfg.led1, 0); | ||
143 | break; | ||
144 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | ||
145 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | ||
146 | /* set I/O and turn off LNA */ | ||
147 | smscore_gpio_configure(coredev, | ||
148 | board->board_cfg.foreign_lna0_ctrl, | ||
149 | &MyGpioConfig); | ||
150 | smscore_gpio_set_level(coredev, | ||
151 | board->board_cfg.foreign_lna0_ctrl, | ||
152 | 0); | ||
153 | break; | ||
154 | } | ||
155 | break; /* BOARD_EVENT_BIND */ | ||
156 | |||
157 | case BOARD_EVENT_POWER_SUSPEND: | ||
158 | switch (board_id) { | ||
159 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
160 | smscore_gpio_set_level(coredev, | ||
161 | board->board_cfg.leds_power, 0); | ||
162 | smscore_gpio_set_level(coredev, | ||
163 | board->board_cfg.led0, 0); | ||
164 | smscore_gpio_set_level(coredev, | ||
165 | board->board_cfg.led1, 0); | ||
166 | break; | ||
167 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | ||
168 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | ||
169 | smscore_gpio_set_level(coredev, | ||
170 | board->board_cfg.foreign_lna0_ctrl, | ||
171 | 0); | ||
172 | break; | ||
173 | } | ||
174 | break; /* BOARD_EVENT_POWER_SUSPEND */ | ||
175 | |||
176 | case BOARD_EVENT_POWER_RESUME: | ||
177 | switch (board_id) { | ||
178 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
179 | smscore_gpio_set_level(coredev, | ||
180 | board->board_cfg.leds_power, 1); | ||
181 | smscore_gpio_set_level(coredev, | ||
182 | board->board_cfg.led0, 1); | ||
183 | smscore_gpio_set_level(coredev, | ||
184 | board->board_cfg.led1, 0); | ||
185 | break; | ||
186 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | ||
187 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | ||
188 | smscore_gpio_set_level(coredev, | ||
189 | board->board_cfg.foreign_lna0_ctrl, | ||
190 | 1); | ||
191 | break; | ||
192 | } | ||
193 | break; /* BOARD_EVENT_POWER_RESUME */ | ||
194 | |||
195 | case BOARD_EVENT_BIND: | ||
196 | switch (board_id) { | ||
197 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
198 | smscore_gpio_set_level(coredev, | ||
199 | board->board_cfg.leds_power, 1); | ||
200 | smscore_gpio_set_level(coredev, | ||
201 | board->board_cfg.led0, 1); | ||
202 | smscore_gpio_set_level(coredev, | ||
203 | board->board_cfg.led1, 0); | ||
204 | break; | ||
205 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | ||
206 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | ||
207 | smscore_gpio_set_level(coredev, | ||
208 | board->board_cfg.foreign_lna0_ctrl, | ||
209 | 1); | ||
210 | break; | ||
211 | } | ||
212 | break; /* BOARD_EVENT_BIND */ | ||
213 | |||
214 | case BOARD_EVENT_SCAN_PROG: | ||
215 | break; /* BOARD_EVENT_SCAN_PROG */ | ||
216 | case BOARD_EVENT_SCAN_COMP: | ||
217 | break; /* BOARD_EVENT_SCAN_COMP */ | ||
218 | case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL: | ||
219 | break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */ | ||
220 | case BOARD_EVENT_FE_LOCK: | ||
221 | switch (board_id) { | ||
222 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
223 | smscore_gpio_set_level(coredev, | ||
224 | board->board_cfg.led1, 1); | ||
225 | break; | ||
226 | } | ||
227 | break; /* BOARD_EVENT_FE_LOCK */ | ||
228 | case BOARD_EVENT_FE_UNLOCK: | ||
229 | switch (board_id) { | ||
230 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
231 | smscore_gpio_set_level(coredev, | ||
232 | board->board_cfg.led1, 0); | ||
233 | break; | ||
234 | } | ||
235 | break; /* BOARD_EVENT_FE_UNLOCK */ | ||
236 | case BOARD_EVENT_DEMOD_LOCK: | ||
237 | break; /* BOARD_EVENT_DEMOD_LOCK */ | ||
238 | case BOARD_EVENT_DEMOD_UNLOCK: | ||
239 | break; /* BOARD_EVENT_DEMOD_UNLOCK */ | ||
240 | case BOARD_EVENT_RECEPTION_MAX_4: | ||
241 | break; /* BOARD_EVENT_RECEPTION_MAX_4 */ | ||
242 | case BOARD_EVENT_RECEPTION_3: | ||
243 | break; /* BOARD_EVENT_RECEPTION_3 */ | ||
244 | case BOARD_EVENT_RECEPTION_2: | ||
245 | break; /* BOARD_EVENT_RECEPTION_2 */ | ||
246 | case BOARD_EVENT_RECEPTION_1: | ||
247 | break; /* BOARD_EVENT_RECEPTION_1 */ | ||
248 | case BOARD_EVENT_RECEPTION_LOST_0: | ||
249 | break; /* BOARD_EVENT_RECEPTION_LOST_0 */ | ||
250 | case BOARD_EVENT_MULTIPLEX_OK: | ||
251 | switch (board_id) { | ||
252 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
253 | smscore_gpio_set_level(coredev, | ||
254 | board->board_cfg.led1, 1); | ||
255 | break; | ||
256 | } | ||
257 | break; /* BOARD_EVENT_MULTIPLEX_OK */ | ||
258 | case BOARD_EVENT_MULTIPLEX_ERRORS: | ||
259 | switch (board_id) { | ||
260 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
261 | smscore_gpio_set_level(coredev, | ||
262 | board->board_cfg.led1, 0); | ||
263 | break; | ||
264 | } | ||
265 | break; /* BOARD_EVENT_MULTIPLEX_ERRORS */ | ||
266 | |||
267 | default: | ||
268 | sms_err("Unknown SMS board event"); | ||
269 | break; | ||
270 | } | ||
271 | return 0; | ||
272 | } | ||
273 | EXPORT_SYMBOL_GPL(sms_board_event); | ||
94 | 274 | ||
95 | static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable) | 275 | static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable) |
96 | { | 276 | { |
97 | int lvl, ret; | 277 | int lvl, ret; |
98 | u32 gpio; | 278 | u32 gpio; |
99 | struct smscore_gpio_config gpioconfig = { | 279 | struct smscore_config_gpio gpioconfig = { |
100 | .direction = SMS_GPIO_DIRECTION_OUTPUT, | 280 | .direction = SMS_GPIO_DIRECTION_OUTPUT, |
101 | .pullupdown = SMS_GPIO_PULLUPDOWN_NONE, | 281 | .pullupdown = SMS_GPIO_PULLUPDOWN_NONE, |
102 | .inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL, | 282 | .inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL, |
diff --git a/drivers/media/dvb/siano/sms-cards.h b/drivers/media/dvb/siano/sms-cards.h index 64d74c59c33f..38f062f6ad68 100644 --- a/drivers/media/dvb/siano/sms-cards.h +++ b/drivers/media/dvb/siano/sms-cards.h | |||
@@ -22,6 +22,7 @@ | |||
22 | 22 | ||
23 | #include <linux/usb.h> | 23 | #include <linux/usb.h> |
24 | #include "smscoreapi.h" | 24 | #include "smscoreapi.h" |
25 | #include "smsir.h" | ||
25 | 26 | ||
26 | #define SMS_BOARD_UNKNOWN 0 | 27 | #define SMS_BOARD_UNKNOWN 0 |
27 | #define SMS1XXX_BOARD_SIANO_STELLAR 1 | 28 | #define SMS1XXX_BOARD_SIANO_STELLAR 1 |
@@ -34,10 +35,47 @@ | |||
34 | #define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8 | 35 | #define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8 |
35 | #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD 9 | 36 | #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD 9 |
36 | #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10 | 37 | #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10 |
38 | #define SMS1XXX_BOARD_SIANO_NICE 11 | ||
39 | #define SMS1XXX_BOARD_SIANO_VENICE 12 | ||
40 | |||
41 | struct sms_board_gpio_cfg { | ||
42 | int lna_vhf_exist; | ||
43 | int lna_vhf_ctrl; | ||
44 | int lna_uhf_exist; | ||
45 | int lna_uhf_ctrl; | ||
46 | int lna_uhf_d_ctrl; | ||
47 | int lna_sband_exist; | ||
48 | int lna_sband_ctrl; | ||
49 | int lna_sband_d_ctrl; | ||
50 | int foreign_lna0_ctrl; | ||
51 | int foreign_lna1_ctrl; | ||
52 | int foreign_lna2_ctrl; | ||
53 | int rf_switch_vhf; | ||
54 | int rf_switch_uhf; | ||
55 | int rf_switch_sband; | ||
56 | int leds_power; | ||
57 | int led0; | ||
58 | int led1; | ||
59 | int led2; | ||
60 | int led3; | ||
61 | int led4; | ||
62 | int ir; | ||
63 | int eeprom_wp; | ||
64 | int mrc_sense; | ||
65 | int mrc_pdn_resetn; | ||
66 | int mrc_gp0; /* mrcs spi int */ | ||
67 | int mrc_gp1; | ||
68 | int mrc_gp2; | ||
69 | int mrc_gp3; | ||
70 | int mrc_gp4; | ||
71 | int host_spi_gsp_ts_int; | ||
72 | }; | ||
37 | 73 | ||
38 | struct sms_board { | 74 | struct sms_board { |
39 | enum sms_device_type_st type; | 75 | enum sms_device_type_st type; |
40 | char *name, *fw[DEVICE_MODE_MAX]; | 76 | char *name, *fw[DEVICE_MODE_MAX]; |
77 | struct sms_board_gpio_cfg board_cfg; | ||
78 | enum ir_kb_type ir_kb_type; | ||
41 | 79 | ||
42 | /* gpios */ | 80 | /* gpios */ |
43 | int led_power, led_hi, led_lo, lna_ctrl, rf_switch; | 81 | int led_power, led_hi, led_lo, lna_ctrl, rf_switch; |
@@ -45,6 +83,32 @@ struct sms_board { | |||
45 | 83 | ||
46 | struct sms_board *sms_get_board(int id); | 84 | struct sms_board *sms_get_board(int id); |
47 | 85 | ||
86 | extern struct smscore_device_t *coredev; | ||
87 | |||
88 | enum SMS_BOARD_EVENTS { | ||
89 | BOARD_EVENT_POWER_INIT, | ||
90 | BOARD_EVENT_POWER_SUSPEND, | ||
91 | BOARD_EVENT_POWER_RESUME, | ||
92 | BOARD_EVENT_BIND, | ||
93 | BOARD_EVENT_SCAN_PROG, | ||
94 | BOARD_EVENT_SCAN_COMP, | ||
95 | BOARD_EVENT_EMERGENCY_WARNING_SIGNAL, | ||
96 | BOARD_EVENT_FE_LOCK, | ||
97 | BOARD_EVENT_FE_UNLOCK, | ||
98 | BOARD_EVENT_DEMOD_LOCK, | ||
99 | BOARD_EVENT_DEMOD_UNLOCK, | ||
100 | BOARD_EVENT_RECEPTION_MAX_4, | ||
101 | BOARD_EVENT_RECEPTION_3, | ||
102 | BOARD_EVENT_RECEPTION_2, | ||
103 | BOARD_EVENT_RECEPTION_1, | ||
104 | BOARD_EVENT_RECEPTION_LOST_0, | ||
105 | BOARD_EVENT_MULTIPLEX_OK, | ||
106 | BOARD_EVENT_MULTIPLEX_ERRORS | ||
107 | }; | ||
108 | |||
109 | int sms_board_event(struct smscore_device_t *coredev, | ||
110 | enum SMS_BOARD_EVENTS gevent); | ||
111 | |||
48 | int sms_board_setup(struct smscore_device_t *coredev); | 112 | int sms_board_setup(struct smscore_device_t *coredev); |
49 | 113 | ||
50 | #define SMS_LED_OFF 0 | 114 | #define SMS_LED_OFF 0 |
diff --git a/drivers/media/dvb/siano/smscoreapi.c b/drivers/media/dvb/siano/smscoreapi.c index 7bd4d1dee2b3..32be382f0e97 100644 --- a/drivers/media/dvb/siano/smscoreapi.c +++ b/drivers/media/dvb/siano/smscoreapi.c | |||
@@ -30,9 +30,13 @@ | |||
30 | #include <linux/io.h> | 30 | #include <linux/io.h> |
31 | 31 | ||
32 | #include <linux/firmware.h> | 32 | #include <linux/firmware.h> |
33 | #include <linux/wait.h> | ||
34 | #include <asm/byteorder.h> | ||
33 | 35 | ||
34 | #include "smscoreapi.h" | 36 | #include "smscoreapi.h" |
35 | #include "sms-cards.h" | 37 | #include "sms-cards.h" |
38 | #include "smsir.h" | ||
39 | #include "smsendian.h" | ||
36 | 40 | ||
37 | static int sms_dbg; | 41 | static int sms_dbg; |
38 | module_param_named(debug, sms_dbg, int, 0644); | 42 | module_param_named(debug, sms_dbg, int, 0644); |
@@ -58,42 +62,6 @@ struct smscore_client_t { | |||
58 | onremove_t onremove_handler; | 62 | onremove_t onremove_handler; |
59 | }; | 63 | }; |
60 | 64 | ||
61 | struct smscore_device_t { | ||
62 | struct list_head entry; | ||
63 | |||
64 | struct list_head clients; | ||
65 | struct list_head subclients; | ||
66 | spinlock_t clientslock; | ||
67 | |||
68 | struct list_head buffers; | ||
69 | spinlock_t bufferslock; | ||
70 | int num_buffers; | ||
71 | |||
72 | void *common_buffer; | ||
73 | int common_buffer_size; | ||
74 | dma_addr_t common_buffer_phys; | ||
75 | |||
76 | void *context; | ||
77 | struct device *device; | ||
78 | |||
79 | char devpath[32]; | ||
80 | unsigned long device_flags; | ||
81 | |||
82 | setmode_t setmode_handler; | ||
83 | detectmode_t detectmode_handler; | ||
84 | sendrequest_t sendrequest_handler; | ||
85 | preload_t preload_handler; | ||
86 | postload_t postload_handler; | ||
87 | |||
88 | int mode, modes_supported; | ||
89 | |||
90 | struct completion version_ex_done, data_download_done, trigger_done; | ||
91 | struct completion init_device_done, reload_start_done, resume_done; | ||
92 | |||
93 | int board_id; | ||
94 | int led_state; | ||
95 | }; | ||
96 | |||
97 | void smscore_set_board_id(struct smscore_device_t *core, int id) | 65 | void smscore_set_board_id(struct smscore_device_t *core, int id) |
98 | { | 66 | { |
99 | core->board_id = id; | 67 | core->board_id = id; |
@@ -384,6 +352,13 @@ int smscore_register_device(struct smsdevice_params_t *params, | |||
384 | init_completion(&dev->init_device_done); | 352 | init_completion(&dev->init_device_done); |
385 | init_completion(&dev->reload_start_done); | 353 | init_completion(&dev->reload_start_done); |
386 | init_completion(&dev->resume_done); | 354 | init_completion(&dev->resume_done); |
355 | init_completion(&dev->gpio_configuration_done); | ||
356 | init_completion(&dev->gpio_set_level_done); | ||
357 | init_completion(&dev->gpio_get_level_done); | ||
358 | init_completion(&dev->ir_init_done); | ||
359 | |||
360 | /* Buffer management */ | ||
361 | init_waitqueue_head(&dev->buffer_mng_waitq); | ||
387 | 362 | ||
388 | /* alloc common buffer */ | 363 | /* alloc common buffer */ |
389 | dev->common_buffer_size = params->buffer_size * params->num_buffers; | 364 | dev->common_buffer_size = params->buffer_size * params->num_buffers; |
@@ -439,6 +414,71 @@ int smscore_register_device(struct smsdevice_params_t *params, | |||
439 | } | 414 | } |
440 | EXPORT_SYMBOL_GPL(smscore_register_device); | 415 | EXPORT_SYMBOL_GPL(smscore_register_device); |
441 | 416 | ||
417 | |||
418 | static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, | ||
419 | void *buffer, size_t size, struct completion *completion) { | ||
420 | int rc = coredev->sendrequest_handler(coredev->context, buffer, size); | ||
421 | if (rc < 0) { | ||
422 | sms_info("sendrequest returned error %d", rc); | ||
423 | return rc; | ||
424 | } | ||
425 | |||
426 | return wait_for_completion_timeout(completion, | ||
427 | msecs_to_jiffies(SMS_PROTOCOL_MAX_RAOUNDTRIP_MS)) ? | ||
428 | 0 : -ETIME; | ||
429 | } | ||
430 | |||
431 | /** | ||
432 | * Starts & enables IR operations | ||
433 | * | ||
434 | * @return 0 on success, < 0 on error. | ||
435 | */ | ||
436 | static int smscore_init_ir(struct smscore_device_t *coredev) | ||
437 | { | ||
438 | int ir_io; | ||
439 | int rc; | ||
440 | void *buffer; | ||
441 | |||
442 | coredev->ir.input_dev = NULL; | ||
443 | ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir; | ||
444 | if (ir_io) {/* only if IR port exist we use IR sub-module */ | ||
445 | sms_info("IR loading"); | ||
446 | rc = sms_ir_init(coredev); | ||
447 | |||
448 | if (rc != 0) | ||
449 | sms_err("Error initialization DTV IR sub-module"); | ||
450 | else { | ||
451 | buffer = kmalloc(sizeof(struct SmsMsgData_ST2) + | ||
452 | SMS_DMA_ALIGNMENT, | ||
453 | GFP_KERNEL | GFP_DMA); | ||
454 | if (buffer) { | ||
455 | struct SmsMsgData_ST2 *msg = | ||
456 | (struct SmsMsgData_ST2 *) | ||
457 | SMS_ALIGN_ADDRESS(buffer); | ||
458 | |||
459 | SMS_INIT_MSG(&msg->xMsgHeader, | ||
460 | MSG_SMS_START_IR_REQ, | ||
461 | sizeof(struct SmsMsgData_ST2)); | ||
462 | msg->msgData[0] = coredev->ir.controller; | ||
463 | msg->msgData[1] = coredev->ir.timeout; | ||
464 | |||
465 | smsendian_handle_tx_message( | ||
466 | (struct SmsMsgHdr_ST2 *)msg); | ||
467 | rc = smscore_sendrequest_and_wait(coredev, msg, | ||
468 | msg->xMsgHeader. msgLength, | ||
469 | &coredev->ir_init_done); | ||
470 | |||
471 | kfree(buffer); | ||
472 | } else | ||
473 | sms_err | ||
474 | ("Sending IR initialization message failed"); | ||
475 | } | ||
476 | } else | ||
477 | sms_info("IR port has not been detected"); | ||
478 | |||
479 | return 0; | ||
480 | } | ||
481 | |||
442 | /** | 482 | /** |
443 | * sets initial device mode and notifies client hotplugs that device is ready | 483 | * sets initial device mode and notifies client hotplugs that device is ready |
444 | * | 484 | * |
@@ -459,6 +499,7 @@ int smscore_start_device(struct smscore_device_t *coredev) | |||
459 | kmutex_lock(&g_smscore_deviceslock); | 499 | kmutex_lock(&g_smscore_deviceslock); |
460 | 500 | ||
461 | rc = smscore_notify_callbacks(coredev, coredev->device, 1); | 501 | rc = smscore_notify_callbacks(coredev, coredev->device, 1); |
502 | smscore_init_ir(coredev); | ||
462 | 503 | ||
463 | sms_info("device %p started, rc %d", coredev, rc); | 504 | sms_info("device %p started, rc %d", coredev, rc); |
464 | 505 | ||
@@ -468,29 +509,19 @@ int smscore_start_device(struct smscore_device_t *coredev) | |||
468 | } | 509 | } |
469 | EXPORT_SYMBOL_GPL(smscore_start_device); | 510 | EXPORT_SYMBOL_GPL(smscore_start_device); |
470 | 511 | ||
471 | static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, | ||
472 | void *buffer, size_t size, | ||
473 | struct completion *completion) | ||
474 | { | ||
475 | int rc = coredev->sendrequest_handler(coredev->context, buffer, size); | ||
476 | if (rc < 0) { | ||
477 | sms_info("sendrequest returned error %d", rc); | ||
478 | return rc; | ||
479 | } | ||
480 | |||
481 | return wait_for_completion_timeout(completion, | ||
482 | msecs_to_jiffies(10000)) ? | ||
483 | 0 : -ETIME; | ||
484 | } | ||
485 | 512 | ||
486 | static int smscore_load_firmware_family2(struct smscore_device_t *coredev, | 513 | static int smscore_load_firmware_family2(struct smscore_device_t *coredev, |
487 | void *buffer, size_t size) | 514 | void *buffer, size_t size) |
488 | { | 515 | { |
489 | struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer; | 516 | struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer; |
490 | struct SmsMsgHdr_ST *msg; | 517 | struct SmsMsgHdr_ST *msg; |
491 | u32 mem_address = firmware->StartAddress; | 518 | u32 mem_address; |
492 | u8 *payload = firmware->Payload; | 519 | u8 *payload = firmware->Payload; |
493 | int rc = 0; | 520 | int rc = 0; |
521 | firmware->StartAddress = le32_to_cpu(firmware->StartAddress); | ||
522 | firmware->Length = le32_to_cpu(firmware->Length); | ||
523 | |||
524 | mem_address = firmware->StartAddress; | ||
494 | 525 | ||
495 | sms_info("loading FW to addr 0x%x size %d", | 526 | sms_info("loading FW to addr 0x%x size %d", |
496 | mem_address, firmware->Length); | 527 | mem_address, firmware->Length); |
@@ -657,6 +688,9 @@ void smscore_unregister_device(struct smscore_device_t *coredev) | |||
657 | 688 | ||
658 | kmutex_lock(&g_smscore_deviceslock); | 689 | kmutex_lock(&g_smscore_deviceslock); |
659 | 690 | ||
691 | /* Release input device (IR) resources */ | ||
692 | sms_ir_exit(coredev); | ||
693 | |||
660 | smscore_notify_clients(coredev); | 694 | smscore_notify_clients(coredev); |
661 | smscore_notify_callbacks(coredev, NULL, 0); | 695 | smscore_notify_callbacks(coredev, NULL, 0); |
662 | 696 | ||
@@ -664,7 +698,9 @@ void smscore_unregister_device(struct smscore_device_t *coredev) | |||
664 | * onresponse must no longer be called */ | 698 | * onresponse must no longer be called */ |
665 | 699 | ||
666 | while (1) { | 700 | while (1) { |
667 | while ((cb = smscore_getbuffer(coredev))) { | 701 | while (!list_empty(&coredev->buffers)) { |
702 | cb = (struct smscore_buffer_t *) coredev->buffers.next; | ||
703 | list_del(&cb->entry); | ||
668 | kfree(cb); | 704 | kfree(cb); |
669 | num_buffers++; | 705 | num_buffers++; |
670 | } | 706 | } |
@@ -685,8 +721,10 @@ void smscore_unregister_device(struct smscore_device_t *coredev) | |||
685 | 721 | ||
686 | if (coredev->common_buffer) | 722 | if (coredev->common_buffer) |
687 | dma_free_coherent(NULL, coredev->common_buffer_size, | 723 | dma_free_coherent(NULL, coredev->common_buffer_size, |
688 | coredev->common_buffer, | 724 | coredev->common_buffer, coredev->common_buffer_phys); |
689 | coredev->common_buffer_phys); | 725 | |
726 | if (coredev->fw_buf != NULL) | ||
727 | kfree(coredev->fw_buf); | ||
690 | 728 | ||
691 | list_del(&coredev->entry); | 729 | list_del(&coredev->entry); |
692 | kfree(coredev); | 730 | kfree(coredev); |
@@ -746,7 +784,7 @@ static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = { | |||
746 | /*BDA*/ | 784 | /*BDA*/ |
747 | {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, | 785 | {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, |
748 | /*ISDBT*/ | 786 | /*ISDBT*/ |
749 | {"none", "isdbt_nova_12mhz.inp", "dvb_nova_12mhz.inp", "none"}, | 787 | {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, |
750 | /*ISDBTBDA*/ | 788 | /*ISDBTBDA*/ |
751 | {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, | 789 | {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, |
752 | /*CMMB*/ | 790 | /*CMMB*/ |
@@ -870,7 +908,7 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) | |||
870 | coredev->device_flags &= ~SMS_DEVICE_NOT_READY; | 908 | coredev->device_flags &= ~SMS_DEVICE_NOT_READY; |
871 | } | 909 | } |
872 | 910 | ||
873 | if (rc != 0) | 911 | if (rc < 0) |
874 | sms_err("return error code %d.", rc); | 912 | sms_err("return error code %d.", rc); |
875 | return rc; | 913 | return rc; |
876 | } | 914 | } |
@@ -940,14 +978,11 @@ smscore_client_t *smscore_find_client(struct smscore_device_t *coredev, | |||
940 | * | 978 | * |
941 | */ | 979 | */ |
942 | void smscore_onresponse(struct smscore_device_t *coredev, | 980 | void smscore_onresponse(struct smscore_device_t *coredev, |
943 | struct smscore_buffer_t *cb) | 981 | struct smscore_buffer_t *cb) { |
944 | { | 982 | struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) ((u8 *) cb->p |
945 | struct SmsMsgHdr_ST *phdr = | 983 | + cb->offset); |
946 | (struct SmsMsgHdr_ST *)((u8 *) cb->p + cb->offset); | 984 | struct smscore_client_t *client; |
947 | struct smscore_client_t *client = | ||
948 | smscore_find_client(coredev, phdr->msgType, phdr->msgDstId); | ||
949 | int rc = -EBUSY; | 985 | int rc = -EBUSY; |
950 | |||
951 | static unsigned long last_sample_time; /* = 0; */ | 986 | static unsigned long last_sample_time; /* = 0; */ |
952 | static int data_total; /* = 0; */ | 987 | static int data_total; /* = 0; */ |
953 | unsigned long time_now = jiffies_to_msecs(jiffies); | 988 | unsigned long time_now = jiffies_to_msecs(jiffies); |
@@ -965,6 +1000,16 @@ void smscore_onresponse(struct smscore_device_t *coredev, | |||
965 | } | 1000 | } |
966 | 1001 | ||
967 | data_total += cb->size; | 1002 | data_total += cb->size; |
1003 | /* Do we need to re-route? */ | ||
1004 | if ((phdr->msgType == MSG_SMS_HO_PER_SLICES_IND) || | ||
1005 | (phdr->msgType == MSG_SMS_TRANSMISSION_IND)) { | ||
1006 | if (coredev->mode == DEVICE_MODE_DVBT_BDA) | ||
1007 | phdr->msgDstId = DVBT_BDA_CONTROL_MSG_ID; | ||
1008 | } | ||
1009 | |||
1010 | |||
1011 | client = smscore_find_client(coredev, phdr->msgType, phdr->msgDstId); | ||
1012 | |||
968 | /* If no client registered for type & id, | 1013 | /* If no client registered for type & id, |
969 | * check for control client where type is not registered */ | 1014 | * check for control client where type is not registered */ |
970 | if (client) | 1015 | if (client) |
@@ -1009,6 +1054,35 @@ void smscore_onresponse(struct smscore_device_t *coredev, | |||
1009 | case MSG_SMS_SLEEP_RESUME_COMP_IND: | 1054 | case MSG_SMS_SLEEP_RESUME_COMP_IND: |
1010 | complete(&coredev->resume_done); | 1055 | complete(&coredev->resume_done); |
1011 | break; | 1056 | break; |
1057 | case MSG_SMS_GPIO_CONFIG_EX_RES: | ||
1058 | sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES"); | ||
1059 | complete(&coredev->gpio_configuration_done); | ||
1060 | break; | ||
1061 | case MSG_SMS_GPIO_SET_LEVEL_RES: | ||
1062 | sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES"); | ||
1063 | complete(&coredev->gpio_set_level_done); | ||
1064 | break; | ||
1065 | case MSG_SMS_GPIO_GET_LEVEL_RES: | ||
1066 | { | ||
1067 | u32 *msgdata = (u32 *) phdr; | ||
1068 | coredev->gpio_get_res = msgdata[1]; | ||
1069 | sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d", | ||
1070 | coredev->gpio_get_res); | ||
1071 | complete(&coredev->gpio_get_level_done); | ||
1072 | break; | ||
1073 | } | ||
1074 | case MSG_SMS_START_IR_RES: | ||
1075 | complete(&coredev->ir_init_done); | ||
1076 | break; | ||
1077 | case MSG_SMS_IR_SAMPLES_IND: | ||
1078 | sms_ir_event(coredev, | ||
1079 | (const char *) | ||
1080 | ((char *)phdr | ||
1081 | + sizeof(struct SmsMsgHdr_ST)), | ||
1082 | (int)phdr->msgLength | ||
1083 | - sizeof(struct SmsMsgHdr_ST)); | ||
1084 | break; | ||
1085 | |||
1012 | default: | 1086 | default: |
1013 | break; | 1087 | break; |
1014 | } | 1088 | } |
@@ -1030,12 +1104,24 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) | |||
1030 | struct smscore_buffer_t *cb = NULL; | 1104 | struct smscore_buffer_t *cb = NULL; |
1031 | unsigned long flags; | 1105 | unsigned long flags; |
1032 | 1106 | ||
1107 | DEFINE_WAIT(wait); | ||
1108 | |||
1033 | spin_lock_irqsave(&coredev->bufferslock, flags); | 1109 | spin_lock_irqsave(&coredev->bufferslock, flags); |
1034 | 1110 | ||
1035 | if (!list_empty(&coredev->buffers)) { | 1111 | /* This function must return a valid buffer, since the buffer list is |
1036 | cb = (struct smscore_buffer_t *) coredev->buffers.next; | 1112 | * finite, we check that there is an available buffer, if not, we wait |
1037 | list_del(&cb->entry); | 1113 | * until such buffer become available. |
1038 | } | 1114 | */ |
1115 | |||
1116 | prepare_to_wait(&coredev->buffer_mng_waitq, &wait, TASK_INTERRUPTIBLE); | ||
1117 | |||
1118 | if (list_empty(&coredev->buffers)) | ||
1119 | schedule(); | ||
1120 | |||
1121 | finish_wait(&coredev->buffer_mng_waitq, &wait); | ||
1122 | |||
1123 | cb = (struct smscore_buffer_t *) coredev->buffers.next; | ||
1124 | list_del(&cb->entry); | ||
1039 | 1125 | ||
1040 | spin_unlock_irqrestore(&coredev->bufferslock, flags); | 1126 | spin_unlock_irqrestore(&coredev->bufferslock, flags); |
1041 | 1127 | ||
@@ -1052,8 +1138,8 @@ EXPORT_SYMBOL_GPL(smscore_getbuffer); | |||
1052 | * | 1138 | * |
1053 | */ | 1139 | */ |
1054 | void smscore_putbuffer(struct smscore_device_t *coredev, | 1140 | void smscore_putbuffer(struct smscore_device_t *coredev, |
1055 | struct smscore_buffer_t *cb) | 1141 | struct smscore_buffer_t *cb) { |
1056 | { | 1142 | wake_up_interruptible(&coredev->buffer_mng_waitq); |
1057 | list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock); | 1143 | list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock); |
1058 | } | 1144 | } |
1059 | EXPORT_SYMBOL_GPL(smscore_putbuffer); | 1145 | EXPORT_SYMBOL_GPL(smscore_putbuffer); |
@@ -1210,8 +1296,9 @@ int smsclient_sendrequest(struct smscore_client_t *client, | |||
1210 | EXPORT_SYMBOL_GPL(smsclient_sendrequest); | 1296 | EXPORT_SYMBOL_GPL(smsclient_sendrequest); |
1211 | 1297 | ||
1212 | 1298 | ||
1299 | /* old GPIO managments implementation */ | ||
1213 | int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin, | 1300 | int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin, |
1214 | struct smscore_gpio_config *pinconfig) | 1301 | struct smscore_config_gpio *pinconfig) |
1215 | { | 1302 | { |
1216 | struct { | 1303 | struct { |
1217 | struct SmsMsgHdr_ST hdr; | 1304 | struct SmsMsgHdr_ST hdr; |
@@ -1280,35 +1367,254 @@ int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level) | |||
1280 | &msg, sizeof(msg)); | 1367 | &msg, sizeof(msg)); |
1281 | } | 1368 | } |
1282 | 1369 | ||
1283 | static int __init smscore_module_init(void) | 1370 | /* new GPIO managment implementation */ |
1284 | { | 1371 | static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum, |
1285 | int rc = 0; | 1372 | u32 *pGroupNum, u32 *pGroupCfg) { |
1373 | |||
1374 | *pGroupCfg = 1; | ||
1375 | |||
1376 | if (PinNum >= 0 && PinNum <= 1) { | ||
1377 | *pTranslatedPinNum = 0; | ||
1378 | *pGroupNum = 9; | ||
1379 | *pGroupCfg = 2; | ||
1380 | } else if (PinNum >= 2 && PinNum <= 6) { | ||
1381 | *pTranslatedPinNum = 2; | ||
1382 | *pGroupNum = 0; | ||
1383 | *pGroupCfg = 2; | ||
1384 | } else if (PinNum >= 7 && PinNum <= 11) { | ||
1385 | *pTranslatedPinNum = 7; | ||
1386 | *pGroupNum = 1; | ||
1387 | } else if (PinNum >= 12 && PinNum <= 15) { | ||
1388 | *pTranslatedPinNum = 12; | ||
1389 | *pGroupNum = 2; | ||
1390 | *pGroupCfg = 3; | ||
1391 | } else if (PinNum == 16) { | ||
1392 | *pTranslatedPinNum = 16; | ||
1393 | *pGroupNum = 23; | ||
1394 | } else if (PinNum >= 17 && PinNum <= 24) { | ||
1395 | *pTranslatedPinNum = 17; | ||
1396 | *pGroupNum = 3; | ||
1397 | } else if (PinNum == 25) { | ||
1398 | *pTranslatedPinNum = 25; | ||
1399 | *pGroupNum = 6; | ||
1400 | } else if (PinNum >= 26 && PinNum <= 28) { | ||
1401 | *pTranslatedPinNum = 26; | ||
1402 | *pGroupNum = 4; | ||
1403 | } else if (PinNum == 29) { | ||
1404 | *pTranslatedPinNum = 29; | ||
1405 | *pGroupNum = 5; | ||
1406 | *pGroupCfg = 2; | ||
1407 | } else if (PinNum == 30) { | ||
1408 | *pTranslatedPinNum = 30; | ||
1409 | *pGroupNum = 8; | ||
1410 | } else if (PinNum == 31) { | ||
1411 | *pTranslatedPinNum = 31; | ||
1412 | *pGroupNum = 17; | ||
1413 | } else | ||
1414 | return -1; | ||
1286 | 1415 | ||
1287 | INIT_LIST_HEAD(&g_smscore_notifyees); | 1416 | *pGroupCfg <<= 24; |
1288 | INIT_LIST_HEAD(&g_smscore_devices); | ||
1289 | kmutex_init(&g_smscore_deviceslock); | ||
1290 | 1417 | ||
1291 | INIT_LIST_HEAD(&g_smscore_registry); | 1418 | return 0; |
1292 | kmutex_init(&g_smscore_registrylock); | 1419 | } |
1420 | |||
1421 | int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, | ||
1422 | struct smscore_gpio_config *pGpioConfig) { | ||
1423 | |||
1424 | u32 totalLen; | ||
1425 | u32 TranslatedPinNum; | ||
1426 | u32 GroupNum; | ||
1427 | u32 ElectricChar; | ||
1428 | u32 groupCfg; | ||
1429 | void *buffer; | ||
1430 | int rc; | ||
1431 | |||
1432 | struct SetGpioMsg { | ||
1433 | struct SmsMsgHdr_ST xMsgHeader; | ||
1434 | u32 msgData[6]; | ||
1435 | } *pMsg; | ||
1436 | |||
1437 | |||
1438 | if (PinNum > MAX_GPIO_PIN_NUMBER) | ||
1439 | return -EINVAL; | ||
1440 | |||
1441 | if (pGpioConfig == NULL) | ||
1442 | return -EINVAL; | ||
1443 | |||
1444 | totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6); | ||
1445 | |||
1446 | buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, | ||
1447 | GFP_KERNEL | GFP_DMA); | ||
1448 | if (!buffer) | ||
1449 | return -ENOMEM; | ||
1450 | |||
1451 | pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); | ||
1452 | |||
1453 | pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
1454 | pMsg->xMsgHeader.msgDstId = HIF_TASK; | ||
1455 | pMsg->xMsgHeader.msgFlags = 0; | ||
1456 | pMsg->xMsgHeader.msgLength = (u16) totalLen; | ||
1457 | pMsg->msgData[0] = PinNum; | ||
1458 | |||
1459 | if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) { | ||
1460 | pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ; | ||
1461 | if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum, | ||
1462 | &groupCfg) != 0) | ||
1463 | return -EINVAL; | ||
1464 | |||
1465 | pMsg->msgData[1] = TranslatedPinNum; | ||
1466 | pMsg->msgData[2] = GroupNum; | ||
1467 | ElectricChar = (pGpioConfig->PullUpDown) | ||
1468 | | (pGpioConfig->InputCharacteristics << 2) | ||
1469 | | (pGpioConfig->OutputSlewRate << 3) | ||
1470 | | (pGpioConfig->OutputDriving << 4); | ||
1471 | pMsg->msgData[3] = ElectricChar; | ||
1472 | pMsg->msgData[4] = pGpioConfig->Direction; | ||
1473 | pMsg->msgData[5] = groupCfg; | ||
1474 | } else { | ||
1475 | pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ; | ||
1476 | pMsg->msgData[1] = pGpioConfig->PullUpDown; | ||
1477 | pMsg->msgData[2] = pGpioConfig->OutputSlewRate; | ||
1478 | pMsg->msgData[3] = pGpioConfig->OutputDriving; | ||
1479 | pMsg->msgData[4] = pGpioConfig->Direction; | ||
1480 | pMsg->msgData[5] = 0; | ||
1481 | } | ||
1482 | |||
1483 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); | ||
1484 | rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, | ||
1485 | &coredev->gpio_configuration_done); | ||
1486 | |||
1487 | if (rc != 0) { | ||
1488 | if (rc == -ETIME) | ||
1489 | sms_err("smscore_gpio_configure timeout"); | ||
1490 | else | ||
1491 | sms_err("smscore_gpio_configure error"); | ||
1492 | } | ||
1493 | kfree(buffer); | ||
1494 | |||
1495 | return rc; | ||
1496 | } | ||
1497 | |||
1498 | int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum, | ||
1499 | u8 NewLevel) { | ||
1500 | |||
1501 | u32 totalLen; | ||
1502 | int rc; | ||
1503 | void *buffer; | ||
1504 | |||
1505 | struct SetGpioMsg { | ||
1506 | struct SmsMsgHdr_ST xMsgHeader; | ||
1507 | u32 msgData[3]; /* keep it 3 ! */ | ||
1508 | } *pMsg; | ||
1509 | |||
1510 | if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER) || | ||
1511 | (PinNum > MAX_GPIO_PIN_NUMBER)) | ||
1512 | return -EINVAL; | ||
1293 | 1513 | ||
1514 | totalLen = sizeof(struct SmsMsgHdr_ST) + | ||
1515 | (3 * sizeof(u32)); /* keep it 3 ! */ | ||
1294 | 1516 | ||
1517 | buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, | ||
1518 | GFP_KERNEL | GFP_DMA); | ||
1519 | if (!buffer) | ||
1520 | return -ENOMEM; | ||
1295 | 1521 | ||
1522 | pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); | ||
1296 | 1523 | ||
1524 | pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
1525 | pMsg->xMsgHeader.msgDstId = HIF_TASK; | ||
1526 | pMsg->xMsgHeader.msgFlags = 0; | ||
1527 | pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ; | ||
1528 | pMsg->xMsgHeader.msgLength = (u16) totalLen; | ||
1529 | pMsg->msgData[0] = PinNum; | ||
1530 | pMsg->msgData[1] = NewLevel; | ||
1297 | 1531 | ||
1532 | /* Send message to SMS */ | ||
1533 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); | ||
1534 | rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, | ||
1535 | &coredev->gpio_set_level_done); | ||
1536 | |||
1537 | if (rc != 0) { | ||
1538 | if (rc == -ETIME) | ||
1539 | sms_err("smscore_gpio_set_level timeout"); | ||
1540 | else | ||
1541 | sms_err("smscore_gpio_set_level error"); | ||
1542 | } | ||
1543 | kfree(buffer); | ||
1298 | 1544 | ||
1299 | return rc; | 1545 | return rc; |
1300 | sms_debug("rc %d", rc); | 1546 | } |
1547 | |||
1548 | int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum, | ||
1549 | u8 *level) { | ||
1550 | |||
1551 | u32 totalLen; | ||
1552 | int rc; | ||
1553 | void *buffer; | ||
1554 | |||
1555 | struct SetGpioMsg { | ||
1556 | struct SmsMsgHdr_ST xMsgHeader; | ||
1557 | u32 msgData[2]; | ||
1558 | } *pMsg; | ||
1559 | |||
1560 | |||
1561 | if (PinNum > MAX_GPIO_PIN_NUMBER) | ||
1562 | return -EINVAL; | ||
1563 | |||
1564 | totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32)); | ||
1565 | |||
1566 | buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, | ||
1567 | GFP_KERNEL | GFP_DMA); | ||
1568 | if (!buffer) | ||
1569 | return -ENOMEM; | ||
1570 | |||
1571 | pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); | ||
1572 | |||
1573 | pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
1574 | pMsg->xMsgHeader.msgDstId = HIF_TASK; | ||
1575 | pMsg->xMsgHeader.msgFlags = 0; | ||
1576 | pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ; | ||
1577 | pMsg->xMsgHeader.msgLength = (u16) totalLen; | ||
1578 | pMsg->msgData[0] = PinNum; | ||
1579 | pMsg->msgData[1] = 0; | ||
1580 | |||
1581 | /* Send message to SMS */ | ||
1582 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); | ||
1583 | rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, | ||
1584 | &coredev->gpio_get_level_done); | ||
1585 | |||
1586 | if (rc != 0) { | ||
1587 | if (rc == -ETIME) | ||
1588 | sms_err("smscore_gpio_get_level timeout"); | ||
1589 | else | ||
1590 | sms_err("smscore_gpio_get_level error"); | ||
1591 | } | ||
1592 | kfree(buffer); | ||
1593 | |||
1594 | /* Its a race between other gpio_get_level() and the copy of the single | ||
1595 | * global 'coredev->gpio_get_res' to the function's variable 'level' | ||
1596 | */ | ||
1597 | *level = coredev->gpio_get_res; | ||
1301 | 1598 | ||
1302 | return rc; | 1599 | return rc; |
1303 | } | 1600 | } |
1304 | 1601 | ||
1305 | static void __exit smscore_module_exit(void) | 1602 | static int __init smscore_module_init(void) |
1306 | { | 1603 | { |
1604 | int rc = 0; | ||
1307 | 1605 | ||
1606 | INIT_LIST_HEAD(&g_smscore_notifyees); | ||
1607 | INIT_LIST_HEAD(&g_smscore_devices); | ||
1608 | kmutex_init(&g_smscore_deviceslock); | ||
1308 | 1609 | ||
1610 | INIT_LIST_HEAD(&g_smscore_registry); | ||
1611 | kmutex_init(&g_smscore_registrylock); | ||
1309 | 1612 | ||
1613 | return rc; | ||
1614 | } | ||
1310 | 1615 | ||
1311 | 1616 | static void __exit smscore_module_exit(void) | |
1617 | { | ||
1312 | kmutex_lock(&g_smscore_deviceslock); | 1618 | kmutex_lock(&g_smscore_deviceslock); |
1313 | while (!list_empty(&g_smscore_notifyees)) { | 1619 | while (!list_empty(&g_smscore_notifyees)) { |
1314 | struct smscore_device_notifyee_t *notifyee = | 1620 | struct smscore_device_notifyee_t *notifyee = |
diff --git a/drivers/media/dvb/siano/smscoreapi.h b/drivers/media/dvb/siano/smscoreapi.h index 548de9056e8b..f1108c64e895 100644 --- a/drivers/media/dvb/siano/smscoreapi.h +++ b/drivers/media/dvb/siano/smscoreapi.h | |||
@@ -1,26 +1,26 @@ | |||
1 | /* | 1 | /**************************************************************** |
2 | * Driver for the Siano SMS1xxx USB dongle | 2 | |
3 | * | 3 | Siano Mobile Silicon, Inc. |
4 | * author: Anatoly Greenblat | 4 | MDTV receiver kernel modules. |
5 | * | 5 | Copyright (C) 2006-2008, Uri Shkolnik, Anatoly Greenblat |
6 | * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. | 6 | |
7 | * | 7 | This program is free software: you can redistribute it and/or modify |
8 | * This program is free software; you can redistribute it and/or modify | 8 | it under the terms of the GNU General Public License as published by |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | the Free Software Foundation, either version 2 of the License, or |
10 | * published by the Free Software Foundation; | 10 | (at your option) any later version. |
11 | * | 11 | |
12 | * Software distributed under the License is distributed on an "AS IS" | 12 | This program is distributed in the hope that it will be useful, |
13 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. | 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * | 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * See the GNU General Public License for more details. | 15 | GNU General Public License for more details. |
16 | * | 16 | |
17 | * You should have received a copy of the GNU General Public License | 17 | You should have received a copy of the GNU General Public License |
18 | * along with this program; if not, write to the Free Software | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | |
20 | */ | 20 | ****************************************************************/ |
21 | 21 | ||
22 | #ifndef __smscoreapi_h__ | 22 | #ifndef __SMS_CORE_API_H__ |
23 | #define __smscoreapi_h__ | 23 | #define __SMS_CORE_API_H__ |
24 | 24 | ||
25 | #include <linux/version.h> | 25 | #include <linux/version.h> |
26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
@@ -28,14 +28,13 @@ | |||
28 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
29 | #include <linux/scatterlist.h> | 29 | #include <linux/scatterlist.h> |
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <asm/page.h> | ||
32 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
32 | #include <linux/wait.h> | ||
33 | #include <linux/timer.h> | ||
33 | 34 | ||
34 | #include "dmxdev.h" | 35 | #include <asm/page.h> |
35 | #include "dvbdev.h" | ||
36 | #include "dvb_demux.h" | ||
37 | #include "dvb_frontend.h" | ||
38 | 36 | ||
37 | #include "smsir.h" | ||
39 | 38 | ||
40 | #define kmutex_init(_p_) mutex_init(_p_) | 39 | #define kmutex_init(_p_) mutex_init(_p_) |
41 | #define kmutex_lock(_p_) mutex_lock(_p_) | 40 | #define kmutex_lock(_p_) mutex_lock(_p_) |
@@ -46,13 +45,14 @@ | |||
46 | #define min(a, b) (((a) < (b)) ? (a) : (b)) | 45 | #define min(a, b) (((a) < (b)) ? (a) : (b)) |
47 | #endif | 46 | #endif |
48 | 47 | ||
49 | #define SMS_ALLOC_ALIGNMENT 128 | 48 | #define SMS_PROTOCOL_MAX_RAOUNDTRIP_MS (10000) |
50 | #define SMS_DMA_ALIGNMENT 16 | 49 | #define SMS_ALLOC_ALIGNMENT 128 |
50 | #define SMS_DMA_ALIGNMENT 16 | ||
51 | #define SMS_ALIGN_ADDRESS(addr) \ | 51 | #define SMS_ALIGN_ADDRESS(addr) \ |
52 | ((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1)) | 52 | ((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1)) |
53 | 53 | ||
54 | #define SMS_DEVICE_FAMILY2 1 | 54 | #define SMS_DEVICE_FAMILY2 1 |
55 | #define SMS_ROM_NO_RESPONSE 2 | 55 | #define SMS_ROM_NO_RESPONSE 2 |
56 | #define SMS_DEVICE_NOT_READY 0x8000000 | 56 | #define SMS_DEVICE_NOT_READY 0x8000000 |
57 | 57 | ||
58 | enum sms_device_type_st { | 58 | enum sms_device_type_st { |
@@ -83,13 +83,13 @@ typedef void (*onremove_t)(void *context); | |||
83 | struct smscore_buffer_t { | 83 | struct smscore_buffer_t { |
84 | /* public members, once passed to clients can be changed freely */ | 84 | /* public members, once passed to clients can be changed freely */ |
85 | struct list_head entry; | 85 | struct list_head entry; |
86 | int size; | 86 | int size; |
87 | int offset; | 87 | int offset; |
88 | 88 | ||
89 | /* private members, read-only for clients */ | 89 | /* private members, read-only for clients */ |
90 | void *p; | 90 | void *p; |
91 | dma_addr_t phys; | 91 | dma_addr_t phys; |
92 | unsigned long offset_in_common; | 92 | unsigned long offset_in_common; |
93 | }; | 93 | }; |
94 | 94 | ||
95 | struct smsdevice_params_t { | 95 | struct smsdevice_params_t { |
@@ -116,10 +116,63 @@ struct smsclient_params_t { | |||
116 | int data_type; | 116 | int data_type; |
117 | onresponse_t onresponse_handler; | 117 | onresponse_t onresponse_handler; |
118 | onremove_t onremove_handler; | 118 | onremove_t onremove_handler; |
119 | |||
120 | void *context; | 119 | void *context; |
121 | }; | 120 | }; |
122 | 121 | ||
122 | struct smscore_device_t { | ||
123 | struct list_head entry; | ||
124 | |||
125 | struct list_head clients; | ||
126 | struct list_head subclients; | ||
127 | spinlock_t clientslock; | ||
128 | |||
129 | struct list_head buffers; | ||
130 | spinlock_t bufferslock; | ||
131 | int num_buffers; | ||
132 | |||
133 | void *common_buffer; | ||
134 | int common_buffer_size; | ||
135 | dma_addr_t common_buffer_phys; | ||
136 | |||
137 | void *context; | ||
138 | struct device *device; | ||
139 | |||
140 | char devpath[32]; | ||
141 | unsigned long device_flags; | ||
142 | |||
143 | setmode_t setmode_handler; | ||
144 | detectmode_t detectmode_handler; | ||
145 | sendrequest_t sendrequest_handler; | ||
146 | preload_t preload_handler; | ||
147 | postload_t postload_handler; | ||
148 | |||
149 | int mode, modes_supported; | ||
150 | |||
151 | /* host <--> device messages */ | ||
152 | struct completion version_ex_done, data_download_done, trigger_done; | ||
153 | struct completion init_device_done, reload_start_done, resume_done; | ||
154 | struct completion gpio_configuration_done, gpio_set_level_done; | ||
155 | struct completion gpio_get_level_done, ir_init_done; | ||
156 | |||
157 | /* Buffer management */ | ||
158 | wait_queue_head_t buffer_mng_waitq; | ||
159 | |||
160 | /* GPIO */ | ||
161 | int gpio_get_res; | ||
162 | |||
163 | /* Target hardware board */ | ||
164 | int board_id; | ||
165 | |||
166 | /* Firmware */ | ||
167 | u8 *fw_buf; | ||
168 | u32 fw_buf_size; | ||
169 | |||
170 | /* Infrared (IR) */ | ||
171 | struct ir_t ir; | ||
172 | |||
173 | int led_state; | ||
174 | }; | ||
175 | |||
123 | /* GPIO definitions for antenna frequency domain control (SMS8021) */ | 176 | /* GPIO definitions for antenna frequency domain control (SMS8021) */ |
124 | #define SMS_ANTENNA_GPIO_0 1 | 177 | #define SMS_ANTENNA_GPIO_0 1 |
125 | #define SMS_ANTENNA_GPIO_1 0 | 178 | #define SMS_ANTENNA_GPIO_1 0 |
@@ -154,18 +207,15 @@ struct smsclient_params_t { | |||
154 | #define MSG_SMS_INIT_DEVICE_RES 579 | 207 | #define MSG_SMS_INIT_DEVICE_RES 579 |
155 | #define MSG_SMS_ADD_PID_FILTER_REQ 601 | 208 | #define MSG_SMS_ADD_PID_FILTER_REQ 601 |
156 | #define MSG_SMS_ADD_PID_FILTER_RES 602 | 209 | #define MSG_SMS_ADD_PID_FILTER_RES 602 |
157 | #define MSG_SMS_REMOVE_PID_FILTER_REQ 603 | 210 | #define MSG_SMS_REMOVE_PID_FILTER_REQ 603 |
158 | #define MSG_SMS_REMOVE_PID_FILTER_RES 604 | 211 | #define MSG_SMS_REMOVE_PID_FILTER_RES 604 |
159 | #define MSG_SMS_DAB_CHANNEL 607 | 212 | #define MSG_SMS_DAB_CHANNEL 607 |
160 | #define MSG_SMS_GET_PID_FILTER_LIST_REQ 608 | 213 | #define MSG_SMS_GET_PID_FILTER_LIST_REQ 608 |
161 | #define MSG_SMS_GET_PID_FILTER_LIST_RES 609 | 214 | #define MSG_SMS_GET_PID_FILTER_LIST_RES 609 |
162 | #define MSG_SMS_GET_STATISTICS_REQ 615 | 215 | #define MSG_SMS_HO_PER_SLICES_IND 630 |
163 | #define MSG_SMS_GET_STATISTICS_RES 616 | 216 | #define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651 |
164 | #define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651 | 217 | #define MSG_SMS_SET_ANTENNA_CONFIG_RES 652 |
165 | #define MSG_SMS_SET_ANTENNA_CONFIG_RES 652 | 218 | #define MSG_SMS_SLEEP_RESUME_COMP_IND 655 |
166 | #define MSG_SMS_GET_STATISTICS_EX_REQ 653 | ||
167 | #define MSG_SMS_GET_STATISTICS_EX_RES 654 | ||
168 | #define MSG_SMS_SLEEP_RESUME_COMP_IND 655 | ||
169 | #define MSG_SMS_DATA_DOWNLOAD_REQ 660 | 219 | #define MSG_SMS_DATA_DOWNLOAD_REQ 660 |
170 | #define MSG_SMS_DATA_DOWNLOAD_RES 661 | 220 | #define MSG_SMS_DATA_DOWNLOAD_RES 661 |
171 | #define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ 664 | 221 | #define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ 664 |
@@ -190,14 +240,31 @@ struct smsclient_params_t { | |||
190 | #define MSG_SMS_GPIO_CONFIG_EX_RES 713 | 240 | #define MSG_SMS_GPIO_CONFIG_EX_RES 713 |
191 | #define MSG_SMS_ISDBT_TUNE_REQ 776 | 241 | #define MSG_SMS_ISDBT_TUNE_REQ 776 |
192 | #define MSG_SMS_ISDBT_TUNE_RES 777 | 242 | #define MSG_SMS_ISDBT_TUNE_RES 777 |
243 | #define MSG_SMS_TRANSMISSION_IND 782 | ||
244 | #define MSG_SMS_START_IR_REQ 800 | ||
245 | #define MSG_SMS_START_IR_RES 801 | ||
246 | #define MSG_SMS_IR_SAMPLES_IND 802 | ||
247 | #define MSG_SMS_SIGNAL_DETECTED_IND 827 | ||
248 | #define MSG_SMS_NO_SIGNAL_IND 828 | ||
193 | 249 | ||
194 | #define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \ | 250 | #define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \ |
195 | (ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \ | 251 | (ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \ |
196 | (ptr)->msgLength = len; (ptr)->msgFlags = 0; \ | 252 | (ptr)->msgLength = len; (ptr)->msgFlags = 0; \ |
197 | } while (0) | 253 | } while (0) |
254 | |||
198 | #define SMS_INIT_MSG(ptr, type, len) \ | 255 | #define SMS_INIT_MSG(ptr, type, len) \ |
199 | SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len) | 256 | SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len) |
200 | 257 | ||
258 | enum SMS_DVB3_EVENTS { | ||
259 | DVB3_EVENT_INIT = 0, | ||
260 | DVB3_EVENT_SLEEP, | ||
261 | DVB3_EVENT_HOTPLUG, | ||
262 | DVB3_EVENT_FE_LOCK, | ||
263 | DVB3_EVENT_FE_UNLOCK, | ||
264 | DVB3_EVENT_UNC_OK, | ||
265 | DVB3_EVENT_UNC_ERR | ||
266 | }; | ||
267 | |||
201 | enum SMS_DEVICE_MODE { | 268 | enum SMS_DEVICE_MODE { |
202 | DEVICE_MODE_NONE = -1, | 269 | DEVICE_MODE_NONE = -1, |
203 | DEVICE_MODE_DVBT = 0, | 270 | DEVICE_MODE_DVBT = 0, |
@@ -221,8 +288,13 @@ struct SmsMsgHdr_ST { | |||
221 | }; | 288 | }; |
222 | 289 | ||
223 | struct SmsMsgData_ST { | 290 | struct SmsMsgData_ST { |
224 | struct SmsMsgHdr_ST xMsgHeader; | 291 | struct SmsMsgHdr_ST xMsgHeader; |
225 | u32 msgData[1]; | 292 | u32 msgData[1]; |
293 | }; | ||
294 | |||
295 | struct SmsMsgData_ST2 { | ||
296 | struct SmsMsgHdr_ST xMsgHeader; | ||
297 | u32 msgData[2]; | ||
226 | }; | 298 | }; |
227 | 299 | ||
228 | struct SmsDataDownload_ST { | 300 | struct SmsDataDownload_ST { |
@@ -238,11 +310,12 @@ struct SmsVersionRes_ST { | |||
238 | u8 Step; /* 0 - Step A */ | 310 | u8 Step; /* 0 - Step A */ |
239 | u8 MetalFix; /* 0 - Metal 0 */ | 311 | u8 MetalFix; /* 0 - Metal 0 */ |
240 | 312 | ||
241 | u8 FirmwareId; /* 0xFF � ROM, otherwise the | 313 | /* FirmwareId 0xFF if ROM, otherwise the |
242 | * value indicated by | 314 | * value indicated by SMSHOSTLIB_DEVICE_MODES_E */ |
243 | * SMSHOSTLIB_DEVICE_MODES_E */ | 315 | u8 FirmwareId; |
244 | u8 SupportedProtocols; /* Bitwise OR combination of | 316 | /* SupportedProtocols Bitwise OR combination of |
245 | * supported protocols */ | 317 | * supported protocols */ |
318 | u8 SupportedProtocols; | ||
246 | 319 | ||
247 | u8 VersionMajor; | 320 | u8 VersionMajor; |
248 | u8 VersionMinor; | 321 | u8 VersionMinor; |
@@ -264,86 +337,219 @@ struct SmsFirmware_ST { | |||
264 | u8 Payload[1]; | 337 | u8 Payload[1]; |
265 | }; | 338 | }; |
266 | 339 | ||
267 | struct SMSHOSTLIB_STATISTICS_ST { | 340 | /* Statistics information returned as response for |
268 | u32 Reserved; /* Reserved */ | 341 | * SmsHostApiGetStatistics_Req */ |
342 | struct SMSHOSTLIB_STATISTICS_S { | ||
343 | u32 Reserved; /* Reserved */ | ||
269 | 344 | ||
270 | /* Common parameters */ | 345 | /* Common parameters */ |
271 | u32 IsRfLocked; /* 0 - not locked, 1 - locked */ | 346 | u32 IsRfLocked; /* 0 - not locked, 1 - locked */ |
272 | u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ | 347 | u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ |
273 | u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ | 348 | u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ |
274 | 349 | ||
275 | /* Reception quality */ | 350 | /* Reception quality */ |
276 | s32 SNR; /* dB */ | 351 | s32 SNR; /* dB */ |
277 | u32 BER; /* Post Viterbi BER [1E-5] */ | 352 | u32 BER; /* Post Viterbi BER [1E-5] */ |
278 | u32 FIB_CRC; /* CRC errors percentage, valid only for DAB */ | 353 | u32 FIB_CRC; /* CRC errors percentage, valid only for DAB */ |
279 | u32 TS_PER; /* Transport stream PER, 0xFFFFFFFF indicate N/A, | 354 | u32 TS_PER; /* Transport stream PER, |
280 | * valid only for DVB-T/H */ | 355 | 0xFFFFFFFF indicate N/A, valid only for DVB-T/H */ |
281 | u32 MFER; /* DVB-H frame error rate in percentage, | 356 | u32 MFER; /* DVB-H frame error rate in percentage, |
282 | * 0xFFFFFFFF indicate N/A, valid only for DVB-H */ | 357 | 0xFFFFFFFF indicate N/A, valid only for DVB-H */ |
283 | s32 RSSI; /* dBm */ | 358 | s32 RSSI; /* dBm */ |
284 | s32 InBandPwr; /* In band power in dBM */ | 359 | s32 InBandPwr; /* In band power in dBM */ |
285 | s32 CarrierOffset; /* Carrier Offset in bin/1024 */ | 360 | s32 CarrierOffset; /* Carrier Offset in bin/1024 */ |
286 | 361 | ||
287 | /* Transmission parameters, valid only for DVB-T/H */ | 362 | /* Transmission parameters */ |
288 | u32 Frequency; /* Frequency in Hz */ | 363 | u32 Frequency; /* Frequency in Hz */ |
289 | u32 Bandwidth; /* Bandwidth in MHz */ | 364 | u32 Bandwidth; /* Bandwidth in MHz, valid only for DVB-T/H */ |
290 | u32 TransmissionMode; /* Transmission Mode, for DAB modes 1-4, | 365 | u32 TransmissionMode; /* Transmission Mode, for DAB modes 1-4, |
291 | * for DVB-T/H FFT mode carriers in Kilos */ | 366 | for DVB-T/H FFT mode carriers in Kilos */ |
292 | u32 ModemState; /* from SMS_DvbModemState_ET */ | 367 | u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET, |
293 | u32 GuardInterval; /* Guard Interval, 1 divided by value */ | 368 | valid only for DVB-T/H */ |
294 | u32 CodeRate; /* Code Rate from SMS_DvbModemState_ET */ | 369 | u32 GuardInterval; /* Guard Interval from |
295 | u32 LPCodeRate; /* Low Priority Code Rate from SMS_DvbModemState_ET */ | 370 | SMSHOSTLIB_GUARD_INTERVALS_ET, valid only for DVB-T/H */ |
296 | u32 Hierarchy; /* Hierarchy from SMS_Hierarchy_ET */ | 371 | u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET, |
297 | u32 Constellation; /* Constellation from SMS_Constellation_ET */ | 372 | valid only for DVB-T/H */ |
373 | u32 LPCodeRate; /* Low Priority Code Rate from | ||
374 | SMSHOSTLIB_CODE_RATE_ET, valid only for DVB-T/H */ | ||
375 | u32 Hierarchy; /* Hierarchy from SMSHOSTLIB_HIERARCHY_ET, | ||
376 | valid only for DVB-T/H */ | ||
377 | u32 Constellation; /* Constellation from | ||
378 | SMSHOSTLIB_CONSTELLATION_ET, valid only for DVB-T/H */ | ||
298 | 379 | ||
299 | /* Burst parameters, valid only for DVB-H */ | 380 | /* Burst parameters, valid only for DVB-H */ |
300 | u32 BurstSize; /* Current burst size in bytes */ | 381 | u32 BurstSize; /* Current burst size in bytes, |
301 | u32 BurstDuration; /* Current burst duration in mSec */ | 382 | valid only for DVB-H */ |
302 | u32 BurstCycleTime; /* Current burst cycle time in mSec */ | 383 | u32 BurstDuration; /* Current burst duration in mSec, |
303 | u32 CalculatedBurstCycleTime; /* Current burst cycle time in mSec, | 384 | valid only for DVB-H */ |
304 | * as calculated by demodulator */ | 385 | u32 BurstCycleTime; /* Current burst cycle time in mSec, |
305 | u32 NumOfRows; /* Number of rows in MPE table */ | 386 | valid only for DVB-H */ |
306 | u32 NumOfPaddCols; /* Number of padding columns in MPE table */ | 387 | u32 CalculatedBurstCycleTime;/* Current burst cycle time in mSec, |
307 | u32 NumOfPunctCols; /* Number of puncturing columns in MPE table */ | 388 | as calculated by demodulator, valid only for DVB-H */ |
308 | /* Burst parameters */ | 389 | u32 NumOfRows; /* Number of rows in MPE table, |
309 | u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */ | 390 | valid only for DVB-H */ |
310 | u32 TotalTSPackets; /* Total number of transport-stream packets */ | 391 | u32 NumOfPaddCols; /* Number of padding columns in MPE table, |
311 | u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include | 392 | valid only for DVB-H */ |
312 | * errors after MPE RS decoding */ | 393 | u32 NumOfPunctCols; /* Number of puncturing columns in MPE table, |
313 | u32 NumOfInvalidMpeTlbs; /* Number of MPE tables which include errors | 394 | valid only for DVB-H */ |
314 | * after MPE RS decoding */ | 395 | u32 ErrorTSPackets; /* Number of erroneous |
315 | u32 NumOfCorrectedMpeTlbs; /* Number of MPE tables which were corrected | 396 | transport-stream packets */ |
316 | * by MPE RS decoding */ | 397 | u32 TotalTSPackets; /* Total number of transport-stream packets */ |
317 | 398 | u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include | |
399 | errors after MPE RS decoding */ | ||
400 | u32 NumOfInvalidMpeTlbs;/* Number of MPE tables which include errors | ||
401 | after MPE RS decoding */ | ||
402 | u32 NumOfCorrectedMpeTlbs;/* Number of MPE tables which were | ||
403 | corrected by MPE RS decoding */ | ||
318 | /* Common params */ | 404 | /* Common params */ |
319 | u32 BERErrorCount; /* Number of errornous SYNC bits. */ | 405 | u32 BERErrorCount; /* Number of errornous SYNC bits. */ |
320 | u32 BERBitCount; /* Total number of SYNC bits. */ | 406 | u32 BERBitCount; /* Total number of SYNC bits. */ |
321 | 407 | ||
322 | /* Interface information */ | 408 | /* Interface information */ |
323 | u32 SmsToHostTxErrors; /* Total number of transmission errors. */ | 409 | u32 SmsToHostTxErrors; /* Total number of transmission errors. */ |
324 | 410 | ||
325 | /* DAB/T-DMB */ | 411 | /* DAB/T-DMB */ |
326 | u32 PreBER; /* DAB/T-DMB only: Pre Viterbi BER [1E-5] */ | 412 | u32 PreBER; /* DAB/T-DMB only: Pre Viterbi BER [1E-5] */ |
327 | 413 | ||
328 | /* DVB-H TPS parameters */ | 414 | /* DVB-H TPS parameters */ |
329 | u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; | 415 | u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; |
330 | * if set to 0xFFFFFFFF cell_id not yet recovered */ | 416 | if set to 0xFFFFFFFF cell_id not yet recovered */ |
417 | u32 DvbhSrvIndHP; /* DVB-H service indication info, bit 1 - | ||
418 | Time Slicing indicator, bit 0 - MPE-FEC indicator */ | ||
419 | u32 DvbhSrvIndLP; /* DVB-H service indication info, bit 1 - | ||
420 | Time Slicing indicator, bit 0 - MPE-FEC indicator */ | ||
331 | 421 | ||
422 | u32 NumMPEReceived; /* DVB-H, Num MPE section received */ | ||
423 | |||
424 | u32 ReservedFields[10]; /* Reserved */ | ||
332 | }; | 425 | }; |
333 | 426 | ||
334 | struct SmsMsgStatisticsInfo_ST { | 427 | struct PID_STATISTICS_DATA_S { |
335 | u32 RequestResult; | 428 | struct PID_BURST_S { |
429 | u32 size; | ||
430 | u32 padding_cols; | ||
431 | u32 punct_cols; | ||
432 | u32 duration; | ||
433 | u32 cycle; | ||
434 | u32 calc_cycle; | ||
435 | } burst; | ||
436 | |||
437 | u32 tot_tbl_cnt; | ||
438 | u32 invalid_tbl_cnt; | ||
439 | u32 tot_cor_tbl; | ||
440 | }; | ||
336 | 441 | ||
337 | struct SMSHOSTLIB_STATISTICS_ST Stat; | 442 | struct PID_DATA_S { |
443 | u32 pid; | ||
444 | u32 num_rows; | ||
445 | struct PID_STATISTICS_DATA_S pid_statistics; | ||
446 | }; | ||
338 | 447 | ||
339 | /* Split the calc of the SNR in DAB */ | 448 | #define CORRECT_STAT_RSSI(_stat) ((_stat).RSSI *= -1) |
340 | u32 Signal; /* dB */ | 449 | #define CORRECT_STAT_BANDWIDTH(_stat) (_stat.Bandwidth = 8 - _stat.Bandwidth) |
341 | u32 Noise; /* dB */ | 450 | #define CORRECT_STAT_TRANSMISSON_MODE(_stat) \ |
451 | if (_stat.TransmissionMode == 0) \ | ||
452 | _stat.TransmissionMode = 2; \ | ||
453 | else if (_stat.TransmissionMode == 1) \ | ||
454 | _stat.TransmissionMode = 8; \ | ||
455 | else \ | ||
456 | _stat.TransmissionMode = 4; | ||
457 | |||
458 | struct TRANSMISSION_STATISTICS_S { | ||
459 | u32 Frequency; /* Frequency in Hz */ | ||
460 | u32 Bandwidth; /* Bandwidth in MHz */ | ||
461 | u32 TransmissionMode; /* FFT mode carriers in Kilos */ | ||
462 | u32 GuardInterval; /* Guard Interval from | ||
463 | SMSHOSTLIB_GUARD_INTERVALS_ET */ | ||
464 | u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET */ | ||
465 | u32 LPCodeRate; /* Low Priority Code Rate from | ||
466 | SMSHOSTLIB_CODE_RATE_ET */ | ||
467 | u32 Hierarchy; /* Hierarchy from SMSHOSTLIB_HIERARCHY_ET */ | ||
468 | u32 Constellation; /* Constellation from | ||
469 | SMSHOSTLIB_CONSTELLATION_ET */ | ||
342 | 470 | ||
471 | /* DVB-H TPS parameters */ | ||
472 | u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; | ||
473 | if set to 0xFFFFFFFF cell_id not yet recovered */ | ||
474 | u32 DvbhSrvIndHP; /* DVB-H service indication info, bit 1 - | ||
475 | Time Slicing indicator, bit 0 - MPE-FEC indicator */ | ||
476 | u32 DvbhSrvIndLP; /* DVB-H service indication info, bit 1 - | ||
477 | Time Slicing indicator, bit 0 - MPE-FEC indicator */ | ||
478 | u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ | ||
343 | }; | 479 | }; |
344 | 480 | ||
481 | struct RECEPTION_STATISTICS_S { | ||
482 | u32 IsRfLocked; /* 0 - not locked, 1 - locked */ | ||
483 | u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ | ||
484 | u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ | ||
485 | |||
486 | u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */ | ||
487 | s32 SNR; /* dB */ | ||
488 | u32 BER; /* Post Viterbi BER [1E-5] */ | ||
489 | u32 BERErrorCount; /* Number of erronous SYNC bits. */ | ||
490 | u32 BERBitCount; /* Total number of SYNC bits. */ | ||
491 | u32 TS_PER; /* Transport stream PER, | ||
492 | 0xFFFFFFFF indicate N/A */ | ||
493 | u32 MFER; /* DVB-H frame error rate in percentage, | ||
494 | 0xFFFFFFFF indicate N/A, valid only for DVB-H */ | ||
495 | s32 RSSI; /* dBm */ | ||
496 | s32 InBandPwr; /* In band power in dBM */ | ||
497 | s32 CarrierOffset; /* Carrier Offset in bin/1024 */ | ||
498 | u32 ErrorTSPackets; /* Number of erroneous | ||
499 | transport-stream packets */ | ||
500 | u32 TotalTSPackets; /* Total number of transport-stream packets */ | ||
501 | |||
502 | s32 MRC_SNR; /* dB */ | ||
503 | s32 MRC_RSSI; /* dBm */ | ||
504 | s32 MRC_InBandPwr; /* In band power in dBM */ | ||
505 | }; | ||
345 | 506 | ||
346 | struct smscore_gpio_config { | 507 | |
508 | /* Statistics information returned as response for | ||
509 | * SmsHostApiGetStatisticsEx_Req for DVB applications, SMS1100 and up */ | ||
510 | struct SMSHOSTLIB_STATISTICS_DVB_S { | ||
511 | /* Reception */ | ||
512 | struct RECEPTION_STATISTICS_S ReceptionData; | ||
513 | |||
514 | /* Transmission parameters */ | ||
515 | struct TRANSMISSION_STATISTICS_S TransmissionData; | ||
516 | |||
517 | /* Burst parameters, valid only for DVB-H */ | ||
518 | #define SRVM_MAX_PID_FILTERS 8 | ||
519 | struct PID_DATA_S PidData[SRVM_MAX_PID_FILTERS]; | ||
520 | }; | ||
521 | |||
522 | struct SRVM_SIGNAL_STATUS_S { | ||
523 | u32 result; | ||
524 | u32 snr; | ||
525 | u32 tsPackets; | ||
526 | u32 etsPackets; | ||
527 | u32 constellation; | ||
528 | u32 hpCode; | ||
529 | u32 tpsSrvIndLP; | ||
530 | u32 tpsSrvIndHP; | ||
531 | u32 cellId; | ||
532 | u32 reason; | ||
533 | |||
534 | s32 inBandPower; | ||
535 | u32 requestId; | ||
536 | }; | ||
537 | |||
538 | struct SMSHOSTLIB_I2C_REQ_ST { | ||
539 | u32 DeviceAddress; /* I2c device address */ | ||
540 | u32 WriteCount; /* number of bytes to write */ | ||
541 | u32 ReadCount; /* number of bytes to read */ | ||
542 | u8 Data[1]; | ||
543 | }; | ||
544 | |||
545 | struct SMSHOSTLIB_I2C_RES_ST { | ||
546 | u32 Status; /* non-zero value in case of failure */ | ||
547 | u32 ReadCount; /* number of bytes read */ | ||
548 | u8 Data[1]; | ||
549 | }; | ||
550 | |||
551 | |||
552 | struct smscore_config_gpio { | ||
347 | #define SMS_GPIO_DIRECTION_INPUT 0 | 553 | #define SMS_GPIO_DIRECTION_INPUT 0 |
348 | #define SMS_GPIO_DIRECTION_OUTPUT 1 | 554 | #define SMS_GPIO_DIRECTION_OUTPUT 1 |
349 | u8 direction; | 555 | u8 direction; |
@@ -369,6 +575,47 @@ struct smscore_gpio_config { | |||
369 | u8 outputdriving; | 575 | u8 outputdriving; |
370 | }; | 576 | }; |
371 | 577 | ||
578 | struct smscore_gpio_config { | ||
579 | #define SMS_GPIO_DIRECTION_INPUT 0 | ||
580 | #define SMS_GPIO_DIRECTION_OUTPUT 1 | ||
581 | u8 Direction; | ||
582 | |||
583 | #define SMS_GPIO_PULL_UP_DOWN_NONE 0 | ||
584 | #define SMS_GPIO_PULL_UP_DOWN_PULLDOWN 1 | ||
585 | #define SMS_GPIO_PULL_UP_DOWN_PULLUP 2 | ||
586 | #define SMS_GPIO_PULL_UP_DOWN_KEEPER 3 | ||
587 | u8 PullUpDown; | ||
588 | |||
589 | #define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL 0 | ||
590 | #define SMS_GPIO_INPUT_CHARACTERISTICS_SCHMITT 1 | ||
591 | u8 InputCharacteristics; | ||
592 | |||
593 | #define SMS_GPIO_OUTPUT_SLEW_RATE_SLOW 1 /* 10xx */ | ||
594 | #define SMS_GPIO_OUTPUT_SLEW_RATE_FAST 0 /* 10xx */ | ||
595 | |||
596 | |||
597 | #define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS 0 /* 11xx */ | ||
598 | #define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS 1 /* 11xx */ | ||
599 | #define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS 2 /* 11xx */ | ||
600 | #define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS 3 /* 11xx */ | ||
601 | u8 OutputSlewRate; | ||
602 | |||
603 | #define SMS_GPIO_OUTPUT_DRIVING_S_4mA 0 /* 10xx */ | ||
604 | #define SMS_GPIO_OUTPUT_DRIVING_S_8mA 1 /* 10xx */ | ||
605 | #define SMS_GPIO_OUTPUT_DRIVING_S_12mA 2 /* 10xx */ | ||
606 | #define SMS_GPIO_OUTPUT_DRIVING_S_16mA 3 /* 10xx */ | ||
607 | |||
608 | #define SMS_GPIO_OUTPUT_DRIVING_1_5mA 0 /* 11xx */ | ||
609 | #define SMS_GPIO_OUTPUT_DRIVING_2_8mA 1 /* 11xx */ | ||
610 | #define SMS_GPIO_OUTPUT_DRIVING_4mA 2 /* 11xx */ | ||
611 | #define SMS_GPIO_OUTPUT_DRIVING_7mA 3 /* 11xx */ | ||
612 | #define SMS_GPIO_OUTPUT_DRIVING_10mA 4 /* 11xx */ | ||
613 | #define SMS_GPIO_OUTPUT_DRIVING_11mA 5 /* 11xx */ | ||
614 | #define SMS_GPIO_OUTPUT_DRIVING_14mA 6 /* 11xx */ | ||
615 | #define SMS_GPIO_OUTPUT_DRIVING_16mA 7 /* 11xx */ | ||
616 | u8 OutputDriving; | ||
617 | }; | ||
618 | |||
372 | extern void smscore_registry_setmode(char *devpath, int mode); | 619 | extern void smscore_registry_setmode(char *devpath, int mode); |
373 | extern int smscore_registry_getmode(char *devpath); | 620 | extern int smscore_registry_getmode(char *devpath); |
374 | 621 | ||
@@ -410,10 +657,19 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev); | |||
410 | extern void smscore_putbuffer(struct smscore_device_t *coredev, | 657 | extern void smscore_putbuffer(struct smscore_device_t *coredev, |
411 | struct smscore_buffer_t *cb); | 658 | struct smscore_buffer_t *cb); |
412 | 659 | ||
660 | /* old GPIO managment */ | ||
413 | int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin, | 661 | int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin, |
414 | struct smscore_gpio_config *pinconfig); | 662 | struct smscore_config_gpio *pinconfig); |
415 | int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level); | 663 | int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level); |
416 | 664 | ||
665 | /* new GPIO managment */ | ||
666 | extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, | ||
667 | struct smscore_gpio_config *pGpioConfig); | ||
668 | extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum, | ||
669 | u8 NewLevel); | ||
670 | extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum, | ||
671 | u8 *level); | ||
672 | |||
417 | void smscore_set_board_id(struct smscore_device_t *core, int id); | 673 | void smscore_set_board_id(struct smscore_device_t *core, int id); |
418 | int smscore_get_board_id(struct smscore_device_t *core); | 674 | int smscore_get_board_id(struct smscore_device_t *core); |
419 | 675 | ||
@@ -442,4 +698,4 @@ int smscore_led_state(struct smscore_device_t *core, int led); | |||
442 | dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg) | 698 | dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg) |
443 | 699 | ||
444 | 700 | ||
445 | #endif /* __smscoreapi_h__ */ | 701 | #endif /* __SMS_CORE_API_H__ */ |
diff --git a/drivers/media/dvb/siano/smsdvb.c b/drivers/media/dvb/siano/smsdvb.c index ba080b95befb..3ee1c3902c56 100644 --- a/drivers/media/dvb/siano/smsdvb.c +++ b/drivers/media/dvb/siano/smsdvb.c | |||
@@ -1,28 +1,34 @@ | |||
1 | /* | 1 | /**************************************************************** |
2 | * Driver for the Siano SMS1xxx USB dongle | 2 | |
3 | * | 3 | Siano Mobile Silicon, Inc. |
4 | * Author: Uri Shkolni | 4 | MDTV receiver kernel modules. |
5 | * | 5 | Copyright (C) 2006-2008, Uri Shkolnik |
6 | * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. | 6 | |
7 | * | 7 | This program is free software: you can redistribute it and/or modify |
8 | * This program is free software; you can redistribute it and/or modify | 8 | it under the terms of the GNU General Public License as published by |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | the Free Software Foundation, either version 2 of the License, or |
10 | * published by the Free Software Foundation; | 10 | (at your option) any later version. |
11 | * | 11 | |
12 | * Software distributed under the License is distributed on an "AS IS" | 12 | This program is distributed in the hope that it will be useful, |
13 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. | 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * | 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * See the GNU General Public License for more details. | 15 | GNU General Public License for more details. |
16 | * | 16 | |
17 | * You should have received a copy of the GNU General Public License | 17 | You should have received a copy of the GNU General Public License |
18 | * along with this program; if not, write to the Free Software | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | |
20 | */ | 20 | ****************************************************************/ |
21 | 21 | ||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | 24 | ||
25 | #include "dmxdev.h" | ||
26 | #include "dvbdev.h" | ||
27 | #include "dvb_demux.h" | ||
28 | #include "dvb_frontend.h" | ||
29 | |||
25 | #include "smscoreapi.h" | 30 | #include "smscoreapi.h" |
31 | #include "smsendian.h" | ||
26 | #include "sms-cards.h" | 32 | #include "sms-cards.h" |
27 | 33 | ||
28 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | 34 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
@@ -39,12 +45,15 @@ struct smsdvb_client_t { | |||
39 | struct dvb_frontend frontend; | 45 | struct dvb_frontend frontend; |
40 | 46 | ||
41 | fe_status_t fe_status; | 47 | fe_status_t fe_status; |
42 | int fe_ber, fe_snr, fe_unc, fe_signal_strength; | ||
43 | 48 | ||
44 | struct completion tune_done, stat_done; | 49 | struct completion tune_done; |
45 | 50 | ||
46 | /* todo: save freq/band instead whole struct */ | 51 | /* todo: save freq/band instead whole struct */ |
47 | struct dvb_frontend_parameters fe_params; | 52 | struct dvb_frontend_parameters fe_params; |
53 | |||
54 | struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb; | ||
55 | int event_fe_state; | ||
56 | int event_unc_state; | ||
48 | }; | 57 | }; |
49 | 58 | ||
50 | static struct list_head g_smsdvb_clients; | 59 | static struct list_head g_smsdvb_clients; |
@@ -54,11 +63,69 @@ static int sms_dbg; | |||
54 | module_param_named(debug, sms_dbg, int, 0644); | 63 | module_param_named(debug, sms_dbg, int, 0644); |
55 | MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); | 64 | MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); |
56 | 65 | ||
66 | /* Events that may come from DVB v3 adapter */ | ||
67 | static void sms_board_dvb3_event(struct smsdvb_client_t *client, | ||
68 | enum SMS_DVB3_EVENTS event) { | ||
69 | |||
70 | struct smscore_device_t *coredev = client->coredev; | ||
71 | switch (event) { | ||
72 | case DVB3_EVENT_INIT: | ||
73 | sms_debug("DVB3_EVENT_INIT"); | ||
74 | sms_board_event(coredev, BOARD_EVENT_BIND); | ||
75 | break; | ||
76 | case DVB3_EVENT_SLEEP: | ||
77 | sms_debug("DVB3_EVENT_SLEEP"); | ||
78 | sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND); | ||
79 | break; | ||
80 | case DVB3_EVENT_HOTPLUG: | ||
81 | sms_debug("DVB3_EVENT_HOTPLUG"); | ||
82 | sms_board_event(coredev, BOARD_EVENT_POWER_INIT); | ||
83 | break; | ||
84 | case DVB3_EVENT_FE_LOCK: | ||
85 | if (client->event_fe_state != DVB3_EVENT_FE_LOCK) { | ||
86 | client->event_fe_state = DVB3_EVENT_FE_LOCK; | ||
87 | sms_debug("DVB3_EVENT_FE_LOCK"); | ||
88 | sms_board_event(coredev, BOARD_EVENT_FE_LOCK); | ||
89 | } | ||
90 | break; | ||
91 | case DVB3_EVENT_FE_UNLOCK: | ||
92 | if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) { | ||
93 | client->event_fe_state = DVB3_EVENT_FE_UNLOCK; | ||
94 | sms_debug("DVB3_EVENT_FE_UNLOCK"); | ||
95 | sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK); | ||
96 | } | ||
97 | break; | ||
98 | case DVB3_EVENT_UNC_OK: | ||
99 | if (client->event_unc_state != DVB3_EVENT_UNC_OK) { | ||
100 | client->event_unc_state = DVB3_EVENT_UNC_OK; | ||
101 | sms_debug("DVB3_EVENT_UNC_OK"); | ||
102 | sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK); | ||
103 | } | ||
104 | break; | ||
105 | case DVB3_EVENT_UNC_ERR: | ||
106 | if (client->event_unc_state != DVB3_EVENT_UNC_ERR) { | ||
107 | client->event_unc_state = DVB3_EVENT_UNC_ERR; | ||
108 | sms_debug("DVB3_EVENT_UNC_ERR"); | ||
109 | sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS); | ||
110 | } | ||
111 | break; | ||
112 | |||
113 | default: | ||
114 | sms_err("Unknown dvb3 api event"); | ||
115 | break; | ||
116 | } | ||
117 | } | ||
118 | |||
57 | static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) | 119 | static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) |
58 | { | 120 | { |
59 | struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; | 121 | struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; |
60 | struct SmsMsgHdr_ST *phdr = | 122 | struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p) |
61 | (struct SmsMsgHdr_ST *)(((u8 *) cb->p) + cb->offset); | 123 | + cb->offset); |
124 | u32 *pMsgData = (u32 *) phdr + 1; | ||
125 | /*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/ | ||
126 | bool is_status_update = false; | ||
127 | |||
128 | smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr); | ||
62 | 129 | ||
63 | switch (phdr->msgType) { | 130 | switch (phdr->msgType) { |
64 | case MSG_SMS_DVBT_BDA_DATA: | 131 | case MSG_SMS_DVBT_BDA_DATA: |
@@ -70,43 +137,110 @@ static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) | |||
70 | complete(&client->tune_done); | 137 | complete(&client->tune_done); |
71 | break; | 138 | break; |
72 | 139 | ||
73 | case MSG_SMS_GET_STATISTICS_RES: | 140 | case MSG_SMS_SIGNAL_DETECTED_IND: |
74 | { | 141 | sms_info("MSG_SMS_SIGNAL_DETECTED_IND"); |
75 | struct SmsMsgStatisticsInfo_ST *p = | 142 | client->sms_stat_dvb.TransmissionData.IsDemodLocked = true; |
76 | (struct SmsMsgStatisticsInfo_ST *)(phdr + 1); | 143 | is_status_update = true; |
77 | 144 | break; | |
78 | if (p->Stat.IsDemodLocked) { | 145 | |
79 | client->fe_status = FE_HAS_SIGNAL | | 146 | case MSG_SMS_NO_SIGNAL_IND: |
80 | FE_HAS_CARRIER | | 147 | sms_info("MSG_SMS_NO_SIGNAL_IND"); |
81 | FE_HAS_VITERBI | | 148 | client->sms_stat_dvb.TransmissionData.IsDemodLocked = false; |
82 | FE_HAS_SYNC | | 149 | is_status_update = true; |
83 | FE_HAS_LOCK; | 150 | break; |
84 | 151 | ||
85 | client->fe_snr = p->Stat.SNR; | 152 | case MSG_SMS_TRANSMISSION_IND: { |
86 | client->fe_ber = p->Stat.BER; | 153 | sms_info("MSG_SMS_TRANSMISSION_IND"); |
87 | client->fe_unc = p->Stat.BERErrorCount; | 154 | |
88 | 155 | pMsgData++; | |
89 | if (p->Stat.InBandPwr < -95) | 156 | memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData, |
90 | client->fe_signal_strength = 0; | 157 | sizeof(struct TRANSMISSION_STATISTICS_S)); |
91 | else if (p->Stat.InBandPwr > -29) | 158 | |
92 | client->fe_signal_strength = 100; | 159 | /* Mo need to correct guard interval |
93 | else | 160 | * (as opposed to old statistics message). |
94 | client->fe_signal_strength = | 161 | */ |
95 | (p->Stat.InBandPwr + 95) * 3 / 2; | 162 | CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData); |
163 | CORRECT_STAT_TRANSMISSON_MODE( | ||
164 | client->sms_stat_dvb.TransmissionData); | ||
165 | is_status_update = true; | ||
166 | break; | ||
167 | } | ||
168 | case MSG_SMS_HO_PER_SLICES_IND: { | ||
169 | struct RECEPTION_STATISTICS_S *pReceptionData = | ||
170 | &client->sms_stat_dvb.ReceptionData; | ||
171 | struct SRVM_SIGNAL_STATUS_S SignalStatusData; | ||
172 | |||
173 | /*sms_info("MSG_SMS_HO_PER_SLICES_IND");*/ | ||
174 | pMsgData++; | ||
175 | SignalStatusData.result = pMsgData[0]; | ||
176 | SignalStatusData.snr = pMsgData[1]; | ||
177 | SignalStatusData.inBandPower = (s32) pMsgData[2]; | ||
178 | SignalStatusData.tsPackets = pMsgData[3]; | ||
179 | SignalStatusData.etsPackets = pMsgData[4]; | ||
180 | SignalStatusData.constellation = pMsgData[5]; | ||
181 | SignalStatusData.hpCode = pMsgData[6]; | ||
182 | SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03; | ||
183 | SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03; | ||
184 | SignalStatusData.cellId = pMsgData[9] & 0xFFFF; | ||
185 | SignalStatusData.reason = pMsgData[10]; | ||
186 | SignalStatusData.requestId = pMsgData[11]; | ||
187 | pReceptionData->IsRfLocked = pMsgData[16]; | ||
188 | pReceptionData->IsDemodLocked = pMsgData[17]; | ||
189 | pReceptionData->ModemState = pMsgData[12]; | ||
190 | pReceptionData->SNR = pMsgData[1]; | ||
191 | pReceptionData->BER = pMsgData[13]; | ||
192 | pReceptionData->RSSI = pMsgData[14]; | ||
193 | CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData); | ||
194 | |||
195 | pReceptionData->InBandPwr = (s32) pMsgData[2]; | ||
196 | pReceptionData->CarrierOffset = (s32) pMsgData[15]; | ||
197 | pReceptionData->TotalTSPackets = pMsgData[3]; | ||
198 | pReceptionData->ErrorTSPackets = pMsgData[4]; | ||
199 | |||
200 | /* TS PER */ | ||
201 | if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets) | ||
202 | > 0) { | ||
203 | pReceptionData->TS_PER = (SignalStatusData.etsPackets | ||
204 | * 100) / (SignalStatusData.tsPackets | ||
205 | + SignalStatusData.etsPackets); | ||
96 | } else { | 206 | } else { |
97 | client->fe_status = 0; | 207 | pReceptionData->TS_PER = 0; |
98 | client->fe_snr = | ||
99 | client->fe_ber = | ||
100 | client->fe_unc = | ||
101 | client->fe_signal_strength = 0; | ||
102 | } | 208 | } |
103 | 209 | ||
104 | complete(&client->stat_done); | 210 | pReceptionData->BERBitCount = pMsgData[18]; |
105 | break; | 211 | pReceptionData->BERErrorCount = pMsgData[19]; |
106 | } } | ||
107 | 212 | ||
213 | pReceptionData->MRC_SNR = pMsgData[20]; | ||
214 | pReceptionData->MRC_InBandPwr = pMsgData[21]; | ||
215 | pReceptionData->MRC_RSSI = pMsgData[22]; | ||
216 | |||
217 | is_status_update = true; | ||
218 | break; | ||
219 | } | ||
220 | } | ||
108 | smscore_putbuffer(client->coredev, cb); | 221 | smscore_putbuffer(client->coredev, cb); |
109 | 222 | ||
223 | if (is_status_update) { | ||
224 | if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) { | ||
225 | client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER | ||
226 | | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | ||
227 | sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK); | ||
228 | if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets | ||
229 | == 0) | ||
230 | sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK); | ||
231 | else | ||
232 | sms_board_dvb3_event(client, | ||
233 | DVB3_EVENT_UNC_ERR); | ||
234 | |||
235 | } else { | ||
236 | /*client->fe_status = | ||
237 | (phdr->msgType == MSG_SMS_NO_SIGNAL_IND) ? | ||
238 | 0 : FE_HAS_SIGNAL;*/ | ||
239 | client->fe_status = 0; | ||
240 | sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK); | ||
241 | } | ||
242 | } | ||
243 | |||
110 | return 0; | 244 | return 0; |
111 | } | 245 | } |
112 | 246 | ||
@@ -149,6 +283,7 @@ static int smsdvb_start_feed(struct dvb_demux_feed *feed) | |||
149 | PidMsg.xMsgHeader.msgLength = sizeof(PidMsg); | 283 | PidMsg.xMsgHeader.msgLength = sizeof(PidMsg); |
150 | PidMsg.msgData[0] = feed->pid; | 284 | PidMsg.msgData[0] = feed->pid; |
151 | 285 | ||
286 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg); | ||
152 | return smsclient_sendrequest(client->smsclient, | 287 | return smsclient_sendrequest(client->smsclient, |
153 | &PidMsg, sizeof(PidMsg)); | 288 | &PidMsg, sizeof(PidMsg)); |
154 | } | 289 | } |
@@ -169,6 +304,7 @@ static int smsdvb_stop_feed(struct dvb_demux_feed *feed) | |||
169 | PidMsg.xMsgHeader.msgLength = sizeof(PidMsg); | 304 | PidMsg.xMsgHeader.msgLength = sizeof(PidMsg); |
170 | PidMsg.msgData[0] = feed->pid; | 305 | PidMsg.msgData[0] = feed->pid; |
171 | 306 | ||
307 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg); | ||
172 | return smsclient_sendrequest(client->smsclient, | 308 | return smsclient_sendrequest(client->smsclient, |
173 | &PidMsg, sizeof(PidMsg)); | 309 | &PidMsg, sizeof(PidMsg)); |
174 | } | 310 | } |
@@ -177,7 +313,10 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, | |||
177 | void *buffer, size_t size, | 313 | void *buffer, size_t size, |
178 | struct completion *completion) | 314 | struct completion *completion) |
179 | { | 315 | { |
180 | int rc = smsclient_sendrequest(client->smsclient, buffer, size); | 316 | int rc; |
317 | |||
318 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)buffer); | ||
319 | rc = smsclient_sendrequest(client->smsclient, buffer, size); | ||
181 | if (rc < 0) | 320 | if (rc < 0) |
182 | return rc; | 321 | return rc; |
183 | 322 | ||
@@ -186,83 +325,61 @@ static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, | |||
186 | 0 : -ETIME; | 325 | 0 : -ETIME; |
187 | } | 326 | } |
188 | 327 | ||
189 | static int smsdvb_send_statistics_request(struct smsdvb_client_t *client) | ||
190 | { | ||
191 | struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ, | ||
192 | DVBT_BDA_CONTROL_MSG_ID, | ||
193 | HIF_TASK, sizeof(struct SmsMsgHdr_ST), 0 }; | ||
194 | int ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | ||
195 | &client->stat_done); | ||
196 | if (ret < 0) | ||
197 | return ret; | ||
198 | |||
199 | if (client->fe_status & FE_HAS_LOCK) | ||
200 | sms_board_led_feedback(client->coredev, | ||
201 | (client->fe_unc == 0) ? | ||
202 | SMS_LED_HI : SMS_LED_LO); | ||
203 | else | ||
204 | sms_board_led_feedback(client->coredev, SMS_LED_OFF); | ||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) | 328 | static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) |
209 | { | 329 | { |
210 | struct smsdvb_client_t *client = | 330 | struct smsdvb_client_t *client; |
211 | container_of(fe, struct smsdvb_client_t, frontend); | 331 | client = container_of(fe, struct smsdvb_client_t, frontend); |
212 | int rc = smsdvb_send_statistics_request(client); | ||
213 | 332 | ||
214 | if (!rc) | 333 | *stat = client->fe_status; |
215 | *stat = client->fe_status; | ||
216 | 334 | ||
217 | return rc; | 335 | return 0; |
218 | } | 336 | } |
219 | 337 | ||
220 | static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) | 338 | static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) |
221 | { | 339 | { |
222 | struct smsdvb_client_t *client = | 340 | struct smsdvb_client_t *client; |
223 | container_of(fe, struct smsdvb_client_t, frontend); | 341 | client = container_of(fe, struct smsdvb_client_t, frontend); |
224 | int rc = smsdvb_send_statistics_request(client); | ||
225 | 342 | ||
226 | if (!rc) | 343 | *ber = client->sms_stat_dvb.ReceptionData.BER; |
227 | *ber = client->fe_ber; | ||
228 | 344 | ||
229 | return rc; | 345 | return 0; |
230 | } | 346 | } |
231 | 347 | ||
232 | static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | 348 | static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) |
233 | { | 349 | { |
234 | struct smsdvb_client_t *client = | 350 | struct smsdvb_client_t *client; |
235 | container_of(fe, struct smsdvb_client_t, frontend); | 351 | client = container_of(fe, struct smsdvb_client_t, frontend); |
236 | int rc = smsdvb_send_statistics_request(client); | ||
237 | 352 | ||
238 | if (!rc) | 353 | if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95) |
239 | *strength = client->fe_signal_strength; | 354 | *strength = 0; |
355 | else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29) | ||
356 | *strength = 100; | ||
357 | else | ||
358 | *strength = | ||
359 | (client->sms_stat_dvb.ReceptionData.InBandPwr | ||
360 | + 95) * 3 / 2; | ||
240 | 361 | ||
241 | return rc; | 362 | return 0; |
242 | } | 363 | } |
243 | 364 | ||
244 | static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) | 365 | static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) |
245 | { | 366 | { |
246 | struct smsdvb_client_t *client = | 367 | struct smsdvb_client_t *client; |
247 | container_of(fe, struct smsdvb_client_t, frontend); | 368 | client = container_of(fe, struct smsdvb_client_t, frontend); |
248 | int rc = smsdvb_send_statistics_request(client); | ||
249 | 369 | ||
250 | if (!rc) | 370 | *snr = client->sms_stat_dvb.ReceptionData.SNR; |
251 | *snr = client->fe_snr; | ||
252 | 371 | ||
253 | return rc; | 372 | return 0; |
254 | } | 373 | } |
255 | 374 | ||
256 | static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | 375 | static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) |
257 | { | 376 | { |
258 | struct smsdvb_client_t *client = | 377 | struct smsdvb_client_t *client; |
259 | container_of(fe, struct smsdvb_client_t, frontend); | 378 | client = container_of(fe, struct smsdvb_client_t, frontend); |
260 | int rc = smsdvb_send_statistics_request(client); | ||
261 | 379 | ||
262 | if (!rc) | 380 | *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets; |
263 | *ucblocks = client->fe_unc; | ||
264 | 381 | ||
265 | return rc; | 382 | return 0; |
266 | } | 383 | } |
267 | 384 | ||
268 | static int smsdvb_get_tune_settings(struct dvb_frontend *fe, | 385 | static int smsdvb_get_tune_settings(struct dvb_frontend *fe, |
@@ -286,12 +403,15 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, | |||
286 | struct SmsMsgHdr_ST Msg; | 403 | struct SmsMsgHdr_ST Msg; |
287 | u32 Data[3]; | 404 | u32 Data[3]; |
288 | } Msg; | 405 | } Msg; |
289 | int ret; | ||
290 | 406 | ||
291 | Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | 407 | client->fe_status = FE_HAS_SIGNAL; |
292 | Msg.Msg.msgDstId = HIF_TASK; | 408 | client->event_fe_state = -1; |
293 | Msg.Msg.msgFlags = 0; | 409 | client->event_unc_state = -1; |
294 | Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ; | 410 | |
411 | Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
412 | Msg.Msg.msgDstId = HIF_TASK; | ||
413 | Msg.Msg.msgFlags = 0; | ||
414 | Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ; | ||
295 | Msg.Msg.msgLength = sizeof(Msg); | 415 | Msg.Msg.msgLength = sizeof(Msg); |
296 | Msg.Data[0] = fep->frequency; | 416 | Msg.Data[0] = fep->frequency; |
297 | Msg.Data[2] = 12000000; | 417 | Msg.Data[2] = 12000000; |
@@ -307,24 +427,6 @@ static int smsdvb_set_frontend(struct dvb_frontend *fe, | |||
307 | default: return -EINVAL; | 427 | default: return -EINVAL; |
308 | } | 428 | } |
309 | 429 | ||
310 | /* Disable LNA, if any. An error is returned if no LNA is present */ | ||
311 | ret = sms_board_lna_control(client->coredev, 0); | ||
312 | if (ret == 0) { | ||
313 | fe_status_t status; | ||
314 | |||
315 | /* tune with LNA off at first */ | ||
316 | ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | ||
317 | &client->tune_done); | ||
318 | |||
319 | smsdvb_read_status(fe, &status); | ||
320 | |||
321 | if (status & FE_HAS_LOCK) | ||
322 | return ret; | ||
323 | |||
324 | /* previous tune didnt lock - enable LNA and tune again */ | ||
325 | sms_board_lna_control(client->coredev, 1); | ||
326 | } | ||
327 | |||
328 | return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | 430 | return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), |
329 | &client->tune_done); | 431 | &client->tune_done); |
330 | } | 432 | } |
@@ -349,8 +451,7 @@ static int smsdvb_init(struct dvb_frontend *fe) | |||
349 | struct smsdvb_client_t *client = | 451 | struct smsdvb_client_t *client = |
350 | container_of(fe, struct smsdvb_client_t, frontend); | 452 | container_of(fe, struct smsdvb_client_t, frontend); |
351 | 453 | ||
352 | sms_board_power(client->coredev, 1); | 454 | sms_board_dvb3_event(client, DVB3_EVENT_INIT); |
353 | |||
354 | return 0; | 455 | return 0; |
355 | } | 456 | } |
356 | 457 | ||
@@ -359,8 +460,7 @@ static int smsdvb_sleep(struct dvb_frontend *fe) | |||
359 | struct smsdvb_client_t *client = | 460 | struct smsdvb_client_t *client = |
360 | container_of(fe, struct smsdvb_client_t, frontend); | 461 | container_of(fe, struct smsdvb_client_t, frontend); |
361 | 462 | ||
362 | sms_board_led_feedback(client->coredev, SMS_LED_OFF); | 463 | sms_board_dvb3_event(client, DVB3_EVENT_SLEEP); |
363 | sms_board_power(client->coredev, 0); | ||
364 | 464 | ||
365 | return 0; | 465 | return 0; |
366 | } | 466 | } |
@@ -485,7 +585,6 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, | |||
485 | client->coredev = coredev; | 585 | client->coredev = coredev; |
486 | 586 | ||
487 | init_completion(&client->tune_done); | 587 | init_completion(&client->tune_done); |
488 | init_completion(&client->stat_done); | ||
489 | 588 | ||
490 | kmutex_lock(&g_smsdvb_clientslock); | 589 | kmutex_lock(&g_smsdvb_clientslock); |
491 | 590 | ||
@@ -493,8 +592,11 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, | |||
493 | 592 | ||
494 | kmutex_unlock(&g_smsdvb_clientslock); | 593 | kmutex_unlock(&g_smsdvb_clientslock); |
495 | 594 | ||
496 | sms_info("success"); | 595 | client->event_fe_state = -1; |
596 | client->event_unc_state = -1; | ||
597 | sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG); | ||
497 | 598 | ||
599 | sms_info("success"); | ||
498 | sms_board_setup(coredev); | 600 | sms_board_setup(coredev); |
499 | 601 | ||
500 | return 0; | 602 | return 0; |
@@ -547,5 +649,5 @@ module_init(smsdvb_module_init); | |||
547 | module_exit(smsdvb_module_exit); | 649 | module_exit(smsdvb_module_exit); |
548 | 650 | ||
549 | MODULE_DESCRIPTION("SMS DVB subsystem adaptation module"); | 651 | MODULE_DESCRIPTION("SMS DVB subsystem adaptation module"); |
550 | MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)"); | 652 | MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)"); |
551 | MODULE_LICENSE("GPL"); | 653 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/media/dvb/siano/smsendian.c b/drivers/media/dvb/siano/smsendian.c new file mode 100644 index 000000000000..457b6d02ef85 --- /dev/null +++ b/drivers/media/dvb/siano/smsendian.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /**************************************************************** | ||
2 | |||
3 | Siano Mobile Silicon, Inc. | ||
4 | MDTV receiver kernel modules. | ||
5 | Copyright (C) 2006-2009, Uri Shkolnik | ||
6 | |||
7 | This program is free software: you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation, either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | |||
20 | ****************************************************************/ | ||
21 | |||
22 | #include <asm/byteorder.h> | ||
23 | |||
24 | #include "smsendian.h" | ||
25 | #include "smscoreapi.h" | ||
26 | |||
27 | void smsendian_handle_tx_message(void *buffer) | ||
28 | { | ||
29 | #ifdef __BIG_ENDIAN | ||
30 | struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer; | ||
31 | int i; | ||
32 | int msgWords; | ||
33 | |||
34 | switch (msg->xMsgHeader.msgType) { | ||
35 | case MSG_SMS_DATA_DOWNLOAD_REQ: | ||
36 | { | ||
37 | msg->msgData[0] = le32_to_cpu(msg->msgData[0]); | ||
38 | break; | ||
39 | } | ||
40 | |||
41 | default: | ||
42 | msgWords = (msg->xMsgHeader.msgLength - | ||
43 | sizeof(struct SmsMsgHdr_ST))/4; | ||
44 | |||
45 | for (i = 0; i < msgWords; i++) | ||
46 | msg->msgData[i] = le32_to_cpu(msg->msgData[i]); | ||
47 | |||
48 | break; | ||
49 | } | ||
50 | #endif /* __BIG_ENDIAN */ | ||
51 | } | ||
52 | EXPORT_SYMBOL_GPL(smsendian_handle_tx_message); | ||
53 | |||
54 | void smsendian_handle_rx_message(void *buffer) | ||
55 | { | ||
56 | #ifdef __BIG_ENDIAN | ||
57 | struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer; | ||
58 | int i; | ||
59 | int msgWords; | ||
60 | |||
61 | switch (msg->xMsgHeader.msgType) { | ||
62 | case MSG_SMS_GET_VERSION_EX_RES: | ||
63 | { | ||
64 | struct SmsVersionRes_ST *ver = | ||
65 | (struct SmsVersionRes_ST *) msg; | ||
66 | ver->ChipModel = le16_to_cpu(ver->ChipModel); | ||
67 | break; | ||
68 | } | ||
69 | |||
70 | case MSG_SMS_DVBT_BDA_DATA: | ||
71 | case MSG_SMS_DAB_CHANNEL: | ||
72 | case MSG_SMS_DATA_MSG: | ||
73 | { | ||
74 | break; | ||
75 | } | ||
76 | |||
77 | default: | ||
78 | { | ||
79 | msgWords = (msg->xMsgHeader.msgLength - | ||
80 | sizeof(struct SmsMsgHdr_ST))/4; | ||
81 | |||
82 | for (i = 0; i < msgWords; i++) | ||
83 | msg->msgData[i] = le32_to_cpu(msg->msgData[i]); | ||
84 | |||
85 | break; | ||
86 | } | ||
87 | } | ||
88 | #endif /* __BIG_ENDIAN */ | ||
89 | } | ||
90 | EXPORT_SYMBOL_GPL(smsendian_handle_rx_message); | ||
91 | |||
92 | void smsendian_handle_message_header(void *msg) | ||
93 | { | ||
94 | #ifdef __BIG_ENDIAN | ||
95 | struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)msg; | ||
96 | |||
97 | phdr->msgType = le16_to_cpu(phdr->msgType); | ||
98 | phdr->msgLength = le16_to_cpu(phdr->msgLength); | ||
99 | phdr->msgFlags = le16_to_cpu(phdr->msgFlags); | ||
100 | #endif /* __BIG_ENDIAN */ | ||
101 | } | ||
102 | EXPORT_SYMBOL_GPL(smsendian_handle_message_header); | ||
diff --git a/drivers/media/dvb/siano/smsendian.h b/drivers/media/dvb/siano/smsendian.h new file mode 100644 index 000000000000..1624d6fd367b --- /dev/null +++ b/drivers/media/dvb/siano/smsendian.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /**************************************************************** | ||
2 | |||
3 | Siano Mobile Silicon, Inc. | ||
4 | MDTV receiver kernel modules. | ||
5 | Copyright (C) 2006-2009, Uri Shkolnik | ||
6 | |||
7 | This program is free software: you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation, either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | |||
20 | ****************************************************************/ | ||
21 | |||
22 | #ifndef __SMS_ENDIAN_H__ | ||
23 | #define __SMS_ENDIAN_H__ | ||
24 | |||
25 | #include <asm/byteorder.h> | ||
26 | |||
27 | extern void smsendian_handle_tx_message(void *buffer); | ||
28 | extern void smsendian_handle_rx_message(void *buffer); | ||
29 | extern void smsendian_handle_message_header(void *msg); | ||
30 | |||
31 | #endif /* __SMS_ENDIAN_H__ */ | ||
32 | |||
diff --git a/drivers/media/dvb/siano/smsir.c b/drivers/media/dvb/siano/smsir.c new file mode 100644 index 000000000000..e3d776feeaca --- /dev/null +++ b/drivers/media/dvb/siano/smsir.c | |||
@@ -0,0 +1,301 @@ | |||
1 | /**************************************************************** | ||
2 | |||
3 | Siano Mobile Silicon, Inc. | ||
4 | MDTV receiver kernel modules. | ||
5 | Copyright (C) 2006-2009, Uri Shkolnik | ||
6 | |||
7 | This program is free software: you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation, either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | |||
20 | ****************************************************************/ | ||
21 | |||
22 | |||
23 | #include <linux/types.h> | ||
24 | #include <linux/input.h> | ||
25 | |||
26 | #include "smscoreapi.h" | ||
27 | #include "smsir.h" | ||
28 | #include "sms-cards.h" | ||
29 | |||
30 | /* In order to add new IR remote control - | ||
31 | * 1) Add it to the <enum ir_kb_type> @ smsir,h, | ||
32 | * 2) Add its map to keyboard_layout_maps below | ||
33 | * 3) Set your board (sms-cards sub-module) to use it | ||
34 | */ | ||
35 | |||
36 | static struct keyboard_layout_map_t keyboard_layout_maps[] = { | ||
37 | [SMS_IR_KB_DEFAULT_TV] = { | ||
38 | .ir_protocol = IR_RC5, | ||
39 | .rc5_kbd_address = KEYBOARD_ADDRESS_TV1, | ||
40 | .keyboard_layout_map = { | ||
41 | KEY_0, KEY_1, KEY_2, | ||
42 | KEY_3, KEY_4, KEY_5, | ||
43 | KEY_6, KEY_7, KEY_8, | ||
44 | KEY_9, 0, 0, KEY_POWER, | ||
45 | KEY_MUTE, 0, 0, | ||
46 | KEY_VOLUMEUP, KEY_VOLUMEDOWN, | ||
47 | KEY_BRIGHTNESSUP, | ||
48 | KEY_BRIGHTNESSDOWN, KEY_CHANNELUP, | ||
49 | KEY_CHANNELDOWN, | ||
50 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
51 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
52 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
53 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
54 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
55 | } | ||
56 | }, | ||
57 | [SMS_IR_KB_HCW_SILVER] = { | ||
58 | .ir_protocol = IR_RC5, | ||
59 | .rc5_kbd_address = KEYBOARD_ADDRESS_LIGHTING1, | ||
60 | .keyboard_layout_map = { | ||
61 | KEY_0, KEY_1, KEY_2, | ||
62 | KEY_3, KEY_4, KEY_5, | ||
63 | KEY_6, KEY_7, KEY_8, | ||
64 | KEY_9, KEY_TEXT, KEY_RED, | ||
65 | KEY_RADIO, KEY_MENU, | ||
66 | KEY_SUBTITLE, | ||
67 | KEY_MUTE, KEY_VOLUMEUP, | ||
68 | KEY_VOLUMEDOWN, KEY_PREVIOUS, 0, | ||
69 | KEY_UP, KEY_DOWN, KEY_LEFT, | ||
70 | KEY_RIGHT, KEY_VIDEO, KEY_AUDIO, | ||
71 | KEY_MHP, KEY_EPG, KEY_TV, | ||
72 | 0, KEY_NEXTSONG, KEY_EXIT, | ||
73 | KEY_CHANNELUP, KEY_CHANNELDOWN, | ||
74 | KEY_CHANNEL, 0, | ||
75 | KEY_PREVIOUSSONG, KEY_ENTER, | ||
76 | KEY_SLEEP, 0, 0, KEY_BLUE, | ||
77 | 0, 0, 0, 0, KEY_GREEN, 0, | ||
78 | KEY_PAUSE, 0, KEY_REWIND, | ||
79 | 0, KEY_FASTFORWARD, KEY_PLAY, | ||
80 | KEY_STOP, KEY_RECORD, | ||
81 | KEY_YELLOW, 0, 0, KEY_SELECT, | ||
82 | KEY_ZOOM, KEY_POWER, 0, 0 | ||
83 | } | ||
84 | }, | ||
85 | { } /* Terminating entry */ | ||
86 | }; | ||
87 | |||
88 | u32 ir_pos; | ||
89 | u32 ir_word; | ||
90 | u32 ir_toggle; | ||
91 | |||
92 | #define RC5_PUSH_BIT(dst, bit, pos) \ | ||
93 | { dst <<= 1; dst |= bit; pos++; } | ||
94 | |||
95 | |||
96 | static void sms_ir_rc5_event(struct smscore_device_t *coredev, | ||
97 | u32 toggle, u32 addr, u32 cmd) | ||
98 | { | ||
99 | bool toggle_changed; | ||
100 | u16 keycode; | ||
101 | |||
102 | sms_log("IR RC5 word: address %d, command %d, toggle %d", | ||
103 | addr, cmd, toggle); | ||
104 | |||
105 | toggle_changed = ir_toggle != toggle; | ||
106 | /* keep toggle */ | ||
107 | ir_toggle = toggle; | ||
108 | |||
109 | if (addr != | ||
110 | keyboard_layout_maps[coredev->ir.ir_kb_type].rc5_kbd_address) | ||
111 | return; /* Check for valid address */ | ||
112 | |||
113 | keycode = | ||
114 | keyboard_layout_maps | ||
115 | [coredev->ir.ir_kb_type].keyboard_layout_map[cmd]; | ||
116 | |||
117 | if (!toggle_changed && | ||
118 | (keycode != KEY_VOLUMEUP && keycode != KEY_VOLUMEDOWN)) | ||
119 | return; /* accept only repeated volume, reject other keys */ | ||
120 | |||
121 | sms_log("kernel input keycode (from ir) %d", keycode); | ||
122 | input_report_key(coredev->ir.input_dev, keycode, 1); | ||
123 | input_sync(coredev->ir.input_dev); | ||
124 | |||
125 | } | ||
126 | |||
127 | /* decode raw bit pattern to RC5 code */ | ||
128 | /* taken from ir-functions.c */ | ||
129 | static u32 ir_rc5_decode(unsigned int code) | ||
130 | { | ||
131 | /* unsigned int org_code = code;*/ | ||
132 | unsigned int pair; | ||
133 | unsigned int rc5 = 0; | ||
134 | int i; | ||
135 | |||
136 | for (i = 0; i < 14; ++i) { | ||
137 | pair = code & 0x3; | ||
138 | code >>= 2; | ||
139 | |||
140 | rc5 <<= 1; | ||
141 | switch (pair) { | ||
142 | case 0: | ||
143 | case 2: | ||
144 | break; | ||
145 | case 1: | ||
146 | rc5 |= 1; | ||
147 | break; | ||
148 | case 3: | ||
149 | /* dprintk(1, "ir-common: ir_rc5_decode(%x) bad code\n", org_code);*/ | ||
150 | sms_log("bad code"); | ||
151 | return 0; | ||
152 | } | ||
153 | } | ||
154 | /* | ||
155 | dprintk(1, "ir-common: code=%x, rc5=%x, start=%x, | ||
156 | toggle=%x, address=%x, " | ||
157 | "instr=%x\n", rc5, org_code, RC5_START(rc5), | ||
158 | RC5_TOGGLE(rc5), RC5_ADDR(rc5), RC5_INSTR(rc5)); | ||
159 | */ | ||
160 | return rc5; | ||
161 | } | ||
162 | |||
163 | static void sms_rc5_parse_word(struct smscore_device_t *coredev) | ||
164 | { | ||
165 | #define RC5_START(x) (((x)>>12)&3) | ||
166 | #define RC5_TOGGLE(x) (((x)>>11)&1) | ||
167 | #define RC5_ADDR(x) (((x)>>6)&0x1F) | ||
168 | #define RC5_INSTR(x) ((x)&0x3F) | ||
169 | |||
170 | int i, j; | ||
171 | u32 rc5_word = 0; | ||
172 | |||
173 | /* Reverse the IR word direction */ | ||
174 | for (i = 0 ; i < 28 ; i++) | ||
175 | RC5_PUSH_BIT(rc5_word, (ir_word>>i)&1, j) | ||
176 | |||
177 | rc5_word = ir_rc5_decode(rc5_word); | ||
178 | /* sms_log("temp = 0x%x, rc5_code = 0x%x", ir_word, rc5_word); */ | ||
179 | |||
180 | sms_ir_rc5_event(coredev, | ||
181 | RC5_TOGGLE(rc5_word), | ||
182 | RC5_ADDR(rc5_word), | ||
183 | RC5_INSTR(rc5_word)); | ||
184 | } | ||
185 | |||
186 | |||
187 | static void sms_rc5_accumulate_bits(struct smscore_device_t *coredev, | ||
188 | s32 ir_sample) | ||
189 | { | ||
190 | #define RC5_TIME_GRANULARITY 200 | ||
191 | #define RC5_DEF_BIT_TIME 889 | ||
192 | #define RC5_MAX_SAME_BIT_CONT 4 | ||
193 | #define RC5_WORD_LEN 27 /* 28 bit */ | ||
194 | |||
195 | u32 i, j; | ||
196 | s32 delta_time; | ||
197 | u32 time = (ir_sample > 0) ? ir_sample : (0-ir_sample); | ||
198 | u32 level = (ir_sample < 0) ? 0 : 1; | ||
199 | |||
200 | for (i = RC5_MAX_SAME_BIT_CONT; i > 0; i--) { | ||
201 | delta_time = time - (i*RC5_DEF_BIT_TIME) + RC5_TIME_GRANULARITY; | ||
202 | if (delta_time < 0) | ||
203 | continue; /* not so many consecutive bits */ | ||
204 | if (delta_time > (2 * RC5_TIME_GRANULARITY)) { | ||
205 | /* timeout */ | ||
206 | if (ir_pos == (RC5_WORD_LEN-1)) | ||
207 | /* complete last bit */ | ||
208 | RC5_PUSH_BIT(ir_word, level, ir_pos) | ||
209 | |||
210 | if (ir_pos == RC5_WORD_LEN) | ||
211 | sms_rc5_parse_word(coredev); | ||
212 | else if (ir_pos) /* timeout within a word */ | ||
213 | sms_log("IR error parsing a word"); | ||
214 | |||
215 | ir_pos = 0; | ||
216 | ir_word = 0; | ||
217 | /* sms_log("timeout %d", time); */ | ||
218 | break; | ||
219 | } | ||
220 | /* The time is within the range of this number of bits */ | ||
221 | for (j = 0 ; j < i ; j++) | ||
222 | RC5_PUSH_BIT(ir_word, level, ir_pos) | ||
223 | |||
224 | break; | ||
225 | } | ||
226 | } | ||
227 | |||
228 | void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len) | ||
229 | { | ||
230 | #define IR_DATA_RECEIVE_MAX_LEN 520 /* 128*4 + 4 + 4 */ | ||
231 | u32 i; | ||
232 | enum ir_protocol ir_protocol = | ||
233 | keyboard_layout_maps[coredev->ir.ir_kb_type] | ||
234 | .ir_protocol; | ||
235 | s32 *samples; | ||
236 | int count = len>>2; | ||
237 | |||
238 | samples = (s32 *)buf; | ||
239 | /* sms_log("IR buffer received, length = %d", count);*/ | ||
240 | |||
241 | for (i = 0; i < count; i++) | ||
242 | if (ir_protocol == IR_RC5) | ||
243 | sms_rc5_accumulate_bits(coredev, samples[i]); | ||
244 | /* IR_RCMM not implemented */ | ||
245 | } | ||
246 | |||
247 | int sms_ir_init(struct smscore_device_t *coredev) | ||
248 | { | ||
249 | struct input_dev *input_dev; | ||
250 | |||
251 | sms_log("Allocating input device"); | ||
252 | input_dev = input_allocate_device(); | ||
253 | if (!input_dev) { | ||
254 | sms_err("Not enough memory"); | ||
255 | return -ENOMEM; | ||
256 | } | ||
257 | |||
258 | coredev->ir.input_dev = input_dev; | ||
259 | coredev->ir.ir_kb_type = | ||
260 | sms_get_board(smscore_get_board_id(coredev))->ir_kb_type; | ||
261 | coredev->ir.keyboard_layout_map = | ||
262 | keyboard_layout_maps[coredev->ir.ir_kb_type]. | ||
263 | keyboard_layout_map; | ||
264 | sms_log("IR remote keyboard type is %d", coredev->ir.ir_kb_type); | ||
265 | |||
266 | coredev->ir.controller = 0; /* Todo: vega/nova SPI number */ | ||
267 | coredev->ir.timeout = IR_DEFAULT_TIMEOUT; | ||
268 | sms_log("IR port %d, timeout %d ms", | ||
269 | coredev->ir.controller, coredev->ir.timeout); | ||
270 | |||
271 | snprintf(coredev->ir.name, | ||
272 | IR_DEV_NAME_MAX_LEN, | ||
273 | "SMS IR w/kbd type %d", | ||
274 | coredev->ir.ir_kb_type); | ||
275 | input_dev->name = coredev->ir.name; | ||
276 | input_dev->phys = coredev->ir.name; | ||
277 | input_dev->dev.parent = coredev->device; | ||
278 | |||
279 | /* Key press events only */ | ||
280 | input_dev->evbit[0] = BIT_MASK(EV_KEY); | ||
281 | input_dev->keybit[BIT_WORD(BTN_0)] = BIT_MASK(BTN_0); | ||
282 | |||
283 | sms_log("Input device (IR) %s is set for key events", input_dev->name); | ||
284 | |||
285 | if (input_register_device(input_dev)) { | ||
286 | sms_err("Failed to register device"); | ||
287 | input_free_device(input_dev); | ||
288 | return -EACCES; | ||
289 | } | ||
290 | |||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | void sms_ir_exit(struct smscore_device_t *coredev) | ||
295 | { | ||
296 | if (coredev->ir.input_dev) | ||
297 | input_unregister_device(coredev->ir.input_dev); | ||
298 | |||
299 | sms_log(""); | ||
300 | } | ||
301 | |||
diff --git a/drivers/media/dvb/siano/smsir.h b/drivers/media/dvb/siano/smsir.h new file mode 100644 index 000000000000..b7d703e2d338 --- /dev/null +++ b/drivers/media/dvb/siano/smsir.h | |||
@@ -0,0 +1,93 @@ | |||
1 | /**************************************************************** | ||
2 | |||
3 | Siano Mobile Silicon, Inc. | ||
4 | MDTV receiver kernel modules. | ||
5 | Copyright (C) 2006-2009, Uri Shkolnik | ||
6 | |||
7 | This program is free software: you can redistribute it and/or modify | ||
8 | it under the terms of the GNU General Public License as published by | ||
9 | the Free Software Foundation, either version 2 of the License, or | ||
10 | (at your option) any later version. | ||
11 | |||
12 | This program is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | GNU General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU General Public License | ||
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
19 | |||
20 | ****************************************************************/ | ||
21 | |||
22 | #ifndef __SMS_IR_H__ | ||
23 | #define __SMS_IR_H__ | ||
24 | |||
25 | #include <linux/input.h> | ||
26 | |||
27 | #define IR_DEV_NAME_MAX_LEN 23 /* "SMS IR kbd type nn\0" */ | ||
28 | #define IR_KEYBOARD_LAYOUT_SIZE 64 | ||
29 | #define IR_DEFAULT_TIMEOUT 100 | ||
30 | |||
31 | enum ir_kb_type { | ||
32 | SMS_IR_KB_DEFAULT_TV, | ||
33 | SMS_IR_KB_HCW_SILVER | ||
34 | }; | ||
35 | |||
36 | enum rc5_keyboard_address { | ||
37 | KEYBOARD_ADDRESS_TV1 = 0, | ||
38 | KEYBOARD_ADDRESS_TV2 = 1, | ||
39 | KEYBOARD_ADDRESS_TELETEXT = 2, | ||
40 | KEYBOARD_ADDRESS_VIDEO = 3, | ||
41 | KEYBOARD_ADDRESS_LV1 = 4, | ||
42 | KEYBOARD_ADDRESS_VCR1 = 5, | ||
43 | KEYBOARD_ADDRESS_VCR2 = 6, | ||
44 | KEYBOARD_ADDRESS_EXPERIMENTAL = 7, | ||
45 | KEYBOARD_ADDRESS_SAT1 = 8, | ||
46 | KEYBOARD_ADDRESS_CAMERA = 9, | ||
47 | KEYBOARD_ADDRESS_SAT2 = 10, | ||
48 | KEYBOARD_ADDRESS_CDV = 12, | ||
49 | KEYBOARD_ADDRESS_CAMCORDER = 13, | ||
50 | KEYBOARD_ADDRESS_PRE_AMP = 16, | ||
51 | KEYBOARD_ADDRESS_TUNER = 17, | ||
52 | KEYBOARD_ADDRESS_RECORDER1 = 18, | ||
53 | KEYBOARD_ADDRESS_PRE_AMP1 = 19, | ||
54 | KEYBOARD_ADDRESS_CD_PLAYER = 20, | ||
55 | KEYBOARD_ADDRESS_PHONO = 21, | ||
56 | KEYBOARD_ADDRESS_SATA = 22, | ||
57 | KEYBOARD_ADDRESS_RECORDER2 = 23, | ||
58 | KEYBOARD_ADDRESS_CDR = 26, | ||
59 | KEYBOARD_ADDRESS_LIGHTING = 29, | ||
60 | KEYBOARD_ADDRESS_LIGHTING1 = 30, /* KEYBOARD_ADDRESS_HCW_SILVER */ | ||
61 | KEYBOARD_ADDRESS_PHONE = 31, | ||
62 | KEYBOARD_ADDRESS_NOT_RC5 = 0xFFFF | ||
63 | }; | ||
64 | |||
65 | enum ir_protocol { | ||
66 | IR_RC5, | ||
67 | IR_RCMM | ||
68 | }; | ||
69 | |||
70 | struct keyboard_layout_map_t { | ||
71 | enum ir_protocol ir_protocol; | ||
72 | enum rc5_keyboard_address rc5_kbd_address; | ||
73 | u16 keyboard_layout_map[IR_KEYBOARD_LAYOUT_SIZE]; | ||
74 | }; | ||
75 | |||
76 | struct smscore_device_t; | ||
77 | |||
78 | struct ir_t { | ||
79 | struct input_dev *input_dev; | ||
80 | enum ir_kb_type ir_kb_type; | ||
81 | char name[IR_DEV_NAME_MAX_LEN+1]; | ||
82 | u16 *keyboard_layout_map; | ||
83 | u32 timeout; | ||
84 | u32 controller; | ||
85 | }; | ||
86 | |||
87 | int sms_ir_init(struct smscore_device_t *coredev); | ||
88 | void sms_ir_exit(struct smscore_device_t *coredev); | ||
89 | void sms_ir_event(struct smscore_device_t *coredev, | ||
90 | const char *buf, int len); | ||
91 | |||
92 | #endif /* __SMS_IR_H__ */ | ||
93 | |||
diff --git a/drivers/media/dvb/siano/smssdio.c b/drivers/media/dvb/siano/smssdio.c new file mode 100644 index 000000000000..dfaa49a53f32 --- /dev/null +++ b/drivers/media/dvb/siano/smssdio.c | |||
@@ -0,0 +1,357 @@ | |||
1 | /* | ||
2 | * smssdio.c - Siano 1xxx SDIO interface driver | ||
3 | * | ||
4 | * Copyright 2008 Pierre Ossman | ||
5 | * | ||
6 | * Based on code by Siano Mobile Silicon, Inc., | ||
7 | * Copyright (C) 2006-2008, Uri Shkolnik | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or (at | ||
12 | * your option) any later version. | ||
13 | * | ||
14 | * | ||
15 | * This hardware is a bit odd in that all transfers should be done | ||
16 | * to/from the SMSSDIO_DATA register, yet the "increase address" bit | ||
17 | * always needs to be set. | ||
18 | * | ||
19 | * Also, buffers from the card are always aligned to 128 byte | ||
20 | * boundaries. | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * General cleanup notes: | ||
25 | * | ||
26 | * - only typedefs should be name *_t | ||
27 | * | ||
28 | * - use ERR_PTR and friends for smscore_register_device() | ||
29 | * | ||
30 | * - smscore_getbuffer should zero fields | ||
31 | * | ||
32 | * Fix stop command | ||
33 | */ | ||
34 | |||
35 | #include <linux/moduleparam.h> | ||
36 | #include <linux/firmware.h> | ||
37 | #include <linux/delay.h> | ||
38 | #include <linux/mmc/card.h> | ||
39 | #include <linux/mmc/sdio_func.h> | ||
40 | #include <linux/mmc/sdio_ids.h> | ||
41 | |||
42 | #include "smscoreapi.h" | ||
43 | #include "sms-cards.h" | ||
44 | |||
45 | /* Registers */ | ||
46 | |||
47 | #define SMSSDIO_DATA 0x00 | ||
48 | #define SMSSDIO_INT 0x04 | ||
49 | |||
50 | static const struct sdio_device_id smssdio_ids[] = { | ||
51 | {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR), | ||
52 | .driver_data = SMS1XXX_BOARD_SIANO_STELLAR}, | ||
53 | {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0), | ||
54 | .driver_data = SMS1XXX_BOARD_SIANO_NOVA_A}, | ||
55 | {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_B0), | ||
56 | .driver_data = SMS1XXX_BOARD_SIANO_NOVA_B}, | ||
57 | {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VEGA_A0), | ||
58 | .driver_data = SMS1XXX_BOARD_SIANO_VEGA}, | ||
59 | {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VENICE), | ||
60 | .driver_data = SMS1XXX_BOARD_SIANO_VEGA}, | ||
61 | { /* end: all zeroes */ }, | ||
62 | }; | ||
63 | |||
64 | MODULE_DEVICE_TABLE(sdio, smssdio_ids); | ||
65 | |||
66 | struct smssdio_device { | ||
67 | struct sdio_func *func; | ||
68 | |||
69 | struct smscore_device_t *coredev; | ||
70 | |||
71 | struct smscore_buffer_t *split_cb; | ||
72 | }; | ||
73 | |||
74 | /*******************************************************************/ | ||
75 | /* Siano core callbacks */ | ||
76 | /*******************************************************************/ | ||
77 | |||
78 | static int smssdio_sendrequest(void *context, void *buffer, size_t size) | ||
79 | { | ||
80 | int ret; | ||
81 | struct smssdio_device *smsdev; | ||
82 | |||
83 | smsdev = context; | ||
84 | |||
85 | sdio_claim_host(smsdev->func); | ||
86 | |||
87 | while (size >= smsdev->func->cur_blksize) { | ||
88 | ret = sdio_write_blocks(smsdev->func, SMSSDIO_DATA, buffer, 1); | ||
89 | if (ret) | ||
90 | goto out; | ||
91 | |||
92 | buffer += smsdev->func->cur_blksize; | ||
93 | size -= smsdev->func->cur_blksize; | ||
94 | } | ||
95 | |||
96 | if (size) { | ||
97 | ret = sdio_write_bytes(smsdev->func, SMSSDIO_DATA, | ||
98 | buffer, size); | ||
99 | } | ||
100 | |||
101 | out: | ||
102 | sdio_release_host(smsdev->func); | ||
103 | |||
104 | return ret; | ||
105 | } | ||
106 | |||
107 | /*******************************************************************/ | ||
108 | /* SDIO callbacks */ | ||
109 | /*******************************************************************/ | ||
110 | |||
111 | static void smssdio_interrupt(struct sdio_func *func) | ||
112 | { | ||
113 | int ret, isr; | ||
114 | |||
115 | struct smssdio_device *smsdev; | ||
116 | struct smscore_buffer_t *cb; | ||
117 | struct SmsMsgHdr_ST *hdr; | ||
118 | size_t size; | ||
119 | |||
120 | smsdev = sdio_get_drvdata(func); | ||
121 | |||
122 | /* | ||
123 | * The interrupt register has no defined meaning. It is just | ||
124 | * a way of turning of the level triggered interrupt. | ||
125 | */ | ||
126 | isr = sdio_readb(func, SMSSDIO_INT, &ret); | ||
127 | if (ret) { | ||
128 | dev_err(&smsdev->func->dev, | ||
129 | "Unable to read interrupt register!\n"); | ||
130 | return; | ||
131 | } | ||
132 | |||
133 | if (smsdev->split_cb == NULL) { | ||
134 | cb = smscore_getbuffer(smsdev->coredev); | ||
135 | if (!cb) { | ||
136 | dev_err(&smsdev->func->dev, | ||
137 | "Unable to allocate data buffer!\n"); | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | ret = sdio_read_blocks(smsdev->func, cb->p, SMSSDIO_DATA, 1); | ||
142 | if (ret) { | ||
143 | dev_err(&smsdev->func->dev, | ||
144 | "Error %d reading initial block!\n", ret); | ||
145 | return; | ||
146 | } | ||
147 | |||
148 | hdr = cb->p; | ||
149 | |||
150 | if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) { | ||
151 | smsdev->split_cb = cb; | ||
152 | return; | ||
153 | } | ||
154 | |||
155 | size = hdr->msgLength - smsdev->func->cur_blksize; | ||
156 | } else { | ||
157 | cb = smsdev->split_cb; | ||
158 | hdr = cb->p; | ||
159 | |||
160 | size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST); | ||
161 | |||
162 | smsdev->split_cb = NULL; | ||
163 | } | ||
164 | |||
165 | if (hdr->msgLength > smsdev->func->cur_blksize) { | ||
166 | void *buffer; | ||
167 | |||
168 | size = ALIGN(size, 128); | ||
169 | buffer = cb->p + hdr->msgLength; | ||
170 | |||
171 | BUG_ON(smsdev->func->cur_blksize != 128); | ||
172 | |||
173 | /* | ||
174 | * First attempt to transfer all of it in one go... | ||
175 | */ | ||
176 | ret = sdio_read_blocks(smsdev->func, buffer, | ||
177 | SMSSDIO_DATA, size / 128); | ||
178 | if (ret && ret != -EINVAL) { | ||
179 | smscore_putbuffer(smsdev->coredev, cb); | ||
180 | dev_err(&smsdev->func->dev, | ||
181 | "Error %d reading data from card!\n", ret); | ||
182 | return; | ||
183 | } | ||
184 | |||
185 | /* | ||
186 | * ..then fall back to one block at a time if that is | ||
187 | * not possible... | ||
188 | * | ||
189 | * (we have to do this manually because of the | ||
190 | * problem with the "increase address" bit) | ||
191 | */ | ||
192 | if (ret == -EINVAL) { | ||
193 | while (size) { | ||
194 | ret = sdio_read_blocks(smsdev->func, | ||
195 | buffer, SMSSDIO_DATA, 1); | ||
196 | if (ret) { | ||
197 | smscore_putbuffer(smsdev->coredev, cb); | ||
198 | dev_err(&smsdev->func->dev, | ||
199 | "Error %d reading " | ||
200 | "data from card!\n", ret); | ||
201 | return; | ||
202 | } | ||
203 | |||
204 | buffer += smsdev->func->cur_blksize; | ||
205 | if (size > smsdev->func->cur_blksize) | ||
206 | size -= smsdev->func->cur_blksize; | ||
207 | else | ||
208 | size = 0; | ||
209 | } | ||
210 | } | ||
211 | } | ||
212 | |||
213 | cb->size = hdr->msgLength; | ||
214 | cb->offset = 0; | ||
215 | |||
216 | smscore_onresponse(smsdev->coredev, cb); | ||
217 | } | ||
218 | |||
219 | static int smssdio_probe(struct sdio_func *func, | ||
220 | const struct sdio_device_id *id) | ||
221 | { | ||
222 | int ret; | ||
223 | |||
224 | int board_id; | ||
225 | struct smssdio_device *smsdev; | ||
226 | struct smsdevice_params_t params; | ||
227 | |||
228 | board_id = id->driver_data; | ||
229 | |||
230 | smsdev = kzalloc(sizeof(struct smssdio_device), GFP_KERNEL); | ||
231 | if (!smsdev) | ||
232 | return -ENOMEM; | ||
233 | |||
234 | smsdev->func = func; | ||
235 | |||
236 | memset(¶ms, 0, sizeof(struct smsdevice_params_t)); | ||
237 | |||
238 | params.device = &func->dev; | ||
239 | params.buffer_size = 0x5000; /* ?? */ | ||
240 | params.num_buffers = 22; /* ?? */ | ||
241 | params.context = smsdev; | ||
242 | |||
243 | snprintf(params.devpath, sizeof(params.devpath), | ||
244 | "sdio\\%s", sdio_func_id(func)); | ||
245 | |||
246 | params.sendrequest_handler = smssdio_sendrequest; | ||
247 | |||
248 | params.device_type = sms_get_board(board_id)->type; | ||
249 | |||
250 | if (params.device_type != SMS_STELLAR) | ||
251 | params.flags |= SMS_DEVICE_FAMILY2; | ||
252 | else { | ||
253 | /* | ||
254 | * FIXME: Stellar needs special handling... | ||
255 | */ | ||
256 | ret = -ENODEV; | ||
257 | goto free; | ||
258 | } | ||
259 | |||
260 | ret = smscore_register_device(¶ms, &smsdev->coredev); | ||
261 | if (ret < 0) | ||
262 | goto free; | ||
263 | |||
264 | smscore_set_board_id(smsdev->coredev, board_id); | ||
265 | |||
266 | sdio_claim_host(func); | ||
267 | |||
268 | ret = sdio_enable_func(func); | ||
269 | if (ret) | ||
270 | goto release; | ||
271 | |||
272 | ret = sdio_set_block_size(func, 128); | ||
273 | if (ret) | ||
274 | goto disable; | ||
275 | |||
276 | ret = sdio_claim_irq(func, smssdio_interrupt); | ||
277 | if (ret) | ||
278 | goto disable; | ||
279 | |||
280 | sdio_set_drvdata(func, smsdev); | ||
281 | |||
282 | sdio_release_host(func); | ||
283 | |||
284 | ret = smscore_start_device(smsdev->coredev); | ||
285 | if (ret < 0) | ||
286 | goto reclaim; | ||
287 | |||
288 | return 0; | ||
289 | |||
290 | reclaim: | ||
291 | sdio_claim_host(func); | ||
292 | sdio_release_irq(func); | ||
293 | disable: | ||
294 | sdio_disable_func(func); | ||
295 | release: | ||
296 | sdio_release_host(func); | ||
297 | smscore_unregister_device(smsdev->coredev); | ||
298 | free: | ||
299 | kfree(smsdev); | ||
300 | |||
301 | return ret; | ||
302 | } | ||
303 | |||
304 | static void smssdio_remove(struct sdio_func *func) | ||
305 | { | ||
306 | struct smssdio_device *smsdev; | ||
307 | |||
308 | smsdev = sdio_get_drvdata(func); | ||
309 | |||
310 | /* FIXME: racy! */ | ||
311 | if (smsdev->split_cb) | ||
312 | smscore_putbuffer(smsdev->coredev, smsdev->split_cb); | ||
313 | |||
314 | smscore_unregister_device(smsdev->coredev); | ||
315 | |||
316 | sdio_claim_host(func); | ||
317 | sdio_release_irq(func); | ||
318 | sdio_disable_func(func); | ||
319 | sdio_release_host(func); | ||
320 | |||
321 | kfree(smsdev); | ||
322 | } | ||
323 | |||
324 | static struct sdio_driver smssdio_driver = { | ||
325 | .name = "smssdio", | ||
326 | .id_table = smssdio_ids, | ||
327 | .probe = smssdio_probe, | ||
328 | .remove = smssdio_remove, | ||
329 | }; | ||
330 | |||
331 | /*******************************************************************/ | ||
332 | /* Module functions */ | ||
333 | /*******************************************************************/ | ||
334 | |||
335 | int smssdio_module_init(void) | ||
336 | { | ||
337 | int ret = 0; | ||
338 | |||
339 | printk(KERN_INFO "smssdio: Siano SMS1xxx SDIO driver\n"); | ||
340 | printk(KERN_INFO "smssdio: Copyright Pierre Ossman\n"); | ||
341 | |||
342 | ret = sdio_register_driver(&smssdio_driver); | ||
343 | |||
344 | return ret; | ||
345 | } | ||
346 | |||
347 | void smssdio_module_exit(void) | ||
348 | { | ||
349 | sdio_unregister_driver(&smssdio_driver); | ||
350 | } | ||
351 | |||
352 | module_init(smssdio_module_init); | ||
353 | module_exit(smssdio_module_exit); | ||
354 | |||
355 | MODULE_DESCRIPTION("Siano SMS1xxx SDIO driver"); | ||
356 | MODULE_AUTHOR("Pierre Ossman"); | ||
357 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c index 71c65f544c07..cb8a358b7310 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/dvb/siano/smsusb.c | |||
@@ -1,23 +1,23 @@ | |||
1 | /* | 1 | /**************************************************************** |
2 | * Driver for the Siano SMS1xxx USB dongle | 2 | |
3 | * | 3 | Siano Mobile Silicon, Inc. |
4 | * author: Anatoly Greenblat | 4 | MDTV receiver kernel modules. |
5 | * | 5 | Copyright (C) 2005-2009, Uri Shkolnik, Anatoly Greenblat |
6 | * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. | 6 | |
7 | * | 7 | This program is free software: you can redistribute it and/or modify |
8 | * This program is free software; you can redistribute it and/or modify | 8 | it under the terms of the GNU General Public License as published by |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | the Free Software Foundation, either version 2 of the License, or |
10 | * published by the Free Software Foundation; | 10 | (at your option) any later version. |
11 | * | 11 | |
12 | * Software distributed under the License is distributed on an "AS IS" | 12 | This program is distributed in the hope that it will be useful, |
13 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. | 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * | 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * See the GNU General Public License for more details. | 15 | GNU General Public License for more details. |
16 | * | 16 | |
17 | * You should have received a copy of the GNU General Public License | 17 | You should have received a copy of the GNU General Public License |
18 | * along with this program; if not, write to the Free Software | 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | |
20 | */ | 20 | ****************************************************************/ |
21 | 21 | ||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include "smscoreapi.h" | 27 | #include "smscoreapi.h" |
28 | #include "sms-cards.h" | 28 | #include "sms-cards.h" |
29 | #include "smsendian.h" | ||
29 | 30 | ||
30 | static int sms_dbg; | 31 | static int sms_dbg; |
31 | module_param_named(debug, sms_dbg, int, 0644); | 32 | module_param_named(debug, sms_dbg, int, 0644); |
@@ -64,15 +65,16 @@ static void smsusb_onresponse(struct urb *urb) | |||
64 | struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context; | 65 | struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context; |
65 | struct smsusb_device_t *dev = surb->dev; | 66 | struct smsusb_device_t *dev = surb->dev; |
66 | 67 | ||
67 | if (urb->status < 0) { | 68 | if (urb->status == -ESHUTDOWN) { |
68 | sms_err("error, urb status %d, %d bytes", | 69 | sms_err("error, urb status %d (-ESHUTDOWN), %d bytes", |
69 | urb->status, urb->actual_length); | 70 | urb->status, urb->actual_length); |
70 | return; | 71 | return; |
71 | } | 72 | } |
72 | 73 | ||
73 | if (urb->actual_length > 0) { | 74 | if ((urb->actual_length > 0) && (urb->status == 0)) { |
74 | struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) surb->cb->p; | 75 | struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)surb->cb->p; |
75 | 76 | ||
77 | smsendian_handle_message_header(phdr); | ||
76 | if (urb->actual_length >= phdr->msgLength) { | 78 | if (urb->actual_length >= phdr->msgLength) { |
77 | surb->cb->size = phdr->msgLength; | 79 | surb->cb->size = phdr->msgLength; |
78 | 80 | ||
@@ -109,7 +111,10 @@ static void smsusb_onresponse(struct urb *urb) | |||
109 | "msglen %d actual %d", | 111 | "msglen %d actual %d", |
110 | phdr->msgLength, urb->actual_length); | 112 | phdr->msgLength, urb->actual_length); |
111 | } | 113 | } |
112 | } | 114 | } else |
115 | sms_err("error, urb status %d, %d bytes", | ||
116 | urb->status, urb->actual_length); | ||
117 | |||
113 | 118 | ||
114 | exit_and_resubmit: | 119 | exit_and_resubmit: |
115 | smsusb_submit_urb(dev, surb); | 120 | smsusb_submit_urb(dev, surb); |
@@ -176,6 +181,7 @@ static int smsusb_sendrequest(void *context, void *buffer, size_t size) | |||
176 | struct smsusb_device_t *dev = (struct smsusb_device_t *) context; | 181 | struct smsusb_device_t *dev = (struct smsusb_device_t *) context; |
177 | int dummy; | 182 | int dummy; |
178 | 183 | ||
184 | smsendian_handle_message_header((struct SmsMsgHdr_ST *)buffer); | ||
179 | return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2), | 185 | return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2), |
180 | buffer, size, &dummy, 1000); | 186 | buffer, size, &dummy, 1000); |
181 | } | 187 | } |
@@ -333,8 +339,8 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) | |||
333 | case SMS_VEGA: | 339 | case SMS_VEGA: |
334 | dev->buffer_size = USB2_BUFFER_SIZE; | 340 | dev->buffer_size = USB2_BUFFER_SIZE; |
335 | dev->response_alignment = | 341 | dev->response_alignment = |
336 | dev->udev->ep_in[1]->desc.wMaxPacketSize - | 342 | le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) - |
337 | sizeof(struct SmsMsgHdr_ST); | 343 | sizeof(struct SmsMsgHdr_ST); |
338 | 344 | ||
339 | params.flags |= SMS_DEVICE_FAMILY2; | 345 | params.flags |= SMS_DEVICE_FAMILY2; |
340 | break; | 346 | break; |
@@ -479,7 +485,6 @@ static int smsusb_resume(struct usb_interface *intf) | |||
479 | } | 485 | } |
480 | 486 | ||
481 | struct usb_device_id smsusb_id_table[] = { | 487 | struct usb_device_id smsusb_id_table[] = { |
482 | #ifdef CONFIG_DVB_SIANO_SMS1XXX_SMS_IDS | ||
483 | { USB_DEVICE(0x187f, 0x0010), | 488 | { USB_DEVICE(0x187f, 0x0010), |
484 | .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, | 489 | .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, |
485 | { USB_DEVICE(0x187f, 0x0100), | 490 | { USB_DEVICE(0x187f, 0x0100), |
@@ -490,7 +495,6 @@ struct usb_device_id smsusb_id_table[] = { | |||
490 | .driver_info = SMS1XXX_BOARD_SIANO_NOVA_B }, | 495 | .driver_info = SMS1XXX_BOARD_SIANO_NOVA_B }, |
491 | { USB_DEVICE(0x187f, 0x0300), | 496 | { USB_DEVICE(0x187f, 0x0300), |
492 | .driver_info = SMS1XXX_BOARD_SIANO_VEGA }, | 497 | .driver_info = SMS1XXX_BOARD_SIANO_VEGA }, |
493 | #endif | ||
494 | { USB_DEVICE(0x2040, 0x1700), | 498 | { USB_DEVICE(0x2040, 0x1700), |
495 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT }, | 499 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT }, |
496 | { USB_DEVICE(0x2040, 0x1800), | 500 | { USB_DEVICE(0x2040, 0x1800), |
@@ -521,8 +525,13 @@ struct usb_device_id smsusb_id_table[] = { | |||
521 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, | 525 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, |
522 | { USB_DEVICE(0x2040, 0x5590), | 526 | { USB_DEVICE(0x2040, 0x5590), |
523 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, | 527 | .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, |
524 | { } /* Terminating entry */ | 528 | { USB_DEVICE(0x187f, 0x0202), |
525 | }; | 529 | .driver_info = SMS1XXX_BOARD_SIANO_NICE }, |
530 | { USB_DEVICE(0x187f, 0x0301), | ||
531 | .driver_info = SMS1XXX_BOARD_SIANO_VENICE }, | ||
532 | { } /* Terminating entry */ | ||
533 | }; | ||
534 | |||
526 | MODULE_DEVICE_TABLE(usb, smsusb_id_table); | 535 | MODULE_DEVICE_TABLE(usb, smsusb_id_table); |
527 | 536 | ||
528 | static struct usb_driver smsusb_driver = { | 537 | static struct usb_driver smsusb_driver = { |
@@ -548,14 +557,14 @@ int smsusb_module_init(void) | |||
548 | 557 | ||
549 | void smsusb_module_exit(void) | 558 | void smsusb_module_exit(void) |
550 | { | 559 | { |
551 | sms_debug(""); | ||
552 | /* Regular USB Cleanup */ | 560 | /* Regular USB Cleanup */ |
553 | usb_deregister(&smsusb_driver); | 561 | usb_deregister(&smsusb_driver); |
562 | sms_info("end"); | ||
554 | } | 563 | } |
555 | 564 | ||
556 | module_init(smsusb_module_init); | 565 | module_init(smsusb_module_init); |
557 | module_exit(smsusb_module_exit); | 566 | module_exit(smsusb_module_exit); |
558 | 567 | ||
559 | MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle"); | 568 | MODULE_DESCRIPTION("Driver for the Siano SMS1xxx USB dongle"); |
560 | MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)"); | 569 | MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)"); |
561 | MODULE_LICENSE("GPL"); | 570 | MODULE_LICENSE("GPL"); |