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