dibx000_common.c revision c6d74c2ce86a80c9859010eb65e622214a6993ed
142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher#include <linux/i2c.h> 242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher#include "dibx000_common.h" 442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcherstatic int debug; 642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettchermodule_param(debug, int, 0644); 742afd061700edb43bb082bc65a2ddde431151d6bPatrick BoettcherMODULE_PARM_DESC(debug, "turn on debugging (default: 0)"); 842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); } } while (0) 1042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 1142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcherstatic int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val) 1242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 1342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher u8 b[4] = { 1442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher (reg >> 8) & 0xff, reg & 0xff, 1542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher (val >> 8) & 0xff, val & 0xff, 1642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher }; 1742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher struct i2c_msg msg = { 1842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher .addr = mst->i2c_addr, .flags = 0, .buf = b, .len = 4 1942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher }; 2042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; 2142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 2242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 2342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 2442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcherstatic int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf) 2542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 2642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) { 2742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher dprintk("selecting interface: %d\n",intf); 2842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher mst->selected_interface = intf; 2942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return dibx000_write_word(mst, mst->base_reg + 4, intf); 3042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher } 3142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return 0; 3242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 3342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 3442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcherstatic int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4], u8 addr, int onoff) 3542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 3642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher u16 val; 3742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 3842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 3942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher if (onoff) 4042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher val = addr << 8; // bit 7 = use master or not, if 0, the gate is open 4142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher else 4242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher val = 1 << 7; 4342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 4442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher if (mst->device_rev > DIB7000) 4542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher val <<= 1; 4642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 4742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher tx[0] = (((mst->base_reg + 1) >> 8) & 0xff); 4842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher tx[1] = ( (mst->base_reg + 1) & 0xff); 4942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher tx[2] = val >> 8; 5042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher tx[3] = val & 0xff; 5142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 5242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return 0; 5342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 5442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 5542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcherstatic u32 dibx000_i2c_func(struct i2c_adapter *adapter) 5642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 5742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return I2C_FUNC_I2C; 5842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 5942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 6042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcherstatic int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num) 6142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 6242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap); 6342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher struct i2c_msg m[2 + num]; 6442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher u8 tx_open[4], tx_close[4]; 6542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 6642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher memset(m,0, sizeof(struct i2c_msg) * (2 + num)), 6742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 6842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER); 6942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 7042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1); 7142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher m[0].addr = mst->i2c_addr; 7242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher m[0].buf = tx_open; 7342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher m[0].len = 4; 7442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 7542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher memcpy(&m[1], msg, sizeof(struct i2c_msg) * num); 7642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 7742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0); 7842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher m[num+1].addr = mst->i2c_addr; 7942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher m[num+1].buf = tx_close; 8042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher m[num+1].len = 4; 8142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 8242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return i2c_transfer(mst->i2c_adap, m, 2+num) == 2 + num ? num : -EIO; 8342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 8442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 8542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcherstatic struct i2c_algorithm dibx000_i2c_gated_tuner_algo = { 8642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher .master_xfer = dibx000_i2c_gated_tuner_xfer, 8742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher .functionality = dibx000_i2c_func, 8842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher}; 8942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 9042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcherstruct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf, int gating) 9142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 9242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher struct i2c_adapter *i2c = NULL; 9342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 9442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher switch (intf) { 9542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher case DIBX000_I2C_INTERFACE_TUNER: 9642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher if (gating) 9742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher i2c = &mst->gated_tuner_i2c_adap; 9842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher break; 9942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher default: 10042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n"); 10142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher break; 10242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher } 10342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 10442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return i2c; 10542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 10642afd061700edb43bb082bc65a2ddde431151d6bPatrick BoettcherEXPORT_SYMBOL(dibx000_get_i2c_adapter); 10742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 10842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcherstatic int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char name[I2C_NAME_SIZE], struct dibx000_i2c_master *mst) 10942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 11042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher strncpy(i2c_adap->name, name, I2C_NAME_SIZE); 11142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher i2c_adap->class = I2C_CLASS_TV_DIGITAL, 11242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher i2c_adap->algo = algo; 11342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher i2c_adap->algo_data = NULL; 11442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher i2c_set_adapdata(i2c_adap, mst); 11542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher if (i2c_add_adapter(i2c_adap) < 0) 11642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return -ENODEV; 11742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return 0; 11842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 11942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 12042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcherint dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, struct i2c_adapter *i2c_adap, u8 i2c_addr) 12142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 12242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher u8 tx[4]; 12342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher struct i2c_msg m = { .addr = i2c_addr >> 1, .buf = tx, .len = 4 }; 12442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 12542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher mst->device_rev = device_rev; 12642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher mst->i2c_adap = i2c_adap; 12742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher mst->i2c_addr = i2c_addr >> 1; 12842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 12942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher if (device_rev == DIB7000P) 13042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher mst->base_reg = 1024; 13142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher else 13242afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher mst->base_reg = 768; 13342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 13442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher if (i2c_adapter_init(&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo, "DiBX000 tuner I2C bus", mst) != 0) 13542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher printk(KERN_ERR "DiBX000: could not initialize the tuner i2c_adapter\n"); 13642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 13742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher /* initialize the i2c-master by closing the gate */ 13842afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher dibx000_i2c_gate_ctrl(mst, tx, 0, 0); 13942afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 14042afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher return i2c_transfer(i2c_adap, &m, 1) == 1; 14142afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 14242afd061700edb43bb082bc65a2ddde431151d6bPatrick BoettcherEXPORT_SYMBOL(dibx000_init_i2c_master); 14342afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher 14442afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettchervoid dibx000_exit_i2c_master(struct dibx000_i2c_master *mst) 14542afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher{ 14642afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher i2c_del_adapter(&mst->gated_tuner_i2c_adap); 14742afd061700edb43bb082bc65a2ddde431151d6bPatrick Boettcher} 14842afd061700edb43bb082bc65a2ddde431151d6bPatrick BoettcherEXPORT_SYMBOL(dibx000_exit_i2c_master); 149c6d74c2ce86a80c9859010eb65e622214a6993edPatrick Boettcher 150c6d74c2ce86a80c9859010eb65e622214a6993edPatrick BoettcherMODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>"); 151c6d74c2ce86a80c9859010eb65e622214a6993edPatrick BoettcherMODULE_DESCRIPTION("Common function the DiBcom demodulator family"); 152c6d74c2ce86a80c9859010eb65e622214a6993edPatrick BoettcherMODULE_LICENSE("GPL"); 153