linux/drivers/media/usb/em28xx/em28xx-cards.c

// SPDX-License-Identifier: GPL-2.0+
//
// em28xx-cards.c - driver for Empia EM2800/EM2820/2840 USB
//		    video capture devices
//
// Copyright (C) 2005 Ludovico Cavedon <[email protected]>
//		      Markus Rechberger <[email protected]>
//		      Mauro Carvalho Chehab <[email protected]>
//		      Sascha Sommer <[email protected]>
// Copyright (C) 2012 Frank Schäfer <[email protected]>

#include "em28xx.h"

#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/usb.h>
#include <media/tuner.h>
#include <media/drv-intf/msp3400.h>
#include <media/i2c/saa7115.h>
#include <dt-bindings/media/tvp5150.h>
#include <media/i2c/tvaudio.h>
#include <media/tveeprom.h>
#include <media/v4l2-common.h>
#include <sound/ac97_codec.h>

#define DRIVER_NAME

static int tuner =;
module_param(tuner, int, 0444);
MODULE_PARM_DESC();

static unsigned int disable_ir;
module_param(disable_ir, int, 0444);
MODULE_PARM_DESC();

static unsigned int disable_usb_speed_check;
module_param(disable_usb_speed_check, int, 0444);
MODULE_PARM_DESC();

static unsigned int card[]     =;
module_param_array();
MODULE_PARM_DESC();

static int usb_xfer_mode =;
module_param(usb_xfer_mode, int, 0444);
MODULE_PARM_DESC();

/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS - 1 */
static DECLARE_BITMAP(em28xx_devused, EM28XX_MAXBOARDS);

struct em28xx_hash_table {};

static void em28xx_pre_card_setup(struct em28xx *dev);

/*
 *  Reset sequences for analog/digital modes
 */

/* Reset for the most [analog] boards */
static const struct em28xx_reg_seq default_analog[] =;

/* Reset for the most [digital] boards */
static const struct em28xx_reg_seq default_digital[] =;

/* Board :Zolid Hybrid Tv Stick */
static struct em28xx_reg_seq zolid_tuner[] =;

static struct em28xx_reg_seq zolid_digital[] =;

/* Board Hauppauge WinTV HVR 900 analog */
static const struct em28xx_reg_seq hauppauge_wintv_hvr_900_analog[] =;

/* Board Hauppauge WinTV HVR 900 digital */
static const struct em28xx_reg_seq hauppauge_wintv_hvr_900_digital[] =;

/* Board Hauppauge WinTV HVR 900 (R2) digital */
static const struct em28xx_reg_seq hauppauge_wintv_hvr_900R2_digital[] =;

/* Boards - EM2880 MSI DIGIVOX AD and EM2880_BOARD_MSI_DIGIVOX_AD_II */
static const struct em28xx_reg_seq em2880_msi_digivox_ad_analog[] =;

/* Board - EM2882 Kworld 315U digital */
static const struct em28xx_reg_seq em2882_kworld_315u_digital[] =;

static const struct em28xx_reg_seq em2882_kworld_315u_tuner_gpio[] =;

static const struct em28xx_reg_seq kworld_330u_analog[] =;

static const struct em28xx_reg_seq kworld_330u_digital[] =;

/*
 * Evga inDtube
 * GPIO0 - Enable digital power (s5h1409) - low to enable
 * GPIO1 - Enable analog power (tvp5150/emp202) - low to enable
 * GPIO4 - xc3028 reset
 * GOP3  - s5h1409 reset
 */
static const struct em28xx_reg_seq evga_indtube_analog[] =;

static const struct em28xx_reg_seq evga_indtube_digital[] =;

/*
 * KWorld PlusTV 340U, UB435-Q and UB435-Q V2 (ATSC) GPIOs map:
 * EM_GPIO_0 - currently unknown
 * EM_GPIO_1 - LED disable/enable (1 = off, 0 = on)
 * EM_GPIO_2 - currently unknown
 * EM_GPIO_3 - currently unknown
 * EM_GPIO_4 - TDA18271HD/C1 tuner (1 = active, 0 = in reset)
 * EM_GPIO_5 - LGDT3304 ATSC/QAM demod (1 = active, 0 = in reset)
 * EM_GPIO_6 - currently unknown
 * EM_GPIO_7 - currently unknown
 */
static const struct em28xx_reg_seq kworld_a340_digital[] =;

static const struct em28xx_reg_seq kworld_ub435q_v3_digital[] =;

/* Pinnacle Hybrid Pro eb1a:2881 */
static const struct em28xx_reg_seq pinnacle_hybrid_pro_analog[] =;

static const struct em28xx_reg_seq pinnacle_hybrid_pro_digital[] =;

static const struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_analog[] =;

static const struct em28xx_reg_seq terratec_cinergy_USB_XS_FR_digital[] =;

/*
 * PCTV HD Mini (80e) GPIOs
 * 0-5: not used
 * 6:   demod reset, active low
 * 7:   LED on, active high
 */
static const struct em28xx_reg_seq em2874_pctv_80e_digital[] =;

/*
 * eb1a:2868 Reddo DVB-C USB TV Box
 * GPIO4 - CU1216L NIM
 * Other GPIOs seems to be don't care.
 */
static const struct em28xx_reg_seq reddo_dvb_c_usb_box[] =;

/* Callback for the most boards */
static const struct em28xx_reg_seq default_tuner_gpio[] =;

/* Mute/unmute */
static const struct em28xx_reg_seq compro_unmute_tv_gpio[] =;

static const struct em28xx_reg_seq compro_unmute_svid_gpio[] =;

static const struct em28xx_reg_seq compro_mute_gpio[] =;

/* Terratec AV350 */
static const struct em28xx_reg_seq terratec_av350_mute_gpio[] =;

static const struct em28xx_reg_seq terratec_av350_unmute_gpio[] =;

static const struct em28xx_reg_seq silvercrest_reg_seq[] =;

static const struct em28xx_reg_seq vc211a_enable[] =;

static const struct em28xx_reg_seq dikom_dk300_digital[] =;

/* Reset for the most [digital] boards */
static const struct em28xx_reg_seq leadership_digital[] =;

static const struct em28xx_reg_seq leadership_reset[] =;

/*
 * 2013:024f PCTV nanoStick T2 290e
 * GPIO_6 - demod reset
 * GPIO_7 - LED
 */
static const struct em28xx_reg_seq pctv_290e[] =;

#if 0
static const struct em28xx_reg_seq terratec_h5_gpio[] = {
	{EM2820_R08_GPIO_CTRL,		0xff,	0xff,	10},
	{EM2874_R80_GPIO_P0_CTRL,	0xf6,	0xff,	100},
	{EM2874_R80_GPIO_P0_CTRL,	0xf2,	0xff,	50},
	{EM2874_R80_GPIO_P0_CTRL,	0xf6,	0xff,	50},
	{	-1,			-1,	-1,	-1},
};

static const struct em28xx_reg_seq terratec_h5_digital[] = {
	{EM2874_R80_GPIO_P0_CTRL,	0xf6,	0xff,	10},
	{EM2874_R80_GPIO_P0_CTRL,	0xe6,	0xff,	100},
	{EM2874_R80_GPIO_P0_CTRL,	0xa6,	0xff,	10},
	{	-1,			-1,	-1,	-1},
};
#endif

/*
 * 2013:024f PCTV DVB-S2 Stick 460e
 * GPIO_0 - POWER_ON
 * GPIO_1 - BOOST
 * GPIO_2 - VUV_LNB (red LED)
 * GPIO_3 - EXT_12V
 * GPIO_4 - INT_DEM (DEMOD GPIO_0)
 * GPIO_5 - INT_LNB
 * GPIO_6 - RESET_DEM
 * GPIO_7 - LED (green LED)
 */
static const struct em28xx_reg_seq pctv_460e[] =;

static const struct em28xx_reg_seq c3tech_digital_duo_digital[] =;

/*
 * 2013:0258 PCTV DVB-S2 Stick (461e)
 * GPIO 0 = POWER_ON
 * GPIO 1 = BOOST
 * GPIO 2 = VUV_LNB (red LED)
 * GPIO 3 = #EXT_12V
 * GPIO 4 = INT_DEM
 * GPIO 5 = INT_LNB
 * GPIO 6 = #RESET_DEM
 * GPIO 7 = P07_LED (green LED)
 */
static const struct em28xx_reg_seq pctv_461e[] =;

#if 0
static const struct em28xx_reg_seq hauppauge_930c_gpio[] = {
	{EM2874_R80_GPIO_P0_CTRL,	0x6f,	0xff,	10},
	{EM2874_R80_GPIO_P0_CTRL,	0x4f,	0xff,	10}, /* xc5000 reset */
	{EM2874_R80_GPIO_P0_CTRL,	0x6f,	0xff,	10},
	{EM2874_R80_GPIO_P0_CTRL,	0x4f,	0xff,	10},
	{	-1,			-1,	-1,	-1},
};

static const struct em28xx_reg_seq hauppauge_930c_digital[] = {
	{EM2874_R80_GPIO_P0_CTRL,	0xf6,	0xff,	10},
	{EM2874_R80_GPIO_P0_CTRL,	0xe6,	0xff,	100},
	{EM2874_R80_GPIO_P0_CTRL,	0xa6,	0xff,	10},
	{	-1,			-1,	-1,	-1},
};
#endif

/*
 * 1b80:e425 MaxMedia UB425-TC
 * 1b80:e1cc Delock 61959
 * GPIO_6 - demod reset, 0=active
 * GPIO_7 - LED, 0=active
 */
static const struct em28xx_reg_seq maxmedia_ub425_tc[] =;

/*
 * 2304:0242 PCTV QuatroStick (510e)
 * GPIO_2: decoder reset, 0=active
 * GPIO_4: decoder suspend, 0=active
 * GPIO_6: demod reset, 0=active
 * GPIO_7: LED, 1=active
 */
static const struct em28xx_reg_seq pctv_510e[] =;

/*
 * 2013:0251 PCTV QuatroStick nano (520e)
 * GPIO_2: decoder reset, 0=active
 * GPIO_4: decoder suspend, 0=active
 * GPIO_6: demod reset, 0=active
 * GPIO_7: LED, 1=active
 */
static const struct em28xx_reg_seq pctv_520e[] =;

/*
 * 1ae7:9003/9004 SpeedLink Vicious And Devine Laplace webcam
 * reg 0x80/0x84:
 * GPIO_0: capturing LED, 0=on, 1=off
 * GPIO_2: AV mute button, 0=pressed, 1=unpressed
 * GPIO 3: illumination button, 0=pressed, 1=unpressed
 * GPIO_6: illumination/flash LED, 0=on, 1=off
 * reg 0x81/0x85:
 * GPIO_7: snapshot button, 0=pressed, 1=unpressed
 */
static const struct em28xx_reg_seq speedlink_vad_laplace_reg_seq[] =;

static const struct em28xx_reg_seq pctv_292e[] =;

static const struct em28xx_reg_seq terratec_t2_stick_hd[] =;

static const struct em28xx_reg_seq plex_px_bcud[] =;

/*
 * 2040:0265 Hauppauge WinTV-dualHD DVB Isoc
 * 2040:8265 Hauppauge WinTV-dualHD DVB Bulk
 * 2040:026d Hauppauge WinTV-dualHD ATSC/QAM Isoc
 * 2040:826d Hauppauge WinTV-dualHD ATSC/QAM Bulk
 * reg 0x80/0x84:
 * GPIO_0: Yellow LED tuner 1, 0=on, 1=off
 * GPIO_1: Green LED tuner 1, 0=on, 1=off
 * GPIO_2: Yellow LED tuner 2, 0=on, 1=off
 * GPIO_3: Green LED tuner 2, 0=on, 1=off
 * GPIO_5: Reset #2, 0=active
 * GPIO_6: Reset #1, 0=active
 */
static const struct em28xx_reg_seq hauppauge_dualhd_dvb[] =;

/* Hauppauge USB QuadHD */
static struct em28xx_reg_seq hauppauge_usb_quadhd_atsc_reg_seq[] =;

/*
 * MyGica USB TV Box
 * GPIO_1,0: 00=Composite audio
 *           01=Tuner audio
 *           10=Mute audio
 *           11=FM radio? (if equipped)
 * GPIO_2-6: Unused
 * GPIO_7:   ??
 */
static const struct em28xx_reg_seq mygica_utv3_composite_audio_gpio[] =;

static const struct em28xx_reg_seq mygica_utv3_tuner_audio_gpio[] =;

static const struct em28xx_reg_seq mygica_utv3_suspend_gpio[] =;

/*
 *  Button definitions
 */
static const struct em28xx_button std_snapshot_button[] =;

static const struct em28xx_button speedlink_vad_laplace_buttons[] =;

/*
 *  LED definitions
 */
static struct em28xx_led speedlink_vad_laplace_leds[] =;

static struct em28xx_led kworld_ub435q_v3_leds[] =;

static struct em28xx_led pctv_80e_leds[] =;

static struct em28xx_led terratec_grabby_leds[] =;

static struct em28xx_led hauppauge_dualhd_leds[] =;

static struct em28xx_led hauppauge_usb_quadhd_leds[] =;

/*
 *  Board definitions
 */
const struct em28xx_board em28xx_boards[] =;
EXPORT_SYMBOL_GPL();

static const unsigned int em28xx_bcount =;

/* table of devices that work with this driver */
struct usb_device_id em28xx_id_table[] =;
MODULE_DEVICE_TABLE(usb, em28xx_id_table);

/*
 * EEPROM hash table for devices with generic USB IDs
 */
static const struct em28xx_hash_table em28xx_eeprom_hash[] =;

/* I2C devicelist hash table for devices with generic USB IDs */
static const struct em28xx_hash_table em28xx_i2c_hash[] =;

/* NOTE: introduce a separate hash table for devices with 16 bit eeproms */

int em28xx_tuner_callback(void *ptr, int component, int command, int arg)
{}
EXPORT_SYMBOL_GPL();

static inline void em28xx_set_xclk_i2c_speed(struct em28xx *dev)
{}

static inline void em28xx_set_model(struct em28xx *dev)
{}

/*
 * Wait until AC97_RESET reports the expected value reliably before proceeding.
 * We also check that two unrelated registers accesses don't return the same
 * value to avoid premature return.
 * This procedure helps ensuring AC97 register accesses are reliable.
 */
static int em28xx_wait_until_ac97_features_equals(struct em28xx *dev,
						  int expected_feat)
{}

/*
 * Since em28xx_pre_card_setup() requires a proper dev->model,
 * this won't work for boards with generic PCI IDs
 */
static void em28xx_pre_card_setup(struct em28xx *dev)
{}

static int em28xx_hint_board(struct em28xx *dev)
{}

static void em28xx_card_setup(struct em28xx *dev)
{}

void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl)
{}
EXPORT_SYMBOL_GPL();

static void request_module_async(struct work_struct *work)
{}

static void request_modules(struct em28xx *dev)
{}

static void flush_request_modules(struct em28xx *dev)
{}

static int em28xx_media_device_init(struct em28xx *dev,
				    struct usb_device *udev)
{}

static void em28xx_unregister_media_device(struct em28xx *dev)
{}

/*
 * em28xx_release_resources()
 * unregisters the v4l2,i2c and usb devices
 * called when the device gets disconnected or at module unload
 */
static void em28xx_release_resources(struct em28xx *dev)
{
	struct usb_device *udev = interface_to_usbdev(dev->intf);

	/*FIXME: I2C IR should be disconnected */

	mutex_lock(&dev->lock);

	em28xx_unregister_media_device(dev);

	if (dev->def_i2c_bus)
		em28xx_i2c_unregister(dev, 1);
	em28xx_i2c_unregister(dev, 0);

	if (dev->ts == PRIMARY_TS)
		usb_put_dev(udev);

	/* Mark device as unused */
	clear_bit(dev->devno, em28xx_devused);

	mutex_unlock(&dev->lock);
};

/**
 * em28xx_free_device() - Free em28xx device
 *
 * @ref: struct kref for em28xx device
 *
 * This is called when all extensions and em28xx core unregisters a device
 */
void em28xx_free_device(struct kref *ref)
{}
EXPORT_SYMBOL_GPL();

/*
 * em28xx_init_dev()
 * allocates and inits the device structs, registers i2c bus and v4l device
 */
static int em28xx_init_dev(struct em28xx *dev, struct usb_device *udev,
			   struct usb_interface *intf,
			   int minor)
{}

static int em28xx_duplicate_dev(struct em28xx *dev)
{}

/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
#define hb_mult(wMaxPacketSize)

static void em28xx_check_usb_descriptor(struct em28xx *dev,
					struct usb_device *udev,
					struct usb_interface *intf,
					int alt, int ep,
					bool *has_vendor_audio,
					bool *has_video,
					bool *has_dvb)
{}

/*
 * em28xx_usb_probe()
 * checks for supported devices
 */
static int em28xx_usb_probe(struct usb_interface *intf,
			    const struct usb_device_id *id)
{}

/*
 * em28xx_usb_disconnect()
 * called when the device gets disconnected
 * video device will be unregistered on v4l2_close in case it is still open
 */
static void em28xx_usb_disconnect(struct usb_interface *intf)
{}

static int em28xx_usb_suspend(struct usb_interface *intf,
			      pm_message_t message)
{}

static int em28xx_usb_resume(struct usb_interface *intf)
{}

static struct usb_driver em28xx_usb_driver =;

module_usb_driver();