File Index
Files and directories
Sign in
FILE

budget-av.c

File preview with syntax highlighting.

linux-6.19.14/drivers/media/pci/ttpci/budget-av.c C
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * budget-av.ko: driver for the SAA7146 based Budget DVB cards
   4 *               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  Metzler
  14 *                       & Marcus Metzler for convergence integrated media GmbH
  15 *
  16 * the project's page is at https://linuxtv.org
  17 */
  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		0x02420000
  44
  45#define SLOTSTATUS_NONE         1
  46#define SLOTSTATUS_PRESENT      2
  47#define SLOTSTATUS_RESET        4
  48#define SLOTSTATUS_READY        8
  49#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 Memory
  70 * 2 - CI Card Enable (Active Low)
  71 * 3 - CI Card Detect
  72 */
  73
  74/****************************************************************************
  75 * INITIALIZATION
  76 ****************************************************************************/
  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 carefully
 272	 * 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. If
 288	 * there is no CAM, we will get a timeout. Only done if there is no cam
 289	 * present, since this test actually breaks some cams :(
 290	 *
 291	 * if the CI interface is not open, we also do the above test since we
 292	 * don't care if the cam has problems - we'll be resetting it on open() anyway
 293	 */
 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	0xff
 413};
 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  0x3d
 543	0x11, 0x84,
 544	0x12, 0xb9,
 545	0x15, 0xc9,		// lock detector threshold
 546	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:0
 557	0x29, 0x1e,		// 1/2 threshold
 558	0x2a, 0x14,		// 2/3 threshold
 559	0x2b, 0x0f,		// 3/4 threshold
 560	0x2c, 0x09,		// 5/6 threshold
 561	0x2d, 0x05,		// 7/8 threshold
 562	0x2e, 0x01,
 563	0x31, 0x1f,		// test all FECs
 564	0x32, 0x19,		// viterbi and synchro search
 565	0x33, 0xfc,		// rs control
 566	0x34, 0x93,		// error control
 567	0x0f, 0x92,
 568	0xff, 0xff
 569};
 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 36125000
 617#define TUNER_MUL 62500
 618
 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 configuration
 680	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 pump
 700	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	else
 722		return -EINVAL;
 723
 724	// determine band
 725	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	else
 734		return -EINVAL;
 735
 736	// setup PLL filter
 737	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 divisor
 755	// ((36166000+((1000000/6)/2)) + Finput)/(1000000/6)
 756	tuner_frequency = (((c->frequency / 1000) * 6) + 217496) / 1000;
 757
 758	// setup tuner buffer
 759	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, 0xff
 833};
 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	= NULL
1144};
1145
1146/*
1147 * SD1878/SHA tuner config
1148 * 1F, Single I/P, Horizontal mount, High Sensitivity
1149 */
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			0x0010
1172#define SUBID_DVBS_KNC1_PLUS		0x0011
1173#define SUBID_DVBS_TYPHOON		0x4f56
1174#define SUBID_DVBS_CINERGY1200		0x1154
1175#define SUBID_DVBS_CYNERGY1200N		0x1155
1176#define SUBID_DVBS_TV_STAR		0x0014
1177#define SUBID_DVBS_TV_STAR_PLUS_X4	0x0015
1178#define SUBID_DVBS_TV_STAR_CI		0x0016
1179#define SUBID_DVBS2_KNC1		0x0018
1180#define SUBID_DVBS2_KNC1_OEM		0x0019
1181#define SUBID_DVBS_EASYWATCH_1		0x001a
1182#define SUBID_DVBS_EASYWATCH_2		0x001b
1183#define SUBID_DVBS2_EASYWATCH		0x001d
1184#define SUBID_DVBS_EASYWATCH		0x001e
1185
1186#define SUBID_DVBC_EASYWATCH		0x002a
1187#define SUBID_DVBC_EASYWATCH_MK3	0x002c
1188#define SUBID_DVBC_KNC1			0x0020
1189#define SUBID_DVBC_KNC1_PLUS		0x0021
1190#define SUBID_DVBC_KNC1_MK3		0x0022
1191#define SUBID_DVBC_KNC1_TDA10024	0x0028
1192#define SUBID_DVBC_KNC1_PLUS_MK3	0x0023
1193#define SUBID_DVBC_CINERGY1200		0x1156
1194#define SUBID_DVBC_CINERGY1200_MK3	0x1176
1195
1196#define SUBID_DVBT_EASYWATCH		0x003a
1197#define SUBID_DVBT_KNC1_PLUS		0x0031
1198#define SUBID_DVBT_KNC1			0x0030
1199#define SUBID_DVBT_CINERGY1200		0x1157
1200
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 type
1232		 */
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 2
1394static 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 saa7113
1527	.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)");
~/ Read-only file preview.