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