brintos

brintos / linux-shallow public Read only

0
0
Text · 4.7 KiB · d74e346 Raw
243 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2  /*3     Driver for ST STB6000 DVBS Silicon tuner4 5     Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)6 7 8  */9 10#include <linux/slab.h>11#include <linux/module.h>12#include <linux/dvb/frontend.h>13#include <asm/types.h>14 15#include "stb6000.h"16 17static int debug;18#define dprintk(args...) \19	do { \20		if (debug) \21			printk(KERN_DEBUG "stb6000: " args); \22	} while (0)23 24struct stb6000_priv {25	/* i2c details */26	int i2c_address;27	struct i2c_adapter *i2c;28	u32 frequency;29};30 31static void stb6000_release(struct dvb_frontend *fe)32{33	kfree(fe->tuner_priv);34	fe->tuner_priv = NULL;35}36 37static int stb6000_sleep(struct dvb_frontend *fe)38{39	struct stb6000_priv *priv = fe->tuner_priv;40	int ret;41	u8 buf[] = { 10, 0 };42	struct i2c_msg msg = {43		.addr = priv->i2c_address,44		.flags = 0,45		.buf = buf,46		.len = 247	};48 49	dprintk("%s:\n", __func__);50 51	if (fe->ops.i2c_gate_ctrl)52		fe->ops.i2c_gate_ctrl(fe, 1);53 54	ret = i2c_transfer(priv->i2c, &msg, 1);55	if (ret != 1)56		dprintk("%s: i2c error\n", __func__);57 58	if (fe->ops.i2c_gate_ctrl)59		fe->ops.i2c_gate_ctrl(fe, 0);60 61	return (ret == 1) ? 0 : ret;62}63 64static int stb6000_set_params(struct dvb_frontend *fe)65{66	struct dtv_frontend_properties *p = &fe->dtv_property_cache;67	struct stb6000_priv *priv = fe->tuner_priv;68	unsigned int n, m;69	int ret;70	u32 freq_mhz;71	int bandwidth;72	u8 buf[12];73	struct i2c_msg msg = {74		.addr = priv->i2c_address,75		.flags = 0,76		.buf = buf,77		.len = 1278	};79 80	dprintk("%s:\n", __func__);81 82	freq_mhz = p->frequency / 1000;83	bandwidth = p->symbol_rate / 1000000;84 85	if (bandwidth > 31)86		bandwidth = 31;87 88	if ((freq_mhz > 949) && (freq_mhz < 2151)) {89		buf[0] = 0x01;90		buf[1] = 0xac;91		if (freq_mhz < 1950)92			buf[1] = 0xaa;93		if (freq_mhz < 1800)94			buf[1] = 0xa8;95		if (freq_mhz < 1650)96			buf[1] = 0xa6;97		if (freq_mhz < 1530)98			buf[1] = 0xa5;99		if (freq_mhz < 1470)100			buf[1] = 0xa4;101		if (freq_mhz < 1370)102			buf[1] = 0xa2;103		if (freq_mhz < 1300)104			buf[1] = 0xa1;105		if (freq_mhz < 1200)106			buf[1] = 0xa0;107		if (freq_mhz < 1075)108			buf[1] = 0xbc;109		if (freq_mhz < 1000)110			buf[1] = 0xba;111		if (freq_mhz < 1075) {112			n = freq_mhz / 8; /* vco=lo*4 */113			m = 2;114		} else {115			n = freq_mhz / 16; /* vco=lo*2 */116			m = 1;117		}118		buf[2] = n >> 1;119		buf[3] = (unsigned char)(((n & 1) << 7) |120					(m * freq_mhz - n * 16) | 0x60);121		buf[4] = 0x04;122		buf[5] = 0x0e;123 124		buf[6] = (unsigned char)(bandwidth);125 126		buf[7] = 0xd8;127		buf[8] = 0xd0;128		buf[9] = 0x50;129		buf[10] = 0xeb;130		buf[11] = 0x4f;131 132		if (fe->ops.i2c_gate_ctrl)133			fe->ops.i2c_gate_ctrl(fe, 1);134 135		ret = i2c_transfer(priv->i2c, &msg, 1);136		if (ret != 1)137			dprintk("%s: i2c error\n", __func__);138 139		udelay(10);140		if (fe->ops.i2c_gate_ctrl)141			fe->ops.i2c_gate_ctrl(fe, 0);142 143		buf[0] = 0x07;144		buf[1] = 0xdf;145		buf[2] = 0xd0;146		buf[3] = 0x50;147		buf[4] = 0xfb;148		msg.len = 5;149 150		if (fe->ops.i2c_gate_ctrl)151			fe->ops.i2c_gate_ctrl(fe, 1);152 153		ret = i2c_transfer(priv->i2c, &msg, 1);154		if (ret != 1)155			dprintk("%s: i2c error\n", __func__);156 157		udelay(10);158		if (fe->ops.i2c_gate_ctrl)159			fe->ops.i2c_gate_ctrl(fe, 0);160 161		priv->frequency = freq_mhz * 1000;162 163		return (ret == 1) ? 0 : ret;164	}165	return -1;166}167 168static int stb6000_get_frequency(struct dvb_frontend *fe, u32 *frequency)169{170	struct stb6000_priv *priv = fe->tuner_priv;171	*frequency = priv->frequency;172	return 0;173}174 175static const struct dvb_tuner_ops stb6000_tuner_ops = {176	.info = {177		.name = "ST STB6000",178		.frequency_min_hz =  950 * MHz,179		.frequency_max_hz = 2150 * MHz180	},181	.release = stb6000_release,182	.sleep = stb6000_sleep,183	.set_params = stb6000_set_params,184	.get_frequency = stb6000_get_frequency,185};186 187struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,188						struct i2c_adapter *i2c)189{190	struct stb6000_priv *priv = NULL;191	u8 b0[] = { 0 };192	u8 b1[] = { 0, 0 };193	struct i2c_msg msg[2] = {194		{195			.addr = addr,196			.flags = 0,197			.buf = b0,198			.len = 0199		}, {200			.addr = addr,201			.flags = I2C_M_RD,202			.buf = b1,203			.len = 2204		}205	};206	int ret;207 208	dprintk("%s:\n", __func__);209 210	if (fe->ops.i2c_gate_ctrl)211		fe->ops.i2c_gate_ctrl(fe, 1);212 213	/* is some i2c device here ? */214	ret = i2c_transfer(i2c, msg, 2);215	if (fe->ops.i2c_gate_ctrl)216		fe->ops.i2c_gate_ctrl(fe, 0);217 218	if (ret != 2)219		return NULL;220 221	priv = kzalloc(sizeof(struct stb6000_priv), GFP_KERNEL);222	if (priv == NULL)223		return NULL;224 225	priv->i2c_address = addr;226	priv->i2c = i2c;227 228	memcpy(&fe->ops.tuner_ops, &stb6000_tuner_ops,229				sizeof(struct dvb_tuner_ops));230 231	fe->tuner_priv = priv;232 233	return fe;234}235EXPORT_SYMBOL_GPL(stb6000_attach);236 237module_param(debug, int, 0644);238MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");239 240MODULE_DESCRIPTION("DVB STB6000 driver");241MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>");242MODULE_LICENSE("GPL");243