0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include "digitv.h"
0012
0013 #include "mt352.h"
0014 #include "nxt6000.h"
0015
0016
0017 static int dvb_usb_digitv_debug;
0018 module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
0019 MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
0020
0021 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
0022
0023 #define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args)
0024
0025 static int digitv_ctrl_msg(struct dvb_usb_device *d,
0026 u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
0027 {
0028 struct digitv_state *st = d->priv;
0029 int ret, wo;
0030
0031 wo = (rbuf == NULL || rlen == 0);
0032
0033 if (wlen > 4 || rlen > 4)
0034 return -EIO;
0035
0036 memset(st->sndbuf, 0, 7);
0037 memset(st->rcvbuf, 0, 7);
0038
0039 st->sndbuf[0] = cmd;
0040 st->sndbuf[1] = vv;
0041 st->sndbuf[2] = wo ? wlen : rlen;
0042
0043 if (wo) {
0044 memcpy(&st->sndbuf[3], wbuf, wlen);
0045 ret = dvb_usb_generic_write(d, st->sndbuf, 7);
0046 } else {
0047 ret = dvb_usb_generic_rw(d, st->sndbuf, 7, st->rcvbuf, 7, 10);
0048 memcpy(rbuf, &st->rcvbuf[3], rlen);
0049 }
0050 return ret;
0051 }
0052
0053
0054 static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
0055 {
0056 struct dvb_usb_device *d = i2c_get_adapdata(adap);
0057 int i;
0058
0059 if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
0060 return -EAGAIN;
0061
0062 if (num > 2)
0063 warn("more than 2 i2c messages at a time is not handled yet. TODO.");
0064
0065 for (i = 0; i < num; i++) {
0066
0067 if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
0068 if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0,
0069 msg[i+1].buf,msg[i+1].len) < 0)
0070 break;
0071 i++;
0072 } else
0073 if (digitv_ctrl_msg(d,USB_WRITE_COFDM, msg[i].buf[0],
0074 &msg[i].buf[1],msg[i].len-1,NULL,0) < 0)
0075 break;
0076 }
0077
0078 mutex_unlock(&d->i2c_mutex);
0079 return i;
0080 }
0081
0082 static u32 digitv_i2c_func(struct i2c_adapter *adapter)
0083 {
0084 return I2C_FUNC_I2C;
0085 }
0086
0087 static struct i2c_algorithm digitv_i2c_algo = {
0088 .master_xfer = digitv_i2c_xfer,
0089 .functionality = digitv_i2c_func,
0090 };
0091
0092
0093 static int digitv_identify_state(struct usb_device *udev,
0094 const struct dvb_usb_device_properties *props,
0095 const struct dvb_usb_device_description **desc,
0096 int *cold)
0097 {
0098 *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
0099 return 0;
0100 }
0101
0102 static int digitv_mt352_demod_init(struct dvb_frontend *fe)
0103 {
0104 static u8 reset_buf[] = { 0x89, 0x38, 0x8a, 0x2d, 0x50, 0x80 };
0105 static u8 init_buf[] = { 0x68, 0xa0, 0x8e, 0x40, 0x53, 0x50,
0106 0x67, 0x20, 0x7d, 0x01, 0x7c, 0x00, 0x7a, 0x00,
0107 0x79, 0x20, 0x57, 0x05, 0x56, 0x31, 0x88, 0x0f,
0108 0x75, 0x32 };
0109 int i;
0110
0111 for (i = 0; i < ARRAY_SIZE(reset_buf); i += 2)
0112 mt352_write(fe, &reset_buf[i], 2);
0113
0114 msleep(1);
0115
0116 for (i = 0; i < ARRAY_SIZE(init_buf); i += 2)
0117 mt352_write(fe, &init_buf[i], 2);
0118
0119 return 0;
0120 }
0121
0122 static struct mt352_config digitv_mt352_config = {
0123 .demod_init = digitv_mt352_demod_init,
0124 };
0125
0126 static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe)
0127 {
0128 struct dvb_usb_adapter *adap = fe->dvb->priv;
0129 u8 b[5];
0130
0131 fe->ops.tuner_ops.calc_regs(fe, b, sizeof(b));
0132 if (fe->ops.i2c_gate_ctrl)
0133 fe->ops.i2c_gate_ctrl(fe, 1);
0134 return digitv_ctrl_msg(adap->dev, USB_WRITE_TUNER, 0, &b[1], 4, NULL, 0);
0135 }
0136
0137 static struct nxt6000_config digitv_nxt6000_config = {
0138 .clock_inversion = 1,
0139 };
0140
0141 static int digitv_frontend_attach(struct dvb_usb_adapter *adap)
0142 {
0143 struct digitv_state *st = adap->dev->priv;
0144
0145 adap->fe_adap[0].fe = dvb_attach(mt352_attach, &digitv_mt352_config,
0146 &adap->dev->i2c_adap);
0147 if ((adap->fe_adap[0].fe) != NULL) {
0148 st->is_nxt6000 = 0;
0149 return 0;
0150 }
0151 adap->fe_adap[0].fe = dvb_attach(nxt6000_attach,
0152 &digitv_nxt6000_config,
0153 &adap->dev->i2c_adap);
0154 if ((adap->fe_adap[0].fe) != NULL) {
0155 st->is_nxt6000 = 1;
0156 return 0;
0157 }
0158 return -EIO;
0159 }
0160
0161 static int digitv_tuner_attach(struct dvb_usb_adapter *adap)
0162 {
0163 struct digitv_state *st = adap->dev->priv;
0164
0165 if (!dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, NULL, DVB_PLL_TDED4))
0166 return -ENODEV;
0167
0168 if (st->is_nxt6000)
0169 adap->fe_adap[0].fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
0170
0171 return 0;
0172 }
0173
0174 static struct rc_map_table rc_map_digitv_table[] = {
0175 { 0x5f55, KEY_0 },
0176 { 0x6f55, KEY_1 },
0177 { 0x9f55, KEY_2 },
0178 { 0xaf55, KEY_3 },
0179 { 0x5f56, KEY_4 },
0180 { 0x6f56, KEY_5 },
0181 { 0x9f56, KEY_6 },
0182 { 0xaf56, KEY_7 },
0183 { 0x5f59, KEY_8 },
0184 { 0x6f59, KEY_9 },
0185 { 0x9f59, KEY_TV },
0186 { 0xaf59, KEY_AUX },
0187 { 0x5f5a, KEY_DVD },
0188 { 0x6f5a, KEY_POWER },
0189 { 0x9f5a, KEY_CAMERA },
0190 { 0xaf5a, KEY_AUDIO },
0191 { 0x5f65, KEY_INFO },
0192 { 0x6f65, KEY_F13 },
0193 { 0x9f65, KEY_F14 },
0194 { 0xaf65, KEY_EPG },
0195 { 0x5f66, KEY_EXIT },
0196 { 0x6f66, KEY_MENU },
0197 { 0x9f66, KEY_UP },
0198 { 0xaf66, KEY_DOWN },
0199 { 0x5f69, KEY_LEFT },
0200 { 0x6f69, KEY_RIGHT },
0201 { 0x9f69, KEY_ENTER },
0202 { 0xaf69, KEY_CHANNELUP },
0203 { 0x5f6a, KEY_CHANNELDOWN },
0204 { 0x6f6a, KEY_VOLUMEUP },
0205 { 0x9f6a, KEY_VOLUMEDOWN },
0206 { 0xaf6a, KEY_RED },
0207 { 0x5f95, KEY_GREEN },
0208 { 0x6f95, KEY_YELLOW },
0209 { 0x9f95, KEY_BLUE },
0210 { 0xaf95, KEY_SUBTITLE },
0211 { 0x5f96, KEY_F15 },
0212 { 0x6f96, KEY_TEXT },
0213 { 0x9f96, KEY_MUTE },
0214 { 0xaf96, KEY_REWIND },
0215 { 0x5f99, KEY_STOP },
0216 { 0x6f99, KEY_PLAY },
0217 { 0x9f99, KEY_FASTFORWARD },
0218 { 0xaf99, KEY_F16 },
0219 { 0x5f9a, KEY_PAUSE },
0220 { 0x6f9a, KEY_PLAY },
0221 { 0x9f9a, KEY_RECORD },
0222 { 0xaf9a, KEY_F17 },
0223 { 0x5fa5, KEY_KPPLUS },
0224 { 0x6fa5, KEY_KPMINUS },
0225 { 0x9fa5, KEY_F18 },
0226 { 0xafa5, KEY_F19 },
0227 { 0x5fa6, KEY_EMAIL },
0228 { 0x6fa6, KEY_PHONE },
0229 { 0x9fa6, KEY_PC },
0230 };
0231
0232 static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
0233 {
0234 struct rc_map_table *entry;
0235 int ret, i;
0236 u8 key[4];
0237 u8 b[4] = { 0 };
0238
0239 *event = 0;
0240 *state = REMOTE_NO_KEY_PRESSED;
0241
0242 ret = digitv_ctrl_msg(d, USB_READ_REMOTE, 0, NULL, 0, key, 4);
0243 if (ret)
0244 return ret;
0245
0246
0247
0248 ret = digitv_ctrl_msg(d, USB_WRITE_REMOTE, 0, b, 4, NULL, 0);
0249 if (ret)
0250 return ret;
0251
0252
0253 if (key[0] != 0) {
0254 for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
0255 entry = &d->props.rc.legacy.rc_map_table[i];
0256
0257 if (rc5_custom(entry) == key[0] &&
0258 rc5_data(entry) == key[1]) {
0259 *event = entry->keycode;
0260 *state = REMOTE_KEY_PRESSED;
0261 return 0;
0262 }
0263 }
0264
0265 deb_rc("key: %*ph\n", 4, key);
0266 }
0267
0268 return 0;
0269 }
0270
0271
0272 static struct dvb_usb_device_properties digitv_properties;
0273
0274 static int digitv_probe(struct usb_interface *intf,
0275 const struct usb_device_id *id)
0276 {
0277 struct dvb_usb_device *d;
0278 int ret = dvb_usb_device_init(intf, &digitv_properties, THIS_MODULE, &d,
0279 adapter_nr);
0280 if (ret == 0) {
0281 u8 b[4] = { 0 };
0282
0283 if (d != NULL) {
0284 b[0] = 1;
0285 digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
0286
0287 b[0] = 0;
0288 digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
0289 }
0290 }
0291 return ret;
0292 }
0293
0294 enum {
0295 ANCHOR_NEBULA_DIGITV,
0296 };
0297
0298 static struct usb_device_id digitv_table[] = {
0299 DVB_USB_DEV(ANCHOR, ANCHOR_NEBULA_DIGITV),
0300 { }
0301 };
0302
0303 MODULE_DEVICE_TABLE (usb, digitv_table);
0304
0305 static struct dvb_usb_device_properties digitv_properties = {
0306 .caps = DVB_USB_IS_AN_I2C_ADAPTER,
0307
0308 .usb_ctrl = CYPRESS_FX2,
0309 .firmware = "dvb-usb-digitv-02.fw",
0310
0311 .size_of_priv = sizeof(struct digitv_state),
0312
0313 .num_adapters = 1,
0314 .adapter = {
0315 {
0316 .num_frontends = 1,
0317 .fe = {{
0318 .frontend_attach = digitv_frontend_attach,
0319 .tuner_attach = digitv_tuner_attach,
0320
0321
0322 .stream = {
0323 .type = USB_BULK,
0324 .count = 7,
0325 .endpoint = 0x02,
0326 .u = {
0327 .bulk = {
0328 .buffersize = 4096,
0329 }
0330 }
0331 },
0332 }},
0333 }
0334 },
0335 .identify_state = digitv_identify_state,
0336
0337 .rc.legacy = {
0338 .rc_interval = 1000,
0339 .rc_map_table = rc_map_digitv_table,
0340 .rc_map_size = ARRAY_SIZE(rc_map_digitv_table),
0341 .rc_query = digitv_rc_query,
0342 },
0343
0344 .i2c_algo = &digitv_i2c_algo,
0345
0346 .generic_bulk_ctrl_endpoint = 0x01,
0347
0348 .num_device_descs = 1,
0349 .devices = {
0350 { "Nebula Electronics uDigiTV DVB-T USB2.0)",
0351 { &digitv_table[ANCHOR_NEBULA_DIGITV], NULL },
0352 { NULL },
0353 },
0354 { NULL },
0355 }
0356 };
0357
0358 static struct usb_driver digitv_driver = {
0359 .name = "dvb_usb_digitv",
0360 .probe = digitv_probe,
0361 .disconnect = dvb_usb_device_exit,
0362 .id_table = digitv_table,
0363 };
0364
0365 module_usb_driver(digitv_driver);
0366
0367 MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
0368 MODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0");
0369 MODULE_VERSION("1.0-alpha");
0370 MODULE_LICENSE("GPL");