1/* 2 * 3 * $Id: pvrusb2-audio.c,v 1.1.1.1 2007/08/03 18:52:41 Exp $ 4 * 5 * Copyright (C) 2005 Mike Isely <isely@pobox.com> 6 * Copyright (C) 2004 Aurelien Alleaume <slts@free.fr> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * 21 */ 22 23#include "pvrusb2-audio.h" 24#include "pvrusb2-hdw-internal.h" 25#include "pvrusb2-debug.h" 26#include <linux/videodev2.h> 27#include <media/msp3400.h> 28#include <media/v4l2-common.h> 29 30struct pvr2_msp3400_handler { 31 struct pvr2_hdw *hdw; 32 struct pvr2_i2c_client *client; 33 struct pvr2_i2c_handler i2c_handler; 34 unsigned long stale_mask; 35}; 36 37 38/* This function selects the correct audio input source */ 39static void set_stereo(struct pvr2_msp3400_handler *ctxt) 40{ 41 struct pvr2_hdw *hdw = ctxt->hdw; 42 struct v4l2_routing route; 43 44 pvr2_trace(PVR2_TRACE_CHIPS,"i2c msp3400 v4l2 set_stereo"); 45 46 route.input = MSP_INPUT_DEFAULT; 47 route.output = MSP_OUTPUT(MSP_SC_IN_DSP_SCART1); 48 switch (hdw->input_val) { 49 case PVR2_CVAL_INPUT_TV: 50 break; 51 case PVR2_CVAL_INPUT_RADIO: 52 /* Assume that msp34xx also handle FM decoding, in which case 53 we're still using the tuner. */ 54 /* HV: actually it is more likely to be the SCART2 input if 55 the ivtv experience is any indication. */ 56 route.input = MSP_INPUT(MSP_IN_SCART2, MSP_IN_TUNER1, 57 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART); 58 break; 59 case PVR2_CVAL_INPUT_SVIDEO: 60 case PVR2_CVAL_INPUT_COMPOSITE: 61 /* SCART 1 input */ 62 route.input = MSP_INPUT(MSP_IN_SCART1, MSP_IN_TUNER1, 63 MSP_DSP_IN_SCART, MSP_DSP_IN_SCART); 64 break; 65 } 66 pvr2_i2c_client_cmd(ctxt->client,VIDIOC_INT_S_AUDIO_ROUTING,&route); 67} 68 69 70static int check_stereo(struct pvr2_msp3400_handler *ctxt) 71{ 72 struct pvr2_hdw *hdw = ctxt->hdw; 73 return hdw->input_dirty; 74} 75 76 77struct pvr2_msp3400_ops { 78 void (*update)(struct pvr2_msp3400_handler *); 79 int (*check)(struct pvr2_msp3400_handler *); 80}; 81 82 83static const struct pvr2_msp3400_ops msp3400_ops[] = { 84 { .update = set_stereo, .check = check_stereo}, 85}; 86 87 88static int msp3400_check(struct pvr2_msp3400_handler *ctxt) 89{ 90 unsigned long msk; 91 unsigned int idx; 92 93 for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) { 94 msk = 1 << idx; 95 if (ctxt->stale_mask & msk) continue; 96 if (msp3400_ops[idx].check(ctxt)) { 97 ctxt->stale_mask |= msk; 98 } 99 } 100 return ctxt->stale_mask != 0; 101} 102 103 104static void msp3400_update(struct pvr2_msp3400_handler *ctxt) 105{ 106 unsigned long msk; 107 unsigned int idx; 108 109 for (idx = 0; idx < ARRAY_SIZE(msp3400_ops); idx++) { 110 msk = 1 << idx; 111 if (!(ctxt->stale_mask & msk)) continue; 112 ctxt->stale_mask &= ~msk; 113 msp3400_ops[idx].update(ctxt); 114 } 115} 116 117 118static void pvr2_msp3400_detach(struct pvr2_msp3400_handler *ctxt) 119{ 120 ctxt->client->handler = NULL; 121 kfree(ctxt); 122} 123 124 125static unsigned int pvr2_msp3400_describe(struct pvr2_msp3400_handler *ctxt, 126 char *buf,unsigned int cnt) 127{ 128 return scnprintf(buf,cnt,"handler: pvrusb2-audio v4l2"); 129} 130 131 132static const struct pvr2_i2c_handler_functions msp3400_funcs = { 133 .detach = (void (*)(void *))pvr2_msp3400_detach, 134 .check = (int (*)(void *))msp3400_check, 135 .update = (void (*)(void *))msp3400_update, 136 .describe = (unsigned int (*)(void *,char *,unsigned int))pvr2_msp3400_describe, 137}; 138 139 140int pvr2_i2c_msp3400_setup(struct pvr2_hdw *hdw,struct pvr2_i2c_client *cp) 141{ 142 struct pvr2_msp3400_handler *ctxt; 143 if (cp->handler) return 0; 144 145 ctxt = kzalloc(sizeof(*ctxt),GFP_KERNEL); 146 if (!ctxt) return 0; 147 148 ctxt->i2c_handler.func_data = ctxt; 149 ctxt->i2c_handler.func_table = &msp3400_funcs; 150 ctxt->client = cp; 151 ctxt->hdw = hdw; 152 ctxt->stale_mask = (1 << ARRAY_SIZE(msp3400_ops)) - 1; 153 cp->handler = &ctxt->i2c_handler; 154 pvr2_trace(PVR2_TRACE_CHIPS,"i2c 0x%x msp3400 V4L2 handler set up", 155 cp->client->addr); 156 return !0; 157} 158 159 160/* 161 Stuff for Emacs to see, in order to encourage consistent editing style: 162 *** Local Variables: *** 163 *** mode: c *** 164 *** fill-column: 70 *** 165 *** tab-width: 8 *** 166 *** c-basic-offset: 8 *** 167 *** End: *** 168 */ 169