aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/frontends
diff options
context:
space:
mode:
authorIgor M. Liplianin <liplianin@me.by>2008-09-23 14:43:57 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2008-10-12 07:37:07 -0400
commite4aab64cb78a42e45e1d387f272712e06cf89a66 (patch)
tree71085956cf8364b5a49723c9812cd18a54bbb792 /drivers/media/dvb/frontends
parent8316568930074723bdc47d6777f822be0422a5b7 (diff)
V4L/DVB (9026): Add support for ST STV0288 demodulator and cards with it.
Add support for ST STV0288 demodulator and cards with it, such as TeVii S420. Patch is co-authored with Georg Acher <acher@baycom.de> Signed-off-by: Georg Acher <acher@baycom.de> Signed-off-by: Igor M. Liplianin <liplianin@me.by> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb/frontends')
-rw-r--r--drivers/media/dvb/frontends/Kconfig14
-rw-r--r--drivers/media/dvb/frontends/Makefile2
-rw-r--r--drivers/media/dvb/frontends/stb6000.c254
-rw-r--r--drivers/media/dvb/frontends/stb6000.h51
-rw-r--r--drivers/media/dvb/frontends/stv0288.c606
-rw-r--r--drivers/media/dvb/frontends/stv0288.h65
-rw-r--r--drivers/media/dvb/frontends/stv0299.c2
-rw-r--r--drivers/media/dvb/frontends/stv0299.h13
8 files changed, 1002 insertions, 5 deletions
diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig
index 7697391ca86c..96b93e21a84b 100644
--- a/drivers/media/dvb/frontends/Kconfig
+++ b/drivers/media/dvb/frontends/Kconfig
@@ -43,6 +43,20 @@ config DVB_S5H1420
43 help 43 help
44 A DVB-S tuner module. Say Y when you want to support this frontend. 44 A DVB-S tuner module. Say Y when you want to support this frontend.
45 45
46config DVB_STV0288
47 tristate "ST STV0288 based"
48 depends on DVB_CORE && I2C
49 default m if DVB_FE_CUSTOMISE
50 help
51 A DVB-S tuner module. Say Y when you want to support this frontend.
52
53config DVB_STB6000
54 tristate "ST STB6000 silicon tuner"
55 depends on DVB_CORE && I2C
56 default m if DVB_FE_CUSTOMISE
57 help
58 A DVB-S silicon tuner module. Say Y when you want to support this tuner.
59
46config DVB_STV0299 60config DVB_STV0299
47 tristate "ST STV0299 based" 61 tristate "ST STV0299 based"
48 depends on DVB_CORE && I2C 62 depends on DVB_CORE && I2C
diff --git a/drivers/media/dvb/frontends/Makefile b/drivers/media/dvb/frontends/Makefile
index c719b7fdce4a..491eb5c55855 100644
--- a/drivers/media/dvb/frontends/Makefile
+++ b/drivers/media/dvb/frontends/Makefile
@@ -53,3 +53,5 @@ obj-$(CONFIG_DVB_DUMMY_FE) += dvb_dummy_fe.o
53obj-$(CONFIG_DVB_AF9013) += af9013.o 53obj-$(CONFIG_DVB_AF9013) += af9013.o
54obj-$(CONFIG_DVB_CX24116) += cx24116.o 54obj-$(CONFIG_DVB_CX24116) += cx24116.o
55obj-$(CONFIG_DVB_SI21XX) += si21xx.o 55obj-$(CONFIG_DVB_SI21XX) += si21xx.o
56obj-$(CONFIG_DVB_STV0299) += stv0288.o
57obj-$(CONFIG_DVB_STB6000) += stb6000.o
diff --git a/drivers/media/dvb/frontends/stb6000.c b/drivers/media/dvb/frontends/stb6000.c
new file mode 100644
index 000000000000..7d65123b4ec9
--- /dev/null
+++ b/drivers/media/dvb/frontends/stb6000.c
@@ -0,0 +1,254 @@
1 /*
2 Driver for ST STB6000 DVBS Silicon tuner
3
4 Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 */
22
23#include <linux/module.h>
24#include <linux/dvb/frontend.h>
25#include <asm/types.h>
26
27#include "stb6000.h"
28
29static int debug;
30#define dprintk(args...) \
31 do { \
32 if (debug) \
33 printk(KERN_DEBUG "stb6000: " args); \
34 } while (0)
35
36struct stb6000_priv {
37 /* i2c details */
38 int i2c_address;
39 struct i2c_adapter *i2c;
40 u32 frequency;
41};
42
43static int stb6000_release(struct dvb_frontend *fe)
44{
45 kfree(fe->tuner_priv);
46 fe->tuner_priv = NULL;
47 return 0;
48}
49
50static int stb6000_sleep(struct dvb_frontend *fe)
51{
52 struct stb6000_priv *priv = fe->tuner_priv;
53 int ret;
54 u8 buf[] = { 10, 0 };
55 struct i2c_msg msg = {
56 .addr = priv->i2c_address,
57 .flags = 0,
58 .buf = buf,
59 .len = 2
60 };
61
62 dprintk("%s:\n", __func__);
63
64 if (fe->ops.i2c_gate_ctrl)
65 fe->ops.i2c_gate_ctrl(fe, 1);
66
67 ret = i2c_transfer(priv->i2c, &msg, 1);
68 if (ret != 1)
69 dprintk("%s: i2c error\n", __func__);
70
71 if (fe->ops.i2c_gate_ctrl)
72 fe->ops.i2c_gate_ctrl(fe, 0);
73
74 return (ret == 1) ? 0 : ret;
75}
76
77static int stb6000_set_params(struct dvb_frontend *fe,
78 struct dvb_frontend_parameters *params)
79{
80 struct stb6000_priv *priv = fe->tuner_priv;
81 unsigned int n, m;
82 int ret;
83 u32 freq_mhz;
84 int bandwidth;
85 u8 buf[12];
86 struct i2c_msg msg = {
87 .addr = priv->i2c_address,
88 .flags = 0,
89 .buf = buf,
90 .len = 12
91 };
92
93 dprintk("%s:\n", __func__);
94
95 freq_mhz = params->frequency / 1000;
96 bandwidth = params->u.qpsk.symbol_rate / 1000000;
97
98 if (bandwidth > 31)
99 bandwidth = 31;
100
101 if ((freq_mhz > 949) && (freq_mhz < 2151)) {
102 buf[0] = 0x01;
103 buf[1] = 0xac;
104 if (freq_mhz < 1950)
105 buf[1] = 0xaa;
106 if (freq_mhz < 1800)
107 buf[1] = 0xa8;
108 if (freq_mhz < 1650)
109 buf[1] = 0xa6;
110 if (freq_mhz < 1530)
111 buf[1] = 0xa5;
112 if (freq_mhz < 1470)
113 buf[1] = 0xa4;
114 if (freq_mhz < 1370)
115 buf[1] = 0xa2;
116 if (freq_mhz < 1300)
117 buf[1] = 0xa1;
118 if (freq_mhz < 1200)
119 buf[1] = 0xa0;
120 if (freq_mhz < 1075)
121 buf[1] = 0xbc;
122 if (freq_mhz < 1000)
123 buf[1] = 0xba;
124 if (freq_mhz < 1075) {
125 n = freq_mhz / 8; /* vco=lo*4 */
126 m = 2;
127 } else {
128 n = freq_mhz / 16; /* vco=lo*2 */
129 m = 1;
130 }
131 buf[2] = n >> 1;
132 buf[3] = (unsigned char)(((n & 1) << 7) |
133 (m * freq_mhz - n * 16) | 0x60);
134 buf[4] = 0x04;
135 buf[5] = 0x0e;
136
137 buf[6] = (unsigned char)(bandwidth);
138
139 buf[7] = 0xd8;
140 buf[8] = 0xd0;
141 buf[9] = 0x50;
142 buf[10] = 0xeb;
143 buf[11] = 0x4f;
144
145 if (fe->ops.i2c_gate_ctrl)
146 fe->ops.i2c_gate_ctrl(fe, 1);
147
148 ret = i2c_transfer(priv->i2c, &msg, 1);
149 if (ret != 1)
150 dprintk("%s: i2c error\n", __func__);
151
152 udelay(10);
153 if (fe->ops.i2c_gate_ctrl)
154 fe->ops.i2c_gate_ctrl(fe, 0);
155
156 buf[0] = 0x07;
157 buf[1] = 0xdf;
158 buf[2] = 0xd0;
159 buf[3] = 0x50;
160 buf[4] = 0xfb;
161 msg.len = 5;
162
163 if (fe->ops.i2c_gate_ctrl)
164 fe->ops.i2c_gate_ctrl(fe, 1);
165
166 ret = i2c_transfer(priv->i2c, &msg, 1);
167 if (ret != 1)
168 dprintk("%s: i2c error\n", __func__);
169
170 udelay(10);
171 if (fe->ops.i2c_gate_ctrl)
172 fe->ops.i2c_gate_ctrl(fe, 0);
173
174 priv->frequency = freq_mhz * 1000;
175
176 return (ret == 1) ? 0 : ret;
177 }
178 return -1;
179}
180
181static int stb6000_get_frequency(struct dvb_frontend *fe, u32 *frequency)
182{
183 struct stb6000_priv *priv = fe->tuner_priv;
184 *frequency = priv->frequency;
185 return 0;
186}
187
188static struct dvb_tuner_ops stb6000_tuner_ops = {
189 .info = {
190 .name = "ST STB6000",
191 .frequency_min = 950000,
192 .frequency_max = 2150000
193 },
194 .release = stb6000_release,
195 .sleep = stb6000_sleep,
196 .set_params = stb6000_set_params,
197 .get_frequency = stb6000_get_frequency,
198};
199
200struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
201 struct i2c_adapter *i2c)
202{
203 struct stb6000_priv *priv = NULL;
204 u8 b1[] = { 0, 0 };
205 struct i2c_msg msg[2] = {
206 {
207 .addr = addr,
208 .flags = 0,
209 .buf = NULL,
210 .len = 0
211 }, {
212 .addr = addr,
213 .flags = I2C_M_RD,
214 .buf = b1,
215 .len = 2
216 }
217 };
218 int ret;
219
220 dprintk("%s:\n", __func__);
221
222 if (fe->ops.i2c_gate_ctrl)
223 fe->ops.i2c_gate_ctrl(fe, 1);
224
225 /* is some i2c device here ? */
226 ret = i2c_transfer(i2c, msg, 2);
227 if (fe->ops.i2c_gate_ctrl)
228 fe->ops.i2c_gate_ctrl(fe, 0);
229
230 if (ret != 2)
231 return NULL;
232
233 priv = kzalloc(sizeof(struct stb6000_priv), GFP_KERNEL);
234 if (priv == NULL)
235 return NULL;
236
237 priv->i2c_address = addr;
238 priv->i2c = i2c;
239
240 memcpy(&fe->ops.tuner_ops, &stb6000_tuner_ops,
241 sizeof(struct dvb_tuner_ops));
242
243 fe->tuner_priv = priv;
244
245 return fe;
246}
247EXPORT_SYMBOL(stb6000_attach);
248
249module_param(debug, int, 0644);
250MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
251
252MODULE_DESCRIPTION("DVB STB6000 driver");
253MODULE_AUTHOR("Igor M. Liplianin <liplianin@me.by>");
254MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/frontends/stb6000.h b/drivers/media/dvb/frontends/stb6000.h
new file mode 100644
index 000000000000..7be479c22d5b
--- /dev/null
+++ b/drivers/media/dvb/frontends/stb6000.h
@@ -0,0 +1,51 @@
1 /*
2 Driver for ST stb6000 DVBS Silicon tuner
3
4 Copyright (C) 2008 Igor M. Liplianin (liplianin@me.by)
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20
21 */
22
23#ifndef __DVB_STB6000_H__
24#define __DVB_STB6000_H__
25
26#include <linux/i2c.h>
27#include "dvb_frontend.h"
28
29/**
30 * Attach a stb6000 tuner to the supplied frontend structure.
31 *
32 * @param fe Frontend to attach to.
33 * @param addr i2c address of the tuner.
34 * @param i2c i2c adapter to use.
35 * @return FE pointer on success, NULL on failure.
36 */
37#if defined(CONFIG_DVB_STB6000) || (defined(CONFIG_DVB_STB6000_MODULE) \
38 && defined(MODULE))
39extern struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe, int addr,
40 struct i2c_adapter *i2c);
41#else
42static inline struct dvb_frontend *stb6000_attach(struct dvb_frontend *fe,
43 int addr,
44 struct i2c_adapter *i2c)
45{
46 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
47 return NULL;
48}
49#endif /* CONFIG_DVB_STB6000 */
50
51#endif /* __DVB_STB6000_H__ */
diff --git a/drivers/media/dvb/frontends/stv0288.c b/drivers/media/dvb/frontends/stv0288.c
new file mode 100644
index 000000000000..90e72e771a04
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv0288.c
@@ -0,0 +1,606 @@
1/*
2 Driver for ST STV0288 demodulator
3 Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de
4 for Reel Multimedia
5 Copyright (C) 2008 TurboSight.com, Bob Liu <bob@turbosight.com>
6 Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
7 Removed stb6000 specific tuner code and revised some
8 procedures.
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
24*/
25
26#include <linux/init.h>
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/string.h>
30#include <linux/slab.h>
31#include <linux/jiffies.h>
32#include <asm/div64.h>
33
34#include "dvb_frontend.h"
35#include "stv0288.h"
36
37struct stv0288_state {
38 struct i2c_adapter *i2c;
39 const struct stv0288_config *config;
40 struct dvb_frontend frontend;
41
42 u8 initialised:1;
43 u32 tuner_frequency;
44 u32 symbol_rate;
45 fe_code_rate_t fec_inner;
46 int errmode;
47};
48
49#define STATUS_BER 0
50#define STATUS_UCBLOCKS 1
51
52static int debug;
53static int debug_legacy_dish_switch;
54#define dprintk(args...) \
55 do { \
56 if (debug) \
57 printk(KERN_DEBUG "stv0288: " args); \
58 } while (0)
59
60
61static int stv0288_writeregI(struct stv0288_state *state, u8 reg, u8 data)
62{
63 int ret;
64 u8 buf[] = { reg, data };
65 struct i2c_msg msg = {
66 .addr = state->config->demod_address,
67 .flags = 0,
68 .buf = buf,
69 .len = 2
70 };
71
72 ret = i2c_transfer(state->i2c, &msg, 1);
73
74 if (ret != 1)
75 dprintk("%s: writereg error (reg == 0x%02x, val == 0x%02x, "
76 "ret == %i)\n", __func__, reg, data, ret);
77
78 return (ret != 1) ? -EREMOTEIO : 0;
79}
80
81static int stv0288_write(struct dvb_frontend *fe, u8 *buf, int len)
82{
83 struct stv0288_state *state = fe->demodulator_priv;
84
85 if (len != 2)
86 return -EINVAL;
87
88 return stv0288_writeregI(state, buf[0], buf[1]);
89}
90
91static u8 stv0288_readreg(struct stv0288_state *state, u8 reg)
92{
93 int ret;
94 u8 b0[] = { reg };
95 u8 b1[] = { 0 };
96 struct i2c_msg msg[] = {
97 {
98 .addr = state->config->demod_address,
99 .flags = 0,
100 .buf = b0,
101 .len = 1
102 }, {
103 .addr = state->config->demod_address,
104 .flags = I2C_M_RD,
105 .buf = b1,
106 .len = 1
107 }
108 };
109
110 ret = i2c_transfer(state->i2c, msg, 2);
111
112 if (ret != 2)
113 dprintk("%s: readreg error (reg == 0x%02x, ret == %i)\n",
114 __func__, reg, ret);
115
116 return b1[0];
117}
118
119static int stv0288_set_symbolrate(struct dvb_frontend *fe, u32 srate)
120{
121 struct stv0288_state *state = fe->demodulator_priv;
122 unsigned int temp;
123 unsigned char b[3];
124
125 if ((srate < 1000000) || (srate > 45000000))
126 return -EINVAL;
127
128 temp = (unsigned int)srate / 1000;
129
130 temp = temp * 32768;
131 temp = temp / 25;
132 temp = temp / 125;
133 b[0] = (unsigned char)((temp >> 12) & 0xff);
134 b[1] = (unsigned char)((temp >> 4) & 0xff);
135 b[2] = (unsigned char)((temp << 4) & 0xf0);
136 stv0288_writeregI(state, 0x28, 0x80); /* SFRH */
137 stv0288_writeregI(state, 0x29, 0); /* SFRM */
138 stv0288_writeregI(state, 0x2a, 0); /* SFRL */
139
140 stv0288_writeregI(state, 0x28, b[0]);
141 stv0288_writeregI(state, 0x29, b[1]);
142 stv0288_writeregI(state, 0x2a, b[2]);
143 dprintk("stv0288: stv0288_set_symbolrate\n");
144
145 return 0;
146}
147
148static int stv0288_send_diseqc_msg(struct dvb_frontend *fe,
149 struct dvb_diseqc_master_cmd *m)
150{
151 struct stv0288_state *state = fe->demodulator_priv;
152
153 int i;
154
155 dprintk("%s\n", __func__);
156
157 stv0288_writeregI(state, 0x09, 0);
158 msleep(30);
159 stv0288_writeregI(state, 0x05, 0x16);
160
161 for (i = 0; i < m->msg_len; i++) {
162 if (stv0288_writeregI(state, 0x06, m->msg[i]))
163 return -EREMOTEIO;
164 msleep(12);
165 }
166
167 return 0;
168}
169
170static int stv0288_send_diseqc_burst(struct dvb_frontend *fe,
171 fe_sec_mini_cmd_t burst)
172{
173 struct stv0288_state *state = fe->demodulator_priv;
174
175 dprintk("%s\n", __func__);
176
177 if (stv0288_writeregI(state, 0x05, 0x16))/* burst mode */
178 return -EREMOTEIO;
179
180 if (stv0288_writeregI(state, 0x06, burst == SEC_MINI_A ? 0x00 : 0xff))
181 return -EREMOTEIO;
182
183 if (stv0288_writeregI(state, 0x06, 0x12))
184 return -EREMOTEIO;
185
186 return 0;
187}
188
189static int stv0288_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
190{
191 struct stv0288_state *state = fe->demodulator_priv;
192
193 switch (tone) {
194 case SEC_TONE_ON:
195 if (stv0288_writeregI(state, 0x05, 0x10))/* burst mode */
196 return -EREMOTEIO;
197 return stv0288_writeregI(state, 0x06, 0xff);
198
199 case SEC_TONE_OFF:
200 if (stv0288_writeregI(state, 0x05, 0x13))/* burst mode */
201 return -EREMOTEIO;
202 return stv0288_writeregI(state, 0x06, 0x00);
203
204 default:
205 return -EINVAL;
206 }
207}
208
209static u8 stv0288_inittab[] = {
210 0x01, 0x15,
211 0x02, 0x20,
212 0x09, 0x0,
213 0x0a, 0x4,
214 0x0b, 0x0,
215 0x0c, 0x0,
216 0x0d, 0x0,
217 0x0e, 0xd4,
218 0x0f, 0x30,
219 0x11, 0x80,
220 0x12, 0x03,
221 0x13, 0x48,
222 0x14, 0x84,
223 0x15, 0x45,
224 0x16, 0xb7,
225 0x17, 0x9c,
226 0x18, 0x0,
227 0x19, 0xa6,
228 0x1a, 0x88,
229 0x1b, 0x8f,
230 0x1c, 0xf0,
231 0x20, 0x0b,
232 0x21, 0x54,
233 0x22, 0x0,
234 0x23, 0x0,
235 0x2b, 0xff,
236 0x2c, 0xf7,
237 0x30, 0x0,
238 0x31, 0x1e,
239 0x32, 0x14,
240 0x33, 0x0f,
241 0x34, 0x09,
242 0x35, 0x0c,
243 0x36, 0x05,
244 0x37, 0x2f,
245 0x38, 0x16,
246 0x39, 0xbe,
247 0x3a, 0x0,
248 0x3b, 0x13,
249 0x3c, 0x11,
250 0x3d, 0x30,
251 0x40, 0x63,
252 0x41, 0x04,
253 0x42, 0x60,
254 0x43, 0x00,
255 0x44, 0x00,
256 0x45, 0x00,
257 0x46, 0x00,
258 0x47, 0x00,
259 0x4a, 0x00,
260 0x50, 0x10,
261 0x51, 0x38,
262 0x52, 0x21,
263 0x58, 0x54,
264 0x59, 0x86,
265 0x5a, 0x0,
266 0x5b, 0x9b,
267 0x5c, 0x08,
268 0x5d, 0x7f,
269 0x5e, 0x0,
270 0x5f, 0xff,
271 0x70, 0x0,
272 0x71, 0x0,
273 0x72, 0x0,
274 0x74, 0x0,
275 0x75, 0x0,
276 0x76, 0x0,
277 0x81, 0x0,
278 0x82, 0x3f,
279 0x83, 0x3f,
280 0x84, 0x0,
281 0x85, 0x0,
282 0x88, 0x0,
283 0x89, 0x0,
284 0x8a, 0x0,
285 0x8b, 0x0,
286 0x8c, 0x0,
287 0x90, 0x0,
288 0x91, 0x0,
289 0x92, 0x0,
290 0x93, 0x0,
291 0x94, 0x1c,
292 0x97, 0x0,
293 0xa0, 0x48,
294 0xa1, 0x0,
295 0xb0, 0xb8,
296 0xb1, 0x3a,
297 0xb2, 0x10,
298 0xb3, 0x82,
299 0xb4, 0x80,
300 0xb5, 0x82,
301 0xb6, 0x82,
302 0xb7, 0x82,
303 0xb8, 0x20,
304 0xb9, 0x0,
305 0xf0, 0x0,
306 0xf1, 0x0,
307 0xf2, 0xc0,
308 0x51, 0x36,
309 0x52, 0x09,
310 0x53, 0x94,
311 0x54, 0x62,
312 0x55, 0x29,
313 0x56, 0x64,
314 0x57, 0x2b,
315 0xff, 0xff,
316};
317
318static int stv0288_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t volt)
319{
320 dprintk("%s: %s\n", __func__,
321 volt == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
322 volt == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "??");
323
324 return 0;
325}
326
327static int stv0288_init(struct dvb_frontend *fe)
328{
329 struct stv0288_state *state = fe->demodulator_priv;
330 int i;
331
332 dprintk("stv0288: init chip\n");
333 stv0288_writeregI(state, 0x41, 0x04);
334 msleep(50);
335
336 for (i = 0; !(stv0288_inittab[i] == 0xff &&
337 stv0288_inittab[i + 1] == 0xff); i += 2)
338 stv0288_writeregI(state, stv0288_inittab[i],
339 stv0288_inittab[i + 1]);
340
341 return 0;
342}
343
344static int stv0288_read_status(struct dvb_frontend *fe, fe_status_t *status)
345{
346 struct stv0288_state *state = fe->demodulator_priv;
347
348 u8 sync = stv0288_readreg(state, 0x24);
349 if (sync == 255)
350 sync = 0;
351
352 dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
353
354 *status = 0;
355
356 if ((sync & 0x08) == 0x08) {
357 *status |= FE_HAS_LOCK;
358 dprintk("stv0288 has locked\n");
359 }
360
361 return 0;
362}
363
364static int stv0288_read_ber(struct dvb_frontend *fe, u32 *ber)
365{
366 struct stv0288_state *state = fe->demodulator_priv;
367
368 if (state->errmode != STATUS_BER)
369 return 0;
370 *ber = (stv0288_readreg(state, 0x26) << 8) |
371 stv0288_readreg(state, 0x27);
372 dprintk("stv0288_read_ber %d\n", *ber);
373
374 return 0;
375}
376
377
378static int stv0288_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
379{
380 struct stv0288_state *state = fe->demodulator_priv;
381
382 s32 signal = 0xffff - ((stv0288_readreg(state, 0x10) << 8));
383
384
385 signal = signal * 5 / 4;
386 *strength = (signal > 0xffff) ? 0xffff : (signal < 0) ? 0 : signal;
387 dprintk("stv0288_read_signal_strength %d\n", *strength);
388
389 return 0;
390}
391static int stv0288_sleep(struct dvb_frontend *fe)
392{
393 struct stv0288_state *state = fe->demodulator_priv;
394
395 stv0288_writeregI(state, 0x41, 0x84);
396 state->initialised = 0;
397
398 return 0;
399}
400static int stv0288_read_snr(struct dvb_frontend *fe, u16 *snr)
401{
402 struct stv0288_state *state = fe->demodulator_priv;
403
404 s32 xsnr = 0xffff - ((stv0288_readreg(state, 0x2d) << 8)
405 | stv0288_readreg(state, 0x2e));
406 xsnr = 3 * (xsnr - 0xa100);
407 *snr = (xsnr > 0xffff) ? 0xffff : (xsnr < 0) ? 0 : xsnr;
408 dprintk("stv0288_read_snr %d\n", *snr);
409
410 return 0;
411}
412
413static int stv0288_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
414{
415 struct stv0288_state *state = fe->demodulator_priv;
416
417 if (state->errmode != STATUS_BER)
418 return 0;
419 *ucblocks = (stv0288_readreg(state, 0x26) << 8) |
420 stv0288_readreg(state, 0x27);
421 dprintk("stv0288_read_ber %d\n", *ucblocks);
422
423 return 0;
424}
425
426static int stv0288_set_property(struct dvb_frontend *fe, struct dtv_property *p)
427{
428 dprintk("%s(..)\n", __func__);
429 return 0;
430}
431
432static int stv0288_get_property(struct dvb_frontend *fe, struct dtv_property *p)
433{
434 dprintk("%s(..)\n", __func__);
435 return 0;
436}
437
438static int stv0288_set_frontend(struct dvb_frontend *fe,
439 struct dvb_frontend_parameters *dfp)
440{
441 struct stv0288_state *state = fe->demodulator_priv;
442 struct dtv_frontend_properties *c = &fe->dtv_property_cache;
443
444 char tm;
445 unsigned char tda[3];
446
447 dprintk("%s : FE_SET_FRONTEND\n", __func__);
448
449 if (c->delivery_system != SYS_DVBS) {
450 dprintk("%s: unsupported delivery "
451 "system selected (%d)\n",
452 __func__, c->delivery_system);
453 return -EOPNOTSUPP;
454 }
455
456 if (state->config->set_ts_params)
457 state->config->set_ts_params(fe, 0);
458
459 /* only frequency & symbol_rate are used for tuner*/
460 dfp->frequency = c->frequency;
461 dfp->u.qpsk.symbol_rate = c->symbol_rate;
462 if (fe->ops.tuner_ops.set_params) {
463 fe->ops.tuner_ops.set_params(fe, dfp);
464 if (fe->ops.i2c_gate_ctrl)
465 fe->ops.i2c_gate_ctrl(fe, 0);
466 }
467
468 udelay(10);
469 stv0288_set_symbolrate(fe, c->symbol_rate);
470 /* Carrier lock control register */
471 stv0288_writeregI(state, 0x15, 0xc5);
472
473 tda[0] = 0x2b; /* CFRM */
474 tda[2] = 0x0; /* CFRL */
475 for (tm = -6; tm < 7;) {
476 /* Viterbi status */
477 if (stv0288_readreg(state, 0x24) & 0x80)
478 break;
479
480 tda[2] += 40;
481 if (tda[2] < 40)
482 tm++;
483 tda[1] = (unsigned char)tm;
484 stv0288_writeregI(state, 0x2b, tda[1]);
485 stv0288_writeregI(state, 0x2c, tda[2]);
486 udelay(30);
487 }
488
489 state->tuner_frequency = c->frequency;
490 state->fec_inner = FEC_AUTO;
491 state->symbol_rate = c->symbol_rate;
492
493 return 0;
494}
495
496static int stv0288_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
497{
498 struct stv0288_state *state = fe->demodulator_priv;
499
500 if (enable)
501 stv0288_writeregI(state, 0x01, 0xb5);
502 else
503 stv0288_writeregI(state, 0x01, 0x35);
504
505 udelay(1);
506
507 return 0;
508}
509
510static void stv0288_release(struct dvb_frontend *fe)
511{
512 struct stv0288_state *state = fe->demodulator_priv;
513 kfree(state);
514}
515
516static struct dvb_frontend_ops stv0288_ops = {
517
518 .info = {
519 .name = "ST STV0288 DVB-S",
520 .type = FE_QPSK,
521 .frequency_min = 950000,
522 .frequency_max = 2150000,
523 .frequency_stepsize = 1000, /* kHz for QPSK frontends */
524 .frequency_tolerance = 0,
525 .symbol_rate_min = 1000000,
526 .symbol_rate_max = 45000000,
527 .symbol_rate_tolerance = 500, /* ppm */
528 .caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
529 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
530 FE_CAN_QPSK |
531 FE_CAN_FEC_AUTO
532 },
533
534 .release = stv0288_release,
535 .init = stv0288_init,
536 .sleep = stv0288_sleep,
537 .write = stv0288_write,
538 .i2c_gate_ctrl = stv0288_i2c_gate_ctrl,
539 .read_status = stv0288_read_status,
540 .read_ber = stv0288_read_ber,
541 .read_signal_strength = stv0288_read_signal_strength,
542 .read_snr = stv0288_read_snr,
543 .read_ucblocks = stv0288_read_ucblocks,
544 .diseqc_send_master_cmd = stv0288_send_diseqc_msg,
545 .diseqc_send_burst = stv0288_send_diseqc_burst,
546 .set_tone = stv0288_set_tone,
547 .set_voltage = stv0288_set_voltage,
548
549 .set_property = stv0288_set_property,
550 .get_property = stv0288_get_property,
551 .set_frontend = stv0288_set_frontend,
552};
553
554struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
555 struct i2c_adapter *i2c)
556{
557 struct stv0288_state *state = NULL;
558 int id;
559
560 /* allocate memory for the internal state */
561 state = kmalloc(sizeof(struct stv0288_state), GFP_KERNEL);
562 if (state == NULL)
563 goto error;
564
565 /* setup the state */
566 state->config = config;
567 state->i2c = i2c;
568 state->initialised = 0;
569 state->tuner_frequency = 0;
570 state->symbol_rate = 0;
571 state->fec_inner = 0;
572 state->errmode = STATUS_BER;
573
574 stv0288_writeregI(state, 0x41, 0x04);
575 msleep(200);
576 id = stv0288_readreg(state, 0x00);
577 dprintk("stv0288 id %x\n", id);
578
579 /* register 0x00 contains 0x11 for STV0288 */
580 if (id != 0x11)
581 goto error;
582
583 /* create dvb_frontend */
584 memcpy(&state->frontend.ops, &stv0288_ops,
585 sizeof(struct dvb_frontend_ops));
586 state->frontend.demodulator_priv = state;
587 return &state->frontend;
588
589error:
590 kfree(state);
591
592 return NULL;
593}
594EXPORT_SYMBOL(stv0288_attach);
595
596module_param(debug_legacy_dish_switch, int, 0444);
597MODULE_PARM_DESC(debug_legacy_dish_switch,
598 "Enable timing analysis for Dish Network legacy switches");
599
600module_param(debug, int, 0644);
601MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
602
603MODULE_DESCRIPTION("ST STV0288 DVB Demodulator driver");
604MODULE_AUTHOR("Georg Acher, Bob Liu, Igor liplianin");
605MODULE_LICENSE("GPL");
606
diff --git a/drivers/media/dvb/frontends/stv0288.h b/drivers/media/dvb/frontends/stv0288.h
new file mode 100644
index 000000000000..aa0cdd273040
--- /dev/null
+++ b/drivers/media/dvb/frontends/stv0288.h
@@ -0,0 +1,65 @@
1/*
2 Driver for ST STV0288 demodulator
3
4 Copyright (C) 2006 Georg Acher, BayCom GmbH, acher (at) baycom (dot) de
5 for Reel Multimedia
6 Copyright (C) 2008 TurboSight.com, <bob@turbosight.com>
7 Copyright (C) 2008 Igor M. Liplianin <liplianin@me.by>
8 Removed stb6000 specific tuner code and revised some
9 procedures.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
25*/
26
27#ifndef STV0288_H
28#define STV0288_H
29
30#include <linux/dvb/frontend.h>
31#include "dvb_frontend.h"
32
33struct stv0288_config {
34 /* the demodulator's i2c address */
35 u8 demod_address;
36
37 /* minimum delay before retuning */
38 int min_delay_ms;
39
40 int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
41};
42
43#if defined(CONFIG_DVB_STV0288) || (defined(CONFIG_DVB_STV0288_MODULE) && \
44 defined(MODULE))
45extern struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
46 struct i2c_adapter *i2c);
47#else
48static inline struct dvb_frontend *stv0288_attach(const struct stv0288_config *config,
49 struct i2c_adapter *i2c)
50{
51 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
52 return NULL;
53}
54#endif /* CONFIG_DVB_STV0288 */
55
56static inline int stv0288_writereg(struct dvb_frontend *fe, u8 reg, u8 val)
57{
58 int r = 0;
59 u8 buf[] = { reg, val };
60 if (fe->ops.write)
61 r = fe->ops.write(fe, buf, 2);
62 return r;
63}
64
65#endif /* STV0288_H */
diff --git a/drivers/media/dvb/frontends/stv0299.c b/drivers/media/dvb/frontends/stv0299.c
index 35435bef8e79..6c1cb1973c6e 100644
--- a/drivers/media/dvb/frontends/stv0299.c
+++ b/drivers/media/dvb/frontends/stv0299.c
@@ -559,6 +559,8 @@ static int stv0299_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par
559 int invval = 0; 559 int invval = 0;
560 560
561 dprintk ("%s : FE_SET_FRONTEND\n", __func__); 561 dprintk ("%s : FE_SET_FRONTEND\n", __func__);
562 if (state->config->set_ts_params)
563 state->config->set_ts_params(fe, 0);
562 564
563 // set the inversion 565 // set the inversion
564 if (p->inversion == INVERSION_OFF) invval = 0; 566 if (p->inversion == INVERSION_OFF) invval = 0;
diff --git a/drivers/media/dvb/frontends/stv0299.h b/drivers/media/dvb/frontends/stv0299.h
index 3282f43022f5..0fd96e22b650 100644
--- a/drivers/media/dvb/frontends/stv0299.h
+++ b/drivers/media/dvb/frontends/stv0299.h
@@ -89,15 +89,18 @@ struct stv0299_config
89 int min_delay_ms; 89 int min_delay_ms;
90 90
91 /* Set the symbol rate */ 91 /* Set the symbol rate */
92 int (*set_symbol_rate)(struct dvb_frontend* fe, u32 srate, u32 ratio); 92 int (*set_symbol_rate)(struct dvb_frontend *fe, u32 srate, u32 ratio);
93
94 /* Set device param to start dma */
95 int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
93}; 96};
94 97
95#if defined(CONFIG_DVB_STV0299) || (defined(CONFIG_DVB_STV0299_MODULE) && defined(MODULE)) 98#if defined(CONFIG_DVB_STV0299) || (defined(CONFIG_DVB_STV0299_MODULE) && defined(MODULE))
96extern struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, 99extern struct dvb_frontend *stv0299_attach(const struct stv0299_config *config,
97 struct i2c_adapter* i2c); 100 struct i2c_adapter *i2c);
98#else 101#else
99static inline struct dvb_frontend* stv0299_attach(const struct stv0299_config* config, 102static inline struct dvb_frontend *stv0299_attach(const struct stv0299_config *config,
100 struct i2c_adapter* i2c) 103 struct i2c_adapter *i2c)
101{ 104{
102 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); 105 printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
103 return NULL; 106 return NULL;