root/drivers/media/pci/cx18/cx18-i2c.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cx18_i2c_new_ir
  2. cx18_i2c_register
  3. cx18_find_hw
  4. cx18_setscl
  5. cx18_setsda
  6. cx18_getscl
  7. cx18_getsda
  8. init_cx18_i2c
  9. exit_cx18_i2c

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

/* [<][>][^][v][top][bottom][index][help] */