brintos

brintos / linux-shallow public Read only

0
0
Text · 5.9 KiB · a0d0a38 Raw
297 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3	Intersil ISL6423 SEC and LNB Power supply controller4 5	Copyright (C) Manu Abraham <abraham.manu@gmail.com>6 7*/8 9#include <linux/delay.h>10#include <linux/errno.h>11#include <linux/init.h>12#include <linux/kernel.h>13#include <linux/module.h>14#include <linux/string.h>15#include <linux/slab.h>16 17#include <media/dvb_frontend.h>18#include "isl6423.h"19 20static unsigned int verbose;21module_param(verbose, int, 0644);22MODULE_PARM_DESC(verbose, "Set Verbosity level");23 24#define FE_ERROR				025#define FE_NOTICE				126#define FE_INFO					227#define FE_DEBUG				328#define FE_DEBUGREG				429 30#define dprintk(__y, __z, format, arg...) do {						\31	if (__z) {									\32		if	((verbose > FE_ERROR) && (verbose > __y))			\33			printk(KERN_ERR "%s: " format "\n", __func__ , ##arg);		\34		else if	((verbose > FE_NOTICE) && (verbose > __y))			\35			printk(KERN_NOTICE "%s: " format "\n", __func__ , ##arg);	\36		else if ((verbose > FE_INFO) && (verbose > __y))			\37			printk(KERN_INFO "%s: " format "\n", __func__ , ##arg);		\38		else if ((verbose > FE_DEBUG) && (verbose > __y))			\39			printk(KERN_DEBUG "%s: " format "\n", __func__ , ##arg);	\40	} else {									\41		if (verbose > __y)							\42			printk(format, ##arg);						\43	}										\44} while (0)45 46struct isl6423_dev {47	const struct isl6423_config	*config;48	struct i2c_adapter		*i2c;49 50	u8 reg_3;51	u8 reg_4;52 53	unsigned int verbose;54};55 56static int isl6423_write(struct isl6423_dev *isl6423, u8 reg)57{58	struct i2c_adapter *i2c = isl6423->i2c;59	u8 addr			= isl6423->config->addr;60	int err = 0;61 62	struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = &reg, .len = 1 };63 64	dprintk(FE_DEBUG, 1, "write reg %02X", reg);65	err = i2c_transfer(i2c, &msg, 1);66	if (err < 0)67		goto exit;68	return 0;69 70exit:71	dprintk(FE_ERROR, 1, "I/O error <%d>", err);72	return err;73}74 75static int isl6423_set_modulation(struct dvb_frontend *fe)76{77	struct isl6423_dev *isl6423		= (struct isl6423_dev *) fe->sec_priv;78	const struct isl6423_config *config	= isl6423->config;79	int err = 0;80	u8 reg_2 = 0;81 82	reg_2 = 0x01 << 5;83 84	if (config->mod_extern)85		reg_2 |= (1 << 3);86	else87		reg_2 |= (1 << 4);88 89	err = isl6423_write(isl6423, reg_2);90	if (err < 0)91		goto exit;92	return 0;93 94exit:95	dprintk(FE_ERROR, 1, "I/O error <%d>", err);96	return err;97}98 99static int isl6423_voltage_boost(struct dvb_frontend *fe, long arg)100{101	struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;102	u8 reg_3 = isl6423->reg_3;103	u8 reg_4 = isl6423->reg_4;104	int err = 0;105 106	if (arg) {107		/* EN = 1, VSPEN = 1, VBOT = 1 */108		reg_4 |= (1 << 4);109		reg_4 |= 0x1;110		reg_3 |= (1 << 3);111	} else {112		/* EN = 1, VSPEN = 1, VBOT = 0 */113		reg_4 |= (1 << 4);114		reg_4 &= ~0x1;115		reg_3 |= (1 << 3);116	}117	err = isl6423_write(isl6423, reg_3);118	if (err < 0)119		goto exit;120 121	err = isl6423_write(isl6423, reg_4);122	if (err < 0)123		goto exit;124 125	isl6423->reg_3 = reg_3;126	isl6423->reg_4 = reg_4;127 128	return 0;129exit:130	dprintk(FE_ERROR, 1, "I/O error <%d>", err);131	return err;132}133 134 135static int isl6423_set_voltage(struct dvb_frontend *fe,136			       enum fe_sec_voltage voltage)137{138	struct isl6423_dev *isl6423 = (struct isl6423_dev *) fe->sec_priv;139	u8 reg_3 = isl6423->reg_3;140	u8 reg_4 = isl6423->reg_4;141	int err = 0;142 143	switch (voltage) {144	case SEC_VOLTAGE_OFF:145		/* EN = 0 */146		reg_4 &= ~(1 << 4);147		break;148 149	case SEC_VOLTAGE_13:150		/* EN = 1, VSPEN = 1, VTOP = 0, VBOT = 0 */151		reg_4 |= (1 << 4);152		reg_4 &= ~0x3;153		reg_3 |= (1 << 3);154		break;155 156	case SEC_VOLTAGE_18:157		/* EN = 1, VSPEN = 1, VTOP = 1, VBOT = 0 */158		reg_4 |= (1 << 4);159		reg_4 |=  0x2;160		reg_4 &= ~0x1;161		reg_3 |= (1 << 3);162		break;163 164	default:165		break;166	}167	err = isl6423_write(isl6423, reg_3);168	if (err < 0)169		goto exit;170 171	err = isl6423_write(isl6423, reg_4);172	if (err < 0)173		goto exit;174 175	isl6423->reg_3 = reg_3;176	isl6423->reg_4 = reg_4;177 178	return 0;179exit:180	dprintk(FE_ERROR, 1, "I/O error <%d>", err);181	return err;182}183 184static int isl6423_set_current(struct dvb_frontend *fe)185{186	struct isl6423_dev *isl6423		= (struct isl6423_dev *) fe->sec_priv;187	u8 reg_3 = isl6423->reg_3;188	const struct isl6423_config *config	= isl6423->config;189	int err = 0;190 191	switch (config->current_max) {192	case SEC_CURRENT_275m:193		/* 275mA */194		/* ISELH = 0, ISELL = 0 */195		reg_3 &= ~0x3;196		break;197 198	case SEC_CURRENT_515m:199		/* 515mA */200		/* ISELH = 0, ISELL = 1 */201		reg_3 &= ~0x2;202		reg_3 |=  0x1;203		break;204 205	case SEC_CURRENT_635m:206		/* 635mA */207		/* ISELH = 1, ISELL = 0 */208		reg_3 &= ~0x1;209		reg_3 |=  0x2;210		break;211 212	case SEC_CURRENT_800m:213		/* 800mA */214		/* ISELH = 1, ISELL = 1 */215		reg_3 |= 0x3;216		break;217	}218 219	err = isl6423_write(isl6423, reg_3);220	if (err < 0)221		goto exit;222 223	switch (config->curlim) {224	case SEC_CURRENT_LIM_ON:225		/* DCL = 0 */226		reg_3 &= ~0x10;227		break;228 229	case SEC_CURRENT_LIM_OFF:230		/* DCL = 1 */231		reg_3 |= 0x10;232		break;233	}234 235	err = isl6423_write(isl6423, reg_3);236	if (err < 0)237		goto exit;238 239	isl6423->reg_3 = reg_3;240 241	return 0;242exit:243	dprintk(FE_ERROR, 1, "I/O error <%d>", err);244	return err;245}246 247static void isl6423_release(struct dvb_frontend *fe)248{249	isl6423_set_voltage(fe, SEC_VOLTAGE_OFF);250 251	kfree(fe->sec_priv);252	fe->sec_priv = NULL;253}254 255struct dvb_frontend *isl6423_attach(struct dvb_frontend *fe,256				    struct i2c_adapter *i2c,257				    const struct isl6423_config *config)258{259	struct isl6423_dev *isl6423;260 261	isl6423 = kzalloc(sizeof(struct isl6423_dev), GFP_KERNEL);262	if (!isl6423)263		return NULL;264 265	isl6423->config	= config;266	isl6423->i2c	= i2c;267	fe->sec_priv	= isl6423;268 269	/* SR3H = 0, SR3M = 1, SR3L = 0 */270	isl6423->reg_3 = 0x02 << 5;271	/* SR4H = 0, SR4M = 1, SR4L = 1 */272	isl6423->reg_4 = 0x03 << 5;273 274	if (isl6423_set_current(fe))275		goto exit;276 277	if (isl6423_set_modulation(fe))278		goto exit;279 280	fe->ops.release_sec		= isl6423_release;281	fe->ops.set_voltage		= isl6423_set_voltage;282	fe->ops.enable_high_lnb_voltage = isl6423_voltage_boost;283	isl6423->verbose		= verbose;284 285	return fe;286 287exit:288	kfree(isl6423);289	fe->sec_priv = NULL;290	return NULL;291}292EXPORT_SYMBOL_GPL(isl6423_attach);293 294MODULE_DESCRIPTION("ISL6423 SEC");295MODULE_AUTHOR("Manu Abraham");296MODULE_LICENSE("GPL");297