1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Sharp QM1D1B0004 satellite tuner 4 * 5 * Copyright (C) 2014 Akihiro Tsukada <tskd08@gmail.com> 6 * 7 * based on (former) drivers/media/pci/pt1/va1j5jf8007s.c. 8 */ 9 10 /* 11 * Note: 12 * Since the data-sheet of this tuner chip is not available, 13 * this driver lacks some tuner_ops and config options. 14 * In addition, the implementation might be dependent on the specific use 15 * in the FE module: VA1J5JF8007S and/or in the product: Earthsoft PT1/PT2. 16 */ 17 18 #include <linux/kernel.h> 19 #include <linux/module.h> 20 #include <media/dvb_frontend.h> 21 #include "qm1d1b0004.h" 22 23 /* 24 * Tuner I/F (copied from the former va1j5jf8007s.c) 25 * b[0] I2C addr 26 * b[1] "0":1, BG:2, divider_quotient[7:3]:5 27 * b[2] divider_quotient[2:0]:3, divider_remainder:5 28 * b[3] "111":3, LPF[3:2]:2, TM:1, "0":1, REF:1 29 * b[4] BANDX, PSC:1, LPF[1:0]:2, DIV:1, "0":1 30 * 31 * PLL frequency step := 32 * REF == 0 -> PLL XTL frequency(4MHz) / 8 33 * REF == 1 -> PLL XTL frequency(4MHz) / 4 34 * 35 * PreScaler := 36 * PSC == 0 -> x32 37 * PSC == 1 -> x16 38 * 39 * divider_quotient := (frequency / PLL frequency step) / PreScaler 40 * divider_remainder := (frequency / PLL frequency step) % PreScaler 41 * 42 * LPF := LPF Frequency / 1000 / 2 - 2 43 * LPF Frequency @ baudrate=28.86Mbps = 30000 44 * 45 * band (1..9) 46 * band 1 (freq < 986000) -> DIV:1, BANDX:5, PSC:1 47 * band 2 (freq < 1072000) -> DIV:1, BANDX:6, PSC:1 48 * band 3 (freq < 1154000) -> DIV:1, BANDX:7, PSC:0 49 * band 4 (freq < 1291000) -> DIV:0, BANDX:1, PSC:0 50 * band 5 (freq < 1447000) -> DIV:0, BANDX:2, PSC:0 51 * band 6 (freq < 1615000) -> DIV:0, BANDX:3, PSC:0 52 * band 7 (freq < 1791000) -> DIV:0, BANDX:4, PSC:0 53 * band 8 (freq < 1972000) -> DIV:0, BANDX:5, PSC:0 54 * band 9 (freq < 2150000) -> DIV:0, BANDX:6, PSC:0 55 */ 56 57 #define QM1D1B0004_PSC_MASK (1 << 4) 58 59 #define QM1D1B0004_XTL_FREQ 4000 60 #define QM1D1B0004_LPF_FALLBACK 30000 61 62 #if 0 /* Currently unused */ 63 static const struct qm1d1b0004_config default_cfg = { 64 .lpf_freq = QM1D1B0004_CFG_LPF_DFLT, 65 .half_step = false, 66 }; 67 #endif 68 69 struct qm1d1b0004_state { 70 struct qm1d1b0004_config cfg; 71 struct i2c_client *i2c; 72 }; 73 74 75 struct qm1d1b0004_cb_map { 76 u32 frequency; 77 u8 cb; 78 }; 79 80 static const struct qm1d1b0004_cb_map cb_maps[] = { 81 { 986000, 0xb2 }, 82 { 1072000, 0xd2 }, 83 { 1154000, 0xe2 }, 84 { 1291000, 0x20 }, 85 { 1447000, 0x40 }, 86 { 1615000, 0x60 }, 87 { 1791000, 0x80 }, 88 { 1972000, 0xa0 }, 89 }; 90 91 static u8 lookup_cb(u32 frequency) 92 { 93 int i; 94 const struct qm1d1b0004_cb_map *map; 95 96 for (i = 0; i < ARRAY_SIZE(cb_maps); i++) { 97 map = &cb_maps[i]; 98 if (frequency < map->frequency) 99 return map->cb; 100 } 101 return 0xc0; 102 } 103 104 static int qm1d1b0004_set_params(struct dvb_frontend *fe) 105 { 106 struct qm1d1b0004_state *state; 107 u32 frequency, pll, lpf_freq; 108 u16 word; 109 u8 buf[4], cb, lpf; 110 int ret; 111 112 state = fe->tuner_priv; 113 frequency = fe->dtv_property_cache.frequency; 114 115 pll = QM1D1B0004_XTL_FREQ / 4; 116 if (state->cfg.half_step) 117 pll /= 2; 118 word = DIV_ROUND_CLOSEST(frequency, pll); 119 cb = lookup_cb(frequency); 120 if (cb & QM1D1B0004_PSC_MASK) 121 word = (word << 1 & ~0x1f) | (word & 0x0f); 122 123 /* step.1: set frequency with BG:2, TM:0(4MHZ), LPF:4MHz */ 124 buf[0] = 0x40 | word >> 8; 125 buf[1] = word; 126 /* inconsisnten with the above I/F doc. maybe the doc is wrong */ 127 buf[2] = 0xe0 | state->cfg.half_step; 128 buf[3] = cb; 129 ret = i2c_master_send(state->i2c, buf, 4); 130 if (ret < 0) 131 return ret; 132 133 /* step.2: set TM:1 */ 134 buf[0] = 0xe4 | state->cfg.half_step; 135 ret = i2c_master_send(state->i2c, buf, 1); 136 if (ret < 0) 137 return ret; 138 msleep(20); 139 140 /* step.3: set LPF */ 141 lpf_freq = state->cfg.lpf_freq; 142 if (lpf_freq == QM1D1B0004_CFG_LPF_DFLT) 143 lpf_freq = fe->dtv_property_cache.symbol_rate / 1000; 144 if (lpf_freq == 0) 145 lpf_freq = QM1D1B0004_LPF_FALLBACK; 146 lpf = DIV_ROUND_UP(lpf_freq, 2000) - 2; 147 buf[0] = 0xe4 | ((lpf & 0x0c) << 1) | state->cfg.half_step; 148 buf[1] = cb | ((lpf & 0x03) << 2); 149 ret = i2c_master_send(state->i2c, buf, 2); 150 if (ret < 0) 151 return ret; 152 153 /* step.4: read PLL lock? */ 154 buf[0] = 0; 155 ret = i2c_master_recv(state->i2c, buf, 1); 156 if (ret < 0) 157 return ret; 158 return 0; 159 } 160 161 162 static int qm1d1b0004_set_config(struct dvb_frontend *fe, void *priv_cfg) 163 { 164 struct qm1d1b0004_state *state; 165 166 state = fe->tuner_priv; 167 memcpy(&state->cfg, priv_cfg, sizeof(state->cfg)); 168 return 0; 169 } 170 171 172 static int qm1d1b0004_init(struct dvb_frontend *fe) 173 { 174 struct qm1d1b0004_state *state; 175 u8 buf[2] = {0xf8, 0x04}; 176 177 state = fe->tuner_priv; 178 if (state->cfg.half_step) 179 buf[0] |= 0x01; 180 181 return i2c_master_send(state->i2c, buf, 2); 182 } 183 184 185 static const struct dvb_tuner_ops qm1d1b0004_ops = { 186 .info = { 187 .name = "Sharp qm1d1b0004", 188 189 .frequency_min_hz = 950 * MHz, 190 .frequency_max_hz = 2150 * MHz, 191 }, 192 193 .init = qm1d1b0004_init, 194 195 .set_params = qm1d1b0004_set_params, 196 .set_config = qm1d1b0004_set_config, 197 }; 198 199 static int 200 qm1d1b0004_probe(struct i2c_client *client, const struct i2c_device_id *id) 201 { 202 struct dvb_frontend *fe; 203 struct qm1d1b0004_config *cfg; 204 struct qm1d1b0004_state *state; 205 int ret; 206 207 cfg = client->dev.platform_data; 208 fe = cfg->fe; 209 i2c_set_clientdata(client, fe); 210 211 fe->tuner_priv = kzalloc(sizeof(struct qm1d1b0004_state), GFP_KERNEL); 212 if (!fe->tuner_priv) { 213 ret = -ENOMEM; 214 goto err_mem; 215 } 216 217 memcpy(&fe->ops.tuner_ops, &qm1d1b0004_ops, sizeof(fe->ops.tuner_ops)); 218 219 state = fe->tuner_priv; 220 state->i2c = client; 221 ret = qm1d1b0004_set_config(fe, cfg); 222 if (ret != 0) 223 goto err_priv; 224 225 dev_info(&client->dev, "Sharp QM1D1B0004 attached.\n"); 226 return 0; 227 228 err_priv: 229 kfree(fe->tuner_priv); 230 err_mem: 231 fe->tuner_priv = NULL; 232 return ret; 233 } 234 235 static int qm1d1b0004_remove(struct i2c_client *client) 236 { 237 struct dvb_frontend *fe; 238 239 fe = i2c_get_clientdata(client); 240 kfree(fe->tuner_priv); 241 fe->tuner_priv = NULL; 242 return 0; 243 } 244 245 246 static const struct i2c_device_id qm1d1b0004_id[] = { 247 {"qm1d1b0004", 0}, 248 {} 249 }; 250 251 MODULE_DEVICE_TABLE(i2c, qm1d1b0004_id); 252 253 static struct i2c_driver qm1d1b0004_driver = { 254 .driver = { 255 .name = "qm1d1b0004", 256 }, 257 .probe = qm1d1b0004_probe, 258 .remove = qm1d1b0004_remove, 259 .id_table = qm1d1b0004_id, 260 }; 261 262 module_i2c_driver(qm1d1b0004_driver); 263 264 MODULE_DESCRIPTION("Sharp QM1D1B0004"); 265 MODULE_AUTHOR("Akihiro Tsukada"); 266 MODULE_LICENSE("GPL"); 267