1 /* 2 * Samsung s5h1432 DVB-T demodulator driver 3 * 4 * Copyright (C) 2009 Bill Liu <Bill.Liu@Conexant.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 */ 16 17 #include <linux/kernel.h> 18 #include <linux/init.h> 19 #include <linux/module.h> 20 #include <linux/string.h> 21 #include <linux/slab.h> 22 #include <linux/delay.h> 23 #include <media/dvb_frontend.h> 24 #include "s5h1432.h" 25 26 struct s5h1432_state { 27 28 struct i2c_adapter *i2c; 29 30 /* configuration settings */ 31 const struct s5h1432_config *config; 32 33 struct dvb_frontend frontend; 34 35 enum fe_modulation current_modulation; 36 unsigned int first_tune:1; 37 38 u32 current_frequency; 39 int if_freq; 40 41 u8 inversion; 42 }; 43 44 static int debug; 45 46 #define dprintk(arg...) do { \ 47 if (debug) \ 48 printk(arg); \ 49 } while (0) 50 51 static int s5h1432_writereg(struct s5h1432_state *state, 52 u8 addr, u8 reg, u8 data) 53 { 54 int ret; 55 u8 buf[] = { reg, data }; 56 57 struct i2c_msg msg = {.addr = addr, .flags = 0, .buf = buf, .len = 2 }; 58 59 ret = i2c_transfer(state->i2c, &msg, 1); 60 61 if (ret != 1) 62 printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, ret == %i)\n", 63 __func__, addr, reg, data, ret); 64 65 return (ret != 1) ? -1 : 0; 66 } 67 68 static u8 s5h1432_readreg(struct s5h1432_state *state, u8 addr, u8 reg) 69 { 70 int ret; 71 u8 b0[] = { reg }; 72 u8 b1[] = { 0 }; 73 74 struct i2c_msg msg[] = { 75 {.addr = addr, .flags = 0, .buf = b0, .len = 1}, 76 {.addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 1} 77 }; 78 79 ret = i2c_transfer(state->i2c, msg, 2); 80 81 if (ret != 2) 82 printk(KERN_ERR "%s: readreg error (ret == %i)\n", 83 __func__, ret); 84 return b1[0]; 85 } 86 87 static int s5h1432_sleep(struct dvb_frontend *fe) 88 { 89 return 0; 90 } 91 92 static int s5h1432_set_channel_bandwidth(struct dvb_frontend *fe, 93 u32 bandwidth) 94 { 95 struct s5h1432_state *state = fe->demodulator_priv; 96 97 u8 reg = 0; 98 99 /* Register [0x2E] bit 3:2 : 8MHz = 0; 7MHz = 1; 6MHz = 2 */ 100 reg = s5h1432_readreg(state, S5H1432_I2C_TOP_ADDR, 0x2E); 101 reg &= ~(0x0C); 102 switch (bandwidth) { 103 case 6: 104 reg |= 0x08; 105 break; 106 case 7: 107 reg |= 0x04; 108 break; 109 case 8: 110 reg |= 0x00; 111 break; 112 default: 113 return 0; 114 } 115 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x2E, reg); 116 return 1; 117 } 118 119 static int s5h1432_set_IF(struct dvb_frontend *fe, u32 ifFreqHz) 120 { 121 struct s5h1432_state *state = fe->demodulator_priv; 122 123 switch (ifFreqHz) { 124 case TAIWAN_HI_IF_FREQ_44_MHZ: 125 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x55); 126 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x55); 127 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0x15); 128 break; 129 case EUROPE_HI_IF_FREQ_36_MHZ: 130 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x00); 131 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x00); 132 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0x40); 133 break; 134 case IF_FREQ_6_MHZ: 135 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x00); 136 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x00); 137 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xe0); 138 break; 139 case IF_FREQ_3point3_MHZ: 140 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x66); 141 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x66); 142 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEE); 143 break; 144 case IF_FREQ_3point5_MHZ: 145 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x55); 146 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x55); 147 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xED); 148 break; 149 case IF_FREQ_4_MHZ: 150 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0xAA); 151 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0xAA); 152 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEA); 153 break; 154 default: 155 { 156 u32 value = 0; 157 value = (u32) (((48000 - (ifFreqHz / 1000)) * 512 * 158 (u32) 32768) / (48 * 1000)); 159 printk(KERN_INFO 160 "Default IFFreq %d :reg value = 0x%x\n", 161 ifFreqHz, value); 162 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 163 (u8) value & 0xFF); 164 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 165 (u8) (value >> 8) & 0xFF); 166 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 167 (u8) (value >> 16) & 0xFF); 168 break; 169 } 170 171 } 172 173 return 1; 174 } 175 176 /* Talk to the demod, set the FEC, GUARD, QAM settings etc */ 177 static int s5h1432_set_frontend(struct dvb_frontend *fe) 178 { 179 struct dtv_frontend_properties *p = &fe->dtv_property_cache; 180 u32 dvb_bandwidth = 8; 181 struct s5h1432_state *state = fe->demodulator_priv; 182 183 if (p->frequency == state->current_frequency) { 184 /*current_frequency = p->frequency; */ 185 /*state->current_frequency = p->frequency; */ 186 } else { 187 fe->ops.tuner_ops.set_params(fe); 188 msleep(300); 189 s5h1432_set_channel_bandwidth(fe, dvb_bandwidth); 190 switch (p->bandwidth_hz) { 191 case 6000000: 192 dvb_bandwidth = 6; 193 s5h1432_set_IF(fe, IF_FREQ_4_MHZ); 194 break; 195 case 7000000: 196 dvb_bandwidth = 7; 197 s5h1432_set_IF(fe, IF_FREQ_4_MHZ); 198 break; 199 case 8000000: 200 dvb_bandwidth = 8; 201 s5h1432_set_IF(fe, IF_FREQ_4_MHZ); 202 break; 203 default: 204 return 0; 205 } 206 /*fe->ops.tuner_ops.set_params(fe); */ 207 /*Soft Reset chip*/ 208 msleep(30); 209 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a); 210 msleep(30); 211 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b); 212 213 s5h1432_set_channel_bandwidth(fe, dvb_bandwidth); 214 switch (p->bandwidth_hz) { 215 case 6000000: 216 dvb_bandwidth = 6; 217 s5h1432_set_IF(fe, IF_FREQ_4_MHZ); 218 break; 219 case 7000000: 220 dvb_bandwidth = 7; 221 s5h1432_set_IF(fe, IF_FREQ_4_MHZ); 222 break; 223 case 8000000: 224 dvb_bandwidth = 8; 225 s5h1432_set_IF(fe, IF_FREQ_4_MHZ); 226 break; 227 default: 228 return 0; 229 } 230 /*fe->ops.tuner_ops.set_params(fe); */ 231 /*Soft Reset chip*/ 232 msleep(30); 233 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a); 234 msleep(30); 235 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b); 236 237 } 238 239 state->current_frequency = p->frequency; 240 241 return 0; 242 } 243 244 static int s5h1432_init(struct dvb_frontend *fe) 245 { 246 struct s5h1432_state *state = fe->demodulator_priv; 247 248 u8 reg = 0; 249 state->current_frequency = 0; 250 printk(KERN_INFO " s5h1432_init().\n"); 251 252 /*Set VSB mode as default, this also does a soft reset */ 253 /*Initialize registers */ 254 255 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x04, 0xa8); 256 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x05, 0x01); 257 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x07, 0x70); 258 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x19, 0x80); 259 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1b, 0x9D); 260 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1c, 0x30); 261 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1d, 0x20); 262 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1e, 0x1B); 263 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x2e, 0x40); 264 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x42, 0x84); 265 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x50, 0x5a); 266 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x5a, 0xd3); 267 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x68, 0x50); 268 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xb8, 0x3c); 269 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xc4, 0x10); 270 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xcc, 0x9c); 271 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xDA, 0x00); 272 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe1, 0x94); 273 /* s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xf4, 0xa1); */ 274 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xf9, 0x00); 275 276 /*For NXP tuner*/ 277 278 /*Set 3.3MHz as default IF frequency */ 279 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x66); 280 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x66); 281 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEE); 282 /* Set reg 0x1E to get the full dynamic range */ 283 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1e, 0x31); 284 285 /* Mode setting in demod */ 286 reg = s5h1432_readreg(state, S5H1432_I2C_TOP_ADDR, 0x42); 287 reg |= 0x80; 288 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x42, reg); 289 /* Serial mode */ 290 291 /* Soft Reset chip */ 292 293 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a); 294 msleep(30); 295 s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b); 296 297 298 return 0; 299 } 300 301 static int s5h1432_read_status(struct dvb_frontend *fe, enum fe_status *status) 302 { 303 return 0; 304 } 305 306 static int s5h1432_read_signal_strength(struct dvb_frontend *fe, 307 u16 *signal_strength) 308 { 309 return 0; 310 } 311 312 static int s5h1432_read_snr(struct dvb_frontend *fe, u16 *snr) 313 { 314 return 0; 315 } 316 317 static int s5h1432_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 318 { 319 320 return 0; 321 } 322 323 static int s5h1432_read_ber(struct dvb_frontend *fe, u32 *ber) 324 { 325 return 0; 326 } 327 328 static int s5h1432_get_tune_settings(struct dvb_frontend *fe, 329 struct dvb_frontend_tune_settings *tune) 330 { 331 return 0; 332 } 333 334 static void s5h1432_release(struct dvb_frontend *fe) 335 { 336 struct s5h1432_state *state = fe->demodulator_priv; 337 kfree(state); 338 } 339 340 static const struct dvb_frontend_ops s5h1432_ops; 341 342 struct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config, 343 struct i2c_adapter *i2c) 344 { 345 struct s5h1432_state *state = NULL; 346 347 printk(KERN_INFO " Enter s5h1432_attach(). attach success!\n"); 348 /* allocate memory for the internal state */ 349 state = kmalloc(sizeof(struct s5h1432_state), GFP_KERNEL); 350 if (!state) 351 return NULL; 352 353 /* setup the state */ 354 state->config = config; 355 state->i2c = i2c; 356 state->current_modulation = QAM_16; 357 state->inversion = state->config->inversion; 358 359 /* create dvb_frontend */ 360 memcpy(&state->frontend.ops, &s5h1432_ops, 361 sizeof(struct dvb_frontend_ops)); 362 363 state->frontend.demodulator_priv = state; 364 365 return &state->frontend; 366 } 367 EXPORT_SYMBOL(s5h1432_attach); 368 369 static const struct dvb_frontend_ops s5h1432_ops = { 370 .delsys = { SYS_DVBT }, 371 .info = { 372 .name = "Samsung s5h1432 DVB-T Frontend", 373 .frequency_min_hz = 177 * MHz, 374 .frequency_max_hz = 858 * MHz, 375 .frequency_stepsize_hz = 166666, 376 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 377 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 378 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | 379 FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | 380 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER}, 381 382 .init = s5h1432_init, 383 .sleep = s5h1432_sleep, 384 .set_frontend = s5h1432_set_frontend, 385 .get_tune_settings = s5h1432_get_tune_settings, 386 .read_status = s5h1432_read_status, 387 .read_ber = s5h1432_read_ber, 388 .read_signal_strength = s5h1432_read_signal_strength, 389 .read_snr = s5h1432_read_snr, 390 .read_ucblocks = s5h1432_read_ucblocks, 391 .release = s5h1432_release, 392 }; 393 394 module_param(debug, int, 0644); 395 MODULE_PARM_DESC(debug, "Enable verbose debug messages"); 396 397 MODULE_DESCRIPTION("Samsung s5h1432 DVB-T Demodulator driver"); 398 MODULE_AUTHOR("Bill Liu"); 399 MODULE_LICENSE("GPL"); 400