提交 4d1f413e 编写于 作者: H HIRANO Takahito 提交者: Mauro Carvalho Chehab

V4L/DVB: pt1: Support Earthsoft PT2

Support Earthsoft PT2.
Signed-off-by: NHIRANO Takahito <hiranotaka@zng.info>
Signed-off-by: NMauro Carvalho Chehab <mchehab@redhat.com>
上级 2f790884
/* /*
* driver for Earthsoft PT1 * driver for Earthsoft PT1/PT2
* *
* Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
* *
...@@ -77,6 +77,10 @@ struct pt1 { ...@@ -77,6 +77,10 @@ struct pt1 {
struct pt1_adapter *adaps[PT1_NR_ADAPS]; struct pt1_adapter *adaps[PT1_NR_ADAPS];
struct pt1_table *tables; struct pt1_table *tables;
struct task_struct *kthread; struct task_struct *kthread;
struct mutex lock;
int power;
int reset;
}; };
struct pt1_adapter { struct pt1_adapter {
...@@ -95,6 +99,11 @@ struct pt1_adapter { ...@@ -95,6 +99,11 @@ struct pt1_adapter {
struct dvb_frontend *fe; struct dvb_frontend *fe;
int (*orig_set_voltage)(struct dvb_frontend *fe, int (*orig_set_voltage)(struct dvb_frontend *fe,
fe_sec_voltage_t voltage); fe_sec_voltage_t voltage);
int (*orig_sleep)(struct dvb_frontend *fe);
int (*orig_init)(struct dvb_frontend *fe);
fe_sec_voltage_t voltage;
int sleep;
}; };
#define pt1_printk(level, pt1, format, arg...) \ #define pt1_printk(level, pt1, format, arg...) \
...@@ -219,8 +228,10 @@ static int pt1_do_enable_ram(struct pt1 *pt1) ...@@ -219,8 +228,10 @@ static int pt1_do_enable_ram(struct pt1 *pt1)
static int pt1_enable_ram(struct pt1 *pt1) static int pt1_enable_ram(struct pt1 *pt1)
{ {
int i, ret; int i, ret;
int phase;
schedule_timeout_uninterruptible((HZ + 999) / 1000); schedule_timeout_uninterruptible((HZ + 999) / 1000);
for (i = 0; i < 10; i++) { phase = pt1->pdev->device == 0x211a ? 128 : 166;
for (i = 0; i < phase; i++) {
ret = pt1_do_enable_ram(pt1); ret = pt1_do_enable_ram(pt1);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -485,33 +496,47 @@ static int pt1_stop_feed(struct dvb_demux_feed *feed) ...@@ -485,33 +496,47 @@ static int pt1_stop_feed(struct dvb_demux_feed *feed)
} }
static void static void
pt1_set_power(struct pt1 *pt1, int power, int lnb, int reset) pt1_update_power(struct pt1 *pt1)
{ {
pt1_write_reg(pt1, 1, power | lnb << 1 | !reset << 3); int bits;
int i;
struct pt1_adapter *adap;
static const int sleep_bits[] = {
1 << 4,
1 << 6 | 1 << 7,
1 << 5,
1 << 6 | 1 << 8,
};
bits = pt1->power | !pt1->reset << 3;
mutex_lock(&pt1->lock);
for (i = 0; i < PT1_NR_ADAPS; i++) {
adap = pt1->adaps[i];
switch (adap->voltage) {
case SEC_VOLTAGE_13: /* actually 11V */
bits |= 1 << 1;
break;
case SEC_VOLTAGE_18: /* actually 15V */
bits |= 1 << 1 | 1 << 2;
break;
default:
break;
}
/* XXX: The bits should be changed depending on adap->sleep. */
bits |= sleep_bits[i];
}
pt1_write_reg(pt1, 1, bits);
mutex_unlock(&pt1->lock);
} }
static int pt1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) static int pt1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
{ {
struct pt1_adapter *adap; struct pt1_adapter *adap;
int lnb;
adap = container_of(fe->dvb, struct pt1_adapter, adap); adap = container_of(fe->dvb, struct pt1_adapter, adap);
adap->voltage = voltage;
switch (voltage) { pt1_update_power(adap->pt1);
case SEC_VOLTAGE_13: /* actually 11V */
lnb = 2;
break;
case SEC_VOLTAGE_18: /* actually 15V */
lnb = 3;
break;
case SEC_VOLTAGE_OFF:
lnb = 0;
break;
default:
return -EINVAL;
}
pt1_set_power(adap->pt1, 1, lnb, 0);
if (adap->orig_set_voltage) if (adap->orig_set_voltage)
return adap->orig_set_voltage(fe, voltage); return adap->orig_set_voltage(fe, voltage);
...@@ -519,9 +544,37 @@ static int pt1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) ...@@ -519,9 +544,37 @@ static int pt1_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
return 0; return 0;
} }
static int pt1_sleep(struct dvb_frontend *fe)
{
struct pt1_adapter *adap;
adap = container_of(fe->dvb, struct pt1_adapter, adap);
adap->sleep = 1;
pt1_update_power(adap->pt1);
if (adap->orig_sleep)
return adap->orig_sleep(fe);
else
return 0;
}
static int pt1_wakeup(struct dvb_frontend *fe)
{
struct pt1_adapter *adap;
adap = container_of(fe->dvb, struct pt1_adapter, adap);
adap->sleep = 0;
pt1_update_power(adap->pt1);
schedule_timeout_uninterruptible((HZ + 999) / 1000);
if (adap->orig_init)
return adap->orig_init(fe);
else
return 0;
}
static void pt1_free_adapter(struct pt1_adapter *adap) static void pt1_free_adapter(struct pt1_adapter *adap)
{ {
dvb_unregister_frontend(adap->fe);
dvb_net_release(&adap->net); dvb_net_release(&adap->net);
adap->demux.dmx.close(&adap->demux.dmx); adap->demux.dmx.close(&adap->demux.dmx);
dvb_dmxdev_release(&adap->dmxdev); dvb_dmxdev_release(&adap->dmxdev);
...@@ -534,7 +587,7 @@ static void pt1_free_adapter(struct pt1_adapter *adap) ...@@ -534,7 +587,7 @@ static void pt1_free_adapter(struct pt1_adapter *adap)
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
static struct pt1_adapter * static struct pt1_adapter *
pt1_alloc_adapter(struct pt1 *pt1, struct dvb_frontend *fe) pt1_alloc_adapter(struct pt1 *pt1)
{ {
struct pt1_adapter *adap; struct pt1_adapter *adap;
void *buf; void *buf;
...@@ -551,8 +604,8 @@ pt1_alloc_adapter(struct pt1 *pt1, struct dvb_frontend *fe) ...@@ -551,8 +604,8 @@ pt1_alloc_adapter(struct pt1 *pt1, struct dvb_frontend *fe)
adap->pt1 = pt1; adap->pt1 = pt1;
adap->orig_set_voltage = fe->ops.set_voltage; adap->voltage = SEC_VOLTAGE_OFF;
fe->ops.set_voltage = pt1_set_voltage; adap->sleep = 1;
buf = (u8 *)__get_free_page(GFP_KERNEL); buf = (u8 *)__get_free_page(GFP_KERNEL);
if (!buf) { if (!buf) {
...@@ -593,17 +646,8 @@ pt1_alloc_adapter(struct pt1 *pt1, struct dvb_frontend *fe) ...@@ -593,17 +646,8 @@ pt1_alloc_adapter(struct pt1 *pt1, struct dvb_frontend *fe)
dvb_net_init(dvb_adap, &adap->net, &demux->dmx); dvb_net_init(dvb_adap, &adap->net, &demux->dmx);
ret = dvb_register_frontend(dvb_adap, fe);
if (ret < 0)
goto err_net_release;
adap->fe = fe;
return adap; return adap;
err_net_release:
dvb_net_release(&adap->net);
adap->demux.dmx.close(&adap->demux.dmx);
dvb_dmxdev_release(&adap->dmxdev);
err_dmx_release: err_dmx_release:
dvb_dmx_release(demux); dvb_dmx_release(demux);
err_unregister_adapter: err_unregister_adapter:
...@@ -623,6 +667,62 @@ static void pt1_cleanup_adapters(struct pt1 *pt1) ...@@ -623,6 +667,62 @@ static void pt1_cleanup_adapters(struct pt1 *pt1)
pt1_free_adapter(pt1->adaps[i]); pt1_free_adapter(pt1->adaps[i]);
} }
static int pt1_init_adapters(struct pt1 *pt1)
{
int i;
struct pt1_adapter *adap;
int ret;
for (i = 0; i < PT1_NR_ADAPS; i++) {
adap = pt1_alloc_adapter(pt1);
if (IS_ERR(adap)) {
ret = PTR_ERR(adap);
goto err;
}
adap->index = i;
pt1->adaps[i] = adap;
}
return 0;
err:
while (i--)
pt1_free_adapter(pt1->adaps[i]);
return ret;
}
static void pt1_cleanup_frontend(struct pt1_adapter *adap)
{
dvb_unregister_frontend(adap->fe);
}
static int pt1_init_frontend(struct pt1_adapter *adap, struct dvb_frontend *fe)
{
int ret;
adap->orig_set_voltage = fe->ops.set_voltage;
adap->orig_sleep = fe->ops.sleep;
adap->orig_init = fe->ops.init;
fe->ops.set_voltage = pt1_set_voltage;
fe->ops.sleep = pt1_sleep;
fe->ops.init = pt1_wakeup;
ret = dvb_register_frontend(&adap->adap, fe);
if (ret < 0)
return ret;
adap->fe = fe;
return 0;
}
static void pt1_cleanup_frontends(struct pt1 *pt1)
{
int i;
for (i = 0; i < PT1_NR_ADAPS; i++)
pt1_cleanup_frontend(pt1->adaps[i]);
}
struct pt1_config { struct pt1_config {
struct va1j5jf8007s_config va1j5jf8007s_config; struct va1j5jf8007s_config va1j5jf8007s_config;
struct va1j5jf8007t_config va1j5jf8007t_config; struct va1j5jf8007t_config va1j5jf8007t_config;
...@@ -630,29 +730,63 @@ struct pt1_config { ...@@ -630,29 +730,63 @@ struct pt1_config {
static const struct pt1_config pt1_configs[2] = { static const struct pt1_config pt1_configs[2] = {
{ {
{ .demod_address = 0x1b }, {
{ .demod_address = 0x1a }, .demod_address = 0x1b,
.frequency = VA1J5JF8007S_20MHZ,
},
{
.demod_address = 0x1a,
.frequency = VA1J5JF8007T_20MHZ,
},
}, { }, {
{ .demod_address = 0x19 }, {
{ .demod_address = 0x18 }, .demod_address = 0x19,
.frequency = VA1J5JF8007S_20MHZ,
},
{
.demod_address = 0x18,
.frequency = VA1J5JF8007T_20MHZ,
},
}, },
}; };
static int pt1_init_adapters(struct pt1 *pt1) static const struct pt1_config pt2_configs[2] = {
{
{
.demod_address = 0x1b,
.frequency = VA1J5JF8007S_25MHZ,
},
{
.demod_address = 0x1a,
.frequency = VA1J5JF8007T_25MHZ,
},
}, {
{
.demod_address = 0x19,
.frequency = VA1J5JF8007S_25MHZ,
},
{
.demod_address = 0x18,
.frequency = VA1J5JF8007T_25MHZ,
},
},
};
static int pt1_init_frontends(struct pt1 *pt1)
{ {
int i, j; int i, j;
struct i2c_adapter *i2c_adap; struct i2c_adapter *i2c_adap;
const struct pt1_config *config; const struct pt1_config *configs, *config;
struct dvb_frontend *fe[4]; struct dvb_frontend *fe[4];
struct pt1_adapter *adap;
int ret; int ret;
i = 0; i = 0;
j = 0; j = 0;
i2c_adap = &pt1->i2c_adap; i2c_adap = &pt1->i2c_adap;
configs = pt1->pdev->device == 0x211a ? pt1_configs : pt2_configs;
do { do {
config = &pt1_configs[i / 2]; config = &configs[i / 2];
fe[i] = va1j5jf8007s_attach(&config->va1j5jf8007s_config, fe[i] = va1j5jf8007s_attach(&config->va1j5jf8007s_config,
i2c_adap); i2c_adap);
...@@ -681,11 +815,9 @@ static int pt1_init_adapters(struct pt1 *pt1) ...@@ -681,11 +815,9 @@ static int pt1_init_adapters(struct pt1 *pt1)
} while (i < 4); } while (i < 4);
do { do {
adap = pt1_alloc_adapter(pt1, fe[j]); ret = pt1_init_frontend(pt1->adaps[j], fe[j]);
if (IS_ERR(adap)) if (ret < 0)
goto err; goto err;
adap->index = j;
pt1->adaps[j] = adap;
} while (++j < 4); } while (++j < 4);
return 0; return 0;
...@@ -695,7 +827,7 @@ static int pt1_init_adapters(struct pt1 *pt1) ...@@ -695,7 +827,7 @@ static int pt1_init_adapters(struct pt1 *pt1)
fe[i]->ops.release(fe[i]); fe[i]->ops.release(fe[i]);
while (j--) while (j--)
pt1_free_adapter(pt1->adaps[j]); dvb_unregister_frontend(fe[j]);
return ret; return ret;
} }
...@@ -890,9 +1022,12 @@ static void __devexit pt1_remove(struct pci_dev *pdev) ...@@ -890,9 +1022,12 @@ static void __devexit pt1_remove(struct pci_dev *pdev)
kthread_stop(pt1->kthread); kthread_stop(pt1->kthread);
pt1_cleanup_tables(pt1); pt1_cleanup_tables(pt1);
pt1_cleanup_adapters(pt1); pt1_cleanup_frontends(pt1);
pt1_disable_ram(pt1); pt1_disable_ram(pt1);
pt1_set_power(pt1, 0, 0, 1); pt1->power = 0;
pt1->reset = 1;
pt1_update_power(pt1);
pt1_cleanup_adapters(pt1);
i2c_del_adapter(&pt1->i2c_adap); i2c_del_adapter(&pt1->i2c_adap);
pci_set_drvdata(pdev, NULL); pci_set_drvdata(pdev, NULL);
kfree(pt1); kfree(pt1);
...@@ -936,10 +1071,21 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -936,10 +1071,21 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_pci_iounmap; goto err_pci_iounmap;
} }
mutex_init(&pt1->lock);
pt1->pdev = pdev; pt1->pdev = pdev;
pt1->regs = regs; pt1->regs = regs;
pci_set_drvdata(pdev, pt1); pci_set_drvdata(pdev, pt1);
ret = pt1_init_adapters(pt1);
if (ret < 0)
goto err_kfree;
mutex_init(&pt1->lock);
pt1->power = 0;
pt1->reset = 1;
pt1_update_power(pt1);
i2c_adap = &pt1->i2c_adap; i2c_adap = &pt1->i2c_adap;
i2c_adap->class = I2C_CLASS_TV_DIGITAL; i2c_adap->class = I2C_CLASS_TV_DIGITAL;
i2c_adap->algo = &pt1_i2c_algo; i2c_adap->algo = &pt1_i2c_algo;
...@@ -948,9 +1094,7 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -948,9 +1094,7 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
i2c_set_adapdata(i2c_adap, pt1); i2c_set_adapdata(i2c_adap, pt1);
ret = i2c_add_adapter(i2c_adap); ret = i2c_add_adapter(i2c_adap);
if (ret < 0) if (ret < 0)
goto err_kfree; goto err_pt1_cleanup_adapters;
pt1_set_power(pt1, 0, 0, 1);
pt1_i2c_init(pt1); pt1_i2c_init(pt1);
pt1_i2c_wait(pt1); pt1_i2c_wait(pt1);
...@@ -979,19 +1123,21 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -979,19 +1123,21 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
pt1_init_streams(pt1); pt1_init_streams(pt1);
pt1_set_power(pt1, 1, 0, 1); pt1->power = 1;
pt1_update_power(pt1);
schedule_timeout_uninterruptible((HZ + 49) / 50); schedule_timeout_uninterruptible((HZ + 49) / 50);
pt1_set_power(pt1, 1, 0, 0); pt1->reset = 0;
pt1_update_power(pt1);
schedule_timeout_uninterruptible((HZ + 999) / 1000); schedule_timeout_uninterruptible((HZ + 999) / 1000);
ret = pt1_init_adapters(pt1); ret = pt1_init_frontends(pt1);
if (ret < 0) if (ret < 0)
goto err_pt1_disable_ram; goto err_pt1_disable_ram;
ret = pt1_init_tables(pt1); ret = pt1_init_tables(pt1);
if (ret < 0) if (ret < 0)
goto err_pt1_cleanup_adapters; goto err_pt1_cleanup_frontends;
kthread = kthread_run(pt1_thread, pt1, "pt1"); kthread = kthread_run(pt1_thread, pt1, "pt1");
if (IS_ERR(kthread)) { if (IS_ERR(kthread)) {
...@@ -1004,11 +1150,15 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1004,11 +1150,15 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
err_pt1_cleanup_tables: err_pt1_cleanup_tables:
pt1_cleanup_tables(pt1); pt1_cleanup_tables(pt1);
err_pt1_cleanup_adapters: err_pt1_cleanup_frontends:
pt1_cleanup_adapters(pt1); pt1_cleanup_frontends(pt1);
err_pt1_disable_ram: err_pt1_disable_ram:
pt1_disable_ram(pt1); pt1_disable_ram(pt1);
pt1_set_power(pt1, 0, 0, 1); pt1->power = 0;
pt1->reset = 1;
pt1_update_power(pt1);
err_pt1_cleanup_adapters:
pt1_cleanup_adapters(pt1);
err_i2c_del_adapter: err_i2c_del_adapter:
i2c_del_adapter(i2c_adap); i2c_del_adapter(i2c_adap);
err_kfree: err_kfree:
...@@ -1027,6 +1177,7 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1027,6 +1177,7 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
static struct pci_device_id pt1_id_table[] = { static struct pci_device_id pt1_id_table[] = {
{ PCI_DEVICE(0x10ee, 0x211a) }, { PCI_DEVICE(0x10ee, 0x211a) },
{ PCI_DEVICE(0x10ee, 0x222a) },
{ }, { },
}; };
MODULE_DEVICE_TABLE(pci, pt1_id_table); MODULE_DEVICE_TABLE(pci, pt1_id_table);
...@@ -1054,5 +1205,5 @@ module_init(pt1_init); ...@@ -1054,5 +1205,5 @@ module_init(pt1_init);
module_exit(pt1_cleanup); module_exit(pt1_cleanup);
MODULE_AUTHOR("Takahito HIRANO <hiranotaka@zng.info>"); MODULE_AUTHOR("Takahito HIRANO <hiranotaka@zng.info>");
MODULE_DESCRIPTION("Earthsoft PT1 Driver"); MODULE_DESCRIPTION("Earthsoft PT1/PT2 Driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* /*
* ISDB-S driver for VA1J5JF8007 * ISDB-S driver for VA1J5JF8007/VA1J5JF8011
* *
* Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
* *
...@@ -580,7 +580,7 @@ static void va1j5jf8007s_release(struct dvb_frontend *fe) ...@@ -580,7 +580,7 @@ static void va1j5jf8007s_release(struct dvb_frontend *fe)
static struct dvb_frontend_ops va1j5jf8007s_ops = { static struct dvb_frontend_ops va1j5jf8007s_ops = {
.info = { .info = {
.name = "VA1J5JF8007 ISDB-S", .name = "VA1J5JF8007/VA1J5JF8011 ISDB-S",
.type = FE_QPSK, .type = FE_QPSK,
.frequency_min = 950000, .frequency_min = 950000,
.frequency_max = 2150000, .frequency_max = 2150000,
...@@ -628,28 +628,50 @@ static int va1j5jf8007s_prepare_1(struct va1j5jf8007s_state *state) ...@@ -628,28 +628,50 @@ static int va1j5jf8007s_prepare_1(struct va1j5jf8007s_state *state)
return 0; return 0;
} }
static const u8 va1j5jf8007s_prepare_bufs[][2] = { static const u8 va1j5jf8007s_20mhz_prepare_bufs[][2] = {
{0x04, 0x02}, {0x0d, 0x55}, {0x11, 0x40}, {0x13, 0x80}, {0x17, 0x01}, {0x04, 0x02}, {0x0d, 0x55}, {0x11, 0x40}, {0x13, 0x80}, {0x17, 0x01},
{0x1c, 0x0a}, {0x1d, 0xaa}, {0x1e, 0x20}, {0x1f, 0x88}, {0x51, 0xb0}, {0x1c, 0x0a}, {0x1d, 0xaa}, {0x1e, 0x20}, {0x1f, 0x88}, {0x51, 0xb0},
{0x52, 0x89}, {0x53, 0xb3}, {0x5a, 0x2d}, {0x5b, 0xd3}, {0x85, 0x69}, {0x52, 0x89}, {0x53, 0xb3}, {0x5a, 0x2d}, {0x5b, 0xd3}, {0x85, 0x69},
{0x87, 0x04}, {0x8e, 0x02}, {0xa3, 0xf7}, {0xa5, 0xc0}, {0x87, 0x04}, {0x8e, 0x02}, {0xa3, 0xf7}, {0xa5, 0xc0},
}; };
static const u8 va1j5jf8007s_25mhz_prepare_bufs[][2] = {
{0x04, 0x02}, {0x11, 0x40}, {0x13, 0x80}, {0x17, 0x01}, {0x1c, 0x0a},
{0x1d, 0xaa}, {0x1e, 0x20}, {0x1f, 0x88}, {0x51, 0xb0}, {0x52, 0x89},
{0x53, 0xb3}, {0x5a, 0x2d}, {0x5b, 0xd3}, {0x85, 0x69}, {0x87, 0x04},
{0x8e, 0x26}, {0xa3, 0xf7}, {0xa5, 0xc0},
};
static int va1j5jf8007s_prepare_2(struct va1j5jf8007s_state *state) static int va1j5jf8007s_prepare_2(struct va1j5jf8007s_state *state)
{ {
const u8 (*bufs)[2];
int size;
u8 addr; u8 addr;
u8 buf[2]; u8 buf[2];
struct i2c_msg msg; struct i2c_msg msg;
int i; int i;
switch (state->config->frequency) {
case VA1J5JF8007S_20MHZ:
bufs = va1j5jf8007s_20mhz_prepare_bufs;
size = ARRAY_SIZE(va1j5jf8007s_20mhz_prepare_bufs);
break;
case VA1J5JF8007S_25MHZ:
bufs = va1j5jf8007s_25mhz_prepare_bufs;
size = ARRAY_SIZE(va1j5jf8007s_25mhz_prepare_bufs);
break;
default:
return -EINVAL;
}
addr = state->config->demod_address; addr = state->config->demod_address;
msg.addr = addr; msg.addr = addr;
msg.flags = 0; msg.flags = 0;
msg.len = 2; msg.len = 2;
msg.buf = buf; msg.buf = buf;
for (i = 0; i < ARRAY_SIZE(va1j5jf8007s_prepare_bufs); i++) { for (i = 0; i < size; i++) {
memcpy(buf, va1j5jf8007s_prepare_bufs[i], sizeof(buf)); memcpy(buf, bufs[i], sizeof(buf));
if (i2c_transfer(state->adap, &msg, 1) != 1) if (i2c_transfer(state->adap, &msg, 1) != 1)
return -EREMOTEIO; return -EREMOTEIO;
} }
......
/* /*
* ISDB-S driver for VA1J5JF8007 * ISDB-S driver for VA1J5JF8007/VA1J5JF8011
* *
* Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
* *
...@@ -24,8 +24,14 @@ ...@@ -24,8 +24,14 @@
#ifndef VA1J5JF8007S_H #ifndef VA1J5JF8007S_H
#define VA1J5JF8007S_H #define VA1J5JF8007S_H
enum va1j5jf8007s_frequency {
VA1J5JF8007S_20MHZ,
VA1J5JF8007S_25MHZ,
};
struct va1j5jf8007s_config { struct va1j5jf8007s_config {
u8 demod_address; u8 demod_address;
enum va1j5jf8007s_frequency frequency;
}; };
struct i2c_adapter; struct i2c_adapter;
......
/* /*
* ISDB-T driver for VA1J5JF8007 * ISDB-T driver for VA1J5JF8007/VA1J5JF8011
* *
* Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
* *
...@@ -429,7 +429,7 @@ static void va1j5jf8007t_release(struct dvb_frontend *fe) ...@@ -429,7 +429,7 @@ static void va1j5jf8007t_release(struct dvb_frontend *fe)
static struct dvb_frontend_ops va1j5jf8007t_ops = { static struct dvb_frontend_ops va1j5jf8007t_ops = {
.info = { .info = {
.name = "VA1J5JF8007 ISDB-T", .name = "VA1J5JF8007/VA1J5JF8011 ISDB-T",
.type = FE_OFDM, .type = FE_OFDM,
.frequency_min = 90000000, .frequency_min = 90000000,
.frequency_max = 770000000, .frequency_max = 770000000,
...@@ -448,29 +448,50 @@ static struct dvb_frontend_ops va1j5jf8007t_ops = { ...@@ -448,29 +448,50 @@ static struct dvb_frontend_ops va1j5jf8007t_ops = {
.release = va1j5jf8007t_release, .release = va1j5jf8007t_release,
}; };
static const u8 va1j5jf8007t_prepare_bufs[][2] = { static const u8 va1j5jf8007t_20mhz_prepare_bufs[][2] = {
{0x03, 0x90}, {0x14, 0x8f}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2}, {0x03, 0x90}, {0x14, 0x8f}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2},
{0x22, 0x83}, {0x31, 0x0d}, {0x32, 0xe0}, {0x39, 0xd3}, {0x3a, 0x00}, {0x22, 0x83}, {0x31, 0x0d}, {0x32, 0xe0}, {0x39, 0xd3}, {0x3a, 0x00},
{0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x02}, {0x76, 0x4e}, {0x77, 0x03}, {0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x02}, {0x76, 0x4e}, {0x77, 0x03},
{0xef, 0x01} {0xef, 0x01}
}; };
static const u8 va1j5jf8007t_25mhz_prepare_bufs[][2] = {
{0x03, 0x90}, {0x1c, 0x2a}, {0x1d, 0xa8}, {0x1e, 0xa2}, {0x22, 0x83},
{0x3a, 0x00}, {0x5c, 0x40}, {0x5f, 0x80}, {0x75, 0x0a}, {0x76, 0x4c},
{0x77, 0x03}, {0xef, 0x01}
};
int va1j5jf8007t_prepare(struct dvb_frontend *fe) int va1j5jf8007t_prepare(struct dvb_frontend *fe)
{ {
struct va1j5jf8007t_state *state; struct va1j5jf8007t_state *state;
const u8 (*bufs)[2];
int size;
u8 buf[2]; u8 buf[2];
struct i2c_msg msg; struct i2c_msg msg;
int i; int i;
state = fe->demodulator_priv; state = fe->demodulator_priv;
switch (state->config->frequency) {
case VA1J5JF8007T_20MHZ:
bufs = va1j5jf8007t_20mhz_prepare_bufs;
size = ARRAY_SIZE(va1j5jf8007t_20mhz_prepare_bufs);
break;
case VA1J5JF8007T_25MHZ:
bufs = va1j5jf8007t_25mhz_prepare_bufs;
size = ARRAY_SIZE(va1j5jf8007t_25mhz_prepare_bufs);
break;
default:
return -EINVAL;
}
msg.addr = state->config->demod_address; msg.addr = state->config->demod_address;
msg.flags = 0; msg.flags = 0;
msg.len = sizeof(buf); msg.len = sizeof(buf);
msg.buf = buf; msg.buf = buf;
for (i = 0; i < ARRAY_SIZE(va1j5jf8007t_prepare_bufs); i++) { for (i = 0; i < size; i++) {
memcpy(buf, va1j5jf8007t_prepare_bufs[i], sizeof(buf)); memcpy(buf, bufs[i], sizeof(buf));
if (i2c_transfer(state->adap, &msg, 1) != 1) if (i2c_transfer(state->adap, &msg, 1) != 1)
return -EREMOTEIO; return -EREMOTEIO;
} }
......
/* /*
* ISDB-T driver for VA1J5JF8007 * ISDB-T driver for VA1J5JF8007/VA1J5JF8011
* *
* Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info> * Copyright (C) 2009 HIRANO Takahito <hiranotaka@zng.info>
* *
...@@ -24,8 +24,14 @@ ...@@ -24,8 +24,14 @@
#ifndef VA1J5JF8007T_H #ifndef VA1J5JF8007T_H
#define VA1J5JF8007T_H #define VA1J5JF8007T_H
enum va1j5jf8007t_frequency {
VA1J5JF8007T_20MHZ,
VA1J5JF8007T_25MHZ,
};
struct va1j5jf8007t_config { struct va1j5jf8007t_config {
u8 demod_address; u8 demod_address;
enum va1j5jf8007t_frequency frequency;
}; };
struct i2c_adapter; struct i2c_adapter;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册