brintos

brintos / linux-shallow public Read only

0
0
Text · 3.6 KiB · 7d28a74 Raw
149 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * isl6405.c - driver for dual lnb supply and control ic ISL64054 *5 * Copyright (C) 2008 Hartmut Hackmann6 * Copyright (C) 2006 Oliver Endriss7 *8 * the project's page is at https://linuxtv.org9 */10#include <linux/delay.h>11#include <linux/errno.h>12#include <linux/init.h>13#include <linux/kernel.h>14#include <linux/module.h>15#include <linux/string.h>16#include <linux/slab.h>17 18#include <media/dvb_frontend.h>19#include "isl6405.h"20 21struct isl6405 {22	u8			config;23	u8			override_or;24	u8			override_and;25	struct i2c_adapter	*i2c;26	u8			i2c_addr;27};28 29static int isl6405_set_voltage(struct dvb_frontend *fe,30			       enum fe_sec_voltage voltage)31{32	struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;33	struct i2c_msg msg = {	.addr = isl6405->i2c_addr, .flags = 0,34				.buf = &isl6405->config,35				.len = sizeof(isl6405->config) };36 37	if (isl6405->override_or & 0x80) {38		isl6405->config &= ~(ISL6405_VSEL2 | ISL6405_EN2);39		switch (voltage) {40		case SEC_VOLTAGE_OFF:41			break;42		case SEC_VOLTAGE_13:43			isl6405->config |= ISL6405_EN2;44			break;45		case SEC_VOLTAGE_18:46			isl6405->config |= (ISL6405_EN2 | ISL6405_VSEL2);47			break;48		default:49			return -EINVAL;50		}51	} else {52		isl6405->config &= ~(ISL6405_VSEL1 | ISL6405_EN1);53		switch (voltage) {54		case SEC_VOLTAGE_OFF:55			break;56		case SEC_VOLTAGE_13:57			isl6405->config |= ISL6405_EN1;58			break;59		case SEC_VOLTAGE_18:60			isl6405->config |= (ISL6405_EN1 | ISL6405_VSEL1);61			break;62		default:63			return -EINVAL;64		}65	}66	isl6405->config |= isl6405->override_or;67	isl6405->config &= isl6405->override_and;68 69	return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;70}71 72static int isl6405_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)73{74	struct isl6405 *isl6405 = (struct isl6405 *) fe->sec_priv;75	struct i2c_msg msg = {	.addr = isl6405->i2c_addr, .flags = 0,76				.buf = &isl6405->config,77				.len = sizeof(isl6405->config) };78 79	if (isl6405->override_or & 0x80) {80		if (arg)81			isl6405->config |= ISL6405_LLC2;82		else83			isl6405->config &= ~ISL6405_LLC2;84	} else {85		if (arg)86			isl6405->config |= ISL6405_LLC1;87		else88			isl6405->config &= ~ISL6405_LLC1;89	}90	isl6405->config |= isl6405->override_or;91	isl6405->config &= isl6405->override_and;92 93	return (i2c_transfer(isl6405->i2c, &msg, 1) == 1) ? 0 : -EIO;94}95 96static void isl6405_release(struct dvb_frontend *fe)97{98	/* power off */99	isl6405_set_voltage(fe, SEC_VOLTAGE_OFF);100 101	/* free */102	kfree(fe->sec_priv);103	fe->sec_priv = NULL;104}105 106struct dvb_frontend *isl6405_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c,107				    u8 i2c_addr, u8 override_set, u8 override_clear)108{109	struct isl6405 *isl6405 = kmalloc(sizeof(struct isl6405), GFP_KERNEL);110	if (!isl6405)111		return NULL;112 113	/* default configuration */114	if (override_set & 0x80)115		isl6405->config = ISL6405_ISEL2;116	else117		isl6405->config = ISL6405_ISEL1;118	isl6405->i2c = i2c;119	isl6405->i2c_addr = i2c_addr;120	fe->sec_priv = isl6405;121 122	/* bits which should be forced to '1' */123	isl6405->override_or = override_set;124 125	/* bits which should be forced to '0' */126	isl6405->override_and = ~override_clear;127 128	/* detect if it is present or not */129	if (isl6405_set_voltage(fe, SEC_VOLTAGE_OFF)) {130		kfree(isl6405);131		fe->sec_priv = NULL;132		return NULL;133	}134 135	/* install release callback */136	fe->ops.release_sec = isl6405_release;137 138	/* override frontend ops */139	fe->ops.set_voltage = isl6405_set_voltage;140	fe->ops.enable_high_lnb_voltage = isl6405_enable_high_lnb_voltage;141 142	return fe;143}144EXPORT_SYMBOL_GPL(isl6405_attach);145 146MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6405");147MODULE_AUTHOR("Hartmut Hackmann & Oliver Endriss");148MODULE_LICENSE("GPL");149