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