tuner-i2c.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /*
  2. tuner-i2c.h - i2c interface for different tuners
  3. Copyright (C) 2007 Michael Krufky (mkrufky@linuxtv.org)
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #ifndef __TUNER_I2C_H__
  17. #define __TUNER_I2C_H__
  18. #include <linux/i2c.h>
  19. #include <linux/slab.h>
  20. struct tuner_i2c_props {
  21. u8 addr;
  22. struct i2c_adapter *adap;
  23. /* used for tuner instance management */
  24. int count;
  25. char *name;
  26. };
  27. static inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, char *buf, int len)
  28. {
  29. struct i2c_msg msg = { .addr = props->addr, .flags = 0,
  30. .buf = buf, .len = len };
  31. int ret = i2c_transfer(props->adap, &msg, 1);
  32. return (ret == 1) ? len : ret;
  33. }
  34. static inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props, char *buf, int len)
  35. {
  36. struct i2c_msg msg = { .addr = props->addr, .flags = I2C_M_RD,
  37. .buf = buf, .len = len };
  38. int ret = i2c_transfer(props->adap, &msg, 1);
  39. return (ret == 1) ? len : ret;
  40. }
  41. static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props,
  42. char *obuf, int olen,
  43. char *ibuf, int ilen)
  44. {
  45. struct i2c_msg msg[2] = { { .addr = props->addr, .flags = 0,
  46. .buf = obuf, .len = olen },
  47. { .addr = props->addr, .flags = I2C_M_RD,
  48. .buf = ibuf, .len = ilen } };
  49. int ret = i2c_transfer(props->adap, msg, 2);
  50. return (ret == 2) ? ilen : ret;
  51. }
  52. /* Callers must declare as a global for the module:
  53. *
  54. * static LIST_HEAD(hybrid_tuner_instance_list);
  55. *
  56. * hybrid_tuner_instance_list should be the third argument
  57. * passed into hybrid_tuner_request_state().
  58. *
  59. * state structure must contain the following:
  60. *
  61. * struct list_head hybrid_tuner_instance_list;
  62. * struct tuner_i2c_props i2c_props;
  63. *
  64. * hybrid_tuner_instance_list (both within state structure and globally)
  65. * is only required if the driver is using hybrid_tuner_request_state
  66. * and hybrid_tuner_release_state to manage state sharing between
  67. * multiple instances of hybrid tuners.
  68. */
  69. #define tuner_printk(kernlvl, i2cprops, fmt, arg...) do { \
  70. printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name, \
  71. i2cprops.adap ? \
  72. i2c_adapter_id(i2cprops.adap) : -1, \
  73. i2cprops.addr, ##arg); \
  74. } while (0)
  75. /* TO DO: convert all callers of these macros to pass in
  76. * struct tuner_i2c_props, then remove the macro wrappers */
  77. #define __tuner_warn(i2cprops, fmt, arg...) do { \
  78. tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg); \
  79. } while (0)
  80. #define __tuner_info(i2cprops, fmt, arg...) do { \
  81. tuner_printk(KERN_INFO, i2cprops, fmt, ##arg); \
  82. } while (0)
  83. #define __tuner_err(i2cprops, fmt, arg...) do { \
  84. tuner_printk(KERN_ERR, i2cprops, fmt, ##arg); \
  85. } while (0)
  86. #define __tuner_dbg(i2cprops, fmt, arg...) do { \
  87. if ((debug)) \
  88. tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg); \
  89. } while (0)
  90. #define tuner_warn(fmt, arg...) __tuner_warn(priv->i2c_props, fmt, ##arg)
  91. #define tuner_info(fmt, arg...) __tuner_info(priv->i2c_props, fmt, ##arg)
  92. #define tuner_err(fmt, arg...) __tuner_err(priv->i2c_props, fmt, ##arg)
  93. #define tuner_dbg(fmt, arg...) __tuner_dbg(priv->i2c_props, fmt, ##arg)
  94. /****************************************************************************/
  95. /* The return value of hybrid_tuner_request_state indicates the number of
  96. * instances using this tuner object.
  97. *
  98. * 0 - no instances, indicates an error - kzalloc must have failed
  99. *
  100. * 1 - one instance, indicates that the tuner object was created successfully
  101. *
  102. * 2 (or more) instances, indicates that an existing tuner object was found
  103. */
  104. #define hybrid_tuner_request_state(type, state, list, i2cadap, i2caddr, devname)\
  105. ({ \
  106. int __ret = 0; \
  107. list_for_each_entry(state, &list, hybrid_tuner_instance_list) { \
  108. if (((i2cadap) && (state->i2c_props.adap)) && \
  109. ((i2c_adapter_id(state->i2c_props.adap) == \
  110. i2c_adapter_id(i2cadap)) && \
  111. (i2caddr == state->i2c_props.addr))) { \
  112. __tuner_info(state->i2c_props, \
  113. "attaching existing instance\n"); \
  114. state->i2c_props.count++; \
  115. __ret = state->i2c_props.count; \
  116. break; \
  117. } \
  118. } \
  119. if (0 == __ret) { \
  120. state = kzalloc(sizeof(type), GFP_KERNEL); \
  121. if (NULL == state) \
  122. goto __fail; \
  123. state->i2c_props.addr = i2caddr; \
  124. state->i2c_props.adap = i2cadap; \
  125. state->i2c_props.name = devname; \
  126. __tuner_info(state->i2c_props, \
  127. "creating new instance\n"); \
  128. list_add_tail(&state->hybrid_tuner_instance_list, &list);\
  129. state->i2c_props.count++; \
  130. __ret = state->i2c_props.count; \
  131. } \
  132. __fail: \
  133. __ret; \
  134. })
  135. #define hybrid_tuner_release_state(state) \
  136. ({ \
  137. int __ret; \
  138. state->i2c_props.count--; \
  139. __ret = state->i2c_props.count; \
  140. if (!state->i2c_props.count) { \
  141. __tuner_info(state->i2c_props, "destroying instance\n");\
  142. list_del(&state->hybrid_tuner_instance_list); \
  143. kfree(state); \
  144. } \
  145. __ret; \
  146. })
  147. #define hybrid_tuner_report_instance_count(state) \
  148. ({ \
  149. int __ret = 0; \
  150. if (state) \
  151. __ret = state->i2c_props.count; \
  152. __ret; \
  153. })
  154. #endif /* __TUNER_I2C_H__ */