linux/drivers/media/dvb-frontends/ec100.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * E3C EC100 demodulator driver
   4 *
   5 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
   6 */
   7
   8#include <media/dvb_frontend.h>
   9#include "ec100.h"
  10
  11struct ec100_state {
  12        struct i2c_adapter *i2c;
  13        struct dvb_frontend frontend;
  14        struct ec100_config config;
  15
  16        u16 ber;
  17};
  18
  19/* write single register */
  20static int ec100_write_reg(struct ec100_state *state, u8 reg, u8 val)
  21{
  22        int ret;
  23        u8 buf[2] = {reg, val};
  24        struct i2c_msg msg[1] = {
  25                {
  26                        .addr = state->config.demod_address,
  27                        .flags = 0,
  28                        .len = sizeof(buf),
  29                        .buf = buf,
  30                }
  31        };
  32
  33        ret = i2c_transfer(state->i2c, msg, 1);
  34        if (ret == 1) {
  35                ret = 0;
  36        } else {
  37                dev_warn(&state->i2c->dev, "%s: i2c wr failed=%d reg=%02x\n",
  38                                KBUILD_MODNAME, ret, reg);
  39                ret = -EREMOTEIO;
  40        }
  41
  42        return ret;
  43}
  44
  45/* read single register */
  46static int ec100_read_reg(struct ec100_state *state, u8 reg, u8 *val)
  47{
  48        int ret;
  49        struct i2c_msg msg[2] = {
  50                {
  51                        .addr = state->config.demod_address,
  52                        .flags = 0,
  53                        .len = 1,
  54                        .buf = &reg
  55                }, {
  56                        .addr = state->config.demod_address,
  57                        .flags = I2C_M_RD,
  58                        .len = 1,
  59                        .buf = val
  60                }
  61        };
  62
  63        ret = i2c_transfer(state->i2c, msg, 2);
  64        if (ret == 2) {
  65                ret = 0;
  66        } else {
  67                dev_warn(&state->i2c->dev, "%s: i2c rd failed=%d reg=%02x\n",
  68                                KBUILD_MODNAME, ret, reg);
  69                ret = -EREMOTEIO;
  70        }
  71
  72        return ret;
  73}
  74
  75static int ec100_set_frontend(struct dvb_frontend *fe)
  76{
  77        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  78        struct ec100_state *state = fe->demodulator_priv;
  79        int ret;
  80        u8 tmp, tmp2;
  81
  82        dev_dbg(&state->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n",
  83                        __func__, c->frequency, c->bandwidth_hz);
  84
  85        /* program tuner */
  86        if (fe->ops.tuner_ops.set_params)
  87                fe->ops.tuner_ops.set_params(fe);
  88
  89        ret = ec100_write_reg(state, 0x04, 0x06);
  90        if (ret)
  91                goto error;
  92        ret = ec100_write_reg(state, 0x67, 0x58);
  93        if (ret)
  94                goto error;
  95        ret = ec100_write_reg(state, 0x05, 0x18);
  96        if (ret)
  97                goto error;
  98
  99        /* reg/bw |   6  |   7  |   8
 100           -------+------+------+------
 101           A 0x1b | 0xa1 | 0xe7 | 0x2c
 102           A 0x1c | 0x55 | 0x63 | 0x72
 103           -------+------+------+------
 104           B 0x1b | 0xb7 | 0x00 | 0x49
 105           B 0x1c | 0x55 | 0x64 | 0x72 */
 106
 107        switch (c->bandwidth_hz) {
 108        case 6000000:
 109                tmp = 0xb7;
 110                tmp2 = 0x55;
 111                break;
 112        case 7000000:
 113                tmp = 0x00;
 114                tmp2 = 0x64;
 115                break;
 116        case 8000000:
 117        default:
 118                tmp = 0x49;
 119                tmp2 = 0x72;
 120        }
 121
 122        ret = ec100_write_reg(state, 0x1b, tmp);
 123        if (ret)
 124                goto error;
 125        ret = ec100_write_reg(state, 0x1c, tmp2);
 126        if (ret)
 127                goto error;
 128
 129        ret = ec100_write_reg(state, 0x0c, 0xbb); /* if freq */
 130        if (ret)
 131                goto error;
 132        ret = ec100_write_reg(state, 0x0d, 0x31); /* if freq */
 133        if (ret)
 134                goto error;
 135
 136        ret = ec100_write_reg(state, 0x08, 0x24);
 137        if (ret)
 138                goto error;
 139
 140        ret = ec100_write_reg(state, 0x00, 0x00); /* go */
 141        if (ret)
 142                goto error;
 143        ret = ec100_write_reg(state, 0x00, 0x20); /* go */
 144        if (ret)
 145                goto error;
 146
 147        return ret;
 148error:
 149        dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
 150        return ret;
 151}
 152
 153static int ec100_get_tune_settings(struct dvb_frontend *fe,
 154        struct dvb_frontend_tune_settings *fesettings)
 155{
 156        fesettings->min_delay_ms = 300;
 157        fesettings->step_size = 0;
 158        fesettings->max_drift = 0;
 159
 160        return 0;
 161}
 162
 163static int ec100_read_status(struct dvb_frontend *fe, enum fe_status *status)
 164{
 165        struct ec100_state *state = fe->demodulator_priv;
 166        int ret;
 167        u8 tmp;
 168        *status = 0;
 169
 170        ret = ec100_read_reg(state, 0x42, &tmp);
 171        if (ret)
 172                goto error;
 173
 174        if (tmp & 0x80) {
 175                /* bit7 set - have lock */
 176                *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI |
 177                        FE_HAS_SYNC | FE_HAS_LOCK;
 178        } else {
 179                ret = ec100_read_reg(state, 0x01, &tmp);
 180                if (ret)
 181                        goto error;
 182
 183                if (tmp & 0x10) {
 184                        /* bit4 set - have signal */
 185                        *status |= FE_HAS_SIGNAL;
 186                        if (!(tmp & 0x01)) {
 187                                /* bit0 clear - have ~valid signal */
 188                                *status |= FE_HAS_CARRIER |  FE_HAS_VITERBI;
 189                        }
 190                }
 191        }
 192
 193        return ret;
 194error:
 195        dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
 196        return ret;
 197}
 198
 199static int ec100_read_ber(struct dvb_frontend *fe, u32 *ber)
 200{
 201        struct ec100_state *state = fe->demodulator_priv;
 202        int ret;
 203        u8 tmp, tmp2;
 204        u16 ber2;
 205
 206        *ber = 0;
 207
 208        ret = ec100_read_reg(state, 0x65, &tmp);
 209        if (ret)
 210                goto error;
 211        ret = ec100_read_reg(state, 0x66, &tmp2);
 212        if (ret)
 213                goto error;
 214
 215        ber2 = (tmp2 << 8) | tmp;
 216
 217        /* if counter overflow or clear */
 218        if (ber2 < state->ber)
 219                *ber = ber2;
 220        else
 221                *ber = ber2 - state->ber;
 222
 223        state->ber = ber2;
 224
 225        return ret;
 226error:
 227        dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
 228        return ret;
 229}
 230
 231static int ec100_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 232{
 233        struct ec100_state *state = fe->demodulator_priv;
 234        int ret;
 235        u8 tmp;
 236
 237        ret = ec100_read_reg(state, 0x24, &tmp);
 238        if (ret) {
 239                *strength = 0;
 240                goto error;
 241        }
 242
 243        *strength = ((tmp << 8) | tmp);
 244
 245        return ret;
 246error:
 247        dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
 248        return ret;
 249}
 250
 251static int ec100_read_snr(struct dvb_frontend *fe, u16 *snr)
 252{
 253        *snr = 0;
 254        return 0;
 255}
 256
 257static int ec100_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 258{
 259        *ucblocks = 0;
 260        return 0;
 261}
 262
 263static void ec100_release(struct dvb_frontend *fe)
 264{
 265        struct ec100_state *state = fe->demodulator_priv;
 266        kfree(state);
 267}
 268
 269static const struct dvb_frontend_ops ec100_ops;
 270
 271struct dvb_frontend *ec100_attach(const struct ec100_config *config,
 272        struct i2c_adapter *i2c)
 273{
 274        int ret;
 275        struct ec100_state *state = NULL;
 276        u8 tmp;
 277
 278        /* allocate memory for the internal state */
 279        state = kzalloc(sizeof(struct ec100_state), GFP_KERNEL);
 280        if (state == NULL)
 281                goto error;
 282
 283        /* setup the state */
 284        state->i2c = i2c;
 285        memcpy(&state->config, config, sizeof(struct ec100_config));
 286
 287        /* check if the demod is there */
 288        ret = ec100_read_reg(state, 0x33, &tmp);
 289        if (ret || tmp != 0x0b)
 290                goto error;
 291
 292        /* create dvb_frontend */
 293        memcpy(&state->frontend.ops, &ec100_ops,
 294                sizeof(struct dvb_frontend_ops));
 295        state->frontend.demodulator_priv = state;
 296
 297        return &state->frontend;
 298error:
 299        kfree(state);
 300        return NULL;
 301}
 302EXPORT_SYMBOL(ec100_attach);
 303
 304static const struct dvb_frontend_ops ec100_ops = {
 305        .delsys = { SYS_DVBT },
 306        .info = {
 307                .name = "E3C EC100 DVB-T",
 308                .caps =
 309                        FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
 310                        FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
 311                        FE_CAN_QPSK | FE_CAN_QAM_16 |
 312                        FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
 313                        FE_CAN_TRANSMISSION_MODE_AUTO |
 314                        FE_CAN_GUARD_INTERVAL_AUTO |
 315                        FE_CAN_HIERARCHY_AUTO |
 316                        FE_CAN_MUTE_TS
 317        },
 318
 319        .release = ec100_release,
 320        .set_frontend = ec100_set_frontend,
 321        .get_tune_settings = ec100_get_tune_settings,
 322        .read_status = ec100_read_status,
 323        .read_ber = ec100_read_ber,
 324        .read_signal_strength = ec100_read_signal_strength,
 325        .read_snr = ec100_read_snr,
 326        .read_ucblocks = ec100_read_ucblocks,
 327};
 328
 329MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 330MODULE_DESCRIPTION("E3C EC100 DVB-T demodulator driver");
 331MODULE_LICENSE("GPL");
 332