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