V4L/DVB: tlg2300: remove the country code for analog tv and radio
video : use the V4L2_STD macros to select the proper audio setting. radio : add preemphasis ctr. test it by the command: v4l2-ctl -d /dev/radio0 --set-ctrl=pre_emphasis_settings=1 [mchehab@redhat.com: folded documentation patch] Signed-off-by: Huang Shijie <shijie8@gmail.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Родитель
5b3f03f044
Коммит
007ad83036
|
@ -37,195 +37,11 @@ TESTED APPLICATIONS:
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
KNOWN PROBLEMS:
|
KNOWN PROBLEMS:
|
||||||
|
about preemphasis:
|
||||||
|
You can set the preemphasis for radio by the following command:
|
||||||
|
#v4l2-ctl -d /dev/radio0 --set-ctrl=pre_emphasis_settings=1
|
||||||
|
|
||||||
country code
|
"pre_emphasis_settings=1" means that you select the 50us. If you want
|
||||||
- The firmware of the chip needs the country code to determine
|
to select the 75us, please use "pre_emphasis_settings=2"
|
||||||
the stardards of video and audio when it runs for analog TV or radio.
|
|
||||||
The DVB-T does not need the country code.
|
|
||||||
|
|
||||||
So you must set the country-code correctly. The V4L2 does not have
|
|
||||||
the interface,the driver has to provide a parameter `country_code'.
|
|
||||||
|
|
||||||
You could set the coutry code in two ways, take USA as example
|
|
||||||
(The USA's country code is 1):
|
|
||||||
|
|
||||||
[1] add the following line in /etc/modprobe.conf before you insert the
|
|
||||||
card into USB hub's port :
|
|
||||||
poseidon country_code=1
|
|
||||||
|
|
||||||
[2] You can also modify the parameter at runtime (before you run the
|
|
||||||
application such as VLC)
|
|
||||||
#echo 1 > /sys/module/poseidon/parameter/country_code
|
|
||||||
|
|
||||||
The known country codes show below:
|
|
||||||
country code : country
|
|
||||||
93 "Afghanistan"
|
|
||||||
355 "Albania"
|
|
||||||
213 "Algeria"
|
|
||||||
684 "American Samoa"
|
|
||||||
376 "Andorra"
|
|
||||||
244 "Angola"
|
|
||||||
54 "Argentina"
|
|
||||||
374 "Armenia"
|
|
||||||
61 "Australia"
|
|
||||||
43 "Austria"
|
|
||||||
994 "Azerbaijan"
|
|
||||||
973 "Bahrain"
|
|
||||||
880 "Bangladesh"
|
|
||||||
375 "Belarus"
|
|
||||||
32 "Belgium"
|
|
||||||
501 "Belize"
|
|
||||||
229 "Benin"
|
|
||||||
591 "Bolivia"
|
|
||||||
387 "Bosnia and Herzegovina"
|
|
||||||
267 "Botswana"
|
|
||||||
55 "Brazil"
|
|
||||||
673 "Brunei Darussalam"
|
|
||||||
359 "Bulgalia"
|
|
||||||
226 "Burkina Faso"
|
|
||||||
257 "Burundi"
|
|
||||||
237 "Cameroon"
|
|
||||||
1 "Canada"
|
|
||||||
236 "Central African Republic"
|
|
||||||
235 "Chad"
|
|
||||||
56 "Chile"
|
|
||||||
86 "China"
|
|
||||||
57 "Colombia"
|
|
||||||
242 "Congo"
|
|
||||||
243 "Congo, Dem. Rep. of "
|
|
||||||
506 "Costa Rica"
|
|
||||||
385 "Croatia"
|
|
||||||
53 "Cuba or Guantanamo Bay"
|
|
||||||
357 "Cyprus"
|
|
||||||
420 "Czech Republic"
|
|
||||||
45 "Denmark"
|
|
||||||
246 "Diego Garcia"
|
|
||||||
253 "Djibouti"
|
|
||||||
593 "Ecuador"
|
|
||||||
20 "Egypt"
|
|
||||||
503 "El Salvador"
|
|
||||||
240 "Equatorial Guinea"
|
|
||||||
372 "Estonia"
|
|
||||||
251 "Ethiopia"
|
|
||||||
358 "Finland"
|
|
||||||
33 "France"
|
|
||||||
594 "French Guiana"
|
|
||||||
689 "French Polynesia"
|
|
||||||
241 "Gabonese Republic"
|
|
||||||
220 "Gambia"
|
|
||||||
995 "Georgia"
|
|
||||||
49 "Germany"
|
|
||||||
233 "Ghana"
|
|
||||||
350 "Gibraltar"
|
|
||||||
30 "Greece"
|
|
||||||
299 "Greenland"
|
|
||||||
671 "Guam"
|
|
||||||
502 "Guatemala"
|
|
||||||
592 "Guyana"
|
|
||||||
509 "Haiti"
|
|
||||||
504 "Honduras"
|
|
||||||
852 "Hong Kong SAR, China"
|
|
||||||
36 "Hungary"
|
|
||||||
354 "Iceland"
|
|
||||||
91 "India"
|
|
||||||
98 "Iran"
|
|
||||||
964 "Iraq"
|
|
||||||
353 "Ireland"
|
|
||||||
972 "Israel"
|
|
||||||
39 "Italy or Vatican City"
|
|
||||||
225 "Ivory Coast"
|
|
||||||
81 "Japan"
|
|
||||||
962 "Jordan"
|
|
||||||
7 "Kazakhstan or Kyrgyzstan"
|
|
||||||
254 "Kenya"
|
|
||||||
686 "Kiribati"
|
|
||||||
965 "Kuwait"
|
|
||||||
856 "Laos"
|
|
||||||
371 "Latvia"
|
|
||||||
961 "Lebanon"
|
|
||||||
266 "Lesotho"
|
|
||||||
231 "Liberia"
|
|
||||||
218 "Libya"
|
|
||||||
41 "Liechtenstein or Switzerland"
|
|
||||||
370 "Lithuania"
|
|
||||||
352 "Luxembourg"
|
|
||||||
853 "Macau SAR, China"
|
|
||||||
261 "Madagascar"
|
|
||||||
60 "Malaysia"
|
|
||||||
960 "Maldives"
|
|
||||||
223 "Mali Republic"
|
|
||||||
356 "Malta"
|
|
||||||
692 "Marshall Islands"
|
|
||||||
596 "Martinique"
|
|
||||||
222 "Mauritania"
|
|
||||||
230 "Mauritus"
|
|
||||||
52 "Mexico"
|
|
||||||
691 "Micronesia"
|
|
||||||
373 "Moldova"
|
|
||||||
377 "Monaco"
|
|
||||||
976 "Mongolia"
|
|
||||||
212 "Morocco"
|
|
||||||
258 "Mozambique"
|
|
||||||
95 "Myanmar"
|
|
||||||
264 "Namibia"
|
|
||||||
674 "Nauru"
|
|
||||||
31 "Netherlands"
|
|
||||||
687 "New Caledonia"
|
|
||||||
64 "New Zealand"
|
|
||||||
505 "Nicaragua"
|
|
||||||
227 "Niger"
|
|
||||||
234 "Nigeria"
|
|
||||||
850 "North Korea"
|
|
||||||
47 "Norway"
|
|
||||||
968 "Oman"
|
|
||||||
92 "Pakistan"
|
|
||||||
680 "Palau"
|
|
||||||
507 "Panama"
|
|
||||||
675 "Papua New Guinea"
|
|
||||||
595 "Paraguay"
|
|
||||||
51 "Peru"
|
|
||||||
63 "Philippines"
|
|
||||||
48 "Poland"
|
|
||||||
351 "Portugal"
|
|
||||||
974 "Qatar"
|
|
||||||
262 "Reunion Island"
|
|
||||||
40 "Romania"
|
|
||||||
7 "Russia"
|
|
||||||
378 "San Marino"
|
|
||||||
239 "Sao Tome and Principe"
|
|
||||||
966 "Saudi Arabia"
|
|
||||||
221 "Senegal"
|
|
||||||
248 "Seychelles Republic"
|
|
||||||
232 "Sierra Leone"
|
|
||||||
65 "Singapore"
|
|
||||||
421 "Slovak Republic"
|
|
||||||
386 "Slovenia"
|
|
||||||
27 "South Africa"
|
|
||||||
82 "South Korea "
|
|
||||||
34 "Spain"
|
|
||||||
94 "Sri Lanka"
|
|
||||||
508 "St. Pierre and Miquelon"
|
|
||||||
249 "Sudan"
|
|
||||||
597 "Suriname"
|
|
||||||
268 "Swaziland"
|
|
||||||
46 "Sweden"
|
|
||||||
963 "Syria"
|
|
||||||
886 "Taiwan Region"
|
|
||||||
255 "Tanzania"
|
|
||||||
66 "Thailand"
|
|
||||||
228 "Togolese Republic"
|
|
||||||
216 "Tunisia"
|
|
||||||
90 "Turkey"
|
|
||||||
993 "Turkmenistan"
|
|
||||||
256 "Uganda"
|
|
||||||
380 "Ukraine"
|
|
||||||
971 "United Arab Emirates"
|
|
||||||
44 "United Kingdom"
|
|
||||||
1 "United States of America"
|
|
||||||
598 "Uruguay"
|
|
||||||
58 "Venezuela"
|
|
||||||
84 "Vietnam"
|
|
||||||
967 "Yemen"
|
|
||||||
260 "Zambia"
|
|
||||||
255 "Zanzibar"
|
|
||||||
263 "Zimbabwe"
|
|
||||||
|
|
|
@ -118,6 +118,7 @@ struct radio_data {
|
||||||
__u32 fm_freq;
|
__u32 fm_freq;
|
||||||
int users;
|
int users;
|
||||||
unsigned int is_radio_streaming;
|
unsigned int is_radio_streaming;
|
||||||
|
int pre_emphasis;
|
||||||
struct video_device *fm_dev;
|
struct video_device *fm_dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -185,7 +186,6 @@ struct poseidon {
|
||||||
struct pd_dvb_adapter dvb_data; /* DVB */
|
struct pd_dvb_adapter dvb_data; /* DVB */
|
||||||
|
|
||||||
u32 state;
|
u32 state;
|
||||||
int country_code;
|
|
||||||
struct file *file_for_stream; /* the active stream*/
|
struct file *file_for_stream; /* the active stream*/
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM
|
||||||
|
@ -240,7 +240,6 @@ struct video_device *vdev_init(struct poseidon *, struct video_device *);
|
||||||
int send_set_req(struct poseidon*, u8, s32, s32*);
|
int send_set_req(struct poseidon*, u8, s32, s32*);
|
||||||
int send_get_req(struct poseidon*, u8, s32, void*, s32*, s32);
|
int send_get_req(struct poseidon*, u8, s32, void*, s32*, s32);
|
||||||
s32 set_tuner_mode(struct poseidon*, unsigned char);
|
s32 set_tuner_mode(struct poseidon*, unsigned char);
|
||||||
enum tlg__analog_audio_standard get_audio_std(s32, s32);
|
|
||||||
|
|
||||||
/* bulk urb alloc/free */
|
/* bulk urb alloc/free */
|
||||||
int alloc_bulk_urbs_generic(struct urb **urb_array, int num,
|
int alloc_bulk_urbs_generic(struct urb **urb_array, int num,
|
||||||
|
@ -252,7 +251,6 @@ void free_all_urb_generic(struct urb **urb_array, int num);
|
||||||
/* misc */
|
/* misc */
|
||||||
void poseidon_delete(struct kref *kref);
|
void poseidon_delete(struct kref *kref);
|
||||||
void destroy_video_device(struct video_device **v_dev);
|
void destroy_video_device(struct video_device **v_dev);
|
||||||
extern int country_code;
|
|
||||||
extern int debug_mode;
|
extern int debug_mode;
|
||||||
void set_debug_mode(struct video_device *vfd, int debug_mode);
|
void set_debug_mode(struct video_device *vfd, int debug_mode);
|
||||||
|
|
||||||
|
|
|
@ -189,41 +189,6 @@ int set_tuner_mode(struct poseidon *pd, unsigned char mode)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum tlg__analog_audio_standard get_audio_std(s32 mode, s32 country_code)
|
|
||||||
{
|
|
||||||
s32 nicam[] = {27, 32, 33, 34, 36, 44, 45, 46, 47, 48, 64,
|
|
||||||
65, 86, 351, 352, 353, 354, 358, 372, 852, 972};
|
|
||||||
s32 btsc[] = {1, 52, 54, 55, 886};
|
|
||||||
s32 eiaj[] = {81};
|
|
||||||
s32 i;
|
|
||||||
|
|
||||||
if (mode == TLG_MODE_FM_RADIO) {
|
|
||||||
if (country_code == 1)
|
|
||||||
return TLG_TUNE_ASTD_FM_US;
|
|
||||||
else
|
|
||||||
return TLG_TUNE_ASTD_FM_EUR;
|
|
||||||
} else if (mode == TLG_MODE_ANALOG_TV_UNCOMP) {
|
|
||||||
for (i = 0; i < sizeof(nicam) / sizeof(s32); i++) {
|
|
||||||
if (country_code == nicam[i])
|
|
||||||
return TLG_TUNE_ASTD_NICAM;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < sizeof(btsc) / sizeof(s32); i++) {
|
|
||||||
if (country_code == btsc[i])
|
|
||||||
return TLG_TUNE_ASTD_BTSC;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < sizeof(eiaj) / sizeof(s32); i++) {
|
|
||||||
if (country_code == eiaj[i])
|
|
||||||
return TLG_TUNE_ASTD_EIAJ;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TLG_TUNE_ASTD_A2;
|
|
||||||
} else {
|
|
||||||
return TLG_TUNE_ASTD_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void poseidon_delete(struct kref *kref)
|
void poseidon_delete(struct kref *kref)
|
||||||
{
|
{
|
||||||
struct poseidon *pd = container_of(kref, struct poseidon, kref);
|
struct poseidon *pd = container_of(kref, struct poseidon, kref);
|
||||||
|
@ -462,7 +427,6 @@ static int poseidon_probe(struct usb_interface *interface,
|
||||||
struct device *dev = &interface->dev;
|
struct device *dev = &interface->dev;
|
||||||
|
|
||||||
logpm(pd);
|
logpm(pd);
|
||||||
pd->country_code = 86;
|
|
||||||
mutex_init(&pd->lock);
|
mutex_init(&pd->lock);
|
||||||
|
|
||||||
/* register v4l2 device */
|
/* register v4l2 device */
|
||||||
|
|
|
@ -22,9 +22,16 @@ static int poseidon_fm_open(struct file *filp);
|
||||||
#define TUNER_FREQ_MIN_FM 76000000
|
#define TUNER_FREQ_MIN_FM 76000000
|
||||||
#define TUNER_FREQ_MAX_FM 108000000
|
#define TUNER_FREQ_MAX_FM 108000000
|
||||||
|
|
||||||
|
#define MAX_PREEMPHASIS (V4L2_PREEMPHASIS_75_uS + 1)
|
||||||
|
static int preemphasis[MAX_PREEMPHASIS] = {
|
||||||
|
TLG_TUNE_ASTD_NONE, /* V4L2_PREEMPHASIS_DISABLED */
|
||||||
|
TLG_TUNE_ASTD_FM_EUR, /* V4L2_PREEMPHASIS_50_uS */
|
||||||
|
TLG_TUNE_ASTD_FM_US, /* V4L2_PREEMPHASIS_75_uS */
|
||||||
|
};
|
||||||
|
|
||||||
static int poseidon_check_mode_radio(struct poseidon *p)
|
static int poseidon_check_mode_radio(struct poseidon *p)
|
||||||
{
|
{
|
||||||
int ret, radiomode;
|
int ret;
|
||||||
u32 status;
|
u32 status;
|
||||||
|
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
|
@ -38,8 +45,8 @@ static int poseidon_check_mode_radio(struct poseidon *p)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = send_set_req(p, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &status);
|
ret = send_set_req(p, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &status);
|
||||||
radiomode = get_audio_std(TLG_MODE_FM_RADIO, p->country_code);
|
ret = send_set_req(p, TUNER_AUD_ANA_STD,
|
||||||
ret = send_set_req(p, TUNER_AUD_ANA_STD, radiomode, &status);
|
p->radio_data.pre_emphasis, &status);
|
||||||
ret |= send_set_req(p, TUNER_AUD_MODE,
|
ret |= send_set_req(p, TUNER_AUD_MODE,
|
||||||
TLG_TUNE_TVAUDIO_MODE_STEREO, &status);
|
TLG_TUNE_TVAUDIO_MODE_STEREO, &status);
|
||||||
ret |= send_set_req(p, AUDIO_SAMPLE_RATE_SEL,
|
ret |= send_set_req(p, AUDIO_SAMPLE_RATE_SEL,
|
||||||
|
@ -91,7 +98,9 @@ static int poseidon_fm_open(struct file *filp)
|
||||||
|
|
||||||
usb_autopm_get_interface(p->interface);
|
usb_autopm_get_interface(p->interface);
|
||||||
if (0 == p->state) {
|
if (0 == p->state) {
|
||||||
p->country_code = country_code;
|
/* default pre-emphasis */
|
||||||
|
if (p->radio_data.pre_emphasis == 0)
|
||||||
|
p->radio_data.pre_emphasis = TLG_TUNE_ASTD_FM_EUR;
|
||||||
set_debug_mode(vfd, debug_mode);
|
set_debug_mode(vfd, debug_mode);
|
||||||
|
|
||||||
ret = poseidon_check_mode_radio(p);
|
ret = poseidon_check_mode_radio(p);
|
||||||
|
@ -205,13 +214,12 @@ int fm_get_freq(struct file *file, void *priv, struct v4l2_frequency *argp)
|
||||||
static int set_frequency(struct poseidon *p, __u32 frequency)
|
static int set_frequency(struct poseidon *p, __u32 frequency)
|
||||||
{
|
{
|
||||||
__u32 freq ;
|
__u32 freq ;
|
||||||
int ret, status, radiomode;
|
int ret, status;
|
||||||
|
|
||||||
mutex_lock(&p->lock);
|
mutex_lock(&p->lock);
|
||||||
|
|
||||||
radiomode = get_audio_std(TLG_MODE_FM_RADIO, p->country_code);
|
ret = send_set_req(p, TUNER_AUD_ANA_STD,
|
||||||
/*NTSC 8,PAL 2 */
|
p->radio_data.pre_emphasis, &status);
|
||||||
ret = send_set_req(p, TUNER_AUD_ANA_STD, radiomode, &status);
|
|
||||||
|
|
||||||
freq = (frequency * 125) * 500 / 1000;/* kHZ */
|
freq = (frequency * 125) * 500 / 1000;/* kHZ */
|
||||||
if (freq < TUNER_FREQ_MIN_FM/1000 || freq > TUNER_FREQ_MAX_FM/1000) {
|
if (freq < TUNER_FREQ_MIN_FM/1000 || freq > TUNER_FREQ_MAX_FM/1000) {
|
||||||
|
@ -253,27 +261,86 @@ int fm_set_freq(struct file *file, void *priv, struct v4l2_frequency *argp)
|
||||||
int tlg_fm_vidioc_g_ctrl(struct file *file, void *priv,
|
int tlg_fm_vidioc_g_ctrl(struct file *file, void *priv,
|
||||||
struct v4l2_control *arg)
|
struct v4l2_control *arg)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tlg_fm_vidioc_exts_ctrl(struct file *file, void *fh,
|
int tlg_fm_vidioc_g_exts_ctrl(struct file *file, void *fh,
|
||||||
struct v4l2_ext_controls *a)
|
struct v4l2_ext_controls *ctrls)
|
||||||
{
|
{
|
||||||
return 0;
|
struct poseidon *p = file->private_data;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
for (i = 0; i < ctrls->count; i++) {
|
||||||
|
struct v4l2_ext_control *ctrl = ctrls->controls + i;
|
||||||
|
|
||||||
|
if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (i < MAX_PREEMPHASIS)
|
||||||
|
ctrl->value = p->radio_data.pre_emphasis;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tlg_fm_vidioc_s_exts_ctrl(struct file *file, void *fh,
|
||||||
|
struct v4l2_ext_controls *ctrls)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (ctrls->ctrl_class != V4L2_CTRL_CLASS_FM_TX)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
for (i = 0; i < ctrls->count; i++) {
|
||||||
|
struct v4l2_ext_control *ctrl = ctrls->controls + i;
|
||||||
|
|
||||||
|
if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ctrl->value >= 0 && ctrl->value < MAX_PREEMPHASIS) {
|
||||||
|
struct poseidon *p = file->private_data;
|
||||||
|
int pre_emphasis = preemphasis[ctrl->value];
|
||||||
|
u32 status;
|
||||||
|
|
||||||
|
send_set_req(p, TUNER_AUD_ANA_STD,
|
||||||
|
pre_emphasis, &status);
|
||||||
|
p->radio_data.pre_emphasis = pre_emphasis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tlg_fm_vidioc_s_ctrl(struct file *file, void *priv,
|
int tlg_fm_vidioc_s_ctrl(struct file *file, void *priv,
|
||||||
struct v4l2_control *arg)
|
struct v4l2_control *ctrl)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tlg_fm_vidioc_queryctrl(struct file *file, void *priv,
|
int tlg_fm_vidioc_queryctrl(struct file *file, void *priv,
|
||||||
struct v4l2_queryctrl *arg)
|
struct v4l2_queryctrl *ctrl)
|
||||||
{
|
{
|
||||||
arg->minimum = 0;
|
if (!(ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL))
|
||||||
arg->maximum = 65535;
|
return -EINVAL;
|
||||||
return 0;
|
|
||||||
|
ctrl->id &= ~V4L2_CTRL_FLAG_NEXT_CTRL;
|
||||||
|
if (ctrl->id != V4L2_CID_TUNE_PREEMPHASIS) {
|
||||||
|
/* return the next supported control */
|
||||||
|
ctrl->id = V4L2_CID_TUNE_PREEMPHASIS;
|
||||||
|
v4l2_ctrl_query_fill(ctrl, V4L2_PREEMPHASIS_DISABLED,
|
||||||
|
V4L2_PREEMPHASIS_75_uS, 1,
|
||||||
|
V4L2_PREEMPHASIS_50_uS);
|
||||||
|
ctrl->flags = V4L2_CTRL_FLAG_UPDATE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tlg_fm_vidioc_querymenu(struct file *file, void *fh,
|
||||||
|
struct v4l2_querymenu *qmenu)
|
||||||
|
{
|
||||||
|
return v4l2_ctrl_query_menu(qmenu, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
|
static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
|
||||||
|
@ -311,9 +378,11 @@ static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = {
|
||||||
.vidioc_g_input = vidioc_g_input,
|
.vidioc_g_input = vidioc_g_input,
|
||||||
.vidioc_s_input = vidioc_s_input,
|
.vidioc_s_input = vidioc_s_input,
|
||||||
.vidioc_queryctrl = tlg_fm_vidioc_queryctrl,
|
.vidioc_queryctrl = tlg_fm_vidioc_queryctrl,
|
||||||
|
.vidioc_querymenu = tlg_fm_vidioc_querymenu,
|
||||||
.vidioc_g_ctrl = tlg_fm_vidioc_g_ctrl,
|
.vidioc_g_ctrl = tlg_fm_vidioc_g_ctrl,
|
||||||
.vidioc_s_ctrl = tlg_fm_vidioc_s_ctrl,
|
.vidioc_s_ctrl = tlg_fm_vidioc_s_ctrl,
|
||||||
.vidioc_s_ext_ctrls = tlg_fm_vidioc_exts_ctrl,
|
.vidioc_s_ext_ctrls = tlg_fm_vidioc_s_exts_ctrl,
|
||||||
|
.vidioc_g_ext_ctrls = tlg_fm_vidioc_g_exts_ctrl,
|
||||||
.vidioc_s_tuner = vidioc_s_tuner,
|
.vidioc_s_tuner = vidioc_s_tuner,
|
||||||
.vidioc_g_tuner = tlg_fm_vidioc_g_tuner,
|
.vidioc_g_tuner = tlg_fm_vidioc_g_tuner,
|
||||||
.vidioc_g_frequency = fm_get_freq,
|
.vidioc_g_frequency = fm_get_freq,
|
||||||
|
|
|
@ -15,10 +15,6 @@ static int pm_video_suspend(struct poseidon *pd);
|
||||||
static int pm_video_resume(struct poseidon *pd);
|
static int pm_video_resume(struct poseidon *pd);
|
||||||
static void iso_bubble_handler(struct work_struct *w);
|
static void iso_bubble_handler(struct work_struct *w);
|
||||||
|
|
||||||
int country_code = 86;
|
|
||||||
module_param(country_code, int, 0644);
|
|
||||||
MODULE_PARM_DESC(country_code, "country code (e.g China is 86)");
|
|
||||||
|
|
||||||
int usb_transfer_mode;
|
int usb_transfer_mode;
|
||||||
module_param(usb_transfer_mode, int, 0644);
|
module_param(usb_transfer_mode, int, 0644);
|
||||||
MODULE_PARM_DESC(usb_transfer_mode, "0 = Bulk, 1 = Isochronous");
|
MODULE_PARM_DESC(usb_transfer_mode, "0 = Bulk, 1 = Isochronous");
|
||||||
|
@ -93,27 +89,53 @@ static struct poseidon_control controls[] = {
|
||||||
{ V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER,
|
{ V4L2_CID_BRIGHTNESS, V4L2_CTRL_TYPE_INTEGER,
|
||||||
"brightness", 0, 10000, 1, 100, 0, },
|
"brightness", 0, 10000, 1, 100, 0, },
|
||||||
CUST_PARM_ID_BRIGHTNESS_CTRL
|
CUST_PARM_ID_BRIGHTNESS_CTRL
|
||||||
},
|
}, {
|
||||||
|
|
||||||
{
|
|
||||||
{ V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER,
|
{ V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER,
|
||||||
"contrast", 0, 10000, 1, 100, 0, },
|
"contrast", 0, 10000, 1, 100, 0, },
|
||||||
CUST_PARM_ID_CONTRAST_CTRL,
|
CUST_PARM_ID_CONTRAST_CTRL,
|
||||||
},
|
}, {
|
||||||
|
|
||||||
{
|
|
||||||
{ V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER,
|
{ V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER,
|
||||||
"hue", 0, 10000, 1, 100, 0, },
|
"hue", 0, 10000, 1, 100, 0, },
|
||||||
CUST_PARM_ID_HUE_CTRL,
|
CUST_PARM_ID_HUE_CTRL,
|
||||||
},
|
}, {
|
||||||
|
|
||||||
{
|
|
||||||
{ V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER,
|
{ V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER,
|
||||||
"saturation", 0, 10000, 1, 100, 0, },
|
"saturation", 0, 10000, 1, 100, 0, },
|
||||||
CUST_PARM_ID_SATURATION_CTRL,
|
CUST_PARM_ID_SATURATION_CTRL,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct video_std_to_audio_std {
|
||||||
|
v4l2_std_id video_std;
|
||||||
|
int audio_std;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct video_std_to_audio_std video_to_audio_map[] = {
|
||||||
|
/* country : { 27, 32, 33, 34, 36, 44, 45, 46, 47, 48, 64,
|
||||||
|
65, 86, 351, 352, 353, 354, 358, 372, 852, 972 } */
|
||||||
|
{ (V4L2_STD_PAL_I | V4L2_STD_PAL_B | V4L2_STD_PAL_D |
|
||||||
|
V4L2_STD_SECAM_L | V4L2_STD_SECAM_D), TLG_TUNE_ASTD_NICAM },
|
||||||
|
|
||||||
|
/* country : { 1, 52, 54, 55, 886 } */
|
||||||
|
{V4L2_STD_NTSC_M | V4L2_STD_PAL_N | V4L2_STD_PAL_M, TLG_TUNE_ASTD_BTSC},
|
||||||
|
|
||||||
|
/* country : { 81 } */
|
||||||
|
{ V4L2_STD_NTSC_M_JP, TLG_TUNE_ASTD_EIAJ },
|
||||||
|
|
||||||
|
/* other country : TLG_TUNE_ASTD_A2 */
|
||||||
|
};
|
||||||
|
static const unsigned int map_size = ARRAY_SIZE(video_to_audio_map);
|
||||||
|
|
||||||
|
static int get_audio_std(v4l2_std_id v4l2_std)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (; i < map_size; i++) {
|
||||||
|
if (v4l2_std & video_to_audio_map[i].video_std)
|
||||||
|
return video_to_audio_map[i].audio_std;
|
||||||
|
}
|
||||||
|
return TLG_TUNE_ASTD_A2;
|
||||||
|
}
|
||||||
|
|
||||||
static int vidioc_querycap(struct file *file, void *fh,
|
static int vidioc_querycap(struct file *file, void *fh,
|
||||||
struct v4l2_capability *cap)
|
struct v4l2_capability *cap)
|
||||||
{
|
{
|
||||||
|
@ -1067,7 +1089,7 @@ static int pd_vidioc_s_tuner(struct poseidon *pd, int index)
|
||||||
mutex_lock(&pd->lock);
|
mutex_lock(&pd->lock);
|
||||||
param = pd_audio_modes[index].tlg_audio_mode;
|
param = pd_audio_modes[index].tlg_audio_mode;
|
||||||
ret = send_set_req(pd, TUNER_AUD_MODE, param, &cmd_status);
|
ret = send_set_req(pd, TUNER_AUD_MODE, param, &cmd_status);
|
||||||
audiomode = get_audio_std(TLG_MODE_ANALOG_TV, pd->country_code);
|
audiomode = get_audio_std(pd->video_data.context.tvnormid);
|
||||||
ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode,
|
ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode,
|
||||||
&cmd_status);
|
&cmd_status);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
|
@ -1255,9 +1277,7 @@ static int vidioc_streamoff(struct file *file, void *fh,
|
||||||
return videobuf_streamoff(&front->q);
|
return videobuf_streamoff(&front->q);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Set the firmware's default values : need altersetting */
|
||||||
* Set the firmware' default values : need altersetting and country code
|
|
||||||
*/
|
|
||||||
static int pd_video_checkmode(struct poseidon *pd)
|
static int pd_video_checkmode(struct poseidon *pd)
|
||||||
{
|
{
|
||||||
s32 ret = 0, cmd_status, audiomode;
|
s32 ret = 0, cmd_status, audiomode;
|
||||||
|
@ -1286,8 +1306,8 @@ static int pd_video_checkmode(struct poseidon *pd)
|
||||||
ret |= send_set_req(pd, TUNE_FREQ_SELECT, TUNER_FREQ_MIN, &cmd_status);
|
ret |= send_set_req(pd, TUNE_FREQ_SELECT, TUNER_FREQ_MIN, &cmd_status);
|
||||||
ret |= send_set_req(pd, VBI_DATA_SEL, 1, &cmd_status);/* enable vbi */
|
ret |= send_set_req(pd, VBI_DATA_SEL, 1, &cmd_status);/* enable vbi */
|
||||||
|
|
||||||
/* need country code to set the audio */
|
/* set the audio */
|
||||||
audiomode = get_audio_std(TLG_MODE_ANALOG_TV, pd->country_code);
|
audiomode = get_audio_std(pd->video_data.context.tvnormid);
|
||||||
ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode, &cmd_status);
|
ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode, &cmd_status);
|
||||||
ret |= send_set_req(pd, TUNER_AUD_MODE,
|
ret |= send_set_req(pd, TUNER_AUD_MODE,
|
||||||
TLG_TUNE_TVAUDIO_MODE_STEREO, &cmd_status);
|
TLG_TUNE_TVAUDIO_MODE_STEREO, &cmd_status);
|
||||||
|
@ -1392,7 +1412,6 @@ static int pd_video_open(struct file *file)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
pd->cur_transfer_mode = usb_transfer_mode;/* bulk or iso */
|
pd->cur_transfer_mode = usb_transfer_mode;/* bulk or iso */
|
||||||
pd->country_code = country_code;
|
|
||||||
init_video_context(&pd->video_data.context);
|
init_video_context(&pd->video_data.context);
|
||||||
|
|
||||||
ret = pd_video_checkmode(pd);
|
ret = pd_video_checkmode(pd);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче