1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * cx18 audio-related functions 4 * 5 * Derived from ivtv-audio.c 6 * 7 * Copyright (C) 2007 Hans Verkuil <hverkuil@xs4all.nl> 8 */ 9 10 #include "cx18-driver.h" 11 #include "cx18-io.h" 12 #include "cx18-cards.h" 13 #include "cx18-audio.h" 14 15 #define CX18_AUDIO_ENABLE 0xc72014 16 #define CX18_AI1_MUX_MASK 0x30 17 #define CX18_AI1_MUX_I2S1 0x00 18 #define CX18_AI1_MUX_I2S2 0x10 19 #define CX18_AI1_MUX_843_I2S 0x20 20 21 /* Selects the audio input and output according to the current 22 settings. */ 23 int cx18_audio_set_io(struct cx18 *cx) 24 { 25 const struct cx18_card_audio_input *in; 26 u32 u, v; 27 int err; 28 29 /* Determine which input to use */ 30 if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags)) 31 in = &cx->card->radio_input; 32 else 33 in = &cx->card->audio_inputs[cx->audio_input]; 34 35 /* handle muxer chips */ 36 v4l2_subdev_call(cx->sd_extmux, audio, s_routing, 37 (u32) in->muxer_input, 0, 0); 38 39 err = cx18_call_hw_err(cx, cx->card->hw_audio_ctrl, 40 audio, s_routing, in->audio_input, 0, 0); 41 if (err) 42 return err; 43 44 /* FIXME - this internal mux should be abstracted to a subdev */ 45 u = cx18_read_reg(cx, CX18_AUDIO_ENABLE); 46 v = u & ~CX18_AI1_MUX_MASK; 47 switch (in->audio_input) { 48 case CX18_AV_AUDIO_SERIAL1: 49 v |= CX18_AI1_MUX_I2S1; 50 break; 51 case CX18_AV_AUDIO_SERIAL2: 52 v |= CX18_AI1_MUX_I2S2; 53 break; 54 default: 55 v |= CX18_AI1_MUX_843_I2S; 56 break; 57 } 58 if (v == u) { 59 /* force a toggle of some AI1 MUX control bits */ 60 u &= ~CX18_AI1_MUX_MASK; 61 switch (in->audio_input) { 62 case CX18_AV_AUDIO_SERIAL1: 63 u |= CX18_AI1_MUX_843_I2S; 64 break; 65 case CX18_AV_AUDIO_SERIAL2: 66 u |= CX18_AI1_MUX_843_I2S; 67 break; 68 default: 69 u |= CX18_AI1_MUX_I2S1; 70 break; 71 } 72 cx18_write_reg_expect(cx, u | 0xb00, CX18_AUDIO_ENABLE, 73 u, CX18_AI1_MUX_MASK); 74 } 75 cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE, 76 v, CX18_AI1_MUX_MASK); 77 return 0; 78 } 79