This patch adds support for the PVR150 internal connector and exposes the 4 
choices of inputs from the wm8775.

Jean-Francois Thibert
diff -Naur ivtv-0.3.4s-orig/driver/cx25840-driver.c ivtv-0.3.4s/driver/cx25840-driver.c
--- ivtv-0.3.4s-orig/driver/cx25840-driver.c	2005-05-14 00:46:49.000000000 -0400
+++ ivtv-0.3.4s/driver/cx25840-driver.c	2005-05-16 11:25:13.247441408 -0400
@@ -63,7 +63,7 @@
 static int debug = 1;
 static char *fw_file_name = NULL;
 static int i2c_enable[IVTV_MAX_CARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
-static int no_black_magic = 0;
+static int no_black_magic = 1; // This really doesn't belong in this module
 static int cardtype = 0;
 static int audiofmt = 0xf;
 static int vbi_mode = 0;
@@ -413,6 +413,13 @@
 
 inline static int cx25840_initialize(struct i2c_client *client)
 {
+	// Needed for NTSC audio to work, couldn't figure out why...
+	int i;
+	for( i= 0; i<number_of_registers; i++ )
+	{
+		cx25840_write(client, CX25840_REGISTER_ADDRESS(i), CX25840_REGISTER_DEFAULT(i));
+	}
+
 	cx25840_reset(client);
 
 	/* Load Audio Firmware */
@@ -528,7 +535,7 @@
 
 int cx25840_set_audio_input(struct i2c_client *client, struct decoder_state *state, int audio_input)
 {
-	if(audio_input <= 2) {
+	if(audio_input <= 4) {
 		DEBUG(1, "set_audio_input %d", audio_input);
 		
 		CX25840_SET_SOFT_RESET(0x0001);
@@ -557,8 +564,10 @@
 			CX25840_SET_SOFT1_MUTE_EN(0x0001);
 			break;
 		
-		case 1: // external line-in
-		case 2: // FM Radio
+		case 1: // external line-in (???)
+		case 2: // external line-in (external)
+		case 3: // external line-in (internal)
+		case 4: // FM Radio
 			// 12
 			CX25840_SET_PATH1_SEL_CTL(0x0002);
 			CX25840_SET_PATH1_AVC_RMS_CON(0x0001);
@@ -594,7 +603,7 @@
 
 int cx25840_set_audio_rate(struct i2c_client *client, struct decoder_state *state, int audio)
 {
-	if((state->audio_input > 2) || (state->audio_input < 0)) {
+	if((state->audio_input > 4) || (state->audio_input < 0)) {
 		DEBUG(1, "Invalid audio input selected %d", state->audio_input);
 		return -EINVAL;
 	}
@@ -603,7 +612,7 @@
 	CX25840_SET_SOFT_RESET(0x0001);
 	CX25840_SET_START_MICROCNTL(0x0000);
 	
-		// common for all inputs and rates
+	// common for all inputs and rates
 	CX25840_SET_VID_PLL_INT(0x000f);
 	CX25840_SET_VID_PLL_POST(0x0004);
 	CX25840_SET_SA_MCLK_SEL(0x0001);
@@ -685,8 +694,10 @@
 		CX25840_SET_AUD_STANDARD(((audiofmt == 0x0f) && (state->norm == VIDEO_MODE_NTSC)) ? 1 : audiofmt);
 		break;
 	
-	case 1: // external line in
-	case 2: // FM radio
+	case 1: // external line in (???)
+	case 2: // external line in (external)
+	case 3: // external line in (internal)
+	case 4: // FM radio
 		switch (audio) {
 		case DECODER_AUDIO_32_KHZ:
 			// pll_ctl1 = 0x1e08040f;
@@ -1107,9 +1118,9 @@
 			DEBUG(1, "Composite Input");
 			CX25840_SET_DUAL_MODE_ADC2(0x0000);
 			CX25840_SET_CHIP_ACFG_DIS(0x0000);
-			CX25840_SET_CH_1__SOURCE(0x0002);
-			CX25840_SET_CH_2__SOURCE(0x0000);
-			CX25840_SET_CH_3__SOURCE(0x0000);
+			CX25840_SET_CH_1__SOURCE(0x0002|(state->input&1));
+			CX25840_SET_CH_2__SOURCE(0x0003);
+			CX25840_SET_CH_3__SOURCE(0x0003);
 			CX25840_SET_AUX_PLL_POST(0x0018);
 			CX25840_SET_INPUT_MODE(0x0000);
 			if(cardtype > 0) {
@@ -1131,9 +1142,10 @@
 			DEBUG(1, "S-Video Input");
 			CX25840_SET_DUAL_MODE_ADC2(0x0000);
 			CX25840_SET_CHIP_ACFG_DIS(0x0000);
-			CX25840_SET_CH_1__SOURCE(0x0000);
-			CX25840_SET_CH_2__SOURCE(0x0001);
-			CX25840_SET_CH_3__SOURCE(0x0000);
+			CX25840_SET_CH_SEL_ADC2(0x0000);
+			CX25840_SET_CH_1__SOURCE(0x0000|(state->input&1));
+			CX25840_SET_CH_2__SOURCE(0x0001+(state->input&1));
+			CX25840_SET_CH_3__SOURCE(0x0003);
 			CX25840_SET_AUX_PLL_POST(0x0018);
 			CX25840_SET_INPUT_MODE(0x0001);
 			CX25840_SET_PREF_MODE(0x0004);
@@ -1155,6 +1167,7 @@
 
 		case CX25840_TUNER:
 			DEBUG(1, "Tuner Input");
+			CX25840_SET_CH_SEL_ADC2(0x0001);
 			CX25840_SET_DUAL_MODE_ADC2(0x0000);
 			CX25840_SET_CH_1__SOURCE(cardtype ==
 						 2 ? 0x0001 : 0x0006);
@@ -1181,7 +1194,7 @@
 		}
 
 		// reset audio path     
-		cx25840_command(client, DECODER_SET_AUDIO, &state->audio);
+		cx25840_command(client, DECODER_SET_AUDIO_INPUT, &state->audio);
 		break;
 	}
 
diff -Naur ivtv-0.3.4s-orig/driver/ivtv-audio.c ivtv-0.3.4s/driver/ivtv-audio.c
--- ivtv-0.3.4s-orig/driver/ivtv-audio.c	2005-05-13 15:50:50.000000000 -0400
+++ ivtv-0.3.4s/driver/ivtv-audio.c	2005-05-16 11:25:13.240442472 -0400
@@ -116,7 +116,7 @@
 /* switching audio input on PVR-150/500, only tested on 150 thus far */
 static int ivtv_set_audio_for_pvr150(struct ivtv *itv, u32 audio_input)
 {
-      if (audio_input <= 2) {
+      if (audio_input <= 4) {
               int cx_input = (int)audio_input;
               u8 wm_input = 0;
               wm8775_ioctl ctl;
@@ -130,11 +130,18 @@
                       wm_input = 0; // TV audio bypasses wm8775
                       break;
 
-              case 1: // external line in
+              case 1: // external line in 1 (???)
+                      wm_input = 0x01;
+                      break;
+              
+              case 2: // external line in 2 (back panel)
                       wm_input = 0x02;
                       break;
+              case 3: // external line in 3 (internal connector)
+                      wm_input = 0x04;
+                      break;
 
-              case 2: // FM Radio
+              case 4: // external line in 4 FM Radio
                       wm_input = 0x08;
                       break;
               }
diff -Naur ivtv-0.3.4s-orig/driver/ivtv-cards.c ivtv-0.3.4s/driver/ivtv-cards.c
--- ivtv-0.3.4s-orig/driver/ivtv-cards.c	2005-05-12 09:04:59.000000000 -0400
+++ ivtv-0.3.4s/driver/ivtv-cards.c	2005-05-16 11:25:13.247441408 -0400
@@ -382,14 +382,49 @@
 	     }
 };
 
+static struct v4l2_audio ivtv_pvr150_audio_inputs[] = {
+	{
+	 .index = 0,
+	 .name = "Tuner Audio In",
+	 .capability = V4L2_AUDCAP_STEREO,
+	}, {
+	 .index = 1,
+	 .name = "Audio Line 1",
+	 .capability = V4L2_AUDCAP_STEREO,
+	}, {
+	 .index = 2,
+	 .name = "Audio Line 2",
+	 .capability = V4L2_AUDCAP_STEREO,
+	}, {
+	 .index = 3,
+	 .name = "Audio Line 3",
+	 .capability = V4L2_AUDCAP_STEREO,
+	}, {
+	 .index = 4,
+	 .name = "Audio Line 4",
+	 .capability = V4L2_AUDCAP_STEREO,
+	}
+};
+
 static const int ivtv_pvr_audio_inputs_size =
     sizeof(ivtv_pvr_audio_inputs) / sizeof(ivtv_pvr_audio_inputs[0]);
 
+static const int ivtv_pvr150_audio_inputs_size =
+    sizeof(ivtv_pvr150_audio_inputs) / sizeof(ivtv_pvr150_audio_inputs[0]);
+
 const struct v4l2_audio *ivtv_get_audio_input(struct ivtv *itv, u16 index)
 {
-	if (index >= ivtv_pvr_audio_inputs_size)
-		return NULL;
-	return &ivtv_pvr_audio_inputs[index];
+	switch (itv->card->type) {
+	case IVTV_CARD_PVR_150:
+		if (index >= ivtv_pvr150_audio_inputs_size)
+			return NULL;
+		return &ivtv_pvr150_audio_inputs[index];
+		break;
+	default:
+		if (index >= ivtv_pvr_audio_inputs_size)
+			return NULL;
+		return &ivtv_pvr_audio_inputs[index];
+	}
 }
 
 /* Audio outputs */
diff -Naur ivtv-0.3.4s-orig/driver/ivtv-gpio.c ivtv-0.3.4s/driver/ivtv-gpio.c
--- ivtv-0.3.4s-orig/driver/ivtv-gpio.c	2005-05-13 15:24:39.000000000 -0400
+++ ivtv-0.3.4s/driver/ivtv-gpio.c	2005-05-16 11:25:13.240442472 -0400
@@ -192,6 +192,28 @@
 	return ivtv_gpio_read(address) & (mask ^ 0xffff);
 }
 
+void ivtv_reset_ir_gpio(struct ivtv *itv)
+{
+	int curdir,curout;
+	if(itv->card->type!=IVTV_CARD_PVR_150) 
+		return;
+	IVTV_DEBUG(IVTV_DEBUG_INFO,
+		"Reseting PVR150 IR\n");
+	curout = ivtv_gpio_read(itv->reg_mem + IVTV_GPIO_OUT_ADDR);
+	curdir = ivtv_gpio_read(itv->reg_mem + IVTV_GPIO_DIREC_ADDR);
+	curdir|=0x80;
+	ivtv_gpio_write(itv->reg_mem + IVTV_GPIO_DIREC_ADDR, curdir);
+	curout=(curout&~0xF)|1;
+	ivtv_gpio_write(itv->reg_mem + IVTV_GPIO_OUT_ADDR, curout);
+	// We could use something else for smaller time
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(1);
+	curout|=2;
+	ivtv_gpio_write(itv->reg_mem + IVTV_GPIO_OUT_ADDR, curout);
+	curdir&=~0x80;
+	ivtv_gpio_write(itv->reg_mem + IVTV_GPIO_DIREC_ADDR, curdir);        
+}
+
 /* audio control by GPIO */
 void ivtv_set_gpio_audio(struct ivtv *itv, int command)
 {
diff -Naur ivtv-0.3.4s-orig/driver/ivtv-ioctl.c ivtv-0.3.4s/driver/ivtv-ioctl.c
--- ivtv-0.3.4s-orig/driver/ivtv-ioctl.c	2005-05-15 20:18:36.000000000 -0400
+++ ivtv-0.3.4s/driver/ivtv-ioctl.c	2005-05-16 11:25:13.246441560 -0400
@@ -650,6 +650,9 @@
 	case IVTV_IOC_G_VIDEO_STATUS:
 		return ivtv_cx25840(itv, DECODER_GET_VIDEO_STATUS, arg);
 
+	case IVTV_IOC_RESET_IR:
+		return ivtv_reset_ir_gpio(itv);
+
 	default:
 		IVTV_DEBUG(IVTV_DEBUG_ERR,
 			   "unknown internal IVTV command %08x\n", cmd);
@@ -1815,7 +1818,7 @@
 	case IVTV_IOC_G_CX25840_SETTING:
 	case IVTV_IOC_S_CX25840_SETTING:
 	case IVTV_IOC_G_VIDEO_STATUS:
-
+	case IVTV_IOC_RESET_IR:
 		return ivtv_internal_ioctls(itv, streamtype, cmd, arg);
 
 	case VIDIOC_QUERYCAP:
diff -Naur ivtv-0.3.4s-orig/driver/ivtv.h ivtv-0.3.4s/driver/ivtv.h
--- ivtv-0.3.4s-orig/driver/ivtv.h	2005-05-15 20:18:36.000000000 -0400
+++ ivtv-0.3.4s/driver/ivtv.h	2005-05-16 11:25:13.245441712 -0400
@@ -415,6 +415,7 @@
 #define IVTV_IOC_G_CX25840_SETTING _IOWR('@', 213, struct ivtv_cx25840_setting)
 #define IVTV_IOC_S_CX25840_SETTING _IOW ('@', 214, struct ivtv_cx25840_setting)
 #define IVTV_IOC_G_VIDEO_STATUS    _IOR ('@', 215, int *)
+#define IVTV_IOC_RESET_IR          _IO  ('@', 216)
 
 #endif
 

Reply via email to