diff options
| author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-06-14 15:36:01 -0400 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-13 22:52:52 -0400 |
| commit | 0013ca8c52ba7bb1030ed75d6df7e58af0314018 (patch) | |
| tree | 31672d38162cff3dee895d1d815a8dd85ba67d5d /drivers/media/usb/siano | |
| parent | ed0c8b5465d6cec5458d9a3041a5167d83f40fdb (diff) | |
[media] siano: break it into common, mmc and usb
siano is, in fact, 2 drivers: one for MMC and one for USB, plus
a common bus-independent code. Break it accordingly.
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/usb/siano')
| -rw-r--r-- | drivers/media/usb/siano/Kconfig | 26 | ||||
| -rw-r--r-- | drivers/media/usb/siano/Makefile | 7 | ||||
| -rw-r--r-- | drivers/media/usb/siano/sms-cards.c | 311 | ||||
| -rw-r--r-- | drivers/media/usb/siano/sms-cards.h | 123 | ||||
| -rw-r--r-- | drivers/media/usb/siano/smscoreapi.c | 1637 | ||||
| -rw-r--r-- | drivers/media/usb/siano/smscoreapi.h | 775 | ||||
| -rw-r--r-- | drivers/media/usb/siano/smsdvb.c | 1078 | ||||
| -rw-r--r-- | drivers/media/usb/siano/smsendian.c | 103 | ||||
| -rw-r--r-- | drivers/media/usb/siano/smsendian.h | 32 | ||||
| -rw-r--r-- | drivers/media/usb/siano/smsir.c | 114 | ||||
| -rw-r--r-- | drivers/media/usb/siano/smsir.h | 55 | ||||
| -rw-r--r-- | drivers/media/usb/siano/smssdio.c | 365 |
12 files changed, 2 insertions, 4624 deletions
diff --git a/drivers/media/usb/siano/Kconfig b/drivers/media/usb/siano/Kconfig index bc6456eb2c4f..3c76e62d820d 100644 --- a/drivers/media/usb/siano/Kconfig +++ b/drivers/media/usb/siano/Kconfig | |||
| @@ -2,33 +2,9 @@ | |||
| 2 | # Siano Mobile Silicon Digital TV device configuration | 2 | # Siano Mobile Silicon Digital TV device configuration |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | config SMS_SIANO_MDTV | 5 | config SMS_USB_DRV |
| 6 | tristate "Siano SMS1xxx based MDTV receiver" | 6 | tristate "Siano SMS1xxx based MDTV receiver" |
| 7 | depends on DVB_CORE && RC_CORE && HAS_DMA | 7 | depends on DVB_CORE && RC_CORE && HAS_DMA |
| 8 | ---help--- | 8 | ---help--- |
| 9 | Choose Y or M here if you have MDTV receiver with a Siano chipset. | ||
| 10 | |||
| 11 | To compile this driver as a module, choose M here | ||
| 12 | (The module will be called smsmdtv). | ||
| 13 | |||
| 14 | Further documentation on this driver can be found on the WWW | ||
| 15 | at http://www.siano-ms.com/ | ||
| 16 | |||
| 17 | if SMS_SIANO_MDTV | ||
| 18 | menu "Siano module components" | ||
| 19 | |||
| 20 | # Hardware interfaces support | ||
| 21 | |||
| 22 | config SMS_USB_DRV | ||
| 23 | tristate "USB interface support" | ||
| 24 | depends on DVB_CORE && USB | ||
| 25 | ---help--- | ||
| 26 | Choose if you would like to have Siano's support for USB interface | 9 | Choose if you would like to have Siano's support for USB interface |
| 27 | 10 | ||
| 28 | config SMS_SDIO_DRV | ||
| 29 | tristate "SDIO interface support" | ||
| 30 | depends on DVB_CORE && MMC | ||
| 31 | ---help--- | ||
| 32 | Choose if you would like to have Siano's support for SDIO interface | ||
| 33 | endmenu | ||
| 34 | endif # SMS_SIANO_MDTV | ||
diff --git a/drivers/media/usb/siano/Makefile b/drivers/media/usb/siano/Makefile index 14756bdb6eaa..758b6a090c59 100644 --- a/drivers/media/usb/siano/Makefile +++ b/drivers/media/usb/siano/Makefile | |||
| @@ -1,11 +1,6 @@ | |||
| 1 | |||
| 2 | smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o | ||
| 3 | |||
| 4 | obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o | ||
| 5 | obj-$(CONFIG_SMS_USB_DRV) += smsusb.o | 1 | obj-$(CONFIG_SMS_USB_DRV) += smsusb.o |
| 6 | obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o | ||
| 7 | 2 | ||
| 8 | ccflags-y += -Idrivers/media/dvb-core | 3 | ccflags-y += -Idrivers/media/dvb-core |
| 9 | 4 | ccflags-y += -Idrivers/media/common/siano | |
| 10 | ccflags-y += $(extra-cflags-y) $(extra-cflags-m) | 5 | ccflags-y += $(extra-cflags-y) $(extra-cflags-m) |
| 11 | 6 | ||
diff --git a/drivers/media/usb/siano/sms-cards.c b/drivers/media/usb/siano/sms-cards.c deleted file mode 100644 index 680c781c8dd6..000000000000 --- a/drivers/media/usb/siano/sms-cards.c +++ /dev/null | |||
| @@ -1,311 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Card-specific functions for the Siano SMS1xxx USB dongle | ||
| 3 | * | ||
| 4 | * Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation; | ||
| 9 | * | ||
| 10 | * Software distributed under the License is distributed on an "AS IS" | ||
| 11 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. | ||
| 12 | * | ||
| 13 | * See the GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include "sms-cards.h" | ||
| 21 | #include "smsir.h" | ||
| 22 | #include <linux/module.h> | ||
| 23 | |||
| 24 | static int sms_dbg; | ||
| 25 | module_param_named(cards_dbg, sms_dbg, int, 0644); | ||
| 26 | MODULE_PARM_DESC(cards_dbg, "set debug level (info=1, adv=2 (or-able))"); | ||
| 27 | |||
| 28 | static struct sms_board sms_boards[] = { | ||
| 29 | [SMS_BOARD_UNKNOWN] = { | ||
| 30 | .name = "Unknown board", | ||
| 31 | }, | ||
| 32 | [SMS1XXX_BOARD_SIANO_STELLAR] = { | ||
| 33 | .name = "Siano Stellar Digital Receiver", | ||
| 34 | .type = SMS_STELLAR, | ||
| 35 | }, | ||
| 36 | [SMS1XXX_BOARD_SIANO_NOVA_A] = { | ||
| 37 | .name = "Siano Nova A Digital Receiver", | ||
| 38 | .type = SMS_NOVA_A0, | ||
| 39 | }, | ||
| 40 | [SMS1XXX_BOARD_SIANO_NOVA_B] = { | ||
| 41 | .name = "Siano Nova B Digital Receiver", | ||
| 42 | .type = SMS_NOVA_B0, | ||
| 43 | }, | ||
| 44 | [SMS1XXX_BOARD_SIANO_VEGA] = { | ||
| 45 | .name = "Siano Vega Digital Receiver", | ||
| 46 | .type = SMS_VEGA, | ||
| 47 | }, | ||
| 48 | [SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT] = { | ||
| 49 | .name = "Hauppauge Catamount", | ||
| 50 | .type = SMS_STELLAR, | ||
| 51 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-stellar-dvbt-01.fw", | ||
| 52 | }, | ||
| 53 | [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A] = { | ||
| 54 | .name = "Hauppauge Okemo-A", | ||
| 55 | .type = SMS_NOVA_A0, | ||
| 56 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-a-dvbt-01.fw", | ||
| 57 | }, | ||
| 58 | [SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B] = { | ||
| 59 | .name = "Hauppauge Okemo-B", | ||
| 60 | .type = SMS_NOVA_B0, | ||
| 61 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-nova-b-dvbt-01.fw", | ||
| 62 | }, | ||
| 63 | [SMS1XXX_BOARD_HAUPPAUGE_WINDHAM] = { | ||
| 64 | .name = "Hauppauge WinTV MiniStick", | ||
| 65 | .type = SMS_NOVA_B0, | ||
| 66 | .fw[DEVICE_MODE_ISDBT_BDA] = "sms1xxx-hcw-55xxx-isdbt-02.fw", | ||
| 67 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", | ||
| 68 | .rc_codes = RC_MAP_HAUPPAUGE, | ||
| 69 | .board_cfg.leds_power = 26, | ||
| 70 | .board_cfg.led0 = 27, | ||
| 71 | .board_cfg.led1 = 28, | ||
| 72 | .board_cfg.ir = 9, | ||
| 73 | .led_power = 26, | ||
| 74 | .led_lo = 27, | ||
| 75 | .led_hi = 28, | ||
| 76 | }, | ||
| 77 | [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD] = { | ||
| 78 | .name = "Hauppauge WinTV MiniCard", | ||
| 79 | .type = SMS_NOVA_B0, | ||
| 80 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", | ||
| 81 | .lna_ctrl = 29, | ||
| 82 | .board_cfg.foreign_lna0_ctrl = 29, | ||
| 83 | .rf_switch = 17, | ||
| 84 | .board_cfg.rf_switch_uhf = 17, | ||
| 85 | }, | ||
| 86 | [SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2] = { | ||
| 87 | .name = "Hauppauge WinTV MiniCard", | ||
| 88 | .type = SMS_NOVA_B0, | ||
| 89 | .fw[DEVICE_MODE_DVBT_BDA] = "sms1xxx-hcw-55xxx-dvbt-02.fw", | ||
| 90 | .lna_ctrl = -1, | ||
| 91 | }, | ||
| 92 | [SMS1XXX_BOARD_SIANO_NICE] = { | ||
| 93 | /* 11 */ | ||
| 94 | .name = "Siano Nice Digital Receiver", | ||
| 95 | .type = SMS_NOVA_B0, | ||
| 96 | }, | ||
| 97 | [SMS1XXX_BOARD_SIANO_VENICE] = { | ||
| 98 | /* 12 */ | ||
| 99 | .name = "Siano Venice Digital Receiver", | ||
| 100 | .type = SMS_VEGA, | ||
| 101 | }, | ||
| 102 | }; | ||
| 103 | |||
| 104 | struct sms_board *sms_get_board(unsigned id) | ||
| 105 | { | ||
| 106 | BUG_ON(id >= ARRAY_SIZE(sms_boards)); | ||
| 107 | |||
| 108 | return &sms_boards[id]; | ||
| 109 | } | ||
| 110 | EXPORT_SYMBOL_GPL(sms_get_board); | ||
| 111 | static inline void sms_gpio_assign_11xx_default_led_config( | ||
| 112 | struct smscore_gpio_config *pGpioConfig) { | ||
| 113 | pGpioConfig->Direction = SMS_GPIO_DIRECTION_OUTPUT; | ||
| 114 | pGpioConfig->InputCharacteristics = | ||
| 115 | SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL; | ||
| 116 | pGpioConfig->OutputDriving = SMS_GPIO_OUTPUT_DRIVING_4mA; | ||
| 117 | pGpioConfig->OutputSlewRate = SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS; | ||
| 118 | pGpioConfig->PullUpDown = SMS_GPIO_PULL_UP_DOWN_NONE; | ||
| 119 | } | ||
| 120 | |||
| 121 | int sms_board_event(struct smscore_device_t *coredev, | ||
| 122 | enum SMS_BOARD_EVENTS gevent) { | ||
| 123 | struct smscore_gpio_config MyGpioConfig; | ||
| 124 | |||
| 125 | sms_gpio_assign_11xx_default_led_config(&MyGpioConfig); | ||
| 126 | |||
| 127 | switch (gevent) { | ||
| 128 | case BOARD_EVENT_POWER_INIT: /* including hotplug */ | ||
| 129 | break; /* BOARD_EVENT_BIND */ | ||
| 130 | |||
| 131 | case BOARD_EVENT_POWER_SUSPEND: | ||
| 132 | break; /* BOARD_EVENT_POWER_SUSPEND */ | ||
| 133 | |||
| 134 | case BOARD_EVENT_POWER_RESUME: | ||
| 135 | break; /* BOARD_EVENT_POWER_RESUME */ | ||
| 136 | |||
| 137 | case BOARD_EVENT_BIND: | ||
| 138 | break; /* BOARD_EVENT_BIND */ | ||
| 139 | |||
| 140 | case BOARD_EVENT_SCAN_PROG: | ||
| 141 | break; /* BOARD_EVENT_SCAN_PROG */ | ||
| 142 | case BOARD_EVENT_SCAN_COMP: | ||
| 143 | break; /* BOARD_EVENT_SCAN_COMP */ | ||
| 144 | case BOARD_EVENT_EMERGENCY_WARNING_SIGNAL: | ||
| 145 | break; /* BOARD_EVENT_EMERGENCY_WARNING_SIGNAL */ | ||
| 146 | case BOARD_EVENT_FE_LOCK: | ||
| 147 | break; /* BOARD_EVENT_FE_LOCK */ | ||
| 148 | case BOARD_EVENT_FE_UNLOCK: | ||
| 149 | break; /* BOARD_EVENT_FE_UNLOCK */ | ||
| 150 | case BOARD_EVENT_DEMOD_LOCK: | ||
| 151 | break; /* BOARD_EVENT_DEMOD_LOCK */ | ||
| 152 | case BOARD_EVENT_DEMOD_UNLOCK: | ||
| 153 | break; /* BOARD_EVENT_DEMOD_UNLOCK */ | ||
| 154 | case BOARD_EVENT_RECEPTION_MAX_4: | ||
| 155 | break; /* BOARD_EVENT_RECEPTION_MAX_4 */ | ||
| 156 | case BOARD_EVENT_RECEPTION_3: | ||
| 157 | break; /* BOARD_EVENT_RECEPTION_3 */ | ||
| 158 | case BOARD_EVENT_RECEPTION_2: | ||
| 159 | break; /* BOARD_EVENT_RECEPTION_2 */ | ||
| 160 | case BOARD_EVENT_RECEPTION_1: | ||
| 161 | break; /* BOARD_EVENT_RECEPTION_1 */ | ||
| 162 | case BOARD_EVENT_RECEPTION_LOST_0: | ||
| 163 | break; /* BOARD_EVENT_RECEPTION_LOST_0 */ | ||
| 164 | case BOARD_EVENT_MULTIPLEX_OK: | ||
| 165 | break; /* BOARD_EVENT_MULTIPLEX_OK */ | ||
| 166 | case BOARD_EVENT_MULTIPLEX_ERRORS: | ||
| 167 | break; /* BOARD_EVENT_MULTIPLEX_ERRORS */ | ||
| 168 | |||
| 169 | default: | ||
| 170 | sms_err("Unknown SMS board event"); | ||
| 171 | break; | ||
| 172 | } | ||
| 173 | return 0; | ||
| 174 | } | ||
| 175 | EXPORT_SYMBOL_GPL(sms_board_event); | ||
| 176 | |||
| 177 | static int sms_set_gpio(struct smscore_device_t *coredev, int pin, int enable) | ||
| 178 | { | ||
| 179 | int lvl, ret; | ||
| 180 | u32 gpio; | ||
| 181 | struct smscore_config_gpio gpioconfig = { | ||
| 182 | .direction = SMS_GPIO_DIRECTION_OUTPUT, | ||
| 183 | .pullupdown = SMS_GPIO_PULLUPDOWN_NONE, | ||
| 184 | .inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL, | ||
| 185 | .outputslewrate = SMS_GPIO_OUTPUTSLEWRATE_FAST, | ||
| 186 | .outputdriving = SMS_GPIO_OUTPUTDRIVING_4mA, | ||
| 187 | }; | ||
| 188 | |||
| 189 | if (pin == 0) | ||
| 190 | return -EINVAL; | ||
| 191 | |||
| 192 | if (pin < 0) { | ||
| 193 | /* inverted gpio */ | ||
| 194 | gpio = pin * -1; | ||
| 195 | lvl = enable ? 0 : 1; | ||
| 196 | } else { | ||
| 197 | gpio = pin; | ||
| 198 | lvl = enable ? 1 : 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | ret = smscore_configure_gpio(coredev, gpio, &gpioconfig); | ||
| 202 | if (ret < 0) | ||
| 203 | return ret; | ||
| 204 | |||
| 205 | return smscore_set_gpio(coredev, gpio, lvl); | ||
| 206 | } | ||
| 207 | |||
| 208 | int sms_board_setup(struct smscore_device_t *coredev) | ||
| 209 | { | ||
| 210 | int board_id = smscore_get_board_id(coredev); | ||
| 211 | struct sms_board *board = sms_get_board(board_id); | ||
| 212 | |||
| 213 | switch (board_id) { | ||
| 214 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
| 215 | /* turn off all LEDs */ | ||
| 216 | sms_set_gpio(coredev, board->led_power, 0); | ||
| 217 | sms_set_gpio(coredev, board->led_hi, 0); | ||
| 218 | sms_set_gpio(coredev, board->led_lo, 0); | ||
| 219 | break; | ||
| 220 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | ||
| 221 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | ||
| 222 | /* turn off LNA */ | ||
| 223 | sms_set_gpio(coredev, board->lna_ctrl, 0); | ||
| 224 | break; | ||
| 225 | } | ||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | EXPORT_SYMBOL_GPL(sms_board_setup); | ||
| 229 | |||
| 230 | int sms_board_power(struct smscore_device_t *coredev, int onoff) | ||
| 231 | { | ||
| 232 | int board_id = smscore_get_board_id(coredev); | ||
| 233 | struct sms_board *board = sms_get_board(board_id); | ||
| 234 | |||
| 235 | switch (board_id) { | ||
| 236 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
| 237 | /* power LED */ | ||
| 238 | sms_set_gpio(coredev, | ||
| 239 | board->led_power, onoff ? 1 : 0); | ||
| 240 | break; | ||
| 241 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | ||
| 242 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | ||
| 243 | /* LNA */ | ||
| 244 | if (!onoff) | ||
| 245 | sms_set_gpio(coredev, board->lna_ctrl, 0); | ||
| 246 | break; | ||
| 247 | } | ||
| 248 | return 0; | ||
| 249 | } | ||
| 250 | EXPORT_SYMBOL_GPL(sms_board_power); | ||
| 251 | |||
| 252 | int sms_board_led_feedback(struct smscore_device_t *coredev, int led) | ||
| 253 | { | ||
| 254 | int board_id = smscore_get_board_id(coredev); | ||
| 255 | struct sms_board *board = sms_get_board(board_id); | ||
| 256 | |||
| 257 | /* dont touch GPIO if LEDs are already set */ | ||
| 258 | if (smscore_led_state(coredev, -1) == led) | ||
| 259 | return 0; | ||
| 260 | |||
| 261 | switch (board_id) { | ||
| 262 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
| 263 | sms_set_gpio(coredev, | ||
| 264 | board->led_lo, (led & SMS_LED_LO) ? 1 : 0); | ||
| 265 | sms_set_gpio(coredev, | ||
| 266 | board->led_hi, (led & SMS_LED_HI) ? 1 : 0); | ||
| 267 | |||
| 268 | smscore_led_state(coredev, led); | ||
| 269 | break; | ||
| 270 | } | ||
| 271 | return 0; | ||
| 272 | } | ||
| 273 | EXPORT_SYMBOL_GPL(sms_board_led_feedback); | ||
| 274 | |||
| 275 | int sms_board_lna_control(struct smscore_device_t *coredev, int onoff) | ||
| 276 | { | ||
| 277 | int board_id = smscore_get_board_id(coredev); | ||
| 278 | struct sms_board *board = sms_get_board(board_id); | ||
| 279 | |||
| 280 | sms_debug("%s: LNA %s", __func__, onoff ? "enabled" : "disabled"); | ||
| 281 | |||
| 282 | switch (board_id) { | ||
| 283 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | ||
| 284 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | ||
| 285 | sms_set_gpio(coredev, | ||
| 286 | board->rf_switch, onoff ? 1 : 0); | ||
| 287 | return sms_set_gpio(coredev, | ||
| 288 | board->lna_ctrl, onoff ? 1 : 0); | ||
| 289 | } | ||
| 290 | return -EINVAL; | ||
| 291 | } | ||
| 292 | EXPORT_SYMBOL_GPL(sms_board_lna_control); | ||
| 293 | |||
| 294 | int sms_board_load_modules(int id) | ||
| 295 | { | ||
| 296 | switch (id) { | ||
| 297 | case SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT: | ||
| 298 | case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A: | ||
| 299 | case SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B: | ||
| 300 | case SMS1XXX_BOARD_HAUPPAUGE_WINDHAM: | ||
| 301 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD: | ||
| 302 | case SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2: | ||
| 303 | request_module("smsdvb"); | ||
| 304 | break; | ||
| 305 | default: | ||
| 306 | /* do nothing */ | ||
| 307 | break; | ||
| 308 | } | ||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | EXPORT_SYMBOL_GPL(sms_board_load_modules); | ||
diff --git a/drivers/media/usb/siano/sms-cards.h b/drivers/media/usb/siano/sms-cards.h deleted file mode 100644 index d8cdf756f7cf..000000000000 --- a/drivers/media/usb/siano/sms-cards.h +++ /dev/null | |||
| @@ -1,123 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Card-specific functions for the Siano SMS1xxx USB dongle | ||
| 3 | * | ||
| 4 | * Copyright (c) 2008 Michael Krufky <mkrufky@linuxtv.org> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation; | ||
| 9 | * | ||
| 10 | * Software distributed under the License is distributed on an "AS IS" | ||
| 11 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. | ||
| 12 | * | ||
| 13 | * See the GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 18 | */ | ||
| 19 | |||
| 20 | #ifndef __SMS_CARDS_H__ | ||
| 21 | #define __SMS_CARDS_H__ | ||
| 22 | |||
| 23 | #include <linux/usb.h> | ||
| 24 | #include "smscoreapi.h" | ||
| 25 | #include "smsir.h" | ||
| 26 | |||
| 27 | #define SMS_BOARD_UNKNOWN 0 | ||
| 28 | #define SMS1XXX_BOARD_SIANO_STELLAR 1 | ||
| 29 | #define SMS1XXX_BOARD_SIANO_NOVA_A 2 | ||
| 30 | #define SMS1XXX_BOARD_SIANO_NOVA_B 3 | ||
| 31 | #define SMS1XXX_BOARD_SIANO_VEGA 4 | ||
| 32 | #define SMS1XXX_BOARD_HAUPPAUGE_CATAMOUNT 5 | ||
| 33 | #define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_A 6 | ||
| 34 | #define SMS1XXX_BOARD_HAUPPAUGE_OKEMO_B 7 | ||
| 35 | #define SMS1XXX_BOARD_HAUPPAUGE_WINDHAM 8 | ||
| 36 | #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD 9 | ||
| 37 | #define SMS1XXX_BOARD_HAUPPAUGE_TIGER_MINICARD_R2 10 | ||
| 38 | #define SMS1XXX_BOARD_SIANO_NICE 11 | ||
| 39 | #define SMS1XXX_BOARD_SIANO_VENICE 12 | ||
| 40 | |||
| 41 | struct sms_board_gpio_cfg { | ||
| 42 | int lna_vhf_exist; | ||
| 43 | int lna_vhf_ctrl; | ||
| 44 | int lna_uhf_exist; | ||
| 45 | int lna_uhf_ctrl; | ||
| 46 | int lna_uhf_d_ctrl; | ||
| 47 | int lna_sband_exist; | ||
| 48 | int lna_sband_ctrl; | ||
| 49 | int lna_sband_d_ctrl; | ||
| 50 | int foreign_lna0_ctrl; | ||
| 51 | int foreign_lna1_ctrl; | ||
| 52 | int foreign_lna2_ctrl; | ||
| 53 | int rf_switch_vhf; | ||
| 54 | int rf_switch_uhf; | ||
| 55 | int rf_switch_sband; | ||
| 56 | int leds_power; | ||
| 57 | int led0; | ||
| 58 | int led1; | ||
| 59 | int led2; | ||
| 60 | int led3; | ||
| 61 | int led4; | ||
| 62 | int ir; | ||
| 63 | int eeprom_wp; | ||
| 64 | int mrc_sense; | ||
| 65 | int mrc_pdn_resetn; | ||
| 66 | int mrc_gp0; /* mrcs spi int */ | ||
| 67 | int mrc_gp1; | ||
| 68 | int mrc_gp2; | ||
| 69 | int mrc_gp3; | ||
| 70 | int mrc_gp4; | ||
| 71 | int host_spi_gsp_ts_int; | ||
| 72 | }; | ||
| 73 | |||
| 74 | struct sms_board { | ||
| 75 | enum sms_device_type_st type; | ||
| 76 | char *name, *fw[DEVICE_MODE_MAX]; | ||
| 77 | struct sms_board_gpio_cfg board_cfg; | ||
| 78 | char *rc_codes; /* Name of IR codes table */ | ||
| 79 | |||
| 80 | /* gpios */ | ||
| 81 | int led_power, led_hi, led_lo, lna_ctrl, rf_switch; | ||
| 82 | }; | ||
| 83 | |||
| 84 | struct sms_board *sms_get_board(unsigned id); | ||
| 85 | |||
| 86 | extern struct smscore_device_t *coredev; | ||
| 87 | |||
| 88 | enum SMS_BOARD_EVENTS { | ||
| 89 | BOARD_EVENT_POWER_INIT, | ||
| 90 | BOARD_EVENT_POWER_SUSPEND, | ||
| 91 | BOARD_EVENT_POWER_RESUME, | ||
| 92 | BOARD_EVENT_BIND, | ||
| 93 | BOARD_EVENT_SCAN_PROG, | ||
| 94 | BOARD_EVENT_SCAN_COMP, | ||
| 95 | BOARD_EVENT_EMERGENCY_WARNING_SIGNAL, | ||
| 96 | BOARD_EVENT_FE_LOCK, | ||
| 97 | BOARD_EVENT_FE_UNLOCK, | ||
| 98 | BOARD_EVENT_DEMOD_LOCK, | ||
| 99 | BOARD_EVENT_DEMOD_UNLOCK, | ||
| 100 | BOARD_EVENT_RECEPTION_MAX_4, | ||
| 101 | BOARD_EVENT_RECEPTION_3, | ||
| 102 | BOARD_EVENT_RECEPTION_2, | ||
| 103 | BOARD_EVENT_RECEPTION_1, | ||
| 104 | BOARD_EVENT_RECEPTION_LOST_0, | ||
| 105 | BOARD_EVENT_MULTIPLEX_OK, | ||
| 106 | BOARD_EVENT_MULTIPLEX_ERRORS | ||
| 107 | }; | ||
| 108 | |||
| 109 | int sms_board_event(struct smscore_device_t *coredev, | ||
| 110 | enum SMS_BOARD_EVENTS gevent); | ||
| 111 | |||
| 112 | int sms_board_setup(struct smscore_device_t *coredev); | ||
| 113 | |||
| 114 | #define SMS_LED_OFF 0 | ||
| 115 | #define SMS_LED_LO 1 | ||
| 116 | #define SMS_LED_HI 2 | ||
| 117 | int sms_board_led_feedback(struct smscore_device_t *coredev, int led); | ||
| 118 | int sms_board_power(struct smscore_device_t *coredev, int onoff); | ||
| 119 | int sms_board_lna_control(struct smscore_device_t *coredev, int onoff); | ||
| 120 | |||
| 121 | extern int sms_board_load_modules(int id); | ||
| 122 | |||
| 123 | #endif /* __SMS_CARDS_H__ */ | ||
diff --git a/drivers/media/usb/siano/smscoreapi.c b/drivers/media/usb/siano/smscoreapi.c deleted file mode 100644 index 9cc55546cc30..000000000000 --- a/drivers/media/usb/siano/smscoreapi.c +++ /dev/null | |||
| @@ -1,1637 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Siano core API module | ||
| 3 | * | ||
| 4 | * This file contains implementation for the interface to sms core component | ||
| 5 | * | ||
| 6 | * author: Uri Shkolnik | ||
| 7 | * | ||
| 8 | * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 as | ||
| 12 | * published by the Free Software Foundation; | ||
| 13 | * | ||
| 14 | * Software distributed under the License is distributed on an "AS IS" | ||
| 15 | * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. | ||
| 16 | * | ||
| 17 | * See the GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/kernel.h> | ||
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/moduleparam.h> | ||
| 28 | #include <linux/dma-mapping.h> | ||
| 29 | #include <linux/delay.h> | ||
| 30 | #include <linux/io.h> | ||
| 31 | #include <linux/slab.h> | ||
| 32 | |||
| 33 | #include <linux/firmware.h> | ||
| 34 | #include <linux/wait.h> | ||
| 35 | #include <asm/byteorder.h> | ||
| 36 | |||
| 37 | #include "smscoreapi.h" | ||
| 38 | #include "sms-cards.h" | ||
| 39 | #include "smsir.h" | ||
| 40 | #include "smsendian.h" | ||
| 41 | |||
| 42 | static int sms_dbg; | ||
| 43 | module_param_named(debug, sms_dbg, int, 0644); | ||
| 44 | MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); | ||
| 45 | |||
| 46 | struct smscore_device_notifyee_t { | ||
| 47 | struct list_head entry; | ||
| 48 | hotplug_t hotplug; | ||
| 49 | }; | ||
| 50 | |||
| 51 | struct smscore_idlist_t { | ||
| 52 | struct list_head entry; | ||
| 53 | int id; | ||
| 54 | int data_type; | ||
| 55 | }; | ||
| 56 | |||
| 57 | struct smscore_client_t { | ||
| 58 | struct list_head entry; | ||
| 59 | struct smscore_device_t *coredev; | ||
| 60 | void *context; | ||
| 61 | struct list_head idlist; | ||
| 62 | onresponse_t onresponse_handler; | ||
| 63 | onremove_t onremove_handler; | ||
| 64 | }; | ||
| 65 | |||
| 66 | void smscore_set_board_id(struct smscore_device_t *core, int id) | ||
| 67 | { | ||
| 68 | core->board_id = id; | ||
| 69 | } | ||
| 70 | |||
| 71 | int smscore_led_state(struct smscore_device_t *core, int led) | ||
| 72 | { | ||
| 73 | if (led >= 0) | ||
| 74 | core->led_state = led; | ||
| 75 | return core->led_state; | ||
| 76 | } | ||
| 77 | EXPORT_SYMBOL_GPL(smscore_set_board_id); | ||
| 78 | |||
| 79 | int smscore_get_board_id(struct smscore_device_t *core) | ||
| 80 | { | ||
| 81 | return core->board_id; | ||
| 82 | } | ||
| 83 | EXPORT_SYMBOL_GPL(smscore_get_board_id); | ||
| 84 | |||
| 85 | struct smscore_registry_entry_t { | ||
| 86 | struct list_head entry; | ||
| 87 | char devpath[32]; | ||
| 88 | int mode; | ||
| 89 | enum sms_device_type_st type; | ||
| 90 | }; | ||
| 91 | |||
| 92 | static struct list_head g_smscore_notifyees; | ||
| 93 | static struct list_head g_smscore_devices; | ||
| 94 | static struct mutex g_smscore_deviceslock; | ||
| 95 | |||
| 96 | static struct list_head g_smscore_registry; | ||
| 97 | static struct mutex g_smscore_registrylock; | ||
| 98 | |||
| 99 | static int default_mode = 4; | ||
| 100 | |||
| 101 | module_param(default_mode, int, 0644); | ||
| 102 | MODULE_PARM_DESC(default_mode, "default firmware id (device mode)"); | ||
| 103 | |||
| 104 | static struct smscore_registry_entry_t *smscore_find_registry(char *devpath) | ||
| 105 | { | ||
| 106 | struct smscore_registry_entry_t *entry; | ||
| 107 | struct list_head *next; | ||
| 108 | |||
| 109 | kmutex_lock(&g_smscore_registrylock); | ||
| 110 | for (next = g_smscore_registry.next; | ||
| 111 | next != &g_smscore_registry; | ||
| 112 | next = next->next) { | ||
| 113 | entry = (struct smscore_registry_entry_t *) next; | ||
| 114 | if (!strcmp(entry->devpath, devpath)) { | ||
| 115 | kmutex_unlock(&g_smscore_registrylock); | ||
| 116 | return entry; | ||
| 117 | } | ||
| 118 | } | ||
| 119 | entry = kmalloc(sizeof(struct smscore_registry_entry_t), GFP_KERNEL); | ||
| 120 | if (entry) { | ||
| 121 | entry->mode = default_mode; | ||
| 122 | strcpy(entry->devpath, devpath); | ||
| 123 | list_add(&entry->entry, &g_smscore_registry); | ||
| 124 | } else | ||
| 125 | sms_err("failed to create smscore_registry."); | ||
| 126 | kmutex_unlock(&g_smscore_registrylock); | ||
| 127 | return entry; | ||
| 128 | } | ||
| 129 | |||
| 130 | int smscore_registry_getmode(char *devpath) | ||
| 131 | { | ||
| 132 | struct smscore_registry_entry_t *entry; | ||
| 133 | |||
| 134 | entry = smscore_find_registry(devpath); | ||
| 135 | if (entry) | ||
| 136 | return entry->mode; | ||
| 137 | else | ||
| 138 | sms_err("No registry found."); | ||
| 139 | |||
| 140 | return default_mode; | ||
| 141 | } | ||
| 142 | EXPORT_SYMBOL_GPL(smscore_registry_getmode); | ||
| 143 | |||
| 144 | static enum sms_device_type_st smscore_registry_gettype(char *devpath) | ||
| 145 | { | ||
| 146 | struct smscore_registry_entry_t *entry; | ||
| 147 | |||
| 148 | entry = smscore_find_registry(devpath); | ||
| 149 | if (entry) | ||
| 150 | return entry->type; | ||
| 151 | else | ||
| 152 | sms_err("No registry found."); | ||
| 153 | |||
| 154 | return -1; | ||
| 155 | } | ||
| 156 | |||
| 157 | void smscore_registry_setmode(char *devpath, int mode) | ||
| 158 | { | ||
| 159 | struct smscore_registry_entry_t *entry; | ||
| 160 | |||
| 161 | entry = smscore_find_registry(devpath); | ||
| 162 | if (entry) | ||
| 163 | entry->mode = mode; | ||
| 164 | else | ||
| 165 | sms_err("No registry found."); | ||
| 166 | } | ||
| 167 | |||
| 168 | static void smscore_registry_settype(char *devpath, | ||
| 169 | enum sms_device_type_st type) | ||
| 170 | { | ||
| 171 | struct smscore_registry_entry_t *entry; | ||
| 172 | |||
| 173 | entry = smscore_find_registry(devpath); | ||
| 174 | if (entry) | ||
| 175 | entry->type = type; | ||
| 176 | else | ||
| 177 | sms_err("No registry found."); | ||
| 178 | } | ||
| 179 | |||
| 180 | |||
| 181 | static void list_add_locked(struct list_head *new, struct list_head *head, | ||
| 182 | spinlock_t *lock) | ||
| 183 | { | ||
| 184 | unsigned long flags; | ||
| 185 | |||
| 186 | spin_lock_irqsave(lock, flags); | ||
| 187 | |||
| 188 | list_add(new, head); | ||
| 189 | |||
| 190 | spin_unlock_irqrestore(lock, flags); | ||
| 191 | } | ||
| 192 | |||
| 193 | /** | ||
| 194 | * register a client callback that called when device plugged in/unplugged | ||
| 195 | * NOTE: if devices exist callback is called immediately for each device | ||
| 196 | * | ||
| 197 | * @param hotplug callback | ||
| 198 | * | ||
| 199 | * @return 0 on success, <0 on error. | ||
| 200 | */ | ||
| 201 | int smscore_register_hotplug(hotplug_t hotplug) | ||
| 202 | { | ||
| 203 | struct smscore_device_notifyee_t *notifyee; | ||
| 204 | struct list_head *next, *first; | ||
| 205 | int rc = 0; | ||
| 206 | |||
| 207 | kmutex_lock(&g_smscore_deviceslock); | ||
| 208 | |||
| 209 | notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t), | ||
| 210 | GFP_KERNEL); | ||
| 211 | if (notifyee) { | ||
| 212 | /* now notify callback about existing devices */ | ||
| 213 | first = &g_smscore_devices; | ||
| 214 | for (next = first->next; | ||
| 215 | next != first && !rc; | ||
| 216 | next = next->next) { | ||
| 217 | struct smscore_device_t *coredev = | ||
| 218 | (struct smscore_device_t *) next; | ||
| 219 | rc = hotplug(coredev, coredev->device, 1); | ||
| 220 | } | ||
| 221 | |||
| 222 | if (rc >= 0) { | ||
| 223 | notifyee->hotplug = hotplug; | ||
| 224 | list_add(¬ifyee->entry, &g_smscore_notifyees); | ||
| 225 | } else | ||
| 226 | kfree(notifyee); | ||
| 227 | } else | ||
| 228 | rc = -ENOMEM; | ||
| 229 | |||
| 230 | kmutex_unlock(&g_smscore_deviceslock); | ||
| 231 | |||
| 232 | return rc; | ||
| 233 | } | ||
| 234 | EXPORT_SYMBOL_GPL(smscore_register_hotplug); | ||
| 235 | |||
| 236 | /** | ||
| 237 | * unregister a client callback that called when device plugged in/unplugged | ||
| 238 | * | ||
| 239 | * @param hotplug callback | ||
| 240 | * | ||
| 241 | */ | ||
| 242 | void smscore_unregister_hotplug(hotplug_t hotplug) | ||
| 243 | { | ||
| 244 | struct list_head *next, *first; | ||
| 245 | |||
| 246 | kmutex_lock(&g_smscore_deviceslock); | ||
| 247 | |||
| 248 | first = &g_smscore_notifyees; | ||
| 249 | |||
| 250 | for (next = first->next; next != first;) { | ||
| 251 | struct smscore_device_notifyee_t *notifyee = | ||
| 252 | (struct smscore_device_notifyee_t *) next; | ||
| 253 | next = next->next; | ||
| 254 | |||
| 255 | if (notifyee->hotplug == hotplug) { | ||
| 256 | list_del(¬ifyee->entry); | ||
| 257 | kfree(notifyee); | ||
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 261 | kmutex_unlock(&g_smscore_deviceslock); | ||
| 262 | } | ||
| 263 | EXPORT_SYMBOL_GPL(smscore_unregister_hotplug); | ||
| 264 | |||
| 265 | static void smscore_notify_clients(struct smscore_device_t *coredev) | ||
| 266 | { | ||
| 267 | struct smscore_client_t *client; | ||
| 268 | |||
| 269 | /* the client must call smscore_unregister_client from remove handler */ | ||
| 270 | while (!list_empty(&coredev->clients)) { | ||
| 271 | client = (struct smscore_client_t *) coredev->clients.next; | ||
| 272 | client->onremove_handler(client->context); | ||
| 273 | } | ||
| 274 | } | ||
| 275 | |||
| 276 | static int smscore_notify_callbacks(struct smscore_device_t *coredev, | ||
| 277 | struct device *device, int arrival) | ||
| 278 | { | ||
| 279 | struct smscore_device_notifyee_t *elem; | ||
| 280 | int rc = 0; | ||
| 281 | |||
| 282 | /* note: must be called under g_deviceslock */ | ||
| 283 | |||
| 284 | list_for_each_entry(elem, &g_smscore_notifyees, entry) { | ||
| 285 | rc = elem->hotplug(coredev, device, arrival); | ||
| 286 | if (rc < 0) | ||
| 287 | break; | ||
| 288 | } | ||
| 289 | |||
| 290 | return rc; | ||
| 291 | } | ||
| 292 | |||
| 293 | static struct | ||
| 294 | smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer, | ||
| 295 | dma_addr_t common_buffer_phys) | ||
| 296 | { | ||
| 297 | struct smscore_buffer_t *cb = | ||
| 298 | kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL); | ||
| 299 | if (!cb) { | ||
| 300 | sms_info("kmalloc(...) failed"); | ||
| 301 | return NULL; | ||
| 302 | } | ||
| 303 | |||
| 304 | cb->p = buffer; | ||
| 305 | cb->offset_in_common = buffer - (u8 *) common_buffer; | ||
| 306 | cb->phys = common_buffer_phys + cb->offset_in_common; | ||
| 307 | |||
| 308 | return cb; | ||
| 309 | } | ||
| 310 | |||
| 311 | /** | ||
| 312 | * creates coredev object for a device, prepares buffers, | ||
| 313 | * creates buffer mappings, notifies registered hotplugs about new device. | ||
| 314 | * | ||
| 315 | * @param params device pointer to struct with device specific parameters | ||
| 316 | * and handlers | ||
| 317 | * @param coredev pointer to a value that receives created coredev object | ||
| 318 | * | ||
| 319 | * @return 0 on success, <0 on error. | ||
| 320 | */ | ||
| 321 | int smscore_register_device(struct smsdevice_params_t *params, | ||
| 322 | struct smscore_device_t **coredev) | ||
| 323 | { | ||
| 324 | struct smscore_device_t *dev; | ||
| 325 | u8 *buffer; | ||
| 326 | |||
| 327 | dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL); | ||
| 328 | if (!dev) { | ||
| 329 | sms_info("kzalloc(...) failed"); | ||
| 330 | return -ENOMEM; | ||
| 331 | } | ||
| 332 | |||
| 333 | /* init list entry so it could be safe in smscore_unregister_device */ | ||
| 334 | INIT_LIST_HEAD(&dev->entry); | ||
| 335 | |||
| 336 | /* init queues */ | ||
| 337 | INIT_LIST_HEAD(&dev->clients); | ||
| 338 | INIT_LIST_HEAD(&dev->buffers); | ||
| 339 | |||
| 340 | /* init locks */ | ||
| 341 | spin_lock_init(&dev->clientslock); | ||
| 342 | spin_lock_init(&dev->bufferslock); | ||
| 343 | |||
| 344 | /* init completion events */ | ||
| 345 | init_completion(&dev->version_ex_done); | ||
| 346 | init_completion(&dev->data_download_done); | ||
| 347 | init_completion(&dev->trigger_done); | ||
| 348 | init_completion(&dev->init_device_done); | ||
| 349 | init_completion(&dev->reload_start_done); | ||
| 350 | init_completion(&dev->resume_done); | ||
| 351 | init_completion(&dev->gpio_configuration_done); | ||
| 352 | init_completion(&dev->gpio_set_level_done); | ||
| 353 | init_completion(&dev->gpio_get_level_done); | ||
| 354 | init_completion(&dev->ir_init_done); | ||
| 355 | |||
| 356 | /* Buffer management */ | ||
| 357 | init_waitqueue_head(&dev->buffer_mng_waitq); | ||
| 358 | |||
| 359 | /* alloc common buffer */ | ||
| 360 | dev->common_buffer_size = params->buffer_size * params->num_buffers; | ||
| 361 | dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size, | ||
| 362 | &dev->common_buffer_phys, | ||
| 363 | GFP_KERNEL | GFP_DMA); | ||
| 364 | if (!dev->common_buffer) { | ||
| 365 | smscore_unregister_device(dev); | ||
| 366 | return -ENOMEM; | ||
| 367 | } | ||
| 368 | |||
| 369 | /* prepare dma buffers */ | ||
| 370 | for (buffer = dev->common_buffer; | ||
| 371 | dev->num_buffers < params->num_buffers; | ||
| 372 | dev->num_buffers++, buffer += params->buffer_size) { | ||
| 373 | struct smscore_buffer_t *cb = | ||
| 374 | smscore_createbuffer(buffer, dev->common_buffer, | ||
| 375 | dev->common_buffer_phys); | ||
| 376 | if (!cb) { | ||
| 377 | smscore_unregister_device(dev); | ||
| 378 | return -ENOMEM; | ||
| 379 | } | ||
| 380 | |||
| 381 | smscore_putbuffer(dev, cb); | ||
| 382 | } | ||
| 383 | |||
| 384 | sms_info("allocated %d buffers", dev->num_buffers); | ||
| 385 | |||
| 386 | dev->mode = DEVICE_MODE_NONE; | ||
| 387 | dev->context = params->context; | ||
| 388 | dev->device = params->device; | ||
| 389 | dev->setmode_handler = params->setmode_handler; | ||
| 390 | dev->detectmode_handler = params->detectmode_handler; | ||
| 391 | dev->sendrequest_handler = params->sendrequest_handler; | ||
| 392 | dev->preload_handler = params->preload_handler; | ||
| 393 | dev->postload_handler = params->postload_handler; | ||
| 394 | |||
| 395 | dev->device_flags = params->flags; | ||
| 396 | strcpy(dev->devpath, params->devpath); | ||
| 397 | |||
| 398 | smscore_registry_settype(dev->devpath, params->device_type); | ||
| 399 | |||
| 400 | /* add device to devices list */ | ||
| 401 | kmutex_lock(&g_smscore_deviceslock); | ||
| 402 | list_add(&dev->entry, &g_smscore_devices); | ||
| 403 | kmutex_unlock(&g_smscore_deviceslock); | ||
| 404 | |||
| 405 | *coredev = dev; | ||
| 406 | |||
| 407 | sms_info("device %p created", dev); | ||
| 408 | |||
| 409 | return 0; | ||
| 410 | } | ||
| 411 | EXPORT_SYMBOL_GPL(smscore_register_device); | ||
| 412 | |||
| 413 | |||
| 414 | static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, | ||
| 415 | void *buffer, size_t size, struct completion *completion) { | ||
| 416 | int rc = coredev->sendrequest_handler(coredev->context, buffer, size); | ||
| 417 | if (rc < 0) { | ||
| 418 | sms_info("sendrequest returned error %d", rc); | ||
| 419 | return rc; | ||
| 420 | } | ||
| 421 | |||
| 422 | return wait_for_completion_timeout(completion, | ||
| 423 | msecs_to_jiffies(SMS_PROTOCOL_MAX_RAOUNDTRIP_MS)) ? | ||
| 424 | 0 : -ETIME; | ||
| 425 | } | ||
| 426 | |||
| 427 | /** | ||
| 428 | * Starts & enables IR operations | ||
| 429 | * | ||
| 430 | * @return 0 on success, < 0 on error. | ||
| 431 | */ | ||
| 432 | static int smscore_init_ir(struct smscore_device_t *coredev) | ||
| 433 | { | ||
| 434 | int ir_io; | ||
| 435 | int rc; | ||
| 436 | void *buffer; | ||
| 437 | |||
| 438 | coredev->ir.dev = NULL; | ||
| 439 | ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir; | ||
| 440 | if (ir_io) {/* only if IR port exist we use IR sub-module */ | ||
| 441 | sms_info("IR loading"); | ||
| 442 | rc = sms_ir_init(coredev); | ||
| 443 | |||
| 444 | if (rc != 0) | ||
| 445 | sms_err("Error initialization DTV IR sub-module"); | ||
| 446 | else { | ||
| 447 | buffer = kmalloc(sizeof(struct SmsMsgData_ST2) + | ||
| 448 | SMS_DMA_ALIGNMENT, | ||
| 449 | GFP_KERNEL | GFP_DMA); | ||
| 450 | if (buffer) { | ||
| 451 | struct SmsMsgData_ST2 *msg = | ||
| 452 | (struct SmsMsgData_ST2 *) | ||
| 453 | SMS_ALIGN_ADDRESS(buffer); | ||
| 454 | |||
| 455 | SMS_INIT_MSG(&msg->xMsgHeader, | ||
| 456 | MSG_SMS_START_IR_REQ, | ||
| 457 | sizeof(struct SmsMsgData_ST2)); | ||
| 458 | msg->msgData[0] = coredev->ir.controller; | ||
| 459 | msg->msgData[1] = coredev->ir.timeout; | ||
| 460 | |||
| 461 | smsendian_handle_tx_message( | ||
| 462 | (struct SmsMsgHdr_ST2 *)msg); | ||
| 463 | rc = smscore_sendrequest_and_wait(coredev, msg, | ||
| 464 | msg->xMsgHeader. msgLength, | ||
| 465 | &coredev->ir_init_done); | ||
| 466 | |||
| 467 | kfree(buffer); | ||
| 468 | } else | ||
| 469 | sms_err | ||
| 470 | ("Sending IR initialization message failed"); | ||
| 471 | } | ||
| 472 | } else | ||
| 473 | sms_info("IR port has not been detected"); | ||
| 474 | |||
| 475 | return 0; | ||
| 476 | } | ||
| 477 | |||
| 478 | /** | ||
| 479 | * sets initial device mode and notifies client hotplugs that device is ready | ||
| 480 | * | ||
| 481 | * @param coredev pointer to a coredev object returned by | ||
| 482 | * smscore_register_device | ||
| 483 | * | ||
| 484 | * @return 0 on success, <0 on error. | ||
| 485 | */ | ||
| 486 | int smscore_start_device(struct smscore_device_t *coredev) | ||
| 487 | { | ||
| 488 | int rc = smscore_set_device_mode( | ||
| 489 | coredev, smscore_registry_getmode(coredev->devpath)); | ||
| 490 | if (rc < 0) { | ||
| 491 | sms_info("set device mode faile , rc %d", rc); | ||
| 492 | return rc; | ||
| 493 | } | ||
| 494 | |||
| 495 | kmutex_lock(&g_smscore_deviceslock); | ||
| 496 | |||
| 497 | rc = smscore_notify_callbacks(coredev, coredev->device, 1); | ||
| 498 | smscore_init_ir(coredev); | ||
| 499 | |||
| 500 | sms_info("device %p started, rc %d", coredev, rc); | ||
| 501 | |||
| 502 | kmutex_unlock(&g_smscore_deviceslock); | ||
| 503 | |||
| 504 | return rc; | ||
| 505 | } | ||
| 506 | EXPORT_SYMBOL_GPL(smscore_start_device); | ||
| 507 | |||
| 508 | |||
| 509 | static int smscore_load_firmware_family2(struct smscore_device_t *coredev, | ||
| 510 | void *buffer, size_t size) | ||
| 511 | { | ||
| 512 | struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer; | ||
| 513 | struct SmsMsgHdr_ST *msg; | ||
| 514 | u32 mem_address; | ||
| 515 | u8 *payload = firmware->Payload; | ||
| 516 | int rc = 0; | ||
| 517 | firmware->StartAddress = le32_to_cpu(firmware->StartAddress); | ||
| 518 | firmware->Length = le32_to_cpu(firmware->Length); | ||
| 519 | |||
| 520 | mem_address = firmware->StartAddress; | ||
| 521 | |||
| 522 | sms_info("loading FW to addr 0x%x size %d", | ||
| 523 | mem_address, firmware->Length); | ||
| 524 | if (coredev->preload_handler) { | ||
| 525 | rc = coredev->preload_handler(coredev->context); | ||
| 526 | if (rc < 0) | ||
| 527 | return rc; | ||
| 528 | } | ||
| 529 | |||
| 530 | /* PAGE_SIZE buffer shall be enough and dma aligned */ | ||
| 531 | msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA); | ||
| 532 | if (!msg) | ||
| 533 | return -ENOMEM; | ||
| 534 | |||
| 535 | if (coredev->mode != DEVICE_MODE_NONE) { | ||
| 536 | sms_debug("sending reload command."); | ||
| 537 | SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ, | ||
| 538 | sizeof(struct SmsMsgHdr_ST)); | ||
| 539 | rc = smscore_sendrequest_and_wait(coredev, msg, | ||
| 540 | msg->msgLength, | ||
| 541 | &coredev->reload_start_done); | ||
| 542 | mem_address = *(u32 *) &payload[20]; | ||
| 543 | } | ||
| 544 | |||
| 545 | while (size && rc >= 0) { | ||
| 546 | struct SmsDataDownload_ST *DataMsg = | ||
| 547 | (struct SmsDataDownload_ST *) msg; | ||
| 548 | int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE); | ||
| 549 | |||
| 550 | SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ, | ||
| 551 | (u16)(sizeof(struct SmsMsgHdr_ST) + | ||
| 552 | sizeof(u32) + payload_size)); | ||
| 553 | |||
| 554 | DataMsg->MemAddr = mem_address; | ||
| 555 | memcpy(DataMsg->Payload, payload, payload_size); | ||
| 556 | |||
| 557 | if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) && | ||
| 558 | (coredev->mode == DEVICE_MODE_NONE)) | ||
| 559 | rc = coredev->sendrequest_handler( | ||
| 560 | coredev->context, DataMsg, | ||
| 561 | DataMsg->xMsgHeader.msgLength); | ||
| 562 | else | ||
| 563 | rc = smscore_sendrequest_and_wait( | ||
| 564 | coredev, DataMsg, | ||
| 565 | DataMsg->xMsgHeader.msgLength, | ||
| 566 | &coredev->data_download_done); | ||
| 567 | |||
| 568 | payload += payload_size; | ||
| 569 | size -= payload_size; | ||
| 570 | mem_address += payload_size; | ||
| 571 | } | ||
| 572 | |||
| 573 | if (rc >= 0) { | ||
| 574 | if (coredev->mode == DEVICE_MODE_NONE) { | ||
| 575 | struct SmsMsgData_ST *TriggerMsg = | ||
| 576 | (struct SmsMsgData_ST *) msg; | ||
| 577 | |||
| 578 | SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ, | ||
| 579 | sizeof(struct SmsMsgHdr_ST) + | ||
| 580 | sizeof(u32) * 5); | ||
| 581 | |||
| 582 | TriggerMsg->msgData[0] = firmware->StartAddress; | ||
| 583 | /* Entry point */ | ||
| 584 | TriggerMsg->msgData[1] = 5; /* Priority */ | ||
| 585 | TriggerMsg->msgData[2] = 0x200; /* Stack size */ | ||
| 586 | TriggerMsg->msgData[3] = 0; /* Parameter */ | ||
| 587 | TriggerMsg->msgData[4] = 4; /* Task ID */ | ||
| 588 | |||
| 589 | if (coredev->device_flags & SMS_ROM_NO_RESPONSE) { | ||
| 590 | rc = coredev->sendrequest_handler( | ||
| 591 | coredev->context, TriggerMsg, | ||
| 592 | TriggerMsg->xMsgHeader.msgLength); | ||
| 593 | msleep(100); | ||
| 594 | } else | ||
| 595 | rc = smscore_sendrequest_and_wait( | ||
| 596 | coredev, TriggerMsg, | ||
| 597 | TriggerMsg->xMsgHeader.msgLength, | ||
| 598 | &coredev->trigger_done); | ||
| 599 | } else { | ||
| 600 | SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ, | ||
| 601 | sizeof(struct SmsMsgHdr_ST)); | ||
| 602 | |||
| 603 | rc = coredev->sendrequest_handler(coredev->context, | ||
| 604 | msg, msg->msgLength); | ||
| 605 | } | ||
| 606 | msleep(500); | ||
| 607 | } | ||
| 608 | |||
| 609 | sms_debug("rc=%d, postload=%p ", rc, | ||
| 610 | coredev->postload_handler); | ||
| 611 | |||
| 612 | kfree(msg); | ||
| 613 | |||
| 614 | return ((rc >= 0) && coredev->postload_handler) ? | ||
| 615 | coredev->postload_handler(coredev->context) : | ||
| 616 | rc; | ||
| 617 | } | ||
| 618 | |||
| 619 | /** | ||
| 620 | * loads specified firmware into a buffer and calls device loadfirmware_handler | ||
| 621 | * | ||
| 622 | * @param coredev pointer to a coredev object returned by | ||
| 623 | * smscore_register_device | ||
| 624 | * @param filename null-terminated string specifies firmware file name | ||
| 625 | * @param loadfirmware_handler device handler that loads firmware | ||
| 626 | * | ||
| 627 | * @return 0 on success, <0 on error. | ||
| 628 | */ | ||
| 629 | static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, | ||
| 630 | char *filename, | ||
| 631 | loadfirmware_t loadfirmware_handler) | ||
| 632 | { | ||
| 633 | int rc = -ENOENT; | ||
| 634 | const struct firmware *fw; | ||
| 635 | u8 *fw_buffer; | ||
| 636 | |||
| 637 | if (loadfirmware_handler == NULL && !(coredev->device_flags & | ||
| 638 | SMS_DEVICE_FAMILY2)) | ||
| 639 | return -EINVAL; | ||
| 640 | |||
| 641 | rc = request_firmware(&fw, filename, coredev->device); | ||
| 642 | if (rc < 0) { | ||
| 643 | sms_info("failed to open \"%s\"", filename); | ||
| 644 | return rc; | ||
| 645 | } | ||
| 646 | sms_info("read FW %s, size=%zd", filename, fw->size); | ||
| 647 | fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT), | ||
| 648 | GFP_KERNEL | GFP_DMA); | ||
| 649 | if (fw_buffer) { | ||
| 650 | memcpy(fw_buffer, fw->data, fw->size); | ||
| 651 | |||
| 652 | rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ? | ||
| 653 | smscore_load_firmware_family2(coredev, | ||
| 654 | fw_buffer, | ||
| 655 | fw->size) : | ||
| 656 | loadfirmware_handler(coredev->context, | ||
| 657 | fw_buffer, fw->size); | ||
| 658 | |||
| 659 | kfree(fw_buffer); | ||
| 660 | } else { | ||
| 661 | sms_info("failed to allocate firmware buffer"); | ||
| 662 | rc = -ENOMEM; | ||
| 663 | } | ||
| 664 | |||
| 665 | release_firmware(fw); | ||
| 666 | |||
| 667 | return rc; | ||
| 668 | } | ||
| 669 | |||
| 670 | /** | ||
| 671 | * notifies all clients registered with the device, notifies hotplugs, | ||
| 672 | * frees all buffers and coredev object | ||
| 673 | * | ||
| 674 | * @param coredev pointer to a coredev object returned by | ||
| 675 | * smscore_register_device | ||
| 676 | * | ||
| 677 | * @return 0 on success, <0 on error. | ||
| 678 | */ | ||
| 679 | void smscore_unregister_device(struct smscore_device_t *coredev) | ||
| 680 | { | ||
| 681 | struct smscore_buffer_t *cb; | ||
| 682 | int num_buffers = 0; | ||
| 683 | int retry = 0; | ||
| 684 | |||
| 685 | kmutex_lock(&g_smscore_deviceslock); | ||
| 686 | |||
| 687 | /* Release input device (IR) resources */ | ||
| 688 | sms_ir_exit(coredev); | ||
| 689 | |||
| 690 | smscore_notify_clients(coredev); | ||
| 691 | smscore_notify_callbacks(coredev, NULL, 0); | ||
| 692 | |||
| 693 | /* at this point all buffers should be back | ||
| 694 | * onresponse must no longer be called */ | ||
| 695 | |||
| 696 | while (1) { | ||
| 697 | while (!list_empty(&coredev->buffers)) { | ||
| 698 | cb = (struct smscore_buffer_t *) coredev->buffers.next; | ||
| 699 | list_del(&cb->entry); | ||
| 700 | kfree(cb); | ||
| 701 | num_buffers++; | ||
| 702 | } | ||
| 703 | if (num_buffers == coredev->num_buffers) | ||
| 704 | break; | ||
| 705 | if (++retry > 10) { | ||
| 706 | sms_info("exiting although " | ||
| 707 | "not all buffers released."); | ||
| 708 | break; | ||
| 709 | } | ||
| 710 | |||
| 711 | sms_info("waiting for %d buffer(s)", | ||
| 712 | coredev->num_buffers - num_buffers); | ||
| 713 | msleep(100); | ||
| 714 | } | ||
| 715 | |||
| 716 | sms_info("freed %d buffers", num_buffers); | ||
| 717 | |||
| 718 | if (coredev->common_buffer) | ||
| 719 | dma_free_coherent(NULL, coredev->common_buffer_size, | ||
| 720 | coredev->common_buffer, coredev->common_buffer_phys); | ||
| 721 | |||
| 722 | if (coredev->fw_buf != NULL) | ||
| 723 | kfree(coredev->fw_buf); | ||
| 724 | |||
| 725 | list_del(&coredev->entry); | ||
| 726 | kfree(coredev); | ||
| 727 | |||
| 728 | kmutex_unlock(&g_smscore_deviceslock); | ||
| 729 | |||
| 730 | sms_info("device %p destroyed", coredev); | ||
| 731 | } | ||
| 732 | EXPORT_SYMBOL_GPL(smscore_unregister_device); | ||
| 733 | |||
| 734 | static int smscore_detect_mode(struct smscore_device_t *coredev) | ||
| 735 | { | ||
| 736 | void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT, | ||
| 737 | GFP_KERNEL | GFP_DMA); | ||
| 738 | struct SmsMsgHdr_ST *msg = | ||
| 739 | (struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer); | ||
| 740 | int rc; | ||
| 741 | |||
| 742 | if (!buffer) | ||
| 743 | return -ENOMEM; | ||
| 744 | |||
| 745 | SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ, | ||
| 746 | sizeof(struct SmsMsgHdr_ST)); | ||
| 747 | |||
| 748 | rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength, | ||
| 749 | &coredev->version_ex_done); | ||
| 750 | if (rc == -ETIME) { | ||
| 751 | sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try"); | ||
| 752 | |||
| 753 | if (wait_for_completion_timeout(&coredev->resume_done, | ||
| 754 | msecs_to_jiffies(5000))) { | ||
| 755 | rc = smscore_sendrequest_and_wait( | ||
| 756 | coredev, msg, msg->msgLength, | ||
| 757 | &coredev->version_ex_done); | ||
| 758 | if (rc < 0) | ||
| 759 | sms_err("MSG_SMS_GET_VERSION_EX_REQ failed " | ||
| 760 | "second try, rc %d", rc); | ||
| 761 | } else | ||
| 762 | rc = -ETIME; | ||
| 763 | } | ||
| 764 | |||
| 765 | kfree(buffer); | ||
| 766 | |||
| 767 | return rc; | ||
| 768 | } | ||
| 769 | |||
| 770 | static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = { | ||
| 771 | /*Stellar NOVA A0 Nova B0 VEGA*/ | ||
| 772 | /*DVBT*/ | ||
| 773 | {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, | ||
| 774 | /*DVBH*/ | ||
| 775 | {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, | ||
| 776 | /*TDMB*/ | ||
| 777 | {"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"}, | ||
| 778 | /*DABIP*/ | ||
| 779 | {"none", "none", "none", "none"}, | ||
| 780 | /*BDA*/ | ||
| 781 | {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, | ||
| 782 | /*ISDBT*/ | ||
| 783 | {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, | ||
| 784 | /*ISDBTBDA*/ | ||
| 785 | {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, | ||
| 786 | /*CMMB*/ | ||
| 787 | {"none", "none", "none", "cmmb_vega_12mhz.inp"} | ||
| 788 | }; | ||
| 789 | |||
| 790 | static inline char *sms_get_fw_name(struct smscore_device_t *coredev, | ||
| 791 | int mode, enum sms_device_type_st type) | ||
| 792 | { | ||
| 793 | char **fw = sms_get_board(smscore_get_board_id(coredev))->fw; | ||
| 794 | return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type]; | ||
| 795 | } | ||
| 796 | |||
| 797 | /** | ||
| 798 | * calls device handler to change mode of operation | ||
| 799 | * NOTE: stellar/usb may disconnect when changing mode | ||
| 800 | * | ||
| 801 | * @param coredev pointer to a coredev object returned by | ||
| 802 | * smscore_register_device | ||
| 803 | * @param mode requested mode of operation | ||
| 804 | * | ||
| 805 | * @return 0 on success, <0 on error. | ||
| 806 | */ | ||
| 807 | int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) | ||
| 808 | { | ||
| 809 | void *buffer; | ||
| 810 | int rc = 0; | ||
| 811 | enum sms_device_type_st type; | ||
| 812 | |||
| 813 | sms_debug("set device mode to %d", mode); | ||
| 814 | if (coredev->device_flags & SMS_DEVICE_FAMILY2) { | ||
| 815 | if (mode < DEVICE_MODE_DVBT || mode >= DEVICE_MODE_RAW_TUNER) { | ||
| 816 | sms_err("invalid mode specified %d", mode); | ||
| 817 | return -EINVAL; | ||
| 818 | } | ||
| 819 | |||
| 820 | smscore_registry_setmode(coredev->devpath, mode); | ||
| 821 | |||
| 822 | if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) { | ||
| 823 | rc = smscore_detect_mode(coredev); | ||
| 824 | if (rc < 0) { | ||
| 825 | sms_err("mode detect failed %d", rc); | ||
| 826 | return rc; | ||
| 827 | } | ||
| 828 | } | ||
| 829 | |||
| 830 | if (coredev->mode == mode) { | ||
| 831 | sms_info("device mode %d already set", mode); | ||
| 832 | return 0; | ||
| 833 | } | ||
| 834 | |||
| 835 | if (!(coredev->modes_supported & (1 << mode))) { | ||
| 836 | char *fw_filename; | ||
| 837 | |||
| 838 | type = smscore_registry_gettype(coredev->devpath); | ||
| 839 | fw_filename = sms_get_fw_name(coredev, mode, type); | ||
| 840 | |||
| 841 | rc = smscore_load_firmware_from_file(coredev, | ||
| 842 | fw_filename, NULL); | ||
| 843 | if (rc < 0) { | ||
| 844 | sms_warn("error %d loading firmware: %s, " | ||
| 845 | "trying again with default firmware", | ||
| 846 | rc, fw_filename); | ||
| 847 | |||
| 848 | /* try again with the default firmware */ | ||
| 849 | fw_filename = smscore_fw_lkup[mode][type]; | ||
| 850 | rc = smscore_load_firmware_from_file(coredev, | ||
| 851 | fw_filename, NULL); | ||
| 852 | |||
| 853 | if (rc < 0) { | ||
| 854 | sms_warn("error %d loading " | ||
| 855 | "firmware: %s", rc, | ||
| 856 | fw_filename); | ||
| 857 | return rc; | ||
| 858 | } | ||
| 859 | } | ||
| 860 | sms_log("firmware download success: %s", fw_filename); | ||
| 861 | } else | ||
| 862 | sms_info("mode %d supported by running " | ||
| 863 | "firmware", mode); | ||
| 864 | |||
| 865 | buffer = kmalloc(sizeof(struct SmsMsgData_ST) + | ||
| 866 | SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA); | ||
| 867 | if (buffer) { | ||
| 868 | struct SmsMsgData_ST *msg = | ||
| 869 | (struct SmsMsgData_ST *) | ||
| 870 | SMS_ALIGN_ADDRESS(buffer); | ||
| 871 | |||
| 872 | SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ, | ||
| 873 | sizeof(struct SmsMsgData_ST)); | ||
| 874 | msg->msgData[0] = mode; | ||
| 875 | |||
| 876 | rc = smscore_sendrequest_and_wait( | ||
| 877 | coredev, msg, msg->xMsgHeader.msgLength, | ||
| 878 | &coredev->init_device_done); | ||
| 879 | |||
| 880 | kfree(buffer); | ||
| 881 | } else { | ||
| 882 | sms_err("Could not allocate buffer for " | ||
| 883 | "init device message."); | ||
| 884 | rc = -ENOMEM; | ||
| 885 | } | ||
| 886 | } else { | ||
| 887 | if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) { | ||
| 888 | sms_err("invalid mode specified %d", mode); | ||
| 889 | return -EINVAL; | ||
| 890 | } | ||
| 891 | |||
| 892 | smscore_registry_setmode(coredev->devpath, mode); | ||
| 893 | |||
| 894 | if (coredev->detectmode_handler) | ||
| 895 | coredev->detectmode_handler(coredev->context, | ||
| 896 | &coredev->mode); | ||
| 897 | |||
| 898 | if (coredev->mode != mode && coredev->setmode_handler) | ||
| 899 | rc = coredev->setmode_handler(coredev->context, mode); | ||
| 900 | } | ||
| 901 | |||
| 902 | if (rc >= 0) { | ||
| 903 | coredev->mode = mode; | ||
| 904 | coredev->device_flags &= ~SMS_DEVICE_NOT_READY; | ||
| 905 | } | ||
| 906 | |||
| 907 | if (rc < 0) | ||
| 908 | sms_err("return error code %d.", rc); | ||
| 909 | return rc; | ||
| 910 | } | ||
| 911 | |||
| 912 | /** | ||
| 913 | * calls device handler to get current mode of operation | ||
| 914 | * | ||
| 915 | * @param coredev pointer to a coredev object returned by | ||
| 916 | * smscore_register_device | ||
| 917 | * | ||
| 918 | * @return current mode | ||
| 919 | */ | ||
| 920 | int smscore_get_device_mode(struct smscore_device_t *coredev) | ||
| 921 | { | ||
| 922 | return coredev->mode; | ||
| 923 | } | ||
| 924 | EXPORT_SYMBOL_GPL(smscore_get_device_mode); | ||
| 925 | |||
| 926 | /** | ||
| 927 | * find client by response id & type within the clients list. | ||
| 928 | * return client handle or NULL. | ||
| 929 | * | ||
| 930 | * @param coredev pointer to a coredev object returned by | ||
| 931 | * smscore_register_device | ||
| 932 | * @param data_type client data type (SMS_DONT_CARE for all types) | ||
| 933 | * @param id client id (SMS_DONT_CARE for all id) | ||
| 934 | * | ||
| 935 | */ | ||
| 936 | static struct | ||
| 937 | smscore_client_t *smscore_find_client(struct smscore_device_t *coredev, | ||
| 938 | int data_type, int id) | ||
| 939 | { | ||
| 940 | struct list_head *first; | ||
| 941 | struct smscore_client_t *client; | ||
| 942 | unsigned long flags; | ||
| 943 | struct list_head *firstid; | ||
| 944 | struct smscore_idlist_t *client_id; | ||
| 945 | |||
| 946 | spin_lock_irqsave(&coredev->clientslock, flags); | ||
| 947 | first = &coredev->clients; | ||
| 948 | list_for_each_entry(client, first, entry) { | ||
| 949 | firstid = &client->idlist; | ||
| 950 | list_for_each_entry(client_id, firstid, entry) { | ||
| 951 | if ((client_id->id == id) && | ||
| 952 | (client_id->data_type == data_type || | ||
| 953 | (client_id->data_type == 0))) | ||
| 954 | goto found; | ||
| 955 | } | ||
| 956 | } | ||
| 957 | client = NULL; | ||
| 958 | found: | ||
| 959 | spin_unlock_irqrestore(&coredev->clientslock, flags); | ||
| 960 | return client; | ||
| 961 | } | ||
| 962 | |||
| 963 | /** | ||
| 964 | * find client by response id/type, call clients onresponse handler | ||
| 965 | * return buffer to pool on error | ||
| 966 | * | ||
| 967 | * @param coredev pointer to a coredev object returned by | ||
| 968 | * smscore_register_device | ||
| 969 | * @param cb pointer to response buffer descriptor | ||
| 970 | * | ||
| 971 | */ | ||
| 972 | void smscore_onresponse(struct smscore_device_t *coredev, | ||
| 973 | struct smscore_buffer_t *cb) { | ||
| 974 | struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) ((u8 *) cb->p | ||
| 975 | + cb->offset); | ||
| 976 | struct smscore_client_t *client; | ||
| 977 | int rc = -EBUSY; | ||
| 978 | static unsigned long last_sample_time; /* = 0; */ | ||
| 979 | static int data_total; /* = 0; */ | ||
| 980 | unsigned long time_now = jiffies_to_msecs(jiffies); | ||
| 981 | |||
| 982 | if (!last_sample_time) | ||
| 983 | last_sample_time = time_now; | ||
| 984 | |||
| 985 | if (time_now - last_sample_time > 10000) { | ||
| 986 | sms_debug("\ndata rate %d bytes/secs", | ||
| 987 | (int)((data_total * 1000) / | ||
| 988 | (time_now - last_sample_time))); | ||
| 989 | |||
| 990 | last_sample_time = time_now; | ||
| 991 | data_total = 0; | ||
| 992 | } | ||
| 993 | |||
| 994 | data_total += cb->size; | ||
| 995 | /* Do we need to re-route? */ | ||
| 996 | if ((phdr->msgType == MSG_SMS_HO_PER_SLICES_IND) || | ||
| 997 | (phdr->msgType == MSG_SMS_TRANSMISSION_IND)) { | ||
| 998 | if (coredev->mode == DEVICE_MODE_DVBT_BDA) | ||
| 999 | phdr->msgDstId = DVBT_BDA_CONTROL_MSG_ID; | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | |||
| 1003 | client = smscore_find_client(coredev, phdr->msgType, phdr->msgDstId); | ||
| 1004 | |||
| 1005 | /* If no client registered for type & id, | ||
| 1006 | * check for control client where type is not registered */ | ||
| 1007 | if (client) | ||
| 1008 | rc = client->onresponse_handler(client->context, cb); | ||
| 1009 | |||
| 1010 | if (rc < 0) { | ||
| 1011 | switch (phdr->msgType) { | ||
| 1012 | case MSG_SMS_GET_VERSION_EX_RES: | ||
| 1013 | { | ||
| 1014 | struct SmsVersionRes_ST *ver = | ||
| 1015 | (struct SmsVersionRes_ST *) phdr; | ||
| 1016 | sms_debug("MSG_SMS_GET_VERSION_EX_RES " | ||
| 1017 | "id %d prots 0x%x ver %d.%d", | ||
| 1018 | ver->FirmwareId, ver->SupportedProtocols, | ||
| 1019 | ver->RomVersionMajor, ver->RomVersionMinor); | ||
| 1020 | |||
| 1021 | coredev->mode = ver->FirmwareId == 255 ? | ||
| 1022 | DEVICE_MODE_NONE : ver->FirmwareId; | ||
| 1023 | coredev->modes_supported = ver->SupportedProtocols; | ||
| 1024 | |||
| 1025 | complete(&coredev->version_ex_done); | ||
| 1026 | break; | ||
| 1027 | } | ||
| 1028 | case MSG_SMS_INIT_DEVICE_RES: | ||
| 1029 | sms_debug("MSG_SMS_INIT_DEVICE_RES"); | ||
| 1030 | complete(&coredev->init_device_done); | ||
| 1031 | break; | ||
| 1032 | case MSG_SW_RELOAD_START_RES: | ||
| 1033 | sms_debug("MSG_SW_RELOAD_START_RES"); | ||
| 1034 | complete(&coredev->reload_start_done); | ||
| 1035 | break; | ||
| 1036 | case MSG_SMS_DATA_DOWNLOAD_RES: | ||
| 1037 | complete(&coredev->data_download_done); | ||
| 1038 | break; | ||
| 1039 | case MSG_SW_RELOAD_EXEC_RES: | ||
| 1040 | sms_debug("MSG_SW_RELOAD_EXEC_RES"); | ||
| 1041 | break; | ||
| 1042 | case MSG_SMS_SWDOWNLOAD_TRIGGER_RES: | ||
| 1043 | sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES"); | ||
| 1044 | complete(&coredev->trigger_done); | ||
| 1045 | break; | ||
| 1046 | case MSG_SMS_SLEEP_RESUME_COMP_IND: | ||
| 1047 | complete(&coredev->resume_done); | ||
| 1048 | break; | ||
| 1049 | case MSG_SMS_GPIO_CONFIG_EX_RES: | ||
| 1050 | sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES"); | ||
| 1051 | complete(&coredev->gpio_configuration_done); | ||
| 1052 | break; | ||
| 1053 | case MSG_SMS_GPIO_SET_LEVEL_RES: | ||
| 1054 | sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES"); | ||
| 1055 | complete(&coredev->gpio_set_level_done); | ||
| 1056 | break; | ||
| 1057 | case MSG_SMS_GPIO_GET_LEVEL_RES: | ||
| 1058 | { | ||
| 1059 | u32 *msgdata = (u32 *) phdr; | ||
| 1060 | coredev->gpio_get_res = msgdata[1]; | ||
| 1061 | sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d", | ||
| 1062 | coredev->gpio_get_res); | ||
| 1063 | complete(&coredev->gpio_get_level_done); | ||
| 1064 | break; | ||
| 1065 | } | ||
| 1066 | case MSG_SMS_START_IR_RES: | ||
| 1067 | complete(&coredev->ir_init_done); | ||
| 1068 | break; | ||
| 1069 | case MSG_SMS_IR_SAMPLES_IND: | ||
| 1070 | sms_ir_event(coredev, | ||
| 1071 | (const char *) | ||
| 1072 | ((char *)phdr | ||
| 1073 | + sizeof(struct SmsMsgHdr_ST)), | ||
| 1074 | (int)phdr->msgLength | ||
| 1075 | - sizeof(struct SmsMsgHdr_ST)); | ||
| 1076 | break; | ||
| 1077 | |||
| 1078 | default: | ||
| 1079 | break; | ||
| 1080 | } | ||
| 1081 | smscore_putbuffer(coredev, cb); | ||
| 1082 | } | ||
| 1083 | } | ||
| 1084 | EXPORT_SYMBOL_GPL(smscore_onresponse); | ||
| 1085 | |||
| 1086 | /** | ||
| 1087 | * return pointer to next free buffer descriptor from core pool | ||
| 1088 | * | ||
| 1089 | * @param coredev pointer to a coredev object returned by | ||
| 1090 | * smscore_register_device | ||
| 1091 | * | ||
| 1092 | * @return pointer to descriptor on success, NULL on error. | ||
| 1093 | */ | ||
| 1094 | |||
| 1095 | struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev) | ||
| 1096 | { | ||
| 1097 | struct smscore_buffer_t *cb = NULL; | ||
| 1098 | unsigned long flags; | ||
| 1099 | |||
| 1100 | spin_lock_irqsave(&coredev->bufferslock, flags); | ||
| 1101 | if (!list_empty(&coredev->buffers)) { | ||
| 1102 | cb = (struct smscore_buffer_t *) coredev->buffers.next; | ||
| 1103 | list_del(&cb->entry); | ||
| 1104 | } | ||
| 1105 | spin_unlock_irqrestore(&coredev->bufferslock, flags); | ||
| 1106 | return cb; | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) | ||
| 1110 | { | ||
| 1111 | struct smscore_buffer_t *cb = NULL; | ||
| 1112 | |||
| 1113 | wait_event(coredev->buffer_mng_waitq, (cb = get_entry(coredev))); | ||
| 1114 | |||
| 1115 | return cb; | ||
| 1116 | } | ||
| 1117 | EXPORT_SYMBOL_GPL(smscore_getbuffer); | ||
| 1118 | |||
| 1119 | /** | ||
| 1120 | * return buffer descriptor to a pool | ||
| 1121 | * | ||
| 1122 | * @param coredev pointer to a coredev object returned by | ||
| 1123 | * smscore_register_device | ||
| 1124 | * @param cb pointer buffer descriptor | ||
| 1125 | * | ||
| 1126 | */ | ||
| 1127 | void smscore_putbuffer(struct smscore_device_t *coredev, | ||
| 1128 | struct smscore_buffer_t *cb) { | ||
| 1129 | wake_up_interruptible(&coredev->buffer_mng_waitq); | ||
| 1130 | list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock); | ||
| 1131 | } | ||
| 1132 | EXPORT_SYMBOL_GPL(smscore_putbuffer); | ||
| 1133 | |||
| 1134 | static int smscore_validate_client(struct smscore_device_t *coredev, | ||
| 1135 | struct smscore_client_t *client, | ||
| 1136 | int data_type, int id) | ||
| 1137 | { | ||
| 1138 | struct smscore_idlist_t *listentry; | ||
| 1139 | struct smscore_client_t *registered_client; | ||
| 1140 | |||
| 1141 | if (!client) { | ||
| 1142 | sms_err("bad parameter."); | ||
| 1143 | return -EINVAL; | ||
| 1144 | } | ||
| 1145 | registered_client = smscore_find_client(coredev, data_type, id); | ||
| 1146 | if (registered_client == client) | ||
| 1147 | return 0; | ||
| 1148 | |||
| 1149 | if (registered_client) { | ||
| 1150 | sms_err("The msg ID already registered to another client."); | ||
| 1151 | return -EEXIST; | ||
| 1152 | } | ||
| 1153 | listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL); | ||
| 1154 | if (!listentry) { | ||
| 1155 | sms_err("Can't allocate memory for client id."); | ||
| 1156 | return -ENOMEM; | ||
| 1157 | } | ||
| 1158 | listentry->id = id; | ||
| 1159 | listentry->data_type = data_type; | ||
| 1160 | list_add_locked(&listentry->entry, &client->idlist, | ||
| 1161 | &coredev->clientslock); | ||
| 1162 | return 0; | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | /** | ||
| 1166 | * creates smsclient object, check that id is taken by another client | ||
| 1167 | * | ||
| 1168 | * @param coredev pointer to a coredev object from clients hotplug | ||
| 1169 | * @param initial_id all messages with this id would be sent to this client | ||
| 1170 | * @param data_type all messages of this type would be sent to this client | ||
| 1171 | * @param onresponse_handler client handler that is called to | ||
| 1172 | * process incoming messages | ||
| 1173 | * @param onremove_handler client handler that is called when device is removed | ||
| 1174 | * @param context client-specific context | ||
| 1175 | * @param client pointer to a value that receives created smsclient object | ||
| 1176 | * | ||
| 1177 | * @return 0 on success, <0 on error. | ||
| 1178 | */ | ||
| 1179 | int smscore_register_client(struct smscore_device_t *coredev, | ||
| 1180 | struct smsclient_params_t *params, | ||
| 1181 | struct smscore_client_t **client) | ||
| 1182 | { | ||
| 1183 | struct smscore_client_t *newclient; | ||
| 1184 | /* check that no other channel with same parameters exists */ | ||
| 1185 | if (smscore_find_client(coredev, params->data_type, | ||
| 1186 | params->initial_id)) { | ||
| 1187 | sms_err("Client already exist."); | ||
| 1188 | return -EEXIST; | ||
| 1189 | } | ||
| 1190 | |||
| 1191 | newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL); | ||
| 1192 | if (!newclient) { | ||
| 1193 | sms_err("Failed to allocate memory for client."); | ||
| 1194 | return -ENOMEM; | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | INIT_LIST_HEAD(&newclient->idlist); | ||
| 1198 | newclient->coredev = coredev; | ||
| 1199 | newclient->onresponse_handler = params->onresponse_handler; | ||
| 1200 | newclient->onremove_handler = params->onremove_handler; | ||
| 1201 | newclient->context = params->context; | ||
| 1202 | list_add_locked(&newclient->entry, &coredev->clients, | ||
| 1203 | &coredev->clientslock); | ||
| 1204 | smscore_validate_client(coredev, newclient, params->data_type, | ||
| 1205 | params->initial_id); | ||
| 1206 | *client = newclient; | ||
| 1207 | sms_debug("%p %d %d", params->context, params->data_type, | ||
| 1208 | params->initial_id); | ||
| 1209 | |||
| 1210 | return 0; | ||
| 1211 | } | ||
| 1212 | EXPORT_SYMBOL_GPL(smscore_register_client); | ||
| 1213 | |||
| 1214 | /** | ||
| 1215 | * frees smsclient object and all subclients associated with it | ||
| 1216 | * | ||
| 1217 | * @param client pointer to smsclient object returned by | ||
| 1218 | * smscore_register_client | ||
| 1219 | * | ||
| 1220 | */ | ||
| 1221 | void smscore_unregister_client(struct smscore_client_t *client) | ||
| 1222 | { | ||
| 1223 | struct smscore_device_t *coredev = client->coredev; | ||
| 1224 | unsigned long flags; | ||
| 1225 | |||
| 1226 | spin_lock_irqsave(&coredev->clientslock, flags); | ||
| 1227 | |||
| 1228 | |||
| 1229 | while (!list_empty(&client->idlist)) { | ||
| 1230 | struct smscore_idlist_t *identry = | ||
| 1231 | (struct smscore_idlist_t *) client->idlist.next; | ||
| 1232 | list_del(&identry->entry); | ||
| 1233 | kfree(identry); | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | sms_info("%p", client->context); | ||
| 1237 | |||
| 1238 | list_del(&client->entry); | ||
| 1239 | kfree(client); | ||
| 1240 | |||
| 1241 | spin_unlock_irqrestore(&coredev->clientslock, flags); | ||
| 1242 | } | ||
| 1243 | EXPORT_SYMBOL_GPL(smscore_unregister_client); | ||
| 1244 | |||
| 1245 | /** | ||
| 1246 | * verifies that source id is not taken by another client, | ||
| 1247 | * calls device handler to send requests to the device | ||
| 1248 | * | ||
| 1249 | * @param client pointer to smsclient object returned by | ||
| 1250 | * smscore_register_client | ||
| 1251 | * @param buffer pointer to a request buffer | ||
| 1252 | * @param size size (in bytes) of request buffer | ||
| 1253 | * | ||
| 1254 | * @return 0 on success, <0 on error. | ||
| 1255 | */ | ||
| 1256 | int smsclient_sendrequest(struct smscore_client_t *client, | ||
| 1257 | void *buffer, size_t size) | ||
| 1258 | { | ||
| 1259 | struct smscore_device_t *coredev; | ||
| 1260 | struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer; | ||
| 1261 | int rc; | ||
| 1262 | |||
| 1263 | if (client == NULL) { | ||
| 1264 | sms_err("Got NULL client"); | ||
| 1265 | return -EINVAL; | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | coredev = client->coredev; | ||
| 1269 | |||
| 1270 | /* check that no other channel with same id exists */ | ||
| 1271 | if (coredev == NULL) { | ||
| 1272 | sms_err("Got NULL coredev"); | ||
| 1273 | return -EINVAL; | ||
| 1274 | } | ||
| 1275 | |||
| 1276 | rc = smscore_validate_client(client->coredev, client, 0, | ||
| 1277 | phdr->msgSrcId); | ||
| 1278 | if (rc < 0) | ||
| 1279 | return rc; | ||
| 1280 | |||
| 1281 | return coredev->sendrequest_handler(coredev->context, buffer, size); | ||
| 1282 | } | ||
| 1283 | EXPORT_SYMBOL_GPL(smsclient_sendrequest); | ||
| 1284 | |||
| 1285 | |||
| 1286 | /* old GPIO managements implementation */ | ||
| 1287 | int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin, | ||
| 1288 | struct smscore_config_gpio *pinconfig) | ||
| 1289 | { | ||
| 1290 | struct { | ||
| 1291 | struct SmsMsgHdr_ST hdr; | ||
| 1292 | u32 data[6]; | ||
| 1293 | } msg; | ||
| 1294 | |||
| 1295 | if (coredev->device_flags & SMS_DEVICE_FAMILY2) { | ||
| 1296 | msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
| 1297 | msg.hdr.msgDstId = HIF_TASK; | ||
| 1298 | msg.hdr.msgFlags = 0; | ||
| 1299 | msg.hdr.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ; | ||
| 1300 | msg.hdr.msgLength = sizeof(msg); | ||
| 1301 | |||
| 1302 | msg.data[0] = pin; | ||
| 1303 | msg.data[1] = pinconfig->pullupdown; | ||
| 1304 | |||
| 1305 | /* Convert slew rate for Nova: Fast(0) = 3 / Slow(1) = 0; */ | ||
| 1306 | msg.data[2] = pinconfig->outputslewrate == 0 ? 3 : 0; | ||
| 1307 | |||
| 1308 | switch (pinconfig->outputdriving) { | ||
| 1309 | case SMS_GPIO_OUTPUTDRIVING_16mA: | ||
| 1310 | msg.data[3] = 7; /* Nova - 16mA */ | ||
| 1311 | break; | ||
| 1312 | case SMS_GPIO_OUTPUTDRIVING_12mA: | ||
| 1313 | msg.data[3] = 5; /* Nova - 11mA */ | ||
| 1314 | break; | ||
| 1315 | case SMS_GPIO_OUTPUTDRIVING_8mA: | ||
| 1316 | msg.data[3] = 3; /* Nova - 7mA */ | ||
| 1317 | break; | ||
| 1318 | case SMS_GPIO_OUTPUTDRIVING_4mA: | ||
| 1319 | default: | ||
| 1320 | msg.data[3] = 2; /* Nova - 4mA */ | ||
| 1321 | break; | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | msg.data[4] = pinconfig->direction; | ||
| 1325 | msg.data[5] = 0; | ||
| 1326 | } else /* TODO: SMS_DEVICE_FAMILY1 */ | ||
| 1327 | return -EINVAL; | ||
| 1328 | |||
| 1329 | return coredev->sendrequest_handler(coredev->context, | ||
| 1330 | &msg, sizeof(msg)); | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level) | ||
| 1334 | { | ||
| 1335 | struct { | ||
| 1336 | struct SmsMsgHdr_ST hdr; | ||
| 1337 | u32 data[3]; | ||
| 1338 | } msg; | ||
| 1339 | |||
| 1340 | if (pin > MAX_GPIO_PIN_NUMBER) | ||
| 1341 | return -EINVAL; | ||
| 1342 | |||
| 1343 | msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
| 1344 | msg.hdr.msgDstId = HIF_TASK; | ||
| 1345 | msg.hdr.msgFlags = 0; | ||
| 1346 | msg.hdr.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ; | ||
| 1347 | msg.hdr.msgLength = sizeof(msg); | ||
| 1348 | |||
| 1349 | msg.data[0] = pin; | ||
| 1350 | msg.data[1] = level ? 1 : 0; | ||
| 1351 | msg.data[2] = 0; | ||
| 1352 | |||
| 1353 | return coredev->sendrequest_handler(coredev->context, | ||
| 1354 | &msg, sizeof(msg)); | ||
| 1355 | } | ||
| 1356 | |||
| 1357 | /* new GPIO management implementation */ | ||
| 1358 | static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum, | ||
| 1359 | u32 *pGroupNum, u32 *pGroupCfg) { | ||
| 1360 | |||
| 1361 | *pGroupCfg = 1; | ||
| 1362 | |||
| 1363 | if (PinNum <= 1) { | ||
| 1364 | *pTranslatedPinNum = 0; | ||
| 1365 | *pGroupNum = 9; | ||
| 1366 | *pGroupCfg = 2; | ||
| 1367 | } else if (PinNum >= 2 && PinNum <= 6) { | ||
| 1368 | *pTranslatedPinNum = 2; | ||
| 1369 | *pGroupNum = 0; | ||
| 1370 | *pGroupCfg = 2; | ||
| 1371 | } else if (PinNum >= 7 && PinNum <= 11) { | ||
| 1372 | *pTranslatedPinNum = 7; | ||
| 1373 | *pGroupNum = 1; | ||
| 1374 | } else if (PinNum >= 12 && PinNum <= 15) { | ||
| 1375 | *pTranslatedPinNum = 12; | ||
| 1376 | *pGroupNum = 2; | ||
| 1377 | *pGroupCfg = 3; | ||
| 1378 | } else if (PinNum == 16) { | ||
| 1379 | *pTranslatedPinNum = 16; | ||
| 1380 | *pGroupNum = 23; | ||
| 1381 | } else if (PinNum >= 17 && PinNum <= 24) { | ||
| 1382 | *pTranslatedPinNum = 17; | ||
| 1383 | *pGroupNum = 3; | ||
| 1384 | } else if (PinNum == 25) { | ||
| 1385 | *pTranslatedPinNum = 25; | ||
| 1386 | *pGroupNum = 6; | ||
| 1387 | } else if (PinNum >= 26 && PinNum <= 28) { | ||
| 1388 | *pTranslatedPinNum = 26; | ||
| 1389 | *pGroupNum = 4; | ||
| 1390 | } else if (PinNum == 29) { | ||
| 1391 | *pTranslatedPinNum = 29; | ||
| 1392 | *pGroupNum = 5; | ||
| 1393 | *pGroupCfg = 2; | ||
| 1394 | } else if (PinNum == 30) { | ||
| 1395 | *pTranslatedPinNum = 30; | ||
| 1396 | *pGroupNum = 8; | ||
| 1397 | } else if (PinNum == 31) { | ||
| 1398 | *pTranslatedPinNum = 31; | ||
| 1399 | *pGroupNum = 17; | ||
| 1400 | } else | ||
| 1401 | return -1; | ||
| 1402 | |||
| 1403 | *pGroupCfg <<= 24; | ||
| 1404 | |||
| 1405 | return 0; | ||
| 1406 | } | ||
| 1407 | |||
| 1408 | int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, | ||
| 1409 | struct smscore_gpio_config *pGpioConfig) { | ||
| 1410 | |||
| 1411 | u32 totalLen; | ||
| 1412 | u32 TranslatedPinNum = 0; | ||
| 1413 | u32 GroupNum = 0; | ||
| 1414 | u32 ElectricChar; | ||
| 1415 | u32 groupCfg; | ||
| 1416 | void *buffer; | ||
| 1417 | int rc; | ||
| 1418 | |||
| 1419 | struct SetGpioMsg { | ||
| 1420 | struct SmsMsgHdr_ST xMsgHeader; | ||
| 1421 | u32 msgData[6]; | ||
| 1422 | } *pMsg; | ||
| 1423 | |||
| 1424 | |||
| 1425 | if (PinNum > MAX_GPIO_PIN_NUMBER) | ||
| 1426 | return -EINVAL; | ||
| 1427 | |||
| 1428 | if (pGpioConfig == NULL) | ||
| 1429 | return -EINVAL; | ||
| 1430 | |||
| 1431 | totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6); | ||
| 1432 | |||
| 1433 | buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, | ||
| 1434 | GFP_KERNEL | GFP_DMA); | ||
| 1435 | if (!buffer) | ||
| 1436 | return -ENOMEM; | ||
| 1437 | |||
| 1438 | pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); | ||
| 1439 | |||
| 1440 | pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
| 1441 | pMsg->xMsgHeader.msgDstId = HIF_TASK; | ||
| 1442 | pMsg->xMsgHeader.msgFlags = 0; | ||
| 1443 | pMsg->xMsgHeader.msgLength = (u16) totalLen; | ||
| 1444 | pMsg->msgData[0] = PinNum; | ||
| 1445 | |||
| 1446 | if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) { | ||
| 1447 | pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ; | ||
| 1448 | if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum, | ||
| 1449 | &groupCfg) != 0) { | ||
| 1450 | rc = -EINVAL; | ||
| 1451 | goto free; | ||
| 1452 | } | ||
| 1453 | |||
| 1454 | pMsg->msgData[1] = TranslatedPinNum; | ||
| 1455 | pMsg->msgData[2] = GroupNum; | ||
| 1456 | ElectricChar = (pGpioConfig->PullUpDown) | ||
| 1457 | | (pGpioConfig->InputCharacteristics << 2) | ||
| 1458 | | (pGpioConfig->OutputSlewRate << 3) | ||
| 1459 | | (pGpioConfig->OutputDriving << 4); | ||
| 1460 | pMsg->msgData[3] = ElectricChar; | ||
| 1461 | pMsg->msgData[4] = pGpioConfig->Direction; | ||
| 1462 | pMsg->msgData[5] = groupCfg; | ||
| 1463 | } else { | ||
| 1464 | pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ; | ||
| 1465 | pMsg->msgData[1] = pGpioConfig->PullUpDown; | ||
| 1466 | pMsg->msgData[2] = pGpioConfig->OutputSlewRate; | ||
| 1467 | pMsg->msgData[3] = pGpioConfig->OutputDriving; | ||
| 1468 | pMsg->msgData[4] = pGpioConfig->Direction; | ||
| 1469 | pMsg->msgData[5] = 0; | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); | ||
| 1473 | rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, | ||
| 1474 | &coredev->gpio_configuration_done); | ||
| 1475 | |||
| 1476 | if (rc != 0) { | ||
| 1477 | if (rc == -ETIME) | ||
| 1478 | sms_err("smscore_gpio_configure timeout"); | ||
| 1479 | else | ||
| 1480 | sms_err("smscore_gpio_configure error"); | ||
| 1481 | } | ||
| 1482 | free: | ||
| 1483 | kfree(buffer); | ||
| 1484 | |||
| 1485 | return rc; | ||
| 1486 | } | ||
| 1487 | |||
| 1488 | int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum, | ||
| 1489 | u8 NewLevel) { | ||
| 1490 | |||
| 1491 | u32 totalLen; | ||
| 1492 | int rc; | ||
| 1493 | void *buffer; | ||
| 1494 | |||
| 1495 | struct SetGpioMsg { | ||
| 1496 | struct SmsMsgHdr_ST xMsgHeader; | ||
| 1497 | u32 msgData[3]; /* keep it 3 ! */ | ||
| 1498 | } *pMsg; | ||
| 1499 | |||
| 1500 | if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER)) | ||
| 1501 | return -EINVAL; | ||
| 1502 | |||
| 1503 | totalLen = sizeof(struct SmsMsgHdr_ST) + | ||
| 1504 | (3 * sizeof(u32)); /* keep it 3 ! */ | ||
| 1505 | |||
| 1506 | buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, | ||
| 1507 | GFP_KERNEL | GFP_DMA); | ||
| 1508 | if (!buffer) | ||
| 1509 | return -ENOMEM; | ||
| 1510 | |||
| 1511 | pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); | ||
| 1512 | |||
| 1513 | pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
| 1514 | pMsg->xMsgHeader.msgDstId = HIF_TASK; | ||
| 1515 | pMsg->xMsgHeader.msgFlags = 0; | ||
| 1516 | pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ; | ||
| 1517 | pMsg->xMsgHeader.msgLength = (u16) totalLen; | ||
| 1518 | pMsg->msgData[0] = PinNum; | ||
| 1519 | pMsg->msgData[1] = NewLevel; | ||
| 1520 | |||
| 1521 | /* Send message to SMS */ | ||
| 1522 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); | ||
| 1523 | rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, | ||
| 1524 | &coredev->gpio_set_level_done); | ||
| 1525 | |||
| 1526 | if (rc != 0) { | ||
| 1527 | if (rc == -ETIME) | ||
| 1528 | sms_err("smscore_gpio_set_level timeout"); | ||
| 1529 | else | ||
| 1530 | sms_err("smscore_gpio_set_level error"); | ||
| 1531 | } | ||
| 1532 | kfree(buffer); | ||
| 1533 | |||
| 1534 | return rc; | ||
| 1535 | } | ||
| 1536 | |||
| 1537 | int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum, | ||
| 1538 | u8 *level) { | ||
| 1539 | |||
| 1540 | u32 totalLen; | ||
| 1541 | int rc; | ||
| 1542 | void *buffer; | ||
| 1543 | |||
| 1544 | struct SetGpioMsg { | ||
| 1545 | struct SmsMsgHdr_ST xMsgHeader; | ||
| 1546 | u32 msgData[2]; | ||
| 1547 | } *pMsg; | ||
| 1548 | |||
| 1549 | |||
| 1550 | if (PinNum > MAX_GPIO_PIN_NUMBER) | ||
| 1551 | return -EINVAL; | ||
| 1552 | |||
| 1553 | totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32)); | ||
| 1554 | |||
| 1555 | buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, | ||
| 1556 | GFP_KERNEL | GFP_DMA); | ||
| 1557 | if (!buffer) | ||
| 1558 | return -ENOMEM; | ||
| 1559 | |||
| 1560 | pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); | ||
| 1561 | |||
| 1562 | pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
| 1563 | pMsg->xMsgHeader.msgDstId = HIF_TASK; | ||
| 1564 | pMsg->xMsgHeader.msgFlags = 0; | ||
| 1565 | pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ; | ||
| 1566 | pMsg->xMsgHeader.msgLength = (u16) totalLen; | ||
| 1567 | pMsg->msgData[0] = PinNum; | ||
| 1568 | pMsg->msgData[1] = 0; | ||
| 1569 | |||
| 1570 | /* Send message to SMS */ | ||
| 1571 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); | ||
| 1572 | rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, | ||
| 1573 | &coredev->gpio_get_level_done); | ||
| 1574 | |||
| 1575 | if (rc != 0) { | ||
| 1576 | if (rc == -ETIME) | ||
| 1577 | sms_err("smscore_gpio_get_level timeout"); | ||
| 1578 | else | ||
| 1579 | sms_err("smscore_gpio_get_level error"); | ||
| 1580 | } | ||
| 1581 | kfree(buffer); | ||
| 1582 | |||
| 1583 | /* Its a race between other gpio_get_level() and the copy of the single | ||
| 1584 | * global 'coredev->gpio_get_res' to the function's variable 'level' | ||
| 1585 | */ | ||
| 1586 | *level = coredev->gpio_get_res; | ||
| 1587 | |||
| 1588 | return rc; | ||
| 1589 | } | ||
| 1590 | |||
| 1591 | static int __init smscore_module_init(void) | ||
| 1592 | { | ||
| 1593 | int rc = 0; | ||
| 1594 | |||
| 1595 | INIT_LIST_HEAD(&g_smscore_notifyees); | ||
| 1596 | INIT_LIST_HEAD(&g_smscore_devices); | ||
| 1597 | kmutex_init(&g_smscore_deviceslock); | ||
| 1598 | |||
| 1599 | INIT_LIST_HEAD(&g_smscore_registry); | ||
| 1600 | kmutex_init(&g_smscore_registrylock); | ||
| 1601 | |||
| 1602 | return rc; | ||
| 1603 | } | ||
| 1604 | |||
| 1605 | static void __exit smscore_module_exit(void) | ||
| 1606 | { | ||
| 1607 | kmutex_lock(&g_smscore_deviceslock); | ||
| 1608 | while (!list_empty(&g_smscore_notifyees)) { | ||
| 1609 | struct smscore_device_notifyee_t *notifyee = | ||
| 1610 | (struct smscore_device_notifyee_t *) | ||
| 1611 | g_smscore_notifyees.next; | ||
| 1612 | |||
| 1613 | list_del(¬ifyee->entry); | ||
| 1614 | kfree(notifyee); | ||
| 1615 | } | ||
| 1616 | kmutex_unlock(&g_smscore_deviceslock); | ||
| 1617 | |||
| 1618 | kmutex_lock(&g_smscore_registrylock); | ||
| 1619 | while (!list_empty(&g_smscore_registry)) { | ||
| 1620 | struct smscore_registry_entry_t *entry = | ||
| 1621 | (struct smscore_registry_entry_t *) | ||
| 1622 | g_smscore_registry.next; | ||
| 1623 | |||
| 1624 | list_del(&entry->entry); | ||
| 1625 | kfree(entry); | ||
| 1626 | } | ||
| 1627 | kmutex_unlock(&g_smscore_registrylock); | ||
| 1628 | |||
| 1629 | sms_debug(""); | ||
| 1630 | } | ||
| 1631 | |||
| 1632 | module_init(smscore_module_init); | ||
| 1633 | module_exit(smscore_module_exit); | ||
| 1634 | |||
| 1635 | MODULE_DESCRIPTION("Siano MDTV Core module"); | ||
| 1636 | MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)"); | ||
| 1637 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/usb/siano/smscoreapi.h b/drivers/media/usb/siano/smscoreapi.h deleted file mode 100644 index c592ae090397..000000000000 --- a/drivers/media/usb/siano/smscoreapi.h +++ /dev/null | |||
| @@ -1,775 +0,0 @@ | |||
| 1 | /**************************************************************** | ||
| 2 | |||
| 3 | Siano Mobile Silicon, Inc. | ||
| 4 | MDTV receiver kernel modules. | ||
| 5 | Copyright (C) 2006-2008, Uri Shkolnik, Anatoly Greenblat | ||
| 6 | |||
| 7 | This program is free software: you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation, either version 2 of the License, or | ||
| 10 | (at your option) any later version. | ||
| 11 | |||
| 12 | This program is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 19 | |||
| 20 | ****************************************************************/ | ||
| 21 | |||
| 22 | #ifndef __SMS_CORE_API_H__ | ||
| 23 | #define __SMS_CORE_API_H__ | ||
| 24 | |||
| 25 | #include <linux/device.h> | ||
| 26 | #include <linux/list.h> | ||
| 27 | #include <linux/mm.h> | ||
| 28 | #include <linux/scatterlist.h> | ||
| 29 | #include <linux/types.h> | ||
| 30 | #include <linux/mutex.h> | ||
| 31 | #include <linux/wait.h> | ||
| 32 | #include <linux/timer.h> | ||
| 33 | |||
| 34 | #include <asm/page.h> | ||
| 35 | |||
| 36 | #include "smsir.h" | ||
| 37 | |||
| 38 | #define kmutex_init(_p_) mutex_init(_p_) | ||
| 39 | #define kmutex_lock(_p_) mutex_lock(_p_) | ||
| 40 | #define kmutex_trylock(_p_) mutex_trylock(_p_) | ||
| 41 | #define kmutex_unlock(_p_) mutex_unlock(_p_) | ||
| 42 | |||
| 43 | #ifndef min | ||
| 44 | #define min(a, b) (((a) < (b)) ? (a) : (b)) | ||
| 45 | #endif | ||
| 46 | |||
| 47 | #define SMS_PROTOCOL_MAX_RAOUNDTRIP_MS (10000) | ||
| 48 | #define SMS_ALLOC_ALIGNMENT 128 | ||
| 49 | #define SMS_DMA_ALIGNMENT 16 | ||
| 50 | #define SMS_ALIGN_ADDRESS(addr) \ | ||
| 51 | ((((uintptr_t)(addr)) + (SMS_DMA_ALIGNMENT-1)) & ~(SMS_DMA_ALIGNMENT-1)) | ||
| 52 | |||
| 53 | #define SMS_DEVICE_FAMILY2 1 | ||
| 54 | #define SMS_ROM_NO_RESPONSE 2 | ||
| 55 | #define SMS_DEVICE_NOT_READY 0x8000000 | ||
| 56 | |||
| 57 | enum sms_device_type_st { | ||
| 58 | SMS_STELLAR = 0, | ||
| 59 | SMS_NOVA_A0, | ||
| 60 | SMS_NOVA_B0, | ||
| 61 | SMS_VEGA, | ||
| 62 | SMS_NUM_OF_DEVICE_TYPES | ||
| 63 | }; | ||
| 64 | |||
| 65 | struct smscore_device_t; | ||
| 66 | struct smscore_client_t; | ||
| 67 | struct smscore_buffer_t; | ||
| 68 | |||
| 69 | typedef int (*hotplug_t)(struct smscore_device_t *coredev, | ||
| 70 | struct device *device, int arrival); | ||
| 71 | |||
| 72 | typedef int (*setmode_t)(void *context, int mode); | ||
| 73 | typedef void (*detectmode_t)(void *context, int *mode); | ||
| 74 | typedef int (*sendrequest_t)(void *context, void *buffer, size_t size); | ||
| 75 | typedef int (*loadfirmware_t)(void *context, void *buffer, size_t size); | ||
| 76 | typedef int (*preload_t)(void *context); | ||
| 77 | typedef int (*postload_t)(void *context); | ||
| 78 | |||
| 79 | typedef int (*onresponse_t)(void *context, struct smscore_buffer_t *cb); | ||
| 80 | typedef void (*onremove_t)(void *context); | ||
| 81 | |||
| 82 | struct smscore_buffer_t { | ||
| 83 | /* public members, once passed to clients can be changed freely */ | ||
| 84 | struct list_head entry; | ||
| 85 | int size; | ||
| 86 | int offset; | ||
| 87 | |||
| 88 | /* private members, read-only for clients */ | ||
| 89 | void *p; | ||
| 90 | dma_addr_t phys; | ||
| 91 | unsigned long offset_in_common; | ||
| 92 | }; | ||
| 93 | |||
| 94 | struct smsdevice_params_t { | ||
| 95 | struct device *device; | ||
| 96 | |||
| 97 | int buffer_size; | ||
| 98 | int num_buffers; | ||
| 99 | |||
| 100 | char devpath[32]; | ||
| 101 | unsigned long flags; | ||
| 102 | |||
| 103 | setmode_t setmode_handler; | ||
| 104 | detectmode_t detectmode_handler; | ||
| 105 | sendrequest_t sendrequest_handler; | ||
| 106 | preload_t preload_handler; | ||
| 107 | postload_t postload_handler; | ||
| 108 | |||
| 109 | void *context; | ||
| 110 | enum sms_device_type_st device_type; | ||
| 111 | }; | ||
| 112 | |||
| 113 | struct smsclient_params_t { | ||
| 114 | int initial_id; | ||
| 115 | int data_type; | ||
| 116 | onresponse_t onresponse_handler; | ||
| 117 | onremove_t onremove_handler; | ||
| 118 | void *context; | ||
| 119 | }; | ||
| 120 | |||
| 121 | struct smscore_device_t { | ||
| 122 | struct list_head entry; | ||
| 123 | |||
| 124 | struct list_head clients; | ||
| 125 | struct list_head subclients; | ||
| 126 | spinlock_t clientslock; | ||
| 127 | |||
| 128 | struct list_head buffers; | ||
| 129 | spinlock_t bufferslock; | ||
| 130 | int num_buffers; | ||
| 131 | |||
| 132 | void *common_buffer; | ||
| 133 | int common_buffer_size; | ||
| 134 | dma_addr_t common_buffer_phys; | ||
| 135 | |||
| 136 | void *context; | ||
| 137 | struct device *device; | ||
| 138 | |||
| 139 | char devpath[32]; | ||
| 140 | unsigned long device_flags; | ||
| 141 | |||
| 142 | setmode_t setmode_handler; | ||
| 143 | detectmode_t detectmode_handler; | ||
| 144 | sendrequest_t sendrequest_handler; | ||
| 145 | preload_t preload_handler; | ||
| 146 | postload_t postload_handler; | ||
| 147 | |||
| 148 | int mode, modes_supported; | ||
| 149 | |||
| 150 | /* host <--> device messages */ | ||
| 151 | struct completion version_ex_done, data_download_done, trigger_done; | ||
| 152 | struct completion init_device_done, reload_start_done, resume_done; | ||
| 153 | struct completion gpio_configuration_done, gpio_set_level_done; | ||
| 154 | struct completion gpio_get_level_done, ir_init_done; | ||
| 155 | |||
| 156 | /* Buffer management */ | ||
| 157 | wait_queue_head_t buffer_mng_waitq; | ||
| 158 | |||
| 159 | /* GPIO */ | ||
| 160 | int gpio_get_res; | ||
| 161 | |||
| 162 | /* Target hardware board */ | ||
| 163 | int board_id; | ||
| 164 | |||
| 165 | /* Firmware */ | ||
| 166 | u8 *fw_buf; | ||
| 167 | u32 fw_buf_size; | ||
| 168 | |||
| 169 | /* Infrared (IR) */ | ||
| 170 | struct ir_t ir; | ||
| 171 | |||
| 172 | int led_state; | ||
| 173 | }; | ||
| 174 | |||
| 175 | /* GPIO definitions for antenna frequency domain control (SMS8021) */ | ||
| 176 | #define SMS_ANTENNA_GPIO_0 1 | ||
| 177 | #define SMS_ANTENNA_GPIO_1 0 | ||
| 178 | |||
| 179 | #define BW_8_MHZ 0 | ||
| 180 | #define BW_7_MHZ 1 | ||
| 181 | #define BW_6_MHZ 2 | ||
| 182 | #define BW_5_MHZ 3 | ||
| 183 | #define BW_ISDBT_1SEG 4 | ||
| 184 | #define BW_ISDBT_3SEG 5 | ||
| 185 | |||
| 186 | #define MSG_HDR_FLAG_SPLIT_MSG 4 | ||
| 187 | |||
| 188 | #define MAX_GPIO_PIN_NUMBER 31 | ||
| 189 | |||
| 190 | #define HIF_TASK 11 | ||
| 191 | #define SMS_HOST_LIB 150 | ||
| 192 | #define DVBT_BDA_CONTROL_MSG_ID 201 | ||
| 193 | |||
| 194 | #define SMS_MAX_PAYLOAD_SIZE 240 | ||
| 195 | #define SMS_TUNE_TIMEOUT 500 | ||
| 196 | |||
| 197 | #define MSG_SMS_GPIO_CONFIG_REQ 507 | ||
| 198 | #define MSG_SMS_GPIO_CONFIG_RES 508 | ||
| 199 | #define MSG_SMS_GPIO_SET_LEVEL_REQ 509 | ||
| 200 | #define MSG_SMS_GPIO_SET_LEVEL_RES 510 | ||
| 201 | #define MSG_SMS_GPIO_GET_LEVEL_REQ 511 | ||
| 202 | #define MSG_SMS_GPIO_GET_LEVEL_RES 512 | ||
| 203 | #define MSG_SMS_RF_TUNE_REQ 561 | ||
| 204 | #define MSG_SMS_RF_TUNE_RES 562 | ||
| 205 | #define MSG_SMS_INIT_DEVICE_REQ 578 | ||
| 206 | #define MSG_SMS_INIT_DEVICE_RES 579 | ||
| 207 | #define MSG_SMS_ADD_PID_FILTER_REQ 601 | ||
| 208 | #define MSG_SMS_ADD_PID_FILTER_RES 602 | ||
| 209 | #define MSG_SMS_REMOVE_PID_FILTER_REQ 603 | ||
| 210 | #define MSG_SMS_REMOVE_PID_FILTER_RES 604 | ||
| 211 | #define MSG_SMS_DAB_CHANNEL 607 | ||
| 212 | #define MSG_SMS_GET_PID_FILTER_LIST_REQ 608 | ||
| 213 | #define MSG_SMS_GET_PID_FILTER_LIST_RES 609 | ||
| 214 | #define MSG_SMS_GET_STATISTICS_RES 616 | ||
| 215 | #define MSG_SMS_GET_STATISTICS_REQ 615 | ||
| 216 | #define MSG_SMS_HO_PER_SLICES_IND 630 | ||
| 217 | #define MSG_SMS_SET_ANTENNA_CONFIG_REQ 651 | ||
| 218 | #define MSG_SMS_SET_ANTENNA_CONFIG_RES 652 | ||
| 219 | #define MSG_SMS_SLEEP_RESUME_COMP_IND 655 | ||
| 220 | #define MSG_SMS_DATA_DOWNLOAD_REQ 660 | ||
| 221 | #define MSG_SMS_DATA_DOWNLOAD_RES 661 | ||
| 222 | #define MSG_SMS_SWDOWNLOAD_TRIGGER_REQ 664 | ||
| 223 | #define MSG_SMS_SWDOWNLOAD_TRIGGER_RES 665 | ||
| 224 | #define MSG_SMS_SWDOWNLOAD_BACKDOOR_REQ 666 | ||
| 225 | #define MSG_SMS_SWDOWNLOAD_BACKDOOR_RES 667 | ||
| 226 | #define MSG_SMS_GET_VERSION_EX_REQ 668 | ||
| 227 | #define MSG_SMS_GET_VERSION_EX_RES 669 | ||
| 228 | #define MSG_SMS_SET_CLOCK_OUTPUT_REQ 670 | ||
| 229 | #define MSG_SMS_I2C_SET_FREQ_REQ 685 | ||
| 230 | #define MSG_SMS_GENERIC_I2C_REQ 687 | ||
| 231 | #define MSG_SMS_GENERIC_I2C_RES 688 | ||
| 232 | #define MSG_SMS_DVBT_BDA_DATA 693 | ||
| 233 | #define MSG_SW_RELOAD_REQ 697 | ||
| 234 | #define MSG_SMS_DATA_MSG 699 | ||
| 235 | #define MSG_SW_RELOAD_START_REQ 702 | ||
| 236 | #define MSG_SW_RELOAD_START_RES 703 | ||
| 237 | #define MSG_SW_RELOAD_EXEC_REQ 704 | ||
| 238 | #define MSG_SW_RELOAD_EXEC_RES 705 | ||
| 239 | #define MSG_SMS_SPI_INT_LINE_SET_REQ 710 | ||
| 240 | #define MSG_SMS_GPIO_CONFIG_EX_REQ 712 | ||
| 241 | #define MSG_SMS_GPIO_CONFIG_EX_RES 713 | ||
| 242 | #define MSG_SMS_ISDBT_TUNE_REQ 776 | ||
| 243 | #define MSG_SMS_ISDBT_TUNE_RES 777 | ||
| 244 | #define MSG_SMS_TRANSMISSION_IND 782 | ||
| 245 | #define MSG_SMS_START_IR_REQ 800 | ||
| 246 | #define MSG_SMS_START_IR_RES 801 | ||
| 247 | #define MSG_SMS_IR_SAMPLES_IND 802 | ||
| 248 | #define MSG_SMS_SIGNAL_DETECTED_IND 827 | ||
| 249 | #define MSG_SMS_NO_SIGNAL_IND 828 | ||
| 250 | |||
| 251 | #define SMS_INIT_MSG_EX(ptr, type, src, dst, len) do { \ | ||
| 252 | (ptr)->msgType = type; (ptr)->msgSrcId = src; (ptr)->msgDstId = dst; \ | ||
| 253 | (ptr)->msgLength = len; (ptr)->msgFlags = 0; \ | ||
| 254 | } while (0) | ||
| 255 | |||
| 256 | #define SMS_INIT_MSG(ptr, type, len) \ | ||
| 257 | SMS_INIT_MSG_EX(ptr, type, 0, HIF_TASK, len) | ||
| 258 | |||
| 259 | enum SMS_DVB3_EVENTS { | ||
| 260 | DVB3_EVENT_INIT = 0, | ||
| 261 | DVB3_EVENT_SLEEP, | ||
| 262 | DVB3_EVENT_HOTPLUG, | ||
| 263 | DVB3_EVENT_FE_LOCK, | ||
| 264 | DVB3_EVENT_FE_UNLOCK, | ||
| 265 | DVB3_EVENT_UNC_OK, | ||
| 266 | DVB3_EVENT_UNC_ERR | ||
| 267 | }; | ||
| 268 | |||
| 269 | enum SMS_DEVICE_MODE { | ||
| 270 | DEVICE_MODE_NONE = -1, | ||
| 271 | DEVICE_MODE_DVBT = 0, | ||
| 272 | DEVICE_MODE_DVBH, | ||
| 273 | DEVICE_MODE_DAB_TDMB, | ||
| 274 | DEVICE_MODE_DAB_TDMB_DABIP, | ||
| 275 | DEVICE_MODE_DVBT_BDA, | ||
| 276 | DEVICE_MODE_ISDBT, | ||
| 277 | DEVICE_MODE_ISDBT_BDA, | ||
| 278 | DEVICE_MODE_CMMB, | ||
| 279 | DEVICE_MODE_RAW_TUNER, | ||
| 280 | DEVICE_MODE_MAX, | ||
| 281 | }; | ||
| 282 | |||
| 283 | struct SmsMsgHdr_ST { | ||
| 284 | u16 msgType; | ||
| 285 | u8 msgSrcId; | ||
| 286 | u8 msgDstId; | ||
| 287 | u16 msgLength; /* Length of entire message, including header */ | ||
| 288 | u16 msgFlags; | ||
| 289 | }; | ||
| 290 | |||
| 291 | struct SmsMsgData_ST { | ||
| 292 | struct SmsMsgHdr_ST xMsgHeader; | ||
| 293 | u32 msgData[1]; | ||
| 294 | }; | ||
| 295 | |||
| 296 | struct SmsMsgData_ST2 { | ||
| 297 | struct SmsMsgHdr_ST xMsgHeader; | ||
| 298 | u32 msgData[2]; | ||
| 299 | }; | ||
| 300 | |||
| 301 | struct SmsDataDownload_ST { | ||
| 302 | struct SmsMsgHdr_ST xMsgHeader; | ||
| 303 | u32 MemAddr; | ||
| 304 | u8 Payload[SMS_MAX_PAYLOAD_SIZE]; | ||
| 305 | }; | ||
| 306 | |||
| 307 | struct SmsVersionRes_ST { | ||
| 308 | struct SmsMsgHdr_ST xMsgHeader; | ||
| 309 | |||
| 310 | u16 ChipModel; /* e.g. 0x1102 for SMS-1102 "Nova" */ | ||
| 311 | u8 Step; /* 0 - Step A */ | ||
| 312 | u8 MetalFix; /* 0 - Metal 0 */ | ||
| 313 | |||
| 314 | /* FirmwareId 0xFF if ROM, otherwise the | ||
| 315 | * value indicated by SMSHOSTLIB_DEVICE_MODES_E */ | ||
| 316 | u8 FirmwareId; | ||
| 317 | /* SupportedProtocols Bitwise OR combination of | ||
| 318 | * supported protocols */ | ||
| 319 | u8 SupportedProtocols; | ||
| 320 | |||
| 321 | u8 VersionMajor; | ||
| 322 | u8 VersionMinor; | ||
| 323 | u8 VersionPatch; | ||
| 324 | u8 VersionFieldPatch; | ||
| 325 | |||
| 326 | u8 RomVersionMajor; | ||
| 327 | u8 RomVersionMinor; | ||
| 328 | u8 RomVersionPatch; | ||
| 329 | u8 RomVersionFieldPatch; | ||
| 330 | |||
| 331 | u8 TextLabel[34]; | ||
| 332 | }; | ||
| 333 | |||
| 334 | struct SmsFirmware_ST { | ||
| 335 | u32 CheckSum; | ||
| 336 | u32 Length; | ||
| 337 | u32 StartAddress; | ||
| 338 | u8 Payload[1]; | ||
| 339 | }; | ||
| 340 | |||
| 341 | /* Statistics information returned as response for | ||
| 342 | * SmsHostApiGetStatistics_Req */ | ||
| 343 | struct SMSHOSTLIB_STATISTICS_ST { | ||
| 344 | u32 Reserved; /* Reserved */ | ||
| 345 | |||
| 346 | /* Common parameters */ | ||
| 347 | u32 IsRfLocked; /* 0 - not locked, 1 - locked */ | ||
| 348 | u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ | ||
| 349 | u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ | ||
| 350 | |||
| 351 | /* Reception quality */ | ||
| 352 | s32 SNR; /* dB */ | ||
| 353 | u32 BER; /* Post Viterbi BER [1E-5] */ | ||
| 354 | u32 FIB_CRC; /* CRC errors percentage, valid only for DAB */ | ||
| 355 | u32 TS_PER; /* Transport stream PER, | ||
| 356 | 0xFFFFFFFF indicate N/A, valid only for DVB-T/H */ | ||
| 357 | u32 MFER; /* DVB-H frame error rate in percentage, | ||
| 358 | 0xFFFFFFFF indicate N/A, valid only for DVB-H */ | ||
| 359 | s32 RSSI; /* dBm */ | ||
| 360 | s32 InBandPwr; /* In band power in dBM */ | ||
| 361 | s32 CarrierOffset; /* Carrier Offset in bin/1024 */ | ||
| 362 | |||
| 363 | /* Transmission parameters */ | ||
| 364 | u32 Frequency; /* Frequency in Hz */ | ||
| 365 | u32 Bandwidth; /* Bandwidth in MHz, valid only for DVB-T/H */ | ||
| 366 | u32 TransmissionMode; /* Transmission Mode, for DAB modes 1-4, | ||
| 367 | for DVB-T/H FFT mode carriers in Kilos */ | ||
| 368 | u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET, | ||
| 369 | valid only for DVB-T/H */ | ||
| 370 | u32 GuardInterval; /* Guard Interval from | ||
| 371 | SMSHOSTLIB_GUARD_INTERVALS_ET, valid only for DVB-T/H */ | ||
| 372 | u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET, | ||
| 373 | valid only for DVB-T/H */ | ||
| 374 | u32 LPCodeRate; /* Low Priority Code Rate from | ||
| 375 | SMSHOSTLIB_CODE_RATE_ET, valid only for DVB-T/H */ | ||
| 376 | u32 Hierarchy; /* Hierarchy from SMSHOSTLIB_HIERARCHY_ET, | ||
| 377 | valid only for DVB-T/H */ | ||
| 378 | u32 Constellation; /* Constellation from | ||
| 379 | SMSHOSTLIB_CONSTELLATION_ET, valid only for DVB-T/H */ | ||
| 380 | |||
| 381 | /* Burst parameters, valid only for DVB-H */ | ||
| 382 | u32 BurstSize; /* Current burst size in bytes, | ||
| 383 | valid only for DVB-H */ | ||
| 384 | u32 BurstDuration; /* Current burst duration in mSec, | ||
| 385 | valid only for DVB-H */ | ||
| 386 | u32 BurstCycleTime; /* Current burst cycle time in mSec, | ||
| 387 | valid only for DVB-H */ | ||
| 388 | u32 CalculatedBurstCycleTime;/* Current burst cycle time in mSec, | ||
| 389 | as calculated by demodulator, valid only for DVB-H */ | ||
| 390 | u32 NumOfRows; /* Number of rows in MPE table, | ||
| 391 | valid only for DVB-H */ | ||
| 392 | u32 NumOfPaddCols; /* Number of padding columns in MPE table, | ||
| 393 | valid only for DVB-H */ | ||
| 394 | u32 NumOfPunctCols; /* Number of puncturing columns in MPE table, | ||
| 395 | valid only for DVB-H */ | ||
| 396 | u32 ErrorTSPackets; /* Number of erroneous | ||
| 397 | transport-stream packets */ | ||
| 398 | u32 TotalTSPackets; /* Total number of transport-stream packets */ | ||
| 399 | u32 NumOfValidMpeTlbs; /* Number of MPE tables which do not include | ||
| 400 | errors after MPE RS decoding */ | ||
| 401 | u32 NumOfInvalidMpeTlbs;/* Number of MPE tables which include errors | ||
| 402 | after MPE RS decoding */ | ||
| 403 | u32 NumOfCorrectedMpeTlbs;/* Number of MPE tables which were | ||
| 404 | corrected by MPE RS decoding */ | ||
| 405 | /* Common params */ | ||
| 406 | u32 BERErrorCount; /* Number of errornous SYNC bits. */ | ||
| 407 | u32 BERBitCount; /* Total number of SYNC bits. */ | ||
| 408 | |||
| 409 | /* Interface information */ | ||
| 410 | u32 SmsToHostTxErrors; /* Total number of transmission errors. */ | ||
| 411 | |||
| 412 | /* DAB/T-DMB */ | ||
| 413 | u32 PreBER; /* DAB/T-DMB only: Pre Viterbi BER [1E-5] */ | ||
| 414 | |||
| 415 | /* DVB-H TPS parameters */ | ||
| 416 | u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; | ||
| 417 | if set to 0xFFFFFFFF cell_id not yet recovered */ | ||
| 418 | u32 DvbhSrvIndHP; /* DVB-H service indication info, bit 1 - | ||
| 419 | Time Slicing indicator, bit 0 - MPE-FEC indicator */ | ||
| 420 | u32 DvbhSrvIndLP; /* DVB-H service indication info, bit 1 - | ||
| 421 | Time Slicing indicator, bit 0 - MPE-FEC indicator */ | ||
| 422 | |||
| 423 | u32 NumMPEReceived; /* DVB-H, Num MPE section received */ | ||
| 424 | |||
| 425 | u32 ReservedFields[10]; /* Reserved */ | ||
| 426 | }; | ||
| 427 | |||
| 428 | struct SmsMsgStatisticsInfo_ST { | ||
| 429 | u32 RequestResult; | ||
| 430 | |||
| 431 | struct SMSHOSTLIB_STATISTICS_ST Stat; | ||
| 432 | |||
| 433 | /* Split the calc of the SNR in DAB */ | ||
| 434 | u32 Signal; /* dB */ | ||
| 435 | u32 Noise; /* dB */ | ||
| 436 | |||
| 437 | }; | ||
| 438 | |||
| 439 | struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST { | ||
| 440 | /* Per-layer information */ | ||
| 441 | u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET, | ||
| 442 | * 255 means layer does not exist */ | ||
| 443 | u32 Constellation; /* Constellation from SMSHOSTLIB_CONSTELLATION_ET, | ||
| 444 | * 255 means layer does not exist */ | ||
| 445 | u32 BER; /* Post Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */ | ||
| 446 | u32 BERErrorCount; /* Post Viterbi Error Bits Count */ | ||
| 447 | u32 BERBitCount; /* Post Viterbi Total Bits Count */ | ||
| 448 | u32 PreBER; /* Pre Viterbi BER [1E-5], 0xFFFFFFFF indicate N/A */ | ||
| 449 | u32 TS_PER; /* Transport stream PER [%], 0xFFFFFFFF indicate N/A */ | ||
| 450 | u32 ErrorTSPackets; /* Number of erroneous transport-stream packets */ | ||
| 451 | u32 TotalTSPackets; /* Total number of transport-stream packets */ | ||
| 452 | u32 TILdepthI; /* Time interleaver depth I parameter, | ||
| 453 | * 255 means layer does not exist */ | ||
| 454 | u32 NumberOfSegments; /* Number of segments in layer A, | ||
| 455 | * 255 means layer does not exist */ | ||
| 456 | u32 TMCCErrors; /* TMCC errors */ | ||
| 457 | }; | ||
| 458 | |||
| 459 | struct SMSHOSTLIB_STATISTICS_ISDBT_ST { | ||
| 460 | u32 StatisticsType; /* Enumerator identifying the type of the | ||
| 461 | * structure. Values are the same as | ||
| 462 | * SMSHOSTLIB_DEVICE_MODES_E | ||
| 463 | * | ||
| 464 | * This field MUST always be first in any | ||
| 465 | * statistics structure */ | ||
| 466 | |||
| 467 | u32 FullSize; /* Total size of the structure returned by the modem. | ||
| 468 | * If the size requested by the host is smaller than | ||
| 469 | * FullSize, the struct will be truncated */ | ||
| 470 | |||
| 471 | /* Common parameters */ | ||
| 472 | u32 IsRfLocked; /* 0 - not locked, 1 - locked */ | ||
| 473 | u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ | ||
| 474 | u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ | ||
| 475 | |||
| 476 | /* Reception quality */ | ||
| 477 | s32 SNR; /* dB */ | ||
| 478 | s32 RSSI; /* dBm */ | ||
| 479 | s32 InBandPwr; /* In band power in dBM */ | ||
| 480 | s32 CarrierOffset; /* Carrier Offset in Hz */ | ||
| 481 | |||
| 482 | /* Transmission parameters */ | ||
| 483 | u32 Frequency; /* Frequency in Hz */ | ||
| 484 | u32 Bandwidth; /* Bandwidth in MHz */ | ||
| 485 | u32 TransmissionMode; /* ISDB-T transmission mode */ | ||
| 486 | u32 ModemState; /* 0 - Acquisition, 1 - Locked */ | ||
| 487 | u32 GuardInterval; /* Guard Interval, 1 divided by value */ | ||
| 488 | u32 SystemType; /* ISDB-T system type (ISDB-T / ISDB-Tsb) */ | ||
| 489 | u32 PartialReception; /* TRUE - partial reception, FALSE otherwise */ | ||
| 490 | u32 NumOfLayers; /* Number of ISDB-T layers in the network */ | ||
| 491 | |||
| 492 | /* Per-layer information */ | ||
| 493 | /* Layers A, B and C */ | ||
| 494 | struct SMSHOSTLIB_ISDBT_LAYER_STAT_ST LayerInfo[3]; | ||
| 495 | /* Per-layer statistics, see SMSHOSTLIB_ISDBT_LAYER_STAT_ST */ | ||
| 496 | |||
| 497 | /* Interface information */ | ||
| 498 | u32 SmsToHostTxErrors; /* Total number of transmission errors. */ | ||
| 499 | }; | ||
| 500 | |||
| 501 | struct PID_STATISTICS_DATA_S { | ||
| 502 | struct PID_BURST_S { | ||
| 503 | u32 size; | ||
| 504 | u32 padding_cols; | ||
| 505 | u32 punct_cols; | ||
| 506 | u32 duration; | ||
| 507 | u32 cycle; | ||
| 508 | u32 calc_cycle; | ||
| 509 | } burst; | ||
| 510 | |||
| 511 | u32 tot_tbl_cnt; | ||
| 512 | u32 invalid_tbl_cnt; | ||
| 513 | u32 tot_cor_tbl; | ||
| 514 | }; | ||
| 515 | |||
| 516 | struct PID_DATA_S { | ||
| 517 | u32 pid; | ||
| 518 | u32 num_rows; | ||
| 519 | struct PID_STATISTICS_DATA_S pid_statistics; | ||
| 520 | }; | ||
| 521 | |||
| 522 | #define CORRECT_STAT_RSSI(_stat) ((_stat).RSSI *= -1) | ||
| 523 | #define CORRECT_STAT_BANDWIDTH(_stat) (_stat.Bandwidth = 8 - _stat.Bandwidth) | ||
| 524 | #define CORRECT_STAT_TRANSMISSON_MODE(_stat) \ | ||
| 525 | if (_stat.TransmissionMode == 0) \ | ||
| 526 | _stat.TransmissionMode = 2; \ | ||
| 527 | else if (_stat.TransmissionMode == 1) \ | ||
| 528 | _stat.TransmissionMode = 8; \ | ||
| 529 | else \ | ||
| 530 | _stat.TransmissionMode = 4; | ||
| 531 | |||
| 532 | struct TRANSMISSION_STATISTICS_S { | ||
| 533 | u32 Frequency; /* Frequency in Hz */ | ||
| 534 | u32 Bandwidth; /* Bandwidth in MHz */ | ||
| 535 | u32 TransmissionMode; /* FFT mode carriers in Kilos */ | ||
| 536 | u32 GuardInterval; /* Guard Interval from | ||
| 537 | SMSHOSTLIB_GUARD_INTERVALS_ET */ | ||
| 538 | u32 CodeRate; /* Code Rate from SMSHOSTLIB_CODE_RATE_ET */ | ||
| 539 | u32 LPCodeRate; /* Low Priority Code Rate from | ||
| 540 | SMSHOSTLIB_CODE_RATE_ET */ | ||
| 541 | u32 Hierarchy; /* Hierarchy from SMSHOSTLIB_HIERARCHY_ET */ | ||
| 542 | u32 Constellation; /* Constellation from | ||
| 543 | SMSHOSTLIB_CONSTELLATION_ET */ | ||
| 544 | |||
| 545 | /* DVB-H TPS parameters */ | ||
| 546 | u32 CellId; /* TPS Cell ID in bits 15..0, bits 31..16 zero; | ||
| 547 | if set to 0xFFFFFFFF cell_id not yet recovered */ | ||
| 548 | u32 DvbhSrvIndHP; /* DVB-H service indication info, bit 1 - | ||
| 549 | Time Slicing indicator, bit 0 - MPE-FEC indicator */ | ||
| 550 | u32 DvbhSrvIndLP; /* DVB-H service indication info, bit 1 - | ||
| 551 | Time Slicing indicator, bit 0 - MPE-FEC indicator */ | ||
| 552 | u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ | ||
| 553 | }; | ||
| 554 | |||
| 555 | struct RECEPTION_STATISTICS_S { | ||
| 556 | u32 IsRfLocked; /* 0 - not locked, 1 - locked */ | ||
| 557 | u32 IsDemodLocked; /* 0 - not locked, 1 - locked */ | ||
| 558 | u32 IsExternalLNAOn; /* 0 - external LNA off, 1 - external LNA on */ | ||
| 559 | |||
| 560 | u32 ModemState; /* from SMSHOSTLIB_DVB_MODEM_STATE_ET */ | ||
| 561 | s32 SNR; /* dB */ | ||
| 562 | u32 BER; /* Post Viterbi BER [1E-5] */ | ||
| 563 | u32 BERErrorCount; /* Number of erronous SYNC bits. */ | ||
| 564 | u32 BERBitCount; /* Total number of SYNC bits. */ | ||
| 565 | u32 TS_PER; /* Transport stream PER, | ||
| 566 | 0xFFFFFFFF indicate N/A */ | ||
| 567 | u32 MFER; /* DVB-H frame error rate in percentage, | ||
| 568 | 0xFFFFFFFF indicate N/A, valid only for DVB-H */ | ||
| 569 | s32 RSSI; /* dBm */ | ||
| 570 | s32 InBandPwr; /* In band power in dBM */ | ||
| 571 | s32 CarrierOffset; /* Carrier Offset in bin/1024 */ | ||
| 572 | u32 ErrorTSPackets; /* Number of erroneous | ||
| 573 | transport-stream packets */ | ||
| 574 | u32 TotalTSPackets; /* Total number of transport-stream packets */ | ||
| 575 | |||
| 576 | s32 MRC_SNR; /* dB */ | ||
| 577 | s32 MRC_RSSI; /* dBm */ | ||
| 578 | s32 MRC_InBandPwr; /* In band power in dBM */ | ||
| 579 | }; | ||
| 580 | |||
| 581 | |||
| 582 | /* Statistics information returned as response for | ||
| 583 | * SmsHostApiGetStatisticsEx_Req for DVB applications, SMS1100 and up */ | ||
| 584 | struct SMSHOSTLIB_STATISTICS_DVB_S { | ||
| 585 | /* Reception */ | ||
| 586 | struct RECEPTION_STATISTICS_S ReceptionData; | ||
| 587 | |||
| 588 | /* Transmission parameters */ | ||
| 589 | struct TRANSMISSION_STATISTICS_S TransmissionData; | ||
| 590 | |||
| 591 | /* Burst parameters, valid only for DVB-H */ | ||
| 592 | #define SRVM_MAX_PID_FILTERS 8 | ||
| 593 | struct PID_DATA_S PidData[SRVM_MAX_PID_FILTERS]; | ||
| 594 | }; | ||
| 595 | |||
| 596 | struct SRVM_SIGNAL_STATUS_S { | ||
| 597 | u32 result; | ||
| 598 | u32 snr; | ||
| 599 | u32 tsPackets; | ||
| 600 | u32 etsPackets; | ||
| 601 | u32 constellation; | ||
| 602 | u32 hpCode; | ||
| 603 | u32 tpsSrvIndLP; | ||
| 604 | u32 tpsSrvIndHP; | ||
| 605 | u32 cellId; | ||
| 606 | u32 reason; | ||
| 607 | |||
| 608 | s32 inBandPower; | ||
| 609 | u32 requestId; | ||
| 610 | }; | ||
| 611 | |||
| 612 | struct SMSHOSTLIB_I2C_REQ_ST { | ||
| 613 | u32 DeviceAddress; /* I2c device address */ | ||
| 614 | u32 WriteCount; /* number of bytes to write */ | ||
| 615 | u32 ReadCount; /* number of bytes to read */ | ||
| 616 | u8 Data[1]; | ||
| 617 | }; | ||
| 618 | |||
| 619 | struct SMSHOSTLIB_I2C_RES_ST { | ||
| 620 | u32 Status; /* non-zero value in case of failure */ | ||
| 621 | u32 ReadCount; /* number of bytes read */ | ||
| 622 | u8 Data[1]; | ||
| 623 | }; | ||
| 624 | |||
| 625 | |||
| 626 | struct smscore_config_gpio { | ||
| 627 | #define SMS_GPIO_DIRECTION_INPUT 0 | ||
| 628 | #define SMS_GPIO_DIRECTION_OUTPUT 1 | ||
| 629 | u8 direction; | ||
| 630 | |||
| 631 | #define SMS_GPIO_PULLUPDOWN_NONE 0 | ||
| 632 | #define SMS_GPIO_PULLUPDOWN_PULLDOWN 1 | ||
| 633 | #define SMS_GPIO_PULLUPDOWN_PULLUP 2 | ||
| 634 | #define SMS_GPIO_PULLUPDOWN_KEEPER 3 | ||
| 635 | u8 pullupdown; | ||
| 636 | |||
| 637 | #define SMS_GPIO_INPUTCHARACTERISTICS_NORMAL 0 | ||
| 638 | #define SMS_GPIO_INPUTCHARACTERISTICS_SCHMITT 1 | ||
| 639 | u8 inputcharacteristics; | ||
| 640 | |||
| 641 | #define SMS_GPIO_OUTPUTSLEWRATE_FAST 0 | ||
| 642 | #define SMS_GPIO_OUTPUTSLEWRATE_SLOW 1 | ||
| 643 | u8 outputslewrate; | ||
| 644 | |||
| 645 | #define SMS_GPIO_OUTPUTDRIVING_4mA 0 | ||
| 646 | #define SMS_GPIO_OUTPUTDRIVING_8mA 1 | ||
| 647 | #define SMS_GPIO_OUTPUTDRIVING_12mA 2 | ||
| 648 | #define SMS_GPIO_OUTPUTDRIVING_16mA 3 | ||
| 649 | u8 outputdriving; | ||
| 650 | }; | ||
| 651 | |||
| 652 | struct smscore_gpio_config { | ||
| 653 | #define SMS_GPIO_DIRECTION_INPUT 0 | ||
| 654 | #define SMS_GPIO_DIRECTION_OUTPUT 1 | ||
| 655 | u8 Direction; | ||
| 656 | |||
| 657 | #define SMS_GPIO_PULL_UP_DOWN_NONE 0 | ||
| 658 | #define SMS_GPIO_PULL_UP_DOWN_PULLDOWN 1 | ||
| 659 | #define SMS_GPIO_PULL_UP_DOWN_PULLUP 2 | ||
| 660 | #define SMS_GPIO_PULL_UP_DOWN_KEEPER 3 | ||
| 661 | u8 PullUpDown; | ||
| 662 | |||
| 663 | #define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL 0 | ||
| 664 | #define SMS_GPIO_INPUT_CHARACTERISTICS_SCHMITT 1 | ||
| 665 | u8 InputCharacteristics; | ||
| 666 | |||
| 667 | #define SMS_GPIO_OUTPUT_SLEW_RATE_SLOW 1 /* 10xx */ | ||
| 668 | #define SMS_GPIO_OUTPUT_SLEW_RATE_FAST 0 /* 10xx */ | ||
| 669 | |||
| 670 | |||
| 671 | #define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS 0 /* 11xx */ | ||
| 672 | #define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS 1 /* 11xx */ | ||
| 673 | #define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS 2 /* 11xx */ | ||
| 674 | #define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS 3 /* 11xx */ | ||
| 675 | u8 OutputSlewRate; | ||
| 676 | |||
| 677 | #define SMS_GPIO_OUTPUT_DRIVING_S_4mA 0 /* 10xx */ | ||
| 678 | #define SMS_GPIO_OUTPUT_DRIVING_S_8mA 1 /* 10xx */ | ||
| 679 | #define SMS_GPIO_OUTPUT_DRIVING_S_12mA 2 /* 10xx */ | ||
| 680 | #define SMS_GPIO_OUTPUT_DRIVING_S_16mA 3 /* 10xx */ | ||
| 681 | |||
| 682 | #define SMS_GPIO_OUTPUT_DRIVING_1_5mA 0 /* 11xx */ | ||
| 683 | #define SMS_GPIO_OUTPUT_DRIVING_2_8mA 1 /* 11xx */ | ||
| 684 | #define SMS_GPIO_OUTPUT_DRIVING_4mA 2 /* 11xx */ | ||
| 685 | #define SMS_GPIO_OUTPUT_DRIVING_7mA 3 /* 11xx */ | ||
| 686 | #define SMS_GPIO_OUTPUT_DRIVING_10mA 4 /* 11xx */ | ||
| 687 | #define SMS_GPIO_OUTPUT_DRIVING_11mA 5 /* 11xx */ | ||
| 688 | #define SMS_GPIO_OUTPUT_DRIVING_14mA 6 /* 11xx */ | ||
| 689 | #define SMS_GPIO_OUTPUT_DRIVING_16mA 7 /* 11xx */ | ||
| 690 | u8 OutputDriving; | ||
| 691 | }; | ||
| 692 | |||
| 693 | extern void smscore_registry_setmode(char *devpath, int mode); | ||
| 694 | extern int smscore_registry_getmode(char *devpath); | ||
| 695 | |||
| 696 | extern int smscore_register_hotplug(hotplug_t hotplug); | ||
| 697 | extern void smscore_unregister_hotplug(hotplug_t hotplug); | ||
| 698 | |||
| 699 | extern int smscore_register_device(struct smsdevice_params_t *params, | ||
| 700 | struct smscore_device_t **coredev); | ||
| 701 | extern void smscore_unregister_device(struct smscore_device_t *coredev); | ||
| 702 | |||
| 703 | extern int smscore_start_device(struct smscore_device_t *coredev); | ||
| 704 | extern int smscore_load_firmware(struct smscore_device_t *coredev, | ||
| 705 | char *filename, | ||
| 706 | loadfirmware_t loadfirmware_handler); | ||
| 707 | |||
| 708 | extern int smscore_set_device_mode(struct smscore_device_t *coredev, int mode); | ||
| 709 | extern int smscore_get_device_mode(struct smscore_device_t *coredev); | ||
| 710 | |||
| 711 | extern int smscore_register_client(struct smscore_device_t *coredev, | ||
| 712 | struct smsclient_params_t *params, | ||
| 713 | struct smscore_client_t **client); | ||
| 714 | extern void smscore_unregister_client(struct smscore_client_t *client); | ||
| 715 | |||
| 716 | extern int smsclient_sendrequest(struct smscore_client_t *client, | ||
| 717 | void *buffer, size_t size); | ||
| 718 | extern void smscore_onresponse(struct smscore_device_t *coredev, | ||
| 719 | struct smscore_buffer_t *cb); | ||
| 720 | |||
| 721 | extern int smscore_get_common_buffer_size(struct smscore_device_t *coredev); | ||
| 722 | extern int smscore_map_common_buffer(struct smscore_device_t *coredev, | ||
| 723 | struct vm_area_struct *vma); | ||
| 724 | extern int smscore_get_fw_filename(struct smscore_device_t *coredev, | ||
| 725 | int mode, char *filename); | ||
| 726 | extern int smscore_send_fw_file(struct smscore_device_t *coredev, | ||
| 727 | u8 *ufwbuf, int size); | ||
| 728 | |||
| 729 | extern | ||
| 730 | struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev); | ||
| 731 | extern void smscore_putbuffer(struct smscore_device_t *coredev, | ||
| 732 | struct smscore_buffer_t *cb); | ||
| 733 | |||
| 734 | /* old GPIO management */ | ||
| 735 | int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin, | ||
| 736 | struct smscore_config_gpio *pinconfig); | ||
| 737 | int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level); | ||
| 738 | |||
| 739 | /* new GPIO management */ | ||
| 740 | extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, | ||
| 741 | struct smscore_gpio_config *pGpioConfig); | ||
| 742 | extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum, | ||
| 743 | u8 NewLevel); | ||
| 744 | extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum, | ||
| 745 | u8 *level); | ||
| 746 | |||
| 747 | void smscore_set_board_id(struct smscore_device_t *core, int id); | ||
| 748 | int smscore_get_board_id(struct smscore_device_t *core); | ||
| 749 | |||
| 750 | int smscore_led_state(struct smscore_device_t *core, int led); | ||
| 751 | |||
| 752 | |||
| 753 | /* ------------------------------------------------------------------------ */ | ||
| 754 | |||
| 755 | #define DBG_INFO 1 | ||
| 756 | #define DBG_ADV 2 | ||
| 757 | |||
| 758 | #define sms_printk(kern, fmt, arg...) \ | ||
| 759 | printk(kern "%s: " fmt "\n", __func__, ##arg) | ||
| 760 | |||
| 761 | #define dprintk(kern, lvl, fmt, arg...) do {\ | ||
| 762 | if (sms_dbg & lvl) \ | ||
| 763 | sms_printk(kern, fmt, ##arg); } while (0) | ||
| 764 | |||
| 765 | #define sms_log(fmt, arg...) sms_printk(KERN_INFO, fmt, ##arg) | ||
| 766 | #define sms_err(fmt, arg...) \ | ||
| 767 | sms_printk(KERN_ERR, "line: %d: " fmt, __LINE__, ##arg) | ||
| 768 | #define sms_warn(fmt, arg...) sms_printk(KERN_WARNING, fmt, ##arg) | ||
| 769 | #define sms_info(fmt, arg...) \ | ||
| 770 | dprintk(KERN_INFO, DBG_INFO, fmt, ##arg) | ||
| 771 | #define sms_debug(fmt, arg...) \ | ||
| 772 | dprintk(KERN_DEBUG, DBG_ADV, fmt, ##arg) | ||
| 773 | |||
| 774 | |||
| 775 | #endif /* __SMS_CORE_API_H__ */ | ||
diff --git a/drivers/media/usb/siano/smsdvb.c b/drivers/media/usb/siano/smsdvb.c deleted file mode 100644 index aa77e54a8fae..000000000000 --- a/drivers/media/usb/siano/smsdvb.c +++ /dev/null | |||
| @@ -1,1078 +0,0 @@ | |||
| 1 | /**************************************************************** | ||
| 2 | |||
| 3 | Siano Mobile Silicon, Inc. | ||
| 4 | MDTV receiver kernel modules. | ||
| 5 | Copyright (C) 2006-2008, 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 <linux/module.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | |||
| 26 | #include "dmxdev.h" | ||
| 27 | #include "dvbdev.h" | ||
| 28 | #include "dvb_demux.h" | ||
| 29 | #include "dvb_frontend.h" | ||
| 30 | |||
| 31 | #include "smscoreapi.h" | ||
| 32 | #include "smsendian.h" | ||
| 33 | #include "sms-cards.h" | ||
| 34 | |||
| 35 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
| 36 | |||
| 37 | struct smsdvb_client_t { | ||
| 38 | struct list_head entry; | ||
| 39 | |||
| 40 | struct smscore_device_t *coredev; | ||
| 41 | struct smscore_client_t *smsclient; | ||
| 42 | |||
| 43 | struct dvb_adapter adapter; | ||
| 44 | struct dvb_demux demux; | ||
| 45 | struct dmxdev dmxdev; | ||
| 46 | struct dvb_frontend frontend; | ||
| 47 | |||
| 48 | fe_status_t fe_status; | ||
| 49 | |||
| 50 | struct completion tune_done; | ||
| 51 | |||
| 52 | struct SMSHOSTLIB_STATISTICS_DVB_S sms_stat_dvb; | ||
| 53 | int event_fe_state; | ||
| 54 | int event_unc_state; | ||
| 55 | }; | ||
| 56 | |||
| 57 | static struct list_head g_smsdvb_clients; | ||
| 58 | static struct mutex g_smsdvb_clientslock; | ||
| 59 | |||
| 60 | static int sms_dbg; | ||
| 61 | module_param_named(debug, sms_dbg, int, 0644); | ||
| 62 | MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); | ||
| 63 | |||
| 64 | /* Events that may come from DVB v3 adapter */ | ||
| 65 | static void sms_board_dvb3_event(struct smsdvb_client_t *client, | ||
| 66 | enum SMS_DVB3_EVENTS event) { | ||
| 67 | |||
| 68 | struct smscore_device_t *coredev = client->coredev; | ||
| 69 | switch (event) { | ||
| 70 | case DVB3_EVENT_INIT: | ||
| 71 | sms_debug("DVB3_EVENT_INIT"); | ||
| 72 | sms_board_event(coredev, BOARD_EVENT_BIND); | ||
| 73 | break; | ||
| 74 | case DVB3_EVENT_SLEEP: | ||
| 75 | sms_debug("DVB3_EVENT_SLEEP"); | ||
| 76 | sms_board_event(coredev, BOARD_EVENT_POWER_SUSPEND); | ||
| 77 | break; | ||
| 78 | case DVB3_EVENT_HOTPLUG: | ||
| 79 | sms_debug("DVB3_EVENT_HOTPLUG"); | ||
| 80 | sms_board_event(coredev, BOARD_EVENT_POWER_INIT); | ||
| 81 | break; | ||
| 82 | case DVB3_EVENT_FE_LOCK: | ||
| 83 | if (client->event_fe_state != DVB3_EVENT_FE_LOCK) { | ||
| 84 | client->event_fe_state = DVB3_EVENT_FE_LOCK; | ||
| 85 | sms_debug("DVB3_EVENT_FE_LOCK"); | ||
| 86 | sms_board_event(coredev, BOARD_EVENT_FE_LOCK); | ||
| 87 | } | ||
| 88 | break; | ||
| 89 | case DVB3_EVENT_FE_UNLOCK: | ||
| 90 | if (client->event_fe_state != DVB3_EVENT_FE_UNLOCK) { | ||
| 91 | client->event_fe_state = DVB3_EVENT_FE_UNLOCK; | ||
| 92 | sms_debug("DVB3_EVENT_FE_UNLOCK"); | ||
| 93 | sms_board_event(coredev, BOARD_EVENT_FE_UNLOCK); | ||
| 94 | } | ||
| 95 | break; | ||
| 96 | case DVB3_EVENT_UNC_OK: | ||
| 97 | if (client->event_unc_state != DVB3_EVENT_UNC_OK) { | ||
| 98 | client->event_unc_state = DVB3_EVENT_UNC_OK; | ||
| 99 | sms_debug("DVB3_EVENT_UNC_OK"); | ||
| 100 | sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_OK); | ||
| 101 | } | ||
| 102 | break; | ||
| 103 | case DVB3_EVENT_UNC_ERR: | ||
| 104 | if (client->event_unc_state != DVB3_EVENT_UNC_ERR) { | ||
| 105 | client->event_unc_state = DVB3_EVENT_UNC_ERR; | ||
| 106 | sms_debug("DVB3_EVENT_UNC_ERR"); | ||
| 107 | sms_board_event(coredev, BOARD_EVENT_MULTIPLEX_ERRORS); | ||
| 108 | } | ||
| 109 | break; | ||
| 110 | |||
| 111 | default: | ||
| 112 | sms_err("Unknown dvb3 api event"); | ||
| 113 | break; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | |||
| 117 | |||
| 118 | static void smsdvb_update_dvb_stats(struct RECEPTION_STATISTICS_S *pReceptionData, | ||
| 119 | struct SMSHOSTLIB_STATISTICS_ST *p) | ||
| 120 | { | ||
| 121 | if (sms_dbg & 2) { | ||
| 122 | printk(KERN_DEBUG "Reserved = %d", p->Reserved); | ||
| 123 | printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked); | ||
| 124 | printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked); | ||
| 125 | printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn); | ||
| 126 | printk(KERN_DEBUG "SNR = %d", p->SNR); | ||
| 127 | printk(KERN_DEBUG "BER = %d", p->BER); | ||
| 128 | printk(KERN_DEBUG "FIB_CRC = %d", p->FIB_CRC); | ||
| 129 | printk(KERN_DEBUG "TS_PER = %d", p->TS_PER); | ||
| 130 | printk(KERN_DEBUG "MFER = %d", p->MFER); | ||
| 131 | printk(KERN_DEBUG "RSSI = %d", p->RSSI); | ||
| 132 | printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr); | ||
| 133 | printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset); | ||
| 134 | printk(KERN_DEBUG "Frequency = %d", p->Frequency); | ||
| 135 | printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth); | ||
| 136 | printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode); | ||
| 137 | printk(KERN_DEBUG "ModemState = %d", p->ModemState); | ||
| 138 | printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval); | ||
| 139 | printk(KERN_DEBUG "CodeRate = %d", p->CodeRate); | ||
| 140 | printk(KERN_DEBUG "LPCodeRate = %d", p->LPCodeRate); | ||
| 141 | printk(KERN_DEBUG "Hierarchy = %d", p->Hierarchy); | ||
| 142 | printk(KERN_DEBUG "Constellation = %d", p->Constellation); | ||
| 143 | printk(KERN_DEBUG "BurstSize = %d", p->BurstSize); | ||
| 144 | printk(KERN_DEBUG "BurstDuration = %d", p->BurstDuration); | ||
| 145 | printk(KERN_DEBUG "BurstCycleTime = %d", p->BurstCycleTime); | ||
| 146 | printk(KERN_DEBUG "CalculatedBurstCycleTime = %d", p->CalculatedBurstCycleTime); | ||
| 147 | printk(KERN_DEBUG "NumOfRows = %d", p->NumOfRows); | ||
| 148 | printk(KERN_DEBUG "NumOfPaddCols = %d", p->NumOfPaddCols); | ||
| 149 | printk(KERN_DEBUG "NumOfPunctCols = %d", p->NumOfPunctCols); | ||
| 150 | printk(KERN_DEBUG "ErrorTSPackets = %d", p->ErrorTSPackets); | ||
| 151 | printk(KERN_DEBUG "TotalTSPackets = %d", p->TotalTSPackets); | ||
| 152 | printk(KERN_DEBUG "NumOfValidMpeTlbs = %d", p->NumOfValidMpeTlbs); | ||
| 153 | printk(KERN_DEBUG "NumOfInvalidMpeTlbs = %d", p->NumOfInvalidMpeTlbs); | ||
| 154 | printk(KERN_DEBUG "NumOfCorrectedMpeTlbs = %d", p->NumOfCorrectedMpeTlbs); | ||
| 155 | printk(KERN_DEBUG "BERErrorCount = %d", p->BERErrorCount); | ||
| 156 | printk(KERN_DEBUG "BERBitCount = %d", p->BERBitCount); | ||
| 157 | printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors); | ||
| 158 | printk(KERN_DEBUG "PreBER = %d", p->PreBER); | ||
| 159 | printk(KERN_DEBUG "CellId = %d", p->CellId); | ||
| 160 | printk(KERN_DEBUG "DvbhSrvIndHP = %d", p->DvbhSrvIndHP); | ||
| 161 | printk(KERN_DEBUG "DvbhSrvIndLP = %d", p->DvbhSrvIndLP); | ||
| 162 | printk(KERN_DEBUG "NumMPEReceived = %d", p->NumMPEReceived); | ||
| 163 | } | ||
| 164 | |||
| 165 | pReceptionData->IsDemodLocked = p->IsDemodLocked; | ||
| 166 | |||
| 167 | pReceptionData->SNR = p->SNR; | ||
| 168 | pReceptionData->BER = p->BER; | ||
| 169 | pReceptionData->BERErrorCount = p->BERErrorCount; | ||
| 170 | pReceptionData->InBandPwr = p->InBandPwr; | ||
| 171 | pReceptionData->ErrorTSPackets = p->ErrorTSPackets; | ||
| 172 | }; | ||
| 173 | |||
| 174 | |||
| 175 | static void smsdvb_update_isdbt_stats(struct RECEPTION_STATISTICS_S *pReceptionData, | ||
| 176 | struct SMSHOSTLIB_STATISTICS_ISDBT_ST *p) | ||
| 177 | { | ||
| 178 | int i; | ||
| 179 | |||
| 180 | if (sms_dbg & 2) { | ||
| 181 | printk(KERN_DEBUG "IsRfLocked = %d", p->IsRfLocked); | ||
| 182 | printk(KERN_DEBUG "IsDemodLocked = %d", p->IsDemodLocked); | ||
| 183 | printk(KERN_DEBUG "IsExternalLNAOn = %d", p->IsExternalLNAOn); | ||
| 184 | printk(KERN_DEBUG "SNR = %d", p->SNR); | ||
| 185 | printk(KERN_DEBUG "RSSI = %d", p->RSSI); | ||
| 186 | printk(KERN_DEBUG "InBandPwr = %d", p->InBandPwr); | ||
| 187 | printk(KERN_DEBUG "CarrierOffset = %d", p->CarrierOffset); | ||
| 188 | printk(KERN_DEBUG "Frequency = %d", p->Frequency); | ||
| 189 | printk(KERN_DEBUG "Bandwidth = %d", p->Bandwidth); | ||
| 190 | printk(KERN_DEBUG "TransmissionMode = %d", p->TransmissionMode); | ||
| 191 | printk(KERN_DEBUG "ModemState = %d", p->ModemState); | ||
| 192 | printk(KERN_DEBUG "GuardInterval = %d", p->GuardInterval); | ||
| 193 | printk(KERN_DEBUG "SystemType = %d", p->SystemType); | ||
| 194 | printk(KERN_DEBUG "PartialReception = %d", p->PartialReception); | ||
| 195 | printk(KERN_DEBUG "NumOfLayers = %d", p->NumOfLayers); | ||
| 196 | printk(KERN_DEBUG "SmsToHostTxErrors = %d", p->SmsToHostTxErrors); | ||
| 197 | |||
| 198 | for (i = 0; i < 3; i++) { | ||
| 199 | printk(KERN_DEBUG "%d: CodeRate = %d", i, p->LayerInfo[i].CodeRate); | ||
| 200 | printk(KERN_DEBUG "%d: Constellation = %d", i, p->LayerInfo[i].Constellation); | ||
| 201 | printk(KERN_DEBUG "%d: BER = %d", i, p->LayerInfo[i].BER); | ||
| 202 | printk(KERN_DEBUG "%d: BERErrorCount = %d", i, p->LayerInfo[i].BERErrorCount); | ||
| 203 | printk(KERN_DEBUG "%d: BERBitCount = %d", i, p->LayerInfo[i].BERBitCount); | ||
| 204 | printk(KERN_DEBUG "%d: PreBER = %d", i, p->LayerInfo[i].PreBER); | ||
| 205 | printk(KERN_DEBUG "%d: TS_PER = %d", i, p->LayerInfo[i].TS_PER); | ||
| 206 | printk(KERN_DEBUG "%d: ErrorTSPackets = %d", i, p->LayerInfo[i].ErrorTSPackets); | ||
| 207 | printk(KERN_DEBUG "%d: TotalTSPackets = %d", i, p->LayerInfo[i].TotalTSPackets); | ||
| 208 | printk(KERN_DEBUG "%d: TILdepthI = %d", i, p->LayerInfo[i].TILdepthI); | ||
| 209 | printk(KERN_DEBUG "%d: NumberOfSegments = %d", i, p->LayerInfo[i].NumberOfSegments); | ||
| 210 | printk(KERN_DEBUG "%d: TMCCErrors = %d", i, p->LayerInfo[i].TMCCErrors); | ||
| 211 | } | ||
| 212 | } | ||
| 213 | |||
| 214 | pReceptionData->IsDemodLocked = p->IsDemodLocked; | ||
| 215 | |||
| 216 | pReceptionData->SNR = p->SNR; | ||
| 217 | pReceptionData->InBandPwr = p->InBandPwr; | ||
| 218 | |||
| 219 | pReceptionData->ErrorTSPackets = 0; | ||
| 220 | pReceptionData->BER = 0; | ||
| 221 | pReceptionData->BERErrorCount = 0; | ||
| 222 | for (i = 0; i < 3; i++) { | ||
| 223 | pReceptionData->BER += p->LayerInfo[i].BER; | ||
| 224 | pReceptionData->BERErrorCount += p->LayerInfo[i].BERErrorCount; | ||
| 225 | pReceptionData->ErrorTSPackets += p->LayerInfo[i].ErrorTSPackets; | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 229 | static int smsdvb_onresponse(void *context, struct smscore_buffer_t *cb) | ||
| 230 | { | ||
| 231 | struct smsdvb_client_t *client = (struct smsdvb_client_t *) context; | ||
| 232 | struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) (((u8 *) cb->p) | ||
| 233 | + cb->offset); | ||
| 234 | u32 *pMsgData = (u32 *) phdr + 1; | ||
| 235 | /*u32 MsgDataLen = phdr->msgLength - sizeof(struct SmsMsgHdr_ST);*/ | ||
| 236 | bool is_status_update = false; | ||
| 237 | |||
| 238 | smsendian_handle_rx_message((struct SmsMsgData_ST *) phdr); | ||
| 239 | |||
| 240 | switch (phdr->msgType) { | ||
| 241 | case MSG_SMS_DVBT_BDA_DATA: | ||
| 242 | dvb_dmx_swfilter(&client->demux, (u8 *)(phdr + 1), | ||
| 243 | cb->size - sizeof(struct SmsMsgHdr_ST)); | ||
| 244 | break; | ||
| 245 | |||
| 246 | case MSG_SMS_RF_TUNE_RES: | ||
| 247 | case MSG_SMS_ISDBT_TUNE_RES: | ||
| 248 | complete(&client->tune_done); | ||
| 249 | break; | ||
| 250 | |||
| 251 | case MSG_SMS_SIGNAL_DETECTED_IND: | ||
| 252 | sms_info("MSG_SMS_SIGNAL_DETECTED_IND"); | ||
| 253 | client->sms_stat_dvb.TransmissionData.IsDemodLocked = true; | ||
| 254 | is_status_update = true; | ||
| 255 | break; | ||
| 256 | |||
| 257 | case MSG_SMS_NO_SIGNAL_IND: | ||
| 258 | sms_info("MSG_SMS_NO_SIGNAL_IND"); | ||
| 259 | client->sms_stat_dvb.TransmissionData.IsDemodLocked = false; | ||
| 260 | is_status_update = true; | ||
| 261 | break; | ||
| 262 | |||
| 263 | case MSG_SMS_TRANSMISSION_IND: { | ||
| 264 | sms_info("MSG_SMS_TRANSMISSION_IND"); | ||
| 265 | |||
| 266 | pMsgData++; | ||
| 267 | memcpy(&client->sms_stat_dvb.TransmissionData, pMsgData, | ||
| 268 | sizeof(struct TRANSMISSION_STATISTICS_S)); | ||
| 269 | |||
| 270 | /* Mo need to correct guard interval | ||
| 271 | * (as opposed to old statistics message). | ||
| 272 | */ | ||
| 273 | CORRECT_STAT_BANDWIDTH(client->sms_stat_dvb.TransmissionData); | ||
| 274 | CORRECT_STAT_TRANSMISSON_MODE( | ||
| 275 | client->sms_stat_dvb.TransmissionData); | ||
| 276 | is_status_update = true; | ||
| 277 | break; | ||
| 278 | } | ||
| 279 | case MSG_SMS_HO_PER_SLICES_IND: { | ||
| 280 | struct RECEPTION_STATISTICS_S *pReceptionData = | ||
| 281 | &client->sms_stat_dvb.ReceptionData; | ||
| 282 | struct SRVM_SIGNAL_STATUS_S SignalStatusData; | ||
| 283 | |||
| 284 | /*sms_info("MSG_SMS_HO_PER_SLICES_IND");*/ | ||
| 285 | pMsgData++; | ||
| 286 | SignalStatusData.result = pMsgData[0]; | ||
| 287 | SignalStatusData.snr = pMsgData[1]; | ||
| 288 | SignalStatusData.inBandPower = (s32) pMsgData[2]; | ||
| 289 | SignalStatusData.tsPackets = pMsgData[3]; | ||
| 290 | SignalStatusData.etsPackets = pMsgData[4]; | ||
| 291 | SignalStatusData.constellation = pMsgData[5]; | ||
| 292 | SignalStatusData.hpCode = pMsgData[6]; | ||
| 293 | SignalStatusData.tpsSrvIndLP = pMsgData[7] & 0x03; | ||
| 294 | SignalStatusData.tpsSrvIndHP = pMsgData[8] & 0x03; | ||
| 295 | SignalStatusData.cellId = pMsgData[9] & 0xFFFF; | ||
| 296 | SignalStatusData.reason = pMsgData[10]; | ||
| 297 | SignalStatusData.requestId = pMsgData[11]; | ||
| 298 | pReceptionData->IsRfLocked = pMsgData[16]; | ||
| 299 | pReceptionData->IsDemodLocked = pMsgData[17]; | ||
| 300 | pReceptionData->ModemState = pMsgData[12]; | ||
| 301 | pReceptionData->SNR = pMsgData[1]; | ||
| 302 | pReceptionData->BER = pMsgData[13]; | ||
| 303 | pReceptionData->RSSI = pMsgData[14]; | ||
| 304 | CORRECT_STAT_RSSI(client->sms_stat_dvb.ReceptionData); | ||
| 305 | |||
| 306 | pReceptionData->InBandPwr = (s32) pMsgData[2]; | ||
| 307 | pReceptionData->CarrierOffset = (s32) pMsgData[15]; | ||
| 308 | pReceptionData->TotalTSPackets = pMsgData[3]; | ||
| 309 | pReceptionData->ErrorTSPackets = pMsgData[4]; | ||
| 310 | |||
| 311 | /* TS PER */ | ||
| 312 | if ((SignalStatusData.tsPackets + SignalStatusData.etsPackets) | ||
| 313 | > 0) { | ||
| 314 | pReceptionData->TS_PER = (SignalStatusData.etsPackets | ||
| 315 | * 100) / (SignalStatusData.tsPackets | ||
| 316 | + SignalStatusData.etsPackets); | ||
| 317 | } else { | ||
| 318 | pReceptionData->TS_PER = 0; | ||
| 319 | } | ||
| 320 | |||
| 321 | pReceptionData->BERBitCount = pMsgData[18]; | ||
| 322 | pReceptionData->BERErrorCount = pMsgData[19]; | ||
| 323 | |||
| 324 | pReceptionData->MRC_SNR = pMsgData[20]; | ||
| 325 | pReceptionData->MRC_InBandPwr = pMsgData[21]; | ||
| 326 | pReceptionData->MRC_RSSI = pMsgData[22]; | ||
| 327 | |||
| 328 | is_status_update = true; | ||
| 329 | break; | ||
| 330 | } | ||
| 331 | case MSG_SMS_GET_STATISTICS_RES: { | ||
| 332 | union { | ||
| 333 | struct SMSHOSTLIB_STATISTICS_ISDBT_ST isdbt; | ||
| 334 | struct SmsMsgStatisticsInfo_ST dvb; | ||
| 335 | } *p = (void *) (phdr + 1); | ||
| 336 | struct RECEPTION_STATISTICS_S *pReceptionData = | ||
| 337 | &client->sms_stat_dvb.ReceptionData; | ||
| 338 | |||
| 339 | sms_info("MSG_SMS_GET_STATISTICS_RES"); | ||
| 340 | |||
| 341 | is_status_update = true; | ||
| 342 | |||
| 343 | switch (smscore_get_device_mode(client->coredev)) { | ||
| 344 | case DEVICE_MODE_ISDBT: | ||
| 345 | case DEVICE_MODE_ISDBT_BDA: | ||
| 346 | smsdvb_update_isdbt_stats(pReceptionData, &p->isdbt); | ||
| 347 | break; | ||
| 348 | default: | ||
| 349 | smsdvb_update_dvb_stats(pReceptionData, &p->dvb.Stat); | ||
| 350 | } | ||
| 351 | if (!pReceptionData->IsDemodLocked) { | ||
| 352 | pReceptionData->SNR = 0; | ||
| 353 | pReceptionData->BER = 0; | ||
| 354 | pReceptionData->BERErrorCount = 0; | ||
| 355 | pReceptionData->InBandPwr = 0; | ||
| 356 | pReceptionData->ErrorTSPackets = 0; | ||
| 357 | } | ||
| 358 | |||
| 359 | complete(&client->tune_done); | ||
| 360 | break; | ||
| 361 | } | ||
| 362 | default: | ||
| 363 | sms_info("Unhandled message %d", phdr->msgType); | ||
| 364 | |||
| 365 | } | ||
| 366 | smscore_putbuffer(client->coredev, cb); | ||
| 367 | |||
| 368 | if (is_status_update) { | ||
| 369 | if (client->sms_stat_dvb.ReceptionData.IsDemodLocked) { | ||
| 370 | client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER | ||
| 371 | | FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; | ||
| 372 | sms_board_dvb3_event(client, DVB3_EVENT_FE_LOCK); | ||
| 373 | if (client->sms_stat_dvb.ReceptionData.ErrorTSPackets | ||
| 374 | == 0) | ||
| 375 | sms_board_dvb3_event(client, DVB3_EVENT_UNC_OK); | ||
| 376 | else | ||
| 377 | sms_board_dvb3_event(client, | ||
| 378 | DVB3_EVENT_UNC_ERR); | ||
| 379 | |||
| 380 | } else { | ||
| 381 | if (client->sms_stat_dvb.ReceptionData.IsRfLocked) | ||
| 382 | client->fe_status = FE_HAS_SIGNAL | FE_HAS_CARRIER; | ||
| 383 | else | ||
| 384 | client->fe_status = 0; | ||
| 385 | sms_board_dvb3_event(client, DVB3_EVENT_FE_UNLOCK); | ||
| 386 | } | ||
| 387 | } | ||
| 388 | |||
| 389 | return 0; | ||
| 390 | } | ||
| 391 | |||
| 392 | static void smsdvb_unregister_client(struct smsdvb_client_t *client) | ||
| 393 | { | ||
| 394 | /* must be called under clientslock */ | ||
| 395 | |||
| 396 | list_del(&client->entry); | ||
| 397 | |||
| 398 | smscore_unregister_client(client->smsclient); | ||
| 399 | dvb_unregister_frontend(&client->frontend); | ||
| 400 | dvb_dmxdev_release(&client->dmxdev); | ||
| 401 | dvb_dmx_release(&client->demux); | ||
| 402 | dvb_unregister_adapter(&client->adapter); | ||
| 403 | kfree(client); | ||
| 404 | } | ||
| 405 | |||
| 406 | static void smsdvb_onremove(void *context) | ||
| 407 | { | ||
| 408 | kmutex_lock(&g_smsdvb_clientslock); | ||
| 409 | |||
| 410 | smsdvb_unregister_client((struct smsdvb_client_t *) context); | ||
| 411 | |||
| 412 | kmutex_unlock(&g_smsdvb_clientslock); | ||
| 413 | } | ||
| 414 | |||
| 415 | static int smsdvb_start_feed(struct dvb_demux_feed *feed) | ||
| 416 | { | ||
| 417 | struct smsdvb_client_t *client = | ||
| 418 | container_of(feed->demux, struct smsdvb_client_t, demux); | ||
| 419 | struct SmsMsgData_ST PidMsg; | ||
| 420 | |||
| 421 | sms_debug("add pid %d(%x)", | ||
| 422 | feed->pid, feed->pid); | ||
| 423 | |||
| 424 | PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
| 425 | PidMsg.xMsgHeader.msgDstId = HIF_TASK; | ||
| 426 | PidMsg.xMsgHeader.msgFlags = 0; | ||
| 427 | PidMsg.xMsgHeader.msgType = MSG_SMS_ADD_PID_FILTER_REQ; | ||
| 428 | PidMsg.xMsgHeader.msgLength = sizeof(PidMsg); | ||
| 429 | PidMsg.msgData[0] = feed->pid; | ||
| 430 | |||
| 431 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg); | ||
| 432 | return smsclient_sendrequest(client->smsclient, | ||
| 433 | &PidMsg, sizeof(PidMsg)); | ||
| 434 | } | ||
| 435 | |||
| 436 | static int smsdvb_stop_feed(struct dvb_demux_feed *feed) | ||
| 437 | { | ||
| 438 | struct smsdvb_client_t *client = | ||
| 439 | container_of(feed->demux, struct smsdvb_client_t, demux); | ||
| 440 | struct SmsMsgData_ST PidMsg; | ||
| 441 | |||
| 442 | sms_debug("remove pid %d(%x)", | ||
| 443 | feed->pid, feed->pid); | ||
| 444 | |||
| 445 | PidMsg.xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
| 446 | PidMsg.xMsgHeader.msgDstId = HIF_TASK; | ||
| 447 | PidMsg.xMsgHeader.msgFlags = 0; | ||
| 448 | PidMsg.xMsgHeader.msgType = MSG_SMS_REMOVE_PID_FILTER_REQ; | ||
| 449 | PidMsg.xMsgHeader.msgLength = sizeof(PidMsg); | ||
| 450 | PidMsg.msgData[0] = feed->pid; | ||
| 451 | |||
| 452 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)&PidMsg); | ||
| 453 | return smsclient_sendrequest(client->smsclient, | ||
| 454 | &PidMsg, sizeof(PidMsg)); | ||
| 455 | } | ||
| 456 | |||
| 457 | static int smsdvb_sendrequest_and_wait(struct smsdvb_client_t *client, | ||
| 458 | void *buffer, size_t size, | ||
| 459 | struct completion *completion) | ||
| 460 | { | ||
| 461 | int rc; | ||
| 462 | |||
| 463 | smsendian_handle_tx_message((struct SmsMsgHdr_ST *)buffer); | ||
| 464 | rc = smsclient_sendrequest(client->smsclient, buffer, size); | ||
| 465 | if (rc < 0) | ||
| 466 | return rc; | ||
| 467 | |||
| 468 | return wait_for_completion_timeout(completion, | ||
| 469 | msecs_to_jiffies(2000)) ? | ||
| 470 | 0 : -ETIME; | ||
| 471 | } | ||
| 472 | |||
| 473 | static int smsdvb_send_statistics_request(struct smsdvb_client_t *client) | ||
| 474 | { | ||
| 475 | int rc; | ||
| 476 | struct SmsMsgHdr_ST Msg = { MSG_SMS_GET_STATISTICS_REQ, | ||
| 477 | DVBT_BDA_CONTROL_MSG_ID, | ||
| 478 | HIF_TASK, | ||
| 479 | sizeof(struct SmsMsgHdr_ST), 0 }; | ||
| 480 | |||
| 481 | rc = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | ||
| 482 | &client->tune_done); | ||
| 483 | |||
| 484 | return rc; | ||
| 485 | } | ||
| 486 | |||
| 487 | static inline int led_feedback(struct smsdvb_client_t *client) | ||
| 488 | { | ||
| 489 | if (client->fe_status & FE_HAS_LOCK) | ||
| 490 | return sms_board_led_feedback(client->coredev, | ||
| 491 | (client->sms_stat_dvb.ReceptionData.BER | ||
| 492 | == 0) ? SMS_LED_HI : SMS_LED_LO); | ||
| 493 | else | ||
| 494 | return sms_board_led_feedback(client->coredev, SMS_LED_OFF); | ||
| 495 | } | ||
| 496 | |||
| 497 | static int smsdvb_read_status(struct dvb_frontend *fe, fe_status_t *stat) | ||
| 498 | { | ||
| 499 | int rc; | ||
| 500 | struct smsdvb_client_t *client; | ||
| 501 | client = container_of(fe, struct smsdvb_client_t, frontend); | ||
| 502 | |||
| 503 | rc = smsdvb_send_statistics_request(client); | ||
| 504 | |||
| 505 | *stat = client->fe_status; | ||
| 506 | |||
| 507 | led_feedback(client); | ||
| 508 | |||
| 509 | return rc; | ||
| 510 | } | ||
| 511 | |||
| 512 | static int smsdvb_read_ber(struct dvb_frontend *fe, u32 *ber) | ||
| 513 | { | ||
| 514 | int rc; | ||
| 515 | struct smsdvb_client_t *client; | ||
| 516 | client = container_of(fe, struct smsdvb_client_t, frontend); | ||
| 517 | |||
| 518 | rc = smsdvb_send_statistics_request(client); | ||
| 519 | |||
| 520 | *ber = client->sms_stat_dvb.ReceptionData.BER; | ||
| 521 | |||
| 522 | led_feedback(client); | ||
| 523 | |||
| 524 | return rc; | ||
| 525 | } | ||
| 526 | |||
| 527 | static int smsdvb_read_signal_strength(struct dvb_frontend *fe, u16 *strength) | ||
| 528 | { | ||
| 529 | int rc; | ||
| 530 | |||
| 531 | struct smsdvb_client_t *client; | ||
| 532 | client = container_of(fe, struct smsdvb_client_t, frontend); | ||
| 533 | |||
| 534 | rc = smsdvb_send_statistics_request(client); | ||
| 535 | |||
| 536 | if (client->sms_stat_dvb.ReceptionData.InBandPwr < -95) | ||
| 537 | *strength = 0; | ||
| 538 | else if (client->sms_stat_dvb.ReceptionData.InBandPwr > -29) | ||
| 539 | *strength = 100; | ||
| 540 | else | ||
| 541 | *strength = | ||
| 542 | (client->sms_stat_dvb.ReceptionData.InBandPwr | ||
| 543 | + 95) * 3 / 2; | ||
| 544 | |||
| 545 | led_feedback(client); | ||
| 546 | |||
| 547 | return rc; | ||
| 548 | } | ||
| 549 | |||
| 550 | static int smsdvb_read_snr(struct dvb_frontend *fe, u16 *snr) | ||
| 551 | { | ||
| 552 | int rc; | ||
| 553 | struct smsdvb_client_t *client; | ||
| 554 | client = container_of(fe, struct smsdvb_client_t, frontend); | ||
| 555 | |||
| 556 | rc = smsdvb_send_statistics_request(client); | ||
| 557 | |||
| 558 | *snr = client->sms_stat_dvb.ReceptionData.SNR; | ||
| 559 | |||
| 560 | led_feedback(client); | ||
| 561 | |||
| 562 | return rc; | ||
| 563 | } | ||
| 564 | |||
| 565 | static int smsdvb_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) | ||
| 566 | { | ||
| 567 | int rc; | ||
| 568 | struct smsdvb_client_t *client; | ||
| 569 | client = container_of(fe, struct smsdvb_client_t, frontend); | ||
| 570 | |||
| 571 | rc = smsdvb_send_statistics_request(client); | ||
| 572 | |||
| 573 | *ucblocks = client->sms_stat_dvb.ReceptionData.ErrorTSPackets; | ||
| 574 | |||
| 575 | led_feedback(client); | ||
| 576 | |||
| 577 | return rc; | ||
| 578 | } | ||
| 579 | |||
| 580 | static int smsdvb_get_tune_settings(struct dvb_frontend *fe, | ||
| 581 | struct dvb_frontend_tune_settings *tune) | ||
| 582 | { | ||
| 583 | sms_debug(""); | ||
| 584 | |||
| 585 | tune->min_delay_ms = 400; | ||
| 586 | tune->step_size = 250000; | ||
| 587 | tune->max_drift = 0; | ||
| 588 | return 0; | ||
| 589 | } | ||
| 590 | |||
| 591 | static int smsdvb_dvbt_set_frontend(struct dvb_frontend *fe) | ||
| 592 | { | ||
| 593 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 594 | struct smsdvb_client_t *client = | ||
| 595 | container_of(fe, struct smsdvb_client_t, frontend); | ||
| 596 | |||
| 597 | struct { | ||
| 598 | struct SmsMsgHdr_ST Msg; | ||
| 599 | u32 Data[3]; | ||
| 600 | } Msg; | ||
| 601 | |||
| 602 | int ret; | ||
| 603 | |||
| 604 | client->fe_status = FE_HAS_SIGNAL; | ||
| 605 | client->event_fe_state = -1; | ||
| 606 | client->event_unc_state = -1; | ||
| 607 | fe->dtv_property_cache.delivery_system = SYS_DVBT; | ||
| 608 | |||
| 609 | Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
| 610 | Msg.Msg.msgDstId = HIF_TASK; | ||
| 611 | Msg.Msg.msgFlags = 0; | ||
| 612 | Msg.Msg.msgType = MSG_SMS_RF_TUNE_REQ; | ||
| 613 | Msg.Msg.msgLength = sizeof(Msg); | ||
| 614 | Msg.Data[0] = c->frequency; | ||
| 615 | Msg.Data[2] = 12000000; | ||
| 616 | |||
| 617 | sms_info("%s: freq %d band %d", __func__, c->frequency, | ||
| 618 | c->bandwidth_hz); | ||
| 619 | |||
| 620 | switch (c->bandwidth_hz / 1000000) { | ||
| 621 | case 8: | ||
| 622 | Msg.Data[1] = BW_8_MHZ; | ||
| 623 | break; | ||
| 624 | case 7: | ||
| 625 | Msg.Data[1] = BW_7_MHZ; | ||
| 626 | break; | ||
| 627 | case 6: | ||
| 628 | Msg.Data[1] = BW_6_MHZ; | ||
| 629 | break; | ||
| 630 | case 0: | ||
| 631 | return -EOPNOTSUPP; | ||
| 632 | default: | ||
| 633 | return -EINVAL; | ||
| 634 | } | ||
| 635 | /* Disable LNA, if any. An error is returned if no LNA is present */ | ||
| 636 | ret = sms_board_lna_control(client->coredev, 0); | ||
| 637 | if (ret == 0) { | ||
| 638 | fe_status_t status; | ||
| 639 | |||
| 640 | /* tune with LNA off at first */ | ||
| 641 | ret = smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | ||
| 642 | &client->tune_done); | ||
| 643 | |||
| 644 | smsdvb_read_status(fe, &status); | ||
| 645 | |||
| 646 | if (status & FE_HAS_LOCK) | ||
| 647 | return ret; | ||
| 648 | |||
| 649 | /* previous tune didn't lock - enable LNA and tune again */ | ||
| 650 | sms_board_lna_control(client->coredev, 1); | ||
| 651 | } | ||
| 652 | |||
| 653 | return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | ||
| 654 | &client->tune_done); | ||
| 655 | } | ||
| 656 | |||
| 657 | static int smsdvb_isdbt_set_frontend(struct dvb_frontend *fe) | ||
| 658 | { | ||
| 659 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | ||
| 660 | struct smsdvb_client_t *client = | ||
| 661 | container_of(fe, struct smsdvb_client_t, frontend); | ||
| 662 | |||
| 663 | struct { | ||
| 664 | struct SmsMsgHdr_ST Msg; | ||
| 665 | u32 Data[4]; | ||
| 666 | } Msg; | ||
| 667 | |||
| 668 | fe->dtv_property_cache.delivery_system = SYS_ISDBT; | ||
| 669 | |||
| 670 | Msg.Msg.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; | ||
| 671 | Msg.Msg.msgDstId = HIF_TASK; | ||
| 672 | Msg.Msg.msgFlags = 0; | ||
| 673 | Msg.Msg.msgType = MSG_SMS_ISDBT_TUNE_REQ; | ||
| 674 | Msg.Msg.msgLength = sizeof(Msg); | ||
| 675 | |||
| 676 | if (c->isdbt_sb_segment_idx == -1) | ||
| 677 | c->isdbt_sb_segment_idx = 0; | ||
| 678 | |||
| 679 | switch (c->isdbt_sb_segment_count) { | ||
| 680 | case 3: | ||
| 681 | Msg.Data[1] = BW_ISDBT_3SEG; | ||
| 682 | break; | ||
| 683 | case 1: | ||
| 684 | Msg.Data[1] = BW_ISDBT_1SEG; | ||
| 685 | break; | ||
| 686 | case 0: /* AUTO */ | ||
| 687 | switch (c->bandwidth_hz / 1000000) { | ||
| 688 | case 8: | ||
| 689 | case 7: | ||
| 690 | c->isdbt_sb_segment_count = 3; | ||
| 691 | Msg.Data[1] = BW_ISDBT_3SEG; | ||
| 692 | break; | ||
| 693 | case 6: | ||
| 694 | c->isdbt_sb_segment_count = 1; | ||
| 695 | Msg.Data[1] = BW_ISDBT_1SEG; | ||
| 696 | break; | ||
| 697 | default: /* Assumes 6 MHZ bw */ | ||
| 698 | c->isdbt_sb_segment_count = 1; | ||
| 699 | c->bandwidth_hz = 6000; | ||
| 700 | Msg.Data[1] = BW_ISDBT_1SEG; | ||
| 701 | break; | ||
| 702 | } | ||
| 703 | break; | ||
| 704 | default: | ||
| 705 | sms_info("Segment count %d not supported", c->isdbt_sb_segment_count); | ||
| 706 | return -EINVAL; | ||
| 707 | } | ||
| 708 | |||
| 709 | Msg.Data[0] = c->frequency; | ||
| 710 | Msg.Data[2] = 12000000; | ||
| 711 | Msg.Data[3] = c->isdbt_sb_segment_idx; | ||
| 712 | |||
| 713 | sms_info("%s: freq %d segwidth %d segindex %d\n", __func__, | ||
| 714 | c->frequency, c->isdbt_sb_segment_count, | ||
| 715 | c->isdbt_sb_segment_idx); | ||
| 716 | |||
| 717 | return smsdvb_sendrequest_and_wait(client, &Msg, sizeof(Msg), | ||
| 718 | &client->tune_done); | ||
| 719 | } | ||
| 720 | |||
| 721 | static int smsdvb_set_frontend(struct dvb_frontend *fe) | ||
| 722 | { | ||
| 723 | struct smsdvb_client_t *client = | ||
| 724 | container_of(fe, struct smsdvb_client_t, frontend); | ||
| 725 | struct smscore_device_t *coredev = client->coredev; | ||
| 726 | |||
| 727 | switch (smscore_get_device_mode(coredev)) { | ||
| 728 | case DEVICE_MODE_DVBT: | ||
| 729 | case DEVICE_MODE_DVBT_BDA: | ||
| 730 | return smsdvb_dvbt_set_frontend(fe); | ||
| 731 | case DEVICE_MODE_ISDBT: | ||
| 732 | case DEVICE_MODE_ISDBT_BDA: | ||
| 733 | return smsdvb_isdbt_set_frontend(fe); | ||
| 734 | default: | ||
| 735 | return -EINVAL; | ||
| 736 | } | ||
| 737 | } | ||
| 738 | |||
| 739 | static int smsdvb_get_frontend(struct dvb_frontend *fe) | ||
| 740 | { | ||
| 741 | struct dtv_frontend_properties *fep = &fe->dtv_property_cache; | ||
| 742 | struct smsdvb_client_t *client = | ||
| 743 | container_of(fe, struct smsdvb_client_t, frontend); | ||
| 744 | struct smscore_device_t *coredev = client->coredev; | ||
| 745 | struct TRANSMISSION_STATISTICS_S *td = | ||
| 746 | &client->sms_stat_dvb.TransmissionData; | ||
| 747 | |||
| 748 | switch (smscore_get_device_mode(coredev)) { | ||
| 749 | case DEVICE_MODE_DVBT: | ||
| 750 | case DEVICE_MODE_DVBT_BDA: | ||
| 751 | fep->frequency = td->Frequency; | ||
| 752 | |||
| 753 | switch (td->Bandwidth) { | ||
| 754 | case 6: | ||
| 755 | fep->bandwidth_hz = 6000000; | ||
| 756 | break; | ||
| 757 | case 7: | ||
| 758 | fep->bandwidth_hz = 7000000; | ||
| 759 | break; | ||
| 760 | case 8: | ||
| 761 | fep->bandwidth_hz = 8000000; | ||
| 762 | break; | ||
| 763 | } | ||
| 764 | |||
| 765 | switch (td->TransmissionMode) { | ||
| 766 | case 2: | ||
| 767 | fep->transmission_mode = TRANSMISSION_MODE_2K; | ||
| 768 | break; | ||
| 769 | case 8: | ||
| 770 | fep->transmission_mode = TRANSMISSION_MODE_8K; | ||
| 771 | } | ||
| 772 | |||
| 773 | switch (td->GuardInterval) { | ||
| 774 | case 0: | ||
| 775 | fep->guard_interval = GUARD_INTERVAL_1_32; | ||
| 776 | break; | ||
| 777 | case 1: | ||
| 778 | fep->guard_interval = GUARD_INTERVAL_1_16; | ||
| 779 | break; | ||
| 780 | case 2: | ||
| 781 | fep->guard_interval = GUARD_INTERVAL_1_8; | ||
| 782 | break; | ||
| 783 | case 3: | ||
| 784 | fep->guard_interval = GUARD_INTERVAL_1_4; | ||
| 785 | break; | ||
| 786 | } | ||
| 787 | |||
| 788 | switch (td->CodeRate) { | ||
| 789 | case 0: | ||
| 790 | fep->code_rate_HP = FEC_1_2; | ||
| 791 | break; | ||
| 792 | case 1: | ||
| 793 | fep->code_rate_HP = FEC_2_3; | ||
| 794 | break; | ||
| 795 | case 2: | ||
| 796 | fep->code_rate_HP = FEC_3_4; | ||
| 797 | break; | ||
| 798 | case 3: | ||
| 799 | fep->code_rate_HP = FEC_5_6; | ||
| 800 | break; | ||
| 801 | case 4: | ||
| 802 | fep->code_rate_HP = FEC_7_8; | ||
| 803 | break; | ||
| 804 | } | ||
| 805 | |||
| 806 | switch (td->LPCodeRate) { | ||
| 807 | case 0: | ||
| 808 | fep->code_rate_LP = FEC_1_2; | ||
| 809 | break; | ||
| 810 | case 1: | ||
| 811 | fep->code_rate_LP = FEC_2_3; | ||
| 812 | break; | ||
| 813 | case 2: | ||
| 814 | fep->code_rate_LP = FEC_3_4; | ||
| 815 | break; | ||
| 816 | case 3: | ||
| 817 | fep->code_rate_LP = FEC_5_6; | ||
| 818 | break; | ||
| 819 | case 4: | ||
| 820 | fep->code_rate_LP = FEC_7_8; | ||
| 821 | break; | ||
| 822 | } | ||
| 823 | |||
| 824 | switch (td->Constellation) { | ||
| 825 | case 0: | ||
| 826 | fep->modulation = QPSK; | ||
| 827 | break; | ||
| 828 | case 1: | ||
| 829 | fep->modulation = QAM_16; | ||
| 830 | break; | ||
| 831 | case 2: | ||
| 832 | fep->modulation = QAM_64; | ||
| 833 | break; | ||
| 834 | } | ||
| 835 | |||
| 836 | switch (td->Hierarchy) { | ||
| 837 | case 0: | ||
| 838 | fep->hierarchy = HIERARCHY_NONE; | ||
| 839 | break; | ||
| 840 | case 1: | ||
| 841 | fep->hierarchy = HIERARCHY_1; | ||
| 842 | break; | ||
| 843 | case 2: | ||
| 844 | fep->hierarchy = HIERARCHY_2; | ||
| 845 | break; | ||
| 846 | case 3: | ||
| 847 | fep->hierarchy = HIERARCHY_4; | ||
| 848 | break; | ||
| 849 | } | ||
| 850 | |||
| 851 | fep->inversion = INVERSION_AUTO; | ||
| 852 | break; | ||
| 853 | case DEVICE_MODE_ISDBT: | ||
| 854 | case DEVICE_MODE_ISDBT_BDA: | ||
| 855 | fep->frequency = td->Frequency; | ||
| 856 | fep->bandwidth_hz = 6000000; | ||
| 857 | /* todo: retrive the other parameters */ | ||
| 858 | break; | ||
| 859 | default: | ||
| 860 | return -EINVAL; | ||
| 861 | } | ||
| 862 | |||
| 863 | return 0; | ||
| 864 | } | ||
| 865 | |||
| 866 | static int smsdvb_init(struct dvb_frontend *fe) | ||
| 867 | { | ||
| 868 | struct smsdvb_client_t *client = | ||
| 869 | container_of(fe, struct smsdvb_client_t, frontend); | ||
| 870 | |||
| 871 | sms_board_power(client->coredev, 1); | ||
| 872 | |||
| 873 | sms_board_dvb3_event(client, DVB3_EVENT_INIT); | ||
| 874 | return 0; | ||
| 875 | } | ||
| 876 | |||
| 877 | static int smsdvb_sleep(struct dvb_frontend *fe) | ||
| 878 | { | ||
| 879 | struct smsdvb_client_t *client = | ||
| 880 | container_of(fe, struct smsdvb_client_t, frontend); | ||
| 881 | |||
| 882 | sms_board_led_feedback(client->coredev, SMS_LED_OFF); | ||
| 883 | sms_board_power(client->coredev, 0); | ||
| 884 | |||
| 885 | sms_board_dvb3_event(client, DVB3_EVENT_SLEEP); | ||
| 886 | |||
| 887 | return 0; | ||
| 888 | } | ||
| 889 | |||
| 890 | static void smsdvb_release(struct dvb_frontend *fe) | ||
| 891 | { | ||
| 892 | /* do nothing */ | ||
| 893 | } | ||
| 894 | |||
| 895 | static struct dvb_frontend_ops smsdvb_fe_ops = { | ||
| 896 | .info = { | ||
| 897 | .name = "Siano Mobile Digital MDTV Receiver", | ||
| 898 | .frequency_min = 44250000, | ||
| 899 | .frequency_max = 867250000, | ||
| 900 | .frequency_stepsize = 250000, | ||
| 901 | .caps = FE_CAN_INVERSION_AUTO | | ||
| 902 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | ||
| 903 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | ||
| 904 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | | ||
| 905 | FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO | | ||
| 906 | FE_CAN_GUARD_INTERVAL_AUTO | | ||
| 907 | FE_CAN_RECOVER | | ||
| 908 | FE_CAN_HIERARCHY_AUTO, | ||
| 909 | }, | ||
| 910 | |||
| 911 | .release = smsdvb_release, | ||
| 912 | |||
| 913 | .set_frontend = smsdvb_set_frontend, | ||
| 914 | .get_frontend = smsdvb_get_frontend, | ||
| 915 | .get_tune_settings = smsdvb_get_tune_settings, | ||
| 916 | |||
| 917 | .read_status = smsdvb_read_status, | ||
| 918 | .read_ber = smsdvb_read_ber, | ||
| 919 | .read_signal_strength = smsdvb_read_signal_strength, | ||
| 920 | .read_snr = smsdvb_read_snr, | ||
| 921 | .read_ucblocks = smsdvb_read_ucblocks, | ||
| 922 | |||
| 923 | .init = smsdvb_init, | ||
| 924 | .sleep = smsdvb_sleep, | ||
| 925 | }; | ||
| 926 | |||
| 927 | static int smsdvb_hotplug(struct smscore_device_t *coredev, | ||
| 928 | struct device *device, int arrival) | ||
| 929 | { | ||
| 930 | struct smsclient_params_t params; | ||
| 931 | struct smsdvb_client_t *client; | ||
| 932 | int rc; | ||
| 933 | |||
| 934 | /* device removal handled by onremove callback */ | ||
| 935 | if (!arrival) | ||
| 936 | return 0; | ||
| 937 | client = kzalloc(sizeof(struct smsdvb_client_t), GFP_KERNEL); | ||
| 938 | if (!client) { | ||
| 939 | sms_err("kmalloc() failed"); | ||
| 940 | return -ENOMEM; | ||
| 941 | } | ||
| 942 | |||
| 943 | /* register dvb adapter */ | ||
| 944 | rc = dvb_register_adapter(&client->adapter, | ||
| 945 | sms_get_board( | ||
| 946 | smscore_get_board_id(coredev))->name, | ||
| 947 | THIS_MODULE, device, adapter_nr); | ||
| 948 | if (rc < 0) { | ||
| 949 | sms_err("dvb_register_adapter() failed %d", rc); | ||
| 950 | goto adapter_error; | ||
| 951 | } | ||
| 952 | |||
| 953 | /* init dvb demux */ | ||
| 954 | client->demux.dmx.capabilities = DMX_TS_FILTERING; | ||
| 955 | client->demux.filternum = 32; /* todo: nova ??? */ | ||
| 956 | client->demux.feednum = 32; | ||
| 957 | client->demux.start_feed = smsdvb_start_feed; | ||
| 958 | client->demux.stop_feed = smsdvb_stop_feed; | ||
| 959 | |||
| 960 | rc = dvb_dmx_init(&client->demux); | ||
| 961 | if (rc < 0) { | ||
| 962 | sms_err("dvb_dmx_init failed %d", rc); | ||
| 963 | goto dvbdmx_error; | ||
| 964 | } | ||
| 965 | |||
| 966 | /* init dmxdev */ | ||
| 967 | client->dmxdev.filternum = 32; | ||
| 968 | client->dmxdev.demux = &client->demux.dmx; | ||
| 969 | client->dmxdev.capabilities = 0; | ||
| 970 | |||
| 971 | rc = dvb_dmxdev_init(&client->dmxdev, &client->adapter); | ||
| 972 | if (rc < 0) { | ||
| 973 | sms_err("dvb_dmxdev_init failed %d", rc); | ||
| 974 | goto dmxdev_error; | ||
| 975 | } | ||
| 976 | |||
| 977 | /* init and register frontend */ | ||
| 978 | memcpy(&client->frontend.ops, &smsdvb_fe_ops, | ||
| 979 | sizeof(struct dvb_frontend_ops)); | ||
| 980 | |||
| 981 | switch (smscore_get_device_mode(coredev)) { | ||
| 982 | case DEVICE_MODE_DVBT: | ||
| 983 | case DEVICE_MODE_DVBT_BDA: | ||
| 984 | client->frontend.ops.delsys[0] = SYS_DVBT; | ||
| 985 | break; | ||
| 986 | case DEVICE_MODE_ISDBT: | ||
| 987 | case DEVICE_MODE_ISDBT_BDA: | ||
| 988 | client->frontend.ops.delsys[0] = SYS_ISDBT; | ||
| 989 | break; | ||
| 990 | } | ||
| 991 | |||
| 992 | rc = dvb_register_frontend(&client->adapter, &client->frontend); | ||
| 993 | if (rc < 0) { | ||
| 994 | sms_err("frontend registration failed %d", rc); | ||
| 995 | goto frontend_error; | ||
| 996 | } | ||
| 997 | |||
| 998 | params.initial_id = 1; | ||
| 999 | params.data_type = MSG_SMS_DVBT_BDA_DATA; | ||
| 1000 | params.onresponse_handler = smsdvb_onresponse; | ||
| 1001 | params.onremove_handler = smsdvb_onremove; | ||
| 1002 | params.context = client; | ||
| 1003 | |||
| 1004 | rc = smscore_register_client(coredev, ¶ms, &client->smsclient); | ||
| 1005 | if (rc < 0) { | ||
| 1006 | sms_err("smscore_register_client() failed %d", rc); | ||
| 1007 | goto client_error; | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | client->coredev = coredev; | ||
| 1011 | |||
| 1012 | init_completion(&client->tune_done); | ||
| 1013 | |||
| 1014 | kmutex_lock(&g_smsdvb_clientslock); | ||
| 1015 | |||
| 1016 | list_add(&client->entry, &g_smsdvb_clients); | ||
| 1017 | |||
| 1018 | kmutex_unlock(&g_smsdvb_clientslock); | ||
| 1019 | |||
| 1020 | client->event_fe_state = -1; | ||
| 1021 | client->event_unc_state = -1; | ||
| 1022 | sms_board_dvb3_event(client, DVB3_EVENT_HOTPLUG); | ||
| 1023 | |||
| 1024 | sms_info("success"); | ||
| 1025 | sms_board_setup(coredev); | ||
| 1026 | |||
| 1027 | return 0; | ||
| 1028 | |||
| 1029 | client_error: | ||
| 1030 | dvb_unregister_frontend(&client->frontend); | ||
| 1031 | |||
| 1032 | frontend_error: | ||
| 1033 | dvb_dmxdev_release(&client->dmxdev); | ||
| 1034 | |||
| 1035 | dmxdev_error: | ||
| 1036 | dvb_dmx_release(&client->demux); | ||
| 1037 | |||
| 1038 | dvbdmx_error: | ||
| 1039 | dvb_unregister_adapter(&client->adapter); | ||
| 1040 | |||
| 1041 | adapter_error: | ||
| 1042 | kfree(client); | ||
| 1043 | return rc; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | static int __init smsdvb_module_init(void) | ||
| 1047 | { | ||
| 1048 | int rc; | ||
| 1049 | |||
| 1050 | INIT_LIST_HEAD(&g_smsdvb_clients); | ||
| 1051 | kmutex_init(&g_smsdvb_clientslock); | ||
| 1052 | |||
| 1053 | rc = smscore_register_hotplug(smsdvb_hotplug); | ||
| 1054 | |||
| 1055 | sms_debug(""); | ||
| 1056 | |||
| 1057 | return rc; | ||
| 1058 | } | ||
| 1059 | |||
| 1060 | static void __exit smsdvb_module_exit(void) | ||
| 1061 | { | ||
| 1062 | smscore_unregister_hotplug(smsdvb_hotplug); | ||
| 1063 | |||
| 1064 | kmutex_lock(&g_smsdvb_clientslock); | ||
| 1065 | |||
| 1066 | while (!list_empty(&g_smsdvb_clients)) | ||
| 1067 | smsdvb_unregister_client( | ||
| 1068 | (struct smsdvb_client_t *) g_smsdvb_clients.next); | ||
| 1069 | |||
| 1070 | kmutex_unlock(&g_smsdvb_clientslock); | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | module_init(smsdvb_module_init); | ||
| 1074 | module_exit(smsdvb_module_exit); | ||
| 1075 | |||
| 1076 | MODULE_DESCRIPTION("SMS DVB subsystem adaptation module"); | ||
| 1077 | MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)"); | ||
| 1078 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/usb/siano/smsendian.c b/drivers/media/usb/siano/smsendian.c deleted file mode 100644 index e2657c2f0109..000000000000 --- a/drivers/media/usb/siano/smsendian.c +++ /dev/null | |||
| @@ -1,103 +0,0 @@ | |||
| 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 <linux/export.h> | ||
| 23 | #include <asm/byteorder.h> | ||
| 24 | |||
| 25 | #include "smsendian.h" | ||
| 26 | #include "smscoreapi.h" | ||
| 27 | |||
| 28 | void smsendian_handle_tx_message(void *buffer) | ||
| 29 | { | ||
| 30 | #ifdef __BIG_ENDIAN | ||
| 31 | struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer; | ||
| 32 | int i; | ||
| 33 | int msgWords; | ||
| 34 | |||
| 35 | switch (msg->xMsgHeader.msgType) { | ||
| 36 | case MSG_SMS_DATA_DOWNLOAD_REQ: | ||
| 37 | { | ||
| 38 | msg->msgData[0] = le32_to_cpu(msg->msgData[0]); | ||
| 39 | break; | ||
| 40 | } | ||
| 41 | |||
| 42 | default: | ||
| 43 | msgWords = (msg->xMsgHeader.msgLength - | ||
| 44 | sizeof(struct SmsMsgHdr_ST))/4; | ||
| 45 | |||
| 46 | for (i = 0; i < msgWords; i++) | ||
| 47 | msg->msgData[i] = le32_to_cpu(msg->msgData[i]); | ||
| 48 | |||
| 49 | break; | ||
| 50 | } | ||
| 51 | #endif /* __BIG_ENDIAN */ | ||
| 52 | } | ||
| 53 | EXPORT_SYMBOL_GPL(smsendian_handle_tx_message); | ||
| 54 | |||
| 55 | void smsendian_handle_rx_message(void *buffer) | ||
| 56 | { | ||
| 57 | #ifdef __BIG_ENDIAN | ||
| 58 | struct SmsMsgData_ST *msg = (struct SmsMsgData_ST *)buffer; | ||
| 59 | int i; | ||
| 60 | int msgWords; | ||
| 61 | |||
| 62 | switch (msg->xMsgHeader.msgType) { | ||
| 63 | case MSG_SMS_GET_VERSION_EX_RES: | ||
| 64 | { | ||
| 65 | struct SmsVersionRes_ST *ver = | ||
| 66 | (struct SmsVersionRes_ST *) msg; | ||
| 67 | ver->ChipModel = le16_to_cpu(ver->ChipModel); | ||
| 68 | break; | ||
| 69 | } | ||
| 70 | |||
| 71 | case MSG_SMS_DVBT_BDA_DATA: | ||
| 72 | case MSG_SMS_DAB_CHANNEL: | ||
| 73 | case MSG_SMS_DATA_MSG: | ||
| 74 | { | ||
| 75 | break; | ||
| 76 | } | ||
| 77 | |||
| 78 | default: | ||
| 79 | { | ||
| 80 | msgWords = (msg->xMsgHeader.msgLength - | ||
| 81 | sizeof(struct SmsMsgHdr_ST))/4; | ||
| 82 | |||
| 83 | for (i = 0; i < msgWords; i++) | ||
| 84 | msg->msgData[i] = le32_to_cpu(msg->msgData[i]); | ||
| 85 | |||
| 86 | break; | ||
| 87 | } | ||
| 88 | } | ||
| 89 | #endif /* __BIG_ENDIAN */ | ||
| 90 | } | ||
| 91 | EXPORT_SYMBOL_GPL(smsendian_handle_rx_message); | ||
| 92 | |||
| 93 | void smsendian_handle_message_header(void *msg) | ||
| 94 | { | ||
| 95 | #ifdef __BIG_ENDIAN | ||
| 96 | struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *)msg; | ||
| 97 | |||
| 98 | phdr->msgType = le16_to_cpu(phdr->msgType); | ||
| 99 | phdr->msgLength = le16_to_cpu(phdr->msgLength); | ||
| 100 | phdr->msgFlags = le16_to_cpu(phdr->msgFlags); | ||
| 101 | #endif /* __BIG_ENDIAN */ | ||
| 102 | } | ||
| 103 | EXPORT_SYMBOL_GPL(smsendian_handle_message_header); | ||
diff --git a/drivers/media/usb/siano/smsendian.h b/drivers/media/usb/siano/smsendian.h deleted file mode 100644 index 1624d6fd367b..000000000000 --- a/drivers/media/usb/siano/smsendian.h +++ /dev/null | |||
| @@ -1,32 +0,0 @@ | |||
| 1 | /**************************************************************** | ||
| 2 | |||
| 3 | Siano Mobile Silicon, Inc. | ||
| 4 | MDTV receiver kernel modules. | ||
| 5 | Copyright (C) 2006-2009, Uri Shkolnik | ||
| 6 | |||
| 7 | This program is free software: you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation, either version 2 of the License, or | ||
| 10 | (at your option) any later version. | ||
| 11 | |||
| 12 | This program is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 19 | |||
| 20 | ****************************************************************/ | ||
| 21 | |||
| 22 | #ifndef __SMS_ENDIAN_H__ | ||
| 23 | #define __SMS_ENDIAN_H__ | ||
| 24 | |||
| 25 | #include <asm/byteorder.h> | ||
| 26 | |||
| 27 | extern void smsendian_handle_tx_message(void *buffer); | ||
| 28 | extern void smsendian_handle_rx_message(void *buffer); | ||
| 29 | extern void smsendian_handle_message_header(void *msg); | ||
| 30 | |||
| 31 | #endif /* __SMS_ENDIAN_H__ */ | ||
| 32 | |||
diff --git a/drivers/media/usb/siano/smsir.c b/drivers/media/usb/siano/smsir.c deleted file mode 100644 index 37bc5c4b8ad8..000000000000 --- a/drivers/media/usb/siano/smsir.c +++ /dev/null | |||
| @@ -1,114 +0,0 @@ | |||
| 1 | /**************************************************************** | ||
| 2 | |||
| 3 | Siano Mobile Silicon, Inc. | ||
| 4 | MDTV receiver kernel modules. | ||
| 5 | Copyright (C) 2006-2009, Uri Shkolnik | ||
| 6 | |||
| 7 | Copyright (c) 2010 - Mauro Carvalho Chehab | ||
| 8 | - Ported the driver to use rc-core | ||
| 9 | - IR raw event decoding is now done at rc-core | ||
| 10 | - Code almost re-written | ||
| 11 | |||
| 12 | This program is free software: you can redistribute it and/or modify | ||
| 13 | it under the terms of the GNU General Public License as published by | ||
| 14 | the Free Software Foundation, either version 2 of the License, or | ||
| 15 | (at your option) any later version. | ||
| 16 | |||
| 17 | This program is distributed in the hope that it will be useful, | ||
| 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | GNU General Public License for more details. | ||
| 21 | |||
| 22 | You should have received a copy of the GNU General Public License | ||
| 23 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 24 | |||
| 25 | ****************************************************************/ | ||
| 26 | |||
| 27 | |||
| 28 | #include <linux/types.h> | ||
| 29 | #include <linux/input.h> | ||
| 30 | |||
| 31 | #include "smscoreapi.h" | ||
| 32 | #include "smsir.h" | ||
| 33 | #include "sms-cards.h" | ||
| 34 | |||
| 35 | #define MODULE_NAME "smsmdtv" | ||
| 36 | |||
| 37 | void sms_ir_event(struct smscore_device_t *coredev, const char *buf, int len) | ||
| 38 | { | ||
| 39 | int i; | ||
| 40 | const s32 *samples = (const void *)buf; | ||
| 41 | |||
| 42 | for (i = 0; i < len >> 2; i++) { | ||
| 43 | DEFINE_IR_RAW_EVENT(ev); | ||
| 44 | |||
| 45 | ev.duration = abs(samples[i]) * 1000; /* Convert to ns */ | ||
| 46 | ev.pulse = (samples[i] > 0) ? false : true; | ||
| 47 | |||
| 48 | ir_raw_event_store(coredev->ir.dev, &ev); | ||
| 49 | } | ||
| 50 | ir_raw_event_handle(coredev->ir.dev); | ||
| 51 | } | ||
| 52 | |||
| 53 | int sms_ir_init(struct smscore_device_t *coredev) | ||
| 54 | { | ||
| 55 | int err; | ||
| 56 | int board_id = smscore_get_board_id(coredev); | ||
| 57 | struct rc_dev *dev; | ||
| 58 | |||
| 59 | sms_log("Allocating rc device"); | ||
| 60 | dev = rc_allocate_device(); | ||
| 61 | if (!dev) { | ||
| 62 | sms_err("Not enough memory"); | ||
| 63 | return -ENOMEM; | ||
| 64 | } | ||
| 65 | |||
| 66 | coredev->ir.controller = 0; /* Todo: vega/nova SPI number */ | ||
| 67 | coredev->ir.timeout = IR_DEFAULT_TIMEOUT; | ||
| 68 | sms_log("IR port %d, timeout %d ms", | ||
| 69 | coredev->ir.controller, coredev->ir.timeout); | ||
| 70 | |||
| 71 | snprintf(coredev->ir.name, sizeof(coredev->ir.name), | ||
| 72 | "SMS IR (%s)", sms_get_board(board_id)->name); | ||
| 73 | |||
| 74 | strlcpy(coredev->ir.phys, coredev->devpath, sizeof(coredev->ir.phys)); | ||
| 75 | strlcat(coredev->ir.phys, "/ir0", sizeof(coredev->ir.phys)); | ||
| 76 | |||
| 77 | dev->input_name = coredev->ir.name; | ||
| 78 | dev->input_phys = coredev->ir.phys; | ||
| 79 | dev->dev.parent = coredev->device; | ||
| 80 | |||
| 81 | #if 0 | ||
| 82 | /* TODO: properly initialize the parameters bellow */ | ||
| 83 | dev->input_id.bustype = BUS_USB; | ||
| 84 | dev->input_id.version = 1; | ||
| 85 | dev->input_id.vendor = le16_to_cpu(dev->udev->descriptor.idVendor); | ||
| 86 | dev->input_id.product = le16_to_cpu(dev->udev->descriptor.idProduct); | ||
| 87 | #endif | ||
| 88 | |||
| 89 | dev->priv = coredev; | ||
| 90 | dev->driver_type = RC_DRIVER_IR_RAW; | ||
| 91 | dev->allowed_protos = RC_TYPE_ALL; | ||
| 92 | dev->map_name = sms_get_board(board_id)->rc_codes; | ||
| 93 | dev->driver_name = MODULE_NAME; | ||
| 94 | |||
| 95 | sms_log("Input device (IR) %s is set for key events", dev->input_name); | ||
| 96 | |||
| 97 | err = rc_register_device(dev); | ||
| 98 | if (err < 0) { | ||
| 99 | sms_err("Failed to register device"); | ||
| 100 | rc_free_device(dev); | ||
| 101 | return err; | ||
| 102 | } | ||
| 103 | |||
| 104 | coredev->ir.dev = dev; | ||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | |||
| 108 | void sms_ir_exit(struct smscore_device_t *coredev) | ||
| 109 | { | ||
| 110 | if (coredev->ir.dev) | ||
| 111 | rc_unregister_device(coredev->ir.dev); | ||
| 112 | |||
| 113 | sms_log(""); | ||
| 114 | } | ||
diff --git a/drivers/media/usb/siano/smsir.h b/drivers/media/usb/siano/smsir.h deleted file mode 100644 index ae92b3a8587e..000000000000 --- a/drivers/media/usb/siano/smsir.h +++ /dev/null | |||
| @@ -1,55 +0,0 @@ | |||
| 1 | /**************************************************************** | ||
| 2 | |||
| 3 | Siano Mobile Silicon, Inc. | ||
| 4 | MDTV receiver kernel modules. | ||
| 5 | Copyright (C) 2006-2009, Uri Shkolnik | ||
| 6 | |||
| 7 | Copyright (c) 2010 - Mauro Carvalho Chehab | ||
| 8 | - Ported the driver to use rc-core | ||
| 9 | - IR raw event decoding is now done at rc-core | ||
| 10 | - Code almost re-written | ||
| 11 | |||
| 12 | This program is free software: you can redistribute it and/or modify | ||
| 13 | it under the terms of the GNU General Public License as published by | ||
| 14 | the Free Software Foundation, either version 2 of the License, or | ||
| 15 | (at your option) any later version. | ||
| 16 | |||
| 17 | This program is distributed in the hope that it will be useful, | ||
| 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 20 | GNU General Public License for more details. | ||
| 21 | |||
| 22 | You should have received a copy of the GNU General Public License | ||
| 23 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 24 | |||
| 25 | ****************************************************************/ | ||
| 26 | |||
| 27 | #ifndef __SMS_IR_H__ | ||
| 28 | #define __SMS_IR_H__ | ||
| 29 | |||
| 30 | #include <linux/input.h> | ||
| 31 | #include <media/rc-core.h> | ||
| 32 | |||
| 33 | #define IR_DEFAULT_TIMEOUT 100 | ||
| 34 | |||
| 35 | struct smscore_device_t; | ||
| 36 | |||
| 37 | struct ir_t { | ||
| 38 | struct rc_dev *dev; | ||
| 39 | char name[40]; | ||
| 40 | char phys[32]; | ||
| 41 | |||
| 42 | char *rc_codes; | ||
| 43 | u64 protocol; | ||
| 44 | |||
| 45 | u32 timeout; | ||
| 46 | u32 controller; | ||
| 47 | }; | ||
| 48 | |||
| 49 | int sms_ir_init(struct smscore_device_t *coredev); | ||
| 50 | void sms_ir_exit(struct smscore_device_t *coredev); | ||
| 51 | void sms_ir_event(struct smscore_device_t *coredev, | ||
| 52 | const char *buf, int len); | ||
| 53 | |||
| 54 | #endif /* __SMS_IR_H__ */ | ||
| 55 | |||
diff --git a/drivers/media/usb/siano/smssdio.c b/drivers/media/usb/siano/smssdio.c deleted file mode 100644 index d6f3f100699a..000000000000 --- a/drivers/media/usb/siano/smssdio.c +++ /dev/null | |||
| @@ -1,365 +0,0 @@ | |||
| 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/slab.h> | ||
| 37 | #include <linux/firmware.h> | ||
| 38 | #include <linux/delay.h> | ||
| 39 | #include <linux/mmc/card.h> | ||
| 40 | #include <linux/mmc/sdio_func.h> | ||
| 41 | #include <linux/mmc/sdio_ids.h> | ||
| 42 | #include <linux/module.h> | ||
| 43 | |||
| 44 | #include "smscoreapi.h" | ||
| 45 | #include "sms-cards.h" | ||
| 46 | |||
| 47 | /* Registers */ | ||
| 48 | |||
| 49 | #define SMSSDIO_DATA 0x00 | ||
| 50 | #define SMSSDIO_INT 0x04 | ||
| 51 | #define SMSSDIO_BLOCK_SIZE 128 | ||
| 52 | |||
| 53 | static const struct sdio_device_id smssdio_ids[] __devinitconst = { | ||
| 54 | {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_STELLAR), | ||
| 55 | .driver_data = SMS1XXX_BOARD_SIANO_STELLAR}, | ||
| 56 | {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_A0), | ||
| 57 | .driver_data = SMS1XXX_BOARD_SIANO_NOVA_A}, | ||
| 58 | {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_NOVA_B0), | ||
| 59 | .driver_data = SMS1XXX_BOARD_SIANO_NOVA_B}, | ||
| 60 | {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VEGA_A0), | ||
| 61 | .driver_data = SMS1XXX_BOARD_SIANO_VEGA}, | ||
| 62 | {SDIO_DEVICE(SDIO_VENDOR_ID_SIANO, SDIO_DEVICE_ID_SIANO_VENICE), | ||
| 63 | .driver_data = SMS1XXX_BOARD_SIANO_VEGA}, | ||
| 64 | { /* end: all zeroes */ }, | ||
| 65 | }; | ||
| 66 | |||
| 67 | MODULE_DEVICE_TABLE(sdio, smssdio_ids); | ||
| 68 | |||
| 69 | struct smssdio_device { | ||
| 70 | struct sdio_func *func; | ||
| 71 | |||
| 72 | struct smscore_device_t *coredev; | ||
| 73 | |||
| 74 | struct smscore_buffer_t *split_cb; | ||
| 75 | }; | ||
| 76 | |||
| 77 | /*******************************************************************/ | ||
| 78 | /* Siano core callbacks */ | ||
| 79 | /*******************************************************************/ | ||
| 80 | |||
| 81 | static int smssdio_sendrequest(void *context, void *buffer, size_t size) | ||
| 82 | { | ||
| 83 | int ret = 0; | ||
| 84 | struct smssdio_device *smsdev; | ||
| 85 | |||
| 86 | smsdev = context; | ||
| 87 | |||
| 88 | sdio_claim_host(smsdev->func); | ||
| 89 | |||
| 90 | while (size >= smsdev->func->cur_blksize) { | ||
| 91 | ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA, | ||
| 92 | buffer, smsdev->func->cur_blksize); | ||
| 93 | if (ret) | ||
| 94 | goto out; | ||
| 95 | |||
| 96 | buffer += smsdev->func->cur_blksize; | ||
| 97 | size -= smsdev->func->cur_blksize; | ||
| 98 | } | ||
| 99 | |||
| 100 | if (size) { | ||
| 101 | ret = sdio_memcpy_toio(smsdev->func, SMSSDIO_DATA, | ||
| 102 | buffer, size); | ||
| 103 | } | ||
| 104 | |||
| 105 | out: | ||
| 106 | sdio_release_host(smsdev->func); | ||
| 107 | |||
| 108 | return ret; | ||
| 109 | } | ||
| 110 | |||
| 111 | /*******************************************************************/ | ||
| 112 | /* SDIO callbacks */ | ||
| 113 | /*******************************************************************/ | ||
| 114 | |||
| 115 | static void smssdio_interrupt(struct sdio_func *func) | ||
| 116 | { | ||
| 117 | int ret; | ||
| 118 | |||
| 119 | struct smssdio_device *smsdev; | ||
| 120 | struct smscore_buffer_t *cb; | ||
| 121 | struct SmsMsgHdr_ST *hdr; | ||
| 122 | size_t size; | ||
| 123 | |||
| 124 | smsdev = sdio_get_drvdata(func); | ||
| 125 | |||
| 126 | /* | ||
| 127 | * The interrupt register has no defined meaning. It is just | ||
| 128 | * a way of turning of the level triggered interrupt. | ||
| 129 | */ | ||
| 130 | (void)sdio_readb(func, SMSSDIO_INT, &ret); | ||
| 131 | if (ret) { | ||
| 132 | sms_err("Unable to read interrupt register!\n"); | ||
| 133 | return; | ||
| 134 | } | ||
| 135 | |||
| 136 | if (smsdev->split_cb == NULL) { | ||
| 137 | cb = smscore_getbuffer(smsdev->coredev); | ||
| 138 | if (!cb) { | ||
| 139 | sms_err("Unable to allocate data buffer!\n"); | ||
| 140 | return; | ||
| 141 | } | ||
| 142 | |||
| 143 | ret = sdio_memcpy_fromio(smsdev->func, | ||
| 144 | cb->p, | ||
| 145 | SMSSDIO_DATA, | ||
| 146 | SMSSDIO_BLOCK_SIZE); | ||
| 147 | if (ret) { | ||
| 148 | sms_err("Error %d reading initial block!\n", ret); | ||
| 149 | return; | ||
| 150 | } | ||
| 151 | |||
| 152 | hdr = cb->p; | ||
| 153 | |||
| 154 | if (hdr->msgFlags & MSG_HDR_FLAG_SPLIT_MSG) { | ||
| 155 | smsdev->split_cb = cb; | ||
| 156 | return; | ||
| 157 | } | ||
| 158 | |||
| 159 | if (hdr->msgLength > smsdev->func->cur_blksize) | ||
| 160 | size = hdr->msgLength - smsdev->func->cur_blksize; | ||
| 161 | else | ||
| 162 | size = 0; | ||
| 163 | } else { | ||
| 164 | cb = smsdev->split_cb; | ||
| 165 | hdr = cb->p; | ||
| 166 | |||
| 167 | size = hdr->msgLength - sizeof(struct SmsMsgHdr_ST); | ||
| 168 | |||
| 169 | smsdev->split_cb = NULL; | ||
| 170 | } | ||
| 171 | |||
| 172 | if (size) { | ||
| 173 | void *buffer; | ||
| 174 | |||
| 175 | buffer = cb->p + (hdr->msgLength - size); | ||
| 176 | size = ALIGN(size, SMSSDIO_BLOCK_SIZE); | ||
| 177 | |||
| 178 | BUG_ON(smsdev->func->cur_blksize != SMSSDIO_BLOCK_SIZE); | ||
| 179 | |||
| 180 | /* | ||
| 181 | * First attempt to transfer all of it in one go... | ||
| 182 | */ | ||
| 183 | ret = sdio_memcpy_fromio(smsdev->func, | ||
| 184 | buffer, | ||
| 185 | SMSSDIO_DATA, | ||
| 186 | size); | ||
| 187 | if (ret && ret != -EINVAL) { | ||
| 188 | smscore_putbuffer(smsdev->coredev, cb); | ||
| 189 | sms_err("Error %d reading data from card!\n", ret); | ||
| 190 | return; | ||
| 191 | } | ||
| 192 | |||
| 193 | /* | ||
| 194 | * ..then fall back to one block at a time if that is | ||
| 195 | * not possible... | ||
| 196 | * | ||
| 197 | * (we have to do this manually because of the | ||
| 198 | * problem with the "increase address" bit) | ||
| 199 | */ | ||
| 200 | if (ret == -EINVAL) { | ||
| 201 | while (size) { | ||
| 202 | ret = sdio_memcpy_fromio(smsdev->func, | ||
| 203 | buffer, SMSSDIO_DATA, | ||
| 204 | smsdev->func->cur_blksize); | ||
| 205 | if (ret) { | ||
| 206 | smscore_putbuffer(smsdev->coredev, cb); | ||
| 207 | sms_err("Error %d reading " | ||
| 208 | "data from card!\n", ret); | ||
| 209 | return; | ||
| 210 | } | ||
| 211 | |||
| 212 | buffer += smsdev->func->cur_blksize; | ||
| 213 | if (size > smsdev->func->cur_blksize) | ||
| 214 | size -= smsdev->func->cur_blksize; | ||
| 215 | else | ||
| 216 | size = 0; | ||
| 217 | } | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | cb->size = hdr->msgLength; | ||
| 222 | cb->offset = 0; | ||
| 223 | |||
| 224 | smscore_onresponse(smsdev->coredev, cb); | ||
| 225 | } | ||
| 226 | |||
| 227 | static int __devinit smssdio_probe(struct sdio_func *func, | ||
| 228 | const struct sdio_device_id *id) | ||
| 229 | { | ||
| 230 | int ret; | ||
| 231 | |||
| 232 | int board_id; | ||
| 233 | struct smssdio_device *smsdev; | ||
| 234 | struct smsdevice_params_t params; | ||
| 235 | |||
| 236 | board_id = id->driver_data; | ||
| 237 | |||
| 238 | smsdev = kzalloc(sizeof(struct smssdio_device), GFP_KERNEL); | ||
| 239 | if (!smsdev) | ||
| 240 | return -ENOMEM; | ||
| 241 | |||
| 242 | smsdev->func = func; | ||
| 243 | |||
| 244 | memset(¶ms, 0, sizeof(struct smsdevice_params_t)); | ||
| 245 | |||
| 246 | params.device = &func->dev; | ||
| 247 | params.buffer_size = 0x5000; /* ?? */ | ||
| 248 | params.num_buffers = 22; /* ?? */ | ||
| 249 | params.context = smsdev; | ||
| 250 | |||
| 251 | snprintf(params.devpath, sizeof(params.devpath), | ||
| 252 | "sdio\\%s", sdio_func_id(func)); | ||
| 253 | |||
| 254 | params.sendrequest_handler = smssdio_sendrequest; | ||
| 255 | |||
| 256 | params.device_type = sms_get_board(board_id)->type; | ||
| 257 | |||
| 258 | if (params.device_type != SMS_STELLAR) | ||
| 259 | params.flags |= SMS_DEVICE_FAMILY2; | ||
| 260 | else { | ||
| 261 | /* | ||
| 262 | * FIXME: Stellar needs special handling... | ||
| 263 | */ | ||
| 264 | ret = -ENODEV; | ||
| 265 | goto free; | ||
| 266 | } | ||
| 267 | |||
| 268 | ret = smscore_register_device(¶ms, &smsdev->coredev); | ||
| 269 | if (ret < 0) | ||
| 270 | goto free; | ||
| 271 | |||
| 272 | smscore_set_board_id(smsdev->coredev, board_id); | ||
| 273 | |||
| 274 | sdio_claim_host(func); | ||
| 275 | |||
| 276 | ret = sdio_enable_func(func); | ||
| 277 | if (ret) | ||
| 278 | goto release; | ||
| 279 | |||
| 280 | ret = sdio_set_block_size(func, SMSSDIO_BLOCK_SIZE); | ||
| 281 | if (ret) | ||
| 282 | goto disable; | ||
| 283 | |||
| 284 | ret = sdio_claim_irq(func, smssdio_interrupt); | ||
| 285 | if (ret) | ||
| 286 | goto disable; | ||
| 287 | |||
| 288 | sdio_set_drvdata(func, smsdev); | ||
| 289 | |||
| 290 | sdio_release_host(func); | ||
| 291 | |||
| 292 | ret = smscore_start_device(smsdev->coredev); | ||
| 293 | if (ret < 0) | ||
| 294 | goto reclaim; | ||
| 295 | |||
| 296 | return 0; | ||
| 297 | |||
| 298 | reclaim: | ||
| 299 | sdio_claim_host(func); | ||
| 300 | sdio_release_irq(func); | ||
| 301 | disable: | ||
| 302 | sdio_disable_func(func); | ||
| 303 | release: | ||
| 304 | sdio_release_host(func); | ||
| 305 | smscore_unregister_device(smsdev->coredev); | ||
| 306 | free: | ||
| 307 | kfree(smsdev); | ||
| 308 | |||
| 309 | return ret; | ||
| 310 | } | ||
| 311 | |||
| 312 | static void smssdio_remove(struct sdio_func *func) | ||
| 313 | { | ||
| 314 | struct smssdio_device *smsdev; | ||
| 315 | |||
| 316 | smsdev = sdio_get_drvdata(func); | ||
| 317 | |||
| 318 | /* FIXME: racy! */ | ||
| 319 | if (smsdev->split_cb) | ||
| 320 | smscore_putbuffer(smsdev->coredev, smsdev->split_cb); | ||
| 321 | |||
| 322 | smscore_unregister_device(smsdev->coredev); | ||
| 323 | |||
| 324 | sdio_claim_host(func); | ||
| 325 | sdio_release_irq(func); | ||
| 326 | sdio_disable_func(func); | ||
| 327 | sdio_release_host(func); | ||
| 328 | |||
| 329 | kfree(smsdev); | ||
| 330 | } | ||
| 331 | |||
| 332 | static struct sdio_driver smssdio_driver = { | ||
| 333 | .name = "smssdio", | ||
| 334 | .id_table = smssdio_ids, | ||
| 335 | .probe = smssdio_probe, | ||
| 336 | .remove = smssdio_remove, | ||
| 337 | }; | ||
| 338 | |||
| 339 | /*******************************************************************/ | ||
| 340 | /* Module functions */ | ||
| 341 | /*******************************************************************/ | ||
| 342 | |||
| 343 | static int __init smssdio_module_init(void) | ||
| 344 | { | ||
| 345 | int ret = 0; | ||
| 346 | |||
| 347 | printk(KERN_INFO "smssdio: Siano SMS1xxx SDIO driver\n"); | ||
| 348 | printk(KERN_INFO "smssdio: Copyright Pierre Ossman\n"); | ||
| 349 | |||
| 350 | ret = sdio_register_driver(&smssdio_driver); | ||
| 351 | |||
| 352 | return ret; | ||
| 353 | } | ||
| 354 | |||
| 355 | static void __exit smssdio_module_exit(void) | ||
| 356 | { | ||
| 357 | sdio_unregister_driver(&smssdio_driver); | ||
| 358 | } | ||
| 359 | |||
| 360 | module_init(smssdio_module_init); | ||
| 361 | module_exit(smssdio_module_exit); | ||
| 362 | |||
| 363 | MODULE_DESCRIPTION("Siano SMS1xxx SDIO driver"); | ||
| 364 | MODULE_AUTHOR("Pierre Ossman"); | ||
| 365 | MODULE_LICENSE("GPL"); | ||
