162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Hauppauge HD PVR USB driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2008 Janne Grunau (j@jannau.net) 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/usb.h> 962306a36Sopenharmony_ci#include <linux/i2c.h> 1062306a36Sopenharmony_ci#include <linux/mutex.h> 1162306a36Sopenharmony_ci#include <linux/workqueue.h> 1262306a36Sopenharmony_ci#include <linux/videodev2.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <media/v4l2-device.h> 1562306a36Sopenharmony_ci#include <media/v4l2-ctrls.h> 1662306a36Sopenharmony_ci#include <media/i2c/ir-kbd-i2c.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define HDPVR_MAX 8 1962306a36Sopenharmony_ci#define HDPVR_I2C_MAX_SIZE 128 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* Define these values to match your devices */ 2262306a36Sopenharmony_ci#define HD_PVR_VENDOR_ID 0x2040 2362306a36Sopenharmony_ci#define HD_PVR_PRODUCT_ID 0x4900 2462306a36Sopenharmony_ci#define HD_PVR_PRODUCT_ID1 0x4901 2562306a36Sopenharmony_ci#define HD_PVR_PRODUCT_ID2 0x4902 2662306a36Sopenharmony_ci#define HD_PVR_PRODUCT_ID4 0x4903 2762306a36Sopenharmony_ci#define HD_PVR_PRODUCT_ID3 0x4982 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#define UNSET (-1U) 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define NUM_BUFFERS 64 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#define HDPVR_FIRMWARE_VERSION 0x08 3462306a36Sopenharmony_ci#define HDPVR_FIRMWARE_VERSION_AC3 0x0d 3562306a36Sopenharmony_ci#define HDPVR_FIRMWARE_VERSION_0X12 0x12 3662306a36Sopenharmony_ci#define HDPVR_FIRMWARE_VERSION_0X15 0x15 3762306a36Sopenharmony_ci#define HDPVR_FIRMWARE_VERSION_0X1E 0x1e 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci/* #define HDPVR_DEBUG */ 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ciextern int hdpvr_debug; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#define MSG_INFO 1 4462306a36Sopenharmony_ci#define MSG_BUFFER 2 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct hdpvr_options { 4762306a36Sopenharmony_ci u8 video_std; 4862306a36Sopenharmony_ci u8 video_input; 4962306a36Sopenharmony_ci u8 audio_input; 5062306a36Sopenharmony_ci u8 bitrate; /* in 100kbps */ 5162306a36Sopenharmony_ci u8 peak_bitrate; /* in 100kbps */ 5262306a36Sopenharmony_ci u8 bitrate_mode; 5362306a36Sopenharmony_ci u8 gop_mode; 5462306a36Sopenharmony_ci enum v4l2_mpeg_audio_encoding audio_codec; 5562306a36Sopenharmony_ci u8 brightness; 5662306a36Sopenharmony_ci u8 contrast; 5762306a36Sopenharmony_ci u8 hue; 5862306a36Sopenharmony_ci u8 saturation; 5962306a36Sopenharmony_ci u8 sharpness; 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* Structure to hold all of our device specific stuff */ 6362306a36Sopenharmony_cistruct hdpvr_device { 6462306a36Sopenharmony_ci /* the v4l device for this device */ 6562306a36Sopenharmony_ci struct video_device video_dev; 6662306a36Sopenharmony_ci /* the control handler for this device */ 6762306a36Sopenharmony_ci struct v4l2_ctrl_handler hdl; 6862306a36Sopenharmony_ci /* the usb device for this device */ 6962306a36Sopenharmony_ci struct usb_device *udev; 7062306a36Sopenharmony_ci /* v4l2-device unused */ 7162306a36Sopenharmony_ci struct v4l2_device v4l2_dev; 7262306a36Sopenharmony_ci struct { /* video mode/bitrate control cluster */ 7362306a36Sopenharmony_ci struct v4l2_ctrl *video_mode; 7462306a36Sopenharmony_ci struct v4l2_ctrl *video_bitrate; 7562306a36Sopenharmony_ci struct v4l2_ctrl *video_bitrate_peak; 7662306a36Sopenharmony_ci }; 7762306a36Sopenharmony_ci /* v4l2 format */ 7862306a36Sopenharmony_ci uint width, height; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci /* the max packet size of the bulk endpoint */ 8162306a36Sopenharmony_ci size_t bulk_in_size; 8262306a36Sopenharmony_ci /* the address of the bulk in endpoint */ 8362306a36Sopenharmony_ci __u8 bulk_in_endpointAddr; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci /* holds the current device status */ 8662306a36Sopenharmony_ci __u8 status; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* holds the current set options */ 8962306a36Sopenharmony_ci struct hdpvr_options options; 9062306a36Sopenharmony_ci v4l2_std_id cur_std; 9162306a36Sopenharmony_ci struct v4l2_dv_timings cur_dv_timings; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci uint flags; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci /* synchronize I/O */ 9662306a36Sopenharmony_ci struct mutex io_mutex; 9762306a36Sopenharmony_ci /* available buffers */ 9862306a36Sopenharmony_ci struct list_head free_buff_list; 9962306a36Sopenharmony_ci /* in progress buffers */ 10062306a36Sopenharmony_ci struct list_head rec_buff_list; 10162306a36Sopenharmony_ci /* waitqueue for buffers */ 10262306a36Sopenharmony_ci wait_queue_head_t wait_buffer; 10362306a36Sopenharmony_ci /* waitqueue for data */ 10462306a36Sopenharmony_ci wait_queue_head_t wait_data; 10562306a36Sopenharmony_ci /**/ 10662306a36Sopenharmony_ci struct work_struct worker; 10762306a36Sopenharmony_ci /* current stream owner */ 10862306a36Sopenharmony_ci struct v4l2_fh *owner; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci /* I2C adapter */ 11162306a36Sopenharmony_ci struct i2c_adapter i2c_adapter; 11262306a36Sopenharmony_ci /* I2C lock */ 11362306a36Sopenharmony_ci struct mutex i2c_mutex; 11462306a36Sopenharmony_ci /* I2C message buffer space */ 11562306a36Sopenharmony_ci char i2c_buf[HDPVR_I2C_MAX_SIZE]; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci /* For passing data to ir-kbd-i2c */ 11862306a36Sopenharmony_ci struct IR_i2c_init_data ir_i2c_init_data; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci /* usb control transfer buffer and lock */ 12162306a36Sopenharmony_ci struct mutex usbc_mutex; 12262306a36Sopenharmony_ci u8 *usbc_buf; 12362306a36Sopenharmony_ci u8 fw_ver; 12462306a36Sopenharmony_ci}; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistatic inline struct hdpvr_device *to_hdpvr_dev(struct v4l2_device *v4l2_dev) 12762306a36Sopenharmony_ci{ 12862306a36Sopenharmony_ci return container_of(v4l2_dev, struct hdpvr_device, v4l2_dev); 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci/* buffer one bulk urb of data */ 13362306a36Sopenharmony_cistruct hdpvr_buffer { 13462306a36Sopenharmony_ci struct list_head buff_list; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci struct urb *urb; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci struct hdpvr_device *dev; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci uint pos; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci __u8 status; 14362306a36Sopenharmony_ci}; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci/* */ 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistruct hdpvr_video_info { 14862306a36Sopenharmony_ci u16 width; 14962306a36Sopenharmony_ci u16 height; 15062306a36Sopenharmony_ci u8 fps; 15162306a36Sopenharmony_ci bool valid; 15262306a36Sopenharmony_ci}; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cienum { 15562306a36Sopenharmony_ci STATUS_UNINITIALIZED = 0, 15662306a36Sopenharmony_ci STATUS_IDLE, 15762306a36Sopenharmony_ci STATUS_STARTING, 15862306a36Sopenharmony_ci STATUS_SHUTTING_DOWN, 15962306a36Sopenharmony_ci STATUS_STREAMING, 16062306a36Sopenharmony_ci STATUS_ERROR, 16162306a36Sopenharmony_ci STATUS_DISCONNECTED, 16262306a36Sopenharmony_ci}; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cienum { 16562306a36Sopenharmony_ci HDPVR_FLAG_AC3_CAP = 1, 16662306a36Sopenharmony_ci}; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cienum { 16962306a36Sopenharmony_ci BUFSTAT_UNINITIALIZED = 0, 17062306a36Sopenharmony_ci BUFSTAT_AVAILABLE, 17162306a36Sopenharmony_ci BUFSTAT_INPROGRESS, 17262306a36Sopenharmony_ci BUFSTAT_READY, 17362306a36Sopenharmony_ci}; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci#define CTRL_START_STREAMING_VALUE 0x0700 17662306a36Sopenharmony_ci#define CTRL_STOP_STREAMING_VALUE 0x0800 17762306a36Sopenharmony_ci#define CTRL_BITRATE_VALUE 0x1000 17862306a36Sopenharmony_ci#define CTRL_BITRATE_MODE_VALUE 0x1200 17962306a36Sopenharmony_ci#define CTRL_GOP_MODE_VALUE 0x1300 18062306a36Sopenharmony_ci#define CTRL_VIDEO_INPUT_VALUE 0x1500 18162306a36Sopenharmony_ci#define CTRL_VIDEO_STD_TYPE 0x1700 18262306a36Sopenharmony_ci#define CTRL_AUDIO_INPUT_VALUE 0x2500 18362306a36Sopenharmony_ci#define CTRL_BRIGHTNESS 0x2900 18462306a36Sopenharmony_ci#define CTRL_CONTRAST 0x2a00 18562306a36Sopenharmony_ci#define CTRL_HUE 0x2b00 18662306a36Sopenharmony_ci#define CTRL_SATURATION 0x2c00 18762306a36Sopenharmony_ci#define CTRL_SHARPNESS 0x2d00 18862306a36Sopenharmony_ci#define CTRL_LOW_PASS_FILTER_VALUE 0x3100 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci#define CTRL_DEFAULT_INDEX 0x0003 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci /* :0 s 38 01 1000 0003 0004 4 = 0a00ca00 19462306a36Sopenharmony_ci * BITRATE SETTING 19562306a36Sopenharmony_ci * 1st and 2nd byte (little endian): average bitrate in 100 000 bit/s 19662306a36Sopenharmony_ci * min: 1 mbit/s, max: 13.5 mbit/s 19762306a36Sopenharmony_ci * 3rd and 4th byte (little endian): peak bitrate in 100 000 bit/s 19862306a36Sopenharmony_ci * min: average + 100kbit/s, 19962306a36Sopenharmony_ci * max: 20.2 mbit/s 20062306a36Sopenharmony_ci */ 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci /* :0 s 38 01 1200 0003 0001 1 = 02 20362306a36Sopenharmony_ci * BIT RATE MODE 20462306a36Sopenharmony_ci * constant = 1, variable (peak) = 2, variable (average) = 3 20562306a36Sopenharmony_ci */ 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci /* :0 s 38 01 1300 0003 0001 1 = 03 20862306a36Sopenharmony_ci * GOP MODE (2 bit) 20962306a36Sopenharmony_ci * low bit 0/1: advanced/simple GOP 21062306a36Sopenharmony_ci * high bit 0/1: IDR(4/32/128) / no IDR (4/32/0) 21162306a36Sopenharmony_ci */ 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci /* :0 s 38 01 1700 0003 0001 1 = 00 21462306a36Sopenharmony_ci * VIDEO STANDARD or FREQUENCY 0 = 60hz, 1 = 50hz 21562306a36Sopenharmony_ci */ 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci /* :0 s 38 01 3100 0003 0004 4 = 03030000 21862306a36Sopenharmony_ci * FILTER CONTROL 21962306a36Sopenharmony_ci * 1st byte luma low pass filter strength, 22062306a36Sopenharmony_ci * 2nd byte chroma low pass filter strength, 22162306a36Sopenharmony_ci * 3rd byte MF enable chroma, min=0, max=1 22262306a36Sopenharmony_ci * 4th byte n 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci /* :0 s 38 b9 0001 0000 0000 0 */ 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci/* :0 s 38 d3 0000 0000 0001 1 = 00 */ 23162306a36Sopenharmony_ci/* ret = usb_control_msg(dev->udev, */ 23262306a36Sopenharmony_ci/* usb_sndctrlpipe(dev->udev, 0), */ 23362306a36Sopenharmony_ci/* 0xd3, 0x38, */ 23462306a36Sopenharmony_ci/* 0, 0, */ 23562306a36Sopenharmony_ci/* "\0", 1, */ 23662306a36Sopenharmony_ci/* 1000); */ 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci/* info("control request returned %d", ret); */ 23962306a36Sopenharmony_ci/* msleep(5000); */ 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci /* :0 s b8 81 1400 0003 0005 5 < 24362306a36Sopenharmony_ci * :0 0 5 = d0024002 19 24462306a36Sopenharmony_ci * QUERY FRAME SIZE AND RATE 24562306a36Sopenharmony_ci * 1st and 2nd byte (little endian): horizontal resolution 24662306a36Sopenharmony_ci * 3rd and 4th byte (little endian): vertical resolution 24762306a36Sopenharmony_ci * 5th byte: frame rate 24862306a36Sopenharmony_ci */ 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci /* :0 s b8 81 1800 0003 0003 3 < 25162306a36Sopenharmony_ci * :0 0 3 = 030104 25262306a36Sopenharmony_ci * QUERY SIGNAL AND DETECTED LINES, maybe INPUT 25362306a36Sopenharmony_ci */ 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cienum hdpvr_video_std { 25662306a36Sopenharmony_ci HDPVR_60HZ = 0, 25762306a36Sopenharmony_ci HDPVR_50HZ, 25862306a36Sopenharmony_ci}; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_cienum hdpvr_video_input { 26162306a36Sopenharmony_ci HDPVR_COMPONENT = 0, 26262306a36Sopenharmony_ci HDPVR_SVIDEO, 26362306a36Sopenharmony_ci HDPVR_COMPOSITE, 26462306a36Sopenharmony_ci HDPVR_VIDEO_INPUTS 26562306a36Sopenharmony_ci}; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_cienum hdpvr_audio_inputs { 26862306a36Sopenharmony_ci HDPVR_RCA_BACK = 0, 26962306a36Sopenharmony_ci HDPVR_RCA_FRONT, 27062306a36Sopenharmony_ci HDPVR_SPDIF, 27162306a36Sopenharmony_ci HDPVR_AUDIO_INPUTS 27262306a36Sopenharmony_ci}; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cienum hdpvr_bitrate_mode { 27562306a36Sopenharmony_ci HDPVR_CONSTANT = 1, 27662306a36Sopenharmony_ci HDPVR_VARIABLE_PEAK, 27762306a36Sopenharmony_ci HDPVR_VARIABLE_AVERAGE, 27862306a36Sopenharmony_ci}; 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_cienum hdpvr_gop_mode { 28162306a36Sopenharmony_ci HDPVR_ADVANCED_IDR_GOP = 0, 28262306a36Sopenharmony_ci HDPVR_SIMPLE_IDR_GOP, 28362306a36Sopenharmony_ci HDPVR_ADVANCED_NOIDR_GOP, 28462306a36Sopenharmony_ci HDPVR_SIMPLE_NOIDR_GOP, 28562306a36Sopenharmony_ci}; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_civoid hdpvr_delete(struct hdpvr_device *dev); 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci/*========================================================================*/ 29062306a36Sopenharmony_ci/* hardware control functions */ 29162306a36Sopenharmony_ciint hdpvr_set_options(struct hdpvr_device *dev); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ciint hdpvr_set_bitrate(struct hdpvr_device *dev); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ciint hdpvr_set_audio(struct hdpvr_device *dev, u8 input, 29662306a36Sopenharmony_ci enum v4l2_mpeg_audio_encoding codec); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ciint hdpvr_config_call(struct hdpvr_device *dev, uint value, 29962306a36Sopenharmony_ci unsigned char valbuf); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ciint get_video_info(struct hdpvr_device *dev, struct hdpvr_video_info *vid_info); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci/* :0 s b8 81 1800 0003 0003 3 < */ 30462306a36Sopenharmony_ci/* :0 0 3 = 0301ff */ 30562306a36Sopenharmony_ciint get_input_lines_info(struct hdpvr_device *dev); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci/*========================================================================*/ 30962306a36Sopenharmony_ci/* v4l2 registration */ 31062306a36Sopenharmony_ciint hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent, 31162306a36Sopenharmony_ci int devnumber); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ciint hdpvr_cancel_queue(struct hdpvr_device *dev); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci/*========================================================================*/ 31662306a36Sopenharmony_ci/* i2c adapter registration */ 31762306a36Sopenharmony_ciint hdpvr_register_i2c_adapter(struct hdpvr_device *dev); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_cistruct i2c_client *hdpvr_register_ir_i2c(struct hdpvr_device *dev); 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci/*========================================================================*/ 32262306a36Sopenharmony_ci/* buffer management */ 32362306a36Sopenharmony_ciint hdpvr_free_buffers(struct hdpvr_device *dev); 32462306a36Sopenharmony_ciint hdpvr_alloc_buffers(struct hdpvr_device *dev, uint count); 325