18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci Frontend/Card driver for TwinHan DST Frontend 48c2ecf20Sopenharmony_ci Copyright (C) 2003 Jamie Honan 58c2ecf20Sopenharmony_ci Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com) 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci*/ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/init.h> 148c2ecf20Sopenharmony_ci#include <linux/string.h> 158c2ecf20Sopenharmony_ci#include <linux/slab.h> 168c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 178c2ecf20Sopenharmony_ci#include <linux/delay.h> 188c2ecf20Sopenharmony_ci#include <asm/div64.h> 198c2ecf20Sopenharmony_ci#include <media/dvb_frontend.h> 208c2ecf20Sopenharmony_ci#include "dst_priv.h" 218c2ecf20Sopenharmony_ci#include "dst_common.h" 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic unsigned int verbose; 248c2ecf20Sopenharmony_cimodule_param(verbose, int, 0644); 258c2ecf20Sopenharmony_ciMODULE_PARM_DESC(verbose, "verbosity level (0 to 3)"); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistatic unsigned int dst_addons; 288c2ecf20Sopenharmony_cimodule_param(dst_addons, int, 0644); 298c2ecf20Sopenharmony_ciMODULE_PARM_DESC(dst_addons, "CA daughterboard, default is 0 (No addons)"); 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic unsigned int dst_algo; 328c2ecf20Sopenharmony_cimodule_param(dst_algo, int, 0644); 338c2ecf20Sopenharmony_ciMODULE_PARM_DESC(dst_algo, "tuning algo: default is 0=(SW), 1=(HW)"); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define HAS_LOCK 1 368c2ecf20Sopenharmony_ci#define ATTEMPT_TUNE 2 378c2ecf20Sopenharmony_ci#define HAS_POWER 4 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#define dprintk(level, fmt, arg...) do { \ 408c2ecf20Sopenharmony_ci if (level >= verbose) \ 418c2ecf20Sopenharmony_ci printk(KERN_DEBUG pr_fmt("%s: " fmt), \ 428c2ecf20Sopenharmony_ci __func__, ##arg); \ 438c2ecf20Sopenharmony_ci} while(0) 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic int dst_command(struct dst_state *state, u8 *data, u8 len); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cistatic void dst_packsize(struct dst_state *state, int psize) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci union dst_gpio_packet bits; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci bits.psize = psize; 528c2ecf20Sopenharmony_ci bt878_device_control(state->bt, DST_IG_TS, &bits); 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic int dst_gpio_outb(struct dst_state *state, u32 mask, u32 enbb, 568c2ecf20Sopenharmony_ci u32 outhigh, int delay) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci union dst_gpio_packet enb; 598c2ecf20Sopenharmony_ci union dst_gpio_packet bits; 608c2ecf20Sopenharmony_ci int err; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci enb.enb.mask = mask; 638c2ecf20Sopenharmony_ci enb.enb.enable = enbb; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci dprintk(2, "mask=[%04x], enbb=[%04x], outhigh=[%04x]\n", 668c2ecf20Sopenharmony_ci mask, enbb, outhigh); 678c2ecf20Sopenharmony_ci if ((err = bt878_device_control(state->bt, DST_IG_ENABLE, &enb)) < 0) { 688c2ecf20Sopenharmony_ci dprintk(2, "dst_gpio_enb error (err == %i, mask == %02x, enb == %02x)\n", 698c2ecf20Sopenharmony_ci err, mask, enbb); 708c2ecf20Sopenharmony_ci return -EREMOTEIO; 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci udelay(1000); 738c2ecf20Sopenharmony_ci /* because complete disabling means no output, no need to do output packet */ 748c2ecf20Sopenharmony_ci if (enbb == 0) 758c2ecf20Sopenharmony_ci return 0; 768c2ecf20Sopenharmony_ci if (delay) 778c2ecf20Sopenharmony_ci msleep(10); 788c2ecf20Sopenharmony_ci bits.outp.mask = enbb; 798c2ecf20Sopenharmony_ci bits.outp.highvals = outhigh; 808c2ecf20Sopenharmony_ci if ((err = bt878_device_control(state->bt, DST_IG_WRITE, &bits)) < 0) { 818c2ecf20Sopenharmony_ci dprintk(2, "dst_gpio_outb error (err == %i, enbb == %02x, outhigh == %02x)\n", 828c2ecf20Sopenharmony_ci err, enbb, outhigh); 838c2ecf20Sopenharmony_ci return -EREMOTEIO; 848c2ecf20Sopenharmony_ci } 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci return 0; 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic int dst_gpio_inb(struct dst_state *state, u8 *result) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci union dst_gpio_packet rd_packet; 928c2ecf20Sopenharmony_ci int err; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci *result = 0; 958c2ecf20Sopenharmony_ci if ((err = bt878_device_control(state->bt, DST_IG_READ, &rd_packet)) < 0) { 968c2ecf20Sopenharmony_ci pr_err("dst_gpio_inb error (err == %i)\n", err); 978c2ecf20Sopenharmony_ci return -EREMOTEIO; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci *result = (u8) rd_packet.rd.value; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci return 0; 1028c2ecf20Sopenharmony_ci} 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ciint rdc_reset_state(struct dst_state *state) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci dprintk(2, "Resetting state machine\n"); 1078c2ecf20Sopenharmony_ci if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, 0, NO_DELAY) < 0) { 1088c2ecf20Sopenharmony_ci pr_err("dst_gpio_outb ERROR !\n"); 1098c2ecf20Sopenharmony_ci return -1; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci msleep(10); 1128c2ecf20Sopenharmony_ci if (dst_gpio_outb(state, RDC_8820_INT, RDC_8820_INT, RDC_8820_INT, NO_DELAY) < 0) { 1138c2ecf20Sopenharmony_ci pr_err("dst_gpio_outb ERROR !\n"); 1148c2ecf20Sopenharmony_ci msleep(10); 1158c2ecf20Sopenharmony_ci return -1; 1168c2ecf20Sopenharmony_ci } 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci return 0; 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ciEXPORT_SYMBOL(rdc_reset_state); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistatic int rdc_8820_reset(struct dst_state *state) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci dprintk(3, "Resetting DST\n"); 1258c2ecf20Sopenharmony_ci if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, 0, NO_DELAY) < 0) { 1268c2ecf20Sopenharmony_ci pr_err("dst_gpio_outb ERROR !\n"); 1278c2ecf20Sopenharmony_ci return -1; 1288c2ecf20Sopenharmony_ci } 1298c2ecf20Sopenharmony_ci udelay(1000); 1308c2ecf20Sopenharmony_ci if (dst_gpio_outb(state, RDC_8820_RESET, RDC_8820_RESET, RDC_8820_RESET, DELAY) < 0) { 1318c2ecf20Sopenharmony_ci pr_err("dst_gpio_outb ERROR !\n"); 1328c2ecf20Sopenharmony_ci return -1; 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci return 0; 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic int dst_pio_enable(struct dst_state *state) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_ENABLE, 0, NO_DELAY) < 0) { 1418c2ecf20Sopenharmony_ci pr_err("dst_gpio_outb ERROR !\n"); 1428c2ecf20Sopenharmony_ci return -1; 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci udelay(1000); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci return 0; 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ciint dst_pio_disable(struct dst_state *state) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci if (dst_gpio_outb(state, ~0, RDC_8820_PIO_0_DISABLE, RDC_8820_PIO_0_DISABLE, NO_DELAY) < 0) { 1528c2ecf20Sopenharmony_ci pr_err("dst_gpio_outb ERROR !\n"); 1538c2ecf20Sopenharmony_ci return -1; 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_FW_1) 1568c2ecf20Sopenharmony_ci udelay(1000); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci return 0; 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dst_pio_disable); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ciint dst_wait_dst_ready(struct dst_state *state, u8 delay_mode) 1638c2ecf20Sopenharmony_ci{ 1648c2ecf20Sopenharmony_ci u8 reply; 1658c2ecf20Sopenharmony_ci int i; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci for (i = 0; i < 200; i++) { 1688c2ecf20Sopenharmony_ci if (dst_gpio_inb(state, &reply) < 0) { 1698c2ecf20Sopenharmony_ci pr_err("dst_gpio_inb ERROR !\n"); 1708c2ecf20Sopenharmony_ci return -1; 1718c2ecf20Sopenharmony_ci } 1728c2ecf20Sopenharmony_ci if ((reply & RDC_8820_PIO_0_ENABLE) == 0) { 1738c2ecf20Sopenharmony_ci dprintk(2, "dst wait ready after %d\n", i); 1748c2ecf20Sopenharmony_ci return 1; 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci msleep(10); 1778c2ecf20Sopenharmony_ci } 1788c2ecf20Sopenharmony_ci dprintk(1, "dst wait NOT ready after %d\n", i); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci return 0; 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dst_wait_dst_ready); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ciint dst_error_recovery(struct dst_state *state) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci dprintk(1, "Trying to return from previous errors.\n"); 1878c2ecf20Sopenharmony_ci dst_pio_disable(state); 1888c2ecf20Sopenharmony_ci msleep(10); 1898c2ecf20Sopenharmony_ci dst_pio_enable(state); 1908c2ecf20Sopenharmony_ci msleep(10); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci return 0; 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dst_error_recovery); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ciint dst_error_bailout(struct dst_state *state) 1978c2ecf20Sopenharmony_ci{ 1988c2ecf20Sopenharmony_ci dprintk(2, "Trying to bailout from previous error.\n"); 1998c2ecf20Sopenharmony_ci rdc_8820_reset(state); 2008c2ecf20Sopenharmony_ci dst_pio_disable(state); 2018c2ecf20Sopenharmony_ci msleep(10); 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci return 0; 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dst_error_bailout); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ciint dst_comm_init(struct dst_state *state) 2088c2ecf20Sopenharmony_ci{ 2098c2ecf20Sopenharmony_ci dprintk(2, "Initializing DST.\n"); 2108c2ecf20Sopenharmony_ci if ((dst_pio_enable(state)) < 0) { 2118c2ecf20Sopenharmony_ci pr_err("PIO Enable Failed\n"); 2128c2ecf20Sopenharmony_ci return -1; 2138c2ecf20Sopenharmony_ci } 2148c2ecf20Sopenharmony_ci if ((rdc_reset_state(state)) < 0) { 2158c2ecf20Sopenharmony_ci pr_err("RDC 8820 State RESET Failed.\n"); 2168c2ecf20Sopenharmony_ci return -1; 2178c2ecf20Sopenharmony_ci } 2188c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_FW_1) 2198c2ecf20Sopenharmony_ci msleep(100); 2208c2ecf20Sopenharmony_ci else 2218c2ecf20Sopenharmony_ci msleep(5); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci return 0; 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dst_comm_init); 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ciint write_dst(struct dst_state *state, u8 *data, u8 len) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci struct i2c_msg msg = { 2308c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 2318c2ecf20Sopenharmony_ci .flags = 0, 2328c2ecf20Sopenharmony_ci .buf = data, 2338c2ecf20Sopenharmony_ci .len = len 2348c2ecf20Sopenharmony_ci }; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci int err; 2378c2ecf20Sopenharmony_ci u8 cnt; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci dprintk(1, "writing [ %*ph ]\n", len, data); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci for (cnt = 0; cnt < 2; cnt++) { 2428c2ecf20Sopenharmony_ci if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) { 2438c2ecf20Sopenharmony_ci dprintk(2, "_write_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", 2448c2ecf20Sopenharmony_ci err, len, data[0]); 2458c2ecf20Sopenharmony_ci dst_error_recovery(state); 2468c2ecf20Sopenharmony_ci continue; 2478c2ecf20Sopenharmony_ci } else 2488c2ecf20Sopenharmony_ci break; 2498c2ecf20Sopenharmony_ci } 2508c2ecf20Sopenharmony_ci if (cnt >= 2) { 2518c2ecf20Sopenharmony_ci dprintk(2, "RDC 8820 RESET\n"); 2528c2ecf20Sopenharmony_ci dst_error_bailout(state); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci return -1; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci return 0; 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_ciEXPORT_SYMBOL(write_dst); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ciint read_dst(struct dst_state *state, u8 *ret, u8 len) 2628c2ecf20Sopenharmony_ci{ 2638c2ecf20Sopenharmony_ci struct i2c_msg msg = { 2648c2ecf20Sopenharmony_ci .addr = state->config->demod_address, 2658c2ecf20Sopenharmony_ci .flags = I2C_M_RD, 2668c2ecf20Sopenharmony_ci .buf = ret, 2678c2ecf20Sopenharmony_ci .len = len 2688c2ecf20Sopenharmony_ci }; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci int err; 2718c2ecf20Sopenharmony_ci int cnt; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci for (cnt = 0; cnt < 2; cnt++) { 2748c2ecf20Sopenharmony_ci if ((err = i2c_transfer(state->i2c, &msg, 1)) < 0) { 2758c2ecf20Sopenharmony_ci dprintk(2, "read_dst error (err == %i, len == 0x%02x, b0 == 0x%02x)\n", 2768c2ecf20Sopenharmony_ci err, len, ret[0]); 2778c2ecf20Sopenharmony_ci dst_error_recovery(state); 2788c2ecf20Sopenharmony_ci continue; 2798c2ecf20Sopenharmony_ci } else 2808c2ecf20Sopenharmony_ci break; 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci if (cnt >= 2) { 2838c2ecf20Sopenharmony_ci dprintk(2, "RDC 8820 RESET\n"); 2848c2ecf20Sopenharmony_ci dst_error_bailout(state); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci return -1; 2878c2ecf20Sopenharmony_ci } 2888c2ecf20Sopenharmony_ci dprintk(3, "reply is %*ph\n", len, ret); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci return 0; 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ciEXPORT_SYMBOL(read_dst); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistatic int dst_set_polarization(struct dst_state *state) 2958c2ecf20Sopenharmony_ci{ 2968c2ecf20Sopenharmony_ci switch (state->voltage) { 2978c2ecf20Sopenharmony_ci case SEC_VOLTAGE_13: /* Vertical */ 2988c2ecf20Sopenharmony_ci dprintk(2, "Polarization=[Vertical]\n"); 2998c2ecf20Sopenharmony_ci state->tx_tuna[8] &= ~0x40; 3008c2ecf20Sopenharmony_ci break; 3018c2ecf20Sopenharmony_ci case SEC_VOLTAGE_18: /* Horizontal */ 3028c2ecf20Sopenharmony_ci dprintk(2, "Polarization=[Horizontal]\n"); 3038c2ecf20Sopenharmony_ci state->tx_tuna[8] |= 0x40; 3048c2ecf20Sopenharmony_ci break; 3058c2ecf20Sopenharmony_ci case SEC_VOLTAGE_OFF: 3068c2ecf20Sopenharmony_ci break; 3078c2ecf20Sopenharmony_ci } 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci return 0; 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic int dst_set_freq(struct dst_state *state, u32 freq) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci state->frequency = freq; 3158c2ecf20Sopenharmony_ci dprintk(2, "set Frequency %u\n", freq); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci if (state->dst_type == DST_TYPE_IS_SAT) { 3188c2ecf20Sopenharmony_ci freq = freq / 1000; 3198c2ecf20Sopenharmony_ci if (freq < 950 || freq > 2150) 3208c2ecf20Sopenharmony_ci return -EINVAL; 3218c2ecf20Sopenharmony_ci state->tx_tuna[2] = (freq >> 8); 3228c2ecf20Sopenharmony_ci state->tx_tuna[3] = (u8) freq; 3238c2ecf20Sopenharmony_ci state->tx_tuna[4] = 0x01; 3248c2ecf20Sopenharmony_ci state->tx_tuna[8] &= ~0x04; 3258c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_OBS_REGS) { 3268c2ecf20Sopenharmony_ci if (freq < 1531) 3278c2ecf20Sopenharmony_ci state->tx_tuna[8] |= 0x04; 3288c2ecf20Sopenharmony_ci } 3298c2ecf20Sopenharmony_ci } else if (state->dst_type == DST_TYPE_IS_TERR) { 3308c2ecf20Sopenharmony_ci freq = freq / 1000; 3318c2ecf20Sopenharmony_ci if (freq < 137000 || freq > 858000) 3328c2ecf20Sopenharmony_ci return -EINVAL; 3338c2ecf20Sopenharmony_ci state->tx_tuna[2] = (freq >> 16) & 0xff; 3348c2ecf20Sopenharmony_ci state->tx_tuna[3] = (freq >> 8) & 0xff; 3358c2ecf20Sopenharmony_ci state->tx_tuna[4] = (u8) freq; 3368c2ecf20Sopenharmony_ci } else if (state->dst_type == DST_TYPE_IS_CABLE) { 3378c2ecf20Sopenharmony_ci freq = freq / 1000; 3388c2ecf20Sopenharmony_ci state->tx_tuna[2] = (freq >> 16) & 0xff; 3398c2ecf20Sopenharmony_ci state->tx_tuna[3] = (freq >> 8) & 0xff; 3408c2ecf20Sopenharmony_ci state->tx_tuna[4] = (u8) freq; 3418c2ecf20Sopenharmony_ci } else if (state->dst_type == DST_TYPE_IS_ATSC) { 3428c2ecf20Sopenharmony_ci freq = freq / 1000; 3438c2ecf20Sopenharmony_ci if (freq < 51000 || freq > 858000) 3448c2ecf20Sopenharmony_ci return -EINVAL; 3458c2ecf20Sopenharmony_ci state->tx_tuna[2] = (freq >> 16) & 0xff; 3468c2ecf20Sopenharmony_ci state->tx_tuna[3] = (freq >> 8) & 0xff; 3478c2ecf20Sopenharmony_ci state->tx_tuna[4] = (u8) freq; 3488c2ecf20Sopenharmony_ci state->tx_tuna[5] = 0x00; /* ATSC */ 3498c2ecf20Sopenharmony_ci state->tx_tuna[6] = 0x00; 3508c2ecf20Sopenharmony_ci if (state->dst_hw_cap & DST_TYPE_HAS_ANALOG) 3518c2ecf20Sopenharmony_ci state->tx_tuna[7] = 0x00; /* Digital */ 3528c2ecf20Sopenharmony_ci } else 3538c2ecf20Sopenharmony_ci return -EINVAL; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci return 0; 3568c2ecf20Sopenharmony_ci} 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_cistatic int dst_set_bandwidth(struct dst_state *state, u32 bandwidth) 3598c2ecf20Sopenharmony_ci{ 3608c2ecf20Sopenharmony_ci state->bandwidth = bandwidth; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci if (state->dst_type != DST_TYPE_IS_TERR) 3638c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci switch (bandwidth) { 3668c2ecf20Sopenharmony_ci case 6000000: 3678c2ecf20Sopenharmony_ci if (state->dst_hw_cap & DST_TYPE_HAS_CA) 3688c2ecf20Sopenharmony_ci state->tx_tuna[7] = 0x06; 3698c2ecf20Sopenharmony_ci else { 3708c2ecf20Sopenharmony_ci state->tx_tuna[6] = 0x06; 3718c2ecf20Sopenharmony_ci state->tx_tuna[7] = 0x00; 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci break; 3748c2ecf20Sopenharmony_ci case 7000000: 3758c2ecf20Sopenharmony_ci if (state->dst_hw_cap & DST_TYPE_HAS_CA) 3768c2ecf20Sopenharmony_ci state->tx_tuna[7] = 0x07; 3778c2ecf20Sopenharmony_ci else { 3788c2ecf20Sopenharmony_ci state->tx_tuna[6] = 0x07; 3798c2ecf20Sopenharmony_ci state->tx_tuna[7] = 0x00; 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci break; 3828c2ecf20Sopenharmony_ci case 8000000: 3838c2ecf20Sopenharmony_ci if (state->dst_hw_cap & DST_TYPE_HAS_CA) 3848c2ecf20Sopenharmony_ci state->tx_tuna[7] = 0x08; 3858c2ecf20Sopenharmony_ci else { 3868c2ecf20Sopenharmony_ci state->tx_tuna[6] = 0x08; 3878c2ecf20Sopenharmony_ci state->tx_tuna[7] = 0x00; 3888c2ecf20Sopenharmony_ci } 3898c2ecf20Sopenharmony_ci break; 3908c2ecf20Sopenharmony_ci default: 3918c2ecf20Sopenharmony_ci return -EINVAL; 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci return 0; 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_cistatic int dst_set_inversion(struct dst_state *state, 3988c2ecf20Sopenharmony_ci enum fe_spectral_inversion inversion) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci state->inversion = inversion; 4018c2ecf20Sopenharmony_ci switch (inversion) { 4028c2ecf20Sopenharmony_ci case INVERSION_OFF: /* Inversion = Normal */ 4038c2ecf20Sopenharmony_ci state->tx_tuna[8] &= ~0x80; 4048c2ecf20Sopenharmony_ci break; 4058c2ecf20Sopenharmony_ci case INVERSION_ON: 4068c2ecf20Sopenharmony_ci state->tx_tuna[8] |= 0x80; 4078c2ecf20Sopenharmony_ci break; 4088c2ecf20Sopenharmony_ci default: 4098c2ecf20Sopenharmony_ci return -EINVAL; 4108c2ecf20Sopenharmony_ci } 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci return 0; 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_cistatic int dst_set_fec(struct dst_state *state, enum fe_code_rate fec) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci state->fec = fec; 4188c2ecf20Sopenharmony_ci return 0; 4198c2ecf20Sopenharmony_ci} 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_cistatic enum fe_code_rate dst_get_fec(struct dst_state *state) 4228c2ecf20Sopenharmony_ci{ 4238c2ecf20Sopenharmony_ci return state->fec; 4248c2ecf20Sopenharmony_ci} 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_cistatic int dst_set_symbolrate(struct dst_state *state, u32 srate) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci u32 symcalc; 4298c2ecf20Sopenharmony_ci u64 sval; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci state->symbol_rate = srate; 4328c2ecf20Sopenharmony_ci if (state->dst_type == DST_TYPE_IS_TERR) { 4338c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 4348c2ecf20Sopenharmony_ci } 4358c2ecf20Sopenharmony_ci dprintk(2, "set symrate %u\n", srate); 4368c2ecf20Sopenharmony_ci srate /= 1000; 4378c2ecf20Sopenharmony_ci if (state->dst_type == DST_TYPE_IS_SAT) { 4388c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_SYMDIV) { 4398c2ecf20Sopenharmony_ci sval = srate; 4408c2ecf20Sopenharmony_ci sval <<= 20; 4418c2ecf20Sopenharmony_ci do_div(sval, 88000); 4428c2ecf20Sopenharmony_ci symcalc = (u32) sval; 4438c2ecf20Sopenharmony_ci dprintk(2, "set symcalc %u\n", symcalc); 4448c2ecf20Sopenharmony_ci state->tx_tuna[5] = (u8) (symcalc >> 12); 4458c2ecf20Sopenharmony_ci state->tx_tuna[6] = (u8) (symcalc >> 4); 4468c2ecf20Sopenharmony_ci state->tx_tuna[7] = (u8) (symcalc << 4); 4478c2ecf20Sopenharmony_ci } else { 4488c2ecf20Sopenharmony_ci state->tx_tuna[5] = (u8) (srate >> 16) & 0x7f; 4498c2ecf20Sopenharmony_ci state->tx_tuna[6] = (u8) (srate >> 8); 4508c2ecf20Sopenharmony_ci state->tx_tuna[7] = (u8) srate; 4518c2ecf20Sopenharmony_ci } 4528c2ecf20Sopenharmony_ci state->tx_tuna[8] &= ~0x20; 4538c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_OBS_REGS) { 4548c2ecf20Sopenharmony_ci if (srate > 8000) 4558c2ecf20Sopenharmony_ci state->tx_tuna[8] |= 0x20; 4568c2ecf20Sopenharmony_ci } 4578c2ecf20Sopenharmony_ci } else if (state->dst_type == DST_TYPE_IS_CABLE) { 4588c2ecf20Sopenharmony_ci dprintk(3, "%s\n", state->fw_name); 4598c2ecf20Sopenharmony_ci if (!strncmp(state->fw_name, "DCTNEW", 6)) { 4608c2ecf20Sopenharmony_ci state->tx_tuna[5] = (u8) (srate >> 8); 4618c2ecf20Sopenharmony_ci state->tx_tuna[6] = (u8) srate; 4628c2ecf20Sopenharmony_ci state->tx_tuna[7] = 0x00; 4638c2ecf20Sopenharmony_ci } else if (!strncmp(state->fw_name, "DCT-CI", 6)) { 4648c2ecf20Sopenharmony_ci state->tx_tuna[5] = 0x00; 4658c2ecf20Sopenharmony_ci state->tx_tuna[6] = (u8) (srate >> 8); 4668c2ecf20Sopenharmony_ci state->tx_tuna[7] = (u8) srate; 4678c2ecf20Sopenharmony_ci } 4688c2ecf20Sopenharmony_ci } 4698c2ecf20Sopenharmony_ci return 0; 4708c2ecf20Sopenharmony_ci} 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_cistatic int dst_set_modulation(struct dst_state *state, 4738c2ecf20Sopenharmony_ci enum fe_modulation modulation) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci if (state->dst_type != DST_TYPE_IS_CABLE) 4768c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci state->modulation = modulation; 4798c2ecf20Sopenharmony_ci switch (modulation) { 4808c2ecf20Sopenharmony_ci case QAM_16: 4818c2ecf20Sopenharmony_ci state->tx_tuna[8] = 0x10; 4828c2ecf20Sopenharmony_ci break; 4838c2ecf20Sopenharmony_ci case QAM_32: 4848c2ecf20Sopenharmony_ci state->tx_tuna[8] = 0x20; 4858c2ecf20Sopenharmony_ci break; 4868c2ecf20Sopenharmony_ci case QAM_64: 4878c2ecf20Sopenharmony_ci state->tx_tuna[8] = 0x40; 4888c2ecf20Sopenharmony_ci break; 4898c2ecf20Sopenharmony_ci case QAM_128: 4908c2ecf20Sopenharmony_ci state->tx_tuna[8] = 0x80; 4918c2ecf20Sopenharmony_ci break; 4928c2ecf20Sopenharmony_ci case QAM_256: 4938c2ecf20Sopenharmony_ci if (!strncmp(state->fw_name, "DCTNEW", 6)) 4948c2ecf20Sopenharmony_ci state->tx_tuna[8] = 0xff; 4958c2ecf20Sopenharmony_ci else if (!strncmp(state->fw_name, "DCT-CI", 6)) 4968c2ecf20Sopenharmony_ci state->tx_tuna[8] = 0x00; 4978c2ecf20Sopenharmony_ci break; 4988c2ecf20Sopenharmony_ci case QPSK: 4998c2ecf20Sopenharmony_ci case QAM_AUTO: 5008c2ecf20Sopenharmony_ci case VSB_8: 5018c2ecf20Sopenharmony_ci case VSB_16: 5028c2ecf20Sopenharmony_ci default: 5038c2ecf20Sopenharmony_ci return -EINVAL; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci } 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci return 0; 5088c2ecf20Sopenharmony_ci} 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_cistatic enum fe_modulation dst_get_modulation(struct dst_state *state) 5118c2ecf20Sopenharmony_ci{ 5128c2ecf20Sopenharmony_ci return state->modulation; 5138c2ecf20Sopenharmony_ci} 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci 5168c2ecf20Sopenharmony_ciu8 dst_check_sum(u8 *buf, u32 len) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci u32 i; 5198c2ecf20Sopenharmony_ci u8 val = 0; 5208c2ecf20Sopenharmony_ci if (!len) 5218c2ecf20Sopenharmony_ci return 0; 5228c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) { 5238c2ecf20Sopenharmony_ci val += buf[i]; 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci return ((~val) + 1); 5268c2ecf20Sopenharmony_ci} 5278c2ecf20Sopenharmony_ciEXPORT_SYMBOL(dst_check_sum); 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_cistatic void dst_type_flags_print(struct dst_state *state) 5308c2ecf20Sopenharmony_ci{ 5318c2ecf20Sopenharmony_ci u32 type_flags = state->type_flags; 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci pr_err("DST type flags :\n"); 5348c2ecf20Sopenharmony_ci if (type_flags & DST_TYPE_HAS_TS188) 5358c2ecf20Sopenharmony_ci pr_err(" 0x%x newtuner\n", DST_TYPE_HAS_TS188); 5368c2ecf20Sopenharmony_ci if (type_flags & DST_TYPE_HAS_NEWTUNE_2) 5378c2ecf20Sopenharmony_ci pr_err(" 0x%x newtuner 2\n", DST_TYPE_HAS_NEWTUNE_2); 5388c2ecf20Sopenharmony_ci if (type_flags & DST_TYPE_HAS_TS204) 5398c2ecf20Sopenharmony_ci pr_err(" 0x%x ts204\n", DST_TYPE_HAS_TS204); 5408c2ecf20Sopenharmony_ci if (type_flags & DST_TYPE_HAS_VLF) 5418c2ecf20Sopenharmony_ci pr_err(" 0x%x VLF\n", DST_TYPE_HAS_VLF); 5428c2ecf20Sopenharmony_ci if (type_flags & DST_TYPE_HAS_SYMDIV) 5438c2ecf20Sopenharmony_ci pr_err(" 0x%x symdiv\n", DST_TYPE_HAS_SYMDIV); 5448c2ecf20Sopenharmony_ci if (type_flags & DST_TYPE_HAS_FW_1) 5458c2ecf20Sopenharmony_ci pr_err(" 0x%x firmware version = 1\n", DST_TYPE_HAS_FW_1); 5468c2ecf20Sopenharmony_ci if (type_flags & DST_TYPE_HAS_FW_2) 5478c2ecf20Sopenharmony_ci pr_err(" 0x%x firmware version = 2\n", DST_TYPE_HAS_FW_2); 5488c2ecf20Sopenharmony_ci if (type_flags & DST_TYPE_HAS_FW_3) 5498c2ecf20Sopenharmony_ci pr_err(" 0x%x firmware version = 3\n", DST_TYPE_HAS_FW_3); 5508c2ecf20Sopenharmony_ci pr_err("\n"); 5518c2ecf20Sopenharmony_ci} 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_cistatic int dst_type_print(struct dst_state *state, u8 type) 5558c2ecf20Sopenharmony_ci{ 5568c2ecf20Sopenharmony_ci char *otype; 5578c2ecf20Sopenharmony_ci switch (type) { 5588c2ecf20Sopenharmony_ci case DST_TYPE_IS_SAT: 5598c2ecf20Sopenharmony_ci otype = "satellite"; 5608c2ecf20Sopenharmony_ci break; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci case DST_TYPE_IS_TERR: 5638c2ecf20Sopenharmony_ci otype = "terrestrial"; 5648c2ecf20Sopenharmony_ci break; 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci case DST_TYPE_IS_CABLE: 5678c2ecf20Sopenharmony_ci otype = "cable"; 5688c2ecf20Sopenharmony_ci break; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci case DST_TYPE_IS_ATSC: 5718c2ecf20Sopenharmony_ci otype = "atsc"; 5728c2ecf20Sopenharmony_ci break; 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci default: 5758c2ecf20Sopenharmony_ci dprintk(2, "invalid dst type %d\n", type); 5768c2ecf20Sopenharmony_ci return -EINVAL; 5778c2ecf20Sopenharmony_ci } 5788c2ecf20Sopenharmony_ci dprintk(2, "DST type: %s\n", otype); 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci return 0; 5818c2ecf20Sopenharmony_ci} 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_cistatic struct tuner_types tuner_list[] = { 5848c2ecf20Sopenharmony_ci { 5858c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_L64724, 5868c2ecf20Sopenharmony_ci .tuner_name = "L 64724", 5878c2ecf20Sopenharmony_ci .board_name = "UNKNOWN", 5888c2ecf20Sopenharmony_ci .fw_name = "UNKNOWN" 5898c2ecf20Sopenharmony_ci }, 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci { 5928c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_STV0299, 5938c2ecf20Sopenharmony_ci .tuner_name = "STV 0299", 5948c2ecf20Sopenharmony_ci .board_name = "VP1020", 5958c2ecf20Sopenharmony_ci .fw_name = "DST-MOT" 5968c2ecf20Sopenharmony_ci }, 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci { 5998c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_STV0299, 6008c2ecf20Sopenharmony_ci .tuner_name = "STV 0299", 6018c2ecf20Sopenharmony_ci .board_name = "VP1020", 6028c2ecf20Sopenharmony_ci .fw_name = "DST-03T" 6038c2ecf20Sopenharmony_ci }, 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci { 6068c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_MB86A15, 6078c2ecf20Sopenharmony_ci .tuner_name = "MB 86A15", 6088c2ecf20Sopenharmony_ci .board_name = "VP1022", 6098c2ecf20Sopenharmony_ci .fw_name = "DST-03T" 6108c2ecf20Sopenharmony_ci }, 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci { 6138c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_MB86A15, 6148c2ecf20Sopenharmony_ci .tuner_name = "MB 86A15", 6158c2ecf20Sopenharmony_ci .board_name = "VP1025", 6168c2ecf20Sopenharmony_ci .fw_name = "DST-03T" 6178c2ecf20Sopenharmony_ci }, 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci { 6208c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_STV0299, 6218c2ecf20Sopenharmony_ci .tuner_name = "STV 0299", 6228c2ecf20Sopenharmony_ci .board_name = "VP1030", 6238c2ecf20Sopenharmony_ci .fw_name = "DST-CI" 6248c2ecf20Sopenharmony_ci }, 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci { 6278c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_STV0299, 6288c2ecf20Sopenharmony_ci .tuner_name = "STV 0299", 6298c2ecf20Sopenharmony_ci .board_name = "VP1030", 6308c2ecf20Sopenharmony_ci .fw_name = "DSTMCI" 6318c2ecf20Sopenharmony_ci }, 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci { 6348c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_UNKNOWN, 6358c2ecf20Sopenharmony_ci .tuner_name = "UNKNOWN", 6368c2ecf20Sopenharmony_ci .board_name = "VP2021", 6378c2ecf20Sopenharmony_ci .fw_name = "DCTNEW" 6388c2ecf20Sopenharmony_ci }, 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci { 6418c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_UNKNOWN, 6428c2ecf20Sopenharmony_ci .tuner_name = "UNKNOWN", 6438c2ecf20Sopenharmony_ci .board_name = "VP2030", 6448c2ecf20Sopenharmony_ci .fw_name = "DCT-CI" 6458c2ecf20Sopenharmony_ci }, 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci { 6488c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_UNKNOWN, 6498c2ecf20Sopenharmony_ci .tuner_name = "UNKNOWN", 6508c2ecf20Sopenharmony_ci .board_name = "VP2031", 6518c2ecf20Sopenharmony_ci .fw_name = "DCT-CI" 6528c2ecf20Sopenharmony_ci }, 6538c2ecf20Sopenharmony_ci 6548c2ecf20Sopenharmony_ci { 6558c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_UNKNOWN, 6568c2ecf20Sopenharmony_ci .tuner_name = "UNKNOWN", 6578c2ecf20Sopenharmony_ci .board_name = "VP2040", 6588c2ecf20Sopenharmony_ci .fw_name = "DCT-CI" 6598c2ecf20Sopenharmony_ci }, 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci { 6628c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_UNKNOWN, 6638c2ecf20Sopenharmony_ci .tuner_name = "UNKNOWN", 6648c2ecf20Sopenharmony_ci .board_name = "VP3020", 6658c2ecf20Sopenharmony_ci .fw_name = "DTTFTA" 6668c2ecf20Sopenharmony_ci }, 6678c2ecf20Sopenharmony_ci 6688c2ecf20Sopenharmony_ci { 6698c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_UNKNOWN, 6708c2ecf20Sopenharmony_ci .tuner_name = "UNKNOWN", 6718c2ecf20Sopenharmony_ci .board_name = "VP3021", 6728c2ecf20Sopenharmony_ci .fw_name = "DTTFTA" 6738c2ecf20Sopenharmony_ci }, 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_ci { 6768c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_TDA10046, 6778c2ecf20Sopenharmony_ci .tuner_name = "TDA10046", 6788c2ecf20Sopenharmony_ci .board_name = "VP3040", 6798c2ecf20Sopenharmony_ci .fw_name = "DTT-CI" 6808c2ecf20Sopenharmony_ci }, 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci { 6838c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_UNKNOWN, 6848c2ecf20Sopenharmony_ci .tuner_name = "UNKNOWN", 6858c2ecf20Sopenharmony_ci .board_name = "VP3051", 6868c2ecf20Sopenharmony_ci .fw_name = "DTTNXT" 6878c2ecf20Sopenharmony_ci }, 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci { 6908c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_NXT200x, 6918c2ecf20Sopenharmony_ci .tuner_name = "NXT200x", 6928c2ecf20Sopenharmony_ci .board_name = "VP3220", 6938c2ecf20Sopenharmony_ci .fw_name = "ATSCDI" 6948c2ecf20Sopenharmony_ci }, 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci { 6978c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_NXT200x, 6988c2ecf20Sopenharmony_ci .tuner_name = "NXT200x", 6998c2ecf20Sopenharmony_ci .board_name = "VP3250", 7008c2ecf20Sopenharmony_ci .fw_name = "ATSCAD" 7018c2ecf20Sopenharmony_ci }, 7028c2ecf20Sopenharmony_ci}; 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci/* 7058c2ecf20Sopenharmony_ci Known cards list 7068c2ecf20Sopenharmony_ci Satellite 7078c2ecf20Sopenharmony_ci ------------------- 7088c2ecf20Sopenharmony_ci 200103A 7098c2ecf20Sopenharmony_ci VP-1020 DST-MOT LG(old), TS=188 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci VP-1020 DST-03T LG(new), TS=204 7128c2ecf20Sopenharmony_ci VP-1022 DST-03T LG(new), TS=204 7138c2ecf20Sopenharmony_ci VP-1025 DST-03T LG(new), TS=204 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci VP-1030 DSTMCI, LG(new), TS=188 7168c2ecf20Sopenharmony_ci VP-1032 DSTMCI, LG(new), TS=188 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci Cable 7198c2ecf20Sopenharmony_ci ------------------- 7208c2ecf20Sopenharmony_ci VP-2030 DCT-CI, Samsung, TS=204 7218c2ecf20Sopenharmony_ci VP-2021 DCT-CI, Unknown, TS=204 7228c2ecf20Sopenharmony_ci VP-2031 DCT-CI, Philips, TS=188 7238c2ecf20Sopenharmony_ci VP-2040 DCT-CI, Philips, TS=188, with CA daughter board 7248c2ecf20Sopenharmony_ci VP-2040 DCT-CI, Philips, TS=204, without CA daughter board 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci Terrestrial 7278c2ecf20Sopenharmony_ci ------------------- 7288c2ecf20Sopenharmony_ci VP-3050 DTTNXT TS=188 7298c2ecf20Sopenharmony_ci VP-3040 DTT-CI, Philips, TS=188 7308c2ecf20Sopenharmony_ci VP-3040 DTT-CI, Philips, TS=204 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci ATSC 7338c2ecf20Sopenharmony_ci ------------------- 7348c2ecf20Sopenharmony_ci VP-3220 ATSCDI, TS=188 7358c2ecf20Sopenharmony_ci VP-3250 ATSCAD, TS=188 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci*/ 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_cistatic struct dst_types dst_tlist[] = { 7408c2ecf20Sopenharmony_ci { 7418c2ecf20Sopenharmony_ci .device_id = "200103A", 7428c2ecf20Sopenharmony_ci .offset = 0, 7438c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_SAT, 7448c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_OBS_REGS, 7458c2ecf20Sopenharmony_ci .dst_feature = 0, 7468c2ecf20Sopenharmony_ci .tuner_type = 0 7478c2ecf20Sopenharmony_ci }, /* obsolete */ 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci { 7508c2ecf20Sopenharmony_ci .device_id = "DST-020", 7518c2ecf20Sopenharmony_ci .offset = 0, 7528c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_SAT, 7538c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1, 7548c2ecf20Sopenharmony_ci .dst_feature = 0, 7558c2ecf20Sopenharmony_ci .tuner_type = 0 7568c2ecf20Sopenharmony_ci }, /* obsolete */ 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci { 7598c2ecf20Sopenharmony_ci .device_id = "DST-030", 7608c2ecf20Sopenharmony_ci .offset = 0, 7618c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_SAT, 7628c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1, 7638c2ecf20Sopenharmony_ci .dst_feature = 0, 7648c2ecf20Sopenharmony_ci .tuner_type = 0 7658c2ecf20Sopenharmony_ci }, /* obsolete */ 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci { 7688c2ecf20Sopenharmony_ci .device_id = "DST-03T", 7698c2ecf20Sopenharmony_ci .offset = 0, 7708c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_SAT, 7718c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_2, 7728c2ecf20Sopenharmony_ci .dst_feature = DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 | DST_TYPE_HAS_DISEQC5 7738c2ecf20Sopenharmony_ci | DST_TYPE_HAS_MAC | DST_TYPE_HAS_MOTO, 7748c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_MULTI 7758c2ecf20Sopenharmony_ci }, 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci { 7788c2ecf20Sopenharmony_ci .device_id = "DST-MOT", 7798c2ecf20Sopenharmony_ci .offset = 0, 7808c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_SAT, 7818c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_SYMDIV | DST_TYPE_HAS_FW_1, 7828c2ecf20Sopenharmony_ci .dst_feature = 0, 7838c2ecf20Sopenharmony_ci .tuner_type = 0 7848c2ecf20Sopenharmony_ci }, /* obsolete */ 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci { 7878c2ecf20Sopenharmony_ci .device_id = "DST-CI", 7888c2ecf20Sopenharmony_ci .offset = 1, 7898c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_SAT, 7908c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_TS204 | DST_TYPE_HAS_FW_1, 7918c2ecf20Sopenharmony_ci .dst_feature = DST_TYPE_HAS_CA, 7928c2ecf20Sopenharmony_ci .tuner_type = 0 7938c2ecf20Sopenharmony_ci }, /* An OEM board */ 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci { 7968c2ecf20Sopenharmony_ci .device_id = "DSTMCI", 7978c2ecf20Sopenharmony_ci .offset = 1, 7988c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_SAT, 7998c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_INC_COUNT | DST_TYPE_HAS_VLF, 8008c2ecf20Sopenharmony_ci .dst_feature = DST_TYPE_HAS_CA | DST_TYPE_HAS_DISEQC3 | DST_TYPE_HAS_DISEQC4 8018c2ecf20Sopenharmony_ci | DST_TYPE_HAS_MOTO | DST_TYPE_HAS_MAC, 8028c2ecf20Sopenharmony_ci .tuner_type = TUNER_TYPE_MULTI 8038c2ecf20Sopenharmony_ci }, 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci { 8068c2ecf20Sopenharmony_ci .device_id = "DSTFCI", 8078c2ecf20Sopenharmony_ci .offset = 1, 8088c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_SAT, 8098c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_1, 8108c2ecf20Sopenharmony_ci .dst_feature = 0, 8118c2ecf20Sopenharmony_ci .tuner_type = 0 8128c2ecf20Sopenharmony_ci }, /* unknown to vendor */ 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci { 8158c2ecf20Sopenharmony_ci .device_id = "DCT-CI", 8168c2ecf20Sopenharmony_ci .offset = 1, 8178c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_CABLE, 8188c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_1 | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_VLF, 8198c2ecf20Sopenharmony_ci .dst_feature = DST_TYPE_HAS_CA, 8208c2ecf20Sopenharmony_ci .tuner_type = 0 8218c2ecf20Sopenharmony_ci }, 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci { 8248c2ecf20Sopenharmony_ci .device_id = "DCTNEW", 8258c2ecf20Sopenharmony_ci .offset = 1, 8268c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_CABLE, 8278c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_TS188 | DST_TYPE_HAS_FW_3 | DST_TYPE_HAS_FW_BUILD | DST_TYPE_HAS_MULTI_FE, 8288c2ecf20Sopenharmony_ci .dst_feature = 0, 8298c2ecf20Sopenharmony_ci .tuner_type = 0 8308c2ecf20Sopenharmony_ci }, 8318c2ecf20Sopenharmony_ci 8328c2ecf20Sopenharmony_ci { 8338c2ecf20Sopenharmony_ci .device_id = "DTT-CI", 8348c2ecf20Sopenharmony_ci .offset = 1, 8358c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_TERR, 8368c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_VLF, 8378c2ecf20Sopenharmony_ci .dst_feature = DST_TYPE_HAS_CA, 8388c2ecf20Sopenharmony_ci .tuner_type = 0 8398c2ecf20Sopenharmony_ci }, 8408c2ecf20Sopenharmony_ci 8418c2ecf20Sopenharmony_ci { 8428c2ecf20Sopenharmony_ci .device_id = "DTTDIG", 8438c2ecf20Sopenharmony_ci .offset = 1, 8448c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_TERR, 8458c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_FW_2, 8468c2ecf20Sopenharmony_ci .dst_feature = 0, 8478c2ecf20Sopenharmony_ci .tuner_type = 0 8488c2ecf20Sopenharmony_ci }, 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci { 8518c2ecf20Sopenharmony_ci .device_id = "DTTNXT", 8528c2ecf20Sopenharmony_ci .offset = 1, 8538c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_TERR, 8548c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_FW_2, 8558c2ecf20Sopenharmony_ci .dst_feature = DST_TYPE_HAS_ANALOG, 8568c2ecf20Sopenharmony_ci .tuner_type = 0 8578c2ecf20Sopenharmony_ci }, 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci { 8608c2ecf20Sopenharmony_ci .device_id = "ATSCDI", 8618c2ecf20Sopenharmony_ci .offset = 1, 8628c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_ATSC, 8638c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_FW_2, 8648c2ecf20Sopenharmony_ci .dst_feature = 0, 8658c2ecf20Sopenharmony_ci .tuner_type = 0 8668c2ecf20Sopenharmony_ci }, 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci { 8698c2ecf20Sopenharmony_ci .device_id = "ATSCAD", 8708c2ecf20Sopenharmony_ci .offset = 1, 8718c2ecf20Sopenharmony_ci .dst_type = DST_TYPE_IS_ATSC, 8728c2ecf20Sopenharmony_ci .type_flags = DST_TYPE_HAS_MULTI_FE | DST_TYPE_HAS_FW_2 | DST_TYPE_HAS_FW_BUILD, 8738c2ecf20Sopenharmony_ci .dst_feature = DST_TYPE_HAS_MAC | DST_TYPE_HAS_ANALOG, 8748c2ecf20Sopenharmony_ci .tuner_type = 0 8758c2ecf20Sopenharmony_ci }, 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci { } 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci}; 8808c2ecf20Sopenharmony_ci 8818c2ecf20Sopenharmony_cistatic int dst_get_mac(struct dst_state *state) 8828c2ecf20Sopenharmony_ci{ 8838c2ecf20Sopenharmony_ci u8 get_mac[] = { 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 8848c2ecf20Sopenharmony_ci get_mac[7] = dst_check_sum(get_mac, 7); 8858c2ecf20Sopenharmony_ci if (dst_command(state, get_mac, 8) < 0) { 8868c2ecf20Sopenharmony_ci dprintk(2, "Unsupported Command\n"); 8878c2ecf20Sopenharmony_ci return -1; 8888c2ecf20Sopenharmony_ci } 8898c2ecf20Sopenharmony_ci memset(&state->mac_address, '\0', 8); 8908c2ecf20Sopenharmony_ci memcpy(&state->mac_address, &state->rxbuffer, 6); 8918c2ecf20Sopenharmony_ci pr_err("MAC Address=[%pM]\n", state->mac_address); 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci return 0; 8948c2ecf20Sopenharmony_ci} 8958c2ecf20Sopenharmony_ci 8968c2ecf20Sopenharmony_cistatic int dst_fw_ver(struct dst_state *state) 8978c2ecf20Sopenharmony_ci{ 8988c2ecf20Sopenharmony_ci u8 get_ver[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 8998c2ecf20Sopenharmony_ci get_ver[7] = dst_check_sum(get_ver, 7); 9008c2ecf20Sopenharmony_ci if (dst_command(state, get_ver, 8) < 0) { 9018c2ecf20Sopenharmony_ci dprintk(2, "Unsupported Command\n"); 9028c2ecf20Sopenharmony_ci return -1; 9038c2ecf20Sopenharmony_ci } 9048c2ecf20Sopenharmony_ci memcpy(&state->fw_version, &state->rxbuffer, 8); 9058c2ecf20Sopenharmony_ci pr_err("Firmware Ver = %x.%x Build = %02x, on %x:%x, %x-%x-20%02x\n", 9068c2ecf20Sopenharmony_ci state->fw_version[0] >> 4, state->fw_version[0] & 0x0f, 9078c2ecf20Sopenharmony_ci state->fw_version[1], 9088c2ecf20Sopenharmony_ci state->fw_version[5], state->fw_version[6], 9098c2ecf20Sopenharmony_ci state->fw_version[4], state->fw_version[3], state->fw_version[2]); 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci return 0; 9128c2ecf20Sopenharmony_ci} 9138c2ecf20Sopenharmony_ci 9148c2ecf20Sopenharmony_cistatic int dst_card_type(struct dst_state *state) 9158c2ecf20Sopenharmony_ci{ 9168c2ecf20Sopenharmony_ci int j; 9178c2ecf20Sopenharmony_ci struct tuner_types *p_tuner_list = NULL; 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci u8 get_type[] = { 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 9208c2ecf20Sopenharmony_ci get_type[7] = dst_check_sum(get_type, 7); 9218c2ecf20Sopenharmony_ci if (dst_command(state, get_type, 8) < 0) { 9228c2ecf20Sopenharmony_ci dprintk(2, "Unsupported Command\n"); 9238c2ecf20Sopenharmony_ci return -1; 9248c2ecf20Sopenharmony_ci } 9258c2ecf20Sopenharmony_ci memset(&state->card_info, '\0', 8); 9268c2ecf20Sopenharmony_ci memcpy(&state->card_info, &state->rxbuffer, 7); 9278c2ecf20Sopenharmony_ci pr_err("Device Model=[%s]\n", &state->card_info[0]); 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) { 9308c2ecf20Sopenharmony_ci if (!strcmp(&state->card_info[0], p_tuner_list->board_name)) { 9318c2ecf20Sopenharmony_ci state->tuner_type = p_tuner_list->tuner_type; 9328c2ecf20Sopenharmony_ci pr_err("DST has [%s] tuner, tuner type=[%d]\n", 9338c2ecf20Sopenharmony_ci p_tuner_list->tuner_name, p_tuner_list->tuner_type); 9348c2ecf20Sopenharmony_ci } 9358c2ecf20Sopenharmony_ci } 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci return 0; 9388c2ecf20Sopenharmony_ci} 9398c2ecf20Sopenharmony_ci 9408c2ecf20Sopenharmony_cistatic int dst_get_vendor(struct dst_state *state) 9418c2ecf20Sopenharmony_ci{ 9428c2ecf20Sopenharmony_ci u8 get_vendor[] = { 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 9438c2ecf20Sopenharmony_ci get_vendor[7] = dst_check_sum(get_vendor, 7); 9448c2ecf20Sopenharmony_ci if (dst_command(state, get_vendor, 8) < 0) { 9458c2ecf20Sopenharmony_ci dprintk(2, "Unsupported Command\n"); 9468c2ecf20Sopenharmony_ci return -1; 9478c2ecf20Sopenharmony_ci } 9488c2ecf20Sopenharmony_ci memset(&state->vendor, '\0', 8); 9498c2ecf20Sopenharmony_ci memcpy(&state->vendor, &state->rxbuffer, 7); 9508c2ecf20Sopenharmony_ci pr_err("Vendor=[%s]\n", &state->vendor[0]); 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci return 0; 9538c2ecf20Sopenharmony_ci} 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_cistatic void debug_dst_buffer(struct dst_state *state) 9568c2ecf20Sopenharmony_ci{ 9578c2ecf20Sopenharmony_ci dprintk(3, "%s: [ %*ph ]\n", __func__, 8, state->rxbuffer); 9588c2ecf20Sopenharmony_ci} 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_cistatic int dst_check_stv0299(struct dst_state *state) 9618c2ecf20Sopenharmony_ci{ 9628c2ecf20Sopenharmony_ci u8 check_stv0299[] = { 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci check_stv0299[7] = dst_check_sum(check_stv0299, 7); 9658c2ecf20Sopenharmony_ci if (dst_command(state, check_stv0299, 8) < 0) { 9668c2ecf20Sopenharmony_ci pr_err("Cmd=[0x04] failed\n"); 9678c2ecf20Sopenharmony_ci return -1; 9688c2ecf20Sopenharmony_ci } 9698c2ecf20Sopenharmony_ci debug_dst_buffer(state); 9708c2ecf20Sopenharmony_ci 9718c2ecf20Sopenharmony_ci if (memcmp(&check_stv0299, &state->rxbuffer, 8)) { 9728c2ecf20Sopenharmony_ci pr_err("Found a STV0299 NIM\n"); 9738c2ecf20Sopenharmony_ci state->tuner_type = TUNER_TYPE_STV0299; 9748c2ecf20Sopenharmony_ci return 0; 9758c2ecf20Sopenharmony_ci } 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci return -1; 9788c2ecf20Sopenharmony_ci} 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_cistatic int dst_check_mb86a15(struct dst_state *state) 9818c2ecf20Sopenharmony_ci{ 9828c2ecf20Sopenharmony_ci u8 check_mb86a15[] = { 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci check_mb86a15[7] = dst_check_sum(check_mb86a15, 7); 9858c2ecf20Sopenharmony_ci if (dst_command(state, check_mb86a15, 8) < 0) { 9868c2ecf20Sopenharmony_ci pr_err("Cmd=[0x10], failed\n"); 9878c2ecf20Sopenharmony_ci return -1; 9888c2ecf20Sopenharmony_ci } 9898c2ecf20Sopenharmony_ci debug_dst_buffer(state); 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci if (memcmp(&check_mb86a15, &state->rxbuffer, 8) < 0) { 9928c2ecf20Sopenharmony_ci pr_err("Found a MB86A15 NIM\n"); 9938c2ecf20Sopenharmony_ci state->tuner_type = TUNER_TYPE_MB86A15; 9948c2ecf20Sopenharmony_ci return 0; 9958c2ecf20Sopenharmony_ci } 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci return -1; 9988c2ecf20Sopenharmony_ci} 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_cistatic int dst_get_tuner_info(struct dst_state *state) 10018c2ecf20Sopenharmony_ci{ 10028c2ecf20Sopenharmony_ci u8 get_tuner_1[] = { 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 10038c2ecf20Sopenharmony_ci u8 get_tuner_2[] = { 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; 10048c2ecf20Sopenharmony_ci 10058c2ecf20Sopenharmony_ci get_tuner_1[7] = dst_check_sum(get_tuner_1, 7); 10068c2ecf20Sopenharmony_ci get_tuner_2[7] = dst_check_sum(get_tuner_2, 7); 10078c2ecf20Sopenharmony_ci pr_err("DST TYpe = MULTI FE\n"); 10088c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_MULTI_FE) { 10098c2ecf20Sopenharmony_ci if (dst_command(state, get_tuner_1, 8) < 0) { 10108c2ecf20Sopenharmony_ci dprintk(2, "Cmd=[0x13], Unsupported\n"); 10118c2ecf20Sopenharmony_ci goto force; 10128c2ecf20Sopenharmony_ci } 10138c2ecf20Sopenharmony_ci } else { 10148c2ecf20Sopenharmony_ci if (dst_command(state, get_tuner_2, 8) < 0) { 10158c2ecf20Sopenharmony_ci dprintk(2, "Cmd=[0xb], Unsupported\n"); 10168c2ecf20Sopenharmony_ci goto force; 10178c2ecf20Sopenharmony_ci } 10188c2ecf20Sopenharmony_ci } 10198c2ecf20Sopenharmony_ci memcpy(&state->board_info, &state->rxbuffer, 8); 10208c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_MULTI_FE) { 10218c2ecf20Sopenharmony_ci pr_err("DST type has TS=188\n"); 10228c2ecf20Sopenharmony_ci } 10238c2ecf20Sopenharmony_ci if (state->board_info[0] == 0xbc) { 10248c2ecf20Sopenharmony_ci if (state->dst_type != DST_TYPE_IS_ATSC) 10258c2ecf20Sopenharmony_ci state->type_flags |= DST_TYPE_HAS_TS188; 10268c2ecf20Sopenharmony_ci else 10278c2ecf20Sopenharmony_ci state->type_flags |= DST_TYPE_HAS_NEWTUNE_2; 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci if (state->board_info[1] == 0x01) { 10308c2ecf20Sopenharmony_ci state->dst_hw_cap |= DST_TYPE_HAS_DBOARD; 10318c2ecf20Sopenharmony_ci pr_err("DST has Daughterboard\n"); 10328c2ecf20Sopenharmony_ci } 10338c2ecf20Sopenharmony_ci } 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci return 0; 10368c2ecf20Sopenharmony_ciforce: 10378c2ecf20Sopenharmony_ci if (!strncmp(state->fw_name, "DCT-CI", 6)) { 10388c2ecf20Sopenharmony_ci state->type_flags |= DST_TYPE_HAS_TS204; 10398c2ecf20Sopenharmony_ci pr_err("Forcing [%s] to TS188\n", state->fw_name); 10408c2ecf20Sopenharmony_ci } 10418c2ecf20Sopenharmony_ci 10428c2ecf20Sopenharmony_ci return -1; 10438c2ecf20Sopenharmony_ci} 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_cistatic int dst_get_device_id(struct dst_state *state) 10468c2ecf20Sopenharmony_ci{ 10478c2ecf20Sopenharmony_ci u8 reply; 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci int i, j; 10508c2ecf20Sopenharmony_ci struct dst_types *p_dst_type = NULL; 10518c2ecf20Sopenharmony_ci struct tuner_types *p_tuner_list = NULL; 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci u8 use_dst_type = 0; 10548c2ecf20Sopenharmony_ci u32 use_type_flags = 0; 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci static u8 device_type[8] = {0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff}; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci state->tuner_type = 0; 10598c2ecf20Sopenharmony_ci device_type[7] = dst_check_sum(device_type, 7); 10608c2ecf20Sopenharmony_ci 10618c2ecf20Sopenharmony_ci if (write_dst(state, device_type, FIXED_COMM)) 10628c2ecf20Sopenharmony_ci return -1; /* Write failed */ 10638c2ecf20Sopenharmony_ci if ((dst_pio_disable(state)) < 0) 10648c2ecf20Sopenharmony_ci return -1; 10658c2ecf20Sopenharmony_ci if (read_dst(state, &reply, GET_ACK)) 10668c2ecf20Sopenharmony_ci return -1; /* Read failure */ 10678c2ecf20Sopenharmony_ci if (reply != ACK) { 10688c2ecf20Sopenharmony_ci dprintk(2, "Write not Acknowledged! [Reply=0x%02x]\n", reply); 10698c2ecf20Sopenharmony_ci return -1; /* Unack'd write */ 10708c2ecf20Sopenharmony_ci } 10718c2ecf20Sopenharmony_ci if (!dst_wait_dst_ready(state, DEVICE_INIT)) 10728c2ecf20Sopenharmony_ci return -1; /* DST not ready yet */ 10738c2ecf20Sopenharmony_ci if (read_dst(state, state->rxbuffer, FIXED_COMM)) 10748c2ecf20Sopenharmony_ci return -1; 10758c2ecf20Sopenharmony_ci 10768c2ecf20Sopenharmony_ci dst_pio_disable(state); 10778c2ecf20Sopenharmony_ci if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) { 10788c2ecf20Sopenharmony_ci dprintk(2, "Checksum failure!\n"); 10798c2ecf20Sopenharmony_ci return -1; /* Checksum failure */ 10808c2ecf20Sopenharmony_ci } 10818c2ecf20Sopenharmony_ci state->rxbuffer[7] = '\0'; 10828c2ecf20Sopenharmony_ci 10838c2ecf20Sopenharmony_ci for (i = 0, p_dst_type = dst_tlist; i < ARRAY_SIZE(dst_tlist); i++, p_dst_type++) { 10848c2ecf20Sopenharmony_ci if (!strncmp (&state->rxbuffer[p_dst_type->offset], p_dst_type->device_id, strlen (p_dst_type->device_id))) { 10858c2ecf20Sopenharmony_ci use_type_flags = p_dst_type->type_flags; 10868c2ecf20Sopenharmony_ci use_dst_type = p_dst_type->dst_type; 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci /* Card capabilities */ 10898c2ecf20Sopenharmony_ci state->dst_hw_cap = p_dst_type->dst_feature; 10908c2ecf20Sopenharmony_ci pr_err("Recognise [%s]\n", p_dst_type->device_id); 10918c2ecf20Sopenharmony_ci strscpy(state->fw_name, p_dst_type->device_id, 10928c2ecf20Sopenharmony_ci sizeof(state->fw_name)); 10938c2ecf20Sopenharmony_ci /* Multiple tuners */ 10948c2ecf20Sopenharmony_ci if (p_dst_type->tuner_type & TUNER_TYPE_MULTI) { 10958c2ecf20Sopenharmony_ci switch (use_dst_type) { 10968c2ecf20Sopenharmony_ci case DST_TYPE_IS_SAT: 10978c2ecf20Sopenharmony_ci /* STV0299 check */ 10988c2ecf20Sopenharmony_ci if (dst_check_stv0299(state) < 0) { 10998c2ecf20Sopenharmony_ci pr_err("Unsupported\n"); 11008c2ecf20Sopenharmony_ci state->tuner_type = TUNER_TYPE_MB86A15; 11018c2ecf20Sopenharmony_ci } 11028c2ecf20Sopenharmony_ci break; 11038c2ecf20Sopenharmony_ci default: 11048c2ecf20Sopenharmony_ci break; 11058c2ecf20Sopenharmony_ci } 11068c2ecf20Sopenharmony_ci if (dst_check_mb86a15(state) < 0) 11078c2ecf20Sopenharmony_ci pr_err("Unsupported\n"); 11088c2ecf20Sopenharmony_ci /* Single tuner */ 11098c2ecf20Sopenharmony_ci } else { 11108c2ecf20Sopenharmony_ci state->tuner_type = p_dst_type->tuner_type; 11118c2ecf20Sopenharmony_ci } 11128c2ecf20Sopenharmony_ci for (j = 0, p_tuner_list = tuner_list; j < ARRAY_SIZE(tuner_list); j++, p_tuner_list++) { 11138c2ecf20Sopenharmony_ci if (!(strncmp(p_dst_type->device_id, p_tuner_list->fw_name, 7)) && 11148c2ecf20Sopenharmony_ci p_tuner_list->tuner_type == state->tuner_type) { 11158c2ecf20Sopenharmony_ci pr_err("[%s] has a [%s]\n", 11168c2ecf20Sopenharmony_ci p_dst_type->device_id, p_tuner_list->tuner_name); 11178c2ecf20Sopenharmony_ci } 11188c2ecf20Sopenharmony_ci } 11198c2ecf20Sopenharmony_ci break; 11208c2ecf20Sopenharmony_ci } 11218c2ecf20Sopenharmony_ci } 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci if (i >= ARRAY_SIZE(dst_tlist)) { 11248c2ecf20Sopenharmony_ci pr_err("Unable to recognize %s or %s\n", &state->rxbuffer[0], &state->rxbuffer[1]); 11258c2ecf20Sopenharmony_ci pr_err("please email linux-dvb@linuxtv.org with this type in"); 11268c2ecf20Sopenharmony_ci use_dst_type = DST_TYPE_IS_SAT; 11278c2ecf20Sopenharmony_ci use_type_flags = DST_TYPE_HAS_SYMDIV; 11288c2ecf20Sopenharmony_ci } 11298c2ecf20Sopenharmony_ci dst_type_print(state, use_dst_type); 11308c2ecf20Sopenharmony_ci state->type_flags = use_type_flags; 11318c2ecf20Sopenharmony_ci state->dst_type = use_dst_type; 11328c2ecf20Sopenharmony_ci dst_type_flags_print(state); 11338c2ecf20Sopenharmony_ci 11348c2ecf20Sopenharmony_ci return 0; 11358c2ecf20Sopenharmony_ci} 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_cistatic int dst_probe(struct dst_state *state) 11388c2ecf20Sopenharmony_ci{ 11398c2ecf20Sopenharmony_ci mutex_init(&state->dst_mutex); 11408c2ecf20Sopenharmony_ci if (dst_addons & DST_TYPE_HAS_CA) { 11418c2ecf20Sopenharmony_ci if ((rdc_8820_reset(state)) < 0) { 11428c2ecf20Sopenharmony_ci pr_err("RDC 8820 RESET Failed.\n"); 11438c2ecf20Sopenharmony_ci return -1; 11448c2ecf20Sopenharmony_ci } 11458c2ecf20Sopenharmony_ci msleep(4000); 11468c2ecf20Sopenharmony_ci } else { 11478c2ecf20Sopenharmony_ci msleep(100); 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci if ((dst_comm_init(state)) < 0) { 11508c2ecf20Sopenharmony_ci pr_err("DST Initialization Failed.\n"); 11518c2ecf20Sopenharmony_ci return -1; 11528c2ecf20Sopenharmony_ci } 11538c2ecf20Sopenharmony_ci msleep(100); 11548c2ecf20Sopenharmony_ci if (dst_get_device_id(state) < 0) { 11558c2ecf20Sopenharmony_ci pr_err("unknown device.\n"); 11568c2ecf20Sopenharmony_ci return -1; 11578c2ecf20Sopenharmony_ci } 11588c2ecf20Sopenharmony_ci if (dst_get_mac(state) < 0) { 11598c2ecf20Sopenharmony_ci dprintk(2, "MAC: Unsupported command\n"); 11608c2ecf20Sopenharmony_ci } 11618c2ecf20Sopenharmony_ci if ((state->type_flags & DST_TYPE_HAS_MULTI_FE) || (state->type_flags & DST_TYPE_HAS_FW_BUILD)) { 11628c2ecf20Sopenharmony_ci if (dst_get_tuner_info(state) < 0) 11638c2ecf20Sopenharmony_ci dprintk(2, "Tuner: Unsupported command\n"); 11648c2ecf20Sopenharmony_ci } 11658c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_TS204) { 11668c2ecf20Sopenharmony_ci dst_packsize(state, 204); 11678c2ecf20Sopenharmony_ci } 11688c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_FW_BUILD) { 11698c2ecf20Sopenharmony_ci if (dst_fw_ver(state) < 0) { 11708c2ecf20Sopenharmony_ci dprintk(2, "FW: Unsupported command\n"); 11718c2ecf20Sopenharmony_ci return 0; 11728c2ecf20Sopenharmony_ci } 11738c2ecf20Sopenharmony_ci if (dst_card_type(state) < 0) { 11748c2ecf20Sopenharmony_ci dprintk(2, "Card: Unsupported command\n"); 11758c2ecf20Sopenharmony_ci return 0; 11768c2ecf20Sopenharmony_ci } 11778c2ecf20Sopenharmony_ci if (dst_get_vendor(state) < 0) { 11788c2ecf20Sopenharmony_ci dprintk(2, "Vendor: Unsupported command\n"); 11798c2ecf20Sopenharmony_ci return 0; 11808c2ecf20Sopenharmony_ci } 11818c2ecf20Sopenharmony_ci } 11828c2ecf20Sopenharmony_ci 11838c2ecf20Sopenharmony_ci return 0; 11848c2ecf20Sopenharmony_ci} 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_cistatic int dst_command(struct dst_state *state, u8 *data, u8 len) 11878c2ecf20Sopenharmony_ci{ 11888c2ecf20Sopenharmony_ci u8 reply; 11898c2ecf20Sopenharmony_ci 11908c2ecf20Sopenharmony_ci mutex_lock(&state->dst_mutex); 11918c2ecf20Sopenharmony_ci if ((dst_comm_init(state)) < 0) { 11928c2ecf20Sopenharmony_ci dprintk(1, "DST Communication Initialization Failed.\n"); 11938c2ecf20Sopenharmony_ci goto error; 11948c2ecf20Sopenharmony_ci } 11958c2ecf20Sopenharmony_ci if (write_dst(state, data, len)) { 11968c2ecf20Sopenharmony_ci dprintk(2, "Trying to recover..\n"); 11978c2ecf20Sopenharmony_ci if ((dst_error_recovery(state)) < 0) { 11988c2ecf20Sopenharmony_ci pr_err("Recovery Failed.\n"); 11998c2ecf20Sopenharmony_ci goto error; 12008c2ecf20Sopenharmony_ci } 12018c2ecf20Sopenharmony_ci goto error; 12028c2ecf20Sopenharmony_ci } 12038c2ecf20Sopenharmony_ci if ((dst_pio_disable(state)) < 0) { 12048c2ecf20Sopenharmony_ci pr_err("PIO Disable Failed.\n"); 12058c2ecf20Sopenharmony_ci goto error; 12068c2ecf20Sopenharmony_ci } 12078c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_FW_1) 12088c2ecf20Sopenharmony_ci mdelay(3); 12098c2ecf20Sopenharmony_ci if (read_dst(state, &reply, GET_ACK)) { 12108c2ecf20Sopenharmony_ci dprintk(3, "Trying to recover..\n"); 12118c2ecf20Sopenharmony_ci if ((dst_error_recovery(state)) < 0) { 12128c2ecf20Sopenharmony_ci dprintk(2, "Recovery Failed.\n"); 12138c2ecf20Sopenharmony_ci goto error; 12148c2ecf20Sopenharmony_ci } 12158c2ecf20Sopenharmony_ci goto error; 12168c2ecf20Sopenharmony_ci } 12178c2ecf20Sopenharmony_ci if (reply != ACK) { 12188c2ecf20Sopenharmony_ci dprintk(2, "write not acknowledged 0x%02x\n", reply); 12198c2ecf20Sopenharmony_ci goto error; 12208c2ecf20Sopenharmony_ci } 12218c2ecf20Sopenharmony_ci if (len >= 2 && data[0] == 0 && (data[1] == 1 || data[1] == 3)) 12228c2ecf20Sopenharmony_ci goto error; 12238c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_FW_1) 12248c2ecf20Sopenharmony_ci mdelay(3); 12258c2ecf20Sopenharmony_ci else 12268c2ecf20Sopenharmony_ci udelay(2000); 12278c2ecf20Sopenharmony_ci if (!dst_wait_dst_ready(state, NO_DELAY)) 12288c2ecf20Sopenharmony_ci goto error; 12298c2ecf20Sopenharmony_ci if (read_dst(state, state->rxbuffer, FIXED_COMM)) { 12308c2ecf20Sopenharmony_ci dprintk(3, "Trying to recover..\n"); 12318c2ecf20Sopenharmony_ci if ((dst_error_recovery(state)) < 0) { 12328c2ecf20Sopenharmony_ci dprintk(2, "Recovery failed.\n"); 12338c2ecf20Sopenharmony_ci goto error; 12348c2ecf20Sopenharmony_ci } 12358c2ecf20Sopenharmony_ci goto error; 12368c2ecf20Sopenharmony_ci } 12378c2ecf20Sopenharmony_ci if (state->rxbuffer[7] != dst_check_sum(state->rxbuffer, 7)) { 12388c2ecf20Sopenharmony_ci dprintk(2, "checksum failure\n"); 12398c2ecf20Sopenharmony_ci goto error; 12408c2ecf20Sopenharmony_ci } 12418c2ecf20Sopenharmony_ci mutex_unlock(&state->dst_mutex); 12428c2ecf20Sopenharmony_ci return 0; 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_cierror: 12458c2ecf20Sopenharmony_ci mutex_unlock(&state->dst_mutex); 12468c2ecf20Sopenharmony_ci return -EIO; 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci} 12498c2ecf20Sopenharmony_ci 12508c2ecf20Sopenharmony_cistatic int dst_get_signal(struct dst_state *state) 12518c2ecf20Sopenharmony_ci{ 12528c2ecf20Sopenharmony_ci int retval; 12538c2ecf20Sopenharmony_ci u8 get_signal[] = { 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb }; 12548c2ecf20Sopenharmony_ci //dprintk("%s: Getting Signal strength and other parameters\n", __func__); 12558c2ecf20Sopenharmony_ci if ((state->diseq_flags & ATTEMPT_TUNE) == 0) { 12568c2ecf20Sopenharmony_ci state->decode_lock = state->decode_strength = state->decode_snr = 0; 12578c2ecf20Sopenharmony_ci return 0; 12588c2ecf20Sopenharmony_ci } 12598c2ecf20Sopenharmony_ci if (0 == (state->diseq_flags & HAS_LOCK)) { 12608c2ecf20Sopenharmony_ci state->decode_lock = state->decode_strength = state->decode_snr = 0; 12618c2ecf20Sopenharmony_ci return 0; 12628c2ecf20Sopenharmony_ci } 12638c2ecf20Sopenharmony_ci if (time_after_eq(jiffies, state->cur_jiff + (HZ / 5))) { 12648c2ecf20Sopenharmony_ci retval = dst_command(state, get_signal, 8); 12658c2ecf20Sopenharmony_ci if (retval < 0) 12668c2ecf20Sopenharmony_ci return retval; 12678c2ecf20Sopenharmony_ci if (state->dst_type == DST_TYPE_IS_SAT) { 12688c2ecf20Sopenharmony_ci state->decode_lock = ((state->rxbuffer[6] & 0x10) == 0) ? 1 : 0; 12698c2ecf20Sopenharmony_ci state->decode_strength = state->rxbuffer[5] << 8; 12708c2ecf20Sopenharmony_ci state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3]; 12718c2ecf20Sopenharmony_ci } else if ((state->dst_type == DST_TYPE_IS_TERR) || (state->dst_type == DST_TYPE_IS_CABLE)) { 12728c2ecf20Sopenharmony_ci state->decode_lock = (state->rxbuffer[1]) ? 1 : 0; 12738c2ecf20Sopenharmony_ci state->decode_strength = state->rxbuffer[4] << 8; 12748c2ecf20Sopenharmony_ci state->decode_snr = state->rxbuffer[3] << 8; 12758c2ecf20Sopenharmony_ci } else if (state->dst_type == DST_TYPE_IS_ATSC) { 12768c2ecf20Sopenharmony_ci state->decode_lock = (state->rxbuffer[6] == 0x00) ? 1 : 0; 12778c2ecf20Sopenharmony_ci state->decode_strength = state->rxbuffer[4] << 8; 12788c2ecf20Sopenharmony_ci state->decode_snr = state->rxbuffer[2] << 8 | state->rxbuffer[3]; 12798c2ecf20Sopenharmony_ci } 12808c2ecf20Sopenharmony_ci state->cur_jiff = jiffies; 12818c2ecf20Sopenharmony_ci } 12828c2ecf20Sopenharmony_ci return 0; 12838c2ecf20Sopenharmony_ci} 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_cistatic int dst_tone_power_cmd(struct dst_state *state) 12868c2ecf20Sopenharmony_ci{ 12878c2ecf20Sopenharmony_ci u8 packet[8] = { 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 }; 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci if (state->dst_type != DST_TYPE_IS_SAT) 12908c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 12918c2ecf20Sopenharmony_ci packet[4] = state->tx_tuna[4]; 12928c2ecf20Sopenharmony_ci packet[2] = state->tx_tuna[2]; 12938c2ecf20Sopenharmony_ci packet[3] = state->tx_tuna[3]; 12948c2ecf20Sopenharmony_ci packet[7] = dst_check_sum (packet, 7); 12958c2ecf20Sopenharmony_ci return dst_command(state, packet, 8); 12968c2ecf20Sopenharmony_ci} 12978c2ecf20Sopenharmony_ci 12988c2ecf20Sopenharmony_cistatic int dst_get_tuna(struct dst_state *state) 12998c2ecf20Sopenharmony_ci{ 13008c2ecf20Sopenharmony_ci int retval; 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci if ((state->diseq_flags & ATTEMPT_TUNE) == 0) 13038c2ecf20Sopenharmony_ci return 0; 13048c2ecf20Sopenharmony_ci state->diseq_flags &= ~(HAS_LOCK); 13058c2ecf20Sopenharmony_ci if (!dst_wait_dst_ready(state, NO_DELAY)) 13068c2ecf20Sopenharmony_ci return -EIO; 13078c2ecf20Sopenharmony_ci if ((state->type_flags & DST_TYPE_HAS_VLF) && 13088c2ecf20Sopenharmony_ci !(state->dst_type == DST_TYPE_IS_ATSC)) 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci retval = read_dst(state, state->rx_tuna, 10); 13118c2ecf20Sopenharmony_ci else 13128c2ecf20Sopenharmony_ci retval = read_dst(state, &state->rx_tuna[2], FIXED_COMM); 13138c2ecf20Sopenharmony_ci if (retval < 0) { 13148c2ecf20Sopenharmony_ci dprintk(3, "read not successful\n"); 13158c2ecf20Sopenharmony_ci return retval; 13168c2ecf20Sopenharmony_ci } 13178c2ecf20Sopenharmony_ci if ((state->type_flags & DST_TYPE_HAS_VLF) && 13188c2ecf20Sopenharmony_ci !(state->dst_type == DST_TYPE_IS_ATSC)) { 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[0], 9)) { 13218c2ecf20Sopenharmony_ci dprintk(2, "checksum failure ?\n"); 13228c2ecf20Sopenharmony_ci return -EIO; 13238c2ecf20Sopenharmony_ci } 13248c2ecf20Sopenharmony_ci } else { 13258c2ecf20Sopenharmony_ci if (state->rx_tuna[9] != dst_check_sum(&state->rx_tuna[2], 7)) { 13268c2ecf20Sopenharmony_ci dprintk(2, "checksum failure?\n"); 13278c2ecf20Sopenharmony_ci return -EIO; 13288c2ecf20Sopenharmony_ci } 13298c2ecf20Sopenharmony_ci } 13308c2ecf20Sopenharmony_ci if (state->rx_tuna[2] == 0 && state->rx_tuna[3] == 0) 13318c2ecf20Sopenharmony_ci return 0; 13328c2ecf20Sopenharmony_ci if (state->dst_type == DST_TYPE_IS_SAT) { 13338c2ecf20Sopenharmony_ci state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 8) + state->rx_tuna[3]; 13348c2ecf20Sopenharmony_ci } else { 13358c2ecf20Sopenharmony_ci state->decode_freq = ((state->rx_tuna[2] & 0x7f) << 16) + (state->rx_tuna[3] << 8) + state->rx_tuna[4]; 13368c2ecf20Sopenharmony_ci } 13378c2ecf20Sopenharmony_ci state->decode_freq = state->decode_freq * 1000; 13388c2ecf20Sopenharmony_ci state->decode_lock = 1; 13398c2ecf20Sopenharmony_ci state->diseq_flags |= HAS_LOCK; 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci return 1; 13428c2ecf20Sopenharmony_ci} 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_cistatic int dst_set_voltage(struct dvb_frontend *fe, 13458c2ecf20Sopenharmony_ci enum fe_sec_voltage voltage); 13468c2ecf20Sopenharmony_ci 13478c2ecf20Sopenharmony_cistatic int dst_write_tuna(struct dvb_frontend *fe) 13488c2ecf20Sopenharmony_ci{ 13498c2ecf20Sopenharmony_ci struct dst_state *state = fe->demodulator_priv; 13508c2ecf20Sopenharmony_ci int retval; 13518c2ecf20Sopenharmony_ci u8 reply; 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci dprintk(2, "type_flags 0x%x\n", state->type_flags); 13548c2ecf20Sopenharmony_ci state->decode_freq = 0; 13558c2ecf20Sopenharmony_ci state->decode_lock = state->decode_strength = state->decode_snr = 0; 13568c2ecf20Sopenharmony_ci if (state->dst_type == DST_TYPE_IS_SAT) { 13578c2ecf20Sopenharmony_ci if (!(state->diseq_flags & HAS_POWER)) 13588c2ecf20Sopenharmony_ci dst_set_voltage(fe, SEC_VOLTAGE_13); 13598c2ecf20Sopenharmony_ci } 13608c2ecf20Sopenharmony_ci state->diseq_flags &= ~(HAS_LOCK | ATTEMPT_TUNE); 13618c2ecf20Sopenharmony_ci mutex_lock(&state->dst_mutex); 13628c2ecf20Sopenharmony_ci if ((dst_comm_init(state)) < 0) { 13638c2ecf20Sopenharmony_ci dprintk(3, "DST Communication initialization failed.\n"); 13648c2ecf20Sopenharmony_ci goto error; 13658c2ecf20Sopenharmony_ci } 13668c2ecf20Sopenharmony_ci// if (state->type_flags & DST_TYPE_HAS_NEWTUNE) { 13678c2ecf20Sopenharmony_ci if ((state->type_flags & DST_TYPE_HAS_VLF) && 13688c2ecf20Sopenharmony_ci (!(state->dst_type == DST_TYPE_IS_ATSC))) { 13698c2ecf20Sopenharmony_ci 13708c2ecf20Sopenharmony_ci state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[0], 9); 13718c2ecf20Sopenharmony_ci retval = write_dst(state, &state->tx_tuna[0], 10); 13728c2ecf20Sopenharmony_ci } else { 13738c2ecf20Sopenharmony_ci state->tx_tuna[9] = dst_check_sum(&state->tx_tuna[2], 7); 13748c2ecf20Sopenharmony_ci retval = write_dst(state, &state->tx_tuna[2], FIXED_COMM); 13758c2ecf20Sopenharmony_ci } 13768c2ecf20Sopenharmony_ci if (retval < 0) { 13778c2ecf20Sopenharmony_ci dst_pio_disable(state); 13788c2ecf20Sopenharmony_ci dprintk(3, "write not successful\n"); 13798c2ecf20Sopenharmony_ci goto werr; 13808c2ecf20Sopenharmony_ci } 13818c2ecf20Sopenharmony_ci if ((dst_pio_disable(state)) < 0) { 13828c2ecf20Sopenharmony_ci dprintk(3, "DST PIO disable failed !\n"); 13838c2ecf20Sopenharmony_ci goto error; 13848c2ecf20Sopenharmony_ci } 13858c2ecf20Sopenharmony_ci if ((read_dst(state, &reply, GET_ACK) < 0)) { 13868c2ecf20Sopenharmony_ci dprintk(3, "read verify not successful.\n"); 13878c2ecf20Sopenharmony_ci goto error; 13888c2ecf20Sopenharmony_ci } 13898c2ecf20Sopenharmony_ci if (reply != ACK) { 13908c2ecf20Sopenharmony_ci dprintk(3, "write not acknowledged 0x%02x\n", reply); 13918c2ecf20Sopenharmony_ci goto error; 13928c2ecf20Sopenharmony_ci } 13938c2ecf20Sopenharmony_ci state->diseq_flags |= ATTEMPT_TUNE; 13948c2ecf20Sopenharmony_ci retval = dst_get_tuna(state); 13958c2ecf20Sopenharmony_ciwerr: 13968c2ecf20Sopenharmony_ci mutex_unlock(&state->dst_mutex); 13978c2ecf20Sopenharmony_ci return retval; 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_cierror: 14008c2ecf20Sopenharmony_ci mutex_unlock(&state->dst_mutex); 14018c2ecf20Sopenharmony_ci return -EIO; 14028c2ecf20Sopenharmony_ci} 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci/* 14058c2ecf20Sopenharmony_ci * line22k0 0x00, 0x09, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00 14068c2ecf20Sopenharmony_ci * line22k1 0x00, 0x09, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00 14078c2ecf20Sopenharmony_ci * line22k2 0x00, 0x09, 0x02, 0xff, 0x01, 0x00, 0x00, 0x00 14088c2ecf20Sopenharmony_ci * tone 0x00, 0x09, 0xff, 0x00, 0x01, 0x00, 0x00, 0x00 14098c2ecf20Sopenharmony_ci * data 0x00, 0x09, 0xff, 0x01, 0x01, 0x00, 0x00, 0x00 14108c2ecf20Sopenharmony_ci * power_off 0x00, 0x09, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 14118c2ecf20Sopenharmony_ci * power_on 0x00, 0x09, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00 14128c2ecf20Sopenharmony_ci * Diseqc 1 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec 14138c2ecf20Sopenharmony_ci * Diseqc 2 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf4, 0xe8 14148c2ecf20Sopenharmony_ci * Diseqc 3 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf8, 0xe4 14158c2ecf20Sopenharmony_ci * Diseqc 4 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xfc, 0xe0 14168c2ecf20Sopenharmony_ci */ 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_cistatic int dst_set_diseqc(struct dvb_frontend *fe, struct dvb_diseqc_master_cmd *cmd) 14198c2ecf20Sopenharmony_ci{ 14208c2ecf20Sopenharmony_ci struct dst_state *state = fe->demodulator_priv; 14218c2ecf20Sopenharmony_ci u8 packet[8] = { 0x00, 0x08, 0x04, 0xe0, 0x10, 0x38, 0xf0, 0xec }; 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci if (state->dst_type != DST_TYPE_IS_SAT) 14248c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 14258c2ecf20Sopenharmony_ci if (cmd->msg_len > 0 && cmd->msg_len < 5) 14268c2ecf20Sopenharmony_ci memcpy(&packet[3], cmd->msg, cmd->msg_len); 14278c2ecf20Sopenharmony_ci else if (cmd->msg_len == 5 && state->dst_hw_cap & DST_TYPE_HAS_DISEQC5) 14288c2ecf20Sopenharmony_ci memcpy(&packet[2], cmd->msg, cmd->msg_len); 14298c2ecf20Sopenharmony_ci else 14308c2ecf20Sopenharmony_ci return -EINVAL; 14318c2ecf20Sopenharmony_ci packet[7] = dst_check_sum(&packet[0], 7); 14328c2ecf20Sopenharmony_ci return dst_command(state, packet, 8); 14338c2ecf20Sopenharmony_ci} 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_cistatic int dst_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage) 14368c2ecf20Sopenharmony_ci{ 14378c2ecf20Sopenharmony_ci int need_cmd, retval = 0; 14388c2ecf20Sopenharmony_ci struct dst_state *state = fe->demodulator_priv; 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci state->voltage = voltage; 14418c2ecf20Sopenharmony_ci if (state->dst_type != DST_TYPE_IS_SAT) 14428c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci need_cmd = 0; 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_ci switch (voltage) { 14478c2ecf20Sopenharmony_ci case SEC_VOLTAGE_13: 14488c2ecf20Sopenharmony_ci case SEC_VOLTAGE_18: 14498c2ecf20Sopenharmony_ci if ((state->diseq_flags & HAS_POWER) == 0) 14508c2ecf20Sopenharmony_ci need_cmd = 1; 14518c2ecf20Sopenharmony_ci state->diseq_flags |= HAS_POWER; 14528c2ecf20Sopenharmony_ci state->tx_tuna[4] = 0x01; 14538c2ecf20Sopenharmony_ci break; 14548c2ecf20Sopenharmony_ci case SEC_VOLTAGE_OFF: 14558c2ecf20Sopenharmony_ci need_cmd = 1; 14568c2ecf20Sopenharmony_ci state->diseq_flags &= ~(HAS_POWER | HAS_LOCK | ATTEMPT_TUNE); 14578c2ecf20Sopenharmony_ci state->tx_tuna[4] = 0x00; 14588c2ecf20Sopenharmony_ci break; 14598c2ecf20Sopenharmony_ci default: 14608c2ecf20Sopenharmony_ci return -EINVAL; 14618c2ecf20Sopenharmony_ci } 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci if (need_cmd) 14648c2ecf20Sopenharmony_ci retval = dst_tone_power_cmd(state); 14658c2ecf20Sopenharmony_ci 14668c2ecf20Sopenharmony_ci return retval; 14678c2ecf20Sopenharmony_ci} 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_cistatic int dst_set_tone(struct dvb_frontend *fe, enum fe_sec_tone_mode tone) 14708c2ecf20Sopenharmony_ci{ 14718c2ecf20Sopenharmony_ci struct dst_state *state = fe->demodulator_priv; 14728c2ecf20Sopenharmony_ci 14738c2ecf20Sopenharmony_ci state->tone = tone; 14748c2ecf20Sopenharmony_ci if (state->dst_type != DST_TYPE_IS_SAT) 14758c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 14768c2ecf20Sopenharmony_ci 14778c2ecf20Sopenharmony_ci switch (tone) { 14788c2ecf20Sopenharmony_ci case SEC_TONE_OFF: 14798c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_OBS_REGS) 14808c2ecf20Sopenharmony_ci state->tx_tuna[2] = 0x00; 14818c2ecf20Sopenharmony_ci else 14828c2ecf20Sopenharmony_ci state->tx_tuna[2] = 0xff; 14838c2ecf20Sopenharmony_ci break; 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_ci case SEC_TONE_ON: 14868c2ecf20Sopenharmony_ci state->tx_tuna[2] = 0x02; 14878c2ecf20Sopenharmony_ci break; 14888c2ecf20Sopenharmony_ci default: 14898c2ecf20Sopenharmony_ci return -EINVAL; 14908c2ecf20Sopenharmony_ci } 14918c2ecf20Sopenharmony_ci return dst_tone_power_cmd(state); 14928c2ecf20Sopenharmony_ci} 14938c2ecf20Sopenharmony_ci 14948c2ecf20Sopenharmony_cistatic int dst_send_burst(struct dvb_frontend *fe, enum fe_sec_mini_cmd minicmd) 14958c2ecf20Sopenharmony_ci{ 14968c2ecf20Sopenharmony_ci struct dst_state *state = fe->demodulator_priv; 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci if (state->dst_type != DST_TYPE_IS_SAT) 14998c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 15008c2ecf20Sopenharmony_ci state->minicmd = minicmd; 15018c2ecf20Sopenharmony_ci switch (minicmd) { 15028c2ecf20Sopenharmony_ci case SEC_MINI_A: 15038c2ecf20Sopenharmony_ci state->tx_tuna[3] = 0x02; 15048c2ecf20Sopenharmony_ci break; 15058c2ecf20Sopenharmony_ci case SEC_MINI_B: 15068c2ecf20Sopenharmony_ci state->tx_tuna[3] = 0xff; 15078c2ecf20Sopenharmony_ci break; 15088c2ecf20Sopenharmony_ci } 15098c2ecf20Sopenharmony_ci return dst_tone_power_cmd(state); 15108c2ecf20Sopenharmony_ci} 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci 15138c2ecf20Sopenharmony_cistatic int bt8xx_dst_init(struct dvb_frontend *fe) 15148c2ecf20Sopenharmony_ci{ 15158c2ecf20Sopenharmony_ci struct dst_state *state = fe->demodulator_priv; 15168c2ecf20Sopenharmony_ci 15178c2ecf20Sopenharmony_ci static u8 sat_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x00, 0x73, 0x21, 0x00, 0x00 }; 15188c2ecf20Sopenharmony_ci static u8 sat_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x55, 0xbd, 0x50, 0x00, 0x00 }; 15198c2ecf20Sopenharmony_ci static u8 ter_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; 15208c2ecf20Sopenharmony_ci static u8 ter_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; 15218c2ecf20Sopenharmony_ci static u8 cab_tuna_188[] = { 0x09, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; 15228c2ecf20Sopenharmony_ci static u8 cab_tuna_204[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; 15238c2ecf20Sopenharmony_ci static u8 atsc_tuner[] = { 0x00, 0x00, 0x03, 0xb6, 0x01, 0x07, 0x00, 0x00, 0x00, 0x00 }; 15248c2ecf20Sopenharmony_ci 15258c2ecf20Sopenharmony_ci state->inversion = INVERSION_OFF; 15268c2ecf20Sopenharmony_ci state->voltage = SEC_VOLTAGE_13; 15278c2ecf20Sopenharmony_ci state->tone = SEC_TONE_OFF; 15288c2ecf20Sopenharmony_ci state->diseq_flags = 0; 15298c2ecf20Sopenharmony_ci state->k22 = 0x02; 15308c2ecf20Sopenharmony_ci state->bandwidth = 7000000; 15318c2ecf20Sopenharmony_ci state->cur_jiff = jiffies; 15328c2ecf20Sopenharmony_ci if (state->dst_type == DST_TYPE_IS_SAT) 15338c2ecf20Sopenharmony_ci memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? sat_tuna_188 : sat_tuna_204), sizeof (sat_tuna_204)); 15348c2ecf20Sopenharmony_ci else if (state->dst_type == DST_TYPE_IS_TERR) 15358c2ecf20Sopenharmony_ci memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? ter_tuna_188 : ter_tuna_204), sizeof (ter_tuna_204)); 15368c2ecf20Sopenharmony_ci else if (state->dst_type == DST_TYPE_IS_CABLE) 15378c2ecf20Sopenharmony_ci memcpy(state->tx_tuna, ((state->type_flags & DST_TYPE_HAS_VLF) ? cab_tuna_188 : cab_tuna_204), sizeof (cab_tuna_204)); 15388c2ecf20Sopenharmony_ci else if (state->dst_type == DST_TYPE_IS_ATSC) 15398c2ecf20Sopenharmony_ci memcpy(state->tx_tuna, atsc_tuner, sizeof (atsc_tuner)); 15408c2ecf20Sopenharmony_ci 15418c2ecf20Sopenharmony_ci return 0; 15428c2ecf20Sopenharmony_ci} 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_cistatic int dst_read_status(struct dvb_frontend *fe, enum fe_status *status) 15458c2ecf20Sopenharmony_ci{ 15468c2ecf20Sopenharmony_ci struct dst_state *state = fe->demodulator_priv; 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci *status = 0; 15498c2ecf20Sopenharmony_ci if (state->diseq_flags & HAS_LOCK) { 15508c2ecf20Sopenharmony_ci// dst_get_signal(state); // don't require(?) to ask MCU 15518c2ecf20Sopenharmony_ci if (state->decode_lock) 15528c2ecf20Sopenharmony_ci *status |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_SYNC | FE_HAS_VITERBI; 15538c2ecf20Sopenharmony_ci } 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci return 0; 15568c2ecf20Sopenharmony_ci} 15578c2ecf20Sopenharmony_ci 15588c2ecf20Sopenharmony_cistatic int dst_read_signal_strength(struct dvb_frontend *fe, u16 *strength) 15598c2ecf20Sopenharmony_ci{ 15608c2ecf20Sopenharmony_ci struct dst_state *state = fe->demodulator_priv; 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci int retval = dst_get_signal(state); 15638c2ecf20Sopenharmony_ci *strength = state->decode_strength; 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci return retval; 15668c2ecf20Sopenharmony_ci} 15678c2ecf20Sopenharmony_ci 15688c2ecf20Sopenharmony_cistatic int dst_read_snr(struct dvb_frontend *fe, u16 *snr) 15698c2ecf20Sopenharmony_ci{ 15708c2ecf20Sopenharmony_ci struct dst_state *state = fe->demodulator_priv; 15718c2ecf20Sopenharmony_ci 15728c2ecf20Sopenharmony_ci int retval = dst_get_signal(state); 15738c2ecf20Sopenharmony_ci *snr = state->decode_snr; 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_ci return retval; 15768c2ecf20Sopenharmony_ci} 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_cistatic int dst_set_frontend(struct dvb_frontend *fe) 15798c2ecf20Sopenharmony_ci{ 15808c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 15818c2ecf20Sopenharmony_ci int retval = -EINVAL; 15828c2ecf20Sopenharmony_ci struct dst_state *state = fe->demodulator_priv; 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci if (p != NULL) { 15858c2ecf20Sopenharmony_ci retval = dst_set_freq(state, p->frequency); 15868c2ecf20Sopenharmony_ci if(retval != 0) 15878c2ecf20Sopenharmony_ci return retval; 15888c2ecf20Sopenharmony_ci dprintk(3, "Set Frequency=[%d]\n", p->frequency); 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_ci if (state->dst_type == DST_TYPE_IS_SAT) { 15918c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_OBS_REGS) 15928c2ecf20Sopenharmony_ci dst_set_inversion(state, p->inversion); 15938c2ecf20Sopenharmony_ci dst_set_fec(state, p->fec_inner); 15948c2ecf20Sopenharmony_ci dst_set_symbolrate(state, p->symbol_rate); 15958c2ecf20Sopenharmony_ci dst_set_polarization(state); 15968c2ecf20Sopenharmony_ci dprintk(3, "Set Symbolrate=[%d]\n", p->symbol_rate); 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci } else if (state->dst_type == DST_TYPE_IS_TERR) 15998c2ecf20Sopenharmony_ci dst_set_bandwidth(state, p->bandwidth_hz); 16008c2ecf20Sopenharmony_ci else if (state->dst_type == DST_TYPE_IS_CABLE) { 16018c2ecf20Sopenharmony_ci dst_set_fec(state, p->fec_inner); 16028c2ecf20Sopenharmony_ci dst_set_symbolrate(state, p->symbol_rate); 16038c2ecf20Sopenharmony_ci dst_set_modulation(state, p->modulation); 16048c2ecf20Sopenharmony_ci } 16058c2ecf20Sopenharmony_ci retval = dst_write_tuna(fe); 16068c2ecf20Sopenharmony_ci } 16078c2ecf20Sopenharmony_ci 16088c2ecf20Sopenharmony_ci return retval; 16098c2ecf20Sopenharmony_ci} 16108c2ecf20Sopenharmony_ci 16118c2ecf20Sopenharmony_cistatic int dst_tune_frontend(struct dvb_frontend* fe, 16128c2ecf20Sopenharmony_ci bool re_tune, 16138c2ecf20Sopenharmony_ci unsigned int mode_flags, 16148c2ecf20Sopenharmony_ci unsigned int *delay, 16158c2ecf20Sopenharmony_ci enum fe_status *status) 16168c2ecf20Sopenharmony_ci{ 16178c2ecf20Sopenharmony_ci struct dst_state *state = fe->demodulator_priv; 16188c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p = &fe->dtv_property_cache; 16198c2ecf20Sopenharmony_ci 16208c2ecf20Sopenharmony_ci if (re_tune) { 16218c2ecf20Sopenharmony_ci dst_set_freq(state, p->frequency); 16228c2ecf20Sopenharmony_ci dprintk(3, "Set Frequency=[%d]\n", p->frequency); 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_ci if (state->dst_type == DST_TYPE_IS_SAT) { 16258c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_OBS_REGS) 16268c2ecf20Sopenharmony_ci dst_set_inversion(state, p->inversion); 16278c2ecf20Sopenharmony_ci dst_set_fec(state, p->fec_inner); 16288c2ecf20Sopenharmony_ci dst_set_symbolrate(state, p->symbol_rate); 16298c2ecf20Sopenharmony_ci dst_set_polarization(state); 16308c2ecf20Sopenharmony_ci dprintk(3, "Set Symbolrate=[%d]\n", p->symbol_rate); 16318c2ecf20Sopenharmony_ci 16328c2ecf20Sopenharmony_ci } else if (state->dst_type == DST_TYPE_IS_TERR) 16338c2ecf20Sopenharmony_ci dst_set_bandwidth(state, p->bandwidth_hz); 16348c2ecf20Sopenharmony_ci else if (state->dst_type == DST_TYPE_IS_CABLE) { 16358c2ecf20Sopenharmony_ci dst_set_fec(state, p->fec_inner); 16368c2ecf20Sopenharmony_ci dst_set_symbolrate(state, p->symbol_rate); 16378c2ecf20Sopenharmony_ci dst_set_modulation(state, p->modulation); 16388c2ecf20Sopenharmony_ci } 16398c2ecf20Sopenharmony_ci dst_write_tuna(fe); 16408c2ecf20Sopenharmony_ci } 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) 16438c2ecf20Sopenharmony_ci dst_read_status(fe, status); 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_ci *delay = HZ/10; 16468c2ecf20Sopenharmony_ci return 0; 16478c2ecf20Sopenharmony_ci} 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_cistatic enum dvbfe_algo dst_get_tuning_algo(struct dvb_frontend *fe) 16508c2ecf20Sopenharmony_ci{ 16518c2ecf20Sopenharmony_ci return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW; 16528c2ecf20Sopenharmony_ci} 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_cistatic int dst_get_frontend(struct dvb_frontend *fe, 16558c2ecf20Sopenharmony_ci struct dtv_frontend_properties *p) 16568c2ecf20Sopenharmony_ci{ 16578c2ecf20Sopenharmony_ci struct dst_state *state = fe->demodulator_priv; 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci p->frequency = state->decode_freq; 16608c2ecf20Sopenharmony_ci if (state->dst_type == DST_TYPE_IS_SAT) { 16618c2ecf20Sopenharmony_ci if (state->type_flags & DST_TYPE_HAS_OBS_REGS) 16628c2ecf20Sopenharmony_ci p->inversion = state->inversion; 16638c2ecf20Sopenharmony_ci p->symbol_rate = state->symbol_rate; 16648c2ecf20Sopenharmony_ci p->fec_inner = dst_get_fec(state); 16658c2ecf20Sopenharmony_ci } else if (state->dst_type == DST_TYPE_IS_TERR) { 16668c2ecf20Sopenharmony_ci p->bandwidth_hz = state->bandwidth; 16678c2ecf20Sopenharmony_ci } else if (state->dst_type == DST_TYPE_IS_CABLE) { 16688c2ecf20Sopenharmony_ci p->symbol_rate = state->symbol_rate; 16698c2ecf20Sopenharmony_ci p->fec_inner = dst_get_fec(state); 16708c2ecf20Sopenharmony_ci p->modulation = dst_get_modulation(state); 16718c2ecf20Sopenharmony_ci } 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_ci return 0; 16748c2ecf20Sopenharmony_ci} 16758c2ecf20Sopenharmony_ci 16768c2ecf20Sopenharmony_cistatic void bt8xx_dst_release(struct dvb_frontend *fe) 16778c2ecf20Sopenharmony_ci{ 16788c2ecf20Sopenharmony_ci struct dst_state *state = fe->demodulator_priv; 16798c2ecf20Sopenharmony_ci if (state->dst_ca) { 16808c2ecf20Sopenharmony_ci dvb_unregister_device(state->dst_ca); 16818c2ecf20Sopenharmony_ci#ifdef CONFIG_MEDIA_ATTACH 16828c2ecf20Sopenharmony_ci symbol_put(dst_ca_attach); 16838c2ecf20Sopenharmony_ci#endif 16848c2ecf20Sopenharmony_ci } 16858c2ecf20Sopenharmony_ci kfree(state); 16868c2ecf20Sopenharmony_ci} 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dst_dvbt_ops; 16898c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dst_dvbs_ops; 16908c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dst_dvbc_ops; 16918c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dst_atsc_ops; 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_cistruct dst_state *dst_attach(struct dst_state *state, struct dvb_adapter *dvb_adapter) 16948c2ecf20Sopenharmony_ci{ 16958c2ecf20Sopenharmony_ci /* check if the ASIC is there */ 16968c2ecf20Sopenharmony_ci if (dst_probe(state) < 0) { 16978c2ecf20Sopenharmony_ci kfree(state); 16988c2ecf20Sopenharmony_ci return NULL; 16998c2ecf20Sopenharmony_ci } 17008c2ecf20Sopenharmony_ci /* determine settings based on type */ 17018c2ecf20Sopenharmony_ci /* create dvb_frontend */ 17028c2ecf20Sopenharmony_ci switch (state->dst_type) { 17038c2ecf20Sopenharmony_ci case DST_TYPE_IS_TERR: 17048c2ecf20Sopenharmony_ci memcpy(&state->frontend.ops, &dst_dvbt_ops, sizeof(struct dvb_frontend_ops)); 17058c2ecf20Sopenharmony_ci break; 17068c2ecf20Sopenharmony_ci case DST_TYPE_IS_CABLE: 17078c2ecf20Sopenharmony_ci memcpy(&state->frontend.ops, &dst_dvbc_ops, sizeof(struct dvb_frontend_ops)); 17088c2ecf20Sopenharmony_ci break; 17098c2ecf20Sopenharmony_ci case DST_TYPE_IS_SAT: 17108c2ecf20Sopenharmony_ci memcpy(&state->frontend.ops, &dst_dvbs_ops, sizeof(struct dvb_frontend_ops)); 17118c2ecf20Sopenharmony_ci break; 17128c2ecf20Sopenharmony_ci case DST_TYPE_IS_ATSC: 17138c2ecf20Sopenharmony_ci memcpy(&state->frontend.ops, &dst_atsc_ops, sizeof(struct dvb_frontend_ops)); 17148c2ecf20Sopenharmony_ci break; 17158c2ecf20Sopenharmony_ci default: 17168c2ecf20Sopenharmony_ci pr_err("unknown DST type. please report to the LinuxTV.org DVB mailinglist.\n"); 17178c2ecf20Sopenharmony_ci kfree(state); 17188c2ecf20Sopenharmony_ci return NULL; 17198c2ecf20Sopenharmony_ci } 17208c2ecf20Sopenharmony_ci state->frontend.demodulator_priv = state; 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci return state; /* Manu (DST is a card not a frontend) */ 17238c2ecf20Sopenharmony_ci} 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dst_attach); 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dst_dvbt_ops = { 17288c2ecf20Sopenharmony_ci .delsys = { SYS_DVBT }, 17298c2ecf20Sopenharmony_ci .info = { 17308c2ecf20Sopenharmony_ci .name = "DST DVB-T", 17318c2ecf20Sopenharmony_ci .frequency_min_hz = 137 * MHz, 17328c2ecf20Sopenharmony_ci .frequency_max_hz = 858 * MHz, 17338c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 166667, 17348c2ecf20Sopenharmony_ci .caps = FE_CAN_FEC_AUTO | 17358c2ecf20Sopenharmony_ci FE_CAN_QAM_AUTO | 17368c2ecf20Sopenharmony_ci FE_CAN_QAM_16 | 17378c2ecf20Sopenharmony_ci FE_CAN_QAM_32 | 17388c2ecf20Sopenharmony_ci FE_CAN_QAM_64 | 17398c2ecf20Sopenharmony_ci FE_CAN_QAM_128 | 17408c2ecf20Sopenharmony_ci FE_CAN_QAM_256 | 17418c2ecf20Sopenharmony_ci FE_CAN_TRANSMISSION_MODE_AUTO | 17428c2ecf20Sopenharmony_ci FE_CAN_GUARD_INTERVAL_AUTO 17438c2ecf20Sopenharmony_ci }, 17448c2ecf20Sopenharmony_ci 17458c2ecf20Sopenharmony_ci .release = bt8xx_dst_release, 17468c2ecf20Sopenharmony_ci .init = bt8xx_dst_init, 17478c2ecf20Sopenharmony_ci .tune = dst_tune_frontend, 17488c2ecf20Sopenharmony_ci .set_frontend = dst_set_frontend, 17498c2ecf20Sopenharmony_ci .get_frontend = dst_get_frontend, 17508c2ecf20Sopenharmony_ci .get_frontend_algo = dst_get_tuning_algo, 17518c2ecf20Sopenharmony_ci .read_status = dst_read_status, 17528c2ecf20Sopenharmony_ci .read_signal_strength = dst_read_signal_strength, 17538c2ecf20Sopenharmony_ci .read_snr = dst_read_snr, 17548c2ecf20Sopenharmony_ci}; 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dst_dvbs_ops = { 17578c2ecf20Sopenharmony_ci .delsys = { SYS_DVBS }, 17588c2ecf20Sopenharmony_ci .info = { 17598c2ecf20Sopenharmony_ci .name = "DST DVB-S", 17608c2ecf20Sopenharmony_ci .frequency_min_hz = 950 * MHz, 17618c2ecf20Sopenharmony_ci .frequency_max_hz = 2150 * MHz, 17628c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 1 * MHz, 17638c2ecf20Sopenharmony_ci .frequency_tolerance_hz = 29500 * kHz, 17648c2ecf20Sopenharmony_ci .symbol_rate_min = 1000000, 17658c2ecf20Sopenharmony_ci .symbol_rate_max = 45000000, 17668c2ecf20Sopenharmony_ci /* . symbol_rate_tolerance = ???,*/ 17678c2ecf20Sopenharmony_ci .caps = FE_CAN_FEC_AUTO | FE_CAN_QPSK 17688c2ecf20Sopenharmony_ci }, 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_ci .release = bt8xx_dst_release, 17718c2ecf20Sopenharmony_ci .init = bt8xx_dst_init, 17728c2ecf20Sopenharmony_ci .tune = dst_tune_frontend, 17738c2ecf20Sopenharmony_ci .set_frontend = dst_set_frontend, 17748c2ecf20Sopenharmony_ci .get_frontend = dst_get_frontend, 17758c2ecf20Sopenharmony_ci .get_frontend_algo = dst_get_tuning_algo, 17768c2ecf20Sopenharmony_ci .read_status = dst_read_status, 17778c2ecf20Sopenharmony_ci .read_signal_strength = dst_read_signal_strength, 17788c2ecf20Sopenharmony_ci .read_snr = dst_read_snr, 17798c2ecf20Sopenharmony_ci .diseqc_send_burst = dst_send_burst, 17808c2ecf20Sopenharmony_ci .diseqc_send_master_cmd = dst_set_diseqc, 17818c2ecf20Sopenharmony_ci .set_voltage = dst_set_voltage, 17828c2ecf20Sopenharmony_ci .set_tone = dst_set_tone, 17838c2ecf20Sopenharmony_ci}; 17848c2ecf20Sopenharmony_ci 17858c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dst_dvbc_ops = { 17868c2ecf20Sopenharmony_ci .delsys = { SYS_DVBC_ANNEX_A }, 17878c2ecf20Sopenharmony_ci .info = { 17888c2ecf20Sopenharmony_ci .name = "DST DVB-C", 17898c2ecf20Sopenharmony_ci .frequency_min_hz = 51 * MHz, 17908c2ecf20Sopenharmony_ci .frequency_max_hz = 858 * MHz, 17918c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 62500, 17928c2ecf20Sopenharmony_ci .symbol_rate_min = 1000000, 17938c2ecf20Sopenharmony_ci .symbol_rate_max = 45000000, 17948c2ecf20Sopenharmony_ci .caps = FE_CAN_FEC_AUTO | 17958c2ecf20Sopenharmony_ci FE_CAN_QAM_AUTO | 17968c2ecf20Sopenharmony_ci FE_CAN_QAM_16 | 17978c2ecf20Sopenharmony_ci FE_CAN_QAM_32 | 17988c2ecf20Sopenharmony_ci FE_CAN_QAM_64 | 17998c2ecf20Sopenharmony_ci FE_CAN_QAM_128 | 18008c2ecf20Sopenharmony_ci FE_CAN_QAM_256 18018c2ecf20Sopenharmony_ci }, 18028c2ecf20Sopenharmony_ci 18038c2ecf20Sopenharmony_ci .release = bt8xx_dst_release, 18048c2ecf20Sopenharmony_ci .init = bt8xx_dst_init, 18058c2ecf20Sopenharmony_ci .tune = dst_tune_frontend, 18068c2ecf20Sopenharmony_ci .set_frontend = dst_set_frontend, 18078c2ecf20Sopenharmony_ci .get_frontend = dst_get_frontend, 18088c2ecf20Sopenharmony_ci .get_frontend_algo = dst_get_tuning_algo, 18098c2ecf20Sopenharmony_ci .read_status = dst_read_status, 18108c2ecf20Sopenharmony_ci .read_signal_strength = dst_read_signal_strength, 18118c2ecf20Sopenharmony_ci .read_snr = dst_read_snr, 18128c2ecf20Sopenharmony_ci}; 18138c2ecf20Sopenharmony_ci 18148c2ecf20Sopenharmony_cistatic const struct dvb_frontend_ops dst_atsc_ops = { 18158c2ecf20Sopenharmony_ci .delsys = { SYS_ATSC }, 18168c2ecf20Sopenharmony_ci .info = { 18178c2ecf20Sopenharmony_ci .name = "DST ATSC", 18188c2ecf20Sopenharmony_ci .frequency_min_hz = 510 * MHz, 18198c2ecf20Sopenharmony_ci .frequency_max_hz = 858 * MHz, 18208c2ecf20Sopenharmony_ci .frequency_stepsize_hz = 62500, 18218c2ecf20Sopenharmony_ci .symbol_rate_min = 1000000, 18228c2ecf20Sopenharmony_ci .symbol_rate_max = 45000000, 18238c2ecf20Sopenharmony_ci .caps = FE_CAN_FEC_AUTO | FE_CAN_QAM_AUTO | FE_CAN_QAM_64 | FE_CAN_QAM_256 | FE_CAN_8VSB 18248c2ecf20Sopenharmony_ci }, 18258c2ecf20Sopenharmony_ci 18268c2ecf20Sopenharmony_ci .release = bt8xx_dst_release, 18278c2ecf20Sopenharmony_ci .init = bt8xx_dst_init, 18288c2ecf20Sopenharmony_ci .tune = dst_tune_frontend, 18298c2ecf20Sopenharmony_ci .set_frontend = dst_set_frontend, 18308c2ecf20Sopenharmony_ci .get_frontend = dst_get_frontend, 18318c2ecf20Sopenharmony_ci .get_frontend_algo = dst_get_tuning_algo, 18328c2ecf20Sopenharmony_ci .read_status = dst_read_status, 18338c2ecf20Sopenharmony_ci .read_signal_strength = dst_read_signal_strength, 18348c2ecf20Sopenharmony_ci .read_snr = dst_read_snr, 18358c2ecf20Sopenharmony_ci}; 18368c2ecf20Sopenharmony_ci 18378c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("DST DVB-S/T/C/ATSC Combo Frontend driver"); 18388c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jamie Honan, Manu Abraham"); 18398c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1840