zl10039.c (6645B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Driver for Zarlink ZL10039 DVB-S tuner 4 * 5 * Copyright 2007 Jan D. Louw <jd.louw@mweb.co.za> 6 */ 7 8#include <linux/module.h> 9#include <linux/init.h> 10#include <linux/string.h> 11#include <linux/slab.h> 12#include <linux/dvb/frontend.h> 13 14#include <media/dvb_frontend.h> 15#include "zl10039.h" 16 17static int debug; 18 19/* Max transfer size done by I2C transfer functions */ 20#define MAX_XFER_SIZE 64 21 22#define dprintk(args...) \ 23 do { \ 24 if (debug) \ 25 printk(KERN_DEBUG args); \ 26 } while (0) 27 28enum zl10039_model_id { 29 ID_ZL10039 = 1 30}; 31 32struct zl10039_state { 33 struct i2c_adapter *i2c; 34 u8 i2c_addr; 35 u8 id; 36}; 37 38enum zl10039_reg_addr { 39 PLL0 = 0, 40 PLL1, 41 PLL2, 42 PLL3, 43 RFFE, 44 BASE0, 45 BASE1, 46 BASE2, 47 LO0, 48 LO1, 49 LO2, 50 LO3, 51 LO4, 52 LO5, 53 LO6, 54 GENERAL 55}; 56 57static int zl10039_read(const struct zl10039_state *state, 58 const enum zl10039_reg_addr reg, u8 *buf, 59 const size_t count) 60{ 61 u8 regbuf[] = { reg }; 62 struct i2c_msg msg[] = { 63 {/* Write register address */ 64 .addr = state->i2c_addr, 65 .flags = 0, 66 .buf = regbuf, 67 .len = 1, 68 }, {/* Read count bytes */ 69 .addr = state->i2c_addr, 70 .flags = I2C_M_RD, 71 .buf = buf, 72 .len = count, 73 }, 74 }; 75 76 dprintk("%s\n", __func__); 77 78 if (i2c_transfer(state->i2c, msg, 2) != 2) { 79 dprintk("%s: i2c read error\n", __func__); 80 return -EREMOTEIO; 81 } 82 83 return 0; /* Success */ 84} 85 86static int zl10039_write(struct zl10039_state *state, 87 const enum zl10039_reg_addr reg, const u8 *src, 88 const size_t count) 89{ 90 u8 buf[MAX_XFER_SIZE]; 91 struct i2c_msg msg = { 92 .addr = state->i2c_addr, 93 .flags = 0, 94 .buf = buf, 95 .len = count + 1, 96 }; 97 98 if (1 + count > sizeof(buf)) { 99 printk(KERN_WARNING 100 "%s: i2c wr reg=%04x: len=%zu is too big!\n", 101 KBUILD_MODNAME, reg, count); 102 return -EINVAL; 103 } 104 105 dprintk("%s\n", __func__); 106 /* Write register address and data in one go */ 107 buf[0] = reg; 108 memcpy(&buf[1], src, count); 109 if (i2c_transfer(state->i2c, &msg, 1) != 1) { 110 dprintk("%s: i2c write error\n", __func__); 111 return -EREMOTEIO; 112 } 113 114 return 0; /* Success */ 115} 116 117static inline int zl10039_readreg(struct zl10039_state *state, 118 const enum zl10039_reg_addr reg, u8 *val) 119{ 120 return zl10039_read(state, reg, val, 1); 121} 122 123static inline int zl10039_writereg(struct zl10039_state *state, 124 const enum zl10039_reg_addr reg, 125 const u8 val) 126{ 127 const u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */ 128 129 return zl10039_write(state, reg, &tmp, 1); 130} 131 132static int zl10039_init(struct dvb_frontend *fe) 133{ 134 struct zl10039_state *state = fe->tuner_priv; 135 int ret; 136 137 dprintk("%s\n", __func__); 138 if (fe->ops.i2c_gate_ctrl) 139 fe->ops.i2c_gate_ctrl(fe, 1); 140 /* Reset logic */ 141 ret = zl10039_writereg(state, GENERAL, 0x40); 142 if (ret < 0) { 143 dprintk("Note: i2c write error normal when resetting the tuner\n"); 144 } 145 /* Wake up */ 146 ret = zl10039_writereg(state, GENERAL, 0x01); 147 if (ret < 0) { 148 dprintk("Tuner power up failed\n"); 149 return ret; 150 } 151 if (fe->ops.i2c_gate_ctrl) 152 fe->ops.i2c_gate_ctrl(fe, 0); 153 154 return 0; 155} 156 157static int zl10039_sleep(struct dvb_frontend *fe) 158{ 159 struct zl10039_state *state = fe->tuner_priv; 160 int ret; 161 162 dprintk("%s\n", __func__); 163 if (fe->ops.i2c_gate_ctrl) 164 fe->ops.i2c_gate_ctrl(fe, 1); 165 ret = zl10039_writereg(state, GENERAL, 0x80); 166 if (ret < 0) { 167 dprintk("Tuner sleep failed\n"); 168 return ret; 169 } 170 if (fe->ops.i2c_gate_ctrl) 171 fe->ops.i2c_gate_ctrl(fe, 0); 172 173 return 0; 174} 175 176static int zl10039_set_params(struct dvb_frontend *fe) 177{ 178 struct dtv_frontend_properties *c = &fe->dtv_property_cache; 179 struct zl10039_state *state = fe->tuner_priv; 180 u8 buf[6]; 181 u8 bf; 182 u32 fbw; 183 u32 div; 184 int ret; 185 186 dprintk("%s\n", __func__); 187 dprintk("Set frequency = %d, symbol rate = %d\n", 188 c->frequency, c->symbol_rate); 189 190 /* Assumed 10.111 MHz crystal oscillator */ 191 /* Cancelled num/den 80 to prevent overflow */ 192 div = (c->frequency * 1000) / 126387; 193 fbw = (c->symbol_rate * 27) / 32000; 194 /* Cancelled num/den 10 to prevent overflow */ 195 bf = ((fbw * 5088) / 1011100) - 1; 196 197 /*PLL divider*/ 198 buf[0] = (div >> 8) & 0x7f; 199 buf[1] = (div >> 0) & 0xff; 200 /*Reference divider*/ 201 /* Select reference ratio of 80 */ 202 buf[2] = 0x1D; 203 /*PLL test modes*/ 204 buf[3] = 0x40; 205 /*RF Control register*/ 206 buf[4] = 0x6E; /* Bypass enable */ 207 /*Baseband filter cutoff */ 208 buf[5] = bf; 209 210 /* Open i2c gate */ 211 if (fe->ops.i2c_gate_ctrl) 212 fe->ops.i2c_gate_ctrl(fe, 1); 213 /* BR = 10, Enable filter adjustment */ 214 ret = zl10039_writereg(state, BASE1, 0x0A); 215 if (ret < 0) 216 goto error; 217 /* Write new config values */ 218 ret = zl10039_write(state, PLL0, buf, sizeof(buf)); 219 if (ret < 0) 220 goto error; 221 /* BR = 10, Disable filter adjustment */ 222 ret = zl10039_writereg(state, BASE1, 0x6A); 223 if (ret < 0) 224 goto error; 225 226 /* Close i2c gate */ 227 if (fe->ops.i2c_gate_ctrl) 228 fe->ops.i2c_gate_ctrl(fe, 0); 229 return 0; 230error: 231 dprintk("Error setting tuner\n"); 232 return ret; 233} 234 235static void zl10039_release(struct dvb_frontend *fe) 236{ 237 struct zl10039_state *state = fe->tuner_priv; 238 239 dprintk("%s\n", __func__); 240 kfree(state); 241 fe->tuner_priv = NULL; 242} 243 244static const struct dvb_tuner_ops zl10039_ops = { 245 .release = zl10039_release, 246 .init = zl10039_init, 247 .sleep = zl10039_sleep, 248 .set_params = zl10039_set_params, 249}; 250 251struct dvb_frontend *zl10039_attach(struct dvb_frontend *fe, 252 u8 i2c_addr, struct i2c_adapter *i2c) 253{ 254 struct zl10039_state *state = NULL; 255 256 dprintk("%s\n", __func__); 257 state = kmalloc(sizeof(struct zl10039_state), GFP_KERNEL); 258 if (state == NULL) 259 goto error; 260 261 state->i2c = i2c; 262 state->i2c_addr = i2c_addr; 263 264 /* Open i2c gate */ 265 if (fe->ops.i2c_gate_ctrl) 266 fe->ops.i2c_gate_ctrl(fe, 1); 267 /* check if this is a valid tuner */ 268 if (zl10039_readreg(state, GENERAL, &state->id) < 0) { 269 /* Close i2c gate */ 270 if (fe->ops.i2c_gate_ctrl) 271 fe->ops.i2c_gate_ctrl(fe, 0); 272 goto error; 273 } 274 /* Close i2c gate */ 275 if (fe->ops.i2c_gate_ctrl) 276 fe->ops.i2c_gate_ctrl(fe, 0); 277 278 state->id = state->id & 0x0f; 279 switch (state->id) { 280 case ID_ZL10039: 281 strscpy(fe->ops.tuner_ops.info.name, 282 "Zarlink ZL10039 DVB-S tuner", 283 sizeof(fe->ops.tuner_ops.info.name)); 284 break; 285 default: 286 dprintk("Chip ID=%x does not match a known type\n", state->id); 287 goto error; 288 } 289 290 memcpy(&fe->ops.tuner_ops, &zl10039_ops, sizeof(struct dvb_tuner_ops)); 291 fe->tuner_priv = state; 292 dprintk("Tuner attached @ i2c address 0x%02x\n", i2c_addr); 293 return fe; 294error: 295 kfree(state); 296 return NULL; 297} 298EXPORT_SYMBOL(zl10039_attach); 299 300module_param(debug, int, 0644); 301MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); 302MODULE_DESCRIPTION("Zarlink ZL10039 DVB-S tuner driver"); 303MODULE_AUTHOR("Jan D. Louw <jd.louw@mweb.co.za>"); 304MODULE_LICENSE("GPL");