^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * receiver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * partly based on the SDK published by Nebula Electronics
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "digitv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "mt352.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "nxt6000.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* debug */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) static int dvb_usb_digitv_debug;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) module_param_named(debug,dvb_usb_digitv_debug, int, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define deb_rc(args...) dprintk(dvb_usb_digitv_debug,0x01,args)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static int digitv_ctrl_msg(struct dvb_usb_device *d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct digitv_state *st = d->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int ret, wo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) wo = (rbuf == NULL || rlen == 0); /* write-only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) if (wlen > 4 || rlen > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) memset(st->sndbuf, 0, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) memset(st->rcvbuf, 0, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) st->sndbuf[0] = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) st->sndbuf[1] = vv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) st->sndbuf[2] = wo ? wlen : rlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (wo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) memcpy(&st->sndbuf[3], wbuf, wlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ret = dvb_usb_generic_write(d, st->sndbuf, 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ret = dvb_usb_generic_rw(d, st->sndbuf, 7, st->rcvbuf, 7, 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) memcpy(rbuf, &st->rcvbuf[3], rlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* I2C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct dvb_usb_device *d = i2c_get_adapdata(adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (num > 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) warn("more than 2 i2c messages at a time is not handled yet. TODO.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /* write/read request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) msg[i+1].buf,msg[i+1].len) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (digitv_ctrl_msg(d,USB_WRITE_COFDM, msg[i].buf[0],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) &msg[i].buf[1],msg[i].len-1,NULL,0) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) mutex_unlock(&d->i2c_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) static u32 digitv_i2c_func(struct i2c_adapter *adapter)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return I2C_FUNC_I2C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static struct i2c_algorithm digitv_i2c_algo = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) .master_xfer = digitv_i2c_xfer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) .functionality = digitv_i2c_func,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* Callbacks for DVB USB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) static int digitv_identify_state(struct usb_device *udev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) const struct dvb_usb_device_properties *props,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) const struct dvb_usb_device_description **desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) int *cold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static int digitv_mt352_demod_init(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static u8 reset_buf[] = { 0x89, 0x38, 0x8a, 0x2d, 0x50, 0x80 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static u8 init_buf[] = { 0x68, 0xa0, 0x8e, 0x40, 0x53, 0x50,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 0x67, 0x20, 0x7d, 0x01, 0x7c, 0x00, 0x7a, 0x00,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 0x79, 0x20, 0x57, 0x05, 0x56, 0x31, 0x88, 0x0f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 0x75, 0x32 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) for (i = 0; i < ARRAY_SIZE(reset_buf); i += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) mt352_write(fe, &reset_buf[i], 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) msleep(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) for (i = 0; i < ARRAY_SIZE(init_buf); i += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) mt352_write(fe, &init_buf[i], 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) static struct mt352_config digitv_mt352_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .demod_init = digitv_mt352_demod_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) struct dvb_usb_adapter *adap = fe->dvb->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) u8 b[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) fe->ops.tuner_ops.calc_regs(fe, b, sizeof(b));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) if (fe->ops.i2c_gate_ctrl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) fe->ops.i2c_gate_ctrl(fe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return digitv_ctrl_msg(adap->dev, USB_WRITE_TUNER, 0, &b[1], 4, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static struct nxt6000_config digitv_nxt6000_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .clock_inversion = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) static int digitv_frontend_attach(struct dvb_usb_adapter *adap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct digitv_state *st = adap->dev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) adap->fe_adap[0].fe = dvb_attach(mt352_attach, &digitv_mt352_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) &adap->dev->i2c_adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if ((adap->fe_adap[0].fe) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) st->is_nxt6000 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) adap->fe_adap[0].fe = dvb_attach(nxt6000_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) &digitv_nxt6000_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) &adap->dev->i2c_adap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if ((adap->fe_adap[0].fe) != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) st->is_nxt6000 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) static int digitv_tuner_attach(struct dvb_usb_adapter *adap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct digitv_state *st = adap->dev->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (!dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, NULL, DVB_PLL_TDED4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (st->is_nxt6000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) adap->fe_adap[0].fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static struct rc_map_table rc_map_digitv_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) { 0x5f55, KEY_0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) { 0x6f55, KEY_1 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) { 0x9f55, KEY_2 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) { 0xaf55, KEY_3 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) { 0x5f56, KEY_4 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) { 0x6f56, KEY_5 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) { 0x9f56, KEY_6 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) { 0xaf56, KEY_7 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) { 0x5f59, KEY_8 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) { 0x6f59, KEY_9 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) { 0x9f59, KEY_TV },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) { 0xaf59, KEY_AUX },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) { 0x5f5a, KEY_DVD },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) { 0x6f5a, KEY_POWER },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) { 0x9f5a, KEY_CAMERA }, /* labelled 'Picture' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) { 0xaf5a, KEY_AUDIO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) { 0x5f65, KEY_INFO },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) { 0x6f65, KEY_F13 }, /* 16:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) { 0x9f65, KEY_F14 }, /* 14:9 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) { 0xaf65, KEY_EPG },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) { 0x5f66, KEY_EXIT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) { 0x6f66, KEY_MENU },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) { 0x9f66, KEY_UP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) { 0xaf66, KEY_DOWN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) { 0x5f69, KEY_LEFT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) { 0x6f69, KEY_RIGHT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) { 0x9f69, KEY_ENTER },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) { 0xaf69, KEY_CHANNELUP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) { 0x5f6a, KEY_CHANNELDOWN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) { 0x6f6a, KEY_VOLUMEUP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) { 0x9f6a, KEY_VOLUMEDOWN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) { 0xaf6a, KEY_RED },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) { 0x5f95, KEY_GREEN },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) { 0x6f95, KEY_YELLOW },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) { 0x9f95, KEY_BLUE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) { 0xaf95, KEY_SUBTITLE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) { 0x5f96, KEY_F15 }, /* AD */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) { 0x6f96, KEY_TEXT },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) { 0x9f96, KEY_MUTE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) { 0xaf96, KEY_REWIND },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) { 0x5f99, KEY_STOP },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) { 0x6f99, KEY_PLAY },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) { 0x9f99, KEY_FASTFORWARD },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) { 0xaf99, KEY_F16 }, /* chapter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) { 0x5f9a, KEY_PAUSE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) { 0x6f9a, KEY_PLAY },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) { 0x9f9a, KEY_RECORD },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) { 0xaf9a, KEY_F17 }, /* picture in picture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) { 0x5fa5, KEY_KPPLUS }, /* zoom in */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) { 0x6fa5, KEY_KPMINUS }, /* zoom out */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) { 0x9fa5, KEY_F18 }, /* capture */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) { 0xafa5, KEY_F19 }, /* web */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) { 0x5fa6, KEY_EMAIL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) { 0x6fa6, KEY_PHONE },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) { 0x9fa6, KEY_PC },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) static int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) struct rc_map_table *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) u8 key[4];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) u8 b[4] = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) *event = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) *state = REMOTE_NO_KEY_PRESSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ret = digitv_ctrl_msg(d, USB_READ_REMOTE, 0, NULL, 0, key, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /* Tell the device we've read the remote. Not sure how necessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) this is, but the Nebula SDK does it. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) ret = digitv_ctrl_msg(d, USB_WRITE_REMOTE, 0, b, 4, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* if something is inside the buffer, simulate key press */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (key[0] != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) entry = &d->props.rc.legacy.rc_map_table[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if (rc5_custom(entry) == key[0] &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) rc5_data(entry) == key[1]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) *event = entry->keycode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) *state = REMOTE_KEY_PRESSED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) deb_rc("key: %*ph\n", 4, key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /* DVB USB Driver stuff */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static struct dvb_usb_device_properties digitv_properties;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) static int digitv_probe(struct usb_interface *intf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) const struct usb_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct dvb_usb_device *d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int ret = dvb_usb_device_init(intf, &digitv_properties, THIS_MODULE, &d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) adapter_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) u8 b[4] = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) if (d != NULL) { /* do that only when the firmware is loaded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) b[0] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) b[0] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) static struct usb_device_id digitv_table [] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) { USB_DEVICE(USB_VID_ANCHOR, USB_PID_NEBULA_DIGITV) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) { } /* Terminating entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) MODULE_DEVICE_TABLE (usb, digitv_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static struct dvb_usb_device_properties digitv_properties = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .caps = DVB_USB_IS_AN_I2C_ADAPTER,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .usb_ctrl = CYPRESS_FX2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) .firmware = "dvb-usb-digitv-02.fw",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) .size_of_priv = sizeof(struct digitv_state),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) .num_adapters = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) .adapter = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) .num_frontends = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) .fe = {{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) .frontend_attach = digitv_frontend_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) .tuner_attach = digitv_tuner_attach,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /* parameter for the MPEG2-data transfer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) .stream = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) .type = USB_BULK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) .count = 7,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) .endpoint = 0x02,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) .u = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) .bulk = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) .buffersize = 4096,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) .identify_state = digitv_identify_state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) .rc.legacy = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) .rc_interval = 1000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) .rc_map_table = rc_map_digitv_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) .rc_map_size = ARRAY_SIZE(rc_map_digitv_table),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) .rc_query = digitv_rc_query,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) .i2c_algo = &digitv_i2c_algo,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) .generic_bulk_ctrl_endpoint = 0x01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) .num_device_descs = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) .devices = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) { "Nebula Electronics uDigiTV DVB-T USB2.0)",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) { &digitv_table[0], NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) { NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) { NULL },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) static struct usb_driver digitv_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) .name = "dvb_usb_digitv",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) .probe = digitv_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) .disconnect = dvb_usb_device_exit,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) .id_table = digitv_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) module_usb_driver(digitv_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) MODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) MODULE_VERSION("1.0-alpha");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) MODULE_LICENSE("GPL");