1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* DVB USB framework compliant Linux driver for the HanfTek UMT-010 USB2.0 |
3 | * DVB-T receiver. |
4 | * |
5 | * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) |
6 | * |
7 | * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information |
8 | */ |
9 | #include "dibusb.h" |
10 | |
11 | #include "mt352.h" |
12 | |
13 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); |
14 | |
15 | static int umt_mt352_demod_init(struct dvb_frontend *fe) |
16 | { |
17 | static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d }; |
18 | static u8 mt352_reset[] = { 0x50, 0x80 }; |
19 | static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 }; |
20 | static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 }; |
21 | static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 }; |
22 | |
23 | static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff }; |
24 | static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff }; |
25 | static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 }; |
26 | static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 }; |
27 | static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f }; |
28 | |
29 | static u8 mt352_acq_ctl[] = { 0x53, 0x50 }; |
30 | static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 }; |
31 | |
32 | mt352_write(fe, buf: mt352_clock_config, len: sizeof(mt352_clock_config)); |
33 | udelay(2000); |
34 | mt352_write(fe, buf: mt352_reset, len: sizeof(mt352_reset)); |
35 | mt352_write(fe, buf: mt352_mclk_ratio, len: sizeof(mt352_mclk_ratio)); |
36 | |
37 | mt352_write(fe, buf: mt352_adc_ctl_1_cfg, len: sizeof(mt352_adc_ctl_1_cfg)); |
38 | mt352_write(fe, buf: mt352_agc_cfg, len: sizeof(mt352_agc_cfg)); |
39 | |
40 | mt352_write(fe, buf: mt352_sec_agc_cfg1, len: sizeof(mt352_sec_agc_cfg1)); |
41 | mt352_write(fe, buf: mt352_sec_agc_cfg2, len: sizeof(mt352_sec_agc_cfg2)); |
42 | mt352_write(fe, buf: mt352_sec_agc_cfg3, len: sizeof(mt352_sec_agc_cfg3)); |
43 | mt352_write(fe, buf: mt352_sec_agc_cfg4, len: sizeof(mt352_sec_agc_cfg4)); |
44 | mt352_write(fe, buf: mt352_sec_agc_cfg5, len: sizeof(mt352_sec_agc_cfg5)); |
45 | |
46 | mt352_write(fe, buf: mt352_acq_ctl, len: sizeof(mt352_acq_ctl)); |
47 | mt352_write(fe, buf: mt352_input_freq_1, len: sizeof(mt352_input_freq_1)); |
48 | |
49 | return 0; |
50 | } |
51 | |
52 | static int umt_mt352_frontend_attach(struct dvb_usb_adapter *adap) |
53 | { |
54 | struct mt352_config umt_config; |
55 | |
56 | memset(&umt_config,0,sizeof(struct mt352_config)); |
57 | umt_config.demod_init = umt_mt352_demod_init; |
58 | umt_config.demod_address = 0xf; |
59 | |
60 | adap->fe_adap[0].fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap); |
61 | |
62 | return 0; |
63 | } |
64 | |
65 | static int umt_tuner_attach (struct dvb_usb_adapter *adap) |
66 | { |
67 | dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, NULL, DVB_PLL_TUA6034); |
68 | return 0; |
69 | } |
70 | |
71 | /* USB Driver stuff */ |
72 | static struct dvb_usb_device_properties umt_properties; |
73 | |
74 | static int umt_probe(struct usb_interface *intf, |
75 | const struct usb_device_id *id) |
76 | { |
77 | if (0 == dvb_usb_device_init(intf, &umt_properties, |
78 | THIS_MODULE, NULL, adapter_nums: adapter_nr)) |
79 | return 0; |
80 | return -EINVAL; |
81 | } |
82 | |
83 | /* do not change the order of the ID table */ |
84 | enum { |
85 | HANFTEK_UMT_010_COLD, |
86 | HANFTEK_UMT_010_WARM, |
87 | }; |
88 | |
89 | static struct usb_device_id umt_table[] = { |
90 | DVB_USB_DEV(HANFTEK, HANFTEK_UMT_010_COLD), |
91 | DVB_USB_DEV(HANFTEK, HANFTEK_UMT_010_WARM), |
92 | { } |
93 | }; |
94 | |
95 | MODULE_DEVICE_TABLE (usb, umt_table); |
96 | |
97 | static struct dvb_usb_device_properties umt_properties = { |
98 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, |
99 | |
100 | .usb_ctrl = CYPRESS_FX2, |
101 | .firmware = "dvb-usb-umt-010-02.fw" , |
102 | |
103 | .num_adapters = 1, |
104 | .adapter = { |
105 | { |
106 | .num_frontends = 1, |
107 | .fe = {{ |
108 | .streaming_ctrl = dibusb2_0_streaming_ctrl, |
109 | .frontend_attach = umt_mt352_frontend_attach, |
110 | .tuner_attach = umt_tuner_attach, |
111 | |
112 | /* parameter for the MPEG2-data transfer */ |
113 | .stream = { |
114 | .type = USB_BULK, |
115 | .count = MAX_NO_URBS_FOR_DATA_STREAM, |
116 | .endpoint = 0x06, |
117 | .u = { |
118 | .bulk = { |
119 | .buffersize = 512, |
120 | } |
121 | } |
122 | }, |
123 | }}, |
124 | .size_of_priv = sizeof(struct dibusb_state), |
125 | } |
126 | }, |
127 | .power_ctrl = dibusb_power_ctrl, |
128 | |
129 | .i2c_algo = &dibusb_i2c_algo, |
130 | |
131 | .generic_bulk_ctrl_endpoint = 0x01, |
132 | |
133 | .num_device_descs = 1, |
134 | .devices = { |
135 | { "Hanftek UMT-010 DVB-T USB2.0" , |
136 | { &umt_table[HANFTEK_UMT_010_COLD], NULL }, |
137 | { &umt_table[HANFTEK_UMT_010_WARM], NULL }, |
138 | }, |
139 | } |
140 | }; |
141 | |
142 | static struct usb_driver umt_driver = { |
143 | .name = "dvb_usb_umt_010" , |
144 | .probe = umt_probe, |
145 | .disconnect = dvb_usb_device_exit, |
146 | .id_table = umt_table, |
147 | }; |
148 | |
149 | module_usb_driver(umt_driver); |
150 | |
151 | MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>" ); |
152 | MODULE_DESCRIPTION("Driver for HanfTek UMT 010 USB2.0 DVB-T device" ); |
153 | MODULE_VERSION("1.0" ); |
154 | MODULE_LICENSE("GPL" ); |
155 | |