linux/drivers/media/tuners/tua9001.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Infineon TUA9001 silicon tuner driver
   4 *
   5 * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
   6 */
   7
   8#include "tua9001_priv.h"
   9
  10static int tua9001_init(struct dvb_frontend *fe)
  11{
  12        struct tua9001_dev *dev = fe->tuner_priv;
  13        struct i2c_client *client = dev->client;
  14        int ret, i;
  15        static const struct tua9001_reg_val data[] = {
  16                {0x1e, 0x6512},
  17                {0x25, 0xb888},
  18                {0x39, 0x5460},
  19                {0x3b, 0x00c0},
  20                {0x3a, 0xf000},
  21                {0x08, 0x0000},
  22                {0x32, 0x0030},
  23                {0x41, 0x703a},
  24                {0x40, 0x1c78},
  25                {0x2c, 0x1c00},
  26                {0x36, 0xc013},
  27                {0x37, 0x6f18},
  28                {0x27, 0x0008},
  29                {0x2a, 0x0001},
  30                {0x34, 0x0a40},
  31        };
  32
  33        dev_dbg(&client->dev, "\n");
  34
  35        if (fe->callback) {
  36                ret = fe->callback(client->adapter,
  37                                   DVB_FRONTEND_COMPONENT_TUNER,
  38                                   TUA9001_CMD_RESETN, 0);
  39                if (ret)
  40                        goto err;
  41        }
  42
  43        for (i = 0; i < ARRAY_SIZE(data); i++) {
  44                ret = regmap_write(dev->regmap, data[i].reg, data[i].val);
  45                if (ret)
  46                        goto err;
  47        }
  48        return 0;
  49err:
  50        dev_dbg(&client->dev, "failed=%d\n", ret);
  51        return ret;
  52}
  53
  54static int tua9001_sleep(struct dvb_frontend *fe)
  55{
  56        struct tua9001_dev *dev = fe->tuner_priv;
  57        struct i2c_client *client = dev->client;
  58        int ret;
  59
  60        dev_dbg(&client->dev, "\n");
  61
  62        if (fe->callback) {
  63                ret = fe->callback(client->adapter,
  64                                   DVB_FRONTEND_COMPONENT_TUNER,
  65                                   TUA9001_CMD_RESETN, 1);
  66                if (ret)
  67                        goto err;
  68        }
  69        return 0;
  70err:
  71        dev_dbg(&client->dev, "failed=%d\n", ret);
  72        return ret;
  73}
  74
  75static int tua9001_set_params(struct dvb_frontend *fe)
  76{
  77        struct tua9001_dev *dev = fe->tuner_priv;
  78        struct i2c_client *client = dev->client;
  79        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
  80        int ret, i;
  81        u16 val;
  82        struct tua9001_reg_val data[2];
  83
  84        dev_dbg(&client->dev,
  85                "delivery_system=%u frequency=%u bandwidth_hz=%u\n",
  86                c->delivery_system, c->frequency, c->bandwidth_hz);
  87
  88        switch (c->delivery_system) {
  89        case SYS_DVBT:
  90                switch (c->bandwidth_hz) {
  91                case 8000000:
  92                        val  = 0x0000;
  93                        break;
  94                case 7000000:
  95                        val  = 0x1000;
  96                        break;
  97                case 6000000:
  98                        val  = 0x2000;
  99                        break;
 100                case 5000000:
 101                        val  = 0x3000;
 102                        break;
 103                default:
 104                        ret = -EINVAL;
 105                        goto err;
 106                }
 107                break;
 108        default:
 109                ret = -EINVAL;
 110                goto err;
 111        }
 112
 113        data[0].reg = 0x04;
 114        data[0].val = val;
 115        data[1].reg = 0x1f;
 116        data[1].val = div_u64((u64) (c->frequency - 150000000) * 48, 1000000);
 117
 118        if (fe->callback) {
 119                ret = fe->callback(client->adapter,
 120                                   DVB_FRONTEND_COMPONENT_TUNER,
 121                                   TUA9001_CMD_RXEN, 0);
 122                if (ret)
 123                        goto err;
 124        }
 125
 126        for (i = 0; i < ARRAY_SIZE(data); i++) {
 127                ret = regmap_write(dev->regmap, data[i].reg, data[i].val);
 128                if (ret)
 129                        goto err;
 130        }
 131
 132        if (fe->callback) {
 133                ret = fe->callback(client->adapter,
 134                                   DVB_FRONTEND_COMPONENT_TUNER,
 135                                   TUA9001_CMD_RXEN, 1);
 136                if (ret)
 137                        goto err;
 138        }
 139        return 0;
 140err:
 141        dev_dbg(&client->dev, "failed=%d\n", ret);
 142        return ret;
 143}
 144
 145static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 146{
 147        struct tua9001_dev *dev = fe->tuner_priv;
 148        struct i2c_client *client = dev->client;
 149
 150        dev_dbg(&client->dev, "\n");
 151
 152        *frequency = 0; /* Zero-IF */
 153        return 0;
 154}
 155
 156static const struct dvb_tuner_ops tua9001_tuner_ops = {
 157        .info = {
 158                .name             = "Infineon TUA9001",
 159                .frequency_min_hz = 170 * MHz,
 160                .frequency_max_hz = 862 * MHz,
 161        },
 162
 163        .init = tua9001_init,
 164        .sleep = tua9001_sleep,
 165        .set_params = tua9001_set_params,
 166
 167        .get_if_frequency = tua9001_get_if_frequency,
 168};
 169
 170static int tua9001_probe(struct i2c_client *client,
 171                        const struct i2c_device_id *id)
 172{
 173        struct tua9001_dev *dev;
 174        struct tua9001_platform_data *pdata = client->dev.platform_data;
 175        struct dvb_frontend *fe = pdata->dvb_frontend;
 176        int ret;
 177        static const struct regmap_config regmap_config = {
 178                .reg_bits =  8,
 179                .val_bits = 16,
 180        };
 181
 182        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 183        if (!dev) {
 184                ret = -ENOMEM;
 185                goto err;
 186        }
 187
 188        dev->fe = pdata->dvb_frontend;
 189        dev->client = client;
 190        dev->regmap = devm_regmap_init_i2c(client, &regmap_config);
 191        if (IS_ERR(dev->regmap)) {
 192                ret = PTR_ERR(dev->regmap);
 193                goto err_kfree;
 194        }
 195
 196        if (fe->callback) {
 197                ret = fe->callback(client->adapter,
 198                                   DVB_FRONTEND_COMPONENT_TUNER,
 199                                   TUA9001_CMD_CEN, 1);
 200                if (ret)
 201                        goto err_kfree;
 202
 203                ret = fe->callback(client->adapter,
 204                                   DVB_FRONTEND_COMPONENT_TUNER,
 205                                   TUA9001_CMD_RXEN, 0);
 206                if (ret)
 207                        goto err_kfree;
 208
 209                ret = fe->callback(client->adapter,
 210                                   DVB_FRONTEND_COMPONENT_TUNER,
 211                                   TUA9001_CMD_RESETN, 1);
 212                if (ret)
 213                        goto err_kfree;
 214        }
 215
 216        fe->tuner_priv = dev;
 217        memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops,
 218                        sizeof(struct dvb_tuner_ops));
 219        i2c_set_clientdata(client, dev);
 220
 221        dev_info(&client->dev, "Infineon TUA9001 successfully attached\n");
 222        return 0;
 223err_kfree:
 224        kfree(dev);
 225err:
 226        dev_dbg(&client->dev, "failed=%d\n", ret);
 227        return ret;
 228}
 229
 230static int tua9001_remove(struct i2c_client *client)
 231{
 232        struct tua9001_dev *dev = i2c_get_clientdata(client);
 233        struct dvb_frontend *fe = dev->fe;
 234        int ret;
 235
 236        dev_dbg(&client->dev, "\n");
 237
 238        if (fe->callback) {
 239                ret = fe->callback(client->adapter,
 240                                   DVB_FRONTEND_COMPONENT_TUNER,
 241                                   TUA9001_CMD_CEN, 0);
 242                if (ret)
 243                        goto err_kfree;
 244        }
 245        kfree(dev);
 246        return 0;
 247err_kfree:
 248        kfree(dev);
 249        dev_dbg(&client->dev, "failed=%d\n", ret);
 250        return ret;
 251}
 252
 253static const struct i2c_device_id tua9001_id_table[] = {
 254        {"tua9001", 0},
 255        {}
 256};
 257MODULE_DEVICE_TABLE(i2c, tua9001_id_table);
 258
 259static struct i2c_driver tua9001_driver = {
 260        .driver = {
 261                .name   = "tua9001",
 262                .suppress_bind_attrs = true,
 263        },
 264        .probe          = tua9001_probe,
 265        .remove         = tua9001_remove,
 266        .id_table       = tua9001_id_table,
 267};
 268
 269module_i2c_driver(tua9001_driver);
 270
 271MODULE_DESCRIPTION("Infineon TUA9001 silicon tuner driver");
 272MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 273MODULE_LICENSE("GPL");
 274