linux/drivers/media/dvb-frontends/s5h1432.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  Samsung s5h1432 DVB-T demodulator driver
   4 *
   5 *  Copyright (C) 2009 Bill Liu <Bill.Liu@Conexant.com>
   6 */
   7
   8#include <linux/kernel.h>
   9#include <linux/init.h>
  10#include <linux/module.h>
  11#include <linux/string.h>
  12#include <linux/slab.h>
  13#include <linux/delay.h>
  14#include <media/dvb_frontend.h>
  15#include "s5h1432.h"
  16
  17struct s5h1432_state {
  18
  19        struct i2c_adapter *i2c;
  20
  21        /* configuration settings */
  22        const struct s5h1432_config *config;
  23
  24        struct dvb_frontend frontend;
  25
  26        enum fe_modulation current_modulation;
  27        unsigned int first_tune:1;
  28
  29        u32 current_frequency;
  30        int if_freq;
  31
  32        u8 inversion;
  33};
  34
  35static int debug;
  36
  37#define dprintk(arg...) do {    \
  38        if (debug)              \
  39                printk(arg);    \
  40        } while (0)
  41
  42static int s5h1432_writereg(struct s5h1432_state *state,
  43                            u8 addr, u8 reg, u8 data)
  44{
  45        int ret;
  46        u8 buf[] = { reg, data };
  47
  48        struct i2c_msg msg = {.addr = addr, .flags = 0, .buf = buf, .len = 2 };
  49
  50        ret = i2c_transfer(state->i2c, &msg, 1);
  51
  52        if (ret != 1)
  53                printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, ret == %i)\n",
  54                       __func__, addr, reg, data, ret);
  55
  56        return (ret != 1) ? -1 : 0;
  57}
  58
  59static u8 s5h1432_readreg(struct s5h1432_state *state, u8 addr, u8 reg)
  60{
  61        int ret;
  62        u8 b0[] = { reg };
  63        u8 b1[] = { 0 };
  64
  65        struct i2c_msg msg[] = {
  66                {.addr = addr, .flags = 0, .buf = b0, .len = 1},
  67                {.addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 1}
  68        };
  69
  70        ret = i2c_transfer(state->i2c, msg, 2);
  71
  72        if (ret != 2)
  73                printk(KERN_ERR "%s: readreg error (ret == %i)\n",
  74                       __func__, ret);
  75        return b1[0];
  76}
  77
  78static int s5h1432_sleep(struct dvb_frontend *fe)
  79{
  80        return 0;
  81}
  82
  83static int s5h1432_set_channel_bandwidth(struct dvb_frontend *fe,
  84                                         u32 bandwidth)
  85{
  86        struct s5h1432_state *state = fe->demodulator_priv;
  87
  88        u8 reg = 0;
  89
  90        /* Register [0x2E] bit 3:2 : 8MHz = 0; 7MHz = 1; 6MHz = 2 */
  91        reg = s5h1432_readreg(state, S5H1432_I2C_TOP_ADDR, 0x2E);
  92        reg &= ~(0x0C);
  93        switch (bandwidth) {
  94        case 6:
  95                reg |= 0x08;
  96                break;
  97        case 7:
  98                reg |= 0x04;
  99                break;
 100        case 8:
 101                reg |= 0x00;
 102                break;
 103        default:
 104                return 0;
 105        }
 106        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x2E, reg);
 107        return 1;
 108}
 109
 110static int s5h1432_set_IF(struct dvb_frontend *fe, u32 ifFreqHz)
 111{
 112        struct s5h1432_state *state = fe->demodulator_priv;
 113
 114        switch (ifFreqHz) {
 115        case TAIWAN_HI_IF_FREQ_44_MHZ:
 116                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x55);
 117                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x55);
 118                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0x15);
 119                break;
 120        case EUROPE_HI_IF_FREQ_36_MHZ:
 121                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x00);
 122                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x00);
 123                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0x40);
 124                break;
 125        case IF_FREQ_6_MHZ:
 126                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x00);
 127                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x00);
 128                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xe0);
 129                break;
 130        case IF_FREQ_3point3_MHZ:
 131                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x66);
 132                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x66);
 133                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEE);
 134                break;
 135        case IF_FREQ_3point5_MHZ:
 136                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x55);
 137                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x55);
 138                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xED);
 139                break;
 140        case IF_FREQ_4_MHZ:
 141                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0xAA);
 142                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0xAA);
 143                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEA);
 144                break;
 145        default:
 146                {
 147                        u32 value = 0;
 148                        value = (u32) (((48000 - (ifFreqHz / 1000)) * 512 *
 149                                        (u32) 32768) / (48 * 1000));
 150                        printk(KERN_INFO
 151                               "Default IFFreq %d :reg value = 0x%x\n",
 152                               ifFreqHz, value);
 153                        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4,
 154                                         (u8) value & 0xFF);
 155                        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5,
 156                                         (u8) (value >> 8) & 0xFF);
 157                        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7,
 158                                         (u8) (value >> 16) & 0xFF);
 159                        break;
 160                }
 161
 162        }
 163
 164        return 1;
 165}
 166
 167/* Talk to the demod, set the FEC, GUARD, QAM settings etc */
 168static int s5h1432_set_frontend(struct dvb_frontend *fe)
 169{
 170        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
 171        u32 dvb_bandwidth = 8;
 172        struct s5h1432_state *state = fe->demodulator_priv;
 173
 174        if (p->frequency == state->current_frequency) {
 175                /*current_frequency = p->frequency; */
 176                /*state->current_frequency = p->frequency; */
 177        } else {
 178                fe->ops.tuner_ops.set_params(fe);
 179                msleep(300);
 180                s5h1432_set_channel_bandwidth(fe, dvb_bandwidth);
 181                switch (p->bandwidth_hz) {
 182                case 6000000:
 183                        dvb_bandwidth = 6;
 184                        s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
 185                        break;
 186                case 7000000:
 187                        dvb_bandwidth = 7;
 188                        s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
 189                        break;
 190                case 8000000:
 191                        dvb_bandwidth = 8;
 192                        s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
 193                        break;
 194                default:
 195                        return 0;
 196                }
 197                /*fe->ops.tuner_ops.set_params(fe); */
 198/*Soft Reset chip*/
 199                msleep(30);
 200                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
 201                msleep(30);
 202                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b);
 203
 204                s5h1432_set_channel_bandwidth(fe, dvb_bandwidth);
 205                switch (p->bandwidth_hz) {
 206                case 6000000:
 207                        dvb_bandwidth = 6;
 208                        s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
 209                        break;
 210                case 7000000:
 211                        dvb_bandwidth = 7;
 212                        s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
 213                        break;
 214                case 8000000:
 215                        dvb_bandwidth = 8;
 216                        s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
 217                        break;
 218                default:
 219                        return 0;
 220                }
 221                /*fe->ops.tuner_ops.set_params(fe); */
 222                /*Soft Reset chip*/
 223                msleep(30);
 224                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
 225                msleep(30);
 226                s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b);
 227
 228        }
 229
 230        state->current_frequency = p->frequency;
 231
 232        return 0;
 233}
 234
 235static int s5h1432_init(struct dvb_frontend *fe)
 236{
 237        struct s5h1432_state *state = fe->demodulator_priv;
 238
 239        u8 reg = 0;
 240        state->current_frequency = 0;
 241        printk(KERN_INFO " s5h1432_init().\n");
 242
 243        /*Set VSB mode as default, this also does a soft reset */
 244        /*Initialize registers */
 245
 246        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x04, 0xa8);
 247        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x05, 0x01);
 248        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x07, 0x70);
 249        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x19, 0x80);
 250        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1b, 0x9D);
 251        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1c, 0x30);
 252        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1d, 0x20);
 253        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1e, 0x1B);
 254        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x2e, 0x40);
 255        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x42, 0x84);
 256        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x50, 0x5a);
 257        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x5a, 0xd3);
 258        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x68, 0x50);
 259        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xb8, 0x3c);
 260        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xc4, 0x10);
 261        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xcc, 0x9c);
 262        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xDA, 0x00);
 263        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe1, 0x94);
 264        /* s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xf4, 0xa1); */
 265        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xf9, 0x00);
 266
 267        /*For NXP tuner*/
 268
 269        /*Set 3.3MHz as default IF frequency */
 270        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x66);
 271        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x66);
 272        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEE);
 273        /* Set reg 0x1E to get the full dynamic range */
 274        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1e, 0x31);
 275
 276        /* Mode setting in demod */
 277        reg = s5h1432_readreg(state, S5H1432_I2C_TOP_ADDR, 0x42);
 278        reg |= 0x80;
 279        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x42, reg);
 280        /* Serial mode */
 281
 282        /* Soft Reset chip */
 283
 284        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
 285        msleep(30);
 286        s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b);
 287
 288
 289        return 0;
 290}
 291
 292static int s5h1432_read_status(struct dvb_frontend *fe, enum fe_status *status)
 293{
 294        return 0;
 295}
 296
 297static int s5h1432_read_signal_strength(struct dvb_frontend *fe,
 298                                        u16 *signal_strength)
 299{
 300        return 0;
 301}
 302
 303static int s5h1432_read_snr(struct dvb_frontend *fe, u16 *snr)
 304{
 305        return 0;
 306}
 307
 308static int s5h1432_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 309{
 310
 311        return 0;
 312}
 313
 314static int s5h1432_read_ber(struct dvb_frontend *fe, u32 *ber)
 315{
 316        return 0;
 317}
 318
 319static int s5h1432_get_tune_settings(struct dvb_frontend *fe,
 320                                     struct dvb_frontend_tune_settings *tune)
 321{
 322        return 0;
 323}
 324
 325static void s5h1432_release(struct dvb_frontend *fe)
 326{
 327        struct s5h1432_state *state = fe->demodulator_priv;
 328        kfree(state);
 329}
 330
 331static const struct dvb_frontend_ops s5h1432_ops;
 332
 333struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
 334                                    struct i2c_adapter *i2c)
 335{
 336        struct s5h1432_state *state = NULL;
 337
 338        printk(KERN_INFO " Enter s5h1432_attach(). attach success!\n");
 339        /* allocate memory for the internal state */
 340        state = kmalloc(sizeof(struct s5h1432_state), GFP_KERNEL);
 341        if (!state)
 342                return NULL;
 343
 344        /* setup the state */
 345        state->config = config;
 346        state->i2c = i2c;
 347        state->current_modulation = QAM_16;
 348        state->inversion = state->config->inversion;
 349
 350        /* create dvb_frontend */
 351        memcpy(&state->frontend.ops, &s5h1432_ops,
 352               sizeof(struct dvb_frontend_ops));
 353
 354        state->frontend.demodulator_priv = state;
 355
 356        return &state->frontend;
 357}
 358EXPORT_SYMBOL(s5h1432_attach);
 359
 360static const struct dvb_frontend_ops s5h1432_ops = {
 361        .delsys = { SYS_DVBT },
 362        .info = {
 363                 .name = "Samsung s5h1432 DVB-T Frontend",
 364                 .frequency_min_hz = 177 * MHz,
 365                 .frequency_max_hz = 858 * MHz,
 366                 .frequency_stepsize_hz = 166666,
 367                 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
 368                 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
 369                 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
 370                 FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
 371                 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER},
 372
 373        .init = s5h1432_init,
 374        .sleep = s5h1432_sleep,
 375        .set_frontend = s5h1432_set_frontend,
 376        .get_tune_settings = s5h1432_get_tune_settings,
 377        .read_status = s5h1432_read_status,
 378        .read_ber = s5h1432_read_ber,
 379        .read_signal_strength = s5h1432_read_signal_strength,
 380        .read_snr = s5h1432_read_snr,
 381        .read_ucblocks = s5h1432_read_ucblocks,
 382        .release = s5h1432_release,
 383};
 384
 385module_param(debug, int, 0644);
 386MODULE_PARM_DESC(debug, "Enable verbose debug messages");
 387
 388MODULE_DESCRIPTION("Samsung s5h1432 DVB-T Demodulator driver");
 389MODULE_AUTHOR("Bill Liu");
 390MODULE_LICENSE("GPL");
 391