xref: /linux/drivers/media/pci/cx18/cx18-audio.c (revision a4eb44a6435d6d8f9e642407a4a06f65eb90ca04)
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