Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  Samsung s5h1432 DVB-T demodulator driver
0004  *
0005  *  Copyright (C) 2009 Bill Liu <Bill.Liu@Conexant.com>
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/init.h>
0010 #include <linux/module.h>
0011 #include <linux/string.h>
0012 #include <linux/slab.h>
0013 #include <linux/delay.h>
0014 #include <media/dvb_frontend.h>
0015 #include "s5h1432.h"
0016 
0017 struct s5h1432_state {
0018 
0019     struct i2c_adapter *i2c;
0020 
0021     /* configuration settings */
0022     const struct s5h1432_config *config;
0023 
0024     struct dvb_frontend frontend;
0025 
0026     enum fe_modulation current_modulation;
0027     unsigned int first_tune:1;
0028 
0029     u32 current_frequency;
0030     int if_freq;
0031 
0032     u8 inversion;
0033 };
0034 
0035 static int debug;
0036 
0037 #define dprintk(arg...) do {    \
0038     if (debug)      \
0039         printk(arg);    \
0040     } while (0)
0041 
0042 static int s5h1432_writereg(struct s5h1432_state *state,
0043                 u8 addr, u8 reg, u8 data)
0044 {
0045     int ret;
0046     u8 buf[] = { reg, data };
0047 
0048     struct i2c_msg msg = {.addr = addr, .flags = 0, .buf = buf, .len = 2 };
0049 
0050     ret = i2c_transfer(state->i2c, &msg, 1);
0051 
0052     if (ret != 1)
0053         printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, ret == %i)\n",
0054                __func__, addr, reg, data, ret);
0055 
0056     return (ret != 1) ? -1 : 0;
0057 }
0058 
0059 static u8 s5h1432_readreg(struct s5h1432_state *state, u8 addr, u8 reg)
0060 {
0061     int ret;
0062     u8 b0[] = { reg };
0063     u8 b1[] = { 0 };
0064 
0065     struct i2c_msg msg[] = {
0066         {.addr = addr, .flags = 0, .buf = b0, .len = 1},
0067         {.addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 1}
0068     };
0069 
0070     ret = i2c_transfer(state->i2c, msg, 2);
0071 
0072     if (ret != 2)
0073         printk(KERN_ERR "%s: readreg error (ret == %i)\n",
0074                __func__, ret);
0075     return b1[0];
0076 }
0077 
0078 static int s5h1432_sleep(struct dvb_frontend *fe)
0079 {
0080     return 0;
0081 }
0082 
0083 static int s5h1432_set_channel_bandwidth(struct dvb_frontend *fe,
0084                      u32 bandwidth)
0085 {
0086     struct s5h1432_state *state = fe->demodulator_priv;
0087 
0088     u8 reg = 0;
0089 
0090     /* Register [0x2E] bit 3:2 : 8MHz = 0; 7MHz = 1; 6MHz = 2 */
0091     reg = s5h1432_readreg(state, S5H1432_I2C_TOP_ADDR, 0x2E);
0092     reg &= ~(0x0C);
0093     switch (bandwidth) {
0094     case 6:
0095         reg |= 0x08;
0096         break;
0097     case 7:
0098         reg |= 0x04;
0099         break;
0100     case 8:
0101         reg |= 0x00;
0102         break;
0103     default:
0104         return 0;
0105     }
0106     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x2E, reg);
0107     return 1;
0108 }
0109 
0110 static int s5h1432_set_IF(struct dvb_frontend *fe, u32 ifFreqHz)
0111 {
0112     struct s5h1432_state *state = fe->demodulator_priv;
0113 
0114     switch (ifFreqHz) {
0115     case TAIWAN_HI_IF_FREQ_44_MHZ:
0116         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x55);
0117         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x55);
0118         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0x15);
0119         break;
0120     case EUROPE_HI_IF_FREQ_36_MHZ:
0121         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x00);
0122         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x00);
0123         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0x40);
0124         break;
0125     case IF_FREQ_6_MHZ:
0126         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x00);
0127         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x00);
0128         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xe0);
0129         break;
0130     case IF_FREQ_3point3_MHZ:
0131         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x66);
0132         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x66);
0133         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEE);
0134         break;
0135     case IF_FREQ_3point5_MHZ:
0136         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x55);
0137         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x55);
0138         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xED);
0139         break;
0140     case IF_FREQ_4_MHZ:
0141         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0xAA);
0142         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0xAA);
0143         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEA);
0144         break;
0145     default:
0146         {
0147             u32 value = 0;
0148             value = (u32) (((48000 - (ifFreqHz / 1000)) * 512 *
0149                     (u32) 32768) / (48 * 1000));
0150             printk(KERN_INFO
0151                    "Default IFFreq %d :reg value = 0x%x\n",
0152                    ifFreqHz, value);
0153             s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4,
0154                      (u8) value & 0xFF);
0155             s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5,
0156                      (u8) (value >> 8) & 0xFF);
0157             s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7,
0158                      (u8) (value >> 16) & 0xFF);
0159             break;
0160         }
0161 
0162     }
0163 
0164     return 1;
0165 }
0166 
0167 /* Talk to the demod, set the FEC, GUARD, QAM settings etc */
0168 static int s5h1432_set_frontend(struct dvb_frontend *fe)
0169 {
0170     struct dtv_frontend_properties *p = &fe->dtv_property_cache;
0171     u32 dvb_bandwidth = 8;
0172     struct s5h1432_state *state = fe->demodulator_priv;
0173 
0174     if (p->frequency == state->current_frequency) {
0175         /*current_frequency = p->frequency; */
0176         /*state->current_frequency = p->frequency; */
0177     } else {
0178         fe->ops.tuner_ops.set_params(fe);
0179         msleep(300);
0180         s5h1432_set_channel_bandwidth(fe, dvb_bandwidth);
0181         switch (p->bandwidth_hz) {
0182         case 6000000:
0183             dvb_bandwidth = 6;
0184             s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
0185             break;
0186         case 7000000:
0187             dvb_bandwidth = 7;
0188             s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
0189             break;
0190         case 8000000:
0191             dvb_bandwidth = 8;
0192             s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
0193             break;
0194         default:
0195             return 0;
0196         }
0197         /*fe->ops.tuner_ops.set_params(fe); */
0198 /*Soft Reset chip*/
0199         msleep(30);
0200         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
0201         msleep(30);
0202         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b);
0203 
0204         s5h1432_set_channel_bandwidth(fe, dvb_bandwidth);
0205         switch (p->bandwidth_hz) {
0206         case 6000000:
0207             dvb_bandwidth = 6;
0208             s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
0209             break;
0210         case 7000000:
0211             dvb_bandwidth = 7;
0212             s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
0213             break;
0214         case 8000000:
0215             dvb_bandwidth = 8;
0216             s5h1432_set_IF(fe, IF_FREQ_4_MHZ);
0217             break;
0218         default:
0219             return 0;
0220         }
0221         /*fe->ops.tuner_ops.set_params(fe); */
0222         /*Soft Reset chip*/
0223         msleep(30);
0224         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
0225         msleep(30);
0226         s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b);
0227 
0228     }
0229 
0230     state->current_frequency = p->frequency;
0231 
0232     return 0;
0233 }
0234 
0235 static int s5h1432_init(struct dvb_frontend *fe)
0236 {
0237     struct s5h1432_state *state = fe->demodulator_priv;
0238 
0239     u8 reg = 0;
0240     state->current_frequency = 0;
0241     printk(KERN_INFO " s5h1432_init().\n");
0242 
0243     /*Set VSB mode as default, this also does a soft reset */
0244     /*Initialize registers */
0245 
0246     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x04, 0xa8);
0247     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x05, 0x01);
0248     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x07, 0x70);
0249     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x19, 0x80);
0250     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1b, 0x9D);
0251     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1c, 0x30);
0252     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1d, 0x20);
0253     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1e, 0x1B);
0254     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x2e, 0x40);
0255     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x42, 0x84);
0256     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x50, 0x5a);
0257     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x5a, 0xd3);
0258     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x68, 0x50);
0259     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xb8, 0x3c);
0260     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xc4, 0x10);
0261     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xcc, 0x9c);
0262     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xDA, 0x00);
0263     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe1, 0x94);
0264     /* s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xf4, 0xa1); */
0265     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xf9, 0x00);
0266 
0267     /*For NXP tuner*/
0268 
0269     /*Set 3.3MHz as default IF frequency */
0270     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x66);
0271     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x66);
0272     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEE);
0273     /* Set reg 0x1E to get the full dynamic range */
0274     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1e, 0x31);
0275 
0276     /* Mode setting in demod */
0277     reg = s5h1432_readreg(state, S5H1432_I2C_TOP_ADDR, 0x42);
0278     reg |= 0x80;
0279     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x42, reg);
0280     /* Serial mode */
0281 
0282     /* Soft Reset chip */
0283 
0284     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a);
0285     msleep(30);
0286     s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b);
0287 
0288 
0289     return 0;
0290 }
0291 
0292 static int s5h1432_read_status(struct dvb_frontend *fe, enum fe_status *status)
0293 {
0294     return 0;
0295 }
0296 
0297 static int s5h1432_read_signal_strength(struct dvb_frontend *fe,
0298                     u16 *signal_strength)
0299 {
0300     return 0;
0301 }
0302 
0303 static int s5h1432_read_snr(struct dvb_frontend *fe, u16 *snr)
0304 {
0305     return 0;
0306 }
0307 
0308 static int s5h1432_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
0309 {
0310 
0311     return 0;
0312 }
0313 
0314 static int s5h1432_read_ber(struct dvb_frontend *fe, u32 *ber)
0315 {
0316     return 0;
0317 }
0318 
0319 static int s5h1432_get_tune_settings(struct dvb_frontend *fe,
0320                      struct dvb_frontend_tune_settings *tune)
0321 {
0322     return 0;
0323 }
0324 
0325 static void s5h1432_release(struct dvb_frontend *fe)
0326 {
0327     struct s5h1432_state *state = fe->demodulator_priv;
0328     kfree(state);
0329 }
0330 
0331 static const struct dvb_frontend_ops s5h1432_ops;
0332 
0333 struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config,
0334                     struct i2c_adapter *i2c)
0335 {
0336     struct s5h1432_state *state = NULL;
0337 
0338     printk(KERN_INFO " Enter s5h1432_attach(). attach success!\n");
0339     /* allocate memory for the internal state */
0340     state = kmalloc(sizeof(struct s5h1432_state), GFP_KERNEL);
0341     if (!state)
0342         return NULL;
0343 
0344     /* setup the state */
0345     state->config = config;
0346     state->i2c = i2c;
0347     state->current_modulation = QAM_16;
0348     state->inversion = state->config->inversion;
0349 
0350     /* create dvb_frontend */
0351     memcpy(&state->frontend.ops, &s5h1432_ops,
0352            sizeof(struct dvb_frontend_ops));
0353 
0354     state->frontend.demodulator_priv = state;
0355 
0356     return &state->frontend;
0357 }
0358 EXPORT_SYMBOL(s5h1432_attach);
0359 
0360 static const struct dvb_frontend_ops s5h1432_ops = {
0361     .delsys = { SYS_DVBT },
0362     .info = {
0363          .name = "Samsung s5h1432 DVB-T Frontend",
0364          .frequency_min_hz = 177 * MHz,
0365          .frequency_max_hz = 858 * MHz,
0366          .frequency_stepsize_hz = 166666,
0367          .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
0368          FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
0369          FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
0370          FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
0371          FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER},
0372 
0373     .init = s5h1432_init,
0374     .sleep = s5h1432_sleep,
0375     .set_frontend = s5h1432_set_frontend,
0376     .get_tune_settings = s5h1432_get_tune_settings,
0377     .read_status = s5h1432_read_status,
0378     .read_ber = s5h1432_read_ber,
0379     .read_signal_strength = s5h1432_read_signal_strength,
0380     .read_snr = s5h1432_read_snr,
0381     .read_ucblocks = s5h1432_read_ucblocks,
0382     .release = s5h1432_release,
0383 };
0384 
0385 module_param(debug, int, 0644);
0386 MODULE_PARM_DESC(debug, "Enable verbose debug messages");
0387 
0388 MODULE_DESCRIPTION("Samsung s5h1432 DVB-T Demodulator driver");
0389 MODULE_AUTHOR("Bill Liu");
0390 MODULE_LICENSE("GPL");