Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * horus3a.h
0004  *
0005  * Sony Horus3A DVB-S/S2 tuner driver
0006  *
0007  * Copyright 2012 Sony Corporation
0008  * Copyright (C) 2014 NetUP Inc.
0009  * Copyright (C) 2014 Sergey Kozlov <serjk@netup.ru>
0010  * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru>
0011  */
0012 
0013 #include <linux/slab.h>
0014 #include <linux/module.h>
0015 #include <linux/dvb/frontend.h>
0016 #include <linux/types.h>
0017 #include "horus3a.h"
0018 #include <media/dvb_frontend.h>
0019 
0020 #define MAX_WRITE_REGSIZE      5
0021 
0022 enum horus3a_state {
0023     STATE_UNKNOWN,
0024     STATE_SLEEP,
0025     STATE_ACTIVE
0026 };
0027 
0028 struct horus3a_priv {
0029     u32         frequency;
0030     u8          i2c_address;
0031     struct i2c_adapter  *i2c;
0032     enum horus3a_state  state;
0033     void            *set_tuner_data;
0034     int         (*set_tuner)(void *, int);
0035 };
0036 
0037 static void horus3a_i2c_debug(struct horus3a_priv *priv,
0038                   u8 reg, u8 write, const u8 *data, u32 len)
0039 {
0040     dev_dbg(&priv->i2c->dev, "horus3a: I2C %s reg 0x%02x size %d\n",
0041         (write == 0 ? "read" : "write"), reg, len);
0042     print_hex_dump_bytes("horus3a: I2C data: ",
0043         DUMP_PREFIX_OFFSET, data, len);
0044 }
0045 
0046 static int horus3a_write_regs(struct horus3a_priv *priv,
0047                   u8 reg, const u8 *data, u32 len)
0048 {
0049     int ret;
0050     u8 buf[MAX_WRITE_REGSIZE + 1];
0051     struct i2c_msg msg[1] = {
0052         {
0053             .addr = priv->i2c_address,
0054             .flags = 0,
0055             .len = len + 1,
0056             .buf = buf,
0057         }
0058     };
0059 
0060     if (len + 1 > sizeof(buf)) {
0061         dev_warn(&priv->i2c->dev,"wr reg=%04x: len=%d is too big!\n",
0062              reg, len + 1);
0063         return -E2BIG;
0064     }
0065 
0066     horus3a_i2c_debug(priv, reg, 1, data, len);
0067     buf[0] = reg;
0068     memcpy(&buf[1], data, len);
0069     ret = i2c_transfer(priv->i2c, msg, 1);
0070     if (ret >= 0 && ret != 1)
0071         ret = -EREMOTEIO;
0072     if (ret < 0) {
0073         dev_warn(&priv->i2c->dev,
0074             "%s: i2c wr failed=%d reg=%02x len=%d\n",
0075             KBUILD_MODNAME, ret, reg, len);
0076         return ret;
0077     }
0078     return 0;
0079 }
0080 
0081 static int horus3a_write_reg(struct horus3a_priv *priv, u8 reg, u8 val)
0082 {
0083     u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
0084 
0085     return horus3a_write_regs(priv, reg, &tmp, 1);
0086 }
0087 
0088 static int horus3a_enter_power_save(struct horus3a_priv *priv)
0089 {
0090     u8 data[2];
0091 
0092     dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
0093     if (priv->state == STATE_SLEEP)
0094         return 0;
0095     /* IQ Generator disable */
0096     horus3a_write_reg(priv, 0x2a, 0x79);
0097     /* MDIV_EN = 0 */
0098     horus3a_write_reg(priv, 0x29, 0x70);
0099     /* VCO disable preparation */
0100     horus3a_write_reg(priv, 0x28, 0x3e);
0101     /* VCO buffer disable */
0102     horus3a_write_reg(priv, 0x2a, 0x19);
0103     /* VCO calibration disable */
0104     horus3a_write_reg(priv, 0x1c, 0x00);
0105     /* Power save setting (xtal is not stopped) */
0106     data[0] = 0xC0;
0107     /* LNA is Disabled */
0108     data[1] = 0xA7;
0109     /* 0x11 - 0x12 */
0110     horus3a_write_regs(priv, 0x11, data, sizeof(data));
0111     priv->state = STATE_SLEEP;
0112     return 0;
0113 }
0114 
0115 static int horus3a_leave_power_save(struct horus3a_priv *priv)
0116 {
0117     u8 data[2];
0118 
0119     dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
0120     if (priv->state == STATE_ACTIVE)
0121         return 0;
0122     /* Leave power save */
0123     data[0] = 0x00;
0124     /* LNA is Disabled */
0125     data[1] = 0xa7;
0126     /* 0x11 - 0x12 */
0127     horus3a_write_regs(priv, 0x11, data, sizeof(data));
0128     /* VCO buffer enable */
0129     horus3a_write_reg(priv, 0x2a, 0x79);
0130     /* VCO calibration enable */
0131     horus3a_write_reg(priv, 0x1c, 0xc0);
0132     /* MDIV_EN = 1 */
0133     horus3a_write_reg(priv, 0x29, 0x71);
0134     usleep_range(5000, 7000);
0135     priv->state = STATE_ACTIVE;
0136     return 0;
0137 }
0138 
0139 static int horus3a_init(struct dvb_frontend *fe)
0140 {
0141     struct horus3a_priv *priv = fe->tuner_priv;
0142 
0143     dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
0144     return 0;
0145 }
0146 
0147 static void horus3a_release(struct dvb_frontend *fe)
0148 {
0149     struct horus3a_priv *priv = fe->tuner_priv;
0150 
0151     dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
0152     kfree(fe->tuner_priv);
0153     fe->tuner_priv = NULL;
0154 }
0155 
0156 static int horus3a_sleep(struct dvb_frontend *fe)
0157 {
0158     struct horus3a_priv *priv = fe->tuner_priv;
0159 
0160     dev_dbg(&priv->i2c->dev, "%s()\n", __func__);
0161     horus3a_enter_power_save(priv);
0162     return 0;
0163 }
0164 
0165 static int horus3a_set_params(struct dvb_frontend *fe)
0166 {
0167     struct dtv_frontend_properties *p = &fe->dtv_property_cache;
0168     struct horus3a_priv *priv = fe->tuner_priv;
0169     u32 frequency = p->frequency;
0170     u32 symbol_rate = p->symbol_rate/1000;
0171     u8 mixdiv = 0;
0172     u8 mdiv = 0;
0173     u32 ms = 0;
0174     u8 f_ctl = 0;
0175     u8 g_ctl = 0;
0176     u8 fc_lpf = 0;
0177     u8 data[5];
0178 
0179     dev_dbg(&priv->i2c->dev, "%s(): frequency %dkHz symbol_rate %dksps\n",
0180         __func__, frequency, symbol_rate);
0181     if (priv->set_tuner)
0182         priv->set_tuner(priv->set_tuner_data, 0);
0183     if (priv->state == STATE_SLEEP)
0184         horus3a_leave_power_save(priv);
0185 
0186     /* frequency should be X MHz (X : integer) */
0187     frequency = DIV_ROUND_CLOSEST(frequency, 1000) * 1000;
0188     if (frequency <= 1155000) {
0189         mixdiv = 4;
0190         mdiv = 1;
0191     } else {
0192         mixdiv = 2;
0193         mdiv = 0;
0194     }
0195     /* Assumed that fREF == 1MHz (1000kHz) */
0196     ms = DIV_ROUND_CLOSEST((frequency * mixdiv) / 2, 1000);
0197     if (ms > 0x7FFF) { /* 15 bit */
0198         dev_err(&priv->i2c->dev, "horus3a: invalid frequency %d\n",
0199             frequency);
0200         return -EINVAL;
0201     }
0202     if (frequency < 975000) {
0203         /* F_CTL=11100 G_CTL=001 */
0204         f_ctl = 0x1C;
0205         g_ctl = 0x01;
0206     } else if (frequency < 1050000) {
0207         /* F_CTL=11000 G_CTL=010 */
0208         f_ctl = 0x18;
0209         g_ctl = 0x02;
0210     } else if (frequency < 1150000) {
0211         /* F_CTL=10100 G_CTL=010 */
0212         f_ctl = 0x14;
0213         g_ctl = 0x02;
0214     } else if (frequency < 1250000) {
0215         /* F_CTL=10000 G_CTL=011 */
0216         f_ctl = 0x10;
0217         g_ctl = 0x03;
0218     } else if (frequency < 1350000) {
0219         /* F_CTL=01100 G_CTL=100 */
0220         f_ctl = 0x0C;
0221         g_ctl = 0x04;
0222     } else if (frequency < 1450000) {
0223         /* F_CTL=01010 G_CTL=100 */
0224         f_ctl = 0x0A;
0225         g_ctl = 0x04;
0226     } else if (frequency < 1600000) {
0227         /* F_CTL=00111 G_CTL=101 */
0228         f_ctl = 0x07;
0229         g_ctl = 0x05;
0230     } else if (frequency < 1800000) {
0231         /* F_CTL=00100 G_CTL=010 */
0232         f_ctl = 0x04;
0233         g_ctl = 0x02;
0234     } else if (frequency < 2000000) {
0235         /* F_CTL=00010 G_CTL=001 */
0236         f_ctl = 0x02;
0237         g_ctl = 0x01;
0238     } else {
0239         /* F_CTL=00000 G_CTL=000 */
0240         f_ctl = 0x00;
0241         g_ctl = 0x00;
0242     }
0243     /* LPF cutoff frequency setting */
0244     if (p->delivery_system == SYS_DVBS) {
0245         /*
0246          * rolloff = 0.35
0247          * SR <= 4.3
0248          * fc_lpf = 5
0249          * 4.3 < SR <= 10
0250          * fc_lpf = SR * (1 + rolloff) / 2 + SR / 2 =
0251          *  SR * 1.175 = SR * (47/40)
0252          * 10 < SR
0253          * fc_lpf = SR * (1 + rolloff) / 2 + 5 =
0254          *  SR * 0.675 + 5 = SR * (27/40) + 5
0255          * NOTE: The result should be round up.
0256          */
0257         if (symbol_rate <= 4300)
0258             fc_lpf = 5;
0259         else if (symbol_rate <= 10000)
0260             fc_lpf = (u8)DIV_ROUND_UP(symbol_rate * 47, 40000);
0261         else
0262             fc_lpf = (u8)DIV_ROUND_UP(symbol_rate * 27, 40000) + 5;
0263         /* 5 <= fc_lpf <= 36 */
0264         if (fc_lpf > 36)
0265             fc_lpf = 36;
0266     } else if (p->delivery_system == SYS_DVBS2) {
0267         /*
0268          * SR <= 4.5:
0269          * fc_lpf = 5
0270          * 4.5 < SR <= 10:
0271          * fc_lpf = SR * (1 + rolloff) / 2 + SR / 2
0272          * 10 < SR:
0273          * fc_lpf = SR * (1 + rolloff) / 2 + 5
0274          * NOTE: The result should be round up.
0275          */
0276         if (symbol_rate <= 4500)
0277             fc_lpf = 5;
0278         else if (symbol_rate <= 10000)
0279             fc_lpf = (u8)((symbol_rate * 11 + (10000-1)) / 10000);
0280         else
0281             fc_lpf = (u8)((symbol_rate * 3 + (5000-1)) / 5000 + 5);
0282         /* 5 <= fc_lpf <= 36 is valid */
0283         if (fc_lpf > 36)
0284             fc_lpf = 36;
0285     } else {
0286         dev_err(&priv->i2c->dev,
0287             "horus3a: invalid delivery system %d\n",
0288             p->delivery_system);
0289         return -EINVAL;
0290     }
0291     /* 0x00 - 0x04 */
0292     data[0] = (u8)((ms >> 7) & 0xFF);
0293     data[1] = (u8)((ms << 1) & 0xFF);
0294     data[2] = 0x00;
0295     data[3] = 0x00;
0296     data[4] = (u8)(mdiv << 7);
0297     horus3a_write_regs(priv, 0x00, data, sizeof(data));
0298     /* Write G_CTL, F_CTL */
0299     horus3a_write_reg(priv, 0x09, (u8)((g_ctl << 5) | f_ctl));
0300     /* Write LPF cutoff frequency */
0301     horus3a_write_reg(priv, 0x37, (u8)(0x80 | (fc_lpf << 1)));
0302     /* Start Calibration */
0303     horus3a_write_reg(priv, 0x05, 0x80);
0304     /* IQ Generator enable */
0305     horus3a_write_reg(priv, 0x2a, 0x7b);
0306     /* tuner stabilization time */
0307     msleep(60);
0308     /* Store tuned frequency to the struct */
0309     priv->frequency = ms * 2 * 1000 / mixdiv;
0310     return 0;
0311 }
0312 
0313 static int horus3a_get_frequency(struct dvb_frontend *fe, u32 *frequency)
0314 {
0315     struct horus3a_priv *priv = fe->tuner_priv;
0316 
0317     *frequency = priv->frequency;
0318     return 0;
0319 }
0320 
0321 static const struct dvb_tuner_ops horus3a_tuner_ops = {
0322     .info = {
0323         .name = "Sony Horus3a",
0324         .frequency_min_hz  =  950 * MHz,
0325         .frequency_max_hz  = 2150 * MHz,
0326         .frequency_step_hz =    1 * MHz,
0327     },
0328     .init = horus3a_init,
0329     .release = horus3a_release,
0330     .sleep = horus3a_sleep,
0331     .set_params = horus3a_set_params,
0332     .get_frequency = horus3a_get_frequency,
0333 };
0334 
0335 struct dvb_frontend *horus3a_attach(struct dvb_frontend *fe,
0336                     const struct horus3a_config *config,
0337                     struct i2c_adapter *i2c)
0338 {
0339     u8 buf[3], val;
0340     struct horus3a_priv *priv = NULL;
0341 
0342     priv = kzalloc(sizeof(struct horus3a_priv), GFP_KERNEL);
0343     if (priv == NULL)
0344         return NULL;
0345     priv->i2c_address = (config->i2c_address >> 1);
0346     priv->i2c = i2c;
0347     priv->set_tuner_data = config->set_tuner_priv;
0348     priv->set_tuner = config->set_tuner_callback;
0349 
0350     if (fe->ops.i2c_gate_ctrl)
0351         fe->ops.i2c_gate_ctrl(fe, 1);
0352 
0353     /* wait 4ms after power on */
0354     usleep_range(4000, 6000);
0355     /* IQ Generator disable */
0356     horus3a_write_reg(priv, 0x2a, 0x79);
0357     /* REF_R = Xtal Frequency */
0358     buf[0] = config->xtal_freq_mhz;
0359     buf[1] = config->xtal_freq_mhz;
0360     buf[2] = 0;
0361     /* 0x6 - 0x8 */
0362     horus3a_write_regs(priv, 0x6, buf, 3);
0363     /* IQ Out = Single Ended */
0364     horus3a_write_reg(priv, 0x0a, 0x40);
0365     switch (config->xtal_freq_mhz) {
0366     case 27:
0367         val = 0x1f;
0368         break;
0369     case 24:
0370         val = 0x10;
0371         break;
0372     case 16:
0373         val = 0xc;
0374         break;
0375     default:
0376         val = 0;
0377         dev_warn(&priv->i2c->dev,
0378             "horus3a: invalid xtal frequency %dMHz\n",
0379             config->xtal_freq_mhz);
0380         break;
0381     }
0382     val <<= 2;
0383     horus3a_write_reg(priv, 0x0e, val);
0384     horus3a_enter_power_save(priv);
0385     usleep_range(3000, 5000);
0386 
0387     if (fe->ops.i2c_gate_ctrl)
0388         fe->ops.i2c_gate_ctrl(fe, 0);
0389 
0390     memcpy(&fe->ops.tuner_ops, &horus3a_tuner_ops,
0391                 sizeof(struct dvb_tuner_ops));
0392     fe->tuner_priv = priv;
0393     dev_info(&priv->i2c->dev,
0394         "Sony HORUS3A attached on addr=%x at I2C adapter %p\n",
0395         priv->i2c_address, priv->i2c);
0396     return fe;
0397 }
0398 EXPORT_SYMBOL(horus3a_attach);
0399 
0400 MODULE_DESCRIPTION("Sony HORUS3A satellite tuner driver");
0401 MODULE_AUTHOR("Sergey Kozlov <serjk@netup.ru>");
0402 MODULE_LICENSE("GPL");