V4L/DVB: tlg2300: remove the country code for analog tv and radio
authorHuang Shijie <shijie8@gmail.com>
Thu, 11 Feb 2010 06:53:51 +0000 (03:53 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Fri, 26 Feb 2010 18:10:58 +0000 (15:10 -0300)
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>
Documentation/video4linux/README.tlg2300
drivers/media/video/tlg2300/pd-common.h
drivers/media/video/tlg2300/pd-main.c
drivers/media/video/tlg2300/pd-radio.c
drivers/media/video/tlg2300/pd-video.c

index 82417db..416ccb9 100644 (file)
@@ -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"
index 619fd00..ae9cb6c 100644 (file)
@@ -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);
 
index 6df9380..fdcc500 100644 (file)
@@ -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 */
index bdbb0c1..755766b 100644 (file)
@@ -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,
index 5f0300a..becfba6 100644 (file)
@@ -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);