📄 pvrusb2-hdw.c
字号:
/* * * $Id$ * * Copyright (C) 2005 Mike Isely <isely@pobox.com> * * 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 * * 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 * */#include "compat.h"#include <linux/errno.h>#include <linux/string.h>#include <linux/slab.h>#include <linux/firmware.h>#include <linux/videodev2.h>#include <asm/semaphore.h>#include "pvrusb2.h"#include "pvrusb2-util.h"#include "pvrusb2-hdw.h"#include "pvrusb2-i2c-core.h"#include "pvrusb2-tuner.h"#include "pvrusb2-eeprom.h"#include "pvrusb2-hdw-internal.h"#include "pvrusb2-encoder.h"#include "pvrusb2-debug.h"struct usb_device_id pvr2_device_table[] = { [PVR2_HDW_TYPE_29XXX] = { USB_DEVICE(0x2040, 0x2900) },#ifdef CONFIG_VIDEO_PVRUSB2_24XXX [PVR2_HDW_TYPE_24XXX] = { USB_DEVICE(0x2040, 0x2400) },#endif { }};MODULE_DEVICE_TABLE(usb, pvr2_device_table);static const char *pvr2_device_names[] = { [PVR2_HDW_TYPE_29XXX] = "WinTV PVR USB2 Model Category 29xxxx",#ifdef CONFIG_VIDEO_PVRUSB2_24XXX [PVR2_HDW_TYPE_24XXX] = "WinTV PVR USB2 Model Category 24xxxx",#endif};static struct pvr2_hdw *unit_pointers[PVR_NUM] = {[ 0 ... PVR_NUM-1 ] = 0};DECLARE_MUTEX(pvr2_unit_sem);static int ctlchg = 0;static int initusbreset = 1;static int procreload = 0;static int tuner[PVR_NUM] = { [0 ... PVR_NUM-1] = -1 };static int tolerance[PVR_NUM] = { [0 ... PVR_NUM-1] = 0 };static int init_pause_msec = 0;module_param(ctlchg, int, S_IRUGO|S_IWUSR);MODULE_PARM_DESC(ctlchg, "0=optimize ctl change 1=always accept new ctl value");module_param(init_pause_msec, int, S_IRUGO|S_IWUSR);MODULE_PARM_DESC(init_pause_msec, "hardware initialization settling delay");module_param(initusbreset, int, S_IRUGO|S_IWUSR);MODULE_PARM_DESC(initusbreset, "Do USB reset device on probe");module_param(procreload, int, S_IRUGO|S_IWUSR);MODULE_PARM_DESC(procreload, "Attempt init failure recovery with firmware reload");module_param_array(tuner, int, NULL, 0444);MODULE_PARM_DESC(tuner,"specify installed tuner type");module_param_array(tolerance, int, NULL, 0444);MODULE_PARM_DESC(tolerance,"specify stream error tolerance");#define PVR2_CTL_WRITE_ENDPOINT 0x01#define PVR2_CTL_READ_ENDPOINT 0x81#define PVR2_GPIO_IN 0x9008#define PVR2_GPIO_OUT 0x900c#define PVR2_GPIO_DIR 0x9020#define trace_firmware(...) pvr2_trace(PVR2_TRACE_FIRMWARE,__VA_ARGS__)#define PVR2_FIRMWARE_ENDPOINT 0x02/* size of a firmware chunk */#define FIRMWARE_CHUNK_SIZE 0x2000static const char *control_values_srate[] = { [PVR2_CVAL_SRATE_48] = "48KHz", [PVR2_CVAL_SRATE_44_1] = "44.1KHz",};static const char *control_values_audiobitrate[] = { [PVR2_CVAL_AUDIOBITRATE_384] = "384kb/s", [PVR2_CVAL_AUDIOBITRATE_320] = "320kb/s", [PVR2_CVAL_AUDIOBITRATE_256] = "256kb/s", [PVR2_CVAL_AUDIOBITRATE_224] = "224kb/s", [PVR2_CVAL_AUDIOBITRATE_192] = "192kb/s", [PVR2_CVAL_AUDIOBITRATE_160] = "160kb/s", [PVR2_CVAL_AUDIOBITRATE_128] = "128kb/s", [PVR2_CVAL_AUDIOBITRATE_112] = "112kb/s", [PVR2_CVAL_AUDIOBITRATE_96] = "96kb/s", [PVR2_CVAL_AUDIOBITRATE_80] = "80kb/s", [PVR2_CVAL_AUDIOBITRATE_64] = "64kb/s", [PVR2_CVAL_AUDIOBITRATE_56] = "56kb/s", [PVR2_CVAL_AUDIOBITRATE_48] = "48kb/s", [PVR2_CVAL_AUDIOBITRATE_32] = "32kb/s", [PVR2_CVAL_AUDIOBITRATE_VBR] = "VBR",};static const char *control_values_audioemphasis[] = { [PVR2_CVAL_AUDIOEMPHASIS_NONE] = "None", [PVR2_CVAL_AUDIOEMPHASIS_50_15] = "50/15us", [PVR2_CVAL_AUDIOEMPHASIS_CCITT] = "CCITT J.17",};static const char *control_values_videostandard[] = { "PAL-B", "PAL-B1", "PAL-G", "PAL-H", "PAL-I", "PAL-D", "PAL-D1", "PAL-K", "PAL-M", "PAL-N", "PAL-Nc", "PAL-60", "NTSC-M", "NTSC-M-JP", "NTSC-443", 0, "SECAM-B", "SECAM-D", "SECAM-G", "SECAM-H", "SECAM-K", "SECAM-K1", "SECAM-L", "SECAM-LC",};static const char *control_values_input[] = { [PVR2_CVAL_INPUT_TV] = "television", /*xawtv needs this name*/ [PVR2_CVAL_INPUT_RADIO] = "radio", [PVR2_CVAL_INPUT_SVIDEO] = "s-video", [PVR2_CVAL_INPUT_COMPOSITE] = "composite",};static const char *control_values_audiomode[] = { [V4L2_TUNER_MODE_MONO] = "Mono", [V4L2_TUNER_MODE_STEREO] = "Stereo", [V4L2_TUNER_MODE_LANG1] = "Lang1", [V4L2_TUNER_MODE_LANG2] = "Lang2", [V4L2_TUNER_MODE_LANG1_LANG2] = "Lang1+Lang2",};static const char *control_values_hsm[] = { [PVR2_CVAL_HSM_FAIL] = "Fail", [PVR2_CVAL_HSM_HIGH] = "High", [PVR2_CVAL_HSM_FULL] = "Full",};#define VDEF(x) \ .value_defs_ptr = x, \ .value_defs_count = (sizeof(x)/sizeof(x[0]))static int pvr2_ctl_set_chanprog_id(struct pvr2_ctrl *cptr,int value);static int pvr2_ctl_get_chanprog_id(struct pvr2_ctrl *cptr);static int pvr2_ctl_get_signal(struct pvr2_ctrl *cptr);static int pvr2_ctl_get_streaming(struct pvr2_ctrl *cptr);static int pvr2_ctl_get_hsm(struct pvr2_ctrl *cptr);static int pvr2_ctl_get_subsys_mask(struct pvr2_ctrl *cptr);static int pvr2_ctl_set_subsys_mask(struct pvr2_ctrl *cptr,int val);static int pvr2_ctl_get_subsys_stream_mask(struct pvr2_ctrl *cptr);static int pvr2_ctl_set_subsys_stream_mask(struct pvr2_ctrl *cptr,int val);static int pvr2_ctl_set_stdcur(struct pvr2_ctrl *cptr,int val);static int pvr2_ctl_get_stdcur(struct pvr2_ctrl *cptr);static int pvr2_ctl_get_stdavail(struct pvr2_ctrl *cptr);static int pvr2_ctl_set_stdenumcur(struct pvr2_ctrl *cptr,int val);static int pvr2_ctl_get_stdenumcur(struct pvr2_ctrl *cptr);static struct pvr2_ctl_def control_defs[] ={ [PVR2_CID_BRIGHTNESS] = { .id = V4L2_CID_BRIGHTNESS, .is_valid = !0, .desc = "Brightness", .name = "brightness", .min_value = 0, .max_value = 255, .default_value = 128, }, [PVR2_CID_CONTRAST] = { .id = V4L2_CID_CONTRAST, .is_valid = !0, .desc = "Contrast", .name = "contrast", .min_value = 0, .max_value = 127, .default_value = 68, }, [PVR2_CID_SATURATION] = { .id = V4L2_CID_SATURATION, .is_valid = !0, .desc = "Saturation", .name = "saturation", .min_value = 0, .max_value = 127, .default_value = 64, }, [PVR2_CID_HUE] = { .id = V4L2_CID_HUE, .is_valid = !0, .desc = "Hue", .name = "hue", .min_value = -128, .max_value = 127, .default_value = 0, }, [PVR2_CID_VOLUME] = { .id = V4L2_CID_AUDIO_VOLUME, .is_valid = !0, .desc = "Volume", .name = "volume", .min_value = 0, .max_value = 65535, .default_value = 65535, }, [PVR2_CID_BALANCE] = { .id = V4L2_CID_AUDIO_BALANCE, .is_valid = !0, .desc = "Balance", .name = "balance", .min_value = -32768, .max_value = 32767, .default_value = 0, }, [PVR2_CID_BASS] = { .id = V4L2_CID_AUDIO_BASS, .is_valid = !0, .desc = "Bass", .name = "bass", .min_value = -32768, .max_value = 32767, .default_value = 0, }, [PVR2_CID_TREBLE] = { .id = V4L2_CID_AUDIO_TREBLE, .is_valid = !0, .desc = "Treble", .name = "treble", .min_value = -32768, .max_value = 32767, .default_value = 0, }, [PVR2_CID_MUTE] = { .id = V4L2_CID_AUDIO_MUTE, .is_valid = !0, .desc = "Mute", .name = "mute", .min_value = 0, .max_value = 1, .default_value = 0, }, [PVR2_CID_SRATE] = { .id = V4L2_CID_PVR_SRATE, .is_valid = !0, .desc = "Sample rate", .name = "srate", .min_value = PVR2_CVAL_SRATE_MIN, .max_value = PVR2_CVAL_SRATE_MAX, .default_value = PVR2_CVAL_SRATE_48, VDEF(control_values_srate), }, [PVR2_CID_AUDIOBITRATE] = { .id = V4L2_CID_PVR_AUDIOBITRATE, .is_valid = !0, .desc = "Audio Bitrate", .name = "audio_bitrate", .min_value = PVR2_CVAL_AUDIOBITRATE_MIN, .max_value = PVR2_CVAL_AUDIOBITRATE_MAX, .default_value = PVR2_CVAL_AUDIOBITRATE_224, VDEF(control_values_audiobitrate), }, [PVR2_CID_AUDIOCRC] = { .id = V4L2_CID_PVR_AUDIOCRC, .is_valid = !0, .desc = "Audio CRC", .name = "audio_crc", .min_value = 0, .max_value = 1, .default_value = 1, }, [PVR2_CID_AUDIOEMPHASIS] = { .id = V4L2_CID_PVR_AUDIOEMPHASIS, .is_valid = !0, .desc = "Audio Emphasis", .name = "audio_emphasis", .min_value = PVR2_CVAL_AUDIOEMPHASIS_MIN, .max_value = PVR2_CVAL_AUDIOEMPHASIS_MAX, .default_value = PVR2_CVAL_AUDIOEMPHASIS_NONE, VDEF(control_values_audioemphasis), }, [PVR2_CID_VBR] = { .id = V4L2_CID_PVR_VBR, .is_valid = !0, .desc = "Variable video bitrate", .name = "vbr", .min_value = 0, .max_value = 1, .default_value = 0, }, [PVR2_CID_AVERAGEVIDEOBITRATE] = { .id = V4L2_CID_PVR_VIDEOBITRATE, .is_valid = !0, .desc = "Average video bitrate", .name = "video_average_bitrate", .min_value = 1, .max_value = 20000000, .default_value = 6000000, }, [PVR2_CID_PEAKVIDEOBITRATE] = { .id = V4L2_CID_PVR_VIDEOPEAK, .is_valid = !0, .desc = "Peak video bitrate", .name = "video_peak_bitrate", .min_value = 1, .max_value = 20000000, .default_value = 6000000, }, [PVR2_CID_STDAVAIL] = { .is_valid = !0, .desc = "Video Standards Available Mask", .name = "video_standard_mask_available", .min_value = 0, .max_value = 0, .default_value = (int)V4L2_STD_UNKNOWN, .mask_value = (int)V4L2_STD_ALL, .get_func = pvr2_ctl_get_stdavail, VDEF(control_values_videostandard), }, [PVR2_CID_INPUT] = { .id = V4L2_CID_PVR_INPUT, .is_valid = !0, .desc = "Video Source", .name = "input", .min_value = PVR2_CVAL_INPUT_MIN, .max_value = PVR2_CVAL_INPUT_MAX, .default_value = PVR2_CVAL_INPUT_TV, VDEF(control_values_input), }, [PVR2_CID_AUDIOMODE] = { .id = V4L2_CID_PVR_AUDIOMODE, .is_valid = !0, .desc = "Audio Mode", .name = "audio_mode", .min_value = V4L2_TUNER_MODE_MONO, .max_value = V4L2_TUNER_MODE_LANG1_LANG2, .default_value = V4L2_TUNER_MODE_STEREO, VDEF(control_values_audiomode), }, [PVR2_CID_FREQUENCY] = { .id = V4L2_CID_PVR_FREQUENCY, .is_valid = !0, .desc = "Tuner Frequency (Hz)", .name = "frequency", .min_value = 55250000L, .max_value = 850000000L, .default_value = 175250000L, }, [PVR2_CID_HRES] = { .id = V4L2_CID_PVR_HRES, .is_valid = !0, .desc = "Horizontal capture resolution", .name = "resolution_hor", .min_value = 320, .max_value = 720, .default_value = 720, }, [PVR2_CID_VRES] = { .id = V4L2_CID_PVR_VRES, .is_valid = !0, .desc = "Vertical capture resolution", .name = "resolution_ver", .min_value = 200, .max_value = 625, .default_value = 480, }, [PVR2_CID_INTERLACE] = { .id = V4L2_CID_PVR_INTERLACE, .is_valid = !0, .desc = "Interlace mode", .name = "interlace", .min_value = 0, .max_value = 1, .default_value = 0, }, [PVR2_CID_AUDIOLAYER] = { .is_valid = !0, .desc = "Audio Layer", .name = "audio_layer", .min_value = 0, /* This is all a wild guess */ .max_value = 3, .default_value = 2, /* Appears to be all that is supported */ }, [PVR2_CID_CHANNEL] = { .is_valid = !0, .desc = "Channel", .name = "channel", .min_value = 0, .max_value = FREQTABLE_SIZE, .default_value = 0, }, [PVR2_CID_CHANPROG_ID] = { .is_valid = !0, .desc = "Channel Program ID", .name = "freq_table_channel", .min_value = 0, .max_value = FREQTABLE_SIZE, .default_value = 0, }, [PVR2_CID_CHANPROG_FREQ] = { .is_valid = !0, .desc = "Channel Program Frequency", .name = "freq_table_value", .min_value = 55250000L, .max_value = 850000000L, .skip_init = !0, .set_func = pvr2_ctl_set_chanprog_id, .get_func = pvr2_ctl_get_chanprog_id, }, [PVR2_CID_SIGNAL_PRESENT] = { .is_valid = !0, .desc = "Signal Present", .name = "signal_present", .min_value = 0, .max_value = 1, .get_func = pvr2_ctl_get_signal, }, [PVR2_CID_STREAMING_ENABLED] = { .is_valid = !0, .desc = "Streaming Enabled", .name = "streaming_enabled", .min_value = 0, .max_value = 1, .get_func = pvr2_ctl_get_streaming, }, [PVR2_CID_HSM] = { .is_valid = !0, .desc = "USB Speed", .name = "usb_speed", .min_value = PVR2_CVAL_HSM_MIN, .max_value = PVR2_CVAL_HSM_MAX, .get_func = pvr2_ctl_get_hsm, VDEF(control_values_hsm), }, [PVR2_CID_SUBSYS_MASK] = { .is_valid = !0, .desc = "Subsystem enabled mask", .name = "debug_subsys_mask", .min_value = 0, .max_value = 0x7fffffff, .skip_init = !0, .get_func = pvr2_ctl_get_subsys_mask, .set_func = pvr2_ctl_set_subsys_mask, }, [PVR2_CID_SUBSYS_STREAM_MASK] = { .is_valid = !0, .desc = "Subsystem stream mask", .name = "debug_subsys_stream_mask", .min_value = 0, .max_value = 0x7fffffff, .skip_init = !0, .get_func = pvr2_ctl_get_subsys_stream_mask,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -