2 * Copyright (c) 2004-2007 Marcus Overhagen <marcus@overhagen.de>
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify,
8 * merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
25 #include <KernelExport.h>
28 #include "dvb_interface.h"
30 #include "cx23882_i2c.h"
37 #define TRACE_INTERFACE
38 #ifdef TRACE_INTERFACE
47 dump_eeprom(cx23882_device
*device
)
56 res
= i2c_xfer(device
->i2c_bus
, I2C_ADDR_EEPROM
, &adr
, 1, d
, sizeof(d
));
58 TRACE("i2c_read failed: %08lx\n", res
);
61 for (p
= d
, i
= 0; i
< ((int)sizeof(d
) / 8); i
++, p
+= 8)
62 TRACE("EEPROM %02x: %02x %02x %02x %02x %02x %02x %02x %02x\n", i
* 8, p
[0], p
[1], p
[2], p
[3], p
[4], p
[5], p
[6], p
[7]);
69 interface_attach(void **cookie
, const pci_info
*info
)
71 cx23882_device
*device
;
75 TRACE("interface_attach\n");
77 device
= malloc(sizeof(cx23882_device
));
83 memset(device
, 0, sizeof(*device
));
84 device
->regs_area
= -1;
85 device
->dma_buf1_area
= -1;
86 device
->dma_buf2_area
= -1;
87 device
->capture_sem
= -1;
89 device
->pci_info
= info
;
91 // enable busmaster and memory mapped access, disable io port access
92 val
= gPci
->read_pci_config(device
->pci_info
->bus
, device
->pci_info
->device
, device
->pci_info
->function
, PCI_command
, 2);
93 val
= PCI_PCICMD_BME
| PCI_PCICMD_MSE
| (val
& ~PCI_PCICMD_IOS
);
94 gPci
->write_pci_config(device
->pci_info
->bus
, device
->pci_info
->device
, device
->pci_info
->function
, PCI_command
, 2, val
);
96 // adjust PCI latency timer
97 val
= gPci
->read_pci_config(device
->pci_info
->bus
, device
->pci_info
->device
, device
->pci_info
->function
, PCI_latency
, 1);
98 TRACE("PCI latency is %02" B_PRIx32
", changing to %02x\n", val
,
100 gPci
->write_pci_config(device
->pci_info
->bus
, device
->pci_info
->device
, device
->pci_info
->function
, PCI_latency
, 1, PCI_LATENCY
);
103 device
->irq
= gPci
->read_pci_config(device
->pci_info
->bus
, device
->pci_info
->device
, device
->pci_info
->function
, PCI_interrupt_line
, 1);
104 if (device
->irq
== 0 || device
->irq
== 0xff) {
105 dprintf("cx23882: Error, no IRQ assigned\n");
108 TRACE("IRQ %d\n", device
->irq
);
110 // map registers into memory
111 val
= gPci
->read_pci_config(device
->pci_info
->bus
, device
->pci_info
->device
, device
->pci_info
->function
, 0x10, 4);
112 val
&= PCI_address_memory_32_mask
;
114 dprintf("cx23882: Error, no memory space assigned\n");
117 TRACE("hardware register address 0x%" B_PRIx32
"\n", val
);
118 device
->regs_area
= map_mem(&device
->regs
, (addr_t
)val
,
119 16777216 /* 16 MB */, 0, "cx23882 registers");
120 if (device
->regs_area
< B_OK
) {
121 dprintf("cx23882: Error, can't map hardware registers\n");
124 TRACE("mapped registers to %p\n", device
->regs
);
126 device
->capture_sem
= create_sem(0, "cx23882 capture");
128 cx23882_reset(device
);
130 if (i2c_init(device
) < B_OK
) {
131 dprintf("cx23882: Error, can't init I2C\n");
135 if (cx23882_init(device
) < B_OK
) {
136 dprintf("cx23882: Error, can't init hardware\n");
140 for (i
= 0; i
< 20; i
++)
141 if (cx22702_init(device
->i2c_bus
) == B_OK
)
144 TRACE("cx22702_init failed\n");
148 // setup interrupt handler
149 if (install_io_interrupt_handler(device
->irq
, cx23882_int
, device
, 0) < B_OK
) {
150 dprintf("cx23882: Error, can't install interrupt handler\n");
154 // dump_eeprom(device);
155 // dtt7582_test(device->i2c_bus);
165 interface_detach(void *cookie
)
167 cx23882_device
*device
= cookie
;
169 i2c_terminate(device
);
171 if (cx23882_terminate(device
) < B_OK
) {
174 remove_io_interrupt_handler(device
->irq
, cx23882_int
, device
);
176 delete_area(device
->regs_area
);
178 delete_sem(device
->capture_sem
);
180 TRACE("interface_detach\n");
185 interface_get_interface_info(dvb_interface_info_t
*info
)
187 memset(info
, 0, sizeof(*info
));
190 info
->type
= DVB_TYPE_DVB_T
;
191 strcpy(info
->name
, "CX23882");
192 strcpy(info
->info
, "Hauppauge WinTV-NOVA-T model 928 driver, Copyright (c) 2005 Marcus Overhagen");
197 interface_ioctl(void *cookie
, uint32 op
, void *arg
, size_t len
)
199 cx23882_device
*device
= cookie
;
203 case DVB_GET_INTERFACE_INFO
:
205 dvb_interface_info_t info
;
206 interface_get_interface_info(&info
);
207 if (user_memcpy(arg
, &info
, sizeof(info
)) < B_OK
)
208 return B_BAD_ADDRESS
;
212 case DVB_GET_FREQUENCY_INFO
:
214 dvb_frequency_info_t info
;
215 if ((res
= cx22702_get_frequency_info(device
->i2c_bus
, &info
)) < B_OK
)
217 if (user_memcpy(arg
, &info
, sizeof(info
)) < B_OK
)
218 return B_BAD_ADDRESS
;
222 case DVB_START_CAPTURE
:
224 return cx23882_start_capture(device
);
227 case DVB_STOP_CAPTURE
:
229 return cx23882_stop_capture(device
);
232 case DVB_SET_TUNING_PARAMETERS
:
234 dvb_tuning_parameters_t params
;
235 if (user_memcpy(¶ms
, arg
, sizeof(params
)) < B_OK
)
236 return B_BAD_ADDRESS
;
237 if ((res
= cx22702_set_tuning_parameters(device
->i2c_bus
, ¶ms
.u
.dvb_t
)) < B_OK
)
242 case DVB_GET_TUNING_PARAMETERS
:
244 dvb_tuning_parameters_t params
;
245 if ((res
= cx22702_get_tuning_parameters(device
->i2c_bus
, ¶ms
.u
.dvb_t
)) < B_OK
)
247 if (user_memcpy(arg
, ¶ms
, sizeof(params
)) < B_OK
)
248 return B_BAD_ADDRESS
;
255 if ((res
= cx22702_get_status(device
->i2c_bus
, &status
)) < B_OK
)
257 if (user_memcpy(arg
, &status
, sizeof(status
)) < B_OK
)
258 return B_BAD_ADDRESS
;
265 if ((res
= cx22702_get_ss(device
->i2c_bus
, &value
)) < B_OK
)
267 if (user_memcpy(arg
, &value
, sizeof(value
)) < B_OK
)
268 return B_BAD_ADDRESS
;
275 if ((res
= cx22702_get_ber(device
->i2c_bus
, &value
)) < B_OK
)
277 if (user_memcpy(arg
, &value
, sizeof(value
)) < B_OK
)
278 return B_BAD_ADDRESS
;
285 if ((res
= cx22702_get_snr(device
->i2c_bus
, &value
)) < B_OK
)
287 if (user_memcpy(arg
, &value
, sizeof(value
)) < B_OK
)
288 return B_BAD_ADDRESS
;
295 if ((res
= cx22702_get_upc(device
->i2c_bus
, &value
)) < B_OK
)
297 if (user_memcpy(arg
, &value
, sizeof(value
)) < B_OK
)
298 return B_BAD_ADDRESS
;
304 dvb_capture_t cap_data
;
305 // wait for data ready interrupt, with 100 ms timeout (in case tuning failed, bad reception, etc)
306 if ((res
= acquire_sem_etc(device
->capture_sem
, 1, B_CAN_INTERRUPT
| B_RELATIVE_TIMEOUT
, 100000)) < B_OK
)
308 cap_data
.data
= device
->capture_data
;
309 cap_data
.size
= device
->capture_size
;
310 cap_data
.end_time
= device
->capture_end_time
;
311 if (user_memcpy(arg
, &cap_data
, sizeof(cap_data
)) < B_OK
)
312 return B_BAD_ADDRESS
;
318 TRACE("interface_ioctl\n");