162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/* DVB USB compliant linux driver for Nebula Electronics uDigiTV DVB-T USB2.0
362306a36Sopenharmony_ci * receiver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2005 Patrick Boettcher (patrick.boettcher@posteo.de)
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * partly based on the SDK published by Nebula Electronics
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci#include "digitv.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#include "mt352.h"
1462306a36Sopenharmony_ci#include "nxt6000.h"
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci/* debug */
1762306a36Sopenharmony_cistatic int dvb_usb_digitv_debug;
1862306a36Sopenharmony_cimodule_param_named(debug,dvb_usb_digitv_debug, int, 0644);
1962306a36Sopenharmony_ciMODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))." DVB_USB_DEBUG_STATUS);
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ciDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define deb_rc(args...)   dprintk(dvb_usb_digitv_debug,0x01,args)
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic int digitv_ctrl_msg(struct dvb_usb_device *d,
2662306a36Sopenharmony_ci		u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
2762306a36Sopenharmony_ci{
2862306a36Sopenharmony_ci	struct digitv_state *st = d->priv;
2962306a36Sopenharmony_ci	int ret, wo;
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	wo = (rbuf == NULL || rlen == 0); /* write-only */
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	if (wlen > 4 || rlen > 4)
3462306a36Sopenharmony_ci		return -EIO;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	memset(st->sndbuf, 0, 7);
3762306a36Sopenharmony_ci	memset(st->rcvbuf, 0, 7);
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	st->sndbuf[0] = cmd;
4062306a36Sopenharmony_ci	st->sndbuf[1] = vv;
4162306a36Sopenharmony_ci	st->sndbuf[2] = wo ? wlen : rlen;
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci	if (wo) {
4462306a36Sopenharmony_ci		memcpy(&st->sndbuf[3], wbuf, wlen);
4562306a36Sopenharmony_ci		ret = dvb_usb_generic_write(d, st->sndbuf, 7);
4662306a36Sopenharmony_ci	} else {
4762306a36Sopenharmony_ci		ret = dvb_usb_generic_rw(d, st->sndbuf, 7, st->rcvbuf, 7, 10);
4862306a36Sopenharmony_ci		memcpy(rbuf, &st->rcvbuf[3], rlen);
4962306a36Sopenharmony_ci	}
5062306a36Sopenharmony_ci	return ret;
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci/* I2C */
5462306a36Sopenharmony_cistatic int digitv_i2c_xfer(struct i2c_adapter *adap,struct i2c_msg msg[],int num)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	struct dvb_usb_device *d = i2c_get_adapdata(adap);
5762306a36Sopenharmony_ci	int i;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
6062306a36Sopenharmony_ci		return -EAGAIN;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	if (num > 2)
6362306a36Sopenharmony_ci		warn("more than 2 i2c messages at a time is not handled yet. TODO.");
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci	for (i = 0; i < num; i++) {
6662306a36Sopenharmony_ci		if (msg[i].len < 1) {
6762306a36Sopenharmony_ci			i = -EOPNOTSUPP;
6862306a36Sopenharmony_ci			break;
6962306a36Sopenharmony_ci		}
7062306a36Sopenharmony_ci		/* write/read request */
7162306a36Sopenharmony_ci		if (i+1 < num && (msg[i+1].flags & I2C_M_RD)) {
7262306a36Sopenharmony_ci			if (digitv_ctrl_msg(d, USB_READ_COFDM, msg[i].buf[0], NULL, 0,
7362306a36Sopenharmony_ci						msg[i+1].buf,msg[i+1].len) < 0)
7462306a36Sopenharmony_ci				break;
7562306a36Sopenharmony_ci			i++;
7662306a36Sopenharmony_ci		} else
7762306a36Sopenharmony_ci			if (digitv_ctrl_msg(d,USB_WRITE_COFDM, msg[i].buf[0],
7862306a36Sopenharmony_ci						&msg[i].buf[1],msg[i].len-1,NULL,0) < 0)
7962306a36Sopenharmony_ci				break;
8062306a36Sopenharmony_ci	}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	mutex_unlock(&d->i2c_mutex);
8362306a36Sopenharmony_ci	return i;
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic u32 digitv_i2c_func(struct i2c_adapter *adapter)
8762306a36Sopenharmony_ci{
8862306a36Sopenharmony_ci	return I2C_FUNC_I2C;
8962306a36Sopenharmony_ci}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_cistatic struct i2c_algorithm digitv_i2c_algo = {
9262306a36Sopenharmony_ci	.master_xfer   = digitv_i2c_xfer,
9362306a36Sopenharmony_ci	.functionality = digitv_i2c_func,
9462306a36Sopenharmony_ci};
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/* Callbacks for DVB USB */
9762306a36Sopenharmony_cistatic int digitv_identify_state(struct usb_device *udev,
9862306a36Sopenharmony_ci				 const struct dvb_usb_device_properties *props,
9962306a36Sopenharmony_ci				 const struct dvb_usb_device_description **desc,
10062306a36Sopenharmony_ci				 int *cold)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	*cold = udev->descriptor.iManufacturer == 0 && udev->descriptor.iProduct == 0;
10362306a36Sopenharmony_ci	return 0;
10462306a36Sopenharmony_ci}
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_cistatic int digitv_mt352_demod_init(struct dvb_frontend *fe)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	static u8 reset_buf[] = { 0x89, 0x38,  0x8a, 0x2d, 0x50, 0x80 };
10962306a36Sopenharmony_ci	static u8 init_buf[] = { 0x68, 0xa0,  0x8e, 0x40,  0x53, 0x50,
11062306a36Sopenharmony_ci			0x67, 0x20,  0x7d, 0x01,  0x7c, 0x00,  0x7a, 0x00,
11162306a36Sopenharmony_ci			0x79, 0x20,  0x57, 0x05,  0x56, 0x31,  0x88, 0x0f,
11262306a36Sopenharmony_ci			0x75, 0x32 };
11362306a36Sopenharmony_ci	int i;
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(reset_buf); i += 2)
11662306a36Sopenharmony_ci		mt352_write(fe, &reset_buf[i], 2);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	msleep(1);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(init_buf); i += 2)
12162306a36Sopenharmony_ci		mt352_write(fe, &init_buf[i], 2);
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	return 0;
12462306a36Sopenharmony_ci}
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistatic struct mt352_config digitv_mt352_config = {
12762306a36Sopenharmony_ci	.demod_init = digitv_mt352_demod_init,
12862306a36Sopenharmony_ci};
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic int digitv_nxt6000_tuner_set_params(struct dvb_frontend *fe)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	struct dvb_usb_adapter *adap = fe->dvb->priv;
13362306a36Sopenharmony_ci	u8 b[5];
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci	fe->ops.tuner_ops.calc_regs(fe, b, sizeof(b));
13662306a36Sopenharmony_ci	if (fe->ops.i2c_gate_ctrl)
13762306a36Sopenharmony_ci		fe->ops.i2c_gate_ctrl(fe, 1);
13862306a36Sopenharmony_ci	return digitv_ctrl_msg(adap->dev, USB_WRITE_TUNER, 0, &b[1], 4, NULL, 0);
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic struct nxt6000_config digitv_nxt6000_config = {
14262306a36Sopenharmony_ci	.clock_inversion = 1,
14362306a36Sopenharmony_ci};
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_cistatic int digitv_frontend_attach(struct dvb_usb_adapter *adap)
14662306a36Sopenharmony_ci{
14762306a36Sopenharmony_ci	struct digitv_state *st = adap->dev->priv;
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(mt352_attach, &digitv_mt352_config,
15062306a36Sopenharmony_ci					 &adap->dev->i2c_adap);
15162306a36Sopenharmony_ci	if ((adap->fe_adap[0].fe) != NULL) {
15262306a36Sopenharmony_ci		st->is_nxt6000 = 0;
15362306a36Sopenharmony_ci		return 0;
15462306a36Sopenharmony_ci	}
15562306a36Sopenharmony_ci	adap->fe_adap[0].fe = dvb_attach(nxt6000_attach,
15662306a36Sopenharmony_ci					 &digitv_nxt6000_config,
15762306a36Sopenharmony_ci					 &adap->dev->i2c_adap);
15862306a36Sopenharmony_ci	if ((adap->fe_adap[0].fe) != NULL) {
15962306a36Sopenharmony_ci		st->is_nxt6000 = 1;
16062306a36Sopenharmony_ci		return 0;
16162306a36Sopenharmony_ci	}
16262306a36Sopenharmony_ci	return -EIO;
16362306a36Sopenharmony_ci}
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_cistatic int digitv_tuner_attach(struct dvb_usb_adapter *adap)
16662306a36Sopenharmony_ci{
16762306a36Sopenharmony_ci	struct digitv_state *st = adap->dev->priv;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	if (!dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x60, NULL, DVB_PLL_TDED4))
17062306a36Sopenharmony_ci		return -ENODEV;
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci	if (st->is_nxt6000)
17362306a36Sopenharmony_ci		adap->fe_adap[0].fe->ops.tuner_ops.set_params = digitv_nxt6000_tuner_set_params;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	return 0;
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cistatic struct rc_map_table rc_map_digitv_table[] = {
17962306a36Sopenharmony_ci	{ 0x5f55, KEY_0 },
18062306a36Sopenharmony_ci	{ 0x6f55, KEY_1 },
18162306a36Sopenharmony_ci	{ 0x9f55, KEY_2 },
18262306a36Sopenharmony_ci	{ 0xaf55, KEY_3 },
18362306a36Sopenharmony_ci	{ 0x5f56, KEY_4 },
18462306a36Sopenharmony_ci	{ 0x6f56, KEY_5 },
18562306a36Sopenharmony_ci	{ 0x9f56, KEY_6 },
18662306a36Sopenharmony_ci	{ 0xaf56, KEY_7 },
18762306a36Sopenharmony_ci	{ 0x5f59, KEY_8 },
18862306a36Sopenharmony_ci	{ 0x6f59, KEY_9 },
18962306a36Sopenharmony_ci	{ 0x9f59, KEY_TV },
19062306a36Sopenharmony_ci	{ 0xaf59, KEY_AUX },
19162306a36Sopenharmony_ci	{ 0x5f5a, KEY_DVD },
19262306a36Sopenharmony_ci	{ 0x6f5a, KEY_POWER },
19362306a36Sopenharmony_ci	{ 0x9f5a, KEY_CAMERA },     /* labelled 'Picture' */
19462306a36Sopenharmony_ci	{ 0xaf5a, KEY_AUDIO },
19562306a36Sopenharmony_ci	{ 0x5f65, KEY_INFO },
19662306a36Sopenharmony_ci	{ 0x6f65, KEY_F13 },     /* 16:9 */
19762306a36Sopenharmony_ci	{ 0x9f65, KEY_F14 },     /* 14:9 */
19862306a36Sopenharmony_ci	{ 0xaf65, KEY_EPG },
19962306a36Sopenharmony_ci	{ 0x5f66, KEY_EXIT },
20062306a36Sopenharmony_ci	{ 0x6f66, KEY_MENU },
20162306a36Sopenharmony_ci	{ 0x9f66, KEY_UP },
20262306a36Sopenharmony_ci	{ 0xaf66, KEY_DOWN },
20362306a36Sopenharmony_ci	{ 0x5f69, KEY_LEFT },
20462306a36Sopenharmony_ci	{ 0x6f69, KEY_RIGHT },
20562306a36Sopenharmony_ci	{ 0x9f69, KEY_ENTER },
20662306a36Sopenharmony_ci	{ 0xaf69, KEY_CHANNELUP },
20762306a36Sopenharmony_ci	{ 0x5f6a, KEY_CHANNELDOWN },
20862306a36Sopenharmony_ci	{ 0x6f6a, KEY_VOLUMEUP },
20962306a36Sopenharmony_ci	{ 0x9f6a, KEY_VOLUMEDOWN },
21062306a36Sopenharmony_ci	{ 0xaf6a, KEY_RED },
21162306a36Sopenharmony_ci	{ 0x5f95, KEY_GREEN },
21262306a36Sopenharmony_ci	{ 0x6f95, KEY_YELLOW },
21362306a36Sopenharmony_ci	{ 0x9f95, KEY_BLUE },
21462306a36Sopenharmony_ci	{ 0xaf95, KEY_SUBTITLE },
21562306a36Sopenharmony_ci	{ 0x5f96, KEY_F15 },     /* AD */
21662306a36Sopenharmony_ci	{ 0x6f96, KEY_TEXT },
21762306a36Sopenharmony_ci	{ 0x9f96, KEY_MUTE },
21862306a36Sopenharmony_ci	{ 0xaf96, KEY_REWIND },
21962306a36Sopenharmony_ci	{ 0x5f99, KEY_STOP },
22062306a36Sopenharmony_ci	{ 0x6f99, KEY_PLAY },
22162306a36Sopenharmony_ci	{ 0x9f99, KEY_FASTFORWARD },
22262306a36Sopenharmony_ci	{ 0xaf99, KEY_F16 },     /* chapter */
22362306a36Sopenharmony_ci	{ 0x5f9a, KEY_PAUSE },
22462306a36Sopenharmony_ci	{ 0x6f9a, KEY_PLAY },
22562306a36Sopenharmony_ci	{ 0x9f9a, KEY_RECORD },
22662306a36Sopenharmony_ci	{ 0xaf9a, KEY_F17 },     /* picture in picture */
22762306a36Sopenharmony_ci	{ 0x5fa5, KEY_KPPLUS },  /* zoom in */
22862306a36Sopenharmony_ci	{ 0x6fa5, KEY_KPMINUS }, /* zoom out */
22962306a36Sopenharmony_ci	{ 0x9fa5, KEY_F18 },     /* capture */
23062306a36Sopenharmony_ci	{ 0xafa5, KEY_F19 },     /* web */
23162306a36Sopenharmony_ci	{ 0x5fa6, KEY_EMAIL },
23262306a36Sopenharmony_ci	{ 0x6fa6, KEY_PHONE },
23362306a36Sopenharmony_ci	{ 0x9fa6, KEY_PC },
23462306a36Sopenharmony_ci};
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_cistatic int digitv_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
23762306a36Sopenharmony_ci{
23862306a36Sopenharmony_ci	struct rc_map_table *entry;
23962306a36Sopenharmony_ci	int ret, i;
24062306a36Sopenharmony_ci	u8 key[4];
24162306a36Sopenharmony_ci	u8 b[4] = { 0 };
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	*event = 0;
24462306a36Sopenharmony_ci	*state = REMOTE_NO_KEY_PRESSED;
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	ret = digitv_ctrl_msg(d, USB_READ_REMOTE, 0, NULL, 0, key, 4);
24762306a36Sopenharmony_ci	if (ret)
24862306a36Sopenharmony_ci		return ret;
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	/* Tell the device we've read the remote. Not sure how necessary
25162306a36Sopenharmony_ci	   this is, but the Nebula SDK does it. */
25262306a36Sopenharmony_ci	ret = digitv_ctrl_msg(d, USB_WRITE_REMOTE, 0, b, 4, NULL, 0);
25362306a36Sopenharmony_ci	if (ret)
25462306a36Sopenharmony_ci		return ret;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	/* if something is inside the buffer, simulate key press */
25762306a36Sopenharmony_ci	if (key[0] != 0) {
25862306a36Sopenharmony_ci		for (i = 0; i < d->props.rc.legacy.rc_map_size; i++) {
25962306a36Sopenharmony_ci			entry = &d->props.rc.legacy.rc_map_table[i];
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci			if (rc5_custom(entry) == key[0] &&
26262306a36Sopenharmony_ci			    rc5_data(entry) == key[1]) {
26362306a36Sopenharmony_ci				*event = entry->keycode;
26462306a36Sopenharmony_ci				*state = REMOTE_KEY_PRESSED;
26562306a36Sopenharmony_ci				return 0;
26662306a36Sopenharmony_ci			}
26762306a36Sopenharmony_ci		}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci		deb_rc("key: %*ph\n", 4, key);
27062306a36Sopenharmony_ci	}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	return 0;
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci/* DVB USB Driver stuff */
27662306a36Sopenharmony_cistatic struct dvb_usb_device_properties digitv_properties;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_cistatic int digitv_probe(struct usb_interface *intf,
27962306a36Sopenharmony_ci		const struct usb_device_id *id)
28062306a36Sopenharmony_ci{
28162306a36Sopenharmony_ci	struct dvb_usb_device *d;
28262306a36Sopenharmony_ci	int ret = dvb_usb_device_init(intf, &digitv_properties, THIS_MODULE, &d,
28362306a36Sopenharmony_ci				      adapter_nr);
28462306a36Sopenharmony_ci	if (ret == 0) {
28562306a36Sopenharmony_ci		u8 b[4] = { 0 };
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci		if (d != NULL) { /* do that only when the firmware is loaded */
28862306a36Sopenharmony_ci			b[0] = 1;
28962306a36Sopenharmony_ci			digitv_ctrl_msg(d,USB_WRITE_REMOTE_TYPE,0,b,4,NULL,0);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci			b[0] = 0;
29262306a36Sopenharmony_ci			digitv_ctrl_msg(d,USB_WRITE_REMOTE,0,b,4,NULL,0);
29362306a36Sopenharmony_ci		}
29462306a36Sopenharmony_ci	}
29562306a36Sopenharmony_ci	return ret;
29662306a36Sopenharmony_ci}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_cienum {
29962306a36Sopenharmony_ci	ANCHOR_NEBULA_DIGITV,
30062306a36Sopenharmony_ci};
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_cistatic struct usb_device_id digitv_table[] = {
30362306a36Sopenharmony_ci	DVB_USB_DEV(ANCHOR, ANCHOR_NEBULA_DIGITV),
30462306a36Sopenharmony_ci	{ }
30562306a36Sopenharmony_ci};
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ciMODULE_DEVICE_TABLE (usb, digitv_table);
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_cistatic struct dvb_usb_device_properties digitv_properties = {
31062306a36Sopenharmony_ci	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	.usb_ctrl = CYPRESS_FX2,
31362306a36Sopenharmony_ci	.firmware = "dvb-usb-digitv-02.fw",
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	.size_of_priv = sizeof(struct digitv_state),
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	.num_adapters = 1,
31862306a36Sopenharmony_ci	.adapter = {
31962306a36Sopenharmony_ci		{
32062306a36Sopenharmony_ci		.num_frontends = 1,
32162306a36Sopenharmony_ci		.fe = {{
32262306a36Sopenharmony_ci			.frontend_attach  = digitv_frontend_attach,
32362306a36Sopenharmony_ci			.tuner_attach     = digitv_tuner_attach,
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci			/* parameter for the MPEG2-data transfer */
32662306a36Sopenharmony_ci			.stream = {
32762306a36Sopenharmony_ci				.type = USB_BULK,
32862306a36Sopenharmony_ci				.count = 7,
32962306a36Sopenharmony_ci				.endpoint = 0x02,
33062306a36Sopenharmony_ci				.u = {
33162306a36Sopenharmony_ci					.bulk = {
33262306a36Sopenharmony_ci						.buffersize = 4096,
33362306a36Sopenharmony_ci					}
33462306a36Sopenharmony_ci				}
33562306a36Sopenharmony_ci			},
33662306a36Sopenharmony_ci		}},
33762306a36Sopenharmony_ci		}
33862306a36Sopenharmony_ci	},
33962306a36Sopenharmony_ci	.identify_state   = digitv_identify_state,
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci	.rc.legacy = {
34262306a36Sopenharmony_ci		.rc_interval      = 1000,
34362306a36Sopenharmony_ci		.rc_map_table     = rc_map_digitv_table,
34462306a36Sopenharmony_ci		.rc_map_size      = ARRAY_SIZE(rc_map_digitv_table),
34562306a36Sopenharmony_ci		.rc_query         = digitv_rc_query,
34662306a36Sopenharmony_ci	},
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	.i2c_algo         = &digitv_i2c_algo,
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	.generic_bulk_ctrl_endpoint = 0x01,
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	.num_device_descs = 1,
35362306a36Sopenharmony_ci	.devices = {
35462306a36Sopenharmony_ci		{   "Nebula Electronics uDigiTV DVB-T USB2.0)",
35562306a36Sopenharmony_ci			{ &digitv_table[ANCHOR_NEBULA_DIGITV], NULL },
35662306a36Sopenharmony_ci			{ NULL },
35762306a36Sopenharmony_ci		},
35862306a36Sopenharmony_ci		{ NULL },
35962306a36Sopenharmony_ci	}
36062306a36Sopenharmony_ci};
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_cistatic struct usb_driver digitv_driver = {
36362306a36Sopenharmony_ci	.name		= "dvb_usb_digitv",
36462306a36Sopenharmony_ci	.probe		= digitv_probe,
36562306a36Sopenharmony_ci	.disconnect = dvb_usb_device_exit,
36662306a36Sopenharmony_ci	.id_table	= digitv_table,
36762306a36Sopenharmony_ci};
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_cimodule_usb_driver(digitv_driver);
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ciMODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
37262306a36Sopenharmony_ciMODULE_DESCRIPTION("Driver for Nebula Electronics uDigiTV DVB-T USB2.0");
37362306a36Sopenharmony_ciMODULE_VERSION("1.0-alpha");
37462306a36Sopenharmony_ciMODULE_LICENSE("GPL");
375