dibx000_common.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #include <linux/i2c.h>
  2. #include "dibx000_common.h"
  3. static int debug;
  4. module_param(debug, int, 0644);
  5. MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
  6. #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiBX000: "); printk(args); } } while (0)
  7. static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
  8. {
  9. u8 b[4] = {
  10. (reg >> 8) & 0xff, reg & 0xff,
  11. (val >> 8) & 0xff, val & 0xff,
  12. };
  13. struct i2c_msg msg = {
  14. .addr = mst->i2c_addr, .flags = 0, .buf = b, .len = 4
  15. };
  16. return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
  17. }
  18. static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf)
  19. {
  20. if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {
  21. dprintk("selecting interface: %d\n",intf);
  22. mst->selected_interface = intf;
  23. return dibx000_write_word(mst, mst->base_reg + 4, intf);
  24. }
  25. return 0;
  26. }
  27. static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4], u8 addr, int onoff)
  28. {
  29. u16 val;
  30. if (onoff)
  31. val = addr << 8; // bit 7 = use master or not, if 0, the gate is open
  32. else
  33. val = 1 << 7;
  34. if (mst->device_rev > DIB7000)
  35. val <<= 1;
  36. tx[0] = (((mst->base_reg + 1) >> 8) & 0xff);
  37. tx[1] = ( (mst->base_reg + 1) & 0xff);
  38. tx[2] = val >> 8;
  39. tx[3] = val & 0xff;
  40. return 0;
  41. }
  42. static u32 dibx000_i2c_func(struct i2c_adapter *adapter)
  43. {
  44. return I2C_FUNC_I2C;
  45. }
  46. static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
  47. {
  48. struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
  49. struct i2c_msg m[2 + num];
  50. u8 tx_open[4], tx_close[4];
  51. memset(m,0, sizeof(struct i2c_msg) * (2 + num));
  52. dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
  53. dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
  54. m[0].addr = mst->i2c_addr;
  55. m[0].buf = tx_open;
  56. m[0].len = 4;
  57. memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
  58. dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
  59. m[num+1].addr = mst->i2c_addr;
  60. m[num+1].buf = tx_close;
  61. m[num+1].len = 4;
  62. return i2c_transfer(mst->i2c_adap, m, 2+num) == 2 + num ? num : -EIO;
  63. }
  64. static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
  65. .master_xfer = dibx000_i2c_gated_tuner_xfer,
  66. .functionality = dibx000_i2c_func,
  67. };
  68. struct i2c_adapter * dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst, enum dibx000_i2c_interface intf, int gating)
  69. {
  70. struct i2c_adapter *i2c = NULL;
  71. switch (intf) {
  72. case DIBX000_I2C_INTERFACE_TUNER:
  73. if (gating)
  74. i2c = &mst->gated_tuner_i2c_adap;
  75. break;
  76. default:
  77. printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n");
  78. break;
  79. }
  80. return i2c;
  81. }
  82. EXPORT_SYMBOL(dibx000_get_i2c_adapter);
  83. static int i2c_adapter_init(struct i2c_adapter *i2c_adap, struct i2c_algorithm *algo, const char *name, struct dibx000_i2c_master *mst)
  84. {
  85. strncpy(i2c_adap->name, name, sizeof(i2c_adap->name));
  86. i2c_adap->class = I2C_CLASS_TV_DIGITAL,
  87. i2c_adap->algo = algo;
  88. i2c_adap->algo_data = NULL;
  89. i2c_set_adapdata(i2c_adap, mst);
  90. if (i2c_add_adapter(i2c_adap) < 0)
  91. return -ENODEV;
  92. return 0;
  93. }
  94. int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev, struct i2c_adapter *i2c_adap, u8 i2c_addr)
  95. {
  96. u8 tx[4];
  97. struct i2c_msg m = { .addr = i2c_addr >> 1, .buf = tx, .len = 4 };
  98. mst->device_rev = device_rev;
  99. mst->i2c_adap = i2c_adap;
  100. mst->i2c_addr = i2c_addr >> 1;
  101. if (device_rev == DIB7000P)
  102. mst->base_reg = 1024;
  103. else
  104. mst->base_reg = 768;
  105. if (i2c_adapter_init(&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo, "DiBX000 tuner I2C bus", mst) != 0)
  106. printk(KERN_ERR "DiBX000: could not initialize the tuner i2c_adapter\n");
  107. /* initialize the i2c-master by closing the gate */
  108. dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
  109. return i2c_transfer(i2c_adap, &m, 1) == 1;
  110. }
  111. EXPORT_SYMBOL(dibx000_init_i2c_master);
  112. void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
  113. {
  114. i2c_del_adapter(&mst->gated_tuner_i2c_adap);
  115. }
  116. EXPORT_SYMBOL(dibx000_exit_i2c_master);
  117. MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
  118. MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
  119. MODULE_LICENSE("GPL");