linux/drivers/media/pci/cx23885/cx23885-f300.c
<<
>>
Prefs
   1/*
   2 * Driver for Silicon Labs C8051F300 microcontroller.
   3 *
   4 * It is used for LNB power control in TeVii S470,
   5 * TBS 6920 PCIe DVB-S2 cards.
   6 *
   7 * Microcontroller connected to cx23885 GPIO pins:
   8 * GPIO0 - data         - P0.3 F300
   9 * GPIO1 - reset        - P0.2 F300
  10 * GPIO2 - clk          - P0.1 F300
  11 * GPIO3 - busy         - P0.0 F300
  12 *
  13 * Copyright (C) 2009 Igor M. Liplianin <liplianin@me.by>
  14 *
  15 * This program is free software; you can redistribute it and/or modify
  16 * it under the terms of the GNU General Public License as published by
  17 * the Free Software Foundation; either version 2 of the License, or
  18 * (at your option) any later version.
  19 *
  20 * This program is distributed in the hope that it will be useful,
  21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  23 *
  24 * GNU General Public License for more details.
  25 */
  26
  27#include "cx23885.h"
  28#include "cx23885-f300.h"
  29
  30#define F300_DATA       GPIO_0
  31#define F300_RESET      GPIO_1
  32#define F300_CLK        GPIO_2
  33#define F300_BUSY       GPIO_3
  34
  35static void f300_set_line(struct cx23885_dev *dev, u32 line, u8 lvl)
  36{
  37        cx23885_gpio_enable(dev, line, 1);
  38        if (lvl == 1)
  39                cx23885_gpio_set(dev, line);
  40        else
  41                cx23885_gpio_clear(dev, line);
  42}
  43
  44static u8 f300_get_line(struct cx23885_dev *dev, u32 line)
  45{
  46        cx23885_gpio_enable(dev, line, 0);
  47
  48        return cx23885_gpio_get(dev, line);
  49}
  50
  51static void f300_send_byte(struct cx23885_dev *dev, u8 dta)
  52{
  53        u8 i;
  54
  55        for (i = 0; i < 8; i++) {
  56                f300_set_line(dev, F300_CLK, 0);
  57                udelay(30);
  58                f300_set_line(dev, F300_DATA, (dta & 0x80) >> 7);/* msb first */
  59                udelay(30);
  60                dta <<= 1;
  61                f300_set_line(dev, F300_CLK, 1);
  62                udelay(30);
  63        }
  64}
  65
  66static u8 f300_get_byte(struct cx23885_dev *dev)
  67{
  68        u8 i, dta = 0;
  69
  70        for (i = 0; i < 8; i++) {
  71                f300_set_line(dev, F300_CLK, 0);
  72                udelay(30);
  73                dta <<= 1;
  74                f300_set_line(dev, F300_CLK, 1);
  75                udelay(30);
  76                dta |= f300_get_line(dev, F300_DATA);/* msb first */
  77
  78        }
  79
  80        return dta;
  81}
  82
  83static u8 f300_xfer(struct dvb_frontend *fe, u8 *buf)
  84{
  85        struct cx23885_tsport *port = fe->dvb->priv;
  86        struct cx23885_dev *dev = port->dev;
  87        u8 i, temp, ret = 0;
  88
  89        temp = buf[0];
  90        for (i = 0; i < buf[0]; i++)
  91                temp += buf[i + 1];
  92        temp = (~temp + 1);/* get check sum */
  93        buf[1 + buf[0]] = temp;
  94
  95        f300_set_line(dev, F300_RESET, 1);
  96        f300_set_line(dev, F300_CLK, 1);
  97        udelay(30);
  98        f300_set_line(dev, F300_DATA, 1);
  99        msleep(1);
 100
 101        /* question: */
 102        f300_set_line(dev, F300_RESET, 0);/* begin to send data */
 103        msleep(1);
 104
 105        f300_send_byte(dev, 0xe0);/* the slave address is 0xe0, write */
 106        msleep(1);
 107
 108        temp = buf[0];
 109        temp += 2;
 110        for (i = 0; i < temp; i++)
 111                f300_send_byte(dev, buf[i]);
 112
 113        f300_set_line(dev, F300_RESET, 1);/* sent data over */
 114        f300_set_line(dev, F300_DATA, 1);
 115
 116        /* answer: */
 117        temp = 0;
 118        for (i = 0; ((i < 8) & (temp == 0)); i++) {
 119                msleep(1);
 120                if (f300_get_line(dev, F300_BUSY) == 0)
 121                        temp = 1;
 122        }
 123
 124        if (i > 7) {
 125                pr_err("%s: timeout, the slave no response\n",
 126                                                                __func__);
 127                ret = 1; /* timeout, the slave no response */
 128        } else { /* the slave not busy, prepare for getting data */
 129                f300_set_line(dev, F300_RESET, 0);/*ready...*/
 130                msleep(1);
 131                f300_send_byte(dev, 0xe1);/* 0xe1 is Read */
 132                msleep(1);
 133                temp = f300_get_byte(dev);/*get the data length */
 134                if (temp > 14)
 135                        temp = 14;
 136
 137                for (i = 0; i < (temp + 1); i++)
 138                        f300_get_byte(dev);/* get data to empty buffer */
 139
 140                f300_set_line(dev, F300_RESET, 1);/* received data over */
 141                f300_set_line(dev, F300_DATA, 1);
 142        }
 143
 144        return ret;
 145}
 146
 147int f300_set_voltage(struct dvb_frontend *fe, enum fe_sec_voltage voltage)
 148{
 149        u8 buf[16];
 150
 151        buf[0] = 0x05;
 152        buf[1] = 0x38;/* write port */
 153        buf[2] = 0x01;/* A port, lnb power */
 154
 155        switch (voltage) {
 156        case SEC_VOLTAGE_13:
 157                buf[3] = 0x01;/* power on */
 158                buf[4] = 0x02;/* B port, H/V */
 159                buf[5] = 0x00;/*13V v*/
 160                break;
 161        case SEC_VOLTAGE_18:
 162                buf[3] = 0x01;
 163                buf[4] = 0x02;
 164                buf[5] = 0x01;/* 18V h*/
 165                break;
 166        case SEC_VOLTAGE_OFF:
 167                buf[3] = 0x00;/* power off */
 168                buf[4] = 0x00;
 169                buf[5] = 0x00;
 170                break;
 171        }
 172
 173        return f300_xfer(fe, buf);
 174}
 175