aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/siano
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/siano')
-rw-r--r--drivers/media/dvb/siano/Makefile2
-rw-r--r--drivers/media/dvb/siano/sms-cards.c188
-rw-r--r--drivers/media/dvb/siano/sms-cards.h64
-rw-r--r--drivers/media/dvb/siano/smscoreapi.c468
-rw-r--r--drivers/media/dvb/siano/smscoreapi.h488
-rw-r--r--drivers/media/dvb/siano/smsdvb.c372
-rw-r--r--drivers/media/dvb/siano/smsendian.c102
-rw-r--r--drivers/media/dvb/siano/smsendian.h32
-rw-r--r--drivers/media/dvb/siano/smsir.c301
-rw-r--r--drivers/media/dvb/siano/smsir.h93
-rw-r--r--drivers/media/dvb/siano/smssdio.c357
-rw-r--r--drivers/media/dvb/siano/smsusb.c75
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 @@
1sms1xxx-objs := smscoreapi.o sms-cards.o 1sms1xxx-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o
2 2
3obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o 3obj-$(CONFIG_DVB_SIANO_SMS1XXX) += sms1xxx.o
4obj-$(CONFIG_DVB_SIANO_SMS1XXX) += smsusb.o 4obj-$(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
22static int sms_dbg; 23static int sms_dbg;
23module_param_named(cards_dbg, sms_dbg, int, 0644); 24module_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
87struct sms_board *sms_get_board(int id) 100struct 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}
93EXPORT_SYMBOL_GPL(sms_get_board); 106EXPORT_SYMBOL_GPL(sms_get_board);
107static 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
117int 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}
273EXPORT_SYMBOL_GPL(sms_board_event);
94 274
95static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable) 275static 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
41struct 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
38struct sms_board { 74struct 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
46struct sms_board *sms_get_board(int id); 84struct sms_board *sms_get_board(int id);
47 85
86extern struct smscore_device_t *coredev;
87
88enum 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
109int sms_board_event(struct smscore_device_t *coredev,
110 enum SMS_BOARD_EVENTS gevent);
111
48int sms_board_setup(struct smscore_device_t *coredev); 112int 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
37static int sms_dbg; 41static int sms_dbg;
38module_param_named(debug, sms_dbg, int, 0644); 42module_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
61struct 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
97void smscore_set_board_id(struct smscore_device_t *core, int id) 65void 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}
440EXPORT_SYMBOL_GPL(smscore_register_device); 415EXPORT_SYMBOL_GPL(smscore_register_device);
441 416
417
418static 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 */
436static 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}
469EXPORT_SYMBOL_GPL(smscore_start_device); 510EXPORT_SYMBOL_GPL(smscore_start_device);
470 511
471static 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
486static int smscore_load_firmware_family2(struct smscore_device_t *coredev, 513static 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 */
942void smscore_onresponse(struct smscore_device_t *coredev, 980void 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 */
1054void smscore_putbuffer(struct smscore_device_t *coredev, 1140void 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}
1059EXPORT_SYMBOL_GPL(smscore_putbuffer); 1145EXPORT_SYMBOL_GPL(smscore_putbuffer);
@@ -1210,8 +1296,9 @@ int smsclient_sendrequest(struct smscore_client_t *client,
1210EXPORT_SYMBOL_GPL(smsclient_sendrequest); 1296EXPORT_SYMBOL_GPL(smsclient_sendrequest);
1211 1297
1212 1298
1299/* old GPIO managments implementation */
1213int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin, 1300int 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
1283static int __init smscore_module_init(void) 1370/* new GPIO managment implementation */
1284{ 1371static 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
1421int 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
1498int 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
1548int 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
1305static void __exit smscore_module_exit(void) 1602static 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 1616static 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 * 3Siano Mobile Silicon, Inc.
4 * author: Anatoly Greenblat 4MDTV receiver kernel modules.
5 * 5Copyright (C) 2006-2008, Uri Shkolnik, Anatoly Greenblat
6 * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. 6
7 * 7This program is free software: you can redistribute it and/or modify
8 * This program is free software; you can redistribute it and/or modify 8it 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 9the 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. 13but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * See the GNU General Public License for more details. 15GNU General Public License for more details.
16 * 16
17 * You should have received a copy of the GNU General Public License 17You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software 18along 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
58enum sms_device_type_st { 58enum sms_device_type_st {
@@ -83,13 +83,13 @@ typedef void (*onremove_t)(void *context);
83struct smscore_buffer_t { 83struct 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
95struct smsdevice_params_t { 95struct 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
122struct 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
258enum 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
201enum SMS_DEVICE_MODE { 268enum 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
223struct SmsMsgData_ST { 290struct SmsMsgData_ST {
224 struct SmsMsgHdr_ST xMsgHeader; 291 struct SmsMsgHdr_ST xMsgHeader;
225 u32 msgData[1]; 292 u32 msgData[1];
293};
294
295struct SmsMsgData_ST2 {
296 struct SmsMsgHdr_ST xMsgHeader;
297 u32 msgData[2];
226}; 298};
227 299
228struct SmsDataDownload_ST { 300struct 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
267struct SMSHOSTLIB_STATISTICS_ST { 340/* Statistics information returned as response for
268 u32 Reserved; /* Reserved */ 341 * SmsHostApiGetStatistics_Req */
342struct 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
334struct SmsMsgStatisticsInfo_ST { 427struct 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; 442struct 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
458struct 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
481struct 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
346struct smscore_gpio_config { 507
508/* Statistics information returned as response for
509 * SmsHostApiGetStatisticsEx_Req for DVB applications, SMS1100 and up */
510struct 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
522struct 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
538struct 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
545struct 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
552struct 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
578struct 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
372extern void smscore_registry_setmode(char *devpath, int mode); 619extern void smscore_registry_setmode(char *devpath, int mode);
373extern int smscore_registry_getmode(char *devpath); 620extern int smscore_registry_getmode(char *devpath);
374 621
@@ -410,10 +657,19 @@ struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev);
410extern void smscore_putbuffer(struct smscore_device_t *coredev, 657extern 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 */
413int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin, 661int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
414 struct smscore_gpio_config *pinconfig); 662 struct smscore_config_gpio *pinconfig);
415int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level); 663int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level);
416 664
665/* new GPIO managment */
666extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
667 struct smscore_gpio_config *pGpioConfig);
668extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
669 u8 NewLevel);
670extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
671 u8 *level);
672
417void smscore_set_board_id(struct smscore_device_t *core, int id); 673void smscore_set_board_id(struct smscore_device_t *core, int id);
418int smscore_get_board_id(struct smscore_device_t *core); 674int 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 * 3Siano Mobile Silicon, Inc.
4 * Author: Uri Shkolni 4MDTV receiver kernel modules.
5 * 5Copyright (C) 2006-2008, Uri Shkolnik
6 * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. 6
7 * 7This program is free software: you can redistribute it and/or modify
8 * This program is free software; you can redistribute it and/or modify 8it 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 9the 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. 13but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * See the GNU General Public License for more details. 15GNU General Public License for more details.
16 * 16
17 * You should have received a copy of the GNU General Public License 17You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software 18along 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
28DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 34DVB_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
50static struct list_head g_smsdvb_clients; 59static struct list_head g_smsdvb_clients;
@@ -54,11 +63,69 @@ static int sms_dbg;
54module_param_named(debug, sms_dbg, int, 0644); 63module_param_named(debug, sms_dbg, int, 0644);
55MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); 64MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");
56 65
66/* Events that may come from DVB v3 adapter */
67static 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
57static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) 119static 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
189static 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
208static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) 328static 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
220static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) 338static 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
232static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 348static 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
244static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) 365static 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
256static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 375static 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
268static int smsdvb_get_tune_settings(struct dvb_frontend *fe, 385static 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);
547module_exit(smsdvb_module_exit); 649module_exit(smsdvb_module_exit);
548 650
549MODULE_DESCRIPTION("SMS DVB subsystem adaptation module"); 651MODULE_DESCRIPTION("SMS DVB subsystem adaptation module");
550MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)"); 652MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)");
551MODULE_LICENSE("GPL"); 653MODULE_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
27void 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}
52EXPORT_SYMBOL_GPL(smsendian_handle_tx_message);
53
54void 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}
90EXPORT_SYMBOL_GPL(smsendian_handle_rx_message);
91
92void 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}
102EXPORT_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
3Siano Mobile Silicon, Inc.
4MDTV receiver kernel modules.
5Copyright (C) 2006-2009, Uri Shkolnik
6
7This program is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the 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,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along 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
27extern void smsendian_handle_tx_message(void *buffer);
28extern void smsendian_handle_rx_message(void *buffer);
29extern 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
36static 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
88u32 ir_pos;
89u32 ir_word;
90u32 ir_toggle;
91
92#define RC5_PUSH_BIT(dst, bit, pos) \
93 { dst <<= 1; dst |= bit; pos++; }
94
95
96static 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 */
129static 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
163static 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
187static 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
228void 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
247int 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
294void 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
3Siano Mobile Silicon, Inc.
4MDTV receiver kernel modules.
5Copyright (C) 2006-2009, Uri Shkolnik
6
7This program is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the 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,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along 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
31enum ir_kb_type {
32 SMS_IR_KB_DEFAULT_TV,
33 SMS_IR_KB_HCW_SILVER
34};
35
36enum 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
65enum ir_protocol {
66 IR_RC5,
67 IR_RCMM
68};
69
70struct 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
76struct smscore_device_t;
77
78struct 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
87int sms_ir_init(struct smscore_device_t *coredev);
88void sms_ir_exit(struct smscore_device_t *coredev);
89void 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
50static 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
64MODULE_DEVICE_TABLE(sdio, smssdio_ids);
65
66struct 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
78static 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
101out:
102 sdio_release_host(smsdev->func);
103
104 return ret;
105}
106
107/*******************************************************************/
108/* SDIO callbacks */
109/*******************************************************************/
110
111static 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
219static 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(&params, 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(&params, &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
290reclaim:
291 sdio_claim_host(func);
292 sdio_release_irq(func);
293disable:
294 sdio_disable_func(func);
295release:
296 sdio_release_host(func);
297 smscore_unregister_device(smsdev->coredev);
298free:
299 kfree(smsdev);
300
301 return ret;
302}
303
304static 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
324static 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
335int 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
347void smssdio_module_exit(void)
348{
349 sdio_unregister_driver(&smssdio_driver);
350}
351
352module_init(smssdio_module_init);
353module_exit(smssdio_module_exit);
354
355MODULE_DESCRIPTION("Siano SMS1xxx SDIO driver");
356MODULE_AUTHOR("Pierre Ossman");
357MODULE_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 * 3Siano Mobile Silicon, Inc.
4 * author: Anatoly Greenblat 4MDTV receiver kernel modules.
5 * 5Copyright (C) 2005-2009, Uri Shkolnik, Anatoly Greenblat
6 * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. 6
7 * 7This program is free software: you can redistribute it and/or modify
8 * This program is free software; you can redistribute it and/or modify 8it 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 9the 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. 13but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * See the GNU General Public License for more details. 15GNU General Public License for more details.
16 * 16
17 * You should have received a copy of the GNU General Public License 17You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software 18along 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
30static int sms_dbg; 31static int sms_dbg;
31module_param_named(debug, sms_dbg, int, 0644); 32module_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
114exit_and_resubmit: 119exit_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
481struct usb_device_id smsusb_id_table[] = { 487struct 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
526MODULE_DEVICE_TABLE(usb, smsusb_id_table); 535MODULE_DEVICE_TABLE(usb, smsusb_id_table);
527 536
528static struct usb_driver smsusb_driver = { 537static struct usb_driver smsusb_driver = {
@@ -548,14 +557,14 @@ int smsusb_module_init(void)
548 557
549void smsusb_module_exit(void) 558void 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
556module_init(smsusb_module_init); 565module_init(smsusb_module_init);
557module_exit(smsusb_module_exit); 566module_exit(smsusb_module_exit);
558 567
559MODULE_DESCRIPTION("Driver for the Siano SMS1XXX USB dongle"); 568MODULE_DESCRIPTION("Driver for the Siano SMS1xxx USB dongle");
560MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)"); 569MODULE_AUTHOR("Siano Mobile Silicon, INC. (uris@siano-ms.com)");
561MODULE_LICENSE("GPL"); 570MODULE_LICENSE("GPL");