1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * isl6421.h - driver for lnb supply and control ic ISL6421
5 * Copyright (C) 2006 Andrew de Quincey
6 * Copyright (C) 2006 Oliver Endriss
8 * the project's page is at https://linuxtv.org
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>
18 #include <media/dvb_frontend.h>
25 struct i2c_adapter
*i2c
;
30 static int isl6421_set_voltage(struct dvb_frontend
*fe
,
31 enum fe_sec_voltage voltage
)
36 struct isl6421
*isl6421
= (struct isl6421
*) fe
->sec_priv
;
37 struct i2c_msg msg
[2] = {
39 .addr
= isl6421
->i2c_addr
,
41 .buf
= &isl6421
->config
,
44 .addr
= isl6421
->i2c_addr
,
52 isl6421
->config
&= ~(ISL6421_VSEL1
| ISL6421_EN1
);
60 isl6421
->config
|= ISL6421_EN1
;
64 isl6421
->config
|= (ISL6421_EN1
| ISL6421_VSEL1
);
71 * If LNBf were not powered on, disable dynamic current limit, as,
72 * according with datasheet, highly capacitive load on the output may
73 * cause a difficult start-up.
75 if (isl6421
->is_off
&& !is_off
)
76 isl6421
->config
|= ISL6421_DCL
;
78 isl6421
->config
|= isl6421
->override_or
;
79 isl6421
->config
&= isl6421
->override_and
;
81 ret
= i2c_transfer(isl6421
->i2c
, msg
, 2);
87 /* Store off status now in case future commands fail */
88 isl6421
->is_off
= is_off
;
90 /* On overflow, the device will try again after 900 ms (typically) */
91 if (!is_off
&& (buf
& ISL6421_OLF1
))
94 /* Re-enable dynamic current limit */
95 if ((isl6421
->config
& ISL6421_DCL
) &&
96 !(isl6421
->override_or
& ISL6421_DCL
)) {
97 isl6421
->config
&= ~ISL6421_DCL
;
99 ret
= i2c_transfer(isl6421
->i2c
, msg
, 2);
106 /* Check if overload flag is active. If so, disable power */
107 if (!is_off
&& (buf
& ISL6421_OLF1
)) {
108 isl6421
->config
&= ~(ISL6421_VSEL1
| ISL6421_EN1
);
109 ret
= i2c_transfer(isl6421
->i2c
, msg
, 1);
114 isl6421
->is_off
= true;
116 dev_warn(&isl6421
->i2c
->dev
,
117 "Overload current detected. disabling LNBf power\n");
124 static int isl6421_enable_high_lnb_voltage(struct dvb_frontend
*fe
, long arg
)
126 struct isl6421
*isl6421
= (struct isl6421
*) fe
->sec_priv
;
127 struct i2c_msg msg
= { .addr
= isl6421
->i2c_addr
, .flags
= 0,
128 .buf
= &isl6421
->config
,
129 .len
= sizeof(isl6421
->config
) };
132 isl6421
->config
|= ISL6421_LLC1
;
134 isl6421
->config
&= ~ISL6421_LLC1
;
136 isl6421
->config
|= isl6421
->override_or
;
137 isl6421
->config
&= isl6421
->override_and
;
139 return (i2c_transfer(isl6421
->i2c
, &msg
, 1) == 1) ? 0 : -EIO
;
142 static int isl6421_set_tone(struct dvb_frontend
*fe
,
143 enum fe_sec_tone_mode tone
)
145 struct isl6421
*isl6421
= (struct isl6421
*) fe
->sec_priv
;
146 struct i2c_msg msg
= { .addr
= isl6421
->i2c_addr
, .flags
= 0,
147 .buf
= &isl6421
->config
,
148 .len
= sizeof(isl6421
->config
) };
152 isl6421
->config
|= ISL6421_ENT1
;
155 isl6421
->config
&= ~ISL6421_ENT1
;
161 isl6421
->config
|= isl6421
->override_or
;
162 isl6421
->config
&= isl6421
->override_and
;
164 return (i2c_transfer(isl6421
->i2c
, &msg
, 1) == 1) ? 0 : -EIO
;
167 static void isl6421_release(struct dvb_frontend
*fe
)
170 isl6421_set_voltage(fe
, SEC_VOLTAGE_OFF
);
177 struct dvb_frontend
*isl6421_attach(struct dvb_frontend
*fe
, struct i2c_adapter
*i2c
, u8 i2c_addr
,
178 u8 override_set
, u8 override_clear
, bool override_tone
)
180 struct isl6421
*isl6421
= kmalloc(sizeof(struct isl6421
), GFP_KERNEL
);
184 /* default configuration */
185 isl6421
->config
= ISL6421_ISEL1
;
187 isl6421
->i2c_addr
= i2c_addr
;
188 fe
->sec_priv
= isl6421
;
190 /* bits which should be forced to '1' */
191 isl6421
->override_or
= override_set
;
193 /* bits which should be forced to '0' */
194 isl6421
->override_and
= ~override_clear
;
196 /* detect if it is present or not */
197 if (isl6421_set_voltage(fe
, SEC_VOLTAGE_OFF
)) {
203 isl6421
->is_off
= true;
205 /* install release callback */
206 fe
->ops
.release_sec
= isl6421_release
;
208 /* override frontend ops */
209 fe
->ops
.set_voltage
= isl6421_set_voltage
;
210 fe
->ops
.enable_high_lnb_voltage
= isl6421_enable_high_lnb_voltage
;
212 fe
->ops
.set_tone
= isl6421_set_tone
;
216 EXPORT_SYMBOL(isl6421_attach
);
218 MODULE_DESCRIPTION("Driver for lnb supply and control ic isl6421");
219 MODULE_AUTHOR("Andrew de Quincey & Oliver Endriss");
220 MODULE_LICENSE("GPL");