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