brintos

brintos / linux-shallow public Read only

0
0
Text · 43.4 KiB · 69f5e81 Raw
1626 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * budget-av.ko: driver for the SAA7146 based Budget DVB cards4 *               with analog video input (and optionally with CI)5 *6 * Compiled from various sources by Michael Hunold <michael@mihu.de>7 *8 * CI interface support (c) 2004 Olivier Gournet <ogournet@anevia.com> &9 *                               Andrew de Quincey <adq_dvb@lidskialf.net>10 *11 * Copyright (C) 2002 Ralph Metzler <rjkm@metzlerbros.de>12 *13 * Copyright (C) 1999-2002 Ralph  Metzler14 *                       & Marcus Metzler for convergence integrated media GmbH15 *16 * the project's page is at https://linuxtv.org17 */18 19 20#include "budget.h"21#include "stv0299.h"22#include "stb0899_drv.h"23#include "stb0899_reg.h"24#include "stb0899_cfg.h"25#include "tda8261.h"26#include "tda8261_cfg.h"27#include "tda1002x.h"28#include "tda1004x.h"29#include "tua6100.h"30#include "dvb-pll.h"31#include <media/drv-intf/saa7146_vv.h>32#include <linux/module.h>33#include <linux/etherdevice.h>34#include <linux/errno.h>35#include <linux/slab.h>36#include <linux/interrupt.h>37#include <linux/input.h>38#include <linux/spinlock.h>39#include <linux/workqueue.h>40 41#include <media/dvb_ca_en50221.h>42 43#define DEBICICAM		0x0242000044 45#define SLOTSTATUS_NONE         146#define SLOTSTATUS_PRESENT      247#define SLOTSTATUS_RESET        448#define SLOTSTATUS_READY        849#define SLOTSTATUS_OCCUPIED     (SLOTSTATUS_PRESENT|SLOTSTATUS_RESET|SLOTSTATUS_READY)50 51DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);52 53struct budget_av {54	struct budget budget;55	struct video_device vd;56	int cur_input;57	int has_saa7113;58	struct work_struct ciintf_irq_bh_work;59	int slot_status;60	struct dvb_ca_en50221 ca;61	u8 reinitialise_demod:1;62};63 64static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot);65 66/*67 * GPIO Connections:68 * 0 - Vcc/Reset (Reset is controlled by capacitor). Resets the frontend *AS WELL*!69 * 1 - CI memory select 0=>IO memory, 1=>Attribute Memory70 * 2 - CI Card Enable (Active Low)71 * 3 - CI Card Detect72 */73 74/****************************************************************************75 * INITIALIZATION76 ****************************************************************************/77 78static u8 i2c_readreg(struct i2c_adapter *i2c, u8 id, u8 reg)79{80	u8 mm1[] = { 0x00 };81	u8 mm2[] = { 0x00 };82	struct i2c_msg msgs[2];83 84	msgs[0].flags = 0;85	msgs[1].flags = I2C_M_RD;86	msgs[0].addr = msgs[1].addr = id / 2;87	mm1[0] = reg;88	msgs[0].len = 1;89	msgs[1].len = 1;90	msgs[0].buf = mm1;91	msgs[1].buf = mm2;92 93	i2c_transfer(i2c, msgs, 2);94 95	return mm2[0];96}97 98static int i2c_readregs(struct i2c_adapter *i2c, u8 id, u8 reg, u8 *buf, u8 len)99{100	u8 mm1[] = { reg };101	struct i2c_msg msgs[2] = {102		{.addr = id / 2, .flags = 0, .buf = mm1, .len = 1},103		{.addr = id / 2, .flags = I2C_M_RD, .buf = buf, .len = len}104	};105 106	if (i2c_transfer(i2c, msgs, 2) != 2)107		return -EIO;108 109	return 0;110}111 112static int i2c_writereg(struct i2c_adapter *i2c, u8 id, u8 reg, u8 val)113{114	u8 msg[2] = { reg, val };115	struct i2c_msg msgs;116 117	msgs.flags = 0;118	msgs.addr = id / 2;119	msgs.len = 2;120	msgs.buf = msg;121	return i2c_transfer(i2c, &msgs, 1);122}123 124static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)125{126	struct budget_av *budget_av = ca->data;127	int result;128 129	if (slot != 0)130		return -EINVAL;131 132	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);133	udelay(1);134 135	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 0xfff, 1, 0, 1);136	if (result == -ETIMEDOUT) {137		ciintf_slot_shutdown(ca, slot);138		pr_info("cam ejected 1\n");139	}140	return result;141}142 143static int ciintf_write_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address, u8 value)144{145	struct budget_av *budget_av = ca->data;146	int result;147 148	if (slot != 0)149		return -EINVAL;150 151	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTHI);152	udelay(1);153 154	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 0xfff, 1, value, 0, 1);155	if (result == -ETIMEDOUT) {156		ciintf_slot_shutdown(ca, slot);157		pr_info("cam ejected 2\n");158	}159	return result;160}161 162static int ciintf_read_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address)163{164	struct budget_av *budget_av = ca->data;165	int result;166 167	if (slot != 0)168		return -EINVAL;169 170	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);171	udelay(1);172 173	result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, address & 3, 1, 0, 0);174	if (result == -ETIMEDOUT) {175		ciintf_slot_shutdown(ca, slot);176		pr_info("cam ejected 3\n");177		return -ETIMEDOUT;178	}179	return result;180}181 182static int ciintf_write_cam_control(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value)183{184	struct budget_av *budget_av = ca->data;185	int result;186 187	if (slot != 0)188		return -EINVAL;189 190	saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);191	udelay(1);192 193	result = ttpci_budget_debiwrite(&budget_av->budget, DEBICICAM, address & 3, 1, value, 0, 0);194	if (result == -ETIMEDOUT) {195		ciintf_slot_shutdown(ca, slot);196		pr_info("cam ejected 5\n");197	}198	return result;199}200 201static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot)202{203	struct budget_av *budget_av = ca->data;204	struct saa7146_dev *saa = budget_av->budget.dev;205 206	if (slot != 0)207		return -EINVAL;208 209	dprintk(1, "ci slot reset\n");210	budget_av->slot_status = SLOTSTATUS_RESET;211 212	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTHI); /* disable card */213 214	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI); /* Vcc off */215	msleep(2);216	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO); /* Vcc on */217	msleep(20); /* 20 ms Vcc settling time */218 219	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO); /* enable card */220	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);221	msleep(20);222 223	/* reinitialise the frontend if necessary */224	if (budget_av->reinitialise_demod)225		dvb_frontend_reinitialise(budget_av->budget.dvb_frontend);226 227	return 0;228}229 230static int ciintf_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)231{232	struct budget_av *budget_av = ca->data;233	struct saa7146_dev *saa = budget_av->budget.dev;234 235	if (slot != 0)236		return -EINVAL;237 238	dprintk(1, "ci slot shutdown\n");239 240	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTB);241	budget_av->slot_status = SLOTSTATUS_NONE;242 243	return 0;244}245 246static int ciintf_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)247{248	struct budget_av *budget_av = ca->data;249	struct saa7146_dev *saa = budget_av->budget.dev;250 251	if (slot != 0)252		return -EINVAL;253 254	dprintk(1, "ci slot status: %d\n", budget_av->slot_status);255 256	ttpci_budget_set_video_port(saa, BUDGET_VIDEO_PORTA);257 258	return 0;259}260 261static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)262{263	struct budget_av *budget_av = ca->data;264	struct saa7146_dev *saa = budget_av->budget.dev;265	int result;266 267	if (slot != 0)268		return -EINVAL;269 270	/*271	 * test the card detect line - needs to be done carefully272	 * since it never goes high for some CAMs on this interface (e.g. topuptv)273	 */274	if (budget_av->slot_status == SLOTSTATUS_NONE) {275		saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);276		udelay(1);277		if (saa7146_read(saa, PSR) & MASK_06) {278			if (budget_av->slot_status == SLOTSTATUS_NONE) {279				budget_av->slot_status = SLOTSTATUS_PRESENT;280				pr_info("cam inserted A\n");281			}282		}283		saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);284	}285 286	/*287	 * We also try and read from IO memory to work round the above detection bug. If288	 * there is no CAM, we will get a timeout. Only done if there is no cam289	 * present, since this test actually breaks some cams :(290	 *291	 * if the CI interface is not open, we also do the above test since we292	 * don't care if the cam has problems - we'll be resetting it on open() anyway293	 */294	if ((budget_av->slot_status == SLOTSTATUS_NONE) || (!open)) {295		saa7146_setgpio(budget_av->budget.dev, 1, SAA7146_GPIO_OUTLO);296		result = ttpci_budget_debiread(&budget_av->budget, DEBICICAM, 0, 1, 0, 1);297		if ((result >= 0) && (budget_av->slot_status == SLOTSTATUS_NONE)) {298			budget_av->slot_status = SLOTSTATUS_PRESENT;299			pr_info("cam inserted B\n");300		} else if (result < 0) {301			if (budget_av->slot_status != SLOTSTATUS_NONE) {302				ciintf_slot_shutdown(ca, slot);303				pr_info("cam ejected 5\n");304				return 0;305			}306		}307	}308 309	/* read from attribute memory in reset/ready state to know when the CAM is ready */310	if (budget_av->slot_status == SLOTSTATUS_RESET) {311		result = ciintf_read_attribute_mem(ca, slot, 0);312		if (result == 0x1d)313			budget_av->slot_status = SLOTSTATUS_READY;314	}315 316	/* work out correct return code */317	if (budget_av->slot_status != SLOTSTATUS_NONE) {318		if (budget_av->slot_status & SLOTSTATUS_READY)319			return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY;320		return DVB_CA_EN50221_POLL_CAM_PRESENT;321	}322	return 0;323}324 325static int ciintf_init(struct budget_av *budget_av)326{327	struct saa7146_dev *saa = budget_av->budget.dev;328	int result;329 330	memset(&budget_av->ca, 0, sizeof(struct dvb_ca_en50221));331 332	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);333	saa7146_setgpio(saa, 1, SAA7146_GPIO_OUTLO);334	saa7146_setgpio(saa, 2, SAA7146_GPIO_OUTLO);335	saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTLO);336 337	/* Enable DEBI pins */338	saa7146_write(saa, MC1, MASK_27 | MASK_11);339 340	/* register CI interface */341	budget_av->ca.owner = THIS_MODULE;342	budget_av->ca.read_attribute_mem = ciintf_read_attribute_mem;343	budget_av->ca.write_attribute_mem = ciintf_write_attribute_mem;344	budget_av->ca.read_cam_control = ciintf_read_cam_control;345	budget_av->ca.write_cam_control = ciintf_write_cam_control;346	budget_av->ca.slot_reset = ciintf_slot_reset;347	budget_av->ca.slot_shutdown = ciintf_slot_shutdown;348	budget_av->ca.slot_ts_enable = ciintf_slot_ts_enable;349	budget_av->ca.poll_slot_status = ciintf_poll_slot_status;350	budget_av->ca.data = budget_av;351	budget_av->budget.ci_present = 1;352	budget_av->slot_status = SLOTSTATUS_NONE;353 354	result = dvb_ca_en50221_init(&budget_av->budget.dvb_adapter,355				     &budget_av->ca, 0, 1);356	if (result != 0) {357		pr_err("ci initialisation failed\n");358		goto error;359	}360 361	pr_info("ci interface initialised\n");362	return 0;363 364error:365	saa7146_write(saa, MC1, MASK_27);366	return result;367}368 369static void ciintf_deinit(struct budget_av *budget_av)370{371	struct saa7146_dev *saa = budget_av->budget.dev;372 373	saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT);374	saa7146_setgpio(saa, 1, SAA7146_GPIO_INPUT);375	saa7146_setgpio(saa, 2, SAA7146_GPIO_INPUT);376	saa7146_setgpio(saa, 3, SAA7146_GPIO_INPUT);377 378	/* release the CA device */379	dvb_ca_en50221_release(&budget_av->ca);380 381	/* disable DEBI pins */382	saa7146_write(saa, MC1, MASK_27);383}384 385 386static const u8 saa7113_tab[] = {387	0x01, 0x08,388	0x02, 0xc0,389	0x03, 0x33,390	0x04, 0x00,391	0x05, 0x00,392	0x06, 0xeb,393	0x07, 0xe0,394	0x08, 0x28,395	0x09, 0x00,396	0x0a, 0x80,397	0x0b, 0x47,398	0x0c, 0x40,399	0x0d, 0x00,400	0x0e, 0x01,401	0x0f, 0x44,402 403	0x10, 0x08,404	0x11, 0x0c,405	0x12, 0x7b,406	0x13, 0x00,407	0x15, 0x00, 0x16, 0x00, 0x17, 0x00,408 409	0x57, 0xff,410	0x40, 0x82, 0x58, 0x00, 0x59, 0x54, 0x5a, 0x07,411	0x5b, 0x83, 0x5e, 0x00,412	0xff413};414 415static int saa7113_init(struct budget_av *budget_av)416{417	struct budget *budget = &budget_av->budget;418	struct saa7146_dev *saa = budget->dev;419	const u8 *data = saa7113_tab;420 421	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTHI);422	msleep(200);423 424	if (i2c_writereg(&budget->i2c_adap, 0x4a, 0x01, 0x08) != 1) {425		dprintk(1, "saa7113 not found on KNC card\n");426		return -ENODEV;427	}428 429	dprintk(1, "saa7113 detected and initializing\n");430 431	while (*data != 0xff) {432		i2c_writereg(&budget->i2c_adap, 0x4a, *data, *(data + 1));433		data += 2;434	}435 436	dprintk(1, "saa7113  status=%02x\n", i2c_readreg(&budget->i2c_adap, 0x4a, 0x1f));437 438	return 0;439}440 441static int saa7113_setinput(struct budget_av *budget_av, int input)442{443	struct budget *budget = &budget_av->budget;444 445	if (budget_av->has_saa7113 != 1)446		return -ENODEV;447 448	if (input == 1) {449		i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc7);450		i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x80);451	} else if (input == 0) {452		i2c_writereg(&budget->i2c_adap, 0x4a, 0x02, 0xc0);453		i2c_writereg(&budget->i2c_adap, 0x4a, 0x09, 0x00);454	} else {455		return -EINVAL;456	}457 458	budget_av->cur_input = input;459	return 0;460}461 462 463static int philips_su1278_ty_ci_set_symbol_rate(struct dvb_frontend *fe, u32 srate, u32 ratio)464{465	u8 aclk = 0;466	u8 bclk = 0;467	u8 m1;468 469	aclk = 0xb5;470	if (srate < 2000000)471		bclk = 0x86;472	else if (srate < 5000000)473		bclk = 0x89;474	else if (srate < 15000000)475		bclk = 0x8f;476	else if (srate < 45000000)477		bclk = 0x95;478 479	m1 = 0x14;480	if (srate < 4000000)481		m1 = 0x10;482 483	stv0299_writereg(fe, 0x13, aclk);484	stv0299_writereg(fe, 0x14, bclk);485	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);486	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);487	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);488	stv0299_writereg(fe, 0x0f, 0x80 | m1);489 490	return 0;491}492 493static int philips_su1278_ty_ci_tuner_set_params(struct dvb_frontend *fe)494{495	struct dtv_frontend_properties *c = &fe->dtv_property_cache;496	u32 div;497	u8 buf[4];498	struct budget *budget = fe->dvb->priv;499	struct i2c_msg msg = {.addr = 0x61, .flags = 0, .buf = buf, .len = sizeof(buf) };500 501	if ((c->frequency < 950000) || (c->frequency > 2150000))502		return -EINVAL;503 504	div = (c->frequency + (125 - 1)) / 125;	/* round correctly */505	buf[0] = (div >> 8) & 0x7f;506	buf[1] = div & 0xff;507	buf[2] = 0x80 | ((div & 0x18000) >> 10) | 4;508	buf[3] = 0x20;509 510	if (c->symbol_rate < 4000000)511		buf[3] |= 1;512 513	if (c->frequency < 1250000)514		buf[3] |= 0;515	else if (c->frequency < 1550000)516		buf[3] |= 0x40;517	else if (c->frequency < 2050000)518		buf[3] |= 0x80;519	else if (c->frequency < 2150000)520		buf[3] |= 0xC0;521 522	if (fe->ops.i2c_gate_ctrl)523		fe->ops.i2c_gate_ctrl(fe, 1);524	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)525		return -EIO;526	return 0;527}528 529static u8 typhoon_cinergy1200s_inittab[] = {530	0x01, 0x15,531	0x02, 0x30,532	0x03, 0x00,533	0x04, 0x7d,		/* F22FR = 0x7d, F22 = f_VCO / 128 / 0x7d = 22 kHz */534	0x05, 0x35,		/* I2CT = 0, SCLT = 1, SDAT = 1 */535	0x06, 0x40,		/* DAC not used, set to high impendance mode */536	0x07, 0x00,		/* DAC LSB */537	0x08, 0x40,		/* DiSEqC off */538	0x09, 0x00,		/* FIFO */539	0x0c, 0x51,		/* OP1 ctl = Normal, OP1 val = 1 (LNB Power ON) */540	0x0d, 0x82,		/* DC offset compensation = ON, beta_agc1 = 2 */541	0x0e, 0x23,		/* alpha_tmg = 2, beta_tmg = 3 */542	0x10, 0x3f,		// AGC2  0x3d543	0x11, 0x84,544	0x12, 0xb9,545	0x15, 0xc9,		// lock detector threshold546	0x16, 0x00,547	0x17, 0x00,548	0x18, 0x00,549	0x19, 0x00,550	0x1a, 0x00,551	0x1f, 0x50,552	0x20, 0x00,553	0x21, 0x00,554	0x22, 0x00,555	0x23, 0x00,556	0x28, 0x00,		// out imp: normal  out type: parallel FEC mode:0557	0x29, 0x1e,		// 1/2 threshold558	0x2a, 0x14,		// 2/3 threshold559	0x2b, 0x0f,		// 3/4 threshold560	0x2c, 0x09,		// 5/6 threshold561	0x2d, 0x05,		// 7/8 threshold562	0x2e, 0x01,563	0x31, 0x1f,		// test all FECs564	0x32, 0x19,		// viterbi and synchro search565	0x33, 0xfc,		// rs control566	0x34, 0x93,		// error control567	0x0f, 0x92,568	0xff, 0xff569};570 571static const struct stv0299_config typhoon_config = {572	.demod_address = 0x68,573	.inittab = typhoon_cinergy1200s_inittab,574	.mclk = 88000000UL,575	.invert = 0,576	.skip_reinit = 0,577	.lock_output = STV0299_LOCKOUTPUT_1,578	.volt13_op0_op1 = STV0299_VOLT13_OP0,579	.min_delay_ms = 100,580	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,581};582 583 584static const struct stv0299_config cinergy_1200s_config = {585	.demod_address = 0x68,586	.inittab = typhoon_cinergy1200s_inittab,587	.mclk = 88000000UL,588	.invert = 0,589	.skip_reinit = 0,590	.lock_output = STV0299_LOCKOUTPUT_0,591	.volt13_op0_op1 = STV0299_VOLT13_OP0,592	.min_delay_ms = 100,593	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,594};595 596static const struct stv0299_config cinergy_1200s_1894_0010_config = {597	.demod_address = 0x68,598	.inittab = typhoon_cinergy1200s_inittab,599	.mclk = 88000000UL,600	.invert = 1,601	.skip_reinit = 0,602	.lock_output = STV0299_LOCKOUTPUT_1,603	.volt13_op0_op1 = STV0299_VOLT13_OP0,604	.min_delay_ms = 100,605	.set_symbol_rate = philips_su1278_ty_ci_set_symbol_rate,606};607 608static int philips_cu1216_tuner_set_params(struct dvb_frontend *fe)609{610	struct dtv_frontend_properties *c = &fe->dtv_property_cache;611	struct budget *budget = fe->dvb->priv;612	u8 buf[6];613	struct i2c_msg msg = {.addr = 0x60, .flags = 0, .buf = buf, .len = sizeof(buf) };614	int i;615 616#define CU1216_IF 36125000617#define TUNER_MUL 62500618 619	u32 div = (c->frequency + CU1216_IF + TUNER_MUL / 2) / TUNER_MUL;620 621	buf[0] = (div >> 8) & 0x7f;622	buf[1] = div & 0xff;623	buf[2] = 0xce;624	buf[3] = (c->frequency < 150000000 ? 0x01 :625		  c->frequency < 445000000 ? 0x02 : 0x04);626	buf[4] = 0xde;627	buf[5] = 0x20;628 629	if (fe->ops.i2c_gate_ctrl)630		fe->ops.i2c_gate_ctrl(fe, 1);631	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)632		return -EIO;633 634	/* wait for the pll lock */635	msg.flags = I2C_M_RD;636	msg.len = 1;637	for (i = 0; i < 20; i++) {638		if (fe->ops.i2c_gate_ctrl)639			fe->ops.i2c_gate_ctrl(fe, 1);640		if (i2c_transfer(&budget->i2c_adap, &msg, 1) == 1 && (buf[0] & 0x40))641			break;642		msleep(10);643	}644 645	/* switch the charge pump to the lower current */646	msg.flags = 0;647	msg.len = 2;648	msg.buf = &buf[2];649	buf[2] &= ~0x40;650	if (fe->ops.i2c_gate_ctrl)651		fe->ops.i2c_gate_ctrl(fe, 1);652	if (i2c_transfer(&budget->i2c_adap, &msg, 1) != 1)653		return -EIO;654 655	return 0;656}657 658static struct tda1002x_config philips_cu1216_config = {659	.demod_address = 0x0c,660	.invert = 1,661};662 663static struct tda1002x_config philips_cu1216_config_altaddress = {664	.demod_address = 0x0d,665	.invert = 0,666};667 668static struct tda10023_config philips_cu1216_tda10023_config = {669	.demod_address = 0x0c,670	.invert = 1,671};672 673static int philips_tu1216_tuner_init(struct dvb_frontend *fe)674{675	struct budget *budget = fe->dvb->priv;676	static u8 tu1216_init[] = { 0x0b, 0xf5, 0x85, 0xab };677	struct i2c_msg tuner_msg = {.addr = 0x60, .flags = 0, .buf = tu1216_init, .len = sizeof(tu1216_init) };678 679	// setup PLL configuration680	if (fe->ops.i2c_gate_ctrl)681		fe->ops.i2c_gate_ctrl(fe, 1);682	if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)683		return -EIO;684	msleep(1);685 686	return 0;687}688 689static int philips_tu1216_tuner_set_params(struct dvb_frontend *fe)690{691	struct dtv_frontend_properties *c = &fe->dtv_property_cache;692	struct budget *budget = fe->dvb->priv;693	u8 tuner_buf[4];694	struct i2c_msg tuner_msg = {.addr = 0x60, .flags = 0, .buf = tuner_buf, .len =695			sizeof(tuner_buf) };696	int tuner_frequency = 0;697	u8 band, cp, filter;698 699	// determine charge pump700	tuner_frequency = c->frequency + 36166000;701	if (tuner_frequency < 87000000)702		return -EINVAL;703	else if (tuner_frequency < 130000000)704		cp = 3;705	else if (tuner_frequency < 160000000)706		cp = 5;707	else if (tuner_frequency < 200000000)708		cp = 6;709	else if (tuner_frequency < 290000000)710		cp = 3;711	else if (tuner_frequency < 420000000)712		cp = 5;713	else if (tuner_frequency < 480000000)714		cp = 6;715	else if (tuner_frequency < 620000000)716		cp = 3;717	else if (tuner_frequency < 830000000)718		cp = 5;719	else if (tuner_frequency < 895000000)720		cp = 7;721	else722		return -EINVAL;723 724	// determine band725	if (c->frequency < 49000000)726		return -EINVAL;727	else if (c->frequency < 161000000)728		band = 1;729	else if (c->frequency < 444000000)730		band = 2;731	else if (c->frequency < 861000000)732		band = 4;733	else734		return -EINVAL;735 736	// setup PLL filter737	switch (c->bandwidth_hz) {738	case 6000000:739		filter = 0;740		break;741 742	case 7000000:743		filter = 0;744		break;745 746	case 8000000:747		filter = 1;748		break;749 750	default:751		return -EINVAL;752	}753 754	// calculate divisor755	// ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)756	tuner_frequency = (((c->frequency / 1000) * 6) + 217496) / 1000;757 758	// setup tuner buffer759	tuner_buf[0] = (tuner_frequency >> 8) & 0x7f;760	tuner_buf[1] = tuner_frequency & 0xff;761	tuner_buf[2] = 0xca;762	tuner_buf[3] = (cp << 5) | (filter << 3) | band;763 764	if (fe->ops.i2c_gate_ctrl)765		fe->ops.i2c_gate_ctrl(fe, 1);766	if (i2c_transfer(&budget->i2c_adap, &tuner_msg, 1) != 1)767		return -EIO;768 769	msleep(1);770	return 0;771}772 773static int philips_tu1216_request_firmware(struct dvb_frontend *fe,774					   const struct firmware **fw, char *name)775{776	struct budget *budget = fe->dvb->priv;777 778	return request_firmware(fw, name, &budget->dev->pci->dev);779}780 781static struct tda1004x_config philips_tu1216_config = {782 783	.demod_address = 0x8,784	.invert = 1,785	.invert_oclk = 1,786	.xtal_freq = TDA10046_XTAL_4M,787	.agc_config = TDA10046_AGC_DEFAULT,788	.if_freq = TDA10046_FREQ_3617,789	.request_firmware = philips_tu1216_request_firmware,790};791 792static u8 philips_sd1878_inittab[] = {793	0x01, 0x15,794	0x02, 0x30,795	0x03, 0x00,796	0x04, 0x7d,797	0x05, 0x35,798	0x06, 0x40,799	0x07, 0x00,800	0x08, 0x43,801	0x09, 0x02,802	0x0C, 0x51,803	0x0D, 0x82,804	0x0E, 0x23,805	0x10, 0x3f,806	0x11, 0x84,807	0x12, 0xb9,808	0x15, 0xc9,809	0x16, 0x19,810	0x17, 0x8c,811	0x18, 0x59,812	0x19, 0xf8,813	0x1a, 0xfe,814	0x1c, 0x7f,815	0x1d, 0x00,816	0x1e, 0x00,817	0x1f, 0x50,818	0x20, 0x00,819	0x21, 0x00,820	0x22, 0x00,821	0x23, 0x00,822	0x28, 0x00,823	0x29, 0x28,824	0x2a, 0x14,825	0x2b, 0x0f,826	0x2c, 0x09,827	0x2d, 0x09,828	0x31, 0x1f,829	0x32, 0x19,830	0x33, 0xfc,831	0x34, 0x93,832	0xff, 0xff833};834 835static int philips_sd1878_ci_set_symbol_rate(struct dvb_frontend *fe,836		u32 srate, u32 ratio)837{838	u8 aclk = 0;839	u8 bclk = 0;840	u8 m1;841 842	aclk = 0xb5;843	if (srate < 2000000)844		bclk = 0x86;845	else if (srate < 5000000)846		bclk = 0x89;847	else if (srate < 15000000)848		bclk = 0x8f;849	else if (srate < 45000000)850		bclk = 0x95;851 852	m1 = 0x14;853	if (srate < 4000000)854		m1 = 0x10;855 856	stv0299_writereg(fe, 0x0e, 0x23);857	stv0299_writereg(fe, 0x0f, 0x94);858	stv0299_writereg(fe, 0x10, 0x39);859	stv0299_writereg(fe, 0x13, aclk);860	stv0299_writereg(fe, 0x14, bclk);861	stv0299_writereg(fe, 0x15, 0xc9);862	stv0299_writereg(fe, 0x1f, (ratio >> 16) & 0xff);863	stv0299_writereg(fe, 0x20, (ratio >> 8) & 0xff);864	stv0299_writereg(fe, 0x21, (ratio) & 0xf0);865	stv0299_writereg(fe, 0x0f, 0x80 | m1);866 867	return 0;868}869 870static const struct stv0299_config philips_sd1878_config = {871	.demod_address = 0x68,872	.inittab = philips_sd1878_inittab,873	.mclk = 88000000UL,874	.invert = 0,875	.skip_reinit = 0,876	.lock_output = STV0299_LOCKOUTPUT_1,877	.volt13_op0_op1 = STV0299_VOLT13_OP0,878	.min_delay_ms = 100,879	.set_symbol_rate = philips_sd1878_ci_set_symbol_rate,880};881 882/* KNC1 DVB-S (STB0899) Inittab	*/883static const struct stb0899_s1_reg knc1_stb0899_s1_init_1[] = {884 885	{ STB0899_DEV_ID,		0x81 },886	{ STB0899_DISCNTRL1,		0x32 },887	{ STB0899_DISCNTRL2,		0x80 },888	{ STB0899_DISRX_ST0,		0x04 },889	{ STB0899_DISRX_ST1,		0x00 },890	{ STB0899_DISPARITY,		0x00 },891	{ STB0899_DISSTATUS,		0x20 },892	{ STB0899_DISF22,		0x8c },893	{ STB0899_DISF22RX,		0x9a },894	{ STB0899_SYSREG,		0x0b },895	{ STB0899_ACRPRESC,		0x11 },896	{ STB0899_ACRDIV1,		0x0a },897	{ STB0899_ACRDIV2,		0x05 },898	{ STB0899_DACR1,		0x00 },899	{ STB0899_DACR2,		0x00 },900	{ STB0899_OUTCFG,		0x00 },901	{ STB0899_MODECFG,		0x00 },902	{ STB0899_IRQSTATUS_3,		0x30 },903	{ STB0899_IRQSTATUS_2,		0x00 },904	{ STB0899_IRQSTATUS_1,		0x00 },905	{ STB0899_IRQSTATUS_0,		0x00 },906	{ STB0899_IRQMSK_3,		0xf3 },907	{ STB0899_IRQMSK_2,		0xfc },908	{ STB0899_IRQMSK_1,		0xff },909	{ STB0899_IRQMSK_0,		0xff },910	{ STB0899_IRQCFG,		0x00 },911	{ STB0899_I2CCFG,		0x88 },912	{ STB0899_I2CRPT,		0x58 }, /* Repeater=8, Stop=disabled */913	{ STB0899_IOPVALUE5,		0x00 },914	{ STB0899_IOPVALUE4,		0x20 },915	{ STB0899_IOPVALUE3,		0xc9 },916	{ STB0899_IOPVALUE2,		0x90 },917	{ STB0899_IOPVALUE1,		0x40 },918	{ STB0899_IOPVALUE0,		0x00 },919	{ STB0899_GPIO00CFG,		0x82 },920	{ STB0899_GPIO01CFG,		0x82 },921	{ STB0899_GPIO02CFG,		0x82 },922	{ STB0899_GPIO03CFG,		0x82 },923	{ STB0899_GPIO04CFG,		0x82 },924	{ STB0899_GPIO05CFG,		0x82 },925	{ STB0899_GPIO06CFG,		0x82 },926	{ STB0899_GPIO07CFG,		0x82 },927	{ STB0899_GPIO08CFG,		0x82 },928	{ STB0899_GPIO09CFG,		0x82 },929	{ STB0899_GPIO10CFG,		0x82 },930	{ STB0899_GPIO11CFG,		0x82 },931	{ STB0899_GPIO12CFG,		0x82 },932	{ STB0899_GPIO13CFG,		0x82 },933	{ STB0899_GPIO14CFG,		0x82 },934	{ STB0899_GPIO15CFG,		0x82 },935	{ STB0899_GPIO16CFG,		0x82 },936	{ STB0899_GPIO17CFG,		0x82 },937	{ STB0899_GPIO18CFG,		0x82 },938	{ STB0899_GPIO19CFG,		0x82 },939	{ STB0899_GPIO20CFG,		0x82 },940	{ STB0899_SDATCFG,		0xb8 },941	{ STB0899_SCLTCFG,		0xba },942	{ STB0899_AGCRFCFG,		0x08 }, /* 0x1c */943	{ STB0899_GPIO22,		0x82 }, /* AGCBB2CFG */944	{ STB0899_GPIO21,		0x91 }, /* AGCBB1CFG */945	{ STB0899_DIRCLKCFG,		0x82 },946	{ STB0899_CLKOUT27CFG,		0x7e },947	{ STB0899_STDBYCFG,		0x82 },948	{ STB0899_CS0CFG,		0x82 },949	{ STB0899_CS1CFG,		0x82 },950	{ STB0899_DISEQCOCFG,		0x20 },951	{ STB0899_GPIO32CFG,		0x82 },952	{ STB0899_GPIO33CFG,		0x82 },953	{ STB0899_GPIO34CFG,		0x82 },954	{ STB0899_GPIO35CFG,		0x82 },955	{ STB0899_GPIO36CFG,		0x82 },956	{ STB0899_GPIO37CFG,		0x82 },957	{ STB0899_GPIO38CFG,		0x82 },958	{ STB0899_GPIO39CFG,		0x82 },959	{ STB0899_NCOARSE,		0x15 }, /* 0x15 = 27 Mhz Clock, F/3 = 198MHz, F/6 = 99MHz */960	{ STB0899_SYNTCTRL,		0x02 }, /* 0x00 = CLK from CLKI, 0x02 = CLK from XTALI */961	{ STB0899_FILTCTRL,		0x00 },962	{ STB0899_SYSCTRL,		0x00 },963	{ STB0899_STOPCLK1,		0x20 },964	{ STB0899_STOPCLK2,		0x00 },965	{ STB0899_INTBUFSTATUS,		0x00 },966	{ STB0899_INTBUFCTRL,		0x0a },967	{ 0xffff,			0xff },968};969 970static const struct stb0899_s1_reg knc1_stb0899_s1_init_3[] = {971	{ STB0899_DEMOD,		0x00 },972	{ STB0899_RCOMPC,		0xc9 },973	{ STB0899_AGC1CN,		0x41 },974	{ STB0899_AGC1REF,		0x08 },975	{ STB0899_RTC,			0x7a },976	{ STB0899_TMGCFG,		0x4e },977	{ STB0899_AGC2REF,		0x33 },978	{ STB0899_TLSR,			0x84 },979	{ STB0899_CFD,			0xee },980	{ STB0899_ACLC,			0x87 },981	{ STB0899_BCLC,			0x94 },982	{ STB0899_EQON,			0x41 },983	{ STB0899_LDT,			0xdd },984	{ STB0899_LDT2,			0xc9 },985	{ STB0899_EQUALREF,		0xb4 },986	{ STB0899_TMGRAMP,		0x10 },987	{ STB0899_TMGTHD,		0x30 },988	{ STB0899_IDCCOMP,		0xfb },989	{ STB0899_QDCCOMP,		0x03 },990	{ STB0899_POWERI,		0x3b },991	{ STB0899_POWERQ,		0x3d },992	{ STB0899_RCOMP,		0x81 },993	{ STB0899_AGCIQIN,		0x80 },994	{ STB0899_AGC2I1,		0x04 },995	{ STB0899_AGC2I2,		0xf5 },996	{ STB0899_TLIR,			0x25 },997	{ STB0899_RTF,			0x80 },998	{ STB0899_DSTATUS,		0x00 },999	{ STB0899_LDI,			0xca },1000	{ STB0899_CFRM,			0xf1 },1001	{ STB0899_CFRL,			0xf3 },1002	{ STB0899_NIRM,			0x2a },1003	{ STB0899_NIRL,			0x05 },1004	{ STB0899_ISYMB,		0x17 },1005	{ STB0899_QSYMB,		0xfa },1006	{ STB0899_SFRH,			0x2f },1007	{ STB0899_SFRM,			0x68 },1008	{ STB0899_SFRL,			0x40 },1009	{ STB0899_SFRUPH,		0x2f },1010	{ STB0899_SFRUPM,		0x68 },1011	{ STB0899_SFRUPL,		0x40 },1012	{ STB0899_EQUAI1,		0xfd },1013	{ STB0899_EQUAQ1,		0x04 },1014	{ STB0899_EQUAI2,		0x0f },1015	{ STB0899_EQUAQ2,		0xff },1016	{ STB0899_EQUAI3,		0xdf },1017	{ STB0899_EQUAQ3,		0xfa },1018	{ STB0899_EQUAI4,		0x37 },1019	{ STB0899_EQUAQ4,		0x0d },1020	{ STB0899_EQUAI5,		0xbd },1021	{ STB0899_EQUAQ5,		0xf7 },1022	{ STB0899_DSTATUS2,		0x00 },1023	{ STB0899_VSTATUS,		0x00 },1024	{ STB0899_VERROR,		0xff },1025	{ STB0899_IQSWAP,		0x2a },1026	{ STB0899_ECNT1M,		0x00 },1027	{ STB0899_ECNT1L,		0x00 },1028	{ STB0899_ECNT2M,		0x00 },1029	{ STB0899_ECNT2L,		0x00 },1030	{ STB0899_ECNT3M,		0x00 },1031	{ STB0899_ECNT3L,		0x00 },1032	{ STB0899_FECAUTO1,		0x06 },1033	{ STB0899_FECM,			0x01 },1034	{ STB0899_VTH12,		0xf0 },1035	{ STB0899_VTH23,		0xa0 },1036	{ STB0899_VTH34,		0x78 },1037	{ STB0899_VTH56,		0x4e },1038	{ STB0899_VTH67,		0x48 },1039	{ STB0899_VTH78,		0x38 },1040	{ STB0899_PRVIT,		0xff },1041	{ STB0899_VITSYNC,		0x19 },1042	{ STB0899_RSULC,		0xb1 }, /* DVB = 0xb1, DSS = 0xa1 */1043	{ STB0899_TSULC,		0x42 },1044	{ STB0899_RSLLC,		0x40 },1045	{ STB0899_TSLPL,		0x12 },1046	{ STB0899_TSCFGH,		0x0c },1047	{ STB0899_TSCFGM,		0x00 },1048	{ STB0899_TSCFGL,		0x0c },1049	{ STB0899_TSOUT,		0x4d }, /* 0x0d for CAM */1050	{ STB0899_RSSYNCDEL,		0x00 },1051	{ STB0899_TSINHDELH,		0x02 },1052	{ STB0899_TSINHDELM,		0x00 },1053	{ STB0899_TSINHDELL,		0x00 },1054	{ STB0899_TSLLSTKM,		0x00 },1055	{ STB0899_TSLLSTKL,		0x00 },1056	{ STB0899_TSULSTKM,		0x00 },1057	{ STB0899_TSULSTKL,		0xab },1058	{ STB0899_PCKLENUL,		0x00 },1059	{ STB0899_PCKLENLL,		0xcc },1060	{ STB0899_RSPCKLEN,		0xcc },1061	{ STB0899_TSSTATUS,		0x80 },1062	{ STB0899_ERRCTRL1,		0xb6 },1063	{ STB0899_ERRCTRL2,		0x96 },1064	{ STB0899_ERRCTRL3,		0x89 },1065	{ STB0899_DMONMSK1,		0x27 },1066	{ STB0899_DMONMSK0,		0x03 },1067	{ STB0899_DEMAPVIT,		0x5c },1068	{ STB0899_PLPARM,		0x1f },1069	{ STB0899_PDELCTRL,		0x48 },1070	{ STB0899_PDELCTRL2,		0x00 },1071	{ STB0899_BBHCTRL1,		0x00 },1072	{ STB0899_BBHCTRL2,		0x00 },1073	{ STB0899_HYSTTHRESH,		0x77 },1074	{ STB0899_MATCSTM,		0x00 },1075	{ STB0899_MATCSTL,		0x00 },1076	{ STB0899_UPLCSTM,		0x00 },1077	{ STB0899_UPLCSTL,		0x00 },1078	{ STB0899_DFLCSTM,		0x00 },1079	{ STB0899_DFLCSTL,		0x00 },1080	{ STB0899_SYNCCST,		0x00 },1081	{ STB0899_SYNCDCSTM,		0x00 },1082	{ STB0899_SYNCDCSTL,		0x00 },1083	{ STB0899_ISI_ENTRY,		0x00 },1084	{ STB0899_ISI_BIT_EN,		0x00 },1085	{ STB0899_MATSTRM,		0x00 },1086	{ STB0899_MATSTRL,		0x00 },1087	{ STB0899_UPLSTRM,		0x00 },1088	{ STB0899_UPLSTRL,		0x00 },1089	{ STB0899_DFLSTRM,		0x00 },1090	{ STB0899_DFLSTRL,		0x00 },1091	{ STB0899_SYNCSTR,		0x00 },1092	{ STB0899_SYNCDSTRM,		0x00 },1093	{ STB0899_SYNCDSTRL,		0x00 },1094	{ STB0899_CFGPDELSTATUS1,	0x10 },1095	{ STB0899_CFGPDELSTATUS2,	0x00 },1096	{ STB0899_BBFERRORM,		0x00 },1097	{ STB0899_BBFERRORL,		0x00 },1098	{ STB0899_UPKTERRORM,		0x00 },1099	{ STB0899_UPKTERRORL,		0x00 },1100	{ 0xffff,			0xff },1101};1102 1103/* STB0899 demodulator config for the KNC1 and clones */1104static struct stb0899_config knc1_dvbs2_config = {1105	.init_dev		= knc1_stb0899_s1_init_1,1106	.init_s2_demod		= stb0899_s2_init_2,1107	.init_s1_demod		= knc1_stb0899_s1_init_3,1108	.init_s2_fec		= stb0899_s2_init_4,1109	.init_tst		= stb0899_s1_init_5,1110 1111	.postproc		= NULL,1112 1113	.demod_address		= 0x68,1114//	.ts_output_mode		= STB0899_OUT_PARALLEL,	/* types = SERIAL/PARALLEL	*/1115	.block_sync_mode	= STB0899_SYNC_FORCED,	/* DSS, SYNC_FORCED/UNSYNCED	*/1116//	.ts_pfbit_toggle	= STB0899_MPEG_NORMAL,	/* DirecTV, MPEG toggling seq	*/1117 1118	.xtal_freq		= 27000000,1119	.inversion		= IQ_SWAP_OFF,1120 1121	.lo_clk			= 76500000,1122	.hi_clk			= 90000000,1123 1124	.esno_ave		= STB0899_DVBS2_ESNO_AVE,1125	.esno_quant		= STB0899_DVBS2_ESNO_QUANT,1126	.avframes_coarse	= STB0899_DVBS2_AVFRAMES_COARSE,1127	.avframes_fine		= STB0899_DVBS2_AVFRAMES_FINE,1128	.miss_threshold		= STB0899_DVBS2_MISS_THRESHOLD,1129	.uwp_threshold_acq	= STB0899_DVBS2_UWP_THRESHOLD_ACQ,1130	.uwp_threshold_track	= STB0899_DVBS2_UWP_THRESHOLD_TRACK,1131	.uwp_threshold_sof	= STB0899_DVBS2_UWP_THRESHOLD_SOF,1132	.sof_search_timeout	= STB0899_DVBS2_SOF_SEARCH_TIMEOUT,1133 1134	.btr_nco_bits		= STB0899_DVBS2_BTR_NCO_BITS,1135	.btr_gain_shift_offset	= STB0899_DVBS2_BTR_GAIN_SHIFT_OFFSET,1136	.crl_nco_bits		= STB0899_DVBS2_CRL_NCO_BITS,1137	.ldpc_max_iter		= STB0899_DVBS2_LDPC_MAX_ITER,1138 1139	.tuner_get_frequency	= tda8261_get_frequency,1140	.tuner_set_frequency	= tda8261_set_frequency,1141	.tuner_set_bandwidth	= NULL,1142	.tuner_get_bandwidth	= tda8261_get_bandwidth,1143	.tuner_set_rfsiggain	= NULL1144};1145 1146/*1147 * SD1878/SHA tuner config1148 * 1F, Single I/P, Horizontal mount, High Sensitivity1149 */1150static const struct tda8261_config sd1878c_config = {1151//	.name		= "SD1878/SHA",1152	.addr		= 0x60,1153	.step_size	= TDA8261_STEP_1000 /* kHz */1154};1155 1156static u8 read_pwm(struct budget_av *budget_av)1157{1158	u8 b = 0xff;1159	u8 pwm;1160	struct i2c_msg msg[] = { {.addr = 0x50, .flags = 0, .buf = &b, .len = 1},1161	{.addr = 0x50, .flags = I2C_M_RD, .buf = &pwm, .len = 1}1162	};1163 1164	if ((i2c_transfer(&budget_av->budget.i2c_adap, msg, 2) != 2)1165	    || (pwm == 0xff))1166		pwm = 0x48;1167 1168	return pwm;1169}1170 1171#define SUBID_DVBS_KNC1			0x00101172#define SUBID_DVBS_KNC1_PLUS		0x00111173#define SUBID_DVBS_TYPHOON		0x4f561174#define SUBID_DVBS_CINERGY1200		0x11541175#define SUBID_DVBS_CYNERGY1200N		0x11551176#define SUBID_DVBS_TV_STAR		0x00141177#define SUBID_DVBS_TV_STAR_PLUS_X4	0x00151178#define SUBID_DVBS_TV_STAR_CI		0x00161179#define SUBID_DVBS2_KNC1		0x00181180#define SUBID_DVBS2_KNC1_OEM		0x00191181#define SUBID_DVBS_EASYWATCH_1		0x001a1182#define SUBID_DVBS_EASYWATCH_2		0x001b1183#define SUBID_DVBS2_EASYWATCH		0x001d1184#define SUBID_DVBS_EASYWATCH		0x001e1185 1186#define SUBID_DVBC_EASYWATCH		0x002a1187#define SUBID_DVBC_EASYWATCH_MK3	0x002c1188#define SUBID_DVBC_KNC1			0x00201189#define SUBID_DVBC_KNC1_PLUS		0x00211190#define SUBID_DVBC_KNC1_MK3		0x00221191#define SUBID_DVBC_KNC1_TDA10024	0x00281192#define SUBID_DVBC_KNC1_PLUS_MK3	0x00231193#define SUBID_DVBC_CINERGY1200		0x11561194#define SUBID_DVBC_CINERGY1200_MK3	0x11761195 1196#define SUBID_DVBT_EASYWATCH		0x003a1197#define SUBID_DVBT_KNC1_PLUS		0x00311198#define SUBID_DVBT_KNC1			0x00301199#define SUBID_DVBT_CINERGY1200		0x11571200 1201static void frontend_init(struct budget_av *budget_av)1202{1203	struct saa7146_dev *saa = budget_av->budget.dev;1204	struct dvb_frontend *fe = NULL;1205 1206	/* Enable / PowerON Frontend */1207	saa7146_setgpio(saa, 0, SAA7146_GPIO_OUTLO);1208 1209	/* Wait for PowerON */1210	msleep(100);1211 1212	/* additional setup necessary for the PLUS cards */1213	switch (saa->pci->subsystem_device) {1214	case SUBID_DVBS_KNC1_PLUS:1215	case SUBID_DVBC_KNC1_PLUS:1216	case SUBID_DVBT_KNC1_PLUS:1217	case SUBID_DVBC_EASYWATCH:1218	case SUBID_DVBC_KNC1_PLUS_MK3:1219	case SUBID_DVBS2_KNC1:1220	case SUBID_DVBS2_KNC1_OEM:1221	case SUBID_DVBS2_EASYWATCH:1222		saa7146_setgpio(saa, 3, SAA7146_GPIO_OUTHI);1223		break;1224	}1225 1226	switch (saa->pci->subsystem_device) {1227 1228	case SUBID_DVBS_KNC1:1229		/*1230		 * maybe that setting is needed for other dvb-s cards as well,1231		 * but so far it has been only confirmed for this type1232		 */1233		budget_av->reinitialise_demod = 1;1234		fallthrough;1235	case SUBID_DVBS_KNC1_PLUS:1236	case SUBID_DVBS_EASYWATCH_1:1237		if (saa->pci->subsystem_vendor == 0x1894) {1238			fe = dvb_attach(stv0299_attach, &cinergy_1200s_1894_0010_config,1239					     &budget_av->budget.i2c_adap);1240			if (fe)1241				dvb_attach(tua6100_attach, fe, 0x60, &budget_av->budget.i2c_adap);1242		} else {1243			fe = dvb_attach(stv0299_attach, &typhoon_config,1244					     &budget_av->budget.i2c_adap);1245			if (fe)1246				fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;1247		}1248		break;1249 1250	case SUBID_DVBS_TV_STAR:1251	case SUBID_DVBS_TV_STAR_PLUS_X4:1252	case SUBID_DVBS_TV_STAR_CI:1253	case SUBID_DVBS_CYNERGY1200N:1254	case SUBID_DVBS_EASYWATCH:1255	case SUBID_DVBS_EASYWATCH_2:1256		fe = dvb_attach(stv0299_attach, &philips_sd1878_config,1257				&budget_av->budget.i2c_adap);1258		if (fe)1259			dvb_attach(dvb_pll_attach, fe, 0x60,1260				   &budget_av->budget.i2c_adap,1261				   DVB_PLL_PHILIPS_SD1878_TDA8261);1262		break;1263 1264	case SUBID_DVBS_TYPHOON:1265		fe = dvb_attach(stv0299_attach, &typhoon_config,1266				    &budget_av->budget.i2c_adap);1267		if (fe)1268			fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;1269		break;1270	case SUBID_DVBS2_KNC1:1271	case SUBID_DVBS2_KNC1_OEM:1272	case SUBID_DVBS2_EASYWATCH:1273		budget_av->reinitialise_demod = 1;1274		fe = dvb_attach(stb0899_attach, &knc1_dvbs2_config, &budget_av->budget.i2c_adap);1275		if (fe)1276			dvb_attach(tda8261_attach, fe, &sd1878c_config, &budget_av->budget.i2c_adap);1277 1278		break;1279	case SUBID_DVBS_CINERGY1200:1280		fe = dvb_attach(stv0299_attach, &cinergy_1200s_config,1281				    &budget_av->budget.i2c_adap);1282		if (fe)1283			fe->ops.tuner_ops.set_params = philips_su1278_ty_ci_tuner_set_params;1284		break;1285 1286	case SUBID_DVBC_KNC1:1287	case SUBID_DVBC_KNC1_PLUS:1288	case SUBID_DVBC_CINERGY1200:1289	case SUBID_DVBC_EASYWATCH:1290		budget_av->reinitialise_demod = 1;1291		budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;1292		fe = dvb_attach(tda10021_attach, &philips_cu1216_config,1293				     &budget_av->budget.i2c_adap,1294				     read_pwm(budget_av));1295		if (fe == NULL)1296			fe = dvb_attach(tda10021_attach, &philips_cu1216_config_altaddress,1297					     &budget_av->budget.i2c_adap,1298					     read_pwm(budget_av));1299		if (fe)1300			fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;1301		break;1302 1303	case SUBID_DVBC_EASYWATCH_MK3:1304	case SUBID_DVBC_CINERGY1200_MK3:1305	case SUBID_DVBC_KNC1_MK3:1306	case SUBID_DVBC_KNC1_TDA10024:1307	case SUBID_DVBC_KNC1_PLUS_MK3:1308		budget_av->reinitialise_demod = 1;1309		budget_av->budget.dev->i2c_bitrate = SAA7146_I2C_BUS_BIT_RATE_240;1310		fe = dvb_attach(tda10023_attach,1311			&philips_cu1216_tda10023_config,1312			&budget_av->budget.i2c_adap,1313			read_pwm(budget_av));1314		if (fe)1315			fe->ops.tuner_ops.set_params = philips_cu1216_tuner_set_params;1316		break;1317 1318	case SUBID_DVBT_EASYWATCH:1319	case SUBID_DVBT_KNC1:1320	case SUBID_DVBT_KNC1_PLUS:1321	case SUBID_DVBT_CINERGY1200:1322		budget_av->reinitialise_demod = 1;1323		fe = dvb_attach(tda10046_attach, &philips_tu1216_config,1324				     &budget_av->budget.i2c_adap);1325		if (fe) {1326			fe->ops.tuner_ops.init = philips_tu1216_tuner_init;1327			fe->ops.tuner_ops.set_params = philips_tu1216_tuner_set_params;1328		}1329		break;1330	}1331 1332	if (fe == NULL) {1333		pr_err("A frontend driver was not found for device [%04x:%04x] subsystem [%04x:%04x]\n",1334		       saa->pci->vendor,1335		       saa->pci->device,1336		       saa->pci->subsystem_vendor,1337		       saa->pci->subsystem_device);1338		return;1339	}1340 1341	budget_av->budget.dvb_frontend = fe;1342 1343	if (dvb_register_frontend(&budget_av->budget.dvb_adapter,1344				  budget_av->budget.dvb_frontend)) {1345		pr_err("Frontend registration failed!\n");1346		dvb_frontend_detach(budget_av->budget.dvb_frontend);1347		budget_av->budget.dvb_frontend = NULL;1348	}1349}1350 1351 1352static void budget_av_irq(struct saa7146_dev *dev, u32 *isr)1353{1354	struct budget_av *budget_av = dev->ext_priv;1355 1356	dprintk(8, "dev: %p, budget_av: %p\n", dev, budget_av);1357 1358	if (*isr & MASK_10)1359		ttpci_budget_irq10_handler(dev, isr);1360}1361 1362static int budget_av_detach(struct saa7146_dev *dev)1363{1364	struct budget_av *budget_av = dev->ext_priv;1365	int err;1366 1367	dprintk(2, "dev: %p\n", dev);1368 1369	if (budget_av->has_saa7113 == 1) {1370		saa7146_setgpio(dev, 0, SAA7146_GPIO_OUTLO);1371 1372		msleep(200);1373 1374		saa7146_unregister_device(&budget_av->vd, dev);1375 1376		saa7146_vv_release(dev);1377	}1378 1379	if (budget_av->budget.ci_present)1380		ciintf_deinit(budget_av);1381 1382	if (budget_av->budget.dvb_frontend != NULL) {1383		dvb_unregister_frontend(budget_av->budget.dvb_frontend);1384		dvb_frontend_detach(budget_av->budget.dvb_frontend);1385	}1386	err = ttpci_budget_deinit(&budget_av->budget);1387 1388	kfree(budget_av);1389 1390	return err;1391}1392 1393#define KNC1_INPUTS 21394static struct v4l2_input knc1_inputs[KNC1_INPUTS] = {1395	{ 0, "Composite", V4L2_INPUT_TYPE_TUNER, 1, 0,1396		V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },1397	{ 1, "S-Video", V4L2_INPUT_TYPE_CAMERA, 2, 0,1398		V4L2_STD_PAL_BG | V4L2_STD_NTSC_M, 0, V4L2_IN_CAP_STD },1399};1400 1401static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *i)1402{1403	dprintk(1, "VIDIOC_ENUMINPUT %d\n", i->index);1404	if (i->index >= KNC1_INPUTS)1405		return -EINVAL;1406	memcpy(i, &knc1_inputs[i->index], sizeof(struct v4l2_input));1407	return 0;1408}1409 1410static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)1411{1412	struct saa7146_dev *dev = video_drvdata(file);1413	struct budget_av *budget_av = dev->ext_priv;1414 1415	*i = budget_av->cur_input;1416 1417	dprintk(1, "VIDIOC_G_INPUT %d\n", *i);1418	return 0;1419}1420 1421static int vidioc_s_input(struct file *file, void *fh, unsigned int input)1422{1423	struct saa7146_dev *dev = video_drvdata(file);1424	struct budget_av *budget_av = dev->ext_priv;1425 1426	dprintk(1, "VIDIOC_S_INPUT %d\n", input);1427	return saa7113_setinput(budget_av, input);1428}1429 1430static struct saa7146_ext_vv vv_data;1431 1432static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)1433{1434	struct budget_av *budget_av;1435	u8 *mac;1436	int err;1437 1438	dprintk(2, "dev: %p\n", dev);1439 1440	budget_av = kzalloc(sizeof(struct budget_av), GFP_KERNEL);1441	if (!budget_av)1442		return -ENOMEM;1443 1444	budget_av->has_saa7113 = 0;1445	budget_av->budget.ci_present = 0;1446 1447	dev->ext_priv = budget_av;1448 1449	err = ttpci_budget_init(&budget_av->budget, dev, info, THIS_MODULE,1450				adapter_nr);1451	if (err) {1452		kfree(budget_av);1453		return err;1454	}1455 1456	/* knc1 initialization */1457	saa7146_write(dev, DD1_STREAM_B, 0x04000000);1458	saa7146_write(dev, DD1_INIT, 0x07000600);1459	saa7146_write(dev, MC2, MASK_09 | MASK_25 | MASK_10 | MASK_26);1460 1461	if (saa7113_init(budget_av) == 0) {1462		budget_av->has_saa7113 = 1;1463		err = saa7146_vv_init(dev, &vv_data);1464		if (err != 0) {1465			ttpci_budget_deinit(&budget_av->budget);1466			kfree(budget_av);1467			pr_err("cannot init vv subsystem\n");1468			return err;1469		}1470		vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;1471		vv_data.vid_ops.vidioc_g_input = vidioc_g_input;1472		vv_data.vid_ops.vidioc_s_input = vidioc_s_input;1473 1474		err = saa7146_register_device(&budget_av->vd, dev, "knc1", VFL_TYPE_VIDEO);1475		if (err) {1476			saa7146_vv_release(dev);1477			ttpci_budget_deinit(&budget_av->budget);1478			kfree(budget_av);1479			pr_err("cannot register capture v4l2 device\n");1480			return err;1481		}1482 1483		/* beware: this modifies dev->vv ... */1484		saa7146_set_hps_source_and_sync(dev, SAA7146_HPS_SOURCE_PORT_A,1485						SAA7146_HPS_SYNC_PORT_A);1486 1487		saa7113_setinput(budget_av, 0);1488	}1489 1490	/* fixme: find some sane values here... */1491	saa7146_write(dev, PCI_BT_V1, 0x1c00101f);1492 1493	mac = budget_av->budget.dvb_adapter.proposed_mac;1494	if (i2c_readregs(&budget_av->budget.i2c_adap, 0xa0, 0x30, mac, 6)) {1495		pr_err("KNC1-%d: Could not read MAC from KNC1 card\n",1496		       budget_av->budget.dvb_adapter.num);1497		eth_zero_addr(mac);1498	} else {1499		pr_info("KNC1-%d: MAC addr = %pM\n",1500			budget_av->budget.dvb_adapter.num, mac);1501	}1502 1503	budget_av->budget.dvb_adapter.priv = budget_av;1504	frontend_init(budget_av);1505	ciintf_init(budget_av);1506 1507	ttpci_budget_init_hooks(&budget_av->budget);1508 1509	return 0;1510}1511 1512static struct saa7146_standard standard[] = {1513	{.name = "PAL", .id = V4L2_STD_PAL,1514	 .v_offset = 0x17, .v_field = 288,1515	 .h_offset = 0x14, .h_pixels = 680,1516	 .v_max_out = 576, .h_max_out = 768 },1517 1518	{.name = "NTSC", .id = V4L2_STD_NTSC,1519	 .v_offset = 0x16, .v_field = 240,1520	 .h_offset = 0x06, .h_pixels = 708,1521	 .v_max_out = 480, .h_max_out = 640, },1522};1523 1524static struct saa7146_ext_vv vv_data = {1525	.inputs = 2,1526	.capabilities = 0,	// perhaps later: V4L2_CAP_VBI_CAPTURE, but that need tweaking with the saa71131527	.flags = 0,1528	.stds = &standard[0],1529	.num_stds = ARRAY_SIZE(standard),1530};1531 1532static struct saa7146_extension budget_extension;1533 1534MAKE_BUDGET_INFO(knc1s, "KNC1 DVB-S", BUDGET_KNC1S);1535MAKE_BUDGET_INFO(knc1s2, "KNC1 DVB-S2", BUDGET_KNC1S2);1536MAKE_BUDGET_INFO(sates2, "Satelco EasyWatch DVB-S2", BUDGET_KNC1S2);1537MAKE_BUDGET_INFO(knc1c, "KNC1 DVB-C", BUDGET_KNC1C);1538MAKE_BUDGET_INFO(knc1t, "KNC1 DVB-T", BUDGET_KNC1T);1539MAKE_BUDGET_INFO(kncxs, "KNC TV STAR DVB-S", BUDGET_TVSTAR);1540MAKE_BUDGET_INFO(satewpls, "Satelco EasyWatch DVB-S light", BUDGET_TVSTAR);1541MAKE_BUDGET_INFO(satewpls1, "Satelco EasyWatch DVB-S light", BUDGET_KNC1S);1542MAKE_BUDGET_INFO(satewps, "Satelco EasyWatch DVB-S", BUDGET_KNC1S);1543MAKE_BUDGET_INFO(satewplc, "Satelco EasyWatch DVB-C", BUDGET_KNC1CP);1544MAKE_BUDGET_INFO(satewcmk3, "Satelco EasyWatch DVB-C MK3", BUDGET_KNC1C_MK3);1545MAKE_BUDGET_INFO(satewt, "Satelco EasyWatch DVB-T", BUDGET_KNC1T);1546MAKE_BUDGET_INFO(knc1sp, "KNC1 DVB-S Plus", BUDGET_KNC1SP);1547MAKE_BUDGET_INFO(knc1spx4, "KNC1 DVB-S Plus X4", BUDGET_KNC1SP);1548MAKE_BUDGET_INFO(knc1cp, "KNC1 DVB-C Plus", BUDGET_KNC1CP);1549MAKE_BUDGET_INFO(knc1cmk3, "KNC1 DVB-C MK3", BUDGET_KNC1C_MK3);1550MAKE_BUDGET_INFO(knc1ctda10024, "KNC1 DVB-C TDA10024", BUDGET_KNC1C_TDA10024);1551MAKE_BUDGET_INFO(knc1cpmk3, "KNC1 DVB-C Plus MK3", BUDGET_KNC1CP_MK3);1552MAKE_BUDGET_INFO(knc1tp, "KNC1 DVB-T Plus", BUDGET_KNC1TP);1553MAKE_BUDGET_INFO(cin1200s, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);1554MAKE_BUDGET_INFO(cin1200sn, "TerraTec Cinergy 1200 DVB-S", BUDGET_CIN1200S);1555MAKE_BUDGET_INFO(cin1200c, "Terratec Cinergy 1200 DVB-C", BUDGET_CIN1200C);1556MAKE_BUDGET_INFO(cin1200cmk3, "Terratec Cinergy 1200 DVB-C MK3", BUDGET_CIN1200C_MK3);1557MAKE_BUDGET_INFO(cin1200t, "Terratec Cinergy 1200 DVB-T", BUDGET_CIN1200T);1558 1559static const struct pci_device_id pci_tbl[] = {1560	MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x4f56),1561	MAKE_EXTENSION_PCI(knc1s, 0x1131, 0x0010),1562	MAKE_EXTENSION_PCI(knc1s, 0x1894, 0x0010),1563	MAKE_EXTENSION_PCI(knc1sp, 0x1131, 0x0011),1564	MAKE_EXTENSION_PCI(knc1sp, 0x1894, 0x0011),1565	MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0014),1566	MAKE_EXTENSION_PCI(knc1spx4, 0x1894, 0x0015),1567	MAKE_EXTENSION_PCI(kncxs, 0x1894, 0x0016),1568	MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0018),1569	MAKE_EXTENSION_PCI(knc1s2, 0x1894, 0x0019),1570	MAKE_EXTENSION_PCI(sates2, 0x1894, 0x001d),1571	MAKE_EXTENSION_PCI(satewpls, 0x1894, 0x001e),1572	MAKE_EXTENSION_PCI(satewpls1, 0x1894, 0x001a),1573	MAKE_EXTENSION_PCI(satewps, 0x1894, 0x001b),1574	MAKE_EXTENSION_PCI(satewplc, 0x1894, 0x002a),1575	MAKE_EXTENSION_PCI(satewcmk3, 0x1894, 0x002c),1576	MAKE_EXTENSION_PCI(satewt, 0x1894, 0x003a),1577	MAKE_EXTENSION_PCI(knc1c, 0x1894, 0x0020),1578	MAKE_EXTENSION_PCI(knc1cp, 0x1894, 0x0021),1579	MAKE_EXTENSION_PCI(knc1cmk3, 0x1894, 0x0022),1580	MAKE_EXTENSION_PCI(knc1ctda10024, 0x1894, 0x0028),1581	MAKE_EXTENSION_PCI(knc1cpmk3, 0x1894, 0x0023),1582	MAKE_EXTENSION_PCI(knc1t, 0x1894, 0x0030),1583	MAKE_EXTENSION_PCI(knc1tp, 0x1894, 0x0031),1584	MAKE_EXTENSION_PCI(cin1200s, 0x153b, 0x1154),1585	MAKE_EXTENSION_PCI(cin1200sn, 0x153b, 0x1155),1586	MAKE_EXTENSION_PCI(cin1200c, 0x153b, 0x1156),1587	MAKE_EXTENSION_PCI(cin1200cmk3, 0x153b, 0x1176),1588	MAKE_EXTENSION_PCI(cin1200t, 0x153b, 0x1157),1589	{1590	 .vendor = 0,1591	}1592};1593 1594MODULE_DEVICE_TABLE(pci, pci_tbl);1595 1596static struct saa7146_extension budget_extension = {1597	.name = "budget_av",1598	.flags = SAA7146_USE_I2C_IRQ,1599 1600	.pci_tbl = pci_tbl,1601 1602	.module = THIS_MODULE,1603	.attach = budget_av_attach,1604	.detach = budget_av_detach,1605 1606	.irq_mask = MASK_10,1607	.irq_func = budget_av_irq,1608};1609 1610static int __init budget_av_init(void)1611{1612	return saa7146_register_extension(&budget_extension);1613}1614 1615static void __exit budget_av_exit(void)1616{1617	saa7146_unregister_extension(&budget_extension);1618}1619 1620module_init(budget_av_init);1621module_exit(budget_av_exit);1622 1623MODULE_LICENSE("GPL");1624MODULE_AUTHOR("Ralph Metzler, Marcus Metzler, Michael Hunold, others");1625MODULE_DESCRIPTION("driver for the SAA7146 based so-called budget PCI DVB w/ analog input and CI-module (e.g. the KNC cards)");1626