0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #include <linux/kernel.h>
0019 #include <linux/module.h>
0020 #include <media/dvb_frontend.h>
0021 #include "qm1d1b0004.h"
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 #define QM1D1B0004_PSC_MASK (1 << 4)
0058
0059 #define QM1D1B0004_XTL_FREQ 4000
0060 #define QM1D1B0004_LPF_FALLBACK 30000
0061
0062 #if 0
0063 static const struct qm1d1b0004_config default_cfg = {
0064 .lpf_freq = QM1D1B0004_CFG_LPF_DFLT,
0065 .half_step = false,
0066 };
0067 #endif
0068
0069 struct qm1d1b0004_state {
0070 struct qm1d1b0004_config cfg;
0071 struct i2c_client *i2c;
0072 };
0073
0074
0075 struct qm1d1b0004_cb_map {
0076 u32 frequency;
0077 u8 cb;
0078 };
0079
0080 static const struct qm1d1b0004_cb_map cb_maps[] = {
0081 { 986000, 0xb2 },
0082 { 1072000, 0xd2 },
0083 { 1154000, 0xe2 },
0084 { 1291000, 0x20 },
0085 { 1447000, 0x40 },
0086 { 1615000, 0x60 },
0087 { 1791000, 0x80 },
0088 { 1972000, 0xa0 },
0089 };
0090
0091 static u8 lookup_cb(u32 frequency)
0092 {
0093 int i;
0094 const struct qm1d1b0004_cb_map *map;
0095
0096 for (i = 0; i < ARRAY_SIZE(cb_maps); i++) {
0097 map = &cb_maps[i];
0098 if (frequency < map->frequency)
0099 return map->cb;
0100 }
0101 return 0xc0;
0102 }
0103
0104 static int qm1d1b0004_set_params(struct dvb_frontend *fe)
0105 {
0106 struct qm1d1b0004_state *state;
0107 u32 frequency, pll, lpf_freq;
0108 u16 word;
0109 u8 buf[4], cb, lpf;
0110 int ret;
0111
0112 state = fe->tuner_priv;
0113 frequency = fe->dtv_property_cache.frequency;
0114
0115 pll = QM1D1B0004_XTL_FREQ / 4;
0116 if (state->cfg.half_step)
0117 pll /= 2;
0118 word = DIV_ROUND_CLOSEST(frequency, pll);
0119 cb = lookup_cb(frequency);
0120 if (cb & QM1D1B0004_PSC_MASK)
0121 word = (word << 1 & ~0x1f) | (word & 0x0f);
0122
0123
0124 buf[0] = 0x40 | word >> 8;
0125 buf[1] = word;
0126
0127 buf[2] = 0xe0 | state->cfg.half_step;
0128 buf[3] = cb;
0129 ret = i2c_master_send(state->i2c, buf, 4);
0130 if (ret < 0)
0131 return ret;
0132
0133
0134 buf[0] = 0xe4 | state->cfg.half_step;
0135 ret = i2c_master_send(state->i2c, buf, 1);
0136 if (ret < 0)
0137 return ret;
0138 msleep(20);
0139
0140
0141 lpf_freq = state->cfg.lpf_freq;
0142 if (lpf_freq == QM1D1B0004_CFG_LPF_DFLT)
0143 lpf_freq = fe->dtv_property_cache.symbol_rate / 1000;
0144 if (lpf_freq == 0)
0145 lpf_freq = QM1D1B0004_LPF_FALLBACK;
0146 lpf = DIV_ROUND_UP(lpf_freq, 2000) - 2;
0147 buf[0] = 0xe4 | ((lpf & 0x0c) << 1) | state->cfg.half_step;
0148 buf[1] = cb | ((lpf & 0x03) << 2);
0149 ret = i2c_master_send(state->i2c, buf, 2);
0150 if (ret < 0)
0151 return ret;
0152
0153
0154 buf[0] = 0;
0155 ret = i2c_master_recv(state->i2c, buf, 1);
0156 if (ret < 0)
0157 return ret;
0158 return 0;
0159 }
0160
0161
0162 static int qm1d1b0004_set_config(struct dvb_frontend *fe, void *priv_cfg)
0163 {
0164 struct qm1d1b0004_state *state;
0165
0166 state = fe->tuner_priv;
0167 memcpy(&state->cfg, priv_cfg, sizeof(state->cfg));
0168 return 0;
0169 }
0170
0171
0172 static int qm1d1b0004_init(struct dvb_frontend *fe)
0173 {
0174 struct qm1d1b0004_state *state;
0175 u8 buf[2] = {0xf8, 0x04};
0176
0177 state = fe->tuner_priv;
0178 if (state->cfg.half_step)
0179 buf[0] |= 0x01;
0180
0181 return i2c_master_send(state->i2c, buf, 2);
0182 }
0183
0184
0185 static const struct dvb_tuner_ops qm1d1b0004_ops = {
0186 .info = {
0187 .name = "Sharp qm1d1b0004",
0188
0189 .frequency_min_hz = 950 * MHz,
0190 .frequency_max_hz = 2150 * MHz,
0191 },
0192
0193 .init = qm1d1b0004_init,
0194
0195 .set_params = qm1d1b0004_set_params,
0196 .set_config = qm1d1b0004_set_config,
0197 };
0198
0199 static int
0200 qm1d1b0004_probe(struct i2c_client *client, const struct i2c_device_id *id)
0201 {
0202 struct dvb_frontend *fe;
0203 struct qm1d1b0004_config *cfg;
0204 struct qm1d1b0004_state *state;
0205 int ret;
0206
0207 cfg = client->dev.platform_data;
0208 fe = cfg->fe;
0209 i2c_set_clientdata(client, fe);
0210
0211 fe->tuner_priv = kzalloc(sizeof(struct qm1d1b0004_state), GFP_KERNEL);
0212 if (!fe->tuner_priv) {
0213 ret = -ENOMEM;
0214 goto err_mem;
0215 }
0216
0217 memcpy(&fe->ops.tuner_ops, &qm1d1b0004_ops, sizeof(fe->ops.tuner_ops));
0218
0219 state = fe->tuner_priv;
0220 state->i2c = client;
0221 ret = qm1d1b0004_set_config(fe, cfg);
0222 if (ret != 0)
0223 goto err_priv;
0224
0225 dev_info(&client->dev, "Sharp QM1D1B0004 attached.\n");
0226 return 0;
0227
0228 err_priv:
0229 kfree(fe->tuner_priv);
0230 err_mem:
0231 fe->tuner_priv = NULL;
0232 return ret;
0233 }
0234
0235 static int qm1d1b0004_remove(struct i2c_client *client)
0236 {
0237 struct dvb_frontend *fe;
0238
0239 fe = i2c_get_clientdata(client);
0240 kfree(fe->tuner_priv);
0241 fe->tuner_priv = NULL;
0242 return 0;
0243 }
0244
0245
0246 static const struct i2c_device_id qm1d1b0004_id[] = {
0247 {"qm1d1b0004", 0},
0248 {}
0249 };
0250
0251 MODULE_DEVICE_TABLE(i2c, qm1d1b0004_id);
0252
0253 static struct i2c_driver qm1d1b0004_driver = {
0254 .driver = {
0255 .name = "qm1d1b0004",
0256 },
0257 .probe = qm1d1b0004_probe,
0258 .remove = qm1d1b0004_remove,
0259 .id_table = qm1d1b0004_id,
0260 };
0261
0262 module_i2c_driver(qm1d1b0004_driver);
0263
0264 MODULE_DESCRIPTION("Sharp QM1D1B0004");
0265 MODULE_AUTHOR("Akihiro Tsukada");
0266 MODULE_LICENSE("GPL");