linux/drivers/media/dvb-frontends/lnbp22.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * lnbp22.h - driver for lnb supply and control ic lnbp22
   4 *
   5 * Copyright (C) 2006 Dominik Kuhlen
   6 * Based on lnbp21 driver
   7 *
   8 * the project's page is at https://linuxtv.org
   9 */
  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/moduleparam.h>
  16#include <linux/string.h>
  17#include <linux/slab.h>
  18
  19#include <media/dvb_frontend.h>
  20#include "lnbp22.h"
  21
  22static int debug;
  23module_param(debug, int, 0644);
  24MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
  25
  26
  27#define dprintk(lvl, arg...) if (debug >= (lvl)) printk(arg)
  28
  29struct lnbp22 {
  30        u8                  config[4];
  31        struct i2c_adapter *i2c;
  32};
  33
  34static int lnbp22_set_voltage(struct dvb_frontend *fe,
  35                              enum fe_sec_voltage voltage)
  36{
  37        struct lnbp22 *lnbp22 = (struct lnbp22 *)fe->sec_priv;
  38        struct i2c_msg msg = {
  39                .addr = 0x08,
  40                .flags = 0,
  41                .buf = (char *)&lnbp22->config,
  42                .len = sizeof(lnbp22->config),
  43        };
  44
  45        dprintk(1, "%s: %d (18V=%d 13V=%d)\n", __func__, voltage,
  46               SEC_VOLTAGE_18, SEC_VOLTAGE_13);
  47
  48        lnbp22->config[3] = 0x60; /* Power down */
  49        switch (voltage) {
  50        case SEC_VOLTAGE_OFF:
  51                break;
  52        case SEC_VOLTAGE_13:
  53                lnbp22->config[3] |= LNBP22_EN;
  54                break;
  55        case SEC_VOLTAGE_18:
  56                lnbp22->config[3] |= (LNBP22_EN | LNBP22_VSEL);
  57                break;
  58        default:
  59                return -EINVAL;
  60        }
  61
  62        dprintk(1, "%s: 0x%02x)\n", __func__, lnbp22->config[3]);
  63        return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
  64}
  65
  66static int lnbp22_enable_high_lnb_voltage(struct dvb_frontend *fe, long arg)
  67{
  68        struct lnbp22 *lnbp22 = (struct lnbp22 *) fe->sec_priv;
  69        struct i2c_msg msg = {
  70                .addr = 0x08,
  71                .flags = 0,
  72                .buf = (char *)&lnbp22->config,
  73                .len = sizeof(lnbp22->config),
  74        };
  75
  76        dprintk(1, "%s: %d\n", __func__, (int)arg);
  77        if (arg)
  78                lnbp22->config[3] |= LNBP22_LLC;
  79        else
  80                lnbp22->config[3] &= ~LNBP22_LLC;
  81
  82        return (i2c_transfer(lnbp22->i2c, &msg, 1) == 1) ? 0 : -EIO;
  83}
  84
  85static void lnbp22_release(struct dvb_frontend *fe)
  86{
  87        dprintk(1, "%s\n", __func__);
  88        /* LNBP power off */
  89        lnbp22_set_voltage(fe, SEC_VOLTAGE_OFF);
  90
  91        /* free data */
  92        kfree(fe->sec_priv);
  93        fe->sec_priv = NULL;
  94}
  95
  96struct dvb_frontend *lnbp22_attach(struct dvb_frontend *fe,
  97                                        struct i2c_adapter *i2c)
  98{
  99        struct lnbp22 *lnbp22 = kmalloc(sizeof(struct lnbp22), GFP_KERNEL);
 100        if (!lnbp22)
 101                return NULL;
 102
 103        /* default configuration */
 104        lnbp22->config[0] = 0x00; /* ? */
 105        lnbp22->config[1] = 0x28; /* ? */
 106        lnbp22->config[2] = 0x48; /* ? */
 107        lnbp22->config[3] = 0x60; /* Power down */
 108        lnbp22->i2c = i2c;
 109        fe->sec_priv = lnbp22;
 110
 111        /* detect if it is present or not */
 112        if (lnbp22_set_voltage(fe, SEC_VOLTAGE_OFF)) {
 113                dprintk(0, "%s LNBP22 not found\n", __func__);
 114                kfree(lnbp22);
 115                fe->sec_priv = NULL;
 116                return NULL;
 117        }
 118
 119        /* install release callback */
 120        fe->ops.release_sec = lnbp22_release;
 121
 122        /* override frontend ops */
 123        fe->ops.set_voltage = lnbp22_set_voltage;
 124        fe->ops.enable_high_lnb_voltage = lnbp22_enable_high_lnb_voltage;
 125
 126        return fe;
 127}
 128EXPORT_SYMBOL(lnbp22_attach);
 129
 130MODULE_DESCRIPTION("Driver for lnb supply and control ic lnbp22");
 131MODULE_AUTHOR("Dominik Kuhlen");
 132MODULE_LICENSE("GPL");
 133