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. */
cx18_audio_set_io(struct cx18 * cx)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