diff options
Diffstat (limited to 'drivers/media/video/cx23885/cx23885-f300.c')
-rw-r--r-- | drivers/media/video/cx23885/cx23885-f300.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/drivers/media/video/cx23885/cx23885-f300.c b/drivers/media/video/cx23885/cx23885-f300.c new file mode 100644 index 00000000000..93998f22098 --- /dev/null +++ b/drivers/media/video/cx23885/cx23885-f300.c | |||
@@ -0,0 +1,177 @@ | |||
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 | * You should have received a copy of the GNU General Public License | ||
27 | * along with this program; if not, write to the Free Software | ||
28 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
29 | */ | ||
30 | |||
31 | #include "cx23885.h" | ||
32 | |||
33 | #define F300_DATA GPIO_0 | ||
34 | #define F300_RESET GPIO_1 | ||
35 | #define F300_CLK GPIO_2 | ||
36 | #define F300_BUSY GPIO_3 | ||
37 | |||
38 | static void f300_set_line(struct cx23885_dev *dev, u32 line, u8 lvl) | ||
39 | { | ||
40 | cx23885_gpio_enable(dev, line, 1); | ||
41 | if (lvl == 1) | ||
42 | cx23885_gpio_set(dev, line); | ||
43 | else | ||
44 | cx23885_gpio_clear(dev, line); | ||
45 | } | ||
46 | |||
47 | static u8 f300_get_line(struct cx23885_dev *dev, u32 line) | ||
48 | { | ||
49 | cx23885_gpio_enable(dev, line, 0); | ||
50 | |||
51 | return cx23885_gpio_get(dev, line); | ||
52 | } | ||
53 | |||
54 | static void f300_send_byte(struct cx23885_dev *dev, u8 dta) | ||
55 | { | ||
56 | u8 i; | ||
57 | |||
58 | for (i = 0; i < 8; i++) { | ||
59 | f300_set_line(dev, F300_CLK, 0); | ||
60 | udelay(30); | ||
61 | f300_set_line(dev, F300_DATA, (dta & 0x80) >> 7);/* msb first */ | ||
62 | udelay(30); | ||
63 | dta <<= 1; | ||
64 | f300_set_line(dev, F300_CLK, 1); | ||
65 | udelay(30); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | static u8 f300_get_byte(struct cx23885_dev *dev) | ||
70 | { | ||
71 | u8 i, dta = 0; | ||
72 | |||
73 | for (i = 0; i < 8; i++) { | ||
74 | f300_set_line(dev, F300_CLK, 0); | ||
75 | udelay(30); | ||
76 | dta <<= 1; | ||
77 | f300_set_line(dev, F300_CLK, 1); | ||
78 | udelay(30); | ||
79 | dta |= f300_get_line(dev, F300_DATA);/* msb first */ | ||
80 | |||
81 | } | ||
82 | |||
83 | return dta; | ||
84 | } | ||
85 | |||
86 | static u8 f300_xfer(struct dvb_frontend *fe, u8 *buf) | ||
87 | { | ||
88 | struct cx23885_tsport *port = fe->dvb->priv; | ||
89 | struct cx23885_dev *dev = port->dev; | ||
90 | u8 i, temp, ret = 0; | ||
91 | |||
92 | temp = buf[0]; | ||
93 | for (i = 0; i < buf[0]; i++) | ||
94 | temp += buf[i + 1]; | ||
95 | temp = (~temp + 1);/* get check sum */ | ||
96 | buf[1 + buf[0]] = temp; | ||
97 | |||
98 | f300_set_line(dev, F300_RESET, 1); | ||
99 | f300_set_line(dev, F300_CLK, 1); | ||
100 | udelay(30); | ||
101 | f300_set_line(dev, F300_DATA, 1); | ||
102 | msleep(1); | ||
103 | |||
104 | /* question: */ | ||
105 | f300_set_line(dev, F300_RESET, 0);/* begin to send data */ | ||
106 | msleep(1); | ||
107 | |||
108 | f300_send_byte(dev, 0xe0);/* the slave address is 0xe0, write */ | ||
109 | msleep(1); | ||
110 | |||
111 | temp = buf[0]; | ||
112 | temp += 2; | ||
113 | for (i = 0; i < temp; i++) | ||
114 | f300_send_byte(dev, buf[i]); | ||
115 | |||
116 | f300_set_line(dev, F300_RESET, 1);/* sent data over */ | ||
117 | f300_set_line(dev, F300_DATA, 1); | ||
118 | |||
119 | /* answer: */ | ||
120 | temp = 0; | ||
121 | for (i = 0; ((i < 8) & (temp == 0)); i++) { | ||
122 | msleep(1); | ||
123 | if (f300_get_line(dev, F300_BUSY) == 0) | ||
124 | temp = 1; | ||
125 | } | ||
126 | |||
127 | if (i > 7) { | ||
128 | printk(KERN_ERR "%s: timeout, the slave no response\n", | ||
129 | __func__); | ||
130 | ret = 1; /* timeout, the slave no response */ | ||
131 | } else { /* the slave not busy, prepare for getting data */ | ||
132 | f300_set_line(dev, F300_RESET, 0);/*ready...*/ | ||
133 | msleep(1); | ||
134 | f300_send_byte(dev, 0xe1);/* 0xe1 is Read */ | ||
135 | msleep(1); | ||
136 | temp = f300_get_byte(dev);/*get the data length */ | ||
137 | if (temp > 14) | ||
138 | temp = 14; | ||
139 | |||
140 | for (i = 0; i < (temp + 1); i++) | ||
141 | f300_get_byte(dev);/* get data to empty buffer */ | ||
142 | |||
143 | f300_set_line(dev, F300_RESET, 1);/* received data over */ | ||
144 | f300_set_line(dev, F300_DATA, 1); | ||
145 | } | ||
146 | |||
147 | return ret; | ||
148 | } | ||
149 | |||
150 | int f300_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage) | ||
151 | { | ||
152 | u8 buf[16]; | ||
153 | |||
154 | buf[0] = 0x05; | ||
155 | buf[1] = 0x38;/* write port */ | ||
156 | buf[2] = 0x01;/* A port, lnb power */ | ||
157 | |||
158 | switch (voltage) { | ||
159 | case SEC_VOLTAGE_13: | ||
160 | buf[3] = 0x01;/* power on */ | ||
161 | buf[4] = 0x02;/* B port, H/V */ | ||
162 | buf[5] = 0x00;/*13V v*/ | ||
163 | break; | ||
164 | case SEC_VOLTAGE_18: | ||
165 | buf[3] = 0x01; | ||
166 | buf[4] = 0x02; | ||
167 | buf[5] = 0x01;/* 18V h*/ | ||
168 | break; | ||
169 | case SEC_VOLTAGE_OFF: | ||
170 | buf[3] = 0x00;/* power off */ | ||
171 | buf[4] = 0x00; | ||
172 | buf[5] = 0x00; | ||
173 | break; | ||
174 | } | ||
175 | |||
176 | return f300_xfer(fe, buf); | ||
177 | } | ||