0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <linux/slab.h>
0020 #include <linux/module.h>
0021 #include <linux/dvb/frontend.h>
0022 #include <asm/types.h>
0023
0024 #include "tua6100.h"
0025
0026 struct tua6100_priv {
0027
0028 int i2c_address;
0029 struct i2c_adapter *i2c;
0030 u32 frequency;
0031 };
0032
0033 static void tua6100_release(struct dvb_frontend *fe)
0034 {
0035 kfree(fe->tuner_priv);
0036 fe->tuner_priv = NULL;
0037 }
0038
0039 static int tua6100_sleep(struct dvb_frontend *fe)
0040 {
0041 struct tua6100_priv *priv = fe->tuner_priv;
0042 int ret;
0043 u8 reg0[] = { 0x00, 0x00 };
0044 struct i2c_msg msg = { .addr = priv->i2c_address, .flags = 0, .buf = reg0, .len = 2 };
0045
0046 if (fe->ops.i2c_gate_ctrl)
0047 fe->ops.i2c_gate_ctrl(fe, 1);
0048 if ((ret = i2c_transfer (priv->i2c, &msg, 1)) != 1) {
0049 printk("%s: i2c error\n", __func__);
0050 }
0051 if (fe->ops.i2c_gate_ctrl)
0052 fe->ops.i2c_gate_ctrl(fe, 0);
0053
0054 return (ret == 1) ? 0 : ret;
0055 }
0056
0057 static int tua6100_set_params(struct dvb_frontend *fe)
0058 {
0059 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
0060 struct tua6100_priv *priv = fe->tuner_priv;
0061 u32 div;
0062 u32 prediv;
0063 u8 reg0[] = { 0x00, 0x00 };
0064 u8 reg1[] = { 0x01, 0x00, 0x00, 0x00 };
0065 u8 reg2[] = { 0x02, 0x00, 0x00 };
0066 struct i2c_msg msg0 = { .addr = priv->i2c_address, .flags = 0, .buf = reg0, .len = 2 };
0067 struct i2c_msg msg1 = { .addr = priv->i2c_address, .flags = 0, .buf = reg1, .len = 4 };
0068 struct i2c_msg msg2 = { .addr = priv->i2c_address, .flags = 0, .buf = reg2, .len = 3 };
0069
0070 #define _R_VAL 4
0071 #define _P_VAL 32
0072 #define _ri 4000000
0073
0074
0075 if (c->frequency < 2000000)
0076 reg0[1] = 0x03;
0077 else
0078 reg0[1] = 0x07;
0079
0080
0081 if (c->frequency < 1630000)
0082 reg1[1] = 0x2c;
0083 else
0084 reg1[1] = 0x0c;
0085
0086 if (_P_VAL == 64)
0087 reg1[1] |= 0x40;
0088 if (c->frequency >= 1525000)
0089 reg1[1] |= 0x80;
0090
0091
0092 reg2[1] = (_R_VAL >> 8) & 0x03;
0093 reg2[2] = _R_VAL;
0094 if (c->frequency < 1455000)
0095 reg2[1] |= 0x1c;
0096 else if (c->frequency < 1630000)
0097 reg2[1] |= 0x0c;
0098 else
0099 reg2[1] |= 0x1c;
0100
0101
0102
0103
0104
0105 prediv = (c->frequency * _R_VAL) / (_ri / 1000);
0106 div = prediv / _P_VAL;
0107 reg1[1] |= (div >> 9) & 0x03;
0108 reg1[2] = div >> 1;
0109 reg1[3] = (div << 7);
0110 priv->frequency = ((div * _P_VAL) * (_ri / 1000)) / _R_VAL;
0111
0112
0113 reg1[3] |= (prediv - (div*_P_VAL)) & 0x7f;
0114
0115 #undef _R_VAL
0116 #undef _P_VAL
0117 #undef _ri
0118
0119 if (fe->ops.i2c_gate_ctrl)
0120 fe->ops.i2c_gate_ctrl(fe, 1);
0121 if (i2c_transfer(priv->i2c, &msg0, 1) != 1)
0122 return -EIO;
0123
0124 if (fe->ops.i2c_gate_ctrl)
0125 fe->ops.i2c_gate_ctrl(fe, 1);
0126 if (i2c_transfer(priv->i2c, &msg2, 1) != 1)
0127 return -EIO;
0128
0129 if (fe->ops.i2c_gate_ctrl)
0130 fe->ops.i2c_gate_ctrl(fe, 1);
0131 if (i2c_transfer(priv->i2c, &msg1, 1) != 1)
0132 return -EIO;
0133
0134 if (fe->ops.i2c_gate_ctrl)
0135 fe->ops.i2c_gate_ctrl(fe, 0);
0136
0137 return 0;
0138 }
0139
0140 static int tua6100_get_frequency(struct dvb_frontend *fe, u32 *frequency)
0141 {
0142 struct tua6100_priv *priv = fe->tuner_priv;
0143 *frequency = priv->frequency;
0144 return 0;
0145 }
0146
0147 static const struct dvb_tuner_ops tua6100_tuner_ops = {
0148 .info = {
0149 .name = "Infineon TUA6100",
0150 .frequency_min_hz = 950 * MHz,
0151 .frequency_max_hz = 2150 * MHz,
0152 .frequency_step_hz = 1 * MHz,
0153 },
0154 .release = tua6100_release,
0155 .sleep = tua6100_sleep,
0156 .set_params = tua6100_set_params,
0157 .get_frequency = tua6100_get_frequency,
0158 };
0159
0160 struct dvb_frontend *tua6100_attach(struct dvb_frontend *fe, int addr, struct i2c_adapter *i2c)
0161 {
0162 struct tua6100_priv *priv = NULL;
0163 u8 b1 [] = { 0x80 };
0164 u8 b2 [] = { 0x00 };
0165 struct i2c_msg msg [] = { { .addr = addr, .flags = 0, .buf = b1, .len = 1 },
0166 { .addr = addr, .flags = I2C_M_RD, .buf = b2, .len = 1 } };
0167 int ret;
0168
0169 if (fe->ops.i2c_gate_ctrl)
0170 fe->ops.i2c_gate_ctrl(fe, 1);
0171 ret = i2c_transfer (i2c, msg, 2);
0172 if (fe->ops.i2c_gate_ctrl)
0173 fe->ops.i2c_gate_ctrl(fe, 0);
0174
0175 if (ret != 2)
0176 return NULL;
0177
0178 priv = kzalloc(sizeof(struct tua6100_priv), GFP_KERNEL);
0179 if (priv == NULL)
0180 return NULL;
0181
0182 priv->i2c_address = addr;
0183 priv->i2c = i2c;
0184
0185 memcpy(&fe->ops.tuner_ops, &tua6100_tuner_ops, sizeof(struct dvb_tuner_ops));
0186 fe->tuner_priv = priv;
0187 return fe;
0188 }
0189 EXPORT_SYMBOL(tua6100_attach);
0190
0191 MODULE_DESCRIPTION("DVB tua6100 driver");
0192 MODULE_AUTHOR("Andrew de Quincey");
0193 MODULE_LICENSE("GPL");