mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 04:33:26 +02:00
media: usb/dvb-usb: Replace strlcpy() with strscpy()
This commit is contained in:
@@ -259,7 +259,7 @@ static int tbsqboxs1_frontend_attach(struct dvb_usb_adapter *d)
|
||||
tbsqboxs1_op_rw(u->udev, 0x8a, 0, 0,
|
||||
buf, 2, TBSQBOX_WRITE_MSG);
|
||||
|
||||
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@@ -278,7 +278,7 @@ static int tbsqbox2_frontend_attach(struct dvb_usb_adapter *d)
|
||||
tbsqbox2_op_rw(u->udev, 0x8a, 0, 0,
|
||||
buf, 2, TBSQBOX_WRITE_MSG);
|
||||
|
||||
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@@ -224,7 +224,7 @@ static int tbsqbox22_frontend_attach(struct dvb_usb_adapter *d)
|
||||
buf[1] = 1;
|
||||
tbsqbox22_op_rw(u->udev, 0x8a, 0, 0, buf, 2, TBSQBOX_WRITE_MSG);
|
||||
|
||||
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
|
@@ -601,7 +601,7 @@ static int tbsqbox2ci_frontend_attach(struct dvb_usb_adapter *d)
|
||||
|
||||
tbsqbox2ci_init(d);
|
||||
|
||||
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@@ -272,7 +272,7 @@ static int tbsqboxs2_frontend_attach(struct dvb_usb_adapter *d)
|
||||
tbsqboxs2_op_rw(u->udev, 0x8a, 0, 0,
|
||||
buf, 2, TBSQBOX_WRITE_MSG);
|
||||
|
||||
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -188,7 +188,7 @@ static int tbs5220_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
si2168_config.ts_mode = SI2168_TS_PARALLEL;
|
||||
si2168_config.ts_clock_gapped = true;
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(info.type, "si2168", I2C_NAME_SIZE);
|
||||
strscpy(info.type, "si2168", I2C_NAME_SIZE);
|
||||
info.addr = 0x64;
|
||||
info.platform_data = &si2168_config;
|
||||
request_module(info.type);
|
||||
@@ -206,7 +206,7 @@ static int tbs5220_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
si2157_config.fe = adap->fe_adap[0].fe;
|
||||
si2157_config.if_port = 1;
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
|
||||
strscpy(info.type, "si2157", I2C_NAME_SIZE);
|
||||
info.addr = 0x60;
|
||||
info.platform_data = &si2157_config;
|
||||
request_module(info.type);
|
||||
@@ -245,7 +245,7 @@ static int tbs5220_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
tbs5220_op_rw(d->udev, 0x8a, 0, 0,
|
||||
buf, 2, TBS5220_WRITE_MSG);
|
||||
|
||||
strlcpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
|
||||
strscpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,319 +1,319 @@
|
||||
/*
|
||||
* TurboSight TBS 5230 driver
|
||||
*
|
||||
* Copyright (c) 2022/06 Davin zhang<Davin@tbsdtv.com>
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/version.h>
|
||||
#include "tbs5230.h"
|
||||
#include "cxd2878.h"
|
||||
|
||||
|
||||
#define TBS5230_READ_MSG 0
|
||||
#define TBS5230_WRITE_MSG 1
|
||||
|
||||
struct tbs5230_state {
|
||||
u8 initialized;
|
||||
};
|
||||
/* debug */
|
||||
static int dvb_usb_tbs5230_debug;
|
||||
module_param_named(debug, dvb_usb_tbs5230_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
|
||||
DVB_USB_DEBUG_STATUS);
|
||||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
static int tbs5230_op_rw(struct usb_device *dev, u8 request, u16 value,
|
||||
u16 index, u8 * data, u16 len, int flags)
|
||||
{
|
||||
int ret;
|
||||
void *u8buf;
|
||||
|
||||
unsigned int pipe = (flags == TBS5230_READ_MSG) ?
|
||||
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
|
||||
u8 request_type = (flags == TBS5230_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
|
||||
u8buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!u8buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (flags == TBS5230_WRITE_MSG)
|
||||
memcpy(u8buf, data, len);
|
||||
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
|
||||
value, index , u8buf, len, 2000);
|
||||
|
||||
if (flags == TBS5230_READ_MSG)
|
||||
memcpy(data, u8buf, len);
|
||||
kfree(u8buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* I2C */
|
||||
static int tbs5230_i2c_transfer(struct i2c_adapter *adap,
|
||||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
int i = 0;
|
||||
u8 buf6[35];
|
||||
u8 inbuf[35];
|
||||
|
||||
if (!d)
|
||||
return -ENODEV;
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
switch (num) {
|
||||
case 2:
|
||||
buf6[0]=msg[1].len;//lenth
|
||||
buf6[1]=msg[0].addr<<1;//demod addr
|
||||
//register
|
||||
buf6[2] = msg[0].buf[0];
|
||||
|
||||
tbs5230_op_rw(d->udev, 0x90, 0, 0,
|
||||
buf6, 3, TBS5230_WRITE_MSG);
|
||||
//msleep(5);
|
||||
tbs5230_op_rw(d->udev, 0x91, 0, 0,
|
||||
inbuf, buf6[0], TBS5230_READ_MSG);
|
||||
memcpy(msg[1].buf, inbuf, msg[1].len);
|
||||
|
||||
break;
|
||||
case 1:
|
||||
buf6[0] = msg[0].len+1;//lenth
|
||||
buf6[1] = msg[0].addr<<1;//addr
|
||||
for(i=0;i<msg[0].len;i++) {
|
||||
buf6[2+i] = msg[0].buf[i];//register
|
||||
}
|
||||
tbs5230_op_rw(d->udev, 0x80, 0, 0,
|
||||
buf6, msg[0].len+2, TBS5230_WRITE_MSG);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
return num;
|
||||
}
|
||||
|
||||
static u32 tbs5230_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm tbs5230_i2c_algo = {
|
||||
.master_xfer = tbs5230_i2c_transfer,
|
||||
.functionality = tbs5230_i2c_func,
|
||||
};
|
||||
|
||||
static int tbs5230_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
|
||||
{
|
||||
int i,ret;
|
||||
u8 ibuf[3] = {0, 0,0};
|
||||
u8 eeprom[256], eepromline[16];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
ibuf[0]=1;//lenth
|
||||
ibuf[1]=0xa0;//eeprom addr
|
||||
ibuf[2]=i;//register
|
||||
ret = tbs5230_op_rw(d->udev, 0x90, 0, 0,
|
||||
ibuf, 3, TBS5230_WRITE_MSG);
|
||||
ret = tbs5230_op_rw(d->udev, 0x91, 0, 0,
|
||||
ibuf, 1, TBS5230_READ_MSG);
|
||||
if (ret < 0) {
|
||||
err("read eeprom failed.");
|
||||
return -1;
|
||||
} else {
|
||||
eepromline[i%16] = ibuf[0];
|
||||
eeprom[i] = ibuf[0];
|
||||
}
|
||||
|
||||
if ((i % 16) == 15) {
|
||||
deb_xfer("%02x: ", i - 15);
|
||||
debug_dump(eepromline, 16, deb_xfer);
|
||||
}
|
||||
}
|
||||
memcpy(mac, eeprom + 16, 6);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties tbs5230_properties;
|
||||
|
||||
static struct cxd2878_config tbs5230_cfg = {
|
||||
|
||||
.addr_slvt = 0x64,
|
||||
.xtal = SONY_DEMOD_XTAL_24000KHz,
|
||||
.tuner_addr = 0x60,
|
||||
.tuner_xtal = SONY_ASCOT3_XTAL_24000KHz,
|
||||
.ts_mode = 1,
|
||||
.ts_ser_data = 0,
|
||||
.ts_clk = 1,
|
||||
.ts_clk_mask= 1,
|
||||
.ts_valid = 0,
|
||||
.atscCoreDisable = 0,
|
||||
.lock_flag = 1,
|
||||
.write_properties = NULL,
|
||||
.read_properties = NULL,
|
||||
};
|
||||
|
||||
static int tbs5230_frontend_attach(struct dvb_usb_adapter*adap)
|
||||
{
|
||||
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
|
||||
adap->fe_adap[0].fe = dvb_attach(cxd2878_attach, &tbs5230_cfg, &d->i2c_adap);
|
||||
|
||||
if(adap->fe_adap[0].fe!=NULL){
|
||||
strlcpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
|
||||
return 0;
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static struct usb_device_id tbs5230_table[] = {
|
||||
{USB_DEVICE(0x734c, 0x5230)},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, tbs5230_table);
|
||||
|
||||
static int tbs5230_load_firmware(struct usb_device *dev,
|
||||
const struct firmware *frmwr)
|
||||
{
|
||||
u8 *b, *p;
|
||||
int ret = 0, i;
|
||||
u8 reset;
|
||||
const struct firmware *fw;
|
||||
switch (dev->descriptor.idProduct) {
|
||||
case 0x5230:
|
||||
ret = request_firmware(&fw, tbs5230_properties.firmware, &dev->dev);
|
||||
if (ret != 0) {
|
||||
err("did not find the firmware file. (%s) "
|
||||
"Please see linux/Documentation/dvb/ for more details "
|
||||
"on firmware-problems.", tbs5230_properties.firmware);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fw = frmwr;
|
||||
break;
|
||||
}
|
||||
info("start downloading TBS5230 firmware");
|
||||
p = kmalloc(fw->size, GFP_KERNEL);
|
||||
reset = 1;
|
||||
/*stop the CPU*/
|
||||
tbs5230_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5230_WRITE_MSG);
|
||||
tbs5230_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5230_WRITE_MSG);
|
||||
|
||||
if (p != NULL) {
|
||||
memcpy(p, fw->data, fw->size);
|
||||
for (i = 0; i < fw->size; i += 0x40) {
|
||||
b = (u8 *) p + i;
|
||||
if (tbs5230_op_rw(dev, 0xa0, i, 0, b , 0x40,
|
||||
TBS5230_WRITE_MSG) != 0x40) {
|
||||
err("error while transferring firmware");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* restart the CPU */
|
||||
reset = 0;
|
||||
if (ret || tbs5230_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
|
||||
TBS5230_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (ret || tbs5230_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
|
||||
TBS5230_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
msleep(100);
|
||||
kfree(p);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct dvb_usb_device_properties tbs5230_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.firmware = "dvb-usb-id5230.fw",
|
||||
.size_of_priv = sizeof(struct tbs5230_state),
|
||||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &tbs5230_i2c_algo,
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
.num_adapters = 1,
|
||||
.download_firmware = tbs5230_load_firmware,
|
||||
.read_mac_address = tbs5230_read_mac_address,
|
||||
|
||||
.adapter = {{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = tbs5230_frontend_attach,
|
||||
.streaming_ctrl = NULL,
|
||||
.tuner_attach = NULL,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
}},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{"TurboSight TBS 5230 DVB-T2/T/C(j83-a/b/c),ISDB-T,ATSC1.0",
|
||||
{&tbs5230_table[0], NULL},
|
||||
{NULL},
|
||||
}
|
||||
}
|
||||
};
|
||||
static int tbs5230_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id*id)
|
||||
{
|
||||
if(0 == dvb_usb_device_init(intf,&tbs5230_properties,
|
||||
THIS_MODULE,NULL,adapter_nr)){
|
||||
return 0;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
static struct usb_driver tbs5230_driver ={
|
||||
.name = "tbs5230",
|
||||
.probe = tbs5230_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.id_table = tbs5230_table,
|
||||
|
||||
};
|
||||
static int __init tbs5230_module_init(void)
|
||||
{
|
||||
int ret = usb_register(&tbs5230_driver);
|
||||
if(ret)
|
||||
err("usb_register failed.Error number %d",ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit tbs5230_module_exit(void)
|
||||
{
|
||||
usb_deregister(&tbs5230_driver);
|
||||
}
|
||||
|
||||
module_init(tbs5230_module_init);
|
||||
module_exit(tbs5230_module_exit);
|
||||
|
||||
MODULE_AUTHOR("TBSDTV,Davin<Davin@tbsdtv.com>");
|
||||
MODULE_DESCRIPTION("Turbosight TBS5230 drivers");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/*
|
||||
* TurboSight TBS 5230 driver
|
||||
*
|
||||
* Copyright (c) 2022/06 Davin zhang<Davin@tbsdtv.com>
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <linux/version.h>
|
||||
#include "tbs5230.h"
|
||||
#include "cxd2878.h"
|
||||
|
||||
|
||||
#define TBS5230_READ_MSG 0
|
||||
#define TBS5230_WRITE_MSG 1
|
||||
|
||||
struct tbs5230_state {
|
||||
u8 initialized;
|
||||
};
|
||||
/* debug */
|
||||
static int dvb_usb_tbs5230_debug;
|
||||
module_param_named(debug, dvb_usb_tbs5230_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
|
||||
DVB_USB_DEBUG_STATUS);
|
||||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
static int tbs5230_op_rw(struct usb_device *dev, u8 request, u16 value,
|
||||
u16 index, u8 * data, u16 len, int flags)
|
||||
{
|
||||
int ret;
|
||||
void *u8buf;
|
||||
|
||||
unsigned int pipe = (flags == TBS5230_READ_MSG) ?
|
||||
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
|
||||
u8 request_type = (flags == TBS5230_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
|
||||
u8buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!u8buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (flags == TBS5230_WRITE_MSG)
|
||||
memcpy(u8buf, data, len);
|
||||
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
|
||||
value, index , u8buf, len, 2000);
|
||||
|
||||
if (flags == TBS5230_READ_MSG)
|
||||
memcpy(data, u8buf, len);
|
||||
kfree(u8buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* I2C */
|
||||
static int tbs5230_i2c_transfer(struct i2c_adapter *adap,
|
||||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
int i = 0;
|
||||
u8 buf6[35];
|
||||
u8 inbuf[35];
|
||||
|
||||
if (!d)
|
||||
return -ENODEV;
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
switch (num) {
|
||||
case 2:
|
||||
buf6[0]=msg[1].len;//lenth
|
||||
buf6[1]=msg[0].addr<<1;//demod addr
|
||||
//register
|
||||
buf6[2] = msg[0].buf[0];
|
||||
|
||||
tbs5230_op_rw(d->udev, 0x90, 0, 0,
|
||||
buf6, 3, TBS5230_WRITE_MSG);
|
||||
//msleep(5);
|
||||
tbs5230_op_rw(d->udev, 0x91, 0, 0,
|
||||
inbuf, buf6[0], TBS5230_READ_MSG);
|
||||
memcpy(msg[1].buf, inbuf, msg[1].len);
|
||||
|
||||
break;
|
||||
case 1:
|
||||
buf6[0] = msg[0].len+1;//lenth
|
||||
buf6[1] = msg[0].addr<<1;//addr
|
||||
for(i=0;i<msg[0].len;i++) {
|
||||
buf6[2+i] = msg[0].buf[i];//register
|
||||
}
|
||||
tbs5230_op_rw(d->udev, 0x80, 0, 0,
|
||||
buf6, msg[0].len+2, TBS5230_WRITE_MSG);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
return num;
|
||||
}
|
||||
|
||||
static u32 tbs5230_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm tbs5230_i2c_algo = {
|
||||
.master_xfer = tbs5230_i2c_transfer,
|
||||
.functionality = tbs5230_i2c_func,
|
||||
};
|
||||
|
||||
static int tbs5230_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
|
||||
{
|
||||
int i,ret;
|
||||
u8 ibuf[3] = {0, 0,0};
|
||||
u8 eeprom[256], eepromline[16];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
ibuf[0]=1;//lenth
|
||||
ibuf[1]=0xa0;//eeprom addr
|
||||
ibuf[2]=i;//register
|
||||
ret = tbs5230_op_rw(d->udev, 0x90, 0, 0,
|
||||
ibuf, 3, TBS5230_WRITE_MSG);
|
||||
ret = tbs5230_op_rw(d->udev, 0x91, 0, 0,
|
||||
ibuf, 1, TBS5230_READ_MSG);
|
||||
if (ret < 0) {
|
||||
err("read eeprom failed.");
|
||||
return -1;
|
||||
} else {
|
||||
eepromline[i%16] = ibuf[0];
|
||||
eeprom[i] = ibuf[0];
|
||||
}
|
||||
|
||||
if ((i % 16) == 15) {
|
||||
deb_xfer("%02x: ", i - 15);
|
||||
debug_dump(eepromline, 16, deb_xfer);
|
||||
}
|
||||
}
|
||||
memcpy(mac, eeprom + 16, 6);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties tbs5230_properties;
|
||||
|
||||
static struct cxd2878_config tbs5230_cfg = {
|
||||
|
||||
.addr_slvt = 0x64,
|
||||
.xtal = SONY_DEMOD_XTAL_24000KHz,
|
||||
.tuner_addr = 0x60,
|
||||
.tuner_xtal = SONY_ASCOT3_XTAL_24000KHz,
|
||||
.ts_mode = 1,
|
||||
.ts_ser_data = 0,
|
||||
.ts_clk = 1,
|
||||
.ts_clk_mask= 1,
|
||||
.ts_valid = 0,
|
||||
.atscCoreDisable = 0,
|
||||
.lock_flag = 1,
|
||||
.write_properties = NULL,
|
||||
.read_properties = NULL,
|
||||
};
|
||||
|
||||
static int tbs5230_frontend_attach(struct dvb_usb_adapter*adap)
|
||||
{
|
||||
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
|
||||
adap->fe_adap[0].fe = dvb_attach(cxd2878_attach, &tbs5230_cfg, &d->i2c_adap);
|
||||
|
||||
if(adap->fe_adap[0].fe!=NULL){
|
||||
strscpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
|
||||
return 0;
|
||||
}
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static struct usb_device_id tbs5230_table[] = {
|
||||
{USB_DEVICE(0x734c, 0x5230)},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, tbs5230_table);
|
||||
|
||||
static int tbs5230_load_firmware(struct usb_device *dev,
|
||||
const struct firmware *frmwr)
|
||||
{
|
||||
u8 *b, *p;
|
||||
int ret = 0, i;
|
||||
u8 reset;
|
||||
const struct firmware *fw;
|
||||
switch (dev->descriptor.idProduct) {
|
||||
case 0x5230:
|
||||
ret = request_firmware(&fw, tbs5230_properties.firmware, &dev->dev);
|
||||
if (ret != 0) {
|
||||
err("did not find the firmware file. (%s) "
|
||||
"Please see linux/Documentation/dvb/ for more details "
|
||||
"on firmware-problems.", tbs5230_properties.firmware);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fw = frmwr;
|
||||
break;
|
||||
}
|
||||
info("start downloading TBS5230 firmware");
|
||||
p = kmalloc(fw->size, GFP_KERNEL);
|
||||
reset = 1;
|
||||
/*stop the CPU*/
|
||||
tbs5230_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5230_WRITE_MSG);
|
||||
tbs5230_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5230_WRITE_MSG);
|
||||
|
||||
if (p != NULL) {
|
||||
memcpy(p, fw->data, fw->size);
|
||||
for (i = 0; i < fw->size; i += 0x40) {
|
||||
b = (u8 *) p + i;
|
||||
if (tbs5230_op_rw(dev, 0xa0, i, 0, b , 0x40,
|
||||
TBS5230_WRITE_MSG) != 0x40) {
|
||||
err("error while transferring firmware");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* restart the CPU */
|
||||
reset = 0;
|
||||
if (ret || tbs5230_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
|
||||
TBS5230_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (ret || tbs5230_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
|
||||
TBS5230_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
msleep(100);
|
||||
kfree(p);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct dvb_usb_device_properties tbs5230_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.firmware = "dvb-usb-id5230.fw",
|
||||
.size_of_priv = sizeof(struct tbs5230_state),
|
||||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &tbs5230_i2c_algo,
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
.num_adapters = 1,
|
||||
.download_firmware = tbs5230_load_firmware,
|
||||
.read_mac_address = tbs5230_read_mac_address,
|
||||
|
||||
.adapter = {{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = tbs5230_frontend_attach,
|
||||
.streaming_ctrl = NULL,
|
||||
.tuner_attach = NULL,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
}},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{"TurboSight TBS 5230 DVB-T2/T/C(j83-a/b/c),ISDB-T,ATSC1.0",
|
||||
{&tbs5230_table[0], NULL},
|
||||
{NULL},
|
||||
}
|
||||
}
|
||||
};
|
||||
static int tbs5230_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id*id)
|
||||
{
|
||||
if(0 == dvb_usb_device_init(intf,&tbs5230_properties,
|
||||
THIS_MODULE,NULL,adapter_nr)){
|
||||
return 0;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
static struct usb_driver tbs5230_driver ={
|
||||
.name = "tbs5230",
|
||||
.probe = tbs5230_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.id_table = tbs5230_table,
|
||||
|
||||
};
|
||||
static int __init tbs5230_module_init(void)
|
||||
{
|
||||
int ret = usb_register(&tbs5230_driver);
|
||||
if(ret)
|
||||
err("usb_register failed.Error number %d",ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit tbs5230_module_exit(void)
|
||||
{
|
||||
usb_deregister(&tbs5230_driver);
|
||||
}
|
||||
|
||||
module_init(tbs5230_module_init);
|
||||
module_exit(tbs5230_module_exit);
|
||||
|
||||
MODULE_AUTHOR("TBSDTV,Davin<Davin@tbsdtv.com>");
|
||||
MODULE_DESCRIPTION("Turbosight TBS5230 drivers");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
|
@@ -1,10 +1,10 @@
|
||||
#ifndef __TBS5230__
|
||||
#define __TBS5230__
|
||||
#include "dvb-usb.h"
|
||||
|
||||
#define DVB_USB_LOG_PREFIX "tbs5230"
|
||||
|
||||
#define deb_xfer(args...) dprintk(dvb_usb_tbs5230_debug, 0x02, args)
|
||||
|
||||
|
||||
#endif
|
||||
#ifndef __TBS5230__
|
||||
#define __TBS5230__
|
||||
#include "dvb-usb.h"
|
||||
|
||||
#define DVB_USB_LOG_PREFIX "tbs5230"
|
||||
|
||||
#define deb_xfer(args...) dprintk(dvb_usb_tbs5230_debug, 0x02, args)
|
||||
|
||||
|
||||
#endif
|
||||
|
@@ -283,7 +283,7 @@ static int tbs5301_frontend_attach(struct dvb_usb_adapter *d)
|
||||
ret = tbs5301_op_rw(u->udev, 0x80, 0, 0,
|
||||
buf, 4, TBS5301_WRITE_MSG);
|
||||
|
||||
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
|
@@ -284,7 +284,7 @@ static int tbs5520_frontend_attach(struct dvb_usb_adapter *d)
|
||||
tbs5520_op_rw(d->dev->udev, 0x8a, 0, 0,
|
||||
buf, 2, TBS5520_WRITE_MSG);
|
||||
|
||||
strlcpy(d->fe_adap->fe->ops.info.name,d->dev->props.devices[0].name,52);
|
||||
strscpy(d->fe_adap->fe->ops.info.name,d->dev->props.devices[0].name,52);
|
||||
return 0;
|
||||
err:
|
||||
printk("TBS5520: frontend attach failed\n");
|
||||
|
@@ -230,7 +230,7 @@ static int tbs5520se_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
si2183_config.RF_switch = NULL;
|
||||
si2183_config.agc_mode = 0x5 ;
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(info.type, "si2183", I2C_NAME_SIZE);
|
||||
strscpy(info.type, "si2183", I2C_NAME_SIZE);
|
||||
info.addr = 0x67;
|
||||
info.platform_data = &si2183_config;
|
||||
request_module(info.type);
|
||||
@@ -264,7 +264,7 @@ static int tbs5520se_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
si2157_config.fe = adap->fe_adap[0].fe;
|
||||
si2157_config.if_port = 1;
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
|
||||
strscpy(info.type, "si2157", I2C_NAME_SIZE);
|
||||
info.addr = 0x61;
|
||||
info.platform_data = &si2157_config;
|
||||
request_module(info.type);
|
||||
@@ -312,9 +312,9 @@ static int tbs5520se_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
tbs5520se_op_rw(d->udev, 0x8a, 0, 0,
|
||||
buf, 2, TBS5520SE_WRITE_MSG);
|
||||
|
||||
strlcpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
|
||||
strscpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
|
||||
strcat(adap->fe_adap[0].fe->ops.info.name," DVB-T/T2/C/C2/ISDB-T");
|
||||
strlcpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
|
||||
strscpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
|
||||
strcat(adap->fe_adap[0].fe2->ops.info.name," DVB-S/S2/S2X");
|
||||
|
||||
return 0;
|
||||
|
@@ -1,425 +1,425 @@
|
||||
/*
|
||||
* TurboSight TBS 5530 driver
|
||||
*
|
||||
* Copyright (c) 2022 Davin <Davin@tbsdtv.com>
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include "tbs5530.h"
|
||||
#include "cxd2878.h"
|
||||
#include "m88rs6060.h"
|
||||
|
||||
#define tbs5530_READ_MSG 0
|
||||
#define tbs5530_WRITE_MSG 1
|
||||
|
||||
|
||||
struct tbs5530_state {
|
||||
struct i2c_client *i2c_client_demod;
|
||||
struct i2c_client *i2c_client_tuner;
|
||||
u32 last_key_pressed;
|
||||
};
|
||||
|
||||
|
||||
/* debug */
|
||||
static int dvb_usb_tbs5530_debug;
|
||||
module_param_named(debug, dvb_usb_tbs5530_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
|
||||
DVB_USB_DEBUG_STATUS);
|
||||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
static int tbs5530_op_rw(struct usb_device *dev, u8 request, u16 value,
|
||||
u16 index, u8 * data, u16 len, int flags)
|
||||
{
|
||||
int ret;
|
||||
void *u8buf;
|
||||
|
||||
unsigned int pipe = (flags == tbs5530_READ_MSG) ?
|
||||
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
|
||||
u8 request_type = (flags == tbs5530_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
|
||||
u8buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!u8buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (flags == tbs5530_WRITE_MSG)
|
||||
memcpy(u8buf, data, len);
|
||||
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
|
||||
value, index , u8buf, len, 2000);
|
||||
|
||||
if (flags == tbs5530_READ_MSG)
|
||||
memcpy(data, u8buf, len);
|
||||
kfree(u8buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* I2C */
|
||||
static int tbs5530_i2c_transfer(struct i2c_adapter *adap,
|
||||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
int i = 0;
|
||||
u8 buf6[50];
|
||||
u8 inbuf[50];
|
||||
|
||||
if (!d)
|
||||
return -ENODEV;
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
switch (num) {
|
||||
case 2:
|
||||
buf6[0]=msg[1].len;//lenth
|
||||
buf6[1]=msg[0].addr<<1;//demod addr
|
||||
//register
|
||||
buf6[2] = msg[0].buf[0];
|
||||
|
||||
tbs5530_op_rw(d->udev, 0x90, 0, 0,
|
||||
buf6, 3, tbs5530_WRITE_MSG);
|
||||
//msleep(5);
|
||||
tbs5530_op_rw(d->udev, 0x91, 0, 0,
|
||||
inbuf, buf6[0], tbs5530_READ_MSG);
|
||||
memcpy(msg[1].buf, inbuf, msg[1].len);
|
||||
|
||||
break;
|
||||
case 1:
|
||||
buf6[0] = msg[0].len+1;//lenth
|
||||
buf6[1] = msg[0].addr<<1;//addr
|
||||
for(i=0;i<msg[0].len;i++) {
|
||||
buf6[2+i] = msg[0].buf[i];//register
|
||||
}
|
||||
tbs5530_op_rw(d->udev, 0x80, 0, 0,
|
||||
buf6, msg[0].len+2, tbs5530_WRITE_MSG);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
return num;
|
||||
}
|
||||
|
||||
static u32 tbs5530_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm tbs5530_i2c_algo = {
|
||||
.master_xfer = tbs5530_i2c_transfer,
|
||||
.functionality = tbs5530_i2c_func,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static int tbs5530_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
|
||||
{
|
||||
int i,ret;
|
||||
u8 ibuf[3] = {0, 0,0};
|
||||
u8 eeprom[256], eepromline[16];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
ibuf[0]=1;//lenth
|
||||
ibuf[1]=0xa0;//eeprom addr
|
||||
ibuf[2]=i;//register
|
||||
ret = tbs5530_op_rw(d->udev, 0x90, 0, 0,
|
||||
ibuf, 3, tbs5530_WRITE_MSG);
|
||||
ret = tbs5530_op_rw(d->udev, 0x91, 0, 0,
|
||||
ibuf, 1, tbs5530_READ_MSG);
|
||||
if (ret < 0) {
|
||||
err("read eeprom failed.");
|
||||
return -1;
|
||||
} else {
|
||||
eepromline[i%16] = ibuf[0];
|
||||
eeprom[i] = ibuf[0];
|
||||
}
|
||||
|
||||
if ((i % 16) == 15) {
|
||||
deb_xfer("%02x: ", i - 15);
|
||||
debug_dump(eepromline, 16, deb_xfer);
|
||||
}
|
||||
}
|
||||
memcpy(mac, eeprom + 16, 6);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties tbs5530_properties;
|
||||
static struct cxd2878_config tbs5530_cfg = {
|
||||
|
||||
.addr_slvt = 0x64,
|
||||
.xtal = SONY_DEMOD_XTAL_24000KHz,
|
||||
.tuner_addr = 0x60,
|
||||
.tuner_xtal = SONY_ASCOT3_XTAL_24000KHz,
|
||||
.ts_mode = 1,
|
||||
.ts_ser_data = 0,
|
||||
.ts_clk = 1,
|
||||
.ts_clk_mask= 1,
|
||||
.ts_valid = 0,
|
||||
.atscCoreDisable = 0,
|
||||
.lock_flag = 1,
|
||||
.write_properties = NULL,
|
||||
.read_properties = NULL,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static int tbs5530_sat_streaming_ctrl(struct dvb_usb_adapter*adap,int onoff) //for open dvbs ts switch
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
u8 buf[20];
|
||||
buf[0] = 10;
|
||||
buf[1] = 1;
|
||||
tbs5530_op_rw(d->udev, 0x8a, 0, 0,
|
||||
buf, 2, tbs5530_WRITE_MSG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int tbs5530_ter_cable_streaming_ctrl(struct dvb_usb_adapter*adap,int onoff)//for open dvbt/c ts
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
u8 buf[20];
|
||||
buf[0] = 10;
|
||||
buf[1] = 0;
|
||||
tbs5530_op_rw(d->udev, 0x8a, 0, 0,
|
||||
buf, 2, tbs5530_WRITE_MSG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int tbs5530_frontend_cxd2878_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
|
||||
//u8 buf[20];
|
||||
|
||||
|
||||
/* attach frontend */
|
||||
adap->fe_adap[0].fe = dvb_attach(cxd2878_attach, &tbs5530_cfg, &d->i2c_adap);
|
||||
|
||||
if(adap->fe_adap[0].fe!=NULL){
|
||||
strlcpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,60);
|
||||
strcat(adap->fe_adap[0].fe->ops.info.name," DVB-T/T2/C/C2,ISDB-T/C,ATSC1.0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// strlcpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
|
||||
|
||||
// strlcpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
|
||||
// strcat(adap->fe_adap[0].fe2->ops.info.name," DVB-S/S2/S2X");
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
static int tbs5930_frontend_m88rs6060_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
struct i2c_client *client;
|
||||
struct i2c_board_info info;
|
||||
struct m88rs6060_cfg m88rs6060_config;
|
||||
u8 buf[20];
|
||||
/* attach frontend */
|
||||
memset(&m88rs6060_config,0,sizeof(m88rs6060_config));
|
||||
m88rs6060_config.fe = &adap->fe_adap[1].fe;
|
||||
m88rs6060_config.clk = 27000000;
|
||||
m88rs6060_config.i2c_wr_max = 33;
|
||||
m88rs6060_config.ts_mode = MtFeTsOutMode_Common;
|
||||
m88rs6060_config.ts_pinswitch = 0;
|
||||
m88rs6060_config.envelope_mode = 0;
|
||||
m88rs6060_config.demod_adr = 0x69;
|
||||
m88rs6060_config.tuner_adr = 0x2c;
|
||||
m88rs6060_config.repeater_value = 0x11;
|
||||
m88rs6060_config.read_properties = NULL;
|
||||
m88rs6060_config.write_properties = NULL;
|
||||
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(info.type, "m88rs6060", I2C_NAME_SIZE);
|
||||
info.addr = 0x69;
|
||||
info.platform_data = &m88rs6060_config;
|
||||
request_module(info.type);
|
||||
client = i2c_new_client_device(&d->i2c_adap,&info);
|
||||
if(!i2c_client_has_driver(client))
|
||||
return -ENODEV;
|
||||
if (!try_module_get(client->dev.driver->owner)) {
|
||||
i2c_unregister_device(client);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = 0;
|
||||
tbs5530_op_rw(d->udev, 0xb7, 0, 0,
|
||||
buf, 2, tbs5530_WRITE_MSG);
|
||||
buf[0] = 8;
|
||||
buf[1] = 1;
|
||||
tbs5530_op_rw(d->udev, 0x8a, 0, 0,
|
||||
buf, 2, tbs5530_WRITE_MSG);
|
||||
msleep(10);
|
||||
|
||||
strlcpy(adap->fe_adap[1].fe->ops.info.name,d->props.devices[0].name,52);
|
||||
strcat(adap->fe_adap[1].fe->ops.info.name," DVB-S/S2/S2X");
|
||||
return 0;
|
||||
}
|
||||
static struct usb_device_id tbs5530_table[] = {
|
||||
{USB_DEVICE(0x734c, 0x5530)},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, tbs5530_table);
|
||||
|
||||
static int tbs5530_load_firmware(struct usb_device *dev,
|
||||
const struct firmware *frmwr)
|
||||
{
|
||||
u8 *b, *p;
|
||||
int ret = 0, i;
|
||||
u8 reset;
|
||||
const struct firmware *fw;
|
||||
switch (dev->descriptor.idProduct) {
|
||||
case 0x5530:
|
||||
ret = request_firmware(&fw, tbs5530_properties.firmware, &dev->dev);
|
||||
if (ret != 0) {
|
||||
err("did not find the firmware file. (%s) "
|
||||
"Please see linux/Documentation/dvb/ for more details "
|
||||
"on firmware-problems.", tbs5530_properties.firmware);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fw = frmwr;
|
||||
break;
|
||||
}
|
||||
info("start downloading tbs5530 firmware");
|
||||
p = kmalloc(fw->size, GFP_KERNEL);
|
||||
reset = 1;
|
||||
/*stop the CPU*/
|
||||
tbs5530_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, tbs5530_WRITE_MSG);
|
||||
tbs5530_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, tbs5530_WRITE_MSG);
|
||||
|
||||
if (p != NULL) {
|
||||
memcpy(p, fw->data, fw->size);
|
||||
for (i = 0; i < fw->size; i += 0x40) {
|
||||
b = (u8 *) p + i;
|
||||
if (tbs5530_op_rw(dev, 0xa0, i, 0, b , 0x40,
|
||||
tbs5530_WRITE_MSG) != 0x40) {
|
||||
err("error while transferring firmware");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* restart the CPU */
|
||||
reset = 0;
|
||||
if (ret || tbs5530_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
|
||||
tbs5530_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (ret || tbs5530_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
|
||||
tbs5530_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
msleep(100);
|
||||
kfree(p);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct dvb_usb_device_properties tbs5530_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.firmware = "dvb-usb-id5530.fw",
|
||||
.size_of_priv = sizeof(struct tbs5530_state),
|
||||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &tbs5530_i2c_algo,
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.num_adapters = 1,
|
||||
.download_firmware = tbs5530_load_firmware,
|
||||
.read_mac_address = tbs5530_read_mac_address,
|
||||
.adapter = {{
|
||||
.num_frontends = 2,
|
||||
.fe = {{
|
||||
.frontend_attach = tbs5530_frontend_cxd2878_attach,
|
||||
.streaming_ctrl = tbs5530_ter_cable_streaming_ctrl,
|
||||
.tuner_attach = NULL,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
},{
|
||||
.frontend_attach = tbs5930_frontend_m88rs6060_attach,
|
||||
.streaming_ctrl = tbs5530_sat_streaming_ctrl,
|
||||
.tuner_attach = NULL,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
}},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{"TurboSight TBS 5530 DVB-T2/T/C/S/S2/S2x,ISDB-T,ATSC1.0",
|
||||
{&tbs5530_table[0], NULL},
|
||||
{NULL},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int tbs5530_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
if (0 == dvb_usb_device_init(intf, &tbs5530_properties,
|
||||
THIS_MODULE, NULL, adapter_nr)) {
|
||||
return 0;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static struct usb_driver tbs5530_driver = {
|
||||
.name = "tbs5530",
|
||||
.probe = tbs5530_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.id_table = tbs5530_table,
|
||||
};
|
||||
|
||||
static int __init tbs5530_module_init(void)
|
||||
{
|
||||
int ret = usb_register(&tbs5530_driver);
|
||||
if (ret)
|
||||
err("usb_register failed. Error number %d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit tbs5530_module_exit(void)
|
||||
{
|
||||
usb_deregister(&tbs5530_driver);
|
||||
}
|
||||
|
||||
module_init(tbs5530_module_init);
|
||||
module_exit(tbs5530_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Davin <Davin@tbsdtv.com>");
|
||||
MODULE_DESCRIPTION("TurboSight TBS 5530 driver");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL");
|
||||
/*
|
||||
* TurboSight TBS 5530 driver
|
||||
*
|
||||
* Copyright (c) 2022 Davin <Davin@tbsdtv.com>
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include "tbs5530.h"
|
||||
#include "cxd2878.h"
|
||||
#include "m88rs6060.h"
|
||||
|
||||
#define tbs5530_READ_MSG 0
|
||||
#define tbs5530_WRITE_MSG 1
|
||||
|
||||
|
||||
struct tbs5530_state {
|
||||
struct i2c_client *i2c_client_demod;
|
||||
struct i2c_client *i2c_client_tuner;
|
||||
u32 last_key_pressed;
|
||||
};
|
||||
|
||||
|
||||
/* debug */
|
||||
static int dvb_usb_tbs5530_debug;
|
||||
module_param_named(debug, dvb_usb_tbs5530_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
|
||||
DVB_USB_DEBUG_STATUS);
|
||||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
static int tbs5530_op_rw(struct usb_device *dev, u8 request, u16 value,
|
||||
u16 index, u8 * data, u16 len, int flags)
|
||||
{
|
||||
int ret;
|
||||
void *u8buf;
|
||||
|
||||
unsigned int pipe = (flags == tbs5530_READ_MSG) ?
|
||||
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
|
||||
u8 request_type = (flags == tbs5530_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
|
||||
u8buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!u8buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (flags == tbs5530_WRITE_MSG)
|
||||
memcpy(u8buf, data, len);
|
||||
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
|
||||
value, index , u8buf, len, 2000);
|
||||
|
||||
if (flags == tbs5530_READ_MSG)
|
||||
memcpy(data, u8buf, len);
|
||||
kfree(u8buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* I2C */
|
||||
static int tbs5530_i2c_transfer(struct i2c_adapter *adap,
|
||||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
int i = 0;
|
||||
u8 buf6[50];
|
||||
u8 inbuf[50];
|
||||
|
||||
if (!d)
|
||||
return -ENODEV;
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
switch (num) {
|
||||
case 2:
|
||||
buf6[0]=msg[1].len;//lenth
|
||||
buf6[1]=msg[0].addr<<1;//demod addr
|
||||
//register
|
||||
buf6[2] = msg[0].buf[0];
|
||||
|
||||
tbs5530_op_rw(d->udev, 0x90, 0, 0,
|
||||
buf6, 3, tbs5530_WRITE_MSG);
|
||||
//msleep(5);
|
||||
tbs5530_op_rw(d->udev, 0x91, 0, 0,
|
||||
inbuf, buf6[0], tbs5530_READ_MSG);
|
||||
memcpy(msg[1].buf, inbuf, msg[1].len);
|
||||
|
||||
break;
|
||||
case 1:
|
||||
buf6[0] = msg[0].len+1;//lenth
|
||||
buf6[1] = msg[0].addr<<1;//addr
|
||||
for(i=0;i<msg[0].len;i++) {
|
||||
buf6[2+i] = msg[0].buf[i];//register
|
||||
}
|
||||
tbs5530_op_rw(d->udev, 0x80, 0, 0,
|
||||
buf6, msg[0].len+2, tbs5530_WRITE_MSG);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
return num;
|
||||
}
|
||||
|
||||
static u32 tbs5530_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm tbs5530_i2c_algo = {
|
||||
.master_xfer = tbs5530_i2c_transfer,
|
||||
.functionality = tbs5530_i2c_func,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static int tbs5530_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
|
||||
{
|
||||
int i,ret;
|
||||
u8 ibuf[3] = {0, 0,0};
|
||||
u8 eeprom[256], eepromline[16];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
ibuf[0]=1;//lenth
|
||||
ibuf[1]=0xa0;//eeprom addr
|
||||
ibuf[2]=i;//register
|
||||
ret = tbs5530_op_rw(d->udev, 0x90, 0, 0,
|
||||
ibuf, 3, tbs5530_WRITE_MSG);
|
||||
ret = tbs5530_op_rw(d->udev, 0x91, 0, 0,
|
||||
ibuf, 1, tbs5530_READ_MSG);
|
||||
if (ret < 0) {
|
||||
err("read eeprom failed.");
|
||||
return -1;
|
||||
} else {
|
||||
eepromline[i%16] = ibuf[0];
|
||||
eeprom[i] = ibuf[0];
|
||||
}
|
||||
|
||||
if ((i % 16) == 15) {
|
||||
deb_xfer("%02x: ", i - 15);
|
||||
debug_dump(eepromline, 16, deb_xfer);
|
||||
}
|
||||
}
|
||||
memcpy(mac, eeprom + 16, 6);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties tbs5530_properties;
|
||||
static struct cxd2878_config tbs5530_cfg = {
|
||||
|
||||
.addr_slvt = 0x64,
|
||||
.xtal = SONY_DEMOD_XTAL_24000KHz,
|
||||
.tuner_addr = 0x60,
|
||||
.tuner_xtal = SONY_ASCOT3_XTAL_24000KHz,
|
||||
.ts_mode = 1,
|
||||
.ts_ser_data = 0,
|
||||
.ts_clk = 1,
|
||||
.ts_clk_mask= 1,
|
||||
.ts_valid = 0,
|
||||
.atscCoreDisable = 0,
|
||||
.lock_flag = 1,
|
||||
.write_properties = NULL,
|
||||
.read_properties = NULL,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static int tbs5530_sat_streaming_ctrl(struct dvb_usb_adapter*adap,int onoff) //for open dvbs ts switch
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
u8 buf[20];
|
||||
buf[0] = 10;
|
||||
buf[1] = 1;
|
||||
tbs5530_op_rw(d->udev, 0x8a, 0, 0,
|
||||
buf, 2, tbs5530_WRITE_MSG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int tbs5530_ter_cable_streaming_ctrl(struct dvb_usb_adapter*adap,int onoff)//for open dvbt/c ts
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
u8 buf[20];
|
||||
buf[0] = 10;
|
||||
buf[1] = 0;
|
||||
tbs5530_op_rw(d->udev, 0x8a, 0, 0,
|
||||
buf, 2, tbs5530_WRITE_MSG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int tbs5530_frontend_cxd2878_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
|
||||
//u8 buf[20];
|
||||
|
||||
|
||||
/* attach frontend */
|
||||
adap->fe_adap[0].fe = dvb_attach(cxd2878_attach, &tbs5530_cfg, &d->i2c_adap);
|
||||
|
||||
if(adap->fe_adap[0].fe!=NULL){
|
||||
strscpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,60);
|
||||
strcat(adap->fe_adap[0].fe->ops.info.name," DVB-T/T2/C/C2,ISDB-T/C,ATSC1.0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// strscpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
|
||||
|
||||
// strscpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
|
||||
// strcat(adap->fe_adap[0].fe2->ops.info.name," DVB-S/S2/S2X");
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
static int tbs5930_frontend_m88rs6060_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
struct i2c_client *client;
|
||||
struct i2c_board_info info;
|
||||
struct m88rs6060_cfg m88rs6060_config;
|
||||
u8 buf[20];
|
||||
/* attach frontend */
|
||||
memset(&m88rs6060_config,0,sizeof(m88rs6060_config));
|
||||
m88rs6060_config.fe = &adap->fe_adap[1].fe;
|
||||
m88rs6060_config.clk = 27000000;
|
||||
m88rs6060_config.i2c_wr_max = 33;
|
||||
m88rs6060_config.ts_mode = MtFeTsOutMode_Common;
|
||||
m88rs6060_config.ts_pinswitch = 0;
|
||||
m88rs6060_config.envelope_mode = 0;
|
||||
m88rs6060_config.demod_adr = 0x69;
|
||||
m88rs6060_config.tuner_adr = 0x2c;
|
||||
m88rs6060_config.repeater_value = 0x11;
|
||||
m88rs6060_config.read_properties = NULL;
|
||||
m88rs6060_config.write_properties = NULL;
|
||||
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strscpy(info.type, "m88rs6060", I2C_NAME_SIZE);
|
||||
info.addr = 0x69;
|
||||
info.platform_data = &m88rs6060_config;
|
||||
request_module(info.type);
|
||||
client = i2c_new_client_device(&d->i2c_adap,&info);
|
||||
if(!i2c_client_has_driver(client))
|
||||
return -ENODEV;
|
||||
if (!try_module_get(client->dev.driver->owner)) {
|
||||
i2c_unregister_device(client);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = 0;
|
||||
tbs5530_op_rw(d->udev, 0xb7, 0, 0,
|
||||
buf, 2, tbs5530_WRITE_MSG);
|
||||
buf[0] = 8;
|
||||
buf[1] = 1;
|
||||
tbs5530_op_rw(d->udev, 0x8a, 0, 0,
|
||||
buf, 2, tbs5530_WRITE_MSG);
|
||||
msleep(10);
|
||||
|
||||
strscpy(adap->fe_adap[1].fe->ops.info.name,d->props.devices[0].name,52);
|
||||
strcat(adap->fe_adap[1].fe->ops.info.name," DVB-S/S2/S2X");
|
||||
return 0;
|
||||
}
|
||||
static struct usb_device_id tbs5530_table[] = {
|
||||
{USB_DEVICE(0x734c, 0x5530)},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, tbs5530_table);
|
||||
|
||||
static int tbs5530_load_firmware(struct usb_device *dev,
|
||||
const struct firmware *frmwr)
|
||||
{
|
||||
u8 *b, *p;
|
||||
int ret = 0, i;
|
||||
u8 reset;
|
||||
const struct firmware *fw;
|
||||
switch (dev->descriptor.idProduct) {
|
||||
case 0x5530:
|
||||
ret = request_firmware(&fw, tbs5530_properties.firmware, &dev->dev);
|
||||
if (ret != 0) {
|
||||
err("did not find the firmware file. (%s) "
|
||||
"Please see linux/Documentation/dvb/ for more details "
|
||||
"on firmware-problems.", tbs5530_properties.firmware);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fw = frmwr;
|
||||
break;
|
||||
}
|
||||
info("start downloading tbs5530 firmware");
|
||||
p = kmalloc(fw->size, GFP_KERNEL);
|
||||
reset = 1;
|
||||
/*stop the CPU*/
|
||||
tbs5530_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, tbs5530_WRITE_MSG);
|
||||
tbs5530_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, tbs5530_WRITE_MSG);
|
||||
|
||||
if (p != NULL) {
|
||||
memcpy(p, fw->data, fw->size);
|
||||
for (i = 0; i < fw->size; i += 0x40) {
|
||||
b = (u8 *) p + i;
|
||||
if (tbs5530_op_rw(dev, 0xa0, i, 0, b , 0x40,
|
||||
tbs5530_WRITE_MSG) != 0x40) {
|
||||
err("error while transferring firmware");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* restart the CPU */
|
||||
reset = 0;
|
||||
if (ret || tbs5530_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
|
||||
tbs5530_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (ret || tbs5530_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
|
||||
tbs5530_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
msleep(100);
|
||||
kfree(p);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct dvb_usb_device_properties tbs5530_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.firmware = "dvb-usb-id5530.fw",
|
||||
.size_of_priv = sizeof(struct tbs5530_state),
|
||||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &tbs5530_i2c_algo,
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.num_adapters = 1,
|
||||
.download_firmware = tbs5530_load_firmware,
|
||||
.read_mac_address = tbs5530_read_mac_address,
|
||||
.adapter = {{
|
||||
.num_frontends = 2,
|
||||
.fe = {{
|
||||
.frontend_attach = tbs5530_frontend_cxd2878_attach,
|
||||
.streaming_ctrl = tbs5530_ter_cable_streaming_ctrl,
|
||||
.tuner_attach = NULL,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
},{
|
||||
.frontend_attach = tbs5930_frontend_m88rs6060_attach,
|
||||
.streaming_ctrl = tbs5530_sat_streaming_ctrl,
|
||||
.tuner_attach = NULL,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
}},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{"TurboSight TBS 5530 DVB-T2/T/C/S/S2/S2x,ISDB-T,ATSC1.0",
|
||||
{&tbs5530_table[0], NULL},
|
||||
{NULL},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int tbs5530_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
if (0 == dvb_usb_device_init(intf, &tbs5530_properties,
|
||||
THIS_MODULE, NULL, adapter_nr)) {
|
||||
return 0;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static struct usb_driver tbs5530_driver = {
|
||||
.name = "tbs5530",
|
||||
.probe = tbs5530_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.id_table = tbs5530_table,
|
||||
};
|
||||
|
||||
static int __init tbs5530_module_init(void)
|
||||
{
|
||||
int ret = usb_register(&tbs5530_driver);
|
||||
if (ret)
|
||||
err("usb_register failed. Error number %d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit tbs5530_module_exit(void)
|
||||
{
|
||||
usb_deregister(&tbs5530_driver);
|
||||
}
|
||||
|
||||
module_init(tbs5530_module_init);
|
||||
module_exit(tbs5530_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Davin <Davin@tbsdtv.com>");
|
||||
MODULE_DESCRIPTION("TurboSight TBS 5530 driver");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@@ -1,8 +1,8 @@
|
||||
#ifndef _TBS5530_H_
|
||||
#define _TBS5530_H_
|
||||
|
||||
#define DVB_USB_LOG_PREFIX "tbs5530"
|
||||
#include "dvb-usb.h"
|
||||
|
||||
#define deb_xfer(args...) dprintk(dvb_usb_tbs5530_debug, 0x02, args)
|
||||
#endif
|
||||
#ifndef _TBS5530_H_
|
||||
#define _TBS5530_H_
|
||||
|
||||
#define DVB_USB_LOG_PREFIX "tbs5530"
|
||||
#include "dvb-usb.h"
|
||||
|
||||
#define deb_xfer(args...) dprintk(dvb_usb_tbs5530_debug, 0x02, args)
|
||||
#endif
|
||||
|
@@ -528,7 +528,7 @@ static int tbs5580_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
si2183_config.RF_switch = NULL;
|
||||
si2183_config.agc_mode = 0x5 ;
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(info.type, "si2183", I2C_NAME_SIZE);
|
||||
strscpy(info.type, "si2183", I2C_NAME_SIZE);
|
||||
info.addr = 0x67;
|
||||
info.platform_data = &si2183_config;
|
||||
request_module(info.type);
|
||||
@@ -561,7 +561,7 @@ static int tbs5580_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
si2157_config.fe = adap->fe_adap[0].fe;
|
||||
si2157_config.if_port = 1;
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
|
||||
strscpy(info.type, "si2157", I2C_NAME_SIZE);
|
||||
info.addr = 0x61;
|
||||
info.platform_data = &si2157_config;
|
||||
request_module(info.type);
|
||||
@@ -612,9 +612,9 @@ static int tbs5580_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
tbs5580_init(adap);
|
||||
|
||||
strlcpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
|
||||
strscpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
|
||||
strcat(adap->fe_adap[0].fe->ops.info.name," DVB-T/T2/C/C2/ISDB-T");
|
||||
strlcpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
|
||||
strscpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
|
||||
strcat(adap->fe_adap[0].fe2->ops.info.name," DVB-S/S2/S2X");
|
||||
|
||||
return 0;
|
||||
|
@@ -422,7 +422,7 @@ static int tbs5590_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
si2183_config.LED_switch = tbs5590_LED_ctrl;
|
||||
si2183_config.agc_mode = 0x5 ;
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(info.type, "si2183", I2C_NAME_SIZE);
|
||||
strscpy(info.type, "si2183", I2C_NAME_SIZE);
|
||||
info.addr = 0x67;
|
||||
info.platform_data = &si2183_config;
|
||||
request_module(info.type);
|
||||
@@ -456,7 +456,7 @@ static int tbs5590_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
si2157_config.fe = adap->fe_adap[0].fe;
|
||||
si2157_config.if_port = 1;
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
|
||||
strscpy(info.type, "si2157", I2C_NAME_SIZE);
|
||||
info.addr = 0x61;
|
||||
info.platform_data = &si2157_config;
|
||||
request_module(info.type);
|
||||
@@ -522,7 +522,7 @@ static int tbs5590_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
m88rs6060_config.LED_switch = tbs5590_LED_ctrl;
|
||||
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(info.type, "m88rs6060", I2C_NAME_SIZE);
|
||||
strscpy(info.type, "m88rs6060", I2C_NAME_SIZE);
|
||||
info.addr = 0x69;
|
||||
info.platform_data = &m88rs6060_config;
|
||||
request_module(info.type);
|
||||
@@ -552,9 +552,9 @@ static int tbs5590_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
|
||||
|
||||
|
||||
strlcpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
|
||||
strscpy(adap->fe_adap[0].fe->ops.info.name,d->props.devices[0].name,52);
|
||||
strcat(adap->fe_adap[0].fe->ops.info.name," DVB-T/T2/C/C2/ISDB-T");
|
||||
strlcpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
|
||||
strscpy(adap->fe_adap[0].fe2->ops.info.name,d->props.devices[0].name,52);
|
||||
strcat(adap->fe_adap[0].fe2->ops.info.name," DVB-S/S2/S2X");
|
||||
|
||||
return 0;
|
||||
@@ -570,7 +570,7 @@ static int tbs5590_ASI_attach(struct dvb_usb_adapter *adap)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
strlcpy(adap->fe_adap[0].fe->ops.info.name,u->props.devices[0].name,52);
|
||||
strscpy(adap->fe_adap[0].fe->ops.info.name,u->props.devices[0].name,52);
|
||||
strcat(adap->fe_adap[0].fe->ops.info.name," ASI-IN");
|
||||
|
||||
return 0;
|
||||
|
@@ -590,7 +590,7 @@ static int tbs5880_frontend_attach(struct dvb_usb_adapter *d)
|
||||
buf, 2, TBS5880_WRITE_MSG);
|
||||
|
||||
tbs5880_init(d);
|
||||
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@@ -507,7 +507,7 @@ static int tbs5881_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
si2168_config.ts_clock_gapped = true;
|
||||
si2168_config.ts_clock_inv = true;
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(info.type, "si2168", I2C_NAME_SIZE);
|
||||
strscpy(info.type, "si2168", I2C_NAME_SIZE);
|
||||
info.addr = 0x64;
|
||||
info.platform_data = &si2168_config;
|
||||
request_module(info.type);
|
||||
@@ -525,7 +525,7 @@ static int tbs5881_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
si2157_config.fe = adap->fe_adap[0].fe;
|
||||
si2157_config.if_port = 1;
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
|
||||
strscpy(info.type, "si2157", I2C_NAME_SIZE);
|
||||
info.addr = 0x60;
|
||||
info.platform_data = &si2157_config;
|
||||
request_module(info.type);
|
||||
@@ -566,7 +566,7 @@ static int tbs5881_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
buf, 2, TBS5881_WRITE_MSG);
|
||||
|
||||
tbs5881_init(adap);
|
||||
strlcpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
|
||||
strscpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -223,7 +223,7 @@ static int tbs5922se_frontend_attach(struct dvb_usb_adapter *d)
|
||||
buf[1] = 1;
|
||||
tbs5922se_op_rw(u->udev, 0x8a, 0, 0, buf, 2, TBS5922SE_WRITE_MSG);
|
||||
|
||||
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
|
@@ -289,7 +289,7 @@ static int tbs5925_frontend_attach(struct dvb_usb_adapter *d)
|
||||
tbs5925_op_rw(u->udev, 0x8a, 0, 0,
|
||||
buf, 2, TBS5925_WRITE_MSG);
|
||||
|
||||
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -295,7 +295,7 @@ static int tbs5927_frontend_attach(struct dvb_usb_adapter *d)
|
||||
tbs5927_op_rw(d->dev->udev, 0x8a, 0, 0,
|
||||
buf, 2, TBS5927_WRITE_MSG);
|
||||
|
||||
strlcpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
strscpy(d->fe_adap->fe->ops.info.name,u->props.devices[0].name,52);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,346 +1,346 @@
|
||||
/*
|
||||
* TurboSight TBS 5930 driver
|
||||
*
|
||||
* Copyright (c) 2017 Davin <smailedavin@hotmail.com>
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include "tbs5930.h"
|
||||
#include "m88rs6060.h"
|
||||
|
||||
#define TBS5930_READ_MSG 0
|
||||
#define TBS5930_WRITE_MSG 1
|
||||
|
||||
#define TBS5930_RC_QUERY (0x1a00)
|
||||
#define TBS5930_VOLTAGE_CTRL (0x1800)
|
||||
|
||||
struct tbs5930_state {
|
||||
u8 initialized;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* debug */
|
||||
static int dvb_usb_tbs5930_debug;
|
||||
module_param_named(debug, dvb_usb_tbs5930_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
|
||||
DVB_USB_DEBUG_STATUS);
|
||||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
static int tbs5930_op_rw(struct usb_device *dev, u8 request, u16 value,
|
||||
u16 index, u8 * data, u16 len, int flags)
|
||||
{
|
||||
int ret;
|
||||
void *u8buf;
|
||||
|
||||
unsigned int pipe = (flags == TBS5930_READ_MSG) ?
|
||||
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
|
||||
u8 request_type = (flags == TBS5930_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
|
||||
u8buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!u8buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (flags == TBS5930_WRITE_MSG)
|
||||
memcpy(u8buf, data, len);
|
||||
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
|
||||
value, index , u8buf, len, 2000);
|
||||
|
||||
if (flags == TBS5930_READ_MSG)
|
||||
memcpy(data, u8buf, len);
|
||||
kfree(u8buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* I2C */
|
||||
static int tbs5930_i2c_transfer(struct i2c_adapter *adap,
|
||||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
int i = 0;
|
||||
u8 buf6[35];
|
||||
u8 inbuf[35];
|
||||
|
||||
if (!d)
|
||||
return -ENODEV;
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
switch (num) {
|
||||
case 2:
|
||||
buf6[0]=msg[1].len;//lenth
|
||||
buf6[1]=msg[0].addr<<1;//demod addr
|
||||
//register
|
||||
buf6[2] = msg[0].buf[0];
|
||||
|
||||
tbs5930_op_rw(d->udev, 0x90, 0, 0,
|
||||
buf6, 3, TBS5930_WRITE_MSG);
|
||||
//msleep(5);
|
||||
tbs5930_op_rw(d->udev, 0x91, 0, 0,
|
||||
inbuf, buf6[0], TBS5930_READ_MSG);
|
||||
memcpy(msg[1].buf, inbuf, msg[1].len);
|
||||
|
||||
break;
|
||||
case 1:
|
||||
buf6[0] = msg[0].len+1;//lenth
|
||||
buf6[1] = msg[0].addr<<1;//addr
|
||||
for(i=0;i<msg[0].len;i++) {
|
||||
buf6[2+i] = msg[0].buf[i];//register
|
||||
}
|
||||
tbs5930_op_rw(d->udev, 0x80, 0, 0,
|
||||
buf6, msg[0].len+2, TBS5930_WRITE_MSG);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
return num;
|
||||
}
|
||||
|
||||
static u32 tbs5930_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm tbs5930_i2c_algo = {
|
||||
.master_xfer = tbs5930_i2c_transfer,
|
||||
.functionality = tbs5930_i2c_func,
|
||||
};
|
||||
|
||||
static int tbs5930_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
|
||||
{
|
||||
int i,ret;
|
||||
u8 ibuf[3] = {0, 0,0};
|
||||
u8 eeprom[256], eepromline[16];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
ibuf[0]=1;//lenth
|
||||
ibuf[1]=0xa0;//eeprom addr
|
||||
ibuf[2]=i;//register
|
||||
ret = tbs5930_op_rw(d->udev, 0x90, 0, 0,
|
||||
ibuf, 3, TBS5930_WRITE_MSG);
|
||||
ret = tbs5930_op_rw(d->udev, 0x91, 0, 0,
|
||||
ibuf, 1, TBS5930_READ_MSG);
|
||||
if (ret < 0) {
|
||||
err("read eeprom failed.");
|
||||
return -1;
|
||||
} else {
|
||||
eepromline[i%16] = ibuf[0];
|
||||
eeprom[i] = ibuf[0];
|
||||
}
|
||||
|
||||
if ((i % 16) == 15) {
|
||||
deb_xfer("%02x: ", i - 15);
|
||||
debug_dump(eepromline, 16, deb_xfer);
|
||||
}
|
||||
}
|
||||
memcpy(mac, eeprom + 16, 6);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties tbs5930_properties;
|
||||
|
||||
static int tbs5930_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
struct i2c_client *client;
|
||||
struct i2c_board_info info;
|
||||
struct m88rs6060_cfg m88rs6060_config;
|
||||
u8 buf[20];
|
||||
/* attach frontend */
|
||||
memset(&m88rs6060_config,0,sizeof(m88rs6060_config));
|
||||
m88rs6060_config.fe = &adap->fe_adap[0].fe;
|
||||
m88rs6060_config.clk = 27000000;
|
||||
m88rs6060_config.i2c_wr_max = 33;
|
||||
m88rs6060_config.ts_mode = MtFeTsOutMode_Common;
|
||||
m88rs6060_config.ts_pinswitch = 0;
|
||||
m88rs6060_config.envelope_mode = 0;
|
||||
m88rs6060_config.demod_adr = 0x69;
|
||||
m88rs6060_config.tuner_adr = 0x2c;
|
||||
m88rs6060_config.repeater_value = 0x11;
|
||||
m88rs6060_config.read_properties = NULL;
|
||||
m88rs6060_config.write_properties = NULL;
|
||||
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strlcpy(info.type, "m88rs6060", I2C_NAME_SIZE);
|
||||
info.addr = 0x69;
|
||||
info.platform_data = &m88rs6060_config;
|
||||
request_module(info.type);
|
||||
client = i2c_new_client_device(&d->i2c_adap,&info);
|
||||
if(!i2c_client_has_driver(client))
|
||||
return -ENODEV;
|
||||
if (!try_module_get(client->dev.driver->owner)) {
|
||||
i2c_unregister_device(client);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = 0;
|
||||
tbs5930_op_rw(d->udev, 0xb7, 0, 0,
|
||||
buf, 2, TBS5930_WRITE_MSG);
|
||||
buf[0] = 8;
|
||||
buf[1] = 1;
|
||||
tbs5930_op_rw(d->udev, 0x8a, 0, 0,
|
||||
buf, 2, TBS5930_WRITE_MSG);
|
||||
msleep(10);
|
||||
|
||||
strlcpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_device_id tbs5930_table[] = {
|
||||
{USB_DEVICE(0x734c, 0x5930)},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, tbs5930_table);
|
||||
|
||||
static int tbs5930_load_firmware(struct usb_device *dev,
|
||||
const struct firmware *frmwr)
|
||||
{
|
||||
u8 *b, *p;
|
||||
int ret = 0, i;
|
||||
u8 reset;
|
||||
const struct firmware *fw;
|
||||
switch (dev->descriptor.idProduct) {
|
||||
case 0x5930:
|
||||
ret = request_firmware(&fw, tbs5930_properties.firmware, &dev->dev);
|
||||
if (ret != 0) {
|
||||
err("did not find the firmware file. (%s) "
|
||||
"Please see linux/Documentation/dvb/ for more details "
|
||||
"on firmware-problems.", tbs5930_properties.firmware);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fw = frmwr;
|
||||
break;
|
||||
}
|
||||
info("start downloading TBS5930 firmware");
|
||||
p = kmalloc(fw->size, GFP_KERNEL);
|
||||
reset = 1;
|
||||
/*stop the CPU*/
|
||||
tbs5930_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5930_WRITE_MSG);
|
||||
tbs5930_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5930_WRITE_MSG);
|
||||
|
||||
if (p != NULL) {
|
||||
memcpy(p, fw->data, fw->size);
|
||||
for (i = 0; i < fw->size; i += 0x40) {
|
||||
b = (u8 *) p + i;
|
||||
if (tbs5930_op_rw(dev, 0xa0, i, 0, b , 0x40,
|
||||
TBS5930_WRITE_MSG) != 0x40) {
|
||||
err("error while transferring firmware");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* restart the CPU */
|
||||
reset = 0;
|
||||
if (ret || tbs5930_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
|
||||
TBS5930_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (ret || tbs5930_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
|
||||
TBS5930_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
msleep(100);
|
||||
kfree(p);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct dvb_usb_device_properties tbs5930_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.firmware = "dvb-usb-id5930.fw",
|
||||
.size_of_priv = sizeof(struct tbs5930_state),
|
||||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &tbs5930_i2c_algo,
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.num_adapters = 1,
|
||||
.download_firmware = tbs5930_load_firmware,
|
||||
.read_mac_address = tbs5930_read_mac_address,
|
||||
.adapter = {{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = tbs5930_frontend_attach,
|
||||
.streaming_ctrl = NULL,
|
||||
.tuner_attach = NULL,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
}},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{"TurboSight TBS 5930 DVB-S/S2/S2x",
|
||||
{&tbs5930_table[0], NULL},
|
||||
{NULL},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int tbs5930_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
if (0 == dvb_usb_device_init(intf, &tbs5930_properties,
|
||||
THIS_MODULE, NULL, adapter_nr)) {
|
||||
return 0;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
static struct usb_driver tbs5930_driver = {
|
||||
.name = "tbs5930",
|
||||
.probe = tbs5930_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.id_table = tbs5930_table,
|
||||
};
|
||||
|
||||
static int __init tbs5930_module_init(void)
|
||||
{
|
||||
int ret = usb_register(&tbs5930_driver);
|
||||
if (ret)
|
||||
err("usb_register failed. Error number %d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit tbs5930_module_exit(void)
|
||||
{
|
||||
usb_deregister(&tbs5930_driver);
|
||||
}
|
||||
|
||||
module_init(tbs5930_module_init);
|
||||
module_exit(tbs5930_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Davin zhang<Davin@tbsdtv.com>");
|
||||
MODULE_DESCRIPTION("TurboSight TBS 5930 driver");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL");
|
||||
/*
|
||||
* TurboSight TBS 5930 driver
|
||||
*
|
||||
* Copyright (c) 2017 Davin <smailedavin@hotmail.com>
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include "tbs5930.h"
|
||||
#include "m88rs6060.h"
|
||||
|
||||
#define TBS5930_READ_MSG 0
|
||||
#define TBS5930_WRITE_MSG 1
|
||||
|
||||
#define TBS5930_RC_QUERY (0x1a00)
|
||||
#define TBS5930_VOLTAGE_CTRL (0x1800)
|
||||
|
||||
struct tbs5930_state {
|
||||
u8 initialized;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* debug */
|
||||
static int dvb_usb_tbs5930_debug;
|
||||
module_param_named(debug, dvb_usb_tbs5930_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
|
||||
DVB_USB_DEBUG_STATUS);
|
||||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
static int tbs5930_op_rw(struct usb_device *dev, u8 request, u16 value,
|
||||
u16 index, u8 * data, u16 len, int flags)
|
||||
{
|
||||
int ret;
|
||||
void *u8buf;
|
||||
|
||||
unsigned int pipe = (flags == TBS5930_READ_MSG) ?
|
||||
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
|
||||
u8 request_type = (flags == TBS5930_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
|
||||
u8buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!u8buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (flags == TBS5930_WRITE_MSG)
|
||||
memcpy(u8buf, data, len);
|
||||
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
|
||||
value, index , u8buf, len, 2000);
|
||||
|
||||
if (flags == TBS5930_READ_MSG)
|
||||
memcpy(data, u8buf, len);
|
||||
kfree(u8buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* I2C */
|
||||
static int tbs5930_i2c_transfer(struct i2c_adapter *adap,
|
||||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
int i = 0;
|
||||
u8 buf6[35];
|
||||
u8 inbuf[35];
|
||||
|
||||
if (!d)
|
||||
return -ENODEV;
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
switch (num) {
|
||||
case 2:
|
||||
buf6[0]=msg[1].len;//lenth
|
||||
buf6[1]=msg[0].addr<<1;//demod addr
|
||||
//register
|
||||
buf6[2] = msg[0].buf[0];
|
||||
|
||||
tbs5930_op_rw(d->udev, 0x90, 0, 0,
|
||||
buf6, 3, TBS5930_WRITE_MSG);
|
||||
//msleep(5);
|
||||
tbs5930_op_rw(d->udev, 0x91, 0, 0,
|
||||
inbuf, buf6[0], TBS5930_READ_MSG);
|
||||
memcpy(msg[1].buf, inbuf, msg[1].len);
|
||||
|
||||
break;
|
||||
case 1:
|
||||
buf6[0] = msg[0].len+1;//lenth
|
||||
buf6[1] = msg[0].addr<<1;//addr
|
||||
for(i=0;i<msg[0].len;i++) {
|
||||
buf6[2+i] = msg[0].buf[i];//register
|
||||
}
|
||||
tbs5930_op_rw(d->udev, 0x80, 0, 0,
|
||||
buf6, msg[0].len+2, TBS5930_WRITE_MSG);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
return num;
|
||||
}
|
||||
|
||||
static u32 tbs5930_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm tbs5930_i2c_algo = {
|
||||
.master_xfer = tbs5930_i2c_transfer,
|
||||
.functionality = tbs5930_i2c_func,
|
||||
};
|
||||
|
||||
static int tbs5930_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
|
||||
{
|
||||
int i,ret;
|
||||
u8 ibuf[3] = {0, 0,0};
|
||||
u8 eeprom[256], eepromline[16];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
ibuf[0]=1;//lenth
|
||||
ibuf[1]=0xa0;//eeprom addr
|
||||
ibuf[2]=i;//register
|
||||
ret = tbs5930_op_rw(d->udev, 0x90, 0, 0,
|
||||
ibuf, 3, TBS5930_WRITE_MSG);
|
||||
ret = tbs5930_op_rw(d->udev, 0x91, 0, 0,
|
||||
ibuf, 1, TBS5930_READ_MSG);
|
||||
if (ret < 0) {
|
||||
err("read eeprom failed.");
|
||||
return -1;
|
||||
} else {
|
||||
eepromline[i%16] = ibuf[0];
|
||||
eeprom[i] = ibuf[0];
|
||||
}
|
||||
|
||||
if ((i % 16) == 15) {
|
||||
deb_xfer("%02x: ", i - 15);
|
||||
debug_dump(eepromline, 16, deb_xfer);
|
||||
}
|
||||
}
|
||||
memcpy(mac, eeprom + 16, 6);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties tbs5930_properties;
|
||||
|
||||
static int tbs5930_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
struct i2c_client *client;
|
||||
struct i2c_board_info info;
|
||||
struct m88rs6060_cfg m88rs6060_config;
|
||||
u8 buf[20];
|
||||
/* attach frontend */
|
||||
memset(&m88rs6060_config,0,sizeof(m88rs6060_config));
|
||||
m88rs6060_config.fe = &adap->fe_adap[0].fe;
|
||||
m88rs6060_config.clk = 27000000;
|
||||
m88rs6060_config.i2c_wr_max = 33;
|
||||
m88rs6060_config.ts_mode = MtFeTsOutMode_Common;
|
||||
m88rs6060_config.ts_pinswitch = 0;
|
||||
m88rs6060_config.envelope_mode = 0;
|
||||
m88rs6060_config.demod_adr = 0x69;
|
||||
m88rs6060_config.tuner_adr = 0x2c;
|
||||
m88rs6060_config.repeater_value = 0x11;
|
||||
m88rs6060_config.read_properties = NULL;
|
||||
m88rs6060_config.write_properties = NULL;
|
||||
|
||||
memset(&info, 0, sizeof(struct i2c_board_info));
|
||||
strscpy(info.type, "m88rs6060", I2C_NAME_SIZE);
|
||||
info.addr = 0x69;
|
||||
info.platform_data = &m88rs6060_config;
|
||||
request_module(info.type);
|
||||
client = i2c_new_client_device(&d->i2c_adap,&info);
|
||||
if(!i2c_client_has_driver(client))
|
||||
return -ENODEV;
|
||||
if (!try_module_get(client->dev.driver->owner)) {
|
||||
i2c_unregister_device(client);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = 0;
|
||||
tbs5930_op_rw(d->udev, 0xb7, 0, 0,
|
||||
buf, 2, TBS5930_WRITE_MSG);
|
||||
buf[0] = 8;
|
||||
buf[1] = 1;
|
||||
tbs5930_op_rw(d->udev, 0x8a, 0, 0,
|
||||
buf, 2, TBS5930_WRITE_MSG);
|
||||
msleep(10);
|
||||
|
||||
strscpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct usb_device_id tbs5930_table[] = {
|
||||
{USB_DEVICE(0x734c, 0x5930)},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, tbs5930_table);
|
||||
|
||||
static int tbs5930_load_firmware(struct usb_device *dev,
|
||||
const struct firmware *frmwr)
|
||||
{
|
||||
u8 *b, *p;
|
||||
int ret = 0, i;
|
||||
u8 reset;
|
||||
const struct firmware *fw;
|
||||
switch (dev->descriptor.idProduct) {
|
||||
case 0x5930:
|
||||
ret = request_firmware(&fw, tbs5930_properties.firmware, &dev->dev);
|
||||
if (ret != 0) {
|
||||
err("did not find the firmware file. (%s) "
|
||||
"Please see linux/Documentation/dvb/ for more details "
|
||||
"on firmware-problems.", tbs5930_properties.firmware);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fw = frmwr;
|
||||
break;
|
||||
}
|
||||
info("start downloading TBS5930 firmware");
|
||||
p = kmalloc(fw->size, GFP_KERNEL);
|
||||
reset = 1;
|
||||
/*stop the CPU*/
|
||||
tbs5930_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5930_WRITE_MSG);
|
||||
tbs5930_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5930_WRITE_MSG);
|
||||
|
||||
if (p != NULL) {
|
||||
memcpy(p, fw->data, fw->size);
|
||||
for (i = 0; i < fw->size; i += 0x40) {
|
||||
b = (u8 *) p + i;
|
||||
if (tbs5930_op_rw(dev, 0xa0, i, 0, b , 0x40,
|
||||
TBS5930_WRITE_MSG) != 0x40) {
|
||||
err("error while transferring firmware");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* restart the CPU */
|
||||
reset = 0;
|
||||
if (ret || tbs5930_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
|
||||
TBS5930_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (ret || tbs5930_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
|
||||
TBS5930_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
msleep(100);
|
||||
kfree(p);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct dvb_usb_device_properties tbs5930_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.firmware = "dvb-usb-id5930.fw",
|
||||
.size_of_priv = sizeof(struct tbs5930_state),
|
||||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &tbs5930_i2c_algo,
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.num_adapters = 1,
|
||||
.download_firmware = tbs5930_load_firmware,
|
||||
.read_mac_address = tbs5930_read_mac_address,
|
||||
.adapter = {{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = tbs5930_frontend_attach,
|
||||
.streaming_ctrl = NULL,
|
||||
.tuner_attach = NULL,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
}},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{"TurboSight TBS 5930 DVB-S/S2/S2x",
|
||||
{&tbs5930_table[0], NULL},
|
||||
{NULL},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int tbs5930_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
if (0 == dvb_usb_device_init(intf, &tbs5930_properties,
|
||||
THIS_MODULE, NULL, adapter_nr)) {
|
||||
return 0;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
static struct usb_driver tbs5930_driver = {
|
||||
.name = "tbs5930",
|
||||
.probe = tbs5930_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.id_table = tbs5930_table,
|
||||
};
|
||||
|
||||
static int __init tbs5930_module_init(void)
|
||||
{
|
||||
int ret = usb_register(&tbs5930_driver);
|
||||
if (ret)
|
||||
err("usb_register failed. Error number %d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit tbs5930_module_exit(void)
|
||||
{
|
||||
usb_deregister(&tbs5930_driver);
|
||||
}
|
||||
|
||||
module_init(tbs5930_module_init);
|
||||
module_exit(tbs5930_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Davin zhang<Davin@tbsdtv.com>");
|
||||
MODULE_DESCRIPTION("TurboSight TBS 5930 driver");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@@ -1,8 +1,8 @@
|
||||
#ifndef _TBS5930_H_
|
||||
#define _TBS5930_H_
|
||||
|
||||
#define DVB_USB_LOG_PREFIX "tbs5930"
|
||||
#include "dvb-usb.h"
|
||||
|
||||
#define deb_xfer(args...) dprintk(dvb_usb_tbs5930_debug, 0x02, args)
|
||||
#endif
|
||||
#ifndef _TBS5930_H_
|
||||
#define _TBS5930_H_
|
||||
|
||||
#define DVB_USB_LOG_PREFIX "tbs5930"
|
||||
#include "dvb-usb.h"
|
||||
|
||||
#define deb_xfer(args...) dprintk(dvb_usb_tbs5930_debug, 0x02, args)
|
||||
#endif
|
||||
|
@@ -1,437 +1,437 @@
|
||||
/*
|
||||
* TurboSight TBS 5930 lite driver
|
||||
*
|
||||
* Copyright (c) 2017 Davin <davin@tbsdtv.com>
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include "tbs5931.h"
|
||||
#include "gx1133.h"
|
||||
#include "tas2101.h"
|
||||
#include "av201x.h"
|
||||
|
||||
#define TBS5931_READ_MSG 0
|
||||
#define TBS5931_WRITE_MSG 1
|
||||
|
||||
#define TBS5931_RC_QUERY (0x1a00)
|
||||
#define TBS5931_VOLTAGE_CTRL (0x1800)
|
||||
|
||||
struct tbs5931_state {
|
||||
u8 initialized;
|
||||
};
|
||||
|
||||
|
||||
static struct tas2101_config gx1132_cfg = {
|
||||
.i2c_address = 0x60,
|
||||
.id = ID_TAS2101,
|
||||
.init = {0x10, 0x32, 0x54, 0x76, 0xA8, 0x9B, 0x33},
|
||||
.init2 = 0,
|
||||
|
||||
};
|
||||
|
||||
static struct gx1133_config gx1133_cfg = {
|
||||
.i2c_address = 0x52,
|
||||
.ts_mode = 0,
|
||||
.ts_cfg = {data_0,data_1,data_2,data_3,data_4,data_5,data_6, \
|
||||
data_7,ts_sync,ts_err,ts_clk,ts_valid},
|
||||
};
|
||||
|
||||
static struct av201x_config av201x_cfg = {
|
||||
.i2c_address = 0x62,
|
||||
.id = ID_AV2012,
|
||||
.xtal_freq = 27000, /* kHz */
|
||||
};
|
||||
|
||||
|
||||
/* debug */
|
||||
static int dvb_usb_tbs5931_debug;
|
||||
module_param_named(debug, dvb_usb_tbs5931_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
|
||||
DVB_USB_DEBUG_STATUS);
|
||||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
static int tbs5931_op_rw(struct usb_device *dev, u8 request, u16 value,
|
||||
u16 index, u8 * data, u16 len, int flags)
|
||||
{
|
||||
int ret;
|
||||
void *u8buf;
|
||||
|
||||
unsigned int pipe = (flags == TBS5931_READ_MSG) ?
|
||||
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
|
||||
u8 request_type = (flags == TBS5931_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
|
||||
u8buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!u8buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (flags == TBS5931_WRITE_MSG)
|
||||
memcpy(u8buf, data, len);
|
||||
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
|
||||
value, index , u8buf, len, 2000);
|
||||
|
||||
if (flags == TBS5931_READ_MSG)
|
||||
memcpy(data, u8buf, len);
|
||||
kfree(u8buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* I2C */
|
||||
static int tbs5931_i2c_transfer(struct i2c_adapter *adap,
|
||||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
int i = 0;
|
||||
u8 buf6[35];
|
||||
u8 inbuf[35];
|
||||
|
||||
if (!d)
|
||||
return -ENODEV;
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
switch (num) {
|
||||
case 2:
|
||||
switch(msg[0].addr){
|
||||
case 0x60:
|
||||
case 0x62:
|
||||
buf6[0]=msg[1].len;//lenth
|
||||
buf6[1]=msg[0].addr<<1;//demod addr
|
||||
//register
|
||||
buf6[2] = msg[0].buf[0];
|
||||
|
||||
tbs5931_op_rw(d->udev, 0x90, 0, 0,
|
||||
buf6, 3, TBS5931_WRITE_MSG);
|
||||
msleep(1);
|
||||
tbs5931_op_rw(d->udev, 0x91, 0, 0,
|
||||
inbuf, buf6[0], TBS5931_READ_MSG);
|
||||
memcpy(msg[1].buf, inbuf, msg[1].len);
|
||||
break;
|
||||
case 0x52:
|
||||
buf6[0]=msg[1].len;//lenth
|
||||
buf6[1]=msg[0].addr<<1;//demod addr
|
||||
//register
|
||||
memcpy(buf6+2,msg[0].buf,msg[0].len);
|
||||
|
||||
tbs5931_op_rw(d->udev, 0x92, 0, 0,
|
||||
buf6, msg[0].len+2, TBS5931_WRITE_MSG);
|
||||
msleep(1);
|
||||
tbs5931_op_rw(d->udev, 0x91, 0, 0,
|
||||
inbuf, msg[1].len, TBS5931_READ_MSG);
|
||||
|
||||
memcpy(msg[1].buf, inbuf, msg[1].len);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
buf6[0] = msg[0].len+1;//lenth
|
||||
buf6[1] = msg[0].addr<<1;//addr
|
||||
for(i=0;i<msg[0].len;i++) {
|
||||
buf6[2+i] = msg[0].buf[i];//register
|
||||
}
|
||||
tbs5931_op_rw(d->udev, 0x80, 0, 0,
|
||||
buf6, msg[0].len+2, TBS5931_WRITE_MSG);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
return num;
|
||||
}
|
||||
|
||||
static u32 tbs5931_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm tbs5931_i2c_algo = {
|
||||
.master_xfer = tbs5931_i2c_transfer,
|
||||
.functionality = tbs5931_i2c_func,
|
||||
};
|
||||
|
||||
static int tbs5931_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
|
||||
{
|
||||
int i,ret;
|
||||
u8 ibuf[3] = {0, 0,0};
|
||||
u8 eeprom[256], eepromline[16];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
ibuf[0]=1;//lenth
|
||||
ibuf[1]=0xA0;//eeprom addr
|
||||
ibuf[2]=i;//register
|
||||
ret = tbs5931_op_rw(d->udev, 0x90, 0, 0,
|
||||
ibuf, 3, TBS5931_WRITE_MSG);
|
||||
ret = tbs5931_op_rw(d->udev, 0x91, 0, 0,
|
||||
ibuf, 1, TBS5931_READ_MSG);
|
||||
if (ret < 0) {
|
||||
err("read eeprom failed.");
|
||||
return -1;
|
||||
} else {
|
||||
eepromline[i%16] = ibuf[0];
|
||||
eeprom[i] = ibuf[0];
|
||||
}
|
||||
|
||||
if ((i % 16) == 15) {
|
||||
deb_xfer("%02x: ", i - 15);
|
||||
debug_dump(eepromline, 16, deb_xfer);
|
||||
}
|
||||
}
|
||||
memcpy(mac, eeprom + 16, 6);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties tbs5931_properties;
|
||||
|
||||
static int tbs5931_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
|
||||
u8 buf[20];
|
||||
u8 a = 0,b = 0;
|
||||
u16 id;
|
||||
//read the id to deceted the chip
|
||||
buf[0]= 1;//lenth
|
||||
buf[1]= 0xC0;//demod addr
|
||||
//register
|
||||
buf[2] = 0x01;
|
||||
tbs5931_op_rw(d->udev, 0x90, 0, 0,
|
||||
buf, 3, TBS5931_WRITE_MSG);
|
||||
msleep(1);
|
||||
tbs5931_op_rw(d->udev, 0x91, 0, 0,
|
||||
&a, buf[0], TBS5931_READ_MSG);
|
||||
msleep(5);
|
||||
|
||||
buf[2] = 0x00;
|
||||
tbs5931_op_rw(d->udev, 0x90, 0, 0,
|
||||
buf, 3, TBS5931_WRITE_MSG);
|
||||
msleep(1);
|
||||
tbs5931_op_rw(d->udev, 0x91, 0, 0,
|
||||
&b, buf[0], TBS5931_READ_MSG);
|
||||
id = (b<<8|a);
|
||||
if(id==0x444c){ //gx1132
|
||||
adap->fe_adap->fe = dvb_attach(tas2101_attach,&gx1132_cfg,&d->i2c_adap);
|
||||
if(adap->fe_adap->fe ==NULL)
|
||||
goto err;
|
||||
|
||||
if(dvb_attach(av201x_attach,adap->fe_adap->fe,&av201x_cfg,
|
||||
tas2101_get_i2c_adapter(adap->fe_adap->fe,2))==NULL){
|
||||
dvb_frontend_detach(adap->fe_adap->fe);
|
||||
adap->fe_adap->fe = NULL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else{
|
||||
id = 0;
|
||||
a = 0;
|
||||
b = 0;
|
||||
|
||||
buf[0]= 1;//lenth
|
||||
buf[1]= 0xA4;//demod addr
|
||||
//register
|
||||
buf[2] = 0xff;
|
||||
buf[3] = 0xf1;
|
||||
tbs5931_op_rw(d->udev, 0x92, 0, 0,
|
||||
buf, 4, TBS5931_WRITE_MSG);
|
||||
msleep(1);
|
||||
tbs5931_op_rw(d->udev, 0x91, 0, 0,
|
||||
&a, buf[0], TBS5931_READ_MSG);
|
||||
msleep(5);
|
||||
|
||||
buf[3] = 0xf0;
|
||||
tbs5931_op_rw(d->udev, 0x92, 0, 0,
|
||||
buf, 4, TBS5931_WRITE_MSG);
|
||||
msleep(1);
|
||||
tbs5931_op_rw(d->udev, 0x91, 0, 0,
|
||||
&b, buf[0], TBS5931_READ_MSG);
|
||||
|
||||
id = (b<<8|a);
|
||||
if(id==0x444c){ //gx1133
|
||||
adap->fe_adap->fe = dvb_attach(gx1133_attach,&gx1133_cfg,&d->i2c_adap);
|
||||
if(adap->fe_adap->fe ==NULL)
|
||||
goto err;
|
||||
|
||||
if(dvb_attach(av201x_attach,adap->fe_adap->fe,&av201x_cfg,
|
||||
gx1133_get_i2c_adapter(adap->fe_adap->fe,2))==NULL){
|
||||
dvb_frontend_detach(adap->fe_adap->fe);
|
||||
adap->fe_adap->fe = NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
goto err;
|
||||
|
||||
}
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = 0;
|
||||
tbs5931_op_rw(d->udev, 0xb7, 0, 0,
|
||||
buf, 2, TBS5931_WRITE_MSG);
|
||||
|
||||
buf[0] = 8;
|
||||
buf[1] = 1;
|
||||
tbs5931_op_rw(d->udev, 0x8a, 0, 0,
|
||||
buf, 2, TBS5931_WRITE_MSG);
|
||||
msleep(10);
|
||||
|
||||
strlcpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static struct usb_device_id tbs5931_table[] = {
|
||||
{USB_DEVICE(0x734c, 0x5931)},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, tbs5931_table);
|
||||
|
||||
static int tbs5931_load_firmware(struct usb_device *dev,
|
||||
const struct firmware *frmwr)
|
||||
{
|
||||
u8 *b, *p;
|
||||
int ret = 0, i;
|
||||
u8 reset;
|
||||
const struct firmware *fw;
|
||||
switch (dev->descriptor.idProduct) {
|
||||
case 0x5931:
|
||||
ret = request_firmware(&fw, tbs5931_properties.firmware, &dev->dev);
|
||||
if (ret != 0) {
|
||||
err("did not find the firmware file. (%s) "
|
||||
"Please see linux/Documentation/dvb/ for more details "
|
||||
"on firmware-problems.", tbs5931_properties.firmware);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fw = frmwr;
|
||||
break;
|
||||
}
|
||||
info("start downloading TBS5931 firmware");
|
||||
p = kmalloc(fw->size, GFP_KERNEL);
|
||||
reset = 1;
|
||||
/*stop the CPU*/
|
||||
tbs5931_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5931_WRITE_MSG);
|
||||
tbs5931_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5931_WRITE_MSG);
|
||||
|
||||
if (p != NULL) {
|
||||
memcpy(p, fw->data, fw->size);
|
||||
for (i = 0; i < fw->size; i += 0x40) {
|
||||
b = (u8 *) p + i;
|
||||
if (tbs5931_op_rw(dev, 0xa0, i, 0, b , 0x40,
|
||||
TBS5931_WRITE_MSG) != 0x40) {
|
||||
err("error while transferring firmware");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* restart the CPU */
|
||||
reset = 0;
|
||||
if (ret || tbs5931_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
|
||||
TBS5931_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (ret || tbs5931_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
|
||||
TBS5931_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
msleep(100);
|
||||
kfree(p);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct dvb_usb_device_properties tbs5931_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.firmware = "dvb-usb-id5931.fw",
|
||||
.size_of_priv = sizeof(struct tbs5931_state),
|
||||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &tbs5931_i2c_algo,
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.num_adapters = 1,
|
||||
.download_firmware = tbs5931_load_firmware,
|
||||
.read_mac_address = tbs5931_read_mac_address,
|
||||
.adapter = {{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = tbs5931_frontend_attach,
|
||||
.streaming_ctrl = NULL,
|
||||
.tuner_attach = NULL,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
}},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{"TurboSight TBS 5930 lite DVB-S/S2",
|
||||
{&tbs5931_table[0], NULL},
|
||||
{NULL},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int tbs5931_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
if (0 == dvb_usb_device_init(intf, &tbs5931_properties,
|
||||
THIS_MODULE, NULL, adapter_nr)) {
|
||||
return 0;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
static struct usb_driver tbs5931_driver = {
|
||||
.name = "tbs5931",
|
||||
.probe = tbs5931_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.id_table = tbs5931_table,
|
||||
};
|
||||
|
||||
static int __init tbs5931_module_init(void)
|
||||
{
|
||||
int ret = usb_register(&tbs5931_driver);
|
||||
if (ret)
|
||||
err("usb_register failed. Error number %d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit tbs5931_module_exit(void)
|
||||
{
|
||||
usb_deregister(&tbs5931_driver);
|
||||
}
|
||||
|
||||
module_init(tbs5931_module_init);
|
||||
module_exit(tbs5931_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Davin zhang<Davin@tbsdtv.com>");
|
||||
MODULE_DESCRIPTION("TurboSight TBS 5931/5903lite driver");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL");
|
||||
/*
|
||||
* TurboSight TBS 5930 lite driver
|
||||
*
|
||||
* Copyright (c) 2017 Davin <davin@tbsdtv.com>
|
||||
*
|
||||
* 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, version 2.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/version.h>
|
||||
#include "tbs5931.h"
|
||||
#include "gx1133.h"
|
||||
#include "tas2101.h"
|
||||
#include "av201x.h"
|
||||
|
||||
#define TBS5931_READ_MSG 0
|
||||
#define TBS5931_WRITE_MSG 1
|
||||
|
||||
#define TBS5931_RC_QUERY (0x1a00)
|
||||
#define TBS5931_VOLTAGE_CTRL (0x1800)
|
||||
|
||||
struct tbs5931_state {
|
||||
u8 initialized;
|
||||
};
|
||||
|
||||
|
||||
static struct tas2101_config gx1132_cfg = {
|
||||
.i2c_address = 0x60,
|
||||
.id = ID_TAS2101,
|
||||
.init = {0x10, 0x32, 0x54, 0x76, 0xA8, 0x9B, 0x33},
|
||||
.init2 = 0,
|
||||
|
||||
};
|
||||
|
||||
static struct gx1133_config gx1133_cfg = {
|
||||
.i2c_address = 0x52,
|
||||
.ts_mode = 0,
|
||||
.ts_cfg = {data_0,data_1,data_2,data_3,data_4,data_5,data_6, \
|
||||
data_7,ts_sync,ts_err,ts_clk,ts_valid},
|
||||
};
|
||||
|
||||
static struct av201x_config av201x_cfg = {
|
||||
.i2c_address = 0x62,
|
||||
.id = ID_AV2012,
|
||||
.xtal_freq = 27000, /* kHz */
|
||||
};
|
||||
|
||||
|
||||
/* debug */
|
||||
static int dvb_usb_tbs5931_debug;
|
||||
module_param_named(debug, dvb_usb_tbs5931_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "set debugging level (1=info 2=xfer (or-able))."
|
||||
DVB_USB_DEBUG_STATUS);
|
||||
|
||||
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
|
||||
|
||||
static int tbs5931_op_rw(struct usb_device *dev, u8 request, u16 value,
|
||||
u16 index, u8 * data, u16 len, int flags)
|
||||
{
|
||||
int ret;
|
||||
void *u8buf;
|
||||
|
||||
unsigned int pipe = (flags == TBS5931_READ_MSG) ?
|
||||
usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0);
|
||||
u8 request_type = (flags == TBS5931_READ_MSG) ? USB_DIR_IN : USB_DIR_OUT;
|
||||
u8buf = kmalloc(len, GFP_KERNEL);
|
||||
if (!u8buf)
|
||||
return -ENOMEM;
|
||||
|
||||
if (flags == TBS5931_WRITE_MSG)
|
||||
memcpy(u8buf, data, len);
|
||||
ret = usb_control_msg(dev, pipe, request, request_type | USB_TYPE_VENDOR,
|
||||
value, index , u8buf, len, 2000);
|
||||
|
||||
if (flags == TBS5931_READ_MSG)
|
||||
memcpy(data, u8buf, len);
|
||||
kfree(u8buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* I2C */
|
||||
static int tbs5931_i2c_transfer(struct i2c_adapter *adap,
|
||||
struct i2c_msg msg[], int num)
|
||||
{
|
||||
struct dvb_usb_device *d = i2c_get_adapdata(adap);
|
||||
int i = 0;
|
||||
u8 buf6[35];
|
||||
u8 inbuf[35];
|
||||
|
||||
if (!d)
|
||||
return -ENODEV;
|
||||
if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
switch (num) {
|
||||
case 2:
|
||||
switch(msg[0].addr){
|
||||
case 0x60:
|
||||
case 0x62:
|
||||
buf6[0]=msg[1].len;//lenth
|
||||
buf6[1]=msg[0].addr<<1;//demod addr
|
||||
//register
|
||||
buf6[2] = msg[0].buf[0];
|
||||
|
||||
tbs5931_op_rw(d->udev, 0x90, 0, 0,
|
||||
buf6, 3, TBS5931_WRITE_MSG);
|
||||
msleep(1);
|
||||
tbs5931_op_rw(d->udev, 0x91, 0, 0,
|
||||
inbuf, buf6[0], TBS5931_READ_MSG);
|
||||
memcpy(msg[1].buf, inbuf, msg[1].len);
|
||||
break;
|
||||
case 0x52:
|
||||
buf6[0]=msg[1].len;//lenth
|
||||
buf6[1]=msg[0].addr<<1;//demod addr
|
||||
//register
|
||||
memcpy(buf6+2,msg[0].buf,msg[0].len);
|
||||
|
||||
tbs5931_op_rw(d->udev, 0x92, 0, 0,
|
||||
buf6, msg[0].len+2, TBS5931_WRITE_MSG);
|
||||
msleep(1);
|
||||
tbs5931_op_rw(d->udev, 0x91, 0, 0,
|
||||
inbuf, msg[1].len, TBS5931_READ_MSG);
|
||||
|
||||
memcpy(msg[1].buf, inbuf, msg[1].len);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
buf6[0] = msg[0].len+1;//lenth
|
||||
buf6[1] = msg[0].addr<<1;//addr
|
||||
for(i=0;i<msg[0].len;i++) {
|
||||
buf6[2+i] = msg[0].buf[i];//register
|
||||
}
|
||||
tbs5931_op_rw(d->udev, 0x80, 0, 0,
|
||||
buf6, msg[0].len+2, TBS5931_WRITE_MSG);
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&d->i2c_mutex);
|
||||
return num;
|
||||
}
|
||||
|
||||
static u32 tbs5931_i2c_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_I2C;
|
||||
}
|
||||
|
||||
static struct i2c_algorithm tbs5931_i2c_algo = {
|
||||
.master_xfer = tbs5931_i2c_transfer,
|
||||
.functionality = tbs5931_i2c_func,
|
||||
};
|
||||
|
||||
static int tbs5931_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
|
||||
{
|
||||
int i,ret;
|
||||
u8 ibuf[3] = {0, 0,0};
|
||||
u8 eeprom[256], eepromline[16];
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
ibuf[0]=1;//lenth
|
||||
ibuf[1]=0xA0;//eeprom addr
|
||||
ibuf[2]=i;//register
|
||||
ret = tbs5931_op_rw(d->udev, 0x90, 0, 0,
|
||||
ibuf, 3, TBS5931_WRITE_MSG);
|
||||
ret = tbs5931_op_rw(d->udev, 0x91, 0, 0,
|
||||
ibuf, 1, TBS5931_READ_MSG);
|
||||
if (ret < 0) {
|
||||
err("read eeprom failed.");
|
||||
return -1;
|
||||
} else {
|
||||
eepromline[i%16] = ibuf[0];
|
||||
eeprom[i] = ibuf[0];
|
||||
}
|
||||
|
||||
if ((i % 16) == 15) {
|
||||
deb_xfer("%02x: ", i - 15);
|
||||
debug_dump(eepromline, 16, deb_xfer);
|
||||
}
|
||||
}
|
||||
memcpy(mac, eeprom + 16, 6);
|
||||
return 0;
|
||||
};
|
||||
|
||||
static struct dvb_usb_device_properties tbs5931_properties;
|
||||
|
||||
static int tbs5931_frontend_attach(struct dvb_usb_adapter *adap)
|
||||
{
|
||||
struct dvb_usb_device *d = adap->dev;
|
||||
|
||||
u8 buf[20];
|
||||
u8 a = 0,b = 0;
|
||||
u16 id;
|
||||
//read the id to deceted the chip
|
||||
buf[0]= 1;//lenth
|
||||
buf[1]= 0xC0;//demod addr
|
||||
//register
|
||||
buf[2] = 0x01;
|
||||
tbs5931_op_rw(d->udev, 0x90, 0, 0,
|
||||
buf, 3, TBS5931_WRITE_MSG);
|
||||
msleep(1);
|
||||
tbs5931_op_rw(d->udev, 0x91, 0, 0,
|
||||
&a, buf[0], TBS5931_READ_MSG);
|
||||
msleep(5);
|
||||
|
||||
buf[2] = 0x00;
|
||||
tbs5931_op_rw(d->udev, 0x90, 0, 0,
|
||||
buf, 3, TBS5931_WRITE_MSG);
|
||||
msleep(1);
|
||||
tbs5931_op_rw(d->udev, 0x91, 0, 0,
|
||||
&b, buf[0], TBS5931_READ_MSG);
|
||||
id = (b<<8|a);
|
||||
if(id==0x444c){ //gx1132
|
||||
adap->fe_adap->fe = dvb_attach(tas2101_attach,&gx1132_cfg,&d->i2c_adap);
|
||||
if(adap->fe_adap->fe ==NULL)
|
||||
goto err;
|
||||
|
||||
if(dvb_attach(av201x_attach,adap->fe_adap->fe,&av201x_cfg,
|
||||
tas2101_get_i2c_adapter(adap->fe_adap->fe,2))==NULL){
|
||||
dvb_frontend_detach(adap->fe_adap->fe);
|
||||
adap->fe_adap->fe = NULL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
else{
|
||||
id = 0;
|
||||
a = 0;
|
||||
b = 0;
|
||||
|
||||
buf[0]= 1;//lenth
|
||||
buf[1]= 0xA4;//demod addr
|
||||
//register
|
||||
buf[2] = 0xff;
|
||||
buf[3] = 0xf1;
|
||||
tbs5931_op_rw(d->udev, 0x92, 0, 0,
|
||||
buf, 4, TBS5931_WRITE_MSG);
|
||||
msleep(1);
|
||||
tbs5931_op_rw(d->udev, 0x91, 0, 0,
|
||||
&a, buf[0], TBS5931_READ_MSG);
|
||||
msleep(5);
|
||||
|
||||
buf[3] = 0xf0;
|
||||
tbs5931_op_rw(d->udev, 0x92, 0, 0,
|
||||
buf, 4, TBS5931_WRITE_MSG);
|
||||
msleep(1);
|
||||
tbs5931_op_rw(d->udev, 0x91, 0, 0,
|
||||
&b, buf[0], TBS5931_READ_MSG);
|
||||
|
||||
id = (b<<8|a);
|
||||
if(id==0x444c){ //gx1133
|
||||
adap->fe_adap->fe = dvb_attach(gx1133_attach,&gx1133_cfg,&d->i2c_adap);
|
||||
if(adap->fe_adap->fe ==NULL)
|
||||
goto err;
|
||||
|
||||
if(dvb_attach(av201x_attach,adap->fe_adap->fe,&av201x_cfg,
|
||||
gx1133_get_i2c_adapter(adap->fe_adap->fe,2))==NULL){
|
||||
dvb_frontend_detach(adap->fe_adap->fe);
|
||||
adap->fe_adap->fe = NULL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
goto err;
|
||||
|
||||
}
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = 0;
|
||||
tbs5931_op_rw(d->udev, 0xb7, 0, 0,
|
||||
buf, 2, TBS5931_WRITE_MSG);
|
||||
|
||||
buf[0] = 8;
|
||||
buf[1] = 1;
|
||||
tbs5931_op_rw(d->udev, 0x8a, 0, 0,
|
||||
buf, 2, TBS5931_WRITE_MSG);
|
||||
msleep(10);
|
||||
|
||||
strscpy(adap->fe_adap->fe->ops.info.name,d->props.devices[0].name,52);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static struct usb_device_id tbs5931_table[] = {
|
||||
{USB_DEVICE(0x734c, 0x5931)},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(usb, tbs5931_table);
|
||||
|
||||
static int tbs5931_load_firmware(struct usb_device *dev,
|
||||
const struct firmware *frmwr)
|
||||
{
|
||||
u8 *b, *p;
|
||||
int ret = 0, i;
|
||||
u8 reset;
|
||||
const struct firmware *fw;
|
||||
switch (dev->descriptor.idProduct) {
|
||||
case 0x5931:
|
||||
ret = request_firmware(&fw, tbs5931_properties.firmware, &dev->dev);
|
||||
if (ret != 0) {
|
||||
err("did not find the firmware file. (%s) "
|
||||
"Please see linux/Documentation/dvb/ for more details "
|
||||
"on firmware-problems.", tbs5931_properties.firmware);
|
||||
return ret;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fw = frmwr;
|
||||
break;
|
||||
}
|
||||
info("start downloading TBS5931 firmware");
|
||||
p = kmalloc(fw->size, GFP_KERNEL);
|
||||
reset = 1;
|
||||
/*stop the CPU*/
|
||||
tbs5931_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1, TBS5931_WRITE_MSG);
|
||||
tbs5931_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1, TBS5931_WRITE_MSG);
|
||||
|
||||
if (p != NULL) {
|
||||
memcpy(p, fw->data, fw->size);
|
||||
for (i = 0; i < fw->size; i += 0x40) {
|
||||
b = (u8 *) p + i;
|
||||
if (tbs5931_op_rw(dev, 0xa0, i, 0, b , 0x40,
|
||||
TBS5931_WRITE_MSG) != 0x40) {
|
||||
err("error while transferring firmware");
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* restart the CPU */
|
||||
reset = 0;
|
||||
if (ret || tbs5931_op_rw(dev, 0xa0, 0x7f92, 0, &reset, 1,
|
||||
TBS5931_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
if (ret || tbs5931_op_rw(dev, 0xa0, 0xe600, 0, &reset, 1,
|
||||
TBS5931_WRITE_MSG) != 1) {
|
||||
err("could not restart the USB controller CPU.");
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
msleep(100);
|
||||
kfree(p);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct dvb_usb_device_properties tbs5931_properties = {
|
||||
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
|
||||
.usb_ctrl = DEVICE_SPECIFIC,
|
||||
.firmware = "dvb-usb-id5931.fw",
|
||||
.size_of_priv = sizeof(struct tbs5931_state),
|
||||
.no_reconnect = 1,
|
||||
|
||||
.i2c_algo = &tbs5931_i2c_algo,
|
||||
|
||||
.generic_bulk_ctrl_endpoint = 0x81,
|
||||
/* parameter for the MPEG2-data transfer */
|
||||
.num_adapters = 1,
|
||||
.download_firmware = tbs5931_load_firmware,
|
||||
.read_mac_address = tbs5931_read_mac_address,
|
||||
.adapter = {{
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
.frontend_attach = tbs5931_frontend_attach,
|
||||
.streaming_ctrl = NULL,
|
||||
.tuner_attach = NULL,
|
||||
.stream = {
|
||||
.type = USB_BULK,
|
||||
.count = 8,
|
||||
.endpoint = 0x82,
|
||||
.u = {
|
||||
.bulk = {
|
||||
.buffersize = 4096,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
}},
|
||||
|
||||
.num_device_descs = 1,
|
||||
.devices = {
|
||||
{"TurboSight TBS 5930 lite DVB-S/S2",
|
||||
{&tbs5931_table[0], NULL},
|
||||
{NULL},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int tbs5931_probe(struct usb_interface *intf,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
if (0 == dvb_usb_device_init(intf, &tbs5931_properties,
|
||||
THIS_MODULE, NULL, adapter_nr)) {
|
||||
return 0;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
static struct usb_driver tbs5931_driver = {
|
||||
.name = "tbs5931",
|
||||
.probe = tbs5931_probe,
|
||||
.disconnect = dvb_usb_device_exit,
|
||||
.id_table = tbs5931_table,
|
||||
};
|
||||
|
||||
static int __init tbs5931_module_init(void)
|
||||
{
|
||||
int ret = usb_register(&tbs5931_driver);
|
||||
if (ret)
|
||||
err("usb_register failed. Error number %d", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit tbs5931_module_exit(void)
|
||||
{
|
||||
usb_deregister(&tbs5931_driver);
|
||||
}
|
||||
|
||||
module_init(tbs5931_module_init);
|
||||
module_exit(tbs5931_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Davin zhang<Davin@tbsdtv.com>");
|
||||
MODULE_DESCRIPTION("TurboSight TBS 5931/5903lite driver");
|
||||
MODULE_VERSION("1.0");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@@ -1,8 +1,8 @@
|
||||
#ifndef _TBS5931_H_
|
||||
#define _TBS5931_H_
|
||||
|
||||
#define DVB_USB_LOG_PREFIX "tbs5931"
|
||||
#include "dvb-usb.h"
|
||||
|
||||
#define deb_xfer(args...) dprintk(dvb_usb_tbs5931_debug, 0x02, args)
|
||||
#endif
|
||||
#ifndef _TBS5931_H_
|
||||
#define _TBS5931_H_
|
||||
|
||||
#define DVB_USB_LOG_PREFIX "tbs5931"
|
||||
#include "dvb-usb.h"
|
||||
|
||||
#define deb_xfer(args...) dprintk(dvb_usb_tbs5931_debug, 0x02, args)
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user