aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/video4linux/README.tlg2300198
-rw-r--r--drivers/media/video/tlg2300/pd-common.h4
-rw-r--r--drivers/media/video/tlg2300/pd-main.c36
-rw-r--r--drivers/media/video/tlg2300/pd-radio.c107
-rw-r--r--drivers/media/video/tlg2300/pd-video.c59
5 files changed, 135 insertions, 269 deletions
diff --git a/Documentation/video4linux/README.tlg2300 b/Documentation/video4linux/README.tlg2300
index 82417db..416ccb9 100644
--- a/Documentation/video4linux/README.tlg2300
+++ b/Documentation/video4linux/README.tlg2300
@@ -37,195 +37,11 @@ TESTED APPLICATIONS:
---------------------------------------------------------------------------
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
+
+ "pre_emphasis_settings=1" means that you select the 50us. If you want
+ to select the 75us, please use "pre_emphasis_settings=2"
+
-country code
- - The firmware of the chip needs the country code to determine
- 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"
diff --git a/drivers/media/video/tlg2300/pd-common.h b/drivers/media/video/tlg2300/pd-common.h
index 619fd00..ae9cb6c 100644
--- a/drivers/media/video/tlg2300/pd-common.h
+++ b/drivers/media/video/tlg2300/pd-common.h
@@ -118,6 +118,7 @@ struct radio_data {
__u32 fm_freq;
int users;
unsigned int is_radio_streaming;
+ int pre_emphasis;
struct video_device *fm_dev;
};
@@ -185,7 +186,6 @@ struct poseidon {
struct pd_dvb_adapter dvb_data; /* DVB */
u32 state;
- int country_code;
struct file *file_for_stream; /* the active stream*/
#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_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,
@@ -252,7 +251,6 @@ 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);
diff --git a/drivers/media/video/tlg2300/pd-main.c b/drivers/media/video/tlg2300/pd-main.c
index 6df9380..fdcc500 100644
--- a/drivers/media/video/tlg2300/pd-main.c
+++ b/drivers/media/video/tlg2300/pd-main.c
@@ -189,41 +189,6 @@ int set_tuner_mode(struct poseidon *pd, unsigned char mode)
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)
{
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;
logpm(pd);
- pd->country_code = 86;
mutex_init(&pd->lock);
/* register v4l2 device */
diff --git a/drivers/media/video/tlg2300/pd-radio.c b/drivers/media/video/tlg2300/pd-radio.c
index bdbb0c1..755766b 100644
--- a/drivers/media/video/tlg2300/pd-radio.c
+++ b/drivers/media/video/tlg2300/pd-radio.c
@@ -22,9 +22,16 @@ static int poseidon_fm_open(struct file *filp);
#define TUNER_FREQ_MIN_FM 76000000
#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)
{
- int ret, radiomode;
+ int ret;
u32 status;
set_current_state(TASK_INTERRUPTIBLE);
@@ -38,8 +45,8 @@ static int poseidon_check_mode_radio(struct poseidon *p)
goto out;
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, radiomode, &status);
+ ret = send_set_req(p, TUNER_AUD_ANA_STD,
+ p->radio_data.pre_emphasis, &status);
ret |= send_set_req(p, TUNER_AUD_MODE,
TLG_TUNE_TVAUDIO_MODE_STEREO, &status);
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);
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);
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)
{
__u32 freq ;
- int ret, status, radiomode;
+ int ret, status;
mutex_lock(&p->lock);
- radiomode = get_audio_std(TLG_MODE_FM_RADIO, p->country_code);
- /*NTSC 8,PAL 2 */
- ret = send_set_req(p, TUNER_AUD_ANA_STD, radiomode, &status);
+ ret = send_set_req(p, TUNER_AUD_ANA_STD,
+ p->radio_data.pre_emphasis, &status);
freq = (frequency * 125) * 500 / 1000;/* kHZ */
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,
struct v4l2_control *arg)
{
- return 0;
+ return 0;
+}
+
+int tlg_fm_vidioc_g_exts_ctrl(struct file *file, void *fh,
+ struct v4l2_ext_controls *ctrls)
+{
+ 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_exts_ctrl(struct file *file, void *fh,
- struct v4l2_ext_controls *a)
+int tlg_fm_vidioc_s_exts_ctrl(struct file *file, void *fh,
+ struct v4l2_ext_controls *ctrls)
{
- return 0;
+ 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,
- struct v4l2_control *arg)
+ struct v4l2_control *ctrl)
{
- return 0;
+ return 0;
}
int tlg_fm_vidioc_queryctrl(struct file *file, void *priv,
- struct v4l2_queryctrl *arg)
+ struct v4l2_queryctrl *ctrl)
{
- arg->minimum = 0;
- arg->maximum = 65535;
- return 0;
+ if (!(ctrl->id & V4L2_CTRL_FLAG_NEXT_CTRL))
+ return -EINVAL;
+
+ 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)
@@ -311,9 +378,11 @@ static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = {
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
.vidioc_queryctrl = tlg_fm_vidioc_queryctrl,
+ .vidioc_querymenu = tlg_fm_vidioc_querymenu,
.vidioc_g_ctrl = tlg_fm_vidioc_g_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_g_tuner = tlg_fm_vidioc_g_tuner,
.vidioc_g_frequency = fm_get_freq,
diff --git a/drivers/media/video/tlg2300/pd-video.c b/drivers/media/video/tlg2300/pd-video.c
index 5f0300a..becfba6 100644
--- a/drivers/media/video/tlg2300/pd-video.c
+++ b/drivers/media/video/tlg2300/pd-video.c
@@ -15,10 +15,6 @@ static int pm_video_suspend(struct poseidon *pd);
static int pm_video_resume(struct poseidon *pd);
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;
module_param(usb_transfer_mode, int, 0644);
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,
"brightness", 0, 10000, 1, 100, 0, },
CUST_PARM_ID_BRIGHTNESS_CTRL
- },
-
- {
+ }, {
{ V4L2_CID_CONTRAST, V4L2_CTRL_TYPE_INTEGER,
"contrast", 0, 10000, 1, 100, 0, },
CUST_PARM_ID_CONTRAST_CTRL,
- },
-
- {
+ }, {
{ V4L2_CID_HUE, V4L2_CTRL_TYPE_INTEGER,
"hue", 0, 10000, 1, 100, 0, },
CUST_PARM_ID_HUE_CTRL,
- },
-
- {
+ }, {
{ V4L2_CID_SATURATION, V4L2_CTRL_TYPE_INTEGER,
"saturation", 0, 10000, 1, 100, 0, },
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,
struct v4l2_capability *cap)
{
@@ -1067,7 +1089,7 @@ static int pd_vidioc_s_tuner(struct poseidon *pd, int index)
mutex_lock(&pd->lock);
param = pd_audio_modes[index].tlg_audio_mode;
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,
&cmd_status);
if (!ret)
@@ -1255,9 +1277,7 @@ static int vidioc_streamoff(struct file *file, void *fh,
return videobuf_streamoff(&front->q);
}
-/*
- * Set the firmware' default values : need altersetting and country code
- */
+/* Set the firmware's default values : need altersetting */
static int pd_video_checkmode(struct poseidon *pd)
{
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, VBI_DATA_SEL, 1, &cmd_status);/* enable vbi */
- /* need country code to set the audio */
- audiomode = get_audio_std(TLG_MODE_ANALOG_TV, pd->country_code);
+ /* set the audio */
+ 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_MODE,
TLG_TUNE_TVAUDIO_MODE_STEREO, &cmd_status);
@@ -1392,7 +1412,6 @@ static int pd_video_open(struct file *file)
goto out;
pd->cur_transfer_mode = usb_transfer_mode;/* bulk or iso */
- pd->country_code = country_code;
init_video_context(&pd->video_data.context);
ret = pd_video_checkmode(pd);