Merge tag 'drm-intel-next-2017-03-06' of git://anongit.freedesktop.org/git/drm-intel...
[sfrench/cifs-2.6.git] / drivers / media / pci / cx18 / cx18-audio.c
1 /*
2  *  cx18 audio-related functions
3  *
4  *  Derived from ivtv-audio.c
5  *
6  *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
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, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  */
18
19 #include "cx18-driver.h"
20 #include "cx18-io.h"
21 #include "cx18-cards.h"
22 #include "cx18-audio.h"
23
24 #define CX18_AUDIO_ENABLE    0xc72014
25 #define CX18_AI1_MUX_MASK    0x30
26 #define CX18_AI1_MUX_I2S1    0x00
27 #define CX18_AI1_MUX_I2S2    0x10
28 #define CX18_AI1_MUX_843_I2S 0x20
29
30 /* Selects the audio input and output according to the current
31    settings. */
32 int cx18_audio_set_io(struct cx18 *cx)
33 {
34         const struct cx18_card_audio_input *in;
35         u32 u, v;
36         int err;
37
38         /* Determine which input to use */
39         if (test_bit(CX18_F_I_RADIO_USER, &cx->i_flags))
40                 in = &cx->card->radio_input;
41         else
42                 in = &cx->card->audio_inputs[cx->audio_input];
43
44         /* handle muxer chips */
45         v4l2_subdev_call(cx->sd_extmux, audio, s_routing,
46                          (u32) in->muxer_input, 0, 0);
47
48         err = cx18_call_hw_err(cx, cx->card->hw_audio_ctrl,
49                                audio, s_routing, in->audio_input, 0, 0);
50         if (err)
51                 return err;
52
53         /* FIXME - this internal mux should be abstracted to a subdev */
54         u = cx18_read_reg(cx, CX18_AUDIO_ENABLE);
55         v = u & ~CX18_AI1_MUX_MASK;
56         switch (in->audio_input) {
57         case CX18_AV_AUDIO_SERIAL1:
58                 v |= CX18_AI1_MUX_I2S1;
59                 break;
60         case CX18_AV_AUDIO_SERIAL2:
61                 v |= CX18_AI1_MUX_I2S2;
62                 break;
63         default:
64                 v |= CX18_AI1_MUX_843_I2S;
65                 break;
66         }
67         if (v == u) {
68                 /* force a toggle of some AI1 MUX control bits */
69                 u &= ~CX18_AI1_MUX_MASK;
70                 switch (in->audio_input) {
71                 case CX18_AV_AUDIO_SERIAL1:
72                         u |= CX18_AI1_MUX_843_I2S;
73                         break;
74                 case CX18_AV_AUDIO_SERIAL2:
75                         u |= CX18_AI1_MUX_843_I2S;
76                         break;
77                 default:
78                         u |= CX18_AI1_MUX_I2S1;
79                         break;
80                 }
81                 cx18_write_reg_expect(cx, u | 0xb00, CX18_AUDIO_ENABLE,
82                                       u, CX18_AI1_MUX_MASK);
83         }
84         cx18_write_reg_expect(cx, v | 0xb00, CX18_AUDIO_ENABLE,
85                               v, CX18_AI1_MUX_MASK);
86         return 0;
87 }