tuner-i2c.h 5.1 KB

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