diff options
Diffstat (limited to 'drivers/media/video/cx25840/cx25840-vbi.c')
-rw-r--r-- | drivers/media/video/cx25840/cx25840-vbi.c | 177 |
1 files changed, 130 insertions, 47 deletions
diff --git a/drivers/media/video/cx25840/cx25840-vbi.c b/drivers/media/video/cx25840/cx25840-vbi.c index 57feca288d2b..6cc8bf215e85 100644 --- a/drivers/media/video/cx25840/cx25840-vbi.c +++ b/drivers/media/video/cx25840/cx25840-vbi.c | |||
@@ -84,67 +84,140 @@ static int decode_vps(u8 * dst, u8 * p) | |||
84 | 84 | ||
85 | void cx25840_vbi_setup(struct i2c_client *client) | 85 | void cx25840_vbi_setup(struct i2c_client *client) |
86 | { | 86 | { |
87 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
87 | v4l2_std_id std = cx25840_get_v4lstd(client); | 88 | v4l2_std_id std = cx25840_get_v4lstd(client); |
89 | int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation; | ||
90 | int luma_lpf,uv_lpf, comb; | ||
91 | u32 pll_int,pll_frac,pll_post; | ||
88 | 92 | ||
93 | /* datasheet startup, step 8d */ | ||
89 | if (std & ~V4L2_STD_NTSC) { | 94 | if (std & ~V4L2_STD_NTSC) { |
90 | /* datasheet startup, step 8d */ | ||
91 | cx25840_write(client, 0x49f, 0x11); | 95 | cx25840_write(client, 0x49f, 0x11); |
96 | } else { | ||
97 | cx25840_write(client, 0x49f, 0x14); | ||
98 | } | ||
92 | 99 | ||
93 | cx25840_write(client, 0x470, 0x84); | 100 | if (std & V4L2_STD_625_50) { |
94 | cx25840_write(client, 0x471, 0x00); | 101 | hblank=0x084; |
95 | cx25840_write(client, 0x472, 0x2d); | 102 | hactive=0x2d0; |
96 | cx25840_write(client, 0x473, 0x5d); | 103 | burst=0x5d; |
97 | 104 | vblank=0x024; | |
98 | cx25840_write(client, 0x474, 0x24); | 105 | vactive=0x244; |
99 | cx25840_write(client, 0x475, 0x40); | 106 | vblank656=0x28; |
100 | cx25840_write(client, 0x476, 0x24); | 107 | src_decimation=0x21f; |
101 | cx25840_write(client, 0x477, 0x28); | ||
102 | |||
103 | cx25840_write(client, 0x478, 0x1f); | ||
104 | cx25840_write(client, 0x479, 0x02); | ||
105 | 108 | ||
109 | luma_lpf=2; | ||
106 | if (std & V4L2_STD_SECAM) { | 110 | if (std & V4L2_STD_SECAM) { |
107 | cx25840_write(client, 0x47a, 0x80); | 111 | uv_lpf=0; |
108 | cx25840_write(client, 0x47b, 0x00); | 112 | comb=0; |
109 | cx25840_write(client, 0x47c, 0x5f); | 113 | sc=0x0a425f; |
110 | cx25840_write(client, 0x47d, 0x42); | ||
111 | } else { | 114 | } else { |
112 | cx25840_write(client, 0x47a, 0x90); | 115 | uv_lpf=1; |
113 | cx25840_write(client, 0x47b, 0x20); | 116 | comb=0x20; |
114 | cx25840_write(client, 0x47c, 0x63); | 117 | sc=0x0a8263; |
115 | cx25840_write(client, 0x47d, 0x82); | ||
116 | } | 118 | } |
117 | |||
118 | cx25840_write(client, 0x47e, 0x0a); | ||
119 | cx25840_write(client, 0x47f, 0x01); | ||
120 | } else { | 119 | } else { |
121 | /* datasheet startup, step 8d */ | 120 | hactive=720; |
122 | cx25840_write(client, 0x49f, 0x14); | 121 | hblank=122; |
122 | vactive=487; | ||
123 | luma_lpf=1; | ||
124 | uv_lpf=1; | ||
125 | |||
126 | src_decimation=0x21f; | ||
127 | if (std == V4L2_STD_PAL_M) { | ||
128 | vblank=20; | ||
129 | vblank656=24; | ||
130 | burst=0x61; | ||
131 | comb=0x20; | ||
132 | |||
133 | sc=555452; | ||
134 | } else { | ||
135 | vblank=26; | ||
136 | vblank656=26; | ||
137 | burst=0x5b; | ||
138 | comb=0x66; | ||
139 | sc=556063; | ||
140 | } | ||
141 | } | ||
142 | |||
143 | /* DEBUG: Displays configured PLL frequency */ | ||
144 | pll_int=cx25840_read(client, 0x108); | ||
145 | pll_frac=cx25840_read4(client, 0x10c)&0x1ffffff; | ||
146 | pll_post=cx25840_read(client, 0x109); | ||
147 | v4l_dbg(1, cx25840_debug, client, | ||
148 | "PLL regs = int: %u, frac: %u, post: %u\n", | ||
149 | pll_int,pll_frac,pll_post); | ||
150 | |||
151 | if (pll_post) { | ||
152 | int fin, fsc; | ||
153 | int pll= (28636363L*((((u64)pll_int)<<25L)+pll_frac)) >>25L; | ||
154 | |||
155 | pll/=pll_post; | ||
156 | v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n", | ||
157 | pll/1000000, pll%1000000); | ||
158 | v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n", | ||
159 | pll/8000000, (pll/8)%1000000); | ||
160 | |||
161 | fin=((u64)src_decimation*pll)>>12; | ||
162 | v4l_dbg(1, cx25840_debug, client, "ADC Sampling freq = " | ||
163 | "%d.%06d MHz\n", | ||
164 | fin/1000000,fin%1000000); | ||
165 | |||
166 | fsc= (((u64)sc)*pll) >> 24L; | ||
167 | v4l_dbg(1, cx25840_debug, client, "Chroma sub-carrier freq = " | ||
168 | "%d.%06d MHz\n", | ||
169 | fsc/1000000,fsc%1000000); | ||
170 | |||
171 | v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, " | ||
172 | "vblank %i , vactive %i, vblank656 %i, src_dec %i," | ||
173 | "burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x," | ||
174 | " sc 0x%06x\n", | ||
175 | hblank, hactive, vblank, vactive, vblank656, | ||
176 | src_decimation, burst, luma_lpf, uv_lpf, comb, sc); | ||
177 | } | ||
178 | |||
179 | /* Sets horizontal blanking delay and active lines */ | ||
180 | cx25840_write(client, 0x470, hblank); | ||
181 | cx25840_write(client, 0x471, 0xff&(((hblank>>8)&0x3)|(hactive <<4))); | ||
182 | cx25840_write(client, 0x472, hactive>>4); | ||
183 | |||
184 | /* Sets burst gate delay */ | ||
185 | cx25840_write(client, 0x473, burst); | ||
123 | 186 | ||
124 | cx25840_write(client, 0x470, 0x7a); | 187 | /* Sets vertical blanking delay and active duration */ |
125 | cx25840_write(client, 0x471, 0x00); | 188 | cx25840_write(client, 0x474, vblank); |
126 | cx25840_write(client, 0x472, 0x2d); | 189 | cx25840_write(client, 0x475, 0xff&(((vblank>>8)&0x3)|(vactive <<4))); |
127 | cx25840_write(client, 0x473, 0x5b); | 190 | cx25840_write(client, 0x476, vactive>>4); |
191 | cx25840_write(client, 0x477, vblank656); | ||
128 | 192 | ||
129 | cx25840_write(client, 0x474, 0x1a); | 193 | /* Sets src decimation rate */ |
130 | cx25840_write(client, 0x475, 0x70); | 194 | cx25840_write(client, 0x478, 0xff&src_decimation); |
131 | cx25840_write(client, 0x476, 0x1e); | 195 | cx25840_write(client, 0x479, 0xff&(src_decimation>>8)); |
132 | cx25840_write(client, 0x477, 0x1e); | ||
133 | 196 | ||
134 | cx25840_write(client, 0x478, 0x1f); | 197 | /* Sets Luma and UV Low pass filters */ |
135 | cx25840_write(client, 0x479, 0x02); | 198 | cx25840_write(client, 0x47a, luma_lpf<<6|((uv_lpf<<4)&0x30)); |
136 | cx25840_write(client, 0x47a, 0x50); | ||
137 | cx25840_write(client, 0x47b, 0x66); | ||
138 | 199 | ||
139 | cx25840_write(client, 0x47c, 0x1f); | 200 | /* Enables comb filters */ |
140 | cx25840_write(client, 0x47d, 0x7c); | 201 | cx25840_write(client, 0x47b, comb); |
141 | cx25840_write(client, 0x47e, 0x08); | 202 | |
203 | /* Sets SC Step*/ | ||
204 | cx25840_write(client, 0x47c, sc); | ||
205 | cx25840_write(client, 0x47d, 0xff&sc>>8); | ||
206 | cx25840_write(client, 0x47e, 0xff&sc>>16); | ||
207 | |||
208 | /* Sets VBI parameters */ | ||
209 | if (std & V4L2_STD_625_50) { | ||
210 | cx25840_write(client, 0x47f, 0x01); | ||
211 | state->vbi_line_offset = 5; | ||
212 | } else { | ||
142 | cx25840_write(client, 0x47f, 0x00); | 213 | cx25840_write(client, 0x47f, 0x00); |
214 | state->vbi_line_offset = 8; | ||
143 | } | 215 | } |
144 | } | 216 | } |
145 | 217 | ||
146 | int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | 218 | int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) |
147 | { | 219 | { |
220 | struct cx25840_state *state = i2c_get_clientdata(client); | ||
148 | struct v4l2_format *fmt; | 221 | struct v4l2_format *fmt; |
149 | struct v4l2_sliced_vbi_format *svbi; | 222 | struct v4l2_sliced_vbi_format *svbi; |
150 | 223 | ||
@@ -182,7 +255,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | |||
182 | 255 | ||
183 | case VIDIOC_S_FMT: | 256 | case VIDIOC_S_FMT: |
184 | { | 257 | { |
185 | int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC); | 258 | int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60); |
186 | int vbi_offset = is_pal ? 1 : 0; | 259 | int vbi_offset = is_pal ? 1 : 0; |
187 | int i, x; | 260 | int i, x; |
188 | u8 lcr[24]; | 261 | u8 lcr[24]; |
@@ -211,7 +284,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | |||
211 | cx25840_vbi_setup(client); | 284 | cx25840_vbi_setup(client); |
212 | 285 | ||
213 | /* Sliced VBI */ | 286 | /* Sliced VBI */ |
214 | cx25840_write(client, 0x404, 0x36); /* Ancillery data */ | 287 | cx25840_write(client, 0x404, 0x32); /* Ancillary data */ |
215 | cx25840_write(client, 0x406, 0x13); | 288 | cx25840_write(client, 0x406, 0x13); |
216 | cx25840_write(client, 0x47f, vbi_offset); | 289 | cx25840_write(client, 0x47f, vbi_offset); |
217 | 290 | ||
@@ -248,8 +321,18 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | |||
248 | } | 321 | } |
249 | } | 322 | } |
250 | 323 | ||
251 | for (x = 1, i = 0x424; i <= 0x434; i++, x++) { | 324 | if (is_pal) { |
252 | cx25840_write(client, i, lcr[6 + x]); | 325 | for (x = 1, i = 0x424; i <= 0x434; i++, x++) { |
326 | cx25840_write(client, i, lcr[6 + x]); | ||
327 | } | ||
328 | } | ||
329 | else { | ||
330 | for (x = 1, i = 0x424; i <= 0x430; i++, x++) { | ||
331 | cx25840_write(client, i, lcr[9 + x]); | ||
332 | } | ||
333 | for (i = 0x431; i <= 0x434; i++) { | ||
334 | cx25840_write(client, i, 0); | ||
335 | } | ||
253 | } | 336 | } |
254 | 337 | ||
255 | cx25840_write(client, 0x43c, 0x16); | 338 | cx25840_write(client, 0x43c, 0x16); |
@@ -257,7 +340,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | |||
257 | if (is_pal) { | 340 | if (is_pal) { |
258 | cx25840_write(client, 0x474, 0x2a); | 341 | cx25840_write(client, 0x474, 0x2a); |
259 | } else { | 342 | } else { |
260 | cx25840_write(client, 0x474, 0x1a + 6); | 343 | cx25840_write(client, 0x474, 0x22); |
261 | } | 344 | } |
262 | break; | 345 | break; |
263 | } | 346 | } |
@@ -278,7 +361,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) | |||
278 | id1 = p[-1]; | 361 | id1 = p[-1]; |
279 | id2 = p[0] & 0xf; | 362 | id2 = p[0] & 0xf; |
280 | l = p[2] & 0x3f; | 363 | l = p[2] & 0x3f; |
281 | l += 5; | 364 | l += state->vbi_line_offset; |
282 | p += 4; | 365 | p += 4; |
283 | 366 | ||
284 | switch (id2) { | 367 | switch (id2) { |