Path: blob/master/drivers/media/video/cx23885/cx23885-f300.c
17988 views
/*1* Driver for Silicon Labs C8051F300 microcontroller.2*3* It is used for LNB power control in TeVii S470,4* TBS 6920 PCIe DVB-S2 cards.5*6* Microcontroller connected to cx23885 GPIO pins:7* GPIO0 - data - P0.3 F3008* GPIO1 - reset - P0.2 F3009* GPIO2 - clk - P0.1 F30010* GPIO3 - busy - P0.0 F30011*12* Copyright (C) 2009 Igor M. Liplianin <[email protected]>13*14* This program is free software; you can redistribute it and/or modify15* it under the terms of the GNU General Public License as published by16* the Free Software Foundation; either version 2 of the License, or17* (at your option) any later version.18*19* This program is distributed in the hope that it will be useful,20* but WITHOUT ANY WARRANTY; without even the implied warranty of21* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the22*23* GNU General Public License for more details.24*25* You should have received a copy of the GNU General Public License26* along with this program; if not, write to the Free Software27* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.28*/2930#include "cx23885.h"3132#define F300_DATA GPIO_033#define F300_RESET GPIO_134#define F300_CLK GPIO_235#define F300_BUSY GPIO_33637static void f300_set_line(struct cx23885_dev *dev, u32 line, u8 lvl)38{39cx23885_gpio_enable(dev, line, 1);40if (lvl == 1)41cx23885_gpio_set(dev, line);42else43cx23885_gpio_clear(dev, line);44}4546static u8 f300_get_line(struct cx23885_dev *dev, u32 line)47{48cx23885_gpio_enable(dev, line, 0);4950return cx23885_gpio_get(dev, line);51}5253static void f300_send_byte(struct cx23885_dev *dev, u8 dta)54{55u8 i;5657for (i = 0; i < 8; i++) {58f300_set_line(dev, F300_CLK, 0);59udelay(30);60f300_set_line(dev, F300_DATA, (dta & 0x80) >> 7);/* msb first */61udelay(30);62dta <<= 1;63f300_set_line(dev, F300_CLK, 1);64udelay(30);65}66}6768static u8 f300_get_byte(struct cx23885_dev *dev)69{70u8 i, dta = 0;7172for (i = 0; i < 8; i++) {73f300_set_line(dev, F300_CLK, 0);74udelay(30);75dta <<= 1;76f300_set_line(dev, F300_CLK, 1);77udelay(30);78dta |= f300_get_line(dev, F300_DATA);/* msb first */7980}8182return dta;83}8485static u8 f300_xfer(struct dvb_frontend *fe, u8 *buf)86{87struct cx23885_tsport *port = fe->dvb->priv;88struct cx23885_dev *dev = port->dev;89u8 i, temp, ret = 0;9091temp = buf[0];92for (i = 0; i < buf[0]; i++)93temp += buf[i + 1];94temp = (~temp + 1);/* get check sum */95buf[1 + buf[0]] = temp;9697f300_set_line(dev, F300_RESET, 1);98f300_set_line(dev, F300_CLK, 1);99udelay(30);100f300_set_line(dev, F300_DATA, 1);101msleep(1);102103/* question: */104f300_set_line(dev, F300_RESET, 0);/* begin to send data */105msleep(1);106107f300_send_byte(dev, 0xe0);/* the slave address is 0xe0, write */108msleep(1);109110temp = buf[0];111temp += 2;112for (i = 0; i < temp; i++)113f300_send_byte(dev, buf[i]);114115f300_set_line(dev, F300_RESET, 1);/* sent data over */116f300_set_line(dev, F300_DATA, 1);117118/* answer: */119temp = 0;120for (i = 0; ((i < 8) & (temp == 0)); i++) {121msleep(1);122if (f300_get_line(dev, F300_BUSY) == 0)123temp = 1;124}125126if (i > 7) {127printk(KERN_ERR "%s: timeout, the slave no response\n",128__func__);129ret = 1; /* timeout, the slave no response */130} else { /* the slave not busy, prepare for getting data */131f300_set_line(dev, F300_RESET, 0);/*ready...*/132msleep(1);133f300_send_byte(dev, 0xe1);/* 0xe1 is Read */134msleep(1);135temp = f300_get_byte(dev);/*get the data length */136if (temp > 14)137temp = 14;138139for (i = 0; i < (temp + 1); i++)140f300_get_byte(dev);/* get data to empty buffer */141142f300_set_line(dev, F300_RESET, 1);/* received data over */143f300_set_line(dev, F300_DATA, 1);144}145146return ret;147}148149int f300_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)150{151u8 buf[16];152153buf[0] = 0x05;154buf[1] = 0x38;/* write port */155buf[2] = 0x01;/* A port, lnb power */156157switch (voltage) {158case SEC_VOLTAGE_13:159buf[3] = 0x01;/* power on */160buf[4] = 0x02;/* B port, H/V */161buf[5] = 0x00;/*13V v*/162break;163case SEC_VOLTAGE_18:164buf[3] = 0x01;165buf[4] = 0x02;166buf[5] = 0x01;/* 18V h*/167break;168case SEC_VOLTAGE_OFF:169buf[3] = 0x00;/* power off */170buf[4] = 0x00;171buf[5] = 0x00;172break;173}174175return f300_xfer(fe, buf);176}177178179