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
go7007_usb_vendor_request(struct go7007 * go,int request,int value,int index,void * transfer_buffer,int length,int in)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
go7007_usb_interface_reset(struct go7007 * go)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
go7007_usb_ezusb_write_interrupt(struct go7007 * go,int addr,int data)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
go7007_usb_onboard_write_interrupt(struct go7007 * go,int addr,int data)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
go7007_usb_readinterrupt_complete(struct urb * urb)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
go7007_usb_read_interrupt(struct go7007 * go)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
go7007_usb_read_video_pipe_complete(struct urb * urb)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
go7007_usb_read_audio_pipe_complete(struct urb * urb)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
go7007_usb_stream_start(struct go7007 * go)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
go7007_usb_stream_stop(struct go7007 * go)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
go7007_usb_send_firmware(struct go7007 * go,u8 * data,int len)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
go7007_usb_release(struct go7007 * go)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
go7007_usb_i2c_master_xfer(struct i2c_adapter * adapter,struct i2c_msg msgs[],int num)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
go7007_usb_functionality(struct i2c_adapter * adapter)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
go7007_usb_probe(struct usb_interface * intf,const struct usb_device_id * id)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);
1047a3ea410cSTakashi 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
113513764128SOliver Neukum ep = usb->usbdev->ep_in[4];
113613764128SOliver Neukum if (!ep)
113747d94dadSPavel Skripkin goto allocfail;
113813764128SOliver Neukum
11397955f03dSHans Verkuil /* Allocate the URB and buffer for receiving incoming interrupts */
11407955f03dSHans Verkuil usb->intr_urb = usb_alloc_urb(0, GFP_KERNEL);
11417955f03dSHans Verkuil if (usb->intr_urb == NULL)
11427955f03dSHans Verkuil goto allocfail;
11436da2ec56SKees Cook usb->intr_urb->transfer_buffer = kmalloc_array(2, sizeof(u16),
11446da2ec56SKees Cook GFP_KERNEL);
11457955f03dSHans Verkuil if (usb->intr_urb->transfer_buffer == NULL)
11467955f03dSHans Verkuil goto allocfail;
11477955f03dSHans Verkuil
1148a3ea410cSTakashi Iwai if (usb_endpoint_type(&ep->desc) == USB_ENDPOINT_XFER_BULK)
11497955f03dSHans Verkuil usb_fill_bulk_urb(usb->intr_urb, usb->usbdev,
11507955f03dSHans Verkuil usb_rcvbulkpipe(usb->usbdev, 4),
11517955f03dSHans Verkuil usb->intr_urb->transfer_buffer, 2*sizeof(u16),
11527955f03dSHans Verkuil go7007_usb_readinterrupt_complete, go);
11537955f03dSHans Verkuil else
11547955f03dSHans Verkuil usb_fill_int_urb(usb->intr_urb, usb->usbdev,
11557955f03dSHans Verkuil usb_rcvintpipe(usb->usbdev, 4),
11567955f03dSHans Verkuil usb->intr_urb->transfer_buffer, 2*sizeof(u16),
11577955f03dSHans Verkuil go7007_usb_readinterrupt_complete, go, 8);
11587955f03dSHans Verkuil usb_set_intfdata(intf, &go->v4l2_dev);
11597955f03dSHans Verkuil
11607955f03dSHans Verkuil /* Boot the GO7007 */
11617955f03dSHans Verkuil if (go7007_boot_encoder(go, go->board_info->flags &
11627955f03dSHans Verkuil GO7007_BOARD_USE_ONBOARD_I2C) < 0)
11637955f03dSHans Verkuil goto allocfail;
11647955f03dSHans Verkuil
11657955f03dSHans Verkuil /* Register the EZ-USB I2C adapter, if we're using it */
11667955f03dSHans Verkuil if (board->flags & GO7007_USB_EZUSB_I2C) {
11677955f03dSHans Verkuil memcpy(&go->i2c_adapter, &go7007_usb_adap_templ,
11687955f03dSHans Verkuil sizeof(go7007_usb_adap_templ));
11697955f03dSHans Verkuil mutex_init(&usb->i2c_lock);
11707955f03dSHans Verkuil go->i2c_adapter.dev.parent = go->dev;
11717955f03dSHans Verkuil i2c_set_adapdata(&go->i2c_adapter, go);
11727955f03dSHans Verkuil if (i2c_add_adapter(&go->i2c_adapter) < 0) {
11737955f03dSHans Verkuil dev_err(go->dev, "error: i2c_add_adapter failed\n");
11747955f03dSHans Verkuil goto allocfail;
11757955f03dSHans Verkuil }
11767955f03dSHans Verkuil go->i2c_adapter_online = 1;
11777955f03dSHans Verkuil }
11787955f03dSHans Verkuil
11797955f03dSHans Verkuil /* Pelco and Adlink reused the XMen and XMen-III vendor and product
11807955f03dSHans Verkuil * IDs for their own incompatible designs. We can detect XMen boards
11817955f03dSHans Verkuil * by probing the sensor, but there is no way to probe the sensors on
11827955f03dSHans Verkuil * the Pelco and Adlink designs so we default to the Adlink. If it
11837955f03dSHans Verkuil * is actually a Pelco, the user must set the assume_endura module
11847955f03dSHans Verkuil * parameter. */
11857955f03dSHans Verkuil if ((go->board_id == GO7007_BOARDID_XMEN ||
11867955f03dSHans Verkuil go->board_id == GO7007_BOARDID_XMEN_III) &&
11877955f03dSHans Verkuil go->i2c_adapter_online) {
11887955f03dSHans Verkuil union i2c_smbus_data data;
11897955f03dSHans Verkuil
11907955f03dSHans Verkuil /* Check to see if register 0x0A is 0x76 */
11917955f03dSHans Verkuil i2c_smbus_xfer(&go->i2c_adapter, 0x21, I2C_CLIENT_SCCB,
11927955f03dSHans Verkuil I2C_SMBUS_READ, 0x0A, I2C_SMBUS_BYTE_DATA, &data);
11937955f03dSHans Verkuil if (data.byte != 0x76) {
11947955f03dSHans Verkuil if (assume_endura) {
11957955f03dSHans Verkuil go->board_id = GO7007_BOARDID_ENDURA;
11967955f03dSHans Verkuil usb->board = board = &board_endura;
11977955f03dSHans Verkuil go->board_info = &board->main_info;
119885709cbfSMauro Carvalho Chehab strscpy(go->name, "Pelco Endura",
11997955f03dSHans Verkuil sizeof(go->name));
12007955f03dSHans Verkuil } else {
12017955f03dSHans Verkuil u16 channel;
12027955f03dSHans Verkuil
12037955f03dSHans Verkuil /* read channel number from GPIO[1:0] */
1204*79159e7cSDaniil Dulov if (go7007_read_addr(go, 0x3c81, &channel))
1205*79159e7cSDaniil Dulov goto allocfail;
1206*79159e7cSDaniil Dulov
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;
123485709cbfSMauro Carvalho Chehab strscpy(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;
124185709cbfSMauro Carvalho Chehab strscpy(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;
124785709cbfSMauro Carvalho Chehab strscpy(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) {
127113764128SOliver Neukum if (!usb->usbdev->ep_in[6])
127213764128SOliver Neukum goto allocfail;
12737955f03dSHans Verkuil v_urb_len = 1024;
12747955f03dSHans Verkuil video_pipe = usb_rcvbulkpipe(usb->usbdev, 6);
12757955f03dSHans Verkuil } else {
127613764128SOliver Neukum if (!usb->usbdev->ep_in[1])
127713764128SOliver Neukum goto allocfail;
12787955f03dSHans Verkuil v_urb_len = 512;
12797955f03dSHans Verkuil video_pipe = usb_rcvbulkpipe(usb->usbdev, 1);
12807955f03dSHans Verkuil }
12817955f03dSHans Verkuil for (i = 0; i < 8; ++i) {
12827955f03dSHans Verkuil usb->video_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
12837955f03dSHans Verkuil if (usb->video_urbs[i] == NULL)
12847955f03dSHans Verkuil goto allocfail;
12857955f03dSHans Verkuil usb->video_urbs[i]->transfer_buffer =
12867955f03dSHans Verkuil kmalloc(v_urb_len, GFP_KERNEL);
12877955f03dSHans Verkuil if (usb->video_urbs[i]->transfer_buffer == NULL)
12887955f03dSHans Verkuil goto allocfail;
12897955f03dSHans Verkuil usb_fill_bulk_urb(usb->video_urbs[i], usb->usbdev, video_pipe,
12907955f03dSHans Verkuil usb->video_urbs[i]->transfer_buffer, v_urb_len,
12917955f03dSHans Verkuil go7007_usb_read_video_pipe_complete, go);
12927955f03dSHans Verkuil }
12937955f03dSHans Verkuil
12947955f03dSHans Verkuil /* Allocate the URBs and buffers for receiving the audio stream */
12957955f03dSHans Verkuil if ((board->flags & GO7007_USB_EZUSB) &&
1296ba463988SHans Verkuil (board->main_info.flags & GO7007_BOARD_HAS_AUDIO)) {
129713764128SOliver Neukum if (!usb->usbdev->ep_in[8])
129813764128SOliver Neukum goto allocfail;
12997955f03dSHans Verkuil for (i = 0; i < 8; ++i) {
13007955f03dSHans Verkuil usb->audio_urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
13017955f03dSHans Verkuil if (usb->audio_urbs[i] == NULL)
13027955f03dSHans Verkuil goto allocfail;
13037955f03dSHans Verkuil usb->audio_urbs[i]->transfer_buffer = kmalloc(4096,
13047955f03dSHans Verkuil GFP_KERNEL);
13057955f03dSHans Verkuil if (usb->audio_urbs[i]->transfer_buffer == NULL)
13067955f03dSHans Verkuil goto allocfail;
13077955f03dSHans Verkuil usb_fill_bulk_urb(usb->audio_urbs[i], usb->usbdev,
13087955f03dSHans Verkuil usb_rcvbulkpipe(usb->usbdev, 8),
13097955f03dSHans Verkuil usb->audio_urbs[i]->transfer_buffer, 4096,
13107955f03dSHans Verkuil go7007_usb_read_audio_pipe_complete, go);
13117955f03dSHans Verkuil }
13127955f03dSHans Verkuil }
13137955f03dSHans Verkuil
13147955f03dSHans Verkuil /* Do any final GO7007 initialization, then register the
13157955f03dSHans Verkuil * V4L2 and ALSA interfaces */
13167955f03dSHans Verkuil if (go7007_register_encoder(go, num_i2c_devs) < 0)
13177955f03dSHans Verkuil goto allocfail;
13187955f03dSHans Verkuil
13197955f03dSHans Verkuil go->status = STATUS_ONLINE;
13207955f03dSHans Verkuil return 0;
13217955f03dSHans Verkuil
13227955f03dSHans Verkuil allocfail:
13237955f03dSHans Verkuil go7007_usb_release(go);
13247955f03dSHans Verkuil kfree(go);
13257955f03dSHans Verkuil return -ENOMEM;
13267955f03dSHans Verkuil }
13277955f03dSHans Verkuil
go7007_usb_disconnect(struct usb_interface * intf)13287955f03dSHans Verkuil static void go7007_usb_disconnect(struct usb_interface *intf)
13297955f03dSHans Verkuil {
13307955f03dSHans Verkuil struct go7007 *go = to_go7007(usb_get_intfdata(intf));
13317955f03dSHans Verkuil
13327955f03dSHans Verkuil mutex_lock(&go->queue_lock);
13337955f03dSHans Verkuil mutex_lock(&go->serialize_lock);
13347955f03dSHans Verkuil
13357955f03dSHans Verkuil if (go->audio_enabled)
13367955f03dSHans Verkuil go7007_snd_remove(go);
13377955f03dSHans Verkuil
13387955f03dSHans Verkuil go->status = STATUS_SHUTDOWN;
13397955f03dSHans Verkuil v4l2_device_disconnect(&go->v4l2_dev);
13407955f03dSHans Verkuil video_unregister_device(&go->vdev);
13417955f03dSHans Verkuil mutex_unlock(&go->serialize_lock);
13427955f03dSHans Verkuil mutex_unlock(&go->queue_lock);
13437955f03dSHans Verkuil
13447955f03dSHans Verkuil v4l2_device_put(&go->v4l2_dev);
13457955f03dSHans Verkuil }
13467955f03dSHans Verkuil
13477955f03dSHans Verkuil static struct usb_driver go7007_usb_driver = {
13487955f03dSHans Verkuil .name = "go7007",
13497955f03dSHans Verkuil .probe = go7007_usb_probe,
13507955f03dSHans Verkuil .disconnect = go7007_usb_disconnect,
13517955f03dSHans Verkuil .id_table = go7007_usb_id_table,
13527955f03dSHans Verkuil };
13537955f03dSHans Verkuil
13547955f03dSHans Verkuil module_usb_driver(go7007_usb_driver);
13557955f03dSHans Verkuil MODULE_LICENSE("GPL v2");
1356