diff options
author | Antti Palosaari <crope@iki.fi> | 2011-11-07 07:28:29 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-01-10 19:57:06 -0500 |
commit | b021bd84d27583017f3f50f98bb1b952c8450342 (patch) | |
tree | 255655088e465ecb26ec30bc84ff0ca1db05d1b7 /drivers/media/dvb | |
parent | ee9b8c8c27679b2b8ab5e8749cb3813d55b49755 (diff) |
[media] HDIC HD29L2 DMB-TH USB2.0 reference design driver
Signed-off-by: Antti Palosaari <crope@iki.fi>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r-- | drivers/media/dvb/dvb-usb/Kconfig | 7 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/Makefile | 3 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/hdic.c | 365 | ||||
-rw-r--r-- | drivers/media/dvb/dvb-usb/hdic.h | 45 |
4 files changed, 420 insertions, 0 deletions
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 9f203c6767a6..df36488b7031 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -361,6 +361,13 @@ config DVB_USB_EC168 | |||
361 | help | 361 | help |
362 | Say Y here to support the E3C EC168 DVB-T USB2.0 receiver. | 362 | Say Y here to support the E3C EC168 DVB-T USB2.0 receiver. |
363 | 363 | ||
364 | config DVB_USB_HDIC | ||
365 | tristate "HDIC HD29L2 reference design" | ||
366 | depends on DVB_USB | ||
367 | select DVB_HD29L2 if !DVB_FE_CUSTOMISE | ||
368 | help | ||
369 | Say Y here to support the HDIC HD29L2 reference design. | ||
370 | |||
364 | config DVB_USB_AZ6027 | 371 | config DVB_USB_AZ6027 |
365 | tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support" | 372 | tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support" |
366 | depends on DVB_USB | 373 | depends on DVB_USB |
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile index 26c8b9e57050..bd724a7eaba6 100644 --- a/drivers/media/dvb/dvb-usb/Makefile +++ b/drivers/media/dvb/dvb-usb/Makefile | |||
@@ -88,6 +88,9 @@ obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o | |||
88 | dvb-usb-ec168-objs = ec168.o | 88 | dvb-usb-ec168-objs = ec168.o |
89 | obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o | 89 | obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o |
90 | 90 | ||
91 | dvb-usb-hdic-objs = hdic.o | ||
92 | obj-$(CONFIG_DVB_USB_HDIC) += dvb-usb-hdic.o | ||
93 | |||
91 | dvb-usb-az6027-objs = az6027.o | 94 | dvb-usb-az6027-objs = az6027.o |
92 | obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o | 95 | obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o |
93 | 96 | ||
diff --git a/drivers/media/dvb/dvb-usb/hdic.c b/drivers/media/dvb/dvb-usb/hdic.c new file mode 100644 index 000000000000..c5768c8f47b8 --- /dev/null +++ b/drivers/media/dvb/dvb-usb/hdic.c | |||
@@ -0,0 +1,365 @@ | |||
1 | /* | ||
2 | * DVB USB Linux driver for the HDIC receiver | ||
3 | * | ||
4 | * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D | ||
5 | * | ||
6 | * Author: Antti Palosaari <crope@iki.fi> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include "hdic.h" | ||
24 | #include "hd29l2.h" | ||
25 | #include "mxl5007t.h" | ||
26 | |||
27 | /* debug */ | ||
28 | static int dvb_usb_hdic_debug; | ||
29 | module_param_named(debug, dvb_usb_hdic_debug, int, 0644); | ||
30 | MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS); | ||
31 | DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); | ||
32 | /* | ||
33 | * I2C addresses (7bit) found by probing I2C bus: | ||
34 | * 0x48 ?? | ||
35 | * 0x51 eeprom | ||
36 | * 0x60 MaxLinear MXL5007T tuner | ||
37 | * 0x73 HDIC HD29L2 demod | ||
38 | * | ||
39 | * Xtals: | ||
40 | * 24.000 MHz Cypress CY7C68013A-56 (FX2) | ||
41 | * 30.400 MHz HDIC HD29L2 | ||
42 | * 24.000 MHz MaxLinear MXL5007T | ||
43 | * | ||
44 | * I/Os: | ||
45 | * RDY1 / SLWR == TS_CLK (USB_SLWR = !TS_CLK&TS_VALID) | ||
46 | * PA1 / INT1 == 29L1_RESET RST_N | ||
47 | */ | ||
48 | |||
49 | /* | ||
50 | * See Qanu DVB-T USB2.0 communication protocol specification for more | ||
51 | * information used USB API. | ||
52 | */ | ||
53 | |||
54 | /* I2C */ | ||
55 | static int hdic_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[], | ||
56 | int num) | ||
57 | { | ||
58 | int ret; | ||
59 | struct dvb_usb_device *d = i2c_get_adapdata(adap); | ||
60 | u8 buf[64]; | ||
61 | |||
62 | /* | ||
63 | * increase sleep when there is a lot of errors: | ||
64 | * dvb-usb: recv bulk message failed: -110 | ||
65 | */ | ||
66 | #define HDIC_I2C_SLEEP 1 | ||
67 | |||
68 | if (mutex_lock_interruptible(&d->i2c_mutex) < 0) | ||
69 | return -EAGAIN; | ||
70 | |||
71 | if (num == 2 && !(msg[0].flags & I2C_M_RD) && | ||
72 | (msg[1].flags & I2C_M_RD)) { | ||
73 | /* I2C write + read combination (typical register read) */ | ||
74 | buf[0] = HDIC_CMD_I2C; | ||
75 | buf[1] = (msg[0].addr << 1); /* I2C write */ | ||
76 | buf[2] = msg[0].len; | ||
77 | buf[3] = 1; /* no I2C stop => repeated start */ | ||
78 | memcpy(&buf[4], msg[0].buf, msg[0].len); | ||
79 | ret = dvb_usb_generic_rw(d, buf, 4+msg[0].len, buf, 1, | ||
80 | HDIC_I2C_SLEEP); | ||
81 | if (ret) | ||
82 | goto err; | ||
83 | |||
84 | buf[0] = HDIC_CMD_I2C; | ||
85 | buf[1] = (msg[1].addr << 1) | 0x01; /* I2C read */ | ||
86 | buf[2] = msg[1].len; | ||
87 | buf[3] = 0; /* I2C stop */ | ||
88 | ret = dvb_usb_generic_rw(d, buf, 4, buf, 1+msg[1].len, | ||
89 | HDIC_I2C_SLEEP); | ||
90 | if (ret) | ||
91 | goto err; | ||
92 | |||
93 | memcpy(msg[1].buf, &buf[1], msg[1].len); | ||
94 | |||
95 | } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) { | ||
96 | /* I2C write (typical register write) */ | ||
97 | buf[0] = HDIC_CMD_I2C; | ||
98 | buf[1] = (msg[0].addr << 1); /* I2C write */ | ||
99 | buf[2] = msg[0].len; | ||
100 | buf[3] = 0; /* I2C stop */ | ||
101 | memcpy(&buf[4], msg[0].buf, msg[0].len); | ||
102 | ret = dvb_usb_generic_rw(d, buf, 4+msg[0].len, buf, 1, | ||
103 | HDIC_I2C_SLEEP); | ||
104 | if (ret) | ||
105 | goto err; | ||
106 | } else { | ||
107 | ret = -EOPNOTSUPP; | ||
108 | goto err; | ||
109 | } | ||
110 | |||
111 | usleep_range(100, 1000); | ||
112 | |||
113 | mutex_unlock(&d->i2c_mutex); | ||
114 | |||
115 | return num; | ||
116 | |||
117 | err: | ||
118 | deb_info("%s: failed=%d\n", __func__, ret); | ||
119 | mutex_unlock(&d->i2c_mutex); | ||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | static u32 hdic_i2c_func(struct i2c_adapter *adapter) | ||
124 | { | ||
125 | return I2C_FUNC_I2C; | ||
126 | } | ||
127 | |||
128 | static struct i2c_algorithm hdic_i2c_algo = { | ||
129 | .master_xfer = hdic_i2c_xfer, | ||
130 | .functionality = hdic_i2c_func, | ||
131 | }; | ||
132 | |||
133 | /* Callbacks for DVB USB */ | ||
134 | static int hdic_power_ctrl(struct dvb_usb_device *d, int enable) | ||
135 | { | ||
136 | u8 sbuf[] = { HDIC_CMD_SLEEP_MODE, enable ? 0 : 1 }; | ||
137 | u8 rbuf[1]; | ||
138 | |||
139 | deb_info("%s: enable=%d\n", __func__, enable); | ||
140 | |||
141 | return dvb_usb_generic_rw(d, sbuf, sizeof(sbuf), rbuf, sizeof(rbuf), 0); | ||
142 | } | ||
143 | |||
144 | static int hdic_streaming_ctrl(struct dvb_usb_adapter *adap, int enable) | ||
145 | { | ||
146 | u8 sbuf[] = { HDIC_CMD_CONTROL_STREAM_TRANSFER, enable }; | ||
147 | u8 rbuf[1]; | ||
148 | |||
149 | deb_info("%s: enable=%d\n", __func__, enable); | ||
150 | |||
151 | return dvb_usb_generic_rw(adap->dev, sbuf, sizeof(sbuf), rbuf, | ||
152 | sizeof(rbuf), 0); | ||
153 | } | ||
154 | |||
155 | /* general callback */ | ||
156 | static int hdic_frontend_callback(void *priv, int component, int cmd, int arg) | ||
157 | { | ||
158 | int ret; | ||
159 | struct dvb_frontend *fe = priv; | ||
160 | struct dvb_usb_adapter *adap = fe->dvb->priv; | ||
161 | u8 sbuf[2] = { HDIC_CMD_DEMOD_RESET }; | ||
162 | u8 rbuf[1]; | ||
163 | |||
164 | deb_info("%s:\n", __func__); | ||
165 | |||
166 | /* enable demod reset */ | ||
167 | sbuf[1] = 1; | ||
168 | ret = dvb_usb_generic_rw(adap->dev, sbuf, sizeof(sbuf), | ||
169 | rbuf, sizeof(rbuf), 0); | ||
170 | if (ret) | ||
171 | deb_info("%s: failed enable demod reset\n", __func__); | ||
172 | |||
173 | usleep_range(100, 10000); | ||
174 | |||
175 | /* disable demod reset */ | ||
176 | sbuf[1] = 0; | ||
177 | ret = dvb_usb_generic_rw(adap->dev, sbuf, sizeof(sbuf), rbuf, | ||
178 | sizeof(rbuf), 0); | ||
179 | if (ret) | ||
180 | deb_info("%s: failed disable demod reset\n", __func__); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static struct hd29l2_config hdic_hd29l2_config = { | ||
186 | .i2c_addr = 0x73, | ||
187 | .tuner_i2c_addr = 0x60, | ||
188 | .ts_mode = HD29L2_TS_PARALLEL, | ||
189 | }; | ||
190 | |||
191 | static int hdic_frontend_attach(struct dvb_usb_adapter *adap) | ||
192 | { | ||
193 | int ret; | ||
194 | u8 sbuf[2]; | ||
195 | u8 rbuf[3]; | ||
196 | |||
197 | deb_info("%s:\n", __func__); | ||
198 | |||
199 | /* wake-up device */ | ||
200 | sbuf[0] = HDIC_CMD_GET_FIRMWARE_VERSION; | ||
201 | ret = dvb_usb_generic_rw(adap->dev, sbuf, sizeof(sbuf), rbuf, | ||
202 | sizeof(rbuf), 0); | ||
203 | if (ret) | ||
204 | deb_info("%s: failed wake-up\n", __func__); | ||
205 | |||
206 | /* disable demod reset */ | ||
207 | sbuf[0] = HDIC_CMD_DEMOD_RESET; | ||
208 | sbuf[1] = 0; | ||
209 | ret = dvb_usb_generic_rw(adap->dev, sbuf, sizeof(sbuf), rbuf, | ||
210 | sizeof(rbuf), 0); | ||
211 | if (ret) | ||
212 | deb_info("%s: failed disable demod reset\n", __func__); | ||
213 | |||
214 | /* attach demod */ | ||
215 | adap->fe_adap[0].fe = dvb_attach(hd29l2_attach, &hdic_hd29l2_config, | ||
216 | &adap->dev->i2c_adap); | ||
217 | if (adap->fe_adap[0].fe == NULL) { | ||
218 | ret = -ENODEV; | ||
219 | goto err; | ||
220 | } | ||
221 | |||
222 | /* setup the reset callback */ | ||
223 | adap->fe_adap[0].fe->callback = hdic_frontend_callback; | ||
224 | |||
225 | return 0; | ||
226 | err: | ||
227 | deb_info("%s: failed=%d\n", __func__, ret); | ||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | static struct mxl5007t_config hdic_mxl5007t_config = { | ||
232 | .xtal_freq_hz = MxL_XTAL_24_MHZ, | ||
233 | .if_freq_hz = MxL_IF_36_15_MHZ, | ||
234 | .invert_if = 1, | ||
235 | }; | ||
236 | |||
237 | static int hdic_tuner_attach(struct dvb_usb_adapter *adap) | ||
238 | { | ||
239 | int ret; | ||
240 | |||
241 | deb_info("%s:\n", __func__); | ||
242 | |||
243 | if (dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe, | ||
244 | &adap->dev->i2c_adap, 0x60, &hdic_mxl5007t_config) == NULL) { | ||
245 | ret = -ENODEV; | ||
246 | goto err; | ||
247 | } | ||
248 | |||
249 | return 0; | ||
250 | err: | ||
251 | deb_info("%s: failed=%d\n", __func__, ret); | ||
252 | return ret; | ||
253 | } | ||
254 | |||
255 | /* DVB USB Driver stuff */ | ||
256 | static struct dvb_usb_device_properties hdic_properties; | ||
257 | |||
258 | static int hdic_probe(struct usb_interface *intf, | ||
259 | const struct usb_device_id *id) | ||
260 | { | ||
261 | return dvb_usb_device_init(intf, &hdic_properties, THIS_MODULE, NULL, | ||
262 | adapter_nr); | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * 04b4:1004 HDIC development board firmware | ||
267 | * 04b4:8613 CY7C68013 EZ-USB FX2 USB 2.0 Development Kit | ||
268 | */ | ||
269 | static struct usb_device_id hdic_id[] = { | ||
270 | #define HDIC_8613 0 /* CY7C68013 EZ-USB FX2 USB 2.0 Development Kit */ | ||
271 | #define HDIC_1004 1 /* HDIC 04b4:1004 */ | ||
272 | #define HDIC_LINUX 2 /* HDIC Linux custom firmware */ | ||
273 | |||
274 | [HDIC_8613] = {USB_DEVICE(USB_VID_CYPRESS, 0x8613)}, | ||
275 | [HDIC_1004] = {USB_DEVICE(USB_VID_CYPRESS, 0x1004)}, | ||
276 | [HDIC_LINUX] = {USB_DEVICE(USB_VID_CYPRESS, 0x1e04)}, | ||
277 | {} /* terminating entry */ | ||
278 | }; | ||
279 | |||
280 | MODULE_DEVICE_TABLE(usb, hdic_id); | ||
281 | |||
282 | static struct dvb_usb_device_properties hdic_properties = { | ||
283 | .caps = DVB_USB_IS_AN_I2C_ADAPTER, | ||
284 | |||
285 | .usb_ctrl = CYPRESS_FX2, | ||
286 | .firmware = "dvb-usb-hdic.fw", | ||
287 | |||
288 | .num_adapters = 1, | ||
289 | .adapter = { | ||
290 | { | ||
291 | .num_frontends = 1, | ||
292 | .fe = { | ||
293 | { | ||
294 | .streaming_ctrl = hdic_streaming_ctrl, | ||
295 | .frontend_attach = hdic_frontend_attach, | ||
296 | .tuner_attach = hdic_tuner_attach, | ||
297 | |||
298 | .stream = { | ||
299 | .type = USB_BULK, | ||
300 | .count = 5, | ||
301 | .endpoint = 0x02, | ||
302 | .u = { | ||
303 | .bulk = { | ||
304 | .buffersize = | ||
305 | (4*512), | ||
306 | } | ||
307 | } | ||
308 | }, | ||
309 | } | ||
310 | }, | ||
311 | } | ||
312 | }, | ||
313 | |||
314 | .power_ctrl = hdic_power_ctrl, | ||
315 | |||
316 | .i2c_algo = &hdic_i2c_algo, | ||
317 | |||
318 | .generic_bulk_ctrl_endpoint = 1, | ||
319 | |||
320 | .num_device_descs = 1, | ||
321 | .devices = { | ||
322 | { | ||
323 | .name = "HDIC reference design", | ||
324 | .cold_ids = {&hdic_id[HDIC_8613], | ||
325 | &hdic_id[HDIC_1004], NULL}, | ||
326 | .warm_ids = {&hdic_id[HDIC_LINUX], NULL}, | ||
327 | }, | ||
328 | } | ||
329 | }; | ||
330 | |||
331 | static struct usb_driver hdic_driver = { | ||
332 | .name = "dvb_usb_hdic", | ||
333 | .probe = hdic_probe, | ||
334 | .disconnect = dvb_usb_device_exit, | ||
335 | .id_table = hdic_id, | ||
336 | }; | ||
337 | |||
338 | /* module stuff */ | ||
339 | static int __init hdic_module_init(void) | ||
340 | { | ||
341 | int ret; | ||
342 | |||
343 | deb_info("%s:\n", __func__); | ||
344 | |||
345 | ret = usb_register(&hdic_driver); | ||
346 | if (ret) | ||
347 | err("module init failed=%d", ret); | ||
348 | |||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | static void __exit hdic_module_exit(void) | ||
353 | { | ||
354 | deb_info("%s:\n", __func__); | ||
355 | |||
356 | /* deregister this driver from the USB subsystem */ | ||
357 | usb_deregister(&hdic_driver); | ||
358 | } | ||
359 | |||
360 | module_init(hdic_module_init); | ||
361 | module_exit(hdic_module_exit); | ||
362 | |||
363 | MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>"); | ||
364 | MODULE_DESCRIPTION("HDIC DMB-TH reference design USB2.0 driver (custom firmware)"); | ||
365 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/media/dvb/dvb-usb/hdic.h b/drivers/media/dvb/dvb-usb/hdic.h new file mode 100644 index 000000000000..01ee73b8c98f --- /dev/null +++ b/drivers/media/dvb/dvb-usb/hdic.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * DVB USB Linux driver for the HDIC receiver | ||
3 | * | ||
4 | * Copyright (C) 2011 Metropolia University of Applied Sciences, Electria R&D | ||
5 | * | ||
6 | * Author: Antti Palosaari <crope@iki.fi> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #ifndef HDIC_H | ||
24 | #define HDIC_H | ||
25 | |||
26 | #define DVB_USB_LOG_PREFIX "hdic" | ||
27 | #include "dvb-usb.h" | ||
28 | |||
29 | #define deb_info(args...) dprintk(dvb_usb_hdic_debug, 0x01, args) | ||
30 | #define deb_rc(args...) dprintk(dvb_usb_hdic_debug, 0x02, args) | ||
31 | #define deb_xfer(args...) dprintk(dvb_usb_hdic_debug, 0x04, args) | ||
32 | #define deb_reg(args...) dprintk(dvb_usb_hdic_debug, 0x08, args) | ||
33 | #define deb_i2c(args...) dprintk(dvb_usb_hdic_debug, 0x10, args) | ||
34 | #define deb_fw(args...) dprintk(dvb_usb_hdic_debug, 0x20, args) | ||
35 | |||
36 | enum hdic_cmd { | ||
37 | HDIC_CMD_I2C = 0x00, | ||
38 | HDIC_CMD_CONTROL_STREAM_TRANSFER = 0x03, | ||
39 | HDIC_CMD_SLEEP_MODE = 0x09, | ||
40 | HDIC_CMD_GET_FIRMWARE_VERSION = 0x0a, | ||
41 | HDIC_CMD_DEMOD_RESET = 0x0b, | ||
42 | }; | ||
43 | |||
44 | |||
45 | #endif | ||