diff mbox

[1/2] remove the country code for analog tv and radio

Message ID 1265871232-2144-1-git-send-email-shijie8@gmail.com (mailing list archive)
State Accepted
Headers show

Commit Message

Huang Shijie Feb. 11, 2010, 6:53 a.m. UTC
None
diff mbox

Patch

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);