Large diffs are not rendered by default.

@@ -0,0 +1,38 @@
/*
tda18273.h - header for the NXP TDA18273 silicon tuner
Copyright (C) 2014 CrazyCat <crazycat69@narod.ru>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef __TDA18273_H
#define __TDA18273_H

#if IS_ENABLED(CONFIG_MEDIA_TUNER_TDA18273)
extern struct dvb_frontend *tda18273_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
const u8 i2c_addr);

#else
static inline struct dvb_frontend *tda18273_attach(struct dvb_frontend *fe,
struct i2c_adapter *i2c,
const u8 i2c_addr)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
#endif

#endif /* __TDA18273_H */

Large diffs are not rendered by default.

@@ -1408,6 +1408,76 @@ static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap)
return 0;
}

static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *d = adap->dev;
struct cxusb_state *st = d->priv;
struct i2c_adapter *adapter;
struct i2c_client *client_demod;
struct i2c_client *client_tuner;
struct i2c_board_info info;
struct si2168_config si2168_config;
struct si2157_config si2157_config;

/* Select required USB configuration */
if (usb_set_interface(d->udev, 0, 0) < 0)
err("set interface failed");

/* Unblock all USB pipes */
usb_clear_halt(d->udev,
usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
usb_clear_halt(d->udev,
usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
usb_clear_halt(d->udev,
usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));

/* attach frontend */
si2168_config.i2c_adapter = &adapter;
si2168_config.fe = &adap->fe_adap[0].fe;
si2168_config.ts_mode = SI2168_TS_PARALLEL;
si2168_config.ts_clock_inv = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2168", I2C_NAME_SIZE);
info.addr = 0x64;
info.platform_data = &si2168_config;
request_module(info.type);
client_demod = i2c_new_device(&d->i2c_adap, &info);
if (client_demod == NULL || client_demod->dev.driver == NULL)
return -ENODEV;

if (!try_module_get(client_demod->dev.driver->owner)) {
i2c_unregister_device(client_demod);
return -ENODEV;
}

st->i2c_client_demod = client_demod;

/* attach tuner */
memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = adap->fe_adap[0].fe;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
info.addr = 0x60;
info.platform_data = &si2157_config;
request_module(info.type);
client_tuner = i2c_new_device(adapter, &info);
if (client_tuner == NULL || client_tuner->dev.driver == NULL) {
module_put(client_demod->dev.driver->owner);
i2c_unregister_device(client_demod);
return -ENODEV;
}
if (!try_module_get(client_tuner->dev.driver->owner)) {
i2c_unregister_device(client_tuner);
module_put(client_demod->dev.driver->owner);
i2c_unregister_device(client_demod);
return -ENODEV;
}

st->i2c_client_tuner = client_tuner;

return 0;
}

static int cxusb_tt_ct2_4400_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *d = adap->dev;
@@ -1610,6 +1680,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
static struct dvb_usb_device_properties cxusb_aver_a868r_properties;
static struct dvb_usb_device_properties cxusb_d680_dmb_properties;
static struct dvb_usb_device_properties cxusb_mygica_d689_properties;
static struct dvb_usb_device_properties cxusb_mygica_t230_properties;
static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties;

static int cxusb_probe(struct usb_interface *intf,
@@ -1641,6 +1712,8 @@ static int cxusb_probe(struct usb_interface *intf,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_mygica_t230_properties,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_tt_ct2_4400_properties,
THIS_MODULE, NULL, adapter_nr) ||
0)
@@ -1702,6 +1775,7 @@ static struct usb_device_id cxusb_table [] = {
{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) },
{ USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_TVSTICK_CT2_4400) },
{ USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI) },
{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230) },
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -2408,6 +2482,59 @@ static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties = {
}
};

static struct dvb_usb_device_properties cxusb_mygica_t230_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,

.usb_ctrl = CYPRESS_FX2,

.size_of_priv = sizeof(struct cxusb_state),

.num_adapters = 1,
.adapter = {
{
.num_frontends = 1,
.fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
.frontend_attach = cxusb_mygica_t230_frontend_attach,

/* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
.count = 5,
.endpoint = 0x02,
.u = {
.bulk = {
.buffersize = 8192,
}
}
},
} },
},
},

.power_ctrl = cxusb_d680_dmb_power_ctrl,

.i2c_algo = &cxusb_i2c_algo,

.generic_bulk_ctrl_endpoint = 0x01,

.rc.legacy = {
.rc_interval = 100,
.rc_map_table = rc_map_d680_dmb_table,
.rc_map_size = ARRAY_SIZE(rc_map_d680_dmb_table),
.rc_query = cxusb_d680_dmb_rc_query,
},

.num_device_descs = 1,
.devices = {
{
"Mygica T230 DVB-T/T2/C",
{ NULL },
{ &cxusb_table[22], NULL },
},
}
};

static struct usb_driver cxusb_driver = {
.name = "dvb_usb_cxusb",
.probe = cxusb_probe,
@@ -2,8 +2,9 @@
* DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
* TeVii S600, S630, S650, S660, S480, S421, S632
* Prof 1100, 7500,
* Geniatech SU3000, T220 Cards
* Geniatech SU3000, T220, T220A Cards
* Copyright (C) 2008-2012 Igor M. Liplianin (liplianin@me.by)
* (C) 2013-2014 CrazyCat (crazycat69@narod.ru)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -30,6 +31,7 @@
#include "stb6100_proc.h"
#include "m88rs2000.h"
#include "tda18271.h"
#include "tda18273.h"
#include "cxd2820r.h"

/* Max transfer size done by I2C transfer functions */
@@ -1436,6 +1438,56 @@ static int t220_frontend_attach(struct dvb_usb_adapter *d)
return -EIO;
}

static int t220a_frontend_attach(struct dvb_usb_adapter *d)
{
u8 obuf[3] = { 0xe, 0x87, 0 };
u8 ibuf[] = { 0 };

if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
err("command 0x0e transfer failed.");

obuf[0] = 0xe;
obuf[1] = 0x86;
obuf[2] = 1;

if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
err("command 0x0e transfer failed.");

obuf[0] = 0xe;
obuf[1] = 0x80;
obuf[2] = 0;

if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
err("command 0x0e transfer failed.");

msleep(50);

obuf[0] = 0xe;
obuf[1] = 0x80;
obuf[2] = 1;

if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
err("command 0x0e transfer failed.");

obuf[0] = 0x51;

if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
err("command 0x51 transfer failed.");

d->fe_adap[0].fe = dvb_attach(cxd2820r_attach, &cxd2820r_config,
&d->dev->i2c_adap, NULL);
if (d->fe_adap[0].fe != NULL) {
if (dvb_attach(tda18273_attach, d->fe_adap[0].fe,
&d->dev->i2c_adap, 0x60)) {
info("Attached TDA18273/CXD2820R!\n");
return 0;
}
}

info("Failed to attach TDA18273/CXD2820R!\n");
return -EIO;
}

static int m88rs2000_frontend_attach(struct dvb_usb_adapter *d)
{
u8 obuf[] = { 0x51 };
@@ -1561,6 +1613,7 @@ enum dw2102_table_entry {
TERRATEC_CINERGY_S2_R2,
GOTVIEW_SAT_HD,
GENIATECH_T220,
GENIATECH_T220A,
};

static struct usb_device_id dw2102_table[] = {
@@ -1584,6 +1637,7 @@ static struct usb_device_id dw2102_table[] = {
[TERRATEC_CINERGY_S2_R2] = {USB_DEVICE(USB_VID_TERRATEC, 0x00b0)},
[GOTVIEW_SAT_HD] = {USB_DEVICE(0x1FE1, USB_PID_GOTVIEW_SAT_HD)},
[GENIATECH_T220] = {USB_DEVICE(0x1f4d, 0xD220)},
[GENIATECH_T220A] = {USB_DEVICE(0x0572, 0xC686)},
{ }
};

@@ -2061,6 +2115,55 @@ static struct dvb_usb_device_properties t220_properties = {
}
};

static struct dvb_usb_device_properties t220a_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = DEVICE_SPECIFIC,
.size_of_priv = sizeof(struct su3000_state),
.power_ctrl = su3000_power_ctrl,
.num_adapters = 1,
.identify_state = su3000_identify_state,
.i2c_algo = &su3000_i2c_algo,

.rc.core = {
.rc_interval = 150,
.rc_codes = RC_MAP_SU3000,
.module_name = "dw2102",
.allowed_protos = RC_BIT_RC5,
.rc_query = su3000_rc_query,
},

.read_mac_address = su3000_read_mac_address,

.generic_bulk_ctrl_endpoint = 0x01,

.adapter = {
{
.num_frontends = 1,
.fe = { {
.streaming_ctrl = su3000_streaming_ctrl,
.frontend_attach = t220a_frontend_attach,
.stream = {
.type = USB_BULK,
.count = 8,
.endpoint = 0x82,
.u = {
.bulk = {
.buffersize = 4096,
}
}
}
} },
}
},
.num_device_descs = 1,
.devices = {
{ "Geniatech T220A DVB-T/T2 USB2.0",
{ &dw2102_table[GENIATECH_T220A], NULL },
{ NULL },
},
}
};

static int dw2102_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -2135,6 +2238,8 @@ static int dw2102_probe(struct usb_interface *intf,
0 == dvb_usb_device_init(intf, &su3000_properties,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &t220_properties,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &t220a_properties,
THIS_MODULE, NULL, adapter_nr))
return 0;

@@ -2155,7 +2260,7 @@ MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
" DVB-C 3101 USB2.0,"
" TeVii S600, S630, S650, S660, S480, S421, S632"
" Prof 1100, 7500 USB2.0,"
" Geniatech SU3000, T220 devices");
" Geniatech SU3000, T220, T220A devices");
MODULE_VERSION("0.1");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(DW2101_FIRMWARE);