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