#define EM2880_BOARD_TERRATEC_PRODIGY_XS 13
#define EM2820_BOARD_PROLINK_PLAYTV_USB2 14
#define EM2800_BOARD_VGEAR_POCKETTV 15
-#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 16
+#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_950 16
+#define EM2880_BOARD_PINNACLE_PCTV_HD_PRO 17
+#define EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900_R2 18
+#define EM2860_BOARD_POINTNIX_INTRAORAL_CAMERA 19
+#define EM2880_BOARD_AMD_ATI_TV_WONDER_HD_600 20
+#define EM2800_BOARD_GRABBEEX_USB2800 21
+#define EM2750_BOARD_UNKNOWN 22
+#define EM2750_BOARD_DLCW_130 23
+#define EM2820_BOARD_DLINK_USB_TV 24
+#define EM2820_BOARD_GADMEI_UTV310 25
+#define EM2820_BOARD_HERCULES_SMART_TV_USB2 26
+#define EM2820_BOARD_PINNACLE_USB_2_FM1216ME 27
+#define EM2820_BOARD_LEADTEK_WINFAST_USBII_DELUXE 28
+#define EM2820_BOARD_VIDEOLOGY_20K14XUSB 30
+#define EM2821_BOARD_USBGEAR_VD204 31
+#define EM2821_BOARD_SUPERCOMP_USB_2 32
+#define EM2821_BOARD_PROLINK_PLAYTV_USB2 33
+#define EM2860_BOARD_TERRATEC_HYBRID_XS 34
+#define EM2860_BOARD_TYPHOON_DVD_MAKER 35
+#define EM2860_BOARD_NETGMBH_CAM 36
+#define EM2860_BOARD_GADMEI_UTV330 37
+#define EM2861_BOARD_YAKUMO_MOVIE_MIXER 38
+#define EM2861_BOARD_KWORLD_PVRTV_300U 39
+#define EM2861_BOARD_PLEXTOR_PX_TV100U 40
+#define EM2870_BOARD_KWORLD_350U 41
+#define EM2870_BOARD_KWORLD_355U 42
+#define EM2870_BOARD_TERRATEC_XS 43
+#define EM2870_BOARD_TERRATEC_XS_MT2060 44
+#define EM2870_BOARD_PINNACLE_PCTV_DVB 45
+#define EM2870_BOARD_COMPRO_VIDEOMATE 46
+#define EM2880_BOARD_KWORLD_DVB_305U 47
+#define EM2880_BOARD_KWORLD_DVB_310U 48
+#define EM2880_BOARD_MSI_DIGIVOX_AD 49
+#define EM2880_BOARD_MSI_DIGIVOX_AD_II 50
+#define EM2880_BOARD_TERRATEC_HYBRID_XS_FR 51
+#define EM2881_BOARD_DNT_DA2_HYBRID 52
+#define EM2881_BOARD_PINNACLE_HYBRID_PRO 53
+#define EM2882_BOARD_KWORLD_VS_DVBT 54
+#define EM2882_BOARD_TERRATEC_HYBRID_XS 55
+#define EM2882_BOARD_PINNACLE_HYBRID_PRO 56
+#define EM2883_BOARD_KWORLD_HYBRID_330U 57
+#define EM2820_BOARD_COMPRO_VIDEOMATE_FORYOU 58
+#define EM2883_BOARD_HAUPPAUGE_WINTV_HVR_850 60
+#define EM2820_BOARD_PROLINK_PLAYTV_BOX4_USB2 61
+#define EM2820_BOARD_GADMEI_TVR200 62
/* Limits minimum and default number of buffers */
#define EM28XX_MIN_BUF 4
#define EM28XX_DEF_BUF 8
+/*Limits the max URB message size */
+#define URB_MAX_CTRL_SIZE 80
+
+/* Params for validated field */
+#define EM28XX_BOARD_NOT_VALIDATED 1
+#define EM28XX_BOARD_VALIDATED 0
+
/* maximum number of em28xx boards */
#define EM28XX_MAXBOARDS 4 /*FIXME: should be bigger */
#define EM2800_I2C_WRITE_TIMEOUT 20
enum em28xx_mode {
+ EM28XX_SUSPEND,
EM28XX_ANALOG_MODE,
EM28XX_DIGITAL_MODE,
};
};
+/* Struct to enumberate video formats */
struct em28xx_fmt {
char *name;
u32 fourcc; /* v4l2 format id */
+ int depth;
+ int reg;
};
/* buffer for one video frame */
EM28XX_RADIO,
};
+enum em28xx_ac97_mode {
+ EM28XX_NO_AC97 = 0,
+ EM28XX_AC97_EM202,
+ EM28XX_AC97_SIGMATEL,
+ EM28XX_AC97_OTHER,
+};
+
+struct em28xx_audio_mode {
+ enum em28xx_ac97_mode ac97;
+
+ u16 ac97_feat;
+ u32 ac97_vendor_id;
+
+ unsigned int has_audio:1;
+
+ unsigned int i2s_3rates:1;
+ unsigned int i2s_5rates:1;
+};
+
+/* em28xx has two audio inputs: tuner and line in.
+ However, on most devices, an auxiliary AC97 codec device is used.
+ The AC97 device may have several different inputs and outputs,
+ depending on their model. So, it is possible to use AC97 mixer to
+ address more than two different entries.
+ */
enum em28xx_amux {
- EM28XX_AMUX_VIDEO,
- EM28XX_AMUX_LINE_IN,
- EM28XX_AMUX_AC97_VIDEO,
- EM28XX_AMUX_AC97_LINE_IN,
+ /* This is the only entry for em28xx tuner input */
+ EM28XX_AMUX_VIDEO, /* em28xx tuner, AC97 mixer Video */
+
+ EM28XX_AMUX_LINE_IN, /* AC97 mixer Line In */
+
+ /* Some less-common mixer setups */
+ EM28XX_AMUX_VIDEO2, /* em28xx Line in, AC97 mixer Video */
+ EM28XX_AMUX_PHONE,
+ EM28XX_AMUX_MIC,
+ EM28XX_AMUX_CD,
+ EM28XX_AMUX_AUX,
+ EM28XX_AMUX_PCM_OUT,
+};
+
+enum em28xx_aout {
+ /* AC97 outputs */
+ EM28XX_AOUT_MASTER = 1 << 0,
+ EM28XX_AOUT_LINE = 1 << 1,
+ EM28XX_AOUT_MONO = 1 << 2,
+ EM28XX_AOUT_LFE = 1 << 3,
+ EM28XX_AOUT_SURR = 1 << 4,
+
+ /* PCM IN Mixer - used by AC97_RECORD_SELECT register */
+ EM28XX_AOUT_PCM_IN = 1 << 7,
+
+ /* Bits 10-8 are used to indicate the PCM IN record select */
+ EM28XX_AOUT_PCM_MIC_PCM = 0 << 8,
+ EM28XX_AOUT_PCM_CD = 1 << 8,
+ EM28XX_AOUT_PCM_VIDEO = 2 << 8,
+ EM28XX_AOUT_PCM_AUX = 3 << 8,
+ EM28XX_AOUT_PCM_LINE = 4 << 8,
+ EM28XX_AOUT_PCM_STEREO = 5 << 8,
+ EM28XX_AOUT_PCM_MONO = 6 << 8,
+ EM28XX_AOUT_PCM_PHONE = 7 << 8,
+};
+
+static inline int ac97_return_record_select(int a_out)
+{
+ return (a_out & 0x700) >> 8;
+}
+
+struct em28xx_reg_seq {
+ int reg;
+ unsigned char val, mask;
+ int sleep;
};
struct em28xx_input {
enum enum28xx_itype type;
unsigned int vmux;
enum em28xx_amux amux;
+ enum em28xx_aout aout;
+ struct em28xx_reg_seq *gpio;
};
#define INPUT(nr) (&em28xx_boards[dev->model].input[nr])
enum em28xx_decoder {
+ EM28XX_NODECODER,
EM28XX_TVP5150,
- EM28XX_SAA7113,
- EM28XX_SAA7114
-};
-
-struct em28xx_reg_seq {
- int reg;
- unsigned char val;
- int sleep;
+ EM28XX_SAA711X,
};
struct em28xx_board {
char *name;
int vchannels;
int tuner_type;
+ int tuner_addr;
/* i2c flags */
unsigned int tda9887_conf;
+ /* GPIO sequences */
+ struct em28xx_reg_seq *dvb_gpio;
+ struct em28xx_reg_seq *suspend_gpio;
+ struct em28xx_reg_seq *tuner_gpio;
+
unsigned int is_em2800:1;
unsigned int has_msp34xx:1;
unsigned int mts_firmware:1;
- unsigned int has_12mhz_i2s:1;
unsigned int max_range_640_480:1;
unsigned int has_dvb:1;
+ unsigned int has_snapshot_button:1;
+ unsigned int valid:1;
+
+ unsigned char xclk, i2c_speed;
enum em28xx_decoder decoder;
struct em28xx_input input[MAX_EM28XX_INPUT];
struct em28xx_input radio;
+ IR_KEYTAB_TYPE *ir_codes;
};
struct em28xx_eeprom {
DEV_MISCONFIGURED = 0x04,
};
-enum em28xx_capture_mode {
- EM28XX_CAPTURE_OFF = 0,
- EM28XX_ANALOG_CAPTURE,
- EM28XX_DIGITAL_CAPTURE,
-};
-
#define EM28XX_AUDIO_BUFS 5
#define EM28XX_NUM_AUDIO_PACKETS 64
#define EM28XX_AUDIO_MAX_PACKET_SIZE 196 /* static value */
char name[30]; /* name (including minor) of the device */
int model; /* index in the device_data struct */
int devno; /* marks the number of this device */
- unsigned int is_em2800:1;
- unsigned int has_msp34xx:1;
- unsigned int has_tda9887:1;
+ enum em28xx_chip_id chip_id;
+
+ struct em28xx_board board;
+
unsigned int stream_on:1; /* Locks streams */
unsigned int has_audio_class:1;
- unsigned int has_12mhz_i2s:1;
- unsigned int max_range_640_480:1;
- unsigned int has_dvb:1;
+ unsigned int has_alsa_audio:1;
+
+ struct em28xx_fmt *format;
+
+ struct em28xx_IR *ir;
/* Some older em28xx chips needs a waiting time after writing */
unsigned int wait_after_write;
- /* GPIO sequences for tuner callback */
- struct em28xx_reg_seq *analog_gpio, *digital_gpio;
-
- int video_inputs; /* number of video inputs */
struct list_head devlist;
u32 i2s_speed; /* I2S speed for audio digital stream */
- enum em28xx_decoder decoder;
+ struct em28xx_audio_mode audio_mode;
int tuner_type; /* type of the tuner */
int tuner_addr; /* tuner address */
v4l2_std_id norm; /* selected tv norm */
int ctl_freq; /* selected frequency */
unsigned int ctl_input; /* selected input */
- unsigned int ctl_ainput; /* slected audio input */
+ unsigned int ctl_ainput;/* selected audio input */
+ unsigned int ctl_aoutput;/* selected audio output */
int mute;
int volume;
/* frame properties */
int width; /* current frame width */
int height; /* current frame height */
- int hscale; /* horizontal scale factor (see datasheet) */
- int vscale; /* vertical scale factor (see datasheet) */
+ unsigned hscale; /* horizontal scale factor (see datasheet) */
+ unsigned vscale; /* vertical scale factor (see datasheet) */
int interlaced; /* 1=interlace fileds, 0=just top fileds */
unsigned int video_bytesread; /* Number of bytes read */
unsigned long i2c_hash; /* i2c devicelist hash -
for boards with generic ID */
- struct em28xx_audio *adev;
+ struct em28xx_audio adev;
/* states */
enum em28xx_dev_state state;
/* locks */
struct mutex lock;
+ struct mutex ctrl_urb_lock; /* protects urb_buf */
/* spinlock_t queue_lock; */
struct list_head inqueue, outqueue;
wait_queue_head_t open, wait_frame, wait_stream;
unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
struct urb *urb[EM28XX_NUM_BUFS]; /* urb for isoc transfers */
char *transfer_buffer[EM28XX_NUM_BUFS]; /* transfer buffers for isoc transfer */
+ char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */
+
/* helper funcs that call usb_control_msg */
int (*em28xx_write_regs) (struct em28xx *dev, u16 reg,
char *buf, int len);
enum em28xx_mode mode;
+ /* register numbers for GPO/GPIO registers */
+ u16 reg_gpo_num, reg_gpio_num;
+
+ /* Caches GPO and GPIO registers */
+ unsigned char reg_gpo, reg_gpio;
+
+ /* Snapshot button */
+ char snapshot_button_path[30]; /* path of the input dev */
+ struct input_dev *sbutton_input_dev;
+ struct delayed_work sbutton_query_work;
+
struct em28xx_dvb *dvb;
};
int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
int len);
int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len);
+int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val);
+
+int em28xx_read_ac97(struct em28xx *dev, u8 reg);
+int em28xx_write_ac97(struct em28xx *dev, u8 reg, u16 val);
+
int em28xx_audio_analog_set(struct em28xx *dev);
+int em28xx_audio_setup(struct em28xx *dev);
int em28xx_colorlevels_set_default(struct em28xx *dev);
int em28xx_capture_start(struct em28xx *dev, int start);
-int em28xx_outfmt_set_yuv422(struct em28xx *dev);
+int em28xx_set_outfmt(struct em28xx *dev);
int em28xx_resolution_set(struct em28xx *dev);
int em28xx_set_alternate(struct em28xx *dev);
int em28xx_init_isoc(struct em28xx *dev, int max_packets,
int num_bufs, int max_pkt_size,
- int (*isoc_copy) (struct em28xx *dev, struct urb *urb),
- int cap_type);
+ int (*isoc_copy) (struct em28xx *dev, struct urb *urb));
void em28xx_uninit_isoc(struct em28xx *dev);
-
-/* Provided by em28xx-video.c */
+int em28xx_set_mode(struct em28xx *dev, enum em28xx_mode set_mode);
+int em28xx_gpio_set(struct em28xx *dev, struct em28xx_reg_seq *gpio);
+void em28xx_wake_i2c(struct em28xx *dev);
+void em28xx_remove_from_devlist(struct em28xx *dev);
+void em28xx_add_into_devlist(struct em28xx *dev);
+struct em28xx *em28xx_get_device(int minor,
+ enum v4l2_buf_type *fh_type,
+ int *has_radio);
int em28xx_register_extension(struct em28xx_ops *dev);
void em28xx_unregister_extension(struct em28xx_ops *dev);
+void em28xx_init_extension(struct em28xx *dev);
+void em28xx_close_extension(struct em28xx *dev);
+
+/* Provided by em28xx-video.c */
+int em28xx_register_analog_devices(struct em28xx *dev);
+void em28xx_release_analog_resources(struct em28xx *dev);
/* Provided by em28xx-cards.c */
extern int em2800_variant_detect(struct usb_device *udev, int model);
extern struct usb_device_id em28xx_id_table[];
extern const unsigned int em28xx_bcount;
void em28xx_set_ir(struct em28xx *dev, struct IR_i2c *ir);
-int em28xx_tuner_callback(void *ptr, int command, int arg);
-void em28xx_setup_xc3028(struct em28xx *dev, struct xc2028_ctrl *ctl);
+int em28xx_tuner_callback(void *ptr, int component, int command, int arg);
+void em28xx_release_resources(struct em28xx *dev);
/* Provided by em28xx-input.c */
-/* TODO: Check if the standard get_key handlers on ir-common can be used */
int em28xx_get_key_terratec(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
int em28xx_get_key_em_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw);
int em28xx_get_key_pinnacle_usb_grey(struct IR_i2c *ir, u32 *ir_key,
u32 *ir_raw);
+void em28xx_register_snapshot_button(struct em28xx *dev);
+void em28xx_deregister_snapshot_button(struct em28xx *dev);
+
+int em28xx_ir_init(struct em28xx *dev);
+int em28xx_ir_fini(struct em28xx *dev);
/* printk macros */
static inline int em28xx_compression_disable(struct em28xx *dev)
{
/* side effect of disabling scaler and mixer */
- return em28xx_write_regs(dev, COMPR_REG, "\x00", 1);
+ return em28xx_write_reg(dev, EM28XX_R26_COMPR, 0x00);
}
static inline int em28xx_contrast_get(struct em28xx *dev)
{
- return em28xx_read_reg(dev, YGAIN_REG) & 0x1f;
+ return em28xx_read_reg(dev, EM28XX_R20_YGAIN) & 0x1f;
}
static inline int em28xx_brightness_get(struct em28xx *dev)
{
- return em28xx_read_reg(dev, YOFFSET_REG);
+ return em28xx_read_reg(dev, EM28XX_R21_YOFFSET);
}
static inline int em28xx_saturation_get(struct em28xx *dev)
{
- return em28xx_read_reg(dev, UVGAIN_REG) & 0x1f;
+ return em28xx_read_reg(dev, EM28XX_R22_UVGAIN) & 0x1f;
}
static inline int em28xx_u_balance_get(struct em28xx *dev)
{
- return em28xx_read_reg(dev, UOFFSET_REG);
+ return em28xx_read_reg(dev, EM28XX_R23_UOFFSET);
}
static inline int em28xx_v_balance_get(struct em28xx *dev)
{
- return em28xx_read_reg(dev, VOFFSET_REG);
+ return em28xx_read_reg(dev, EM28XX_R24_VOFFSET);
}
static inline int em28xx_gamma_get(struct em28xx *dev)
{
- return em28xx_read_reg(dev, GAMMA_REG) & 0x3f;
+ return em28xx_read_reg(dev, EM28XX_R14_GAMMA) & 0x3f;
}
static inline int em28xx_contrast_set(struct em28xx *dev, s32 val)
{
u8 tmp = (u8) val;
- return em28xx_write_regs(dev, YGAIN_REG, &tmp, 1);
+ return em28xx_write_regs(dev, EM28XX_R20_YGAIN, &tmp, 1);
}
static inline int em28xx_brightness_set(struct em28xx *dev, s32 val)
{
u8 tmp = (u8) val;
- return em28xx_write_regs(dev, YOFFSET_REG, &tmp, 1);
+ return em28xx_write_regs(dev, EM28XX_R21_YOFFSET, &tmp, 1);
}
static inline int em28xx_saturation_set(struct em28xx *dev, s32 val)
{
u8 tmp = (u8) val;
- return em28xx_write_regs(dev, UVGAIN_REG, &tmp, 1);
+ return em28xx_write_regs(dev, EM28XX_R22_UVGAIN, &tmp, 1);
}
static inline int em28xx_u_balance_set(struct em28xx *dev, s32 val)
{
u8 tmp = (u8) val;
- return em28xx_write_regs(dev, UOFFSET_REG, &tmp, 1);
+ return em28xx_write_regs(dev, EM28XX_R23_UOFFSET, &tmp, 1);
}
static inline int em28xx_v_balance_set(struct em28xx *dev, s32 val)
{
u8 tmp = (u8) val;
- return em28xx_write_regs(dev, VOFFSET_REG, &tmp, 1);
+ return em28xx_write_regs(dev, EM28XX_R24_VOFFSET, &tmp, 1);
}
static inline int em28xx_gamma_set(struct em28xx *dev, s32 val)
{
u8 tmp = (u8) val;
- return em28xx_write_regs(dev, GAMMA_REG, &tmp, 1);
+ return em28xx_write_regs(dev, EM28XX_R14_GAMMA, &tmp, 1);
}
/*FIXME: maxw should be dependent of alt mode */
static inline unsigned int norm_maxw(struct em28xx *dev)
{
- if (dev->max_range_640_480)
+ if (dev->board.max_range_640_480)
return 640;
else
return 720;
static inline unsigned int norm_maxh(struct em28xx *dev)
{
- if (dev->max_range_640_480)
+ if (dev->board.max_range_640_480)
return 480;
else
return (dev->norm & V4L2_STD_625_50) ? 576 : 480;