linux/drivers/media/video/hdpvr/hdpvr-i2c.c
<<
>>
Prefs
   1
   2/*
   3 * Hauppauge HD PVR USB driver
   4 *
   5 * Copyright (C) 2008      Janne Grunau (j@jannau.net)
   6 *
   7 * IR device registration code is
   8 * Copyright (C) 2010   Andy Walls <awalls@md.metrocast.net>
   9 *
  10 *      This program is free software; you can redistribute it and/or
  11 *      modify it under the terms of the GNU General Public License as
  12 *      published by the Free Software Foundation, version 2.
  13 *
  14 */
  15
  16#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
  17
  18#include <linux/i2c.h>
  19#include <linux/slab.h>
  20
  21#include "hdpvr.h"
  22
  23#define CTRL_READ_REQUEST       0xb8
  24#define CTRL_WRITE_REQUEST      0x38
  25
  26#define REQTYPE_I2C_READ        0xb1
  27#define REQTYPE_I2C_WRITE       0xb0
  28#define REQTYPE_I2C_WRITE_STATT 0xd0
  29
  30#define Z8F0811_IR_TX_I2C_ADDR  0x70
  31#define Z8F0811_IR_RX_I2C_ADDR  0x71
  32
  33
  34struct i2c_client *hdpvr_register_ir_tx_i2c(struct hdpvr_device *dev)
  35{
  36        struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data;
  37        struct i2c_board_info hdpvr_ir_tx_i2c_board_info = {
  38                I2C_BOARD_INFO("ir_tx_z8f0811_hdpvr", Z8F0811_IR_TX_I2C_ADDR),
  39        };
  40
  41        init_data->name = "HD-PVR";
  42        hdpvr_ir_tx_i2c_board_info.platform_data = init_data;
  43
  44        return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_tx_i2c_board_info);
  45}
  46
  47struct i2c_client *hdpvr_register_ir_rx_i2c(struct hdpvr_device *dev)
  48{
  49        struct IR_i2c_init_data *init_data = &dev->ir_i2c_init_data;
  50        struct i2c_board_info hdpvr_ir_rx_i2c_board_info = {
  51                I2C_BOARD_INFO("ir_rx_z8f0811_hdpvr", Z8F0811_IR_RX_I2C_ADDR),
  52        };
  53
  54        /* Our default information for ir-kbd-i2c.c to use */
  55        init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW;
  56        init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
  57        init_data->type = RC_TYPE_RC5;
  58        init_data->name = "HD-PVR";
  59        hdpvr_ir_rx_i2c_board_info.platform_data = init_data;
  60
  61        return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_rx_i2c_board_info);
  62}
  63
  64static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus,
  65                          unsigned char addr, char *data, int len)
  66{
  67        int ret;
  68
  69        if (len > sizeof(dev->i2c_buf))
  70                return -EINVAL;
  71
  72        ret = usb_control_msg(dev->udev,
  73                              usb_rcvctrlpipe(dev->udev, 0),
  74                              REQTYPE_I2C_READ, CTRL_READ_REQUEST,
  75                              (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
  76
  77        if (ret == len) {
  78                memcpy(data, &dev->i2c_buf, len);
  79                ret = 0;
  80        } else if (ret >= 0)
  81                ret = -EIO;
  82
  83        return ret;
  84}
  85
  86static int hdpvr_i2c_write(struct hdpvr_device *dev, int bus,
  87                           unsigned char addr, char *data, int len)
  88{
  89        int ret;
  90
  91        if (len > sizeof(dev->i2c_buf))
  92                return -EINVAL;
  93
  94        memcpy(&dev->i2c_buf, data, len);
  95        ret = usb_control_msg(dev->udev,
  96                              usb_sndctrlpipe(dev->udev, 0),
  97                              REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
  98                              (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
  99
 100        if (ret < 0)
 101                return ret;
 102
 103        ret = usb_control_msg(dev->udev,
 104                              usb_rcvctrlpipe(dev->udev, 0),
 105                              REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST,
 106                              0, 0, &dev->i2c_buf, 2, 1000);
 107
 108        if ((ret == 2) && (dev->i2c_buf[1] == (len - 1)))
 109                ret = 0;
 110        else if (ret >= 0)
 111                ret = -EIO;
 112
 113        return ret;
 114}
 115
 116static int hdpvr_transfer(struct i2c_adapter *i2c_adapter, struct i2c_msg *msgs,
 117                          int num)
 118{
 119        struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter);
 120        int retval = 0, i, addr;
 121
 122        if (num <= 0)
 123                return 0;
 124
 125        mutex_lock(&dev->i2c_mutex);
 126
 127        for (i = 0; i < num && !retval; i++) {
 128                addr = msgs[i].addr << 1;
 129
 130                if (msgs[i].flags & I2C_M_RD)
 131                        retval = hdpvr_i2c_read(dev, 1, addr, msgs[i].buf,
 132                                                msgs[i].len);
 133                else
 134                        retval = hdpvr_i2c_write(dev, 1, addr, msgs[i].buf,
 135                                                 msgs[i].len);
 136        }
 137
 138        mutex_unlock(&dev->i2c_mutex);
 139
 140        return retval ? retval : num;
 141}
 142
 143static u32 hdpvr_functionality(struct i2c_adapter *adapter)
 144{
 145        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 146}
 147
 148static struct i2c_algorithm hdpvr_algo = {
 149        .master_xfer   = hdpvr_transfer,
 150        .functionality = hdpvr_functionality,
 151};
 152
 153static struct i2c_adapter hdpvr_i2c_adapter_template = {
 154        .name   = "Hauppage HD PVR I2C",
 155        .owner  = THIS_MODULE,
 156        .algo   = &hdpvr_algo,
 157};
 158
 159static int hdpvr_activate_ir(struct hdpvr_device *dev)
 160{
 161        char buffer[8];
 162
 163        mutex_lock(&dev->i2c_mutex);
 164
 165        hdpvr_i2c_read(dev, 0, 0x54, buffer, 1);
 166
 167        buffer[0] = 0;
 168        buffer[1] = 0x8;
 169        hdpvr_i2c_write(dev, 1, 0x54, buffer, 2);
 170
 171        buffer[1] = 0x18;
 172        hdpvr_i2c_write(dev, 1, 0x54, buffer, 2);
 173
 174        mutex_unlock(&dev->i2c_mutex);
 175
 176        return 0;
 177}
 178
 179int hdpvr_register_i2c_adapter(struct hdpvr_device *dev)
 180{
 181        int retval = -ENOMEM;
 182
 183        hdpvr_activate_ir(dev);
 184
 185        memcpy(&dev->i2c_adapter, &hdpvr_i2c_adapter_template,
 186               sizeof(struct i2c_adapter));
 187        dev->i2c_adapter.dev.parent = &dev->udev->dev;
 188
 189        i2c_set_adapdata(&dev->i2c_adapter, dev);
 190
 191        retval = i2c_add_adapter(&dev->i2c_adapter);
 192
 193        return retval;
 194}
 195
 196#endif
 197