gp8psk: Fix DVB frontend attach

The DVB binding schema at the DVB core assumes that the frontend is a
separate driver. Faling to do that causes OOPS when the module is
removed, as it tries to do a symbol_put_addr on an internal symbol,
causing craches like:

WARNING: CPU: 1 PID: 28102 at kernel/module.c:1108 module_put+0x57/0x70
Modules linked in: dvb_usb_gp8psk(-) dvb_usb dvb_core nvidia_drm(PO) nvidia_modeset(PO) snd_hda_codec_hdmi snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm snd_timer snd soundcore nvidia(PO) [last unloaded: rc_core]
CPU: 1 PID: 28102 Comm: rmmod Tainted: P WC O 4.8.4-build.1 #1
Hardware name: MSI MS-7309/MS-7309, BIOS V1.12 02/23/2009
Call Trace:
dump_stack+0x44/0x64
__warn+0xfa/0x120
module_put+0x57/0x70
module_put+0x57/0x70
warn_slowpath_null+0x23/0x30
module_put+0x57/0x70
gp8psk_fe_set_frontend+0x460/0x460 [dvb_usb_gp8psk]
symbol_put_addr+0x27/0x50
dvb_usb_adapter_frontend_exit+0x3a/0x70 [dvb_usb]

From Derek's tests:
"Attach bug is fixed, tuning works, module unloads without
crashing. Everything seems ok!"

Reported-by: Derek <user.vdr@gmail.com>
Tested-by: Derek <user.vdr@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by Mauro Carvalho Chehab and committed by Linus Torvalds 7a0786c1 1596c387

Changed files
+244 -150
drivers
+5
drivers/media/dvb-frontends/Kconfig
··· 513 513 depends on DVB_CORE 514 514 default DVB_AS102 515 515 516 + config DVB_GP8PSK_FE 517 + tristate 518 + depends on DVB_CORE 519 + default DVB_USB_GP8PSK 520 + 516 521 comment "DVB-C (cable) frontends" 517 522 depends on DVB_CORE 518 523
+1
drivers/media/dvb-frontends/Makefile
··· 121 121 obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o 122 122 obj-$(CONFIG_DVB_AF9033) += af9033.o 123 123 obj-$(CONFIG_DVB_AS102_FE) += as102_fe.o 124 + obj-$(CONFIG_DVB_GP8PSK_FE) += gp8psk-fe.o 124 125 obj-$(CONFIG_DVB_TC90522) += tc90522.o 125 126 obj-$(CONFIG_DVB_HORUS3A) += horus3a.o 126 127 obj-$(CONFIG_DVB_ASCOT2E) += ascot2e.o
+82
drivers/media/dvb-frontends/gp8psk-fe.h
··· 1 + /* 2 + * gp8psk_fe driver 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License as published by 6 + * the Free Software Foundation; either version 2, or (at your option) 7 + * any later version. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + */ 14 + 15 + #ifndef GP8PSK_FE_H 16 + #define GP8PSK_FE_H 17 + 18 + #include <linux/types.h> 19 + 20 + /* gp8psk commands */ 21 + 22 + #define GET_8PSK_CONFIG 0x80 /* in */ 23 + #define SET_8PSK_CONFIG 0x81 24 + #define I2C_WRITE 0x83 25 + #define I2C_READ 0x84 26 + #define ARM_TRANSFER 0x85 27 + #define TUNE_8PSK 0x86 28 + #define GET_SIGNAL_STRENGTH 0x87 /* in */ 29 + #define LOAD_BCM4500 0x88 30 + #define BOOT_8PSK 0x89 /* in */ 31 + #define START_INTERSIL 0x8A /* in */ 32 + #define SET_LNB_VOLTAGE 0x8B 33 + #define SET_22KHZ_TONE 0x8C 34 + #define SEND_DISEQC_COMMAND 0x8D 35 + #define SET_DVB_MODE 0x8E 36 + #define SET_DN_SWITCH 0x8F 37 + #define GET_SIGNAL_LOCK 0x90 /* in */ 38 + #define GET_FW_VERS 0x92 39 + #define GET_SERIAL_NUMBER 0x93 /* in */ 40 + #define USE_EXTRA_VOLT 0x94 41 + #define GET_FPGA_VERS 0x95 42 + #define CW3K_INIT 0x9d 43 + 44 + /* PSK_configuration bits */ 45 + #define bm8pskStarted 0x01 46 + #define bm8pskFW_Loaded 0x02 47 + #define bmIntersilOn 0x04 48 + #define bmDVBmode 0x08 49 + #define bm22kHz 0x10 50 + #define bmSEL18V 0x20 51 + #define bmDCtuned 0x40 52 + #define bmArmed 0x80 53 + 54 + /* Satellite modulation modes */ 55 + #define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */ 56 + #define ADV_MOD_TURBO_QPSK 1 /* Turbo QPSK */ 57 + #define ADV_MOD_TURBO_8PSK 2 /* Turbo 8PSK (also used for Trellis 8PSK) */ 58 + #define ADV_MOD_TURBO_16QAM 3 /* Turbo 16QAM (also used for Trellis 8PSK) */ 59 + 60 + #define ADV_MOD_DCII_C_QPSK 4 /* Digicipher II Combo */ 61 + #define ADV_MOD_DCII_I_QPSK 5 /* Digicipher II I-stream */ 62 + #define ADV_MOD_DCII_Q_QPSK 6 /* Digicipher II Q-stream */ 63 + #define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */ 64 + #define ADV_MOD_DSS_QPSK 8 /* DSS (DIRECTV) QPSK */ 65 + #define ADV_MOD_DVB_BPSK 9 /* DVB-S BPSK */ 66 + 67 + /* firmware revision id's */ 68 + #define GP8PSK_FW_REV1 0x020604 69 + #define GP8PSK_FW_REV2 0x020704 70 + #define GP8PSK_FW_VERS(_fw_vers) \ 71 + ((_fw_vers)[2]<<0x10 | (_fw_vers)[1]<<0x08 | (_fw_vers)[0]) 72 + 73 + struct gp8psk_fe_ops { 74 + int (*in)(void *priv, u8 req, u16 value, u16 index, u8 *b, int blen); 75 + int (*out)(void *priv, u8 req, u16 value, u16 index, u8 *b, int blen); 76 + int (*reload)(void *priv); 77 + }; 78 + 79 + struct dvb_frontend *gp8psk_fe_attach(const struct gp8psk_fe_ops *ops, 80 + void *priv, bool is_rev1); 81 + 82 + #endif
+1 -1
drivers/media/usb/dvb-usb/Makefile
··· 8 8 dvb-usb-vp702x-objs := vp702x.o vp702x-fe.o 9 9 obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o 10 10 11 - dvb-usb-gp8psk-objs := gp8psk.o gp8psk-fe.o 11 + dvb-usb-gp8psk-objs := gp8psk.o 12 12 obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o 13 13 14 14 dvb-usb-dtt200u-objs := dtt200u.o dtt200u-fe.o
+80 -55
drivers/media/usb/dvb-usb/gp8psk-fe.c drivers/media/dvb-frontends/gp8psk-fe.c
··· 14 14 * 15 15 * see Documentation/dvb/README.dvb-usb for more information 16 16 */ 17 - #include "gp8psk.h" 17 + 18 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 19 + 20 + #include "gp8psk-fe.h" 21 + #include "dvb_frontend.h" 22 + 23 + static int debug; 24 + module_param(debug, int, 0644); 25 + MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); 26 + 27 + #define dprintk(fmt, arg...) do { \ 28 + if (debug) \ 29 + printk(KERN_DEBUG pr_fmt("%s: " fmt), \ 30 + __func__, ##arg); \ 31 + } while (0) 18 32 19 33 struct gp8psk_fe_state { 20 34 struct dvb_frontend fe; 21 - struct dvb_usb_device *d; 35 + void *priv; 36 + const struct gp8psk_fe_ops *ops; 37 + bool is_rev1; 22 38 u8 lock; 23 39 u16 snr; 24 40 unsigned long next_status_check; ··· 45 29 { 46 30 struct gp8psk_fe_state *st = fe->demodulator_priv; 47 31 u8 status; 48 - gp8psk_usb_in_op(st->d, GET_8PSK_CONFIG, 0, 0, &status, 1); 32 + 33 + st->ops->in(st->priv, GET_8PSK_CONFIG, 0, 0, &status, 1); 49 34 return status & bmDCtuned; 50 35 } 51 36 52 37 static int gp8psk_set_tuner_mode(struct dvb_frontend *fe, int mode) 53 38 { 54 - struct gp8psk_fe_state *state = fe->demodulator_priv; 55 - return gp8psk_usb_out_op(state->d, SET_8PSK_CONFIG, mode, 0, NULL, 0); 39 + struct gp8psk_fe_state *st = fe->demodulator_priv; 40 + 41 + return st->ops->out(st->priv, SET_8PSK_CONFIG, mode, 0, NULL, 0); 56 42 } 57 43 58 44 static int gp8psk_fe_update_status(struct gp8psk_fe_state *st) 59 45 { 60 46 u8 buf[6]; 61 47 if (time_after(jiffies,st->next_status_check)) { 62 - gp8psk_usb_in_op(st->d, GET_SIGNAL_LOCK, 0,0,&st->lock,1); 63 - gp8psk_usb_in_op(st->d, GET_SIGNAL_STRENGTH, 0,0,buf,6); 48 + st->ops->in(st->priv, GET_SIGNAL_LOCK, 0, 0, &st->lock, 1); 49 + st->ops->in(st->priv, GET_SIGNAL_STRENGTH, 0, 0, buf, 6); 64 50 st->snr = (buf[1]) << 8 | buf[0]; 65 51 st->next_status_check = jiffies + (st->status_check_interval*HZ)/1000; 66 52 } ··· 134 116 135 117 static int gp8psk_fe_set_frontend(struct dvb_frontend *fe) 136 118 { 137 - struct gp8psk_fe_state *state = fe->demodulator_priv; 119 + struct gp8psk_fe_state *st = fe->demodulator_priv; 138 120 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 139 121 u8 cmd[10]; 140 122 u32 freq = c->frequency * 1000; 141 - int gp_product_id = le16_to_cpu(state->d->udev->descriptor.idProduct); 142 123 143 - deb_fe("%s()\n", __func__); 124 + dprintk("%s()\n", __func__); 144 125 145 126 cmd[4] = freq & 0xff; 146 127 cmd[5] = (freq >> 8) & 0xff; ··· 153 136 switch (c->delivery_system) { 154 137 case SYS_DVBS: 155 138 if (c->modulation != QPSK) { 156 - deb_fe("%s: unsupported modulation selected (%d)\n", 139 + dprintk("%s: unsupported modulation selected (%d)\n", 157 140 __func__, c->modulation); 158 141 return -EOPNOTSUPP; 159 142 } 160 143 c->fec_inner = FEC_AUTO; 161 144 break; 162 145 case SYS_DVBS2: /* kept for backwards compatibility */ 163 - deb_fe("%s: DVB-S2 delivery system selected\n", __func__); 146 + dprintk("%s: DVB-S2 delivery system selected\n", __func__); 164 147 break; 165 148 case SYS_TURBO: 166 - deb_fe("%s: Turbo-FEC delivery system selected\n", __func__); 149 + dprintk("%s: Turbo-FEC delivery system selected\n", __func__); 167 150 break; 168 151 169 152 default: 170 - deb_fe("%s: unsupported delivery system selected (%d)\n", 153 + dprintk("%s: unsupported delivery system selected (%d)\n", 171 154 __func__, c->delivery_system); 172 155 return -EOPNOTSUPP; 173 156 } ··· 178 161 cmd[3] = (c->symbol_rate >> 24) & 0xff; 179 162 switch (c->modulation) { 180 163 case QPSK: 181 - if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) 164 + if (st->is_rev1) 182 165 if (gp8psk_tuned_to_DCII(fe)) 183 - gp8psk_bcm4500_reload(state->d); 166 + st->ops->reload(st->priv); 184 167 switch (c->fec_inner) { 185 168 case FEC_1_2: 186 169 cmd[9] = 0; break; ··· 224 207 cmd[9] = 0; 225 208 break; 226 209 default: /* Unknown modulation */ 227 - deb_fe("%s: unsupported modulation selected (%d)\n", 210 + dprintk("%s: unsupported modulation selected (%d)\n", 228 211 __func__, c->modulation); 229 212 return -EOPNOTSUPP; 230 213 } 231 214 232 - if (gp_product_id == USB_PID_GENPIX_8PSK_REV_1_WARM) 215 + if (st->is_rev1) 233 216 gp8psk_set_tuner_mode(fe, 0); 234 - gp8psk_usb_out_op(state->d, TUNE_8PSK, 0, 0, cmd, 10); 217 + st->ops->out(st->priv, TUNE_8PSK, 0, 0, cmd, 10); 235 218 236 - state->lock = 0; 237 - state->next_status_check = jiffies; 238 - state->status_check_interval = 200; 219 + st->lock = 0; 220 + st->next_status_check = jiffies; 221 + st->status_check_interval = 200; 239 222 240 223 return 0; 241 224 } ··· 245 228 { 246 229 struct gp8psk_fe_state *st = fe->demodulator_priv; 247 230 248 - deb_fe("%s\n",__func__); 231 + dprintk("%s\n", __func__); 249 232 250 - if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, m->msg[0], 0, 233 + if (st->ops->out(st->priv, SEND_DISEQC_COMMAND, m->msg[0], 0, 251 234 m->msg, m->msg_len)) { 252 235 return -EINVAL; 253 236 } ··· 260 243 struct gp8psk_fe_state *st = fe->demodulator_priv; 261 244 u8 cmd; 262 245 263 - deb_fe("%s\n",__func__); 246 + dprintk("%s\n", __func__); 264 247 265 248 /* These commands are certainly wrong */ 266 249 cmd = (burst == SEC_MINI_A) ? 0x00 : 0x01; 267 250 268 - if (gp8psk_usb_out_op(st->d,SEND_DISEQC_COMMAND, cmd, 0, 251 + if (st->ops->out(st->priv, SEND_DISEQC_COMMAND, cmd, 0, 269 252 &cmd, 0)) { 270 253 return -EINVAL; 271 254 } ··· 275 258 static int gp8psk_fe_set_tone(struct dvb_frontend *fe, 276 259 enum fe_sec_tone_mode tone) 277 260 { 278 - struct gp8psk_fe_state* state = fe->demodulator_priv; 261 + struct gp8psk_fe_state *st = fe->demodulator_priv; 279 262 280 - if (gp8psk_usb_out_op(state->d,SET_22KHZ_TONE, 281 - (tone == SEC_TONE_ON), 0, NULL, 0)) { 263 + if (st->ops->out(st->priv, SET_22KHZ_TONE, 264 + (tone == SEC_TONE_ON), 0, NULL, 0)) { 282 265 return -EINVAL; 283 266 } 284 267 return 0; ··· 287 270 static int gp8psk_fe_set_voltage(struct dvb_frontend *fe, 288 271 enum fe_sec_voltage voltage) 289 272 { 290 - struct gp8psk_fe_state* state = fe->demodulator_priv; 273 + struct gp8psk_fe_state *st = fe->demodulator_priv; 291 274 292 - if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, 275 + if (st->ops->out(st->priv, SET_LNB_VOLTAGE, 293 276 voltage == SEC_VOLTAGE_18, 0, NULL, 0)) { 294 277 return -EINVAL; 295 278 } ··· 298 281 299 282 static int gp8psk_fe_enable_high_lnb_voltage(struct dvb_frontend* fe, long onoff) 300 283 { 301 - struct gp8psk_fe_state* state = fe->demodulator_priv; 302 - return gp8psk_usb_out_op(state->d, USE_EXTRA_VOLT, onoff, 0,NULL,0); 284 + struct gp8psk_fe_state *st = fe->demodulator_priv; 285 + 286 + return st->ops->out(st->priv, USE_EXTRA_VOLT, onoff, 0, NULL, 0); 303 287 } 304 288 305 289 static int gp8psk_fe_send_legacy_dish_cmd (struct dvb_frontend* fe, unsigned long sw_cmd) 306 290 { 307 - struct gp8psk_fe_state* state = fe->demodulator_priv; 291 + struct gp8psk_fe_state *st = fe->demodulator_priv; 308 292 u8 cmd = sw_cmd & 0x7f; 309 293 310 - if (gp8psk_usb_out_op(state->d,SET_DN_SWITCH, cmd, 0, 311 - NULL, 0)) { 294 + if (st->ops->out(st->priv, SET_DN_SWITCH, cmd, 0, NULL, 0)) 312 295 return -EINVAL; 313 - } 314 - if (gp8psk_usb_out_op(state->d,SET_LNB_VOLTAGE, !!(sw_cmd & 0x80), 315 - 0, NULL, 0)) { 296 + 297 + if (st->ops->out(st->priv, SET_LNB_VOLTAGE, !!(sw_cmd & 0x80), 298 + 0, NULL, 0)) 316 299 return -EINVAL; 317 - } 318 300 319 301 return 0; 320 302 } 321 303 322 304 static void gp8psk_fe_release(struct dvb_frontend* fe) 323 305 { 324 - struct gp8psk_fe_state *state = fe->demodulator_priv; 325 - kfree(state); 306 + struct gp8psk_fe_state *st = fe->demodulator_priv; 307 + 308 + kfree(st); 326 309 } 327 310 328 311 static struct dvb_frontend_ops gp8psk_fe_ops; 329 312 330 - struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d) 313 + struct dvb_frontend *gp8psk_fe_attach(const struct gp8psk_fe_ops *ops, 314 + void *priv, bool is_rev1) 331 315 { 332 - struct gp8psk_fe_state *s = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL); 333 - if (s == NULL) 334 - goto error; 316 + struct gp8psk_fe_state *st; 335 317 336 - s->d = d; 337 - memcpy(&s->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops)); 338 - s->fe.demodulator_priv = s; 318 + if (!ops || !ops->in || !ops->out || !ops->reload) { 319 + pr_err("Error! gp8psk-fe ops not defined.\n"); 320 + return NULL; 321 + } 339 322 340 - goto success; 341 - error: 342 - return NULL; 343 - success: 344 - return &s->fe; 323 + st = kzalloc(sizeof(struct gp8psk_fe_state), GFP_KERNEL); 324 + if (!st) 325 + return NULL; 326 + 327 + memcpy(&st->fe.ops, &gp8psk_fe_ops, sizeof(struct dvb_frontend_ops)); 328 + st->fe.demodulator_priv = st; 329 + st->ops = ops; 330 + st->priv = priv; 331 + st->is_rev1 = is_rev1; 332 + 333 + pr_info("Frontend %sattached\n", is_rev1 ? "revision 1 " : ""); 334 + 335 + return &st->fe; 345 336 } 346 - 337 + EXPORT_SYMBOL_GPL(gp8psk_fe_attach); 347 338 348 339 static struct dvb_frontend_ops gp8psk_fe_ops = { 349 340 .delsys = { SYS_DVBS },
+75 -31
drivers/media/usb/dvb-usb/gp8psk.c
··· 15 15 * see Documentation/dvb/README.dvb-usb for more information 16 16 */ 17 17 #include "gp8psk.h" 18 + #include "gp8psk-fe.h" 18 19 19 20 /* debug */ 20 21 static char bcm4500_firmware[] = "dvb-usb-gp8psk-02.fw"; ··· 29 28 unsigned char data[80]; 30 29 }; 31 30 32 - static int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers) 33 - { 34 - return (gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6)); 35 - } 36 - 37 - static int gp8psk_get_fpga_version(struct dvb_usb_device *d, u8 *fpga_vers) 38 - { 39 - return (gp8psk_usb_in_op(d, GET_FPGA_VERS, 0, 0, fpga_vers, 1)); 40 - } 41 - 42 - static void gp8psk_info(struct dvb_usb_device *d) 43 - { 44 - u8 fpga_vers, fw_vers[6]; 45 - 46 - if (!gp8psk_get_fw_version(d, fw_vers)) 47 - info("FW Version = %i.%02i.%i (0x%x) Build %4i/%02i/%02i", 48 - fw_vers[2], fw_vers[1], fw_vers[0], GP8PSK_FW_VERS(fw_vers), 49 - 2000 + fw_vers[5], fw_vers[4], fw_vers[3]); 50 - else 51 - info("failed to get FW version"); 52 - 53 - if (!gp8psk_get_fpga_version(d, &fpga_vers)) 54 - info("FPGA Version = %i", fpga_vers); 55 - else 56 - info("failed to get FPGA version"); 57 - } 58 - 59 - int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen) 31 + static int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, 32 + u16 index, u8 *b, int blen) 60 33 { 61 34 struct gp8psk_state *st = d->priv; 62 35 int ret = 0,try = 0; ··· 68 93 return ret; 69 94 } 70 95 71 - int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, 96 + static int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, 72 97 u16 index, u8 *b, int blen) 73 98 { 74 99 struct gp8psk_state *st = d->priv; ··· 97 122 mutex_unlock(&d->usb_mutex); 98 123 99 124 return ret; 125 + } 126 + 127 + 128 + static int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers) 129 + { 130 + return gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6); 131 + } 132 + 133 + static int gp8psk_get_fpga_version(struct dvb_usb_device *d, u8 *fpga_vers) 134 + { 135 + return gp8psk_usb_in_op(d, GET_FPGA_VERS, 0, 0, fpga_vers, 1); 136 + } 137 + 138 + static void gp8psk_info(struct dvb_usb_device *d) 139 + { 140 + u8 fpga_vers, fw_vers[6]; 141 + 142 + if (!gp8psk_get_fw_version(d, fw_vers)) 143 + info("FW Version = %i.%02i.%i (0x%x) Build %4i/%02i/%02i", 144 + fw_vers[2], fw_vers[1], fw_vers[0], GP8PSK_FW_VERS(fw_vers), 145 + 2000 + fw_vers[5], fw_vers[4], fw_vers[3]); 146 + else 147 + info("failed to get FW version"); 148 + 149 + if (!gp8psk_get_fpga_version(d, &fpga_vers)) 150 + info("FPGA Version = %i", fpga_vers); 151 + else 152 + info("failed to get FPGA version"); 100 153 } 101 154 102 155 static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d) ··· 229 226 return 0; 230 227 } 231 228 232 - int gp8psk_bcm4500_reload(struct dvb_usb_device *d) 229 + static int gp8psk_bcm4500_reload(struct dvb_usb_device *d) 233 230 { 234 231 u8 buf; 235 232 int gp_product_id = le16_to_cpu(d->udev->descriptor.idProduct); 233 + 234 + deb_xfer("reloading firmware\n"); 235 + 236 236 /* Turn off 8psk power */ 237 237 if (gp8psk_usb_in_op(d, BOOT_8PSK, 0, 0, &buf, 1)) 238 238 return -EINVAL; ··· 254 248 return gp8psk_usb_out_op(adap->dev, ARM_TRANSFER, onoff, 0 , NULL, 0); 255 249 } 256 250 251 + /* Callbacks for gp8psk-fe.c */ 252 + 253 + static int gp8psk_fe_in(void *priv, u8 req, u16 value, 254 + u16 index, u8 *b, int blen) 255 + { 256 + struct dvb_usb_device *d = priv; 257 + 258 + return gp8psk_usb_in_op(d, req, value, index, b, blen); 259 + } 260 + 261 + static int gp8psk_fe_out(void *priv, u8 req, u16 value, 262 + u16 index, u8 *b, int blen) 263 + { 264 + struct dvb_usb_device *d = priv; 265 + 266 + return gp8psk_usb_out_op(d, req, value, index, b, blen); 267 + } 268 + 269 + static int gp8psk_fe_reload(void *priv) 270 + { 271 + struct dvb_usb_device *d = priv; 272 + 273 + return gp8psk_bcm4500_reload(d); 274 + } 275 + 276 + const struct gp8psk_fe_ops gp8psk_fe_ops = { 277 + .in = gp8psk_fe_in, 278 + .out = gp8psk_fe_out, 279 + .reload = gp8psk_fe_reload, 280 + }; 281 + 257 282 static int gp8psk_frontend_attach(struct dvb_usb_adapter *adap) 258 283 { 259 - adap->fe_adap[0].fe = gp8psk_fe_attach(adap->dev); 284 + struct dvb_usb_device *d = adap->dev; 285 + int id = le16_to_cpu(d->udev->descriptor.idProduct); 286 + int is_rev1; 287 + 288 + is_rev1 = (id == USB_PID_GENPIX_8PSK_REV_1_WARM) ? true : false; 289 + 290 + adap->fe_adap[0].fe = dvb_attach(gp8psk_fe_attach, 291 + &gp8psk_fe_ops, d, is_rev1); 260 292 return 0; 261 293 } 262 294
-63
drivers/media/usb/dvb-usb/gp8psk.h
··· 24 24 #define deb_info(args...) dprintk(dvb_usb_gp8psk_debug,0x01,args) 25 25 #define deb_xfer(args...) dprintk(dvb_usb_gp8psk_debug,0x02,args) 26 26 #define deb_rc(args...) dprintk(dvb_usb_gp8psk_debug,0x04,args) 27 - #define deb_fe(args...) dprintk(dvb_usb_gp8psk_debug,0x08,args) 28 - 29 - /* Twinhan Vendor requests */ 30 - #define TH_COMMAND_IN 0xC0 31 - #define TH_COMMAND_OUT 0xC1 32 - 33 - /* gp8psk commands */ 34 - 35 - #define GET_8PSK_CONFIG 0x80 /* in */ 36 - #define SET_8PSK_CONFIG 0x81 37 - #define I2C_WRITE 0x83 38 - #define I2C_READ 0x84 39 - #define ARM_TRANSFER 0x85 40 - #define TUNE_8PSK 0x86 41 - #define GET_SIGNAL_STRENGTH 0x87 /* in */ 42 - #define LOAD_BCM4500 0x88 43 - #define BOOT_8PSK 0x89 /* in */ 44 - #define START_INTERSIL 0x8A /* in */ 45 - #define SET_LNB_VOLTAGE 0x8B 46 - #define SET_22KHZ_TONE 0x8C 47 - #define SEND_DISEQC_COMMAND 0x8D 48 - #define SET_DVB_MODE 0x8E 49 - #define SET_DN_SWITCH 0x8F 50 - #define GET_SIGNAL_LOCK 0x90 /* in */ 51 - #define GET_FW_VERS 0x92 52 - #define GET_SERIAL_NUMBER 0x93 /* in */ 53 - #define USE_EXTRA_VOLT 0x94 54 - #define GET_FPGA_VERS 0x95 55 - #define CW3K_INIT 0x9d 56 - 57 - /* PSK_configuration bits */ 58 - #define bm8pskStarted 0x01 59 - #define bm8pskFW_Loaded 0x02 60 - #define bmIntersilOn 0x04 61 - #define bmDVBmode 0x08 62 - #define bm22kHz 0x10 63 - #define bmSEL18V 0x20 64 - #define bmDCtuned 0x40 65 - #define bmArmed 0x80 66 - 67 - /* Satellite modulation modes */ 68 - #define ADV_MOD_DVB_QPSK 0 /* DVB-S QPSK */ 69 - #define ADV_MOD_TURBO_QPSK 1 /* Turbo QPSK */ 70 - #define ADV_MOD_TURBO_8PSK 2 /* Turbo 8PSK (also used for Trellis 8PSK) */ 71 - #define ADV_MOD_TURBO_16QAM 3 /* Turbo 16QAM (also used for Trellis 8PSK) */ 72 - 73 - #define ADV_MOD_DCII_C_QPSK 4 /* Digicipher II Combo */ 74 - #define ADV_MOD_DCII_I_QPSK 5 /* Digicipher II I-stream */ 75 - #define ADV_MOD_DCII_Q_QPSK 6 /* Digicipher II Q-stream */ 76 - #define ADV_MOD_DCII_C_OQPSK 7 /* Digicipher II offset QPSK */ 77 - #define ADV_MOD_DSS_QPSK 8 /* DSS (DIRECTV) QPSK */ 78 - #define ADV_MOD_DVB_BPSK 9 /* DVB-S BPSK */ 79 27 80 28 #define GET_USB_SPEED 0x07 81 29 ··· 33 85 #define VENDOR_STRING_READ 0x0C 34 86 #define PRODUCT_STRING_READ 0x0D 35 87 #define FW_BCD_VERSION_READ 0x14 36 - 37 - /* firmware revision id's */ 38 - #define GP8PSK_FW_REV1 0x020604 39 - #define GP8PSK_FW_REV2 0x020704 40 - #define GP8PSK_FW_VERS(_fw_vers) ((_fw_vers)[2]<<0x10 | (_fw_vers)[1]<<0x08 | (_fw_vers)[0]) 41 - 42 - extern struct dvb_frontend * gp8psk_fe_attach(struct dvb_usb_device *d); 43 - extern int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen); 44 - extern int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value, 45 - u16 index, u8 *b, int blen); 46 - extern int gp8psk_bcm4500_reload(struct dvb_usb_device *d); 47 88 48 89 #endif