linux/drivers/media/pci/cx18/cx18-i2c.c
<<
>>
Prefs
   1/*
   2 *  cx18 I2C functions
   3 *
   4 *  Derived from ivtv-i2c.c
   5 *
   6 *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
   7 *  Copyright (C) 2008  Andy Walls <awalls@md.metrocast.net>
   8 *
   9 *  This program is free software; you can redistribute it and/or modify
  10 *  it under the terms of the GNU General Public License as published by
  11 *  the Free Software Foundation; either version 2 of the License, or
  12 *  (at your option) any later version.
  13 *
  14 *  This program is distributed in the hope that it will be useful,
  15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 *  GNU General Public License for more details.
  18 */
  19
  20#include "cx18-driver.h"
  21#include "cx18-io.h"
  22#include "cx18-cards.h"
  23#include "cx18-gpio.h"
  24#include "cx18-i2c.h"
  25#include "cx18-irq.h"
  26
  27#define CX18_REG_I2C_1_WR   0xf15000
  28#define CX18_REG_I2C_1_RD   0xf15008
  29#define CX18_REG_I2C_2_WR   0xf25100
  30#define CX18_REG_I2C_2_RD   0xf25108
  31
  32#define SETSCL_BIT      0x0001
  33#define SETSDL_BIT      0x0002
  34#define GETSCL_BIT      0x0004
  35#define GETSDL_BIT      0x0008
  36
  37#define CX18_CS5345_I2C_ADDR            0x4c
  38#define CX18_Z8F0811_IR_TX_I2C_ADDR     0x70
  39#define CX18_Z8F0811_IR_RX_I2C_ADDR     0x71
  40
  41/* This array should match the CX18_HW_ defines */
  42static const u8 hw_addrs[] = {
  43        0,                              /* CX18_HW_TUNER */
  44        0,                              /* CX18_HW_TVEEPROM */
  45        CX18_CS5345_I2C_ADDR,           /* CX18_HW_CS5345 */
  46        0,                              /* CX18_HW_DVB */
  47        0,                              /* CX18_HW_418_AV */
  48        0,                              /* CX18_HW_GPIO_MUX */
  49        0,                              /* CX18_HW_GPIO_RESET_CTRL */
  50        CX18_Z8F0811_IR_TX_I2C_ADDR,    /* CX18_HW_Z8F0811_IR_TX_HAUP */
  51        CX18_Z8F0811_IR_RX_I2C_ADDR,    /* CX18_HW_Z8F0811_IR_RX_HAUP */
  52};
  53
  54/* This array should match the CX18_HW_ defines */
  55/* This might well become a card-specific array */
  56static const u8 hw_bus[] = {
  57        1,      /* CX18_HW_TUNER */
  58        0,      /* CX18_HW_TVEEPROM */
  59        0,      /* CX18_HW_CS5345 */
  60        0,      /* CX18_HW_DVB */
  61        0,      /* CX18_HW_418_AV */
  62        0,      /* CX18_HW_GPIO_MUX */
  63        0,      /* CX18_HW_GPIO_RESET_CTRL */
  64        0,      /* CX18_HW_Z8F0811_IR_TX_HAUP */
  65        0,      /* CX18_HW_Z8F0811_IR_RX_HAUP */
  66};
  67
  68/* This array should match the CX18_HW_ defines */
  69static const char * const hw_devicenames[] = {
  70        "tuner",
  71        "tveeprom",
  72        "cs5345",
  73        "cx23418_DTV",
  74        "cx23418_AV",
  75        "gpio_mux",
  76        "gpio_reset_ctrl",
  77        "ir_tx_z8f0811_haup",
  78        "ir_rx_z8f0811_haup",
  79};
  80
  81static int cx18_i2c_new_ir(struct cx18 *cx, struct i2c_adapter *adap, u32 hw,
  82                           const char *type, u8 addr)
  83{
  84        struct i2c_board_info info;
  85        struct IR_i2c_init_data *init_data = &cx->ir_i2c_init_data;
  86        unsigned short addr_list[2] = { addr, I2C_CLIENT_END };
  87
  88        memset(&info, 0, sizeof(struct i2c_board_info));
  89        strlcpy(info.type, type, I2C_NAME_SIZE);
  90
  91        /* Our default information for ir-kbd-i2c.c to use */
  92        switch (hw) {
  93        case CX18_HW_Z8F0811_IR_RX_HAUP:
  94                init_data->ir_codes = RC_MAP_HAUPPAUGE;
  95                init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
  96                init_data->type = RC_PROTO_BIT_RC5 | RC_PROTO_BIT_RC6_MCE |
  97                                                        RC_PROTO_BIT_RC6_6A_32;
  98                init_data->name = cx->card_name;
  99                info.platform_data = init_data;
 100                break;
 101        }
 102
 103        return i2c_new_probed_device(adap, &info, addr_list, NULL) == NULL ?
 104               -1 : 0;
 105}
 106
 107int cx18_i2c_register(struct cx18 *cx, unsigned idx)
 108{
 109        struct v4l2_subdev *sd;
 110        int bus = hw_bus[idx];
 111        struct i2c_adapter *adap = &cx->i2c_adap[bus];
 112        const char *type = hw_devicenames[idx];
 113        u32 hw = 1 << idx;
 114
 115        if (hw == CX18_HW_TUNER) {
 116                /* special tuner group handling */
 117                sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
 118                                adap, type, 0, cx->card_i2c->radio);
 119                if (sd != NULL)
 120                        sd->grp_id = hw;
 121                sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
 122                                adap, type, 0, cx->card_i2c->demod);
 123                if (sd != NULL)
 124                        sd->grp_id = hw;
 125                sd = v4l2_i2c_new_subdev(&cx->v4l2_dev,
 126                                adap, type, 0, cx->card_i2c->tv);
 127                if (sd != NULL)
 128                        sd->grp_id = hw;
 129                return sd != NULL ? 0 : -1;
 130        }
 131
 132        if (hw & CX18_HW_IR_ANY)
 133                return cx18_i2c_new_ir(cx, adap, hw, type, hw_addrs[idx]);
 134
 135        /* Is it not an I2C device or one we do not wish to register? */
 136        if (!hw_addrs[idx])
 137                return -1;
 138
 139        /* It's an I2C device other than an analog tuner or IR chip */
 140        sd = v4l2_i2c_new_subdev(&cx->v4l2_dev, adap, type, hw_addrs[idx],
 141                                 NULL);
 142        if (sd != NULL)
 143                sd->grp_id = hw;
 144        return sd != NULL ? 0 : -1;
 145}
 146
 147/* Find the first member of the subdev group id in hw */
 148struct v4l2_subdev *cx18_find_hw(struct cx18 *cx, u32 hw)
 149{
 150        struct v4l2_subdev *result = NULL;
 151        struct v4l2_subdev *sd;
 152
 153        spin_lock(&cx->v4l2_dev.lock);
 154        v4l2_device_for_each_subdev(sd, &cx->v4l2_dev) {
 155                if (sd->grp_id == hw) {
 156                        result = sd;
 157                        break;
 158                }
 159        }
 160        spin_unlock(&cx->v4l2_dev.lock);
 161        return result;
 162}
 163
 164static void cx18_setscl(void *data, int state)
 165{
 166        struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
 167        int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
 168        u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
 169        u32 r = cx18_read_reg(cx, addr);
 170
 171        if (state)
 172                cx18_write_reg(cx, r | SETSCL_BIT, addr);
 173        else
 174                cx18_write_reg(cx, r & ~SETSCL_BIT, addr);
 175}
 176
 177static void cx18_setsda(void *data, int state)
 178{
 179        struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
 180        int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
 181        u32 addr = bus_index ? CX18_REG_I2C_2_WR : CX18_REG_I2C_1_WR;
 182        u32 r = cx18_read_reg(cx, addr);
 183
 184        if (state)
 185                cx18_write_reg(cx, r | SETSDL_BIT, addr);
 186        else
 187                cx18_write_reg(cx, r & ~SETSDL_BIT, addr);
 188}
 189
 190static int cx18_getscl(void *data)
 191{
 192        struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
 193        int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
 194        u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
 195
 196        return cx18_read_reg(cx, addr) & GETSCL_BIT;
 197}
 198
 199static int cx18_getsda(void *data)
 200{
 201        struct cx18 *cx = ((struct cx18_i2c_algo_callback_data *)data)->cx;
 202        int bus_index = ((struct cx18_i2c_algo_callback_data *)data)->bus_index;
 203        u32 addr = bus_index ? CX18_REG_I2C_2_RD : CX18_REG_I2C_1_RD;
 204
 205        return cx18_read_reg(cx, addr) & GETSDL_BIT;
 206}
 207
 208/* template for i2c-bit-algo */
 209static const struct i2c_adapter cx18_i2c_adap_template = {
 210        .name = "cx18 i2c driver",
 211        .algo = NULL,                   /* set by i2c-algo-bit */
 212        .algo_data = NULL,              /* filled from template */
 213        .owner = THIS_MODULE,
 214};
 215
 216#define CX18_SCL_PERIOD (10) /* usecs. 10 usec is period for a 100 KHz clock */
 217#define CX18_ALGO_BIT_TIMEOUT (2) /* seconds */
 218
 219static const struct i2c_algo_bit_data cx18_i2c_algo_template = {
 220        .setsda         = cx18_setsda,
 221        .setscl         = cx18_setscl,
 222        .getsda         = cx18_getsda,
 223        .getscl         = cx18_getscl,
 224        .udelay         = CX18_SCL_PERIOD/2,       /* 1/2 clock period in usec*/
 225        .timeout        = CX18_ALGO_BIT_TIMEOUT*HZ /* jiffies */
 226};
 227
 228/* init + register i2c adapter */
 229int init_cx18_i2c(struct cx18 *cx)
 230{
 231        int i, err;
 232        CX18_DEBUG_I2C("i2c init\n");
 233
 234        for (i = 0; i < 2; i++) {
 235                /* Setup algorithm for adapter */
 236                cx->i2c_algo[i] = cx18_i2c_algo_template;
 237                cx->i2c_algo_cb_data[i].cx = cx;
 238                cx->i2c_algo_cb_data[i].bus_index = i;
 239                cx->i2c_algo[i].data = &cx->i2c_algo_cb_data[i];
 240
 241                /* Setup adapter */
 242                cx->i2c_adap[i] = cx18_i2c_adap_template;
 243                cx->i2c_adap[i].algo_data = &cx->i2c_algo[i];
 244                sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name),
 245                                " #%d-%d", cx->instance, i);
 246                i2c_set_adapdata(&cx->i2c_adap[i], &cx->v4l2_dev);
 247                cx->i2c_adap[i].dev.parent = &cx->pci_dev->dev;
 248        }
 249
 250        if (cx18_read_reg(cx, CX18_REG_I2C_2_WR) != 0x0003c02f) {
 251                /* Reset/Unreset I2C hardware block */
 252                /* Clock select 220MHz */
 253                cx18_write_reg_expect(cx, 0x10000000, 0xc71004,
 254                                          0x00000000, 0x10001000);
 255                /* Clock Enable */
 256                cx18_write_reg_expect(cx, 0x10001000, 0xc71024,
 257                                          0x00001000, 0x10001000);
 258        }
 259        /* courtesy of Steven Toth <stoth@hauppauge.com> */
 260        cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0);
 261        mdelay(10);
 262        cx18_write_reg_expect(cx, 0x00c000c0, 0xc7001c, 0x000000c0, 0x00c000c0);
 263        mdelay(10);
 264        cx18_write_reg_expect(cx, 0x00c00000, 0xc7001c, 0x00000000, 0x00c000c0);
 265        mdelay(10);
 266
 267        /* Set to edge-triggered intrs. */
 268        cx18_write_reg(cx, 0x00c00000, 0xc730c8);
 269        /* Clear any stale intrs */
 270        cx18_write_reg_expect(cx, HW2_I2C1_INT|HW2_I2C2_INT, HW2_INT_CLR_STATUS,
 271                       ~(HW2_I2C1_INT|HW2_I2C2_INT), HW2_I2C1_INT|HW2_I2C2_INT);
 272
 273        /* Hw I2C1 Clock Freq ~100kHz */
 274        cx18_write_reg(cx, 0x00021c0f & ~4, CX18_REG_I2C_1_WR);
 275        cx18_setscl(&cx->i2c_algo_cb_data[0], 1);
 276        cx18_setsda(&cx->i2c_algo_cb_data[0], 1);
 277
 278        /* Hw I2C2 Clock Freq ~100kHz */
 279        cx18_write_reg(cx, 0x00021c0f & ~4, CX18_REG_I2C_2_WR);
 280        cx18_setscl(&cx->i2c_algo_cb_data[1], 1);
 281        cx18_setsda(&cx->i2c_algo_cb_data[1], 1);
 282
 283        cx18_call_hw(cx, CX18_HW_GPIO_RESET_CTRL,
 284                     core, reset, (u32) CX18_GPIO_RESET_I2C);
 285
 286        err = i2c_bit_add_bus(&cx->i2c_adap[0]);
 287        if (err)
 288                goto err;
 289        err = i2c_bit_add_bus(&cx->i2c_adap[1]);
 290        if (err)
 291                goto err_del_bus_0;
 292        return 0;
 293
 294 err_del_bus_0:
 295        i2c_del_adapter(&cx->i2c_adap[0]);
 296 err:
 297        return err;
 298}
 299
 300void exit_cx18_i2c(struct cx18 *cx)
 301{
 302        int i;
 303        CX18_DEBUG_I2C("i2c exit\n");
 304        cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_1_WR) | 4,
 305                                                        CX18_REG_I2C_1_WR);
 306        cx18_write_reg(cx, cx18_read_reg(cx, CX18_REG_I2C_2_WR) | 4,
 307                                                        CX18_REG_I2C_2_WR);
 308
 309        for (i = 0; i < 2; i++) {
 310                i2c_del_adapter(&cx->i2c_adap[i]);
 311        }
 312}
 313
 314/*
 315   Hauppauge HVR1600 should have:
 316   32 cx24227
 317   98 unknown
 318   a0 eeprom
 319   c2 tuner
 320   e? zilog ir
 321   */
 322