stk1160-i2c.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. /*
  2. * STK1160 driver
  3. *
  4. * Copyright (C) 2012 Ezequiel Garcia
  5. * <elezegarcia--a.t--gmail.com>
  6. *
  7. * Based on Easycap driver by R.M. Thomas
  8. * Copyright (C) 2010 R.M. Thomas
  9. * <rmthomas--a.t--sciolus.org>
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. */
  22. #include <linux/module.h>
  23. #include <linux/usb.h>
  24. #include <linux/i2c.h>
  25. #include "stk1160.h"
  26. #include "stk1160-reg.h"
  27. static unsigned int i2c_debug;
  28. module_param(i2c_debug, int, 0644);
  29. MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
  30. #define dprintk_i2c(fmt, args...) \
  31. do { \
  32. if (i2c_debug) \
  33. printk(KERN_DEBUG fmt, ##args); \
  34. } while (0)
  35. static int stk1160_i2c_busy_wait(struct stk1160 *dev, u8 wait_bit_mask)
  36. {
  37. unsigned long end;
  38. u8 flag;
  39. /* Wait until read/write finish bit is set */
  40. end = jiffies + msecs_to_jiffies(STK1160_I2C_TIMEOUT);
  41. while (time_is_after_jiffies(end)) {
  42. stk1160_read_reg(dev, STK1160_SICTL+1, &flag);
  43. /* read/write done? */
  44. if (flag & wait_bit_mask)
  45. goto done;
  46. usleep_range(10 * USEC_PER_MSEC, 20 * USEC_PER_MSEC);
  47. }
  48. return -ETIMEDOUT;
  49. done:
  50. return 0;
  51. }
  52. static int stk1160_i2c_write_reg(struct stk1160 *dev, u8 addr,
  53. u8 reg, u8 value)
  54. {
  55. int rc;
  56. /* Set serial device address */
  57. rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
  58. if (rc < 0)
  59. return rc;
  60. /* Set i2c device register sub-address */
  61. rc = stk1160_write_reg(dev, STK1160_SBUSW_WA, reg);
  62. if (rc < 0)
  63. return rc;
  64. /* Set i2c device register value */
  65. rc = stk1160_write_reg(dev, STK1160_SBUSW_WD, value);
  66. if (rc < 0)
  67. return rc;
  68. /* Start write now */
  69. rc = stk1160_write_reg(dev, STK1160_SICTL, 0x01);
  70. if (rc < 0)
  71. return rc;
  72. rc = stk1160_i2c_busy_wait(dev, 0x04);
  73. if (rc < 0)
  74. return rc;
  75. return 0;
  76. }
  77. static int stk1160_i2c_read_reg(struct stk1160 *dev, u8 addr,
  78. u8 reg, u8 *value)
  79. {
  80. int rc;
  81. /* Set serial device address */
  82. rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
  83. if (rc < 0)
  84. return rc;
  85. /* Set i2c device register sub-address */
  86. rc = stk1160_write_reg(dev, STK1160_SBUSR_RA, reg);
  87. if (rc < 0)
  88. return rc;
  89. /* Start read now */
  90. rc = stk1160_write_reg(dev, STK1160_SICTL, 0x20);
  91. if (rc < 0)
  92. return rc;
  93. rc = stk1160_i2c_busy_wait(dev, 0x01);
  94. if (rc < 0)
  95. return rc;
  96. rc = stk1160_read_reg(dev, STK1160_SBUSR_RD, value);
  97. if (rc < 0)
  98. return rc;
  99. return 0;
  100. }
  101. /*
  102. * stk1160_i2c_check_for_device()
  103. * check if there is a i2c_device at the supplied address
  104. */
  105. static int stk1160_i2c_check_for_device(struct stk1160 *dev,
  106. unsigned char addr)
  107. {
  108. int rc;
  109. /* Set serial device address */
  110. rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
  111. if (rc < 0)
  112. return rc;
  113. /* Set device sub-address, we'll chip version reg */
  114. rc = stk1160_write_reg(dev, STK1160_SBUSR_RA, 0x00);
  115. if (rc < 0)
  116. return rc;
  117. /* Start read now */
  118. rc = stk1160_write_reg(dev, STK1160_SICTL, 0x20);
  119. if (rc < 0)
  120. return rc;
  121. rc = stk1160_i2c_busy_wait(dev, 0x01);
  122. if (rc < 0)
  123. return -ENODEV;
  124. return 0;
  125. }
  126. /*
  127. * stk1160_i2c_xfer()
  128. * the main i2c transfer function
  129. */
  130. static int stk1160_i2c_xfer(struct i2c_adapter *i2c_adap,
  131. struct i2c_msg msgs[], int num)
  132. {
  133. struct stk1160 *dev = i2c_adap->algo_data;
  134. int addr, rc, i;
  135. for (i = 0; i < num; i++) {
  136. addr = msgs[i].addr << 1;
  137. dprintk_i2c("%s: addr=%x", __func__, addr);
  138. if (!msgs[i].len) {
  139. /* no len: check only for device presence */
  140. rc = stk1160_i2c_check_for_device(dev, addr);
  141. if (rc < 0) {
  142. dprintk_i2c(" no device\n");
  143. return rc;
  144. }
  145. } else if (msgs[i].flags & I2C_M_RD) {
  146. /* read request without preceding register selection */
  147. dprintk_i2c(" subaddr not selected");
  148. rc = -EOPNOTSUPP;
  149. goto err;
  150. } else if (i + 1 < num && msgs[i].len <= 2 &&
  151. (msgs[i + 1].flags & I2C_M_RD) &&
  152. msgs[i].addr == msgs[i + 1].addr) {
  153. if (msgs[i].len != 1 || msgs[i + 1].len != 1) {
  154. dprintk_i2c(" len not supported");
  155. rc = -EOPNOTSUPP;
  156. goto err;
  157. }
  158. dprintk_i2c(" subaddr=%x", msgs[i].buf[0]);
  159. rc = stk1160_i2c_read_reg(dev, addr, msgs[i].buf[0],
  160. msgs[i + 1].buf);
  161. dprintk_i2c(" read=%x", *msgs[i + 1].buf);
  162. /* consumed two msgs, so we skip one of them */
  163. i++;
  164. } else {
  165. if (msgs[i].len != 2) {
  166. dprintk_i2c(" len not supported");
  167. rc = -EOPNOTSUPP;
  168. goto err;
  169. }
  170. dprintk_i2c(" subaddr=%x write=%x",
  171. msgs[i].buf[0], msgs[i].buf[1]);
  172. rc = stk1160_i2c_write_reg(dev, addr, msgs[i].buf[0],
  173. msgs[i].buf[1]);
  174. }
  175. if (rc < 0)
  176. goto err;
  177. dprintk_i2c(" OK\n");
  178. }
  179. return num;
  180. err:
  181. dprintk_i2c(" ERROR: %d\n", rc);
  182. return num;
  183. }
  184. /*
  185. * functionality(), what da heck is this?
  186. */
  187. static u32 functionality(struct i2c_adapter *adap)
  188. {
  189. return I2C_FUNC_SMBUS_EMUL;
  190. }
  191. static struct i2c_algorithm algo = {
  192. .master_xfer = stk1160_i2c_xfer,
  193. .functionality = functionality,
  194. };
  195. static struct i2c_adapter adap_template = {
  196. .owner = THIS_MODULE,
  197. .name = "stk1160",
  198. .algo = &algo,
  199. };
  200. static struct i2c_client client_template = {
  201. .name = "stk1160 internal",
  202. };
  203. /*
  204. * stk1160_i2c_register()
  205. * register i2c bus
  206. */
  207. int stk1160_i2c_register(struct stk1160 *dev)
  208. {
  209. int rc;
  210. dev->i2c_adap = adap_template;
  211. dev->i2c_adap.dev.parent = dev->dev;
  212. strcpy(dev->i2c_adap.name, "stk1160");
  213. dev->i2c_adap.algo_data = dev;
  214. i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
  215. rc = i2c_add_adapter(&dev->i2c_adap);
  216. if (rc < 0) {
  217. stk1160_err("cannot add i2c adapter (%d)\n", rc);
  218. return rc;
  219. }
  220. dev->i2c_client = client_template;
  221. dev->i2c_client.adapter = &dev->i2c_adap;
  222. /* Set i2c clock divider device address */
  223. stk1160_write_reg(dev, STK1160_SICTL_CD, 0x0f);
  224. /* ??? */
  225. stk1160_write_reg(dev, STK1160_ASIC + 3, 0x00);
  226. return 0;
  227. }
  228. /*
  229. * stk1160_i2c_unregister()
  230. * unregister i2c_bus
  231. */
  232. int stk1160_i2c_unregister(struct stk1160 *dev)
  233. {
  234. i2c_del_adapter(&dev->i2c_adap);
  235. return 0;
  236. }