18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci STB0899 Multistandard Frontend driver 48c2ecf20Sopenharmony_ci Copyright (C) Manu Abraham (abraham.manu@gmail.com) 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci Copyright (C) ST Microelectronics 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci*/ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/init.h> 118c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <linux/string.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <linux/dvb/frontend.h> 188c2ecf20Sopenharmony_ci#include <media/dvb_frontend.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include "stb0899_drv.h" 218c2ecf20Sopenharmony_ci#include "stb0899_priv.h" 228c2ecf20Sopenharmony_ci#include "stb0899_reg.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/* Max transfer size done by I2C transfer functions */ 258c2ecf20Sopenharmony_ci#define MAX_XFER_SIZE 64 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic unsigned int verbose = 0;//1; 288c2ecf20Sopenharmony_cimodule_param(verbose, int, 0644); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* C/N in dB/10, NIRM/NIRL */ 318c2ecf20Sopenharmony_cistatic const struct stb0899_tab stb0899_cn_tab[] = { 328c2ecf20Sopenharmony_ci { 200, 2600 }, 338c2ecf20Sopenharmony_ci { 190, 2700 }, 348c2ecf20Sopenharmony_ci { 180, 2860 }, 358c2ecf20Sopenharmony_ci { 170, 3020 }, 368c2ecf20Sopenharmony_ci { 160, 3210 }, 378c2ecf20Sopenharmony_ci { 150, 3440 }, 388c2ecf20Sopenharmony_ci { 140, 3710 }, 398c2ecf20Sopenharmony_ci { 130, 4010 }, 408c2ecf20Sopenharmony_ci { 120, 4360 }, 418c2ecf20Sopenharmony_ci { 110, 4740 }, 428c2ecf20Sopenharmony_ci { 100, 5190 }, 438c2ecf20Sopenharmony_ci { 90, 5670 }, 448c2ecf20Sopenharmony_ci { 80, 6200 }, 458c2ecf20Sopenharmony_ci { 70, 6770 }, 468c2ecf20Sopenharmony_ci { 60, 7360 }, 478c2ecf20Sopenharmony_ci { 50, 7970 }, 488c2ecf20Sopenharmony_ci { 40, 8250 }, 498c2ecf20Sopenharmony_ci { 30, 9000 }, 508c2ecf20Sopenharmony_ci { 20, 9450 }, 518c2ecf20Sopenharmony_ci { 15, 9600 }, 528c2ecf20Sopenharmony_ci}; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci/* DVB-S AGCIQ_VALUE vs. signal level in dBm/10. 558c2ecf20Sopenharmony_ci * As measured, connected to a modulator. 568c2ecf20Sopenharmony_ci * -8.0 to -50.0 dBm directly connected, 578c2ecf20Sopenharmony_ci * -52.0 to -74.8 with extra attenuation. 588c2ecf20Sopenharmony_ci * Cut-off to AGCIQ_VALUE = 0x80 below -74.8dBm. 598c2ecf20Sopenharmony_ci * Crude linear extrapolation below -84.8dBm and above -8.0dBm. 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_cistatic const struct stb0899_tab stb0899_dvbsrf_tab[] = { 628c2ecf20Sopenharmony_ci { -750, -128 }, 638c2ecf20Sopenharmony_ci { -748, -94 }, 648c2ecf20Sopenharmony_ci { -745, -92 }, 658c2ecf20Sopenharmony_ci { -735, -90 }, 668c2ecf20Sopenharmony_ci { -720, -87 }, 678c2ecf20Sopenharmony_ci { -670, -77 }, 688c2ecf20Sopenharmony_ci { -640, -70 }, 698c2ecf20Sopenharmony_ci { -610, -62 }, 708c2ecf20Sopenharmony_ci { -600, -60 }, 718c2ecf20Sopenharmony_ci { -590, -56 }, 728c2ecf20Sopenharmony_ci { -560, -41 }, 738c2ecf20Sopenharmony_ci { -540, -25 }, 748c2ecf20Sopenharmony_ci { -530, -17 }, 758c2ecf20Sopenharmony_ci { -520, -11 }, 768c2ecf20Sopenharmony_ci { -500, 1 }, 778c2ecf20Sopenharmony_ci { -490, 6 }, 788c2ecf20Sopenharmony_ci { -480, 10 }, 798c2ecf20Sopenharmony_ci { -440, 22 }, 808c2ecf20Sopenharmony_ci { -420, 27 }, 818c2ecf20Sopenharmony_ci { -400, 31 }, 828c2ecf20Sopenharmony_ci { -380, 34 }, 838c2ecf20Sopenharmony_ci { -340, 40 }, 848c2ecf20Sopenharmony_ci { -320, 43 }, 858c2ecf20Sopenharmony_ci { -280, 48 }, 868c2ecf20Sopenharmony_ci { -250, 52 }, 878c2ecf20Sopenharmony_ci { -230, 55 }, 888c2ecf20Sopenharmony_ci { -180, 61 }, 898c2ecf20Sopenharmony_ci { -140, 66 }, 908c2ecf20Sopenharmony_ci { -90, 73 }, 918c2ecf20Sopenharmony_ci { -80, 74 }, 928c2ecf20Sopenharmony_ci { 500, 127 } 938c2ecf20Sopenharmony_ci}; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* DVB-S2 IF_AGC_GAIN vs. signal level in dBm/10. 968c2ecf20Sopenharmony_ci * As measured, connected to a modulator. 978c2ecf20Sopenharmony_ci * -8.0 to -50.1 dBm directly connected, 988c2ecf20Sopenharmony_ci * -53.0 to -76.6 with extra attenuation. 998c2ecf20Sopenharmony_ci * Cut-off to IF_AGC_GAIN = 0x3fff below -76.6dBm. 1008c2ecf20Sopenharmony_ci * Crude linear extrapolation below -76.6dBm and above -8.0dBm. 1018c2ecf20Sopenharmony_ci */ 1028c2ecf20Sopenharmony_cistatic const struct stb0899_tab stb0899_dvbs2rf_tab[] = { 1038c2ecf20Sopenharmony_ci { 700, 0 }, 1048c2ecf20Sopenharmony_ci { -80, 3217 }, 1058c2ecf20Sopenharmony_ci { -150, 3893 }, 1068c2ecf20Sopenharmony_ci { -190, 4217 }, 1078c2ecf20Sopenharmony_ci { -240, 4621 }, 1088c2ecf20Sopenharmony_ci { -280, 4945 }, 1098c2ecf20Sopenharmony_ci { -320, 5273 }, 1108c2ecf20Sopenharmony_ci { -350, 5545 }, 1118c2ecf20Sopenharmony_ci { -370, 5741 }, 1128c2ecf20Sopenharmony_ci { -410, 6147 }, 1138c2ecf20Sopenharmony_ci { -450, 6671 }, 1148c2ecf20Sopenharmony_ci { -490, 7413 }, 1158c2ecf20Sopenharmony_ci { -501, 7665 }, 1168c2ecf20Sopenharmony_ci { -530, 8767 }, 1178c2ecf20Sopenharmony_ci { -560, 10219 }, 1188c2ecf20Sopenharmony_ci { -580, 10939 }, 1198c2ecf20Sopenharmony_ci { -590, 11518 }, 1208c2ecf20Sopenharmony_ci { -600, 11723 }, 1218c2ecf20Sopenharmony_ci { -650, 12659 }, 1228c2ecf20Sopenharmony_ci { -690, 13219 }, 1238c2ecf20Sopenharmony_ci { -730, 13645 }, 1248c2ecf20Sopenharmony_ci { -750, 13909 }, 1258c2ecf20Sopenharmony_ci { -766, 14153 }, 1268c2ecf20Sopenharmony_ci { -950, 16383 } 1278c2ecf20Sopenharmony_ci}; 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci/* DVB-S2 Es/N0 quant in dB/100 vs read value * 100*/ 1308c2ecf20Sopenharmony_cistatic struct stb0899_tab stb0899_quant_tab[] = { 1318c2ecf20Sopenharmony_ci { 0, 0 }, 1328c2ecf20Sopenharmony_ci { 0, 100 }, 1338c2ecf20Sopenharmony_ci { 600, 200 }, 1348c2ecf20Sopenharmony_ci { 950, 299 }, 1358c2ecf20Sopenharmony_ci { 1200, 398 }, 1368c2ecf20Sopenharmony_ci { 1400, 501 }, 1378c2ecf20Sopenharmony_ci { 1560, 603 }, 1388c2ecf20Sopenharmony_ci { 1690, 700 }, 1398c2ecf20Sopenharmony_ci { 1810, 804 }, 1408c2ecf20Sopenharmony_ci { 1910, 902 }, 1418c2ecf20Sopenharmony_ci { 2000, 1000 }, 1428c2ecf20Sopenharmony_ci { 2080, 1096 }, 1438c2ecf20Sopenharmony_ci { 2160, 1202 }, 1448c2ecf20Sopenharmony_ci { 2230, 1303 }, 1458c2ecf20Sopenharmony_ci { 2350, 1496 }, 1468c2ecf20Sopenharmony_ci { 2410, 1603 }, 1478c2ecf20Sopenharmony_ci { 2460, 1698 }, 1488c2ecf20Sopenharmony_ci { 2510, 1799 }, 1498c2ecf20Sopenharmony_ci { 2600, 1995 }, 1508c2ecf20Sopenharmony_ci { 2650, 2113 }, 1518c2ecf20Sopenharmony_ci { 2690, 2213 }, 1528c2ecf20Sopenharmony_ci { 2720, 2291 }, 1538c2ecf20Sopenharmony_ci { 2760, 2399 }, 1548c2ecf20Sopenharmony_ci { 2800, 2512 }, 1558c2ecf20Sopenharmony_ci { 2860, 2692 }, 1568c2ecf20Sopenharmony_ci { 2930, 2917 }, 1578c2ecf20Sopenharmony_ci { 2960, 3020 }, 1588c2ecf20Sopenharmony_ci { 3010, 3199 }, 1598c2ecf20Sopenharmony_ci { 3040, 3311 }, 1608c2ecf20Sopenharmony_ci { 3060, 3388 }, 1618c2ecf20Sopenharmony_ci { 3120, 3631 }, 1628c2ecf20Sopenharmony_ci { 3190, 3936 }, 1638c2ecf20Sopenharmony_ci { 3400, 5012 }, 1648c2ecf20Sopenharmony_ci { 3610, 6383 }, 1658c2ecf20Sopenharmony_ci { 3800, 7943 }, 1668c2ecf20Sopenharmony_ci { 4210, 12735 }, 1678c2ecf20Sopenharmony_ci { 4500, 17783 }, 1688c2ecf20Sopenharmony_ci { 4690, 22131 }, 1698c2ecf20Sopenharmony_ci { 4810, 25410 } 1708c2ecf20Sopenharmony_ci}; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci/* DVB-S2 Es/N0 estimate in dB/100 vs read value */ 1738c2ecf20Sopenharmony_cistatic struct stb0899_tab stb0899_est_tab[] = { 1748c2ecf20Sopenharmony_ci { 0, 0 }, 1758c2ecf20Sopenharmony_ci { 0, 1 }, 1768c2ecf20Sopenharmony_ci { 301, 2 }, 1778c2ecf20Sopenharmony_ci { 1204, 16 }, 1788c2ecf20Sopenharmony_ci { 1806, 64 }, 1798c2ecf20Sopenharmony_ci { 2408, 256 }, 1808c2ecf20Sopenharmony_ci { 2709, 512 }, 1818c2ecf20Sopenharmony_ci { 3010, 1023 }, 1828c2ecf20Sopenharmony_ci { 3311, 2046 }, 1838c2ecf20Sopenharmony_ci { 3612, 4093 }, 1848c2ecf20Sopenharmony_ci { 3823, 6653 }, 1858c2ecf20Sopenharmony_ci { 3913, 8185 }, 1868c2ecf20Sopenharmony_ci { 4010, 10233 }, 1878c2ecf20Sopenharmony_ci { 4107, 12794 }, 1888c2ecf20Sopenharmony_ci { 4214, 16368 }, 1898c2ecf20Sopenharmony_ci { 4266, 18450 }, 1908c2ecf20Sopenharmony_ci { 4311, 20464 }, 1918c2ecf20Sopenharmony_ci { 4353, 22542 }, 1928c2ecf20Sopenharmony_ci { 4391, 24604 }, 1938c2ecf20Sopenharmony_ci { 4425, 26607 }, 1948c2ecf20Sopenharmony_ci { 4457, 28642 }, 1958c2ecf20Sopenharmony_ci { 4487, 30690 }, 1968c2ecf20Sopenharmony_ci { 4515, 32734 }, 1978c2ecf20Sopenharmony_ci { 4612, 40926 }, 1988c2ecf20Sopenharmony_ci { 4692, 49204 }, 1998c2ecf20Sopenharmony_ci { 4816, 65464 }, 2008c2ecf20Sopenharmony_ci { 4913, 81846 }, 2018c2ecf20Sopenharmony_ci { 4993, 98401 }, 2028c2ecf20Sopenharmony_ci { 5060, 114815 }, 2038c2ecf20Sopenharmony_ci { 5118, 131220 }, 2048c2ecf20Sopenharmony_ci { 5200, 158489 }, 2058c2ecf20Sopenharmony_ci { 5300, 199526 }, 2068c2ecf20Sopenharmony_ci { 5400, 251189 }, 2078c2ecf20Sopenharmony_ci { 5500, 316228 }, 2088c2ecf20Sopenharmony_ci { 5600, 398107 }, 2098c2ecf20Sopenharmony_ci { 5720, 524807 }, 2108c2ecf20Sopenharmony_ci { 5721, 526017 }, 2118c2ecf20Sopenharmony_ci}; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_cistatic int _stb0899_read_reg(struct stb0899_state *state, unsigned int reg) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci int ret; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci u8 b0[] = { reg >> 8, reg & 0xff }; 2188c2ecf20Sopenharmony_ci u8 buf; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci struct i2c_msg msg[] = { 2218c2ecf20Sopenharmony_ci { 2228c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 2238c2ecf20Sopenharmony_ci .flags = 0, 2248c2ecf20Sopenharmony_ci .buf = b0, 2258c2ecf20Sopenharmony_ci .len = 2 2268c2ecf20Sopenharmony_ci },{ 2278c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 2288c2ecf20Sopenharmony_ci .flags = I2C_M_RD, 2298c2ecf20Sopenharmony_ci .buf = &buf, 2308c2ecf20Sopenharmony_ci .len = 1 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci }; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci ret = i2c_transfer(state->i2c, msg, 2); 2358c2ecf20Sopenharmony_ci if (ret != 2) { 2368c2ecf20Sopenharmony_ci if (ret != -ERESTARTSYS) 2378c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_ERROR, 1, 2388c2ecf20Sopenharmony_ci "Read error, Reg=[0x%02x], Status=%d", 2398c2ecf20Sopenharmony_ci reg, ret); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci return ret < 0 ? ret : -EREMOTEIO; 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci if (unlikely(*state->verbose >= FE_DEBUGREG)) 2448c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_ERROR, 1, "Reg=[0x%02x], data=%02x", 2458c2ecf20Sopenharmony_ci reg, buf); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci return (unsigned int)buf; 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ciint stb0899_read_reg(struct stb0899_state *state, unsigned int reg) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci int result; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci result = _stb0899_read_reg(state, reg); 2558c2ecf20Sopenharmony_ci /* 2568c2ecf20Sopenharmony_ci * Bug ID 9: 2578c2ecf20Sopenharmony_ci * access to 0xf2xx/0xf6xx 2588c2ecf20Sopenharmony_ci * must be followed by read from 0xf2ff/0xf6ff. 2598c2ecf20Sopenharmony_ci */ 2608c2ecf20Sopenharmony_ci if ((reg != 0xf2ff) && (reg != 0xf6ff) && 2618c2ecf20Sopenharmony_ci (((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600))) 2628c2ecf20Sopenharmony_ci _stb0899_read_reg(state, (reg | 0x00ff)); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci return result; 2658c2ecf20Sopenharmony_ci} 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ciu32 _stb0899_read_s2reg(struct stb0899_state *state, 2688c2ecf20Sopenharmony_ci u32 stb0899_i2cdev, 2698c2ecf20Sopenharmony_ci u32 stb0899_base_addr, 2708c2ecf20Sopenharmony_ci u16 stb0899_reg_offset) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci int status; 2738c2ecf20Sopenharmony_ci u32 data; 2748c2ecf20Sopenharmony_ci u8 buf[7] = { 0 }; 2758c2ecf20Sopenharmony_ci u16 tmpaddr; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci u8 buf_0[] = { 2788c2ecf20Sopenharmony_ci GETBYTE(stb0899_i2cdev, BYTE1), /* 0xf3 S2 Base Address (MSB) */ 2798c2ecf20Sopenharmony_ci GETBYTE(stb0899_i2cdev, BYTE0), /* 0xfc S2 Base Address (LSB) */ 2808c2ecf20Sopenharmony_ci GETBYTE(stb0899_base_addr, BYTE0), /* 0x00 Base Address (LSB) */ 2818c2ecf20Sopenharmony_ci GETBYTE(stb0899_base_addr, BYTE1), /* 0x04 Base Address (LSB) */ 2828c2ecf20Sopenharmony_ci GETBYTE(stb0899_base_addr, BYTE2), /* 0x00 Base Address (MSB) */ 2838c2ecf20Sopenharmony_ci GETBYTE(stb0899_base_addr, BYTE3), /* 0x00 Base Address (MSB) */ 2848c2ecf20Sopenharmony_ci }; 2858c2ecf20Sopenharmony_ci u8 buf_1[] = { 2868c2ecf20Sopenharmony_ci 0x00, /* 0xf3 Reg Offset */ 2878c2ecf20Sopenharmony_ci 0x00, /* 0x44 Reg Offset */ 2888c2ecf20Sopenharmony_ci }; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci struct i2c_msg msg_0 = { 2918c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 2928c2ecf20Sopenharmony_ci .flags = 0, 2938c2ecf20Sopenharmony_ci .buf = buf_0, 2948c2ecf20Sopenharmony_ci .len = 6 2958c2ecf20Sopenharmony_ci }; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci struct i2c_msg msg_1 = { 2988c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 2998c2ecf20Sopenharmony_ci .flags = 0, 3008c2ecf20Sopenharmony_ci .buf = buf_1, 3018c2ecf20Sopenharmony_ci .len = 2 3028c2ecf20Sopenharmony_ci }; 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci struct i2c_msg msg_r = { 3058c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 3068c2ecf20Sopenharmony_ci .flags = I2C_M_RD, 3078c2ecf20Sopenharmony_ci .buf = buf, 3088c2ecf20Sopenharmony_ci .len = 4 3098c2ecf20Sopenharmony_ci }; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci tmpaddr = stb0899_reg_offset & 0xff00; 3128c2ecf20Sopenharmony_ci if (!(stb0899_reg_offset & 0x8)) 3138c2ecf20Sopenharmony_ci tmpaddr = stb0899_reg_offset | 0x20; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci buf_1[0] = GETBYTE(tmpaddr, BYTE1); 3168c2ecf20Sopenharmony_ci buf_1[1] = GETBYTE(tmpaddr, BYTE0); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci status = i2c_transfer(state->i2c, &msg_0, 1); 3198c2ecf20Sopenharmony_ci if (status < 1) { 3208c2ecf20Sopenharmony_ci if (status != -ERESTARTSYS) 3218c2ecf20Sopenharmony_ci printk(KERN_ERR "%s ERR(1), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n", 3228c2ecf20Sopenharmony_ci __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci goto err; 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* Dummy */ 3288c2ecf20Sopenharmony_ci status = i2c_transfer(state->i2c, &msg_1, 1); 3298c2ecf20Sopenharmony_ci if (status < 1) 3308c2ecf20Sopenharmony_ci goto err; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci status = i2c_transfer(state->i2c, &msg_r, 1); 3338c2ecf20Sopenharmony_ci if (status < 1) 3348c2ecf20Sopenharmony_ci goto err; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci buf_1[0] = GETBYTE(stb0899_reg_offset, BYTE1); 3378c2ecf20Sopenharmony_ci buf_1[1] = GETBYTE(stb0899_reg_offset, BYTE0); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci /* Actual */ 3408c2ecf20Sopenharmony_ci status = i2c_transfer(state->i2c, &msg_1, 1); 3418c2ecf20Sopenharmony_ci if (status < 1) { 3428c2ecf20Sopenharmony_ci if (status != -ERESTARTSYS) 3438c2ecf20Sopenharmony_ci printk(KERN_ERR "%s ERR(2), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n", 3448c2ecf20Sopenharmony_ci __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status); 3458c2ecf20Sopenharmony_ci goto err; 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci status = i2c_transfer(state->i2c, &msg_r, 1); 3498c2ecf20Sopenharmony_ci if (status < 1) { 3508c2ecf20Sopenharmony_ci if (status != -ERESTARTSYS) 3518c2ecf20Sopenharmony_ci printk(KERN_ERR "%s ERR(3), Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Status=%d\n", 3528c2ecf20Sopenharmony_ci __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, status); 3538c2ecf20Sopenharmony_ci return status < 0 ? status : -EREMOTEIO; 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_ci data = MAKEWORD32(buf[3], buf[2], buf[1], buf[0]); 3578c2ecf20Sopenharmony_ci if (unlikely(*state->verbose >= FE_DEBUGREG)) 3588c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s Device=[0x%04x], Base address=[0x%08x], Offset=[0x%04x], Data=[0x%08x]\n", 3598c2ecf20Sopenharmony_ci __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, data); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci return data; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cierr: 3648c2ecf20Sopenharmony_ci return status < 0 ? status : -EREMOTEIO; 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ciint stb0899_write_s2reg(struct stb0899_state *state, 3688c2ecf20Sopenharmony_ci u32 stb0899_i2cdev, 3698c2ecf20Sopenharmony_ci u32 stb0899_base_addr, 3708c2ecf20Sopenharmony_ci u16 stb0899_reg_offset, 3718c2ecf20Sopenharmony_ci u32 stb0899_data) 3728c2ecf20Sopenharmony_ci{ 3738c2ecf20Sopenharmony_ci int status; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci /* Base Address Setup */ 3768c2ecf20Sopenharmony_ci u8 buf_0[] = { 3778c2ecf20Sopenharmony_ci GETBYTE(stb0899_i2cdev, BYTE1), /* 0xf3 S2 Base Address (MSB) */ 3788c2ecf20Sopenharmony_ci GETBYTE(stb0899_i2cdev, BYTE0), /* 0xfc S2 Base Address (LSB) */ 3798c2ecf20Sopenharmony_ci GETBYTE(stb0899_base_addr, BYTE0), /* 0x00 Base Address (LSB) */ 3808c2ecf20Sopenharmony_ci GETBYTE(stb0899_base_addr, BYTE1), /* 0x04 Base Address (LSB) */ 3818c2ecf20Sopenharmony_ci GETBYTE(stb0899_base_addr, BYTE2), /* 0x00 Base Address (MSB) */ 3828c2ecf20Sopenharmony_ci GETBYTE(stb0899_base_addr, BYTE3), /* 0x00 Base Address (MSB) */ 3838c2ecf20Sopenharmony_ci }; 3848c2ecf20Sopenharmony_ci u8 buf_1[] = { 3858c2ecf20Sopenharmony_ci 0x00, /* 0xf3 Reg Offset */ 3868c2ecf20Sopenharmony_ci 0x00, /* 0x44 Reg Offset */ 3878c2ecf20Sopenharmony_ci 0x00, /* data */ 3888c2ecf20Sopenharmony_ci 0x00, /* data */ 3898c2ecf20Sopenharmony_ci 0x00, /* data */ 3908c2ecf20Sopenharmony_ci 0x00, /* data */ 3918c2ecf20Sopenharmony_ci }; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci struct i2c_msg msg_0 = { 3948c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 3958c2ecf20Sopenharmony_ci .flags = 0, 3968c2ecf20Sopenharmony_ci .buf = buf_0, 3978c2ecf20Sopenharmony_ci .len = 6 3988c2ecf20Sopenharmony_ci }; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci struct i2c_msg msg_1 = { 4018c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 4028c2ecf20Sopenharmony_ci .flags = 0, 4038c2ecf20Sopenharmony_ci .buf = buf_1, 4048c2ecf20Sopenharmony_ci .len = 6 4058c2ecf20Sopenharmony_ci }; 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_ci buf_1[0] = GETBYTE(stb0899_reg_offset, BYTE1); 4088c2ecf20Sopenharmony_ci buf_1[1] = GETBYTE(stb0899_reg_offset, BYTE0); 4098c2ecf20Sopenharmony_ci buf_1[2] = GETBYTE(stb0899_data, BYTE0); 4108c2ecf20Sopenharmony_ci buf_1[3] = GETBYTE(stb0899_data, BYTE1); 4118c2ecf20Sopenharmony_ci buf_1[4] = GETBYTE(stb0899_data, BYTE2); 4128c2ecf20Sopenharmony_ci buf_1[5] = GETBYTE(stb0899_data, BYTE3); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci if (unlikely(*state->verbose >= FE_DEBUGREG)) 4158c2ecf20Sopenharmony_ci printk(KERN_DEBUG "%s Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x]\n", 4168c2ecf20Sopenharmony_ci __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci status = i2c_transfer(state->i2c, &msg_0, 1); 4198c2ecf20Sopenharmony_ci if (unlikely(status < 1)) { 4208c2ecf20Sopenharmony_ci if (status != -ERESTARTSYS) 4218c2ecf20Sopenharmony_ci printk(KERN_ERR "%s ERR (1), Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x], status=%d\n", 4228c2ecf20Sopenharmony_ci __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data, status); 4238c2ecf20Sopenharmony_ci goto err; 4248c2ecf20Sopenharmony_ci } 4258c2ecf20Sopenharmony_ci status = i2c_transfer(state->i2c, &msg_1, 1); 4268c2ecf20Sopenharmony_ci if (unlikely(status < 1)) { 4278c2ecf20Sopenharmony_ci if (status != -ERESTARTSYS) 4288c2ecf20Sopenharmony_ci printk(KERN_ERR "%s ERR (2), Device=[0x%04x], Base Address=[0x%08x], Offset=[0x%04x], Data=[0x%08x], status=%d\n", 4298c2ecf20Sopenharmony_ci __func__, stb0899_i2cdev, stb0899_base_addr, stb0899_reg_offset, stb0899_data, status); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci return status < 0 ? status : -EREMOTEIO; 4328c2ecf20Sopenharmony_ci } 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci return 0; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_cierr: 4378c2ecf20Sopenharmony_ci return status < 0 ? status : -EREMOTEIO; 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ciint stb0899_read_regs(struct stb0899_state *state, unsigned int reg, u8 *buf, u32 count) 4418c2ecf20Sopenharmony_ci{ 4428c2ecf20Sopenharmony_ci int status; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci u8 b0[] = { reg >> 8, reg & 0xff }; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci struct i2c_msg msg[] = { 4478c2ecf20Sopenharmony_ci { 4488c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 4498c2ecf20Sopenharmony_ci .flags = 0, 4508c2ecf20Sopenharmony_ci .buf = b0, 4518c2ecf20Sopenharmony_ci .len = 2 4528c2ecf20Sopenharmony_ci },{ 4538c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 4548c2ecf20Sopenharmony_ci .flags = I2C_M_RD, 4558c2ecf20Sopenharmony_ci .buf = buf, 4568c2ecf20Sopenharmony_ci .len = count 4578c2ecf20Sopenharmony_ci } 4588c2ecf20Sopenharmony_ci }; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci status = i2c_transfer(state->i2c, msg, 2); 4618c2ecf20Sopenharmony_ci if (status != 2) { 4628c2ecf20Sopenharmony_ci if (status != -ERESTARTSYS) 4638c2ecf20Sopenharmony_ci printk(KERN_ERR "%s Read error, Reg=[0x%04x], Count=%u, Status=%d\n", 4648c2ecf20Sopenharmony_ci __func__, reg, count, status); 4658c2ecf20Sopenharmony_ci goto err; 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci /* 4688c2ecf20Sopenharmony_ci * Bug ID 9: 4698c2ecf20Sopenharmony_ci * access to 0xf2xx/0xf6xx 4708c2ecf20Sopenharmony_ci * must be followed by read from 0xf2ff/0xf6ff. 4718c2ecf20Sopenharmony_ci */ 4728c2ecf20Sopenharmony_ci if ((reg != 0xf2ff) && (reg != 0xf6ff) && 4738c2ecf20Sopenharmony_ci (((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600))) 4748c2ecf20Sopenharmony_ci _stb0899_read_reg(state, (reg | 0x00ff)); 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUGREG, 1, 4778c2ecf20Sopenharmony_ci "%s [0x%04x]: %*ph", __func__, reg, count, buf); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci return 0; 4808c2ecf20Sopenharmony_cierr: 4818c2ecf20Sopenharmony_ci return status < 0 ? status : -EREMOTEIO; 4828c2ecf20Sopenharmony_ci} 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ciint stb0899_write_regs(struct stb0899_state *state, unsigned int reg, u8 *data, u32 count) 4858c2ecf20Sopenharmony_ci{ 4868c2ecf20Sopenharmony_ci int ret; 4878c2ecf20Sopenharmony_ci u8 buf[MAX_XFER_SIZE]; 4888c2ecf20Sopenharmony_ci struct i2c_msg i2c_msg = { 4898c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 4908c2ecf20Sopenharmony_ci .flags = 0, 4918c2ecf20Sopenharmony_ci .buf = buf, 4928c2ecf20Sopenharmony_ci .len = 2 + count 4938c2ecf20Sopenharmony_ci }; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci if (2 + count > sizeof(buf)) { 4968c2ecf20Sopenharmony_ci printk(KERN_WARNING 4978c2ecf20Sopenharmony_ci "%s: i2c wr reg=%04x: len=%d is too big!\n", 4988c2ecf20Sopenharmony_ci KBUILD_MODNAME, reg, count); 4998c2ecf20Sopenharmony_ci return -EINVAL; 5008c2ecf20Sopenharmony_ci } 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci buf[0] = reg >> 8; 5038c2ecf20Sopenharmony_ci buf[1] = reg & 0xff; 5048c2ecf20Sopenharmony_ci memcpy(&buf[2], data, count); 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUGREG, 1, 5078c2ecf20Sopenharmony_ci "%s [0x%04x]: %*ph", __func__, reg, count, data); 5088c2ecf20Sopenharmony_ci ret = i2c_transfer(state->i2c, &i2c_msg, 1); 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci /* 5118c2ecf20Sopenharmony_ci * Bug ID 9: 5128c2ecf20Sopenharmony_ci * access to 0xf2xx/0xf6xx 5138c2ecf20Sopenharmony_ci * must be followed by read from 0xf2ff/0xf6ff. 5148c2ecf20Sopenharmony_ci */ 5158c2ecf20Sopenharmony_ci if ((((reg & 0xff00) == 0xf200) || ((reg & 0xff00) == 0xf600))) 5168c2ecf20Sopenharmony_ci stb0899_read_reg(state, (reg | 0x00ff)); 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci if (ret != 1) { 5198c2ecf20Sopenharmony_ci if (ret != -ERESTARTSYS) 5208c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_ERROR, 1, "Reg=[0x%04x], Data=[0x%02x ...], Count=%u, Status=%d", 5218c2ecf20Sopenharmony_ci reg, data[0], count, ret); 5228c2ecf20Sopenharmony_ci return ret < 0 ? ret : -EREMOTEIO; 5238c2ecf20Sopenharmony_ci } 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci return 0; 5268c2ecf20Sopenharmony_ci} 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ciint stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data) 5298c2ecf20Sopenharmony_ci{ 5308c2ecf20Sopenharmony_ci u8 tmp = data; 5318c2ecf20Sopenharmony_ci return stb0899_write_regs(state, reg, &tmp, 1); 5328c2ecf20Sopenharmony_ci} 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci/* 5358c2ecf20Sopenharmony_ci * stb0899_get_mclk 5368c2ecf20Sopenharmony_ci * Get STB0899 master clock frequency 5378c2ecf20Sopenharmony_ci * ExtClk: external clock frequency (Hz) 5388c2ecf20Sopenharmony_ci */ 5398c2ecf20Sopenharmony_cistatic u32 stb0899_get_mclk(struct stb0899_state *state) 5408c2ecf20Sopenharmony_ci{ 5418c2ecf20Sopenharmony_ci u32 mclk = 0, div = 0; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci div = stb0899_read_reg(state, STB0899_NCOARSE); 5448c2ecf20Sopenharmony_ci mclk = (div + 1) * state->config->xtal_freq / 6; 5458c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "div=%d, mclk=%d", div, mclk); 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci return mclk; 5488c2ecf20Sopenharmony_ci} 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci/* 5518c2ecf20Sopenharmony_ci * stb0899_set_mclk 5528c2ecf20Sopenharmony_ci * Set STB0899 master Clock frequency 5538c2ecf20Sopenharmony_ci * Mclk: demodulator master clock 5548c2ecf20Sopenharmony_ci * ExtClk: external clock frequency (Hz) 5558c2ecf20Sopenharmony_ci */ 5568c2ecf20Sopenharmony_cistatic void stb0899_set_mclk(struct stb0899_state *state, u32 Mclk) 5578c2ecf20Sopenharmony_ci{ 5588c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 5598c2ecf20Sopenharmony_ci u8 mdiv = 0; 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "state->config=%p", state->config); 5628c2ecf20Sopenharmony_ci mdiv = ((6 * Mclk) / state->config->xtal_freq) - 1; 5638c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "mdiv=%d", mdiv); 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_NCOARSE, mdiv); 5668c2ecf20Sopenharmony_ci internal->master_clk = stb0899_get_mclk(state); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "MasterCLOCK=%d", internal->master_clk); 5698c2ecf20Sopenharmony_ci} 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_cistatic int stb0899_postproc(struct stb0899_state *state, u8 ctl, int enable) 5728c2ecf20Sopenharmony_ci{ 5738c2ecf20Sopenharmony_ci struct stb0899_config *config = state->config; 5748c2ecf20Sopenharmony_ci const struct stb0899_postproc *postproc = config->postproc; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci /* post process event */ 5778c2ecf20Sopenharmony_ci if (postproc) { 5788c2ecf20Sopenharmony_ci if (enable) { 5798c2ecf20Sopenharmony_ci if (postproc[ctl].level == STB0899_GPIOPULLUP) 5808c2ecf20Sopenharmony_ci stb0899_write_reg(state, postproc[ctl].gpio, 0x02); 5818c2ecf20Sopenharmony_ci else 5828c2ecf20Sopenharmony_ci stb0899_write_reg(state, postproc[ctl].gpio, 0x82); 5838c2ecf20Sopenharmony_ci } else { 5848c2ecf20Sopenharmony_ci if (postproc[ctl].level == STB0899_GPIOPULLUP) 5858c2ecf20Sopenharmony_ci stb0899_write_reg(state, postproc[ctl].gpio, 0x82); 5868c2ecf20Sopenharmony_ci else 5878c2ecf20Sopenharmony_ci stb0899_write_reg(state, postproc[ctl].gpio, 0x02); 5888c2ecf20Sopenharmony_ci } 5898c2ecf20Sopenharmony_ci } 5908c2ecf20Sopenharmony_ci return 0; 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_cistatic void stb0899_detach(struct dvb_frontend *fe) 5948c2ecf20Sopenharmony_ci{ 5958c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci /* post process event */ 5988c2ecf20Sopenharmony_ci stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0); 5998c2ecf20Sopenharmony_ci} 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_cistatic void stb0899_release(struct dvb_frontend *fe) 6028c2ecf20Sopenharmony_ci{ 6038c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Release Frontend"); 6068c2ecf20Sopenharmony_ci kfree(state); 6078c2ecf20Sopenharmony_ci} 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci/* 6108c2ecf20Sopenharmony_ci * stb0899_get_alpha 6118c2ecf20Sopenharmony_ci * return: rolloff 6128c2ecf20Sopenharmony_ci */ 6138c2ecf20Sopenharmony_cistatic int stb0899_get_alpha(struct stb0899_state *state) 6148c2ecf20Sopenharmony_ci{ 6158c2ecf20Sopenharmony_ci u8 mode_coeff; 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci mode_coeff = stb0899_read_reg(state, STB0899_DEMOD); 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(MODECOEFF, mode_coeff) == 1) 6208c2ecf20Sopenharmony_ci return 20; 6218c2ecf20Sopenharmony_ci else 6228c2ecf20Sopenharmony_ci return 35; 6238c2ecf20Sopenharmony_ci} 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci/* 6268c2ecf20Sopenharmony_ci * stb0899_init_calc 6278c2ecf20Sopenharmony_ci */ 6288c2ecf20Sopenharmony_cistatic void stb0899_init_calc(struct stb0899_state *state) 6298c2ecf20Sopenharmony_ci{ 6308c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 6318c2ecf20Sopenharmony_ci int master_clk; 6328c2ecf20Sopenharmony_ci u8 agc[2]; 6338c2ecf20Sopenharmony_ci u32 reg; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci /* Read registers (in burst mode) */ 6368c2ecf20Sopenharmony_ci stb0899_read_regs(state, STB0899_AGC1REF, agc, 2); /* AGC1R and AGC2O */ 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci /* Initial calculations */ 6398c2ecf20Sopenharmony_ci master_clk = stb0899_get_mclk(state); 6408c2ecf20Sopenharmony_ci internal->t_agc1 = 0; 6418c2ecf20Sopenharmony_ci internal->t_agc2 = 0; 6428c2ecf20Sopenharmony_ci internal->master_clk = master_clk; 6438c2ecf20Sopenharmony_ci internal->mclk = master_clk / 65536L; 6448c2ecf20Sopenharmony_ci internal->rolloff = stb0899_get_alpha(state); 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_ci /* DVBS2 Initial calculations */ 6478c2ecf20Sopenharmony_ci /* Set AGC value to the middle */ 6488c2ecf20Sopenharmony_ci internal->agc_gain = 8154; 6498c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_CNTRL); 6508c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(IF_GAIN_INIT, reg, internal->agc_gain); 6518c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, STB0899_BASE_IF_AGC_CNTRL, STB0899_OFF0_IF_AGC_CNTRL, reg); 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, RRC_ALPHA); 6548c2ecf20Sopenharmony_ci internal->rrc_alpha = STB0899_GETFIELD(RRC_ALPHA, reg); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci internal->center_freq = 0; 6578c2ecf20Sopenharmony_ci internal->av_frame_coarse = 10; 6588c2ecf20Sopenharmony_ci internal->av_frame_fine = 20; 6598c2ecf20Sopenharmony_ci internal->step_size = 2; 6608c2ecf20Sopenharmony_ci/* 6618c2ecf20Sopenharmony_ci if ((pParams->SpectralInv == FE_IQ_NORMAL) || (pParams->SpectralInv == FE_IQ_AUTO)) 6628c2ecf20Sopenharmony_ci pParams->IQLocked = 0; 6638c2ecf20Sopenharmony_ci else 6648c2ecf20Sopenharmony_ci pParams->IQLocked = 1; 6658c2ecf20Sopenharmony_ci*/ 6668c2ecf20Sopenharmony_ci} 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_cistatic int stb0899_wait_diseqc_fifo_empty(struct stb0899_state *state, int timeout) 6698c2ecf20Sopenharmony_ci{ 6708c2ecf20Sopenharmony_ci u8 reg = 0; 6718c2ecf20Sopenharmony_ci unsigned long start = jiffies; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci while (1) { 6748c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_DISSTATUS); 6758c2ecf20Sopenharmony_ci if (!STB0899_GETFIELD(FIFOFULL, reg)) 6768c2ecf20Sopenharmony_ci break; 6778c2ecf20Sopenharmony_ci if (time_after(jiffies, start + timeout)) { 6788c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_ERROR, 1, "timed out !!"); 6798c2ecf20Sopenharmony_ci return -ETIMEDOUT; 6808c2ecf20Sopenharmony_ci } 6818c2ecf20Sopenharmony_ci } 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci return 0; 6848c2ecf20Sopenharmony_ci} 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_cistatic int stb0899_send_diseqc_msg(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd) 6878c2ecf20Sopenharmony_ci{ 6888c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 6898c2ecf20Sopenharmony_ci u8 reg, i; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci if (cmd->msg_len > sizeof(cmd->msg)) 6928c2ecf20Sopenharmony_ci return -EINVAL; 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci /* enable FIFO precharge */ 6958c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_DISCNTRL1); 6968c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 1); 6978c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DISCNTRL1, reg); 6988c2ecf20Sopenharmony_ci for (i = 0; i < cmd->msg_len; i++) { 6998c2ecf20Sopenharmony_ci /* wait for FIFO empty */ 7008c2ecf20Sopenharmony_ci if (stb0899_wait_diseqc_fifo_empty(state, 100) < 0) 7018c2ecf20Sopenharmony_ci return -ETIMEDOUT; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DISFIFO, cmd->msg[i]); 7048c2ecf20Sopenharmony_ci } 7058c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_DISCNTRL1); 7068c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0); 7078c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DISCNTRL1, reg); 7088c2ecf20Sopenharmony_ci msleep(100); 7098c2ecf20Sopenharmony_ci return 0; 7108c2ecf20Sopenharmony_ci} 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_cistatic int stb0899_wait_diseqc_rxidle(struct stb0899_state *state, int timeout) 7138c2ecf20Sopenharmony_ci{ 7148c2ecf20Sopenharmony_ci u8 reg = 0; 7158c2ecf20Sopenharmony_ci unsigned long start = jiffies; 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci while (!STB0899_GETFIELD(RXEND, reg)) { 7188c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_DISRX_ST0); 7198c2ecf20Sopenharmony_ci if (time_after(jiffies, start + timeout)) { 7208c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_ERROR, 1, "timed out!!"); 7218c2ecf20Sopenharmony_ci return -ETIMEDOUT; 7228c2ecf20Sopenharmony_ci } 7238c2ecf20Sopenharmony_ci msleep(10); 7248c2ecf20Sopenharmony_ci } 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci return 0; 7278c2ecf20Sopenharmony_ci} 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_cistatic int stb0899_recv_slave_reply(struct dvb_frontend *fe, struct dvb_diseqc_slave_reply *reply) 7308c2ecf20Sopenharmony_ci{ 7318c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 7328c2ecf20Sopenharmony_ci u8 reg, length = 0, i; 7338c2ecf20Sopenharmony_ci int result; 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci if (stb0899_wait_diseqc_rxidle(state, 100) < 0) 7368c2ecf20Sopenharmony_ci return -ETIMEDOUT; 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_DISRX_ST0); 7398c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(RXEND, reg)) { 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_DISRX_ST1); 7428c2ecf20Sopenharmony_ci length = STB0899_GETFIELD(FIFOBYTENBR, reg); 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci if (length > sizeof (reply->msg)) { 7458c2ecf20Sopenharmony_ci result = -EOVERFLOW; 7468c2ecf20Sopenharmony_ci goto exit; 7478c2ecf20Sopenharmony_ci } 7488c2ecf20Sopenharmony_ci reply->msg_len = length; 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci /* extract data */ 7518c2ecf20Sopenharmony_ci for (i = 0; i < length; i++) 7528c2ecf20Sopenharmony_ci reply->msg[i] = stb0899_read_reg(state, STB0899_DISFIFO); 7538c2ecf20Sopenharmony_ci } 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci return 0; 7568c2ecf20Sopenharmony_ciexit: 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci return result; 7598c2ecf20Sopenharmony_ci} 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_cistatic int stb0899_wait_diseqc_txidle(struct stb0899_state *state, int timeout) 7628c2ecf20Sopenharmony_ci{ 7638c2ecf20Sopenharmony_ci u8 reg = 0; 7648c2ecf20Sopenharmony_ci unsigned long start = jiffies; 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci while (!STB0899_GETFIELD(TXIDLE, reg)) { 7678c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_DISSTATUS); 7688c2ecf20Sopenharmony_ci if (time_after(jiffies, start + timeout)) { 7698c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_ERROR, 1, "timed out!!"); 7708c2ecf20Sopenharmony_ci return -ETIMEDOUT; 7718c2ecf20Sopenharmony_ci } 7728c2ecf20Sopenharmony_ci msleep(10); 7738c2ecf20Sopenharmony_ci } 7748c2ecf20Sopenharmony_ci return 0; 7758c2ecf20Sopenharmony_ci} 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_cistatic int stb0899_send_diseqc_burst(struct dvb_frontend *fe, 7788c2ecf20Sopenharmony_ci enum fe_sec_mini_cmd burst) 7798c2ecf20Sopenharmony_ci{ 7808c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 7818c2ecf20Sopenharmony_ci u8 reg, old_state; 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci /* wait for diseqc idle */ 7848c2ecf20Sopenharmony_ci if (stb0899_wait_diseqc_txidle(state, 100) < 0) 7858c2ecf20Sopenharmony_ci return -ETIMEDOUT; 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_DISCNTRL1); 7888c2ecf20Sopenharmony_ci old_state = reg; 7898c2ecf20Sopenharmony_ci /* set to burst mode */ 7908c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x03); 7918c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x01); 7928c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DISCNTRL1, reg); 7938c2ecf20Sopenharmony_ci switch (burst) { 7948c2ecf20Sopenharmony_ci case SEC_MINI_A: 7958c2ecf20Sopenharmony_ci /* unmodulated */ 7968c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DISFIFO, 0x00); 7978c2ecf20Sopenharmony_ci break; 7988c2ecf20Sopenharmony_ci case SEC_MINI_B: 7998c2ecf20Sopenharmony_ci /* modulated */ 8008c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DISFIFO, 0xff); 8018c2ecf20Sopenharmony_ci break; 8028c2ecf20Sopenharmony_ci } 8038c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_DISCNTRL1); 8048c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x00); 8058c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DISCNTRL1, reg); 8068c2ecf20Sopenharmony_ci /* wait for diseqc idle */ 8078c2ecf20Sopenharmony_ci if (stb0899_wait_diseqc_txidle(state, 100) < 0) 8088c2ecf20Sopenharmony_ci return -ETIMEDOUT; 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci /* restore state */ 8118c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DISCNTRL1, old_state); 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci return 0; 8148c2ecf20Sopenharmony_ci} 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_cistatic int stb0899_diseqc_init(struct stb0899_state *state) 8178c2ecf20Sopenharmony_ci{ 8188c2ecf20Sopenharmony_ci/* 8198c2ecf20Sopenharmony_ci struct dvb_diseqc_slave_reply rx_data; 8208c2ecf20Sopenharmony_ci*/ 8218c2ecf20Sopenharmony_ci u8 f22_tx, reg; 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci u32 mclk, tx_freq = 22000;/* count = 0, i; */ 8248c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_DISCNTRL2); 8258c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(ONECHIP_TRX, reg, 0); 8268c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DISCNTRL2, reg); 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci /* disable Tx spy */ 8298c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_DISCNTRL1); 8308c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(DISEQCRESET, reg, 1); 8318c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DISCNTRL1, reg); 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_DISCNTRL1); 8348c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(DISEQCRESET, reg, 0); 8358c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DISCNTRL1, reg); 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci mclk = stb0899_get_mclk(state); 8388c2ecf20Sopenharmony_ci f22_tx = mclk / (tx_freq * 32); 8398c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DISF22, f22_tx); /* DiSEqC Tx freq */ 8408c2ecf20Sopenharmony_ci state->rx_freq = 20000; 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci return 0; 8438c2ecf20Sopenharmony_ci} 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_cistatic int stb0899_sleep(struct dvb_frontend *fe) 8468c2ecf20Sopenharmony_ci{ 8478c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 8488c2ecf20Sopenharmony_ci/* 8498c2ecf20Sopenharmony_ci u8 reg; 8508c2ecf20Sopenharmony_ci*/ 8518c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Going to Sleep .. (Really tired .. :-))"); 8528c2ecf20Sopenharmony_ci /* post process event */ 8538c2ecf20Sopenharmony_ci stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 0); 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci return 0; 8568c2ecf20Sopenharmony_ci} 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_cistatic int stb0899_wakeup(struct dvb_frontend *fe) 8598c2ecf20Sopenharmony_ci{ 8608c2ecf20Sopenharmony_ci int rc; 8618c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci if ((rc = stb0899_write_reg(state, STB0899_SYNTCTRL, STB0899_SELOSCI))) 8648c2ecf20Sopenharmony_ci return rc; 8658c2ecf20Sopenharmony_ci /* Activate all clocks; DVB-S2 registers are inaccessible otherwise. */ 8668c2ecf20Sopenharmony_ci if ((rc = stb0899_write_reg(state, STB0899_STOPCLK1, 0x00))) 8678c2ecf20Sopenharmony_ci return rc; 8688c2ecf20Sopenharmony_ci if ((rc = stb0899_write_reg(state, STB0899_STOPCLK2, 0x00))) 8698c2ecf20Sopenharmony_ci return rc; 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci /* post process event */ 8728c2ecf20Sopenharmony_ci stb0899_postproc(state, STB0899_POSTPROC_GPIO_POWER, 1); 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci return 0; 8758c2ecf20Sopenharmony_ci} 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_cistatic int stb0899_init(struct dvb_frontend *fe) 8788c2ecf20Sopenharmony_ci{ 8798c2ecf20Sopenharmony_ci int i; 8808c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 8818c2ecf20Sopenharmony_ci struct stb0899_config *config = state->config; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Initializing STB0899 ... "); 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci /* init device */ 8868c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "init device"); 8878c2ecf20Sopenharmony_ci for (i = 0; config->init_dev[i].address != 0xffff; i++) 8888c2ecf20Sopenharmony_ci stb0899_write_reg(state, config->init_dev[i].address, config->init_dev[i].data); 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "init S2 demod"); 8918c2ecf20Sopenharmony_ci /* init S2 demod */ 8928c2ecf20Sopenharmony_ci for (i = 0; config->init_s2_demod[i].offset != 0xffff; i++) 8938c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2DEMOD, 8948c2ecf20Sopenharmony_ci config->init_s2_demod[i].base_address, 8958c2ecf20Sopenharmony_ci config->init_s2_demod[i].offset, 8968c2ecf20Sopenharmony_ci config->init_s2_demod[i].data); 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "init S1 demod"); 8998c2ecf20Sopenharmony_ci /* init S1 demod */ 9008c2ecf20Sopenharmony_ci for (i = 0; config->init_s1_demod[i].address != 0xffff; i++) 9018c2ecf20Sopenharmony_ci stb0899_write_reg(state, config->init_s1_demod[i].address, config->init_s1_demod[i].data); 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "init S2 FEC"); 9048c2ecf20Sopenharmony_ci /* init S2 fec */ 9058c2ecf20Sopenharmony_ci for (i = 0; config->init_s2_fec[i].offset != 0xffff; i++) 9068c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2FEC, 9078c2ecf20Sopenharmony_ci config->init_s2_fec[i].base_address, 9088c2ecf20Sopenharmony_ci config->init_s2_fec[i].offset, 9098c2ecf20Sopenharmony_ci config->init_s2_fec[i].data); 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "init TST"); 9128c2ecf20Sopenharmony_ci /* init test */ 9138c2ecf20Sopenharmony_ci for (i = 0; config->init_tst[i].address != 0xffff; i++) 9148c2ecf20Sopenharmony_ci stb0899_write_reg(state, config->init_tst[i].address, config->init_tst[i].data); 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci stb0899_init_calc(state); 9178c2ecf20Sopenharmony_ci stb0899_diseqc_init(state); 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci return 0; 9208c2ecf20Sopenharmony_ci} 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_cistatic int stb0899_table_lookup(const struct stb0899_tab *tab, int max, int val) 9238c2ecf20Sopenharmony_ci{ 9248c2ecf20Sopenharmony_ci int res = 0; 9258c2ecf20Sopenharmony_ci int min = 0, med; 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci if (val < tab[min].read) 9288c2ecf20Sopenharmony_ci res = tab[min].real; 9298c2ecf20Sopenharmony_ci else if (val >= tab[max].read) 9308c2ecf20Sopenharmony_ci res = tab[max].real; 9318c2ecf20Sopenharmony_ci else { 9328c2ecf20Sopenharmony_ci while ((max - min) > 1) { 9338c2ecf20Sopenharmony_ci med = (max + min) / 2; 9348c2ecf20Sopenharmony_ci if (val >= tab[min].read && val < tab[med].read) 9358c2ecf20Sopenharmony_ci max = med; 9368c2ecf20Sopenharmony_ci else 9378c2ecf20Sopenharmony_ci min = med; 9388c2ecf20Sopenharmony_ci } 9398c2ecf20Sopenharmony_ci res = ((val - tab[min].read) * 9408c2ecf20Sopenharmony_ci (tab[max].real - tab[min].real) / 9418c2ecf20Sopenharmony_ci (tab[max].read - tab[min].read)) + 9428c2ecf20Sopenharmony_ci tab[min].real; 9438c2ecf20Sopenharmony_ci } 9448c2ecf20Sopenharmony_ci 9458c2ecf20Sopenharmony_ci return res; 9468c2ecf20Sopenharmony_ci} 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_cistatic int stb0899_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 9498c2ecf20Sopenharmony_ci{ 9508c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 9518c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci int val; 9548c2ecf20Sopenharmony_ci u32 reg; 9558c2ecf20Sopenharmony_ci *strength = 0; 9568c2ecf20Sopenharmony_ci switch (state->delsys) { 9578c2ecf20Sopenharmony_ci case SYS_DVBS: 9588c2ecf20Sopenharmony_ci case SYS_DSS: 9598c2ecf20Sopenharmony_ci if (internal->lock) { 9608c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_VSTATUS); 9618c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) { 9628c2ecf20Sopenharmony_ci 9638c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_AGCIQIN); 9648c2ecf20Sopenharmony_ci val = (s32)(s8)STB0899_GETFIELD(AGCIQVALUE, reg); 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci *strength = stb0899_table_lookup(stb0899_dvbsrf_tab, ARRAY_SIZE(stb0899_dvbsrf_tab) - 1, val); 9678c2ecf20Sopenharmony_ci *strength += 750; 9688c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "AGCIQVALUE = 0x%02x, C = %d * 0.1 dBm", 9698c2ecf20Sopenharmony_ci val & 0xff, *strength); 9708c2ecf20Sopenharmony_ci } 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci break; 9738c2ecf20Sopenharmony_ci case SYS_DVBS2: 9748c2ecf20Sopenharmony_ci if (internal->lock) { 9758c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, IF_AGC_GAIN); 9768c2ecf20Sopenharmony_ci val = STB0899_GETFIELD(IF_AGC_GAIN, reg); 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci *strength = stb0899_table_lookup(stb0899_dvbs2rf_tab, ARRAY_SIZE(stb0899_dvbs2rf_tab) - 1, val); 9798c2ecf20Sopenharmony_ci *strength += 950; 9808c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "IF_AGC_GAIN = 0x%04x, C = %d * 0.1 dBm", 9818c2ecf20Sopenharmony_ci val & 0x3fff, *strength); 9828c2ecf20Sopenharmony_ci } 9838c2ecf20Sopenharmony_ci break; 9848c2ecf20Sopenharmony_ci default: 9858c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system"); 9868c2ecf20Sopenharmony_ci return -EINVAL; 9878c2ecf20Sopenharmony_ci } 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_ci return 0; 9908c2ecf20Sopenharmony_ci} 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_cistatic int stb0899_read_snr(struct dvb_frontend *fe, u16 *snr) 9938c2ecf20Sopenharmony_ci{ 9948c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 9958c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci unsigned int val, quant, quantn = -1, est, estn = -1; 9988c2ecf20Sopenharmony_ci u8 buf[2]; 9998c2ecf20Sopenharmony_ci u32 reg; 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci *snr = 0; 10028c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_VSTATUS); 10038c2ecf20Sopenharmony_ci switch (state->delsys) { 10048c2ecf20Sopenharmony_ci case SYS_DVBS: 10058c2ecf20Sopenharmony_ci case SYS_DSS: 10068c2ecf20Sopenharmony_ci if (internal->lock) { 10078c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) { 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_ci stb0899_read_regs(state, STB0899_NIRM, buf, 2); 10108c2ecf20Sopenharmony_ci val = MAKEWORD16(buf[0], buf[1]); 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci *snr = stb0899_table_lookup(stb0899_cn_tab, ARRAY_SIZE(stb0899_cn_tab) - 1, val); 10138c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "NIR = 0x%02x%02x = %u, C/N = %d * 0.1 dBm\n", 10148c2ecf20Sopenharmony_ci buf[0], buf[1], val, *snr); 10158c2ecf20Sopenharmony_ci } 10168c2ecf20Sopenharmony_ci } 10178c2ecf20Sopenharmony_ci break; 10188c2ecf20Sopenharmony_ci case SYS_DVBS2: 10198c2ecf20Sopenharmony_ci if (internal->lock) { 10208c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_CNTRL1); 10218c2ecf20Sopenharmony_ci quant = STB0899_GETFIELD(UWP_ESN0_QUANT, reg); 10228c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, UWP_STAT2); 10238c2ecf20Sopenharmony_ci est = STB0899_GETFIELD(ESN0_EST, reg); 10248c2ecf20Sopenharmony_ci if (est == 1) 10258c2ecf20Sopenharmony_ci val = 301; /* C/N = 30.1 dB */ 10268c2ecf20Sopenharmony_ci else if (est == 2) 10278c2ecf20Sopenharmony_ci val = 270; /* C/N = 27.0 dB */ 10288c2ecf20Sopenharmony_ci else { 10298c2ecf20Sopenharmony_ci /* quantn = 100 * log(quant^2) */ 10308c2ecf20Sopenharmony_ci quantn = stb0899_table_lookup(stb0899_quant_tab, ARRAY_SIZE(stb0899_quant_tab) - 1, quant * 100); 10318c2ecf20Sopenharmony_ci /* estn = 100 * log(est) */ 10328c2ecf20Sopenharmony_ci estn = stb0899_table_lookup(stb0899_est_tab, ARRAY_SIZE(stb0899_est_tab) - 1, est); 10338c2ecf20Sopenharmony_ci /* snr(dBm/10) = -10*(log(est)-log(quant^2)) => snr(dBm/10) = (100*log(quant^2)-100*log(est))/10 */ 10348c2ecf20Sopenharmony_ci val = (quantn - estn) / 10; 10358c2ecf20Sopenharmony_ci } 10368c2ecf20Sopenharmony_ci *snr = val; 10378c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Es/N0 quant = %d (%d) estimate = %u (%d), C/N = %d * 0.1 dBm", 10388c2ecf20Sopenharmony_ci quant, quantn, est, estn, val); 10398c2ecf20Sopenharmony_ci } 10408c2ecf20Sopenharmony_ci break; 10418c2ecf20Sopenharmony_ci default: 10428c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system"); 10438c2ecf20Sopenharmony_ci return -EINVAL; 10448c2ecf20Sopenharmony_ci } 10458c2ecf20Sopenharmony_ci 10468c2ecf20Sopenharmony_ci return 0; 10478c2ecf20Sopenharmony_ci} 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_cistatic int stb0899_read_status(struct dvb_frontend *fe, enum fe_status *status) 10508c2ecf20Sopenharmony_ci{ 10518c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 10528c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 10538c2ecf20Sopenharmony_ci u8 reg; 10548c2ecf20Sopenharmony_ci *status = 0; 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci switch (state->delsys) { 10578c2ecf20Sopenharmony_ci case SYS_DVBS: 10588c2ecf20Sopenharmony_ci case SYS_DSS: 10598c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Delivery system DVB-S/DSS"); 10608c2ecf20Sopenharmony_ci if (internal->lock) { 10618c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_VSTATUS); 10628c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(VSTATUS_LOCKEDVIT, reg)) { 10638c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_CARRIER | FE_HAS_LOCK"); 10648c2ecf20Sopenharmony_ci *status |= FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_LOCK; 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_PLPARM); 10678c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(VITCURPUN, reg)) { 10688c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "--------> FE_HAS_VITERBI | FE_HAS_SYNC"); 10698c2ecf20Sopenharmony_ci *status |= FE_HAS_VITERBI | FE_HAS_SYNC; 10708c2ecf20Sopenharmony_ci /* post process event */ 10718c2ecf20Sopenharmony_ci stb0899_postproc(state, STB0899_POSTPROC_GPIO_LOCK, 1); 10728c2ecf20Sopenharmony_ci } 10738c2ecf20Sopenharmony_ci } 10748c2ecf20Sopenharmony_ci } 10758c2ecf20Sopenharmony_ci break; 10768c2ecf20Sopenharmony_ci case SYS_DVBS2: 10778c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Delivery system DVB-S2"); 10788c2ecf20Sopenharmony_ci if (internal->lock) { 10798c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_STAT2); 10808c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(UWP_LOCK, reg) && STB0899_GETFIELD(CSM_LOCK, reg)) { 10818c2ecf20Sopenharmony_ci *status |= FE_HAS_CARRIER; 10828c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, 10838c2ecf20Sopenharmony_ci "UWP & CSM Lock ! ---> DVB-S2 FE_HAS_CARRIER"); 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_CFGPDELSTATUS1); 10868c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(CFGPDELSTATUS_LOCK, reg)) { 10878c2ecf20Sopenharmony_ci *status |= FE_HAS_LOCK; 10888c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, 10898c2ecf20Sopenharmony_ci "Packet Delineator Locked ! -----> DVB-S2 FE_HAS_LOCK"); 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci } 10928c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(CONTINUOUS_STREAM, reg)) { 10938c2ecf20Sopenharmony_ci *status |= FE_HAS_VITERBI; 10948c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, 10958c2ecf20Sopenharmony_ci "Packet Delineator found VITERBI ! -----> DVB-S2 FE_HAS_VITERBI"); 10968c2ecf20Sopenharmony_ci } 10978c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(ACCEPTED_STREAM, reg)) { 10988c2ecf20Sopenharmony_ci *status |= FE_HAS_SYNC; 10998c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, 11008c2ecf20Sopenharmony_ci "Packet Delineator found SYNC ! -----> DVB-S2 FE_HAS_SYNC"); 11018c2ecf20Sopenharmony_ci /* post process event */ 11028c2ecf20Sopenharmony_ci stb0899_postproc(state, STB0899_POSTPROC_GPIO_LOCK, 1); 11038c2ecf20Sopenharmony_ci } 11048c2ecf20Sopenharmony_ci } 11058c2ecf20Sopenharmony_ci } 11068c2ecf20Sopenharmony_ci break; 11078c2ecf20Sopenharmony_ci default: 11088c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system"); 11098c2ecf20Sopenharmony_ci return -EINVAL; 11108c2ecf20Sopenharmony_ci } 11118c2ecf20Sopenharmony_ci return 0; 11128c2ecf20Sopenharmony_ci} 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci/* 11158c2ecf20Sopenharmony_ci * stb0899_get_error 11168c2ecf20Sopenharmony_ci * viterbi error for DVB-S/DSS 11178c2ecf20Sopenharmony_ci * packet error for DVB-S2 11188c2ecf20Sopenharmony_ci * Bit Error Rate or Packet Error Rate * 10 ^ 7 11198c2ecf20Sopenharmony_ci */ 11208c2ecf20Sopenharmony_cistatic int stb0899_read_ber(struct dvb_frontend *fe, u32 *ber) 11218c2ecf20Sopenharmony_ci{ 11228c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 11238c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci u8 lsb, msb; 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_ci *ber = 0; 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci switch (state->delsys) { 11308c2ecf20Sopenharmony_ci case SYS_DVBS: 11318c2ecf20Sopenharmony_ci case SYS_DSS: 11328c2ecf20Sopenharmony_ci if (internal->lock) { 11338c2ecf20Sopenharmony_ci lsb = stb0899_read_reg(state, STB0899_ECNT1L); 11348c2ecf20Sopenharmony_ci msb = stb0899_read_reg(state, STB0899_ECNT1M); 11358c2ecf20Sopenharmony_ci *ber = MAKEWORD16(msb, lsb); 11368c2ecf20Sopenharmony_ci /* Viterbi Check */ 11378c2ecf20Sopenharmony_ci if (STB0899_GETFIELD(VSTATUS_PRFVIT, internal->v_status)) { 11388c2ecf20Sopenharmony_ci /* Error Rate */ 11398c2ecf20Sopenharmony_ci *ber *= 9766; 11408c2ecf20Sopenharmony_ci /* ber = ber * 10 ^ 7 */ 11418c2ecf20Sopenharmony_ci *ber /= (-1 + (1 << (2 * STB0899_GETFIELD(NOE, internal->err_ctrl)))); 11428c2ecf20Sopenharmony_ci *ber /= 8; 11438c2ecf20Sopenharmony_ci } 11448c2ecf20Sopenharmony_ci } 11458c2ecf20Sopenharmony_ci break; 11468c2ecf20Sopenharmony_ci case SYS_DVBS2: 11478c2ecf20Sopenharmony_ci if (internal->lock) { 11488c2ecf20Sopenharmony_ci lsb = stb0899_read_reg(state, STB0899_ECNT1L); 11498c2ecf20Sopenharmony_ci msb = stb0899_read_reg(state, STB0899_ECNT1M); 11508c2ecf20Sopenharmony_ci *ber = MAKEWORD16(msb, lsb); 11518c2ecf20Sopenharmony_ci /* ber = ber * 10 ^ 7 */ 11528c2ecf20Sopenharmony_ci *ber *= 10000000; 11538c2ecf20Sopenharmony_ci *ber /= (-1 + (1 << (4 + 2 * STB0899_GETFIELD(NOE, internal->err_ctrl)))); 11548c2ecf20Sopenharmony_ci } 11558c2ecf20Sopenharmony_ci break; 11568c2ecf20Sopenharmony_ci default: 11578c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Unsupported delivery system"); 11588c2ecf20Sopenharmony_ci return -EINVAL; 11598c2ecf20Sopenharmony_ci } 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci return 0; 11628c2ecf20Sopenharmony_ci} 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_cistatic int stb0899_set_voltage(struct dvb_frontend *fe, 11658c2ecf20Sopenharmony_ci enum fe_sec_voltage voltage) 11668c2ecf20Sopenharmony_ci{ 11678c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_ci switch (voltage) { 11708c2ecf20Sopenharmony_ci case SEC_VOLTAGE_13: 11718c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_GPIO00CFG, 0x82); 11728c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_GPIO01CFG, 0x02); 11738c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_GPIO02CFG, 0x00); 11748c2ecf20Sopenharmony_ci break; 11758c2ecf20Sopenharmony_ci case SEC_VOLTAGE_18: 11768c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_GPIO00CFG, 0x02); 11778c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_GPIO01CFG, 0x02); 11788c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_GPIO02CFG, 0x82); 11798c2ecf20Sopenharmony_ci break; 11808c2ecf20Sopenharmony_ci case SEC_VOLTAGE_OFF: 11818c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_GPIO00CFG, 0x82); 11828c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_GPIO01CFG, 0x82); 11838c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_GPIO02CFG, 0x82); 11848c2ecf20Sopenharmony_ci break; 11858c2ecf20Sopenharmony_ci default: 11868c2ecf20Sopenharmony_ci return -EINVAL; 11878c2ecf20Sopenharmony_ci } 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci return 0; 11908c2ecf20Sopenharmony_ci} 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_cistatic int stb0899_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone) 11938c2ecf20Sopenharmony_ci{ 11948c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 11958c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci u8 div, reg; 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci /* wait for diseqc idle */ 12008c2ecf20Sopenharmony_ci if (stb0899_wait_diseqc_txidle(state, 100) < 0) 12018c2ecf20Sopenharmony_ci return -ETIMEDOUT; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci switch (tone) { 12048c2ecf20Sopenharmony_ci case SEC_TONE_ON: 12058c2ecf20Sopenharmony_ci div = (internal->master_clk / 100) / 5632; 12068c2ecf20Sopenharmony_ci div = (div + 5) / 10; 12078c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DISEQCOCFG, 0x66); 12088c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_ACRPRESC); 12098c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(ACRPRESC, reg, 0x03); 12108c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_ACRPRESC, reg); 12118c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_ACRDIV1, div); 12128c2ecf20Sopenharmony_ci break; 12138c2ecf20Sopenharmony_ci case SEC_TONE_OFF: 12148c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_DISEQCOCFG, 0x20); 12158c2ecf20Sopenharmony_ci break; 12168c2ecf20Sopenharmony_ci default: 12178c2ecf20Sopenharmony_ci return -EINVAL; 12188c2ecf20Sopenharmony_ci } 12198c2ecf20Sopenharmony_ci return 0; 12208c2ecf20Sopenharmony_ci} 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ciint stb0899_i2c_gate_ctrl(struct dvb_frontend *fe, int enable) 12238c2ecf20Sopenharmony_ci{ 12248c2ecf20Sopenharmony_ci int i2c_stat; 12258c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_ci i2c_stat = stb0899_read_reg(state, STB0899_I2CRPT); 12288c2ecf20Sopenharmony_ci if (i2c_stat < 0) 12298c2ecf20Sopenharmony_ci goto err; 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci if (enable) { 12328c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Enabling I2C Repeater ..."); 12338c2ecf20Sopenharmony_ci i2c_stat |= STB0899_I2CTON; 12348c2ecf20Sopenharmony_ci if (stb0899_write_reg(state, STB0899_I2CRPT, i2c_stat) < 0) 12358c2ecf20Sopenharmony_ci goto err; 12368c2ecf20Sopenharmony_ci } else { 12378c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Disabling I2C Repeater ..."); 12388c2ecf20Sopenharmony_ci i2c_stat &= ~STB0899_I2CTON; 12398c2ecf20Sopenharmony_ci if (stb0899_write_reg(state, STB0899_I2CRPT, i2c_stat) < 0) 12408c2ecf20Sopenharmony_ci goto err; 12418c2ecf20Sopenharmony_ci } 12428c2ecf20Sopenharmony_ci return 0; 12438c2ecf20Sopenharmony_cierr: 12448c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_ERROR, 1, "I2C Repeater control failed"); 12458c2ecf20Sopenharmony_ci return -EREMOTEIO; 12468c2ecf20Sopenharmony_ci} 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_cistatic inline void CONVERT32(u32 x, char *str) 12508c2ecf20Sopenharmony_ci{ 12518c2ecf20Sopenharmony_ci *str++ = (x >> 24) & 0xff; 12528c2ecf20Sopenharmony_ci *str++ = (x >> 16) & 0xff; 12538c2ecf20Sopenharmony_ci *str++ = (x >> 8) & 0xff; 12548c2ecf20Sopenharmony_ci *str++ = (x >> 0) & 0xff; 12558c2ecf20Sopenharmony_ci *str = '\0'; 12568c2ecf20Sopenharmony_ci} 12578c2ecf20Sopenharmony_ci 12588c2ecf20Sopenharmony_cistatic int stb0899_get_dev_id(struct stb0899_state *state) 12598c2ecf20Sopenharmony_ci{ 12608c2ecf20Sopenharmony_ci u8 chip_id, release; 12618c2ecf20Sopenharmony_ci u16 id; 12628c2ecf20Sopenharmony_ci u32 demod_ver = 0, fec_ver = 0; 12638c2ecf20Sopenharmony_ci char demod_str[5] = { 0 }; 12648c2ecf20Sopenharmony_ci char fec_str[5] = { 0 }; 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci id = stb0899_read_reg(state, STB0899_DEV_ID); 12678c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "ID reg=[0x%02x]", id); 12688c2ecf20Sopenharmony_ci chip_id = STB0899_GETFIELD(CHIP_ID, id); 12698c2ecf20Sopenharmony_ci release = STB0899_GETFIELD(CHIP_REL, id); 12708c2ecf20Sopenharmony_ci 12718c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_ERROR, 1, "Device ID=[%d], Release=[%d]", 12728c2ecf20Sopenharmony_ci chip_id, release); 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_ci CONVERT32(STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_CORE_ID), (char *)&demod_str); 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ci demod_ver = STB0899_READ_S2REG(STB0899_S2DEMOD, DMD_VERSION_ID); 12778c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_ERROR, 1, "Demodulator Core ID=[%s], Version=[%d]", (char *) &demod_str, demod_ver); 12788c2ecf20Sopenharmony_ci CONVERT32(STB0899_READ_S2REG(STB0899_S2FEC, FEC_CORE_ID_REG), (char *)&fec_str); 12798c2ecf20Sopenharmony_ci fec_ver = STB0899_READ_S2REG(STB0899_S2FEC, FEC_VER_ID_REG); 12808c2ecf20Sopenharmony_ci if (! (chip_id > 0)) { 12818c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_ERROR, 1, "couldn't find a STB 0899"); 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci return -ENODEV; 12848c2ecf20Sopenharmony_ci } 12858c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_ERROR, 1, "FEC Core ID=[%s], Version=[%d]", (char*) &fec_str, fec_ver); 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci return 0; 12888c2ecf20Sopenharmony_ci} 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_cistatic void stb0899_set_delivery(struct stb0899_state *state) 12918c2ecf20Sopenharmony_ci{ 12928c2ecf20Sopenharmony_ci u8 reg; 12938c2ecf20Sopenharmony_ci u8 stop_clk[2]; 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci stop_clk[0] = stb0899_read_reg(state, STB0899_STOPCLK1); 12968c2ecf20Sopenharmony_ci stop_clk[1] = stb0899_read_reg(state, STB0899_STOPCLK2); 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_ci switch (state->delsys) { 12998c2ecf20Sopenharmony_ci case SYS_DVBS: 13008c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Delivery System -- DVB-S"); 13018c2ecf20Sopenharmony_ci /* FECM/Viterbi ON */ 13028c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_FECM); 13038c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 0); 13048c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 1); 13058c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_FECM, reg); 13068c2ecf20Sopenharmony_ci 13078c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_RSULC, 0xb1); 13088c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_TSULC, 0x40); 13098c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_RSLLC, 0x42); 13108c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_TSLPL, 0x12); 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_TSTRES); 13138c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FRESLDPC, reg, 1); 13148c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_TSTRES, reg); 13158c2ecf20Sopenharmony_ci 13168c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1); 13178c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 1); 13188c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 1); 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 1); 13218c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 1); 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKINTBUF216, stop_clk[0], 1); 13248c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0); 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 1); 13278c2ecf20Sopenharmony_ci break; 13288c2ecf20Sopenharmony_ci case SYS_DVBS2: 13298c2ecf20Sopenharmony_ci /* FECM/Viterbi OFF */ 13308c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_FECM); 13318c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 0); 13328c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 0); 13338c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_FECM, reg); 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_RSULC, 0xb1); 13368c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_TSULC, 0x42); 13378c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_RSLLC, 0x40); 13388c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_TSLPL, 0x02); 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_TSTRES); 13418c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FRESLDPC, reg, 0); 13428c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_TSTRES, reg); 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1); 13458c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 0); 13468c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 0); 13478c2ecf20Sopenharmony_ci 13488c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 0); 13498c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 0); 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKINTBUF216, stop_clk[0], 0); 13528c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0); 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 0); 13558c2ecf20Sopenharmony_ci break; 13568c2ecf20Sopenharmony_ci case SYS_DSS: 13578c2ecf20Sopenharmony_ci /* FECM/Viterbi ON */ 13588c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_FECM); 13598c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FECM_RSVD0, reg, 1); 13608c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FECM_VITERBI_ON, reg, 1); 13618c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_FECM, reg); 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_RSULC, 0xa1); 13648c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_TSULC, 0x61); 13658c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_RSLLC, 0x42); 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci reg = stb0899_read_reg(state, STB0899_TSTRES); 13688c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(FRESLDPC, reg, 1); 13698c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_TSTRES, reg); 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CHK8PSK, stop_clk[0], 1); 13728c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKFEC108, stop_clk[0], 1); 13738c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKFEC216, stop_clk[0], 1); 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKPKDLIN108, stop_clk[1], 1); 13768c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKPKDLIN216, stop_clk[1], 1); 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKCORE216, stop_clk[0], 0); 13798c2ecf20Sopenharmony_ci 13808c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKS2DMD108, stop_clk[1], 1); 13818c2ecf20Sopenharmony_ci break; 13828c2ecf20Sopenharmony_ci default: 13838c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_ERROR, 1, "Unsupported delivery system"); 13848c2ecf20Sopenharmony_ci break; 13858c2ecf20Sopenharmony_ci } 13868c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(STOP_CKADCI108, stop_clk[0], 0); 13878c2ecf20Sopenharmony_ci stb0899_write_regs(state, STB0899_STOPCLK1, stop_clk, 2); 13888c2ecf20Sopenharmony_ci} 13898c2ecf20Sopenharmony_ci 13908c2ecf20Sopenharmony_ci/* 13918c2ecf20Sopenharmony_ci * stb0899_set_iterations 13928c2ecf20Sopenharmony_ci * set the LDPC iteration scale function 13938c2ecf20Sopenharmony_ci */ 13948c2ecf20Sopenharmony_cistatic void stb0899_set_iterations(struct stb0899_state *state) 13958c2ecf20Sopenharmony_ci{ 13968c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 13978c2ecf20Sopenharmony_ci struct stb0899_config *config = state->config; 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci s32 iter_scale; 14008c2ecf20Sopenharmony_ci u32 reg; 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci iter_scale = 17 * (internal->master_clk / 1000); 14038c2ecf20Sopenharmony_ci iter_scale += 410000; 14048c2ecf20Sopenharmony_ci iter_scale /= (internal->srate / 1000000); 14058c2ecf20Sopenharmony_ci iter_scale /= 1000; 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci if (iter_scale > config->ldpc_max_iter) 14088c2ecf20Sopenharmony_ci iter_scale = config->ldpc_max_iter; 14098c2ecf20Sopenharmony_ci 14108c2ecf20Sopenharmony_ci reg = STB0899_READ_S2REG(STB0899_S2FEC, MAX_ITER); 14118c2ecf20Sopenharmony_ci STB0899_SETFIELD_VAL(MAX_ITERATIONS, reg, iter_scale); 14128c2ecf20Sopenharmony_ci stb0899_write_s2reg(state, STB0899_S2FEC, STB0899_BASE_MAX_ITER, STB0899_OFF0_MAX_ITER, reg); 14138c2ecf20Sopenharmony_ci} 14148c2ecf20Sopenharmony_ci 14158c2ecf20Sopenharmony_cistatic enum dvbfe_search stb0899_search(struct dvb_frontend *fe) 14168c2ecf20Sopenharmony_ci{ 14178c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 14188c2ecf20Sopenharmony_ci struct stb0899_params *i_params = &state->params; 14198c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 14208c2ecf20Sopenharmony_ci struct stb0899_config *config = state->config; 14218c2ecf20Sopenharmony_ci struct dtv_frontend_properties *props = &fe->dtv_property_cache; 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci u32 SearchRange, gain; 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_ci i_params->freq = props->frequency; 14268c2ecf20Sopenharmony_ci i_params->srate = props->symbol_rate; 14278c2ecf20Sopenharmony_ci state->delsys = props->delivery_system; 14288c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "delivery system=%d", state->delsys); 14298c2ecf20Sopenharmony_ci 14308c2ecf20Sopenharmony_ci SearchRange = 10000000; 14318c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Frequency=%d, Srate=%d", i_params->freq, i_params->srate); 14328c2ecf20Sopenharmony_ci /* checking Search Range is meaningless for a fixed 3 Mhz */ 14338c2ecf20Sopenharmony_ci if (INRANGE(i_params->srate, 1000000, 45000000)) { 14348c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Parameters IN RANGE"); 14358c2ecf20Sopenharmony_ci stb0899_set_delivery(state); 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci if (state->config->tuner_set_rfsiggain) { 14388c2ecf20Sopenharmony_ci if (internal->srate > 15000000) 14398c2ecf20Sopenharmony_ci gain = 8; /* 15Mb < srate < 45Mb, gain = 8dB */ 14408c2ecf20Sopenharmony_ci else if (internal->srate > 5000000) 14418c2ecf20Sopenharmony_ci gain = 12; /* 5Mb < srate < 15Mb, gain = 12dB */ 14428c2ecf20Sopenharmony_ci else 14438c2ecf20Sopenharmony_ci gain = 14; /* 1Mb < srate < 5Mb, gain = 14db */ 14448c2ecf20Sopenharmony_ci state->config->tuner_set_rfsiggain(fe, gain); 14458c2ecf20Sopenharmony_ci } 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci if (i_params->srate <= 5000000) 14488c2ecf20Sopenharmony_ci stb0899_set_mclk(state, config->lo_clk); 14498c2ecf20Sopenharmony_ci else 14508c2ecf20Sopenharmony_ci stb0899_set_mclk(state, config->hi_clk); 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci switch (state->delsys) { 14538c2ecf20Sopenharmony_ci case SYS_DVBS: 14548c2ecf20Sopenharmony_ci case SYS_DSS: 14558c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "DVB-S delivery system"); 14568c2ecf20Sopenharmony_ci internal->freq = i_params->freq; 14578c2ecf20Sopenharmony_ci internal->srate = i_params->srate; 14588c2ecf20Sopenharmony_ci /* 14598c2ecf20Sopenharmony_ci * search = user search range + 14608c2ecf20Sopenharmony_ci * 500Khz + 14618c2ecf20Sopenharmony_ci * 2 * Tuner_step_size + 14628c2ecf20Sopenharmony_ci * 10% of the symbol rate 14638c2ecf20Sopenharmony_ci */ 14648c2ecf20Sopenharmony_ci internal->srch_range = SearchRange + 1500000 + (i_params->srate / 5); 14658c2ecf20Sopenharmony_ci internal->derot_percent = 30; 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci /* What to do for tuners having no bandwidth setup ? */ 14688c2ecf20Sopenharmony_ci /* enable tuner I/O */ 14698c2ecf20Sopenharmony_ci stb0899_i2c_gate_ctrl(&state->frontend, 1); 14708c2ecf20Sopenharmony_ci 14718c2ecf20Sopenharmony_ci if (state->config->tuner_set_bandwidth) 14728c2ecf20Sopenharmony_ci state->config->tuner_set_bandwidth(fe, (13 * (stb0899_carr_width(state) + SearchRange)) / 10); 14738c2ecf20Sopenharmony_ci if (state->config->tuner_get_bandwidth) 14748c2ecf20Sopenharmony_ci state->config->tuner_get_bandwidth(fe, &internal->tuner_bw); 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_ci /* disable tuner I/O */ 14778c2ecf20Sopenharmony_ci stb0899_i2c_gate_ctrl(&state->frontend, 0); 14788c2ecf20Sopenharmony_ci 14798c2ecf20Sopenharmony_ci /* Set DVB-S1 AGC */ 14808c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_AGCRFCFG, 0x11); 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_ci /* Run the search algorithm */ 14838c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "running DVB-S search algo .."); 14848c2ecf20Sopenharmony_ci if (stb0899_dvbs_algo(state) == RANGEOK) { 14858c2ecf20Sopenharmony_ci internal->lock = 1; 14868c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, 14878c2ecf20Sopenharmony_ci "-------------------------------------> DVB-S LOCK !"); 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci// stb0899_write_reg(state, STB0899_ERRCTRL1, 0x3d); /* Viterbi Errors */ 14908c2ecf20Sopenharmony_ci// internal->v_status = stb0899_read_reg(state, STB0899_VSTATUS); 14918c2ecf20Sopenharmony_ci// internal->err_ctrl = stb0899_read_reg(state, STB0899_ERRCTRL1); 14928c2ecf20Sopenharmony_ci// dprintk(state->verbose, FE_DEBUG, 1, "VSTATUS=0x%02x", internal->v_status); 14938c2ecf20Sopenharmony_ci// dprintk(state->verbose, FE_DEBUG, 1, "ERR_CTRL=0x%02x", internal->err_ctrl); 14948c2ecf20Sopenharmony_ci 14958c2ecf20Sopenharmony_ci return DVBFE_ALGO_SEARCH_SUCCESS; 14968c2ecf20Sopenharmony_ci } else { 14978c2ecf20Sopenharmony_ci internal->lock = 0; 14988c2ecf20Sopenharmony_ci 14998c2ecf20Sopenharmony_ci return DVBFE_ALGO_SEARCH_FAILED; 15008c2ecf20Sopenharmony_ci } 15018c2ecf20Sopenharmony_ci break; 15028c2ecf20Sopenharmony_ci case SYS_DVBS2: 15038c2ecf20Sopenharmony_ci internal->freq = i_params->freq; 15048c2ecf20Sopenharmony_ci internal->srate = i_params->srate; 15058c2ecf20Sopenharmony_ci internal->srch_range = SearchRange; 15068c2ecf20Sopenharmony_ci 15078c2ecf20Sopenharmony_ci /* enable tuner I/O */ 15088c2ecf20Sopenharmony_ci stb0899_i2c_gate_ctrl(&state->frontend, 1); 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci if (state->config->tuner_set_bandwidth) 15118c2ecf20Sopenharmony_ci state->config->tuner_set_bandwidth(fe, (stb0899_carr_width(state) + SearchRange)); 15128c2ecf20Sopenharmony_ci if (state->config->tuner_get_bandwidth) 15138c2ecf20Sopenharmony_ci state->config->tuner_get_bandwidth(fe, &internal->tuner_bw); 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_ci /* disable tuner I/O */ 15168c2ecf20Sopenharmony_ci stb0899_i2c_gate_ctrl(&state->frontend, 0); 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci// pParams->SpectralInv = pSearch->IQ_Inversion; 15198c2ecf20Sopenharmony_ci 15208c2ecf20Sopenharmony_ci /* Set DVB-S2 AGC */ 15218c2ecf20Sopenharmony_ci stb0899_write_reg(state, STB0899_AGCRFCFG, 0x1c); 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_ci /* Set IterScale =f(MCLK,SYMB) */ 15248c2ecf20Sopenharmony_ci stb0899_set_iterations(state); 15258c2ecf20Sopenharmony_ci 15268c2ecf20Sopenharmony_ci /* Run the search algorithm */ 15278c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "running DVB-S2 search algo .."); 15288c2ecf20Sopenharmony_ci if (stb0899_dvbs2_algo(state) == DVBS2_FEC_LOCK) { 15298c2ecf20Sopenharmony_ci internal->lock = 1; 15308c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, 15318c2ecf20Sopenharmony_ci "-------------------------------------> DVB-S2 LOCK !"); 15328c2ecf20Sopenharmony_ci 15338c2ecf20Sopenharmony_ci// stb0899_write_reg(state, STB0899_ERRCTRL1, 0xb6); /* Packet Errors */ 15348c2ecf20Sopenharmony_ci// internal->v_status = stb0899_read_reg(state, STB0899_VSTATUS); 15358c2ecf20Sopenharmony_ci// internal->err_ctrl = stb0899_read_reg(state, STB0899_ERRCTRL1); 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_ci return DVBFE_ALGO_SEARCH_SUCCESS; 15388c2ecf20Sopenharmony_ci } else { 15398c2ecf20Sopenharmony_ci internal->lock = 0; 15408c2ecf20Sopenharmony_ci 15418c2ecf20Sopenharmony_ci return DVBFE_ALGO_SEARCH_FAILED; 15428c2ecf20Sopenharmony_ci } 15438c2ecf20Sopenharmony_ci break; 15448c2ecf20Sopenharmony_ci default: 15458c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_ERROR, 1, "Unsupported delivery system"); 15468c2ecf20Sopenharmony_ci return DVBFE_ALGO_SEARCH_INVALID; 15478c2ecf20Sopenharmony_ci } 15488c2ecf20Sopenharmony_ci } 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci return DVBFE_ALGO_SEARCH_ERROR; 15518c2ecf20Sopenharmony_ci} 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_cistatic int stb0899_get_frontend(struct dvb_frontend *fe, 15548c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p) 15558c2ecf20Sopenharmony_ci{ 15568c2ecf20Sopenharmony_ci struct stb0899_state *state = fe->demodulator_priv; 15578c2ecf20Sopenharmony_ci struct stb0899_internal *internal = &state->internal; 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci dprintk(state->verbose, FE_DEBUG, 1, "Get params"); 15608c2ecf20Sopenharmony_ci p->symbol_rate = internal->srate; 15618c2ecf20Sopenharmony_ci p->frequency = internal->freq; 15628c2ecf20Sopenharmony_ci 15638c2ecf20Sopenharmony_ci return 0; 15648c2ecf20Sopenharmony_ci} 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_cistatic enum dvbfe_algo stb0899_frontend_algo(struct dvb_frontend *fe) 15678c2ecf20Sopenharmony_ci{ 15688c2ecf20Sopenharmony_ci return DVBFE_ALGO_CUSTOM; 15698c2ecf20Sopenharmony_ci} 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops stb0899_ops = { 15728c2ecf20Sopenharmony_ci .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, 15738c2ecf20Sopenharmony_ci .info = { 15748c2ecf20Sopenharmony_ci .name = "STB0899 Multistandard", 15758c2ecf20Sopenharmony_ci .frequency_min_hz = 950 * MHz, 15768c2ecf20Sopenharmony_ci .frequency_max_hz = 2150 * MHz, 15778c2ecf20Sopenharmony_ci .symbol_rate_min = 5000000, 15788c2ecf20Sopenharmony_ci .symbol_rate_max = 45000000, 15798c2ecf20Sopenharmony_ci 15808c2ecf20Sopenharmony_ci .caps = FE_CAN_INVERSION_AUTO | 15818c2ecf20Sopenharmony_ci FE_CAN_FEC_AUTO | 15828c2ecf20Sopenharmony_ci FE_CAN_2G_MODULATION | 15838c2ecf20Sopenharmony_ci FE_CAN_QPSK 15848c2ecf20Sopenharmony_ci }, 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ci .detach = stb0899_detach, 15878c2ecf20Sopenharmony_ci .release = stb0899_release, 15888c2ecf20Sopenharmony_ci .init = stb0899_init, 15898c2ecf20Sopenharmony_ci .sleep = stb0899_sleep, 15908c2ecf20Sopenharmony_ci// .wakeup = stb0899_wakeup, 15918c2ecf20Sopenharmony_ci 15928c2ecf20Sopenharmony_ci .i2c_gate_ctrl = stb0899_i2c_gate_ctrl, 15938c2ecf20Sopenharmony_ci 15948c2ecf20Sopenharmony_ci .get_frontend_algo = stb0899_frontend_algo, 15958c2ecf20Sopenharmony_ci .search = stb0899_search, 15968c2ecf20Sopenharmony_ci .get_frontend = stb0899_get_frontend, 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci 15998c2ecf20Sopenharmony_ci .read_status = stb0899_read_status, 16008c2ecf20Sopenharmony_ci .read_snr = stb0899_read_snr, 16018c2ecf20Sopenharmony_ci .read_signal_strength = stb0899_read_signal_strength, 16028c2ecf20Sopenharmony_ci .read_ber = stb0899_read_ber, 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci .set_voltage = stb0899_set_voltage, 16058c2ecf20Sopenharmony_ci .set_tone = stb0899_set_tone, 16068c2ecf20Sopenharmony_ci 16078c2ecf20Sopenharmony_ci .diseqc_send_master_cmd = stb0899_send_diseqc_msg, 16088c2ecf20Sopenharmony_ci .diseqc_recv_slave_reply = stb0899_recv_slave_reply, 16098c2ecf20Sopenharmony_ci .diseqc_send_burst = stb0899_send_diseqc_burst, 16108c2ecf20Sopenharmony_ci}; 16118c2ecf20Sopenharmony_ci 16128c2ecf20Sopenharmony_cistruct dvb_frontend *stb0899_attach(struct stb0899_config *config, struct i2c_adapter *i2c) 16138c2ecf20Sopenharmony_ci{ 16148c2ecf20Sopenharmony_ci struct stb0899_state *state = NULL; 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci state = kzalloc(sizeof (struct stb0899_state), GFP_KERNEL); 16178c2ecf20Sopenharmony_ci if (state == NULL) 16188c2ecf20Sopenharmony_ci goto error; 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci state->verbose = &verbose; 16218c2ecf20Sopenharmony_ci state->config = config; 16228c2ecf20Sopenharmony_ci state->i2c = i2c; 16238c2ecf20Sopenharmony_ci state->frontend.ops = stb0899_ops; 16248c2ecf20Sopenharmony_ci state->frontend.demodulator_priv = state; 16258c2ecf20Sopenharmony_ci /* use configured inversion as default -- we'll later autodetect inversion */ 16268c2ecf20Sopenharmony_ci state->internal.inversion = config->inversion; 16278c2ecf20Sopenharmony_ci 16288c2ecf20Sopenharmony_ci stb0899_wakeup(&state->frontend); 16298c2ecf20Sopenharmony_ci if (stb0899_get_dev_id(state) == -ENODEV) { 16308c2ecf20Sopenharmony_ci printk("%s: Exiting .. !\n", __func__); 16318c2ecf20Sopenharmony_ci goto error; 16328c2ecf20Sopenharmony_ci } 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci printk("%s: Attaching STB0899 \n", __func__); 16358c2ecf20Sopenharmony_ci return &state->frontend; 16368c2ecf20Sopenharmony_ci 16378c2ecf20Sopenharmony_cierror: 16388c2ecf20Sopenharmony_ci kfree(state); 16398c2ecf20Sopenharmony_ci return NULL; 16408c2ecf20Sopenharmony_ci} 16418c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(stb0899_attach); 16428c2ecf20Sopenharmony_ciMODULE_PARM_DESC(verbose, "Set Verbosity level"); 16438c2ecf20Sopenharmony_ciMODULE_AUTHOR("Manu Abraham"); 16448c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("STB0899 Multi-Std frontend"); 16458c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1646