1*74ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 209ea33e5SIgor M. Liplianin /* 3c1965eaeSKonstantin Dimitrov Montage Technology DS3000 - DVBS/S2 Demodulator driver 4c1965eaeSKonstantin Dimitrov Copyright (C) 2009-2012 Konstantin Dimitrov <kosio.dimitrov@gmail.com> 509ea33e5SIgor M. Liplianin 6c1965eaeSKonstantin Dimitrov Copyright (C) 2009-2012 TurboSight.com 709ea33e5SIgor M. Liplianin 809ea33e5SIgor M. Liplianin */ 909ea33e5SIgor M. Liplianin 1009ea33e5SIgor M. Liplianin #include <linux/slab.h> 1109ea33e5SIgor M. Liplianin #include <linux/kernel.h> 1209ea33e5SIgor M. Liplianin #include <linux/module.h> 1309ea33e5SIgor M. Liplianin #include <linux/moduleparam.h> 1409ea33e5SIgor M. Liplianin #include <linux/init.h> 1509ea33e5SIgor M. Liplianin #include <linux/firmware.h> 1609ea33e5SIgor M. Liplianin 17fada1935SMauro Carvalho Chehab #include <media/dvb_frontend.h> 1873f0af44SKonstantin Dimitrov #include "ts2020.h" 1909ea33e5SIgor M. Liplianin #include "ds3000.h" 2009ea33e5SIgor M. Liplianin 2109ea33e5SIgor M. Liplianin static int debug; 2209ea33e5SIgor M. Liplianin 2309ea33e5SIgor M. Liplianin #define dprintk(args...) \ 2409ea33e5SIgor M. Liplianin do { \ 2509ea33e5SIgor M. Liplianin if (debug) \ 2609ea33e5SIgor M. Liplianin printk(args); \ 2709ea33e5SIgor M. Liplianin } while (0) 2809ea33e5SIgor M. Liplianin 2909ea33e5SIgor M. Liplianin /* as of March 2009 current DS3000 firmware version is 1.78 */ 3009ea33e5SIgor M. Liplianin /* DS3000 FW v1.78 MD5: a32d17910c4f370073f9346e71d34b80 */ 3109ea33e5SIgor M. Liplianin #define DS3000_DEFAULT_FIRMWARE "dvb-fe-ds3000.fw" 3209ea33e5SIgor M. Liplianin 3309ea33e5SIgor M. Liplianin #define DS3000_SAMPLE_RATE 96000 /* in kHz */ 3409ea33e5SIgor M. Liplianin 3509ea33e5SIgor M. Liplianin /* Register values to initialise the demod in DVB-S mode */ 3609ea33e5SIgor M. Liplianin static u8 ds3000_dvbs_init_tab[] = { 3709ea33e5SIgor M. Liplianin 0x23, 0x05, 3809ea33e5SIgor M. Liplianin 0x08, 0x03, 3909ea33e5SIgor M. Liplianin 0x0c, 0x00, 4009ea33e5SIgor M. Liplianin 0x21, 0x54, 4109ea33e5SIgor M. Liplianin 0x25, 0x82, 4209ea33e5SIgor M. Liplianin 0x27, 0x31, 4309ea33e5SIgor M. Liplianin 0x30, 0x08, 4409ea33e5SIgor M. Liplianin 0x31, 0x40, 4509ea33e5SIgor M. Liplianin 0x32, 0x32, 4609ea33e5SIgor M. Liplianin 0x33, 0x35, 4709ea33e5SIgor M. Liplianin 0x35, 0xff, 4809ea33e5SIgor M. Liplianin 0x3a, 0x00, 4909ea33e5SIgor M. Liplianin 0x37, 0x10, 5009ea33e5SIgor M. Liplianin 0x38, 0x10, 5109ea33e5SIgor M. Liplianin 0x39, 0x02, 5209ea33e5SIgor M. Liplianin 0x42, 0x60, 5309ea33e5SIgor M. Liplianin 0x4a, 0x40, 5409ea33e5SIgor M. Liplianin 0x4b, 0x04, 5509ea33e5SIgor M. Liplianin 0x4d, 0x91, 5609ea33e5SIgor M. Liplianin 0x5d, 0xc8, 5709ea33e5SIgor M. Liplianin 0x50, 0x77, 5809ea33e5SIgor M. Liplianin 0x51, 0x77, 5909ea33e5SIgor M. Liplianin 0x52, 0x36, 6009ea33e5SIgor M. Liplianin 0x53, 0x36, 6109ea33e5SIgor M. Liplianin 0x56, 0x01, 6209ea33e5SIgor M. Liplianin 0x63, 0x43, 6309ea33e5SIgor M. Liplianin 0x64, 0x30, 6409ea33e5SIgor M. Liplianin 0x65, 0x40, 6509ea33e5SIgor M. Liplianin 0x68, 0x26, 6609ea33e5SIgor M. Liplianin 0x69, 0x4c, 6709ea33e5SIgor M. Liplianin 0x70, 0x20, 6809ea33e5SIgor M. Liplianin 0x71, 0x70, 6909ea33e5SIgor M. Liplianin 0x72, 0x04, 7009ea33e5SIgor M. Liplianin 0x73, 0x00, 7109ea33e5SIgor M. Liplianin 0x70, 0x40, 7209ea33e5SIgor M. Liplianin 0x71, 0x70, 7309ea33e5SIgor M. Liplianin 0x72, 0x04, 7409ea33e5SIgor M. Liplianin 0x73, 0x00, 7509ea33e5SIgor M. Liplianin 0x70, 0x60, 7609ea33e5SIgor M. Liplianin 0x71, 0x70, 7709ea33e5SIgor M. Liplianin 0x72, 0x04, 7809ea33e5SIgor M. Liplianin 0x73, 0x00, 7909ea33e5SIgor M. Liplianin 0x70, 0x80, 8009ea33e5SIgor M. Liplianin 0x71, 0x70, 8109ea33e5SIgor M. Liplianin 0x72, 0x04, 8209ea33e5SIgor M. Liplianin 0x73, 0x00, 8309ea33e5SIgor M. Liplianin 0x70, 0xa0, 8409ea33e5SIgor M. Liplianin 0x71, 0x70, 8509ea33e5SIgor M. Liplianin 0x72, 0x04, 8609ea33e5SIgor M. Liplianin 0x73, 0x00, 8709ea33e5SIgor M. Liplianin 0x70, 0x1f, 8809ea33e5SIgor M. Liplianin 0x76, 0x00, 8909ea33e5SIgor M. Liplianin 0x77, 0xd1, 9009ea33e5SIgor M. Liplianin 0x78, 0x0c, 9109ea33e5SIgor M. Liplianin 0x79, 0x80, 9209ea33e5SIgor M. Liplianin 0x7f, 0x04, 9309ea33e5SIgor M. Liplianin 0x7c, 0x00, 9409ea33e5SIgor M. Liplianin 0x80, 0x86, 9509ea33e5SIgor M. Liplianin 0x81, 0xa6, 9609ea33e5SIgor M. Liplianin 0x85, 0x04, 9709ea33e5SIgor M. Liplianin 0xcd, 0xf4, 9809ea33e5SIgor M. Liplianin 0x90, 0x33, 9909ea33e5SIgor M. Liplianin 0xa0, 0x44, 10009ea33e5SIgor M. Liplianin 0xc0, 0x18, 10109ea33e5SIgor M. Liplianin 0xc3, 0x10, 10209ea33e5SIgor M. Liplianin 0xc4, 0x08, 10309ea33e5SIgor M. Liplianin 0xc5, 0x80, 10409ea33e5SIgor M. Liplianin 0xc6, 0x80, 10509ea33e5SIgor M. Liplianin 0xc7, 0x0a, 10609ea33e5SIgor M. Liplianin 0xc8, 0x1a, 10709ea33e5SIgor M. Liplianin 0xc9, 0x80, 10809ea33e5SIgor M. Liplianin 0xfe, 0x92, 10909ea33e5SIgor M. Liplianin 0xe0, 0xf8, 11009ea33e5SIgor M. Liplianin 0xe6, 0x8b, 11109ea33e5SIgor M. Liplianin 0xd0, 0x40, 11209ea33e5SIgor M. Liplianin 0xf8, 0x20, 11309ea33e5SIgor M. Liplianin 0xfa, 0x0f, 11409ea33e5SIgor M. Liplianin 0xfd, 0x20, 11509ea33e5SIgor M. Liplianin 0xad, 0x20, 11609ea33e5SIgor M. Liplianin 0xae, 0x07, 11709ea33e5SIgor M. Liplianin 0xb8, 0x00, 11809ea33e5SIgor M. Liplianin }; 11909ea33e5SIgor M. Liplianin 12009ea33e5SIgor M. Liplianin /* Register values to initialise the demod in DVB-S2 mode */ 12109ea33e5SIgor M. Liplianin static u8 ds3000_dvbs2_init_tab[] = { 12209ea33e5SIgor M. Liplianin 0x23, 0x0f, 12309ea33e5SIgor M. Liplianin 0x08, 0x07, 12409ea33e5SIgor M. Liplianin 0x0c, 0x00, 12509ea33e5SIgor M. Liplianin 0x21, 0x54, 12609ea33e5SIgor M. Liplianin 0x25, 0x82, 12709ea33e5SIgor M. Liplianin 0x27, 0x31, 12809ea33e5SIgor M. Liplianin 0x30, 0x08, 12909ea33e5SIgor M. Liplianin 0x31, 0x32, 13009ea33e5SIgor M. Liplianin 0x32, 0x32, 13109ea33e5SIgor M. Liplianin 0x33, 0x35, 13209ea33e5SIgor M. Liplianin 0x35, 0xff, 13309ea33e5SIgor M. Liplianin 0x3a, 0x00, 13409ea33e5SIgor M. Liplianin 0x37, 0x10, 13509ea33e5SIgor M. Liplianin 0x38, 0x10, 13609ea33e5SIgor M. Liplianin 0x39, 0x02, 13709ea33e5SIgor M. Liplianin 0x42, 0x60, 13809ea33e5SIgor M. Liplianin 0x4a, 0x80, 13909ea33e5SIgor M. Liplianin 0x4b, 0x04, 14009ea33e5SIgor M. Liplianin 0x4d, 0x81, 14109ea33e5SIgor M. Liplianin 0x5d, 0x88, 14209ea33e5SIgor M. Liplianin 0x50, 0x36, 14309ea33e5SIgor M. Liplianin 0x51, 0x36, 14409ea33e5SIgor M. Liplianin 0x52, 0x36, 14509ea33e5SIgor M. Liplianin 0x53, 0x36, 14609ea33e5SIgor M. Liplianin 0x63, 0x60, 14709ea33e5SIgor M. Liplianin 0x64, 0x10, 14809ea33e5SIgor M. Liplianin 0x65, 0x10, 14909ea33e5SIgor M. Liplianin 0x68, 0x04, 15009ea33e5SIgor M. Liplianin 0x69, 0x29, 15109ea33e5SIgor M. Liplianin 0x70, 0x20, 15209ea33e5SIgor M. Liplianin 0x71, 0x70, 15309ea33e5SIgor M. Liplianin 0x72, 0x04, 15409ea33e5SIgor M. Liplianin 0x73, 0x00, 15509ea33e5SIgor M. Liplianin 0x70, 0x40, 15609ea33e5SIgor M. Liplianin 0x71, 0x70, 15709ea33e5SIgor M. Liplianin 0x72, 0x04, 15809ea33e5SIgor M. Liplianin 0x73, 0x00, 15909ea33e5SIgor M. Liplianin 0x70, 0x60, 16009ea33e5SIgor M. Liplianin 0x71, 0x70, 16109ea33e5SIgor M. Liplianin 0x72, 0x04, 16209ea33e5SIgor M. Liplianin 0x73, 0x00, 16309ea33e5SIgor M. Liplianin 0x70, 0x80, 16409ea33e5SIgor M. Liplianin 0x71, 0x70, 16509ea33e5SIgor M. Liplianin 0x72, 0x04, 16609ea33e5SIgor M. Liplianin 0x73, 0x00, 16709ea33e5SIgor M. Liplianin 0x70, 0xa0, 16809ea33e5SIgor M. Liplianin 0x71, 0x70, 16909ea33e5SIgor M. Liplianin 0x72, 0x04, 17009ea33e5SIgor M. Liplianin 0x73, 0x00, 17109ea33e5SIgor M. Liplianin 0x70, 0x1f, 17209ea33e5SIgor M. Liplianin 0xa0, 0x44, 17309ea33e5SIgor M. Liplianin 0xc0, 0x08, 17409ea33e5SIgor M. Liplianin 0xc1, 0x10, 17509ea33e5SIgor M. Liplianin 0xc2, 0x08, 17609ea33e5SIgor M. Liplianin 0xc3, 0x10, 17709ea33e5SIgor M. Liplianin 0xc4, 0x08, 17809ea33e5SIgor M. Liplianin 0xc5, 0xf0, 17909ea33e5SIgor M. Liplianin 0xc6, 0xf0, 18009ea33e5SIgor M. Liplianin 0xc7, 0x0a, 18109ea33e5SIgor M. Liplianin 0xc8, 0x1a, 18209ea33e5SIgor M. Liplianin 0xc9, 0x80, 18309ea33e5SIgor M. Liplianin 0xca, 0x23, 18409ea33e5SIgor M. Liplianin 0xcb, 0x24, 18509ea33e5SIgor M. Liplianin 0xce, 0x74, 18609ea33e5SIgor M. Liplianin 0x90, 0x03, 18709ea33e5SIgor M. Liplianin 0x76, 0x80, 18809ea33e5SIgor M. Liplianin 0x77, 0x42, 18909ea33e5SIgor M. Liplianin 0x78, 0x0a, 19009ea33e5SIgor M. Liplianin 0x79, 0x80, 19109ea33e5SIgor M. Liplianin 0xad, 0x40, 19209ea33e5SIgor M. Liplianin 0xae, 0x07, 19309ea33e5SIgor M. Liplianin 0x7f, 0xd4, 19409ea33e5SIgor M. Liplianin 0x7c, 0x00, 19509ea33e5SIgor M. Liplianin 0x80, 0xa8, 19609ea33e5SIgor M. Liplianin 0x81, 0xda, 19709ea33e5SIgor M. Liplianin 0x7c, 0x01, 19809ea33e5SIgor M. Liplianin 0x80, 0xda, 19909ea33e5SIgor M. Liplianin 0x81, 0xec, 20009ea33e5SIgor M. Liplianin 0x7c, 0x02, 20109ea33e5SIgor M. Liplianin 0x80, 0xca, 20209ea33e5SIgor M. Liplianin 0x81, 0xeb, 20309ea33e5SIgor M. Liplianin 0x7c, 0x03, 20409ea33e5SIgor M. Liplianin 0x80, 0xba, 20509ea33e5SIgor M. Liplianin 0x81, 0xdb, 20609ea33e5SIgor M. Liplianin 0x85, 0x08, 20709ea33e5SIgor M. Liplianin 0x86, 0x00, 20809ea33e5SIgor M. Liplianin 0x87, 0x02, 20909ea33e5SIgor M. Liplianin 0x89, 0x80, 21009ea33e5SIgor M. Liplianin 0x8b, 0x44, 21109ea33e5SIgor M. Liplianin 0x8c, 0xaa, 21209ea33e5SIgor M. Liplianin 0x8a, 0x10, 21309ea33e5SIgor M. Liplianin 0xba, 0x00, 21409ea33e5SIgor M. Liplianin 0xf5, 0x04, 21509ea33e5SIgor M. Liplianin 0xfe, 0x44, 21609ea33e5SIgor M. Liplianin 0xd2, 0x32, 21709ea33e5SIgor M. Liplianin 0xb8, 0x00, 21809ea33e5SIgor M. Liplianin }; 21909ea33e5SIgor M. Liplianin 22009ea33e5SIgor M. Liplianin struct ds3000_state { 22109ea33e5SIgor M. Liplianin struct i2c_adapter *i2c; 22209ea33e5SIgor M. Liplianin const struct ds3000_config *config; 22309ea33e5SIgor M. Liplianin struct dvb_frontend frontend; 22409ea33e5SIgor M. Liplianin /* previous uncorrected block counter for DVB-S2 */ 22509ea33e5SIgor M. Liplianin u16 prevUCBS2; 22609ea33e5SIgor M. Liplianin }; 22709ea33e5SIgor M. Liplianin 22809ea33e5SIgor M. Liplianin static int ds3000_writereg(struct ds3000_state *state, int reg, int data) 22909ea33e5SIgor M. Liplianin { 23009ea33e5SIgor M. Liplianin u8 buf[] = { reg, data }; 23109ea33e5SIgor M. Liplianin struct i2c_msg msg = { .addr = state->config->demod_address, 23209ea33e5SIgor M. Liplianin .flags = 0, .buf = buf, .len = 2 }; 23309ea33e5SIgor M. Liplianin int err; 23409ea33e5SIgor M. Liplianin 23509ea33e5SIgor M. Liplianin dprintk("%s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data); 23609ea33e5SIgor M. Liplianin 23709ea33e5SIgor M. Liplianin err = i2c_transfer(state->i2c, &msg, 1); 23809ea33e5SIgor M. Liplianin if (err != 1) { 2394bd69e7bSMauro Carvalho Chehab printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x, value == 0x%02x)\n", 2404bd69e7bSMauro Carvalho Chehab __func__, err, reg, data); 24109ea33e5SIgor M. Liplianin return -EREMOTEIO; 24209ea33e5SIgor M. Liplianin } 24309ea33e5SIgor M. Liplianin 24409ea33e5SIgor M. Liplianin return 0; 24509ea33e5SIgor M. Liplianin } 24609ea33e5SIgor M. Liplianin 247c1965eaeSKonstantin Dimitrov static int ds3000_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 24809ea33e5SIgor M. Liplianin { 249c1965eaeSKonstantin Dimitrov struct ds3000_state *state = fe->demodulator_priv; 25009ea33e5SIgor M. Liplianin 251c1965eaeSKonstantin Dimitrov if (enable) 252c1965eaeSKonstantin Dimitrov ds3000_writereg(state, 0x03, 0x12); 253c1965eaeSKonstantin Dimitrov else 254c1965eaeSKonstantin Dimitrov ds3000_writereg(state, 0x03, 0x02); 25509ea33e5SIgor M. Liplianin 25609ea33e5SIgor M. Liplianin return 0; 25709ea33e5SIgor M. Liplianin } 25809ea33e5SIgor M. Liplianin 25909ea33e5SIgor M. Liplianin /* I2C write for 8k firmware load */ 26009ea33e5SIgor M. Liplianin static int ds3000_writeFW(struct ds3000_state *state, int reg, 26109ea33e5SIgor M. Liplianin const u8 *data, u16 len) 26209ea33e5SIgor M. Liplianin { 263d58f4f27SRémi Cardona int i, ret = 0; 26409ea33e5SIgor M. Liplianin struct i2c_msg msg; 26509ea33e5SIgor M. Liplianin u8 *buf; 26609ea33e5SIgor M. Liplianin 267caa687c8SIgor M. Liplianin buf = kmalloc(33, GFP_KERNEL); 268c38e8657SMarkus Elfring if (!buf) 269d58f4f27SRémi Cardona return -ENOMEM; 27009ea33e5SIgor M. Liplianin 27109ea33e5SIgor M. Liplianin *(buf) = reg; 27209ea33e5SIgor M. Liplianin 27309ea33e5SIgor M. Liplianin msg.addr = state->config->demod_address; 27409ea33e5SIgor M. Liplianin msg.flags = 0; 27509ea33e5SIgor M. Liplianin msg.buf = buf; 276caa687c8SIgor M. Liplianin msg.len = 33; 27709ea33e5SIgor M. Liplianin 278caa687c8SIgor M. Liplianin for (i = 0; i < len; i += 32) { 279caa687c8SIgor M. Liplianin memcpy(buf + 1, data + i, 32); 28009ea33e5SIgor M. Liplianin 28109ea33e5SIgor M. Liplianin dprintk("%s: write reg 0x%02x, len = %d\n", __func__, reg, len); 28209ea33e5SIgor M. Liplianin 28309ea33e5SIgor M. Liplianin ret = i2c_transfer(state->i2c, &msg, 1); 28409ea33e5SIgor M. Liplianin if (ret != 1) { 2854bd69e7bSMauro Carvalho Chehab printk(KERN_ERR "%s: write error(err == %i, reg == 0x%02x\n", 2864bd69e7bSMauro Carvalho Chehab __func__, ret, reg); 28709ea33e5SIgor M. Liplianin ret = -EREMOTEIO; 288d58f4f27SRémi Cardona goto error; 28909ea33e5SIgor M. Liplianin } 29009ea33e5SIgor M. Liplianin } 291d58f4f27SRémi Cardona ret = 0; 29209ea33e5SIgor M. Liplianin 29309ea33e5SIgor M. Liplianin error: 29409ea33e5SIgor M. Liplianin kfree(buf); 29509ea33e5SIgor M. Liplianin 29609ea33e5SIgor M. Liplianin return ret; 29709ea33e5SIgor M. Liplianin } 29809ea33e5SIgor M. Liplianin 29909ea33e5SIgor M. Liplianin static int ds3000_readreg(struct ds3000_state *state, u8 reg) 30009ea33e5SIgor M. Liplianin { 30109ea33e5SIgor M. Liplianin int ret; 30209ea33e5SIgor M. Liplianin u8 b0[] = { reg }; 30309ea33e5SIgor M. Liplianin u8 b1[] = { 0 }; 30409ea33e5SIgor M. Liplianin struct i2c_msg msg[] = { 30509ea33e5SIgor M. Liplianin { 30609ea33e5SIgor M. Liplianin .addr = state->config->demod_address, 30709ea33e5SIgor M. Liplianin .flags = 0, 30809ea33e5SIgor M. Liplianin .buf = b0, 30909ea33e5SIgor M. Liplianin .len = 1 31009ea33e5SIgor M. Liplianin }, { 31109ea33e5SIgor M. Liplianin .addr = state->config->demod_address, 31209ea33e5SIgor M. Liplianin .flags = I2C_M_RD, 31309ea33e5SIgor M. Liplianin .buf = b1, 31409ea33e5SIgor M. Liplianin .len = 1 31509ea33e5SIgor M. Liplianin } 31609ea33e5SIgor M. Liplianin }; 31709ea33e5SIgor M. Liplianin 31809ea33e5SIgor M. Liplianin ret = i2c_transfer(state->i2c, msg, 2); 31909ea33e5SIgor M. Liplianin 32009ea33e5SIgor M. Liplianin if (ret != 2) { 32109ea33e5SIgor M. Liplianin printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret); 32209ea33e5SIgor M. Liplianin return ret; 32309ea33e5SIgor M. Liplianin } 32409ea33e5SIgor M. Liplianin 32509ea33e5SIgor M. Liplianin dprintk("%s: read reg 0x%02x, value 0x%02x\n", __func__, reg, b1[0]); 32609ea33e5SIgor M. Liplianin 32709ea33e5SIgor M. Liplianin return b1[0]; 32809ea33e5SIgor M. Liplianin } 32909ea33e5SIgor M. Liplianin 33009ea33e5SIgor M. Liplianin static int ds3000_load_firmware(struct dvb_frontend *fe, 33109ea33e5SIgor M. Liplianin const struct firmware *fw); 33209ea33e5SIgor M. Liplianin 33309ea33e5SIgor M. Liplianin static int ds3000_firmware_ondemand(struct dvb_frontend *fe) 33409ea33e5SIgor M. Liplianin { 33509ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 33609ea33e5SIgor M. Liplianin const struct firmware *fw; 33709ea33e5SIgor M. Liplianin int ret = 0; 33809ea33e5SIgor M. Liplianin 33909ea33e5SIgor M. Liplianin dprintk("%s()\n", __func__); 34009ea33e5SIgor M. Liplianin 341034351ffSRémi Cardona ret = ds3000_readreg(state, 0xb2); 342034351ffSRémi Cardona if (ret < 0) 34309ea33e5SIgor M. Liplianin return ret; 34409ea33e5SIgor M. Liplianin 34509ea33e5SIgor M. Liplianin /* Load firmware */ 34609ea33e5SIgor M. Liplianin /* request the firmware, this will block until someone uploads it */ 34709ea33e5SIgor M. Liplianin printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__, 34809ea33e5SIgor M. Liplianin DS3000_DEFAULT_FIRMWARE); 34909ea33e5SIgor M. Liplianin ret = request_firmware(&fw, DS3000_DEFAULT_FIRMWARE, 35009ea33e5SIgor M. Liplianin state->i2c->dev.parent); 35109ea33e5SIgor M. Liplianin printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__); 35209ea33e5SIgor M. Liplianin if (ret) { 3534bd69e7bSMauro Carvalho Chehab printk(KERN_ERR "%s: No firmware uploaded (timeout or file not found?)\n", 3544bd69e7bSMauro Carvalho Chehab __func__); 35509ea33e5SIgor M. Liplianin return ret; 35609ea33e5SIgor M. Liplianin } 35709ea33e5SIgor M. Liplianin 35809ea33e5SIgor M. Liplianin ret = ds3000_load_firmware(fe, fw); 35909ea33e5SIgor M. Liplianin if (ret) 36009ea33e5SIgor M. Liplianin printk("%s: Writing firmware to device failed\n", __func__); 36109ea33e5SIgor M. Liplianin 36209ea33e5SIgor M. Liplianin release_firmware(fw); 36309ea33e5SIgor M. Liplianin 36409ea33e5SIgor M. Liplianin dprintk("%s: Firmware upload %s\n", __func__, 36509ea33e5SIgor M. Liplianin ret == 0 ? "complete" : "failed"); 36609ea33e5SIgor M. Liplianin 36709ea33e5SIgor M. Liplianin return ret; 36809ea33e5SIgor M. Liplianin } 36909ea33e5SIgor M. Liplianin 37009ea33e5SIgor M. Liplianin static int ds3000_load_firmware(struct dvb_frontend *fe, 37109ea33e5SIgor M. Liplianin const struct firmware *fw) 37209ea33e5SIgor M. Liplianin { 37309ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 374d58f4f27SRémi Cardona int ret = 0; 37509ea33e5SIgor M. Liplianin 37609ea33e5SIgor M. Liplianin dprintk("%s\n", __func__); 37709ea33e5SIgor M. Liplianin dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n", 37809ea33e5SIgor M. Liplianin fw->size, 37909ea33e5SIgor M. Liplianin fw->data[0], 38009ea33e5SIgor M. Liplianin fw->data[1], 38109ea33e5SIgor M. Liplianin fw->data[fw->size - 2], 38209ea33e5SIgor M. Liplianin fw->data[fw->size - 1]); 38309ea33e5SIgor M. Liplianin 38409ea33e5SIgor M. Liplianin /* Begin the firmware load process */ 38509ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xb2, 0x01); 38609ea33e5SIgor M. Liplianin /* write the entire firmware */ 387d58f4f27SRémi Cardona ret = ds3000_writeFW(state, 0xb0, fw->data, fw->size); 38809ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xb2, 0x00); 38909ea33e5SIgor M. Liplianin 390d58f4f27SRémi Cardona return ret; 39109ea33e5SIgor M. Liplianin } 39209ea33e5SIgor M. Liplianin 3930df289a2SMauro Carvalho Chehab static int ds3000_set_voltage(struct dvb_frontend *fe, 3940df289a2SMauro Carvalho Chehab enum fe_sec_voltage voltage) 395d2ffc447SIgor M. Liplianin { 396d2ffc447SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 397d2ffc447SIgor M. Liplianin u8 data; 398d2ffc447SIgor M. Liplianin 399d2ffc447SIgor M. Liplianin dprintk("%s(%d)\n", __func__, voltage); 400d2ffc447SIgor M. Liplianin 401d2ffc447SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 402d2ffc447SIgor M. Liplianin data |= 0x03; /* bit0 V/H, bit1 off/on */ 403d2ffc447SIgor M. Liplianin 404d2ffc447SIgor M. Liplianin switch (voltage) { 405d2ffc447SIgor M. Liplianin case SEC_VOLTAGE_18: 406d2ffc447SIgor M. Liplianin data &= ~0x03; 407d2ffc447SIgor M. Liplianin break; 408d2ffc447SIgor M. Liplianin case SEC_VOLTAGE_13: 409d2ffc447SIgor M. Liplianin data &= ~0x03; 410d2ffc447SIgor M. Liplianin data |= 0x01; 411d2ffc447SIgor M. Liplianin break; 412d2ffc447SIgor M. Liplianin case SEC_VOLTAGE_OFF: 413d2ffc447SIgor M. Liplianin break; 414d2ffc447SIgor M. Liplianin } 415d2ffc447SIgor M. Liplianin 416d2ffc447SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 417d2ffc447SIgor M. Liplianin 418d2ffc447SIgor M. Liplianin return 0; 419d2ffc447SIgor M. Liplianin } 420d2ffc447SIgor M. Liplianin 4210df289a2SMauro Carvalho Chehab static int ds3000_read_status(struct dvb_frontend *fe, enum fe_status *status) 42209ea33e5SIgor M. Liplianin { 42309ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 42409ea33e5SIgor M. Liplianin struct dtv_frontend_properties *c = &fe->dtv_property_cache; 42509ea33e5SIgor M. Liplianin int lock; 42609ea33e5SIgor M. Liplianin 42709ea33e5SIgor M. Liplianin *status = 0; 42809ea33e5SIgor M. Liplianin 42909ea33e5SIgor M. Liplianin switch (c->delivery_system) { 43009ea33e5SIgor M. Liplianin case SYS_DVBS: 43109ea33e5SIgor M. Liplianin lock = ds3000_readreg(state, 0xd1); 43209ea33e5SIgor M. Liplianin if ((lock & 0x07) == 0x07) 43309ea33e5SIgor M. Liplianin *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | 43409ea33e5SIgor M. Liplianin FE_HAS_VITERBI | FE_HAS_SYNC | 43509ea33e5SIgor M. Liplianin FE_HAS_LOCK; 43609ea33e5SIgor M. Liplianin 43709ea33e5SIgor M. Liplianin break; 43809ea33e5SIgor M. Liplianin case SYS_DVBS2: 43909ea33e5SIgor M. Liplianin lock = ds3000_readreg(state, 0x0d); 44009ea33e5SIgor M. Liplianin if ((lock & 0x8f) == 0x8f) 44109ea33e5SIgor M. Liplianin *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | 44209ea33e5SIgor M. Liplianin FE_HAS_VITERBI | FE_HAS_SYNC | 44309ea33e5SIgor M. Liplianin FE_HAS_LOCK; 44409ea33e5SIgor M. Liplianin 44509ea33e5SIgor M. Liplianin break; 44609ea33e5SIgor M. Liplianin default: 44727924dccSOlli Salonen return -EINVAL; 44809ea33e5SIgor M. Liplianin } 44909ea33e5SIgor M. Liplianin 45043385c8aSIgor M. Liplianin if (state->config->set_lock_led) 45143385c8aSIgor M. Liplianin state->config->set_lock_led(fe, *status == 0 ? 0 : 1); 45243385c8aSIgor M. Liplianin 45309ea33e5SIgor M. Liplianin dprintk("%s: status = 0x%02x\n", __func__, lock); 45409ea33e5SIgor M. Liplianin 45509ea33e5SIgor M. Liplianin return 0; 45609ea33e5SIgor M. Liplianin } 45709ea33e5SIgor M. Liplianin 45809ea33e5SIgor M. Liplianin /* read DS3000 BER value */ 45909ea33e5SIgor M. Liplianin static int ds3000_read_ber(struct dvb_frontend *fe, u32* ber) 46009ea33e5SIgor M. Liplianin { 46109ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 46209ea33e5SIgor M. Liplianin struct dtv_frontend_properties *c = &fe->dtv_property_cache; 46309ea33e5SIgor M. Liplianin u8 data; 46409ea33e5SIgor M. Liplianin u32 ber_reading, lpdc_frames; 46509ea33e5SIgor M. Liplianin 46609ea33e5SIgor M. Liplianin dprintk("%s()\n", __func__); 46709ea33e5SIgor M. Liplianin 46809ea33e5SIgor M. Liplianin switch (c->delivery_system) { 46909ea33e5SIgor M. Liplianin case SYS_DVBS: 47009ea33e5SIgor M. Liplianin /* set the number of bytes checked during 47109ea33e5SIgor M. Liplianin BER estimation */ 47209ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xf9, 0x04); 47309ea33e5SIgor M. Liplianin /* read BER estimation status */ 47409ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xf8); 47509ea33e5SIgor M. Liplianin /* check if BER estimation is ready */ 47609ea33e5SIgor M. Liplianin if ((data & 0x10) == 0) { 47709ea33e5SIgor M. Liplianin /* this is the number of error bits, 47809ea33e5SIgor M. Liplianin to calculate the bit error rate 47909ea33e5SIgor M. Liplianin divide to 8388608 */ 48009ea33e5SIgor M. Liplianin *ber = (ds3000_readreg(state, 0xf7) << 8) | 48109ea33e5SIgor M. Liplianin ds3000_readreg(state, 0xf6); 48209ea33e5SIgor M. Liplianin /* start counting error bits */ 48309ea33e5SIgor M. Liplianin /* need to be set twice 48409ea33e5SIgor M. Liplianin otherwise it fails sometimes */ 48509ea33e5SIgor M. Liplianin data |= 0x10; 48609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xf8, data); 48709ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xf8, data); 48809ea33e5SIgor M. Liplianin } else 48909ea33e5SIgor M. Liplianin /* used to indicate that BER estimation 49009ea33e5SIgor M. Liplianin is not ready, i.e. BER is unknown */ 49109ea33e5SIgor M. Liplianin *ber = 0xffffffff; 49209ea33e5SIgor M. Liplianin break; 49309ea33e5SIgor M. Liplianin case SYS_DVBS2: 49409ea33e5SIgor M. Liplianin /* read the number of LPDC decoded frames */ 49509ea33e5SIgor M. Liplianin lpdc_frames = (ds3000_readreg(state, 0xd7) << 16) | 49609ea33e5SIgor M. Liplianin (ds3000_readreg(state, 0xd6) << 8) | 49709ea33e5SIgor M. Liplianin ds3000_readreg(state, 0xd5); 49809ea33e5SIgor M. Liplianin /* read the number of packets with bad CRC */ 49909ea33e5SIgor M. Liplianin ber_reading = (ds3000_readreg(state, 0xf8) << 8) | 50009ea33e5SIgor M. Liplianin ds3000_readreg(state, 0xf7); 50109ea33e5SIgor M. Liplianin if (lpdc_frames > 750) { 50209ea33e5SIgor M. Liplianin /* clear LPDC frame counters */ 50309ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xd1, 0x01); 50409ea33e5SIgor M. Liplianin /* clear bad packets counter */ 50509ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xf9, 0x01); 50609ea33e5SIgor M. Liplianin /* enable bad packets counter */ 50709ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xf9, 0x00); 50809ea33e5SIgor M. Liplianin /* enable LPDC frame counters */ 50909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xd1, 0x00); 51009ea33e5SIgor M. Liplianin *ber = ber_reading; 51109ea33e5SIgor M. Liplianin } else 51209ea33e5SIgor M. Liplianin /* used to indicate that BER estimation is not ready, 51309ea33e5SIgor M. Liplianin i.e. BER is unknown */ 51409ea33e5SIgor M. Liplianin *ber = 0xffffffff; 51509ea33e5SIgor M. Liplianin break; 51609ea33e5SIgor M. Liplianin default: 51727924dccSOlli Salonen return -EINVAL; 51809ea33e5SIgor M. Liplianin } 51909ea33e5SIgor M. Liplianin 52009ea33e5SIgor M. Liplianin return 0; 52109ea33e5SIgor M. Liplianin } 52209ea33e5SIgor M. Liplianin 523a0a030bdSMalcolm Priestley static int ds3000_read_signal_strength(struct dvb_frontend *fe, 524a0a030bdSMalcolm Priestley u16 *signal_strength) 525a0a030bdSMalcolm Priestley { 526a0a030bdSMalcolm Priestley if (fe->ops.tuner_ops.get_rf_strength) 527a0a030bdSMalcolm Priestley fe->ops.tuner_ops.get_rf_strength(fe, signal_strength); 528a0a030bdSMalcolm Priestley 529a0a030bdSMalcolm Priestley return 0; 530a0a030bdSMalcolm Priestley } 531a0a030bdSMalcolm Priestley 53209ea33e5SIgor M. Liplianin /* calculate DS3000 snr value in dB */ 53309ea33e5SIgor M. Liplianin static int ds3000_read_snr(struct dvb_frontend *fe, u16 *snr) 53409ea33e5SIgor M. Liplianin { 53509ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 53609ea33e5SIgor M. Liplianin struct dtv_frontend_properties *c = &fe->dtv_property_cache; 53709ea33e5SIgor M. Liplianin u8 snr_reading, snr_value; 53809ea33e5SIgor M. Liplianin u32 dvbs2_signal_reading, dvbs2_noise_reading, tmp; 53909ea33e5SIgor M. Liplianin static const u16 dvbs_snr_tab[] = { /* 20 x Table (rounded up) */ 54009ea33e5SIgor M. Liplianin 0x0000, 0x1b13, 0x2aea, 0x3627, 0x3ede, 0x45fe, 0x4c03, 54109ea33e5SIgor M. Liplianin 0x513a, 0x55d4, 0x59f2, 0x5dab, 0x6111, 0x6431, 0x6717, 54209ea33e5SIgor M. Liplianin 0x69c9, 0x6c4e, 0x6eac, 0x70e8, 0x7304, 0x7505 54309ea33e5SIgor M. Liplianin }; 54409ea33e5SIgor M. Liplianin static const u16 dvbs2_snr_tab[] = { /* 80 x Table (rounded up) */ 54509ea33e5SIgor M. Liplianin 0x0000, 0x0bc2, 0x12a3, 0x1785, 0x1b4e, 0x1e65, 0x2103, 54609ea33e5SIgor M. Liplianin 0x2347, 0x2546, 0x2710, 0x28ae, 0x2a28, 0x2b83, 0x2cc5, 54709ea33e5SIgor M. Liplianin 0x2df1, 0x2f09, 0x3010, 0x3109, 0x31f4, 0x32d2, 0x33a6, 54809ea33e5SIgor M. Liplianin 0x3470, 0x3531, 0x35ea, 0x369b, 0x3746, 0x37ea, 0x3888, 54909ea33e5SIgor M. Liplianin 0x3920, 0x39b3, 0x3a42, 0x3acc, 0x3b51, 0x3bd3, 0x3c51, 55009ea33e5SIgor M. Liplianin 0x3ccb, 0x3d42, 0x3db6, 0x3e27, 0x3e95, 0x3f00, 0x3f68, 55109ea33e5SIgor M. Liplianin 0x3fcf, 0x4033, 0x4094, 0x40f4, 0x4151, 0x41ac, 0x4206, 55209ea33e5SIgor M. Liplianin 0x425e, 0x42b4, 0x4308, 0x435b, 0x43ac, 0x43fc, 0x444a, 55309ea33e5SIgor M. Liplianin 0x4497, 0x44e2, 0x452d, 0x4576, 0x45bd, 0x4604, 0x4649, 55409ea33e5SIgor M. Liplianin 0x468e, 0x46d1, 0x4713, 0x4755, 0x4795, 0x47d4, 0x4813, 55509ea33e5SIgor M. Liplianin 0x4851, 0x488d, 0x48c9, 0x4904, 0x493f, 0x4978, 0x49b1, 55609ea33e5SIgor M. Liplianin 0x49e9, 0x4a20, 0x4a57 55709ea33e5SIgor M. Liplianin }; 55809ea33e5SIgor M. Liplianin 55909ea33e5SIgor M. Liplianin dprintk("%s()\n", __func__); 56009ea33e5SIgor M. Liplianin 56109ea33e5SIgor M. Liplianin switch (c->delivery_system) { 56209ea33e5SIgor M. Liplianin case SYS_DVBS: 56309ea33e5SIgor M. Liplianin snr_reading = ds3000_readreg(state, 0xff); 56409ea33e5SIgor M. Liplianin snr_reading /= 8; 56509ea33e5SIgor M. Liplianin if (snr_reading == 0) 56609ea33e5SIgor M. Liplianin *snr = 0x0000; 56709ea33e5SIgor M. Liplianin else { 56809ea33e5SIgor M. Liplianin if (snr_reading > 20) 56909ea33e5SIgor M. Liplianin snr_reading = 20; 57009ea33e5SIgor M. Liplianin snr_value = dvbs_snr_tab[snr_reading - 1] * 10 / 23026; 57109ea33e5SIgor M. Liplianin /* cook the value to be suitable for szap-s2 57209ea33e5SIgor M. Liplianin human readable output */ 57309ea33e5SIgor M. Liplianin *snr = snr_value * 8 * 655; 57409ea33e5SIgor M. Liplianin } 57509ea33e5SIgor M. Liplianin dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__, 57609ea33e5SIgor M. Liplianin snr_reading, *snr); 57709ea33e5SIgor M. Liplianin break; 57809ea33e5SIgor M. Liplianin case SYS_DVBS2: 57909ea33e5SIgor M. Liplianin dvbs2_noise_reading = (ds3000_readreg(state, 0x8c) & 0x3f) + 58009ea33e5SIgor M. Liplianin (ds3000_readreg(state, 0x8d) << 4); 58109ea33e5SIgor M. Liplianin dvbs2_signal_reading = ds3000_readreg(state, 0x8e); 58209ea33e5SIgor M. Liplianin tmp = dvbs2_signal_reading * dvbs2_signal_reading >> 1; 583450df222SNicolas Noirbent if (tmp == 0) { 58409ea33e5SIgor M. Liplianin *snr = 0x0000; 58509ea33e5SIgor M. Liplianin return 0; 58609ea33e5SIgor M. Liplianin } 58709ea33e5SIgor M. Liplianin if (dvbs2_noise_reading == 0) { 58809ea33e5SIgor M. Liplianin snr_value = 0x0013; 58909ea33e5SIgor M. Liplianin /* cook the value to be suitable for szap-s2 59009ea33e5SIgor M. Liplianin human readable output */ 59109ea33e5SIgor M. Liplianin *snr = 0xffff; 59209ea33e5SIgor M. Liplianin return 0; 59309ea33e5SIgor M. Liplianin } 59409ea33e5SIgor M. Liplianin if (tmp > dvbs2_noise_reading) { 59509ea33e5SIgor M. Liplianin snr_reading = tmp / dvbs2_noise_reading; 59609ea33e5SIgor M. Liplianin if (snr_reading > 80) 59709ea33e5SIgor M. Liplianin snr_reading = 80; 59809ea33e5SIgor M. Liplianin snr_value = dvbs2_snr_tab[snr_reading - 1] / 1000; 59909ea33e5SIgor M. Liplianin /* cook the value to be suitable for szap-s2 60009ea33e5SIgor M. Liplianin human readable output */ 60109ea33e5SIgor M. Liplianin *snr = snr_value * 5 * 655; 60209ea33e5SIgor M. Liplianin } else { 60309ea33e5SIgor M. Liplianin snr_reading = dvbs2_noise_reading / tmp; 60409ea33e5SIgor M. Liplianin if (snr_reading > 80) 60509ea33e5SIgor M. Liplianin snr_reading = 80; 606b59de95bSHeinrich Schuchardt *snr = -(dvbs2_snr_tab[snr_reading - 1] / 1000); 60709ea33e5SIgor M. Liplianin } 60809ea33e5SIgor M. Liplianin dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__, 60909ea33e5SIgor M. Liplianin snr_reading, *snr); 61009ea33e5SIgor M. Liplianin break; 61109ea33e5SIgor M. Liplianin default: 61227924dccSOlli Salonen return -EINVAL; 61309ea33e5SIgor M. Liplianin } 61409ea33e5SIgor M. Liplianin 61509ea33e5SIgor M. Liplianin return 0; 61609ea33e5SIgor M. Liplianin } 61709ea33e5SIgor M. Liplianin 61809ea33e5SIgor M. Liplianin /* read DS3000 uncorrected blocks */ 61909ea33e5SIgor M. Liplianin static int ds3000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 62009ea33e5SIgor M. Liplianin { 62109ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 62209ea33e5SIgor M. Liplianin struct dtv_frontend_properties *c = &fe->dtv_property_cache; 62309ea33e5SIgor M. Liplianin u8 data; 62409ea33e5SIgor M. Liplianin u16 _ucblocks; 62509ea33e5SIgor M. Liplianin 62609ea33e5SIgor M. Liplianin dprintk("%s()\n", __func__); 62709ea33e5SIgor M. Liplianin 62809ea33e5SIgor M. Liplianin switch (c->delivery_system) { 62909ea33e5SIgor M. Liplianin case SYS_DVBS: 63009ea33e5SIgor M. Liplianin *ucblocks = (ds3000_readreg(state, 0xf5) << 8) | 63109ea33e5SIgor M. Liplianin ds3000_readreg(state, 0xf4); 63209ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xf8); 63309ea33e5SIgor M. Liplianin /* clear packet counters */ 63409ea33e5SIgor M. Liplianin data &= ~0x20; 63509ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xf8, data); 63609ea33e5SIgor M. Liplianin /* enable packet counters */ 63709ea33e5SIgor M. Liplianin data |= 0x20; 63809ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xf8, data); 63909ea33e5SIgor M. Liplianin break; 64009ea33e5SIgor M. Liplianin case SYS_DVBS2: 64109ea33e5SIgor M. Liplianin _ucblocks = (ds3000_readreg(state, 0xe2) << 8) | 64209ea33e5SIgor M. Liplianin ds3000_readreg(state, 0xe1); 64309ea33e5SIgor M. Liplianin if (_ucblocks > state->prevUCBS2) 64409ea33e5SIgor M. Liplianin *ucblocks = _ucblocks - state->prevUCBS2; 64509ea33e5SIgor M. Liplianin else 64609ea33e5SIgor M. Liplianin *ucblocks = state->prevUCBS2 - _ucblocks; 64709ea33e5SIgor M. Liplianin state->prevUCBS2 = _ucblocks; 64809ea33e5SIgor M. Liplianin break; 64909ea33e5SIgor M. Liplianin default: 65027924dccSOlli Salonen return -EINVAL; 65109ea33e5SIgor M. Liplianin } 65209ea33e5SIgor M. Liplianin 65309ea33e5SIgor M. Liplianin return 0; 65409ea33e5SIgor M. Liplianin } 65509ea33e5SIgor M. Liplianin 6560df289a2SMauro Carvalho Chehab static int ds3000_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone) 65709ea33e5SIgor M. Liplianin { 65809ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 65909ea33e5SIgor M. Liplianin u8 data; 66009ea33e5SIgor M. Liplianin 66109ea33e5SIgor M. Liplianin dprintk("%s(%d)\n", __func__, tone); 66209ea33e5SIgor M. Liplianin if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) { 66309ea33e5SIgor M. Liplianin printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone); 66409ea33e5SIgor M. Liplianin return -EINVAL; 66509ea33e5SIgor M. Liplianin } 66609ea33e5SIgor M. Liplianin 66709ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 66809ea33e5SIgor M. Liplianin data &= ~0xc0; 66909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 67009ea33e5SIgor M. Liplianin 67109ea33e5SIgor M. Liplianin switch (tone) { 67209ea33e5SIgor M. Liplianin case SEC_TONE_ON: 67309ea33e5SIgor M. Liplianin dprintk("%s: setting tone on\n", __func__); 67409ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa1); 67509ea33e5SIgor M. Liplianin data &= ~0x43; 67609ea33e5SIgor M. Liplianin data |= 0x04; 67709ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa1, data); 67809ea33e5SIgor M. Liplianin break; 67909ea33e5SIgor M. Liplianin case SEC_TONE_OFF: 68009ea33e5SIgor M. Liplianin dprintk("%s: setting tone off\n", __func__); 68109ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 68209ea33e5SIgor M. Liplianin data |= 0x80; 68309ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 68409ea33e5SIgor M. Liplianin break; 68509ea33e5SIgor M. Liplianin } 68609ea33e5SIgor M. Liplianin 68709ea33e5SIgor M. Liplianin return 0; 68809ea33e5SIgor M. Liplianin } 68909ea33e5SIgor M. Liplianin 69009ea33e5SIgor M. Liplianin static int ds3000_send_diseqc_msg(struct dvb_frontend *fe, 69109ea33e5SIgor M. Liplianin struct dvb_diseqc_master_cmd *d) 69209ea33e5SIgor M. Liplianin { 69309ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 69409ea33e5SIgor M. Liplianin int i; 69509ea33e5SIgor M. Liplianin u8 data; 69609ea33e5SIgor M. Liplianin 69709ea33e5SIgor M. Liplianin /* Dump DiSEqC message */ 69809ea33e5SIgor M. Liplianin dprintk("%s(", __func__); 69909ea33e5SIgor M. Liplianin for (i = 0 ; i < d->msg_len;) { 70009ea33e5SIgor M. Liplianin dprintk("0x%02x", d->msg[i]); 70109ea33e5SIgor M. Liplianin if (++i < d->msg_len) 70209ea33e5SIgor M. Liplianin dprintk(", "); 70309ea33e5SIgor M. Liplianin } 70409ea33e5SIgor M. Liplianin 70509ea33e5SIgor M. Liplianin /* enable DiSEqC message send pin */ 70609ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 70709ea33e5SIgor M. Liplianin data &= ~0xc0; 70809ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 70909ea33e5SIgor M. Liplianin 71009ea33e5SIgor M. Liplianin /* DiSEqC message */ 71109ea33e5SIgor M. Liplianin for (i = 0; i < d->msg_len; i++) 71209ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa3 + i, d->msg[i]); 71309ea33e5SIgor M. Liplianin 71409ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa1); 71509ea33e5SIgor M. Liplianin /* clear DiSEqC message length and status, 71609ea33e5SIgor M. Liplianin enable DiSEqC message send */ 71709ea33e5SIgor M. Liplianin data &= ~0xf8; 71809ea33e5SIgor M. Liplianin /* set DiSEqC mode, modulation active during 33 pulses, 71909ea33e5SIgor M. Liplianin set DiSEqC message length */ 72009ea33e5SIgor M. Liplianin data |= ((d->msg_len - 1) << 3) | 0x07; 72109ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa1, data); 72209ea33e5SIgor M. Liplianin 72309ea33e5SIgor M. Liplianin /* wait up to 150ms for DiSEqC transmission to complete */ 72409ea33e5SIgor M. Liplianin for (i = 0; i < 15; i++) { 72509ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa1); 72609ea33e5SIgor M. Liplianin if ((data & 0x40) == 0) 72709ea33e5SIgor M. Liplianin break; 72809ea33e5SIgor M. Liplianin msleep(10); 72909ea33e5SIgor M. Liplianin } 73009ea33e5SIgor M. Liplianin 73109ea33e5SIgor M. Liplianin /* DiSEqC timeout after 150ms */ 73209ea33e5SIgor M. Liplianin if (i == 15) { 73309ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa1); 73409ea33e5SIgor M. Liplianin data &= ~0x80; 73509ea33e5SIgor M. Liplianin data |= 0x40; 73609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa1, data); 73709ea33e5SIgor M. Liplianin 73809ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 73909ea33e5SIgor M. Liplianin data &= ~0xc0; 74009ea33e5SIgor M. Liplianin data |= 0x80; 74109ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 74209ea33e5SIgor M. Liplianin 74327924dccSOlli Salonen return -ETIMEDOUT; 74409ea33e5SIgor M. Liplianin } 74509ea33e5SIgor M. Liplianin 74609ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 74709ea33e5SIgor M. Liplianin data &= ~0xc0; 74809ea33e5SIgor M. Liplianin data |= 0x80; 74909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 75009ea33e5SIgor M. Liplianin 75109ea33e5SIgor M. Liplianin return 0; 75209ea33e5SIgor M. Liplianin } 75309ea33e5SIgor M. Liplianin 75409ea33e5SIgor M. Liplianin /* Send DiSEqC burst */ 75509ea33e5SIgor M. Liplianin static int ds3000_diseqc_send_burst(struct dvb_frontend *fe, 7560df289a2SMauro Carvalho Chehab enum fe_sec_mini_cmd burst) 75709ea33e5SIgor M. Liplianin { 75809ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 75909ea33e5SIgor M. Liplianin int i; 76009ea33e5SIgor M. Liplianin u8 data; 76109ea33e5SIgor M. Liplianin 76209ea33e5SIgor M. Liplianin dprintk("%s()\n", __func__); 76309ea33e5SIgor M. Liplianin 76409ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 76509ea33e5SIgor M. Liplianin data &= ~0xc0; 76609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 76709ea33e5SIgor M. Liplianin 76809ea33e5SIgor M. Liplianin /* DiSEqC burst */ 76909ea33e5SIgor M. Liplianin if (burst == SEC_MINI_A) 77009ea33e5SIgor M. Liplianin /* Unmodulated tone burst */ 77109ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa1, 0x02); 77209ea33e5SIgor M. Liplianin else if (burst == SEC_MINI_B) 77309ea33e5SIgor M. Liplianin /* Modulated tone burst */ 77409ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa1, 0x01); 77509ea33e5SIgor M. Liplianin else 77609ea33e5SIgor M. Liplianin return -EINVAL; 77709ea33e5SIgor M. Liplianin 77809ea33e5SIgor M. Liplianin msleep(13); 77909ea33e5SIgor M. Liplianin for (i = 0; i < 5; i++) { 78009ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa1); 78109ea33e5SIgor M. Liplianin if ((data & 0x40) == 0) 78209ea33e5SIgor M. Liplianin break; 78309ea33e5SIgor M. Liplianin msleep(1); 78409ea33e5SIgor M. Liplianin } 78509ea33e5SIgor M. Liplianin 78609ea33e5SIgor M. Liplianin if (i == 5) { 78709ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa1); 78809ea33e5SIgor M. Liplianin data &= ~0x80; 78909ea33e5SIgor M. Liplianin data |= 0x40; 79009ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa1, data); 79109ea33e5SIgor M. Liplianin 79209ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 79309ea33e5SIgor M. Liplianin data &= ~0xc0; 79409ea33e5SIgor M. Liplianin data |= 0x80; 79509ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 79609ea33e5SIgor M. Liplianin 79727924dccSOlli Salonen return -ETIMEDOUT; 79809ea33e5SIgor M. Liplianin } 79909ea33e5SIgor M. Liplianin 80009ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 80109ea33e5SIgor M. Liplianin data &= ~0xc0; 80209ea33e5SIgor M. Liplianin data |= 0x80; 80309ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 80409ea33e5SIgor M. Liplianin 80509ea33e5SIgor M. Liplianin return 0; 80609ea33e5SIgor M. Liplianin } 80709ea33e5SIgor M. Liplianin 80809ea33e5SIgor M. Liplianin static void ds3000_release(struct dvb_frontend *fe) 80909ea33e5SIgor M. Liplianin { 81009ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 81143385c8aSIgor M. Liplianin 81243385c8aSIgor M. Liplianin if (state->config->set_lock_led) 81343385c8aSIgor M. Liplianin state->config->set_lock_led(fe, 0); 81443385c8aSIgor M. Liplianin 81509ea33e5SIgor M. Liplianin dprintk("%s\n", __func__); 81609ea33e5SIgor M. Liplianin kfree(state); 81709ea33e5SIgor M. Liplianin } 81809ea33e5SIgor M. Liplianin 819bd336e63SMax Kellermann static const struct dvb_frontend_ops ds3000_ops; 82009ea33e5SIgor M. Liplianin 82109ea33e5SIgor M. Liplianin struct dvb_frontend *ds3000_attach(const struct ds3000_config *config, 82209ea33e5SIgor M. Liplianin struct i2c_adapter *i2c) 82309ea33e5SIgor M. Liplianin { 824d303b7c5SMarkus Elfring struct ds3000_state *state; 82509ea33e5SIgor M. Liplianin int ret; 82609ea33e5SIgor M. Liplianin 82709ea33e5SIgor M. Liplianin dprintk("%s\n", __func__); 82809ea33e5SIgor M. Liplianin 82909ea33e5SIgor M. Liplianin /* allocate memory for the internal state */ 8302d3da59fSMarkus Elfring state = kzalloc(sizeof(*state), GFP_KERNEL); 831c38e8657SMarkus Elfring if (!state) 8329722e569SMarkus Elfring return NULL; 83309ea33e5SIgor M. Liplianin 83409ea33e5SIgor M. Liplianin state->config = config; 83509ea33e5SIgor M. Liplianin state->i2c = i2c; 83609ea33e5SIgor M. Liplianin state->prevUCBS2 = 0; 83709ea33e5SIgor M. Liplianin 83809ea33e5SIgor M. Liplianin /* check if the demod is present */ 83909ea33e5SIgor M. Liplianin ret = ds3000_readreg(state, 0x00) & 0xfe; 84009ea33e5SIgor M. Liplianin if (ret != 0xe0) { 8419722e569SMarkus Elfring kfree(state); 84209ea33e5SIgor M. Liplianin printk(KERN_ERR "Invalid probe, probably not a DS3000\n"); 8439722e569SMarkus Elfring return NULL; 84409ea33e5SIgor M. Liplianin } 84509ea33e5SIgor M. Liplianin 84609ea33e5SIgor M. Liplianin printk(KERN_INFO "DS3000 chip version: %d.%d attached.\n", 84709ea33e5SIgor M. Liplianin ds3000_readreg(state, 0x02), 84809ea33e5SIgor M. Liplianin ds3000_readreg(state, 0x01)); 84909ea33e5SIgor M. Liplianin 85009ea33e5SIgor M. Liplianin memcpy(&state->frontend.ops, &ds3000_ops, 85109ea33e5SIgor M. Liplianin sizeof(struct dvb_frontend_ops)); 85209ea33e5SIgor M. Liplianin state->frontend.demodulator_priv = state; 8538c5bcdedSUlrich Eckhardt 8548c5bcdedSUlrich Eckhardt /* 8558c5bcdedSUlrich Eckhardt * Some devices like T480 starts with voltage on. Be sure 8568c5bcdedSUlrich Eckhardt * to turn voltage off during init, as this can otherwise 8578c5bcdedSUlrich Eckhardt * interfere with Unicable SCR systems. 8588c5bcdedSUlrich Eckhardt */ 8598c5bcdedSUlrich Eckhardt ds3000_set_voltage(&state->frontend, SEC_VOLTAGE_OFF); 86009ea33e5SIgor M. Liplianin return &state->frontend; 86109ea33e5SIgor M. Liplianin } 86209ea33e5SIgor M. Liplianin EXPORT_SYMBOL(ds3000_attach); 86309ea33e5SIgor M. Liplianin 864a5bf834bSIgor M. Liplianin static int ds3000_set_carrier_offset(struct dvb_frontend *fe, 865a5bf834bSIgor M. Liplianin s32 carrier_offset_khz) 866a5bf834bSIgor M. Liplianin { 867a5bf834bSIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 868a5bf834bSIgor M. Liplianin s32 tmp; 869a5bf834bSIgor M. Liplianin 870a5bf834bSIgor M. Liplianin tmp = carrier_offset_khz; 871a5bf834bSIgor M. Liplianin tmp *= 65536; 872a5bf834bSIgor M. Liplianin tmp = (2 * tmp + DS3000_SAMPLE_RATE) / (2 * DS3000_SAMPLE_RATE); 873a5bf834bSIgor M. Liplianin 874a5bf834bSIgor M. Liplianin if (tmp < 0) 875a5bf834bSIgor M. Liplianin tmp += 65536; 876a5bf834bSIgor M. Liplianin 877a5bf834bSIgor M. Liplianin ds3000_writereg(state, 0x5f, tmp >> 8); 878a5bf834bSIgor M. Liplianin ds3000_writereg(state, 0x5e, tmp & 0xff); 879a5bf834bSIgor M. Liplianin 880a5bf834bSIgor M. Liplianin return 0; 881a5bf834bSIgor M. Liplianin } 882a5bf834bSIgor M. Liplianin 8839fe33018SMauro Carvalho Chehab static int ds3000_set_frontend(struct dvb_frontend *fe) 88409ea33e5SIgor M. Liplianin { 88509ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 88609ea33e5SIgor M. Liplianin struct dtv_frontend_properties *c = &fe->dtv_property_cache; 88709ea33e5SIgor M. Liplianin 88818a73f36SIgor M. Liplianin int i; 8890df289a2SMauro Carvalho Chehab enum fe_status status; 890a5bf834bSIgor M. Liplianin s32 offset_khz; 891c1965eaeSKonstantin Dimitrov u32 frequency; 892c1965eaeSKonstantin Dimitrov u16 value; 89309ea33e5SIgor M. Liplianin 89409ea33e5SIgor M. Liplianin dprintk("%s() ", __func__); 89509ea33e5SIgor M. Liplianin 8960cb73639SIgor M. Liplianin if (state->config->set_ts_params) 8970cb73639SIgor M. Liplianin state->config->set_ts_params(fe, 0); 89809ea33e5SIgor M. Liplianin /* Tune */ 899c1965eaeSKonstantin Dimitrov if (fe->ops.tuner_ops.set_params) 900c1965eaeSKonstantin Dimitrov fe->ops.tuner_ops.set_params(fe); 901a5bf834bSIgor M. Liplianin 90209ea33e5SIgor M. Liplianin /* ds3000 global reset */ 90309ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x07, 0x80); 90409ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x07, 0x00); 905868c9a17SMauro Carvalho Chehab /* ds3000 built-in uC reset */ 90609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xb2, 0x01); 90709ea33e5SIgor M. Liplianin /* ds3000 software reset */ 90809ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x00, 0x01); 90909ea33e5SIgor M. Liplianin 91009ea33e5SIgor M. Liplianin switch (c->delivery_system) { 91109ea33e5SIgor M. Liplianin case SYS_DVBS: 91209ea33e5SIgor M. Liplianin /* initialise the demod in DVB-S mode */ 91309ea33e5SIgor M. Liplianin for (i = 0; i < sizeof(ds3000_dvbs_init_tab); i += 2) 91409ea33e5SIgor M. Liplianin ds3000_writereg(state, 91509ea33e5SIgor M. Liplianin ds3000_dvbs_init_tab[i], 91609ea33e5SIgor M. Liplianin ds3000_dvbs_init_tab[i + 1]); 91709ea33e5SIgor M. Liplianin value = ds3000_readreg(state, 0xfe); 91809ea33e5SIgor M. Liplianin value &= 0xc0; 91909ea33e5SIgor M. Liplianin value |= 0x1b; 92009ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xfe, value); 92109ea33e5SIgor M. Liplianin break; 92209ea33e5SIgor M. Liplianin case SYS_DVBS2: 92309ea33e5SIgor M. Liplianin /* initialise the demod in DVB-S2 mode */ 92409ea33e5SIgor M. Liplianin for (i = 0; i < sizeof(ds3000_dvbs2_init_tab); i += 2) 92509ea33e5SIgor M. Liplianin ds3000_writereg(state, 92609ea33e5SIgor M. Liplianin ds3000_dvbs2_init_tab[i], 92709ea33e5SIgor M. Liplianin ds3000_dvbs2_init_tab[i + 1]); 9287b134e85SIgor M. Liplianin if (c->symbol_rate >= 30000000) 9297b134e85SIgor M. Liplianin ds3000_writereg(state, 0xfe, 0x54); 9307b134e85SIgor M. Liplianin else 9312a66bf37SIgor M. Liplianin ds3000_writereg(state, 0xfe, 0x98); 93209ea33e5SIgor M. Liplianin break; 93309ea33e5SIgor M. Liplianin default: 93427924dccSOlli Salonen return -EINVAL; 93509ea33e5SIgor M. Liplianin } 93609ea33e5SIgor M. Liplianin 93709ea33e5SIgor M. Liplianin /* enable 27MHz clock output */ 93809ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x29, 0x80); 93909ea33e5SIgor M. Liplianin /* enable ac coupling */ 94009ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x25, 0x8a); 94109ea33e5SIgor M. Liplianin 942212fa081SOlli Salonen if ((c->symbol_rate < ds3000_ops.info.symbol_rate_min) || 943212fa081SOlli Salonen (c->symbol_rate > ds3000_ops.info.symbol_rate_max)) { 944212fa081SOlli Salonen dprintk("%s() symbol_rate %u out of range (%u ... %u)\n", 945212fa081SOlli Salonen __func__, c->symbol_rate, 946212fa081SOlli Salonen ds3000_ops.info.symbol_rate_min, 947212fa081SOlli Salonen ds3000_ops.info.symbol_rate_max); 948212fa081SOlli Salonen return -EINVAL; 949212fa081SOlli Salonen } 950212fa081SOlli Salonen 95109ea33e5SIgor M. Liplianin /* enhance symbol rate performance */ 952cb8f74daSIgor M. Liplianin if ((c->symbol_rate / 1000) <= 5000) { 953cb8f74daSIgor M. Liplianin value = 29777 / (c->symbol_rate / 1000) + 1; 95409ea33e5SIgor M. Liplianin if (value % 2 != 0) 95509ea33e5SIgor M. Liplianin value++; 95609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc3, 0x0d); 95709ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc8, value); 95809ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc4, 0x10); 95909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc7, 0x0e); 960cb8f74daSIgor M. Liplianin } else if ((c->symbol_rate / 1000) <= 10000) { 961cb8f74daSIgor M. Liplianin value = 92166 / (c->symbol_rate / 1000) + 1; 96209ea33e5SIgor M. Liplianin if (value % 2 != 0) 96309ea33e5SIgor M. Liplianin value++; 96409ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc3, 0x07); 96509ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc8, value); 96609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc4, 0x09); 96709ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc7, 0x12); 968cb8f74daSIgor M. Liplianin } else if ((c->symbol_rate / 1000) <= 20000) { 969cb8f74daSIgor M. Liplianin value = 64516 / (c->symbol_rate / 1000) + 1; 97009ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc3, value); 97109ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc8, 0x0e); 97209ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc4, 0x07); 97309ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc7, 0x18); 97409ea33e5SIgor M. Liplianin } else { 975cb8f74daSIgor M. Liplianin value = 129032 / (c->symbol_rate / 1000) + 1; 97609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc3, value); 97709ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc8, 0x0a); 97809ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc4, 0x05); 97909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc7, 0x24); 98009ea33e5SIgor M. Liplianin } 98109ea33e5SIgor M. Liplianin 98209ea33e5SIgor M. Liplianin /* normalized symbol rate rounded to the closest integer */ 983cb8f74daSIgor M. Liplianin value = (((c->symbol_rate / 1000) << 16) + 98409ea33e5SIgor M. Liplianin (DS3000_SAMPLE_RATE / 2)) / DS3000_SAMPLE_RATE; 98509ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x61, value & 0x00ff); 98609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x62, (value & 0xff00) >> 8); 98709ea33e5SIgor M. Liplianin 98809ea33e5SIgor M. Liplianin /* co-channel interference cancellation disabled */ 98909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x56, 0x00); 99009ea33e5SIgor M. Liplianin 99109ea33e5SIgor M. Liplianin /* equalizer disabled */ 99209ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x76, 0x00); 99309ea33e5SIgor M. Liplianin 99409ea33e5SIgor M. Liplianin /*ds3000_writereg(state, 0x08, 0x03); 99509ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xfd, 0x22); 99609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x08, 0x07); 99709ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xfd, 0x42); 99809ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x08, 0x07);*/ 99909ea33e5SIgor M. Liplianin 1000d2ffc447SIgor M. Liplianin if (state->config->ci_mode) { 1001d2ffc447SIgor M. Liplianin switch (c->delivery_system) { 1002d2ffc447SIgor M. Liplianin case SYS_DVBS: 1003d2ffc447SIgor M. Liplianin default: 1004d2ffc447SIgor M. Liplianin ds3000_writereg(state, 0xfd, 0x80); 1005d2ffc447SIgor M. Liplianin break; 1006d2ffc447SIgor M. Liplianin case SYS_DVBS2: 1007d2ffc447SIgor M. Liplianin ds3000_writereg(state, 0xfd, 0x01); 1008d2ffc447SIgor M. Liplianin break; 1009d2ffc447SIgor M. Liplianin } 1010d2ffc447SIgor M. Liplianin } 1011d2ffc447SIgor M. Liplianin 101209ea33e5SIgor M. Liplianin /* ds3000 out of software reset */ 101309ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x00, 0x00); 1014868c9a17SMauro Carvalho Chehab /* start ds3000 built-in uC */ 101509ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xb2, 0x00); 101609ea33e5SIgor M. Liplianin 1017c1965eaeSKonstantin Dimitrov if (fe->ops.tuner_ops.get_frequency) { 1018c1965eaeSKonstantin Dimitrov fe->ops.tuner_ops.get_frequency(fe, &frequency); 1019c1965eaeSKonstantin Dimitrov offset_khz = frequency - c->frequency; 1020a5bf834bSIgor M. Liplianin ds3000_set_carrier_offset(fe, offset_khz); 1021c1965eaeSKonstantin Dimitrov } 102209ea33e5SIgor M. Liplianin 102309ea33e5SIgor M. Liplianin for (i = 0; i < 30 ; i++) { 102418a73f36SIgor M. Liplianin ds3000_read_status(fe, &status); 10253a9888f9SDan Carpenter if (status & FE_HAS_LOCK) 102618a73f36SIgor M. Liplianin break; 102718a73f36SIgor M. Liplianin 102818a73f36SIgor M. Liplianin msleep(10); 102909ea33e5SIgor M. Liplianin } 103009ea33e5SIgor M. Liplianin 103118a73f36SIgor M. Liplianin return 0; 103209ea33e5SIgor M. Liplianin } 103309ea33e5SIgor M. Liplianin 1034dcc8a122SIgor M. Liplianin static int ds3000_tune(struct dvb_frontend *fe, 10357e072221SMauro Carvalho Chehab bool re_tune, 1036738e8ff9SIgor M. Liplianin unsigned int mode_flags, 1037738e8ff9SIgor M. Liplianin unsigned int *delay, 10380df289a2SMauro Carvalho Chehab enum fe_status *status) 1039dcc8a122SIgor M. Liplianin { 10407e072221SMauro Carvalho Chehab if (re_tune) { 10419fe33018SMauro Carvalho Chehab int ret = ds3000_set_frontend(fe); 1042738e8ff9SIgor M. Liplianin if (ret) 1043738e8ff9SIgor M. Liplianin return ret; 1044738e8ff9SIgor M. Liplianin } 1045738e8ff9SIgor M. Liplianin 1046738e8ff9SIgor M. Liplianin *delay = HZ / 5; 1047738e8ff9SIgor M. Liplianin 1048738e8ff9SIgor M. Liplianin return ds3000_read_status(fe, status); 1049dcc8a122SIgor M. Liplianin } 1050dcc8a122SIgor M. Liplianin 105109ea33e5SIgor M. Liplianin static enum dvbfe_algo ds3000_get_algo(struct dvb_frontend *fe) 105209ea33e5SIgor M. Liplianin { 105343385c8aSIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 105443385c8aSIgor M. Liplianin 105543385c8aSIgor M. Liplianin if (state->config->set_lock_led) 105643385c8aSIgor M. Liplianin state->config->set_lock_led(fe, 0); 105743385c8aSIgor M. Liplianin 105809ea33e5SIgor M. Liplianin dprintk("%s()\n", __func__); 1059dcc8a122SIgor M. Liplianin return DVBFE_ALGO_HW; 106009ea33e5SIgor M. Liplianin } 106109ea33e5SIgor M. Liplianin 106209ea33e5SIgor M. Liplianin /* 106309ea33e5SIgor M. Liplianin * Initialise or wake up device 106409ea33e5SIgor M. Liplianin * 106509ea33e5SIgor M. Liplianin * Power config will reset and load initial firmware if required 106609ea33e5SIgor M. Liplianin */ 106709ea33e5SIgor M. Liplianin static int ds3000_initfe(struct dvb_frontend *fe) 106809ea33e5SIgor M. Liplianin { 1069a0ea298dSIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 1070a0ea298dSIgor M. Liplianin int ret; 1071a0ea298dSIgor M. Liplianin 107209ea33e5SIgor M. Liplianin dprintk("%s()\n", __func__); 1073a0ea298dSIgor M. Liplianin /* hard reset */ 1074a0ea298dSIgor M. Liplianin ds3000_writereg(state, 0x08, 0x01 | ds3000_readreg(state, 0x08)); 1075a0ea298dSIgor M. Liplianin msleep(1); 1076a0ea298dSIgor M. Liplianin 1077b9bf2eafSIgor M. Liplianin /* Load the firmware if required */ 1078b9bf2eafSIgor M. Liplianin ret = ds3000_firmware_ondemand(fe); 1079b9bf2eafSIgor M. Liplianin if (ret != 0) { 1080b9bf2eafSIgor M. Liplianin printk(KERN_ERR "%s: Unable initialize firmware\n", __func__); 1081b9bf2eafSIgor M. Liplianin return ret; 1082b9bf2eafSIgor M. Liplianin } 1083a0ea298dSIgor M. Liplianin 108409ea33e5SIgor M. Liplianin return 0; 108509ea33e5SIgor M. Liplianin } 108609ea33e5SIgor M. Liplianin 1087bd336e63SMax Kellermann static const struct dvb_frontend_ops ds3000_ops = { 10889fe33018SMauro Carvalho Chehab .delsys = { SYS_DVBS, SYS_DVBS2 }, 108909ea33e5SIgor M. Liplianin .info = { 1090c1965eaeSKonstantin Dimitrov .name = "Montage Technology DS3000", 1091f1b1eabfSMauro Carvalho Chehab .frequency_min_hz = 950 * MHz, 1092f1b1eabfSMauro Carvalho Chehab .frequency_max_hz = 2150 * MHz, 1093f1b1eabfSMauro Carvalho Chehab .frequency_stepsize_hz = 1011 * kHz, 1094f1b1eabfSMauro Carvalho Chehab .frequency_tolerance_hz = 5 * MHz, 109509ea33e5SIgor M. Liplianin .symbol_rate_min = 1000000, 109609ea33e5SIgor M. Liplianin .symbol_rate_max = 45000000, 109709ea33e5SIgor M. Liplianin .caps = FE_CAN_INVERSION_AUTO | 109809ea33e5SIgor M. Liplianin FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 109909ea33e5SIgor M. Liplianin FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | 110009ea33e5SIgor M. Liplianin FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 110109ea33e5SIgor M. Liplianin FE_CAN_2G_MODULATION | 110209ea33e5SIgor M. Liplianin FE_CAN_QPSK | FE_CAN_RECOVER 110309ea33e5SIgor M. Liplianin }, 110409ea33e5SIgor M. Liplianin 110509ea33e5SIgor M. Liplianin .release = ds3000_release, 110609ea33e5SIgor M. Liplianin 110709ea33e5SIgor M. Liplianin .init = ds3000_initfe, 1108c1965eaeSKonstantin Dimitrov .i2c_gate_ctrl = ds3000_i2c_gate_ctrl, 110909ea33e5SIgor M. Liplianin .read_status = ds3000_read_status, 111009ea33e5SIgor M. Liplianin .read_ber = ds3000_read_ber, 1111a0a030bdSMalcolm Priestley .read_signal_strength = ds3000_read_signal_strength, 111209ea33e5SIgor M. Liplianin .read_snr = ds3000_read_snr, 111309ea33e5SIgor M. Liplianin .read_ucblocks = ds3000_read_ucblocks, 1114d2ffc447SIgor M. Liplianin .set_voltage = ds3000_set_voltage, 111509ea33e5SIgor M. Liplianin .set_tone = ds3000_set_tone, 111609ea33e5SIgor M. Liplianin .diseqc_send_master_cmd = ds3000_send_diseqc_msg, 111709ea33e5SIgor M. Liplianin .diseqc_send_burst = ds3000_diseqc_send_burst, 111809ea33e5SIgor M. Liplianin .get_frontend_algo = ds3000_get_algo, 111909ea33e5SIgor M. Liplianin 11209fe33018SMauro Carvalho Chehab .set_frontend = ds3000_set_frontend, 1121dcc8a122SIgor M. Liplianin .tune = ds3000_tune, 112209ea33e5SIgor M. Liplianin }; 112309ea33e5SIgor M. Liplianin 112409ea33e5SIgor M. Liplianin module_param(debug, int, 0644); 112509ea33e5SIgor M. Liplianin MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); 112609ea33e5SIgor M. Liplianin 11274bd69e7bSMauro Carvalho Chehab MODULE_DESCRIPTION("DVB Frontend module for Montage Technology DS3000 hardware"); 1128c1965eaeSKonstantin Dimitrov MODULE_AUTHOR("Konstantin Dimitrov <kosio.dimitrov@gmail.com>"); 112909ea33e5SIgor M. Liplianin MODULE_LICENSE("GPL"); 1130feadd7d3SRémi Cardona MODULE_FIRMWARE(DS3000_DEFAULT_FIRMWARE); 1131