stb6000.c (4761B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 Driver for ST STB6000 DVBS Silicon tuner 4 5 Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by) 6 7 8 */ 9 10#include <linux/slab.h> 11#include <linux/module.h> 12#include <linux/dvb/frontend.h> 13#include <asm/types.h> 14 15#include "stb6000.h" 16 17static int debug; 18#define dprintk(args...) \ 19 do { \ 20 if (debug) \ 21 printk(KERN_DEBUG "stb6000: " args); \ 22 } while (0) 23 24struct stb6000_priv { 25 /* i2c details */ 26 int i2c_address; 27 struct i2c_adapter *i2c; 28 u32 frequency; 29}; 30 31static void stb6000_release(struct dvb_frontend *fe) 32{ 33 kfree(fe->tuner_priv); 34 fe->tuner_priv = NULL; 35} 36 37static int stb6000_sleep(struct dvb_frontend *fe) 38{ 39 struct stb6000_priv *priv = fe->tuner_priv; 40 int ret; 41 u8 buf[] = { 10, 0 }; 42 struct i2c_msg msg = { 43 .addr = priv->i2c_address, 44 .flags = 0, 45 .buf = buf, 46 .len = 2 47 }; 48 49 dprintk("%s:\n", __func__); 50 51 if (fe->ops.i2c_gate_ctrl) 52 fe->ops.i2c_gate_ctrl(fe, 1); 53 54 ret = i2c_transfer(priv->i2c, &msg, 1); 55 if (ret != 1) 56 dprintk("%s: i2c error\n", __func__); 57 58 if (fe->ops.i2c_gate_ctrl) 59 fe->ops.i2c_gate_ctrl(fe, 0); 60 61 return (ret == 1) ? 0 : ret; 62} 63 64static int stb6000_set_params(struct dvb_frontend *fe) 65{ 66 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 67 struct stb6000_priv *priv = fe->tuner_priv; 68 unsigned int n, m; 69 int ret; 70 u32 freq_mhz; 71 int bandwidth; 72 u8 buf[12]; 73 struct i2c_msg msg = { 74 .addr = priv->i2c_address, 75 .flags = 0, 76 .buf = buf, 77 .len = 12 78 }; 79 80 dprintk("%s:\n", __func__); 81 82 freq_mhz = p->frequency / 1000; 83 bandwidth = p->symbol_rate / 1000000; 84 85 if (bandwidth > 31) 86 bandwidth = 31; 87 88 if ((freq_mhz > 949) && (freq_mhz < 2151)) { 89 buf[0] = 0x01; 90 buf[1] = 0xac; 91 if (freq_mhz < 1950) 92 buf[1] = 0xaa; 93 if (freq_mhz < 1800) 94 buf[1] = 0xa8; 95 if (freq_mhz < 1650) 96 buf[1] = 0xa6; 97 if (freq_mhz < 1530) 98 buf[1] = 0xa5; 99 if (freq_mhz < 1470) 100 buf[1] = 0xa4; 101 if (freq_mhz < 1370) 102 buf[1] = 0xa2; 103 if (freq_mhz < 1300) 104 buf[1] = 0xa1; 105 if (freq_mhz < 1200) 106 buf[1] = 0xa0; 107 if (freq_mhz < 1075) 108 buf[1] = 0xbc; 109 if (freq_mhz < 1000) 110 buf[1] = 0xba; 111 if (freq_mhz < 1075) { 112 n = freq_mhz / 8; /* vco=lo*4 */ 113 m = 2; 114 } else { 115 n = freq_mhz / 16; /* vco=lo*2 */ 116 m = 1; 117 } 118 buf[2] = n >> 1; 119 buf[3] = (unsigned char)(((n & 1) << 7) | 120 (m * freq_mhz - n * 16) | 0x60); 121 buf[4] = 0x04; 122 buf[5] = 0x0e; 123 124 buf[6] = (unsigned char)(bandwidth); 125 126 buf[7] = 0xd8; 127 buf[8] = 0xd0; 128 buf[9] = 0x50; 129 buf[10] = 0xeb; 130 buf[11] = 0x4f; 131 132 if (fe->ops.i2c_gate_ctrl) 133 fe->ops.i2c_gate_ctrl(fe, 1); 134 135 ret = i2c_transfer(priv->i2c, &msg, 1); 136 if (ret != 1) 137 dprintk("%s: i2c error\n", __func__); 138 139 udelay(10); 140 if (fe->ops.i2c_gate_ctrl) 141 fe->ops.i2c_gate_ctrl(fe, 0); 142 143 buf[0] = 0x07; 144 buf[1] = 0xdf; 145 buf[2] = 0xd0; 146 buf[3] = 0x50; 147 buf[4] = 0xfb; 148 msg.len = 5; 149 150 if (fe->ops.i2c_gate_ctrl) 151 fe->ops.i2c_gate_ctrl(fe, 1); 152 153 ret = i2c_transfer(priv->i2c, &msg, 1); 154 if (ret != 1) 155 dprintk("%s: i2c error\n", __func__); 156 157 udelay(10); 158 if (fe->ops.i2c_gate_ctrl) 159 fe->ops.i2c_gate_ctrl(fe, 0); 160 161 priv->frequency = freq_mhz * 1000; 162 163 return (ret == 1) ? 0 : ret; 164 } 165 return -1; 166} 167 168static int stb6000_get_frequency(struct dvb_frontend *fe, u32 *frequency) 169{ 170 struct stb6000_priv *priv = fe->tuner_priv; 171 *frequency = priv->frequency; 172 return 0; 173} 174 175static const struct dvb_tuner_ops stb6000_tuner_ops = { 176 .info = { 177 .name = "ST STB6000", 178 .frequency_min_hz = 950 * MHz, 179 .frequency_max_hz = 2150 * MHz 180 }, 181 .release = stb6000_release, 182 .sleep = stb6000_sleep, 183 .set_params = stb6000_set_params, 184 .get_frequency = stb6000_get_frequency, 185}; 186 187struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr, 188 struct i2c_adapter *i2c) 189{ 190 struct stb6000_priv *priv = NULL; 191 u8 b0[] = { 0 }; 192 u8 b1[] = { 0, 0 }; 193 struct i2c_msg msg[2] = { 194 { 195 .addr = addr, 196 .flags = 0, 197 .buf = b0, 198 .len = 0 199 }, { 200 .addr = addr, 201 .flags = I2C_M_RD, 202 .buf = b1, 203 .len = 2 204 } 205 }; 206 int ret; 207 208 dprintk("%s:\n", __func__); 209 210 if (fe->ops.i2c_gate_ctrl) 211 fe->ops.i2c_gate_ctrl(fe, 1); 212 213 /* is some i2c device here ? */ 214 ret = i2c_transfer(i2c, msg, 2); 215 if (fe->ops.i2c_gate_ctrl) 216 fe->ops.i2c_gate_ctrl(fe, 0); 217 218 if (ret != 2) 219 return NULL; 220 221 priv = kzalloc(sizeof(struct stb6000_priv), GFP_KERNEL); 222 if (priv == NULL) 223 return NULL; 224 225 priv->i2c_address = addr; 226 priv->i2c = i2c; 227 228 memcpy(&fe->ops.tuner_ops, &stb6000_tuner_ops, 229 sizeof(struct dvb_tuner_ops)); 230 231 fe->tuner_priv = priv; 232 233 return fe; 234} 235EXPORT_SYMBOL(stb6000_attach); 236 237module_param(debug, int, 0644); 238MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); 239 240MODULE_DESCRIPTION("DVB STB6000 driver"); 241MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>"); 242MODULE_LICENSE("GPL");