AT76C651

Sklaventreiber
crdfreak
Beiträge: 2
Registriert: Donnerstag 30. August 2007, 22:18

Beitrag von crdfreak »

Hallo,

ich habe folgendes Problem:
Zwei gleiche Nokia Kabel, jeweils Avia 500 und 2xI.
Beide liefen bis vor kurzem Problemlos. Dann kam die Unitymedia Kabel Umstellung (->QAM256). Beide haben keine Kanäle mehr gefunden. Akt. Images drauf (MD,JTG), entweder direkt mit Tunerfix bzw. Tunerfixes selber eingespielt (->1820.o).
Die eine Box rennt wie verrückt. Die andere findet nichts, kein ARD, ZDF, etc. . Auch ein auslesen der "guten" Box und flashen auf die "schlechte" bringt nichts. Ich denke, daß die Profis hier noch mal an dem Treiberfix arbeiten müssen. Habe schon in div. Boards gesehen, das es einigen so geht.

Es kommt mir so vor, als wäre Avia 500 und 2xI nicht immer das gleiche, gibt es sonst noch Unterschiede? Die µcodes habe auch so ziemlich alle durch. Bin ziemlich ratlos.

Danke und Gruß
ingrid
Erleuchteter
Erleuchteter
Beiträge: 600
Registriert: Samstag 14. Oktober 2006, 10:53

Beitrag von ingrid »

crdfreak hat geschrieben:ich habe folgendes Problem:
Zwei gleiche Nokia Kabel, jeweils Avia 500 und 2xI.
Falscher Thread, hier geht's um Sagem. Schau mal dort rein, da geht's um Nokia: http://forum.tuxbox-cvs.sourceforge.net ... hp?t=46151
deepblue2000
Interessierter
Interessierter
Beiträge: 21
Registriert: Sonntag 5. Oktober 2003, 21:33

Beitrag von deepblue2000 »

so,

nach mehrere Wochen Test mit den V8... muss ich sagen zum Gucken fast alles in ordnung, nur bei premiere bleibt das bild nun mal stehen (selten) und Aufnahmen sind immer fast unbrauchbar. Immer viele Fehler im Stream usw.

V8 für ISH Kanäle OK aber Premiere macht Probs.

Ich denkmal zum capturn muss ich die V8 rauswerfen und die alten nutzen.
Gorcon
Tuxboxer
Tuxboxer
Beiträge: 5873
Registriert: Samstag 23. Februar 2002, 22:46

Beitrag von Gorcon »

Immer viele Fehler im Stream
Das hat aber nichts mit dem Treiber zu tun sondern mit Premiere selbst. (ist überall so, auch über Sat).

Gruß Gorcon
ThulsaDoom
Interessierter
Interessierter
Beiträge: 86
Registriert: Montag 18. Dezember 2006, 10:28

Beitrag von ThulsaDoom »

Gorcon hat geschrieben:
Immer viele Fehler im Stream
Das hat aber nichts mit dem Treiber zu tun sondern mit Premiere selbst. (ist überall so, auch über Sat).

Gruß Gorcon
Na ja, ist nicht pauschal so (aber ich sehe es Dir nach, denn Du hast ja gar kein Sat und kannst das nicht überprüfen :wink: ). Meine Aufnahmen über DVB-S PC-Karte sind fehlerfrei (bis auf die klitzekleinen Hakler bei Auf-/Ab-/Umschaltung der AC3 bzw. 2ten Tonspur; der Film selbst hat gem. ProjectX keine Fehler).

Gruß
ThulsaDoom
T-Tron
Interessierter
Interessierter
Beiträge: 67
Registriert: Mittwoch 2. November 2005, 07:45

Beitrag von T-Tron »

Framekorrektur beim Streamen + Buffer = ProjectX-Liebling
Gorcon
Tuxboxer
Tuxboxer
Beiträge: 5873
Registriert: Samstag 23. Februar 2002, 22:46

Beitrag von Gorcon »

(aber ich sehe es Dir nach, denn Du hast ja gar kein Sat und kannst das nicht überprüfen ).
Ich habe zwar kein Sat aber Kabel und daher kann ich das sehr wohl überprüfen denn das ist ja ein direkt umgesetztes Satsignal.

Aussserdem hat mein Bruder exakt das gleiche Problem mit Sat und wenn ich die Logs vergleiche sind die fehler immer exakt an den gleichen Stellen, also wird das so gesendet.

Gruß Gorcon
T-Tron
Interessierter
Interessierter
Beiträge: 67
Registriert: Mittwoch 2. November 2005, 07:45

Beitrag von T-Tron »

Dein Bruder hat aber auch eine DBox2, oder? Die pusht einfach nur den TS, und dabei hat sie halt manchmal Probleme 8)
ThulsaDoom
Interessierter
Interessierter
Beiträge: 86
Registriert: Montag 18. Dezember 2006, 10:28

Beitrag von ThulsaDoom »

Gorcon hat geschrieben:
(aber ich sehe es Dir nach, denn Du hast ja gar kein Sat und kannst das nicht überprüfen ).
Ich habe zwar kein Sat aber Kabel und daher kann ich das sehr wohl überprüfen denn das ist ja ein direkt umgesetztes Satsignal.

Aussserdem hat mein Bruder exakt das gleiche Problem mit Sat und wenn ich die Logs vergleiche sind die fehler immer exakt an den gleichen Stellen, also wird das so gesendet.

Gruß Gorcon
Ja Gorcon, ich kenne Dich von einigen Boards (vom lesen) und weiss ja, dass Du eigentlich nie Müll schreibst. Ich will deine Feststellungen auch nicht in Frage stellen, nur habe ich eigentlich jede 2te Nacht einen Film von P auf meinem PC aufgenommen und wenn da mehr als 2 Fehler drinne wären, dann wäre mir schon die Galle hochgekommen. Denn wenn es ruckelt, knackst oder sonstwas, dann würde die Aufnahme sofort wieder runterfliegen bei mir. Glücklicherweise sind diese Momente so gut wie ausgestorben!

T-Tron wird da Recht haben, denke ich.

Gruß
ThulsaDoom

P.S.: Ich will hier aber auch nicht vom eigentlichen Thema ablenken (den Thread habe ich mir nicht weiter durchgelesen, denn es geht ja um irgendwelche Kabeltreiber - denke ich)
Rache Klos
Einsteiger
Einsteiger
Beiträge: 193
Registriert: Samstag 24. November 2001, 00:00

Beitrag von Rache Klos »

Nachdem ich auf diesen Thread gestoßen bin, gibt es wieder etwas Hoffnung.

Mittlerweile habe ich die komplette Verkabelung neu gemacht, neue Dosen, neuer Verstärker etc. Ich dachte immer es läge am Empfang, bis ich Betanova auf meine Sagem gespielt habe und verwundert über das plötzlich fehlerfreie Bild war.

Nun gut, ich habe mittlerweile den neuen Tunertreiber aus dem RAR Archiv TP-Testreihe bei mir eingebunden. Leider stellt es sich direkt so dar, dass kein QAM256 Modulierter Transponder mehr empfangen werden kann, die beiden betreffenden Transponder liegen bei mir auf 113 sowie 121 Mhz, also die typischen Problemfrequenzen.

@Homer, wenn ich für dich irgendwas Debugen kann/soll, dann einfach bescheid geben.
Sagem Kabel 2xI Avia 600 Enx
Sagem Sat 1xI Avia 600 Enx
bellum
bbs-Maintainer
Beiträge: 282
Registriert: Montag 23. Oktober 2006, 22:13

Beitrag von bellum »

Homar hat geschrieben:Hi Folks,

durch einen dummen Fehler habe ich mir die Daten auf meinem Server gelöscht, sodass ich neu installieren musste...

Die Testreihe ist wieder online und es ist nichts aufgegeben worden :-)

Der Treiber funktioniert bei mir gut. Leider war die Resonanz bescheiden, sodass mir zur Zeit die Hände gebunden sind.

In das CVS kann sowas nicht landen, weil es nicht auf allen Boxen gleich gut funktioniert.

@Joker2k1:
Ich schaue mir die Register mal an, thx für deine Mühe.
Vielleicht ergibt sich ja was daraus :wink:
Hallo Homar,
wie ist denn der aktuelle Stand beim Treiber. Ich hatte in den letzten Wochen leider keine Zeit zu testen, aber jetzt sieht es wieder besser aus...
Mein letzter Stand ist, dass ich vor einiger Zeit auch Probleme mit 466 MHz hatte, die ich derzeit aber nicht reproduzieren kann.
Reproduzierbar ist aber ein Fehler auf 113 MHz. Das Bild bleibt ca. 1x pro Stunde stehen und der Ton läuft teilweise weiter.
Diesen Fehler habe ich aber auch mit den Treibern von AudioSlyer. Ein spielen mit den Registern hat leider nichts geholfen.
Wenn ich also noch etwas testen kann/soll...

Gruß bellum
ingrid
Erleuchteter
Erleuchteter
Beiträge: 600
Registriert: Samstag 14. Oktober 2006, 10:53

Beitrag von ingrid »

Ich hol die Frage nochmal nach oben...
ingrid hat geschrieben:Bzgl. der XLS-Liste: Benötigst Du die BER/SNR-Werte mit den Default-Werten des Testtreibers oder sollte ich vorher die besten Registerkombis ausknobeln? Mit den Default-Werten könnte ich Dir die Liste im Prinzip noch heute oder morgen schicken. Mit optimierten Werten würde es halt noch ein wenig dauern.
Das gleiche gilt für die Dumps: Mit default oder optimierten Werten?
Werden die Listen überhaupt noch gebraucht? Homar scheint momentan nicht viel Zeit für den Treiber zu haben, oder?

Hat jemand evtl. ein Diff der Änderungen?
deepblue2000
Interessierter
Interessierter
Beiträge: 21
Registriert: Sonntag 5. Oktober 2003, 21:33

Beitrag von deepblue2000 »

es gab doch schon v9 final treiber von audioslyer und v10.

möchte die denn keiner bitte mal zum download freigeben ?

weil mit dem ganzen "fach-chinesisch" kann ich einfach nix anfangen.



mfg
ingrid
Erleuchteter
Erleuchteter
Beiträge: 600
Registriert: Samstag 14. Oktober 2006, 10:53

Beitrag von ingrid »

@Homar: Da ich inzwischen 'nen 2.4.35er Kernel auf meiner Box habe, kann ich Deinen Treiber nicht mehr laden (kernel-module mismatch). Könntest Du bitte die Sources als Diff gegen das aktuelle CVS zur Verfügung stellen? Dann könnte ich noch einmal schauen, wie sich's auf meinen Boxen verhält und was ich hier so tunen kann.

Wäre wirklich schade, wenn's so langsam nun doch im Sande verläuft.
UEning
Einsteiger
Einsteiger
Beiträge: 152
Registriert: Montag 6. September 2004, 18:18

Beitrag von UEning »

ingrid hat geschrieben:@Homar: Da ich inzwischen 'nen 2.4.35er Kernel auf meiner Box habe, kann ich Deinen Treiber nicht mehr laden (kernel-module mismatch).

Hilft da kein insmod -f vesxxxx.o ?
denis4er
Interessierter
Interessierter
Beiträge: 43
Registriert: Mittwoch 21. Dezember 2005, 11:13

Beitrag von denis4er »

deepblue2000 hat geschrieben:es gab doch schon v9 final treiber von audioslyer und v10.
wo kann man diese Treiber runterladen und testen?

MfG
bellum
bbs-Maintainer
Beiträge: 282
Registriert: Montag 23. Oktober 2006, 22:13

Beitrag von bellum »

So jetzt haben wir den Salat...

Der 2.4.35er Kernel ist im CVS und der optimierte at76c651.o sowohl von AudioSlyer als auch von Homar wird erst einmal nicht mehr vom aktuellen Kernel geladen. Man bekommt das zwar mit insmod -f at76c651 hin aber zu einen ist das doch irgendwie nicht Sinn der Sache zum anderen verhält sich mein sectionsd bei dieser Konstellation instabil (kein EPG).

Ich möchte aus diesem Anlass das ganze noch einmal hochschieben und die Beteiligten bitten, den jetzigen Stand als diff zu veröffentlichen. Ich benutze z.B. AudioSlyers V8u und bin damit sehr zufrieden. Aber deswegen kann ich erst einmal nicht auf einen aktuelle CVS-Stand wechseln...

@AudioSlyer, könntest Du Dir nicht doch einmal einen Ruck geben und die V8u (oder noch besser die V9 ;-) ) veröffentlichen? Ich weiß Du hast Dich in der Vergangenheit über manche Leute geärgert aber wenn du ein diff postest müstest Du auch keinen Support leisten, denn die Leute die mit einem diff etwas Anfangen können bekommen das auch in ein Image eingebaut. Ich würde das ganze auch kompilieren und es findet sich sicher jemand der das Modul irgendwo hostet...

@Homar, wie ist denn bei Dir der aktuelle Stand?

In diesem Sinne

Gruß bellum
bellum
bbs-Maintainer
Beiträge: 282
Registriert: Montag 23. Oktober 2006, 22:13

Beitrag von bellum »

Hallo zusammen,

PandinusImperator hat mir einen Link für einen at76c651.o für den Kernel 2.4.35 geschickt ( http://www.file-upload.net/download-464 ... 651.o.html ) den CarstenW praktischerweise auch gleich nach http://ulc.tuxbox-cvs.sourceforge.net/i ... y=Binaries hochgeladen hat...

Na dann ran ans testen, vielleicht gibt es nach entsprechendem Feedback den Quellcode der es dann endlich ins CVS schafft...

Gruß bellum
PandinusImperator
Interessierter
Interessierter
Beiträge: 32
Registriert: Dienstag 23. Oktober 2007, 09:26

Beitrag von PandinusImperator »

sind für den kernel im cvs
bellum
bbs-Maintainer
Beiträge: 282
Registriert: Montag 23. Oktober 2006, 22:13

Beitrag von bellum »

PandinusImperator hat geschrieben:sind für den kernel im cvs
So, habe Deinen Treiber mit einem aktuellen YADD getestet. Der Treiber wird geladen und die QAM 64 Sender sind soweit O.K., bei den QAM habe ich aber sehr hohe BER 200000-300000...
Was meinst Du eigentlich genau damit, dass der Quelltext schon im CVS ist? Ist dein Treiber für QAM 256 optimiert?

Gruß bellum
happyerazor
Beiträge: 1
Registriert: Freitag 12. Oktober 2007, 18:54

Beitrag von happyerazor »

Hallo
@bellum
um welche Version handelt es sich bei dem von dir genannten Link zum Treiber für 2.4.35?
Ist das der V8?

Ich hab jedenfalls keine unterschiede in den BER und SIG raten feststellen können, was beim V8 anderst war.

MfG
Happy
NoX1911
Interessierter
Interessierter
Beiträge: 50
Registriert: Montag 16. Februar 2004, 16:13

Beitrag von NoX1911 »

Die BER Werte sind bei mir auch hoch, denen schenke ich aber nicht all zu viel Aufmerksamkeit, da sämtliche Programme astrein laufen. Bei den UltimoBER V8 wurde auch schon mal angedeutet, dass die BER Werte u.U. utopisch seien, bzw. nicht der Wahrheit entsprächen.

Ich hatte die UltimoBER V8 auch getestet (mit insmod -f) und das Gefühl die liefen nicht so gut wie der von PandinusImperator (oder wer hat den letzten erstellt?).
bellum
bbs-Maintainer
Beiträge: 282
Registriert: Montag 23. Oktober 2006, 22:13

Beitrag von bellum »

happyerazor hat geschrieben:Hallo
@bellum
um welche Version handelt es sich bei dem von dir genannten Link zum Treiber für 2.4.35?
Ist das der V8?
Welche Version das ist kann ich Dir nicht sagen, ich habe den Link damals von PandinusImperator bekommen und gehe davon aus, dass er den Treiber erstellt hat.
Jedenfalls ist es nicht nicht der V8, da dieser von AudioSlyer für den Kernel 2.4.34 erstellt wurde und wesentlich besser bei QAM 256 Sendern ist mit denen der Treiber von PandinusImperator leider Probleme hat (habe es gerade noch einmal gegengecheckt).

Gruß bellum
NoX1911
Interessierter
Interessierter
Beiträge: 50
Registriert: Montag 16. Februar 2004, 16:13

Beitrag von NoX1911 »

Ich habe bei mir gegenteiliges beobachtet. Der neue Treiber scheint besser zu laufen. Sowohl 658MHz (Souvenirs from the earth), 650MHz (MTV Hits), die 450MHz (Kino) sowie 121Mhz und 113Mhz. Die Box liegt an einer -15db Dose und wurde mit regelbarem Dämpfungsregler feinoptimiert. Absolut keine Schieflage mehr, man muss die unteren Frequenzen (113Mhz) nicht mehr manuell "nachdämpfen" und die oberen haben noch genug Saft, damit keine Ruckler entstehen.
Der Sweet Spot ist sehr schmal, das gebe ich zu. Ohne Dämpfungsregler müsste ich das am Hausverstärker machen. Das Signal muss sehr gut sein.

Welche Sender betrifft das bei dir genau?
AudioSlyer
Erleuchteter
Erleuchteter
Beiträge: 450
Registriert: Sonntag 28. Juli 2002, 01:18

Re: AT76C651

Beitrag von AudioSlyer »

Wollte mal testen, ob man hier viel Code posten kann ;)

Code: Alles auswählen

/*
 * at76c651.c
 *
 * Atmel DVB-C Frontend Driver (at76c651/tua6010xs)
 *
 * Copyright (C) 2001 fnbrd <fnbrd@gmx.de>
 *             & 2002-2004 Andreas Oberritter <obi@linuxtv.org>
 *             & 2003 Wolfram Joost <dbox2@frokaschwei.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * AT76C651
 * http://www.nalanda.nitc.ac.in/industry/datasheets/atmel/acrobat/doc1293.pdf
 * http://www.atmel.com/atmel/acrobat/doc1320.pdf
 *
 * TUA6010XS
 * http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=19512
 *
 */

#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/slab.h>

#if defined(__powerpc__)
#include <asm/bitops.h>
#endif

#include "dvb_frontend.h"
#include "dvb_i2c.h"
#include "dvb_functions.h"

static int debug = 0;
static u8 at76c651_qam;
static u8 at76c651_revision;

#define dprintk	if (debug) printk

// #define AT76C651_PROC_INTERFACE

#ifdef AT76C651_PROC_INTERFACE
#include <linux/proc_fs.h>
static unsigned char at76c651_proc_registered = 0;
#endif

static struct dvb_frontend_info at76c651_info = {
	.name = "Atmel AT76C651B with TUA6010XS",
	.type = FE_QAM,
	.frequency_min = 48250000,
	.frequency_max = 863250000,
	.frequency_stepsize = 62500,
	/*.frequency_tolerance = */	/* FIXME: 12% of SR */
	.symbol_rate_min = 0,		/* FIXME */
	.symbol_rate_max = 9360000,	/* FIXME */
	.symbol_rate_tolerance = 4000,
	.caps = FE_CAN_INVERSION_AUTO |
		    FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
		    FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 |
		    FE_CAN_FEC_7_8 | FE_CAN_FEC_8_9 | FE_CAN_FEC_AUTO |
		    FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 |
		    FE_CAN_MUTE_TS | FE_CAN_QAM_256 | FE_CAN_RECOVER
};

#if ! defined(__powerpc__)
static __inline__ int __ilog2(unsigned long x)
{
	int i;

	if (x == 0)
		return -1;

	for (i = 0; x != 0; i++)
		x >>= 1;

	return i - 1;
}
#endif

static int at76c651_writereg(struct dvb_i2c_bus *i2c, u8 reg, u8 data)
{
	int ret;
	u8 buf[] = { reg, data };
	struct i2c_msg msg =
		{ .addr = 0x1a >> 1, .flags = 0, .buf = buf, .len = 2 };

	ret = i2c->xfer(i2c, &msg, 1);

	if (ret != 1)
		dprintk("%s: writereg error "
			"(reg == 0x%02x, val == 0x%02x, ret == %i)\n",
			__FUNCTION__, reg, data, ret);

	dvb_delay(10);

	return (ret != 1) ? -EREMOTEIO : 0;
}

static u8 at76c651_readreg(struct dvb_i2c_bus *i2c, u8 reg)
{
	int ret;
	u8 val;
	struct i2c_msg msg[] = {
		{ .addr = 0x1a >> 1, .flags = 0, .buf = &reg, .len = 1 },
		{ .addr = 0x1a >> 1, .flags = I2C_M_RD, .buf = &val, .len = 1 }
	};

	ret = i2c->xfer(i2c, msg, 2);

	if (ret != 2)
		dprintk("%s: readreg error (ret == %i)\n", __FUNCTION__, ret);

	return val;
}

static int at76c651_reset(struct dvb_i2c_bus *i2c)
{
	return at76c651_writereg(i2c, 0x07, 0x01);
}

static void at76c651_disable_interrupts(struct dvb_i2c_bus *i2c)
{
	at76c651_writereg(i2c, 0x0b, 0x00);
}

static int at76c651_set_auto_config(struct dvb_i2c_bus *i2c)
{
	/*
	 * Autoconfig
	 */
	at76c651_writereg(i2c, 0x06, 0x01);
	at76c651_writereg(i2c, 0x30, 0x94);
	
	at76c651_writereg(i2c, 0x31, 0x8A); //0.01 02.0 0x8A 0x9C
	at76c651_writereg(i2c, 0x32, 0x9C); //0.01 02.0 0x8A 0x9C
	at76c651_writereg(i2c, 0x33, 0x8A); 
	at76c651_writereg(i2c, 0x34, 0x9C); 
	

	/*
	 * Performance optimizations, should be done after autoconfig
	 */
	at76c651_writereg(i2c, 0x10, 0x06);
	at76c651_writereg(i2c, 0x11, ((at76c651_qam == 5) || (at76c651_qam == 7)) ? 0x12 : 0x10);
	at76c651_writereg(i2c, 0x15, 0x28);
	at76c651_writereg(i2c, 0x20, 0x09);
	at76c651_writereg(i2c, 0x24, ((at76c651_qam == 5) || (at76c651_qam == 7)) ? 0xC0 : 0x90);
	at76c651_writereg(i2c, 0x30, 0x90);
	if (at76c651_qam == 5)
		at76c651_writereg(i2c, 0x35, 0x2A);

	/*
	 * Initialize A/D-converter
	 */
	if (at76c651_revision == 0x11) {
		at76c651_writereg(i2c, 0x2E, 0x38);
		at76c651_writereg(i2c, 0x2F, 0x13);
	}

	at76c651_disable_interrupts(i2c);

	/*
	 * Restart operation
	 */
	at76c651_reset(i2c);

	return 0;
}

static void at76c651_set_bbfreq(struct dvb_i2c_bus *i2c)
{
	at76c651_writereg(i2c, 0x04, 0x3f);
	at76c651_writereg(i2c, 0x05, 0xee);
}

static int at76c651_pll_write(struct dvb_i2c_bus *i2c, u8 *buf, size_t len)
{
	int ret;
	struct i2c_msg msg =
		{ .addr = 0xc2 >> 1, .flags = 0, .buf = buf, .len = len };

	at76c651_writereg(i2c, 0x0c, 0xc3);

	ret = i2c->xfer(i2c, &msg, 1);

	at76c651_writereg(i2c, 0x0c, 0xc2);

	return (ret != 1) ? -EREMOTEIO : 0;
}

static int tua6010_setfreq(struct dvb_i2c_bus *i2c, u32 freq)
{
	u32 div;
	u8 buf[4];
	u8 vu, p2, p1, p0;

	/* 47 MHz ... 862 MHz */
	if ((freq < 47000000) || (freq > 862000000))
		return -EINVAL;

	div = (freq + 36118750 + 31250) / 62500;

	if (freq > 401250000)
		vu = 1;	/* UHF */
	else
		vu = 0; /* VHF */

	if (freq > 401250000)
		p2 = 1, p1 = 0, p0 = 1;
	else if (freq > 117250000)
		p2 = 1, p1 = 1, p0 = 0;
	else
		p2 = 0, p1 = 1, p0 = 1;

	buf[0] = (div >> 8) & 0x7f;
	buf[1] = (div >> 0) & 0xff;
	buf[2] = 0x8e;
	buf[3] = (vu << 7) | (p2 << 2) | (p1 << 1) | p0;

	return at76c651_pll_write(i2c, buf, 4);
}

static int at76c651_set_symbol_rate(struct dvb_i2c_bus *i2c, u32 symbol_rate)
{
	u8 exponent;
	u32 mantissa;

	if (symbol_rate > 9360000)
		return -EINVAL;

	/*
	 * FREF = 57800 kHz
	 * exponent = 10 + floor (log2(symbol_rate / FREF))
	 * mantissa = (symbol_rate / FREF) * (1 << (30 - exponent))
	 */

	exponent = __ilog2((symbol_rate << 4) / 903125);
	mantissa = ((symbol_rate / 3125) * (1 << (24 - exponent))) / 289;

	at76c651_writereg(i2c, 0x00, mantissa >> 13);
	at76c651_writereg(i2c, 0x01, mantissa >> 5);
	at76c651_writereg(i2c, 0x02, (mantissa << 3) | exponent);

	return 0;
}

static int at76c651_set_qam(struct dvb_i2c_bus *i2c, fe_modulation_t qam)
{
	switch (qam) {
	case QPSK:
		at76c651_qam = 0x02;
		break;
	case QAM_16:
		at76c651_qam = 0x04;
		break;
	case QAM_32:
		at76c651_qam = 0x05;
		break;
	case QAM_64:
		at76c651_qam = 0x06;
		break;
	case QAM_128:
		at76c651_qam = 0x07;
		break;
	case QAM_256:
		at76c651_qam = 0x08;
		break;
#if 0
	case QAM_512:
		at76c651_qam = 0x09;
		break;
	case QAM_1024:
		at76c651_qam = 0x0A;
		break;
#endif
	default:
		return -EINVAL;
	}

	return at76c651_writereg(i2c, 0x03, at76c651_qam);
}

static int at76c651_set_inversion(struct dvb_i2c_bus *i2c,
		       fe_spectral_inversion_t inversion)
{
	u8 feciqinv = at76c651_readreg(i2c, 0x60);

	switch (inversion) {
	case INVERSION_OFF:
		feciqinv |= 0x02;
		feciqinv &= 0xFE;
		break;

	case INVERSION_ON:
		feciqinv |= 0x03;
		break;

	case INVERSION_AUTO:
		feciqinv &= 0xFC;
		break;

	default:
		return -EINVAL;
	}

	return at76c651_writereg(i2c, 0x60, feciqinv);
}

static int at76c651_set_parameters(struct dvb_i2c_bus *i2c,
			struct dvb_frontend_parameters *p)
{
	int ret;

	if ((ret = tua6010_setfreq(i2c, p->frequency)))
		return ret;

	if ((ret = at76c651_set_symbol_rate(i2c, p->u.qam.symbol_rate)))
		return ret;

	if ((ret = at76c651_set_qam(i2c, p->u.qam.modulation)))
		return ret;

	if ((ret = at76c651_set_inversion(i2c, p->inversion)))
		return ret;

	return at76c651_set_auto_config(i2c);
}

static int at76c651_set_defaults(struct dvb_i2c_bus *i2c)
{
	at76c651_set_symbol_rate(i2c, 6900000);
	at76c651_set_qam(i2c, QAM_64);
	at76c651_set_bbfreq(i2c);
	at76c651_set_auto_config(i2c);

	return 0;
}

static int at76c651_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
{

	switch (cmd) {
	case FE_GET_INFO:
		memcpy(arg, &at76c651_info, sizeof(struct dvb_frontend_info));
		break;

	case FE_READ_STATUS:
	{
		fe_status_t *status = arg;
		u8 sync;

		/*
		 * Bits: FEC, CAR, EQU, TIM, AGC2, AGC1, ADC, PLL (PLL=0) 
		 */
		sync = at76c651_readreg(fe->i2c, 0x80);

		*status = 0;

		if (sync & (0x04 | 0x10))	/* AGC1 || TIM */
			*status |= FE_HAS_SIGNAL;

		if (sync & 0x10)	/* TIM */
			*status |= FE_HAS_CARRIER;

		if (sync & 0x80)	/* FEC */
			*status |= FE_HAS_VITERBI;

		if (sync & 0x40)	/* CAR */
			*status |= FE_HAS_SYNC;

		if ((sync & 0xF0) == 0xF0)	/* TIM && EQU && CAR && FEC */
			*status |= FE_HAS_LOCK;

		break;
	}

	case FE_READ_BER:
	{
		u32 ber = at76c651_readreg(fe->i2c, 0x83) |
				(at76c651_readreg(fe->i2c, 0x82) << 8) |
		 		((at76c651_readreg(fe->i2c, 0x81) & 0x0f) << 16);
				*((u32*) arg) = ber;
		break;
	}

	case FE_READ_SIGNAL_STRENGTH:
	{
		u8 gain = at76c651_readreg(fe->i2c, 0x91);
		*((u16 *)arg) = (gain << 8) | gain;
		break;
	}

	case FE_READ_SNR:
		*(u16 *)arg = 0xFFFF -
		    ((at76c651_readreg(fe->i2c, 0x8F) << 8) |
		     at76c651_readreg(fe->i2c, 0x90));
		break;

	case FE_READ_UNCORRECTED_BLOCKS:
		*(u32 *)arg = at76c651_readreg(fe->i2c, 0x82);
		break;

	case FE_SET_FRONTEND:
		return at76c651_set_parameters(fe->i2c, arg);

	case FE_GET_FRONTEND:
		break;

	case FE_SLEEP:
		break;

	case FE_INIT:
		return at76c651_set_defaults(fe->i2c);

	case FE_RESET:
		return at76c651_reset(fe->i2c);

	default:
		return -ENOIOCTLCMD;
	}

	return 0;
}

#ifdef AT76C651_PROC_INTERFACE
static int at76c651_proc_read(char *buf, char **start, off_t offset, int len, int *eof, void *i2c)
{
	int nr;
	u8 val;
	int idx;
	u8 bit;
	u32 ber;

	const char *lockdescr[8] =
		{ "FEC", "CAR", "EQU", "TIM", "AGC2", "AGC1", "ADC", "PLL" };

	if (at76c651_revision == 0x10)
		nr = sprintf(buf, "Status of AT76C651A demodulator:\n");
	else
		nr = sprintf(buf, "Status of AT76C651B demodulator:\n");

	val = at76c651_readreg(i2c, 0x80);
	nr += sprintf(buf, "Lock (0x%02X): ", val);

	bit = 0x80;

	for (idx = 0; idx < 8; idx++) {
		if (val & bit)
			nr += sprintf(buf + nr, "%s ", lockdescr[idx]);
		bit >>= 1;
	}

	ber = ((at76c651_readreg(i2c, 0x81) & 0x0F) << 16) |
		(at76c651_readreg(i2c, 0x82) << 8) |
		at76c651_readreg(i2c, 0x83);

	val = at76c651_readreg(i2c, 0x85);

	nr += sprintf(buf + nr - 1, "\nRecoverable block error rate: %d\n"
			"Number of uncorrectable frames: %d\n", ber, val) - 1;

	nr += sprintf(buf + nr, "Number of A/D-converter-saturations: %d\n"
			"AGC1-Value: %d\n",
			at76c651_readreg(i2c, 0x19),
			at76c651_readreg(i2c, 0x91));

	if ((val = at76c651_readreg(i2c, 0x60)) & 0x02)
		nr += sprintf(buf + nr, "FEC: manual mode, %s\n",
				(val & 0x01) ? "inverse" : "normal");
	else
		nr += sprintf(buf + nr, "FEC: automatic mode, %s\n",
				(val & 0x04) ? "inverse" : "normal");

	return nr;
}

static int at76c651_register_proc(struct dvb_i2c_bus *i2c)
{
	struct proc_dir_entry *proc_bus_at76c651;

	if (!proc_bus)
		return -ENOENT;

	proc_bus_at76c651 = create_proc_read_entry("at76c651", 0, proc_bus,
			&at76c651_proc_read,i2c);

	if (!proc_bus_at76c651) {
		printk(KERN_ERR "Cannot create /proc/bus/at76c651\n");
		return -ENOENT;
	}

	at76c651_proc_registered = 1;

	proc_bus_at76c651->owner = THIS_MODULE;

	return 0;
}

static void at76c651_deregister_proc(void)
{
	if (at76c651_proc_registered)
		remove_proc_entry("at76c651",proc_bus);

	at76c651_proc_registered = 0;
}
#endif

static int at76c651_attach(struct dvb_i2c_bus *i2c, void **data)
{
	if (at76c651_readreg(i2c, 0x0E) != 0x65)
		return -ENODEV;

	at76c651_revision = at76c651_readreg(i2c, 0x0F);

	switch (at76c651_revision) {
	case 0x10:
		at76c651_info.name[14] = 'A';
		break;
	case 0x11:
		at76c651_info.name[14] = 'B';
		break;
	default:
		return -ENODEV;
	}

	at76c651_set_defaults(i2c);

#ifdef AT76C651_PROC_INTERFACE
	at76c651_register_proc(i2c);
#endif

	return dvb_register_frontend(at76c651_ioctl, i2c, NULL, &at76c651_info);
}

static void at76c651_detach(struct dvb_i2c_bus *i2c, void *data)
{
#ifdef AT76C651_PROC_INTERFACE
	at76c651_deregister_proc();
#endif

	dvb_unregister_frontend(at76c651_ioctl, i2c);
}

static int __init at76c651_init(void)
{
	return dvb_register_i2c_device(THIS_MODULE,
			at76c651_attach, at76c651_detach);
}

static void __exit at76c651_exit(void)
{
	dvb_unregister_i2c_device(at76c651_attach);
}

module_init(at76c651_init);
module_exit(at76c651_exit);

MODULE_DESCRIPTION("at76c651/dat7021(tua6010xs) dvb-c frontend driver");
MODULE_AUTHOR("Andreas Oberritter <obi@linuxtv.org>");
MODULE_LICENSE("GPL");
MODULE_PARM(debug, "i");