#ifndef PD_COMMON_H #define PD_COMMON_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 <media/v4l2-ctrls.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_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 (45000000U) #define TUNER_FREQ_MAX (862000000U) 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; struct v4l2_ctrl_handler ctrl_handler; /* 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; unsigned int is_radio_streaming; int pre_emphasis; struct video_device fm_dev; struct v4l2_ctrl_handler ctrl_handler; }; #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 dtv_frontend_properties 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; 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 *); /* 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); /* 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); extern int debug_mode; void set_debug_mode(struct video_device *vfd, int debug_mode); #ifdef CONFIG_PM #define in_hibernation(pd) (pd->msg.event == PM_EVENT_FREEZE) #else #define in_hibernation(pd) (0) #endif #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) #endif