linux/drivers/media/dvb-frontends/dibx000_common.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   3
   4#include <linux/i2c.h>
   5#include <linux/mutex.h>
   6#include <linux/module.h>
   7
   8#include "dibx000_common.h"
   9
  10static int debug;
  11module_param(debug, int, 0644);
  12MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
  13
  14#define dprintk(fmt, arg...) do {                                       \
  15        if (debug)                                                      \
  16                printk(KERN_DEBUG pr_fmt("%s: " fmt),                   \
  17                       __func__, ##arg);                                \
  18} while (0)
  19
  20static int dibx000_write_word(struct dibx000_i2c_master *mst, u16 reg, u16 val)
  21{
  22        int ret;
  23
  24        if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
  25                dprintk("could not acquire lock\n");
  26                return -EINVAL;
  27        }
  28
  29        mst->i2c_write_buffer[0] = (reg >> 8) & 0xff;
  30        mst->i2c_write_buffer[1] = reg & 0xff;
  31        mst->i2c_write_buffer[2] = (val >> 8) & 0xff;
  32        mst->i2c_write_buffer[3] = val & 0xff;
  33
  34        memset(mst->msg, 0, sizeof(struct i2c_msg));
  35        mst->msg[0].addr = mst->i2c_addr;
  36        mst->msg[0].flags = 0;
  37        mst->msg[0].buf = mst->i2c_write_buffer;
  38        mst->msg[0].len = 4;
  39
  40        ret = i2c_transfer(mst->i2c_adap, mst->msg, 1) != 1 ? -EREMOTEIO : 0;
  41        mutex_unlock(&mst->i2c_buffer_lock);
  42
  43        return ret;
  44}
  45
  46static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
  47{
  48        u16 ret;
  49
  50        if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
  51                dprintk("could not acquire lock\n");
  52                return 0;
  53        }
  54
  55        mst->i2c_write_buffer[0] = reg >> 8;
  56        mst->i2c_write_buffer[1] = reg & 0xff;
  57
  58        memset(mst->msg, 0, 2 * sizeof(struct i2c_msg));
  59        mst->msg[0].addr = mst->i2c_addr;
  60        mst->msg[0].flags = 0;
  61        mst->msg[0].buf = mst->i2c_write_buffer;
  62        mst->msg[0].len = 2;
  63        mst->msg[1].addr = mst->i2c_addr;
  64        mst->msg[1].flags = I2C_M_RD;
  65        mst->msg[1].buf = mst->i2c_read_buffer;
  66        mst->msg[1].len = 2;
  67
  68        if (i2c_transfer(mst->i2c_adap, mst->msg, 2) != 2)
  69                dprintk("i2c read error on %d\n", reg);
  70
  71        ret = (mst->i2c_read_buffer[0] << 8) | mst->i2c_read_buffer[1];
  72        mutex_unlock(&mst->i2c_buffer_lock);
  73
  74        return ret;
  75}
  76
  77static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
  78{
  79        int i = 100;
  80        u16 status;
  81
  82        while (((status = dibx000_read_word(mst, mst->base_reg + 2)) & 0x0100) == 0 && --i > 0)
  83                ;
  84
  85        /* i2c timed out */
  86        if (i == 0)
  87                return -EREMOTEIO;
  88
  89        /* no acknowledge */
  90        if ((status & 0x0080) == 0)
  91                return -EREMOTEIO;
  92
  93        return 0;
  94}
  95
  96static int dibx000_master_i2c_write(struct dibx000_i2c_master *mst, struct i2c_msg *msg, u8 stop)
  97{
  98        u16 data;
  99        u16 da;
 100        u16 i;
 101        u16 txlen = msg->len, len;
 102        const u8 *b = msg->buf;
 103
 104        while (txlen) {
 105                dibx000_read_word(mst, mst->base_reg + 2);
 106
 107                len = txlen > 8 ? 8 : txlen;
 108                for (i = 0; i < len; i += 2) {
 109                        data = *b++ << 8;
 110                        if (i+1 < len)
 111                                data |= *b++;
 112                        dibx000_write_word(mst, mst->base_reg, data);
 113                }
 114                da = (((u8) (msg->addr))  << 9) |
 115                        (1           << 8) |
 116                        (1           << 7) |
 117                        (0           << 6) |
 118                        (0           << 5) |
 119                        ((len & 0x7) << 2) |
 120                        (0           << 1) |
 121                        (0           << 0);
 122
 123                if (txlen == msg->len)
 124                        da |= 1 << 5; /* start */
 125
 126                if (txlen-len == 0 && stop)
 127                        da |= 1 << 6; /* stop */
 128
 129                dibx000_write_word(mst, mst->base_reg+1, da);
 130
 131                if (dibx000_is_i2c_done(mst) != 0)
 132                        return -EREMOTEIO;
 133                txlen -= len;
 134        }
 135
 136        return 0;
 137}
 138
 139static int dibx000_master_i2c_read(struct dibx000_i2c_master *mst, struct i2c_msg *msg)
 140{
 141        u16 da;
 142        u8 *b = msg->buf;
 143        u16 rxlen = msg->len, len;
 144
 145        while (rxlen) {
 146                len = rxlen > 8 ? 8 : rxlen;
 147                da = (((u8) (msg->addr)) << 9) |
 148                        (1           << 8) |
 149                        (1           << 7) |
 150                        (0           << 6) |
 151                        (0           << 5) |
 152                        ((len & 0x7) << 2) |
 153                        (1           << 1) |
 154                        (0           << 0);
 155
 156                if (rxlen == msg->len)
 157                        da |= 1 << 5; /* start */
 158
 159                if (rxlen-len == 0)
 160                        da |= 1 << 6; /* stop */
 161                dibx000_write_word(mst, mst->base_reg+1, da);
 162
 163                if (dibx000_is_i2c_done(mst) != 0)
 164                        return -EREMOTEIO;
 165
 166                rxlen -= len;
 167
 168                while (len) {
 169                        da = dibx000_read_word(mst, mst->base_reg);
 170                        *b++ = (da >> 8) & 0xff;
 171                        len--;
 172                        if (len >= 1) {
 173                                *b++ =  da   & 0xff;
 174                                len--;
 175                        }
 176                }
 177        }
 178
 179        return 0;
 180}
 181
 182int dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed)
 183{
 184        struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
 185
 186        if (mst->device_rev < DIB7000MC && speed < 235)
 187                speed = 235;
 188        return dibx000_write_word(mst, mst->base_reg + 3, (u16)(60000 / speed));
 189
 190}
 191EXPORT_SYMBOL(dibx000_i2c_set_speed);
 192
 193static u32 dibx000_i2c_func(struct i2c_adapter *adapter)
 194{
 195        return I2C_FUNC_I2C;
 196}
 197
 198static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst,
 199                                        enum dibx000_i2c_interface intf)
 200{
 201        if (mst->device_rev > DIB3000MC && mst->selected_interface != intf) {
 202                dprintk("selecting interface: %d\n", intf);
 203                mst->selected_interface = intf;
 204                return dibx000_write_word(mst, mst->base_reg + 4, intf);
 205        }
 206        return 0;
 207}
 208
 209static int dibx000_i2c_master_xfer_gpio12(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
 210{
 211        struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
 212        int msg_index;
 213        int ret = 0;
 214
 215        dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_1_2);
 216        for (msg_index = 0; msg_index < num; msg_index++) {
 217                if (msg[msg_index].flags & I2C_M_RD) {
 218                        ret = dibx000_master_i2c_read(mst, &msg[msg_index]);
 219                        if (ret != 0)
 220                                return 0;
 221                } else {
 222                        ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);
 223                        if (ret != 0)
 224                                return 0;
 225                }
 226        }
 227
 228        return num;
 229}
 230
 231static int dibx000_i2c_master_xfer_gpio34(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
 232{
 233        struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
 234        int msg_index;
 235        int ret = 0;
 236
 237        dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_3_4);
 238        for (msg_index = 0; msg_index < num; msg_index++) {
 239                if (msg[msg_index].flags & I2C_M_RD) {
 240                        ret = dibx000_master_i2c_read(mst, &msg[msg_index]);
 241                        if (ret != 0)
 242                                return 0;
 243                } else {
 244                        ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);
 245                        if (ret != 0)
 246                                return 0;
 247                }
 248        }
 249
 250        return num;
 251}
 252
 253static struct i2c_algorithm dibx000_i2c_master_gpio12_xfer_algo = {
 254        .master_xfer = dibx000_i2c_master_xfer_gpio12,
 255        .functionality = dibx000_i2c_func,
 256};
 257
 258static struct i2c_algorithm dibx000_i2c_master_gpio34_xfer_algo = {
 259        .master_xfer = dibx000_i2c_master_xfer_gpio34,
 260        .functionality = dibx000_i2c_func,
 261};
 262
 263static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4],
 264                                 u8 addr, int onoff)
 265{
 266        u16 val;
 267
 268
 269        if (onoff)
 270                val = addr << 8;        // bit 7 = use master or not, if 0, the gate is open
 271        else
 272                val = 1 << 7;
 273
 274        if (mst->device_rev > DIB7000)
 275                val <<= 1;
 276
 277        tx[0] = (((mst->base_reg + 1) >> 8) & 0xff);
 278        tx[1] = ((mst->base_reg + 1) & 0xff);
 279        tx[2] = val >> 8;
 280        tx[3] = val & 0xff;
 281
 282        return 0;
 283}
 284
 285static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
 286                                        struct i2c_msg msg[], int num)
 287{
 288        struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
 289        int ret;
 290
 291        if (num > 32) {
 292                dprintk("%s: too much I2C message to be transmitted (%i). Maximum is 32",
 293                        __func__, num);
 294                return -ENOMEM;
 295        }
 296
 297        dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
 298
 299        if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
 300                dprintk("could not acquire lock\n");
 301                return -EINVAL;
 302        }
 303
 304        memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
 305
 306        /* open the gate */
 307        dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
 308        mst->msg[0].addr = mst->i2c_addr;
 309        mst->msg[0].buf = &mst->i2c_write_buffer[0];
 310        mst->msg[0].len = 4;
 311
 312        memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
 313
 314        /* close the gate */
 315        dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
 316        mst->msg[num + 1].addr = mst->i2c_addr;
 317        mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
 318        mst->msg[num + 1].len = 4;
 319
 320        ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
 321                        num : -EIO);
 322
 323        mutex_unlock(&mst->i2c_buffer_lock);
 324        return ret;
 325}
 326
 327static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
 328        .master_xfer = dibx000_i2c_gated_gpio67_xfer,
 329        .functionality = dibx000_i2c_func,
 330};
 331
 332static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
 333                                        struct i2c_msg msg[], int num)
 334{
 335        struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
 336        int ret;
 337
 338        if (num > 32) {
 339                dprintk("%s: too much I2C message to be transmitted (%i). Maximum is 32",
 340                        __func__, num);
 341                return -ENOMEM;
 342        }
 343
 344        dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
 345
 346        if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
 347                dprintk("could not acquire lock\n");
 348                return -EINVAL;
 349        }
 350        memset(mst->msg, 0, sizeof(struct i2c_msg) * (2 + num));
 351
 352        /* open the gate */
 353        dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[0], msg[0].addr, 1);
 354        mst->msg[0].addr = mst->i2c_addr;
 355        mst->msg[0].buf = &mst->i2c_write_buffer[0];
 356        mst->msg[0].len = 4;
 357
 358        memcpy(&mst->msg[1], msg, sizeof(struct i2c_msg) * num);
 359
 360        /* close the gate */
 361        dibx000_i2c_gate_ctrl(mst, &mst->i2c_write_buffer[4], 0, 0);
 362        mst->msg[num + 1].addr = mst->i2c_addr;
 363        mst->msg[num + 1].buf = &mst->i2c_write_buffer[4];
 364        mst->msg[num + 1].len = 4;
 365
 366        ret = (i2c_transfer(mst->i2c_adap, mst->msg, 2 + num) == 2 + num ?
 367                        num : -EIO);
 368        mutex_unlock(&mst->i2c_buffer_lock);
 369        return ret;
 370}
 371
 372static struct i2c_algorithm dibx000_i2c_gated_tuner_algo = {
 373        .master_xfer = dibx000_i2c_gated_tuner_xfer,
 374        .functionality = dibx000_i2c_func,
 375};
 376
 377struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst,
 378                                                enum dibx000_i2c_interface intf,
 379                                                int gating)
 380{
 381        struct i2c_adapter *i2c = NULL;
 382
 383        switch (intf) {
 384        case DIBX000_I2C_INTERFACE_TUNER:
 385                if (gating)
 386                        i2c = &mst->gated_tuner_i2c_adap;
 387                break;
 388        case DIBX000_I2C_INTERFACE_GPIO_1_2:
 389                if (!gating)
 390                        i2c = &mst->master_i2c_adap_gpio12;
 391                break;
 392        case DIBX000_I2C_INTERFACE_GPIO_3_4:
 393                if (!gating)
 394                        i2c = &mst->master_i2c_adap_gpio34;
 395                break;
 396        case DIBX000_I2C_INTERFACE_GPIO_6_7:
 397                if (gating)
 398                        i2c = &mst->master_i2c_adap_gpio67;
 399                break;
 400        default:
 401                pr_err("incorrect I2C interface selected\n");
 402                break;
 403        }
 404
 405        return i2c;
 406}
 407
 408EXPORT_SYMBOL(dibx000_get_i2c_adapter);
 409
 410void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst)
 411{
 412        /* initialize the i2c-master by closing the gate */
 413        u8 tx[4];
 414        struct i2c_msg m = {.addr = mst->i2c_addr,.buf = tx,.len = 4 };
 415
 416        dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
 417        i2c_transfer(mst->i2c_adap, &m, 1);
 418        mst->selected_interface = 0xff; // the first time force a select of the I2C
 419        dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_TUNER);
 420}
 421
 422EXPORT_SYMBOL(dibx000_reset_i2c_master);
 423
 424static int i2c_adapter_init(struct i2c_adapter *i2c_adap,
 425                                struct i2c_algorithm *algo, const char *name,
 426                                struct dibx000_i2c_master *mst)
 427{
 428        strscpy(i2c_adap->name, name, sizeof(i2c_adap->name));
 429        i2c_adap->algo = algo;
 430        i2c_adap->algo_data = NULL;
 431        i2c_set_adapdata(i2c_adap, mst);
 432        if (i2c_add_adapter(i2c_adap) < 0)
 433                return -ENODEV;
 434        return 0;
 435}
 436
 437int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
 438                                struct i2c_adapter *i2c_adap, u8 i2c_addr)
 439{
 440        int ret;
 441
 442        mutex_init(&mst->i2c_buffer_lock);
 443        if (mutex_lock_interruptible(&mst->i2c_buffer_lock) < 0) {
 444                dprintk("could not acquire lock\n");
 445                return -EINVAL;
 446        }
 447        memset(mst->msg, 0, sizeof(struct i2c_msg));
 448        mst->msg[0].addr = i2c_addr >> 1;
 449        mst->msg[0].flags = 0;
 450        mst->msg[0].buf = mst->i2c_write_buffer;
 451        mst->msg[0].len = 4;
 452
 453        mst->device_rev = device_rev;
 454        mst->i2c_adap = i2c_adap;
 455        mst->i2c_addr = i2c_addr >> 1;
 456
 457        if (device_rev == DIB7000P || device_rev == DIB8000)
 458                mst->base_reg = 1024;
 459        else
 460                mst->base_reg = 768;
 461
 462        mst->gated_tuner_i2c_adap.dev.parent = mst->i2c_adap->dev.parent;
 463        if (i2c_adapter_init
 464                        (&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo,
 465                         "DiBX000 tuner I2C bus", mst) != 0)
 466                pr_err("could not initialize the tuner i2c_adapter\n");
 467
 468        mst->master_i2c_adap_gpio12.dev.parent = mst->i2c_adap->dev.parent;
 469        if (i2c_adapter_init
 470                        (&mst->master_i2c_adap_gpio12, &dibx000_i2c_master_gpio12_xfer_algo,
 471                         "DiBX000 master GPIO12 I2C bus", mst) != 0)
 472                pr_err("could not initialize the master i2c_adapter\n");
 473
 474        mst->master_i2c_adap_gpio34.dev.parent = mst->i2c_adap->dev.parent;
 475        if (i2c_adapter_init
 476                        (&mst->master_i2c_adap_gpio34, &dibx000_i2c_master_gpio34_xfer_algo,
 477                         "DiBX000 master GPIO34 I2C bus", mst) != 0)
 478                pr_err("could not initialize the master i2c_adapter\n");
 479
 480        mst->master_i2c_adap_gpio67.dev.parent = mst->i2c_adap->dev.parent;
 481        if (i2c_adapter_init
 482                        (&mst->master_i2c_adap_gpio67, &dibx000_i2c_gated_gpio67_algo,
 483                         "DiBX000 master GPIO67 I2C bus", mst) != 0)
 484                pr_err("could not initialize the master i2c_adapter\n");
 485
 486        /* initialize the i2c-master by closing the gate */
 487        dibx000_i2c_gate_ctrl(mst, mst->i2c_write_buffer, 0, 0);
 488
 489        ret = (i2c_transfer(i2c_adap, mst->msg, 1) == 1);
 490        mutex_unlock(&mst->i2c_buffer_lock);
 491
 492        return ret;
 493}
 494
 495EXPORT_SYMBOL(dibx000_init_i2c_master);
 496
 497void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
 498{
 499        i2c_del_adapter(&mst->gated_tuner_i2c_adap);
 500        i2c_del_adapter(&mst->master_i2c_adap_gpio12);
 501        i2c_del_adapter(&mst->master_i2c_adap_gpio34);
 502        i2c_del_adapter(&mst->master_i2c_adap_gpio67);
 503}
 504EXPORT_SYMBOL(dibx000_exit_i2c_master);
 505
 506MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@posteo.de>");
 507MODULE_DESCRIPTION("Common function the DiBcom demodulator family");
 508MODULE_LICENSE("GPL");
 509