/* ivtv driver initialization and card probing Copyright (C) 2003-2004 Kevin Thayer <nufan_wfk at yahoo.com> Copyright (C) 2004 Chris Kennedy <c@groovy.org> Copyright (C) 2005-2007 Hans Verkuil <hverkuil@xs4all.nl>
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Main Driver file for the ivtv project: * Driver for the Conexant CX23415/CX23416 chip. * Author: Kevin Thayer (nufan_wfk at yahoo.com) * License: GPL * * ----- * MPG600/MPG160 support by T.Adachi <tadachi@tadachi-net.com> * and Takeru KOMORIYA<komoriya@paken.org> * * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org> * using information provided by Jiun-Kuei Jung @ AVerMedia. * * Kurouto Sikou CX23416GYC-STVLP tested by K.Ohta <alpha292@bremen.or.jp> * using information from T.Adachi,Takeru KOMORIYA and others :-) * * Nagase TRANSGEAR 5000TV, Aopen VA2000MAX-STN6 and I/O data GV-MVP/RX * version by T.Adachi. Special thanks Mr.Suzuki
*/
/* If you have already X v4l cards, then set this to X. This way the device numbers stay matched. Example: you have a WinTV card without radio and a PVR-350 with. Normally this would give a video1 device together with a radio0 device for the PVR. By
setting this to 1 you ensure that radio0 is now also radio1. */ int ivtv_first_minor;
/* Callback for registering extensions */ int (*ivtv_ext_init)(struct ivtv *);
EXPORT_SYMBOL(ivtv_ext_init);
/* add your revision and whatnot here */ staticconststruct pci_device_id ivtv_pci_tbl[] = {
{PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV15,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV16,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0,}
};
/* Generic utility functions */ int ivtv_msleep_timeout(unsignedint msecs, int intr)
{ int timeout = msecs_to_jiffies(msecs);
do {
set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
timeout = schedule_timeout(timeout); if (intr) { int ret = signal_pending(current);
if (ret) return ret;
}
} while (timeout); return 0;
}
/* Hauppauge card? get values from tveeprom */ void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv)
{
u8 eedata[256];
/* Many thanks to Steven Toth from Hauppauge for providing the
model numbers */ switch (tv.model) { /* In a few cases the PCI subsystem IDs do not correctly identify the card. A better method is to check the
model number from the eeprom instead. */ case 30012 ... 30039: /* Low profile PVR250 */ case 32000 ... 32999: case 48000 ... 48099: /* 48??? range are PVR250s with a cx23415 */ case 48400 ... 48599:
itv->card = ivtv_get_card(IVTV_CARD_PVR_250); break; case 48100 ... 48399: case 48600 ... 48999:
itv->card = ivtv_get_card(IVTV_CARD_PVR_350); break; case 23000 ... 23999: /* PVR500 */ case 25000 ... 25999: /* Low profile PVR150 */ case 26000 ... 26999: /* Regular PVR150 */
itv->card = ivtv_get_card(IVTV_CARD_PVR_150); break; case 0:
IVTV_ERR("Invalid EEPROM\n"); return; default:
IVTV_ERR("Unknown model %d, defaulting to PVR-150\n", tv.model);
itv->card = ivtv_get_card(IVTV_CARD_PVR_150); break;
}
switch (tv.model) { /* Old style PVR350 (with an saa7114) uses this input for
the tuner. */ case 48254:
itv->card = ivtv_get_card(IVTV_CARD_PVR_350_V1); break; default: break;
}
/* If this is a PVR500 then it should be possible to detect whether it is the first or second unit by looking at the subsystem device ID: is bit 4 is set, then it is the second unit (according to info from Hauppauge).
However, while this works for most cards, I have seen a few PVR500 cards where both units have the same subsystem ID.
So instead I look at the reported 'PCI slot' (which is the slot on the PVR500 PCI bridge) and if it is 8, then it is assumed to be the first unit, otherwise it is the second unit. It is possible that it is a different slot when ivtv is used in Xen, in that case I ignore this card here. The worst that can happen is that the card presents itself with a non-working radio device.
This detection is needed since the eeprom reports incorrectly that a radio is
present on the second unit. */ if (tv.model / 1000 == 23) { staticconststruct ivtv_card_tuner_i2c ivtv_i2c_radio = {
.radio = { 0x60, I2C_CLIENT_END },
.demod = { 0x43, I2C_CLIENT_END },
.tv = { 0x61, I2C_CLIENT_END },
};
itv->options.newi2c = newi2c; if (tunertype < -1 || tunertype > 1) {
IVTV_WARN("Invalid tunertype argument, will autodetect instead\n");
tunertype = -1;
}
itv->std = ivtv_parse_std(itv); if (itv->std == 0 && tunertype >= 0)
itv->std = tunertype ? V4L2_STD_MN : (V4L2_STD_ALL & ~V4L2_STD_MN);
itv->has_cx23415 = (itv->pdev->device == PCI_DEVICE_ID_IVTV15);
chipname = itv->has_cx23415 ? "cx23415" : "cx23416"; if (itv->options.cardtype == -1) {
IVTV_INFO("Ignore card (detected %s based chip)\n", chipname); return;
} if ((itv->card = ivtv_get_card(itv->options.cardtype - 1))) {
IVTV_INFO("User specified %s card (detected %s based chip)\n",
itv->card->name, chipname);
} elseif (itv->options.cardtype != 0) {
IVTV_ERR("Unknown user specified type, trying to autodetect card\n");
} if (itv->card == NULL) { if (itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE ||
itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT1 ||
itv->pdev->subsystem_vendor == IVTV_PCI_ID_HAUPPAUGE_ALT2) {
itv->card = ivtv_get_card(itv->has_cx23415 ? IVTV_CARD_PVR_350 : IVTV_CARD_PVR_150);
IVTV_INFO("Autodetected Hauppauge card (%s based)\n",
chipname);
}
} if (itv->card == NULL) { for (i = 0; (itv->card = ivtv_get_card(i)); i++) { if (itv->card->pci_list == NULL) continue; for (j = 0; itv->card->pci_list[j].device; j++) { if (itv->pdev->device !=
itv->card->pci_list[j].device) continue; if (itv->pdev->subsystem_vendor !=
itv->card->pci_list[j].subsystem_vendor) continue; if (itv->pdev->subsystem_device !=
itv->card->pci_list[j].subsystem_device) continue;
IVTV_INFO("Autodetected %s card (%s based)\n",
itv->card->name, chipname); goto done;
}
}
}
done:
if (itv->card == NULL) {
itv->card = ivtv_get_card(IVTV_CARD_PVR_150);
IVTV_ERR("Unknown card: vendor/device: [%04x:%04x]\n",
itv->pdev->vendor, itv->pdev->device);
IVTV_ERR(" subsystem vendor/device: [%04x:%04x]\n",
itv->pdev->subsystem_vendor, itv->pdev->subsystem_device);
IVTV_ERR(" %s based\n", chipname);
IVTV_ERR("Defaulting to %s card\n", itv->card->name);
IVTV_ERR("Please mail the vendor/device and subsystem vendor/device IDs and what kind of\n");
IVTV_ERR("card you have to the linux-media mailinglist (www.linuxtv.org)\n");
IVTV_ERR("Prefix your subject line with [UNKNOWN IVTV CARD].\n");
}
itv->v4l2_cap = itv->card->v4l2_capabilities;
itv->card_name = itv->card->name;
itv->card_i2c = itv->card->i2c;
}
/* Precondition: the ivtv structure has been memset to 0. Only the dev and num fields have been filled in. No assumptions on the card type may be made here (see ivtv_init_struct2 for that).
*/ staticint ivtv_init_struct1(struct ivtv *itv)
{
itv->base_addr = pci_resource_start(itv->pdev, 0);
itv->enc_mbox.max_mbox = 2; /* the encoder has 3 mailboxes (0-2) */
itv->dec_mbox.max_mbox = 1; /* the decoder has 2 mailboxes (0-1) */
kthread_init_worker(&itv->irq_worker);
itv->irq_worker_task = kthread_run(kthread_worker_fn, &itv->irq_worker, "%s", itv->v4l2_dev.name); if (IS_ERR(itv->irq_worker_task)) {
IVTV_ERR("Could not create ivtv task\n"); return -1;
} /* must use the FIFO scheduler as it is realtime sensitive */
sched_set_fifo(itv->irq_worker_task);
/* Second initialization part. Here the card type has been
autodetected. */ staticvoid ivtv_init_struct2(struct ivtv *itv)
{ int i;
for (i = 0; i < IVTV_CARD_MAX_VIDEO_INPUTS; i++) if (itv->card->video_inputs[i].video_type == 0) break;
itv->nof_inputs = i; for (i = 0; i < IVTV_CARD_MAX_AUDIO_INPUTS; i++) if (itv->card->audio_inputs[i].audio_type == 0) break;
itv->nof_audio_inputs = i;
if (itv->card->hw_all & IVTV_HW_CX25840) {
itv->vbi.sliced_size = 288; /* multiple of 16, real size = 284 */
} else {
itv->vbi.sliced_size = 64; /* multiple of 16, real size = 52 */
}
/* Find tuner input */ for (i = 0; i < itv->nof_inputs; i++) { if (itv->card->video_inputs[i].video_type ==
IVTV_CARD_INPUT_VID_TUNER) break;
} if (i >= itv->nof_inputs)
i = 0;
itv->active_input = i;
itv->audio_input = itv->card->video_inputs[i].audio_index;
}
/* Check for bus mastering */
pci_read_config_word(pdev, PCI_COMMAND, &cmd); if (!(cmd & PCI_COMMAND_MASTER)) {
IVTV_DEBUG_INFO("Attempting to enable Bus Mastering\n");
pci_set_master(pdev);
pci_read_config_word(pdev, PCI_COMMAND, &cmd); if (!(cmd & PCI_COMMAND_MASTER)) {
IVTV_ERR("Bus Mastering is not enabled\n"); return -ENXIO;
}
}
IVTV_DEBUG_INFO("Bus Mastering Enabled.\n");
if (pci_latency < 64 && ivtv_pci_latency) {
IVTV_INFO("Unreasonably low latency timer, setting to 64 (was %d)\n",
pci_latency);
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &pci_latency);
} /* This config space value relates to DMA latencies. The default value 0x8080 is too low however and will lead to DMA errors. 0xffff is the max value which solves
these problems. */
pci_write_config_dword(pdev, 0x40, 0xffff);
if (itv->card->type == IVTV_CARD_CX23416GYC) { /* Several variations of this card exist, detect which card
type should be used. */ if ((hw & (IVTV_HW_UPD64031A | IVTV_HW_UPD6408X)) == 0)
itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGRYCS); elseif ((hw & IVTV_HW_UPD64031A) == 0)
itv->card = ivtv_get_card(IVTV_CARD_CX23416GYC_NOGR);
} elseif (itv->card->type == IVTV_CARD_GV_MVPRX ||
itv->card->type == IVTV_CARD_GV_MVPRX2E) { /* The crystal frequency of GVMVPRX is 24.576MHz */
v4l2_subdev_call(itv->sd_video, video, s_crystal_freq,
SAA7115_FREQ_24_576_MHZ, SAA7115_FREQ_FL_UCGC);
}
/* map io memory */
IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
(u64)itv->base_addr + IVTV_ENCODER_OFFSET, IVTV_ENCODER_SIZE);
itv->enc_mem = devm_ioremap(&pdev->dev,
itv->base_addr + IVTV_ENCODER_OFFSET,
IVTV_ENCODER_SIZE); if (!itv->enc_mem) {
IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 encoder memory\n");
IVTV_ERR("Each capture card with a CX23415/6 needs 8 MB of vmalloc address space for this window\n");
IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
retval = -ENOMEM; goto free_worker;
}
if (itv->has_cx23415) {
IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
(u64)itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
itv->dec_mem = devm_ioremap(&pdev->dev,
itv->base_addr + IVTV_DECODER_OFFSET,
IVTV_DECODER_SIZE); if (!itv->dec_mem) {
IVTV_ERR("ioremap failed. Can't get a window into CX23415 decoder memory\n");
IVTV_ERR("Each capture card with a CX23415 needs 8 MB of vmalloc address space for this window\n");
IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
retval = -ENOMEM; goto free_worker;
}
} else {
itv->dec_mem = itv->enc_mem;
}
/* map registers memory */
IVTV_DEBUG_INFO("attempting ioremap at 0x%llx len 0x%08x\n",
(u64)itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
itv->reg_mem = devm_ioremap(&pdev->dev,
itv->base_addr + IVTV_REG_OFFSET,
IVTV_REG_SIZE); if (!itv->reg_mem) {
IVTV_ERR("ioremap failed. Can't get a window into CX23415/6 register space\n");
IVTV_ERR("Each capture card with a CX23415/6 needs 64 kB of vmalloc address space for this window\n");
IVTV_ERR("Check the output of 'grep Vmalloc /proc/meminfo'\n");
IVTV_ERR("Use the vmalloc= kernel command line option to set VmallocTotal to a larger value\n");
retval = -ENOMEM; goto free_worker;
}
retval = ivtv_gpio_init(itv); if (retval) goto free_worker;
/* active i2c */
IVTV_DEBUG_INFO("activating i2c...\n"); if (init_ivtv_i2c(itv)) {
IVTV_ERR("Could not initialize i2c\n"); goto free_worker;
}
if (itv->card->hw_all & IVTV_HW_TVEEPROM) { /* Based on the model number the cardtype may be changed.
The PCI IDs are not always reliable. */
ivtv_process_eeprom(itv);
} if (itv->card->comment)
IVTV_INFO("%s", itv->card->comment); if (itv->card->v4l2_capabilities == 0) { /* card was detected but is not supported */
retval = -ENODEV; goto free_i2c;
}
if (itv->std == 0) {
itv->std = V4L2_STD_NTSC_M;
}
if (itv->options.tuner == -1) { int i;
for (i = 0; i < IVTV_CARD_MAX_TUNERS; i++) { if ((itv->std & itv->card->tuners[i].std) == 0) continue;
itv->options.tuner = itv->card->tuners[i].tuner; break;
}
} /* if no tuner was found, then pick the first tuner in the card list */ if (itv->options.tuner == -1 && itv->card->tuners[0].std) {
itv->std = itv->card->tuners[0].std; if (itv->std & V4L2_STD_PAL)
itv->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H; elseif (itv->std & V4L2_STD_NTSC)
itv->std = V4L2_STD_NTSC_M; elseif (itv->std & V4L2_STD_SECAM)
itv->std = V4L2_STD_SECAM_L;
itv->options.tuner = itv->card->tuners[0].tuner;
} if (itv->options.radio == -1)
itv->options.radio = (itv->card->radio_input.audio_type != 0);
/* The card is now fully identified, continue with card-specific
initialization. */
ivtv_init_struct2(itv);
/* Setup VBI Raw Size. Should be big enough to hold PAL. It is possible to switch between PAL and NTSC, so we need to
take the largest size here. */ /* 1456 is multiple of 16, real size = 1444 */
itv->vbi.raw_size = 1456; /* We use a buffer size of 1/2 of the total size needed for a frame. This is actually very useful, since we now receive a field at a time and that makes 'compressing' the raw data down to size by stripping off the SAV codes a lot easier. Note: having two different buffer sizes prevents standard
switching on the fly. We need to find a better solution... */
vbi_buf_size = itv->vbi.raw_size * (itv->is_60hz ? 24 : 36) / 2;
itv->stream_buf_size[IVTV_ENC_STREAM_TYPE_VBI] = vbi_buf_size;
itv->stream_buf_size[IVTV_DEC_STREAM_TYPE_VBI] = sizeof(struct v4l2_sliced_vbi_data) * 36;
if (itv->options.radio > 0)
itv->v4l2_cap |= V4L2_CAP_RADIO;
if (itv->options.tuner > -1) { struct tuner_setup setup;
/* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
are not. */
itv->tuner_std = itv->std;
if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) { struct v4l2_ctrl_handler *hdl = itv->v4l2_dev.ctrl_handler;
itv->ctrl_pts = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops,
V4L2_CID_MPEG_VIDEO_DEC_PTS, 0, 0, 0, 0);
itv->ctrl_frame = v4l2_ctrl_new_std(hdl, &ivtv_hdl_out_ops,
V4L2_CID_MPEG_VIDEO_DEC_FRAME, 0, 0, 0, 0); /* Note: V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO is not supported,
mask that menu item. */
itv->ctrl_audio_playback =
v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops,
V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK,
V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO,
1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO,
V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO);
itv->ctrl_audio_multilingual_playback =
v4l2_ctrl_new_std_menu(hdl, &ivtv_hdl_out_ops,
V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK,
V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO,
1 << V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO,
V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT); if (hdl->error) {
retval = hdl->error; goto free_i2c;
}
v4l2_ctrl_cluster(2, &itv->ctrl_pts);
v4l2_ctrl_cluster(2, &itv->ctrl_audio_playback);
ivtv_call_all(itv, video, s_std_output, itv->std); /* Turn off the output signal. The mpeg decoder is not yet active so without this you would get a green image until the
mpeg decoder becomes active. */
ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
}
int ivtv_init_on_first_open(struct ivtv *itv)
{ struct v4l2_frequency vf; /* Needed to call ioctls later */ struct ivtv_open_id fh; int fw_retry_count = 3; int video_input;
fh.itv = itv;
fh.type = IVTV_ENC_STREAM_TYPE_MPG;
if (test_bit(IVTV_F_I_FAILED, &itv->i_flags)) return -ENXIO;
if (test_and_set_bit(IVTV_F_I_INITED, &itv->i_flags)) return 0;
while (--fw_retry_count > 0) { /* load firmware */ if (ivtv_firmware_init(itv) == 0) break; if (fw_retry_count > 1)
IVTV_WARN("Retry loading firmware\n");
}
if (fw_retry_count == 0) {
set_bit(IVTV_F_I_FAILED, &itv->i_flags); return -ENXIO;
}
/* Try and get firmware versions */
IVTV_DEBUG_INFO("Getting firmware version..\n");
ivtv_firmware_versions(itv);
if (itv->card->hw_all & IVTV_HW_CX25840)
v4l2_subdev_call(itv->sd_video, core, load_fw);
vf.tuner = 0;
vf.type = V4L2_TUNER_ANALOG_TV;
vf.frequency = 6400; /* the tuner 'baseline' frequency */
video_input = itv->active_input;
itv->active_input++; /* Force update of input */
ivtv_s_input(NULL, &fh, video_input);
/* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
in one place. */
itv->std++; /* Force full standard initialization */
itv->std_out = itv->std;
ivtv_s_frequency(NULL, &fh, &vf);
if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) { /* Turn on the TV-out: ivtv_init_mpeg_decoder() initializes the mpeg decoder so now the saa7127 receives a proper
signal. */
ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
ivtv_init_mpeg_decoder(itv);
}
/* On a cx23416 this seems to be able to enable DMA to the chip? */ if (!itv->has_cx23415)
write_reg_sync(0x03, IVTV_REG_DMACONTROL);
ivtv_s_std_enc(itv, itv->tuner_std);
/* Default interrupts enabled. For the PVR350 this includes the decoder VSYNC interrupt, which is always on. It is not only used during decoding but also by the OSD. Some old PVR250 cards had a cx23415, so testing for that is too
general. Instead test if the card has video output capability. */ if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC);
ivtv_set_osd_alpha(itv);
ivtv_s_std_dec(itv, itv->tuner_std);
} else {
ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT);
}
if (test_bit(IVTV_F_I_INITED, &itv->i_flags)) { /* Stop all captures */
IVTV_DEBUG_INFO("Stopping all streams\n"); if (atomic_read(&itv->capturing) > 0)
ivtv_stop_all_captures(itv);
/* Stop all decoding */
IVTV_DEBUG_INFO("Stopping decoding\n");
/* Turn off the TV-out */ if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0); if (atomic_read(&itv->decoding) > 0) { int type;
if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
type = IVTV_DEC_STREAM_TYPE_YUV; else
type = IVTV_DEC_STREAM_TYPE_MPG;
ivtv_stop_v4l2_decode_stream(&itv->streams[type],
V4L2_DEC_CMD_STOP_TO_BLACK | V4L2_DEC_CMD_STOP_IMMEDIATELY, 0);
}
ivtv_halt_firmware(itv);
}
/* Note: These symbols are exported because they are used by the ivtvfb
framebuffer module and an infrared module for the IR-blaster. */
EXPORT_SYMBOL(ivtv_set_irq_mask);
EXPORT_SYMBOL(ivtv_api);
EXPORT_SYMBOL(ivtv_vapi);
EXPORT_SYMBOL(ivtv_vapi_result);
EXPORT_SYMBOL(ivtv_clear_irq_mask);
EXPORT_SYMBOL(ivtv_debug); #ifdef CONFIG_VIDEO_ADV_DEBUG
EXPORT_SYMBOL(ivtv_fw_debug); #endif
EXPORT_SYMBOL(ivtv_reset_ir_gpio);
EXPORT_SYMBOL(ivtv_udma_setup);
EXPORT_SYMBOL(ivtv_udma_unmap);
EXPORT_SYMBOL(ivtv_udma_alloc);
EXPORT_SYMBOL(ivtv_udma_prepare);
EXPORT_SYMBOL(ivtv_init_on_first_open);
EXPORT_SYMBOL(ivtv_firmware_check);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.