budget-patch.c revision fdc53a6dbfea18e621dd23ed5cfb160837d7ce52
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * budget-patch.c: driver for Budget Patch, 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hardware modification of DVB-S cards enabling full TS 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Written by Emard <emard@softhome.net> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Original idea by Roberto Deza <rdeza@unav.es> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Special thanks to Holger Waechtler, Michael Hunold, Marian Durkovic 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and Metzlerbros 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is free software; you can redistribute it and/or 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * modify it under the terms of the GNU General Public License 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as published by the Free Software Foundation; either version 2 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the License, or (at your option) any later version. 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This program is distributed in the hope that it will be useful, 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * but WITHOUT ANY WARRANTY; without even the implied warranty of 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * GNU General Public License for more details. 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * along with this program; if not, write to the Free Software 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the project's page is at http://www.linuxtv.org/dvb/ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "av7110.h" 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "av7110_hw.h" 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "budget.h" 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "stv0299.h" 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "ves1x93.h" 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "tda8083.h" 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define budget_patch budget 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct saa7146_extension budget_extension; 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMAKE_BUDGET_INFO(ttbp, "TT-Budget/Patch DVB-S 1.x PCI", BUDGET_PATCH); 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds//MAKE_BUDGET_INFO(satel,"TT-Budget/Patch SATELCO PCI", BUDGET_TT_HW_DISEQC); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pci_device_id pci_tbl[] = { 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MAKE_EXTENSION_PCI(ttbp,0x13c2, 0x0000), 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds// MAKE_EXTENSION_PCI(satel, 0x13c2, 0x1013), 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .vendor = 0, 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* those lines are for budget-patch to be tried 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** on a true budget card and observe the 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** behaviour of VSYNC generated by rps1. 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** this code was shamelessly copy/pasted from budget.c 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void gpio_Set22K (struct budget *budget, int state) 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct saa7146_dev *dev=budget->dev; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(2, "budget: %p\n", budget); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_setgpio(dev, 3, (state ? SAA7146_GPIO_OUTHI : SAA7146_GPIO_OUTLO)); 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Diseqc functions only for TT Budget card */ 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* taken from the Skyvision DVB driver by 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds Ralph Metzler <rjkm@metzlerbros.de> */ 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void DiseqcSendBit (struct budget *budget, int data) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct saa7146_dev *dev=budget->dev; 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(2, "budget: %p\n", budget); 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(data ? 500 : 1000); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(data ? 1000 : 500); 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void DiseqcSendByte (struct budget *budget, int data) 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i, par=1, d; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(2, "budget: %p\n", budget); 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=7; i>=0; i--) { 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds d = (data>>i)&1; 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds par ^= d; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DiseqcSendBit(budget, d); 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DiseqcSendBit(budget, par); 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int SendDiSEqCMsg (struct budget *budget, int len, u8 *msg, unsigned long burst) 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct saa7146_dev *dev=budget->dev; 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(2, "budget: %p\n", budget); 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay(16); 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=0; i<len; i++) 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DiseqcSendByte(budget, msg[i]); 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay(16); 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (burst!=-1) { 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (burst) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds DiseqcSendByte(budget, 0xff); 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else { 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds udelay(12500); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(20); 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* shamelessly copy/pasted from budget.c 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int budget_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct budget* budget = (struct budget*) fe->dvb->priv; 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (tone) { 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SEC_TONE_ON: 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio_Set22K (budget, 1); 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SEC_TONE_OFF: 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds gpio_Set22K (budget, 0); 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int budget_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct budget* budget = (struct budget*) fe->dvb->priv; 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SendDiSEqCMsg (budget, cmd->msg_len, cmd->msg, 0); 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int budget_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct budget* budget = (struct budget*) fe->dvb->priv; 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SendDiSEqCMsg (budget, 0, NULL, minicmd); 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int budget_av7110_send_fw_cmd(struct budget_patch *budget, u16* buf, int length) 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(2, "budget: %p\n", budget); 1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 2; i < length; i++) 1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { 1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND + 2*i, 2, (u32) buf[i], 0,0); 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(5); 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (length) 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND + 2, 2, (u32) buf[1], 0,0); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND + 2, 2, 0, 0,0); 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(5); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ttpci_budget_debiwrite(budget, DEBINOSWAP, COMMAND, 2, (u32) buf[0], 0,0); 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(5); 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void av7110_set22k(struct budget_patch *budget, int state) 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 buf[2] = {( COMTYPE_AUDIODAC << 8) | (state ? ON22K : OFF22K), 0}; 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(2, "budget: %p\n", budget); 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget_av7110_send_fw_cmd(budget, buf, 2); 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int av7110_send_diseqc_msg(struct budget_patch *budget, int len, u8 *msg, int burst) 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int i; 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u16 buf[18] = { ((COMTYPE_AUDIODAC << 8) | SendDiSEqC), 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(2, "budget: %p\n", budget); 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (len>10) 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds len=10; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[1] = len+2; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[2] = len; 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (burst != -1) 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[3]=burst ? 0x01 : 0x00; 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[3]=0xffff; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i=0; i<len; i++) 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[i+4]=msg[i]; 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget_av7110_send_fw_cmd(budget, buf, 18); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int budget_patch_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (tone) { 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SEC_TONE_ON: 2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av7110_set22k (budget, 1); 2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case SEC_TONE_OFF: 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av7110_set22k (budget, 0); 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int budget_patch_diseqc_send_master_cmd(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd* cmd) 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av7110_send_diseqc_msg (budget, cmd->msg_len, cmd->msg, 0); 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int budget_patch_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t minicmd) 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds av7110_send_diseqc_msg (budget, 0, NULL, minicmd); 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int alps_bsrv2_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) 2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 pwr = 0; 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 buf[4]; 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) }; 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 div = (params->frequency + 479500) / 125; 2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (params->frequency > 2000000) pwr = 3; 2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (params->frequency > 1800000) pwr = 2; 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (params->frequency > 1600000) pwr = 1; 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (params->frequency > 1200000) pwr = 0; 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (params->frequency >= 1100000) pwr = 1; 2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else pwr = 2; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[0] = (div >> 8) & 0x7f; 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[1] = div & 0xff; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[2] = ((div & 0x18000) >> 10) | 0x95; 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds buf[3] = (pwr << 6) | 0x30; 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // NOTE: since we're using a prescaler of 2, we set the 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // divisor frequency to 62.5kHz and divide by 125 above 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct ves1x93_config alps_bsrv2_config = { 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .demod_address = 0x08, 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .xin = 90100000UL, 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .invert_pwm = 0, 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pll_set = alps_bsrv2_pll_set, 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 alps_bsru6_inittab[] = { 2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x01, 0x15, 2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x02, 0x00, 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x03, 0x00, 2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x04, 0x7d, /* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */ 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x05, 0x35, /* I2CT = 0, SCLT = 1, SDAT = 1 */ 2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x06, 0x40, /* DAC not used, set to high impendance mode */ 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x07, 0x00, /* DAC LSB */ 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x08, 0x40, /* DiSEqC off, LNB power on OP2/LOCK pin on */ 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x09, 0x00, /* FIFO */ 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x0c, 0x51, /* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */ 3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x0d, 0x82, /* DC offset compensation = ON, beta_agc1 = 2 */ 3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x0e, 0x23, /* alpha_tmg = 2, beta_tmg = 3 */ 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x10, 0x3f, // AGC2 0x3d 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x11, 0x84, 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x12, 0xb5, // Lock detect: -64 Carrier freq detect:on 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x15, 0xc9, // lock detector threshold 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x16, 0x00, 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x17, 0x00, 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x18, 0x00, 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x19, 0x00, 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x1a, 0x00, 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x1f, 0x50, 3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x20, 0x00, 3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x21, 0x00, 3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x22, 0x00, 3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x23, 0x00, 3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x28, 0x00, // out imp: normal out type: parallel FEC mode:0 3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x29, 0x1e, // 1/2 threshold 3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x2a, 0x14, // 2/3 threshold 3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x2b, 0x0f, // 3/4 threshold 3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x2c, 0x09, // 5/6 threshold 3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x2d, 0x05, // 7/8 threshold 3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x2e, 0x01, 3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x31, 0x1f, // test all FECs 3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x32, 0x19, // viterbi and synchro search 3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x33, 0xfc, // rs control 3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x34, 0x93, // error control 3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0x0f, 0x52, 3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0xff, 0xff 3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int alps_bsru6_set_symbol_rate(struct dvb_frontend* fe, u32 srate, u32 ratio) 3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 aclk = 0; 3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 bclk = 0; 3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (srate < 1500000) { aclk = 0xb7; bclk = 0x47; } 3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (srate < 3000000) { aclk = 0xb7; bclk = 0x4b; } 3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (srate < 7000000) { aclk = 0xb7; bclk = 0x4f; } 3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (srate < 14000000) { aclk = 0xb7; bclk = 0x53; } 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (srate < 30000000) { aclk = 0xb6; bclk = 0x53; } 3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else if (srate < 45000000) { aclk = 0xb4; bclk = 0x51; } 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stv0299_writereg (fe, 0x13, aclk); 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stv0299_writereg (fe, 0x14, bclk); 3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stv0299_writereg (fe, 0x1f, (ratio >> 16) & 0xff); 3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stv0299_writereg (fe, 0x20, (ratio >> 8) & 0xff); 3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds stv0299_writereg (fe, 0x21, (ratio ) & 0xf0); 3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int alps_bsru6_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) 3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; 3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 data[4]; 3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 div; 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((params->frequency < 950000) || (params->frequency > 2150000)) return -EINVAL; 3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds div = (params->frequency + (125 - 1)) / 125; // round correctly 3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[0] = (div >> 8) & 0x7f; 3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[1] = div & 0xff; 3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[2] = 0x80 | ((div & 0x18000) >> 10) | 4; 3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[3] = 0xC4; 3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (params->frequency > 1530000) data[3] = 0xc0; 3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; 3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct stv0299_config alps_bsru6_config = { 3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .demod_address = 0x68, 3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .inittab = alps_bsru6_inittab, 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .mclk = 88000000UL, 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .invert = 1, 3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .enhanced_tuning = 0, 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .skip_reinit = 0, 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .lock_output = STV0229_LOCKOUTPUT_1, 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .volt13_op0_op1 = STV0299_VOLT13_OP1, 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .min_delay_ms = 100, 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .set_symbol_rate = alps_bsru6_set_symbol_rate, 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pll_set = alps_bsru6_pll_set, 3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int grundig_29504_451_pll_set(struct dvb_frontend* fe, struct dvb_frontend_parameters* params) 3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct budget_patch* budget = (struct budget_patch*) fe->dvb->priv; 3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u32 div; 3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds u8 data[4]; 3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct i2c_msg msg = { .addr = 0x61, .flags = 0, .buf = data, .len = sizeof(data) }; 3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds div = params->frequency / 125; 4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[0] = (div >> 8) & 0x7f; 4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[1] = div & 0xff; 4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[2] = 0x8e; 4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds data[3] = 0x00; 4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (i2c_transfer (&budget->i2c_adap, &msg, 1) != 1) return -EIO; 4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct tda8083_config grundig_29504_451_config = { 4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .demod_address = 0x68, 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pll_set = grundig_29504_451_pll_set, 4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void frontend_init(struct budget_patch* budget) 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch(budget->dev->pci->subsystem_device) { 4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x0000: // Hauppauge/TT WinTV DVB-S rev1.X 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0x1013: // SATELCO Multimedia PCI 4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // try the ALPS BSRV2 first of all 4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dvb_frontend = ves1x93_attach(&alps_bsrv2_config, &budget->i2c_adap); 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (budget->dvb_frontend) { 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_patch_diseqc_send_master_cmd; 4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dvb_frontend->ops->diseqc_send_burst = budget_patch_diseqc_send_burst; 4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dvb_frontend->ops->set_tone = budget_patch_set_tone; 4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // try the ALPS BSRU6 now 4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dvb_frontend = stv0299_attach(&alps_bsru6_config, &budget->i2c_adap); 4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (budget->dvb_frontend) { 4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; 4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; 4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dvb_frontend->ops->set_tone = budget_set_tone; 4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Try the grundig 29504-451 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dvb_frontend = tda8083_attach(&grundig_29504_451_config, &budget->i2c_adap); 4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (budget->dvb_frontend) { 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dvb_frontend->ops->diseqc_send_master_cmd = budget_diseqc_send_master_cmd; 4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dvb_frontend->ops->diseqc_send_burst = budget_diseqc_send_burst; 4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dvb_frontend->ops->set_tone = budget_set_tone; 4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (budget->dvb_frontend == NULL) { 4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("dvb-ttpci: A frontend driver was not found for device %04x/%04x subsystem %04x/%04x\n", 4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dev->pci->vendor, 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dev->pci->device, 4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dev->pci->subsystem_vendor, 4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dev->pci->subsystem_device); 4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else { 456fdc53a6dbfea18e621dd23ed5cfb160837d7ce52Johannes Stezenbach if (dvb_register_frontend(&budget->dvb_adapter, budget->dvb_frontend)) { 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("budget-av: Frontend registration failed!\n"); 4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (budget->dvb_frontend->ops->release) 4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dvb_frontend->ops->release(budget->dvb_frontend); 4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds budget->dvb_frontend = NULL; 4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* written by Emard */ 4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int budget_patch_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *info) 4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct budget_patch *budget; 4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int count = 0; 4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int detected = 0; 4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PATCH_RESET 0 4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define RPS_IRQ 0 4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define HPS_SETUP 0 4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if PATCH_RESET 4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, MC1, MASK_31); 4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds msleep(40); 4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if HPS_SETUP 4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // initialize registers. Better to have it like this 4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // than leaving something unconfigured 4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, DD1_STREAM_B, 0); 4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // port B VSYNC at rising edge 4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, DD1_INIT, 0x00000200); // have this in budget-core too! 4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, BRS_CTRL, 0x00000000); // VBI 4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // debi config 4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // saa7146_write(dev, DEBI_CONFIG, MASK_30|MASK_28|MASK_18); 4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // zero all HPS registers 4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, HPS_H_PRESCALE, 0); // r68 4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, HPS_H_SCALE, 0); // r6c 4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, BCS_CTRL, 0); // r70 4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, HPS_V_SCALE, 0); // r60 4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, HPS_V_GAIN, 0); // r64 4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, CHROMA_KEY_RANGE, 0); // r74 4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, CLIP_FORMAT_CTRL, 0); // r78 4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Set HPS prescaler for port B input 5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, HPS_CTRL, (1<<30) | (0<<29) | (1<<28) | (0<<12) ); 5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, MC2, 5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0 * (MASK_08 | MASK_24) | // BRS control 5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0 * (MASK_09 | MASK_25) | // a 5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0 * (MASK_10 | MASK_26) | // b 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1 * (MASK_06 | MASK_22) | // HPS_CTRL1 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1 * (MASK_05 | MASK_21) | // HPS_CTRL2 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 0 * (MASK_01 | MASK_15) // DEBI 5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ); 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Disable RPS1 and RPS0 5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, MC1, ( MASK_29 | MASK_28)); 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // RPS1 timeout disable 5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, RPS_TOV1, 0); 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // code for autodetection 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // will wait for VBI_B event (vertical blank at port B) 5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // and will reset GPIO3 after VBI_B is detected. 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // (GPIO3 should be raised high by CPU to 5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // test if GPIO3 will generate vertical blank signal 5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // in budget patch GPIO3 is connected to VSYNC_B 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = 0; 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(CMD_UPLOAD | 5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds MASK_10 | MASK_09 | MASK_08 | MASK_06 | MASK_05 | MASK_04 | MASK_03 | MASK_02 )); 5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_VBI_B)); 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2))); 5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(GPIO3_MSK)); 5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24)); 5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if RPS_IRQ 5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // issue RPS1 interrupt to increment counter 5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT)); 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // at least a NOP is neede between two interrupts 5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(CMD_NOP)); 5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // interrupt again 5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT)); 5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(CMD_STOP)); 5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if RPS_IRQ 5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // set event counter 1 source as RPS1 interrupt (0x03) (rE4 p53) 5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // use 0x03 to track RPS1 interrupts - increase by 1 every gpio3 is toggled 5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // use 0x15 to track VPE interrupts - increase by 1 every vpeirq() is called 5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, EC1SSR, (0x03<<2) | 3 ); 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // set event counter 1 treshold to maximum allowed value (rEC p55) 5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, ECT1R, 0x3fff ); 5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Fix VSYNC level 5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); 5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Set RPS1 Address register to point to RPS code (r108 p42) 5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle); 5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Enable RPS1, (rFC p33) 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, MC1, (MASK_13 | MASK_29 )); 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay(50); 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTHI); 5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay(150); 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if( (saa7146_read(dev, GPIO_CTRL) & 0x10000000) == 0) 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds detected = 1; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if RPS_IRQ 5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("Event Counter 1 0x%04x\n", saa7146_read(dev, EC1R) & 0x3fff ); 5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Disable RPS1 5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, MC1, ( MASK_29 )); 5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if(detected == 0) 5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("budget-patch not detected or saa7146 in non-default state.\n" 5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "try enabling ressetting of 7146 with MASK_31 in MC1 register\n"); 5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk("BUDGET-PATCH DETECTED.\n"); 5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* OLD (Original design by Roberto Deza): 5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** This code will setup the SAA7146_RPS1 to generate a square 5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** wave on GPIO3, changing when a field (TS_HEIGHT/2 "lines" of 5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** TS_WIDTH packets) has been acquired on SAA7146_D1B video port; 5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** then, this GPIO3 output which is connected to the D1B_VSYNC 5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** input, will trigger the acquisition of the alternate field 5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** and so on. 5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Currently, the TT_budget / WinTV_Nova cards have two ICs 5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** (74HCT4040, LVC74) for the generation of this VSYNC signal, 5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** which seems that can be done perfectly without this :-)). 5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* New design (By Emard) 5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** this rps1 code will copy internal HS event to GPIO3 pin. 5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** GPIO3 is in budget-patch hardware connectd to port B VSYNC 5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** HS is an internal event of 7146, accessible with RPS 5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** and temporarily raised high every n lines 5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** (n in defined in the RPS_THRESH1 counter threshold) 5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** I think HS is raised high on the beginning of the n-th line 5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** and remains high until this n-th line that triggered 5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** it is completely received. When the receiption of n-th line 6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** ends, HS is lowered. 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** To transmit data over DMA, 7146 needs changing state at 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** port B VSYNC pin. Any changing of port B VSYNC will 6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** cause some DMA data transfer, with more or less packets loss. 6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** It depends on the phase and frequency of VSYNC and 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** the way of 7146 is instructed to trigger on port B (defined 6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** in DD1_INIT register, 3rd nibble from the right valid 6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** numbers are 0-7, see datasheet) 6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** 6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** The correct triggering can minimize packet loss, 6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** dvbtraffic should give this stable bandwidths: 6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** 22k transponder = 33814 kbit/s 6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** 27.5k transponder = 38045 kbit/s 6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** by experiment it is found that the best results 6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** (stable bandwidths and almost no packet loss) 6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** are obtained using DD1_INIT triggering number 2 6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** (Va at rising edge of VS Fa = HS x VS-failing forced toggle) 6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** and a VSYNC phase that occurs in the middle of DMA transfer 6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** (about byte 188*512=96256 in the DMA window). 6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** 6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** Phase of HS is still not clear to me how to control, 6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** It just happens to be so. It can be seen if one enables 6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** RPS_IRQ and print Event Counter 1 in vpeirq(). Every 6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** time RPS_INTERRUPT is called, the Event Counter 1 will 6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** increment. That's how the 7146 is programmed to do event 6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** counting in this budget-patch.c 6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** I *think* HPS setting has something to do with the phase 6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** of HS but I cant be 100% sure in that. 6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** hardware debug note: a working budget card (including budget patch) 6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** with vpeirq() interrupt setup in mode "0x90" (every 64K) will 6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** generate 3 interrupts per 25-Hz DMA frame of 2*188*512 bytes 6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** and that means 3*25=75 Hz of interrupt freqency, as seen by 6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** watch cat /proc/interrupts 6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** 6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** If this frequency is 3x lower (and data received in the DMA 6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** buffer don't start with 0x47, but in the middle of packets, 6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** whose lengths appear to be like 188 292 188 104 etc. 6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** this means VSYNC line is not connected in the hardware. 6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** (check soldering pcb and pins) 6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** The same behaviour of missing VSYNC can be duplicated on budget 6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds** cards, by seting DD1_INIT trigger mode 7 in 3rd nibble. 6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/ 6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Setup RPS1 "program" (p35) 6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds count = 0; 6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Wait Source Line Counter Threshold (p36) 6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(CMD_PAUSE | EVT_HS)); 6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Set GPIO3=1 (p42) 6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2))); 6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(GPIO3_MSK)); 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTHI<<24)); 6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if RPS_IRQ 6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // issue RPS1 interrupt 6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT)); 6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Wait reset Source Line Counter Threshold (p36) 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(CMD_PAUSE | RPS_INV | EVT_HS)); 6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Set GPIO3=0 (p42) 6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(CMD_WR_REG_MASK | (GPIO_CTRL>>2))); 6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(GPIO3_MSK)); 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(SAA7146_GPIO_OUTLO<<24)); 6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if RPS_IRQ 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // issue RPS1 interrupt 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(CMD_INTERRUPT)); 6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Jump to begin of RPS program (p37) 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(CMD_JUMP)); 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds WRITE_RPS1(cpu_to_le32(dev->d_rps1.dma_handle)); 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Fix VSYNC level 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_setgpio(dev, 3, SAA7146_GPIO_OUTLO); 6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Set RPS1 Address register to point to RPS code (r108 p42) 6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, RPS_ADDR1, dev->d_rps1.dma_handle); 6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Set Source Line Counter Threshold, using BRS (rCC p43) 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // It generates HS event every TS_HEIGHT lines 6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // this is related to TS_WIDTH set in register 6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // NUM_LINE_BYTE3 in budget-core.c. If NUM_LINE_BYTE 6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // low 16 bits are set to TS_WIDTH bytes (TS_WIDTH=2*188 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds //,then RPS_THRESH1 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // should be set to trigger every TS_HEIGHT (512) lines. 6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // 6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, RPS_THRESH1, (TS_HEIGHT*1) | MASK_12 ); 6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // saa7146_write(dev, RPS_THRESH0, ((TS_HEIGHT/2)<<16) |MASK_28| (TS_HEIGHT/2) |MASK_12 ); 6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // Enable RPS1 (rFC p33) 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_write(dev, MC1, (MASK_13 | MASK_29)); 6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!(budget = kmalloc (sizeof(struct budget_patch), GFP_KERNEL))) 6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dprintk(2, "budget: %p\n", budget); 6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((err = ttpci_budget_init (budget, dev, info, THIS_MODULE))) { 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree (budget); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dev->ext_priv = budget; 7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 705fdc53a6dbfea18e621dd23ed5cfb160837d7ce52Johannes Stezenbach budget->dvb_adapter.priv = budget; 7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds frontend_init(budget); 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int budget_patch_detach (struct saa7146_dev* dev) 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct budget_patch *budget = (struct budget_patch*) dev->ext_priv; 7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int err; 7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (budget->dvb_frontend) dvb_unregister_frontend(budget->dvb_frontend); 7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds err = ttpci_budget_deinit (budget); 7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree (budget); 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return err; 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init budget_patch_init(void) 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return saa7146_register_extension(&budget_extension); 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit budget_patch_exit(void) 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds saa7146_unregister_extension(&budget_extension); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct saa7146_extension budget_extension = { 7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "budget_patch dvb\0", 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .flags = 0, 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .module = THIS_MODULE, 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .pci_tbl = pci_tbl, 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .attach = budget_patch_attach, 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .detach = budget_patch_detach, 7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .irq_mask = MASK_10, 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .irq_func = ttpci_budget_irq10_handler, 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(budget_patch_init); 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(budget_patch_exit); 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Emard, Roberto Deza, Holger Waechtler, Michael Hunold, others"); 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("Driver for full TS modified DVB-S SAA7146+AV7110 " 7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds "based so-called Budget Patch cards"); 755