162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* DVB USB framework compliant Linux driver for the HanfTek UMT-010 USB2.0 362306a36Sopenharmony_ci * DVB-T receiver. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2004-5 Patrick Boettcher (patrick.boettcher@posteo.de) 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * see Documentation/driver-api/media/drivers/dvb-usb.rst for more information 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci#include "dibusb.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include "mt352.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ciDVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistatic int umt_mt352_demod_init(struct dvb_frontend *fe) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci static u8 mt352_clock_config[] = { 0x89, 0xb8, 0x2d }; 1862306a36Sopenharmony_ci static u8 mt352_reset[] = { 0x50, 0x80 }; 1962306a36Sopenharmony_ci static u8 mt352_mclk_ratio[] = { 0x8b, 0x00 }; 2062306a36Sopenharmony_ci static u8 mt352_adc_ctl_1_cfg[] = { 0x8E, 0x40 }; 2162306a36Sopenharmony_ci static u8 mt352_agc_cfg[] = { 0x67, 0x10, 0xa0 }; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci static u8 mt352_sec_agc_cfg1[] = { 0x6a, 0xff }; 2462306a36Sopenharmony_ci static u8 mt352_sec_agc_cfg2[] = { 0x6d, 0xff }; 2562306a36Sopenharmony_ci static u8 mt352_sec_agc_cfg3[] = { 0x70, 0x40 }; 2662306a36Sopenharmony_ci static u8 mt352_sec_agc_cfg4[] = { 0x7b, 0x03 }; 2762306a36Sopenharmony_ci static u8 mt352_sec_agc_cfg5[] = { 0x7d, 0x0f }; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci static u8 mt352_acq_ctl[] = { 0x53, 0x50 }; 3062306a36Sopenharmony_ci static u8 mt352_input_freq_1[] = { 0x56, 0x31, 0x06 }; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci mt352_write(fe, mt352_clock_config, sizeof(mt352_clock_config)); 3362306a36Sopenharmony_ci udelay(2000); 3462306a36Sopenharmony_ci mt352_write(fe, mt352_reset, sizeof(mt352_reset)); 3562306a36Sopenharmony_ci mt352_write(fe, mt352_mclk_ratio, sizeof(mt352_mclk_ratio)); 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci mt352_write(fe, mt352_adc_ctl_1_cfg, sizeof(mt352_adc_ctl_1_cfg)); 3862306a36Sopenharmony_ci mt352_write(fe, mt352_agc_cfg, sizeof(mt352_agc_cfg)); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci mt352_write(fe, mt352_sec_agc_cfg1, sizeof(mt352_sec_agc_cfg1)); 4162306a36Sopenharmony_ci mt352_write(fe, mt352_sec_agc_cfg2, sizeof(mt352_sec_agc_cfg2)); 4262306a36Sopenharmony_ci mt352_write(fe, mt352_sec_agc_cfg3, sizeof(mt352_sec_agc_cfg3)); 4362306a36Sopenharmony_ci mt352_write(fe, mt352_sec_agc_cfg4, sizeof(mt352_sec_agc_cfg4)); 4462306a36Sopenharmony_ci mt352_write(fe, mt352_sec_agc_cfg5, sizeof(mt352_sec_agc_cfg5)); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci mt352_write(fe, mt352_acq_ctl, sizeof(mt352_acq_ctl)); 4762306a36Sopenharmony_ci mt352_write(fe, mt352_input_freq_1, sizeof(mt352_input_freq_1)); 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci return 0; 5062306a36Sopenharmony_ci} 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_cistatic int umt_mt352_frontend_attach(struct dvb_usb_adapter *adap) 5362306a36Sopenharmony_ci{ 5462306a36Sopenharmony_ci struct mt352_config umt_config; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci memset(&umt_config,0,sizeof(struct mt352_config)); 5762306a36Sopenharmony_ci umt_config.demod_init = umt_mt352_demod_init; 5862306a36Sopenharmony_ci umt_config.demod_address = 0xf; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci adap->fe_adap[0].fe = dvb_attach(mt352_attach, &umt_config, &adap->dev->i2c_adap); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci return 0; 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic int umt_tuner_attach (struct dvb_usb_adapter *adap) 6662306a36Sopenharmony_ci{ 6762306a36Sopenharmony_ci dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0x61, NULL, DVB_PLL_TUA6034); 6862306a36Sopenharmony_ci return 0; 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci/* USB Driver stuff */ 7262306a36Sopenharmony_cistatic struct dvb_usb_device_properties umt_properties; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic int umt_probe(struct usb_interface *intf, 7562306a36Sopenharmony_ci const struct usb_device_id *id) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci if (0 == dvb_usb_device_init(intf, &umt_properties, 7862306a36Sopenharmony_ci THIS_MODULE, NULL, adapter_nr)) 7962306a36Sopenharmony_ci return 0; 8062306a36Sopenharmony_ci return -EINVAL; 8162306a36Sopenharmony_ci} 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci/* do not change the order of the ID table */ 8462306a36Sopenharmony_cienum { 8562306a36Sopenharmony_ci HANFTEK_UMT_010_COLD, 8662306a36Sopenharmony_ci HANFTEK_UMT_010_WARM, 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic struct usb_device_id umt_table[] = { 9062306a36Sopenharmony_ci DVB_USB_DEV(HANFTEK, HANFTEK_UMT_010_COLD), 9162306a36Sopenharmony_ci DVB_USB_DEV(HANFTEK, HANFTEK_UMT_010_WARM), 9262306a36Sopenharmony_ci { } 9362306a36Sopenharmony_ci}; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ciMODULE_DEVICE_TABLE (usb, umt_table); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_cistatic struct dvb_usb_device_properties umt_properties = { 9862306a36Sopenharmony_ci .caps = DVB_USB_IS_AN_I2C_ADAPTER, 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci .usb_ctrl = CYPRESS_FX2, 10162306a36Sopenharmony_ci .firmware = "dvb-usb-umt-010-02.fw", 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci .num_adapters = 1, 10462306a36Sopenharmony_ci .adapter = { 10562306a36Sopenharmony_ci { 10662306a36Sopenharmony_ci .num_frontends = 1, 10762306a36Sopenharmony_ci .fe = {{ 10862306a36Sopenharmony_ci .streaming_ctrl = dibusb2_0_streaming_ctrl, 10962306a36Sopenharmony_ci .frontend_attach = umt_mt352_frontend_attach, 11062306a36Sopenharmony_ci .tuner_attach = umt_tuner_attach, 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci /* parameter for the MPEG2-data transfer */ 11362306a36Sopenharmony_ci .stream = { 11462306a36Sopenharmony_ci .type = USB_BULK, 11562306a36Sopenharmony_ci .count = MAX_NO_URBS_FOR_DATA_STREAM, 11662306a36Sopenharmony_ci .endpoint = 0x06, 11762306a36Sopenharmony_ci .u = { 11862306a36Sopenharmony_ci .bulk = { 11962306a36Sopenharmony_ci .buffersize = 512, 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci }, 12362306a36Sopenharmony_ci }}, 12462306a36Sopenharmony_ci .size_of_priv = sizeof(struct dibusb_state), 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci }, 12762306a36Sopenharmony_ci .power_ctrl = dibusb_power_ctrl, 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci .i2c_algo = &dibusb_i2c_algo, 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci .generic_bulk_ctrl_endpoint = 0x01, 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci .num_device_descs = 1, 13462306a36Sopenharmony_ci .devices = { 13562306a36Sopenharmony_ci { "Hanftek UMT-010 DVB-T USB2.0", 13662306a36Sopenharmony_ci { &umt_table[HANFTEK_UMT_010_COLD], NULL }, 13762306a36Sopenharmony_ci { &umt_table[HANFTEK_UMT_010_WARM], NULL }, 13862306a36Sopenharmony_ci }, 13962306a36Sopenharmony_ci } 14062306a36Sopenharmony_ci}; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic struct usb_driver umt_driver = { 14362306a36Sopenharmony_ci .name = "dvb_usb_umt_010", 14462306a36Sopenharmony_ci .probe = umt_probe, 14562306a36Sopenharmony_ci .disconnect = dvb_usb_device_exit, 14662306a36Sopenharmony_ci .id_table = umt_table, 14762306a36Sopenharmony_ci}; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cimodule_usb_driver(umt_driver); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ciMODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>"); 15262306a36Sopenharmony_ciMODULE_DESCRIPTION("Driver for HanfTek UMT 010 USB2.0 DVB-T device"); 15362306a36Sopenharmony_ciMODULE_VERSION("1.0"); 15462306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 155