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> 26*b5dcee22SMauro Carvalho Chehab #include <media/i2c/saa7115.h> 277955f03dSHans Verkuil #include <media/tuner.h> 28*b5dcee22SMauro Carvalho Chehab #include <media/i2c/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 3416629e4deSMauro Carvalho Chehab #if 0 3427955f03dSHans Verkuil static const struct go7007_usb_board board_lifeview_lr192 = { 3437955f03dSHans Verkuil .flags = GO7007_USB_EZUSB, 3447955f03dSHans Verkuil .main_info = { 3457955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO | 3467955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C, 3477955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 3487955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 3497955f03dSHans Verkuil .audio_rate = 48000, 3507955f03dSHans Verkuil .audio_bclk_div = 8, 3517955f03dSHans Verkuil .audio_main_div = 2, 3527955f03dSHans Verkuil .hpi_buffer_cap = 7, 3537955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 3547955f03dSHans Verkuil GO7007_SENSOR_VALID_ENABLE | 3557955f03dSHans Verkuil GO7007_SENSOR_TV | 3567955f03dSHans Verkuil GO7007_SENSOR_VBI | 3577955f03dSHans Verkuil GO7007_SENSOR_SCALING, 3587955f03dSHans Verkuil .num_i2c_devs = 0, 3597955f03dSHans Verkuil .num_inputs = 1, 3607955f03dSHans Verkuil .inputs = { 3617955f03dSHans Verkuil { 3627955f03dSHans Verkuil .video_input = 0, 3637955f03dSHans Verkuil .name = "Composite", 3647955f03dSHans Verkuil }, 3657955f03dSHans Verkuil }, 3667955f03dSHans Verkuil }, 3677955f03dSHans Verkuil }; 3686629e4deSMauro Carvalho Chehab #endif 3697955f03dSHans Verkuil 3707955f03dSHans Verkuil static const struct go7007_usb_board board_endura = { 3717955f03dSHans Verkuil .flags = 0, 3727955f03dSHans Verkuil .main_info = { 3737955f03dSHans Verkuil .flags = 0, 3747955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 3757955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 3767955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 3777955f03dSHans Verkuil .audio_rate = 8000, 3787955f03dSHans Verkuil .audio_bclk_div = 48, 3797955f03dSHans Verkuil .audio_main_div = 8, 3807955f03dSHans Verkuil .hpi_buffer_cap = 0, 3817955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 3827955f03dSHans Verkuil GO7007_SENSOR_TV, 3837955f03dSHans Verkuil .sensor_h_offset = 8, 3847955f03dSHans Verkuil .num_i2c_devs = 0, 3857955f03dSHans Verkuil .num_inputs = 1, 3867955f03dSHans Verkuil .inputs = { 3877955f03dSHans Verkuil { 3887955f03dSHans Verkuil .name = "Camera", 3897955f03dSHans Verkuil }, 3907955f03dSHans Verkuil }, 3917955f03dSHans Verkuil }, 3927955f03dSHans Verkuil }; 3937955f03dSHans Verkuil 3947955f03dSHans Verkuil static const struct go7007_usb_board board_adlink_mpg24 = { 3957955f03dSHans Verkuil .flags = 0, 3967955f03dSHans Verkuil .main_info = { 3977955f03dSHans Verkuil .flags = GO7007_BOARD_USE_ONBOARD_I2C, 3987955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 3997955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 4007955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 4017955f03dSHans Verkuil .audio_rate = 48000, 4027955f03dSHans Verkuil .audio_bclk_div = 8, 4037955f03dSHans Verkuil .audio_main_div = 2, 4047955f03dSHans Verkuil .hpi_buffer_cap = 0, 4057955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 4067955f03dSHans Verkuil GO7007_SENSOR_TV | 4077955f03dSHans Verkuil GO7007_SENSOR_VBI, 4087955f03dSHans Verkuil .num_i2c_devs = 1, 4097955f03dSHans Verkuil .i2c_devs = { 4107955f03dSHans Verkuil { 4117955f03dSHans Verkuil .type = "tw2804", 4127955f03dSHans Verkuil .addr = 0x00, /* yes, really */ 4137955f03dSHans Verkuil .flags = I2C_CLIENT_TEN, 4147955f03dSHans Verkuil .is_video = 1, 4157955f03dSHans Verkuil }, 4167955f03dSHans Verkuil }, 4177955f03dSHans Verkuil .num_inputs = 1, 4187955f03dSHans Verkuil .inputs = { 4197955f03dSHans Verkuil { 4207955f03dSHans Verkuil .name = "Composite", 4217955f03dSHans Verkuil }, 4227955f03dSHans Verkuil }, 4237955f03dSHans Verkuil }, 4247955f03dSHans Verkuil }; 4257955f03dSHans Verkuil 4267955f03dSHans Verkuil static const struct go7007_usb_board board_sensoray_2250 = { 4277955f03dSHans Verkuil .flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C, 4287955f03dSHans Verkuil .main_info = { 4297955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 4307955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 4317955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 4327955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO, 4337955f03dSHans Verkuil .audio_rate = 48000, 4347955f03dSHans Verkuil .audio_bclk_div = 8, 4357955f03dSHans Verkuil .audio_main_div = 2, 4367955f03dSHans Verkuil .hpi_buffer_cap = 7, 4377955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 4387955f03dSHans Verkuil GO7007_SENSOR_TV, 4397955f03dSHans Verkuil .num_i2c_devs = 1, 4407955f03dSHans Verkuil .i2c_devs = { 4417955f03dSHans Verkuil { 4427955f03dSHans Verkuil .type = "s2250", 4437955f03dSHans Verkuil .addr = 0x43, 4447955f03dSHans Verkuil .is_video = 1, 4457955f03dSHans Verkuil .is_audio = 1, 4467955f03dSHans Verkuil }, 4477955f03dSHans Verkuil }, 4487955f03dSHans Verkuil .num_inputs = 2, 4497955f03dSHans Verkuil .inputs = { 4507955f03dSHans Verkuil { 4517955f03dSHans Verkuil .video_input = 0, 4527955f03dSHans Verkuil .name = "Composite", 4537955f03dSHans Verkuil }, 4547955f03dSHans Verkuil { 4557955f03dSHans Verkuil .video_input = 1, 4567955f03dSHans Verkuil .name = "S-Video", 4577955f03dSHans Verkuil }, 4587955f03dSHans Verkuil }, 4597955f03dSHans Verkuil .num_aud_inputs = 3, 4607955f03dSHans Verkuil .aud_inputs = { 4617955f03dSHans Verkuil { 4627955f03dSHans Verkuil .audio_input = 0, 4637955f03dSHans Verkuil .name = "Line In", 4647955f03dSHans Verkuil }, 4657955f03dSHans Verkuil { 4667955f03dSHans Verkuil .audio_input = 1, 4677955f03dSHans Verkuil .name = "Mic", 4687955f03dSHans Verkuil }, 4697955f03dSHans Verkuil { 4707955f03dSHans Verkuil .audio_input = 2, 4717955f03dSHans Verkuil .name = "Mic Boost", 4727955f03dSHans Verkuil }, 4737955f03dSHans Verkuil }, 4747955f03dSHans Verkuil }, 4757955f03dSHans Verkuil }; 4767955f03dSHans Verkuil 4777955f03dSHans Verkuil static const struct go7007_usb_board board_ads_usbav_709 = { 4787955f03dSHans Verkuil .flags = GO7007_USB_EZUSB, 4797955f03dSHans Verkuil .main_info = { 4807955f03dSHans Verkuil .flags = GO7007_BOARD_HAS_AUDIO | 4817955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C, 4827955f03dSHans Verkuil .audio_flags = GO7007_AUDIO_I2S_MODE_1 | 4837955f03dSHans Verkuil GO7007_AUDIO_I2S_MASTER | 4847955f03dSHans Verkuil GO7007_AUDIO_WORD_16, 4857955f03dSHans Verkuil .audio_rate = 48000, 4867955f03dSHans Verkuil .audio_bclk_div = 8, 4877955f03dSHans Verkuil .audio_main_div = 2, 4887955f03dSHans Verkuil .hpi_buffer_cap = 7, 4897955f03dSHans Verkuil .sensor_flags = GO7007_SENSOR_656 | 4907955f03dSHans Verkuil GO7007_SENSOR_TV | 4917955f03dSHans Verkuil GO7007_SENSOR_VBI, 4927955f03dSHans Verkuil .num_i2c_devs = 1, 4937955f03dSHans Verkuil .i2c_devs = { 4947955f03dSHans Verkuil { 4957955f03dSHans Verkuil .type = "tw9906", 4967955f03dSHans Verkuil .is_video = 1, 4977955f03dSHans Verkuil .addr = 0x44, 4987955f03dSHans Verkuil }, 4997955f03dSHans Verkuil }, 5007955f03dSHans Verkuil .num_inputs = 2, 5017955f03dSHans Verkuil .inputs = { 5027955f03dSHans Verkuil { 5037955f03dSHans Verkuil .video_input = 0, 5047955f03dSHans Verkuil .name = "Composite", 5057955f03dSHans Verkuil }, 5067955f03dSHans Verkuil { 5077955f03dSHans Verkuil .video_input = 10, 5087955f03dSHans Verkuil .name = "S-Video", 5097955f03dSHans Verkuil }, 5107955f03dSHans Verkuil }, 5117955f03dSHans Verkuil }, 5127955f03dSHans Verkuil }; 5137955f03dSHans Verkuil 5147955f03dSHans Verkuil static const struct usb_device_id go7007_usb_id_table[] = { 5157955f03dSHans Verkuil { 5167955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | 5177955f03dSHans Verkuil USB_DEVICE_ID_MATCH_INT_INFO, 5187955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 5197955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 5207955f03dSHans Verkuil .bcdDevice_lo = 0x200, /* Revision number of XMen */ 5217955f03dSHans Verkuil .bcdDevice_hi = 0x200, 5227955f03dSHans Verkuil .bInterfaceClass = 255, 5237955f03dSHans Verkuil .bInterfaceSubClass = 0, 5247955f03dSHans Verkuil .bInterfaceProtocol = 255, 5257955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN, 5267955f03dSHans Verkuil }, 5277955f03dSHans Verkuil { 5287955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 5297955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 5307955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 5317955f03dSHans Verkuil .bcdDevice_lo = 0x202, /* Revision number of Matrix II */ 5327955f03dSHans Verkuil .bcdDevice_hi = 0x202, 5337955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_II, 5347955f03dSHans Verkuil }, 5357955f03dSHans Verkuil { 5367955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 5377955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 5387955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 5397955f03dSHans Verkuil .bcdDevice_lo = 0x204, /* Revision number of Matrix */ 5407955f03dSHans Verkuil .bcdDevice_hi = 0x204, /* Reloaded */ 5417955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_RELOAD, 5427955f03dSHans Verkuil }, 5437955f03dSHans Verkuil { 5447955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | 5457955f03dSHans Verkuil USB_DEVICE_ID_MATCH_INT_INFO, 5467955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 5477955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 5487955f03dSHans Verkuil .bcdDevice_lo = 0x205, /* Revision number of XMen-II */ 5497955f03dSHans Verkuil .bcdDevice_hi = 0x205, 5507955f03dSHans Verkuil .bInterfaceClass = 255, 5517955f03dSHans Verkuil .bInterfaceSubClass = 0, 5527955f03dSHans Verkuil .bInterfaceProtocol = 255, 5537955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN_II, 5547955f03dSHans Verkuil }, 5557955f03dSHans Verkuil { 5567955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 5577955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 5587955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 5597955f03dSHans Verkuil .bcdDevice_lo = 0x208, /* Revision number of Star Trek */ 5607955f03dSHans Verkuil .bcdDevice_hi = 0x208, 5617955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_STAR_TREK, 5627955f03dSHans Verkuil }, 5637955f03dSHans Verkuil { 5647955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION | 5657955f03dSHans Verkuil USB_DEVICE_ID_MATCH_INT_INFO, 5667955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 5677955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 5687955f03dSHans Verkuil .bcdDevice_lo = 0x209, /* Revision number of XMen-III */ 5697955f03dSHans Verkuil .bcdDevice_hi = 0x209, 5707955f03dSHans Verkuil .bInterfaceClass = 255, 5717955f03dSHans Verkuil .bInterfaceSubClass = 0, 5727955f03dSHans Verkuil .bInterfaceProtocol = 255, 5737955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_XMEN_III, 5747955f03dSHans Verkuil }, 5757955f03dSHans Verkuil { 5767955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 5777955f03dSHans Verkuil .idVendor = 0x0eb1, /* Vendor ID of WIS Technologies */ 5787955f03dSHans Verkuil .idProduct = 0x7007, /* Product ID of GO7007SB chip */ 5797955f03dSHans Verkuil .bcdDevice_lo = 0x210, /* Revision number of Matrix */ 5807955f03dSHans Verkuil .bcdDevice_hi = 0x210, /* Revolution */ 5817955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_MATRIX_REV, 5827955f03dSHans Verkuil }, 5837955f03dSHans Verkuil { 5847955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 5857955f03dSHans Verkuil .idVendor = 0x093b, /* Vendor ID of Plextor */ 5867955f03dSHans Verkuil .idProduct = 0xa102, /* Product ID of M402U */ 5877955f03dSHans Verkuil .bcdDevice_lo = 0x1, /* revision number of Blueberry */ 5887955f03dSHans Verkuil .bcdDevice_hi = 0x1, 5897955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_PX_M402U, 5907955f03dSHans Verkuil }, 5917955f03dSHans Verkuil { 5927955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 5937955f03dSHans Verkuil .idVendor = 0x093b, /* Vendor ID of Plextor */ 5947955f03dSHans Verkuil .idProduct = 0xa104, /* Product ID of TV402U */ 5957955f03dSHans Verkuil .bcdDevice_lo = 0x1, 5967955f03dSHans Verkuil .bcdDevice_hi = 0x1, 5977955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_PX_TV402U, 5987955f03dSHans Verkuil }, 5997955f03dSHans Verkuil { 6007955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 6017955f03dSHans Verkuil .idVendor = 0x10fd, /* Vendor ID of Anubis Electronics */ 6027955f03dSHans Verkuil .idProduct = 0xde00, /* Product ID of Lifeview LR192 */ 6037955f03dSHans Verkuil .bcdDevice_lo = 0x1, 6047955f03dSHans Verkuil .bcdDevice_hi = 0x1, 6057955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_LIFEVIEW_LR192, 6067955f03dSHans Verkuil }, 6077955f03dSHans Verkuil { 6087955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 6097955f03dSHans Verkuil .idVendor = 0x1943, /* Vendor ID Sensoray */ 6107955f03dSHans Verkuil .idProduct = 0x2250, /* Product ID of 2250/2251 */ 6117955f03dSHans Verkuil .bcdDevice_lo = 0x1, 6127955f03dSHans Verkuil .bcdDevice_hi = 0x1, 6137955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_SENSORAY_2250, 6147955f03dSHans Verkuil }, 6157955f03dSHans Verkuil { 6167955f03dSHans Verkuil .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION, 6177955f03dSHans Verkuil .idVendor = 0x06e1, /* Vendor ID of ADS Technologies */ 6187955f03dSHans Verkuil .idProduct = 0x0709, /* Product ID of DVD Xpress DX2 */ 6197955f03dSHans Verkuil .bcdDevice_lo = 0x204, 6207955f03dSHans Verkuil .bcdDevice_hi = 0x204, 6217955f03dSHans Verkuil .driver_info = (kernel_ulong_t)GO7007_BOARDID_ADS_USBAV_709, 6227955f03dSHans Verkuil }, 6237955f03dSHans Verkuil { } /* Terminating entry */ 6247955f03dSHans Verkuil }; 6257955f03dSHans Verkuil 6267955f03dSHans Verkuil MODULE_DEVICE_TABLE(usb, go7007_usb_id_table); 6277955f03dSHans Verkuil 6287955f03dSHans Verkuil /********************* Driver for EZ-USB HPI interface *********************/ 6297955f03dSHans Verkuil 6307955f03dSHans Verkuil static int go7007_usb_vendor_request(struct go7007 *go, int request, 6317955f03dSHans Verkuil int value, int index, void *transfer_buffer, int length, int in) 6327955f03dSHans Verkuil { 6337955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 6347955f03dSHans Verkuil int timeout = 5000; 6357955f03dSHans Verkuil 6367955f03dSHans Verkuil if (in) { 6377955f03dSHans Verkuil return usb_control_msg(usb->usbdev, 6387955f03dSHans Verkuil usb_rcvctrlpipe(usb->usbdev, 0), request, 6397955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 6407955f03dSHans Verkuil value, index, transfer_buffer, length, timeout); 6417955f03dSHans Verkuil } else { 6427955f03dSHans Verkuil return usb_control_msg(usb->usbdev, 6437955f03dSHans Verkuil usb_sndctrlpipe(usb->usbdev, 0), request, 6447955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_DEVICE, 6457955f03dSHans Verkuil value, index, transfer_buffer, length, timeout); 6467955f03dSHans Verkuil } 6477955f03dSHans Verkuil } 6487955f03dSHans Verkuil 6497955f03dSHans Verkuil static int go7007_usb_interface_reset(struct go7007 *go) 6507955f03dSHans Verkuil { 6517955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 6527955f03dSHans Verkuil u16 intr_val, intr_data; 6537955f03dSHans Verkuil 6547955f03dSHans Verkuil if (go->status == STATUS_SHUTDOWN) 6557955f03dSHans Verkuil return -1; 6567955f03dSHans Verkuil /* Reset encoder */ 6577955f03dSHans Verkuil if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0) 6587955f03dSHans Verkuil return -1; 6597955f03dSHans Verkuil msleep(100); 6607955f03dSHans Verkuil 6617955f03dSHans Verkuil if (usb->board->flags & GO7007_USB_EZUSB) { 6627955f03dSHans Verkuil /* Reset buffer in EZ-USB */ 6637955f03dSHans Verkuil pr_debug("resetting EZ-USB buffers\n"); 6647955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0 || 6657955f03dSHans Verkuil go7007_usb_vendor_request(go, 0x10, 0, 0, NULL, 0, 0) < 0) 6667955f03dSHans Verkuil return -1; 6677955f03dSHans Verkuil 6687955f03dSHans Verkuil /* Reset encoder again */ 6697955f03dSHans Verkuil if (go7007_write_interrupt(go, 0x0001, 0x0001) < 0) 6707955f03dSHans Verkuil return -1; 6717955f03dSHans Verkuil msleep(100); 6727955f03dSHans Verkuil } 6737955f03dSHans Verkuil 6747955f03dSHans Verkuil /* Wait for an interrupt to indicate successful hardware reset */ 6757955f03dSHans Verkuil if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || 6767955f03dSHans Verkuil (intr_val & ~0x1) != 0x55aa) { 6777955f03dSHans Verkuil dev_err(go->dev, "unable to reset the USB interface\n"); 6787955f03dSHans Verkuil return -1; 6797955f03dSHans Verkuil } 6807955f03dSHans Verkuil return 0; 6817955f03dSHans Verkuil } 6827955f03dSHans Verkuil 6837955f03dSHans Verkuil static int go7007_usb_ezusb_write_interrupt(struct go7007 *go, 6847955f03dSHans Verkuil int addr, int data) 6857955f03dSHans Verkuil { 6867955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 6877955f03dSHans Verkuil int i, r; 6887955f03dSHans Verkuil u16 status_reg = 0; 6897955f03dSHans Verkuil int timeout = 500; 6907955f03dSHans Verkuil 6917955f03dSHans Verkuil pr_debug("WriteInterrupt: %04x %04x\n", addr, data); 6927955f03dSHans Verkuil 6937955f03dSHans Verkuil for (i = 0; i < 100; ++i) { 6947955f03dSHans Verkuil r = usb_control_msg(usb->usbdev, 6957955f03dSHans Verkuil usb_rcvctrlpipe(usb->usbdev, 0), 0x14, 6967955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 6977955f03dSHans Verkuil 0, HPI_STATUS_ADDR, go->usb_buf, 6987955f03dSHans Verkuil sizeof(status_reg), timeout); 6997955f03dSHans Verkuil if (r < 0) 7007955f03dSHans Verkuil break; 701616e3506SHans Verkuil status_reg = le16_to_cpu(*((__le16 *)go->usb_buf)); 7027955f03dSHans Verkuil if (!(status_reg & 0x0010)) 7037955f03dSHans Verkuil break; 7047955f03dSHans Verkuil msleep(10); 7057955f03dSHans Verkuil } 7067955f03dSHans Verkuil if (r < 0) 7077955f03dSHans Verkuil goto write_int_error; 7087955f03dSHans Verkuil if (i == 100) { 7097955f03dSHans Verkuil dev_err(go->dev, "device is hung, status reg = 0x%04x\n", status_reg); 7107955f03dSHans Verkuil return -1; 7117955f03dSHans Verkuil } 7127955f03dSHans Verkuil r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), 0x12, 7137955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_DEVICE, data, 7147955f03dSHans Verkuil INT_PARAM_ADDR, NULL, 0, timeout); 7157955f03dSHans Verkuil if (r < 0) 7167955f03dSHans Verkuil goto write_int_error; 7177955f03dSHans Verkuil r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 0), 7187955f03dSHans Verkuil 0x12, USB_TYPE_VENDOR | USB_RECIP_DEVICE, addr, 7197955f03dSHans Verkuil INT_INDEX_ADDR, NULL, 0, timeout); 7207955f03dSHans Verkuil if (r < 0) 7217955f03dSHans Verkuil goto write_int_error; 7227955f03dSHans Verkuil return 0; 7237955f03dSHans Verkuil 7247955f03dSHans Verkuil write_int_error: 7257955f03dSHans Verkuil dev_err(go->dev, "error in WriteInterrupt: %d\n", r); 7267955f03dSHans Verkuil return r; 7277955f03dSHans Verkuil } 7287955f03dSHans Verkuil 7297955f03dSHans Verkuil static int go7007_usb_onboard_write_interrupt(struct go7007 *go, 7307955f03dSHans Verkuil int addr, int data) 7317955f03dSHans Verkuil { 7327955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 7337955f03dSHans Verkuil int r; 7347955f03dSHans Verkuil int timeout = 500; 7357955f03dSHans Verkuil 7367955f03dSHans Verkuil pr_debug("WriteInterrupt: %04x %04x\n", addr, data); 7377955f03dSHans Verkuil 7387955f03dSHans Verkuil go->usb_buf[0] = data & 0xff; 7397955f03dSHans Verkuil go->usb_buf[1] = data >> 8; 7407955f03dSHans Verkuil go->usb_buf[2] = addr & 0xff; 7417955f03dSHans Verkuil go->usb_buf[3] = addr >> 8; 7427955f03dSHans Verkuil go->usb_buf[4] = go->usb_buf[5] = go->usb_buf[6] = go->usb_buf[7] = 0; 7437955f03dSHans Verkuil r = usb_control_msg(usb->usbdev, usb_sndctrlpipe(usb->usbdev, 2), 0x00, 7447955f03dSHans Verkuil USB_TYPE_VENDOR | USB_RECIP_ENDPOINT, 0x55aa, 7457955f03dSHans Verkuil 0xf0f0, go->usb_buf, 8, timeout); 7467955f03dSHans Verkuil if (r < 0) { 7477955f03dSHans Verkuil dev_err(go->dev, "error in WriteInterrupt: %d\n", r); 7487955f03dSHans Verkuil return r; 7497955f03dSHans Verkuil } 7507955f03dSHans Verkuil return 0; 7517955f03dSHans Verkuil } 7527955f03dSHans Verkuil 7537955f03dSHans Verkuil static void go7007_usb_readinterrupt_complete(struct urb *urb) 7547955f03dSHans Verkuil { 7557955f03dSHans Verkuil struct go7007 *go = (struct go7007 *)urb->context; 756616e3506SHans Verkuil __le16 *regs = (__le16 *)urb->transfer_buffer; 7577955f03dSHans Verkuil int status = urb->status; 7587955f03dSHans Verkuil 7597955f03dSHans Verkuil if (status) { 7607955f03dSHans Verkuil if (status != -ESHUTDOWN && 7617955f03dSHans Verkuil go->status != STATUS_SHUTDOWN) { 7627955f03dSHans Verkuil dev_err(go->dev, "error in read interrupt: %d\n", urb->status); 7637955f03dSHans Verkuil } else { 7647955f03dSHans Verkuil wake_up(&go->interrupt_waitq); 7657955f03dSHans Verkuil return; 7667955f03dSHans Verkuil } 7677955f03dSHans Verkuil } else if (urb->actual_length != urb->transfer_buffer_length) { 7687955f03dSHans Verkuil dev_err(go->dev, "short read in interrupt pipe!\n"); 7697955f03dSHans Verkuil } else { 7707955f03dSHans Verkuil go->interrupt_available = 1; 7717955f03dSHans Verkuil go->interrupt_data = __le16_to_cpu(regs[0]); 7727955f03dSHans Verkuil go->interrupt_value = __le16_to_cpu(regs[1]); 7737955f03dSHans Verkuil pr_debug("ReadInterrupt: %04x %04x\n", 7747955f03dSHans Verkuil go->interrupt_value, go->interrupt_data); 7757955f03dSHans Verkuil } 7767955f03dSHans Verkuil 7777955f03dSHans Verkuil wake_up(&go->interrupt_waitq); 7787955f03dSHans Verkuil } 7797955f03dSHans Verkuil 7807955f03dSHans Verkuil static int go7007_usb_read_interrupt(struct go7007 *go) 7817955f03dSHans Verkuil { 7827955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 7837955f03dSHans Verkuil int r; 7847955f03dSHans Verkuil 7857955f03dSHans Verkuil r = usb_submit_urb(usb->intr_urb, GFP_KERNEL); 7867955f03dSHans Verkuil if (r < 0) { 7877955f03dSHans Verkuil dev_err(go->dev, "unable to submit interrupt urb: %d\n", r); 7887955f03dSHans Verkuil return r; 7897955f03dSHans Verkuil } 7907955f03dSHans Verkuil return 0; 7917955f03dSHans Verkuil } 7927955f03dSHans Verkuil 7937955f03dSHans Verkuil static void go7007_usb_read_video_pipe_complete(struct urb *urb) 7947955f03dSHans Verkuil { 7957955f03dSHans Verkuil struct go7007 *go = (struct go7007 *)urb->context; 7967955f03dSHans Verkuil int r, status = urb->status; 7977955f03dSHans Verkuil 7987955f03dSHans Verkuil if (!vb2_is_streaming(&go->vidq)) { 7997955f03dSHans Verkuil wake_up_interruptible(&go->frame_waitq); 8007955f03dSHans Verkuil return; 8017955f03dSHans Verkuil } 8027955f03dSHans Verkuil if (status) { 8037955f03dSHans Verkuil dev_err(go->dev, "error in video pipe: %d\n", status); 8047955f03dSHans Verkuil return; 8057955f03dSHans Verkuil } 8067955f03dSHans Verkuil if (urb->actual_length != urb->transfer_buffer_length) { 8077955f03dSHans Verkuil dev_err(go->dev, "short read in video pipe!\n"); 8087955f03dSHans Verkuil return; 8097955f03dSHans Verkuil } 8107955f03dSHans Verkuil go7007_parse_video_stream(go, urb->transfer_buffer, urb->actual_length); 8117955f03dSHans Verkuil r = usb_submit_urb(urb, GFP_ATOMIC); 8127955f03dSHans Verkuil if (r < 0) 8137955f03dSHans Verkuil dev_err(go->dev, "error in video pipe: %d\n", r); 8147955f03dSHans Verkuil } 8157955f03dSHans Verkuil 8167955f03dSHans Verkuil static void go7007_usb_read_audio_pipe_complete(struct urb *urb) 8177955f03dSHans Verkuil { 8187955f03dSHans Verkuil struct go7007 *go = (struct go7007 *)urb->context; 8197955f03dSHans Verkuil int r, status = urb->status; 8207955f03dSHans Verkuil 8217955f03dSHans Verkuil if (!vb2_is_streaming(&go->vidq)) 8227955f03dSHans Verkuil return; 8237955f03dSHans Verkuil if (status) { 8247955f03dSHans Verkuil dev_err(go->dev, "error in audio pipe: %d\n", 8257955f03dSHans Verkuil status); 8267955f03dSHans Verkuil return; 8277955f03dSHans Verkuil } 8287955f03dSHans Verkuil if (urb->actual_length != urb->transfer_buffer_length) { 8297955f03dSHans Verkuil dev_err(go->dev, "short read in audio pipe!\n"); 8307955f03dSHans Verkuil return; 8317955f03dSHans Verkuil } 8327955f03dSHans Verkuil if (go->audio_deliver != NULL) 8337955f03dSHans Verkuil go->audio_deliver(go, urb->transfer_buffer, urb->actual_length); 8347955f03dSHans Verkuil r = usb_submit_urb(urb, GFP_ATOMIC); 8357955f03dSHans Verkuil if (r < 0) 8367955f03dSHans Verkuil dev_err(go->dev, "error in audio pipe: %d\n", r); 8377955f03dSHans Verkuil } 8387955f03dSHans Verkuil 8397955f03dSHans Verkuil static int go7007_usb_stream_start(struct go7007 *go) 8407955f03dSHans Verkuil { 8417955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 8427955f03dSHans Verkuil int i, r; 8437955f03dSHans Verkuil 8447955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 8457955f03dSHans Verkuil r = usb_submit_urb(usb->video_urbs[i], GFP_KERNEL); 8467955f03dSHans Verkuil if (r < 0) { 8477955f03dSHans Verkuil dev_err(go->dev, "error submitting video urb %d: %d\n", i, r); 8487955f03dSHans Verkuil goto video_submit_failed; 8497955f03dSHans Verkuil } 8507955f03dSHans Verkuil } 8517955f03dSHans Verkuil if (!go->audio_enabled) 8527955f03dSHans Verkuil return 0; 8537955f03dSHans Verkuil 8547955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 8557955f03dSHans Verkuil r = usb_submit_urb(usb->audio_urbs[i], GFP_KERNEL); 8567955f03dSHans Verkuil if (r < 0) { 8577955f03dSHans Verkuil dev_err(go->dev, "error submitting audio urb %d: %d\n", i, r); 8587955f03dSHans Verkuil goto audio_submit_failed; 8597955f03dSHans Verkuil } 8607955f03dSHans Verkuil } 8617955f03dSHans Verkuil return 0; 8627955f03dSHans Verkuil 8637955f03dSHans Verkuil audio_submit_failed: 8647955f03dSHans Verkuil for (i = 0; i < 7; ++i) 8657955f03dSHans Verkuil usb_kill_urb(usb->audio_urbs[i]); 8667955f03dSHans Verkuil video_submit_failed: 8677955f03dSHans Verkuil for (i = 0; i < 8; ++i) 8687955f03dSHans Verkuil usb_kill_urb(usb->video_urbs[i]); 8697955f03dSHans Verkuil return -1; 8707955f03dSHans Verkuil } 8717955f03dSHans Verkuil 8727955f03dSHans Verkuil static int go7007_usb_stream_stop(struct go7007 *go) 8737955f03dSHans Verkuil { 8747955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 8757955f03dSHans Verkuil int i; 8767955f03dSHans Verkuil 8777955f03dSHans Verkuil if (go->status == STATUS_SHUTDOWN) 8787955f03dSHans Verkuil return 0; 8797955f03dSHans Verkuil for (i = 0; i < 8; ++i) 8807955f03dSHans Verkuil usb_kill_urb(usb->video_urbs[i]); 8817955f03dSHans Verkuil if (go->audio_enabled) 8827955f03dSHans Verkuil for (i = 0; i < 8; ++i) 8837955f03dSHans Verkuil usb_kill_urb(usb->audio_urbs[i]); 8847955f03dSHans Verkuil return 0; 8857955f03dSHans Verkuil } 8867955f03dSHans Verkuil 8877955f03dSHans Verkuil static int go7007_usb_send_firmware(struct go7007 *go, u8 *data, int len) 8887955f03dSHans Verkuil { 8897955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 8907955f03dSHans Verkuil int transferred, pipe; 8917955f03dSHans Verkuil int timeout = 500; 8927955f03dSHans Verkuil 8937955f03dSHans Verkuil pr_debug("DownloadBuffer sending %d bytes\n", len); 8947955f03dSHans Verkuil 8957955f03dSHans Verkuil if (usb->board->flags & GO7007_USB_EZUSB) 8967955f03dSHans Verkuil pipe = usb_sndbulkpipe(usb->usbdev, 2); 8977955f03dSHans Verkuil else 8987955f03dSHans Verkuil pipe = usb_sndbulkpipe(usb->usbdev, 3); 8997955f03dSHans Verkuil 9007955f03dSHans Verkuil return usb_bulk_msg(usb->usbdev, pipe, data, len, 9017955f03dSHans Verkuil &transferred, timeout); 9027955f03dSHans Verkuil } 9037955f03dSHans Verkuil 9047955f03dSHans Verkuil static void go7007_usb_release(struct go7007 *go) 9057955f03dSHans Verkuil { 9067955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 9077955f03dSHans Verkuil struct urb *vurb, *aurb; 9087955f03dSHans Verkuil int i; 9097955f03dSHans Verkuil 9107955f03dSHans Verkuil if (usb->intr_urb) { 9117955f03dSHans Verkuil usb_kill_urb(usb->intr_urb); 9127955f03dSHans Verkuil kfree(usb->intr_urb->transfer_buffer); 9137955f03dSHans Verkuil usb_free_urb(usb->intr_urb); 9147955f03dSHans Verkuil } 9157955f03dSHans Verkuil 9167955f03dSHans Verkuil /* Free USB-related structs */ 9177955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 9187955f03dSHans Verkuil vurb = usb->video_urbs[i]; 9197955f03dSHans Verkuil if (vurb) { 9207955f03dSHans Verkuil usb_kill_urb(vurb); 9217955f03dSHans Verkuil kfree(vurb->transfer_buffer); 9227955f03dSHans Verkuil usb_free_urb(vurb); 9237955f03dSHans Verkuil } 9247955f03dSHans Verkuil aurb = usb->audio_urbs[i]; 9257955f03dSHans Verkuil if (aurb) { 9267955f03dSHans Verkuil usb_kill_urb(aurb); 9277955f03dSHans Verkuil kfree(aurb->transfer_buffer); 9287955f03dSHans Verkuil usb_free_urb(aurb); 9297955f03dSHans Verkuil } 9307955f03dSHans Verkuil } 9317955f03dSHans Verkuil 9327955f03dSHans Verkuil kfree(go->hpi_context); 9337955f03dSHans Verkuil } 9347955f03dSHans Verkuil 9357955f03dSHans Verkuil static struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = { 9367955f03dSHans Verkuil .interface_reset = go7007_usb_interface_reset, 9377955f03dSHans Verkuil .write_interrupt = go7007_usb_ezusb_write_interrupt, 9387955f03dSHans Verkuil .read_interrupt = go7007_usb_read_interrupt, 9397955f03dSHans Verkuil .stream_start = go7007_usb_stream_start, 9407955f03dSHans Verkuil .stream_stop = go7007_usb_stream_stop, 9417955f03dSHans Verkuil .send_firmware = go7007_usb_send_firmware, 9427955f03dSHans Verkuil .release = go7007_usb_release, 9437955f03dSHans Verkuil }; 9447955f03dSHans Verkuil 9457955f03dSHans Verkuil static struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = { 9467955f03dSHans Verkuil .interface_reset = go7007_usb_interface_reset, 9477955f03dSHans Verkuil .write_interrupt = go7007_usb_onboard_write_interrupt, 9487955f03dSHans Verkuil .read_interrupt = go7007_usb_read_interrupt, 9497955f03dSHans Verkuil .stream_start = go7007_usb_stream_start, 9507955f03dSHans Verkuil .stream_stop = go7007_usb_stream_stop, 9517955f03dSHans Verkuil .send_firmware = go7007_usb_send_firmware, 9527955f03dSHans Verkuil .release = go7007_usb_release, 9537955f03dSHans Verkuil }; 9547955f03dSHans Verkuil 9557955f03dSHans Verkuil /********************* Driver for EZ-USB I2C adapter *********************/ 9567955f03dSHans Verkuil 9577955f03dSHans Verkuil static int go7007_usb_i2c_master_xfer(struct i2c_adapter *adapter, 9587955f03dSHans Verkuil struct i2c_msg msgs[], int num) 9597955f03dSHans Verkuil { 9607955f03dSHans Verkuil struct go7007 *go = i2c_get_adapdata(adapter); 9617955f03dSHans Verkuil struct go7007_usb *usb = go->hpi_context; 9627955f03dSHans Verkuil u8 *buf = go->usb_buf; 9637955f03dSHans Verkuil int buf_len, i; 9647955f03dSHans Verkuil int ret = -EIO; 9657955f03dSHans Verkuil 9667955f03dSHans Verkuil if (go->status == STATUS_SHUTDOWN) 9677955f03dSHans Verkuil return -ENODEV; 9687955f03dSHans Verkuil 9697955f03dSHans Verkuil mutex_lock(&usb->i2c_lock); 9707955f03dSHans Verkuil 9717955f03dSHans Verkuil for (i = 0; i < num; ++i) { 9727955f03dSHans Verkuil /* The hardware command is "write some bytes then read some 9737955f03dSHans Verkuil * bytes", so we try to coalesce a write followed by a read 9747955f03dSHans Verkuil * into a single USB transaction */ 9757955f03dSHans Verkuil if (i + 1 < num && msgs[i].addr == msgs[i + 1].addr && 9767955f03dSHans Verkuil !(msgs[i].flags & I2C_M_RD) && 9777955f03dSHans Verkuil (msgs[i + 1].flags & I2C_M_RD)) { 9787955f03dSHans Verkuil #ifdef GO7007_I2C_DEBUG 9797955f03dSHans Verkuil pr_debug("i2c write/read %d/%d bytes on %02x\n", 9807955f03dSHans Verkuil msgs[i].len, msgs[i + 1].len, msgs[i].addr); 9817955f03dSHans Verkuil #endif 9827955f03dSHans Verkuil buf[0] = 0x01; 9837955f03dSHans Verkuil buf[1] = msgs[i].len + 1; 9847955f03dSHans Verkuil buf[2] = msgs[i].addr << 1; 9857955f03dSHans Verkuil memcpy(&buf[3], msgs[i].buf, msgs[i].len); 9867955f03dSHans Verkuil buf_len = msgs[i].len + 3; 9877955f03dSHans Verkuil buf[buf_len++] = msgs[++i].len; 9887955f03dSHans Verkuil } else if (msgs[i].flags & I2C_M_RD) { 9897955f03dSHans Verkuil #ifdef GO7007_I2C_DEBUG 9907955f03dSHans Verkuil pr_debug("i2c read %d bytes on %02x\n", 9917955f03dSHans Verkuil msgs[i].len, msgs[i].addr); 9927955f03dSHans Verkuil #endif 9937955f03dSHans Verkuil buf[0] = 0x01; 9947955f03dSHans Verkuil buf[1] = 1; 9957955f03dSHans Verkuil buf[2] = msgs[i].addr << 1; 9967955f03dSHans Verkuil buf[3] = msgs[i].len; 9977955f03dSHans Verkuil buf_len = 4; 9987955f03dSHans Verkuil } else { 9997955f03dSHans Verkuil #ifdef GO7007_I2C_DEBUG 10007955f03dSHans Verkuil pr_debug("i2c write %d bytes on %02x\n", 10017955f03dSHans Verkuil msgs[i].len, msgs[i].addr); 10027955f03dSHans Verkuil #endif 10037955f03dSHans Verkuil buf[0] = 0x00; 10047955f03dSHans Verkuil buf[1] = msgs[i].len + 1; 10057955f03dSHans Verkuil buf[2] = msgs[i].addr << 1; 10067955f03dSHans Verkuil memcpy(&buf[3], msgs[i].buf, msgs[i].len); 10077955f03dSHans Verkuil buf_len = msgs[i].len + 3; 10087955f03dSHans Verkuil buf[buf_len++] = 0; 10097955f03dSHans Verkuil } 10107955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x24, 0, 0, 10117955f03dSHans Verkuil buf, buf_len, 0) < 0) 10127955f03dSHans Verkuil goto i2c_done; 10137955f03dSHans Verkuil if (msgs[i].flags & I2C_M_RD) { 10147955f03dSHans Verkuil memset(buf, 0, msgs[i].len + 1); 10157955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x25, 0, 0, buf, 10167955f03dSHans Verkuil msgs[i].len + 1, 1) < 0) 10177955f03dSHans Verkuil goto i2c_done; 10187955f03dSHans Verkuil memcpy(msgs[i].buf, buf + 1, msgs[i].len); 10197955f03dSHans Verkuil } 10207955f03dSHans Verkuil } 10217955f03dSHans Verkuil ret = num; 10227955f03dSHans Verkuil 10237955f03dSHans Verkuil i2c_done: 10247955f03dSHans Verkuil mutex_unlock(&usb->i2c_lock); 10257955f03dSHans Verkuil return ret; 10267955f03dSHans Verkuil } 10277955f03dSHans Verkuil 10287955f03dSHans Verkuil static u32 go7007_usb_functionality(struct i2c_adapter *adapter) 10297955f03dSHans Verkuil { 10307955f03dSHans Verkuil /* No errors are reported by the hardware, so we don't bother 10317955f03dSHans Verkuil * supporting quick writes to avoid confusing probing */ 10327955f03dSHans Verkuil return (I2C_FUNC_SMBUS_EMUL) & ~I2C_FUNC_SMBUS_QUICK; 10337955f03dSHans Verkuil } 10347955f03dSHans Verkuil 10357955f03dSHans Verkuil static struct i2c_algorithm go7007_usb_algo = { 10367955f03dSHans Verkuil .master_xfer = go7007_usb_i2c_master_xfer, 10377955f03dSHans Verkuil .functionality = go7007_usb_functionality, 10387955f03dSHans Verkuil }; 10397955f03dSHans Verkuil 10407955f03dSHans Verkuil static struct i2c_adapter go7007_usb_adap_templ = { 10417955f03dSHans Verkuil .owner = THIS_MODULE, 10427955f03dSHans Verkuil .name = "WIS GO7007SB EZ-USB", 10437955f03dSHans Verkuil .algo = &go7007_usb_algo, 10447955f03dSHans Verkuil }; 10457955f03dSHans Verkuil 10467955f03dSHans Verkuil /********************* USB add/remove functions *********************/ 10477955f03dSHans Verkuil 10487955f03dSHans Verkuil static int go7007_usb_probe(struct usb_interface *intf, 10497955f03dSHans Verkuil const struct usb_device_id *id) 10507955f03dSHans Verkuil { 10517955f03dSHans Verkuil struct go7007 *go; 10527955f03dSHans Verkuil struct go7007_usb *usb; 10537955f03dSHans Verkuil const struct go7007_usb_board *board; 10547955f03dSHans Verkuil struct usb_device *usbdev = interface_to_usbdev(intf); 10557955f03dSHans Verkuil unsigned num_i2c_devs; 10567955f03dSHans Verkuil char *name; 10577955f03dSHans Verkuil int video_pipe, i, v_urb_len; 10587955f03dSHans Verkuil 10597955f03dSHans Verkuil pr_debug("probing new GO7007 USB board\n"); 10607955f03dSHans Verkuil 10617955f03dSHans Verkuil switch (id->driver_info) { 10627955f03dSHans Verkuil case GO7007_BOARDID_MATRIX_II: 10637955f03dSHans Verkuil name = "WIS Matrix II or compatible"; 10647955f03dSHans Verkuil board = &board_matrix_ii; 10657955f03dSHans Verkuil break; 10667955f03dSHans Verkuil case GO7007_BOARDID_MATRIX_RELOAD: 10677955f03dSHans Verkuil name = "WIS Matrix Reloaded or compatible"; 10687955f03dSHans Verkuil board = &board_matrix_reload; 10697955f03dSHans Verkuil break; 10707955f03dSHans Verkuil case GO7007_BOARDID_MATRIX_REV: 10717955f03dSHans Verkuil name = "WIS Matrix Revolution or compatible"; 10727955f03dSHans Verkuil board = &board_matrix_revolution; 10737955f03dSHans Verkuil break; 10747955f03dSHans Verkuil case GO7007_BOARDID_STAR_TREK: 10757955f03dSHans Verkuil name = "WIS Star Trek or compatible"; 10767955f03dSHans Verkuil board = &board_star_trek; 10777955f03dSHans Verkuil break; 10787955f03dSHans Verkuil case GO7007_BOARDID_XMEN: 10797955f03dSHans Verkuil name = "WIS XMen or compatible"; 10807955f03dSHans Verkuil board = &board_xmen; 10817955f03dSHans Verkuil break; 10827955f03dSHans Verkuil case GO7007_BOARDID_XMEN_II: 10837955f03dSHans Verkuil name = "WIS XMen II or compatible"; 10847955f03dSHans Verkuil board = &board_xmen; 10857955f03dSHans Verkuil break; 10867955f03dSHans Verkuil case GO7007_BOARDID_XMEN_III: 10877955f03dSHans Verkuil name = "WIS XMen III or compatible"; 10887955f03dSHans Verkuil board = &board_xmen; 10897955f03dSHans Verkuil break; 10907955f03dSHans Verkuil case GO7007_BOARDID_PX_M402U: 10917955f03dSHans Verkuil name = "Plextor PX-M402U"; 10927955f03dSHans Verkuil board = &board_matrix_ii; 10937955f03dSHans Verkuil break; 10947955f03dSHans Verkuil case GO7007_BOARDID_PX_TV402U: 10957955f03dSHans Verkuil name = "Plextor PX-TV402U (unknown tuner)"; 10967955f03dSHans Verkuil board = &board_px_tv402u; 10977955f03dSHans Verkuil break; 10987955f03dSHans Verkuil case GO7007_BOARDID_LIFEVIEW_LR192: 10997955f03dSHans Verkuil dev_err(&intf->dev, "The Lifeview TV Walker Ultra is not supported. Sorry!\n"); 11007955f03dSHans Verkuil return -ENODEV; 11016629e4deSMauro Carvalho Chehab #if 0 11027955f03dSHans Verkuil name = "Lifeview TV Walker Ultra"; 11037955f03dSHans Verkuil board = &board_lifeview_lr192; 11046629e4deSMauro Carvalho Chehab #endif 11057955f03dSHans Verkuil break; 11067955f03dSHans Verkuil case GO7007_BOARDID_SENSORAY_2250: 11077955f03dSHans Verkuil dev_info(&intf->dev, "Sensoray 2250 found\n"); 11087955f03dSHans Verkuil name = "Sensoray 2250/2251"; 11097955f03dSHans Verkuil board = &board_sensoray_2250; 11107955f03dSHans Verkuil break; 11117955f03dSHans Verkuil case GO7007_BOARDID_ADS_USBAV_709: 11127955f03dSHans Verkuil name = "ADS Tech DVD Xpress DX2"; 11137955f03dSHans Verkuil board = &board_ads_usbav_709; 11147955f03dSHans Verkuil break; 11157955f03dSHans Verkuil default: 11167955f03dSHans Verkuil dev_err(&intf->dev, "unknown board ID %d!\n", 11177955f03dSHans Verkuil (unsigned int)id->driver_info); 11187955f03dSHans Verkuil return -ENODEV; 11197955f03dSHans Verkuil } 11207955f03dSHans Verkuil 11217955f03dSHans Verkuil go = go7007_alloc(&board->main_info, &intf->dev); 11227955f03dSHans Verkuil if (go == NULL) 11237955f03dSHans Verkuil return -ENOMEM; 11247955f03dSHans Verkuil 11257955f03dSHans Verkuil usb = kzalloc(sizeof(struct go7007_usb), GFP_KERNEL); 11267955f03dSHans Verkuil if (usb == NULL) { 11277955f03dSHans Verkuil kfree(go); 11287955f03dSHans Verkuil return -ENOMEM; 11297955f03dSHans Verkuil } 11307955f03dSHans Verkuil 11317955f03dSHans Verkuil usb->board = board; 11327955f03dSHans Verkuil usb->usbdev = usbdev; 11337955f03dSHans Verkuil usb_make_path(usbdev, go->bus_info, sizeof(go->bus_info)); 11347955f03dSHans Verkuil go->board_id = id->driver_info; 11357955f03dSHans Verkuil strncpy(go->name, name, sizeof(go->name)); 11367955f03dSHans Verkuil if (board->flags & GO7007_USB_EZUSB) 11377955f03dSHans Verkuil go->hpi_ops = &go7007_usb_ezusb_hpi_ops; 11387955f03dSHans Verkuil else 11397955f03dSHans Verkuil go->hpi_ops = &go7007_usb_onboard_hpi_ops; 11407955f03dSHans Verkuil go->hpi_context = usb; 11417955f03dSHans Verkuil 11427955f03dSHans Verkuil /* Allocate the URB and buffer for receiving incoming interrupts */ 11437955f03dSHans Verkuil usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL); 11447955f03dSHans Verkuil if (usb->intr_urb == NULL) 11457955f03dSHans Verkuil goto allocfail; 11467955f03dSHans Verkuil usb->intr_urb->transfer_buffer = kmalloc(2*sizeof(u16), GFP_KERNEL); 11477955f03dSHans Verkuil if (usb->intr_urb->transfer_buffer == NULL) 11487955f03dSHans Verkuil goto allocfail; 11497955f03dSHans Verkuil 11507955f03dSHans Verkuil if (go->board_id == GO7007_BOARDID_SENSORAY_2250) 11517955f03dSHans Verkuil usb_fill_bulk_urb(usb->intr_urb, usb->usbdev, 11527955f03dSHans Verkuil usb_rcvbulkpipe(usb->usbdev, 4), 11537955f03dSHans Verkuil usb->intr_urb->transfer_buffer, 2*sizeof(u16), 11547955f03dSHans Verkuil go7007_usb_readinterrupt_complete, go); 11557955f03dSHans Verkuil else 11567955f03dSHans Verkuil usb_fill_int_urb(usb->intr_urb, usb->usbdev, 11577955f03dSHans Verkuil usb_rcvintpipe(usb->usbdev, 4), 11587955f03dSHans Verkuil usb->intr_urb->transfer_buffer, 2*sizeof(u16), 11597955f03dSHans Verkuil go7007_usb_readinterrupt_complete, go, 8); 11607955f03dSHans Verkuil usb_set_intfdata(intf, &go->v4l2_dev); 11617955f03dSHans Verkuil 11627955f03dSHans Verkuil /* Boot the GO7007 */ 11637955f03dSHans Verkuil if (go7007_boot_encoder(go, go->board_info->flags & 11647955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C) < 0) 11657955f03dSHans Verkuil goto allocfail; 11667955f03dSHans Verkuil 11677955f03dSHans Verkuil /* Register the EZ-USB I2C adapter, if we're using it */ 11687955f03dSHans Verkuil if (board->flags & GO7007_USB_EZUSB_I2C) { 11697955f03dSHans Verkuil memcpy(&go->i2c_adapter, &go7007_usb_adap_templ, 11707955f03dSHans Verkuil sizeof(go7007_usb_adap_templ)); 11717955f03dSHans Verkuil mutex_init(&usb->i2c_lock); 11727955f03dSHans Verkuil go->i2c_adapter.dev.parent = go->dev; 11737955f03dSHans Verkuil i2c_set_adapdata(&go->i2c_adapter, go); 11747955f03dSHans Verkuil if (i2c_add_adapter(&go->i2c_adapter) < 0) { 11757955f03dSHans Verkuil dev_err(go->dev, "error: i2c_add_adapter failed\n"); 11767955f03dSHans Verkuil goto allocfail; 11777955f03dSHans Verkuil } 11787955f03dSHans Verkuil go->i2c_adapter_online = 1; 11797955f03dSHans Verkuil } 11807955f03dSHans Verkuil 11817955f03dSHans Verkuil /* Pelco and Adlink reused the XMen and XMen-III vendor and product 11827955f03dSHans Verkuil * IDs for their own incompatible designs. We can detect XMen boards 11837955f03dSHans Verkuil * by probing the sensor, but there is no way to probe the sensors on 11847955f03dSHans Verkuil * the Pelco and Adlink designs so we default to the Adlink. If it 11857955f03dSHans Verkuil * is actually a Pelco, the user must set the assume_endura module 11867955f03dSHans Verkuil * parameter. */ 11877955f03dSHans Verkuil if ((go->board_id == GO7007_BOARDID_XMEN || 11887955f03dSHans Verkuil go->board_id == GO7007_BOARDID_XMEN_III) && 11897955f03dSHans Verkuil go->i2c_adapter_online) { 11907955f03dSHans Verkuil union i2c_smbus_data data; 11917955f03dSHans Verkuil 11927955f03dSHans Verkuil /* Check to see if register 0x0A is 0x76 */ 11937955f03dSHans Verkuil i2c_smbus_xfer(&go->i2c_adapter, 0x21, I2C_CLIENT_SCCB, 11947955f03dSHans Verkuil I2C_SMBUS_READ, 0x0A, I2C_SMBUS_BYTE_DATA, &data); 11957955f03dSHans Verkuil if (data.byte != 0x76) { 11967955f03dSHans Verkuil if (assume_endura) { 11977955f03dSHans Verkuil go->board_id = GO7007_BOARDID_ENDURA; 11987955f03dSHans Verkuil usb->board = board = &board_endura; 11997955f03dSHans Verkuil go->board_info = &board->main_info; 12007955f03dSHans Verkuil strncpy(go->name, "Pelco Endura", 12017955f03dSHans Verkuil sizeof(go->name)); 12027955f03dSHans Verkuil } else { 12037955f03dSHans Verkuil u16 channel; 12047955f03dSHans Verkuil 12057955f03dSHans Verkuil /* read channel number from GPIO[1:0] */ 12067955f03dSHans Verkuil go7007_read_addr(go, 0x3c81, &channel); 12077955f03dSHans Verkuil channel &= 0x3; 12087955f03dSHans Verkuil go->board_id = GO7007_BOARDID_ADLINK_MPG24; 12097955f03dSHans Verkuil usb->board = board = &board_adlink_mpg24; 12107955f03dSHans Verkuil go->board_info = &board->main_info; 12117955f03dSHans Verkuil go->channel_number = channel; 12127955f03dSHans Verkuil snprintf(go->name, sizeof(go->name), 12137955f03dSHans Verkuil "Adlink PCI-MPG24, channel #%d", 12147955f03dSHans Verkuil channel); 12157955f03dSHans Verkuil } 12167955f03dSHans Verkuil go7007_update_board(go); 12177955f03dSHans Verkuil } 12187955f03dSHans Verkuil } 12197955f03dSHans Verkuil 12207955f03dSHans Verkuil num_i2c_devs = go->board_info->num_i2c_devs; 12217955f03dSHans Verkuil 12227955f03dSHans Verkuil /* Probe the tuner model on the TV402U */ 12237955f03dSHans Verkuil if (go->board_id == GO7007_BOARDID_PX_TV402U) { 12247955f03dSHans Verkuil /* Board strapping indicates tuner model */ 12257955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x41, 0, 0, go->usb_buf, 3, 12267955f03dSHans Verkuil 1) < 0) { 12277955f03dSHans Verkuil dev_err(go->dev, "GPIO read failed!\n"); 12287955f03dSHans Verkuil goto allocfail; 12297955f03dSHans Verkuil } 12307955f03dSHans Verkuil switch (go->usb_buf[0] >> 6) { 12317955f03dSHans Verkuil case 1: 12327955f03dSHans Verkuil go->tuner_type = TUNER_SONY_BTF_PG472Z; 12337955f03dSHans Verkuil go->std = V4L2_STD_PAL; 12347955f03dSHans Verkuil strncpy(go->name, "Plextor PX-TV402U-EU", 12357955f03dSHans Verkuil sizeof(go->name)); 12367955f03dSHans Verkuil break; 12377955f03dSHans Verkuil case 2: 12387955f03dSHans Verkuil go->tuner_type = TUNER_SONY_BTF_PK467Z; 12397955f03dSHans Verkuil go->std = V4L2_STD_NTSC_M_JP; 12407955f03dSHans Verkuil num_i2c_devs -= 2; 12417955f03dSHans Verkuil strncpy(go->name, "Plextor PX-TV402U-JP", 12427955f03dSHans Verkuil sizeof(go->name)); 12437955f03dSHans Verkuil break; 12447955f03dSHans Verkuil case 3: 12457955f03dSHans Verkuil go->tuner_type = TUNER_SONY_BTF_PB463Z; 12467955f03dSHans Verkuil num_i2c_devs -= 2; 12477955f03dSHans Verkuil strncpy(go->name, "Plextor PX-TV402U-NA", 12487955f03dSHans Verkuil sizeof(go->name)); 12497955f03dSHans Verkuil break; 12507955f03dSHans Verkuil default: 12517955f03dSHans Verkuil pr_debug("unable to detect tuner type!\n"); 12527955f03dSHans Verkuil break; 12537955f03dSHans Verkuil } 12547955f03dSHans Verkuil /* Configure tuner mode selection inputs connected 12557955f03dSHans Verkuil * to the EZ-USB GPIO output pins */ 12567955f03dSHans Verkuil if (go7007_usb_vendor_request(go, 0x40, 0x7f02, 0, 12577955f03dSHans Verkuil NULL, 0, 0) < 0) { 12587955f03dSHans Verkuil dev_err(go->dev, "GPIO write failed!\n"); 12597955f03dSHans Verkuil goto allocfail; 12607955f03dSHans Verkuil } 12617955f03dSHans Verkuil } 12627955f03dSHans Verkuil 12637955f03dSHans Verkuil /* Print a nasty message if the user attempts to use a USB2.0 device in 12647955f03dSHans Verkuil * a USB1.1 port. There will be silent corruption of the stream. */ 12657955f03dSHans Verkuil if ((board->flags & GO7007_USB_EZUSB) && 12667955f03dSHans Verkuil usbdev->speed != USB_SPEED_HIGH) 12677955f03dSHans 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"); 12687955f03dSHans Verkuil 12697955f03dSHans Verkuil /* Allocate the URBs and buffers for receiving the video stream */ 12707955f03dSHans Verkuil if (board->flags & GO7007_USB_EZUSB) { 12717955f03dSHans Verkuil v_urb_len = 1024; 12727955f03dSHans Verkuil video_pipe = usb_rcvbulkpipe(usb->usbdev, 6); 12737955f03dSHans Verkuil } else { 12747955f03dSHans Verkuil v_urb_len = 512; 12757955f03dSHans Verkuil video_pipe = usb_rcvbulkpipe(usb->usbdev, 1); 12767955f03dSHans Verkuil } 12777955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 12787955f03dSHans Verkuil usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); 12797955f03dSHans Verkuil if (usb->video_urbs[i] == NULL) 12807955f03dSHans Verkuil goto allocfail; 12817955f03dSHans Verkuil usb->video_urbs[i]->transfer_buffer = 12827955f03dSHans Verkuil kmalloc(v_urb_len, GFP_KERNEL); 12837955f03dSHans Verkuil if (usb->video_urbs[i]->transfer_buffer == NULL) 12847955f03dSHans Verkuil goto allocfail; 12857955f03dSHans Verkuil usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe, 12867955f03dSHans Verkuil usb->video_urbs[i]->transfer_buffer, v_urb_len, 12877955f03dSHans Verkuil go7007_usb_read_video_pipe_complete, go); 12887955f03dSHans Verkuil } 12897955f03dSHans Verkuil 12907955f03dSHans Verkuil /* Allocate the URBs and buffers for receiving the audio stream */ 12917955f03dSHans Verkuil if ((board->flags & GO7007_USB_EZUSB) && 12927955f03dSHans Verkuil (board->flags & GO7007_BOARD_HAS_AUDIO)) { 12937955f03dSHans Verkuil for (i = 0; i < 8; ++i) { 12947955f03dSHans Verkuil usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL); 12957955f03dSHans Verkuil if (usb->audio_urbs[i] == NULL) 12967955f03dSHans Verkuil goto allocfail; 12977955f03dSHans Verkuil usb->audio_urbs[i]->transfer_buffer = kmalloc(4096, 12987955f03dSHans Verkuil GFP_KERNEL); 12997955f03dSHans Verkuil if (usb->audio_urbs[i]->transfer_buffer == NULL) 13007955f03dSHans Verkuil goto allocfail; 13017955f03dSHans Verkuil usb_fill_bulk_urb(usb->audio_urbs[i], usb->usbdev, 13027955f03dSHans Verkuil usb_rcvbulkpipe(usb->usbdev, 8), 13037955f03dSHans Verkuil usb->audio_urbs[i]->transfer_buffer, 4096, 13047955f03dSHans Verkuil go7007_usb_read_audio_pipe_complete, go); 13057955f03dSHans Verkuil } 13067955f03dSHans Verkuil } 13077955f03dSHans Verkuil 13087955f03dSHans Verkuil /* Do any final GO7007 initialization, then register the 13097955f03dSHans Verkuil * V4L2 and ALSA interfaces */ 13107955f03dSHans Verkuil if (go7007_register_encoder(go, num_i2c_devs) < 0) 13117955f03dSHans Verkuil goto allocfail; 13127955f03dSHans Verkuil 13137955f03dSHans Verkuil go->status = STATUS_ONLINE; 13147955f03dSHans Verkuil return 0; 13157955f03dSHans Verkuil 13167955f03dSHans Verkuil allocfail: 13177955f03dSHans Verkuil go7007_usb_release(go); 13187955f03dSHans Verkuil kfree(go); 13197955f03dSHans Verkuil return -ENOMEM; 13207955f03dSHans Verkuil } 13217955f03dSHans Verkuil 13227955f03dSHans Verkuil static void go7007_usb_disconnect(struct usb_interface *intf) 13237955f03dSHans Verkuil { 13247955f03dSHans Verkuil struct go7007 *go = to_go7007(usb_get_intfdata(intf)); 13257955f03dSHans Verkuil 13267955f03dSHans Verkuil mutex_lock(&go->queue_lock); 13277955f03dSHans Verkuil mutex_lock(&go->serialize_lock); 13287955f03dSHans Verkuil 13297955f03dSHans Verkuil if (go->audio_enabled) 13307955f03dSHans Verkuil go7007_snd_remove(go); 13317955f03dSHans Verkuil 13327955f03dSHans Verkuil go->status = STATUS_SHUTDOWN; 13337955f03dSHans Verkuil v4l2_device_disconnect(&go->v4l2_dev); 13347955f03dSHans Verkuil video_unregister_device(&go->vdev); 13357955f03dSHans Verkuil mutex_unlock(&go->serialize_lock); 13367955f03dSHans Verkuil mutex_unlock(&go->queue_lock); 13377955f03dSHans Verkuil 13387955f03dSHans Verkuil v4l2_device_put(&go->v4l2_dev); 13397955f03dSHans Verkuil } 13407955f03dSHans Verkuil 13417955f03dSHans Verkuil static struct usb_driver go7007_usb_driver = { 13427955f03dSHans Verkuil .name = "go7007", 13437955f03dSHans Verkuil .probe = go7007_usb_probe, 13447955f03dSHans Verkuil .disconnect = go7007_usb_disconnect, 13457955f03dSHans Verkuil .id_table = go7007_usb_id_table, 13467955f03dSHans Verkuil }; 13477955f03dSHans Verkuil 13487955f03dSHans Verkuil module_usb_driver(go7007_usb_driver); 13497955f03dSHans Verkuil MODULE_LICENSE("GPL v2"); 1350