1102227Smike/* SPDX-License-Identifier: GPL-2.0-or-later */ 2102227Smike/* 3102227Smike tuner-i2c.h - i2c interface for different tuners 4102227Smike 5102227Smike Copyright (C) 2007 Michael Krufky (mkrufky@linuxtv.org) 6102227Smike 7102227Smike*/ 8102227Smike 9102227Smike#ifndef __TUNER_I2C_H__ 10102227Smike#define __TUNER_I2C_H__ 11102227Smike 12102227Smike#include <linux/i2c.h> 13102227Smike#include <linux/slab.h> 14102227Smike 15102227Smikestruct tuner_i2c_props { 16102227Smike u8 addr; 17102227Smike struct i2c_adapter *adap; 18102227Smike 19102227Smike /* used for tuner instance management */ 20102227Smike int count; 21102227Smike char *name; 22102227Smike}; 23102227Smike 24102227Smikestatic inline int tuner_i2c_xfer_send(struct tuner_i2c_props *props, 25102227Smike unsigned char *buf, int len) 26102227Smike{ 27102227Smike struct i2c_msg msg = { .addr = props->addr, .flags = 0, 28102227Smike .buf = buf, .len = len }; 29102227Smike int ret = i2c_transfer(props->adap, &msg, 1); 30102227Smike 31102227Smike return (ret == 1) ? len : ret; 32102227Smike} 33102227Smike 34102227Smikestatic inline int tuner_i2c_xfer_recv(struct tuner_i2c_props *props, 35102227Smike unsigned char *buf, int len) 36102227Smike{ 37102227Smike struct i2c_msg msg = { .addr = props->addr, .flags = I2C_M_RD, 38102227Smike .buf = buf, .len = len }; 39102227Smike int ret = i2c_transfer(props->adap, &msg, 1); 40102227Smike 41102227Smike return (ret == 1) ? len : ret; 42143063Sjoerg} 43143063Sjoerg 44143063Sjoergstatic inline int tuner_i2c_xfer_send_recv(struct tuner_i2c_props *props, 45143063Sjoerg unsigned char *obuf, int olen, 46102227Smike unsigned char *ibuf, int ilen) 47102227Smike{ 48102227Smike struct i2c_msg msg[2] = { { .addr = props->addr, .flags = 0, 49228469Sed .buf = obuf, .len = olen }, 50102227Smike { .addr = props->addr, .flags = I2C_M_RD, 51102227Smike .buf = ibuf, .len = ilen } }; 52102227Smike int ret = i2c_transfer(props->adap, msg, 2); 53102227Smike 54102227Smike return (ret == 2) ? ilen : ret; 55217147Stijl} 56209975Snwhitehorn 57209975Snwhitehorn/* Callers must declare as a global for the module: 58209975Snwhitehorn * 59217146Stijl * static LIST_HEAD(hybrid_tuner_instance_list); 60217146Stijl * 61217146Stijl * hybrid_tuner_instance_list should be the third argument 62102227Smike * passed into hybrid_tuner_request_state(). 63217146Stijl * 64217146Stijl * state structure must contain the following: 65217146Stijl * 66217146Stijl * struct list_head hybrid_tuner_instance_list; 67102227Smike * struct tuner_i2c_props i2c_props; 68217146Stijl * 69109475Sgrehan * hybrid_tuner_instance_list (both within state structure and globally) 70102227Smike * is only required if the driver is using hybrid_tuner_request_state 71102227Smike * and hybrid_tuner_release_state to manage state sharing between 72102227Smike * multiple instances of hybrid tuners. 73102227Smike */ 74102227Smike 75110566Smike#define tuner_printk(kernlvl, i2cprops, fmt, arg...) do { \ 76230229Sdas printk(kernlvl "%s %d-%04x: " fmt, i2cprops.name, \ 77217147Stijl i2cprops.adap ? \ 78209975Snwhitehorn i2c_adapter_id(i2cprops.adap) : -1, \ 79209975Snwhitehorn i2cprops.addr, ##arg); \ 80209975Snwhitehorn } while (0) 81209975Snwhitehorn 82209975Snwhitehorn/* TO DO: convert all callers of these macros to pass in 83102227Smike * struct tuner_i2c_props, then remove the macro wrappers */ 84209975Snwhitehorn 85209975Snwhitehorn#define __tuner_warn(i2cprops, fmt, arg...) do { \ 86102227Smike tuner_printk(KERN_WARNING, i2cprops, fmt, ##arg); \ 87102227Smike } while (0) 88102227Smike 89102227Smike#define __tuner_info(i2cprops, fmt, arg...) do { \ 90102227Smike tuner_printk(KERN_INFO, i2cprops, fmt, ##arg); \ 91102227Smike } while (0) 92102227Smike 93102227Smike#define __tuner_err(i2cprops, fmt, arg...) do { \ 94102227Smike tuner_printk(KERN_ERR, i2cprops, fmt, ##arg); \ 95217147Stijl } while (0) 96209975Snwhitehorn 97209975Snwhitehorn#define __tuner_dbg(i2cprops, fmt, arg...) do { \ 98209975Snwhitehorn if ((debug)) \ 99209975Snwhitehorn tuner_printk(KERN_DEBUG, i2cprops, fmt, ##arg); \ 100209975Snwhitehorn } while (0) 101209975Snwhitehorn 102209975Snwhitehorn#define tuner_warn(fmt, arg...) __tuner_warn(priv->i2c_props, fmt, ##arg) 103209975Snwhitehorn#define tuner_info(fmt, arg...) __tuner_info(priv->i2c_props, fmt, ##arg) 104209975Snwhitehorn#define tuner_err(fmt, arg...) __tuner_err(priv->i2c_props, fmt, ##arg) 105102227Smike#define tuner_dbg(fmt, arg...) __tuner_dbg(priv->i2c_props, fmt, ##arg) 106102227Smike 107102227Smike/****************************************************************************/ 108102227Smike 109102227Smike/* The return value of hybrid_tuner_request_state indicates the number of 110102227Smike * instances using this tuner object. 111102227Smike * 112209975Snwhitehorn * 0 - no instances, indicates an error - kzalloc must have failed 113209975Snwhitehorn * 114102227Smike * 1 - one instance, indicates that the tuner object was created successfully 115102227Smike * 116102227Smike * 2 (or more) instances, indicates that an existing tuner object was found 117102227Smike */ 118102227Smike 119102227Smike#define hybrid_tuner_request_state(type, state, list, i2cadap, i2caddr, devname)\ 120102227Smike({ \ 121102227Smike int __ret = 0; \ 122102227Smike list_for_each_entry(state, &list, hybrid_tuner_instance_list) { \ 123217147Stijl if (((i2cadap) && (state->i2c_props.adap)) && \ 124209975Snwhitehorn ((i2c_adapter_id(state->i2c_props.adap) == \ 125209975Snwhitehorn i2c_adapter_id(i2cadap)) && \ 126209975Snwhitehorn (i2caddr == state->i2c_props.addr))) { \ 127209975Snwhitehorn __tuner_info(state->i2c_props, \ 128209975Snwhitehorn "attaching existing instance\n"); \ 129102227Smike state->i2c_props.count++; \ 130102227Smike __ret = state->i2c_props.count; \ 131209975Snwhitehorn break; \ 132209975Snwhitehorn } \ 133209975Snwhitehorn } \ 134102227Smike if (0 == __ret) { \ 135102227Smike state = kzalloc(sizeof(type), GFP_KERNEL); \ 136264496Stijl if (!state) { \ 137102227Smike __ret = -ENOMEM; \ 138237517Sandrew goto __fail; \ 139237517Sandrew } \ 140237517Sandrew state->i2c_props.addr = i2caddr; \ 141102227Smike state->i2c_props.adap = i2cadap; \ 142102227Smike state->i2c_props.name = devname; \ 143102227Smike __tuner_info(state->i2c_props, \ 144143063Sjoerg "creating new instance\n"); \ 145102227Smike list_add_tail(&state->hybrid_tuner_instance_list, &list);\ 146102227Smike state->i2c_props.count++; \ 147102227Smike __ret = state->i2c_props.count; \ 148102227Smike } \ 149102227Smike__fail: \ 150102227Smike __ret; \ 151102227Smike}) 152102227Smike 153102227Smike#define hybrid_tuner_release_state(state) \ 154102227Smike({ \ 155143063Sjoerg int __ret; \ 156143063Sjoerg state->i2c_props.count--; \ 157102227Smike __ret = state->i2c_props.count; \ 158102227Smike if (!state->i2c_props.count) { \ 159102227Smike __tuner_info(state->i2c_props, "destroying instance\n");\ 160102227Smike list_del(&state->hybrid_tuner_instance_list); \ 161102227Smike kfree(state); \ 162 } \ 163 __ret; \ 164}) 165 166#define hybrid_tuner_report_instance_count(state) \ 167({ \ 168 int __ret = 0; \ 169 if (state) \ 170 __ret = state->i2c_props.count; \ 171 __ret; \ 172}) 173 174#endif /* __TUNER_I2C_H__ */ 175