Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6
* 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-2.6: (46 commits) [media] rc: call input_sync after scancode reports [media] imon: allow either proto on unknown 0xffdc [media] imon: auto-config ffdc 7e device [media] saa7134: fix raw IR timeout value [media] rc: fix ghost keypresses with certain hw [media] [staging] lirc_serial: allocate irq at init time [media] lirc_zilog: fix spinning rx thread [media] keymaps: fix table for pinnacle pctv hd devices [media] ite-cir: 8709 needs to use pnp resource 2 [media] V4L: mx1-camera: fix uninitialized variable [media] omap_vout: Added check in reqbuf & mmap for buf_size allocation [media] OMAP_VOUT: Change hardcoded device node number to -1 [media] OMAP_VOUTLIB: Fix wrong resizer calculation [media] uvcvideo: Disable the queue when failing to start [media] uvcvideo: Remove buffers from the queues when freeing [media] uvcvideo: Ignore entities for terminals with no supported format [media] v4l: Don't access media entity after is has been destroyed [media] media: omap3isp: fix a potential NULL deref [media] media: vb2: fix allocation failure check [media] media: vb2: reset queued_count value during queue reinitialization ... Fix up trivial conflict in MAINTAINERS as per Mauro
This commit is contained in:
Коммит
de3796e77a
|
@ -6733,6 +6733,7 @@ F: fs/fat/
|
|||
VIDEOBUF2 FRAMEWORK
|
||||
M: Pawel Osciak <pawel@osciak.com>
|
||||
M: Marek Szyprowski <m.szyprowski@samsung.com>
|
||||
M: Kyungmin Park <kyungmin.park@samsung.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/media/video/videobuf2-*
|
||||
|
|
|
@ -597,12 +597,17 @@ static void __devexit fintek_remove(struct pnp_dev *pdev)
|
|||
static int fintek_suspend(struct pnp_dev *pdev, pm_message_t state)
|
||||
{
|
||||
struct fintek_dev *fintek = pnp_get_drvdata(pdev);
|
||||
unsigned long flags;
|
||||
|
||||
fit_dbg("%s called", __func__);
|
||||
|
||||
spin_lock_irqsave(&fintek->fintek_lock, flags);
|
||||
|
||||
/* disable all CIR interrupts */
|
||||
fintek_cir_reg_write(fintek, CIR_STATUS_IRQ_MASK, CIR_STATUS);
|
||||
|
||||
spin_unlock_irqrestore(&fintek->fintek_lock, flags);
|
||||
|
||||
fintek_config_mode_enable(fintek);
|
||||
|
||||
/* disable cir logical dev */
|
||||
|
|
|
@ -307,6 +307,14 @@ static const struct {
|
|||
/* 0xffdc iMON MCE VFD */
|
||||
{ 0x00010000ffffffeell, KEY_VOLUMEUP },
|
||||
{ 0x01000000ffffffeell, KEY_VOLUMEDOWN },
|
||||
{ 0x00000001ffffffeell, KEY_MUTE },
|
||||
{ 0x0000000fffffffeell, KEY_MEDIA },
|
||||
{ 0x00000012ffffffeell, KEY_UP },
|
||||
{ 0x00000013ffffffeell, KEY_DOWN },
|
||||
{ 0x00000014ffffffeell, KEY_LEFT },
|
||||
{ 0x00000015ffffffeell, KEY_RIGHT },
|
||||
{ 0x00000016ffffffeell, KEY_ENTER },
|
||||
{ 0x00000017ffffffeell, KEY_ESC },
|
||||
/* iMON Knob values */
|
||||
{ 0x000100ffffffffeell, KEY_VOLUMEUP },
|
||||
{ 0x010000ffffffffeell, KEY_VOLUMEDOWN },
|
||||
|
@ -1582,16 +1590,16 @@ static void imon_incoming_packet(struct imon_context *ictx,
|
|||
/* Only panel type events left to process now */
|
||||
spin_lock_irqsave(&ictx->kc_lock, flags);
|
||||
|
||||
do_gettimeofday(&t);
|
||||
/* KEY_MUTE repeats from knob need to be suppressed */
|
||||
if (ictx->kc == KEY_MUTE && ictx->kc == ictx->last_keycode) {
|
||||
do_gettimeofday(&t);
|
||||
msec = tv2int(&t, &prev_time);
|
||||
prev_time = t;
|
||||
if (msec < ictx->idev->rep[REP_DELAY]) {
|
||||
spin_unlock_irqrestore(&ictx->kc_lock, flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
prev_time = t;
|
||||
kc = ictx->kc;
|
||||
|
||||
spin_unlock_irqrestore(&ictx->kc_lock, flags);
|
||||
|
@ -1603,7 +1611,9 @@ static void imon_incoming_packet(struct imon_context *ictx,
|
|||
input_report_key(ictx->idev, kc, 0);
|
||||
input_sync(ictx->idev);
|
||||
|
||||
spin_lock_irqsave(&ictx->kc_lock, flags);
|
||||
ictx->last_keycode = kc;
|
||||
spin_unlock_irqrestore(&ictx->kc_lock, flags);
|
||||
|
||||
return;
|
||||
|
||||
|
@ -1740,6 +1750,8 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
|
|||
detected_display_type = IMON_DISPLAY_TYPE_VFD;
|
||||
break;
|
||||
/* iMON VFD, MCE IR */
|
||||
case 0x46:
|
||||
case 0x7e:
|
||||
case 0x9e:
|
||||
dev_info(ictx->dev, "0xffdc iMON VFD, MCE IR");
|
||||
detected_display_type = IMON_DISPLAY_TYPE_VFD;
|
||||
|
@ -1755,6 +1767,9 @@ static void imon_get_ffdc_type(struct imon_context *ictx)
|
|||
dev_info(ictx->dev, "Unknown 0xffdc device, "
|
||||
"defaulting to VFD and iMON IR");
|
||||
detected_display_type = IMON_DISPLAY_TYPE_VFD;
|
||||
/* We don't know which one it is, allow user to set the
|
||||
* RC6 one from userspace if OTHER wasn't correct. */
|
||||
allowed_protos |= RC_TYPE_RC6;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -114,18 +114,20 @@ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type)
|
|||
s64 delta; /* ns */
|
||||
DEFINE_IR_RAW_EVENT(ev);
|
||||
int rc = 0;
|
||||
int delay;
|
||||
|
||||
if (!dev->raw)
|
||||
return -EINVAL;
|
||||
|
||||
now = ktime_get();
|
||||
delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event));
|
||||
delay = MS_TO_NS(dev->input_dev->rep[REP_DELAY]);
|
||||
|
||||
/* Check for a long duration since last event or if we're
|
||||
* being called for the first time, note that delta can't
|
||||
* possibly be negative.
|
||||
*/
|
||||
if (delta > IR_MAX_DURATION || !dev->raw->last_type)
|
||||
if (delta > delay || !dev->raw->last_type)
|
||||
type |= IR_START_EVENT;
|
||||
else
|
||||
ev.duration = delta;
|
||||
|
|
|
@ -1347,6 +1347,7 @@ static const struct ite_dev_params ite_dev_descs[] = {
|
|||
{ /* 0: ITE8704 */
|
||||
.model = "ITE8704 CIR transceiver",
|
||||
.io_region_size = IT87_IOREG_LENGTH,
|
||||
.io_rsrc_no = 0,
|
||||
.hw_tx_capable = true,
|
||||
.sample_period = (u32) (1000000000ULL / 115200),
|
||||
.tx_carrier_freq = 38000,
|
||||
|
@ -1371,6 +1372,7 @@ static const struct ite_dev_params ite_dev_descs[] = {
|
|||
{ /* 1: ITE8713 */
|
||||
.model = "ITE8713 CIR transceiver",
|
||||
.io_region_size = IT87_IOREG_LENGTH,
|
||||
.io_rsrc_no = 0,
|
||||
.hw_tx_capable = true,
|
||||
.sample_period = (u32) (1000000000ULL / 115200),
|
||||
.tx_carrier_freq = 38000,
|
||||
|
@ -1395,6 +1397,7 @@ static const struct ite_dev_params ite_dev_descs[] = {
|
|||
{ /* 2: ITE8708 */
|
||||
.model = "ITE8708 CIR transceiver",
|
||||
.io_region_size = IT8708_IOREG_LENGTH,
|
||||
.io_rsrc_no = 0,
|
||||
.hw_tx_capable = true,
|
||||
.sample_period = (u32) (1000000000ULL / 115200),
|
||||
.tx_carrier_freq = 38000,
|
||||
|
@ -1420,6 +1423,7 @@ static const struct ite_dev_params ite_dev_descs[] = {
|
|||
{ /* 3: ITE8709 */
|
||||
.model = "ITE8709 CIR transceiver",
|
||||
.io_region_size = IT8709_IOREG_LENGTH,
|
||||
.io_rsrc_no = 2,
|
||||
.hw_tx_capable = true,
|
||||
.sample_period = (u32) (1000000000ULL / 115200),
|
||||
.tx_carrier_freq = 38000,
|
||||
|
@ -1461,6 +1465,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
|
|||
struct rc_dev *rdev = NULL;
|
||||
int ret = -ENOMEM;
|
||||
int model_no;
|
||||
int io_rsrc_no;
|
||||
|
||||
ite_dbg("%s called", __func__);
|
||||
|
||||
|
@ -1490,10 +1495,11 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
|
|||
|
||||
/* get the description for the device */
|
||||
dev_desc = &ite_dev_descs[model_no];
|
||||
io_rsrc_no = dev_desc->io_rsrc_no;
|
||||
|
||||
/* validate pnp resources */
|
||||
if (!pnp_port_valid(pdev, 0) ||
|
||||
pnp_port_len(pdev, 0) != dev_desc->io_region_size) {
|
||||
if (!pnp_port_valid(pdev, io_rsrc_no) ||
|
||||
pnp_port_len(pdev, io_rsrc_no) != dev_desc->io_region_size) {
|
||||
dev_err(&pdev->dev, "IR PNP Port not valid!\n");
|
||||
goto failure;
|
||||
}
|
||||
|
@ -1504,7 +1510,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
|
|||
}
|
||||
|
||||
/* store resource values */
|
||||
itdev->cir_addr = pnp_port_start(pdev, 0);
|
||||
itdev->cir_addr = pnp_port_start(pdev, io_rsrc_no);
|
||||
itdev->cir_irq = pnp_irq(pdev, 0);
|
||||
|
||||
/* initialize spinlocks */
|
||||
|
|
|
@ -57,6 +57,9 @@ struct ite_dev_params {
|
|||
/* size of the I/O region */
|
||||
int io_region_size;
|
||||
|
||||
/* IR pnp I/O resource number */
|
||||
int io_rsrc_no;
|
||||
|
||||
/* true if the hardware supports transmission */
|
||||
bool hw_tx_capable;
|
||||
|
||||
|
|
|
@ -15,43 +15,39 @@
|
|||
/* Pinnacle PCTV HD 800i mini remote */
|
||||
|
||||
static struct rc_map_table pinnacle_pctv_hd[] = {
|
||||
|
||||
{ 0x0f, KEY_1 },
|
||||
{ 0x15, KEY_2 },
|
||||
{ 0x10, KEY_3 },
|
||||
{ 0x18, KEY_4 },
|
||||
{ 0x1b, KEY_5 },
|
||||
{ 0x1e, KEY_6 },
|
||||
{ 0x11, KEY_7 },
|
||||
{ 0x21, KEY_8 },
|
||||
{ 0x12, KEY_9 },
|
||||
{ 0x27, KEY_0 },
|
||||
|
||||
{ 0x24, KEY_ZOOM },
|
||||
{ 0x2a, KEY_SUBTITLE },
|
||||
|
||||
{ 0x00, KEY_MUTE },
|
||||
{ 0x01, KEY_ENTER }, /* Pinnacle Logo */
|
||||
{ 0x39, KEY_POWER },
|
||||
|
||||
{ 0x03, KEY_VOLUMEUP },
|
||||
{ 0x09, KEY_VOLUMEDOWN },
|
||||
{ 0x06, KEY_CHANNELUP },
|
||||
{ 0x0c, KEY_CHANNELDOWN },
|
||||
|
||||
{ 0x2d, KEY_REWIND },
|
||||
{ 0x30, KEY_PLAYPAUSE },
|
||||
{ 0x33, KEY_FASTFORWARD },
|
||||
{ 0x3c, KEY_STOP },
|
||||
{ 0x36, KEY_RECORD },
|
||||
{ 0x3f, KEY_EPG }, /* Labeled "?" */
|
||||
/* Key codes for the tiny Pinnacle remote*/
|
||||
{ 0x0700, KEY_MUTE },
|
||||
{ 0x0701, KEY_MENU }, /* Pinnacle logo */
|
||||
{ 0x0739, KEY_POWER },
|
||||
{ 0x0703, KEY_VOLUMEUP },
|
||||
{ 0x0709, KEY_VOLUMEDOWN },
|
||||
{ 0x0706, KEY_CHANNELUP },
|
||||
{ 0x070c, KEY_CHANNELDOWN },
|
||||
{ 0x070f, KEY_1 },
|
||||
{ 0x0715, KEY_2 },
|
||||
{ 0x0710, KEY_3 },
|
||||
{ 0x0718, KEY_4 },
|
||||
{ 0x071b, KEY_5 },
|
||||
{ 0x071e, KEY_6 },
|
||||
{ 0x0711, KEY_7 },
|
||||
{ 0x0721, KEY_8 },
|
||||
{ 0x0712, KEY_9 },
|
||||
{ 0x0727, KEY_0 },
|
||||
{ 0x0724, KEY_ZOOM }, /* 'Square' key */
|
||||
{ 0x072a, KEY_SUBTITLE }, /* 'T' key */
|
||||
{ 0x072d, KEY_REWIND },
|
||||
{ 0x0730, KEY_PLAYPAUSE },
|
||||
{ 0x0733, KEY_FASTFORWARD },
|
||||
{ 0x0736, KEY_RECORD },
|
||||
{ 0x073c, KEY_STOP },
|
||||
{ 0x073f, KEY_HELP }, /* '?' key */
|
||||
};
|
||||
|
||||
static struct rc_map_list pinnacle_pctv_hd_map = {
|
||||
.map = {
|
||||
.scan = pinnacle_pctv_hd,
|
||||
.size = ARRAY_SIZE(pinnacle_pctv_hd),
|
||||
.rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
|
||||
.rc_type = RC_TYPE_RC5,
|
||||
.name = RC_MAP_PINNACLE_PCTV_HD,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -55,6 +55,8 @@ struct irctl {
|
|||
struct lirc_buffer *buf;
|
||||
unsigned int chunk_size;
|
||||
|
||||
struct cdev *cdev;
|
||||
|
||||
struct task_struct *task;
|
||||
long jiffies_to_wait;
|
||||
};
|
||||
|
@ -62,7 +64,6 @@ struct irctl {
|
|||
static DEFINE_MUTEX(lirc_dev_lock);
|
||||
|
||||
static struct irctl *irctls[MAX_IRCTL_DEVICES];
|
||||
static struct cdev cdevs[MAX_IRCTL_DEVICES];
|
||||
|
||||
/* Only used for sysfs but defined to void otherwise */
|
||||
static struct class *lirc_class;
|
||||
|
@ -167,9 +168,13 @@ static struct file_operations lirc_dev_fops = {
|
|||
|
||||
static int lirc_cdev_add(struct irctl *ir)
|
||||
{
|
||||
int retval;
|
||||
int retval = -ENOMEM;
|
||||
struct lirc_driver *d = &ir->d;
|
||||
struct cdev *cdev = &cdevs[d->minor];
|
||||
struct cdev *cdev;
|
||||
|
||||
cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
|
||||
if (!cdev)
|
||||
goto err_out;
|
||||
|
||||
if (d->fops) {
|
||||
cdev_init(cdev, d->fops);
|
||||
|
@ -180,12 +185,20 @@ static int lirc_cdev_add(struct irctl *ir)
|
|||
}
|
||||
retval = kobject_set_name(&cdev->kobj, "lirc%d", d->minor);
|
||||
if (retval)
|
||||
return retval;
|
||||
goto err_out;
|
||||
|
||||
retval = cdev_add(cdev, MKDEV(MAJOR(lirc_base_dev), d->minor), 1);
|
||||
if (retval)
|
||||
if (retval) {
|
||||
kobject_put(&cdev->kobj);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
ir->cdev = cdev;
|
||||
|
||||
return 0;
|
||||
|
||||
err_out:
|
||||
kfree(cdev);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -214,7 +227,7 @@ int lirc_register_driver(struct lirc_driver *d)
|
|||
if (MAX_IRCTL_DEVICES <= d->minor) {
|
||||
dev_err(d->dev, "lirc_dev: lirc_register_driver: "
|
||||
"\"minor\" must be between 0 and %d (%d)!\n",
|
||||
MAX_IRCTL_DEVICES-1, d->minor);
|
||||
MAX_IRCTL_DEVICES - 1, d->minor);
|
||||
err = -EBADRQC;
|
||||
goto out;
|
||||
}
|
||||
|
@ -369,7 +382,7 @@ int lirc_unregister_driver(int minor)
|
|||
|
||||
if (minor < 0 || minor >= MAX_IRCTL_DEVICES) {
|
||||
printk(KERN_ERR "lirc_dev: %s: minor (%d) must be between "
|
||||
"0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES-1);
|
||||
"0 and %d!\n", __func__, minor, MAX_IRCTL_DEVICES - 1);
|
||||
return -EBADRQC;
|
||||
}
|
||||
|
||||
|
@ -380,7 +393,7 @@ int lirc_unregister_driver(int minor)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
cdev = &cdevs[minor];
|
||||
cdev = ir->cdev;
|
||||
|
||||
mutex_lock(&lirc_dev_lock);
|
||||
|
||||
|
@ -410,6 +423,7 @@ int lirc_unregister_driver(int minor)
|
|||
} else {
|
||||
lirc_irctl_cleanup(ir);
|
||||
cdev_del(cdev);
|
||||
kfree(cdev);
|
||||
kfree(ir);
|
||||
irctls[minor] = NULL;
|
||||
}
|
||||
|
@ -453,7 +467,7 @@ int lirc_dev_fop_open(struct inode *inode, struct file *file)
|
|||
goto error;
|
||||
}
|
||||
|
||||
cdev = &cdevs[iminor(inode)];
|
||||
cdev = ir->cdev;
|
||||
if (try_module_get(cdev->owner)) {
|
||||
ir->open++;
|
||||
retval = ir->d.set_use_inc(ir->d.data);
|
||||
|
@ -484,13 +498,15 @@ EXPORT_SYMBOL(lirc_dev_fop_open);
|
|||
int lirc_dev_fop_close(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct irctl *ir = irctls[iminor(inode)];
|
||||
struct cdev *cdev = &cdevs[iminor(inode)];
|
||||
struct cdev *cdev;
|
||||
|
||||
if (!ir) {
|
||||
printk(KERN_ERR "%s: called with invalid irctl\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cdev = ir->cdev;
|
||||
|
||||
dev_dbg(ir->d.dev, LOGHEAD "close called\n", ir->d.name, ir->d.minor);
|
||||
|
||||
WARN_ON(mutex_lock_killable(&lirc_dev_lock));
|
||||
|
@ -503,6 +519,7 @@ int lirc_dev_fop_close(struct inode *inode, struct file *file)
|
|||
lirc_irctl_cleanup(ir);
|
||||
cdev_del(cdev);
|
||||
irctls[ir->d.minor] = NULL;
|
||||
kfree(cdev);
|
||||
kfree(ir);
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,12 @@ static int debug = 1;
|
|||
static int debug;
|
||||
#endif
|
||||
|
||||
#define mce_dbg(dev, fmt, ...) \
|
||||
do { \
|
||||
if (debug) \
|
||||
dev_info(dev, fmt, ## __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/* general constants */
|
||||
#define SEND_FLAG_IN_PROGRESS 1
|
||||
#define SEND_FLAG_COMPLETE 2
|
||||
|
@ -246,6 +252,9 @@ static struct usb_device_id mceusb_dev_table[] = {
|
|||
.driver_info = MCE_GEN2_TX_INV },
|
||||
/* SMK eHome Infrared Transceiver */
|
||||
{ USB_DEVICE(VENDOR_SMK, 0x0338) },
|
||||
/* SMK/I-O Data GV-MC7/RCKIT Receiver */
|
||||
{ USB_DEVICE(VENDOR_SMK, 0x0353),
|
||||
.driver_info = MCE_GEN2_NO_TX },
|
||||
/* Tatung eHome Infrared Transceiver */
|
||||
{ USB_DEVICE(VENDOR_TATUNG, 0x9150) },
|
||||
/* Shuttle eHome Infrared Transceiver */
|
||||
|
@ -606,12 +615,15 @@ static void mce_async_callback(struct urb *urb, struct pt_regs *regs)
|
|||
if (ir) {
|
||||
len = urb->actual_length;
|
||||
|
||||
dev_dbg(ir->dev, "callback called (status=%d len=%d)\n",
|
||||
mce_dbg(ir->dev, "callback called (status=%d len=%d)\n",
|
||||
urb->status, len);
|
||||
|
||||
mceusb_dev_printdata(ir, urb->transfer_buffer, 0, len, true);
|
||||
}
|
||||
|
||||
/* the transfer buffer and urb were allocated in mce_request_packet */
|
||||
kfree(urb->transfer_buffer);
|
||||
usb_free_urb(urb);
|
||||
}
|
||||
|
||||
/* request incoming or send outgoing usb packet - used to initialize remote */
|
||||
|
@ -655,17 +667,17 @@ static void mce_request_packet(struct mceusb_dev *ir, unsigned char *data,
|
|||
return;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "receive request called (size=%#x)\n", size);
|
||||
mce_dbg(dev, "receive request called (size=%#x)\n", size);
|
||||
|
||||
async_urb->transfer_buffer_length = size;
|
||||
async_urb->dev = ir->usbdev;
|
||||
|
||||
res = usb_submit_urb(async_urb, GFP_ATOMIC);
|
||||
if (res) {
|
||||
dev_dbg(dev, "receive request FAILED! (res=%d)\n", res);
|
||||
mce_dbg(dev, "receive request FAILED! (res=%d)\n", res);
|
||||
return;
|
||||
}
|
||||
dev_dbg(dev, "receive request complete (res=%d)\n", res);
|
||||
mce_dbg(dev, "receive request complete (res=%d)\n", res);
|
||||
}
|
||||
|
||||
static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
|
||||
|
@ -673,9 +685,9 @@ static void mce_async_out(struct mceusb_dev *ir, unsigned char *data, int size)
|
|||
mce_request_packet(ir, data, size, MCEUSB_TX);
|
||||
}
|
||||
|
||||
static void mce_sync_in(struct mceusb_dev *ir, unsigned char *data, int size)
|
||||
static void mce_flush_rx_buffer(struct mceusb_dev *ir, int size)
|
||||
{
|
||||
mce_request_packet(ir, data, size, MCEUSB_RX);
|
||||
mce_request_packet(ir, NULL, size, MCEUSB_RX);
|
||||
}
|
||||
|
||||
/* Send data out the IR blaster port(s) */
|
||||
|
@ -794,7 +806,7 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier)
|
|||
ir->carrier = carrier;
|
||||
cmdbuf[2] = MCE_CMD_SIG_END;
|
||||
cmdbuf[3] = MCE_IRDATA_TRAILER;
|
||||
dev_dbg(ir->dev, "%s: disabling carrier "
|
||||
mce_dbg(ir->dev, "%s: disabling carrier "
|
||||
"modulation\n", __func__);
|
||||
mce_async_out(ir, cmdbuf, sizeof(cmdbuf));
|
||||
return carrier;
|
||||
|
@ -806,7 +818,7 @@ static int mceusb_set_tx_carrier(struct rc_dev *dev, u32 carrier)
|
|||
ir->carrier = carrier;
|
||||
cmdbuf[2] = prescaler;
|
||||
cmdbuf[3] = divisor;
|
||||
dev_dbg(ir->dev, "%s: requesting %u HZ "
|
||||
mce_dbg(ir->dev, "%s: requesting %u HZ "
|
||||
"carrier\n", __func__, carrier);
|
||||
|
||||
/* Transmit new carrier to mce device */
|
||||
|
@ -879,7 +891,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
|
|||
rawir.duration = (ir->buf_in[i] & MCE_PULSE_MASK)
|
||||
* US_TO_NS(MCE_TIME_UNIT);
|
||||
|
||||
dev_dbg(ir->dev, "Storing %s with duration %d\n",
|
||||
mce_dbg(ir->dev, "Storing %s with duration %d\n",
|
||||
rawir.pulse ? "pulse" : "space",
|
||||
rawir.duration);
|
||||
|
||||
|
@ -911,7 +923,7 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
|
|||
if (ir->parser_state != CMD_HEADER && !ir->rem)
|
||||
ir->parser_state = CMD_HEADER;
|
||||
}
|
||||
dev_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n");
|
||||
mce_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n");
|
||||
ir_raw_event_handle(ir->rc);
|
||||
}
|
||||
|
||||
|
@ -933,7 +945,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
|
|||
|
||||
if (ir->send_flags == RECV_FLAG_IN_PROGRESS) {
|
||||
ir->send_flags = SEND_FLAG_COMPLETE;
|
||||
dev_dbg(ir->dev, "setup answer received %d bytes\n",
|
||||
mce_dbg(ir->dev, "setup answer received %d bytes\n",
|
||||
buf_len);
|
||||
}
|
||||
|
||||
|
@ -951,7 +963,7 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
|
|||
|
||||
case -EPIPE:
|
||||
default:
|
||||
dev_dbg(ir->dev, "Error: urb status = %d\n", urb->status);
|
||||
mce_dbg(ir->dev, "Error: urb status = %d\n", urb->status);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -961,7 +973,6 @@ static void mceusb_dev_recv(struct urb *urb, struct pt_regs *regs)
|
|||
static void mceusb_gen1_init(struct mceusb_dev *ir)
|
||||
{
|
||||
int ret;
|
||||
int maxp = ir->len_in;
|
||||
struct device *dev = ir->dev;
|
||||
char *data;
|
||||
|
||||
|
@ -978,8 +989,8 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)
|
|||
ret = usb_control_msg(ir->usbdev, usb_rcvctrlpipe(ir->usbdev, 0),
|
||||
USB_REQ_SET_ADDRESS, USB_TYPE_VENDOR, 0, 0,
|
||||
data, USB_CTRL_MSG_SZ, HZ * 3);
|
||||
dev_dbg(dev, "%s - ret = %d\n", __func__, ret);
|
||||
dev_dbg(dev, "%s - data[0] = %d, data[1] = %d\n",
|
||||
mce_dbg(dev, "%s - ret = %d\n", __func__, ret);
|
||||
mce_dbg(dev, "%s - data[0] = %d, data[1] = %d\n",
|
||||
__func__, data[0], data[1]);
|
||||
|
||||
/* set feature: bit rate 38400 bps */
|
||||
|
@ -987,71 +998,56 @@ static void mceusb_gen1_init(struct mceusb_dev *ir)
|
|||
USB_REQ_SET_FEATURE, USB_TYPE_VENDOR,
|
||||
0xc04e, 0x0000, NULL, 0, HZ * 3);
|
||||
|
||||
dev_dbg(dev, "%s - ret = %d\n", __func__, ret);
|
||||
mce_dbg(dev, "%s - ret = %d\n", __func__, ret);
|
||||
|
||||
/* bRequest 4: set char length to 8 bits */
|
||||
ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
|
||||
4, USB_TYPE_VENDOR,
|
||||
0x0808, 0x0000, NULL, 0, HZ * 3);
|
||||
dev_dbg(dev, "%s - retB = %d\n", __func__, ret);
|
||||
mce_dbg(dev, "%s - retB = %d\n", __func__, ret);
|
||||
|
||||
/* bRequest 2: set handshaking to use DTR/DSR */
|
||||
ret = usb_control_msg(ir->usbdev, usb_sndctrlpipe(ir->usbdev, 0),
|
||||
2, USB_TYPE_VENDOR,
|
||||
0x0000, 0x0100, NULL, 0, HZ * 3);
|
||||
dev_dbg(dev, "%s - retC = %d\n", __func__, ret);
|
||||
mce_dbg(dev, "%s - retC = %d\n", __func__, ret);
|
||||
|
||||
/* device reset */
|
||||
mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
|
||||
mce_sync_in(ir, NULL, maxp);
|
||||
|
||||
/* get hw/sw revision? */
|
||||
mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
|
||||
mce_sync_in(ir, NULL, maxp);
|
||||
|
||||
kfree(data);
|
||||
};
|
||||
|
||||
static void mceusb_gen2_init(struct mceusb_dev *ir)
|
||||
{
|
||||
int maxp = ir->len_in;
|
||||
|
||||
/* device reset */
|
||||
mce_async_out(ir, DEVICE_RESET, sizeof(DEVICE_RESET));
|
||||
mce_sync_in(ir, NULL, maxp);
|
||||
|
||||
/* get hw/sw revision? */
|
||||
mce_async_out(ir, GET_REVISION, sizeof(GET_REVISION));
|
||||
mce_sync_in(ir, NULL, maxp);
|
||||
|
||||
/* unknown what the next two actually return... */
|
||||
mce_async_out(ir, GET_UNKNOWN, sizeof(GET_UNKNOWN));
|
||||
mce_sync_in(ir, NULL, maxp);
|
||||
mce_async_out(ir, GET_UNKNOWN2, sizeof(GET_UNKNOWN2));
|
||||
mce_sync_in(ir, NULL, maxp);
|
||||
}
|
||||
|
||||
static void mceusb_get_parameters(struct mceusb_dev *ir)
|
||||
{
|
||||
int maxp = ir->len_in;
|
||||
|
||||
/* get the carrier and frequency */
|
||||
mce_async_out(ir, GET_CARRIER_FREQ, sizeof(GET_CARRIER_FREQ));
|
||||
mce_sync_in(ir, NULL, maxp);
|
||||
|
||||
if (!ir->flags.no_tx) {
|
||||
if (!ir->flags.no_tx)
|
||||
/* get the transmitter bitmask */
|
||||
mce_async_out(ir, GET_TX_BITMASK, sizeof(GET_TX_BITMASK));
|
||||
mce_sync_in(ir, NULL, maxp);
|
||||
}
|
||||
|
||||
/* get receiver timeout value */
|
||||
mce_async_out(ir, GET_RX_TIMEOUT, sizeof(GET_RX_TIMEOUT));
|
||||
mce_sync_in(ir, NULL, maxp);
|
||||
|
||||
/* get receiver sensor setting */
|
||||
mce_async_out(ir, GET_RX_SENSOR, sizeof(GET_RX_SENSOR));
|
||||
mce_sync_in(ir, NULL, maxp);
|
||||
}
|
||||
|
||||
static struct rc_dev *mceusb_init_rc_dev(struct mceusb_dev *ir)
|
||||
|
@ -1122,7 +1118,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
|
|||
bool tx_mask_normal;
|
||||
int ir_intfnum;
|
||||
|
||||
dev_dbg(&intf->dev, "%s called\n", __func__);
|
||||
mce_dbg(&intf->dev, "%s called\n", __func__);
|
||||
|
||||
idesc = intf->cur_altsetting;
|
||||
|
||||
|
@ -1150,7 +1146,7 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
|
|||
ep_in = ep;
|
||||
ep_in->bmAttributes = USB_ENDPOINT_XFER_INT;
|
||||
ep_in->bInterval = 1;
|
||||
dev_dbg(&intf->dev, "acceptable inbound endpoint "
|
||||
mce_dbg(&intf->dev, "acceptable inbound endpoint "
|
||||
"found\n");
|
||||
}
|
||||
|
||||
|
@ -1165,12 +1161,12 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
|
|||
ep_out = ep;
|
||||
ep_out->bmAttributes = USB_ENDPOINT_XFER_INT;
|
||||
ep_out->bInterval = 1;
|
||||
dev_dbg(&intf->dev, "acceptable outbound endpoint "
|
||||
mce_dbg(&intf->dev, "acceptable outbound endpoint "
|
||||
"found\n");
|
||||
}
|
||||
}
|
||||
if (ep_in == NULL) {
|
||||
dev_dbg(&intf->dev, "inbound and/or endpoint not found\n");
|
||||
mce_dbg(&intf->dev, "inbound and/or endpoint not found\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
@ -1215,16 +1211,16 @@ static int __devinit mceusb_dev_probe(struct usb_interface *intf,
|
|||
if (!ir->rc)
|
||||
goto rc_dev_fail;
|
||||
|
||||
/* flush buffers on the device */
|
||||
mce_sync_in(ir, NULL, maxp);
|
||||
mce_sync_in(ir, NULL, maxp);
|
||||
|
||||
/* wire up inbound data handler */
|
||||
usb_fill_int_urb(ir->urb_in, dev, pipe, ir->buf_in,
|
||||
maxp, (usb_complete_t) mceusb_dev_recv, ir, ep_in->bInterval);
|
||||
ir->urb_in->transfer_dma = ir->dma_in;
|
||||
ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
|
||||
|
||||
/* flush buffers on the device */
|
||||
mce_dbg(&intf->dev, "Flushing receive buffers\n");
|
||||
mce_flush_rx_buffer(ir, maxp);
|
||||
|
||||
/* initialize device */
|
||||
if (ir->flags.microsoft_gen1)
|
||||
mceusb_gen1_init(ir);
|
||||
|
|
|
@ -991,7 +991,6 @@ static int nvt_open(struct rc_dev *dev)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&nvt->nvt_lock, flags);
|
||||
nvt->in_use = true;
|
||||
nvt_enable_cir(nvt);
|
||||
spin_unlock_irqrestore(&nvt->nvt_lock, flags);
|
||||
|
||||
|
@ -1004,7 +1003,6 @@ static void nvt_close(struct rc_dev *dev)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&nvt->nvt_lock, flags);
|
||||
nvt->in_use = false;
|
||||
nvt_disable_cir(nvt);
|
||||
spin_unlock_irqrestore(&nvt->nvt_lock, flags);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,6 @@ struct nvt_dev {
|
|||
struct ir_raw_event rawir;
|
||||
|
||||
spinlock_t nvt_lock;
|
||||
bool in_use;
|
||||
|
||||
/* for rx */
|
||||
u8 buf[RX_BUF_LEN];
|
||||
|
|
|
@ -522,18 +522,20 @@ EXPORT_SYMBOL_GPL(rc_g_keycode_from_table);
|
|||
/**
|
||||
* ir_do_keyup() - internal function to signal the release of a keypress
|
||||
* @dev: the struct rc_dev descriptor of the device
|
||||
* @sync: whether or not to call input_sync
|
||||
*
|
||||
* This function is used internally to release a keypress, it must be
|
||||
* called with keylock held.
|
||||
*/
|
||||
static void ir_do_keyup(struct rc_dev *dev)
|
||||
static void ir_do_keyup(struct rc_dev *dev, bool sync)
|
||||
{
|
||||
if (!dev->keypressed)
|
||||
return;
|
||||
|
||||
IR_dprintk(1, "keyup key 0x%04x\n", dev->last_keycode);
|
||||
input_report_key(dev->input_dev, dev->last_keycode, 0);
|
||||
input_sync(dev->input_dev);
|
||||
if (sync)
|
||||
input_sync(dev->input_dev);
|
||||
dev->keypressed = false;
|
||||
}
|
||||
|
||||
|
@ -549,7 +551,7 @@ void rc_keyup(struct rc_dev *dev)
|
|||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&dev->keylock, flags);
|
||||
ir_do_keyup(dev);
|
||||
ir_do_keyup(dev, true);
|
||||
spin_unlock_irqrestore(&dev->keylock, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rc_keyup);
|
||||
|
@ -578,7 +580,7 @@ static void ir_timer_keyup(unsigned long cookie)
|
|||
*/
|
||||
spin_lock_irqsave(&dev->keylock, flags);
|
||||
if (time_is_before_eq_jiffies(dev->keyup_jiffies))
|
||||
ir_do_keyup(dev);
|
||||
ir_do_keyup(dev, true);
|
||||
spin_unlock_irqrestore(&dev->keylock, flags);
|
||||
}
|
||||
|
||||
|
@ -597,6 +599,7 @@ void rc_repeat(struct rc_dev *dev)
|
|||
spin_lock_irqsave(&dev->keylock, flags);
|
||||
|
||||
input_event(dev->input_dev, EV_MSC, MSC_SCAN, dev->last_scancode);
|
||||
input_sync(dev->input_dev);
|
||||
|
||||
if (!dev->keypressed)
|
||||
goto out;
|
||||
|
@ -622,29 +625,28 @@ EXPORT_SYMBOL_GPL(rc_repeat);
|
|||
static void ir_do_keydown(struct rc_dev *dev, int scancode,
|
||||
u32 keycode, u8 toggle)
|
||||
{
|
||||
bool new_event = !dev->keypressed ||
|
||||
dev->last_scancode != scancode ||
|
||||
dev->last_toggle != toggle;
|
||||
|
||||
if (new_event && dev->keypressed)
|
||||
ir_do_keyup(dev, false);
|
||||
|
||||
input_event(dev->input_dev, EV_MSC, MSC_SCAN, scancode);
|
||||
|
||||
/* Repeat event? */
|
||||
if (dev->keypressed &&
|
||||
dev->last_scancode == scancode &&
|
||||
dev->last_toggle == toggle)
|
||||
return;
|
||||
if (new_event && keycode != KEY_RESERVED) {
|
||||
/* Register a keypress */
|
||||
dev->keypressed = true;
|
||||
dev->last_scancode = scancode;
|
||||
dev->last_toggle = toggle;
|
||||
dev->last_keycode = keycode;
|
||||
|
||||
/* Release old keypress */
|
||||
ir_do_keyup(dev);
|
||||
IR_dprintk(1, "%s: key down event, "
|
||||
"key 0x%04x, scancode 0x%04x\n",
|
||||
dev->input_name, keycode, scancode);
|
||||
input_report_key(dev->input_dev, keycode, 1);
|
||||
}
|
||||
|
||||
dev->last_scancode = scancode;
|
||||
dev->last_toggle = toggle;
|
||||
dev->last_keycode = keycode;
|
||||
|
||||
if (keycode == KEY_RESERVED)
|
||||
return;
|
||||
|
||||
/* Register a keypress */
|
||||
dev->keypressed = true;
|
||||
IR_dprintk(1, "%s: key down event, key 0x%04x, scancode 0x%04x\n",
|
||||
dev->input_name, keycode, scancode);
|
||||
input_report_key(dev->input_dev, dev->last_keycode, 1);
|
||||
input_sync(dev->input_dev);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
* Header for M-5MOLS 8M Pixel camera sensor with ISP
|
||||
*
|
||||
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
|
||||
* Author: HeungJun Kim, riverful.kim@samsung.com
|
||||
* Author: HeungJun Kim <riverful.kim@samsung.com>
|
||||
*
|
||||
* Copyright (C) 2009 Samsung Electronics Co., Ltd.
|
||||
* Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
|
||||
* Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -106,23 +106,23 @@ struct m5mols_capture {
|
|||
* The each value according to each scenemode is recommended in the documents.
|
||||
*/
|
||||
struct m5mols_scenemode {
|
||||
u32 metering;
|
||||
u32 ev_bias;
|
||||
u32 wb_mode;
|
||||
u32 wb_preset;
|
||||
u32 chroma_en;
|
||||
u32 chroma_lvl;
|
||||
u32 edge_en;
|
||||
u32 edge_lvl;
|
||||
u32 af_range;
|
||||
u32 fd_mode;
|
||||
u32 mcc;
|
||||
u32 light;
|
||||
u32 flash;
|
||||
u32 tone;
|
||||
u32 iso;
|
||||
u32 capt_mode;
|
||||
u32 wdr;
|
||||
u8 metering;
|
||||
u8 ev_bias;
|
||||
u8 wb_mode;
|
||||
u8 wb_preset;
|
||||
u8 chroma_en;
|
||||
u8 chroma_lvl;
|
||||
u8 edge_en;
|
||||
u8 edge_lvl;
|
||||
u8 af_range;
|
||||
u8 fd_mode;
|
||||
u8 mcc;
|
||||
u8 light;
|
||||
u8 flash;
|
||||
u8 tone;
|
||||
u8 iso;
|
||||
u8 capt_mode;
|
||||
u8 wdr;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -154,7 +154,6 @@ struct m5mols_version {
|
|||
u8 str[VERSION_STRING_SIZE];
|
||||
u8 af;
|
||||
};
|
||||
#define VERSION_SIZE sizeof(struct m5mols_version)
|
||||
|
||||
/**
|
||||
* struct m5mols_info - M-5MOLS driver data structure
|
||||
|
@ -216,9 +215,9 @@ struct m5mols_info {
|
|||
bool lock_ae;
|
||||
bool lock_awb;
|
||||
u8 resolution;
|
||||
u32 interrupt;
|
||||
u32 mode;
|
||||
u32 mode_save;
|
||||
u8 interrupt;
|
||||
u8 mode;
|
||||
u8 mode_save;
|
||||
int (*set_power)(struct device *dev, int on);
|
||||
};
|
||||
|
||||
|
@ -256,9 +255,11 @@ struct m5mols_info {
|
|||
* +-------+---+----------+-----+------+------+------+------+
|
||||
* - d[0..3]: according to size1
|
||||
*/
|
||||
int m5mols_read(struct v4l2_subdev *sd, u32 reg_comb, u32 *val);
|
||||
int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg_comb, u8 *val);
|
||||
int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg_comb, u16 *val);
|
||||
int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg_comb, u32 *val);
|
||||
int m5mols_write(struct v4l2_subdev *sd, u32 reg_comb, u32 val);
|
||||
int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 value);
|
||||
int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 value);
|
||||
|
||||
/*
|
||||
* Mode operation of the M-5MOLS
|
||||
|
@ -280,12 +281,12 @@ int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 value);
|
|||
* The available executing order between each modes are as follows:
|
||||
* PARAMETER <---> MONITOR <---> CAPTURE
|
||||
*/
|
||||
int m5mols_mode(struct m5mols_info *info, u32 mode);
|
||||
int m5mols_mode(struct m5mols_info *info, u8 mode);
|
||||
|
||||
int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg);
|
||||
int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg);
|
||||
int m5mols_sync_controls(struct m5mols_info *info);
|
||||
int m5mols_start_capture(struct m5mols_info *info);
|
||||
int m5mols_do_scenemode(struct m5mols_info *info, u32 mode);
|
||||
int m5mols_do_scenemode(struct m5mols_info *info, u8 mode);
|
||||
int m5mols_lock_3a(struct m5mols_info *info, bool lock);
|
||||
int m5mols_set_ctrl(struct v4l2_ctrl *ctrl);
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
* The Capture code for Fujitsu M-5MOLS ISP
|
||||
*
|
||||
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
|
||||
* Author: HeungJun Kim, riverful.kim@samsung.com
|
||||
* Author: HeungJun Kim <riverful.kim@samsung.com>
|
||||
*
|
||||
* Copyright (C) 2009 Samsung Electronics Co., Ltd.
|
||||
* Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
|
||||
* Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -58,9 +58,9 @@ static int m5mols_read_rational(struct v4l2_subdev *sd, u32 addr_num,
|
|||
{
|
||||
u32 num, den;
|
||||
|
||||
int ret = m5mols_read(sd, addr_num, &num);
|
||||
int ret = m5mols_read_u32(sd, addr_num, &num);
|
||||
if (!ret)
|
||||
ret = m5mols_read(sd, addr_den, &den);
|
||||
ret = m5mols_read_u32(sd, addr_den, &den);
|
||||
if (ret)
|
||||
return ret;
|
||||
*val = den == 0 ? 0 : num / den;
|
||||
|
@ -99,20 +99,20 @@ static int m5mols_capture_info(struct m5mols_info *info)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = m5mols_read(sd, EXIF_INFO_ISO, (u32 *)&exif->iso_speed);
|
||||
ret = m5mols_read_u16(sd, EXIF_INFO_ISO, &exif->iso_speed);
|
||||
if (!ret)
|
||||
ret = m5mols_read(sd, EXIF_INFO_FLASH, (u32 *)&exif->flash);
|
||||
ret = m5mols_read_u16(sd, EXIF_INFO_FLASH, &exif->flash);
|
||||
if (!ret)
|
||||
ret = m5mols_read(sd, EXIF_INFO_SDR, (u32 *)&exif->sdr);
|
||||
ret = m5mols_read_u16(sd, EXIF_INFO_SDR, &exif->sdr);
|
||||
if (!ret)
|
||||
ret = m5mols_read(sd, EXIF_INFO_QVAL, (u32 *)&exif->qval);
|
||||
ret = m5mols_read_u16(sd, EXIF_INFO_QVAL, &exif->qval);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!ret)
|
||||
ret = m5mols_read(sd, CAPC_IMAGE_SIZE, &info->cap.main);
|
||||
ret = m5mols_read_u32(sd, CAPC_IMAGE_SIZE, &info->cap.main);
|
||||
if (!ret)
|
||||
ret = m5mols_read(sd, CAPC_THUMB_SIZE, &info->cap.thumb);
|
||||
ret = m5mols_read_u32(sd, CAPC_THUMB_SIZE, &info->cap.thumb);
|
||||
if (!ret)
|
||||
info->cap.total = info->cap.main + info->cap.thumb;
|
||||
|
||||
|
@ -122,7 +122,7 @@ static int m5mols_capture_info(struct m5mols_info *info)
|
|||
int m5mols_start_capture(struct m5mols_info *info)
|
||||
{
|
||||
struct v4l2_subdev *sd = &info->sd;
|
||||
u32 resolution = info->resolution;
|
||||
u8 resolution = info->resolution;
|
||||
int timeout;
|
||||
int ret;
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
* Controls for M-5MOLS 8M Pixel camera sensor with ISP
|
||||
*
|
||||
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
|
||||
* Author: HeungJun Kim, riverful.kim@samsung.com
|
||||
* Author: HeungJun Kim <riverful.kim@samsung.com>
|
||||
*
|
||||
* Copyright (C) 2009 Samsung Electronics Co., Ltd.
|
||||
* Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
|
||||
* Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -130,7 +130,7 @@ static struct m5mols_scenemode m5mols_default_scenemode[] = {
|
|||
*
|
||||
* WARNING: The execution order is important. Do not change the order.
|
||||
*/
|
||||
int m5mols_do_scenemode(struct m5mols_info *info, u32 mode)
|
||||
int m5mols_do_scenemode(struct m5mols_info *info, u8 mode)
|
||||
{
|
||||
struct v4l2_subdev *sd = &info->sd;
|
||||
struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode];
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
* Driver for M-5MOLS 8M Pixel camera sensor with ISP
|
||||
*
|
||||
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
|
||||
* Author: HeungJun Kim, riverful.kim@samsung.com
|
||||
* Author: HeungJun Kim <riverful.kim@samsung.com>
|
||||
*
|
||||
* Copyright (C) 2009 Samsung Electronics Co., Ltd.
|
||||
* Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
|
||||
* Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -133,13 +133,13 @@ static u32 m5mols_swap_byte(u8 *data, u8 length)
|
|||
/**
|
||||
* m5mols_read - I2C read function
|
||||
* @reg: combination of size, category and command for the I2C packet
|
||||
* @size: desired size of I2C packet
|
||||
* @val: read value
|
||||
*/
|
||||
int m5mols_read(struct v4l2_subdev *sd, u32 reg, u32 *val)
|
||||
static int m5mols_read(struct v4l2_subdev *sd, u32 size, u32 reg, u32 *val)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||
u8 rbuf[M5MOLS_I2C_MAX_SIZE + 1];
|
||||
u8 size = I2C_SIZE(reg);
|
||||
u8 category = I2C_CATEGORY(reg);
|
||||
u8 cmd = I2C_COMMAND(reg);
|
||||
struct i2c_msg msg[2];
|
||||
|
@ -149,11 +149,6 @@ int m5mols_read(struct v4l2_subdev *sd, u32 reg, u32 *val)
|
|||
if (!client->adapter)
|
||||
return -ENODEV;
|
||||
|
||||
if (size != 1 && size != 2 && size != 4) {
|
||||
v4l2_err(sd, "Wrong data size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msg[0].addr = client->addr;
|
||||
msg[0].flags = 0;
|
||||
msg[0].len = 5;
|
||||
|
@ -184,6 +179,52 @@ int m5mols_read(struct v4l2_subdev *sd, u32 reg, u32 *val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int m5mols_read_u8(struct v4l2_subdev *sd, u32 reg, u8 *val)
|
||||
{
|
||||
u32 val_32;
|
||||
int ret;
|
||||
|
||||
if (I2C_SIZE(reg) != 1) {
|
||||
v4l2_err(sd, "Wrong data size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = (u8)val_32;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int m5mols_read_u16(struct v4l2_subdev *sd, u32 reg, u16 *val)
|
||||
{
|
||||
u32 val_32;
|
||||
int ret;
|
||||
|
||||
if (I2C_SIZE(reg) != 2) {
|
||||
v4l2_err(sd, "Wrong data size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = m5mols_read(sd, I2C_SIZE(reg), reg, &val_32);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*val = (u16)val_32;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int m5mols_read_u32(struct v4l2_subdev *sd, u32 reg, u32 *val)
|
||||
{
|
||||
if (I2C_SIZE(reg) != 4) {
|
||||
v4l2_err(sd, "Wrong data size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return m5mols_read(sd, I2C_SIZE(reg), reg, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* m5mols_write - I2C command write function
|
||||
* @reg: combination of size, category and command for the I2C packet
|
||||
|
@ -231,13 +272,14 @@ int m5mols_write(struct v4l2_subdev *sd, u32 reg, u32 val)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 mask)
|
||||
int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u8 mask)
|
||||
{
|
||||
u32 busy, i;
|
||||
u8 busy;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < M5MOLS_I2C_CHECK_RETRY; i++) {
|
||||
ret = m5mols_read(sd, I2C_REG(category, cmd, 1), &busy);
|
||||
ret = m5mols_read_u8(sd, I2C_REG(category, cmd, 1), &busy);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if ((busy & mask) == mask)
|
||||
|
@ -252,14 +294,14 @@ int m5mols_busy(struct v4l2_subdev *sd, u8 category, u8 cmd, u32 mask)
|
|||
* Before writing desired interrupt value the INT_FACTOR register should
|
||||
* be read to clear pending interrupts.
|
||||
*/
|
||||
int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg)
|
||||
int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
|
||||
{
|
||||
struct m5mols_info *info = to_m5mols(sd);
|
||||
u32 mask = is_available_af(info) ? REG_INT_AF : 0;
|
||||
u32 dummy;
|
||||
u8 mask = is_available_af(info) ? REG_INT_AF : 0;
|
||||
u8 dummy;
|
||||
int ret;
|
||||
|
||||
ret = m5mols_read(sd, SYSTEM_INT_FACTOR, &dummy);
|
||||
ret = m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &dummy);
|
||||
if (!ret)
|
||||
ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask);
|
||||
return ret;
|
||||
|
@ -271,7 +313,7 @@ int m5mols_enable_interrupt(struct v4l2_subdev *sd, u32 reg)
|
|||
* It always accompanies a little delay changing the M-5MOLS mode, so it is
|
||||
* needed checking current busy status to guarantee right mode.
|
||||
*/
|
||||
static int m5mols_reg_mode(struct v4l2_subdev *sd, u32 mode)
|
||||
static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode)
|
||||
{
|
||||
int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode);
|
||||
|
||||
|
@ -286,16 +328,16 @@ static int m5mols_reg_mode(struct v4l2_subdev *sd, u32 mode)
|
|||
* can be guaranteed only when the sensor is operating in mode which which
|
||||
* a command belongs to.
|
||||
*/
|
||||
int m5mols_mode(struct m5mols_info *info, u32 mode)
|
||||
int m5mols_mode(struct m5mols_info *info, u8 mode)
|
||||
{
|
||||
struct v4l2_subdev *sd = &info->sd;
|
||||
int ret = -EINVAL;
|
||||
u32 reg;
|
||||
u8 reg;
|
||||
|
||||
if (mode < REG_PARAMETER && mode > REG_CAPTURE)
|
||||
return ret;
|
||||
|
||||
ret = m5mols_read(sd, SYSTEM_SYSMODE, ®);
|
||||
ret = m5mols_read_u8(sd, SYSTEM_SYSMODE, ®);
|
||||
if ((!ret && reg == mode) || ret)
|
||||
return ret;
|
||||
|
||||
|
@ -344,41 +386,37 @@ int m5mols_mode(struct m5mols_info *info, u32 mode)
|
|||
static int m5mols_get_version(struct v4l2_subdev *sd)
|
||||
{
|
||||
struct m5mols_info *info = to_m5mols(sd);
|
||||
union {
|
||||
struct m5mols_version ver;
|
||||
u8 bytes[VERSION_SIZE];
|
||||
} version;
|
||||
u32 *value;
|
||||
u8 cmd = CAT0_VER_CUSTOMER;
|
||||
struct m5mols_version *ver = &info->ver;
|
||||
u8 *str = ver->str;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
value = (u32 *)&version.bytes[cmd];
|
||||
ret = m5mols_read(sd, SYSTEM_CMD(cmd), value);
|
||||
if (ret)
|
||||
return ret;
|
||||
} while (cmd++ != CAT0_VER_AWB);
|
||||
|
||||
do {
|
||||
value = (u32 *)&version.bytes[cmd];
|
||||
ret = m5mols_read(sd, SYSTEM_VER_STRING, value);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (cmd >= VERSION_SIZE - 1)
|
||||
return -EINVAL;
|
||||
} while (version.bytes[cmd++]);
|
||||
|
||||
value = (u32 *)&version.bytes[cmd];
|
||||
ret = m5mols_read(sd, AF_VERSION, value);
|
||||
ret = m5mols_read_u8(sd, SYSTEM_VER_CUSTOMER, &ver->customer);
|
||||
if (!ret)
|
||||
ret = m5mols_read_u8(sd, SYSTEM_VER_PROJECT, &ver->project);
|
||||
if (!ret)
|
||||
ret = m5mols_read_u16(sd, SYSTEM_VER_FIRMWARE, &ver->fw);
|
||||
if (!ret)
|
||||
ret = m5mols_read_u16(sd, SYSTEM_VER_HARDWARE, &ver->hw);
|
||||
if (!ret)
|
||||
ret = m5mols_read_u16(sd, SYSTEM_VER_PARAMETER, &ver->param);
|
||||
if (!ret)
|
||||
ret = m5mols_read_u16(sd, SYSTEM_VER_AWB, &ver->awb);
|
||||
if (!ret)
|
||||
ret = m5mols_read_u8(sd, AF_VERSION, &ver->af);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* store version information swapped for being readable */
|
||||
info->ver = version.ver;
|
||||
info->ver.fw = be16_to_cpu(info->ver.fw);
|
||||
info->ver.hw = be16_to_cpu(info->ver.hw);
|
||||
info->ver.param = be16_to_cpu(info->ver.param);
|
||||
info->ver.awb = be16_to_cpu(info->ver.awb);
|
||||
for (i = 0; i < VERSION_STRING_SIZE; i++) {
|
||||
ret = m5mols_read_u8(sd, SYSTEM_VER_STRING, &str[i]);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ver->fw = be16_to_cpu(ver->fw);
|
||||
ver->hw = be16_to_cpu(ver->hw);
|
||||
ver->param = be16_to_cpu(ver->param);
|
||||
ver->awb = be16_to_cpu(ver->awb);
|
||||
|
||||
v4l2_info(sd, "Manufacturer\t[%s]\n",
|
||||
is_manufacturer(info, REG_SAMSUNG_ELECTRO) ?
|
||||
|
@ -722,7 +760,7 @@ static int m5mols_init_controls(struct m5mols_info *info)
|
|||
int ret;
|
||||
|
||||
/* Determine value's range & step of controls for various FW version */
|
||||
ret = m5mols_read(sd, AE_MAX_GAIN_MON, (u32 *)&max_exposure);
|
||||
ret = m5mols_read_u16(sd, AE_MAX_GAIN_MON, &max_exposure);
|
||||
if (!ret)
|
||||
step_zoom = is_manufacturer(info, REG_SAMSUNG_OPTICS) ? 31 : 1;
|
||||
if (ret)
|
||||
|
@ -842,18 +880,18 @@ static void m5mols_irq_work(struct work_struct *work)
|
|||
struct m5mols_info *info =
|
||||
container_of(work, struct m5mols_info, work_irq);
|
||||
struct v4l2_subdev *sd = &info->sd;
|
||||
u32 reg;
|
||||
u8 reg;
|
||||
int ret;
|
||||
|
||||
if (!is_powered(info) ||
|
||||
m5mols_read(sd, SYSTEM_INT_FACTOR, &info->interrupt))
|
||||
m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &info->interrupt))
|
||||
return;
|
||||
|
||||
switch (info->interrupt & REG_INT_MASK) {
|
||||
case REG_INT_AF:
|
||||
if (!is_available_af(info))
|
||||
break;
|
||||
ret = m5mols_read(sd, AF_STATUS, ®);
|
||||
ret = m5mols_read_u8(sd, AF_STATUS, ®);
|
||||
v4l2_dbg(2, m5mols_debug, sd, "AF %s\n",
|
||||
reg == REG_AF_FAIL ? "Failed" :
|
||||
reg == REG_AF_SUCCESS ? "Success" :
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
* Register map for M-5MOLS 8M Pixel camera sensor with ISP
|
||||
*
|
||||
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
|
||||
* Author: HeungJun Kim, riverful.kim@samsung.com
|
||||
* Author: HeungJun Kim <riverful.kim@samsung.com>
|
||||
*
|
||||
* Copyright (C) 2009 Samsung Electronics Co., Ltd.
|
||||
* Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
|
||||
* Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -56,13 +56,24 @@
|
|||
* more specific contents, see definition if file m5mols.h.
|
||||
*/
|
||||
#define CAT0_VER_CUSTOMER 0x00 /* customer version */
|
||||
#define CAT0_VER_AWB 0x09 /* Auto WB version */
|
||||
#define CAT0_VER_PROJECT 0x01 /* project version */
|
||||
#define CAT0_VER_FIRMWARE 0x02 /* Firmware version */
|
||||
#define CAT0_VER_HARDWARE 0x04 /* Hardware version */
|
||||
#define CAT0_VER_PARAMETER 0x06 /* Parameter version */
|
||||
#define CAT0_VER_AWB 0x08 /* Auto WB version */
|
||||
#define CAT0_VER_STRING 0x0a /* string including M-5MOLS */
|
||||
#define CAT0_SYSMODE 0x0b /* SYSTEM mode register */
|
||||
#define CAT0_STATUS 0x0c /* SYSTEM mode status register */
|
||||
#define CAT0_INT_FACTOR 0x10 /* interrupt pending register */
|
||||
#define CAT0_INT_ENABLE 0x11 /* interrupt enable register */
|
||||
|
||||
#define SYSTEM_VER_CUSTOMER I2C_REG(CAT_SYSTEM, CAT0_VER_CUSTOMER, 1)
|
||||
#define SYSTEM_VER_PROJECT I2C_REG(CAT_SYSTEM, CAT0_VER_PROJECT, 1)
|
||||
#define SYSTEM_VER_FIRMWARE I2C_REG(CAT_SYSTEM, CAT0_VER_FIRMWARE, 2)
|
||||
#define SYSTEM_VER_HARDWARE I2C_REG(CAT_SYSTEM, CAT0_VER_HARDWARE, 2)
|
||||
#define SYSTEM_VER_PARAMETER I2C_REG(CAT_SYSTEM, CAT0_VER_PARAMETER, 2)
|
||||
#define SYSTEM_VER_AWB I2C_REG(CAT_SYSTEM, CAT0_VER_AWB, 2)
|
||||
|
||||
#define SYSTEM_SYSMODE I2C_REG(CAT_SYSTEM, CAT0_SYSMODE, 1)
|
||||
#define REG_SYSINIT 0x00 /* SYSTEM mode */
|
||||
#define REG_PARAMETER 0x01 /* PARAMETER mode */
|
||||
|
@ -382,8 +393,8 @@
|
|||
#define REG_CAP_START_MAIN 0x01
|
||||
#define REG_CAP_START_THUMB 0x03
|
||||
|
||||
#define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 1)
|
||||
#define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 1)
|
||||
#define CAPC_IMAGE_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_IMAGE_SIZE, 4)
|
||||
#define CAPC_THUMB_SIZE I2C_REG(CAT_CAPT_CTRL, CATC_CAP_THUMB_SIZE, 4)
|
||||
|
||||
/*
|
||||
* Category F - Flash
|
||||
|
|
|
@ -444,12 +444,9 @@ static int mx1_camera_add_device(struct soc_camera_device *icd)
|
|||
{
|
||||
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
||||
struct mx1_camera_dev *pcdev = ici->priv;
|
||||
int ret;
|
||||
|
||||
if (pcdev->icd) {
|
||||
ret = -EBUSY;
|
||||
goto ebusy;
|
||||
}
|
||||
if (pcdev->icd)
|
||||
return -EBUSY;
|
||||
|
||||
dev_info(icd->dev.parent, "MX1 Camera driver attached to camera %d\n",
|
||||
icd->devnum);
|
||||
|
@ -458,8 +455,7 @@ static int mx1_camera_add_device(struct soc_camera_device *icd)
|
|||
|
||||
pcdev->icd = icd;
|
||||
|
||||
ebusy:
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mx1_camera_remove_device(struct soc_camera_device *icd)
|
||||
|
|
|
@ -982,6 +982,14 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
|
|||
startindex = (vout->vid == OMAP_VIDEO1) ?
|
||||
video1_numbuffers : video2_numbuffers;
|
||||
|
||||
/* Check the size of the buffer */
|
||||
if (*size > vout->buffer_size) {
|
||||
v4l2_err(&vout->vid_dev->v4l2_dev,
|
||||
"buffer allocation mismatch [%u] [%u]\n",
|
||||
*size, vout->buffer_size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
for (i = startindex; i < *count; i++) {
|
||||
vout->buffer_size = *size;
|
||||
|
||||
|
@ -1228,6 +1236,14 @@ static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma)
|
|||
(vma->vm_pgoff << PAGE_SHIFT));
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Check the size of the buffer */
|
||||
if (size > vout->buffer_size) {
|
||||
v4l2_err(&vout->vid_dev->v4l2_dev,
|
||||
"insufficient memory [%lu] [%u]\n",
|
||||
size, vout->buffer_size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
q->bufs[i]->baddr = vma->vm_start;
|
||||
|
||||
vma->vm_flags |= VM_RESERVED;
|
||||
|
@ -2391,7 +2407,7 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
|
|||
/* Register the Video device with V4L2
|
||||
*/
|
||||
vfd = vout->vfd;
|
||||
if (video_register_device(vfd, VFL_TYPE_GRABBER, k + 1) < 0) {
|
||||
if (video_register_device(vfd, VFL_TYPE_GRABBER, -1) < 0) {
|
||||
dev_err(&pdev->dev, ": Could not register "
|
||||
"Video for Linux device\n");
|
||||
vfd->minor = -1;
|
||||
|
|
|
@ -193,7 +193,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
|
|||
return -EINVAL;
|
||||
|
||||
if (cpu_is_omap24xx()) {
|
||||
if (crop->height != win->w.height) {
|
||||
if (try_crop.height != win->w.height) {
|
||||
/* If we're resizing vertically, we can't support a
|
||||
* crop width wider than 768 pixels.
|
||||
*/
|
||||
|
@ -202,7 +202,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
|
|||
}
|
||||
}
|
||||
/* vertical resizing */
|
||||
vresize = (1024 * crop->height) / win->w.height;
|
||||
vresize = (1024 * try_crop.height) / win->w.height;
|
||||
if (cpu_is_omap24xx() && (vresize > 2048))
|
||||
vresize = 2048;
|
||||
else if (cpu_is_omap34xx() && (vresize > 4096))
|
||||
|
@ -221,7 +221,7 @@ int omap_vout_new_crop(struct v4l2_pix_format *pix,
|
|||
try_crop.height = 2;
|
||||
}
|
||||
/* horizontal resizing */
|
||||
hresize = (1024 * crop->width) / win->w.width;
|
||||
hresize = (1024 * try_crop.width) / win->w.width;
|
||||
if (cpu_is_omap24xx() && (hresize > 2048))
|
||||
hresize = 2048;
|
||||
else if (cpu_is_omap34xx() && (hresize > 4096))
|
||||
|
|
|
@ -1748,7 +1748,7 @@ static int isp_register_entities(struct isp_device *isp)
|
|||
goto done;
|
||||
|
||||
/* Register external entities */
|
||||
for (subdevs = pdata->subdevs; subdevs->subdevs; ++subdevs) {
|
||||
for (subdevs = pdata->subdevs; subdevs && subdevs->subdevs; ++subdevs) {
|
||||
struct v4l2_subdev *sensor;
|
||||
struct media_entity *input;
|
||||
unsigned int flags;
|
||||
|
|
|
@ -1414,7 +1414,7 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
|
|||
{
|
||||
ARG_DEF(struct pwc_probe, probe)
|
||||
|
||||
strcpy(ARGR(probe).name, pdev->vdev->name);
|
||||
strcpy(ARGR(probe).name, pdev->vdev.name);
|
||||
ARGR(probe).type = pdev->type;
|
||||
ARG_OUT(probe)
|
||||
break;
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
Oh yes, convention: to disctinguish between all the various pointers to
|
||||
device-structures, I use these names for the pointer variables:
|
||||
udev: struct usb_device *
|
||||
vdev: struct video_device *
|
||||
vdev: struct video_device (member of pwc_dev)
|
||||
pdev: struct pwc_devive *
|
||||
*/
|
||||
|
||||
|
@ -152,6 +152,7 @@ static ssize_t pwc_video_read(struct file *file, char __user *buf,
|
|||
size_t count, loff_t *ppos);
|
||||
static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
|
||||
static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
|
||||
static void pwc_video_release(struct video_device *vfd);
|
||||
|
||||
static const struct v4l2_file_operations pwc_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
|
@ -164,41 +165,11 @@ static const struct v4l2_file_operations pwc_fops = {
|
|||
};
|
||||
static struct video_device pwc_template = {
|
||||
.name = "Philips Webcam", /* Filled in later */
|
||||
.release = video_device_release,
|
||||
.release = pwc_video_release,
|
||||
.fops = &pwc_fops,
|
||||
.ioctl_ops = &pwc_ioctl_ops,
|
||||
};
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
/* Okay, this is some magic that I worked out and the reasoning behind it...
|
||||
|
||||
The biggest problem with any USB device is of course: "what to do
|
||||
when the user unplugs the device while it is in use by an application?"
|
||||
We have several options:
|
||||
1) Curse them with the 7 plagues when they do (requires divine intervention)
|
||||
2) Tell them not to (won't work: they'll do it anyway)
|
||||
3) Oops the kernel (this will have a negative effect on a user's uptime)
|
||||
4) Do something sensible.
|
||||
|
||||
Of course, we go for option 4.
|
||||
|
||||
It happens that this device will be linked to two times, once from
|
||||
usb_device and once from the video_device in their respective 'private'
|
||||
pointers. This is done when the device is probed() and all initialization
|
||||
succeeded. The pwc_device struct links back to both structures.
|
||||
|
||||
When a device is unplugged while in use it will be removed from the
|
||||
list of known USB devices; I also de-register it as a V4L device, but
|
||||
unfortunately I can't free the memory since the struct is still in use
|
||||
by the file descriptor. This free-ing is then deferend until the first
|
||||
opportunity. Crude, but it works.
|
||||
|
||||
A small 'advantage' is that if a user unplugs the cam and plugs it back
|
||||
in, it should get assigned the same video device minor, but unfortunately
|
||||
it's non-trivial to re-link the cam back to the video device... (that
|
||||
would surely be magic! :))
|
||||
*/
|
||||
|
||||
/***************************************************************************/
|
||||
/* Private functions */
|
||||
|
||||
|
@ -1016,16 +987,15 @@ static ssize_t show_snapshot_button_status(struct device *class_dev,
|
|||
static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
|
||||
NULL);
|
||||
|
||||
static int pwc_create_sysfs_files(struct video_device *vdev)
|
||||
static int pwc_create_sysfs_files(struct pwc_device *pdev)
|
||||
{
|
||||
struct pwc_device *pdev = video_get_drvdata(vdev);
|
||||
int rc;
|
||||
|
||||
rc = device_create_file(&vdev->dev, &dev_attr_button);
|
||||
rc = device_create_file(&pdev->vdev.dev, &dev_attr_button);
|
||||
if (rc)
|
||||
goto err;
|
||||
if (pdev->features & FEATURE_MOTOR_PANTILT) {
|
||||
rc = device_create_file(&vdev->dev, &dev_attr_pan_tilt);
|
||||
rc = device_create_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
|
||||
if (rc)
|
||||
goto err_button;
|
||||
}
|
||||
|
@ -1033,19 +1003,17 @@ static int pwc_create_sysfs_files(struct video_device *vdev)
|
|||
return 0;
|
||||
|
||||
err_button:
|
||||
device_remove_file(&vdev->dev, &dev_attr_button);
|
||||
device_remove_file(&pdev->vdev.dev, &dev_attr_button);
|
||||
err:
|
||||
PWC_ERROR("Could not create sysfs files.\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void pwc_remove_sysfs_files(struct video_device *vdev)
|
||||
static void pwc_remove_sysfs_files(struct pwc_device *pdev)
|
||||
{
|
||||
struct pwc_device *pdev = video_get_drvdata(vdev);
|
||||
|
||||
if (pdev->features & FEATURE_MOTOR_PANTILT)
|
||||
device_remove_file(&vdev->dev, &dev_attr_pan_tilt);
|
||||
device_remove_file(&vdev->dev, &dev_attr_button);
|
||||
device_remove_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
|
||||
device_remove_file(&pdev->vdev.dev, &dev_attr_button);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USB_PWC_DEBUG
|
||||
|
@ -1106,7 +1074,7 @@ static int pwc_video_open(struct file *file)
|
|||
if (ret >= 0)
|
||||
{
|
||||
PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
|
||||
pdev->vdev->name,
|
||||
pdev->vdev.name,
|
||||
pwc_sensor_type_to_string(i), i);
|
||||
}
|
||||
}
|
||||
|
@ -1180,16 +1148,15 @@ static int pwc_video_open(struct file *file)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void pwc_cleanup(struct pwc_device *pdev)
|
||||
static void pwc_video_release(struct video_device *vfd)
|
||||
{
|
||||
pwc_remove_sysfs_files(pdev->vdev);
|
||||
video_unregister_device(pdev->vdev);
|
||||
struct pwc_device *pdev = container_of(vfd, struct pwc_device, vdev);
|
||||
int hint;
|
||||
|
||||
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
|
||||
if (pdev->button_dev)
|
||||
input_unregister_device(pdev->button_dev);
|
||||
#endif
|
||||
/* search device_hint[] table if we occupy a slot, by any chance */
|
||||
for (hint = 0; hint < MAX_DEV_HINTS; hint++)
|
||||
if (device_hint[hint].pdev == pdev)
|
||||
device_hint[hint].pdev = NULL;
|
||||
|
||||
kfree(pdev);
|
||||
}
|
||||
|
@ -1199,7 +1166,7 @@ static int pwc_video_close(struct file *file)
|
|||
{
|
||||
struct video_device *vdev = file->private_data;
|
||||
struct pwc_device *pdev;
|
||||
int i, hint;
|
||||
int i;
|
||||
|
||||
PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
|
||||
|
||||
|
@ -1234,12 +1201,6 @@ static int pwc_video_close(struct file *file)
|
|||
}
|
||||
pdev->vopen--;
|
||||
PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
|
||||
} else {
|
||||
pwc_cleanup(pdev);
|
||||
/* search device_hint[] table if we occupy a slot, by any chance */
|
||||
for (hint = 0; hint < MAX_DEV_HINTS; hint++)
|
||||
if (device_hint[hint].pdev == pdev)
|
||||
device_hint[hint].pdev = NULL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1715,19 +1676,12 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
|
|||
init_waitqueue_head(&pdev->frameq);
|
||||
pdev->vcompression = pwc_preferred_compression;
|
||||
|
||||
/* Allocate video_device structure */
|
||||
pdev->vdev = video_device_alloc();
|
||||
if (!pdev->vdev) {
|
||||
PWC_ERROR("Err, cannot allocate video_device struture. Failing probe.");
|
||||
rc = -ENOMEM;
|
||||
goto err_free_mem;
|
||||
}
|
||||
memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
|
||||
pdev->vdev->parent = &intf->dev;
|
||||
pdev->vdev->lock = &pdev->modlock;
|
||||
pdev->vdev->ioctl_ops = &pwc_ioctl_ops;
|
||||
strcpy(pdev->vdev->name, name);
|
||||
video_set_drvdata(pdev->vdev, pdev);
|
||||
/* Init video_device structure */
|
||||
memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
|
||||
pdev->vdev.parent = &intf->dev;
|
||||
pdev->vdev.lock = &pdev->modlock;
|
||||
strcpy(pdev->vdev.name, name);
|
||||
video_set_drvdata(&pdev->vdev, pdev);
|
||||
|
||||
pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
|
||||
PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
|
||||
|
@ -1746,8 +1700,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
|
|||
}
|
||||
}
|
||||
|
||||
pdev->vdev->release = video_device_release;
|
||||
|
||||
/* occupy slot */
|
||||
if (hint < MAX_DEV_HINTS)
|
||||
device_hint[hint].pdev = pdev;
|
||||
|
@ -1759,16 +1711,16 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
|
|||
pwc_set_leds(pdev, 0, 0);
|
||||
pwc_camera_power(pdev, 0);
|
||||
|
||||
rc = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
|
||||
rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
|
||||
if (rc < 0) {
|
||||
PWC_ERROR("Failed to register as video device (%d).\n", rc);
|
||||
goto err_video_release;
|
||||
goto err_free_mem;
|
||||
}
|
||||
rc = pwc_create_sysfs_files(pdev->vdev);
|
||||
rc = pwc_create_sysfs_files(pdev);
|
||||
if (rc)
|
||||
goto err_video_unreg;
|
||||
|
||||
PWC_INFO("Registered as %s.\n", video_device_node_name(pdev->vdev));
|
||||
PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
|
||||
|
||||
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
|
||||
/* register webcam snapshot button input device */
|
||||
|
@ -1776,7 +1728,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
|
|||
if (!pdev->button_dev) {
|
||||
PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
|
||||
rc = -ENOMEM;
|
||||
pwc_remove_sysfs_files(pdev->vdev);
|
||||
pwc_remove_sysfs_files(pdev);
|
||||
goto err_video_unreg;
|
||||
}
|
||||
|
||||
|
@ -1794,7 +1746,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
|
|||
if (rc) {
|
||||
input_free_device(pdev->button_dev);
|
||||
pdev->button_dev = NULL;
|
||||
pwc_remove_sysfs_files(pdev->vdev);
|
||||
pwc_remove_sysfs_files(pdev);
|
||||
goto err_video_unreg;
|
||||
}
|
||||
#endif
|
||||
|
@ -1804,10 +1756,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
|
|||
err_video_unreg:
|
||||
if (hint < MAX_DEV_HINTS)
|
||||
device_hint[hint].pdev = NULL;
|
||||
video_unregister_device(pdev->vdev);
|
||||
pdev->vdev = NULL; /* So we don't try to release it below */
|
||||
err_video_release:
|
||||
video_device_release(pdev->vdev);
|
||||
video_unregister_device(&pdev->vdev);
|
||||
err_free_mem:
|
||||
kfree(pdev);
|
||||
return rc;
|
||||
|
@ -1816,10 +1765,8 @@ err_free_mem:
|
|||
/* The user yanked out the cable... */
|
||||
static void usb_pwc_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct pwc_device *pdev;
|
||||
int hint;
|
||||
struct pwc_device *pdev = usb_get_intfdata(intf);
|
||||
|
||||
pdev = usb_get_intfdata (intf);
|
||||
mutex_lock(&pdev->modlock);
|
||||
usb_set_intfdata (intf, NULL);
|
||||
if (pdev == NULL) {
|
||||
|
@ -1836,30 +1783,25 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
|
|||
}
|
||||
|
||||
/* We got unplugged; this is signalled by an EPIPE error code */
|
||||
if (pdev->vopen) {
|
||||
PWC_INFO("Disconnected while webcam is in use!\n");
|
||||
pdev->error_status = EPIPE;
|
||||
}
|
||||
pdev->error_status = EPIPE;
|
||||
pdev->unplugged = 1;
|
||||
|
||||
/* Alert waiting processes */
|
||||
wake_up_interruptible(&pdev->frameq);
|
||||
/* Wait until device is closed */
|
||||
if (pdev->vopen) {
|
||||
pdev->unplugged = 1;
|
||||
pwc_iso_stop(pdev);
|
||||
} else {
|
||||
/* Device is closed, so we can safely unregister it */
|
||||
PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
|
||||
|
||||
/* No need to keep the urbs around after disconnection */
|
||||
pwc_isoc_cleanup(pdev);
|
||||
|
||||
disconnect_out:
|
||||
/* search device_hint[] table if we occupy a slot, by any chance */
|
||||
for (hint = 0; hint < MAX_DEV_HINTS; hint++)
|
||||
if (device_hint[hint].pdev == pdev)
|
||||
device_hint[hint].pdev = NULL;
|
||||
}
|
||||
|
||||
mutex_unlock(&pdev->modlock);
|
||||
pwc_cleanup(pdev);
|
||||
|
||||
pwc_remove_sysfs_files(pdev);
|
||||
video_unregister_device(&pdev->vdev);
|
||||
|
||||
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
|
||||
if (pdev->button_dev)
|
||||
input_unregister_device(pdev->button_dev);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -162,9 +162,9 @@ struct pwc_imgbuf
|
|||
|
||||
struct pwc_device
|
||||
{
|
||||
struct video_device *vdev;
|
||||
struct video_device vdev;
|
||||
|
||||
/* Pointer to our usb_device */
|
||||
/* Pointer to our usb_device, may be NULL after unplug */
|
||||
struct usb_device *udev;
|
||||
|
||||
int type; /* type of cam (645, 646, 675, 680, 690, 720, 730, 740, 750) */
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Samsung S5P SoC series camera interface (camera capture) driver
|
||||
* Samsung S5P/EXYNOS4 SoC series camera interface (camera capture) driver
|
||||
*
|
||||
* Copyright (c) 2010 Samsung Electronics Co., Ltd
|
||||
* Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd.
|
||||
* Author: Sylwester Nawrocki, <s.nawrocki@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -262,12 +262,7 @@ static unsigned int get_plane_size(struct fimc_frame *fr, unsigned int plane)
|
|||
{
|
||||
if (!fr || plane >= fr->fmt->memplanes)
|
||||
return 0;
|
||||
|
||||
dbg("%s: w: %d. h: %d. depth[%d]: %d",
|
||||
__func__, fr->width, fr->height, plane, fr->fmt->depth[plane]);
|
||||
|
||||
return fr->f_width * fr->f_height * fr->fmt->depth[plane] / 8;
|
||||
|
||||
}
|
||||
|
||||
static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
|
||||
|
@ -283,24 +278,14 @@ static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
|
|||
|
||||
*num_planes = fmt->memplanes;
|
||||
|
||||
dbg("%s, buffer count=%d, plane count=%d",
|
||||
__func__, *num_buffers, *num_planes);
|
||||
|
||||
for (i = 0; i < fmt->memplanes; i++) {
|
||||
sizes[i] = get_plane_size(&ctx->d_frame, i);
|
||||
dbg("plane: %u, plane_size: %lu", i, sizes[i]);
|
||||
allocators[i] = ctx->fimc_dev->alloc_ctx;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int buffer_init(struct vb2_buffer *vb)
|
||||
{
|
||||
/* TODO: */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int buffer_prepare(struct vb2_buffer *vb)
|
||||
{
|
||||
struct vb2_queue *vq = vb->vb2_queue;
|
||||
|
@ -380,7 +365,6 @@ static struct vb2_ops fimc_capture_qops = {
|
|||
.queue_setup = queue_setup,
|
||||
.buf_prepare = buffer_prepare,
|
||||
.buf_queue = buffer_queue,
|
||||
.buf_init = buffer_init,
|
||||
.wait_prepare = fimc_unlock,
|
||||
.wait_finish = fimc_lock,
|
||||
.start_streaming = start_streaming,
|
||||
|
@ -903,6 +887,7 @@ err_vd_reg:
|
|||
err_v4l2_reg:
|
||||
v4l2_device_unregister(v4l2_dev);
|
||||
err_info:
|
||||
kfree(ctx);
|
||||
dev_err(&fimc->pdev->dev, "failed to install\n");
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
/*
|
||||
* S5P camera interface (video postprocessor) driver
|
||||
* Samsung S5P/EXYNOS4 SoC series camera interface (video postprocessor) driver
|
||||
*
|
||||
* Copyright (c) 2010 Samsung Electronics Co., Ltd
|
||||
*
|
||||
* Sylwester Nawrocki, <s.nawrocki@samsung.com>
|
||||
* Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
|
||||
* Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
|
@ -42,7 +41,6 @@ static struct fimc_fmt fimc_formats[] = {
|
|||
.color = S5P_FIMC_RGB565,
|
||||
.memplanes = 1,
|
||||
.colplanes = 1,
|
||||
.mbus_code = V4L2_MBUS_FMT_RGB565_2X8_BE,
|
||||
.flags = FMT_FLAGS_M2M,
|
||||
}, {
|
||||
.name = "BGR666",
|
||||
|
@ -232,11 +230,7 @@ static int fimc_get_scaler_factor(u32 src, u32 tar, u32 *ratio, u32 *shift)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
*shift = 0, *ratio = 1;
|
||||
|
||||
dbg("s: %d, t: %d, shift: %d, ratio: %d",
|
||||
src, tar, *shift, *ratio);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -268,10 +262,8 @@ int fimc_set_scaler_info(struct fimc_ctx *ctx)
|
|||
err("invalid source size: %d x %d", sx, sy);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sc->real_width = sx;
|
||||
sc->real_height = sy;
|
||||
dbg("sx= %d, sy= %d, tx= %d, ty= %d", sx, sy, tx, ty);
|
||||
|
||||
ret = fimc_get_scaler_factor(sx, tx, &sc->pre_hratio, &sc->hfactor);
|
||||
if (ret)
|
||||
|
@ -711,22 +703,18 @@ static int fimc_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
|
|||
f = ctx_get_frame(ctx, vq->type);
|
||||
if (IS_ERR(f))
|
||||
return PTR_ERR(f);
|
||||
|
||||
/*
|
||||
* Return number of non-contigous planes (plane buffers)
|
||||
* depending on the configured color format.
|
||||
*/
|
||||
if (f->fmt)
|
||||
*num_planes = f->fmt->memplanes;
|
||||
if (!f->fmt)
|
||||
return -EINVAL;
|
||||
|
||||
*num_planes = f->fmt->memplanes;
|
||||
for (i = 0; i < f->fmt->memplanes; i++) {
|
||||
sizes[i] = (f->width * f->height * f->fmt->depth[i]) >> 3;
|
||||
sizes[i] = (f->f_width * f->f_height * f->fmt->depth[i]) / 8;
|
||||
allocators[i] = ctx->fimc_dev->alloc_ctx;
|
||||
}
|
||||
|
||||
if (*num_buffers == 0)
|
||||
*num_buffers = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -852,7 +840,7 @@ struct fimc_fmt *find_format(struct v4l2_format *f, unsigned int mask)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(fimc_formats); ++i) {
|
||||
fmt = &fimc_formats[i];
|
||||
if (fmt->fourcc == f->fmt.pix.pixelformat &&
|
||||
if (fmt->fourcc == f->fmt.pix_mp.pixelformat &&
|
||||
(fmt->flags & mask))
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2010 Samsung Electronics
|
||||
*
|
||||
* Sylwester Nawrocki, <s.nawrocki@samsung.com>
|
||||
* Copyright (C) 2010 - 2011 Samsung Electronics Co., Ltd.
|
||||
*
|
||||
* 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
|
||||
|
@ -135,9 +133,10 @@ enum fimc_color_fmt {
|
|||
* @name: format description
|
||||
* @fourcc: the fourcc code for this format, 0 if not applicable
|
||||
* @color: the corresponding fimc_color_fmt
|
||||
* @depth: per plane driver's private 'number of bits per pixel'
|
||||
* @memplanes: number of physically non-contiguous data planes
|
||||
* @colplanes: number of physically contiguous data planes
|
||||
* @depth: per plane driver's private 'number of bits per pixel'
|
||||
* @flags: flags indicating which operation mode format applies to
|
||||
*/
|
||||
struct fimc_fmt {
|
||||
enum v4l2_mbus_pixelcode mbus_code;
|
||||
|
@ -171,7 +170,7 @@ struct fimc_dma_offset {
|
|||
};
|
||||
|
||||
/**
|
||||
* struct fimc_effect - the configuration data for the "Arbitrary" image effect
|
||||
* struct fimc_effect - color effect information
|
||||
* @type: effect type
|
||||
* @pat_cb: cr value when type is "arbitrary"
|
||||
* @pat_cr: cr value when type is "arbitrary"
|
||||
|
@ -184,7 +183,6 @@ struct fimc_effect {
|
|||
|
||||
/**
|
||||
* struct fimc_scaler - the configuration data for FIMC inetrnal scaler
|
||||
*
|
||||
* @scaleup_h: flag indicating scaling up horizontally
|
||||
* @scaleup_v: flag indicating scaling up vertically
|
||||
* @copy_mode: flag indicating transparent DMA transfer (no scaling
|
||||
|
@ -220,7 +218,6 @@ struct fimc_scaler {
|
|||
|
||||
/**
|
||||
* struct fimc_addr - the FIMC physical address set for DMA
|
||||
*
|
||||
* @y: luminance plane physical address
|
||||
* @cb: Cb plane physical address
|
||||
* @cr: Cr plane physical address
|
||||
|
@ -234,6 +231,7 @@ struct fimc_addr {
|
|||
/**
|
||||
* struct fimc_vid_buffer - the driver's video buffer
|
||||
* @vb: v4l videobuf buffer
|
||||
* @list: linked list structure for buffer queue
|
||||
* @paddr: precalculated physical address set
|
||||
* @index: buffer index for the output DMA engine
|
||||
*/
|
||||
|
@ -254,11 +252,10 @@ struct fimc_vid_buffer {
|
|||
* @offs_v: image vertical pixel offset
|
||||
* @width: image pixel width
|
||||
* @height: image pixel weight
|
||||
* @paddr: image frame buffer physical addresses
|
||||
* @buf_cnt: number of buffers depending on a color format
|
||||
* @payload: image size in bytes (w x h x bpp)
|
||||
* @color: color format
|
||||
* @paddr: image frame buffer physical addresses
|
||||
* @dma_offset: DMA offset in bytes
|
||||
* @fmt: fimc color format pointer
|
||||
*/
|
||||
struct fimc_frame {
|
||||
u32 f_width;
|
||||
|
@ -390,21 +387,22 @@ struct fimc_ctx;
|
|||
|
||||
/**
|
||||
* struct fimc_dev - abstraction for FIMC entity
|
||||
*
|
||||
* @slock: the spinlock protecting this data structure
|
||||
* @lock: the mutex protecting this data structure
|
||||
* @pdev: pointer to the FIMC platform device
|
||||
* @pdata: pointer to the device platform data
|
||||
* @variant: the IP variant information
|
||||
* @id: FIMC device index (0..FIMC_MAX_DEVS)
|
||||
* @num_clocks: the number of clocks managed by this device instance
|
||||
* @clock[]: the clocks required for FIMC operation
|
||||
* @clock: clocks required for FIMC operation
|
||||
* @regs: the mapped hardware registers
|
||||
* @regs_res: the resource claimed for IO registers
|
||||
* @irq: interrupt number of the FIMC subdevice
|
||||
* @irq_queue:
|
||||
* @irq: FIMC interrupt number
|
||||
* @irq_queue: interrupt handler waitqueue
|
||||
* @m2m: memory-to-memory V4L2 device information
|
||||
* @vid_cap: camera capture device information
|
||||
* @state: flags used to synchronize m2m and capture mode operation
|
||||
* @alloc_ctx: videobuf2 memory allocator context
|
||||
*/
|
||||
struct fimc_dev {
|
||||
spinlock_t slock;
|
||||
|
@ -427,8 +425,7 @@ struct fimc_dev {
|
|||
|
||||
/**
|
||||
* fimc_ctx - the device context data
|
||||
*
|
||||
* @lock: mutex protecting this data structure
|
||||
* @slock: spinlock protecting this data structure
|
||||
* @s_frame: source frame properties
|
||||
* @d_frame: destination frame properties
|
||||
* @out_order_1p: output 1-plane YCBCR order
|
||||
|
|
|
@ -963,7 +963,7 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev)
|
|||
* to work with other protocols.
|
||||
*/
|
||||
if (!ir->active) {
|
||||
timeout = jiffies + jiffies_to_msecs(15);
|
||||
timeout = jiffies + msecs_to_jiffies(15);
|
||||
mod_timer(&ir->timer, timeout);
|
||||
ir->active = true;
|
||||
}
|
||||
|
|
|
@ -27,14 +27,20 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain,
|
|||
struct uvc_entity *entity)
|
||||
{
|
||||
const u32 flags = MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE;
|
||||
struct uvc_entity *remote;
|
||||
struct media_entity *sink;
|
||||
unsigned int i;
|
||||
u8 remote_pad;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
|
||||
sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING)
|
||||
? (entity->vdev ? &entity->vdev->entity : NULL)
|
||||
: &entity->subdev.entity;
|
||||
if (sink == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < entity->num_pads; ++i) {
|
||||
struct media_entity *source;
|
||||
struct media_entity *sink;
|
||||
struct uvc_entity *remote;
|
||||
u8 remote_pad;
|
||||
|
||||
if (!(entity->pads[i].flags & MEDIA_PAD_FL_SINK))
|
||||
continue;
|
||||
|
@ -43,10 +49,11 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain,
|
|||
if (remote == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
source = (UVC_ENTITY_TYPE(remote) == UVC_TT_STREAMING)
|
||||
? &remote->vdev->entity : &remote->subdev.entity;
|
||||
sink = (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING)
|
||||
? &entity->vdev->entity : &entity->subdev.entity;
|
||||
source = (UVC_ENTITY_TYPE(remote) != UVC_TT_STREAMING)
|
||||
? (remote->vdev ? &remote->vdev->entity : NULL)
|
||||
: &remote->subdev.entity;
|
||||
if (source == NULL)
|
||||
continue;
|
||||
|
||||
remote_pad = remote->num_pads - 1;
|
||||
ret = media_entity_create_link(source, remote_pad,
|
||||
|
@ -55,11 +62,10 @@ static int uvc_mc_register_entity(struct uvc_video_chain *chain,
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (UVC_ENTITY_TYPE(entity) != UVC_TT_STREAMING)
|
||||
ret = v4l2_device_register_subdev(&chain->dev->vdev,
|
||||
&entity->subdev);
|
||||
if (UVC_ENTITY_TYPE(entity) == UVC_TT_STREAMING)
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
return v4l2_device_register_subdev(&chain->dev->vdev, &entity->subdev);
|
||||
}
|
||||
|
||||
static struct v4l2_subdev_ops uvc_subdev_ops = {
|
||||
|
@ -84,9 +90,11 @@ static int uvc_mc_init_entity(struct uvc_entity *entity)
|
|||
|
||||
ret = media_entity_init(&entity->subdev.entity,
|
||||
entity->num_pads, entity->pads, 0);
|
||||
} else
|
||||
} else if (entity->vdev != NULL) {
|
||||
ret = media_entity_init(&entity->vdev->entity,
|
||||
entity->num_pads, entity->pads, 0);
|
||||
} else
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -104,6 +104,8 @@ static int __uvc_free_buffers(struct uvc_video_queue *queue)
|
|||
}
|
||||
|
||||
if (queue->count) {
|
||||
uvc_queue_cancel(queue, 0);
|
||||
INIT_LIST_HEAD(&queue->mainqueue);
|
||||
vfree(queue->mem);
|
||||
queue->count = 0;
|
||||
}
|
||||
|
|
|
@ -1255,8 +1255,10 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
|
|||
|
||||
/* Commit the streaming parameters. */
|
||||
ret = uvc_commit_video(stream, &stream->ctrl);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
uvc_queue_enable(&stream->queue, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return uvc_init_video(stream, GFP_KERNEL);
|
||||
}
|
||||
|
|
|
@ -167,6 +167,12 @@ static void v4l2_device_release(struct device *cd)
|
|||
|
||||
mutex_unlock(&videodev_lock);
|
||||
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
|
||||
vdev->vfl_type != VFL_TYPE_SUBDEV)
|
||||
media_device_unregister_entity(&vdev->entity);
|
||||
#endif
|
||||
|
||||
/* Release video_device and perform other
|
||||
cleanups as needed. */
|
||||
vdev->release(vdev);
|
||||
|
@ -389,9 +395,6 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
|
|||
static int v4l2_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct video_device *vdev;
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
struct media_entity *entity = NULL;
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
/* Check if the video device is available */
|
||||
|
@ -405,17 +408,6 @@ static int v4l2_open(struct inode *inode, struct file *filp)
|
|||
/* and increase the device refcount */
|
||||
video_get(vdev);
|
||||
mutex_unlock(&videodev_lock);
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
|
||||
vdev->vfl_type != VFL_TYPE_SUBDEV) {
|
||||
entity = media_entity_get(&vdev->entity);
|
||||
if (!entity) {
|
||||
ret = -EBUSY;
|
||||
video_put(vdev);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (vdev->fops->open) {
|
||||
if (vdev->lock && mutex_lock_interruptible(vdev->lock)) {
|
||||
ret = -ERESTARTSYS;
|
||||
|
@ -431,14 +423,8 @@ static int v4l2_open(struct inode *inode, struct file *filp)
|
|||
|
||||
err:
|
||||
/* decrease the refcount in case of an error */
|
||||
if (ret) {
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
|
||||
vdev->vfl_type != VFL_TYPE_SUBDEV)
|
||||
media_entity_put(entity);
|
||||
#endif
|
||||
if (ret)
|
||||
video_put(vdev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -455,11 +441,6 @@ static int v4l2_release(struct inode *inode, struct file *filp)
|
|||
if (vdev->lock)
|
||||
mutex_unlock(vdev->lock);
|
||||
}
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
|
||||
vdev->vfl_type != VFL_TYPE_SUBDEV)
|
||||
media_entity_put(&vdev->entity);
|
||||
#endif
|
||||
/* decrease the refcount unconditionally since the release()
|
||||
return value is ignored. */
|
||||
video_put(vdev);
|
||||
|
@ -754,12 +735,6 @@ void video_unregister_device(struct video_device *vdev)
|
|||
if (!vdev || !video_is_registered(vdev))
|
||||
return;
|
||||
|
||||
#if defined(CONFIG_MEDIA_CONTROLLER)
|
||||
if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
|
||||
vdev->vfl_type != VFL_TYPE_SUBDEV)
|
||||
media_device_unregister_entity(&vdev->entity);
|
||||
#endif
|
||||
|
||||
mutex_lock(&videodev_lock);
|
||||
/* This must be in a critical section to prevent a race with v4l2_open.
|
||||
* Once this bit has been cleared video_get may never be called again.
|
||||
|
|
|
@ -492,13 +492,6 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the same number of buffers and memory access method is requested
|
||||
* then return immediately.
|
||||
*/
|
||||
if (q->memory == req->memory && req->count == q->num_buffers)
|
||||
return 0;
|
||||
|
||||
if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) {
|
||||
/*
|
||||
* We already have buffers allocated, so first check if they
|
||||
|
@ -539,9 +532,9 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
|
|||
/* Finally, allocate buffers and video memory */
|
||||
ret = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes,
|
||||
plane_sizes);
|
||||
if (ret < 0) {
|
||||
dprintk(1, "Memory allocation failed with error: %d\n", ret);
|
||||
return ret;
|
||||
if (ret == 0) {
|
||||
dprintk(1, "Memory allocation failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1196,6 +1189,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
|
|||
* has not already dequeued before initiating cancel.
|
||||
*/
|
||||
INIT_LIST_HEAD(&q->done_list);
|
||||
atomic_set(&q->queued_count, 0);
|
||||
wake_up_all(&q->done_wq);
|
||||
|
||||
/*
|
||||
|
|
|
@ -62,7 +62,7 @@ static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size)
|
|||
goto fail_pages_array_alloc;
|
||||
|
||||
for (i = 0; i < buf->sg_desc.num_pages; ++i) {
|
||||
buf->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO);
|
||||
buf->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN);
|
||||
if (NULL == buf->pages[i])
|
||||
goto fail_pages_alloc;
|
||||
sg_set_page(&buf->sg_desc.sglist[i],
|
||||
|
|
|
@ -672,8 +672,6 @@ static void imon_incoming_packet(struct imon_context *context,
|
|||
static void usb_rx_callback(struct urb *urb)
|
||||
{
|
||||
struct imon_context *context;
|
||||
unsigned char *buf;
|
||||
int len;
|
||||
int intfnum = 0;
|
||||
|
||||
if (!urb)
|
||||
|
@ -683,9 +681,6 @@ static void usb_rx_callback(struct urb *urb)
|
|||
if (!context)
|
||||
return;
|
||||
|
||||
buf = urb->transfer_buffer;
|
||||
len = urb->actual_length;
|
||||
|
||||
switch (urb->status) {
|
||||
case -ENOENT: /* usbcore unlink successful! */
|
||||
return;
|
||||
|
@ -728,7 +723,6 @@ static int imon_probe(struct usb_interface *interface,
|
|||
int ir_ep_found = 0;
|
||||
int alloc_status = 0;
|
||||
int vfd_proto_6p = 0;
|
||||
int code_length;
|
||||
struct imon_context *context = NULL;
|
||||
int i;
|
||||
u16 vendor, product;
|
||||
|
@ -749,8 +743,6 @@ static int imon_probe(struct usb_interface *interface,
|
|||
else
|
||||
context->display = 1;
|
||||
|
||||
code_length = BUF_CHUNK_SIZE * 8;
|
||||
|
||||
usbdev = usb_get_dev(interface_to_usbdev(interface));
|
||||
iface_desc = interface->cur_altsetting;
|
||||
num_endpts = iface_desc->desc.bNumEndpoints;
|
||||
|
@ -856,7 +848,7 @@ static int imon_probe(struct usb_interface *interface,
|
|||
|
||||
strcpy(driver->name, MOD_NAME);
|
||||
driver->minor = -1;
|
||||
driver->code_length = sizeof(int) * 8;
|
||||
driver->code_length = BUF_CHUNK_SIZE * 8;
|
||||
driver->sample_rate = 0;
|
||||
driver->features = LIRC_CAN_REC_MODE2;
|
||||
driver->data = context;
|
||||
|
|
|
@ -838,7 +838,23 @@ static int hardware_init_port(void)
|
|||
|
||||
static int init_port(void)
|
||||
{
|
||||
int i, nlow, nhigh;
|
||||
int i, nlow, nhigh, result;
|
||||
|
||||
result = request_irq(irq, irq_handler,
|
||||
IRQF_DISABLED | (share_irq ? IRQF_SHARED : 0),
|
||||
LIRC_DRIVER_NAME, (void *)&hardware);
|
||||
|
||||
switch (result) {
|
||||
case -EBUSY:
|
||||
printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq);
|
||||
return -EBUSY;
|
||||
case -EINVAL:
|
||||
printk(KERN_ERR LIRC_DRIVER_NAME
|
||||
": Bad irq number or handler\n");
|
||||
return -EINVAL;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
/* Reserve io region. */
|
||||
/*
|
||||
|
@ -893,34 +909,17 @@ static int init_port(void)
|
|||
printk(KERN_INFO LIRC_DRIVER_NAME ": Manually using active "
|
||||
"%s receiver\n", sense ? "low" : "high");
|
||||
|
||||
dprintk("Interrupt %d, port %04x obtained\n", irq, io);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_use_inc(void *data)
|
||||
{
|
||||
int result;
|
||||
unsigned long flags;
|
||||
|
||||
/* initialize timestamp */
|
||||
do_gettimeofday(&lasttv);
|
||||
|
||||
result = request_irq(irq, irq_handler,
|
||||
IRQF_DISABLED | (share_irq ? IRQF_SHARED : 0),
|
||||
LIRC_DRIVER_NAME, (void *)&hardware);
|
||||
|
||||
switch (result) {
|
||||
case -EBUSY:
|
||||
printk(KERN_ERR LIRC_DRIVER_NAME ": IRQ %d busy\n", irq);
|
||||
return -EBUSY;
|
||||
case -EINVAL:
|
||||
printk(KERN_ERR LIRC_DRIVER_NAME
|
||||
": Bad irq number or handler\n");
|
||||
return -EINVAL;
|
||||
default:
|
||||
dprintk("Interrupt %d, port %04x obtained\n", irq, io);
|
||||
break;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&hardware[type].lock, flags);
|
||||
|
||||
/* Set DLAB 0. */
|
||||
|
@ -945,10 +944,6 @@ static void set_use_dec(void *data)
|
|||
soutp(UART_IER, sinp(UART_IER) &
|
||||
(~(UART_IER_MSI|UART_IER_RLSI|UART_IER_THRI|UART_IER_RDI)));
|
||||
spin_unlock_irqrestore(&hardware[type].lock, flags);
|
||||
|
||||
free_irq(irq, (void *)&hardware);
|
||||
|
||||
dprintk("freed IRQ %d\n", irq);
|
||||
}
|
||||
|
||||
static ssize_t lirc_write(struct file *file, const char *buf,
|
||||
|
@ -1256,6 +1251,9 @@ exit_serial_exit:
|
|||
static void __exit lirc_serial_exit_module(void)
|
||||
{
|
||||
lirc_serial_exit();
|
||||
|
||||
free_irq(irq, (void *)&hardware);
|
||||
|
||||
if (iommap != 0)
|
||||
release_mem_region(iommap, 8 << ioshift);
|
||||
else
|
||||
|
|
|
@ -739,23 +739,16 @@ static void send_space(unsigned long len)
|
|||
static void send_pulse(unsigned long len)
|
||||
{
|
||||
long bytes_out = len / TIME_CONST;
|
||||
long time_left;
|
||||
|
||||
time_left = (long)len - (long)bytes_out * (long)TIME_CONST;
|
||||
if (bytes_out == 0) {
|
||||
if (bytes_out == 0)
|
||||
bytes_out++;
|
||||
time_left = 0;
|
||||
}
|
||||
|
||||
while (bytes_out--) {
|
||||
outb(PULSE, io + UART_TX);
|
||||
/* FIXME treba seriozne cakanie z char/serial.c */
|
||||
while (!(inb(io + UART_LSR) & UART_LSR_THRE))
|
||||
;
|
||||
}
|
||||
#if 0
|
||||
if (time_left > 0)
|
||||
safe_udelay(time_left);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -475,14 +475,14 @@ static int lirc_thread(void *arg)
|
|||
dprintk("poll thread started\n");
|
||||
|
||||
while (!kthread_should_stop()) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
/* if device not opened, we can sleep half a second */
|
||||
if (atomic_read(&ir->open_count) == 0) {
|
||||
schedule_timeout(HZ/2);
|
||||
continue;
|
||||
}
|
||||
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
/*
|
||||
* This is ~113*2 + 24 + jitter (2*repeat gap + code length).
|
||||
* We use this interval as the chip resets every time you poll
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#ifndef _LINUX_LIRC_DEV_H
|
||||
#define _LINUX_LIRC_DEV_H
|
||||
|
||||
#define MAX_IRCTL_DEVICES 4
|
||||
#define MAX_IRCTL_DEVICES 8
|
||||
#define BUFLEN 16
|
||||
|
||||
#define mod(n, div) ((n) % (div))
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
* Driver header for M-5MOLS 8M Pixel camera sensor with ISP
|
||||
*
|
||||
* Copyright (C) 2011 Samsung Electronics Co., Ltd.
|
||||
* Author: HeungJun Kim, riverful.kim@samsung.com
|
||||
* Author: HeungJun Kim <riverful.kim@samsung.com>
|
||||
*
|
||||
* Copyright (C) 2009 Samsung Electronics Co., Ltd.
|
||||
* Author: Dongsoo Nathaniel Kim, dongsoo45.kim@samsung.com
|
||||
* Author: Dongsoo Nathaniel Kim <dongsoo45.kim@samsung.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
Загрузка…
Ссылка в новой задаче