1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * Copyright (C) 2005-2006 Micronas USA Inc. |
4 | */ |
5 | |
6 | #include <linux/module.h> |
7 | #include <linux/delay.h> |
8 | #include <linux/sched.h> |
9 | #include <linux/spinlock.h> |
10 | #include <linux/unistd.h> |
11 | #include <linux/time.h> |
12 | #include <linux/mm.h> |
13 | #include <linux/vmalloc.h> |
14 | #include <linux/device.h> |
15 | #include <linux/i2c.h> |
16 | #include <linux/firmware.h> |
17 | #include <linux/mutex.h> |
18 | #include <linux/uaccess.h> |
19 | #include <linux/slab.h> |
20 | #include <linux/videodev2.h> |
21 | #include <media/tuner.h> |
22 | #include <media/v4l2-common.h> |
23 | #include <media/v4l2-event.h> |
24 | |
25 | #include "go7007-priv.h" |
26 | |
27 | /* |
28 | * Wait for an interrupt to be delivered from the GO7007SB and return |
29 | * the associated value and data. |
30 | * |
31 | * Must be called with the hw_lock held. |
32 | */ |
33 | int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data) |
34 | { |
35 | go->interrupt_available = 0; |
36 | go->hpi_ops->read_interrupt(go); |
37 | if (wait_event_timeout(go->interrupt_waitq, |
38 | go->interrupt_available, 5*HZ) < 0) { |
39 | v4l2_err(&go->v4l2_dev, "timeout waiting for read interrupt\n" ); |
40 | return -1; |
41 | } |
42 | if (!go->interrupt_available) |
43 | return -1; |
44 | go->interrupt_available = 0; |
45 | *value = go->interrupt_value & 0xfffe; |
46 | *data = go->interrupt_data; |
47 | return 0; |
48 | } |
49 | EXPORT_SYMBOL(go7007_read_interrupt); |
50 | |
51 | /* |
52 | * Read a register/address on the GO7007SB. |
53 | * |
54 | * Must be called with the hw_lock held. |
55 | */ |
56 | int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data) |
57 | { |
58 | int count = 100; |
59 | u16 value; |
60 | |
61 | if (go7007_write_interrupt(go, 0x0010, addr) < 0) |
62 | return -EIO; |
63 | while (count-- > 0) { |
64 | if (go7007_read_interrupt(go, &value, data) == 0 && |
65 | value == 0xa000) |
66 | return 0; |
67 | } |
68 | return -EIO; |
69 | } |
70 | EXPORT_SYMBOL(go7007_read_addr); |
71 | |
72 | /* |
73 | * Send the boot firmware to the encoder, which just wakes it up and lets |
74 | * us talk to the GPIO pins and on-board I2C adapter. |
75 | * |
76 | * Must be called with the hw_lock held. |
77 | */ |
78 | static int go7007_load_encoder(struct go7007 *go) |
79 | { |
80 | const struct firmware *fw_entry; |
81 | char fw_name[] = "go7007/go7007fw.bin" ; |
82 | void *bounce; |
83 | int fw_len; |
84 | u16 intr_val, intr_data; |
85 | |
86 | if (go->boot_fw == NULL) { |
87 | if (request_firmware(fw: &fw_entry, name: fw_name, device: go->dev)) { |
88 | v4l2_err(go, "unable to load firmware from file \"%s\"\n" , fw_name); |
89 | return -1; |
90 | } |
91 | if (fw_entry->size < 16 || memcmp(p: fw_entry->data, q: "WISGO7007FW" , size: 11)) { |
92 | v4l2_err(go, "file \"%s\" does not appear to be go7007 firmware\n" , fw_name); |
93 | release_firmware(fw: fw_entry); |
94 | return -1; |
95 | } |
96 | fw_len = fw_entry->size - 16; |
97 | bounce = kmemdup(p: fw_entry->data + 16, size: fw_len, GFP_KERNEL); |
98 | if (bounce == NULL) { |
99 | v4l2_err(go, "unable to allocate %d bytes for firmware transfer\n" , fw_len); |
100 | release_firmware(fw: fw_entry); |
101 | return -1; |
102 | } |
103 | release_firmware(fw: fw_entry); |
104 | go->boot_fw_len = fw_len; |
105 | go->boot_fw = bounce; |
106 | } |
107 | if (go7007_interface_reset(go) < 0 || |
108 | go7007_send_firmware(go, go->boot_fw, go->boot_fw_len) < 0 || |
109 | go7007_read_interrupt(go, &intr_val, &intr_data) < 0 || |
110 | (intr_val & ~0x1) != 0x5a5a) { |
111 | v4l2_err(go, "error transferring firmware\n" ); |
112 | kfree(objp: go->boot_fw); |
113 | go->boot_fw = NULL; |
114 | return -1; |
115 | } |
116 | return 0; |
117 | } |
118 | |
119 | MODULE_FIRMWARE("go7007/go7007fw.bin" ); |
120 | |
121 | /* |
122 | * Boot the encoder and register the I2C adapter if requested. Do the |
123 | * minimum initialization necessary, since the board-specific code may |
124 | * still need to probe the board ID. |
125 | * |
126 | * Must NOT be called with the hw_lock held. |
127 | */ |
128 | int go7007_boot_encoder(struct go7007 *go, int init_i2c) |
129 | { |
130 | int ret; |
131 | |
132 | mutex_lock(&go->hw_lock); |
133 | ret = go7007_load_encoder(go); |
134 | mutex_unlock(lock: &go->hw_lock); |
135 | if (ret < 0) |
136 | return -1; |
137 | if (!init_i2c) |
138 | return 0; |
139 | if (go7007_i2c_init(go) < 0) |
140 | return -1; |
141 | go->i2c_adapter_online = 1; |
142 | return 0; |
143 | } |
144 | EXPORT_SYMBOL(go7007_boot_encoder); |
145 | |
146 | /* |
147 | * Configure any hardware-related registers in the GO7007, such as GPIO |
148 | * pins and bus parameters, which are board-specific. This assumes |
149 | * the boot firmware has already been downloaded. |
150 | * |
151 | * Must be called with the hw_lock held. |
152 | */ |
153 | static int go7007_init_encoder(struct go7007 *go) |
154 | { |
155 | if (go->board_info->audio_flags & GO7007_AUDIO_I2S_MASTER) { |
156 | go7007_write_addr(go, 0x1000, 0x0811); |
157 | go7007_write_addr(go, 0x1000, 0x0c11); |
158 | } |
159 | switch (go->board_id) { |
160 | case GO7007_BOARDID_MATRIX_REV: |
161 | /* Set GPIO pin 0 to be an output (audio clock control) */ |
162 | go7007_write_addr(go, 0x3c82, 0x0001); |
163 | go7007_write_addr(go, 0x3c80, 0x00fe); |
164 | break; |
165 | case GO7007_BOARDID_ADLINK_MPG24: |
166 | /* set GPIO5 to be an output, currently low */ |
167 | go7007_write_addr(go, 0x3c82, 0x0000); |
168 | go7007_write_addr(go, 0x3c80, 0x00df); |
169 | break; |
170 | case GO7007_BOARDID_ADS_USBAV_709: |
171 | /* GPIO pin 0: audio clock control */ |
172 | /* pin 2: TW9906 reset */ |
173 | /* pin 3: capture LED */ |
174 | go7007_write_addr(go, 0x3c82, 0x000d); |
175 | go7007_write_addr(go, 0x3c80, 0x00f2); |
176 | break; |
177 | } |
178 | return 0; |
179 | } |
180 | |
181 | /* |
182 | * Send the boot firmware to the GO7007 and configure the registers. This |
183 | * is the only way to stop the encoder once it has started streaming video. |
184 | * |
185 | * Must be called with the hw_lock held. |
186 | */ |
187 | int go7007_reset_encoder(struct go7007 *go) |
188 | { |
189 | if (go7007_load_encoder(go) < 0) |
190 | return -1; |
191 | return go7007_init_encoder(go); |
192 | } |
193 | |
194 | /* |
195 | * Attempt to instantiate an I2C client by ID, probably loading a module. |
196 | */ |
197 | static int init_i2c_module(struct i2c_adapter *adapter, const struct go_i2c *const i2c) |
198 | { |
199 | struct go7007 *go = i2c_get_adapdata(adap: adapter); |
200 | struct v4l2_device *v4l2_dev = &go->v4l2_dev; |
201 | struct v4l2_subdev *sd; |
202 | struct i2c_board_info info; |
203 | |
204 | memset(&info, 0, sizeof(info)); |
205 | strscpy(info.type, i2c->type, sizeof(info.type)); |
206 | info.addr = i2c->addr; |
207 | info.flags = i2c->flags; |
208 | |
209 | sd = v4l2_i2c_new_subdev_board(v4l2_dev, adapter, info: &info, NULL); |
210 | if (sd) { |
211 | if (i2c->is_video) |
212 | go->sd_video = sd; |
213 | if (i2c->is_audio) |
214 | go->sd_audio = sd; |
215 | return 0; |
216 | } |
217 | |
218 | pr_info("go7007: probing for module i2c:%s failed\n" , i2c->type); |
219 | return -EINVAL; |
220 | } |
221 | |
222 | /* |
223 | * Detach and unregister the encoder. The go7007 struct won't be freed |
224 | * until v4l2 finishes releasing its resources and all associated fds are |
225 | * closed by applications. |
226 | */ |
227 | static void go7007_remove(struct v4l2_device *v4l2_dev) |
228 | { |
229 | struct go7007 *go = container_of(v4l2_dev, struct go7007, v4l2_dev); |
230 | |
231 | v4l2_device_unregister(v4l2_dev); |
232 | if (go->hpi_ops->release) |
233 | go->hpi_ops->release(go); |
234 | if (go->i2c_adapter_online) { |
235 | i2c_del_adapter(adap: &go->i2c_adapter); |
236 | go->i2c_adapter_online = 0; |
237 | } |
238 | |
239 | kfree(objp: go->boot_fw); |
240 | go7007_v4l2_remove(go); |
241 | kfree(objp: go); |
242 | } |
243 | |
244 | /* |
245 | * Finalize the GO7007 hardware setup, register the on-board I2C adapter |
246 | * (if used on this board), load the I2C client driver for the sensor |
247 | * (SAA7115 or whatever) and other devices, and register the ALSA and V4L2 |
248 | * interfaces. |
249 | * |
250 | * Must NOT be called with the hw_lock held. |
251 | */ |
252 | int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs) |
253 | { |
254 | int i, ret; |
255 | |
256 | dev_info(go->dev, "go7007: registering new %s\n" , go->name); |
257 | |
258 | go->v4l2_dev.release = go7007_remove; |
259 | ret = v4l2_device_register(dev: go->dev, v4l2_dev: &go->v4l2_dev); |
260 | if (ret < 0) |
261 | return ret; |
262 | |
263 | mutex_lock(&go->hw_lock); |
264 | ret = go7007_init_encoder(go); |
265 | mutex_unlock(lock: &go->hw_lock); |
266 | if (ret < 0) |
267 | return ret; |
268 | |
269 | ret = go7007_v4l2_ctrl_init(go); |
270 | if (ret < 0) |
271 | return ret; |
272 | |
273 | if (!go->i2c_adapter_online && |
274 | go->board_info->flags & GO7007_BOARD_USE_ONBOARD_I2C) { |
275 | ret = go7007_i2c_init(go); |
276 | if (ret < 0) |
277 | return ret; |
278 | go->i2c_adapter_online = 1; |
279 | } |
280 | if (go->i2c_adapter_online) { |
281 | if (go->board_id == GO7007_BOARDID_ADS_USBAV_709) { |
282 | /* Reset the TW9906 */ |
283 | go7007_write_addr(go, 0x3c82, 0x0009); |
284 | msleep(msecs: 50); |
285 | go7007_write_addr(go, 0x3c82, 0x000d); |
286 | } |
287 | for (i = 0; i < num_i2c_devs; ++i) |
288 | init_i2c_module(adapter: &go->i2c_adapter, i2c: &go->board_info->i2c_devs[i]); |
289 | |
290 | if (go->tuner_type >= 0) { |
291 | struct tuner_setup setup = { |
292 | .addr = ADDR_UNSET, |
293 | .type = go->tuner_type, |
294 | .mode_mask = T_ANALOG_TV, |
295 | }; |
296 | |
297 | v4l2_device_call_all(&go->v4l2_dev, 0, tuner, |
298 | s_type_addr, &setup); |
299 | } |
300 | if (go->board_id == GO7007_BOARDID_ADLINK_MPG24) |
301 | v4l2_subdev_call(go->sd_video, video, s_routing, |
302 | 0, 0, go->channel_number + 1); |
303 | } |
304 | |
305 | ret = go7007_v4l2_init(go); |
306 | if (ret < 0) |
307 | return ret; |
308 | |
309 | if (go->board_info->flags & GO7007_BOARD_HAS_AUDIO) { |
310 | go->audio_enabled = 1; |
311 | go7007_snd_init(go); |
312 | } |
313 | return 0; |
314 | } |
315 | EXPORT_SYMBOL(go7007_register_encoder); |
316 | |
317 | /* |
318 | * Send the encode firmware to the encoder, which will cause it |
319 | * to immediately start delivering the video and audio streams. |
320 | * |
321 | * Must be called with the hw_lock held. |
322 | */ |
323 | int go7007_start_encoder(struct go7007 *go) |
324 | { |
325 | u8 *fw; |
326 | int fw_len, rv = 0, i, x, y; |
327 | u16 intr_val, intr_data; |
328 | |
329 | go->modet_enable = 0; |
330 | for (i = 0; i < 4; i++) |
331 | go->modet[i].enable = 0; |
332 | |
333 | switch (v4l2_ctrl_g_ctrl(ctrl: go->modet_mode)) { |
334 | case V4L2_DETECT_MD_MODE_GLOBAL: |
335 | memset(go->modet_map, 0, sizeof(go->modet_map)); |
336 | go->modet[0].enable = 1; |
337 | go->modet_enable = 1; |
338 | break; |
339 | case V4L2_DETECT_MD_MODE_REGION_GRID: |
340 | for (y = 0; y < go->height / 16; y++) { |
341 | for (x = 0; x < go->width / 16; x++) { |
342 | int idx = y * go->width / 16 + x; |
343 | |
344 | go->modet[go->modet_map[idx]].enable = 1; |
345 | } |
346 | } |
347 | go->modet_enable = 1; |
348 | break; |
349 | } |
350 | |
351 | if (go->dvd_mode) |
352 | go->modet_enable = 0; |
353 | |
354 | if (go7007_construct_fw_image(go, fw: &fw, fwlen: &fw_len) < 0) |
355 | return -1; |
356 | |
357 | if (go7007_send_firmware(go, fw, fw_len) < 0 || |
358 | go7007_read_interrupt(go, &intr_val, &intr_data) < 0) { |
359 | v4l2_err(&go->v4l2_dev, "error transferring firmware\n" ); |
360 | rv = -1; |
361 | goto start_error; |
362 | } |
363 | |
364 | go->state = STATE_DATA; |
365 | go->parse_length = 0; |
366 | go->seen_frame = 0; |
367 | if (go7007_stream_start(go) < 0) { |
368 | v4l2_err(&go->v4l2_dev, "error starting stream transfer\n" ); |
369 | rv = -1; |
370 | goto start_error; |
371 | } |
372 | |
373 | start_error: |
374 | kfree(objp: fw); |
375 | return rv; |
376 | } |
377 | |
378 | /* |
379 | * Store a byte in the current video buffer, if there is one. |
380 | */ |
381 | static inline void store_byte(struct go7007_buffer *vb, u8 byte) |
382 | { |
383 | if (vb && vb->vb.vb2_buf.planes[0].bytesused < GO7007_BUF_SIZE) { |
384 | u8 *ptr = vb2_plane_vaddr(vb: &vb->vb.vb2_buf, plane_no: 0); |
385 | |
386 | ptr[vb->vb.vb2_buf.planes[0].bytesused++] = byte; |
387 | } |
388 | } |
389 | |
390 | static void go7007_set_motion_regions(struct go7007 *go, struct go7007_buffer *vb, |
391 | u32 motion_regions) |
392 | { |
393 | if (motion_regions != go->modet_event_status) { |
394 | struct v4l2_event ev = { |
395 | .type = V4L2_EVENT_MOTION_DET, |
396 | .u.motion_det = { |
397 | .flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ, |
398 | .frame_sequence = vb->vb.sequence, |
399 | .region_mask = motion_regions, |
400 | }, |
401 | }; |
402 | |
403 | v4l2_event_queue(vdev: &go->vdev, ev: &ev); |
404 | go->modet_event_status = motion_regions; |
405 | } |
406 | } |
407 | |
408 | /* |
409 | * Determine regions with motion and send a motion detection event |
410 | * in case of changes. |
411 | */ |
412 | static void go7007_motion_regions(struct go7007 *go, struct go7007_buffer *vb) |
413 | { |
414 | u32 *bytesused = &vb->vb.vb2_buf.planes[0].bytesused; |
415 | unsigned motion[4] = { 0, 0, 0, 0 }; |
416 | u32 motion_regions = 0; |
417 | unsigned stride = (go->width + 7) >> 3; |
418 | unsigned x, y; |
419 | int i; |
420 | |
421 | for (i = 0; i < 216; ++i) |
422 | store_byte(vb, byte: go->active_map[i]); |
423 | for (y = 0; y < go->height / 16; y++) { |
424 | for (x = 0; x < go->width / 16; x++) { |
425 | if (!(go->active_map[y * stride + (x >> 3)] & (1 << (x & 7)))) |
426 | continue; |
427 | motion[go->modet_map[y * (go->width / 16) + x]]++; |
428 | } |
429 | } |
430 | motion_regions = ((motion[0] > 0) << 0) | |
431 | ((motion[1] > 0) << 1) | |
432 | ((motion[2] > 0) << 2) | |
433 | ((motion[3] > 0) << 3); |
434 | *bytesused -= 216; |
435 | go7007_set_motion_regions(go, vb, motion_regions); |
436 | } |
437 | |
438 | /* |
439 | * Deliver the last video buffer and get a new one to start writing to. |
440 | */ |
441 | static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buffer *vb) |
442 | { |
443 | u32 *bytesused; |
444 | struct go7007_buffer *vb_tmp = NULL; |
445 | unsigned long flags; |
446 | |
447 | if (vb == NULL) { |
448 | spin_lock_irqsave(&go->spinlock, flags); |
449 | if (!list_empty(head: &go->vidq_active)) |
450 | vb = go->active_buf = |
451 | list_first_entry(&go->vidq_active, struct go7007_buffer, list); |
452 | spin_unlock_irqrestore(lock: &go->spinlock, flags); |
453 | go->next_seq++; |
454 | return vb; |
455 | } |
456 | bytesused = &vb->vb.vb2_buf.planes[0].bytesused; |
457 | |
458 | vb->vb.sequence = go->next_seq++; |
459 | if (vb->modet_active && *bytesused + 216 < GO7007_BUF_SIZE) |
460 | go7007_motion_regions(go, vb); |
461 | else |
462 | go7007_set_motion_regions(go, vb, motion_regions: 0); |
463 | |
464 | vb->vb.vb2_buf.timestamp = ktime_get_ns(); |
465 | vb_tmp = vb; |
466 | spin_lock_irqsave(&go->spinlock, flags); |
467 | list_del(entry: &vb->list); |
468 | if (list_empty(head: &go->vidq_active)) |
469 | vb = NULL; |
470 | else |
471 | vb = list_first_entry(&go->vidq_active, |
472 | struct go7007_buffer, list); |
473 | go->active_buf = vb; |
474 | spin_unlock_irqrestore(lock: &go->spinlock, flags); |
475 | vb2_buffer_done(vb: &vb_tmp->vb.vb2_buf, state: VB2_BUF_STATE_DONE); |
476 | return vb; |
477 | } |
478 | |
479 | static void write_bitmap_word(struct go7007 *go) |
480 | { |
481 | int x, y, i, stride = ((go->width >> 4) + 7) >> 3; |
482 | |
483 | for (i = 0; i < 16; ++i) { |
484 | y = (((go->parse_length - 1) << 3) + i) / (go->width >> 4); |
485 | x = (((go->parse_length - 1) << 3) + i) % (go->width >> 4); |
486 | if (stride * y + (x >> 3) < sizeof(go->active_map)) |
487 | go->active_map[stride * y + (x >> 3)] |= |
488 | (go->modet_word & 1) << (x & 0x7); |
489 | go->modet_word >>= 1; |
490 | } |
491 | } |
492 | |
493 | /* |
494 | * Parse a chunk of the video stream into frames. The frames are not |
495 | * delimited by the hardware, so we have to parse the frame boundaries |
496 | * based on the type of video stream we're receiving. |
497 | */ |
498 | void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length) |
499 | { |
500 | struct go7007_buffer *vb = go->active_buf; |
501 | int i, seq_start_code = -1, gop_start_code = -1, frame_start_code = -1; |
502 | |
503 | switch (go->format) { |
504 | case V4L2_PIX_FMT_MPEG4: |
505 | seq_start_code = 0xB0; |
506 | gop_start_code = 0xB3; |
507 | frame_start_code = 0xB6; |
508 | break; |
509 | case V4L2_PIX_FMT_MPEG1: |
510 | case V4L2_PIX_FMT_MPEG2: |
511 | seq_start_code = 0xB3; |
512 | gop_start_code = 0xB8; |
513 | frame_start_code = 0x00; |
514 | break; |
515 | } |
516 | |
517 | for (i = 0; i < length; ++i) { |
518 | if (vb && vb->vb.vb2_buf.planes[0].bytesused >= |
519 | GO7007_BUF_SIZE - 3) { |
520 | v4l2_info(&go->v4l2_dev, "dropping oversized frame\n" ); |
521 | vb2_set_plane_payload(vb: &vb->vb.vb2_buf, plane_no: 0, size: 0); |
522 | vb->frame_offset = 0; |
523 | vb->modet_active = 0; |
524 | vb = go->active_buf = NULL; |
525 | } |
526 | |
527 | switch (go->state) { |
528 | case STATE_DATA: |
529 | switch (buf[i]) { |
530 | case 0x00: |
531 | go->state = STATE_00; |
532 | break; |
533 | case 0xFF: |
534 | go->state = STATE_FF; |
535 | break; |
536 | default: |
537 | store_byte(vb, byte: buf[i]); |
538 | break; |
539 | } |
540 | break; |
541 | case STATE_00: |
542 | switch (buf[i]) { |
543 | case 0x00: |
544 | go->state = STATE_00_00; |
545 | break; |
546 | case 0xFF: |
547 | store_byte(vb, byte: 0x00); |
548 | go->state = STATE_FF; |
549 | break; |
550 | default: |
551 | store_byte(vb, byte: 0x00); |
552 | store_byte(vb, byte: buf[i]); |
553 | go->state = STATE_DATA; |
554 | break; |
555 | } |
556 | break; |
557 | case STATE_00_00: |
558 | switch (buf[i]) { |
559 | case 0x00: |
560 | store_byte(vb, byte: 0x00); |
561 | /* go->state remains STATE_00_00 */ |
562 | break; |
563 | case 0x01: |
564 | go->state = STATE_00_00_01; |
565 | break; |
566 | case 0xFF: |
567 | store_byte(vb, byte: 0x00); |
568 | store_byte(vb, byte: 0x00); |
569 | go->state = STATE_FF; |
570 | break; |
571 | default: |
572 | store_byte(vb, byte: 0x00); |
573 | store_byte(vb, byte: 0x00); |
574 | store_byte(vb, byte: buf[i]); |
575 | go->state = STATE_DATA; |
576 | break; |
577 | } |
578 | break; |
579 | case STATE_00_00_01: |
580 | if (buf[i] == 0xF8 && go->modet_enable == 0) { |
581 | /* MODET start code, but MODET not enabled */ |
582 | store_byte(vb, byte: 0x00); |
583 | store_byte(vb, byte: 0x00); |
584 | store_byte(vb, byte: 0x01); |
585 | store_byte(vb, byte: 0xF8); |
586 | go->state = STATE_DATA; |
587 | break; |
588 | } |
589 | /* If this is the start of a new MPEG frame, |
590 | * get a new buffer */ |
591 | if ((go->format == V4L2_PIX_FMT_MPEG1 || |
592 | go->format == V4L2_PIX_FMT_MPEG2 || |
593 | go->format == V4L2_PIX_FMT_MPEG4) && |
594 | (buf[i] == seq_start_code || |
595 | buf[i] == gop_start_code || |
596 | buf[i] == frame_start_code)) { |
597 | if (vb == NULL || go->seen_frame) |
598 | vb = frame_boundary(go, vb); |
599 | go->seen_frame = buf[i] == frame_start_code; |
600 | if (vb && go->seen_frame) |
601 | vb->frame_offset = |
602 | vb->vb.vb2_buf.planes[0].bytesused; |
603 | } |
604 | /* Handle any special chunk types, or just write the |
605 | * start code to the (potentially new) buffer */ |
606 | switch (buf[i]) { |
607 | case 0xF5: /* timestamp */ |
608 | go->parse_length = 12; |
609 | go->state = STATE_UNPARSED; |
610 | break; |
611 | case 0xF6: /* vbi */ |
612 | go->state = STATE_VBI_LEN_A; |
613 | break; |
614 | case 0xF8: /* MD map */ |
615 | go->parse_length = 0; |
616 | memset(go->active_map, 0, |
617 | sizeof(go->active_map)); |
618 | go->state = STATE_MODET_MAP; |
619 | break; |
620 | case 0xFF: /* Potential JPEG start code */ |
621 | store_byte(vb, byte: 0x00); |
622 | store_byte(vb, byte: 0x00); |
623 | store_byte(vb, byte: 0x01); |
624 | go->state = STATE_FF; |
625 | break; |
626 | default: |
627 | store_byte(vb, byte: 0x00); |
628 | store_byte(vb, byte: 0x00); |
629 | store_byte(vb, byte: 0x01); |
630 | store_byte(vb, byte: buf[i]); |
631 | go->state = STATE_DATA; |
632 | break; |
633 | } |
634 | break; |
635 | case STATE_FF: |
636 | switch (buf[i]) { |
637 | case 0x00: |
638 | store_byte(vb, byte: 0xFF); |
639 | go->state = STATE_00; |
640 | break; |
641 | case 0xFF: |
642 | store_byte(vb, byte: 0xFF); |
643 | /* go->state remains STATE_FF */ |
644 | break; |
645 | case 0xD8: |
646 | if (go->format == V4L2_PIX_FMT_MJPEG) |
647 | vb = frame_boundary(go, vb); |
648 | fallthrough; |
649 | default: |
650 | store_byte(vb, byte: 0xFF); |
651 | store_byte(vb, byte: buf[i]); |
652 | go->state = STATE_DATA; |
653 | break; |
654 | } |
655 | break; |
656 | case STATE_VBI_LEN_A: |
657 | go->parse_length = buf[i] << 8; |
658 | go->state = STATE_VBI_LEN_B; |
659 | break; |
660 | case STATE_VBI_LEN_B: |
661 | go->parse_length |= buf[i]; |
662 | if (go->parse_length > 0) |
663 | go->state = STATE_UNPARSED; |
664 | else |
665 | go->state = STATE_DATA; |
666 | break; |
667 | case STATE_MODET_MAP: |
668 | if (go->parse_length < 204) { |
669 | if (go->parse_length & 1) { |
670 | go->modet_word |= buf[i]; |
671 | write_bitmap_word(go); |
672 | } else |
673 | go->modet_word = buf[i] << 8; |
674 | } else if (go->parse_length == 207 && vb) { |
675 | vb->modet_active = buf[i]; |
676 | } |
677 | if (++go->parse_length == 208) |
678 | go->state = STATE_DATA; |
679 | break; |
680 | case STATE_UNPARSED: |
681 | if (--go->parse_length == 0) |
682 | go->state = STATE_DATA; |
683 | break; |
684 | } |
685 | } |
686 | } |
687 | EXPORT_SYMBOL(go7007_parse_video_stream); |
688 | |
689 | /* |
690 | * Allocate a new go7007 struct. Used by the hardware-specific probe. |
691 | */ |
692 | struct go7007 *go7007_alloc(const struct go7007_board_info *board, |
693 | struct device *dev) |
694 | { |
695 | struct go7007 *go; |
696 | |
697 | go = kzalloc(size: sizeof(struct go7007), GFP_KERNEL); |
698 | if (go == NULL) |
699 | return NULL; |
700 | go->dev = dev; |
701 | go->board_info = board; |
702 | go->tuner_type = -1; |
703 | mutex_init(&go->hw_lock); |
704 | init_waitqueue_head(&go->frame_waitq); |
705 | spin_lock_init(&go->spinlock); |
706 | go->status = STATUS_INIT; |
707 | init_waitqueue_head(&go->interrupt_waitq); |
708 | go7007_update_board(go); |
709 | go->format = V4L2_PIX_FMT_MJPEG; |
710 | go->bitrate = 1500000; |
711 | go->fps_scale = 1; |
712 | go->aspect_ratio = GO7007_RATIO_1_1; |
713 | |
714 | return go; |
715 | } |
716 | EXPORT_SYMBOL(go7007_alloc); |
717 | |
718 | void go7007_update_board(struct go7007 *go) |
719 | { |
720 | const struct go7007_board_info *board = go->board_info; |
721 | |
722 | if (board->sensor_flags & GO7007_SENSOR_TV) { |
723 | go->standard = GO7007_STD_NTSC; |
724 | go->std = V4L2_STD_NTSC_M; |
725 | go->width = 720; |
726 | go->height = 480; |
727 | go->sensor_framerate = 30000; |
728 | } else { |
729 | go->standard = GO7007_STD_OTHER; |
730 | go->width = board->sensor_width; |
731 | go->height = board->sensor_height; |
732 | go->sensor_framerate = board->sensor_framerate; |
733 | } |
734 | go->encoder_v_offset = board->sensor_v_offset; |
735 | go->encoder_h_offset = board->sensor_h_offset; |
736 | } |
737 | EXPORT_SYMBOL(go7007_update_board); |
738 | |
739 | MODULE_LICENSE("GPL v2" ); |
740 | |