pd-common.h 6.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
#ifndef PD_COMMON_H
#define PD_COMMON_H

#include <linux/version.h>
#include <linux/fs.h>
#include <linux/wait.h>
#include <linux/list.h>
#include <linux/videodev2.h>
#include <linux/semaphore.h>
#include <linux/usb.h>
#include <linux/poll.h>
#include <media/videobuf-vmalloc.h>
#include <media/v4l2-device.h>

#include "dvb_frontend.h"
#include "dvbdev.h"
#include "dvb_demux.h"
#include "dmxdev.h"

#define SBUF_NUM	8
#define MAX_BUFFER_NUM	6
#define PK_PER_URB	32
#define ISO_PKT_SIZE	3072

#define POSEIDON_STATE_NONE		(0x0000)
#define POSEIDON_STATE_ANALOG		(0x0001)
#define POSEIDON_STATE_FM		(0x0002)
#define POSEIDON_STATE_DVBT		(0x0004)
#define POSEIDON_STATE_VBI		(0x0008)
#define POSEIDON_STATE_DISCONNECT	(0x0080)

#define PM_SUSPEND_DELAY	3

#define V4L_PAL_VBI_LINES	18
#define V4L_NTSC_VBI_LINES	12
#define V4L_PAL_VBI_FRAMESIZE	(V4L_PAL_VBI_LINES * 1440 * 2)
#define V4L_NTSC_VBI_FRAMESIZE	(V4L_NTSC_VBI_LINES * 1440 * 2)

#define TUNER_FREQ_MIN		(45000000)
#define TUNER_FREQ_MAX		(862000000)

struct vbi_data {
	struct video_device	*v_dev;
	struct video_data	*video;
	struct front_face	*front;

	unsigned int		copied;
	unsigned int		vbi_size; /* the whole size of two fields */
	int 			users;
};

/*
 * This is the running context of the video, it is useful for
 * resume()
 */
struct running_context {
	u32		freq;		/* VIDIOC_S_FREQUENCY */
	int		audio_idx;	/* VIDIOC_S_TUNER    */
	v4l2_std_id	tvnormid;	/* VIDIOC_S_STD     */
	int		sig_index;	/* VIDIOC_S_INPUT  */
	struct v4l2_pix_format pix;	/* VIDIOC_S_FMT   */
};

struct video_data {
	/* v4l2 video device */
	struct video_device	*v_dev;

	/* the working context */
	struct running_context	context;

	/* for data copy */
	int		field_count;

	char		*dst;
	int		lines_copied;
	int		prev_left;

	int		lines_per_field;
	int		lines_size;

	/* for communication */
	u8			endpoint_addr;
	struct urb 		*urb_array[SBUF_NUM];
	struct vbi_data		*vbi;
	struct poseidon 	*pd;
	struct front_face	*front;

	int			is_streaming;
	int			users;

	/* for bubble handler */
	struct work_struct	bubble_work;
};

enum pcm_stream_state {
	STREAM_OFF,
	STREAM_ON,
	STREAM_SUSPEND,
};

#define AUDIO_BUFS (3)
#define CAPTURE_STREAM_EN 1
struct poseidon_audio {
	struct urb		*urb_array[AUDIO_BUFS];
	unsigned int 		copied_position;
	struct snd_pcm_substream   *capture_pcm_substream;

	unsigned int 		rcv_position;
	struct	snd_card	*card;
	int 			card_close;

	int 			users;
	int			pm_state;
	enum pcm_stream_state 	capture_stream;
};

struct radio_data {
	__u32		fm_freq;
	int		users;
	unsigned int	is_radio_streaming;
	struct video_device *fm_dev;
};

#define DVB_SBUF_NUM		4
#define DVB_URB_BUF_SIZE	0x2000
struct pd_dvb_adapter {
	struct dvb_adapter	dvb_adap;
	struct dvb_frontend	dvb_fe;
	struct dmxdev		dmxdev;
	struct dvb_demux	demux;

	atomic_t		users;
	atomic_t		active_feed;

	/* data transfer */
	s32			is_streaming;
	struct urb		*urb_array[DVB_SBUF_NUM];
	struct poseidon		*pd_device;
	u8			ep_addr;
	u8			reserved[3];

	/* data for power resume*/
	struct dvb_frontend_parameters fe_param;

	/* for channel scanning */
	int		prev_freq;
	int		bandwidth;
	unsigned long	last_jiffies;
};

struct front_face {
	/* use this field to distinguish VIDEO and VBI */
	enum v4l2_buf_type	type;

	/* for host */
	struct videobuf_queue	q;

	/* the bridge for host and device */
	struct videobuf_buffer	*curr_frame;

	/* for device */
	spinlock_t		queue_lock;
	struct list_head	active;
	struct poseidon		*pd;
};

struct poseidon {
	struct list_head	device_list;

	struct mutex		lock;
	struct kref		kref;

	/* for V4L2 */
	struct v4l2_device	v4l2_dev;

	/* hardware info */
	struct usb_device	*udev;
	struct usb_interface	*interface;
	int 			cur_transfer_mode;

	struct video_data	video_data;	/* video */
	struct vbi_data		vbi_data;	/* vbi	 */
	struct poseidon_audio	audio;		/* audio (alsa) */
	struct radio_data	radio_data;	/* FM	 */
	struct pd_dvb_adapter	dvb_data;	/* DVB	 */

	u32			state;
	int			country_code;
	struct file		*file_for_stream; /* the active stream*/

#ifdef CONFIG_PM
	int (*pm_suspend)(struct poseidon *);
	int (*pm_resume)(struct poseidon *);
	pm_message_t		msg;

	struct work_struct	pm_work;
	u8			portnum;
#endif
};

struct poseidon_format {
	char 	*name;
	int	fourcc;		 /* video4linux 2	  */
	int	depth;		 /* bit/pixel		  */
	int	flags;
};

struct poseidon_tvnorm {
	v4l2_std_id	v4l2_id;
	char		name[12];
	u32		tlg_tvnorm;
};

/* video */
int pd_video_init(struct poseidon *);
void pd_video_exit(struct poseidon *);
int stop_all_video_stream(struct poseidon *);

/* alsa audio */
int poseidon_audio_init(struct poseidon *);
int poseidon_audio_free(struct poseidon *);
#ifdef CONFIG_PM
int pm_alsa_suspend(struct poseidon *);
int pm_alsa_resume(struct poseidon *);
#endif

/* dvb */
int pd_dvb_usb_device_init(struct poseidon *);
void pd_dvb_usb_device_exit(struct poseidon *);
void pd_dvb_usb_device_cleanup(struct poseidon *);
int pd_dvb_get_adapter_num(struct pd_dvb_adapter *);
void dvb_stop_streaming(struct pd_dvb_adapter *);

/* FM */
int poseidon_fm_init(struct poseidon *);
int poseidon_fm_exit(struct poseidon *);
struct video_device *vdev_init(struct poseidon *, struct video_device *);

/* vendor command ops */
int send_set_req(struct poseidon*, u8, s32, s32*);
int send_get_req(struct poseidon*, u8, s32, void*, s32*, s32);
s32 set_tuner_mode(struct poseidon*, unsigned char);
enum tlg__analog_audio_standard get_audio_std(s32, s32);

/* bulk urb alloc/free */
int alloc_bulk_urbs_generic(struct urb **urb_array, int num,
			struct usb_device *udev, u8 ep_addr,
			int buf_size, gfp_t gfp_flags,
			usb_complete_t complete_fn, void *context);
void free_all_urb_generic(struct urb **urb_array, int num);

/* misc */
void poseidon_delete(struct kref *kref);
void destroy_video_device(struct video_device **v_dev);
extern int country_code;
extern int debug_mode;
void set_debug_mode(struct video_device *vfd, int debug_mode);

#define in_hibernation(pd) (pd->msg.event == PM_EVENT_FREEZE)
#define get_pm_count(p) (atomic_read(&(p)->interface->pm_usage_cnt))

#define log(a, ...) printk(KERN_DEBUG "\t[ %s : %.3d ] "a"\n", \
				__func__, __LINE__,  ## __VA_ARGS__)

/* for power management */
#define logpm(pd) do {\
			if (debug_mode & 0x10)\
				log();\
		} while (0)

#define logs(f) do { \
			if ((debug_mode & 0x4) && \
				(f)->type == V4L2_BUF_TYPE_VBI_CAPTURE) \
					log("type : VBI");\
								\
			if ((debug_mode & 0x8) && \
				(f)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) \
					log("type : VIDEO");\
		} while (0)
#endif