18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Samsung s5h1432 DVB-T demodulator driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2009 Bill Liu <Bill.Liu@Conexant.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/kernel.h> 98c2ecf20Sopenharmony_ci#include <linux/init.h> 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/string.h> 128c2ecf20Sopenharmony_ci#include <linux/slab.h> 138c2ecf20Sopenharmony_ci#include <linux/delay.h> 148c2ecf20Sopenharmony_ci#include <media/dvb_frontend.h> 158c2ecf20Sopenharmony_ci#include "s5h1432.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistruct s5h1432_state { 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci struct i2c_adapter *i2c; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci /* configuration settings */ 228c2ecf20Sopenharmony_ci const struct s5h1432_config *config; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci struct dvb_frontend frontend; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci enum fe_modulation current_modulation; 278c2ecf20Sopenharmony_ci unsigned int first_tune:1; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci u32 current_frequency; 308c2ecf20Sopenharmony_ci int if_freq; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci u8 inversion; 338c2ecf20Sopenharmony_ci}; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic int debug; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci#define dprintk(arg...) do { \ 388c2ecf20Sopenharmony_ci if (debug) \ 398c2ecf20Sopenharmony_ci printk(arg); \ 408c2ecf20Sopenharmony_ci } while (0) 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic int s5h1432_writereg(struct s5h1432_state *state, 438c2ecf20Sopenharmony_ci u8 addr, u8 reg, u8 data) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci int ret; 468c2ecf20Sopenharmony_ci u8 buf[] = { reg, data }; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci struct i2c_msg msg = {.addr = addr, .flags = 0, .buf = buf, .len = 2 }; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci ret = i2c_transfer(state->i2c, &msg, 1); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci if (ret != 1) 538c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: writereg error 0x%02x 0x%02x 0x%04x, ret == %i)\n", 548c2ecf20Sopenharmony_ci __func__, addr, reg, data, ret); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci return (ret != 1) ? -1 : 0; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic u8 s5h1432_readreg(struct s5h1432_state *state, u8 addr, u8 reg) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci int ret; 628c2ecf20Sopenharmony_ci u8 b0[] = { reg }; 638c2ecf20Sopenharmony_ci u8 b1[] = { 0 }; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci struct i2c_msg msg[] = { 668c2ecf20Sopenharmony_ci {.addr = addr, .flags = 0, .buf = b0, .len = 1}, 678c2ecf20Sopenharmony_ci {.addr = addr, .flags = I2C_M_RD, .buf = b1, .len = 1} 688c2ecf20Sopenharmony_ci }; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci ret = i2c_transfer(state->i2c, msg, 2); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci if (ret != 2) 738c2ecf20Sopenharmony_ci printk(KERN_ERR "%s: readreg error (ret == %i)\n", 748c2ecf20Sopenharmony_ci __func__, ret); 758c2ecf20Sopenharmony_ci return b1[0]; 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic int s5h1432_sleep(struct dvb_frontend *fe) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci return 0; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic int s5h1432_set_channel_bandwidth(struct dvb_frontend *fe, 848c2ecf20Sopenharmony_ci u32 bandwidth) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci struct s5h1432_state *state = fe->demodulator_priv; 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci u8 reg = 0; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci /* Register [0x2E] bit 3:2 : 8MHz = 0; 7MHz = 1; 6MHz = 2 */ 918c2ecf20Sopenharmony_ci reg = s5h1432_readreg(state, S5H1432_I2C_TOP_ADDR, 0x2E); 928c2ecf20Sopenharmony_ci reg &= ~(0x0C); 938c2ecf20Sopenharmony_ci switch (bandwidth) { 948c2ecf20Sopenharmony_ci case 6: 958c2ecf20Sopenharmony_ci reg |= 0x08; 968c2ecf20Sopenharmony_ci break; 978c2ecf20Sopenharmony_ci case 7: 988c2ecf20Sopenharmony_ci reg |= 0x04; 998c2ecf20Sopenharmony_ci break; 1008c2ecf20Sopenharmony_ci case 8: 1018c2ecf20Sopenharmony_ci reg |= 0x00; 1028c2ecf20Sopenharmony_ci break; 1038c2ecf20Sopenharmony_ci default: 1048c2ecf20Sopenharmony_ci return 0; 1058c2ecf20Sopenharmony_ci } 1068c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x2E, reg); 1078c2ecf20Sopenharmony_ci return 1; 1088c2ecf20Sopenharmony_ci} 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic int s5h1432_set_IF(struct dvb_frontend *fe, u32 ifFreqHz) 1118c2ecf20Sopenharmony_ci{ 1128c2ecf20Sopenharmony_ci struct s5h1432_state *state = fe->demodulator_priv; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci switch (ifFreqHz) { 1158c2ecf20Sopenharmony_ci case TAIWAN_HI_IF_FREQ_44_MHZ: 1168c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x55); 1178c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x55); 1188c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0x15); 1198c2ecf20Sopenharmony_ci break; 1208c2ecf20Sopenharmony_ci case EUROPE_HI_IF_FREQ_36_MHZ: 1218c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x00); 1228c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x00); 1238c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0x40); 1248c2ecf20Sopenharmony_ci break; 1258c2ecf20Sopenharmony_ci case IF_FREQ_6_MHZ: 1268c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x00); 1278c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x00); 1288c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xe0); 1298c2ecf20Sopenharmony_ci break; 1308c2ecf20Sopenharmony_ci case IF_FREQ_3point3_MHZ: 1318c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x66); 1328c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x66); 1338c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEE); 1348c2ecf20Sopenharmony_ci break; 1358c2ecf20Sopenharmony_ci case IF_FREQ_3point5_MHZ: 1368c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x55); 1378c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x55); 1388c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xED); 1398c2ecf20Sopenharmony_ci break; 1408c2ecf20Sopenharmony_ci case IF_FREQ_4_MHZ: 1418c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0xAA); 1428c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0xAA); 1438c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEA); 1448c2ecf20Sopenharmony_ci break; 1458c2ecf20Sopenharmony_ci default: 1468c2ecf20Sopenharmony_ci { 1478c2ecf20Sopenharmony_ci u32 value = 0; 1488c2ecf20Sopenharmony_ci value = (u32) (((48000 - (ifFreqHz / 1000)) * 512 * 1498c2ecf20Sopenharmony_ci (u32) 32768) / (48 * 1000)); 1508c2ecf20Sopenharmony_ci printk(KERN_INFO 1518c2ecf20Sopenharmony_ci "Default IFFreq %d :reg value = 0x%x\n", 1528c2ecf20Sopenharmony_ci ifFreqHz, value); 1538c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 1548c2ecf20Sopenharmony_ci (u8) value & 0xFF); 1558c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 1568c2ecf20Sopenharmony_ci (u8) (value >> 8) & 0xFF); 1578c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 1588c2ecf20Sopenharmony_ci (u8) (value >> 16) & 0xFF); 1598c2ecf20Sopenharmony_ci break; 1608c2ecf20Sopenharmony_ci } 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci return 1; 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci/* Talk to the demod, set the FEC, GUARD, QAM settings etc */ 1688c2ecf20Sopenharmony_cistatic int s5h1432_set_frontend(struct dvb_frontend *fe) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 1718c2ecf20Sopenharmony_ci u32 dvb_bandwidth = 8; 1728c2ecf20Sopenharmony_ci struct s5h1432_state *state = fe->demodulator_priv; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci if (p->frequency == state->current_frequency) { 1758c2ecf20Sopenharmony_ci /*current_frequency = p->frequency; */ 1768c2ecf20Sopenharmony_ci /*state->current_frequency = p->frequency; */ 1778c2ecf20Sopenharmony_ci } else { 1788c2ecf20Sopenharmony_ci fe->ops.tuner_ops.set_params(fe); 1798c2ecf20Sopenharmony_ci msleep(300); 1808c2ecf20Sopenharmony_ci s5h1432_set_channel_bandwidth(fe, dvb_bandwidth); 1818c2ecf20Sopenharmony_ci switch (p->bandwidth_hz) { 1828c2ecf20Sopenharmony_ci case 6000000: 1838c2ecf20Sopenharmony_ci dvb_bandwidth = 6; 1848c2ecf20Sopenharmony_ci s5h1432_set_IF(fe, IF_FREQ_4_MHZ); 1858c2ecf20Sopenharmony_ci break; 1868c2ecf20Sopenharmony_ci case 7000000: 1878c2ecf20Sopenharmony_ci dvb_bandwidth = 7; 1888c2ecf20Sopenharmony_ci s5h1432_set_IF(fe, IF_FREQ_4_MHZ); 1898c2ecf20Sopenharmony_ci break; 1908c2ecf20Sopenharmony_ci case 8000000: 1918c2ecf20Sopenharmony_ci dvb_bandwidth = 8; 1928c2ecf20Sopenharmony_ci s5h1432_set_IF(fe, IF_FREQ_4_MHZ); 1938c2ecf20Sopenharmony_ci break; 1948c2ecf20Sopenharmony_ci default: 1958c2ecf20Sopenharmony_ci return 0; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci /*fe->ops.tuner_ops.set_params(fe); */ 1988c2ecf20Sopenharmony_ci/*Soft Reset chip*/ 1998c2ecf20Sopenharmony_ci msleep(30); 2008c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a); 2018c2ecf20Sopenharmony_ci msleep(30); 2028c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci s5h1432_set_channel_bandwidth(fe, dvb_bandwidth); 2058c2ecf20Sopenharmony_ci switch (p->bandwidth_hz) { 2068c2ecf20Sopenharmony_ci case 6000000: 2078c2ecf20Sopenharmony_ci dvb_bandwidth = 6; 2088c2ecf20Sopenharmony_ci s5h1432_set_IF(fe, IF_FREQ_4_MHZ); 2098c2ecf20Sopenharmony_ci break; 2108c2ecf20Sopenharmony_ci case 7000000: 2118c2ecf20Sopenharmony_ci dvb_bandwidth = 7; 2128c2ecf20Sopenharmony_ci s5h1432_set_IF(fe, IF_FREQ_4_MHZ); 2138c2ecf20Sopenharmony_ci break; 2148c2ecf20Sopenharmony_ci case 8000000: 2158c2ecf20Sopenharmony_ci dvb_bandwidth = 8; 2168c2ecf20Sopenharmony_ci s5h1432_set_IF(fe, IF_FREQ_4_MHZ); 2178c2ecf20Sopenharmony_ci break; 2188c2ecf20Sopenharmony_ci default: 2198c2ecf20Sopenharmony_ci return 0; 2208c2ecf20Sopenharmony_ci } 2218c2ecf20Sopenharmony_ci /*fe->ops.tuner_ops.set_params(fe); */ 2228c2ecf20Sopenharmony_ci /*Soft Reset chip*/ 2238c2ecf20Sopenharmony_ci msleep(30); 2248c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a); 2258c2ecf20Sopenharmony_ci msleep(30); 2268c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b); 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci } 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci state->current_frequency = p->frequency; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci return 0; 2338c2ecf20Sopenharmony_ci} 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cistatic int s5h1432_init(struct dvb_frontend *fe) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci struct s5h1432_state *state = fe->demodulator_priv; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci u8 reg = 0; 2408c2ecf20Sopenharmony_ci state->current_frequency = 0; 2418c2ecf20Sopenharmony_ci printk(KERN_INFO " s5h1432_init().\n"); 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci /*Set VSB mode as default, this also does a soft reset */ 2448c2ecf20Sopenharmony_ci /*Initialize registers */ 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x04, 0xa8); 2478c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x05, 0x01); 2488c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x07, 0x70); 2498c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x19, 0x80); 2508c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1b, 0x9D); 2518c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1c, 0x30); 2528c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1d, 0x20); 2538c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1e, 0x1B); 2548c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x2e, 0x40); 2558c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x42, 0x84); 2568c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x50, 0x5a); 2578c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x5a, 0xd3); 2588c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x68, 0x50); 2598c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xb8, 0x3c); 2608c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xc4, 0x10); 2618c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xcc, 0x9c); 2628c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xDA, 0x00); 2638c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe1, 0x94); 2648c2ecf20Sopenharmony_ci /* s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xf4, 0xa1); */ 2658c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xf9, 0x00); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /*For NXP tuner*/ 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci /*Set 3.3MHz as default IF frequency */ 2708c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe4, 0x66); 2718c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe5, 0x66); 2728c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0xe7, 0xEE); 2738c2ecf20Sopenharmony_ci /* Set reg 0x1E to get the full dynamic range */ 2748c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x1e, 0x31); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci /* Mode setting in demod */ 2778c2ecf20Sopenharmony_ci reg = s5h1432_readreg(state, S5H1432_I2C_TOP_ADDR, 0x42); 2788c2ecf20Sopenharmony_ci reg |= 0x80; 2798c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x42, reg); 2808c2ecf20Sopenharmony_ci /* Serial mode */ 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci /* Soft Reset chip */ 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1a); 2858c2ecf20Sopenharmony_ci msleep(30); 2868c2ecf20Sopenharmony_ci s5h1432_writereg(state, S5H1432_I2C_TOP_ADDR, 0x09, 0x1b); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci return 0; 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistatic int s5h1432_read_status(struct dvb_frontend *fe, enum fe_status *status) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci return 0; 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic int s5h1432_read_signal_strength(struct dvb_frontend *fe, 2988c2ecf20Sopenharmony_ci u16 *signal_strength) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci return 0; 3018c2ecf20Sopenharmony_ci} 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_cistatic int s5h1432_read_snr(struct dvb_frontend *fe, u16 *snr) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci return 0; 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistatic int s5h1432_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci return 0; 3128c2ecf20Sopenharmony_ci} 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_cistatic int s5h1432_read_ber(struct dvb_frontend *fe, u32 *ber) 3158c2ecf20Sopenharmony_ci{ 3168c2ecf20Sopenharmony_ci return 0; 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cistatic int s5h1432_get_tune_settings(struct dvb_frontend *fe, 3208c2ecf20Sopenharmony_ci struct dvb_frontend_tune_settings *tune) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci return 0; 3238c2ecf20Sopenharmony_ci} 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_cistatic void s5h1432_release(struct dvb_frontend *fe) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci struct s5h1432_state *state = fe->demodulator_priv; 3288c2ecf20Sopenharmony_ci kfree(state); 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops s5h1432_ops; 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cistruct dvb_frontend *s5h1432_attach(const struct s5h1432_config *config, 3348c2ecf20Sopenharmony_ci struct i2c_adapter *i2c) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci struct s5h1432_state *state = NULL; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci printk(KERN_INFO " Enter s5h1432_attach(). attach success!\n"); 3398c2ecf20Sopenharmony_ci /* allocate memory for the internal state */ 3408c2ecf20Sopenharmony_ci state = kmalloc(sizeof(struct s5h1432_state), GFP_KERNEL); 3418c2ecf20Sopenharmony_ci if (!state) 3428c2ecf20Sopenharmony_ci return NULL; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci /* setup the state */ 3458c2ecf20Sopenharmony_ci state->config = config; 3468c2ecf20Sopenharmony_ci state->i2c = i2c; 3478c2ecf20Sopenharmony_ci state->current_modulation = QAM_16; 3488c2ecf20Sopenharmony_ci state->inversion = state->config->inversion; 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci /* create dvb_frontend */ 3518c2ecf20Sopenharmony_ci memcpy(&state->frontend.ops, &s5h1432_ops, 3528c2ecf20Sopenharmony_ci sizeof(struct dvb_frontend_ops)); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ci state->frontend.demodulator_priv = state; 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci return &state->frontend; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(s5h1432_attach); 3598c2ecf20Sopenharmony_ci 3608c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops s5h1432_ops = { 3618c2ecf20Sopenharmony_ci .delsys = { SYS_DVBT }, 3628c2ecf20Sopenharmony_ci .info = { 3638c2ecf20Sopenharmony_ci .name = "Samsung s5h1432 DVB-T Frontend", 3648c2ecf20Sopenharmony_ci .frequency_min_hz = 177 * MHz, 3658c2ecf20Sopenharmony_ci .frequency_max_hz = 858 * MHz, 3668c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 166666, 3678c2ecf20Sopenharmony_ci .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | 3688c2ecf20Sopenharmony_ci FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | 3698c2ecf20Sopenharmony_ci FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO | 3708c2ecf20Sopenharmony_ci FE_CAN_HIERARCHY_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | 3718c2ecf20Sopenharmony_ci FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER}, 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci .init = s5h1432_init, 3748c2ecf20Sopenharmony_ci .sleep = s5h1432_sleep, 3758c2ecf20Sopenharmony_ci .set_frontend = s5h1432_set_frontend, 3768c2ecf20Sopenharmony_ci .get_tune_settings = s5h1432_get_tune_settings, 3778c2ecf20Sopenharmony_ci .read_status = s5h1432_read_status, 3788c2ecf20Sopenharmony_ci .read_ber = s5h1432_read_ber, 3798c2ecf20Sopenharmony_ci .read_signal_strength = s5h1432_read_signal_strength, 3808c2ecf20Sopenharmony_ci .read_snr = s5h1432_read_snr, 3818c2ecf20Sopenharmony_ci .read_ucblocks = s5h1432_read_ucblocks, 3828c2ecf20Sopenharmony_ci .release = s5h1432_release, 3838c2ecf20Sopenharmony_ci}; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_cimodule_param(debug, int, 0644); 3868c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "Enable verbose debug messages"); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Samsung s5h1432 DVB-T Demodulator driver"); 3898c2ecf20Sopenharmony_ciMODULE_AUTHOR("Bill Liu"); 3908c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 391