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