tuner-i2c.h 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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,
  28. unsigned char *buf, int len)
  29. {
  30. struct i2c_msg msg = { .addr = props->addr, .flags = 0,
  31. .buf = buf, .len = len };
  32. int ret = i2c_transfer(props->adap, &msg, 1);
  33. return (ret == 1) ? len : ret;
  34. }
  35. static inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props,
  36. unsigned char *buf, int len)
  37. {
  38. struct i2c_msg msg = { .addr = props->addr, .flags = I2C_M_RD,
  39. .buf = buf, .len = len };
  40. int ret = i2c_transfer(props->adap, &msg, 1);
  41. return (ret == 1) ? len : ret;
  42. }
  43. static inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props,
  44. unsigned char *obuf, int olen,
  45. unsigned char *ibuf, int ilen)
  46. {
  47. struct i2c_msg msg[2] = { { .addr = props->addr, .flags = 0,
  48. .buf = obuf, .len = olen },
  49. { .addr = props->addr, .flags = I2C_M_RD,
  50. .buf = ibuf, .len = ilen } };
  51. int ret = i2c_transfer(props->adap, msg, 2);
  52. return (ret == 2) ? ilen : ret;
  53. }
  54. /* Callers must declare as a global for the module:
  55. *
  56. * static LIST_HEAD(hybrid_tuner_instance_list);
  57. *
  58. * hybrid_tuner_instance_list should be the third argument
  59. * passed into hybrid_tuner_request_state().
  60. *
  61. * state structure must contain the following:
  62. *
  63. * struct list_head hybrid_tuner_instance_list;
  64. * struct tuner_i2c_props i2c_props;
  65. *
  66. * hybrid_tuner_instance_list (both within state structure and globally)
  67. * is only required if the driver is using hybrid_tuner_request_state
  68. * and hybrid_tuner_release_state to manage state sharing between
  69. * multiple instances of hybrid tuners.
  70. */
  71. #define tuner_printk(kernlvl, i2cprops, fmt, arg...) do { \
  72. printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name, \
  73. i2cprops.adap ? \
  74. i2c_adapter_id(i2cprops.adap) : -1, \
  75. i2cprops.addr, ##arg); \
  76. } while (0)
  77. /* TO DO: convert all callers of these macros to pass in
  78. * struct tuner_i2c_props, then remove the macro wrappers */
  79. #define __tuner_warn(i2cprops, fmt, arg...) do { \
  80. tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg); \
  81. } while (0)
  82. #define __tuner_info(i2cprops, fmt, arg...) do { \
  83. tuner_printk(KERN_INFO, i2cprops, fmt, ##arg); \
  84. } while (0)
  85. #define __tuner_err(i2cprops, fmt, arg...) do { \
  86. tuner_printk(KERN_ERR, i2cprops, fmt, ##arg); \
  87. } while (0)
  88. #define __tuner_dbg(i2cprops, fmt, arg...) do { \
  89. if ((debug)) \
  90. tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg); \
  91. } while (0)
  92. #define tuner_warn(fmt, arg...) __tuner_warn(priv->i2c_props, fmt, ##arg)
  93. #define tuner_info(fmt, arg...) __tuner_info(priv->i2c_props, fmt, ##arg)
  94. #define tuner_err(fmt, arg...) __tuner_err(priv->i2c_props, fmt, ##arg)
  95. #define tuner_dbg(fmt, arg...) __tuner_dbg(priv->i2c_props, fmt, ##arg)
  96. /****************************************************************************/
  97. /* The return value of hybrid_tuner_request_state indicates the number of
  98. * instances using this tuner object.
  99. *
  100. * 0 - no instances, indicates an error - kzalloc must have failed
  101. *
  102. * 1 - one instance, indicates that the tuner object was created successfully
  103. *
  104. * 2 (or more) instances, indicates that an existing tuner object was found
  105. */
  106. #define hybrid_tuner_request_state(type, state, list, i2cadap, i2caddr, devname)\
  107. ({ \
  108. int __ret = 0; \
  109. list_for_each_entry(state, &list, hybrid_tuner_instance_list) { \
  110. if (((i2cadap) && (state->i2c_props.adap)) && \
  111. ((i2c_adapter_id(state->i2c_props.adap) == \
  112. i2c_adapter_id(i2cadap)) && \
  113. (i2caddr == state->i2c_props.addr))) { \
  114. __tuner_info(state->i2c_props, \
  115. "attaching existing instance\n"); \
  116. state->i2c_props.count++; \
  117. __ret = state->i2c_props.count; \
  118. break; \
  119. } \
  120. } \
  121. if (0 == __ret) { \
  122. state = kzalloc(sizeof(type), GFP_KERNEL); \
  123. if (NULL == state) \
  124. goto __fail; \
  125. state->i2c_props.addr = i2caddr; \
  126. state->i2c_props.adap = i2cadap; \
  127. state->i2c_props.name = devname; \
  128. __tuner_info(state->i2c_props, \
  129. "creating new instance\n"); \
  130. list_add_tail(&state->hybrid_tuner_instance_list, &list);\
  131. state->i2c_props.count++; \
  132. __ret = state->i2c_props.count; \
  133. } \
  134. __fail: \
  135. __ret; \
  136. })
  137. #define hybrid_tuner_release_state(state) \
  138. ({ \
  139. int __ret; \
  140. state->i2c_props.count--; \
  141. __ret = state->i2c_props.count; \
  142. if (!state->i2c_props.count) { \
  143. __tuner_info(state->i2c_props, "destroying instance\n");\
  144. list_del(&state->hybrid_tuner_instance_list); \
  145. kfree(state); \
  146. } \
  147. __ret; \
  148. })
  149. #define hybrid_tuner_report_instance_count(state) \
  150. ({ \
  151. int __ret = 0; \
  152. if (state) \
  153. __ret = state->i2c_props.count; \
  154. __ret; \
  155. })
  156. #endif /* __TUNER_I2C_H__ */