18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * descriptions + helper functions for simple dvb plls.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * (c) 2004 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/slab.h>
118c2ecf20Sopenharmony_ci#include <linux/module.h>
128c2ecf20Sopenharmony_ci#include <linux/idr.h>
138c2ecf20Sopenharmony_ci#include <linux/dvb/frontend.h>
148c2ecf20Sopenharmony_ci#include <asm/types.h>
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#include "dvb-pll.h"
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define dprintk(fmt, arg...) \
198c2ecf20Sopenharmony_ci	printk(KERN_DEBUG pr_fmt("%s: " fmt), __func__, ##arg)
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistruct dvb_pll_priv {
228c2ecf20Sopenharmony_ci	/* pll number */
238c2ecf20Sopenharmony_ci	int nr;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	/* i2c details */
268c2ecf20Sopenharmony_ci	int pll_i2c_address;
278c2ecf20Sopenharmony_ci	struct i2c_adapter *i2c;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	/* the PLL descriptor */
308c2ecf20Sopenharmony_ci	const struct dvb_pll_desc *pll_desc;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	/* cached frequency/bandwidth */
338c2ecf20Sopenharmony_ci	u32 frequency;
348c2ecf20Sopenharmony_ci	u32 bandwidth;
358c2ecf20Sopenharmony_ci};
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#define DVB_PLL_MAX 64
388c2ecf20Sopenharmony_cistatic DEFINE_IDA(pll_ida);
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_cistatic int debug;
418c2ecf20Sopenharmony_cimodule_param(debug, int, 0644);
428c2ecf20Sopenharmony_ciMODULE_PARM_DESC(debug, "enable verbose debug messages");
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_cistatic unsigned int id[DVB_PLL_MAX] =
458c2ecf20Sopenharmony_ci	{ [ 0 ... (DVB_PLL_MAX-1) ] = DVB_PLL_UNDEFINED };
468c2ecf20Sopenharmony_cimodule_param_array(id, int, NULL, 0644);
478c2ecf20Sopenharmony_ciMODULE_PARM_DESC(id, "force pll id to use (DEBUG ONLY)");
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci/* ----------------------------------------------------------- */
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_cistruct dvb_pll_desc {
528c2ecf20Sopenharmony_ci	const char *name;
538c2ecf20Sopenharmony_ci	u32  min;
548c2ecf20Sopenharmony_ci	u32  max;
558c2ecf20Sopenharmony_ci	u32  iffreq;
568c2ecf20Sopenharmony_ci	void (*set)(struct dvb_frontend *fe, u8 *buf);
578c2ecf20Sopenharmony_ci	u8   *initdata;
588c2ecf20Sopenharmony_ci	u8   *initdata2;
598c2ecf20Sopenharmony_ci	u8   *sleepdata;
608c2ecf20Sopenharmony_ci	int  count;
618c2ecf20Sopenharmony_ci	struct {
628c2ecf20Sopenharmony_ci		u32 limit;
638c2ecf20Sopenharmony_ci		u32 stepsize;
648c2ecf20Sopenharmony_ci		u8  config;
658c2ecf20Sopenharmony_ci		u8  cb;
668c2ecf20Sopenharmony_ci	} entries[];
678c2ecf20Sopenharmony_ci};
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_ci/* ----------------------------------------------------------- */
708c2ecf20Sopenharmony_ci/* descriptions                                                */
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {
738c2ecf20Sopenharmony_ci	.name  = "Thomson dtt7579",
748c2ecf20Sopenharmony_ci	.min   = 177 * MHz,
758c2ecf20Sopenharmony_ci	.max   = 858 * MHz,
768c2ecf20Sopenharmony_ci	.iffreq= 36166667,
778c2ecf20Sopenharmony_ci	.sleepdata = (u8[]){ 2, 0xb4, 0x03 },
788c2ecf20Sopenharmony_ci	.count = 4,
798c2ecf20Sopenharmony_ci	.entries = {
808c2ecf20Sopenharmony_ci		{  443250000, 166667, 0xb4, 0x02 },
818c2ecf20Sopenharmony_ci		{  542000000, 166667, 0xb4, 0x08 },
828c2ecf20Sopenharmony_ci		{  771000000, 166667, 0xbc, 0x08 },
838c2ecf20Sopenharmony_ci		{  999999999, 166667, 0xf4, 0x08 },
848c2ecf20Sopenharmony_ci	},
858c2ecf20Sopenharmony_ci};
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_cistatic void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	u32 bw = fe->dtv_property_cache.bandwidth_hz;
908c2ecf20Sopenharmony_ci	if (bw == 7000000)
918c2ecf20Sopenharmony_ci		buf[3] |= 0x10;
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
958c2ecf20Sopenharmony_ci	.name  = "Thomson dtt759x",
968c2ecf20Sopenharmony_ci	.min   = 177 * MHz,
978c2ecf20Sopenharmony_ci	.max   = 896 * MHz,
988c2ecf20Sopenharmony_ci	.set   = thomson_dtt759x_bw,
998c2ecf20Sopenharmony_ci	.iffreq= 36166667,
1008c2ecf20Sopenharmony_ci	.sleepdata = (u8[]){ 2, 0x84, 0x03 },
1018c2ecf20Sopenharmony_ci	.count = 5,
1028c2ecf20Sopenharmony_ci	.entries = {
1038c2ecf20Sopenharmony_ci		{  264000000, 166667, 0xb4, 0x02 },
1048c2ecf20Sopenharmony_ci		{  470000000, 166667, 0xbc, 0x02 },
1058c2ecf20Sopenharmony_ci		{  735000000, 166667, 0xbc, 0x08 },
1068c2ecf20Sopenharmony_ci		{  835000000, 166667, 0xf4, 0x08 },
1078c2ecf20Sopenharmony_ci		{  999999999, 166667, 0xfc, 0x08 },
1088c2ecf20Sopenharmony_ci	},
1098c2ecf20Sopenharmony_ci};
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cistatic void thomson_dtt7520x_bw(struct dvb_frontend *fe, u8 *buf)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	u32 bw = fe->dtv_property_cache.bandwidth_hz;
1148c2ecf20Sopenharmony_ci	if (bw == 8000000)
1158c2ecf20Sopenharmony_ci		buf[3] ^= 0x10;
1168c2ecf20Sopenharmony_ci}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
1198c2ecf20Sopenharmony_ci	.name  = "Thomson dtt7520x",
1208c2ecf20Sopenharmony_ci	.min   = 185 * MHz,
1218c2ecf20Sopenharmony_ci	.max   = 900 * MHz,
1228c2ecf20Sopenharmony_ci	.set   = thomson_dtt7520x_bw,
1238c2ecf20Sopenharmony_ci	.iffreq = 36166667,
1248c2ecf20Sopenharmony_ci	.count = 7,
1258c2ecf20Sopenharmony_ci	.entries = {
1268c2ecf20Sopenharmony_ci		{  305000000, 166667, 0xb4, 0x12 },
1278c2ecf20Sopenharmony_ci		{  405000000, 166667, 0xbc, 0x12 },
1288c2ecf20Sopenharmony_ci		{  445000000, 166667, 0xbc, 0x12 },
1298c2ecf20Sopenharmony_ci		{  465000000, 166667, 0xf4, 0x18 },
1308c2ecf20Sopenharmony_ci		{  735000000, 166667, 0xfc, 0x18 },
1318c2ecf20Sopenharmony_ci		{  835000000, 166667, 0xbc, 0x18 },
1328c2ecf20Sopenharmony_ci		{  999999999, 166667, 0xfc, 0x18 },
1338c2ecf20Sopenharmony_ci	},
1348c2ecf20Sopenharmony_ci};
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_lg_z201 = {
1378c2ecf20Sopenharmony_ci	.name  = "LG z201",
1388c2ecf20Sopenharmony_ci	.min   = 174 * MHz,
1398c2ecf20Sopenharmony_ci	.max   = 862 * MHz,
1408c2ecf20Sopenharmony_ci	.iffreq= 36166667,
1418c2ecf20Sopenharmony_ci	.sleepdata = (u8[]){ 2, 0xbc, 0x03 },
1428c2ecf20Sopenharmony_ci	.count = 5,
1438c2ecf20Sopenharmony_ci	.entries = {
1448c2ecf20Sopenharmony_ci		{  157500000, 166667, 0xbc, 0x01 },
1458c2ecf20Sopenharmony_ci		{  443250000, 166667, 0xbc, 0x02 },
1468c2ecf20Sopenharmony_ci		{  542000000, 166667, 0xbc, 0x04 },
1478c2ecf20Sopenharmony_ci		{  830000000, 166667, 0xf4, 0x04 },
1488c2ecf20Sopenharmony_ci		{  999999999, 166667, 0xfc, 0x04 },
1498c2ecf20Sopenharmony_ci	},
1508c2ecf20Sopenharmony_ci};
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_unknown_1 = {
1538c2ecf20Sopenharmony_ci	.name  = "unknown 1", /* used by dntv live dvb-t */
1548c2ecf20Sopenharmony_ci	.min   = 174 * MHz,
1558c2ecf20Sopenharmony_ci	.max   = 862 * MHz,
1568c2ecf20Sopenharmony_ci	.iffreq= 36166667,
1578c2ecf20Sopenharmony_ci	.count = 9,
1588c2ecf20Sopenharmony_ci	.entries = {
1598c2ecf20Sopenharmony_ci		{  150000000, 166667, 0xb4, 0x01 },
1608c2ecf20Sopenharmony_ci		{  173000000, 166667, 0xbc, 0x01 },
1618c2ecf20Sopenharmony_ci		{  250000000, 166667, 0xb4, 0x02 },
1628c2ecf20Sopenharmony_ci		{  400000000, 166667, 0xbc, 0x02 },
1638c2ecf20Sopenharmony_ci		{  420000000, 166667, 0xf4, 0x02 },
1648c2ecf20Sopenharmony_ci		{  470000000, 166667, 0xfc, 0x02 },
1658c2ecf20Sopenharmony_ci		{  600000000, 166667, 0xbc, 0x08 },
1668c2ecf20Sopenharmony_ci		{  730000000, 166667, 0xf4, 0x08 },
1678c2ecf20Sopenharmony_ci		{  999999999, 166667, 0xfc, 0x08 },
1688c2ecf20Sopenharmony_ci	},
1698c2ecf20Sopenharmony_ci};
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci/* Infineon TUA6010XS
1728c2ecf20Sopenharmony_ci * used in Thomson Cable Tuner
1738c2ecf20Sopenharmony_ci */
1748c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_tua6010xs = {
1758c2ecf20Sopenharmony_ci	.name  = "Infineon TUA6010XS",
1768c2ecf20Sopenharmony_ci	.min   = 44250 * kHz,
1778c2ecf20Sopenharmony_ci	.max   = 858 * MHz,
1788c2ecf20Sopenharmony_ci	.iffreq= 36125000,
1798c2ecf20Sopenharmony_ci	.count = 3,
1808c2ecf20Sopenharmony_ci	.entries = {
1818c2ecf20Sopenharmony_ci		{  115750000, 62500, 0x8e, 0x03 },
1828c2ecf20Sopenharmony_ci		{  403250000, 62500, 0x8e, 0x06 },
1838c2ecf20Sopenharmony_ci		{  999999999, 62500, 0x8e, 0x85 },
1848c2ecf20Sopenharmony_ci	},
1858c2ecf20Sopenharmony_ci};
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci/* Panasonic env57h1xd5 (some Philips PLL ?) */
1888c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_env57h1xd5 = {
1898c2ecf20Sopenharmony_ci	.name  = "Panasonic ENV57H1XD5",
1908c2ecf20Sopenharmony_ci	.min   = 44250 * kHz,
1918c2ecf20Sopenharmony_ci	.max   = 858 * MHz,
1928c2ecf20Sopenharmony_ci	.iffreq= 36125000,
1938c2ecf20Sopenharmony_ci	.count = 4,
1948c2ecf20Sopenharmony_ci	.entries = {
1958c2ecf20Sopenharmony_ci		{  153000000, 166667, 0xc2, 0x41 },
1968c2ecf20Sopenharmony_ci		{  470000000, 166667, 0xc2, 0x42 },
1978c2ecf20Sopenharmony_ci		{  526000000, 166667, 0xc2, 0x84 },
1988c2ecf20Sopenharmony_ci		{  999999999, 166667, 0xc2, 0xa4 },
1998c2ecf20Sopenharmony_ci	},
2008c2ecf20Sopenharmony_ci};
2018c2ecf20Sopenharmony_ci
2028c2ecf20Sopenharmony_ci/* Philips TDA6650/TDA6651
2038c2ecf20Sopenharmony_ci * used in Panasonic ENV77H11D5
2048c2ecf20Sopenharmony_ci */
2058c2ecf20Sopenharmony_cistatic void tda665x_bw(struct dvb_frontend *fe, u8 *buf)
2068c2ecf20Sopenharmony_ci{
2078c2ecf20Sopenharmony_ci	u32 bw = fe->dtv_property_cache.bandwidth_hz;
2088c2ecf20Sopenharmony_ci	if (bw == 8000000)
2098c2ecf20Sopenharmony_ci		buf[3] |= 0x08;
2108c2ecf20Sopenharmony_ci}
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_tda665x = {
2138c2ecf20Sopenharmony_ci	.name  = "Philips TDA6650/TDA6651",
2148c2ecf20Sopenharmony_ci	.min   = 44250 * kHz,
2158c2ecf20Sopenharmony_ci	.max   = 858 * MHz,
2168c2ecf20Sopenharmony_ci	.set   = tda665x_bw,
2178c2ecf20Sopenharmony_ci	.iffreq= 36166667,
2188c2ecf20Sopenharmony_ci	.initdata = (u8[]){ 4, 0x0b, 0xf5, 0x85, 0xab },
2198c2ecf20Sopenharmony_ci	.count = 12,
2208c2ecf20Sopenharmony_ci	.entries = {
2218c2ecf20Sopenharmony_ci		{   93834000, 166667, 0xca, 0x61 /* 011 0 0 0  01 */ },
2228c2ecf20Sopenharmony_ci		{  123834000, 166667, 0xca, 0xa1 /* 101 0 0 0  01 */ },
2238c2ecf20Sopenharmony_ci		{  161000000, 166667, 0xca, 0xa1 /* 101 0 0 0  01 */ },
2248c2ecf20Sopenharmony_ci		{  163834000, 166667, 0xca, 0xc2 /* 110 0 0 0  10 */ },
2258c2ecf20Sopenharmony_ci		{  253834000, 166667, 0xca, 0x62 /* 011 0 0 0  10 */ },
2268c2ecf20Sopenharmony_ci		{  383834000, 166667, 0xca, 0xa2 /* 101 0 0 0  10 */ },
2278c2ecf20Sopenharmony_ci		{  443834000, 166667, 0xca, 0xc2 /* 110 0 0 0  10 */ },
2288c2ecf20Sopenharmony_ci		{  444000000, 166667, 0xca, 0xc4 /* 110 0 0 1  00 */ },
2298c2ecf20Sopenharmony_ci		{  583834000, 166667, 0xca, 0x64 /* 011 0 0 1  00 */ },
2308c2ecf20Sopenharmony_ci		{  793834000, 166667, 0xca, 0xa4 /* 101 0 0 1  00 */ },
2318c2ecf20Sopenharmony_ci		{  444834000, 166667, 0xca, 0xc4 /* 110 0 0 1  00 */ },
2328c2ecf20Sopenharmony_ci		{  861000000, 166667, 0xca, 0xe4 /* 111 0 0 1  00 */ },
2338c2ecf20Sopenharmony_ci	}
2348c2ecf20Sopenharmony_ci};
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci/* Infineon TUA6034
2378c2ecf20Sopenharmony_ci * used in LG TDTP E102P
2388c2ecf20Sopenharmony_ci */
2398c2ecf20Sopenharmony_cistatic void tua6034_bw(struct dvb_frontend *fe, u8 *buf)
2408c2ecf20Sopenharmony_ci{
2418c2ecf20Sopenharmony_ci	u32 bw = fe->dtv_property_cache.bandwidth_hz;
2428c2ecf20Sopenharmony_ci	if (bw == 7000000)
2438c2ecf20Sopenharmony_ci		buf[3] |= 0x08;
2448c2ecf20Sopenharmony_ci}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_tua6034 = {
2478c2ecf20Sopenharmony_ci	.name  = "Infineon TUA6034",
2488c2ecf20Sopenharmony_ci	.min   = 44250 * kHz,
2498c2ecf20Sopenharmony_ci	.max   = 858 * MHz,
2508c2ecf20Sopenharmony_ci	.iffreq= 36166667,
2518c2ecf20Sopenharmony_ci	.count = 3,
2528c2ecf20Sopenharmony_ci	.set   = tua6034_bw,
2538c2ecf20Sopenharmony_ci	.entries = {
2548c2ecf20Sopenharmony_ci		{  174500000, 62500, 0xce, 0x01 },
2558c2ecf20Sopenharmony_ci		{  230000000, 62500, 0xce, 0x02 },
2568c2ecf20Sopenharmony_ci		{  999999999, 62500, 0xce, 0x04 },
2578c2ecf20Sopenharmony_ci	},
2588c2ecf20Sopenharmony_ci};
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci/* ALPS TDED4
2618c2ecf20Sopenharmony_ci * used in Nebula-Cards and USB boxes
2628c2ecf20Sopenharmony_ci */
2638c2ecf20Sopenharmony_cistatic void tded4_bw(struct dvb_frontend *fe, u8 *buf)
2648c2ecf20Sopenharmony_ci{
2658c2ecf20Sopenharmony_ci	u32 bw = fe->dtv_property_cache.bandwidth_hz;
2668c2ecf20Sopenharmony_ci	if (bw == 8000000)
2678c2ecf20Sopenharmony_ci		buf[3] |= 0x04;
2688c2ecf20Sopenharmony_ci}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_tded4 = {
2718c2ecf20Sopenharmony_ci	.name = "ALPS TDED4",
2728c2ecf20Sopenharmony_ci	.min =  47 * MHz,
2738c2ecf20Sopenharmony_ci	.max = 863 * MHz,
2748c2ecf20Sopenharmony_ci	.iffreq= 36166667,
2758c2ecf20Sopenharmony_ci	.set   = tded4_bw,
2768c2ecf20Sopenharmony_ci	.count = 4,
2778c2ecf20Sopenharmony_ci	.entries = {
2788c2ecf20Sopenharmony_ci		{ 153000000, 166667, 0x85, 0x01 },
2798c2ecf20Sopenharmony_ci		{ 470000000, 166667, 0x85, 0x02 },
2808c2ecf20Sopenharmony_ci		{ 823000000, 166667, 0x85, 0x08 },
2818c2ecf20Sopenharmony_ci		{ 999999999, 166667, 0x85, 0x88 },
2828c2ecf20Sopenharmony_ci	}
2838c2ecf20Sopenharmony_ci};
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci/* ALPS TDHU2
2868c2ecf20Sopenharmony_ci * used in AverTVHD MCE A180
2878c2ecf20Sopenharmony_ci */
2888c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_tdhu2 = {
2898c2ecf20Sopenharmony_ci	.name = "ALPS TDHU2",
2908c2ecf20Sopenharmony_ci	.min =  54 * MHz,
2918c2ecf20Sopenharmony_ci	.max = 864 * MHz,
2928c2ecf20Sopenharmony_ci	.iffreq= 44000000,
2938c2ecf20Sopenharmony_ci	.count = 4,
2948c2ecf20Sopenharmony_ci	.entries = {
2958c2ecf20Sopenharmony_ci		{ 162000000, 62500, 0x85, 0x01 },
2968c2ecf20Sopenharmony_ci		{ 426000000, 62500, 0x85, 0x02 },
2978c2ecf20Sopenharmony_ci		{ 782000000, 62500, 0x85, 0x08 },
2988c2ecf20Sopenharmony_ci		{ 999999999, 62500, 0x85, 0x88 },
2998c2ecf20Sopenharmony_ci	}
3008c2ecf20Sopenharmony_ci};
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci/* Samsung TBMV30111IN / TBMV30712IN1
3038c2ecf20Sopenharmony_ci * used in Air2PC ATSC - 2nd generation (nxt2002)
3048c2ecf20Sopenharmony_ci */
3058c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_samsung_tbmv = {
3068c2ecf20Sopenharmony_ci	.name = "Samsung TBMV30111IN / TBMV30712IN1",
3078c2ecf20Sopenharmony_ci	.min =  54 * MHz,
3088c2ecf20Sopenharmony_ci	.max = 860 * MHz,
3098c2ecf20Sopenharmony_ci	.iffreq= 44000000,
3108c2ecf20Sopenharmony_ci	.count = 6,
3118c2ecf20Sopenharmony_ci	.entries = {
3128c2ecf20Sopenharmony_ci		{ 172000000, 166667, 0xb4, 0x01 },
3138c2ecf20Sopenharmony_ci		{ 214000000, 166667, 0xb4, 0x02 },
3148c2ecf20Sopenharmony_ci		{ 467000000, 166667, 0xbc, 0x02 },
3158c2ecf20Sopenharmony_ci		{ 721000000, 166667, 0xbc, 0x08 },
3168c2ecf20Sopenharmony_ci		{ 841000000, 166667, 0xf4, 0x08 },
3178c2ecf20Sopenharmony_ci		{ 999999999, 166667, 0xfc, 0x02 },
3188c2ecf20Sopenharmony_ci	}
3198c2ecf20Sopenharmony_ci};
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci/*
3228c2ecf20Sopenharmony_ci * Philips SD1878 Tuner.
3238c2ecf20Sopenharmony_ci */
3248c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {
3258c2ecf20Sopenharmony_ci	.name  = "Philips SD1878",
3268c2ecf20Sopenharmony_ci	.min   =  950 * MHz,
3278c2ecf20Sopenharmony_ci	.max   = 2150 * MHz,
3288c2ecf20Sopenharmony_ci	.iffreq= 249, /* zero-IF, offset 249 is to round up */
3298c2ecf20Sopenharmony_ci	.count = 4,
3308c2ecf20Sopenharmony_ci	.entries = {
3318c2ecf20Sopenharmony_ci		{ 1250000, 500, 0xc4, 0x00},
3328c2ecf20Sopenharmony_ci		{ 1450000, 500, 0xc4, 0x40},
3338c2ecf20Sopenharmony_ci		{ 2050000, 500, 0xc4, 0x80},
3348c2ecf20Sopenharmony_ci		{ 2150000, 500, 0xc4, 0xc0},
3358c2ecf20Sopenharmony_ci	},
3368c2ecf20Sopenharmony_ci};
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_cistatic void opera1_bw(struct dvb_frontend *fe, u8 *buf)
3398c2ecf20Sopenharmony_ci{
3408c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
3418c2ecf20Sopenharmony_ci	struct dvb_pll_priv *priv = fe->tuner_priv;
3428c2ecf20Sopenharmony_ci	u32 b_w  = (c->symbol_rate * 27) / 32000;
3438c2ecf20Sopenharmony_ci	struct i2c_msg msg = {
3448c2ecf20Sopenharmony_ci		.addr = priv->pll_i2c_address,
3458c2ecf20Sopenharmony_ci		.flags = 0,
3468c2ecf20Sopenharmony_ci		.buf = buf,
3478c2ecf20Sopenharmony_ci		.len = 4
3488c2ecf20Sopenharmony_ci	};
3498c2ecf20Sopenharmony_ci	int result;
3508c2ecf20Sopenharmony_ci	u8 lpf;
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	if (fe->ops.i2c_gate_ctrl)
3538c2ecf20Sopenharmony_ci		fe->ops.i2c_gate_ctrl(fe, 1);
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	result = i2c_transfer(priv->i2c, &msg, 1);
3568c2ecf20Sopenharmony_ci	if (result != 1)
3578c2ecf20Sopenharmony_ci		pr_err("%s: i2c_transfer failed:%d",
3588c2ecf20Sopenharmony_ci			__func__, result);
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci	if (b_w <= 10000)
3618c2ecf20Sopenharmony_ci		lpf = 0xc;
3628c2ecf20Sopenharmony_ci	else if (b_w <= 12000)
3638c2ecf20Sopenharmony_ci		lpf = 0x2;
3648c2ecf20Sopenharmony_ci	else if (b_w <= 14000)
3658c2ecf20Sopenharmony_ci		lpf = 0xa;
3668c2ecf20Sopenharmony_ci	else if (b_w <= 16000)
3678c2ecf20Sopenharmony_ci		lpf = 0x6;
3688c2ecf20Sopenharmony_ci	else if (b_w <= 18000)
3698c2ecf20Sopenharmony_ci		lpf = 0xe;
3708c2ecf20Sopenharmony_ci	else if (b_w <= 20000)
3718c2ecf20Sopenharmony_ci		lpf = 0x1;
3728c2ecf20Sopenharmony_ci	else if (b_w <= 22000)
3738c2ecf20Sopenharmony_ci		lpf = 0x9;
3748c2ecf20Sopenharmony_ci	else if (b_w <= 24000)
3758c2ecf20Sopenharmony_ci		lpf = 0x5;
3768c2ecf20Sopenharmony_ci	else if (b_w <= 26000)
3778c2ecf20Sopenharmony_ci		lpf = 0xd;
3788c2ecf20Sopenharmony_ci	else if (b_w <= 28000)
3798c2ecf20Sopenharmony_ci		lpf = 0x3;
3808c2ecf20Sopenharmony_ci		else
3818c2ecf20Sopenharmony_ci		lpf = 0xb;
3828c2ecf20Sopenharmony_ci	buf[2] ^= 0x1c; /* Flip bits 3-5 */
3838c2ecf20Sopenharmony_ci	/* Set lpf */
3848c2ecf20Sopenharmony_ci	buf[2] |= ((lpf >> 2) & 0x3) << 3;
3858c2ecf20Sopenharmony_ci	buf[3] |= (lpf & 0x3) << 2;
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	return;
3888c2ecf20Sopenharmony_ci}
3898c2ecf20Sopenharmony_ci
3908c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_opera1 = {
3918c2ecf20Sopenharmony_ci	.name  = "Opera Tuner",
3928c2ecf20Sopenharmony_ci	.min   =  900 * MHz,
3938c2ecf20Sopenharmony_ci	.max   = 2250 * MHz,
3948c2ecf20Sopenharmony_ci	.initdata = (u8[]){ 4, 0x08, 0xe5, 0xe1, 0x00 },
3958c2ecf20Sopenharmony_ci	.initdata2 = (u8[]){ 4, 0x08, 0xe5, 0xe5, 0x00 },
3968c2ecf20Sopenharmony_ci	.iffreq= 0,
3978c2ecf20Sopenharmony_ci	.set   = opera1_bw,
3988c2ecf20Sopenharmony_ci	.count = 8,
3998c2ecf20Sopenharmony_ci	.entries = {
4008c2ecf20Sopenharmony_ci		{ 1064000, 500, 0xf9, 0xc2 },
4018c2ecf20Sopenharmony_ci		{ 1169000, 500, 0xf9, 0xe2 },
4028c2ecf20Sopenharmony_ci		{ 1299000, 500, 0xf9, 0x20 },
4038c2ecf20Sopenharmony_ci		{ 1444000, 500, 0xf9, 0x40 },
4048c2ecf20Sopenharmony_ci		{ 1606000, 500, 0xf9, 0x60 },
4058c2ecf20Sopenharmony_ci		{ 1777000, 500, 0xf9, 0x80 },
4068c2ecf20Sopenharmony_ci		{ 1941000, 500, 0xf9, 0xa0 },
4078c2ecf20Sopenharmony_ci		{ 2250000, 500, 0xf9, 0xc0 },
4088c2ecf20Sopenharmony_ci	}
4098c2ecf20Sopenharmony_ci};
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_cistatic void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf)
4128c2ecf20Sopenharmony_ci{
4138c2ecf20Sopenharmony_ci	struct dvb_pll_priv *priv = fe->tuner_priv;
4148c2ecf20Sopenharmony_ci	struct i2c_msg msg = {
4158c2ecf20Sopenharmony_ci		.addr = priv->pll_i2c_address,
4168c2ecf20Sopenharmony_ci		.flags = 0,
4178c2ecf20Sopenharmony_ci		.buf = buf,
4188c2ecf20Sopenharmony_ci		.len = 4
4198c2ecf20Sopenharmony_ci	};
4208c2ecf20Sopenharmony_ci	int result;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	if (fe->ops.i2c_gate_ctrl)
4238c2ecf20Sopenharmony_ci		fe->ops.i2c_gate_ctrl(fe, 1);
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	result = i2c_transfer(priv->i2c, &msg, 1);
4268c2ecf20Sopenharmony_ci	if (result != 1)
4278c2ecf20Sopenharmony_ci		pr_err("%s: i2c_transfer failed:%d",
4288c2ecf20Sopenharmony_ci			__func__, result);
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	buf[2] = 0x9e;
4318c2ecf20Sopenharmony_ci	buf[3] = 0x90;
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci	return;
4348c2ecf20Sopenharmony_ci}
4358c2ecf20Sopenharmony_ci
4368c2ecf20Sopenharmony_ci/* unknown pll used in Samsung DTOS403IH102A DVB-C tuner */
4378c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {
4388c2ecf20Sopenharmony_ci	.name   = "Samsung DTOS403IH102A",
4398c2ecf20Sopenharmony_ci	.min    = 44250 * kHz,
4408c2ecf20Sopenharmony_ci	.max    = 858 * MHz,
4418c2ecf20Sopenharmony_ci	.iffreq =  36125000,
4428c2ecf20Sopenharmony_ci	.count  = 8,
4438c2ecf20Sopenharmony_ci	.set    = samsung_dtos403ih102a_set,
4448c2ecf20Sopenharmony_ci	.entries = {
4458c2ecf20Sopenharmony_ci		{ 135000000, 62500, 0xbe, 0x01 },
4468c2ecf20Sopenharmony_ci		{ 177000000, 62500, 0xf6, 0x01 },
4478c2ecf20Sopenharmony_ci		{ 370000000, 62500, 0xbe, 0x02 },
4488c2ecf20Sopenharmony_ci		{ 450000000, 62500, 0xf6, 0x02 },
4498c2ecf20Sopenharmony_ci		{ 466000000, 62500, 0xfe, 0x02 },
4508c2ecf20Sopenharmony_ci		{ 538000000, 62500, 0xbe, 0x08 },
4518c2ecf20Sopenharmony_ci		{ 826000000, 62500, 0xf6, 0x08 },
4528c2ecf20Sopenharmony_ci		{ 999999999, 62500, 0xfe, 0x08 },
4538c2ecf20Sopenharmony_ci	}
4548c2ecf20Sopenharmony_ci};
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci/* Samsung TDTC9251DH0 DVB-T NIM, as used on AirStar 2 */
4578c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {
4588c2ecf20Sopenharmony_ci	.name	= "Samsung TDTC9251DH0",
4598c2ecf20Sopenharmony_ci	.min	=  48 * MHz,
4608c2ecf20Sopenharmony_ci	.max	= 863 * MHz,
4618c2ecf20Sopenharmony_ci	.iffreq	=  36166667,
4628c2ecf20Sopenharmony_ci	.count	= 3,
4638c2ecf20Sopenharmony_ci	.entries = {
4648c2ecf20Sopenharmony_ci		{ 157500000, 166667, 0xcc, 0x09 },
4658c2ecf20Sopenharmony_ci		{ 443000000, 166667, 0xcc, 0x0a },
4668c2ecf20Sopenharmony_ci		{ 863000000, 166667, 0xcc, 0x08 },
4678c2ecf20Sopenharmony_ci	}
4688c2ecf20Sopenharmony_ci};
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci/* Samsung TBDU18132 DVB-S NIM with TSA5059 PLL, used in SkyStar2 DVB-S 2.3 */
4718c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {
4728c2ecf20Sopenharmony_ci	.name = "Samsung TBDU18132",
4738c2ecf20Sopenharmony_ci	.min	=  950 * MHz,
4748c2ecf20Sopenharmony_ci	.max	= 2150 * MHz, /* guesses */
4758c2ecf20Sopenharmony_ci	.iffreq = 0,
4768c2ecf20Sopenharmony_ci	.count = 2,
4778c2ecf20Sopenharmony_ci	.entries = {
4788c2ecf20Sopenharmony_ci		{ 1550000, 125, 0x84, 0x82 },
4798c2ecf20Sopenharmony_ci		{ 4095937, 125, 0x84, 0x80 },
4808c2ecf20Sopenharmony_ci	}
4818c2ecf20Sopenharmony_ci	/* TSA5059 PLL has a 17 bit divisor rather than the 15 bits supported
4828c2ecf20Sopenharmony_ci	 * by this driver.  The two extra bits are 0x60 in the third byte.  15
4838c2ecf20Sopenharmony_ci	 * bits is enough for over 4 GHz, which is enough to cover the range
4848c2ecf20Sopenharmony_ci	 * of this tuner.  We could use the additional divisor bits by adding
4858c2ecf20Sopenharmony_ci	 * more entries, e.g.
4868c2ecf20Sopenharmony_ci	 { 0x0ffff * 125 + 125/2, 125, 0x84 | 0x20, },
4878c2ecf20Sopenharmony_ci	 { 0x17fff * 125 + 125/2, 125, 0x84 | 0x40, },
4888c2ecf20Sopenharmony_ci	 { 0x1ffff * 125 + 125/2, 125, 0x84 | 0x60, }, */
4898c2ecf20Sopenharmony_ci};
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci/* Samsung TBMU24112 DVB-S NIM with SL1935 zero-IF tuner */
4928c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {
4938c2ecf20Sopenharmony_ci	.name = "Samsung TBMU24112",
4948c2ecf20Sopenharmony_ci	.min	=  950 * MHz,
4958c2ecf20Sopenharmony_ci	.max	= 2150 * MHz, /* guesses */
4968c2ecf20Sopenharmony_ci	.iffreq = 0,
4978c2ecf20Sopenharmony_ci	.count = 2,
4988c2ecf20Sopenharmony_ci	.entries = {
4998c2ecf20Sopenharmony_ci		{ 1500000, 125, 0x84, 0x18 },
5008c2ecf20Sopenharmony_ci		{ 9999999, 125, 0x84, 0x08 },
5018c2ecf20Sopenharmony_ci	}
5028c2ecf20Sopenharmony_ci};
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci/* Alps TDEE4 DVB-C NIM, used on Cablestar 2 */
5058c2ecf20Sopenharmony_ci/* byte 4 : 1  *   *   AGD R3  R2  R1  R0
5068c2ecf20Sopenharmony_ci * byte 5 : C1 *   RE  RTS BS4 BS3 BS2 BS1
5078c2ecf20Sopenharmony_ci * AGD = 1, R3 R2 R1 R0 = 0 1 0 1 => byte 4 = 1**10101 = 0x95
5088c2ecf20Sopenharmony_ci * Range(MHz)  C1 *  RE RTS BS4 BS3 BS2 BS1  Byte 5
5098c2ecf20Sopenharmony_ci *  47 - 153   0  *  0   0   0   0   0   1   0x01
5108c2ecf20Sopenharmony_ci * 153 - 430   0  *  0   0   0   0   1   0   0x02
5118c2ecf20Sopenharmony_ci * 430 - 822   0  *  0   0   1   0   0   0   0x08
5128c2ecf20Sopenharmony_ci * 822 - 862   1  *  0   0   1   0   0   0   0x88 */
5138c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_alps_tdee4 = {
5148c2ecf20Sopenharmony_ci	.name = "ALPS TDEE4",
5158c2ecf20Sopenharmony_ci	.min	=  47 * MHz,
5168c2ecf20Sopenharmony_ci	.max	= 862 * MHz,
5178c2ecf20Sopenharmony_ci	.iffreq	=  36125000,
5188c2ecf20Sopenharmony_ci	.count = 4,
5198c2ecf20Sopenharmony_ci	.entries = {
5208c2ecf20Sopenharmony_ci		{ 153000000, 62500, 0x95, 0x01 },
5218c2ecf20Sopenharmony_ci		{ 430000000, 62500, 0x95, 0x02 },
5228c2ecf20Sopenharmony_ci		{ 822000000, 62500, 0x95, 0x08 },
5238c2ecf20Sopenharmony_ci		{ 999999999, 62500, 0x95, 0x88 },
5248c2ecf20Sopenharmony_ci	}
5258c2ecf20Sopenharmony_ci};
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci/* Infineon TUA6034 ISDB-T, used in Friio */
5288c2ecf20Sopenharmony_ci/* CP cur. 50uA, AGC takeover: 103dBuV, PORT3 on */
5298c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_tua6034_friio = {
5308c2ecf20Sopenharmony_ci	.name   = "Infineon TUA6034 ISDB-T (Friio)",
5318c2ecf20Sopenharmony_ci	.min    =  90 * MHz,
5328c2ecf20Sopenharmony_ci	.max    = 770 * MHz,
5338c2ecf20Sopenharmony_ci	.iffreq =  57000000,
5348c2ecf20Sopenharmony_ci	.initdata = (u8[]){ 4, 0x9a, 0x50, 0xb2, 0x08 },
5358c2ecf20Sopenharmony_ci	.sleepdata = (u8[]){ 4, 0x9a, 0x70, 0xb3, 0x0b },
5368c2ecf20Sopenharmony_ci	.count = 3,
5378c2ecf20Sopenharmony_ci	.entries = {
5388c2ecf20Sopenharmony_ci		{ 170000000, 142857, 0xba, 0x09 },
5398c2ecf20Sopenharmony_ci		{ 470000000, 142857, 0xba, 0x0a },
5408c2ecf20Sopenharmony_ci		{ 770000000, 142857, 0xb2, 0x08 },
5418c2ecf20Sopenharmony_ci	}
5428c2ecf20Sopenharmony_ci};
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci/* Philips TDA6651 ISDB-T, used in Earthsoft PT1 */
5458c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc dvb_pll_tda665x_earth_pt1 = {
5468c2ecf20Sopenharmony_ci	.name   = "Philips TDA6651 ISDB-T (EarthSoft PT1)",
5478c2ecf20Sopenharmony_ci	.min    =  90 * MHz,
5488c2ecf20Sopenharmony_ci	.max    = 770 * MHz,
5498c2ecf20Sopenharmony_ci	.iffreq =  57000000,
5508c2ecf20Sopenharmony_ci	.initdata = (u8[]){ 5, 0x0e, 0x7f, 0xc1, 0x80, 0x80 },
5518c2ecf20Sopenharmony_ci	.count = 10,
5528c2ecf20Sopenharmony_ci	.entries = {
5538c2ecf20Sopenharmony_ci		{ 140000000, 142857, 0xc1, 0x81 },
5548c2ecf20Sopenharmony_ci		{ 170000000, 142857, 0xc1, 0xa1 },
5558c2ecf20Sopenharmony_ci		{ 220000000, 142857, 0xc1, 0x62 },
5568c2ecf20Sopenharmony_ci		{ 330000000, 142857, 0xc1, 0xa2 },
5578c2ecf20Sopenharmony_ci		{ 402000000, 142857, 0xc1, 0xe2 },
5588c2ecf20Sopenharmony_ci		{ 450000000, 142857, 0xc1, 0x64 },
5598c2ecf20Sopenharmony_ci		{ 550000000, 142857, 0xc1, 0x84 },
5608c2ecf20Sopenharmony_ci		{ 600000000, 142857, 0xc1, 0xa4 },
5618c2ecf20Sopenharmony_ci		{ 700000000, 142857, 0xc1, 0xc4 },
5628c2ecf20Sopenharmony_ci		{ 770000000, 142857, 0xc1, 0xe4 },
5638c2ecf20Sopenharmony_ci	}
5648c2ecf20Sopenharmony_ci};
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci/* ----------------------------------------------------------- */
5678c2ecf20Sopenharmony_ci
5688c2ecf20Sopenharmony_cistatic const struct dvb_pll_desc *pll_list[] = {
5698c2ecf20Sopenharmony_ci	[DVB_PLL_UNDEFINED]              = NULL,
5708c2ecf20Sopenharmony_ci	[DVB_PLL_THOMSON_DTT7579]        = &dvb_pll_thomson_dtt7579,
5718c2ecf20Sopenharmony_ci	[DVB_PLL_THOMSON_DTT759X]        = &dvb_pll_thomson_dtt759x,
5728c2ecf20Sopenharmony_ci	[DVB_PLL_THOMSON_DTT7520X]       = &dvb_pll_thomson_dtt7520x,
5738c2ecf20Sopenharmony_ci	[DVB_PLL_LG_Z201]                = &dvb_pll_lg_z201,
5748c2ecf20Sopenharmony_ci	[DVB_PLL_UNKNOWN_1]              = &dvb_pll_unknown_1,
5758c2ecf20Sopenharmony_ci	[DVB_PLL_TUA6010XS]              = &dvb_pll_tua6010xs,
5768c2ecf20Sopenharmony_ci	[DVB_PLL_ENV57H1XD5]             = &dvb_pll_env57h1xd5,
5778c2ecf20Sopenharmony_ci	[DVB_PLL_TUA6034]                = &dvb_pll_tua6034,
5788c2ecf20Sopenharmony_ci	[DVB_PLL_TDA665X]                = &dvb_pll_tda665x,
5798c2ecf20Sopenharmony_ci	[DVB_PLL_TDED4]                  = &dvb_pll_tded4,
5808c2ecf20Sopenharmony_ci	[DVB_PLL_TDEE4]                  = &dvb_pll_alps_tdee4,
5818c2ecf20Sopenharmony_ci	[DVB_PLL_TDHU2]                  = &dvb_pll_tdhu2,
5828c2ecf20Sopenharmony_ci	[DVB_PLL_SAMSUNG_TBMV]           = &dvb_pll_samsung_tbmv,
5838c2ecf20Sopenharmony_ci	[DVB_PLL_PHILIPS_SD1878_TDA8261] = &dvb_pll_philips_sd1878_tda8261,
5848c2ecf20Sopenharmony_ci	[DVB_PLL_OPERA1]                 = &dvb_pll_opera1,
5858c2ecf20Sopenharmony_ci	[DVB_PLL_SAMSUNG_DTOS403IH102A]  = &dvb_pll_samsung_dtos403ih102a,
5868c2ecf20Sopenharmony_ci	[DVB_PLL_SAMSUNG_TDTC9251DH0]    = &dvb_pll_samsung_tdtc9251dh0,
5878c2ecf20Sopenharmony_ci	[DVB_PLL_SAMSUNG_TBDU18132]	 = &dvb_pll_samsung_tbdu18132,
5888c2ecf20Sopenharmony_ci	[DVB_PLL_SAMSUNG_TBMU24112]      = &dvb_pll_samsung_tbmu24112,
5898c2ecf20Sopenharmony_ci	[DVB_PLL_TUA6034_FRIIO]          = &dvb_pll_tua6034_friio,
5908c2ecf20Sopenharmony_ci	[DVB_PLL_TDA665X_EARTH_PT1]      = &dvb_pll_tda665x_earth_pt1,
5918c2ecf20Sopenharmony_ci};
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci/* ----------------------------------------------------------- */
5948c2ecf20Sopenharmony_ci/* code                                                        */
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_cistatic int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,
5978c2ecf20Sopenharmony_ci			     const u32 frequency)
5988c2ecf20Sopenharmony_ci{
5998c2ecf20Sopenharmony_ci	struct dvb_pll_priv *priv = fe->tuner_priv;
6008c2ecf20Sopenharmony_ci	const struct dvb_pll_desc *desc = priv->pll_desc;
6018c2ecf20Sopenharmony_ci	u32 div;
6028c2ecf20Sopenharmony_ci	int i;
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci	for (i = 0; i < desc->count; i++) {
6058c2ecf20Sopenharmony_ci		if (frequency > desc->entries[i].limit)
6068c2ecf20Sopenharmony_ci			continue;
6078c2ecf20Sopenharmony_ci		break;
6088c2ecf20Sopenharmony_ci	}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	if (debug)
6118c2ecf20Sopenharmony_ci		dprintk("pll: %s: freq=%d | i=%d/%d\n", desc->name,
6128c2ecf20Sopenharmony_ci		       frequency, i, desc->count);
6138c2ecf20Sopenharmony_ci	if (i == desc->count)
6148c2ecf20Sopenharmony_ci		return -EINVAL;
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci	div = (frequency + desc->iffreq +
6178c2ecf20Sopenharmony_ci	       desc->entries[i].stepsize/2) / desc->entries[i].stepsize;
6188c2ecf20Sopenharmony_ci	buf[0] = div >> 8;
6198c2ecf20Sopenharmony_ci	buf[1] = div & 0xff;
6208c2ecf20Sopenharmony_ci	buf[2] = desc->entries[i].config;
6218c2ecf20Sopenharmony_ci	buf[3] = desc->entries[i].cb;
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	if (desc->set)
6248c2ecf20Sopenharmony_ci		desc->set(fe, buf);
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	if (debug)
6278c2ecf20Sopenharmony_ci		dprintk("pll: %s: div=%d | buf=0x%02x,0x%02x,0x%02x,0x%02x\n",
6288c2ecf20Sopenharmony_ci		       desc->name, div, buf[0], buf[1], buf[2], buf[3]);
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	// calculate the frequency we set it to
6318c2ecf20Sopenharmony_ci	return (div * desc->entries[i].stepsize) - desc->iffreq;
6328c2ecf20Sopenharmony_ci}
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_cistatic void dvb_pll_release(struct dvb_frontend *fe)
6358c2ecf20Sopenharmony_ci{
6368c2ecf20Sopenharmony_ci	kfree(fe->tuner_priv);
6378c2ecf20Sopenharmony_ci	fe->tuner_priv = NULL;
6388c2ecf20Sopenharmony_ci}
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_cistatic int dvb_pll_sleep(struct dvb_frontend *fe)
6418c2ecf20Sopenharmony_ci{
6428c2ecf20Sopenharmony_ci	struct dvb_pll_priv *priv = fe->tuner_priv;
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	if (priv->i2c == NULL)
6458c2ecf20Sopenharmony_ci		return -EINVAL;
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	if (priv->pll_desc->sleepdata) {
6488c2ecf20Sopenharmony_ci		struct i2c_msg msg = { .flags = 0,
6498c2ecf20Sopenharmony_ci			.addr = priv->pll_i2c_address,
6508c2ecf20Sopenharmony_ci			.buf = priv->pll_desc->sleepdata + 1,
6518c2ecf20Sopenharmony_ci			.len = priv->pll_desc->sleepdata[0] };
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci		int result;
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci		if (fe->ops.i2c_gate_ctrl)
6568c2ecf20Sopenharmony_ci			fe->ops.i2c_gate_ctrl(fe, 1);
6578c2ecf20Sopenharmony_ci		if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
6588c2ecf20Sopenharmony_ci			return result;
6598c2ecf20Sopenharmony_ci		}
6608c2ecf20Sopenharmony_ci		return 0;
6618c2ecf20Sopenharmony_ci	}
6628c2ecf20Sopenharmony_ci	/* Shouldn't be called when initdata is NULL, maybe BUG()? */
6638c2ecf20Sopenharmony_ci	return -EINVAL;
6648c2ecf20Sopenharmony_ci}
6658c2ecf20Sopenharmony_ci
6668c2ecf20Sopenharmony_cistatic int dvb_pll_set_params(struct dvb_frontend *fe)
6678c2ecf20Sopenharmony_ci{
6688c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
6698c2ecf20Sopenharmony_ci	struct dvb_pll_priv *priv = fe->tuner_priv;
6708c2ecf20Sopenharmony_ci	u8 buf[4];
6718c2ecf20Sopenharmony_ci	struct i2c_msg msg =
6728c2ecf20Sopenharmony_ci		{ .addr = priv->pll_i2c_address, .flags = 0,
6738c2ecf20Sopenharmony_ci		  .buf = buf, .len = sizeof(buf) };
6748c2ecf20Sopenharmony_ci	int result;
6758c2ecf20Sopenharmony_ci	u32 frequency = 0;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	if (priv->i2c == NULL)
6788c2ecf20Sopenharmony_ci		return -EINVAL;
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	result = dvb_pll_configure(fe, buf, c->frequency);
6818c2ecf20Sopenharmony_ci	if (result < 0)
6828c2ecf20Sopenharmony_ci		return result;
6838c2ecf20Sopenharmony_ci	else
6848c2ecf20Sopenharmony_ci		frequency = result;
6858c2ecf20Sopenharmony_ci
6868c2ecf20Sopenharmony_ci	if (fe->ops.i2c_gate_ctrl)
6878c2ecf20Sopenharmony_ci		fe->ops.i2c_gate_ctrl(fe, 1);
6888c2ecf20Sopenharmony_ci	if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
6898c2ecf20Sopenharmony_ci		return result;
6908c2ecf20Sopenharmony_ci	}
6918c2ecf20Sopenharmony_ci
6928c2ecf20Sopenharmony_ci	priv->frequency = frequency;
6938c2ecf20Sopenharmony_ci	priv->bandwidth = c->bandwidth_hz;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_ci	return 0;
6968c2ecf20Sopenharmony_ci}
6978c2ecf20Sopenharmony_ci
6988c2ecf20Sopenharmony_cistatic int dvb_pll_calc_regs(struct dvb_frontend *fe,
6998c2ecf20Sopenharmony_ci			     u8 *buf, int buf_len)
7008c2ecf20Sopenharmony_ci{
7018c2ecf20Sopenharmony_ci	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
7028c2ecf20Sopenharmony_ci	struct dvb_pll_priv *priv = fe->tuner_priv;
7038c2ecf20Sopenharmony_ci	int result;
7048c2ecf20Sopenharmony_ci	u32 frequency = 0;
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	if (buf_len < 5)
7078c2ecf20Sopenharmony_ci		return -EINVAL;
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	result = dvb_pll_configure(fe, buf + 1, c->frequency);
7108c2ecf20Sopenharmony_ci	if (result < 0)
7118c2ecf20Sopenharmony_ci		return result;
7128c2ecf20Sopenharmony_ci	else
7138c2ecf20Sopenharmony_ci		frequency = result;
7148c2ecf20Sopenharmony_ci
7158c2ecf20Sopenharmony_ci	buf[0] = priv->pll_i2c_address;
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	priv->frequency = frequency;
7188c2ecf20Sopenharmony_ci	priv->bandwidth = c->bandwidth_hz;
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	return 5;
7218c2ecf20Sopenharmony_ci}
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_cistatic int dvb_pll_get_frequency(struct dvb_frontend *fe, u32 *frequency)
7248c2ecf20Sopenharmony_ci{
7258c2ecf20Sopenharmony_ci	struct dvb_pll_priv *priv = fe->tuner_priv;
7268c2ecf20Sopenharmony_ci	*frequency = priv->frequency;
7278c2ecf20Sopenharmony_ci	return 0;
7288c2ecf20Sopenharmony_ci}
7298c2ecf20Sopenharmony_ci
7308c2ecf20Sopenharmony_cistatic int dvb_pll_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
7318c2ecf20Sopenharmony_ci{
7328c2ecf20Sopenharmony_ci	struct dvb_pll_priv *priv = fe->tuner_priv;
7338c2ecf20Sopenharmony_ci	*bandwidth = priv->bandwidth;
7348c2ecf20Sopenharmony_ci	return 0;
7358c2ecf20Sopenharmony_ci}
7368c2ecf20Sopenharmony_ci
7378c2ecf20Sopenharmony_cistatic int dvb_pll_init(struct dvb_frontend *fe)
7388c2ecf20Sopenharmony_ci{
7398c2ecf20Sopenharmony_ci	struct dvb_pll_priv *priv = fe->tuner_priv;
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	if (priv->i2c == NULL)
7428c2ecf20Sopenharmony_ci		return -EINVAL;
7438c2ecf20Sopenharmony_ci
7448c2ecf20Sopenharmony_ci	if (priv->pll_desc->initdata) {
7458c2ecf20Sopenharmony_ci		struct i2c_msg msg = { .flags = 0,
7468c2ecf20Sopenharmony_ci			.addr = priv->pll_i2c_address,
7478c2ecf20Sopenharmony_ci			.buf = priv->pll_desc->initdata + 1,
7488c2ecf20Sopenharmony_ci			.len = priv->pll_desc->initdata[0] };
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci		int result;
7518c2ecf20Sopenharmony_ci		if (fe->ops.i2c_gate_ctrl)
7528c2ecf20Sopenharmony_ci			fe->ops.i2c_gate_ctrl(fe, 1);
7538c2ecf20Sopenharmony_ci		result = i2c_transfer(priv->i2c, &msg, 1);
7548c2ecf20Sopenharmony_ci		if (result != 1)
7558c2ecf20Sopenharmony_ci			return result;
7568c2ecf20Sopenharmony_ci		if (priv->pll_desc->initdata2) {
7578c2ecf20Sopenharmony_ci			msg.buf = priv->pll_desc->initdata2 + 1;
7588c2ecf20Sopenharmony_ci			msg.len = priv->pll_desc->initdata2[0];
7598c2ecf20Sopenharmony_ci			if (fe->ops.i2c_gate_ctrl)
7608c2ecf20Sopenharmony_ci				fe->ops.i2c_gate_ctrl(fe, 1);
7618c2ecf20Sopenharmony_ci			result = i2c_transfer(priv->i2c, &msg, 1);
7628c2ecf20Sopenharmony_ci			if (result != 1)
7638c2ecf20Sopenharmony_ci				return result;
7648c2ecf20Sopenharmony_ci		}
7658c2ecf20Sopenharmony_ci		return 0;
7668c2ecf20Sopenharmony_ci	}
7678c2ecf20Sopenharmony_ci	/* Shouldn't be called when initdata is NULL, maybe BUG()? */
7688c2ecf20Sopenharmony_ci	return -EINVAL;
7698c2ecf20Sopenharmony_ci}
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_cistatic const struct dvb_tuner_ops dvb_pll_tuner_ops = {
7728c2ecf20Sopenharmony_ci	.release = dvb_pll_release,
7738c2ecf20Sopenharmony_ci	.sleep = dvb_pll_sleep,
7748c2ecf20Sopenharmony_ci	.init = dvb_pll_init,
7758c2ecf20Sopenharmony_ci	.set_params = dvb_pll_set_params,
7768c2ecf20Sopenharmony_ci	.calc_regs = dvb_pll_calc_regs,
7778c2ecf20Sopenharmony_ci	.get_frequency = dvb_pll_get_frequency,
7788c2ecf20Sopenharmony_ci	.get_bandwidth = dvb_pll_get_bandwidth,
7798c2ecf20Sopenharmony_ci};
7808c2ecf20Sopenharmony_ci
7818c2ecf20Sopenharmony_cistruct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,
7828c2ecf20Sopenharmony_ci				    struct i2c_adapter *i2c,
7838c2ecf20Sopenharmony_ci				    unsigned int pll_desc_id)
7848c2ecf20Sopenharmony_ci{
7858c2ecf20Sopenharmony_ci	u8 *b1;
7868c2ecf20Sopenharmony_ci	struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .len = 1 };
7878c2ecf20Sopenharmony_ci	struct dvb_pll_priv *priv = NULL;
7888c2ecf20Sopenharmony_ci	int ret;
7898c2ecf20Sopenharmony_ci	const struct dvb_pll_desc *desc;
7908c2ecf20Sopenharmony_ci	int nr;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	b1 = kmalloc(1, GFP_KERNEL);
7938c2ecf20Sopenharmony_ci	if (!b1)
7948c2ecf20Sopenharmony_ci		return NULL;
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_ci	b1[0] = 0;
7978c2ecf20Sopenharmony_ci	msg.buf = b1;
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_ci	nr = ida_simple_get(&pll_ida, 0, DVB_PLL_MAX, GFP_KERNEL);
8008c2ecf20Sopenharmony_ci	if (nr < 0) {
8018c2ecf20Sopenharmony_ci		kfree(b1);
8028c2ecf20Sopenharmony_ci		return NULL;
8038c2ecf20Sopenharmony_ci	}
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_ci	if (id[nr] > DVB_PLL_UNDEFINED && id[nr] < ARRAY_SIZE(pll_list))
8068c2ecf20Sopenharmony_ci		pll_desc_id = id[nr];
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	BUG_ON(pll_desc_id < 1 || pll_desc_id >= ARRAY_SIZE(pll_list));
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci	desc = pll_list[pll_desc_id];
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	if (i2c != NULL) {
8138c2ecf20Sopenharmony_ci		if (fe->ops.i2c_gate_ctrl)
8148c2ecf20Sopenharmony_ci			fe->ops.i2c_gate_ctrl(fe, 1);
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci		ret = i2c_transfer (i2c, &msg, 1);
8178c2ecf20Sopenharmony_ci		if (ret != 1)
8188c2ecf20Sopenharmony_ci			goto out;
8198c2ecf20Sopenharmony_ci		if (fe->ops.i2c_gate_ctrl)
8208c2ecf20Sopenharmony_ci			     fe->ops.i2c_gate_ctrl(fe, 0);
8218c2ecf20Sopenharmony_ci	}
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL);
8248c2ecf20Sopenharmony_ci	if (!priv)
8258c2ecf20Sopenharmony_ci		goto out;
8268c2ecf20Sopenharmony_ci
8278c2ecf20Sopenharmony_ci	priv->pll_i2c_address = pll_addr;
8288c2ecf20Sopenharmony_ci	priv->i2c = i2c;
8298c2ecf20Sopenharmony_ci	priv->pll_desc = desc;
8308c2ecf20Sopenharmony_ci	priv->nr = nr;
8318c2ecf20Sopenharmony_ci
8328c2ecf20Sopenharmony_ci	memcpy(&fe->ops.tuner_ops, &dvb_pll_tuner_ops,
8338c2ecf20Sopenharmony_ci	       sizeof(struct dvb_tuner_ops));
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ci	strscpy(fe->ops.tuner_ops.info.name, desc->name,
8368c2ecf20Sopenharmony_ci		sizeof(fe->ops.tuner_ops.info.name));
8378c2ecf20Sopenharmony_ci
8388c2ecf20Sopenharmony_ci	fe->ops.tuner_ops.info.frequency_min_hz = desc->min;
8398c2ecf20Sopenharmony_ci	fe->ops.tuner_ops.info.frequency_max_hz = desc->max;
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	dprintk("%s tuner, frequency range: %u...%u\n",
8428c2ecf20Sopenharmony_ci		desc->name, desc->min, desc->max);
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_ci	if (!desc->initdata)
8458c2ecf20Sopenharmony_ci		fe->ops.tuner_ops.init = NULL;
8468c2ecf20Sopenharmony_ci	if (!desc->sleepdata)
8478c2ecf20Sopenharmony_ci		fe->ops.tuner_ops.sleep = NULL;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	fe->tuner_priv = priv;
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	if ((debug) || (id[priv->nr] == pll_desc_id)) {
8528c2ecf20Sopenharmony_ci		dprintk("dvb-pll[%d]", priv->nr);
8538c2ecf20Sopenharmony_ci		if (i2c != NULL)
8548c2ecf20Sopenharmony_ci			pr_cont(" %d-%04x", i2c_adapter_id(i2c), pll_addr);
8558c2ecf20Sopenharmony_ci		pr_cont(": id# %d (%s) attached, %s\n", pll_desc_id, desc->name,
8568c2ecf20Sopenharmony_ci		       id[priv->nr] == pll_desc_id ?
8578c2ecf20Sopenharmony_ci				"insmod option" : "autodetected");
8588c2ecf20Sopenharmony_ci	}
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	kfree(b1);
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci	return fe;
8638c2ecf20Sopenharmony_ciout:
8648c2ecf20Sopenharmony_ci	kfree(b1);
8658c2ecf20Sopenharmony_ci	ida_simple_remove(&pll_ida, nr);
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci	return NULL;
8688c2ecf20Sopenharmony_ci}
8698c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(dvb_pll_attach);
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_cistatic int
8738c2ecf20Sopenharmony_cidvb_pll_probe(struct i2c_client *client, const struct i2c_device_id *id)
8748c2ecf20Sopenharmony_ci{
8758c2ecf20Sopenharmony_ci	struct dvb_pll_config *cfg;
8768c2ecf20Sopenharmony_ci	struct dvb_frontend *fe;
8778c2ecf20Sopenharmony_ci	unsigned int desc_id;
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci	cfg = client->dev.platform_data;
8808c2ecf20Sopenharmony_ci	fe = cfg->fe;
8818c2ecf20Sopenharmony_ci	i2c_set_clientdata(client, fe);
8828c2ecf20Sopenharmony_ci	desc_id = (unsigned int) id->driver_data;
8838c2ecf20Sopenharmony_ci
8848c2ecf20Sopenharmony_ci	if (!dvb_pll_attach(fe, client->addr, client->adapter, desc_id))
8858c2ecf20Sopenharmony_ci		return -ENOMEM;
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	/*
8888c2ecf20Sopenharmony_ci	 * Unset tuner_ops.release (== dvb_pll_release)
8898c2ecf20Sopenharmony_ci	 * which has been just set in the above dvb_pll_attach(),
8908c2ecf20Sopenharmony_ci	 * because if tuner_ops.release was left defined,
8918c2ecf20Sopenharmony_ci	 * this module would be 'put' twice on exit:
8928c2ecf20Sopenharmony_ci	 * once by dvb_frontend_detach() and another by dvb_module_release().
8938c2ecf20Sopenharmony_ci	 *
8948c2ecf20Sopenharmony_ci	 * dvb_pll_release is instead executed in the i2c driver's .remove(),
8958c2ecf20Sopenharmony_ci	 * keeping dvb_pll_attach untouched for legacy (dvb_attach) drivers.
8968c2ecf20Sopenharmony_ci	 */
8978c2ecf20Sopenharmony_ci	fe->ops.tuner_ops.release = NULL;
8988c2ecf20Sopenharmony_ci	dev_info(&client->dev, "DVB Simple Tuner attached.\n");
8998c2ecf20Sopenharmony_ci	return 0;
9008c2ecf20Sopenharmony_ci}
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_cistatic int dvb_pll_remove(struct i2c_client *client)
9038c2ecf20Sopenharmony_ci{
9048c2ecf20Sopenharmony_ci	struct dvb_frontend *fe = i2c_get_clientdata(client);
9058c2ecf20Sopenharmony_ci	struct dvb_pll_priv *priv = fe->tuner_priv;
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_ci	ida_simple_remove(&pll_ida, priv->nr);
9088c2ecf20Sopenharmony_ci	dvb_pll_release(fe);
9098c2ecf20Sopenharmony_ci	return 0;
9108c2ecf20Sopenharmony_ci}
9118c2ecf20Sopenharmony_ci
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_cistatic const struct i2c_device_id dvb_pll_id[] = {
9148c2ecf20Sopenharmony_ci	{"dtt7579",		DVB_PLL_THOMSON_DTT7579},
9158c2ecf20Sopenharmony_ci	{"dtt759x",		DVB_PLL_THOMSON_DTT759X},
9168c2ecf20Sopenharmony_ci	{"z201",		DVB_PLL_LG_Z201},
9178c2ecf20Sopenharmony_ci	{"unknown_1",		DVB_PLL_UNKNOWN_1},
9188c2ecf20Sopenharmony_ci	{"tua6010xs",		DVB_PLL_TUA6010XS},
9198c2ecf20Sopenharmony_ci	{"env57h1xd5",		DVB_PLL_ENV57H1XD5},
9208c2ecf20Sopenharmony_ci	{"tua6034",		DVB_PLL_TUA6034},
9218c2ecf20Sopenharmony_ci	{"tda665x",		DVB_PLL_TDA665X},
9228c2ecf20Sopenharmony_ci	{"tded4",		DVB_PLL_TDED4},
9238c2ecf20Sopenharmony_ci	{"tdhu2",		DVB_PLL_TDHU2},
9248c2ecf20Sopenharmony_ci	{"tbmv",		DVB_PLL_SAMSUNG_TBMV},
9258c2ecf20Sopenharmony_ci	{"sd1878_tda8261",	DVB_PLL_PHILIPS_SD1878_TDA8261},
9268c2ecf20Sopenharmony_ci	{"opera1",		DVB_PLL_OPERA1},
9278c2ecf20Sopenharmony_ci	{"dtos403ih102a",	DVB_PLL_SAMSUNG_DTOS403IH102A},
9288c2ecf20Sopenharmony_ci	{"tdtc9251dh0",		DVB_PLL_SAMSUNG_TDTC9251DH0},
9298c2ecf20Sopenharmony_ci	{"tbdu18132",		DVB_PLL_SAMSUNG_TBDU18132},
9308c2ecf20Sopenharmony_ci	{"tbmu24112",		DVB_PLL_SAMSUNG_TBMU24112},
9318c2ecf20Sopenharmony_ci	{"tdee4",		DVB_PLL_TDEE4},
9328c2ecf20Sopenharmony_ci	{"dtt7520x",		DVB_PLL_THOMSON_DTT7520X},
9338c2ecf20Sopenharmony_ci	{"tua6034_friio",	DVB_PLL_TUA6034_FRIIO},
9348c2ecf20Sopenharmony_ci	{"tda665x_earthpt1",	DVB_PLL_TDA665X_EARTH_PT1},
9358c2ecf20Sopenharmony_ci	{}
9368c2ecf20Sopenharmony_ci};
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci
9398c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, dvb_pll_id);
9408c2ecf20Sopenharmony_ci
9418c2ecf20Sopenharmony_cistatic struct i2c_driver dvb_pll_driver = {
9428c2ecf20Sopenharmony_ci	.driver = {
9438c2ecf20Sopenharmony_ci		.name = "dvb_pll",
9448c2ecf20Sopenharmony_ci	},
9458c2ecf20Sopenharmony_ci	.probe    = dvb_pll_probe,
9468c2ecf20Sopenharmony_ci	.remove   = dvb_pll_remove,
9478c2ecf20Sopenharmony_ci	.id_table = dvb_pll_id,
9488c2ecf20Sopenharmony_ci};
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_cimodule_i2c_driver(dvb_pll_driver);
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("dvb pll library");
9538c2ecf20Sopenharmony_ciMODULE_AUTHOR("Gerd Knorr");
9548c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
955