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