17955f03dSHans Verkuil /* 27955f03dSHans Verkuil * Copyright (C) 2005-2006 Micronas USA Inc. 37955f03dSHans Verkuil * 47955f03dSHans Verkuil * This program is free software; you can redistribute it and/or modify 57955f03dSHans Verkuil * it under the terms of the GNU General Public License (Version 2) as 67955f03dSHans Verkuil * published by the Free Software Foundation. 77955f03dSHans Verkuil * 87955f03dSHans Verkuil * This program is distributed in the hope that it will be useful, 97955f03dSHans Verkuil * but WITHOUT ANY WARRANTY; without even the implied warranty of 107955f03dSHans Verkuil * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 117955f03dSHans Verkuil * GNU General Public License for more details. 127955f03dSHans Verkuil */ 137955f03dSHans Verkuil 147955f03dSHans Verkuil #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 157955f03dSHans Verkuil 167955f03dSHans Verkuil #include <linux/module.h> 177955f03dSHans Verkuil #include <linux/kernel.h> 187955f03dSHans Verkuil #include <linux/wait.h> 197955f03dSHans Verkuil #include <linux/list.h> 207955f03dSHans Verkuil #include <linux/slab.h> 217955f03dSHans Verkuil #include <linux/time.h> 227955f03dSHans Verkuil #include <linux/mm.h> 237955f03dSHans Verkuil #include <linux/usb.h> 247955f03dSHans Verkuil #include <linux/i2c.h> 257955f03dSHans Verkuil #include <asm/byteorder.h> 267955f03dSHans Verkuil #include <media/saa7115.h> 277955f03dSHans Verkuil #include <media/tuner.h> 287955f03dSHans Verkuil #include <media/uda1342.h> 297955f03dSHans Verkuil 307955f03dSHans Verkuil #include "go7007-priv.h" 317955f03dSHans Verkuil 327955f03dSHans Verkuil static unsigned int assume_endura; 337955f03dSHans Verkuil module_param(assume_endura, int, 0644); 347955f03dSHans Verkuil MODULE_PARM_DESC(assume_endura, 357955f03dSHans Verkuil "when probing fails, hardware is a Pelco Endura"); 367955f03dSHans Verkuil 377955f03dSHans Verkuil /* #define GO7007_I2C_DEBUG */ /* for debugging the EZ-USB I2C adapter */ 387955f03dSHans Verkuil 397955f03dSHans Verkuil #define HPI_STATUS_ADDR 0xFFF4 407955f03dSHans Verkuil #define INT_PARAM_ADDR 0xFFF6 417955f03dSHans Verkuil #define INT_INDEX_ADDR 0xFFF8 427955f03dSHans Verkuil 437955f03dSHans Verkuil /* 447955f03dSHans Verkuil * Pipes on EZ-USB interface: 457955f03dSHans Verkuil * 0 snd - Control 467955f03dSHans Verkuil * 0 rcv - Control 477955f03dSHans Verkuil * 2 snd - Download firmware (control) 487955f03dSHans Verkuil * 4 rcv - Read Interrupt (interrupt) 497955f03dSHans Verkuil * 6 rcv - Read Video (bulk) 507955f03dSHans Verkuil * 8 rcv - Read Audio (bulk) 517955f03dSHans Verkuil */ 527955f03dSHans Verkuil 537955f03dSHans Verkuil #define GO7007_USB_EZUSB (1<<0) 547955f03dSHans Verkuil #define GO7007_USB_EZUSB_I2C (1<<1) 557955f03dSHans Verkuil 567955f03dSHans Verkuil struct go7007_usb_board { 577955f03dSHans Verkuil unsigned int flags; 587955f03dSHans Verkuil struct go7007_board_info main_info; 597955f03dSHans Verkuil }; 607955f03dSHans Verkuil 617955f03dSHans Verkuil struct go7007_usb { 627955f03dSHans Verkuil const struct go7007_usb_board *board; 637955f03dSHans Verkuil struct mutex i2c_lock; 647955f03dSHans Verkuil struct usb_device *usbdev; 657955f03dSHans Verkuil struct urb *video_urbs[8]; 667955f03dSHans Verkuil struct urb *audio_urbs[8]; 677955f03dSHans Verkuil struct urb *intr_urb; 687955f03dSHans Verkuil }; 697955f03dSHans Verkuil 707955f03dSHans Verkuil /*********************** Product specification data ***********************/ 717955f03dSHans Verkuil 727955f03dSHans Verkuil static const struct go7007_usb_board board_matrix_ii = { 737955f03dSHans Verkuil .flags = GO7007_USB_EZUSB, 747955f03dSHans Verkuil .main_info = { 757955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO | 767955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C, 777955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 787955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 797955f03dSHans Verkuil .audio_rate = 48000, 807955f03dSHans Verkuil .audio_bclk_div = 8, 817955f03dSHans Verkuil .audio_main_div = 2, 827955f03dSHans Verkuil .hpi_buffer_cap = 7, 837955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 847955f03dSHans Verkuil GO7007_SENSOR_VALID_ENABLE | 857955f03dSHans Verkuil GO7007_SENSOR_TV | 867955f03dSHans Verkuil GO7007_SENSOR_SAA7115 | 877955f03dSHans Verkuil GO7007_SENSOR_VBI | 887955f03dSHans Verkuil GO7007_SENSOR_SCALING, 897955f03dSHans Verkuil .num_i2c_devs = 1, 907955f03dSHans Verkuil .i2c_devs = { 917955f03dSHans Verkuil { 927955f03dSHans Verkuil .type = "saa7115", 937955f03dSHans Verkuil .addr = 0x20, 947955f03dSHans Verkuil .is_video = 1, 957955f03dSHans Verkuil }, 967955f03dSHans Verkuil }, 977955f03dSHans Verkuil .num_inputs = 2, 987955f03dSHans Verkuil .inputs = { 997955f03dSHans Verkuil { 1007955f03dSHans Verkuil .video_input = 0, 1017955f03dSHans Verkuil .name = "Composite", 1027955f03dSHans Verkuil }, 1037955f03dSHans Verkuil { 1047955f03dSHans Verkuil .video_input = 9, 1057955f03dSHans Verkuil .name = "S-Video", 1067955f03dSHans Verkuil }, 1077955f03dSHans Verkuil }, 1087955f03dSHans Verkuil .video_config = SAA7115_IDQ_IS_DEFAULT, 1097955f03dSHans Verkuil }, 1107955f03dSHans Verkuil }; 1117955f03dSHans Verkuil 1127955f03dSHans Verkuil static const struct go7007_usb_board board_matrix_reload = { 1137955f03dSHans Verkuil .flags = GO7007_USB_EZUSB, 1147955f03dSHans Verkuil .main_info = { 1157955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO | 1167955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C, 1177955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 1187955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 1197955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 1207955f03dSHans Verkuil .audio_rate = 48000, 1217955f03dSHans Verkuil .audio_bclk_div = 8, 1227955f03dSHans Verkuil .audio_main_div = 2, 1237955f03dSHans Verkuil .hpi_buffer_cap = 7, 1247955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 1257955f03dSHans Verkuil GO7007_SENSOR_TV, 1267955f03dSHans Verkuil .num_i2c_devs = 1, 1277955f03dSHans Verkuil .i2c_devs = { 1287955f03dSHans Verkuil { 1297955f03dSHans Verkuil .type = "saa7113", 1307955f03dSHans Verkuil .addr = 0x25, 1317955f03dSHans Verkuil .is_video = 1, 1327955f03dSHans Verkuil }, 1337955f03dSHans Verkuil }, 1347955f03dSHans Verkuil .num_inputs = 2, 1357955f03dSHans Verkuil .inputs = { 1367955f03dSHans Verkuil { 1377955f03dSHans Verkuil .video_input = 0, 1387955f03dSHans Verkuil .name = "Composite", 1397955f03dSHans Verkuil }, 1407955f03dSHans Verkuil { 1417955f03dSHans Verkuil .video_input = 9, 1427955f03dSHans Verkuil .name = "S-Video", 1437955f03dSHans Verkuil }, 1447955f03dSHans Verkuil }, 1457955f03dSHans Verkuil .video_config = SAA7115_IDQ_IS_DEFAULT, 1467955f03dSHans Verkuil }, 1477955f03dSHans Verkuil }; 1487955f03dSHans Verkuil 1497955f03dSHans Verkuil static const struct go7007_usb_board board_star_trek = { 1507955f03dSHans Verkuil .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, 1517955f03dSHans Verkuil .main_info = { 1527955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO, /* | 1537955f03dSHans Verkuil GO7007_BOARD_HAS_TUNER, */ 1547955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 1557955f03dSHans Verkuil GO7007_SENSOR_VALID_ENABLE | 1567955f03dSHans Verkuil GO7007_SENSOR_TV | 1577955f03dSHans Verkuil GO7007_SENSOR_SAA7115 | 1587955f03dSHans Verkuil GO7007_SENSOR_VBI | 1597955f03dSHans Verkuil GO7007_SENSOR_SCALING, 1607955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 1617955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 1627955f03dSHans Verkuil .audio_bclk_div = 8, 1637955f03dSHans Verkuil .audio_main_div = 2, 1647955f03dSHans Verkuil .hpi_buffer_cap = 7, 1657955f03dSHans Verkuil .num_i2c_devs = 1, 1667955f03dSHans Verkuil .i2c_devs = { 1677955f03dSHans Verkuil { 1687955f03dSHans Verkuil .type = "saa7115", 1697955f03dSHans Verkuil .addr = 0x20, 1707955f03dSHans Verkuil .is_video = 1, 1717955f03dSHans Verkuil }, 1727955f03dSHans Verkuil }, 1737955f03dSHans Verkuil .num_inputs = 2, 1747955f03dSHans Verkuil .inputs = { 1757955f03dSHans Verkuil /* { 1767955f03dSHans Verkuil * .video_input = 3, 1777955f03dSHans Verkuil * .audio_index = AUDIO_TUNER, 1787955f03dSHans Verkuil * .name = "Tuner", 1797955f03dSHans Verkuil * }, 1807955f03dSHans Verkuil */ 1817955f03dSHans Verkuil { 1827955f03dSHans Verkuil .video_input = 1, 1837955f03dSHans Verkuil /* .audio_index = AUDIO_EXTERN, */ 1847955f03dSHans Verkuil .name = "Composite", 1857955f03dSHans Verkuil }, 1867955f03dSHans Verkuil { 1877955f03dSHans Verkuil .video_input = 8, 1887955f03dSHans Verkuil /* .audio_index = AUDIO_EXTERN, */ 1897955f03dSHans Verkuil .name = "S-Video", 1907955f03dSHans Verkuil }, 1917955f03dSHans Verkuil }, 1927955f03dSHans Verkuil .video_config = SAA7115_IDQ_IS_DEFAULT, 1937955f03dSHans Verkuil }, 1947955f03dSHans Verkuil }; 1957955f03dSHans Verkuil 1967955f03dSHans Verkuil static const struct go7007_usb_board board_px_tv402u = { 1977955f03dSHans Verkuil .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, 1987955f03dSHans Verkuil .main_info = { 1997955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO | 2007955f03dSHans Verkuil GO7007_BOARD_HAS_TUNER, 2017955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 2027955f03dSHans Verkuil GO7007_SENSOR_VALID_ENABLE | 2037955f03dSHans Verkuil GO7007_SENSOR_TV | 2047955f03dSHans Verkuil GO7007_SENSOR_SAA7115 | 2057955f03dSHans Verkuil GO7007_SENSOR_VBI | 2067955f03dSHans Verkuil GO7007_SENSOR_SCALING, 2077955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 2087955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 2097955f03dSHans Verkuil .audio_bclk_div = 8, 2107955f03dSHans Verkuil .audio_main_div = 2, 2117955f03dSHans Verkuil .hpi_buffer_cap = 7, 2127955f03dSHans Verkuil .num_i2c_devs = 5, 2137955f03dSHans Verkuil .i2c_devs = { 2147955f03dSHans Verkuil { 2157955f03dSHans Verkuil .type = "saa7115", 2167955f03dSHans Verkuil .addr = 0x20, 2177955f03dSHans Verkuil .is_video = 1, 2187955f03dSHans Verkuil }, 2197955f03dSHans Verkuil { 2207955f03dSHans Verkuil .type = "uda1342", 2217955f03dSHans Verkuil .addr = 0x1a, 2227955f03dSHans Verkuil .is_audio = 1, 2237955f03dSHans Verkuil }, 2247955f03dSHans Verkuil { 2257955f03dSHans Verkuil .type = "tuner", 2267955f03dSHans Verkuil .addr = 0x60, 2277955f03dSHans Verkuil }, 2287955f03dSHans Verkuil { 2297955f03dSHans Verkuil .type = "tuner", 2307955f03dSHans Verkuil .addr = 0x43, 2317955f03dSHans Verkuil }, 2327955f03dSHans Verkuil { 2337955f03dSHans Verkuil .type = "sony-btf-mpx", 2347955f03dSHans Verkuil .addr = 0x44, 2357955f03dSHans Verkuil }, 2367955f03dSHans Verkuil }, 2377955f03dSHans Verkuil .num_inputs = 3, 2387955f03dSHans Verkuil .inputs = { 2397955f03dSHans Verkuil { 2407955f03dSHans Verkuil .video_input = 3, 2417955f03dSHans Verkuil .audio_index = 0, 2427955f03dSHans Verkuil .name = "Tuner", 2437955f03dSHans Verkuil }, 2447955f03dSHans Verkuil { 2457955f03dSHans Verkuil .video_input = 1, 2467955f03dSHans Verkuil .audio_index = 1, 2477955f03dSHans Verkuil .name = "Composite", 2487955f03dSHans Verkuil }, 2497955f03dSHans Verkuil { 2507955f03dSHans Verkuil .video_input = 8, 2517955f03dSHans Verkuil .audio_index = 1, 2527955f03dSHans Verkuil .name = "S-Video", 2537955f03dSHans Verkuil }, 2547955f03dSHans Verkuil }, 2557955f03dSHans Verkuil .video_config = SAA7115_IDQ_IS_DEFAULT, 2567955f03dSHans Verkuil .num_aud_inputs = 2, 2577955f03dSHans Verkuil .aud_inputs = { 2587955f03dSHans Verkuil { 2597955f03dSHans Verkuil .audio_input = UDA1342_IN2, 2607955f03dSHans Verkuil .name = "Tuner", 2617955f03dSHans Verkuil }, 2627955f03dSHans Verkuil { 2637955f03dSHans Verkuil .audio_input = UDA1342_IN1, 2647955f03dSHans Verkuil .name = "Line In", 2657955f03dSHans Verkuil }, 2667955f03dSHans Verkuil }, 2677955f03dSHans Verkuil }, 2687955f03dSHans Verkuil }; 2697955f03dSHans Verkuil 2707955f03dSHans Verkuil static const struct go7007_usb_board board_xmen = { 2717955f03dSHans Verkuil .flags = 0, 2727955f03dSHans Verkuil .main_info = { 2737955f03dSHans Verkuil .flags = GO7007_BOARD_USE_ONBOARD_I2C, 2747955f03dSHans Verkuil .hpi_buffer_cap = 0, 2757955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_VREF_POLAR, 2767955f03dSHans Verkuil .sensor_width = 320, 2777955f03dSHans Verkuil .sensor_height = 240, 2787955f03dSHans Verkuil .sensor_framerate = 30030, 2797955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_ONE_CHANNEL | 2807955f03dSHans Verkuil GO7007_AUDIO_I2S_MODE_3 | 2817955f03dSHans Verkuil GO7007_AUDIO_WORD_14 | 2827955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 2837955f03dSHans Verkuil GO7007_AUDIO_BCLK_POLAR | 2847955f03dSHans Verkuil GO7007_AUDIO_OKI_MODE, 2857955f03dSHans Verkuil .audio_rate = 8000, 2867955f03dSHans Verkuil .audio_bclk_div = 48, 2877955f03dSHans Verkuil .audio_main_div = 1, 2887955f03dSHans Verkuil .num_i2c_devs = 1, 2897955f03dSHans Verkuil .i2c_devs = { 2907955f03dSHans Verkuil { 2917955f03dSHans Verkuil .type = "ov7640", 2927955f03dSHans Verkuil .addr = 0x21, 2937955f03dSHans Verkuil }, 2947955f03dSHans Verkuil }, 2957955f03dSHans Verkuil .num_inputs = 1, 2967955f03dSHans Verkuil .inputs = { 2977955f03dSHans Verkuil { 2987955f03dSHans Verkuil .name = "Camera", 2997955f03dSHans Verkuil }, 3007955f03dSHans Verkuil }, 3017955f03dSHans Verkuil }, 3027955f03dSHans Verkuil }; 3037955f03dSHans Verkuil 3047955f03dSHans Verkuil static const struct go7007_usb_board board_matrix_revolution = { 3057955f03dSHans Verkuil .flags = GO7007_USB_EZUSB, 3067955f03dSHans Verkuil .main_info = { 3077955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO | 3087955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C, 3097955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 3107955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 3117955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 3127955f03dSHans Verkuil .audio_rate = 48000, 3137955f03dSHans Verkuil .audio_bclk_div = 8, 3147955f03dSHans Verkuil .audio_main_div = 2, 3157955f03dSHans Verkuil .hpi_buffer_cap = 7, 3167955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 3177955f03dSHans Verkuil GO7007_SENSOR_TV | 3187955f03dSHans Verkuil GO7007_SENSOR_VBI, 3197955f03dSHans Verkuil .num_i2c_devs = 1, 3207955f03dSHans Verkuil .i2c_devs = { 3217955f03dSHans Verkuil { 3227955f03dSHans Verkuil .type = "tw9903", 3237955f03dSHans Verkuil .is_video = 1, 3247955f03dSHans Verkuil .addr = 0x44, 3257955f03dSHans Verkuil }, 3267955f03dSHans Verkuil }, 3277955f03dSHans Verkuil .num_inputs = 2, 3287955f03dSHans Verkuil .inputs = { 3297955f03dSHans Verkuil { 3307955f03dSHans Verkuil .video_input = 2, 3317955f03dSHans Verkuil .name = "Composite", 3327955f03dSHans Verkuil }, 3337955f03dSHans Verkuil { 3347955f03dSHans Verkuil .video_input = 8, 3357955f03dSHans Verkuil .name = "S-Video", 3367955f03dSHans Verkuil }, 3377955f03dSHans Verkuil }, 3387955f03dSHans Verkuil }, 3397955f03dSHans Verkuil }; 3407955f03dSHans Verkuil 3417955f03dSHans Verkuil static const struct go7007_usb_board board_lifeview_lr192 = { 3427955f03dSHans Verkuil .flags = GO7007_USB_EZUSB, 3437955f03dSHans Verkuil .main_info = { 3447955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO | 3457955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C, 3467955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 3477955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 3487955f03dSHans Verkuil .audio_rate = 48000, 3497955f03dSHans Verkuil .audio_bclk_div = 8, 3507955f03dSHans Verkuil .audio_main_div = 2, 3517955f03dSHans Verkuil .hpi_buffer_cap = 7, 3527955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 3537955f03dSHans Verkuil GO7007_SENSOR_VALID_ENABLE | 3547955f03dSHans Verkuil GO7007_SENSOR_TV | 3557955f03dSHans Verkuil GO7007_SENSOR_VBI | 3567955f03dSHans Verkuil GO7007_SENSOR_SCALING, 3577955f03dSHans Verkuil .num_i2c_devs = 0, 3587955f03dSHans Verkuil .num_inputs = 1, 3597955f03dSHans Verkuil .inputs = { 3607955f03dSHans Verkuil { 3617955f03dSHans Verkuil .video_input = 0, 3627955f03dSHans Verkuil .name = "Composite", 3637955f03dSHans Verkuil }, 3647955f03dSHans Verkuil }, 3657955f03dSHans Verkuil }, 3667955f03dSHans Verkuil }; 3677955f03dSHans Verkuil 3687955f03dSHans Verkuil static const struct go7007_usb_board board_endura = { 3697955f03dSHans Verkuil .flags = 0, 3707955f03dSHans Verkuil .main_info = { 3717955f03dSHans Verkuil .flags = 0, 3727955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 3737955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 3747955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 3757955f03dSHans Verkuil .audio_rate = 8000, 3767955f03dSHans Verkuil .audio_bclk_div = 48, 3777955f03dSHans Verkuil .audio_main_div = 8, 3787955f03dSHans Verkuil .hpi_buffer_cap = 0, 3797955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 3807955f03dSHans Verkuil GO7007_SENSOR_TV, 3817955f03dSHans Verkuil .sensor_h_offset = 8, 3827955f03dSHans Verkuil .num_i2c_devs = 0, 3837955f03dSHans Verkuil .num_inputs = 1, 3847955f03dSHans Verkuil .inputs = { 3857955f03dSHans Verkuil { 3867955f03dSHans Verkuil .name = "Camera", 3877955f03dSHans Verkuil }, 3887955f03dSHans Verkuil }, 3897955f03dSHans Verkuil }, 3907955f03dSHans Verkuil }; 3917955f03dSHans Verkuil 3927955f03dSHans Verkuil static const struct go7007_usb_board board_adlink_mpg24 = { 3937955f03dSHans Verkuil .flags = 0, 3947955f03dSHans Verkuil .main_info = { 3957955f03dSHans Verkuil .flags = GO7007_BOARD_USE_ONBOARD_I2C, 3967955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 3977955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 3987955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 3997955f03dSHans Verkuil .audio_rate = 48000, 4007955f03dSHans Verkuil .audio_bclk_div = 8, 4017955f03dSHans Verkuil .audio_main_div = 2, 4027955f03dSHans Verkuil .hpi_buffer_cap = 0, 4037955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 4047955f03dSHans Verkuil GO7007_SENSOR_TV | 4057955f03dSHans Verkuil GO7007_SENSOR_VBI, 4067955f03dSHans Verkuil .num_i2c_devs = 1, 4077955f03dSHans Verkuil .i2c_devs = { 4087955f03dSHans Verkuil { 4097955f03dSHans Verkuil .type = "tw2804", 4107955f03dSHans Verkuil .addr = 0x00, /* yes, really */ 4117955f03dSHans Verkuil .flags = I2C_CLIENT_TEN, 4127955f03dSHans Verkuil .is_video = 1, 4137955f03dSHans Verkuil }, 4147955f03dSHans Verkuil }, 4157955f03dSHans Verkuil .num_inputs = 1, 4167955f03dSHans Verkuil .inputs = { 4177955f03dSHans Verkuil { 4187955f03dSHans Verkuil .name = "Composite", 4197955f03dSHans Verkuil }, 4207955f03dSHans Verkuil }, 4217955f03dSHans Verkuil }, 4227955f03dSHans Verkuil }; 4237955f03dSHans Verkuil 4247955f03dSHans Verkuil static const struct go7007_usb_board board_sensoray_2250 = { 4257955f03dSHans Verkuil .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, 4267955f03dSHans Verkuil .main_info = { 4277955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 4287955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 4297955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 4307955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO, 4317955f03dSHans Verkuil .audio_rate = 48000, 4327955f03dSHans Verkuil .audio_bclk_div = 8, 4337955f03dSHans Verkuil .audio_main_div = 2, 4347955f03dSHans Verkuil .hpi_buffer_cap = 7, 4357955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 4367955f03dSHans Verkuil GO7007_SENSOR_TV, 4377955f03dSHans Verkuil .num_i2c_devs = 1, 4387955f03dSHans Verkuil .i2c_devs = { 4397955f03dSHans Verkuil { 4407955f03dSHans Verkuil .type = "s2250", 4417955f03dSHans Verkuil .addr = 0x43, 4427955f03dSHans Verkuil .is_video = 1, 4437955f03dSHans Verkuil .is_audio = 1, 4447955f03dSHans Verkuil }, 4457955f03dSHans Verkuil }, 4467955f03dSHans Verkuil .num_inputs = 2, 4477955f03dSHans Verkuil .inputs = { 4487955f03dSHans Verkuil { 4497955f03dSHans Verkuil .video_input = 0, 4507955f03dSHans Verkuil .name = "Composite", 4517955f03dSHans Verkuil }, 4527955f03dSHans Verkuil { 4537955f03dSHans Verkuil .video_input = 1, 4547955f03dSHans Verkuil .name = "S-Video", 4557955f03dSHans Verkuil }, 4567955f03dSHans Verkuil }, 4577955f03dSHans Verkuil .num_aud_inputs = 3, 4587955f03dSHans Verkuil .aud_inputs = { 4597955f03dSHans Verkuil { 4607955f03dSHans Verkuil .audio_input = 0, 4617955f03dSHans Verkuil .name = "Line In", 4627955f03dSHans Verkuil }, 4637955f03dSHans Verkuil { 4647955f03dSHans Verkuil .audio_input = 1, 4657955f03dSHans Verkuil .name = "Mic", 4667955f03dSHans Verkuil }, 4677955f03dSHans Verkuil { 4687955f03dSHans Verkuil .audio_input = 2, 4697955f03dSHans Verkuil .name = "Mic Boost", 4707955f03dSHans Verkuil }, 4717955f03dSHans Verkuil }, 4727955f03dSHans Verkuil }, 4737955f03dSHans Verkuil }; 4747955f03dSHans Verkuil 4757955f03dSHans Verkuil static const struct go7007_usb_board board_ads_usbav_709 = { 4767955f03dSHans Verkuil .flags = GO7007_USB_EZUSB, 4777955f03dSHans Verkuil .main_info = { 4787955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO | 4797955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C, 4807955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 4817955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 4827955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 4837955f03dSHans Verkuil .audio_rate = 48000, 4847955f03dSHans Verkuil .audio_bclk_div = 8, 4857955f03dSHans Verkuil .audio_main_div = 2, 4867955f03dSHans Verkuil .hpi_buffer_cap = 7, 4877955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 4887955f03dSHans Verkuil GO7007_SENSOR_TV | 4897955f03dSHans Verkuil GO7007_SENSOR_VBI, 4907955f03dSHans Verkuil .num_i2c_devs = 1, 4917955f03dSHans Verkuil .i2c_devs = { 4927955f03dSHans Verkuil { 4937955f03dSHans Verkuil .type = "tw9906", 4947955f03dSHans Verkuil .is_video = 1, 4957955f03dSHans Verkuil .addr = 0x44, 4967955f03dSHans Verkuil }, 4977955f03dSHans Verkuil }, 4987955f03dSHans Verkuil .num_inputs = 2, 4997955f03dSHans Verkuil .inputs = { 5007955f03dSHans Verkuil { 5017955f03dSHans Verkuil .video_input = 0, 5027955f03dSHans Verkuil .name = "Composite", 5037955f03dSHans Verkuil }, 5047955f03dSHans Verkuil { 5057955f03dSHans Verkuil .video_input = 10, 5067955f03dSHans Verkuil .name = "S-Video", 5077955f03dSHans Verkuil }, 5087955f03dSHans Verkuil }, 5097955f03dSHans Verkuil }, 5107955f03dSHans Verkuil }; 5117955f03dSHans Verkuil 5127955f03dSHans Verkuil static const struct usb_device_id go7007_usb_id_table[] = { 5137955f03dSHans Verkuil { 5147955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | 5157955f03dSHans Verkuil USB_DEVICE_ID_MATCH_INT_INFO, 5167955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 5177955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 5187955f03dSHans Verkuil .bcdDevice_lo = 0x200, /* Revision number of XMen */ 5197955f03dSHans Verkuil .bcdDevice_hi = 0x200, 5207955f03dSHans Verkuil .bInterfaceClass = 255, 5217955f03dSHans Verkuil .bInterfaceSubClass = 0, 5227955f03dSHans Verkuil .bInterfaceProtocol = 255, 5237955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN, 5247955f03dSHans Verkuil }, 5257955f03dSHans Verkuil { 5267955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 5277955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 5287955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 5297955f03dSHans Verkuil .bcdDevice_lo = 0x202, /* Revision number of Matrix II */ 5307955f03dSHans Verkuil .bcdDevice_hi = 0x202, 5317955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_II, 5327955f03dSHans Verkuil }, 5337955f03dSHans Verkuil { 5347955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 5357955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 5367955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 5377955f03dSHans Verkuil .bcdDevice_lo = 0x204, /* Revision number of Matrix */ 5387955f03dSHans Verkuil .bcdDevice_hi = 0x204, /* Reloaded */ 5397955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_RELOAD, 5407955f03dSHans Verkuil }, 5417955f03dSHans Verkuil { 5427955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | 5437955f03dSHans Verkuil USB_DEVICE_ID_MATCH_INT_INFO, 5447955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 5457955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 5467955f03dSHans Verkuil .bcdDevice_lo = 0x205, /* Revision number of XMen-II */ 5477955f03dSHans Verkuil .bcdDevice_hi = 0x205, 5487955f03dSHans Verkuil .bInterfaceClass = 255, 5497955f03dSHans Verkuil .bInterfaceSubClass = 0, 5507955f03dSHans Verkuil .bInterfaceProtocol = 255, 5517955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN_II, 5527955f03dSHans Verkuil }, 5537955f03dSHans Verkuil { 5547955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 5557955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 5567955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 5577955f03dSHans Verkuil .bcdDevice_lo = 0x208, /* Revision number of Star Trek */ 5587955f03dSHans Verkuil .bcdDevice_hi = 0x208, 5597955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_STAR_TREK, 5607955f03dSHans Verkuil }, 5617955f03dSHans Verkuil { 5627955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | 5637955f03dSHans Verkuil USB_DEVICE_ID_MATCH_INT_INFO, 5647955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 5657955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 5667955f03dSHans Verkuil .bcdDevice_lo = 0x209, /* Revision number of XMen-III */ 5677955f03dSHans Verkuil .bcdDevice_hi = 0x209, 5687955f03dSHans Verkuil .bInterfaceClass = 255, 5697955f03dSHans Verkuil .bInterfaceSubClass = 0, 5707955f03dSHans Verkuil .bInterfaceProtocol = 255, 5717955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN_III, 5727955f03dSHans Verkuil }, 5737955f03dSHans Verkuil { 5747955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 5757955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 5767955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 5777955f03dSHans Verkuil .bcdDevice_lo = 0x210, /* Revision number of Matrix */ 5787955f03dSHans Verkuil .bcdDevice_hi = 0x210, /* Revolution */ 5797955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_REV, 5807955f03dSHans Verkuil }, 5817955f03dSHans Verkuil { 5827955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 5837955f03dSHans Verkuil .idVendor = 0x093b, /* Vendor ID of Plextor */ 5847955f03dSHans Verkuil .idProduct = 0xa102, /* Product ID of M402U */ 5857955f03dSHans Verkuil .bcdDevice_lo = 0x1, /* revision number of Blueberry */ 5867955f03dSHans Verkuil .bcdDevice_hi = 0x1, 5877955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_PX_M402U, 5887955f03dSHans Verkuil }, 5897955f03dSHans Verkuil { 5907955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 5917955f03dSHans Verkuil .idVendor = 0x093b, /* Vendor ID of Plextor */ 5927955f03dSHans Verkuil .idProduct = 0xa104, /* Product ID of TV402U */ 5937955f03dSHans Verkuil .bcdDevice_lo = 0x1, 5947955f03dSHans Verkuil .bcdDevice_hi = 0x1, 5957955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_PX_TV402U, 5967955f03dSHans Verkuil }, 5977955f03dSHans Verkuil { 5987955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 5997955f03dSHans Verkuil .idVendor = 0x10fd, /* Vendor ID of Anubis Electronics */ 6007955f03dSHans Verkuil .idProduct = 0xde00, /* Product ID of Lifeview LR192 */ 6017955f03dSHans Verkuil .bcdDevice_lo = 0x1, 6027955f03dSHans Verkuil .bcdDevice_hi = 0x1, 6037955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_LIFEVIEW_LR192, 6047955f03dSHans Verkuil }, 6057955f03dSHans Verkuil { 6067955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 6077955f03dSHans Verkuil .idVendor = 0x1943, /* Vendor ID Sensoray */ 6087955f03dSHans Verkuil .idProduct = 0x2250, /* Product ID of 2250/2251 */ 6097955f03dSHans Verkuil .bcdDevice_lo = 0x1, 6107955f03dSHans Verkuil .bcdDevice_hi = 0x1, 6117955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_SENSORAY_2250, 6127955f03dSHans Verkuil }, 6137955f03dSHans Verkuil { 6147955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 6157955f03dSHans Verkuil .idVendor = 0x06e1, /* Vendor ID of ADS Technologies */ 6167955f03dSHans Verkuil .idProduct = 0x0709, /* Product ID of DVD Xpress DX2 */ 6177955f03dSHans Verkuil .bcdDevice_lo = 0x204, 6187955f03dSHans Verkuil .bcdDevice_hi = 0x204, 6197955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_ADS_USBAV_709, 6207955f03dSHans Verkuil }, 6217955f03dSHans Verkuil { } /* Terminating entry */ 6227955f03dSHans Verkuil }; 6237955f03dSHans Verkuil 6247955f03dSHans Verkuil MODULE_DEVICE_TABLE(usb, go7007_usb_id_table); 6257955f03dSHans Verkuil 6267955f03dSHans Verkuil /********************* Driver for EZ-USB HPI interface *********************/ 6277955f03dSHans Verkuil 6287955f03dSHans Verkuil static int go7007_usb_vendor_request(struct go7007 *go, int request, 6297955f03dSHans Verkuil int value, int index, void *transfer_buffer, int length, int in) 6307955f03dSHans Verkuil { 6317955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 6327955f03dSHans Verkuil int timeout = 5000; 6337955f03dSHans Verkuil 6347955f03dSHans Verkuil if (in) { 6357955f03dSHans Verkuil return usb_control_msg(usb->usbdev, 6367955f03dSHans Verkuil usb_rcvctrlpipe(usb->usbdev, 0), request, 6377955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 6387955f03dSHans Verkuil value, index, transfer_buffer, length, timeout); 6397955f03dSHans Verkuil } else { 6407955f03dSHans Verkuil return usb_control_msg(usb->usbdev, 6417955f03dSHans Verkuil usb_sndctrlpipe(usb->usbdev, 0), request, 6427955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_DEVICE, 6437955f03dSHans Verkuil value, index, transfer_buffer, length, timeout); 6447955f03dSHans Verkuil } 6457955f03dSHans Verkuil } 6467955f03dSHans Verkuil 6477955f03dSHans Verkuil static int go7007_usb_interface_reset(struct go7007 *go) 6487955f03dSHans Verkuil { 6497955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 6507955f03dSHans Verkuil u16 intr_val, intr_data; 6517955f03dSHans Verkuil 6527955f03dSHans Verkuil if (go->status == STATUS_SHUTDOWN) 6537955f03dSHans Verkuil return -1; 6547955f03dSHans Verkuil /* Reset encoder */ 6557955f03dSHans Verkuil if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0) 6567955f03dSHans Verkuil return -1; 6577955f03dSHans Verkuil msleep(100); 6587955f03dSHans Verkuil 6597955f03dSHans Verkuil if (usb->board->flags & GO7007_USB_EZUSB) { 6607955f03dSHans Verkuil /* Reset buffer in EZ-USB */ 6617955f03dSHans Verkuil pr_debug("resetting EZ-USB buffers\n"); 6627955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0 || 6637955f03dSHans Verkuil go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0) 6647955f03dSHans Verkuil return -1; 6657955f03dSHans Verkuil 6667955f03dSHans Verkuil /* Reset encoder again */ 6677955f03dSHans Verkuil if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0) 6687955f03dSHans Verkuil return -1; 6697955f03dSHans Verkuil msleep(100); 6707955f03dSHans Verkuil } 6717955f03dSHans Verkuil 6727955f03dSHans Verkuil /* Wait for an interrupt to indicate successful hardware reset */ 6737955f03dSHans Verkuil if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || 6747955f03dSHans Verkuil (intr_val & ~0x1) != 0x55aa) { 6757955f03dSHans Verkuil dev_err(go->dev, "unable to reset the USB interface\n"); 6767955f03dSHans Verkuil return -1; 6777955f03dSHans Verkuil } 6787955f03dSHans Verkuil return 0; 6797955f03dSHans Verkuil } 6807955f03dSHans Verkuil 6817955f03dSHans Verkuil static int go7007_usb_ezusb_write_interrupt(struct go7007 *go, 6827955f03dSHans Verkuil int addr, int data) 6837955f03dSHans Verkuil { 6847955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 6857955f03dSHans Verkuil int i, r; 6867955f03dSHans Verkuil u16 status_reg = 0; 6877955f03dSHans Verkuil int timeout = 500; 6887955f03dSHans Verkuil 6897955f03dSHans Verkuil pr_debug("WriteInterrupt: %04x %04x\n", addr, data); 6907955f03dSHans Verkuil 6917955f03dSHans Verkuil for (i = 0; i < 100; ++i) { 6927955f03dSHans Verkuil r = usb_control_msg(usb->usbdev, 6937955f03dSHans Verkuil usb_rcvctrlpipe(usb->usbdev, 0), 0x14, 6947955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 6957955f03dSHans Verkuil 0, HPI_STATUS_ADDR, go->usb_buf, 6967955f03dSHans Verkuil sizeof(status_reg), timeout); 6977955f03dSHans Verkuil if (r < 0) 6987955f03dSHans Verkuil break; 699*616e3506SHans Verkuil status_reg = le16_to_cpu(*((__le16 *)go->usb_buf)); 7007955f03dSHans Verkuil if (!(status_reg & 0x0010)) 7017955f03dSHans Verkuil break; 7027955f03dSHans Verkuil msleep(10); 7037955f03dSHans Verkuil } 7047955f03dSHans Verkuil if (r < 0) 7057955f03dSHans Verkuil goto write_int_error; 7067955f03dSHans Verkuil if (i == 100) { 7077955f03dSHans Verkuil dev_err(go->dev, "device is hung, status reg = 0x%04x\n", status_reg); 7087955f03dSHans Verkuil return -1; 7097955f03dSHans Verkuil } 7107955f03dSHans Verkuil r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), 0x12, 7117955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_DEVICE, data, 7127955f03dSHans Verkuil INT_PARAM_ADDR, NULL, 0, timeout); 7137955f03dSHans Verkuil if (r < 0) 7147955f03dSHans Verkuil goto write_int_error; 7157955f03dSHans Verkuil r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), 7167955f03dSHans Verkuil 0x12, USB_TYPE_VENDOR | USB_RECIP_DEVICE, addr, 7177955f03dSHans Verkuil INT_INDEX_ADDR, NULL, 0, timeout); 7187955f03dSHans Verkuil if (r < 0) 7197955f03dSHans Verkuil goto write_int_error; 7207955f03dSHans Verkuil return 0; 7217955f03dSHans Verkuil 7227955f03dSHans Verkuil write_int_error: 7237955f03dSHans Verkuil dev_err(go->dev, "error in WriteInterrupt: %d\n", r); 7247955f03dSHans Verkuil return r; 7257955f03dSHans Verkuil } 7267955f03dSHans Verkuil 7277955f03dSHans Verkuil static int go7007_usb_onboard_write_interrupt(struct go7007 *go, 7287955f03dSHans Verkuil int addr, int data) 7297955f03dSHans Verkuil { 7307955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 7317955f03dSHans Verkuil int r; 7327955f03dSHans Verkuil int timeout = 500; 7337955f03dSHans Verkuil 7347955f03dSHans Verkuil pr_debug("WriteInterrupt: %04x %04x\n", addr, data); 7357955f03dSHans Verkuil 7367955f03dSHans Verkuil go->usb_buf[0] = data & 0xff; 7377955f03dSHans Verkuil go->usb_buf[1] = data >> 8; 7387955f03dSHans Verkuil go->usb_buf[2] = addr & 0xff; 7397955f03dSHans Verkuil go->usb_buf[3] = addr >> 8; 7407955f03dSHans Verkuil go->usb_buf[4] = go->usb_buf[5] = go->usb_buf[6] = go->usb_buf[7] = 0; 7417955f03dSHans Verkuil r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 2), 0x00, 7427955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0x55aa, 7437955f03dSHans Verkuil 0xf0f0, go->usb_buf, 8, timeout); 7447955f03dSHans Verkuil if (r < 0) { 7457955f03dSHans Verkuil dev_err(go->dev, "error in WriteInterrupt: %d\n", r); 7467955f03dSHans Verkuil return r; 7477955f03dSHans Verkuil } 7487955f03dSHans Verkuil return 0; 7497955f03dSHans Verkuil } 7507955f03dSHans Verkuil 7517955f03dSHans Verkuil static void go7007_usb_readinterrupt_complete(struct urb *urb) 7527955f03dSHans Verkuil { 7537955f03dSHans Verkuil struct go7007 *go = (struct go7007 *)urb->context; 754*616e3506SHans Verkuil __le16 *regs = (__le16 *)urb->transfer_buffer; 7557955f03dSHans Verkuil int status = urb->status; 7567955f03dSHans Verkuil 7577955f03dSHans Verkuil if (status) { 7587955f03dSHans Verkuil if (status != -ESHUTDOWN && 7597955f03dSHans Verkuil go->status != STATUS_SHUTDOWN) { 7607955f03dSHans Verkuil dev_err(go->dev, "error in read interrupt: %d\n", urb->status); 7617955f03dSHans Verkuil } else { 7627955f03dSHans Verkuil wake_up(&go->interrupt_waitq); 7637955f03dSHans Verkuil return; 7647955f03dSHans Verkuil } 7657955f03dSHans Verkuil } else if (urb->actual_length != urb->transfer_buffer_length) { 7667955f03dSHans Verkuil dev_err(go->dev, "short read in interrupt pipe!\n"); 7677955f03dSHans Verkuil } else { 7687955f03dSHans Verkuil go->interrupt_available = 1; 7697955f03dSHans Verkuil go->interrupt_data = __le16_to_cpu(regs[0]); 7707955f03dSHans Verkuil go->interrupt_value = __le16_to_cpu(regs[1]); 7717955f03dSHans Verkuil pr_debug("ReadInterrupt: %04x %04x\n", 7727955f03dSHans Verkuil go->interrupt_value, go->interrupt_data); 7737955f03dSHans Verkuil } 7747955f03dSHans Verkuil 7757955f03dSHans Verkuil wake_up(&go->interrupt_waitq); 7767955f03dSHans Verkuil } 7777955f03dSHans Verkuil 7787955f03dSHans Verkuil static int go7007_usb_read_interrupt(struct go7007 *go) 7797955f03dSHans Verkuil { 7807955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 7817955f03dSHans Verkuil int r; 7827955f03dSHans Verkuil 7837955f03dSHans Verkuil r = usb_submit_urb(usb->intr_urb, GFP_KERNEL); 7847955f03dSHans Verkuil if (r < 0) { 7857955f03dSHans Verkuil dev_err(go->dev, "unable to submit interrupt urb: %d\n", r); 7867955f03dSHans Verkuil return r; 7877955f03dSHans Verkuil } 7887955f03dSHans Verkuil return 0; 7897955f03dSHans Verkuil } 7907955f03dSHans Verkuil 7917955f03dSHans Verkuil static void go7007_usb_read_video_pipe_complete(struct urb *urb) 7927955f03dSHans Verkuil { 7937955f03dSHans Verkuil struct go7007 *go = (struct go7007 *)urb->context; 7947955f03dSHans Verkuil int r, status = urb->status; 7957955f03dSHans Verkuil 7967955f03dSHans Verkuil if (!vb2_is_streaming(&go->vidq)) { 7977955f03dSHans Verkuil wake_up_interruptible(&go->frame_waitq); 7987955f03dSHans Verkuil return; 7997955f03dSHans Verkuil } 8007955f03dSHans Verkuil if (status) { 8017955f03dSHans Verkuil dev_err(go->dev, "error in video pipe: %d\n", status); 8027955f03dSHans Verkuil return; 8037955f03dSHans Verkuil } 8047955f03dSHans Verkuil if (urb->actual_length != urb->transfer_buffer_length) { 8057955f03dSHans Verkuil dev_err(go->dev, "short read in video pipe!\n"); 8067955f03dSHans Verkuil return; 8077955f03dSHans Verkuil } 8087955f03dSHans Verkuil go7007_parse_video_stream(go, urb->transfer_buffer, urb->actual_length); 8097955f03dSHans Verkuil r = usb_submit_urb(urb, GFP_ATOMIC); 8107955f03dSHans Verkuil if (r < 0) 8117955f03dSHans Verkuil dev_err(go->dev, "error in video pipe: %d\n", r); 8127955f03dSHans Verkuil } 8137955f03dSHans Verkuil 8147955f03dSHans Verkuil static void go7007_usb_read_audio_pipe_complete(struct urb *urb) 8157955f03dSHans Verkuil { 8167955f03dSHans Verkuil struct go7007 *go = (struct go7007 *)urb->context; 8177955f03dSHans Verkuil int r, status = urb->status; 8187955f03dSHans Verkuil 8197955f03dSHans Verkuil if (!vb2_is_streaming(&go->vidq)) 8207955f03dSHans Verkuil return; 8217955f03dSHans Verkuil if (status) { 8227955f03dSHans Verkuil dev_err(go->dev, "error in audio pipe: %d\n", 8237955f03dSHans Verkuil status); 8247955f03dSHans Verkuil return; 8257955f03dSHans Verkuil } 8267955f03dSHans Verkuil if (urb->actual_length != urb->transfer_buffer_length) { 8277955f03dSHans Verkuil dev_err(go->dev, "short read in audio pipe!\n"); 8287955f03dSHans Verkuil return; 8297955f03dSHans Verkuil } 8307955f03dSHans Verkuil if (go->audio_deliver != NULL) 8317955f03dSHans Verkuil go->audio_deliver(go, urb->transfer_buffer, urb->actual_length); 8327955f03dSHans Verkuil r = usb_submit_urb(urb, GFP_ATOMIC); 8337955f03dSHans Verkuil if (r < 0) 8347955f03dSHans Verkuil dev_err(go->dev, "error in audio pipe: %d\n", r); 8357955f03dSHans Verkuil } 8367955f03dSHans Verkuil 8377955f03dSHans Verkuil static int go7007_usb_stream_start(struct go7007 *go) 8387955f03dSHans Verkuil { 8397955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 8407955f03dSHans Verkuil int i, r; 8417955f03dSHans Verkuil 8427955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 8437955f03dSHans Verkuil r = usb_submit_urb(usb->video_urbs[i], GFP_KERNEL); 8447955f03dSHans Verkuil if (r < 0) { 8457955f03dSHans Verkuil dev_err(go->dev, "error submitting video urb %d: %d\n", i, r); 8467955f03dSHans Verkuil goto video_submit_failed; 8477955f03dSHans Verkuil } 8487955f03dSHans Verkuil } 8497955f03dSHans Verkuil if (!go->audio_enabled) 8507955f03dSHans Verkuil return 0; 8517955f03dSHans Verkuil 8527955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 8537955f03dSHans Verkuil r = usb_submit_urb(usb->audio_urbs[i], GFP_KERNEL); 8547955f03dSHans Verkuil if (r < 0) { 8557955f03dSHans Verkuil dev_err(go->dev, "error submitting audio urb %d: %d\n", i, r); 8567955f03dSHans Verkuil goto audio_submit_failed; 8577955f03dSHans Verkuil } 8587955f03dSHans Verkuil } 8597955f03dSHans Verkuil return 0; 8607955f03dSHans Verkuil 8617955f03dSHans Verkuil audio_submit_failed: 8627955f03dSHans Verkuil for (i = 0; i < 7; ++i) 8637955f03dSHans Verkuil usb_kill_urb(usb->audio_urbs[i]); 8647955f03dSHans Verkuil video_submit_failed: 8657955f03dSHans Verkuil for (i = 0; i < 8; ++i) 8667955f03dSHans Verkuil usb_kill_urb(usb->video_urbs[i]); 8677955f03dSHans Verkuil return -1; 8687955f03dSHans Verkuil } 8697955f03dSHans Verkuil 8707955f03dSHans Verkuil static int go7007_usb_stream_stop(struct go7007 *go) 8717955f03dSHans Verkuil { 8727955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 8737955f03dSHans Verkuil int i; 8747955f03dSHans Verkuil 8757955f03dSHans Verkuil if (go->status == STATUS_SHUTDOWN) 8767955f03dSHans Verkuil return 0; 8777955f03dSHans Verkuil for (i = 0; i < 8; ++i) 8787955f03dSHans Verkuil usb_kill_urb(usb->video_urbs[i]); 8797955f03dSHans Verkuil if (go->audio_enabled) 8807955f03dSHans Verkuil for (i = 0; i < 8; ++i) 8817955f03dSHans Verkuil usb_kill_urb(usb->audio_urbs[i]); 8827955f03dSHans Verkuil return 0; 8837955f03dSHans Verkuil } 8847955f03dSHans Verkuil 8857955f03dSHans Verkuil static int go7007_usb_send_firmware(struct go7007 *go, u8 *data, int len) 8867955f03dSHans Verkuil { 8877955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 8887955f03dSHans Verkuil int transferred, pipe; 8897955f03dSHans Verkuil int timeout = 500; 8907955f03dSHans Verkuil 8917955f03dSHans Verkuil pr_debug("DownloadBuffer sending %d bytes\n", len); 8927955f03dSHans Verkuil 8937955f03dSHans Verkuil if (usb->board->flags & GO7007_USB_EZUSB) 8947955f03dSHans Verkuil pipe = usb_sndbulkpipe(usb->usbdev, 2); 8957955f03dSHans Verkuil else 8967955f03dSHans Verkuil pipe = usb_sndbulkpipe(usb->usbdev, 3); 8977955f03dSHans Verkuil 8987955f03dSHans Verkuil return usb_bulk_msg(usb->usbdev, pipe, data, len, 8997955f03dSHans Verkuil &transferred, timeout); 9007955f03dSHans Verkuil } 9017955f03dSHans Verkuil 9027955f03dSHans Verkuil static void go7007_usb_release(struct go7007 *go) 9037955f03dSHans Verkuil { 9047955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 9057955f03dSHans Verkuil struct urb *vurb, *aurb; 9067955f03dSHans Verkuil int i; 9077955f03dSHans Verkuil 9087955f03dSHans Verkuil if (usb->intr_urb) { 9097955f03dSHans Verkuil usb_kill_urb(usb->intr_urb); 9107955f03dSHans Verkuil kfree(usb->intr_urb->transfer_buffer); 9117955f03dSHans Verkuil usb_free_urb(usb->intr_urb); 9127955f03dSHans Verkuil } 9137955f03dSHans Verkuil 9147955f03dSHans Verkuil /* Free USB-related structs */ 9157955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 9167955f03dSHans Verkuil vurb = usb->video_urbs[i]; 9177955f03dSHans Verkuil if (vurb) { 9187955f03dSHans Verkuil usb_kill_urb(vurb); 9197955f03dSHans Verkuil kfree(vurb->transfer_buffer); 9207955f03dSHans Verkuil usb_free_urb(vurb); 9217955f03dSHans Verkuil } 9227955f03dSHans Verkuil aurb = usb->audio_urbs[i]; 9237955f03dSHans Verkuil if (aurb) { 9247955f03dSHans Verkuil usb_kill_urb(aurb); 9257955f03dSHans Verkuil kfree(aurb->transfer_buffer); 9267955f03dSHans Verkuil usb_free_urb(aurb); 9277955f03dSHans Verkuil } 9287955f03dSHans Verkuil } 9297955f03dSHans Verkuil 9307955f03dSHans Verkuil kfree(go->hpi_context); 9317955f03dSHans Verkuil } 9327955f03dSHans Verkuil 9337955f03dSHans Verkuil static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { 9347955f03dSHans Verkuil .interface_reset = go7007_usb_interface_reset, 9357955f03dSHans Verkuil .write_interrupt = go7007_usb_ezusb_write_interrupt, 9367955f03dSHans Verkuil .read_interrupt = go7007_usb_read_interrupt, 9377955f03dSHans Verkuil .stream_start = go7007_usb_stream_start, 9387955f03dSHans Verkuil .stream_stop = go7007_usb_stream_stop, 9397955f03dSHans Verkuil .send_firmware = go7007_usb_send_firmware, 9407955f03dSHans Verkuil .release = go7007_usb_release, 9417955f03dSHans Verkuil }; 9427955f03dSHans Verkuil 9437955f03dSHans Verkuil static struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = { 9447955f03dSHans Verkuil .interface_reset = go7007_usb_interface_reset, 9457955f03dSHans Verkuil .write_interrupt = go7007_usb_onboard_write_interrupt, 9467955f03dSHans Verkuil .read_interrupt = go7007_usb_read_interrupt, 9477955f03dSHans Verkuil .stream_start = go7007_usb_stream_start, 9487955f03dSHans Verkuil .stream_stop = go7007_usb_stream_stop, 9497955f03dSHans Verkuil .send_firmware = go7007_usb_send_firmware, 9507955f03dSHans Verkuil .release = go7007_usb_release, 9517955f03dSHans Verkuil }; 9527955f03dSHans Verkuil 9537955f03dSHans Verkuil /********************* Driver for EZ-USB I2C adapter *********************/ 9547955f03dSHans Verkuil 9557955f03dSHans Verkuil static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter, 9567955f03dSHans Verkuil struct i2c_msg msgs[], int num) 9577955f03dSHans Verkuil { 9587955f03dSHans Verkuil struct go7007 *go = i2c_get_adapdata(adapter); 9597955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 9607955f03dSHans Verkuil u8 *buf = go->usb_buf; 9617955f03dSHans Verkuil int buf_len, i; 9627955f03dSHans Verkuil int ret = -EIO; 9637955f03dSHans Verkuil 9647955f03dSHans Verkuil if (go->status == STATUS_SHUTDOWN) 9657955f03dSHans Verkuil return -ENODEV; 9667955f03dSHans Verkuil 9677955f03dSHans Verkuil mutex_lock(&usb->i2c_lock); 9687955f03dSHans Verkuil 9697955f03dSHans Verkuil for (i = 0; i < num; ++i) { 9707955f03dSHans Verkuil /* The hardware command is "write some bytes then read some 9717955f03dSHans Verkuil * bytes", so we try to coalesce a write followed by a read 9727955f03dSHans Verkuil * into a single USB transaction */ 9737955f03dSHans Verkuil if (i + 1 < num && msgs[i].addr == msgs[i + 1].addr && 9747955f03dSHans Verkuil !(msgs[i].flags & I2C_M_RD) && 9757955f03dSHans Verkuil (msgs[i + 1].flags & I2C_M_RD)) { 9767955f03dSHans Verkuil #ifdef GO7007_I2C_DEBUG 9777955f03dSHans Verkuil pr_debug("i2c write/read %d/%d bytes on %02x\n", 9787955f03dSHans Verkuil msgs[i].len, msgs[i + 1].len, msgs[i].addr); 9797955f03dSHans Verkuil #endif 9807955f03dSHans Verkuil buf[0] = 0x01; 9817955f03dSHans Verkuil buf[1] = msgs[i].len + 1; 9827955f03dSHans Verkuil buf[2] = msgs[i].addr << 1; 9837955f03dSHans Verkuil memcpy(&buf[3], msgs[i].buf, msgs[i].len); 9847955f03dSHans Verkuil buf_len = msgs[i].len + 3; 9857955f03dSHans Verkuil buf[buf_len++] = msgs[++i].len; 9867955f03dSHans Verkuil } else if (msgs[i].flags & I2C_M_RD) { 9877955f03dSHans Verkuil #ifdef GO7007_I2C_DEBUG 9887955f03dSHans Verkuil pr_debug("i2c read %d bytes on %02x\n", 9897955f03dSHans Verkuil msgs[i].len, msgs[i].addr); 9907955f03dSHans Verkuil #endif 9917955f03dSHans Verkuil buf[0] = 0x01; 9927955f03dSHans Verkuil buf[1] = 1; 9937955f03dSHans Verkuil buf[2] = msgs[i].addr << 1; 9947955f03dSHans Verkuil buf[3] = msgs[i].len; 9957955f03dSHans Verkuil buf_len = 4; 9967955f03dSHans Verkuil } else { 9977955f03dSHans Verkuil #ifdef GO7007_I2C_DEBUG 9987955f03dSHans Verkuil pr_debug("i2c write %d bytes on %02x\n", 9997955f03dSHans Verkuil msgs[i].len, msgs[i].addr); 10007955f03dSHans Verkuil #endif 10017955f03dSHans Verkuil buf[0] = 0x00; 10027955f03dSHans Verkuil buf[1] = msgs[i].len + 1; 10037955f03dSHans Verkuil buf[2] = msgs[i].addr << 1; 10047955f03dSHans Verkuil memcpy(&buf[3], msgs[i].buf, msgs[i].len); 10057955f03dSHans Verkuil buf_len = msgs[i].len + 3; 10067955f03dSHans Verkuil buf[buf_len++] = 0; 10077955f03dSHans Verkuil } 10087955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x24, 0, 0, 10097955f03dSHans Verkuil buf, buf_len, 0) < 0) 10107955f03dSHans Verkuil goto i2c_done; 10117955f03dSHans Verkuil if (msgs[i].flags & I2C_M_RD) { 10127955f03dSHans Verkuil memset(buf, 0, msgs[i].len + 1); 10137955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x25, 0, 0, buf, 10147955f03dSHans Verkuil msgs[i].len + 1, 1) < 0) 10157955f03dSHans Verkuil goto i2c_done; 10167955f03dSHans Verkuil memcpy(msgs[i].buf, buf + 1, msgs[i].len); 10177955f03dSHans Verkuil } 10187955f03dSHans Verkuil } 10197955f03dSHans Verkuil ret = num; 10207955f03dSHans Verkuil 10217955f03dSHans Verkuil i2c_done: 10227955f03dSHans Verkuil mutex_unlock(&usb->i2c_lock); 10237955f03dSHans Verkuil return ret; 10247955f03dSHans Verkuil } 10257955f03dSHans Verkuil 10267955f03dSHans Verkuil static u32 go7007_usb_functionality(struct i2c_adapter *adapter) 10277955f03dSHans Verkuil { 10287955f03dSHans Verkuil /* No errors are reported by the hardware, so we don't bother 10297955f03dSHans Verkuil * supporting quick writes to avoid confusing probing */ 10307955f03dSHans Verkuil return (I2C_FUNC_SMBUS_EMUL) & ~I2C_FUNC_SMBUS_QUICK; 10317955f03dSHans Verkuil } 10327955f03dSHans Verkuil 10337955f03dSHans Verkuil static struct i2c_algorithm go7007_usb_algo = { 10347955f03dSHans Verkuil .master_xfer = go7007_usb_i2c_master_xfer, 10357955f03dSHans Verkuil .functionality = go7007_usb_functionality, 10367955f03dSHans Verkuil }; 10377955f03dSHans Verkuil 10387955f03dSHans Verkuil static struct i2c_adapter go7007_usb_adap_templ = { 10397955f03dSHans Verkuil .owner = THIS_MODULE, 10407955f03dSHans Verkuil .name = "WIS GO7007SB EZ-USB", 10417955f03dSHans Verkuil .algo = &go7007_usb_algo, 10427955f03dSHans Verkuil }; 10437955f03dSHans Verkuil 10447955f03dSHans Verkuil /********************* USB add/remove functions *********************/ 10457955f03dSHans Verkuil 10467955f03dSHans Verkuil static int go7007_usb_probe(struct usb_interface *intf, 10477955f03dSHans Verkuil const struct usb_device_id *id) 10487955f03dSHans Verkuil { 10497955f03dSHans Verkuil struct go7007 *go; 10507955f03dSHans Verkuil struct go7007_usb *usb; 10517955f03dSHans Verkuil const struct go7007_usb_board *board; 10527955f03dSHans Verkuil struct usb_device *usbdev = interface_to_usbdev(intf); 10537955f03dSHans Verkuil unsigned num_i2c_devs; 10547955f03dSHans Verkuil char *name; 10557955f03dSHans Verkuil int video_pipe, i, v_urb_len; 10567955f03dSHans Verkuil 10577955f03dSHans Verkuil pr_debug("probing new GO7007 USB board\n"); 10587955f03dSHans Verkuil 10597955f03dSHans Verkuil switch (id->driver_info) { 10607955f03dSHans Verkuil case GO7007_BOARDID_MATRIX_II: 10617955f03dSHans Verkuil name = "WIS Matrix II or compatible"; 10627955f03dSHans Verkuil board = &board_matrix_ii; 10637955f03dSHans Verkuil break; 10647955f03dSHans Verkuil case GO7007_BOARDID_MATRIX_RELOAD: 10657955f03dSHans Verkuil name = "WIS Matrix Reloaded or compatible"; 10667955f03dSHans Verkuil board = &board_matrix_reload; 10677955f03dSHans Verkuil break; 10687955f03dSHans Verkuil case GO7007_BOARDID_MATRIX_REV: 10697955f03dSHans Verkuil name = "WIS Matrix Revolution or compatible"; 10707955f03dSHans Verkuil board = &board_matrix_revolution; 10717955f03dSHans Verkuil break; 10727955f03dSHans Verkuil case GO7007_BOARDID_STAR_TREK: 10737955f03dSHans Verkuil name = "WIS Star Trek or compatible"; 10747955f03dSHans Verkuil board = &board_star_trek; 10757955f03dSHans Verkuil break; 10767955f03dSHans Verkuil case GO7007_BOARDID_XMEN: 10777955f03dSHans Verkuil name = "WIS XMen or compatible"; 10787955f03dSHans Verkuil board = &board_xmen; 10797955f03dSHans Verkuil break; 10807955f03dSHans Verkuil case GO7007_BOARDID_XMEN_II: 10817955f03dSHans Verkuil name = "WIS XMen II or compatible"; 10827955f03dSHans Verkuil board = &board_xmen; 10837955f03dSHans Verkuil break; 10847955f03dSHans Verkuil case GO7007_BOARDID_XMEN_III: 10857955f03dSHans Verkuil name = "WIS XMen III or compatible"; 10867955f03dSHans Verkuil board = &board_xmen; 10877955f03dSHans Verkuil break; 10887955f03dSHans Verkuil case GO7007_BOARDID_PX_M402U: 10897955f03dSHans Verkuil name = "Plextor PX-M402U"; 10907955f03dSHans Verkuil board = &board_matrix_ii; 10917955f03dSHans Verkuil break; 10927955f03dSHans Verkuil case GO7007_BOARDID_PX_TV402U: 10937955f03dSHans Verkuil name = "Plextor PX-TV402U (unknown tuner)"; 10947955f03dSHans Verkuil board = &board_px_tv402u; 10957955f03dSHans Verkuil break; 10967955f03dSHans Verkuil case GO7007_BOARDID_LIFEVIEW_LR192: 10977955f03dSHans Verkuil dev_err(&intf->dev, "The Lifeview TV Walker Ultra is not supported. Sorry!\n"); 10987955f03dSHans Verkuil return -ENODEV; 10997955f03dSHans Verkuil name = "Lifeview TV Walker Ultra"; 11007955f03dSHans Verkuil board = &board_lifeview_lr192; 11017955f03dSHans Verkuil break; 11027955f03dSHans Verkuil case GO7007_BOARDID_SENSORAY_2250: 11037955f03dSHans Verkuil dev_info(&intf->dev, "Sensoray 2250 found\n"); 11047955f03dSHans Verkuil name = "Sensoray 2250/2251"; 11057955f03dSHans Verkuil board = &board_sensoray_2250; 11067955f03dSHans Verkuil break; 11077955f03dSHans Verkuil case GO7007_BOARDID_ADS_USBAV_709: 11087955f03dSHans Verkuil name = "ADS Tech DVD Xpress DX2"; 11097955f03dSHans Verkuil board = &board_ads_usbav_709; 11107955f03dSHans Verkuil break; 11117955f03dSHans Verkuil default: 11127955f03dSHans Verkuil dev_err(&intf->dev, "unknown board ID %d!\n", 11137955f03dSHans Verkuil (unsigned int)id->driver_info); 11147955f03dSHans Verkuil return -ENODEV; 11157955f03dSHans Verkuil } 11167955f03dSHans Verkuil 11177955f03dSHans Verkuil go = go7007_alloc(&board->main_info, &intf->dev); 11187955f03dSHans Verkuil if (go == NULL) 11197955f03dSHans Verkuil return -ENOMEM; 11207955f03dSHans Verkuil 11217955f03dSHans Verkuil usb = kzalloc(sizeof(struct go7007_usb), GFP_KERNEL); 11227955f03dSHans Verkuil if (usb == NULL) { 11237955f03dSHans Verkuil kfree(go); 11247955f03dSHans Verkuil return -ENOMEM; 11257955f03dSHans Verkuil } 11267955f03dSHans Verkuil 11277955f03dSHans Verkuil usb->board = board; 11287955f03dSHans Verkuil usb->usbdev = usbdev; 11297955f03dSHans Verkuil usb_make_path(usbdev, go->bus_info, sizeof(go->bus_info)); 11307955f03dSHans Verkuil go->board_id = id->driver_info; 11317955f03dSHans Verkuil strncpy(go->name, name, sizeof(go->name)); 11327955f03dSHans Verkuil if (board->flags & GO7007_USB_EZUSB) 11337955f03dSHans Verkuil go->hpi_ops = &go7007_usb_ezusb_hpi_ops; 11347955f03dSHans Verkuil else 11357955f03dSHans Verkuil go->hpi_ops = &go7007_usb_onboard_hpi_ops; 11367955f03dSHans Verkuil go->hpi_context = usb; 11377955f03dSHans Verkuil 11387955f03dSHans Verkuil /* Allocate the URB and buffer for receiving incoming interrupts */ 11397955f03dSHans Verkuil usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL); 11407955f03dSHans Verkuil if (usb->intr_urb == NULL) 11417955f03dSHans Verkuil goto allocfail; 11427955f03dSHans Verkuil usb->intr_urb->transfer_buffer = kmalloc(2*sizeof(u16), GFP_KERNEL); 11437955f03dSHans Verkuil if (usb->intr_urb->transfer_buffer == NULL) 11447955f03dSHans Verkuil goto allocfail; 11457955f03dSHans Verkuil 11467955f03dSHans Verkuil if (go->board_id == GO7007_BOARDID_SENSORAY_2250) 11477955f03dSHans Verkuil usb_fill_bulk_urb(usb->intr_urb, usb->usbdev, 11487955f03dSHans Verkuil usb_rcvbulkpipe(usb->usbdev, 4), 11497955f03dSHans Verkuil usb->intr_urb->transfer_buffer, 2*sizeof(u16), 11507955f03dSHans Verkuil go7007_usb_readinterrupt_complete, go); 11517955f03dSHans Verkuil else 11527955f03dSHans Verkuil usb_fill_int_urb(usb->intr_urb, usb->usbdev, 11537955f03dSHans Verkuil usb_rcvintpipe(usb->usbdev, 4), 11547955f03dSHans Verkuil usb->intr_urb->transfer_buffer, 2*sizeof(u16), 11557955f03dSHans Verkuil go7007_usb_readinterrupt_complete, go, 8); 11567955f03dSHans Verkuil usb_set_intfdata(intf, &go->v4l2_dev); 11577955f03dSHans Verkuil 11587955f03dSHans Verkuil /* Boot the GO7007 */ 11597955f03dSHans Verkuil if (go7007_boot_encoder(go, go->board_info->flags & 11607955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C) < 0) 11617955f03dSHans Verkuil goto allocfail; 11627955f03dSHans Verkuil 11637955f03dSHans Verkuil /* Register the EZ-USB I2C adapter, if we're using it */ 11647955f03dSHans Verkuil if (board->flags & GO7007_USB_EZUSB_I2C) { 11657955f03dSHans Verkuil memcpy(&go->i2c_adapter, &go7007_usb_adap_templ, 11667955f03dSHans Verkuil sizeof(go7007_usb_adap_templ)); 11677955f03dSHans Verkuil mutex_init(&usb->i2c_lock); 11687955f03dSHans Verkuil go->i2c_adapter.dev.parent = go->dev; 11697955f03dSHans Verkuil i2c_set_adapdata(&go->i2c_adapter, go); 11707955f03dSHans Verkuil if (i2c_add_adapter(&go->i2c_adapter) < 0) { 11717955f03dSHans Verkuil dev_err(go->dev, "error: i2c_add_adapter failed\n"); 11727955f03dSHans Verkuil goto allocfail; 11737955f03dSHans Verkuil } 11747955f03dSHans Verkuil go->i2c_adapter_online = 1; 11757955f03dSHans Verkuil } 11767955f03dSHans Verkuil 11777955f03dSHans Verkuil /* Pelco and Adlink reused the XMen and XMen-III vendor and product 11787955f03dSHans Verkuil * IDs for their own incompatible designs. We can detect XMen boards 11797955f03dSHans Verkuil * by probing the sensor, but there is no way to probe the sensors on 11807955f03dSHans Verkuil * the Pelco and Adlink designs so we default to the Adlink. If it 11817955f03dSHans Verkuil * is actually a Pelco, the user must set the assume_endura module 11827955f03dSHans Verkuil * parameter. */ 11837955f03dSHans Verkuil if ((go->board_id == GO7007_BOARDID_XMEN || 11847955f03dSHans Verkuil go->board_id == GO7007_BOARDID_XMEN_III) && 11857955f03dSHans Verkuil go->i2c_adapter_online) { 11867955f03dSHans Verkuil union i2c_smbus_data data; 11877955f03dSHans Verkuil 11887955f03dSHans Verkuil /* Check to see if register 0x0A is 0x76 */ 11897955f03dSHans Verkuil i2c_smbus_xfer(&go->i2c_adapter, 0x21, I2C_CLIENT_SCCB, 11907955f03dSHans Verkuil I2C_SMBUS_READ, 0x0A, I2C_SMBUS_BYTE_DATA, &data); 11917955f03dSHans Verkuil if (data.byte != 0x76) { 11927955f03dSHans Verkuil if (assume_endura) { 11937955f03dSHans Verkuil go->board_id = GO7007_BOARDID_ENDURA; 11947955f03dSHans Verkuil usb->board = board = &board_endura; 11957955f03dSHans Verkuil go->board_info = &board->main_info; 11967955f03dSHans Verkuil strncpy(go->name, "Pelco Endura", 11977955f03dSHans Verkuil sizeof(go->name)); 11987955f03dSHans Verkuil } else { 11997955f03dSHans Verkuil u16 channel; 12007955f03dSHans Verkuil 12017955f03dSHans Verkuil /* read channel number from GPIO[1:0] */ 12027955f03dSHans Verkuil go7007_read_addr(go, 0x3c81, &channel); 12037955f03dSHans Verkuil channel &= 0x3; 12047955f03dSHans Verkuil go->board_id = GO7007_BOARDID_ADLINK_MPG24; 12057955f03dSHans Verkuil usb->board = board = &board_adlink_mpg24; 12067955f03dSHans Verkuil go->board_info = &board->main_info; 12077955f03dSHans Verkuil go->channel_number = channel; 12087955f03dSHans Verkuil snprintf(go->name, sizeof(go->name), 12097955f03dSHans Verkuil "Adlink PCI-MPG24, channel #%d", 12107955f03dSHans Verkuil channel); 12117955f03dSHans Verkuil } 12127955f03dSHans Verkuil go7007_update_board(go); 12137955f03dSHans Verkuil } 12147955f03dSHans Verkuil } 12157955f03dSHans Verkuil 12167955f03dSHans Verkuil num_i2c_devs = go->board_info->num_i2c_devs; 12177955f03dSHans Verkuil 12187955f03dSHans Verkuil /* Probe the tuner model on the TV402U */ 12197955f03dSHans Verkuil if (go->board_id == GO7007_BOARDID_PX_TV402U) { 12207955f03dSHans Verkuil /* Board strapping indicates tuner model */ 12217955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3, 12227955f03dSHans Verkuil 1) < 0) { 12237955f03dSHans Verkuil dev_err(go->dev, "GPIO read failed!\n"); 12247955f03dSHans Verkuil goto allocfail; 12257955f03dSHans Verkuil } 12267955f03dSHans Verkuil switch (go->usb_buf[0] >> 6) { 12277955f03dSHans Verkuil case 1: 12287955f03dSHans Verkuil go->tuner_type = TUNER_SONY_BTF_PG472Z; 12297955f03dSHans Verkuil go->std = V4L2_STD_PAL; 12307955f03dSHans Verkuil strncpy(go->name, "Plextor PX-TV402U-EU", 12317955f03dSHans Verkuil sizeof(go->name)); 12327955f03dSHans Verkuil break; 12337955f03dSHans Verkuil case 2: 12347955f03dSHans Verkuil go->tuner_type = TUNER_SONY_BTF_PK467Z; 12357955f03dSHans Verkuil go->std = V4L2_STD_NTSC_M_JP; 12367955f03dSHans Verkuil num_i2c_devs -= 2; 12377955f03dSHans Verkuil strncpy(go->name, "Plextor PX-TV402U-JP", 12387955f03dSHans Verkuil sizeof(go->name)); 12397955f03dSHans Verkuil break; 12407955f03dSHans Verkuil case 3: 12417955f03dSHans Verkuil go->tuner_type = TUNER_SONY_BTF_PB463Z; 12427955f03dSHans Verkuil num_i2c_devs -= 2; 12437955f03dSHans Verkuil strncpy(go->name, "Plextor PX-TV402U-NA", 12447955f03dSHans Verkuil sizeof(go->name)); 12457955f03dSHans Verkuil break; 12467955f03dSHans Verkuil default: 12477955f03dSHans Verkuil pr_debug("unable to detect tuner type!\n"); 12487955f03dSHans Verkuil break; 12497955f03dSHans Verkuil } 12507955f03dSHans Verkuil /* Configure tuner mode selection inputs connected 12517955f03dSHans Verkuil * to the EZ-USB GPIO output pins */ 12527955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0, 12537955f03dSHans Verkuil NULL, 0, 0) < 0) { 12547955f03dSHans Verkuil dev_err(go->dev, "GPIO write failed!\n"); 12557955f03dSHans Verkuil goto allocfail; 12567955f03dSHans Verkuil } 12577955f03dSHans Verkuil } 12587955f03dSHans Verkuil 12597955f03dSHans Verkuil /* Print a nasty message if the user attempts to use a USB2.0 device in 12607955f03dSHans Verkuil * a USB1.1 port. There will be silent corruption of the stream. */ 12617955f03dSHans Verkuil if ((board->flags & GO7007_USB_EZUSB) && 12627955f03dSHans Verkuil usbdev->speed != USB_SPEED_HIGH) 12637955f03dSHans Verkuil dev_err(go->dev, "*** WARNING *** This device must be connected to a USB 2.0 port! Attempting to capture video through a USB 1.1 port will result in stream corruption, even at low bitrates!\n"); 12647955f03dSHans Verkuil 12657955f03dSHans Verkuil /* Allocate the URBs and buffers for receiving the video stream */ 12667955f03dSHans Verkuil if (board->flags & GO7007_USB_EZUSB) { 12677955f03dSHans Verkuil v_urb_len = 1024; 12687955f03dSHans Verkuil video_pipe = usb_rcvbulkpipe(usb->usbdev, 6); 12697955f03dSHans Verkuil } else { 12707955f03dSHans Verkuil v_urb_len = 512; 12717955f03dSHans Verkuil video_pipe = usb_rcvbulkpipe(usb->usbdev, 1); 12727955f03dSHans Verkuil } 12737955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 12747955f03dSHans Verkuil usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); 12757955f03dSHans Verkuil if (usb->video_urbs[i] == NULL) 12767955f03dSHans Verkuil goto allocfail; 12777955f03dSHans Verkuil usb->video_urbs[i]->transfer_buffer = 12787955f03dSHans Verkuil kmalloc(v_urb_len, GFP_KERNEL); 12797955f03dSHans Verkuil if (usb->video_urbs[i]->transfer_buffer == NULL) 12807955f03dSHans Verkuil goto allocfail; 12817955f03dSHans Verkuil usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe, 12827955f03dSHans Verkuil usb->video_urbs[i]->transfer_buffer, v_urb_len, 12837955f03dSHans Verkuil go7007_usb_read_video_pipe_complete, go); 12847955f03dSHans Verkuil } 12857955f03dSHans Verkuil 12867955f03dSHans Verkuil /* Allocate the URBs and buffers for receiving the audio stream */ 12877955f03dSHans Verkuil if ((board->flags & GO7007_USB_EZUSB) && 12887955f03dSHans Verkuil (board->flags & GO7007_BOARD_HAS_AUDIO)) { 12897955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 12907955f03dSHans Verkuil usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); 12917955f03dSHans Verkuil if (usb->audio_urbs[i] == NULL) 12927955f03dSHans Verkuil goto allocfail; 12937955f03dSHans Verkuil usb->audio_urbs[i]->transfer_buffer = kmalloc(4096, 12947955f03dSHans Verkuil GFP_KERNEL); 12957955f03dSHans Verkuil if (usb->audio_urbs[i]->transfer_buffer == NULL) 12967955f03dSHans Verkuil goto allocfail; 12977955f03dSHans Verkuil usb_fill_bulk_urb(usb->audio_urbs[i], usb->usbdev, 12987955f03dSHans Verkuil usb_rcvbulkpipe(usb->usbdev, 8), 12997955f03dSHans Verkuil usb->audio_urbs[i]->transfer_buffer, 4096, 13007955f03dSHans Verkuil go7007_usb_read_audio_pipe_complete, go); 13017955f03dSHans Verkuil } 13027955f03dSHans Verkuil } 13037955f03dSHans Verkuil 13047955f03dSHans Verkuil /* Do any final GO7007 initialization, then register the 13057955f03dSHans Verkuil * V4L2 and ALSA interfaces */ 13067955f03dSHans Verkuil if (go7007_register_encoder(go, num_i2c_devs) < 0) 13077955f03dSHans Verkuil goto allocfail; 13087955f03dSHans Verkuil 13097955f03dSHans Verkuil go->status = STATUS_ONLINE; 13107955f03dSHans Verkuil return 0; 13117955f03dSHans Verkuil 13127955f03dSHans Verkuil allocfail: 13137955f03dSHans Verkuil go7007_usb_release(go); 13147955f03dSHans Verkuil kfree(go); 13157955f03dSHans Verkuil return -ENOMEM; 13167955f03dSHans Verkuil } 13177955f03dSHans Verkuil 13187955f03dSHans Verkuil static void go7007_usb_disconnect(struct usb_interface *intf) 13197955f03dSHans Verkuil { 13207955f03dSHans Verkuil struct go7007 *go = to_go7007(usb_get_intfdata(intf)); 13217955f03dSHans Verkuil 13227955f03dSHans Verkuil mutex_lock(&go->queue_lock); 13237955f03dSHans Verkuil mutex_lock(&go->serialize_lock); 13247955f03dSHans Verkuil 13257955f03dSHans Verkuil if (go->audio_enabled) 13267955f03dSHans Verkuil go7007_snd_remove(go); 13277955f03dSHans Verkuil 13287955f03dSHans Verkuil go->status = STATUS_SHUTDOWN; 13297955f03dSHans Verkuil v4l2_device_disconnect(&go->v4l2_dev); 13307955f03dSHans Verkuil video_unregister_device(&go->vdev); 13317955f03dSHans Verkuil mutex_unlock(&go->serialize_lock); 13327955f03dSHans Verkuil mutex_unlock(&go->queue_lock); 13337955f03dSHans Verkuil 13347955f03dSHans Verkuil v4l2_device_put(&go->v4l2_dev); 13357955f03dSHans Verkuil } 13367955f03dSHans Verkuil 13377955f03dSHans Verkuil static struct usb_driver go7007_usb_driver = { 13387955f03dSHans Verkuil .name = "go7007", 13397955f03dSHans Verkuil .probe = go7007_usb_probe, 13407955f03dSHans Verkuil .disconnect = go7007_usb_disconnect, 13417955f03dSHans Verkuil .id_table = go7007_usb_id_table, 13427955f03dSHans Verkuil }; 13437955f03dSHans Verkuil 13447955f03dSHans Verkuil module_usb_driver(go7007_usb_driver); 13457955f03dSHans Verkuil MODULE_LICENSE("GPL v2"); 1346