Commit | Line | Data |
---|---|---|
02b20b0b MCC |
1 | /* |
2 | * Driver for the Conexant CX25821 PCIe bridge | |
3 | * | |
bb4c9a74 | 4 | * Copyright (C) 2009 Conexant Systems Inc. |
02b20b0b MCC |
5 | * Authors <shu.lin@conexant.com>, <hiep.huynh@conexant.com> |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License as published by | |
9 | * the Free Software Foundation; either version 2 of the License, or | |
10 | * (at your option) any later version. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
21 | */ | |
22 | ||
23 | #include "cx25821.h" | |
24 | #include "cx25821-medusa-video.h" | |
25 | #include "cx25821-biffuncs.h" | |
26 | ||
0dd8be8c OP |
27 | /* |
28 | * medusa_enable_bluefield_output() | |
29 | * | |
30 | * Enable the generation of blue filed output if no video | |
31 | * | |
32 | */ | |
1a9fc855 MCC |
33 | static void medusa_enable_bluefield_output(struct cx25821_dev *dev, int channel, |
34 | int enable) | |
02b20b0b | 35 | { |
1a9fc855 MCC |
36 | int ret_val = 1; |
37 | u32 value = 0; | |
38 | u32 tmp = 0; | |
39 | int out_ctrl = OUT_CTRL1; | |
40 | int out_ctrl_ns = OUT_CTRL_NS; | |
bb4c9a74 | 41 | |
1a9fc855 | 42 | switch (channel) { |
bb4c9a74 MCC |
43 | default: |
44 | case VDEC_A: | |
1a9fc855 | 45 | break; |
bb4c9a74 | 46 | case VDEC_B: |
1a9fc855 MCC |
47 | out_ctrl = VDEC_B_OUT_CTRL1; |
48 | out_ctrl_ns = VDEC_B_OUT_CTRL_NS; | |
49 | break; | |
bb4c9a74 | 50 | case VDEC_C: |
1a9fc855 MCC |
51 | out_ctrl = VDEC_C_OUT_CTRL1; |
52 | out_ctrl_ns = VDEC_C_OUT_CTRL_NS; | |
53 | break; | |
bb4c9a74 | 54 | case VDEC_D: |
1a9fc855 MCC |
55 | out_ctrl = VDEC_D_OUT_CTRL1; |
56 | out_ctrl_ns = VDEC_D_OUT_CTRL_NS; | |
57 | break; | |
bb4c9a74 | 58 | case VDEC_E: |
1a9fc855 MCC |
59 | out_ctrl = VDEC_E_OUT_CTRL1; |
60 | out_ctrl_ns = VDEC_E_OUT_CTRL_NS; | |
61 | return; | |
bb4c9a74 | 62 | case VDEC_F: |
1a9fc855 MCC |
63 | out_ctrl = VDEC_F_OUT_CTRL1; |
64 | out_ctrl_ns = VDEC_F_OUT_CTRL_NS; | |
65 | return; | |
bb4c9a74 | 66 | case VDEC_G: |
1a9fc855 MCC |
67 | out_ctrl = VDEC_G_OUT_CTRL1; |
68 | out_ctrl_ns = VDEC_G_OUT_CTRL_NS; | |
69 | return; | |
bb4c9a74 | 70 | case VDEC_H: |
1a9fc855 MCC |
71 | out_ctrl = VDEC_H_OUT_CTRL1; |
72 | out_ctrl_ns = VDEC_H_OUT_CTRL_NS; | |
73 | return; | |
74 | } | |
75 | ||
76 | value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl, &tmp); | |
0dd8be8c | 77 | value &= 0xFFFFFF7F; /* clear BLUE_FIELD_EN */ |
1a9fc855 | 78 | if (enable) |
0dd8be8c | 79 | value |= 0x00000080; /* set BLUE_FIELD_EN */ |
1a9fc855 MCC |
80 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl, value); |
81 | ||
82 | value = cx25821_i2c_read(&dev->i2c_bus[0], out_ctrl_ns, &tmp); | |
83 | value &= 0xFFFFFF7F; | |
84 | if (enable) | |
0dd8be8c | 85 | value |= 0x00000080; /* set BLUE_FIELD_EN */ |
1a9fc855 | 86 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], out_ctrl_ns, value); |
02b20b0b MCC |
87 | } |
88 | ||
02b20b0b MCC |
89 | static int medusa_initialize_ntsc(struct cx25821_dev *dev) |
90 | { | |
1a9fc855 MCC |
91 | int ret_val = 0; |
92 | int i = 0; | |
93 | u32 value = 0; | |
94 | u32 tmp = 0; | |
95 | ||
96 | mutex_lock(&dev->lock); | |
97 | ||
98 | for (i = 0; i < MAX_DECODERS; i++) { | |
0dd8be8c | 99 | /* set video format NTSC-M */ |
1a9fc855 MCC |
100 | value = |
101 | cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | |
102 | &tmp); | |
103 | value &= 0xFFFFFFF0; | |
0dd8be8c OP |
104 | /* enable the fast locking mode bit[16] */ |
105 | value |= 0x10001; | |
1a9fc855 MCC |
106 | ret_val = |
107 | cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | |
108 | value); | |
109 | ||
0dd8be8c | 110 | /* resolution NTSC 720x480 */ |
1a9fc855 MCC |
111 | value = |
112 | cx25821_i2c_read(&dev->i2c_bus[0], | |
113 | HORIZ_TIM_CTRL + (0x200 * i), &tmp); | |
114 | value &= 0x00C00C00; | |
115 | value |= 0x612D0074; | |
116 | ret_val = | |
117 | cx25821_i2c_write(&dev->i2c_bus[0], | |
118 | HORIZ_TIM_CTRL + (0x200 * i), value); | |
119 | ||
120 | value = | |
121 | cx25821_i2c_read(&dev->i2c_bus[0], | |
122 | VERT_TIM_CTRL + (0x200 * i), &tmp); | |
123 | value &= 0x00C00C00; | |
0dd8be8c | 124 | value |= 0x1C1E001A; /* vblank_cnt + 2 to get camera ID */ |
1a9fc855 MCC |
125 | ret_val = |
126 | cx25821_i2c_write(&dev->i2c_bus[0], | |
127 | VERT_TIM_CTRL + (0x200 * i), value); | |
128 | ||
0dd8be8c | 129 | /* chroma subcarrier step size */ |
1a9fc855 MCC |
130 | ret_val = |
131 | cx25821_i2c_write(&dev->i2c_bus[0], | |
132 | SC_STEP_SIZE + (0x200 * i), 0x43E00000); | |
133 | ||
0dd8be8c | 134 | /* enable VIP optional active */ |
1a9fc855 MCC |
135 | value = |
136 | cx25821_i2c_read(&dev->i2c_bus[0], | |
137 | OUT_CTRL_NS + (0x200 * i), &tmp); | |
138 | value &= 0xFFFBFFFF; | |
139 | value |= 0x00040000; | |
140 | ret_val = | |
141 | cx25821_i2c_write(&dev->i2c_bus[0], | |
142 | OUT_CTRL_NS + (0x200 * i), value); | |
143 | ||
0dd8be8c | 144 | /* enable VIP optional active (VIP_OPT_AL) for direct output. */ |
1a9fc855 MCC |
145 | value = |
146 | cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | |
147 | &tmp); | |
148 | value &= 0xFFFBFFFF; | |
149 | value |= 0x00040000; | |
150 | ret_val = | |
151 | cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | |
152 | value); | |
153 | ||
0dd8be8c OP |
154 | /* |
155 | * clear VPRES_VERT_EN bit, fixes the chroma run away problem | |
156 | * when the input switching rate < 16 fields | |
157 | */ | |
1a9fc855 MCC |
158 | value = |
159 | cx25821_i2c_read(&dev->i2c_bus[0], | |
160 | MISC_TIM_CTRL + (0x200 * i), &tmp); | |
0dd8be8c OP |
161 | /* disable special play detection */ |
162 | value = setBitAtPos(value, 14); | |
1a9fc855 MCC |
163 | value = clearBitAtPos(value, 15); |
164 | ret_val = | |
165 | cx25821_i2c_write(&dev->i2c_bus[0], | |
166 | MISC_TIM_CTRL + (0x200 * i), value); | |
167 | ||
0dd8be8c | 168 | /* set vbi_gate_en to 0 */ |
1a9fc855 MCC |
169 | value = |
170 | cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | |
171 | &tmp); | |
172 | value = clearBitAtPos(value, 29); | |
173 | ret_val = | |
174 | cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | |
175 | value); | |
176 | ||
0dd8be8c | 177 | /* Enable the generation of blue field output if no video */ |
1a9fc855 MCC |
178 | medusa_enable_bluefield_output(dev, i, 1); |
179 | } | |
180 | ||
181 | for (i = 0; i < MAX_ENCODERS; i++) { | |
0dd8be8c | 182 | /* NTSC hclock */ |
1a9fc855 MCC |
183 | value = |
184 | cx25821_i2c_read(&dev->i2c_bus[0], | |
185 | DENC_A_REG_1 + (0x100 * i), &tmp); | |
186 | value &= 0xF000FC00; | |
187 | value |= 0x06B402D0; | |
188 | ret_val = | |
189 | cx25821_i2c_write(&dev->i2c_bus[0], | |
190 | DENC_A_REG_1 + (0x100 * i), value); | |
191 | ||
0dd8be8c | 192 | /* burst begin and burst end */ |
1a9fc855 MCC |
193 | value = |
194 | cx25821_i2c_read(&dev->i2c_bus[0], | |
195 | DENC_A_REG_2 + (0x100 * i), &tmp); | |
196 | value &= 0xFF000000; | |
197 | value |= 0x007E9054; | |
198 | ret_val = | |
199 | cx25821_i2c_write(&dev->i2c_bus[0], | |
200 | DENC_A_REG_2 + (0x100 * i), value); | |
201 | ||
202 | value = | |
203 | cx25821_i2c_read(&dev->i2c_bus[0], | |
204 | DENC_A_REG_3 + (0x100 * i), &tmp); | |
205 | value &= 0xFC00FE00; | |
206 | value |= 0x00EC00F0; | |
207 | ret_val = | |
208 | cx25821_i2c_write(&dev->i2c_bus[0], | |
209 | DENC_A_REG_3 + (0x100 * i), value); | |
210 | ||
0dd8be8c | 211 | /* set NTSC vblank, no phase alternation, 7.5 IRE pedestal */ |
1a9fc855 MCC |
212 | value = |
213 | cx25821_i2c_read(&dev->i2c_bus[0], | |
214 | DENC_A_REG_4 + (0x100 * i), &tmp); | |
215 | value &= 0x00FCFFFF; | |
216 | value |= 0x13020000; | |
217 | ret_val = | |
218 | cx25821_i2c_write(&dev->i2c_bus[0], | |
219 | DENC_A_REG_4 + (0x100 * i), value); | |
220 | ||
221 | value = | |
222 | cx25821_i2c_read(&dev->i2c_bus[0], | |
223 | DENC_A_REG_5 + (0x100 * i), &tmp); | |
224 | value &= 0xFFFF0000; | |
225 | value |= 0x0000E575; | |
226 | ret_val = | |
227 | cx25821_i2c_write(&dev->i2c_bus[0], | |
228 | DENC_A_REG_5 + (0x100 * i), value); | |
229 | ||
230 | ret_val = | |
231 | cx25821_i2c_write(&dev->i2c_bus[0], | |
232 | DENC_A_REG_6 + (0x100 * i), 0x009A89C1); | |
233 | ||
0dd8be8c | 234 | /* Subcarrier Increment */ |
1a9fc855 MCC |
235 | ret_val = |
236 | cx25821_i2c_write(&dev->i2c_bus[0], | |
237 | DENC_A_REG_7 + (0x100 * i), 0x21F07C1F); | |
238 | } | |
239 | ||
0dd8be8c OP |
240 | /* set picture resolutions */ |
241 | /* 0 - 720 */ | |
242 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); | |
243 | /* 0 - 480 */ | |
244 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); | |
1a9fc855 | 245 | |
0dd8be8c | 246 | /* set Bypass input format to NTSC 525 lines */ |
1a9fc855 MCC |
247 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); |
248 | value |= 0x00080200; | |
249 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); | |
02b20b0b | 250 | |
1a9fc855 MCC |
251 | mutex_unlock(&dev->lock); |
252 | ||
253 | return ret_val; | |
254 | } | |
02b20b0b MCC |
255 | |
256 | static int medusa_PALCombInit(struct cx25821_dev *dev, int dec) | |
257 | { | |
1a9fc855 MCC |
258 | int ret_val = -1; |
259 | u32 value = 0, tmp = 0; | |
260 | ||
0dd8be8c | 261 | /* Setup for 2D threshold */ |
1a9fc855 MCC |
262 | ret_val = |
263 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFS_CFG + (0x200 * dec), | |
264 | 0x20002861); | |
265 | ret_val = | |
266 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_HFD_CFG + (0x200 * dec), | |
267 | 0x20002861); | |
268 | ret_val = | |
269 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_LF_CFG + (0x200 * dec), | |
270 | 0x200A1023); | |
271 | ||
0dd8be8c | 272 | /* Setup flat chroma and luma thresholds */ |
1a9fc855 MCC |
273 | value = |
274 | cx25821_i2c_read(&dev->i2c_bus[0], | |
275 | COMB_FLAT_THRESH_CTRL + (0x200 * dec), &tmp); | |
276 | value &= 0x06230000; | |
277 | ret_val = | |
278 | cx25821_i2c_write(&dev->i2c_bus[0], | |
279 | COMB_FLAT_THRESH_CTRL + (0x200 * dec), value); | |
280 | ||
0dd8be8c | 281 | /* set comb 2D blend */ |
1a9fc855 MCC |
282 | ret_val = |
283 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_2D_BLEND + (0x200 * dec), | |
284 | 0x210F0F0F); | |
285 | ||
0dd8be8c | 286 | /* COMB MISC CONTROL */ |
1a9fc855 MCC |
287 | ret_val = |
288 | cx25821_i2c_write(&dev->i2c_bus[0], COMB_MISC_CTRL + (0x200 * dec), | |
289 | 0x41120A7F); | |
290 | ||
291 | return ret_val; | |
02b20b0b MCC |
292 | } |
293 | ||
02b20b0b MCC |
294 | static int medusa_initialize_pal(struct cx25821_dev *dev) |
295 | { | |
1a9fc855 MCC |
296 | int ret_val = 0; |
297 | int i = 0; | |
298 | u32 value = 0; | |
299 | u32 tmp = 0; | |
300 | ||
301 | mutex_lock(&dev->lock); | |
302 | ||
303 | for (i = 0; i < MAX_DECODERS; i++) { | |
0dd8be8c | 304 | /* set video format PAL-BDGHI */ |
1a9fc855 MCC |
305 | value = |
306 | cx25821_i2c_read(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | |
307 | &tmp); | |
308 | value &= 0xFFFFFFF0; | |
0dd8be8c OP |
309 | /* enable the fast locking mode bit[16] */ |
310 | value |= 0x10004; | |
1a9fc855 MCC |
311 | ret_val = |
312 | cx25821_i2c_write(&dev->i2c_bus[0], MODE_CTRL + (0x200 * i), | |
313 | value); | |
314 | ||
0dd8be8c | 315 | /* resolution PAL 720x576 */ |
1a9fc855 MCC |
316 | value = |
317 | cx25821_i2c_read(&dev->i2c_bus[0], | |
318 | HORIZ_TIM_CTRL + (0x200 * i), &tmp); | |
319 | value &= 0x00C00C00; | |
320 | value |= 0x632D007D; | |
321 | ret_val = | |
322 | cx25821_i2c_write(&dev->i2c_bus[0], | |
323 | HORIZ_TIM_CTRL + (0x200 * i), value); | |
324 | ||
0dd8be8c | 325 | /* vblank656_cnt=x26, vactive_cnt=240h, vblank_cnt=x24 */ |
1a9fc855 MCC |
326 | value = |
327 | cx25821_i2c_read(&dev->i2c_bus[0], | |
328 | VERT_TIM_CTRL + (0x200 * i), &tmp); | |
329 | value &= 0x00C00C00; | |
0dd8be8c | 330 | value |= 0x28240026; /* vblank_cnt + 2 to get camera ID */ |
1a9fc855 MCC |
331 | ret_val = |
332 | cx25821_i2c_write(&dev->i2c_bus[0], | |
333 | VERT_TIM_CTRL + (0x200 * i), value); | |
334 | ||
0dd8be8c | 335 | /* chroma subcarrier step size */ |
1a9fc855 MCC |
336 | ret_val = |
337 | cx25821_i2c_write(&dev->i2c_bus[0], | |
338 | SC_STEP_SIZE + (0x200 * i), 0x5411E2D0); | |
339 | ||
0dd8be8c | 340 | /* enable VIP optional active */ |
1a9fc855 MCC |
341 | value = |
342 | cx25821_i2c_read(&dev->i2c_bus[0], | |
343 | OUT_CTRL_NS + (0x200 * i), &tmp); | |
344 | value &= 0xFFFBFFFF; | |
345 | value |= 0x00040000; | |
346 | ret_val = | |
347 | cx25821_i2c_write(&dev->i2c_bus[0], | |
348 | OUT_CTRL_NS + (0x200 * i), value); | |
349 | ||
0dd8be8c | 350 | /* enable VIP optional active (VIP_OPT_AL) for direct output. */ |
1a9fc855 MCC |
351 | value = |
352 | cx25821_i2c_read(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | |
353 | &tmp); | |
354 | value &= 0xFFFBFFFF; | |
355 | value |= 0x00040000; | |
356 | ret_val = | |
357 | cx25821_i2c_write(&dev->i2c_bus[0], OUT_CTRL1 + (0x200 * i), | |
358 | value); | |
359 | ||
0dd8be8c OP |
360 | /* |
361 | * clear VPRES_VERT_EN bit, fixes the chroma run away problem | |
362 | * when the input switching rate < 16 fields | |
363 | */ | |
1a9fc855 MCC |
364 | value = |
365 | cx25821_i2c_read(&dev->i2c_bus[0], | |
366 | MISC_TIM_CTRL + (0x200 * i), &tmp); | |
0dd8be8c OP |
367 | /* disable special play detection */ |
368 | value = setBitAtPos(value, 14); | |
1a9fc855 MCC |
369 | value = clearBitAtPos(value, 15); |
370 | ret_val = | |
371 | cx25821_i2c_write(&dev->i2c_bus[0], | |
372 | MISC_TIM_CTRL + (0x200 * i), value); | |
373 | ||
0dd8be8c | 374 | /* set vbi_gate_en to 0 */ |
1a9fc855 MCC |
375 | value = |
376 | cx25821_i2c_read(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | |
377 | &tmp); | |
378 | value = clearBitAtPos(value, 29); | |
379 | ret_val = | |
380 | cx25821_i2c_write(&dev->i2c_bus[0], DFE_CTRL1 + (0x200 * i), | |
381 | value); | |
382 | ||
383 | medusa_PALCombInit(dev, i); | |
384 | ||
0dd8be8c | 385 | /* Enable the generation of blue field output if no video */ |
1a9fc855 MCC |
386 | medusa_enable_bluefield_output(dev, i, 1); |
387 | } | |
388 | ||
389 | for (i = 0; i < MAX_ENCODERS; i++) { | |
0dd8be8c | 390 | /* PAL hclock */ |
1a9fc855 MCC |
391 | value = |
392 | cx25821_i2c_read(&dev->i2c_bus[0], | |
393 | DENC_A_REG_1 + (0x100 * i), &tmp); | |
394 | value &= 0xF000FC00; | |
395 | value |= 0x06C002D0; | |
396 | ret_val = | |
397 | cx25821_i2c_write(&dev->i2c_bus[0], | |
398 | DENC_A_REG_1 + (0x100 * i), value); | |
399 | ||
0dd8be8c | 400 | /* burst begin and burst end */ |
1a9fc855 MCC |
401 | value = |
402 | cx25821_i2c_read(&dev->i2c_bus[0], | |
403 | DENC_A_REG_2 + (0x100 * i), &tmp); | |
404 | value &= 0xFF000000; | |
405 | value |= 0x007E9754; | |
406 | ret_val = | |
407 | cx25821_i2c_write(&dev->i2c_bus[0], | |
408 | DENC_A_REG_2 + (0x100 * i), value); | |
409 | ||
0dd8be8c | 410 | /* hblank and vactive */ |
1a9fc855 MCC |
411 | value = |
412 | cx25821_i2c_read(&dev->i2c_bus[0], | |
413 | DENC_A_REG_3 + (0x100 * i), &tmp); | |
414 | value &= 0xFC00FE00; | |
415 | value |= 0x00FC0120; | |
416 | ret_val = | |
417 | cx25821_i2c_write(&dev->i2c_bus[0], | |
418 | DENC_A_REG_3 + (0x100 * i), value); | |
419 | ||
0dd8be8c | 420 | /* set PAL vblank, phase alternation, 0 IRE pedestal */ |
1a9fc855 MCC |
421 | value = |
422 | cx25821_i2c_read(&dev->i2c_bus[0], | |
423 | DENC_A_REG_4 + (0x100 * i), &tmp); | |
424 | value &= 0x00FCFFFF; | |
425 | value |= 0x14010000; | |
426 | ret_val = | |
427 | cx25821_i2c_write(&dev->i2c_bus[0], | |
428 | DENC_A_REG_4 + (0x100 * i), value); | |
429 | ||
430 | value = | |
431 | cx25821_i2c_read(&dev->i2c_bus[0], | |
432 | DENC_A_REG_5 + (0x100 * i), &tmp); | |
433 | value &= 0xFFFF0000; | |
434 | value |= 0x0000F078; | |
435 | ret_val = | |
436 | cx25821_i2c_write(&dev->i2c_bus[0], | |
437 | DENC_A_REG_5 + (0x100 * i), value); | |
438 | ||
439 | ret_val = | |
440 | cx25821_i2c_write(&dev->i2c_bus[0], | |
441 | DENC_A_REG_6 + (0x100 * i), 0x00A493CF); | |
442 | ||
0dd8be8c | 443 | /* Subcarrier Increment */ |
1a9fc855 MCC |
444 | ret_val = |
445 | cx25821_i2c_write(&dev->i2c_bus[0], | |
446 | DENC_A_REG_7 + (0x100 * i), 0x2A098ACB); | |
447 | } | |
448 | ||
0dd8be8c OP |
449 | /* set picture resolutions */ |
450 | /* 0 - 720 */ | |
451 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], HSCALE_CTRL, 0x0); | |
452 | /* 0 - 576 */ | |
453 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], VSCALE_CTRL, 0x0); | |
1a9fc855 | 454 | |
0dd8be8c | 455 | /* set Bypass input format to PAL 625 lines */ |
1a9fc855 MCC |
456 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); |
457 | value &= 0xFFF7FDFF; | |
458 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); | |
459 | ||
460 | mutex_unlock(&dev->lock); | |
02b20b0b | 461 | |
1a9fc855 MCC |
462 | return ret_val; |
463 | } | |
02b20b0b MCC |
464 | |
465 | int medusa_set_videostandard(struct cx25821_dev *dev) | |
466 | { | |
1a9fc855 MCC |
467 | int status = STATUS_SUCCESS; |
468 | u32 value = 0, tmp = 0; | |
469 | ||
0dd8be8c | 470 | if (dev->tvnorm & V4L2_STD_PAL_BG || dev->tvnorm & V4L2_STD_PAL_DK) |
1a9fc855 | 471 | status = medusa_initialize_pal(dev); |
0dd8be8c | 472 | else |
1a9fc855 | 473 | status = medusa_initialize_ntsc(dev); |
1a9fc855 | 474 | |
0dd8be8c | 475 | /* Enable DENC_A output */ |
1a9fc855 MCC |
476 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_A_REG_4, &tmp); |
477 | value = setBitAtPos(value, 4); | |
478 | status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_A_REG_4, value); | |
479 | ||
0dd8be8c | 480 | /* Enable DENC_B output */ |
1a9fc855 MCC |
481 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_B_REG_4, &tmp); |
482 | value = setBitAtPos(value, 4); | |
483 | status = cx25821_i2c_write(&dev->i2c_bus[0], DENC_B_REG_4, value); | |
484 | ||
485 | return status; | |
02b20b0b MCC |
486 | } |
487 | ||
1a9fc855 MCC |
488 | void medusa_set_resolution(struct cx25821_dev *dev, int width, |
489 | int decoder_select) | |
02b20b0b | 490 | { |
1a9fc855 MCC |
491 | int decoder = 0; |
492 | int decoder_count = 0; | |
493 | int ret_val = 0; | |
494 | u32 hscale = 0x0; | |
495 | u32 vscale = 0x0; | |
496 | const int MAX_WIDTH = 720; | |
497 | ||
498 | mutex_lock(&dev->lock); | |
499 | ||
0dd8be8c | 500 | /* validate the width - cannot be negative */ |
1a9fc855 MCC |
501 | if (width > MAX_WIDTH) { |
502 | printk | |
0dd8be8c | 503 | ("cx25821 %s() : width %d > MAX_WIDTH %d ! resetting to MAX_WIDTH\n", |
1a9fc855 MCC |
504 | __func__, width, MAX_WIDTH); |
505 | width = MAX_WIDTH; | |
506 | } | |
507 | ||
508 | if (decoder_select <= 7 && decoder_select >= 0) { | |
509 | decoder = decoder_select; | |
510 | decoder_count = decoder_select + 1; | |
511 | } else { | |
512 | decoder = 0; | |
513 | decoder_count = _num_decoders; | |
514 | } | |
515 | ||
516 | switch (width) { | |
bb4c9a74 | 517 | case 320: |
1a9fc855 MCC |
518 | hscale = 0x13E34B; |
519 | vscale = 0x0; | |
520 | break; | |
bb4c9a74 MCC |
521 | |
522 | case 352: | |
1a9fc855 MCC |
523 | hscale = 0x10A273; |
524 | vscale = 0x0; | |
525 | break; | |
bb4c9a74 MCC |
526 | |
527 | case 176: | |
1a9fc855 MCC |
528 | hscale = 0x3115B2; |
529 | vscale = 0x1E00; | |
530 | break; | |
bb4c9a74 MCC |
531 | |
532 | case 160: | |
1a9fc855 MCC |
533 | hscale = 0x378D84; |
534 | vscale = 0x1E00; | |
535 | break; | |
536 | ||
0dd8be8c | 537 | default: /* 720 */ |
1a9fc855 MCC |
538 | hscale = 0x0; |
539 | vscale = 0x0; | |
540 | break; | |
541 | } | |
542 | ||
543 | for (; decoder < decoder_count; decoder++) { | |
0dd8be8c | 544 | /* write scaling values for each decoder */ |
1a9fc855 MCC |
545 | ret_val = |
546 | cx25821_i2c_write(&dev->i2c_bus[0], | |
547 | HSCALE_CTRL + (0x200 * decoder), hscale); | |
548 | ret_val = | |
549 | cx25821_i2c_write(&dev->i2c_bus[0], | |
550 | VSCALE_CTRL + (0x200 * decoder), vscale); | |
551 | } | |
552 | ||
553 | mutex_unlock(&dev->lock); | |
02b20b0b MCC |
554 | } |
555 | ||
1a9fc855 MCC |
556 | static void medusa_set_decoderduration(struct cx25821_dev *dev, int decoder, |
557 | int duration) | |
02b20b0b | 558 | { |
1a9fc855 MCC |
559 | int ret_val = 0; |
560 | u32 fld_cnt = 0; | |
561 | u32 tmp = 0; | |
562 | u32 disp_cnt_reg = DISP_AB_CNT; | |
bb4c9a74 | 563 | |
1a9fc855 | 564 | mutex_lock(&dev->lock); |
02b20b0b | 565 | |
0dd8be8c | 566 | /* no support */ |
1a9fc855 MCC |
567 | if (decoder < VDEC_A && decoder > VDEC_H) { |
568 | mutex_unlock(&dev->lock); | |
569 | return; | |
570 | } | |
02b20b0b | 571 | |
1a9fc855 | 572 | switch (decoder) { |
bb4c9a74 | 573 | default: |
1a9fc855 | 574 | break; |
bb4c9a74 MCC |
575 | case VDEC_C: |
576 | case VDEC_D: | |
1a9fc855 MCC |
577 | disp_cnt_reg = DISP_CD_CNT; |
578 | break; | |
bb4c9a74 MCC |
579 | case VDEC_E: |
580 | case VDEC_F: | |
1a9fc855 MCC |
581 | disp_cnt_reg = DISP_EF_CNT; |
582 | break; | |
bb4c9a74 MCC |
583 | case VDEC_G: |
584 | case VDEC_H: | |
1a9fc855 MCC |
585 | disp_cnt_reg = DISP_GH_CNT; |
586 | break; | |
587 | } | |
02b20b0b | 588 | |
1a9fc855 | 589 | _display_field_cnt[decoder] = duration; |
02b20b0b | 590 | |
0dd8be8c | 591 | /* update hardware */ |
1a9fc855 | 592 | fld_cnt = cx25821_i2c_read(&dev->i2c_bus[0], disp_cnt_reg, &tmp); |
bb4c9a74 | 593 | |
0dd8be8c | 594 | if (!(decoder % 2)) { /* EVEN decoder */ |
1a9fc855 MCC |
595 | fld_cnt &= 0xFFFF0000; |
596 | fld_cnt |= duration; | |
597 | } else { | |
598 | fld_cnt &= 0x0000FFFF; | |
599 | fld_cnt |= ((u32) duration) << 16; | |
600 | } | |
02b20b0b | 601 | |
1a9fc855 | 602 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], disp_cnt_reg, fld_cnt); |
bb4c9a74 | 603 | |
1a9fc855 | 604 | mutex_unlock(&dev->lock); |
02b20b0b MCC |
605 | } |
606 | ||
0dd8be8c | 607 | /* Map to Medusa register setting */ |
1a9fc855 MCC |
608 | static int mapM(int srcMin, |
609 | int srcMax, int srcVal, int dstMin, int dstMax, int *dstVal) | |
02b20b0b | 610 | { |
1a9fc855 MCC |
611 | int numerator; |
612 | int denominator; | |
613 | int quotient; | |
614 | ||
0dd8be8c | 615 | if ((srcMin == srcMax) || (srcVal < srcMin) || (srcVal > srcMax)) |
1a9fc855 | 616 | return -1; |
0dd8be8c OP |
617 | /* |
618 | * This is the overall expression used: | |
619 | * *dstVal = | |
620 | * (srcVal - srcMin)*(dstMax - dstMin) / (srcMax - srcMin) + dstMin; | |
621 | * but we need to account for rounding so below we use the modulus | |
622 | * operator to find the remainder and increment if necessary. | |
623 | */ | |
1a9fc855 MCC |
624 | numerator = (srcVal - srcMin) * (dstMax - dstMin); |
625 | denominator = srcMax - srcMin; | |
626 | quotient = numerator / denominator; | |
627 | ||
0dd8be8c | 628 | if (2 * (numerator % denominator) >= denominator) |
1a9fc855 | 629 | quotient++; |
1a9fc855 MCC |
630 | |
631 | *dstVal = quotient + dstMin; | |
632 | ||
633 | return 0; | |
02b20b0b MCC |
634 | } |
635 | ||
636 | static unsigned long convert_to_twos(long numeric, unsigned long bits_len) | |
637 | { | |
1a9fc855 MCC |
638 | unsigned char temp; |
639 | ||
640 | if (numeric >= 0) | |
641 | return numeric; | |
642 | else { | |
643 | temp = ~(abs(numeric) & 0xFF); | |
644 | temp += 1; | |
645 | return temp; | |
646 | } | |
02b20b0b | 647 | } |
1a9fc855 | 648 | |
02b20b0b MCC |
649 | int medusa_set_brightness(struct cx25821_dev *dev, int brightness, int decoder) |
650 | { | |
1a9fc855 MCC |
651 | int ret_val = 0; |
652 | int value = 0; | |
653 | u32 val = 0, tmp = 0; | |
654 | ||
655 | mutex_lock(&dev->lock); | |
656 | if ((brightness > VIDEO_PROCAMP_MAX) | |
657 | || (brightness < VIDEO_PROCAMP_MIN)) { | |
658 | mutex_unlock(&dev->lock); | |
659 | return -1; | |
660 | } | |
661 | ret_val = | |
662 | mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, brightness, | |
663 | SIGNED_BYTE_MIN, SIGNED_BYTE_MAX, &value); | |
664 | value = convert_to_twos(value, 8); | |
665 | val = | |
666 | cx25821_i2c_read(&dev->i2c_bus[0], | |
667 | VDEC_A_BRITE_CTRL + (0x200 * decoder), &tmp); | |
668 | val &= 0xFFFFFF00; | |
669 | ret_val |= | |
670 | cx25821_i2c_write(&dev->i2c_bus[0], | |
671 | VDEC_A_BRITE_CTRL + (0x200 * decoder), | |
672 | val | value); | |
bb4c9a74 | 673 | mutex_unlock(&dev->lock); |
1a9fc855 | 674 | return ret_val; |
02b20b0b MCC |
675 | } |
676 | ||
02b20b0b MCC |
677 | int medusa_set_contrast(struct cx25821_dev *dev, int contrast, int decoder) |
678 | { | |
1a9fc855 MCC |
679 | int ret_val = 0; |
680 | int value = 0; | |
681 | u32 val = 0, tmp = 0; | |
682 | ||
683 | mutex_lock(&dev->lock); | |
684 | ||
685 | if ((contrast > VIDEO_PROCAMP_MAX) || (contrast < VIDEO_PROCAMP_MIN)) { | |
686 | mutex_unlock(&dev->lock); | |
687 | return -1; | |
688 | } | |
689 | ||
690 | ret_val = | |
691 | mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, contrast, | |
692 | UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); | |
693 | val = | |
694 | cx25821_i2c_read(&dev->i2c_bus[0], | |
695 | VDEC_A_CNTRST_CTRL + (0x200 * decoder), &tmp); | |
696 | val &= 0xFFFFFF00; | |
697 | ret_val |= | |
698 | cx25821_i2c_write(&dev->i2c_bus[0], | |
699 | VDEC_A_CNTRST_CTRL + (0x200 * decoder), | |
700 | val | value); | |
bb4c9a74 | 701 | |
bb4c9a74 | 702 | mutex_unlock(&dev->lock); |
1a9fc855 | 703 | return ret_val; |
02b20b0b MCC |
704 | } |
705 | ||
02b20b0b MCC |
706 | int medusa_set_hue(struct cx25821_dev *dev, int hue, int decoder) |
707 | { | |
1a9fc855 MCC |
708 | int ret_val = 0; |
709 | int value = 0; | |
710 | u32 val = 0, tmp = 0; | |
02b20b0b | 711 | |
1a9fc855 | 712 | mutex_lock(&dev->lock); |
bb4c9a74 | 713 | |
1a9fc855 MCC |
714 | if ((hue > VIDEO_PROCAMP_MAX) || (hue < VIDEO_PROCAMP_MIN)) { |
715 | mutex_unlock(&dev->lock); | |
716 | return -1; | |
717 | } | |
02b20b0b | 718 | |
1a9fc855 MCC |
719 | ret_val = |
720 | mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, hue, SIGNED_BYTE_MIN, | |
721 | SIGNED_BYTE_MAX, &value); | |
bb4c9a74 | 722 | |
1a9fc855 MCC |
723 | value = convert_to_twos(value, 8); |
724 | val = | |
725 | cx25821_i2c_read(&dev->i2c_bus[0], | |
726 | VDEC_A_HUE_CTRL + (0x200 * decoder), &tmp); | |
727 | val &= 0xFFFFFF00; | |
02b20b0b | 728 | |
1a9fc855 MCC |
729 | ret_val |= |
730 | cx25821_i2c_write(&dev->i2c_bus[0], | |
731 | VDEC_A_HUE_CTRL + (0x200 * decoder), val | value); | |
02b20b0b | 732 | |
1a9fc855 MCC |
733 | mutex_unlock(&dev->lock); |
734 | return ret_val; | |
02b20b0b MCC |
735 | } |
736 | ||
02b20b0b MCC |
737 | int medusa_set_saturation(struct cx25821_dev *dev, int saturation, int decoder) |
738 | { | |
1a9fc855 MCC |
739 | int ret_val = 0; |
740 | int value = 0; | |
741 | u32 val = 0, tmp = 0; | |
742 | ||
743 | mutex_lock(&dev->lock); | |
744 | ||
745 | if ((saturation > VIDEO_PROCAMP_MAX) | |
746 | || (saturation < VIDEO_PROCAMP_MIN)) { | |
747 | mutex_unlock(&dev->lock); | |
748 | return -1; | |
749 | } | |
750 | ||
751 | ret_val = | |
752 | mapM(VIDEO_PROCAMP_MIN, VIDEO_PROCAMP_MAX, saturation, | |
753 | UNSIGNED_BYTE_MIN, UNSIGNED_BYTE_MAX, &value); | |
754 | ||
755 | val = | |
756 | cx25821_i2c_read(&dev->i2c_bus[0], | |
757 | VDEC_A_USAT_CTRL + (0x200 * decoder), &tmp); | |
758 | val &= 0xFFFFFF00; | |
759 | ret_val |= | |
760 | cx25821_i2c_write(&dev->i2c_bus[0], | |
761 | VDEC_A_USAT_CTRL + (0x200 * decoder), | |
762 | val | value); | |
763 | ||
764 | val = | |
765 | cx25821_i2c_read(&dev->i2c_bus[0], | |
766 | VDEC_A_VSAT_CTRL + (0x200 * decoder), &tmp); | |
767 | val &= 0xFFFFFF00; | |
768 | ret_val |= | |
769 | cx25821_i2c_write(&dev->i2c_bus[0], | |
770 | VDEC_A_VSAT_CTRL + (0x200 * decoder), | |
771 | val | value); | |
bb4c9a74 | 772 | |
bb4c9a74 | 773 | mutex_unlock(&dev->lock); |
1a9fc855 | 774 | return ret_val; |
02b20b0b MCC |
775 | } |
776 | ||
0dd8be8c OP |
777 | /* Program the display sequence and monitor output. */ |
778 | ||
02b20b0b MCC |
779 | int medusa_video_init(struct cx25821_dev *dev) |
780 | { | |
64561a38 MCC |
781 | u32 value, tmp = 0; |
782 | int ret_val; | |
783 | int i; | |
bb4c9a74 | 784 | |
1a9fc855 | 785 | mutex_lock(&dev->lock); |
bb4c9a74 | 786 | |
1a9fc855 | 787 | _num_decoders = dev->_max_num_decoders; |
02b20b0b | 788 | |
0dd8be8c | 789 | /* disable Auto source selection on all video decoders */ |
1a9fc855 MCC |
790 | value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); |
791 | value &= 0xFFFFF0FF; | |
792 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); | |
64561a38 MCC |
793 | if (ret_val < 0) |
794 | goto error; | |
02b20b0b | 795 | |
0dd8be8c | 796 | /* Turn off Master source switch enable */ |
1a9fc855 MCC |
797 | value = cx25821_i2c_read(&dev->i2c_bus[0], MON_A_CTRL, &tmp); |
798 | value &= 0xFFFFFFDF; | |
799 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], MON_A_CTRL, value); | |
7a02f549 | 800 | if (ret_val < 0) |
64561a38 | 801 | goto error; |
02b20b0b | 802 | |
bb4c9a74 | 803 | mutex_unlock(&dev->lock); |
02b20b0b | 804 | |
0dd8be8c | 805 | for (i = 0; i < _num_decoders; i++) |
1a9fc855 | 806 | medusa_set_decoderduration(dev, i, _display_field_cnt[i]); |
1a9fc855 MCC |
807 | |
808 | mutex_lock(&dev->lock); | |
809 | ||
0dd8be8c | 810 | /* Select monitor as DENC A input, power up the DAC */ |
1a9fc855 MCC |
811 | value = cx25821_i2c_read(&dev->i2c_bus[0], DENC_AB_CTRL, &tmp); |
812 | value &= 0xFF70FF70; | |
0dd8be8c | 813 | value |= 0x00090008; /* set en_active */ |
1a9fc855 | 814 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], DENC_AB_CTRL, value); |
64561a38 MCC |
815 | if (ret_val < 0) |
816 | goto error; | |
1a9fc855 | 817 | |
0dd8be8c | 818 | /* enable input is VIP/656 */ |
1a9fc855 | 819 | value = cx25821_i2c_read(&dev->i2c_bus[0], BYP_AB_CTRL, &tmp); |
0dd8be8c | 820 | value |= 0x00040100; /* enable VIP */ |
1a9fc855 MCC |
821 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], BYP_AB_CTRL, value); |
822 | ||
64561a38 MCC |
823 | if (ret_val < 0) |
824 | goto error; | |
825 | ||
0dd8be8c | 826 | /* select AFE clock to output mode */ |
1a9fc855 MCC |
827 | value = cx25821_i2c_read(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, &tmp); |
828 | value &= 0x83FFFFFF; | |
64561a38 MCC |
829 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], AFE_AB_DIAG_CTRL, |
830 | value | 0x10000000); | |
831 | if (ret_val < 0) | |
832 | goto error; | |
1a9fc855 | 833 | |
0dd8be8c | 834 | /* Turn on all of the data out and control output pins. */ |
1a9fc855 MCC |
835 | value = cx25821_i2c_read(&dev->i2c_bus[0], PIN_OE_CTRL, &tmp); |
836 | value &= 0xFEF0FE00; | |
837 | if (_num_decoders == MAX_DECODERS) { | |
0dd8be8c OP |
838 | /* |
839 | * Note: The octal board does not support control pins(bit16-19) | |
840 | * These bits are ignored in the octal board. | |
841 | * | |
842 | * disable VDEC A-C port, default to Mobilygen Interface | |
843 | */ | |
844 | value |= 0x010001F8; | |
1a9fc855 | 845 | } else { |
0dd8be8c OP |
846 | /* disable VDEC A-C port, default to Mobilygen Interface */ |
847 | value |= 0x010F0108; | |
1a9fc855 MCC |
848 | } |
849 | ||
850 | value |= 7; | |
851 | ret_val = cx25821_i2c_write(&dev->i2c_bus[0], PIN_OE_CTRL, value); | |
64561a38 MCC |
852 | if (ret_val < 0) |
853 | goto error; | |
bb4c9a74 | 854 | |
bb4c9a74 | 855 | mutex_unlock(&dev->lock); |
02b20b0b | 856 | |
1a9fc855 | 857 | ret_val = medusa_set_videostandard(dev); |
64561a38 | 858 | return ret_val; |
bb4c9a74 | 859 | |
64561a38 MCC |
860 | error: |
861 | mutex_unlock(&dev->lock); | |
862 | return ret_val; | |
02b20b0b | 863 | } |