diff options
Diffstat (limited to 'v4l_experimental/pvrusb2/pvrusb2-audio.c')
-rw-r--r-- | v4l_experimental/pvrusb2/pvrusb2-audio.c | 200 |
1 files changed, 108 insertions, 92 deletions
diff --git a/v4l_experimental/pvrusb2/pvrusb2-audio.c b/v4l_experimental/pvrusb2/pvrusb2-audio.c index 8ba8827be..81408e1a6 100644 --- a/v4l_experimental/pvrusb2/pvrusb2-audio.c +++ b/v4l_experimental/pvrusb2/pvrusb2-audio.c @@ -1,6 +1,6 @@ /* * - * $Id: pvrusb2-audio.c,v 1.2 2005/11/29 14:10:44 mchehab Exp $ + * $Id: pvrusb2-audio.c,v 1.3 2006/01/01 08:26:03 mcisely Exp $ * * Copyright (C) 2005 Mike Isely <isely@pobox.com> * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> @@ -20,7 +20,6 @@ * */ -#include "pvrusb2-i2c.h" #include "pvrusb2-audio.h" #include "pvrusb2-hdw-internal.h" #include "pvrusb2-debug.h" @@ -28,6 +27,15 @@ #include <linux/videodev.h> #include <media/audiochip.h> +struct pvr2_msp3400_handler { + struct pvr2_hdw *hdw; + struct pvr2_i2c_client *client; + struct pvr2_i2c_handler i2c_handler; + struct pvr2_audio_stat astat; + unsigned long stale_mask; +}; + + /* MCI <isely@pobox.com> 10-Mar-2005 - Rather than operate the msp34xx @@ -60,48 +68,22 @@ static int xlat_audiomode_to_v4l2(int id) return V4L2_TUNER_MODE_STEREO; } -/* Relay the video standard into the msp3400 module so that it can use - that information as additional clue(s) for correctly detecting - audio. */ -int pvr2_audio_set_standard(struct pvr2_hdw *hdw) -{ - struct video_channel vc; - memset(&vc,0,sizeof(vc)); - switch (hdw->controls[PVR2_CID_VIDEOSTANDARD].value) { - default: - case PVR2_CVAL_VIDEOSTANDARD_NTSC_M: - case PVR2_CVAL_VIDEOSTANDARD_PAL_M: /* Hack */ - vc.norm = VIDEO_MODE_NTSC; - break; - case PVR2_CVAL_VIDEOSTANDARD_SECAM_L: - vc.norm = VIDEO_MODE_SECAM; - break; - case PVR2_CVAL_VIDEOSTANDARD_PAL_BG: - case PVR2_CVAL_VIDEOSTANDARD_PAL_I: - case PVR2_CVAL_VIDEOSTANDARD_PAL_DK: - vc.norm = VIDEO_MODE_PAL; - break; - } - hdw->subsys_enabled_mask |= PVR2_SUBSYS_AUDIO_CFG_STD; - return pvr2_i2c_msp3400_cmd(hdw,VIDIOCSCHAN,&vc); -} /* This function selects the correct audio input source */ -int pvr2_audio_set_stereo(struct pvr2_hdw *hdw) +static void set_stereo(struct pvr2_msp3400_handler *ctxt) { - int stat; + struct pvr2_hdw *hdw = ctxt->hdw; unsigned short sarg = 0; struct msp_matrix mspm; - pvr2_trace(PVR2_TRACE_AUDIO,"pvr_audio_set_stereo"); + pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 set_stereo"); if (hdw->controls[PVR2_CID_INPUT].value == PVR2_CVAL_INPUT_TV) { struct v4l2_tuner vt; memset(&vt,0,sizeof(vt)); vt.audmode = xlat_audiomode_to_v4l2( hdw->controls[PVR2_CID_AUDIOMODE].value); - stat = pvr2_i2c_msp3400_cmd(hdw,VIDIOC_S_TUNER,&vt); - if (stat < 0) return stat; + pvr2_i2c_client_cmd(ctxt->client,VIDIOC_S_TUNER,&vt); } sarg = AUDIO_TUNER; @@ -119,8 +101,7 @@ int pvr2_audio_set_stereo(struct pvr2_hdw *hdw) sarg = AUDIO_EXTERN; break; } - stat = pvr2_i2c_msp3400_cmd(hdw,AUDC_SET_INPUT,&sarg); - if (stat < 0) return stat; + pvr2_i2c_client_cmd(ctxt->client,AUDC_SET_INPUT,&sarg); /* The above should have been enough to do the job, however msp3400.ko does an incomplete job of handling the scart @@ -144,82 +125,117 @@ int pvr2_audio_set_stereo(struct pvr2_hdw *hdw) break; } mspm.output = 1; - stat = pvr2_i2c_msp3400_cmd(hdw,MSP_SET_MATRIX,&mspm); - if (stat < 0) return stat; + pvr2_i2c_client_cmd(ctxt->client,MSP_SET_MATRIX,&mspm); +} - hdw->subsys_enabled_mask |= PVR2_SUBSYS_AUDIO_CFG_MODE; - return 0; +static int check_stereo(struct pvr2_msp3400_handler *ctxt) +{ + struct pvr2_hdw *hdw = ctxt->hdw; + return hdw->controls[PVR2_CID_INPUT].dirty != 0; } -/* This sets the audio volume parameters */ -int pvr2_audio_setvolume(struct pvr2_hdw *hdw) + +struct pvr2_msp3400_ops { + void (*update)(struct pvr2_msp3400_handler *); + int (*check)(struct pvr2_msp3400_handler *); +}; + + +static const struct pvr2_msp3400_ops msp3400_ops[] = { + { .update = set_stereo, .check = check_stereo}, +}; + + +static int msp3400_check(struct pvr2_msp3400_handler *ctxt) { - struct video_audio vt; - memset(&vt,0,sizeof(vt)); - vt.flags = (VIDEO_AUDIO_VOLUME | - VIDEO_AUDIO_BALANCE | - VIDEO_AUDIO_BASS | - VIDEO_AUDIO_TREBLE | - VIDEO_AUDIO_MUTABLE); - if (hdw->controls[PVR2_CID_MUTE].value) vt.flags |= VIDEO_AUDIO_MUTE; - vt.volume = hdw->controls[PVR2_CID_VOLUME].value; - vt.balance = hdw->controls[PVR2_CID_BALANCE].value; - vt.bass = hdw->controls[PVR2_CID_BASS].value; - vt.treble = hdw->controls[PVR2_CID_TREBLE].value; - pvr2_trace(PVR2_TRACE_AUDIO, - "pvr_audio_setvolume(vol=%d bal=%d bas=%d treb=%d mute=%d)", - vt.volume,vt.balance,vt.bass,vt.treble, - (vt.flags & VIDEO_AUDIO_MUTE) != 0); - - hdw->subsys_enabled_mask |= PVR2_SUBSYS_AUDIO_CFG_VBBTM; - - return pvr2_i2c_msp3400_cmd(hdw,VIDIOCSAUDIO,&vt); + unsigned long msk; + unsigned int idx; + + for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]); + idx++) { + msk = 1 << idx; + if (ctxt->stale_mask & msk) continue; + if (msp3400_ops[idx].check(ctxt)) { + ctxt->stale_mask |= msk; + } + } + return ctxt->stale_mask != 0; } + +static void msp3400_update(struct pvr2_msp3400_handler *ctxt) +{ + unsigned long msk; + unsigned int idx; + + for (idx = 0; idx < sizeof(msp3400_ops)/sizeof(msp3400_ops[0]); + idx++) { + msk = 1 << idx; + if (!(ctxt->stale_mask & msk)) continue; + ctxt->stale_mask &= ~msk; + msp3400_ops[idx].update(ctxt); + } +} + + /* This reads back the current volume parameters and signal type */ -int pvr2_audio_update_status(struct pvr2_hdw *hdw) +static int get_audio_status(struct pvr2_msp3400_handler *ctxt) { struct video_audio vt; int stat; - stat = pvr2_i2c_msp3400_cmd(hdw,VIDIOCGAUDIO,&vt); + memset(&vt,0,sizeof(vt)); + stat = pvr2_i2c_client_cmd(ctxt->client,VIDIOCGAUDIO,&vt); if (stat < 0) return stat; -#ifdef notdef - if (vt.flags & VIDEO_AUDIO_MUTABLE) { - hdw->controls[PVR2_CID_MUTE].value = - (vt.flags & VIDEO_AUDIO_MUTE) ? 1 : 0; - } - if (vt.flags & VIDEO_AUDIO_VOLUME) { - pvr2_trace(PVR2_TRACE_AUDIO, - "pvr_audio_update_status: got volume"); - hdw->controls[PVR2_CID_VOLUME].value = vt.volume; - } - if (vt.flags & VIDEO_AUDIO_BASS) { - pvr2_trace(PVR2_TRACE_AUDIO, - "pvr_audio_update_status: got bass"); - hdw->controls[PVR2_CID_BASS].value = vt.bass; - } - if (vt.flags & VIDEO_AUDIO_TREBLE) { - pvr2_trace(PVR2_TRACE_AUDIO, - "pvr_audio_update_status: got treble"); - hdw->controls[PVR2_CID_TREBLE].value = vt.treble; - } - if (vt.flags & (VIDEO_AUDIO_BALANCE|VIDEO_AUDIO_VOLUME)) { - pvr2_trace(PVR2_TRACE_AUDIO, - "pvr_audio_update_status: got balance"); - hdw->controls[PVR2_CID_BALANCE].value = vt.balance; - } -#endif - - hdw->flag_stereo = (vt.mode & VIDEO_SOUND_STEREO) != 0; - hdw->flag_bilingual = (vt.mode & - (VIDEO_SOUND_LANG1|VIDEO_SOUND_LANG2)) != 0; + ctxt->hdw->flag_stereo = (vt.mode & VIDEO_SOUND_STEREO) != 0; + ctxt->hdw->flag_bilingual = + (vt.mode & (VIDEO_SOUND_LANG1|VIDEO_SOUND_LANG2)) != 0; return 0; } +static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt) +{ + ctxt->client->handler = 0; + ctxt->hdw->audio_stat = 0; + kfree(ctxt); +} + + +const static struct pvr2_i2c_handler_functions msp3400_funcs = { + .detach = (void (*)(void *))pvr2_msp3400_detach, + .check = (int (*)(void *))msp3400_check, + .update = (void (*)(void *))msp3400_update, +}; + + +int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) +{ + struct pvr2_msp3400_handler *ctxt; + if (hdw->audio_stat) return 0; + if (cp->handler) return 0; + + ctxt = kmalloc(sizeof(*ctxt),GFP_KERNEL); + if (!ctxt) return 0; + memset(ctxt,0,sizeof(*ctxt)); + + ctxt->i2c_handler.func_data = ctxt; + ctxt->i2c_handler.func_table = &msp3400_funcs; + ctxt->client = cp; + ctxt->hdw = hdw; + ctxt->astat.ctxt = ctxt; + ctxt->astat.status = (int (*)(void *))get_audio_status; + ctxt->astat.detach = (void (*)(void *))pvr2_msp3400_detach; + ctxt->stale_mask = 1 << ((sizeof(msp3400_ops)/ + sizeof(msp3400_ops[0])) - 1); + cp->handler = &ctxt->i2c_handler; + hdw->audio_stat = &ctxt->astat; + return !0; +} + + /* Stuff for Emacs to see, in order to encourage consistent editing style: *** Local Variables: *** |