2008-02-16 08:53:09 +08:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2005-2006 Micronas USA Inc.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License (Version 2) as
|
|
|
|
* published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/delay.h>
|
|
|
|
#include <linux/sched.h>
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <linux/unistd.h>
|
|
|
|
#include <linux/time.h>
|
|
|
|
#include <linux/mm.h>
|
|
|
|
#include <linux/vmalloc.h>
|
|
|
|
#include <linux/device.h>
|
|
|
|
#include <linux/i2c.h>
|
|
|
|
#include <linux/firmware.h>
|
2009-09-15 22:07:59 +08:00
|
|
|
#include <linux/mutex.h>
|
2008-02-16 08:53:09 +08:00
|
|
|
#include <linux/uaccess.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 16:04:11 +08:00
|
|
|
#include <linux/slab.h>
|
2008-09-30 10:36:24 +08:00
|
|
|
#include <linux/videodev2.h>
|
2008-02-16 08:53:09 +08:00
|
|
|
#include <media/tuner.h>
|
|
|
|
#include <media/v4l2-common.h>
|
2014-06-10 18:39:04 +08:00
|
|
|
#include <media/v4l2-event.h>
|
2008-02-16 08:53:09 +08:00
|
|
|
|
|
|
|
#include "go7007-priv.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Wait for an interrupt to be delivered from the GO7007SB and return
|
|
|
|
* the associated value and data.
|
|
|
|
*
|
|
|
|
* Must be called with the hw_lock held.
|
|
|
|
*/
|
|
|
|
int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data)
|
|
|
|
{
|
|
|
|
go->interrupt_available = 0;
|
|
|
|
go->hpi_ops->read_interrupt(go);
|
|
|
|
if (wait_event_timeout(go->interrupt_waitq,
|
|
|
|
go->interrupt_available, 5*HZ) < 0) {
|
2009-11-17 02:07:42 +08:00
|
|
|
v4l2_err(&go->v4l2_dev, "timeout waiting for read interrupt\n");
|
2008-02-16 08:53:09 +08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (!go->interrupt_available)
|
|
|
|
return -1;
|
|
|
|
go->interrupt_available = 0;
|
|
|
|
*value = go->interrupt_value & 0xfffe;
|
|
|
|
*data = go->interrupt_data;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(go7007_read_interrupt);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read a register/address on the GO7007SB.
|
|
|
|
*
|
|
|
|
* Must be called with the hw_lock held.
|
|
|
|
*/
|
|
|
|
int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data)
|
|
|
|
{
|
|
|
|
int count = 100;
|
|
|
|
u16 value;
|
|
|
|
|
|
|
|
if (go7007_write_interrupt(go, 0x0010, addr) < 0)
|
|
|
|
return -EIO;
|
|
|
|
while (count-- > 0) {
|
|
|
|
if (go7007_read_interrupt(go, &value, data) == 0 &&
|
|
|
|
value == 0xa000)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return -EIO;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(go7007_read_addr);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send the boot firmware to the encoder, which just wakes it up and lets
|
|
|
|
* us talk to the GPIO pins and on-board I2C adapter.
|
|
|
|
*
|
|
|
|
* Must be called with the hw_lock held.
|
|
|
|
*/
|
|
|
|
static int go7007_load_encoder(struct go7007 *go)
|
|
|
|
{
|
|
|
|
const struct firmware *fw_entry;
|
2013-03-11 17:45:14 +08:00
|
|
|
char fw_name[] = "go7007/go7007fw.bin";
|
2008-02-16 08:53:09 +08:00
|
|
|
void *bounce;
|
|
|
|
int fw_len, rv = 0;
|
|
|
|
u16 intr_val, intr_data;
|
|
|
|
|
2013-03-09 21:37:52 +08:00
|
|
|
if (go->boot_fw == NULL) {
|
|
|
|
if (request_firmware(&fw_entry, fw_name, go->dev)) {
|
|
|
|
v4l2_err(go, "unable to load firmware from file \"%s\"\n", fw_name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) {
|
|
|
|
v4l2_err(go, "file \"%s\" does not appear to be go7007 firmware\n", fw_name);
|
|
|
|
release_firmware(fw_entry);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
fw_len = fw_entry->size - 16;
|
|
|
|
bounce = kmemdup(fw_entry->data + 16, fw_len, GFP_KERNEL);
|
|
|
|
if (bounce == NULL) {
|
|
|
|
v4l2_err(go, "unable to allocate %d bytes for firmware transfer\n", fw_len);
|
|
|
|
release_firmware(fw_entry);
|
|
|
|
return -1;
|
|
|
|
}
|
2008-02-16 08:53:09 +08:00
|
|
|
release_firmware(fw_entry);
|
2013-03-09 21:37:52 +08:00
|
|
|
go->boot_fw_len = fw_len;
|
|
|
|
go->boot_fw = bounce;
|
2008-02-16 08:53:09 +08:00
|
|
|
}
|
|
|
|
if (go7007_interface_reset(go) < 0 ||
|
2013-03-09 21:37:52 +08:00
|
|
|
go7007_send_firmware(go, go->boot_fw, go->boot_fw_len) < 0 ||
|
|
|
|
go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
|
2008-02-16 08:53:09 +08:00
|
|
|
(intr_val & ~0x1) != 0x5a5a) {
|
2009-09-19 10:06:15 +08:00
|
|
|
v4l2_err(go, "error transferring firmware\n");
|
2008-02-16 08:53:09 +08:00
|
|
|
rv = -1;
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2013-03-11 17:45:14 +08:00
|
|
|
MODULE_FIRMWARE("go7007/go7007fw.bin");
|
2010-01-14 07:36:09 +08:00
|
|
|
|
2008-02-16 08:53:09 +08:00
|
|
|
/*
|
|
|
|
* Boot the encoder and register the I2C adapter if requested. Do the
|
|
|
|
* minimum initialization necessary, since the board-specific code may
|
|
|
|
* still need to probe the board ID.
|
|
|
|
*
|
|
|
|
* Must NOT be called with the hw_lock held.
|
|
|
|
*/
|
|
|
|
int go7007_boot_encoder(struct go7007 *go, int init_i2c)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
|
2009-09-15 22:07:59 +08:00
|
|
|
mutex_lock(&go->hw_lock);
|
2008-02-16 08:53:09 +08:00
|
|
|
ret = go7007_load_encoder(go);
|
2009-09-15 22:07:59 +08:00
|
|
|
mutex_unlock(&go->hw_lock);
|
2008-02-16 08:53:09 +08:00
|
|
|
if (ret < 0)
|
|
|
|
return -1;
|
|
|
|
if (!init_i2c)
|
|
|
|
return 0;
|
|
|
|
if (go7007_i2c_init(go) < 0)
|
|
|
|
return -1;
|
|
|
|
go->i2c_adapter_online = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(go7007_boot_encoder);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Configure any hardware-related registers in the GO7007, such as GPIO
|
|
|
|
* pins and bus parameters, which are board-specific. This assumes
|
|
|
|
* the boot firmware has already been downloaded.
|
|
|
|
*
|
|
|
|
* Must be called with the hw_lock held.
|
|
|
|
*/
|
|
|
|
static int go7007_init_encoder(struct go7007 *go)
|
|
|
|
{
|
|
|
|
if (go->board_info->audio_flags & GO7007_AUDIO_I2S_MASTER) {
|
|
|
|
go7007_write_addr(go, 0x1000, 0x0811);
|
|
|
|
go7007_write_addr(go, 0x1000, 0x0c11);
|
|
|
|
}
|
2013-03-17 21:15:03 +08:00
|
|
|
switch (go->board_id) {
|
|
|
|
case GO7007_BOARDID_MATRIX_REV:
|
2008-02-16 08:53:09 +08:00
|
|
|
/* Set GPIO pin 0 to be an output (audio clock control) */
|
|
|
|
go7007_write_addr(go, 0x3c82, 0x0001);
|
|
|
|
go7007_write_addr(go, 0x3c80, 0x00fe);
|
2013-03-17 21:15:03 +08:00
|
|
|
break;
|
|
|
|
case GO7007_BOARDID_ADLINK_MPG24:
|
2013-01-16 20:00:50 +08:00
|
|
|
/* set GPIO5 to be an output, currently low */
|
|
|
|
go7007_write_addr(go, 0x3c82, 0x0000);
|
|
|
|
go7007_write_addr(go, 0x3c80, 0x00df);
|
2013-03-17 21:15:03 +08:00
|
|
|
break;
|
|
|
|
case GO7007_BOARDID_ADS_USBAV_709:
|
|
|
|
/* GPIO pin 0: audio clock control */
|
|
|
|
/* pin 2: TW9906 reset */
|
|
|
|
/* pin 3: capture LED */
|
|
|
|
go7007_write_addr(go, 0x3c82, 0x000d);
|
|
|
|
go7007_write_addr(go, 0x3c80, 0x00f2);
|
|
|
|
break;
|
2013-01-16 20:00:50 +08:00
|
|
|
}
|
2008-02-16 08:53:09 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send the boot firmware to the GO7007 and configure the registers. This
|
|
|
|
* is the only way to stop the encoder once it has started streaming video.
|
|
|
|
*
|
|
|
|
* Must be called with the hw_lock held.
|
|
|
|
*/
|
|
|
|
int go7007_reset_encoder(struct go7007 *go)
|
|
|
|
{
|
|
|
|
if (go7007_load_encoder(go) < 0)
|
|
|
|
return -1;
|
|
|
|
return go7007_init_encoder(go);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Attempt to instantiate an I2C client by ID, probably loading a module.
|
|
|
|
*/
|
2013-03-09 19:48:25 +08:00
|
|
|
static int init_i2c_module(struct i2c_adapter *adapter, const struct go_i2c *const i2c)
|
2008-02-16 08:53:09 +08:00
|
|
|
{
|
2009-11-17 02:16:00 +08:00
|
|
|
struct go7007 *go = i2c_get_adapdata(adapter);
|
|
|
|
struct v4l2_device *v4l2_dev = &go->v4l2_dev;
|
2013-03-09 20:25:47 +08:00
|
|
|
struct v4l2_subdev *sd;
|
2013-03-09 19:48:25 +08:00
|
|
|
struct i2c_board_info info;
|
2008-02-16 08:53:09 +08:00
|
|
|
|
2013-03-09 19:48:25 +08:00
|
|
|
memset(&info, 0, sizeof(info));
|
|
|
|
strlcpy(info.type, i2c->type, sizeof(info.type));
|
|
|
|
info.addr = i2c->addr;
|
|
|
|
info.flags = i2c->flags;
|
|
|
|
|
2013-03-09 20:25:47 +08:00
|
|
|
sd = v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, NULL);
|
|
|
|
if (sd) {
|
|
|
|
if (i2c->is_video)
|
|
|
|
go->sd_video = sd;
|
|
|
|
if (i2c->is_audio)
|
|
|
|
go->sd_audio = sd;
|
2008-02-16 08:53:09 +08:00
|
|
|
return 0;
|
2013-03-09 20:25:47 +08:00
|
|
|
}
|
2009-11-17 02:16:00 +08:00
|
|
|
|
2014-07-18 07:40:20 +08:00
|
|
|
pr_info("go7007: probing for module i2c:%s failed\n", i2c->type);
|
2013-03-09 19:48:25 +08:00
|
|
|
return -EINVAL;
|
2008-02-16 08:53:09 +08:00
|
|
|
}
|
|
|
|
|
2013-03-11 15:48:30 +08:00
|
|
|
/*
|
|
|
|
* Detach and unregister the encoder. The go7007 struct won't be freed
|
|
|
|
* until v4l2 finishes releasing its resources and all associated fds are
|
|
|
|
* closed by applications.
|
|
|
|
*/
|
|
|
|
static void go7007_remove(struct v4l2_device *v4l2_dev)
|
|
|
|
{
|
|
|
|
struct go7007 *go = container_of(v4l2_dev, struct go7007, v4l2_dev);
|
|
|
|
|
|
|
|
v4l2_device_unregister(v4l2_dev);
|
|
|
|
if (go->hpi_ops->release)
|
|
|
|
go->hpi_ops->release(go);
|
|
|
|
if (go->i2c_adapter_online) {
|
2013-05-03 05:38:53 +08:00
|
|
|
i2c_del_adapter(&go->i2c_adapter);
|
|
|
|
go->i2c_adapter_online = 0;
|
2013-03-11 15:48:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
kfree(go->boot_fw);
|
|
|
|
go7007_v4l2_remove(go);
|
|
|
|
kfree(go);
|
|
|
|
}
|
|
|
|
|
2008-02-16 08:53:09 +08:00
|
|
|
/*
|
|
|
|
* Finalize the GO7007 hardware setup, register the on-board I2C adapter
|
|
|
|
* (if used on this board), load the I2C client driver for the sensor
|
|
|
|
* (SAA7115 or whatever) and other devices, and register the ALSA and V4L2
|
|
|
|
* interfaces.
|
|
|
|
*
|
|
|
|
* Must NOT be called with the hw_lock held.
|
|
|
|
*/
|
2013-03-09 20:25:47 +08:00
|
|
|
int go7007_register_encoder(struct go7007 *go, unsigned num_i2c_devs)
|
2008-02-16 08:53:09 +08:00
|
|
|
{
|
|
|
|
int i, ret;
|
|
|
|
|
2012-11-05 03:40:22 +08:00
|
|
|
dev_info(go->dev, "go7007: registering new %s\n", go->name);
|
2008-02-16 08:53:09 +08:00
|
|
|
|
2013-03-11 15:48:30 +08:00
|
|
|
go->v4l2_dev.release = go7007_remove;
|
|
|
|
ret = v4l2_device_register(go->dev, &go->v4l2_dev);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
2009-09-15 22:07:59 +08:00
|
|
|
mutex_lock(&go->hw_lock);
|
2008-02-16 08:53:09 +08:00
|
|
|
ret = go7007_init_encoder(go);
|
2009-09-15 22:07:59 +08:00
|
|
|
mutex_unlock(&go->hw_lock);
|
2008-02-16 08:53:09 +08:00
|
|
|
if (ret < 0)
|
2013-03-11 16:19:59 +08:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
ret = go7007_v4l2_ctrl_init(go);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
2008-02-16 08:53:09 +08:00
|
|
|
|
|
|
|
if (!go->i2c_adapter_online &&
|
|
|
|
go->board_info->flags & GO7007_BOARD_USE_ONBOARD_I2C) {
|
2013-03-11 16:19:59 +08:00
|
|
|
ret = go7007_i2c_init(go);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
2008-02-16 08:53:09 +08:00
|
|
|
go->i2c_adapter_online = 1;
|
|
|
|
}
|
|
|
|
if (go->i2c_adapter_online) {
|
2013-03-17 21:15:03 +08:00
|
|
|
if (go->board_id == GO7007_BOARDID_ADS_USBAV_709) {
|
|
|
|
/* Reset the TW9906 */
|
|
|
|
go7007_write_addr(go, 0x3c82, 0x0009);
|
|
|
|
msleep(50);
|
|
|
|
go7007_write_addr(go, 0x3c82, 0x000d);
|
|
|
|
}
|
2013-03-09 20:25:47 +08:00
|
|
|
for (i = 0; i < num_i2c_devs; ++i)
|
2013-03-09 19:48:25 +08:00
|
|
|
init_i2c_module(&go->i2c_adapter, &go->board_info->i2c_devs[i]);
|
2013-03-09 20:25:47 +08:00
|
|
|
|
|
|
|
if (go->tuner_type >= 0) {
|
|
|
|
struct tuner_setup setup = {
|
|
|
|
.addr = ADDR_UNSET,
|
|
|
|
.type = go->tuner_type,
|
|
|
|
.mode_mask = T_ANALOG_TV,
|
|
|
|
};
|
|
|
|
|
|
|
|
v4l2_device_call_all(&go->v4l2_dev, 0, tuner,
|
|
|
|
s_type_addr, &setup);
|
|
|
|
}
|
2008-02-16 08:53:09 +08:00
|
|
|
if (go->board_id == GO7007_BOARDID_ADLINK_MPG24)
|
2013-03-09 20:25:47 +08:00
|
|
|
v4l2_subdev_call(go->sd_video, video, s_routing,
|
|
|
|
0, 0, go->channel_number + 1);
|
2008-02-16 08:53:09 +08:00
|
|
|
}
|
2013-03-11 15:48:30 +08:00
|
|
|
|
|
|
|
ret = go7007_v4l2_init(go);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
2008-02-16 08:53:09 +08:00
|
|
|
if (go->board_info->flags & GO7007_BOARD_HAS_AUDIO) {
|
|
|
|
go->audio_enabled = 1;
|
|
|
|
go7007_snd_init(go);
|
|
|
|
}
|
2009-11-17 02:16:00 +08:00
|
|
|
return 0;
|
2008-02-16 08:53:09 +08:00
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(go7007_register_encoder);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Send the encode firmware to the encoder, which will cause it
|
|
|
|
* to immediately start delivering the video and audio streams.
|
|
|
|
*
|
|
|
|
* Must be called with the hw_lock held.
|
|
|
|
*/
|
|
|
|
int go7007_start_encoder(struct go7007 *go)
|
|
|
|
{
|
|
|
|
u8 *fw;
|
2014-06-10 18:39:04 +08:00
|
|
|
int fw_len, rv = 0, i, x, y;
|
2008-02-16 08:53:09 +08:00
|
|
|
u16 intr_val, intr_data;
|
|
|
|
|
|
|
|
go->modet_enable = 0;
|
2014-06-10 18:39:04 +08:00
|
|
|
for (i = 0; i < 4; i++)
|
|
|
|
go->modet[i].enable = 0;
|
|
|
|
|
|
|
|
switch (v4l2_ctrl_g_ctrl(go->modet_mode)) {
|
|
|
|
case V4L2_DETECT_MD_MODE_GLOBAL:
|
|
|
|
memset(go->modet_map, 0, sizeof(go->modet_map));
|
|
|
|
go->modet[0].enable = 1;
|
|
|
|
go->modet_enable = 1;
|
|
|
|
break;
|
|
|
|
case V4L2_DETECT_MD_MODE_REGION_GRID:
|
|
|
|
for (y = 0; y < go->height / 16; y++) {
|
|
|
|
for (x = 0; x < go->width / 16; x++) {
|
|
|
|
int idx = y * go->width / 16 + x;
|
|
|
|
|
|
|
|
go->modet[go->modet_map[idx]].enable = 1;
|
2008-02-16 08:53:09 +08:00
|
|
|
}
|
|
|
|
}
|
2014-06-10 18:39:04 +08:00
|
|
|
go->modet_enable = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (go->dvd_mode)
|
|
|
|
go->modet_enable = 0;
|
2008-02-16 08:53:09 +08:00
|
|
|
|
|
|
|
if (go7007_construct_fw_image(go, &fw, &fw_len) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (go7007_send_firmware(go, fw, fw_len) < 0 ||
|
|
|
|
go7007_read_interrupt(go, &intr_val, &intr_data) < 0) {
|
2009-11-17 02:07:42 +08:00
|
|
|
v4l2_err(&go->v4l2_dev, "error transferring firmware\n");
|
2008-02-16 08:53:09 +08:00
|
|
|
rv = -1;
|
|
|
|
goto start_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
go->state = STATE_DATA;
|
|
|
|
go->parse_length = 0;
|
|
|
|
go->seen_frame = 0;
|
|
|
|
if (go7007_stream_start(go) < 0) {
|
2009-11-17 02:07:42 +08:00
|
|
|
v4l2_err(&go->v4l2_dev, "error starting stream transfer\n");
|
2008-02-16 08:53:09 +08:00
|
|
|
rv = -1;
|
|
|
|
goto start_error;
|
|
|
|
}
|
|
|
|
|
|
|
|
start_error:
|
|
|
|
kfree(fw);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Store a byte in the current video buffer, if there is one.
|
|
|
|
*/
|
2013-03-11 17:52:27 +08:00
|
|
|
static inline void store_byte(struct go7007_buffer *vb, u8 byte)
|
2008-02-16 08:53:09 +08:00
|
|
|
{
|
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 21:30:30 +08:00
|
|
|
if (vb && vb->vb.vb2_buf.planes[0].bytesused < GO7007_BUF_SIZE) {
|
|
|
|
u8 *ptr = vb2_plane_vaddr(&vb->vb.vb2_buf, 0);
|
2008-02-16 08:53:09 +08:00
|
|
|
|
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 21:30:30 +08:00
|
|
|
ptr[vb->vb.vb2_buf.planes[0].bytesused++] = byte;
|
2008-02-16 08:53:09 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-10 18:39:04 +08:00
|
|
|
static void go7007_set_motion_regions(struct go7007 *go, struct go7007_buffer *vb,
|
|
|
|
u32 motion_regions)
|
|
|
|
{
|
|
|
|
if (motion_regions != go->modet_event_status) {
|
|
|
|
struct v4l2_event ev = {
|
|
|
|
.type = V4L2_EVENT_MOTION_DET,
|
|
|
|
.u.motion_det = {
|
|
|
|
.flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
|
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 21:30:30 +08:00
|
|
|
.frame_sequence = vb->vb.sequence,
|
2014-06-10 18:39:04 +08:00
|
|
|
.region_mask = motion_regions,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
v4l2_event_queue(&go->vdev, &ev);
|
|
|
|
go->modet_event_status = motion_regions;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-16 08:53:09 +08:00
|
|
|
/*
|
2014-06-10 18:39:04 +08:00
|
|
|
* Determine regions with motion and send a motion detection event
|
|
|
|
* in case of changes.
|
2008-02-16 08:53:09 +08:00
|
|
|
*/
|
2014-06-10 18:39:04 +08:00
|
|
|
static void go7007_motion_regions(struct go7007 *go, struct go7007_buffer *vb)
|
2008-02-16 08:53:09 +08:00
|
|
|
{
|
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 21:30:30 +08:00
|
|
|
u32 *bytesused = &vb->vb.vb2_buf.planes[0].bytesused;
|
2014-06-10 18:39:04 +08:00
|
|
|
unsigned motion[4] = { 0, 0, 0, 0 };
|
|
|
|
u32 motion_regions = 0;
|
|
|
|
unsigned stride = (go->width + 7) >> 3;
|
|
|
|
unsigned x, y;
|
2008-02-16 08:53:09 +08:00
|
|
|
int i;
|
|
|
|
|
2014-06-10 18:39:04 +08:00
|
|
|
for (i = 0; i < 216; ++i)
|
|
|
|
store_byte(vb, go->active_map[i]);
|
|
|
|
for (y = 0; y < go->height / 16; y++) {
|
|
|
|
for (x = 0; x < go->width / 16; x++) {
|
|
|
|
if (!(go->active_map[y * stride + (x >> 3)] & (1 << (x & 7))))
|
|
|
|
continue;
|
|
|
|
motion[go->modet_map[y * (go->width / 16) + x]]++;
|
2008-02-16 08:53:09 +08:00
|
|
|
}
|
2014-06-10 18:39:04 +08:00
|
|
|
}
|
|
|
|
motion_regions = ((motion[0] > 0) << 0) |
|
|
|
|
((motion[1] > 0) << 1) |
|
|
|
|
((motion[2] > 0) << 2) |
|
|
|
|
((motion[3] > 0) << 3);
|
|
|
|
*bytesused -= 216;
|
|
|
|
go7007_set_motion_regions(go, vb, motion_regions);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Deliver the last video buffer and get a new one to start writing to.
|
|
|
|
*/
|
|
|
|
static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buffer *vb)
|
|
|
|
{
|
2015-04-29 04:09:23 +08:00
|
|
|
u32 *bytesused;
|
2014-06-10 18:39:04 +08:00
|
|
|
struct go7007_buffer *vb_tmp = NULL;
|
|
|
|
|
|
|
|
if (vb == NULL) {
|
2013-03-11 17:52:27 +08:00
|
|
|
spin_lock(&go->spinlock);
|
2014-06-10 18:39:04 +08:00
|
|
|
if (!list_empty(&go->vidq_active))
|
|
|
|
vb = go->active_buf =
|
|
|
|
list_first_entry(&go->vidq_active, struct go7007_buffer, list);
|
2013-03-11 17:52:27 +08:00
|
|
|
spin_unlock(&go->spinlock);
|
2014-06-10 18:39:04 +08:00
|
|
|
go->next_seq++;
|
2013-03-11 17:52:27 +08:00
|
|
|
return vb;
|
2008-02-16 08:53:09 +08:00
|
|
|
}
|
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 21:30:30 +08:00
|
|
|
bytesused = &vb->vb.vb2_buf.planes[0].bytesused;
|
2014-06-10 18:39:04 +08:00
|
|
|
|
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 21:30:30 +08:00
|
|
|
vb->vb.sequence = go->next_seq++;
|
2014-06-10 18:39:04 +08:00
|
|
|
if (vb->modet_active && *bytesused + 216 < GO7007_BUF_SIZE)
|
|
|
|
go7007_motion_regions(go, vb);
|
|
|
|
else
|
|
|
|
go7007_set_motion_regions(go, vb, 0);
|
|
|
|
|
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 21:30:30 +08:00
|
|
|
v4l2_get_timestamp(&vb->vb.timestamp);
|
2014-06-10 18:39:04 +08:00
|
|
|
vb_tmp = vb;
|
2013-03-11 17:52:27 +08:00
|
|
|
spin_lock(&go->spinlock);
|
2014-06-10 18:39:04 +08:00
|
|
|
list_del(&vb->list);
|
|
|
|
if (list_empty(&go->vidq_active))
|
|
|
|
vb = NULL;
|
|
|
|
else
|
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 21:30:30 +08:00
|
|
|
vb = list_first_entry(&go->vidq_active,
|
|
|
|
struct go7007_buffer, list);
|
2014-06-10 18:39:04 +08:00
|
|
|
go->active_buf = vb;
|
2013-03-11 17:52:27 +08:00
|
|
|
spin_unlock(&go->spinlock);
|
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 21:30:30 +08:00
|
|
|
vb2_buffer_done(&vb_tmp->vb.vb2_buf, VB2_BUF_STATE_DONE);
|
2013-03-11 17:52:27 +08:00
|
|
|
return vb;
|
2008-02-16 08:53:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void write_bitmap_word(struct go7007 *go)
|
|
|
|
{
|
|
|
|
int x, y, i, stride = ((go->width >> 4) + 7) >> 3;
|
|
|
|
|
|
|
|
for (i = 0; i < 16; ++i) {
|
|
|
|
y = (((go->parse_length - 1) << 3) + i) / (go->width >> 4);
|
|
|
|
x = (((go->parse_length - 1) << 3) + i) % (go->width >> 4);
|
2010-09-24 01:43:41 +08:00
|
|
|
if (stride * y + (x >> 3) < sizeof(go->active_map))
|
|
|
|
go->active_map[stride * y + (x >> 3)] |=
|
2008-02-16 08:53:09 +08:00
|
|
|
(go->modet_word & 1) << (x & 0x7);
|
|
|
|
go->modet_word >>= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Parse a chunk of the video stream into frames. The frames are not
|
|
|
|
* delimited by the hardware, so we have to parse the frame boundaries
|
|
|
|
* based on the type of video stream we're receiving.
|
|
|
|
*/
|
|
|
|
void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
|
|
|
|
{
|
2013-03-11 17:52:27 +08:00
|
|
|
struct go7007_buffer *vb = go->active_buf;
|
2013-03-17 21:11:32 +08:00
|
|
|
int i, seq_start_code = -1, gop_start_code = -1, frame_start_code = -1;
|
2008-02-16 08:53:09 +08:00
|
|
|
|
|
|
|
switch (go->format) {
|
2013-03-11 16:58:55 +08:00
|
|
|
case V4L2_PIX_FMT_MPEG4:
|
2008-02-16 08:53:09 +08:00
|
|
|
seq_start_code = 0xB0;
|
2013-03-17 21:11:32 +08:00
|
|
|
gop_start_code = 0xB3;
|
2008-02-16 08:53:09 +08:00
|
|
|
frame_start_code = 0xB6;
|
|
|
|
break;
|
2013-03-11 16:58:55 +08:00
|
|
|
case V4L2_PIX_FMT_MPEG1:
|
|
|
|
case V4L2_PIX_FMT_MPEG2:
|
2008-02-16 08:53:09 +08:00
|
|
|
seq_start_code = 0xB3;
|
2013-03-17 21:11:32 +08:00
|
|
|
gop_start_code = 0xB8;
|
2008-02-16 08:53:09 +08:00
|
|
|
frame_start_code = 0x00;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < length; ++i) {
|
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 21:30:30 +08:00
|
|
|
if (vb && vb->vb.vb2_buf.planes[0].bytesused >=
|
|
|
|
GO7007_BUF_SIZE - 3) {
|
2009-11-17 02:07:42 +08:00
|
|
|
v4l2_info(&go->v4l2_dev, "dropping oversized frame\n");
|
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 21:30:30 +08:00
|
|
|
vb->vb.vb2_buf.planes[0].bytesused = 0;
|
2013-03-11 17:52:27 +08:00
|
|
|
vb->frame_offset = 0;
|
|
|
|
vb->modet_active = 0;
|
|
|
|
vb = go->active_buf = NULL;
|
2008-02-16 08:53:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (go->state) {
|
|
|
|
case STATE_DATA:
|
|
|
|
switch (buf[i]) {
|
|
|
|
case 0x00:
|
|
|
|
go->state = STATE_00;
|
|
|
|
break;
|
|
|
|
case 0xFF:
|
|
|
|
go->state = STATE_FF;
|
|
|
|
break;
|
|
|
|
default:
|
2013-03-11 17:52:27 +08:00
|
|
|
store_byte(vb, buf[i]);
|
2008-02-16 08:53:09 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_00:
|
|
|
|
switch (buf[i]) {
|
|
|
|
case 0x00:
|
|
|
|
go->state = STATE_00_00;
|
|
|
|
break;
|
|
|
|
case 0xFF:
|
2013-03-11 17:52:27 +08:00
|
|
|
store_byte(vb, 0x00);
|
2008-02-16 08:53:09 +08:00
|
|
|
go->state = STATE_FF;
|
|
|
|
break;
|
|
|
|
default:
|
2013-03-11 17:52:27 +08:00
|
|
|
store_byte(vb, 0x00);
|
|
|
|
store_byte(vb, buf[i]);
|
2008-02-16 08:53:09 +08:00
|
|
|
go->state = STATE_DATA;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_00_00:
|
|
|
|
switch (buf[i]) {
|
|
|
|
case 0x00:
|
2013-03-11 17:52:27 +08:00
|
|
|
store_byte(vb, 0x00);
|
2008-02-16 08:53:09 +08:00
|
|
|
/* go->state remains STATE_00_00 */
|
|
|
|
break;
|
|
|
|
case 0x01:
|
|
|
|
go->state = STATE_00_00_01;
|
|
|
|
break;
|
|
|
|
case 0xFF:
|
2013-03-11 17:52:27 +08:00
|
|
|
store_byte(vb, 0x00);
|
|
|
|
store_byte(vb, 0x00);
|
2008-02-16 08:53:09 +08:00
|
|
|
go->state = STATE_FF;
|
|
|
|
break;
|
|
|
|
default:
|
2013-03-11 17:52:27 +08:00
|
|
|
store_byte(vb, 0x00);
|
|
|
|
store_byte(vb, 0x00);
|
|
|
|
store_byte(vb, buf[i]);
|
2008-02-16 08:53:09 +08:00
|
|
|
go->state = STATE_DATA;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_00_00_01:
|
2010-09-24 01:43:41 +08:00
|
|
|
if (buf[i] == 0xF8 && go->modet_enable == 0) {
|
|
|
|
/* MODET start code, but MODET not enabled */
|
2013-03-11 17:52:27 +08:00
|
|
|
store_byte(vb, 0x00);
|
|
|
|
store_byte(vb, 0x00);
|
|
|
|
store_byte(vb, 0x01);
|
|
|
|
store_byte(vb, 0xF8);
|
2010-09-24 01:43:41 +08:00
|
|
|
go->state = STATE_DATA;
|
|
|
|
break;
|
|
|
|
}
|
2008-02-16 08:53:09 +08:00
|
|
|
/* If this is the start of a new MPEG frame,
|
|
|
|
* get a new buffer */
|
2013-03-11 16:58:55 +08:00
|
|
|
if ((go->format == V4L2_PIX_FMT_MPEG1 ||
|
|
|
|
go->format == V4L2_PIX_FMT_MPEG2 ||
|
|
|
|
go->format == V4L2_PIX_FMT_MPEG4) &&
|
2013-03-11 17:52:27 +08:00
|
|
|
(buf[i] == seq_start_code ||
|
2013-03-17 21:11:32 +08:00
|
|
|
buf[i] == gop_start_code ||
|
2013-03-11 17:52:27 +08:00
|
|
|
buf[i] == frame_start_code)) {
|
|
|
|
if (vb == NULL || go->seen_frame)
|
|
|
|
vb = frame_boundary(go, vb);
|
|
|
|
go->seen_frame = buf[i] == frame_start_code;
|
|
|
|
if (vb && go->seen_frame)
|
[media] media: videobuf2: Restructure vb2_buffer
Remove v4l2 stuff - v4l2_buf, v4l2_plane - from struct vb2_buffer.
Add new member variables - bytesused, length, offset, userptr, fd,
data_offset - to struct vb2_plane in order to cover all information
of v4l2_plane.
struct vb2_plane {
<snip>
unsigned int bytesused;
unsigned int length;
union {
unsigned int offset;
unsigned long userptr;
int fd;
} m;
unsigned int data_offset;
}
Replace v4l2_buf with new member variables - index, type, memory - which
are common fields for buffer management.
struct vb2_buffer {
<snip>
unsigned int index;
unsigned int type;
unsigned int memory;
unsigned int num_planes;
struct vb2_plane planes[VIDEO_MAX_PLANES];
<snip>
};
v4l2 specific fields - flags, field, timestamp, timecode,
sequence - are moved to vb2_v4l2_buffer in videobuf2-v4l2.c
struct vb2_v4l2_buffer {
struct vb2_buffer vb2_buf;
__u32 flags;
__u32 field;
struct timeval timestamp;
struct v4l2_timecode timecode;
__u32 sequence;
};
Signed-off-by: Junghak Sung <jh1009.sung@samsung.com>
Signed-off-by: Geunyoung Kim <nenggun.kim@samsung.com>
Acked-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Acked-by: Inki Dae <inki.dae@samsung.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
2015-09-22 21:30:30 +08:00
|
|
|
vb->frame_offset =
|
|
|
|
vb->vb.vb2_buf.planes[0].bytesused;
|
2008-02-16 08:53:09 +08:00
|
|
|
}
|
|
|
|
/* Handle any special chunk types, or just write the
|
|
|
|
* start code to the (potentially new) buffer */
|
|
|
|
switch (buf[i]) {
|
|
|
|
case 0xF5: /* timestamp */
|
|
|
|
go->parse_length = 12;
|
|
|
|
go->state = STATE_UNPARSED;
|
|
|
|
break;
|
|
|
|
case 0xF6: /* vbi */
|
|
|
|
go->state = STATE_VBI_LEN_A;
|
|
|
|
break;
|
|
|
|
case 0xF8: /* MD map */
|
|
|
|
go->parse_length = 0;
|
|
|
|
memset(go->active_map, 0,
|
|
|
|
sizeof(go->active_map));
|
|
|
|
go->state = STATE_MODET_MAP;
|
|
|
|
break;
|
|
|
|
case 0xFF: /* Potential JPEG start code */
|
2013-03-11 17:52:27 +08:00
|
|
|
store_byte(vb, 0x00);
|
|
|
|
store_byte(vb, 0x00);
|
|
|
|
store_byte(vb, 0x01);
|
2008-02-16 08:53:09 +08:00
|
|
|
go->state = STATE_FF;
|
|
|
|
break;
|
|
|
|
default:
|
2013-03-11 17:52:27 +08:00
|
|
|
store_byte(vb, 0x00);
|
|
|
|
store_byte(vb, 0x00);
|
|
|
|
store_byte(vb, 0x01);
|
|
|
|
store_byte(vb, buf[i]);
|
2008-02-16 08:53:09 +08:00
|
|
|
go->state = STATE_DATA;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_FF:
|
|
|
|
switch (buf[i]) {
|
|
|
|
case 0x00:
|
2013-03-11 17:52:27 +08:00
|
|
|
store_byte(vb, 0xFF);
|
2008-02-16 08:53:09 +08:00
|
|
|
go->state = STATE_00;
|
|
|
|
break;
|
|
|
|
case 0xFF:
|
2013-03-11 17:52:27 +08:00
|
|
|
store_byte(vb, 0xFF);
|
2008-02-16 08:53:09 +08:00
|
|
|
/* go->state remains STATE_FF */
|
|
|
|
break;
|
|
|
|
case 0xD8:
|
2013-03-11 16:58:55 +08:00
|
|
|
if (go->format == V4L2_PIX_FMT_MJPEG)
|
2013-03-11 17:52:27 +08:00
|
|
|
vb = frame_boundary(go, vb);
|
2008-02-16 08:53:09 +08:00
|
|
|
/* fall through */
|
|
|
|
default:
|
2013-03-11 17:52:27 +08:00
|
|
|
store_byte(vb, 0xFF);
|
|
|
|
store_byte(vb, buf[i]);
|
2008-02-16 08:53:09 +08:00
|
|
|
go->state = STATE_DATA;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATE_VBI_LEN_A:
|
|
|
|
go->parse_length = buf[i] << 8;
|
|
|
|
go->state = STATE_VBI_LEN_B;
|
|
|
|
break;
|
|
|
|
case STATE_VBI_LEN_B:
|
|
|
|
go->parse_length |= buf[i];
|
|
|
|
if (go->parse_length > 0)
|
|
|
|
go->state = STATE_UNPARSED;
|
|
|
|
else
|
|
|
|
go->state = STATE_DATA;
|
|
|
|
break;
|
|
|
|
case STATE_MODET_MAP:
|
|
|
|
if (go->parse_length < 204) {
|
|
|
|
if (go->parse_length & 1) {
|
|
|
|
go->modet_word |= buf[i];
|
|
|
|
write_bitmap_word(go);
|
|
|
|
} else
|
|
|
|
go->modet_word = buf[i] << 8;
|
2013-03-11 17:52:27 +08:00
|
|
|
} else if (go->parse_length == 207 && vb) {
|
|
|
|
vb->modet_active = buf[i];
|
2008-02-16 08:53:09 +08:00
|
|
|
}
|
|
|
|
if (++go->parse_length == 208)
|
|
|
|
go->state = STATE_DATA;
|
|
|
|
break;
|
|
|
|
case STATE_UNPARSED:
|
|
|
|
if (--go->parse_length == 0)
|
|
|
|
go->state = STATE_DATA;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(go7007_parse_video_stream);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Allocate a new go7007 struct. Used by the hardware-specific probe.
|
|
|
|
*/
|
2013-03-17 21:56:20 +08:00
|
|
|
struct go7007 *go7007_alloc(const struct go7007_board_info *board,
|
|
|
|
struct device *dev)
|
2008-02-16 08:53:09 +08:00
|
|
|
{
|
|
|
|
struct go7007 *go;
|
|
|
|
int i;
|
|
|
|
|
2013-01-16 20:00:48 +08:00
|
|
|
go = kzalloc(sizeof(struct go7007), GFP_KERNEL);
|
2008-02-16 08:53:09 +08:00
|
|
|
if (go == NULL)
|
|
|
|
return NULL;
|
|
|
|
go->dev = dev;
|
|
|
|
go->board_info = board;
|
|
|
|
go->board_id = 0;
|
|
|
|
go->tuner_type = -1;
|
|
|
|
go->channel_number = 0;
|
|
|
|
go->name[0] = 0;
|
2009-09-15 22:07:59 +08:00
|
|
|
mutex_init(&go->hw_lock);
|
2008-02-16 08:53:09 +08:00
|
|
|
init_waitqueue_head(&go->frame_waitq);
|
|
|
|
spin_lock_init(&go->spinlock);
|
|
|
|
go->status = STATUS_INIT;
|
|
|
|
memset(&go->i2c_adapter, 0, sizeof(go->i2c_adapter));
|
|
|
|
go->i2c_adapter_online = 0;
|
|
|
|
go->interrupt_available = 0;
|
|
|
|
init_waitqueue_head(&go->interrupt_waitq);
|
|
|
|
go->input = 0;
|
2013-03-11 16:50:21 +08:00
|
|
|
go7007_update_board(go);
|
2008-02-16 08:53:09 +08:00
|
|
|
go->encoder_h_halve = 0;
|
|
|
|
go->encoder_v_halve = 0;
|
|
|
|
go->encoder_subsample = 0;
|
2013-03-11 16:58:55 +08:00
|
|
|
go->format = V4L2_PIX_FMT_MJPEG;
|
2008-02-16 08:53:09 +08:00
|
|
|
go->bitrate = 1500000;
|
|
|
|
go->fps_scale = 1;
|
|
|
|
go->pali = 0;
|
|
|
|
go->aspect_ratio = GO7007_RATIO_1_1;
|
|
|
|
go->gop_size = 0;
|
|
|
|
go->ipb = 0;
|
|
|
|
go->closed_gop = 0;
|
|
|
|
go->repeat_seqhead = 0;
|
|
|
|
go->seq_header_enable = 0;
|
|
|
|
go->gop_header_enable = 0;
|
|
|
|
go->dvd_mode = 0;
|
|
|
|
go->interlace_coding = 0;
|
|
|
|
for (i = 0; i < 4; ++i)
|
2010-11-15 11:04:48 +08:00
|
|
|
go->modet[i].enable = 0;
|
2008-02-16 08:53:09 +08:00
|
|
|
for (i = 0; i < 1624; ++i)
|
|
|
|
go->modet_map[i] = 0;
|
|
|
|
go->audio_deliver = NULL;
|
|
|
|
go->audio_enabled = 0;
|
|
|
|
|
|
|
|
return go;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(go7007_alloc);
|
|
|
|
|
2013-03-11 16:50:21 +08:00
|
|
|
void go7007_update_board(struct go7007 *go)
|
|
|
|
{
|
2013-03-17 21:56:20 +08:00
|
|
|
const struct go7007_board_info *board = go->board_info;
|
2013-03-11 16:50:21 +08:00
|
|
|
|
|
|
|
if (board->sensor_flags & GO7007_SENSOR_TV) {
|
|
|
|
go->standard = GO7007_STD_NTSC;
|
|
|
|
go->std = V4L2_STD_NTSC_M;
|
|
|
|
go->width = 720;
|
|
|
|
go->height = 480;
|
|
|
|
go->sensor_framerate = 30000;
|
|
|
|
} else {
|
|
|
|
go->standard = GO7007_STD_OTHER;
|
|
|
|
go->width = board->sensor_width;
|
|
|
|
go->height = board->sensor_height;
|
|
|
|
go->sensor_framerate = board->sensor_framerate;
|
|
|
|
}
|
|
|
|
go->encoder_v_offset = board->sensor_v_offset;
|
|
|
|
go->encoder_h_offset = board->sensor_h_offset;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(go7007_update_board);
|
|
|
|
|
2008-02-16 08:53:09 +08:00
|
|
|
MODULE_LICENSE("GPL v2");
|