2008-02-16 08:53:09 +08:00
/*
* Copyright ( C ) 2005 - 2006 Micronas USA Inc .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License ( Version 2 ) as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*/
2013-11-26 01:21:55 +08:00
# define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
2008-02-16 08:53:09 +08:00
# include <linux/module.h>
# include <linux/kernel.h>
# include <linux/wait.h>
# include <linux/list.h>
# include <linux/slab.h>
# include <linux/time.h>
# include <linux/mm.h>
# include <linux/usb.h>
# include <linux/i2c.h>
# include <asm/byteorder.h>
2015-11-10 22:01:44 +08:00
# include <media/i2c/saa7115.h>
2013-03-10 00:14:32 +08:00
# include <media/tuner.h>
2015-11-10 22:01:44 +08:00
# include <media/i2c/uda1342.h>
2008-02-16 08:53:09 +08:00
# include "go7007-priv.h"
static unsigned int assume_endura ;
module_param ( assume_endura , int , 0644 ) ;
2013-10-09 17:51:38 +08:00
MODULE_PARM_DESC ( assume_endura ,
" when probing fails, hardware is a Pelco Endura " ) ;
2008-02-16 08:53:09 +08:00
/* #define GO7007_I2C_DEBUG */ /* for debugging the EZ-USB I2C adapter */
# define HPI_STATUS_ADDR 0xFFF4
# define INT_PARAM_ADDR 0xFFF6
# define INT_INDEX_ADDR 0xFFF8
/*
* Pipes on EZ - USB interface :
2009-09-19 08:28:59 +08:00
* 0 snd - Control
* 0 rcv - Control
* 2 snd - Download firmware ( control )
* 4 rcv - Read Interrupt ( interrupt )
* 6 rcv - Read Video ( bulk )
* 8 rcv - Read Audio ( bulk )
2008-02-16 08:53:09 +08:00
*/
# define GO7007_USB_EZUSB (1<<0)
# define GO7007_USB_EZUSB_I2C (1<<1)
struct go7007_usb_board {
unsigned int flags ;
struct go7007_board_info main_info ;
} ;
struct go7007_usb {
2013-03-17 21:56:20 +08:00
const struct go7007_usb_board * board ;
2009-09-15 22:07:59 +08:00
struct mutex i2c_lock ;
2008-02-16 08:53:09 +08:00
struct usb_device * usbdev ;
struct urb * video_urbs [ 8 ] ;
struct urb * audio_urbs [ 8 ] ;
struct urb * intr_urb ;
} ;
/*********************** Product specification data ***********************/
2013-03-17 21:56:20 +08:00
static const struct go7007_usb_board board_matrix_ii = {
2008-02-16 08:53:09 +08:00
. flags = GO7007_USB_EZUSB ,
. main_info = {
. flags = GO7007_BOARD_HAS_AUDIO |
GO7007_BOARD_USE_ONBOARD_I2C ,
. audio_flags = GO7007_AUDIO_I2S_MODE_1 |
GO7007_AUDIO_WORD_16 ,
. audio_rate = 48000 ,
. audio_bclk_div = 8 ,
. audio_main_div = 2 ,
. hpi_buffer_cap = 7 ,
. sensor_flags = GO7007_SENSOR_656 |
GO7007_SENSOR_VALID_ENABLE |
GO7007_SENSOR_TV |
2013-03-11 17:12:10 +08:00
GO7007_SENSOR_SAA7115 |
2008-02-16 08:53:09 +08:00
GO7007_SENSOR_VBI |
GO7007_SENSOR_SCALING ,
. num_i2c_devs = 1 ,
. i2c_devs = {
{
2013-03-09 20:25:47 +08:00
. type = " saa7115 " ,
2008-02-16 08:53:09 +08:00
. addr = 0x20 ,
2013-03-09 20:25:47 +08:00
. is_video = 1 ,
2008-02-16 08:53:09 +08:00
} ,
} ,
. num_inputs = 2 ,
2009-09-19 08:28:59 +08:00
. inputs = {
2008-02-16 08:53:09 +08:00
{
. video_input = 0 ,
. name = " Composite " ,
} ,
{
. video_input = 9 ,
. name = " S-Video " ,
} ,
} ,
2013-03-09 20:25:47 +08:00
. video_config = SAA7115_IDQ_IS_DEFAULT ,
2008-02-16 08:53:09 +08:00
} ,
} ;
2013-03-17 21:56:20 +08:00
static const struct go7007_usb_board board_matrix_reload = {
2008-02-16 08:53:09 +08:00
. flags = GO7007_USB_EZUSB ,
. main_info = {
. flags = GO7007_BOARD_HAS_AUDIO |
GO7007_BOARD_USE_ONBOARD_I2C ,
. audio_flags = GO7007_AUDIO_I2S_MODE_1 |
GO7007_AUDIO_I2S_MASTER |
GO7007_AUDIO_WORD_16 ,
. audio_rate = 48000 ,
. audio_bclk_div = 8 ,
. audio_main_div = 2 ,
. hpi_buffer_cap = 7 ,
. sensor_flags = GO7007_SENSOR_656 |
GO7007_SENSOR_TV ,
. num_i2c_devs = 1 ,
. i2c_devs = {
{
2013-03-11 17:12:10 +08:00
. type = " saa7113 " ,
2008-02-16 08:53:09 +08:00
. addr = 0x25 ,
2013-03-09 20:25:47 +08:00
. is_video = 1 ,
2008-02-16 08:53:09 +08:00
} ,
} ,
. num_inputs = 2 ,
2009-09-19 08:28:59 +08:00
. inputs = {
2008-02-16 08:53:09 +08:00
{
. video_input = 0 ,
. name = " Composite " ,
} ,
{
. video_input = 9 ,
. name = " S-Video " ,
} ,
} ,
2013-03-09 20:25:47 +08:00
. video_config = SAA7115_IDQ_IS_DEFAULT ,
2008-02-16 08:53:09 +08:00
} ,
} ;
2013-03-17 21:56:20 +08:00
static const struct go7007_usb_board board_star_trek = {
2008-02-16 08:53:09 +08:00
. flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C ,
. main_info = {
. flags = GO7007_BOARD_HAS_AUDIO , /* |
GO7007_BOARD_HAS_TUNER , */
. sensor_flags = GO7007_SENSOR_656 |
GO7007_SENSOR_VALID_ENABLE |
GO7007_SENSOR_TV |
2013-03-11 17:12:10 +08:00
GO7007_SENSOR_SAA7115 |
2008-02-16 08:53:09 +08:00
GO7007_SENSOR_VBI |
GO7007_SENSOR_SCALING ,
. audio_flags = GO7007_AUDIO_I2S_MODE_1 |
GO7007_AUDIO_WORD_16 ,
. audio_bclk_div = 8 ,
. audio_main_div = 2 ,
. hpi_buffer_cap = 7 ,
. num_i2c_devs = 1 ,
. i2c_devs = {
{
2013-03-09 20:25:47 +08:00
. type = " saa7115 " ,
2008-02-16 08:53:09 +08:00
. addr = 0x20 ,
2013-03-09 20:25:47 +08:00
. is_video = 1 ,
2008-02-16 08:53:09 +08:00
} ,
} ,
. num_inputs = 2 ,
2009-09-19 08:28:59 +08:00
. inputs = {
2013-03-09 20:25:47 +08:00
/* {
* . video_input = 3 ,
* . audio_index = AUDIO_TUNER ,
* . name = " Tuner " ,
* } ,
*/
2008-02-16 08:53:09 +08:00
{
. video_input = 1 ,
2013-03-09 20:25:47 +08:00
/* .audio_index = AUDIO_EXTERN, */
2008-02-16 08:53:09 +08:00
. name = " Composite " ,
} ,
{
. video_input = 8 ,
2013-03-09 20:25:47 +08:00
/* .audio_index = AUDIO_EXTERN, */
2008-02-16 08:53:09 +08:00
. name = " S-Video " ,
} ,
} ,
2013-03-09 20:25:47 +08:00
. video_config = SAA7115_IDQ_IS_DEFAULT ,
2008-02-16 08:53:09 +08:00
} ,
} ;
2013-03-17 21:56:20 +08:00
static const struct go7007_usb_board board_px_tv402u = {
2008-02-16 08:53:09 +08:00
. flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C ,
. main_info = {
. flags = GO7007_BOARD_HAS_AUDIO |
GO7007_BOARD_HAS_TUNER ,
. sensor_flags = GO7007_SENSOR_656 |
GO7007_SENSOR_VALID_ENABLE |
GO7007_SENSOR_TV |
2013-03-11 17:12:10 +08:00
GO7007_SENSOR_SAA7115 |
2008-02-16 08:53:09 +08:00
GO7007_SENSOR_VBI |
GO7007_SENSOR_SCALING ,
. audio_flags = GO7007_AUDIO_I2S_MODE_1 |
GO7007_AUDIO_WORD_16 ,
. audio_bclk_div = 8 ,
. audio_main_div = 2 ,
. hpi_buffer_cap = 7 ,
2013-03-09 20:25:47 +08:00
. num_i2c_devs = 5 ,
2008-02-16 08:53:09 +08:00
. i2c_devs = {
{
2013-03-09 20:25:47 +08:00
. type = " saa7115 " ,
2008-02-16 08:53:09 +08:00
. addr = 0x20 ,
2013-03-09 20:25:47 +08:00
. is_video = 1 ,
2008-02-16 08:53:09 +08:00
} ,
{
2013-03-09 20:25:47 +08:00
. type = " uda1342 " ,
2008-02-16 08:53:09 +08:00
. addr = 0x1a ,
2013-03-09 20:25:47 +08:00
. is_audio = 1 ,
2008-02-16 08:53:09 +08:00
} ,
{
2013-03-09 20:25:47 +08:00
. type = " tuner " ,
2008-02-16 08:53:09 +08:00
. addr = 0x60 ,
} ,
2013-03-09 20:25:47 +08:00
{
. type = " tuner " ,
. addr = 0x43 ,
} ,
{
. type = " sony-btf-mpx " ,
. addr = 0x44 ,
} ,
2008-02-16 08:53:09 +08:00
} ,
. num_inputs = 3 ,
2009-09-19 08:28:59 +08:00
. inputs = {
2013-03-09 20:25:47 +08:00
{
. video_input = 3 ,
. audio_index = 0 ,
. name = " Tuner " ,
} ,
2008-02-16 08:53:09 +08:00
{
. video_input = 1 ,
2013-03-09 20:25:47 +08:00
. audio_index = 1 ,
2008-02-16 08:53:09 +08:00
. name = " Composite " ,
} ,
{
. video_input = 8 ,
2013-03-09 20:25:47 +08:00
. audio_index = 1 ,
2008-02-16 08:53:09 +08:00
. name = " S-Video " ,
} ,
2013-03-09 20:25:47 +08:00
} ,
. video_config = SAA7115_IDQ_IS_DEFAULT ,
. num_aud_inputs = 2 ,
. aud_inputs = {
2008-02-16 08:53:09 +08:00
{
2013-03-09 20:25:47 +08:00
. audio_input = UDA1342_IN2 ,
2008-02-16 08:53:09 +08:00
. name = " Tuner " ,
} ,
2013-03-09 20:25:47 +08:00
{
. audio_input = UDA1342_IN1 ,
. name = " Line In " ,
} ,
2008-02-16 08:53:09 +08:00
} ,
} ,
} ;
2013-03-17 21:56:20 +08:00
static const struct go7007_usb_board board_xmen = {
2008-02-16 08:53:09 +08:00
. flags = 0 ,
. main_info = {
. flags = GO7007_BOARD_USE_ONBOARD_I2C ,
. hpi_buffer_cap = 0 ,
. sensor_flags = GO7007_SENSOR_VREF_POLAR ,
. sensor_width = 320 ,
. sensor_height = 240 ,
. sensor_framerate = 30030 ,
. audio_flags = GO7007_AUDIO_ONE_CHANNEL |
GO7007_AUDIO_I2S_MODE_3 |
GO7007_AUDIO_WORD_14 |
GO7007_AUDIO_I2S_MASTER |
GO7007_AUDIO_BCLK_POLAR |
GO7007_AUDIO_OKI_MODE ,
. audio_rate = 8000 ,
. audio_bclk_div = 48 ,
. audio_main_div = 1 ,
. num_i2c_devs = 1 ,
. i2c_devs = {
{
2013-03-09 20:25:47 +08:00
. type = " ov7640 " ,
2008-02-16 08:53:09 +08:00
. addr = 0x21 ,
} ,
} ,
. num_inputs = 1 ,
2009-09-19 08:28:59 +08:00
. inputs = {
2008-02-16 08:53:09 +08:00
{
. name = " Camera " ,
} ,
} ,
} ,
} ;
2013-03-17 21:56:20 +08:00
static const struct go7007_usb_board board_matrix_revolution = {
2008-02-16 08:53:09 +08:00
. flags = GO7007_USB_EZUSB ,
. main_info = {
. flags = GO7007_BOARD_HAS_AUDIO |
GO7007_BOARD_USE_ONBOARD_I2C ,
. audio_flags = GO7007_AUDIO_I2S_MODE_1 |
GO7007_AUDIO_I2S_MASTER |
GO7007_AUDIO_WORD_16 ,
. audio_rate = 48000 ,
. audio_bclk_div = 8 ,
. audio_main_div = 2 ,
. hpi_buffer_cap = 7 ,
. sensor_flags = GO7007_SENSOR_656 |
GO7007_SENSOR_TV |
GO7007_SENSOR_VBI ,
. num_i2c_devs = 1 ,
. i2c_devs = {
{
2013-03-09 20:25:47 +08:00
. type = " tw9903 " ,
. is_video = 1 ,
2008-02-16 08:53:09 +08:00
. addr = 0x44 ,
} ,
} ,
. num_inputs = 2 ,
2009-09-19 08:28:59 +08:00
. inputs = {
2008-02-16 08:53:09 +08:00
{
. video_input = 2 ,
. name = " Composite " ,
} ,
{
. video_input = 8 ,
. name = " S-Video " ,
} ,
} ,
} ,
} ;
2015-04-29 23:44:18 +08:00
#if 0
2013-03-17 21:56:20 +08:00
static const struct go7007_usb_board board_lifeview_lr192 = {
2008-02-16 08:53:09 +08:00
. flags = GO7007_USB_EZUSB ,
. main_info = {
. flags = GO7007_BOARD_HAS_AUDIO |
GO7007_BOARD_USE_ONBOARD_I2C ,
. audio_flags = GO7007_AUDIO_I2S_MODE_1 |
GO7007_AUDIO_WORD_16 ,
. audio_rate = 48000 ,
. audio_bclk_div = 8 ,
. audio_main_div = 2 ,
. hpi_buffer_cap = 7 ,
. sensor_flags = GO7007_SENSOR_656 |
GO7007_SENSOR_VALID_ENABLE |
GO7007_SENSOR_TV |
GO7007_SENSOR_VBI |
GO7007_SENSOR_SCALING ,
. num_i2c_devs = 0 ,
. num_inputs = 1 ,
2009-09-19 08:28:59 +08:00
. inputs = {
2008-02-16 08:53:09 +08:00
{
. video_input = 0 ,
. name = " Composite " ,
} ,
} ,
} ,
} ;
2015-04-29 23:44:18 +08:00
# endif
2008-02-16 08:53:09 +08:00
2013-03-17 21:56:20 +08:00
static const struct go7007_usb_board board_endura = {
2008-02-16 08:53:09 +08:00
. flags = 0 ,
. main_info = {
. flags = 0 ,
. audio_flags = GO7007_AUDIO_I2S_MODE_1 |
GO7007_AUDIO_I2S_MASTER |
GO7007_AUDIO_WORD_16 ,
. audio_rate = 8000 ,
. audio_bclk_div = 48 ,
. audio_main_div = 8 ,
. hpi_buffer_cap = 0 ,
. sensor_flags = GO7007_SENSOR_656 |
GO7007_SENSOR_TV ,
. sensor_h_offset = 8 ,
. num_i2c_devs = 0 ,
. num_inputs = 1 ,
2009-09-19 08:28:59 +08:00
. inputs = {
2008-02-16 08:53:09 +08:00
{
. name = " Camera " ,
} ,
} ,
} ,
} ;
2013-03-17 21:56:20 +08:00
static const struct go7007_usb_board board_adlink_mpg24 = {
2008-02-16 08:53:09 +08:00
. flags = 0 ,
. main_info = {
. flags = GO7007_BOARD_USE_ONBOARD_I2C ,
. audio_flags = GO7007_AUDIO_I2S_MODE_1 |
GO7007_AUDIO_I2S_MASTER |
GO7007_AUDIO_WORD_16 ,
. audio_rate = 48000 ,
. audio_bclk_div = 8 ,
. audio_main_div = 2 ,
. hpi_buffer_cap = 0 ,
. sensor_flags = GO7007_SENSOR_656 |
GO7007_SENSOR_TV |
GO7007_SENSOR_VBI ,
. num_i2c_devs = 1 ,
. i2c_devs = {
{
2013-03-09 20:25:47 +08:00
. type = " tw2804 " ,
2008-02-16 08:53:09 +08:00
. addr = 0x00 , /* yes, really */
2013-03-09 19:48:25 +08:00
. flags = I2C_CLIENT_TEN ,
2013-03-09 20:25:47 +08:00
. is_video = 1 ,
2008-02-16 08:53:09 +08:00
} ,
} ,
. num_inputs = 1 ,
2009-09-19 08:28:59 +08:00
. inputs = {
2008-02-16 08:53:09 +08:00
{
. name = " Composite " ,
} ,
} ,
} ,
} ;
2013-03-17 21:56:20 +08:00
static const struct go7007_usb_board board_sensoray_2250 = {
2008-10-31 03:56:41 +08:00
. flags = GO7007_USB_EZUSB | GO7007_USB_EZUSB_I2C ,
. main_info = {
. audio_flags = GO7007_AUDIO_I2S_MODE_1 |
GO7007_AUDIO_I2S_MASTER |
GO7007_AUDIO_WORD_16 ,
. flags = GO7007_BOARD_HAS_AUDIO ,
. audio_rate = 48000 ,
. audio_bclk_div = 8 ,
. audio_main_div = 2 ,
. hpi_buffer_cap = 7 ,
. sensor_flags = GO7007_SENSOR_656 |
GO7007_SENSOR_TV ,
. num_i2c_devs = 1 ,
. i2c_devs = {
{
2009-11-17 02:13:51 +08:00
. type = " s2250 " ,
2009-04-22 03:47:22 +08:00
. addr = 0x43 ,
2013-03-09 20:25:47 +08:00
. is_video = 1 ,
. is_audio = 1 ,
2008-10-31 03:56:41 +08:00
} ,
} ,
. num_inputs = 2 ,
2009-09-19 08:28:59 +08:00
. inputs = {
2008-10-31 03:56:41 +08:00
{
. video_input = 0 ,
. name = " Composite " ,
} ,
{
. video_input = 1 ,
. name = " S-Video " ,
} ,
} ,
2013-03-09 20:25:47 +08:00
. num_aud_inputs = 3 ,
. aud_inputs = {
{
. audio_input = 0 ,
. name = " Line In " ,
} ,
{
. audio_input = 1 ,
. name = " Mic " ,
} ,
{
. audio_input = 2 ,
. name = " Mic Boost " ,
} ,
} ,
2008-10-31 03:56:41 +08:00
} ,
} ;
2013-03-17 21:15:03 +08:00
static const struct go7007_usb_board board_ads_usbav_709 = {
. flags = GO7007_USB_EZUSB ,
. main_info = {
. flags = GO7007_BOARD_HAS_AUDIO |
GO7007_BOARD_USE_ONBOARD_I2C ,
. audio_flags = GO7007_AUDIO_I2S_MODE_1 |
GO7007_AUDIO_I2S_MASTER |
GO7007_AUDIO_WORD_16 ,
. audio_rate = 48000 ,
. audio_bclk_div = 8 ,
. audio_main_div = 2 ,
. hpi_buffer_cap = 7 ,
. sensor_flags = GO7007_SENSOR_656 |
GO7007_SENSOR_TV |
GO7007_SENSOR_VBI ,
. num_i2c_devs = 1 ,
. i2c_devs = {
{
. type = " tw9906 " ,
. is_video = 1 ,
. addr = 0x44 ,
} ,
} ,
. num_inputs = 2 ,
. inputs = {
{
. video_input = 0 ,
. name = " Composite " ,
} ,
{
. video_input = 10 ,
. name = " S-Video " ,
} ,
} ,
} ,
} ;
2010-01-10 07:18:34 +08:00
static const struct usb_device_id go7007_usb_id_table [ ] = {
2008-02-16 08:53:09 +08:00
{
. match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
USB_DEVICE_ID_MATCH_INT_INFO ,
. idVendor = 0x0eb1 , /* Vendor ID of WIS Technologies */
. idProduct = 0x7007 , /* Product ID of GO7007SB chip */
. bcdDevice_lo = 0x200 , /* Revision number of XMen */
. bcdDevice_hi = 0x200 ,
. bInterfaceClass = 255 ,
. bInterfaceSubClass = 0 ,
. bInterfaceProtocol = 255 ,
. driver_info = ( kernel_ulong_t ) GO7007_BOARDID_XMEN ,
} ,
{
. match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION ,
. idVendor = 0x0eb1 , /* Vendor ID of WIS Technologies */
. idProduct = 0x7007 , /* Product ID of GO7007SB chip */
. bcdDevice_lo = 0x202 , /* Revision number of Matrix II */
. bcdDevice_hi = 0x202 ,
. driver_info = ( kernel_ulong_t ) GO7007_BOARDID_MATRIX_II ,
} ,
{
. match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION ,
. idVendor = 0x0eb1 , /* Vendor ID of WIS Technologies */
. idProduct = 0x7007 , /* Product ID of GO7007SB chip */
. bcdDevice_lo = 0x204 , /* Revision number of Matrix */
. bcdDevice_hi = 0x204 , /* Reloaded */
. driver_info = ( kernel_ulong_t ) GO7007_BOARDID_MATRIX_RELOAD ,
} ,
{
. match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
USB_DEVICE_ID_MATCH_INT_INFO ,
. idVendor = 0x0eb1 , /* Vendor ID of WIS Technologies */
. idProduct = 0x7007 , /* Product ID of GO7007SB chip */
. bcdDevice_lo = 0x205 , /* Revision number of XMen-II */
. bcdDevice_hi = 0x205 ,
. bInterfaceClass = 255 ,
. bInterfaceSubClass = 0 ,
. bInterfaceProtocol = 255 ,
. driver_info = ( kernel_ulong_t ) GO7007_BOARDID_XMEN_II ,
} ,
{
. match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION ,
. idVendor = 0x0eb1 , /* Vendor ID of WIS Technologies */
. idProduct = 0x7007 , /* Product ID of GO7007SB chip */
. bcdDevice_lo = 0x208 , /* Revision number of Star Trek */
. bcdDevice_hi = 0x208 ,
. driver_info = ( kernel_ulong_t ) GO7007_BOARDID_STAR_TREK ,
} ,
{
. match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
USB_DEVICE_ID_MATCH_INT_INFO ,
. idVendor = 0x0eb1 , /* Vendor ID of WIS Technologies */
. idProduct = 0x7007 , /* Product ID of GO7007SB chip */
. bcdDevice_lo = 0x209 , /* Revision number of XMen-III */
. bcdDevice_hi = 0x209 ,
. bInterfaceClass = 255 ,
. bInterfaceSubClass = 0 ,
. bInterfaceProtocol = 255 ,
. driver_info = ( kernel_ulong_t ) GO7007_BOARDID_XMEN_III ,
} ,
{
. match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION ,
. idVendor = 0x0eb1 , /* Vendor ID of WIS Technologies */
. idProduct = 0x7007 , /* Product ID of GO7007SB chip */
. bcdDevice_lo = 0x210 , /* Revision number of Matrix */
. bcdDevice_hi = 0x210 , /* Revolution */
. driver_info = ( kernel_ulong_t ) GO7007_BOARDID_MATRIX_REV ,
} ,
{
. match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION ,
. idVendor = 0x093b , /* Vendor ID of Plextor */
. idProduct = 0xa102 , /* Product ID of M402U */
. bcdDevice_lo = 0x1 , /* revision number of Blueberry */
. bcdDevice_hi = 0x1 ,
. driver_info = ( kernel_ulong_t ) GO7007_BOARDID_PX_M402U ,
} ,
{
. match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION ,
. idVendor = 0x093b , /* Vendor ID of Plextor */
. idProduct = 0xa104 , /* Product ID of TV402U */
. bcdDevice_lo = 0x1 ,
. bcdDevice_hi = 0x1 ,
2013-03-11 17:11:03 +08:00
. driver_info = ( kernel_ulong_t ) GO7007_BOARDID_PX_TV402U ,
2008-02-16 08:53:09 +08:00
} ,
{
. match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION ,
. idVendor = 0x10fd , /* Vendor ID of Anubis Electronics */
. idProduct = 0xde00 , /* Product ID of Lifeview LR192 */
. bcdDevice_lo = 0x1 ,
. bcdDevice_hi = 0x1 ,
. driver_info = ( kernel_ulong_t ) GO7007_BOARDID_LIFEVIEW_LR192 ,
} ,
2008-10-31 03:56:41 +08:00
{
. match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION ,
. idVendor = 0x1943 , /* Vendor ID Sensoray */
. idProduct = 0x2250 , /* Product ID of 2250/2251 */
. bcdDevice_lo = 0x1 ,
. bcdDevice_hi = 0x1 ,
. driver_info = ( kernel_ulong_t ) GO7007_BOARDID_SENSORAY_2250 ,
} ,
2013-03-17 21:15:03 +08:00
{
. match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION ,
. idVendor = 0x06e1 , /* Vendor ID of ADS Technologies */
. idProduct = 0x0709 , /* Product ID of DVD Xpress DX2 */
. bcdDevice_lo = 0x204 ,
. bcdDevice_hi = 0x204 ,
. driver_info = ( kernel_ulong_t ) GO7007_BOARDID_ADS_USBAV_709 ,
} ,
2008-02-16 08:53:09 +08:00
{ } /* Terminating entry */
} ;
MODULE_DEVICE_TABLE ( usb , go7007_usb_id_table ) ;
/********************* Driver for EZ-USB HPI interface *********************/
static int go7007_usb_vendor_request ( struct go7007 * go , int request ,
int value , int index , void * transfer_buffer , int length , int in )
{
struct go7007_usb * usb = go - > hpi_context ;
int timeout = 5000 ;
if ( in ) {
return usb_control_msg ( usb - > usbdev ,
usb_rcvctrlpipe ( usb - > usbdev , 0 ) , request ,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN ,
value , index , transfer_buffer , length , timeout ) ;
} else {
return usb_control_msg ( usb - > usbdev ,
usb_sndctrlpipe ( usb - > usbdev , 0 ) , request ,
USB_TYPE_VENDOR | USB_RECIP_DEVICE ,
value , index , transfer_buffer , length , timeout ) ;
}
}
static int go7007_usb_interface_reset ( struct go7007 * go )
{
struct go7007_usb * usb = go - > hpi_context ;
u16 intr_val , intr_data ;
2013-03-11 15:48:30 +08:00
if ( go - > status = = STATUS_SHUTDOWN )
return - 1 ;
2008-02-16 08:53:09 +08:00
/* Reset encoder */
if ( go7007_write_interrupt ( go , 0x0001 , 0x0001 ) < 0 )
return - 1 ;
msleep ( 100 ) ;
if ( usb - > board - > flags & GO7007_USB_EZUSB ) {
/* Reset buffer in EZ-USB */
2013-11-26 01:21:55 +08:00
pr_debug ( " resetting EZ-USB buffers \n " ) ;
2008-02-16 08:53:09 +08:00
if ( go7007_usb_vendor_request ( go , 0x10 , 0 , 0 , NULL , 0 , 0 ) < 0 | |
go7007_usb_vendor_request ( go , 0x10 , 0 , 0 , NULL , 0 , 0 ) < 0 )
return - 1 ;
/* Reset encoder again */
if ( go7007_write_interrupt ( go , 0x0001 , 0x0001 ) < 0 )
return - 1 ;
msleep ( 100 ) ;
}
/* Wait for an interrupt to indicate successful hardware reset */
if ( go7007_read_interrupt ( go , & intr_val , & intr_data ) < 0 | |
( intr_val & ~ 0x1 ) ! = 0x55aa ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " unable to reset the USB interface \n " ) ;
2008-02-16 08:53:09 +08:00
return - 1 ;
}
return 0 ;
}
static int go7007_usb_ezusb_write_interrupt ( struct go7007 * go ,
int addr , int data )
{
struct go7007_usb * usb = go - > hpi_context ;
int i , r ;
2013-03-09 20:59:16 +08:00
u16 status_reg = 0 ;
2008-02-16 08:53:09 +08:00
int timeout = 500 ;
2013-11-26 01:21:55 +08:00
pr_debug ( " WriteInterrupt: %04x %04x \n " , addr , data ) ;
2008-02-16 08:53:09 +08:00
for ( i = 0 ; i < 100 ; + + i ) {
r = usb_control_msg ( usb - > usbdev ,
usb_rcvctrlpipe ( usb - > usbdev , 0 ) , 0x14 ,
USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN ,
2013-03-09 20:59:16 +08:00
0 , HPI_STATUS_ADDR , go - > usb_buf ,
2008-02-16 08:53:09 +08:00
sizeof ( status_reg ) , timeout ) ;
if ( r < 0 )
2013-03-09 20:59:16 +08:00
break ;
2014-08-21 03:55:35 +08:00
status_reg = le16_to_cpu ( * ( ( __le16 * ) go - > usb_buf ) ) ;
2008-02-16 08:53:09 +08:00
if ( ! ( status_reg & 0x0010 ) )
break ;
msleep ( 10 ) ;
}
2013-03-09 20:59:16 +08:00
if ( r < 0 )
goto write_int_error ;
2008-02-16 08:53:09 +08:00
if ( i = = 100 ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " device is hung, status reg = 0x%04x \n " , status_reg ) ;
2008-02-16 08:53:09 +08:00
return - 1 ;
}
r = usb_control_msg ( usb - > usbdev , usb_sndctrlpipe ( usb - > usbdev , 0 ) , 0x12 ,
USB_TYPE_VENDOR | USB_RECIP_DEVICE , data ,
INT_PARAM_ADDR , NULL , 0 , timeout ) ;
if ( r < 0 )
goto write_int_error ;
r = usb_control_msg ( usb - > usbdev , usb_sndctrlpipe ( usb - > usbdev , 0 ) ,
0x12 , USB_TYPE_VENDOR | USB_RECIP_DEVICE , addr ,
INT_INDEX_ADDR , NULL , 0 , timeout ) ;
if ( r < 0 )
goto write_int_error ;
return 0 ;
write_int_error :
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " error in WriteInterrupt: %d \n " , r ) ;
2008-02-16 08:53:09 +08:00
return r ;
}
static int go7007_usb_onboard_write_interrupt ( struct go7007 * go ,
int addr , int data )
{
struct go7007_usb * usb = go - > hpi_context ;
int r ;
int timeout = 500 ;
2013-11-26 01:21:55 +08:00
pr_debug ( " WriteInterrupt: %04x %04x \n " , addr , data ) ;
2008-02-16 08:53:09 +08:00
2013-03-09 20:59:16 +08:00
go - > usb_buf [ 0 ] = data & 0xff ;
go - > usb_buf [ 1 ] = data > > 8 ;
go - > usb_buf [ 2 ] = addr & 0xff ;
go - > usb_buf [ 3 ] = addr > > 8 ;
go - > usb_buf [ 4 ] = go - > usb_buf [ 5 ] = go - > usb_buf [ 6 ] = go - > usb_buf [ 7 ] = 0 ;
2008-02-16 08:53:09 +08:00
r = usb_control_msg ( usb - > usbdev , usb_sndctrlpipe ( usb - > usbdev , 2 ) , 0x00 ,
USB_TYPE_VENDOR | USB_RECIP_ENDPOINT , 0x55aa ,
2013-03-09 20:59:16 +08:00
0xf0f0 , go - > usb_buf , 8 , timeout ) ;
2008-02-16 08:53:09 +08:00
if ( r < 0 ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " error in WriteInterrupt: %d \n " , r ) ;
2008-02-16 08:53:09 +08:00
return r ;
}
return 0 ;
}
static void go7007_usb_readinterrupt_complete ( struct urb * urb )
{
struct go7007 * go = ( struct go7007 * ) urb - > context ;
2014-08-21 03:55:35 +08:00
__le16 * regs = ( __le16 * ) urb - > transfer_buffer ;
2008-12-18 20:52:39 +08:00
int status = urb - > status ;
2008-02-16 08:53:09 +08:00
2008-12-18 20:52:39 +08:00
if ( status ) {
if ( status ! = - ESHUTDOWN & &
2008-02-16 08:53:09 +08:00
go - > status ! = STATUS_SHUTDOWN ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " error in read interrupt: %d \n " , urb - > status ) ;
2008-02-16 08:53:09 +08:00
} else {
wake_up ( & go - > interrupt_waitq ) ;
return ;
}
} else if ( urb - > actual_length ! = urb - > transfer_buffer_length ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " short read in interrupt pipe! \n " ) ;
2008-02-16 08:53:09 +08:00
} else {
go - > interrupt_available = 1 ;
go - > interrupt_data = __le16_to_cpu ( regs [ 0 ] ) ;
go - > interrupt_value = __le16_to_cpu ( regs [ 1 ] ) ;
2013-11-26 01:21:55 +08:00
pr_debug ( " ReadInterrupt: %04x %04x \n " ,
2008-02-16 08:53:09 +08:00
go - > interrupt_value , go - > interrupt_data ) ;
}
wake_up ( & go - > interrupt_waitq ) ;
}
static int go7007_usb_read_interrupt ( struct go7007 * go )
{
struct go7007_usb * usb = go - > hpi_context ;
int r ;
r = usb_submit_urb ( usb - > intr_urb , GFP_KERNEL ) ;
if ( r < 0 ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " unable to submit interrupt urb: %d \n " , r ) ;
2008-02-16 08:53:09 +08:00
return r ;
}
return 0 ;
}
static void go7007_usb_read_video_pipe_complete ( struct urb * urb )
{
struct go7007 * go = ( struct go7007 * ) urb - > context ;
2009-09-15 22:07:59 +08:00
int r , status = urb - > status ;
2008-02-16 08:53:09 +08:00
2013-03-11 17:52:27 +08:00
if ( ! vb2_is_streaming ( & go - > vidq ) ) {
2008-02-16 08:53:09 +08:00
wake_up_interruptible ( & go - > frame_waitq ) ;
return ;
}
2008-12-18 20:52:39 +08:00
if ( status ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " error in video pipe: %d \n " , status ) ;
2008-02-16 08:53:09 +08:00
return ;
}
if ( urb - > actual_length ! = urb - > transfer_buffer_length ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " short read in video pipe! \n " ) ;
2008-02-16 08:53:09 +08:00
return ;
}
go7007_parse_video_stream ( go , urb - > transfer_buffer , urb - > actual_length ) ;
r = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( r < 0 )
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " error in video pipe: %d \n " , r ) ;
2008-02-16 08:53:09 +08:00
}
static void go7007_usb_read_audio_pipe_complete ( struct urb * urb )
{
struct go7007 * go = ( struct go7007 * ) urb - > context ;
2008-12-18 20:52:39 +08:00
int r , status = urb - > status ;
2008-02-16 08:53:09 +08:00
2013-03-11 17:52:27 +08:00
if ( ! vb2_is_streaming ( & go - > vidq ) )
2008-02-16 08:53:09 +08:00
return ;
2008-12-18 20:52:39 +08:00
if ( status ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " error in audio pipe: %d \n " ,
2009-09-19 08:28:59 +08:00
status ) ;
2008-02-16 08:53:09 +08:00
return ;
}
if ( urb - > actual_length ! = urb - > transfer_buffer_length ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " short read in audio pipe! \n " ) ;
2008-02-16 08:53:09 +08:00
return ;
}
if ( go - > audio_deliver ! = NULL )
go - > audio_deliver ( go , urb - > transfer_buffer , urb - > actual_length ) ;
r = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( r < 0 )
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " error in audio pipe: %d \n " , r ) ;
2008-02-16 08:53:09 +08:00
}
static int go7007_usb_stream_start ( struct go7007 * go )
{
struct go7007_usb * usb = go - > hpi_context ;
int i , r ;
for ( i = 0 ; i < 8 ; + + i ) {
r = usb_submit_urb ( usb - > video_urbs [ i ] , GFP_KERNEL ) ;
if ( r < 0 ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " error submitting video urb %d: %d \n " , i , r ) ;
2008-02-16 08:53:09 +08:00
goto video_submit_failed ;
}
}
if ( ! go - > audio_enabled )
return 0 ;
for ( i = 0 ; i < 8 ; + + i ) {
r = usb_submit_urb ( usb - > audio_urbs [ i ] , GFP_KERNEL ) ;
if ( r < 0 ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " error submitting audio urb %d: %d \n " , i , r ) ;
2008-02-16 08:53:09 +08:00
goto audio_submit_failed ;
}
}
return 0 ;
audio_submit_failed :
2008-12-18 20:52:39 +08:00
for ( i = 0 ; i < 7 ; + + i )
2008-02-16 08:53:09 +08:00
usb_kill_urb ( usb - > audio_urbs [ i ] ) ;
video_submit_failed :
for ( i = 0 ; i < 8 ; + + i )
usb_kill_urb ( usb - > video_urbs [ i ] ) ;
return - 1 ;
}
static int go7007_usb_stream_stop ( struct go7007 * go )
{
struct go7007_usb * usb = go - > hpi_context ;
int i ;
if ( go - > status = = STATUS_SHUTDOWN )
return 0 ;
for ( i = 0 ; i < 8 ; + + i )
usb_kill_urb ( usb - > video_urbs [ i ] ) ;
if ( go - > audio_enabled )
for ( i = 0 ; i < 8 ; + + i )
usb_kill_urb ( usb - > audio_urbs [ i ] ) ;
return 0 ;
}
static int go7007_usb_send_firmware ( struct go7007 * go , u8 * data , int len )
{
struct go7007_usb * usb = go - > hpi_context ;
int transferred , pipe ;
int timeout = 500 ;
2013-11-26 01:21:55 +08:00
pr_debug ( " DownloadBuffer sending %d bytes \n " , len ) ;
2008-02-16 08:53:09 +08:00
if ( usb - > board - > flags & GO7007_USB_EZUSB )
pipe = usb_sndbulkpipe ( usb - > usbdev , 2 ) ;
else
pipe = usb_sndbulkpipe ( usb - > usbdev , 3 ) ;
return usb_bulk_msg ( usb - > usbdev , pipe , data , len ,
& transferred , timeout ) ;
}
2013-03-11 15:48:30 +08:00
static void go7007_usb_release ( struct go7007 * go )
{
struct go7007_usb * usb = go - > hpi_context ;
struct urb * vurb , * aurb ;
int i ;
2013-03-17 20:23:25 +08:00
if ( usb - > intr_urb ) {
usb_kill_urb ( usb - > intr_urb ) ;
kfree ( usb - > intr_urb - > transfer_buffer ) ;
usb_free_urb ( usb - > intr_urb ) ;
}
2013-03-11 15:48:30 +08:00
/* Free USB-related structs */
for ( i = 0 ; i < 8 ; + + i ) {
vurb = usb - > video_urbs [ i ] ;
if ( vurb ) {
usb_kill_urb ( vurb ) ;
kfree ( vurb - > transfer_buffer ) ;
usb_free_urb ( vurb ) ;
}
aurb = usb - > audio_urbs [ i ] ;
if ( aurb ) {
usb_kill_urb ( aurb ) ;
kfree ( aurb - > transfer_buffer ) ;
usb_free_urb ( aurb ) ;
}
}
kfree ( go - > hpi_context ) ;
}
2015-12-12 00:16:48 +08:00
static const struct go7007_hpi_ops go7007_usb_ezusb_hpi_ops = {
2008-02-16 08:53:09 +08:00
. interface_reset = go7007_usb_interface_reset ,
. write_interrupt = go7007_usb_ezusb_write_interrupt ,
. read_interrupt = go7007_usb_read_interrupt ,
. stream_start = go7007_usb_stream_start ,
. stream_stop = go7007_usb_stream_stop ,
. send_firmware = go7007_usb_send_firmware ,
2013-03-11 15:48:30 +08:00
. release = go7007_usb_release ,
2008-02-16 08:53:09 +08:00
} ;
2015-12-12 00:16:48 +08:00
static const struct go7007_hpi_ops go7007_usb_onboard_hpi_ops = {
2008-02-16 08:53:09 +08:00
. interface_reset = go7007_usb_interface_reset ,
. write_interrupt = go7007_usb_onboard_write_interrupt ,
. read_interrupt = go7007_usb_read_interrupt ,
. stream_start = go7007_usb_stream_start ,
. stream_stop = go7007_usb_stream_stop ,
. send_firmware = go7007_usb_send_firmware ,
2013-03-11 15:48:30 +08:00
. release = go7007_usb_release ,
2008-02-16 08:53:09 +08:00
} ;
/********************* Driver for EZ-USB I2C adapter *********************/
static int go7007_usb_i2c_master_xfer ( struct i2c_adapter * adapter ,
struct i2c_msg msgs [ ] , int num )
{
struct go7007 * go = i2c_get_adapdata ( adapter ) ;
struct go7007_usb * usb = go - > hpi_context ;
2013-03-09 20:59:16 +08:00
u8 * buf = go - > usb_buf ;
2008-02-16 08:53:09 +08:00
int buf_len , i ;
2013-03-09 17:18:03 +08:00
int ret = - EIO ;
2008-02-16 08:53:09 +08:00
if ( go - > status = = STATUS_SHUTDOWN )
2013-03-09 17:18:03 +08:00
return - ENODEV ;
2008-02-16 08:53:09 +08:00
2009-09-15 22:07:59 +08:00
mutex_lock ( & usb - > i2c_lock ) ;
2008-02-16 08:53:09 +08:00
for ( i = 0 ; i < num ; + + i ) {
/* The hardware command is "write some bytes then read some
* bytes " , so we try to coalesce a write followed by a read
* into a single USB transaction */
if ( i + 1 < num & & msgs [ i ] . addr = = msgs [ i + 1 ] . addr & &
! ( msgs [ i ] . flags & I2C_M_RD ) & &
( msgs [ i + 1 ] . flags & I2C_M_RD ) ) {
# ifdef GO7007_I2C_DEBUG
2013-11-26 01:21:55 +08:00
pr_debug ( " i2c write/read %d/%d bytes on %02x \n " ,
2013-10-09 17:51:38 +08:00
msgs [ i ] . len , msgs [ i + 1 ] . len , msgs [ i ] . addr ) ;
2008-02-16 08:53:09 +08:00
# endif
buf [ 0 ] = 0x01 ;
buf [ 1 ] = msgs [ i ] . len + 1 ;
buf [ 2 ] = msgs [ i ] . addr < < 1 ;
memcpy ( & buf [ 3 ] , msgs [ i ] . buf , msgs [ i ] . len ) ;
buf_len = msgs [ i ] . len + 3 ;
buf [ buf_len + + ] = msgs [ + + i ] . len ;
} else if ( msgs [ i ] . flags & I2C_M_RD ) {
# ifdef GO7007_I2C_DEBUG
2013-11-26 01:21:55 +08:00
pr_debug ( " i2c read %d bytes on %02x \n " ,
2013-10-09 17:51:38 +08:00
msgs [ i ] . len , msgs [ i ] . addr ) ;
2008-02-16 08:53:09 +08:00
# endif
buf [ 0 ] = 0x01 ;
buf [ 1 ] = 1 ;
buf [ 2 ] = msgs [ i ] . addr < < 1 ;
buf [ 3 ] = msgs [ i ] . len ;
buf_len = 4 ;
} else {
# ifdef GO7007_I2C_DEBUG
2013-11-26 01:21:55 +08:00
pr_debug ( " i2c write %d bytes on %02x \n " ,
2013-10-09 17:51:38 +08:00
msgs [ i ] . len , msgs [ i ] . addr ) ;
2008-02-16 08:53:09 +08:00
# endif
buf [ 0 ] = 0x00 ;
buf [ 1 ] = msgs [ i ] . len + 1 ;
buf [ 2 ] = msgs [ i ] . addr < < 1 ;
memcpy ( & buf [ 3 ] , msgs [ i ] . buf , msgs [ i ] . len ) ;
buf_len = msgs [ i ] . len + 3 ;
buf [ buf_len + + ] = 0 ;
}
if ( go7007_usb_vendor_request ( go , 0x24 , 0 , 0 ,
buf , buf_len , 0 ) < 0 )
goto i2c_done ;
if ( msgs [ i ] . flags & I2C_M_RD ) {
2013-03-26 15:45:11 +08:00
memset ( buf , 0 , msgs [ i ] . len + 1 ) ;
2008-02-16 08:53:09 +08:00
if ( go7007_usb_vendor_request ( go , 0x25 , 0 , 0 , buf ,
msgs [ i ] . len + 1 , 1 ) < 0 )
goto i2c_done ;
memcpy ( msgs [ i ] . buf , buf + 1 , msgs [ i ] . len ) ;
}
}
2013-03-09 17:18:03 +08:00
ret = num ;
2008-02-16 08:53:09 +08:00
i2c_done :
2009-09-15 22:07:59 +08:00
mutex_unlock ( & usb - > i2c_lock ) ;
2008-02-16 08:53:09 +08:00
return ret ;
}
static u32 go7007_usb_functionality ( struct i2c_adapter * adapter )
{
/* No errors are reported by the hardware, so we don't bother
* supporting quick writes to avoid confusing probing */
return ( I2C_FUNC_SMBUS_EMUL ) & ~ I2C_FUNC_SMBUS_QUICK ;
}
2016-08-29 21:12:01 +08:00
static const struct i2c_algorithm go7007_usb_algo = {
2008-02-16 08:53:09 +08:00
. master_xfer = go7007_usb_i2c_master_xfer ,
. functionality = go7007_usb_functionality ,
} ;
static struct i2c_adapter go7007_usb_adap_templ = {
. owner = THIS_MODULE ,
. name = " WIS GO7007SB EZ-USB " ,
. algo = & go7007_usb_algo ,
} ;
/********************* USB add/remove functions *********************/
static int go7007_usb_probe ( struct usb_interface * intf ,
const struct usb_device_id * id )
{
struct go7007 * go ;
struct go7007_usb * usb ;
2013-03-17 21:56:20 +08:00
const struct go7007_usb_board * board ;
2008-02-16 08:53:09 +08:00
struct usb_device * usbdev = interface_to_usbdev ( intf ) ;
2013-03-09 20:25:47 +08:00
unsigned num_i2c_devs ;
2008-02-16 08:53:09 +08:00
char * name ;
int video_pipe , i , v_urb_len ;
2013-11-26 01:21:55 +08:00
pr_debug ( " probing new GO7007 USB board \n " ) ;
2008-02-16 08:53:09 +08:00
switch ( id - > driver_info ) {
case GO7007_BOARDID_MATRIX_II :
name = " WIS Matrix II or compatible " ;
board = & board_matrix_ii ;
break ;
case GO7007_BOARDID_MATRIX_RELOAD :
name = " WIS Matrix Reloaded or compatible " ;
board = & board_matrix_reload ;
break ;
case GO7007_BOARDID_MATRIX_REV :
name = " WIS Matrix Revolution or compatible " ;
board = & board_matrix_revolution ;
break ;
case GO7007_BOARDID_STAR_TREK :
name = " WIS Star Trek or compatible " ;
board = & board_star_trek ;
break ;
case GO7007_BOARDID_XMEN :
name = " WIS XMen or compatible " ;
board = & board_xmen ;
break ;
case GO7007_BOARDID_XMEN_II :
name = " WIS XMen II or compatible " ;
board = & board_xmen ;
break ;
case GO7007_BOARDID_XMEN_III :
name = " WIS XMen III or compatible " ;
board = & board_xmen ;
break ;
case GO7007_BOARDID_PX_M402U :
name = " Plextor PX-M402U " ;
board = & board_matrix_ii ;
break ;
2013-03-11 17:11:03 +08:00
case GO7007_BOARDID_PX_TV402U :
2008-02-16 08:53:09 +08:00
name = " Plextor PX-TV402U (unknown tuner) " ;
board = & board_px_tv402u ;
break ;
case GO7007_BOARDID_LIFEVIEW_LR192 :
2013-11-26 01:29:32 +08:00
dev_err ( & intf - > dev , " The Lifeview TV Walker Ultra is not supported. Sorry! \n " ) ;
2013-06-20 03:57:40 +08:00
return - ENODEV ;
2015-04-29 23:44:18 +08:00
#if 0
2008-02-16 08:53:09 +08:00
name = " Lifeview TV Walker Ultra " ;
board = & board_lifeview_lr192 ;
2015-04-29 23:44:18 +08:00
# endif
2008-02-16 08:53:09 +08:00
break ;
2008-10-31 03:56:41 +08:00
case GO7007_BOARDID_SENSORAY_2250 :
2013-11-26 01:29:32 +08:00
dev_info ( & intf - > dev , " Sensoray 2250 found \n " ) ;
2009-09-19 08:28:59 +08:00
name = " Sensoray 2250/2251 " ;
2008-10-31 03:56:41 +08:00
board = & board_sensoray_2250 ;
break ;
2013-03-17 21:15:03 +08:00
case GO7007_BOARDID_ADS_USBAV_709 :
name = " ADS Tech DVD Xpress DX2 " ;
board = & board_ads_usbav_709 ;
break ;
2008-02-16 08:53:09 +08:00
default :
2013-11-26 01:29:32 +08:00
dev_err ( & intf - > dev , " unknown board ID %d! \n " ,
2008-02-16 08:53:09 +08:00
( unsigned int ) id - > driver_info ) ;
2013-06-20 03:57:40 +08:00
return - ENODEV ;
2008-02-16 08:53:09 +08:00
}
2013-03-17 20:23:25 +08:00
go = go7007_alloc ( & board - > main_info , & intf - > dev ) ;
if ( go = = NULL )
2008-02-16 08:53:09 +08:00
return - ENOMEM ;
2013-03-17 20:23:25 +08:00
usb = kzalloc ( sizeof ( struct go7007_usb ) , GFP_KERNEL ) ;
if ( usb = = NULL ) {
kfree ( go ) ;
return - ENOMEM ;
}
2008-02-16 08:53:09 +08:00
usb - > board = board ;
usb - > usbdev = usbdev ;
2013-03-09 20:38:03 +08:00
usb_make_path ( usbdev , go - > bus_info , sizeof ( go - > bus_info ) ) ;
2008-02-16 08:53:09 +08:00
go - > board_id = id - > driver_info ;
strncpy ( go - > name , name , sizeof ( go - > name ) ) ;
if ( board - > flags & GO7007_USB_EZUSB )
go - > hpi_ops = & go7007_usb_ezusb_hpi_ops ;
else
go - > hpi_ops = & go7007_usb_onboard_hpi_ops ;
go - > hpi_context = usb ;
2013-03-17 20:23:25 +08:00
/* Allocate the URB and buffer for receiving incoming interrupts */
usb - > intr_urb = usb_alloc_urb ( 0 , GFP_KERNEL ) ;
if ( usb - > intr_urb = = NULL )
goto allocfail ;
usb - > intr_urb - > transfer_buffer = kmalloc ( 2 * sizeof ( u16 ) , GFP_KERNEL ) ;
if ( usb - > intr_urb - > transfer_buffer = = NULL )
goto allocfail ;
2011-11-19 02:00:15 +08:00
if ( go - > board_id = = GO7007_BOARDID_SENSORAY_2250 )
usb_fill_bulk_urb ( usb - > intr_urb , usb - > usbdev ,
usb_rcvbulkpipe ( usb - > usbdev , 4 ) ,
usb - > intr_urb - > transfer_buffer , 2 * sizeof ( u16 ) ,
go7007_usb_readinterrupt_complete , go ) ;
else
usb_fill_int_urb ( usb - > intr_urb , usb - > usbdev ,
2008-02-16 08:53:09 +08:00
usb_rcvintpipe ( usb - > usbdev , 4 ) ,
usb - > intr_urb - > transfer_buffer , 2 * sizeof ( u16 ) ,
go7007_usb_readinterrupt_complete , go , 8 ) ;
2009-11-17 02:07:42 +08:00
usb_set_intfdata ( intf , & go - > v4l2_dev ) ;
2008-02-16 08:53:09 +08:00
/* Boot the GO7007 */
if ( go7007_boot_encoder ( go , go - > board_info - > flags &
GO7007_BOARD_USE_ONBOARD_I2C ) < 0 )
2013-03-17 20:23:25 +08:00
goto allocfail ;
2008-02-16 08:53:09 +08:00
/* Register the EZ-USB I2C adapter, if we're using it */
if ( board - > flags & GO7007_USB_EZUSB_I2C ) {
memcpy ( & go - > i2c_adapter , & go7007_usb_adap_templ ,
sizeof ( go7007_usb_adap_templ ) ) ;
2009-09-15 22:07:59 +08:00
mutex_init ( & usb - > i2c_lock ) ;
2008-02-16 08:53:09 +08:00
go - > i2c_adapter . dev . parent = go - > dev ;
i2c_set_adapdata ( & go - > i2c_adapter , go ) ;
if ( i2c_add_adapter ( & go - > i2c_adapter ) < 0 ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " error: i2c_add_adapter failed \n " ) ;
2013-03-17 20:23:25 +08:00
goto allocfail ;
2008-02-16 08:53:09 +08:00
}
go - > i2c_adapter_online = 1 ;
}
/* Pelco and Adlink reused the XMen and XMen-III vendor and product
* IDs for their own incompatible designs . We can detect XMen boards
* by probing the sensor , but there is no way to probe the sensors on
* the Pelco and Adlink designs so we default to the Adlink . If it
* is actually a Pelco , the user must set the assume_endura module
* parameter . */
if ( ( go - > board_id = = GO7007_BOARDID_XMEN | |
go - > board_id = = GO7007_BOARDID_XMEN_III ) & &
go - > i2c_adapter_online ) {
union i2c_smbus_data data ;
/* Check to see if register 0x0A is 0x76 */
i2c_smbus_xfer ( & go - > i2c_adapter , 0x21 , I2C_CLIENT_SCCB ,
I2C_SMBUS_READ , 0x0A , I2C_SMBUS_BYTE_DATA , & data ) ;
if ( data . byte ! = 0x76 ) {
if ( assume_endura ) {
go - > board_id = GO7007_BOARDID_ENDURA ;
usb - > board = board = & board_endura ;
go - > board_info = & board - > main_info ;
strncpy ( go - > name , " Pelco Endura " ,
2009-09-19 08:28:59 +08:00
sizeof ( go - > name ) ) ;
2008-02-16 08:53:09 +08:00
} else {
u16 channel ;
/* read channel number from GPIO[1:0] */
go7007_read_addr ( go , 0x3c81 , & channel ) ;
channel & = 0x3 ;
go - > board_id = GO7007_BOARDID_ADLINK_MPG24 ;
usb - > board = board = & board_adlink_mpg24 ;
go - > board_info = & board - > main_info ;
go - > channel_number = channel ;
snprintf ( go - > name , sizeof ( go - > name ) ,
" Adlink PCI-MPG24, channel #%d " ,
channel ) ;
}
2013-03-11 16:50:21 +08:00
go7007_update_board ( go ) ;
2008-02-16 08:53:09 +08:00
}
}
2013-03-09 20:25:47 +08:00
num_i2c_devs = go - > board_info - > num_i2c_devs ;
2008-02-16 08:53:09 +08:00
/* Probe the tuner model on the TV402U */
2013-03-11 17:11:03 +08:00
if ( go - > board_id = = GO7007_BOARDID_PX_TV402U ) {
2008-02-16 08:53:09 +08:00
/* Board strapping indicates tuner model */
2013-10-09 17:51:20 +08:00
if ( go7007_usb_vendor_request ( go , 0x41 , 0 , 0 , go - > usb_buf , 3 ,
1 ) < 0 ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " GPIO read failed! \n " ) ;
2013-03-17 20:23:25 +08:00
goto allocfail ;
2008-02-16 08:53:09 +08:00
}
2013-03-09 20:59:16 +08:00
switch ( go - > usb_buf [ 0 ] > > 6 ) {
2008-02-16 08:53:09 +08:00
case 1 :
go - > tuner_type = TUNER_SONY_BTF_PG472Z ;
2013-03-11 16:50:21 +08:00
go - > std = V4L2_STD_PAL ;
2008-02-16 08:53:09 +08:00
strncpy ( go - > name , " Plextor PX-TV402U-EU " ,
sizeof ( go - > name ) ) ;
break ;
case 2 :
go - > tuner_type = TUNER_SONY_BTF_PK467Z ;
2013-03-11 16:50:21 +08:00
go - > std = V4L2_STD_NTSC_M_JP ;
2013-03-09 20:25:47 +08:00
num_i2c_devs - = 2 ;
2008-02-16 08:53:09 +08:00
strncpy ( go - > name , " Plextor PX-TV402U-JP " ,
sizeof ( go - > name ) ) ;
break ;
case 3 :
go - > tuner_type = TUNER_SONY_BTF_PB463Z ;
2013-03-09 20:25:47 +08:00
num_i2c_devs - = 2 ;
2008-02-16 08:53:09 +08:00
strncpy ( go - > name , " Plextor PX-TV402U-NA " ,
sizeof ( go - > name ) ) ;
break ;
default :
2013-11-26 01:21:55 +08:00
pr_debug ( " unable to detect tuner type! \n " ) ;
2008-02-16 08:53:09 +08:00
break ;
}
/* Configure tuner mode selection inputs connected
* to the EZ - USB GPIO output pins */
if ( go7007_usb_vendor_request ( go , 0x40 , 0x7f02 , 0 ,
NULL , 0 , 0 ) < 0 ) {
2013-10-21 01:26:45 +08:00
dev_err ( go - > dev , " GPIO write failed! \n " ) ;
2013-03-17 20:23:25 +08:00
goto allocfail ;
2008-02-16 08:53:09 +08:00
}
}
/* Print a nasty message if the user attempts to use a USB2.0 device in
* a USB1 .1 port . There will be silent corruption of the stream . */
if ( ( board - > flags & GO7007_USB_EZUSB ) & &
usbdev - > speed ! = USB_SPEED_HIGH )
2013-10-21 01:26:45 +08:00
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 " ) ;
2008-02-16 08:53:09 +08:00
/* Allocate the URBs and buffers for receiving the video stream */
if ( board - > flags & GO7007_USB_EZUSB ) {
v_urb_len = 1024 ;
video_pipe = usb_rcvbulkpipe ( usb - > usbdev , 6 ) ;
} else {
v_urb_len = 512 ;
video_pipe = usb_rcvbulkpipe ( usb - > usbdev , 1 ) ;
}
for ( i = 0 ; i < 8 ; + + i ) {
usb - > video_urbs [ i ] = usb_alloc_urb ( 0 , GFP_KERNEL ) ;
if ( usb - > video_urbs [ i ] = = NULL )
2013-03-17 20:23:25 +08:00
goto allocfail ;
2008-02-16 08:53:09 +08:00
usb - > video_urbs [ i ] - > transfer_buffer =
kmalloc ( v_urb_len , GFP_KERNEL ) ;
if ( usb - > video_urbs [ i ] - > transfer_buffer = = NULL )
2013-03-17 20:23:25 +08:00
goto allocfail ;
2008-02-16 08:53:09 +08:00
usb_fill_bulk_urb ( usb - > video_urbs [ i ] , usb - > usbdev , video_pipe ,
usb - > video_urbs [ i ] - > transfer_buffer , v_urb_len ,
go7007_usb_read_video_pipe_complete , go ) ;
}
/* Allocate the URBs and buffers for receiving the audio stream */
2013-03-17 20:23:25 +08:00
if ( ( board - > flags & GO7007_USB_EZUSB ) & &
2015-10-22 16:56:21 +08:00
( board - > main_info . flags & GO7007_BOARD_HAS_AUDIO ) ) {
2008-02-16 08:53:09 +08:00
for ( i = 0 ; i < 8 ; + + i ) {
usb - > audio_urbs [ i ] = usb_alloc_urb ( 0 , GFP_KERNEL ) ;
if ( usb - > audio_urbs [ i ] = = NULL )
2013-03-17 20:23:25 +08:00
goto allocfail ;
2008-02-16 08:53:09 +08:00
usb - > audio_urbs [ i ] - > transfer_buffer = kmalloc ( 4096 ,
GFP_KERNEL ) ;
if ( usb - > audio_urbs [ i ] - > transfer_buffer = = NULL )
2013-03-17 20:23:25 +08:00
goto allocfail ;
2008-02-16 08:53:09 +08:00
usb_fill_bulk_urb ( usb - > audio_urbs [ i ] , usb - > usbdev ,
usb_rcvbulkpipe ( usb - > usbdev , 8 ) ,
usb - > audio_urbs [ i ] - > transfer_buffer , 4096 ,
go7007_usb_read_audio_pipe_complete , go ) ;
}
2013-03-17 20:23:25 +08:00
}
2008-02-16 08:53:09 +08:00
2013-03-17 20:23:25 +08:00
/* Do any final GO7007 initialization, then register the
* V4L2 and ALSA interfaces */
if ( go7007_register_encoder ( go , num_i2c_devs ) < 0 )
goto allocfail ;
2008-02-16 08:53:09 +08:00
go - > status = STATUS_ONLINE ;
return 0 ;
allocfail :
2013-03-17 20:23:25 +08:00
go7007_usb_release ( go ) ;
kfree ( go ) ;
2008-02-16 08:53:09 +08:00
return - ENOMEM ;
}
static void go7007_usb_disconnect ( struct usb_interface * intf )
{
2009-11-17 02:07:42 +08:00
struct go7007 * go = to_go7007 ( usb_get_intfdata ( intf ) ) ;
2008-02-16 08:53:09 +08:00
2013-03-11 17:52:27 +08:00
mutex_lock ( & go - > queue_lock ) ;
mutex_lock ( & go - > serialize_lock ) ;
2013-03-11 15:48:30 +08:00
if ( go - > audio_enabled )
go7007_snd_remove ( go ) ;
2008-02-16 08:53:09 +08:00
2013-01-16 20:00:49 +08:00
go - > status = STATUS_SHUTDOWN ;
2013-03-11 15:48:30 +08:00
v4l2_device_disconnect ( & go - > v4l2_dev ) ;
2013-03-11 17:34:22 +08:00
video_unregister_device ( & go - > vdev ) ;
2013-03-11 17:52:27 +08:00
mutex_unlock ( & go - > serialize_lock ) ;
mutex_unlock ( & go - > queue_lock ) ;
2013-03-11 15:48:30 +08:00
v4l2_device_put ( & go - > v4l2_dev ) ;
2008-02-16 08:53:09 +08:00
}
static struct usb_driver go7007_usb_driver = {
. name = " go7007 " ,
. probe = go7007_usb_probe ,
. disconnect = go7007_usb_disconnect ,
. id_table = go7007_usb_id_table ,
} ;
2011-11-19 01:42:11 +08:00
module_usb_driver ( go7007_usb_driver ) ;
2012-02-02 11:04:02 +08:00
MODULE_LICENSE ( " GPL v2 " ) ;