linux/drivers/media/dvb-frontends/stb6000.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2  /*
   3     Driver for ST STB6000 DVBS Silicon tuner
   4
   5     Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
   6
   7
   8  */
   9
  10#include <linux/slab.h>
  11#include <linux/module.h>
  12#include <linux/dvb/frontend.h>
  13#include <asm/types.h>
  14
  15#include "stb6000.h"
  16
  17static int debug;
  18#define dprintk(args...) \
  19        do { \
  20                if (debug) \
  21                        printk(KERN_DEBUG "stb6000: " args); \
  22        } while (0)
  23
  24struct stb6000_priv {
  25        /* i2c details */
  26        int i2c_address;
  27        struct i2c_adapter *i2c;
  28        u32 frequency;
  29};
  30
  31static void stb6000_release(struct dvb_frontend *fe)
  32{
  33        kfree(fe->tuner_priv);
  34        fe->tuner_priv = NULL;
  35}
  36
  37static int stb6000_sleep(struct dvb_frontend *fe)
  38{
  39        struct stb6000_priv *priv = fe->tuner_priv;
  40        int ret;
  41        u8 buf[] = { 10, 0 };
  42        struct i2c_msg msg = {
  43                .addr = priv->i2c_address,
  44                .flags = 0,
  45                .buf = buf,
  46                .len = 2
  47        };
  48
  49        dprintk("%s:\n", __func__);
  50
  51        if (fe->ops.i2c_gate_ctrl)
  52                fe->ops.i2c_gate_ctrl(fe, 1);
  53
  54        ret = i2c_transfer(priv->i2c, &msg, 1);
  55        if (ret != 1)
  56                dprintk("%s: i2c error\n", __func__);
  57
  58        if (fe->ops.i2c_gate_ctrl)
  59                fe->ops.i2c_gate_ctrl(fe, 0);
  60
  61        return (ret == 1) ? 0 : ret;
  62}
  63
  64static int stb6000_set_params(struct dvb_frontend *fe)
  65{
  66        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
  67        struct stb6000_priv *priv = fe->tuner_priv;
  68        unsigned int n, m;
  69        int ret;
  70        u32 freq_mhz;
  71        int bandwidth;
  72        u8 buf[12];
  73        struct i2c_msg msg = {
  74                .addr = priv->i2c_address,
  75                .flags = 0,
  76                .buf = buf,
  77                .len = 12
  78        };
  79
  80        dprintk("%s:\n", __func__);
  81
  82        freq_mhz = p->frequency / 1000;
  83        bandwidth = p->symbol_rate / 1000000;
  84
  85        if (bandwidth > 31)
  86                bandwidth = 31;
  87
  88        if ((freq_mhz > 949) && (freq_mhz < 2151)) {
  89                buf[0] = 0x01;
  90                buf[1] = 0xac;
  91                if (freq_mhz < 1950)
  92                        buf[1] = 0xaa;
  93                if (freq_mhz < 1800)
  94                        buf[1] = 0xa8;
  95                if (freq_mhz < 1650)
  96                        buf[1] = 0xa6;
  97                if (freq_mhz < 1530)
  98                        buf[1] = 0xa5;
  99                if (freq_mhz < 1470)
 100                        buf[1] = 0xa4;
 101                if (freq_mhz < 1370)
 102                        buf[1] = 0xa2;
 103                if (freq_mhz < 1300)
 104                        buf[1] = 0xa1;
 105                if (freq_mhz < 1200)
 106                        buf[1] = 0xa0;
 107                if (freq_mhz < 1075)
 108                        buf[1] = 0xbc;
 109                if (freq_mhz < 1000)
 110                        buf[1] = 0xba;
 111                if (freq_mhz < 1075) {
 112                        n = freq_mhz / 8; /* vco=lo*4 */
 113                        m = 2;
 114                } else {
 115                        n = freq_mhz / 16; /* vco=lo*2 */
 116                        m = 1;
 117                }
 118                buf[2] = n >> 1;
 119                buf[3] = (unsigned char)(((n & 1) << 7) |
 120                                        (m * freq_mhz - n * 16) | 0x60);
 121                buf[4] = 0x04;
 122                buf[5] = 0x0e;
 123
 124                buf[6] = (unsigned char)(bandwidth);
 125
 126                buf[7] = 0xd8;
 127                buf[8] = 0xd0;
 128                buf[9] = 0x50;
 129                buf[10] = 0xeb;
 130                buf[11] = 0x4f;
 131
 132                if (fe->ops.i2c_gate_ctrl)
 133                        fe->ops.i2c_gate_ctrl(fe, 1);
 134
 135                ret = i2c_transfer(priv->i2c, &msg, 1);
 136                if (ret != 1)
 137                        dprintk("%s: i2c error\n", __func__);
 138
 139                udelay(10);
 140                if (fe->ops.i2c_gate_ctrl)
 141                        fe->ops.i2c_gate_ctrl(fe, 0);
 142
 143                buf[0] = 0x07;
 144                buf[1] = 0xdf;
 145                buf[2] = 0xd0;
 146                buf[3] = 0x50;
 147                buf[4] = 0xfb;
 148                msg.len = 5;
 149
 150                if (fe->ops.i2c_gate_ctrl)
 151                        fe->ops.i2c_gate_ctrl(fe, 1);
 152
 153                ret = i2c_transfer(priv->i2c, &msg, 1);
 154                if (ret != 1)
 155                        dprintk("%s: i2c error\n", __func__);
 156
 157                udelay(10);
 158                if (fe->ops.i2c_gate_ctrl)
 159                        fe->ops.i2c_gate_ctrl(fe, 0);
 160
 161                priv->frequency = freq_mhz * 1000;
 162
 163                return (ret == 1) ? 0 : ret;
 164        }
 165        return -1;
 166}
 167
 168static int stb6000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
 169{
 170        struct stb6000_priv *priv = fe->tuner_priv;
 171        *frequency = priv->frequency;
 172        return 0;
 173}
 174
 175static const struct dvb_tuner_ops stb6000_tuner_ops = {
 176        .info = {
 177                .name = "ST STB6000",
 178                .frequency_min_hz =  950 * MHz,
 179                .frequency_max_hz = 2150 * MHz
 180        },
 181        .release = stb6000_release,
 182        .sleep = stb6000_sleep,
 183        .set_params = stb6000_set_params,
 184        .get_frequency = stb6000_get_frequency,
 185};
 186
 187struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
 188                                                struct i2c_adapter *i2c)
 189{
 190        struct stb6000_priv *priv = NULL;
 191        u8 b0[] = { 0 };
 192        u8 b1[] = { 0, 0 };
 193        struct i2c_msg msg[2] = {
 194                {
 195                        .addr = addr,
 196                        .flags = 0,
 197                        .buf = b0,
 198                        .len = 0
 199                }, {
 200                        .addr = addr,
 201                        .flags = I2C_M_RD,
 202                        .buf = b1,
 203                        .len = 2
 204                }
 205        };
 206        int ret;
 207
 208        dprintk("%s:\n", __func__);
 209
 210        if (fe->ops.i2c_gate_ctrl)
 211                fe->ops.i2c_gate_ctrl(fe, 1);
 212
 213        /* is some i2c device here ? */
 214        ret = i2c_transfer(i2c, msg, 2);
 215        if (fe->ops.i2c_gate_ctrl)
 216                fe->ops.i2c_gate_ctrl(fe, 0);
 217
 218        if (ret != 2)
 219                return NULL;
 220
 221        priv = kzalloc(sizeof(struct stb6000_priv), GFP_KERNEL);
 222        if (priv == NULL)
 223                return NULL;
 224
 225        priv->i2c_address = addr;
 226        priv->i2c = i2c;
 227
 228        memcpy(&fe->ops.tuner_ops, &stb6000_tuner_ops,
 229                                sizeof(struct dvb_tuner_ops));
 230
 231        fe->tuner_priv = priv;
 232
 233        return fe;
 234}
 235EXPORT_SYMBOL(stb6000_attach);
 236
 237module_param(debug, int, 0644);
 238MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
 239
 240MODULE_DESCRIPTION("DVB STB6000 driver");
 241MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>");
 242MODULE_LICENSE("GPL");
 243