Commit d7d7271f421f1e45289f2a737c7f636c02c673ce
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull media fixes from Mauro Carvalho Chehab: "Two driver fixes. One avoids reading any file at a system with a cx25821 board (fortunately, this is not a common device). The other one prevents reading after a buffer with ISDB-T devices based on mb86a20s." * 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: [media] cx25821: do not expose broken video output streams [media] mb86a20s: Fix estimate_rate setting
Showing 2 changed files Inline Diff
drivers/media/dvb-frontends/mb86a20s.c
1 | /* | 1 | /* |
2 | * Fujitu mb86a20s ISDB-T/ISDB-Tsb Module driver | 2 | * Fujitu mb86a20s ISDB-T/ISDB-Tsb Module driver |
3 | * | 3 | * |
4 | * Copyright (C) 2010-2013 Mauro Carvalho Chehab <mchehab@redhat.com> | 4 | * Copyright (C) 2010-2013 Mauro Carvalho Chehab <mchehab@redhat.com> |
5 | * Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com> | 5 | * Copyright (C) 2009-2010 Douglas Landgraf <dougsland@redhat.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the terms of the GNU General Public License as | 8 | * modify it under the terms of the GNU General Public License as |
9 | * published by the Free Software Foundation version 2. | 9 | * published by the Free Software Foundation version 2. |
10 | * | 10 | * |
11 | * This program is distributed in the hope that it will be useful, | 11 | * This program is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * General Public License for more details. | 14 | * General Public License for more details. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <asm/div64.h> | 18 | #include <asm/div64.h> |
19 | 19 | ||
20 | #include "dvb_frontend.h" | 20 | #include "dvb_frontend.h" |
21 | #include "mb86a20s.h" | 21 | #include "mb86a20s.h" |
22 | 22 | ||
23 | static int debug = 1; | 23 | static int debug = 1; |
24 | module_param(debug, int, 0644); | 24 | module_param(debug, int, 0644); |
25 | MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); | 25 | MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); |
26 | 26 | ||
27 | struct mb86a20s_state { | 27 | struct mb86a20s_state { |
28 | struct i2c_adapter *i2c; | 28 | struct i2c_adapter *i2c; |
29 | const struct mb86a20s_config *config; | 29 | const struct mb86a20s_config *config; |
30 | u32 last_frequency; | 30 | u32 last_frequency; |
31 | 31 | ||
32 | struct dvb_frontend frontend; | 32 | struct dvb_frontend frontend; |
33 | 33 | ||
34 | u32 estimated_rate[3]; | 34 | u32 estimated_rate[3]; |
35 | 35 | ||
36 | bool need_init; | 36 | bool need_init; |
37 | }; | 37 | }; |
38 | 38 | ||
39 | struct regdata { | 39 | struct regdata { |
40 | u8 reg; | 40 | u8 reg; |
41 | u8 data; | 41 | u8 data; |
42 | }; | 42 | }; |
43 | 43 | ||
44 | #define BER_SAMPLING_RATE 1 /* Seconds */ | 44 | #define BER_SAMPLING_RATE 1 /* Seconds */ |
45 | 45 | ||
46 | /* | 46 | /* |
47 | * Initialization sequence: Use whatevere default values that PV SBTVD | 47 | * Initialization sequence: Use whatevere default values that PV SBTVD |
48 | * does on its initialisation, obtained via USB snoop | 48 | * does on its initialisation, obtained via USB snoop |
49 | */ | 49 | */ |
50 | static struct regdata mb86a20s_init[] = { | 50 | static struct regdata mb86a20s_init[] = { |
51 | { 0x70, 0x0f }, | 51 | { 0x70, 0x0f }, |
52 | { 0x70, 0xff }, | 52 | { 0x70, 0xff }, |
53 | { 0x08, 0x01 }, | 53 | { 0x08, 0x01 }, |
54 | { 0x09, 0x3e }, | 54 | { 0x09, 0x3e }, |
55 | { 0x50, 0xd1 }, { 0x51, 0x22 }, | 55 | { 0x50, 0xd1 }, { 0x51, 0x22 }, |
56 | { 0x39, 0x01 }, | 56 | { 0x39, 0x01 }, |
57 | { 0x71, 0x00 }, | 57 | { 0x71, 0x00 }, |
58 | { 0x28, 0x2a }, { 0x29, 0x00 }, { 0x2a, 0xff }, { 0x2b, 0x80 }, | 58 | { 0x28, 0x2a }, { 0x29, 0x00 }, { 0x2a, 0xff }, { 0x2b, 0x80 }, |
59 | { 0x28, 0x20 }, { 0x29, 0x33 }, { 0x2a, 0xdf }, { 0x2b, 0xa9 }, | 59 | { 0x28, 0x20 }, { 0x29, 0x33 }, { 0x2a, 0xdf }, { 0x2b, 0xa9 }, |
60 | { 0x28, 0x22 }, { 0x29, 0x00 }, { 0x2a, 0x1f }, { 0x2b, 0xf0 }, | 60 | { 0x28, 0x22 }, { 0x29, 0x00 }, { 0x2a, 0x1f }, { 0x2b, 0xf0 }, |
61 | { 0x3b, 0x21 }, | 61 | { 0x3b, 0x21 }, |
62 | { 0x3c, 0x3a }, | 62 | { 0x3c, 0x3a }, |
63 | { 0x01, 0x0d }, | 63 | { 0x01, 0x0d }, |
64 | { 0x04, 0x08 }, { 0x05, 0x05 }, | 64 | { 0x04, 0x08 }, { 0x05, 0x05 }, |
65 | { 0x04, 0x0e }, { 0x05, 0x00 }, | 65 | { 0x04, 0x0e }, { 0x05, 0x00 }, |
66 | { 0x04, 0x0f }, { 0x05, 0x14 }, | 66 | { 0x04, 0x0f }, { 0x05, 0x14 }, |
67 | { 0x04, 0x0b }, { 0x05, 0x8c }, | 67 | { 0x04, 0x0b }, { 0x05, 0x8c }, |
68 | { 0x04, 0x00 }, { 0x05, 0x00 }, | 68 | { 0x04, 0x00 }, { 0x05, 0x00 }, |
69 | { 0x04, 0x01 }, { 0x05, 0x07 }, | 69 | { 0x04, 0x01 }, { 0x05, 0x07 }, |
70 | { 0x04, 0x02 }, { 0x05, 0x0f }, | 70 | { 0x04, 0x02 }, { 0x05, 0x0f }, |
71 | { 0x04, 0x03 }, { 0x05, 0xa0 }, | 71 | { 0x04, 0x03 }, { 0x05, 0xa0 }, |
72 | { 0x04, 0x09 }, { 0x05, 0x00 }, | 72 | { 0x04, 0x09 }, { 0x05, 0x00 }, |
73 | { 0x04, 0x0a }, { 0x05, 0xff }, | 73 | { 0x04, 0x0a }, { 0x05, 0xff }, |
74 | { 0x04, 0x27 }, { 0x05, 0x64 }, | 74 | { 0x04, 0x27 }, { 0x05, 0x64 }, |
75 | { 0x04, 0x28 }, { 0x05, 0x00 }, | 75 | { 0x04, 0x28 }, { 0x05, 0x00 }, |
76 | { 0x04, 0x1e }, { 0x05, 0xff }, | 76 | { 0x04, 0x1e }, { 0x05, 0xff }, |
77 | { 0x04, 0x29 }, { 0x05, 0x0a }, | 77 | { 0x04, 0x29 }, { 0x05, 0x0a }, |
78 | { 0x04, 0x32 }, { 0x05, 0x0a }, | 78 | { 0x04, 0x32 }, { 0x05, 0x0a }, |
79 | { 0x04, 0x14 }, { 0x05, 0x02 }, | 79 | { 0x04, 0x14 }, { 0x05, 0x02 }, |
80 | { 0x04, 0x04 }, { 0x05, 0x00 }, | 80 | { 0x04, 0x04 }, { 0x05, 0x00 }, |
81 | { 0x04, 0x05 }, { 0x05, 0x22 }, | 81 | { 0x04, 0x05 }, { 0x05, 0x22 }, |
82 | { 0x04, 0x06 }, { 0x05, 0x0e }, | 82 | { 0x04, 0x06 }, { 0x05, 0x0e }, |
83 | { 0x04, 0x07 }, { 0x05, 0xd8 }, | 83 | { 0x04, 0x07 }, { 0x05, 0xd8 }, |
84 | { 0x04, 0x12 }, { 0x05, 0x00 }, | 84 | { 0x04, 0x12 }, { 0x05, 0x00 }, |
85 | { 0x04, 0x13 }, { 0x05, 0xff }, | 85 | { 0x04, 0x13 }, { 0x05, 0xff }, |
86 | { 0x04, 0x15 }, { 0x05, 0x4e }, | 86 | { 0x04, 0x15 }, { 0x05, 0x4e }, |
87 | { 0x04, 0x16 }, { 0x05, 0x20 }, | 87 | { 0x04, 0x16 }, { 0x05, 0x20 }, |
88 | 88 | ||
89 | /* | 89 | /* |
90 | * On this demod, when the bit count reaches the count below, | 90 | * On this demod, when the bit count reaches the count below, |
91 | * it collects the bit error count. The bit counters are initialized | 91 | * it collects the bit error count. The bit counters are initialized |
92 | * to 65535 here. This warrants that all of them will be quickly | 92 | * to 65535 here. This warrants that all of them will be quickly |
93 | * calculated when device gets locked. As TMCC is parsed, the values | 93 | * calculated when device gets locked. As TMCC is parsed, the values |
94 | * will be adjusted later in the driver's code. | 94 | * will be adjusted later in the driver's code. |
95 | */ | 95 | */ |
96 | { 0x52, 0x01 }, /* Turn on BER before Viterbi */ | 96 | { 0x52, 0x01 }, /* Turn on BER before Viterbi */ |
97 | { 0x50, 0xa7 }, { 0x51, 0x00 }, | 97 | { 0x50, 0xa7 }, { 0x51, 0x00 }, |
98 | { 0x50, 0xa8 }, { 0x51, 0xff }, | 98 | { 0x50, 0xa8 }, { 0x51, 0xff }, |
99 | { 0x50, 0xa9 }, { 0x51, 0xff }, | 99 | { 0x50, 0xa9 }, { 0x51, 0xff }, |
100 | { 0x50, 0xaa }, { 0x51, 0x00 }, | 100 | { 0x50, 0xaa }, { 0x51, 0x00 }, |
101 | { 0x50, 0xab }, { 0x51, 0xff }, | 101 | { 0x50, 0xab }, { 0x51, 0xff }, |
102 | { 0x50, 0xac }, { 0x51, 0xff }, | 102 | { 0x50, 0xac }, { 0x51, 0xff }, |
103 | { 0x50, 0xad }, { 0x51, 0x00 }, | 103 | { 0x50, 0xad }, { 0x51, 0x00 }, |
104 | { 0x50, 0xae }, { 0x51, 0xff }, | 104 | { 0x50, 0xae }, { 0x51, 0xff }, |
105 | { 0x50, 0xaf }, { 0x51, 0xff }, | 105 | { 0x50, 0xaf }, { 0x51, 0xff }, |
106 | 106 | ||
107 | /* | 107 | /* |
108 | * On this demod, post BER counts blocks. When the count reaches the | 108 | * On this demod, post BER counts blocks. When the count reaches the |
109 | * value below, it collects the block error count. The block counters | 109 | * value below, it collects the block error count. The block counters |
110 | * are initialized to 127 here. This warrants that all of them will be | 110 | * are initialized to 127 here. This warrants that all of them will be |
111 | * quickly calculated when device gets locked. As TMCC is parsed, the | 111 | * quickly calculated when device gets locked. As TMCC is parsed, the |
112 | * values will be adjusted later in the driver's code. | 112 | * values will be adjusted later in the driver's code. |
113 | */ | 113 | */ |
114 | { 0x5e, 0x07 }, /* Turn on BER after Viterbi */ | 114 | { 0x5e, 0x07 }, /* Turn on BER after Viterbi */ |
115 | { 0x50, 0xdc }, { 0x51, 0x00 }, | 115 | { 0x50, 0xdc }, { 0x51, 0x00 }, |
116 | { 0x50, 0xdd }, { 0x51, 0x7f }, | 116 | { 0x50, 0xdd }, { 0x51, 0x7f }, |
117 | { 0x50, 0xde }, { 0x51, 0x00 }, | 117 | { 0x50, 0xde }, { 0x51, 0x00 }, |
118 | { 0x50, 0xdf }, { 0x51, 0x7f }, | 118 | { 0x50, 0xdf }, { 0x51, 0x7f }, |
119 | { 0x50, 0xe0 }, { 0x51, 0x00 }, | 119 | { 0x50, 0xe0 }, { 0x51, 0x00 }, |
120 | { 0x50, 0xe1 }, { 0x51, 0x7f }, | 120 | { 0x50, 0xe1 }, { 0x51, 0x7f }, |
121 | 121 | ||
122 | /* | 122 | /* |
123 | * On this demod, when the block count reaches the count below, | 123 | * On this demod, when the block count reaches the count below, |
124 | * it collects the block error count. The block counters are initialized | 124 | * it collects the block error count. The block counters are initialized |
125 | * to 127 here. This warrants that all of them will be quickly | 125 | * to 127 here. This warrants that all of them will be quickly |
126 | * calculated when device gets locked. As TMCC is parsed, the values | 126 | * calculated when device gets locked. As TMCC is parsed, the values |
127 | * will be adjusted later in the driver's code. | 127 | * will be adjusted later in the driver's code. |
128 | */ | 128 | */ |
129 | { 0x50, 0xb0 }, { 0x51, 0x07 }, /* Enable PER */ | 129 | { 0x50, 0xb0 }, { 0x51, 0x07 }, /* Enable PER */ |
130 | { 0x50, 0xb2 }, { 0x51, 0x00 }, | 130 | { 0x50, 0xb2 }, { 0x51, 0x00 }, |
131 | { 0x50, 0xb3 }, { 0x51, 0x7f }, | 131 | { 0x50, 0xb3 }, { 0x51, 0x7f }, |
132 | { 0x50, 0xb4 }, { 0x51, 0x00 }, | 132 | { 0x50, 0xb4 }, { 0x51, 0x00 }, |
133 | { 0x50, 0xb5 }, { 0x51, 0x7f }, | 133 | { 0x50, 0xb5 }, { 0x51, 0x7f }, |
134 | { 0x50, 0xb6 }, { 0x51, 0x00 }, | 134 | { 0x50, 0xb6 }, { 0x51, 0x00 }, |
135 | { 0x50, 0xb7 }, { 0x51, 0x7f }, | 135 | { 0x50, 0xb7 }, { 0x51, 0x7f }, |
136 | 136 | ||
137 | { 0x50, 0x50 }, { 0x51, 0x02 }, /* MER manual mode */ | 137 | { 0x50, 0x50 }, { 0x51, 0x02 }, /* MER manual mode */ |
138 | { 0x50, 0x51 }, { 0x51, 0x04 }, /* MER symbol 4 */ | 138 | { 0x50, 0x51 }, { 0x51, 0x04 }, /* MER symbol 4 */ |
139 | { 0x45, 0x04 }, /* CN symbol 4 */ | 139 | { 0x45, 0x04 }, /* CN symbol 4 */ |
140 | { 0x48, 0x04 }, /* CN manual mode */ | 140 | { 0x48, 0x04 }, /* CN manual mode */ |
141 | 141 | ||
142 | { 0x50, 0xd5 }, { 0x51, 0x01 }, /* Serial */ | 142 | { 0x50, 0xd5 }, { 0x51, 0x01 }, /* Serial */ |
143 | { 0x50, 0xd6 }, { 0x51, 0x1f }, | 143 | { 0x50, 0xd6 }, { 0x51, 0x1f }, |
144 | { 0x50, 0xd2 }, { 0x51, 0x03 }, | 144 | { 0x50, 0xd2 }, { 0x51, 0x03 }, |
145 | { 0x50, 0xd7 }, { 0x51, 0x3f }, | 145 | { 0x50, 0xd7 }, { 0x51, 0x3f }, |
146 | { 0x28, 0x74 }, { 0x29, 0x00 }, { 0x28, 0x74 }, { 0x29, 0x40 }, | 146 | { 0x28, 0x74 }, { 0x29, 0x00 }, { 0x28, 0x74 }, { 0x29, 0x40 }, |
147 | { 0x28, 0x46 }, { 0x29, 0x2c }, { 0x28, 0x46 }, { 0x29, 0x0c }, | 147 | { 0x28, 0x46 }, { 0x29, 0x2c }, { 0x28, 0x46 }, { 0x29, 0x0c }, |
148 | 148 | ||
149 | { 0x04, 0x40 }, { 0x05, 0x00 }, | 149 | { 0x04, 0x40 }, { 0x05, 0x00 }, |
150 | { 0x28, 0x00 }, { 0x29, 0x10 }, | 150 | { 0x28, 0x00 }, { 0x29, 0x10 }, |
151 | { 0x28, 0x05 }, { 0x29, 0x02 }, | 151 | { 0x28, 0x05 }, { 0x29, 0x02 }, |
152 | { 0x1c, 0x01 }, | 152 | { 0x1c, 0x01 }, |
153 | { 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x03 }, | 153 | { 0x28, 0x06 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x03 }, |
154 | { 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0d }, | 154 | { 0x28, 0x07 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0d }, |
155 | { 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 }, | 155 | { 0x28, 0x08 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x02 }, |
156 | { 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x01 }, | 156 | { 0x28, 0x09 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x01 }, |
157 | { 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x21 }, | 157 | { 0x28, 0x0a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x21 }, |
158 | { 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x29 }, | 158 | { 0x28, 0x0b }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x29 }, |
159 | { 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 }, | 159 | { 0x28, 0x0c }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x16 }, |
160 | { 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x31 }, | 160 | { 0x28, 0x0d }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x31 }, |
161 | { 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0e }, | 161 | { 0x28, 0x0e }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0e }, |
162 | { 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x4e }, | 162 | { 0x28, 0x0f }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x4e }, |
163 | { 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x46 }, | 163 | { 0x28, 0x10 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x46 }, |
164 | { 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f }, | 164 | { 0x28, 0x11 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x0f }, |
165 | { 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x56 }, | 165 | { 0x28, 0x12 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x56 }, |
166 | { 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x35 }, | 166 | { 0x28, 0x13 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x35 }, |
167 | { 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbe }, | 167 | { 0x28, 0x14 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbe }, |
168 | { 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0x84 }, | 168 | { 0x28, 0x15 }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0x84 }, |
169 | { 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x03 }, { 0x2b, 0xee }, | 169 | { 0x28, 0x16 }, { 0x29, 0x00 }, { 0x2a, 0x03 }, { 0x2b, 0xee }, |
170 | { 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x98 }, | 170 | { 0x28, 0x17 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x98 }, |
171 | { 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x9f }, | 171 | { 0x28, 0x18 }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x9f }, |
172 | { 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xb2 }, | 172 | { 0x28, 0x19 }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0xb2 }, |
173 | { 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0xc2 }, | 173 | { 0x28, 0x1a }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0xc2 }, |
174 | { 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0x4a }, | 174 | { 0x28, 0x1b }, { 0x29, 0x00 }, { 0x2a, 0x07 }, { 0x2b, 0x4a }, |
175 | { 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbc }, | 175 | { 0x28, 0x1c }, { 0x29, 0x00 }, { 0x2a, 0x01 }, { 0x2b, 0xbc }, |
176 | { 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x04 }, { 0x2b, 0xba }, | 176 | { 0x28, 0x1d }, { 0x29, 0x00 }, { 0x2a, 0x04 }, { 0x2b, 0xba }, |
177 | { 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0x14 }, | 177 | { 0x28, 0x1e }, { 0x29, 0x00 }, { 0x2a, 0x06 }, { 0x2b, 0x14 }, |
178 | { 0x50, 0x1e }, { 0x51, 0x5d }, | 178 | { 0x50, 0x1e }, { 0x51, 0x5d }, |
179 | { 0x50, 0x22 }, { 0x51, 0x00 }, | 179 | { 0x50, 0x22 }, { 0x51, 0x00 }, |
180 | { 0x50, 0x23 }, { 0x51, 0xc8 }, | 180 | { 0x50, 0x23 }, { 0x51, 0xc8 }, |
181 | { 0x50, 0x24 }, { 0x51, 0x00 }, | 181 | { 0x50, 0x24 }, { 0x51, 0x00 }, |
182 | { 0x50, 0x25 }, { 0x51, 0xf0 }, | 182 | { 0x50, 0x25 }, { 0x51, 0xf0 }, |
183 | { 0x50, 0x26 }, { 0x51, 0x00 }, | 183 | { 0x50, 0x26 }, { 0x51, 0x00 }, |
184 | { 0x50, 0x27 }, { 0x51, 0xc3 }, | 184 | { 0x50, 0x27 }, { 0x51, 0xc3 }, |
185 | { 0x50, 0x39 }, { 0x51, 0x02 }, | 185 | { 0x50, 0x39 }, { 0x51, 0x02 }, |
186 | { 0x28, 0x6a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 }, | 186 | { 0x28, 0x6a }, { 0x29, 0x00 }, { 0x2a, 0x00 }, { 0x2b, 0x00 }, |
187 | { 0xd0, 0x00 }, | 187 | { 0xd0, 0x00 }, |
188 | }; | 188 | }; |
189 | 189 | ||
190 | static struct regdata mb86a20s_reset_reception[] = { | 190 | static struct regdata mb86a20s_reset_reception[] = { |
191 | { 0x70, 0xf0 }, | 191 | { 0x70, 0xf0 }, |
192 | { 0x70, 0xff }, | 192 | { 0x70, 0xff }, |
193 | { 0x08, 0x01 }, | 193 | { 0x08, 0x01 }, |
194 | { 0x08, 0x00 }, | 194 | { 0x08, 0x00 }, |
195 | }; | 195 | }; |
196 | 196 | ||
197 | static struct regdata mb86a20s_per_ber_reset[] = { | 197 | static struct regdata mb86a20s_per_ber_reset[] = { |
198 | { 0x53, 0x00 }, /* pre BER Counter reset */ | 198 | { 0x53, 0x00 }, /* pre BER Counter reset */ |
199 | { 0x53, 0x07 }, | 199 | { 0x53, 0x07 }, |
200 | 200 | ||
201 | { 0x5f, 0x00 }, /* post BER Counter reset */ | 201 | { 0x5f, 0x00 }, /* post BER Counter reset */ |
202 | { 0x5f, 0x07 }, | 202 | { 0x5f, 0x07 }, |
203 | 203 | ||
204 | { 0x50, 0xb1 }, /* PER Counter reset */ | 204 | { 0x50, 0xb1 }, /* PER Counter reset */ |
205 | { 0x51, 0x07 }, | 205 | { 0x51, 0x07 }, |
206 | { 0x51, 0x00 }, | 206 | { 0x51, 0x00 }, |
207 | }; | 207 | }; |
208 | 208 | ||
209 | /* | 209 | /* |
210 | * I2C read/write functions and macros | 210 | * I2C read/write functions and macros |
211 | */ | 211 | */ |
212 | 212 | ||
213 | static int mb86a20s_i2c_writereg(struct mb86a20s_state *state, | 213 | static int mb86a20s_i2c_writereg(struct mb86a20s_state *state, |
214 | u8 i2c_addr, u8 reg, u8 data) | 214 | u8 i2c_addr, u8 reg, u8 data) |
215 | { | 215 | { |
216 | u8 buf[] = { reg, data }; | 216 | u8 buf[] = { reg, data }; |
217 | struct i2c_msg msg = { | 217 | struct i2c_msg msg = { |
218 | .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2 | 218 | .addr = i2c_addr, .flags = 0, .buf = buf, .len = 2 |
219 | }; | 219 | }; |
220 | int rc; | 220 | int rc; |
221 | 221 | ||
222 | rc = i2c_transfer(state->i2c, &msg, 1); | 222 | rc = i2c_transfer(state->i2c, &msg, 1); |
223 | if (rc != 1) { | 223 | if (rc != 1) { |
224 | dev_err(&state->i2c->dev, | 224 | dev_err(&state->i2c->dev, |
225 | "%s: writereg error (rc == %i, reg == 0x%02x, data == 0x%02x)\n", | 225 | "%s: writereg error (rc == %i, reg == 0x%02x, data == 0x%02x)\n", |
226 | __func__, rc, reg, data); | 226 | __func__, rc, reg, data); |
227 | return rc; | 227 | return rc; |
228 | } | 228 | } |
229 | 229 | ||
230 | return 0; | 230 | return 0; |
231 | } | 231 | } |
232 | 232 | ||
233 | static int mb86a20s_i2c_writeregdata(struct mb86a20s_state *state, | 233 | static int mb86a20s_i2c_writeregdata(struct mb86a20s_state *state, |
234 | u8 i2c_addr, struct regdata *rd, int size) | 234 | u8 i2c_addr, struct regdata *rd, int size) |
235 | { | 235 | { |
236 | int i, rc; | 236 | int i, rc; |
237 | 237 | ||
238 | for (i = 0; i < size; i++) { | 238 | for (i = 0; i < size; i++) { |
239 | rc = mb86a20s_i2c_writereg(state, i2c_addr, rd[i].reg, | 239 | rc = mb86a20s_i2c_writereg(state, i2c_addr, rd[i].reg, |
240 | rd[i].data); | 240 | rd[i].data); |
241 | if (rc < 0) | 241 | if (rc < 0) |
242 | return rc; | 242 | return rc; |
243 | } | 243 | } |
244 | return 0; | 244 | return 0; |
245 | } | 245 | } |
246 | 246 | ||
247 | static int mb86a20s_i2c_readreg(struct mb86a20s_state *state, | 247 | static int mb86a20s_i2c_readreg(struct mb86a20s_state *state, |
248 | u8 i2c_addr, u8 reg) | 248 | u8 i2c_addr, u8 reg) |
249 | { | 249 | { |
250 | u8 val; | 250 | u8 val; |
251 | int rc; | 251 | int rc; |
252 | struct i2c_msg msg[] = { | 252 | struct i2c_msg msg[] = { |
253 | { .addr = i2c_addr, .flags = 0, .buf = ®, .len = 1 }, | 253 | { .addr = i2c_addr, .flags = 0, .buf = ®, .len = 1 }, |
254 | { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 } | 254 | { .addr = i2c_addr, .flags = I2C_M_RD, .buf = &val, .len = 1 } |
255 | }; | 255 | }; |
256 | 256 | ||
257 | rc = i2c_transfer(state->i2c, msg, 2); | 257 | rc = i2c_transfer(state->i2c, msg, 2); |
258 | 258 | ||
259 | if (rc != 2) { | 259 | if (rc != 2) { |
260 | dev_err(&state->i2c->dev, "%s: reg=0x%x (error=%d)\n", | 260 | dev_err(&state->i2c->dev, "%s: reg=0x%x (error=%d)\n", |
261 | __func__, reg, rc); | 261 | __func__, reg, rc); |
262 | return (rc < 0) ? rc : -EIO; | 262 | return (rc < 0) ? rc : -EIO; |
263 | } | 263 | } |
264 | 264 | ||
265 | return val; | 265 | return val; |
266 | } | 266 | } |
267 | 267 | ||
268 | #define mb86a20s_readreg(state, reg) \ | 268 | #define mb86a20s_readreg(state, reg) \ |
269 | mb86a20s_i2c_readreg(state, state->config->demod_address, reg) | 269 | mb86a20s_i2c_readreg(state, state->config->demod_address, reg) |
270 | #define mb86a20s_writereg(state, reg, val) \ | 270 | #define mb86a20s_writereg(state, reg, val) \ |
271 | mb86a20s_i2c_writereg(state, state->config->demod_address, reg, val) | 271 | mb86a20s_i2c_writereg(state, state->config->demod_address, reg, val) |
272 | #define mb86a20s_writeregdata(state, regdata) \ | 272 | #define mb86a20s_writeregdata(state, regdata) \ |
273 | mb86a20s_i2c_writeregdata(state, state->config->demod_address, \ | 273 | mb86a20s_i2c_writeregdata(state, state->config->demod_address, \ |
274 | regdata, ARRAY_SIZE(regdata)) | 274 | regdata, ARRAY_SIZE(regdata)) |
275 | 275 | ||
276 | /* | 276 | /* |
277 | * Ancillary internal routines (likely compiled inlined) | 277 | * Ancillary internal routines (likely compiled inlined) |
278 | * | 278 | * |
279 | * The functions below assume that gateway lock has already obtained | 279 | * The functions below assume that gateway lock has already obtained |
280 | */ | 280 | */ |
281 | 281 | ||
282 | static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status) | 282 | static int mb86a20s_read_status(struct dvb_frontend *fe, fe_status_t *status) |
283 | { | 283 | { |
284 | struct mb86a20s_state *state = fe->demodulator_priv; | 284 | struct mb86a20s_state *state = fe->demodulator_priv; |
285 | int val; | 285 | int val; |
286 | 286 | ||
287 | *status = 0; | 287 | *status = 0; |
288 | 288 | ||
289 | val = mb86a20s_readreg(state, 0x0a) & 0xf; | 289 | val = mb86a20s_readreg(state, 0x0a) & 0xf; |
290 | if (val < 0) | 290 | if (val < 0) |
291 | return val; | 291 | return val; |
292 | 292 | ||
293 | if (val >= 2) | 293 | if (val >= 2) |
294 | *status |= FE_HAS_SIGNAL; | 294 | *status |= FE_HAS_SIGNAL; |
295 | 295 | ||
296 | if (val >= 4) | 296 | if (val >= 4) |
297 | *status |= FE_HAS_CARRIER; | 297 | *status |= FE_HAS_CARRIER; |
298 | 298 | ||
299 | if (val >= 5) | 299 | if (val >= 5) |
300 | *status |= FE_HAS_VITERBI; | 300 | *status |= FE_HAS_VITERBI; |
301 | 301 | ||
302 | if (val >= 7) | 302 | if (val >= 7) |
303 | *status |= FE_HAS_SYNC; | 303 | *status |= FE_HAS_SYNC; |
304 | 304 | ||
305 | if (val >= 8) /* Maybe 9? */ | 305 | if (val >= 8) /* Maybe 9? */ |
306 | *status |= FE_HAS_LOCK; | 306 | *status |= FE_HAS_LOCK; |
307 | 307 | ||
308 | dev_dbg(&state->i2c->dev, "%s: Status = 0x%02x (state = %d)\n", | 308 | dev_dbg(&state->i2c->dev, "%s: Status = 0x%02x (state = %d)\n", |
309 | __func__, *status, val); | 309 | __func__, *status, val); |
310 | 310 | ||
311 | return 0; | 311 | return 0; |
312 | } | 312 | } |
313 | 313 | ||
314 | static int mb86a20s_read_signal_strength(struct dvb_frontend *fe) | 314 | static int mb86a20s_read_signal_strength(struct dvb_frontend *fe) |
315 | { | 315 | { |
316 | struct mb86a20s_state *state = fe->demodulator_priv; | 316 | struct mb86a20s_state *state = fe->demodulator_priv; |
317 | int rc; | 317 | int rc; |
318 | unsigned rf_max, rf_min, rf; | 318 | unsigned rf_max, rf_min, rf; |
319 | 319 | ||
320 | /* Does a binary search to get RF strength */ | 320 | /* Does a binary search to get RF strength */ |
321 | rf_max = 0xfff; | 321 | rf_max = 0xfff; |
322 | rf_min = 0; | 322 | rf_min = 0; |
323 | do { | 323 | do { |
324 | rf = (rf_max + rf_min) / 2; | 324 | rf = (rf_max + rf_min) / 2; |
325 | rc = mb86a20s_writereg(state, 0x04, 0x1f); | 325 | rc = mb86a20s_writereg(state, 0x04, 0x1f); |
326 | if (rc < 0) | 326 | if (rc < 0) |
327 | return rc; | 327 | return rc; |
328 | rc = mb86a20s_writereg(state, 0x05, rf >> 8); | 328 | rc = mb86a20s_writereg(state, 0x05, rf >> 8); |
329 | if (rc < 0) | 329 | if (rc < 0) |
330 | return rc; | 330 | return rc; |
331 | rc = mb86a20s_writereg(state, 0x04, 0x20); | 331 | rc = mb86a20s_writereg(state, 0x04, 0x20); |
332 | if (rc < 0) | 332 | if (rc < 0) |
333 | return rc; | 333 | return rc; |
334 | rc = mb86a20s_writereg(state, 0x04, rf); | 334 | rc = mb86a20s_writereg(state, 0x04, rf); |
335 | if (rc < 0) | 335 | if (rc < 0) |
336 | return rc; | 336 | return rc; |
337 | 337 | ||
338 | rc = mb86a20s_readreg(state, 0x02); | 338 | rc = mb86a20s_readreg(state, 0x02); |
339 | if (rc < 0) | 339 | if (rc < 0) |
340 | return rc; | 340 | return rc; |
341 | if (rc & 0x08) | 341 | if (rc & 0x08) |
342 | rf_min = (rf_max + rf_min) / 2; | 342 | rf_min = (rf_max + rf_min) / 2; |
343 | else | 343 | else |
344 | rf_max = (rf_max + rf_min) / 2; | 344 | rf_max = (rf_max + rf_min) / 2; |
345 | if (rf_max - rf_min < 4) { | 345 | if (rf_max - rf_min < 4) { |
346 | rf = (rf_max + rf_min) / 2; | 346 | rf = (rf_max + rf_min) / 2; |
347 | 347 | ||
348 | /* Rescale it from 2^12 (4096) to 2^16 */ | 348 | /* Rescale it from 2^12 (4096) to 2^16 */ |
349 | rf <<= (16 - 12); | 349 | rf <<= (16 - 12); |
350 | dev_dbg(&state->i2c->dev, | 350 | dev_dbg(&state->i2c->dev, |
351 | "%s: signal strength = %d (%d < RF=%d < %d)\n", | 351 | "%s: signal strength = %d (%d < RF=%d < %d)\n", |
352 | __func__, rf, rf_min, rf >> 4, rf_max); | 352 | __func__, rf, rf_min, rf >> 4, rf_max); |
353 | return rf; | 353 | return rf; |
354 | } | 354 | } |
355 | } while (1); | 355 | } while (1); |
356 | 356 | ||
357 | return 0; | 357 | return 0; |
358 | } | 358 | } |
359 | 359 | ||
360 | static int mb86a20s_get_modulation(struct mb86a20s_state *state, | 360 | static int mb86a20s_get_modulation(struct mb86a20s_state *state, |
361 | unsigned layer) | 361 | unsigned layer) |
362 | { | 362 | { |
363 | int rc; | 363 | int rc; |
364 | static unsigned char reg[] = { | 364 | static unsigned char reg[] = { |
365 | [0] = 0x86, /* Layer A */ | 365 | [0] = 0x86, /* Layer A */ |
366 | [1] = 0x8a, /* Layer B */ | 366 | [1] = 0x8a, /* Layer B */ |
367 | [2] = 0x8e, /* Layer C */ | 367 | [2] = 0x8e, /* Layer C */ |
368 | }; | 368 | }; |
369 | 369 | ||
370 | if (layer >= ARRAY_SIZE(reg)) | 370 | if (layer >= ARRAY_SIZE(reg)) |
371 | return -EINVAL; | 371 | return -EINVAL; |
372 | rc = mb86a20s_writereg(state, 0x6d, reg[layer]); | 372 | rc = mb86a20s_writereg(state, 0x6d, reg[layer]); |
373 | if (rc < 0) | 373 | if (rc < 0) |
374 | return rc; | 374 | return rc; |
375 | rc = mb86a20s_readreg(state, 0x6e); | 375 | rc = mb86a20s_readreg(state, 0x6e); |
376 | if (rc < 0) | 376 | if (rc < 0) |
377 | return rc; | 377 | return rc; |
378 | switch ((rc >> 4) & 0x07) { | 378 | switch ((rc >> 4) & 0x07) { |
379 | case 0: | 379 | case 0: |
380 | return DQPSK; | 380 | return DQPSK; |
381 | case 1: | 381 | case 1: |
382 | return QPSK; | 382 | return QPSK; |
383 | case 2: | 383 | case 2: |
384 | return QAM_16; | 384 | return QAM_16; |
385 | case 3: | 385 | case 3: |
386 | return QAM_64; | 386 | return QAM_64; |
387 | default: | 387 | default: |
388 | return QAM_AUTO; | 388 | return QAM_AUTO; |
389 | } | 389 | } |
390 | } | 390 | } |
391 | 391 | ||
392 | static int mb86a20s_get_fec(struct mb86a20s_state *state, | 392 | static int mb86a20s_get_fec(struct mb86a20s_state *state, |
393 | unsigned layer) | 393 | unsigned layer) |
394 | { | 394 | { |
395 | int rc; | 395 | int rc; |
396 | 396 | ||
397 | static unsigned char reg[] = { | 397 | static unsigned char reg[] = { |
398 | [0] = 0x87, /* Layer A */ | 398 | [0] = 0x87, /* Layer A */ |
399 | [1] = 0x8b, /* Layer B */ | 399 | [1] = 0x8b, /* Layer B */ |
400 | [2] = 0x8f, /* Layer C */ | 400 | [2] = 0x8f, /* Layer C */ |
401 | }; | 401 | }; |
402 | 402 | ||
403 | if (layer >= ARRAY_SIZE(reg)) | 403 | if (layer >= ARRAY_SIZE(reg)) |
404 | return -EINVAL; | 404 | return -EINVAL; |
405 | rc = mb86a20s_writereg(state, 0x6d, reg[layer]); | 405 | rc = mb86a20s_writereg(state, 0x6d, reg[layer]); |
406 | if (rc < 0) | 406 | if (rc < 0) |
407 | return rc; | 407 | return rc; |
408 | rc = mb86a20s_readreg(state, 0x6e); | 408 | rc = mb86a20s_readreg(state, 0x6e); |
409 | if (rc < 0) | 409 | if (rc < 0) |
410 | return rc; | 410 | return rc; |
411 | switch ((rc >> 4) & 0x07) { | 411 | switch ((rc >> 4) & 0x07) { |
412 | case 0: | 412 | case 0: |
413 | return FEC_1_2; | 413 | return FEC_1_2; |
414 | case 1: | 414 | case 1: |
415 | return FEC_2_3; | 415 | return FEC_2_3; |
416 | case 2: | 416 | case 2: |
417 | return FEC_3_4; | 417 | return FEC_3_4; |
418 | case 3: | 418 | case 3: |
419 | return FEC_5_6; | 419 | return FEC_5_6; |
420 | case 4: | 420 | case 4: |
421 | return FEC_7_8; | 421 | return FEC_7_8; |
422 | default: | 422 | default: |
423 | return FEC_AUTO; | 423 | return FEC_AUTO; |
424 | } | 424 | } |
425 | } | 425 | } |
426 | 426 | ||
427 | static int mb86a20s_get_interleaving(struct mb86a20s_state *state, | 427 | static int mb86a20s_get_interleaving(struct mb86a20s_state *state, |
428 | unsigned layer) | 428 | unsigned layer) |
429 | { | 429 | { |
430 | int rc; | 430 | int rc; |
431 | 431 | ||
432 | static unsigned char reg[] = { | 432 | static unsigned char reg[] = { |
433 | [0] = 0x88, /* Layer A */ | 433 | [0] = 0x88, /* Layer A */ |
434 | [1] = 0x8c, /* Layer B */ | 434 | [1] = 0x8c, /* Layer B */ |
435 | [2] = 0x90, /* Layer C */ | 435 | [2] = 0x90, /* Layer C */ |
436 | }; | 436 | }; |
437 | 437 | ||
438 | if (layer >= ARRAY_SIZE(reg)) | 438 | if (layer >= ARRAY_SIZE(reg)) |
439 | return -EINVAL; | 439 | return -EINVAL; |
440 | rc = mb86a20s_writereg(state, 0x6d, reg[layer]); | 440 | rc = mb86a20s_writereg(state, 0x6d, reg[layer]); |
441 | if (rc < 0) | 441 | if (rc < 0) |
442 | return rc; | 442 | return rc; |
443 | rc = mb86a20s_readreg(state, 0x6e); | 443 | rc = mb86a20s_readreg(state, 0x6e); |
444 | if (rc < 0) | 444 | if (rc < 0) |
445 | return rc; | 445 | return rc; |
446 | 446 | ||
447 | switch ((rc >> 4) & 0x07) { | 447 | switch ((rc >> 4) & 0x07) { |
448 | case 1: | 448 | case 1: |
449 | return GUARD_INTERVAL_1_4; | 449 | return GUARD_INTERVAL_1_4; |
450 | case 2: | 450 | case 2: |
451 | return GUARD_INTERVAL_1_8; | 451 | return GUARD_INTERVAL_1_8; |
452 | case 3: | 452 | case 3: |
453 | return GUARD_INTERVAL_1_16; | 453 | return GUARD_INTERVAL_1_16; |
454 | case 4: | 454 | case 4: |
455 | return GUARD_INTERVAL_1_32; | 455 | return GUARD_INTERVAL_1_32; |
456 | 456 | ||
457 | default: | 457 | default: |
458 | case 0: | 458 | case 0: |
459 | return GUARD_INTERVAL_AUTO; | 459 | return GUARD_INTERVAL_AUTO; |
460 | } | 460 | } |
461 | } | 461 | } |
462 | 462 | ||
463 | static int mb86a20s_get_segment_count(struct mb86a20s_state *state, | 463 | static int mb86a20s_get_segment_count(struct mb86a20s_state *state, |
464 | unsigned layer) | 464 | unsigned layer) |
465 | { | 465 | { |
466 | int rc, count; | 466 | int rc, count; |
467 | static unsigned char reg[] = { | 467 | static unsigned char reg[] = { |
468 | [0] = 0x89, /* Layer A */ | 468 | [0] = 0x89, /* Layer A */ |
469 | [1] = 0x8d, /* Layer B */ | 469 | [1] = 0x8d, /* Layer B */ |
470 | [2] = 0x91, /* Layer C */ | 470 | [2] = 0x91, /* Layer C */ |
471 | }; | 471 | }; |
472 | 472 | ||
473 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 473 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
474 | 474 | ||
475 | if (layer >= ARRAY_SIZE(reg)) | 475 | if (layer >= ARRAY_SIZE(reg)) |
476 | return -EINVAL; | 476 | return -EINVAL; |
477 | 477 | ||
478 | rc = mb86a20s_writereg(state, 0x6d, reg[layer]); | 478 | rc = mb86a20s_writereg(state, 0x6d, reg[layer]); |
479 | if (rc < 0) | 479 | if (rc < 0) |
480 | return rc; | 480 | return rc; |
481 | rc = mb86a20s_readreg(state, 0x6e); | 481 | rc = mb86a20s_readreg(state, 0x6e); |
482 | if (rc < 0) | 482 | if (rc < 0) |
483 | return rc; | 483 | return rc; |
484 | count = (rc >> 4) & 0x0f; | 484 | count = (rc >> 4) & 0x0f; |
485 | 485 | ||
486 | dev_dbg(&state->i2c->dev, "%s: segments: %d.\n", __func__, count); | 486 | dev_dbg(&state->i2c->dev, "%s: segments: %d.\n", __func__, count); |
487 | 487 | ||
488 | return count; | 488 | return count; |
489 | } | 489 | } |
490 | 490 | ||
491 | static void mb86a20s_reset_frontend_cache(struct dvb_frontend *fe) | 491 | static void mb86a20s_reset_frontend_cache(struct dvb_frontend *fe) |
492 | { | 492 | { |
493 | struct mb86a20s_state *state = fe->demodulator_priv; | 493 | struct mb86a20s_state *state = fe->demodulator_priv; |
494 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 494 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
495 | 495 | ||
496 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 496 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
497 | 497 | ||
498 | /* Fixed parameters */ | 498 | /* Fixed parameters */ |
499 | c->delivery_system = SYS_ISDBT; | 499 | c->delivery_system = SYS_ISDBT; |
500 | c->bandwidth_hz = 6000000; | 500 | c->bandwidth_hz = 6000000; |
501 | 501 | ||
502 | /* Initialize values that will be later autodetected */ | 502 | /* Initialize values that will be later autodetected */ |
503 | c->isdbt_layer_enabled = 0; | 503 | c->isdbt_layer_enabled = 0; |
504 | c->transmission_mode = TRANSMISSION_MODE_AUTO; | 504 | c->transmission_mode = TRANSMISSION_MODE_AUTO; |
505 | c->guard_interval = GUARD_INTERVAL_AUTO; | 505 | c->guard_interval = GUARD_INTERVAL_AUTO; |
506 | c->isdbt_sb_mode = 0; | 506 | c->isdbt_sb_mode = 0; |
507 | c->isdbt_sb_segment_count = 0; | 507 | c->isdbt_sb_segment_count = 0; |
508 | } | 508 | } |
509 | 509 | ||
510 | /* | 510 | /* |
511 | * Estimates the bit rate using the per-segment bit rate given by | 511 | * Estimates the bit rate using the per-segment bit rate given by |
512 | * ABNT/NBR 15601 spec (table 4). | 512 | * ABNT/NBR 15601 spec (table 4). |
513 | */ | 513 | */ |
514 | static u32 isdbt_rate[3][5][4] = { | 514 | static u32 isdbt_rate[3][5][4] = { |
515 | { /* DQPSK/QPSK */ | 515 | { /* DQPSK/QPSK */ |
516 | { 280850, 312060, 330420, 340430 }, /* 1/2 */ | 516 | { 280850, 312060, 330420, 340430 }, /* 1/2 */ |
517 | { 374470, 416080, 440560, 453910 }, /* 2/3 */ | 517 | { 374470, 416080, 440560, 453910 }, /* 2/3 */ |
518 | { 421280, 468090, 495630, 510650 }, /* 3/4 */ | 518 | { 421280, 468090, 495630, 510650 }, /* 3/4 */ |
519 | { 468090, 520100, 550700, 567390 }, /* 5/6 */ | 519 | { 468090, 520100, 550700, 567390 }, /* 5/6 */ |
520 | { 491500, 546110, 578230, 595760 }, /* 7/8 */ | 520 | { 491500, 546110, 578230, 595760 }, /* 7/8 */ |
521 | }, { /* QAM16 */ | 521 | }, { /* QAM16 */ |
522 | { 561710, 624130, 660840, 680870 }, /* 1/2 */ | 522 | { 561710, 624130, 660840, 680870 }, /* 1/2 */ |
523 | { 748950, 832170, 881120, 907820 }, /* 2/3 */ | 523 | { 748950, 832170, 881120, 907820 }, /* 2/3 */ |
524 | { 842570, 936190, 991260, 1021300 }, /* 3/4 */ | 524 | { 842570, 936190, 991260, 1021300 }, /* 3/4 */ |
525 | { 936190, 1040210, 1101400, 1134780 }, /* 5/6 */ | 525 | { 936190, 1040210, 1101400, 1134780 }, /* 5/6 */ |
526 | { 983000, 1092220, 1156470, 1191520 }, /* 7/8 */ | 526 | { 983000, 1092220, 1156470, 1191520 }, /* 7/8 */ |
527 | }, { /* QAM64 */ | 527 | }, { /* QAM64 */ |
528 | { 842570, 936190, 991260, 1021300 }, /* 1/2 */ | 528 | { 842570, 936190, 991260, 1021300 }, /* 1/2 */ |
529 | { 1123430, 1248260, 1321680, 1361740 }, /* 2/3 */ | 529 | { 1123430, 1248260, 1321680, 1361740 }, /* 2/3 */ |
530 | { 1263860, 1404290, 1486900, 1531950 }, /* 3/4 */ | 530 | { 1263860, 1404290, 1486900, 1531950 }, /* 3/4 */ |
531 | { 1404290, 1560320, 1652110, 1702170 }, /* 5/6 */ | 531 | { 1404290, 1560320, 1652110, 1702170 }, /* 5/6 */ |
532 | { 1474500, 1638340, 1734710, 1787280 }, /* 7/8 */ | 532 | { 1474500, 1638340, 1734710, 1787280 }, /* 7/8 */ |
533 | } | 533 | } |
534 | }; | 534 | }; |
535 | 535 | ||
536 | static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer, | 536 | static void mb86a20s_layer_bitrate(struct dvb_frontend *fe, u32 layer, |
537 | u32 modulation, u32 fec, u32 interleaving, | 537 | u32 modulation, u32 fec, u32 interleaving, |
538 | u32 segment) | 538 | u32 segment) |
539 | { | 539 | { |
540 | struct mb86a20s_state *state = fe->demodulator_priv; | 540 | struct mb86a20s_state *state = fe->demodulator_priv; |
541 | u32 rate; | 541 | u32 rate; |
542 | int m, f, i; | 542 | int m, f, i; |
543 | 543 | ||
544 | /* | 544 | /* |
545 | * If modulation/fec/interleaving is not detected, the default is | 545 | * If modulation/fec/interleaving is not detected, the default is |
546 | * to consider the lowest bit rate, to avoid taking too long time | 546 | * to consider the lowest bit rate, to avoid taking too long time |
547 | * to get BER. | 547 | * to get BER. |
548 | */ | 548 | */ |
549 | switch (modulation) { | 549 | switch (modulation) { |
550 | case DQPSK: | 550 | case DQPSK: |
551 | case QPSK: | 551 | case QPSK: |
552 | default: | 552 | default: |
553 | m = 0; | 553 | m = 0; |
554 | break; | 554 | break; |
555 | case QAM_16: | 555 | case QAM_16: |
556 | m = 1; | 556 | m = 1; |
557 | break; | 557 | break; |
558 | case QAM_64: | 558 | case QAM_64: |
559 | m = 2; | 559 | m = 2; |
560 | break; | 560 | break; |
561 | } | 561 | } |
562 | 562 | ||
563 | switch (fec) { | 563 | switch (fec) { |
564 | default: | 564 | default: |
565 | case FEC_1_2: | 565 | case FEC_1_2: |
566 | case FEC_AUTO: | 566 | case FEC_AUTO: |
567 | f = 0; | 567 | f = 0; |
568 | break; | 568 | break; |
569 | case FEC_2_3: | 569 | case FEC_2_3: |
570 | f = 1; | 570 | f = 1; |
571 | break; | 571 | break; |
572 | case FEC_3_4: | 572 | case FEC_3_4: |
573 | f = 2; | 573 | f = 2; |
574 | break; | 574 | break; |
575 | case FEC_5_6: | 575 | case FEC_5_6: |
576 | f = 3; | 576 | f = 3; |
577 | break; | 577 | break; |
578 | case FEC_7_8: | 578 | case FEC_7_8: |
579 | f = 4; | 579 | f = 4; |
580 | break; | 580 | break; |
581 | } | 581 | } |
582 | 582 | ||
583 | switch (interleaving) { | 583 | switch (interleaving) { |
584 | default: | 584 | default: |
585 | case GUARD_INTERVAL_1_4: | 585 | case GUARD_INTERVAL_1_4: |
586 | i = 0; | 586 | i = 0; |
587 | break; | 587 | break; |
588 | case GUARD_INTERVAL_1_8: | 588 | case GUARD_INTERVAL_1_8: |
589 | i = 1; | 589 | i = 1; |
590 | break; | 590 | break; |
591 | case GUARD_INTERVAL_1_16: | 591 | case GUARD_INTERVAL_1_16: |
592 | i = 2; | 592 | i = 2; |
593 | break; | 593 | break; |
594 | case GUARD_INTERVAL_1_32: | 594 | case GUARD_INTERVAL_1_32: |
595 | i = 3; | 595 | i = 3; |
596 | break; | 596 | break; |
597 | } | 597 | } |
598 | 598 | ||
599 | /* Samples BER at BER_SAMPLING_RATE seconds */ | 599 | /* Samples BER at BER_SAMPLING_RATE seconds */ |
600 | rate = isdbt_rate[m][f][i] * segment * BER_SAMPLING_RATE; | 600 | rate = isdbt_rate[m][f][i] * segment * BER_SAMPLING_RATE; |
601 | 601 | ||
602 | /* Avoids sampling too quickly or to overflow the register */ | 602 | /* Avoids sampling too quickly or to overflow the register */ |
603 | if (rate < 256) | 603 | if (rate < 256) |
604 | rate = 256; | 604 | rate = 256; |
605 | else if (rate > (1 << 24) - 1) | 605 | else if (rate > (1 << 24) - 1) |
606 | rate = (1 << 24) - 1; | 606 | rate = (1 << 24) - 1; |
607 | 607 | ||
608 | dev_dbg(&state->i2c->dev, | 608 | dev_dbg(&state->i2c->dev, |
609 | "%s: layer %c bitrate: %d kbps; counter = %d (0x%06x)\n", | 609 | "%s: layer %c bitrate: %d kbps; counter = %d (0x%06x)\n", |
610 | __func__, 'A' + layer, segment * isdbt_rate[m][f][i]/1000, | 610 | __func__, 'A' + layer, segment * isdbt_rate[m][f][i]/1000, |
611 | rate, rate); | 611 | rate, rate); |
612 | 612 | ||
613 | state->estimated_rate[i] = rate; | 613 | state->estimated_rate[layer] = rate; |
614 | } | 614 | } |
615 | 615 | ||
616 | 616 | ||
617 | static int mb86a20s_get_frontend(struct dvb_frontend *fe) | 617 | static int mb86a20s_get_frontend(struct dvb_frontend *fe) |
618 | { | 618 | { |
619 | struct mb86a20s_state *state = fe->demodulator_priv; | 619 | struct mb86a20s_state *state = fe->demodulator_priv; |
620 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 620 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
621 | int i, rc; | 621 | int i, rc; |
622 | 622 | ||
623 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 623 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
624 | 624 | ||
625 | /* Reset frontend cache to default values */ | 625 | /* Reset frontend cache to default values */ |
626 | mb86a20s_reset_frontend_cache(fe); | 626 | mb86a20s_reset_frontend_cache(fe); |
627 | 627 | ||
628 | /* Check for partial reception */ | 628 | /* Check for partial reception */ |
629 | rc = mb86a20s_writereg(state, 0x6d, 0x85); | 629 | rc = mb86a20s_writereg(state, 0x6d, 0x85); |
630 | if (rc < 0) | 630 | if (rc < 0) |
631 | return rc; | 631 | return rc; |
632 | rc = mb86a20s_readreg(state, 0x6e); | 632 | rc = mb86a20s_readreg(state, 0x6e); |
633 | if (rc < 0) | 633 | if (rc < 0) |
634 | return rc; | 634 | return rc; |
635 | c->isdbt_partial_reception = (rc & 0x10) ? 1 : 0; | 635 | c->isdbt_partial_reception = (rc & 0x10) ? 1 : 0; |
636 | 636 | ||
637 | /* Get per-layer data */ | 637 | /* Get per-layer data */ |
638 | 638 | ||
639 | for (i = 0; i < 3; i++) { | 639 | for (i = 0; i < 3; i++) { |
640 | dev_dbg(&state->i2c->dev, "%s: getting data for layer %c.\n", | 640 | dev_dbg(&state->i2c->dev, "%s: getting data for layer %c.\n", |
641 | __func__, 'A' + i); | 641 | __func__, 'A' + i); |
642 | 642 | ||
643 | rc = mb86a20s_get_segment_count(state, i); | 643 | rc = mb86a20s_get_segment_count(state, i); |
644 | if (rc < 0) | 644 | if (rc < 0) |
645 | goto noperlayer_error; | 645 | goto noperlayer_error; |
646 | if (rc >= 0 && rc < 14) { | 646 | if (rc >= 0 && rc < 14) { |
647 | c->layer[i].segment_count = rc; | 647 | c->layer[i].segment_count = rc; |
648 | } else { | 648 | } else { |
649 | c->layer[i].segment_count = 0; | 649 | c->layer[i].segment_count = 0; |
650 | state->estimated_rate[i] = 0; | 650 | state->estimated_rate[i] = 0; |
651 | continue; | 651 | continue; |
652 | } | 652 | } |
653 | c->isdbt_layer_enabled |= 1 << i; | 653 | c->isdbt_layer_enabled |= 1 << i; |
654 | rc = mb86a20s_get_modulation(state, i); | 654 | rc = mb86a20s_get_modulation(state, i); |
655 | if (rc < 0) | 655 | if (rc < 0) |
656 | goto noperlayer_error; | 656 | goto noperlayer_error; |
657 | dev_dbg(&state->i2c->dev, "%s: modulation %d.\n", | 657 | dev_dbg(&state->i2c->dev, "%s: modulation %d.\n", |
658 | __func__, rc); | 658 | __func__, rc); |
659 | c->layer[i].modulation = rc; | 659 | c->layer[i].modulation = rc; |
660 | rc = mb86a20s_get_fec(state, i); | 660 | rc = mb86a20s_get_fec(state, i); |
661 | if (rc < 0) | 661 | if (rc < 0) |
662 | goto noperlayer_error; | 662 | goto noperlayer_error; |
663 | dev_dbg(&state->i2c->dev, "%s: FEC %d.\n", | 663 | dev_dbg(&state->i2c->dev, "%s: FEC %d.\n", |
664 | __func__, rc); | 664 | __func__, rc); |
665 | c->layer[i].fec = rc; | 665 | c->layer[i].fec = rc; |
666 | rc = mb86a20s_get_interleaving(state, i); | 666 | rc = mb86a20s_get_interleaving(state, i); |
667 | if (rc < 0) | 667 | if (rc < 0) |
668 | goto noperlayer_error; | 668 | goto noperlayer_error; |
669 | dev_dbg(&state->i2c->dev, "%s: interleaving %d.\n", | 669 | dev_dbg(&state->i2c->dev, "%s: interleaving %d.\n", |
670 | __func__, rc); | 670 | __func__, rc); |
671 | c->layer[i].interleaving = rc; | 671 | c->layer[i].interleaving = rc; |
672 | mb86a20s_layer_bitrate(fe, i, c->layer[i].modulation, | 672 | mb86a20s_layer_bitrate(fe, i, c->layer[i].modulation, |
673 | c->layer[i].fec, | 673 | c->layer[i].fec, |
674 | c->layer[i].interleaving, | 674 | c->layer[i].interleaving, |
675 | c->layer[i].segment_count); | 675 | c->layer[i].segment_count); |
676 | } | 676 | } |
677 | 677 | ||
678 | rc = mb86a20s_writereg(state, 0x6d, 0x84); | 678 | rc = mb86a20s_writereg(state, 0x6d, 0x84); |
679 | if (rc < 0) | 679 | if (rc < 0) |
680 | return rc; | 680 | return rc; |
681 | if ((rc & 0x60) == 0x20) { | 681 | if ((rc & 0x60) == 0x20) { |
682 | c->isdbt_sb_mode = 1; | 682 | c->isdbt_sb_mode = 1; |
683 | /* At least, one segment should exist */ | 683 | /* At least, one segment should exist */ |
684 | if (!c->isdbt_sb_segment_count) | 684 | if (!c->isdbt_sb_segment_count) |
685 | c->isdbt_sb_segment_count = 1; | 685 | c->isdbt_sb_segment_count = 1; |
686 | } | 686 | } |
687 | 687 | ||
688 | /* Get transmission mode and guard interval */ | 688 | /* Get transmission mode and guard interval */ |
689 | rc = mb86a20s_readreg(state, 0x07); | 689 | rc = mb86a20s_readreg(state, 0x07); |
690 | if (rc < 0) | 690 | if (rc < 0) |
691 | return rc; | 691 | return rc; |
692 | if ((rc & 0x60) == 0x20) { | 692 | if ((rc & 0x60) == 0x20) { |
693 | switch (rc & 0x0c >> 2) { | 693 | switch (rc & 0x0c >> 2) { |
694 | case 0: | 694 | case 0: |
695 | c->transmission_mode = TRANSMISSION_MODE_2K; | 695 | c->transmission_mode = TRANSMISSION_MODE_2K; |
696 | break; | 696 | break; |
697 | case 1: | 697 | case 1: |
698 | c->transmission_mode = TRANSMISSION_MODE_4K; | 698 | c->transmission_mode = TRANSMISSION_MODE_4K; |
699 | break; | 699 | break; |
700 | case 2: | 700 | case 2: |
701 | c->transmission_mode = TRANSMISSION_MODE_8K; | 701 | c->transmission_mode = TRANSMISSION_MODE_8K; |
702 | break; | 702 | break; |
703 | } | 703 | } |
704 | } | 704 | } |
705 | if (!(rc & 0x10)) { | 705 | if (!(rc & 0x10)) { |
706 | switch (rc & 0x3) { | 706 | switch (rc & 0x3) { |
707 | case 0: | 707 | case 0: |
708 | c->guard_interval = GUARD_INTERVAL_1_4; | 708 | c->guard_interval = GUARD_INTERVAL_1_4; |
709 | break; | 709 | break; |
710 | case 1: | 710 | case 1: |
711 | c->guard_interval = GUARD_INTERVAL_1_8; | 711 | c->guard_interval = GUARD_INTERVAL_1_8; |
712 | break; | 712 | break; |
713 | case 2: | 713 | case 2: |
714 | c->guard_interval = GUARD_INTERVAL_1_16; | 714 | c->guard_interval = GUARD_INTERVAL_1_16; |
715 | break; | 715 | break; |
716 | } | 716 | } |
717 | } | 717 | } |
718 | return 0; | 718 | return 0; |
719 | 719 | ||
720 | noperlayer_error: | 720 | noperlayer_error: |
721 | 721 | ||
722 | /* per-layer info is incomplete; discard all per-layer */ | 722 | /* per-layer info is incomplete; discard all per-layer */ |
723 | c->isdbt_layer_enabled = 0; | 723 | c->isdbt_layer_enabled = 0; |
724 | 724 | ||
725 | return rc; | 725 | return rc; |
726 | } | 726 | } |
727 | 727 | ||
728 | static int mb86a20s_reset_counters(struct dvb_frontend *fe) | 728 | static int mb86a20s_reset_counters(struct dvb_frontend *fe) |
729 | { | 729 | { |
730 | struct mb86a20s_state *state = fe->demodulator_priv; | 730 | struct mb86a20s_state *state = fe->demodulator_priv; |
731 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 731 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
732 | int rc, val; | 732 | int rc, val; |
733 | 733 | ||
734 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 734 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
735 | 735 | ||
736 | /* Reset the counters, if the channel changed */ | 736 | /* Reset the counters, if the channel changed */ |
737 | if (state->last_frequency != c->frequency) { | 737 | if (state->last_frequency != c->frequency) { |
738 | memset(&c->strength, 0, sizeof(c->strength)); | 738 | memset(&c->strength, 0, sizeof(c->strength)); |
739 | memset(&c->cnr, 0, sizeof(c->cnr)); | 739 | memset(&c->cnr, 0, sizeof(c->cnr)); |
740 | memset(&c->pre_bit_error, 0, sizeof(c->pre_bit_error)); | 740 | memset(&c->pre_bit_error, 0, sizeof(c->pre_bit_error)); |
741 | memset(&c->pre_bit_count, 0, sizeof(c->pre_bit_count)); | 741 | memset(&c->pre_bit_count, 0, sizeof(c->pre_bit_count)); |
742 | memset(&c->post_bit_error, 0, sizeof(c->post_bit_error)); | 742 | memset(&c->post_bit_error, 0, sizeof(c->post_bit_error)); |
743 | memset(&c->post_bit_count, 0, sizeof(c->post_bit_count)); | 743 | memset(&c->post_bit_count, 0, sizeof(c->post_bit_count)); |
744 | memset(&c->block_error, 0, sizeof(c->block_error)); | 744 | memset(&c->block_error, 0, sizeof(c->block_error)); |
745 | memset(&c->block_count, 0, sizeof(c->block_count)); | 745 | memset(&c->block_count, 0, sizeof(c->block_count)); |
746 | 746 | ||
747 | state->last_frequency = c->frequency; | 747 | state->last_frequency = c->frequency; |
748 | } | 748 | } |
749 | 749 | ||
750 | /* Clear status for most stats */ | 750 | /* Clear status for most stats */ |
751 | 751 | ||
752 | /* BER/PER counter reset */ | 752 | /* BER/PER counter reset */ |
753 | rc = mb86a20s_writeregdata(state, mb86a20s_per_ber_reset); | 753 | rc = mb86a20s_writeregdata(state, mb86a20s_per_ber_reset); |
754 | if (rc < 0) | 754 | if (rc < 0) |
755 | goto err; | 755 | goto err; |
756 | 756 | ||
757 | /* CNR counter reset */ | 757 | /* CNR counter reset */ |
758 | rc = mb86a20s_readreg(state, 0x45); | 758 | rc = mb86a20s_readreg(state, 0x45); |
759 | if (rc < 0) | 759 | if (rc < 0) |
760 | goto err; | 760 | goto err; |
761 | val = rc; | 761 | val = rc; |
762 | rc = mb86a20s_writereg(state, 0x45, val | 0x10); | 762 | rc = mb86a20s_writereg(state, 0x45, val | 0x10); |
763 | if (rc < 0) | 763 | if (rc < 0) |
764 | goto err; | 764 | goto err; |
765 | rc = mb86a20s_writereg(state, 0x45, val & 0x6f); | 765 | rc = mb86a20s_writereg(state, 0x45, val & 0x6f); |
766 | if (rc < 0) | 766 | if (rc < 0) |
767 | goto err; | 767 | goto err; |
768 | 768 | ||
769 | /* MER counter reset */ | 769 | /* MER counter reset */ |
770 | rc = mb86a20s_writereg(state, 0x50, 0x50); | 770 | rc = mb86a20s_writereg(state, 0x50, 0x50); |
771 | if (rc < 0) | 771 | if (rc < 0) |
772 | goto err; | 772 | goto err; |
773 | rc = mb86a20s_readreg(state, 0x51); | 773 | rc = mb86a20s_readreg(state, 0x51); |
774 | if (rc < 0) | 774 | if (rc < 0) |
775 | goto err; | 775 | goto err; |
776 | val = rc; | 776 | val = rc; |
777 | rc = mb86a20s_writereg(state, 0x51, val | 0x01); | 777 | rc = mb86a20s_writereg(state, 0x51, val | 0x01); |
778 | if (rc < 0) | 778 | if (rc < 0) |
779 | goto err; | 779 | goto err; |
780 | rc = mb86a20s_writereg(state, 0x51, val & 0x06); | 780 | rc = mb86a20s_writereg(state, 0x51, val & 0x06); |
781 | if (rc < 0) | 781 | if (rc < 0) |
782 | goto err; | 782 | goto err; |
783 | 783 | ||
784 | goto ok; | 784 | goto ok; |
785 | err: | 785 | err: |
786 | dev_err(&state->i2c->dev, | 786 | dev_err(&state->i2c->dev, |
787 | "%s: Can't reset FE statistics (error %d).\n", | 787 | "%s: Can't reset FE statistics (error %d).\n", |
788 | __func__, rc); | 788 | __func__, rc); |
789 | ok: | 789 | ok: |
790 | return rc; | 790 | return rc; |
791 | } | 791 | } |
792 | 792 | ||
793 | static int mb86a20s_get_pre_ber(struct dvb_frontend *fe, | 793 | static int mb86a20s_get_pre_ber(struct dvb_frontend *fe, |
794 | unsigned layer, | 794 | unsigned layer, |
795 | u32 *error, u32 *count) | 795 | u32 *error, u32 *count) |
796 | { | 796 | { |
797 | struct mb86a20s_state *state = fe->demodulator_priv; | 797 | struct mb86a20s_state *state = fe->demodulator_priv; |
798 | int rc, val; | 798 | int rc, val; |
799 | 799 | ||
800 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 800 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
801 | 801 | ||
802 | if (layer >= 3) | 802 | if (layer >= 3) |
803 | return -EINVAL; | 803 | return -EINVAL; |
804 | 804 | ||
805 | /* Check if the BER measures are already available */ | 805 | /* Check if the BER measures are already available */ |
806 | rc = mb86a20s_readreg(state, 0x54); | 806 | rc = mb86a20s_readreg(state, 0x54); |
807 | if (rc < 0) | 807 | if (rc < 0) |
808 | return rc; | 808 | return rc; |
809 | 809 | ||
810 | /* Check if data is available for that layer */ | 810 | /* Check if data is available for that layer */ |
811 | if (!(rc & (1 << layer))) { | 811 | if (!(rc & (1 << layer))) { |
812 | dev_dbg(&state->i2c->dev, | 812 | dev_dbg(&state->i2c->dev, |
813 | "%s: preBER for layer %c is not available yet.\n", | 813 | "%s: preBER for layer %c is not available yet.\n", |
814 | __func__, 'A' + layer); | 814 | __func__, 'A' + layer); |
815 | return -EBUSY; | 815 | return -EBUSY; |
816 | } | 816 | } |
817 | 817 | ||
818 | /* Read Bit Error Count */ | 818 | /* Read Bit Error Count */ |
819 | rc = mb86a20s_readreg(state, 0x55 + layer * 3); | 819 | rc = mb86a20s_readreg(state, 0x55 + layer * 3); |
820 | if (rc < 0) | 820 | if (rc < 0) |
821 | return rc; | 821 | return rc; |
822 | *error = rc << 16; | 822 | *error = rc << 16; |
823 | rc = mb86a20s_readreg(state, 0x56 + layer * 3); | 823 | rc = mb86a20s_readreg(state, 0x56 + layer * 3); |
824 | if (rc < 0) | 824 | if (rc < 0) |
825 | return rc; | 825 | return rc; |
826 | *error |= rc << 8; | 826 | *error |= rc << 8; |
827 | rc = mb86a20s_readreg(state, 0x57 + layer * 3); | 827 | rc = mb86a20s_readreg(state, 0x57 + layer * 3); |
828 | if (rc < 0) | 828 | if (rc < 0) |
829 | return rc; | 829 | return rc; |
830 | *error |= rc; | 830 | *error |= rc; |
831 | 831 | ||
832 | dev_dbg(&state->i2c->dev, | 832 | dev_dbg(&state->i2c->dev, |
833 | "%s: bit error before Viterbi for layer %c: %d.\n", | 833 | "%s: bit error before Viterbi for layer %c: %d.\n", |
834 | __func__, 'A' + layer, *error); | 834 | __func__, 'A' + layer, *error); |
835 | 835 | ||
836 | /* Read Bit Count */ | 836 | /* Read Bit Count */ |
837 | rc = mb86a20s_writereg(state, 0x50, 0xa7 + layer * 3); | 837 | rc = mb86a20s_writereg(state, 0x50, 0xa7 + layer * 3); |
838 | if (rc < 0) | 838 | if (rc < 0) |
839 | return rc; | 839 | return rc; |
840 | rc = mb86a20s_readreg(state, 0x51); | 840 | rc = mb86a20s_readreg(state, 0x51); |
841 | if (rc < 0) | 841 | if (rc < 0) |
842 | return rc; | 842 | return rc; |
843 | *count = rc << 16; | 843 | *count = rc << 16; |
844 | rc = mb86a20s_writereg(state, 0x50, 0xa8 + layer * 3); | 844 | rc = mb86a20s_writereg(state, 0x50, 0xa8 + layer * 3); |
845 | if (rc < 0) | 845 | if (rc < 0) |
846 | return rc; | 846 | return rc; |
847 | rc = mb86a20s_readreg(state, 0x51); | 847 | rc = mb86a20s_readreg(state, 0x51); |
848 | if (rc < 0) | 848 | if (rc < 0) |
849 | return rc; | 849 | return rc; |
850 | *count |= rc << 8; | 850 | *count |= rc << 8; |
851 | rc = mb86a20s_writereg(state, 0x50, 0xa9 + layer * 3); | 851 | rc = mb86a20s_writereg(state, 0x50, 0xa9 + layer * 3); |
852 | if (rc < 0) | 852 | if (rc < 0) |
853 | return rc; | 853 | return rc; |
854 | rc = mb86a20s_readreg(state, 0x51); | 854 | rc = mb86a20s_readreg(state, 0x51); |
855 | if (rc < 0) | 855 | if (rc < 0) |
856 | return rc; | 856 | return rc; |
857 | *count |= rc; | 857 | *count |= rc; |
858 | 858 | ||
859 | dev_dbg(&state->i2c->dev, | 859 | dev_dbg(&state->i2c->dev, |
860 | "%s: bit count before Viterbi for layer %c: %d.\n", | 860 | "%s: bit count before Viterbi for layer %c: %d.\n", |
861 | __func__, 'A' + layer, *count); | 861 | __func__, 'A' + layer, *count); |
862 | 862 | ||
863 | 863 | ||
864 | /* | 864 | /* |
865 | * As we get TMCC data from the frontend, we can better estimate the | 865 | * As we get TMCC data from the frontend, we can better estimate the |
866 | * BER bit counters, in order to do the BER measure during a longer | 866 | * BER bit counters, in order to do the BER measure during a longer |
867 | * time. Use those data, if available, to update the bit count | 867 | * time. Use those data, if available, to update the bit count |
868 | * measure. | 868 | * measure. |
869 | */ | 869 | */ |
870 | 870 | ||
871 | if (state->estimated_rate[layer] | 871 | if (state->estimated_rate[layer] |
872 | && state->estimated_rate[layer] != *count) { | 872 | && state->estimated_rate[layer] != *count) { |
873 | dev_dbg(&state->i2c->dev, | 873 | dev_dbg(&state->i2c->dev, |
874 | "%s: updating layer %c preBER counter to %d.\n", | 874 | "%s: updating layer %c preBER counter to %d.\n", |
875 | __func__, 'A' + layer, state->estimated_rate[layer]); | 875 | __func__, 'A' + layer, state->estimated_rate[layer]); |
876 | 876 | ||
877 | /* Turn off BER before Viterbi */ | 877 | /* Turn off BER before Viterbi */ |
878 | rc = mb86a20s_writereg(state, 0x52, 0x00); | 878 | rc = mb86a20s_writereg(state, 0x52, 0x00); |
879 | 879 | ||
880 | /* Update counter for this layer */ | 880 | /* Update counter for this layer */ |
881 | rc = mb86a20s_writereg(state, 0x50, 0xa7 + layer * 3); | 881 | rc = mb86a20s_writereg(state, 0x50, 0xa7 + layer * 3); |
882 | if (rc < 0) | 882 | if (rc < 0) |
883 | return rc; | 883 | return rc; |
884 | rc = mb86a20s_writereg(state, 0x51, | 884 | rc = mb86a20s_writereg(state, 0x51, |
885 | state->estimated_rate[layer] >> 16); | 885 | state->estimated_rate[layer] >> 16); |
886 | if (rc < 0) | 886 | if (rc < 0) |
887 | return rc; | 887 | return rc; |
888 | rc = mb86a20s_writereg(state, 0x50, 0xa8 + layer * 3); | 888 | rc = mb86a20s_writereg(state, 0x50, 0xa8 + layer * 3); |
889 | if (rc < 0) | 889 | if (rc < 0) |
890 | return rc; | 890 | return rc; |
891 | rc = mb86a20s_writereg(state, 0x51, | 891 | rc = mb86a20s_writereg(state, 0x51, |
892 | state->estimated_rate[layer] >> 8); | 892 | state->estimated_rate[layer] >> 8); |
893 | if (rc < 0) | 893 | if (rc < 0) |
894 | return rc; | 894 | return rc; |
895 | rc = mb86a20s_writereg(state, 0x50, 0xa9 + layer * 3); | 895 | rc = mb86a20s_writereg(state, 0x50, 0xa9 + layer * 3); |
896 | if (rc < 0) | 896 | if (rc < 0) |
897 | return rc; | 897 | return rc; |
898 | rc = mb86a20s_writereg(state, 0x51, | 898 | rc = mb86a20s_writereg(state, 0x51, |
899 | state->estimated_rate[layer]); | 899 | state->estimated_rate[layer]); |
900 | if (rc < 0) | 900 | if (rc < 0) |
901 | return rc; | 901 | return rc; |
902 | 902 | ||
903 | /* Turn on BER before Viterbi */ | 903 | /* Turn on BER before Viterbi */ |
904 | rc = mb86a20s_writereg(state, 0x52, 0x01); | 904 | rc = mb86a20s_writereg(state, 0x52, 0x01); |
905 | 905 | ||
906 | /* Reset all preBER counters */ | 906 | /* Reset all preBER counters */ |
907 | rc = mb86a20s_writereg(state, 0x53, 0x00); | 907 | rc = mb86a20s_writereg(state, 0x53, 0x00); |
908 | if (rc < 0) | 908 | if (rc < 0) |
909 | return rc; | 909 | return rc; |
910 | rc = mb86a20s_writereg(state, 0x53, 0x07); | 910 | rc = mb86a20s_writereg(state, 0x53, 0x07); |
911 | } else { | 911 | } else { |
912 | /* Reset counter to collect new data */ | 912 | /* Reset counter to collect new data */ |
913 | rc = mb86a20s_readreg(state, 0x53); | 913 | rc = mb86a20s_readreg(state, 0x53); |
914 | if (rc < 0) | 914 | if (rc < 0) |
915 | return rc; | 915 | return rc; |
916 | val = rc; | 916 | val = rc; |
917 | rc = mb86a20s_writereg(state, 0x53, val & ~(1 << layer)); | 917 | rc = mb86a20s_writereg(state, 0x53, val & ~(1 << layer)); |
918 | if (rc < 0) | 918 | if (rc < 0) |
919 | return rc; | 919 | return rc; |
920 | rc = mb86a20s_writereg(state, 0x53, val | (1 << layer)); | 920 | rc = mb86a20s_writereg(state, 0x53, val | (1 << layer)); |
921 | } | 921 | } |
922 | 922 | ||
923 | return rc; | 923 | return rc; |
924 | } | 924 | } |
925 | 925 | ||
926 | static int mb86a20s_get_post_ber(struct dvb_frontend *fe, | 926 | static int mb86a20s_get_post_ber(struct dvb_frontend *fe, |
927 | unsigned layer, | 927 | unsigned layer, |
928 | u32 *error, u32 *count) | 928 | u32 *error, u32 *count) |
929 | { | 929 | { |
930 | struct mb86a20s_state *state = fe->demodulator_priv; | 930 | struct mb86a20s_state *state = fe->demodulator_priv; |
931 | u32 counter, collect_rate; | 931 | u32 counter, collect_rate; |
932 | int rc, val; | 932 | int rc, val; |
933 | 933 | ||
934 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 934 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
935 | 935 | ||
936 | if (layer >= 3) | 936 | if (layer >= 3) |
937 | return -EINVAL; | 937 | return -EINVAL; |
938 | 938 | ||
939 | /* Check if the BER measures are already available */ | 939 | /* Check if the BER measures are already available */ |
940 | rc = mb86a20s_readreg(state, 0x60); | 940 | rc = mb86a20s_readreg(state, 0x60); |
941 | if (rc < 0) | 941 | if (rc < 0) |
942 | return rc; | 942 | return rc; |
943 | 943 | ||
944 | /* Check if data is available for that layer */ | 944 | /* Check if data is available for that layer */ |
945 | if (!(rc & (1 << layer))) { | 945 | if (!(rc & (1 << layer))) { |
946 | dev_dbg(&state->i2c->dev, | 946 | dev_dbg(&state->i2c->dev, |
947 | "%s: post BER for layer %c is not available yet.\n", | 947 | "%s: post BER for layer %c is not available yet.\n", |
948 | __func__, 'A' + layer); | 948 | __func__, 'A' + layer); |
949 | return -EBUSY; | 949 | return -EBUSY; |
950 | } | 950 | } |
951 | 951 | ||
952 | /* Read Bit Error Count */ | 952 | /* Read Bit Error Count */ |
953 | rc = mb86a20s_readreg(state, 0x64 + layer * 3); | 953 | rc = mb86a20s_readreg(state, 0x64 + layer * 3); |
954 | if (rc < 0) | 954 | if (rc < 0) |
955 | return rc; | 955 | return rc; |
956 | *error = rc << 16; | 956 | *error = rc << 16; |
957 | rc = mb86a20s_readreg(state, 0x65 + layer * 3); | 957 | rc = mb86a20s_readreg(state, 0x65 + layer * 3); |
958 | if (rc < 0) | 958 | if (rc < 0) |
959 | return rc; | 959 | return rc; |
960 | *error |= rc << 8; | 960 | *error |= rc << 8; |
961 | rc = mb86a20s_readreg(state, 0x66 + layer * 3); | 961 | rc = mb86a20s_readreg(state, 0x66 + layer * 3); |
962 | if (rc < 0) | 962 | if (rc < 0) |
963 | return rc; | 963 | return rc; |
964 | *error |= rc; | 964 | *error |= rc; |
965 | 965 | ||
966 | dev_dbg(&state->i2c->dev, | 966 | dev_dbg(&state->i2c->dev, |
967 | "%s: post bit error for layer %c: %d.\n", | 967 | "%s: post bit error for layer %c: %d.\n", |
968 | __func__, 'A' + layer, *error); | 968 | __func__, 'A' + layer, *error); |
969 | 969 | ||
970 | /* Read Bit Count */ | 970 | /* Read Bit Count */ |
971 | rc = mb86a20s_writereg(state, 0x50, 0xdc + layer * 2); | 971 | rc = mb86a20s_writereg(state, 0x50, 0xdc + layer * 2); |
972 | if (rc < 0) | 972 | if (rc < 0) |
973 | return rc; | 973 | return rc; |
974 | rc = mb86a20s_readreg(state, 0x51); | 974 | rc = mb86a20s_readreg(state, 0x51); |
975 | if (rc < 0) | 975 | if (rc < 0) |
976 | return rc; | 976 | return rc; |
977 | counter = rc << 8; | 977 | counter = rc << 8; |
978 | rc = mb86a20s_writereg(state, 0x50, 0xdd + layer * 2); | 978 | rc = mb86a20s_writereg(state, 0x50, 0xdd + layer * 2); |
979 | if (rc < 0) | 979 | if (rc < 0) |
980 | return rc; | 980 | return rc; |
981 | rc = mb86a20s_readreg(state, 0x51); | 981 | rc = mb86a20s_readreg(state, 0x51); |
982 | if (rc < 0) | 982 | if (rc < 0) |
983 | return rc; | 983 | return rc; |
984 | counter |= rc; | 984 | counter |= rc; |
985 | *count = counter * 204 * 8; | 985 | *count = counter * 204 * 8; |
986 | 986 | ||
987 | dev_dbg(&state->i2c->dev, | 987 | dev_dbg(&state->i2c->dev, |
988 | "%s: post bit count for layer %c: %d.\n", | 988 | "%s: post bit count for layer %c: %d.\n", |
989 | __func__, 'A' + layer, *count); | 989 | __func__, 'A' + layer, *count); |
990 | 990 | ||
991 | /* | 991 | /* |
992 | * As we get TMCC data from the frontend, we can better estimate the | 992 | * As we get TMCC data from the frontend, we can better estimate the |
993 | * BER bit counters, in order to do the BER measure during a longer | 993 | * BER bit counters, in order to do the BER measure during a longer |
994 | * time. Use those data, if available, to update the bit count | 994 | * time. Use those data, if available, to update the bit count |
995 | * measure. | 995 | * measure. |
996 | */ | 996 | */ |
997 | 997 | ||
998 | if (!state->estimated_rate[layer]) | 998 | if (!state->estimated_rate[layer]) |
999 | goto reset_measurement; | 999 | goto reset_measurement; |
1000 | 1000 | ||
1001 | collect_rate = state->estimated_rate[layer] / 204 / 8; | 1001 | collect_rate = state->estimated_rate[layer] / 204 / 8; |
1002 | if (collect_rate < 32) | 1002 | if (collect_rate < 32) |
1003 | collect_rate = 32; | 1003 | collect_rate = 32; |
1004 | if (collect_rate > 65535) | 1004 | if (collect_rate > 65535) |
1005 | collect_rate = 65535; | 1005 | collect_rate = 65535; |
1006 | if (collect_rate != counter) { | 1006 | if (collect_rate != counter) { |
1007 | dev_dbg(&state->i2c->dev, | 1007 | dev_dbg(&state->i2c->dev, |
1008 | "%s: updating postBER counter on layer %c to %d.\n", | 1008 | "%s: updating postBER counter on layer %c to %d.\n", |
1009 | __func__, 'A' + layer, collect_rate); | 1009 | __func__, 'A' + layer, collect_rate); |
1010 | 1010 | ||
1011 | /* Turn off BER after Viterbi */ | 1011 | /* Turn off BER after Viterbi */ |
1012 | rc = mb86a20s_writereg(state, 0x5e, 0x00); | 1012 | rc = mb86a20s_writereg(state, 0x5e, 0x00); |
1013 | 1013 | ||
1014 | /* Update counter for this layer */ | 1014 | /* Update counter for this layer */ |
1015 | rc = mb86a20s_writereg(state, 0x50, 0xdc + layer * 2); | 1015 | rc = mb86a20s_writereg(state, 0x50, 0xdc + layer * 2); |
1016 | if (rc < 0) | 1016 | if (rc < 0) |
1017 | return rc; | 1017 | return rc; |
1018 | rc = mb86a20s_writereg(state, 0x51, collect_rate >> 8); | 1018 | rc = mb86a20s_writereg(state, 0x51, collect_rate >> 8); |
1019 | if (rc < 0) | 1019 | if (rc < 0) |
1020 | return rc; | 1020 | return rc; |
1021 | rc = mb86a20s_writereg(state, 0x50, 0xdd + layer * 2); | 1021 | rc = mb86a20s_writereg(state, 0x50, 0xdd + layer * 2); |
1022 | if (rc < 0) | 1022 | if (rc < 0) |
1023 | return rc; | 1023 | return rc; |
1024 | rc = mb86a20s_writereg(state, 0x51, collect_rate & 0xff); | 1024 | rc = mb86a20s_writereg(state, 0x51, collect_rate & 0xff); |
1025 | if (rc < 0) | 1025 | if (rc < 0) |
1026 | return rc; | 1026 | return rc; |
1027 | 1027 | ||
1028 | /* Turn on BER after Viterbi */ | 1028 | /* Turn on BER after Viterbi */ |
1029 | rc = mb86a20s_writereg(state, 0x5e, 0x07); | 1029 | rc = mb86a20s_writereg(state, 0x5e, 0x07); |
1030 | 1030 | ||
1031 | /* Reset all preBER counters */ | 1031 | /* Reset all preBER counters */ |
1032 | rc = mb86a20s_writereg(state, 0x5f, 0x00); | 1032 | rc = mb86a20s_writereg(state, 0x5f, 0x00); |
1033 | if (rc < 0) | 1033 | if (rc < 0) |
1034 | return rc; | 1034 | return rc; |
1035 | rc = mb86a20s_writereg(state, 0x5f, 0x07); | 1035 | rc = mb86a20s_writereg(state, 0x5f, 0x07); |
1036 | 1036 | ||
1037 | return rc; | 1037 | return rc; |
1038 | } | 1038 | } |
1039 | 1039 | ||
1040 | reset_measurement: | 1040 | reset_measurement: |
1041 | /* Reset counter to collect new data */ | 1041 | /* Reset counter to collect new data */ |
1042 | rc = mb86a20s_readreg(state, 0x5f); | 1042 | rc = mb86a20s_readreg(state, 0x5f); |
1043 | if (rc < 0) | 1043 | if (rc < 0) |
1044 | return rc; | 1044 | return rc; |
1045 | val = rc; | 1045 | val = rc; |
1046 | rc = mb86a20s_writereg(state, 0x5f, val & ~(1 << layer)); | 1046 | rc = mb86a20s_writereg(state, 0x5f, val & ~(1 << layer)); |
1047 | if (rc < 0) | 1047 | if (rc < 0) |
1048 | return rc; | 1048 | return rc; |
1049 | rc = mb86a20s_writereg(state, 0x5f, val | (1 << layer)); | 1049 | rc = mb86a20s_writereg(state, 0x5f, val | (1 << layer)); |
1050 | 1050 | ||
1051 | return rc; | 1051 | return rc; |
1052 | } | 1052 | } |
1053 | 1053 | ||
1054 | static int mb86a20s_get_blk_error(struct dvb_frontend *fe, | 1054 | static int mb86a20s_get_blk_error(struct dvb_frontend *fe, |
1055 | unsigned layer, | 1055 | unsigned layer, |
1056 | u32 *error, u32 *count) | 1056 | u32 *error, u32 *count) |
1057 | { | 1057 | { |
1058 | struct mb86a20s_state *state = fe->demodulator_priv; | 1058 | struct mb86a20s_state *state = fe->demodulator_priv; |
1059 | int rc, val; | 1059 | int rc, val; |
1060 | u32 collect_rate; | 1060 | u32 collect_rate; |
1061 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 1061 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
1062 | 1062 | ||
1063 | if (layer >= 3) | 1063 | if (layer >= 3) |
1064 | return -EINVAL; | 1064 | return -EINVAL; |
1065 | 1065 | ||
1066 | /* Check if the PER measures are already available */ | 1066 | /* Check if the PER measures are already available */ |
1067 | rc = mb86a20s_writereg(state, 0x50, 0xb8); | 1067 | rc = mb86a20s_writereg(state, 0x50, 0xb8); |
1068 | if (rc < 0) | 1068 | if (rc < 0) |
1069 | return rc; | 1069 | return rc; |
1070 | rc = mb86a20s_readreg(state, 0x51); | 1070 | rc = mb86a20s_readreg(state, 0x51); |
1071 | if (rc < 0) | 1071 | if (rc < 0) |
1072 | return rc; | 1072 | return rc; |
1073 | 1073 | ||
1074 | /* Check if data is available for that layer */ | 1074 | /* Check if data is available for that layer */ |
1075 | 1075 | ||
1076 | if (!(rc & (1 << layer))) { | 1076 | if (!(rc & (1 << layer))) { |
1077 | dev_dbg(&state->i2c->dev, | 1077 | dev_dbg(&state->i2c->dev, |
1078 | "%s: block counts for layer %c aren't available yet.\n", | 1078 | "%s: block counts for layer %c aren't available yet.\n", |
1079 | __func__, 'A' + layer); | 1079 | __func__, 'A' + layer); |
1080 | return -EBUSY; | 1080 | return -EBUSY; |
1081 | } | 1081 | } |
1082 | 1082 | ||
1083 | /* Read Packet error Count */ | 1083 | /* Read Packet error Count */ |
1084 | rc = mb86a20s_writereg(state, 0x50, 0xb9 + layer * 2); | 1084 | rc = mb86a20s_writereg(state, 0x50, 0xb9 + layer * 2); |
1085 | if (rc < 0) | 1085 | if (rc < 0) |
1086 | return rc; | 1086 | return rc; |
1087 | rc = mb86a20s_readreg(state, 0x51); | 1087 | rc = mb86a20s_readreg(state, 0x51); |
1088 | if (rc < 0) | 1088 | if (rc < 0) |
1089 | return rc; | 1089 | return rc; |
1090 | *error = rc << 8; | 1090 | *error = rc << 8; |
1091 | rc = mb86a20s_writereg(state, 0x50, 0xba + layer * 2); | 1091 | rc = mb86a20s_writereg(state, 0x50, 0xba + layer * 2); |
1092 | if (rc < 0) | 1092 | if (rc < 0) |
1093 | return rc; | 1093 | return rc; |
1094 | rc = mb86a20s_readreg(state, 0x51); | 1094 | rc = mb86a20s_readreg(state, 0x51); |
1095 | if (rc < 0) | 1095 | if (rc < 0) |
1096 | return rc; | 1096 | return rc; |
1097 | *error |= rc; | 1097 | *error |= rc; |
1098 | dev_err(&state->i2c->dev, "%s: block error for layer %c: %d.\n", | 1098 | dev_err(&state->i2c->dev, "%s: block error for layer %c: %d.\n", |
1099 | __func__, 'A' + layer, *error); | 1099 | __func__, 'A' + layer, *error); |
1100 | 1100 | ||
1101 | /* Read Bit Count */ | 1101 | /* Read Bit Count */ |
1102 | rc = mb86a20s_writereg(state, 0x50, 0xb2 + layer * 2); | 1102 | rc = mb86a20s_writereg(state, 0x50, 0xb2 + layer * 2); |
1103 | if (rc < 0) | 1103 | if (rc < 0) |
1104 | return rc; | 1104 | return rc; |
1105 | rc = mb86a20s_readreg(state, 0x51); | 1105 | rc = mb86a20s_readreg(state, 0x51); |
1106 | if (rc < 0) | 1106 | if (rc < 0) |
1107 | return rc; | 1107 | return rc; |
1108 | *count = rc << 8; | 1108 | *count = rc << 8; |
1109 | rc = mb86a20s_writereg(state, 0x50, 0xb3 + layer * 2); | 1109 | rc = mb86a20s_writereg(state, 0x50, 0xb3 + layer * 2); |
1110 | if (rc < 0) | 1110 | if (rc < 0) |
1111 | return rc; | 1111 | return rc; |
1112 | rc = mb86a20s_readreg(state, 0x51); | 1112 | rc = mb86a20s_readreg(state, 0x51); |
1113 | if (rc < 0) | 1113 | if (rc < 0) |
1114 | return rc; | 1114 | return rc; |
1115 | *count |= rc; | 1115 | *count |= rc; |
1116 | 1116 | ||
1117 | dev_dbg(&state->i2c->dev, | 1117 | dev_dbg(&state->i2c->dev, |
1118 | "%s: block count for layer %c: %d.\n", | 1118 | "%s: block count for layer %c: %d.\n", |
1119 | __func__, 'A' + layer, *count); | 1119 | __func__, 'A' + layer, *count); |
1120 | 1120 | ||
1121 | /* | 1121 | /* |
1122 | * As we get TMCC data from the frontend, we can better estimate the | 1122 | * As we get TMCC data from the frontend, we can better estimate the |
1123 | * BER bit counters, in order to do the BER measure during a longer | 1123 | * BER bit counters, in order to do the BER measure during a longer |
1124 | * time. Use those data, if available, to update the bit count | 1124 | * time. Use those data, if available, to update the bit count |
1125 | * measure. | 1125 | * measure. |
1126 | */ | 1126 | */ |
1127 | 1127 | ||
1128 | if (!state->estimated_rate[layer]) | 1128 | if (!state->estimated_rate[layer]) |
1129 | goto reset_measurement; | 1129 | goto reset_measurement; |
1130 | 1130 | ||
1131 | collect_rate = state->estimated_rate[layer] / 204 / 8; | 1131 | collect_rate = state->estimated_rate[layer] / 204 / 8; |
1132 | if (collect_rate < 32) | 1132 | if (collect_rate < 32) |
1133 | collect_rate = 32; | 1133 | collect_rate = 32; |
1134 | if (collect_rate > 65535) | 1134 | if (collect_rate > 65535) |
1135 | collect_rate = 65535; | 1135 | collect_rate = 65535; |
1136 | 1136 | ||
1137 | if (collect_rate != *count) { | 1137 | if (collect_rate != *count) { |
1138 | dev_dbg(&state->i2c->dev, | 1138 | dev_dbg(&state->i2c->dev, |
1139 | "%s: updating PER counter on layer %c to %d.\n", | 1139 | "%s: updating PER counter on layer %c to %d.\n", |
1140 | __func__, 'A' + layer, collect_rate); | 1140 | __func__, 'A' + layer, collect_rate); |
1141 | 1141 | ||
1142 | /* Stop PER measurement */ | 1142 | /* Stop PER measurement */ |
1143 | rc = mb86a20s_writereg(state, 0x50, 0xb0); | 1143 | rc = mb86a20s_writereg(state, 0x50, 0xb0); |
1144 | if (rc < 0) | 1144 | if (rc < 0) |
1145 | return rc; | 1145 | return rc; |
1146 | rc = mb86a20s_writereg(state, 0x51, 0x00); | 1146 | rc = mb86a20s_writereg(state, 0x51, 0x00); |
1147 | if (rc < 0) | 1147 | if (rc < 0) |
1148 | return rc; | 1148 | return rc; |
1149 | 1149 | ||
1150 | /* Update this layer's counter */ | 1150 | /* Update this layer's counter */ |
1151 | rc = mb86a20s_writereg(state, 0x50, 0xb2 + layer * 2); | 1151 | rc = mb86a20s_writereg(state, 0x50, 0xb2 + layer * 2); |
1152 | if (rc < 0) | 1152 | if (rc < 0) |
1153 | return rc; | 1153 | return rc; |
1154 | rc = mb86a20s_writereg(state, 0x51, collect_rate >> 8); | 1154 | rc = mb86a20s_writereg(state, 0x51, collect_rate >> 8); |
1155 | if (rc < 0) | 1155 | if (rc < 0) |
1156 | return rc; | 1156 | return rc; |
1157 | rc = mb86a20s_writereg(state, 0x50, 0xb3 + layer * 2); | 1157 | rc = mb86a20s_writereg(state, 0x50, 0xb3 + layer * 2); |
1158 | if (rc < 0) | 1158 | if (rc < 0) |
1159 | return rc; | 1159 | return rc; |
1160 | rc = mb86a20s_writereg(state, 0x51, collect_rate & 0xff); | 1160 | rc = mb86a20s_writereg(state, 0x51, collect_rate & 0xff); |
1161 | if (rc < 0) | 1161 | if (rc < 0) |
1162 | return rc; | 1162 | return rc; |
1163 | 1163 | ||
1164 | /* start PER measurement */ | 1164 | /* start PER measurement */ |
1165 | rc = mb86a20s_writereg(state, 0x50, 0xb0); | 1165 | rc = mb86a20s_writereg(state, 0x50, 0xb0); |
1166 | if (rc < 0) | 1166 | if (rc < 0) |
1167 | return rc; | 1167 | return rc; |
1168 | rc = mb86a20s_writereg(state, 0x51, 0x07); | 1168 | rc = mb86a20s_writereg(state, 0x51, 0x07); |
1169 | if (rc < 0) | 1169 | if (rc < 0) |
1170 | return rc; | 1170 | return rc; |
1171 | 1171 | ||
1172 | /* Reset all counters to collect new data */ | 1172 | /* Reset all counters to collect new data */ |
1173 | rc = mb86a20s_writereg(state, 0x50, 0xb1); | 1173 | rc = mb86a20s_writereg(state, 0x50, 0xb1); |
1174 | if (rc < 0) | 1174 | if (rc < 0) |
1175 | return rc; | 1175 | return rc; |
1176 | rc = mb86a20s_writereg(state, 0x51, 0x07); | 1176 | rc = mb86a20s_writereg(state, 0x51, 0x07); |
1177 | if (rc < 0) | 1177 | if (rc < 0) |
1178 | return rc; | 1178 | return rc; |
1179 | rc = mb86a20s_writereg(state, 0x51, 0x00); | 1179 | rc = mb86a20s_writereg(state, 0x51, 0x00); |
1180 | 1180 | ||
1181 | return rc; | 1181 | return rc; |
1182 | } | 1182 | } |
1183 | 1183 | ||
1184 | reset_measurement: | 1184 | reset_measurement: |
1185 | /* Reset counter to collect new data */ | 1185 | /* Reset counter to collect new data */ |
1186 | rc = mb86a20s_writereg(state, 0x50, 0xb1); | 1186 | rc = mb86a20s_writereg(state, 0x50, 0xb1); |
1187 | if (rc < 0) | 1187 | if (rc < 0) |
1188 | return rc; | 1188 | return rc; |
1189 | rc = mb86a20s_readreg(state, 0x51); | 1189 | rc = mb86a20s_readreg(state, 0x51); |
1190 | if (rc < 0) | 1190 | if (rc < 0) |
1191 | return rc; | 1191 | return rc; |
1192 | val = rc; | 1192 | val = rc; |
1193 | rc = mb86a20s_writereg(state, 0x51, val | (1 << layer)); | 1193 | rc = mb86a20s_writereg(state, 0x51, val | (1 << layer)); |
1194 | if (rc < 0) | 1194 | if (rc < 0) |
1195 | return rc; | 1195 | return rc; |
1196 | rc = mb86a20s_writereg(state, 0x51, val & ~(1 << layer)); | 1196 | rc = mb86a20s_writereg(state, 0x51, val & ~(1 << layer)); |
1197 | 1197 | ||
1198 | return rc; | 1198 | return rc; |
1199 | } | 1199 | } |
1200 | 1200 | ||
1201 | struct linear_segments { | 1201 | struct linear_segments { |
1202 | unsigned x, y; | 1202 | unsigned x, y; |
1203 | }; | 1203 | }; |
1204 | 1204 | ||
1205 | /* | 1205 | /* |
1206 | * All tables below return a dB/1000 measurement | 1206 | * All tables below return a dB/1000 measurement |
1207 | */ | 1207 | */ |
1208 | 1208 | ||
1209 | static struct linear_segments cnr_to_db_table[] = { | 1209 | static struct linear_segments cnr_to_db_table[] = { |
1210 | { 19648, 0}, | 1210 | { 19648, 0}, |
1211 | { 18187, 1000}, | 1211 | { 18187, 1000}, |
1212 | { 16534, 2000}, | 1212 | { 16534, 2000}, |
1213 | { 14823, 3000}, | 1213 | { 14823, 3000}, |
1214 | { 13161, 4000}, | 1214 | { 13161, 4000}, |
1215 | { 11622, 5000}, | 1215 | { 11622, 5000}, |
1216 | { 10279, 6000}, | 1216 | { 10279, 6000}, |
1217 | { 9089, 7000}, | 1217 | { 9089, 7000}, |
1218 | { 8042, 8000}, | 1218 | { 8042, 8000}, |
1219 | { 7137, 9000}, | 1219 | { 7137, 9000}, |
1220 | { 6342, 10000}, | 1220 | { 6342, 10000}, |
1221 | { 5641, 11000}, | 1221 | { 5641, 11000}, |
1222 | { 5030, 12000}, | 1222 | { 5030, 12000}, |
1223 | { 4474, 13000}, | 1223 | { 4474, 13000}, |
1224 | { 3988, 14000}, | 1224 | { 3988, 14000}, |
1225 | { 3556, 15000}, | 1225 | { 3556, 15000}, |
1226 | { 3180, 16000}, | 1226 | { 3180, 16000}, |
1227 | { 2841, 17000}, | 1227 | { 2841, 17000}, |
1228 | { 2541, 18000}, | 1228 | { 2541, 18000}, |
1229 | { 2276, 19000}, | 1229 | { 2276, 19000}, |
1230 | { 2038, 20000}, | 1230 | { 2038, 20000}, |
1231 | { 1800, 21000}, | 1231 | { 1800, 21000}, |
1232 | { 1625, 22000}, | 1232 | { 1625, 22000}, |
1233 | { 1462, 23000}, | 1233 | { 1462, 23000}, |
1234 | { 1324, 24000}, | 1234 | { 1324, 24000}, |
1235 | { 1175, 25000}, | 1235 | { 1175, 25000}, |
1236 | { 1063, 26000}, | 1236 | { 1063, 26000}, |
1237 | { 980, 27000}, | 1237 | { 980, 27000}, |
1238 | { 907, 28000}, | 1238 | { 907, 28000}, |
1239 | { 840, 29000}, | 1239 | { 840, 29000}, |
1240 | { 788, 30000}, | 1240 | { 788, 30000}, |
1241 | }; | 1241 | }; |
1242 | 1242 | ||
1243 | static struct linear_segments cnr_64qam_table[] = { | 1243 | static struct linear_segments cnr_64qam_table[] = { |
1244 | { 3922688, 0}, | 1244 | { 3922688, 0}, |
1245 | { 3920384, 1000}, | 1245 | { 3920384, 1000}, |
1246 | { 3902720, 2000}, | 1246 | { 3902720, 2000}, |
1247 | { 3894784, 3000}, | 1247 | { 3894784, 3000}, |
1248 | { 3882496, 4000}, | 1248 | { 3882496, 4000}, |
1249 | { 3872768, 5000}, | 1249 | { 3872768, 5000}, |
1250 | { 3858944, 6000}, | 1250 | { 3858944, 6000}, |
1251 | { 3851520, 7000}, | 1251 | { 3851520, 7000}, |
1252 | { 3838976, 8000}, | 1252 | { 3838976, 8000}, |
1253 | { 3829248, 9000}, | 1253 | { 3829248, 9000}, |
1254 | { 3818240, 10000}, | 1254 | { 3818240, 10000}, |
1255 | { 3806976, 11000}, | 1255 | { 3806976, 11000}, |
1256 | { 3791872, 12000}, | 1256 | { 3791872, 12000}, |
1257 | { 3767040, 13000}, | 1257 | { 3767040, 13000}, |
1258 | { 3720960, 14000}, | 1258 | { 3720960, 14000}, |
1259 | { 3637504, 15000}, | 1259 | { 3637504, 15000}, |
1260 | { 3498496, 16000}, | 1260 | { 3498496, 16000}, |
1261 | { 3296000, 17000}, | 1261 | { 3296000, 17000}, |
1262 | { 3031040, 18000}, | 1262 | { 3031040, 18000}, |
1263 | { 2715392, 19000}, | 1263 | { 2715392, 19000}, |
1264 | { 2362624, 20000}, | 1264 | { 2362624, 20000}, |
1265 | { 1963264, 21000}, | 1265 | { 1963264, 21000}, |
1266 | { 1649664, 22000}, | 1266 | { 1649664, 22000}, |
1267 | { 1366784, 23000}, | 1267 | { 1366784, 23000}, |
1268 | { 1120768, 24000}, | 1268 | { 1120768, 24000}, |
1269 | { 890880, 25000}, | 1269 | { 890880, 25000}, |
1270 | { 723456, 26000}, | 1270 | { 723456, 26000}, |
1271 | { 612096, 27000}, | 1271 | { 612096, 27000}, |
1272 | { 518912, 28000}, | 1272 | { 518912, 28000}, |
1273 | { 448256, 29000}, | 1273 | { 448256, 29000}, |
1274 | { 388864, 30000}, | 1274 | { 388864, 30000}, |
1275 | }; | 1275 | }; |
1276 | 1276 | ||
1277 | static struct linear_segments cnr_16qam_table[] = { | 1277 | static struct linear_segments cnr_16qam_table[] = { |
1278 | { 5314816, 0}, | 1278 | { 5314816, 0}, |
1279 | { 5219072, 1000}, | 1279 | { 5219072, 1000}, |
1280 | { 5118720, 2000}, | 1280 | { 5118720, 2000}, |
1281 | { 4998912, 3000}, | 1281 | { 4998912, 3000}, |
1282 | { 4875520, 4000}, | 1282 | { 4875520, 4000}, |
1283 | { 4736000, 5000}, | 1283 | { 4736000, 5000}, |
1284 | { 4604160, 6000}, | 1284 | { 4604160, 6000}, |
1285 | { 4458752, 7000}, | 1285 | { 4458752, 7000}, |
1286 | { 4300288, 8000}, | 1286 | { 4300288, 8000}, |
1287 | { 4092928, 9000}, | 1287 | { 4092928, 9000}, |
1288 | { 3836160, 10000}, | 1288 | { 3836160, 10000}, |
1289 | { 3521024, 11000}, | 1289 | { 3521024, 11000}, |
1290 | { 3155968, 12000}, | 1290 | { 3155968, 12000}, |
1291 | { 2756864, 13000}, | 1291 | { 2756864, 13000}, |
1292 | { 2347008, 14000}, | 1292 | { 2347008, 14000}, |
1293 | { 1955072, 15000}, | 1293 | { 1955072, 15000}, |
1294 | { 1593600, 16000}, | 1294 | { 1593600, 16000}, |
1295 | { 1297920, 17000}, | 1295 | { 1297920, 17000}, |
1296 | { 1043968, 18000}, | 1296 | { 1043968, 18000}, |
1297 | { 839680, 19000}, | 1297 | { 839680, 19000}, |
1298 | { 672256, 20000}, | 1298 | { 672256, 20000}, |
1299 | { 523008, 21000}, | 1299 | { 523008, 21000}, |
1300 | { 424704, 22000}, | 1300 | { 424704, 22000}, |
1301 | { 345088, 23000}, | 1301 | { 345088, 23000}, |
1302 | { 280064, 24000}, | 1302 | { 280064, 24000}, |
1303 | { 221440, 25000}, | 1303 | { 221440, 25000}, |
1304 | { 179712, 26000}, | 1304 | { 179712, 26000}, |
1305 | { 151040, 27000}, | 1305 | { 151040, 27000}, |
1306 | { 128512, 28000}, | 1306 | { 128512, 28000}, |
1307 | { 110080, 29000}, | 1307 | { 110080, 29000}, |
1308 | { 95744, 30000}, | 1308 | { 95744, 30000}, |
1309 | }; | 1309 | }; |
1310 | 1310 | ||
1311 | struct linear_segments cnr_qpsk_table[] = { | 1311 | struct linear_segments cnr_qpsk_table[] = { |
1312 | { 2834176, 0}, | 1312 | { 2834176, 0}, |
1313 | { 2683648, 1000}, | 1313 | { 2683648, 1000}, |
1314 | { 2536960, 2000}, | 1314 | { 2536960, 2000}, |
1315 | { 2391808, 3000}, | 1315 | { 2391808, 3000}, |
1316 | { 2133248, 4000}, | 1316 | { 2133248, 4000}, |
1317 | { 1906176, 5000}, | 1317 | { 1906176, 5000}, |
1318 | { 1666560, 6000}, | 1318 | { 1666560, 6000}, |
1319 | { 1422080, 7000}, | 1319 | { 1422080, 7000}, |
1320 | { 1189632, 8000}, | 1320 | { 1189632, 8000}, |
1321 | { 976384, 9000}, | 1321 | { 976384, 9000}, |
1322 | { 790272, 10000}, | 1322 | { 790272, 10000}, |
1323 | { 633344, 11000}, | 1323 | { 633344, 11000}, |
1324 | { 505600, 12000}, | 1324 | { 505600, 12000}, |
1325 | { 402944, 13000}, | 1325 | { 402944, 13000}, |
1326 | { 320768, 14000}, | 1326 | { 320768, 14000}, |
1327 | { 255488, 15000}, | 1327 | { 255488, 15000}, |
1328 | { 204032, 16000}, | 1328 | { 204032, 16000}, |
1329 | { 163072, 17000}, | 1329 | { 163072, 17000}, |
1330 | { 130304, 18000}, | 1330 | { 130304, 18000}, |
1331 | { 105216, 19000}, | 1331 | { 105216, 19000}, |
1332 | { 83456, 20000}, | 1332 | { 83456, 20000}, |
1333 | { 65024, 21000}, | 1333 | { 65024, 21000}, |
1334 | { 52480, 22000}, | 1334 | { 52480, 22000}, |
1335 | { 42752, 23000}, | 1335 | { 42752, 23000}, |
1336 | { 34560, 24000}, | 1336 | { 34560, 24000}, |
1337 | { 27136, 25000}, | 1337 | { 27136, 25000}, |
1338 | { 22016, 26000}, | 1338 | { 22016, 26000}, |
1339 | { 18432, 27000}, | 1339 | { 18432, 27000}, |
1340 | { 15616, 28000}, | 1340 | { 15616, 28000}, |
1341 | { 13312, 29000}, | 1341 | { 13312, 29000}, |
1342 | { 11520, 30000}, | 1342 | { 11520, 30000}, |
1343 | }; | 1343 | }; |
1344 | 1344 | ||
1345 | static u32 interpolate_value(u32 value, struct linear_segments *segments, | 1345 | static u32 interpolate_value(u32 value, struct linear_segments *segments, |
1346 | unsigned len) | 1346 | unsigned len) |
1347 | { | 1347 | { |
1348 | u64 tmp64; | 1348 | u64 tmp64; |
1349 | u32 dx, dy; | 1349 | u32 dx, dy; |
1350 | int i, ret; | 1350 | int i, ret; |
1351 | 1351 | ||
1352 | if (value >= segments[0].x) | 1352 | if (value >= segments[0].x) |
1353 | return segments[0].y; | 1353 | return segments[0].y; |
1354 | if (value < segments[len-1].x) | 1354 | if (value < segments[len-1].x) |
1355 | return segments[len-1].y; | 1355 | return segments[len-1].y; |
1356 | 1356 | ||
1357 | for (i = 1; i < len - 1; i++) { | 1357 | for (i = 1; i < len - 1; i++) { |
1358 | /* If value is identical, no need to interpolate */ | 1358 | /* If value is identical, no need to interpolate */ |
1359 | if (value == segments[i].x) | 1359 | if (value == segments[i].x) |
1360 | return segments[i].y; | 1360 | return segments[i].y; |
1361 | if (value > segments[i].x) | 1361 | if (value > segments[i].x) |
1362 | break; | 1362 | break; |
1363 | } | 1363 | } |
1364 | 1364 | ||
1365 | /* Linear interpolation between the two (x,y) points */ | 1365 | /* Linear interpolation between the two (x,y) points */ |
1366 | dy = segments[i].y - segments[i - 1].y; | 1366 | dy = segments[i].y - segments[i - 1].y; |
1367 | dx = segments[i - 1].x - segments[i].x; | 1367 | dx = segments[i - 1].x - segments[i].x; |
1368 | tmp64 = value - segments[i].x; | 1368 | tmp64 = value - segments[i].x; |
1369 | tmp64 *= dy; | 1369 | tmp64 *= dy; |
1370 | do_div(tmp64, dx); | 1370 | do_div(tmp64, dx); |
1371 | ret = segments[i].y - tmp64; | 1371 | ret = segments[i].y - tmp64; |
1372 | 1372 | ||
1373 | return ret; | 1373 | return ret; |
1374 | } | 1374 | } |
1375 | 1375 | ||
1376 | static int mb86a20s_get_main_CNR(struct dvb_frontend *fe) | 1376 | static int mb86a20s_get_main_CNR(struct dvb_frontend *fe) |
1377 | { | 1377 | { |
1378 | struct mb86a20s_state *state = fe->demodulator_priv; | 1378 | struct mb86a20s_state *state = fe->demodulator_priv; |
1379 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1379 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1380 | u32 cnr_linear, cnr; | 1380 | u32 cnr_linear, cnr; |
1381 | int rc, val; | 1381 | int rc, val; |
1382 | 1382 | ||
1383 | /* Check if CNR is available */ | 1383 | /* Check if CNR is available */ |
1384 | rc = mb86a20s_readreg(state, 0x45); | 1384 | rc = mb86a20s_readreg(state, 0x45); |
1385 | if (rc < 0) | 1385 | if (rc < 0) |
1386 | return rc; | 1386 | return rc; |
1387 | 1387 | ||
1388 | if (!(rc & 0x40)) { | 1388 | if (!(rc & 0x40)) { |
1389 | dev_info(&state->i2c->dev, "%s: CNR is not available yet.\n", | 1389 | dev_info(&state->i2c->dev, "%s: CNR is not available yet.\n", |
1390 | __func__); | 1390 | __func__); |
1391 | return -EBUSY; | 1391 | return -EBUSY; |
1392 | } | 1392 | } |
1393 | val = rc; | 1393 | val = rc; |
1394 | 1394 | ||
1395 | rc = mb86a20s_readreg(state, 0x46); | 1395 | rc = mb86a20s_readreg(state, 0x46); |
1396 | if (rc < 0) | 1396 | if (rc < 0) |
1397 | return rc; | 1397 | return rc; |
1398 | cnr_linear = rc << 8; | 1398 | cnr_linear = rc << 8; |
1399 | 1399 | ||
1400 | rc = mb86a20s_readreg(state, 0x46); | 1400 | rc = mb86a20s_readreg(state, 0x46); |
1401 | if (rc < 0) | 1401 | if (rc < 0) |
1402 | return rc; | 1402 | return rc; |
1403 | cnr_linear |= rc; | 1403 | cnr_linear |= rc; |
1404 | 1404 | ||
1405 | cnr = interpolate_value(cnr_linear, | 1405 | cnr = interpolate_value(cnr_linear, |
1406 | cnr_to_db_table, ARRAY_SIZE(cnr_to_db_table)); | 1406 | cnr_to_db_table, ARRAY_SIZE(cnr_to_db_table)); |
1407 | 1407 | ||
1408 | c->cnr.stat[0].scale = FE_SCALE_DECIBEL; | 1408 | c->cnr.stat[0].scale = FE_SCALE_DECIBEL; |
1409 | c->cnr.stat[0].svalue = cnr; | 1409 | c->cnr.stat[0].svalue = cnr; |
1410 | 1410 | ||
1411 | dev_dbg(&state->i2c->dev, "%s: CNR is %d.%03d dB (%d)\n", | 1411 | dev_dbg(&state->i2c->dev, "%s: CNR is %d.%03d dB (%d)\n", |
1412 | __func__, cnr / 1000, cnr % 1000, cnr_linear); | 1412 | __func__, cnr / 1000, cnr % 1000, cnr_linear); |
1413 | 1413 | ||
1414 | /* CNR counter reset */ | 1414 | /* CNR counter reset */ |
1415 | rc = mb86a20s_writereg(state, 0x45, val | 0x10); | 1415 | rc = mb86a20s_writereg(state, 0x45, val | 0x10); |
1416 | if (rc < 0) | 1416 | if (rc < 0) |
1417 | return rc; | 1417 | return rc; |
1418 | rc = mb86a20s_writereg(state, 0x45, val & 0x6f); | 1418 | rc = mb86a20s_writereg(state, 0x45, val & 0x6f); |
1419 | 1419 | ||
1420 | return rc; | 1420 | return rc; |
1421 | } | 1421 | } |
1422 | 1422 | ||
1423 | static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe) | 1423 | static int mb86a20s_get_blk_error_layer_CNR(struct dvb_frontend *fe) |
1424 | { | 1424 | { |
1425 | struct mb86a20s_state *state = fe->demodulator_priv; | 1425 | struct mb86a20s_state *state = fe->demodulator_priv; |
1426 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1426 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1427 | u32 mer, cnr; | 1427 | u32 mer, cnr; |
1428 | int rc, val, i; | 1428 | int rc, val, i; |
1429 | struct linear_segments *segs; | 1429 | struct linear_segments *segs; |
1430 | unsigned segs_len; | 1430 | unsigned segs_len; |
1431 | 1431 | ||
1432 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 1432 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
1433 | 1433 | ||
1434 | /* Check if the measures are already available */ | 1434 | /* Check if the measures are already available */ |
1435 | rc = mb86a20s_writereg(state, 0x50, 0x5b); | 1435 | rc = mb86a20s_writereg(state, 0x50, 0x5b); |
1436 | if (rc < 0) | 1436 | if (rc < 0) |
1437 | return rc; | 1437 | return rc; |
1438 | rc = mb86a20s_readreg(state, 0x51); | 1438 | rc = mb86a20s_readreg(state, 0x51); |
1439 | if (rc < 0) | 1439 | if (rc < 0) |
1440 | return rc; | 1440 | return rc; |
1441 | 1441 | ||
1442 | /* Check if data is available */ | 1442 | /* Check if data is available */ |
1443 | if (!(rc & 0x01)) { | 1443 | if (!(rc & 0x01)) { |
1444 | dev_info(&state->i2c->dev, | 1444 | dev_info(&state->i2c->dev, |
1445 | "%s: MER measures aren't available yet.\n", __func__); | 1445 | "%s: MER measures aren't available yet.\n", __func__); |
1446 | return -EBUSY; | 1446 | return -EBUSY; |
1447 | } | 1447 | } |
1448 | 1448 | ||
1449 | /* Read all layers */ | 1449 | /* Read all layers */ |
1450 | for (i = 0; i < 3; i++) { | 1450 | for (i = 0; i < 3; i++) { |
1451 | if (!(c->isdbt_layer_enabled & (1 << i))) { | 1451 | if (!(c->isdbt_layer_enabled & (1 << i))) { |
1452 | c->cnr.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; | 1452 | c->cnr.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; |
1453 | continue; | 1453 | continue; |
1454 | } | 1454 | } |
1455 | 1455 | ||
1456 | rc = mb86a20s_writereg(state, 0x50, 0x52 + i * 3); | 1456 | rc = mb86a20s_writereg(state, 0x50, 0x52 + i * 3); |
1457 | if (rc < 0) | 1457 | if (rc < 0) |
1458 | return rc; | 1458 | return rc; |
1459 | rc = mb86a20s_readreg(state, 0x51); | 1459 | rc = mb86a20s_readreg(state, 0x51); |
1460 | if (rc < 0) | 1460 | if (rc < 0) |
1461 | return rc; | 1461 | return rc; |
1462 | mer = rc << 16; | 1462 | mer = rc << 16; |
1463 | rc = mb86a20s_writereg(state, 0x50, 0x53 + i * 3); | 1463 | rc = mb86a20s_writereg(state, 0x50, 0x53 + i * 3); |
1464 | if (rc < 0) | 1464 | if (rc < 0) |
1465 | return rc; | 1465 | return rc; |
1466 | rc = mb86a20s_readreg(state, 0x51); | 1466 | rc = mb86a20s_readreg(state, 0x51); |
1467 | if (rc < 0) | 1467 | if (rc < 0) |
1468 | return rc; | 1468 | return rc; |
1469 | mer |= rc << 8; | 1469 | mer |= rc << 8; |
1470 | rc = mb86a20s_writereg(state, 0x50, 0x54 + i * 3); | 1470 | rc = mb86a20s_writereg(state, 0x50, 0x54 + i * 3); |
1471 | if (rc < 0) | 1471 | if (rc < 0) |
1472 | return rc; | 1472 | return rc; |
1473 | rc = mb86a20s_readreg(state, 0x51); | 1473 | rc = mb86a20s_readreg(state, 0x51); |
1474 | if (rc < 0) | 1474 | if (rc < 0) |
1475 | return rc; | 1475 | return rc; |
1476 | mer |= rc; | 1476 | mer |= rc; |
1477 | 1477 | ||
1478 | switch (c->layer[i].modulation) { | 1478 | switch (c->layer[i].modulation) { |
1479 | case DQPSK: | 1479 | case DQPSK: |
1480 | case QPSK: | 1480 | case QPSK: |
1481 | segs = cnr_qpsk_table; | 1481 | segs = cnr_qpsk_table; |
1482 | segs_len = ARRAY_SIZE(cnr_qpsk_table); | 1482 | segs_len = ARRAY_SIZE(cnr_qpsk_table); |
1483 | break; | 1483 | break; |
1484 | case QAM_16: | 1484 | case QAM_16: |
1485 | segs = cnr_16qam_table; | 1485 | segs = cnr_16qam_table; |
1486 | segs_len = ARRAY_SIZE(cnr_16qam_table); | 1486 | segs_len = ARRAY_SIZE(cnr_16qam_table); |
1487 | break; | 1487 | break; |
1488 | default: | 1488 | default: |
1489 | case QAM_64: | 1489 | case QAM_64: |
1490 | segs = cnr_64qam_table; | 1490 | segs = cnr_64qam_table; |
1491 | segs_len = ARRAY_SIZE(cnr_64qam_table); | 1491 | segs_len = ARRAY_SIZE(cnr_64qam_table); |
1492 | break; | 1492 | break; |
1493 | } | 1493 | } |
1494 | cnr = interpolate_value(mer, segs, segs_len); | 1494 | cnr = interpolate_value(mer, segs, segs_len); |
1495 | 1495 | ||
1496 | c->cnr.stat[1 + i].scale = FE_SCALE_DECIBEL; | 1496 | c->cnr.stat[1 + i].scale = FE_SCALE_DECIBEL; |
1497 | c->cnr.stat[1 + i].svalue = cnr; | 1497 | c->cnr.stat[1 + i].svalue = cnr; |
1498 | 1498 | ||
1499 | dev_dbg(&state->i2c->dev, | 1499 | dev_dbg(&state->i2c->dev, |
1500 | "%s: CNR for layer %c is %d.%03d dB (MER = %d).\n", | 1500 | "%s: CNR for layer %c is %d.%03d dB (MER = %d).\n", |
1501 | __func__, 'A' + i, cnr / 1000, cnr % 1000, mer); | 1501 | __func__, 'A' + i, cnr / 1000, cnr % 1000, mer); |
1502 | 1502 | ||
1503 | } | 1503 | } |
1504 | 1504 | ||
1505 | /* Start a new MER measurement */ | 1505 | /* Start a new MER measurement */ |
1506 | /* MER counter reset */ | 1506 | /* MER counter reset */ |
1507 | rc = mb86a20s_writereg(state, 0x50, 0x50); | 1507 | rc = mb86a20s_writereg(state, 0x50, 0x50); |
1508 | if (rc < 0) | 1508 | if (rc < 0) |
1509 | return rc; | 1509 | return rc; |
1510 | rc = mb86a20s_readreg(state, 0x51); | 1510 | rc = mb86a20s_readreg(state, 0x51); |
1511 | if (rc < 0) | 1511 | if (rc < 0) |
1512 | return rc; | 1512 | return rc; |
1513 | val = rc; | 1513 | val = rc; |
1514 | 1514 | ||
1515 | rc = mb86a20s_writereg(state, 0x51, val | 0x01); | 1515 | rc = mb86a20s_writereg(state, 0x51, val | 0x01); |
1516 | if (rc < 0) | 1516 | if (rc < 0) |
1517 | return rc; | 1517 | return rc; |
1518 | rc = mb86a20s_writereg(state, 0x51, val & 0x06); | 1518 | rc = mb86a20s_writereg(state, 0x51, val & 0x06); |
1519 | if (rc < 0) | 1519 | if (rc < 0) |
1520 | return rc; | 1520 | return rc; |
1521 | 1521 | ||
1522 | return 0; | 1522 | return 0; |
1523 | } | 1523 | } |
1524 | 1524 | ||
1525 | static void mb86a20s_stats_not_ready(struct dvb_frontend *fe) | 1525 | static void mb86a20s_stats_not_ready(struct dvb_frontend *fe) |
1526 | { | 1526 | { |
1527 | struct mb86a20s_state *state = fe->demodulator_priv; | 1527 | struct mb86a20s_state *state = fe->demodulator_priv; |
1528 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1528 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1529 | int i; | 1529 | int i; |
1530 | 1530 | ||
1531 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 1531 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
1532 | 1532 | ||
1533 | /* Fill the length of each status counter */ | 1533 | /* Fill the length of each status counter */ |
1534 | 1534 | ||
1535 | /* Only global stats */ | 1535 | /* Only global stats */ |
1536 | c->strength.len = 1; | 1536 | c->strength.len = 1; |
1537 | 1537 | ||
1538 | /* Per-layer stats - 3 layers + global */ | 1538 | /* Per-layer stats - 3 layers + global */ |
1539 | c->cnr.len = 4; | 1539 | c->cnr.len = 4; |
1540 | c->pre_bit_error.len = 4; | 1540 | c->pre_bit_error.len = 4; |
1541 | c->pre_bit_count.len = 4; | 1541 | c->pre_bit_count.len = 4; |
1542 | c->post_bit_error.len = 4; | 1542 | c->post_bit_error.len = 4; |
1543 | c->post_bit_count.len = 4; | 1543 | c->post_bit_count.len = 4; |
1544 | c->block_error.len = 4; | 1544 | c->block_error.len = 4; |
1545 | c->block_count.len = 4; | 1545 | c->block_count.len = 4; |
1546 | 1546 | ||
1547 | /* Signal is always available */ | 1547 | /* Signal is always available */ |
1548 | c->strength.stat[0].scale = FE_SCALE_RELATIVE; | 1548 | c->strength.stat[0].scale = FE_SCALE_RELATIVE; |
1549 | c->strength.stat[0].uvalue = 0; | 1549 | c->strength.stat[0].uvalue = 0; |
1550 | 1550 | ||
1551 | /* Put all of them at FE_SCALE_NOT_AVAILABLE */ | 1551 | /* Put all of them at FE_SCALE_NOT_AVAILABLE */ |
1552 | for (i = 0; i < 4; i++) { | 1552 | for (i = 0; i < 4; i++) { |
1553 | c->cnr.stat[i].scale = FE_SCALE_NOT_AVAILABLE; | 1553 | c->cnr.stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
1554 | c->pre_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; | 1554 | c->pre_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
1555 | c->pre_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; | 1555 | c->pre_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
1556 | c->post_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; | 1556 | c->post_bit_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
1557 | c->post_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; | 1557 | c->post_bit_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
1558 | c->block_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; | 1558 | c->block_error.stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
1559 | c->block_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; | 1559 | c->block_count.stat[i].scale = FE_SCALE_NOT_AVAILABLE; |
1560 | } | 1560 | } |
1561 | } | 1561 | } |
1562 | 1562 | ||
1563 | static int mb86a20s_get_stats(struct dvb_frontend *fe) | 1563 | static int mb86a20s_get_stats(struct dvb_frontend *fe) |
1564 | { | 1564 | { |
1565 | struct mb86a20s_state *state = fe->demodulator_priv; | 1565 | struct mb86a20s_state *state = fe->demodulator_priv; |
1566 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1566 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1567 | int rc = 0, i; | 1567 | int rc = 0, i; |
1568 | u32 bit_error = 0, bit_count = 0; | 1568 | u32 bit_error = 0, bit_count = 0; |
1569 | u32 t_pre_bit_error = 0, t_pre_bit_count = 0; | 1569 | u32 t_pre_bit_error = 0, t_pre_bit_count = 0; |
1570 | u32 t_post_bit_error = 0, t_post_bit_count = 0; | 1570 | u32 t_post_bit_error = 0, t_post_bit_count = 0; |
1571 | u32 block_error = 0, block_count = 0; | 1571 | u32 block_error = 0, block_count = 0; |
1572 | u32 t_block_error = 0, t_block_count = 0; | 1572 | u32 t_block_error = 0, t_block_count = 0; |
1573 | int active_layers = 0, pre_ber_layers = 0, post_ber_layers = 0; | 1573 | int active_layers = 0, pre_ber_layers = 0, post_ber_layers = 0; |
1574 | int per_layers = 0; | 1574 | int per_layers = 0; |
1575 | 1575 | ||
1576 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 1576 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
1577 | 1577 | ||
1578 | mb86a20s_get_main_CNR(fe); | 1578 | mb86a20s_get_main_CNR(fe); |
1579 | 1579 | ||
1580 | /* Get per-layer stats */ | 1580 | /* Get per-layer stats */ |
1581 | mb86a20s_get_blk_error_layer_CNR(fe); | 1581 | mb86a20s_get_blk_error_layer_CNR(fe); |
1582 | 1582 | ||
1583 | for (i = 0; i < 3; i++) { | 1583 | for (i = 0; i < 3; i++) { |
1584 | if (c->isdbt_layer_enabled & (1 << i)) { | 1584 | if (c->isdbt_layer_enabled & (1 << i)) { |
1585 | /* Layer is active and has rc segments */ | 1585 | /* Layer is active and has rc segments */ |
1586 | active_layers++; | 1586 | active_layers++; |
1587 | 1587 | ||
1588 | /* Handle BER before vterbi */ | 1588 | /* Handle BER before vterbi */ |
1589 | rc = mb86a20s_get_pre_ber(fe, i, | 1589 | rc = mb86a20s_get_pre_ber(fe, i, |
1590 | &bit_error, &bit_count); | 1590 | &bit_error, &bit_count); |
1591 | if (rc >= 0) { | 1591 | if (rc >= 0) { |
1592 | c->pre_bit_error.stat[1 + i].scale = FE_SCALE_COUNTER; | 1592 | c->pre_bit_error.stat[1 + i].scale = FE_SCALE_COUNTER; |
1593 | c->pre_bit_error.stat[1 + i].uvalue += bit_error; | 1593 | c->pre_bit_error.stat[1 + i].uvalue += bit_error; |
1594 | c->pre_bit_count.stat[1 + i].scale = FE_SCALE_COUNTER; | 1594 | c->pre_bit_count.stat[1 + i].scale = FE_SCALE_COUNTER; |
1595 | c->pre_bit_count.stat[1 + i].uvalue += bit_count; | 1595 | c->pre_bit_count.stat[1 + i].uvalue += bit_count; |
1596 | } else if (rc != -EBUSY) { | 1596 | } else if (rc != -EBUSY) { |
1597 | /* | 1597 | /* |
1598 | * If an I/O error happened, | 1598 | * If an I/O error happened, |
1599 | * measures are now unavailable | 1599 | * measures are now unavailable |
1600 | */ | 1600 | */ |
1601 | c->pre_bit_error.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; | 1601 | c->pre_bit_error.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; |
1602 | c->pre_bit_count.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; | 1602 | c->pre_bit_count.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; |
1603 | dev_err(&state->i2c->dev, | 1603 | dev_err(&state->i2c->dev, |
1604 | "%s: Can't get BER for layer %c (error %d).\n", | 1604 | "%s: Can't get BER for layer %c (error %d).\n", |
1605 | __func__, 'A' + i, rc); | 1605 | __func__, 'A' + i, rc); |
1606 | } | 1606 | } |
1607 | if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) | 1607 | if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) |
1608 | pre_ber_layers++; | 1608 | pre_ber_layers++; |
1609 | 1609 | ||
1610 | /* Handle BER post vterbi */ | 1610 | /* Handle BER post vterbi */ |
1611 | rc = mb86a20s_get_post_ber(fe, i, | 1611 | rc = mb86a20s_get_post_ber(fe, i, |
1612 | &bit_error, &bit_count); | 1612 | &bit_error, &bit_count); |
1613 | if (rc >= 0) { | 1613 | if (rc >= 0) { |
1614 | c->post_bit_error.stat[1 + i].scale = FE_SCALE_COUNTER; | 1614 | c->post_bit_error.stat[1 + i].scale = FE_SCALE_COUNTER; |
1615 | c->post_bit_error.stat[1 + i].uvalue += bit_error; | 1615 | c->post_bit_error.stat[1 + i].uvalue += bit_error; |
1616 | c->post_bit_count.stat[1 + i].scale = FE_SCALE_COUNTER; | 1616 | c->post_bit_count.stat[1 + i].scale = FE_SCALE_COUNTER; |
1617 | c->post_bit_count.stat[1 + i].uvalue += bit_count; | 1617 | c->post_bit_count.stat[1 + i].uvalue += bit_count; |
1618 | } else if (rc != -EBUSY) { | 1618 | } else if (rc != -EBUSY) { |
1619 | /* | 1619 | /* |
1620 | * If an I/O error happened, | 1620 | * If an I/O error happened, |
1621 | * measures are now unavailable | 1621 | * measures are now unavailable |
1622 | */ | 1622 | */ |
1623 | c->post_bit_error.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; | 1623 | c->post_bit_error.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; |
1624 | c->post_bit_count.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; | 1624 | c->post_bit_count.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; |
1625 | dev_err(&state->i2c->dev, | 1625 | dev_err(&state->i2c->dev, |
1626 | "%s: Can't get BER for layer %c (error %d).\n", | 1626 | "%s: Can't get BER for layer %c (error %d).\n", |
1627 | __func__, 'A' + i, rc); | 1627 | __func__, 'A' + i, rc); |
1628 | } | 1628 | } |
1629 | if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) | 1629 | if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) |
1630 | post_ber_layers++; | 1630 | post_ber_layers++; |
1631 | 1631 | ||
1632 | /* Handle Block errors for PER/UCB reports */ | 1632 | /* Handle Block errors for PER/UCB reports */ |
1633 | rc = mb86a20s_get_blk_error(fe, i, | 1633 | rc = mb86a20s_get_blk_error(fe, i, |
1634 | &block_error, | 1634 | &block_error, |
1635 | &block_count); | 1635 | &block_count); |
1636 | if (rc >= 0) { | 1636 | if (rc >= 0) { |
1637 | c->block_error.stat[1 + i].scale = FE_SCALE_COUNTER; | 1637 | c->block_error.stat[1 + i].scale = FE_SCALE_COUNTER; |
1638 | c->block_error.stat[1 + i].uvalue += block_error; | 1638 | c->block_error.stat[1 + i].uvalue += block_error; |
1639 | c->block_count.stat[1 + i].scale = FE_SCALE_COUNTER; | 1639 | c->block_count.stat[1 + i].scale = FE_SCALE_COUNTER; |
1640 | c->block_count.stat[1 + i].uvalue += block_count; | 1640 | c->block_count.stat[1 + i].uvalue += block_count; |
1641 | } else if (rc != -EBUSY) { | 1641 | } else if (rc != -EBUSY) { |
1642 | /* | 1642 | /* |
1643 | * If an I/O error happened, | 1643 | * If an I/O error happened, |
1644 | * measures are now unavailable | 1644 | * measures are now unavailable |
1645 | */ | 1645 | */ |
1646 | c->block_error.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; | 1646 | c->block_error.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; |
1647 | c->block_count.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; | 1647 | c->block_count.stat[1 + i].scale = FE_SCALE_NOT_AVAILABLE; |
1648 | dev_err(&state->i2c->dev, | 1648 | dev_err(&state->i2c->dev, |
1649 | "%s: Can't get PER for layer %c (error %d).\n", | 1649 | "%s: Can't get PER for layer %c (error %d).\n", |
1650 | __func__, 'A' + i, rc); | 1650 | __func__, 'A' + i, rc); |
1651 | 1651 | ||
1652 | } | 1652 | } |
1653 | if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) | 1653 | if (c->block_error.stat[1 + i].scale != FE_SCALE_NOT_AVAILABLE) |
1654 | per_layers++; | 1654 | per_layers++; |
1655 | 1655 | ||
1656 | /* Update total preBER */ | 1656 | /* Update total preBER */ |
1657 | t_pre_bit_error += c->pre_bit_error.stat[1 + i].uvalue; | 1657 | t_pre_bit_error += c->pre_bit_error.stat[1 + i].uvalue; |
1658 | t_pre_bit_count += c->pre_bit_count.stat[1 + i].uvalue; | 1658 | t_pre_bit_count += c->pre_bit_count.stat[1 + i].uvalue; |
1659 | 1659 | ||
1660 | /* Update total postBER */ | 1660 | /* Update total postBER */ |
1661 | t_post_bit_error += c->post_bit_error.stat[1 + i].uvalue; | 1661 | t_post_bit_error += c->post_bit_error.stat[1 + i].uvalue; |
1662 | t_post_bit_count += c->post_bit_count.stat[1 + i].uvalue; | 1662 | t_post_bit_count += c->post_bit_count.stat[1 + i].uvalue; |
1663 | 1663 | ||
1664 | /* Update total PER */ | 1664 | /* Update total PER */ |
1665 | t_block_error += c->block_error.stat[1 + i].uvalue; | 1665 | t_block_error += c->block_error.stat[1 + i].uvalue; |
1666 | t_block_count += c->block_count.stat[1 + i].uvalue; | 1666 | t_block_count += c->block_count.stat[1 + i].uvalue; |
1667 | } | 1667 | } |
1668 | } | 1668 | } |
1669 | 1669 | ||
1670 | /* | 1670 | /* |
1671 | * Start showing global count if at least one error count is | 1671 | * Start showing global count if at least one error count is |
1672 | * available. | 1672 | * available. |
1673 | */ | 1673 | */ |
1674 | if (pre_ber_layers) { | 1674 | if (pre_ber_layers) { |
1675 | /* | 1675 | /* |
1676 | * At least one per-layer BER measure was read. We can now | 1676 | * At least one per-layer BER measure was read. We can now |
1677 | * calculate the total BER | 1677 | * calculate the total BER |
1678 | * | 1678 | * |
1679 | * Total Bit Error/Count is calculated as the sum of the | 1679 | * Total Bit Error/Count is calculated as the sum of the |
1680 | * bit errors on all active layers. | 1680 | * bit errors on all active layers. |
1681 | */ | 1681 | */ |
1682 | c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; | 1682 | c->pre_bit_error.stat[0].scale = FE_SCALE_COUNTER; |
1683 | c->pre_bit_error.stat[0].uvalue = t_pre_bit_error; | 1683 | c->pre_bit_error.stat[0].uvalue = t_pre_bit_error; |
1684 | c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; | 1684 | c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; |
1685 | c->pre_bit_count.stat[0].uvalue = t_pre_bit_count; | 1685 | c->pre_bit_count.stat[0].uvalue = t_pre_bit_count; |
1686 | } else { | 1686 | } else { |
1687 | c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | 1687 | c->pre_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
1688 | c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; | 1688 | c->pre_bit_count.stat[0].scale = FE_SCALE_COUNTER; |
1689 | } | 1689 | } |
1690 | 1690 | ||
1691 | /* | 1691 | /* |
1692 | * Start showing global count if at least one error count is | 1692 | * Start showing global count if at least one error count is |
1693 | * available. | 1693 | * available. |
1694 | */ | 1694 | */ |
1695 | if (post_ber_layers) { | 1695 | if (post_ber_layers) { |
1696 | /* | 1696 | /* |
1697 | * At least one per-layer BER measure was read. We can now | 1697 | * At least one per-layer BER measure was read. We can now |
1698 | * calculate the total BER | 1698 | * calculate the total BER |
1699 | * | 1699 | * |
1700 | * Total Bit Error/Count is calculated as the sum of the | 1700 | * Total Bit Error/Count is calculated as the sum of the |
1701 | * bit errors on all active layers. | 1701 | * bit errors on all active layers. |
1702 | */ | 1702 | */ |
1703 | c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; | 1703 | c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER; |
1704 | c->post_bit_error.stat[0].uvalue = t_post_bit_error; | 1704 | c->post_bit_error.stat[0].uvalue = t_post_bit_error; |
1705 | c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; | 1705 | c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; |
1706 | c->post_bit_count.stat[0].uvalue = t_post_bit_count; | 1706 | c->post_bit_count.stat[0].uvalue = t_post_bit_count; |
1707 | } else { | 1707 | } else { |
1708 | c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | 1708 | c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
1709 | c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; | 1709 | c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER; |
1710 | } | 1710 | } |
1711 | 1711 | ||
1712 | if (per_layers) { | 1712 | if (per_layers) { |
1713 | /* | 1713 | /* |
1714 | * At least one per-layer UCB measure was read. We can now | 1714 | * At least one per-layer UCB measure was read. We can now |
1715 | * calculate the total UCB | 1715 | * calculate the total UCB |
1716 | * | 1716 | * |
1717 | * Total block Error/Count is calculated as the sum of the | 1717 | * Total block Error/Count is calculated as the sum of the |
1718 | * block errors on all active layers. | 1718 | * block errors on all active layers. |
1719 | */ | 1719 | */ |
1720 | c->block_error.stat[0].scale = FE_SCALE_COUNTER; | 1720 | c->block_error.stat[0].scale = FE_SCALE_COUNTER; |
1721 | c->block_error.stat[0].uvalue = t_block_error; | 1721 | c->block_error.stat[0].uvalue = t_block_error; |
1722 | c->block_count.stat[0].scale = FE_SCALE_COUNTER; | 1722 | c->block_count.stat[0].scale = FE_SCALE_COUNTER; |
1723 | c->block_count.stat[0].uvalue = t_block_count; | 1723 | c->block_count.stat[0].uvalue = t_block_count; |
1724 | } else { | 1724 | } else { |
1725 | c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; | 1725 | c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; |
1726 | c->block_count.stat[0].scale = FE_SCALE_COUNTER; | 1726 | c->block_count.stat[0].scale = FE_SCALE_COUNTER; |
1727 | } | 1727 | } |
1728 | 1728 | ||
1729 | return rc; | 1729 | return rc; |
1730 | } | 1730 | } |
1731 | 1731 | ||
1732 | /* | 1732 | /* |
1733 | * The functions below are called via DVB callbacks, so they need to | 1733 | * The functions below are called via DVB callbacks, so they need to |
1734 | * properly use the I2C gate control | 1734 | * properly use the I2C gate control |
1735 | */ | 1735 | */ |
1736 | 1736 | ||
1737 | static int mb86a20s_initfe(struct dvb_frontend *fe) | 1737 | static int mb86a20s_initfe(struct dvb_frontend *fe) |
1738 | { | 1738 | { |
1739 | struct mb86a20s_state *state = fe->demodulator_priv; | 1739 | struct mb86a20s_state *state = fe->demodulator_priv; |
1740 | int rc; | 1740 | int rc; |
1741 | u8 regD5 = 1; | 1741 | u8 regD5 = 1; |
1742 | 1742 | ||
1743 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 1743 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
1744 | 1744 | ||
1745 | if (fe->ops.i2c_gate_ctrl) | 1745 | if (fe->ops.i2c_gate_ctrl) |
1746 | fe->ops.i2c_gate_ctrl(fe, 0); | 1746 | fe->ops.i2c_gate_ctrl(fe, 0); |
1747 | 1747 | ||
1748 | /* Initialize the frontend */ | 1748 | /* Initialize the frontend */ |
1749 | rc = mb86a20s_writeregdata(state, mb86a20s_init); | 1749 | rc = mb86a20s_writeregdata(state, mb86a20s_init); |
1750 | if (rc < 0) | 1750 | if (rc < 0) |
1751 | goto err; | 1751 | goto err; |
1752 | 1752 | ||
1753 | if (!state->config->is_serial) { | 1753 | if (!state->config->is_serial) { |
1754 | regD5 &= ~1; | 1754 | regD5 &= ~1; |
1755 | 1755 | ||
1756 | rc = mb86a20s_writereg(state, 0x50, 0xd5); | 1756 | rc = mb86a20s_writereg(state, 0x50, 0xd5); |
1757 | if (rc < 0) | 1757 | if (rc < 0) |
1758 | goto err; | 1758 | goto err; |
1759 | rc = mb86a20s_writereg(state, 0x51, regD5); | 1759 | rc = mb86a20s_writereg(state, 0x51, regD5); |
1760 | if (rc < 0) | 1760 | if (rc < 0) |
1761 | goto err; | 1761 | goto err; |
1762 | } | 1762 | } |
1763 | 1763 | ||
1764 | err: | 1764 | err: |
1765 | if (fe->ops.i2c_gate_ctrl) | 1765 | if (fe->ops.i2c_gate_ctrl) |
1766 | fe->ops.i2c_gate_ctrl(fe, 1); | 1766 | fe->ops.i2c_gate_ctrl(fe, 1); |
1767 | 1767 | ||
1768 | if (rc < 0) { | 1768 | if (rc < 0) { |
1769 | state->need_init = true; | 1769 | state->need_init = true; |
1770 | dev_info(&state->i2c->dev, | 1770 | dev_info(&state->i2c->dev, |
1771 | "mb86a20s: Init failed. Will try again later\n"); | 1771 | "mb86a20s: Init failed. Will try again later\n"); |
1772 | } else { | 1772 | } else { |
1773 | state->need_init = false; | 1773 | state->need_init = false; |
1774 | dev_dbg(&state->i2c->dev, "Initialization succeeded.\n"); | 1774 | dev_dbg(&state->i2c->dev, "Initialization succeeded.\n"); |
1775 | } | 1775 | } |
1776 | return rc; | 1776 | return rc; |
1777 | } | 1777 | } |
1778 | 1778 | ||
1779 | static int mb86a20s_set_frontend(struct dvb_frontend *fe) | 1779 | static int mb86a20s_set_frontend(struct dvb_frontend *fe) |
1780 | { | 1780 | { |
1781 | struct mb86a20s_state *state = fe->demodulator_priv; | 1781 | struct mb86a20s_state *state = fe->demodulator_priv; |
1782 | int rc; | 1782 | int rc; |
1783 | #if 0 | 1783 | #if 0 |
1784 | /* | 1784 | /* |
1785 | * FIXME: Properly implement the set frontend properties | 1785 | * FIXME: Properly implement the set frontend properties |
1786 | */ | 1786 | */ |
1787 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1787 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1788 | #endif | 1788 | #endif |
1789 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 1789 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
1790 | 1790 | ||
1791 | /* | 1791 | /* |
1792 | * Gate should already be opened, but it doesn't hurt to | 1792 | * Gate should already be opened, but it doesn't hurt to |
1793 | * double-check | 1793 | * double-check |
1794 | */ | 1794 | */ |
1795 | if (fe->ops.i2c_gate_ctrl) | 1795 | if (fe->ops.i2c_gate_ctrl) |
1796 | fe->ops.i2c_gate_ctrl(fe, 1); | 1796 | fe->ops.i2c_gate_ctrl(fe, 1); |
1797 | fe->ops.tuner_ops.set_params(fe); | 1797 | fe->ops.tuner_ops.set_params(fe); |
1798 | 1798 | ||
1799 | /* | 1799 | /* |
1800 | * Make it more reliable: if, for some reason, the initial | 1800 | * Make it more reliable: if, for some reason, the initial |
1801 | * device initialization doesn't happen, initialize it when | 1801 | * device initialization doesn't happen, initialize it when |
1802 | * a SBTVD parameters are adjusted. | 1802 | * a SBTVD parameters are adjusted. |
1803 | * | 1803 | * |
1804 | * Unfortunately, due to a hard to track bug at tda829x/tda18271, | 1804 | * Unfortunately, due to a hard to track bug at tda829x/tda18271, |
1805 | * the agc callback logic is not called during DVB attach time, | 1805 | * the agc callback logic is not called during DVB attach time, |
1806 | * causing mb86a20s to not be initialized with Kworld SBTVD. | 1806 | * causing mb86a20s to not be initialized with Kworld SBTVD. |
1807 | * So, this hack is needed, in order to make Kworld SBTVD to work. | 1807 | * So, this hack is needed, in order to make Kworld SBTVD to work. |
1808 | */ | 1808 | */ |
1809 | if (state->need_init) | 1809 | if (state->need_init) |
1810 | mb86a20s_initfe(fe); | 1810 | mb86a20s_initfe(fe); |
1811 | 1811 | ||
1812 | if (fe->ops.i2c_gate_ctrl) | 1812 | if (fe->ops.i2c_gate_ctrl) |
1813 | fe->ops.i2c_gate_ctrl(fe, 0); | 1813 | fe->ops.i2c_gate_ctrl(fe, 0); |
1814 | 1814 | ||
1815 | rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception); | 1815 | rc = mb86a20s_writeregdata(state, mb86a20s_reset_reception); |
1816 | mb86a20s_reset_counters(fe); | 1816 | mb86a20s_reset_counters(fe); |
1817 | 1817 | ||
1818 | if (fe->ops.i2c_gate_ctrl) | 1818 | if (fe->ops.i2c_gate_ctrl) |
1819 | fe->ops.i2c_gate_ctrl(fe, 1); | 1819 | fe->ops.i2c_gate_ctrl(fe, 1); |
1820 | 1820 | ||
1821 | return rc; | 1821 | return rc; |
1822 | } | 1822 | } |
1823 | 1823 | ||
1824 | static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe, | 1824 | static int mb86a20s_read_status_and_stats(struct dvb_frontend *fe, |
1825 | fe_status_t *status) | 1825 | fe_status_t *status) |
1826 | { | 1826 | { |
1827 | struct mb86a20s_state *state = fe->demodulator_priv; | 1827 | struct mb86a20s_state *state = fe->demodulator_priv; |
1828 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1828 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1829 | int rc; | 1829 | int rc; |
1830 | 1830 | ||
1831 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 1831 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
1832 | 1832 | ||
1833 | if (fe->ops.i2c_gate_ctrl) | 1833 | if (fe->ops.i2c_gate_ctrl) |
1834 | fe->ops.i2c_gate_ctrl(fe, 0); | 1834 | fe->ops.i2c_gate_ctrl(fe, 0); |
1835 | 1835 | ||
1836 | /* Get lock */ | 1836 | /* Get lock */ |
1837 | rc = mb86a20s_read_status(fe, status); | 1837 | rc = mb86a20s_read_status(fe, status); |
1838 | if (!(*status & FE_HAS_LOCK)) { | 1838 | if (!(*status & FE_HAS_LOCK)) { |
1839 | mb86a20s_stats_not_ready(fe); | 1839 | mb86a20s_stats_not_ready(fe); |
1840 | mb86a20s_reset_frontend_cache(fe); | 1840 | mb86a20s_reset_frontend_cache(fe); |
1841 | } | 1841 | } |
1842 | if (rc < 0) { | 1842 | if (rc < 0) { |
1843 | dev_err(&state->i2c->dev, | 1843 | dev_err(&state->i2c->dev, |
1844 | "%s: Can't read frontend lock status\n", __func__); | 1844 | "%s: Can't read frontend lock status\n", __func__); |
1845 | goto error; | 1845 | goto error; |
1846 | } | 1846 | } |
1847 | 1847 | ||
1848 | /* Get signal strength */ | 1848 | /* Get signal strength */ |
1849 | rc = mb86a20s_read_signal_strength(fe); | 1849 | rc = mb86a20s_read_signal_strength(fe); |
1850 | if (rc < 0) { | 1850 | if (rc < 0) { |
1851 | dev_err(&state->i2c->dev, | 1851 | dev_err(&state->i2c->dev, |
1852 | "%s: Can't reset VBER registers.\n", __func__); | 1852 | "%s: Can't reset VBER registers.\n", __func__); |
1853 | mb86a20s_stats_not_ready(fe); | 1853 | mb86a20s_stats_not_ready(fe); |
1854 | mb86a20s_reset_frontend_cache(fe); | 1854 | mb86a20s_reset_frontend_cache(fe); |
1855 | 1855 | ||
1856 | rc = 0; /* Status is OK */ | 1856 | rc = 0; /* Status is OK */ |
1857 | goto error; | 1857 | goto error; |
1858 | } | 1858 | } |
1859 | /* Fill signal strength */ | 1859 | /* Fill signal strength */ |
1860 | c->strength.stat[0].uvalue = rc; | 1860 | c->strength.stat[0].uvalue = rc; |
1861 | 1861 | ||
1862 | if (*status & FE_HAS_LOCK) { | 1862 | if (*status & FE_HAS_LOCK) { |
1863 | /* Get TMCC info*/ | 1863 | /* Get TMCC info*/ |
1864 | rc = mb86a20s_get_frontend(fe); | 1864 | rc = mb86a20s_get_frontend(fe); |
1865 | if (rc < 0) { | 1865 | if (rc < 0) { |
1866 | dev_err(&state->i2c->dev, | 1866 | dev_err(&state->i2c->dev, |
1867 | "%s: Can't get FE TMCC data.\n", __func__); | 1867 | "%s: Can't get FE TMCC data.\n", __func__); |
1868 | rc = 0; /* Status is OK */ | 1868 | rc = 0; /* Status is OK */ |
1869 | goto error; | 1869 | goto error; |
1870 | } | 1870 | } |
1871 | 1871 | ||
1872 | /* Get statistics */ | 1872 | /* Get statistics */ |
1873 | rc = mb86a20s_get_stats(fe); | 1873 | rc = mb86a20s_get_stats(fe); |
1874 | if (rc < 0 && rc != -EBUSY) { | 1874 | if (rc < 0 && rc != -EBUSY) { |
1875 | dev_err(&state->i2c->dev, | 1875 | dev_err(&state->i2c->dev, |
1876 | "%s: Can't get FE statistics.\n", __func__); | 1876 | "%s: Can't get FE statistics.\n", __func__); |
1877 | rc = 0; | 1877 | rc = 0; |
1878 | goto error; | 1878 | goto error; |
1879 | } | 1879 | } |
1880 | rc = 0; /* Don't return EBUSY to userspace */ | 1880 | rc = 0; /* Don't return EBUSY to userspace */ |
1881 | } | 1881 | } |
1882 | goto ok; | 1882 | goto ok; |
1883 | 1883 | ||
1884 | error: | 1884 | error: |
1885 | mb86a20s_stats_not_ready(fe); | 1885 | mb86a20s_stats_not_ready(fe); |
1886 | 1886 | ||
1887 | ok: | 1887 | ok: |
1888 | if (fe->ops.i2c_gate_ctrl) | 1888 | if (fe->ops.i2c_gate_ctrl) |
1889 | fe->ops.i2c_gate_ctrl(fe, 1); | 1889 | fe->ops.i2c_gate_ctrl(fe, 1); |
1890 | 1890 | ||
1891 | return rc; | 1891 | return rc; |
1892 | } | 1892 | } |
1893 | 1893 | ||
1894 | static int mb86a20s_read_signal_strength_from_cache(struct dvb_frontend *fe, | 1894 | static int mb86a20s_read_signal_strength_from_cache(struct dvb_frontend *fe, |
1895 | u16 *strength) | 1895 | u16 *strength) |
1896 | { | 1896 | { |
1897 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1897 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1898 | 1898 | ||
1899 | 1899 | ||
1900 | *strength = c->strength.stat[0].uvalue; | 1900 | *strength = c->strength.stat[0].uvalue; |
1901 | 1901 | ||
1902 | return 0; | 1902 | return 0; |
1903 | } | 1903 | } |
1904 | 1904 | ||
1905 | static int mb86a20s_get_frontend_dummy(struct dvb_frontend *fe) | 1905 | static int mb86a20s_get_frontend_dummy(struct dvb_frontend *fe) |
1906 | { | 1906 | { |
1907 | /* | 1907 | /* |
1908 | * get_frontend is now handled together with other stats | 1908 | * get_frontend is now handled together with other stats |
1909 | * retrival, when read_status() is called, as some statistics | 1909 | * retrival, when read_status() is called, as some statistics |
1910 | * will depend on the layers detection. | 1910 | * will depend on the layers detection. |
1911 | */ | 1911 | */ |
1912 | return 0; | 1912 | return 0; |
1913 | }; | 1913 | }; |
1914 | 1914 | ||
1915 | static int mb86a20s_tune(struct dvb_frontend *fe, | 1915 | static int mb86a20s_tune(struct dvb_frontend *fe, |
1916 | bool re_tune, | 1916 | bool re_tune, |
1917 | unsigned int mode_flags, | 1917 | unsigned int mode_flags, |
1918 | unsigned int *delay, | 1918 | unsigned int *delay, |
1919 | fe_status_t *status) | 1919 | fe_status_t *status) |
1920 | { | 1920 | { |
1921 | struct mb86a20s_state *state = fe->demodulator_priv; | 1921 | struct mb86a20s_state *state = fe->demodulator_priv; |
1922 | int rc = 0; | 1922 | int rc = 0; |
1923 | 1923 | ||
1924 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 1924 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
1925 | 1925 | ||
1926 | if (re_tune) | 1926 | if (re_tune) |
1927 | rc = mb86a20s_set_frontend(fe); | 1927 | rc = mb86a20s_set_frontend(fe); |
1928 | 1928 | ||
1929 | if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) | 1929 | if (!(mode_flags & FE_TUNE_MODE_ONESHOT)) |
1930 | mb86a20s_read_status_and_stats(fe, status); | 1930 | mb86a20s_read_status_and_stats(fe, status); |
1931 | 1931 | ||
1932 | return rc; | 1932 | return rc; |
1933 | } | 1933 | } |
1934 | 1934 | ||
1935 | static void mb86a20s_release(struct dvb_frontend *fe) | 1935 | static void mb86a20s_release(struct dvb_frontend *fe) |
1936 | { | 1936 | { |
1937 | struct mb86a20s_state *state = fe->demodulator_priv; | 1937 | struct mb86a20s_state *state = fe->demodulator_priv; |
1938 | 1938 | ||
1939 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); | 1939 | dev_dbg(&state->i2c->dev, "%s called.\n", __func__); |
1940 | 1940 | ||
1941 | kfree(state); | 1941 | kfree(state); |
1942 | } | 1942 | } |
1943 | 1943 | ||
1944 | static struct dvb_frontend_ops mb86a20s_ops; | 1944 | static struct dvb_frontend_ops mb86a20s_ops; |
1945 | 1945 | ||
1946 | struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config, | 1946 | struct dvb_frontend *mb86a20s_attach(const struct mb86a20s_config *config, |
1947 | struct i2c_adapter *i2c) | 1947 | struct i2c_adapter *i2c) |
1948 | { | 1948 | { |
1949 | struct mb86a20s_state *state; | 1949 | struct mb86a20s_state *state; |
1950 | u8 rev; | 1950 | u8 rev; |
1951 | 1951 | ||
1952 | dev_dbg(&i2c->dev, "%s called.\n", __func__); | 1952 | dev_dbg(&i2c->dev, "%s called.\n", __func__); |
1953 | 1953 | ||
1954 | /* allocate memory for the internal state */ | 1954 | /* allocate memory for the internal state */ |
1955 | state = kzalloc(sizeof(struct mb86a20s_state), GFP_KERNEL); | 1955 | state = kzalloc(sizeof(struct mb86a20s_state), GFP_KERNEL); |
1956 | if (state == NULL) { | 1956 | if (state == NULL) { |
1957 | dev_err(&i2c->dev, | 1957 | dev_err(&i2c->dev, |
1958 | "%s: unable to allocate memory for state\n", __func__); | 1958 | "%s: unable to allocate memory for state\n", __func__); |
1959 | goto error; | 1959 | goto error; |
1960 | } | 1960 | } |
1961 | 1961 | ||
1962 | /* setup the state */ | 1962 | /* setup the state */ |
1963 | state->config = config; | 1963 | state->config = config; |
1964 | state->i2c = i2c; | 1964 | state->i2c = i2c; |
1965 | 1965 | ||
1966 | /* create dvb_frontend */ | 1966 | /* create dvb_frontend */ |
1967 | memcpy(&state->frontend.ops, &mb86a20s_ops, | 1967 | memcpy(&state->frontend.ops, &mb86a20s_ops, |
1968 | sizeof(struct dvb_frontend_ops)); | 1968 | sizeof(struct dvb_frontend_ops)); |
1969 | state->frontend.demodulator_priv = state; | 1969 | state->frontend.demodulator_priv = state; |
1970 | 1970 | ||
1971 | /* Check if it is a mb86a20s frontend */ | 1971 | /* Check if it is a mb86a20s frontend */ |
1972 | rev = mb86a20s_readreg(state, 0); | 1972 | rev = mb86a20s_readreg(state, 0); |
1973 | 1973 | ||
1974 | if (rev == 0x13) { | 1974 | if (rev == 0x13) { |
1975 | dev_info(&i2c->dev, | 1975 | dev_info(&i2c->dev, |
1976 | "Detected a Fujitsu mb86a20s frontend\n"); | 1976 | "Detected a Fujitsu mb86a20s frontend\n"); |
1977 | } else { | 1977 | } else { |
1978 | dev_dbg(&i2c->dev, | 1978 | dev_dbg(&i2c->dev, |
1979 | "Frontend revision %d is unknown - aborting.\n", | 1979 | "Frontend revision %d is unknown - aborting.\n", |
1980 | rev); | 1980 | rev); |
1981 | goto error; | 1981 | goto error; |
1982 | } | 1982 | } |
1983 | 1983 | ||
1984 | return &state->frontend; | 1984 | return &state->frontend; |
1985 | 1985 | ||
1986 | error: | 1986 | error: |
1987 | kfree(state); | 1987 | kfree(state); |
1988 | return NULL; | 1988 | return NULL; |
1989 | } | 1989 | } |
1990 | EXPORT_SYMBOL(mb86a20s_attach); | 1990 | EXPORT_SYMBOL(mb86a20s_attach); |
1991 | 1991 | ||
1992 | static struct dvb_frontend_ops mb86a20s_ops = { | 1992 | static struct dvb_frontend_ops mb86a20s_ops = { |
1993 | .delsys = { SYS_ISDBT }, | 1993 | .delsys = { SYS_ISDBT }, |
1994 | /* Use dib8000 values per default */ | 1994 | /* Use dib8000 values per default */ |
1995 | .info = { | 1995 | .info = { |
1996 | .name = "Fujitsu mb86A20s", | 1996 | .name = "Fujitsu mb86A20s", |
1997 | .caps = FE_CAN_INVERSION_AUTO | FE_CAN_RECOVER | | 1997 | .caps = FE_CAN_INVERSION_AUTO | FE_CAN_RECOVER | |
1998 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | | 1998 | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | |
1999 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | | 1999 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | |
2000 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | | 2000 | FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | |
2001 | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_QAM_AUTO | | 2001 | FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_QAM_AUTO | |
2002 | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO, | 2002 | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO, |
2003 | /* Actually, those values depend on the used tuner */ | 2003 | /* Actually, those values depend on the used tuner */ |
2004 | .frequency_min = 45000000, | 2004 | .frequency_min = 45000000, |
2005 | .frequency_max = 864000000, | 2005 | .frequency_max = 864000000, |
2006 | .frequency_stepsize = 62500, | 2006 | .frequency_stepsize = 62500, |
2007 | }, | 2007 | }, |
2008 | 2008 | ||
2009 | .release = mb86a20s_release, | 2009 | .release = mb86a20s_release, |
2010 | 2010 | ||
2011 | .init = mb86a20s_initfe, | 2011 | .init = mb86a20s_initfe, |
2012 | .set_frontend = mb86a20s_set_frontend, | 2012 | .set_frontend = mb86a20s_set_frontend, |
2013 | .get_frontend = mb86a20s_get_frontend_dummy, | 2013 | .get_frontend = mb86a20s_get_frontend_dummy, |
2014 | .read_status = mb86a20s_read_status_and_stats, | 2014 | .read_status = mb86a20s_read_status_and_stats, |
2015 | .read_signal_strength = mb86a20s_read_signal_strength_from_cache, | 2015 | .read_signal_strength = mb86a20s_read_signal_strength_from_cache, |
2016 | .tune = mb86a20s_tune, | 2016 | .tune = mb86a20s_tune, |
2017 | }; | 2017 | }; |
2018 | 2018 | ||
2019 | MODULE_DESCRIPTION("DVB Frontend module for Fujitsu mb86A20s hardware"); | 2019 | MODULE_DESCRIPTION("DVB Frontend module for Fujitsu mb86A20s hardware"); |
2020 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); | 2020 | MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>"); |
2021 | MODULE_LICENSE("GPL"); | 2021 | MODULE_LICENSE("GPL"); |
2022 | 2022 |
drivers/media/pci/cx25821/cx25821-video.c
1 | /* | 1 | /* |
2 | * Driver for the Conexant CX25821 PCIe bridge | 2 | * Driver for the Conexant CX25821 PCIe bridge |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Conexant Systems Inc. | 4 | * Copyright (C) 2009 Conexant Systems Inc. |
5 | * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> | 5 | * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> |
6 | * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver | 6 | * Based on Steven Toth <stoth@linuxtv.org> cx23885 driver |
7 | * Parts adapted/taken from Eduardo Moscoso Rubino | 7 | * Parts adapted/taken from Eduardo Moscoso Rubino |
8 | * Copyright (C) 2009 Eduardo Moscoso Rubino <moscoso@TopoLogica.com> | 8 | * Copyright (C) 2009 Eduardo Moscoso Rubino <moscoso@TopoLogica.com> |
9 | * | 9 | * |
10 | * | 10 | * |
11 | * This program is free software; you can redistribute it and/or modify | 11 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 12 | * it under the terms of the GNU General Public License as published by |
13 | * the Free Software Foundation; either version 2 of the License, or | 13 | * the Free Software Foundation; either version 2 of the License, or |
14 | * (at your option) any later version. | 14 | * (at your option) any later version. |
15 | * | 15 | * |
16 | * This program is distributed in the hope that it will be useful, | 16 | * This program is distributed in the hope that it will be useful, |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | * | 19 | * |
20 | * GNU General Public License for more details. | 20 | * GNU General Public License for more details. |
21 | * | 21 | * |
22 | * You should have received a copy of the GNU General Public License | 22 | * You should have received a copy of the GNU General Public License |
23 | * along with this program; if not, write to the Free Software | 23 | * along with this program; if not, write to the Free Software |
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 27 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
28 | 28 | ||
29 | #include "cx25821-video.h" | 29 | #include "cx25821-video.h" |
30 | 30 | ||
31 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); | 31 | MODULE_DESCRIPTION("v4l2 driver module for cx25821 based TV cards"); |
32 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); | 32 | MODULE_AUTHOR("Hiep Huynh <hiep.huynh@conexant.com>"); |
33 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
34 | 34 | ||
35 | static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; | 35 | static unsigned int video_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; |
36 | static unsigned int radio_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; | 36 | static unsigned int radio_nr[] = {[0 ... (CX25821_MAXBOARDS - 1)] = UNSET }; |
37 | 37 | ||
38 | module_param_array(video_nr, int, NULL, 0444); | 38 | module_param_array(video_nr, int, NULL, 0444); |
39 | module_param_array(radio_nr, int, NULL, 0444); | 39 | module_param_array(radio_nr, int, NULL, 0444); |
40 | 40 | ||
41 | MODULE_PARM_DESC(video_nr, "video device numbers"); | 41 | MODULE_PARM_DESC(video_nr, "video device numbers"); |
42 | MODULE_PARM_DESC(radio_nr, "radio device numbers"); | 42 | MODULE_PARM_DESC(radio_nr, "radio device numbers"); |
43 | 43 | ||
44 | static unsigned int video_debug = VIDEO_DEBUG; | 44 | static unsigned int video_debug = VIDEO_DEBUG; |
45 | module_param(video_debug, int, 0644); | 45 | module_param(video_debug, int, 0644); |
46 | MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); | 46 | MODULE_PARM_DESC(video_debug, "enable debug messages [video]"); |
47 | 47 | ||
48 | static unsigned int irq_debug; | 48 | static unsigned int irq_debug; |
49 | module_param(irq_debug, int, 0644); | 49 | module_param(irq_debug, int, 0644); |
50 | MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]"); | 50 | MODULE_PARM_DESC(irq_debug, "enable debug messages [IRQ handler]"); |
51 | 51 | ||
52 | unsigned int vid_limit = 16; | 52 | unsigned int vid_limit = 16; |
53 | module_param(vid_limit, int, 0644); | 53 | module_param(vid_limit, int, 0644); |
54 | MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); | 54 | MODULE_PARM_DESC(vid_limit, "capture memory limit in megabytes"); |
55 | 55 | ||
56 | static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num); | 56 | static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num); |
57 | 57 | ||
58 | static const struct v4l2_file_operations video_fops; | 58 | static const struct v4l2_file_operations video_fops; |
59 | static const struct v4l2_ioctl_ops video_ioctl_ops; | 59 | static const struct v4l2_ioctl_ops video_ioctl_ops; |
60 | 60 | ||
61 | #define FORMAT_FLAGS_PACKED 0x01 | 61 | #define FORMAT_FLAGS_PACKED 0x01 |
62 | 62 | ||
63 | struct cx25821_fmt formats[] = { | 63 | struct cx25821_fmt formats[] = { |
64 | { | 64 | { |
65 | .name = "8 bpp, gray", | 65 | .name = "8 bpp, gray", |
66 | .fourcc = V4L2_PIX_FMT_GREY, | 66 | .fourcc = V4L2_PIX_FMT_GREY, |
67 | .depth = 8, | 67 | .depth = 8, |
68 | .flags = FORMAT_FLAGS_PACKED, | 68 | .flags = FORMAT_FLAGS_PACKED, |
69 | }, { | 69 | }, { |
70 | .name = "4:1:1, packed, Y41P", | 70 | .name = "4:1:1, packed, Y41P", |
71 | .fourcc = V4L2_PIX_FMT_Y41P, | 71 | .fourcc = V4L2_PIX_FMT_Y41P, |
72 | .depth = 12, | 72 | .depth = 12, |
73 | .flags = FORMAT_FLAGS_PACKED, | 73 | .flags = FORMAT_FLAGS_PACKED, |
74 | }, { | 74 | }, { |
75 | .name = "4:2:2, packed, YUYV", | 75 | .name = "4:2:2, packed, YUYV", |
76 | .fourcc = V4L2_PIX_FMT_YUYV, | 76 | .fourcc = V4L2_PIX_FMT_YUYV, |
77 | .depth = 16, | 77 | .depth = 16, |
78 | .flags = FORMAT_FLAGS_PACKED, | 78 | .flags = FORMAT_FLAGS_PACKED, |
79 | }, { | 79 | }, { |
80 | .name = "4:2:2, packed, UYVY", | 80 | .name = "4:2:2, packed, UYVY", |
81 | .fourcc = V4L2_PIX_FMT_UYVY, | 81 | .fourcc = V4L2_PIX_FMT_UYVY, |
82 | .depth = 16, | 82 | .depth = 16, |
83 | .flags = FORMAT_FLAGS_PACKED, | 83 | .flags = FORMAT_FLAGS_PACKED, |
84 | }, { | 84 | }, { |
85 | .name = "4:2:0, YUV", | 85 | .name = "4:2:0, YUV", |
86 | .fourcc = V4L2_PIX_FMT_YUV420, | 86 | .fourcc = V4L2_PIX_FMT_YUV420, |
87 | .depth = 12, | 87 | .depth = 12, |
88 | .flags = FORMAT_FLAGS_PACKED, | 88 | .flags = FORMAT_FLAGS_PACKED, |
89 | }, | 89 | }, |
90 | }; | 90 | }; |
91 | 91 | ||
92 | int cx25821_get_format_size(void) | 92 | int cx25821_get_format_size(void) |
93 | { | 93 | { |
94 | return ARRAY_SIZE(formats); | 94 | return ARRAY_SIZE(formats); |
95 | } | 95 | } |
96 | 96 | ||
97 | struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc) | 97 | struct cx25821_fmt *cx25821_format_by_fourcc(unsigned int fourcc) |
98 | { | 98 | { |
99 | unsigned int i; | 99 | unsigned int i; |
100 | 100 | ||
101 | if (fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P) | 101 | if (fourcc == V4L2_PIX_FMT_Y41P || fourcc == V4L2_PIX_FMT_YUV411P) |
102 | return formats + 1; | 102 | return formats + 1; |
103 | 103 | ||
104 | for (i = 0; i < ARRAY_SIZE(formats); i++) | 104 | for (i = 0; i < ARRAY_SIZE(formats); i++) |
105 | if (formats[i].fourcc == fourcc) | 105 | if (formats[i].fourcc == fourcc) |
106 | return formats + i; | 106 | return formats + i; |
107 | 107 | ||
108 | pr_err("%s(0x%08x) NOT FOUND\n", __func__, fourcc); | 108 | pr_err("%s(0x%08x) NOT FOUND\n", __func__, fourcc); |
109 | return NULL; | 109 | return NULL; |
110 | } | 110 | } |
111 | 111 | ||
112 | void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, | 112 | void cx25821_video_wakeup(struct cx25821_dev *dev, struct cx25821_dmaqueue *q, |
113 | u32 count) | 113 | u32 count) |
114 | { | 114 | { |
115 | struct cx25821_buffer *buf; | 115 | struct cx25821_buffer *buf; |
116 | int bc; | 116 | int bc; |
117 | 117 | ||
118 | for (bc = 0;; bc++) { | 118 | for (bc = 0;; bc++) { |
119 | if (list_empty(&q->active)) { | 119 | if (list_empty(&q->active)) { |
120 | dprintk(1, "bc=%d (=0: active empty)\n", bc); | 120 | dprintk(1, "bc=%d (=0: active empty)\n", bc); |
121 | break; | 121 | break; |
122 | } | 122 | } |
123 | 123 | ||
124 | buf = list_entry(q->active.next, struct cx25821_buffer, | 124 | buf = list_entry(q->active.next, struct cx25821_buffer, |
125 | vb.queue); | 125 | vb.queue); |
126 | 126 | ||
127 | /* count comes from the hw and it is 16bit wide -- | 127 | /* count comes from the hw and it is 16bit wide -- |
128 | * this trick handles wrap-arounds correctly for | 128 | * this trick handles wrap-arounds correctly for |
129 | * up to 32767 buffers in flight... */ | 129 | * up to 32767 buffers in flight... */ |
130 | if ((s16) (count - buf->count) < 0) | 130 | if ((s16) (count - buf->count) < 0) |
131 | break; | 131 | break; |
132 | 132 | ||
133 | v4l2_get_timestamp(&buf->vb.ts); | 133 | v4l2_get_timestamp(&buf->vb.ts); |
134 | buf->vb.state = VIDEOBUF_DONE; | 134 | buf->vb.state = VIDEOBUF_DONE; |
135 | list_del(&buf->vb.queue); | 135 | list_del(&buf->vb.queue); |
136 | wake_up(&buf->vb.done); | 136 | wake_up(&buf->vb.done); |
137 | } | 137 | } |
138 | 138 | ||
139 | if (list_empty(&q->active)) | 139 | if (list_empty(&q->active)) |
140 | del_timer(&q->timeout); | 140 | del_timer(&q->timeout); |
141 | else | 141 | else |
142 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | 142 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); |
143 | if (bc != 1) | 143 | if (bc != 1) |
144 | pr_err("%s: %d buffers handled (should be 1)\n", __func__, bc); | 144 | pr_err("%s: %d buffers handled (should be 1)\n", __func__, bc); |
145 | } | 145 | } |
146 | 146 | ||
147 | #ifdef TUNER_FLAG | 147 | #ifdef TUNER_FLAG |
148 | int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm) | 148 | int cx25821_set_tvnorm(struct cx25821_dev *dev, v4l2_std_id norm) |
149 | { | 149 | { |
150 | dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", | 150 | dprintk(1, "%s(norm = 0x%08x) name: [%s]\n", |
151 | __func__, (unsigned int)norm, v4l2_norm_to_name(norm)); | 151 | __func__, (unsigned int)norm, v4l2_norm_to_name(norm)); |
152 | 152 | ||
153 | dev->tvnorm = norm; | 153 | dev->tvnorm = norm; |
154 | 154 | ||
155 | /* Tell the internal A/V decoder */ | 155 | /* Tell the internal A/V decoder */ |
156 | cx25821_call_all(dev, core, s_std, norm); | 156 | cx25821_call_all(dev, core, s_std, norm); |
157 | 157 | ||
158 | return 0; | 158 | return 0; |
159 | } | 159 | } |
160 | #endif | 160 | #endif |
161 | 161 | ||
162 | struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, | 162 | struct video_device *cx25821_vdev_init(struct cx25821_dev *dev, |
163 | struct pci_dev *pci, | 163 | struct pci_dev *pci, |
164 | struct video_device *template, | 164 | struct video_device *template, |
165 | char *type) | 165 | char *type) |
166 | { | 166 | { |
167 | struct video_device *vfd; | 167 | struct video_device *vfd; |
168 | dprintk(1, "%s()\n", __func__); | 168 | dprintk(1, "%s()\n", __func__); |
169 | 169 | ||
170 | vfd = video_device_alloc(); | 170 | vfd = video_device_alloc(); |
171 | if (NULL == vfd) | 171 | if (NULL == vfd) |
172 | return NULL; | 172 | return NULL; |
173 | *vfd = *template; | 173 | *vfd = *template; |
174 | vfd->v4l2_dev = &dev->v4l2_dev; | 174 | vfd->v4l2_dev = &dev->v4l2_dev; |
175 | vfd->release = video_device_release; | 175 | vfd->release = video_device_release; |
176 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, | 176 | snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name, type, |
177 | cx25821_boards[dev->board].name); | 177 | cx25821_boards[dev->board].name); |
178 | video_set_drvdata(vfd, dev); | 178 | video_set_drvdata(vfd, dev); |
179 | return vfd; | 179 | return vfd; |
180 | } | 180 | } |
181 | 181 | ||
182 | /* | 182 | /* |
183 | static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) | 183 | static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) |
184 | { | 184 | { |
185 | int i; | 185 | int i; |
186 | 186 | ||
187 | if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1) | 187 | if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1) |
188 | return -EINVAL; | 188 | return -EINVAL; |
189 | for (i = 0; i < CX25821_CTLS; i++) | 189 | for (i = 0; i < CX25821_CTLS; i++) |
190 | if (cx25821_ctls[i].v.id == qctrl->id) | 190 | if (cx25821_ctls[i].v.id == qctrl->id) |
191 | break; | 191 | break; |
192 | if (i == CX25821_CTLS) { | 192 | if (i == CX25821_CTLS) { |
193 | *qctrl = no_ctl; | 193 | *qctrl = no_ctl; |
194 | return 0; | 194 | return 0; |
195 | } | 195 | } |
196 | *qctrl = cx25821_ctls[i].v; | 196 | *qctrl = cx25821_ctls[i].v; |
197 | return 0; | 197 | return 0; |
198 | } | 198 | } |
199 | */ | 199 | */ |
200 | 200 | ||
201 | /* resource management */ | 201 | /* resource management */ |
202 | int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, | 202 | int cx25821_res_get(struct cx25821_dev *dev, struct cx25821_fh *fh, |
203 | unsigned int bit) | 203 | unsigned int bit) |
204 | { | 204 | { |
205 | dprintk(1, "%s()\n", __func__); | 205 | dprintk(1, "%s()\n", __func__); |
206 | if (fh->resources & bit) | 206 | if (fh->resources & bit) |
207 | /* have it already allocated */ | 207 | /* have it already allocated */ |
208 | return 1; | 208 | return 1; |
209 | 209 | ||
210 | /* is it free? */ | 210 | /* is it free? */ |
211 | mutex_lock(&dev->lock); | 211 | mutex_lock(&dev->lock); |
212 | if (dev->channels[fh->channel_id].resources & bit) { | 212 | if (dev->channels[fh->channel_id].resources & bit) { |
213 | /* no, someone else uses it */ | 213 | /* no, someone else uses it */ |
214 | mutex_unlock(&dev->lock); | 214 | mutex_unlock(&dev->lock); |
215 | return 0; | 215 | return 0; |
216 | } | 216 | } |
217 | /* it's free, grab it */ | 217 | /* it's free, grab it */ |
218 | fh->resources |= bit; | 218 | fh->resources |= bit; |
219 | dev->channels[fh->channel_id].resources |= bit; | 219 | dev->channels[fh->channel_id].resources |= bit; |
220 | dprintk(1, "res: get %d\n", bit); | 220 | dprintk(1, "res: get %d\n", bit); |
221 | mutex_unlock(&dev->lock); | 221 | mutex_unlock(&dev->lock); |
222 | return 1; | 222 | return 1; |
223 | } | 223 | } |
224 | 224 | ||
225 | int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit) | 225 | int cx25821_res_check(struct cx25821_fh *fh, unsigned int bit) |
226 | { | 226 | { |
227 | return fh->resources & bit; | 227 | return fh->resources & bit; |
228 | } | 228 | } |
229 | 229 | ||
230 | int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit) | 230 | int cx25821_res_locked(struct cx25821_fh *fh, unsigned int bit) |
231 | { | 231 | { |
232 | return fh->dev->channels[fh->channel_id].resources & bit; | 232 | return fh->dev->channels[fh->channel_id].resources & bit; |
233 | } | 233 | } |
234 | 234 | ||
235 | void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, | 235 | void cx25821_res_free(struct cx25821_dev *dev, struct cx25821_fh *fh, |
236 | unsigned int bits) | 236 | unsigned int bits) |
237 | { | 237 | { |
238 | BUG_ON((fh->resources & bits) != bits); | 238 | BUG_ON((fh->resources & bits) != bits); |
239 | dprintk(1, "%s()\n", __func__); | 239 | dprintk(1, "%s()\n", __func__); |
240 | 240 | ||
241 | mutex_lock(&dev->lock); | 241 | mutex_lock(&dev->lock); |
242 | fh->resources &= ~bits; | 242 | fh->resources &= ~bits; |
243 | dev->channels[fh->channel_id].resources &= ~bits; | 243 | dev->channels[fh->channel_id].resources &= ~bits; |
244 | dprintk(1, "res: put %d\n", bits); | 244 | dprintk(1, "res: put %d\n", bits); |
245 | mutex_unlock(&dev->lock); | 245 | mutex_unlock(&dev->lock); |
246 | } | 246 | } |
247 | 247 | ||
248 | int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input) | 248 | int cx25821_video_mux(struct cx25821_dev *dev, unsigned int input) |
249 | { | 249 | { |
250 | struct v4l2_routing route; | 250 | struct v4l2_routing route; |
251 | memset(&route, 0, sizeof(route)); | 251 | memset(&route, 0, sizeof(route)); |
252 | 252 | ||
253 | dprintk(1, "%s(): video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", | 253 | dprintk(1, "%s(): video_mux: %d [vmux=%d, gpio=0x%x,0x%x,0x%x,0x%x]\n", |
254 | __func__, input, INPUT(input)->vmux, INPUT(input)->gpio0, | 254 | __func__, input, INPUT(input)->vmux, INPUT(input)->gpio0, |
255 | INPUT(input)->gpio1, INPUT(input)->gpio2, INPUT(input)->gpio3); | 255 | INPUT(input)->gpio1, INPUT(input)->gpio2, INPUT(input)->gpio3); |
256 | dev->input = input; | 256 | dev->input = input; |
257 | 257 | ||
258 | route.input = INPUT(input)->vmux; | 258 | route.input = INPUT(input)->vmux; |
259 | 259 | ||
260 | /* Tell the internal A/V decoder */ | 260 | /* Tell the internal A/V decoder */ |
261 | cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0); | 261 | cx25821_call_all(dev, video, s_routing, INPUT(input)->vmux, 0, 0); |
262 | 262 | ||
263 | return 0; | 263 | return 0; |
264 | } | 264 | } |
265 | 265 | ||
266 | int cx25821_start_video_dma(struct cx25821_dev *dev, | 266 | int cx25821_start_video_dma(struct cx25821_dev *dev, |
267 | struct cx25821_dmaqueue *q, | 267 | struct cx25821_dmaqueue *q, |
268 | struct cx25821_buffer *buf, | 268 | struct cx25821_buffer *buf, |
269 | struct sram_channel *channel) | 269 | struct sram_channel *channel) |
270 | { | 270 | { |
271 | int tmp = 0; | 271 | int tmp = 0; |
272 | 272 | ||
273 | /* setup fifo + format */ | 273 | /* setup fifo + format */ |
274 | cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma); | 274 | cx25821_sram_channel_setup(dev, channel, buf->bpl, buf->risc.dma); |
275 | 275 | ||
276 | /* reset counter */ | 276 | /* reset counter */ |
277 | cx_write(channel->gpcnt_ctl, 3); | 277 | cx_write(channel->gpcnt_ctl, 3); |
278 | q->count = 1; | 278 | q->count = 1; |
279 | 279 | ||
280 | /* enable irq */ | 280 | /* enable irq */ |
281 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << channel->i)); | 281 | cx_set(PCI_INT_MSK, cx_read(PCI_INT_MSK) | (1 << channel->i)); |
282 | cx_set(channel->int_msk, 0x11); | 282 | cx_set(channel->int_msk, 0x11); |
283 | 283 | ||
284 | /* start dma */ | 284 | /* start dma */ |
285 | cx_write(channel->dma_ctl, 0x11); /* FIFO and RISC enable */ | 285 | cx_write(channel->dma_ctl, 0x11); /* FIFO and RISC enable */ |
286 | 286 | ||
287 | /* make sure upstream setting if any is reversed */ | 287 | /* make sure upstream setting if any is reversed */ |
288 | tmp = cx_read(VID_CH_MODE_SEL); | 288 | tmp = cx_read(VID_CH_MODE_SEL); |
289 | cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); | 289 | cx_write(VID_CH_MODE_SEL, tmp & 0xFFFFFE00); |
290 | 290 | ||
291 | return 0; | 291 | return 0; |
292 | } | 292 | } |
293 | 293 | ||
294 | static int cx25821_restart_video_queue(struct cx25821_dev *dev, | 294 | static int cx25821_restart_video_queue(struct cx25821_dev *dev, |
295 | struct cx25821_dmaqueue *q, | 295 | struct cx25821_dmaqueue *q, |
296 | struct sram_channel *channel) | 296 | struct sram_channel *channel) |
297 | { | 297 | { |
298 | struct cx25821_buffer *buf, *prev; | 298 | struct cx25821_buffer *buf, *prev; |
299 | struct list_head *item; | 299 | struct list_head *item; |
300 | 300 | ||
301 | if (!list_empty(&q->active)) { | 301 | if (!list_empty(&q->active)) { |
302 | buf = list_entry(q->active.next, struct cx25821_buffer, | 302 | buf = list_entry(q->active.next, struct cx25821_buffer, |
303 | vb.queue); | 303 | vb.queue); |
304 | 304 | ||
305 | cx25821_start_video_dma(dev, q, buf, channel); | 305 | cx25821_start_video_dma(dev, q, buf, channel); |
306 | 306 | ||
307 | list_for_each(item, &q->active) { | 307 | list_for_each(item, &q->active) { |
308 | buf = list_entry(item, struct cx25821_buffer, vb.queue); | 308 | buf = list_entry(item, struct cx25821_buffer, vb.queue); |
309 | buf->count = q->count++; | 309 | buf->count = q->count++; |
310 | } | 310 | } |
311 | 311 | ||
312 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | 312 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); |
313 | return 0; | 313 | return 0; |
314 | } | 314 | } |
315 | 315 | ||
316 | prev = NULL; | 316 | prev = NULL; |
317 | for (;;) { | 317 | for (;;) { |
318 | if (list_empty(&q->queued)) | 318 | if (list_empty(&q->queued)) |
319 | return 0; | 319 | return 0; |
320 | 320 | ||
321 | buf = list_entry(q->queued.next, struct cx25821_buffer, | 321 | buf = list_entry(q->queued.next, struct cx25821_buffer, |
322 | vb.queue); | 322 | vb.queue); |
323 | 323 | ||
324 | if (NULL == prev) { | 324 | if (NULL == prev) { |
325 | list_move_tail(&buf->vb.queue, &q->active); | 325 | list_move_tail(&buf->vb.queue, &q->active); |
326 | cx25821_start_video_dma(dev, q, buf, channel); | 326 | cx25821_start_video_dma(dev, q, buf, channel); |
327 | buf->vb.state = VIDEOBUF_ACTIVE; | 327 | buf->vb.state = VIDEOBUF_ACTIVE; |
328 | buf->count = q->count++; | 328 | buf->count = q->count++; |
329 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | 329 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); |
330 | } else if (prev->vb.width == buf->vb.width && | 330 | } else if (prev->vb.width == buf->vb.width && |
331 | prev->vb.height == buf->vb.height && | 331 | prev->vb.height == buf->vb.height && |
332 | prev->fmt == buf->fmt) { | 332 | prev->fmt == buf->fmt) { |
333 | list_move_tail(&buf->vb.queue, &q->active); | 333 | list_move_tail(&buf->vb.queue, &q->active); |
334 | buf->vb.state = VIDEOBUF_ACTIVE; | 334 | buf->vb.state = VIDEOBUF_ACTIVE; |
335 | buf->count = q->count++; | 335 | buf->count = q->count++; |
336 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | 336 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); |
337 | prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */ | 337 | prev->risc.jmp[2] = cpu_to_le32(0); /* Bits 63 - 32 */ |
338 | } else { | 338 | } else { |
339 | return 0; | 339 | return 0; |
340 | } | 340 | } |
341 | prev = buf; | 341 | prev = buf; |
342 | } | 342 | } |
343 | } | 343 | } |
344 | 344 | ||
345 | static void cx25821_vid_timeout(unsigned long data) | 345 | static void cx25821_vid_timeout(unsigned long data) |
346 | { | 346 | { |
347 | struct cx25821_data *timeout_data = (struct cx25821_data *)data; | 347 | struct cx25821_data *timeout_data = (struct cx25821_data *)data; |
348 | struct cx25821_dev *dev = timeout_data->dev; | 348 | struct cx25821_dev *dev = timeout_data->dev; |
349 | struct sram_channel *channel = timeout_data->channel; | 349 | struct sram_channel *channel = timeout_data->channel; |
350 | struct cx25821_dmaqueue *q = &dev->channels[channel->i].vidq; | 350 | struct cx25821_dmaqueue *q = &dev->channels[channel->i].vidq; |
351 | struct cx25821_buffer *buf; | 351 | struct cx25821_buffer *buf; |
352 | unsigned long flags; | 352 | unsigned long flags; |
353 | 353 | ||
354 | /* cx25821_sram_channel_dump(dev, channel); */ | 354 | /* cx25821_sram_channel_dump(dev, channel); */ |
355 | cx_clear(channel->dma_ctl, 0x11); | 355 | cx_clear(channel->dma_ctl, 0x11); |
356 | 356 | ||
357 | spin_lock_irqsave(&dev->slock, flags); | 357 | spin_lock_irqsave(&dev->slock, flags); |
358 | while (!list_empty(&q->active)) { | 358 | while (!list_empty(&q->active)) { |
359 | buf = list_entry(q->active.next, struct cx25821_buffer, | 359 | buf = list_entry(q->active.next, struct cx25821_buffer, |
360 | vb.queue); | 360 | vb.queue); |
361 | list_del(&buf->vb.queue); | 361 | list_del(&buf->vb.queue); |
362 | 362 | ||
363 | buf->vb.state = VIDEOBUF_ERROR; | 363 | buf->vb.state = VIDEOBUF_ERROR; |
364 | wake_up(&buf->vb.done); | 364 | wake_up(&buf->vb.done); |
365 | } | 365 | } |
366 | 366 | ||
367 | cx25821_restart_video_queue(dev, q, channel); | 367 | cx25821_restart_video_queue(dev, q, channel); |
368 | spin_unlock_irqrestore(&dev->slock, flags); | 368 | spin_unlock_irqrestore(&dev->slock, flags); |
369 | } | 369 | } |
370 | 370 | ||
371 | int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) | 371 | int cx25821_video_irq(struct cx25821_dev *dev, int chan_num, u32 status) |
372 | { | 372 | { |
373 | u32 count = 0; | 373 | u32 count = 0; |
374 | int handled = 0; | 374 | int handled = 0; |
375 | u32 mask; | 375 | u32 mask; |
376 | struct sram_channel *channel = dev->channels[chan_num].sram_channels; | 376 | struct sram_channel *channel = dev->channels[chan_num].sram_channels; |
377 | 377 | ||
378 | mask = cx_read(channel->int_msk); | 378 | mask = cx_read(channel->int_msk); |
379 | if (0 == (status & mask)) | 379 | if (0 == (status & mask)) |
380 | return handled; | 380 | return handled; |
381 | 381 | ||
382 | cx_write(channel->int_stat, status); | 382 | cx_write(channel->int_stat, status); |
383 | 383 | ||
384 | /* risc op code error */ | 384 | /* risc op code error */ |
385 | if (status & (1 << 16)) { | 385 | if (status & (1 << 16)) { |
386 | pr_warn("%s, %s: video risc op code error\n", | 386 | pr_warn("%s, %s: video risc op code error\n", |
387 | dev->name, channel->name); | 387 | dev->name, channel->name); |
388 | cx_clear(channel->dma_ctl, 0x11); | 388 | cx_clear(channel->dma_ctl, 0x11); |
389 | cx25821_sram_channel_dump(dev, channel); | 389 | cx25821_sram_channel_dump(dev, channel); |
390 | } | 390 | } |
391 | 391 | ||
392 | /* risc1 y */ | 392 | /* risc1 y */ |
393 | if (status & FLD_VID_DST_RISC1) { | 393 | if (status & FLD_VID_DST_RISC1) { |
394 | spin_lock(&dev->slock); | 394 | spin_lock(&dev->slock); |
395 | count = cx_read(channel->gpcnt); | 395 | count = cx_read(channel->gpcnt); |
396 | cx25821_video_wakeup(dev, &dev->channels[channel->i].vidq, | 396 | cx25821_video_wakeup(dev, &dev->channels[channel->i].vidq, |
397 | count); | 397 | count); |
398 | spin_unlock(&dev->slock); | 398 | spin_unlock(&dev->slock); |
399 | handled++; | 399 | handled++; |
400 | } | 400 | } |
401 | 401 | ||
402 | /* risc2 y */ | 402 | /* risc2 y */ |
403 | if (status & 0x10) { | 403 | if (status & 0x10) { |
404 | dprintk(2, "stopper video\n"); | 404 | dprintk(2, "stopper video\n"); |
405 | spin_lock(&dev->slock); | 405 | spin_lock(&dev->slock); |
406 | cx25821_restart_video_queue(dev, | 406 | cx25821_restart_video_queue(dev, |
407 | &dev->channels[channel->i].vidq, channel); | 407 | &dev->channels[channel->i].vidq, channel); |
408 | spin_unlock(&dev->slock); | 408 | spin_unlock(&dev->slock); |
409 | handled++; | 409 | handled++; |
410 | } | 410 | } |
411 | return handled; | 411 | return handled; |
412 | } | 412 | } |
413 | 413 | ||
414 | void cx25821_videoioctl_unregister(struct cx25821_dev *dev) | 414 | void cx25821_videoioctl_unregister(struct cx25821_dev *dev) |
415 | { | 415 | { |
416 | if (dev->ioctl_dev) { | 416 | if (dev->ioctl_dev) { |
417 | if (video_is_registered(dev->ioctl_dev)) | 417 | if (video_is_registered(dev->ioctl_dev)) |
418 | video_unregister_device(dev->ioctl_dev); | 418 | video_unregister_device(dev->ioctl_dev); |
419 | else | 419 | else |
420 | video_device_release(dev->ioctl_dev); | 420 | video_device_release(dev->ioctl_dev); |
421 | 421 | ||
422 | dev->ioctl_dev = NULL; | 422 | dev->ioctl_dev = NULL; |
423 | } | 423 | } |
424 | } | 424 | } |
425 | 425 | ||
426 | void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num) | 426 | void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num) |
427 | { | 427 | { |
428 | cx_clear(PCI_INT_MSK, 1); | 428 | cx_clear(PCI_INT_MSK, 1); |
429 | 429 | ||
430 | if (dev->channels[chan_num].video_dev) { | 430 | if (dev->channels[chan_num].video_dev) { |
431 | if (video_is_registered(dev->channels[chan_num].video_dev)) | 431 | if (video_is_registered(dev->channels[chan_num].video_dev)) |
432 | video_unregister_device( | 432 | video_unregister_device( |
433 | dev->channels[chan_num].video_dev); | 433 | dev->channels[chan_num].video_dev); |
434 | else | 434 | else |
435 | video_device_release( | 435 | video_device_release( |
436 | dev->channels[chan_num].video_dev); | 436 | dev->channels[chan_num].video_dev); |
437 | 437 | ||
438 | dev->channels[chan_num].video_dev = NULL; | 438 | dev->channels[chan_num].video_dev = NULL; |
439 | 439 | ||
440 | btcx_riscmem_free(dev->pci, | 440 | btcx_riscmem_free(dev->pci, |
441 | &dev->channels[chan_num].vidq.stopper); | 441 | &dev->channels[chan_num].vidq.stopper); |
442 | 442 | ||
443 | pr_warn("device %d released!\n", chan_num); | 443 | pr_warn("device %d released!\n", chan_num); |
444 | } | 444 | } |
445 | 445 | ||
446 | } | 446 | } |
447 | 447 | ||
448 | int cx25821_video_register(struct cx25821_dev *dev) | 448 | int cx25821_video_register(struct cx25821_dev *dev) |
449 | { | 449 | { |
450 | int err; | 450 | int err; |
451 | int i; | 451 | int i; |
452 | 452 | ||
453 | struct video_device cx25821_video_device = { | 453 | struct video_device cx25821_video_device = { |
454 | .name = "cx25821-video", | 454 | .name = "cx25821-video", |
455 | .fops = &video_fops, | 455 | .fops = &video_fops, |
456 | .minor = -1, | 456 | .minor = -1, |
457 | .ioctl_ops = &video_ioctl_ops, | 457 | .ioctl_ops = &video_ioctl_ops, |
458 | .tvnorms = CX25821_NORMS, | 458 | .tvnorms = CX25821_NORMS, |
459 | .current_norm = V4L2_STD_NTSC_M, | 459 | .current_norm = V4L2_STD_NTSC_M, |
460 | }; | 460 | }; |
461 | 461 | ||
462 | spin_lock_init(&dev->slock); | 462 | spin_lock_init(&dev->slock); |
463 | 463 | ||
464 | for (i = 0; i < MAX_VID_CHANNEL_NUM - 1; ++i) { | 464 | for (i = 0; i < VID_CHANNEL_NUM; ++i) { |
465 | cx25821_init_controls(dev, i); | 465 | cx25821_init_controls(dev, i); |
466 | 466 | ||
467 | cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper, | 467 | cx25821_risc_stopper(dev->pci, &dev->channels[i].vidq.stopper, |
468 | dev->channels[i].sram_channels->dma_ctl, 0x11, 0); | 468 | dev->channels[i].sram_channels->dma_ctl, 0x11, 0); |
469 | 469 | ||
470 | dev->channels[i].sram_channels = &cx25821_sram_channels[i]; | 470 | dev->channels[i].sram_channels = &cx25821_sram_channels[i]; |
471 | dev->channels[i].video_dev = NULL; | 471 | dev->channels[i].video_dev = NULL; |
472 | dev->channels[i].resources = 0; | 472 | dev->channels[i].resources = 0; |
473 | 473 | ||
474 | cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff); | 474 | cx_write(dev->channels[i].sram_channels->int_stat, 0xffffffff); |
475 | 475 | ||
476 | INIT_LIST_HEAD(&dev->channels[i].vidq.active); | 476 | INIT_LIST_HEAD(&dev->channels[i].vidq.active); |
477 | INIT_LIST_HEAD(&dev->channels[i].vidq.queued); | 477 | INIT_LIST_HEAD(&dev->channels[i].vidq.queued); |
478 | 478 | ||
479 | dev->channels[i].timeout_data.dev = dev; | 479 | dev->channels[i].timeout_data.dev = dev; |
480 | dev->channels[i].timeout_data.channel = | 480 | dev->channels[i].timeout_data.channel = |
481 | &cx25821_sram_channels[i]; | 481 | &cx25821_sram_channels[i]; |
482 | dev->channels[i].vidq.timeout.function = cx25821_vid_timeout; | 482 | dev->channels[i].vidq.timeout.function = cx25821_vid_timeout; |
483 | dev->channels[i].vidq.timeout.data = | 483 | dev->channels[i].vidq.timeout.data = |
484 | (unsigned long)&dev->channels[i].timeout_data; | 484 | (unsigned long)&dev->channels[i].timeout_data; |
485 | init_timer(&dev->channels[i].vidq.timeout); | 485 | init_timer(&dev->channels[i].vidq.timeout); |
486 | 486 | ||
487 | /* register v4l devices */ | 487 | /* register v4l devices */ |
488 | dev->channels[i].video_dev = cx25821_vdev_init(dev, dev->pci, | 488 | dev->channels[i].video_dev = cx25821_vdev_init(dev, dev->pci, |
489 | &cx25821_video_device, "video"); | 489 | &cx25821_video_device, "video"); |
490 | 490 | ||
491 | err = video_register_device(dev->channels[i].video_dev, | 491 | err = video_register_device(dev->channels[i].video_dev, |
492 | VFL_TYPE_GRABBER, video_nr[dev->nr]); | 492 | VFL_TYPE_GRABBER, video_nr[dev->nr]); |
493 | 493 | ||
494 | if (err < 0) | 494 | if (err < 0) |
495 | goto fail_unreg; | 495 | goto fail_unreg; |
496 | 496 | ||
497 | } | 497 | } |
498 | 498 | ||
499 | /* set PCI interrupt */ | 499 | /* set PCI interrupt */ |
500 | cx_set(PCI_INT_MSK, 0xff); | 500 | cx_set(PCI_INT_MSK, 0xff); |
501 | 501 | ||
502 | /* initial device configuration */ | 502 | /* initial device configuration */ |
503 | mutex_lock(&dev->lock); | 503 | mutex_lock(&dev->lock); |
504 | #ifdef TUNER_FLAG | 504 | #ifdef TUNER_FLAG |
505 | dev->tvnorm = cx25821_video_device.current_norm; | 505 | dev->tvnorm = cx25821_video_device.current_norm; |
506 | cx25821_set_tvnorm(dev, dev->tvnorm); | 506 | cx25821_set_tvnorm(dev, dev->tvnorm); |
507 | #endif | 507 | #endif |
508 | mutex_unlock(&dev->lock); | 508 | mutex_unlock(&dev->lock); |
509 | 509 | ||
510 | return 0; | 510 | return 0; |
511 | 511 | ||
512 | fail_unreg: | 512 | fail_unreg: |
513 | cx25821_video_unregister(dev, i); | 513 | cx25821_video_unregister(dev, i); |
514 | return err; | 514 | return err; |
515 | } | 515 | } |
516 | 516 | ||
517 | int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count, | 517 | int cx25821_buffer_setup(struct videobuf_queue *q, unsigned int *count, |
518 | unsigned int *size) | 518 | unsigned int *size) |
519 | { | 519 | { |
520 | struct cx25821_fh *fh = q->priv_data; | 520 | struct cx25821_fh *fh = q->priv_data; |
521 | 521 | ||
522 | *size = fh->fmt->depth * fh->width * fh->height >> 3; | 522 | *size = fh->fmt->depth * fh->width * fh->height >> 3; |
523 | 523 | ||
524 | if (0 == *count) | 524 | if (0 == *count) |
525 | *count = 32; | 525 | *count = 32; |
526 | 526 | ||
527 | if (*size * *count > vid_limit * 1024 * 1024) | 527 | if (*size * *count > vid_limit * 1024 * 1024) |
528 | *count = (vid_limit * 1024 * 1024) / *size; | 528 | *count = (vid_limit * 1024 * 1024) / *size; |
529 | 529 | ||
530 | return 0; | 530 | return 0; |
531 | } | 531 | } |
532 | 532 | ||
533 | int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, | 533 | int cx25821_buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, |
534 | enum v4l2_field field) | 534 | enum v4l2_field field) |
535 | { | 535 | { |
536 | struct cx25821_fh *fh = q->priv_data; | 536 | struct cx25821_fh *fh = q->priv_data; |
537 | struct cx25821_dev *dev = fh->dev; | 537 | struct cx25821_dev *dev = fh->dev; |
538 | struct cx25821_buffer *buf = | 538 | struct cx25821_buffer *buf = |
539 | container_of(vb, struct cx25821_buffer, vb); | 539 | container_of(vb, struct cx25821_buffer, vb); |
540 | int rc, init_buffer = 0; | 540 | int rc, init_buffer = 0; |
541 | u32 line0_offset; | 541 | u32 line0_offset; |
542 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); | 542 | struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); |
543 | int bpl_local = LINE_SIZE_D1; | 543 | int bpl_local = LINE_SIZE_D1; |
544 | int channel_opened = fh->channel_id; | 544 | int channel_opened = fh->channel_id; |
545 | 545 | ||
546 | BUG_ON(NULL == fh->fmt); | 546 | BUG_ON(NULL == fh->fmt); |
547 | if (fh->width < 48 || fh->width > 720 || | 547 | if (fh->width < 48 || fh->width > 720 || |
548 | fh->height < 32 || fh->height > 576) | 548 | fh->height < 32 || fh->height > 576) |
549 | return -EINVAL; | 549 | return -EINVAL; |
550 | 550 | ||
551 | buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; | 551 | buf->vb.size = (fh->width * fh->height * fh->fmt->depth) >> 3; |
552 | 552 | ||
553 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) | 553 | if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size) |
554 | return -EINVAL; | 554 | return -EINVAL; |
555 | 555 | ||
556 | if (buf->fmt != fh->fmt || | 556 | if (buf->fmt != fh->fmt || |
557 | buf->vb.width != fh->width || | 557 | buf->vb.width != fh->width || |
558 | buf->vb.height != fh->height || buf->vb.field != field) { | 558 | buf->vb.height != fh->height || buf->vb.field != field) { |
559 | buf->fmt = fh->fmt; | 559 | buf->fmt = fh->fmt; |
560 | buf->vb.width = fh->width; | 560 | buf->vb.width = fh->width; |
561 | buf->vb.height = fh->height; | 561 | buf->vb.height = fh->height; |
562 | buf->vb.field = field; | 562 | buf->vb.field = field; |
563 | init_buffer = 1; | 563 | init_buffer = 1; |
564 | } | 564 | } |
565 | 565 | ||
566 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { | 566 | if (VIDEOBUF_NEEDS_INIT == buf->vb.state) { |
567 | init_buffer = 1; | 567 | init_buffer = 1; |
568 | rc = videobuf_iolock(q, &buf->vb, NULL); | 568 | rc = videobuf_iolock(q, &buf->vb, NULL); |
569 | if (0 != rc) { | 569 | if (0 != rc) { |
570 | printk(KERN_DEBUG pr_fmt("videobuf_iolock failed!\n")); | 570 | printk(KERN_DEBUG pr_fmt("videobuf_iolock failed!\n")); |
571 | goto fail; | 571 | goto fail; |
572 | } | 572 | } |
573 | } | 573 | } |
574 | 574 | ||
575 | dprintk(1, "init_buffer=%d\n", init_buffer); | 575 | dprintk(1, "init_buffer=%d\n", init_buffer); |
576 | 576 | ||
577 | if (init_buffer) { | 577 | if (init_buffer) { |
578 | 578 | ||
579 | channel_opened = dev->channel_opened; | 579 | channel_opened = dev->channel_opened; |
580 | if (channel_opened < 0 || channel_opened > 7) | 580 | if (channel_opened < 0 || channel_opened > 7) |
581 | channel_opened = 7; | 581 | channel_opened = 7; |
582 | 582 | ||
583 | if (dev->channels[channel_opened].pixel_formats == | 583 | if (dev->channels[channel_opened].pixel_formats == |
584 | PIXEL_FRMT_411) | 584 | PIXEL_FRMT_411) |
585 | buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3; | 585 | buf->bpl = (buf->fmt->depth * buf->vb.width) >> 3; |
586 | else | 586 | else |
587 | buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width); | 587 | buf->bpl = (buf->fmt->depth >> 3) * (buf->vb.width); |
588 | 588 | ||
589 | if (dev->channels[channel_opened].pixel_formats == | 589 | if (dev->channels[channel_opened].pixel_formats == |
590 | PIXEL_FRMT_411) { | 590 | PIXEL_FRMT_411) { |
591 | bpl_local = buf->bpl; | 591 | bpl_local = buf->bpl; |
592 | } else { | 592 | } else { |
593 | bpl_local = buf->bpl; /* Default */ | 593 | bpl_local = buf->bpl; /* Default */ |
594 | 594 | ||
595 | if (channel_opened >= 0 && channel_opened <= 7) { | 595 | if (channel_opened >= 0 && channel_opened <= 7) { |
596 | if (dev->channels[channel_opened] | 596 | if (dev->channels[channel_opened] |
597 | .use_cif_resolution) { | 597 | .use_cif_resolution) { |
598 | if (dev->tvnorm & V4L2_STD_PAL_BG || | 598 | if (dev->tvnorm & V4L2_STD_PAL_BG || |
599 | dev->tvnorm & V4L2_STD_PAL_DK) | 599 | dev->tvnorm & V4L2_STD_PAL_DK) |
600 | bpl_local = 352 << 1; | 600 | bpl_local = 352 << 1; |
601 | else | 601 | else |
602 | bpl_local = dev->channels[ | 602 | bpl_local = dev->channels[ |
603 | channel_opened]. | 603 | channel_opened]. |
604 | cif_width << 1; | 604 | cif_width << 1; |
605 | } | 605 | } |
606 | } | 606 | } |
607 | } | 607 | } |
608 | 608 | ||
609 | switch (buf->vb.field) { | 609 | switch (buf->vb.field) { |
610 | case V4L2_FIELD_TOP: | 610 | case V4L2_FIELD_TOP: |
611 | cx25821_risc_buffer(dev->pci, &buf->risc, | 611 | cx25821_risc_buffer(dev->pci, &buf->risc, |
612 | dma->sglist, 0, UNSET, | 612 | dma->sglist, 0, UNSET, |
613 | buf->bpl, 0, buf->vb.height); | 613 | buf->bpl, 0, buf->vb.height); |
614 | break; | 614 | break; |
615 | case V4L2_FIELD_BOTTOM: | 615 | case V4L2_FIELD_BOTTOM: |
616 | cx25821_risc_buffer(dev->pci, &buf->risc, | 616 | cx25821_risc_buffer(dev->pci, &buf->risc, |
617 | dma->sglist, UNSET, 0, | 617 | dma->sglist, UNSET, 0, |
618 | buf->bpl, 0, buf->vb.height); | 618 | buf->bpl, 0, buf->vb.height); |
619 | break; | 619 | break; |
620 | case V4L2_FIELD_INTERLACED: | 620 | case V4L2_FIELD_INTERLACED: |
621 | /* All other formats are top field first */ | 621 | /* All other formats are top field first */ |
622 | line0_offset = 0; | 622 | line0_offset = 0; |
623 | dprintk(1, "top field first\n"); | 623 | dprintk(1, "top field first\n"); |
624 | 624 | ||
625 | cx25821_risc_buffer(dev->pci, &buf->risc, | 625 | cx25821_risc_buffer(dev->pci, &buf->risc, |
626 | dma->sglist, line0_offset, | 626 | dma->sglist, line0_offset, |
627 | bpl_local, bpl_local, bpl_local, | 627 | bpl_local, bpl_local, bpl_local, |
628 | buf->vb.height >> 1); | 628 | buf->vb.height >> 1); |
629 | break; | 629 | break; |
630 | case V4L2_FIELD_SEQ_TB: | 630 | case V4L2_FIELD_SEQ_TB: |
631 | cx25821_risc_buffer(dev->pci, &buf->risc, | 631 | cx25821_risc_buffer(dev->pci, &buf->risc, |
632 | dma->sglist, | 632 | dma->sglist, |
633 | 0, buf->bpl * (buf->vb.height >> 1), | 633 | 0, buf->bpl * (buf->vb.height >> 1), |
634 | buf->bpl, 0, buf->vb.height >> 1); | 634 | buf->bpl, 0, buf->vb.height >> 1); |
635 | break; | 635 | break; |
636 | case V4L2_FIELD_SEQ_BT: | 636 | case V4L2_FIELD_SEQ_BT: |
637 | cx25821_risc_buffer(dev->pci, &buf->risc, | 637 | cx25821_risc_buffer(dev->pci, &buf->risc, |
638 | dma->sglist, | 638 | dma->sglist, |
639 | buf->bpl * (buf->vb.height >> 1), 0, | 639 | buf->bpl * (buf->vb.height >> 1), 0, |
640 | buf->bpl, 0, buf->vb.height >> 1); | 640 | buf->bpl, 0, buf->vb.height >> 1); |
641 | break; | 641 | break; |
642 | default: | 642 | default: |
643 | BUG(); | 643 | BUG(); |
644 | } | 644 | } |
645 | } | 645 | } |
646 | 646 | ||
647 | dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", | 647 | dprintk(2, "[%p/%d] buffer_prep - %dx%d %dbpp \"%s\" - dma=0x%08lx\n", |
648 | buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth, | 648 | buf, buf->vb.i, fh->width, fh->height, fh->fmt->depth, |
649 | fh->fmt->name, (unsigned long)buf->risc.dma); | 649 | fh->fmt->name, (unsigned long)buf->risc.dma); |
650 | 650 | ||
651 | buf->vb.state = VIDEOBUF_PREPARED; | 651 | buf->vb.state = VIDEOBUF_PREPARED; |
652 | 652 | ||
653 | return 0; | 653 | return 0; |
654 | 654 | ||
655 | fail: | 655 | fail: |
656 | cx25821_free_buffer(q, buf); | 656 | cx25821_free_buffer(q, buf); |
657 | return rc; | 657 | return rc; |
658 | } | 658 | } |
659 | 659 | ||
660 | void cx25821_buffer_release(struct videobuf_queue *q, | 660 | void cx25821_buffer_release(struct videobuf_queue *q, |
661 | struct videobuf_buffer *vb) | 661 | struct videobuf_buffer *vb) |
662 | { | 662 | { |
663 | struct cx25821_buffer *buf = | 663 | struct cx25821_buffer *buf = |
664 | container_of(vb, struct cx25821_buffer, vb); | 664 | container_of(vb, struct cx25821_buffer, vb); |
665 | 665 | ||
666 | cx25821_free_buffer(q, buf); | 666 | cx25821_free_buffer(q, buf); |
667 | } | 667 | } |
668 | 668 | ||
669 | struct videobuf_queue *get_queue(struct cx25821_fh *fh) | 669 | struct videobuf_queue *get_queue(struct cx25821_fh *fh) |
670 | { | 670 | { |
671 | switch (fh->type) { | 671 | switch (fh->type) { |
672 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 672 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
673 | return &fh->vidq; | 673 | return &fh->vidq; |
674 | default: | 674 | default: |
675 | BUG(); | 675 | BUG(); |
676 | return NULL; | 676 | return NULL; |
677 | } | 677 | } |
678 | } | 678 | } |
679 | 679 | ||
680 | int cx25821_get_resource(struct cx25821_fh *fh, int resource) | 680 | int cx25821_get_resource(struct cx25821_fh *fh, int resource) |
681 | { | 681 | { |
682 | switch (fh->type) { | 682 | switch (fh->type) { |
683 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 683 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
684 | return resource; | 684 | return resource; |
685 | default: | 685 | default: |
686 | BUG(); | 686 | BUG(); |
687 | return 0; | 687 | return 0; |
688 | } | 688 | } |
689 | } | 689 | } |
690 | 690 | ||
691 | int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma) | 691 | int cx25821_video_mmap(struct file *file, struct vm_area_struct *vma) |
692 | { | 692 | { |
693 | struct cx25821_fh *fh = file->private_data; | 693 | struct cx25821_fh *fh = file->private_data; |
694 | 694 | ||
695 | return videobuf_mmap_mapper(get_queue(fh), vma); | 695 | return videobuf_mmap_mapper(get_queue(fh), vma); |
696 | } | 696 | } |
697 | 697 | ||
698 | 698 | ||
699 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) | 699 | static void buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb) |
700 | { | 700 | { |
701 | struct cx25821_buffer *buf = | 701 | struct cx25821_buffer *buf = |
702 | container_of(vb, struct cx25821_buffer, vb); | 702 | container_of(vb, struct cx25821_buffer, vb); |
703 | struct cx25821_buffer *prev; | 703 | struct cx25821_buffer *prev; |
704 | struct cx25821_fh *fh = vq->priv_data; | 704 | struct cx25821_fh *fh = vq->priv_data; |
705 | struct cx25821_dev *dev = fh->dev; | 705 | struct cx25821_dev *dev = fh->dev; |
706 | struct cx25821_dmaqueue *q = &dev->channels[fh->channel_id].vidq; | 706 | struct cx25821_dmaqueue *q = &dev->channels[fh->channel_id].vidq; |
707 | 707 | ||
708 | /* add jump to stopper */ | 708 | /* add jump to stopper */ |
709 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); | 709 | buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC); |
710 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); | 710 | buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma); |
711 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ | 711 | buf->risc.jmp[2] = cpu_to_le32(0); /* bits 63-32 */ |
712 | 712 | ||
713 | dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); | 713 | dprintk(2, "jmp to stopper (0x%x)\n", buf->risc.jmp[1]); |
714 | 714 | ||
715 | if (!list_empty(&q->queued)) { | 715 | if (!list_empty(&q->queued)) { |
716 | list_add_tail(&buf->vb.queue, &q->queued); | 716 | list_add_tail(&buf->vb.queue, &q->queued); |
717 | buf->vb.state = VIDEOBUF_QUEUED; | 717 | buf->vb.state = VIDEOBUF_QUEUED; |
718 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, | 718 | dprintk(2, "[%p/%d] buffer_queue - append to queued\n", buf, |
719 | buf->vb.i); | 719 | buf->vb.i); |
720 | 720 | ||
721 | } else if (list_empty(&q->active)) { | 721 | } else if (list_empty(&q->active)) { |
722 | list_add_tail(&buf->vb.queue, &q->active); | 722 | list_add_tail(&buf->vb.queue, &q->active); |
723 | cx25821_start_video_dma(dev, q, buf, | 723 | cx25821_start_video_dma(dev, q, buf, |
724 | dev->channels[fh->channel_id].sram_channels); | 724 | dev->channels[fh->channel_id].sram_channels); |
725 | buf->vb.state = VIDEOBUF_ACTIVE; | 725 | buf->vb.state = VIDEOBUF_ACTIVE; |
726 | buf->count = q->count++; | 726 | buf->count = q->count++; |
727 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); | 727 | mod_timer(&q->timeout, jiffies + BUFFER_TIMEOUT); |
728 | dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", | 728 | dprintk(2, "[%p/%d] buffer_queue - first active, buf cnt = %d, q->count = %d\n", |
729 | buf, buf->vb.i, buf->count, q->count); | 729 | buf, buf->vb.i, buf->count, q->count); |
730 | } else { | 730 | } else { |
731 | prev = list_entry(q->active.prev, struct cx25821_buffer, | 731 | prev = list_entry(q->active.prev, struct cx25821_buffer, |
732 | vb.queue); | 732 | vb.queue); |
733 | if (prev->vb.width == buf->vb.width | 733 | if (prev->vb.width == buf->vb.width |
734 | && prev->vb.height == buf->vb.height | 734 | && prev->vb.height == buf->vb.height |
735 | && prev->fmt == buf->fmt) { | 735 | && prev->fmt == buf->fmt) { |
736 | list_add_tail(&buf->vb.queue, &q->active); | 736 | list_add_tail(&buf->vb.queue, &q->active); |
737 | buf->vb.state = VIDEOBUF_ACTIVE; | 737 | buf->vb.state = VIDEOBUF_ACTIVE; |
738 | buf->count = q->count++; | 738 | buf->count = q->count++; |
739 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); | 739 | prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma); |
740 | 740 | ||
741 | /* 64 bit bits 63-32 */ | 741 | /* 64 bit bits 63-32 */ |
742 | prev->risc.jmp[2] = cpu_to_le32(0); | 742 | prev->risc.jmp[2] = cpu_to_le32(0); |
743 | dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", | 743 | dprintk(2, "[%p/%d] buffer_queue - append to active, buf->count=%d\n", |
744 | buf, buf->vb.i, buf->count); | 744 | buf, buf->vb.i, buf->count); |
745 | 745 | ||
746 | } else { | 746 | } else { |
747 | list_add_tail(&buf->vb.queue, &q->queued); | 747 | list_add_tail(&buf->vb.queue, &q->queued); |
748 | buf->vb.state = VIDEOBUF_QUEUED; | 748 | buf->vb.state = VIDEOBUF_QUEUED; |
749 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, | 749 | dprintk(2, "[%p/%d] buffer_queue - first queued\n", buf, |
750 | buf->vb.i); | 750 | buf->vb.i); |
751 | } | 751 | } |
752 | } | 752 | } |
753 | 753 | ||
754 | if (list_empty(&q->active)) | 754 | if (list_empty(&q->active)) |
755 | dprintk(2, "active queue empty!\n"); | 755 | dprintk(2, "active queue empty!\n"); |
756 | } | 756 | } |
757 | 757 | ||
758 | static struct videobuf_queue_ops cx25821_video_qops = { | 758 | static struct videobuf_queue_ops cx25821_video_qops = { |
759 | .buf_setup = cx25821_buffer_setup, | 759 | .buf_setup = cx25821_buffer_setup, |
760 | .buf_prepare = cx25821_buffer_prepare, | 760 | .buf_prepare = cx25821_buffer_prepare, |
761 | .buf_queue = buffer_queue, | 761 | .buf_queue = buffer_queue, |
762 | .buf_release = cx25821_buffer_release, | 762 | .buf_release = cx25821_buffer_release, |
763 | }; | 763 | }; |
764 | 764 | ||
765 | static int video_open(struct file *file) | 765 | static int video_open(struct file *file) |
766 | { | 766 | { |
767 | struct video_device *vdev = video_devdata(file); | 767 | struct video_device *vdev = video_devdata(file); |
768 | struct cx25821_dev *h, *dev = video_drvdata(file); | 768 | struct cx25821_dev *h, *dev = video_drvdata(file); |
769 | struct cx25821_fh *fh; | 769 | struct cx25821_fh *fh; |
770 | struct list_head *list; | 770 | struct list_head *list; |
771 | int minor = video_devdata(file)->minor; | 771 | int minor = video_devdata(file)->minor; |
772 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 772 | enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
773 | u32 pix_format; | 773 | u32 pix_format; |
774 | int ch_id = 0; | 774 | int ch_id = 0; |
775 | int i; | 775 | int i; |
776 | 776 | ||
777 | dprintk(1, "open dev=%s type=%s\n", video_device_node_name(vdev), | 777 | dprintk(1, "open dev=%s type=%s\n", video_device_node_name(vdev), |
778 | v4l2_type_names[type]); | 778 | v4l2_type_names[type]); |
779 | 779 | ||
780 | /* allocate + initialize per filehandle data */ | 780 | /* allocate + initialize per filehandle data */ |
781 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); | 781 | fh = kzalloc(sizeof(*fh), GFP_KERNEL); |
782 | if (NULL == fh) | 782 | if (NULL == fh) |
783 | return -ENOMEM; | 783 | return -ENOMEM; |
784 | 784 | ||
785 | mutex_lock(&cx25821_devlist_mutex); | 785 | mutex_lock(&cx25821_devlist_mutex); |
786 | 786 | ||
787 | list_for_each(list, &cx25821_devlist) | 787 | list_for_each(list, &cx25821_devlist) |
788 | { | 788 | { |
789 | h = list_entry(list, struct cx25821_dev, devlist); | 789 | h = list_entry(list, struct cx25821_dev, devlist); |
790 | 790 | ||
791 | for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) { | 791 | for (i = 0; i < MAX_VID_CHANNEL_NUM; i++) { |
792 | if (h->channels[i].video_dev && | 792 | if (h->channels[i].video_dev && |
793 | h->channels[i].video_dev->minor == minor) { | 793 | h->channels[i].video_dev->minor == minor) { |
794 | dev = h; | 794 | dev = h; |
795 | ch_id = i; | 795 | ch_id = i; |
796 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | 796 | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
797 | } | 797 | } |
798 | } | 798 | } |
799 | } | 799 | } |
800 | 800 | ||
801 | if (NULL == dev) { | 801 | if (NULL == dev) { |
802 | mutex_unlock(&cx25821_devlist_mutex); | 802 | mutex_unlock(&cx25821_devlist_mutex); |
803 | kfree(fh); | 803 | kfree(fh); |
804 | return -ENODEV; | 804 | return -ENODEV; |
805 | } | 805 | } |
806 | 806 | ||
807 | file->private_data = fh; | 807 | file->private_data = fh; |
808 | fh->dev = dev; | 808 | fh->dev = dev; |
809 | fh->type = type; | 809 | fh->type = type; |
810 | fh->width = 720; | 810 | fh->width = 720; |
811 | fh->channel_id = ch_id; | 811 | fh->channel_id = ch_id; |
812 | 812 | ||
813 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) | 813 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) |
814 | fh->height = 576; | 814 | fh->height = 576; |
815 | else | 815 | else |
816 | fh->height = 480; | 816 | fh->height = 480; |
817 | 817 | ||
818 | dev->channel_opened = fh->channel_id; | 818 | dev->channel_opened = fh->channel_id; |
819 | if (dev->channels[ch_id].pixel_formats == PIXEL_FRMT_411) | 819 | if (dev->channels[ch_id].pixel_formats == PIXEL_FRMT_411) |
820 | pix_format = V4L2_PIX_FMT_Y41P; | 820 | pix_format = V4L2_PIX_FMT_Y41P; |
821 | else | 821 | else |
822 | pix_format = V4L2_PIX_FMT_YUYV; | 822 | pix_format = V4L2_PIX_FMT_YUYV; |
823 | fh->fmt = cx25821_format_by_fourcc(pix_format); | 823 | fh->fmt = cx25821_format_by_fourcc(pix_format); |
824 | 824 | ||
825 | v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio); | 825 | v4l2_prio_open(&dev->channels[ch_id].prio, &fh->prio); |
826 | 826 | ||
827 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, &dev->pci->dev, | 827 | videobuf_queue_sg_init(&fh->vidq, &cx25821_video_qops, &dev->pci->dev, |
828 | &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, | 828 | &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, |
829 | V4L2_FIELD_INTERLACED, sizeof(struct cx25821_buffer), | 829 | V4L2_FIELD_INTERLACED, sizeof(struct cx25821_buffer), |
830 | fh, NULL); | 830 | fh, NULL); |
831 | 831 | ||
832 | dprintk(1, "post videobuf_queue_init()\n"); | 832 | dprintk(1, "post videobuf_queue_init()\n"); |
833 | mutex_unlock(&cx25821_devlist_mutex); | 833 | mutex_unlock(&cx25821_devlist_mutex); |
834 | 834 | ||
835 | return 0; | 835 | return 0; |
836 | } | 836 | } |
837 | 837 | ||
838 | static ssize_t video_read(struct file *file, char __user * data, size_t count, | 838 | static ssize_t video_read(struct file *file, char __user * data, size_t count, |
839 | loff_t *ppos) | 839 | loff_t *ppos) |
840 | { | 840 | { |
841 | struct cx25821_fh *fh = file->private_data; | 841 | struct cx25821_fh *fh = file->private_data; |
842 | 842 | ||
843 | switch (fh->type) { | 843 | switch (fh->type) { |
844 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: | 844 | case V4L2_BUF_TYPE_VIDEO_CAPTURE: |
845 | if (cx25821_res_locked(fh, RESOURCE_VIDEO0)) | 845 | if (cx25821_res_locked(fh, RESOURCE_VIDEO0)) |
846 | return -EBUSY; | 846 | return -EBUSY; |
847 | 847 | ||
848 | return videobuf_read_one(&fh->vidq, data, count, ppos, | 848 | return videobuf_read_one(&fh->vidq, data, count, ppos, |
849 | file->f_flags & O_NONBLOCK); | 849 | file->f_flags & O_NONBLOCK); |
850 | 850 | ||
851 | default: | 851 | default: |
852 | BUG(); | 852 | BUG(); |
853 | return 0; | 853 | return 0; |
854 | } | 854 | } |
855 | } | 855 | } |
856 | 856 | ||
857 | static unsigned int video_poll(struct file *file, | 857 | static unsigned int video_poll(struct file *file, |
858 | struct poll_table_struct *wait) | 858 | struct poll_table_struct *wait) |
859 | { | 859 | { |
860 | struct cx25821_fh *fh = file->private_data; | 860 | struct cx25821_fh *fh = file->private_data; |
861 | struct cx25821_buffer *buf; | 861 | struct cx25821_buffer *buf; |
862 | 862 | ||
863 | if (cx25821_res_check(fh, RESOURCE_VIDEO0)) { | 863 | if (cx25821_res_check(fh, RESOURCE_VIDEO0)) { |
864 | /* streaming capture */ | 864 | /* streaming capture */ |
865 | if (list_empty(&fh->vidq.stream)) | 865 | if (list_empty(&fh->vidq.stream)) |
866 | return POLLERR; | 866 | return POLLERR; |
867 | buf = list_entry(fh->vidq.stream.next, | 867 | buf = list_entry(fh->vidq.stream.next, |
868 | struct cx25821_buffer, vb.stream); | 868 | struct cx25821_buffer, vb.stream); |
869 | } else { | 869 | } else { |
870 | /* read() capture */ | 870 | /* read() capture */ |
871 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; | 871 | buf = (struct cx25821_buffer *)fh->vidq.read_buf; |
872 | if (NULL == buf) | 872 | if (NULL == buf) |
873 | return POLLERR; | 873 | return POLLERR; |
874 | } | 874 | } |
875 | 875 | ||
876 | poll_wait(file, &buf->vb.done, wait); | 876 | poll_wait(file, &buf->vb.done, wait); |
877 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { | 877 | if (buf->vb.state == VIDEOBUF_DONE || buf->vb.state == VIDEOBUF_ERROR) { |
878 | if (buf->vb.state == VIDEOBUF_DONE) { | 878 | if (buf->vb.state == VIDEOBUF_DONE) { |
879 | struct cx25821_dev *dev = fh->dev; | 879 | struct cx25821_dev *dev = fh->dev; |
880 | 880 | ||
881 | if (dev && dev->channels[fh->channel_id] | 881 | if (dev && dev->channels[fh->channel_id] |
882 | .use_cif_resolution) { | 882 | .use_cif_resolution) { |
883 | u8 cam_id = *((char *)buf->vb.baddr + 3); | 883 | u8 cam_id = *((char *)buf->vb.baddr + 3); |
884 | memcpy((char *)buf->vb.baddr, | 884 | memcpy((char *)buf->vb.baddr, |
885 | (char *)buf->vb.baddr + (fh->width * 2), | 885 | (char *)buf->vb.baddr + (fh->width * 2), |
886 | (fh->width * 2)); | 886 | (fh->width * 2)); |
887 | *((char *)buf->vb.baddr + 3) = cam_id; | 887 | *((char *)buf->vb.baddr + 3) = cam_id; |
888 | } | 888 | } |
889 | } | 889 | } |
890 | 890 | ||
891 | return POLLIN | POLLRDNORM; | 891 | return POLLIN | POLLRDNORM; |
892 | } | 892 | } |
893 | 893 | ||
894 | return 0; | 894 | return 0; |
895 | } | 895 | } |
896 | 896 | ||
897 | static int video_release(struct file *file) | 897 | static int video_release(struct file *file) |
898 | { | 898 | { |
899 | struct cx25821_fh *fh = file->private_data; | 899 | struct cx25821_fh *fh = file->private_data; |
900 | struct cx25821_dev *dev = fh->dev; | 900 | struct cx25821_dev *dev = fh->dev; |
901 | 901 | ||
902 | /* stop the risc engine and fifo */ | 902 | /* stop the risc engine and fifo */ |
903 | cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */ | 903 | cx_write(channel0->dma_ctl, 0); /* FIFO and RISC disable */ |
904 | 904 | ||
905 | /* stop video capture */ | 905 | /* stop video capture */ |
906 | if (cx25821_res_check(fh, RESOURCE_VIDEO0)) { | 906 | if (cx25821_res_check(fh, RESOURCE_VIDEO0)) { |
907 | videobuf_queue_cancel(&fh->vidq); | 907 | videobuf_queue_cancel(&fh->vidq); |
908 | cx25821_res_free(dev, fh, RESOURCE_VIDEO0); | 908 | cx25821_res_free(dev, fh, RESOURCE_VIDEO0); |
909 | } | 909 | } |
910 | 910 | ||
911 | if (fh->vidq.read_buf) { | 911 | if (fh->vidq.read_buf) { |
912 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); | 912 | cx25821_buffer_release(&fh->vidq, fh->vidq.read_buf); |
913 | kfree(fh->vidq.read_buf); | 913 | kfree(fh->vidq.read_buf); |
914 | } | 914 | } |
915 | 915 | ||
916 | videobuf_mmap_free(&fh->vidq); | 916 | videobuf_mmap_free(&fh->vidq); |
917 | 917 | ||
918 | v4l2_prio_close(&dev->channels[fh->channel_id].prio, fh->prio); | 918 | v4l2_prio_close(&dev->channels[fh->channel_id].prio, fh->prio); |
919 | file->private_data = NULL; | 919 | file->private_data = NULL; |
920 | kfree(fh); | 920 | kfree(fh); |
921 | 921 | ||
922 | return 0; | 922 | return 0; |
923 | } | 923 | } |
924 | 924 | ||
925 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) | 925 | static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i) |
926 | { | 926 | { |
927 | struct cx25821_fh *fh = priv; | 927 | struct cx25821_fh *fh = priv; |
928 | struct cx25821_dev *dev = fh->dev; | 928 | struct cx25821_dev *dev = fh->dev; |
929 | 929 | ||
930 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) | 930 | if (unlikely(fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)) |
931 | return -EINVAL; | 931 | return -EINVAL; |
932 | 932 | ||
933 | if (unlikely(i != fh->type)) | 933 | if (unlikely(i != fh->type)) |
934 | return -EINVAL; | 934 | return -EINVAL; |
935 | 935 | ||
936 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, | 936 | if (unlikely(!cx25821_res_get(dev, fh, cx25821_get_resource(fh, |
937 | RESOURCE_VIDEO0)))) | 937 | RESOURCE_VIDEO0)))) |
938 | return -EBUSY; | 938 | return -EBUSY; |
939 | 939 | ||
940 | return videobuf_streamon(get_queue(fh)); | 940 | return videobuf_streamon(get_queue(fh)); |
941 | } | 941 | } |
942 | 942 | ||
943 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) | 943 | static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i) |
944 | { | 944 | { |
945 | struct cx25821_fh *fh = priv; | 945 | struct cx25821_fh *fh = priv; |
946 | struct cx25821_dev *dev = fh->dev; | 946 | struct cx25821_dev *dev = fh->dev; |
947 | int err, res; | 947 | int err, res; |
948 | 948 | ||
949 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 949 | if (fh->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
950 | return -EINVAL; | 950 | return -EINVAL; |
951 | if (i != fh->type) | 951 | if (i != fh->type) |
952 | return -EINVAL; | 952 | return -EINVAL; |
953 | 953 | ||
954 | res = cx25821_get_resource(fh, RESOURCE_VIDEO0); | 954 | res = cx25821_get_resource(fh, RESOURCE_VIDEO0); |
955 | err = videobuf_streamoff(get_queue(fh)); | 955 | err = videobuf_streamoff(get_queue(fh)); |
956 | if (err < 0) | 956 | if (err < 0) |
957 | return err; | 957 | return err; |
958 | cx25821_res_free(dev, fh, res); | 958 | cx25821_res_free(dev, fh, res); |
959 | return 0; | 959 | return 0; |
960 | } | 960 | } |
961 | 961 | ||
962 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, | 962 | static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, |
963 | struct v4l2_format *f) | 963 | struct v4l2_format *f) |
964 | { | 964 | { |
965 | struct cx25821_fh *fh = priv; | 965 | struct cx25821_fh *fh = priv; |
966 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 966 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
967 | struct v4l2_mbus_framefmt mbus_fmt; | 967 | struct v4l2_mbus_framefmt mbus_fmt; |
968 | int err; | 968 | int err; |
969 | int pix_format = PIXEL_FRMT_422; | 969 | int pix_format = PIXEL_FRMT_422; |
970 | 970 | ||
971 | if (fh) { | 971 | if (fh) { |
972 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, | 972 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, |
973 | fh->prio); | 973 | fh->prio); |
974 | if (0 != err) | 974 | if (0 != err) |
975 | return err; | 975 | return err; |
976 | } | 976 | } |
977 | 977 | ||
978 | dprintk(2, "%s()\n", __func__); | 978 | dprintk(2, "%s()\n", __func__); |
979 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); | 979 | err = cx25821_vidioc_try_fmt_vid_cap(file, priv, f); |
980 | 980 | ||
981 | if (0 != err) | 981 | if (0 != err) |
982 | return err; | 982 | return err; |
983 | 983 | ||
984 | fh->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat); | 984 | fh->fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat); |
985 | fh->vidq.field = f->fmt.pix.field; | 985 | fh->vidq.field = f->fmt.pix.field; |
986 | 986 | ||
987 | /* check if width and height is valid based on set standard */ | 987 | /* check if width and height is valid based on set standard */ |
988 | if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) | 988 | if (cx25821_is_valid_width(f->fmt.pix.width, dev->tvnorm)) |
989 | fh->width = f->fmt.pix.width; | 989 | fh->width = f->fmt.pix.width; |
990 | 990 | ||
991 | if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) | 991 | if (cx25821_is_valid_height(f->fmt.pix.height, dev->tvnorm)) |
992 | fh->height = f->fmt.pix.height; | 992 | fh->height = f->fmt.pix.height; |
993 | 993 | ||
994 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) | 994 | if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_Y41P) |
995 | pix_format = PIXEL_FRMT_411; | 995 | pix_format = PIXEL_FRMT_411; |
996 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) | 996 | else if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) |
997 | pix_format = PIXEL_FRMT_422; | 997 | pix_format = PIXEL_FRMT_422; |
998 | else | 998 | else |
999 | return -EINVAL; | 999 | return -EINVAL; |
1000 | 1000 | ||
1001 | cx25821_set_pixel_format(dev, SRAM_CH00, pix_format); | 1001 | cx25821_set_pixel_format(dev, SRAM_CH00, pix_format); |
1002 | 1002 | ||
1003 | /* check if cif resolution */ | 1003 | /* check if cif resolution */ |
1004 | if (fh->width == 320 || fh->width == 352) | 1004 | if (fh->width == 320 || fh->width == 352) |
1005 | dev->channels[fh->channel_id].use_cif_resolution = 1; | 1005 | dev->channels[fh->channel_id].use_cif_resolution = 1; |
1006 | else | 1006 | else |
1007 | dev->channels[fh->channel_id].use_cif_resolution = 0; | 1007 | dev->channels[fh->channel_id].use_cif_resolution = 0; |
1008 | 1008 | ||
1009 | dev->channels[fh->channel_id].cif_width = fh->width; | 1009 | dev->channels[fh->channel_id].cif_width = fh->width; |
1010 | medusa_set_resolution(dev, fh->width, SRAM_CH00); | 1010 | medusa_set_resolution(dev, fh->width, SRAM_CH00); |
1011 | 1011 | ||
1012 | dprintk(2, "%s(): width=%d height=%d field=%d\n", __func__, fh->width, | 1012 | dprintk(2, "%s(): width=%d height=%d field=%d\n", __func__, fh->width, |
1013 | fh->height, fh->vidq.field); | 1013 | fh->height, fh->vidq.field); |
1014 | v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED); | 1014 | v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED); |
1015 | cx25821_call_all(dev, video, s_mbus_fmt, &mbus_fmt); | 1015 | cx25821_call_all(dev, video, s_mbus_fmt, &mbus_fmt); |
1016 | 1016 | ||
1017 | return 0; | 1017 | return 0; |
1018 | } | 1018 | } |
1019 | 1019 | ||
1020 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) | 1020 | static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p) |
1021 | { | 1021 | { |
1022 | int ret_val = 0; | 1022 | int ret_val = 0; |
1023 | struct cx25821_fh *fh = priv; | 1023 | struct cx25821_fh *fh = priv; |
1024 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1024 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1025 | 1025 | ||
1026 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); | 1026 | ret_val = videobuf_dqbuf(get_queue(fh), p, file->f_flags & O_NONBLOCK); |
1027 | 1027 | ||
1028 | p->sequence = dev->channels[fh->channel_id].vidq.count; | 1028 | p->sequence = dev->channels[fh->channel_id].vidq.count; |
1029 | 1029 | ||
1030 | return ret_val; | 1030 | return ret_val; |
1031 | } | 1031 | } |
1032 | 1032 | ||
1033 | static int vidioc_log_status(struct file *file, void *priv) | 1033 | static int vidioc_log_status(struct file *file, void *priv) |
1034 | { | 1034 | { |
1035 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1035 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1036 | struct cx25821_fh *fh = priv; | 1036 | struct cx25821_fh *fh = priv; |
1037 | char name[32 + 2]; | 1037 | char name[32 + 2]; |
1038 | 1038 | ||
1039 | struct sram_channel *sram_ch = dev->channels[fh->channel_id] | 1039 | struct sram_channel *sram_ch = dev->channels[fh->channel_id] |
1040 | .sram_channels; | 1040 | .sram_channels; |
1041 | u32 tmp = 0; | 1041 | u32 tmp = 0; |
1042 | 1042 | ||
1043 | snprintf(name, sizeof(name), "%s/2", dev->name); | 1043 | snprintf(name, sizeof(name), "%s/2", dev->name); |
1044 | pr_info("%s/2: ============ START LOG STATUS ============\n", | 1044 | pr_info("%s/2: ============ START LOG STATUS ============\n", |
1045 | dev->name); | 1045 | dev->name); |
1046 | cx25821_call_all(dev, core, log_status); | 1046 | cx25821_call_all(dev, core, log_status); |
1047 | tmp = cx_read(sram_ch->dma_ctl); | 1047 | tmp = cx_read(sram_ch->dma_ctl); |
1048 | pr_info("Video input 0 is %s\n", | 1048 | pr_info("Video input 0 is %s\n", |
1049 | (tmp & 0x11) ? "streaming" : "stopped"); | 1049 | (tmp & 0x11) ? "streaming" : "stopped"); |
1050 | pr_info("%s/2: ============= END LOG STATUS =============\n", | 1050 | pr_info("%s/2: ============= END LOG STATUS =============\n", |
1051 | dev->name); | 1051 | dev->name); |
1052 | return 0; | 1052 | return 0; |
1053 | } | 1053 | } |
1054 | 1054 | ||
1055 | static int vidioc_s_ctrl(struct file *file, void *priv, | 1055 | static int vidioc_s_ctrl(struct file *file, void *priv, |
1056 | struct v4l2_control *ctl) | 1056 | struct v4l2_control *ctl) |
1057 | { | 1057 | { |
1058 | struct cx25821_fh *fh = priv; | 1058 | struct cx25821_fh *fh = priv; |
1059 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1059 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1060 | int err; | 1060 | int err; |
1061 | 1061 | ||
1062 | if (fh) { | 1062 | if (fh) { |
1063 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, | 1063 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, |
1064 | fh->prio); | 1064 | fh->prio); |
1065 | if (0 != err) | 1065 | if (0 != err) |
1066 | return err; | 1066 | return err; |
1067 | } | 1067 | } |
1068 | 1068 | ||
1069 | return cx25821_set_control(dev, ctl, fh->channel_id); | 1069 | return cx25821_set_control(dev, ctl, fh->channel_id); |
1070 | } | 1070 | } |
1071 | 1071 | ||
1072 | /* VIDEO IOCTLS */ | 1072 | /* VIDEO IOCTLS */ |
1073 | int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv, | 1073 | int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv, |
1074 | struct v4l2_format *f) | 1074 | struct v4l2_format *f) |
1075 | { | 1075 | { |
1076 | struct cx25821_fh *fh = priv; | 1076 | struct cx25821_fh *fh = priv; |
1077 | 1077 | ||
1078 | f->fmt.pix.width = fh->width; | 1078 | f->fmt.pix.width = fh->width; |
1079 | f->fmt.pix.height = fh->height; | 1079 | f->fmt.pix.height = fh->height; |
1080 | f->fmt.pix.field = fh->vidq.field; | 1080 | f->fmt.pix.field = fh->vidq.field; |
1081 | f->fmt.pix.pixelformat = fh->fmt->fourcc; | 1081 | f->fmt.pix.pixelformat = fh->fmt->fourcc; |
1082 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3; | 1082 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fh->fmt->depth) >> 3; |
1083 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 1083 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
1084 | 1084 | ||
1085 | return 0; | 1085 | return 0; |
1086 | } | 1086 | } |
1087 | 1087 | ||
1088 | int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv, | 1088 | int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv, |
1089 | struct v4l2_format *f) | 1089 | struct v4l2_format *f) |
1090 | { | 1090 | { |
1091 | struct cx25821_fmt *fmt; | 1091 | struct cx25821_fmt *fmt; |
1092 | enum v4l2_field field; | 1092 | enum v4l2_field field; |
1093 | unsigned int maxw, maxh; | 1093 | unsigned int maxw, maxh; |
1094 | 1094 | ||
1095 | fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat); | 1095 | fmt = cx25821_format_by_fourcc(f->fmt.pix.pixelformat); |
1096 | if (NULL == fmt) | 1096 | if (NULL == fmt) |
1097 | return -EINVAL; | 1097 | return -EINVAL; |
1098 | 1098 | ||
1099 | field = f->fmt.pix.field; | 1099 | field = f->fmt.pix.field; |
1100 | maxw = 720; | 1100 | maxw = 720; |
1101 | maxh = 576; | 1101 | maxh = 576; |
1102 | 1102 | ||
1103 | if (V4L2_FIELD_ANY == field) { | 1103 | if (V4L2_FIELD_ANY == field) { |
1104 | if (f->fmt.pix.height > maxh / 2) | 1104 | if (f->fmt.pix.height > maxh / 2) |
1105 | field = V4L2_FIELD_INTERLACED; | 1105 | field = V4L2_FIELD_INTERLACED; |
1106 | else | 1106 | else |
1107 | field = V4L2_FIELD_TOP; | 1107 | field = V4L2_FIELD_TOP; |
1108 | } | 1108 | } |
1109 | 1109 | ||
1110 | switch (field) { | 1110 | switch (field) { |
1111 | case V4L2_FIELD_TOP: | 1111 | case V4L2_FIELD_TOP: |
1112 | case V4L2_FIELD_BOTTOM: | 1112 | case V4L2_FIELD_BOTTOM: |
1113 | maxh = maxh / 2; | 1113 | maxh = maxh / 2; |
1114 | break; | 1114 | break; |
1115 | case V4L2_FIELD_INTERLACED: | 1115 | case V4L2_FIELD_INTERLACED: |
1116 | break; | 1116 | break; |
1117 | default: | 1117 | default: |
1118 | return -EINVAL; | 1118 | return -EINVAL; |
1119 | } | 1119 | } |
1120 | 1120 | ||
1121 | f->fmt.pix.field = field; | 1121 | f->fmt.pix.field = field; |
1122 | if (f->fmt.pix.height < 32) | 1122 | if (f->fmt.pix.height < 32) |
1123 | f->fmt.pix.height = 32; | 1123 | f->fmt.pix.height = 32; |
1124 | if (f->fmt.pix.height > maxh) | 1124 | if (f->fmt.pix.height > maxh) |
1125 | f->fmt.pix.height = maxh; | 1125 | f->fmt.pix.height = maxh; |
1126 | if (f->fmt.pix.width < 48) | 1126 | if (f->fmt.pix.width < 48) |
1127 | f->fmt.pix.width = 48; | 1127 | f->fmt.pix.width = 48; |
1128 | if (f->fmt.pix.width > maxw) | 1128 | if (f->fmt.pix.width > maxw) |
1129 | f->fmt.pix.width = maxw; | 1129 | f->fmt.pix.width = maxw; |
1130 | f->fmt.pix.width &= ~0x03; | 1130 | f->fmt.pix.width &= ~0x03; |
1131 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; | 1131 | f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3; |
1132 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; | 1132 | f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline; |
1133 | 1133 | ||
1134 | return 0; | 1134 | return 0; |
1135 | } | 1135 | } |
1136 | 1136 | ||
1137 | int cx25821_vidioc_querycap(struct file *file, void *priv, | 1137 | int cx25821_vidioc_querycap(struct file *file, void *priv, |
1138 | struct v4l2_capability *cap) | 1138 | struct v4l2_capability *cap) |
1139 | { | 1139 | { |
1140 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1140 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1141 | 1141 | ||
1142 | strcpy(cap->driver, "cx25821"); | 1142 | strcpy(cap->driver, "cx25821"); |
1143 | strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); | 1143 | strlcpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); |
1144 | sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); | 1144 | sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); |
1145 | cap->version = CX25821_VERSION_CODE; | 1145 | cap->version = CX25821_VERSION_CODE; |
1146 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | | 1146 | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | |
1147 | V4L2_CAP_STREAMING; | 1147 | V4L2_CAP_STREAMING; |
1148 | if (UNSET != dev->tuner_type) | 1148 | if (UNSET != dev->tuner_type) |
1149 | cap->capabilities |= V4L2_CAP_TUNER; | 1149 | cap->capabilities |= V4L2_CAP_TUNER; |
1150 | return 0; | 1150 | return 0; |
1151 | } | 1151 | } |
1152 | 1152 | ||
1153 | int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv, | 1153 | int cx25821_vidioc_enum_fmt_vid_cap(struct file *file, void *priv, |
1154 | struct v4l2_fmtdesc *f) | 1154 | struct v4l2_fmtdesc *f) |
1155 | { | 1155 | { |
1156 | if (unlikely(f->index >= ARRAY_SIZE(formats))) | 1156 | if (unlikely(f->index >= ARRAY_SIZE(formats))) |
1157 | return -EINVAL; | 1157 | return -EINVAL; |
1158 | 1158 | ||
1159 | strlcpy(f->description, formats[f->index].name, sizeof(f->description)); | 1159 | strlcpy(f->description, formats[f->index].name, sizeof(f->description)); |
1160 | f->pixelformat = formats[f->index].fourcc; | 1160 | f->pixelformat = formats[f->index].fourcc; |
1161 | 1161 | ||
1162 | return 0; | 1162 | return 0; |
1163 | } | 1163 | } |
1164 | 1164 | ||
1165 | int cx25821_vidioc_reqbufs(struct file *file, void *priv, | 1165 | int cx25821_vidioc_reqbufs(struct file *file, void *priv, |
1166 | struct v4l2_requestbuffers *p) | 1166 | struct v4l2_requestbuffers *p) |
1167 | { | 1167 | { |
1168 | struct cx25821_fh *fh = priv; | 1168 | struct cx25821_fh *fh = priv; |
1169 | return videobuf_reqbufs(get_queue(fh), p); | 1169 | return videobuf_reqbufs(get_queue(fh), p); |
1170 | } | 1170 | } |
1171 | 1171 | ||
1172 | int cx25821_vidioc_querybuf(struct file *file, void *priv, | 1172 | int cx25821_vidioc_querybuf(struct file *file, void *priv, |
1173 | struct v4l2_buffer *p) | 1173 | struct v4l2_buffer *p) |
1174 | { | 1174 | { |
1175 | struct cx25821_fh *fh = priv; | 1175 | struct cx25821_fh *fh = priv; |
1176 | return videobuf_querybuf(get_queue(fh), p); | 1176 | return videobuf_querybuf(get_queue(fh), p); |
1177 | } | 1177 | } |
1178 | 1178 | ||
1179 | int cx25821_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) | 1179 | int cx25821_vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p) |
1180 | { | 1180 | { |
1181 | struct cx25821_fh *fh = priv; | 1181 | struct cx25821_fh *fh = priv; |
1182 | return videobuf_qbuf(get_queue(fh), p); | 1182 | return videobuf_qbuf(get_queue(fh), p); |
1183 | } | 1183 | } |
1184 | 1184 | ||
1185 | int cx25821_vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p) | 1185 | int cx25821_vidioc_g_priority(struct file *file, void *f, enum v4l2_priority *p) |
1186 | { | 1186 | { |
1187 | struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; | 1187 | struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; |
1188 | struct cx25821_fh *fh = f; | 1188 | struct cx25821_fh *fh = f; |
1189 | 1189 | ||
1190 | *p = v4l2_prio_max(&dev->channels[fh->channel_id].prio); | 1190 | *p = v4l2_prio_max(&dev->channels[fh->channel_id].prio); |
1191 | 1191 | ||
1192 | return 0; | 1192 | return 0; |
1193 | } | 1193 | } |
1194 | 1194 | ||
1195 | int cx25821_vidioc_s_priority(struct file *file, void *f, | 1195 | int cx25821_vidioc_s_priority(struct file *file, void *f, |
1196 | enum v4l2_priority prio) | 1196 | enum v4l2_priority prio) |
1197 | { | 1197 | { |
1198 | struct cx25821_fh *fh = f; | 1198 | struct cx25821_fh *fh = f; |
1199 | struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; | 1199 | struct cx25821_dev *dev = ((struct cx25821_fh *)f)->dev; |
1200 | 1200 | ||
1201 | return v4l2_prio_change(&dev->channels[fh->channel_id].prio, &fh->prio, | 1201 | return v4l2_prio_change(&dev->channels[fh->channel_id].prio, &fh->prio, |
1202 | prio); | 1202 | prio); |
1203 | } | 1203 | } |
1204 | 1204 | ||
1205 | #ifdef TUNER_FLAG | 1205 | #ifdef TUNER_FLAG |
1206 | int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms) | 1206 | int cx25821_vidioc_s_std(struct file *file, void *priv, v4l2_std_id * tvnorms) |
1207 | { | 1207 | { |
1208 | struct cx25821_fh *fh = priv; | 1208 | struct cx25821_fh *fh = priv; |
1209 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1209 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1210 | int err; | 1210 | int err; |
1211 | 1211 | ||
1212 | dprintk(1, "%s()\n", __func__); | 1212 | dprintk(1, "%s()\n", __func__); |
1213 | 1213 | ||
1214 | if (fh) { | 1214 | if (fh) { |
1215 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, | 1215 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, |
1216 | fh->prio); | 1216 | fh->prio); |
1217 | if (0 != err) | 1217 | if (0 != err) |
1218 | return err; | 1218 | return err; |
1219 | } | 1219 | } |
1220 | 1220 | ||
1221 | if (dev->tvnorm == *tvnorms) | 1221 | if (dev->tvnorm == *tvnorms) |
1222 | return 0; | 1222 | return 0; |
1223 | 1223 | ||
1224 | mutex_lock(&dev->lock); | 1224 | mutex_lock(&dev->lock); |
1225 | cx25821_set_tvnorm(dev, *tvnorms); | 1225 | cx25821_set_tvnorm(dev, *tvnorms); |
1226 | mutex_unlock(&dev->lock); | 1226 | mutex_unlock(&dev->lock); |
1227 | 1227 | ||
1228 | medusa_set_videostandard(dev); | 1228 | medusa_set_videostandard(dev); |
1229 | 1229 | ||
1230 | return 0; | 1230 | return 0; |
1231 | } | 1231 | } |
1232 | #endif | 1232 | #endif |
1233 | 1233 | ||
1234 | int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i) | 1234 | int cx25821_enum_input(struct cx25821_dev *dev, struct v4l2_input *i) |
1235 | { | 1235 | { |
1236 | static const char * const iname[] = { | 1236 | static const char * const iname[] = { |
1237 | [CX25821_VMUX_COMPOSITE] = "Composite", | 1237 | [CX25821_VMUX_COMPOSITE] = "Composite", |
1238 | [CX25821_VMUX_SVIDEO] = "S-Video", | 1238 | [CX25821_VMUX_SVIDEO] = "S-Video", |
1239 | [CX25821_VMUX_DEBUG] = "for debug only", | 1239 | [CX25821_VMUX_DEBUG] = "for debug only", |
1240 | }; | 1240 | }; |
1241 | unsigned int n; | 1241 | unsigned int n; |
1242 | dprintk(1, "%s()\n", __func__); | 1242 | dprintk(1, "%s()\n", __func__); |
1243 | 1243 | ||
1244 | n = i->index; | 1244 | n = i->index; |
1245 | if (n >= 2) | 1245 | if (n >= 2) |
1246 | return -EINVAL; | 1246 | return -EINVAL; |
1247 | 1247 | ||
1248 | if (0 == INPUT(n)->type) | 1248 | if (0 == INPUT(n)->type) |
1249 | return -EINVAL; | 1249 | return -EINVAL; |
1250 | 1250 | ||
1251 | i->type = V4L2_INPUT_TYPE_CAMERA; | 1251 | i->type = V4L2_INPUT_TYPE_CAMERA; |
1252 | strcpy(i->name, iname[INPUT(n)->type]); | 1252 | strcpy(i->name, iname[INPUT(n)->type]); |
1253 | 1253 | ||
1254 | i->std = CX25821_NORMS; | 1254 | i->std = CX25821_NORMS; |
1255 | return 0; | 1255 | return 0; |
1256 | } | 1256 | } |
1257 | 1257 | ||
1258 | int cx25821_vidioc_enum_input(struct file *file, void *priv, | 1258 | int cx25821_vidioc_enum_input(struct file *file, void *priv, |
1259 | struct v4l2_input *i) | 1259 | struct v4l2_input *i) |
1260 | { | 1260 | { |
1261 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1261 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1262 | dprintk(1, "%s()\n", __func__); | 1262 | dprintk(1, "%s()\n", __func__); |
1263 | return cx25821_enum_input(dev, i); | 1263 | return cx25821_enum_input(dev, i); |
1264 | } | 1264 | } |
1265 | 1265 | ||
1266 | int cx25821_vidioc_g_input(struct file *file, void *priv, unsigned int *i) | 1266 | int cx25821_vidioc_g_input(struct file *file, void *priv, unsigned int *i) |
1267 | { | 1267 | { |
1268 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1268 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1269 | 1269 | ||
1270 | *i = dev->input; | 1270 | *i = dev->input; |
1271 | dprintk(1, "%s(): returns %d\n", __func__, *i); | 1271 | dprintk(1, "%s(): returns %d\n", __func__, *i); |
1272 | return 0; | 1272 | return 0; |
1273 | } | 1273 | } |
1274 | 1274 | ||
1275 | int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i) | 1275 | int cx25821_vidioc_s_input(struct file *file, void *priv, unsigned int i) |
1276 | { | 1276 | { |
1277 | struct cx25821_fh *fh = priv; | 1277 | struct cx25821_fh *fh = priv; |
1278 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1278 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1279 | int err; | 1279 | int err; |
1280 | 1280 | ||
1281 | dprintk(1, "%s(%d)\n", __func__, i); | 1281 | dprintk(1, "%s(%d)\n", __func__, i); |
1282 | 1282 | ||
1283 | if (fh) { | 1283 | if (fh) { |
1284 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, | 1284 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, |
1285 | fh->prio); | 1285 | fh->prio); |
1286 | if (0 != err) | 1286 | if (0 != err) |
1287 | return err; | 1287 | return err; |
1288 | } | 1288 | } |
1289 | 1289 | ||
1290 | if (i >= CX25821_NR_INPUT) { | 1290 | if (i >= CX25821_NR_INPUT) { |
1291 | dprintk(1, "%s(): -EINVAL\n", __func__); | 1291 | dprintk(1, "%s(): -EINVAL\n", __func__); |
1292 | return -EINVAL; | 1292 | return -EINVAL; |
1293 | } | 1293 | } |
1294 | 1294 | ||
1295 | mutex_lock(&dev->lock); | 1295 | mutex_lock(&dev->lock); |
1296 | cx25821_video_mux(dev, i); | 1296 | cx25821_video_mux(dev, i); |
1297 | mutex_unlock(&dev->lock); | 1297 | mutex_unlock(&dev->lock); |
1298 | return 0; | 1298 | return 0; |
1299 | } | 1299 | } |
1300 | 1300 | ||
1301 | #ifdef TUNER_FLAG | 1301 | #ifdef TUNER_FLAG |
1302 | int cx25821_vidioc_g_frequency(struct file *file, void *priv, | 1302 | int cx25821_vidioc_g_frequency(struct file *file, void *priv, |
1303 | struct v4l2_frequency *f) | 1303 | struct v4l2_frequency *f) |
1304 | { | 1304 | { |
1305 | struct cx25821_fh *fh = priv; | 1305 | struct cx25821_fh *fh = priv; |
1306 | struct cx25821_dev *dev = fh->dev; | 1306 | struct cx25821_dev *dev = fh->dev; |
1307 | 1307 | ||
1308 | f->frequency = dev->freq; | 1308 | f->frequency = dev->freq; |
1309 | 1309 | ||
1310 | cx25821_call_all(dev, tuner, g_frequency, f); | 1310 | cx25821_call_all(dev, tuner, g_frequency, f); |
1311 | 1311 | ||
1312 | return 0; | 1312 | return 0; |
1313 | } | 1313 | } |
1314 | 1314 | ||
1315 | int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f) | 1315 | int cx25821_set_freq(struct cx25821_dev *dev, struct v4l2_frequency *f) |
1316 | { | 1316 | { |
1317 | mutex_lock(&dev->lock); | 1317 | mutex_lock(&dev->lock); |
1318 | dev->freq = f->frequency; | 1318 | dev->freq = f->frequency; |
1319 | 1319 | ||
1320 | cx25821_call_all(dev, tuner, s_frequency, f); | 1320 | cx25821_call_all(dev, tuner, s_frequency, f); |
1321 | 1321 | ||
1322 | /* When changing channels it is required to reset TVAUDIO */ | 1322 | /* When changing channels it is required to reset TVAUDIO */ |
1323 | msleep(10); | 1323 | msleep(10); |
1324 | 1324 | ||
1325 | mutex_unlock(&dev->lock); | 1325 | mutex_unlock(&dev->lock); |
1326 | 1326 | ||
1327 | return 0; | 1327 | return 0; |
1328 | } | 1328 | } |
1329 | 1329 | ||
1330 | int cx25821_vidioc_s_frequency(struct file *file, void *priv, | 1330 | int cx25821_vidioc_s_frequency(struct file *file, void *priv, |
1331 | struct v4l2_frequency *f) | 1331 | struct v4l2_frequency *f) |
1332 | { | 1332 | { |
1333 | struct cx25821_fh *fh = priv; | 1333 | struct cx25821_fh *fh = priv; |
1334 | struct cx25821_dev *dev; | 1334 | struct cx25821_dev *dev; |
1335 | int err; | 1335 | int err; |
1336 | 1336 | ||
1337 | if (fh) { | 1337 | if (fh) { |
1338 | dev = fh->dev; | 1338 | dev = fh->dev; |
1339 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, | 1339 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, |
1340 | fh->prio); | 1340 | fh->prio); |
1341 | if (0 != err) | 1341 | if (0 != err) |
1342 | return err; | 1342 | return err; |
1343 | } else { | 1343 | } else { |
1344 | pr_err("Invalid fh pointer!\n"); | 1344 | pr_err("Invalid fh pointer!\n"); |
1345 | return -EINVAL; | 1345 | return -EINVAL; |
1346 | } | 1346 | } |
1347 | 1347 | ||
1348 | return cx25821_set_freq(dev, f); | 1348 | return cx25821_set_freq(dev, f); |
1349 | } | 1349 | } |
1350 | #endif | 1350 | #endif |
1351 | 1351 | ||
1352 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1352 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1353 | int cx25821_vidioc_g_register(struct file *file, void *fh, | 1353 | int cx25821_vidioc_g_register(struct file *file, void *fh, |
1354 | struct v4l2_dbg_register *reg) | 1354 | struct v4l2_dbg_register *reg) |
1355 | { | 1355 | { |
1356 | struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; | 1356 | struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; |
1357 | 1357 | ||
1358 | if (!v4l2_chip_match_host(®->match)) | 1358 | if (!v4l2_chip_match_host(®->match)) |
1359 | return -EINVAL; | 1359 | return -EINVAL; |
1360 | 1360 | ||
1361 | cx25821_call_all(dev, core, g_register, reg); | 1361 | cx25821_call_all(dev, core, g_register, reg); |
1362 | 1362 | ||
1363 | return 0; | 1363 | return 0; |
1364 | } | 1364 | } |
1365 | 1365 | ||
1366 | int cx25821_vidioc_s_register(struct file *file, void *fh, | 1366 | int cx25821_vidioc_s_register(struct file *file, void *fh, |
1367 | struct v4l2_dbg_register *reg) | 1367 | struct v4l2_dbg_register *reg) |
1368 | { | 1368 | { |
1369 | struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; | 1369 | struct cx25821_dev *dev = ((struct cx25821_fh *)fh)->dev; |
1370 | 1370 | ||
1371 | if (!v4l2_chip_match_host(®->match)) | 1371 | if (!v4l2_chip_match_host(®->match)) |
1372 | return -EINVAL; | 1372 | return -EINVAL; |
1373 | 1373 | ||
1374 | cx25821_call_all(dev, core, s_register, reg); | 1374 | cx25821_call_all(dev, core, s_register, reg); |
1375 | 1375 | ||
1376 | return 0; | 1376 | return 0; |
1377 | } | 1377 | } |
1378 | 1378 | ||
1379 | #endif | 1379 | #endif |
1380 | 1380 | ||
1381 | #ifdef TUNER_FLAG | 1381 | #ifdef TUNER_FLAG |
1382 | int cx25821_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) | 1382 | int cx25821_vidioc_g_tuner(struct file *file, void *priv, struct v4l2_tuner *t) |
1383 | { | 1383 | { |
1384 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1384 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1385 | 1385 | ||
1386 | if (unlikely(UNSET == dev->tuner_type)) | 1386 | if (unlikely(UNSET == dev->tuner_type)) |
1387 | return -EINVAL; | 1387 | return -EINVAL; |
1388 | if (0 != t->index) | 1388 | if (0 != t->index) |
1389 | return -EINVAL; | 1389 | return -EINVAL; |
1390 | 1390 | ||
1391 | strcpy(t->name, "Television"); | 1391 | strcpy(t->name, "Television"); |
1392 | t->type = V4L2_TUNER_ANALOG_TV; | 1392 | t->type = V4L2_TUNER_ANALOG_TV; |
1393 | t->capability = V4L2_TUNER_CAP_NORM; | 1393 | t->capability = V4L2_TUNER_CAP_NORM; |
1394 | t->rangehigh = 0xffffffffUL; | 1394 | t->rangehigh = 0xffffffffUL; |
1395 | 1395 | ||
1396 | t->signal = 0xffff; /* LOCKED */ | 1396 | t->signal = 0xffff; /* LOCKED */ |
1397 | return 0; | 1397 | return 0; |
1398 | } | 1398 | } |
1399 | 1399 | ||
1400 | int cx25821_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) | 1400 | int cx25821_vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t) |
1401 | { | 1401 | { |
1402 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1402 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1403 | struct cx25821_fh *fh = priv; | 1403 | struct cx25821_fh *fh = priv; |
1404 | int err; | 1404 | int err; |
1405 | 1405 | ||
1406 | if (fh) { | 1406 | if (fh) { |
1407 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, | 1407 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, |
1408 | fh->prio); | 1408 | fh->prio); |
1409 | if (0 != err) | 1409 | if (0 != err) |
1410 | return err; | 1410 | return err; |
1411 | } | 1411 | } |
1412 | 1412 | ||
1413 | dprintk(1, "%s()\n", __func__); | 1413 | dprintk(1, "%s()\n", __func__); |
1414 | if (UNSET == dev->tuner_type) | 1414 | if (UNSET == dev->tuner_type) |
1415 | return -EINVAL; | 1415 | return -EINVAL; |
1416 | if (0 != t->index) | 1416 | if (0 != t->index) |
1417 | return -EINVAL; | 1417 | return -EINVAL; |
1418 | 1418 | ||
1419 | return 0; | 1419 | return 0; |
1420 | } | 1420 | } |
1421 | 1421 | ||
1422 | #endif | 1422 | #endif |
1423 | /*****************************************************************************/ | 1423 | /*****************************************************************************/ |
1424 | static const struct v4l2_queryctrl no_ctl = { | 1424 | static const struct v4l2_queryctrl no_ctl = { |
1425 | .name = "42", | 1425 | .name = "42", |
1426 | .flags = V4L2_CTRL_FLAG_DISABLED, | 1426 | .flags = V4L2_CTRL_FLAG_DISABLED, |
1427 | }; | 1427 | }; |
1428 | 1428 | ||
1429 | static struct v4l2_queryctrl cx25821_ctls[] = { | 1429 | static struct v4l2_queryctrl cx25821_ctls[] = { |
1430 | /* --- video --- */ | 1430 | /* --- video --- */ |
1431 | { | 1431 | { |
1432 | .id = V4L2_CID_BRIGHTNESS, | 1432 | .id = V4L2_CID_BRIGHTNESS, |
1433 | .name = "Brightness", | 1433 | .name = "Brightness", |
1434 | .minimum = 0, | 1434 | .minimum = 0, |
1435 | .maximum = 10000, | 1435 | .maximum = 10000, |
1436 | .step = 1, | 1436 | .step = 1, |
1437 | .default_value = 6200, | 1437 | .default_value = 6200, |
1438 | .type = V4L2_CTRL_TYPE_INTEGER, | 1438 | .type = V4L2_CTRL_TYPE_INTEGER, |
1439 | }, { | 1439 | }, { |
1440 | .id = V4L2_CID_CONTRAST, | 1440 | .id = V4L2_CID_CONTRAST, |
1441 | .name = "Contrast", | 1441 | .name = "Contrast", |
1442 | .minimum = 0, | 1442 | .minimum = 0, |
1443 | .maximum = 10000, | 1443 | .maximum = 10000, |
1444 | .step = 1, | 1444 | .step = 1, |
1445 | .default_value = 5000, | 1445 | .default_value = 5000, |
1446 | .type = V4L2_CTRL_TYPE_INTEGER, | 1446 | .type = V4L2_CTRL_TYPE_INTEGER, |
1447 | }, { | 1447 | }, { |
1448 | .id = V4L2_CID_SATURATION, | 1448 | .id = V4L2_CID_SATURATION, |
1449 | .name = "Saturation", | 1449 | .name = "Saturation", |
1450 | .minimum = 0, | 1450 | .minimum = 0, |
1451 | .maximum = 10000, | 1451 | .maximum = 10000, |
1452 | .step = 1, | 1452 | .step = 1, |
1453 | .default_value = 5000, | 1453 | .default_value = 5000, |
1454 | .type = V4L2_CTRL_TYPE_INTEGER, | 1454 | .type = V4L2_CTRL_TYPE_INTEGER, |
1455 | }, { | 1455 | }, { |
1456 | .id = V4L2_CID_HUE, | 1456 | .id = V4L2_CID_HUE, |
1457 | .name = "Hue", | 1457 | .name = "Hue", |
1458 | .minimum = 0, | 1458 | .minimum = 0, |
1459 | .maximum = 10000, | 1459 | .maximum = 10000, |
1460 | .step = 1, | 1460 | .step = 1, |
1461 | .default_value = 5000, | 1461 | .default_value = 5000, |
1462 | .type = V4L2_CTRL_TYPE_INTEGER, | 1462 | .type = V4L2_CTRL_TYPE_INTEGER, |
1463 | } | 1463 | } |
1464 | }; | 1464 | }; |
1465 | static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls); | 1465 | static const int CX25821_CTLS = ARRAY_SIZE(cx25821_ctls); |
1466 | 1466 | ||
1467 | static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) | 1467 | static int cx25821_ctrl_query(struct v4l2_queryctrl *qctrl) |
1468 | { | 1468 | { |
1469 | int i; | 1469 | int i; |
1470 | 1470 | ||
1471 | if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1) | 1471 | if (qctrl->id < V4L2_CID_BASE || qctrl->id >= V4L2_CID_LASTP1) |
1472 | return -EINVAL; | 1472 | return -EINVAL; |
1473 | for (i = 0; i < CX25821_CTLS; i++) | 1473 | for (i = 0; i < CX25821_CTLS; i++) |
1474 | if (cx25821_ctls[i].id == qctrl->id) | 1474 | if (cx25821_ctls[i].id == qctrl->id) |
1475 | break; | 1475 | break; |
1476 | if (i == CX25821_CTLS) { | 1476 | if (i == CX25821_CTLS) { |
1477 | *qctrl = no_ctl; | 1477 | *qctrl = no_ctl; |
1478 | return 0; | 1478 | return 0; |
1479 | } | 1479 | } |
1480 | *qctrl = cx25821_ctls[i]; | 1480 | *qctrl = cx25821_ctls[i]; |
1481 | return 0; | 1481 | return 0; |
1482 | } | 1482 | } |
1483 | 1483 | ||
1484 | int cx25821_vidioc_queryctrl(struct file *file, void *priv, | 1484 | int cx25821_vidioc_queryctrl(struct file *file, void *priv, |
1485 | struct v4l2_queryctrl *qctrl) | 1485 | struct v4l2_queryctrl *qctrl) |
1486 | { | 1486 | { |
1487 | return cx25821_ctrl_query(qctrl); | 1487 | return cx25821_ctrl_query(qctrl); |
1488 | } | 1488 | } |
1489 | 1489 | ||
1490 | /* ------------------------------------------------------------------ */ | 1490 | /* ------------------------------------------------------------------ */ |
1491 | /* VIDEO CTRL IOCTLS */ | 1491 | /* VIDEO CTRL IOCTLS */ |
1492 | 1492 | ||
1493 | static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id) | 1493 | static const struct v4l2_queryctrl *ctrl_by_id(unsigned int id) |
1494 | { | 1494 | { |
1495 | unsigned int i; | 1495 | unsigned int i; |
1496 | 1496 | ||
1497 | for (i = 0; i < CX25821_CTLS; i++) | 1497 | for (i = 0; i < CX25821_CTLS; i++) |
1498 | if (cx25821_ctls[i].id == id) | 1498 | if (cx25821_ctls[i].id == id) |
1499 | return cx25821_ctls + i; | 1499 | return cx25821_ctls + i; |
1500 | return NULL; | 1500 | return NULL; |
1501 | } | 1501 | } |
1502 | 1502 | ||
1503 | int cx25821_vidioc_g_ctrl(struct file *file, void *priv, | 1503 | int cx25821_vidioc_g_ctrl(struct file *file, void *priv, |
1504 | struct v4l2_control *ctl) | 1504 | struct v4l2_control *ctl) |
1505 | { | 1505 | { |
1506 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1506 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1507 | struct cx25821_fh *fh = priv; | 1507 | struct cx25821_fh *fh = priv; |
1508 | 1508 | ||
1509 | const struct v4l2_queryctrl *ctrl; | 1509 | const struct v4l2_queryctrl *ctrl; |
1510 | 1510 | ||
1511 | ctrl = ctrl_by_id(ctl->id); | 1511 | ctrl = ctrl_by_id(ctl->id); |
1512 | 1512 | ||
1513 | if (NULL == ctrl) | 1513 | if (NULL == ctrl) |
1514 | return -EINVAL; | 1514 | return -EINVAL; |
1515 | switch (ctl->id) { | 1515 | switch (ctl->id) { |
1516 | case V4L2_CID_BRIGHTNESS: | 1516 | case V4L2_CID_BRIGHTNESS: |
1517 | ctl->value = dev->channels[fh->channel_id].ctl_bright; | 1517 | ctl->value = dev->channels[fh->channel_id].ctl_bright; |
1518 | break; | 1518 | break; |
1519 | case V4L2_CID_HUE: | 1519 | case V4L2_CID_HUE: |
1520 | ctl->value = dev->channels[fh->channel_id].ctl_hue; | 1520 | ctl->value = dev->channels[fh->channel_id].ctl_hue; |
1521 | break; | 1521 | break; |
1522 | case V4L2_CID_CONTRAST: | 1522 | case V4L2_CID_CONTRAST: |
1523 | ctl->value = dev->channels[fh->channel_id].ctl_contrast; | 1523 | ctl->value = dev->channels[fh->channel_id].ctl_contrast; |
1524 | break; | 1524 | break; |
1525 | case V4L2_CID_SATURATION: | 1525 | case V4L2_CID_SATURATION: |
1526 | ctl->value = dev->channels[fh->channel_id].ctl_saturation; | 1526 | ctl->value = dev->channels[fh->channel_id].ctl_saturation; |
1527 | break; | 1527 | break; |
1528 | } | 1528 | } |
1529 | return 0; | 1529 | return 0; |
1530 | } | 1530 | } |
1531 | 1531 | ||
1532 | int cx25821_set_control(struct cx25821_dev *dev, | 1532 | int cx25821_set_control(struct cx25821_dev *dev, |
1533 | struct v4l2_control *ctl, int chan_num) | 1533 | struct v4l2_control *ctl, int chan_num) |
1534 | { | 1534 | { |
1535 | int err; | 1535 | int err; |
1536 | const struct v4l2_queryctrl *ctrl; | 1536 | const struct v4l2_queryctrl *ctrl; |
1537 | 1537 | ||
1538 | err = -EINVAL; | 1538 | err = -EINVAL; |
1539 | 1539 | ||
1540 | ctrl = ctrl_by_id(ctl->id); | 1540 | ctrl = ctrl_by_id(ctl->id); |
1541 | 1541 | ||
1542 | if (NULL == ctrl) | 1542 | if (NULL == ctrl) |
1543 | return err; | 1543 | return err; |
1544 | 1544 | ||
1545 | switch (ctrl->type) { | 1545 | switch (ctrl->type) { |
1546 | case V4L2_CTRL_TYPE_BOOLEAN: | 1546 | case V4L2_CTRL_TYPE_BOOLEAN: |
1547 | case V4L2_CTRL_TYPE_MENU: | 1547 | case V4L2_CTRL_TYPE_MENU: |
1548 | case V4L2_CTRL_TYPE_INTEGER: | 1548 | case V4L2_CTRL_TYPE_INTEGER: |
1549 | if (ctl->value < ctrl->minimum) | 1549 | if (ctl->value < ctrl->minimum) |
1550 | ctl->value = ctrl->minimum; | 1550 | ctl->value = ctrl->minimum; |
1551 | if (ctl->value > ctrl->maximum) | 1551 | if (ctl->value > ctrl->maximum) |
1552 | ctl->value = ctrl->maximum; | 1552 | ctl->value = ctrl->maximum; |
1553 | break; | 1553 | break; |
1554 | default: | 1554 | default: |
1555 | /* nothing */ ; | 1555 | /* nothing */ ; |
1556 | } | 1556 | } |
1557 | 1557 | ||
1558 | switch (ctl->id) { | 1558 | switch (ctl->id) { |
1559 | case V4L2_CID_BRIGHTNESS: | 1559 | case V4L2_CID_BRIGHTNESS: |
1560 | dev->channels[chan_num].ctl_bright = ctl->value; | 1560 | dev->channels[chan_num].ctl_bright = ctl->value; |
1561 | medusa_set_brightness(dev, ctl->value, chan_num); | 1561 | medusa_set_brightness(dev, ctl->value, chan_num); |
1562 | break; | 1562 | break; |
1563 | case V4L2_CID_HUE: | 1563 | case V4L2_CID_HUE: |
1564 | dev->channels[chan_num].ctl_hue = ctl->value; | 1564 | dev->channels[chan_num].ctl_hue = ctl->value; |
1565 | medusa_set_hue(dev, ctl->value, chan_num); | 1565 | medusa_set_hue(dev, ctl->value, chan_num); |
1566 | break; | 1566 | break; |
1567 | case V4L2_CID_CONTRAST: | 1567 | case V4L2_CID_CONTRAST: |
1568 | dev->channels[chan_num].ctl_contrast = ctl->value; | 1568 | dev->channels[chan_num].ctl_contrast = ctl->value; |
1569 | medusa_set_contrast(dev, ctl->value, chan_num); | 1569 | medusa_set_contrast(dev, ctl->value, chan_num); |
1570 | break; | 1570 | break; |
1571 | case V4L2_CID_SATURATION: | 1571 | case V4L2_CID_SATURATION: |
1572 | dev->channels[chan_num].ctl_saturation = ctl->value; | 1572 | dev->channels[chan_num].ctl_saturation = ctl->value; |
1573 | medusa_set_saturation(dev, ctl->value, chan_num); | 1573 | medusa_set_saturation(dev, ctl->value, chan_num); |
1574 | break; | 1574 | break; |
1575 | } | 1575 | } |
1576 | 1576 | ||
1577 | err = 0; | 1577 | err = 0; |
1578 | 1578 | ||
1579 | return err; | 1579 | return err; |
1580 | } | 1580 | } |
1581 | 1581 | ||
1582 | static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num) | 1582 | static void cx25821_init_controls(struct cx25821_dev *dev, int chan_num) |
1583 | { | 1583 | { |
1584 | struct v4l2_control ctrl; | 1584 | struct v4l2_control ctrl; |
1585 | int i; | 1585 | int i; |
1586 | for (i = 0; i < CX25821_CTLS; i++) { | 1586 | for (i = 0; i < CX25821_CTLS; i++) { |
1587 | ctrl.id = cx25821_ctls[i].id; | 1587 | ctrl.id = cx25821_ctls[i].id; |
1588 | ctrl.value = cx25821_ctls[i].default_value; | 1588 | ctrl.value = cx25821_ctls[i].default_value; |
1589 | 1589 | ||
1590 | cx25821_set_control(dev, &ctrl, chan_num); | 1590 | cx25821_set_control(dev, &ctrl, chan_num); |
1591 | } | 1591 | } |
1592 | } | 1592 | } |
1593 | 1593 | ||
1594 | int cx25821_vidioc_cropcap(struct file *file, void *priv, | 1594 | int cx25821_vidioc_cropcap(struct file *file, void *priv, |
1595 | struct v4l2_cropcap *cropcap) | 1595 | struct v4l2_cropcap *cropcap) |
1596 | { | 1596 | { |
1597 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1597 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1598 | 1598 | ||
1599 | if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 1599 | if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
1600 | return -EINVAL; | 1600 | return -EINVAL; |
1601 | cropcap->bounds.top = 0; | 1601 | cropcap->bounds.top = 0; |
1602 | cropcap->bounds.left = 0; | 1602 | cropcap->bounds.left = 0; |
1603 | cropcap->bounds.width = 720; | 1603 | cropcap->bounds.width = 720; |
1604 | cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480; | 1604 | cropcap->bounds.height = dev->tvnorm == V4L2_STD_PAL_BG ? 576 : 480; |
1605 | cropcap->pixelaspect.numerator = | 1605 | cropcap->pixelaspect.numerator = |
1606 | dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10; | 1606 | dev->tvnorm == V4L2_STD_PAL_BG ? 59 : 10; |
1607 | cropcap->pixelaspect.denominator = | 1607 | cropcap->pixelaspect.denominator = |
1608 | dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11; | 1608 | dev->tvnorm == V4L2_STD_PAL_BG ? 54 : 11; |
1609 | cropcap->defrect = cropcap->bounds; | 1609 | cropcap->defrect = cropcap->bounds; |
1610 | return 0; | 1610 | return 0; |
1611 | } | 1611 | } |
1612 | 1612 | ||
1613 | int cx25821_vidioc_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop) | 1613 | int cx25821_vidioc_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop) |
1614 | { | 1614 | { |
1615 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; | 1615 | struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev; |
1616 | struct cx25821_fh *fh = priv; | 1616 | struct cx25821_fh *fh = priv; |
1617 | int err; | 1617 | int err; |
1618 | 1618 | ||
1619 | if (fh) { | 1619 | if (fh) { |
1620 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, | 1620 | err = v4l2_prio_check(&dev->channels[fh->channel_id].prio, |
1621 | fh->prio); | 1621 | fh->prio); |
1622 | if (0 != err) | 1622 | if (0 != err) |
1623 | return err; | 1623 | return err; |
1624 | } | 1624 | } |
1625 | /* cx25821_vidioc_s_crop not supported */ | 1625 | /* cx25821_vidioc_s_crop not supported */ |
1626 | return -EINVAL; | 1626 | return -EINVAL; |
1627 | } | 1627 | } |
1628 | 1628 | ||
1629 | int cx25821_vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop) | 1629 | int cx25821_vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop) |
1630 | { | 1630 | { |
1631 | /* cx25821_vidioc_g_crop not supported */ | 1631 | /* cx25821_vidioc_g_crop not supported */ |
1632 | return -EINVAL; | 1632 | return -EINVAL; |
1633 | } | 1633 | } |
1634 | 1634 | ||
1635 | int cx25821_vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm) | 1635 | int cx25821_vidioc_querystd(struct file *file, void *priv, v4l2_std_id * norm) |
1636 | { | 1636 | { |
1637 | /* medusa does not support video standard sensing of current input */ | 1637 | /* medusa does not support video standard sensing of current input */ |
1638 | *norm = CX25821_NORMS; | 1638 | *norm = CX25821_NORMS; |
1639 | 1639 | ||
1640 | return 0; | 1640 | return 0; |
1641 | } | 1641 | } |
1642 | 1642 | ||
1643 | int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm) | 1643 | int cx25821_is_valid_width(u32 width, v4l2_std_id tvnorm) |
1644 | { | 1644 | { |
1645 | if (tvnorm == V4L2_STD_PAL_BG) { | 1645 | if (tvnorm == V4L2_STD_PAL_BG) { |
1646 | if (width == 352 || width == 720) | 1646 | if (width == 352 || width == 720) |
1647 | return 1; | 1647 | return 1; |
1648 | else | 1648 | else |
1649 | return 0; | 1649 | return 0; |
1650 | } | 1650 | } |
1651 | 1651 | ||
1652 | if (tvnorm == V4L2_STD_NTSC_M) { | 1652 | if (tvnorm == V4L2_STD_NTSC_M) { |
1653 | if (width == 320 || width == 352 || width == 720) | 1653 | if (width == 320 || width == 352 || width == 720) |
1654 | return 1; | 1654 | return 1; |
1655 | else | 1655 | else |
1656 | return 0; | 1656 | return 0; |
1657 | } | 1657 | } |
1658 | return 0; | 1658 | return 0; |
1659 | } | 1659 | } |
1660 | 1660 | ||
1661 | int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm) | 1661 | int cx25821_is_valid_height(u32 height, v4l2_std_id tvnorm) |
1662 | { | 1662 | { |
1663 | if (tvnorm == V4L2_STD_PAL_BG) { | 1663 | if (tvnorm == V4L2_STD_PAL_BG) { |
1664 | if (height == 576 || height == 288) | 1664 | if (height == 576 || height == 288) |
1665 | return 1; | 1665 | return 1; |
1666 | else | 1666 | else |
1667 | return 0; | 1667 | return 0; |
1668 | } | 1668 | } |
1669 | 1669 | ||
1670 | if (tvnorm == V4L2_STD_NTSC_M) { | 1670 | if (tvnorm == V4L2_STD_NTSC_M) { |
1671 | if (height == 480 || height == 240) | 1671 | if (height == 480 || height == 240) |
1672 | return 1; | 1672 | return 1; |
1673 | else | 1673 | else |
1674 | return 0; | 1674 | return 0; |
1675 | } | 1675 | } |
1676 | 1676 | ||
1677 | return 0; | 1677 | return 0; |
1678 | } | 1678 | } |
1679 | 1679 | ||
1680 | static long video_ioctl_upstream9(struct file *file, unsigned int cmd, | 1680 | static long video_ioctl_upstream9(struct file *file, unsigned int cmd, |
1681 | unsigned long arg) | 1681 | unsigned long arg) |
1682 | { | 1682 | { |
1683 | struct cx25821_fh *fh = file->private_data; | 1683 | struct cx25821_fh *fh = file->private_data; |
1684 | struct cx25821_dev *dev = fh->dev; | 1684 | struct cx25821_dev *dev = fh->dev; |
1685 | int command = 0; | 1685 | int command = 0; |
1686 | struct upstream_user_struct *data_from_user; | 1686 | struct upstream_user_struct *data_from_user; |
1687 | 1687 | ||
1688 | data_from_user = (struct upstream_user_struct *)arg; | 1688 | data_from_user = (struct upstream_user_struct *)arg; |
1689 | 1689 | ||
1690 | if (!data_from_user) { | 1690 | if (!data_from_user) { |
1691 | pr_err("%s(): Upstream data is INVALID. Returning\n", __func__); | 1691 | pr_err("%s(): Upstream data is INVALID. Returning\n", __func__); |
1692 | return 0; | 1692 | return 0; |
1693 | } | 1693 | } |
1694 | 1694 | ||
1695 | command = data_from_user->command; | 1695 | command = data_from_user->command; |
1696 | 1696 | ||
1697 | if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO) | 1697 | if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO) |
1698 | return 0; | 1698 | return 0; |
1699 | 1699 | ||
1700 | dev->input_filename = data_from_user->input_filename; | 1700 | dev->input_filename = data_from_user->input_filename; |
1701 | dev->input_audiofilename = data_from_user->input_filename; | 1701 | dev->input_audiofilename = data_from_user->input_filename; |
1702 | dev->vid_stdname = data_from_user->vid_stdname; | 1702 | dev->vid_stdname = data_from_user->vid_stdname; |
1703 | dev->pixel_format = data_from_user->pixel_format; | 1703 | dev->pixel_format = data_from_user->pixel_format; |
1704 | dev->channel_select = data_from_user->channel_select; | 1704 | dev->channel_select = data_from_user->channel_select; |
1705 | dev->command = data_from_user->command; | 1705 | dev->command = data_from_user->command; |
1706 | 1706 | ||
1707 | switch (command) { | 1707 | switch (command) { |
1708 | case UPSTREAM_START_VIDEO: | 1708 | case UPSTREAM_START_VIDEO: |
1709 | cx25821_start_upstream_video_ch1(dev, data_from_user); | 1709 | cx25821_start_upstream_video_ch1(dev, data_from_user); |
1710 | break; | 1710 | break; |
1711 | 1711 | ||
1712 | case UPSTREAM_STOP_VIDEO: | 1712 | case UPSTREAM_STOP_VIDEO: |
1713 | cx25821_stop_upstream_video_ch1(dev); | 1713 | cx25821_stop_upstream_video_ch1(dev); |
1714 | break; | 1714 | break; |
1715 | } | 1715 | } |
1716 | 1716 | ||
1717 | return 0; | 1717 | return 0; |
1718 | } | 1718 | } |
1719 | 1719 | ||
1720 | static long video_ioctl_upstream10(struct file *file, unsigned int cmd, | 1720 | static long video_ioctl_upstream10(struct file *file, unsigned int cmd, |
1721 | unsigned long arg) | 1721 | unsigned long arg) |
1722 | { | 1722 | { |
1723 | struct cx25821_fh *fh = file->private_data; | 1723 | struct cx25821_fh *fh = file->private_data; |
1724 | struct cx25821_dev *dev = fh->dev; | 1724 | struct cx25821_dev *dev = fh->dev; |
1725 | int command = 0; | 1725 | int command = 0; |
1726 | struct upstream_user_struct *data_from_user; | 1726 | struct upstream_user_struct *data_from_user; |
1727 | 1727 | ||
1728 | data_from_user = (struct upstream_user_struct *)arg; | 1728 | data_from_user = (struct upstream_user_struct *)arg; |
1729 | 1729 | ||
1730 | if (!data_from_user) { | 1730 | if (!data_from_user) { |
1731 | pr_err("%s(): Upstream data is INVALID. Returning\n", __func__); | 1731 | pr_err("%s(): Upstream data is INVALID. Returning\n", __func__); |
1732 | return 0; | 1732 | return 0; |
1733 | } | 1733 | } |
1734 | 1734 | ||
1735 | command = data_from_user->command; | 1735 | command = data_from_user->command; |
1736 | 1736 | ||
1737 | if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO) | 1737 | if (command != UPSTREAM_START_VIDEO && command != UPSTREAM_STOP_VIDEO) |
1738 | return 0; | 1738 | return 0; |
1739 | 1739 | ||
1740 | dev->input_filename_ch2 = data_from_user->input_filename; | 1740 | dev->input_filename_ch2 = data_from_user->input_filename; |
1741 | dev->input_audiofilename = data_from_user->input_filename; | 1741 | dev->input_audiofilename = data_from_user->input_filename; |
1742 | dev->vid_stdname_ch2 = data_from_user->vid_stdname; | 1742 | dev->vid_stdname_ch2 = data_from_user->vid_stdname; |
1743 | dev->pixel_format_ch2 = data_from_user->pixel_format; | 1743 | dev->pixel_format_ch2 = data_from_user->pixel_format; |
1744 | dev->channel_select_ch2 = data_from_user->channel_select; | 1744 | dev->channel_select_ch2 = data_from_user->channel_select; |
1745 | dev->command_ch2 = data_from_user->command; | 1745 | dev->command_ch2 = data_from_user->command; |
1746 | 1746 | ||
1747 | switch (command) { | 1747 | switch (command) { |
1748 | case UPSTREAM_START_VIDEO: | 1748 | case UPSTREAM_START_VIDEO: |
1749 | cx25821_start_upstream_video_ch2(dev, data_from_user); | 1749 | cx25821_start_upstream_video_ch2(dev, data_from_user); |
1750 | break; | 1750 | break; |
1751 | 1751 | ||
1752 | case UPSTREAM_STOP_VIDEO: | 1752 | case UPSTREAM_STOP_VIDEO: |
1753 | cx25821_stop_upstream_video_ch2(dev); | 1753 | cx25821_stop_upstream_video_ch2(dev); |
1754 | break; | 1754 | break; |
1755 | } | 1755 | } |
1756 | 1756 | ||
1757 | return 0; | 1757 | return 0; |
1758 | } | 1758 | } |
1759 | 1759 | ||
1760 | static long video_ioctl_upstream11(struct file *file, unsigned int cmd, | 1760 | static long video_ioctl_upstream11(struct file *file, unsigned int cmd, |
1761 | unsigned long arg) | 1761 | unsigned long arg) |
1762 | { | 1762 | { |
1763 | struct cx25821_fh *fh = file->private_data; | 1763 | struct cx25821_fh *fh = file->private_data; |
1764 | struct cx25821_dev *dev = fh->dev; | 1764 | struct cx25821_dev *dev = fh->dev; |
1765 | int command = 0; | 1765 | int command = 0; |
1766 | struct upstream_user_struct *data_from_user; | 1766 | struct upstream_user_struct *data_from_user; |
1767 | 1767 | ||
1768 | data_from_user = (struct upstream_user_struct *)arg; | 1768 | data_from_user = (struct upstream_user_struct *)arg; |
1769 | 1769 | ||
1770 | if (!data_from_user) { | 1770 | if (!data_from_user) { |
1771 | pr_err("%s(): Upstream data is INVALID. Returning\n", __func__); | 1771 | pr_err("%s(): Upstream data is INVALID. Returning\n", __func__); |
1772 | return 0; | 1772 | return 0; |
1773 | } | 1773 | } |
1774 | 1774 | ||
1775 | command = data_from_user->command; | 1775 | command = data_from_user->command; |
1776 | 1776 | ||
1777 | if (command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO) | 1777 | if (command != UPSTREAM_START_AUDIO && command != UPSTREAM_STOP_AUDIO) |
1778 | return 0; | 1778 | return 0; |
1779 | 1779 | ||
1780 | dev->input_filename = data_from_user->input_filename; | 1780 | dev->input_filename = data_from_user->input_filename; |
1781 | dev->input_audiofilename = data_from_user->input_filename; | 1781 | dev->input_audiofilename = data_from_user->input_filename; |
1782 | dev->vid_stdname = data_from_user->vid_stdname; | 1782 | dev->vid_stdname = data_from_user->vid_stdname; |
1783 | dev->pixel_format = data_from_user->pixel_format; | 1783 | dev->pixel_format = data_from_user->pixel_format; |
1784 | dev->channel_select = data_from_user->channel_select; | 1784 | dev->channel_select = data_from_user->channel_select; |
1785 | dev->command = data_from_user->command; | 1785 | dev->command = data_from_user->command; |
1786 | 1786 | ||
1787 | switch (command) { | 1787 | switch (command) { |
1788 | case UPSTREAM_START_AUDIO: | 1788 | case UPSTREAM_START_AUDIO: |
1789 | cx25821_start_upstream_audio(dev, data_from_user); | 1789 | cx25821_start_upstream_audio(dev, data_from_user); |
1790 | break; | 1790 | break; |
1791 | 1791 | ||
1792 | case UPSTREAM_STOP_AUDIO: | 1792 | case UPSTREAM_STOP_AUDIO: |
1793 | cx25821_stop_upstream_audio(dev); | 1793 | cx25821_stop_upstream_audio(dev); |
1794 | break; | 1794 | break; |
1795 | } | 1795 | } |
1796 | 1796 | ||
1797 | return 0; | 1797 | return 0; |
1798 | } | 1798 | } |
1799 | 1799 | ||
1800 | static long video_ioctl_set(struct file *file, unsigned int cmd, | 1800 | static long video_ioctl_set(struct file *file, unsigned int cmd, |
1801 | unsigned long arg) | 1801 | unsigned long arg) |
1802 | { | 1802 | { |
1803 | struct cx25821_fh *fh = file->private_data; | 1803 | struct cx25821_fh *fh = file->private_data; |
1804 | struct cx25821_dev *dev = fh->dev; | 1804 | struct cx25821_dev *dev = fh->dev; |
1805 | struct downstream_user_struct *data_from_user; | 1805 | struct downstream_user_struct *data_from_user; |
1806 | int command; | 1806 | int command; |
1807 | int width = 720; | 1807 | int width = 720; |
1808 | int selected_channel = 0; | 1808 | int selected_channel = 0; |
1809 | int pix_format = 0; | 1809 | int pix_format = 0; |
1810 | int i = 0; | 1810 | int i = 0; |
1811 | int cif_enable = 0; | 1811 | int cif_enable = 0; |
1812 | int cif_width = 0; | 1812 | int cif_width = 0; |
1813 | 1813 | ||
1814 | data_from_user = (struct downstream_user_struct *)arg; | 1814 | data_from_user = (struct downstream_user_struct *)arg; |
1815 | 1815 | ||
1816 | if (!data_from_user) { | 1816 | if (!data_from_user) { |
1817 | pr_err("%s(): User data is INVALID. Returning\n", __func__); | 1817 | pr_err("%s(): User data is INVALID. Returning\n", __func__); |
1818 | return 0; | 1818 | return 0; |
1819 | } | 1819 | } |
1820 | 1820 | ||
1821 | command = data_from_user->command; | 1821 | command = data_from_user->command; |
1822 | 1822 | ||
1823 | if (command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT | 1823 | if (command != SET_VIDEO_STD && command != SET_PIXEL_FORMAT |
1824 | && command != ENABLE_CIF_RESOLUTION && command != REG_READ | 1824 | && command != ENABLE_CIF_RESOLUTION && command != REG_READ |
1825 | && command != REG_WRITE && command != MEDUSA_READ | 1825 | && command != REG_WRITE && command != MEDUSA_READ |
1826 | && command != MEDUSA_WRITE) { | 1826 | && command != MEDUSA_WRITE) { |
1827 | return 0; | 1827 | return 0; |
1828 | } | 1828 | } |
1829 | 1829 | ||
1830 | switch (command) { | 1830 | switch (command) { |
1831 | case SET_VIDEO_STD: | 1831 | case SET_VIDEO_STD: |
1832 | if (!strcmp(data_from_user->vid_stdname, "PAL")) | 1832 | if (!strcmp(data_from_user->vid_stdname, "PAL")) |
1833 | dev->tvnorm = V4L2_STD_PAL_BG; | 1833 | dev->tvnorm = V4L2_STD_PAL_BG; |
1834 | else | 1834 | else |
1835 | dev->tvnorm = V4L2_STD_NTSC_M; | 1835 | dev->tvnorm = V4L2_STD_NTSC_M; |
1836 | medusa_set_videostandard(dev); | 1836 | medusa_set_videostandard(dev); |
1837 | break; | 1837 | break; |
1838 | 1838 | ||
1839 | case SET_PIXEL_FORMAT: | 1839 | case SET_PIXEL_FORMAT: |
1840 | selected_channel = data_from_user->decoder_select; | 1840 | selected_channel = data_from_user->decoder_select; |
1841 | pix_format = data_from_user->pixel_format; | 1841 | pix_format = data_from_user->pixel_format; |
1842 | 1842 | ||
1843 | if (!(selected_channel <= 7 && selected_channel >= 0)) { | 1843 | if (!(selected_channel <= 7 && selected_channel >= 0)) { |
1844 | selected_channel -= 4; | 1844 | selected_channel -= 4; |
1845 | selected_channel = selected_channel % 8; | 1845 | selected_channel = selected_channel % 8; |
1846 | } | 1846 | } |
1847 | 1847 | ||
1848 | if (selected_channel >= 0) | 1848 | if (selected_channel >= 0) |
1849 | cx25821_set_pixel_format(dev, selected_channel, | 1849 | cx25821_set_pixel_format(dev, selected_channel, |
1850 | pix_format); | 1850 | pix_format); |
1851 | 1851 | ||
1852 | break; | 1852 | break; |
1853 | 1853 | ||
1854 | case ENABLE_CIF_RESOLUTION: | 1854 | case ENABLE_CIF_RESOLUTION: |
1855 | selected_channel = data_from_user->decoder_select; | 1855 | selected_channel = data_from_user->decoder_select; |
1856 | cif_enable = data_from_user->cif_resolution_enable; | 1856 | cif_enable = data_from_user->cif_resolution_enable; |
1857 | cif_width = data_from_user->cif_width; | 1857 | cif_width = data_from_user->cif_width; |
1858 | 1858 | ||
1859 | if (cif_enable) { | 1859 | if (cif_enable) { |
1860 | if (dev->tvnorm & V4L2_STD_PAL_BG | 1860 | if (dev->tvnorm & V4L2_STD_PAL_BG |
1861 | || dev->tvnorm & V4L2_STD_PAL_DK) { | 1861 | || dev->tvnorm & V4L2_STD_PAL_DK) { |
1862 | width = 352; | 1862 | width = 352; |
1863 | } else { | 1863 | } else { |
1864 | width = cif_width; | 1864 | width = cif_width; |
1865 | if (cif_width != 320 && cif_width != 352) | 1865 | if (cif_width != 320 && cif_width != 352) |
1866 | width = 320; | 1866 | width = 320; |
1867 | } | 1867 | } |
1868 | } | 1868 | } |
1869 | 1869 | ||
1870 | if (!(selected_channel <= 7 && selected_channel >= 0)) { | 1870 | if (!(selected_channel <= 7 && selected_channel >= 0)) { |
1871 | selected_channel -= 4; | 1871 | selected_channel -= 4; |
1872 | selected_channel = selected_channel % 8; | 1872 | selected_channel = selected_channel % 8; |
1873 | } | 1873 | } |
1874 | 1874 | ||
1875 | if (selected_channel <= 7 && selected_channel >= 0) { | 1875 | if (selected_channel <= 7 && selected_channel >= 0) { |
1876 | dev->channels[selected_channel].use_cif_resolution = | 1876 | dev->channels[selected_channel].use_cif_resolution = |
1877 | cif_enable; | 1877 | cif_enable; |
1878 | dev->channels[selected_channel].cif_width = width; | 1878 | dev->channels[selected_channel].cif_width = width; |
1879 | } else { | 1879 | } else { |
1880 | for (i = 0; i < VID_CHANNEL_NUM; i++) { | 1880 | for (i = 0; i < VID_CHANNEL_NUM; i++) { |
1881 | dev->channels[i].use_cif_resolution = | 1881 | dev->channels[i].use_cif_resolution = |
1882 | cif_enable; | 1882 | cif_enable; |
1883 | dev->channels[i].cif_width = width; | 1883 | dev->channels[i].cif_width = width; |
1884 | } | 1884 | } |
1885 | } | 1885 | } |
1886 | 1886 | ||
1887 | medusa_set_resolution(dev, width, selected_channel); | 1887 | medusa_set_resolution(dev, width, selected_channel); |
1888 | break; | 1888 | break; |
1889 | case REG_READ: | 1889 | case REG_READ: |
1890 | data_from_user->reg_data = cx_read(data_from_user->reg_address); | 1890 | data_from_user->reg_data = cx_read(data_from_user->reg_address); |
1891 | break; | 1891 | break; |
1892 | case REG_WRITE: | 1892 | case REG_WRITE: |
1893 | cx_write(data_from_user->reg_address, data_from_user->reg_data); | 1893 | cx_write(data_from_user->reg_address, data_from_user->reg_data); |
1894 | break; | 1894 | break; |
1895 | case MEDUSA_READ: | 1895 | case MEDUSA_READ: |
1896 | cx25821_i2c_read(&dev->i2c_bus[0], | 1896 | cx25821_i2c_read(&dev->i2c_bus[0], |
1897 | (u16) data_from_user->reg_address, | 1897 | (u16) data_from_user->reg_address, |
1898 | &data_from_user->reg_data); | 1898 | &data_from_user->reg_data); |
1899 | break; | 1899 | break; |
1900 | case MEDUSA_WRITE: | 1900 | case MEDUSA_WRITE: |
1901 | cx25821_i2c_write(&dev->i2c_bus[0], | 1901 | cx25821_i2c_write(&dev->i2c_bus[0], |
1902 | (u16) data_from_user->reg_address, | 1902 | (u16) data_from_user->reg_address, |
1903 | data_from_user->reg_data); | 1903 | data_from_user->reg_data); |
1904 | break; | 1904 | break; |
1905 | } | 1905 | } |
1906 | 1906 | ||
1907 | return 0; | 1907 | return 0; |
1908 | } | 1908 | } |
1909 | 1909 | ||
1910 | static long cx25821_video_ioctl(struct file *file, | 1910 | static long cx25821_video_ioctl(struct file *file, |
1911 | unsigned int cmd, unsigned long arg) | 1911 | unsigned int cmd, unsigned long arg) |
1912 | { | 1912 | { |
1913 | int ret = 0; | 1913 | int ret = 0; |
1914 | 1914 | ||
1915 | struct cx25821_fh *fh = file->private_data; | 1915 | struct cx25821_fh *fh = file->private_data; |
1916 | 1916 | ||
1917 | /* check to see if it's the video upstream */ | 1917 | /* check to see if it's the video upstream */ |
1918 | if (fh->channel_id == SRAM_CH09) { | 1918 | if (fh->channel_id == SRAM_CH09) { |
1919 | ret = video_ioctl_upstream9(file, cmd, arg); | 1919 | ret = video_ioctl_upstream9(file, cmd, arg); |
1920 | return ret; | 1920 | return ret; |
1921 | } else if (fh->channel_id == SRAM_CH10) { | 1921 | } else if (fh->channel_id == SRAM_CH10) { |
1922 | ret = video_ioctl_upstream10(file, cmd, arg); | 1922 | ret = video_ioctl_upstream10(file, cmd, arg); |
1923 | return ret; | 1923 | return ret; |
1924 | } else if (fh->channel_id == SRAM_CH11) { | 1924 | } else if (fh->channel_id == SRAM_CH11) { |
1925 | ret = video_ioctl_upstream11(file, cmd, arg); | 1925 | ret = video_ioctl_upstream11(file, cmd, arg); |
1926 | ret = video_ioctl_set(file, cmd, arg); | 1926 | ret = video_ioctl_set(file, cmd, arg); |
1927 | return ret; | 1927 | return ret; |
1928 | } | 1928 | } |
1929 | 1929 | ||
1930 | return video_ioctl2(file, cmd, arg); | 1930 | return video_ioctl2(file, cmd, arg); |
1931 | } | 1931 | } |
1932 | 1932 | ||
1933 | /* exported stuff */ | 1933 | /* exported stuff */ |
1934 | static const struct v4l2_file_operations video_fops = { | 1934 | static const struct v4l2_file_operations video_fops = { |
1935 | .owner = THIS_MODULE, | 1935 | .owner = THIS_MODULE, |
1936 | .open = video_open, | 1936 | .open = video_open, |
1937 | .release = video_release, | 1937 | .release = video_release, |
1938 | .read = video_read, | 1938 | .read = video_read, |
1939 | .poll = video_poll, | 1939 | .poll = video_poll, |
1940 | .mmap = cx25821_video_mmap, | 1940 | .mmap = cx25821_video_mmap, |
1941 | .ioctl = cx25821_video_ioctl, | 1941 | .ioctl = cx25821_video_ioctl, |
1942 | }; | 1942 | }; |
1943 | 1943 | ||
1944 | static const struct v4l2_ioctl_ops video_ioctl_ops = { | 1944 | static const struct v4l2_ioctl_ops video_ioctl_ops = { |
1945 | .vidioc_querycap = cx25821_vidioc_querycap, | 1945 | .vidioc_querycap = cx25821_vidioc_querycap, |
1946 | .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, | 1946 | .vidioc_enum_fmt_vid_cap = cx25821_vidioc_enum_fmt_vid_cap, |
1947 | .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, | 1947 | .vidioc_g_fmt_vid_cap = cx25821_vidioc_g_fmt_vid_cap, |
1948 | .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, | 1948 | .vidioc_try_fmt_vid_cap = cx25821_vidioc_try_fmt_vid_cap, |
1949 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, | 1949 | .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap, |
1950 | .vidioc_reqbufs = cx25821_vidioc_reqbufs, | 1950 | .vidioc_reqbufs = cx25821_vidioc_reqbufs, |
1951 | .vidioc_querybuf = cx25821_vidioc_querybuf, | 1951 | .vidioc_querybuf = cx25821_vidioc_querybuf, |
1952 | .vidioc_qbuf = cx25821_vidioc_qbuf, | 1952 | .vidioc_qbuf = cx25821_vidioc_qbuf, |
1953 | .vidioc_dqbuf = vidioc_dqbuf, | 1953 | .vidioc_dqbuf = vidioc_dqbuf, |
1954 | #ifdef TUNER_FLAG | 1954 | #ifdef TUNER_FLAG |
1955 | .vidioc_s_std = cx25821_vidioc_s_std, | 1955 | .vidioc_s_std = cx25821_vidioc_s_std, |
1956 | .vidioc_querystd = cx25821_vidioc_querystd, | 1956 | .vidioc_querystd = cx25821_vidioc_querystd, |
1957 | #endif | 1957 | #endif |
1958 | .vidioc_cropcap = cx25821_vidioc_cropcap, | 1958 | .vidioc_cropcap = cx25821_vidioc_cropcap, |
1959 | .vidioc_s_crop = cx25821_vidioc_s_crop, | 1959 | .vidioc_s_crop = cx25821_vidioc_s_crop, |
1960 | .vidioc_g_crop = cx25821_vidioc_g_crop, | 1960 | .vidioc_g_crop = cx25821_vidioc_g_crop, |
1961 | .vidioc_enum_input = cx25821_vidioc_enum_input, | 1961 | .vidioc_enum_input = cx25821_vidioc_enum_input, |
1962 | .vidioc_g_input = cx25821_vidioc_g_input, | 1962 | .vidioc_g_input = cx25821_vidioc_g_input, |
1963 | .vidioc_s_input = cx25821_vidioc_s_input, | 1963 | .vidioc_s_input = cx25821_vidioc_s_input, |
1964 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, | 1964 | .vidioc_g_ctrl = cx25821_vidioc_g_ctrl, |
1965 | .vidioc_s_ctrl = vidioc_s_ctrl, | 1965 | .vidioc_s_ctrl = vidioc_s_ctrl, |
1966 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, | 1966 | .vidioc_queryctrl = cx25821_vidioc_queryctrl, |
1967 | .vidioc_streamon = vidioc_streamon, | 1967 | .vidioc_streamon = vidioc_streamon, |
1968 | .vidioc_streamoff = vidioc_streamoff, | 1968 | .vidioc_streamoff = vidioc_streamoff, |
1969 | .vidioc_log_status = vidioc_log_status, | 1969 | .vidioc_log_status = vidioc_log_status, |
1970 | .vidioc_g_priority = cx25821_vidioc_g_priority, | 1970 | .vidioc_g_priority = cx25821_vidioc_g_priority, |
1971 | .vidioc_s_priority = cx25821_vidioc_s_priority, | 1971 | .vidioc_s_priority = cx25821_vidioc_s_priority, |
1972 | #ifdef TUNER_FLAG | 1972 | #ifdef TUNER_FLAG |
1973 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, | 1973 | .vidioc_g_tuner = cx25821_vidioc_g_tuner, |
1974 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, | 1974 | .vidioc_s_tuner = cx25821_vidioc_s_tuner, |
1975 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, | 1975 | .vidioc_g_frequency = cx25821_vidioc_g_frequency, |
1976 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, | 1976 | .vidioc_s_frequency = cx25821_vidioc_s_frequency, |
1977 | #endif | 1977 | #endif |
1978 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 1978 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
1979 | .vidioc_g_register = cx25821_vidioc_g_register, | 1979 | .vidioc_g_register = cx25821_vidioc_g_register, |
1980 | .vidioc_s_register = cx25821_vidioc_s_register, | 1980 | .vidioc_s_register = cx25821_vidioc_s_register, |
1981 | #endif | 1981 | #endif |
1982 | }; | 1982 | }; |
1983 | 1983 | ||
1984 | struct video_device cx25821_videoioctl_template = { | 1984 | struct video_device cx25821_videoioctl_template = { |
1985 | .name = "cx25821-videoioctl", | 1985 | .name = "cx25821-videoioctl", |
1986 | .fops = &video_fops, | 1986 | .fops = &video_fops, |
1987 | .ioctl_ops = &video_ioctl_ops, | 1987 | .ioctl_ops = &video_ioctl_ops, |
1988 | .tvnorms = CX25821_NORMS, | 1988 | .tvnorms = CX25821_NORMS, |
1989 | .current_norm = V4L2_STD_NTSC_M, | 1989 | .current_norm = V4L2_STD_NTSC_M, |
1990 | }; | 1990 | }; |
1991 | 1991 |