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