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