109ea33e5SIgor M. Liplianin /* 2*c1965eaeSKonstantin Dimitrov Montage Technology DS3000 - DVBS/S2 Demodulator driver 3*c1965eaeSKonstantin Dimitrov Copyright (C) 2009-2012 Konstantin Dimitrov <kosio.dimitrov@gmail.com> 409ea33e5SIgor M. Liplianin 5*c1965eaeSKonstantin Dimitrov Copyright (C) 2009-2012 TurboSight.com 609ea33e5SIgor M. Liplianin 709ea33e5SIgor M. Liplianin This program is free software; you can redistribute it and/or modify 809ea33e5SIgor M. Liplianin it under the terms of the GNU General Public License as published by 909ea33e5SIgor M. Liplianin the Free Software Foundation; either version 2 of the License, or 1009ea33e5SIgor M. Liplianin (at your option) any later version. 1109ea33e5SIgor M. Liplianin 1209ea33e5SIgor M. Liplianin This program is distributed in the hope that it will be useful, 1309ea33e5SIgor M. Liplianin but WITHOUT ANY WARRANTY; without even the implied warranty of 1409ea33e5SIgor M. Liplianin MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1509ea33e5SIgor M. Liplianin GNU General Public License for more details. 1609ea33e5SIgor M. Liplianin 1709ea33e5SIgor M. Liplianin You should have received a copy of the GNU General Public License 1809ea33e5SIgor M. Liplianin along with this program; if not, write to the Free Software 1909ea33e5SIgor M. Liplianin Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 2009ea33e5SIgor M. Liplianin */ 2109ea33e5SIgor M. Liplianin 2209ea33e5SIgor M. Liplianin #include <linux/slab.h> 2309ea33e5SIgor M. Liplianin #include <linux/kernel.h> 2409ea33e5SIgor M. Liplianin #include <linux/module.h> 2509ea33e5SIgor M. Liplianin #include <linux/moduleparam.h> 2609ea33e5SIgor M. Liplianin #include <linux/init.h> 2709ea33e5SIgor M. Liplianin #include <linux/firmware.h> 2809ea33e5SIgor M. Liplianin 2909ea33e5SIgor M. Liplianin #include "dvb_frontend.h" 3009ea33e5SIgor M. Liplianin #include "ds3000.h" 3109ea33e5SIgor M. Liplianin 3209ea33e5SIgor M. Liplianin static int debug; 3309ea33e5SIgor M. Liplianin 3409ea33e5SIgor M. Liplianin #define dprintk(args...) \ 3509ea33e5SIgor M. Liplianin do { \ 3609ea33e5SIgor M. Liplianin if (debug) \ 3709ea33e5SIgor M. Liplianin printk(args); \ 3809ea33e5SIgor M. Liplianin } while (0) 3909ea33e5SIgor M. Liplianin 4009ea33e5SIgor M. Liplianin /* as of March 2009 current DS3000 firmware version is 1.78 */ 4109ea33e5SIgor M. Liplianin /* DS3000 FW v1.78 MD5: a32d17910c4f370073f9346e71d34b80 */ 4209ea33e5SIgor M. Liplianin #define DS3000_DEFAULT_FIRMWARE "dvb-fe-ds3000.fw" 4309ea33e5SIgor M. Liplianin 4409ea33e5SIgor M. Liplianin #define DS3000_SAMPLE_RATE 96000 /* in kHz */ 4509ea33e5SIgor M. Liplianin 4609ea33e5SIgor M. Liplianin /* Register values to initialise the demod in DVB-S mode */ 4709ea33e5SIgor M. Liplianin static u8 ds3000_dvbs_init_tab[] = { 4809ea33e5SIgor M. Liplianin 0x23, 0x05, 4909ea33e5SIgor M. Liplianin 0x08, 0x03, 5009ea33e5SIgor M. Liplianin 0x0c, 0x00, 5109ea33e5SIgor M. Liplianin 0x21, 0x54, 5209ea33e5SIgor M. Liplianin 0x25, 0x82, 5309ea33e5SIgor M. Liplianin 0x27, 0x31, 5409ea33e5SIgor M. Liplianin 0x30, 0x08, 5509ea33e5SIgor M. Liplianin 0x31, 0x40, 5609ea33e5SIgor M. Liplianin 0x32, 0x32, 5709ea33e5SIgor M. Liplianin 0x33, 0x35, 5809ea33e5SIgor M. Liplianin 0x35, 0xff, 5909ea33e5SIgor M. Liplianin 0x3a, 0x00, 6009ea33e5SIgor M. Liplianin 0x37, 0x10, 6109ea33e5SIgor M. Liplianin 0x38, 0x10, 6209ea33e5SIgor M. Liplianin 0x39, 0x02, 6309ea33e5SIgor M. Liplianin 0x42, 0x60, 6409ea33e5SIgor M. Liplianin 0x4a, 0x40, 6509ea33e5SIgor M. Liplianin 0x4b, 0x04, 6609ea33e5SIgor M. Liplianin 0x4d, 0x91, 6709ea33e5SIgor M. Liplianin 0x5d, 0xc8, 6809ea33e5SIgor M. Liplianin 0x50, 0x77, 6909ea33e5SIgor M. Liplianin 0x51, 0x77, 7009ea33e5SIgor M. Liplianin 0x52, 0x36, 7109ea33e5SIgor M. Liplianin 0x53, 0x36, 7209ea33e5SIgor M. Liplianin 0x56, 0x01, 7309ea33e5SIgor M. Liplianin 0x63, 0x43, 7409ea33e5SIgor M. Liplianin 0x64, 0x30, 7509ea33e5SIgor M. Liplianin 0x65, 0x40, 7609ea33e5SIgor M. Liplianin 0x68, 0x26, 7709ea33e5SIgor M. Liplianin 0x69, 0x4c, 7809ea33e5SIgor M. Liplianin 0x70, 0x20, 7909ea33e5SIgor M. Liplianin 0x71, 0x70, 8009ea33e5SIgor M. Liplianin 0x72, 0x04, 8109ea33e5SIgor M. Liplianin 0x73, 0x00, 8209ea33e5SIgor M. Liplianin 0x70, 0x40, 8309ea33e5SIgor M. Liplianin 0x71, 0x70, 8409ea33e5SIgor M. Liplianin 0x72, 0x04, 8509ea33e5SIgor M. Liplianin 0x73, 0x00, 8609ea33e5SIgor M. Liplianin 0x70, 0x60, 8709ea33e5SIgor M. Liplianin 0x71, 0x70, 8809ea33e5SIgor M. Liplianin 0x72, 0x04, 8909ea33e5SIgor M. Liplianin 0x73, 0x00, 9009ea33e5SIgor M. Liplianin 0x70, 0x80, 9109ea33e5SIgor M. Liplianin 0x71, 0x70, 9209ea33e5SIgor M. Liplianin 0x72, 0x04, 9309ea33e5SIgor M. Liplianin 0x73, 0x00, 9409ea33e5SIgor M. Liplianin 0x70, 0xa0, 9509ea33e5SIgor M. Liplianin 0x71, 0x70, 9609ea33e5SIgor M. Liplianin 0x72, 0x04, 9709ea33e5SIgor M. Liplianin 0x73, 0x00, 9809ea33e5SIgor M. Liplianin 0x70, 0x1f, 9909ea33e5SIgor M. Liplianin 0x76, 0x00, 10009ea33e5SIgor M. Liplianin 0x77, 0xd1, 10109ea33e5SIgor M. Liplianin 0x78, 0x0c, 10209ea33e5SIgor M. Liplianin 0x79, 0x80, 10309ea33e5SIgor M. Liplianin 0x7f, 0x04, 10409ea33e5SIgor M. Liplianin 0x7c, 0x00, 10509ea33e5SIgor M. Liplianin 0x80, 0x86, 10609ea33e5SIgor M. Liplianin 0x81, 0xa6, 10709ea33e5SIgor M. Liplianin 0x85, 0x04, 10809ea33e5SIgor M. Liplianin 0xcd, 0xf4, 10909ea33e5SIgor M. Liplianin 0x90, 0x33, 11009ea33e5SIgor M. Liplianin 0xa0, 0x44, 11109ea33e5SIgor M. Liplianin 0xc0, 0x18, 11209ea33e5SIgor M. Liplianin 0xc3, 0x10, 11309ea33e5SIgor M. Liplianin 0xc4, 0x08, 11409ea33e5SIgor M. Liplianin 0xc5, 0x80, 11509ea33e5SIgor M. Liplianin 0xc6, 0x80, 11609ea33e5SIgor M. Liplianin 0xc7, 0x0a, 11709ea33e5SIgor M. Liplianin 0xc8, 0x1a, 11809ea33e5SIgor M. Liplianin 0xc9, 0x80, 11909ea33e5SIgor M. Liplianin 0xfe, 0x92, 12009ea33e5SIgor M. Liplianin 0xe0, 0xf8, 12109ea33e5SIgor M. Liplianin 0xe6, 0x8b, 12209ea33e5SIgor M. Liplianin 0xd0, 0x40, 12309ea33e5SIgor M. Liplianin 0xf8, 0x20, 12409ea33e5SIgor M. Liplianin 0xfa, 0x0f, 12509ea33e5SIgor M. Liplianin 0xfd, 0x20, 12609ea33e5SIgor M. Liplianin 0xad, 0x20, 12709ea33e5SIgor M. Liplianin 0xae, 0x07, 12809ea33e5SIgor M. Liplianin 0xb8, 0x00, 12909ea33e5SIgor M. Liplianin }; 13009ea33e5SIgor M. Liplianin 13109ea33e5SIgor M. Liplianin /* Register values to initialise the demod in DVB-S2 mode */ 13209ea33e5SIgor M. Liplianin static u8 ds3000_dvbs2_init_tab[] = { 13309ea33e5SIgor M. Liplianin 0x23, 0x0f, 13409ea33e5SIgor M. Liplianin 0x08, 0x07, 13509ea33e5SIgor M. Liplianin 0x0c, 0x00, 13609ea33e5SIgor M. Liplianin 0x21, 0x54, 13709ea33e5SIgor M. Liplianin 0x25, 0x82, 13809ea33e5SIgor M. Liplianin 0x27, 0x31, 13909ea33e5SIgor M. Liplianin 0x30, 0x08, 14009ea33e5SIgor M. Liplianin 0x31, 0x32, 14109ea33e5SIgor M. Liplianin 0x32, 0x32, 14209ea33e5SIgor M. Liplianin 0x33, 0x35, 14309ea33e5SIgor M. Liplianin 0x35, 0xff, 14409ea33e5SIgor M. Liplianin 0x3a, 0x00, 14509ea33e5SIgor M. Liplianin 0x37, 0x10, 14609ea33e5SIgor M. Liplianin 0x38, 0x10, 14709ea33e5SIgor M. Liplianin 0x39, 0x02, 14809ea33e5SIgor M. Liplianin 0x42, 0x60, 14909ea33e5SIgor M. Liplianin 0x4a, 0x80, 15009ea33e5SIgor M. Liplianin 0x4b, 0x04, 15109ea33e5SIgor M. Liplianin 0x4d, 0x81, 15209ea33e5SIgor M. Liplianin 0x5d, 0x88, 15309ea33e5SIgor M. Liplianin 0x50, 0x36, 15409ea33e5SIgor M. Liplianin 0x51, 0x36, 15509ea33e5SIgor M. Liplianin 0x52, 0x36, 15609ea33e5SIgor M. Liplianin 0x53, 0x36, 15709ea33e5SIgor M. Liplianin 0x63, 0x60, 15809ea33e5SIgor M. Liplianin 0x64, 0x10, 15909ea33e5SIgor M. Liplianin 0x65, 0x10, 16009ea33e5SIgor M. Liplianin 0x68, 0x04, 16109ea33e5SIgor M. Liplianin 0x69, 0x29, 16209ea33e5SIgor M. Liplianin 0x70, 0x20, 16309ea33e5SIgor M. Liplianin 0x71, 0x70, 16409ea33e5SIgor M. Liplianin 0x72, 0x04, 16509ea33e5SIgor M. Liplianin 0x73, 0x00, 16609ea33e5SIgor M. Liplianin 0x70, 0x40, 16709ea33e5SIgor M. Liplianin 0x71, 0x70, 16809ea33e5SIgor M. Liplianin 0x72, 0x04, 16909ea33e5SIgor M. Liplianin 0x73, 0x00, 17009ea33e5SIgor M. Liplianin 0x70, 0x60, 17109ea33e5SIgor M. Liplianin 0x71, 0x70, 17209ea33e5SIgor M. Liplianin 0x72, 0x04, 17309ea33e5SIgor M. Liplianin 0x73, 0x00, 17409ea33e5SIgor M. Liplianin 0x70, 0x80, 17509ea33e5SIgor M. Liplianin 0x71, 0x70, 17609ea33e5SIgor M. Liplianin 0x72, 0x04, 17709ea33e5SIgor M. Liplianin 0x73, 0x00, 17809ea33e5SIgor M. Liplianin 0x70, 0xa0, 17909ea33e5SIgor M. Liplianin 0x71, 0x70, 18009ea33e5SIgor M. Liplianin 0x72, 0x04, 18109ea33e5SIgor M. Liplianin 0x73, 0x00, 18209ea33e5SIgor M. Liplianin 0x70, 0x1f, 18309ea33e5SIgor M. Liplianin 0xa0, 0x44, 18409ea33e5SIgor M. Liplianin 0xc0, 0x08, 18509ea33e5SIgor M. Liplianin 0xc1, 0x10, 18609ea33e5SIgor M. Liplianin 0xc2, 0x08, 18709ea33e5SIgor M. Liplianin 0xc3, 0x10, 18809ea33e5SIgor M. Liplianin 0xc4, 0x08, 18909ea33e5SIgor M. Liplianin 0xc5, 0xf0, 19009ea33e5SIgor M. Liplianin 0xc6, 0xf0, 19109ea33e5SIgor M. Liplianin 0xc7, 0x0a, 19209ea33e5SIgor M. Liplianin 0xc8, 0x1a, 19309ea33e5SIgor M. Liplianin 0xc9, 0x80, 19409ea33e5SIgor M. Liplianin 0xca, 0x23, 19509ea33e5SIgor M. Liplianin 0xcb, 0x24, 19609ea33e5SIgor M. Liplianin 0xce, 0x74, 19709ea33e5SIgor M. Liplianin 0x90, 0x03, 19809ea33e5SIgor M. Liplianin 0x76, 0x80, 19909ea33e5SIgor M. Liplianin 0x77, 0x42, 20009ea33e5SIgor M. Liplianin 0x78, 0x0a, 20109ea33e5SIgor M. Liplianin 0x79, 0x80, 20209ea33e5SIgor M. Liplianin 0xad, 0x40, 20309ea33e5SIgor M. Liplianin 0xae, 0x07, 20409ea33e5SIgor M. Liplianin 0x7f, 0xd4, 20509ea33e5SIgor M. Liplianin 0x7c, 0x00, 20609ea33e5SIgor M. Liplianin 0x80, 0xa8, 20709ea33e5SIgor M. Liplianin 0x81, 0xda, 20809ea33e5SIgor M. Liplianin 0x7c, 0x01, 20909ea33e5SIgor M. Liplianin 0x80, 0xda, 21009ea33e5SIgor M. Liplianin 0x81, 0xec, 21109ea33e5SIgor M. Liplianin 0x7c, 0x02, 21209ea33e5SIgor M. Liplianin 0x80, 0xca, 21309ea33e5SIgor M. Liplianin 0x81, 0xeb, 21409ea33e5SIgor M. Liplianin 0x7c, 0x03, 21509ea33e5SIgor M. Liplianin 0x80, 0xba, 21609ea33e5SIgor M. Liplianin 0x81, 0xdb, 21709ea33e5SIgor M. Liplianin 0x85, 0x08, 21809ea33e5SIgor M. Liplianin 0x86, 0x00, 21909ea33e5SIgor M. Liplianin 0x87, 0x02, 22009ea33e5SIgor M. Liplianin 0x89, 0x80, 22109ea33e5SIgor M. Liplianin 0x8b, 0x44, 22209ea33e5SIgor M. Liplianin 0x8c, 0xaa, 22309ea33e5SIgor M. Liplianin 0x8a, 0x10, 22409ea33e5SIgor M. Liplianin 0xba, 0x00, 22509ea33e5SIgor M. Liplianin 0xf5, 0x04, 22609ea33e5SIgor M. Liplianin 0xfe, 0x44, 22709ea33e5SIgor M. Liplianin 0xd2, 0x32, 22809ea33e5SIgor M. Liplianin 0xb8, 0x00, 22909ea33e5SIgor M. Liplianin }; 23009ea33e5SIgor M. Liplianin 23109ea33e5SIgor M. Liplianin struct ds3000_state { 23209ea33e5SIgor M. Liplianin struct i2c_adapter *i2c; 23309ea33e5SIgor M. Liplianin const struct ds3000_config *config; 23409ea33e5SIgor M. Liplianin struct dvb_frontend frontend; 23509ea33e5SIgor M. Liplianin /* previous uncorrected block counter for DVB-S2 */ 23609ea33e5SIgor M. Liplianin u16 prevUCBS2; 23709ea33e5SIgor M. Liplianin }; 23809ea33e5SIgor M. Liplianin 23909ea33e5SIgor M. Liplianin static int ds3000_writereg(struct ds3000_state *state, int reg, int data) 24009ea33e5SIgor M. Liplianin { 24109ea33e5SIgor M. Liplianin u8 buf[] = { reg, data }; 24209ea33e5SIgor M. Liplianin struct i2c_msg msg = { .addr = state->config->demod_address, 24309ea33e5SIgor M. Liplianin .flags = 0, .buf = buf, .len = 2 }; 24409ea33e5SIgor M. Liplianin int err; 24509ea33e5SIgor M. Liplianin 24609ea33e5SIgor M. Liplianin dprintk("%s: write reg 0x%02x, value 0x%02x\n", __func__, reg, data); 24709ea33e5SIgor M. Liplianin 24809ea33e5SIgor M. Liplianin err = i2c_transfer(state->i2c, &msg, 1); 24909ea33e5SIgor M. Liplianin if (err != 1) { 25009ea33e5SIgor M. Liplianin printk(KERN_ERR "%s: writereg error(err == %i, reg == 0x%02x," 25109ea33e5SIgor M. Liplianin " value == 0x%02x)\n", __func__, err, reg, data); 25209ea33e5SIgor M. Liplianin return -EREMOTEIO; 25309ea33e5SIgor M. Liplianin } 25409ea33e5SIgor M. Liplianin 25509ea33e5SIgor M. Liplianin return 0; 25609ea33e5SIgor M. Liplianin } 25709ea33e5SIgor M. Liplianin 258*c1965eaeSKonstantin Dimitrov static int ds3000_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 25909ea33e5SIgor M. Liplianin { 260*c1965eaeSKonstantin Dimitrov struct ds3000_state *state = fe->demodulator_priv; 26109ea33e5SIgor M. Liplianin 262*c1965eaeSKonstantin Dimitrov if (enable) 263*c1965eaeSKonstantin Dimitrov ds3000_writereg(state, 0x03, 0x12); 264*c1965eaeSKonstantin Dimitrov else 265*c1965eaeSKonstantin Dimitrov ds3000_writereg(state, 0x03, 0x02); 26609ea33e5SIgor M. Liplianin 26709ea33e5SIgor M. Liplianin return 0; 26809ea33e5SIgor M. Liplianin } 26909ea33e5SIgor M. Liplianin 27009ea33e5SIgor M. Liplianin /* I2C write for 8k firmware load */ 27109ea33e5SIgor M. Liplianin static int ds3000_writeFW(struct ds3000_state *state, int reg, 27209ea33e5SIgor M. Liplianin const u8 *data, u16 len) 27309ea33e5SIgor M. Liplianin { 27409ea33e5SIgor M. Liplianin int i, ret = -EREMOTEIO; 27509ea33e5SIgor M. Liplianin struct i2c_msg msg; 27609ea33e5SIgor M. Liplianin u8 *buf; 27709ea33e5SIgor M. Liplianin 278caa687c8SIgor M. Liplianin buf = kmalloc(33, GFP_KERNEL); 27909ea33e5SIgor M. Liplianin if (buf == NULL) { 28009ea33e5SIgor M. Liplianin printk(KERN_ERR "Unable to kmalloc\n"); 28109ea33e5SIgor M. Liplianin ret = -ENOMEM; 28209ea33e5SIgor M. Liplianin goto error; 28309ea33e5SIgor M. Liplianin } 28409ea33e5SIgor M. Liplianin 28509ea33e5SIgor M. Liplianin *(buf) = reg; 28609ea33e5SIgor M. Liplianin 28709ea33e5SIgor M. Liplianin msg.addr = state->config->demod_address; 28809ea33e5SIgor M. Liplianin msg.flags = 0; 28909ea33e5SIgor M. Liplianin msg.buf = buf; 290caa687c8SIgor M. Liplianin msg.len = 33; 29109ea33e5SIgor M. Liplianin 292caa687c8SIgor M. Liplianin for (i = 0; i < len; i += 32) { 293caa687c8SIgor M. Liplianin memcpy(buf + 1, data + i, 32); 29409ea33e5SIgor M. Liplianin 29509ea33e5SIgor M. Liplianin dprintk("%s: write reg 0x%02x, len = %d\n", __func__, reg, len); 29609ea33e5SIgor M. Liplianin 29709ea33e5SIgor M. Liplianin ret = i2c_transfer(state->i2c, &msg, 1); 29809ea33e5SIgor M. Liplianin if (ret != 1) { 29909ea33e5SIgor M. Liplianin printk(KERN_ERR "%s: write error(err == %i, " 30009ea33e5SIgor M. Liplianin "reg == 0x%02x\n", __func__, ret, reg); 30109ea33e5SIgor M. Liplianin ret = -EREMOTEIO; 30209ea33e5SIgor M. Liplianin } 30309ea33e5SIgor M. Liplianin } 30409ea33e5SIgor M. Liplianin 30509ea33e5SIgor M. Liplianin error: 30609ea33e5SIgor M. Liplianin kfree(buf); 30709ea33e5SIgor M. Liplianin 30809ea33e5SIgor M. Liplianin return ret; 30909ea33e5SIgor M. Liplianin } 31009ea33e5SIgor M. Liplianin 31109ea33e5SIgor M. Liplianin static int ds3000_readreg(struct ds3000_state *state, u8 reg) 31209ea33e5SIgor M. Liplianin { 31309ea33e5SIgor M. Liplianin int ret; 31409ea33e5SIgor M. Liplianin u8 b0[] = { reg }; 31509ea33e5SIgor M. Liplianin u8 b1[] = { 0 }; 31609ea33e5SIgor M. Liplianin struct i2c_msg msg[] = { 31709ea33e5SIgor M. Liplianin { 31809ea33e5SIgor M. Liplianin .addr = state->config->demod_address, 31909ea33e5SIgor M. Liplianin .flags = 0, 32009ea33e5SIgor M. Liplianin .buf = b0, 32109ea33e5SIgor M. Liplianin .len = 1 32209ea33e5SIgor M. Liplianin }, { 32309ea33e5SIgor M. Liplianin .addr = state->config->demod_address, 32409ea33e5SIgor M. Liplianin .flags = I2C_M_RD, 32509ea33e5SIgor M. Liplianin .buf = b1, 32609ea33e5SIgor M. Liplianin .len = 1 32709ea33e5SIgor M. Liplianin } 32809ea33e5SIgor M. Liplianin }; 32909ea33e5SIgor M. Liplianin 33009ea33e5SIgor M. Liplianin ret = i2c_transfer(state->i2c, msg, 2); 33109ea33e5SIgor M. Liplianin 33209ea33e5SIgor M. Liplianin if (ret != 2) { 33309ea33e5SIgor M. Liplianin printk(KERN_ERR "%s: reg=0x%x(error=%d)\n", __func__, reg, ret); 33409ea33e5SIgor M. Liplianin return ret; 33509ea33e5SIgor M. Liplianin } 33609ea33e5SIgor M. Liplianin 33709ea33e5SIgor M. Liplianin dprintk("%s: read reg 0x%02x, value 0x%02x\n", __func__, reg, b1[0]); 33809ea33e5SIgor M. Liplianin 33909ea33e5SIgor M. Liplianin return b1[0]; 34009ea33e5SIgor M. Liplianin } 34109ea33e5SIgor M. Liplianin 34209ea33e5SIgor M. Liplianin static int ds3000_load_firmware(struct dvb_frontend *fe, 34309ea33e5SIgor M. Liplianin const struct firmware *fw); 34409ea33e5SIgor M. Liplianin 34509ea33e5SIgor M. Liplianin static int ds3000_firmware_ondemand(struct dvb_frontend *fe) 34609ea33e5SIgor M. Liplianin { 34709ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 34809ea33e5SIgor M. Liplianin const struct firmware *fw; 34909ea33e5SIgor M. Liplianin int ret = 0; 35009ea33e5SIgor M. Liplianin 35109ea33e5SIgor M. Liplianin dprintk("%s()\n", __func__); 35209ea33e5SIgor M. Liplianin 353034351ffSRémi Cardona ret = ds3000_readreg(state, 0xb2); 354034351ffSRémi Cardona if (ret < 0) 35509ea33e5SIgor M. Liplianin return ret; 35609ea33e5SIgor M. Liplianin 35709ea33e5SIgor M. Liplianin /* Load firmware */ 35809ea33e5SIgor M. Liplianin /* request the firmware, this will block until someone uploads it */ 35909ea33e5SIgor M. Liplianin printk(KERN_INFO "%s: Waiting for firmware upload (%s)...\n", __func__, 36009ea33e5SIgor M. Liplianin DS3000_DEFAULT_FIRMWARE); 36109ea33e5SIgor M. Liplianin ret = request_firmware(&fw, DS3000_DEFAULT_FIRMWARE, 36209ea33e5SIgor M. Liplianin state->i2c->dev.parent); 36309ea33e5SIgor M. Liplianin printk(KERN_INFO "%s: Waiting for firmware upload(2)...\n", __func__); 36409ea33e5SIgor M. Liplianin if (ret) { 36509ea33e5SIgor M. Liplianin printk(KERN_ERR "%s: No firmware uploaded (timeout or file not " 36609ea33e5SIgor M. Liplianin "found?)\n", __func__); 36709ea33e5SIgor M. Liplianin return ret; 36809ea33e5SIgor M. Liplianin } 36909ea33e5SIgor M. Liplianin 37009ea33e5SIgor M. Liplianin ret = ds3000_load_firmware(fe, fw); 37109ea33e5SIgor M. Liplianin if (ret) 37209ea33e5SIgor M. Liplianin printk("%s: Writing firmware to device failed\n", __func__); 37309ea33e5SIgor M. Liplianin 37409ea33e5SIgor M. Liplianin release_firmware(fw); 37509ea33e5SIgor M. Liplianin 37609ea33e5SIgor M. Liplianin dprintk("%s: Firmware upload %s\n", __func__, 37709ea33e5SIgor M. Liplianin ret == 0 ? "complete" : "failed"); 37809ea33e5SIgor M. Liplianin 37909ea33e5SIgor M. Liplianin return ret; 38009ea33e5SIgor M. Liplianin } 38109ea33e5SIgor M. Liplianin 38209ea33e5SIgor M. Liplianin static int ds3000_load_firmware(struct dvb_frontend *fe, 38309ea33e5SIgor M. Liplianin const struct firmware *fw) 38409ea33e5SIgor M. Liplianin { 38509ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 38609ea33e5SIgor M. Liplianin 38709ea33e5SIgor M. Liplianin dprintk("%s\n", __func__); 38809ea33e5SIgor M. Liplianin dprintk("Firmware is %zu bytes (%02x %02x .. %02x %02x)\n", 38909ea33e5SIgor M. Liplianin fw->size, 39009ea33e5SIgor M. Liplianin fw->data[0], 39109ea33e5SIgor M. Liplianin fw->data[1], 39209ea33e5SIgor M. Liplianin fw->data[fw->size - 2], 39309ea33e5SIgor M. Liplianin fw->data[fw->size - 1]); 39409ea33e5SIgor M. Liplianin 39509ea33e5SIgor M. Liplianin /* Begin the firmware load process */ 39609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xb2, 0x01); 39709ea33e5SIgor M. Liplianin /* write the entire firmware */ 39809ea33e5SIgor M. Liplianin ds3000_writeFW(state, 0xb0, fw->data, fw->size); 39909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xb2, 0x00); 40009ea33e5SIgor M. Liplianin 40109ea33e5SIgor M. Liplianin return 0; 40209ea33e5SIgor M. Liplianin } 40309ea33e5SIgor M. Liplianin 404d2ffc447SIgor M. Liplianin static int ds3000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) 405d2ffc447SIgor M. Liplianin { 406d2ffc447SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 407d2ffc447SIgor M. Liplianin u8 data; 408d2ffc447SIgor M. Liplianin 409d2ffc447SIgor M. Liplianin dprintk("%s(%d)\n", __func__, voltage); 410d2ffc447SIgor M. Liplianin 411d2ffc447SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 412d2ffc447SIgor M. Liplianin data |= 0x03; /* bit0 V/H, bit1 off/on */ 413d2ffc447SIgor M. Liplianin 414d2ffc447SIgor M. Liplianin switch (voltage) { 415d2ffc447SIgor M. Liplianin case SEC_VOLTAGE_18: 416d2ffc447SIgor M. Liplianin data &= ~0x03; 417d2ffc447SIgor M. Liplianin break; 418d2ffc447SIgor M. Liplianin case SEC_VOLTAGE_13: 419d2ffc447SIgor M. Liplianin data &= ~0x03; 420d2ffc447SIgor M. Liplianin data |= 0x01; 421d2ffc447SIgor M. Liplianin break; 422d2ffc447SIgor M. Liplianin case SEC_VOLTAGE_OFF: 423d2ffc447SIgor M. Liplianin break; 424d2ffc447SIgor M. Liplianin } 425d2ffc447SIgor M. Liplianin 426d2ffc447SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 427d2ffc447SIgor M. Liplianin 428d2ffc447SIgor M. Liplianin return 0; 429d2ffc447SIgor M. Liplianin } 430d2ffc447SIgor M. Liplianin 43109ea33e5SIgor M. Liplianin static int ds3000_read_status(struct dvb_frontend *fe, fe_status_t* status) 43209ea33e5SIgor M. Liplianin { 43309ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 43409ea33e5SIgor M. Liplianin struct dtv_frontend_properties *c = &fe->dtv_property_cache; 43509ea33e5SIgor M. Liplianin int lock; 43609ea33e5SIgor M. Liplianin 43709ea33e5SIgor M. Liplianin *status = 0; 43809ea33e5SIgor M. Liplianin 43909ea33e5SIgor M. Liplianin switch (c->delivery_system) { 44009ea33e5SIgor M. Liplianin case SYS_DVBS: 44109ea33e5SIgor M. Liplianin lock = ds3000_readreg(state, 0xd1); 44209ea33e5SIgor M. Liplianin if ((lock & 0x07) == 0x07) 44309ea33e5SIgor M. Liplianin *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | 44409ea33e5SIgor M. Liplianin FE_HAS_VITERBI | FE_HAS_SYNC | 44509ea33e5SIgor M. Liplianin FE_HAS_LOCK; 44609ea33e5SIgor M. Liplianin 44709ea33e5SIgor M. Liplianin break; 44809ea33e5SIgor M. Liplianin case SYS_DVBS2: 44909ea33e5SIgor M. Liplianin lock = ds3000_readreg(state, 0x0d); 45009ea33e5SIgor M. Liplianin if ((lock & 0x8f) == 0x8f) 45109ea33e5SIgor M. Liplianin *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | 45209ea33e5SIgor M. Liplianin FE_HAS_VITERBI | FE_HAS_SYNC | 45309ea33e5SIgor M. Liplianin FE_HAS_LOCK; 45409ea33e5SIgor M. Liplianin 45509ea33e5SIgor M. Liplianin break; 45609ea33e5SIgor M. Liplianin default: 45709ea33e5SIgor M. Liplianin return 1; 45809ea33e5SIgor M. Liplianin } 45909ea33e5SIgor M. Liplianin 46009ea33e5SIgor M. Liplianin dprintk("%s: status = 0x%02x\n", __func__, lock); 46109ea33e5SIgor M. Liplianin 46209ea33e5SIgor M. Liplianin return 0; 46309ea33e5SIgor M. Liplianin } 46409ea33e5SIgor M. Liplianin 46509ea33e5SIgor M. Liplianin /* read DS3000 BER value */ 46609ea33e5SIgor M. Liplianin static int ds3000_read_ber(struct dvb_frontend *fe, u32* ber) 46709ea33e5SIgor M. Liplianin { 46809ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 46909ea33e5SIgor M. Liplianin struct dtv_frontend_properties *c = &fe->dtv_property_cache; 47009ea33e5SIgor M. Liplianin u8 data; 47109ea33e5SIgor M. Liplianin u32 ber_reading, lpdc_frames; 47209ea33e5SIgor M. Liplianin 47309ea33e5SIgor M. Liplianin dprintk("%s()\n", __func__); 47409ea33e5SIgor M. Liplianin 47509ea33e5SIgor M. Liplianin switch (c->delivery_system) { 47609ea33e5SIgor M. Liplianin case SYS_DVBS: 47709ea33e5SIgor M. Liplianin /* set the number of bytes checked during 47809ea33e5SIgor M. Liplianin BER estimation */ 47909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xf9, 0x04); 48009ea33e5SIgor M. Liplianin /* read BER estimation status */ 48109ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xf8); 48209ea33e5SIgor M. Liplianin /* check if BER estimation is ready */ 48309ea33e5SIgor M. Liplianin if ((data & 0x10) == 0) { 48409ea33e5SIgor M. Liplianin /* this is the number of error bits, 48509ea33e5SIgor M. Liplianin to calculate the bit error rate 48609ea33e5SIgor M. Liplianin divide to 8388608 */ 48709ea33e5SIgor M. Liplianin *ber = (ds3000_readreg(state, 0xf7) << 8) | 48809ea33e5SIgor M. Liplianin ds3000_readreg(state, 0xf6); 48909ea33e5SIgor M. Liplianin /* start counting error bits */ 49009ea33e5SIgor M. Liplianin /* need to be set twice 49109ea33e5SIgor M. Liplianin otherwise it fails sometimes */ 49209ea33e5SIgor M. Liplianin data |= 0x10; 49309ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xf8, data); 49409ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xf8, data); 49509ea33e5SIgor M. Liplianin } else 49609ea33e5SIgor M. Liplianin /* used to indicate that BER estimation 49709ea33e5SIgor M. Liplianin is not ready, i.e. BER is unknown */ 49809ea33e5SIgor M. Liplianin *ber = 0xffffffff; 49909ea33e5SIgor M. Liplianin break; 50009ea33e5SIgor M. Liplianin case SYS_DVBS2: 50109ea33e5SIgor M. Liplianin /* read the number of LPDC decoded frames */ 50209ea33e5SIgor M. Liplianin lpdc_frames = (ds3000_readreg(state, 0xd7) << 16) | 50309ea33e5SIgor M. Liplianin (ds3000_readreg(state, 0xd6) << 8) | 50409ea33e5SIgor M. Liplianin ds3000_readreg(state, 0xd5); 50509ea33e5SIgor M. Liplianin /* read the number of packets with bad CRC */ 50609ea33e5SIgor M. Liplianin ber_reading = (ds3000_readreg(state, 0xf8) << 8) | 50709ea33e5SIgor M. Liplianin ds3000_readreg(state, 0xf7); 50809ea33e5SIgor M. Liplianin if (lpdc_frames > 750) { 50909ea33e5SIgor M. Liplianin /* clear LPDC frame counters */ 51009ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xd1, 0x01); 51109ea33e5SIgor M. Liplianin /* clear bad packets counter */ 51209ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xf9, 0x01); 51309ea33e5SIgor M. Liplianin /* enable bad packets counter */ 51409ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xf9, 0x00); 51509ea33e5SIgor M. Liplianin /* enable LPDC frame counters */ 51609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xd1, 0x00); 51709ea33e5SIgor M. Liplianin *ber = ber_reading; 51809ea33e5SIgor M. Liplianin } else 51909ea33e5SIgor M. Liplianin /* used to indicate that BER estimation is not ready, 52009ea33e5SIgor M. Liplianin i.e. BER is unknown */ 52109ea33e5SIgor M. Liplianin *ber = 0xffffffff; 52209ea33e5SIgor M. Liplianin break; 52309ea33e5SIgor M. Liplianin default: 52409ea33e5SIgor M. Liplianin return 1; 52509ea33e5SIgor M. Liplianin } 52609ea33e5SIgor M. Liplianin 52709ea33e5SIgor M. Liplianin return 0; 52809ea33e5SIgor M. Liplianin } 52909ea33e5SIgor M. Liplianin 53009ea33e5SIgor M. Liplianin /* calculate DS3000 snr value in dB */ 53109ea33e5SIgor M. Liplianin static int ds3000_read_snr(struct dvb_frontend *fe, u16 *snr) 53209ea33e5SIgor M. Liplianin { 53309ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 53409ea33e5SIgor M. Liplianin struct dtv_frontend_properties *c = &fe->dtv_property_cache; 53509ea33e5SIgor M. Liplianin u8 snr_reading, snr_value; 53609ea33e5SIgor M. Liplianin u32 dvbs2_signal_reading, dvbs2_noise_reading, tmp; 53709ea33e5SIgor M. Liplianin static const u16 dvbs_snr_tab[] = { /* 20 x Table (rounded up) */ 53809ea33e5SIgor M. Liplianin 0x0000, 0x1b13, 0x2aea, 0x3627, 0x3ede, 0x45fe, 0x4c03, 53909ea33e5SIgor M. Liplianin 0x513a, 0x55d4, 0x59f2, 0x5dab, 0x6111, 0x6431, 0x6717, 54009ea33e5SIgor M. Liplianin 0x69c9, 0x6c4e, 0x6eac, 0x70e8, 0x7304, 0x7505 54109ea33e5SIgor M. Liplianin }; 54209ea33e5SIgor M. Liplianin static const u16 dvbs2_snr_tab[] = { /* 80 x Table (rounded up) */ 54309ea33e5SIgor M. Liplianin 0x0000, 0x0bc2, 0x12a3, 0x1785, 0x1b4e, 0x1e65, 0x2103, 54409ea33e5SIgor M. Liplianin 0x2347, 0x2546, 0x2710, 0x28ae, 0x2a28, 0x2b83, 0x2cc5, 54509ea33e5SIgor M. Liplianin 0x2df1, 0x2f09, 0x3010, 0x3109, 0x31f4, 0x32d2, 0x33a6, 54609ea33e5SIgor M. Liplianin 0x3470, 0x3531, 0x35ea, 0x369b, 0x3746, 0x37ea, 0x3888, 54709ea33e5SIgor M. Liplianin 0x3920, 0x39b3, 0x3a42, 0x3acc, 0x3b51, 0x3bd3, 0x3c51, 54809ea33e5SIgor M. Liplianin 0x3ccb, 0x3d42, 0x3db6, 0x3e27, 0x3e95, 0x3f00, 0x3f68, 54909ea33e5SIgor M. Liplianin 0x3fcf, 0x4033, 0x4094, 0x40f4, 0x4151, 0x41ac, 0x4206, 55009ea33e5SIgor M. Liplianin 0x425e, 0x42b4, 0x4308, 0x435b, 0x43ac, 0x43fc, 0x444a, 55109ea33e5SIgor M. Liplianin 0x4497, 0x44e2, 0x452d, 0x4576, 0x45bd, 0x4604, 0x4649, 55209ea33e5SIgor M. Liplianin 0x468e, 0x46d1, 0x4713, 0x4755, 0x4795, 0x47d4, 0x4813, 55309ea33e5SIgor M. Liplianin 0x4851, 0x488d, 0x48c9, 0x4904, 0x493f, 0x4978, 0x49b1, 55409ea33e5SIgor M. Liplianin 0x49e9, 0x4a20, 0x4a57 55509ea33e5SIgor M. Liplianin }; 55609ea33e5SIgor M. Liplianin 55709ea33e5SIgor M. Liplianin dprintk("%s()\n", __func__); 55809ea33e5SIgor M. Liplianin 55909ea33e5SIgor M. Liplianin switch (c->delivery_system) { 56009ea33e5SIgor M. Liplianin case SYS_DVBS: 56109ea33e5SIgor M. Liplianin snr_reading = ds3000_readreg(state, 0xff); 56209ea33e5SIgor M. Liplianin snr_reading /= 8; 56309ea33e5SIgor M. Liplianin if (snr_reading == 0) 56409ea33e5SIgor M. Liplianin *snr = 0x0000; 56509ea33e5SIgor M. Liplianin else { 56609ea33e5SIgor M. Liplianin if (snr_reading > 20) 56709ea33e5SIgor M. Liplianin snr_reading = 20; 56809ea33e5SIgor M. Liplianin snr_value = dvbs_snr_tab[snr_reading - 1] * 10 / 23026; 56909ea33e5SIgor M. Liplianin /* cook the value to be suitable for szap-s2 57009ea33e5SIgor M. Liplianin human readable output */ 57109ea33e5SIgor M. Liplianin *snr = snr_value * 8 * 655; 57209ea33e5SIgor M. Liplianin } 57309ea33e5SIgor M. Liplianin dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__, 57409ea33e5SIgor M. Liplianin snr_reading, *snr); 57509ea33e5SIgor M. Liplianin break; 57609ea33e5SIgor M. Liplianin case SYS_DVBS2: 57709ea33e5SIgor M. Liplianin dvbs2_noise_reading = (ds3000_readreg(state, 0x8c) & 0x3f) + 57809ea33e5SIgor M. Liplianin (ds3000_readreg(state, 0x8d) << 4); 57909ea33e5SIgor M. Liplianin dvbs2_signal_reading = ds3000_readreg(state, 0x8e); 58009ea33e5SIgor M. Liplianin tmp = dvbs2_signal_reading * dvbs2_signal_reading >> 1; 581450df222SNicolas Noirbent if (tmp == 0) { 58209ea33e5SIgor M. Liplianin *snr = 0x0000; 58309ea33e5SIgor M. Liplianin return 0; 58409ea33e5SIgor M. Liplianin } 58509ea33e5SIgor M. Liplianin if (dvbs2_noise_reading == 0) { 58609ea33e5SIgor M. Liplianin snr_value = 0x0013; 58709ea33e5SIgor M. Liplianin /* cook the value to be suitable for szap-s2 58809ea33e5SIgor M. Liplianin human readable output */ 58909ea33e5SIgor M. Liplianin *snr = 0xffff; 59009ea33e5SIgor M. Liplianin return 0; 59109ea33e5SIgor M. Liplianin } 59209ea33e5SIgor M. Liplianin if (tmp > dvbs2_noise_reading) { 59309ea33e5SIgor M. Liplianin snr_reading = tmp / dvbs2_noise_reading; 59409ea33e5SIgor M. Liplianin if (snr_reading > 80) 59509ea33e5SIgor M. Liplianin snr_reading = 80; 59609ea33e5SIgor M. Liplianin snr_value = dvbs2_snr_tab[snr_reading - 1] / 1000; 59709ea33e5SIgor M. Liplianin /* cook the value to be suitable for szap-s2 59809ea33e5SIgor M. Liplianin human readable output */ 59909ea33e5SIgor M. Liplianin *snr = snr_value * 5 * 655; 60009ea33e5SIgor M. Liplianin } else { 60109ea33e5SIgor M. Liplianin snr_reading = dvbs2_noise_reading / tmp; 60209ea33e5SIgor M. Liplianin if (snr_reading > 80) 60309ea33e5SIgor M. Liplianin snr_reading = 80; 60409ea33e5SIgor M. Liplianin *snr = -(dvbs2_snr_tab[snr_reading] / 1000); 60509ea33e5SIgor M. Liplianin } 60609ea33e5SIgor M. Liplianin dprintk("%s: raw / cooked = 0x%02x / 0x%04x\n", __func__, 60709ea33e5SIgor M. Liplianin snr_reading, *snr); 60809ea33e5SIgor M. Liplianin break; 60909ea33e5SIgor M. Liplianin default: 61009ea33e5SIgor M. Liplianin return 1; 61109ea33e5SIgor M. Liplianin } 61209ea33e5SIgor M. Liplianin 61309ea33e5SIgor M. Liplianin return 0; 61409ea33e5SIgor M. Liplianin } 61509ea33e5SIgor M. Liplianin 61609ea33e5SIgor M. Liplianin /* read DS3000 uncorrected blocks */ 61709ea33e5SIgor M. Liplianin static int ds3000_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 61809ea33e5SIgor M. Liplianin { 61909ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 62009ea33e5SIgor M. Liplianin struct dtv_frontend_properties *c = &fe->dtv_property_cache; 62109ea33e5SIgor M. Liplianin u8 data; 62209ea33e5SIgor M. Liplianin u16 _ucblocks; 62309ea33e5SIgor M. Liplianin 62409ea33e5SIgor M. Liplianin dprintk("%s()\n", __func__); 62509ea33e5SIgor M. Liplianin 62609ea33e5SIgor M. Liplianin switch (c->delivery_system) { 62709ea33e5SIgor M. Liplianin case SYS_DVBS: 62809ea33e5SIgor M. Liplianin *ucblocks = (ds3000_readreg(state, 0xf5) << 8) | 62909ea33e5SIgor M. Liplianin ds3000_readreg(state, 0xf4); 63009ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xf8); 63109ea33e5SIgor M. Liplianin /* clear packet counters */ 63209ea33e5SIgor M. Liplianin data &= ~0x20; 63309ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xf8, data); 63409ea33e5SIgor M. Liplianin /* enable packet counters */ 63509ea33e5SIgor M. Liplianin data |= 0x20; 63609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xf8, data); 63709ea33e5SIgor M. Liplianin break; 63809ea33e5SIgor M. Liplianin case SYS_DVBS2: 63909ea33e5SIgor M. Liplianin _ucblocks = (ds3000_readreg(state, 0xe2) << 8) | 64009ea33e5SIgor M. Liplianin ds3000_readreg(state, 0xe1); 64109ea33e5SIgor M. Liplianin if (_ucblocks > state->prevUCBS2) 64209ea33e5SIgor M. Liplianin *ucblocks = _ucblocks - state->prevUCBS2; 64309ea33e5SIgor M. Liplianin else 64409ea33e5SIgor M. Liplianin *ucblocks = state->prevUCBS2 - _ucblocks; 64509ea33e5SIgor M. Liplianin state->prevUCBS2 = _ucblocks; 64609ea33e5SIgor M. Liplianin break; 64709ea33e5SIgor M. Liplianin default: 64809ea33e5SIgor M. Liplianin return 1; 64909ea33e5SIgor M. Liplianin } 65009ea33e5SIgor M. Liplianin 65109ea33e5SIgor M. Liplianin return 0; 65209ea33e5SIgor M. Liplianin } 65309ea33e5SIgor M. Liplianin 65409ea33e5SIgor M. Liplianin static int ds3000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone) 65509ea33e5SIgor M. Liplianin { 65609ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 65709ea33e5SIgor M. Liplianin u8 data; 65809ea33e5SIgor M. Liplianin 65909ea33e5SIgor M. Liplianin dprintk("%s(%d)\n", __func__, tone); 66009ea33e5SIgor M. Liplianin if ((tone != SEC_TONE_ON) && (tone != SEC_TONE_OFF)) { 66109ea33e5SIgor M. Liplianin printk(KERN_ERR "%s: Invalid, tone=%d\n", __func__, tone); 66209ea33e5SIgor M. Liplianin return -EINVAL; 66309ea33e5SIgor M. Liplianin } 66409ea33e5SIgor M. Liplianin 66509ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 66609ea33e5SIgor M. Liplianin data &= ~0xc0; 66709ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 66809ea33e5SIgor M. Liplianin 66909ea33e5SIgor M. Liplianin switch (tone) { 67009ea33e5SIgor M. Liplianin case SEC_TONE_ON: 67109ea33e5SIgor M. Liplianin dprintk("%s: setting tone on\n", __func__); 67209ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa1); 67309ea33e5SIgor M. Liplianin data &= ~0x43; 67409ea33e5SIgor M. Liplianin data |= 0x04; 67509ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa1, data); 67609ea33e5SIgor M. Liplianin break; 67709ea33e5SIgor M. Liplianin case SEC_TONE_OFF: 67809ea33e5SIgor M. Liplianin dprintk("%s: setting tone off\n", __func__); 67909ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 68009ea33e5SIgor M. Liplianin data |= 0x80; 68109ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 68209ea33e5SIgor M. Liplianin break; 68309ea33e5SIgor M. Liplianin } 68409ea33e5SIgor M. Liplianin 68509ea33e5SIgor M. Liplianin return 0; 68609ea33e5SIgor M. Liplianin } 68709ea33e5SIgor M. Liplianin 68809ea33e5SIgor M. Liplianin static int ds3000_send_diseqc_msg(struct dvb_frontend *fe, 68909ea33e5SIgor M. Liplianin struct dvb_diseqc_master_cmd *d) 69009ea33e5SIgor M. Liplianin { 69109ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 69209ea33e5SIgor M. Liplianin int i; 69309ea33e5SIgor M. Liplianin u8 data; 69409ea33e5SIgor M. Liplianin 69509ea33e5SIgor M. Liplianin /* Dump DiSEqC message */ 69609ea33e5SIgor M. Liplianin dprintk("%s(", __func__); 69709ea33e5SIgor M. Liplianin for (i = 0 ; i < d->msg_len;) { 69809ea33e5SIgor M. Liplianin dprintk("0x%02x", d->msg[i]); 69909ea33e5SIgor M. Liplianin if (++i < d->msg_len) 70009ea33e5SIgor M. Liplianin dprintk(", "); 70109ea33e5SIgor M. Liplianin } 70209ea33e5SIgor M. Liplianin 70309ea33e5SIgor M. Liplianin /* enable DiSEqC message send pin */ 70409ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 70509ea33e5SIgor M. Liplianin data &= ~0xc0; 70609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 70709ea33e5SIgor M. Liplianin 70809ea33e5SIgor M. Liplianin /* DiSEqC message */ 70909ea33e5SIgor M. Liplianin for (i = 0; i < d->msg_len; i++) 71009ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa3 + i, d->msg[i]); 71109ea33e5SIgor M. Liplianin 71209ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa1); 71309ea33e5SIgor M. Liplianin /* clear DiSEqC message length and status, 71409ea33e5SIgor M. Liplianin enable DiSEqC message send */ 71509ea33e5SIgor M. Liplianin data &= ~0xf8; 71609ea33e5SIgor M. Liplianin /* set DiSEqC mode, modulation active during 33 pulses, 71709ea33e5SIgor M. Liplianin set DiSEqC message length */ 71809ea33e5SIgor M. Liplianin data |= ((d->msg_len - 1) << 3) | 0x07; 71909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa1, data); 72009ea33e5SIgor M. Liplianin 72109ea33e5SIgor M. Liplianin /* wait up to 150ms for DiSEqC transmission to complete */ 72209ea33e5SIgor M. Liplianin for (i = 0; i < 15; i++) { 72309ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa1); 72409ea33e5SIgor M. Liplianin if ((data & 0x40) == 0) 72509ea33e5SIgor M. Liplianin break; 72609ea33e5SIgor M. Liplianin msleep(10); 72709ea33e5SIgor M. Liplianin } 72809ea33e5SIgor M. Liplianin 72909ea33e5SIgor M. Liplianin /* DiSEqC timeout after 150ms */ 73009ea33e5SIgor M. Liplianin if (i == 15) { 73109ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa1); 73209ea33e5SIgor M. Liplianin data &= ~0x80; 73309ea33e5SIgor M. Liplianin data |= 0x40; 73409ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa1, data); 73509ea33e5SIgor M. Liplianin 73609ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 73709ea33e5SIgor M. Liplianin data &= ~0xc0; 73809ea33e5SIgor M. Liplianin data |= 0x80; 73909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 74009ea33e5SIgor M. Liplianin 74109ea33e5SIgor M. Liplianin return 1; 74209ea33e5SIgor M. Liplianin } 74309ea33e5SIgor M. Liplianin 74409ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 74509ea33e5SIgor M. Liplianin data &= ~0xc0; 74609ea33e5SIgor M. Liplianin data |= 0x80; 74709ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 74809ea33e5SIgor M. Liplianin 74909ea33e5SIgor M. Liplianin return 0; 75009ea33e5SIgor M. Liplianin } 75109ea33e5SIgor M. Liplianin 75209ea33e5SIgor M. Liplianin /* Send DiSEqC burst */ 75309ea33e5SIgor M. Liplianin static int ds3000_diseqc_send_burst(struct dvb_frontend *fe, 75409ea33e5SIgor M. Liplianin fe_sec_mini_cmd_t burst) 75509ea33e5SIgor M. Liplianin { 75609ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 75709ea33e5SIgor M. Liplianin int i; 75809ea33e5SIgor M. Liplianin u8 data; 75909ea33e5SIgor M. Liplianin 76009ea33e5SIgor M. Liplianin dprintk("%s()\n", __func__); 76109ea33e5SIgor M. Liplianin 76209ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 76309ea33e5SIgor M. Liplianin data &= ~0xc0; 76409ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 76509ea33e5SIgor M. Liplianin 76609ea33e5SIgor M. Liplianin /* DiSEqC burst */ 76709ea33e5SIgor M. Liplianin if (burst == SEC_MINI_A) 76809ea33e5SIgor M. Liplianin /* Unmodulated tone burst */ 76909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa1, 0x02); 77009ea33e5SIgor M. Liplianin else if (burst == SEC_MINI_B) 77109ea33e5SIgor M. Liplianin /* Modulated tone burst */ 77209ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa1, 0x01); 77309ea33e5SIgor M. Liplianin else 77409ea33e5SIgor M. Liplianin return -EINVAL; 77509ea33e5SIgor M. Liplianin 77609ea33e5SIgor M. Liplianin msleep(13); 77709ea33e5SIgor M. Liplianin for (i = 0; i < 5; i++) { 77809ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa1); 77909ea33e5SIgor M. Liplianin if ((data & 0x40) == 0) 78009ea33e5SIgor M. Liplianin break; 78109ea33e5SIgor M. Liplianin msleep(1); 78209ea33e5SIgor M. Liplianin } 78309ea33e5SIgor M. Liplianin 78409ea33e5SIgor M. Liplianin if (i == 5) { 78509ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa1); 78609ea33e5SIgor M. Liplianin data &= ~0x80; 78709ea33e5SIgor M. Liplianin data |= 0x40; 78809ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa1, data); 78909ea33e5SIgor M. Liplianin 79009ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 79109ea33e5SIgor M. Liplianin data &= ~0xc0; 79209ea33e5SIgor M. Liplianin data |= 0x80; 79309ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 79409ea33e5SIgor M. Liplianin 79509ea33e5SIgor M. Liplianin return 1; 79609ea33e5SIgor M. Liplianin } 79709ea33e5SIgor M. Liplianin 79809ea33e5SIgor M. Liplianin data = ds3000_readreg(state, 0xa2); 79909ea33e5SIgor M. Liplianin data &= ~0xc0; 80009ea33e5SIgor M. Liplianin data |= 0x80; 80109ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xa2, data); 80209ea33e5SIgor M. Liplianin 80309ea33e5SIgor M. Liplianin return 0; 80409ea33e5SIgor M. Liplianin } 80509ea33e5SIgor M. Liplianin 80609ea33e5SIgor M. Liplianin static void ds3000_release(struct dvb_frontend *fe) 80709ea33e5SIgor M. Liplianin { 80809ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 80909ea33e5SIgor M. Liplianin dprintk("%s\n", __func__); 81009ea33e5SIgor M. Liplianin kfree(state); 81109ea33e5SIgor M. Liplianin } 81209ea33e5SIgor M. Liplianin 81309ea33e5SIgor M. Liplianin static struct dvb_frontend_ops ds3000_ops; 81409ea33e5SIgor M. Liplianin 81509ea33e5SIgor M. Liplianin struct dvb_frontend *ds3000_attach(const struct ds3000_config *config, 81609ea33e5SIgor M. Liplianin struct i2c_adapter *i2c) 81709ea33e5SIgor M. Liplianin { 81809ea33e5SIgor M. Liplianin struct ds3000_state *state = NULL; 81909ea33e5SIgor M. Liplianin int ret; 82009ea33e5SIgor M. Liplianin 82109ea33e5SIgor M. Liplianin dprintk("%s\n", __func__); 82209ea33e5SIgor M. Liplianin 82309ea33e5SIgor M. Liplianin /* allocate memory for the internal state */ 8242ef17c9fSJulia Lawall state = kzalloc(sizeof(struct ds3000_state), GFP_KERNEL); 82509ea33e5SIgor M. Liplianin if (state == NULL) { 82609ea33e5SIgor M. Liplianin printk(KERN_ERR "Unable to kmalloc\n"); 82709ea33e5SIgor M. Liplianin goto error2; 82809ea33e5SIgor M. Liplianin } 82909ea33e5SIgor M. Liplianin 83009ea33e5SIgor M. Liplianin state->config = config; 83109ea33e5SIgor M. Liplianin state->i2c = i2c; 83209ea33e5SIgor M. Liplianin state->prevUCBS2 = 0; 83309ea33e5SIgor M. Liplianin 83409ea33e5SIgor M. Liplianin /* check if the demod is present */ 83509ea33e5SIgor M. Liplianin ret = ds3000_readreg(state, 0x00) & 0xfe; 83609ea33e5SIgor M. Liplianin if (ret != 0xe0) { 83709ea33e5SIgor M. Liplianin printk(KERN_ERR "Invalid probe, probably not a DS3000\n"); 83809ea33e5SIgor M. Liplianin goto error3; 83909ea33e5SIgor M. Liplianin } 84009ea33e5SIgor M. Liplianin 84109ea33e5SIgor M. Liplianin printk(KERN_INFO "DS3000 chip version: %d.%d attached.\n", 84209ea33e5SIgor M. Liplianin ds3000_readreg(state, 0x02), 84309ea33e5SIgor M. Liplianin ds3000_readreg(state, 0x01)); 84409ea33e5SIgor M. Liplianin 84509ea33e5SIgor M. Liplianin memcpy(&state->frontend.ops, &ds3000_ops, 84609ea33e5SIgor M. Liplianin sizeof(struct dvb_frontend_ops)); 84709ea33e5SIgor M. Liplianin state->frontend.demodulator_priv = state; 84809ea33e5SIgor M. Liplianin return &state->frontend; 84909ea33e5SIgor M. Liplianin 85009ea33e5SIgor M. Liplianin error3: 85109ea33e5SIgor M. Liplianin kfree(state); 85209ea33e5SIgor M. Liplianin error2: 85309ea33e5SIgor M. Liplianin return NULL; 85409ea33e5SIgor M. Liplianin } 85509ea33e5SIgor M. Liplianin EXPORT_SYMBOL(ds3000_attach); 85609ea33e5SIgor M. Liplianin 857a5bf834bSIgor M. Liplianin static int ds3000_set_carrier_offset(struct dvb_frontend *fe, 858a5bf834bSIgor M. Liplianin s32 carrier_offset_khz) 859a5bf834bSIgor M. Liplianin { 860a5bf834bSIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 861a5bf834bSIgor M. Liplianin s32 tmp; 862a5bf834bSIgor M. Liplianin 863a5bf834bSIgor M. Liplianin tmp = carrier_offset_khz; 864a5bf834bSIgor M. Liplianin tmp *= 65536; 865a5bf834bSIgor M. Liplianin tmp = (2 * tmp + DS3000_SAMPLE_RATE) / (2 * DS3000_SAMPLE_RATE); 866a5bf834bSIgor M. Liplianin 867a5bf834bSIgor M. Liplianin if (tmp < 0) 868a5bf834bSIgor M. Liplianin tmp += 65536; 869a5bf834bSIgor M. Liplianin 870a5bf834bSIgor M. Liplianin ds3000_writereg(state, 0x5f, tmp >> 8); 871a5bf834bSIgor M. Liplianin ds3000_writereg(state, 0x5e, tmp & 0xff); 872a5bf834bSIgor M. Liplianin 873a5bf834bSIgor M. Liplianin return 0; 874a5bf834bSIgor M. Liplianin } 875a5bf834bSIgor M. Liplianin 8769fe33018SMauro Carvalho Chehab static int ds3000_set_frontend(struct dvb_frontend *fe) 87709ea33e5SIgor M. Liplianin { 87809ea33e5SIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 87909ea33e5SIgor M. Liplianin struct dtv_frontend_properties *c = &fe->dtv_property_cache; 88009ea33e5SIgor M. Liplianin 88118a73f36SIgor M. Liplianin int i; 882dcc8a122SIgor M. Liplianin fe_status_t status; 883a5bf834bSIgor M. Liplianin s32 offset_khz; 884*c1965eaeSKonstantin Dimitrov u32 frequency; 885*c1965eaeSKonstantin Dimitrov u16 value; 88609ea33e5SIgor M. Liplianin 88709ea33e5SIgor M. Liplianin dprintk("%s() ", __func__); 88809ea33e5SIgor M. Liplianin 8890cb73639SIgor M. Liplianin if (state->config->set_ts_params) 8900cb73639SIgor M. Liplianin state->config->set_ts_params(fe, 0); 89109ea33e5SIgor M. Liplianin /* Tune */ 892*c1965eaeSKonstantin Dimitrov if (fe->ops.tuner_ops.set_params) 893*c1965eaeSKonstantin Dimitrov fe->ops.tuner_ops.set_params(fe); 894a5bf834bSIgor M. Liplianin 89509ea33e5SIgor M. Liplianin /* ds3000 global reset */ 89609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x07, 0x80); 89709ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x07, 0x00); 89809ea33e5SIgor M. Liplianin /* ds3000 build-in uC reset */ 89909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xb2, 0x01); 90009ea33e5SIgor M. Liplianin /* ds3000 software reset */ 90109ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x00, 0x01); 90209ea33e5SIgor M. Liplianin 90309ea33e5SIgor M. Liplianin switch (c->delivery_system) { 90409ea33e5SIgor M. Liplianin case SYS_DVBS: 90509ea33e5SIgor M. Liplianin /* initialise the demod in DVB-S mode */ 90609ea33e5SIgor M. Liplianin for (i = 0; i < sizeof(ds3000_dvbs_init_tab); i += 2) 90709ea33e5SIgor M. Liplianin ds3000_writereg(state, 90809ea33e5SIgor M. Liplianin ds3000_dvbs_init_tab[i], 90909ea33e5SIgor M. Liplianin ds3000_dvbs_init_tab[i + 1]); 91009ea33e5SIgor M. Liplianin value = ds3000_readreg(state, 0xfe); 91109ea33e5SIgor M. Liplianin value &= 0xc0; 91209ea33e5SIgor M. Liplianin value |= 0x1b; 91309ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xfe, value); 91409ea33e5SIgor M. Liplianin break; 91509ea33e5SIgor M. Liplianin case SYS_DVBS2: 91609ea33e5SIgor M. Liplianin /* initialise the demod in DVB-S2 mode */ 91709ea33e5SIgor M. Liplianin for (i = 0; i < sizeof(ds3000_dvbs2_init_tab); i += 2) 91809ea33e5SIgor M. Liplianin ds3000_writereg(state, 91909ea33e5SIgor M. Liplianin ds3000_dvbs2_init_tab[i], 92009ea33e5SIgor M. Liplianin ds3000_dvbs2_init_tab[i + 1]); 9217b134e85SIgor M. Liplianin if (c->symbol_rate >= 30000000) 9227b134e85SIgor M. Liplianin ds3000_writereg(state, 0xfe, 0x54); 9237b134e85SIgor M. Liplianin else 9242a66bf37SIgor M. Liplianin ds3000_writereg(state, 0xfe, 0x98); 92509ea33e5SIgor M. Liplianin break; 92609ea33e5SIgor M. Liplianin default: 92709ea33e5SIgor M. Liplianin return 1; 92809ea33e5SIgor M. Liplianin } 92909ea33e5SIgor M. Liplianin 93009ea33e5SIgor M. Liplianin /* enable 27MHz clock output */ 93109ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x29, 0x80); 93209ea33e5SIgor M. Liplianin /* enable ac coupling */ 93309ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x25, 0x8a); 93409ea33e5SIgor M. Liplianin 93509ea33e5SIgor M. Liplianin /* enhance symbol rate performance */ 936cb8f74daSIgor M. Liplianin if ((c->symbol_rate / 1000) <= 5000) { 937cb8f74daSIgor M. Liplianin value = 29777 / (c->symbol_rate / 1000) + 1; 93809ea33e5SIgor M. Liplianin if (value % 2 != 0) 93909ea33e5SIgor M. Liplianin value++; 94009ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc3, 0x0d); 94109ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc8, value); 94209ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc4, 0x10); 94309ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc7, 0x0e); 944cb8f74daSIgor M. Liplianin } else if ((c->symbol_rate / 1000) <= 10000) { 945cb8f74daSIgor M. Liplianin value = 92166 / (c->symbol_rate / 1000) + 1; 94609ea33e5SIgor M. Liplianin if (value % 2 != 0) 94709ea33e5SIgor M. Liplianin value++; 94809ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc3, 0x07); 94909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc8, value); 95009ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc4, 0x09); 95109ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc7, 0x12); 952cb8f74daSIgor M. Liplianin } else if ((c->symbol_rate / 1000) <= 20000) { 953cb8f74daSIgor M. Liplianin value = 64516 / (c->symbol_rate / 1000) + 1; 95409ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc3, value); 95509ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc8, 0x0e); 95609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc4, 0x07); 95709ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc7, 0x18); 95809ea33e5SIgor M. Liplianin } else { 959cb8f74daSIgor M. Liplianin value = 129032 / (c->symbol_rate / 1000) + 1; 96009ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc3, value); 96109ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc8, 0x0a); 96209ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc4, 0x05); 96309ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xc7, 0x24); 96409ea33e5SIgor M. Liplianin } 96509ea33e5SIgor M. Liplianin 96609ea33e5SIgor M. Liplianin /* normalized symbol rate rounded to the closest integer */ 967cb8f74daSIgor M. Liplianin value = (((c->symbol_rate / 1000) << 16) + 96809ea33e5SIgor M. Liplianin (DS3000_SAMPLE_RATE / 2)) / DS3000_SAMPLE_RATE; 96909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x61, value & 0x00ff); 97009ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x62, (value & 0xff00) >> 8); 97109ea33e5SIgor M. Liplianin 97209ea33e5SIgor M. Liplianin /* co-channel interference cancellation disabled */ 97309ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x56, 0x00); 97409ea33e5SIgor M. Liplianin 97509ea33e5SIgor M. Liplianin /* equalizer disabled */ 97609ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x76, 0x00); 97709ea33e5SIgor M. Liplianin 97809ea33e5SIgor M. Liplianin /*ds3000_writereg(state, 0x08, 0x03); 97909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xfd, 0x22); 98009ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x08, 0x07); 98109ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xfd, 0x42); 98209ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x08, 0x07);*/ 98309ea33e5SIgor M. Liplianin 984d2ffc447SIgor M. Liplianin if (state->config->ci_mode) { 985d2ffc447SIgor M. Liplianin switch (c->delivery_system) { 986d2ffc447SIgor M. Liplianin case SYS_DVBS: 987d2ffc447SIgor M. Liplianin default: 988d2ffc447SIgor M. Liplianin ds3000_writereg(state, 0xfd, 0x80); 989d2ffc447SIgor M. Liplianin break; 990d2ffc447SIgor M. Liplianin case SYS_DVBS2: 991d2ffc447SIgor M. Liplianin ds3000_writereg(state, 0xfd, 0x01); 992d2ffc447SIgor M. Liplianin break; 993d2ffc447SIgor M. Liplianin } 994d2ffc447SIgor M. Liplianin } 995d2ffc447SIgor M. Liplianin 99609ea33e5SIgor M. Liplianin /* ds3000 out of software reset */ 99709ea33e5SIgor M. Liplianin ds3000_writereg(state, 0x00, 0x00); 99809ea33e5SIgor M. Liplianin /* start ds3000 build-in uC */ 99909ea33e5SIgor M. Liplianin ds3000_writereg(state, 0xb2, 0x00); 100009ea33e5SIgor M. Liplianin 1001*c1965eaeSKonstantin Dimitrov if (fe->ops.tuner_ops.get_frequency) { 1002*c1965eaeSKonstantin Dimitrov fe->ops.tuner_ops.get_frequency(fe, &frequency); 1003*c1965eaeSKonstantin Dimitrov offset_khz = frequency - c->frequency; 1004a5bf834bSIgor M. Liplianin ds3000_set_carrier_offset(fe, offset_khz); 1005*c1965eaeSKonstantin Dimitrov } 100609ea33e5SIgor M. Liplianin 100709ea33e5SIgor M. Liplianin for (i = 0; i < 30 ; i++) { 100818a73f36SIgor M. Liplianin ds3000_read_status(fe, &status); 10093a9888f9SDan Carpenter if (status & FE_HAS_LOCK) 101018a73f36SIgor M. Liplianin break; 101118a73f36SIgor M. Liplianin 101218a73f36SIgor M. Liplianin msleep(10); 101309ea33e5SIgor M. Liplianin } 101409ea33e5SIgor M. Liplianin 101518a73f36SIgor M. Liplianin return 0; 101609ea33e5SIgor M. Liplianin } 101709ea33e5SIgor M. Liplianin 1018dcc8a122SIgor M. Liplianin static int ds3000_tune(struct dvb_frontend *fe, 10197e072221SMauro Carvalho Chehab bool re_tune, 1020738e8ff9SIgor M. Liplianin unsigned int mode_flags, 1021738e8ff9SIgor M. Liplianin unsigned int *delay, 1022738e8ff9SIgor M. Liplianin fe_status_t *status) 1023dcc8a122SIgor M. Liplianin { 10247e072221SMauro Carvalho Chehab if (re_tune) { 10259fe33018SMauro Carvalho Chehab int ret = ds3000_set_frontend(fe); 1026738e8ff9SIgor M. Liplianin if (ret) 1027738e8ff9SIgor M. Liplianin return ret; 1028738e8ff9SIgor M. Liplianin } 1029738e8ff9SIgor M. Liplianin 1030738e8ff9SIgor M. Liplianin *delay = HZ / 5; 1031738e8ff9SIgor M. Liplianin 1032738e8ff9SIgor M. Liplianin return ds3000_read_status(fe, status); 1033dcc8a122SIgor M. Liplianin } 1034dcc8a122SIgor M. Liplianin 103509ea33e5SIgor M. Liplianin static enum dvbfe_algo ds3000_get_algo(struct dvb_frontend *fe) 103609ea33e5SIgor M. Liplianin { 103709ea33e5SIgor M. Liplianin dprintk("%s()\n", __func__); 1038dcc8a122SIgor M. Liplianin return DVBFE_ALGO_HW; 103909ea33e5SIgor M. Liplianin } 104009ea33e5SIgor M. Liplianin 104109ea33e5SIgor M. Liplianin /* 104209ea33e5SIgor M. Liplianin * Initialise or wake up device 104309ea33e5SIgor M. Liplianin * 104409ea33e5SIgor M. Liplianin * Power config will reset and load initial firmware if required 104509ea33e5SIgor M. Liplianin */ 104609ea33e5SIgor M. Liplianin static int ds3000_initfe(struct dvb_frontend *fe) 104709ea33e5SIgor M. Liplianin { 1048a0ea298dSIgor M. Liplianin struct ds3000_state *state = fe->demodulator_priv; 1049a0ea298dSIgor M. Liplianin int ret; 1050a0ea298dSIgor M. Liplianin 105109ea33e5SIgor M. Liplianin dprintk("%s()\n", __func__); 1052a0ea298dSIgor M. Liplianin /* hard reset */ 1053a0ea298dSIgor M. Liplianin ds3000_writereg(state, 0x08, 0x01 | ds3000_readreg(state, 0x08)); 1054a0ea298dSIgor M. Liplianin msleep(1); 1055a0ea298dSIgor M. Liplianin 1056b9bf2eafSIgor M. Liplianin /* Load the firmware if required */ 1057b9bf2eafSIgor M. Liplianin ret = ds3000_firmware_ondemand(fe); 1058b9bf2eafSIgor M. Liplianin if (ret != 0) { 1059b9bf2eafSIgor M. Liplianin printk(KERN_ERR "%s: Unable initialize firmware\n", __func__); 1060b9bf2eafSIgor M. Liplianin return ret; 1061b9bf2eafSIgor M. Liplianin } 1062a0ea298dSIgor M. Liplianin 106309ea33e5SIgor M. Liplianin return 0; 106409ea33e5SIgor M. Liplianin } 106509ea33e5SIgor M. Liplianin 106609ea33e5SIgor M. Liplianin static struct dvb_frontend_ops ds3000_ops = { 10679fe33018SMauro Carvalho Chehab .delsys = { SYS_DVBS, SYS_DVBS2 }, 106809ea33e5SIgor M. Liplianin .info = { 1069*c1965eaeSKonstantin Dimitrov .name = "Montage Technology DS3000", 107009ea33e5SIgor M. Liplianin .frequency_min = 950000, 107109ea33e5SIgor M. Liplianin .frequency_max = 2150000, 107209ea33e5SIgor M. Liplianin .frequency_stepsize = 1011, /* kHz for QPSK frontends */ 107309ea33e5SIgor M. Liplianin .frequency_tolerance = 5000, 107409ea33e5SIgor M. Liplianin .symbol_rate_min = 1000000, 107509ea33e5SIgor M. Liplianin .symbol_rate_max = 45000000, 107609ea33e5SIgor M. Liplianin .caps = FE_CAN_INVERSION_AUTO | 107709ea33e5SIgor M. Liplianin FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 107809ea33e5SIgor M. Liplianin FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | 107909ea33e5SIgor M. Liplianin FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 108009ea33e5SIgor M. Liplianin FE_CAN_2G_MODULATION | 108109ea33e5SIgor M. Liplianin FE_CAN_QPSK | FE_CAN_RECOVER 108209ea33e5SIgor M. Liplianin }, 108309ea33e5SIgor M. Liplianin 108409ea33e5SIgor M. Liplianin .release = ds3000_release, 108509ea33e5SIgor M. Liplianin 108609ea33e5SIgor M. Liplianin .init = ds3000_initfe, 1087*c1965eaeSKonstantin Dimitrov .i2c_gate_ctrl = ds3000_i2c_gate_ctrl, 108809ea33e5SIgor M. Liplianin .read_status = ds3000_read_status, 108909ea33e5SIgor M. Liplianin .read_ber = ds3000_read_ber, 109009ea33e5SIgor M. Liplianin .read_snr = ds3000_read_snr, 109109ea33e5SIgor M. Liplianin .read_ucblocks = ds3000_read_ucblocks, 1092d2ffc447SIgor M. Liplianin .set_voltage = ds3000_set_voltage, 109309ea33e5SIgor M. Liplianin .set_tone = ds3000_set_tone, 109409ea33e5SIgor M. Liplianin .diseqc_send_master_cmd = ds3000_send_diseqc_msg, 109509ea33e5SIgor M. Liplianin .diseqc_send_burst = ds3000_diseqc_send_burst, 109609ea33e5SIgor M. Liplianin .get_frontend_algo = ds3000_get_algo, 109709ea33e5SIgor M. Liplianin 10989fe33018SMauro Carvalho Chehab .set_frontend = ds3000_set_frontend, 1099dcc8a122SIgor M. Liplianin .tune = ds3000_tune, 110009ea33e5SIgor M. Liplianin }; 110109ea33e5SIgor M. Liplianin 110209ea33e5SIgor M. Liplianin module_param(debug, int, 0644); 110309ea33e5SIgor M. Liplianin MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); 110409ea33e5SIgor M. Liplianin 110509ea33e5SIgor M. Liplianin MODULE_DESCRIPTION("DVB Frontend module for Montage Technology " 1106*c1965eaeSKonstantin Dimitrov "DS3000 hardware"); 1107*c1965eaeSKonstantin Dimitrov MODULE_AUTHOR("Konstantin Dimitrov <kosio.dimitrov@gmail.com>"); 110809ea33e5SIgor M. Liplianin MODULE_LICENSE("GPL"); 1109feadd7d3SRémi Cardona MODULE_FIRMWARE(DS3000_DEFAULT_FIRMWARE); 1110