18d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri/* 28d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * Driver for Xceive XC4000 "QAM/8VSB single chip tuner" 38d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * 48d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * Copyright (c) 2007 Xceive Corporation 58d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * Copyright (c) 2007 Steven Toth <stoth@linuxtv.org> 68d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * Copyright (c) 2009 Devin Heitmueller <dheitmueller@kernellabs.com> 78d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * Copyright (c) 2009 Davide Ferri <d.ferri@zero11.it> 8341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu * Copyright (c) 2010 Istvan Varga <istvan_v@mailbox.hu> 98d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * 108d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * This program is free software; you can redistribute it and/or modify 118d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * it under the terms of the GNU General Public License as published by 128d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * the Free Software Foundation; either version 2 of the License, or 138d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * (at your option) any later version. 148d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * 158d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * This program is distributed in the hope that it will be useful, 168d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * but WITHOUT ANY WARRANTY; without even the implied warranty of 178d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 188d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * GNU General Public License for more details. 198d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * 208d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * You should have received a copy of the GNU General Public License 218d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * along with this program; if not, write to the Free Software 228d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 238d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri */ 248d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 258d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#include <linux/module.h> 268d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#include <linux/moduleparam.h> 278d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#include <linux/videodev2.h> 288d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#include <linux/delay.h> 298d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#include <linux/dvb/frontend.h> 308d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#include <linux/i2c.h> 315614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga#include <linux/mutex.h> 3211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller#include <asm/unaligned.h> 338d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 348d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#include "dvb_frontend.h" 358d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 368d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#include "xc4000.h" 378d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#include "tuner-i2c.h" 3811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller#include "tuner-xc2028-types.h" 398d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 404922cec59a1b37d49b3e01577ab2f779a13b3ae6Devin Heitmuellerstatic int debug; 418d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferrimodule_param(debug, int, 0644); 42341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.huMODULE_PARM_DESC(debug, "Debugging level (0 to 2, default: 0 (off))."); 438d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 448d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int no_poweroff; 458d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferrimodule_param(no_poweroff, int, 0644); 46341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.huMODULE_PARM_DESC(no_poweroff, "Power management (1: disabled, 2: enabled, " 47341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu "0 (default): use device-specific default mode)."); 48923137a4037d1b9f19d175708eeced209dff9320Istvan Varga 49923137a4037d1b9f19d175708eeced209dff9320Istvan Vargastatic int audio_std; 50923137a4037d1b9f19d175708eeced209dff9320Istvan Vargamodule_param(audio_std, int, 0644); 51341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.huMODULE_PARM_DESC(audio_std, "Audio standard. XC4000 audio decoder explicitly " 52341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu "needs to know what audio standard is needed for some video standards " 53341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu "with audio A2 or NICAM. The valid settings are a sum of:\n" 54341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu " 1: use NICAM/B or A2/B instead of NICAM/A or A2/A\n" 55341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu " 2: use A2 instead of NICAM or BTSC\n" 56341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu " 4: use SECAM/K3 instead of K1\n" 57341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu " 8: use PAL-D/K audio for SECAM-D/K\n" 58341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu "16: use FM radio input 1 instead of input 2\n" 59341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu "32: use mono audio (the lower three bits are ignored)"); 60fa285bc1bf5a2ebe3252523454def096d86a064bIstvan Varga 61fa285bc1bf5a2ebe3252523454def096d86a064bIstvan Vargastatic char firmware_name[30]; 62fa285bc1bf5a2ebe3252523454def096d86a064bIstvan Vargamodule_param_string(firmware_name, firmware_name, sizeof(firmware_name), 0); 63341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.huMODULE_PARM_DESC(firmware_name, "Firmware file name. Allows overriding the " 64341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu "default firmware name."); 65fa285bc1bf5a2ebe3252523454def096d86a064bIstvan Varga 668d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic DEFINE_MUTEX(xc4000_list_mutex); 678d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic LIST_HEAD(hybrid_tuner_instance_list); 688d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 698d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define dprintk(level, fmt, arg...) if (debug >= level) \ 708d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri printk(KERN_INFO "%s: " fmt, "xc4000", ## arg) 718d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 7211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller/* struct for storing firmware table */ 7311091a31fbf7496294795ca72d69db0233857d94Devin Heitmuellerstruct firmware_description { 7411091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller unsigned int type; 7511091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller v4l2_std_id id; 7611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller __u16 int_freq; 7711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller unsigned char *ptr; 7811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller unsigned int size; 7911091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller}; 8011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 8111091a31fbf7496294795ca72d69db0233857d94Devin Heitmuellerstruct firmware_properties { 8211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller unsigned int type; 8311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller v4l2_std_id id; 8411091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller v4l2_std_id std_req; 8511091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller __u16 int_freq; 8611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller unsigned int scode_table; 87e3bb7c607f5ca87030692ad4dab653b4a8d1571aMauro Carvalho Chehab int scode_nr; 8811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller}; 898d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 908d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristruct xc4000_priv { 918d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct tuner_i2c_props i2c_props; 928d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct list_head hybrid_tuner_instance_list; 9311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller struct firmware_description *firm; 94fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga int firm_size; 95fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u32 if_khz; 964c07e32884ab69574cfd9eb4de3334233c938071Mauro Carvalho Chehab u32 freq_hz, freq_offset; 97fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u32 bandwidth; 98fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u8 video_standard; 99fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u8 rf_mode; 1008edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu u8 default_pm; 1018edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu u8 dvb_amplitude; 1028edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu u8 set_smoothedcvbs; 103fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u8 ignore_i2c_write_errors; 1048edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu __u16 firm_version; 105d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller struct firmware_properties cur_fw; 106fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga __u16 hwmodel; 107fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga __u16 hwvers; 1085614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga struct mutex lock; 1098d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri}; 1108d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 111341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu#define XC4000_AUDIO_STD_B 1 112341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu#define XC4000_AUDIO_STD_A2 2 113341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu#define XC4000_AUDIO_STD_K3 4 114341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu#define XC4000_AUDIO_STD_L 8 115341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu#define XC4000_AUDIO_STD_INPUT1 16 116341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu#define XC4000_AUDIO_STD_MONO 32 117341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu 118341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu#define XC4000_DEFAULT_FIRMWARE "dvb-fe-xc4000-1.4.fw" 119da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab#define XC4000_DEFAULT_FIRMWARE_NEW "dvb-fe-xc4000-1.4.1.fw" 120341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu 1218d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri/* Misc Defines */ 1224911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga#define MAX_TV_STANDARD 24 1238d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XC_MAX_I2C_WRITE_LENGTH 64 1245272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga#define XC_POWERED_DOWN 0x80000000U 1258d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1268d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri/* Signal Types */ 1278d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XC_RF_MODE_AIR 0 1288d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XC_RF_MODE_CABLE 1 1298d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1308d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri/* Product id */ 1318d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XC_PRODUCT_ID_FW_NOT_LOADED 0x2000 1327db98fe66be035494912b6b2c4e9c1e3abfedfe5Istvan Varga#define XC_PRODUCT_ID_XC4000 0x0FA0 1337db98fe66be035494912b6b2c4e9c1e3abfedfe5Istvan Varga#define XC_PRODUCT_ID_XC4100 0x1004 1348d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 135ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller/* Registers (Write-only) */ 1368d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XREG_INIT 0x00 1378d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XREG_VIDEO_MODE 0x01 1388d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XREG_AUDIO_MODE 0x02 1398d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XREG_RF_FREQ 0x03 1408d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XREG_D_CODE 0x04 141ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller#define XREG_DIRECTSITTING_MODE 0x05 142ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller#define XREG_SEEK_MODE 0x06 143ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller#define XREG_POWER_DOWN 0x08 144ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller#define XREG_SIGNALSOURCE 0x0A 14530f544ec56eefc628e73e23324dc18105ad13012Istvan Varga#define XREG_SMOOTHEDCVBS 0x0E 146ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller#define XREG_AMPLITUDE 0x10 1478d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 148ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller/* Registers (Read-only) */ 1498d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XREG_ADC_ENV 0x00 1508d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XREG_QUALITY 0x01 1518d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XREG_FRAME_LINES 0x02 1528d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XREG_HSYNC_FREQ 0x03 1538d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XREG_LOCK 0x04 1548d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XREG_FREQ_ERROR 0x05 1558d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XREG_SNR 0x06 1568d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XREG_VERSION 0x07 1578d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri#define XREG_PRODUCT_ID 0x08 1588a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen#define XREG_SIGNAL_LEVEL 0x0A 1598a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen#define XREG_NOISE_LEVEL 0x0B 1608d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1618d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri/* 1628d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri Basic firmware description. This will remain with 1638d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri the driver for documentation purposes. 1648d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1658d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri This represents an I2C firmware file encoded as a 1668d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri string of unsigned char. Format is as follows: 1678d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1688d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri char[0 ]=len0_MSB -> len = len_MSB * 256 + len_LSB 1698d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri char[1 ]=len0_LSB -> length of first write transaction 1708d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri char[2 ]=data0 -> first byte to be sent 1718d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri char[3 ]=data1 1728d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri char[4 ]=data2 1738d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri char[ ]=... 1748d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri char[M ]=dataN -> last byte to be sent 1758d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri char[M+1]=len1_MSB -> len = len_MSB * 256 + len_LSB 1768d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri char[M+2]=len1_LSB -> length of second write transaction 1778d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri char[M+3]=data0 1788d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri char[M+4]=data1 1798d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri ... 1808d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri etc. 1818d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1828d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri The [len] value should be interpreted as follows: 1838d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1848d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri len= len_MSB _ len_LSB 1858d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri len=1111_1111_1111_1111 : End of I2C_SEQUENCE 1868d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri len=0000_0000_0000_0000 : Reset command: Do hardware reset 1878d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri len=0NNN_NNNN_NNNN_NNNN : Normal transaction: number of bytes = {1:32767) 1888d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri len=1WWW_WWWW_WWWW_WWWW : Wait command: wait for {1:32767} ms 1898d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1908d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri For the RESET and WAIT commands, the two following bytes will contain 1918d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri immediately the length of the following transaction. 1928d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri*/ 193fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga 1948d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristruct XC_TV_STANDARD { 195fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga const char *Name; 196341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu u16 audio_mode; 197341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu u16 video_mode; 1984911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga u16 int_freq; 1998d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri}; 2008d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 2018d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri/* Tuner standards */ 202ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller#define XC4000_MN_NTSC_PAL_BTSC 0 203ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller#define XC4000_MN_NTSC_PAL_A2 1 204ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller#define XC4000_MN_NTSC_PAL_EIAJ 2 205ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller#define XC4000_MN_NTSC_PAL_Mono 3 206ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller#define XC4000_BG_PAL_A2 4 207ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller#define XC4000_BG_PAL_NICAM 5 208ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller#define XC4000_BG_PAL_MONO 6 209ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller#define XC4000_I_PAL_NICAM 7 210ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller#define XC4000_I_PAL_NICAM_MONO 8 211ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller#define XC4000_DK_PAL_A2 9 212ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller#define XC4000_DK_PAL_NICAM 10 213ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller#define XC4000_DK_PAL_MONO 11 214ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller#define XC4000_DK_SECAM_A2DK1 12 215e3bb7c607f5ca87030692ad4dab653b4a8d1571aMauro Carvalho Chehab#define XC4000_DK_SECAM_A2LDK3 13 216e3bb7c607f5ca87030692ad4dab653b4a8d1571aMauro Carvalho Chehab#define XC4000_DK_SECAM_A2MONO 14 2174911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga#define XC4000_DK_SECAM_NICAM 15 2184911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga#define XC4000_L_SECAM_NICAM 16 2194911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga#define XC4000_LC_SECAM_NICAM 17 2204911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga#define XC4000_DTV6 18 2214911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga#define XC4000_DTV8 19 2224911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga#define XC4000_DTV7_8 20 2234911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga#define XC4000_DTV7 21 2244911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga#define XC4000_FM_Radio_INPUT2 22 2254911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga#define XC4000_FM_Radio_INPUT1 23 2268d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 227341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hustatic struct XC_TV_STANDARD xc4000_standard[MAX_TV_STANDARD] = { 2284911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"M/N-NTSC/PAL-BTSC", 0x0000, 0x80A0, 4500}, 2294911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"M/N-NTSC/PAL-A2", 0x0000, 0x80A0, 4600}, 2304911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"M/N-NTSC/PAL-EIAJ", 0x0040, 0x80A0, 4500}, 2314911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"M/N-NTSC/PAL-Mono", 0x0078, 0x80A0, 4500}, 2324911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"B/G-PAL-A2", 0x0000, 0x8159, 5640}, 2334911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"B/G-PAL-NICAM", 0x0004, 0x8159, 5740}, 2344911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"B/G-PAL-MONO", 0x0078, 0x8159, 5500}, 2354911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"I-PAL-NICAM", 0x0080, 0x8049, 6240}, 2364911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"I-PAL-NICAM-MONO", 0x0078, 0x8049, 6000}, 2374911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"D/K-PAL-A2", 0x0000, 0x8049, 6380}, 2384911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"D/K-PAL-NICAM", 0x0080, 0x8049, 6200}, 2394911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"D/K-PAL-MONO", 0x0078, 0x8049, 6500}, 2404911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"D/K-SECAM-A2 DK1", 0x0000, 0x8049, 6340}, 2414911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"D/K-SECAM-A2 L/DK3", 0x0000, 0x8049, 6000}, 2424911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"D/K-SECAM-A2 MONO", 0x0078, 0x8049, 6500}, 2434911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"D/K-SECAM-NICAM", 0x0080, 0x8049, 6200}, 2444911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"L-SECAM-NICAM", 0x8080, 0x0009, 6200}, 2454911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"L'-SECAM-NICAM", 0x8080, 0x4009, 6200}, 2464911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"DTV6", 0x00C0, 0x8002, 0}, 2474911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"DTV8", 0x00C0, 0x800B, 0}, 2484911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"DTV7/8", 0x00C0, 0x801B, 0}, 2494911085fa3342d2ccb04f84c2987305b86785ebfIstvan Varga {"DTV7", 0x00C0, 0x8007, 0}, 250941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab {"FM Radio-INPUT2", 0x0008, 0x9800, 10700}, 251941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab {"FM Radio-INPUT1", 0x0008, 0x9000, 10700} 2528d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri}; 2538d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 2548d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val); 255341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hustatic int xc4000_tuner_reset(struct dvb_frontend *fe); 256f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Vargastatic void xc_debug_dump(struct xc4000_priv *priv); 2578d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 2588d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len) 2598d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 2608d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct i2c_msg msg = { .addr = priv->i2c_props.addr, 2618d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .flags = 0, .buf = buf, .len = len }; 2628d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if (i2c_transfer(priv->i2c_props.adap, &msg, 1) != 1) { 263799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller if (priv->ignore_i2c_write_errors == 0) { 264799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n", 265799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller len); 266799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller if (len == 4) { 267c6480cccdbaf1e9f3d1489c0530f011543cca90bAndy Shevchenko printk(KERN_ERR "bytes %*ph\n", 4, buf); 268799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller } 269341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu return -EREMOTEIO; 270799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller } 2718d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 272341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu return 0; 2738d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 2748d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 275341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hustatic int xc4000_tuner_reset(struct dvb_frontend *fe) 2768d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 2778d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct xc4000_priv *priv = fe->tuner_priv; 2788d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri int ret; 2798d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 2808d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "%s()\n", __func__); 2818d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 2828d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if (fe->callback) { 2838d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri ret = fe->callback(((fe->dvb) && (fe->dvb->priv)) ? 2848d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri fe->dvb->priv : 2858d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri priv->i2c_props.adap->algo_data, 2868d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri DVB_FRONTEND_COMPONENT_TUNER, 2878d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri XC4000_TUNER_RESET, 0); 2888d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if (ret) { 2898d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri printk(KERN_ERR "xc4000: reset failed\n"); 290341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu return -EREMOTEIO; 2918d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 2928d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } else { 293341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu printk(KERN_ERR "xc4000: no tuner reset callback function, " 294341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu "fatal\n"); 295341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu return -EINVAL; 2968d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 297341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu return 0; 2988d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 2998d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 3008d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc_write_reg(struct xc4000_priv *priv, u16 regAddr, u16 i2cData) 3018d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 3028d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri u8 buf[4]; 3038d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri int result; 3048d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 3058d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri buf[0] = (regAddr >> 8) & 0xFF; 3068d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri buf[1] = regAddr & 0xFF; 3078d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri buf[2] = (i2cData >> 8) & 0xFF; 3088d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri buf[3] = i2cData & 0xFF; 3098d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri result = xc_send_i2c_data(priv, buf, 4); 3108d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 3118d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return result; 3128d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 3138d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 3148d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc_load_i2c_sequence(struct dvb_frontend *fe, const u8 *i2c_sequence) 3158d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 3168d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct xc4000_priv *priv = fe->tuner_priv; 3178d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 3188d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri int i, nbytes_to_send, result; 3198d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri unsigned int len, pos, index; 3208d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri u8 buf[XC_MAX_I2C_WRITE_LENGTH]; 3218d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 3228d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri index = 0; 3238d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri while ((i2c_sequence[index] != 0xFF) || 3248d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri (i2c_sequence[index + 1] != 0xFF)) { 3258d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri len = i2c_sequence[index] * 256 + i2c_sequence[index+1]; 3268d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if (len == 0x0000) { 3278d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri /* RESET command */ 328341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu /* NOTE: this is ignored, as the reset callback was */ 329341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu /* already called by check_firmware() */ 3308d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri index += 2; 3318d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } else if (len & 0x8000) { 3328d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri /* WAIT command */ 333341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu msleep(len & 0x7FFF); 3348d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri index += 2; 3358d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } else { 3368d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri /* Send i2c data whilst ensuring individual transactions 3378d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri * do not exceed XC_MAX_I2C_WRITE_LENGTH bytes. 3388d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri */ 3398d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri index += 2; 3408d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri buf[0] = i2c_sequence[index]; 3418d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri buf[1] = i2c_sequence[index + 1]; 3428d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri pos = 2; 3438d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri while (pos < len) { 3448d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if ((len - pos) > XC_MAX_I2C_WRITE_LENGTH - 2) 3458d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri nbytes_to_send = 3468d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri XC_MAX_I2C_WRITE_LENGTH; 3478d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri else 3488d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri nbytes_to_send = (len - pos + 2); 3498d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri for (i = 2; i < nbytes_to_send; i++) { 3508d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri buf[i] = i2c_sequence[index + pos + 3518d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri i - 2]; 3528d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 3538d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri result = xc_send_i2c_data(priv, buf, 3548d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri nbytes_to_send); 3558d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 356341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (result != 0) 3578d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return result; 3588d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 3598d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri pos += nbytes_to_send - 2; 3608d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 3618d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri index += len; 3628d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 3638d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 364341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu return 0; 3658d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 3668d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 367341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hustatic int xc_set_tv_standard(struct xc4000_priv *priv, 368341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu u16 video_mode, u16 audio_mode) 3698d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 3708d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri int ret; 371341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu dprintk(1, "%s(0x%04x,0x%04x)\n", __func__, video_mode, audio_mode); 3728d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "%s() Standard = %s\n", 3738d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri __func__, 374341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu xc4000_standard[priv->video_standard].Name); 3758d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 376799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller /* Don't complain when the request fails because of i2c stretching */ 377799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller priv->ignore_i2c_write_errors = 1; 378799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller 379341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu ret = xc_write_reg(priv, XREG_VIDEO_MODE, video_mode); 380341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (ret == 0) 381341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu ret = xc_write_reg(priv, XREG_AUDIO_MODE, audio_mode); 3828d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 383799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller priv->ignore_i2c_write_errors = 0; 384799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller 3858d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return ret; 3868d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 3878d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 388341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hustatic int xc_set_signal_source(struct xc4000_priv *priv, u16 rf_mode) 3898d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 3908d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "%s(%d) Source = %s\n", __func__, rf_mode, 3918d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri rf_mode == XC_RF_MODE_AIR ? "ANTENNA" : "CABLE"); 3928d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 3938d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if ((rf_mode != XC_RF_MODE_AIR) && (rf_mode != XC_RF_MODE_CABLE)) { 3948d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri rf_mode = XC_RF_MODE_CABLE; 3958d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri printk(KERN_ERR 3968d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri "%s(), Invalid mode, defaulting to CABLE", 3978d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri __func__); 3988d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 3998d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return xc_write_reg(priv, XREG_SIGNALSOURCE, rf_mode); 4008d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 4018d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4028d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic const struct dvb_tuner_ops xc4000_tuner_ops; 4038d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 404341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hustatic int xc_set_rf_frequency(struct xc4000_priv *priv, u32 freq_hz) 4058d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 4068d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri u16 freq_code; 4078d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4088d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "%s(%u)\n", __func__, freq_hz); 4098d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4108d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if ((freq_hz > xc4000_tuner_ops.info.frequency_max) || 411341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu (freq_hz < xc4000_tuner_ops.info.frequency_min)) 412341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu return -EINVAL; 4138d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4148d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri freq_code = (u16)(freq_hz / 15625); 4158d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4168d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri /* WAS: Starting in firmware version 1.1.44, Xceive recommends using the 4178d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri FINERFREQ for all normal tuning (the doc indicates reg 0x03 should 4188d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri only be used for fast scanning for channel lock) */ 419341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu /* WAS: XREG_FINERFREQ */ 420341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu return xc_write_reg(priv, XREG_RF_FREQ, freq_code); 4218d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 4228d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 423341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hustatic int xc_get_adc_envelope(struct xc4000_priv *priv, u16 *adc_envelope) 4248d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 4258d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return xc4000_readreg(priv, XREG_ADC_ENV, adc_envelope); 4268d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 4278d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4288d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc_get_frequency_error(struct xc4000_priv *priv, u32 *freq_error_hz) 4298d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 4308d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri int result; 4318d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri u16 regData; 4328d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri u32 tmp; 4338d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4348d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri result = xc4000_readreg(priv, XREG_FREQ_ERROR, ®Data); 435341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (result != 0) 4368d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return result; 4378d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4381368ceb266990af58a72cdb0e121eb4ff22bde6fIstvan Varga tmp = (u32)regData & 0xFFFFU; 4391368ceb266990af58a72cdb0e121eb4ff22bde6fIstvan Varga tmp = (tmp < 0x8000U ? tmp : 0x10000U - tmp); 4401368ceb266990af58a72cdb0e121eb4ff22bde6fIstvan Varga (*freq_error_hz) = tmp * 15625; 4418d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return result; 4428d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 4438d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4448d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc_get_lock_status(struct xc4000_priv *priv, u16 *lock_status) 4458d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 4468d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return xc4000_readreg(priv, XREG_LOCK, lock_status); 4478d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 4488d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4498d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc_get_version(struct xc4000_priv *priv, 4508d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri u8 *hw_majorversion, u8 *hw_minorversion, 4518d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri u8 *fw_majorversion, u8 *fw_minorversion) 4528d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 4538d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri u16 data; 4548d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri int result; 4558d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4568d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri result = xc4000_readreg(priv, XREG_VERSION, &data); 457341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (result != 0) 4588d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return result; 4598d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4608d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri (*hw_majorversion) = (data >> 12) & 0x0F; 4618d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri (*hw_minorversion) = (data >> 8) & 0x0F; 4628d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri (*fw_majorversion) = (data >> 4) & 0x0F; 4638d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri (*fw_minorversion) = data & 0x0F; 4648d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4658d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return 0; 4668d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 4678d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4688d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc_get_hsync_freq(struct xc4000_priv *priv, u32 *hsync_freq_hz) 4698d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 4708d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri u16 regData; 4718d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri int result; 4728d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4738d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri result = xc4000_readreg(priv, XREG_HSYNC_FREQ, ®Data); 474341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (result != 0) 4758d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return result; 4768d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4778d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri (*hsync_freq_hz) = ((regData & 0x0fff) * 763)/100; 4788d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return result; 4798d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 4808d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4818d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc_get_frame_lines(struct xc4000_priv *priv, u16 *frame_lines) 4828d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 4838d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return xc4000_readreg(priv, XREG_FRAME_LINES, frame_lines); 4848d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 4858d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4868d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc_get_quality(struct xc4000_priv *priv, u16 *quality) 4878d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 4888d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return xc4000_readreg(priv, XREG_QUALITY, quality); 4898d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 4908d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 4918a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugenstatic int xc_get_signal_level(struct xc4000_priv *priv, u16 *signal) 4928a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen{ 4938a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen return xc4000_readreg(priv, XREG_SIGNAL_LEVEL, signal); 4948a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen} 4958a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 4968a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugenstatic int xc_get_noise_level(struct xc4000_priv *priv, u16 *noise) 4978a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen{ 4988a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen return xc4000_readreg(priv, XREG_NOISE_LEVEL, noise); 4998a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen} 5008a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 501341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hustatic u16 xc_wait_for_lock(struct xc4000_priv *priv) 5028d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 503341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu u16 lock_state = 0; 504341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu int watchdog_count = 40; 505341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu 506341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu while ((lock_state == 0) && (watchdog_count > 0)) { 507341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu xc_get_lock_status(priv, &lock_state); 508341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (lock_state != 1) { 509341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu msleep(5); 510341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu watchdog_count--; 5118d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 5128d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 513341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu return lock_state; 5148d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 5158d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 516e75873c1f80380f190d0270fec566410f59c4829Istvan Vargastatic int xc_tune_channel(struct xc4000_priv *priv, u32 freq_hz) 5178d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 518e75873c1f80380f190d0270fec566410f59c4829Istvan Varga int found = 1; 519e75873c1f80380f190d0270fec566410f59c4829Istvan Varga int result; 5208d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 5218d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "%s(%u)\n", __func__, freq_hz); 5228d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 523799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller /* Don't complain when the request fails because of i2c stretching */ 524799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller priv->ignore_i2c_write_errors = 1; 525341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu result = xc_set_rf_frequency(priv, freq_hz); 526799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller priv->ignore_i2c_write_errors = 0; 527799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller 528341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (result != 0) 5298d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return 0; 5308d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 531e75873c1f80380f190d0270fec566410f59c4829Istvan Varga /* wait for lock only in analog TV mode */ 532e75873c1f80380f190d0270fec566410f59c4829Istvan Varga if ((priv->cur_fw.type & (FM | DTV6 | DTV7 | DTV78 | DTV8)) == 0) { 533341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (xc_wait_for_lock(priv) != 1) 534e75873c1f80380f190d0270fec566410f59c4829Istvan Varga found = 0; 5358d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 5368d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 537f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga /* Wait for stats to stabilize. 538f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga * Frame Lines needs two frame times after initial lock 539f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga * before it is valid. 540f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga */ 541341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu msleep(debug ? 100 : 10); 542f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga 543f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga if (debug) 544f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga xc_debug_dump(priv); 545f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga 5468d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return found; 5478d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 5488d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 5498d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc4000_readreg(struct xc4000_priv *priv, u16 reg, u16 *val) 5508d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 5518d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri u8 buf[2] = { reg >> 8, reg & 0xff }; 5528d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri u8 bval[2] = { 0, 0 }; 5538d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct i2c_msg msg[2] = { 5548d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri { .addr = priv->i2c_props.addr, 5558d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .flags = 0, .buf = &buf[0], .len = 2 }, 5568d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri { .addr = priv->i2c_props.addr, 5578d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .flags = I2C_M_RD, .buf = &bval[0], .len = 2 }, 5588d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri }; 5598d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 5608d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if (i2c_transfer(priv->i2c_props.adap, msg, 2) != 2) { 561941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "xc4000: I2C read failed\n"); 5628d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return -EREMOTEIO; 5638d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 5648d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 5658d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri *val = (bval[0] << 8) | bval[1]; 566341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu return 0; 5678d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 5688d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 569e3bb7c607f5ca87030692ad4dab653b4a8d1571aMauro Carvalho Chehab#define dump_firm_type(t) dump_firm_type_and_int_freq(t, 0) 570d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmuellerstatic void dump_firm_type_and_int_freq(unsigned int type, u16 int_freq) 571d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller{ 57297e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & BASE) 573941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "BASE "); 57497e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & INIT1) 575941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "INIT1 "); 57697e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & F8MHZ) 577941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "F8MHZ "); 57897e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & MTS) 579941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "MTS "); 58097e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & D2620) 581941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "D2620 "); 58297e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & D2633) 583941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "D2633 "); 58497e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & DTV6) 585941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "DTV6 "); 58697e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & QAM) 587941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "QAM "); 58897e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & DTV7) 589941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "DTV7 "); 59097e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & DTV78) 591941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "DTV78 "); 59297e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & DTV8) 593941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "DTV8 "); 59497e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & FM) 595941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "FM "); 59697e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & INPUT1) 597941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "INPUT1 "); 59897e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & LCD) 599941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "LCD "); 60097e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & NOGD) 601941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "NOGD "); 60297e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & MONO) 603941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "MONO "); 60497e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & ATSC) 605941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "ATSC "); 60697e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & IF) 607941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "IF "); 60897e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & LG60) 609941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "LG60 "); 61097e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & ATI638) 611941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "ATI638 "); 61297e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & OREN538) 613941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "OREN538 "); 61497e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & OREN36) 615941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "OREN36 "); 61697e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & TOYOTA388) 617941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "TOYOTA388 "); 61897e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & TOYOTA794) 619941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "TOYOTA794 "); 62097e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & DIBCOM52) 621941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "DIBCOM52 "); 62297e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & ZARLINK456) 623941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "ZARLINK456 "); 62497e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & CHINA) 625941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "CHINA "); 62697e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & F6MHZ) 627941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "F6MHZ "); 62897e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & INPUT2) 629941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "INPUT2 "); 63097e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & SCODE) 631941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "SCODE "); 63297e0e1e867952d369f245fce0d6791eacb40b2bbMauro Carvalho Chehab if (type & HAS_IF) 633941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "HAS_IF_%d ", int_freq); 634d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller} 635d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 63611091a31fbf7496294795ca72d69db0233857d94Devin Heitmuellerstatic int seek_firmware(struct dvb_frontend *fe, unsigned int type, 63711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller v4l2_std_id *id) 63811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller{ 63911091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller struct xc4000_priv *priv = fe->tuner_priv; 6403db9570482f368cd2f62c258802da21667ec6198Istvan Varga int i, best_i = -1; 6413db9570482f368cd2f62c258802da21667ec6198Istvan Varga unsigned int best_nr_diffs = 255U; 64211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 64311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (!priv->firm) { 644341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu printk(KERN_ERR "Error! firmware not loaded\n"); 64511091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller return -EINVAL; 64611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller } 64711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 64811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (((type & ~SCODE) == 0) && (*id == 0)) 64911091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller *id = V4L2_STD_PAL; 65011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 65111091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller /* Seek for generic video standard match */ 65211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller for (i = 0; i < priv->firm_size; i++) { 6533db9570482f368cd2f62c258802da21667ec6198Istvan Varga v4l2_std_id id_diff_mask = 6543db9570482f368cd2f62c258802da21667ec6198Istvan Varga (priv->firm[i].id ^ (*id)) & (*id); 6553db9570482f368cd2f62c258802da21667ec6198Istvan Varga unsigned int type_diff_mask = 6563db9570482f368cd2f62c258802da21667ec6198Istvan Varga (priv->firm[i].type ^ type) 6573db9570482f368cd2f62c258802da21667ec6198Istvan Varga & (BASE_TYPES | DTV_TYPES | LCD | NOGD | MONO | SCODE); 6583db9570482f368cd2f62c258802da21667ec6198Istvan Varga unsigned int nr_diffs; 6593db9570482f368cd2f62c258802da21667ec6198Istvan Varga 6603db9570482f368cd2f62c258802da21667ec6198Istvan Varga if (type_diff_mask 6613db9570482f368cd2f62c258802da21667ec6198Istvan Varga & (BASE | INIT1 | FM | DTV6 | DTV7 | DTV78 | DTV8 | SCODE)) 66211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller continue; 66311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 6643db9570482f368cd2f62c258802da21667ec6198Istvan Varga nr_diffs = hweight64(id_diff_mask) + hweight32(type_diff_mask); 6653db9570482f368cd2f62c258802da21667ec6198Istvan Varga if (!nr_diffs) /* Supports all the requested standards */ 6663db9570482f368cd2f62c258802da21667ec6198Istvan Varga goto found; 66711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 6683db9570482f368cd2f62c258802da21667ec6198Istvan Varga if (nr_diffs < best_nr_diffs) { 6693db9570482f368cd2f62c258802da21667ec6198Istvan Varga best_nr_diffs = nr_diffs; 67011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller best_i = i; 67111091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller } 67211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller } 67311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 6743db9570482f368cd2f62c258802da21667ec6198Istvan Varga /* FIXME: Would make sense to seek for type "hint" match ? */ 6753db9570482f368cd2f62c258802da21667ec6198Istvan Varga if (best_i < 0) { 6763db9570482f368cd2f62c258802da21667ec6198Istvan Varga i = -ENOENT; 6773db9570482f368cd2f62c258802da21667ec6198Istvan Varga goto ret; 6783db9570482f368cd2f62c258802da21667ec6198Istvan Varga } 6793db9570482f368cd2f62c258802da21667ec6198Istvan Varga 6803db9570482f368cd2f62c258802da21667ec6198Istvan Varga if (best_nr_diffs > 0U) { 681941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_WARNING 682941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab "Selecting best matching firmware (%u bits differ) for " 683341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu "type=(%x), id %016llx:\n", 684341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu best_nr_diffs, type, (unsigned long long)*id); 68511091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller i = best_i; 68611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller } 68711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 68811091a31fbf7496294795ca72d69db0233857d94Devin Heitmuellerfound: 68911091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller *id = priv->firm[i].id; 69011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 69111091a31fbf7496294795ca72d69db0233857d94Devin Heitmuellerret: 69211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (debug) { 693941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_DEBUG "%s firmware for type=", 694341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu (i < 0) ? "Can't find" : "Found"); 695d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller dump_firm_type(type); 696941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_DEBUG "(%x), id %016llx.\n", type, (unsigned long long)*id); 69711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller } 69811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller return i; 69911091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller} 70011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 70111091a31fbf7496294795ca72d69db0233857d94Devin Heitmuellerstatic int load_firmware(struct dvb_frontend *fe, unsigned int type, 70211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller v4l2_std_id *id) 70311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller{ 70411091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller struct xc4000_priv *priv = fe->tuner_priv; 70511091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller int pos, rc; 70631f880e2b99a780a4ee5fb6199e489b62e0a76ecDevin Heitmueller unsigned char *p; 70711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 70811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller pos = seek_firmware(fe, type, id); 70911091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (pos < 0) 71011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller return pos; 71111091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 71211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller p = priv->firm[pos].ptr; 71311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 714799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller /* Don't complain when the request fails because of i2c stretching */ 715799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller priv->ignore_i2c_write_errors = 1; 716799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller 71731f880e2b99a780a4ee5fb6199e489b62e0a76ecDevin Heitmueller rc = xc_load_i2c_sequence(fe, p); 71811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 719799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller priv->ignore_i2c_write_errors = 0; 720799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller 72131f880e2b99a780a4ee5fb6199e489b62e0a76ecDevin Heitmueller return rc; 72211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller} 72311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 7248d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc4000_fwupload(struct dvb_frontend *fe) 7258d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 7268d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct xc4000_priv *priv = fe->tuner_priv; 72711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller const struct firmware *fw = NULL; 72811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller const unsigned char *p, *endp; 72911091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller int rc = 0; 73011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller int n, n_array; 73111091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller char name[33]; 732fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga const char *fname; 73311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 734da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab if (firmware_name[0] != '\0') { 735fa285bc1bf5a2ebe3252523454def096d86a064bIstvan Varga fname = firmware_name; 73611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 737da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab dprintk(1, "Reading custom firmware %s\n", fname); 738da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab rc = request_firmware(&fw, fname, 739da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab priv->i2c_props.adap->dev.parent); 740da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab } else { 741da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab fname = XC4000_DEFAULT_FIRMWARE_NEW; 742da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab dprintk(1, "Trying to read firmware %s\n", fname); 743da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab rc = request_firmware(&fw, fname, 744da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab priv->i2c_props.adap->dev.parent); 745da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab if (rc == -ENOENT) { 746da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab fname = XC4000_DEFAULT_FIRMWARE; 747da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab dprintk(1, "Trying to read firmware %s\n", fname); 748da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab rc = request_firmware(&fw, fname, 749da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab priv->i2c_props.adap->dev.parent); 750da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab } 751da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab } 752da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab 75311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (rc < 0) { 75411091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (rc == -ENOENT) 755941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "Error: firmware %s not found.\n", fname); 75611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller else 757941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "Error %d while requesting firmware %s\n", 758341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu rc, fname); 7598d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 76011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller return rc; 76111091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller } 762da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab dprintk(1, "Loading Firmware: %s\n", fname); 763da7bfa2c5df3221c7b63be05d5110e21a11118dcMauro Carvalho Chehab 76411091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller p = fw->data; 76511091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller endp = p + fw->size; 7668d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 76711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (fw->size < sizeof(name) - 1 + 2 + 2) { 768941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "Error: firmware file %s has invalid size!\n", 769941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab fname); 77011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller goto corrupt; 7718d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 7728d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 77311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller memcpy(name, p, sizeof(name) - 1); 774341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu name[sizeof(name) - 1] = '\0'; 77511091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller p += sizeof(name) - 1; 77611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 77711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller priv->firm_version = get_unaligned_le16(p); 77811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller p += 2; 77911091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 78011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller n_array = get_unaligned_le16(p); 78111091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller p += 2; 78211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 783b6cdb5bea31c86645782950d84745bb2f95ec9caDevin Heitmueller dprintk(1, "Loading %d firmware images from %s, type: %s, ver %d.%d\n", 784b6cdb5bea31c86645782950d84745bb2f95ec9caDevin Heitmueller n_array, fname, name, 785b6cdb5bea31c86645782950d84745bb2f95ec9caDevin Heitmueller priv->firm_version >> 8, priv->firm_version & 0xff); 78611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 7871b7acf0ccd61b814032668d1d21740cfae3304e3Thomas Meyer priv->firm = kcalloc(n_array, sizeof(*priv->firm), GFP_KERNEL); 78811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (priv->firm == NULL) { 789941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "Not enough memory to load firmware file.\n"); 79011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller rc = -ENOMEM; 791941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab goto done; 79211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller } 79311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller priv->firm_size = n_array; 79411091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 79511091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller n = -1; 79611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller while (p < endp) { 79711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller __u32 type, size; 79811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller v4l2_std_id id; 79911091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller __u16 int_freq = 0; 80011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 80111091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller n++; 80211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (n >= n_array) { 803941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "More firmware images in file than " 804fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga "were expected!\n"); 80511091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller goto corrupt; 80611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller } 80711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 80811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller /* Checks if there's enough bytes to read */ 80911091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (endp - p < sizeof(type) + sizeof(id) + sizeof(size)) 81011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller goto header; 81111091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 81211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller type = get_unaligned_le32(p); 81311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller p += sizeof(type); 81411091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 81511091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller id = get_unaligned_le64(p); 81611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller p += sizeof(id); 81711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 81811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (type & HAS_IF) { 81911091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller int_freq = get_unaligned_le16(p); 82011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller p += sizeof(int_freq); 82111091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (endp - p < sizeof(size)) 82211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller goto header; 82311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller } 82411091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 82511091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller size = get_unaligned_le32(p); 82611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller p += sizeof(size); 82711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 82811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (!size || size > endp - p) { 829941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "Firmware type (%x), id %llx is corrupted (size=%d, expected %d)\n", 83011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller type, (unsigned long long)id, 83111091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller (unsigned)(endp - p), size); 83211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller goto corrupt; 83311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller } 83411091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 83511091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller priv->firm[n].ptr = kzalloc(size, GFP_KERNEL); 83611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (priv->firm[n].ptr == NULL) { 837941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "Not enough memory to load firmware file.\n"); 83811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller rc = -ENOMEM; 839941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab goto done; 84011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller } 841d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 84211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (debug) { 843941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_DEBUG "Reading firmware type "); 844d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller dump_firm_type_and_int_freq(type, int_freq); 845941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_DEBUG "(%x), id %llx, size=%d.\n", 84611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller type, (unsigned long long)id, size); 84711091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller } 84811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 84911091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller memcpy(priv->firm[n].ptr, p, size); 85011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller priv->firm[n].type = type; 85111091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller priv->firm[n].id = id; 85211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller priv->firm[n].size = size; 85311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller priv->firm[n].int_freq = int_freq; 85411091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 85511091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller p += size; 8568d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 8578d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 85811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (n + 1 != priv->firm_size) { 859941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "Firmware file is incomplete!\n"); 86011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller goto corrupt; 86111091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller } 86211091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 86311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller goto done; 86411091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 86511091a31fbf7496294795ca72d69db0233857d94Devin Heitmuellerheader: 866941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "Firmware header is incomplete!\n"); 86711091a31fbf7496294795ca72d69db0233857d94Devin Heitmuellercorrupt: 86811091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller rc = -EINVAL; 869941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "Error: firmware file is corrupted!\n"); 87011091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 87111091a31fbf7496294795ca72d69db0233857d94Devin Heitmuellerdone: 8728d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri release_firmware(fw); 87311091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller if (rc == 0) 874b6cdb5bea31c86645782950d84745bb2f95ec9caDevin Heitmueller dprintk(1, "Firmware files loaded.\n"); 87511091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 87611091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller return rc; 8778d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 8788d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 879d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmuellerstatic int load_scode(struct dvb_frontend *fe, unsigned int type, 880d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller v4l2_std_id *id, __u16 int_freq, int scode) 881d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller{ 882d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller struct xc4000_priv *priv = fe->tuner_priv; 883ffce6266c8be9076947462c688ad3a3099c83eebIstvan Varga int pos, rc; 884ffce6266c8be9076947462c688ad3a3099c83eebIstvan Varga unsigned char *p; 885ffce6266c8be9076947462c688ad3a3099c83eebIstvan Varga u8 scode_buf[13]; 886ffce6266c8be9076947462c688ad3a3099c83eebIstvan Varga u8 indirect_mode[5]; 887d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 888fe8303647640e1183640a9b85cd60c4a981c7b4bDevin Heitmueller dprintk(1, "%s called int_freq=%d\n", __func__, int_freq); 889d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 890d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (!int_freq) { 891d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller pos = seek_firmware(fe, type, id); 892d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (pos < 0) 893d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller return pos; 894d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } else { 895d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller for (pos = 0; pos < priv->firm_size; pos++) { 896d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if ((priv->firm[pos].int_freq == int_freq) && 897d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller (priv->firm[pos].type & HAS_IF)) 898d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller break; 899d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } 900d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (pos == priv->firm_size) 901d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller return -ENOENT; 902d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } 903d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 904d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller p = priv->firm[pos].ptr; 905d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 906ffce6266c8be9076947462c688ad3a3099c83eebIstvan Varga if (priv->firm[pos].size != 12 * 16 || scode >= 16) 907ffce6266c8be9076947462c688ad3a3099c83eebIstvan Varga return -EINVAL; 908ffce6266c8be9076947462c688ad3a3099c83eebIstvan Varga p += 12 * scode; 909d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 910941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab if (debug) { 911941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab tuner_info("Loading SCODE for type="); 912941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab dump_firm_type_and_int_freq(priv->firm[pos].type, 913941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab priv->firm[pos].int_freq); 914941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "(%x), id %016llx.\n", priv->firm[pos].type, 915941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab (unsigned long long)*id); 916941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab } 917d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 918ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller scode_buf[0] = 0x00; 919ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller memcpy(&scode_buf[1], p, 12); 920d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 921d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller /* Enter direct-mode */ 922ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller rc = xc_write_reg(priv, XREG_DIRECTSITTING_MODE, 0); 923ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller if (rc < 0) { 924941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "failed to put device into direct mode!\n"); 925d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller return -EIO; 926ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller } 927d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 928ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller rc = xc_send_i2c_data(priv, scode_buf, 13); 929341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (rc != 0) { 930ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller /* Even if the send failed, make sure we set back to indirect 931ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller mode */ 932941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "Failed to set scode %d\n", rc); 933ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller } 934d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 935d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller /* Switch back to indirect-mode */ 936d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller memset(indirect_mode, 0, sizeof(indirect_mode)); 937d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller indirect_mode[4] = 0x88; 938ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller xc_send_i2c_data(priv, indirect_mode, sizeof(indirect_mode)); 939ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller msleep(10); 940d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 941d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller return 0; 942d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller} 943d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 944d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmuellerstatic int check_firmware(struct dvb_frontend *fe, unsigned int type, 945d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller v4l2_std_id std, __u16 int_freq) 946d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller{ 947d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller struct xc4000_priv *priv = fe->tuner_priv; 948d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller struct firmware_properties new_fw; 949d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller int rc = 0, is_retry = 0; 95009f4634293f2d48a9619f51b104bef8e6cc6d559istvan_v@mailbox.hu u16 hwmodel; 951d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller v4l2_std_id std0; 9520d0d76e5bcd70439b0e736a99539d7eef4f87bafMauro Carvalho Chehab u8 hw_major = 0, hw_minor = 0, fw_major = 0, fw_minor = 0; 953d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 954d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller dprintk(1, "%s called\n", __func__); 955d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 956d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (!priv->firm) { 957d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller rc = xc4000_fwupload(fe); 958d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (rc < 0) 959d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller return rc; 960d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } 961d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 962d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmuellerretry: 963d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller new_fw.type = type; 964d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller new_fw.id = std; 965d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller new_fw.std_req = std; 966341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu new_fw.scode_table = SCODE; 967d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller new_fw.scode_nr = 0; 968d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller new_fw.int_freq = int_freq; 969d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 970d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller dprintk(1, "checking firmware, user requested type="); 971d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (debug) { 972d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller dump_firm_type(new_fw.type); 973941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_CONT "(%x), id %016llx, ", new_fw.type, 974d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller (unsigned long long)new_fw.std_req); 975341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (!int_freq) 976341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu printk(KERN_CONT "scode_tbl "); 977341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu else 978341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu printk(KERN_CONT "int_freq %d, ", new_fw.int_freq); 979341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu printk(KERN_CONT "scode_nr %d\n", new_fw.scode_nr); 980d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } 981d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 982d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller /* No need to reload base firmware if it matches */ 983595a83f49a7536f43a68cab78098d5ad11d1c51fIstvan Varga if (priv->cur_fw.type & BASE) { 984d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller dprintk(1, "BASE firmware not changed.\n"); 985d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller goto skip_base; 986d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } 987d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 988d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller /* Updating BASE - forget about all currently loaded firmware */ 989d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); 990d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 991d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller /* Reset is needed before loading firmware */ 992341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu rc = xc4000_tuner_reset(fe); 993d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (rc < 0) 994d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller goto fail; 995d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 996d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller /* BASE firmwares are all std0 */ 997d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller std0 = 0; 998595a83f49a7536f43a68cab78098d5ad11d1c51fIstvan Varga rc = load_firmware(fe, BASE, &std0); 999d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (rc < 0) { 1000941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "Error %d while loading base firmware\n", rc); 1001d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller goto fail; 1002d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } 1003d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1004d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller /* Load INIT1, if needed */ 1005d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller dprintk(1, "Load init1 firmware, if exists\n"); 1006d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1007595a83f49a7536f43a68cab78098d5ad11d1c51fIstvan Varga rc = load_firmware(fe, BASE | INIT1, &std0); 1008d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (rc == -ENOENT) 1009595a83f49a7536f43a68cab78098d5ad11d1c51fIstvan Varga rc = load_firmware(fe, BASE | INIT1, &std0); 1010d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (rc < 0 && rc != -ENOENT) { 1011d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller tuner_err("Error %d while loading init1 firmware\n", 1012d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller rc); 1013d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller goto fail; 1014d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } 1015d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1016d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmuellerskip_base: 1017d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller /* 1018d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller * No need to reload standard specific firmware if base firmware 1019d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller * was not reloaded and requested video standards have not changed. 1020d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller */ 1021d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (priv->cur_fw.type == (BASE | new_fw.type) && 1022d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller priv->cur_fw.std_req == std) { 1023d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller dprintk(1, "Std-specific firmware already loaded.\n"); 1024d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller goto skip_std_specific; 1025d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } 1026d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1027d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller /* Reloading std-specific firmware forces a SCODE update */ 1028d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller priv->cur_fw.scode_table = 0; 1029d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1030ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller /* Load the standard firmware */ 1031d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller rc = load_firmware(fe, new_fw.type, &new_fw.id); 1032d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1033d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (rc < 0) 1034d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller goto fail; 1035d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1036d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmuellerskip_std_specific: 1037d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (priv->cur_fw.scode_table == new_fw.scode_table && 1038d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller priv->cur_fw.scode_nr == new_fw.scode_nr) { 1039d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller dprintk(1, "SCODE firmware already loaded.\n"); 1040d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller goto check_device; 1041d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } 1042d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1043d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller /* Load SCODE firmware, if exists */ 1044d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller rc = load_scode(fe, new_fw.type | new_fw.scode_table, &new_fw.id, 1045d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller new_fw.int_freq, new_fw.scode_nr); 1046341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (rc != 0) 1047ee4c3cd67b90cb42143e230485d3aad60768c551Devin Heitmueller dprintk(1, "load scode failed %d\n", rc); 1048d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1049d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmuellercheck_device: 1050d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller rc = xc4000_readreg(priv, XREG_PRODUCT_ID, &hwmodel); 1051d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1052799ed11afe7694858584d1ed4e9ae2f9e48142ecDevin Heitmueller if (xc_get_version(priv, &hw_major, &hw_minor, &fw_major, 1053341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu &fw_minor) != 0) { 1054941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab printk(KERN_ERR "Unable to read tuner registers.\n"); 1055d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller goto fail; 1056d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } 1057d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1058d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller dprintk(1, "Device is Xceive %d version %d.%d, " 1059d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller "firmware version %d.%d\n", 1060d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller hwmodel, hw_major, hw_minor, fw_major, fw_minor); 1061d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1062d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller /* Check firmware version against what we downloaded. */ 106309f4634293f2d48a9619f51b104bef8e6cc6d559istvan_v@mailbox.hu if (priv->firm_version != ((fw_major << 8) | fw_minor)) { 106409f4634293f2d48a9619f51b104bef8e6cc6d559istvan_v@mailbox.hu printk(KERN_WARNING 106509f4634293f2d48a9619f51b104bef8e6cc6d559istvan_v@mailbox.hu "Incorrect readback of firmware version %d.%d.\n", 106609f4634293f2d48a9619f51b104bef8e6cc6d559istvan_v@mailbox.hu fw_major, fw_minor); 1067d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller goto fail; 1068d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } 1069d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1070d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller /* Check that the tuner hardware model remains consistent over time. */ 10717db98fe66be035494912b6b2c4e9c1e3abfedfe5Istvan Varga if (priv->hwmodel == 0 && 10727db98fe66be035494912b6b2c4e9c1e3abfedfe5Istvan Varga (hwmodel == XC_PRODUCT_ID_XC4000 || 10737db98fe66be035494912b6b2c4e9c1e3abfedfe5Istvan Varga hwmodel == XC_PRODUCT_ID_XC4100)) { 1074d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller priv->hwmodel = hwmodel; 107509f4634293f2d48a9619f51b104bef8e6cc6d559istvan_v@mailbox.hu priv->hwvers = (hw_major << 8) | hw_minor; 1076d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } else if (priv->hwmodel == 0 || priv->hwmodel != hwmodel || 107709f4634293f2d48a9619f51b104bef8e6cc6d559istvan_v@mailbox.hu priv->hwvers != ((hw_major << 8) | hw_minor)) { 107809f4634293f2d48a9619f51b104bef8e6cc6d559istvan_v@mailbox.hu printk(KERN_WARNING 107909f4634293f2d48a9619f51b104bef8e6cc6d559istvan_v@mailbox.hu "Read invalid device hardware information - tuner " 1080fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga "hung?\n"); 1081d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller goto fail; 1082d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } 1083d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 108436628731ec9ef46393d25d2fbdac40cc70c4d27aEzequiel Garcia priv->cur_fw = new_fw; 1085d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1086d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller /* 1087d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller * By setting BASE in cur_fw.type only after successfully loading all 1088d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller * firmwares, we can: 1089d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller * 1. Identify that BASE firmware with type=0 has been loaded; 1090d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller * 2. Tell whether BASE firmware was just changed the next time through. 1091d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller */ 1092d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller priv->cur_fw.type |= BASE; 1093d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1094d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller return 0; 1095d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1096d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmuellerfail: 1097d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller memset(&priv->cur_fw, 0, sizeof(priv->cur_fw)); 1098d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (!is_retry) { 1099d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller msleep(50); 1100d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller is_retry = 1; 1101d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller dprintk(1, "Retrying firmware load\n"); 1102d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller goto retry; 1103d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller } 1104d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller 1105d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller if (rc == -ENOENT) 1106d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller rc = -EINVAL; 1107d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller return rc; 1108d0962382cf6ca55e5a33413b39a10fe2f56bae78Devin Heitmueller} 110911091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 11108d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic void xc_debug_dump(struct xc4000_priv *priv) 11118d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 1112fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u16 adc_envelope; 1113fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u32 freq_error_hz = 0; 1114fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u16 lock_status; 1115fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u32 hsync_freq_hz = 0; 1116fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u16 frame_lines; 1117fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u16 quality; 11188a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen u16 signal = 0; 11198a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen u16 noise = 0; 1120fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u8 hw_majorversion = 0, hw_minorversion = 0; 1121fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u8 fw_majorversion = 0, fw_minorversion = 0; 11228d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1123341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu xc_get_adc_envelope(priv, &adc_envelope); 11248d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "*** ADC envelope (0-1023) = %d\n", adc_envelope); 11258d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 11268d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri xc_get_frequency_error(priv, &freq_error_hz); 11278d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "*** Frequency error = %d Hz\n", freq_error_hz); 11288d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1129fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga xc_get_lock_status(priv, &lock_status); 11308d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "*** Lock status (0-Wait, 1-Locked, 2-No-signal) = %d\n", 11318d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri lock_status); 11328d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1133fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga xc_get_version(priv, &hw_majorversion, &hw_minorversion, 1134fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga &fw_majorversion, &fw_minorversion); 11358d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x\n", 11368d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri hw_majorversion, hw_minorversion, 11378d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri fw_majorversion, fw_minorversion); 11388d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1139f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga if (priv->video_standard < XC4000_DTV6) { 1140f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga xc_get_hsync_freq(priv, &hsync_freq_hz); 1141f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga dprintk(1, "*** Horizontal sync frequency = %d Hz\n", 1142f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga hsync_freq_hz); 11438d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1144f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga xc_get_frame_lines(priv, &frame_lines); 1145f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga dprintk(1, "*** Frame lines = %d\n", frame_lines); 1146f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga } 11478d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1148fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga xc_get_quality(priv, &quality); 11498d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality); 11508a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 11518a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen xc_get_signal_level(priv, &signal); 11528a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen dprintk(1, "*** Signal level = -%ddB (%d)\n", signal >> 8, signal); 11538a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 11548a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen xc_get_noise_level(priv, &noise); 11558a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen dprintk(1, "*** Noise level = %ddB (%d)\n", noise >> 8, noise); 11568d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 11578d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 115814d24d148c7521b2b88b396652e36f55d061e195Mauro Carvalho Chehabstatic int xc4000_set_params(struct dvb_frontend *fe) 11598d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 116040d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab struct dtv_frontend_properties *c = &fe->dtv_property_cache; 116140d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab u32 delsys = c->delivery_system; 116240d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab u32 bw = c->bandwidth_hz; 11638d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct xc4000_priv *priv = fe->tuner_priv; 1164ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller unsigned int type; 11655614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga int ret = -EREMOTEIO; 11668d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 116740d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab dprintk(1, "%s() frequency=%d (Hz)\n", __func__, c->frequency); 11688d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 11695614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga mutex_lock(&priv->lock); 11705614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga 117140d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab switch (delsys) { 117240d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab case SYS_ATSC: 117340d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab dprintk(1, "%s() VSB modulation\n", __func__); 117440d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab priv->rf_mode = XC_RF_MODE_AIR; 11754c07e32884ab69574cfd9eb4de3334233c938071Mauro Carvalho Chehab priv->freq_offset = 1750000; 117640d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab priv->video_standard = XC4000_DTV6; 117740d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab type = DTV6; 117840d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab break; 117940d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab case SYS_DVBC_ANNEX_B: 118040d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab dprintk(1, "%s() QAM modulation\n", __func__); 118140d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab priv->rf_mode = XC_RF_MODE_CABLE; 11824c07e32884ab69574cfd9eb4de3334233c938071Mauro Carvalho Chehab priv->freq_offset = 1750000; 118340d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab priv->video_standard = XC4000_DTV6; 118440d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab type = DTV6; 118540d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab break; 118640d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab case SYS_DVBT: 118740d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab case SYS_DVBT2: 11888d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "%s() OFDM\n", __func__); 118940d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab if (bw == 0) { 119040d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab if (c->frequency < 400000000) { 11914c07e32884ab69574cfd9eb4de3334233c938071Mauro Carvalho Chehab priv->freq_offset = 2250000; 119240d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab } else { 11934c07e32884ab69574cfd9eb4de3334233c938071Mauro Carvalho Chehab priv->freq_offset = 2750000; 119440d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab } 119540d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab priv->video_standard = XC4000_DTV7_8; 119640d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab type = DTV78; 119740d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab } else if (bw <= 6000000) { 1198ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller priv->video_standard = XC4000_DTV6; 11994c07e32884ab69574cfd9eb4de3334233c938071Mauro Carvalho Chehab priv->freq_offset = 1750000; 1200ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller type = DTV6; 120140d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab } else if (bw <= 7000000) { 1202f0ef7c88ca919912011593d2392a59c2fde04748Istvan Varga priv->video_standard = XC4000_DTV7; 12034c07e32884ab69574cfd9eb4de3334233c938071Mauro Carvalho Chehab priv->freq_offset = 2250000; 1204ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller type = DTV7; 120540d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab } else { 1206ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller priv->video_standard = XC4000_DTV8; 12074c07e32884ab69574cfd9eb4de3334233c938071Mauro Carvalho Chehab priv->freq_offset = 2750000; 1208ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller type = DTV8; 12098d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 12108d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri priv->rf_mode = XC_RF_MODE_AIR; 121140d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab break; 121240d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab default: 121340d6f2b83788cfc125867c8c7a7a0b32c72d9e54Mauro Carvalho Chehab printk(KERN_ERR "xc4000 delivery system not supported!\n"); 12145614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga ret = -EINVAL; 12155614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga goto fail; 12168d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 12178d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 12184c07e32884ab69574cfd9eb4de3334233c938071Mauro Carvalho Chehab priv->freq_hz = c->frequency - priv->freq_offset; 12194c07e32884ab69574cfd9eb4de3334233c938071Mauro Carvalho Chehab 12208d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "%s() frequency=%d (compensated)\n", 12218d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri __func__, priv->freq_hz); 12228d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1223ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller /* Make sure the correct firmware type is loaded */ 1224341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (check_firmware(fe, type, 0, priv->if_khz) != 0) 12255614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga goto fail; 1226ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller 1227c6f56e7d794cba022353d464dfa3383d1b3e0125Mauro Carvalho Chehab priv->bandwidth = c->bandwidth_hz; 1228c6f56e7d794cba022353d464dfa3383d1b3e0125Mauro Carvalho Chehab 1229341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu ret = xc_set_signal_source(priv, priv->rf_mode); 1230341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (ret != 0) { 1231341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu printk(KERN_ERR "xc4000: xc_set_signal_source(%d) failed\n", 12325614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga priv->rf_mode); 12335614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga goto fail; 123430f544ec56eefc628e73e23324dc18105ad13012Istvan Varga } else { 123530f544ec56eefc628e73e23324dc18105ad13012Istvan Varga u16 video_mode, audio_mode; 1236341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu video_mode = xc4000_standard[priv->video_standard].video_mode; 1237341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu audio_mode = xc4000_standard[priv->video_standard].audio_mode; 123830f544ec56eefc628e73e23324dc18105ad13012Istvan Varga if (type == DTV6 && priv->firm_version != 0x0102) 123930f544ec56eefc628e73e23324dc18105ad13012Istvan Varga video_mode |= 0x0001; 1240341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu ret = xc_set_tv_standard(priv, video_mode, audio_mode); 1241341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (ret != 0) { 1242341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu printk(KERN_ERR "xc4000: xc_set_tv_standard failed\n"); 124330f544ec56eefc628e73e23324dc18105ad13012Istvan Varga /* DJH - do not return when it fails... */ 124430f544ec56eefc628e73e23324dc18105ad13012Istvan Varga /* goto fail; */ 124530f544ec56eefc628e73e23324dc18105ad13012Istvan Varga } 12468d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 12478d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 12488edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu if (xc_write_reg(priv, XREG_D_CODE, 0) == 0) 12498edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu ret = 0; 12508edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu if (priv->dvb_amplitude != 0) { 125130f544ec56eefc628e73e23324dc18105ad13012Istvan Varga if (xc_write_reg(priv, XREG_AMPLITUDE, 12528edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu (priv->firm_version != 0x0102 || 12538edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu priv->dvb_amplitude != 134 ? 12548edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu priv->dvb_amplitude : 132)) != 0) 125530f544ec56eefc628e73e23324dc18105ad13012Istvan Varga ret = -EREMOTEIO; 12568edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu } 12578edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu if (priv->set_smoothedcvbs != 0) { 125830f544ec56eefc628e73e23324dc18105ad13012Istvan Varga if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0) 125930f544ec56eefc628e73e23324dc18105ad13012Istvan Varga ret = -EREMOTEIO; 12608edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu } 12618edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu if (ret != 0) { 12628edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu printk(KERN_ERR "xc4000: setting registers failed\n"); 12638edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu /* goto fail; */ 12648d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 126530f544ec56eefc628e73e23324dc18105ad13012Istvan Varga 1266e75873c1f80380f190d0270fec566410f59c4829Istvan Varga xc_tune_channel(priv, priv->freq_hz); 12678d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 12685614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga ret = 0; 12695614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga 12705614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Vargafail: 12715614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga mutex_unlock(&priv->lock); 12725614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga 12735614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga return ret; 12748d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 12758d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 12768d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc4000_set_analog_params(struct dvb_frontend *fe, 12778d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct analog_parameters *params) 12788d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 12798d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct xc4000_priv *priv = fe->tuner_priv; 1280818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga unsigned int type = 0; 12815614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga int ret = -EREMOTEIO; 12828d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1283818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga if (params->mode == V4L2_TUNER_RADIO) { 1284818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga dprintk(1, "%s() frequency=%d (in units of 62.5Hz)\n", 1285818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga __func__, params->frequency); 1286818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga 1287818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga mutex_lock(&priv->lock); 1288818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga 1289818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std = 0; 1290818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->freq_hz = params->frequency * 125L / 2; 1291818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga 1292818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga if (audio_std & XC4000_AUDIO_STD_INPUT1) { 1293818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_FM_Radio_INPUT1; 1294818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga type = FM | INPUT1; 1295818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } else { 1296818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_FM_Radio_INPUT2; 1297818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga type = FM | INPUT2; 1298818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } 1299818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga 1300818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga goto tune_channel; 1301818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } 1302818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga 13038d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n", 13048d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri __func__, params->frequency); 13058d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 13065614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga mutex_lock(&priv->lock); 13075614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga 13088d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri /* params->frequency is in units of 62.5khz */ 13098d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri priv->freq_hz = params->frequency * 62500; 13108d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1311818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std &= V4L2_STD_ALL; 1312818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga /* if std is not defined, choose one */ 1313818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga if (!params->std) 1314818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std = V4L2_STD_PAL_BG; 1315818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga 1316818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga if (audio_std & XC4000_AUDIO_STD_MONO) 1317818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga type = MONO; 1318818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga 13198d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if (params->std & V4L2_STD_MN) { 1320818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std = V4L2_STD_MN; 1321818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga if (audio_std & XC4000_AUDIO_STD_MONO) { 1322818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_MN_NTSC_PAL_Mono; 1323818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } else if (audio_std & XC4000_AUDIO_STD_A2) { 1324818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std |= V4L2_STD_A2; 1325818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_MN_NTSC_PAL_A2; 1326818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } else { 1327818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std |= V4L2_STD_BTSC; 1328818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_MN_NTSC_PAL_BTSC; 1329818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } 13308d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri goto tune_channel; 13318d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 13328d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 13338d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if (params->std & V4L2_STD_PAL_BG) { 1334818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std = V4L2_STD_PAL_BG; 1335818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga if (audio_std & XC4000_AUDIO_STD_MONO) { 1336818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_BG_PAL_MONO; 1337818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } else if (!(audio_std & XC4000_AUDIO_STD_A2)) { 1338818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga if (!(audio_std & XC4000_AUDIO_STD_B)) { 1339818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std |= V4L2_STD_NICAM_A; 1340818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_BG_PAL_NICAM; 1341818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } else { 1342818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std |= V4L2_STD_NICAM_B; 1343818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_BG_PAL_NICAM; 1344818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } 1345818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } else { 1346818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga if (!(audio_std & XC4000_AUDIO_STD_B)) { 1347818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std |= V4L2_STD_A2_A; 1348818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_BG_PAL_A2; 1349818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } else { 1350818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std |= V4L2_STD_A2_B; 1351818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_BG_PAL_A2; 1352818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } 1353818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } 13548d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri goto tune_channel; 13558d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 13568d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 13578d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if (params->std & V4L2_STD_PAL_I) { 13588d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri /* default to NICAM audio standard */ 1359818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std = V4L2_STD_PAL_I | V4L2_STD_NICAM; 1360941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab if (audio_std & XC4000_AUDIO_STD_MONO) 1361818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_I_PAL_NICAM_MONO; 1362941830c9278a72e31389eb04cdfc397f66866de0Mauro Carvalho Chehab else 1363818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_I_PAL_NICAM; 13648d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri goto tune_channel; 13658d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 13668d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 13678d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if (params->std & V4L2_STD_PAL_DK) { 1368818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std = V4L2_STD_PAL_DK; 1369818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga if (audio_std & XC4000_AUDIO_STD_MONO) { 1370818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_DK_PAL_MONO; 1371818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } else if (audio_std & XC4000_AUDIO_STD_A2) { 1372818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std |= V4L2_STD_A2; 1373818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_DK_PAL_A2; 1374818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } else { 1375818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std |= V4L2_STD_NICAM; 1376818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_DK_PAL_NICAM; 1377818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } 13788d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri goto tune_channel; 13798d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 13808d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 13818d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if (params->std & V4L2_STD_SECAM_DK) { 1382818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga /* default to A2 audio standard */ 1383818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std = V4L2_STD_SECAM_DK | V4L2_STD_A2; 1384818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga if (audio_std & XC4000_AUDIO_STD_L) { 1385818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga type = 0; 1386818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_DK_SECAM_NICAM; 1387818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } else if (audio_std & XC4000_AUDIO_STD_MONO) { 1388818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_DK_SECAM_A2MONO; 1389818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } else if (audio_std & XC4000_AUDIO_STD_K3) { 1390818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std |= V4L2_STD_SECAM_K3; 1391818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_DK_SECAM_A2LDK3; 1392818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } else { 1393818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->video_standard = XC4000_DK_SECAM_A2DK1; 1394818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga } 13958d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri goto tune_channel; 13968d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 13978d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 13988d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if (params->std & V4L2_STD_SECAM_L) { 1399818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga /* default to NICAM audio standard */ 1400818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga type = 0; 1401818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std = V4L2_STD_SECAM_L | V4L2_STD_NICAM; 1402ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller priv->video_standard = XC4000_L_SECAM_NICAM; 14038d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri goto tune_channel; 14048d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 14058d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 14068d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if (params->std & V4L2_STD_SECAM_LC) { 1407818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga /* default to NICAM audio standard */ 1408818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga type = 0; 1409818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga params->std = V4L2_STD_SECAM_LC | V4L2_STD_NICAM; 1410ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller priv->video_standard = XC4000_LC_SECAM_NICAM; 14118d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri goto tune_channel; 14128d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 14138d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 14148d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferritune_channel: 1415341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu /* FIXME: it could be air. */ 1416818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga priv->rf_mode = XC_RF_MODE_CABLE; 1417ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller 1418818a1776a45c230c4f230c8e4e2d0c7bdf5f8fa3Istvan Varga if (check_firmware(fe, type, params->std, 1419341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu xc4000_standard[priv->video_standard].int_freq) != 0) 14205614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga goto fail; 1421ed23db32271997e03ea59d31839a40470a1c434bDevin Heitmueller 1422341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu ret = xc_set_signal_source(priv, priv->rf_mode); 1423341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (ret != 0) { 14248d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri printk(KERN_ERR 1425341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu "xc4000: xc_set_signal_source(%d) failed\n", 14265614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga priv->rf_mode); 14275614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga goto fail; 142830f544ec56eefc628e73e23324dc18105ad13012Istvan Varga } else { 142930f544ec56eefc628e73e23324dc18105ad13012Istvan Varga u16 video_mode, audio_mode; 1430341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu video_mode = xc4000_standard[priv->video_standard].video_mode; 1431341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu audio_mode = xc4000_standard[priv->video_standard].audio_mode; 143230f544ec56eefc628e73e23324dc18105ad13012Istvan Varga if (priv->video_standard < XC4000_BG_PAL_A2) { 1433341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (type & NOGD) 143430f544ec56eefc628e73e23324dc18105ad13012Istvan Varga video_mode &= 0xFF7F; 143530f544ec56eefc628e73e23324dc18105ad13012Istvan Varga } else if (priv->video_standard < XC4000_I_PAL_NICAM) { 14368edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu if (priv->firm_version == 0x0102) 143730f544ec56eefc628e73e23324dc18105ad13012Istvan Varga video_mode &= 0xFEFF; 1438923137a4037d1b9f19d175708eeced209dff9320Istvan Varga if (audio_std & XC4000_AUDIO_STD_B) 1439923137a4037d1b9f19d175708eeced209dff9320Istvan Varga video_mode |= 0x0080; 144030f544ec56eefc628e73e23324dc18105ad13012Istvan Varga } 1441341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu ret = xc_set_tv_standard(priv, video_mode, audio_mode); 1442341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (ret != 0) { 1443341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu printk(KERN_ERR "xc4000: xc_set_tv_standard failed\n"); 144430f544ec56eefc628e73e23324dc18105ad13012Istvan Varga goto fail; 144530f544ec56eefc628e73e23324dc18105ad13012Istvan Varga } 14468d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 14478d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 14488edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu if (xc_write_reg(priv, XREG_D_CODE, 0) == 0) 14498edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu ret = 0; 14508edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu if (xc_write_reg(priv, XREG_AMPLITUDE, 1) != 0) 14518edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu ret = -EREMOTEIO; 14528edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu if (priv->set_smoothedcvbs != 0) { 145330f544ec56eefc628e73e23324dc18105ad13012Istvan Varga if (xc_write_reg(priv, XREG_SMOOTHEDCVBS, 1) != 0) 145430f544ec56eefc628e73e23324dc18105ad13012Istvan Varga ret = -EREMOTEIO; 14558edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu } 14568edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu if (ret != 0) { 14578edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu printk(KERN_ERR "xc4000: setting registers failed\n"); 14588edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu goto fail; 14598d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 14608d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1461e75873c1f80380f190d0270fec566410f59c4829Istvan Varga xc_tune_channel(priv, priv->freq_hz); 14628d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 14635614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga ret = 0; 14645614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga 14655614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Vargafail: 14665614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga mutex_unlock(&priv->lock); 14675614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga 14685614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga return ret; 14698d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 14708d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 14718a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugenstatic int xc4000_get_signal(struct dvb_frontend *fe, u16 *strength) 14728a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen{ 14738a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen struct xc4000_priv *priv = fe->tuner_priv; 14748a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen u16 value = 0; 14758a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen int rc; 14768a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 14778a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen mutex_lock(&priv->lock); 14788a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen rc = xc4000_readreg(priv, XREG_SIGNAL_LEVEL, &value); 14798a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen mutex_unlock(&priv->lock); 14808a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 14818a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen if (rc < 0) 14828a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen goto ret; 14838a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 14848a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen /* Informations from real testing of DVB-T and radio part, 14858a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen coeficient for one dB is 0xff. 14868a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen */ 14878a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen tuner_dbg("Signal strength: -%ddB (%05d)\n", value >> 8, value); 14888a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 14898a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen /* all known digital modes */ 14908a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen if ((priv->video_standard == XC4000_DTV6) || 14918a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen (priv->video_standard == XC4000_DTV7) || 14928a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen (priv->video_standard == XC4000_DTV7_8) || 14938a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen (priv->video_standard == XC4000_DTV8)) 14948a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen goto digital; 14958a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 14968a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen /* Analog mode has NOISE LEVEL important, signal 14978a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen depends only on gain of antenna and amplifiers, 14988a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen but it doesn't tell anything about real quality 14998a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen of reception. 15008a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen */ 15018a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen mutex_lock(&priv->lock); 15028a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen rc = xc4000_readreg(priv, XREG_NOISE_LEVEL, &value); 15038a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen mutex_unlock(&priv->lock); 15048a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 15058a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen tuner_dbg("Noise level: %ddB (%05d)\n", value >> 8, value); 15068a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 15078a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen /* highest noise level: 32dB */ 15088a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen if (value >= 0x2000) { 15098a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen value = 0; 15108a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen } else { 15118a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen value = ~value << 3; 15128a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen } 15138a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 15148a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen goto ret; 15158a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 15168a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen /* Digital mode has SIGNAL LEVEL important and real 15178a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen noise level is stored in demodulator registers. 15188a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen */ 15198a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugendigital: 15208a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen /* best signal: -50dB */ 15218a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen if (value <= 0x3200) { 15228a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen value = 0xffff; 15238a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen /* minimum: -114dB - should be 0x7200 but real zero is 0x713A */ 15248a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen } else if (value >= 0x713A) { 15258a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen value = 0; 15268a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen } else { 15278a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen value = ~(value - 0x3200) << 2; 15288a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen } 15298a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 15308a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugenret: 15318a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen *strength = value; 15328a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 15338a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen return rc; 15348a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen} 15358a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen 15368d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc4000_get_frequency(struct dvb_frontend *fe, u32 *freq) 15378d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 15388d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct xc4000_priv *priv = fe->tuner_priv; 1539f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga 15404c07e32884ab69574cfd9eb4de3334233c938071Mauro Carvalho Chehab *freq = priv->freq_hz + priv->freq_offset; 1541f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga 1542f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga if (debug) { 1543f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga mutex_lock(&priv->lock); 1544f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga if ((priv->cur_fw.type 1545f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga & (BASE | FM | DTV6 | DTV7 | DTV78 | DTV8)) == BASE) { 1546f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga u16 snr = 0; 1547f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga if (xc4000_readreg(priv, XREG_SNR, &snr) == 0) { 1548f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga mutex_unlock(&priv->lock); 1549f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga dprintk(1, "%s() freq = %u, SNR = %d\n", 1550f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga __func__, *freq, snr); 1551f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga return 0; 1552f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga } 1553f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga } 1554f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga mutex_unlock(&priv->lock); 1555f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga } 1556f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga 1557f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga dprintk(1, "%s()\n", __func__); 1558f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga 15598d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return 0; 15608d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 15618d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 15628d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc4000_get_bandwidth(struct dvb_frontend *fe, u32 *bw) 15638d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 15648d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct xc4000_priv *priv = fe->tuner_priv; 15658d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "%s()\n", __func__); 15668d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 15678d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri *bw = priv->bandwidth; 15688d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return 0; 15698d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 15708d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 15718d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc4000_get_status(struct dvb_frontend *fe, u32 *status) 15728d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 15738d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct xc4000_priv *priv = fe->tuner_priv; 1574fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u16 lock_status = 0; 15758d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 15765614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga mutex_lock(&priv->lock); 15775614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga 1578f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga if (priv->cur_fw.type & BASE) 1579f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga xc_get_lock_status(priv, &lock_status); 15808d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1581f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga *status = (lock_status == 1 ? 1582f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga TUNER_STATUS_LOCKED | TUNER_STATUS_STEREO : 0); 1583f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga if (priv->cur_fw.type & (DTV6 | DTV7 | DTV78 | DTV8)) 1584f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga *status &= (~TUNER_STATUS_STEREO); 15855614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga 1586f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga mutex_unlock(&priv->lock); 15878d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1588f4312e2fd4ca44e1defad1637d054bbe11a4ade6Istvan Varga dprintk(2, "%s() lock_status = %d\n", __func__, lock_status); 15898d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 15908d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return 0; 15918d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 15928d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 15938d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc4000_sleep(struct dvb_frontend *fe) 15948d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 15955272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga struct xc4000_priv *priv = fe->tuner_priv; 1596341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu int ret = 0; 15975272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga 15985272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga dprintk(1, "%s()\n", __func__); 15995272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga 16005272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga mutex_lock(&priv->lock); 16015272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga 16025272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga /* Avoid firmware reload on slow devices */ 16035272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga if ((no_poweroff == 2 || 16048edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu (no_poweroff == 0 && priv->default_pm != 0)) && 16055272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga (priv->cur_fw.type & BASE) != 0) { 16065272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga /* force reset and firmware reload */ 16075272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga priv->cur_fw.type = XC_POWERED_DOWN; 16085272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga 1609341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (xc_write_reg(priv, XREG_POWER_DOWN, 0) != 0) { 16105272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga printk(KERN_ERR 16115272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga "xc4000: %s() unable to shutdown tuner\n", 16125272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga __func__); 16135272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga ret = -EREMOTEIO; 16145272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga } 1615341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu msleep(20); 16165272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga } 16175272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga 16185272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga mutex_unlock(&priv->lock); 16195272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga 16205272f6b1f423d4ce636dc90f190e245897bdb045Istvan Varga return ret; 16218d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 16228d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16238d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc4000_init(struct dvb_frontend *fe) 16248d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 16258d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "%s()\n", __func__); 16268d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16278d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return 0; 16288d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 16298d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16308d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic int xc4000_release(struct dvb_frontend *fe) 16318d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 16328d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct xc4000_priv *priv = fe->tuner_priv; 16338d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16348d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "%s()\n", __func__); 16358d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16368d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri mutex_lock(&xc4000_list_mutex); 16378d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16388d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri if (priv) 16398d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri hybrid_tuner_release_state(priv); 16408d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16418d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri mutex_unlock(&xc4000_list_mutex); 16428d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16438d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri fe->tuner_priv = NULL; 16448d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16458d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return 0; 16468d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 16478d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16488d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristatic const struct dvb_tuner_ops xc4000_tuner_ops = { 16498d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .info = { 16508d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .name = "Xceive XC4000", 16518d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .frequency_min = 1000000, 16528d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .frequency_max = 1023000000, 16538d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .frequency_step = 50000, 16548d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri }, 16558d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16568d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .release = xc4000_release, 16578d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .init = xc4000_init, 16588d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .sleep = xc4000_sleep, 16598d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16608d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .set_params = xc4000_set_params, 16618d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .set_analog_params = xc4000_set_analog_params, 16628d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .get_frequency = xc4000_get_frequency, 16638a538a8855aa95e5a12ae232a140e6b30c56d0c5Miroslav Slugen .get_rf_strength = xc4000_get_signal, 16648d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .get_bandwidth = xc4000_get_bandwidth, 16658d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri .get_status = xc4000_get_status 16668d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri}; 16678d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16688d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferristruct dvb_frontend *xc4000_attach(struct dvb_frontend *fe, 16698d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct i2c_adapter *i2c, 16708d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct xc4000_config *cfg) 16718d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri{ 16728d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri struct xc4000_priv *priv = NULL; 1673fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga int instance; 1674fbe4a29f2f6523b8b839debb19baa49461a302beIstvan Varga u16 id = 0; 16758d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16768d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri dprintk(1, "%s(%d-%04x)\n", __func__, 16778d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri i2c ? i2c_adapter_id(i2c) : -1, 16788d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri cfg ? cfg->i2c_address : -1); 16798d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16808d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri mutex_lock(&xc4000_list_mutex); 16818d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 16828d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri instance = hybrid_tuner_request_state(struct xc4000_priv, priv, 16838d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri hybrid_tuner_instance_list, 16848d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri i2c, cfg->i2c_address, "xc4000"); 16858d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri switch (instance) { 16868d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri case 0: 16878d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri goto fail; 16888d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri case 1: 16898d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri /* new tuner instance */ 1690c6f56e7d794cba022353d464dfa3383d1b3e0125Mauro Carvalho Chehab priv->bandwidth = 6000000; 16918edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu /* set default configuration */ 16928edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu priv->if_khz = 4560; 16938edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu priv->default_pm = 0; 16948edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu priv->dvb_amplitude = 134; 16958edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu priv->set_smoothedcvbs = 1; 16965614942bb06f5620d0d6eb67bc0268c76c5dd921Istvan Varga mutex_init(&priv->lock); 16978d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri fe->tuner_priv = priv; 16988d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri break; 16998d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri default: 17008d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri /* existing tuner instance */ 17018d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri fe->tuner_priv = priv; 17028d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri break; 17038d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 17048d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 17050b4021321c0536a3368746497686ce56e5bcf3e5Istvan Varga if (cfg->if_khz != 0) { 17068edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu /* copy configuration if provided by the caller */ 17078d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri priv->if_khz = cfg->if_khz; 17088edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu priv->default_pm = cfg->default_pm; 17098edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu priv->dvb_amplitude = cfg->dvb_amplitude; 17108edeb6eb1ae113b8f25a79e5076c1a1ec93538d0istvan_v@mailbox.hu priv->set_smoothedcvbs = cfg->set_smoothedcvbs; 17118d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 17128d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 17138d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri /* Check if firmware has been loaded. It is possible that another 17148d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri instance of the driver has loaded the firmware. 17158d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri */ 17168d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1717027fd361860e40736c0ad093a8f4194d727afb63Istvan Varga if (instance == 1) { 1718341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (xc4000_readreg(priv, XREG_PRODUCT_ID, &id) != 0) 17198d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri goto fail; 1720027fd361860e40736c0ad093a8f4194d727afb63Istvan Varga } else { 1721027fd361860e40736c0ad093a8f4194d727afb63Istvan Varga id = ((priv->cur_fw.type & BASE) != 0 ? 1722027fd361860e40736c0ad093a8f4194d727afb63Istvan Varga priv->hwmodel : XC_PRODUCT_ID_FW_NOT_LOADED); 1723027fd361860e40736c0ad093a8f4194d727afb63Istvan Varga } 17248d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 17258d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri switch (id) { 17267db98fe66be035494912b6b2c4e9c1e3abfedfe5Istvan Varga case XC_PRODUCT_ID_XC4000: 17277db98fe66be035494912b6b2c4e9c1e3abfedfe5Istvan Varga case XC_PRODUCT_ID_XC4100: 17288d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri printk(KERN_INFO 17298d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri "xc4000: Successfully identified at address 0x%02x\n", 17308d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri cfg->i2c_address); 17318d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri printk(KERN_INFO 17328d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri "xc4000: Firmware has been loaded previously\n"); 17338d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri break; 17348d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri case XC_PRODUCT_ID_FW_NOT_LOADED: 17358d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri printk(KERN_INFO 17368d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri "xc4000: Successfully identified at address 0x%02x\n", 17378d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri cfg->i2c_address); 17388d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri printk(KERN_INFO 17398d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri "xc4000: Firmware has not been loaded previously\n"); 17408d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri break; 17418d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri default: 17428d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri printk(KERN_ERR 17438d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri "xc4000: Device not found at addr 0x%02x (0x%x)\n", 17448d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri cfg->i2c_address, id); 17458d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri goto fail; 17468d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri } 17478d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 17488d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri mutex_unlock(&xc4000_list_mutex); 17498d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 17508d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri memcpy(&fe->ops.tuner_ops, &xc4000_tuner_ops, 17518d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri sizeof(struct dvb_tuner_ops)); 17528d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 1753027fd361860e40736c0ad093a8f4194d727afb63Istvan Varga if (instance == 1) { 1754027fd361860e40736c0ad093a8f4194d727afb63Istvan Varga int ret; 1755027fd361860e40736c0ad093a8f4194d727afb63Istvan Varga mutex_lock(&priv->lock); 1756027fd361860e40736c0ad093a8f4194d727afb63Istvan Varga ret = xc4000_fwupload(fe); 1757027fd361860e40736c0ad093a8f4194d727afb63Istvan Varga mutex_unlock(&priv->lock); 1758341747bef5dd2e2f56647ba30ea2180752905fa0istvan_v@mailbox.hu if (ret != 0) 1759027fd361860e40736c0ad093a8f4194d727afb63Istvan Varga goto fail2; 1760027fd361860e40736c0ad093a8f4194d727afb63Istvan Varga } 176111091a31fbf7496294795ca72d69db0233857d94Devin Heitmueller 17628d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return fe; 17638d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferrifail: 17648d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri mutex_unlock(&xc4000_list_mutex); 1765027fd361860e40736c0ad093a8f4194d727afb63Istvan Vargafail2: 17668d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri xc4000_release(fe); 17678d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri return NULL; 17688d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri} 17698d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide FerriEXPORT_SYMBOL(xc4000_attach); 17708d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide Ferri 17718d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide FerriMODULE_AUTHOR("Steven Toth, Davide Ferri"); 17728d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide FerriMODULE_DESCRIPTION("Xceive xc4000 silicon tuner driver"); 17738d009a0c41475a482aca17d2a9fc8e6965f2fdf9Davide FerriMODULE_LICENSE("GPL"); 1774612ae142ac02e8b187f23b8c9f1cc9cd8c6a078dMauro Carvalho ChehabMODULE_FIRMWARE(XC4000_DEFAULT_FIRMWARE_NEW); 1775612ae142ac02e8b187f23b8c9f1cc9cd8c6a078dMauro Carvalho ChehabMODULE_FIRMWARE(XC4000_DEFAULT_FIRMWARE); 1776