Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 27893 Details for
Bug 45473
ivtv 0.1.9-r2 broken? please resubmit the 0.1.9-r2.patch to gentoo-mirror
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
avermedia m179/MPG600/MPG160 support
ivtv-avermedia-r1.patch (text/plain), 61.27 KB, created by
Jelle Kalf
on 2004-03-23 15:39:17 UTC
(
hide
)
Description:
avermedia m179/MPG600/MPG160 support
Filename:
MIME Type:
Creator:
Jelle Kalf
Created:
2004-03-23 15:39:17 UTC
Size:
61.27 KB
patch
obsolete
>diff -urN ivtv/driver/ivtv-api.c ivtv.avermedia/driver/ivtv-api.c >--- ivtv/driver/ivtv-api.c 2004-03-23 19:43:41.000000000 +0100 >+++ ivtv.avermedia/driver/ivtv-api.c 2004-03-24 00:14:54.000000000 +0100 >@@ -4,11 +4,23 @@ > * This file will hold API related functions, both internal (firmware api) > * and external (v4l2, etc) > * >+ * ----- >+ * MPG600/MPG160 support by T.Adachi <tadachi@tadachi-net.com> >+ * and Takeru KOMORIYA<komoriya@paken.org> >+ * >+ * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org> >+ * using information provided by Jiun-Kuei Jung @ AVerMedia. > */ > > #include "ivtv.h" > #include "audiochip.h" > >+extern struct i2c_addresses_st ivtv_i2c_addresses[]; >+extern struct card_function_flag_st ivtv_card_flags[]; >+extern struct ivtv_gpio_data_st ivtv_gpio_data[]; >+extern struct ivtv_msp34xx_audio_map_st ivtv_msp34xx_audio_map[]; >+extern struct ivtv_card_params_st ivtv_card_params[]; >+ > /* Fix the v4l2 api breakage - need to define if still using the old api */ > #ifndef VIDIOC_OVERLAY_OLD > #define VIDIOC_OVERLAY_OLD _IOWR ('V', 14, int) >@@ -33,6 +45,8 @@ > static int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, > unsigned int cmd, unsigned long arg); > static int ivtv_v4l2_pre_init(struct ivtv *itv); >+static int ivtv_set_audio_for_msp34xx(struct ivtv *itv); >+static int ivtv_set_audio_for_gpio(struct ivtv *itv); > > struct file_operations ivtv_v4l2_fops = { > owner: THIS_MODULE, >@@ -65,7 +79,8 @@ > .index = 0, > .name = "ivtv TV Tuner", > .type = V4L2_TUNER_ANALOG_TV, >- .capability = (V4L2_TUNER_CAP_NORM|V4L2_TUNER_CAP_STEREO), >+ .capability = (V4L2_TUNER_CAP_NORM|V4L2_TUNER_CAP_STEREO >+ |V4L2_TUNER_CAP_LANG1|V4L2_TUNER_CAP_LANG2), > .rxsubchans = (V4L2_TUNER_SUB_STEREO), > .audmode = V4L2_TUNER_MODE_STEREO, > .signal = 0, >@@ -102,7 +117,7 @@ > } > }; > >-struct v4l2_input tmk_inputs[10] = { /*values that work with the author's card */ >+struct v4l2_input tmk_pvr_inputs[10] = { /*values that work with the author's card */ > { > .index = 0, > .name = "Composite 0", >@@ -176,6 +191,46 @@ > } > }; > >+struct v4l2_input tmk_mpg_inputs[5] = { /* MPG600/MPG160/M179 */ >+ { >+ .index = 0, >+ .name = "S-Video 0", >+ .type = V4L2_INPUT_TYPE_CAMERA, >+ .audioset = 1, >+ .tuner = 0, >+ .status = 0, >+ },{ >+ .index = 1, >+ .name = "N/A", >+ .type = V4L2_INPUT_TYPE_CAMERA, >+ .audioset = 1, >+ .tuner = 0, >+ .status = 0, >+ },{ >+ .index = 2, >+ .name = "N/A", >+ .type = V4L2_INPUT_TYPE_CAMERA, >+ .audioset = 1, >+ .tuner = 0, >+ .status = 0, >+ },{ >+ .index = 3, >+ .name = "Composite 0", >+ .type = V4L2_INPUT_TYPE_CAMERA, >+ .audioset = 1, >+ .tuner = 0, >+ .status = 0, >+ },{ >+ .index = 4, >+ .name = "Tuner 0", >+ .type = V4L2_INPUT_TYPE_TUNER, >+ .audioset = 0, >+ .tuner = 0, >+ .status = 0, >+ } >+}; >+ >+ > //FIXME capability and mode might be wrong > struct v4l2_audio tmk_audio_inputs[3] = { > {0,"Tv Tuner Audio In",0,0,}, >@@ -183,13 +238,6 @@ > {2,"Radio Tuner Audio In", 0,0,}, > }; > >-int tmk_audio_mapping[] = { >- 0,3, /* Input 0 is msp input 3 */ >- 1,1, /* input 1 is msp input 1 */ >- 2,2, /* Input 2 is msp input 2 */ >- 0,0 /* you're at end of list! */ >-}; >- > struct v4l2_queryctrl ivtv_ctrl_menu_freq = { > .id = V4L2_CID_IVTV_FREQ, > .type = V4L2_CTRL_TYPE_MENU, >@@ -211,9 +259,9 @@ > > u32 ivtv_audio_tbl_freq[] = { > /* setting */ >- 0x2 /* 32kHz binary 10 */, >- 0x0 /* 44.1kHz binary 00 */, >- 0x1 /* 48kHz binary 01 */ >+ IVTV_AUDIO_32000 /* 32kHz binary 10 */, >+ IVTV_AUDIO_44100 /* 44.1kHz binary 00 */, >+ IVTV_AUDIO_48000 /* 48kHz binary 01 */ > }; > > u32 ivtv_audio_mask_freq = 0x3; >@@ -710,36 +758,18 @@ > /* Initialize v4l2 variables and register v4l2 device */ > int ivtv_v4l2_setup(struct ivtv *itv) { > int x, cont, retval; >- >- IVTV_DEBUG(IVTV_DEBUG_INFO,"v4l2 setup\n"); > >- //switch based on card type >- // and fill in appropriate v4l2 device >- switch (itv->card_type) { >- case IVTV_350_V1: >- IVTV_DEBUG(IVTV_DEBUG_INFO,"Configuring 350rev1 card\n"); >- itv->v4l2.streamcount = IVTV_350_V1_STREAMS; >- /* Disable dec yuv buffers if requested */ >- if (itv->options.dec_yuv_buffers == 0) itv->v4l2.streamcount--; >- itv->v4l2.capabilities = (V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_TUNER| >- V4L2_CAP_AUDIO|V4L2_CAP_READWRITE|V4L2_CAP_VBI_CAPTURE| >- V4L2_CAP_VIDEO_OUTPUT|V4L2_CAP_RADIO); >- break; >- case IVTV_250_V2: >- IVTV_DEBUG(IVTV_DEBUG_INFO,"Configuring 250rev2 card\n"); >- itv->v4l2.streamcount = IVTV_250_V2_STREAMS; >- itv->v4l2.capabilities = (V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_TUNER| >- V4L2_CAP_AUDIO|V4L2_CAP_READWRITE|V4L2_CAP_VBI_CAPTURE); >- break; >- case IVTV_250_V1: >- IVTV_DEBUG(IVTV_DEBUG_INFO,"Configuring 250rev1 card\n"); >- default: /* shouldn't happen, treat like V1 */ >- itv->v4l2.streamcount = IVTV_250_V1_STREAMS; >- itv->v4l2.capabilities = (V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_TUNER| >- V4L2_CAP_AUDIO|V4L2_CAP_READWRITE|V4L2_CAP_VBI_CAPTURE); >- >- break; >+ IVTV_DEBUG(IVTV_DEBUG_INFO,"v4l2 setup\n"); >+ /* fill in appropriate v4l2 device */ >+ IVTV_DEBUG(IVTV_DEBUG_INFO,"Configuring %s card\n", >+ ivtv_card_params[itv->card_type].card_name); >+ itv->v4l2.streamcount = ivtv_card_params[itv->card_type].stream_count; >+ /* Disable dec yuv buffers if requested */ >+ if (((itv->card_type == IVTV_350_V1) || (itv->card_type == IVTV_350_V2)) >+ && (itv->options.dec_yuv_buffers == 0)) { >+ itv->v4l2.streamcount--; > } >+ itv->v4l2.capabilities = ivtv_card_params[itv->card_type].capabilities; > > /* Initial settings */ > itv->v4l2.codec.bitrate_mode = 0; >@@ -768,7 +798,7 @@ > itv->dec_options.speed.fr_field = 1; > itv->dec_options.decbuffers = 1; > itv->dec_options.prebuffer = 1; >- >+ > /* Allocate streams */ > itv->v4l2.streams = (struct ivtv_v4l2_stream *) > kmalloc((itv->v4l2.streamcount * >@@ -800,9 +830,10 @@ > memcpy(&itv->v4l2.streams[IVTV_ENC_STREAM_TYPE_PCM], &tmk_pcm_stream, > sizeof(struct ivtv_v4l2_stream)); > >- /* Set some card-specific per-stream stuff here */ >- switch (itv->card_type) { >+ /* Set some card-specific per-stream stuff here */ >+ switch (itv->card_type) { > case IVTV_350_V1: >+ case IVTV_350_V2: > memcpy(&itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_MPG], &dec_mpg_stream, > sizeof(struct ivtv_v4l2_stream)); > memcpy(&itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_VBI], &dec_vbi_stream, >@@ -815,9 +846,18 @@ > sizeof(struct ivtv_v4l2_stream)); > } > break; >+ case IVTV_MPG600: >+ break; >+ case IVTV_MPG160: >+ break; >+ case IVTV_M179: >+ break; > case IVTV_250_V2: >+ case IVTV_250_V4: > break; > case IVTV_250_V1: >+ case IVTV_250_V3: >+ break; > default: /* shouldn't happen, treat like V1 */ > break; > } >@@ -893,13 +933,14 @@ > /* Set any card-specific per-stream stuff here */ > switch (itv->card_type) { > case IVTV_350_V1: >+ case IVTV_350_V2: > /* allocate buffers for decoder */ > x = ivtv_init_queue(itv, > &itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_MPG].free_q, > itv->options.dec_mpg_buffers, > itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_MPG].format.type); >- >- itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_MPG].v4l2dev->minor = >+ >+ itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_MPG].v4l2dev->minor = > itv->num + IVTV_V4L2_DEC_OFFSET; > set_bit(IVTV_F_S_UNINIT, &itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_MPG].s_flags); > >@@ -924,9 +965,9 @@ > x = ivtv_init_queue(itv, > &itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_YUV].free_q, > itv->options.dec_yuv_buffers, >- itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_YUV].format.type); >+ itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_YUV].format.type); > >- itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_YUV].v4l2dev->minor = >+ itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_YUV].v4l2dev->minor = > itv->num + IVTV_V4L2_YUV_OFFSET + IVTV_V4L2_DEC_OFFSET; > set_bit(IVTV_F_S_UNINIT, &itv->v4l2.streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags); > } >@@ -938,8 +979,11 @@ > > break; > case IVTV_250_V2: >+ case IVTV_250_V4: > break; > case IVTV_250_V1: >+ case IVTV_250_V3: >+ break; > default: /* shouldn't happen, treat like V1 */ > break; > } >@@ -991,26 +1035,67 @@ > > /* After setting the audio.active param, call this to > * get the right input.. think of it as a resolver */ >-int ivtv_set_audio(struct ivtv *itv, int *map) { >- int input,msp_input; >- struct msp_matrix mspm; >+int ivtv_set_audio(struct ivtv *itv) { >+ switch (ivtv_card_flags[itv->card_type].audio_selector) { >+ case USE_MSP34XX: >+ return ivtv_set_audio_for_msp34xx(itv); >+ case USE_GPIO: >+ return ivtv_set_audio_for_gpio(itv); >+ } > >- do { >- input = *(map++); >- msp_input = *(map++); >- if (input == itv->v4l2.audio.active) { >- IVTV_DEBUG(IVTV_DEBUG_INFO, >- "Setting audio to input %d\n", msp_input); >- mspm.input = msp_input; >- mspm.output = itv->v4l2.audio_output; >- >- ivtv_call_i2c_client(itv, >- IVTV_MSP3400_I2C_ADDR, >- MSP_SET_MATRIX, >- &mspm); >- return 0; >+ IVTV_DEBUG(IVTV_DEBUG_ERR,"Invalid card type [ivtv_set_audio]!\n"); >+ return -EINVAL; >+} >+ >+/* switching audio input for WIN-PVR250/350 and MSP34XX based card */ >+static int ivtv_set_audio_for_msp34xx(struct ivtv *itv) >+{ >+ struct msp_matrix mspm; >+ >+ if (itv->v4l2.audio.active <= 1) { >+ IVTV_DEBUG(IVTV_DEBUG_INFO, >+ "Setting audio to input %d\n", itv->v4l2.audio.active); >+ mspm.output = itv->v4l2.audio_output; >+ switch (itv->v4l2.audio.active) { >+ case 0: /* Tuner Audio */ >+ mspm.input = ivtv_msp34xx_audio_map[itv->card_type].tuner; >+ break; >+ case 1: /* Audio-In (Line-in) */ >+ mspm.input = ivtv_msp34xx_audio_map[itv->card_type].line; >+ break; > } >- } while ((msp_input !=0) || (input != 0)); >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].msp34xx_addr, >+ MSP_SET_MATRIX, >+ &mspm); >+ return 0; >+ } >+ >+ IVTV_DEBUG(IVTV_DEBUG_ERR,"Invalid audio input, shouldn't happen!\n"); >+ >+ return -EINVAL; >+} >+ >+ >+ >+ >+/* switching audio input for MPG600/MPG160/M179 (controlled by GPIO) */ >+static int ivtv_set_audio_for_gpio(struct ivtv *itv) >+{ >+ if (itv->v4l2.audio.active <= 1) { >+ IVTV_DEBUG(IVTV_DEBUG_INFO, >+ "Setting audio to input %d\n", itv->v4l2.audio.active); >+ switch (itv->v4l2.audio.active) { >+ case 0: /* Tuner Audio */ >+ ivtv_set_gpio_audio(itv,IVTV_GPIO_AUDIO_TUNER); >+ break; >+ case 1: /* Audio-In (Line-in) */ >+ ivtv_set_gpio_audio(itv,IVTV_GPIO_AUDIO_LINE); >+ break;; >+ } >+ ivtv_set_gpio_audio(itv,IVTV_GPIO_AUDIO_UNMUTE); >+ return 0; >+ } > > IVTV_DEBUG(IVTV_DEBUG_ERR,"Invalid audio input, shouldn't happen!\n"); > >@@ -1067,9 +1152,17 @@ > > /* FIXME too much hardcoding? */ > //inputs >- itv->v4l2.input.active = 4; >- itv->v4l2.input.count = 10; >- itv->v4l2.input.table.input = tmk_inputs; >+ if ((itv->card_type == IVTV_MPG600) >+ ||(itv->card_type == IVTV_MPG160) >+ ||(itv->card_type == IVTV_M179)) { >+ itv->v4l2.input.active = 4; >+ itv->v4l2.input.count = 5; >+ itv->v4l2.input.table.input = tmk_mpg_inputs; >+ } else { >+ itv->v4l2.input.active = 4; >+ itv->v4l2.input.count = 10; >+ itv->v4l2.input.table.input = tmk_pvr_inputs; >+ } > > itv->v4l2.audio_output = 1; > >@@ -1205,7 +1298,7 @@ > itv->v4l2.audio_meta[x].table[temp]; > } > >- retval = ivtv_set_audio(itv,tmk_audio_mapping); >+ retval = ivtv_set_audio(itv); > if (retval) { > kfree(itv->v4l2.tuner.table.tuner); > return retval; >@@ -1220,9 +1313,18 @@ > struct msp_matrix mspm; > > /* Mute sound to avoid pop */ >- mspm.input = 8; >- mspm.output = itv->v4l2.audio_output; >- ivtv_call_i2c_client(itv,IVTV_MSP3400_I2C_ADDR,MSP_SET_MATRIX,&mspm); >+ switch (ivtv_card_flags[itv->card_type].audio_selector) { >+ case USE_MSP34XX: >+ mspm.input = 8; >+ mspm.output = itv->v4l2.audio_output; >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].msp34xx_addr, >+ MSP_SET_MATRIX,&mspm); >+ break; >+ case USE_GPIO: >+ ivtv_set_gpio_audio(itv,IVTV_GPIO_AUDIO_MUTE); >+ break; >+ } > > if (0 != ivtv_pause_encoder(itv, 0)) > IVTV_DEBUG(IVTV_DEBUG_ERR, "Mute: Error pausing stream\n"); >@@ -1237,7 +1339,7 @@ > IVTV_DEBUG(IVTV_DEBUG_ERR, "Unmute: Error unpausing stream\n"); > > /* Unmute */ >- ivtv_set_audio(itv,tmk_audio_mapping); >+ ivtv_set_audio(itv); > } > > static void ivtv_select_vbi_line(struct ivtv *itv, unsigned long line, int enable, int slicing) >@@ -1483,7 +1585,8 @@ > /* Disable digitizer (saa7115) */ > IVTV_DEBUG(IVTV_DEBUG_INFO, "Disabling digitizer\n"); > dig=0; >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR, >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].saa7115_addr, > DECODER_ENABLE_OUTPUT,&dig); > // setup VBI registers > ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR, >@@ -1598,7 +1701,8 @@ > /* enable digitizer (saa7115) */ > IVTV_DEBUG(IVTV_DEBUG_INFO, "Enabling digitizer\n"); > dig=1; >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR, >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].saa7115_addr, > DECODER_ENABLE_OUTPUT,&dig); > > IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 100ms\n"); >@@ -2189,13 +2293,15 @@ > case SAA7115_GET_REG: { > struct saa7115_reg_t *saa7115_reg = (struct saa7115_reg_t *)arg; > >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,SAA7115_GET_REG,saa7115_reg); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ SAA7115_GET_REG,saa7115_reg); > break; > } > case SAA7115_SET_REG: { > struct saa7115_reg_t *saa7115_reg = (struct saa7115_reg_t *)arg; > >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,SAA7115_SET_REG,saa7115_reg); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ SAA7115_SET_REG,saa7115_reg); > break; > } > #endif >@@ -2727,7 +2833,9 @@ > int vrate = (int)v; > /* FIXME not obvious how this works > * (see ivtv_ctrl_query_freq[]) */ >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,DECODER_SET_AUDIO,&vrate); >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ DECODER_SET_AUDIO,&vrate); > } > } else { > IVTV_DEBUG(IVTV_DEBUG_ERR, >@@ -2782,9 +2890,11 @@ > IVTV_DEBUG(IVTV_DEBUG_ERR, "ctrl: invalid brightness value: %d\n", vctrl->value); > return -EINVAL; > } >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,DECODER_GET_PICTURE,&pic); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ DECODER_GET_PICTURE,&pic); > pic.bright = vctrl->value; >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,DECODER_SET_PICTURE,&pic); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ DECODER_SET_PICTURE,&pic); > break; > } > case V4L2_CID_HUE: { >@@ -2794,9 +2904,11 @@ > IVTV_DEBUG(IVTV_DEBUG_ERR, "ctrl: invalid hue value: %d\n", vctrl->value); > return -EINVAL; > } >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,DECODER_GET_PICTURE,&pic); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ DECODER_GET_PICTURE,&pic); > pic.hue = vctrl->value; >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,DECODER_SET_PICTURE,&pic); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ DECODER_SET_PICTURE,&pic); > break; > } > case V4L2_CID_SATURATION: { >@@ -2806,9 +2918,11 @@ > IVTV_DEBUG(IVTV_DEBUG_ERR, "ctrl: invalid saturation value: %d\n", vctrl->value); > return -EINVAL; > } >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,DECODER_GET_PICTURE,&pic); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ DECODER_GET_PICTURE,&pic); > pic.sat = vctrl->value; >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,DECODER_SET_PICTURE,&pic); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ DECODER_SET_PICTURE,&pic); > break; > } > case V4L2_CID_CONTRAST: { >@@ -2818,9 +2932,11 @@ > IVTV_DEBUG(IVTV_DEBUG_ERR, "ctrl: invalid contrast value: %d\n", vctrl->value); > return -EINVAL; > } >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,DECODER_GET_PICTURE,&pic); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ DECODER_GET_PICTURE,&pic); > pic.contrast = vctrl->value; >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,DECODER_SET_PICTURE,&pic); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ DECODER_SET_PICTURE,&pic); > break; > } > case V4L2_CID_AUDIO_VOLUME: { >@@ -2830,21 +2946,52 @@ > IVTV_DEBUG(IVTV_DEBUG_ERR, "ctrl: invalid value for volume: %d", vctrl->value); > return -EINVAL; > } >- ivtv_call_i2c_client(itv,IVTV_MSP3400_I2C_ADDR,VIDIOCGAUDIO,&va); >- va.volume = vctrl->value; >- va.mode = 0; /* keep stereo mode at automatic stereo detection */ >- ivtv_call_i2c_client(itv,IVTV_MSP3400_I2C_ADDR,VIDIOCSAUDIO,&va); >+ switch (ivtv_card_flags[itv->card_type].audio_selector) >+{ >+ case USE_MSP34XX: >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].msp34xx_addr, >+ VIDIOCGAUDIO,&va); >+ va.volume = vctrl->value; >+ va.mode = 0; /* keep stereo mode at automatic stereo detection */ >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].msp34xx_addr, >+ VIDIOCSAUDIO,&va); >+ break; >+ case USE_GPIO: >+ /* do nothing (MPG600 etc) */ >+ break; >+ } >+ > break; > } > case V4L2_CID_AUDIO_MUTE: { > struct video_audio va; >- ivtv_call_i2c_client(itv,IVTV_MSP3400_I2C_ADDR,VIDIOCGAUDIO,&va); >- if (vctrl->value) >- va.flags |= VIDEO_AUDIO_MUTE; >- else >- va.flags = (va.flags & ~(VIDEO_AUDIO_MUTE)); >- va.mode = 0; /* keep stereo mode at automatic stereo detection */ >- ivtv_call_i2c_client(itv,IVTV_MSP3400_I2C_ADDR,VIDIOCSAUDIO,&va); >+ switch (ivtv_card_flags[itv->card_type].audio_selector) { >+ case USE_MSP34XX: >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].msp34xx_addr, >+ VIDIOCGAUDIO,&va); >+ if (vctrl->value) >+ va.flags |= VIDEO_AUDIO_MUTE; >+ else >+ va.flags = (va.flags & ~(VIDEO_AUDIO_MUTE)); >+ va.mode = 0; /* keep stereo mode at automatic stereo detection */ >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].msp34xx_addr, >+ VIDIOCSAUDIO,&va); >+ break; >+ case USE_GPIO: >+ if (vctrl->value) { >+ va.flags |= VIDEO_AUDIO_MUTE; >+ ivtv_set_gpio_audio(itv,IVTV_GPIO_AUDIO_MUTE); >+ } else { >+ va.flags = (va.flags & ~(VIDEO_AUDIO_MUTE)); >+ ivtv_set_gpio_audio(itv,IVTV_GPIO_AUDIO_UNMUTE); >+ } >+ break; >+ } >+ > break; > } > default: >@@ -2900,37 +3047,71 @@ > switch (vctrl->id) { > case V4L2_CID_BRIGHTNESS: { > struct saa7114 pic; >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,DECODER_GET_PICTURE,&pic); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ DECODER_GET_PICTURE,&pic); > vctrl->value = pic.bright; > break; > } > case V4L2_CID_HUE: { > struct saa7114 pic; >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,DECODER_GET_PICTURE,&pic); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ DECODER_GET_PICTURE,&pic); > vctrl->value = pic.hue; > break; > } > case V4L2_CID_SATURATION: { > struct saa7114 pic; >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,DECODER_GET_PICTURE,&pic); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ DECODER_GET_PICTURE,&pic); > vctrl->value = pic.sat; > break; > } > case V4L2_CID_CONTRAST: { > struct saa7114 pic; >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR,DECODER_GET_PICTURE,&pic); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ DECODER_GET_PICTURE,&pic); > vctrl->value = pic.contrast; > break; > } > case V4L2_CID_AUDIO_VOLUME: { > struct video_audio va; >- ivtv_call_i2c_client(itv,IVTV_MSP3400_I2C_ADDR,VIDIOCGAUDIO,&va); >+ switch (ivtv_card_flags[itv->card_type].audio_selector) { >+ case USE_MSP34XX: >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].msp34xx_addr, >+ VIDIOCGAUDIO,&va); >+ break; >+ case USE_GPIO: >+ if (ivtv_card_flags[itv->card_type].vol_control) { >+ /* if you can control VOLUME, write code here */ >+ } else { >+ /* do nothing (MPG600 etc) */ >+ va.volume = 65535; /* dummy code */ >+ } >+ break; >+ } > vctrl->value = va.volume; > break; > } > case V4L2_CID_AUDIO_MUTE: { > struct video_audio va; >- ivtv_call_i2c_client(itv,IVTV_MSP3400_I2C_ADDR,VIDIOCGAUDIO,&va); >+ switch (ivtv_card_flags[itv->card_type].audio_selector) { >+ case USE_MSP34XX: >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].msp34xx_addr, >+ VIDIOCGAUDIO,&va); >+ break; >+ case USE_GPIO: >+ if (ivtv_card_flags[itv->card_type].vol_control) { >+ /* if you can control VOLUME, write code here */ >+ } else { >+ /* MPG600 etc */ >+ va.flags = 0; >+ if (ivtv_get_gpio_audio(itv,IVTV_GPIO_AUDIO_MUTE)) >+ va.flags = VIDEO_AUDIO_MUTE; >+ } >+ break; >+ } > vctrl->value = (va.flags & VIDEO_AUDIO_MUTE); > break; > } >@@ -3035,7 +3216,8 @@ > /* FIXME only sets resolution for now */ > wind.width = vfmt->fmt.pix.width; > wind.height = vfmt->fmt.pix.height; >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR, >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].saa7115_addr, > DECODER_SET_SIZE,&wind); > > /* FIXME switch on stream type, bounds checking */ >@@ -3166,14 +3348,24 @@ > > /* Tuner */ > ivtv_call_i2c_client(itv, >- IVTV_TUNER_I2C_ADDR, >+ ivtv_i2c_addresses[itv->card_type].tuner_addr, > VIDIOCSCHAN,&v); >+ > /* Tuner Audio */ >- ivtv_call_i2c_client(itv, >- IVTV_MSP3400_I2C_ADDR, >- VIDIOCSCHAN,&v); >+ switch (ivtv_card_flags[itv->card_type].audio_selector) { >+ case USE_MSP34XX: >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].msp34xx_addr, >+ VIDIOCSCHAN,&v); >+ break; >+ case USE_GPIO: >+ ivtv_set_gpio_audio(itv,IVTV_GPIO_AUDIO_TUNER); >+ break; >+ } >+ > /* Digitizer */ >- ivtv_call_i2c_client(itv,IVTV_SAA7115_I2C_ADDR, >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].saa7115_addr, > DECODER_SET_NORM,&v.norm); > > if (itv->v4l2.standard.active == 0) { // NTSC >@@ -3197,9 +3389,15 @@ > > if ((vt->index < 0) || (vt->index >= itv->v4l2.tuner.count)) > return -EINVAL; >- /* looks like tuner.c doesn't support selection >- * fallback to stereo... */ >- vt->audmode = V4L2_TUNER_MODE_STEREO; >+ if ((itv->card_type == IVTV_MPG600) >+ ||(itv->card_type == IVTV_MPG160) >+ ||(itv->card_type == IVTV_M179)) { >+ ivtv_set_gpio_audiomode(itv,vt->audmode); >+ } else { >+ /* looks like tuner.c doesn't support selection >+ * fallback to stereo... */ >+ vt->audmode = V4L2_TUNER_MODE_STEREO; >+ } > > break; > } >@@ -3241,32 +3439,63 @@ > else { > vt->signal = 0; > } >- } >+ } >+ >+ if ((itv->card_type == IVTV_MPG600) >+ ||(itv->card_type == IVTV_MPG160)) { >+ /* MPGxxx can read tuner audio status */ >+ switch (ivtv_get_gpio_audiomode(itv)) { >+ case 0: /* mono */ >+ vt->rxsubchans = V4L2_TUNER_SUB_MONO; >+ break; >+ case 1: /* stereo */ >+ if ((vt->audmode == V4L2_TUNER_MODE_STEREO) >+ || (vt->audmode == V4L2_TUNER_MODE_LANG1)) >+ vt->rxsubchans = V4L2_TUNER_SUB_STEREO; >+ else >+ vt->rxsubchans = V4L2_TUNER_SUB_MONO; >+ break; >+ case 2: /* multiplex */ >+ if (vt->audmode == V4L2_TUNER_MODE_LANG2) >+ vt->rxsubchans = V4L2_TUNER_SUB_LANG2 | V4L2_TUNER_SUB_MONO; >+ else >+ vt->rxsubchans = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_MONO; >+ break; >+ } >+ } >+ > break; > } > case MSP_SET_MATRIX: { > //FIXME copy_from_user needed > struct msp_matrix *mspm = (struct msp_matrix *)arg; > >- /* FIXME hardcoding! */ >- if ((mspm->input < 1) || (mspm->input > 8)) { >- IVTV_DEBUG(IVTV_DEBUG_ERR,"Invalid audio input!\n"); >- return -EINVAL; >- } >- if ((mspm->output < 0) || (mspm->output >= 3)) { >- IVTV_DEBUG(IVTV_DEBUG_ERR,"Invalid audio output!\n"); >- return -EINVAL; >- } >- >- itv->v4l2.audio_output = mspm->output; >- >- IVTV_DEBUG(IVTV_DEBUG_INFO, >- "v4l2 ioctl: set matrix in=%d,out=%d\n", >- mspm->input, >- mspm->output); >- >- ivtv_call_i2c_client(itv,IVTV_MSP3400_I2C_ADDR,MSP_SET_MATRIX, mspm); >- break; >+ switch (ivtv_card_flags[itv->card_type].audio_selector) { >+ case USE_MSP34XX: >+ /* FIXME hardcoding! */ >+ if ((mspm->input < 1) || (mspm->input > 8)) { >+ IVTV_DEBUG(IVTV_DEBUG_ERR,"Invalid audio input!\n"); >+ return -EINVAL; >+ } >+ if ((mspm->output < 0) || (mspm->output > 3)) { >+ IVTV_DEBUG(IVTV_DEBUG_ERR,"Invalid audio output!\n"); >+ return -EINVAL; >+ } >+ itv->v4l2.audio_output = mspm->output; >+ >+ IVTV_DEBUG(IVTV_DEBUG_INFO, >+ "v4l2 ioctl: set matrix in=%d,out=%d\n", >+ mspm->input, >+ mspm->output); >+ >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].msp34xx_addr, >+ MSP_SET_MATRIX, mspm); >+ break; >+ case USE_GPIO: >+ /* do nothing */ >+ break; >+ } > } > case IVTV_IOC_G_CODEC: { > //FIXME copy_from_user needed >@@ -3293,6 +3522,11 @@ > sizeof(struct ivtv_ioctl_codec)); > } > >+ if (itv->card_type == IVTV_M179) >+ { >+ ivtv_set_gpio_audiofreq(itv,codec->audio_bitmap & 0x03); >+ } >+ > /* VCD streamtype has some quirks. Handle them here */ > if ((codec->stream_type == IVTV_STREAM_VCD) || > (codec->stream_type == IVTV_STREAM_MPEG1)) { >@@ -3301,20 +3535,21 @@ > int tmpsize = 480; > > if (itv->v4l2.standard.active == 1) tmpsize = 576; >- >+ > IVTV_DEBUG(IVTV_DEBUG_INFO,"ivtv ioctl: mpeg1_stream " > "size %d\n", tmpsize); > > /* so far it looks like you can change width at will * > * but the compressor is unhappy when the height changes * > * to anything other than 240 */ >- wind.width = 352; >+ wind.width = 352; > wind.height = tmpsize; > vfmt->fmt.pix.width = 352; > vfmt->fmt.pix.height = tmpsize / 2; > > ivtv_call_i2c_client(itv, >- IVTV_SAA7115_I2C_ADDR,DECODER_SET_SIZE,&wind); >+ ivtv_i2c_addresses[itv->card_type].saa7115_addr, >+ DECODER_SET_SIZE,&wind); > memcpy (&itv->v4l2.streams[0].format, > vfmt, sizeof(struct v4l2_format)); > } >@@ -3348,7 +3583,7 @@ > put_user(ivtv_debug, dbg_level); > break; > } >- case VIDIOC_STREAMOFF: { >+ case VIDIOC_STREAMOFF: { > ivtv_v4l2_streamoff(id); > break; > } >@@ -3362,4 +3597,3 @@ > } > return 0; > } >- >diff -urN ivtv/driver/ivtv-driver.c ivtv.avermedia/driver/ivtv-driver.c >--- ivtv/driver/ivtv-driver.c 2004-03-23 19:43:41.000000000 +0100 >+++ ivtv.avermedia/driver/ivtv-driver.c 2004-03-23 19:48:20.000000000 +0100 >@@ -3,6 +3,13 @@ > * Author: Kevin Thayer (nufan_wfk at yahoo.com) > * License: GPL > * http://www.sourceforge.net/projects/ivtv/ >+ * >+ * ----- >+ * MPG600/MPG160 support by T.Adachi <tadachi@tadachi-net.com> >+ * and Takeru KOMORIYA<komoriya@paken.org> >+ * >+ * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org> >+ * using information provided by Jiun-Kuei Jung @ AVerMedia. > */ > > #include "ivtv.h" >@@ -49,6 +56,228 @@ > {0,} > }; > >+/********************** card configuration *******************************/ >+/* card spec flags */ >+struct card_function_flag_st ivtv_card_flags[] = { >+ {IVTV_250_V1, 1, USE_MSP34XX, HANDLE_VOL}, >+ {IVTV_250_V2, 0, USE_MSP34XX, HANDLE_VOL}, >+ {IVTV_250_V3, 1, USE_MSP34XX, HANDLE_VOL}, >+ {IVTV_250_V4, 0, USE_MSP34XX, HANDLE_VOL}, >+ {IVTV_350_V1, 1, USE_MSP34XX, HANDLE_VOL}, >+ {IVTV_350_V2, 1, USE_MSP34XX, HANDLE_VOL}, >+ {IVTV_MPG600, 0, USE_GPIO, NOT_HANDLE_VOL}, >+ {IVTV_MPG160, 1, USE_GPIO, NOT_HANDLE_VOL}, >+ {IVTV_M179, 1, USE_GPIO, NOT_HANDLE_VOL} >+}; >+ >+/* >+ * GPIO assignment of Yuan MPG600/MPG160 >+ * >+ * bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 >+ * OUTPUT IN1 IN0 AM3 AM2 AM1 AM0 >+ * INPUT DM1 DM0 >+ * >+ * IN* : Input selection >+ * IN1 IN0 >+ * 1 1 N/A >+ * 1 0 Line >+ * 0 1 N/A >+ * 0 0 Tuner >+ * >+ * AM* : Audio Mode >+ * AM3 0: Normal 1: Mixed(Sub+Main channel) >+ * AM2 0: Subchannel 1: Main channel >+ * AM1 0: Stereo 1: Mono >+ * AM0 0: Normal 1: Mute >+ * >+ * DM* : Detected tuner audio Mode >+ * DM1 0: Stereo 1: Mono >+ * DM0 0: Multiplex 1: Normal >+ * >+ * GPIO Initial Settings >+ * MPG600 MPG160 >+ * DIR 0x3080 0x7080 >+ * OUTPUT 0x000C 0x400C >+ * >+ * Special thanks to Makoto Iguchi <iguchi@tahoo.org> and Mr. Anonymous >+ * for analyzing GPIO of MPG160. >+ * >+ ***************************************************************************** >+ * >+ * GPIO assignment of Avermedia M179 (per information direct from AVerMedia) >+ * >+ * bit 15 14 13 12 | 11 10 9 8 | 7 6 5 4 | 3 2 1 0 >+ * OUTPUT IN0 AM0 IN1 AM1 AM2 IN2 BR0 BR1 >+ * INPUT >+ * >+ * IN* : Input selection >+ * IN0 IN1 IN2 >+ * * 1 * Mute >+ * 0 0 0 Line-In >+ * 1 0 0 TV Tuner Audio >+ * 0 0 1 FM Audio >+ * 1 0 1 Mute >+ * >+ * AM* : Audio Mode >+ * AM0 AM1 AM2 >+ * 0 0 0 TV Tuner Audio: L_OUT=(L+R)/2, R_OUT=SAP >+ * 0 0 1 TV Tuner Audio: L_OUT=R_OUT=SAP (SAP) >+ * 0 1 0 TV Tuner Audio: L_OUT=L, R_OUT=R (stereo) >+ * 0 1 1 TV Tuner Audio: mute >+ * 1 * * TV Tuner Audio: L_OUT=R_OUT=(L+R)/2 (mono) >+ * >+ * BR* : Audio Bitrate >+ * BR0 BR1 >+ * 0 0 32 kHz >+ * 0 1 44.1 kHz >+ * 1 0 48 kHz >+ * >+ * DM* : Detected tuner audio Mode >+ * Unknown currently >+ * >+ * GPIO Initial Settings >+ * MPG600 MPG160 >+ * DIR 0x3080 0x7080 >+ * OUTPUT 0x000C 0x400C >+ * >+ * Special thanks to AVerMedia Technologies, Inc. and Jiun-Kuei Jung at >+ * AVerMedia for providing the GPIO information used to add support >+ * for the M179 cards. >+ */ >+ >+struct ivtv_gpio_data_st ivtv_gpio_data[] = { >+ /* card_type,need_init,direction,out_init, >+ * input_mask,input_tuner,input_line,mute_mask,mute_mute,mute_unmute, >+ * audio_mask,audio_mono,audio_stereo,audio_main,audio_sub,audio_mixed, >+ * audio_freq_mask, audio_32000, audio_44100, audio_48000, >+ * tuner_mask,tuner_stereo,tuner_mono,tuner_multiples >+ */ >+ {IVTV_250_V1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, >+ 0, 0, 0, 0, 0, 0}, >+ {IVTV_250_V2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, >+ 0, 0, 0, 0, 0, 0}, >+ {IVTV_250_V3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, >+ 0, 0, 0, 0, 0, 0}, >+ {IVTV_250_V4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, >+ 0, 0, 0, 0, 0, 0}, >+ {IVTV_350_V1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, >+ 0, 0, 0, 0, 0, 0}, >+ {IVTV_350_V2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, >+ 0, 0, 0, 0, 0, 0}, >+ {IVTV_MPG600, 1, 0x3080, 0x0004, /* Normal/main ch./Stereo */ >+ 0xcfff, 0x0000, 0x2000, 0xfffe, 0x0001, 0x0000, >+ 0xfff1, 0x0006, 0x0004, 0x0004, 0x0000, 0x0008, >+ 0xffff, 0x0000, 0x0000, 0x0000, >+ 0xf6ff, 0x0100, 0x0900, 0x0100}, >+ {IVTV_MPG160, 1, 0x7080, 0x400c, /* Normal/main ch./Stereo */ >+ 0xcfff, 0x0000, 0x2000, 0xfffe, 0x0001, 0x0000, >+ 0xfff1, 0x0006, 0x0004, 0x0004, 0x0000, 0x0008, >+ 0xffff, 0x0000, 0x0000, 0x0000, >+ 0xf6ff, 0x0100, 0x0900, 0x0100}, >+ {IVTV_M179, 1, 0xE380, 0x8290, /* Normal/main ch./Stereo, 48kHz */ >+ ~0x8040, 0x8000, 0x0000, ~0x2000, 0x2000, 0x0000, >+ ~0x4300, 0x4000, 0x0200, 0x0200, 0x0100, 0x0000, >+ ~0x0018, 0x0000, 0x0008, 0x0010, >+ ~0x4000, 0x0000, 0x4000, 0x0000} >+}; >+ >+/* I2C addresses */ >+struct i2c_addresses_st ivtv_i2c_addresses[] = { >+ {IVTV_250_V1, IVTV_TUNER_I2C_ADDR, IVTV_SAA7115_I2C_ADDR, IVTV_MSP3400_I2C_ADDR}, >+ {IVTV_250_V2, IVTV_TUNER_I2C_ADDR, IVTV_SAA7115_I2C_ADDR, IVTV_MSP3400_I2C_ADDR}, >+ {IVTV_250_V3, IVTV_TUNER_I2C_ADDR, IVTV_SAA7115_I2C_ADDR, IVTV_MSP3400_I2C_ADDR}, >+ {IVTV_250_V4, IVTV_TUNER_I2C_ADDR, IVTV_SAA7115_I2C_ADDR, IVTV_MSP3400_I2C_ADDR}, >+ {IVTV_350_V1, IVTV_TUNER_I2C_ADDR, IVTV_SAA7115_I2C_ADDR, IVTV_MSP3400_I2C_ADDR}, >+ {IVTV_350_V2, IVTV_TUNER_I2C_ADDR, IVTV_SAA7115_I2C_ADDR, IVTV_MSP3400_I2C_ADDR}, >+ {IVTV_MPG600, IVTV_MPG600_TUNER_I2C_ADDR, IVTV_SAA7115_I2C_ADDR, 0}, >+ {IVTV_MPG160, IVTV_MPG160_TUNER_I2C_ADDR, IVTV_SAA7115_I2C_ADDR, 0}, >+ {IVTV_M179, IVTV_M179_TUNER_I2C_ADDR, IVTV_SAA7115_I2C_ADDR, 0} >+}; >+ >+/* MSP34XX audio mapping */ >+struct ivtv_msp34xx_audio_map_st ivtv_msp34xx_audio_map[] = { >+ {IVTV_250_V1, 3, 1}, >+ {IVTV_250_V2, 3, 1}, >+ {IVTV_250_V3, 3, 1}, >+ {IVTV_250_V4, 3, 1}, >+ {IVTV_350_V1, 3, 1}, >+ {IVTV_350_V2, 3, 1}, >+ {IVTV_MPG600, 0, 0}, >+ {IVTV_MPG160, 0, 0}, >+ {IVTV_M179, 0, 0} >+}; >+ >+struct ivtv_card_params_st ivtv_card_params[] = { >+ /* card_type, subsystem id, capabilities, stream, card name, chip name */ >+ {IVTV_250_V1, IVTV_PCI_ID_250_V1, >+ (V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_TUNER| >+ V4L2_CAP_AUDIO|V4L2_CAP_READWRITE), >+ IVTV_250_V1_STREAMS, >+ "wintv pvr 250rev1", >+ "iTVC15"}, >+ >+ {IVTV_250_V2, IVTV_PCI_ID_250_V2, >+ (V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_TUNER| >+ V4L2_CAP_AUDIO|V4L2_CAP_READWRITE), >+ IVTV_250_V2_STREAMS, >+ "wintv pvr 250rev2", >+ "iTVC16"}, >+ >+ {IVTV_250_V3, IVTV_PCI_ID_250_V3, >+ (V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_TUNER| >+ V4L2_CAP_AUDIO|V4L2_CAP_READWRITE), >+ IVTV_250_V3_STREAMS, >+ "wintv pvr 250rev3", >+ "iTVC15"}, >+ >+ {IVTV_250_V4, IVTV_PCI_ID_250_V4, >+ (V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_TUNER| >+ V4L2_CAP_AUDIO|V4L2_CAP_READWRITE), >+ IVTV_250_V4_STREAMS, >+ "wintv pvr 250rev4", >+ "iTVC16"}, >+ >+ {IVTV_350_V1, IVTV_PCI_ID_350_V1, >+ (V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_TUNER| >+ V4L2_CAP_AUDIO|V4L2_CAP_READWRITE| >+ V4L2_CAP_VIDEO_OUTPUT), >+ IVTV_350_V1_STREAMS, >+ "wintv pvr 350rev1", >+ "iTVC15"}, >+ >+ {IVTV_350_V2, IVTV_PCI_ID_350_V2, >+ (V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_TUNER| >+ V4L2_CAP_AUDIO|V4L2_CAP_READWRITE| >+ V4L2_CAP_VIDEO_OUTPUT), >+ IVTV_350_V2_STREAMS, >+ "wintv pvr 350rev2", >+ "iTVC15"}, >+ >+ {IVTV_MPG600, IVTV_PCI_ID_MPG600, >+ (V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_TUNER| >+ V4L2_CAP_AUDIO|V4L2_CAP_READWRITE), >+ IVTV_MPG600_STREAMS, >+ "YUAN MPG600/Kuroutoshikou ITVC16-STVLP", >+ "iTVC16"}, >+ >+ {IVTV_MPG160, IVTV_PCI_ID_MPG160, >+ (V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_TUNER| >+ V4L2_CAP_AUDIO|V4L2_CAP_READWRITE), >+ IVTV_MPG160_STREAMS, >+ "YUAN MPG160/Kuroutoshikou ITVC15-STVLP", >+ "iTVC15"}, >+ >+ {IVTV_M179, IVTV_PCI_ID_M179, >+ (V4L2_CAP_VIDEO_CAPTURE|V4L2_CAP_TUNER| >+ V4L2_CAP_AUDIO|V4L2_CAP_READWRITE), >+ IVTV_M179_STREAMS, >+ "AverMedia M179", >+ "iTVC15"}, >+ >+ {-1,0,0,0,NULL} >+}; >+/********************** end of card configuration ************************/ >+ > static void ivtv_irq_dec_vsync(struct ivtv* itv); > static IRQRETURN_T ivtv_irq_handler(int irq, void *dev_id, struct pt_regs *regs); > static void ivtv_DMA_done(struct ivtv *itv); >@@ -79,7 +308,7 @@ > /* low debugging by default */ > #if 0 > int debug = ( IVTV_DEBUG_ERR | IVTV_DEBUG_INFO | IVTV_DEBUG_API >- | IVTV_DEBUG_DMA | IVTV_DEBUG_IOCTL | IVTV_DEBUG_I2C >+ | IVTV_DEBUG_DMA | IVTV_DEBUG_IOCTL | IVTV_DEBUG_I2C > | IVTV_DEBUG_IRQ ); > #endif > int ivtv_debug = IVTV_DEBUG_ERR; >@@ -497,7 +726,7 @@ > } > > >- if (itv->card_type != IVTV_250_V2) { >+ if (ivtv_card_flags[itv->card_type].ivtv15) { > IVTV_DEBUG(IVTV_DEBUG_INFO, "Loading decoder firmware\n"); > if (load_fw_direct(IVTV_FIRM_DEC_FILENAME, > (char *)(itv->io_mem + IVTV_DEC_MEM_START)) != >@@ -540,7 +769,7 @@ > ivtv_sleep_timeout(HZ/100); > > /*halt dec firmware */ >- if (IVTV_250_V2 != itv->card_type) { >+ if (ivtv_card_flags[itv->card_type].ivtv15) { > x = ivtv_api(itv->dec_mbox, &itv->dec_msem, IVTV_API_DEC_HALT_FW, > &result, 0, &data[0]); > if (x) IVTV_DEBUG(IVTV_DEBUG_ERR, "stop_fw error 4. Code %d\n",x); >@@ -576,7 +805,7 @@ > writel(IVTV_CMD_APU_PING, (IVTV_REG_APU + itv->reg_mem)); > > IVTV_DEBUG(IVTV_DEBUG_INFO, "Stopping VPU\n"); >- if (IVTV_250_V2 == itv->card_type) { >+ if (!ivtv_card_flags[itv->card_type].ivtv15) { > writel(IVTV_CMD_VPU_STOP16, (IVTV_REG_VPU + itv->reg_mem)); > } > else { >@@ -626,7 +855,7 @@ > ivtv_sleep_timeout(HZ); > > /*I guess this is read-modify-write :)*/ >- if (IVTV_250_V2 == itv->card_type) { >+ if (!ivtv_card_flags[itv->card_type].ivtv15) { > writel((readl(itv->reg_mem + IVTV_REG_VPU)&IVTV_MASK_VPU_ENABLE16), > (IVTV_REG_VPU+itv->reg_mem)); > } >@@ -638,6 +867,12 @@ > IVTV_DEBUG(IVTV_DEBUG_INFO, "Sleeping for 1 sec\n"); > ivtv_sleep_timeout(HZ); > >+ /* GPIO init */ >+ if (ivtv_gpio_data[itv->card_type].need_init) { >+ IVTV_DEBUG(IVTV_DEBUG_INFO, "GPIO INIT\n"); >+ ivtv_set_gpio_audio(itv,IVTV_GPIO_AUDIO_INIT); >+ } >+ > /* FIXME Send Status API commands to encoder and decoder to verify!*/ > > return 0; >@@ -898,7 +1133,7 @@ > default: > if (down_interruptible(sem)) return -ERESTARTSYS; > gotsem = 1; >- break; >+ break; > } > > /* wait 200ms for mailbox to become free */ >@@ -913,14 +1148,14 @@ > if (x == -EBUSY) { > /* dilemma here: > if the command that currently has the mailbox >- is lost, then it'll never free up the box, and >+ is lost, then it'll never free up the box, and > we'll lose our only 'general purpose' box forever. > But if it comes back, we run the risk of squishing > something important!. */ > switch (local_box->cmd) { > case IVTV_API_DEC_DMA_FROM_HOST: >- /* if we got here, it's because the call to xfer the dma >- was finished, and the command that wants to run has >+ /* if we got here, it's because the call to xfer the dma >+ was finished, and the command that wants to run has > already slept for 20ms. It's probably safe to take over > */ > IVTV_DEBUG(IVTV_DEBUG_API, "Forcibly freeing mailbox\n"); >@@ -975,8 +1210,8 @@ > "Encoder revision: 0x%08x\n", data[0]); > } > >- if (itv->card_type != IVTV_250_V2) { >- /* Decoder */ >+ if (ivtv_card_flags[itv->card_type].ivtv15) { >+ /* Decoder */ > IVTV_DEBUG(IVTV_DEBUG_INFO, "Getting decoder firmware rev.\n"); > x = ivtv_api(itv->dec_mbox, &itv->dec_msem, IVTV_API_DEC_GETVER, > &result, 0, &data[0]); >@@ -989,7 +1224,7 @@ > "Decoder revision: 0x%08x\n", data[0]); > } > } >- >+ > return 0; > } > >@@ -1290,7 +1525,7 @@ > struct ivtv *itv=(struct ivtv *)dev_id; > > spin_lock(&itv->lock); >- >+ > /* get contents of irq status register*/ > stat = readl(itv->reg_mem + IVTV_REG_IRQSTATUS); > >@@ -1743,7 +1978,7 @@ > > /* FIXME this function does way more than it should */ > static int __devinit ivtv_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) { >- int retval=0; >+ int i, retval=0; > unsigned char pci_latency; > struct ivtv *itv; > struct video_channel v; >@@ -1788,26 +2023,19 @@ > /* Set FrameBuffer-ID to invalid */ > itv->fb_id = -1; > >- switch (dev->subsystem_device) { >- case IVTV_PCI_ID_250_V2: >- case IVTV_PCI_ID_250_V4: >- IVTV_DEBUG(IVTV_DEBUG_ERR, "Found an iTVC16 based chip\n"); >- itv->card_type = IVTV_250_V2; >- break; >- case IVTV_PCI_ID_350_V1: >- case IVTV_PCI_ID_350_V2: >- IVTV_DEBUG(IVTV_DEBUG_ERR, "Found an iTVC15 based chip\n"); >- itv->card_type = IVTV_350_V1; >- break; >- case IVTV_PCI_ID_250_V1: >- case IVTV_PCI_ID_250_V3: >- IVTV_DEBUG(IVTV_DEBUG_ERR, "Found an iTVC15 based chip\n"); >+ i=0; >+ do { >+ if (dev->subsystem_device == ivtv_card_params[i].subsystem_id) break; >+ i++; >+ } while(ivtv_card_params[i].card_type != -1); >+ >+ if (ivtv_card_params[i].card_type != -1) { >+ itv->card_type = ivtv_card_params[i].card_type; >+ IVTV_DEBUG(IVTV_DEBUG_ERR, "Found an %s based chip\n",ivtv_card_params[i].chip); >+ } else { >+ IVTV_DEBUG(IVTV_DEBUG_INFO, "subsystem_id is %x\n",dev->subsystem_device); > itv->card_type = IVTV_250_V1; >- break; >- default: /* Default to 250 v1 style */ > IVTV_DEBUG(IVTV_DEBUG_ERR, "Found an unknown chip, treating it like an iTVC15\n"); >- itv->card_type = IVTV_250_V1; >- break; > } > > init_MUTEX(&itv->enc_msem); >@@ -1869,6 +2097,14 @@ > pci_read_config_byte(dev, PCI_CLASS_REVISION, &itv->card_rev); > pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); > >+ if (pci_latency < 64) { >+ IVTV_DEBUG(IVTV_DEBUG_ERR, "Unreasonably low latency timer, " >+ "setting to 64 (was %d)\n", >+ pci_latency); >+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64); >+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency); >+ } >+ > IVTV_DEBUG(IVTV_DEBUG_INFO, "%d (rev %d) at %02x:%02x.%x, ", > itv->dev->device, itv->card_rev, dev->bus->number, > PCI_SLOT(dev->devfn),PCI_FUNC(dev->devfn)); >@@ -1967,10 +2203,10 @@ > SGarray_size), > PCI_DMA_TODEVICE); > >- if (itv->card_type == IVTV_350_V1) { >+ if (itv->card_type == IVTV_350_V1 || itv->card_type == IVTV_350_V2) { > /* decoder */ > itv->DSGarray = (struct ivtv_SG_element *) >- kmalloc(sizeof(struct ivtv_SG_element) * >+ kmalloc(sizeof(struct ivtv_SG_element) * > DSGarray_size, GFP_KERNEL); > if (!(itv->DSGarray)) { > IVTV_DEBUG(IVTV_DEBUG_ERR, "Error allocating DSGarray[].\n"); >@@ -2000,12 +2236,15 @@ > else > v.norm = VIDEO_MODE_PAL; > >- ivtv_call_i2c_client(itv,IVTV_TUNER_I2C_ADDR, VIDIOCSCHAN,&v); >+ ivtv_call_i2c_client(itv,ivtv_i2c_addresses[itv->card_type].tuner_addr, >+ VIDIOCSCHAN,&v); > > if (!ivtv_pal) { > /* set the channel */ > freq = 1076; /* ch. 4 67250*16/1000 */ >- ivtv_call_i2c_client(itv,IVTV_TUNER_I2C_ADDR,VIDIOCSFREQ,&freq); >+ ivtv_call_i2c_client(itv, >+ ivtv_i2c_addresses[itv->card_type].tuner_addr, >+ VIDIOCSFREQ,&freq); > } > > retval = ivtv_v4l2_setup(itv); >@@ -2318,7 +2557,7 @@ > /* Skip the first 4 bytes of mpg streams to help out > * finicky decoders.. but not for iTVC16 */ > if ((id->type == 0) && (itv->first_read == 1) && >- (itv->card_type != IVTV_250_V2)) { >+ (ivtv_card_flags[itv->card_type].ivtv15)) { > for( x = 0; x < buf->buffer.bytesused-4; x++ ) { > unsigned char *p; > itv->first_read = 0; >@@ -2943,6 +3182,181 @@ > return ret; > } > >+/********************* GPIO stuffs *********************/ >+ >+void ivtv_gpio_write(unsigned char *gpio_addr, u32 data) >+{ >+ writel(data,(u32)gpio_addr); >+} >+ >+u32 ivtv_gpio_read(unsigned char *gpio_addr) >+{ >+ return readl((u32)gpio_addr); >+} >+ >+void ivtv_chg_gpio(unsigned char *address, u32 mask, u32 write_data) >+{ >+ ivtv_gpio_write(address,(readl(address) & mask)|write_data); >+} >+ >+u32 ivtv_chk_gpio(unsigned char *address, u32 mask) >+{ >+ return (ivtv_gpio_read(address) & (mask ^ 0xffff)); >+} >+ >+/* audio control by GPIO */ >+void ivtv_set_gpio_audio(struct ivtv *itv, int command) >+{ >+ struct ivtv_gpio_data_st gpio_data = ivtv_gpio_data[itv->card_type]; >+ >+ switch (command) { >+ case IVTV_GPIO_AUDIO_INIT: >+ IVTV_DEBUG(IVTV_DEBUG_INFO, >+ "GPIO initial dir:%08x, out:%08x\n", >+ ivtv_gpio_read(itv->reg_mem+IVTV_GPIO_DIREC_ADDR), >+ ivtv_gpio_read(itv->reg_mem+IVTV_GPIO_OUT_ADDR)); >+ /* init output data then direction */ >+ ivtv_gpio_write(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.out_init); >+ ivtv_gpio_write(itv->reg_mem+IVTV_GPIO_DIREC_ADDR, >+ gpio_data.direction); >+ break; >+ case IVTV_GPIO_AUDIO_TUNER: >+ ivtv_chg_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.input_mask,gpio_data.input_tuner); >+ break; >+ case IVTV_GPIO_AUDIO_LINE: >+ ivtv_chg_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.input_mask,gpio_data.input_line); >+ break; >+ case IVTV_GPIO_AUDIO_MUTE: >+ ivtv_chg_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.mute_mask,gpio_data.mute_mute); >+ break; >+ case IVTV_GPIO_AUDIO_UNMUTE: >+ ivtv_chg_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.mute_mask,gpio_data.mute_unmute); >+ break; >+ } >+} >+ >+int ivtv_get_gpio_audio(struct ivtv *itv, int command) >+{ >+ struct ivtv_gpio_data_st gpio_data = ivtv_gpio_data[itv->card_type]; >+ int out, data; >+ >+ out = 0; >+ data = -1; /* 'data' must be different from 'out' here */ >+ >+ switch (command) { >+ case IVTV_GPIO_AUDIO_INIT: >+ /* do nothing*/ >+ break; >+ case IVTV_GPIO_AUDIO_TUNER: >+ out = ivtv_chk_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.input_mask); >+ data = gpio_data.input_tuner; >+ break; >+ case IVTV_GPIO_AUDIO_LINE: >+ out = ivtv_chk_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.input_mask); >+ data = gpio_data.input_line; >+ break; >+ case IVTV_GPIO_AUDIO_MUTE: >+ out = ivtv_chk_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.mute_mask); >+ data = gpio_data.mute_mute; >+ break; >+ case IVTV_GPIO_AUDIO_UNMUTE: >+ out = ivtv_chk_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.mute_mask); >+ data = gpio_data.mute_unmute; >+ break; >+ } >+ >+ if (out == data) >+ return 1; >+ >+ return 0; >+} >+ >+/* set MPG600/MPG160/M179 tuner audio freq */ >+void ivtv_set_gpio_audiofreq(struct ivtv *itv,int audio_freq) >+{ >+ struct ivtv_gpio_data_st gpio_data = ivtv_gpio_data[itv->card_type]; >+ >+ switch (audio_freq) { >+ case IVTV_AUDIO_32000: >+ ivtv_chg_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.audio_freq_mask,gpio_data.audio_32000); >+ break; >+ case IVTV_AUDIO_44100: >+ ivtv_chg_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.audio_freq_mask,gpio_data.audio_44100); >+ break; >+ case IVTV_AUDIO_48000: >+ ivtv_chg_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.audio_freq_mask,gpio_data.audio_48000); >+ break; >+ } >+} >+ >+/* set MPG600/MPG160/M179 tuner audio mode */ >+void ivtv_set_gpio_audiomode(struct ivtv *itv,int audio_mode) >+{ >+ struct ivtv_gpio_data_st gpio_data = ivtv_gpio_data[itv->card_type]; >+ u32 gpio_dir, gpio_out, gpio_in; >+ >+ switch (audio_mode) { >+ case V4L2_TUNER_MODE_MONO: >+ ivtv_chg_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.audio_mask,gpio_data.audio_mono); >+ break; >+ case V4L2_TUNER_MODE_STEREO: >+ ivtv_chg_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.audio_mask,gpio_data.audio_stereo); >+ break; >+ case V4L2_TUNER_MODE_LANG1: >+ ivtv_chg_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.audio_mask,gpio_data.audio_main); >+ break; >+ case V4L2_TUNER_MODE_LANG2: >+ ivtv_chg_gpio(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ gpio_data.audio_mask,gpio_data.audio_sub); >+ break; >+ } >+ >+ /* GPIO debug interface */ >+ if ((audio_mode & 0x10000) != 0) { >+ ivtv_gpio_write(itv->reg_mem+IVTV_GPIO_OUT_ADDR, >+ (u32)(audio_mode & 0xffff)); >+ gpio_dir = ivtv_gpio_read(itv->reg_mem+IVTV_GPIO_DIREC_ADDR); >+ gpio_out = ivtv_gpio_read(itv->reg_mem+IVTV_GPIO_OUT_ADDR); >+ gpio_in = ivtv_gpio_read(itv->reg_mem+IVTV_GPIO_IN_ADDR); >+ >+ IVTV_DEBUG(IVTV_DEBUG_INFO, >+ "GPIO status: DIR=0x%04x OUT=0x%04x IN=0x%04x\n", >+ gpio_dir, gpio_out, gpio_in); >+ } >+} >+ >+/* get MPG600/MPG160/M179 tuner audio mode */ >+int ivtv_get_gpio_audiomode(struct ivtv *itv) >+{ >+ struct ivtv_gpio_data_st gpio_data = ivtv_gpio_data[itv->card_type]; >+ u32 st; >+ >+ st = ivtv_chk_gpio(itv->reg_mem+IVTV_GPIO_IN_ADDR, >+ gpio_data.tuner_mask); >+ >+ if (st == gpio_data.tuner_multiplex) >+ return 2; >+ else if (st == gpio_data.tuner_stereo) >+ return 1; >+ return 0; /* mono */ >+} >+ >+ > static int module_start(void) { > int loop_a; > int i; >diff -urN ivtv/driver/ivtv.h ivtv.avermedia/driver/ivtv.h >--- ivtv/driver/ivtv.h 2004-03-23 19:43:41.000000000 +0100 >+++ ivtv.avermedia/driver/ivtv.h 2004-03-23 21:40:00.000000000 +0100 >@@ -6,6 +6,13 @@ > * Author: Kevin Thayer (nufan_wfk at yahoo.com) > * License: GPL > * http://www.sourceforge.net/projects/ivtv/ >+ * >+ * ----- >+ * MPG600/MPG160 support by T.Adachi <tadachi@tadachi-net.com> >+ * and Takeru KOMORIYA<komoriya@paken.org> >+ * >+ * AVerMedia M179 GPIO info by Chris Pinkham <cpinkham@bc2va.org> >+ * using information provided by Jiun-Kuei Jung @ AVerMedia. > */ > #ifndef MODULE > #define MODULE >@@ -104,12 +111,39 @@ > #define IVTV_PCI_ID_250_V4 0x4803 /* treat like 250_V2 */ > #define IVTV_PCI_ID_350_V1 0x4000 > #define IVTV_PCI_ID_350_V2 0x4800 /* treat like 350_V1 */ >+#define IVTV_PCI_ID_MPG600 0xfff3 >+#define IVTV_PCI_ID_MPG160 0x0000 >+#define IVTV_PCI_ID_M179 0xa3cf > #define IVTV_250_V1 0 /* wintv pvr 250, encoder and decoder */ > #define IVTV_250_V2 1 /* pvr 250, encoder only */ >-#define IVTV_350_V1 2 /* encoder, decoder, tv-out */ >+#define IVTV_250_V3 2 /* wintv pvr 250, encoder and decoder */ >+#define IVTV_250_V4 3 /* pvr 250, encoder only */ >+#define IVTV_350_V1 4 /* encoder, decoder, tv-out */ >+#define IVTV_350_V2 5 /* encoder, decoder, tv-out */ >+#define IVTV_MPG600 6 /* Kuroutoshikou ITVC16-STVLP/YUAN MPG600, encoder only */ >+#define IVTV_MPG160 7 /* Kuroutoshikou ITVC15-STVLP/YUAN MPG160 >+ iTVC15 based, but does not have tv-out */ >+#define IVTV_M179 8 /* AVerMedia M179 (encoder only) */ >+ >+/* #define IVTV_350_V1 2 /* encoder, decoder, tv-out */ > #define IVTV_250_V1_STREAMS 4 > #define IVTV_250_V2_STREAMS 4 >+#define IVTV_250_V3_STREAMS 4 >+#define IVTV_250_V4_STREAMS 4 > #define IVTV_350_V1_STREAMS 8 >+#define IVTV_350_V2_STREAMS 8 >+#define IVTV_MPG600_STREAMS 3 >+#define IVTV_MPG160_STREAMS 3 >+#define IVTV_M179_STREAMS 3 >+ >+#define NO_AUDIO 0 /* the card can't handle audio */ >+#define USE_MSP34XX 1 /* switch audio by MSP34XX */ >+#define USE_GPIO 2 /* switch audio by GPIO */ >+ >+#define IVTV_AUDIO_32000 0x2 /* 32 kHz audio */ >+#define IVTV_AUDIO_44100 0x0 /* 44.1 kHz audio */ >+#define IVTV_AUDIO_48000 0x1 /* 48 kHz audio */ >+ > #define IVTV_V4L2_DEC_OFFSET 16 /* offset from 0 to register dec. v4l2 minors on */ > #define IVTV_V4L2_PCM_OFFSET 24 /* offset from 0 to register pcm v4l2 minors on */ > #define IVTV_V4L2_YUV_OFFSET 32 /* offset from 0 to register yuv v4l2 minors on */ >@@ -139,7 +173,13 @@ > #define IVTV_MBOX_SIZE 80 > #define IVTV_SAA7115_I2C_ADDR 0x21 > #define IVTV_TUNER_I2C_ADDR 0x61 >+#define IVTV_MPG600_TUNER_I2C_ADDR 0x60 >+#define IVTV_MPG160_TUNER_I2C_ADDR 0x60 >+#define IVTV_M179_TUNER_I2C_ADDR 0x60 > #define IVTV_MSP3400_I2C_ADDR 0x40 >+#define IVTV_GPIO_IN_ADDR 0x9008 >+#define IVTV_GPIO_OUT_ADDR 0x900c >+#define IVTV_GPIO_DIREC_ADDR 0x9020 > #define IVTV_DMA_BUF_SIZE 34560 /* 0x8000 = 32kbytes, 0x20000 = 128kbytes */ > #define IVTV_DMA_DEC_BUF_SIZE 32768 /* 0x8000 = 32kbytes, 0x20000 = 128kbytes */ > //#define IVTV_DMA_BUF_SIZE 65536 /* 0x8000 = 32kbytes, 0x20000 = 128kbytes */ >@@ -549,6 +589,16 @@ > > #define IVTV_V4L2_DEC_MENUCOUNT 7 > >+/* MPG600/MPG160/M179 audio stuff */ >+#define IVTV_GPIO_AUDIO_INIT 0 >+#define IVTV_GPIO_AUDIO_TUNER 1 >+#define IVTV_GPIO_AUDIO_LINE 2 >+#define IVTV_GPIO_AUDIO_MUTE 3 >+#define IVTV_GPIO_AUDIO_UNMUTE 4 >+ >+#define NOT_HANDLE_VOL 0 >+#define HANDLE_VOL 1 >+ > #ifdef SAA7115_REGTEST > /* allow direct access to the saa7115 registers for testing */ > #define SAA7115_GET_REG 0xFFEE7705 >@@ -857,6 +907,67 @@ > struct list_head client_list; > }; > >+/* for flag/value of each cards */ >+struct card_function_flag_st { >+ int card_type; /* card_type no */ >+ int ivtv15; /* ivtv15:1 ivtv16:0 */ >+ int audio_selector; /* audio selector */ >+ int vol_control; /* 1: the card can handle volume 0:not */ >+}; >+ >+/* I2C address list */ >+struct i2c_addresses_st { >+ int card_type; >+ u32 tuner_addr; >+ u32 saa7115_addr; >+ u32 msp34xx_addr; >+}; >+ >+/* for GPIO setting parameter */ >+struct ivtv_gpio_data_st { >+ int card_type; >+ int need_init; /* need to init GPIO? 1:yes 0:no */ >+ u32 direction; /* GPIO direction (GPIO[0..16]) 0:Input 1:Output */ >+ u32 out_init; /* GPIO output port init data */ >+ u32 input_mask; /* for input selection (tuner/line-in/mute) */ >+ u32 input_tuner; >+ u32 input_line; >+ u32 mute_mask; /* for muting */ >+ u32 mute_mute; >+ u32 mute_unmute; >+ u32 audio_mask; /* for tuner's audio mode selection */ >+ u32 audio_mono; >+ u32 audio_stereo; >+ u32 audio_main; >+ u32 audio_sub; >+ u32 audio_mixed; >+ u32 audio_freq_mask; >+ u32 audio_32000; >+ u32 audio_44100; >+ u32 audio_48000; >+ u32 tuner_mask; /* for tuner audio status */ >+ u32 tuner_stereo; >+ u32 tuner_mono; >+ u32 tuner_multiplex; >+}; >+ >+/* for MSP34XX audio mapping */ >+struct ivtv_msp34xx_audio_map_st { >+ int card_type; >+ int tuner; /* tuner audio input */ >+ int line; /* line-in audio input */ >+}; >+ >+/* for card information/param */ >+struct ivtv_card_params_st { >+ int card_type; >+ unsigned short subsystem_id; >+ u32 capabilities; >+ int stream_count; >+ char *card_name; >+ char *chip; >+}; >+ > /* Globals */ > extern struct ivtv ivtv_cards[]; > extern int ivtv_cards_active; >@@ -939,6 +1050,17 @@ > extern void ivtv_clear_irq_mask(struct ivtv *itv, unsigned long mask); > extern void ivtv_sleep_timeout(int timeout); > >+/* GPIO stuff */ >+void ivtv_set_gpio_audio(struct ivtv *itv, int command); >+void ivtv_chg_gpio_out(unsigned char *address, u32 mask, u32 write_data); >+void ivtv_gpio_write(unsigned char *gpio_addr, u32 data); >+int ivtv_get_gpio_audio(struct ivtv *itv, int command); >+u32 ivtv_chk_gpio_out(unsigned char *address, u32 mask); >+u32 ivtv_gpio_read(unsigned char *gpio_addr); >+void ivtv_set_gpio_audiomode(struct ivtv *itv,int audio_mode); >+void ivtv_set_gpio_audiofreq(struct ivtv *itv,int audio_freq); >+int ivtv_get_gpio_audiomode(struct ivtv *itv); >+ > /* Testing/Debugging */ > extern int ivtv_close(struct ivtv_open_id *id); > >diff -urN ivtv/utils/ivtvfwextract.pl ivtv.avermedia/utils/ivtvfwextract.pl >--- ivtv/utils/ivtvfwextract.pl 2004-03-23 19:43:41.000000000 +0100 >+++ ivtv.avermedia/utils/ivtvfwextract.pl 2004-03-23 19:48:20.000000000 +0100 >@@ -43,6 +43,8 @@ > > $packed_driver_name = "pvr48xxx.exe"; > $fw_driver_name = "hcwpvrp2.sys"; >+# for Yuan MPG600/MPG160 >+#$fw_driver_name = "p2driver.sys"; > $decoder_magic = "a703000066bb55aa"; > $encoder_magic = "a70d000066bb55aa"; > >diff -urN ivtv/utils/ptune.pl ivtv.avermedia/utils/ptune.pl >--- ivtv/utils/ptune.pl 2004-03-23 19:43:41.000000000 +0100 >+++ ivtv.avermedia/utils/ptune.pl 2004-03-23 19:48:20.000000000 +0100 >@@ -1,6 +1,6 @@ > #!/usr/bin/perl > # >-# $Header: /cvsroot/ivtv/ivtv/ivtv/utils/ptune.pl,v 1.12 2003/07/16 03:30:39 pcxuser Exp $ >+# $Header: /home/komoriya/cvsroot/ivtv/utils/ptune.pl,v 1.1.1.1 2003/09/30 13:30:04 komoriya Exp $ > # > use strict; > >diff -urN ivtv/utils/test_ioctl.c ivtv.avermedia/utils/test_ioctl.c >--- ivtv/utils/test_ioctl.c 2004-03-23 19:43:41.000000000 +0100 >+++ ivtv.avermedia/utils/test_ioctl.c 2004-03-23 19:55:10.000000000 +0100 >@@ -41,6 +41,8 @@ > #define OptSetDebugLevel (1L<<19) > #define OptGetDebugLevel (1L<<20) > #define OptSetVBI (1L<<21) >+#define OptSetAudioMode (1L<<21) >+#define OptSetGPIO (1L<<22) > > /* Codec's specified */ > #define CAspect (1L<<1) >@@ -114,6 +116,9 @@ > printf(" get frequency for <tuner> [VIDIOC_G_FREQUENCY]\n"); > printf(" -r, --set-freq=tuner=<tuner>,freq=<freq>\n"); > printf(" sets frequency to <freq> for tuner <tuner> [VIDIOC_S_FREQUENCY]\n"); >+ printf(" -A, --set-audio-mode=tuner=<tuner>,audio_mode=<mode>\n"); >+ printf(" sets audio mode to <mode> for tuner <tuner> [VIDIOC_S_TUNER]\n"); >+ printf(" <mode> = 0:Mono 1:Stereo 2:Lang2/SAP 3:Lang1\n"); > printf(" -s, --list-standards\n"); > printf(" display supported video standards [VIDIOC_ENUMSTD]\n"); > printf(" -t, --get-standard\n"); >@@ -132,6 +137,8 @@ > printf(" contrast =<#> Picture contrast or luma gain. [0 - 127]\n"); > printf(" volume =<#> Overall audio volume. [0 - 65535]\n"); > printf(" mute =<#> Mute audio, i. e. set the volume to zero [boolean]\n"); >+ printf(" -i --set-gpio=<mode>\n"); >+ printf(" sets GPIO output to <mode> for debugging.[0x0000-0xffff]\n"); > printf(" -D --debug=level sets/gets the module ivtv_debug variable\n"); > exit(0); > } >@@ -298,6 +305,8 @@ > "volume", > #define SUB_MUTE 28 > "mute", >+ #define SUB_AUDIO_MODE 29 >+ "audio_mode", > NULL > }; > >@@ -326,6 +335,8 @@ > struct v4l2_frequency vf; /* get_freq/set_freq */ > struct v4l2_standard vs; /* list_std */ > struct msp_matrix mspm; /* set_io */ >+ struct v4l2_tuner vt; /* set_audio_mode */ >+ __u32 gpio_out = 0x0; /* GPIO output data */ > int debug_level = 0; > struct ivtv_ioctl_framesync frameinfo; > struct ivtv_ioctl_vbi_mode vbi_mode; >@@ -357,12 +368,14 @@ > {"set-input", 1, 0, 0}, > {"get-freq", 1, 0, 0}, > {"set-freq", 1, 0, 0}, >+ {"set-audio-mode", 1, 0, 0}, > {"list-standards", 0, 0, 0}, > {"get-standard", 0, 0, 0}, > {"set-standard", 1, 0, 0}, > {"set-io", 1, 0, 0}, > {"list-ctrls", 0, 0, 0}, > {"set-ctrl", 1, 0, 0}, >+ {"set-gpio", 1, 0, 0}, > {"sync", 0, 0, 0}, > {"debug", 1, 0, 0}, > {0, 0, 0, 0} >@@ -406,6 +419,8 @@ > ch = 'q'; > else if (!strcmp(long_options[option_index].name, "set-freq")) > ch = 'r'; >+ else if (!strcmp(long_options[option_index].name, "set-audio-mode")) >+ ch = 'A'; > else if (!strcmp(long_options[option_index].name, "list-standards")) > ch = 's'; > else if (!strcmp(long_options[option_index].name, "get-standard")) >@@ -418,6 +433,8 @@ > ch = 'Y'; > else if (!strcmp(long_options[option_index].name, "set-ctrl")) > ch = 'y'; >+ else if (!strcmp(long_options[option_index].name, "set-gpio")) >+ ch = 'i'; > else if (!strcmp(long_options[option_index].name, "debug")) > ch = 'D'; > } >@@ -747,6 +764,32 @@ > } > } > break; >+ case 'A': >+ set_opts |= OptSetAudioMode; >+ subs = optarg; >+ while(*subs != '\0') { >+ switch(getsubopt(&subs,subopts,&value) ) { >+ case SUB_TUNER: >+ if (value == NULL) { >+ printf("No value given to suboption <tuner>\n"); >+ usage(); >+ } >+ vt.index = strtol(value, 0L, 0); >+ break; >+ case SUB_AUDIO_MODE: >+ if (value == NULL) { >+ printf("No value given to suboption <mode>\n"); >+ usage(); >+ } >+ vt.audmode = strtol(value, 0L, 0); >+ break; >+ default: >+ printf("Invalid suboptions specified\n"); >+ usage(); >+ break; >+ } >+ } >+ break; > case 's': > set_opts |= OptListStandards; > break; >@@ -824,6 +867,10 @@ > } > } > break; >+ case 'i': >+ set_opts |= OptSetGPIO; >+ gpio_out = strtol(optarg, 0L, 0); >+ break; > case ':': > fprintf(stderr, "Option `%s' requires a value\n", argv[optind]); > usage(); >@@ -927,6 +974,19 @@ > printf("Frequency set to %d\n", vf.frequency); > } > >+ if (set_opts & OptSetAudioMode) { >+ __u32 audmode; >+ audmode = vt.audmode; >+ if (ioctl(fd, VIDIOC_G_TUNER, &vt) < 0) >+ fprintf(stderr, "ioctl: VIDIOC_G_TUNER failed\n"); >+ printf("ioctl: VIDIOC_S_TUNER\n"); >+ vt.audmode = audmode; >+ if (ioctl(fd, VIDIOC_S_TUNER, &vt) < 0) >+ fprintf(stderr, "ioctl: VIDIOC_S_TUNER failed\n"); >+ else >+ printf("Audio mode set to %d\n", vt.audmode); >+ } >+ > if (set_opts & OptSetStandard) { > printf("ioctl: VIDIOC_S_STD\n"); > if (ioctl(fd, VIDIOC_S_STD, &std) < 0) >@@ -1121,6 +1181,14 @@ > } > } > >+ if (set_opts & OptSetGPIO) { >+ printf("set GPIO output to 0x%04X\n", gpio_out); >+ vt.index = 0; >+ vt.audmode = 0x10000 | gpio_out; >+ if (ioctl(fd, VIDIOC_S_TUNER, &vt) < 0) >+ fprintf(stderr, "ioctl: VIDIOC_S_TUNER failed\n"); >+ } >+ > if (set_opts & OptSetDebugLevel) { > printf("ioctl: IVTV_IOCTL_SET_DEBUG_LEVEL\n"); > new_debug_level = debug_level;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 45473
:
27833
| 27893 |
27894